def setUp(self): QgsSettings().setValue('pythonConsole/contextHelpOnFirstLaunch', False)
def testStyle(self): # First test with invalid URI vl = QgsVectorLayer('/idont/exist.gpkg', 'test', 'ogr') self.assertFalse( vl.dataProvider().isSaveAndLoadStyleToDatabaseSupported()) related_count, idlist, namelist, desclist, errmsg = vl.listStylesInDatabase( ) self.assertEqual(related_count, -1) self.assertEqual(idlist, []) self.assertEqual(namelist, []) self.assertEqual(desclist, []) self.assertNotEqual(errmsg, "") qml, errmsg = vl.getStyleFromDatabase("1") self.assertEqual(qml, "") self.assertNotEqual(errmsg, "") qml, success = vl.loadNamedStyle('/idont/exist.gpkg') self.assertFalse(success) errorMsg = vl.saveStyleToDatabase("name", "description", False, "") self.assertNotEqual(errorMsg, "") # Now with valid URI tmpfile = os.path.join(self.basetestpath, 'testStyle.gpkg') ds = ogr.GetDriverByName('GPKG').CreateDataSource(tmpfile) lyr = ds.CreateLayer('test', geom_type=ogr.wkbMultiPolygon) lyr.CreateField(ogr.FieldDefn('foo', ogr.OFTString)) f = ogr.Feature(lyr.GetLayerDefn()) f['foo'] = 'bar' lyr.CreateFeature(f) f = None lyr = ds.CreateLayer('test2', geom_type=ogr.wkbMultiPolygon) lyr.CreateField(ogr.FieldDefn('foo', ogr.OFTString)) f = ogr.Feature(lyr.GetLayerDefn()) f['foo'] = 'bar' lyr.CreateFeature(f) f = None ds = None vl = QgsVectorLayer('{}|layername=test'.format(tmpfile), 'test', 'ogr') self.assertTrue(vl.isValid()) vl2 = QgsVectorLayer('{}|layername=test2'.format(tmpfile), 'test2', 'ogr') self.assertTrue(vl2.isValid()) self.assertTrue( vl.dataProvider().isSaveAndLoadStyleToDatabaseSupported()) related_count, idlist, namelist, desclist, errmsg = vl.listStylesInDatabase( ) self.assertEqual(related_count, 0) self.assertEqual(idlist, []) self.assertEqual(namelist, []) self.assertEqual(desclist, []) self.assertNotEqual(errmsg, "") qml, errmsg = vl.getStyleFromDatabase("not_existing") self.assertEqual(qml, "") self.assertNotEqual(errmsg, "") qml, success = vl.loadNamedStyle('{}|layerid=0'.format(tmpfile)) self.assertFalse(success) errorMsg = vl.saveStyleToDatabase("name", "description", False, "") self.assertEqual(errorMsg, "") qml, errmsg = vl.getStyleFromDatabase("not_existing") self.assertEqual(qml, "") self.assertNotEqual(errmsg, "") related_count, idlist, namelist, desclist, errmsg = vl.listStylesInDatabase( ) self.assertEqual(related_count, 1) self.assertEqual(errmsg, "") self.assertEqual(idlist, ['1']) self.assertEqual(namelist, ['name']) self.assertEqual(desclist, ['description']) qml, errmsg = vl.getStyleFromDatabase("100") self.assertEqual(qml, "") self.assertNotEqual(errmsg, "") qml, errmsg = vl.getStyleFromDatabase("1") self.assertTrue(qml.startswith('<!DOCTYPE qgis'), qml) self.assertEqual(errmsg, "") # Try overwrite it but simulate answer no settings = QgsSettings() settings.setValue("/qgis/overwriteStyle", False) errorMsg = vl.saveStyleToDatabase("name", "description_bis", False, "") self.assertNotEqual(errorMsg, "") related_count, idlist, namelist, desclist, errmsg = vl.listStylesInDatabase( ) self.assertEqual(related_count, 1) self.assertEqual(errmsg, "") self.assertEqual(idlist, ['1']) self.assertEqual(namelist, ['name']) self.assertEqual(desclist, ['description']) # Try overwrite it and simulate answer yes settings = QgsSettings() settings.setValue("/qgis/overwriteStyle", True) errorMsg = vl.saveStyleToDatabase("name", "description_bis", False, "") self.assertEqual(errorMsg, "") related_count, idlist, namelist, desclist, errmsg = vl.listStylesInDatabase( ) self.assertEqual(related_count, 1) self.assertEqual(errmsg, "") self.assertEqual(idlist, ['1']) self.assertEqual(namelist, ['name']) self.assertEqual(desclist, ['description_bis']) errorMsg = vl2.saveStyleToDatabase("name_test2", "description_test2", True, "") self.assertEqual(errorMsg, "") errorMsg = vl.saveStyleToDatabase("name2", "description2", True, "") self.assertEqual(errorMsg, "") errorMsg = vl.saveStyleToDatabase("name3", "description3", True, "") self.assertEqual(errorMsg, "") related_count, idlist, namelist, desclist, errmsg = vl.listStylesInDatabase( ) self.assertEqual(related_count, 3) self.assertEqual(errmsg, "") self.assertEqual(idlist, ['1', '3', '4', '2']) self.assertEqual(namelist, ['name', 'name2', 'name3', 'name_test2']) self.assertEqual( desclist, ['description_bis', 'description2', 'description3', 'name_test2']) # Check that layers_style table is not list in subLayers() vl = QgsVectorLayer(tmpfile, 'test', 'ogr') sublayers = vl.dataProvider().subLayers() self.assertEqual(len(sublayers), 2, sublayers)
def enableCompiler(self): QgsSettings().setValue('/qgis/compileExpressions', True)
def testPrefixes(self): """ Test custom (active) prefixes """ def got_hit(result): got_hit._results_.append(result.displayString) got_hit._results_ = [] context = QgsLocatorContext() l = QgsLocator() # filter with prefix filter_a = test_filter('a', 'aaa') l.registerFilter(filter_a) self.assertEqual(filter_a.prefix(), 'aaa') self.assertEqual(filter_a.activePrefix(), 'aaa') self.assertEqual(filter_a.useWithoutPrefix(), True) l.foundResult.connect(got_hit) l.fetchResults('aaa a', context) for i in range(100): sleep(0.002) QCoreApplication.processEvents() self.assertEqual(set(got_hit._results_), {'a0', 'a1', 'a2'}) got_hit._results_ = [] l.fetchResults('bbb b', context) for i in range(100): sleep(0.002) QCoreApplication.processEvents() self.assertEqual(set(got_hit._results_), {'a0', 'a1', 'a2'}) got_hit._results_ = [] filter_a.setUseWithoutPrefix(False) self.assertEqual(filter_a.useWithoutPrefix(), False) l.fetchResults('bbb b', context) for i in range(100): sleep(0.002) QCoreApplication.processEvents() self.assertEqual(got_hit._results_, []) got_hit._results_ = [] # test with two filters filter_b = test_filter('b', 'bbb') l.registerFilter(filter_b) self.assertEqual(filter_b.prefix(), 'bbb') self.assertEqual(filter_b.activePrefix(), 'bbb') got_hit._results_ = [] l.fetchResults('bbb b', context) for i in range(100): sleep(0.002) QCoreApplication.processEvents() self.assertEqual(set(got_hit._results_), {'b0', 'b1', 'b2'}) l.deregisterFilter(filter_b) # test with two filters with same prefix filter_b = test_filter('b', 'aaa') l.registerFilter(filter_b) self.assertEqual(filter_b.prefix(), 'aaa') self.assertEqual(filter_b.activePrefix(), 'aaa') got_hit._results_ = [] l.fetchResults('aaa b', context) for i in range(100): sleep(0.002) QCoreApplication.processEvents() self.assertEqual(set(got_hit._results_), {'a0', 'a1', 'a2', 'b0', 'b1', 'b2'}) l.deregisterFilter(filter_b) # filter with invalid prefix (less than 3 char) filter_c = test_filter('c', 'bb') l.registerFilter(filter_c) self.assertEqual(filter_c.prefix(), 'bb') self.assertEqual(filter_c.activePrefix(), '') got_hit._results_ = [] l.fetchResults('b', context) for i in range(100): sleep(0.002) QCoreApplication.processEvents() self.assertEqual(set(got_hit._results_), {'c0', 'c1', 'c2'}) l.deregisterFilter(filter_c) # filter with custom prefix QgsSettings().setValue("locator_filters/prefix_test_custom", 'xyz', QgsSettings.Gui) filter_c = test_filter('custom', 'abc') l.registerFilter(filter_c) self.assertEqual(filter_c.prefix(), 'abc') self.assertEqual(filter_c.activePrefix(), 'xyz') got_hit._results_ = [] l.fetchResults('b', context) for i in range(100): sleep(0.002) QCoreApplication.processEvents() self.assertEqual(set(got_hit._results_), {'custom0', 'custom1', 'custom2'}) l.deregisterFilter(filter_c) del l
def setUp(self): QgsSettings().clear()
def setUpClass(cls): """Run before all tests""" QCoreApplication.setOrganizationName("QGIS_Test") QCoreApplication.setOrganizationDomain("TestPyQgsAFSProvider.com") QCoreApplication.setApplicationName("TestPyQgsAFSProvider") QgsSettings().clear() start_app() # On Windows we must make sure that any backslash in the path is # replaced by a forward slash so that QUrl can process it cls.basetestpath = tempfile.mkdtemp().replace('\\', '/') endpoint = cls.basetestpath + '/fake_qgis_http_endpoint' with open(sanitize(endpoint, '?f=json'), 'wb') as f: f.write(""" {"currentVersion":10.22,"id":1,"name":"QGIS Test","type":"Feature Layer","description": "QGIS Provider Test Layer.\n","geometryType":"esriGeometryPoint","copyrightText":"","parentLayer":{"id":0,"name":"QGIS Tests"},"subLayers":[], "minScale":72225,"maxScale":0, "defaultVisibility":true, "extent":{"xmin":-71.123,"ymin":66.33,"xmax":-65.32,"ymax":78.3, "spatialReference":{"wkid":4326,"latestWkid":4326}}, "hasAttachments":false,"htmlPopupType":"esriServerHTMLPopupTypeAsHTMLText", "displayField":"LABEL","typeIdField":null, "fields":[{"name":"OBJECTID","type":"esriFieldTypeOID","alias":"OBJECTID","domain":null}, {"name":"pk","type":"esriFieldTypeInteger","alias":"pk","domain":null}, {"name":"cnt","type":"esriFieldTypeInteger","alias":"cnt","domain":null}, {"name":"name","type":"esriFieldTypeString","alias":"name","length":100,"domain":null}, {"name":"name2","type":"esriFieldTypeString","alias":"name2","length":100,"domain":null}, {"name":"num_char","type":"esriFieldTypeString","alias":"num_char","length":100,"domain":null}, {"name":"Shape","type":"esriFieldTypeGeometry","alias":"Shape","domain":null}], "relationships":[],"canModifyLayer":false,"canScaleSymbols":false,"hasLabels":false, "capabilities":"Map,Query,Data","maxRecordCount":1000,"supportsStatistics":true, "supportsAdvancedQueries":true,"supportedQueryFormats":"JSON, AMF", "ownershipBasedAccessControlForFeatures":{"allowOthersToQuery":true},"useStandardizedQueries":true}""" .encode('UTF-8')) with open( sanitize(endpoint, '/query?f=json_where=1=1&returnIdsOnly=true'), 'wb') as f: f.write(""" { "objectIdFieldName": "OBJECTID", "objectIds": [ 5, 3, 1, 2, 4 ] } """.encode('UTF-8')) # Create test layer cls.vl = QgsVectorLayer( "url='http://" + endpoint + "' crs='epsg:4326'", 'test', 'arcgisfeatureserver') assert cls.vl.isValid() cls.source = cls.vl.dataProvider() with open( sanitize( endpoint, '/query?f=json&objectIds=5,3,1,2,4&inSR=4326&outSR=4326&returnGeometry=true&outFields=OBJECTID,pk,cnt,name,name2,num_char&returnM=false&returnZ=false' ), 'wb') as f: f.write(""" { "displayFieldName": "name", "fieldAliases": { "name": "name" }, "geometryType": "esriGeometryPoint", "spatialReference": { "wkid": 4326, "latestWkid": 4326 }, "fields":[{"name":"OBJECTID","type":"esriFieldTypeOID","alias":"OBJECTID","domain":null}, {"name":"pk","type":"esriFieldTypeInteger","alias":"pk","domain":null}, {"name":"cnt","type":"esriFieldTypeInteger","alias":"cnt","domain":null}, {"name":"name","type":"esriFieldTypeString","alias":"name","length":100,"domain":null}, {"name":"name2","type":"esriFieldTypeString","alias":"name2","length":100,"domain":null}, {"name":"num_char","type":"esriFieldTypeString","alias":"num_char","length":100,"domain":null}, {"name":"Shape","type":"esriFieldTypeGeometry","alias":"Shape","domain":null}], "features": [ { "attributes": { "OBJECTID": 5, "pk": 5, "cnt": -200, "name": null, "name2":"NuLl", "num_char":"5" }, "geometry": { "x": -71.123, "y": 78.23 } }, { "attributes": { "OBJECTID": 3, "pk": 3, "cnt": 300, "name": "Pear", "name2":"PEaR", "num_char":"3" }, "geometry": null }, { "attributes": { "OBJECTID": 1, "pk": 1, "cnt": 100, "name": "Orange", "name2":"oranGe", "num_char":"1" }, "geometry": { "x": -70.332, "y": 66.33 } }, { "attributes": { "OBJECTID": 2, "pk": 2, "cnt": 200, "name": "Apple", "name2":"Apple", "num_char":"2" }, "geometry": { "x": -68.2, "y": 70.8 } }, { "attributes": { "OBJECTID": 4, "pk": 4, "cnt": 400, "name": "Honey", "name2":"Honey", "num_char":"4" }, "geometry": { "x": -65.32, "y": 78.3 } } ] }""".encode('UTF-8')) with open( sanitize( endpoint, '/query?f=json&objectIds=5,3,1,2,4&inSR=4326&outSR=4326&returnGeometry=true&outFields=OBJECTID,pk,cnt,name,name2,num_char&returnM=false&returnZ=false&geometry=-71.123000,66.330000,-65.320000,78.300000&geometryType=esriGeometryEnvelope&spatialRel=esriSpatialRelEnvelopeIntersects' ), 'wb') as f: f.write(""" { "displayFieldName": "name", "fieldAliases": { "name": "name" }, "geometryType": "esriGeometryPoint", "spatialReference": { "wkid": 4326, "latestWkid": 4326 }, "fields":[{"name":"OBJECTID","type":"esriFieldTypeOID","alias":"OBJECTID","domain":null}, {"name":"pk","type":"esriFieldTypeInteger","alias":"pk","domain":null}, {"name":"cnt","type":"esriFieldTypeInteger","alias":"cnt","domain":null}, {"name":"name","type":"esriFieldTypeString","alias":"name","length":100,"domain":null}, {"name":"name2","type":"esriFieldTypeString","alias":"name2","length":100,"domain":null}, {"name":"num_char","type":"esriFieldTypeString","alias":"num_char","length":100,"domain":null}, {"name":"Shape","type":"esriFieldTypeGeometry","alias":"Shape","domain":null}], "features": [ { "attributes": { "OBJECTID": 5, "pk": 5, "cnt": -200, "name": null, "name2":"NuLl", "num_char":"5" }, "geometry": { "x": -71.123, "y": 78.23 } }, { "attributes": { "OBJECTID": 3, "pk": 3, "cnt": 300, "name": "Pear", "name2":"PEaR", "num_char":"3" }, "geometry": null }, { "attributes": { "OBJECTID": 1, "pk": 1, "cnt": 100, "name": "Orange", "name2":"oranGe", "num_char":"1" }, "geometry": { "x": -70.332, "y": 66.33 } }, { "attributes": { "OBJECTID": 2, "pk": 2, "cnt": 200, "name": "Apple", "name2":"Apple", "num_char":"2" }, "geometry": { "x": -68.2, "y": 70.8 } }, { "attributes": { "OBJECTID": 4, "pk": 4, "cnt": 400, "name": "Honey", "name2":"Honey", "num_char":"4" }, "geometry": { "x": -65.32, "y": 78.3 } } ] }""".encode('UTF-8')) with open( sanitize( endpoint, '/query?f=json&objectIds=2,4&inSR=4326&outSR=4326&returnGeometry=true&outFields=OBJECTID,pk,cnt,name,name2,num_char&returnM=false&returnZ=false' ), 'wb') as f: f.write(""" { "displayFieldName": "name", "fieldAliases": { "name": "name" }, "geometryType": "esriGeometryPoint", "spatialReference": { "wkid": 4326, "latestWkid": 4326 }, "fields":[{"name":"OBJECTID","type":"esriFieldTypeOID","alias":"OBJECTID","domain":null}, {"name":"pk","type":"esriFieldTypeInteger","alias":"pk","domain":null}, {"name":"cnt","type":"esriFieldTypeInteger","alias":"cnt","domain":null}, {"name":"name","type":"esriFieldTypeString","alias":"name","length":100,"domain":null}, {"name":"name2","type":"esriFieldTypeString","alias":"name2","length":100,"domain":null}, {"name":"num_char","type":"esriFieldTypeString","alias":"num_char","length":100,"domain":null}, {"name":"Shape","type":"esriFieldTypeGeometry","alias":"Shape","domain":null}], "features": [ { "attributes": { "OBJECTID": 2, "pk": 2, "cnt": 200, "name": "Apple", "name2":"Apple", "num_char":"2" }, "geometry": { "x": -68.2, "y": 70.8 } }, { "attributes": { "OBJECTID": 4, "pk": 4, "cnt": 400, "name": "Honey", "name2":"Honey", "num_char":"4" }, "geometry": { "x": -65.32, "y": 78.3 } } ] }""".encode('UTF-8')) with open( sanitize( endpoint, '/query?f=json&where=1=1&returnIdsOnly=true&geometry=-70.000000,67.000000,-60.000000,80.000000&geometryType=esriGeometryEnvelope&spatialRel=esriSpatialRelEnvelopeIntersects' ), 'wb') as f: f.write(""" { "objectIdFieldName": "OBJECTID", "objectIds": [ 2, 4 ] } """.encode('UTF-8')) with open( sanitize( endpoint, '/query?f=json&where==1=&returnIdsOnly=true&geometry=-73.000000,70.000000,-63.000000,80.000000&geometryType=esriGeometryEnvelope&spatialRel=esriSpatialRelEnvelopeIntersects' ), 'wb') as f: f.write(""" { "objectIdFieldName": "OBJECTID", "objectIds": [ 2, 4 ] } """.encode('UTF-8')) with open( sanitize( endpoint, '/query?f=json&where=1=1&returnIdsOnly=true&geometry=-68.721119,68.177676,-64.678700,79.123755&geometryType=esriGeometryEnvelope&spatialRel=esriSpatialRelEnvelopeIntersects' ), 'wb') as f: f.write(""" { "objectIdFieldName": "OBJECTID", "objectIds": [ 2, 4 ] } """.encode('UTF-8'))
def reject(self): QgsSettings().setValue("RATAddRow/geometry", self.saveGeometry(), QgsSettings.Plugins) super().reject()
def uninstallPlugin(self, key, quiet=False): """ Uninstall given plugin """ if key in plugins.all(): plugin = plugins.all()[key] else: plugin = plugins.localCache[key] if not plugin: return if not quiet: warning = self.tr( "Are you sure you want to uninstall the following plugin?" ) + "\n(" + plugin["name"] + ")" if plugin["status"] == "orphan" and not plugin["error"]: warning += "\n\n" + self.tr( "Warning: this plugin isn't available in any accessible repository!" ) if QMessageBox.warning(iface.mainWindow(), self.tr("QGIS Python Plugin Installer"), warning, QMessageBox.Yes, QMessageBox.No) == QMessageBox.No: return # unload the plugin QApplication.setOverrideCursor(Qt.WaitCursor) try: unloadPlugin(key) except: pass pluginDir = qgis.utils.home_plugin_path + "/" + plugin["id"] result = removeDir(pluginDir) if result: QApplication.restoreOverrideCursor() msg = "<b>%s:</b>%s" % (self.tr("Plugin uninstall failed"), result) iface.pluginManagerInterface().pushMessage(msg, Qgis.Critical) else: # safe remove try: unloadPlugin(plugin["id"]) except: pass try: exec("plugins[%s].unload()" % plugin["id"]) exec("del plugins[%s]" % plugin["id"]) except: pass try: exec("del sys.modules[%s]" % plugin["id"]) except: pass try: exec("del plugins_metadata_parser[%s]" % plugin["id"]) except: pass plugins.getAllInstalled() plugins.rebuild() self.exportPluginsToManager() QApplication.restoreOverrideCursor() iface.pluginManagerInterface().pushMessage( self.tr("Plugin uninstalled successfully"), Qgis.Info) settings = QgsSettings() settings.remove("/PythonPlugins/" + key)
def installFromZipFile(self, filePath): if not os.path.isfile(filePath): return settings = QgsSettings() settings.setValue(settingsGroup + '/lastZipDirectory', QFileInfo(filePath).absoluteDir().absolutePath()) pluginName = None with zipfile.ZipFile(filePath, 'r') as zf: # search for metadata.txt. In case of multiple files, we can assume that # the shortest path relates <pluginname>/metadata.txt metadatafiles = sorted(f for f in zf.namelist() if f.endswith('metadata.txt')) if len(metadatafiles) > 0: pluginName = os.path.split(metadatafiles[0])[0] pluginFileName = os.path.splitext(os.path.basename(filePath))[0] if not pluginName: msg_box = QMessageBox() msg_box.setIcon(QMessageBox.Warning) msg_box.setWindowTitle( self.tr("QGIS Python Install from ZIP Plugin Installer")) msg_box.setText( self. tr("The Zip file is not a valid QGIS python plugin. No root folder was found inside." )) msg_box.setStandardButtons(QMessageBox.Ok) more_info_btn = msg_box.addButton(self.tr("More Information"), QMessageBox.HelpRole) msg_box.exec() if msg_box.clickedButton() == more_info_btn: QgsHelp.openHelp( "plugins/plugins.html#the-install-from-zip-tab") return pluginsDirectory = qgis.utils.home_plugin_path if not QDir(pluginsDirectory).exists(): QDir().mkpath(pluginsDirectory) pluginDirectory = QDir.cleanPath( os.path.join(pluginsDirectory, pluginName)) # If the target directory already exists as a link, # remove the link without resolving QFile(pluginDirectory).remove() password = None infoString = None success = False keepTrying = True while keepTrying: try: # Test extraction. If fails, then exception will be raised and no removing occurs unzip(filePath, pluginsDirectory, password) # Removing old plugin files if exist removeDir(pluginDirectory) # Extract new files unzip(filePath, pluginsDirectory, password) keepTrying = False success = True except Exception as e: success = False if 'password' in str(e): infoString = self.tr('Aborted by user') if 'Bad password' in str(e): msg = self.tr( 'Wrong password. Please enter a correct password to the zip file.' ) else: msg = self.tr( 'The zip file is encrypted. Please enter password.' ) # Display a password dialog with QgsPasswordLineEdit dlg = QDialog() dlg.setWindowTitle(self.tr('Enter password')) buttonBox = QDialogButtonBox( QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal) buttonBox.rejected.connect(dlg.reject) buttonBox.accepted.connect(dlg.accept) lePass = QgsPasswordLineEdit() layout = QVBoxLayout() layout.addWidget(QLabel(msg)) layout.addWidget(lePass) layout.addWidget(buttonBox) dlg.setLayout(layout) keepTrying = dlg.exec_() password = lePass.text() else: infoString = self.tr( "Failed to unzip the plugin package\n{}.\nProbably it is broken" .format(filePath)) keepTrying = False if success: with OverrideCursor(Qt.WaitCursor): updateAvailablePlugins() self.processDependencies(pluginName) loadPlugin(pluginName) plugins.getAllInstalled() plugins.rebuild() if settings.contains('/PythonPlugins/' + pluginName): # Plugin was available? if settings.value('/PythonPlugins/' + pluginName, False, bool): # Plugin was also active? reloadPlugin( pluginName ) # unloadPlugin + loadPlugin + startPlugin else: unloadPlugin(pluginName) loadPlugin(pluginName) else: if startPlugin(pluginName): settings.setValue('/PythonPlugins/' + pluginName, True) self.exportPluginsToManager() msg = "<b>%s</b>" % self.tr("Plugin installed successfully") else: msg = "<b>%s:</b> %s" % (self.tr("Plugin installation failed"), infoString) level = Qgis.Info if success else Qgis.Critical iface.pluginManagerInterface().pushMessage(msg, level)
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) # Autocomletion self.setAutoCompletionThreshold(2) self.setAutoCompletionSource(QsciScintilla.AcsAPIs) self.setFonts(10) self.initLexer()
def installPlugin(self, key, quiet=False, stable=True): """ Install given plugin """ error = False status_key = 'status' if stable else 'status_exp' infoString = ('', '') plugin = plugins.all()[key] previousStatus = plugin[status_key] if not plugin: return if plugin[status_key] == "newer" and not plugin[ "error"]: # ask for confirmation if user downgrades an usable plugin if QMessageBox.warning( iface.mainWindow(), self.tr("QGIS Python Plugin Installer"), self. tr("Are you sure you want to downgrade the plugin to the latest available version? The installed one is newer!" ), QMessageBox.Yes, QMessageBox.No) == QMessageBox.No: return dlg = QgsPluginInstallerInstallingDialog(iface.mainWindow(), plugin, stable=stable) dlg.exec_() plugin_path = qgis.utils.home_plugin_path + "/" + key if dlg.result(): error = True infoString = (self.tr("Plugin installation failed"), dlg.result()) elif not QDir(plugin_path).exists(): error = True infoString = ( self.tr("Plugin has disappeared"), self. tr("The plugin seems to have been installed but it's not possible to know where. The directory \"{}\" " "has not been found. Probably the plugin package contained a wrong named directory.\nPlease search " "the list of installed plugins. You should find the plugin there, but it's not possible to " "determine which of them it is and it's also not possible to inform you about available updates. " "Please contact the plugin author and submit this issue." ).format(plugin_path)) with OverrideCursor(Qt.WaitCursor): plugins.getAllInstalled() plugins.rebuild() self.exportPluginsToManager() else: QApplication.setOverrideCursor(Qt.WaitCursor) # update the list of plugins in plugin handling routines updateAvailablePlugins() self.processDependencies(plugin["id"]) # try to load the plugin loadPlugin(plugin["id"]) plugins.getAllInstalled() plugins.rebuild() plugin = plugins.all()[key] if not plugin["error"]: if previousStatus in ["not installed", "new"]: infoString = (self.tr("Plugin installed successfully"), "") if startPlugin(plugin["id"]): settings = QgsSettings() settings.setValue("/PythonPlugins/" + plugin["id"], True) else: settings = QgsSettings() if settings.value( "/PythonPlugins/" + key, False, type=bool ): # plugin will be reloaded on the fly only if currently loaded reloadPlugin( key) # unloadPlugin + loadPlugin + startPlugin infoString = ( self.tr("Plugin reinstalled successfully"), "") else: unloadPlugin( key ) # Just for a case. Will exit quietly if really not loaded loadPlugin(key) infoString = ( self.tr("Plugin reinstalled successfully"), self. tr("Python plugin reinstalled.\nYou need to restart QGIS in order to reload it." )) if quiet: infoString = (None, None) QApplication.restoreOverrideCursor() else: QApplication.restoreOverrideCursor() if plugin["error"] == "incompatible": message = self.tr( "The plugin is not compatible with this version of QGIS. It's designed for QGIS versions:" ) message += " <b>" + plugin["error_details"] + "</b>" elif plugin["error"] == "dependent": message = self.tr( "The plugin depends on some components missing on your system. You need to install the following Python module in order to enable it:" ) message += "<b> " + plugin["error_details"] + "</b>" else: message = self.tr("The plugin is broken. Python said:") message += "<br><b>" + plugin["error_details"] + "</b>" dlg = QgsPluginInstallerPluginErrorDialog( iface.mainWindow(), message) dlg.exec_() if dlg.result(): # revert installation pluginDir = qgis.utils.home_plugin_path + "/" + plugin["id"] result = removeDir(pluginDir) if QDir(pluginDir).exists(): error = True infoString = (self.tr("Plugin uninstall failed"), result) try: exec("sys.path_importer_cache.clear()") exec("import %s" % plugin["id"]) exec("reload (%s)" % plugin["id"]) except: pass else: try: exec("del sys.modules[%s]" % plugin["id"]) except: pass plugins.getAllInstalled() plugins.rebuild() self.exportPluginsToManager() if infoString[0]: level = error and Qgis.Critical or Qgis.Info msg = "<b>%s</b>" % infoString[0] if infoString[1]: msg += "<b>:</b> %s" % infoString[1] iface.pluginManagerInterface().pushMessage(msg, level)
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)
def set_service_id(self, service_id: str): # pylint:disable=too-many-branches """ Sets the associated service ID """ self.service_id = service_id service_config = SERVICE_MANAGER.service_details( self.service_type, self.service_id) if 'fields' in service_config['default']: self.output_fields = service_config['default']['fields'] if not service_config['settings'].get('outputtext', False): if self.radio_basic_output.isChecked(): self.radio_extended_output.setChecked(True) self.radio_basic_output.setEnabled(False) else: self.radio_basic_output.setEnabled(self.allow_basic_output) if not service_config['settings'].get('outputxml', False): if self.radio_extended_output.isChecked(): self.radio_basic_output.setChecked(True) self.radio_extended_output.setEnabled(False) else: self.radio_extended_output.setEnabled(True) self.block_style_changes = True s = QgsSettings() prev_event_style = s.value( '/plugins/qquake/last_event_style_{}_{}'.format( self.service_type, self.service_id), '', str) prev_mdp_style = s.value( '/plugins/qquake/last_mdp_style_{}_{}'.format( self.service_type, self.service_id), '', str) prev_station_style = s.value( '/plugins/qquake/last_station_style_{}_{}'.format( self.service_type, self.service_id), '', str) default_style_index = self.combo_style_macro.findText(prev_mdp_style) if prev_mdp_style and default_style_index >= 0: self.combo_style_macro.setCurrentIndex(default_style_index) elif isinstance(service_config['default'].get('style'), dict) and 'mdp' in service_config['default']['style']: default_style_index = self.combo_style_macro.findText( service_config['default']['style']['mdp'].get('style', '')) if default_style_index >= 0: self.combo_style_macro.setCurrentIndex(default_style_index) default_style_index = self.combo_style_epicentres.findText( prev_event_style) if prev_event_style and default_style_index >= 0: self.combo_style_epicentres.setCurrentIndex(default_style_index) elif isinstance( service_config['default']['style'], dict) and 'events' in service_config['default']['style']: default_style_index = self.combo_style_epicentres.findText( service_config['default']['style']['events'].get('style', '')) if default_style_index >= 0: self.combo_style_epicentres.setCurrentIndex( default_style_index) default_style_index = self.combo_style_stations.findText( prev_station_style) if prev_station_style and default_style_index >= 0: self.combo_style_stations.setCurrentIndex(default_style_index) elif isinstance( service_config['default']['style'], dict) and 'stations' in service_config['default']['style']: default_style_index = self.combo_style_stations.findText( service_config['default']['style']['stations'].get( 'style', '')) if default_style_index >= 0: self.combo_style_stations.setCurrentIndex(default_style_index) self.block_style_changes = False
def save(self, qsettings=QgsSettings()): if self.valuetype == self.SELECTION: qsettings.setValue(self.qname, self.options.index(self.value)) else: qsettings.setValue(self.qname, self.value)
def __init__(self, model=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, 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(): 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, 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].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 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.fillAlgorithmTree() self.view.centerOn(0, 0) self.help = None self.hasChanged = False
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())) self.toolBar.setIconSize(iface.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)
def tearDownClass(cls): """Run after all tests""" QgsSettings().clear() #shutil.rmtree(cls.basetestpath, True) cls.vl = None # so as to properly close the provider and remove any temporary file
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', QgsMessageLog.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( e.message + 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', QgsMessageLog.INFO) GdalUtils.consoleOutput = loglines
def accept(self): description = self.nameTextBox.text() if description.strip() == '': QMessageBox.warning(self, self.tr('Unable to define parameter'), self.tr('Invalid parameter name')) return if self.param is None: validChars = \ 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' safeName = ''.join(c for c in description if c in validChars) name = safeName.lower() i = 2 while self.alg.parameterDefinition(name): name = safeName.lower() + str(i) i += 1 else: name = self.param.name() if (self.paramType == parameters.PARAMETER_BOOLEAN or isinstance(self.param, QgsProcessingParameterBoolean)): self.param = QgsProcessingParameterBoolean(name, description, self.state.isChecked()) elif (self.paramType == parameters.PARAMETER_TABLE_FIELD or isinstance(self.param, QgsProcessingParameterField)): if self.parentCombo.currentIndex() < 0: QMessageBox.warning(self, self.tr('Unable to define parameter'), self.tr('Wrong or missing parameter values')) return parent = self.parentCombo.currentData() datatype = self.datatypeCombo.currentData() default = self.defaultTextBox.text() if not default: default = None self.param = QgsProcessingParameterField(name, description, defaultValue=default, parentLayerParameterName=parent, type=datatype, allowMultiple=self.multipleCheck.isChecked()) elif (self.paramType == parameters.PARAMETER_BAND or isinstance(self.param, QgsProcessingParameterBand)): if self.parentCombo.currentIndex() < 0: QMessageBox.warning(self, self.tr('Unable to define parameter'), self.tr('Wrong or missing parameter values')) return parent = self.parentCombo.currentData() self.param = QgsProcessingParameterBand(name, description, None, parent) elif (self.paramType == parameters.PARAMETER_MAP_LAYER or isinstance(self.param, QgsProcessingParameterMapLayer)): self.param = QgsProcessingParameterMapLayer( name, description) elif (self.paramType == parameters.PARAMETER_RASTER or isinstance(self.param, QgsProcessingParameterRasterLayer)): self.param = QgsProcessingParameterRasterLayer( name, description) elif (self.paramType == parameters.PARAMETER_TABLE or isinstance(self.param, QgsProcessingParameterVectorLayer)): self.param = QgsProcessingParameterVectorLayer( name, description, [self.shapetypeCombo.currentData()]) elif (self.paramType == parameters.PARAMETER_VECTOR or isinstance(self.param, QgsProcessingParameterFeatureSource)): self.param = QgsProcessingParameterFeatureSource( name, description, [self.shapetypeCombo.currentData()]) elif (self.paramType == parameters.PARAMETER_MULTIPLE or isinstance(self.param, QgsProcessingParameterMultipleLayers)): self.param = QgsProcessingParameterMultipleLayers( name, description, self.datatypeCombo.currentData()) elif (self.paramType == parameters.PARAMETER_NUMBER or isinstance(self.param, (QgsProcessingParameterNumber, QgsProcessingParameterDistance))): try: self.param = QgsProcessingParameterNumber(name, description, QgsProcessingParameterNumber.Double, self.defaultTextBox.text()) vmin = self.minTextBox.text().strip() if not vmin == '': self.param.setMinimum(float(vmin)) vmax = self.maxTextBox.text().strip() if not vmax == '': self.param.setMaximum(float(vmax)) except: QMessageBox.warning(self, self.tr('Unable to define parameter'), self.tr('Wrong or missing parameter values')) return elif (self.paramType == parameters.PARAMETER_EXPRESSION or isinstance(self.param, QgsProcessingParameterExpression)): parent = self.parentCombo.currentData() self.param = QgsProcessingParameterExpression(name, description, str(self.defaultEdit.expression()), parent) elif (self.paramType == parameters.PARAMETER_STRING or isinstance(self.param, QgsProcessingParameterString)): self.param = QgsProcessingParameterString(name, description, str(self.defaultTextBox.text())) elif (self.paramType == parameters.PARAMETER_EXTENT or isinstance(self.param, QgsProcessingParameterExtent)): self.param = QgsProcessingParameterExtent(name, description) elif (self.paramType == parameters.PARAMETER_FILE or isinstance(self.param, QgsProcessingParameterFile)): isFolder = self.fileFolderCombo.currentIndex() == 1 self.param = QgsProcessingParameterFile(name, description, QgsProcessingParameterFile.Folder if isFolder else QgsProcessingParameterFile.File) elif (self.paramType == parameters.PARAMETER_POINT or isinstance(self.param, QgsProcessingParameterPoint)): self.param = QgsProcessingParameterPoint(name, description, str(self.defaultTextBox.text())) elif (self.paramType == parameters.PARAMETER_CRS or isinstance(self.param, QgsProcessingParameterCrs)): self.param = QgsProcessingParameterCrs(name, description, self.selector.crs().authid()) elif (self.paramType == parameters.PARAMETER_ENUM or isinstance(self.param, QgsProcessingParameterEnum)): self.param = QgsProcessingParameterEnum(name, description, self.widget.options(), self.widget.allowMultiple(), self.widget.defaultOptions()) elif (self.paramType == parameters.PARAMETER_MATRIX or isinstance(self.param, QgsProcessingParameterMatrix)): self.param = QgsProcessingParameterMatrix(name, description, hasFixedNumberRows=self.widget.fixedRows(), headers=self.widget.headers(), defaultValue=self.widget.value()) # Destination parameter elif (isinstance(self.param, QgsProcessingParameterFeatureSink)): self.param = QgsProcessingParameterFeatureSink( name=name, description=self.param.description(), type=self.param.dataType(), defaultValue=self.defaultWidget.getValue()) elif (isinstance(self.param, QgsProcessingParameterFileDestination)): self.param = QgsProcessingParameterFileDestination( name=name, description=self.param.description(), fileFilter=self.param.fileFilter(), defaultValue=self.defaultWidget.getValue()) elif (isinstance(self.param, QgsProcessingParameterFolderDestination)): self.param = QgsProcessingParameterFolderDestination( name=name, description=self.param.description(), defaultValue=self.defaultWidget.getValue()) elif (isinstance(self.param, QgsProcessingParameterRasterDestination)): self.param = QgsProcessingParameterRasterDestination( name=name, description=self.param.description(), defaultValue=self.defaultWidget.getValue()) elif (isinstance(self.param, QgsProcessingParameterVectorDestination)): self.param = QgsProcessingParameterVectorDestination( name=name, description=self.param.description(), type=self.param.dataType(), defaultValue=self.defaultWidget.getValue()) else: if self.paramType: typeId = self.paramType else: typeId = self.param.type() paramTypeDef = QgsApplication.instance().processingRegistry().parameterType(typeId) if not paramTypeDef: msg = self.tr('The parameter `{}` is not registered, are you missing a required plugin?'.format(typeId)) raise UndefinedParameterException(msg) self.param = paramTypeDef.create(name) self.param.setDescription(description) self.param.setMetadata(paramTypeDef.metadata()) if not self.requiredCheck.isChecked(): self.param.setFlags(self.param.flags() | QgsProcessingParameterDefinition.FlagOptional) else: self.param.setFlags(self.param.flags() & ~QgsProcessingParameterDefinition.FlagOptional) settings = QgsSettings() settings.setValue("/Processing/modelParametersDefinitionDialogGeometry", self.saveGeometry()) QDialog.accept(self)
def __init__(self, parent=None): super(ShellScintilla, self).__init__(parent) code.InteractiveInterpreter.__init__(self, locals=None) self.parent = parent self.opening = ['(', '{', '[', "'", '"'] self.closing = [')', '}', ']', "'", '"'] self.settings = QgsSettings() self.new_input_line = True self.setCaretLineVisible(False) self.setMarginLineNumbers(0, False) # NO linenumbers for the input line self.buffer = [] self.continuationLine = False self.displayPrompt(self.continuationLine) for line in _init_commands: self.runsource(line) self.history = [] self.softHistory = [''] self.softHistoryIndex = 0 # Read history command file self.readHistoryFile() self.historyDlg = HistoryDialog(self) # Brace matching: enable for a brace immediately before or after # the current position self.setBraceMatching(QsciScintilla.SloppyBraceMatch) self.refreshSettingsShell() # Don't want to see the horizontal scrollbar at all # Use raw message to Scintilla here (all messages are documented # here: http://www.scintilla.org/ScintillaDoc.html) self.SendScintilla(QsciScintilla.SCI_SETHSCROLLBAR, 0) # not too small # self.setMinimumSize(500, 300) self.setWrapMode(QsciScintilla.WrapCharacter) self.SendScintilla(QsciScintilla.SCI_EMPTYUNDOBUFFER) # Disable command key ctrl, shift = self.SCMOD_CTRL << 16, self.SCMOD_SHIFT << 16 self.SendScintilla(QsciScintilla.SCI_CLEARCMDKEY, ord('L') + ctrl) self.SendScintilla(QsciScintilla.SCI_CLEARCMDKEY, ord('T') + ctrl) self.SendScintilla(QsciScintilla.SCI_CLEARCMDKEY, ord('D') + ctrl) self.SendScintilla(QsciScintilla.SCI_CLEARCMDKEY, ord('Z') + ctrl) self.SendScintilla(QsciScintilla.SCI_CLEARCMDKEY, ord('Y') + ctrl) self.SendScintilla(QsciScintilla.SCI_CLEARCMDKEY, ord('L') + ctrl + shift) # New QShortcut = ctrl+space/ctrl+alt+space for Autocomplete self.newShortcutCSS = QShortcut( QKeySequence(Qt.CTRL + Qt.SHIFT + Qt.Key_Space), self) self.newShortcutCAS = QShortcut( QKeySequence(Qt.CTRL + Qt.ALT + Qt.Key_Space), self) self.newShortcutCSS.setContext(Qt.WidgetShortcut) self.newShortcutCAS.setContext(Qt.WidgetShortcut) self.newShortcutCAS.activated.connect(self.autoCompleteKeyBinding) self.newShortcutCSS.activated.connect(self.showHistory)
def closeEvent(self, event): settings = QgsSettings() settings.setValue("/Processing/modelParametersDialogGeometry", self.saveGeometry()) super(ModelerParametersDialog, self).closeEvent(event)
def testSetSequence(self): """ test setting key sequences """ QgsSettings().clear() s = QgsShortcutsManager(None) shortcut1 = QShortcut(None) shortcut1.setObjectName('shortcut1') shortcut2 = QShortcut(None) shortcut2.setObjectName('shortcut2') action1 = QAction('action1', None) action2 = QAction('action2', None) s.registerShortcut(shortcut1, 'A') s.registerShortcut(shortcut2, 'B') s.registerAction(action1, 'C') s.registerAction(action2, 'D') # test setting by action/shortcut self.assertTrue(s.setKeySequence(shortcut1, 'E')) self.assertTrue(s.setKeySequence(shortcut2, 'F')) self.assertTrue(s.setKeySequence(action1, 'G')) self.assertTrue(s.setKeySequence(action2, 'H')) # test that action/shortcuts have been updated self.assertEqual(shortcut1.key().toString(), 'E') self.assertEqual(shortcut2.key().toString(), 'F') self.assertEqual(action1.shortcut().toString(), 'G') self.assertEqual(action2.shortcut().toString(), 'H') # new manager s = QgsShortcutsManager(None) # new shortcuts shortcut1 = QShortcut(None) shortcut1.setObjectName('shortcut1') shortcut2 = QShortcut(None) shortcut2.setObjectName('shortcut2') action1 = QAction('action1', None) action2 = QAction('action2', None) # register them s.registerShortcut(shortcut1, 'A') s.registerShortcut(shortcut2, 'B') s.registerAction(action1, 'C') s.registerAction(action2, 'D') # check that previously set sequence has been restored self.assertEqual(shortcut1.key().toString(), 'E') self.assertEqual(shortcut2.key().toString(), 'F') self.assertEqual(action1.shortcut().toString(), 'G') self.assertEqual(action2.shortcut().toString(), 'H') # same test, using setObjectKeySequence QgsSettings().clear() s = QgsShortcutsManager(None) shortcut1 = QShortcut(None) shortcut1.setObjectName('shortcut1') action1 = QAction('action1', None) s.registerShortcut(shortcut1, 'A') s.registerAction(action1, 'C') self.assertTrue(s.setObjectKeySequence(shortcut1, 'E')) self.assertTrue(s.setObjectKeySequence(action1, 'G')) self.assertEqual(shortcut1.key().toString(), 'E') self.assertEqual(action1.shortcut().toString(), 'G') s = QgsShortcutsManager(None) shortcut1 = QShortcut(None) shortcut1.setObjectName('shortcut1') action1 = QAction('action1', None) s.registerShortcut(shortcut1, 'A') s.registerAction(action1, 'C') self.assertEqual(shortcut1.key().toString(), 'E') self.assertEqual(action1.shortcut().toString(), 'G') # same test, using setKeySequence by name QgsSettings().clear() s = QgsShortcutsManager(None) shortcut1 = QShortcut(None) shortcut1.setObjectName('shortcut1') action1 = QAction('action1', None) s.registerShortcut(shortcut1, 'A') s.registerAction(action1, 'C') self.assertFalse(s.setKeySequence('invalid_name', 'E')) self.assertTrue(s.setKeySequence('shortcut1', 'E')) self.assertTrue(s.setKeySequence('action1', 'G')) self.assertEqual(shortcut1.key().toString(), 'E') self.assertEqual(action1.shortcut().toString(), 'G') s = QgsShortcutsManager(None) shortcut1 = QShortcut(None) shortcut1.setObjectName('shortcut1') action1 = QAction('action1', None) s.registerShortcut(shortcut1, 'A') s.registerAction(action1, 'C') self.assertEqual(shortcut1.key().toString(), 'E') self.assertEqual(action1.shortcut().toString(), 'G')
def dbConnectionNames(self): settings = QgsSettings() settings.beginGroup('/PostgreSQL/connections/') return settings.childGroups()
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
def __init__(self, destination, encoding, fields, geometryType, crs, options=None): self.destination = destination self.isNotFileBased = False self.layer = None self.writer = None if encoding is None: settings = QgsSettings() encoding = settings.value('/Processing/encoding', 'System', str) if self.destination.startswith(self.MEMORY_LAYER_PREFIX): self.isNotFileBased = True uri = QgsWkbTypes.displayString(geometryType) + "?uuid=" + str( uuid.uuid4()) if crs.isValid(): uri += '&crs=' + crs.authid() fieldsdesc = [] for f in fields: qgsfield = _toQgsField(f) fieldsdesc.append( 'field=%s:%s' % (qgsfield.name(), TYPE_MAP_MEMORY_LAYER.get(qgsfield.type(), "string"))) if fieldsdesc: uri += '&' + '&'.join(fieldsdesc) self.layer = QgsVectorLayer(uri, self.destination, 'memory') self.writer = self.layer.dataProvider() elif self.destination.startswith(self.POSTGIS_LAYER_PREFIX): self.isNotFileBased = True uri = QgsDataSourceUri( self.destination[len(self.POSTGIS_LAYER_PREFIX):]) connInfo = uri.connectionInfo() (success, user, passwd) = QgsCredentials.instance().get(connInfo, None, None) if success: QgsCredentials.instance().put(connInfo, user, passwd) else: raise GeoAlgorithmExecutionException( "Couldn't connect to database") try: db = postgis.GeoDB(host=uri.host(), port=int(uri.port()), dbname=uri.database(), user=user, passwd=passwd) except postgis.DbError as e: raise GeoAlgorithmExecutionException( "Couldn't connect to database:\n%s" % e.message) def _runSQL(sql): try: db._exec_sql_and_commit(str(sql)) except postgis.DbError as e: raise GeoAlgorithmExecutionException( 'Error creating output PostGIS table:\n%s' % e.message) fields = [_toQgsField(f) for f in fields] fieldsdesc = ",".join( '%s %s' % (f.name(), TYPE_MAP_POSTGIS_LAYER.get(f.type(), "VARCHAR")) for f in fields) _runSQL("CREATE TABLE %s.%s (%s)" % (uri.schema(), uri.table().lower(), fieldsdesc)) if geometryType != QgsWkbTypes.NullGeometry: _runSQL( "SELECT AddGeometryColumn('{schema}', '{table}', 'the_geom', {srid}, '{typmod}', 2)" .format(table=uri.table().lower(), schema=uri.schema(), srid=crs.authid().split(":")[-1], typmod=QgsWkbTypes.displayString( geometryType).upper())) self.layer = QgsVectorLayer(uri.uri(), uri.table(), "postgres") self.writer = self.layer.dataProvider() elif self.destination.startswith(self.SPATIALITE_LAYER_PREFIX): self.isNotFileBased = True uri = QgsDataSourceUri( self.destination[len(self.SPATIALITE_LAYER_PREFIX):]) try: db = spatialite.GeoDB(uri=uri) except spatialite.DbError as e: raise GeoAlgorithmExecutionException( "Couldn't connect to database:\n%s" % e.message) def _runSQL(sql): try: db._exec_sql_and_commit(str(sql)) except spatialite.DbError as e: raise GeoAlgorithmExecutionException( 'Error creating output Spatialite table:\n%s' % str(e)) fields = [_toQgsField(f) for f in fields] fieldsdesc = ",".join( '%s %s' % (f.name(), TYPE_MAP_SPATIALITE_LAYER.get(f.type(), "VARCHAR")) for f in fields) _runSQL("DROP TABLE IF EXISTS %s" % uri.table().lower()) _runSQL("CREATE TABLE %s (%s)" % (uri.table().lower(), fieldsdesc)) if geometryType != QgsWkbTypes.NullGeometry: _runSQL( "SELECT AddGeometryColumn('{table}', 'the_geom', {srid}, '{typmod}', 2)" .format(table=uri.table().lower(), srid=crs.authid().split(":")[-1], typmod=QgsWkbTypes.displayString( geometryType).upper())) self.layer = QgsVectorLayer(uri.uri(), uri.table(), "spatialite") self.writer = self.layer.dataProvider() else: formats = QgsVectorFileWriter.supportedFiltersAndFormats() OGRCodes = {} for (key, value) in list(formats.items()): extension = str(key) extension = extension[extension.find('*.') + 2:] extension = extension[:extension.find(' ')] OGRCodes[extension] = value OGRCodes['dbf'] = "DBF file" extension = self.destination[self.destination.rfind('.') + 1:] if extension not in OGRCodes: extension = 'shp' self.destination = self.destination + '.shp' if geometryType == QgsWkbTypes.NoGeometry: if extension == 'shp': extension = 'dbf' self.destination = self.destination[:self.destination. rfind('.')] + '.dbf' if extension not in self.nogeometry_extensions: raise GeoAlgorithmExecutionException( "Unsupported format for tables with no geometry") qgsfields = QgsFields() for field in fields: qgsfields.append(_toQgsField(field)) # use default dataset/layer options dataset_options = QgsVectorFileWriter.defaultDatasetOptions( OGRCodes[extension]) layer_options = QgsVectorFileWriter.defaultLayerOptions( OGRCodes[extension]) self.writer = QgsVectorFileWriter(self.destination, encoding, qgsfields, geometryType, crs, OGRCodes[extension], dataset_options, layer_options)
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 tearDownClass(cls): """Run after all tests""" shutil.rmtree(cls.basetestpath, True) QgsSettings().clear()
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 disableCompiler(self): QgsSettings().setValue('/qgis/compileExpressions', False)
def setUpClass(cls): """Run before all tests""" QCoreApplication.setOrganizationName("QGIS_Test") QCoreApplication.setOrganizationDomain("TestQgsCoordinateTransformContext.com") QCoreApplication.setApplicationName("TestQgsCoordinateTransformContext") QgsSettings().clear()