diff --git a/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/GeometryEditorButton.qml b/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/GeometryEditorButton.qml new file mode 100644 index 0000000000..d9c2f51428 --- /dev/null +++ b/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/GeometryEditorButton.qml @@ -0,0 +1,64 @@ +// [WriteFile Name=CreateAndEditGeometries, Category=Geometry] +// [Legal] +// Copyright 2023 Esri. + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// [Legal] + +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts + +// This component defines each of the buttons in the Geometry Editor control UI + +RoundButton { + id: geometryEditorButton + + property string buttonName: "" + property string iconPath: "" + + Layout.fillWidth: true + + // Set the focus policy so that the buttons do not take focus from the MapView + focusPolicy: Qt.NoFocus + + radius: 5 + + Rectangle { + anchors.fill: parent + radius: parent.radius + opacity: parent.enabled || parent.checked ? 1 : 0.3 + color: geometryEditorButton.down ? "#d0d0d0" : "#e0e0e0" + } + + Image { + id: imgComponent + anchors { + horizontalCenter: parent.horizontalCenter + verticalCenter: parent.verticalCenter + verticalCenterOffset: -textComponent.height/2 + } + source: iconPath + width: 20 + fillMode: Image.PreserveAspectFit + } + + Text { + id: textComponent + anchors { + top: imgComponent.bottom + horizontalCenter: parent.horizontalCenter + } + text: buttonName + font.pixelSize: 8 + } +} diff --git a/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/Info.plist b/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/Info.plist new file mode 100644 index 0000000000..59320340a3 --- /dev/null +++ b/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/Info.plist @@ -0,0 +1,55 @@ + + + + + CFBundleDisplayName + SnapGeometryEdits + CFBundleExecutable + SnapGeometryEdits + CFBundleGetInfoString + ArcGIS + CFBundleIcons~ipad + + CFBundleIdentifier + com.esri.${PRODUCT_NAME:rfc1034identifier} + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + NOTE + This app is cool + UIFileSharingEnabled + FALSE + UIRequiresPersistentWiFi + NO + LSRequiresIPhoneOS + + NSLocationAlwaysUsageDescription + + NSLocationWhenInUseUsageDescription + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UILaunchStoryboardName + LaunchScreen + + + diff --git a/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/SnapGeometryEdits.cpp b/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/SnapGeometryEdits.cpp new file mode 100644 index 0000000000..3ccafab4b3 --- /dev/null +++ b/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/SnapGeometryEdits.cpp @@ -0,0 +1,349 @@ +// [WriteFile Name=SnapGeometryEdits, Category=EditData] +// [Legal] +// Copyright 2024 Esri. + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// [Legal] + +#include "Geometry.h" +#ifdef PCH_BUILD +#include "pch.hpp" +#endif // PCH_BUILD + +#include "SnapGeometryEdits.h" + +#include "Map.h" +#include "MapQuickView.h" +#include "MapTypes.h" +#include "Portal.h" +#include "PortalItem.h" +#include "SnapGeometryEdits.h" +#include "LoadSettings.h" +#include "LayerListModel.h" +#include "Layer.h" +#include "GeometryEditor.h" +#include "GraphicsOverlay.h" +#include "GeometryEditor.h" +#include "GeometryTypes.h" +#include "GraphicsOverlayListModel.h" +#include "SimpleFillSymbol.h" +#include "SimpleLineSymbol.h" +#include "SimpleMarkerSymbol.h" +#include "SymbolTypes.h" +#include "IdentifyGraphicsOverlayResult.h" +#include "Graphic.h" +#include "SnapSettings.h" +#include "SnapSourceSettings.h" +#include "GraphicListModel.h" +#include "GeometryEditorElement.h" +#include "FeatureLayer.h" +#include "FeatureTable.h" + +#include + +using namespace Esri::ArcGISRuntime; + +SnapGeometryEdits::SnapGeometryEdits(QObject* parent /* = nullptr */) : + QObject(parent), + m_portal(new Portal(this)), + m_portalItem(new PortalItem(m_portal, "b95fe18073bc4f7788f0375af2bb445e", this)) +{ + m_map = new Map(m_portalItem, this); + m_map->loadSettings()->setFeatureTilingMode(FeatureTilingMode::EnabledWhenSupported); + m_geometryEditor = new GeometryEditor(this); + m_graphicsOverlay = new GraphicsOverlay(this); + m_tempGraphicsParent = new QObject(this); + connect(m_map, &Map::doneLoading, this, [this]() + { + for (Layer* layer : *m_map->operationalLayers()) + { + connect(layer, &Layer::doneLoading, this, [layer]() + { + qDebug() << "done" << layer->name(); + }); + } + }); + } + + + + +SnapGeometryEdits::~SnapGeometryEdits() = default; + +void SnapGeometryEdits::init() +{ + // Register the map view for QML + qmlRegisterType("Esri.Samples", 1, 0, "MapView"); + qmlRegisterType("Esri.Samples", 1, 0, "SnapGeometryEditsSample"); +} + +MapQuickView* SnapGeometryEdits::mapView() const +{ + return m_mapView; +} + +// Set the view (created in QML) +void SnapGeometryEdits::setMapView(MapQuickView* mapView) +{ + if (!mapView || mapView == m_mapView) + return; + + m_mapView = mapView; + m_mapView->setMap(m_map); + + m_mapView->graphicsOverlays()->append(m_graphicsOverlay); + + // Set the geometry editor on the map view + m_mapView->setGeometryEditor(m_geometryEditor); + + m_mapView->setMagnifierEnabled(true); + + + emit mapViewChanged(); + createInitialSymbols(); + createConnections(); + + // showBottomSheet(); +} + +// Create symbols used by all graphics +void SnapGeometryEdits::createInitialSymbols() +{ + m_pointSymbol = new SimpleMarkerSymbol(SimpleMarkerSymbolStyle::Square, QColor(255, 45, 0), 20, this); + m_multiPointSymbol = new SimpleMarkerSymbol(SimpleMarkerSymbolStyle::Square, QColor(255, 45, 0), 20, this); + m_lineSymbol = new SimpleLineSymbol(SimpleLineSymbolStyle::Solid, QColor(255, 45, 0), 2, this); + m_polygonSymbol = new SimpleFillSymbol(SimpleFillSymbolStyle::Solid, QColor(255, 0, 0, 75), + new SimpleLineSymbol(SimpleLineSymbolStyle::Dash, QColor(0, 0, 0), 1.0, this), this); +} + +void SnapGeometryEdits::createConnections() +{ + qDebug() << "1"; + + // Allow user to edit existing graphics by clicking on them + connect(m_mapView, &MapQuickView::mouseClicked, this, [this](const QMouseEvent& mouseEvent) + {qDebug() << "2"; + if (!m_geometryEditor->isStarted()) + {qDebug() << "3"; + m_mapView->identifyGraphicsOverlayAsync(m_graphicsOverlay, mouseEvent.position(), 10 ,false).then(this, + [this](IdentifyGraphicsOverlayResult* rawResult){ + // Handle editing selected graphics, if any + + auto identifyResult = std::unique_ptr(rawResult); + + // Return if no graphics were identified + if (identifyResult->graphics().isEmpty()) + return; + + m_editingGraphic = identifyResult->graphics().first(); + + // Hide the graphic currently being edited + m_editingGraphic->setVisible(false); + + // Start the geometry editor with the graphic's geometry. This does not directly affect the graphic. + m_geometryEditor->start(m_editingGraphic->geometry()); + + emit geometryEditorStartedChanged(); + }); + } + emit canUndoChanged(); + emit elementIsSelectedChanged(); + }); + + // Enable or disable buttons when mouse is released (ie after a drag operation) + connect(m_mapView, &MapQuickView::mouseReleased, this, [this](const QMouseEvent&) + { + emit canUndoChanged(); + emit elementIsSelectedChanged(); + }); +} + +bool SnapGeometryEdits::geometryEditorStarted() const +{ + return (m_geometryEditor && m_geometryEditor->isStarted()); +} + +bool SnapGeometryEdits::canUndo() +{ + return (m_geometryEditor && m_geometryEditor->canUndo()); +} + +bool SnapGeometryEdits::elementIsSelected() +{ + return (m_geometryEditor && m_geometryEditor->selectedElement() && m_geometryEditor->selectedElement()->canDelete()); +} + +void SnapGeometryEdits::snappingEnabledStatus(bool snappingCheckedState) +{ + m_geometryEditor->snapSettings()->setEnabled(snappingCheckedState); +} + +void SnapGeometryEdits::pointSourceEnabledStatus(bool snappingCheckedState, int index) +{ + m_pointSourceCheckedState[index] = snappingCheckedState; + m_geometryEditor->snapSettings()->sourceSettings()[index]->setEnabled(m_pointSourceCheckedState[index]); + +} + +void SnapGeometryEdits::polylineSourceEnabledStatus(bool snappingCheckedState, int index) +{ + m_polylineSourceCheckedState[index] = snappingCheckedState; + m_geometryEditor->snapSettings()->sourceSettings()[index]->setEnabled(m_polylineSourceCheckedState[index]); + +} + +void SnapGeometryEdits::onPointLayersEnabled() +{ + for (int index = 0; index < m_snapSourceList.size()-1; ++index) + { + FeatureLayer *featureLayer = static_cast(m_snapSourceList[index]->source()); + if (featureLayer && featureLayer->featureTable() && featureLayer->featureTable()->geometryType() == GeometryType::Point) + { + pointSourceEnabledStatus(true, index); + } + } + emit pointSourceCheckedStateChanged(); +} + +void SnapGeometryEdits::onPolylineLayersEnabled() +{ + for (int index = 0; index < m_snapSourceList.size()-1; ++index) + { + FeatureLayer *featureLayer = static_cast(m_snapSourceList[index]->source()); + if (featureLayer && featureLayer->featureTable() && featureLayer->featureTable()->geometryType() == GeometryType::Polyline) + { + polylineSourceEnabledStatus(true, index); + } + } + emit polylineSourceCheckedStateChanged(); +} + +void SnapGeometryEdits::startEditor(GeometryEditorMode geometryEditorMode) +{ + switch (geometryEditorMode) + { + case GeometryEditorMode::PointMode: + m_geometryEditor->start(Esri::ArcGISRuntime::GeometryType::Point); + break; + + case GeometryEditorMode::MultipointMode: + m_geometryEditor->start(Esri::ArcGISRuntime::GeometryType::Multipoint); + break; + + case GeometryEditorMode::PolylineMode: + m_geometryEditor->start(Esri::ArcGISRuntime::GeometryType::Polyline); + break; + + case GeometryEditorMode::PolygonMode: + m_geometryEditor->start(Esri::ArcGISRuntime::GeometryType::Polygon); + break; + + default: + break; + } + + emit geometryEditorStartedChanged(); +} + +void SnapGeometryEdits::stopEditor() +{ + const Geometry geometry = m_geometryEditor->stop(); + emit geometryEditorStartedChanged(); + + if (m_editingGraphic) + { + m_editingGraphic->setGeometry(geometry); + + // Show the graphic and clear the selection + m_editingGraphic->setVisible(true); + m_editingGraphic = nullptr; + + return; + } + + Symbol* geometrySymbol = nullptr; + switch (geometry.geometryType()) + { + case GeometryType::Point: + geometrySymbol = m_pointSymbol; + break; + + case GeometryType::Multipoint: + geometrySymbol = m_multiPointSymbol; + break; + + case GeometryType::Polyline: + geometrySymbol = m_lineSymbol; + break; + + case GeometryType::Polygon: + geometrySymbol = m_polygonSymbol; + break; + + default: + return; + } + + // Append the new graphic to the graphics overlay + m_graphicsOverlay->graphics()->append(new Graphic(geometry, geometrySymbol, m_tempGraphicsParent)); +} + +void SnapGeometryEdits::deleteSelection() +{ + m_geometryEditor->deleteSelectedElement(); + emit canUndoChanged(); +} + +void SnapGeometryEdits::editorUndo() +{ + // if (m_geometryEditor->canUndo()) + m_geometryEditor->undo(); + emit canUndoChanged(); +} + +void SnapGeometryEdits::configureSnapping() +{ + + if (m_geometryEditor->snapSettings()->sourceSettings().empty()) + { + + m_geometryEditor->snapSettings()->syncSourceSettings(); + m_geometryEditor->snapSettings()->setEnabled(true); + + m_snapSourceList = m_geometryEditor->snapSettings()->sourceSettings(); + qDebug() << m_snapSourceList.size(); + qDebug() << static_cast(m_snapSourceList[0]->source())->name(); + qDebug() << static_cast(m_snapSourceList[1]->source())->name(); + qDebug() << static_cast(m_snapSourceList[2]->source())->name(); + qDebug() << static_cast(m_snapSourceList[3]->source())->name(); + } + + m_pointLayers.clear(); + m_polylineLayers.clear(); + for (int index = 0; index < m_snapSourceList.size()-1; ++index) + { + FeatureLayer *featureLayer = static_cast(m_snapSourceList[index]->source()); + if (featureLayer->featureTable()->geometryType() == GeometryType::Point) + { + m_pointLayers.append(featureLayer->name()); + m_pointSourceCheckedState.append(m_snapSourceList[index]->isEnabled()); + } + else if (featureLayer->featureTable()->geometryType() == GeometryType::Polyline) + { + m_polylineLayers.append(featureLayer->name()); + m_polylineSourceCheckedState.append(m_snapSourceList[index]->isEnabled()); + } + } + + emit pointLayersChanged(); + emit polylineLayersChanged(); +} diff --git a/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/SnapGeometryEdits.h b/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/SnapGeometryEdits.h new file mode 100644 index 0000000000..fef337ce4a --- /dev/null +++ b/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/SnapGeometryEdits.h @@ -0,0 +1,117 @@ +// [WriteFile Name=SnapGeometryEdits, Category=EditData] +// [Legal] +// Copyright 2024 Esri. + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// [Legal] + +#ifndef SNAPGEOMETRYEDITS_H +#define SNAPGEOMETRYEDITS_H + +#include "GeometryEditor.h" +namespace Esri::ArcGISRuntime { + class Map; + class MapQuickView; + class Portal; + class PortalItem; + class GeometryEditor; + class Graphic; + class GraphicsOverlay; + class SimpleMarkerSymbol; + class SimpleLineSymbol; + class SimpleFillSymbol; + class SnapSourceSettings; +} + +#include + +Q_MOC_INCLUDE("MapQuickView.h"); + +class SnapGeometryEdits : public QObject +{ + Q_OBJECT + + Q_PROPERTY(Esri::ArcGISRuntime::MapQuickView* mapView READ mapView WRITE setMapView NOTIFY mapViewChanged) + Q_PROPERTY(bool geometryEditorStarted READ geometryEditorStarted NOTIFY geometryEditorStartedChanged) + Q_PROPERTY(bool canUndo READ canUndo NOTIFY canUndoChanged) + Q_PROPERTY(bool elementIsSelected READ elementIsSelected NOTIFY elementIsSelectedChanged) + Q_PROPERTY(QList pointLayers MEMBER m_pointLayers NOTIFY pointLayersChanged) + Q_PROPERTY(QList polylineLayers MEMBER m_polylineLayers NOTIFY polylineLayersChanged) + Q_PROPERTY(QList pointSourceCheckedState MEMBER m_pointSourceCheckedState NOTIFY pointSourceCheckedStateChanged) + Q_PROPERTY(QList polylineSourceCheckedState MEMBER m_polylineSourceCheckedState NOTIFY polylineSourceCheckedStateChanged) + +public: + explicit SnapGeometryEdits(QObject* parent = nullptr); + ~SnapGeometryEdits() override; + + enum class GeometryEditorMode { + PointMode, + MultipointMode, + PolylineMode, + PolygonMode + }; + + Q_ENUM(GeometryEditorMode) + + static void init(); + Q_INVOKABLE void startEditor(GeometryEditorMode geometryEditorMode); + Q_INVOKABLE void stopEditor(); + Q_INVOKABLE void deleteSelection(); + Q_INVOKABLE void editorUndo(); + Q_INVOKABLE void snappingEnabledStatus(bool checkedValue); + Q_INVOKABLE void onPointLayersEnabled(); + Q_INVOKABLE void onPolylineLayersEnabled(); + Q_INVOKABLE void configureSnapping(); + Q_INVOKABLE void pointSourceEnabledStatus(bool snappingCheckedState, int index); + Q_INVOKABLE void polylineSourceEnabledStatus(bool snappingCheckedState, int index); + +signals: + void mapViewChanged(); + void geometryEditorStartedChanged(); + void canUndoChanged(); + void elementIsSelectedChanged(); + void polylineLayersChanged(); + void pointLayersChanged(); + void pointSourceCheckedStateChanged(); + void polylineSourceCheckedStateChanged(); + +private: + Esri::ArcGISRuntime::MapQuickView* mapView() const; + void setMapView(Esri::ArcGISRuntime::MapQuickView* mapView); + bool geometryEditorStarted() const; + void createInitialSymbols(); + void createConnections(); + bool canUndo(); + bool elementIsSelected(); + + + + Esri::ArcGISRuntime::Map* m_map = nullptr; + Esri::ArcGISRuntime::MapQuickView* m_mapView = nullptr; + Esri::ArcGISRuntime::Portal* m_portal = nullptr; + Esri::ArcGISRuntime::PortalItem* m_portalItem = nullptr; + Esri::ArcGISRuntime::GraphicsOverlay* m_graphicsOverlay = nullptr; + Esri::ArcGISRuntime::Graphic* m_editingGraphic = nullptr; + Esri::ArcGISRuntime::GeometryEditor* m_geometryEditor = nullptr; + Esri::ArcGISRuntime::SimpleMarkerSymbol* m_pointSymbol = nullptr; + Esri::ArcGISRuntime::SimpleMarkerSymbol* m_multiPointSymbol = nullptr; + Esri::ArcGISRuntime::SimpleLineSymbol* m_lineSymbol = nullptr; + Esri::ArcGISRuntime::SimpleFillSymbol* m_polygonSymbol = nullptr; + QList m_pointSourceCheckedState; + QList m_polylineSourceCheckedState; + QList m_snapSourceList; + QList m_pointLayers; + QList m_polylineLayers; + QObject* m_tempGraphicsParent = nullptr; +}; + +#endif // SNAPGEOMETRYEDITS_H diff --git a/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/SnapGeometryEdits.pro b/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/SnapGeometryEdits.pro new file mode 100644 index 0000000000..8555b4c0b4 --- /dev/null +++ b/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/SnapGeometryEdits.pro @@ -0,0 +1,65 @@ +#------------------------------------------------- +# Copyright 2024 Esri. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#------------------------------------------------- + +mac { + cache() +} + +#------------------------------------------------------------------------------- + +CONFIG += c++17 + +# additional modules are pulled in via arcgisruntime.pri +QT += opengl qml quick + +TEMPLATE = app +TARGET = SnapGeometryEdits + +ARCGIS_RUNTIME_VERSION = 200.5.0 +include($$PWD/arcgisruntime.pri) + +#------------------------------------------------------------------------------- + +HEADERS += \ + SnapGeometryEdits.h + +SOURCES += \ + main.cpp \ + SnapGeometryEdits.cpp + +RESOURCES += SnapGeometryEdits.qrc + +#------------------------------------------------------------------------------- + +win32 { + LIBS += \ + Ole32.lib +} + +ios { + INCLUDEPATH += $$PWD + DEPENDPATH += $$PWD + + OTHER_FILES += \ + $$PWD/Info.plist + + QMAKE_INFO_PLIST = $$PWD/Info.plist +} + +android { + INCLUDEPATH += $$PWD + DEPENDPATH += $$PWD +} +android: include(/Users/har13205/Library/Android/sdk/android_openssl/openssl.pri) diff --git a/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/SnapGeometryEdits.qml b/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/SnapGeometryEdits.qml new file mode 100644 index 0000000000..6c3e0307d3 --- /dev/null +++ b/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/SnapGeometryEdits.qml @@ -0,0 +1,521 @@ +// [WriteFile Name=SnapGeometryEdits, Category=EditData] +// [Legal] +// Copyright 2024 Esri. + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// [Legal] + +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Esri.Samples + +Item { + // property var phases: ["System Value", "Service Connection", "Curb Stop Value"] + property var pointLayers: snapGeometryEditsSampleModel.pointLayers + property var polylineLayers: ["Lateral","Main"] + // add a mapView component + MapView { + id: view + anchors.fill: parent + + Component.onCompleted: { + // Set and keep the focus on MapView to enable keyboard navigation + forceActiveFocus(); + } + } + + // Declare the C++ instance which creates the map etc. and supply the view + SnapGeometryEditsSample { + id: snapGeometryEditsSampleModel + mapView: view + } + +Rectangle { + + anchors { + right: parent.right + margins: 10 + } + + Control { + id: control + anchors.right: parent.right + padding: 5 + width: 140 + + background: Rectangle { + color: "black" + opacity: .5 + } + + contentItem: ColumnLayout { + id: columns + anchors { + verticalCenter: parent.verticalCenter + horizontalCenter: parent.horizontalCenter + } + + GridLayout { + id: geometryColumn + Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter + columns: 2 + + Text { + id: geometryHeader + Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter + Layout.columnSpan: 2 + text: "Create" + color: "white" + font.pixelSize: 16 + font.bold: true + } + + GeometryEditorButton { + id: pointButton + buttonName: qsTr("Point") + iconPath: "qrc:/Samples/EditData/SnapGeometryEdits/iconAssets/point-32.png" + checkable: true + enabled: !snapGeometryEditsSampleModel.geometryEditorStarted + onClicked: { + snapGeometryEditsSampleModel.startEditor(SnapGeometryEditsSample.PointMode); + } + } + + GeometryEditorButton { + id: multiPointButton + buttonName: qsTr("Multipoint") + iconPath: "qrc:/Samples/EditData/SnapGeometryEdits/iconAssets/multipoint-32.png" + checkable: true + enabled: !snapGeometryEditsSampleModel.geometryEditorStarted + onClicked: { + snapGeometryEditsSampleModel.startEditor(SnapGeometryEditsSample.MultipointMode); + } + } + + GeometryEditorButton { + id: lineButton + buttonName: qsTr("Line") + iconPath: "qrc:/Samples/EditData/SnapGeometryEdits/iconAssets/line-32.png" + checkable: true + enabled: !snapGeometryEditsSampleModel.geometryEditorStarted + onClicked: { + snapGeometryEditsSampleModel.startEditor(SnapGeometryEditsSample.PolylineMode); + } + } + + GeometryEditorButton { + id: polygonButton + buttonName: qsTr("Polygon") + iconPath: "qrc:/Samples/EditData/SnapGeometryEdits/iconAssets/polygon-32.png" + checkable: true + enabled: !snapGeometryEditsSampleModel.geometryEditorStarted + onClicked: { + snapGeometryEditsSampleModel.startEditor(SnapGeometryEditsSample.PolygonMode); + } + } + } + + GridLayout { + id: editingColumn + Layout.fillWidth: true + Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter + columns: 2 + + Text { + id: editingHeader + Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter + Layout.columnSpan: 2 + text: qsTr("Edit") + color: "white" + font.pixelSize: 16 + font.bold: true + } + + GeometryEditorButton { + id: undoButton + buttonName: qsTr("Undo") + iconPath: "qrc:/Samples/EditData/SnapGeometryEdits/iconAssets/undo-32.png" + enabled: snapGeometryEditsSampleModel.geometryEditorStarted && snapGeometryEditsSampleModel.canUndo + onClicked: snapGeometryEditsSampleModel.editorUndo(); + } + + GeometryEditorButton { + id: deleteVertexButton + buttonName: qsTr("Delete") + iconPath: "qrc:/Samples/EditData/SnapGeometryEdits/iconAssets/erase-32.png" + // Layout.columnSpan: 2 + enabled: snapGeometryEditsSampleModel.geometryEditorStarted || snapGeometryEditsSampleModel.elementIsSelected + onClicked: snapGeometryEditsSampleModel.deleteSelection(); + } + + GeometryEditorButton { + id: saveEditsButton + buttonName: qsTr("Save") + iconPath: "qrc:/Samples/EditData/SnapGeometryEdits/iconAssets/save-32.png" + Layout.columnSpan: 2 + enabled: snapGeometryEditsSampleModel.geometryEditorStarted + onClicked: { + snapGeometryEditsSampleModel.stopEditor(); + } + } + + GeometryEditorButton { + id: snapSettingsButton + buttonName: qsTr("Snap Settings") + iconPath: "qrc:/Samples/EditData/SnapGeometryEdits/iconAssets/settings.png" + Layout.columnSpan: 2 + enabled: true + // MouseArea { + // anchors.fill: parent + // onClicked: optionPanel.visible = true; + // } + onClicked: { + optionPanel.visible = true; + snapGeometryEditsSampleModel.configureSnapping(); + } + } + } + } + } +} + Rectangle { + id: optionPanel + anchors { + right: parent.right + top: parent.top + // bottom: sceneView.attributionTop + bottom: parent.bottom + } + width: 360 + visible: false + color: "white" + opacity: 1 + + Flickable { + anchors { + fill: parent + margins: 10 + } + contentWidth: parent.width + contentHeight: parent.height + flickableDirection: Flickable.VerticalFlick + ColumnLayout + { + id: layout + spacing: 40 + Column { + id: optionColumn + spacing: 10 + width: optionPanel.width + + Item { + width: parent.width + height: 25 + + + Text { + text: "Snapping" + // anchors.horizontalCenter: parent.horizontalCenter + font.pixelSize: 15 + color: "#8434C1" + font.bold: true + + } + + Rectangle { + anchors { + right: parent.right + margins: 10 + } + width: 45 + height: 20 + + Text { + text: "Done" + font.pixelSize: 15 + color: "#8434C1" + font.bold: true + } + + MouseArea { + anchors.fill: parent + onClicked: optionPanel.visible = false; + } + } + } + + Item { + width: parent.width + height: 25 + + Rectangle { + // anchors.centerIn: parent + // width: childrenRect.width + // height: childrenRect.height + // anchors.margins: 40 + + + anchors { + // right: parent.right + margins: 10 + } + + width: 340 + height: 45 + color: "#E9DFEA" + radius: 5 + border { + color: "#4D4D4D" + width: 1 + } + + Text { + anchors.verticalCenter: parent.verticalCenter + // width: parent.width * 0.75 + text: qsTr("Enabled") + font.pixelSize: 15 + anchors { + left: parent.left + margins: 10 + verticalCenter: parent.verticalCenter + } + } + + Switch { + anchors { + right: parent.right + margins: 10 + verticalCenter: parent.verticalCenter + } + onCheckedChanged: snapGeometryEditsSampleModel.snappingEnabledStatus(checked) + } + } + } + } + Column { + id: optionColumn2 + spacing: 10 + width: optionPanel.width + Item { + width: parent.width + height: 25 + + Text { + text: "Point Layers" + // anchors.horizontalCenter: parent.horizontalCenter + font.pixelSize: 15 + color: "#8434C1" + font.bold: true + + } + + + Rectangle { + anchors { + right: parent.right + margins: 10 + } + width: 140 + height: 20 + + Text { + text: "Enable All Sources" + font.pixelSize: 15 + color: "#8434C1" + font.bold: true + } + + MouseArea { + anchors.fill: parent + onClicked: { + // checkAllPoint = true + snapGeometryEditsSampleModel.onPointLayersEnabled() + } + } + } + } + + Item { + id: item + + width: parent.width + height: 25 + + Rectangle { + anchors.margins: 20 + width: 340 + height: grid.height + color: "#E9DFEA" + radius: 5 + border { + color: "#4D4D4D" + width: 1 + } + + ColumnLayout { + id: grid + Repeater { + id: repeater + model: snapGeometryEditsSampleModel.pointLayers // Adjust the number of items as needed + delegate: RowLayout { + Layout.margins: 10 + + Text { + id: textItem + text: pointLayers[index] + Layout.alignment: Qt.AlignLeft + Layout.fillWidth: true // Allow text to take all available space + Layout.rightMargin: 110 + font.pixelSize: 15 + } + + Switch { + id: switchItem + Layout.alignment: Qt.AlignRight + // property bool localChecked: snapGeometryEditsSampleModel.snapSourceCheckedState[index] + + onCheckedChanged: { + // if (localChecked !== checked) { + // snapGeometryEditsSampleModel.sourceEnabledStatus(checked, index) + // localChecked = checked + // } + snapGeometryEditsSampleModel.pointSourceEnabledStatus(checked, index) + } + // Bind the checked property to the localChecked property + checked: snapGeometryEditsSampleModel.pointSourceCheckedState[index] + } + } + } + } + + + } + + + } + + } + + Item { + // width: mainColumn.width + height: optionColumn2.height+10 // Adjust as needed + } + + Column { + id: optionColumn3 + spacing: 10 + width: optionPanel.width + + Item { + width: parent.width + height: 25 + + Text { + text: "Polyline Layers" + // anchors.horizontalCenter: parent.horizontalCenter + font.pixelSize: 15 + color: "#8434C1" + font.bold: true + + } + + + Rectangle { + anchors { + right: parent.right + margins: 10 + } + width: 140 + height: 20 + + Text { + text: "Enable All Sources" + font.pixelSize: 15 + color: "#8434C1" + font.bold: true + } + + MouseArea { + anchors.fill: parent + onClicked: { + // checkAllPoint = true + console.log("polyline") + snapGeometryEditsSampleModel.onPolylineLayersEnabled() + } + } + } + } + + Item { + + width: parent.width + height: 25 + + Rectangle { + anchors.margins: 20 + width: 340 + height: grid2.height + color: "#E9DFEA" + radius: 5 + border { + color: "#4D4D4D" + width: 1 + } + + ColumnLayout { + id: grid2 + // Layout.bottomMargin: 10 + // Layout.topMargin: 10 + Repeater { + id: repeater2 + model: snapGeometryEditsSampleModel.polylineLayers // Adjust the number of items as needed + delegate: RowLayout { + // Layout.bottomMargin: 10 + // Layout.topMargin: 10 + Layout.margins: 10 + // spacing: 10 // Adjust the default spacing between items + + Text { + id: textItem2 + text: polylineLayers[index] + Layout.alignment: Qt.AlignLeft + Layout.fillWidth: true // Allow text to take all available space + Layout.rightMargin: 200 + // Layout.leftMargin: 10 + font.pixelSize: 15 + } + + Switch { + id: switchItem2 + Layout.alignment: Qt.AlignRight + } + } + } + } + + + } + + + } + + } + } + } + } + } + + + + + diff --git a/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/SnapGeometryEdits.qrc b/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/SnapGeometryEdits.qrc new file mode 100644 index 0000000000..1643593a4a --- /dev/null +++ b/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/SnapGeometryEdits.qrc @@ -0,0 +1,21 @@ + + + README.metadata.json + SnapGeometryEdits.qml + SnapGeometryEdits.h + SnapGeometryEdits.cpp + main.qml + screenshot.png + README.md + iconAssets/erase-32.png + iconAssets/line-32.png + iconAssets/multipoint-32.png + iconAssets/point-32.png + iconAssets/polygon-32.png + iconAssets/save-32.png + iconAssets/trash-32.png + iconAssets/undo-32.png + GeometryEditorButton.qml + iconAssets/settings.png + + diff --git a/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/arcgisruntime.pri b/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/arcgisruntime.pri new file mode 100644 index 0000000000..23b71ebbe0 --- /dev/null +++ b/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/arcgisruntime.pri @@ -0,0 +1,29 @@ +#------------------------------------------------- +# Copyright 2024 Esri. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#------------------------------------------------- + +contains(QMAKE_HOST.os, Windows):{ + iniPath = $$(ALLUSERSPROFILE)\EsriRuntimeQt\ArcGIS Runtime SDK for Qt $${ARCGIS_RUNTIME_VERSION}.ini +} +else { + userHome = $$system(echo $HOME) + iniPath = $${userHome}/.config/EsriRuntimeQt/ArcGIS Runtime SDK for Qt $${ARCGIS_RUNTIME_VERSION}.ini +} +iniLine = $$cat($${iniPath}, "lines") +dirPath = $$find(iniLine, "InstallDir") +cleanDirPath = $$replace(dirPath, "InstallDir=", "") +priLocation = $$replace(cleanDirPath, '"', "") +!include($$priLocation/sdk/ideintegration/arcgis_runtime_qml_cpp.pri) { + message("Error. Cannot locate ArcGIS Runtime PRI file") +} diff --git a/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/iconAssets/erase-32.png b/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/iconAssets/erase-32.png new file mode 100644 index 0000000000..2a967045b0 Binary files /dev/null and b/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/iconAssets/erase-32.png differ diff --git a/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/iconAssets/line-32.png b/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/iconAssets/line-32.png new file mode 100644 index 0000000000..60bd40459b Binary files /dev/null and b/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/iconAssets/line-32.png differ diff --git a/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/iconAssets/multipoint-32.png b/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/iconAssets/multipoint-32.png new file mode 100644 index 0000000000..6edabfb9fc Binary files /dev/null and b/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/iconAssets/multipoint-32.png differ diff --git a/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/iconAssets/point-32.png b/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/iconAssets/point-32.png new file mode 100644 index 0000000000..10b0e3e55b Binary files /dev/null and b/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/iconAssets/point-32.png differ diff --git a/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/iconAssets/polygon-32.png b/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/iconAssets/polygon-32.png new file mode 100644 index 0000000000..621ff9cb5d Binary files /dev/null and b/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/iconAssets/polygon-32.png differ diff --git a/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/iconAssets/save-32.png b/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/iconAssets/save-32.png new file mode 100644 index 0000000000..6b71f0cfe7 Binary files /dev/null and b/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/iconAssets/save-32.png differ diff --git a/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/iconAssets/settings.png b/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/iconAssets/settings.png new file mode 100644 index 0000000000..74928c4e41 Binary files /dev/null and b/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/iconAssets/settings.png differ diff --git a/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/iconAssets/trash-32.png b/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/iconAssets/trash-32.png new file mode 100644 index 0000000000..d23b3d8516 Binary files /dev/null and b/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/iconAssets/trash-32.png differ diff --git a/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/iconAssets/undo-32.png b/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/iconAssets/undo-32.png new file mode 100644 index 0000000000..5512b01bc0 Binary files /dev/null and b/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/iconAssets/undo-32.png differ diff --git a/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/main.cpp b/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/main.cpp new file mode 100644 index 0000000000..88dfb7a50e --- /dev/null +++ b/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/main.cpp @@ -0,0 +1,85 @@ +// Copyright 2024 Esri. + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "ArcGISRuntimeEnvironment.h" +#include "SnapGeometryEdits.h" + +#include +#include +#include +#include + +#ifdef Q_OS_WIN +#include +#endif + +void setAPIKey(const QGuiApplication& app, QString apiKey); + +int main(int argc, char* argv[]) +{ + QGuiApplication app(argc, argv); + app.setApplicationName(QString("SnapGeometryEdits - C++")); + + // Access to Esri location services requires an API key. This can be copied below or used as a command line argument. + const QString apiKey = QString(""); + setAPIKey(app, apiKey); + + // Initialize the sample + SnapGeometryEdits::init(); + + // Initialize application view + QQmlApplicationEngine engine; + // Add the import Path + engine.addImportPath(QDir(QCoreApplication::applicationDirPath()).filePath("qml")); + +#ifdef ARCGIS_RUNTIME_IMPORT_PATH_2 + engine.addImportPath(ARCGIS_RUNTIME_IMPORT_PATH_2); +#endif + + // Set the source + engine.load(QUrl("qrc:/Samples/EditData/SnapGeometryEdits/main.qml")); + + return app.exec(); +} + +// Use of Esri location services, including basemaps and geocoding, +// requires authentication using either an ArcGIS identity or an API Key. +// 1. ArcGIS identity: An ArcGIS named user account that is a member of an +// organization in ArcGIS Online or ArcGIS Enterprise. +// 2. API key: API key: a permanent key that grants access to +// location services and premium content in your applications. +// Visit your ArcGIS Developers Dashboard to create a new +// API key or access an existing API key. + +void setAPIKey(const QGuiApplication& app, QString apiKey) +{ + if (apiKey.isEmpty()) + { + // Try parsing API key from command line argument, which uses the following syntax "-k ". + QCommandLineParser cmdParser; + QCommandLineOption apiKeyArgument(QStringList{"k", "api"}, "The API Key property used to access Esri location services", "apiKeyInput"); + cmdParser.addOption(apiKeyArgument); + cmdParser.process(app); + + apiKey = cmdParser.value(apiKeyArgument); + + if (apiKey.isEmpty()) + { + qWarning() << "Use of Esri location services, including basemaps, requires" + << "you to authenticate with an ArcGIS identity or set the API Key property."; + return; + } + } + + Esri::ArcGISRuntime::ArcGISRuntimeEnvironment::setApiKey(apiKey); +} diff --git a/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/main.qml b/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/main.qml new file mode 100644 index 0000000000..74ef4d96a7 --- /dev/null +++ b/ArcGISRuntimeSDKQt_CppSamples/EditData/SnapGeometryEdits/main.qml @@ -0,0 +1,25 @@ +// Copyright 2024 Esri. + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import QtQuick.Controls +import Esri.Samples + +ApplicationWindow { + visible: true + width: 800 + height: 600 + + SnapGeometryEdits { + anchors.fill: parent + } +}