def get_capabilities(self, params: Dict[str, str], response: QgsServerResponse, project: QgsProject) -> None: """ Get cadastral capabilities based on config stored as project custom variables """ # get project custom variables variables = project.customVariables() if 'cadastre_parcelle_layer_id' not in variables or \ 'cadastre_parcelle_unique_field' not in variables: raise CadastreError(400, "Project has no cadastral capabilities") parcelle_layer_id = variables['cadastre_parcelle_layer_id'] parcelle_layer_unique_field = variables['cadastre_parcelle_unique_field'] player = project.mapLayer(parcelle_layer_id) if not player: raise CadastreError(404, "Parcel layer not available") capabilities = { 'parcelle': { 'id': player.id(), 'name': player.name(), 'title': player.title(), 'shortName': player.shortName(), 'unique_field': parcelle_layer_unique_field } } if 'cadastre_section_layer_id' in variables: section_layer_id = variables['cadastre_section_layer_id'] slayer = project.mapLayer(section_layer_id) if slayer: capabilities['section'] = { 'id': slayer.id(), 'name': slayer.name(), 'title': slayer.title(), 'shortName': slayer.shortName() } if 'cadastre_section_unique_field' in variables: capabilities['section']['unique_field'] = variables['cadastre_section_unique_field'] if 'cadastre_commune_layer_id' in variables: commune_layer_id = variables['cadastre_commune_layer_id'] slayer = project.mapLayer(commune_layer_id) if slayer: capabilities['commune'] = { 'id': slayer.id(), 'name': slayer.name(), 'title': slayer.title(), 'shortName': slayer.shortName() } if 'cadastre_commune_unique_field' in variables: capabilities['commune']['unique_field'] = variables['cadastre_commune_unique_field'] write_json_response({ 'status': 'success', 'message': 'Capabilities', 'data': capabilities }, response)
def test_style_delete(self): """Test delete style""" self.assertTrue(self.qdjango_layer.delete_style('style2')) self.assertFalse(self.qdjango_layer.delete_style('style1')) # Verify p = QgsProject() p.read(self.qdjango_project.qgis_project.fileName()) l = p.mapLayer(self.qdjango_layer.qgis_layer.id()) self.assertTrue(l.isValid()) sm = l.styleManager() self.assertEqual(sm.styles(), ['style1']) del(sm) del(p)
def testEmbeddedGroup(self): testdata_path = unitTestDataPath('embedded_groups') + '/' prj_path = os.path.join(testdata_path, "project2.qgs") prj = QgsProject() prj.read(prj_path) layer_tree_group = prj.layerTreeRoot() self.assertEqual(len(layer_tree_group.findLayerIds()), 2) for layer_id in layer_tree_group.findLayerIds(): name = prj.mapLayer(layer_id).name() self.assertTrue(name in ['polys', 'lines']) if name == 'polys': self.assertTrue(layer_tree_group.findLayer(layer_id).itemVisibilityChecked()) elif name == 'lines': self.assertFalse(layer_tree_group.findLayer(layer_id).itemVisibilityChecked())
def testEmbeddedGroup(self): testdata_path = unitTestDataPath('embedded_groups') + '/' prj_path = os.path.join(testdata_path, "project2.qgs") prj = QgsProject() prj.read(prj_path) layer_tree_group = prj.layerTreeRoot() layers_ids = layer_tree_group.findLayerIds() layers_names = [] for layer_id in layers_ids: name = prj.mapLayer(layer_id).name() layers_names.append(name) expected = ['polys', 'lines'] self.assertEqual(sorted(layers_names), sorted(expected))
def testEmbeddedGroup(self): testdata_path = unitTestDataPath('embedded_groups') + '/' prj_path = os.path.join(testdata_path, "project2.qgs") prj = QgsProject() prj.read(prj_path) layer_tree_group = prj.layerTreeRoot() self.assertEqual(len(layer_tree_group.findLayerIds()), 2) for layer_id in layer_tree_group.findLayerIds(): name = prj.mapLayer(layer_id).name() self.assertTrue(name in ['polys', 'lines']) if name == 'polys': self.assertTrue( layer_tree_group.findLayer( layer_id).itemVisibilityChecked()) elif name == 'lines': self.assertFalse( layer_tree_group.findLayer( layer_id).itemVisibilityChecked())
def actions(nameAction, params): def _getRasterLayer(feature): pathfile = feature.attribute('pathfile') info = QFileInfo(pathfile) if not info.exists(): return { 'isOk': False, 'message': "Raster file '{}' not found".format(pathfile) } sources = dict([(layer.source(), layer) for layer in project.mapLayers().values()]) if pathfile in sources.keys(): layer = sources[pathfile] needAdd = False else: name = QFileInfo(pathfile).completeBaseName() layer = QgsRasterLayer(pathfile, name) needAdd = True return {'isOk': True, 'layer': layer, 'needAdd': needAdd} def _addRaster(layer): project.addMapLayer(layer) ltl = project.layerTreeRoot().findLayer(layer) ltl.setItemVisibilityChecked(True) ltl.setExpanded(False) # Actions functions def flash(): m = MapCanvasFeature() m.flash(layer, feature) return {'isOk': True} def zoom(): m = MapCanvasFeature() m.zoom(layer, feature) return {'isOk': True} def show_hideImage(): r = _getRasterLayer(feature) if not r['isOk']: return r if r['needAdd']: _addRaster(r['layer']) else: ltl = project.layerTreeRoot().findLayer(r['layer']) ltl.setItemVisibilityChecked(not ltl.isVisible()) return {'isOk': True} def setCurrent(): r = _getRasterLayer(feature) if not r['isOk']: return r if r['needAdd']: _addRaster(r['layer']) else: QgsUtils.iface.setActiveLayer(r['layer']) return {'isOk': True} def setZeroTransparency(): def existsCatalog(raster): vfilter = '"pathfile" = \'{}\''.format(raster.source()) viter = layer.getFeatures(vfilter) feat = QgsFeature() vreturn = viter.nextFeature(feat) del feat return vreturn maplayers = map(lambda ltl: ltl.layer(), StyleOutputFootPrint.root.findLayers()) rasters = filter( lambda layer: layer.type() == QgsMapLayer.RasterLayer, maplayers) for raster in rasters: if existsCatalog(raster): RasterTransparency.setTransparency(raster) return {'isOk': True} actionsFunc = { 'flash': flash, 'zoom': zoom, 'show_hideImage': show_hideImage, 'setCurrent': setCurrent, 'setZeroTransparency': setZeroTransparency } if not nameAction in actionsFunc.keys(): return { 'isOk': False, 'message': "Missing action '{}'".format(nameAction) } project = QgsProject().instance() layer = project.mapLayer(params['layer_id']) if 'feature_id' in params: feature = layer.getFeature(params['feature_id']) return actionsFunc[nameAction]()
def onItemChanged(self, layerType, item): """ Get data when table item content has changed And store it for future use """ # Get table if layerType == 'vector': table = self.dlg.vectorLayers elif layerType == 'raster': table = self.dlg.rasterLayers else: return # Get row and column row = item.row() col = item.column() # Unselect row and item table.clearSelection() # Get layer layerId = table.item(row, 0).data(Qt.EditRole) lr = QgsProject().instance() layer = lr.mapLayer(layerId) if not layer: return # Get changed property prop = self.layersAttributes[layerType][col]['key'] data = table.item(row, col).data(Qt.EditRole) # test if new datasource prop is valid otherwise restore previous data if prop == 'source|uri' and not self.newDatasourceIsValid(layer, data): table.itemChanged.disconnect() item.setData(Qt.EditRole, self.getLayerProperty(layer, 'source|uri')) slot = partial(self.onItemChanged, layerType) table.itemChanged.connect(slot) return # Check encoding and revert if problem if prop == 'encoding' and data not in layer.dataProvider().availableEncodings(): table.itemChanged.disconnect() item.setData(Qt.EditRole, self.getLayerProperty(layer, 'encoding')) slot = partial(self.onItemChanged, layerType) table.itemChanged.connect(slot) return # Check shortname and modify to remove unwanted chars if prop == 'shortname': table.itemChanged.disconnect() newshortname = re.sub('[^A-Za-z0-9\.-]', '_', data) item.setData(Qt.EditRole, newshortname) slot = partial(self.onItemChanged, layerType) table.itemChanged.connect(slot) # Store data in global property self.layerBoardChangedData[layerType][layerId][prop] = data # Change cell background table.item(row, col).setBackground(Qt.yellow)
def populateLayerTable(self, layerType): """ Fill the table for a given layer type """ # Get parameters for the widget lt = self.layersTable[layerType] table = lt['tableWidget'] # Reset layerBoardChangedData self.layerBoardChangedData[layerType] = {} # disconnect itemChanged signal try: table.itemChanged.disconnect() except Exception: pass attributes = self.layersTable['generic']['attributes'] + lt['attributes'] self.layersAttributes[layerType] = attributes self.layerBoardData[layerType] = [] headerData = [a['key'] for a in attributes] self.layerBoardData[layerType].append(headerData) # empty previous content for row in range(table.rowCount()): table.removeRow(row) table.setRowCount(0) table.setColumnCount(0) # create columns and header row columns = [a['key'] for a in attributes] columnsLabels = [a['label'] for a in attributes] colCount = len(columns) table.setColumnCount(colCount) table.setHorizontalHeaderLabels(tuple(columnsLabels)) # load content from project layers lr = QgsProject().instance() for lid in lr.mapLayers(): layer = lr.mapLayer(lid) if layerType == 'vector' and layer.type() != QgsMapLayer.VectorLayer: continue if layerType == 'raster' and layer.type() != QgsMapLayer.RasterLayer: continue # Add layer in the layerBoardChangedData self.layerBoardChangedData[layerType][lid] = {} lineData = [] # Set row and column count twRowCount = table.rowCount() # add a new line table.setRowCount(twRowCount + 1) table.setColumnCount(colCount) i = 0 # get information for attr in attributes: newItem = QTableWidgetItem() newItem.setToolTip(layer.name()) if layerType == 'vector' and not layer.isSpatial() and attr.get('spatial_only'): newItem.setFlags(Qt.NoItemFlags) # Is editable or not elif attr.get('editable'): newItem.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEditable | Qt.ItemIsEnabled) else: newItem.setFlags(Qt.ItemIsSelectable) # Item value if layerType == 'vector' and not layer.isSpatial() and attr.get('spatial_only'): value = None else: value = self.getLayerProperty(layer, attr['key']) newItem.setData(Qt.EditRole, value) # Add cell data to lineData # encode it in the file system encoding, only if needed # TODO DISABLED due to migration to Python 3, related to CSV export # if hasattr(value, 'encode'): # value = value.encode(sys.getfilesystemencoding()) lineData.append(value) if attr['key'] == 'name': icon = QgsMapLayerModel.iconForLayer(layer) newItem.setIcon(icon) # Add item table.setItem(twRowCount, i, newItem) i += 1 # Add data to layerBoardData self.layerBoardData[layerType].append(lineData) # Launch slot on item changed slot slot = partial(self.onItemChanged, layerType) table.itemChanged.connect(slot)
def test_model_methods(self): """Test model style manager CRUD methods""" self.assertEqual(self.qdjango_layer.styles, [ { 'name': 'style1', 'current': False }, { 'name': 'style2', 'current': True }, ]) self.assertFalse(self.qdjango_project.is_dirty) self.assertFalse( self.qdjango_layer.set_current_style('style1234567890')) self.assertTrue(self.qdjango_layer.set_current_style('style1')) self.assertTrue(self.qdjango_project.is_dirty) self.assertEqual(self.qdjango_layer.styles, [ { 'name': 'style1', 'current': True }, { 'name': 'style2', 'current': False }, ]) # Verify the project was written p = QgsProject() p.read(self.qdjango_project.qgis_project.fileName()) l = p.mapLayer(self.qdjango_layer.qgis_layer.id()) self.assertTrue(l.isValid()) sm = l.styleManager() self.assertEqual(sm.currentStyle(), 'style1') del(sm) del(p) # Test rename self.assertFalse(self.qdjango_layer.rename_style( 'style1234567890', 'new_name')) self.assertFalse(self.qdjango_layer.rename_style('style2', 'style1')) self.assertTrue(self.qdjango_layer.rename_style('style2', 'new_name')) self.assertTrue(self.qdjango_layer.rename_style('style1', 'new_name1')) self.assertTrue(self.qdjango_layer.rename_style('new_name1', 'style1')) # Verify the project was written p = QgsProject() p.read(self.qdjango_project.qgis_project.fileName()) l = p.mapLayer(self.qdjango_layer.qgis_layer.id()) self.assertTrue(l.isValid()) sm = l.styleManager() self.assertEqual(sm.styles(), ['new_name', 'style1']) del(sm) del(p) # Test remove/delete self.assertFalse(self.qdjango_layer.delete_style('style1234567890')) self.assertTrue(self.qdjango_layer.delete_style('style1')) self.assertFalse(self.qdjango_layer.delete_style('new_name')) assert self.qdjango_layer.rename_style('new_name', 'style1') # Verify the project was written p = QgsProject() p.read(self.qdjango_project.qgis_project.fileName()) l = p.mapLayer(self.qdjango_layer.qgis_layer.id()) self.assertTrue(l.isValid()) sm = l.styleManager() self.assertEqual(sm.styles(), ['style1']) del(sm) del(p) # Test add new style with open(os.path.join( CURRENT_PATH + TEST_BASE_PATH, 'multiple_styles_manager_test.qml'), 'r') as f: qml = f.read() self.assertFalse(self.qdjango_layer.add_style('style1', qml)) self.assertTrue(self.qdjango_layer.add_style( 'My new fancy èé style', qml)) # Verify the project was written p = QgsProject() p.read(self.qdjango_project.qgis_project.fileName()) l = p.mapLayer(self.qdjango_layer.qgis_layer.id()) self.assertTrue(l.isValid()) sm = l.styleManager() self.assertEqual(sm.styles(), ['My new fancy èé style', 'style1']) del(sm) del(p) # Test invalid QML self.assertFalse(self.qdjango_layer.add_style( 'My invalid style', '<xxxx>this is not a valid style</xxxx>')) # Restore the project and check the dirt flag project_file = File(open(self.project_path, 'r')) project = QgisProject(project_file) project.instance = self.qdjango_project project.title = 'Test qdjango postgres multiple styles manager project' project.group = self.project_group project.save() self.assertFalse(self.qdjango_project.is_dirty)
def test_layer_info(self): p = QgsProject() p.read(list(projects().values())[1]) info = layer_info( p.mapLayer('points_842425df_7f45_4091_a6c9_086e1dc1edd1')) self.assertEqual(info['name'], 'points') self.assertEqual(info['id'], 'points_842425df_7f45_4091_a6c9_086e1dc1edd1') self.assertEqual( info['metadata']['categories'], ['Geoscientific Information', 'Imagery Base Maps Earth Cover']) self.assertEqual( info['metadata']['contacts'][0], { 'name': 'Layer Metadata Contact Name', 'role': 'distributor', 'email': 'Layer Metadata Contact Email', 'fax': 'Layer Metadata Contact Fax', 'voice': 'Layer Metadata Contact Voice', 'organization': 'Layer Metadata Contact Organization', 'position': 'Layer Metadata Contact Position', 'addresses': [{ 'address': 'street 1', 'city': 'Milan', 'country': 'Italy', 'postalCode': '10021', 'type': 'postal', 'administrativeArea': 'Lombardy' }] }) self.assertEqual( info['fields'], { 'fid': { 'type': 'Integer64', 'label': 'fid', 'precision': 0, 'length': 0, 'not_null': True, 'unique': True, 'has_expression': False, 'default': 'Autogenerate', 'expression': '', 'editable': False }, 'name': { 'type': 'String', 'label': 'name', 'precision': 0, 'length': 0, 'not_null': False, 'unique': False, 'has_expression': False, 'default': '', 'expression': '', 'editable': True } })