def newmemorylayer(): uri = "point?crs=epsg:4326&field=id:integer" layer = QgsVectorLayer(uri, "testlayer", "memory") print QgsProviderRegistry.instance().pluginList() print layer.dataProvider() print layer.dataProvider().errors() return layer
def getFileFilter(param): """ Returns a suitable file filter pattern for the specified parameter definition :param param: :return: """ if param.type() == 'layer': vectors = QgsProviderRegistry.instance().fileVectorFilters().split(';;') vectors.pop(0) rasters = QgsProviderRegistry.instance().fileRasterFilters().split(';;') rasters.pop(0) filters = set(vectors + rasters) filters = sorted(filters) return tr('All files (*.*)') + ';;' + ";;".join(filters) elif param.type() == 'multilayer': if param.layerType() == QgsProcessing.TypeRaster: exts = QgsRasterFileWriter.supportedFormatExtensions() elif param.layerType() == QgsProcessing.TypeFile: return tr('All files (*.*)', 'QgsProcessingParameterMultipleLayers') else: exts = QgsVectorFileWriter.supportedFormatExtensions() for i in range(len(exts)): exts[i] = tr('{0} files (*.{1})', 'QgsProcessingParameterMultipleLayers').format(exts[i].upper(), exts[i].lower()) return tr('All files (*.*)') + ';;' + ';;'.join(exts) elif param.type() == 'raster': return QgsProviderRegistry.instance().fileRasterFilters() elif param.type() == 'rasterDestination': if param.provider() is not None: exts = param.provider().supportedOutputRasterLayerExtensions() else: exts = QgsRasterFileWriter.supportedFormatExtensions() for i in range(len(exts)): exts[i] = tr('{0} files (*.{1})', 'ParameterRaster').format(exts[i].upper(), exts[i].lower()) return ';;'.join(exts) + ';;' + tr('All files (*.*)') elif param.type() in ('sink', 'vectorDestination'): if param.provider() is not None: exts = param.provider().supportedOutputVectorLayerExtensions() else: exts = QgsVectorFileWriter.supportedFormatExtensions() for i in range(len(exts)): exts[i] = tr('{0} files (*.{1})', 'ParameterVector').format(exts[i].upper(), exts[i].lower()) return ';;'.join(exts) + ';;' + tr('All files (*.*)') elif param.type() == 'source': return QgsProviderRegistry.instance().fileVectorFilters() elif param.type() == 'vector': return QgsProviderRegistry.instance().fileVectorFilters() elif param.type() == 'fileDestination': return param.fileFilter() + ';;' + tr('All files (*.*)') if param.defaultFileExtension(): return tr('Default extension') + ' (*.' + param.defaultFileExtension() + ')' else: return ''
def testDecodeUri(self): """ Test decoding an AFS uri """ uri = self.vl.source() parts = QgsProviderRegistry.instance().decodeUri(self.vl.dataProvider().name(), uri) self.assertEqual(parts, {'url': 'http://' + self.basetestpath + '/fake_qgis_http_endpoint'})
def _open_wmts(self, name, capabilites_url): # Add new HTTPConnection like in source # https://github.com/qgis/QGIS/blob/master/src/gui/qgsnewhttpconnection.cpp self.msg_log(u'add WM(T)S: Name = {0}, URL = {1}'.format(name, capabilites_url)) s = QSettings() s.setValue(u'Qgis/WMS/{0}/password'.format(name), '') s.setValue(u'Qgis/WMS/{0}/username'.format(name), '') s.setValue(u'Qgis/connections-wms/{0}/dpiMode'.format(name), 7) # refer to https://github.com/qgis/QGIS/blob/master/src/gui/qgsnewhttpconnection.cpp#L229-L247 s.setValue(u'Qgis/connections-wms/{0}/ignoreAxisOrientation'.format(name), False) s.setValue(u'Qgis/connections-wms/{0}/ignoreGetFeatureInfoURI'.format(name), False) s.setValue(u'Qgis/connections-wms/{0}/ignoreGetMapURI'.format(name), False) s.setValue(u'Qgis/connections-wms/{0}/invertAxisOrientation'.format(name), False) s.setValue(u'Qgis/connections-wms/{0}/referer'.format(name), '') s.setValue(u'Qgis/connections-wms/{0}/smoothPixmapTransform'.format(name), False) s.setValue(u'Qgis/connections-wms/{0}/url'.format(name), capabilites_url) s.setValue(u'Qgis/connections-wms/selected', name) # create new dialog wms_dlg = QgsProviderRegistry.instance().selectWidget("wms", self.main_win) QObject.connect(wms_dlg, SIGNAL( "addRasterLayer( QString const &, QString const &, QString const & )" ), self.main_win, SLOT( "addRasterLayer( QString const &, QString const &, QString const & )" ) ) wms_dlg.show()
def test_qgis_environment(self): """QGIS environment has the expected providers""" r = QgsProviderRegistry.instance() self.assertIn('gdal', r.providerList()) self.assertIn('ogr', r.providerList()) self.assertIn('postgres', r.providerList())
def loadVectorLayerFromParameter(self, name, parameters, context, feedback, external=False): """ Creates a dedicated command to load a vector into the temporary GRASS DB. :param name: name of the parameter :param parameters: Parameters of the algorithm. :param context: Processing context :param external: use v.external (v.in.ogr if False). """ layer = self.parameterAsVectorLayer(parameters, name, context) is_ogr_disk_based_layer = layer is not None and layer.dataProvider().name() == 'ogr' if is_ogr_disk_based_layer: # we only support direct reading of disk based ogr layers -- not ogr postgres layers, etc source_parts = QgsProviderRegistry.instance().decodeUri('ogr', layer.source()) if not source_parts.get('path'): is_ogr_disk_based_layer = False elif source_parts.get('layerId'): # no support for directly reading layers by id in grass is_ogr_disk_based_layer = False if not is_ogr_disk_based_layer: # parameter is not a vector layer or not an OGR layer - try to convert to a source compatible with # grass OGR inputs and extract selection if required path = self.parameterAsCompatibleSourceLayerPath(parameters, name, context, QgsVectorFileWriter.supportedFormatExtensions(), feedback=feedback) ogr_layer = QgsVectorLayer(path, '', 'ogr') self.loadVectorLayer(name, ogr_layer, external=external, feedback=feedback) else: # already an ogr disk based layer source self.loadVectorLayer(name, layer, external=external, feedback=feedback)
def setUpClass(cls): """Run before all tests""" # qgis instances cls._QgisApp, cls._Canvas, cls._Iface, cls._Parent = \ QGISAPP, CANVAS, IFACE, PARENT # verify that spatialite provider is available msg = '\nSpatialite provider not found, SKIPPING TEST SUITE' res = 'spatialite' in QgsProviderRegistry.instance().providerList() assert res, msg cls._TestFunction = '' cls._TestGroup = '' cls._TestGroupPrefix = '' cls._TestGroupAbbr = '' cls._TestImage = '' # initialize class MapRegistry, Canvas, MapRenderer, Map and PAL cls._MapRegistry = QgsMapLayerRegistry.instance() # set color to match render test comparisons background cls._Canvas.setCanvasColor(QColor(152, 219, 249)) cls._Map = cls._Canvas.map() cls._Map.resize(QSize(600, 400)) cls._MapRenderer = cls._Canvas.mapRenderer() cls._CRS = QgsCoordinateReferenceSystem() # default for labeling test data sources: WGS 84 / UTM zone 13N cls._CRS.createFromSrid(32613) cls._MapRenderer.setDestinationCrs(cls._CRS) # use platform's native logical output dpi for QgsMapRenderer on launch cls.setDefaultEngineSettings() msg = ('\nCould not initialize PAL labeling engine, ' 'SKIPPING TEST SUITE') assert cls._PalEngine, msg
def test_043_decodeuri(self): # URI decoding filename = '/home/to/path/test.csv' uri = 'file://{}?geomType=none'.format(filename) registry = QgsProviderRegistry.instance() components = registry.decodeUri('delimitedtext', uri) self.assertEqual(components['path'], filename)
def setUpClass(cls): """Run before all tests""" # Register the provider r = QgsProviderRegistry.instance() metadata = QgsProviderMetadata(PyProvider.providerKey(), PyProvider.description(), PyProvider.createProvider) assert r.registerProvider(metadata) assert r.providerMetadata(PyProvider.providerKey()) == metadata # Create test layer cls.vl = cls.createLayer() assert (cls.vl.isValid()) cls.source = cls.vl.dataProvider() # poly layer cls.poly_vl = QgsVectorLayer('Polygon?crs=epsg:4326&field=pk:integer&key=pk', 'test', 'pythonprovider') assert (cls.poly_vl.isValid()) cls.poly_provider = cls.poly_vl.dataProvider() f1 = QgsFeature() f1.setAttributes([1]) f1.setGeometry(QgsGeometry.fromWkt('Polygon ((-69.03664108 81.35818902, -69.09237722 80.24346619, -73.718477 80.1319939, -73.718477 76.28620011, -74.88893598 76.34193625, -74.83319983 81.35818902, -69.03664108 81.35818902))')) f2 = QgsFeature() f2.setAttributes([2]) f2.setGeometry(QgsGeometry.fromWkt('Polygon ((-67.58750139 81.1909806, -66.30557012 81.24671674, -66.30557012 76.89929767, -67.58750139 76.89929767, -67.58750139 81.1909806))')) f3 = QgsFeature() f3.setAttributes([3]) f3.setGeometry(QgsGeometry.fromWkt('Polygon ((-68.36780737 75.78457483, -67.53176524 72.60761475, -68.64648808 73.66660144, -70.20710006 72.9420316, -68.36780737 75.78457483))')) f4 = QgsFeature() f4.setAttributes([4]) cls.poly_provider.addFeatures([f1, f2, f3, f4])
def _open_wfs(self, name, capabilites_url): # Add new HTTPConnection like in source # https://github.com/qgis/QGIS/blob/master/src/gui/qgsnewhttpconnection.cpp # https://github.com/qgis/QGIS/blob/79616fd8d8285b4eb93adafdfcb97a3e429b832e/src/app/qgisapp.cpp#L3783 self.msg_log(u'add WFS: Name={0}, original URL={1}'.format(name, capabilites_url)) # remove additional url parameters, otherwise adding wfs works the frist time only # https://github.com/qgis/QGIS/blob/9eee12111567a84f4d4de7e020392b3c01c28598/src/gui/qgsnewhttpconnection.cpp#L199-L214 url = QUrl(capabilites_url) url.removeQueryItem('SERVICE') url.removeQueryItem('REQUEST') url.removeQueryItem('FORMAT') url.removeQueryItem('service') url.removeQueryItem('request') url.removeQueryItem('format') #also remove VERSION: shouldn't be necessary, but QGIS sometimes seems to append version=1.0.0 url.removeQueryItem('VERSION') url.removeQueryItem('version') capabilites_url = url.toString() self.msg_log(u'add WFS: Name={0}, base URL={1}'.format(name, capabilites_url)) s = QSettings() self.msg_log(u'existing WFS url: {0}'.format(s.value(u'Qgis/connections-wfs/{0}/url'.format(name), ''))) key_user = u'Qgis/WFS/{0}/username'.format(name) key_pwd = u'Qgis/WFS/{0}/password'.format(name) key_referer = u'Qgis/connections-wfs/{0}/referer'.format(name) key_url = u'Qgis/connections-wfs/{0}/url'.format(name) key_authcfg = u'Qgis/WFS/{0}/authcfg'.format(name) s.remove(key_user) s.remove(key_pwd) s.remove(key_referer) s.remove(key_url) s.sync() s.setValue(key_user, '') s.setValue(key_pwd, '') s.setValue(key_referer, '') s.setValue(key_url, capabilites_url) if self.settings.auth_propagate and self.settings.authcfg: s.setValue(key_authcfg, self.settings.authcfg) s.setValue(u'Qgis/connections-wfs/selected', name) # create new dialog wfs_dlg = QgsProviderRegistry.instance().selectWidget("WFS", self.main_win) QObject.connect( wfs_dlg , SIGNAL("addWfsLayer( QString, QString )") , self.main_win, SLOT("addWfsLayer( QString, QString )") ) wfs_dlg.show()
def selectFiles( self ): filters = QgsProviderRegistry.instance().fileVectorFilters() files, self.encoding = ftools_utils.openDialog( self, filtering=filters, dialogMode="MultipleFiles" ) if files is None: return self.layers.extend( [ unicode( f ) for f in files ] ) self.lstLayers.addItems( files )
def dump_configinfo(self): from qgis.core import QgsApplication, QgsProviderRegistry from PyQt4.QtGui import QImageReader, QImageWriter yield QgsProviderRegistry.instance().pluginList() yield QImageReader.supportedImageFormats() yield QImageWriter.supportedImageFormats() yield QgsApplication.libraryPaths() yield "Translation file: {}".format(self.translationFile)
def testDecodeUri(self): """Check that the provider URI decoding returns expected values""" filename = '/home/to/path/test.db' uri = 'dbname=\'{}\' table="test" (geometry) sql='.format(filename) registry = QgsProviderRegistry.instance() components = registry.decodeUri('spatialite', uri) self.assertEqual(components['path'], filename)
def allRastersFilter(self): if self.rastersFilter == '': self.rastersFilter = QgsProviderRegistry.instance().fileRasterFilters() # workaround for Qgis < 1.5 (see #2376) # removed as this is a core plugin Qgis >= 1.9 return self.rastersFilter
def test_qgis_environment(self): """QGIS environment has the expected providers""" # noinspection PyUnresolvedReferences r = QgsProviderRegistry.instance() # print 'Provider count: %s' % len(r.providerList()) assert 'gdal' in r.providerList() assert 'ogr' in r.providerList() assert 'postgres' in r.providerList()
def __init__(self, template_path, debug=False): """Constructor. :param template_path: Absolute path to a QGIS composer template file. :type template_path: str """ gui_flag = True self.app = QgsApplication(sys.argv, gui_flag) # Make sure QGIS_PREFIX_PATH is set in your env if needed! self.app.initQgis() if debug: print QgsProviderRegistry.instance().pluginList() self.canvas = QgsMapCanvas() self.canvas.enableAntiAliasing(True) self.template_path = template_path
def test_QGISEnvironment(self): """QGIS environment has the expected providers""" r = QgsProviderRegistry.instance() #for item in r.providerList(): # print str(item) #print 'Provider count: %s' % len(r.providerList()) assert 'gdal' in r.providerList() assert 'ogr' in r.providerList()
def setUpClass(cls): """Run before all tests""" # qgis instances cls._QgisApp, cls._Canvas, cls._Iface, cls._Parent = \ QGISAPP, CANVAS, IFACE, PARENT cls._PalReportDir = PALREPORTDIR # verify that spatialite provider is available msg = ('\nSpatialite provider not found, ' 'SKIPPING TEST SUITE') res = 'spatialite' in QgsProviderRegistry.instance().providerList() assert res, msg # load the FreeSansQGIS labeling test font fontdb = QFontDatabase() cls._TestFontID = fontdb.addApplicationFont( os.path.join(cls._TestDataDir, 'font', 'FreeSansQGIS.ttf')) msg = ('\nCould not store test font in font database, ' 'SKIPPING TEST SUITE') assert cls._TestFontID != -1, msg cls._TestFont = fontdb.font('FreeSansQGIS', 'Medium', 48) appfont = QApplication.font() msg = ('\nCould not load test font from font database, ' 'SKIPPING TEST SUITE') assert cls._TestFont.toString() != appfont.toString(), msg cls._TestFunction = '' cls._TestGroup = '' cls._TestGroupPrefix = '' cls._TestGroupAbbr = '' # initialize class MapRegistry, Canvas, MapRenderer, Map and PAL cls._MapRegistry = QgsMapLayerRegistry.instance() # set color to match render test comparisons background cls._Canvas.setCanvasColor(QColor(152, 219, 249)) cls._Map = cls._Canvas.map() cls._Map.resize(QSize(600, 400)) cls._MapRenderer = cls._Canvas.mapRenderer() crs = QgsCoordinateReferenceSystem() # default for labeling test data sources: WGS 84 / UTM zone 13N crs.createFromSrid(32613) cls._MapRenderer.setDestinationCrs(crs) # TODO: match and store platform's native logical output dpi cls._MapRenderer.setOutputSize(QSize(600, 400), 72) cls._Pal = QgsPalLabeling() cls._MapRenderer.setLabelingEngine(cls._Pal) cls._PalEngine = cls._MapRenderer.labelingEngine() msg = ('\nCould not initialize PAL labeling engine, ' 'SKIPPING TEST SUITE') assert cls._PalEngine, msg
def open_file_browser(self): # noinspection PyArgumentList raster_filter = QgsProviderRegistry.instance().fileRasterFilters() # noinspection PyArgumentList raster = QFileDialog.getOpenFileName( parent=self.parent, caption=tr('Select raster'), filter=raster_filter) self.le_shapefile.setText(raster)
def populateControls(self): if self.populated: return self.updateCOMPorts() # Read version self.versionLabel.setText(roam.__version__) self.qgisapiLabel.setText(str(QGis.QGIS_VERSION)) ecwsupport = 'ecw' in QgsProviderRegistry.instance().fileRasterFilters() self.ecwlabel.setText("Yes" if ecwsupport else "No")
def getFileFilter(param): """ Returns a suitable file filter pattern for the specified parameter definition :param param: :return: """ if param.type() == 'multilayer': if param.layerType() == QgsProcessing.TypeRaster: exts = dataobjects.getSupportedOutputRasterLayerExtensions() elif param.layerType() == QgsProcessing.TypeFile: return tr('All files (*.*)', 'QgsProcessingParameterMultipleLayers') else: exts = QgsVectorFileWriter.supportedFormatExtensions() for i in range(len(exts)): exts[i] = tr('{0} files (*.{1})', 'QgsProcessingParameterMultipleLayers').format(exts[i].upper(), exts[i].lower()) return tr('All files (*.*)') + ';;' + ';;'.join(exts) elif param.type() == 'raster': return QgsProviderRegistry.instance().fileRasterFilters() elif param.type() == 'rasterDestination': exts = dataobjects.getSupportedOutputRasterLayerExtensions() for i in range(len(exts)): exts[i] = tr('{0} files (*.{1})', 'QgsProcessingParameterRasterDestination').format(exts[i].upper(), exts[i].lower()) return tr('All files (*.*)') + ';;' + ';;'.join(exts) elif param.type() == 'table': exts = ['csv', 'dbf'] for i in range(len(exts)): exts[i] = tr('{0} files (*.{1})', 'ParameterTable').format(exts[i].upper(), exts[i].lower()) return tr('All files (*.*)') + ';;' + ';;'.join(exts) elif param.type() == 'sink': exts = QgsVectorFileWriter.supportedFormatExtensions() for i in range(len(exts)): exts[i] = tr('{0} files (*.{1})', 'ParameterVector').format(exts[i].upper(), exts[i].lower()) return tr('All files (*.*)') + ';;' + ';;'.join(exts) elif param.type() == 'source': return QgsProviderRegistry.instance().fileVectorFilters() elif param.type() == 'vector': return QgsProviderRegistry.instance().fileVectorFilters() elif param.type() == 'fileOut': return tr('All files (*.*)') + ';;' + param.fileFilter() return ''
def getOgrCompatibleSource(self, parameter_name, parameters, context, feedback, executing): """ Interprets a parameter as an OGR compatible source and layer name :param executing: """ if not executing and parameter_name in parameters and isinstance(parameters[parameter_name], QgsProcessingFeatureSourceDefinition): # if not executing, then we throw away all 'selected features only' settings # since these have no meaning for command line gdal use, and we don't want to force # an export of selected features only to a temporary file just to show the command! parameters = {parameter_name: parameters[parameter_name].source} input_layer = self.parameterAsVectorLayer(parameters, parameter_name, context) ogr_data_path = None ogr_layer_name = None if input_layer is None or input_layer.dataProvider().name() == 'memory': if executing: # parameter is not a vector layer - try to convert to a source compatible with OGR # and extract selection if required ogr_data_path = self.parameterAsCompatibleSourceLayerPath(parameters, parameter_name, context, QgsVectorFileWriter.supportedFormatExtensions(), feedback=feedback) ogr_layer_name = GdalUtils.ogrLayerName(ogr_data_path) else: #not executing - don't waste time converting incompatible sources, just return dummy strings #for the command preview (since the source isn't compatible with OGR, it has no meaning anyway and can't #be run directly in the command line) ogr_data_path = 'path_to_data_file' ogr_layer_name = 'layer_name' elif input_layer.dataProvider().name() == 'ogr': if executing and isinstance(parameters[parameter_name], QgsProcessingFeatureSourceDefinition) and parameters[parameter_name].selectedFeaturesOnly: # parameter is a vector layer, with OGR data provider # so extract selection if required ogr_data_path = self.parameterAsCompatibleSourceLayerPath(parameters, parameter_name, context, QgsVectorFileWriter.supportedFormatExtensions(), feedback=feedback) parts = QgsProviderRegistry.instance().decodeUri('ogr', ogr_data_path) ogr_data_path = parts['path'] if 'layerName' in parts and parts['layerName']: ogr_layer_name = parts['layerName'] else: ogr_layer_name = GdalUtils.ogrLayerName(ogr_data_path) else: #either not using the selection, or #not executing - don't worry about 'selected features only' handling. It has no meaning #for the command line preview since it has no meaning outside of a QGIS session! ogr_data_path = GdalUtils.ogrConnectionStringAndFormatFromLayer(input_layer)[0] ogr_layer_name = GdalUtils.ogrLayerName(input_layer.dataProvider().dataSourceUri()) else: # vector layer, but not OGR - get OGR compatible path # TODO - handle "selected features only" mode!! ogr_data_path = GdalUtils.ogrConnectionStringFromLayer(input_layer) ogr_layer_name = GdalUtils.ogrLayerName(input_layer.dataProvider().dataSourceUri()) return ogr_data_path, ogr_layer_name
def testConnections(self): """ Test credentials injection """ pr = QgsProviderRegistry.instance().createProvider('ogr', '') for uri, expanded in TEST_URIS.items(): pr.setDataSourceUri(uri % self.authcfg) self.assertTrue(expanded in pr.dataSourceUri(True), "%s != %s" % (expanded, pr.dataSourceUri(True))) # Test sublayers for uri, expanded in TEST_URIS.items(): pr.setDataSourceUri((uri + '|sublayer1') % self.authcfg) self.assertEqual(pr.dataSourceUri(True).split('|')[1], "sublayer1", pr.dataSourceUri(True))
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 _open_csv(self, full_path): # Add new HTTPConnection like in source # https://github.com/qgis/QGIS/blob/master/src/gui/qgsnewhttpconnection.cpp self.msg_log(u'add CSV file: {0}'.format(full_path)) # create new dialog csv_dlg = QgsProviderRegistry.instance().selectWidget("delimitedtext", self.main_win) QObject.connect(csv_dlg, SIGNAL( "addVectorLayer( QString, QString, QString )" ), self.main_win, SLOT( "addSelectedVectorLayer( QString, QString, QString )" ) ) csv_dlg.children()[1].children()[2].setText(full_path) csv_dlg.show()
def __init__(self, parent=None): self.parent = parent super(OpenCsv, self).__init__() mdi_area = QMdiArea() # noinspection PyArgumentList dialog = QgsProviderRegistry.instance().selectWidget('delimitedtext') dialog.setWindowTitle(tr('Open a CSV')) layout = QVBoxLayout(self) layout.addWidget(mdi_area) mdi_area.addSubWindow(dialog) dialog.addVectorLayer[str, str, str].connect(self.success) dialog.rejected.connect(self.signalAskCloseWindow.emit)
def chooseInputFile(self): vectorFormats = QgsProviderRegistry.instance().fileVectorFilters() # get last used dir and format settings = QSettings() 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 dump_configinfo(self): from qgis.core import QgsApplication, QgsProviderRegistry from PyQt4.QtGui import QImageReader, QImageWriter import roam from qgis.core import QGis config = [] config.append("====Providers===") config.append(QgsProviderRegistry.instance().pluginList()) config.append("====Library paths===") config.append('\n'.join(QgsApplication.libraryPaths())) config.append("====Translation File===") config.append(self.translationFile) config.append("Roam Version: {}".format(roam.__version__)) config.append("QGIS Version: {}".format(str(QGis.QGIS_VERSION))) return '\n'.join(config)
def setUpProvider(cls, authId): cls.dbconn = 'dbname=\'qgis_test\'' if 'QGIS_PGTEST_DB' in os.environ: cls.dbconn = os.environ['QGIS_PGTEST_DB'] uri = QgsDataSourceUri() uri.setConnection("localhost", cls.port, cls.dbname, "", "", QgsDataSourceUri.SslVerifyFull, authId) uri.setKeyColumn('pk') uri.setSrid('EPSG:4326') uri.setDataSource('qgis_test', 'someData', "geom", "", "pk") provider = QgsProviderRegistry.instance().createProvider('postgres', uri.uri(False)) if provider is None: raise Exception("cannot create postgres provider") if not provider.isValid(): raise Exception("Created postgres provider is not valid: {}".format(str(provider.errors()))) # save provider config that is the way how db_manager is aware of a PG connection cls.addConnectionConfig(TEST_CONNECTION_NAME, uri)
def loadVectorLayer(self, name, layer, external=False, feedback=None): """ Creates a dedicated command to load a vector into temporary GRASS DB. :param name: name of the parameter :param layer: QgsMapLayer for the vector layer. :param external: use v.external (v.in.ogr if False). :param feedback: feedback object """ # TODO: support multiple input formats if external is None: external = ProcessingConfig.getSetting( Grass7Utils.GRASS_USE_VEXTERNAL) source_parts = QgsProviderRegistry.instance().decodeUri('ogr', layer.source()) file_path = source_parts.get('path') layer_name = source_parts.get('layerName') # safety check: we can only use external for ogr layers which support random read if external: if feedback is not None: feedback.pushInfo('Attempting to use v.external for direct layer read') ds = ogr.Open(file_path) if ds is not None: ogr_layer = ds.GetLayer() if ogr_layer is None or not ogr_layer.TestCapability(ogr.OLCRandomRead): if feedback is not None: feedback.reportError('Cannot use v.external: layer does not support random read') external = False else: if feedback is not None: feedback.reportError('Cannot use v.external: error reading layer') external = False self.inputLayers.append(layer) self.setSessionProjectionFromLayer(layer) destFilename = 'vector_{}'.format(os.path.basename(getTempFilename())) self.exportedLayers[name] = destFilename command = '{0}{1}{2} input="{3}"{4} output="{5}" --overwrite -o'.format( 'v.external' if external else 'v.in.ogr', ' min_area={}'.format(self.minArea) if not external else '', ' snap={}'.format(self.snapTolerance) if not external else '', os.path.normpath(file_path), ' layer="{}"'.format(layer_name) if layer_name else '', destFilename) self.commands.append(command)
def testModel(self): conn = QgsProviderRegistry.instance().providerMetadata( 'postgres').createConnection(self.uri, {}) self.assertTrue(conn) model = QgsDatabaseSchemaModel(conn) self.assertGreaterEqual(model.rowCount(), 3) old_count = model.rowCount() self.assertEqual(model.columnCount(), 1) schemas = [ model.data(model.index(r, 0, QModelIndex()), Qt.DisplayRole) for r in range(model.rowCount()) ] self.assertIn('public', schemas) self.assertIn('CamelCaseSchema', schemas) self.assertIn('qgis_test', schemas) self.assertEqual( model.data( model.index(schemas.index('qgis_test'), 0, QModelIndex()), Qt.ToolTipRole), 'qgis_test') self.assertIsNone( model.data(model.index(model.rowCount(), 0, QModelIndex()), Qt.DisplayRole)) model.refresh() self.assertEqual(model.rowCount(), old_count) conn.createSchema('myNewSchema') self.assertEqual(model.rowCount(), old_count) model.refresh() self.assertEqual(model.rowCount(), old_count + 1) schemas = [ model.data(model.index(r, 0, QModelIndex()), Qt.DisplayRole) for r in range(model.rowCount()) ] self.assertIn('public', schemas) self.assertIn('CamelCaseSchema', schemas) self.assertIn('qgis_test', schemas) self.assertIn('myNewSchema', schemas) conn.createSchema('myNewSchema2') conn.createSchema('myNewSchema3') model.refresh() self.assertEqual(model.rowCount(), old_count + 3) schemas = [ model.data(model.index(r, 0, QModelIndex()), Qt.DisplayRole) for r in range(model.rowCount()) ] self.assertIn('public', schemas) self.assertIn('CamelCaseSchema', schemas) self.assertIn('qgis_test', schemas) self.assertIn('myNewSchema', schemas) self.assertIn('myNewSchema2', schemas) self.assertIn('myNewSchema3', schemas) conn.createSchema('myNewSchema4') conn.dropSchema('myNewSchema2') conn.dropSchema('myNewSchema') model.refresh() self.assertEqual(model.rowCount(), old_count + 2) schemas = [ model.data(model.index(r, 0, QModelIndex()), Qt.DisplayRole) for r in range(model.rowCount()) ] self.assertIn('public', schemas) self.assertIn('CamelCaseSchema', schemas) self.assertIn('qgis_test', schemas) self.assertNotIn('myNewSchema', schemas) self.assertNotIn('myNewSchema2', schemas) self.assertIn('myNewSchema3', schemas) self.assertIn('myNewSchema4', schemas) conn.dropSchema('myNewSchema3') conn.dropSchema('myNewSchema4') model.refresh() self.assertEqual(model.rowCount(), old_count) schemas = [ model.data(model.index(r, 0, QModelIndex()), Qt.DisplayRole) for r in range(model.rowCount()) ] self.assertIn('public', schemas) self.assertIn('CamelCaseSchema', schemas) self.assertIn('qgis_test', schemas) self.assertNotIn('myNewSchema3', schemas) self.assertNotIn('myNewSchema4', schemas)
def test(self): # This test is quite fragile as it depends on windows manager behavior # regarding focus, so not surprising it doesn't pass # on other platforms than Linux. # if 'TRAVIS_OS_NAME' in os.environ and os.environ['TRAVIS_OS_NAME'] == 'osx': # return main_dialog = QgsProviderRegistry.instance().createSelectionWidget( "WFS") main_dialog.setProperty("hideDialogs", True) self.assertIsNotNone(main_dialog) # Create new connection btnNew = main_dialog.findChild(QWidget, "btnNew") self.assertIsNotNone(btnNew) QTest.mouseClick(btnNew, Qt.LeftButton) new_conn = find_window('QgsNewHttpConnectionBase') self.assertIsNotNone(new_conn) txtName = new_conn.findChild(QLineEdit, "txtName") self.assertIsNotNone(txtName) txtName.setText("test_connection") txtUrl = new_conn.findChild(QLineEdit, "txtUrl") self.assertIsNotNone(txtUrl) txtUrl.setText("test_url") new_conn.accept() # Wait for object to be destroyed new_conn = self.wait_object_destruction(new_conn) # Try to connect btnConnect = main_dialog.findChild(QWidget, "btnConnect") self.assertIsNotNone(btnConnect) QTest.mouseClick(btnConnect, Qt.LeftButton) # Depends on asynchronous signal QApplication.processEvents() error_box = find_window('WFSCapabilitiesErrorBox') self.assertIsNotNone(error_box) # Close error box error_box.accept() # Wait for object to be destroyed error_box = self.wait_object_destruction(error_box) # Edit connection btnEdit = main_dialog.findChild(QWidget, "btnEdit") self.assertIsNotNone(btnEdit) QTest.mouseClick(btnEdit, Qt.LeftButton) new_conn = find_window('QgsNewHttpConnectionBase', ) self.assertIsNotNone(new_conn) txtName = new_conn.findChild(QLineEdit, "txtName") self.assertIsNotNone(txtName) txtName.setText("test_connection") txtUrl = new_conn.findChild(QLineEdit, "txtUrl") self.assertIsNotNone(txtUrl) endpoint = self.basetestpath + '/fake_qgis_http_endpoint' expected_endpoint = endpoint if sys.platform == 'win32' and expected_endpoint[1] == ':': expected_endpoint = expected_endpoint[0] + expected_endpoint[2:] with open( sanitize( endpoint, '?SERVICE=WFS?REQUEST=GetCapabilities?ACCEPTVERSIONS=2.0.0,1.1.0,1.0.0' ), 'wb') as f: f.write(""" <wfs:WFS_Capabilities version="2.0.0" xmlns="http://www.opengis.net/wfs/2.0" xmlns:wfs="http://www.opengis.net/wfs/2.0" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:gml="http://schemas.opengis.net/gml/3.2" xmlns:fes="http://www.opengis.net/fes/2.0"> <FeatureTypeList> <FeatureType> <Name>my:typename</Name> <Title>Title</Title> <Abstract>Abstract</Abstract> <DefaultCRS>urn:ogc:def:crs:EPSG::4326</DefaultCRS> <ows:WGS84BoundingBox> <ows:LowerCorner>-71.123 66.33</ows:LowerCorner> <ows:UpperCorner>-65.32 78.3</ows:UpperCorner> </ows:WGS84BoundingBox> </FeatureType> </FeatureTypeList> <fes:Filter_Capabilities> <fes:Spatial_Capabilities> <fes:GeometryOperands> <fes:GeometryOperand name="gml:Envelope"/> <fes:GeometryOperand name="gml:Point"/> <fes:GeometryOperand name="gml:MultiPoint"/> <fes:GeometryOperand name="gml:LineString"/> <fes:GeometryOperand name="gml:MultiLineString"/> <fes:GeometryOperand name="gml:Polygon"/> <fes:GeometryOperand name="gml:MultiPolygon"/> <fes:GeometryOperand name="gml:MultiGeometry"/> </fes:GeometryOperands> <fes:SpatialOperators> <fes:SpatialOperator name="Disjoint"/> <fes:SpatialOperator name="Equals"/> <fes:SpatialOperator name="DWithin"/> <fes:SpatialOperator name="Beyond"/> <fes:SpatialOperator name="Intersects"/> <fes:SpatialOperator name="Touches"/> <fes:SpatialOperator name="Crosses"/> <fes:SpatialOperator name="Within"/> <fes:SpatialOperator name="Contains"/> <fes:SpatialOperator name="Overlaps"/> <fes:SpatialOperator name="BBOX"/> </fes:SpatialOperators> </fes:Spatial_Capabilities> <fes:Functions> <fes:Function name="abs"> <fes:Returns>xs:int</fes:Returns> <fes:Arguments> <fes:Argument name="param"> <fes:Type>xs:int</fes:Type> </fes:Argument> </fes:Arguments> </fes:Function> </fes:Functions> </fes:Filter_Capabilities> </wfs:WFS_Capabilities>""".encode('UTF-8')) txtUrl.setText("http://" + endpoint) new_conn.accept() # Wait for object to be destroyed new_conn = self.wait_object_destruction(new_conn) # Try to connect btnConnect = main_dialog.findChild(QWidget, "btnConnect") self.assertIsNotNone(btnConnect) QTest.mouseClick(btnConnect, Qt.LeftButton) buttonAdd = self.get_button_add(main_dialog) for i in range(10): QApplication.processEvents() if buttonAdd.isEnabled(): break self.assertTrue(buttonAdd.isEnabled()) # Add layer self.addWfsLayer_uri = None self.addWfsLayer_layer_name = None main_dialog.addVectorLayer.connect(self.slotAddWfsLayer) QTest.mouseClick(buttonAdd, Qt.LeftButton) self.assertEqual( self.addWfsLayer_uri, ' restrictToRequestBBOX=\'1\' srsname=\'EPSG:4326\' typename=\'my:typename\' url=\'' + "http://" + expected_endpoint + '\' version=\'auto\' table="" sql=') self.assertEqual(self.addWfsLayer_layer_name, 'my:typename') # Click on Build Query buttonBuildQuery = self.get_button_build_query(main_dialog) self.assertTrue(buttonBuildQuery.isEnabled()) QTest.mouseClick(buttonBuildQuery, Qt.LeftButton) error_box = find_window('WFSFeatureTypeErrorBox') self.assertIsNotNone(error_box) # Close error box error_box.accept() # Wait for object to be destroyed error_box = self.wait_object_destruction(error_box) # Click again but with valid DescribeFeatureType with open( sanitize( endpoint, '?SERVICE=WFS&REQUEST=DescribeFeatureType&VERSION=2.0.0&TYPENAME=my:typename' ), 'wb') as f: f.write(""" <xsd:schema xmlns:my="http://my" xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://my"> <xsd:import namespace="http://www.opengis.net/gml/3.2"/> <xsd:complexType name="typenameType"> <xsd:complexContent> <xsd:extension base="gml:AbstractFeatureType"> <xsd:sequence> <xsd:element maxOccurs="1" minOccurs="0" name="intfield" nillable="true" type="xsd:int"/> <xsd:element maxOccurs="1" minOccurs="0" name="geometryProperty" nillable="true" type="gml:PolygonPropertyType"/> </xsd:sequence> </xsd:extension> </xsd:complexContent> </xsd:complexType> <xsd:element name="typename" substitutionGroup="gml:_Feature" type="my:typenameType"/> </xsd:schema> """.encode('UTF-8')) QTest.mouseClick(buttonBuildQuery, Qt.LeftButton) # Check that the combos are properly initialized dialog = find_window('QgsSQLComposerDialogBase') self.assertIsNotNone(dialog) mTablesCombo = dialog.findChild(QComboBox, "mTablesCombo") self.assertIsNotNone(mTablesCombo) self.assertEqual(mTablesCombo.itemText(1), 'typename (Title)') mColumnsCombo = dialog.findChild(QComboBox, "mColumnsCombo") self.assertIsNotNone(mColumnsCombo) self.assertEqual(mColumnsCombo.itemText(1), 'intfield (int)') self.assertEqual(mColumnsCombo.itemText(mColumnsCombo.count() - 2), 'geometryProperty (geometry)') self.assertEqual(mColumnsCombo.itemText(mColumnsCombo.count() - 1), '*') mFunctionsCombo = dialog.findChild(QComboBox, "mFunctionsCombo") self.assertIsNotNone(mFunctionsCombo) self.assertEqual(mFunctionsCombo.itemText(1), 'abs(param: int): int') mSpatialPredicatesCombo = dialog.findChild(QComboBox, "mSpatialPredicatesCombo") self.assertIsNotNone(mSpatialPredicatesCombo) self.assertEqual(mSpatialPredicatesCombo.itemText(1), 'ST_Disjoint(geometry, geometry): boolean') mWhereEditor = dialog.findChild(QTextEdit, "mWhereEditor") self.assertIsNotNone(mWhereEditor) mWhereEditor.setText('1 = 1') dialog.accept() # Wait for object to be destroyed dialog = self.wait_object_destruction(dialog) # Add layer buttonAdd = self.get_button_add(main_dialog) self.assertTrue(buttonAdd.isEnabled()) self.addWfsLayer_uri = None self.addWfsLayer_layer_name = None main_dialog.addVectorLayer.connect(self.slotAddWfsLayer) QTest.mouseClick(buttonAdd, Qt.LeftButton) self.assertEqual( self.addWfsLayer_uri, ' restrictToRequestBBOX=\'1\' srsname=\'EPSG:4326\' typename=\'my:typename\' url=\'' + "http://" + expected_endpoint + '\' version=\'auto\' table="" sql=SELECT * FROM typename WHERE 1 = 1' ) self.assertEqual(self.addWfsLayer_layer_name, 'my:typename')
def testExtentFromGeometryTable(self): """ Check if the behavior of the mssql provider if extent is defined in the geometry_column table """ # Create a layer layer = QgsVectorLayer( "Point?field=id:integer&field=fldtxt:string&field=fldint:integer", "layer", "memory") pr = layer.dataProvider() f1 = QgsFeature() f1.setAttributes([1, "test", 1]) f1.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(1, 2))) f2 = QgsFeature() f2.setAttributes([2, "test2", 3]) f3 = QgsFeature() f3.setAttributes([3, "test2", NULL]) f3.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(3, 2))) f4 = QgsFeature() f4.setAttributes([4, NULL, 3]) f4.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(4, 3))) pr.addFeatures([f1, f2, f3, f4]) uri = '{} table="qgis_test"."layer_extent_in_geometry_table" sql='.format( self.dbconn) QgsVectorLayerExporter.exportLayer( layer, uri, 'mssql', QgsCoordinateReferenceSystem('EPSG:4326')) layerUri = QgsDataSourceUri(uri) # Load and check if the layer is valid loadedLayer = QgsVectorLayer(layerUri.uri(), "valid", "mssql") self.assertTrue(loadedLayer.isValid()) extent = loadedLayer.extent() self.assertEqual(extent.toString(1), QgsRectangle(1.0, 2.0, 4.0, 3.0).toString(1)) # Load with flag extent in geometry_columns table and check if the layer is still valid and extent doesn't change layerUri.setParam('extentInGeometryColumns', '1') loadedLayer = QgsVectorLayer(layerUri.uri(), "invalid", "mssql") self.assertTrue(loadedLayer.isValid()) extent = loadedLayer.extent() self.assertEqual(extent.toString(1), QgsRectangle(1.0, 2.0, 4.0, 3.0).toString(1)) md = QgsProviderRegistry.instance().providerMetadata('mssql') conn = md.createConnection(self.dbconn, {}) conn.addField(QgsField('qgis_xmin', QVariant.Double, 'FLOAT(24)'), 'dbo', 'geometry_columns') conn.addField(QgsField('qgis_xmax', QVariant.Double, 'FLOAT(24)'), 'dbo', 'geometry_columns') conn.addField(QgsField('qgis_ymin', QVariant.Double, 'FLOAT(24)'), 'dbo', 'geometry_columns') conn.addField(QgsField('qgis_ymax', QVariant.Double, 'FLOAT(24)'), 'dbo', 'geometry_columns') # try with empty attribute layerUri.setParam('extentInGeometryColumns', '1') loadedLayer = QgsVectorLayer(layerUri.uri(), "invalid", "mssql") self.assertTrue(loadedLayer.isValid()) self.assertTrue(loadedLayer.isValid()) extent = loadedLayer.extent() self.assertEqual(extent.toString(1), QgsRectangle(1.0, 2.0, 4.0, 3.0).toString(1)) conn.execSql( 'UPDATE dbo.geometry_columns SET qgis_xmin=0, qgis_xmax=5.5, qgis_ymin=0.5, qgis_ymax=6 WHERE f_table_name=\'layer_extent_in_geometry_table\'' ) # try with valid attribute layerUri.setParam('extentInGeometryColumns', '1') loadedLayer = QgsVectorLayer(layerUri.uri(), "valid", "mssql") self.assertTrue(loadedLayer.isValid()) extent = loadedLayer.extent() self.assertEqual(extent.toString(1), QgsRectangle(0.0, 0.5, 5.5, 6.0).toString(1))
def getOgrCompatibleSource(self, parameter_name, parameters, context, feedback, executing): """ Interprets a parameter as an OGR compatible source and layer name :param executing: """ if not executing and parameter_name in parameters and isinstance( parameters[parameter_name], QgsProcessingFeatureSourceDefinition): # if not executing, then we throw away all 'selected features only' settings # since these have no meaning for command line gdal use, and we don't want to force # an export of selected features only to a temporary file just to show the command! parameters = {parameter_name: parameters[parameter_name].source} input_layer = self.parameterAsVectorLayer(parameters, parameter_name, context) ogr_data_path = None ogr_layer_name = None if input_layer is None or input_layer.dataProvider().name( ) == 'memory': if executing: # parameter is not a vector layer - try to convert to a source compatible with OGR # and extract selection if required ogr_data_path = self.parameterAsCompatibleSourceLayerPath( parameters, parameter_name, context, QgsVectorFileWriter.supportedFormatExtensions(), feedback=feedback) ogr_layer_name = GdalUtils.ogrLayerName(ogr_data_path) else: #not executing - don't waste time converting incompatible sources, just return dummy strings #for the command preview (since the source isn't compatible with OGR, it has no meaning anyway and can't #be run directly in the command line) ogr_data_path = 'path_to_data_file' ogr_layer_name = 'layer_name' elif input_layer.dataProvider().name() == 'ogr': if executing and isinstance( parameters[parameter_name], QgsProcessingFeatureSourceDefinition ) and parameters[parameter_name].selectedFeaturesOnly: # parameter is a vector layer, with OGR data provider # so extract selection if required ogr_data_path = self.parameterAsCompatibleSourceLayerPath( parameters, parameter_name, context, QgsVectorFileWriter.supportedFormatExtensions(), feedback=feedback) parts = QgsProviderRegistry.instance().decodeUri( 'ogr', ogr_data_path) ogr_data_path = parts['path'] if 'layerName' in parts and parts['layerName']: ogr_layer_name = parts['layerName'] else: ogr_layer_name = GdalUtils.ogrLayerName(ogr_data_path) else: #either not using the selection, or #not executing - don't worry about 'selected features only' handling. It has no meaning #for the command line preview since it has no meaning outside of a QGIS session! ogr_data_path = GdalUtils.ogrConnectionStringAndFormatFromLayer( input_layer)[0] ogr_layer_name = GdalUtils.ogrLayerName( input_layer.dataProvider().dataSourceUri()) else: # vector layer, but not OGR - get OGR compatible path # TODO - handle "selected features only" mode!! ogr_data_path = GdalUtils.ogrConnectionStringFromLayer(input_layer) ogr_layer_name = GdalUtils.ogrLayerName( input_layer.dataProvider().dataSourceUri()) return ogr_data_path, ogr_layer_name
def processAlgorithm(self, parameters, context, feedback): connection_name = self.parameterAsConnectionName( parameters, self.DATABASE, context) # resolve connection details to uri try: md = QgsProviderRegistry.instance().providerMetadata('postgres') conn = md.createConnection(connection_name) except QgsProviderConnectionException: raise QgsProcessingException( self.tr('Could not retrieve connection details for {}').format( connection_name)) schema = self.parameterAsSchema(parameters, self.SCHEMA, context) overwrite = self.parameterAsBoolean(parameters, self.OVERWRITE, context) createIndex = self.parameterAsBoolean(parameters, self.CREATEINDEX, context) convertLowerCase = self.parameterAsBoolean(parameters, self.LOWERCASE_NAMES, context) dropStringLength = self.parameterAsBoolean(parameters, self.DROP_STRING_LENGTH, context) forceSinglePart = self.parameterAsBoolean(parameters, self.FORCE_SINGLEPART, context) primaryKeyField = self.parameterAsString(parameters, self.PRIMARY_KEY, context) or 'id' encoding = self.parameterAsString(parameters, self.ENCODING, context) source = self.parameterAsSource(parameters, self.INPUT, context) if source is None: raise QgsProcessingException( self.invalidSourceError(parameters, self.INPUT)) table = self.parameterAsDatabaseTableName(parameters, self.TABLENAME, context) if table: table.strip() if not table or table == '': table = source.sourceName() table = table.replace('.', '_') table = table.replace(' ', '')[0:62] providerName = 'postgres' geomColumn = self.parameterAsString(parameters, self.GEOMETRY_COLUMN, context) if not geomColumn: geomColumn = 'geom' options = {} if overwrite: options['overwrite'] = True if convertLowerCase: options['lowercaseFieldNames'] = True geomColumn = geomColumn.lower() if dropStringLength: options['dropStringConstraints'] = True if forceSinglePart: options['forceSinglePartGeometryType'] = True # Clear geometry column for non-geometry tables if source.wkbType() == QgsWkbTypes.NoGeometry: geomColumn = None uri = QgsDataSourceUri(conn.uri()) uri.setSchema(schema) uri.setTable(table) uri.setKeyColumn(primaryKeyField) uri.setGeometryColumn(geomColumn) if encoding: options['fileEncoding'] = encoding exporter = QgsVectorLayerExporter(uri.uri(), providerName, source.fields(), source.wkbType(), source.sourceCrs(), overwrite, options) if exporter.errorCode() != QgsVectorLayerExporter.NoError: raise QgsProcessingException( self.tr('Error importing to PostGIS\n{0}').format( exporter.errorMessage())) features = source.getFeatures() total = 100.0 / source.featureCount() if source.featureCount() else 0 for current, f in enumerate(features): if feedback.isCanceled(): break if not exporter.addFeature(f, QgsFeatureSink.FastInsert): feedback.reportError(exporter.errorMessage()) feedback.setProgress(int(current * total)) exporter.flushBuffer() if exporter.errorCode() != QgsVectorLayerExporter.NoError: raise QgsProcessingException( self.tr('Error importing to PostGIS\n{0}').format( exporter.errorMessage())) if geomColumn and createIndex: try: options = QgsAbstractDatabaseProviderConnection.SpatialIndexOptions( ) options.geometryColumnName = geomColumn conn.createSpatialIndex(schema, table, options) except QgsProviderConnectionException as e: raise QgsProcessingException( self.tr('Error creating spatial index:\n{0}').format(e)) try: conn.vacuum(schema, table) except QgsProviderConnectionException as e: feedback.reportError( self.tr('Error vacuuming table:\n{0}').format(e)) return {}
def testCapabilities(self): self.assertTrue(QgsProviderRegistry.instance().providerCapabilities("ogr") & QgsDataProvider.File) self.assertTrue(QgsProviderRegistry.instance().providerCapabilities("ogr") & QgsDataProvider.Dir)
def test_001_provider_defined(self): registry = QgsProviderRegistry.instance() metadata = registry.providerMetadata('delimitedtext') assert metadata is not None, "Delimited text provider is not installed"
def test_char_type_conversion(self): """Test char types: see GH #34806""" md = QgsProviderRegistry.instance().providerMetadata(self.providerKey) conn = md.createConnection(self.uri, {}) self.assertEqual(conn.executeSql("SELECT relname, relkind FROM pg_class c, pg_namespace n WHERE n.oid = c.relnamespace AND relname = 'bikes_view' AND c.relkind IN ('t', 'v', 'm')"), [['bikes_view', 'v']])
def test_postgis_connections(self): """Create some connections and retrieve them""" md = QgsProviderRegistry.instance().providerMetadata('postgres') conn = md.createConnection(self.uri, {}) md.saveConnection(conn, 'qgis_test1') # Retrieve capabilities capabilities = conn.capabilities() self.assertTrue( bool(capabilities & QgsAbstractDatabaseProviderConnection.Tables)) self.assertTrue( bool(capabilities & QgsAbstractDatabaseProviderConnection.Schemas)) self.assertTrue( bool(capabilities & QgsAbstractDatabaseProviderConnection.CreateVectorTable)) self.assertTrue( bool(capabilities & QgsAbstractDatabaseProviderConnection.DropVectorTable)) self.assertTrue( bool(capabilities & QgsAbstractDatabaseProviderConnection.RenameVectorTable)) self.assertTrue( bool(capabilities & QgsAbstractDatabaseProviderConnection.RenameRasterTable)) # Check filters and special cases table_names = self._table_names( conn.tables('qgis_test', QgsAbstractDatabaseProviderConnection.Raster)) self.assertTrue('Raster1' in table_names) self.assertFalse('geometryless_table' in table_names) self.assertFalse('geometries_table' in table_names) self.assertFalse('geometries_view' in table_names) table_names = self._table_names( conn.tables('qgis_test', QgsAbstractDatabaseProviderConnection.View)) self.assertFalse('Raster1' in table_names) self.assertFalse('geometryless_table' in table_names) self.assertFalse('geometries_table' in table_names) self.assertTrue('geometries_view' in table_names) table_names = self._table_names( conn.tables('qgis_test', QgsAbstractDatabaseProviderConnection.Aspatial)) self.assertFalse('Raster1' in table_names) self.assertTrue('geometryless_table' in table_names) self.assertFalse('geometries_table' in table_names) self.assertFalse('geometries_view' in table_names) tables = conn.tables( 'qgis_test', QgsAbstractDatabaseProviderConnection.Aspatial | QgsAbstractDatabaseProviderConnection.View) table_names = self._table_names(tables) b32523_view = self._table_by_name(tables, 'b32523') self.assertTrue(b32523_view) pks = b32523_view.primaryKeyColumns() self.assertTrue('pk' in pks) self.assertTrue('random' in pks) geometries_table = self._table_by_name(conn.tables('qgis_test'), 'geometries_table') srids_and_types = [[t.crs.postgisSrid(), t.wkbType] for t in geometries_table.geometryColumnTypes()] srids_and_types.sort() self.assertEqual( srids_and_types, [[0, 1], [0, 2], [0, 3], [0, 7], [3857, 1], [4326, 1]]) # Check TopoGeometry and Pointcloud layers are found in vector table names tables = conn.tables('qgis_test', QgsAbstractDatabaseProviderConnection.Vector) table_names = self._table_names(tables) self.assertTrue('TopoLayer1' in table_names) self.assertTrue('PointCloudPointLayer' in table_names) self.assertTrue('PointCloudPatchLayer' in table_names) self.assertTrue('geometries_table' in table_names) # Revoke select permissions on topology.topology from qgis_test_user conn.executeSql( 'REVOKE SELECT ON topology.topology FROM qgis_test_user') # Revoke select permissions on pointcloud_format from qgis_test_user conn.executeSql( 'REVOKE SELECT ON pointcloud_formats FROM qgis_test_user') # Re-connect as the qgis_test_role role newuri = self.uri + ' user=qgis_test_user password=qgis_test_user_password' newconn = md.createConnection(newuri, {}) # Check TopoGeometry and Pointcloud layers are not found in vector table names tables = newconn.tables('qgis_test', QgsAbstractDatabaseProviderConnection.Vector) table_names = self._table_names(tables) self.assertFalse('TopoLayer1' in table_names) self.assertFalse('PointCloudPointLayer' in table_names) self.assertFalse('PointCloudPatchLayer' in table_names) self.assertTrue('geometries_table' in table_names) # TODO: only revoke select permission on topology.layer, grant # on topology.topology # TODO: only revoke usage permission on topology, grant # all on topology.layer and topology.topology # TODO: only revoke select permission the actual topology # schema associated with TopoLayer1 # TODO: only revoke select permission the pointcloud_columns # table # Grant select permissions back on topology.topology to qgis_test_user conn.executeSql('GRANT SELECT ON topology.topology TO qgis_test_user') conn.executeSql('GRANT SELECT ON pointcloud_formats TO qgis_test_user')
def testCreateSqlVectorLayer(self): """Test vector layer creation from SQL query""" md = QgsProviderRegistry.instance().providerMetadata(self.providerKey) conn = md.createConnection(self.uri, {}) if not conn.capabilities() & QgsAbstractDatabaseProviderConnection.SqlLayers: print(f"FIXME: {self.providerKey} data provider does not support query layers!") return schema = getattr(self, 'sqlVectorLayerSchema', None) if schema is None: print(f"FIXME: {self.providerKey} data provider test case does not define self.sqlVectorLayerSchema for query layers test!") return table = getattr(self, 'sqlVectorLayerTable', None) if table is None: print(f"FIXME: {self.providerKey} data provider test case does not define self.sqlVectorLayerTable for query layers test!") return sql_layer_capabilities = conn.sqlLayerDefinitionCapabilities() # Try a simple select first table_info = conn.table(schema, table) options = QgsAbstractDatabaseProviderConnection.SqlVectorLayerOptions() options.layerName = 'My SQL Layer' # Some providers do not support schema if schema != '': options.sql = f'SELECT * FROM "{table_info.schema()}"."{table_info.tableName()}"' else: options.sql = f'SELECT * FROM "{table_info.tableName()}"' options.geometryColumn = table_info.geometryColumn() options.primaryKeyColumns = table_info.primaryKeyColumns() vl = conn.createSqlVectorLayer(options) self.assertTrue(vl.isSqlQuery()) self.assertTrue(vl.isValid()) self.assertTrue(vl.isSpatial()) self.assertEqual(vl.name(), options.layerName) # Test that a database connection can be retrieved from an existing layer vlconn = QgsMapLayerUtils.databaseConnection(vl) self.assertIsNotNone(vlconn) self.assertEqual(vlconn.uri(), conn.uri()) # Some providers can also create SQL layer without an explicit PK if sql_layer_capabilities & Qgis.SqlLayerDefinitionCapability.PrimaryKeys: options.primaryKeyColumns = [] vl = conn.createSqlVectorLayer(options) self.assertTrue(vl.isSqlQuery()) self.assertTrue(vl.isValid()) self.assertTrue(vl.isSpatial()) # Some providers can also create SQL layer without an explicit geometry column if sql_layer_capabilities & Qgis.SqlLayerDefinitionCapability.GeometryColumn: options.primaryKeyColumns = table_info.primaryKeyColumns() options.geometryColumn = '' vl = conn.createSqlVectorLayer(options) self.assertTrue(vl.isValid()) self.assertTrue(vl.isSqlQuery()) # This may fail for OGR where the provider is smart enough to guess the geometry column if self.providerKey != 'ogr': self.assertFalse(vl.isSpatial()) # Some providers can also create SQL layer with filters if sql_layer_capabilities & Qgis.SqlLayerDefinitionCapability.SubsetStringFilter: options.primaryKeyColumns = table_info.primaryKeyColumns() options.geometryColumn = table_info.geometryColumn() options.filter = f'"{options.primaryKeyColumns[0]}" > 0' vl = conn.createSqlVectorLayer(options) self.assertTrue(vl.isValid()) self.assertTrue(vl.isSqlQuery()) self.assertTrue(vl.isSpatial())
def test_mssql_connections_from_uri(self): """Create a connection from a layer uri and retrieve it""" md = QgsProviderRegistry.instance().providerMetadata('mssql')
def processAlgorithm(self, parameters, context, feedback): metadata = QgsProviderRegistry.instance().providerMetadata('postgres') if Qgis.QGIS_VERSION_INT >= 31400: connection_name = self.parameterAsConnectionName( parameters, self.CONNECTION_NAME, context) else: connection_name = self.parameterAsString(parameters, self.CONNECTION_NAME, context) connection = metadata.findConnection(connection_name) if not connection: raise QgsProcessingException( tr("La connexion {} n'existe pas.").format(connection_name)) # Drop schema if needed override = self.parameterAsBool(parameters, self.OVERRIDE, context) if override and SCHEMA in connection.schemas(): feedback.pushInfo(tr("Suppression du schéma {}…").format(SCHEMA)) try: connection.dropSchema(SCHEMA, True) except QgsProviderConnectionException as e: raise QgsProcessingException(str(e)) # Create full structure sql_files = [ "00_initialize_database.sql", "{}/10_FUNCTION.sql".format(SCHEMA), "{}/20_TABLE_SEQUENCE_DEFAULT.sql".format(SCHEMA), "{}/30_VIEW.sql".format(SCHEMA), "{}/40_INDEX.sql".format(SCHEMA), "{}/50_TRIGGER.sql".format(SCHEMA), "{}/60_CONSTRAINT.sql".format(SCHEMA), "{}/70_COMMENT.sql".format(SCHEMA), "{}/90_GLOSSARY.sql".format(SCHEMA), "99_finalize_database.sql", ] # Add test data add_test_data = self.parameterAsBool(parameters, self.ADD_TEST_DATA, context) if add_test_data: sql_files.append("99_test_data.sql") plugin_dir = plugin_path() plugin_version = version() dev_version = False run_migration = os.environ.get("TEST_DATABASE_INSTALL_{}".format( SCHEMA.upper())) if plugin_version in ["master", "dev"] and not run_migration: feedback.reportError( "Be careful, running the install on a development branch!") dev_version = True if run_migration: plugin_dir = plugin_test_data_path() feedback.reportError( "Be careful, running migrations on an empty database using {} " "instead of {}".format(run_migration, plugin_version)) plugin_version = run_migration # Loop sql files and run SQL code for sf in sql_files: feedback.pushInfo(sf) sql_file = os.path.join(plugin_dir, "install/sql/{}".format(sf)) with open(sql_file, "r") as f: sql = f.read() if len(sql.strip()) == 0: feedback.pushInfo(" Skipped (empty file)") continue try: connection.executeSql(sql) except QgsProviderConnectionException as e: raise QgsProcessingException(str(e)) feedback.pushInfo(" Success !") # Add version if run_migration or not dev_version: metadata_version = plugin_version else: migrations = available_migrations(000000) last_migration = migrations[-1] metadata_version = (last_migration.replace("upgrade_to_", "").replace(".sql", "").strip()) feedback.reportError( "Latest migration is {}".format(metadata_version)) sql = """ INSERT INTO {}.metadata (me_version, me_version_date, me_status) VALUES ( '{}', now()::timestamp(0), 1 )""".format(SCHEMA, metadata_version) try: connection.executeSql(sql) except QgsProviderConnectionException as e: raise QgsProcessingException(str(e)) feedback.pushInfo( "Version de la base de données '{}'.".format(metadata_version)) if run_migration: feedback.reportError( "You need to run migrations, old version installed !") results = { self.DATABASE_VERSION: metadata_version, } return results
def testModel(self): conn = QgsProviderRegistry.instance().providerMetadata( 'postgres').createConnection(self.uri, {}) self.assertTrue(conn) model = QgsDatabaseTableModel(conn) self.assertGreaterEqual(model.rowCount(), 3) old_count = model.rowCount() self.assertEqual(model.columnCount(), 1) tables = [ model.data(model.index(r, 0, QModelIndex()), Qt.DisplayRole) for r in range(model.rowCount()) ] self.assertIn('qgis_test.someData', tables) self.assertIn('qgis_test.some_poly_data', tables) self.assertIn('information_schema.attributes', tables) self.assertEqual( model.data( model.index(tables.index('qgis_test.someData'), 0, QModelIndex()), QgsDatabaseTableModel.RoleTableName), 'someData') self.assertEqual( model.data( model.index(tables.index('qgis_test.someData'), 0, QModelIndex()), QgsDatabaseTableModel.RoleSchema), 'qgis_test') self.assertEqual( model.data( model.index(tables.index('qgis_test.someData'), 0, QModelIndex()), QgsDatabaseTableModel.RoleComment), 'QGIS Test Table') self.assertEqual( model.data( model.index(tables.index('qgis_test.someData'), 0, QModelIndex()), QgsDatabaseTableModel.RoleCrs), QgsCoordinateReferenceSystem('EPSG:4326')) self.assertEqual( model.data( model.index(tables.index('qgis_test.someData'), 0, QModelIndex()), QgsDatabaseTableModel.RoleCustomInfo), {}) self.assertEqual( model.data( model.index(tables.index('qgis_test.someData'), 0, QModelIndex()), QgsDatabaseTableModel.RoleTableFlags), 4) self.assertEqual( model.data( model.index(tables.index('qgis_test.someData'), 0, QModelIndex()), QgsDatabaseTableModel.RoleWkbType), QgsWkbTypes.Point) self.assertEqual( model.data( model.index(tables.index('qgis_test.some_poly_data'), 0, QModelIndex()), QgsDatabaseTableModel.RoleWkbType), QgsWkbTypes.Polygon) self.assertIsNone( model.data(model.index(model.rowCount(), 0, QModelIndex()), Qt.DisplayRole)) model.refresh() self.assertEqual(model.rowCount(), old_count) fields = QgsFields() fields.append(QgsField('test', QVariant.String)) conn.createVectorTable('qgis_test', 'myNewTable', fields, QgsWkbTypes.Point, QgsCoordinateReferenceSystem('EPSG:3857'), False, {}) self.assertEqual(model.rowCount(), old_count) model.refresh() self.assertEqual(model.rowCount(), old_count + 1) tables = [ model.data(model.index(r, 0, QModelIndex()), Qt.DisplayRole) for r in range(model.rowCount()) ] self.assertIn('qgis_test.someData', tables) self.assertIn('qgis_test.some_poly_data', tables) self.assertIn('information_schema.attributes', tables) self.assertIn('qgis_test.myNewTable', tables) conn.createVectorTable('qgis_test', 'myNewTable2', fields, QgsWkbTypes.Point, QgsCoordinateReferenceSystem('EPSG:3857'), False, {}) conn.createVectorTable('qgis_test', 'myNewTable3', fields, QgsWkbTypes.Point, QgsCoordinateReferenceSystem('EPSG:3857'), False, {}) model.refresh() self.assertEqual(model.rowCount(), old_count + 3) tables = [ model.data(model.index(r, 0, QModelIndex()), Qt.DisplayRole) for r in range(model.rowCount()) ] self.assertIn('qgis_test.someData', tables) self.assertIn('qgis_test.some_poly_data', tables) self.assertIn('information_schema.attributes', tables) self.assertIn('qgis_test.myNewTable', tables) self.assertIn('qgis_test.myNewTable2', tables) self.assertIn('qgis_test.myNewTable3', tables) conn.createVectorTable('qgis_test', 'myNewTable4', fields, QgsWkbTypes.Point, QgsCoordinateReferenceSystem('EPSG:3857'), False, {}) conn.dropVectorTable('qgis_test', 'myNewTable2') conn.dropVectorTable('qgis_test', 'myNewTable') model.refresh() self.assertEqual(model.rowCount(), old_count + 2) tables = [ model.data(model.index(r, 0, QModelIndex()), Qt.DisplayRole) for r in range(model.rowCount()) ] self.assertIn('qgis_test.someData', tables) self.assertIn('qgis_test.some_poly_data', tables) self.assertIn('information_schema.attributes', tables) self.assertNotIn('qgis_test.myNewTable', tables) self.assertNotIn('qgis_test.myNewTable2', tables) self.assertIn('qgis_test.myNewTable3', tables) self.assertIn('qgis_test.myNewTable4', tables) conn.dropVectorTable('qgis_test', 'myNewTable3') conn.dropVectorTable('qgis_test', 'myNewTable4') model.refresh() self.assertEqual(model.rowCount(), old_count) tables = [ model.data(model.index(r, 0, QModelIndex()), Qt.DisplayRole) for r in range(model.rowCount()) ] self.assertIn('qgis_test.someData', tables) self.assertIn('qgis_test.some_poly_data', tables) self.assertIn('information_schema.attributes', tables) self.assertNotIn('qgis_test.myNewTable', tables) self.assertNotIn('qgis_test.myNewTable2', tables) self.assertNotIn('qgis_test.myNewTable3', tables) self.assertNotIn('qgis_test.myNewTable4', tables)
def tesRegisterSameProviderTwice(self): """Test that a provider cannot be registered twice""" r = QgsProviderRegistry.instance() metadata = QgsProviderMetadata(PyProvider.providerKey(), PyProvider.description(), PyProvider.createProvider) self.assertFalse(r.registerProvider(metadata))
def test_schemas(self): """Test schemas retrieval""" md = QgsProviderRegistry.instance().providerMetadata('oracle') conn = md.createConnection(self.uri, {}) self.assertTrue('QGIS' in conn.schemas())
def test_postgis_connections(self): """Create some connections and retrieve them""" md = QgsProviderRegistry.instance().providerMetadata('postgres') conn = md.createConnection(self.uri, {}) md.saveConnection(conn, 'qgis_test1') # Retrieve capabilities capabilities = conn.capabilities() self.assertTrue( bool(capabilities & QgsAbstractDatabaseProviderConnection.Tables)) self.assertTrue( bool(capabilities & QgsAbstractDatabaseProviderConnection.Schemas)) self.assertTrue( bool(capabilities & QgsAbstractDatabaseProviderConnection.CreateVectorTable)) self.assertTrue( bool(capabilities & QgsAbstractDatabaseProviderConnection.DropVectorTable)) self.assertTrue( bool(capabilities & QgsAbstractDatabaseProviderConnection.RenameVectorTable)) self.assertTrue( bool(capabilities & QgsAbstractDatabaseProviderConnection.RenameRasterTable)) # Check filters and special cases table_names = self._table_names( conn.tables('qgis_test', QgsAbstractDatabaseProviderConnection.Raster)) self.assertTrue('Raster1' in table_names) self.assertFalse('geometryless_table' in table_names) self.assertFalse('geometries_table' in table_names) self.assertFalse('geometries_view' in table_names) table_names = self._table_names( conn.tables('qgis_test', QgsAbstractDatabaseProviderConnection.View)) self.assertFalse('Raster1' in table_names) self.assertFalse('geometryless_table' in table_names) self.assertFalse('geometries_table' in table_names) self.assertTrue('geometries_view' in table_names) table_names = self._table_names( conn.tables('qgis_test', QgsAbstractDatabaseProviderConnection.Aspatial)) self.assertFalse('Raster1' in table_names) self.assertTrue('geometryless_table' in table_names) self.assertFalse('geometries_table' in table_names) self.assertFalse('geometries_view' in table_names) geometries_table = self._table_by_name(conn.tables('qgis_test'), 'geometries_table') srids = [ t.crs.postgisSrid() for t in geometries_table.geometryColumnTypes() ] self.assertEqual(srids, [0, 0, 0, 3857, 4326, 0]) types = [t.wkbType for t in geometries_table.geometryColumnTypes()] self.assertEqual(types, [7, 2, 1, 1, 1, 3])
def test_tables_with_options(self): md = QgsProviderRegistry.instance().providerMetadata('oracle') def get_tables( schema, configuration, flags=QgsAbstractDatabaseProviderConnection.TableFlags()): conn = md.createConnection(self.uri, configuration) tables = conn.tables(schema, flags) return sorted([ table.tableName() for table in tables if table.tableName() in [ 'DATE_TIMES', 'GENERATED_COLUMNS', 'LINE_DATA', 'OTHER_TABLE', 'POINT_DATA', 'POINT_DATA_IDENTITY', 'POLY_DATA', 'SOME_DATA', 'SOME_POLY_DATA' ] ]) # all tables self.assertEqual(get_tables('QGIS', {}), [ 'DATE_TIMES', 'GENERATED_COLUMNS', 'LINE_DATA', 'POINT_DATA', 'POINT_DATA_IDENTITY', 'POLY_DATA', 'SOME_DATA', 'SOME_POLY_DATA' ]) # only non-spatial tables self.assertEqual( get_tables('QGIS', {}, QgsAbstractDatabaseProviderConnection.Aspatial), ['DATE_TIMES', 'GENERATED_COLUMNS']) # only vector tables self.assertEqual( get_tables('QGIS', {}, QgsAbstractDatabaseProviderConnection.Vector), [ 'LINE_DATA', 'POINT_DATA', 'POINT_DATA_IDENTITY', 'POLY_DATA', 'SOME_DATA', 'SOME_POLY_DATA' ]) # only table existing in sdo_geom_metadata table self.assertEqual( get_tables('QGIS', {"geometryColumnsOnly": True}, QgsAbstractDatabaseProviderConnection.Vector), ['SOME_DATA', 'SOME_POLY_DATA']) self.execSQLCommand('DROP TABLE OTHER_USER.OTHER_TABLE', ignore_errors=True) self.execSQLCommand('DROP USER OTHER_USER CASCADE', ignore_errors=True) self.execSQLCommand('CREATE USER OTHER_USER') self.execSQLCommand('GRANT ALL PRIVILEGES TO OTHER_USER') self.execSQLCommand( 'CREATE TABLE OTHER_USER.OTHER_TABLE ( "pk" INTEGER PRIMARY KEY, GEOM SDO_GEOMETRY)' ) # if a schema is specified, schema (i.e. user) tables are returned, whatever userTablesOnly value self.assertEqual(get_tables('OTHER_USER', {"userTablesOnly": True}), ['OTHER_TABLE']) self.assertEqual(get_tables('OTHER_USER', {"userTablesOnly": False}), ['OTHER_TABLE']) # no schema is specified, all user tables (vector ones in this case) are returned self.assertEqual( get_tables('', {"userTablesOnly": True}, QgsAbstractDatabaseProviderConnection.Vector), [ 'LINE_DATA', 'POINT_DATA', 'POINT_DATA_IDENTITY', 'POLY_DATA', 'SOME_DATA', 'SOME_POLY_DATA' ]) # no schema is specified, all tables (vector ones in this case) tables are returned self.assertEqual( get_tables('', {"userTablesOnly": False}, QgsAbstractDatabaseProviderConnection.Vector), [ 'LINE_DATA', 'OTHER_TABLE', 'POINT_DATA', 'POINT_DATA_IDENTITY', 'POLY_DATA', 'SOME_DATA', 'SOME_POLY_DATA' ])
def allVectorsFilter(self): if self.vectorsFilter == '': self.vectorsFilter = QgsProviderRegistry.instance( ).fileVectorFilters() return self.vectorsFilter
def test_dialog(self): md = QgsProviderRegistry.instance().providerMetadata('ogr') conn = md.createConnection(self.uri, {}) dialog = QgsNewVectorTableDialog(conn) dialog.setFields(conn.fields('', 'cdb_lines')) dialog.setTableName('no_lock_me_down_again') # dialog.exec_() geom_type_combo = dialog.findChildren(QComboBox, 'mGeomTypeCbo')[0] geom_name_le = dialog.findChildren(QLineEdit, 'mGeomColumn')[0] has_z_chk = dialog.findChildren(QCheckBox, 'mHasZChk')[0] has_m_chk = dialog.findChildren(QCheckBox, 'mHasMChk')[0] table_name = dialog.findChildren(QLineEdit, 'mTableName')[0] buttons = dialog.findChildren(QDialogButtonBox, 'mButtonBox')[0] ok_btn = buttons.button(QDialogButtonBox.Ok) # Default is no geometry, let's check if all geom options are disabled self.assertFalse(geom_name_le.isEnabled()) self.assertFalse(has_z_chk.isEnabled()) self.assertFalse(has_m_chk.isEnabled()) # 2 is linestring geom_type_combo.setCurrentIndex(3) self.assertTrue(geom_name_le.isEnabled()) self.assertTrue(has_z_chk.isEnabled()) self.assertTrue(has_m_chk.isEnabled()) self.assertEqual(dialog.geometryType(), QgsWkbTypes.LineString) # Set Z and check the type has_z_chk.setChecked(True) self.assertEqual(dialog.geometryType(), QgsWkbTypes.LineStringZ) has_z_chk.setChecked(False) # Set M and check the type has_m_chk.setChecked(True) self.assertEqual(dialog.geometryType(), QgsWkbTypes.LineStringM) # Set both has_z_chk.setChecked(True) self.assertEqual(dialog.geometryType(), QgsWkbTypes.LineStringZM) # Test validation (ok button enabled) buttons = dialog.findChildren(QDialogButtonBox, 'mButtonBox')[0] ok_btn = buttons.button(QDialogButtonBox.Ok) self.assertTrue(ok_btn.isEnabled()) # Duplicate table name table_name.setText('cdb_lines') self.assertFalse(ok_btn.isEnabled()) table_name.setText('cdb_lines2') self.assertTrue(ok_btn.isEnabled()) # No fields (but geometry is ok) dialog.setFields(QgsFields()) self.assertTrue(ok_btn.isEnabled()) # Change to aspatial and check validity geom_type_combo.setCurrentIndex(0) self.assertFalse(ok_btn.isEnabled())
def getFileFilter(param): """ Returns a suitable file filter pattern for the specified parameter definition :param param: :return: """ if param.type() == 'layer': vectors = QgsProviderRegistry.instance().fileVectorFilters().split( ';;') vectors.pop(0) rasters = QgsProviderRegistry.instance().fileRasterFilters().split( ';;') rasters.pop(0) filters = set(vectors + rasters) filters = sorted(filters) return tr('All files (*.*)') + ';;' + ";;".join(filters) elif param.type() == 'multilayer': if param.layerType() == QgsProcessing.TypeRaster: exts = QgsRasterFileWriter.supportedFormatExtensions() elif param.layerType() == QgsProcessing.TypeFile: return tr('All files (*.*)', 'QgsProcessingParameterMultipleLayers') else: exts = QgsVectorFileWriter.supportedFormatExtensions() for i in range(len(exts)): exts[i] = tr('{0} files (*.{1})', 'QgsProcessingParameterMultipleLayers').format( exts[i].upper(), exts[i].lower()) return tr('All files (*.*)') + ';;' + ';;'.join(exts) elif param.type() == 'raster': return QgsProviderRegistry.instance().fileRasterFilters() elif param.type() == 'rasterDestination': if param.provider() is not None: exts = param.provider().supportedOutputRasterLayerExtensions() else: exts = QgsRasterFileWriter.supportedFormatExtensions() for i in range(len(exts)): exts[i] = tr('{0} files (*.{1})', 'ParameterRaster').format(exts[i].upper(), exts[i].lower()) return ';;'.join(exts) + ';;' + tr('All files (*.*)') elif param.type() in ('sink', 'vectorDestination'): if param.provider() is not None: exts = param.provider().supportedOutputVectorLayerExtensions() else: exts = QgsVectorFileWriter.supportedFormatExtensions() for i in range(len(exts)): exts[i] = tr('{0} files (*.{1})', 'ParameterVector').format(exts[i].upper(), exts[i].lower()) return ';;'.join(exts) + ';;' + tr('All files (*.*)') elif param.type() == 'source': return QgsProviderRegistry.instance().fileVectorFilters() elif param.type() == 'vector': return QgsProviderRegistry.instance().fileVectorFilters() elif param.type() == 'fileDestination': return param.fileFilter() + ';;' + tr('All files (*.*)') if param.defaultFileExtension(): return tr( 'Default extension') + ' (*.' + param.defaultFileExtension() + ')' else: return ''
def test_model(self): """Test model functionality""" md = QgsProviderRegistry.instance().providerMetadata('ogr') conn = md.createConnection(self.gpkg_path, {}) md.saveConnection(conn, 'qgis_test1') model = QgsProviderConnectionModel('ogr') self.assertEqual(model.rowCount(), 1) self.assertEqual(model.columnCount(), 1) self.assertEqual( model.data(model.index(0, 0, QModelIndex()), Qt.DisplayRole), 'qgis_test1') self.assertEqual( model.data(model.index(0, 0, QModelIndex()), Qt.ToolTipRole), self.gpkg_path) self.assertEqual( model.data(model.index(0, 0, QModelIndex()), QgsProviderConnectionModel.RoleConnectionName), 'qgis_test1') self.assertEqual( model.data(model.index(0, 0, QModelIndex()), QgsProviderConnectionModel.RoleUri), self.gpkg_path) self.assertEqual( model.data(model.index(0, 0, QModelIndex()), QgsProviderConnectionModel.RoleConfiguration), {}) md.saveConnection(conn, 'qgis_test1') self.assertEqual(model.rowCount(), 1) self.assertEqual( model.data(model.index(0, 0, QModelIndex()), Qt.DisplayRole), 'qgis_test1') conn2 = md.createConnection(self.gpkg_path2, {}) md.saveConnection(conn2, 'qgis_test2') self.assertEqual(model.rowCount(), 2) self.assertEqual( model.data(model.index(0, 0, QModelIndex()), Qt.DisplayRole), 'qgis_test1') self.assertEqual( model.data(model.index(0, 0, QModelIndex()), Qt.ToolTipRole), self.gpkg_path) self.assertEqual( model.data(model.index(0, 0, QModelIndex()), QgsProviderConnectionModel.RoleConnectionName), 'qgis_test1') self.assertEqual( model.data(model.index(0, 0, QModelIndex()), QgsProviderConnectionModel.RoleUri), self.gpkg_path) self.assertEqual( model.data(model.index(1, 0, QModelIndex()), Qt.DisplayRole), 'qgis_test2') self.assertEqual( model.data(model.index(1, 0, QModelIndex()), Qt.ToolTipRole), self.gpkg_path2) self.assertEqual( model.data(model.index(1, 0, QModelIndex()), QgsProviderConnectionModel.RoleConnectionName), 'qgis_test2') self.assertEqual( model.data(model.index(1, 0, QModelIndex()), QgsProviderConnectionModel.RoleUri), self.gpkg_path2) md.deleteConnection('qgis_test1') self.assertEqual(model.rowCount(), 1) self.assertEqual( model.data(model.index(0, 0, QModelIndex()), Qt.DisplayRole), 'qgis_test2') md.deleteConnection('qgis_test2')
def testCombo(self): """ test combobox functionality """ md = QgsProviderRegistry.instance().providerMetadata('postgres') conn = md.createConnection(self.uri, {}) md.saveConnection(conn, 'mycon') m = QgsDatabaseTableComboBox('postgres', 'mycon') self.assertGreaterEqual(m.comboBox().count(), 3) text = [m.comboBox().itemText(i) for i in range(m.comboBox().count())] self.assertIn('information_schema.attributes', text) self.assertIn('qgis_test.some_poly_data', text) self.assertLess(text.index('information_schema.attributes'), text.index('qgis_test.some_poly_data')) self.assertTrue(m.currentSchema()) self.assertTrue(m.currentTable()) m.setSchema('information_schema') m.setTable('attributes') spy = QSignalSpy(m.tableChanged) m.setSchema('qgis_test') text = [m.comboBox().itemText(i) for i in range(m.comboBox().count())] self.assertNotIn('information_schema.attributes', text) self.assertNotIn('attributes', text) self.assertIn('some_poly_data', text) self.assertEqual(m.currentTable(), '') self.assertEqual(m.currentSchema(), '') self.assertEqual(len(spy), 1) self.assertFalse(spy[-1][0]) m.setTable('') self.assertEqual(m.currentTable(), '') self.assertEqual(m.currentSchema(), '') self.assertEqual(len(spy), 1) self.assertFalse(spy[-1][0]) m.setTable('someData') self.assertEqual(len(spy), 2) self.assertEqual(m.currentSchema(), 'qgis_test') self.assertEqual(m.currentTable(), 'someData') self.assertEqual(spy[-1][0], 'someData') self.assertEqual(spy[-1][1], 'qgis_test') fields = QgsFields() fields.append(QgsField('test', QVariant.String)) conn.createVectorTable('qgis_test', 'myNewTable', fields, QgsWkbTypes.Point, QgsCoordinateReferenceSystem('EPSG:3857'), False, {}) text2 = [m.comboBox().itemText(i) for i in range(m.comboBox().count())] # tables are not automatically refreshed self.assertEqual(text2, text) # but setting a new connection should fix this! md = QgsProviderRegistry.instance().providerMetadata('postgres') conn2 = md.createConnection(self.uri, {}) md.saveConnection(conn2, 'another') m.setConnectionName('another', 'postgres') # ideally there'd be no extra signal here, but it's a minor issue... self.assertEqual(len(spy), 3) self.assertEqual(m.currentTable(), 'someData') self.assertEqual(m.currentSchema(), 'qgis_test') self.assertEqual(spy[-1][0], 'someData') self.assertEqual(spy[-1][1], 'qgis_test') text2 = [m.comboBox().itemText(i) for i in range(m.comboBox().count())] self.assertNotEqual(text2, text) self.assertIn('myNewTable', text2) m.setTable('myNewTable') self.assertEqual(len(spy), 4) self.assertEqual(m.currentTable(), 'myNewTable') self.assertEqual(m.currentSchema(), 'qgis_test') self.assertEqual(spy[-1][0], 'myNewTable') self.assertEqual(spy[-1][1], 'qgis_test') # no auto drop conn.dropVectorTable('qgis_test', 'myNewTable') self.assertEqual(len(spy), 4) self.assertEqual(m.currentTable(), 'myNewTable') self.assertEqual(m.currentSchema(), 'qgis_test') self.assertEqual(spy[-1][0], 'myNewTable') self.assertEqual(spy[-1][1], 'qgis_test') m.refreshTables() text2 = [m.comboBox().itemText(i) for i in range(m.comboBox().count())] self.assertNotIn('myNewTable', text2) self.assertEqual(len(spy), 5) self.assertFalse(m.currentSchema()) self.assertFalse(spy[-1][0])
def createProviderMetadata(self): return QgsProviderRegistry.instance().providerMetadata( self.providerKey)
def test_model_allow_empty(self): """Test model with empty entry""" model = QgsProviderConnectionModel('ogr') self.assertEqual(model.rowCount(), 0) model.setAllowEmptyConnection(True) self.assertEqual(model.rowCount(), 1) self.assertFalse( model.data(model.index(0, 0, QModelIndex()), Qt.DisplayRole)) self.assertTrue( model.data(model.index(0, 0, QModelIndex()), QgsProviderConnectionModel.RoleEmpty)) md = QgsProviderRegistry.instance().providerMetadata('ogr') conn = md.createConnection(self.gpkg_path, {}) md.saveConnection(conn, 'qgis_test1') model.setAllowEmptyConnection(False) model.setAllowEmptyConnection(False) self.assertEqual(model.rowCount(), 1) self.assertEqual(model.columnCount(), 1) self.assertEqual( model.data(model.index(0, 0, QModelIndex()), Qt.DisplayRole), 'qgis_test1') self.assertEqual( model.data(model.index(0, 0, QModelIndex()), Qt.ToolTipRole), self.gpkg_path) self.assertEqual( model.data(model.index(0, 0, QModelIndex()), QgsProviderConnectionModel.RoleConnectionName), 'qgis_test1') self.assertEqual( model.data(model.index(0, 0, QModelIndex()), QgsProviderConnectionModel.RoleUri), self.gpkg_path) self.assertEqual( model.data(model.index(0, 0, QModelIndex()), QgsProviderConnectionModel.RoleConfiguration), {}) self.assertFalse( model.data(model.index(0, 0, QModelIndex()), QgsProviderConnectionModel.RoleEmpty)) model.setAllowEmptyConnection(True) model.setAllowEmptyConnection(True) self.assertEqual(model.rowCount(), 2) self.assertFalse( model.data(model.index(0, 0, QModelIndex()), Qt.DisplayRole)) self.assertFalse( model.data(model.index(0, 0, QModelIndex()), Qt.ToolTipRole)) self.assertFalse( model.data(model.index(0, 0, QModelIndex()), QgsProviderConnectionModel.RoleConnectionName)) self.assertFalse( model.data(model.index(0, 0, QModelIndex()), QgsProviderConnectionModel.RoleUri)) self.assertFalse( model.data(model.index(0, 0, QModelIndex()), QgsProviderConnectionModel.RoleConfiguration)) self.assertTrue( model.data(model.index(0, 0, QModelIndex()), QgsProviderConnectionModel.RoleEmpty)) self.assertEqual( model.data(model.index(1, 0, QModelIndex()), Qt.DisplayRole), 'qgis_test1') self.assertEqual( model.data(model.index(1, 0, QModelIndex()), Qt.ToolTipRole), self.gpkg_path) self.assertEqual( model.data(model.index(1, 0, QModelIndex()), QgsProviderConnectionModel.RoleConnectionName), 'qgis_test1') self.assertEqual( model.data(model.index(1, 0, QModelIndex()), QgsProviderConnectionModel.RoleUri), self.gpkg_path) self.assertEqual( model.data(model.index(1, 0, QModelIndex()), QgsProviderConnectionModel.RoleConfiguration), {}) self.assertFalse( model.data(model.index(1, 0, QModelIndex()), QgsProviderConnectionModel.RoleEmpty)) md.saveConnection(conn, 'qgis_test1') self.assertEqual(model.rowCount(), 2) self.assertFalse( model.data(model.index(0, 0, QModelIndex()), Qt.DisplayRole)) self.assertTrue( model.data(model.index(0, 0, QModelIndex()), QgsProviderConnectionModel.RoleEmpty)) self.assertEqual( model.data(model.index(1, 0, QModelIndex()), Qt.DisplayRole), 'qgis_test1') self.assertFalse( model.data(model.index(1, 0, QModelIndex()), QgsProviderConnectionModel.RoleEmpty)) model.setAllowEmptyConnection(False) self.assertEqual(model.rowCount(), 1) self.assertEqual( model.data(model.index(0, 0, QModelIndex()), Qt.DisplayRole), 'qgis_test1') self.assertFalse( model.data(model.index(0, 0, QModelIndex()), QgsProviderConnectionModel.RoleEmpty)) model.setAllowEmptyConnection(True) conn2 = md.createConnection(self.gpkg_path2, {}) md.saveConnection(conn2, 'qgis_test2') self.assertEqual(model.rowCount(), 3) self.assertFalse( model.data(model.index(0, 0, QModelIndex()), Qt.DisplayRole)) self.assertTrue( model.data(model.index(0, 0, QModelIndex()), QgsProviderConnectionModel.RoleEmpty)) self.assertEqual( model.data(model.index(1, 0, QModelIndex()), Qt.DisplayRole), 'qgis_test1') self.assertEqual( model.data(model.index(1, 0, QModelIndex()), Qt.ToolTipRole), self.gpkg_path) self.assertEqual( model.data(model.index(1, 0, QModelIndex()), QgsProviderConnectionModel.RoleConnectionName), 'qgis_test1') self.assertEqual( model.data(model.index(1, 0, QModelIndex()), QgsProviderConnectionModel.RoleUri), self.gpkg_path) self.assertFalse( model.data(model.index(1, 0, QModelIndex()), QgsProviderConnectionModel.RoleEmpty)) self.assertEqual( model.data(model.index(2, 0, QModelIndex()), Qt.DisplayRole), 'qgis_test2') self.assertEqual( model.data(model.index(2, 0, QModelIndex()), Qt.ToolTipRole), self.gpkg_path2) self.assertEqual( model.data(model.index(2, 0, QModelIndex()), QgsProviderConnectionModel.RoleConnectionName), 'qgis_test2') self.assertEqual( model.data(model.index(2, 0, QModelIndex()), QgsProviderConnectionModel.RoleUri), self.gpkg_path2) self.assertFalse( model.data(model.index(2, 0, QModelIndex()), QgsProviderConnectionModel.RoleEmpty)) model.setAllowEmptyConnection(False) self.assertEqual(model.rowCount(), 2) self.assertEqual( model.data(model.index(0, 0, QModelIndex()), Qt.DisplayRole), 'qgis_test1') self.assertEqual( model.data(model.index(1, 0, QModelIndex()), Qt.DisplayRole), 'qgis_test2') model.setAllowEmptyConnection(True) md.deleteConnection('qgis_test1') self.assertEqual(model.rowCount(), 2) self.assertFalse( model.data(model.index(0, 0, QModelIndex()), Qt.DisplayRole)) self.assertEqual( model.data(model.index(1, 0, QModelIndex()), Qt.DisplayRole), 'qgis_test2') model.setAllowEmptyConnection(False) self.assertEqual(model.rowCount(), 1) self.assertEqual( model.data(model.index(0, 0, QModelIndex()), Qt.DisplayRole), 'qgis_test2')
def test_model_allow_empty(self): """Test model with empty entry""" conn = QgsProviderRegistry.instance().providerMetadata( 'postgres').createConnection(self.uri, {}) self.assertTrue(conn) model = QgsDatabaseSchemaModel(conn) self.assertGreaterEqual(model.rowCount(), 3) old_count = model.rowCount() model.setAllowEmptySchema(True) self.assertEqual(model.rowCount(), old_count + 1) schemas = [ model.data(model.index(r, 0, QModelIndex()), Qt.DisplayRole) for r in range(model.rowCount()) ] self.assertIn('public', schemas) self.assertIn('CamelCaseSchema', schemas) self.assertIn('qgis_test', schemas) self.assertFalse( model.data(model.index(0, 0, QModelIndex()), Qt.DisplayRole)) self.assertTrue( model.data(model.index(0, 0, QModelIndex()), QgsDatabaseSchemaModel.RoleEmpty)) self.assertFalse( model.data( model.index(schemas.index('qgis_test'), 0, QModelIndex()), QgsDatabaseSchemaModel.RoleEmpty)) self.assertIsNone( model.data(model.index(model.rowCount(), 0, QModelIndex()), Qt.DisplayRole)) model.refresh() self.assertEqual(model.rowCount(), old_count + 1) conn.createSchema('myNewSchema') self.assertEqual(model.rowCount(), old_count + 1) model.refresh() self.assertEqual(model.rowCount(), old_count + 2) schemas = [ model.data(model.index(r, 0, QModelIndex()), Qt.DisplayRole) for r in range(model.rowCount()) ] self.assertIn('public', schemas) self.assertIn('CamelCaseSchema', schemas) self.assertIn('qgis_test', schemas) self.assertIn('myNewSchema', schemas) self.assertFalse( model.data(model.index(0, 0, QModelIndex()), Qt.DisplayRole)) self.assertTrue( model.data(model.index(0, 0, QModelIndex()), QgsDatabaseSchemaModel.RoleEmpty)) self.assertFalse( model.data( model.index(schemas.index('qgis_test'), 0, QModelIndex()), QgsDatabaseSchemaModel.RoleEmpty)) model.setAllowEmptySchema(False) self.assertEqual(model.rowCount(), old_count + 1) self.assertTrue( model.data(model.index(0, 0, QModelIndex()), Qt.DisplayRole)) self.assertFalse( model.data(model.index(0, 0, QModelIndex()), QgsDatabaseSchemaModel.RoleEmpty)) model.setAllowEmptySchema(True) self.assertEqual(model.rowCount(), old_count + 2) self.assertFalse( model.data(model.index(0, 0, QModelIndex()), Qt.DisplayRole)) self.assertTrue( model.data(model.index(0, 0, QModelIndex()), QgsDatabaseSchemaModel.RoleEmpty)) self.assertFalse( model.data( model.index(schemas.index('qgis_test'), 0, QModelIndex()), QgsDatabaseSchemaModel.RoleEmpty)) conn.createSchema('myNewSchema2') conn.createSchema('myNewSchema3') model.refresh() self.assertEqual(model.rowCount(), old_count + 4) schemas = [ model.data(model.index(r, 0, QModelIndex()), Qt.DisplayRole) for r in range(model.rowCount()) ] self.assertIn('public', schemas) self.assertIn('CamelCaseSchema', schemas) self.assertIn('qgis_test', schemas) self.assertIn('myNewSchema', schemas) self.assertIn('myNewSchema2', schemas) self.assertIn('myNewSchema3', schemas) self.assertFalse( model.data(model.index(0, 0, QModelIndex()), Qt.DisplayRole)) self.assertTrue( model.data(model.index(0, 0, QModelIndex()), QgsDatabaseSchemaModel.RoleEmpty)) self.assertFalse( model.data( model.index(schemas.index('qgis_test'), 0, QModelIndex()), QgsDatabaseSchemaModel.RoleEmpty)) conn.createSchema('myNewSchema4') conn.dropSchema('myNewSchema2') conn.dropSchema('myNewSchema') model.refresh() self.assertEqual(model.rowCount(), old_count + 3) schemas = [ model.data(model.index(r, 0, QModelIndex()), Qt.DisplayRole) for r in range(model.rowCount()) ] self.assertIn('public', schemas) self.assertIn('CamelCaseSchema', schemas) self.assertIn('qgis_test', schemas) self.assertNotIn('myNewSchema', schemas) self.assertNotIn('myNewSchema2', schemas) self.assertIn('myNewSchema3', schemas) self.assertIn('myNewSchema4', schemas) self.assertFalse( model.data(model.index(0, 0, QModelIndex()), Qt.DisplayRole)) self.assertTrue( model.data(model.index(0, 0, QModelIndex()), QgsDatabaseSchemaModel.RoleEmpty)) self.assertFalse( model.data( model.index(schemas.index('qgis_test'), 0, QModelIndex()), QgsDatabaseSchemaModel.RoleEmpty)) conn.dropSchema('myNewSchema3') conn.dropSchema('myNewSchema4') model.refresh() self.assertEqual(model.rowCount(), old_count + 1) schemas = [ model.data(model.index(r, 0, QModelIndex()), Qt.DisplayRole) for r in range(model.rowCount()) ] self.assertIn('public', schemas) self.assertIn('CamelCaseSchema', schemas) self.assertIn('qgis_test', schemas) self.assertNotIn('myNewSchema3', schemas) self.assertNotIn('myNewSchema4', schemas) self.assertFalse( model.data(model.index(0, 0, QModelIndex()), Qt.DisplayRole)) self.assertTrue( model.data(model.index(0, 0, QModelIndex()), QgsDatabaseSchemaModel.RoleEmpty)) self.assertFalse( model.data( model.index(schemas.index('qgis_test'), 0, QModelIndex()), QgsDatabaseSchemaModel.RoleEmpty)) model.setAllowEmptySchema(False) self.assertEqual(model.rowCount(), old_count) self.assertTrue( model.data(model.index(0, 0, QModelIndex()), Qt.DisplayRole)) self.assertFalse( model.data(model.index(0, 0, QModelIndex()), QgsDatabaseSchemaModel.RoleEmpty))
def test_create_vector_layer(self): """Test query layers""" md = QgsProviderRegistry.instance().providerMetadata('postgres') conn = md.createConnection(self.uri, {}) sql = """ DROP TABLE IF EXISTS qgis_test.query_layer1; CREATE TABLE qgis_test.query_layer1 ( id SERIAL PRIMARY KEY, geom geometry(POINT,4326) ); INSERT INTO qgis_test.query_layer1 (id, geom) VALUES (221, ST_GeomFromText('point(9 45)', 4326)); INSERT INTO qgis_test.query_layer1 (id, geom) VALUES (201, ST_GeomFromText('point(9.5 45.5)', 4326)); """ conn.executeSql(sql) options = QgsAbstractDatabaseProviderConnection.SqlVectorLayerOptions() options.sql = 'SELECT id, geom FROM qgis_test.query_layer1 WHERE id < 200 LIMIT 2' options.primaryKeyColumns = ['id'] options.geometryColumn = 'geom' vl = conn.createSqlVectorLayer(options) self.assertTrue(vl.isValid()) self.assertTrue(vl.isSqlQuery()) # Test flags self.assertTrue(vl.vectorLayerTypeFlags() & Qgis.VectorLayerTypeFlag.SqlQuery) self.assertEqual(vl.geometryType(), QgsWkbTypes.PointGeometry) features = [f for f in vl.getFeatures()] self.assertEqual(len(features), 0) options.sql = 'SELECT id, geom FROM qgis_test.query_layer1 WHERE id > 200 LIMIT 2' vl = conn.createSqlVectorLayer(options) self.assertTrue(vl.isValid()) self.assertTrue(vl.isSqlQuery()) self.assertEqual(vl.geometryType(), QgsWkbTypes.PointGeometry) features = [f for f in vl.getFeatures()] self.assertEqual(len(features), 2) options.sql = 'SELECT id, geom FROM qgis_test.query_layer1 WHERE id > 210 LIMIT 2' vl = conn.createSqlVectorLayer(options) self.assertTrue(vl.isValid()) self.assertTrue(vl.isSqlQuery()) self.assertEqual(vl.geometryType(), QgsWkbTypes.PointGeometry) features = [f for f in vl.getFeatures()] self.assertEqual(len(features), 1) options.sql = 'SELECT id, geom FROM qgis_test.query_layer1 LIMIT 2' options.filter = 'id > 210' vl = conn.createSqlVectorLayer(options) self.assertTrue(vl.isValid()) self.assertTrue(vl.isSqlQuery()) self.assertEqual(vl.geometryType(), QgsWkbTypes.PointGeometry) features = [f for f in vl.getFeatures()] self.assertEqual(len(features), 1) # Wrong calls options.primaryKeyColumns = ['DOES_NOT_EXIST'] vl = conn.createSqlVectorLayer(options) self.assertFalse(vl.isValid()) self.assertFalse(vl.vectorLayerTypeFlags() & Qgis.VectorLayerTypeFlag.SqlQuery) self.assertFalse(vl.isSqlQuery()) options.primaryKeyColumns = ['id'] options.geometryColumn = 'DOES_NOT_EXIST' vl = conn.createSqlVectorLayer(options) self.assertFalse(vl.isValid()) self.assertFalse(vl.isSqlQuery()) options.sql = 'SELECT id, geom FROM qgis_test.query_layer1 WHERE id > 210 LIMIT 2' options.primaryKeyColumns = [] options.geometryColumn = '' vl = conn.createSqlVectorLayer(options) self.assertTrue(vl.isValid()) self.assertTrue(vl.isSqlQuery()) features = [f for f in vl.getFeatures()] self.assertEqual(len(features), 1) # No geometry and no PK, aspatial layer options.sql = 'SELECT id, geom FROM qgis_test.query_layer1 WHERE id > 210 LIMIT 2' options.primaryKeyColumns = [] options.geometryColumn = '' vl = conn.createSqlVectorLayer(options) self.assertTrue(vl.isValid()) self.assertTrue(vl.isSqlQuery()) self.assertNotEqual(vl.geometryType(), QgsWkbTypes.PointGeometry) features = [f for f in vl.getFeatures()] self.assertEqual(len(features), 1) # Composite keys sql = """ DROP TABLE IF EXISTS qgis_test.query_layer2; CREATE TABLE qgis_test.query_layer2 ( id SERIAL, id2 SERIAL, geom geometry(POINT,4326), PRIMARY KEY(id, id2) ); INSERT INTO qgis_test.query_layer2 (id, id2, geom) VALUES (101, 101, ST_GeomFromText('point(9 45)', 4326)); INSERT INTO qgis_test.query_layer2 (id, id2, geom) VALUES (201, 201, ST_GeomFromText('point(9.5 45.5)', 4326)); """ conn.executeSql(sql) options = QgsAbstractDatabaseProviderConnection.SqlVectorLayerOptions() options.sql = 'SELECT id, id2, geom FROM qgis_test.query_layer2 ORDER BY id ASC LIMIT 1' options.primaryKeyColumns = ['id', 'id2'] options.geometryColumn = 'geom' vl = conn.createSqlVectorLayer(options) self.assertTrue(vl.isValid()) self.assertTrue(vl.isSqlQuery()) # Test flags self.assertTrue(vl.vectorLayerTypeFlags() & Qgis.VectorLayerTypeFlag.SqlQuery) self.assertEqual(vl.geometryType(), QgsWkbTypes.PointGeometry) features = [f for f in vl.getFeatures()] self.assertEqual(len(features), 1) # No PKs options.primaryKeyColumns = [] options.geometryColumn = 'geom' vl = conn.createSqlVectorLayer(options) self.assertTrue(vl.isSqlQuery()) self.assertTrue(vl.isValid()) self.assertEqual(vl.geometryType(), QgsWkbTypes.PointGeometry) features = [f for f in vl.getFeatures()] self.assertEqual(len(features), 1)
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)()