def upgradeInstalledPlugins(): installer = pyplugin_installer.instance() initPluginManager(installer) errors = [] pluginsList = plugins.all().copy() for plugin in pluginsList: if isBoundlessPlugin(pluginsList[plugin]): if pluginsList[plugin]['installed'] and pluginsList[plugin]['status'] == 'upgradeable': dlg = QgsPluginInstallerInstallingDialog(iface.mainWindow(), plugins.all()[plugin]) dlg.exec_() if dlg.result(): errors.append(dlg.result()) else: updateAvailablePlugins() loadPlugin(plugins.all()[plugin]['id']) plugins.getAllInstalled(testLoad=True) plugins.rebuild() if not plugins.all()[plugin]["error"]: if startPlugin(plugins.all()[plugin]['id']): settings = QSettings() settings.setValue('/PythonPlugins/' + plugins.all()[plugin]['id'], True) installer.exportPluginsToManager() return errors
def addBoundlessRepository(): """Add Boundless plugin repository to list of the available plugin repositories if it is not presented here """ repoUrl = pluginSetting('repoUrl') if repoUrl == '': repoUrl = setRepositoryUrl() if isRepositoryInDirectory(): return settings = QSettings() settings.beginGroup(reposGroup) hasBoundlessRepository = False for repo in settings.childGroups(): url = settings.value(repo + '/url', '') if url == repoUrl: hasBoundlessRepository = True # Boundless repository not found, so we add it to the list if not hasBoundlessRepository: settings.setValue(boundlessRepoName + '/url', repoUrl) settings.setValue(boundlessRepoName + '/authcfg', '') settings.endGroup()
def installAllFromRepository(): """Install Boundless plugins from remote repository """ installer = pyplugin_installer.instance() initPluginManager(installer) errors = [] pluginsList = plugins.all().copy() for plugin in pluginsList: if isBoundlessPlugin(pluginsList[plugin]): if (pluginsList[plugin]['installed'] and pluginsList[plugin]['deprecated']) or \ not pluginsList[plugin]['deprecated'] and \ pluginsList[plugin]["zip_repository"] != '': dlg = QgsPluginInstallerInstallingDialog(iface.mainWindow(), plugins.all()[plugin]) dlg.exec_() if dlg.result(): errors.append(dlg.result()) else: updateAvailablePlugins() loadPlugin(plugins.all()[plugin]['id']) plugins.getAllInstalled(testLoad=True) plugins.rebuild() if not plugins.all()[plugin]["error"]: if startPlugin(plugins.all()[plugin]['id']): settings = QSettings() settings.setValue('/PythonPlugins/' + plugins.all()[plugin]['id'], True) installer.exportPluginsToManager() return errors
def selectFile(self): output = self.alg.parameterDefinition('OUTPUT') fileFilter = getFileFilter(output) settings = QgsSettings() if settings.contains('/Processing/LastOutputPath'): path = settings.value('/Processing/LastOutputPath') else: path = ProcessingConfig.getSetting(ProcessingConfig.OUTPUT_FOLDER) lastEncoding = settings.value('/Processing/encoding', 'System') fileDialog = QgsEncodingFileDialog(self, self.tr('Save file'), path, fileFilter, lastEncoding) fileDialog.setFileMode(QFileDialog.AnyFile) fileDialog.setAcceptMode(QFileDialog.AcceptSave) fileDialog.setOption(QFileDialog.DontConfirmOverwrite, False) if fileDialog.exec_() == QDialog.Accepted: files = fileDialog.selectedFiles() encoding = str(fileDialog.encoding()) output.encoding = encoding filename = str(files[0]) selectedFileFilter = str(fileDialog.selectedNameFilter()) if not filename.lower().endswith( tuple(re.findall("\\*(\\.[a-z]{1,10})", fileFilter))): ext = re.search("\\*(\\.[a-z]{1,10})", selectedFileFilter) if ext: filename = filename + ext.group(1) self.leOutputFile.setText(filename) settings.setValue('/Processing/LastOutputPath', os.path.dirname(filename)) settings.setValue('/Processing/encoding', encoding)
def execute(self): settings = QgsSettings() lastDir = settings.value('Processing/lastModelsDir', '') filename, selected_filter = QFileDialog.getOpenFileName(self.toolbox, self.tr('Open model', 'AddModelFromFileAction'), lastDir, self.tr('Processing model files (*.model *.MODEL)', 'AddModelFromFileAction')) if filename: try: settings.setValue('Processing/lastModelsDir', QFileInfo(filename).absoluteDir().absolutePath()) ModelerAlgorithm.fromFile(filename) except WrongModelException: QMessageBox.warning( self.toolbox, self.tr('Error reading model', 'AddModelFromFileAction'), self.tr('The selected file does not contain a valid model', 'AddModelFromFileAction')) return except: QMessageBox.warning(self.toolbox, self.tr('Error reading model', 'AddModelFromFileAction'), self.tr('Cannot read file', 'AddModelFromFileAction')) return destFilename = os.path.join(ModelerUtils.modelsFolders()[0], os.path.basename(filename)) shutil.copyfile(filename, destFilename) QgsApplication.processingRegistry().providerById('model').refreshAlgorithms()
def chooseOutputFile(self): # get last used dir settings = QgsSettings() lastUsedDir = settings.value(self.lastUsedVectorDirSettingsKey, ".") # get selected filter selectedFilter = self.cboFileFormat.currentData() # ask for a filename filename, filter = QFileDialog.getSaveFileName(self, self.tr("Choose where to save the file"), lastUsedDir, selectedFilter) if filename == "": return filterString = QgsVectorFileWriter.filterForDriver(selectedFilter) ext = filterString[filterString.find('.'):] ext = ext[:ext.find(' ')] if not filename.lower().endswith(ext): filename += ext # store the last used dir settings.setValue(self.lastUsedVectorDirSettingsKey, QFileInfo(filename).filePath()) self.editOutputFile.setText(filename)
def saveToGeopackage(self): file_filter = self.tr('GeoPackage files (*.gpkg);;All files (*.*)', 'OutputFile') settings = QgsSettings() if settings.contains('/Processing/LastOutputPath'): path = settings.value('/Processing/LastOutputPath') else: path = ProcessingConfig.getSetting(ProcessingConfig.OUTPUT_FOLDER) filename, filter = QFileDialog.getSaveFileName(self, self.tr("Save to GeoPackage"), path, file_filter, options=QFileDialog.DontConfirmOverwrite) if not filename: return layer_name, ok = QInputDialog.getText(self, self.tr('Save to GeoPackage'), self.tr('Layer name'), text=self.parameter.name().lower()) if ok: self.use_temporary = False if not filename.lower().endswith('.gpkg'): filename += '.gpkg' settings.setValue('/Processing/LastOutputPath', os.path.dirname(filename)) uri = QgsDataSourceUri() uri.setDatabase(filename) uri.setDataSource('', layer_name, 'geom' if isinstance(self.parameter, QgsProcessingParameterFeatureSink) and self.parameter.hasGeometry() else None) self.leText.setText("ogr:" + uri.uri()) self.skipOutputChanged.emit(False) self.destinationChanged.emit()
def updateSeenPluginsList(self): settings = QSettings() seenPlugins = settings.value(seenPluginGroup, list(self.plugins.keys()), str) for i in list(self.plugins.keys()): if seenPlugins.count(i) == 0: seenPlugins += [i] settings.setValue(seenPluginGroup, seenPlugins)
def execute(self): settings = QgsSettings() lastDir = settings.value('Processing/lastScriptsDir', '') filenames, selected_filter = QFileDialog.getOpenFileNames(self.toolbox, self.tr('Script files', 'AddScriptFromFileAction'), lastDir, self.tr('Script files (*.py *.PY)', 'AddScriptFromFileAction')) if filenames: validAlgs = 0 wrongAlgs = [] for filename in filenames: try: settings.setValue('Processing/lastScriptsDir', QFileInfo(filename).absoluteDir().absolutePath()) script = ScriptAlgorithm(filename) destFilename = os.path.join(ScriptUtils.scriptsFolders()[0], os.path.basename(filename)) with open(destFilename, 'w') as f: f.write(script.script) validAlgs += 1 except WrongScriptException: wrongAlgs.append(os.path.basename(filename)) if validAlgs: QgsApplication.processingRegistry().providerById('script').refreshAlgorithms() if wrongAlgs: QMessageBox.warning(self.toolbox, self.tr('Error reading scripts', 'AddScriptFromFileAction'), self.tr('The following files do not contain a valid script:\n-', 'AddScriptFromFileAction') + "\n-".join(wrongAlgs))
def showSelectionDialog(self): # Find the file dialog's working directory settings = QgsSettings() text = self.leText.text() if os.path.isdir(text): path = text elif os.path.isdir(os.path.dirname(text)): path = os.path.dirname(text) elif settings.contains('/Processing/LastInputPath'): path = settings.value('/Processing/LastInputPath') else: path = '' if self.isFolder: folder = QFileDialog.getExistingDirectory(self, self.tr('Select Folder'), path) if folder: self.leText.setText(folder) settings.setValue('/Processing/LastInputPath', os.path.dirname(folder)) else: filenames, selected_filter = QFileDialog.getOpenFileNames(self, self.tr('Select File'), path, self.tr('{} files').format(self.ext.upper()) + ' (*.' + self.ext + self.tr(');;All files (*.*)')) if filenames: self.leText.setText(u';'.join(filenames)) settings.setValue('/Processing/LastInputPath', os.path.dirname(filenames[0]))
def saveToSpatialite(self): fileFilter = self.tr('SpatiaLite files (*.sqlite)', 'OutputFile') settings = QgsSettings() if settings.contains('/Processing/LastOutputPath'): path = settings.value('/Processing/LastOutputPath') else: path = ProcessingConfig.getSetting(ProcessingConfig.OUTPUT_FOLDER) fileDialog = QgsEncodingFileDialog( self, self.tr('Save SpatiaLite'), path, fileFilter, self.encoding) fileDialog.setFileMode(QFileDialog.AnyFile) fileDialog.setAcceptMode(QFileDialog.AcceptSave) fileDialog.setOption(QFileDialog.DontConfirmOverwrite, True) if fileDialog.exec_() == QDialog.Accepted: self.use_temporary = False files = fileDialog.selectedFiles() self.encoding = str(fileDialog.encoding()) fileName = str(files[0]) selectedFileFilter = str(fileDialog.selectedNameFilter()) if not fileName.lower().endswith( tuple(re.findall("\\*(\\.[a-z]{1,10})", fileFilter))): ext = re.search("\\*(\\.[a-z]{1,10})", selectedFileFilter) if ext: fileName += ext.group(1) settings.setValue('/Processing/LastOutputPath', os.path.dirname(fileName)) settings.setValue('/Processing/encoding', self.encoding) uri = QgsDataSourceUri() uri.setDatabase(fileName) uri.setDataSource('', self.parameter.name().lower(), 'the_geom' if isinstance(self.parameter, QgsProcessingParameterFeatureSink) and self.parameter.hasGeometry() else None) self.leText.setText("spatialite:" + uri.uri())
def save(self, qsettings=None): if not qsettings: qsettings = QgsSettings() if self.valuetype == self.SELECTION: qsettings.setValue(self.qname, self.options.index(self.value)) else: qsettings.setValue(self.qname, self.value)
def reject(self): self.param = None settings = QgsSettings() settings.setValue("/Processing/modelParametersDefinitionDialogGeometry", self.saveGeometry()) QDialog.reject(self)
def showFileSelectionDialog(self): settings = QgsSettings() text = str(self.text.text()) if os.path.isdir(text): path = text elif os.path.isdir(os.path.dirname(text)): path = os.path.dirname(text) elif settings.contains('/Processing/LastInputPath'): path = str(settings.value('/Processing/LastInputPath')) else: path = '' ret, selected_filter = QFileDialog.getOpenFileNames(self, self.tr('Select Files'), path, getFileFilter(self.param)) if ret: files = list(ret) settings.setValue('/Processing/LastInputPath', os.path.dirname(str(files[0]))) for i, filename in enumerate(files): files[i] = dataobjects.getRasterSublayer(filename, self.param) if len(files) == 1: self.text.setText(files[0]) self.textEditingFinished() else: if isinstance(self.param, QgsProcessingParameterMultipleLayers): self.text.setText(';'.join(str(f) for f in files)) else: rowdif = len(files) - (self._table().rowCount() - self.row) for i in range(rowdif): self._panel().addRow() for i, f in enumerate(files): self._table().cellWidget(i + self.row, self.col).setValue(f)
def load(self): """ populate the mRepositories dict""" self.mRepositories = {} settings = QgsSettings() settings.beginGroup(reposGroup) # first, update repositories in QgsSettings if needed officialRepoPresent = False for key in settings.childGroups(): url = settings.value(key + "/url", "", type=str) if url == officialRepo[1]: officialRepoPresent = True if not officialRepoPresent: settings.setValue(officialRepo[0] + "/url", officialRepo[1]) for key in settings.childGroups(): self.mRepositories[key] = {} self.mRepositories[key]["url"] = settings.value(key + "/url", "", type=str) self.mRepositories[key]["authcfg"] = settings.value(key + "/authcfg", "", type=str) self.mRepositories[key]["enabled"] = settings.value(key + "/enabled", True, type=bool) self.mRepositories[key]["valid"] = settings.value(key + "/valid", True, type=bool) self.mRepositories[key]["Relay"] = Relay(key) self.mRepositories[key]["xmlData"] = None self.mRepositories[key]["state"] = 0 self.mRepositories[key]["error"] = "" settings.endGroup()
def showFileDialog(self, seldir): settings = QgsSettings() text = str(self.text.text()) if os.path.isdir(text): path = text elif not seldir and os.path.isdir(os.path.dirname(text)): path = os.path.dirname(text) elif settings.contains('/Processing/LastInputPath'): path = str(settings.value('/Processing/LastInputPath')) else: path = '' if not seldir: ret, selected_filter = QFileDialog.getOpenFileNames( self, self.tr('Select Files'), path, getFileFilter(self.param) ) else: ret = QFileDialog.getExistingDirectory(self, self.tr('Select Directory'), path) if ret: if seldir: settings.setValue('/Processing/LastInputPath', ret) files = [] for pp in Path(ret).rglob("*"): if not pp.is_file(): continue p = pp.as_posix() if ((isinstance(self.param, QgsProcessingParameterRasterLayer) or (isinstance(self.param, QgsProcessingParameterMultipleLayers) and self.param.layerType() == QgsProcessing.TypeRaster)) and not QgsRasterLayer.isValidRasterFileName(p)): continue files.append(p) if not files: return else: files = list(ret) settings.setValue('/Processing/LastInputPath', os.path.dirname(str(files[0]))) for i, filename in enumerate(files): files[i] = dataobjects.getRasterSublayer(filename, self.param) if len(files) == 1: self.text.setText(files[0]) self.textEditingFinished() else: if isinstance(self.param, QgsProcessingParameterMultipleLayers): self.text.setText(';'.join(str(f) for f in files)) else: rowdif = len(files) - (self._table().rowCount() - self.row) for i in range(rowdif): self._panel().addRow() for i, f in enumerate(files): self._table().cellWidget(i + self.row, self.col).setValue(f)
def installFromZipFile(self, filePath): if not os.path.isfile(filePath): return settings = QgsSettings() settings.setValue(settingsGroup + '/lastZipDirectory', QFileInfo(filePath).absoluteDir().absolutePath()) error = False infoString = None with zipfile.ZipFile(filePath, 'r') as zf: pluginName = os.path.split(zf.namelist()[0])[0] pluginFileName = os.path.splitext(os.path.basename(filePath))[0] pluginsDirectory = qgis.utils.home_plugin_path if not QDir(pluginsDirectory).exists(): QDir().mkpath(pluginsDirectory) # If the target directory already exists as a link, # remove the link without resolving QFile(os.path.join(pluginsDirectory, pluginFileName)).remove() try: # Test extraction. If fails, then exception will be raised # and no removing occurs unzip(str(filePath), str(pluginsDirectory)) # Removing old plugin files if exist removeDir(QDir.cleanPath(os.path.join(pluginsDirectory, pluginFileName))) # Extract new files unzip(str(filePath), str(pluginsDirectory)) except: error = True infoString = (self.tr("Plugin installation failed"), self.tr("Failed to unzip the plugin package\n{}.\nProbably it is broken".format(filePath))) if infoString is None: updateAvailablePlugins() loadPlugin(pluginName) plugins.getAllInstalled(testLoad=True) plugins.rebuild() if settings.contains('/PythonPlugins/' + pluginName): if settings.value('/PythonPlugins/' + pluginName, False, bool): startPlugin(pluginName) reloadPlugin(pluginName) else: unloadPlugin(pluginName) loadPlugin(pluginName) else: if startPlugin(pluginName): settings.setValue('/PythonPlugins/' + pluginName, True) infoString = (self.tr("Plugin installed successfully"), "") if infoString[0]: level = error and QgsMessageBar.CRITICAL or QgsMessageBar.INFO msg = "<b>%s:</b>%s" % (infoString[0], infoString[1]) iface.pluginManagerInterface().pushMessage(msg, level)
def loadAPIFile(self): settings = QgsSettings() lastDirPath = settings.value("pythonConsole/lastDirAPIPath", "", type=str) fileAPI, selected_filter = QFileDialog.getOpenFileName( self, "Open API File", lastDirPath, "API file (*.api)") if fileAPI: self.addAPI(fileAPI) settings.setValue("pythonConsole/lastDirAPIPath", fileAPI)
def selectEncoding(self): dialog = QgsEncodingSelectionDialog( self, self.tr('File encoding'), self.encoding) if dialog.exec_() == QDialog.Accepted: self.encoding = dialog.encoding() settings = QgsSettings() settings.setValue('/Processing/encoding', self.encoding) dialog.deleteLater()
def updateSeenPluginsList(self): """ update the list of all seen plugins """ settings = QgsSettings() seenPlugins = settings.value(settingsGroup + '/seen_plugins', list(self.mPlugins.keys()), type=str) for i in list(self.mPlugins.keys()): if seenPlugins.count(i) == 0: seenPlugins += [i] settings.setValue(settingsGroup + '/seen_plugins', seenPlugins)
def closeEvent(self, e): self.unregisterAllActions() # clear preview, this will delete the layer in preview tab self.preview.loadPreview(None) # save the window state settings = QgsSettings() settings.setValue("/DB_Manager/mainWindow/windowState", self.saveState()) settings.setValue("/DB_Manager/mainWindow/geometry", self.saveGeometry()) QMainWindow.closeEvent(self, e)
def checkFirstRun(self): settings = QSettings() firstRun = settings.value('boundlessconnect/firstRun', True, bool) settings.setValue('boundlessconnect/firstRun', False) if self.dockWidget is None: self.dockWidget = getConnectDockWidget() if firstRun: self.dockWidget.show() utils.installFromStandardPath()
def writeQueryHistory(self, sql, affectedRows, secs): if len(self.history[self.connectionName]) >= self.QUERY_HISTORY_LIMIT: self.history[self.connectionName].pop(0) settings = QgsSettings() self.history[self.connectionName].append({'query': sql, 'rows': affectedRows, 'secs': secs}) settings.setValue('DB_Manager/queryHistory/' + self.dbType, self.history) self.populateQueryHistory()
def processAlgorithm(self, feedback): settings = QgsSettings() initial_method_setting = settings.value(settings_method_key, 1) method = self.getParameterValue(self.METHOD) if method != 0: settings.setValue(settings_method_key, method) try: self.doCheck(feedback) finally: settings.setValue(settings_method_key, initial_method_setting)
def selectDirectory(self): lastDir = self.leText.text() settings = QgsSettings() if not lastDir: lastDir = settings.value("/Processing/LastOutputPath", QDir.homePath()) dirName = QFileDialog.getExistingDirectory(self, self.tr('Select directory'), lastDir, QFileDialog.ShowDirsOnly) if dirName: self.leText.setText(QDir.toNativeSeparators(dirName)) settings.setValue('/Processing/LastOutputPath', dirName)
def execute(self): settings = QgsSettings() lastDir = settings.value('Processing/lastScriptsDir', '') filename, selected_filter = QFileDialog.getOpenFileName(self.toolbox, self.tr('Open Script', 'AddScriptFromFileAction'), lastDir, self.tr('Script files (*.py)', 'AddScriptFromFileAction')) if filename: settings.setValue('Processing/lastScriptsDir', QFileInfo(filename).absoluteDir().absolutePath()) dlg = ScriptEditorDialog(filePath=filename) dlg.show()
def setRepositoryAuth(authConfigId): """Add auth to the repository """ repoUrl = pluginSetting('repoUrl') settings = QSettings() settings.beginGroup(reposGroup) for repo in settings.childGroups(): url = settings.value(repo + '/url', '') if url == repoUrl: settings.setValue(repo + '/authcfg', authConfigId) settings.endGroup()
def requestFinished(self): QApplication.restoreOverrideCursor() reply = self.sender() visible = True if reply.error() != QNetworkReply.NoError: if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) == 401: msg = 'Your credentials seem invalid.\n' \ 'You will not be able to access any content.\n' \ 'Please enter valid Connect credentials to use plugin.' else: msg = 'An error occurred when validating your ' \ 'credentials. Server responded:\n{}.\n' \ 'You will not be able to access any content.\n' \ 'Please enter valid Connect credentials to use plugin'.format(reply.errorString()) QMessageBox.warning(self, 'Error!', msg) return else: self.btnSignOut.setText("Logout") self.saveOrUpdateAuthId() self.roles = json.loads(str(reply.readAll())) # if this is first login ask if user wants to have basemap settings = QSettings() firstLogin = settings.value('boundlessconnect/firstLogin', True, bool) if firstLogin: settings.setValue('boundlessconnect/firstLogin', False) if oauth2_supported() and basemaputils.canAccessBasemap(self.roles): ret = QMessageBox.question(self, self.tr('Base Maps'), self.tr('Would you like to add Boundless basemap ' 'to your default project? This option can ' 'be disabled at any time in the settings.'), QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if ret == QMessageBox.Yes: if self.token is None: self._showMessage("Seems you have no Connect token. Login with valid Connect credentials and try again.", QgsMessageBar.WARNING) return if self.installBaseMap(): pass execute(connect.loadPlugins) self.stackedWidget.setCurrentIndex(1) self.labelLevel.setVisible(visible) self.labelLevel.setText("Logged in as: <b>%s</b>" % self.connectWidget.login()) self.loggedIn = True cat = ",".join(list(connect.categories.keys())) self._findContent(cat)
def execute(self): settings = QgsSettings() lastDir = settings.value('Processing/lastModelsDir', '') filename, selected_filter = QFileDialog.getOpenFileName(self.toolbox, self.tr('Open Model', 'AddModelFromFileAction'), lastDir, self.tr('Processing models (*.model3 *.MODEL3)', 'AddModelFromFileAction')) if filename: settings.setValue('Processing/lastModelsDir', QFileInfo(filename).absoluteDir().absolutePath()) dlg = ModelerDialog() dlg.loadModel(filename) dlg.show()
def selectDirectory(self): settings = QgsSettings() if settings.contains('/Processing/LastBatchOutputPath'): lastDir = str(settings.value('/Processing/LastBatchOutputPath')) else: lastDir = '' dirName = QFileDialog.getExistingDirectory(self, self.tr('Output Directory'), lastDir, QFileDialog.ShowDirsOnly) if dirName: self.table.cellWidget(self.row, self.col).setValue(dirName) settings.setValue('/Processing/LastBatchOutputPath', dirName)
class MultipleInputDialog(BASE, WIDGET): def __init__(self, options, selectedoptions=None, datatype=None): super(MultipleInputDialog, self).__init__(None) self.setupUi(self) self.datatype = datatype self.model = None self.options = [] for i, option in enumerate(options): if option is None or isinstance(option, str): self.options.append((i, option)) else: self.options.append((option[0], option[1])) self.selectedoptions = selectedoptions or [] # Additional buttons self.btnSelectAll = QPushButton(self.tr('Select All')) self.buttonBox.addButton(self.btnSelectAll, QDialogButtonBox.ActionRole) self.btnClearSelection = QPushButton(self.tr('Clear Selection')) self.buttonBox.addButton(self.btnClearSelection, QDialogButtonBox.ActionRole) self.btnToggleSelection = QPushButton(self.tr('Toggle Selection')) self.buttonBox.addButton(self.btnToggleSelection, QDialogButtonBox.ActionRole) if self.datatype is not None: btnAddFile = QPushButton( QCoreApplication.translate("MultipleInputDialog", 'Add File(s)…')) btnAddFile.clicked.connect(self.addFiles) self.buttonBox.addButton(btnAddFile, QDialogButtonBox.ActionRole) self.btnSelectAll.clicked.connect(lambda: self.selectAll(True)) self.btnClearSelection.clicked.connect(lambda: self.selectAll(False)) self.btnToggleSelection.clicked.connect(self.toggleSelection) self.settings = QgsSettings() self.restoreGeometry( self.settings.value("/Processing/multipleInputDialogGeometry", QByteArray())) self.lstLayers.setSelectionMode(QAbstractItemView.ExtendedSelection) self.lstLayers.setDragDropMode(QAbstractItemView.InternalMove) self.populateList() self.finished.connect(self.saveWindowGeometry) def saveWindowGeometry(self): self.settings.setValue("/Processing/multipleInputDialogGeometry", self.saveGeometry()) def populateList(self): self.model = QStandardItemModel() for value, text in self.options: item = QStandardItem(text) item.setData(value, Qt.UserRole) item.setCheckState(Qt.Checked if value in self.selectedoptions else Qt.Unchecked) item.setCheckable(True) item.setDropEnabled(False) self.model.appendRow(item) # add extra options (e.g. manually added layers) for t in [o for o in self.selectedoptions if not isinstance(o, int)]: if isinstance(t, QgsProcessingModelChildParameterSource): item = QStandardItem(t.staticValue()) else: item = QStandardItem(t) item.setData(item.text(), Qt.UserRole) item.setCheckState(Qt.Checked) item.setCheckable(True) item.setDropEnabled(False) self.model.appendRow(item) self.lstLayers.setModel(self.model) def accept(self): self.selectedoptions = [] model = self.lstLayers.model() for i in range(model.rowCount()): item = model.item(i) if item.checkState() == Qt.Checked: self.selectedoptions.append(item.data(Qt.UserRole)) QDialog.accept(self) def reject(self): self.selectedoptions = None QDialog.reject(self) def getItemsToModify(self): items = [] if len(self.lstLayers.selectedIndexes()) > 1: for i in self.lstLayers.selectedIndexes(): items.append(self.model.itemFromIndex(i)) else: for i in range(self.model.rowCount()): items.append(self.model.item(i)) return items def selectAll(self, value): for item in self.getItemsToModify(): item.setCheckState(Qt.Checked if value else Qt.Unchecked) def toggleSelection(self): for item in self.getItemsToModify(): checked = item.checkState() == Qt.Checked item.setCheckState(Qt.Unchecked if checked else Qt.Checked) def getFileFilter(self, datatype): """ Returns a suitable file filter pattern for the specified parameter definition :param param: :return: """ if datatype == QgsProcessing.TypeRaster: return QgsProviderRegistry.instance().fileRasterFilters() elif datatype == QgsProcessing.TypeFile: return self.tr('All files (*.*)') else: exts = QgsVectorFileWriter.supportedFormatExtensions() for i in range(len(exts)): exts[i] = self.tr('{0} files (*.{1})').format( exts[i].upper(), exts[i].lower()) return self.tr('All files (*.*)') + ';;' + ';;'.join(exts) def addFiles(self): filter = self.getFileFilter(self.datatype) settings = QgsSettings() path = str(settings.value('/Processing/LastInputPath')) ret, selected_filter = QFileDialog.getOpenFileNames( self, self.tr('Select File(s)'), path, filter) if ret: files = list(ret) settings.setValue('/Processing/LastInputPath', os.path.dirname(str(files[0]))) for filename in files: item = QStandardItem(filename) item.setData(filename, Qt.UserRole) item.setCheckState(Qt.Checked) item.setCheckable(True) item.setDropEnabled(False) self.model.appendRow(item)
class AlgorithmDialogBase(BASE, WIDGET): def __init__(self, alg): super(AlgorithmDialogBase, self).__init__(iface.mainWindow() if iface else None) self.setupUi(self) # don't collapse parameters panel self.splitter.setCollapsible(0, False) # add collapse button to splitter splitterHandle = self.splitter.handle(1) handleLayout = QVBoxLayout() handleLayout.setContentsMargins(0, 0, 0, 0) self.btnCollapse = QToolButton(splitterHandle) self.btnCollapse.setAutoRaise(True) self.btnCollapse.setFixedSize(12, 12) self.btnCollapse.setCursor(Qt.ArrowCursor) handleLayout.addWidget(self.btnCollapse) handleLayout.addStretch() splitterHandle.setLayout(handleLayout) self.settings = QgsSettings() self.splitter.restoreState( self.settings.value("/Processing/dialogBaseSplitter", QByteArray())) self.restoreGeometry( self.settings.value("/Processing/dialogBase", QByteArray())) self.splitterState = self.splitter.saveState() self.splitterChanged(0, 0) self.executed = False self.mainWidget = None self.alg = alg self.setWindowTitle(self.alg.displayName()) self.buttonBox.rejected.connect(self.reject) self.buttonBox.accepted.connect(self.accept) # Rename OK button to Run self.btnRun = self.buttonBox.button(QDialogButtonBox.Ok) self.btnRun.setText(self.tr('Run')) self.buttonCancel.setEnabled(False) self.btnClose = self.buttonBox.button(QDialogButtonBox.Close) self.buttonBox.helpRequested.connect(self.openHelp) self.btnCollapse.clicked.connect(self.toggleCollapsed) self.splitter.splitterMoved.connect(self.splitterChanged) # desktop = QDesktopWidget() # if desktop.physicalDpiX() > 96: # self.txtHelp.setZoomFactor(desktop.physicalDpiX() / 96) algHelp = self.formatHelp(self.alg) if algHelp is None: self.textShortHelp.hide() else: self.textShortHelp.document().setDefaultStyleSheet( '''.summary { margin-left: 10px; margin-right: 10px; } h2 { color: #555555; padding-bottom: 15px; } a { text-decoration: none; color: #3498db; font-weight: bold; } p { color: #666666; } b { color: #333333; } dl dd { margin-bottom: 5px; }''' ) self.textShortHelp.setHtml(algHelp) def linkClicked(url): webbrowser.open(url.toString()) self.textShortHelp.anchorClicked.connect(linkClicked) self.showDebug = ProcessingConfig.getSetting( ProcessingConfig.SHOW_DEBUG_IN_DIALOG) def createFeedback(self): feedback = AlgorithmDialogFeedback(self) feedback.progressChanged.connect(self.setPercentage) feedback.error.connect(self.error) feedback.progress_text.connect(self.setText) feedback.info.connect(self.setInfo) feedback.command_info.connect(self.setCommand) feedback.debug_info.connect(self.setDebugInfo) feedback.console_info.connect(self.setConsoleInfo) self.buttonCancel.clicked.connect(feedback.cancel) return feedback def formatHelp(self, alg): text = alg.shortHelpString() if not text: return None return "<h2>%s</h2>%s" % (alg.displayName(), "".join( ["<p>%s</p>" % s for s in text.split("\n")])) def closeEvent(self, event): self._saveGeometry() super(AlgorithmDialogBase, self).closeEvent(event) def setMainWidget(self, widget): if self.mainWidget is not None: QgsProject.instance().layerWasAdded.disconnect( self.mainWidget.layerRegistryChanged) QgsProject.instance().layersWillBeRemoved.disconnect( self.mainWidget.layerRegistryChanged) self.mainWidget = widget self.tabWidget.widget(0).layout().addWidget(self.mainWidget) QgsProject.instance().layerWasAdded.connect( self.mainWidget.layerRegistryChanged) QgsProject.instance().layersWillBeRemoved.connect( self.mainWidget.layerRegistryChanged) def error(self, msg): self.setInfo(msg, True) self.resetGUI() self.tabWidget.setCurrentIndex(1) def resetGUI(self): self.lblProgress.setText('') self.progressBar.setMaximum(100) self.progressBar.setValue(0) self.btnRun.setEnabled(True) self.btnClose.setEnabled(True) def setInfo(self, msg, error=False, escape_html=True): if error: self.txtLog.append( '<span style="color:red">{}</span><br />'.format(msg, quote=False)) elif escape_html: self.txtLog.append(html.escape(msg)) else: self.txtLog.append(msg) def setCommand(self, cmd): if self.showDebug: self.txtLog.append('<code>{}<code>'.format( html.escape(cmd, quote=False))) def setDebugInfo(self, msg): if self.showDebug: self.txtLog.append('<span style="color:blue">{}</span>'.format( html.escape(msg, quote=False))) def setConsoleInfo(self, msg): if self.showDebug: self.txtLog.append( '<code><span style="color:darkgray">{}</span></code>'.format( html.escape(msg, quote=False))) def setPercentage(self, value): if self.progressBar.maximum() == 0: self.progressBar.setMaximum(100) self.progressBar.setValue(value) def setText(self, text): self.lblProgress.setText(text) self.setInfo(text, False) def getParamValues(self): return {} def accept(self): pass def reject(self): self._saveGeometry() super(AlgorithmDialogBase, self).reject() def finish(self, successful, result, context, feedback): pass def toggleCollapsed(self): if self.helpCollapsed: self.splitter.restoreState(self.splitterState) self.btnCollapse.setArrowType(Qt.RightArrow) else: self.splitterState = self.splitter.saveState() self.splitter.setSizes([1, 0]) self.btnCollapse.setArrowType(Qt.LeftArrow) self.helpCollapsed = not self.helpCollapsed def splitterChanged(self, pos, index): if self.splitter.sizes()[1] == 0: self.helpCollapsed = True self.btnCollapse.setArrowType(Qt.LeftArrow) else: self.helpCollapsed = False self.btnCollapse.setArrowType(Qt.RightArrow) def openHelp(self): algHelp = self.alg.helpUrl() if not algHelp: algHelp = QgsHelp.helpUrl("processing_algs/{}/{}".format( self.alg.provider().id(), self.alg.id())).toString() if algHelp not in [None, ""]: webbrowser.open(algHelp) def _saveGeometry(self): self.settings.setValue("/Processing/dialogBaseSplitter", self.splitter.saveState()) self.settings.setValue("/Processing/dialogBase", self.saveGeometry()) class InvalidParameterValue(Exception): def __init__(self, param, widget): (self.parameter, self.widget) = (param, widget)
def installFromZipFile(self, filePath): if not os.path.isfile(filePath): return settings = QgsSettings() settings.setValue(settingsGroup + '/lastZipDirectory', QFileInfo(filePath).absoluteDir().absolutePath()) error = False infoString = None with zipfile.ZipFile(filePath, 'r') as zf: pluginName = os.path.split(zf.namelist()[0])[0] pluginFileName = os.path.splitext(os.path.basename(filePath))[0] pluginsDirectory = qgis.utils.home_plugin_path if not QDir(pluginsDirectory).exists(): QDir().mkpath(pluginsDirectory) # If the target directory already exists as a link, # remove the link without resolving QFile(os.path.join(pluginsDirectory, pluginFileName)).remove() try: # Test extraction. If fails, then exception will be raised # and no removing occurs unzip(str(filePath), str(pluginsDirectory)) # Removing old plugin files if exist removeDir( QDir.cleanPath(os.path.join(pluginsDirectory, pluginFileName))) # Extract new files unzip(str(filePath), str(pluginsDirectory)) except: error = True infoString = ( self.tr("Plugin installation failed"), self. tr("Failed to unzip the plugin package\n{}.\nProbably it is broken" .format(filePath))) if infoString is None: updateAvailablePlugins() loadPlugin(pluginName) plugins.getAllInstalled() plugins.rebuild() self.exportPluginsToManager() if settings.contains('/PythonPlugins/' + pluginName): if settings.value('/PythonPlugins/' + pluginName, False, bool): startPlugin(pluginName) reloadPlugin(pluginName) else: unloadPlugin(pluginName) loadPlugin(pluginName) else: if startPlugin(pluginName): settings.setValue('/PythonPlugins/' + pluginName, True) infoString = (self.tr("Plugin installed successfully"), "") if infoString[0]: level = error and QgsMessageBar.CRITICAL or QgsMessageBar.INFO msg = "<b>%s</b>" % infoString[0] if infoString[1]: msg += "<b>:</b> %s" % infoString[1] iface.pluginManagerInterface().pushMessage(msg, level)
class AlgorithmDialogBase(BASE, WIDGET): def __init__(self, alg): super(AlgorithmDialogBase, self).__init__(iface.mainWindow()) self.setupUi(self) self.feedback = AlgorithmDialogFeedback(self) self.feedback.progressChanged.connect(self.setPercentage) self.settings = QgsSettings() self.restoreGeometry( self.settings.value("/Processing/dialogBase", QByteArray())) self.executed = False self.mainWidget = None self.alg = alg # Rename OK button to Run self.btnRun = self.buttonBox.button(QDialogButtonBox.Ok) self.btnRun.setText(self.tr('Run')) self.btnClose = self.buttonBox.button(QDialogButtonBox.Close) self.setWindowTitle(self.alg.displayName()) # desktop = QDesktopWidget() # if desktop.physicalDpiX() > 96: # self.txtHelp.setZoomFactor(desktop.physicalDpiX() / 96) algHelp = self.alg.shortHelp() if algHelp is None: self.textShortHelp.setVisible(False) else: self.textShortHelp.document().setDefaultStyleSheet( '''.summary { margin-left: 10px; margin-right: 10px; } h2 { color: #555555; padding-bottom: 15px; } a { text-decoration: none; color: #3498db; font-weight: bold; } p { color: #666666; } b { color: #333333; } dl dd { margin-bottom: 5px; }''' ) self.textShortHelp.setHtml(algHelp) self.textShortHelp.setOpenLinks(False) def linkClicked(url): webbrowser.open(url.toString()) self.textShortHelp.anchorClicked.connect(linkClicked) isText, algHelp = self.alg.help() if algHelp is not None: algHelp = algHelp if isText else QUrl(algHelp) try: if isText: self.txtHelp.setHtml(algHelp) else: html = self.tr( '<p>Downloading algorithm help... Please wait.</p>') self.txtHelp.setHtml(html) rq = QNetworkRequest(algHelp) self.reply = QgsNetworkAccessManager.instance().get(rq) self.reply.finished.connect(self.requestFinished) except Exception: self.tabWidget.removeTab(2) else: self.tabWidget.removeTab(2) self.showDebug = ProcessingConfig.getSetting( ProcessingConfig.SHOW_DEBUG_IN_DIALOG) def requestFinished(self): """Change the webview HTML content""" reply = self.sender() if reply.error() != QNetworkReply.NoError: html = self.tr( '<h2>No help available for this algorithm</h2><p>{}</p>'. format(reply.errorString())) else: html = str(reply.readAll()) reply.deleteLater() self.txtHelp.setHtml(html) def closeEvent(self, evt): self.settings.setValue("/Processing/dialogBase", self.saveGeometry()) super(AlgorithmDialogBase, self).closeEvent(evt) def setMainWidget(self, widget): if self.mainWidget is not None: QgsProject.instance().layerWasAdded.disconnect( self.mainWidget.layerRegistryChanged) QgsProject.instance().layersWillBeRemoved.disconnect( self.mainWidget.layerRegistryChanged) self.mainWidget = widget self.tabWidget.widget(0).layout().addWidget(self.mainWidget) QgsProject.instance().layerWasAdded.connect( self.mainWidget.layerRegistryChanged) QgsProject.instance().layersWillBeRemoved.connect( self.mainWidget.layerRegistryChanged) def error(self, msg): QApplication.restoreOverrideCursor() self.setInfo(msg, True) self.resetGUI() self.tabWidget.setCurrentIndex(1) def resetGUI(self): QApplication.restoreOverrideCursor() self.lblProgress.setText('') self.progressBar.setMaximum(100) self.progressBar.setValue(0) self.btnRun.setEnabled(True) self.btnClose.setEnabled(True) def setInfo(self, msg, error=False): if error: self.txtLog.append('<span style="color:red"><br>%s<br></span>' % msg) else: self.txtLog.append(msg) QCoreApplication.processEvents() def setCommand(self, cmd): if self.showDebug: self.setInfo('<code>%s<code>' % cmd) QCoreApplication.processEvents() def setDebugInfo(self, msg): if self.showDebug: self.setInfo('<span style="color:blue">%s</span>' % msg) QCoreApplication.processEvents() def setConsoleInfo(self, msg): if self.showDebug: self.setCommand('<span style="color:darkgray">%s</span>' % msg) QCoreApplication.processEvents() def setPercentage(self, value): if self.progressBar.maximum() == 0: self.progressBar.setMaximum(100) self.progressBar.setValue(value) QCoreApplication.processEvents() def setText(self, text): self.lblProgress.setText(text) self.setInfo(text, False) QCoreApplication.processEvents() def setParamValues(self): pass def setParamValue(self, param, widget, alg=None): pass def accept(self): pass def finish(self): pass class InvalidParameterValue(Exception): def __init__(self, param, widget): (self.parameter, self.widget) = (param, widget)
def accept(self): description = self.nameTextBox.text() if description.strip() == '': QMessageBox.warning(self, self.tr('Unable to define parameter'), self.tr('Invalid parameter name')) return if self.param is None: validChars = \ 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' safeName = ''.join(c for c in description if c in validChars) name = safeName.lower() i = 2 while self.alg.parameterDefinition(name): name = safeName.lower() + str(i) i += 1 else: name = self.param.name() if (self.paramType == parameters.PARAMETER_BOOLEAN or isinstance(self.param, QgsProcessingParameterBoolean)): self.param = QgsProcessingParameterBoolean(name, description, self.state.isChecked()) elif (self.paramType == parameters.PARAMETER_TABLE_FIELD or isinstance(self.param, QgsProcessingParameterField)): if self.parentCombo.currentIndex() < 0: QMessageBox.warning(self, self.tr('Unable to define parameter'), self.tr('Wrong or missing parameter values')) return parent = self.parentCombo.currentData() datatype = self.datatypeCombo.currentData() default = self.defaultTextBox.text() if not default: default = None self.param = QgsProcessingParameterField(name, description, defaultValue=default, parentLayerParameterName=parent, type=datatype, allowMultiple=self.multipleCheck.isChecked()) elif (self.paramType == parameters.PARAMETER_BAND or isinstance(self.param, QgsProcessingParameterBand)): if self.parentCombo.currentIndex() < 0: QMessageBox.warning(self, self.tr('Unable to define parameter'), self.tr('Wrong or missing parameter values')) return parent = self.parentCombo.currentData() self.param = QgsProcessingParameterBand(name, description, None, parent) elif (self.paramType == parameters.PARAMETER_MAP_LAYER or isinstance(self.param, QgsProcessingParameterMapLayer)): self.param = QgsProcessingParameterMapLayer( name, description) elif (self.paramType == parameters.PARAMETER_RASTER or isinstance(self.param, QgsProcessingParameterRasterLayer)): self.param = QgsProcessingParameterRasterLayer( name, description) elif (self.paramType == parameters.PARAMETER_TABLE or isinstance(self.param, QgsProcessingParameterVectorLayer)): self.param = QgsProcessingParameterVectorLayer( name, description, [self.shapetypeCombo.currentData()]) elif (self.paramType == parameters.PARAMETER_VECTOR or isinstance(self.param, QgsProcessingParameterFeatureSource)): self.param = QgsProcessingParameterFeatureSource( name, description, [self.shapetypeCombo.currentData()]) elif (self.paramType == parameters.PARAMETER_MULTIPLE or isinstance(self.param, QgsProcessingParameterMultipleLayers)): self.param = QgsProcessingParameterMultipleLayers( name, description, self.datatypeCombo.currentData()) elif (self.paramType == parameters.PARAMETER_NUMBER or isinstance(self.param, (QgsProcessingParameterNumber, QgsProcessingParameterDistance))): try: self.param = QgsProcessingParameterNumber(name, description, QgsProcessingParameterNumber.Double, self.defaultTextBox.text()) vmin = self.minTextBox.text().strip() if not vmin == '': self.param.setMinimum(float(vmin)) vmax = self.maxTextBox.text().strip() if not vmax == '': self.param.setMaximum(float(vmax)) except: QMessageBox.warning(self, self.tr('Unable to define parameter'), self.tr('Wrong or missing parameter values')) return elif (self.paramType == parameters.PARAMETER_EXPRESSION or isinstance(self.param, QgsProcessingParameterExpression)): parent = self.parentCombo.currentData() self.param = QgsProcessingParameterExpression(name, description, str(self.defaultEdit.expression()), parent) elif (self.paramType == parameters.PARAMETER_STRING or isinstance(self.param, QgsProcessingParameterString)): self.param = QgsProcessingParameterString(name, description, str(self.defaultTextBox.text())) elif (self.paramType == parameters.PARAMETER_EXTENT or isinstance(self.param, QgsProcessingParameterExtent)): self.param = QgsProcessingParameterExtent(name, description) elif (self.paramType == parameters.PARAMETER_FILE or isinstance(self.param, QgsProcessingParameterFile)): isFolder = self.fileFolderCombo.currentIndex() == 1 self.param = QgsProcessingParameterFile(name, description, QgsProcessingParameterFile.Folder if isFolder else QgsProcessingParameterFile.File) elif (self.paramType == parameters.PARAMETER_POINT or isinstance(self.param, QgsProcessingParameterPoint)): self.param = QgsProcessingParameterPoint(name, description, str(self.defaultTextBox.text())) elif (self.paramType == parameters.PARAMETER_CRS or isinstance(self.param, QgsProcessingParameterCrs)): self.param = QgsProcessingParameterCrs(name, description, self.selector.crs().authid()) elif (self.paramType == parameters.PARAMETER_ENUM or isinstance(self.param, QgsProcessingParameterEnum)): self.param = QgsProcessingParameterEnum(name, description, self.widget.options(), self.widget.allowMultiple(), self.widget.defaultOptions()) elif (self.paramType == parameters.PARAMETER_MATRIX or isinstance(self.param, QgsProcessingParameterMatrix)): self.param = QgsProcessingParameterMatrix(name, description, hasFixedNumberRows=self.widget.fixedRows(), headers=self.widget.headers(), defaultValue=self.widget.value()) # Destination parameter elif (isinstance(self.param, QgsProcessingParameterFeatureSink)): self.param = QgsProcessingParameterFeatureSink( name=name, description=self.param.description(), type=self.param.dataType(), defaultValue=self.defaultWidget.getValue()) elif (isinstance(self.param, QgsProcessingParameterFileDestination)): self.param = QgsProcessingParameterFileDestination( name=name, description=self.param.description(), fileFilter=self.param.fileFilter(), defaultValue=self.defaultWidget.getValue()) elif (isinstance(self.param, QgsProcessingParameterFolderDestination)): self.param = QgsProcessingParameterFolderDestination( name=name, description=self.param.description(), defaultValue=self.defaultWidget.getValue()) elif (isinstance(self.param, QgsProcessingParameterRasterDestination)): self.param = QgsProcessingParameterRasterDestination( name=name, description=self.param.description(), defaultValue=self.defaultWidget.getValue()) elif (isinstance(self.param, QgsProcessingParameterVectorDestination)): self.param = QgsProcessingParameterVectorDestination( name=name, description=self.param.description(), type=self.param.dataType(), defaultValue=self.defaultWidget.getValue()) else: if self.paramType: typeId = self.paramType else: typeId = self.param.type() paramTypeDef = QgsApplication.instance().processingRegistry().parameterType(typeId) if not paramTypeDef: msg = self.tr('The parameter `{}` is not registered, are you missing a required plugin?'.format(typeId)) raise UndefinedParameterException(msg) self.param = paramTypeDef.create(name) self.param.setDescription(description) self.param.setMetadata(paramTypeDef.metadata()) if not self.requiredCheck.isChecked(): self.param.setFlags(self.param.flags() | QgsProcessingParameterDefinition.FlagOptional) else: self.param.setFlags(self.param.flags() & ~QgsProcessingParameterDefinition.FlagOptional) settings = QgsSettings() settings.setValue("/Processing/modelParametersDefinitionDialogGeometry", self.saveGeometry()) QDialog.accept(self)
def accept(self): description = str(self.nameTextBox.text()) if description.strip() == '': QMessageBox.warning(self, self.tr('Unable to define parameter'), self.tr('Invalid parameter name')) return if self.param is None: validChars = \ 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' safeName = ''.join(c for c in description if c in validChars) name = safeName.lower() i = 2 while self.alg.parameterDefinition(name): name = safeName.lower() + str(i) i += 1 else: name = self.param.name() if (self.paramType == parameters.PARAMETER_BOOLEAN or isinstance(self.param, QgsProcessingParameterBoolean)): self.param = QgsProcessingParameterBoolean(name, description, self.state.isChecked()) elif (self.paramType == parameters.PARAMETER_TABLE_FIELD or isinstance(self.param, QgsProcessingParameterField)): if self.parentCombo.currentIndex() < 0: QMessageBox.warning( self, self.tr('Unable to define parameter'), self.tr('Wrong or missing parameter values')) return parent = self.parentCombo.currentData() datatype = self.datatypeCombo.currentData() default = self.defaultTextBox.text() if not default: default = None self.param = QgsProcessingParameterField( name, description, defaultValue=default, parentLayerParameterName=parent, type=datatype, allowMultiple=self.multipleCheck.isChecked()) elif (self.paramType == parameters.PARAMETER_BAND or isinstance(self.param, QgsProcessingParameterBand)): if self.parentCombo.currentIndex() < 0: QMessageBox.warning( self, self.tr('Unable to define parameter'), self.tr('Wrong or missing parameter values')) return parent = self.parentCombo.currentData() self.param = QgsProcessingParameterBand(name, description, None, parent) elif (self.paramType == parameters.PARAMETER_MAP_LAYER or isinstance(self.param, QgsProcessingParameterMapLayer)): self.param = QgsProcessingParameterMapLayer(name, description) elif (self.paramType == parameters.PARAMETER_RASTER or isinstance(self.param, QgsProcessingParameterRasterLayer)): self.param = QgsProcessingParameterRasterLayer(name, description) elif (self.paramType == parameters.PARAMETER_TABLE or isinstance(self.param, QgsProcessingParameterVectorLayer)): self.param = QgsProcessingParameterVectorLayer( name, description, [self.shapetypeCombo.currentData()]) elif (self.paramType == parameters.PARAMETER_VECTOR or isinstance(self.param, QgsProcessingParameterFeatureSource)): self.param = QgsProcessingParameterFeatureSource( name, description, [self.shapetypeCombo.currentData()]) elif (self.paramType == parameters.PARAMETER_MULTIPLE or isinstance(self.param, QgsProcessingParameterMultipleLayers)): self.param = QgsProcessingParameterMultipleLayers( name, description, self.datatypeCombo.currentData()) elif (self.paramType == parameters.PARAMETER_NUMBER or isinstance(self.param, QgsProcessingParameterNumber)): try: self.param = QgsProcessingParameterNumber( name, description, QgsProcessingParameterNumber.Double, self.defaultTextBox.text()) vmin = self.minTextBox.text().strip() if not vmin == '': self.param.setMinimum(float(vmin)) vmax = self.maxTextBox.text().strip() if not vmax == '': self.param.setMaximum(float(vmax)) except: QMessageBox.warning( self, self.tr('Unable to define parameter'), self.tr('Wrong or missing parameter values')) return elif (self.paramType == parameters.PARAMETER_EXPRESSION or isinstance(self.param, QgsProcessingParameterExpression)): parent = self.parentCombo.currentData() self.param = QgsProcessingParameterExpression( name, description, str(self.defaultEdit.expression()), parent) elif (self.paramType == parameters.PARAMETER_STRING or isinstance(self.param, QgsProcessingParameterString)): self.param = QgsProcessingParameterString( name, description, str(self.defaultTextBox.text())) elif (self.paramType == parameters.PARAMETER_EXTENT or isinstance(self.param, QgsProcessingParameterExtent)): self.param = QgsProcessingParameterExtent(name, description) elif (self.paramType == parameters.PARAMETER_FILE or isinstance(self.param, QgsProcessingParameterFile)): isFolder = self.fileFolderCombo.currentIndex() == 1 self.param = QgsProcessingParameterFile( name, description, QgsProcessingParameterFile.Folder if isFolder else QgsProcessingParameterFile.File) elif (self.paramType == parameters.PARAMETER_POINT or isinstance(self.param, QgsProcessingParameterPoint)): self.param = QgsProcessingParameterPoint( name, description, str(self.defaultTextBox.text())) elif (self.paramType == parameters.PARAMETER_CRS or isinstance(self.param, QgsProcessingParameterCrs)): self.param = QgsProcessingParameterCrs( name, description, self.selector.crs().authid()) else: from processing.core.Processing import Processing param = Processing.registeredParameters()[self.paramType] self.param = param['parameter'](name, description, None) self.param.setMetadata(param['metadata']) if not self.requiredCheck.isChecked(): self.param.setFlags( self.param.flags() | QgsProcessingParameterDefinition.FlagOptional) settings = QgsSettings() settings.setValue( "/Processing/modelParametersDefinitionDialogGeometry", self.saveGeometry()) QDialog.accept(self)
def _saveSetting(key, value): """Saves the setting with specified key.""" s = QgsSettings() s.setValue('QgsOpenScope/%s' % key, value)
def setCheckingOnStart(self, state): """ set state of checking for news and updates """ settings = QgsSettings() settings.setValue(settingsGroup + "/checkOnStart", state)
class MultipleFileInputDialog(BASE, WIDGET): def __init__(self, options): super(MultipleFileInputDialog, self).__init__(None) self.setupUi(self) self.lstLayers.setSelectionMode(QAbstractItemView.ExtendedSelection) self.selectedoptions = options # Additional buttons self.btnAdd = QPushButton(self.tr('Add file')) self.buttonBox.addButton(self.btnAdd, QDialogButtonBox.ActionRole) self.btnRemove = QPushButton(self.tr('Remove file(s)')) self.buttonBox.addButton(self.btnRemove, QDialogButtonBox.ActionRole) self.btnRemoveAll = QPushButton(self.tr('Remove all')) self.buttonBox.addButton(self.btnRemoveAll, QDialogButtonBox.ActionRole) self.btnAdd.clicked.connect(self.addFile) self.btnRemove.clicked.connect(lambda: self.removeRows()) self.btnRemoveAll.clicked.connect(lambda: self.removeRows(True)) self.settings = QgsSettings() self.restoreGeometry( self.settings.value("/Processing/multipleFileInputDialogGeometry", QByteArray())) self.populateList() self.finished.connect(self.saveWindowGeometry) def saveWindowGeometry(self): self.settings.setValue("/Processing/multipleInputDialogGeometry", self.saveGeometry()) def populateList(self): model = QStandardItemModel() for option in self.selectedoptions: item = QStandardItem(option) model.appendRow(item) self.lstLayers.setModel(model) def accept(self): self.selectedoptions = [] model = self.lstLayers.model() for i in range(model.rowCount()): item = model.item(i) self.selectedoptions.append(item.text()) QDialog.accept(self) def reject(self): QDialog.reject(self) def addFile(self): settings = QgsSettings() if settings.contains('/Processing/LastInputPath'): path = settings.value('/Processing/LastInputPath') else: path = '' files, selected_filter = QFileDialog.getOpenFileNames( self, self.tr('Select file(s)'), path, self.tr('All files (*.*)')) if len(files) == 0: return model = self.lstLayers.model() for filePath in files: item = QStandardItem(filePath) model.appendRow(item) settings.setValue('/Processing/LastInputPath', os.path.dirname(files[0])) def removeRows(self, removeAll=False): if removeAll: self.lstLayers.model().clear() else: self.lstLayers.setUpdatesEnabled(False) indexes = sorted(self.lstLayers.selectionModel().selectedIndexes()) for i in reversed(indexes): self.lstLayers.model().removeRow(i.row()) self.lstLayers.setUpdatesEnabled(True)
def testStyle(self): # First test with invalid URI vl = QgsVectorLayer('/idont/exist.gpkg', 'test', 'ogr') self.assertFalse( vl.dataProvider().isSaveAndLoadStyleToDatabaseSupported()) related_count, idlist, namelist, desclist, errmsg = vl.listStylesInDatabase( ) self.assertEqual(related_count, -1) self.assertEqual(idlist, []) self.assertEqual(namelist, []) self.assertEqual(desclist, []) self.assertNotEqual(errmsg, "") qml, errmsg = vl.getStyleFromDatabase("1") self.assertEqual(qml, "") self.assertNotEqual(errmsg, "") qml, success = vl.loadNamedStyle('/idont/exist.gpkg') self.assertFalse(success) errorMsg = vl.saveStyleToDatabase("name", "description", False, "") self.assertNotEqual(errorMsg, "") # Now with valid URI tmpfile = os.path.join(self.basetestpath, 'testStyle.gpkg') ds = ogr.GetDriverByName('GPKG').CreateDataSource(tmpfile) lyr = ds.CreateLayer('test', geom_type=ogr.wkbMultiPolygon) lyr.CreateField(ogr.FieldDefn('foo', ogr.OFTString)) f = ogr.Feature(lyr.GetLayerDefn()) f['foo'] = 'bar' lyr.CreateFeature(f) f = None lyr = ds.CreateLayer('test2', geom_type=ogr.wkbMultiPolygon) lyr.CreateField(ogr.FieldDefn('foo', ogr.OFTString)) f = ogr.Feature(lyr.GetLayerDefn()) f['foo'] = 'bar' lyr.CreateFeature(f) f = None ds = None vl = QgsVectorLayer('{}|layername=test'.format(tmpfile), 'test', 'ogr') self.assertTrue(vl.isValid()) vl2 = QgsVectorLayer('{}|layername=test2'.format(tmpfile), 'test2', 'ogr') self.assertTrue(vl2.isValid()) self.assertTrue( vl.dataProvider().isSaveAndLoadStyleToDatabaseSupported()) related_count, idlist, namelist, desclist, errmsg = vl.listStylesInDatabase( ) self.assertEqual(related_count, 0) self.assertEqual(idlist, []) self.assertEqual(namelist, []) self.assertEqual(desclist, []) self.assertNotEqual(errmsg, "") qml, errmsg = vl.getStyleFromDatabase("not_existing") self.assertEqual(qml, "") self.assertNotEqual(errmsg, "") qml, success = vl.loadNamedStyle('{}|layerid=0'.format(tmpfile)) self.assertFalse(success) errorMsg = vl.saveStyleToDatabase("name", "description", False, "") self.assertEqual(errorMsg, "") qml, errmsg = vl.getStyleFromDatabase("not_existing") self.assertEqual(qml, "") self.assertNotEqual(errmsg, "") related_count, idlist, namelist, desclist, errmsg = vl.listStylesInDatabase( ) self.assertEqual(related_count, 1) self.assertEqual(errmsg, "") self.assertEqual(idlist, ['1']) self.assertEqual(namelist, ['name']) self.assertEqual(desclist, ['description']) qml, errmsg = vl.getStyleFromDatabase("100") self.assertEqual(qml, "") self.assertNotEqual(errmsg, "") qml, errmsg = vl.getStyleFromDatabase("1") self.assertTrue(qml.startswith('<!DOCTYPE qgis'), qml) self.assertEqual(errmsg, "") # Try overwrite it but simulate answer no settings = QgsSettings() settings.setValue("/qgis/overwriteStyle", False) errorMsg = vl.saveStyleToDatabase("name", "description_bis", False, "") self.assertNotEqual(errorMsg, "") related_count, idlist, namelist, desclist, errmsg = vl.listStylesInDatabase( ) self.assertEqual(related_count, 1) self.assertEqual(errmsg, "") self.assertEqual(idlist, ['1']) self.assertEqual(namelist, ['name']) self.assertEqual(desclist, ['description']) # Try overwrite it and simulate answer yes settings = QgsSettings() settings.setValue("/qgis/overwriteStyle", True) errorMsg = vl.saveStyleToDatabase("name", "description_bis", False, "") self.assertEqual(errorMsg, "") related_count, idlist, namelist, desclist, errmsg = vl.listStylesInDatabase( ) self.assertEqual(related_count, 1) self.assertEqual(errmsg, "") self.assertEqual(idlist, ['1']) self.assertEqual(namelist, ['name']) self.assertEqual(desclist, ['description_bis']) errorMsg = vl2.saveStyleToDatabase("name_test2", "description_test2", True, "") self.assertEqual(errorMsg, "") errorMsg = vl.saveStyleToDatabase("name2", "description2", True, "") self.assertEqual(errorMsg, "") errorMsg = vl.saveStyleToDatabase("name3", "description3", True, "") self.assertEqual(errorMsg, "") related_count, idlist, namelist, desclist, errmsg = vl.listStylesInDatabase( ) self.assertEqual(related_count, 3) self.assertEqual(errmsg, "") self.assertEqual(idlist, ['1', '3', '4', '2']) self.assertEqual(namelist, ['name', 'name2', 'name3', 'name_test2']) self.assertEqual( desclist, ['description_bis', 'description2', 'description3', 'name_test2']) # Check that layers_style table is not list in subLayers() vl = QgsVectorLayer(tmpfile, 'test', 'ogr') sublayers = vl.dataProvider().subLayers() self.assertEqual(len(sublayers), 2, sublayers)
def installPlugin(self, key, quiet=False): """ Install given plugin """ error = False infoString = ('', '') plugin = plugins.all()[key] previousStatus = plugin["status"] if not plugin: return if plugin["status"] == "newer" and not plugin[ "error"]: # ask for confirmation if user downgrades an usable plugin if QMessageBox.warning( iface.mainWindow(), self.tr("QGIS Python Plugin Installer"), self. tr("Are you sure you want to downgrade the plugin to the latest available version? The installed one is newer!" ), QMessageBox.Yes, QMessageBox.No) == QMessageBox.No: return dlg = QgsPluginInstallerInstallingDialog(iface.mainWindow(), plugin) dlg.exec_() if dlg.result(): error = True infoString = (self.tr("Plugin installation failed"), dlg.result()) elif not QDir(qgis.utils.home_plugin_path + "/" + key).exists(): error = True infoString = ( self.tr("Plugin has disappeared"), self. tr("The plugin seems to have been installed but I don't know where. Probably the plugin package contained a wrong named directory.\nPlease search the list of installed plugins. I'm nearly sure you'll find the plugin there, but I just can't determine which of them it is. It also means that I won't be able to determine if this plugin is installed and inform you about available updates. However the plugin may work. Please contact the plugin author and submit this issue." )) QApplication.setOverrideCursor(Qt.WaitCursor) plugins.getAllInstalled() plugins.rebuild() self.exportPluginsToManager() QApplication.restoreOverrideCursor() else: QApplication.setOverrideCursor(Qt.WaitCursor) # update the list of plugins in plugin handling routines updateAvailablePlugins() # try to load the plugin loadPlugin(plugin["id"]) plugins.getAllInstalled() plugins.rebuild() plugin = plugins.all()[key] if not plugin["error"]: if previousStatus in ["not installed", "new"]: infoString = (self.tr("Plugin installed successfully"), "") if startPlugin(plugin["id"]): settings = QgsSettings() settings.setValue("/PythonPlugins/" + plugin["id"], True) else: settings = QgsSettings() if settings.value( "/PythonPlugins/" + key, False, type=bool ): # plugin will be reloaded on the fly only if currently loaded reloadPlugin( key) # unloadPlugin + loadPlugin + startPlugin infoString = ( self.tr("Plugin reinstalled successfully"), "") else: unloadPlugin( key ) # Just for a case. Will exit quietly if really not loaded loadPlugin(key) infoString = ( self.tr("Plugin reinstalled successfully"), self. tr("Python plugin reinstalled.\nYou need to restart QGIS in order to reload it." )) if quiet: infoString = (None, None) QApplication.restoreOverrideCursor() else: QApplication.restoreOverrideCursor() if plugin["error"] == "incompatible": message = self.tr( "The plugin is not compatible with this version of QGIS. It's designed for QGIS versions:" ) message += " <b>" + plugin["error_details"] + "</b>" elif plugin["error"] == "dependent": message = self.tr( "The plugin depends on some components missing on your system. You need to install the following Python module in order to enable it:" ) message += "<b> " + plugin["error_details"] + "</b>" else: message = self.tr("The plugin is broken. Python said:") message += "<br><b>" + plugin["error_details"] + "</b>" dlg = QgsPluginInstallerPluginErrorDialog( iface.mainWindow(), message) dlg.exec_() if dlg.result(): # revert installation pluginDir = qgis.utils.home_plugin_path + "/" + plugin["id"] result = removeDir(pluginDir) if QDir(pluginDir).exists(): error = True infoString = (self.tr("Plugin uninstall failed"), result) try: exec("sys.path_importer_cache.clear()") exec("import %s" % plugin["id"]) exec("reload (%s)" % plugin["id"]) except: pass else: try: exec("del sys.modules[%s]" % plugin["id"]) except: pass plugins.getAllInstalled() plugins.rebuild() self.exportPluginsToManager() if infoString[0]: level = error and QgsMessageBar.CRITICAL or QgsMessageBar.INFO msg = "<b>%s</b>" % infoString[0] if infoString[1]: msg += "<b>:</b> %s" % infoString[1] iface.pluginManagerInterface().pushMessage(msg, level)
def showSelectionDialog(self): if isinstance(self.output, QgsProcessingParameterFolderDestination): self.selectDirectory() return filefilter = getFileFilter(self.output) settings = QgsSettings() if settings.contains('/Processing/LastBatchOutputPath'): path = str(settings.value('/Processing/LastBatchOutputPath')) else: path = '' filename, selectedFileFilter = QFileDialog.getSaveFileName(self, self.tr('Save File'), path, filefilter) if filename: if not filename.lower().endswith( tuple(re.findall("\\*(\\.[a-z]{1,10})", filefilter))): ext = re.search("\\*(\\.[a-z]{1,10})", selectedFileFilter) if ext: filename += ext.group(1) settings.setValue('/Processing/LastBatchOutputPath', os.path.dirname(filename)) dlg = AutofillDialog(self.alg) dlg.exec_() if dlg.mode is not None: try: if dlg.mode == AutofillDialog.DO_NOT_AUTOFILL: self.table.cellWidget(self.row, self.col).setValue(filename) elif dlg.mode == AutofillDialog.FILL_WITH_NUMBERS: n = self.table.rowCount() - self.row for i in range(n): name = filename[:filename.rfind('.')] \ + str(i + 1) + filename[filename.rfind('.'):] self.table.cellWidget(i + self.row, self.col).setValue(name) elif dlg.mode == AutofillDialog.FILL_WITH_PARAMETER: n = self.table.rowCount() - self.row for i in range(n): widget = self.table.cellWidget(i + self.row, dlg.param_index) param = self.alg.parameterDefinitions()[dlg.param_index] if isinstance(param, (QgsProcessingParameterRasterLayer, QgsProcessingParameterFeatureSource, QgsProcessingParameterVectorLayer, QgsProcessingParameterMultipleLayers)): v = widget.value() if isinstance(v, QgsMapLayer): s = v.name() else: s = os.path.basename(v) s = os.path.splitext(s)[0] elif isinstance(param, QgsProcessingParameterBoolean): s = str(widget.currentIndex() == 0) elif isinstance(param, QgsProcessingParameterEnum): s = str(widget.currentText()) elif isinstance(param, QgsProcessingParameterMatrix): s = str(widget.table) else: s = str(widget.text()) name = filename[:filename.rfind('.')] + s \ + filename[filename.rfind('.'):] self.table.cellWidget(i + self.row, self.col).setValue(name) except: pass
def setCheckingOnStartInterval(self, interval): """ set checking for news and updates interval """ settings = QgsSettings() settings.setValue(settingsGroup + "/checkOnStartInterval", interval)
class PythonConsoleWidget(QWidget): def __init__(self, parent=None): QWidget.__init__(self, parent) self.setWindowTitle(QCoreApplication.translate("PythonConsole", "Python Console")) self.settings = QgsSettings() self.shell = ShellScintilla(self) self.setFocusProxy(self.shell) self.shellOut = ShellOutputScintilla(self) self.tabEditorWidget = EditorTabWidget(self) # ------------ UI ------------------------------- self.splitterEditor = QSplitter(self) self.splitterEditor.setOrientation(Qt.Horizontal) self.splitterEditor.setHandleWidth(6) self.splitterEditor.setChildrenCollapsible(True) self.shellOutWidget = QWidget(self) self.shellOutWidget.setLayout(QVBoxLayout()) self.shellOutWidget.layout().setContentsMargins(0, 0, 0, 0) self.shellOutWidget.layout().addWidget(self.shellOut) self.splitter = QSplitter(self.splitterEditor) self.splitter.setOrientation(Qt.Vertical) self.splitter.setHandleWidth(3) self.splitter.setChildrenCollapsible(False) self.splitter.addWidget(self.shellOutWidget) self.splitter.addWidget(self.shell) # self.splitterEditor.addWidget(self.tabEditorWidget) self.splitterObj = QSplitter(self.splitterEditor) self.splitterObj.setHandleWidth(3) self.splitterObj.setOrientation(Qt.Horizontal) # self.splitterObj.setSizes([0, 0]) # self.splitterObj.setStretchFactor(0, 1) self.widgetEditor = QWidget(self.splitterObj) self.widgetFind = QWidget(self) self.listClassMethod = QTreeWidget(self.splitterObj) self.listClassMethod.setColumnCount(2) objInspLabel = QCoreApplication.translate("PythonConsole", "Object Inspector") self.listClassMethod.setHeaderLabels([objInspLabel, '']) self.listClassMethod.setColumnHidden(1, True) self.listClassMethod.setAlternatingRowColors(True) # self.splitterEditor.addWidget(self.widgetEditor) # self.splitterObj.addWidget(self.listClassMethod) # self.splitterObj.addWidget(self.widgetEditor) # Hide side editor on start up self.splitterObj.hide() self.listClassMethod.hide() # Hide search widget on start up self.widgetFind.hide() icon_size = iface.iconSize(dockedToolbar=True) if iface else QSize(16, 16) sizes = self.splitter.sizes() self.splitter.setSizes(sizes) # ----------------Restore Settings------------------------------------ self.restoreSettingsConsole() # ------------------Toolbar Editor------------------------------------- # Action for Open File openFileBt = QCoreApplication.translate("PythonConsole", "Open Script...") self.openFileButton = QAction(self) self.openFileButton.setCheckable(False) self.openFileButton.setEnabled(True) self.openFileButton.setIcon(QgsApplication.getThemeIcon("console/iconOpenConsole.png")) self.openFileButton.setMenuRole(QAction.PreferencesRole) self.openFileButton.setIconVisibleInMenu(True) self.openFileButton.setToolTip(openFileBt) self.openFileButton.setText(openFileBt) openExtEditorBt = QCoreApplication.translate("PythonConsole", "Open in External Editor") self.openInEditorButton = QAction(self) self.openInEditorButton.setCheckable(False) self.openInEditorButton.setEnabled(True) self.openInEditorButton.setIcon(QgsApplication.getThemeIcon("console/iconShowEditorConsole.png")) self.openInEditorButton.setMenuRole(QAction.PreferencesRole) self.openInEditorButton.setIconVisibleInMenu(True) self.openInEditorButton.setToolTip(openExtEditorBt) self.openInEditorButton.setText(openExtEditorBt) # Action for Save File saveFileBt = QCoreApplication.translate("PythonConsole", "Save") self.saveFileButton = QAction(self) self.saveFileButton.setCheckable(False) self.saveFileButton.setEnabled(False) self.saveFileButton.setIcon(QgsApplication.getThemeIcon("console/iconSaveConsole.png")) self.saveFileButton.setMenuRole(QAction.PreferencesRole) self.saveFileButton.setIconVisibleInMenu(True) self.saveFileButton.setToolTip(saveFileBt) self.saveFileButton.setText(saveFileBt) # Action for Save File As saveAsFileBt = QCoreApplication.translate("PythonConsole", "Save As...") self.saveAsFileButton = QAction(self) self.saveAsFileButton.setCheckable(False) self.saveAsFileButton.setEnabled(True) self.saveAsFileButton.setIcon(QgsApplication.getThemeIcon("console/iconSaveAsConsole.png")) self.saveAsFileButton.setMenuRole(QAction.PreferencesRole) self.saveAsFileButton.setIconVisibleInMenu(True) self.saveAsFileButton.setToolTip(saveAsFileBt) self.saveAsFileButton.setText(saveAsFileBt) # Action Cut cutEditorBt = QCoreApplication.translate("PythonConsole", "Cut") self.cutEditorButton = QAction(self) self.cutEditorButton.setCheckable(False) self.cutEditorButton.setEnabled(True) self.cutEditorButton.setIcon(QgsApplication.getThemeIcon("mActionEditCut.svg")) self.cutEditorButton.setMenuRole(QAction.PreferencesRole) self.cutEditorButton.setIconVisibleInMenu(True) self.cutEditorButton.setToolTip(cutEditorBt) self.cutEditorButton.setText(cutEditorBt) # Action Copy copyEditorBt = QCoreApplication.translate("PythonConsole", "Copy") self.copyEditorButton = QAction(self) self.copyEditorButton.setCheckable(False) self.copyEditorButton.setEnabled(True) self.copyEditorButton.setIcon(QgsApplication.getThemeIcon("mActionEditCopy.svg")) self.copyEditorButton.setMenuRole(QAction.PreferencesRole) self.copyEditorButton.setIconVisibleInMenu(True) self.copyEditorButton.setToolTip(copyEditorBt) self.copyEditorButton.setText(copyEditorBt) # Action Paste pasteEditorBt = QCoreApplication.translate("PythonConsole", "Paste") self.pasteEditorButton = QAction(self) self.pasteEditorButton.setCheckable(False) self.pasteEditorButton.setEnabled(True) self.pasteEditorButton.setIcon(QgsApplication.getThemeIcon("mActionEditPaste.svg")) self.pasteEditorButton.setMenuRole(QAction.PreferencesRole) self.pasteEditorButton.setIconVisibleInMenu(True) self.pasteEditorButton.setToolTip(pasteEditorBt) self.pasteEditorButton.setText(pasteEditorBt) # Action Run Script (subprocess) runScriptEditorBt = QCoreApplication.translate("PythonConsole", "Run script") self.runScriptEditorButton = QAction(self) self.runScriptEditorButton.setCheckable(False) self.runScriptEditorButton.setEnabled(True) self.runScriptEditorButton.setIcon(QgsApplication.getThemeIcon("console/iconRunScriptConsole.png")) self.runScriptEditorButton.setMenuRole(QAction.PreferencesRole) self.runScriptEditorButton.setIconVisibleInMenu(True) self.runScriptEditorButton.setToolTip(runScriptEditorBt) self.runScriptEditorButton.setText(runScriptEditorBt) # Action Run Script (subprocess) commentEditorBt = QCoreApplication.translate("PythonConsole", "Comment") self.commentEditorButton = QAction(self) self.commentEditorButton.setCheckable(False) self.commentEditorButton.setEnabled(True) self.commentEditorButton.setIcon(QgsApplication.getThemeIcon("console/iconCommentEditorConsole.png")) self.commentEditorButton.setMenuRole(QAction.PreferencesRole) self.commentEditorButton.setIconVisibleInMenu(True) self.commentEditorButton.setToolTip(commentEditorBt) self.commentEditorButton.setText(commentEditorBt) # Action Run Script (subprocess) uncommentEditorBt = QCoreApplication.translate("PythonConsole", "Uncomment") self.uncommentEditorButton = QAction(self) self.uncommentEditorButton.setCheckable(False) self.uncommentEditorButton.setEnabled(True) self.uncommentEditorButton.setIcon(QgsApplication.getThemeIcon("console/iconUncommentEditorConsole.png")) self.uncommentEditorButton.setMenuRole(QAction.PreferencesRole) self.uncommentEditorButton.setIconVisibleInMenu(True) self.uncommentEditorButton.setToolTip(uncommentEditorBt) self.uncommentEditorButton.setText(uncommentEditorBt) # Action for Object browser objList = QCoreApplication.translate("PythonConsole", "Object Inspector...") self.objectListButton = QAction(self) self.objectListButton.setCheckable(True) self.objectListButton.setEnabled(self.settings.value("pythonConsole/enableObjectInsp", False, type=bool)) self.objectListButton.setIcon(QgsApplication.getThemeIcon("console/iconClassBrowserConsole.png")) self.objectListButton.setMenuRole(QAction.PreferencesRole) self.objectListButton.setIconVisibleInMenu(True) self.objectListButton.setToolTip(objList) self.objectListButton.setText(objList) # Action for Find text findText = QCoreApplication.translate("PythonConsole", "Find Text") self.findTextButton = QAction(self) self.findTextButton.setCheckable(True) self.findTextButton.setEnabled(True) self.findTextButton.setIcon(QgsApplication.getThemeIcon("console/iconSearchEditorConsole.png")) self.findTextButton.setMenuRole(QAction.PreferencesRole) self.findTextButton.setIconVisibleInMenu(True) self.findTextButton.setToolTip(findText) self.findTextButton.setText(findText) # ----------------Toolbar Console------------------------------------- # Action Show Editor showEditor = QCoreApplication.translate("PythonConsole", "Show Editor") self.showEditorButton = QAction(self) self.showEditorButton.setEnabled(True) self.showEditorButton.setCheckable(True) self.showEditorButton.setIcon(QgsApplication.getThemeIcon("console/iconShowEditorConsole.png")) self.showEditorButton.setMenuRole(QAction.PreferencesRole) self.showEditorButton.setIconVisibleInMenu(True) self.showEditorButton.setToolTip(showEditor) self.showEditorButton.setText(showEditor) # Action for Clear button clearBt = QCoreApplication.translate("PythonConsole", "Clear Console") self.clearButton = QAction(self) self.clearButton.setCheckable(False) self.clearButton.setEnabled(True) self.clearButton.setIcon(QgsApplication.getThemeIcon("console/iconClearConsole.png")) self.clearButton.setMenuRole(QAction.PreferencesRole) self.clearButton.setIconVisibleInMenu(True) self.clearButton.setToolTip(clearBt) self.clearButton.setText(clearBt) # Action for settings optionsBt = QCoreApplication.translate("PythonConsole", "Options...") self.optionsButton = QAction(self) self.optionsButton.setCheckable(False) self.optionsButton.setEnabled(True) self.optionsButton.setIcon(QgsApplication.getThemeIcon("console/iconSettingsConsole.png")) self.optionsButton.setMenuRole(QAction.PreferencesRole) self.optionsButton.setIconVisibleInMenu(True) self.optionsButton.setToolTip(optionsBt) self.optionsButton.setText(optionsBt) # Action for Run script runBt = QCoreApplication.translate("PythonConsole", "Run Command") self.runButton = QAction(self) self.runButton.setCheckable(False) self.runButton.setEnabled(True) self.runButton.setIcon(QgsApplication.getThemeIcon("console/iconRunConsole.png")) self.runButton.setMenuRole(QAction.PreferencesRole) self.runButton.setIconVisibleInMenu(True) self.runButton.setToolTip(runBt) self.runButton.setText(runBt) # Help action helpBt = QCoreApplication.translate("PythonConsole", "Help...") self.helpButton = QAction(self) self.helpButton.setCheckable(False) self.helpButton.setEnabled(True) self.helpButton.setIcon(QgsApplication.getThemeIcon("console/iconHelpConsole.png")) self.helpButton.setMenuRole(QAction.PreferencesRole) self.helpButton.setIconVisibleInMenu(True) self.helpButton.setToolTip(helpBt) self.helpButton.setText(helpBt) self.toolBar = QToolBar() self.toolBar.setEnabled(True) self.toolBar.setFocusPolicy(Qt.NoFocus) self.toolBar.setContextMenuPolicy(Qt.DefaultContextMenu) self.toolBar.setLayoutDirection(Qt.LeftToRight) self.toolBar.setIconSize(icon_size) self.toolBar.setMovable(False) self.toolBar.setFloatable(False) self.toolBar.addAction(self.clearButton) self.toolBar.addAction(self.runButton) self.toolBar.addSeparator() self.toolBar.addAction(self.showEditorButton) self.toolBar.addSeparator() self.toolBar.addAction(self.optionsButton) self.toolBar.addAction(self.helpButton) self.toolBarEditor = QToolBar() self.toolBarEditor.setEnabled(False) self.toolBarEditor.setFocusPolicy(Qt.NoFocus) self.toolBarEditor.setContextMenuPolicy(Qt.DefaultContextMenu) self.toolBarEditor.setLayoutDirection(Qt.LeftToRight) self.toolBarEditor.setIconSize(icon_size) self.toolBarEditor.setMovable(False) self.toolBarEditor.setFloatable(False) self.toolBarEditor.addAction(self.openFileButton) self.toolBarEditor.addAction(self.openInEditorButton) self.toolBarEditor.addSeparator() self.toolBarEditor.addAction(self.saveFileButton) self.toolBarEditor.addAction(self.saveAsFileButton) self.toolBarEditor.addSeparator() self.toolBarEditor.addAction(self.runScriptEditorButton) self.toolBarEditor.addSeparator() self.toolBarEditor.addAction(self.findTextButton) self.toolBarEditor.addSeparator() self.toolBarEditor.addAction(self.cutEditorButton) self.toolBarEditor.addAction(self.copyEditorButton) self.toolBarEditor.addAction(self.pasteEditorButton) self.toolBarEditor.addSeparator() self.toolBarEditor.addAction(self.commentEditorButton) self.toolBarEditor.addAction(self.uncommentEditorButton) self.toolBarEditor.addSeparator() self.toolBarEditor.addAction(self.objectListButton) self.widgetButton = QWidget() sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.widgetButton.sizePolicy().hasHeightForWidth()) self.widgetButton.setSizePolicy(sizePolicy) self.widgetButtonEditor = QWidget(self.widgetEditor) sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.widgetButtonEditor.sizePolicy().hasHeightForWidth()) self.widgetButtonEditor.setSizePolicy(sizePolicy) sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.shellOut.sizePolicy().hasHeightForWidth()) self.shellOut.setSizePolicy(sizePolicy) self.shellOut.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.shell.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) # ------------ Layout ------------------------------- self.mainLayout = QGridLayout(self) self.mainLayout.setMargin(0) self.mainLayout.setSpacing(0) self.mainLayout.addWidget(self.widgetButton, 0, 0, 1, 1) self.mainLayout.addWidget(self.splitterEditor, 0, 1, 1, 1) self.shellOutWidget.layout().insertWidget(0, self.toolBar) self.layoutEditor = QGridLayout(self.widgetEditor) self.layoutEditor.setMargin(0) self.layoutEditor.setSpacing(0) self.layoutEditor.addWidget(self.toolBarEditor, 0, 1, 1, 1) self.layoutEditor.addWidget(self.widgetButtonEditor, 1, 0, 2, 1) self.layoutEditor.addWidget(self.tabEditorWidget, 1, 1, 1, 1) self.layoutEditor.addWidget(self.widgetFind, 2, 1, 1, 1) # Layout for the find widget self.layoutFind = QGridLayout(self.widgetFind) self.layoutFind.setContentsMargins(0, 0, 0, 0) self.lineEditFind = QgsFilterLineEdit() placeHolderTxt = QCoreApplication.translate("PythonConsole", "Enter text to find...") self.lineEditFind.setPlaceholderText(placeHolderTxt) self.findNextButton = QToolButton() self.findNextButton.setEnabled(False) toolTipfindNext = QCoreApplication.translate("PythonConsole", "Find Next") self.findNextButton.setToolTip(toolTipfindNext) self.findNextButton.setIcon(QgsApplication.getThemeIcon("console/iconSearchNextEditorConsole.png")) self.findNextButton.setIconSize(QSize(24, 24)) self.findNextButton.setAutoRaise(True) self.findPrevButton = QToolButton() self.findPrevButton.setEnabled(False) toolTipfindPrev = QCoreApplication.translate("PythonConsole", "Find Previous") self.findPrevButton.setToolTip(toolTipfindPrev) self.findPrevButton.setIcon(QgsApplication.getThemeIcon("console/iconSearchPrevEditorConsole.png")) self.findPrevButton.setIconSize(QSize(24, 24)) self.findPrevButton.setAutoRaise(True) self.caseSensitive = QCheckBox() caseSensTr = QCoreApplication.translate("PythonConsole", "Case Sensitive") self.caseSensitive.setText(caseSensTr) self.wholeWord = QCheckBox() wholeWordTr = QCoreApplication.translate("PythonConsole", "Whole Word") self.wholeWord.setText(wholeWordTr) self.wrapAround = QCheckBox() self.wrapAround.setChecked(True) wrapAroundTr = QCoreApplication.translate("PythonConsole", "Wrap Around") self.wrapAround.setText(wrapAroundTr) self.layoutFind.addWidget(self.lineEditFind, 0, 1, 1, 1) self.layoutFind.addWidget(self.findPrevButton, 0, 2, 1, 1) self.layoutFind.addWidget(self.findNextButton, 0, 3, 1, 1) self.layoutFind.addWidget(self.caseSensitive, 0, 4, 1, 1) self.layoutFind.addWidget(self.wholeWord, 0, 5, 1, 1) self.layoutFind.addWidget(self.wrapAround, 0, 6, 1, 1) # ------------ Add first Tab in Editor ------------------------------- # self.tabEditorWidget.newTabEditor(tabName='first', filename=None) # ------------ Signal ------------------------------- self.findTextButton.triggered.connect(self._toggleFind) self.objectListButton.toggled.connect(self.toggleObjectListWidget) self.commentEditorButton.triggered.connect(self.commentCode) self.uncommentEditorButton.triggered.connect(self.uncommentCode) self.runScriptEditorButton.triggered.connect(self.runScriptEditor) self.cutEditorButton.triggered.connect(self.cutEditor) self.copyEditorButton.triggered.connect(self.copyEditor) self.pasteEditorButton.triggered.connect(self.pasteEditor) self.showEditorButton.toggled.connect(self.toggleEditor) self.clearButton.triggered.connect(self.shellOut.clearConsole) self.optionsButton.triggered.connect(self.openSettings) self.runButton.triggered.connect(self.shell.entered) self.openFileButton.triggered.connect(self.openScriptFile) self.openInEditorButton.triggered.connect(self.openScriptFileExtEditor) self.saveFileButton.triggered.connect(self.saveScriptFile) self.saveAsFileButton.triggered.connect(self.saveAsScriptFile) self.helpButton.triggered.connect(self.openHelp) self.listClassMethod.itemClicked.connect(self.onClickGoToLine) self.lineEditFind.returnPressed.connect(self._findNext) self.findNextButton.clicked.connect(self._findNext) self.findPrevButton.clicked.connect(self._findPrev) self.lineEditFind.textChanged.connect(self._textFindChanged) self.findScut = QShortcut(QKeySequence.Find, self.widgetEditor) self.findScut.setContext(Qt.WidgetWithChildrenShortcut) self.findScut.activated.connect(self._openFind) self.findNextScut = QShortcut(QKeySequence.FindNext, self.widgetEditor) self.findNextScut.setContext(Qt.WidgetWithChildrenShortcut) self.findNextScut.activated.connect(self._findNext) self.findPreviousScut = QShortcut(QKeySequence.FindPrevious, self.widgetEditor) self.findPreviousScut.setContext(Qt.WidgetWithChildrenShortcut) self.findPreviousScut.activated.connect(self._findPrev) # Escape on editor hides the find bar self.findScut = QShortcut(Qt.Key_Escape, self.widgetEditor) self.findScut.setContext(Qt.WidgetWithChildrenShortcut) self.findScut.activated.connect(self._closeFind) def _toggleFind(self): self.tabEditorWidget.currentWidget().newEditor.toggleFindWidget() def _openFind(self): self.tabEditorWidget.currentWidget().newEditor.openFindWidget() def _closeFind(self): self.tabEditorWidget.currentWidget().newEditor.closeFindWidget() def _findNext(self): self.tabEditorWidget.currentWidget().newEditor.findText(True) def _findPrev(self): self.tabEditorWidget.currentWidget().newEditor.findText(False) def _textFindChanged(self): if self.lineEditFind.text(): self.findNextButton.setEnabled(True) self.findPrevButton.setEnabled(True) self.tabEditorWidget.currentWidget().newEditor.findText(True, showMessage=False, findFirst=True) else: self.lineEditFind.setStyleSheet('') self.findNextButton.setEnabled(False) self.findPrevButton.setEnabled(False) def onClickGoToLine(self, item, column): tabEditor = self.tabEditorWidget.currentWidget().newEditor if item.text(1) == 'syntaxError': check = tabEditor.syntaxCheck(fromContextMenu=False) if check and not tabEditor.isReadOnly(): self.tabEditorWidget.currentWidget().save() return linenr = int(item.text(1)) itemName = str(item.text(0)) charPos = itemName.find(' ') if charPos != -1: objName = itemName[0:charPos] else: objName = itemName tabEditor.goToLine(objName, linenr) def toggleEditor(self, checked): self.splitterObj.show() if checked else self.splitterObj.hide() if not self.tabEditorWidget: self.tabEditorWidget.enableToolBarEditor(checked) self.tabEditorWidget.restoreTabsOrAddNew() def toggleObjectListWidget(self, checked): self.listClassMethod.show() if checked else self.listClassMethod.hide() def pasteEditor(self): self.tabEditorWidget.currentWidget().newEditor.paste() def cutEditor(self): self.tabEditorWidget.currentWidget().newEditor.cut() def copyEditor(self): self.tabEditorWidget.currentWidget().newEditor.copy() def runScriptEditor(self): self.tabEditorWidget.currentWidget().newEditor.runScriptCode() def commentCode(self): self.tabEditorWidget.currentWidget().newEditor.commentEditorCode(True) def uncommentCode(self): self.tabEditorWidget.currentWidget().newEditor.commentEditorCode(False) def openScriptFileExtEditor(self): tabWidget = self.tabEditorWidget.currentWidget() path = tabWidget.path import subprocess try: subprocess.Popen([os.environ['EDITOR'], path]) except KeyError: QDesktopServices.openUrl(QUrl.fromLocalFile(path)) def openScriptFile(self): lastDirPath = self.settings.value("pythonConsole/lastDirPath", QDir.homePath()) openFileTr = QCoreApplication.translate("PythonConsole", "Open File") fileList, selected_filter = QFileDialog.getOpenFileNames( self, openFileTr, lastDirPath, "Script file (*.py)") if fileList: for pyFile in fileList: for i in range(self.tabEditorWidget.count()): tabWidget = self.tabEditorWidget.widget(i) if tabWidget.path == pyFile: self.tabEditorWidget.setCurrentWidget(tabWidget) break else: tabName = QFileInfo(pyFile).fileName() self.tabEditorWidget.newTabEditor(tabName, pyFile) lastDirPath = QFileInfo(pyFile).path() self.settings.setValue("pythonConsole/lastDirPath", pyFile) self.updateTabListScript(pyFile, action='append') def saveScriptFile(self): tabWidget = self.tabEditorWidget.currentWidget() try: tabWidget.save() except (IOError, OSError) as error: msgText = QCoreApplication.translate('PythonConsole', 'The file <b>{0}</b> could not be saved. Error: {1}').format(tabWidget.path, error.strerror) self.callWidgetMessageBarEditor(msgText, 2, False) def saveAsScriptFile(self, index=None): tabWidget = self.tabEditorWidget.currentWidget() if not index: index = self.tabEditorWidget.currentIndex() if not tabWidget.path: fileName = self.tabEditorWidget.tabText(index) + '.py' folder = self.settings.value("pythonConsole/lastDirPath", QDir.home()) pathFileName = os.path.join(folder, fileName) fileNone = True else: pathFileName = tabWidget.path fileNone = False saveAsFileTr = QCoreApplication.translate("PythonConsole", "Save File As") filename, filter = QFileDialog.getSaveFileName(self, saveAsFileTr, pathFileName, "Script file (*.py)") if filename: try: tabWidget.save(filename) except (IOError, OSError) as error: msgText = QCoreApplication.translate('PythonConsole', 'The file <b>{0}</b> could not be saved. Error: {1}').format(tabWidget.path, error.strerror) self.callWidgetMessageBarEditor(msgText, 2, False) if fileNone: tabWidget.path = None else: tabWidget.path = pathFileName return if not fileNone: self.updateTabListScript(pathFileName, action='remove') def openHelp(self): QgsHelp.openHelp("plugins/python_console.html") def openSettings(self): if optionsDialog(self).exec_(): self.shell.refreshSettingsShell() self.shellOut.refreshSettingsOutput() self.tabEditorWidget.refreshSettingsEditor() def callWidgetMessageBar(self, text): self.shellOut.widgetMessageBar(iface, text) def callWidgetMessageBarEditor(self, text, level, timed): self.tabEditorWidget.widgetMessageBar(iface, text, level, timed) def updateTabListScript(self, script, action=None): if action == 'remove': self.tabListScript.remove(script) elif action == 'append': if not self.tabListScript: self.tabListScript = [] if script not in self.tabListScript: self.tabListScript.append(script) else: self.tabListScript = [] self.settings.setValue("pythonConsole/tabScripts", self.tabListScript) def saveSettingsConsole(self): self.settings.setValue("pythonConsole/splitterConsole", self.splitter.saveState()) self.settings.setValue("pythonConsole/splitterObj", self.splitterObj.saveState()) self.settings.setValue("pythonConsole/splitterEditor", self.splitterEditor.saveState()) self.shell.writeHistoryFile(True) def restoreSettingsConsole(self): storedTabScripts = self.settings.value("pythonConsole/tabScripts", []) self.tabListScript = storedTabScripts self.splitter.restoreState(self.settings.value("pythonConsole/splitterConsole", QByteArray())) self.splitterEditor.restoreState(self.settings.value("pythonConsole/splitterEditor", QByteArray())) self.splitterObj.restoreState(self.settings.value("pythonConsole/splitterObj", QByteArray()))
class QTilesDialog(QDialog, Ui_Dialog): # MAX_ZOOM_LEVEL = 18 MIN_ZOOM_LEVEL = 0 def __init__(self, iface: object) -> object: QDialog.__init__(self) self.setupUi(self) #self.skipBlankTiles = False; #self.macroTile = 1 self.btnOk = self.buttonBox.addButton(self.tr("Run"), QDialogButtonBox.AcceptRole) # self.spnZoomMax.setMaximum(self.MAX_ZOOM_LEVEL) self.spnZoomMax.setMinimum(self.MIN_ZOOM_LEVEL) # self.spnZoomMin.setMaximum(self.MAX_ZOOM_LEVEL) self.spnZoomMin.setMinimum(self.MIN_ZOOM_LEVEL) self.spnZoomMin.valueChanged.connect(self.spnZoomMax.setMinimum) self.spnZoomMax.valueChanged.connect(self.spnZoomMin.setMaximum) self.iface = iface self.workThread = None self.FORMATS = { self.tr('ZIP archives (*.zip *.ZIP)'): '.zip', self.tr('MBTiles databases (*.mbtiles *.MBTILES)'): '.mbtiles' } self.settings = QgsSettings('NextGIS', 'QTiles') # self.grpParameters.setSettings(self.settings) self.btnClose = self.buttonBox.button(QDialogButtonBox.Close) self.rbExtentLayer.toggled.connect(self.__toggleLayerSelector) self.chkLockRatio.stateChanged.connect(self.__toggleHeightEdit) self.spnTileWidth.valueChanged.connect(self.__updateTileSize) self.btnBrowse.clicked.connect(self.__select_output) self.cmbFormat.activated.connect(self.formatChanged) self.rbOutputZip.toggled.connect(self.__toggleTarget) self.rbOutputDir.toggled.connect(self.__toggleTarget) self.rbOutputNGM.toggled.connect(self.__toggleTarget) self.rbOutputNGM.setIcon(QIcon(':/icons/ngm_index_24x24.png')) self.lInfoIconOutputZip.linkActivated.connect(self.show_output_info) self.lInfoIconOutputDir.linkActivated.connect(self.show_output_info) self.lInfoIconOutputNGM.linkActivated.connect(self.show_output_info) self.lInfoIconMacroTile.linkActivated.connect(self.show_output_info) self.manageGui() def show_output_info(self): title = self.tr("Output type info") message = "" if self.sender() is self.lInfoIconOutputZip: message = self.tr("Save tiles as Zip or MBTiles") elif self.sender() is self.lInfoIconOutputDir: message = self.tr("Save tiles as directory structure") elif self.sender() is self.lInfoIconOutputNGM: message = "<table cellspacing='10'> <tr> \ <td> \ <img src=':/icons/ngm_index_24x24.png'/> \ </td> \ <td> \ %s \ </td> \ </tr> </table>" % self.tr( "Prepare package for <a href='http://nextgis.ru/en/nextgis-mobile/'> NextGIS Mobile </a>" ) elif self.sender() is self.lInfoIconMacroTile: title = self.tr("Render tile sets") message = self.tr( "Rendering a set of many adjacent tiles at once\nsaves process time, at the expense of system memory" ) msgBox = QMessageBox() msgBox.setWindowTitle(title) msgBox.setText(message) msgBox.exec_() def format_time_hhmmss(self, seconds): m, s = divmod(seconds, 60) h, m = divmod(m, 60) time_str = "%02d:%02d:%02d" % (h, m, s) return time_str def formatChanged(self): if self.cmbFormat.currentText() == 'JPG': self.spnTransparency.setEnabled(False) self.spnQuality.setEnabled(True) else: self.spnTransparency.setEnabled(True) self.spnQuality.setEnabled(False) def manageGui(self): layers = utils.getMapLayers() root = QgsProject.instance().layerTreeRoot() for layer in sorted(layers.items(), key=operator.itemgetter(1)): node = root.findLayer(layer[0]) if node.parent() == root: self.cmbLayers.addItem(layer[1], layer[0]) else: self.cmbLayers.addItem( '%s - %s' % (layer[1], node.parent().name()), layer[0]) self.rbOutputZip.setChecked( self.settings.value('outputToZip', True, type=bool)) self.rbOutputDir.setChecked( self.settings.value('outputToDir', False, type=bool)) self.rbOutputNGM.setChecked( self.settings.value('outputToNGM', False, type=bool)) if self.rbOutputZip.isChecked(): self.leDirectoryName.setEnabled(False) self.leTilesFroNGM.setEnabled(False) elif self.rbOutputDir.isChecked(): self.leZipFileName.setEnabled(False) self.leTilesFroNGM.setEnabled(False) elif self.rbOutputNGM.isChecked(): self.leZipFileName.setEnabled(False) self.leDirectoryName.setEnabled(False) else: self.leZipFileName.setEnabled(False) self.leDirectoryName.setEnabled(False) self.leTilesFroNGM.setEnabled(False) self.leZipFileName.setText(self.settings.value('outputToZip_Path', '')) self.leDirectoryName.setText( self.settings.value('outputToDir_Path', '')) self.leTilesFroNGM.setText(self.settings.value('outputToNGM_Path', '')) self.cmbLayers.setEnabled(False) self.leRootDir.setText(self.settings.value('rootDir', 'Mapnik')) self.rbExtentCanvas.setChecked( self.settings.value('extentCanvas', True, type=bool)) self.rbExtentFull.setChecked( self.settings.value('extentFull', False, type=bool)) self.rbExtentLayer.setChecked( self.settings.value('extentLayer', False, type=bool)) self.spnZoomMin.setValue(self.settings.value('minZoom', 0, type=int)) self.spnZoomMax.setValue(self.settings.value('maxZoom', 18, type=int)) self.chkLockRatio.setChecked( self.settings.value('keepRatio', True, type=bool)) self.spnTileWidth.setValue( self.settings.value('tileWidth', 256, type=int)) self.spnTileHeight.setValue( self.settings.value('tileHeight', 256, type=int)) self.spnTransparency.setValue( self.settings.value('transparency', 255, type=int)) self.spnQuality.setValue(self.settings.value('quality', 70, type=int)) self.spnMacroTile.setValue( self.settings.value('macroTile', 1, type=int)) self.cmbFormat.setCurrentIndex(int(self.settings.value('format', 0))) self.chkAntialiasing.setChecked( self.settings.value('enable_antialiasing', False, type=bool)) self.chkTMSConvention.setChecked( self.settings.value('use_tms_filenames', False, type=bool)) self.chkMBTilesCompression.setChecked( self.settings.value('use_mbtiles_compression', False, type=bool)) self.chkWriteJson.setChecked( self.settings.value("write_json", False, type=bool)) self.chkWriteOverview.setChecked( self.settings.value("write_overview", False, type=bool)) self.chkWriteMapurl.setChecked( self.settings.value("write_mapurl", False, type=bool)) self.chkWriteViewer.setChecked( self.settings.value("write_viewer", False, type=bool)) # self.chkRenderOutsideTiles.setChecked(self.settings.value("renderOutsideTiles", True, type=bool)) self.chkMsgDialogs.setChecked( self.settings.value("chkMsgDialogs", True, type=bool)) self.chkSkipBlankTiles.setChecked( self.settings.value("skipBlankTiles", False, type=bool)) self.formatChanged() def reject(self): QDialog.reject(self) def accept(self): self.startTime = time.time() self.tileCount = 0 self.blankCount = 0 if self.rbOutputZip.isChecked(): output = self.leZipFileName.text() elif self.rbOutputDir.isChecked(): output = self.leDirectoryName.text() if not QFileInfo(output).exists(): os.mkdir(QFileInfo(output).absoluteFilePath()) elif self.rbOutputNGM.isChecked(): output = self.leTilesFroNGM.text() if not output: QMessageBox.warning( self, self.tr('No output'), self. tr('Output path is not set. Please enter correct path and try again.' )) return fileInfo = QFileInfo(output) if fileInfo.isDir() and not len( QDir(output).entryList(QDir.Dirs | QDir.Files | QDir.NoDotAndDotDot)) == 0: res = QMessageBox.warning( self, self.tr('Directory not empty'), self.tr('Selected directory is not empty. Continue?'), QMessageBox.Yes | QMessageBox.No) if res == QMessageBox.No: return if self.spnZoomMin.value() > self.spnZoomMax.value(): QMessageBox.warning( self, self.tr('Wrong zoom'), self. tr('Maximum zoom value is lower than minimum. Please correct this and try again.' )) return self.settings.setValue('rootDir', self.leRootDir.text()) self.settings.setValue('outputToZip', self.rbOutputZip.isChecked()) self.settings.setValue('outputToDir', self.rbOutputDir.isChecked()) self.settings.setValue('outputToNGM', self.rbOutputNGM.isChecked()) self.settings.setValue('extentCanvas', self.rbExtentCanvas.isChecked()) self.settings.setValue('extentFull', self.rbExtentFull.isChecked()) self.settings.setValue('extentLayer', self.rbExtentLayer.isChecked()) self.settings.setValue('minZoom', self.spnZoomMin.value()) self.settings.setValue('maxZoom', self.spnZoomMax.value()) self.settings.setValue('keepRatio', self.chkLockRatio.isChecked()) self.settings.setValue('tileWidth', self.spnTileWidth.value()) self.settings.setValue('tileHeight', self.spnTileHeight.value()) self.settings.setValue('format', self.cmbFormat.currentIndex()) self.settings.setValue('transparency', self.spnTransparency.value()) self.settings.setValue('quality', self.spnQuality.value()) self.settings.setValue('macroTile', self.spnMacroTile.value()) self.settings.setValue('enable_antialiasing', self.chkAntialiasing.isChecked()) self.settings.setValue('use_tms_filenames', self.chkTMSConvention.isChecked()) self.settings.setValue('skipBlankTiles', self.chkSkipBlankTiles.isChecked()) self.settings.setValue('use_mbtiles_compression', self.chkMBTilesCompression.isChecked()) self.settings.setValue('write_json', self.chkWriteJson.isChecked()) self.settings.setValue('write_overview', self.chkWriteOverview.isChecked()) self.settings.setValue('write_mapurl', self.chkWriteMapurl.isChecked()) self.settings.setValue('write_viewer', self.chkWriteViewer.isChecked()) self.settings.setValue('chkMsgDialogs', self.chkMsgDialogs.isChecked()) canvas = self.iface.mapCanvas() if self.rbExtentCanvas.isChecked(): extent = canvas.extent() elif self.rbExtentFull.isChecked(): extent = canvas.fullExtent() else: layer = utils.getLayerById( self.cmbLayers.itemData(self.cmbLayers.currentIndex())) extent = canvas.mapSettings().layerExtentToOutputExtent( layer, layer.extent()) extent = QgsCoordinateTransform( canvas.mapSettings().destinationCrs(), QgsCoordinateReferenceSystem('EPSG:4326'), QgsProject.instance()).transform(extent) arctanSinhPi = math.degrees(math.atan(math.sinh(math.pi))) extent = extent.intersect( QgsRectangle(-180, -arctanSinhPi, 180, arctanSinhPi)) layers = canvas.layers() writeMapurl = self.chkWriteMapurl.isEnabled( ) and self.chkWriteMapurl.isChecked() writeViewer = self.chkWriteViewer.isEnabled( ) and self.chkWriteViewer.isChecked() self.workThread = TilingThread( layers, extent, self.spnZoomMin.value(), self.spnZoomMax.value(), self.spnTileWidth.value(), self.spnTileHeight.value(), self.spnMacroTile.value(), self.spnTransparency.value(), self.spnQuality.value(), self.cmbFormat.currentText(), fileInfo, self.leRootDir.text(), self.chkAntialiasing.isChecked(), self.chkTMSConvention.isChecked(), self.chkMBTilesCompression.isChecked(), self.chkWriteJson.isChecked(), self.chkWriteOverview.isChecked(), # self.chkRenderOutsideTiles.isChecked(), self.chkSkipBlankTiles.isChecked(), writeMapurl, writeViewer) self.workThread.rangeChanged.connect(self.setProgressRange) self.workThread.updateProgress.connect(self.updateProgress) self.workThread.processFinished.connect(self.processFinished) self.workThread.processInterrupted.connect(self.processInterrupted) self.workThread.threshold.connect(self.confirmContinueThreshold) self.btnOk.setEnabled(False) self.btnClose.setText(self.tr('Cancel')) self.buttonBox.rejected.disconnect(self.reject) self.btnClose.clicked.connect(self.stopProcessing) self.workThread.start() def confirmContinueThreshold(self, tilesCountThreshold): res = QMessageBox.question( self.parent(), self.tr("Confirmation"), self.tr("Estimate number of tiles more then %d! Continue?") % tilesCountThreshold, QMessageBox.Yes | QMessageBox.No) if res == QMessageBox.Yes: self.workThread.confirmContinue() else: self.workThread.confirmStop() def setProgressRange(self, message, value): self.progressBar.setFormat(message) self.progressBar.setRange(0, value) def updateProgress(self, tileCount, blankCount): self.tileCount = tileCount self.blankCount = blankCount self.progressBar.setValue(self.progressBar.value() + 1) def processInterrupted(self): if self.chkMsgDialogs.isChecked(): QMessageBox.warning(self, "Qtiles", "Process interrupted!") self.restoreGui() def processFinished(self): self.stopProcessing() elapsedTime = time.time() - self.startTime txt = "Process finished normally.\nElapsed time: %s.\nTiles written: %d." % ( self.format_time_hhmmss(elapsedTime), self.tileCount) if self.blankCount > 0: txt = "%s\nBlank tiles: %d." % (txt, self.blankCount) if self.chkMsgDialogs.isChecked(): QMessageBox.information(self, "Qtiles", txt) self.restoreGui() def stopProcessing(self): if self.workThread is not None: self.workThread.stop() self.workThread = None def restoreGui(self): self.progressBar.setFormat('%p%') self.progressBar.setRange(0, 1) self.progressBar.setValue(0) self.buttonBox.rejected.connect(self.reject) self.btnClose.clicked.disconnect(self.stopProcessing) self.btnClose.setText(self.tr('Close')) self.btnOk.setEnabled(True) def __toggleTarget(self, checked): if checked: if self.sender() is self.rbOutputZip: self.leZipFileName.setEnabled(True) self.leDirectoryName.setEnabled(False) self.leTilesFroNGM.setEnabled(False) self.chkWriteMapurl.setEnabled(False) self.chkWriteViewer.setEnabled(False) self.chkWriteJson.setEnabled(True) self.spnTileWidth.setEnabled(True) self.chkLockRatio.setEnabled(True) self.cmbFormat.setEnabled(True) self.chkMBTilesCompression.setEnabled(True) self.chkWriteOverview.setEnabled(True) elif self.sender() is self.rbOutputDir: self.leZipFileName.setEnabled(False) self.leDirectoryName.setEnabled(True) self.leTilesFroNGM.setEnabled(False) self.chkWriteMapurl.setEnabled(True) self.chkWriteViewer.setEnabled(True) self.chkWriteJson.setEnabled(True) self.chkMBTilesCompression.setEnabled(False) self.spnTileWidth.setEnabled(True) self.chkLockRatio.setEnabled(True) self.cmbFormat.setEnabled(True) self.chkWriteOverview.setEnabled(True) elif self.sender() is self.rbOutputNGM: self.leZipFileName.setEnabled(False) self.leDirectoryName.setEnabled(False) self.leTilesFroNGM.setEnabled(True) self.chkWriteMapurl.setEnabled(False) self.chkWriteViewer.setEnabled(False) self.chkMBTilesCompression.setEnabled(False) self.spnTileWidth.setValue(256) self.spnTileWidth.setEnabled(False) self.chkLockRatio.setCheckState(Qt.Checked) self.chkLockRatio.setEnabled(False) self.cmbFormat.setCurrentIndex(0) self.cmbFormat.setEnabled(False) self.chkWriteOverview.setChecked(False) self.chkWriteOverview.setEnabled(False) self.chkWriteJson.setChecked(False) self.chkWriteJson.setEnabled(False) def __toggleLayerSelector(self, checked): self.cmbLayers.setEnabled(checked) def __toggleHeightEdit(self, state): if state == Qt.Checked: self.lblHeight.setEnabled(False) self.spnTileHeight.setEnabled(False) self.spnTileHeight.setValue(self.spnTileWidth.value()) else: self.lblHeight.setEnabled(True) self.spnTileHeight.setEnabled(True) @pyqtSlot(int) def __updateTileSize(self, value): if self.chkLockRatio.isChecked(): self.spnTileHeight.setValue(value) def __select_output(self): if self.rbOutputZip.isChecked(): file_directory = QFileInfo( self.settings.value('outputToZip_Path', '.')).absolutePath() outPath, outFilter = QFileDialog.getSaveFileName( self, self.tr('Save to file'), file_directory, ';;'.join(list(self.FORMATS.keys())), list(self.FORMATS.keys())[list( self.FORMATS.values()).index('.zip')]) if not outPath: return if not outPath.lower().endswith(self.FORMATS[outFilter]): outPath += self.FORMATS[outFilter] self.leZipFileName.setText(outPath) self.settings.setValue('outputToZip_Path', QFileInfo(outPath).absoluteFilePath()) elif self.rbOutputDir.isChecked(): dir_directory = QFileInfo( self.settings.value('outputToDir_Path', '.')).absolutePath() outPath = QFileDialog.getExistingDirectory( self, self.tr('Save to directory'), dir_directory, QFileDialog.ShowDirsOnly) if not outPath: return self.leDirectoryName.setText(outPath) self.settings.setValue('outputToDir_Path', QFileInfo(outPath).absoluteFilePath()) elif self.rbOutputNGM.isChecked(): zip_directory = QFileInfo( self.settings.value('outputToNGM_Path', '.')).absolutePath() outPath, outFilter = QFileDialog.getSaveFileName( self, self.tr('Save to file'), zip_directory, 'ngrc') if not outPath: return if not outPath.lower().endswith('ngrc'): outPath += '.ngrc' self.leTilesFroNGM.setText(outPath) self.settings.setValue('outputToNGM_Path', QFileInfo(outPath).absoluteFilePath())
class TestQgsSettings(unittest.TestCase): cnt = 0 def setUp(self): self.cnt += 1 h, path = tempfile.mkstemp('.ini') Path(path).touch() assert QgsSettings.setGlobalSettingsPath(path) self.settings = QgsSettings('testqgissettings', 'testqgissettings%s' % self.cnt) self.globalsettings = QSettings(self.settings.globalSettingsPath(), QSettings.IniFormat) self.globalsettings.sync() assert os.path.exists(self.globalsettings.fileName()) def tearDown(self): settings_file = self.settings.fileName() settings_default_file = self.settings.globalSettingsPath() del (self.settings) try: os.unlink(settings_file) except: pass try: os.unlink(settings_default_file) except: pass def addToDefaults(self, key, value): self.globalsettings.setValue(key, value) self.globalsettings.sync() def addArrayToDefaults(self, prefix, key, values): defaults = QSettings(self.settings.globalSettingsPath(), QSettings.IniFormat) # NOQA self.globalsettings.beginWriteArray(prefix) i = 0 for v in values: self.globalsettings.setArrayIndex(i) self.globalsettings.setValue(key, v) i += 1 self.globalsettings.endArray() self.globalsettings.sync() def addGroupToDefaults(self, prefix, kvp): defaults = QSettings(self.settings.globalSettingsPath(), QSettings.IniFormat) # NOQA self.globalsettings.beginGroup(prefix) for k, v in kvp.items(): self.globalsettings.setValue(k, v) self.globalsettings.endGroup() self.globalsettings.sync() def test_basic_functionality(self): self.assertEqual( self.settings.value('testqgissettings/doesnotexists', 'notexist'), 'notexist') self.settings.setValue('testqgissettings/name', 'qgisrocks') self.settings.sync() self.assertEqual(self.settings.value('testqgissettings/name'), 'qgisrocks') def test_defaults(self): self.assertIsNone(self.settings.value('testqgissettings/name')) self.addToDefaults('testqgissettings/name', 'qgisrocks') self.assertEqual(self.settings.value('testqgissettings/name'), 'qgisrocks') def test_allkeys(self): self.assertEqual(self.settings.allKeys(), []) self.addToDefaults('testqgissettings/name', 'qgisrocks') self.addToDefaults('testqgissettings/name2', 'qgisrocks2') self.settings.setValue('nepoti/eman', 'osaple') self.assertEqual(3, len(self.settings.allKeys())) self.assertIn('testqgissettings/name', self.settings.allKeys()) self.assertIn('nepoti/eman', self.settings.allKeys()) self.assertEqual('qgisrocks', self.settings.value('testqgissettings/name')) self.assertEqual('qgisrocks2', self.settings.value('testqgissettings/name2')) self.assertEqual('qgisrocks', self.globalsettings.value('testqgissettings/name')) self.assertEqual('osaple', self.settings.value('nepoti/eman')) self.assertEqual(3, len(self.settings.allKeys())) self.assertEqual(2, len(self.globalsettings.allKeys())) def test_precedence_simple(self): self.assertEqual(self.settings.allKeys(), []) self.addToDefaults('testqgissettings/names/name1', 'qgisrocks1') self.settings.setValue('testqgissettings/names/name1', 'qgisrocks-1') self.assertEqual(self.settings.value('testqgissettings/names/name1'), 'qgisrocks-1') def test_precedence_group(self): """Test if user can override a group value""" self.assertEqual(self.settings.allKeys(), []) self.addGroupToDefaults( 'connections-xyz', { 'OSM': 'http://a.tile.openstreetmap.org/{z}/{x}/{y}.png', 'OSM-b': 'http://b.tile.openstreetmap.org/{z}/{x}/{y}.png', }) self.settings.beginGroup('connections-xyz') self.assertEqual(self.settings.value('OSM'), 'http://a.tile.openstreetmap.org/{z}/{x}/{y}.png') self.assertEqual(self.settings.value('OSM-b'), 'http://b.tile.openstreetmap.org/{z}/{x}/{y}.png') self.settings.endGroup() # Override edit self.settings.beginGroup('connections-xyz') self.settings.setValue( 'OSM', 'http://c.tile.openstreetmap.org/{z}/{x}/{y}.png') self.settings.endGroup() # Check it again! self.settings.beginGroup('connections-xyz') self.assertEqual(self.settings.value('OSM'), 'http://c.tile.openstreetmap.org/{z}/{x}/{y}.png') self.assertEqual(self.settings.value('OSM-b'), 'http://b.tile.openstreetmap.org/{z}/{x}/{y}.png') self.settings.endGroup() # Override remove: the global value will be resumed!!! self.settings.beginGroup('connections-xyz') self.settings.remove('OSM') self.settings.endGroup() # Check it again! self.settings.beginGroup('connections-xyz') self.assertEqual(self.settings.value('OSM'), 'http://a.tile.openstreetmap.org/{z}/{x}/{y}.png') self.assertEqual(self.settings.value('OSM-b'), 'http://b.tile.openstreetmap.org/{z}/{x}/{y}.png') self.settings.endGroup() # Override remove: store a blank! self.settings.beginGroup('connections-xyz') self.settings.setValue('OSM', '') self.settings.endGroup() # Check it again! self.settings.beginGroup('connections-xyz') self.assertEqual(self.settings.value('OSM'), '') self.assertEqual(self.settings.value('OSM-b'), 'http://b.tile.openstreetmap.org/{z}/{x}/{y}.png') self.settings.endGroup() # Override remove: store a None: will resume the global setting! self.settings.beginGroup('connections-xyz') self.settings.setValue('OSM', None) self.settings.endGroup() # Check it again! self.settings.beginGroup('connections-xyz') self.assertEqual(self.settings.value('OSM'), 'http://a.tile.openstreetmap.org/{z}/{x}/{y}.png') self.assertEqual(self.settings.value('OSM-b'), 'http://b.tile.openstreetmap.org/{z}/{x}/{y}.png') self.settings.endGroup() def test_uft8(self): self.assertEqual(self.settings.allKeys(), []) self.addToDefaults('testqgissettings/names/namèé↓1', 'qgisrocks↓1') self.assertEqual(self.settings.value('testqgissettings/names/namèé↓1'), 'qgisrocks↓1') self.settings.setValue('testqgissettings/names/namèé↓2', 'qgisrocks↓2') self.assertEqual(self.settings.value('testqgissettings/names/namèé↓2'), 'qgisrocks↓2') self.settings.setValue('testqgissettings/names/namèé↓1', 'qgisrocks↓-1') self.assertEqual(self.settings.value('testqgissettings/names/namèé↓1'), 'qgisrocks↓-1') def test_groups(self): self.assertEqual(self.settings.allKeys(), []) self.addToDefaults('testqgissettings/names/name1', 'qgisrocks1') self.addToDefaults('testqgissettings/names/name2', 'qgisrocks2') self.addToDefaults('testqgissettings/names/name3', 'qgisrocks3') self.addToDefaults('testqgissettings/name', 'qgisrocks') self.settings.beginGroup('testqgissettings') self.assertEqual(self.settings.group(), 'testqgissettings') self.assertEqual(['names'], self.settings.childGroups()) self.settings.setValue('surnames/name1', 'qgisrocks-1') self.assertEqual(['surnames', 'names'], self.settings.childGroups()) self.settings.setValue('names/name1', 'qgisrocks-1') self.assertEqual('qgisrocks-1', self.settings.value('names/name1')) self.settings.endGroup() self.assertEqual(self.settings.group(), '') self.settings.beginGroup('testqgissettings/names') self.assertEqual(self.settings.group(), 'testqgissettings/names') self.settings.setValue('name4', 'qgisrocks-4') keys = sorted(self.settings.childKeys()) self.assertEqual(keys, ['name1', 'name2', 'name3', 'name4']) self.settings.endGroup() self.assertEqual(self.settings.group(), '') self.assertEqual('qgisrocks-1', self.settings.value('testqgissettings/names/name1')) self.assertEqual('qgisrocks-4', self.settings.value('testqgissettings/names/name4')) def test_global_groups(self): self.assertEqual(self.settings.allKeys(), []) self.assertEqual(self.globalsettings.allKeys(), []) self.addToDefaults('testqgissettings/foo/first', 'qgis') self.addToDefaults('testqgissettings/foo/last', 'rocks') self.settings.beginGroup('testqgissettings') self.assertEqual(self.settings.group(), 'testqgissettings') self.assertEqual(['foo'], self.settings.childGroups()) self.assertEqual(['foo'], self.settings.globalChildGroups()) self.settings.endGroup() self.assertEqual(self.settings.group(), '') self.settings.setValue('testqgissettings/bar/first', 'qgis') self.settings.setValue('testqgissettings/bar/last', 'rocks') self.settings.beginGroup('testqgissettings') self.assertEqual(sorted(['bar', 'foo']), sorted(self.settings.childGroups())) self.assertEqual(['foo'], self.settings.globalChildGroups()) self.settings.endGroup() self.globalsettings.remove('testqgissettings/foo') self.settings.beginGroup('testqgissettings') self.assertEqual(['bar'], self.settings.childGroups()) self.assertEqual([], self.settings.globalChildGroups()) self.settings.endGroup() def test_group_section(self): # Test group by using Section self.settings.beginGroup('firstgroup', section=QgsSettings.Core) self.assertEqual(self.settings.group(), 'core/firstgroup') self.assertEqual([], self.settings.childGroups()) self.settings.setValue('key', 'value') self.settings.setValue('key2/subkey1', 'subvalue1') self.settings.setValue('key2/subkey2', 'subvalue2') self.settings.setValue('key3', 'value3') self.assertEqual(['key', 'key2/subkey1', 'key2/subkey2', 'key3'], self.settings.allKeys()) self.assertEqual(['key', 'key3'], self.settings.childKeys()) self.assertEqual(['key2'], self.settings.childGroups()) self.settings.endGroup() self.assertEqual(self.settings.group(), '') # Set value by writing the group manually self.settings.setValue('firstgroup/key4', 'value4', section=QgsSettings.Core) # Checking the value that have been set self.assertEqual( self.settings.value('firstgroup/key', section=QgsSettings.Core), 'value') self.assertEqual( self.settings.value('firstgroup/key2/subkey1', section=QgsSettings.Core), 'subvalue1') self.assertEqual( self.settings.value('firstgroup/key2/subkey2', section=QgsSettings.Core), 'subvalue2') self.assertEqual( self.settings.value('firstgroup/key3', section=QgsSettings.Core), 'value3') self.assertEqual( self.settings.value('firstgroup/key4', section=QgsSettings.Core), 'value4') # Clean up firstgroup self.settings.remove('firstgroup', section=QgsSettings.Core) def test_array(self): self.assertEqual(self.settings.allKeys(), []) self.addArrayToDefaults('testqgissettings', 'key', ['qgisrocks1', 'qgisrocks2', 'qgisrocks3']) self.assertEqual(self.settings.allKeys(), [ 'testqgissettings/1/key', 'testqgissettings/2/key', 'testqgissettings/3/key', 'testqgissettings/size' ]) self.assertEqual(self.globalsettings.allKeys(), [ 'testqgissettings/1/key', 'testqgissettings/2/key', 'testqgissettings/3/key', 'testqgissettings/size' ]) self.assertEqual( 3, self.globalsettings.beginReadArray('testqgissettings')) self.globalsettings.endArray() self.assertEqual(3, self.settings.beginReadArray('testqgissettings')) values = [] for i in range(3): self.settings.setArrayIndex(i) values.append(self.settings.value("key")) self.assertEqual(values, ['qgisrocks1', 'qgisrocks2', 'qgisrocks3']) def test_array_overrides(self): """Test if an array completely shadows the global one""" self.assertEqual(self.settings.allKeys(), []) self.addArrayToDefaults('testqgissettings', 'key', ['qgisrocks1', 'qgisrocks2', 'qgisrocks3']) self.assertEqual(self.settings.allKeys(), [ 'testqgissettings/1/key', 'testqgissettings/2/key', 'testqgissettings/3/key', 'testqgissettings/size' ]) self.assertEqual(self.globalsettings.allKeys(), [ 'testqgissettings/1/key', 'testqgissettings/2/key', 'testqgissettings/3/key', 'testqgissettings/size' ]) self.assertEqual( 3, self.globalsettings.beginReadArray('testqgissettings')) self.globalsettings.endArray() self.assertEqual(3, self.settings.beginReadArray('testqgissettings')) # Now override! self.settings.beginWriteArray('testqgissettings') self.settings.setArrayIndex(0) self.settings.setValue('key', 'myqgisrocksmore1') self.settings.setArrayIndex(1) self.settings.setValue('key', 'myqgisrocksmore2') self.settings.endArray() # Check it! self.assertEqual(2, self.settings.beginReadArray('testqgissettings')) values = [] for i in range(2): self.settings.setArrayIndex(i) values.append(self.settings.value("key")) self.assertEqual(values, ['myqgisrocksmore1', 'myqgisrocksmore2']) def test_section_getters_setters(self): self.assertEqual(self.settings.allKeys(), []) self.settings.setValue('key1', 'core1', section=QgsSettings.Core) self.settings.setValue('key2', 'core2', section=QgsSettings.Core) self.settings.setValue('key1', 'server1', section=QgsSettings.Server) self.settings.setValue('key2', 'server2', section=QgsSettings.Server) self.settings.setValue('key1', 'gui1', section=QgsSettings.Gui) self.settings.setValue('key2', 'gui2', QgsSettings.Gui) self.settings.setValue('key1', 'plugins1', section=QgsSettings.Plugins) self.settings.setValue('key2', 'plugins2', section=QgsSettings.Plugins) self.settings.setValue('key1', 'misc1', section=QgsSettings.Misc) self.settings.setValue('key2', 'misc2', section=QgsSettings.Misc) self.settings.setValue('key1', 'auth1', section=QgsSettings.Auth) self.settings.setValue('key2', 'auth2', section=QgsSettings.Auth) self.settings.setValue('key1', 'app1', section=QgsSettings.App) self.settings.setValue('key2', 'app2', section=QgsSettings.App) self.settings.setValue('key1', 'provider1', section=QgsSettings.Providers) self.settings.setValue('key2', 'provider2', section=QgsSettings.Providers) # This is an overwrite of previous setting and it is intentional self.settings.setValue('key1', 'auth1', section=QgsSettings.Auth) self.settings.setValue('key2', 'auth2', section=QgsSettings.Auth) # Test that the values are namespaced self.assertEqual(self.settings.value('core/key1'), 'core1') self.assertEqual(self.settings.value('core/key2'), 'core2') self.assertEqual(self.settings.value('server/key1'), 'server1') self.assertEqual(self.settings.value('server/key2'), 'server2') self.assertEqual(self.settings.value('gui/key1'), 'gui1') self.assertEqual(self.settings.value('gui/key2'), 'gui2') self.assertEqual(self.settings.value('plugins/key1'), 'plugins1') self.assertEqual(self.settings.value('plugins/key2'), 'plugins2') self.assertEqual(self.settings.value('misc/key1'), 'misc1') self.assertEqual(self.settings.value('misc/key2'), 'misc2') # Test getters self.assertEqual( self.settings.value('key1', None, section=QgsSettings.Core), 'core1') self.assertEqual( self.settings.value('key2', None, section=QgsSettings.Core), 'core2') self.assertEqual( self.settings.value('key1', None, section=QgsSettings.Server), 'server1') self.assertEqual( self.settings.value('key2', None, section=QgsSettings.Server), 'server2') self.assertEqual( self.settings.value('key1', None, section=QgsSettings.Gui), 'gui1') self.assertEqual( self.settings.value('key2', None, section=QgsSettings.Gui), 'gui2') self.assertEqual( self.settings.value('key1', None, section=QgsSettings.Plugins), 'plugins1') self.assertEqual( self.settings.value('key2', None, section=QgsSettings.Plugins), 'plugins2') self.assertEqual( self.settings.value('key1', None, section=QgsSettings.Misc), 'misc1') self.assertEqual( self.settings.value('key2', None, section=QgsSettings.Misc), 'misc2') self.assertEqual( self.settings.value('key1', None, section=QgsSettings.Auth), 'auth1') self.assertEqual( self.settings.value('key2', None, section=QgsSettings.Auth), 'auth2') self.assertEqual( self.settings.value('key1', None, section=QgsSettings.App), 'app1') self.assertEqual( self.settings.value('key2', None, section=QgsSettings.App), 'app2') self.assertEqual( self.settings.value('key1', None, section=QgsSettings.Providers), 'provider1') self.assertEqual( self.settings.value('key2', None, section=QgsSettings.Providers), 'provider2') # Test default values on Section getter self.assertEqual( self.settings.value('key_not_exist', 'misc_not_exist', section=QgsSettings.Misc), 'misc_not_exist') def test_contains(self): self.assertEqual(self.settings.allKeys(), []) self.addToDefaults('testqgissettings/name', 'qgisrocks1') self.addToDefaults('testqgissettings/name2', 'qgisrocks2') self.assertTrue(self.settings.contains('testqgissettings/name')) self.assertTrue(self.settings.contains('testqgissettings/name2')) self.settings.setValue('testqgissettings/name3', 'qgisrocks3') self.assertTrue(self.settings.contains('testqgissettings/name3')) def test_remove(self): self.settings.setValue('testQgisSettings/temp', True) self.assertEqual(self.settings.value('testQgisSettings/temp'), True) self.settings.remove('testQgisSettings/temp') self.assertEqual(self.settings.value('testqQgisSettings/temp'), None) # Test remove by using Section self.settings.setValue('testQgisSettings/tempSection', True, section=QgsSettings.Core) self.assertEqual( self.settings.value('testQgisSettings/tempSection', section=QgsSettings.Core), True) self.settings.remove('testQgisSettings/temp', section=QgsSettings.Core) self.assertEqual( self.settings.value('testqQgisSettings/temp', section=QgsSettings.Core), None) def test_enumValue(self): self.settings.setValue('enum', 'LayerUnits') self.assertEqual(self.settings.enumValue('enum', QgsTolerance.Pixels), QgsTolerance.LayerUnits) self.settings.setValue('enum', 'dummy_setting') self.assertEqual(self.settings.enumValue('enum', QgsTolerance.Pixels), QgsTolerance.Pixels) self.assertEqual( type(self.settings.enumValue('enum', QgsTolerance.Pixels)), QgsTolerance.UnitType) def test_setEnumValue(self): self.settings.setValue('enum', 'LayerUnits') self.assertEqual(self.settings.enumValue('enum', QgsTolerance.Pixels), QgsTolerance.LayerUnits) self.settings.setEnumValue('enum', QgsTolerance.Pixels) self.assertEqual(self.settings.enumValue('enum', QgsTolerance.Pixels), QgsTolerance.Pixels) def test_flagValue(self): pointAndLine = QgsMapLayerProxyModel.Filters( QgsMapLayerProxyModel.PointLayer | QgsMapLayerProxyModel.LineLayer) pointAndPolygon = QgsMapLayerProxyModel.Filters( QgsMapLayerProxyModel.PointLayer | QgsMapLayerProxyModel.PolygonLayer) self.settings.setValue('flag', 'PointLayer|PolygonLayer') self.assertEqual(self.settings.flagValue('flag', pointAndLine), pointAndPolygon) self.settings.setValue('flag', 'dummy_setting') self.assertEqual(self.settings.flagValue('flag', pointAndLine), pointAndLine) self.assertEqual(type(self.settings.flagValue('enum', pointAndLine)), QgsMapLayerProxyModel.Filters) def test_overwriteDefaultValues(self): """Test that unchanged values are not stored""" self.globalsettings.setValue('a_value_with_default', 'a value') self.globalsettings.setValue('an_invalid_value', QVariant()) self.assertEqual(self.settings.value('a_value_with_default'), 'a value') self.assertEqual(self.settings.value('an_invalid_value'), QVariant()) # Now, set them with the same current value self.settings.setValue('a_value_with_default', 'a value') self.settings.setValue('an_invalid_value', QVariant()) # Check pure_settings = QSettings(self.settings.fileName(), QSettings.IniFormat) self.assertFalse('a_value_with_default' in pure_settings.allKeys()) self.assertFalse('an_invalid_value' in pure_settings.allKeys()) # Set a changed value self.settings.setValue('a_value_with_default', 'a new value') self.settings.setValue('an_invalid_value', 'valid value') # Check self.assertTrue('a_value_with_default' in pure_settings.allKeys()) self.assertTrue('an_invalid_value' in pure_settings.allKeys()) self.assertEqual(self.settings.value('a_value_with_default'), 'a new value') self.assertEqual(self.settings.value('an_invalid_value'), 'valid value') # Re-set to original values self.settings.setValue('a_value_with_default', 'a value') self.settings.setValue('an_invalid_value', QVariant()) self.assertEqual(self.settings.value('a_value_with_default'), 'a value') self.assertEqual(self.settings.value('an_invalid_value'), QVariant()) # Check if they are gone pure_settings = QSettings(self.settings.fileName(), QSettings.IniFormat) self.assertFalse('a_value_with_default' not in pure_settings.allKeys()) self.assertFalse('an_invalid_value' not in pure_settings.allKeys())
class FieldRestrictionTypeUtilsMixin(): def __init__(self, iface): #RestrictionTypeUtilsMixin.__init__(self, iface) self.iface = iface self.settings = QgsSettings() self.params = gpsParams() #self.TOMsUtils = RestrictionTypeUtilsMixin(self.iface) def setDefaultFieldRestrictionDetails(self, currRestriction, currRestrictionLayer, currDate): TOMsMessageLog.logMessage("In setDefaultFieldRestrictionDetails: {}".format(currRestrictionLayer.name()), level=Qgis.Info) # TODO: Need to check whether or not these fields exist. Also need to retain the last values and reuse # gis.stackexchange.com/questions/138563/replacing-action-triggered-script-by-one-supplied-through-qgis-plugin try: currRestriction.setAttribute("LastUpdateDateTime", currDate) except Exception as e: TOMsMessageLog.logMessage("In setDefaultFieldRestrictionDetails. Problem with setting LastUpdateDateTime: {}".format(e), level=Qgis.Info) try: generateGeometryUtils.setRoadName(currRestriction) except Exception as e: TOMsMessageLog.logMessage("In setDefaultFieldRestrictionDetails. Problem with setting Road Name: {}".format(e), level=Qgis.Info) """if currRestrictionLayer.geometryType() == 1: # Line or Bay generateGeometryUtils.setAzimuthToRoadCentreLine(currRestriction) currRestriction.setAttribute("RestrictionLength", currRestriction.geometry().length())""" currentCPZ, cpzWaitingTimeID, cpzMatchDayTimePeriodID = generateGeometryUtils.getCurrentCPZDetails(currRestriction) """TOMsMessageLog.logMessage( "In setDefaultFieldRestrictionDetails. CPZ found: {}: control: {}".format(currentCPZ, cpzWaitingTimeID), level=Qgis.Warning)""" #currRestriction.setAttribute("CPZ", currentCPZ) newRestrictionID = str(uuid.uuid4()) currRestriction.setAttribute("RestrictionID", newRestrictionID) TOMsMessageLog.logMessage("In setDefaultFieldRestrictionDetails. newRestID: {}, {}".format(newRestrictionID, currRestriction[currRestrictionLayer.fields().indexFromName("RestrictionID")]), level=Qgis.Info) if currRestrictionLayer.name() == "Lines": currRestriction.setAttribute("RestrictionTypeID", self.readLastUsedDetails("Lines", "RestrictionTypeID", 201)) # 10 = SYL (Lines) currRestriction.setAttribute("GeomShapeID", self.readLastUsedDetails("Lines", "GeomShapeID", 10)) # 10 = Parallel Line currRestriction.setAttribute("NoWaitingTimeID", cpzWaitingTimeID) #currRestriction.setAttribute("NoLoadingTimeID", self.readLastUsedDetails("Lines", "NoLoadingTimeID", None)) #currRestriction.setAttribute("NoWTimeID", cpzWaitingTimeID) #currRestriction.setAttribute("CreateDateTime", currDate) currRestriction.setAttribute("UnacceptableTypeID", self.readLastUsedDetails("Lines", "UnacceptableTypeID", None)) generateGeometryUtils.setAzimuthToRoadCentreLine(currRestriction) currRestriction.setAttribute("RestrictionLength", currRestriction.geometry().length()) currRestriction.setAttribute("CPZ", currentCPZ) currRestriction.setAttribute("MatchDayTimePeriodID", cpzMatchDayTimePeriodID) currRestriction.setAttribute("ComplianceRestrictionSignIssue", 1) # No issue currRestriction.setAttribute("ComplianceRoadMarkingsFaded", 1) # No issue elif currRestrictionLayer.name() == "Bays": currRestriction.setAttribute("RestrictionTypeID", self.readLastUsedDetails("Bays", "RestrictionTypeID", 101)) # 28 = Permit Holders Bays (Bays) currRestriction.setAttribute("GeomShapeID", self.readLastUsedDetails("Bays", "GeomShapeID", 1)) # 21 = Parallel Bay (Polygon) currRestriction.setAttribute("NrBays", -1) currRestriction.setAttribute("TimePeriodID", cpzWaitingTimeID) #currRestriction.setAttribute("MaxStayID", ptaMaxStayID) #currRestriction.setAttribute("NoReturnID", ptaNoReturnTimeID) #currRestriction.setAttribute("ParkingTariffArea", currentPTA) #currRestriction.setAttribute("CreateDateTime", currDate) generateGeometryUtils.setAzimuthToRoadCentreLine(currRestriction) currRestriction.setAttribute("RestrictionLength", currRestriction.geometry().length()) currRestriction.setAttribute("CPZ", currentCPZ) currRestriction.setAttribute("MatchDayTimePeriodID", cpzMatchDayTimePeriodID) currRestriction.setAttribute("ComplianceRestrictionSignIssue", 1) # No issue currRestriction.setAttribute("ComplianceRoadMarkingsFaded", 1) # No issue try: payParkingAreasLayer = QgsProject.instance().mapLayersByName("PayParkingAreas")[0] currPayParkingArea = generateGeometryUtils.getPolygonForRestriction(currRestriction, payParkingAreasLayer) currRestriction.setAttribute("PayParkingAreaID", currPayParkingArea.attribute("Code")) except Exception as e: TOMsMessageLog.logMessage( "In setDefaultFieldRestrictionDetails. issue obtaining PayParkingAreaID: {}".format(e), level=Qgis.Info) elif currRestrictionLayer.name() == "Signs": currRestriction.setAttribute("SignType_1", self.readLastUsedDetails("Signs", "SignType_1", 28)) # 28 = Permit Holders Only (Signs) currRestriction.setAttribute("SignOrientationTypeID", 3) currRestriction.setAttribute("SignConditionTypeID", 1) # 1 = Good currRestriction.setAttribute("ComplianceRestrictionSignIssue", 1) # No issue elif currRestrictionLayer.name() == "RestrictionPolygons": currRestriction.setAttribute("RestrictionTypeID", self.readLastUsedDetails("RestrictionPolygons", "RestrictionTypeID", 4)) # 28 = Residential mews area (RestrictionPolygons) currRestriction.setAttribute("CPZ", currentCPZ) currRestriction.setAttribute("MatchDayTimePeriodID", cpzMatchDayTimePeriodID) currRestriction.setAttribute("GeomShapeID", self.readLastUsedDetails("Lines", "GeomShapeID", 50)) # 10 = Parallel Line currRestriction.setAttribute("ComplianceRestrictionSignIssue", 1) # No issue currRestriction.setAttribute("ComplianceRoadMarkingsFaded", 1) # No issue elif currRestrictionLayer.name() == "CrossingPoints": generateGeometryUtils.setAzimuthToRoadCentreLine(currRestriction) currRestriction.setAttribute("GeomShapeID", 35) # 35 = Crossover # set compliance defaults try: currRestriction.setAttribute("ComplianceRoadMarkingsFaded", 1) # No issue except Exception as e: TOMsMessageLog.logMessage("In setDefaultFieldRestrictionDetails. Problem with setting ComplianceRoadMarkingsFaded: {}".format(e), level=Qgis.Info) try: currRestriction.setAttribute("ComplianceRestrictionSignIssue", 1) # No issue except Exception as e: TOMsMessageLog.logMessage("In setDefaultFieldRestrictionDetails. Problem with setting ComplianceRestrictionSignIssue: {}".format(e), level=Qgis.Info) # update feature #currRestrictionLayer.updateFeature(currRestriction) def storeLastUsedDetails(self, layer, field, value): entry = '{layer}/{field}'.format(layer=layer, field=field) TOMsMessageLog.logMessage("In storeLastUsedDetails: " + str(entry) + " (" + str(value) + ")", level=Qgis.Info) self.settings.setValue(entry, value) def readLastUsedDetails(self, layer, field, default): entry = '{layer}/{field}'.format(layer=layer, field=field) TOMsMessageLog.logMessage("In readLastUsedDetails: " + str(entry) + " (" + str(default) + ")", level=Qgis.Info) return self.settings.value(entry, default) def setupFieldRestrictionDialog(self, restrictionDialog, currRestrictionLayer, currRestriction): #self.restrictionDialog = restrictionDialog #self.currRestrictionLayer = currRestrictionLayer #self.currRestriction = currRestriction #self.restrictionTransaction = restrictionTransaction self.params.getParams() # Create a copy of the feature self.origFeature = originalFeature() self.origFeature.setFeature(currRestriction) if restrictionDialog is None: reply = QMessageBox.information(None, "Error", "setupFieldRestrictionDialog. Correct form not found", QMessageBox.Ok) TOMsMessageLog.logMessage( "In setupRestrictionDialog. dialog not found", level=Qgis.Warning) return restrictionDialog.attributeForm().disconnectButtonBox() button_box = restrictionDialog.findChild(QDialogButtonBox, "button_box") if button_box is None: TOMsMessageLog.logMessage( "In setupRestrictionDialog. button box not found", level=Qgis.Warning) return button_box.accepted.connect(functools.partial(self.onSaveFieldRestrictionDetails, currRestriction, currRestrictionLayer, restrictionDialog)) button_box.rejected.connect(functools.partial(self.onRejectFieldRestrictionDetailsFromForm, restrictionDialog, currRestrictionLayer)) restrictionDialog.attributeForm().attributeChanged.connect(functools.partial(self.onAttributeChangedClass2_local, currRestriction, currRestrictionLayer)) self.photoDetails_field(restrictionDialog, currRestrictionLayer, currRestriction) self.addScrollBars(restrictionDialog) """def onSaveRestrictionDetailsFromForm(self): TOMsMessageLog.logMessage("In onSaveRestrictionDetailsFromForm", level=Qgis.Info) self.onSaveRestrictionDetails(self.currRestriction, self.currRestrictionLayer, self.restrictionDialog, self.restrictionTransaction)""" def onAttributeChangedClass2_local(self, currFeature, layer, fieldName, value): #self.TOMsUtils.onAttributeChangedClass2(currFeature, layer, fieldName, value) TOMsMessageLog.logMessage( "In field:FormOpen:onAttributeChangedClass 2 - layer: " + str(layer.name()) + " (" + fieldName + "): " + str(value), level=Qgis.Info) # self.currRestriction.setAttribute(fieldName, value) try: currFeature[layer.fields().indexFromName(fieldName)] = value #currFeature.setAttribute(layer.fields().indexFromName(fieldName), value) except Exception as e: reply = QMessageBox.information(None, "Error", "onAttributeChangedClass2. Update failed for: " + str(layer.name()) + " (" + fieldName + "): " + str(value), QMessageBox.Ok) # rollback all changes self.storeLastUsedDetails(layer.name(), fieldName, value) return def onSaveFieldRestrictionDetails(self, currFeature, currFeatureLayer, dialog): TOMsMessageLog.logMessage("In onSaveFieldRestrictionDetails: ", level=Qgis.Info) try: self.camera1.endCamera() self.camera2.endCamera() self.camera3.endCamera() except: None attrs1 = currFeature.attributes() TOMsMessageLog.logMessage("In onSaveDemandDetails: currRestriction: " + str(attrs1), level=Qgis.Warning) TOMsMessageLog.logMessage( ("In onSaveDemandDetails. geometry: " + str(currFeature.geometry().asWkt())), level=Qgis.Warning) currFeatureID = currFeature.id() TOMsMessageLog.logMessage("In onSaveDemandDetails: currFeatureID: " + str(currFeatureID), level=Qgis.Warning) status = currFeatureLayer.updateFeature(currFeature) TOMsMessageLog.logMessage("In onSaveDemandDetails: feature updated: " + str(currFeatureID), level=Qgis.Warning) """if currFeatureID > 0: # Not sure what this value should if the feature has not been created ... # TODO: Sort out this for UPDATE self.setDefaultRestrictionDetails(currFeature, currFeatureLayer) status = currFeatureLayer.updateFeature(currFeature) TOMsMessageLog.logMessage("In onSaveDemandDetails: updated Feature: ", level=Qgis.Info) else: status = currFeatureLayer.addFeature(currFeature) TOMsMessageLog.logMessage("In onSaveDemandDetails: added Feature: " + str(status), level=Qgis.Info)""" status = dialog.attributeForm().close() TOMsMessageLog.logMessage("In onSaveDemandDetails: dialog saved: " + str(currFeatureID), level=Qgis.Warning) #currRestrictionLayer.addFeature(currRestriction) # TH (added for v3) #status = currFeatureLayer.updateFeature(currFeature) # TH (added for v3) try: currFeatureLayer.commitChanges() except Exception as e: reply = QMessageBox.information(None, "Information", "Problem committing changes: {}".format(e), QMessageBox.Ok) #currFeatureLayer.blockSignals(False) TOMsMessageLog.logMessage("In onSaveDemandDetails: changes committed", level=Qgis.Info) status = dialog.close() #self.mapTool = None #self.iface.mapCanvas().unsetMapTool(self.iface.mapCanvas().mapTool()) def onRejectFieldRestrictionDetailsFromForm(self, restrictionDialog, currFeatureLayer): TOMsMessageLog.logMessage("In onRejectFieldRestrictionDetailsFromForm", level=Qgis.Info) try: self.camera1.endCamera() self.camera2.endCamera() self.camera3.endCamera() except: None currFeatureLayer.rollBack() restrictionDialog.reject() #del self.mapTool def photoDetails_field(self, restrictionDialog, currRestrictionLayer, currRestriction): # Function to deal with photo fields self.demandDialog = restrictionDialog self.currDemandLayer = currRestrictionLayer self.currFeature = currRestriction TOMsMessageLog.logMessage("In photoDetails", level=Qgis.Info) photoPath = QgsExpressionContextUtils.projectScope(QgsProject.instance()).variable('PhotoPath') projectFolder = QgsExpressionContextUtils.projectScope(QgsProject.instance()).variable('project_folder') path_absolute = os.path.join(projectFolder, photoPath) if path_absolute == None: reply = QMessageBox.information(None, "Information", "Please set value for PhotoPath.", QMessageBox.Ok) return # Check path exists ... if os.path.isdir(path_absolute) == False: reply = QMessageBox.information(None, "Information", "PhotoPath folder " + str( path_absolute) + " does not exist. Please check value.", QMessageBox.Ok) return # if cv2 is available, check camera nr try: cameraNr = int(self.params.setParam("CameraNr")) except Exception as e: TOMsMessageLog.logMessage("In photoDetails_field: cameraNr issue: {}".format(e), level=Qgis.Info) if cv2_available: cameraNr = QMessageBox.information(None, "Information", "Please set value for CameraNr.", QMessageBox.Ok) cameraNr = None TOMsMessageLog.logMessage("In photoDetails_field: cameraNr is: {}".format(cameraNr), level=Qgis.Info) layerName = self.currDemandLayer.name() # Generate the full path to the file fileName1 = "Photos_01" fileName2 = "Photos_02" fileName3 = "Photos_03" idx1 = self.currDemandLayer.fields().indexFromName(fileName1) idx2 = self.currDemandLayer.fields().indexFromName(fileName2) idx3 = self.currDemandLayer.fields().indexFromName(fileName3) TOMsMessageLog.logMessage("In photoDetails. idx1: " + str(idx1) + "; " + str(idx2) + "; " + str(idx3), level=Qgis.Info) if cameraNr is not None: TOMsMessageLog.logMessage("Camera TRUE", level=Qgis.Info) takePhoto = True else: TOMsMessageLog.logMessage("Camera FALSE", level=Qgis.Info) takePhoto = False FIELD1 = self.demandDialog.findChild(QLabel, "Photo_Widget_01") FIELD2 = self.demandDialog.findChild(QLabel, "Photo_Widget_02") FIELD3 = self.demandDialog.findChild(QLabel, "Photo_Widget_03") if FIELD1: TOMsMessageLog.logMessage("In photoDetails. FIELD 1 exists", level=Qgis.Info) if self.currFeature[idx1]: newPhotoFileName1 = os.path.join(path_absolute, self.currFeature[idx1]) TOMsMessageLog.logMessage("In photoDetails. photo1: {}".format(newPhotoFileName1), level=Qgis.Info) else: newPhotoFileName1 = None pixmap1 = QPixmap(newPhotoFileName1) if pixmap1.isNull(): pass # FIELD1.setText('Picture could not be opened ({path})'.format(path=newPhotoFileName1)) else: tab = FIELD1.parentWidget() grid = FIELD1.parentWidget().layout() photo_Widget1 = imageLabel(tab) TOMsMessageLog.logMessage( "In photoDetails. FIELD 1 w: {}; h: {}".format(FIELD1.width(), FIELD1.height()), level=Qgis.Info) photo_Widget1.setObjectName("Photo_Widget_01") photo_Widget1.setText("No photo is here") #photo_Widget1 = imageLabel(tab) grid.addWidget(photo_Widget1, 0, 0, 1, 1) FIELD1.hide() FIELD1.setParent(None) FIELD1 = photo_Widget1 FIELD1.set_Pixmap(pixmap1) TOMsMessageLog.logMessage("In photoDetails. FIELD 1 Photo1: " + str(newPhotoFileName1), level=Qgis.Info) TOMsMessageLog.logMessage("In photoDetails.pixmap1 size: {}".format(pixmap1.size()), level=Qgis.Info) FIELD1.pixmapUpdated.connect(functools.partial(self.displayPixmapUpdated, FIELD1)) #ZOOM_IN_1 = self.demandDialog.findChild(QPushButton, "pb_zoomIn_01") #ZOOM_IN_1.clicked.connect(FIELD1._zoomInButton) #ZOOM_OUT_1 = self.demandDialog.findChild(QPushButton, "pb_zoomOut_01") #ZOOM_OUT_1.clicked.connect(FIELD1._zoomOutButton) if takePhoto: START_CAMERA_1 = self.demandDialog.findChild(QPushButton, "startCamera1") TAKE_PHOTO_1 = self.demandDialog.findChild(QPushButton, "getPhoto1") TAKE_PHOTO_1.setEnabled(False) self.camera1 = formCamera(path_absolute, newPhotoFileName1, cameraNr) START_CAMERA_1.clicked.connect( functools.partial(self.camera1.useCamera, START_CAMERA_1, TAKE_PHOTO_1, FIELD1)) self.camera1.notifyPhotoTaken.connect(functools.partial(self.savePhotoTaken, idx1)) if FIELD2: TOMsMessageLog.logMessage("In photoDetails. FIELD 2 exisits", level=Qgis.Info) if self.currFeature[idx2]: newPhotoFileName2 = os.path.join(path_absolute, self.currFeature[idx2]) TOMsMessageLog.logMessage("In photoDetails. Photo1: " + str(newPhotoFileName2), level=Qgis.Info) else: newPhotoFileName2 = None # newPhotoFileName2 = os.path.join(path_absolute, str(self.currFeature[idx2])) # newPhotoFileName2 = os.path.join(path_absolute, str(self.currFeature.attribute(fileName2))) # TOMsMessageLog.logMessage("In photoDetails. Photo2: " + str(newPhotoFileName2), level=Qgis.Info) pixmap2 = QPixmap(newPhotoFileName2) if pixmap2.isNull(): pass # FIELD1.setText('Picture could not be opened ({path})'.format(path=newPhotoFileName1)) else: tab = FIELD2.parentWidget() grid = FIELD2.parentWidget().layout() photo_Widget2 = imageLabel(tab) TOMsMessageLog.logMessage( "In photoDetails. FIELD 2 w: {}; h: {}".format(FIELD2.width(), FIELD2.height()), level=Qgis.Info) photo_Widget2.setObjectName("Photo_Widget_02") photo_Widget2.setText("No photo is here") #photo_Widget2 = imageLabel(tab) grid.addWidget(photo_Widget2, 0, 0, 1, 1) FIELD2.hide() FIELD2.setParent(None) FIELD2 = photo_Widget2 FIELD2.set_Pixmap(pixmap2) TOMsMessageLog.logMessage("In photoDetails. FIELD 2 Photo2: " + str(newPhotoFileName2), level=Qgis.Info) TOMsMessageLog.logMessage("In photoDetails.pixmap2 size: {}".format(pixmap2.size()), level=Qgis.Info) FIELD2.pixmapUpdated.connect(functools.partial(self.displayPixmapUpdated, FIELD2)) #ZOOM_IN_2 = self.demandDialog.findChild(QPushButton, "pb_zoomIn_02") #ZOOM_IN_2.clicked.connect(FIELD2._zoomInButton) #ZOOM_OUT_2 = self.demandDialog.findChild(QPushButton, "pb_zoomOut_02") #ZOOM_OUT_2.clicked.connect(FIELD2._zoomOutButton) """ FIELD2.setPixmap(pixmap2) FIELD2.setScaledContents(True) TOMsMessageLog.logMessage("In photoDetails. Photo2: " + str(newPhotoFileName2), level=Qgis.Info)""" if takePhoto: START_CAMERA_2 = self.demandDialog.findChild(QPushButton, "startCamera2") TAKE_PHOTO_2 = self.demandDialog.findChild(QPushButton, "getPhoto2") TAKE_PHOTO_2.setEnabled(False) self.camera2 = formCamera(path_absolute, newPhotoFileName2, cameraNr) START_CAMERA_2.clicked.connect( functools.partial(self.camera2.useCamera, START_CAMERA_2, TAKE_PHOTO_2, FIELD2)) self.camera2.notifyPhotoTaken.connect(functools.partial(self.savePhotoTaken, idx2)) if FIELD3: TOMsMessageLog.logMessage("In photoDetails. FIELD 3 exisits", level=Qgis.Info) if self.currFeature[idx3]: newPhotoFileName3 = os.path.join(path_absolute, self.currFeature[idx3]) TOMsMessageLog.logMessage("In photoDetails. Photo1: " + str(newPhotoFileName3), level=Qgis.Info) else: newPhotoFileName3 = None # newPhotoFileName3 = os.path.join(path_absolute, str(self.currFeature[idx3])) # newPhotoFileName3 = os.path.join(path_absolute, # str(self.currFeature.attribute(fileName3))) # newPhotoFileName3 = os.path.join(path_absolute, str(layerName + "_Photos_03")) # TOMsMessageLog.logMessage("In photoDetails. Photo3: " + str(newPhotoFileName3), level=Qgis.Info) pixmap3 = QPixmap(newPhotoFileName3) if pixmap3.isNull(): pass # FIELD1.setText('Picture could not be opened ({path})'.format(path=newPhotoFileName1)) else: tab = FIELD3.parentWidget() grid = FIELD3.parentWidget().layout() photo_Widget3 = imageLabel(tab) TOMsMessageLog.logMessage( "In photoDetails. FIELD 3 w: {}; h: {}".format(FIELD3.width(), FIELD3.height()), level=Qgis.Info) photo_Widget3.setObjectName("Photo_Widget_03") photo_Widget3.setText("No photo is here") #photo_Widget3 = imageLabel(tab) grid.addWidget(photo_Widget3, 0, 0, 1, 1) FIELD3.hide() FIELD3.setParent(None) FIELD3 = photo_Widget3 FIELD3.set_Pixmap(pixmap3) TOMsMessageLog.logMessage("In photoDetails. FIELD 3 Photo3: " + str(newPhotoFileName3), level=Qgis.Info) TOMsMessageLog.logMessage("In photoDetails.pixmap3 size: {}".format(pixmap3.size()), level=Qgis.Info) FIELD3.pixmapUpdated.connect(functools.partial(self.displayPixmapUpdated, FIELD3)) #ZOOM_IN_3 = self.demandDialog.findChild(QPushButton, "pb_zoomIn_03") #ZOOM_IN_3.clicked.connect(FIELD3._zoomInButton) #ZOOM_OUT_3 = self.demandDialog.findChild(QPushButton, "pb_zoomOut_03") #ZOOM_OUT_3.clicked.connect(FIELD3._zoomOutButton) """FIELD3.setPixmap(pixmap3) FIELD3.setScaledContents(True) TOMsMessageLog.logMessage("In photoDetails. Photo3: " + str(newPhotoFileName3), level=Qgis.Info)""" if takePhoto: START_CAMERA_3 = self.demandDialog.findChild(QPushButton, "startCamera3") TAKE_PHOTO_3 = self.demandDialog.findChild(QPushButton, "getPhoto3") TAKE_PHOTO_3.setEnabled(False) self.camera3 = formCamera(path_absolute, newPhotoFileName3, cameraNr) START_CAMERA_3.clicked.connect( functools.partial(self.camera3.useCamera, START_CAMERA_3, TAKE_PHOTO_3, FIELD3)) self.camera3.notifyPhotoTaken.connect(functools.partial(self.savePhotoTaken, idx3)) pass def addScrollBars(self, restrictionDialog): TOMsMessageLog.logMessage("In addScrollBars", level=Qgis.Info) # find any combo boxes in the form and add the scroll bar childWidgetList = restrictionDialog.findChildren(QComboBox) #button_box = restrictionDialog.findChild(QDialogButtonBox, "button_box") for formWidget in childWidgetList: TOMsMessageLog.logMessage("In addScrollBars: widget type {}".format(type(formWidget)), level=Qgis.Info) if isinstance(formWidget, QComboBox): #print('WidgetName: {}'.format(formWidget.objectName())) formWidget.setStyleSheet("QComboBox { combobox-popup: 0; }") formWidget.setMaxVisibleItems(10) formWidget.view().setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) return def getLookupDescription(self, lookupLayer, code): #TOMsMessageLog.logMessage("In getLookupDescription", level=Qgis.Info) query = "\"Code\" = " + str(code) request = QgsFeatureRequest().setFilterExpression(query) #TOMsMessageLog.logMessage("In getLookupDescription. queryStatus: " + str(query), level=Qgis.Info) for row in lookupLayer.getFeatures(request): #TOMsMessageLog.logMessage("In getLookupDescription: found row " + str(row.attribute("Description")), level=Qgis.Info) return row.attribute("Description") # make assumption that only one row return None @pyqtSlot(QPixmap) def displayPixmapUpdated(self, FIELD, pixmap): TOMsMessageLog.logMessage("In utils::displayPixmapUpdated ... ", level=Qgis.Info) FIELD.setPixmap(pixmap) FIELD.setScaledContents(True) QApplication.processEvents() # processes the event queue - https://stackoverflow.com/questions/43094589/opencv-imshow-prevents-qt-python-crashing """"@pyqtSlot(QPixmap) def displayFrame(self, pixmap): TOMsMessageLog.logMessage("In formCamera::displayFrame ... ", level=Qgis.Info) self.FIELD.setPixmap(pixmap) self.FIELD.setScaledContents(True) QApplication.processEvents() # processes the event queue - https://stackoverflow.com/questions/43094589/opencv-imshow-prevents-qt-python-crashing""" @pyqtSlot(str) def savePhotoTaken(self, idx, fileName): TOMsMessageLog.logMessage("In demandFormUtils::savePhotoTaken ... " + fileName + " idx: " + str(idx), level=Qgis.Info) if len(fileName) > 0: simpleFile = os.path.basename(fileName) TOMsMessageLog.logMessage("In demandFormUtils::savePhotoTaken. Simple file: " + simpleFile, level=Qgis.Info) try: self.currFeature[idx] = simpleFile TOMsMessageLog.logMessage("In demandFormUtils::savePhotoTaken. attrib value changed", level=Qgis.Info) except: TOMsMessageLog.logMessage("In demandFormUtils::savePhotoTaken. problem changing attrib value", level=Qgis.Info) reply = QMessageBox.information(None, "Error", "savePhotoTaken. problem changing attrib value", QMessageBox.Ok) def store_gnss_pts(self, curr_gps_location, curr_gps_info): TOMsMessageLog.logMessage("In gnssTools.store_gnss_pts ", level=Qgis.Info) GNSS_Pts_Layer = self.tableNames.setLayer("GNSS_Pts") try: GNSS_Pts_Layer.startEditing() except Exception as e: reply = QMessageBox.information(None, "Information", "Problem starting edit session on GNSS_Pts: {}".format(e), QMessageBox.Ok) TOMsMessageLog.logMessage("Problem starting edit session on GNSS_Pts: {}".format(e), level=Qgis.Warning) return False fields = GNSS_Pts_Layer.fields() feature = QgsFeature() feature.setFields(fields) feature.setGeometry(QgsGeometry.fromPointXY(curr_gps_location)) for gnssField in dir(curr_gps_info): #TOMsMessageLog.logMessage ('Attribute: {}'.format(gnssField), level=Qgis.Warning) if gnssField in fields.names(): value = getattr(curr_gps_info, gnssField) TOMsMessageLog.logMessage ('** Found {}: {}'.format(gnssField, value), level=Qgis.Info) if GNSS_Pts_Layer.fields().field(gnssField).isNumeric(): if math.isnan(value): # https://stackoverflow.com/questions/944700/how-can-i-check-for-nan-values value = None feature[GNSS_Pts_Layer.fields().indexFromName(gnssField)] = value #attrs = feature.attributes() #TOMsMessageLog.logMessage('--Attribs {}'.format(attrs), level=Qgis.Warning) GNSS_Pts_Layer.addFeatures([feature]) try: GNSS_Pts_Layer.commitChanges() except Exception as e: reply = QMessageBox.information(None, "Information", "Problem committing changes to GNSS_Pts: {}".format(e), QMessageBox.Ok) TOMsMessageLog.logMessage("Problem committing changes to GNSS_Pts: {}".format(e), level=Qgis.Warning) return False return True
def addConnectionConfig(cls, conn_name, uri): """Necessary to allow db_manager to have the list of connections get from settings.""" uri = QgsDataSourceUri(uri) settings = QgsSettings() baseKey = "/PostgreSQL/connections/" baseKey += conn_name settings.setValue(baseKey + "/service", uri.service()) settings.setValue(baseKey + "/host", uri.host()) settings.setValue(baseKey + "/port", uri.port()) settings.setValue(baseKey + "/database", uri.database()) if uri.username(): settings.setValue(baseKey + "/username", uri.username()) if uri.password(): settings.setValue(baseKey + "/password", uri.password()) if uri.authConfigId(): settings.setValue(baseKey + "/authcfg", uri.authConfigId()) if uri.sslMode(): settings.setValue(baseKey + "/sslmode", uri.sslMode())
class MetaSearchDialog(QDialog, BASE_CLASS): """main dialogue""" def __init__(self, iface): """init window""" QDialog.__init__(self) self.setupUi(self) self.iface = iface self.map = iface.mapCanvas() self.settings = QgsSettings() self.catalog = None self.catalog_url = None self.catalog_username = None self.catalog_password = None self.context = StaticContext() self.leKeywords.setShowSearchIcon(True) self.leKeywords.setPlaceholderText(self.tr('Search keywords')) self.setWindowTitle(self.tr('MetaSearch')) self.rubber_band = QgsRubberBand(self.map, True) # True = a polygon self.rubber_band.setColor(QColor(255, 0, 0, 75)) self.rubber_band.setWidth(5) # form inputs self.startfrom = 0 self.maxrecords = 10 self.timeout = 10 self.constraints = [] # Servers tab self.cmbConnectionsServices.activated.connect(self.save_connection) self.cmbConnectionsSearch.activated.connect(self.save_connection) self.btnServerInfo.clicked.connect(self.connection_info) self.btnAddDefault.clicked.connect(self.add_default_connections) self.btnCapabilities.clicked.connect(self.show_xml) self.tabWidget.currentChanged.connect(self.populate_connection_list) # server management buttons self.btnNew.clicked.connect(self.add_connection) self.btnEdit.clicked.connect(self.edit_connection) self.btnDelete.clicked.connect(self.delete_connection) self.btnLoad.clicked.connect(self.load_connections) self.btnSave.clicked.connect(save_connections) # Search tab self.treeRecords.itemSelectionChanged.connect(self.record_clicked) self.treeRecords.itemDoubleClicked.connect(self.show_metadata) self.btnSearch.clicked.connect(self.search) self.leKeywords.returnPressed.connect(self.search) # prevent dialog from closing upon pressing enter self.buttonBox.button(QDialogButtonBox.Close).setAutoDefault(False) # launch help from button self.buttonBox.helpRequested.connect(self.help) self.btnCanvasBbox.setAutoDefault(False) self.btnCanvasBbox.clicked.connect(self.set_bbox_from_map) self.btnGlobalBbox.clicked.connect(self.set_bbox_global) # navigation buttons self.btnFirst.clicked.connect(self.navigate) self.btnPrev.clicked.connect(self.navigate) self.btnNext.clicked.connect(self.navigate) self.btnLast.clicked.connect(self.navigate) self.mActionAddWms.triggered.connect(self.add_to_ows) self.mActionAddWfs.triggered.connect(self.add_to_ows) self.mActionAddWcs.triggered.connect(self.add_to_ows) self.mActionAddAms.triggered.connect(self.add_to_ows) self.mActionAddAfs.triggered.connect(self.add_to_ows) self.mActionAddGisFile.triggered.connect(self.add_gis_file) self.btnShowXml.clicked.connect(self.show_xml) self.manageGui() def manageGui(self): """open window""" self.tabWidget.setCurrentIndex(0) self.populate_connection_list() self.btnCapabilities.setEnabled(False) self.spnRecords.setValue( int(self.settings.value('/MetaSearch/returnRecords', 10))) key = '/MetaSearch/%s' % self.cmbConnectionsSearch.currentText() self.catalog_url = self.settings.value('%s/url' % key) self.catalog_username = self.settings.value('%s/username' % key) self.catalog_password = self.settings.value('%s/password' % key) self.set_bbox_global() self.reset_buttons() # install proxy handler if specified in QGIS settings self.install_proxy() # Servers tab def populate_connection_list(self): """populate select box with connections""" self.settings.beginGroup('/MetaSearch/') self.cmbConnectionsServices.clear() self.cmbConnectionsServices.addItems(self.settings.childGroups()) self.cmbConnectionsSearch.clear() self.cmbConnectionsSearch.addItems(self.settings.childGroups()) self.settings.endGroup() self.set_connection_list_position() if self.cmbConnectionsServices.count() == 0: # no connections - disable various buttons state_disabled = False self.btnSave.setEnabled(state_disabled) # and start with connection tab open self.tabWidget.setCurrentIndex(1) # tell the user to add services msg = self.tr('No services/connections defined. To get ' 'started with MetaSearch, create a new ' 'connection by clicking \'New\' or click ' '\'Add default services\'.') self.textMetadata.setHtml('<p><h3>%s</h3></p>' % msg) else: # connections - enable various buttons state_disabled = True self.btnServerInfo.setEnabled(state_disabled) self.btnEdit.setEnabled(state_disabled) self.btnDelete.setEnabled(state_disabled) def set_connection_list_position(self): """set the current index to the selected connection""" to_select = self.settings.value('/MetaSearch/selected') conn_count = self.cmbConnectionsServices.count() if conn_count == 0: self.btnDelete.setEnabled(False) self.btnServerInfo.setEnabled(False) self.btnEdit.setEnabled(False) # does to_select exist in cmbConnectionsServices? exists = False for i in range(conn_count): if self.cmbConnectionsServices.itemText(i) == to_select: self.cmbConnectionsServices.setCurrentIndex(i) self.cmbConnectionsSearch.setCurrentIndex(i) exists = True break # If we couldn't find the stored item, but there are some, default # to the last item (this makes some sense when deleting items as it # allows the user to repeatidly click on delete to remove a whole # lot of items) if not exists and conn_count > 0: # If to_select is null, then the selected connection wasn't found # by QgsSettings, which probably means that this is the first time # the user has used CSWClient, so default to the first in the list # of connetions. Otherwise default to the last. if not to_select: current_index = 0 else: current_index = conn_count - 1 self.cmbConnectionsServices.setCurrentIndex(current_index) self.cmbConnectionsSearch.setCurrentIndex(current_index) def save_connection(self): """save connection""" caller = self.sender().objectName() if caller == 'cmbConnectionsServices': # servers tab current_text = self.cmbConnectionsServices.currentText() elif caller == 'cmbConnectionsSearch': # search tab current_text = self.cmbConnectionsSearch.currentText() self.settings.setValue('/MetaSearch/selected', current_text) key = '/MetaSearch/%s' % current_text if caller == 'cmbConnectionsSearch': # bind to service in search tab self.catalog_url = self.settings.value('%s/url' % key) self.catalog_username = self.settings.value('%s/username' % key) self.catalog_password = self.settings.value('%s/password' % key) if caller == 'cmbConnectionsServices': # clear server metadata self.textMetadata.clear() self.btnCapabilities.setEnabled(False) def connection_info(self): """show connection info""" current_text = self.cmbConnectionsServices.currentText() key = '/MetaSearch/%s' % current_text self.catalog_url = self.settings.value('%s/url' % key) self.catalog_username = self.settings.value('%s/username' % key) self.catalog_password = self.settings.value('%s/password' % key) # connect to the server if not self._get_csw(): return if self.catalog: # display service metadata self.btnCapabilities.setEnabled(True) metadata = render_template('en', self.context, self.catalog, 'service_metadata.html') style = QgsApplication.reportStyleSheet() self.textMetadata.clear() self.textMetadata.document().setDefaultStyleSheet(style) self.textMetadata.setHtml(metadata) def add_connection(self): """add new service""" conn_new = NewConnectionDialog() conn_new.setWindowTitle(self.tr('New Catalog Service')) if conn_new.exec_() == QDialog.Accepted: # add to service list self.populate_connection_list() self.textMetadata.clear() def edit_connection(self): """modify existing connection""" current_text = self.cmbConnectionsServices.currentText() url = self.settings.value('/MetaSearch/%s/url' % current_text) conn_edit = NewConnectionDialog(current_text) conn_edit.setWindowTitle(self.tr('Edit Catalog Service')) conn_edit.leName.setText(current_text) conn_edit.leURL.setText(url) conn_edit.leUsername.setText( self.settings.value('/MetaSearch/%s/username' % current_text)) conn_edit.lePassword.setText( self.settings.value('/MetaSearch/%s/password' % current_text)) if conn_edit.exec_() == QDialog.Accepted: # update service list self.populate_connection_list() def delete_connection(self): """delete connection""" current_text = self.cmbConnectionsServices.currentText() key = '/MetaSearch/%s' % current_text msg = self.tr('Remove service {0}?').format(current_text) result = QMessageBox.question(self, self.tr('Delete Service'), msg, QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if result == QMessageBox.Yes: # remove service from list self.settings.remove(key) index_to_delete = self.cmbConnectionsServices.currentIndex() self.cmbConnectionsServices.removeItem(index_to_delete) self.cmbConnectionsSearch.removeItem(index_to_delete) self.set_connection_list_position() def load_connections(self): """load services from list""" ManageConnectionsDialog(1).exec_() self.populate_connection_list() def add_default_connections(self): """add default connections""" filename = os.path.join(self.context.ppath, 'resources', 'connections-default.xml') doc = get_connections_from_file(self, filename) if doc is None: return self.settings.beginGroup('/MetaSearch/') keys = self.settings.childGroups() self.settings.endGroup() for server in doc.findall('csw'): name = server.attrib.get('name') # check for duplicates if name in keys: msg = self.tr('{0} exists. Overwrite?').format(name) res = QMessageBox.warning(self, self.tr('Loading connections'), msg, QMessageBox.Yes | QMessageBox.No) if res != QMessageBox.Yes: continue # no dups detected or overwrite is allowed key = '/MetaSearch/%s' % name self.settings.setValue('%s/url' % key, server.attrib.get('url')) self.populate_connection_list() # Settings tab def set_ows_save_title_ask(self): """save ows save strategy as save ows title, ask if duplicate""" self.settings.setValue('/MetaSearch/ows_save_strategy', 'title_ask') def set_ows_save_title_no_ask(self): """save ows save strategy as save ows title, do NOT ask if duplicate""" self.settings.setValue('/MetaSearch/ows_save_strategy', 'title_no_ask') def set_ows_save_temp_name(self): """save ows save strategy as save with a temporary name""" self.settings.setValue('/MetaSearch/ows_save_strategy', 'temp_name') # Search tab def set_bbox_from_map(self): """set bounding box from map extent""" crs = self.map.mapSettings().destinationCrs() try: crsid = int(crs.authid().split(':')[1]) except IndexError: # no projection crsid = 4326 extent = self.map.extent() if crsid != 4326: # reproject to EPSG:4326 src = QgsCoordinateReferenceSystem(crsid) dest = QgsCoordinateReferenceSystem(4326) xform = QgsCoordinateTransform(src, dest, QgsProject.instance()) minxy = xform.transform( QgsPointXY(extent.xMinimum(), extent.yMinimum())) maxxy = xform.transform( QgsPointXY(extent.xMaximum(), extent.yMaximum())) minx, miny = minxy maxx, maxy = maxxy else: # 4326 minx = extent.xMinimum() miny = extent.yMinimum() maxx = extent.xMaximum() maxy = extent.yMaximum() self.leNorth.setText(str(maxy)[0:9]) self.leSouth.setText(str(miny)[0:9]) self.leWest.setText(str(minx)[0:9]) self.leEast.setText(str(maxx)[0:9]) def set_bbox_global(self): """set global bounding box""" self.leNorth.setText('90') self.leSouth.setText('-90') self.leWest.setText('-180') self.leEast.setText('180') def search(self): """execute search""" self.catalog = None self.constraints = [] # clear all fields and disable buttons self.lblResults.clear() self.treeRecords.clear() self.reset_buttons() # save some settings self.settings.setValue('/MetaSearch/returnRecords', self.spnRecords.cleanText()) # set current catalog current_text = self.cmbConnectionsSearch.currentText() key = '/MetaSearch/%s' % current_text self.catalog_url = self.settings.value('%s/url' % key) self.catalog_username = self.settings.value('%s/username' % key) self.catalog_password = self.settings.value('%s/password' % key) # start position and number of records to return self.startfrom = 0 self.maxrecords = self.spnRecords.value() # set timeout self.timeout = self.spnTimeout.value() # bbox # CRS is WGS84 with axis order longitude, latitude # defined by 'urn:ogc:def:crs:OGC:1.3:CRS84' minx = self.leWest.text() miny = self.leSouth.text() maxx = self.leEast.text() maxy = self.leNorth.text() bbox = [minx, miny, maxx, maxy] # only apply spatial filter if bbox is not global # even for a global bbox, if a spatial filter is applied, then # the CSW server will skip records without a bbox if bbox != ['-180', '-90', '180', '90']: self.constraints.append( BBox(bbox, crs='urn:ogc:def:crs:OGC:1.3:CRS84')) # keywords if self.leKeywords.text(): # TODO: handle multiple word searches keywords = self.leKeywords.text() self.constraints.append(PropertyIsLike('csw:AnyText', keywords)) if len(self.constraints) > 1: # exclusive search (a && b) self.constraints = [self.constraints] # build request if not self._get_csw(): return # TODO: allow users to select resources types # to find ('service', 'dataset', etc.) try: with OverrideCursor(Qt.WaitCursor): self.catalog.getrecords2(constraints=self.constraints, maxrecords=self.maxrecords, esn='full') except ExceptionReport as err: QMessageBox.warning(self, self.tr('Search error'), self.tr('Search error: {0}').format(err)) return except Exception as err: QMessageBox.warning(self, self.tr('Connection error'), self.tr('Connection error: {0}').format(err)) return if self.catalog.results['matches'] == 0: self.lblResults.setText(self.tr('0 results')) return self.display_results() def display_results(self): """display search results""" self.treeRecords.clear() position = self.catalog.results['returned'] + self.startfrom msg = self.tr('Showing {0} - {1} of %n result(s)', 'number of results', self.catalog.results['matches']).format( self.startfrom + 1, position) self.lblResults.setText(msg) for rec in self.catalog.records: item = QTreeWidgetItem(self.treeRecords) if self.catalog.records[rec].type: item.setText(0, normalize_text(self.catalog.records[rec].type)) else: item.setText(0, 'unknown') if self.catalog.records[rec].title: item.setText(1, normalize_text(self.catalog.records[rec].title)) if self.catalog.records[rec].identifier: set_item_data(item, 'identifier', self.catalog.records[rec].identifier) self.btnShowXml.setEnabled(True) if self.catalog.results["matches"] < self.maxrecords: disabled = False else: disabled = True self.btnFirst.setEnabled(disabled) self.btnPrev.setEnabled(disabled) self.btnNext.setEnabled(disabled) self.btnLast.setEnabled(disabled) def record_clicked(self): """record clicked signal""" # disable only service buttons self.reset_buttons(True, False, False) if not self.treeRecords.selectedItems(): return item = self.treeRecords.currentItem() if not item: return identifier = get_item_data(item, 'identifier') try: record = self.catalog.records[identifier] except KeyError as err: QMessageBox.warning(self, self.tr('Record parsing error'), 'Unable to locate record identifier') return # if the record has a bbox, show a footprint on the map if record.bbox is not None: points = bbox_to_polygon(record.bbox) if points is not None: src = QgsCoordinateReferenceSystem(4326) dst = self.map.mapSettings().destinationCrs() geom = QgsGeometry.fromWkt(points) if src.postgisSrid() != dst.postgisSrid(): ctr = QgsCoordinateTransform(src, dst, QgsProject.instance()) try: geom.transform(ctr) except Exception as err: QMessageBox.warning( self, self.tr('Coordinate Transformation Error'), str(err)) self.rubber_band.setToGeometry(geom, None) # figure out if the data is interactive and can be operated on self.find_services(record, item) def find_services(self, record, item): """scan record for WMS/WMTS|WFS|WCS endpoints""" links = record.uris + record.references services = {} for link in links: if 'scheme' in link: link_type = link['scheme'] elif 'protocol' in link: link_type = link['protocol'] else: link_type = None if link_type is not None: link_type = link_type.upper() wmswmst_link_types = list( map(str.upper, link_types.WMSWMST_LINK_TYPES)) wfs_link_types = list(map(str.upper, link_types.WFS_LINK_TYPES)) wcs_link_types = list(map(str.upper, link_types.WCS_LINK_TYPES)) ams_link_types = list(map(str.upper, link_types.AMS_LINK_TYPES)) afs_link_types = list(map(str.upper, link_types.AFS_LINK_TYPES)) gis_file_link_types = list( map(str.upper, link_types.GIS_FILE_LINK_TYPES)) # if the link type exists, and it is one of the acceptable # interactive link types, then set if all([ link_type is not None, link_type in wmswmst_link_types + wfs_link_types + wcs_link_types + ams_link_types + afs_link_types + gis_file_link_types ]): if link_type in wmswmst_link_types: services['wms'] = link['url'] self.mActionAddWms.setEnabled(True) if link_type in wfs_link_types: services['wfs'] = link['url'] self.mActionAddWfs.setEnabled(True) if link_type in wcs_link_types: services['wcs'] = link['url'] self.mActionAddWcs.setEnabled(True) if link_type in ams_link_types: services['ams'] = link['url'] self.mActionAddAms.setEnabled(True) if link_type in afs_link_types: services['afs'] = link['url'] self.mActionAddAfs.setEnabled(True) if link_type in gis_file_link_types: services['gis_file'] = link['url'] services['title'] = record.title self.mActionAddGisFile.setEnabled(True) self.tbAddData.setEnabled(True) set_item_data(item, 'link', json.dumps(services)) def navigate(self): """manage navigation / paging""" caller = self.sender().objectName() if caller == 'btnFirst': self.startfrom = 0 elif caller == 'btnLast': self.startfrom = self.catalog.results['matches'] - self.maxrecords elif caller == 'btnNext': self.startfrom += self.maxrecords if self.startfrom >= self.catalog.results["matches"]: msg = self.tr('End of results. Go to start?') res = QMessageBox.information( self, self.tr('Navigation'), msg, (QMessageBox.Ok | QMessageBox.Cancel)) if res == QMessageBox.Ok: self.startfrom = 0 else: return elif caller == "btnPrev": self.startfrom -= self.maxrecords if self.startfrom <= 0: msg = self.tr('Start of results. Go to end?') res = QMessageBox.information( self, self.tr('Navigation'), msg, (QMessageBox.Ok | QMessageBox.Cancel)) if res == QMessageBox.Ok: self.startfrom = (self.catalog.results['matches'] - self.maxrecords) else: return try: with OverrideCursor(Qt.WaitCursor): self.catalog.getrecords2(constraints=self.constraints, maxrecords=self.maxrecords, startposition=self.startfrom, esn='full') except ExceptionReport as err: QMessageBox.warning(self, self.tr('Search error'), self.tr('Search error: {0}').format(err)) return except Exception as err: QMessageBox.warning(self, self.tr('Connection error'), self.tr('Connection error: {0}').format(err)) return self.display_results() def add_to_ows(self): """add to OWS provider connection list""" conn_name_matches = [] item = self.treeRecords.currentItem() if not item: return item_data = json.loads(get_item_data(item, 'link')) caller = self.sender().objectName() # stype = human name,/qgis/connections-%s,providername if caller == 'mActionAddWms': stype = ['OGC:WMS/OGC:WMTS', 'wms', 'wms'] data_url = item_data['wms'] elif caller == 'mActionAddWfs': stype = ['OGC:WFS', 'wfs', 'WFS'] data_url = item_data['wfs'] elif caller == 'mActionAddWcs': stype = ['OGC:WCS', 'wcs', 'wcs'] data_url = item_data['wcs'] elif caller == 'mActionAddAms': stype = ['ESRI:ArcGIS:MapServer', 'ams', 'arcgismapserver'] data_url = item_data['ams'].split('MapServer')[0] + 'MapServer' elif caller == 'mActionAddAfs': stype = ['ESRI:ArcGIS:FeatureServer', 'afs', 'arcgisfeatureserver'] data_url = item_data['afs'].split( 'FeatureServer')[0] + 'FeatureServer' sname = '%s from MetaSearch' % stype[1] # store connection # check if there is a connection with same name if caller in ['mActionAddAms', 'mActionAddAfs']: self.settings.beginGroup('/qgis/connections-%s' % stype[2]) else: self.settings.beginGroup('/qgis/connections-%s' % stype[1]) keys = self.settings.childGroups() self.settings.endGroup() for key in keys: if key.startswith(sname): conn_name_matches.append(key) if conn_name_matches: sname = conn_name_matches[-1] # check for duplicates if sname in keys: # duplicate found msg = self.tr('Connection {0} exists. Overwrite?').format(sname) res = QMessageBox.warning(self, self.tr('Saving server'), msg, QMessageBox.Yes | QMessageBox.No) if res != QMessageBox.Yes: # assign new name with serial sname = serialize_string(sname) # no dups detected or overwrite is allowed if caller in ['mActionAddAms', 'mActionAddAfs']: self.settings.beginGroup('/qgis/connections-%s' % stype[2]) else: self.settings.beginGroup('/qgis/connections-%s' % stype[1]) self.settings.setValue('/%s/url' % sname, clean_ows_url(data_url)) self.settings.endGroup() # open provider window ows_provider = QgsProviderRegistry.instance().createSelectionWidget( stype[2], self) service_type = stype[0] # connect dialog signals to iface slots if service_type == 'OGC:WMS/OGC:WMTS': ows_provider.addRasterLayer.connect(self.iface.addRasterLayer) conn_cmb = ows_provider.findChild(QWidget, 'cmbConnections') connect = 'btnConnect_clicked' elif service_type == 'OGC:WFS': def addVectorLayer(path, name): self.iface.mainWindow().addVectorLayer(path, name, 'WFS') ows_provider.addVectorLayer.connect(addVectorLayer) conn_cmb = ows_provider.findChild(QWidget, 'cmbConnections') connect = 'connectToServer' elif service_type == 'OGC:WCS': ows_provider.addRasterLayer.connect(self.iface.addRasterLayer) conn_cmb = ows_provider.findChild(QWidget, 'mConnectionsComboBox') connect = 'mConnectButton_clicked' elif service_type == 'ESRI:ArcGIS:MapServer': ows_provider.addRasterLayer.connect(self.iface.addRasterLayer) conn_cmb = ows_provider.findChild(QComboBox) connect = 'connectToServer' elif service_type == 'ESRI:ArcGIS:FeatureServer': def addAfsLayer(path, name): self.iface.mainWindow().addVectorLayer(path, name, 'afs') ows_provider.addVectorLayer.connect(addAfsLayer) conn_cmb = ows_provider.findChild(QComboBox) connect = 'connectToServer' ows_provider.setModal(False) ows_provider.show() # open provider dialogue against added OWS index = conn_cmb.findText(sname) if index > -1: conn_cmb.setCurrentIndex(index) # only for wfs if service_type == 'OGC:WFS': ows_provider.cmbConnections_activated(index) elif service_type in [ 'ESRI:ArcGIS:MapServer', 'ESRI:ArcGIS:FeatureServer' ]: ows_provider.cmbConnections_activated(index) getattr(ows_provider, connect)() def add_gis_file(self): """add GIS file from result""" item = self.treeRecords.currentItem() if not item: return item_data = json.loads(get_item_data(item, 'link')) gis_file = item_data['gis_file'] title = item_data['title'] layer = self.iface.addVectorLayer(gis_file, title, "ogr") if not layer: self.iface.messageBar().pushWarning(None, "Layer failed to load!") def show_metadata(self): """show record metadata""" if not self.treeRecords.selectedItems(): return item = self.treeRecords.currentItem() if not item: return identifier = get_item_data(item, 'identifier') try: with OverrideCursor(Qt.WaitCursor): cat = CatalogueServiceWeb( self.catalog_url, timeout=self.timeout, # spellok username=self.catalog_username, password=self.catalog_password) cat.getrecordbyid( [self.catalog.records[identifier].identifier]) except ExceptionReport as err: QMessageBox.warning( self, self.tr('GetRecords error'), self.tr('Error getting response: {0}').format(err)) return except KeyError as err: QMessageBox.warning(self, self.tr('Record parsing error'), self.tr('Unable to locate record identifier')) return record = cat.records[identifier] record.xml_url = cat.request crd = RecordDialog() metadata = render_template('en', self.context, record, 'record_metadata_dc.html') style = QgsApplication.reportStyleSheet() crd.textMetadata.document().setDefaultStyleSheet(style) crd.textMetadata.setHtml(metadata) crd.exec_() def show_xml(self): """show XML request / response""" crd = XMLDialog() request_html = highlight_xml(self.context, self.catalog.request) response_html = highlight_xml(self.context, self.catalog.response) style = QgsApplication.reportStyleSheet() crd.txtbrXMLRequest.clear() crd.txtbrXMLResponse.clear() crd.txtbrXMLRequest.document().setDefaultStyleSheet(style) crd.txtbrXMLResponse.document().setDefaultStyleSheet(style) crd.txtbrXMLRequest.setHtml(request_html) crd.txtbrXMLResponse.setHtml(response_html) crd.exec_() def reset_buttons(self, services=True, xml=True, navigation=True): """Convenience function to disable WMS/WMTS|WFS|WCS buttons""" if services: self.tbAddData.setEnabled(False) self.mActionAddWms.setEnabled(False) self.mActionAddWfs.setEnabled(False) self.mActionAddWcs.setEnabled(False) self.mActionAddAms.setEnabled(False) self.mActionAddAfs.setEnabled(False) self.mActionAddGisFile.setEnabled(False) if xml: self.btnShowXml.setEnabled(False) if navigation: self.btnFirst.setEnabled(False) self.btnPrev.setEnabled(False) self.btnNext.setEnabled(False) self.btnLast.setEnabled(False) def help(self): """launch help""" open_url(get_help_url()) def reject(self): """back out of dialogue""" QDialog.reject(self) self.rubber_band.reset() def _get_csw(self): """convenience function to init owslib.csw.CatalogueServiceWeb""" # spellok # connect to the server with OverrideCursor(Qt.WaitCursor): try: self.catalog = CatalogueServiceWeb( self.catalog_url, # spellok timeout=self.timeout, username=self.catalog_username, password=self.catalog_password) return True except ExceptionReport as err: msg = self.tr('Error connecting to service: {0}').format(err) except ValueError as err: msg = self.tr('Value Error: {0}').format(err) except Exception as err: msg = self.tr('Unknown Error: {0}').format(err) QMessageBox.warning(self, self.tr('CSW Connection error'), msg) return False def install_proxy(self): """set proxy if one is set in QGIS network settings""" # initially support HTTP for now if self.settings.value('/proxy/proxyEnabled') == 'true': if self.settings.value('/proxy/proxyType') == 'HttpProxy': ptype = 'http' else: return user = self.settings.value('/proxy/proxyUser') password = self.settings.value('/proxy/proxyPassword') host = self.settings.value('/proxy/proxyHost') port = self.settings.value('/proxy/proxyPort') proxy_up = '' proxy_port = '' if all([user != '', password != '']): proxy_up = '%s:%s@' % (user, password) if port != '': proxy_port = ':%s' % port conn = '%s://%s%s%s' % (ptype, proxy_up, host, proxy_port) install_opener(build_opener(ProxyHandler({ptype: conn})))
def save(self): toSave = [] context = dataobjects.createContext() for row in range(self.tblParameters.rowCount()): algParams = {} algOutputs = {} col = 0 alg = self.alg for param in alg.parameterDefinitions(): if param.flags() & QgsProcessingParameterDefinition.FlagHidden: continue if param.isDestination(): continue wrapper = self.wrappers[row][col] # For compatibility with 3.x API, we need to check whether the wrapper is # the deprecated WidgetWrapper class. If not, it's the newer # QgsAbstractProcessingParameterWidgetWrapper class # TODO QGIS 4.0 - remove if issubclass(wrapper.__class__, WidgetWrapper): widget = wrapper.widget else: widget = wrapper.wrappedWidget() value = wrapper.parameterValue() if not param.checkValueIsAcceptable(value, context): self.parent.messageBar().pushMessage( "", self.tr( 'Wrong or missing parameter value: {0} (row {1})'). format(param.description(), row + 1), level=Qgis.Warning, duration=5) return algParams[param.name()] = param.valueAsPythonString( value, context) col += 1 for out in alg.destinationParameterDefinitions(): if out.flags() & QgsProcessingParameterDefinition.FlagHidden: continue widget = self.tblParameters.cellWidget(row, col) text = widget.getValue() if text.strip() != '': algOutputs[out.name()] = text.strip() col += 1 else: self.parent.messageBar().pushMessage( "", self.tr('Wrong or missing output value: {0} (row {1})' ).format(out.description(), row + 1), level=Qgis.Warning, duration=5) return toSave.append({ self.PARAMETERS: algParams, self.OUTPUTS: algOutputs }) settings = QgsSettings() last_path = settings.value("/Processing/LastBatchPath", QDir.homePath()) filename, __ = QFileDialog.getSaveFileName( self, self.tr('Save Batch'), last_path, self.tr('JSON files (*.json)')) if filename: if not filename.endswith('.json'): filename += '.json' last_path = QFileInfo(filename).path() settings.setValue('/Processing/LastBatchPath', last_path) with open(filename, 'w') as f: json.dump(toSave, f)
def testSetupProxy(self): """Test proxy setup""" settings = QgsSettings() settings.setValue("proxy/proxyEnabled", True) settings.setValue("proxy/proxyPort", '1234') settings.setValue("proxy/proxyHost", 'myproxyhostname.com') settings.setValue("proxy/proxyUser", 'username') settings.setValue("proxy/proxyPassword", 'password') settings.setValue("proxy/proxyExcludedUrls", "http://www.myhost.com|http://www.myotherhost.com") QgsNetworkAccessManager.instance().setupDefaultProxyAndCache() vl = QgsVectorLayer(TEST_DATA_DIR + '/' + 'lines.shp', 'proxy_test', 'ogr') self.assertTrue(vl.isValid()) self.assertEqual(gdal.GetConfigOption("GDAL_HTTP_PROXY"), "myproxyhostname.com:1234") self.assertEqual(gdal.GetConfigOption("GDAL_HTTP_PROXYUSERPWD"), "username:password") settings.setValue("proxy/proxyEnabled", True) settings.remove("proxy/proxyPort") settings.setValue("proxy/proxyHost", 'myproxyhostname.com') settings.setValue("proxy/proxyUser", 'username') settings.remove("proxy/proxyPassword") settings.setValue("proxy/proxyExcludedUrls", "http://www.myhost.com|http://www.myotherhost.com") QgsNetworkAccessManager.instance().setupDefaultProxyAndCache() vl = QgsVectorLayer(TEST_DATA_DIR + '/' + 'lines.shp', 'proxy_test', 'ogr') self.assertTrue(vl.isValid()) self.assertEqual(gdal.GetConfigOption("GDAL_HTTP_PROXY"), "myproxyhostname.com") self.assertEqual(gdal.GetConfigOption("GDAL_HTTP_PROXYUSERPWD"), "username")
def save_settings(self, prefix: str): """ Saves widget state to settings """ s = QgsSettings() s.setValue('/plugins/qquake/{}_last_event_start_date'.format(prefix), self.fdsn_event_start_date.dateTime()) s.setValue('/plugins/qquake/{}_last_event_end_date'.format(prefix), self.fdsn_event_end_date.dateTime()) s.setValue( '/plugins/qquake/{}_last_event_min_magnitude'.format(prefix), self.fdsn_event_min_magnitude.value()) s.setValue( '/plugins/qquake/{}_last_event_max_magnitude'.format(prefix), self.fdsn_event_max_magnitude.value()) s.setValue( '/plugins/qquake/{}_last_event_extent_enabled2'.format(prefix), self.limit_extent_checkbox.isChecked()) s.setValue('/plugins/qquake/{}_last_event_extent_named'.format(prefix), self.radio_predefined_area.isChecked()) s.setValue('/plugins/qquake/{}_last_event_extent_name'.format(prefix), self.combo_predefined_area.currentData()) s.setValue('/plugins/qquake/{}_last_event_extent_rect2'.format(prefix), self.radio_rectangular_area.isChecked()) s.setValue( '/plugins/qquake/{}_last_event_extent_circle2'.format(prefix), self.radio_circular_area.isChecked()) s.setValue( '/plugins/qquake/{}_last_event_min_lat_checked2'.format(prefix), self.lat_min_checkbox.isChecked()) s.setValue('/plugins/qquake/{}_last_event_min_lat'.format(prefix), self.lat_min_spinbox.value()) s.setValue( '/plugins/qquake/{}_last_event_max_lat_checked2'.format(prefix), self.lat_max_checkbox.isChecked()) s.setValue('/plugins/qquake/{}_last_event_max_lat'.format(prefix), self.lat_max_spinbox.value()) s.setValue( '/plugins/qquake/{}_last_event_min_long_checked2'.format(prefix), self.long_min_checkbox.isChecked()) s.setValue('/plugins/qquake/{}_last_event_min_long'.format(prefix), self.long_min_spinbox.value()) s.setValue( '/plugins/qquake/{}_last_event_max_long_checked2'.format(prefix), self.long_max_checkbox.isChecked()) s.setValue('/plugins/qquake/{}_last_event_max_long'.format(prefix), self.long_max_spinbox.value()) s.setValue('/plugins/qquake/{}_last_event_circle_long'.format(prefix), self.circular_long_spinbox.value()) s.setValue('/plugins/qquake/{}_last_event_circle_lat'.format(prefix), self.circular_lat_spinbox.value()) s.setValue( '/plugins/qquake/{}_last_event_circle_radius_min_checked2'.format( prefix), self.radius_min_checkbox.isChecked()) s.setValue( '/plugins/qquake/{}_last_event_circle_radius_max_checked2'.format( prefix), self.radius_max_checkbox.isChecked()) s.setValue( '/plugins/qquake/{}_last_event_circle_min_radius'.format(prefix), self.radius_min_spinbox.value()) s.setValue( '/plugins/qquake/{}_last_event_circle_max_radius'.format(prefix), self.radius_max_spinbox.value()) s.setValue('/plugins/qquake/{}_last_event_circle_unit'.format(prefix), int(self.radius_unit_combobox.currentData())) s.setValue( '/plugins/qquake/{}_last_event_max_intensity_greater_checked2'. format(prefix), self.earthquake_max_intensity_greater_check.isChecked()) s.setValue( '/plugins/qquake/{}_last_event_max_intensity_greater'.format( prefix), self.earthquake_max_intensity_greater_combo.currentData()) s.setValue( '/plugins/qquake/{}_last_event_mdps_greater_checked2'.format( prefix), self.earthquake_number_mdps_greater_check.isChecked()) s.setValue('/plugins/qquake/{}_last_event_mdps_greater'.format(prefix), self.earthquake_number_mdps_greater_spin.value()) s.setValue( '/plugins/qquake/{}_last_event_min_time_checked2'.format(prefix), self.min_time_check.isChecked()) s.setValue( '/plugins/qquake/{}_last_event_max_time_checked2'.format(prefix), self.max_time_check.isChecked()) s.setValue( '/plugins/qquake/{}_last_event_min_mag_checked2'.format(prefix), self.min_mag_check.isChecked()) s.setValue( '/plugins/qquake/{}_last_event_max_mag_checked2'.format(prefix), self.max_mag_check.isChecked()) s.setValue( '/plugins/qquake/{}_last_event_basic_checked'.format(prefix), self.radio_basic_output.isChecked()) s.setValue( '/plugins/qquake/{}_last_event_extended_checked'.format(prefix), self.radio_extended_output.isChecked()) s.setValue('/plugins/qquake/{}_last_event_type'.format(prefix), self.event_type_combo.currentData()) s.setValue('/plugins/qquake/{}_last_event_type_checked'.format(prefix), self.event_type_check.isChecked()) s.setValue( '/plugins/qquake/{}_events_updated_after_date'.format(prefix), self.events_updated_after.dateTime()) s.setValue( '/plugins/qquake/{}_events_updated_after_checked'.format(prefix), self.events_updated_after_check.isChecked())
class NewConnectionDialog(QDialog, BASE_CLASS): """Dialogue to add a new CSW entry""" def __init__(self, conn_name=None): """init""" QDialog.__init__(self) self.setupUi(self) self.settings = QgsSettings() self.conn_name = None self.conn_name_orig = conn_name self.username = None self.password = None self.cmbCatalogType.addItems(CATALOG_TYPES) def accept(self): """add CSW entry""" conn_name = self.leName.text().strip() conn_url = self.leURL.text().strip() conn_username = self.leUsername.text().strip() conn_password = self.lePassword.text().strip() conn_catalog_type = self.cmbCatalogType.currentText() if any([conn_name == '', conn_url == '']): QMessageBox.warning(self, self.tr('Save Connection'), self.tr('Both Name and URL must be provided.')) return if '/' in conn_name: QMessageBox.warning(self, self.tr('Save Connection'), self.tr('Name cannot contain \'/\'.')) return if conn_name is not None: key = '/MetaSearch/%s' % conn_name keyurl = '%s/url' % key key_orig = '/MetaSearch/%s' % self.conn_name_orig # warn if entry was renamed to an existing connection if all([self.conn_name_orig != conn_name, self.settings.contains(keyurl)]): res = QMessageBox.warning( self, self.tr('Save Connection'), self.tr('Overwrite {0}?').format(conn_name), QMessageBox.Ok | QMessageBox.Cancel) if res == QMessageBox.Cancel: return # on rename delete original entry first if all([self.conn_name_orig is not None, self.conn_name_orig != conn_name]): self.settings.remove(key_orig) self.settings.setValue(keyurl, conn_url) self.settings.setValue('/MetaSearch/selected', conn_name) if conn_username != '': self.settings.setValue('%s/username' % key, conn_username) else: self.settings.remove('%s/username' % key) if conn_password != '': self.settings.setValue('%s/password' % key, conn_password) else: self.settings.remove('%s/password' % key) self.settings.setValue('%s/catalog-type' % key, conn_catalog_type) QDialog.accept(self) def reject(self): """back out of dialogue""" QDialog.reject(self)
def load(fileName, name=None, crs=None, style=None, isRaster=False): """ Loads a layer/table into the current project, given its file. .. deprecated:: 3.0 Do not use, will be removed in QGIS 4.0 """ from warnings import warn warn("processing.load is deprecated and will be removed in QGIS 4.0", DeprecationWarning) if fileName is None: return prjSetting = None settings = QgsSettings() if crs is not None: prjSetting = settings.value('/Projections/defaultBehavior') settings.setValue('/Projections/defaultBehavior', '') if name is None: name = os.path.split(fileName)[1] if isRaster: qgslayer = QgsRasterLayer(fileName, name) if qgslayer.isValid(): if crs is not None and qgslayer.crs() is None: qgslayer.setCrs(crs, False) if style is None: style = ProcessingConfig.getSetting( ProcessingConfig.RASTER_STYLE) qgslayer.loadNamedStyle(style) QgsProject.instance().addMapLayers([qgslayer]) else: if prjSetting: settings.setValue('/Projections/defaultBehavior', prjSetting) raise RuntimeError( QCoreApplication.translate( 'dataobject', 'Could not load layer: {0}\nCheck the processing framework log to look for errors.' ).format(fileName)) else: qgslayer = QgsVectorLayer(fileName, name, 'ogr') if qgslayer.isValid(): if crs is not None and qgslayer.crs() is None: qgslayer.setCrs(crs, False) if style is None: if qgslayer.geometryType() == QgsWkbTypes.PointGeometry: style = ProcessingConfig.getSetting( ProcessingConfig.VECTOR_POINT_STYLE) elif qgslayer.geometryType() == QgsWkbTypes.LineGeometry: style = ProcessingConfig.getSetting( ProcessingConfig.VECTOR_LINE_STYLE) else: style = ProcessingConfig.getSetting( ProcessingConfig.VECTOR_POLYGON_STYLE) qgslayer.loadNamedStyle(style) QgsProject.instance().addMapLayers([qgslayer]) if prjSetting: settings.setValue('/Projections/defaultBehavior', prjSetting) return qgslayer
def saveCheckingOnStartLastDate(self): """ set today's date as the day of last checking """ settings = QgsSettings() settings.setValue(settingsGroup + "/checkOnStartLastDate", QDate.currentDate())
class TestQgsSettings(unittest.TestCase): cnt = 0 def setUp(self): self.cnt += 1 h, path = tempfile.mkstemp('.ini') assert QgsSettings.setGlobalSettingsPath(path) self.settings = QgsSettings('testqgissettings', 'testqgissettings%s' % self.cnt) self.globalsettings = QSettings(self.settings.globalSettingsPath(), QSettings.IniFormat) def tearDown(self): settings_file = self.settings.fileName() settings_default_file = self.settings.globalSettingsPath() del(self.settings) try: os.unlink(settings_file) except: pass try: os.unlink(settings_default_file) except: pass def addToDefaults(self, key, value): self.globalsettings.setValue(key, value) self.globalsettings.sync() def addArrayToDefaults(self, prefix, key, values): defaults = QSettings(self.settings.globalSettingsPath(), QSettings.IniFormat) # NOQA self.globalsettings.beginWriteArray(prefix) i = 0 for v in values: self.globalsettings.setArrayIndex(i) self.globalsettings.setValue(key, v) i += 1 self.globalsettings.endArray() self.globalsettings.sync() def addGroupToDefaults(self, prefix, kvp): defaults = QSettings(self.settings.globalSettingsPath(), QSettings.IniFormat) # NOQA self.globalsettings.beginGroup(prefix) for k, v in kvp.items(): self.globalsettings.setValue(k, v) self.globalsettings.endGroup() self.globalsettings.sync() def test_basic_functionality(self): self.assertEqual(self.settings.value('testqgissettings/doesnotexists', 'notexist'), 'notexist') self.settings.setValue('testqgissettings/name', 'qgisrocks') self.settings.sync() self.assertEqual(self.settings.value('testqgissettings/name'), 'qgisrocks') def test_defaults(self): self.assertIsNone(self.settings.value('testqgissettings/name')) self.addToDefaults('testqgissettings/name', 'qgisrocks') self.assertEqual(self.settings.value('testqgissettings/name'), 'qgisrocks') def test_allkeys(self): self.assertEqual(self.settings.allKeys(), []) self.addToDefaults('testqgissettings/name', 'qgisrocks') self.addToDefaults('testqgissettings/name2', 'qgisrocks2') self.settings.setValue('nepoti/eman', 'osaple') self.assertEqual(3, len(self.settings.allKeys())) self.assertIn('testqgissettings/name', self.settings.allKeys()) self.assertIn('nepoti/eman', self.settings.allKeys()) self.assertEqual('qgisrocks', self.settings.value('testqgissettings/name')) self.assertEqual('qgisrocks2', self.settings.value('testqgissettings/name2')) self.assertEqual('qgisrocks', self.globalsettings.value('testqgissettings/name')) self.assertEqual('osaple', self.settings.value('nepoti/eman')) self.assertEqual(3, len(self.settings.allKeys())) self.assertEqual(2, len(self.globalsettings.allKeys())) def test_precedence_simple(self): self.assertEqual(self.settings.allKeys(), []) self.addToDefaults('testqgissettings/names/name1', 'qgisrocks1') self.settings.setValue('testqgissettings/names/name1', 'qgisrocks-1') self.assertEqual(self.settings.value('testqgissettings/names/name1'), 'qgisrocks-1') def test_precedence_group(self): """Test if user can override a group value""" self.assertEqual(self.settings.allKeys(), []) self.addGroupToDefaults('connections-xyz', { 'OSM': 'http://a.tile.openstreetmap.org/{z}/{x}/{y}.png', 'OSM-b': 'http://b.tile.openstreetmap.org/{z}/{x}/{y}.png', }) self.settings.beginGroup('connections-xyz') self.assertEqual(self.settings.value('OSM'), 'http://a.tile.openstreetmap.org/{z}/{x}/{y}.png') self.assertEqual(self.settings.value('OSM-b'), 'http://b.tile.openstreetmap.org/{z}/{x}/{y}.png') self.settings.endGroup() # Override edit self.settings.beginGroup('connections-xyz') self.settings.setValue('OSM', 'http://c.tile.openstreetmap.org/{z}/{x}/{y}.png') self.settings.endGroup() # Check it again! self.settings.beginGroup('connections-xyz') self.assertEqual(self.settings.value('OSM'), 'http://c.tile.openstreetmap.org/{z}/{x}/{y}.png') self.assertEqual(self.settings.value('OSM-b'), 'http://b.tile.openstreetmap.org/{z}/{x}/{y}.png') self.settings.endGroup() # Override remove: the global value will be resumed!!! self.settings.beginGroup('connections-xyz') self.settings.remove('OSM') self.settings.endGroup() # Check it again! self.settings.beginGroup('connections-xyz') self.assertEqual(self.settings.value('OSM'), 'http://a.tile.openstreetmap.org/{z}/{x}/{y}.png') self.assertEqual(self.settings.value('OSM-b'), 'http://b.tile.openstreetmap.org/{z}/{x}/{y}.png') self.settings.endGroup() # Override remove: store a blank! self.settings.beginGroup('connections-xyz') self.settings.setValue('OSM', '') self.settings.endGroup() # Check it again! self.settings.beginGroup('connections-xyz') self.assertEqual(self.settings.value('OSM'), '') self.assertEqual(self.settings.value('OSM-b'), 'http://b.tile.openstreetmap.org/{z}/{x}/{y}.png') self.settings.endGroup() # Override remove: store a None: will resume the global setting! self.settings.beginGroup('connections-xyz') self.settings.setValue('OSM', None) self.settings.endGroup() # Check it again! self.settings.beginGroup('connections-xyz') self.assertEqual(self.settings.value('OSM'), 'http://a.tile.openstreetmap.org/{z}/{x}/{y}.png') self.assertEqual(self.settings.value('OSM-b'), 'http://b.tile.openstreetmap.org/{z}/{x}/{y}.png') self.settings.endGroup() def test_uft8(self): self.assertEqual(self.settings.allKeys(), []) self.addToDefaults('testqgissettings/names/namèé↓1', 'qgisrocks↓1') self.assertEqual(self.settings.value('testqgissettings/names/namèé↓1'), 'qgisrocks↓1') self.settings.setValue('testqgissettings/names/namèé↓2', 'qgisrocks↓2') self.assertEqual(self.settings.value('testqgissettings/names/namèé↓2'), 'qgisrocks↓2') self.settings.setValue('testqgissettings/names/namèé↓1', 'qgisrocks↓-1') self.assertEqual(self.settings.value('testqgissettings/names/namèé↓1'), 'qgisrocks↓-1') def test_groups(self): self.assertEqual(self.settings.allKeys(), []) self.addToDefaults('testqgissettings/names/name1', 'qgisrocks1') self.addToDefaults('testqgissettings/names/name2', 'qgisrocks2') self.addToDefaults('testqgissettings/names/name3', 'qgisrocks3') self.addToDefaults('testqgissettings/name', 'qgisrocks') self.settings.beginGroup('testqgissettings') self.assertEqual(['names'], self.settings.childGroups()) self.settings.setValue('surnames/name1', 'qgisrocks-1') self.assertEqual(['surnames', 'names'], self.settings.childGroups()) self.settings.setValue('names/name1', 'qgisrocks-1') self.assertEqual('qgisrocks-1', self.settings.value('names/name1')) self.settings.endGroup() self.settings.beginGroup('testqgissettings/names') self.settings.setValue('name4', 'qgisrocks-4') keys = sorted(self.settings.childKeys()) self.assertEqual(keys, ['name1', 'name2', 'name3', 'name4']) self.settings.endGroup() self.assertEqual('qgisrocks-1', self.settings.value('testqgissettings/names/name1')) self.assertEqual('qgisrocks-4', self.settings.value('testqgissettings/names/name4')) def test_array(self): self.assertEqual(self.settings.allKeys(), []) self.addArrayToDefaults('testqgissettings', 'key', ['qgisrocks1', 'qgisrocks2', 'qgisrocks3']) self.assertEqual(self.settings.allKeys(), ['testqgissettings/1/key', 'testqgissettings/2/key', 'testqgissettings/3/key', 'testqgissettings/size']) self.assertEqual(self.globalsettings.allKeys(), ['testqgissettings/1/key', 'testqgissettings/2/key', 'testqgissettings/3/key', 'testqgissettings/size']) self.assertEqual(3, self.globalsettings.beginReadArray('testqgissettings')) self.globalsettings.endArray() self.assertEqual(3, self.settings.beginReadArray('testqgissettings')) values = [] for i in range(3): self.settings.setArrayIndex(i) values.append(self.settings.value("key")) self.assertEqual(values, ['qgisrocks1', 'qgisrocks2', 'qgisrocks3']) def test_array_overrides(self): """Test if an array completely shadows the global one""" self.assertEqual(self.settings.allKeys(), []) self.addArrayToDefaults('testqgissettings', 'key', ['qgisrocks1', 'qgisrocks2', 'qgisrocks3']) self.assertEqual(self.settings.allKeys(), ['testqgissettings/1/key', 'testqgissettings/2/key', 'testqgissettings/3/key', 'testqgissettings/size']) self.assertEqual(self.globalsettings.allKeys(), ['testqgissettings/1/key', 'testqgissettings/2/key', 'testqgissettings/3/key', 'testqgissettings/size']) self.assertEqual(3, self.globalsettings.beginReadArray('testqgissettings')) self.globalsettings.endArray() self.assertEqual(3, self.settings.beginReadArray('testqgissettings')) # Now override! self.settings.beginWriteArray('testqgissettings') self.settings.setArrayIndex(0) self.settings.setValue('key', 'myqgisrocksmore1') self.settings.setArrayIndex(1) self.settings.setValue('key', 'myqgisrocksmore2') self.settings.endArray() # Check it! self.assertEqual(2, self.settings.beginReadArray('testqgissettings')) values = [] for i in range(2): self.settings.setArrayIndex(i) values.append(self.settings.value("key")) self.assertEqual(values, ['myqgisrocksmore1', 'myqgisrocksmore2']) def test_section_getters_setters(self): self.assertEqual(self.settings.allKeys(), []) self.settings.setValue('key1', 'core1', section=QgsSettings.Core) self.settings.setValue('key2', 'core2', section=QgsSettings.Core) self.settings.setValue('key1', 'server1', section=QgsSettings.Server) self.settings.setValue('key2', 'server2', section=QgsSettings.Server) self.settings.setValue('key1', 'gui1', section=QgsSettings.Gui) self.settings.setValue('key2', 'gui2', QgsSettings.Gui) self.settings.setValue('key1', 'plugins1', section=QgsSettings.Plugins) self.settings.setValue('key2', 'plugins2', section=QgsSettings.Plugins) self.settings.setValue('key1', 'misc1', section=QgsSettings.Misc) self.settings.setValue('key2', 'misc2', section=QgsSettings.Misc) self.settings.setValue('key1', 'auth1', section=QgsSettings.Auth) self.settings.setValue('key2', 'auth2', section=QgsSettings.Auth) self.settings.setValue('key1', 'app1', section=QgsSettings.App) self.settings.setValue('key2', 'app2', section=QgsSettings.App) self.settings.setValue('key1', 'provider1', section=QgsSettings.Providers) self.settings.setValue('key2', 'provider2', section=QgsSettings.Providers) self.settings.setValue('key1', 'auth1', section=QgsSettings.Auth) self.settings.setValue('key2', 'auth2', section=QgsSettings.Auth) # Test that the values are namespaced self.assertEqual(self.settings.value('core/key1'), 'core1') self.assertEqual(self.settings.value('core/key2'), 'core2') self.assertEqual(self.settings.value('server/key1'), 'server1') self.assertEqual(self.settings.value('server/key2'), 'server2') self.assertEqual(self.settings.value('gui/key1'), 'gui1') self.assertEqual(self.settings.value('gui/key2'), 'gui2') self.assertEqual(self.settings.value('plugins/key1'), 'plugins1') self.assertEqual(self.settings.value('plugins/key2'), 'plugins2') self.assertEqual(self.settings.value('misc/key1'), 'misc1') self.assertEqual(self.settings.value('misc/key2'), 'misc2') # Test getters self.assertEqual(self.settings.value('key1', None, section=QgsSettings.Core), 'core1') self.assertEqual(self.settings.value('key2', None, section=QgsSettings.Core), 'core2') self.assertEqual(self.settings.value('key1', None, section=QgsSettings.Server), 'server1') self.assertEqual(self.settings.value('key2', None, section=QgsSettings.Server), 'server2') self.assertEqual(self.settings.value('key1', None, section=QgsSettings.Gui), 'gui1') self.assertEqual(self.settings.value('key2', None, section=QgsSettings.Gui), 'gui2') self.assertEqual(self.settings.value('key1', None, section=QgsSettings.Plugins), 'plugins1') self.assertEqual(self.settings.value('key2', None, section=QgsSettings.Plugins), 'plugins2') self.assertEqual(self.settings.value('key1', None, section=QgsSettings.Misc), 'misc1') self.assertEqual(self.settings.value('key2', None, section=QgsSettings.Misc), 'misc2') self.assertEqual(self.settings.value('key1', None, section=QgsSettings.Auth), 'auth1') self.assertEqual(self.settings.value('key2', None, section=QgsSettings.Auth), 'auth2') self.assertEqual(self.settings.value('key1', None, section=QgsSettings.App), 'app1') self.assertEqual(self.settings.value('key2', None, section=QgsSettings.App), 'app2') self.assertEqual(self.settings.value('key1', None, section=QgsSettings.Providers), 'provider1') self.assertEqual(self.settings.value('key2', None, section=QgsSettings.Providers), 'provider2') # Test default values on Section getter self.assertEqual(self.settings.value('key_not_exist', 'misc_not_exist', section=QgsSettings.Misc), 'misc_not_exist') def test_contains(self): self.assertEqual(self.settings.allKeys(), []) self.addToDefaults('testqgissettings/name', 'qgisrocks1') self.addToDefaults('testqgissettings/name2', 'qgisrocks2') self.assertTrue(self.settings.contains('testqgissettings/name')) self.assertTrue(self.settings.contains('testqgissettings/name2')) self.settings.setValue('testqgissettings/name3', 'qgisrocks3') self.assertTrue(self.settings.contains('testqgissettings/name3')) def test_remove(self): self.settings.setValue('testQgisSettings/temp', True) self.assertEqual(self.settings.value('testQgisSettings/temp'), True) self.settings.remove('testQgisSettings/temp') self.assertEqual(self.settings.value('testqQgisSettings/temp'), None)
def setUpClass(cls): """Run before all tests""" QCoreApplication.setOrganizationName("QGIS_Test") QCoreApplication.setOrganizationDomain("QGIS_TestPyQgsColorScheme.com") QCoreApplication.setApplicationName("QGIS_TestPyQgsColorScheme") QgsSettings().clear() start_app() # setup some fake connections settings = QgsSettings() key = 'qgis/connections-wms/test/' settings.setValue(key + 'url', 'aaa.bbb.com') settings.setValue(key + 'referer', 'my_ref') settings.setValue(key + 'ignoreGetMapURI', True) settings.setValue(key + 'ignoreGetFeatureInfoURI', True) settings.setValue(key + 'smoothPixmapTransform', True) settings.setValue(key + 'dpiMode', 4) settings.setValue(key + 'ignoreAxisOrientation', True) settings.setValue(key + 'invertAxisOrientation', True) key = 'qgis/connections-wfs/test/' settings.setValue(key + 'url', 'ccc.ddd.com') settings.setValue(key + 'version', '1.1.0') settings.setValue(key + 'maxnumfeatures', '47') settings.setValue(key + 'ignoreAxisOrientation', True) settings.setValue(key + 'invertAxisOrientation', True)
def closeEvent(self, event): settings = QgsSettings() settings.setValue("/Processing/modelParametersDialogGeometry", self.saveGeometry()) super(ModelerParametersDialog, self).closeEvent(event)
def setUpClass(cls): """Run before all tests""" QCoreApplication.setOrganizationName("QGIS_Test") QCoreApplication.setOrganizationDomain("QGIS_TestPyQgsColorScheme.com") QCoreApplication.setApplicationName("QGIS_TestPyQgsColorScheme") QgsSettings().clear() start_app() # setup a fake connection settings = QgsSettings() key = QgsGeoNodeConnectionUtils.pathGeoNodeConnection() + '/test/' settings.setValue(key + 'wms/referer', 'my_ref') settings.setValue(key + 'wms/ignoreGetMapURI', True) settings.setValue(key + 'wms/ignoreGetFeatureInfoURI', True) settings.setValue(key + 'wms/smoothPixmapTransform', True) settings.setValue(key + 'wms/dpiMode', 4) settings.setValue(key + 'wms/ignoreAxisOrientation', True) settings.setValue(key + 'wms/invertAxisOrientation', True) settings.setValue(key + 'wfs/version', '1.1.0') settings.setValue(key + 'wfs/maxnumfeatures', '47') settings.setValue(key + 'wfs/ignoreAxisOrientation', True) settings.setValue(key + 'wfs/invertAxisOrientation', True)
def save_btn_clicked(self): valResult = self.validate_settings() if valResult[0]: s = QgsSettings() s.setValue("qgis_app/settings/defaultPath", self.ustawieniaDialog.folder_lbl.text()) s.setValue("qgis_app/settings/contactName", self.ustawieniaDialog.contactName_lineEdit.text()) s.setValue("qgis_app/settings/contactMail", self.ustawieniaDialog.contactMail_lineEdit.text()) s.setValue("qgis_app/settings/adminName", self.ustawieniaDialog.adminName_lineEdit.text()) s.setValue("qgis_app/settings/adminMail", self.ustawieniaDialog.adminMail_lineEdit.text()) s.setValue("qgis_app/settings/przestrzenNazw", self.ustawieniaDialog.przestrzenNazw_lineEdit.text()) s.setValue("qgis_app/settings/numerZbioru", self.ustawieniaDialog.numerZbioru_lineEdit.text()) s.setValue("qgis_app/settings/jpt", self.ustawieniaDialog.jpt_lineEdit.text()) s.setValue("qgis_app/settings/rodzajZbioru", self.ustawieniaDialog.rodzajZbioru_comboBox.currentText( )) # COMBOBOX showPopup( 'Ustawienia zapisane pomyślnie', 'Ustawienia zostały zapisane.\n\nWyłącz i włącz program QGIS lub użyj wtyczki "Plugin Reloader" w celu zastosowania zmian.', icon=QMessageBox.Information) else: # błędy walidacji showPopup( 'Błąd zapisu ustawień', 'Ustawienia nie zostały zapisane z następujących powodów:\n\n%s' % valResult[1], icon=QMessageBox.Warning)