def saveToPostGIS(self): dlg = PostgisTableSelector(self, self.parameter.name().lower()) dlg.exec_() if dlg.connection: self.use_temporary = False settings = QgsSettings() mySettings = '/PostgreSQL/connections/' + dlg.connection dbname = settings.value(mySettings + '/database') user = settings.value(mySettings + '/username') host = settings.value(mySettings + '/host') port = settings.value(mySettings + '/port') password = settings.value(mySettings + '/password') uri = QgsDataSourceUri() uri.setConnection(host, str(port), dbname, user, password) uri.setDataSource(dlg.schema, dlg.table, "the_geom" if isinstance(self.parameter, QgsProcessingParameterFeatureSink) and self.parameter.hasGeometry() else None) connInfo = uri.connectionInfo() (success, user, passwd) = QgsCredentials.instance().get(connInfo, None, None) if success: QgsCredentials.instance().put(connInfo, user, passwd) self.leText.setText("postgis:" + uri.uri()) self.skipOutputChanged.emit(False) self.destinationChanged.emit()
def connect(self, parent=None): conn_name = self.connectionName() settings = QgsSettings() settings.beginGroup(u"/%s/%s" % (self.connectionSettingsKey(), conn_name)) if not settings.contains("database"): # non-existent entry? raise InvalidDataException(self.tr('There is no defined database connection "{0}".').format(conn_name)) from qgis.core import QgsDataSourceUri uri = QgsDataSourceUri() settingsList = ["service", "host", "port", "database", "username", "password", "authcfg"] service, host, port, database, username, password, authcfg = [settings.value(x, "", type=str) for x in settingsList] useEstimatedMetadata = settings.value("estimatedMetadata", False, type=bool) sslmode = settings.value("sslmode", QgsDataSourceUri.SslPrefer, type=int) settings.endGroup() if hasattr(authcfg, 'isNull') and authcfg.isNull(): authcfg = '' if service: uri.setConnection(service, database, username, password, sslmode, authcfg) else: uri.setConnection(host, port, database, username, password, sslmode, authcfg) uri.setUseEstimatedMetadata(useEstimatedMetadata) try: return self.connectToUri(uri) except ConnectionError: return False
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 uri_from_name(conn_name): settings = QgsSettings() settings.beginGroup(u"/PostgreSQL/connections/%s" % conn_name) if not settings.contains("database"): # non-existent entry? raise QgsProcessingException(QCoreApplication.translate("PostGIS", 'There is no defined database connection "{0}".').format(conn_name)) uri = QgsDataSourceUri() settingsList = ["service", "host", "port", "database", "username", "password", "authcfg"] service, host, port, database, username, password, authcfg = [settings.value(x, "", type=str) for x in settingsList] useEstimatedMetadata = settings.value("estimatedMetadata", False, type=bool) try: sslmode = settings.value("sslmode", QgsDataSourceUri.SslPrefer, type=int) except TypeError: sslmode = QgsDataSourceUri.SslPrefer settings.endGroup() if hasattr(authcfg, 'isNull') and authcfg.isNull(): authcfg = '' if service: uri.setConnection(service, database, username, password, sslmode, authcfg) else: uri.setConnection(host, port, database, username, password, sslmode, authcfg) uri.setUseEstimatedMetadata(useEstimatedMetadata) return uri
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 initLexer(self): if self.lexerType == self.LEXER_PYTHON: self.lexer = QsciLexerPython() colorDefault = QColor('#2e3436') colorComment = QColor('#c00') colorCommentBlock = QColor('#3465a4') colorNumber = QColor('#4e9a06') colorType = QColor('#4e9a06') colorKeyword = QColor('#204a87') colorString = QColor('#ce5c00') self.lexer.setDefaultFont(self.defaultFont) self.lexer.setDefaultColor(colorDefault) self.lexer.setColor(colorComment, 1) self.lexer.setColor(colorNumber, 2) self.lexer.setColor(colorString, 3) self.lexer.setColor(colorString, 4) self.lexer.setColor(colorKeyword, 5) self.lexer.setColor(colorString, 6) self.lexer.setColor(colorString, 7) self.lexer.setColor(colorType, 8) self.lexer.setColor(colorCommentBlock, 12) self.lexer.setColor(colorString, 15) self.lexer.setFont(self.italicFont, 1) self.lexer.setFont(self.boldFont, 5) self.lexer.setFont(self.boldFont, 8) self.lexer.setFont(self.italicFont, 12) self.api = QsciAPIs(self.lexer) settings = QgsSettings() useDefaultAPI = bool(settings.value('pythonConsole/preloadAPI', True)) if useDefaultAPI: # Load QGIS API shipped with Python console self.api.loadPrepared( os.path.join(QgsApplication.pkgDataPath(), 'python', 'qsci_apis', 'pyqgis.pap')) else: # Load user-defined API files apiPaths = settings.value('pythonConsole/userAPI', []) for path in apiPaths: self.api.load(path) self.api.prepare() self.lexer.setAPIs(self.api) elif self.lexerType == self.LEXER_R: # R lexer self.lexer = LexerR() self.setLexer(self.lexer)
def __init__(self, iface, parent=None): QMainWindow.__init__(self, parent) self.setAttribute(Qt.WA_DeleteOnClose) self.setupUi() self.iface = iface # restore the window state settings = QgsSettings() self.restoreGeometry(settings.value("/DB_Manager/mainWindow/geometry", QByteArray(), type=QByteArray)) self.restoreState(settings.value("/DB_Manager/mainWindow/windowState", QByteArray(), type=QByteArray)) self.tabs.currentChanged.connect(self.tabChanged) self.tree.selectedItemChanged.connect(self.itemChanged) self.itemChanged(None)
def __init__(self, parent=None): super(LayerPreview, self).__init__(parent) self.parent = parent self.setCanvasColor(QColor(255, 255, 255)) self.item = None self.dirty = False self.currentLayerId = None # reuse settings from QGIS settings = QgsSettings() self.enableAntiAliasing(settings.value("/qgis/enable_anti_aliasing", False, type=bool)) zoomFactor = settings.value("/qgis/zoom_factor", 2, type=float) self.setWheelFactor(zoomFactor)
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 main(): datestamp = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S") if QT5: ini_out_dir = QStandardPaths.writableLocation(QStandardPaths.DesktopLocation) else: ini_out_dir = QDesktopServices.storageLocation(QDesktopServices.DesktopLocation) ini_name = 'org.qgis.{0}-settings_{1}.ini'.format(QGIS_APP_NAME, datestamp) ini_out = QDir(ini_out_dir).absoluteFilePath(ini_name) if not os.path.exists(ini_out_dir): print('INI output directory does not exist: {0}'.format(ini_out_dir)) return if not os.access(ini_out_dir, os.W_OK | os.X_OK): print('INI output directory is not writeable: {0}'.format(ini_out_dir)) return # QGIS settings if HAS_QGSSETTINGS: qgis_settings = QgsSettings() else: qgis_settings = QSettings() # Output INI settings ini_settings = QSettings(ini_out, QSettings.IniFormat) qgis_keys = qgis_settings.allKeys() for k in qgis_keys: ini_settings.setValue(k, qgis_settings.value(k)) ini_settings.sync() print("Settings output to: {0}".format(QDir.toNativeSeparators(ini_out)))
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 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 markNews(self): settings = QSettings() seenPlugins = settings.value(seenPluginGroup, list(self.plugins.keys()), str) if len(seenPlugins) > 0: for i in list(self.plugins.keys()): if seenPlugins.count(i) == 0 and self.plugins[i]['status'] == 'not installed': self.plugins[i]['status'] = 'new'
def browse(self): """ open save layer dialog """ settings = QgsSettings() dirName = settings.value("/UI/lastShapefileDir") encode = settings.value("/UI/encoding") fileDialog = QgsEncodingFileDialog(self, "Output shape file", dirName, "Shape file (*.shp)", encode) fileDialog.setDefaultSuffix("shp") fileDialog.setFileMode(QtWidgets.QFileDialog.AnyFile) fileDialog.setAcceptMode(QtWidgets.QFileDialog.AcceptSave) #fileDialog.setConfirmOverwrite(True) if not fileDialog.exec_() == QtWidgets.QDialog.Accepted: return files = fileDialog.selectedFiles() self.pointEdit.setText(files[0]) self.encoding = fileDialog.encoding()
def chooseInputFile(self): vectorFormats = QgsProviderRegistry.instance().fileVectorFilters() # get last used dir and format settings = QgsSettings() lastDir = settings.value("/db_manager/lastUsedDir", "") lastVectorFormat = settings.value("/UI/lastVectorFileFilter", "") # ask for a filename filename, lastVectorFormat = QFileDialog.getOpenFileName(self, self.tr("Choose the file to import"), lastDir, vectorFormats, lastVectorFormat) if filename == "": return # store the last used dir and format settings.setValue("/db_manager/lastUsedDir", QFileInfo(filename).filePath()) settings.setValue("/UI/lastVectorFileFilter", lastVectorFormat) self.cboInputLayer.setEditText(filename)
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 createContext(feedback=None): """ Creates a default processing context :param feedback: Optional existing QgsProcessingFeedback object, or None to use a default feedback object :type feedback: Optional[QgsProcessingFeedback] :returns: New QgsProcessingContext object :rtype: QgsProcessingContext """ context = QgsProcessingContext() context.setProject(QgsProject.instance()) context.setFeedback(feedback) invalid_features_method = ProcessingConfig.getSetting(ProcessingConfig.FILTER_INVALID_GEOMETRIES) if invalid_features_method is None: invalid_features_method = QgsFeatureRequest.GeometryAbortOnInvalid context.setInvalidGeometryCheck(invalid_features_method) settings = QgsSettings() context.setDefaultEncoding(settings.value("/Processing/encoding", "System")) context.setExpressionContext(createExpressionContext()) return context
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 getVectorWriter(self, fields, geomType, crs, context): """Returns a suitable writer to which features can be added as a result of the algorithm. Use this to transparently handle output values instead of creating your own method. Executing this method might modify the object, adding additional information to it, so the writer can be later accessed and processed within QGIS. It should be called just once, since a new call might result in previous data being replaced, thus rendering a previously obtained writer useless. @param fields a list of QgsField @param geomType a suitable geometry type, as it would be passed to a QgsVectorFileWriter constructor @param crs the crs of the layer to create @return writer instance of the vector writer class :param context: """ if self.encoding is None: settings = QgsSettings() self.encoding = settings.value('/Processing/encoding', 'System', str) w, w_dest = QgsProcessingUtils.createFeatureSink(self.value, context, fields, geomType, crs, {'fileEncoding': self.encoding}) self.value = w_dest return w
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 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 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 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 createContext(): """ Creates a default processing context """ context = QgsProcessingContext() context.setProject(QgsProject.instance()) invalid_features_method = ProcessingConfig.getSetting(ProcessingConfig.FILTER_INVALID_GEOMETRIES) if invalid_features_method is None: invalid_features_method = QgsFeatureRequest.GeometryAbortOnInvalid context.setInvalidGeometryCheck(invalid_features_method) def raise_error(f): raise GeoAlgorithmExecutionException(QCoreApplication.translate("FeatureIterator", 'Features with invalid geometries found. Please fix these geometries or specify the "Ignore invalid input features" flag')) context.setInvalidGeometryCallback(raise_error) def raise_transform_error(f): raise GeoAlgorithmExecutionException(QCoreApplication.translate("FeatureIterator", 'Encountered a transform error when reprojecting feature with id {}.'.format(f.id()))) context.setTransformErrorCallback(raise_transform_error) settings = QgsSettings() context.setDefaultEncoding(settings.value("/Processing/encoding", "System")) return context
def __init__(self, alg, model, algName=None, configuration=None): QDialog.__init__(self) self.setModal(True) self._alg = alg # The algorithm to define in this dialog. It is an instance of QgsProcessingAlgorithm self.model = model # The model this algorithm is going to be added to. It is an instance of QgsProcessingModelAlgorithm self.childId = algName # The name of the algorithm in the model, in case we are editing it and not defining it for the first time self.configuration = configuration self.context = createContext() self.widget_labels = {} class ContextGenerator(QgsProcessingContextGenerator): def __init__(self, context): super().__init__() self.processing_context = context def processingContext(self): return self.processing_context self.context_generator = ContextGenerator(self.context) self.setupUi() self.params = None settings = QgsSettings() self.restoreGeometry(settings.value("/Processing/modelParametersDialogGeometry", QByteArray()))
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 markNews(self): """ mark all new plugins as new """ settings = QgsSettings() seenPlugins = settings.value(settingsGroup + '/seen_plugins', list(self.mPlugins.keys()), type=str) if len(seenPlugins) > 0: for i in list(self.mPlugins.keys()): if seenPlugins.count(i) == 0 and self.mPlugins[i]["status"] == "not installed": self.mPlugins[i]["status"] = "new"
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 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)
class ShellOutputScintilla(QsciScintilla): def __init__(self, parent=None): super(ShellOutputScintilla, self).__init__(parent) self.parent = parent self.shell = self.parent.shell self.settings = QgsSettings() # Creates layout for message bar self.layout = QGridLayout(self) self.layout.setContentsMargins(0, 0, 0, 0) spacerItem = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) self.layout.addItem(spacerItem, 1, 0, 1, 1) # messageBar instance self.infoBar = QgsMessageBar() sizePolicy = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.infoBar.setSizePolicy(sizePolicy) self.layout.addWidget(self.infoBar, 0, 0, 1, 1) # Enable non-ascii chars for editor self.setUtf8(True) sys.stdout = writeOut(self, sys.stdout) sys.stderr = writeOut(self, sys.stderr, "_traceback") self.insertInitText() self.refreshSettingsOutput() self.setReadOnly(True) # Set the default font font = QFontDatabase.systemFont(QFontDatabase.FixedFont) self.setFont(font) self.setMarginsFont(font) # Margin 0 is used for line numbers self.setMarginWidth(0, 0) self.setMarginWidth(1, 0) self.setMarginWidth(2, 0) #fm = QFontMetrics(font) self.setMarginsFont(font) self.setMarginWidth(1, "00000") self.setMarginLineNumbers(1, True) self.setMarginsForegroundColor(QColor("#3E3EE3")) self.setMarginsBackgroundColor(QColor("#f9f9f9")) self.setCaretLineVisible(True) self.setCaretWidth(0) self.setMinimumHeight(120) self.setWrapMode(QsciScintilla.WrapCharacter) self.SendScintilla(QsciScintilla.SCI_SETHSCROLLBAR, 0) self.runScut = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_E), self) self.runScut.setContext(Qt.WidgetShortcut) self.runScut.activated.connect(self.enteredSelected) # Reimplemented copy action to prevent paste prompt (>>>,...) in command view self.copyShortcut = QShortcut(QKeySequence.Copy, self) self.copyShortcut.activated.connect(self.copy) self.selectAllShortcut = QShortcut(QKeySequence.SelectAll, self) self.selectAllShortcut.activated.connect(self.selectAll) def insertInitText(self): txtInit = QCoreApplication.translate("PythonConsole", "Python Console \n" "Use iface to access QGIS API interface or Type help(iface) for more info") # some translation string for the console header ends without '\n' # and the first command in console will be appended at the header text. # The following code add a '\n' at the end of the string if not present. if txtInit.endswith('\n'): self.setText(txtInit) else: self.setText(txtInit + '\n') def refreshSettingsOutput(self): # Set Python lexer self.setLexers() caretLineColor = self.settings.value("pythonConsole/caretLineColor", QColor("#fcf3ed")) cursorColor = self.settings.value("pythonConsole/cursorColor", QColor(Qt.black)) self.setCaretLineBackgroundColor(caretLineColor) self.setCaretForegroundColor(cursorColor) def setLexers(self): self.lexer = QsciLexerPython() font = QFontDatabase.systemFont(QFontDatabase.FixedFont) loadFont = self.settings.value("pythonConsole/fontfamilytext") if loadFont: font.setFamily(loadFont) fontSize = self.settings.value("pythonConsole/fontsize", type=int) if fontSize: font.setPointSize(fontSize) self.lexer.setDefaultFont(font) self.lexer.setDefaultColor(QColor(self.settings.value("pythonConsole/defaultFontColor", QColor(Qt.black)))) self.lexer.setColor(QColor(self.settings.value("pythonConsole/commentFontColor", QColor(Qt.gray))), 1) self.lexer.setColor(QColor(self.settings.value("pythonConsole/keywordFontColor", QColor(Qt.darkGreen))), 5) self.lexer.setColor(QColor(self.settings.value("pythonConsole/classFontColor", QColor(Qt.blue))), 8) self.lexer.setColor(QColor(self.settings.value("pythonConsole/methodFontColor", QColor(Qt.darkGray))), 9) self.lexer.setColor(QColor(self.settings.value("pythonConsole/decorFontColor", QColor(Qt.darkBlue))), 15) self.lexer.setColor(QColor(self.settings.value("pythonConsole/commentBlockFontColor", QColor(Qt.gray))), 12) self.lexer.setColor(QColor(self.settings.value("pythonConsole/singleQuoteFontColor", QColor(Qt.blue))), 4) self.lexer.setColor(QColor(self.settings.value("pythonConsole/doubleQuoteFontColor", QColor(Qt.blue))), 3) self.lexer.setColor(QColor(self.settings.value("pythonConsole/tripleSingleQuoteFontColor", QColor(Qt.blue))), 6) self.lexer.setColor(QColor(self.settings.value("pythonConsole/tripleDoubleQuoteFontColor", QColor(Qt.blue))), 7) self.lexer.setColor(QColor(Qt.red), 14) self.lexer.setFont(font, 1) self.lexer.setFont(font, 2) self.lexer.setFont(font, 3) self.lexer.setFont(font, 4) for style in range(0, 33): paperColor = QColor(self.settings.value("pythonConsole/paperBackgroundColor", QColor(Qt.white))) self.lexer.setPaper(paperColor, style) self.setLexer(self.lexer) def clearConsole(self): self.setText('') self.insertInitText() self.shell.setFocus() def contextMenuEvent(self, e): menu = QMenu(self) iconRun = QgsApplication.getThemeIcon("console/iconRunConsole.png") iconClear = QgsApplication.getThemeIcon("console/iconClearConsole.png") iconHideTool = QgsApplication.getThemeIcon("console/iconHideToolConsole.png") iconSettings = QgsApplication.getThemeIcon("console/iconSettingsConsole.png") menu.addAction(iconHideTool, QCoreApplication.translate("PythonConsole", "Hide/Show Toolbar"), self.hideToolBar) menu.addSeparator() showEditorAction = menu.addAction( QCoreApplication.translate("PythonConsole", "Show Editor"), self.showEditor) menu.addSeparator() runAction = menu.addAction(iconRun, QCoreApplication.translate("PythonConsole", "Enter Selected"), self.enteredSelected, QKeySequence(Qt.CTRL + Qt.Key_E)) clearAction = menu.addAction(iconClear, QCoreApplication.translate("PythonConsole", "Clear Console"), self.clearConsole) menu.addSeparator() copyAction = menu.addAction( QCoreApplication.translate("PythonConsole", "Copy"), self.copy, QKeySequence.Copy) selectAllAction = menu.addAction( QCoreApplication.translate("PythonConsole", "Select All"), self.selectAll, QKeySequence.SelectAll) menu.addSeparator() menu.addAction(iconSettings, QCoreApplication.translate("PythonConsole", "Options..."), self.parent.openSettings) runAction.setEnabled(False) clearAction.setEnabled(False) copyAction.setEnabled(False) selectAllAction.setEnabled(False) showEditorAction.setEnabled(True) if self.hasSelectedText(): runAction.setEnabled(True) copyAction.setEnabled(True) if not self.text(3) == '': selectAllAction.setEnabled(True) clearAction.setEnabled(True) if self.parent.tabEditorWidget.isVisible(): showEditorAction.setEnabled(False) menu.exec_(self.mapToGlobal(e.pos())) def hideToolBar(self): tB = self.parent.toolBar tB.hide() if tB.isVisible() else tB.show() self.shell.setFocus() def showEditor(self): Ed = self.parent.splitterObj if not Ed.isVisible(): Ed.show() self.parent.showEditorButton.setChecked(True) self.shell.setFocus() def copy(self): """Copy text to clipboard... or keyboard interrupt""" if self.hasSelectedText(): text = self.selectedText() text = text.replace('>>> ', '').replace('... ', '').strip() # removing prompts QApplication.clipboard().setText(text) else: raise KeyboardInterrupt def enteredSelected(self): cmd = self.selectedText() self.shell.insertFromDropPaste(cmd) self.shell.entered() def keyPressEvent(self, e): # empty text indicates possible shortcut key sequence so stay in output txt = e.text() if len(txt) and txt >= " ": self.shell.append(txt) self.shell.move_cursor_to_end() self.shell.setFocus() e.ignore() else: # possible shortcut key sequence, accept it e.accept() def widgetMessageBar(self, iface, text): timeout = iface.messageTimeout() self.infoBar.pushMessage(text, QgsMessageBar.INFO, timeout)
def initLexer(self): settings = QgsSettings() self.lexer = QsciLexerPython() font = QFontDatabase.systemFont(QFontDatabase.FixedFont) loadFont = settings.value("pythonConsole/fontfamilytextEditor") if loadFont: font.setFamily(loadFont) fontSize = settings.value("pythonConsole/fontsizeEditor", type=int) if fontSize: font.setPointSize(fontSize) self.lexer.setDefaultFont(font) self.lexer.setDefaultColor( QColor( settings.value("pythonConsole/defaultFontColorEditor", QColor(self.DEFAULT_COLOR)))) self.lexer.setColor( QColor( settings.value("pythonConsole/commentFontColorEditor", QColor(self.COMMENT_COLOR))), 1) self.lexer.setColor( QColor( settings.value("pythonConsole/numberFontColorEditor", QColor(self.NUMBER_COLOR))), 2) self.lexer.setColor( QColor( settings.value("pythonConsole/keywordFontColorEditor", QColor(self.KEYWORD_COLOR))), 5) self.lexer.setColor( QColor( settings.value("pythonConsole/classFontColorEditor", QColor(self.CLASS_COLOR))), 8) self.lexer.setColor( QColor( settings.value("pythonConsole/methodFontColorEditor", QColor(self.METHOD_COLOR))), 9) self.lexer.setColor( QColor( settings.value("pythonConsole/decorFontColorEditor", QColor(self.DECORATION_COLOR))), 15) self.lexer.setColor( QColor( settings.value("pythonConsole/commentBlockFontColorEditor", QColor(self.COMMENT_BLOCK_COLOR))), 12) self.lexer.setColor( QColor( settings.value("pythonConsole/singleQuoteFontColorEditor", QColor(self.SINGLE_QUOTE_COLOR))), 4) self.lexer.setColor( QColor( settings.value("pythonConsole/doubleQuoteFontColorEditor", QColor(self.DOUBLE_QUOTE_COLOR))), 3) self.lexer.setColor( QColor( settings.value( "pythonConsole/tripleSingleQuoteFontColorEditor", QColor(self.TRIPLE_SINGLE_QUOTE_COLOR))), 6) self.lexer.setColor( QColor( settings.value( "pythonConsole/tripleDoubleQuoteFontColorEditor", QColor(self.TRIPLE_DOUBLE_QUOTE_COLOR))), 7) self.lexer.setColor( QColor( settings.value("pythonConsole/defaultFontColorEditor", QColor(self.DEFAULT_COLOR))), 13) self.lexer.setFont(font, 1) self.lexer.setFont(font, 3) self.lexer.setFont(font, 4) self.lexer.setFont(font, QsciLexerPython.UnclosedString) for style in range(0, 33): paperColor = QColor( settings.value("pythonConsole/paperBackgroundColorEditor", QColor(self.BACKGROUND_COLOR))) self.lexer.setPaper(paperColor, style) self.api = QsciAPIs(self.lexer) useDefaultAPI = bool(settings.value('pythonConsole/preloadAPI', True)) if useDefaultAPI: # Load QGIS API shipped with Python console self.api.loadPrepared( os.path.join(QgsApplication.pkgDataPath(), 'python', 'qsci_apis', 'pyqgis.pap')) else: # Load user-defined API files apiPaths = settings.value('pythonConsole/userAPI', []) for path in apiPaths: self.api.load(path) self.api.prepare() self.lexer.setAPIs(self.api) self.setLexer(self.lexer)
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, context): pass class InvalidParameterValue(Exception): def __init__(self, param, widget): (self.parameter, self.widget) = (param, widget)
def rebuild(self): """ build or rebuild the mPlugins from the caches """ self.mPlugins = {} for i in list(self.localCache.keys()): self.mPlugins[i] = self.localCache[i].copy() settings = QgsSettings() allowExperimental = settings.value(settingsGroup + "/allowExperimental", False, type=bool) allowDeprecated = settings.value(settingsGroup + "/allowDeprecated", False, type=bool) for i in list(self.repoCache.values()): for j in i: plugin = j.copy() # do not update repoCache elements! key = plugin["id"] # check if the plugin is allowed and if there isn't any better one added already. if (allowExperimental or not plugin["experimental"]) \ and (allowDeprecated or not plugin["deprecated"]) \ and not (key in self.mPlugins and self.mPlugins[key]["version_available"] and compareVersions(self.mPlugins[key]["version_available"], plugin["version_available"]) < 2): # The mPlugins dict contains now locally installed plugins. # Now, add the available one if not present yet or update it if present already. if key not in self.mPlugins: self.mPlugins[key] = plugin # just add a new plugin else: # update local plugin with remote metadata # description, about, icon: only use remote data if local one not available. Prefer local version because of i18n. # NOTE: don't prefer local name to not desynchronize names if repository doesn't support i18n. # Also prefer local icon to avoid downloading. for attrib in translatableAttributes + ["icon"]: if attrib != "name": if not self.mPlugins[key][attrib] and plugin[ attrib]: self.mPlugins[key][attrib] = plugin[attrib] # other remote metadata is preferred: for attrib in [ "name", "plugin_id", "description", "about", "category", "tags", "changelog", "author_name", "author_email", "homepage", "tracker", "code_repository", "experimental", "deprecated", "version_available", "zip_repository", "download_url", "filename", "downloads", "average_vote", "rating_votes", "trusted" ]: if attrib not in translatableAttributes or attrib == "name": # include name! if plugin[attrib]: self.mPlugins[key][attrib] = plugin[attrib] # set status # # installed available status # --------------------------------------- # none any "not installed" (will be later checked if is "new") # any none "orphan" # same same "installed" # less greater "upgradeable" # greater less "newer" if not self.mPlugins[key]["version_available"]: self.mPlugins[key]["status"] = "orphan" elif not self.mPlugins[key]["version_installed"]: self.mPlugins[key]["status"] = "not installed" elif self.mPlugins[key]["version_installed"] in [ "?", "-1" ]: self.mPlugins[key]["status"] = "installed" elif compareVersions( self.mPlugins[key]["version_available"], self.mPlugins[key]["version_installed"]) == 0: self.mPlugins[key]["status"] = "installed" elif compareVersions( self.mPlugins[key]["version_available"], self.mPlugins[key]["version_installed"]) == 1: self.mPlugins[key]["status"] = "upgradeable" else: self.mPlugins[key]["status"] = "newer" # debug: test if the status match the "installed" tag: if self.mPlugins[key]["status"] in [ "not installed" ] and self.mPlugins[key]["installed"]: raise Exception( "Error: plugin status is ambiguous (1)") if self.mPlugins[key]["status"] in [ "installed", "orphan", "upgradeable", "newer" ] and not self.mPlugins[key]["installed"]: raise Exception( "Error: plugin status is ambiguous (2)") self.markNews()
def save(self): toSave = [] context = dataobjects.createContext() for row in range(self.batchRowCount()): 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 + 1, 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)
class MultipleInputDialog(BASE, WIDGET): def __init__(self, options, selectedoptions=None): super(MultipleInputDialog, self).__init__(None) self.setupUi(self) self.lstLayers.setSelectionMode(QAbstractItemView.NoSelection) self.options = [] for i, option in enumerate(options): if option is None or isinstance(option, basestring): 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) 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.populateList() self.finished.connect(self.saveWindowGeometry) def saveWindowGeometry(self): self.settings.setValue("/Processing/multipleInputDialogGeometry", self.saveGeometry()) def populateList(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) 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) 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 selectAll(self, value): model = self.lstLayers.model() for i in range(model.rowCount()): item = model.item(i) item.setCheckState(Qt.Checked if value else Qt.Unchecked) def toggleSelection(self): model = self.lstLayers.model() for i in range(model.rowCount()): item = model.item(i) checked = item.checkState() == Qt.Checked item.setCheckState(Qt.Unchecked if checked else Qt.Checked)
def checkingOnStart(self): """ return true if checking for news and updates is enabled """ settings = QgsSettings() return settings.value(settingsGroup + "/checkOnStart", False, type=bool)
def runGdal(commands, feedback=None): if feedback is None: feedback = QgsProcessingFeedback() envval = os.getenv('PATH') # We need to give some extra hints to get things picked up on OS X isDarwin = False try: isDarwin = platform.system() == 'Darwin' except IOError: # https://travis-ci.org/m-kuhn/QGIS#L1493-L1526 pass if isDarwin and os.path.isfile( os.path.join(QgsApplication.prefixPath(), "bin", "gdalinfo")): # Looks like there's a bundled gdal. Let's use it. os.environ['PATH'] = "{}{}{}".format( os.path.join(QgsApplication.prefixPath(), "bin"), os.pathsep, envval) os.environ['DYLD_LIBRARY_PATH'] = os.path.join( QgsApplication.prefixPath(), "lib") else: # Other platforms should use default gdal finder codepath settings = QgsSettings() path = settings.value('/GdalTools/gdalPath', '') if not path.lower() in envval.lower().split(os.pathsep): envval += '{}{}'.format(os.pathsep, path) os.putenv('PATH', envval) fused_command = ' '.join([str(c) for c in commands]) QgsMessageLog.logMessage(fused_command, 'Processing', Qgis.Info) feedback.pushInfo('GDAL command:') feedback.pushCommandInfo(fused_command) feedback.pushInfo('GDAL command output:') success = False retry_count = 0 while not success: loglines = [] loglines.append('GDAL execution console output') try: with subprocess.Popen( fused_command, shell=True, stdout=subprocess.PIPE, stdin=subprocess.DEVNULL, stderr=subprocess.STDOUT, universal_newlines=True, ) as proc: for line in proc.stdout: feedback.pushConsoleInfo(line) loglines.append(line) success = True except IOError as e: if retry_count < 5: retry_count += 1 else: raise IOError( str(e) + u'\nTried 5 times without success. Last iteration stopped after reading {} line(s).\nLast line(s):\n{}' .format(len(loglines), u'\n'.join(loglines[-10:]))) QgsMessageLog.logMessage('\n'.join(loglines), 'Processing', Qgis.Info) GdalUtils.consoleOutput = loglines
def setCommonOptions(self): # Enable non-ASCII characters self.setUtf8(True) # Default font font = QFont() font.setFamily('Courier') font.setFixedPitch(True) font.setPointSize(10) self.setFont(font) self.setMarginsFont(font) self.setBraceMatching(QsciScintilla.SloppyBraceMatch) self.setWrapMode(QsciScintilla.WrapWord) self.setWrapVisualFlags(QsciScintilla.WrapFlagByText, QsciScintilla.WrapFlagNone, 4) self.setSelectionForegroundColor(QColor('#2e3436')) self.setSelectionBackgroundColor(QColor('#babdb6')) # Show line numbers self.setMarginWidth(1, '000') self.setMarginLineNumbers(1, True) self.setMarginsForegroundColor(QColor('#2e3436')) self.setMarginsBackgroundColor(QColor('#babdb6')) # Highlight current line self.setCaretLineVisible(True) self.setCaretLineBackgroundColor(QColor('#d3d7cf')) # Folding self.setFolding(QsciScintilla.BoxedTreeFoldStyle) self.setFoldMarginColors(QColor('#d3d7cf'), QColor('#d3d7cf')) # Mark column 80 with vertical line self.setEdgeMode(QsciScintilla.EdgeLine) self.setEdgeColumn(80) self.setEdgeColor(QColor('#eeeeec')) # Indentation self.setAutoIndent(True) self.setIndentationsUseTabs(False) self.setIndentationWidth(4) self.setTabIndents(True) self.setBackspaceUnindents(True) self.setTabWidth(4) # Autocomletion self.setAutoCompletionThreshold(2) self.setAutoCompletionSource(QsciScintilla.AcsAPIs) self.setAutoCompletionCaseSensitivity(False) # Load font from Python console settings settings = QgsSettings() fontName = settings.value('pythonConsole/fontfamilytext', 'Monospace') fontSize = int(settings.value('pythonConsole/fontsize', 10)) self.defaultFont = QFont(fontName) self.defaultFont.setFixedPitch(True) self.defaultFont.setPointSize(fontSize) self.defaultFont.setStyleHint(QFont.TypeWriter) self.defaultFont.setStretch(QFont.SemiCondensed) self.defaultFont.setLetterSpacing(QFont.PercentageSpacing, 87.0) self.defaultFont.setBold(False) self.boldFont = QFont(self.defaultFont) self.boldFont.setBold(True) self.italicFont = QFont(self.defaultFont) self.italicFont.setItalic(True) self.setFont(self.defaultFont) self.setMarginsFont(self.defaultFont) self.initLexer()
def old_version_import() -> Service: settings = QgsSettings() if settings.contains('plugins/geomapfsih_locator_plugin/geomapfish_url'): definition = dict() definition['name'] = settings.value( 'plugins/geomapfsih_locator_plugin/filter_name', 'geomapfish', type=str) definition['url'] = settings.value( 'plugins/geomapfsih_locator_plugin/geomapfish_url', '', type=str) definition['crs'] = settings.value( 'plugins/geomapfsih_locator_plugin/geomapfish_crs', '', type=str) definition['remove_leading_digits'] = settings.value( 'plugins/geomapfsih_locator_plugin/remove_leading_digits', True, type=bool) definition['replace_underscore'] = settings.value( 'plugins/geomapfsih_locator_plugin/replace_underscore', True, type=bool) definition['break_camelcase'] = settings.value( 'plugins/geomapfsih_locator_plugin/break_camelcase', True, type=bool) definition['category_limit'] = settings.value( 'plugins/geomapfsih_locator_plugin/category_limit', 8, type=int) definition['total_limit'] = settings.value( 'plugins/geomapfsih_locator_plugin/total_limit', 50, type=int) user = settings.value( 'plugins/geomapfsih_locator_plugin/geomapfish_user', '', type=str) pwd = settings.value( 'plugins/geomapfsih_locator_plugin/geomapfish_pass', '', type=str) info("importing old service: {}".format(definition)) if user: reply = QMessageBox.question( None, "Geomapfish Locator", QCoreApplication.translate( "Geomapfish Locator", "User and password were saved in clear text in former Geomapfish plugin. " "Would you like to use QGIS authentication to store these credentials? " "If not, they will be removed.")) if reply == QMessageBox.Yes: config = QgsAuthMethodConfig('Basic') config.setName('geomapfish_{}'.format(definition['name'])) config.setConfig('username', user) config.setConfig('password', pwd) QgsApplication.authManager().storeAuthenticationConfig(config) definition['authid'] = config.id() dbg_info("created new auth id: {}".format(config.id())) else: drop_keys() return None drop_keys() return Service(definition) else: return None
def setCommonOptions(self): # Enable non-ASCII characters self.setUtf8(True) settings = QgsSettings() # Default font font = QFontDatabase.systemFont(QFontDatabase.FixedFont) self.setFont(font) self.setMarginsFont(font) self.setBraceMatching(QsciScintilla.SloppyBraceMatch) self.setMatchedBraceBackgroundColor( QColor( settings.value( "pythonConsole/matchedBraceBackgroundColorEditor", QColor(self.MATCHED_BRACE_BACKGROUND_COLOR)))) self.setMatchedBraceForegroundColor( QColor( settings.value( "pythonConsole/matchedBraceForegroundColorEditor", QColor(self.MATCHED_BRACE_FOREGROUND_COLOR)))) #self.setWrapMode(QsciScintilla.WrapWord) #self.setWrapVisualFlags(QsciScintilla.WrapFlagByText, # QsciScintilla.WrapFlagNone, 4) self.setSelectionForegroundColor( QColor( settings.value("pythonConsole/selectionForegroundColorEditor", QColor(self.SELECTION_FOREGROUND_COLOR)))) self.setSelectionBackgroundColor( QColor( settings.value("pythonConsole/selectionBackgroundColorEditor", QColor(self.SELECTION_BACKGROUND_COLOR)))) # Show line numbers fontmetrics = QFontMetrics(font) self.setMarginWidth(1, fontmetrics.width("0000") + 5) self.setMarginLineNumbers(1, True) self.setMarginsForegroundColor( QColor( settings.value("pythonConsole/marginForegroundColorEditor", QColor(self.MARGIN_FOREGROUND_COLOR)))) self.setMarginsBackgroundColor( QColor( settings.value("pythonConsole/marginBackgroundColorEditor", QColor(self.MARGIN_BACKGROUND_COLOR)))) self.setIndentationGuidesForegroundColor( QColor( settings.value("pythonConsole/marginForegroundColorEditor", QColor(self.MARGIN_FOREGROUND_COLOR)))) self.setIndentationGuidesBackgroundColor( QColor( settings.value("pythonConsole/marginBackgroundColorEditor", QColor(self.MARGIN_BACKGROUND_COLOR)))) # Highlight current line caretLineColorEditor = settings.value( "pythonConsole/caretLineColorEditor", QColor(self.CARET_LINE_COLOR)) cursorColorEditor = settings.value("pythonConsole/cursorColorEditor", QColor(self.CURSOR_COLOR)) self.setCaretLineVisible(True) self.setCaretWidth(2) self.setCaretLineBackgroundColor(caretLineColorEditor) self.setCaretForegroundColor(cursorColorEditor) # Folding self.setFolding(QsciScintilla.PlainFoldStyle) foldColor = QColor( settings.value("pythonConsole/foldColorEditor", QColor(self.FOLD_COLOR))) self.setFoldMarginColors(foldColor, foldColor) # Mark column 80 with vertical line self.setEdgeMode(QsciScintilla.EdgeLine) self.setEdgeColumn(80) self.setEdgeColor( QColor( settings.value("pythonConsole/edgeColorEditor", QColor(self.EDGE_COLOR)))) # Indentation self.setAutoIndent(True) self.setIndentationsUseTabs(False) self.setIndentationWidth(4) self.setTabIndents(True) self.setBackspaceUnindents(True) self.setTabWidth(4) self.setIndentationGuides(True) # Autocompletion self.setAutoCompletionThreshold(2) self.setAutoCompletionSource(QsciScintilla.AcsAPIs) self.setFonts(10) self.initLexer()
def __init__(self, model=None): super().__init__(None) self.setAttribute(Qt.WA_DeleteOnClose) self.setupUi(self) # LOTS of bug reports when we include the dock creation in the UI file # see e.g. #16428, #19068 # So just roll it all by hand......! self.propertiesDock = QgsDockWidget(self) self.propertiesDock.setFeatures(QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable) self.propertiesDock.setObjectName("propertiesDock") propertiesDockContents = QWidget() self.verticalDockLayout_1 = QVBoxLayout(propertiesDockContents) self.verticalDockLayout_1.setContentsMargins(0, 0, 0, 0) self.verticalDockLayout_1.setSpacing(0) self.scrollArea_1 = QgsScrollArea(propertiesDockContents) sizePolicy = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.scrollArea_1.sizePolicy().hasHeightForWidth()) self.scrollArea_1.setSizePolicy(sizePolicy) self.scrollArea_1.setFocusPolicy(Qt.WheelFocus) self.scrollArea_1.setFrameShape(QFrame.NoFrame) self.scrollArea_1.setFrameShadow(QFrame.Plain) self.scrollArea_1.setWidgetResizable(True) self.scrollAreaWidgetContents_1 = QWidget() self.gridLayout = QGridLayout(self.scrollAreaWidgetContents_1) self.gridLayout.setContentsMargins(6, 6, 6, 6) self.gridLayout.setSpacing(4) self.label_1 = QLabel(self.scrollAreaWidgetContents_1) self.gridLayout.addWidget(self.label_1, 0, 0, 1, 1) self.textName = QLineEdit(self.scrollAreaWidgetContents_1) self.gridLayout.addWidget(self.textName, 0, 1, 1, 1) self.label_2 = QLabel(self.scrollAreaWidgetContents_1) self.gridLayout.addWidget(self.label_2, 1, 0, 1, 1) self.textGroup = QLineEdit(self.scrollAreaWidgetContents_1) self.gridLayout.addWidget(self.textGroup, 1, 1, 1, 1) self.label_1.setText(self.tr("Name")) self.textName.setToolTip(self.tr("Enter model name here")) self.label_2.setText(self.tr("Group")) self.textGroup.setToolTip(self.tr("Enter group name here")) self.scrollArea_1.setWidget(self.scrollAreaWidgetContents_1) self.verticalDockLayout_1.addWidget(self.scrollArea_1) self.propertiesDock.setWidget(propertiesDockContents) self.addDockWidget(Qt.DockWidgetArea(1), self.propertiesDock) self.propertiesDock.setWindowTitle(self.tr("Model properties")) self.inputsDock = QgsDockWidget(self) self.inputsDock.setFeatures(QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable) self.inputsDock.setObjectName("inputsDock") self.inputsDockContents = QWidget() self.verticalLayout_3 = QVBoxLayout(self.inputsDockContents) self.verticalLayout_3.setContentsMargins(0, 0, 0, 0) self.scrollArea_2 = QgsScrollArea(self.inputsDockContents) sizePolicy.setHeightForWidth( self.scrollArea_2.sizePolicy().hasHeightForWidth()) self.scrollArea_2.setSizePolicy(sizePolicy) self.scrollArea_2.setFocusPolicy(Qt.WheelFocus) self.scrollArea_2.setFrameShape(QFrame.NoFrame) self.scrollArea_2.setFrameShadow(QFrame.Plain) self.scrollArea_2.setWidgetResizable(True) self.scrollAreaWidgetContents_2 = QWidget() self.verticalLayout = QVBoxLayout(self.scrollAreaWidgetContents_2) self.verticalLayout.setContentsMargins(0, 0, 0, 0) self.verticalLayout.setSpacing(0) self.inputsTree = QTreeWidget(self.scrollAreaWidgetContents_2) self.inputsTree.setAlternatingRowColors(True) self.inputsTree.header().setVisible(False) self.verticalLayout.addWidget(self.inputsTree) self.scrollArea_2.setWidget(self.scrollAreaWidgetContents_2) self.verticalLayout_3.addWidget(self.scrollArea_2) self.inputsDock.setWidget(self.inputsDockContents) self.addDockWidget(Qt.DockWidgetArea(1), self.inputsDock) self.inputsDock.setWindowTitle(self.tr("Inputs")) self.algorithmsDock = QgsDockWidget(self) self.algorithmsDock.setFeatures(QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable) self.algorithmsDock.setObjectName("algorithmsDock") self.algorithmsDockContents = QWidget() self.verticalLayout_4 = QVBoxLayout(self.algorithmsDockContents) self.verticalLayout_4.setContentsMargins(0, 0, 0, 0) self.scrollArea_3 = QgsScrollArea(self.algorithmsDockContents) sizePolicy.setHeightForWidth( self.scrollArea_3.sizePolicy().hasHeightForWidth()) self.scrollArea_3.setSizePolicy(sizePolicy) self.scrollArea_3.setFocusPolicy(Qt.WheelFocus) self.scrollArea_3.setFrameShape(QFrame.NoFrame) self.scrollArea_3.setFrameShadow(QFrame.Plain) self.scrollArea_3.setWidgetResizable(True) self.scrollAreaWidgetContents_3 = QWidget() self.verticalLayout_2 = QVBoxLayout(self.scrollAreaWidgetContents_3) self.verticalLayout_2.setContentsMargins(0, 0, 0, 0) self.verticalLayout_2.setSpacing(4) self.searchBox = QgsFilterLineEdit(self.scrollAreaWidgetContents_3) self.verticalLayout_2.addWidget(self.searchBox) self.algorithmTree = QgsProcessingToolboxTreeView( None, QgsApplication.processingRegistry()) self.algorithmTree.setAlternatingRowColors(True) self.algorithmTree.header().setVisible(False) self.verticalLayout_2.addWidget(self.algorithmTree) self.scrollArea_3.setWidget(self.scrollAreaWidgetContents_3) self.verticalLayout_4.addWidget(self.scrollArea_3) self.algorithmsDock.setWidget(self.algorithmsDockContents) self.addDockWidget(Qt.DockWidgetArea(1), self.algorithmsDock) self.algorithmsDock.setWindowTitle(self.tr("Algorithms")) self.searchBox.setToolTip( self.tr("Enter algorithm name to filter list")) self.searchBox.setShowSearchIcon(True) self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.centralWidget().layout().insertWidget(0, self.bar) try: self.setDockOptions(self.dockOptions() | QMainWindow.GroupedDragging) except: pass if iface is not None: self.mToolbar.setIconSize(iface.iconSize()) self.setStyleSheet(iface.mainWindow().styleSheet()) self.mActionOpen.setIcon( QgsApplication.getThemeIcon('/mActionFileOpen.svg')) self.mActionSave.setIcon( QgsApplication.getThemeIcon('/mActionFileSave.svg')) self.mActionSaveAs.setIcon( QgsApplication.getThemeIcon('/mActionFileSaveAs.svg')) self.mActionSaveInProject.setIcon( QgsApplication.getThemeIcon('/mAddToProject.svg')) self.mActionZoomActual.setIcon( QgsApplication.getThemeIcon('/mActionZoomActual.svg')) self.mActionZoomIn.setIcon( QgsApplication.getThemeIcon('/mActionZoomIn.svg')) self.mActionZoomOut.setIcon( QgsApplication.getThemeIcon('/mActionZoomOut.svg')) self.mActionExportImage.setIcon( QgsApplication.getThemeIcon('/mActionSaveMapAsImage.svg')) self.mActionZoomToItems.setIcon( QgsApplication.getThemeIcon('/mActionZoomFullExtent.svg')) self.mActionExportPdf.setIcon( QgsApplication.getThemeIcon('/mActionSaveAsPDF.svg')) self.mActionExportSvg.setIcon( QgsApplication.getThemeIcon('/mActionSaveAsSVG.svg')) #self.mActionExportPython.setIcon( # QgsApplication.getThemeIcon('/mActionSaveAsPython.svg')) self.mActionEditHelp.setIcon( QgsApplication.getThemeIcon('/mActionEditHelpContent.svg')) self.mActionRun.setIcon( QgsApplication.getThemeIcon('/mActionStart.svg')) self.addDockWidget(Qt.LeftDockWidgetArea, self.propertiesDock) self.addDockWidget(Qt.LeftDockWidgetArea, self.inputsDock) self.addDockWidget(Qt.LeftDockWidgetArea, self.algorithmsDock) self.tabifyDockWidget(self.inputsDock, self.algorithmsDock) self.inputsDock.raise_() self.zoom = 1 self.setWindowFlags(Qt.WindowMinimizeButtonHint | Qt.WindowMaximizeButtonHint | Qt.WindowCloseButtonHint) settings = QgsSettings() self.restoreState( settings.value("/Processing/stateModeler", QByteArray())) self.restoreGeometry( settings.value("/Processing/geometryModeler", QByteArray())) self.scene = ModelerScene(self, dialog=self) self.scene.setSceneRect( QRectF(0, 0, self.CANVAS_SIZE, self.CANVAS_SIZE)) self.view.setScene(self.scene) self.view.setAcceptDrops(True) self.view.ensureVisible(0, 0, 10, 10) def _dragEnterEvent(event): if event.mimeData().hasText() or event.mimeData().hasFormat( 'application/x-vnd.qgis.qgis.algorithmid'): event.acceptProposedAction() else: event.ignore() def _dropEvent(event): if event.mimeData().hasFormat( 'application/x-vnd.qgis.qgis.algorithmid'): data = event.mimeData().data( 'application/x-vnd.qgis.qgis.algorithmid') stream = QDataStream(data, QIODevice.ReadOnly) algorithm_id = stream.readQString() alg = QgsApplication.processingRegistry().createAlgorithmById( algorithm_id) if alg is not None: self._addAlgorithm(alg, event.pos()) else: assert False, algorithm_id elif event.mimeData().hasText(): itemId = event.mimeData().text() if itemId in [ param.id() for param in QgsApplication.instance(). processingRegistry().parameterTypes() ]: self.addInputOfType(itemId, event.pos()) event.accept() else: event.ignore() def _dragMoveEvent(event): if event.mimeData().hasText() or event.mimeData().hasFormat( 'application/x-vnd.qgis.qgis.algorithmid'): event.accept() else: event.ignore() def _wheelEvent(event): self.view.setTransformationAnchor(QGraphicsView.AnchorUnderMouse) settings = QgsSettings() factor = settings.value('/qgis/zoom_favor', 2.0) # "Normal" mouse has an angle delta of 120, precision mouses provide data # faster, in smaller steps factor = 1.0 + (factor - 1.0) / 120.0 * abs(event.angleDelta().y()) if (event.modifiers() == Qt.ControlModifier): factor = 1.0 + (factor - 1.0) / 20.0 if event.angleDelta().y() < 0: factor = 1 / factor self.view.scale(factor, factor) def _enterEvent(e): QGraphicsView.enterEvent(self.view, e) self.view.viewport().setCursor(Qt.ArrowCursor) def _mouseReleaseEvent(e): QGraphicsView.mouseReleaseEvent(self.view, e) self.view.viewport().setCursor(Qt.ArrowCursor) def _mousePressEvent(e): if e.button() == Qt.MidButton: self.previousMousePos = e.pos() else: QGraphicsView.mousePressEvent(self.view, e) def _mouseMoveEvent(e): if e.buttons() == Qt.MidButton: offset = self.previousMousePos - e.pos() self.previousMousePos = e.pos() self.view.verticalScrollBar().setValue( self.view.verticalScrollBar().value() + offset.y()) self.view.horizontalScrollBar().setValue( self.view.horizontalScrollBar().value() + offset.x()) else: QGraphicsView.mouseMoveEvent(self.view, e) self.view.setDragMode(QGraphicsView.ScrollHandDrag) self.view.dragEnterEvent = _dragEnterEvent self.view.dropEvent = _dropEvent self.view.dragMoveEvent = _dragMoveEvent self.view.wheelEvent = _wheelEvent self.view.enterEvent = _enterEvent self.view.mousePressEvent = _mousePressEvent self.view.mouseMoveEvent = _mouseMoveEvent def _mimeDataInput(items): mimeData = QMimeData() text = items[0].data(0, Qt.UserRole) mimeData.setText(text) return mimeData self.inputsTree.mimeData = _mimeDataInput self.inputsTree.setDragDropMode(QTreeWidget.DragOnly) self.inputsTree.setDropIndicatorShown(True) self.algorithms_model = ModelerToolboxModel( self, QgsApplication.processingRegistry()) self.algorithmTree.setToolboxProxyModel(self.algorithms_model) self.algorithmTree.setDragDropMode(QTreeWidget.DragOnly) self.algorithmTree.setDropIndicatorShown(True) self.algorithmTree.setFilters( QgsProcessingToolboxProxyModel.FilterModeler) if hasattr(self.searchBox, 'setPlaceholderText'): self.searchBox.setPlaceholderText( QCoreApplication.translate('ModelerDialog', 'Search…')) if hasattr(self.textName, 'setPlaceholderText'): self.textName.setPlaceholderText(self.tr('Enter model name here')) if hasattr(self.textGroup, 'setPlaceholderText'): self.textGroup.setPlaceholderText(self.tr('Enter group name here')) # Connect signals and slots self.inputsTree.doubleClicked.connect(self.addInput) self.searchBox.textChanged.connect(self.algorithmTree.setFilterString) self.algorithmTree.doubleClicked.connect(self.addAlgorithm) # Ctrl+= should also trigger a zoom in action ctrlEquals = QShortcut(QKeySequence("Ctrl+="), self) ctrlEquals.activated.connect(self.zoomIn) self.mActionOpen.triggered.connect(self.openModel) self.mActionSave.triggered.connect(self.save) self.mActionSaveAs.triggered.connect(self.saveAs) self.mActionSaveInProject.triggered.connect(self.saveInProject) self.mActionZoomIn.triggered.connect(self.zoomIn) self.mActionZoomOut.triggered.connect(self.zoomOut) self.mActionZoomActual.triggered.connect(self.zoomActual) self.mActionZoomToItems.triggered.connect(self.zoomToItems) self.mActionExportImage.triggered.connect(self.exportAsImage) self.mActionExportPdf.triggered.connect(self.exportAsPdf) self.mActionExportSvg.triggered.connect(self.exportAsSvg) #self.mActionExportPython.triggered.connect(self.exportAsPython) self.mActionEditHelp.triggered.connect(self.editHelp) self.mActionRun.triggered.connect(self.runModel) if model is not None: self.model = model.create() self.model.setSourceFilePath(model.sourceFilePath()) self.textGroup.setText(self.model.group()) self.textName.setText(self.model.displayName()) self.repaintModel() else: self.model = QgsProcessingModelAlgorithm() self.model.setProvider( QgsApplication.processingRegistry().providerById('model')) self.fillInputsTree() self.view.centerOn(0, 0) self.help = None self.hasChanged = False
class ManageConnectionsDialog(QDialog, BASE_CLASS): """manage connections""" def __init__(self, mode): """init dialog""" QDialog.__init__(self) self.setupUi(self) self.settings = QgsSettings() self.filename = None self.mode = mode # 0 - save, 1 - load self.btnBrowse.clicked.connect(self.select_file) self.manage_gui() def manage_gui(self): """manage interface""" if self.mode == 1: self.label.setText(self.tr('Load from file')) self.buttonBox.button(QDialogButtonBox.Ok).setText(self.tr('Load')) else: self.label.setText(self.tr('Save to file')) self.buttonBox.button(QDialogButtonBox.Ok).setText(self.tr('Save')) self.populate() self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False) def select_file(self): """select file ops""" label = self.tr('eXtensible Markup Language (*.xml *.XML)') if self.mode == 0: slabel = self.tr('Save connections') self.filename, filter = QFileDialog.getSaveFileName( self, slabel, '.', label) else: slabel = self.tr('Load connections') self.filename, selected_filter = QFileDialog.getOpenFileName( self, slabel, '.', label) if not self.filename: return # ensure the user never omitted the extension from the file name if not self.filename.lower().endswith('.xml'): self.filename = '%s.xml' % self.filename self.leFileName.setText(self.filename) if self.mode == 1: self.populate() self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(True) def populate(self): """populate connections list from settings""" if self.mode == 0: self.settings.beginGroup('/MetaSearch/') keys = self.settings.childGroups() for key in keys: item = QListWidgetItem(self.listConnections) item.setText(key) self.settings.endGroup() else: # populate connections list from file doc = get_connections_from_file(self, self.filename) if doc is None: self.filename = None self.leFileName.clear() self.listConnections.clear() return for csw in doc.findall('csw'): item = QListWidgetItem(self.listConnections) item.setText(csw.attrib.get('name')) def save(self, connections): """save connections ops""" doc = etree.Element('qgsCSWConnections') doc.attrib['version'] = '1.0' for conn in connections: url = self.settings.value('/MetaSearch/%s/url' % conn) if url is not None: connection = etree.SubElement(doc, 'csw') connection.attrib['name'] = conn connection.attrib['url'] = url # write to disk with open(self.filename, 'w') as fileobj: fileobj.write(prettify_xml(etree.tostring(doc))) QMessageBox.information(self, self.tr('Save Connections'), self.tr('Saved to {0}').format(self.filename)) self.reject() def load(self, items): """load connections""" self.settings.beginGroup('/MetaSearch/') keys = self.settings.childGroups() self.settings.endGroup() exml = etree.parse(self.filename).getroot() for csw in exml.findall('csw'): conn_name = csw.attrib.get('name') # process only selected connections if conn_name not in items: continue # check for duplicates if conn_name in keys: label = self.tr('File {0} exists. Overwrite?').format( conn_name) res = QMessageBox.warning(self, self.tr('Loading Connections'), label, QMessageBox.Yes | QMessageBox.No) if res != QMessageBox.Yes: continue # no dups detected or overwrite is allowed url = '/MetaSearch/%s/url' % conn_name self.settings.setValue(url, csw.attrib.get('url')) def accept(self): """accept connections""" selection = self.listConnections.selectedItems() if len(selection) == 0: return items = [] for sel in selection: items.append(sel.text()) if self.mode == 0: # save self.save(items) else: # load self.load(items) self.filename = None self.leFileName.clear() self.listConnections.clear() self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False) def reject(self): """back out of manage connections dialogue""" QDialog.reject(self)
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
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() version = self.context.metadata.get('general', 'version') self.setWindowTitle(self.tr('MetaSearch {0}').format(version)) 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.btnShowXml.clicked.connect(self.show_xml) # settings self.radioTitleAsk.clicked.connect(self.set_ows_save_title_ask) self.radioTitleNoAsk.clicked.connect(self.set_ows_save_title_no_ask) self.radioTempName.clicked.connect(self.set_ows_save_temp_name) 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() # get preferred connection save strategy from settings and set it save_strategy = self.settings.value('/MetaSearch/ows_save_strategy', 'title_ask') if save_strategy == 'temp_name': self.radioTempName.setChecked(True) elif save_strategy == 'title_no_ask': self.radioTitleNoAsk.setChecked(True) else: self.radioTitleAsk.setChecked(True) # 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 QApplication.restoreOverrideCursor() 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 Catalogue 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 Catalogue 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.information(self, self.tr('Confirm delete'), msg, QMessageBox.Ok | QMessageBox.Cancel) if result == QMessageBox.Ok: # 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) minxy = xform.transform( QgsPoint(extent.xMinimum(), extent.yMinimum())) maxxy = xform.transform( QgsPoint(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 catalogue 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 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)) # 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: self.catalog.getrecords2(constraints=self.constraints, maxrecords=self.maxrecords, esn='full') except ExceptionReport as err: QApplication.restoreOverrideCursor() QMessageBox.warning(self, self.tr('Search error'), self.tr('Search error: {0}').format(err)) return except Exception as err: QApplication.restoreOverrideCursor() QMessageBox.warning(self, self.tr('Connection error'), self.tr('Connection error: {0}').format(err)) return if self.catalog.results['matches'] == 0: QApplication.restoreOverrideCursor() self.lblResults.setText(self.tr('0 results')) return QApplication.restoreOverrideCursor() 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) 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)) # 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 ]): 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) 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 QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) try: self.catalog.getrecords2(constraints=self.constraints, maxrecords=self.maxrecords, startposition=self.startfrom, esn='full') except ExceptionReport as err: QApplication.restoreOverrideCursor() QMessageBox.warning(self, self.tr('Search error'), self.tr('Search error: {0}').format(err)) return except Exception as err: QApplication.restoreOverrideCursor() QMessageBox.warning(self, self.tr('Connection error'), self.tr('Connection error: {0}').format(err)) return QApplication.restoreOverrideCursor() 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'] QApplication.restoreOverrideCursor() sname = '%s from MetaSearch' % stype[1] # store connection # check if there is a connection with same name 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 if self.radioTitleAsk.isChecked(): # ask to overwrite 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) elif self.radioTitleNoAsk.isChecked(): # don't ask to overwrite pass elif self.radioTempName.isChecked(): # use temp name sname = serialize_string(sname) # no dups detected or overwrite is allowed 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().selectWidget( 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 = 'on_btnConnect_clicked' elif service_type == 'OGC:WFS': ows_provider.addWfsLayer.connect( self.iface.mainWindow().addWfsLayer) 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 = 'on_mConnectButton_clicked' 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.on_cmbConnections_activated(index) getattr(ows_provider, connect)() 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: QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) cat = CatalogueServiceWeb(self.catalog_url, timeout=self.timeout, username=self.catalog_username, password=self.catalog_password) cat.getrecordbyid([self.catalog.records[identifier].identifier]) except ExceptionReport as err: QApplication.restoreOverrideCursor() 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')) QApplication.restoreOverrideCursor() return QApplication.restoreOverrideCursor() 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) 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""" # connect to the server try: QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) self.catalog = CatalogueServiceWeb(self.catalog_url, 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) QApplication.restoreOverrideCursor() 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})))
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) 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) 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) self.model.appendRow(item)
def __init__(self, model=None): super().__init__(None) self.setAttribute(Qt.WA_DeleteOnClose) self.setupUi(self) self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.centralWidget().layout().insertWidget(0, self.bar) try: self.setDockOptions(self.dockOptions() | QMainWindow.GroupedDragging) except: pass self.mToolbar.setIconSize(iface.iconSize()) self.mActionOpen.setIcon( QgsApplication.getThemeIcon('/mActionFileOpen.svg')) self.mActionSave.setIcon( QgsApplication.getThemeIcon('/mActionFileSave.svg')) self.mActionSaveAs.setIcon( QgsApplication.getThemeIcon('/mActionFileSaveAs.svg')) self.mActionZoomActual.setIcon( QgsApplication.getThemeIcon('/mActionZoomActual.svg')) self.mActionZoomIn.setIcon( QgsApplication.getThemeIcon('/mActionZoomIn.svg')) self.mActionZoomOut.setIcon( QgsApplication.getThemeIcon('/mActionZoomOut.svg')) self.mActionExportImage.setIcon( QgsApplication.getThemeIcon('/mActionSaveMapAsImage.svg')) self.mActionZoomToItems.setIcon( QgsApplication.getThemeIcon('/mActionZoomFullExtent.svg')) self.mActionExportPdf.setIcon( QgsApplication.getThemeIcon('/mActionSaveAsPDF.svg')) self.mActionExportSvg.setIcon( QgsApplication.getThemeIcon('/mActionSaveAsSVG.svg')) #self.mActionExportPython.setIcon( # QgsApplication.getThemeIcon('/mActionSaveAsPython.svg')) self.mActionEditHelp.setIcon( QgsApplication.getThemeIcon('/mActionEditHelpContent.svg')) self.mActionRun.setIcon( QgsApplication.getThemeIcon('/mActionStart.svg')) self.addDockWidget(Qt.LeftDockWidgetArea, self.propertiesDock) self.addDockWidget(Qt.LeftDockWidgetArea, self.inputsDock) self.addDockWidget(Qt.LeftDockWidgetArea, self.algorithmsDock) self.tabifyDockWidget(self.inputsDock, self.algorithmsDock) self.inputsDock.raise_() self.zoom = 1 self.setWindowFlags(Qt.WindowMinimizeButtonHint | Qt.WindowMaximizeButtonHint | Qt.WindowCloseButtonHint) settings = QgsSettings() self.restoreState( settings.value("/Processing/stateModeler", QByteArray())) self.restoreGeometry( settings.value("/Processing/geometryModeler", QByteArray())) self.scene = ModelerScene(self, dialog=self) self.scene.setSceneRect( QRectF(0, 0, self.CANVAS_SIZE, self.CANVAS_SIZE)) self.view.setScene(self.scene) self.view.setAcceptDrops(True) self.view.ensureVisible(0, 0, 10, 10) def _dragEnterEvent(event): if event.mimeData().hasText(): event.acceptProposedAction() else: event.ignore() def _dropEvent(event): if event.mimeData().hasText(): itemId = event.mimeData().text() if itemId in [ param.id() for param in QgsApplication.instance(). processingRegistry().parameterTypes() ]: self.addInputOfType(itemId, event.pos()) else: alg = QgsApplication.processingRegistry( ).createAlgorithmById(itemId) if alg is not None: self._addAlgorithm(alg, event.pos()) event.accept() else: event.ignore() def _dragMoveEvent(event): if event.mimeData().hasText(): event.accept() else: event.ignore() def _wheelEvent(event): self.view.setTransformationAnchor(QGraphicsView.AnchorUnderMouse) settings = QgsSettings() factor = settings.value('/qgis/zoom_favor', 2.0) # "Normal" mouse has an angle delta of 120, precision mouses provide data # faster, in smaller steps factor = 1.0 + (factor - 1.0) / 120.0 * abs(event.angleDelta().y()) if (event.modifiers() == Qt.ControlModifier): factor = 1.0 + (factor - 1.0) / 20.0 if event.angleDelta().y() < 0: factor = 1 / factor self.view.scale(factor, factor) def _enterEvent(e): QGraphicsView.enterEvent(self.view, e) self.view.viewport().setCursor(Qt.ArrowCursor) def _mouseReleaseEvent(e): QGraphicsView.mouseReleaseEvent(self.view, e) self.view.viewport().setCursor(Qt.ArrowCursor) def _mousePressEvent(e): if e.button() == Qt.MidButton: self.previousMousePos = e.pos() else: QGraphicsView.mousePressEvent(self.view, e) def _mouseMoveEvent(e): if e.buttons() == Qt.MidButton: offset = self.previousMousePos - e.pos() self.previousMousePos = e.pos() self.view.verticalScrollBar().setValue( self.view.verticalScrollBar().value() + offset.y()) self.view.horizontalScrollBar().setValue( self.view.horizontalScrollBar().value() + offset.x()) else: QGraphicsView.mouseMoveEvent(self.view, e) self.view.setDragMode(QGraphicsView.ScrollHandDrag) self.view.dragEnterEvent = _dragEnterEvent self.view.dropEvent = _dropEvent self.view.dragMoveEvent = _dragMoveEvent self.view.wheelEvent = _wheelEvent self.view.enterEvent = _enterEvent self.view.mousePressEvent = _mousePressEvent self.view.mouseMoveEvent = _mouseMoveEvent def _mimeDataInput(items): mimeData = QMimeData() text = items[0].data(0, Qt.UserRole) mimeData.setText(text) return mimeData self.inputsTree.mimeData = _mimeDataInput self.inputsTree.setDragDropMode(QTreeWidget.DragOnly) self.inputsTree.setDropIndicatorShown(True) def _mimeDataAlgorithm(items): item = items[0] mimeData = None if isinstance(item, TreeAlgorithmItem): mimeData = QMimeData() mimeData.setText(item.alg.id()) return mimeData self.algorithmTree.mimeData = _mimeDataAlgorithm self.algorithmTree.setDragDropMode(QTreeWidget.DragOnly) self.algorithmTree.setDropIndicatorShown(True) if hasattr(self.searchBox, 'setPlaceholderText'): self.searchBox.setPlaceholderText( QCoreApplication.translate('ModelerDialog', 'Search…')) if hasattr(self.textName, 'setPlaceholderText'): self.textName.setPlaceholderText(self.tr('Enter model name here')) if hasattr(self.textGroup, 'setPlaceholderText'): self.textGroup.setPlaceholderText(self.tr('Enter group name here')) # Connect signals and slots self.inputsTree.doubleClicked.connect(self.addInput) self.searchBox.textChanged.connect(self.textChanged) self.algorithmTree.doubleClicked.connect(self.addAlgorithm) # Ctrl+= should also trigger a zoom in action ctrlEquals = QShortcut(QKeySequence("Ctrl+="), self) ctrlEquals.activated.connect(self.zoomIn) self.mActionOpen.triggered.connect(self.openModel) self.mActionSave.triggered.connect(self.save) self.mActionSaveAs.triggered.connect(self.saveAs) self.mActionZoomIn.triggered.connect(self.zoomIn) self.mActionZoomOut.triggered.connect(self.zoomOut) self.mActionZoomActual.triggered.connect(self.zoomActual) self.mActionZoomToItems.triggered.connect(self.zoomToItems) self.mActionExportImage.triggered.connect(self.exportAsImage) self.mActionExportPdf.triggered.connect(self.exportAsPdf) self.mActionExportSvg.triggered.connect(self.exportAsSvg) #self.mActionExportPython.triggered.connect(self.exportAsPython) self.mActionEditHelp.triggered.connect(self.editHelp) self.mActionRun.triggered.connect(self.runModel) if model is not None: self.model = model.create() self.model.setSourceFilePath(model.sourceFilePath()) self.textGroup.setText(self.model.group()) self.textName.setText(self.model.displayName()) self.repaintModel() else: self.model = QgsProcessingModelAlgorithm() self.model.setProvider( QgsApplication.processingRegistry().providerById('model')) self.fillInputsTree() self.fillTreeUsingProviders() self.view.centerOn(0, 0) self.help = None self.hasChanged = False
def doCheck(self, feedback): layer = dataobjects.getObjectFromUri( self.getParameterValue(self.INPUT_LAYER)) settings = QgsSettings() method = int(settings.value(settings_method_key, 1)) valid_output = self.getOutputFromName(self.VALID_OUTPUT) valid_fields = layer.fields() valid_writer = valid_output.getVectorWriter( valid_fields, layer.wkbType(), layer.crs()) valid_count = 0 invalid_output = self.getOutputFromName(self.INVALID_OUTPUT) invalid_fields = layer.fields().toList() + [ QgsField(name='_errors', type=QVariant.String, len=255)] invalid_writer = invalid_output.getVectorWriter( invalid_fields, layer.wkbType(), layer.crs()) invalid_count = 0 error_output = self.getOutputFromName(self.ERROR_OUTPUT) error_fields = [ QgsField(name='message', type=QVariant.String, len=255)] error_writer = error_output.getVectorWriter( error_fields, QgsWkbTypes.Point, layer.crs()) error_count = 0 features = vector.features(layer) total = 100.0 / len(features) for current, inFeat in enumerate(features): geom = inFeat.geometry() attrs = inFeat.attributes() valid = True if not geom.isNull() and not geom.isEmpty(): errors = list(geom.validateGeometry()) if errors: # QGIS method return a summary at the end if method == 1: errors.pop() valid = False reasons = [] for error in errors: errFeat = QgsFeature() error_geom = QgsGeometry.fromPoint(error.where()) errFeat.setGeometry(error_geom) errFeat.setAttributes([error.what()]) error_writer.addFeature(errFeat) error_count += 1 reasons.append(error.what()) reason = "\n".join(reasons) if len(reason) > 255: reason = reason[:252] + '...' attrs.append(reason) outFeat = QgsFeature() outFeat.setGeometry(geom) outFeat.setAttributes(attrs) if valid: valid_writer.addFeature(outFeat) valid_count += 1 else: invalid_writer.addFeature(outFeat) invalid_count += 1 feedback.setProgress(int(current * total)) del valid_writer del invalid_writer del error_writer if valid_count == 0: valid_output.open = False if invalid_count == 0: invalid_output.open = False if error_count == 0: error_output.open = False
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(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) 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 __init__(self, algType, alg): super(ScriptEditorDialog, self).__init__(None) self.setupUi(self) self.setWindowFlags(Qt.WindowMinimizeButtonHint | Qt.WindowMaximizeButtonHint | Qt.WindowCloseButtonHint) settings = QgsSettings() self.restoreState(settings.value("/Processing/stateScriptEditor", QByteArray())) self.restoreGeometry(settings.value("/Processing/geometryScriptEditor", QByteArray())) iconSize = int(settings.value("iconsize", 24)) self.toolBar.setIconSize(QSize(iconSize, iconSize)) self.actionOpenScript.setIcon( QgsApplication.getThemeIcon('/mActionFileOpen.svg')) self.actionSaveScript.setIcon( QgsApplication.getThemeIcon('/mActionFileSave.svg')) self.actionSaveScriptAs.setIcon( QgsApplication.getThemeIcon('/mActionFileSaveAs.svg')) self.actionEditScriptHelp.setIcon( QgsApplication.getThemeIcon('/mActionEditHelpContent.svg')) self.actionRunScript.setIcon( QgsApplication.getThemeIcon('/mActionStart.svg')) self.actionCut.setIcon( QgsApplication.getThemeIcon('/mActionEditCut.svg')) self.actionCopy.setIcon( QgsApplication.getThemeIcon('/mActionEditCopy.svg')) self.actionPaste.setIcon( QgsApplication.getThemeIcon('/mActionEditPaste.svg')) self.actionUndo.setIcon( QgsApplication.getThemeIcon('/mActionUndo.svg')) self.actionRedo.setIcon( QgsApplication.getThemeIcon('/mActionRedo.svg')) self.actionIncreaseFontSize.setIcon( QgsApplication.getThemeIcon('/mActionIncreaseFont.svg')) self.actionDecreaseFontSize.setIcon( QgsApplication.getThemeIcon('/mActionDecreaseFont.svg')) # Connect signals and slots self.actionOpenScript.triggered.connect(self.openScript) self.actionSaveScript.triggered.connect(self.save) self.actionSaveScriptAs.triggered.connect(self.saveAs) self.actionEditScriptHelp.triggered.connect(self.editHelp) self.actionRunScript.triggered.connect(self.runAlgorithm) self.actionCut.triggered.connect(self.editor.cut) self.actionCopy.triggered.connect(self.editor.copy) self.actionPaste.triggered.connect(self.editor.paste) self.actionUndo.triggered.connect(self.editor.undo) self.actionRedo.triggered.connect(self.editor.redo) self.actionIncreaseFontSize.triggered.connect(self.editor.zoomIn) self.actionDecreaseFontSize.triggered.connect(self.editor.zoomOut) self.editor.textChanged.connect(lambda: self.setHasChanged(True)) self.alg = alg self.algType = algType self.snippets = {} if self.algType == self.SCRIPT_PYTHON: path = os.path.join(os.path.dirname(os.path.dirname(__file__)), "script", "snippets.py") with codecs.open(path, 'r', encoding='utf-8') as f: lines = f.readlines() snippetlines = [] name = None for line in lines: if line.startswith("##"): if snippetlines: self.snippets[name] = "".join(snippetlines) name = line[2:] snippetlines = [] else: snippetlines.append(line) if snippetlines: self.snippets[name] = "".join(snippetlines) #if self.snippets: # self.btnSnippets.setVisible(False) if self.alg is not None: self.filename = self.alg.descriptionFile self.editor.setText(self.alg.script) else: self.filename = None self.update = False self.help = None self.setHasChanged(False) self.editor.setLexerType(self.algType)
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)
subprocess.call([ cmd, '{}'.format( os.path.join(os.path.dirname(__file__), 'scripts', 'modules_installer.py')), ','.join(install_libraries) ]) else: error = traceback.format_exc() QgsMessageLog.logMessage(error, tag="PyArchInit", level=Qgis.Critical) else: pass s = QgsSettings() if not Pyarchinit_OS_Utility.checkGraphvizInstallation() and s.value( 'pyArchInit/graphvizBinPath'): os.environ['PATH'] += os.pathsep + os.path.normpath( s.value('pyArchInit/graphvizBinPath')) if not Pyarchinit_OS_Utility.checkRInstallation() and s.value( 'pyArchInit/rBinPath'): os.environ['PATH'] += os.pathsep + os.path.normpath( s.value('pyArchInit/rBinPath')) packages = [ 'PypeR', 'graphviz==0.8.3', ] for p in packages: from qgis.PyQt.QtWidgets import QMessageBox if p.startswith('PypeR'):
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 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, self.param.createFileFilter()) 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)
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 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(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_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_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) # 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') # 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 __init__(self, alg=None): super(ModelerDialog, self).__init__(None) self.setupUi(self) self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.centralWidget().layout().insertWidget(0, self.bar) try: self.setDockOptions(self.dockOptions() | QMainWindow.GroupedDragging) except: pass self.addDockWidget(Qt.LeftDockWidgetArea, self.propertiesDock) self.addDockWidget(Qt.LeftDockWidgetArea, self.inputsDock) self.addDockWidget(Qt.LeftDockWidgetArea, self.algorithmsDock) self.tabifyDockWidget(self.inputsDock, self.algorithmsDock) self.inputsDock.raise_() self.zoom = 1 self.setWindowFlags(Qt.WindowMinimizeButtonHint | Qt.WindowMaximizeButtonHint | Qt.WindowCloseButtonHint) settings = QgsSettings() self.restoreState( settings.value("/Processing/stateModeler", QByteArray())) self.restoreGeometry( settings.value("/Processing/geometryModeler", QByteArray())) self.scene = ModelerScene(self) self.scene.setSceneRect( QRectF(0, 0, self.CANVAS_SIZE, self.CANVAS_SIZE)) self.view.setScene(self.scene) self.view.setAcceptDrops(True) self.view.ensureVisible(0, 0, 10, 10) def _dragEnterEvent(event): if event.mimeData().hasText(): event.acceptProposedAction() else: event.ignore() def _dropEvent(event): if event.mimeData().hasText(): text = event.mimeData().text() if text in ModelerParameterDefinitionDialog.paramTypes: self.addInputOfType(text, event.pos()) else: alg = QgsApplication.processingRegistry().algorithmById( text) if alg is not None: self._addAlgorithm(alg.getCopy(), event.pos()) event.accept() else: event.ignore() def _dragMoveEvent(event): if event.mimeData().hasText(): event.accept() else: event.ignore() def _wheelEvent(event): self.view.setTransformationAnchor(QGraphicsView.AnchorUnderMouse) settings = QgsSettings() factor = settings.value('/qgis/zoom_favor', 2.0) if (event.modifiers() == Qt.ControlModifier): factor = 1.0 + (factor - 1.0) / 20.0 if event.angleDelta().y() < 0: factor = 1 / factor self.view.scale(factor, factor) self.repaintModel() def _enterEvent(e): QGraphicsView.enterEvent(self.view, e) self.view.viewport().setCursor(Qt.ArrowCursor) def _mouseReleaseEvent(e): QGraphicsView.mouseReleaseEvent(self.view, e) self.view.viewport().setCursor(Qt.ArrowCursor) def _mousePressEvent(e): if e.button() == Qt.MidButton: self.previousMousePos = e.pos() else: QGraphicsView.mousePressEvent(self.view, e) def _mouseMoveEvent(e): if e.buttons() == Qt.MidButton: offset = self.previousMousePos - e.pos() self.previousMousePos = e.pos() self.view.verticalScrollBar().setValue( self.view.verticalScrollBar().value() + offset.y()) self.view.horizontalScrollBar().setValue( self.view.horizontalScrollBar().value() + offset.x()) else: QGraphicsView.mouseMoveEvent(self.view, e) self.view.setDragMode(QGraphicsView.ScrollHandDrag) self.view.dragEnterEvent = _dragEnterEvent self.view.dropEvent = _dropEvent self.view.dragMoveEvent = _dragMoveEvent self.view.wheelEvent = _wheelEvent self.view.enterEvent = _enterEvent self.view.mousePressEvent = _mousePressEvent self.view.mouseMoveEvent = _mouseMoveEvent def _mimeDataInput(items): mimeData = QMimeData() text = items[0].text(0) mimeData.setText(text) return mimeData self.inputsTree.mimeData = _mimeDataInput self.inputsTree.setDragDropMode(QTreeWidget.DragOnly) self.inputsTree.setDropIndicatorShown(True) def _mimeDataAlgorithm(items): item = items[0] if isinstance(item, TreeAlgorithmItem): mimeData = QMimeData() mimeData.setText(item.alg.id()) return mimeData self.algorithmTree.mimeData = _mimeDataAlgorithm self.algorithmTree.setDragDropMode(QTreeWidget.DragOnly) self.algorithmTree.setDropIndicatorShown(True) if hasattr(self.searchBox, 'setPlaceholderText'): self.searchBox.setPlaceholderText(self.tr('Search...')) if hasattr(self.textName, 'setPlaceholderText'): self.textName.setPlaceholderText(self.tr('Enter model name here')) if hasattr(self.textGroup, 'setPlaceholderText'): self.textGroup.setPlaceholderText(self.tr('Enter group name here')) # Connect signals and slots self.inputsTree.doubleClicked.connect(self.addInput) self.searchBox.textChanged.connect(self.fillAlgorithmTree) self.algorithmTree.doubleClicked.connect(self.addAlgorithm) # Ctrl+= should also trigger a zoom in action ctrlEquals = QShortcut(QKeySequence("Ctrl+="), self) ctrlEquals.activated.connect(self.zoomIn) try: iconSize = int(settings.value("iconsize", 24)) except: iconSize = 24 self.mToolbar.setIconSize(QSize(iconSize, iconSize)) self.mActionOpen.triggered.connect(self.openModel) self.mActionSave.triggered.connect(self.save) self.mActionSaveAs.triggered.connect(self.saveAs) self.mActionZoomIn.triggered.connect(self.zoomIn) self.mActionZoomOut.triggered.connect(self.zoomOut) self.mActionZoomActual.triggered.connect(self.zoomActual) self.mActionZoomToItems.triggered.connect(self.zoomToItems) self.mActionExportImage.triggered.connect(self.exportAsImage) self.mActionExportPdf.triggered.connect(self.exportAsPdf) self.mActionExportSvg.triggered.connect(self.exportAsSvg) self.mActionExportPython.triggered.connect(self.exportAsPython) self.mActionEditHelp.triggered.connect(self.editHelp) self.mActionRun.triggered.connect(self.runModel) if alg is not None: self.alg = alg self.textGroup.setText(alg._group) self.textName.setText(alg.displayName()) self.repaintModel() else: self.alg = ModelerAlgorithm() self.alg.modelerdialog = self self.fillInputsTree() self.fillAlgorithmTree() self.view.centerOn(0, 0) self.alg.setModelerView(self) self.help = None self.hasChanged = False
def __init__( self, # pylint: disable=too-many-locals,too-many-statements service_type, event_service, event_start_date=None, event_end_date=None, event_min_magnitude=None, event_max_magnitude=None, limit_extent_rect=False, min_latitude=None, max_latitude=None, min_longitude=None, max_longitude=None, limit_extent_circle=False, circle_latitude=None, circle_longitude=None, circle_min_radius=None, circle_max_radius=None, circle_radius_unit=QgsUnitTypes.DistanceDegrees, earthquake_number_mdps_greater=None, earthquake_max_intensity_greater=None, event_ids=None, contributor_id=None, network_codes=None, station_codes=None, locations=None, parent=None, output_fields=None, output_type=EXTENDED, convert_negative_depths=False, depth_unit=QgsUnitTypes.DistanceMeters, event_type: Optional[str] = None, updated_after: Optional[QDateTime] = None, split_strategy: Optional[str] = None, styles: Dict[str, str] = None, url=None): super().__init__(parent=parent) self.service_type = service_type self.service_id = event_service self.service_config = SERVICE_MANAGER.service_details( self.service_type, self.service_id) self.split_strategy = split_strategy self.exceeded_limit = False self.event_start_date = event_start_date self.event_end_date = event_end_date # if we have a split strategy set, we HAVE to have a full date range available if self.split_strategy is not None and self.event_start_date is None: self.event_start_date = QDateTime.fromString( self.service_config.get('datestart'), Qt.ISODate) if self.split_strategy is not None and self.event_end_date is None: self.event_end_date = QDateTime.fromString( self.service_config.get('dateend'), Qt.ISODate) if self.service_config.get( 'dateend') else QDateTime.currentDateTime() self.event_start_date_limit = self.event_start_date self.event_end_date_limit = self.event_end_date if self.split_strategy is not None: self.ranges = Fetcher.split_range_by_strategy( self.split_strategy, self.event_start_date, self.event_end_date) self.event_start_date, self.event_end_date = self.ranges[0] del self.ranges[0] else: self.ranges = None self.event_min_magnitude = event_min_magnitude self.event_max_magnitude = event_max_magnitude self.event_type = event_type self.limit_extent_rect = limit_extent_rect self.min_latitude = min_latitude self.max_latitude = max_latitude self.min_longitude = min_longitude self.max_longitude = max_longitude self.limit_extent_circle = limit_extent_circle self.circle_latitude = circle_latitude self.circle_longitude = circle_longitude self.circle_min_radius = circle_min_radius self.circle_max_radius = circle_max_radius self.circle_radius_unit = circle_radius_unit self.earthquake_number_mdps_greater = earthquake_number_mdps_greater self.earthquake_max_intensity_greater = earthquake_max_intensity_greater self.event_ids = event_ids self.contributor_id = contributor_id self.network_codes = network_codes self.station_codes = station_codes self.locations = locations self.pending_event_ids = event_ids self.macro_pending_event_ids = event_ids self.output_type = output_type self.convert_negative_depths = convert_negative_depths self.depth_unit = depth_unit self.updated_after = updated_after self.url = url s = QgsSettings() self.preferred_origins_only = s.value('/plugins/qquake/output_preferred_origins', True, bool) or not \ self.service_config['settings'].get('queryincludeallorigins', False) self.preferred_magnitudes_only = s.value('/plugins/qquake/output_preferred_magnitude', True, bool) or not \ self.service_config['settings'].get('queryincludeallmagnitudes', False) self.preferred_mdp_only = s.value( '/plugins/qquake/output_preferred_mdp', True, bool) self.output_fields = output_fields[:] if output_fields else [] if self.output_type == self.EXTENDED: if not self.preferred_origins_only and "!IsPrefOrigin" not in self.output_fields: self.output_fields.append("!IsPrefOrigin") if not self.preferred_magnitudes_only and "!IsPrefMag" not in self.output_fields: self.output_fields.append("!IsPrefMag") if not self.preferred_mdp_only and "!IsPrefMdpset" not in self.output_fields: self.output_fields.append("!IsPrefMdpset") self.result = QuakeMlParser( convert_negative_depths=self.convert_negative_depths, depth_unit=self.depth_unit) else: self.result = BasicTextParser( convert_negative_depths=self.convert_negative_depths, depth_unit=self.depth_unit) self.missing_origins = set() self.is_missing_origin_request = False self.require_mdp_basic_text_request = self.output_type == self.BASIC and self.service_type == SERVICE_MANAGER.MACROSEISMIC self.is_mdp_basic_text_request = False self.is_first_request = True self.query_limit = None self.styles = styles
def test_settings(client) -> None: """ Test thas settings are read """ settings = QgsSettings() val = settings.value('test/foobar') assert val == '42'
def run(self): """Run method that performs all the real work""" # Create the dialog with elements (after translation) and keep reference # Only create GUI ONCE in callback, so that it will only load when the plugin is started if self.first_start == True: self.first_start = False self.dlg = HarmonyQGISDialog() # get stored settings settings = QgsSettings() # Fetch the currently loaded layers layers = QgsProject.instance().layerTreeRoot().children() layerNames = [layer.name() for layer in layers] # Clear the contents of the comboBox from previous runs self.dlg.comboBox.clear() # Populate the comboBox with names of all the loaded layers self.dlg.comboBox.addItems(layerNames) # use the previous layer as the default if it is in the existing layers # layerName = settings.value("harmony_qgis/layer") # if layerName and layerName in layerNames: # self.dlg.comboBox.setCurrentIndex(layerNames.index(layerName)) layer = self.iface.activeLayer() if layer: self.dlg.comboBox.setCurrentIndex(layerNames.index(layer.name())) # fill the harmnoy url input with the saved setting if available harmonyUrl = settings.value("harmony_qgis/harmony_url") if harmonyUrl: self.dlg.harmonyUrlLineEdit.setText(harmonyUrl) collectionId = settings.value("harmony_qgis/collection_id") if collectionId: self.dlg.collectionField.setText(collectionId) version = settings.value("harmony_qgis/version") or "1.0.0" self.dlg.versionField.setText(version) variable = settings.value("harmony_qgis/variable") if variable: self.dlg.variableField.setText(variable) # clear the table self.dlg.tableWidget.setRowCount(0) # set the table header self.dlg.tableWidget.setHorizontalHeaderLabels('Parameter;Value'.split(';')) # add a parameter/value when the 'Add' button is clicked self.dlg.addButton.clicked.connect(self.addSearchParameter) # show the dialog self.dlg.show() # Run the dialog event loop result = self.dlg.exec_() # See if OK was pressed if result: collectionId = str(self.dlg.collectionField.text()) version = str(self.dlg.versionField.text()) variable = str(self.dlg.variableField.text()) layerName = str(self.dlg.comboBox.currentText()) # TODO handle the case where there is more than one layer by this name layer = QgsProject.instance().mapLayersByName(layerName)[0] opts = QgsVectorFileWriter.SaveVectorOptions() opts.driverName = 'GeoJson' tempFile = '/tmp/qgis.json' QgsVectorFileWriter.writeAsVectorFormatV2(layer, tempFile, QgsCoordinateTransformContext(), opts) harmonyUrl = self.dlg.harmonyUrlLineEdit.text() path = collectionId + "/" + "ogc-api-coverages/" + version + "/collections/" + variable + "/coverage/rangeset" url = harmonyUrl + "/" + path print(url) tempFileHandle = open(tempFile, 'r') contents = tempFileHandle.read() tempFileHandle.close() geoJson = rewind(contents) tempFileHandle = open(tempFile, 'w') tempFileHandle.write(geoJson) tempFileHandle.close() tempFileHandle = open(tempFile, 'rb') multipart_form_data = { 'shapefile': (layerName + '.geojson', tempFileHandle, 'application/geo+json') } rowCount = self.dlg.tableWidget.rowCount() for row in range(rowCount): parameter = self.dlg.tableWidget.item(row, 0).text() value = self.dlg.tableWidget.item(row, 1).text() multipart_form_data[parameter] = (None, value) resp = requests.post(url, files=multipart_form_data, stream=True) tempFileHandle.close() # print(resp) # print(resp.text) with open('/tmp/harmony_output_image.tif', 'wb') as fd: for chunk in resp.iter_content(chunk_size=128): fd.write(chunk) os.remove(tempFile) self.iface.addRasterLayer('/tmp/harmony_output_image.tif', layerName + '-' + variable) # QgsRasterLayer('/tmp/harmony_output_image.tif', layerName) # save settings if collectionId != "": settings.setValue("harmony_qgis/collection_id", collectionId) if version != "": settings.setValue("harmony_qgis/version", version) if variable != "": settings.setValue("harmony_qgis/variable", variable) if harmonyUrl != "": settings.setValue("harmony_qgis/harmony_url", harmonyUrl) settings.setValue("harmony_qgis/layer", layerName)