diff --git a/AboutDialog/AboutDialog.qml b/AboutDialog/AboutDialog.qml index 937206d..38f43cc 100644 --- a/AboutDialog/AboutDialog.qml +++ b/AboutDialog/AboutDialog.qml @@ -54,7 +54,7 @@ Dialog { text: qsTr("About %1").arg(app.info.title) wrapMode: Text.WrapAtWordBoundaryOrAnywhere - font.family: notoRegular + font.family: defaultFontFamily font { pointSize: 22 bold: true @@ -81,7 +81,7 @@ Dialog { } AboutText { - text: "Copyright © 2016 Esri Inc. All Rights Reserved" + text: "Copyright © 2018 Esri Inc. All Rights Reserved" } AboutText { diff --git a/AboutDialog/AboutLabelValue.qml b/AboutDialog/AboutLabelValue.qml index fa91af8..df1e9cd 100644 --- a/AboutDialog/AboutLabelValue.qml +++ b/AboutDialog/AboutLabelValue.qml @@ -43,7 +43,7 @@ Item { pointSize: valueText.font.pointSize bold: !valueText.font.bold } - font.family: notoRegular + font.family: defaultFontFamily text: "Label" anchors { left: parent.left @@ -57,7 +57,7 @@ Item { pointSize: 9 bold: true } - font.family: notoRegular + font.family: defaultFontFamily color: labelText.color wrapMode: Text.WordWrap diff --git a/AboutDialog/AboutText.qml b/AboutDialog/AboutText.qml index df89808..27138d4 100644 --- a/AboutDialog/AboutText.qml +++ b/AboutDialog/AboutText.qml @@ -25,7 +25,7 @@ Text { font { pointSize: 14 } - font.family: notoRegular + font.family: defaultFontFamily onLinkActivated: { Qt.openUrlExternally(link); diff --git a/AppMetrics/FeedbackDialog.qml b/AppMetrics/FeedbackDialog.qml index 924dd8f..6236c23 100644 --- a/AppMetrics/FeedbackDialog.qml +++ b/AppMetrics/FeedbackDialog.qml @@ -60,7 +60,7 @@ Dialog { verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter font.pointSize: Singletons.Config.largeFontSizePoint - font.family: notoRegular + font.family: defaultFontFamily color: Singletons.Colors.formElementFontColor } } @@ -82,7 +82,7 @@ Dialog { textFormat: Text.RichText text: qsTr("Subject") + "*" verticalAlignment: Text.AlignVCenter - font.family: notoRegular + font.family: defaultFontFamily } TextField { @@ -99,7 +99,7 @@ Dialog { color: Singletons.Colors.formElementBackground } textColor: Singletons.Colors.formElementFontColor - font.family: notoRegular + font.family: defaultFontFamily } onTextChanged: { @@ -132,7 +132,7 @@ Dialog { textFormat: Text.RichText text: qsTr("Message") + "*" verticalAlignment: Text.AlignTop - font.family: notoRegular + font.family: defaultFontFamily } TextArea { id: feedbackMessage @@ -141,7 +141,7 @@ Dialog { style: TextAreaStyle { backgroundColor: Singletons.Colors.formElementBackground textColor: Singletons.Colors.formElementFontColor - font.family: notoRegular + font.family: defaultFontFamily frame: Rectangle { border.width: Singletons.Config.formElementBorderWidth border.color: Singletons.Colors.formElementBorderColor @@ -194,7 +194,7 @@ Dialog { textFormat: Text.RichText text: qsTr("Cancel") font.pointSize: Singletons.Config.baseFontSizePoint - font.family: notoRegular + font.family: defaultFontFamily } onClicked: { @@ -236,7 +236,7 @@ Dialog { textFormat: Text.RichText text: qsTr("Send") font.pointSize: Singletons.Config.baseFontSizePoint - font.family: notoRegular + font.family: defaultFontFamily } diff --git a/AppMetrics/HockeyApp.qml b/AppMetrics/HockeyApp.qml index a20b7d0..3eb8fbc 100644 --- a/AppMetrics/HockeyApp.qml +++ b/AppMetrics/HockeyApp.qml @@ -1,4 +1,4 @@ -/* Copyright 2016 Esri +/* Copyright 2018 Esri * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/AppToolBar.qml b/AppToolBar.qml index 7a42cce..2d725ae 100644 --- a/AppToolBar.qml +++ b/AppToolBar.qml @@ -1,4 +1,4 @@ -/* Copyright 2016 Esri +/* Copyright 2018 Esri * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -69,6 +69,8 @@ Item { property alias aboutButtonEnabled: aboutButton.enabled property alias userButtonVisible: userButton.visible property alias userButtonEnabled: userButton.enabled + property alias settingsButtonVisible: settingsButton.visible + property alias settingsButtonEnabled: settingsButton.enabled // UI ////////////////////////////////////////////////////////////////////// @@ -84,7 +86,7 @@ Item { //------------------------------------------------------------------ Button{ - id:backButton + id: backButton Layout.preferredWidth: toolBarHeight Layout.fillHeight: true @@ -112,7 +114,7 @@ Item { Accessible.name: Singletons.Strings.goBackToPreviousView Accessible.description: Singletons.Strings.goBackToPreviousViewDesc Accessible.onPressAction: { - if(enabled && visible){ + if (enabled && visible) { clicked(); } } @@ -131,7 +133,7 @@ Item { anchors.centerIn: parent verticalAlignment: Text.AlignVCenter leftPadding: sf(20) - font.family: notoRegular + font.family: defaultFontFamily font.pointSize: toolBarFontPointSize color: toolBarFontColor textFormat: Text.RichText @@ -165,7 +167,7 @@ Item { Accessible.ignored: true } - Rectangle{ + Rectangle { id: numberOfUpdatesIndicator visible: false color: "orange" @@ -176,7 +178,7 @@ Item { anchors.right: updatesButton.right anchors.topMargin: 4 * AppFramework.displayScaleFactor anchors.rightMargin: 4 * AppFramework.displayScaleFactor - Text{ + Text { id: numberOfUpdatesIndicatorCount anchors.centerIn: parent text: "0" @@ -193,7 +195,7 @@ Item { Accessible.name: Singletons.Strings.xUpdatesAvaliable.arg(numberOfUpdatesIndicatorCount.text) Accessible.description: Singletons.Strings.xUpdatesAvaliableDesc Accessible.onPressAction: { - if(enabled && visible){ + if (enabled && visible) { clicked(); } } @@ -201,7 +203,7 @@ Item { //------------------------------------------------------------------ - Button{ + Button { id: feedbackButton Layout.preferredWidth: toolBarHeight Layout.fillHeight: true @@ -209,7 +211,7 @@ Item { ToolTip.text: Singletons.Strings.feedback enabled: true - background: Rectangle{ + background: Rectangle { color: toolBarBackground anchors.fill: parent } @@ -230,7 +232,7 @@ Item { Accessible.name: Singletons.Strings.feedback Accessible.description: Singletons.Strings.feedbackDesc Accessible.onPressAction: { - if(enabled && visible){ + if (enabled && visible) { clicked(); } } @@ -266,7 +268,7 @@ Item { Accessible.name: Singletons.Strings.aboutTheApp Accessible.description: Singletons.Strings.aboutTheAppDesc Accessible.onPressAction: { - if(enabled && visible){ + if (enabled && visible) { clicked(); } } @@ -274,14 +276,50 @@ Item { //------------------------------------------------------------------ - Button{ + Button { + id: settingsButton + Layout.preferredWidth: toolBarHeight + Layout.fillHeight: true + ToolTip.visible: hovered + ToolTip.text: Singletons.Strings.settings + + background: Rectangle { + color: toolBarBackground + anchors.fill: parent + } + + IconFont { + anchors.centerIn: parent + icon: _icons.settings + iconSizeMultiplier: 1.1 + color: _returnButtonColor(settingsButton) + Accessible.ignored: true + } + + onClicked: { + stackView.push(sv); + } + + Accessible.role: Accessible.Button + Accessible.name: Singletons.Strings.settings + Accessible.description: Singletons.Strings.settingsDesc + Accessible.onPressAction: { + if (enabled && visible) { + clicked(); + } + } + } + + //------------------------------------------------------------------ + + Button { id: historyButton Layout.preferredWidth: toolBarHeight Layout.fillHeight: true ToolTip.visible: hovered ToolTip.text: Singletons.Strings.history - background: Rectangle{ + background: Rectangle { color: toolBarBackground anchors.fill: parent } @@ -302,7 +340,7 @@ Item { Accessible.name: Singletons.Strings.exportAndUploadHistory Accessible.description: Singletons.Strings.exportAndUploadHistoryDesc Accessible.onPressAction: { - if(enabled && visible){ + if (enabled && visible) { clicked(); } } @@ -310,7 +348,7 @@ Item { //------------------------------------------------------------------ - Button{ + Button { id: userButton Layout.preferredWidth: toolBarHeight Layout.fillHeight: true @@ -318,7 +356,7 @@ Item { ToolTip.text: (portal.user !== null && portal.user !== "" && portal.user !== undefined) ? Singletons.Strings.signOut + ": " + portal.user.fullName : "User Unknown" enabled: true - background: Rectangle{ + background: Rectangle { color: toolBarBackground anchors.fill: parent } @@ -341,7 +379,7 @@ Item { Accessible.name: Singletons.Strings.signOut Accessible.description: Singletons.Strings.signOutDesc Accessible.onPressAction: { - if(enabled && visible){ + if (enabled && visible) { clicked(); } } @@ -355,7 +393,7 @@ Item { // SIGNAL IMPLEMENTATIONS ////////////////////////////////////////////////// onUpdateCountChanged: { - if(updateCount > 0){ + if (updateCount > 0) { updatesButtonEnabled = true; updatesButtonVisible = true; updateIndicatorVisible = true; @@ -365,21 +403,21 @@ Item { // COMPONENTS ////////////////////////////////////////////////////////////// - AboutDialog{ + AboutDialog { id: aboutDialog } //-------------------------------------------------------------------------- - FeedbackDialog{ + FeedbackDialog { id: feedbackDialog metrics: mainView.appMetrics } // METHODS ///////////////////////////////////////////////////////////////// - function _returnButtonColor(cntrl){ - if(cntrl.enabled === false){ + function _returnButtonColor(cntrl) { + if (cntrl.enabled === false) { return toolBarButtonDisabledColor; } else if(cntrl.hovered){ @@ -388,7 +426,7 @@ Item { else if(cntrl.pressed){ return toolBarButtonPressedColor; } - else{ + else { return toolBarButtonColor; } } diff --git a/AvailableServicesInfoRequest.qml b/AvailableServicesInfoRequest.qml index 8c8bfee..9b52477 100644 --- a/AvailableServicesInfoRequest.qml +++ b/AvailableServicesInfoRequest.qml @@ -30,9 +30,17 @@ Item { property int tileIndex property string serviceUrl property bool useToken: true + property bool useTimeout: false + property int timeoutInterval: 30 signal complete(var data) + onComplete: { + if (timeoutTimer.running) { + timeoutTimer.stop(); + } + } + // COMPONENTS ////////////////////////////////////////////////////////////// NetworkRequest { @@ -136,7 +144,7 @@ Item { Timer { id: timeoutTimer - interval: 10000 + //interval: timeoutInterval * 1000 running: false repeat: false onTriggered: { @@ -151,11 +159,16 @@ Item { // METHODS ///////////////////////////////////////////////////////////////// - function sendRequest(){ + function sendRequest() { serviceRequest.send(); - timeoutTimer.start(); + if (useTimeout) { + timeoutTimer.interval = timeoutInterval * 1000; + timeoutTimer.start(); + } } + //-------------------------------------------------------------------------- + function _exportTilesAllowed(serviceInfo) { if (serviceInfo.hasOwnProperty("exportTilesAllowed")) { @@ -169,7 +182,6 @@ Item { else { return false; } - } // END ///////////////////////////////////////////////////////////////////// diff --git a/AvailableServicesModel.qml b/AvailableServicesModel.qml index 4606f96..4f4e3f4 100644 --- a/AvailableServicesModel.qml +++ b/AvailableServicesModel.qml @@ -36,8 +36,14 @@ Item { property int tileServiceSum: 0 property var requests: [] property alias getAvailableServices: tileServicesSearch - property string searchQuery: '(type:"Map Service" AND owner:esri AND title:(for Export)) OR (type:"Map Service" AND owner:' + portal.username + ') OR (type:("Map Service") AND group:(access:org))' + property string searchQuery: !app.includeCurrentUserInSearch + ? app.servicesSearchQuery + : app.currentUserSearchQuery > "" + ? app.servicesSearchQuery + " " + app.currentUserSearchQuery + : app.servicesSearchQuery property SqlQueryModel userAddedServices + property bool useTimeout: app.timeoutNonResponsiveServices + property int timeoutInterval: app.timeoutValue property ListModel servicesListModel: ListModel { property var tilesToRemove: [] @@ -63,6 +69,13 @@ Item { signal serviceAdded() signal serviceNotAdded() + + function reset(){ + tileServiceCount = 0; + tileServiceSum = 0; + requests = []; + } + // COMPONENTS ////////////////////////////////////////////////////////////// PortalSearch { @@ -95,7 +108,15 @@ Item { var component = Qt.createComponent("AvailableServicesInfoRequest.qml"); if (component.status === Component.Ready) { - var thisRequest = component.createObject(parent, { portal:availableServicesModel.portal, tileIndex: tileServiceCount, serviceUrl: result.url } ); + var thisRequest = component.createObject(parent, + { + portal:availableServicesModel.portal, + tileIndex: tileServiceCount, + serviceUrl: result.url, + useTimeout: availableServicesModel.useTimeout, + timeoutInterval: availableServicesModel.timeoutInterval + } + ); thisRequest.complete.connect(function(serviceData){ if (serviceData.keep === true) { @@ -187,7 +208,15 @@ Item { var component = Qt.createComponent("AvailableServicesInfoRequest.qml"); if (component.status === Component.Ready) { - var thisRequest = component.createObject(parent, { portal:availableServicesModel.portal, tileIndex: servicesListModel.count+1 , serviceUrl: url } ); + var thisRequest = component.createObject(parent, + { + portal:availableServicesModel.portal, + tileIndex: servicesListModel.count+1, + serviceUrl: url, + useTimeout: availableServicesModel.useTimeout, + timeoutInterval: availableServicesModel.timeoutInterval + } + ); thisRequest.complete.connect(function(serviceData){ if(serviceData.keep === true){ @@ -228,7 +257,8 @@ Item { thisRequest.destroy(2000); }); - thisRequest.send(); + thisRequest.sendRequest(); + //thisRequest.send(); } } diff --git a/AvailableServicesView.qml b/AvailableServicesView.qml index d422d4d..79cf8fa 100644 --- a/AvailableServicesView.qml +++ b/AvailableServicesView.qml @@ -14,8 +14,8 @@ * */ -import QtQuick 2.7 -import QtQuick.Controls 2.1 +import QtQuick 2.9 +import QtQuick.Controls 2.2 import QtQuick.Dialogs 1.2 import QtQuick.Layouts 1.1 import QtGraphicalEffects 1.0 @@ -91,11 +91,7 @@ Item { // SIGNAL IMPLEMENTATIONS ////////////////////////////////////////////////// Component.onCompleted: { - asm.getAvailableServices.start(); - activityIndicator.visible = true; - rotator.target = refreshSpinner; - refreshSpinner.visible = true; - rotator.start(); + getServices(); } //-------------------------------------------------------------------------- @@ -105,7 +101,22 @@ Item { mainView.appToolBar.backButtonEnabled = (!calledFromAnotherApp) ? true : false; mainView.appToolBar.backButtonVisible = (!calledFromAnotherApp) ? true : false; mainView.appToolBar.historyButtonEnabled = true; + mainView.appToolBar.settingsButtonEnabled = true; mainView.appToolBar.toolBarTitleLabel = Singletons.Strings.createNewTilePackage + if (settingsChanged) { + asm.reset(); + servicesStatusText.text = Singletons.Strings.queryingServices; + getServices(); + settingsChanged = false; + } + } + + function getServices(){ + asm.getAvailableServices.start(); + activityIndicator.visible = true; + rotator.target = refreshSpinner; + refreshSpinner.visible = true; + rotator.start(); } // UI ////////////////////////////////////////////////////////////////////// @@ -165,7 +176,7 @@ Item { Text { anchors.fill: parent id: servicesStatusText - font.family: notoRegular + font.family: defaultFontFamily font.pointSize: Singletons.Config.largeFontSizePoint text: Singletons.Strings.queryingServices verticalAlignment: Text.AlignTop @@ -207,7 +218,7 @@ Item { anchors.leftMargin: sf(20) verticalAlignment: Text.AlignVCenter text: Singletons.Strings.selectTileService - font.family: notoRegular + font.family: defaultFontFamily Accessible.role: Accessible.Heading Accessible.name: text @@ -295,7 +306,7 @@ Item { color: _uiEntryElementStates(parent) } color: Singletons.Colors.formElementFontColor - font.family: notoRegular + font.family: defaultFontFamily validator: RegExpValidator { regExp: /(http(s)*:\/\/).*/g @@ -328,7 +339,7 @@ Item { textFormat: Text.RichText text: parent.buttonText font.pointSize: Singletons.Config.baseFontSizePoint - font.family: notoRegular + font.family: defaultFontFamily Accessible.ignored: true } @@ -367,7 +378,7 @@ Item { textFormat: Text.RichText text: parent.buttonText font.pointSize: Singletons.Config.baseFontSizePoint - font.family: notoRegular + font.family: defaultFontFamily Accessible.ignored: true } @@ -428,7 +439,8 @@ Item { Text { anchors.centerIn: parent text: Singletons.Strings.noExportTileServices - font.family: notoBold + font.family: defaultFontFamily + font.weight: Font.Bold font.pointSize: Singletons.Config.largeFontSizePoint color: Singletons.Colors.boldUIElementFontColor } @@ -581,7 +593,7 @@ Item { anchors.margins: sf(10) font { pointSize: Singletons.Config.smallFontSizePoint - family: notoRegular + family: defaultFontFamily } color: Singletons.Colors.boldUIElementFontColor verticalAlignment: Text.AlignVCenter @@ -617,8 +629,8 @@ Item { verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter font.pointSize: Singletons.Config.xSmallFontSizePoint - font.family: notoRegular - text: spatialReference + font.family: defaultFontFamily + text: spatialReference || "N/A" color: isWebMercator ? "#007ac2" : "red" elide: Text.ElideRight @@ -641,7 +653,7 @@ Item { verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter font.pointSize: Singletons.Config.xSmallFontSizePoint - font.family: notoRegular + font.family: defaultFontFamily text: owner === "esri" ? "Esri" : "Non-Esri" color: owner === "esri" ? "#007ac2" : "darkorange" @@ -737,7 +749,7 @@ Item { width: parent.width text: "" color: app.info.properties.toolBarBackgroundColor - font.family: notoRegular + font.family: defaultFontFamily readOnly: true textFormat: Text.RichText wrapMode: TextArea.Wrap @@ -763,6 +775,11 @@ Item { property int menuItemHeight: sf(35) property var currentInfo: asm.servicesListModel.get(servicesGridView.currentIndex) + property bool userAddedService: (contextMenu.currentInfo !== undefined && contextMenu.currentInfo !== null) + ? contextMenu.currentInfo.userAdded !== undefined + ? (contextMenu.currentInfo.userAdded === true ? true : false) + : false + : false background: Rectangle { color: "#fff" @@ -819,8 +836,12 @@ Item { Button { height: visible ? contextMenu.menuItemHeight : 0 width: parent.width - visible: contextMenu.currentInfo !== undefined ? contextMenu.currentInfo.isArcgisTileService || portal.isPortal : false - enabled: contextMenu.currentInfo !== undefined ? contextMenu.currentInfo.isArcgisTileService || portal.isPortal : false + visible: (contextMenu.currentInfo !== undefined && contextMenu.currentInfo !== null) + ? contextMenu.currentInfo.isArcgisTileService || portal.isPortal + : false + enabled: (contextMenu.currentInfo !== undefined && contextMenu.currentInfo !== null) + ? contextMenu.currentInfo.isArcgisTileService || portal.isPortal + : false background: Rectangle { color: parent.hovered ? Singletons.Colors.subtleBackground : "#fff" } @@ -844,7 +865,9 @@ Item { height: sf(1) width: parent.width color: Singletons.Colors.subtleBackground - visible: contextMenu.currentInfo !== undefined ? contextMenu.currentInfo.isArcgisTileService || portal.isPortal : false + visible: (contextMenu.currentInfo !== undefined && contextMenu.currentInfo !== null) + ? contextMenu.currentInfo.isArcgisTileService || portal.isPortal + : false } Button { @@ -856,7 +879,9 @@ Item { contentItem: Text { anchors.fill: parent anchors.leftMargin: sf(10) - text: contextMenu.currentInfo !== undefined ? ( contextMenu.currentInfo.isArcgisTileService ? Singletons.Strings.viewRestService : Singletons.Strings.viewOnlineService) : "" + text: (contextMenu.currentInfo !== undefined && contextMenu.currentInfo !== null) + ? ( contextMenu.currentInfo.isArcgisTileService ? Singletons.Strings.viewRestService : Singletons.Strings.viewOnlineService) + : "" color: Singletons.Colors.boldUIElementFontColor verticalAlignment: Text.AlignVCenter } @@ -907,44 +932,44 @@ Item { Accessible.description: Singletons.Strings.createPItemDesc } -// Rectangle { -// height: sf(1) -// width: parent.width -// color: Singletons.Colors.subtleBackground -// visible: contextMenu.currentInfo !== undefined ? contextMenu.currentInfo.userAdded !== undefined ? (contextMenu.currentInfo.userAdded === true ? true : false) : false : false -// } - -// Button { -// height: contextMenu.menuItemHeight -// visible: contextMenu.currentInfo !== undefined ? contextMenu.currentInfo.userAdded !== undefined ? (contextMenu.currentInfo.userAdded === true ? true : false) : false : false -// enabled: contextMenu.currentInfo !== undefined ? contextMenu.currentInfo.userAdded !== undefined ? (contextMenu.currentInfo.userAdded === true ? true : false) : false : false -// width: parent.width -// background: Rectangle { -// color: parent.hovered ? Singletons.Colors.subtleBackground : "#fff" -// } -// contentItem: Text { -// anchors.fill: parent -// anchors.leftMargin: sf(10) -// text: qsTr("Delete tile service") -// color: Singletons.Colors.boldUIElementFontColor -// verticalAlignment: Text.AlignVCenter -// } -// onClicked: { -// try { -// var sql = "DELETE from 'other_tile_services' WHERE special_id = '%1'".arg(contextMenu.currentInfo.tpkId); -// appDatabase.write(sql); -// } -// catch(e){ -// console.log(e); -// } -// finally { -// //asm.servicesListModel.remove(servicesGridView.currentIndex); -// } -// } -// Accessible.role: Accessible.MenuItem -// Accessible.name: text -// Accessible.description: Singletons.Strings.createPItemDesc -// } + Rectangle { + height: sf(1) + width: parent.width + color: Singletons.Colors.subtleBackground + visible: contextMenu.userAddedService + } + + Button { + height: contextMenu.userAddedService ? contextMenu.menuItemHeight : 0 + visible: contextMenu.userAddedService + enabled: contextMenu.userAddedService + width: parent.width + background: Rectangle { + color: parent.hovered ? Singletons.Colors.subtleBackground : "#fff" + } + contentItem: Text { + anchors.fill: parent + anchors.leftMargin: sf(10) + text: Singletons.Strings.deleteTileService + color: Singletons.Colors.boldUIElementFontColor + verticalAlignment: Text.AlignVCenter + } + onClicked: { + try { + var sql = "DELETE from 'other_tile_services' WHERE special_id = '%1'".arg(contextMenu.currentInfo.tpkId); + appDatabase.write(sql); + asm.servicesListModel.remove(servicesGridView.currentIndex); + servicesGridView.currentIndex = -1; + contextMenu.close(); + } + catch(e){ + console.log(e); + } + } + Accessible.role: Accessible.MenuItem + Accessible.name: text + Accessible.description: Singletons.Strings.deleteTileService + } Accessible.role: Accessible.PopupMenu Accessible.name: Singletons.Strings.contextMenuDesc diff --git a/BrowseOrgView.qml b/BrowseOrgView.qml index 0f02801..9963a3f 100644 --- a/BrowseOrgView.qml +++ b/BrowseOrgView.qml @@ -1,4 +1,4 @@ -/* Copyright 2016 Esri +/* Copyright 2018 Esri * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -58,6 +58,7 @@ Item { StackView.onActivating: { mainView.appToolBar.enabled = true; mainView.appToolBar.historyButtonEnabled = true; + mainView.appToolBar.settingsButtonEnabled = true; mainView.appToolBar.backButtonEnabled = true; mainView.appToolBar.backButtonVisible = true; mainView.appToolBar.toolBarTitleLabel = Singletons.Strings.browseOrgTilePackages @@ -123,7 +124,8 @@ Item { Text { anchors.centerIn: parent text: Singletons.Strings.noOrgTileServices - font.family: notoBold + font.family: defaultFontFamily + font.weight: Font.Bold font.pointSize: Singletons.Config.largeFontSizePoint color: Singletons.Colors.boldUIElementFontColor } @@ -237,7 +239,7 @@ Item { anchors.margins: sf(10) font { pointSize: Singletons.Config.smallFontSizePoint - family: notoRegular + family: defaultFontFamily } color: Singletons.Colors.boldUIElementFontColor verticalAlignment: Text.AlignVCenter @@ -273,7 +275,7 @@ Item { verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter font.pointSize: Singletons.Config.xSmallFontSizePoint - font.family: notoRegular + font.family: defaultFontFamily text: spatialReference color: isWebMercator ? "#007ac2" : "red" elide: Text.ElideRight @@ -297,7 +299,7 @@ Item { verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter font.pointSize: Singletons.Config.xSmallFontSizePoint - font.family: notoRegular + font.family: defaultFontFamily text: owner === "esri" ? "Esri" : "Non-Esri" color: owner === "esri" ? "#007ac2" : "darkorange" @@ -460,7 +462,7 @@ Item { width: parent.width text: "" color: app.info.properties.toolBarBackgroundColor - font.family: notoRegular + font.family: defaultFontFamily readOnly: true textFormat: Text.RichText wrapMode: TextArea.Wrap diff --git a/Controls/StyledCheckBox.qml b/Controls/StyledCheckBox.qml index 3d4a7ff..742d019 100755 --- a/Controls/StyledCheckBox.qml +++ b/Controls/StyledCheckBox.qml @@ -1,4 +1,4 @@ -/* Copyright 2015 Esri +/* Copyright 2018 Esri * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,49 +14,109 @@ * */ -import QtQuick 2.5 -import QtQuick.Controls 1.4 -import QtQuick.Controls.Styles 1.4 +import QtQuick 2.9 +import QtQuick.Controls 2.2 import ArcGIS.AppFramework 1.0 +import "../" +import "../singletons" as Singletons + //------------------------------------------------------------------------------ CheckBox { + + id: control + checked: false + opacity: enabled ? 1 : .4 + + objectName: "ThemeCheckBox" + + property string label: "Checkbox" + property string tooltip: "" + property bool displayTooltip: tooltip > "" ? true : false + property double fontSizeMultiplier: 1 + + ToolTip.visible: displayTooltip && hovered + ToolTip.text: tooltip + + Accessible.role: Accessible.CheckBox + Accessible.name: control.label + Accessible.description: control.label + Accessible.focusable: true + + indicator: Rectangle { + height: parent.height > sf(20) ? sf(20) : parent.height + width: height + border.color: Singletons.Colors.darkGray + color: "transparent" + anchors.verticalCenter: parent.verticalCenter + + IconFont { + anchors.centerIn: parent + icon: _icons.checkmark + iconSizeMultiplier: .6 + color: Singletons.Colors.mainButtonBackgroundColor + Accessible.ignored: true + visible: control.checked + } + } + + contentItem: Text { + text: control.label + horizontalAlignment: !Singletons.Config.rtl ? Text.AlignLeft : Text.AlignRight + verticalAlignment: Text.AlignVCenter + leftPadding: !Singletons.Config.rtl ? control.indicator.width + (6 * AppFramework.displayScaleFactor) : 0 + rightPadding: !Singletons.Config.rtl ? 0 : control.indicator.width + (6 * AppFramework.displayScaleFactor) + color: Singletons.Colors.formElementFontColor + textFormat: Text.RichText + wrapMode: Text.Wrap + font { + family: defaultFontFamily + pointSize: Singletons.Config.baseFontSizePoint * control.fontSizeMultiplier + } + onLinkActivated: { + Qt.openUrlExternally(link); + } + } + + // END ///////////////////////////////////////////////////////////////////// + + property string fontFamily - style: CheckBoxStyle { - label: Item { - implicitWidth: text.implicitWidth + 2 - implicitHeight: text.implicitHeight - baselineOffset: text.baselineOffset +// style: CheckBoxStyle { +// label: Item { +// implicitWidth: text.implicitWidth + 2 +// implicitHeight: text.implicitHeight +// baselineOffset: text.baselineOffset - Rectangle { - anchors.fill: text - anchors.margins: -1 - anchors.leftMargin: -3 - anchors.rightMargin: -3 - visible: control.activeFocus - height: 6 - radius: 3 - color: "#224f9fef" - border.color: "#47b" - opacity: 0.6 - } +// Rectangle { +// anchors.fill: text +// anchors.margins: -1 +// anchors.leftMargin: -3 +// anchors.rightMargin: -3 +// visible: control.activeFocus +// height: 6 +// radius: 3 +// color: "#224f9fef" +// border.color: "#47b" +// opacity: 0.6 +// } - Text { - id: text - text: control.text //StyleHelpers.stylizeMnemonics(control.text) - anchors.centerIn: parent - color: "black" //SystemPaletteSingleton.text(control.enabled) - renderType: Text.QtRendering //Settings.isMobile ? Text.QtRendering : Text.NativeRendering - font { - pointSize: 14 - bold: false - family: fontFamily - } - textFormat: Text.RichText - } - } - } +// Text { +// id: text +// text: control.text //StyleHelpers.stylizeMnemonics(control.text) +// anchors.centerIn: parent +// color: "black" //SystemPaletteSingleton.text(control.enabled) +// renderType: Text.QtRendering //Settings.isMobile ? Text.QtRendering : Text.NativeRendering +// font { +// pointSize: 14 +// bold: false +// family: fontFamily +// } +// textFormat: Text.RichText +// } +// } +// } } diff --git a/Controls/StyledComboBox.qml b/Controls/StyledComboBox.qml index 7fa8d2f..b6633ac 100644 --- a/Controls/StyledComboBox.qml +++ b/Controls/StyledComboBox.qml @@ -5,7 +5,7 @@ import "../singletons" as Singletons ComboBox { id: control - font: notoRegular + font: defaultFontFamily onActivated: { console.log(currentIndex) @@ -58,7 +58,7 @@ ComboBox { rightPadding: control.indicator.width + control.spacing text: control.model !== null ? control.model.get(control.currentIndex)[control.textRole] : "" - font.family: notoRegular + font.family: defaultFontFamily font.pointSize: Singletons.Config.smallFontSizePoint color: Singletons.Colors.darkGray horizontalAlignment: Text.AlignLeft diff --git a/Controls/StyledRadioButton.qml b/Controls/StyledRadioButton.qml index fe6f139..7a275db 100755 --- a/Controls/StyledRadioButton.qml +++ b/Controls/StyledRadioButton.qml @@ -54,7 +54,7 @@ RadioButton { rightPadding: !control.rtl ? 0 : control.indicator.width + sf(1) color: Singletons.Colors.darkGray font { - family: notoRegular + family: defaultFontFamily pointSize: Singletons.Config.smallFontSizePoint } } diff --git a/Controls/StyledSlider.qml b/Controls/StyledSlider.qml new file mode 100644 index 0000000..b03a357 --- /dev/null +++ b/Controls/StyledSlider.qml @@ -0,0 +1,53 @@ +/* Copyright 2018 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 2.9 +import QtQuick.Controls 2.2 +import "../singletons" as Singletons + +Slider { + id: control + + background: Rectangle { + x: control.leftPadding + y: control.topPadding + control.availableHeight / 2 - height / 2 + //implicitWidth: parent.width + //implicitHeight: sf(4) + width: control.availableWidth + height: sf(4) + radius: sf(2) + color: Singletons.Colors.mediumGray + + Rectangle { + width: control.visualPosition * parent.width - x + height: parent.height + color: Singletons.Colors.mediumGray + radius: 2 + } + } + + handle: Rectangle { + x: control.leftPadding + control.visualPosition * (control.availableWidth - width) + y: control.topPadding + control.availableHeight / 2 - height / 2 + implicitWidth: sf(18) + implicitHeight: sf(18) + radius: sf(9) + color: pressed ? Singletons.Colors.mainButtonPressedColor : Singletons.Colors.mainButtonBackgroundColor + border.color: "#fff" + border.width: sf(2) + } + +} diff --git a/Controls/StyledTextField.qml b/Controls/StyledTextField.qml index 24c7543..64d4713 100755 --- a/Controls/StyledTextField.qml +++ b/Controls/StyledTextField.qml @@ -1,4 +1,4 @@ -/* Copyright 2017 Esri +/* Copyright 2018 Esri * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,8 +14,8 @@ * */ -import QtQuick 2.7 -import QtQuick.Controls 2.1 +import QtQuick 2.9 +import QtQuick.Controls 2.2 import "../singletons" as Singletons TextField { @@ -30,7 +30,7 @@ TextField { color: parent.enabled ? "#fff" : Singletons.Colors.lightGray } color: Singletons.Colors.darkGray - font.family: notoRegular + font.family: defaultFontFamily font.pointSize: Singletons.Config.smallFontSizePoint Accessible.role: Accessible.EditableText diff --git a/DeepLinkingRequest/DeepLinkingRequest.qml b/DeepLinkingRequest/DeepLinkingRequest.qml index 808b8f3..6bbf37d 100644 --- a/DeepLinkingRequest/DeepLinkingRequest.qml +++ b/DeepLinkingRequest/DeepLinkingRequest.qml @@ -1,4 +1,4 @@ -/* Copyright 2016 Esri +/* Copyright 2018 Esri * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/DeepLinkingRequest/TilePackageDeepLinkRequest.qml b/DeepLinkingRequest/TilePackageDeepLinkRequest.qml index 2b6103f..e9856a5 100644 --- a/DeepLinkingRequest/TilePackageDeepLinkRequest.qml +++ b/DeepLinkingRequest/TilePackageDeepLinkRequest.qml @@ -1,4 +1,4 @@ -/* Copyright 2016 Esri +/* Copyright 2018 Esri * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/DetailsForm.qml b/DetailsForm.qml index dbbdd20..3c28920 100644 --- a/DetailsForm.qml +++ b/DetailsForm.qml @@ -36,7 +36,7 @@ Rectangle { id: tpkDetailsForm - property int maxLevels: 19 + property int maxLevels: 21 property string currentSharing: "" property string currentExportTitle: "" property var currentTileService: null @@ -153,7 +153,7 @@ Rectangle { text: Singletons.Strings.currentTileService color: Singletons.Colors.darkGray font.pointSize: Singletons.Config.smallFontSizePoint - font.family: notoRegular + font.family: defaultFontFamily Layout.fillWidth: true Layout.fillHeight: true @@ -204,7 +204,7 @@ Rectangle { text: Singletons.Strings.numberOfZoomLevels color: Singletons.Colors.darkGray font.pointSize: Singletons.Config.smallFontSizePoint - font.family: notoRegular + font.family: defaultFontFamily Layout.fillWidth: true Layout.fillHeight: true @@ -254,7 +254,7 @@ Rectangle { horizontalAlignment: Text.AlignRight verticalAlignment: Text.AlignVCenter font.pointSize: Singletons.Config.mediumFontSizePoint - font.family: notoRegular + font.family: defaultFontFamily color: Singletons.Colors.darkGray Accessible.role: Accessible.StaticText @@ -318,7 +318,7 @@ Rectangle { text: Singletons.Strings.bufferRadius color: Singletons.Colors.darkGray font.pointSize: Singletons.Config.smallFontSizePoint - font.family: notoRegular + font.family: defaultFontFamily Layout.fillWidth: true Layout.fillHeight: true Accessible.role: Accessible.Heading @@ -412,7 +412,7 @@ Rectangle { text: Singletons.Strings.title + " *" textFormat: Text.RichText font.pointSize: Singletons.Config.smallFontSizePoint - font.family: notoRegular + font.family: defaultFontFamily color: Singletons.Colors.darkGray verticalAlignment: Text.AlignVCenter @@ -460,7 +460,7 @@ Rectangle { id: tpkFileTitleName anchors.fill: parent font.pointSize: Singletons.Config.xSmallFontSizePoint - font.family: notoRegular + font.family: defaultFontFamily color: Singletons.Colors.formElementFontColor } } @@ -484,7 +484,7 @@ Rectangle { text: Singletons.Strings.saveTo //qsTr("Save To") color: Singletons.Colors.darkGray font.pointSize: Singletons.Config.smallFontSizePoint - font.family: notoRegular + font.family: defaultFontFamily Layout.fillWidth: true Layout.preferredHeight: sf(20) Accessible.role: Accessible.Heading @@ -546,7 +546,7 @@ Rectangle { Text { text: Singletons.Strings.saveTo color: app.info.properties.mainButtonFontColor - font.family: notoRegular + font.family: defaultFontFamily anchors.centerIn: parent } } @@ -575,7 +575,7 @@ Rectangle { id: saveToLocationFolder text: "" font.pointSize: Singletons.Config.smallFontSizePoint - font.family: notoRegular + font.family: defaultFontFamily fontSizeMode: Text.Fit minimumPointSize: 10 verticalAlignment: Text.AlignVCenter @@ -649,7 +649,7 @@ Rectangle { Layout.preferredWidth: parent.width/2 text: Singletons.Strings.description font.pointSize: Singletons.Config.smallFontSizePoint - font.family: notoRegular + font.family: defaultFontFamily color: Singletons.Colors.darkGray verticalAlignment: Text.AlignVCenter Accessible.role: Accessible.Heading @@ -662,7 +662,7 @@ Rectangle { Layout.fillWidth: true text: "4000" font.pointSize: Singletons.Config.xSmallFontSizePoint - font.family: notoRegular + font.family: defaultFontFamily color: Singletons.Colors.darkGray horizontalAlignment: Text.AlignRight verticalAlignment: Text.AlignVCenter @@ -695,7 +695,7 @@ Rectangle { wrapMode: Text.Wrap color: Singletons.Colors.formElementFontColor - font.family: notoRegular + font.family: defaultFontFamily font.pointSize: Singletons.Config.xSmallFontSizePoint background: Rectangle { color: _uiEntryElementStates(parent) @@ -733,7 +733,7 @@ Rectangle { Label { text: Singletons.Strings.shareThisItemWith font.pointSize: Singletons.Config.smallFontSizePoint - font.family: notoRegular + font.family: defaultFontFamily color: Singletons.Colors.mainLabelFontColor anchors.fill: parent verticalAlignment: Text.AlignVCenter diff --git a/ExportView.qml b/ExportView.qml index db0d550..ab2da98 100644 --- a/ExportView.qml +++ b/ExportView.qml @@ -60,7 +60,9 @@ Item { if (serviceInfo.hasOwnProperty("tileInfo")) { if (serviceInfo.tileInfo.hasOwnProperty("lods")) { var availableLevels = (parseInt(serviceInfo.tileInfo.lods.length,10) - 1); - exportDetails.maxLevels = availableLevels > 19 ? 19 : availableLevels; + exportDetails.maxLevels = app.allowAllLevels + ? availableLevels + : availableLevels > 21 ? 21 : availableLevels; mapViewPlus.map.maximumZoomLevel = exportDetails.maxLevels; } } @@ -82,6 +84,7 @@ Item { mainView.appToolBar.backButtonEnabled = true; mainView.appToolBar.backButtonVisible = true; mainView.appToolBar.historyButtonEnabled = true; + mainView.appToolBar.settingsButtonEnabled = false; mainView.appToolBar.toolBarTitleLabel = Singletons.Strings.createNewTilePackage } @@ -169,6 +172,10 @@ Item { zoomLevelIndicator.text = "%1".arg(parseFloat(level).toFixed(1)); } + onClearErrors: { + exportStatusIndicator.hideImmediately(); + } + onPositionChanged: { if (!cursorIsOffMap) { _displayCoordinates(position.coordinate); @@ -215,7 +222,9 @@ Item { if (serviceInfo.hasOwnProperty("tileInfo")) { if (serviceInfo.tileInfo.hasOwnProperty("lods")) { var availableLevels = (parseInt(serviceInfo.tileInfo.lods.length,10) - 1); - exportDetails.maxLevels = availableLevels > 19 ? 19 : availableLevels; + exportDetails.maxLevels = app.allowAllLevels + ? availableLevels + : availableLevels > 21 ? 21 : availableLevels; mapViewPlus.map.maximumZoomLevel = exportDetails.maxLevels; } } @@ -258,7 +267,7 @@ Item { horizontalAlignment: Text.AlignHCenter color: "#fff" font.pointSize: Singletons.Config.smallFontSizePoint - font.family: notoRegular + font.family: defaultFontFamily Accessible.role: Accessible.Heading Accessible.name: text @@ -275,7 +284,7 @@ Item { verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter text: "--" - font.family: notoRegular + font.family: defaultFontFamily Accessible.role: Accessible.Indicator Accessible.name: text @@ -308,7 +317,7 @@ Item { horizontalAlignment: Text.AlignHCenter color: "#fff" font.pointSize: Singletons.Config.smallFontSizePoint - font.family: notoRegular + font.family: defaultFontFamily Accessible.role: Accessible.Heading Accessible.name: text @@ -325,7 +334,7 @@ Item { verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter text: "-- --" - font.family: notoRegular + font.family: defaultFontFamily Accessible.role: Accessible.Indicator Accessible.name: text @@ -358,7 +367,7 @@ Item { horizontalAlignment: Text.AlignHCenter color: "#fff" font.pointSize: Singletons.Config.smallFontSizePoint - font.family: notoRegular + font.family: defaultFontFamily Accessible.role: Accessible.Heading Accessible.name: text @@ -376,7 +385,7 @@ Item { verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter text: Singletons.Strings.notAvailableWithPaths - font.family: notoRegular + font.family: defaultFontFamily Accessible.ignored: mapViewPlus.geometryType !== Singletons.Constants.kMultipath Accessible.role: Accessible.Indicator @@ -392,7 +401,7 @@ Item { verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter text: "Tiles: -- Size: --" - font.family: notoRegular + font.family: defaultFontFamily Accessible.ignored: mapViewPlus.geometryType === Singletons.Constants.kMultipath Accessible.role: Accessible.Indicator @@ -613,7 +622,7 @@ Item { textFormat: Text.RichText text: (!exporting) ? Singletons.Strings.createTilePackage : Singletons.Strings.create font.pointSize: Singletons.Config.baseFontSizePoint - font.family: notoRegular + font.family: defaultFontFamily } ProgressIndicator { @@ -694,7 +703,7 @@ Item { textFormat: Text.RichText text: Singletons.Strings.cancel font.pointSize: Singletons.Config.baseFontSizePoint - font.family: notoRegular + font.family: defaultFontFamily } onClicked: { diff --git a/HistoryView.qml b/HistoryView.qml index 36d9ed1..91e47c3 100644 --- a/HistoryView.qml +++ b/HistoryView.qml @@ -51,6 +51,7 @@ Item { StackView.onActivating: { mainView.appToolBar.enabled = true; mainView.appToolBar.historyButtonEnabled = false; + mainView.appToolBar.settingsButtonEnabled = true; mainView.appToolBar.backButtonEnabled = true; mainView.appToolBar.backButtonVisible = true; mainView.appToolBar.toolBarTitleLabel = Singletons.Strings.exportAndUploadHistory; @@ -91,7 +92,7 @@ Item { Layout.fillWidth: true text: Singletons.Strings.exportHistory font.pointSize: Singletons.Config.mediumFontSizePoint - font.family: notoRegular + font.family: defaultFontFamily verticalAlignment: Text.AlignVCenter } Rectangle { @@ -116,7 +117,7 @@ Item { textFormat: Text.RichText text: Singletons.Strings.deleteHistory font.pointSize: Singletons.Config.baseFontSizePoint - font.family: notoRegular + font.family: defaultFontFamily } onClicked: { @@ -233,7 +234,7 @@ Item { Layout.fillWidth: true text: Singletons.Strings.uploadHistory font.pointSize: Singletons.Config.mediumFontSizePoint - font.family: notoRegular + font.family: defaultFontFamily verticalAlignment: Text.AlignVCenter } Rectangle { @@ -258,7 +259,7 @@ Item { textFormat: Text.RichText text: Singletons.Strings.deleteHistory font.pointSize: Singletons.Config.baseFontSizePoint - font.family: notoRegular + font.family: defaultFontFamily } onClicked: { diff --git a/IconFont.qml b/IconFont.qml index eb173cc..d52ee5a 100644 --- a/IconFont.qml +++ b/IconFont.qml @@ -50,7 +50,7 @@ Item { id: _iconImage visible: !useIconFont anchors.centerIn: _tpkIcon - source: !useIconFont ? _tpkIcon.icon : "images/alpha.svg" + source: !useIconFont ? _tpkIcon.icon : "" sourceSize.width: _tpkIcon.iconImageSize * _tpkIcon.iconSizeMultiplier sourceSize.height: _tpkIcon.iconImageSize * _tpkIcon.iconSizeMultiplier mipmap: true diff --git a/MainView.qml b/MainView.qml index c1f773f..7f0bb24 100644 --- a/MainView.qml +++ b/MainView.qml @@ -107,6 +107,8 @@ Item { appMetrics.userEmail = portal.user.email; appMetrics.checkForUpdates(); + app.currentUserSearchQuery = 'OR (type:"Map Service" AND owner:' + portal.username + ') OR (type:"Image Service" AND owner:' + portal.username + ')'; + if (!calledFromAnotherApp) { mainStackView.push(osv, {}, StackView.Immediate); } @@ -174,6 +176,14 @@ Item { //-------------------------------------------------------------------------- + Component { + id: sv + SettingsView { + } + } + + //-------------------------------------------------------------------------- + UpdatesDialog { id: uD metrics: appMetrics diff --git a/MapViewPlus/GeoJsonHelper.qml b/MapViewPlus/GeoJsonHelper.qml index d24f2a8..f84587f 100644 --- a/MapViewPlus/GeoJsonHelper.qml +++ b/MapViewPlus/GeoJsonHelper.qml @@ -35,132 +35,178 @@ Item{ property int inSR property int outSR + property var geojson: null + + property int currentFeature: 0 + property int numberOfFeatures: 0 + property bool multipleFeatures: numberOfFeatures > 1 + signal success(var geometry) signal error(string message) + signal unsupportedGeometry() // METHODS ///////////////////////////////////////////////////////////////// + function setGeoJson(json) { + geojson = json; + numberOfFeatures = geojson.features.length; + } + function parseGeometryFromFile(filepath){ - if(geoJsonFileFolder.fileExists(filepath)){ - try{ - var json = geoJsonFileFolder.readJsonFile(filepath) - _normalize(json); + if (geoJsonFileFolder.fileExists(filepath)) { + try { + var json = geoJsonFileFolder.readJsonFile(filepath); + setGeoJson(json); + getFeature(0); } - catch(error){ + catch(e) { error("There was an error reading the JSON file."); } } - else{ + else { error("JSON file doesn't exist"); } } //-------------------------------------------------------------------------- - function parseGeometry(json){ - _normalize(json); + function getFeature(feature) { + if (geojson === null) { + error("No geojson data."); + return; + } + + if (feature === undefined || feature < 0 || feature > geojson.features.length){ + feature = 0; + } + + currentFeature = feature; + + _normalize(feature); } //-------------------------------------------------------------------------- + function _normalize(feature){ - function _normalize(json){ + if (geojson === null) { + error("No geojson data."); + return; + } + + if (!geojson.hasOwnProperty("features")) { + error("JSON is missing 'features' attribute."); + return; + } var features; var isWebMercator = false; - if(json.hasOwnProperty("features")){ + if (feature === undefined || feature < 0 || feature > geojson.features.length){ + feature = 0; + } - if(json.features.length > 0){ - features = json.features[0]; - } + features = geojson.features[feature]; - // Esri geojson has crs property ----------------------------------- + // Esri geojson has crs property ----------------------------------- - if(json.hasOwnProperty("crs")){ - var sr = json.crs.properties.name; - if(sr.indexOf("3857") > -1 || sr.indexOf("102100") > -1){ - isWebMercator = true; - //returnGeometry.spatialReference = 3857; - } - else if(sr.indexOf("4326") > -1){ - returnGeometry.spatialReference = 4326; - } - else{ - returnGeometry.spatialRefernce = null; - error("Spatial reference cannot be determined for geojson file.") - } + if (geojson.hasOwnProperty("crs")) { + var sr = geojson.crs.properties.name; + if (sr.indexOf("3857") > -1 || sr.indexOf("102100") > -1) { + isWebMercator = true; + //returnGeometry.spatialReference = 3857; + } + else if (sr.indexOf("4326") > -1) { + returnGeometry.spatialReference = 4326; } + else { + returnGeometry.spatialRefernce = null; + error("Spatial reference cannot be determined for geojson file.") + } + } - // Esri json has spatialReference property ------------------------- + // Esri json has spatialReference property ------------------------- - if(json.hasOwnProperty("spatialReference")){ - if(json.spatialReference.wkid === 102100 || json.spatialReference.wkid === 3857 || json.spatialReference.latestWkid === 3857){ - //returnGeometry.spatialReference = 3857; - isWebMercator = true; - } + if (geojson.hasOwnProperty("spatialReference")) { + console.log("has spatialReference") + if (geojson.spatialReference.wkid === 102100 || geojson.spatialReference.wkid === 3857 || geojson.spatialReference.latestWkid === 3857) { + //returnGeometry.spatialReference = 3857; + isWebMercator = true; } + } - // Normalize type, for convenience normalize to esri types ----- + // Normalize type, for convenience normalize to esri types ----- - if(features.geometry.hasOwnProperty("type")){ - if(features.geometry.type === "Polygon"){ - returnGeometry.type = "esriGeometryPolygon"; - } - if(features.geometry.type === "LineString"){ - returnGeometry.type = "esriGeometryPolyline"; - } + if (features.geometry.hasOwnProperty("type")) { + if (features.geometry.type === "Polygon") { + returnGeometry.type = "esriGeometryPolygon"; } - - if(json.hasOwnProperty("geometryType")){ - returnGeometry.type = json.geometryType; + else if (features.geometry.type === "LineString") { + returnGeometry.type = "esriGeometryPolyline"; + } + else { + error("%1 feature. Feature type not supported.".arg(features.geometry.type)); + unsupportedGeometry(); + return; } + } + if (geojson.hasOwnProperty("geometryType")){ - if(features.hasOwnProperty("geometry")){ + returnGeometry.type = geojson.geometryType; - if(features.geometry.hasOwnProperty("coordinates")){ - returnGeometry.coordinates = (returnGeometry.type === "esriGeometryPolygon") ? features.geometry.coordinates[0]: features.geometry.coordinates; - } - else if(features.geometry.hasOwnProperty("paths")){ - if(features.geometry.paths.length > 0){ - returnGeometry.coordinates = features.geometry.paths[0]; + if (returnGeometry.type !== "esriGeometryPolygon" && returnGeometry.type !== "esriGeometryPolyline") { + error("%1 feature. Feature type not supported.".arg(geojson.geometryType)); + unsupportedGeometry(); + return; + } + } + + if (features.hasOwnProperty("geometry")) { + + if (features.geometry.hasOwnProperty("coordinates")) { + returnGeometry.coordinates = (returnGeometry.type === "esriGeometryPolygon") ? features.geometry.coordinates[0]: features.geometry.coordinates; + } + else if (features.geometry.hasOwnProperty("paths")) { + if (features.geometry.paths.length > 0) { + if (features.geometry.paths.length > 1) { + error(qsTr("Multi-part path features not supported currently. Showing first path only.")); } + returnGeometry.coordinates = features.geometry.paths[0]; } - else if(features.geometry.hasOwnProperty("rings")){ - if(features.geometry.rings.length > 0){ - returnGeometry.coordinates = features.geometry.rings[0]; + } + else if (features.geometry.hasOwnProperty("rings")) { + if (features.geometry.rings.length > 0) { + if (features.geometry.rings.length > 1) { + error(qsTr("Multi-part polygon features not supported currently. Showing first polygon only.")); } + returnGeometry.coordinates = features.geometry.rings[0]; } - else{ - returnGeometry.coordinates = []; - } - - // NOTE: Might need to throw an error if coordinate count is way way too large. Needs testing. + } + else { + returnGeometry.coordinates = []; + } - if(returnGeometry.coordinates.length > 0){ - if(isWebMercator){ - var newCoordsInLngLat = []; - for(var i = 0; i < returnGeometry.coordinates.length; i++){ - newCoordsInLngLat.push(converter.xyToLngLat(returnGeometry.coordinates[i])); - } + // NOTE: Might need to throw an error if coordinate count is way way too large. Needs testing. - returnGeometry.coordinates = newCoordsInLngLat; + if (returnGeometry.coordinates.length > 0) { + if (isWebMercator) { + var newCoordsInLngLat = []; + for (var i = 0; i < returnGeometry.coordinates.length; i++) { + newCoordsInLngLat.push(converter.xyToLngLat(returnGeometry.coordinates[i])); } - returnGeometry.coordinatesForQML = _prepareGeometryForQMLMap(returnGeometry.coordinates); - - success(returnGeometry); - } - else{ - error("JSON is missing geometry"); + returnGeometry.coordinates = newCoordsInLngLat; } + + returnGeometry.coordinatesForQML = _prepareGeometryForQMLMap(returnGeometry.coordinates); + + success(returnGeometry); + } + else { + error("JSON is missing geometry"); } } - else{ - error("JSON is missing 'features' attribute"); - } - } //-------------------------------------------------------------------------- @@ -169,7 +215,7 @@ Item{ var qmlGeometry = []; - for(var i = 0; i < coords.length; i++){ + for (var i = 0; i < coords.length; i++) { var set = coords[i]; @@ -199,7 +245,7 @@ Item{ if (g.hasOwnProperty("type")) { - if(g.type === Singletons.Constants.kMultipath) { + if (g.type === Singletons.Constants.kMultipath) { gType = "LineString"; gCoords = []; for(var x = 0; x < g.geometry.length; x++){ @@ -207,10 +253,10 @@ Item{ } } - if(g.type === Singletons.Constants.kPolygon){ + if (g.type === Singletons.Constants.kPolygon) { gType = "Polygon"; gCoords = [[]]; - for(var y = 0; y < g.geometry.length; y++){ + for (var y = 0; y < g.geometry.length; y++) { gCoords[0].push([g.geometry[y].coordinate.longitude, g.geometry[y].coordinate.latitude]); } } @@ -233,7 +279,7 @@ Item{ //-------------------------------------------------------------------------- - function saveGeojsonToFile(geometry,name){ + function saveGeoJsonToFile(geometry,name){ fileDialog.geoJsonToExport = geometry; fileDialog.geoJsonName = name.replace(/[^a-zA-Z0-9]/g,"_").toLocaleLowerCase(); fileDialog.open(); @@ -262,13 +308,13 @@ Item{ //-------------------------------------------------------------------------- - CoordinateConverter{ + CoordinateConverter { id:converter } //-------------------------------------------------------------------------- - GeometryUtilities{ + GeometryUtilities { id: geomUtilities } diff --git a/MapViewPlus/GeoSearch.qml b/MapViewPlus/GeoSearch.qml index 4b749c5..2d0c5c8 100644 --- a/MapViewPlus/GeoSearch.qml +++ b/MapViewPlus/GeoSearch.qml @@ -1,4 +1,4 @@ -/* Copyright 2016 Esri +/* Copyright 2018 Esri * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -278,7 +278,7 @@ Rectangle { color: Singletons.Colors.darkGray font { - family: notoRegular + family: defaultFontFamily pointSize: Singletons.Config.smallFontSizePoint } } @@ -289,7 +289,7 @@ Rectangle { color: Singletons.Colors.darkGray font { - family: notoRegular + family: defaultFontFamily pointSize: Singletons.Config.xSmallFontSizePoint } } diff --git a/MapViewPlus/MapDrawingMenu.qml b/MapViewPlus/MapDrawingMenu.qml index a5219a6..3a8dede 100644 --- a/MapViewPlus/MapDrawingMenu.qml +++ b/MapViewPlus/MapDrawingMenu.qml @@ -1,4 +1,4 @@ -/* Copyright 2016 Esri +/* Copyright 2018 Esri * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -41,9 +41,13 @@ Rectangle{ property string activeGeometryType: "" property bool historyAvailable: false property bool bookmarksAvailable: false + property bool bookmarksPopupOpen: false + property bool geoJsonInMemory: false + property bool geoJsonPopupOpen: false signal drawingRequest(string g) signal bookmarksRequested() + signal geoJsonFeatureRequested() // UI ////////////////////////////////////////////////////////////////////// @@ -102,6 +106,42 @@ Rectangle{ } } + Rectangle { + Layout.fillHeight: true + Layout.preferredWidth: height + Layout.margins: sf(5) + color: "#fff" + Button { + id: geojsonBtn + anchors.fill: parent + enabled: geoJsonInMemory + visible: geoJsonInMemory + ToolTip.text: qsTr("Shapefile or geojson data") + ToolTip.visible: hovered + + background: Rectangle { + anchors.fill: parent + color: geoJsonPopupOpen ? app.info.properties.mainButtonBorderColor : "#fff" + border.width: app.info.properties.mainButtonBorderWidth + border.color: parent.enabled ? app.info.properties.mainButtonBorderColor : "#ddd" + radius: sf(3) + } + + IconFont { + anchors.centerIn: parent + iconSizeMultiplier: 1.5 + color: parent.enabled + ? geoJsonPopupOpen ? "#fff" : app.info.properties.mainButtonBorderColor + : "#ddd" + icon: _icons.geojson + } + + onClicked: { + geoJsonFeatureRequested(); + } + } + } + Rectangle { Layout.fillHeight: true Layout.preferredWidth: sf(1) @@ -122,7 +162,9 @@ Rectangle{ background: Rectangle { anchors.fill: parent - color: parent.enabled ? ( parent.pressed ? "#bddbee" : "#fff" ) : "#fff" + color: parent.enabled + ? bookmarksPopupOpen ? app.info.properties.mainButtonBorderColor : ( parent.pressed ? "#bddbee" : "#fff" ) + : "#fff" border.width: app.info.properties.mainButtonBorderWidth border.color: parent.enabled ? app.info.properties.mainButtonBorderColor : "#ddd" radius: sf(3) @@ -131,7 +173,9 @@ Rectangle{ IconFont { anchors.centerIn: parent iconSizeMultiplier: 1.5 - color: parent.enabled ? app.info.properties.mainButtonBorderColor : "#ddd" + color: parent.enabled + ? bookmarksPopupOpen ? "#fff" : app.info.properties.mainButtonBorderColor + : "#ddd" icon: _icons.bookmark } @@ -231,7 +275,7 @@ Rectangle{ textFormat: Text.RichText text: name font.pointSize: Singletons.Config.baseFontSizePoint - font.family: notoRegular + font.family: defaultFontFamily } } } diff --git a/MapViewPlus/MapView.qml b/MapViewPlus/MapView.qml index a393aff..c46e71b 100644 --- a/MapViewPlus/MapView.qml +++ b/MapViewPlus/MapView.qml @@ -1,4 +1,4 @@ -/* Copyright 2016 Esri +/* Copyright 2018 Esri * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -63,7 +63,9 @@ Item { Map { id: baseMap + plugin: Plugin { + id: mapPlugin preferred: ["AppStudio"] PluginParameter { @@ -80,6 +82,12 @@ Item { name: "ArcGIS.mapping.mapTypes.mapSources" value: internal.mapSources } + +// PluginParameter { +// id: pluginMaxZoomLevel +// name: "ArcGIS.mapping.maximumZoomLevel" +// value: exportDetails.maxLevels +// } } center: QtPositioning.coordinate(defaultCenter.lat,defaultCenter.long) diff --git a/MapViewPlus/MapViewPlus.qml b/MapViewPlus/MapViewPlus.qml index 3454c9d..06cd8a2 100644 --- a/MapViewPlus/MapViewPlus.qml +++ b/MapViewPlus/MapViewPlus.qml @@ -1,4 +1,4 @@ -/* Copyright 2016 Esri +/* Copyright 2018 Esri * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,9 +14,9 @@ * */ -import QtQuick 2.6 -import QtQuick.Controls 2.1 -import QtQuick.Layouts 1.1 +import QtQuick 2.9 +import QtQuick.Controls 2.2 +import QtQuick.Layouts 1.3 import QtLocation 5.3 import QtPositioning 5.3 import QtGraphicalEffects 1.0 @@ -28,6 +28,7 @@ import ArcGIS.AppFramework.Sql 1.0 import "../Portal" import "../singletons" as Singletons import "../Controls" as Controls +import "../ProgressIndicator" import "../" //------------------------------------------------------------------------------ @@ -80,6 +81,7 @@ Item { signal drawingFinished() signal drawingCleared() signal drawingError(string error) + signal clearErrors() signal zoomLevelChanged(var level) signal positionChanged(var position) signal redraw(var data) @@ -145,6 +147,33 @@ Item { // UI ////////////////////////////////////////////////////////////////////// + Rectangle { + id: busyIndicator + color:"transparent" + anchors.fill: parent + visible: false + z: 10000000 + + Rectangle { + anchors.fill:parent + opacity: .9 + color: Singletons.Colors.subtleBackground + } + + ProgressIndicator { + id: workerScriptProgressIndicator + statusTextFontSize: Singletons.Config.smallFontSizePoint + statusTextMinimumFontSize: 6 + statusTextLeftMargin: sf(10) + iconContainerLeftMargin: sf(5) + iconContainerHeight: this.containerHeight - sf(5) + width: parent.width * .8 + anchors.centerIn: parent + } + } + + // ------------------------------------------------------------------------- + Item { id: topMenu width: ( parent.width < sf(1000) ) ? parent.width - sf(20) : sf(980) @@ -206,8 +235,8 @@ Item { } Item { - Layout.fillWidth: true Layout.fillHeight: true + Layout.preferredWidth: parent.width * .56 MapDrawingMenu { id: drawingMenu @@ -216,6 +245,9 @@ Item { drawingExists: userDrawnExtent historyAvailable: mapViewPlus.historyAvailable && (previewMap.map !== null ? previewMap.map.mapItems.length <= 0 : false) bookmarksAvailable: userBookmarks.count > 0 + bookmarksPopupOpen: bookmarksPopup.visible + geoJsonInMemory: geoJsonHelper.geojson !== null + geoJsonPopupOpen: geoJsonPopup.visible onDrawingRequest: { if (g === Singletons.Constants.kRedraw){ @@ -231,6 +263,12 @@ Item { onBookmarksRequested: { bookmarksPopup.open(); } + onGeoJsonFeatureRequested: { + geoJsonPopup.open(); + if (previewMap.map.mapItems.length === 0 ) { + geoJsonHelper.getFeature(0); + } + } } DropShadow { @@ -269,6 +307,356 @@ Item { clip: true } } + + Popup { + id: geoJsonPopup + width: sf(315) + height: sf(96) + x: topMenu.width - width + y: topMenu.height + padding: 0 + + background: Rectangle { + color: "#fff" + border.color: Singletons.Colors.mediumGray + border.width: sf(1) + } + + RowLayout { + anchors.fill: parent + anchors.margins: sf(5) + spacing: sf(5) + + Item { + Layout.fillWidth: true + Layout.fillHeight: true + + ColumnLayout { + anchors.fill: parent + spacing: 0 + + Item { + Layout.preferredHeight: sf(40) + Layout.topMargin: sf(15) + Layout.fillWidth: true + Accessible.role: Accessible.Pane + + RowLayout { + anchors.fill: parent + spacing: 0 + + Item { + Layout.fillHeight: true + Layout.preferredWidth: height + Accessible.role: Accessible.Pane + + Button { + anchors.fill: parent + + ToolTip.visible: hovered + ToolTip.text: Singletons.Strings.selectPreviousFeature + enabled: geoJsonHelper.multipleFeatures + + background: Rectangle{ + color: "transparent" + anchors.fill: parent + } + + IconFont { + anchors.centerIn: parent + icon: _icons.chevron_left + iconSizeMultiplier: 1 + color: parent.enabled ? Singletons.Colors.mainButtonBackgroundColor : Singletons.Colors.mediumGray + Accessible.ignored: true + } + + onClicked: { + clearErrors(); + var featureToGet = geoJsonHelper.currentFeature === 0 + ? geoJsonHelper.numberOfFeatures - 1 + : geoJsonHelper.currentFeature - 1; + geoJsonHelper.getFeature(featureToGet); + } + + Accessible.role: Accessible.Button + Accessible.name: Singletons.Strings.selectPreviousFeature + Accessible.description: Singletons.Strings.selectPreviousFeature + Accessible.onPressAction: { + if (enabled && visible) { + clicked(); + } + } + } + } + + Item { + Layout.fillHeight: true + Layout.fillWidth: true + Accessible.role: Accessible.Pane + + Controls.StyledTextField { + id: featureToUse + ToolTip.visible: hovered + ToolTip.text: Singletons.Strings.enterASpecificFeature + placeholderText: Singletons.Strings.enterASpecificFeature + anchors.fill: parent + text: "1" + horizontalAlignment: Text.AlignHCenter + leftPadding: 0 + rightPadding: 0 + font.pointSize: Singletons.Config.mediumFontSizePoint + enabled: geoJsonHelper.multipleFeatures + onAccepted: { + clearErrors(); + + var enteredNumber; + + if (!text.match(/^\d+$/)) { + enteredNumber = 1; + } + else { + enteredNumber = parseInt(text, 10); + } + + if (enteredNumber < 0 || enteredNumber === 0) { + enteredNumber = 1; + } + + if (enteredNumber > geoJsonHelper.numberOfFeatures) { + enteredNumber = geoJsonHelper.numberOfFeatures; + } + + enteredNumber--; + + geoJsonHelper.getFeature(enteredNumber); + } + Accessible.name: placeholderText + + Connections { + target: geoJsonHelper + onCurrentFeatureChanged: { + featureToUse.text = geoJsonHelper.currentFeature + 1; + } + } + } + } + + Item { + Layout.fillHeight: true + Layout.preferredWidth: height + Accessible.role: Accessible.Pane + + Button { + anchors.fill: parent + + ToolTip.visible: hovered + ToolTip.text: Singletons.Strings.selectNextFeature + enabled: geoJsonHelper.multipleFeatures + + background: Rectangle{ + color: "transparent" + anchors.fill: parent + } + + IconFont { + anchors.centerIn: parent + icon: _icons.chevron_right + iconSizeMultiplier: 1 + color: parent.enabled ? Singletons.Colors.mainButtonBackgroundColor : Singletons.Colors.mediumGray + Accessible.ignored: true + } + + onClicked: { + clearErrors(); + var featureToGet = geoJsonHelper.currentFeature === geoJsonHelper.numberOfFeatures - 1 + ? 0 + : geoJsonHelper.currentFeature + 1; + console.log(featureToGet) + geoJsonHelper.getFeature(featureToGet); + } + + Accessible.role: Accessible.Button + Accessible.name: Singletons.Strings.selectNextFeature + Accessible.description: Singletons.Strings.selectNextFeature + Accessible.onPressAction: { + if (enabled && visible) { + clicked(); + } + } + } + } + } + } + + Item { + Layout.fillWidth: true + Layout.fillHeight: true + Accessible.role: Accessible.Pane + + Text { + anchors.fill: parent + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + text: Singletons.Strings.viewingFeatureXofX.arg(geoJsonHelper.currentFeature + 1).arg(geoJsonHelper.numberOfFeatures) + color: Singletons.Colors.darkGray + font.pointSize: Singletons.Config.xSmallFontSizePoint + font.family: defaultFontFamily + wrapMode: Text.Wrap + } + } + } + + Accessible.role: Accessible.Pane + } + + Rectangle { + Layout.fillHeight: true + Layout.preferredWidth: sf(1) + color: Singletons.Colors.formElementBorderColor + Accessible.role: Accessible.Separator + } + + Item { + Layout.fillWidth: true + Layout.fillHeight: true + Accessible.role: Accessible.Pane + + ColumnLayout { + anchors.fill: parent + spacing: sf(6) + Item { + Layout.fillHeight: true + Accessible.ignored: true + } + Button { + Layout.preferredHeight: sf(30) + Layout.fillWidth: true + ToolTip.text: Singletons.Strings.saveAsGeojson + ToolTip.visible: hovered + + background: Rectangle { + anchors.fill: parent + color: Singletons.Config.buttonStates(parent, "clear") + radius: sf(4) + border.width: parent.enabled ? app.info.properties.mainButtonBorderWidth : 0 + border.color: app.info.properties.mainButtonBorderColor + } + RowLayout { + anchors.fill: parent + spacing: 0 + Item { + Layout.fillHeight: true + Layout.fillWidth: true + Layout.leftMargin: sf(10) + Accessible.role: Accessible.Pane + + Text { + anchors.fill: parent + verticalAlignment: Text.AlignVCenter + text: Singletons.Strings.saveAsGeojson + font.family: defaultFontFamily + font.pointSize: Singletons.Config.smallFontSizePoint + elide: Text.ElideRight + color: app.info.properties.mainButtonBorderColor + } + } + Item { + Layout.fillHeight: true + Layout.preferredWidth: height + Accessible.role: Accessible.Pane + + IconFont { + anchors.centerIn: parent + icon: _icons.download + iconSizeMultiplier: .8 + color: app.info.properties.mainButtonBorderColor + } + } + } + + onClicked: { + geoJsonHelper.saveGeoJsonToFile(geoJsonHelper.geojson, "tpk_saved_geojson_%1".arg(Date.now().toString())); + } + + Accessible.role: Accessible.Button + Accessible.name: Singletons.Strings.saveAsGeojson + Accessible.description: Singletons.Strings.saveAsGeojson + Accessible.onPressAction: { + if (enabled && visible) { + clicked(); + } + } + } + + Button { + Layout.preferredHeight: sf(30) + Layout.fillWidth: true + ToolTip.text: Singletons.Strings.clearAllData + ToolTip.visible: hovered + + background: Rectangle { + anchors.fill: parent + color: Singletons.Config.buttonStates(parent, "clear") + radius: sf(4) + border.width: parent.enabled ? app.info.properties.mainButtonBorderWidth : 0 + border.color: "red" + } + + RowLayout { + anchors.fill: parent + spacing: 0 + + Item { + Layout.fillHeight: true + Layout.fillWidth: true + Layout.leftMargin: sf(10) + Accessible.role: Accessible.Pane + + Text { + anchors.fill: parent + verticalAlignment: Text.AlignVCenter + text: Singletons.Strings.clearAllData + font.family: defaultFontFamily + font.pointSize: Singletons.Config.smallFontSizePoint + elide: Text.ElideRight + color: "red" + } + } + + Item { + Layout.fillHeight: true + Layout.preferredWidth: height + Accessible.role: Accessible.Pane + + IconFont { + anchors.centerIn: parent + icon: _icons.trash_bin + iconSizeMultiplier: .8 + color: "red" + } + } + } + onClicked: { + geoJsonHelper.geojson = null; + geoJsonPopup.close(); + } + Accessible.role: Accessible.Button + Accessible.name: Singletons.Strings.clearAllData + Accessible.description: Singletons.Strings.clearAllData + Accessible.onPressAction: { + if (enabled && visible) { + clicked(); + } + } + } + Item { + Layout.fillHeight: true + Accessible.ignored: true + } + } + } + } + } } Rectangle { @@ -314,6 +702,7 @@ Item { } onClicked: { + console.log(map.maximumZoomLevel) if(map.zoomLevel < map.maximumZoomLevel){ map.zoomLevel = Math.floor(map.zoomLevel) + 1; } @@ -346,7 +735,7 @@ Item { } } onClicked: { - if(map.zoomLevel > 0 && map.zoomLevel > map.minimumZoomLevel){ + if (map.zoomLevel > 0 && map.zoomLevel > map.minimumZoomLevel){ map.zoomLevel = Math.ceil(map.zoomLevel) - 1; } } @@ -388,7 +777,7 @@ Item { Text { id: drawingNotice anchors.fill: parent - font.family: notoRegular + font.family: defaultFontFamily font.pointSize: Singletons.Config.xSmallFontSizePoint verticalAlignment: Text.AlignVCenter wrapMode: Text.Wrap @@ -410,6 +799,8 @@ Item { z: previewMap.z + 3 } + + //-------------------------------------------------------------------------- DropArea { @@ -420,6 +811,7 @@ Item { // drag.urls } onDropped: { + clearErrors(); var notJSON = false; @@ -437,12 +829,11 @@ Item { for (var x = 0; x < drop.urls.length; x++) { var url = drop.urls[x].toString(); - var fileType = url.substr(url.length-4, 4); - if (fileType === ".prj") { + if (url.search(/.prj$/gi) > -1) { projectionFilePath = url; } - if (fileType === ".shp") { + if (url.search(/.shp$/gi) > -1) { shapeFilePath = url; } } @@ -479,13 +870,14 @@ Item { coordinateSystem = ""; return; } - - console.log(coordinateSystem); } } if (shapeFilePath !== "") { - + busyIndicator.visible = true; + workerScriptProgressIndicator.show(); + workerScriptProgressIndicator.progressIcon = workerScriptProgressIndicator.working; + workerScriptProgressIndicator.progressText = qsTr("Reading shapefile.."); workerScript.sendMessage({"path": shapeFilePath, "coordinate_system": coordinateSystem}); } } @@ -872,8 +1264,9 @@ Item { console.log("paste") if (AppFramework.clipboard.dataAvailable) { try { - var json = JSON.parse(AppFramework.clipboard.text) - geoJsonHelper.parseGeometry(json); + var json = JSON.parse(AppFramework.clipboard.text); + geoJsonHelper.setGeoJson(json); + geoJsonHelper.getFeature(0); } catch(e) { console.log("not json") @@ -894,7 +1287,7 @@ Item { //-------------------------------------------------------------------------- - MapPolyline{ + MapPolyline { id: drawnPolyline line.width: sf(3) line.color: drawnExtentOutlineColor @@ -902,7 +1295,7 @@ Item { //-------------------------------------------------------------------------- - MapPolygon{ + MapPolygon { id: drawnPolygon color: drawingExtentFillColor border.width: sf(2) @@ -1018,6 +1411,18 @@ Item { } mapViewPlus.map.fitViewportToMapItems(); + + if (!geoJsonPopup.visible) { + geoJsonPopup.open(); + } + } + + onUnsupportedGeometry: { + drawingFinished(); + clearDrawingCanvas(); + clearMap(); + drawingCleared(); + _updateDrawingHistory("clear", null); } onError: { @@ -1060,7 +1465,7 @@ Item { text: qsTr("Enter a title") verticalAlignment: Text.AlignVCenter font.pointSize: Singletons.Config.baseFontSizePoint - font.family: notoRegular + font.family: defaultFontFamily } } } @@ -1115,7 +1520,7 @@ Item { textFormat: Text.RichText text: Singletons.Strings.cancel font.pointSize: Singletons.Config.smallFontSizePoint - font.family: notoRegular + font.family: defaultFontFamily } onClicked: { @@ -1145,7 +1550,7 @@ Item { textFormat: Text.RichText text: Singletons.Strings.create font.pointSize: Singletons.Config.smallFontSizePoint - font.family: notoRegular + font.family: defaultFontFamily } onClicked: { @@ -1241,7 +1646,7 @@ Item { anchors.fill: parent verticalAlignment: Text.AlignVCenter text: name - font.family: notoRegular + font.family: defaultFontFamily font.pointSize: Singletons.Config.smallFontSizePoint elide: Text.ElideRight color: app.info.properties.mainButtonFontColor @@ -1258,7 +1663,7 @@ Item { Button { Layout.fillHeight: true Layout.preferredWidth: height - ToolTip.text: qsTr("Download as geojson") + ToolTip.text: Singletons.Strings.saveAsGeojson ToolTip.visible: hovered background: Rectangle { anchors.fill: parent @@ -1276,7 +1681,15 @@ Item { } onClicked: { - geoJsonHelper.saveGeojsonToFile(JSON.parse(geojson), name); + geoJsonHelper.saveGeoJsonToFile(JSON.parse(geojson), name); + } + Accessible.role: Accessible.Button + Accessible.name: Singletons.Strings.saveAsGeojson + Accessible.description: Singletons.Strings.saveAsGeojson + Accessible.onPressAction: { + if (enabled && visible) { + clicked(); + } } } Button { @@ -1304,6 +1717,14 @@ Item { appDatabase.write(sql); _loadBookmarks(); } + Accessible.role: Accessible.Button + Accessible.name: Singletons.Strings.deleteBookmark + Accessible.description: Singletons.Strings.deleteBookmark + Accessible.onPressAction: { + if (enabled && visible) { + clicked(); + } + } } } } @@ -1317,12 +1738,19 @@ Item { onMessage: { if (messageObject.hasOwnProperty("geojson")){ - geoJsonHelper.parseGeometry(messageObject.geojson); - // messageObject.geojson; + workerScriptProgressIndicator.progressIcon = workerScriptProgressIndicator.success + workerScriptProgressIndicator.progressText = Singletons.Strings.shapefileSuccessfullyImported + geoJsonHelper.setGeoJson(messageObject.geojson); + busyIndicator.visible = false; + geoJsonHelper.getFeature(0); + geoJsonPopup.open(); } if (messageObject.hasOwnProperty("error")){ drawingError("Error: %1".arg(messageObject.error.message)); - // messageObject.error.message + busyIndicator.visible = false; + } + if (messageObject.hasOwnProperty("status")){ + workerScriptProgressIndicator.progressText = messageObject.status; } } } @@ -1330,7 +1758,6 @@ Item { // METHODS ///////////////////////////////////////////////////////////////// function getCurrentGeometry(){ - console.log("----------------getCurrentGeometry():", geometryType); var g; if (drawMultipath) { g = getMutlipathGeometry(); diff --git a/MapViewPlus/shapeFileToGeoJSON.js b/MapViewPlus/shapeFileToGeoJSON.js index 1f245ac..4d6ca6d 100644 --- a/MapViewPlus/shapeFileToGeoJSON.js +++ b/MapViewPlus/shapeFileToGeoJSON.js @@ -2,6 +2,27 @@ // An Esri White Paper -- July 1998 // https://www.esri.com/library/whitepapers/pdfs/shapefile.pdf +var shpDataArray = null; +var shapeType = null; +var shapeValue = -1; +var shapeFileByteLength = 0; +var partsArray = []; +var pointsArray = []; +var cursor = 0; +var featureCount = 1; + +var geoJson = { + "type": "FeatureCollection", + "crs": { + "type" : "name", + "properties" : { + "name" : "" + } + }, + "bbox": [], + "shapefile_related": {}, + "features": [] +}; WorkerScript.onMessage = function(shapeFile) { @@ -24,7 +45,21 @@ WorkerScript.onMessage = function(shapeFile) { xhr.responseType = "arraybuffer"; xhr.open("GET", shapeFile.path, true); xhr.send(); +} +function establishSpatialReference(minx, miny, maxx, maxy){ + // the shape file .prj file was other than 3857 or 4326, so attempt + // to see if it is lat / lon or web mercator type values. + + // its highly unlikely a web mercator projection will fall within + // the following parameters, + + if (minx > 180 || minx < -180 || maxx > 180 || maxx < -180 || miny > 90 || miny < -90 || maxy > 90 || maxy < -90) { + return "3857"; + } + else { + return "4326"; + } } var shapeTypes = []; @@ -106,36 +141,32 @@ var shpHeader = { } } -var geoJson = { - "type": "FeatureCollection", - "crs": { - "type" : "name", - "properties" : { - "name" : "" - } - }, - "features": [] -}; - - function getShapeType(val){ return shapeTypes[val]; } function resetFeatures(){ + shpDataArray = null; + shapeFileByteLength = 0; + shapeType = null; + shapeValue = -1; geoJson.features = []; + cursor = 0; + partsArray = []; + pointsArray = []; + featureCount = 1; } function shapefileByteArrayToGeoJson(byteArray) { resetFeatures(); - var geoJsonFeature = {}; + shpDataArray = new DataView(byteArray); - var shpDataArray = new DataView(byteArray); + shapeFileByteLength = shpDataArray.byteLength; // A byteLength less than 101 means there is no geometry.------------------- - if (shpDataArray.byteLength < 101){ + if (shapeFileByteLength < 101){ try { throw new Error("This shapefile contains no geometry"); } @@ -143,149 +174,210 @@ function shapefileByteArrayToGeoJson(byteArray) { WorkerScript.sendMessage({"error": e}); } finally { + resetFeatures(); return; } } - var shapeValue = shpDataArray.getInt32(shpHeader.shape_type.position, shpHeader.shape_type.bigEndian); + shapeValue = shpDataArray.getInt32(shpHeader.shape_type.position, shpHeader.shape_type.bigEndian); + shapeType = shapeTypes[shapeValue]; + + geoJson["shapefile_related"]["byteLength"] = shapeFileByteLength; + geoJson["shapefile_related"]["shapeType"] = shapeValue; // only supporting MultilineString, Polygon -------------------------------- if (shapeValue !== 3 && shapeValue !== 5) { try { - throw new Error("This tool currently only supports polygons and polylines."); + throw new Error("This tool currently only supports polygons and polylines. Not %1".arg(shapeType.esri)); } catch(e) { WorkerScript.sendMessage({"error": e}); } finally { + resetFeatures(); return; } } - var shapeType = shapeTypes[shapeValue]; + var boundingBoxXMin = shpDataArray.getFloat64(shpHeader.xmin.position, shpHeader.xmin.bigEndian); + geoJson["bbox"][0] = boundingBoxXMin; - if (shapeType !== undefined && shapeType !== null && shapeType !== 0 && shapeType.geojson !== null) { + var boundingBoxYMin = shpDataArray.getFloat64(shpHeader.ymin.position, shpHeader.ymin.bigEndian); + geoJson["bbox"][1] = boundingBoxYMin; + + var boundingBoxXMax = shpDataArray.getFloat64(shpHeader.xmax.position, shpHeader.xmax.bigEndian); + geoJson["bbox"][2] = boundingBoxXMax; + + var boundingBoxYMax = shpDataArray.getFloat64(shpHeader.ymax.position, shpHeader.ymax.bigEndian); + geoJson["bbox"][3] = boundingBoxYMax; - geoJsonFeature["type"] = "Feature"; - geoJsonFeature["properties"] = {}; - geoJsonFeature["bbox"] = []; - geoJsonFeature["shapefile_related"] = {}; - geoJsonFeature["geometry"] = { - "type": shapeType.geojson, - "coordinates": [] + var sniffedSpatialReference = establishSpatialReference(boundingBoxXMin, boundingBoxYMin, boundingBoxXMax, boundingBoxYMax); + + if (geoJson["crs"]["properties"]["name"] > "" && geoJson["crs"]["properties"]["name"] !== sniffedSpatialReference.toString()){ + try { + throw new Error("Possible spatial reference mismatch. SR in .prj file doesn't seem to match coordinates found in .shp file."); } + catch(e) { + WorkerScript.sendMessage({"error": e}); + } + finally { + resetFeatures(); + return; + } + } + + if (geoJson["crs"]["properties"]["name"] === "") { + geoJson["crs"]["properties"]["name"] = sniffedSpatialReference; + } + + // geometry entries start at 100 after shape file header ------------------- + cursor = 100; - if (shapeValue === 5){ - geoJsonFeature["geometry"]["coordinates"][0] = []; + if (shapeType !== undefined && shapeType !== null && shapeType !== 0 && shapeType.geojson !== null) { + while (cursor < shapeFileByteLength) { + var feature = getFeature(cursor); + geoJson.features.push(feature); } + } - var boundingBoxXMin = shpDataArray.getFloat64(shpHeader.xmin.position, shpHeader.xmin.bigEndian); - geoJsonFeature["bbox"][0] = boundingBoxXMin; + //console.log(JSON.stringify(geoJson)); - var boundingBoxYMin = shpDataArray.getFloat64(shpHeader.ymin.position, shpHeader.ymin.bigEndian); - geoJsonFeature["bbox"][1] = boundingBoxYMin; + WorkerScript.sendMessage({"geojson": geoJson}); - var boundingBoxXMax = shpDataArray.getFloat64(shpHeader.xmax.position, shpHeader.xmax.bigEndian); - geoJsonFeature["bbox"][2] = boundingBoxXMax; + resetFeatures(); - var boundingBoxYMax = shpDataArray.getFloat64(shpHeader.ymax.position, shpHeader.ymax.bigEndian); - geoJsonFeature["bbox"][3] = boundingBoxYMax; +} - if (geoJson["crs"]["properties"]["name"] === "") { - geoJson["crs"]["properties"]["name"] = establishSpatialReference(boundingBoxXMin, boundingBoxXMin, boundingBoxXMax, boundingBoxYMax); - } +function getFeature(thisCursor){ - geoJsonFeature["shapefile_related"]["RecordNumber"] = shpDataArray.getInt32(100); - geoJsonFeature["shapefile_related"]["Content Length"] = shpDataArray.getInt32(104); - geoJsonFeature["shapefile_related"]["ShapeType"] = shpDataArray.getInt32(108, true); - geoJsonFeature["shapefile_related"]["box"] = [shpDataArray.getFloat64(112, true), shpDataArray.getFloat64(120, true), shpDataArray.getFloat64(128, true), shpDataArray.getFloat64(136, true)]; - geoJsonFeature["shapefile_related"]["numParts"] = shpDataArray.getInt32(144, true); - geoJsonFeature["shapefile_related"]["numPoints"] = shpDataArray.getInt32(148, true); - geoJsonFeature["shapefile_related"]["Parts"] = shpDataArray.getInt32(152, true); - geoJsonFeature["shapefile_related"]["X"] = (152 + 4 * geoJsonFeature["numParts"]); - - // can only handle one feature currenly -------------------------------- - if (geoJsonFeature["shapefile_related"]["numParts"] > 1) { - try { - throw new Error("This tool currently only supports one polygon, line, or multipath feature per shapefile."); - } - catch(e) { - WorkerScript.sendMessage({"error": e}); - } - finally { - return; - } - } + //console.log("getFeature: ", thisCursor); - // over 10000 points? then not gonna process currently ----------------- - if (geoJsonFeature["shapefile_related"]["numParts"] > 10000) { - try { - throw new Error("This tool only supports features with 10000 points on less."); - } - catch(e) { - WorkerScript.sendMessage({"error": e}); - } - finally { - return; - } + var currentFeature = {}; + partsArray = []; + pointsArray = []; + + currentFeature["type"] = "Feature"; + currentFeature["bbox"] = []; + currentFeature["properties"] = {}; + currentFeature["shapefile_related"] = {}; + currentFeature["geometry"] = { + "type": shapeType.geojson, + "coordinates": [] + } + + console.log(JSON.stringify(currentFeature)); + + currentFeature["properties"]["RecordNumber"] = shpDataArray.getInt32(thisCursor); + thisCursor += 4; + currentFeature["shapefile_related"]["Content Length"] = shpDataArray.getInt32(thisCursor); + thisCursor += 4; + currentFeature["shapefile_related"]["ShapeType"] = shpDataArray.getInt32(108, true); + thisCursor += 4; + currentFeature["bbox"] = [] + currentFeature["bbox"][0] = shpDataArray.getFloat64(thisCursor, true); + thisCursor += 8; + currentFeature["bbox"][1] = shpDataArray.getFloat64(thisCursor, true); + thisCursor += 8; + currentFeature["bbox"][2] = shpDataArray.getFloat64(thisCursor, true); + thisCursor += 8; + currentFeature["bbox"][3] = shpDataArray.getFloat64(thisCursor, true); + thisCursor += 8; + currentFeature["shapefile_related"]["numParts"] = shpDataArray.getInt32(thisCursor, true); + thisCursor += 4; + currentFeature["shapefile_related"]["numPoints"] = shpDataArray.getInt32(thisCursor, true); + thisCursor += 4; + + + if (currentFeature["shapefile_related"]["numParts"] > 1000) { + try { + throw new Error("This tool only supports shapefiles with less than 1000 parts."); } + catch(e) { + WorkerScript.sendMessage({"error": e}); + } + finally { + resetFeatures(); + return; + } + } + + if (currentFeature["shapefile_related"]["numParts"] > 0) { - // You've passed all the checks, now cursor through the data ----------- - var pointShapeType = shpDataArray.getFloat64(156, true); - console.log(pointShapeType); + try { - var cursor = 156; - var points = geoJsonFeature["shapefile_related"]["numPoints"]; + WorkerScript.sendMessage({"status": qsTr("Reading %1 features.".arg(featureCount))}); - for (var i = 0; i < points; i++) { - var pointX = shpDataArray.getFloat64(cursor, true); - cursor += 8; - var pointY = shpDataArray.getFloat64(cursor, true); - if(shapeValue === 5){ - geoJsonFeature["geometry"].coordinates[0].push([pointX,pointY]); - } - else if(shapeValue === 3){ - geoJsonFeature["geometry"].coordinates.push([pointX,pointY]); + var x = 0; + + for (x = 0; x < currentFeature["shapefile_related"]["numParts"]; x++) { + var pointLocation = shpDataArray.getInt32(thisCursor, true); + partsArray.push(pointLocation); + thisCursor += 4; } - else{ + console.log("partsArray.length: ", partsArray.length); + + var nP = currentFeature["shapefile_related"]["numPoints"] * 2; + + for (x = 0; x < nP; x++) { + var point = shpDataArray.getFloat64(thisCursor, true); + pointsArray.push(point); + thisCursor += 8; } - cursor +=8; - } +// console.log("pointsArray.length: ", pointsArray.length); - } + for (x = 0; x < partsArray.length; x++) { - geoJson.features.push(geoJsonFeature); + if (shapeValue === 5) { + currentFeature["geometry"].coordinates[x] = []; + } - WorkerScript.sendMessage({"geojson": geoJson}); + var pointStart = partsArray[x] * 2; // e.g. [0,320,333] - return geoJson; +// console.log("pointStart: ", pointStart); -} + var lastPoint = (x === partsArray.length - 1) ? pointsArray.length : partsArray[x+1] * 2; +// console.log("lastPoint: ", lastPoint) -function establishSpatialReference(minx, miny, maxx, maxy){ - console.log("establishSpatialReference") + var coordinate = []; - // the shape file .prj file was other than 3857 or 4326, so attempt - // to see if it is lat / lon or web mercator type values. + for (var pointCounter = pointStart; pointCounter < lastPoint; pointCounter++) { +// console.log("step: %1, pointCounter: %2, coord:%3, cLength:%4".arg(x).arg(pointCounter).arg(pointsArray[pointCounter]).arg(currentFeature["geometry"].coordinates[x].length)); - // its highly unlikely a web mercator projection will fall within - // the following parameters, + coordinate.push(pointsArray[pointCounter]); - if (minx > 180 - || minx < -180 - || maxx > 180 - || maxx < -180 - || miny > 90 - || miny < -90 - || maxy > 90 - || maxy < -90) { + if (coordinate.length === 2) { - return "3857"; - } - else { - return "4326"; + if (shapeValue === 5) { + currentFeature["geometry"].coordinates[x].push(coordinate); + } + else if (shapeValue === 3) { + currentFeature["geometry"].coordinates.push(coordinate); + } + else { + + } + coordinate = []; + } + } + } + featureCount ++; + } + catch(e) { + WorkerScript.sendMessage({"error": e}); + resetFeatures(); + } } + +// console.log("currentFeature: ", JSON.stringify(currentFeature)); + + // Set global cursor so next feature can be read by while loop ------------- + cursor = thisCursor; + +// console.log("cursor: ", cursor) + + return currentFeature; + } diff --git a/OperationSelectionView.qml b/OperationSelectionView.qml index a73c21c..74c9cef 100644 --- a/OperationSelectionView.qml +++ b/OperationSelectionView.qml @@ -39,6 +39,7 @@ Item { mainView.appToolBar.backButtonEnabled = false; mainView.appToolBar.backButtonVisible = false; mainView.appToolBar.historyButtonEnabled = true; + mainView.appToolBar.settingsButtonEnabled = true; } // UI ////////////////////////////////////////////////////////////////////// @@ -111,7 +112,7 @@ Item { textFormat: Text.RichText text: Singletons.Strings.upload font.pointSize: Singletons.Config.largeFontSizePoint * .8 - font.family: notoRegular + font.family: defaultFontFamily font.capitalization: Font.AllUppercase } } @@ -126,7 +127,7 @@ Item { textFormat: Text.RichText text: Singletons.Strings.localTilePackage font.pointSize: Singletons.Config.baseFontSizePoint - font.family: notoRegular + font.family: defaultFontFamily } } Item { @@ -201,7 +202,7 @@ Item { textFormat: Text.RichText text: Singletons.Strings.create font.pointSize: Singletons.Config.largeFontSizePoint * .8 - font.family: notoRegular + font.family: defaultFontFamily font.capitalization: Font.AllUppercase } } @@ -216,7 +217,7 @@ Item { textFormat: Text.RichText text: Singletons.Strings.newTilePackage font.pointSize: Singletons.Config.baseFontSizePoint - font.family: notoRegular + font.family: defaultFontFamily } } Item { @@ -291,7 +292,7 @@ Item { textFormat: Text.RichText text: Singletons.Strings.browse font.pointSize: Singletons.Config.largeFontSizePoint * .8 - font.family: notoRegular + font.family: defaultFontFamily font.capitalization: Font.AllUppercase } } @@ -306,7 +307,7 @@ Item { textFormat: Text.RichText text: Singletons.Strings.organizationTilePackages font.pointSize: Singletons.Config.baseFontSizePoint - font.family: notoRegular + font.family: defaultFontFamily } } Item { diff --git a/Portal/BuiltInSignInView.qml b/Portal/BuiltInSignInView.qml index 7c84343..610a51f 100755 --- a/Portal/BuiltInSignInView.qml +++ b/Portal/BuiltInSignInView.qml @@ -33,7 +33,7 @@ FocusScope { property alias username: usernameField.text property alias password: passwordField.text property bool hideCancel: false - property string fontFamily: notoRegular + property string fontFamily: defaultFontFamily signal rejected() diff --git a/Portal/PortalSettingsPage.qml b/Portal/PortalSettingsPage.qml index af09521..620f2e4 100644 --- a/Portal/PortalSettingsPage.qml +++ b/Portal/PortalSettingsPage.qml @@ -41,7 +41,7 @@ Rectangle { property bool showAuthentication: false - property string fontFamily: notoRegular + property string fontFamily: defaultFontFamily color: "white" diff --git a/Portal/PortalSignInView.qml b/Portal/PortalSignInView.qml index 3765c91..fdba5b6 100644 --- a/Portal/PortalSignInView.qml +++ b/Portal/PortalSignInView.qml @@ -50,12 +50,11 @@ Rectangle { readonly property string messageCodePasswordExired: "LLS_0002" - readonly property bool hasWebView: !(Qt.platform.os == "winrt") //|| Qt.platform.os == "winphone") - readonly property bool useOAuth: hasWebView && portal.supportsOAuth + readonly property bool useOAuth: portal.supportsOAuth property int buttonHeight: 35 * AppFramework.displayScaleFactor - property string fontFamily: notoRegular + property string fontFamily: defaultFontFamily signal accepted() signal rejected() @@ -405,7 +404,7 @@ Rectangle { anchors.fill: parent username: portal.username - fontFamily: notoRegular.family + fontFamily: defaultFontFamily.family onRejected: { signInView.rejected(); diff --git a/ProgressIndicator/ProgressIndicator.qml b/ProgressIndicator/ProgressIndicator.qml index a625f20..91073c4 100644 --- a/ProgressIndicator/ProgressIndicator.qml +++ b/ProgressIndicator/ProgressIndicator.qml @@ -1,4 +1,4 @@ -/* Copyright 2016 Esri +/* Copyright 2018 Esri * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -114,7 +114,7 @@ Rectangle { minimumPointSize: statusTextMinimumFontSize text: "" font.pointSize: statusTextFontSize - font.family: notoRegular + font.family: defaultFontFamily onLinkActivated: { Qt.openUrlExternally(link); } diff --git a/README.md b/README.md index 14a8681..7f4b4eb 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ Esri welcomes contributions from anyone and everyone. Please see our [guidelines ## Copyright and License -Copyright © 2016 Esri Inc. +Copyright © 2018 Esri Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/SettingsView.qml b/SettingsView.qml new file mode 100644 index 0000000..143cafd --- /dev/null +++ b/SettingsView.qml @@ -0,0 +1,296 @@ +/* Copyright 2018 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 2.9 +import QtQuick.Controls 2.2 +import QtQuick.Layouts 1.3 +import QtGraphicalEffects 1.0 +//------------------------------------------------------------------------------ +import ArcGIS.AppFramework 1.0 +import ArcGIS.AppFramework.Controls 1.0 +//------------------------------------------------------------------------------ +import "singletons" as Singletons +import "Controls" as Controls +//------------------------------------------------------------------------------ + +Item { + + // PROPERTIES ////////////////////////////////////////////////////////////// + + id: settingsView + + // SIGNAL IMPLEMENTATIONS ////////////////////////////////////////////////// + + StackView.onActivating: { + app.settingsChanged = false; + mainView.appToolBar.enabled = true; + mainView.appToolBar.settingsButtonEnabled = false; + mainView.appToolBar.historyButtonEnabled = true; + mainView.appToolBar.backButtonEnabled = true; + mainView.appToolBar.backButtonVisible = true; + mainView.appToolBar.toolBarTitleLabel = qsTr("Settings"); + } + + // UI ////////////////////////////////////////////////////////////////////// + + ColumnLayout { + anchors.fill: parent + anchors.margins: sf(10) + spacing: 0 + + Item { + Layout.fillWidth: true + Layout.preferredHeight: sf(30) + Controls.StyledCheckBox { + anchors.fill: parent + checked: app.allowAllLevels + label: Singletons.Strings.enableAllZoomLevels + onCheckedChanged: { + app.allowAllLevels = checked; + } + } + } + + Rectangle { + Layout.preferredHeight: sf(1) + Layout.fillWidth: true + Layout.topMargin: sf(20) + Layout.bottomMargin: sf(20) + color: Singletons.Colors.darkGray + } + + Item { + Layout.fillWidth: true + Layout.preferredHeight: sf(50) + Controls.StyledCheckBox { + id: timeOutCheckBox + anchors.fill: parent + checked: app.timeoutNonResponsiveServices + label: Singletons.Strings.timeOutNonResponsive + onCheckedChanged: { + app.timeoutNonResponsiveServices = checked; + } + } + } + + Item { + Layout.preferredWidth: parent.width * .7 + Layout.preferredHeight: sf(30) + Layout.topMargin: sf(20) + visible: app.timeoutNonResponsiveServices + + RowLayout { + anchors.fill: parent + spacing: sf(10) + Item { + Layout.fillHeight: true + Layout.fillWidth: true + RowLayout { + anchors.fill: parent + spacing: sf(8) + Text { + Layout.fillHeight: true + Layout.preferredWidth: contentWidth + text: Singletons.Strings.timeOutAfter + verticalAlignment: Text.AlignVCenter + wrapMode: Text.Wrap + } + Controls.StyledSlider { + Layout.fillWidth: true + Layout.fillHeight: true + from: 3 + to: 30 + stepSize: 1 + value: app.timeoutValue + snapMode: Slider.SnapAlways + onValueChanged: { + app.timeoutValue = value; + } + } + Text { + Layout.fillHeight: true + Layout.preferredWidth: contentWidth + verticalAlignment: Text.AlignVCenter + text: Singletons.Strings.xSeconds.arg(app.timeoutValue) + } + } + } + } + } + + Rectangle { + Layout.preferredHeight: sf(1) + Layout.fillWidth: true + Layout.topMargin: sf(20) + Layout.bottomMargin: sf(20) + color: Singletons.Colors.darkGray + } + + Item { + Layout.preferredWidth: parent.width + Layout.preferredHeight: sf(160) + + ColumnLayout { + anchors.fill: parent + spacing: sf(8) + Text { + Layout.fillHeight: true + Layout.preferredWidth: contentWidth + text: qsTr("Search Query for Tile Services (see Search API for more details)") + verticalAlignment: Text.AlignVCenter + wrapMode: Text.Wrap + color: Singletons.Colors.formElementFontColor + textFormat: Text.RichText + font { + family: defaultFontFamily + pointSize: Singletons.Config.baseFontSizePoint + } + onLinkActivated: { + Qt.openUrlExternally(link); + } + } + + Item { + Layout.fillWidth: true + Layout.preferredHeight: sf(40) + Controls.StyledTextField { + id: searchQueryTextField + anchors.fill: parent + text: app.settings.value(Singletons.Constants.kSearchQueryString) + Component.onCompleted: { + cursorPosition = 0; + } + } + } + + Item { + Layout.fillWidth: true + Layout.preferredHeight: sf(50) + Controls.StyledCheckBox { + id: includeCurrentUserSearchQuery + anchors.fill: parent + checked: app.includeCurrentUserInSearch + label: qsTr("Include Map and Image Services owned by %1 in query?
%2".arg(portal.username).arg(app.currentUserSearchQuery)) + fontSizeMultiplier: .8 + onCheckedChanged: { + app.includeCurrentUserInSearch = checked; + } + } + } + + RowLayout { + spacing: sf(5) + Layout.preferredHeight: sf(40) + Layout.fillWidth: true + + Item { + Layout.preferredWidth: sf(140) + Layout.fillHeight: true + Button { + anchors.fill: parent + + background: Rectangle { + anchors.fill: parent + color: Singletons.Config.buttonStates(parent, "clear") + radius: app.info.properties.mainButtonRadius + border.width: 0 + border.color: app.info.properties.mainButtonBorderColor + } + Text { + color: app.info.properties.mainButtonBorderColor + anchors.centerIn: parent + textFormat: Text.RichText + text: qsTr("Reset to default") + font.pointSize: Singletons.Config.baseFontSizePoint + font.family: defaultFontFamily + } + onClicked: { + searchQueryTextField.text = app.defaultSearchQuery; + includeCurrentUserSearchQuery.checked = true; + updateButton.clicked(); + } + } + } + Item { + Layout.fillWidth: true + } + + Item { + Layout.preferredWidth: sf(100) + Layout.fillHeight: true + Button { + id: updateButton + anchors.fill: parent + enabled: searchQueryTextField.text > "" + background: Rectangle { + anchors.fill: parent + color: Singletons.Config.buttonStates(parent) + radius: app.info.properties.mainButtonRadius + border.width: parent.enabled ? app.info.properties.mainButtonBorderWidth : 0 + border.color: app.info.properties.mainButtonBorderColor + } + Text { + color: app.info.properties.mainButtonFontColor + anchors.centerIn: parent + textFormat: Text.RichText + text: qsTr("Update") + font.pointSize: Singletons.Config.baseFontSizePoint + font.family: defaultFontFamily + } + onClicked: { + app.servicesSearchQuery = searchQueryTextField.text; + } + } + } + } + } + } + + Rectangle { + Layout.preferredHeight: sf(1) + Layout.fillWidth: true + Layout.topMargin: sf(20) + Layout.bottomMargin: sf(20) + color: Singletons.Colors.darkGray + } + + //---------------------------------------------------------------------- + +// Item { +// Layout.fillWidth: true +// Layout.preferredHeight: sf(30) +// Controls.StyledCheckBox { +// anchors.fill: parent +// label: Singletons.Strings.allowNonWebMerctorServices +// checked: app.allowNonWebMercatorServices +// onCheckedChanged: { +// app.allowNonWebMercatorServices = checked; +// } +// } +// } + + //---------------------------------------------------------------------- + + Item { + Layout.fillHeight: true + } + + //---------------------------------------------------------------------- + + } + + // END ///////////////////////////////////////////////////////////////////// +} diff --git a/StatusIndicator.qml b/StatusIndicator.qml index 0b728bf..2ee75e3 100644 --- a/StatusIndicator.qml +++ b/StatusIndicator.qml @@ -1,4 +1,4 @@ -/* Copyright 2016 Esri +/* Copyright 2018 Esri * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -61,6 +61,7 @@ Rectangle { signal show() signal hide() + signal hideImmediately() signal linkClicked(string link) color: messageType.backgroundColor @@ -86,7 +87,7 @@ Rectangle { textFormat: Text.RichText text: "" font.pointSize: statusTextFontSize - font.family: notoRegular + font.family: defaultFontFamily wrapMode: Text.WordWrap lineHeight: narrowLineHeight ? .7 : 1 onLinkActivated: { @@ -143,6 +144,15 @@ Rectangle { fader.start() } + //-------------------------------------------------------------------------- + + onHideImmediately: { + esriStatusIndicator.visible = false; + if (hideStatusMessage.running) { + hideStatusMessage.stop(); + } + } + // COMPONENTS ////////////////////////////////////////////////////////////// Timer { diff --git a/TilePackage/TilePackageGetPKInfo.qml b/TilePackage/TilePackageGetPKInfo.qml index 6b9c753..70d6561 100644 --- a/TilePackage/TilePackageGetPKInfo.qml +++ b/TilePackage/TilePackageGetPKInfo.qml @@ -1,4 +1,4 @@ -/* Copyright 2016 Esri +/* Copyright 2018 Esri * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/TilePackageKreator.qml b/TilePackageKreator.qml index 65a6751..cda5f39 100644 --- a/TilePackageKreator.qml +++ b/TilePackageKreator.qml @@ -1,4 +1,4 @@ -/* Copyright 2017 Esri +/* Copyright 2018 Esri * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,11 +14,12 @@ * */ -import QtQuick 2.7 +import QtQuick 2.9 //------------------------------------------------------------------------------ import ArcGIS.AppFramework 1.0 //------------------------------------------------------------------------------ import "Portal" +import "singletons" as Singletons //------------------------------------------------------------------------------ App { @@ -35,10 +36,17 @@ App { property bool useIconFont: Qt.platform.os !== "windows" ? true : false property string icons: _icons.status == FontLoader.Ready ? _icons.name : "tilepackage" - property string notoRegular: _notoRegular.status == FontLoader.Ready ? _notoRegular.name : "Noto Sans" - property string notoBold: _notoBold.status == FontLoader.Ready ? _notoBold.name : "Noto Sans" - property string notoItalic: _notoItalic.status == FontLoader.Ready ? _notoItalic.name : "Noto Sans" - property string notoBoldItalic: _notoBoldItalic.status == FontLoader.Ready ? _notoBoldItalic.name : "Noto Sans" + property string defaultFontFamily: Qt.application.font.family + + property bool settingsChanged: false + property bool allowAllLevels: app.settings.boolValue(Singletons.Constants.kAllowAllZoomLevels, false) + property bool allowNonWebMercatorServices: app.settings.boolValue(Singletons.Constants.kAllowNonWebMercatorServices, false) + property bool timeoutNonResponsiveServices: app.settings.boolValue(Singletons.Constants.kTimeOutUnresponsiveServices, true) + property int timeoutValue: app.settings.numberValue(Singletons.Constants.kTimeOutValue, 7) + property string defaultSearchQuery: '(type:"Map Service" AND owner:esri AND title:(for Export)) OR (type:("Map Service") AND group:(access:org))' + property string currentUserSearchQuery: "" + property bool includeCurrentUserInSearch: app.settings.boolValue(Singletons.Constants.kIncludeCurrentUserInSearch, true); + property string servicesSearchQuery: app.settings.value(Singletons.Constants.kSearchQueryString, defaultSearchQuery); Component.onCompleted: { if (!appDatabase.exists()) { @@ -55,6 +63,34 @@ App { } } + onAllowAllLevelsChanged: { + app.settings.setValue(Singletons.Constants.kAllowAllZoomLevels, allowAllLevels); + } + + onAllowNonWebMercatorServicesChanged: { + app.settings.setValue(Singletons.Constants.kAllowNonWebMercatorServices, allowNonWebMercatorServices); + } + + onTimeoutNonResponsiveServicesChanged: { + settingsChanged = true; + app.settings.setValue(Singletons.Constants.kTimeOutUnresponsiveServices, timeoutNonResponsiveServices); + } + + onTimeoutValueChanged: { + settingsChanged = true; + app.settings.setValue(Singletons.Constants.kTimeOutValue, timeoutValue); + } + + onServicesSearchQueryChanged: { + settingsChanged = true; + app.settings.setValue(Singletons.Constants.kSearchQueryString, servicesSearchQuery); + } + + onIncludeCurrentUserInSearchChanged: { + settingsChanged = true; + app.settings.boolValue(Singletons.Constants.kIncludeCurrentUserInSearch, includeCurrentUserInSearch); + } + // COMPONENTS ////////////////////////////////////////////////////////////// Portal { @@ -78,23 +114,6 @@ App { //-------------------------------------------------------------------------- - FontLoader { - id: _notoRegular - source: "fonts/NotoSans-Regular.ttf" - } - FontLoader { - id: _notoBold - source: "fonts/NotoSans-Bold.ttf" - } - FontLoader { - id: _notoItalic - source: "fonts/NotoSans-Italic.ttf" - } - FontLoader { - id: _notoBoldItalic - source: "fonts/NotoSans-BoldItalic.ttf" - } - FontLoader { id: _icons source: "fonts/tilepackage.ttf" @@ -111,6 +130,7 @@ App { property string draw_path: useIconFont ? "y" : "images/draw-path.svg" property string draw_polygon: useIconFont ? "D" : "images/draw-polygon.svg" property string draw_tool: useIconFont ? "F" : "images/draw-tool.svg" + property string geojson: useIconFont ? "H" : "images/geojson.svg" property string happy_face: useIconFont ? "x" : "images/happy.svg" property string history: useIconFont ? "f" : "images/history.svg" property string info: useIconFont ? "r" : "images/info.svg" @@ -121,6 +141,7 @@ App { property string question: useIconFont ? "u" : "images/question.svg" property string redraw_last_path: useIconFont ? "d" : "images/redraw-last.svg" property string sad_face: useIconFont ? "w" : "images/sad.svg" + property string settings: useIconFont ? "G" : "images/settings.svg" property string sign_out: useIconFont ? "c" : "images/sign-out.svg" // property string spinner: "\ue982" property string spinner2: useIconFont ? "i" : "images/spinner2.svg" diff --git a/UploadView.qml b/UploadView.qml index a276069..83cb4b7 100644 --- a/UploadView.qml +++ b/UploadView.qml @@ -67,6 +67,7 @@ Item { mainView.appToolBar.backButtonEnabled = (!calledFromAnotherApp) ? true : false mainView.appToolBar.backButtonVisible = (!calledFromAnotherApp) ? true : false mainView.appToolBar.historyButtonEnabled = true; + mainView.appToolBar.settingsButtonEnabled = true; mainView.appToolBar.toolBarTitleLabel = Singletons.Strings.uploadTilePackage } @@ -166,7 +167,7 @@ Item { horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter font.pointSize: Singletons.Config.largeFontSizePoint - font.family: notoRegular + font.family: defaultFontFamily } Text { Layout.fillWidth: true @@ -175,7 +176,7 @@ Item { color: Singletons.Colors.boldUIElementFontColor horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter - font.family: notoRegular + font.family: defaultFontFamily } Rectangle { Layout.fillWidth: true @@ -202,7 +203,7 @@ Item { textFormat: Text.RichText text: Singletons.Strings.browseForFile font.pointSize: Singletons.Config.baseFontSizePoint - font.family: notoRegular + font.family: defaultFontFamily } onClicked: { resetProperties(); @@ -244,7 +245,7 @@ Item { Layout.preferredHeight: selectedTPK.height / 4 text: "filename.tpk" fontSizeMode: Text.Fit - font.family: notoRegular + font.family: defaultFontFamily minimumPointSize: Singletons.Config.smallFontSizePoint color: Singletons.Colors.boldUIElementFontColor font.pointSize: Singletons.Config.largeFontSizePoint @@ -287,7 +288,7 @@ Item { textFormat: Text.RichText text: Singletons.Strings.useDifferentFile font.pointSize: Singletons.Config.baseFontSizePoint - font.family: notoRegular + font.family: defaultFontFamily } onClicked: { fileAcceptedForUpload = false; @@ -414,7 +415,7 @@ Item { textFormat: Text.RichText text: uploading ? ( tpkPackage.aborted ? Singletons.Strings.cancelling : Singletons.Strings.uploading ): Singletons.Strings.upload font.pointSize: Singletons.Config.baseFontSizePoint - font.family: notoRegular + font.family: defaultFontFamily } ProgressIndicator{ @@ -464,7 +465,7 @@ Item { textFormat: Text.RichText text: Singletons.Strings.cancel font.pointSize: Singletons.Config.baseFontSizePoint - font.family: notoRegular + font.family: defaultFontFamily } onClicked: { diff --git a/appinfo.json b/appinfo.json index 2ddfefa..f03b479 100644 --- a/appinfo.json +++ b/appinfo.json @@ -8,6 +8,10 @@ "camera": false, "fileSharing": false, "highAccuracyLocation": false, + "ios": { + "externalAccessoryProtocolStrings": [ + ] + }, "localnotification": false, "location": true, "microphone": false, @@ -71,6 +75,7 @@ "arcgis-survey123connect" ], "mainFile": "TilePackageKreator.qml", + "multipleInstances": true, "projectFile": "TilePackageKreator.qmlproject", "properties": { "mainButtonBackgroundColor": "#196fa6", @@ -96,7 +101,7 @@ "urlScheme": "arcgis-tilepackage", "version": { "major": 1, - "micro": 23, - "minor": 2 + "micro": 29, + "minor": 3 } } diff --git a/fonts/tilepackage.svg b/fonts/tilepackage.svg new file mode 100644 index 0000000..c4a395d --- /dev/null +++ b/fonts/tilepackage.svg @@ -0,0 +1,44 @@ + + + +Generated by Fontastic.me + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fonts/tilepackage.ttf b/fonts/tilepackage.ttf index 5127c91..42d0045 100644 Binary files a/fonts/tilepackage.ttf and b/fonts/tilepackage.ttf differ diff --git a/fonts/tilepackagekreator.ttf b/fonts/tilepackagekreator.ttf deleted file mode 100644 index efdf150..0000000 Binary files a/fonts/tilepackagekreator.ttf and /dev/null differ diff --git a/fonts/tpk.ttf b/fonts/tpk.ttf deleted file mode 100755 index 3dcabbb..0000000 Binary files a/fonts/tpk.ttf and /dev/null differ diff --git a/images/geojson.svg b/images/geojson.svg new file mode 100644 index 0000000..f6f37d0 --- /dev/null +++ b/images/geojson.svg @@ -0,0 +1,53 @@ + + + +file-empty + + + + + + + + + + + + + diff --git a/images/settings.svg b/images/settings.svg new file mode 100755 index 0000000..67fd8fa --- /dev/null +++ b/images/settings.svg @@ -0,0 +1,5 @@ + + +cogs + + diff --git a/iteminfo.json b/iteminfo.json index da142f7..18410f4 100644 --- a/iteminfo.json +++ b/iteminfo.json @@ -14,6 +14,7 @@ "documentation": null, "extent": [ ], + "groupDesignations": null, "guid": null, "id": "561a8441825441349a3b1ad23fdaea75", "industries": [ @@ -24,19 +25,20 @@ "largeThumbnail": null, "licenseInfo": "\n


", "listed": false, - "modified": 1508218106000, + "modified": 1526012760000, "name": "561a8441825441349a3b1ad23fdaea75.zip", - "numComments": 38, + "numComments": 66, "numRatings": 0, - "numViews": 156, + "numViews": 320, "owner": "appstudio_apps", "ownerFolder": null, "properties": null, "protected": false, "proxyFilter": null, + "scoreCompleteness": 65, "screenshots": [ ], - "size": 849343, + "size": 859238, "snippet": "Tile package creation tool.", "spatialReference": null, "tags": [ diff --git a/singletons/Config.qml b/singletons/Config.qml index 45ec20c..f6ec4fe 100644 --- a/singletons/Config.qml +++ b/singletons/Config.qml @@ -1,4 +1,4 @@ -/* Copyright 2016 Esri +/* Copyright 2018 Esri * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,6 +33,7 @@ QtObject { "tileItemBorderColor": "#eeeeee" } + property bool rtl: false property string mainButtonBackgroundColor: "#196fa6" //property string mainButtonBorderColor: "#007ac2" diff --git a/singletons/Constants.qml b/singletons/Constants.qml index d7bb90a..f6047c9 100644 --- a/singletons/Constants.qml +++ b/singletons/Constants.qml @@ -36,4 +36,10 @@ QtObject { readonly property string kDatabasePath: "~/ArcGIS/Data/Sql" readonly property string kDatabaseName: "tilepackagekreator.sqlite" + readonly property string kAllowAllZoomLevels: "allowAllZoomLevels" + readonly property string kAllowNonWebMercatorServices: "allowNonWebMercatorServices" + readonly property string kTimeOutUnresponsiveServices: "timeoutUnresponsiveServices" + readonly property string kTimeOutValue: "timeoutValue" + readonly property string kSearchQueryString: "searchQueryString" + readonly property string kIncludeCurrentUserInSearch: "includeCurrentUser" } diff --git a/singletons/Strings.qml b/singletons/Strings.qml index 761e1e8..c93d8cd 100644 --- a/singletons/Strings.qml +++ b/singletons/Strings.qml @@ -30,6 +30,7 @@ QtObject { readonly property string addTileService: qsTr("Add a tile service manually") readonly property string addTileServiceDesc: qsTr("This control will reveal an input form which the user can enter a url for a tile service to add to the list.") readonly property string alertMessageDesc: qsTr("This alert message provides information about where .pitem files are saved, or if there was an error.") + readonly property string allowNonWebMerctorServices: qsTr("Allow Non-Web Mercator Services
NOTE: Map may not display but export will still work.") readonly property string animatedSpinner: qsTr("animated spinner") readonly property string animatedSpinnerDesc: qsTr("This is an animated spinner that appears when network queries are in progress.") @@ -48,6 +49,7 @@ QtObject { readonly property string cancel: qsTr("Cancel") readonly property string cancelling: qsTr("Cancelling") readonly property string cancellingUpload: qsTr("Cancelling Upload.") + readonly property string clearAllData: qsTr("Clear all data") readonly property string contextMenuDesc: qsTr("Context menu for this service.") readonly property string checkingSpatialReference: qsTr("Checking Spatial Reference") readonly property string create: qsTr("Create") @@ -67,6 +69,7 @@ QtObject { readonly property string deleteBookmark: qsTr("Delete Bookmark") readonly property string deleteExtent: qsTr("Delete Extent") readonly property string deleteHistory: qsTr("Delete History") + readonly property string deleteTileService: qsTr("Delete tile service") readonly property string description: qsTr("Description") readonly property string descriptionCopyPaste: qsTr("Copy and paste description text here.") readonly property string descriptionCharCountDesc: qsTr("This text displays the number of charcters left available in the description text area.") @@ -85,6 +88,8 @@ QtObject { // E ----------------------------------------------------------------------- + readonly property string enableAllZoomLevels: qsTr("Enable zoom levels greater than 21.
NOTE: Exports often fail above level 21 regardless of area of interest.") + readonly property string enterASpecificFeature: qsTr("Enter a specific feature to use") readonly property string enterATitle: qsTr("Enter a title") readonly property string enterUrlForTileService: qsTr("Enter a url for a tile service.") readonly property string estimatedOutputSize: qsTr("Estimated Output Size") @@ -166,14 +171,20 @@ QtObject { // S ----------------------------------------------------------------------- readonly property string saveAsBookmark: qsTr("Save as bookmark") + readonly property string saveAsGeojson: qsTr("Save as geojson") readonly property string saveTo: qsTr("Save To") readonly property string saveToDesc: qsTr("This button will open a file dialog chooser that allows the user to select the folder to save the tile package to locally.") readonly property string saveToLocationDesc: qsTr("Selected save to location") readonly property string saveTpkLocally: qsTr("Save tile package locally") readonly property string searchAddressOrLatLon: qsTr("Search address or @lat,lon") readonly property string selectAnOperation: qsTr("Select an Operation") + readonly property string selectNextFeature: qsTr("Select next feature") + readonly property string selectPreviousFeature: qsTr("Select previous feature") readonly property string selectTileService: qsTr("Select tile service to be used as the source for the tile package") readonly property string selectTileServiceDesc: qsTr("This control will select the tile service to export tiles from and will transition to the export area and details selection view.") + readonly property string settings: qsTr("Settings") + readonly property string settingsDesc: qsTr("The settings view allows you to change various parameters used in the Tile Package Kreator") + readonly property string shapefileSuccessfullyImported: qsTr("Shapefile successfully read and converted to geojson.") readonly property string shareThisItemWith: qsTr("Share this item with:") readonly property string sharingItem: qsTr("Sharing item.") readonly property string signOut: qsTr("Sign out") @@ -186,10 +197,11 @@ QtObject { readonly property string tileServiceThumbnailDesc: qsTr("Tile service thumbnail image.") readonly property string tileServiceTitleDesc: qsTr("Title of the tile service.") readonly property string tileServiceUrlExample: qsTr("Enter url (e.g. http://someservice.gov/arcgis/rest/services/example/MapServer)") + readonly property string timeOutAfter: qsTr("Time out after:") + readonly property string timeOutNonResponsive: qsTr("Time out non-responsive services when querying available services.
Sometimes services go down or change. This will kill the request to those in the time set,
rather than waiting for the Network Request to time out, which could be up over 60 seconds.
") readonly property string title: qsTr("Title") readonly property string tpkFilesOnly: qsTr(".tpk files only please") - // U ----------------------------------------------------------------------- readonly property string updatesAvailable: qsTr("Updates Available") readonly property string upload: qsTr("Upload") @@ -249,4 +261,6 @@ QtObject { property string xUpdatesAvaliableDesc: qsTr("This button is enabled when there are updates available to the application. The action on this button will only work when the button is enabled via the application.") property string uploadedSeeX: qsTr("Uploaded. See Tile Package Item") property string uploadingAndSharedSeeX: qsTr("Uploaded and Shared. See Tile Package Item") + property string viewingFeatureXofX: qsTr("Viewing feature %1 of %2") + property string xSeconds: qsTr("%1 Seconds") }