def styles_to_attributes_finished(self, input_layer: QgsVectorLayer, context: QgsProcessingContext, id: uuid.UUID, succesful: bool, results: Dict[str, any]) -> None: row = self.layer_rows[id] if succesful: legends = [Legend.from_dict(legend) for legend in results["OUTPUT_LEGEND"].values()] LOGGER.info(tr('Exporting styles for {} finished successfully', input_layer.name())) output_layer: QgsVectorLayer = context.takeResultLayer(results['OUTPUT']) if output_layer and output_layer.isValid(): with tempfile.TemporaryDirectory(dir=resources_path()) as tmpdirname: style_file = os.path.join(tmpdirname, 'style.qml') msg, succeeded = input_layer.saveNamedStyle(style_file) if succeeded: output_layer.loadNamedStyle(style_file) else: LOGGER.error(tr('Could not load style'), extra=bar_msg(msg)) QgsProject.instance().addMapLayer(output_layer) row['styled_layer'] = StyledLayer(row['layer_name'], output_layer.id(), legends) row['finished'] = True else: feedback: LoggerProcessingFeedBack = row['feedback'] error_msg = feedback.last_report_error LOGGER.error(tr('Exporting styles for {} finished with errors', input_layer.name()), extra=bar_msg(details=tr(f'Details: {error_msg}. Check log file for more details'))) self._enable_ui()
def post_process_value_relation_fields(self, e_layer: QgsVectorLayer, o_field: QgsField): project = QgsProject.instance() o_ews = o_field.editorWidgetSetup() o_widget_config = o_ews.config() o_referenced_layer_id = o_widget_config["Layer"] if o_referenced_layer_id not in self.__layer_data_by_id: e_referenced_layer = QgsValueRelationFieldFormatter.resolveLayer( o_widget_config, project) if e_referenced_layer: o_referenced_layer_id = e_referenced_layer.customProperty( "remoteLayerId") # yet another check whether value relation resolver succeeded if o_referenced_layer_id not in self.__layer_data_by_id: self.warning.emit( self.tr("Bad attribute form configuration"), self. tr('Field "{}" in layer "{}" has no configured layer in the value relation widget.' ).format(o_field.name(), e_layer.name()), ) return e_referenced_layer_id = None for e_layer in project.mapLayers().values(): o_layer_data = self.__layer_data_by_id[o_referenced_layer_id] if e_layer.customProperty( "remoteSource") == o_layer_data["source"]: # First try strict matching: the offline layer should have a "remoteSource" property e_referenced_layer_id = e_layer.id() break elif e_layer.name() == o_layer_data["name"]: # If that did not work, go with loose matching e_referenced_layer_id = e_layer.id() break if not e_referenced_layer_id: self.warning.emit( self.tr("Bad attribute form configuration"), self. tr('Field "{}" in layer "{}" has no configured layer in the value relation widget.' ).format(o_field.name(), e_layer.name()), ) return e_widget_config = o_widget_config e_widget_config["Layer"] = e_referenced_layer_id e_layer.setEditorWidgetSetup( e_layer.fields().indexOf(o_field.name()), QgsEditorWidgetSetup(o_ews.type(), e_widget_config), )
def get_sql_layer(self, table, geom, pk, uri, feedback): sql_file = resources_path('sql', 'export', 'export_{}.sql'.format(table)) other = False if not os.path.exists(sql_file): sql_file = resources_path('sql', 'export', 'export_table.sql') other = True with open(sql_file, "r") as f: sql = f.read() if len(sql.strip()) == 0: feedback.reportError("Fichier SQL vide") return None sql = str(sql) if other: sql += table uri.setSchema('') uri.setTable('(' + sql + ')') uri.setGeometryColumn(geom) uri.setKeyColumn(pk) layer = QgsVectorLayer(uri.uri(False), table, "postgres") if not layer.isValid(): feedback.reportError("Layer not valid " + layer.name()) return None return layer
def from_line_layer(layer: QgsVectorLayer): reach = Reach( my_id=0, name=layer.name(), crs_id=layer.crs().authid(), ) section = None for f in layer.getFeatures(): section = Section( my_id=f.attribute("sec_id"), name=f.attribute("sec_name"), pk=f.attribute("abs_long"), ) # Take only the first parts (QgsMultiLineString => QgsLineString) line = next(f.geometry().constParts()).clone() section.set_points([ Point( x=p[0].x(), y=p[0].y(), z=p[1], d=p[2], ) for p in zip( line.points(), f.attribute("zfond").split(","), f.attribute("abs_lat").split(","), ) ]) reach.add_section(section) return reach
def from_point_layer(layer: QgsVectorLayer): reach = Reach( my_id=0, name=layer.name(), crs_id=layer.crs().authid(), ) section = None points = [] for f in layer.getFeatures(): if section is not None: if f.attribute("sec_id") != section.id: reach.add_section(section.set_points(points)) section = None points = [] if section is None: section = Section( my_id=f.attribute("sec_id"), pk=f.attribute("abs_long"), name=f.attribute("sec_name"), ) points.append( Point( x=f.geometry().constGet().x(), y=f.geometry().constGet().y(), z=f.attribute("zfond"), d=f.attribute("abs_lat"), )) if section is not None: reach.add_section(section.set_points(points)) return reach
def export_layer_as(layer, layer_name, layer_format, to_dir): """Convertir un fichier sph en format donné :param layer: la couche :type layer: str ou QgsVectorLayer :param layer_name nom du fichier en sorti :type layer_name: str :param layer_format: le format final :type layer_format: str :param to_dir: le nouveau chemin :type to_dir: str """ if layer_name is None: if isinstance(layer, str): layer_name = basename(layer).replace(".shp", "") layer = QgsVectorLayer(layer, layer_name, "ogr") else: layer_name = layer.name() layer_path = join(to_dir, layer_name + '{}'.format(extension[layer_format])) options = QgsVectorFileWriter.SaveVectorOptions() options.driverName = layer_format options.layerName = layer_name options.fileEncoding = 'utf-8' QgsVectorFileWriter.writeAsVectorFormat(layer, layer_path, options) QgsMessageLog.logMessage( "Les fichiers {} sont bien enregistrés dans {}".format( layer_format, to_dir), 'UnderMap', Qgis.Info)
def test_add_layer_to_registry(self): layer_name = layer_interaction.biuniquify_layer_name('this_layer_was_added_for_testing_purpose') layer = QgsVectorLayer('Polygon?crs=EPSG:3857', layer_name, 'memory', False) number_of_layers = len(QgsMapLayerRegistry.instance().mapLayers()) layer_interaction.add_layer_to_registry(layer) self.layer_list.append(layer.name()) map_layers = QgsMapLayerRegistry.instance().mapLayers() actual = len(map_layers) expected = number_of_layers + 1 message = 'An error occured when adding a layer to the MapLayerRegistry. {} is not {}!'.format(actual, expected) self.assertEqual(actual, expected, message) layer_added = False for layer_key in map_layers: if map_layers[layer_key].name() == layer_name: layer_added = True break self.assertTrue(layer_added, 'An error occured when adding a layer to the MapLayerRegistry.') number_of_layers = len(map_layers) layer_interaction.add_layer_to_registry(None) self.assertEqual(len(QgsMapLayerRegistry.instance().mapLayers()), number_of_layers, 'An error occured when trying to add a none-type-layer to the MapLayerRegistry. The number of layers should not increase.')
def duplicateLayer(self, currentLayer: QgsVectorLayer, suffix: str, scoreName: str): """Duplicate original Layer. :param currentLayer QgsVectorLayer:The layer will be duplicated :param suffix str: Suffix name :param scoreName str: Attribute name of score in attribute table """ # print(currentLayer) # print(suffix) # print(scoreName) layername = str(currentLayer.name()) + "_" + str(suffix) layer = QgsVectorLayer("Polygon?crs=ESPG:4326", layername, 'memory') # print("layer created") layer.setCrs(currentLayer.sourceCrs()) # print("crs set") layer.dataProvider().addAttributes( currentLayer.dataProvider().fields().toList()) # print("add field") # adding score attributes info layer.dataProvider().addAttributes([ QgsField(scoreName, QVariant.Double), QgsField('id', QVariant.Int), QgsField('match', QVariant.Int) ]) # print("field updated") # update the fields layer.updateFields() # print("updated fields") layer.dataProvider().addFeatures(currentLayer.getFeatures()) # print(layer.featureCount()) # print("features updated") return layer
def getSavePaths(fileName: str, domainLayer: QgsVectorLayer, typeDir: str): """Description: Processes a raster image into a vector polygon ocean/land mask. Get a standardized vector name from a Landsat raster file name. Input: str fileName - Landsat raster file name. str glacierName - Root vector file name. str typeDir - name of the type subdirectory. Output: str path - file save paths. """ date = fileName.split('_')[2] year = date.split('-')[0] # if (rootGroup.parent().name().startswith('2') or rootGroup.parent().name().startswith('1')): # rootGroup = rootGroup.parent() path = resolve('CalvingFronts') if (not os.path.exists(path)): os.mkdir(path) path = os.path.join(path, typeDir) if (not os.path.exists(path)): os.mkdir(path) path = os.path.join(path, domainLayer.name()) if (not os.path.exists(path)): os.mkdir(path) path = os.path.join(path, year) if (not os.path.exists(path)): os.mkdir(path) return path
def test_add_layer_to_registry(self): layer_name = layer_interaction.biuniquify_layer_name( 'this_layer_was_added_for_testing_purpose') layer = QgsVectorLayer('Polygon?crs=EPSG:3857', layer_name, 'memory', False) number_of_layers = len(QgsMapLayerRegistry.instance().mapLayers()) layer_interaction.add_layer_to_registry(layer) self.layer_list.append(layer.name()) map_layers = QgsMapLayerRegistry.instance().mapLayers() actual = len(map_layers) expected = number_of_layers + 1 message = 'An error occured when adding a layer to the MapLayerRegistry. {} is not {}!'.format( actual, expected) self.assertEqual(actual, expected, message) layer_added = False for layer_key in map_layers: if map_layers[layer_key].name() == layer_name: layer_added = True break self.assertTrue( layer_added, 'An error occured when adding a layer to the MapLayerRegistry.') number_of_layers = len(map_layers) layer_interaction.add_layer_to_registry(None) self.assertEqual( len(QgsMapLayerRegistry.instance().mapLayers()), number_of_layers, 'An error occured when trying to add a none-type-layer to the MapLayerRegistry. The number of layers should not increase.' )
def _write_gpkg(self, csv_files, output_file): layer_names = [] options = QgsVectorFileWriter.SaveVectorOptions() options.driverName = 'GPKG' for csv in csv_files: # build URI uri = 'file:///{}?delimiter=,'.format(csv) csv_name = Path(Path(csv).name).stem if csv_name == 'stops': uri += '&xField=stop_lon&yField=stop_lat&crs=epsg:4326' elif csv_name == 'shapes': uri += '&xField=shape_pt_lon&yField=shape_pt_lat&crs=epsg:4326' csv_name='shapes_point' # create CSV-based layer layer_names.append(csv_name) layer = QgsVectorLayer(uri, csv_name, 'delimitedtext') # save layer to GPKG options.layerName = layer.name().replace(' ', '_') code, msg = QgsVectorFileWriter.writeAsVectorFormat(layer, output_file, options) # if code != QgsVectorFileWriter.NoError: # raise GtfsError("Unable to create output GPKG file {} (details: {}/{})".format(output_file, code, msg)) # append layers into single GPKG options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteLayer # Return all layers from geopackage return layer_names
def from_qgs_layer(layer: QgsVectorLayer, parent_layer: Optional['LayerWrapper'] = None, foreign_field: Optional[FieldWrapper] = None) -> 'LayerWrapper': pk_idxs = layer.primaryKeyAttributes() if len(pk_idxs): pk_field = layer.fields().toList()[pk_idxs[0]].name() else: pk_field = None return LayerWrapper(layer.name(), pk_field, parent_layer=parent_layer, foreign_field=foreign_field)
def load_layers( self, #load data to project (for console runs) rfp_l, finv_fp, providerLib='ogr'): """ special input loader for standalone runs Im assuming for the plugin these layers will be loaded already""" log = self.logger.getChild('load_layers') #====================================================================== # load rasters #====================================================================== raster_d = dict() for fp in rfp_l: rlayer = self.load_rlay(fp) #add it in basefn = os.path.splitext(os.path.split(fp)[1])[0] raster_d[basefn] = rlayer #====================================================================== # load finv vector layer #====================================================================== fp = finv_fp assert os.path.exists(fp) basefn = os.path.splitext(os.path.split(fp)[1])[0] vlay_raw = QgsVectorLayer(fp, basefn, providerLib) # checks if not isinstance(vlay_raw, QgsVectorLayer): raise IOError #check if this is valid if not vlay_raw.isValid(): raise Error( 'loaded vlay \'%s\' is not valid. \n \n did you initilize?' % vlay_raw.name()) #check if it has geometry if vlay_raw.wkbType() == 100: raise Error('loaded vlay has NoGeometry') self.mstore.addMapLayer(vlay_raw) vlay = vlay_raw dp = vlay.dataProvider() log.info( 'loaded vlay \'%s\' as \'%s\' %s geo with %i feats from file: \n %s' % (vlay.name(), dp.storageType(), QgsWkbTypes().displayString( vlay.wkbType()), dp.featureCount(), fp)) #====================================================================== # wrap #====================================================================== return list(raster_d.values()), vlay
def save_track(self): """ Save the track to disk """ layer_name, selected_filter = QFileDialog.getSaveFileName(None, 'Save Track', "", 'Shapefile (*.shp);;KML (*.kml);;GPX (*.gpx)') if layer_name != '': if self.geom_type == QgsWkbTypes.PointGeometry: geometric_object = "MultiPoint?crs=epsg:4326" else: geometric_object = "LineString?crs=epsg:4326" layer = QgsVectorLayer( geometric_object, layer_name, "memory") feature = QgsFeature() feature.setGeometry(self.band.asGeometry()) layer.dataProvider().addFeatures([feature]) if selected_filter == "Shapefile (*.shp)": if not layer_name.endswith('.shp'): layer_name = layer_name + '.shp' ret = QgsVectorFileWriter.writeAsVectorFormat(layer, layer_name, "utf-8", QgsCoordinateReferenceSystem(4326, QgsCoordinateReferenceSystem.EpsgCrsId), "ESRI Shapefile") if ret == QgsVectorFileWriter.NoError: logger.info(layer.name() + " saved to " + layer_name) elif selected_filter == "KML (*.kml)": if not layer_name.endswith('.kml'): layer_name = layer_name + '.kml' QgsVectorFileWriter.writeAsVectorFormat(layer, layer_name, "utf-8", QgsCoordinateReferenceSystem(4326, QgsCoordinateReferenceSystem.EpsgCrsId), "KML") elif selected_filter == "GPX (*.gpx)": if not layer_name.endswith('.gpx'): layer_name = layer_name + '.gpx' ds_options = list() ds_options.append("GPX_USE_EXTENSIONS=TRUE") QgsVectorFileWriter.writeAsVectorFormat(layer, layer_name, "utf-8", QgsCoordinateReferenceSystem(4326, QgsCoordinateReferenceSystem.EpsgCrsId), "GPX", datasourceOptions=ds_options)
def duplicateEmptyLayer(self, currentLayer: QgsVectorLayer): layer = QgsVectorLayer("Polygon?crs=ESPG:4326", currentLayer.name(), 'memory') # print("layer created") layer.setCrs(currentLayer.sourceCrs()) # print("crs set") layer.dataProvider().addAttributes( currentLayer.dataProvider().fields().toList()) layer.updateFields() return layer
def processAlgorithm(self, parameters, context, feedback): msg = "" table_without_geom = [ 'itineraire', 'element', 'poi_portion', 'poi_acces', 'poi_service', 'poi_tourisme' ] feedback.pushInfo("## CONNEXION A LA BASE DE DONNEES ##") connection = self.parameterAsString(parameters, self.DATABASE, context) table_int = self.parameterAsEnum(parameters, self.TABLE, context) table_name = self.EXPORTABLES[table_int] if table_name in table_without_geom or "val" in table_name: geom = None else: geom = "geom" name = table_name uri = uri_from_name(connection) if table_name == 'portion': name = 'v_portion' uri.setKeyColumn('id_portion') uri.setTable(name) uri.setSchema(self.parameterAsString(parameters, self.SCHEMA, context)) uri.setGeometryColumn(geom) layer = QgsVectorLayer(uri.uri(), table_name, "postgres") layer_name = layer.name() pk = layer.fields().field(layer.primaryKeyAttributes()[0]) dpt = self.parameterAsString(parameters, self.DPT, context) dirname = self.parameterAsString(parameters, self.PROJECTS_FOLDER, context) charger = self.parameterAsBool(parameters, self.CHARGER, context) feedback.pushInfo("") feedback.pushInfo("## CHARGEMENT DE LA COUCHE ##") sql_layer = self.get_sql_layer(layer_name, geom, pk.name(), uri, feedback) result = self.export_layer_to_shape(context, sql_layer, dpt, layer_name, dirname, feedback) if charger: self.load_shapefile(result[0], result[1], layer_name, context, feedback) if not result[0]: output_layer = "" else: output_layer = result[0] return {self.OUTPUT_MSG: msg, self.OUTPUT: output_layer}
def layerPermissions( # noqa: ignore=N802 self, layer: QgsVectorLayer ) -> qgis.server.QgsAccessControlFilter.LayerPermissions: """ Returns the layer rights. """ LOG.debug("layerPermissions %s", layer.name()) try: rights = QgsAccessControlFilter.LayerPermissions() rights.canRead = rights.canInsert = rights.canUpdate = rights.canDelete = False if self.ogcserver is None: parameters = self.serverInterface().requestHandler( ).parameterMap() LOG.warning( "Call on uninitialized plugin, map: %s", os.environ.get("QGIS_PROJECT_FILE", parameters.get("MAP")), ) return rights session = self.DBSession() try: roles = self.get_roles(session) if roles == "ROOT": rights.canRead = True layers = self.get_layers(session) ogc_layer_name = self.ogc_layer_name(layer) if ogc_layer_name not in layers: return rights gmf_layers = self.get_layers(session)[ogc_layer_name] finally: session.close() access, _ = self.get_restriction_areas(gmf_layers, roles=roles) if access is not Access.NO: rights.canRead = True access, _ = self.get_restriction_areas(gmf_layers, read_write=True, roles=roles) rights.canInsert = rights.canUpdate = rights.canDelete = access is not Access.NO return rights except Exception: LOG.error("Cannot run layerPermissions", exc_info=True) raise
def get_field_index(layer: QgsVectorLayer, field_name: str) -> int: """ Get field index if exists :param layer: QgsVectorLayer :param field_name: name of the field :return: index of the field """ field_index = layer.fields().indexFromName(field_name) if field_index == -1: raise KeyError( tr( "Field name {} does not exist in layer {}", field_name, layer.name(), )) return field_index
def layerResize(rasterLayer: QgsRasterLayer, domainLayer: QgsVectorLayer, name: str, resolution: (int, int)) -> None: """Description: Processes a raster image into a vector polygon ocean/land mask. Make sure to save the shapefile, as it will be deleted otherwise! Input: QgsRasterLayer rasterLayer - layer that contains the raster image to process QgsVectorLayer domainLayer - layer that contains a polygon specifying the bounds of the raster image to process QgsVectorLayer outputLayer - layer to save vector layer in. Warning: not supported yet. Output: QgsRasterLayer, QgsVectorLayer - objects referencing the new mask layers """ path = resolve('landsat_raw/' + domainLayer.name() + '/' + name + '.png') img = imread(path) img = resize(img, resolution) print(img.shape, path) if not DRY_RUN: imsave(path, img)
def test_vector_layer(): input_layer = QgsVectorLayer( r"C:\Users\diane.soares\Downloads\ne_10m_airports\ne_10m_airports.shp", "ne_10m_airports", "ogr") if not input_layer: print("Layer failed to load!") print(input_layer.name()) print(input_layer.crs().isValid()) print(input_layer.crs().authid()) print(input_layer.crs().toWkt()) source = unicode(input_layer.source()) print(source) return input_layer
def layerFilterSubsetString( self, layer: QgsVectorLayer) -> str: # noqa: ignore=N802 """ Returns an additional subset string (typically SQL) filter """ LOG.debug("layerFilterSubsetString %s %s", layer.name(), layer.dataProvider().storageType()) if self.ogcserver is None: parameters = self.serverInterface().requestHandler().parameterMap() LOG.warning( "Call on uninitialized plugin, map: %s", os.environ.get("QGIS_PROJECT_FILE", parameters.get("MAP")), ) return "FALSE" try: if layer.dataProvider().storageType( ) not in self.SUBSETSTRING_TYPE: LOG.debug("layerFilterSubsetString not in type") return None session = self.DBSession() try: access, area = self.get_area(layer, session) finally: session.close() if access is Access.FULL: LOG.debug("layerFilterSubsetString no area") return None if access is Access.NO: LOG.debug("layerFilterSubsetString not allowed") return "0" area = "ST_GeomFromText('{}', {})".format(area.wkt, self.srid) if self.srid != layer.crs().postgisSrid(): area = "ST_transform({}, {})".format(area, layer.crs().postgisSrid()) result = "ST_intersects({}, {})".format( QgsDataSourceUri( layer.dataProvider().dataSourceUri()).geometryColumn(), area) LOG.debug("layerFilterSubsetString filter: %s", result) return result except Exception: LOG.error("Cannot run layerFilterSubsetString", exc_info=True) raise
def add_vector_layer(self): """ Add vector layer to project.""" self.vector_filename = self.vector_file_lineEdit.text() self.vector_base_name = self.vector_name_lineEdit.text() if self.vector_file_extension is not None and self.vector_file_extension.lower() == "gpx": vlayer_routes = QgsVectorLayer(self.vector_filename + "?type=route", self.vector_base_name+"_route", "gpx") vlayer_tracks = QgsVectorLayer(self.vector_filename + "?type=track", self.vector_base_name+"_track", "gpx") vlayer_waypoints = QgsVectorLayer(self.vector_filename + "?type=waypoint", self.vector_base_name+" waypoints", "gpx") if not vlayer_routes.isValid() or not vlayer_waypoints.isValid() or not vlayer_tracks.isValid(): logger.warning("Layer failed to load!") QMessageBox.critical(self, "Add Layer", "Layer format is not recognised as a supported file format", QMessageBox.Close) self.msglog.logMessage("Failed to load layer " + self.vector_filename, "LoadingLayer", 1) self.vector_file_lineEdit.setText('') self.vector_name_lineEdit.setText('') else: if vlayer_routes.dataProvider().featureCount() > 0: self.proj.addMapLayer(vlayer_routes) if vlayer_tracks.dataProvider().featureCount() > 0: self.proj.addMapLayer(vlayer_tracks) if vlayer_waypoints.dataProvider().featureCount() > 0: self.proj.addMapLayer(vlayer_waypoints) self.accept() else: vlayer = QgsVectorLayer(self.vector_filename, self.vector_base_name, "ogr") if not vlayer.isValid(): logger.warning("Layer failed to load!") QMessageBox.critical(self, "Add Layer", "Layer format is not recognised as a supported file format", QMessageBox.Close) self.msglog.logMessage("Failed to load layer " + vlayer.name(), "LoadingLayer", 1) self.vector_file_lineEdit.setText('') self.vector_name_lineEdit.setText('') else: self.proj.addMapLayer(vlayer) self.accept()
def exportGlobalSummary(settings_instance, targetFile=None): #settings_instance.getSummaryWidget().updateTotals() csvFileName = settings_instance.summaryWidget.globalSummaryToCSV() csvLayer = QgsVectorLayer(csvFileName, 'summary report', 'ogr') QgsMapLayerRegistry.instance().addMapLayer(csvLayer) print_context = { 'type': 'map', 'job': 'project summary report', 'title': settings_instance.projectDescription.text(), 'template': "global_map.qpt", 'id': csvLayer.id(), 'name': csvLayer.name(), 'source': csvLayer.source(), } print_engine = fdtmPrint(settings_instance) result = print_engine.exportToPdf(print_context, targetFile=targetFile) QgsMapLayerRegistry.instance().removeMapLayer(csvLayer) return result
def layerFilterExpression( self, layer: QgsVectorLayer) -> Optional[str]: # noqa: ignore=N802 """ Returns an additional expression filter. """ LOG.debug("layerFilterExpression %s %s", layer.name(), layer.dataProvider().storageType()) if self.ogcserver is None: parameters = self.serverInterface().requestHandler().parameterMap() LOG.warning( "Call on uninitialized plugin, map: %s", os.environ.get("QGIS_PROJECT_FILE", parameters.get("MAP")), ) return "FALSE" try: if layer.dataProvider().storageType() in self.SUBSETSTRING_TYPE: LOG.debug("layerFilterExpression not in type") return None session = self.DBSession() try: access, area = self.get_area(layer, session) finally: session.close() if access is Access.FULL: LOG.debug("layerFilterExpression no area") return None if access is Access.NO: LOG.debug("layerFilterExpression not allowed") return "0" result = ( f"intersects($geometry, transform(geom_from_wkt('{area.wkt}'), 'EPSG:{self.srid}', " f"'{layer.crs().authid()}'))") LOG.debug("layerFilterExpression filter: %s", result) return result except Exception: LOG.error("Cannot run layerFilterExpression", exc_info=True) raise
def __restore_geometries(self): src_file_name = self.backup_path + QDir.separator() + self.layer_id + '.shp' if not QFile.exists(src_file_name): self.report_message.emit(self.layer_id, 'no backup file') self.completed = True return self.report_message.emit(self.layer_id, 'preparing ...') orig_layer = QgsMapLayerRegistry.instance().mapLayer(self.layer_id) # create a copy of the layer just for editing layer = QgsVectorLayer(orig_layer.source(), orig_layer.name(), orig_layer.providerType()) layer.startEditing() src_layer = QgsVectorLayer(src_file_name, layer.name(), 'ogr') total_features = src_layer.featureCount() QgsMessageLog.logMessage(self.plugin.tr('Features to be restored in layer <{0}>: {1}'). format(orig_layer.name(), total_features), self.plugin.tr('Vertex Tools'), QgsMessageLog.INFO) if total_features == 0: self.report_message.emit(self.layer_id, 'no features to restore') count = 0 for feature in src_layer.getFeatures(): with QMutexLocker(self.mutex): if self.stopped: layer.rollBack() return layer.changeGeometry(feature.id(), feature.geometry()) count += 1 self.run_progressed.emit(self.layer_id, count, total_features) layer.commitChanges() self.completed = True
def _createPolygonLayer(self, crs=None, fields=None): """Creates an empty shape file layer""" if crs is None: crs = QgsCoordinateReferenceSystem() crs.createFromEpsg(4326) if fields is None: fields = {} myTempdir = temp_dir(sub_dir='preprocess') myOutFilename = unique_filename(suffix='.shp', dir=myTempdir) mySHPWriter = QgsVectorFileWriter(myOutFilename, 'UTF-8', fields, QGis.WKBPolygon, crs) #flush the writer to write to file del mySHPWriter myName = self.tr('Entire area') myLayer = QgsVectorLayer(myOutFilename, myName, 'ogr') LOGGER.debug('created' + myLayer.name()) return myLayer
def newFrontageLayer(self): # always create a memory layer first if self.frontagedlg.createNewFileCheckBox.isChecked(): building_layer = self.getSelectedLayer() crs = building_layer.crs() vl = QgsVectorLayer("LineString?crs=" + crs.authid(), "memory:frontages", "memory") else: vl = QgsVectorLayer("LineString?crs=", "memory:frontages", "memory") if vl.crs().toWkt() == "": vl.setCrs(QgsProject.instance().crs()) provider = vl.dataProvider() provider.addAttributes([QgsField(FrontageTool.id_attribute, QVariant.Int), QgsField(FrontageTool.group_attribute, QVariant.String), QgsField(FrontageTool.type_attribute, QVariant.String), QgsField(FrontageTool.length_attribute, QVariant.Double)]) vl.updateFields() # use building layer - explode if self.frontagedlg.createNewFileCheckBox.isChecked(): print('building layer') exploded_features = [] i = 1 for f in building_layer.getFeatures(): points = f.geometry().asPolygon()[0] # get list of points for (p1, p2) in zip(points[:-1], points[1:]): i += 1 feat = QgsFeature() line_geom = QgsGeometry.fromPolyline([p1, p2]) feat.setAttributes([i, NULL, NULL, line_geom.geometry().length()]) feat.setId(i) feat.setGeometry(line_geom) exploded_features.append(feat) print('building layer2') vl.updateFields() vl.startEditing() provider.addFeatures(exploded_features) vl.commitChanges() print('building layer3') if self.frontagedlg.f_shp_radioButton.isChecked(): # layer_type == 'shapefile': path = self.frontagedlg.lineEditFrontages.text() if path and path != '': filename = os.path.basename(path) location = os.path.abspath(path) shph.createShapeFile(vl, path, vl.crs()) vl = self.iface.addVectorLayer(location, filename[:-4], "ogr") else: vl = 'invalid data source' elif self.frontagedlg.f_postgis_radioButton.isChecked(): db_path = self.frontagedlg.lineEditFrontages.text() if db_path and db_path != '': (database, schema, table_name) = (self.frontagedlg.lineEditFrontages.text()).split(':') db_con_info = self.frontagedlg.dbsettings_dlg.available_dbs[database] uri = QgsDataSourceUri() # passwords, usernames need to be empty if not provided or else connection will fail if 'service' in list(db_con_info.keys()): uri.setConnection(db_con_info['service'], '', '', '') # db_con_info['dbname'] elif 'password' in list(db_con_info.keys()): uri.setConnection(db_con_info['host'], db_con_info['port'], db_con_info['dbname'], db_con_info['user'], db_con_info['password']) else: print(db_con_info) # db_con_info['host'] uri.setConnection('', db_con_info['port'], db_con_info['dbname'], '', '') # , db_con_info['user'], '') uri.setDataSource(schema, table_name, "geom") error = QgsVectorLayerExporter.exportLayer(vl, uri.uri(), "postgres", QgsProject.instance().crs()) if error[0] != QgsVectorLayerExporter.NoError: print("Error when creating postgis layer: ", error[1]) vl = 'duplicate' else: vl = QgsVectorLayer(uri.uri(), table_name, "postgres") else: vl = 'invalid data source' if vl == 'invalid data source': msgBar = self.iface.messageBar() msg = msgBar.createMessage(u'Specify output path!') msgBar.pushWidget(msg, Qgis.Info, 10) elif vl == 'duplicate': msgBar = self.iface.messageBar() msg = msgBar.createMessage(u'Fronatges layer already exists!') msgBar.pushWidget(msg, Qgis.Info, 10) elif not vl: msgBar = self.iface.messageBar() msg = msgBar.createMessage(u'Frontages layer failed to load!') msgBar.pushWidget(msg, Qgis.Info, 10) else: QgsProject.instance().addMapLayer(vl) msgBar = self.iface.messageBar() msg = msgBar.createMessage(u'Frontages layer created!') msgBar.pushWidget(msg, Qgis.Info, 10) vl.startEditing() if self.isRequiredLayer(vl, type): self.dockwidget.useExistingcomboBox.addItem(vl.name(), vl) # self.updateFrontageLayer() This is creating problems with signals - REMOVE # TODO: updateLength function should receive a layer as input. It would be used earlier self.frontagedlg.closePopUp()
class TestQgsLayerTreeView(unittest.TestCase): def __init__(self, methodName): """Run once on class initialization.""" unittest.TestCase.__init__(self, methodName) # setup a dummy project self.project = QgsProject() self.layer = QgsVectorLayer("Point?field=fldtxt:string", "layer1", "memory") self.layer2 = QgsVectorLayer("Point?field=fldtxt:string", "layer2", "memory") self.layer3 = QgsVectorLayer("Point?field=fldtxt:string", "layer3", "memory") self.layer4 = QgsVectorLayer("Point?field=fldtxt:string", "layer4", "memory") self.layer5 = QgsVectorLayer("Point?field=fldtxt:string", "layer5", "memory") self.project.addMapLayers([self.layer, self.layer2, self.layer3]) self.model = QgsLayerTreeModel(self.project.layerTreeRoot()) if USE_MODEL_TESTER: self.tester = QAbstractItemModelTester(self.model) def nodeOrder(self, group): nodeorder = [] for node in group: if QgsLayerTree.isGroup(node): groupname = node.name() nodeorder.append(groupname) for child in self.nodeOrder(node.children()): nodeorder.append(groupname + '-' + child) elif QgsLayerTree.isLayer(node): nodeorder.append(node.layer().name()) return nodeorder def testSetModel(self): view = QgsLayerTreeView() # should not work string_list_model = QStringListModel() view.setModel(string_list_model) self.assertFalse(view.model()) # should work view.setModel(self.model) if USE_MODEL_TESTER: proxy_tester = QAbstractItemModelTester(view.model()) self.assertEqual(view.layerTreeModel(), self.model) def testSetCurrentLayer(self): view = QgsLayerTreeView() view.setModel(self.model) if USE_MODEL_TESTER: proxy_tester = QAbstractItemModelTester(view.model()) current_layer_changed_spy = QSignalSpy(view.currentLayerChanged) self.assertFalse(view.currentLayer()) view.setCurrentLayer(self.layer3) self.assertEqual(view.currentLayer(), self.layer3) self.assertEqual(len(current_layer_changed_spy), 1) view.setCurrentLayer(self.layer) self.assertEqual(view.currentLayer(), self.layer) self.assertEqual(len(current_layer_changed_spy), 2) view.setCurrentLayer(None) self.assertFalse(view.currentLayer()) self.assertEqual(len(current_layer_changed_spy), 3) def testDefaultActions(self): view = QgsLayerTreeView() view.setModel(self.model) if USE_MODEL_TESTER: proxy_tester = QAbstractItemModelTester(view.model()) actions = QgsLayerTreeViewDefaultActions(view) # show in overview action view.setCurrentLayer(self.layer) self.assertEqual(view.currentNode().customProperty('overview', 0), False) show_in_overview = actions.actionShowInOverview() show_in_overview.trigger() self.assertEqual(view.currentNode().customProperty('overview', 0), True) show_in_overview.trigger() self.assertEqual(view.currentNode().customProperty('overview', 0), False) def testMoveOutOfGroupActionLayer(self): """Test move out of group action on layer""" view = QgsLayerTreeView() group = self.project.layerTreeRoot().addGroup("embeddedgroup") group.addLayer(self.layer4) group.addLayer(self.layer5) groupname = group.name() view.setModel(self.model) if USE_MODEL_TESTER: proxy_tester = QAbstractItemModelTester(view.model()) actions = QgsLayerTreeViewDefaultActions(view) self.assertEqual( self.nodeOrder(self.project.layerTreeRoot().children()), [ self.layer.name(), self.layer2.name(), self.layer3.name(), groupname, groupname + '-' + self.layer4.name(), groupname + '-' + self.layer5.name(), ]) view.setCurrentLayer(self.layer5) moveOutOfGroup = actions.actionMoveOutOfGroup() moveOutOfGroup.trigger() self.assertEqual( self.nodeOrder(self.project.layerTreeRoot().children()), [ self.layer.name(), self.layer2.name(), self.layer3.name(), self.layer5.name(), groupname, groupname + '-' + self.layer4.name(), ]) def testMoveToTopActionLayer(self): """Test move to top action on layer""" view = QgsLayerTreeView() view.setModel(self.model) if USE_MODEL_TESTER: proxy_tester = QAbstractItemModelTester(view.model()) actions = QgsLayerTreeViewDefaultActions(view) self.assertEqual(self.project.layerTreeRoot().layerOrder(), [self.layer, self.layer2, self.layer3]) view.setCurrentLayer(self.layer3) movetotop = actions.actionMoveToTop() movetotop.trigger() self.assertEqual(self.project.layerTreeRoot().layerOrder(), [self.layer3, self.layer, self.layer2]) def testMoveToTopActionGroup(self): """Test move to top action on group""" view = QgsLayerTreeView() group = self.project.layerTreeRoot().addGroup("embeddedgroup") group.addLayer(self.layer4) group.addLayer(self.layer5) groupname = group.name() view.setModel(self.model) if USE_MODEL_TESTER: proxy_tester = QAbstractItemModelTester(view.model()) actions = QgsLayerTreeViewDefaultActions(view) self.assertEqual( self.nodeOrder(self.project.layerTreeRoot().children()), [ self.layer.name(), self.layer2.name(), self.layer3.name(), groupname, groupname + '-' + self.layer4.name(), groupname + '-' + self.layer5.name(), ]) nodeLayerIndex = view.node2index(group) view.setCurrentIndex(nodeLayerIndex) movetotop = actions.actionMoveToTop() movetotop.trigger() self.assertEqual( self.nodeOrder(self.project.layerTreeRoot().children()), [ groupname, groupname + '-' + self.layer4.name(), groupname + '-' + self.layer5.name(), self.layer.name(), self.layer2.name(), self.layer3.name(), ]) def testMoveToTopActionEmbeddedGroup(self): """Test move to top action on embeddedgroup layer""" view = QgsLayerTreeView() group = self.project.layerTreeRoot().addGroup("embeddedgroup") group.addLayer(self.layer4) group.addLayer(self.layer5) groupname = group.name() view.setModel(self.model) if USE_MODEL_TESTER: proxy_tester = QAbstractItemModelTester(view.model()) actions = QgsLayerTreeViewDefaultActions(view) self.assertEqual( self.nodeOrder(self.project.layerTreeRoot().children()), [ self.layer.name(), self.layer2.name(), self.layer3.name(), groupname, groupname + '-' + self.layer4.name(), groupname + '-' + self.layer5.name(), ]) view.setCurrentLayer(self.layer5) movetotop = actions.actionMoveToTop() movetotop.trigger() self.assertEqual( self.nodeOrder(self.project.layerTreeRoot().children()), [ self.layer.name(), self.layer2.name(), self.layer3.name(), groupname, groupname + '-' + self.layer5.name(), groupname + '-' + self.layer4.name(), ]) def testMoveToTopActionLayerAndGroup(self): """Test move to top action for a group and it's layer simultaneously""" view = QgsLayerTreeView() group = self.project.layerTreeRoot().addGroup("embeddedgroup") group.addLayer(self.layer4) group.addLayer(self.layer5) groupname = group.name() view.setModel(self.model) if USE_MODEL_TESTER: proxy_tester = QAbstractItemModelTester(view.model()) actions = QgsLayerTreeViewDefaultActions(view) self.assertEqual( self.nodeOrder(self.project.layerTreeRoot().children()), [ self.layer.name(), self.layer2.name(), self.layer3.name(), groupname, groupname + '-' + self.layer4.name(), groupname + '-' + self.layer5.name(), ]) selectionMode = view.selectionMode() view.setSelectionMode(QgsLayerTreeView.MultiSelection) nodeLayerIndex = view.node2index(group) view.setCurrentIndex(nodeLayerIndex) view.setCurrentLayer(self.layer5) view.setSelectionMode(selectionMode) movetotop = actions.actionMoveToTop() movetotop.trigger() self.assertEqual( self.nodeOrder(self.project.layerTreeRoot().children()), [ groupname, groupname + '-' + self.layer5.name(), groupname + '-' + self.layer4.name(), self.layer.name(), self.layer2.name(), self.layer3.name(), ]) def testMoveToBottomActionLayer(self): """Test move to bottom action on layer""" view = QgsLayerTreeView() view.setModel(self.model) if USE_MODEL_TESTER: proxy_tester = QAbstractItemModelTester(view.model()) actions = QgsLayerTreeViewDefaultActions(view) self.assertEqual(self.project.layerTreeRoot().layerOrder(), [self.layer, self.layer2, self.layer3]) view.setCurrentLayer(self.layer) movetobottom = actions.actionMoveToBottom() movetobottom.trigger() self.assertEqual(self.project.layerTreeRoot().layerOrder(), [self.layer2, self.layer3, self.layer]) def testMoveToBottomActionGroup(self): """Test move to bottom action on group""" view = QgsLayerTreeView() group = self.project.layerTreeRoot().insertGroup(0, "embeddedgroup") group.addLayer(self.layer4) group.addLayer(self.layer5) groupname = group.name() view.setModel(self.model) if USE_MODEL_TESTER: proxy_tester = QAbstractItemModelTester(view.model()) actions = QgsLayerTreeViewDefaultActions(view) self.assertEqual( self.nodeOrder(self.project.layerTreeRoot().children()), [ groupname, groupname + '-' + self.layer4.name(), groupname + '-' + self.layer5.name(), self.layer.name(), self.layer2.name(), self.layer3.name(), ]) nodeLayerIndex = view.node2index(group) view.setCurrentIndex(nodeLayerIndex) movetobottom = actions.actionMoveToBottom() movetobottom.trigger() self.assertEqual( self.nodeOrder(self.project.layerTreeRoot().children()), [ self.layer.name(), self.layer2.name(), self.layer3.name(), groupname, groupname + '-' + self.layer4.name(), groupname + '-' + self.layer5.name(), ]) def testMoveToBottomActionEmbeddedGroup(self): """Test move to bottom action on embeddedgroup layer""" view = QgsLayerTreeView() group = self.project.layerTreeRoot().addGroup("embeddedgroup") group.addLayer(self.layer4) group.addLayer(self.layer5) groupname = group.name() view.setModel(self.model) if USE_MODEL_TESTER: proxy_tester = QAbstractItemModelTester(view.model()) actions = QgsLayerTreeViewDefaultActions(view) self.assertEqual( self.nodeOrder(self.project.layerTreeRoot().children()), [ self.layer.name(), self.layer2.name(), self.layer3.name(), groupname, groupname + '-' + self.layer4.name(), groupname + '-' + self.layer5.name(), ]) view.setCurrentLayer(self.layer4) movetobottom = actions.actionMoveToBottom() movetobottom.trigger() self.assertEqual( self.nodeOrder(self.project.layerTreeRoot().children()), [ self.layer.name(), self.layer2.name(), self.layer3.name(), groupname, groupname + '-' + self.layer5.name(), groupname + '-' + self.layer4.name(), ]) def testMoveToBottomActionLayerAndGroup(self): """Test move to top action for a group and it's layer simultaneously""" view = QgsLayerTreeView() group = self.project.layerTreeRoot().insertGroup(0, "embeddedgroup") group.addLayer(self.layer4) group.addLayer(self.layer5) groupname = group.name() view.setModel(self.model) if USE_MODEL_TESTER: proxy_tester = QAbstractItemModelTester(view.model()) actions = QgsLayerTreeViewDefaultActions(view) self.assertEqual( self.nodeOrder(self.project.layerTreeRoot().children()), [ groupname, groupname + '-' + self.layer4.name(), groupname + '-' + self.layer5.name(), self.layer.name(), self.layer2.name(), self.layer3.name(), ]) selectionMode = view.selectionMode() view.setSelectionMode(QgsLayerTreeView.MultiSelection) nodeLayerIndex = view.node2index(group) view.setCurrentIndex(nodeLayerIndex) view.setCurrentLayer(self.layer4) view.setSelectionMode(selectionMode) movetobottom = actions.actionMoveToBottom() movetobottom.trigger() self.assertEqual( self.nodeOrder(self.project.layerTreeRoot().children()), [ self.layer.name(), self.layer2.name(), self.layer3.name(), groupname, groupname + '-' + self.layer5.name(), groupname + '-' + self.layer4.name(), ]) def testSetLayerVisible(self): view = QgsLayerTreeView() view.setModel(self.model) if USE_MODEL_TESTER: proxy_tester = QAbstractItemModelTester(view.model()) self.project.layerTreeRoot().findLayer( self.layer).setItemVisibilityChecked(True) self.project.layerTreeRoot().findLayer( self.layer2).setItemVisibilityChecked(True) self.assertTrue(self.project.layerTreeRoot().findLayer( self.layer).itemVisibilityChecked()) self.assertTrue(self.project.layerTreeRoot().findLayer( self.layer2).itemVisibilityChecked()) view.setLayerVisible(None, True) view.setLayerVisible(self.layer, True) self.assertTrue(self.project.layerTreeRoot().findLayer( self.layer).itemVisibilityChecked()) view.setLayerVisible(self.layer2, False) self.assertFalse(self.project.layerTreeRoot().findLayer( self.layer2).itemVisibilityChecked()) view.setLayerVisible(self.layer2, True) self.assertTrue(self.project.layerTreeRoot().findLayer( self.layer2).itemVisibilityChecked()) def testProxyModel(self): """Test proxy model filtering and private layers""" view = QgsLayerTreeView() view.setModel(self.model) if USE_MODEL_TESTER: proxy_tester = QAbstractItemModelTester(view.model()) tree_model = view.layerTreeModel() proxy_model = view.proxyModel() self.assertEqual(tree_model.rowCount(), 3) self.assertEqual(proxy_model.rowCount(), 3) items = [] for r in range(tree_model.rowCount()): items.append(tree_model.data(tree_model.index(r, 0))) self.assertEqual(items, ['layer1', 'layer2', 'layer3']) proxy_items = [] for r in range(proxy_model.rowCount()): proxy_items.append(proxy_model.data(proxy_model.index(r, 0))) self.assertEqual(proxy_items, ['layer1', 'layer2', 'layer3']) self.layer3.setFlags(self.layer.Private) self.assertEqual(tree_model.rowCount(), 3) self.assertEqual(proxy_model.rowCount(), 2) proxy_items = [] for r in range(proxy_model.rowCount()): proxy_items.append(proxy_model.data(proxy_model.index(r, 0))) self.assertEqual(proxy_items, ['layer1', 'layer2']) view.setShowPrivateLayers(True) self.assertEqual(proxy_model.rowCount(), 3) proxy_items = [] for r in range(proxy_model.rowCount()): proxy_items.append(proxy_model.data(proxy_model.index(r, 0))) self.assertEqual(proxy_items, ['layer1', 'layer2', 'layer3']) view.setShowPrivateLayers(False) self.assertEqual(proxy_model.rowCount(), 2) proxy_items = [] for r in range(proxy_model.rowCount()): proxy_items.append(proxy_model.data(proxy_model.index(r, 0))) self.assertEqual(proxy_items, ['layer1', 'layer2']) # Test filters proxy_model.setFilterText('layer2') self.assertEqual(proxy_model.rowCount(), 1) proxy_items = [] for r in range(proxy_model.rowCount()): proxy_items.append(proxy_model.data(proxy_model.index(r, 0))) self.assertEqual(proxy_items, ['layer2']) def testProxyModelCurrentIndex(self): """Test a crash spotted out while developing the proxy model""" view = QgsLayerTreeView() view.setModel(self.model) if USE_MODEL_TESTER: proxy_tester = QAbstractItemModelTester(view.model()) tree_tester = QAbstractItemModelTester(view.layerTreeModel()) view.setCurrentLayer(self.layer3) self.layer3.setFlags(self.layer.Private) def testNode2IndexMethods(self): """Test node2index and node2sourceIndex""" view = QgsLayerTreeView() view.setModel(self.model) if USE_MODEL_TESTER: proxy_tester = QAbstractItemModelTester(view.model()) tree_tester = QAbstractItemModelTester(view.layerTreeModel()) tree_model = view.layerTreeModel() proxy_model = view.proxyModel() proxy_index = proxy_model.index(1, 0) node2 = view.index2node(proxy_index) self.assertEqual(node2.name(), 'layer2') proxy_layer2_index = view.node2index(node2) self.assertEqual(proxy_layer2_index, view.node2index(node2)) source_index = tree_model.index(1, 0) tree_layer2_index = view.node2sourceIndex(node2) self.assertEqual(tree_layer2_index, view.node2sourceIndex(node2))
class TestQgsLayerTreeView(unittest.TestCase): def __init__(self, methodName): """Run once on class initialization.""" unittest.TestCase.__init__(self, methodName) # setup a dummy project self.project = QgsProject() self.layer = QgsVectorLayer("Point?field=fldtxt:string", "layer1", "memory") self.layer2 = QgsVectorLayer("Point?field=fldtxt:string", "layer2", "memory") self.layer3 = QgsVectorLayer("Point?field=fldtxt:string", "layer3", "memory") self.layer4 = QgsVectorLayer("Point?field=fldtxt:string", "layer4", "memory") self.layer5 = QgsVectorLayer("Point?field=fldtxt:string", "layer5", "memory") self.project.addMapLayers([self.layer, self.layer2, self.layer3]) self.model = QgsLayerTreeModel(self.project.layerTreeRoot()) def nodeOrder(self, group): nodeorder = [] layerTree = QgsLayerTree() for node in group: if QgsLayerTree.isGroup(node): groupname = node.name() nodeorder.append(groupname) for child in self.nodeOrder(node.children()): nodeorder.append(groupname + '-' + child) elif QgsLayerTree.isLayer(node): nodeorder.append(node.layer().name()) return nodeorder def testSetModel(self): view = QgsLayerTreeView() # should not work string_list_model = QStringListModel() view.setModel(string_list_model) self.assertFalse(view.model()) # should work view.setModel(self.model) self.assertEqual(view.model(), self.model) def testSetCurrentLayer(self): view = QgsLayerTreeView() view.setModel(self.model) current_layer_changed_spy = QSignalSpy(view.currentLayerChanged) self.assertFalse(view.currentLayer()) view.setCurrentLayer(self.layer3) self.assertEqual(view.currentLayer(), self.layer3) self.assertEqual(len(current_layer_changed_spy), 1) view.setCurrentLayer(self.layer) self.assertEqual(view.currentLayer(), self.layer) self.assertEqual(len(current_layer_changed_spy), 2) view.setCurrentLayer(None) self.assertFalse(view.currentLayer()) self.assertEqual(len(current_layer_changed_spy), 3) def testDefaultActions(self): view = QgsLayerTreeView() view.setModel(self.model) actions = QgsLayerTreeViewDefaultActions(view) # show in overview action view.setCurrentLayer(self.layer) self.assertEqual(view.currentNode().customProperty('overview', 0), False) show_in_overview = actions.actionShowInOverview() show_in_overview.trigger() self.assertEqual(view.currentNode().customProperty('overview', 0), True) show_in_overview.trigger() self.assertEqual(view.currentNode().customProperty('overview', 0), False) def testMoveOutOfGroupActionLayer(self): """Test move out of group action on layer""" view = QgsLayerTreeView() group = self.project.layerTreeRoot().addGroup("embeddedgroup") group.addLayer(self.layer4) group.addLayer(self.layer5) groupname = group.name() view.setModel(self.model) actions = QgsLayerTreeViewDefaultActions(view) self.assertEqual(self.nodeOrder(self.project.layerTreeRoot().children()), [ self.layer.name(), self.layer2.name(), self.layer3.name(), groupname, groupname + '-' + self.layer4.name(), groupname + '-' + self.layer5.name(), ]) view.setCurrentLayer(self.layer5) moveOutOfGroup = actions.actionMoveOutOfGroup() moveOutOfGroup.trigger() self.assertEqual(self.nodeOrder(self.project.layerTreeRoot().children()), [ self.layer.name(), self.layer2.name(), self.layer3.name(), self.layer5.name(), groupname, groupname + '-' + self.layer4.name(), ]) def testMoveToTopActionLayer(self): """Test move to top action on layer""" view = QgsLayerTreeView() view.setModel(self.model) actions = QgsLayerTreeViewDefaultActions(view) self.assertEqual(self.project.layerTreeRoot().layerOrder(), [self.layer, self.layer2, self.layer3]) view.setCurrentLayer(self.layer3) movetotop = actions.actionMoveToTop() movetotop.trigger() self.assertEqual(self.project.layerTreeRoot().layerOrder(), [self.layer3, self.layer, self.layer2]) def testMoveToTopActionGroup(self): """Test move to top action on group""" view = QgsLayerTreeView() group = self.project.layerTreeRoot().addGroup("embeddedgroup") group.addLayer(self.layer4) group.addLayer(self.layer5) groupname = group.name() view.setModel(self.model) actions = QgsLayerTreeViewDefaultActions(view) self.assertEqual(self.nodeOrder(self.project.layerTreeRoot().children()), [ self.layer.name(), self.layer2.name(), self.layer3.name(), groupname, groupname + '-' + self.layer4.name(), groupname + '-' + self.layer5.name(), ]) nodeLayerIndex = self.model.node2index(group) view.setCurrentIndex(nodeLayerIndex) movetotop = actions.actionMoveToTop() movetotop.trigger() self.assertEqual(self.nodeOrder(self.project.layerTreeRoot().children()), [ groupname, groupname + '-' + self.layer4.name(), groupname + '-' + self.layer5.name(), self.layer.name(), self.layer2.name(), self.layer3.name(), ]) def testMoveToTopActionEmbeddedGroup(self): """Test move to top action on embeddedgroup layer""" view = QgsLayerTreeView() group = self.project.layerTreeRoot().addGroup("embeddedgroup") group.addLayer(self.layer4) group.addLayer(self.layer5) groupname = group.name() view.setModel(self.model) actions = QgsLayerTreeViewDefaultActions(view) self.assertEqual(self.nodeOrder(self.project.layerTreeRoot().children()), [ self.layer.name(), self.layer2.name(), self.layer3.name(), groupname, groupname + '-' + self.layer4.name(), groupname + '-' + self.layer5.name(), ]) view.setCurrentLayer(self.layer5) movetotop = actions.actionMoveToTop() movetotop.trigger() self.assertEqual(self.nodeOrder(self.project.layerTreeRoot().children()), [ self.layer.name(), self.layer2.name(), self.layer3.name(), groupname, groupname + '-' + self.layer5.name(), groupname + '-' + self.layer4.name(), ])
def SplitMeshLayer(mlayer, keycolum): # InputLayer メッシュテーブル # output_table 出力メッシュテーブル # SplitFlag フラグが1のメッシュは分割しない # # return new mesh layer # #outputlayer = QgsVectorLayer("Point?crs=EPSG:4326", "layer name you like", "memory") if type(mlayer) is str: mlayer = QgsVectorLayer(mlayer, "mesh", "ogr") if mlayer.isValid(): print("dmesh Layer load OK") else: print("dmesh Layer load Fail") print("dmesh=" + mlayer.name()) sys.exit() crsstr = mlayer.crs().authid() # 作業結果出力レイヤ vectL = 'Polygon?crs=' + crsstr vl1 = QgsVectorLayer(vectL, "temporary_mesh", "memory") if not vl1: print("Virtual Layer failed to load!") sys.exit() #else: # print( out_tb ) #vl1.setCrs( mlayer.crs() ) pr1 = vl1.dataProvider() # フィールド定義 pr1.addAttributes([QgsField(keycolum, QVariant.String)]) # QgsField(divcolumn, QVariant.Int)]) vl1.updateFields() # vl1.beginEditCommand("Add Polygons") features = mlayer.getFeatures() for feature in features: code = feature[keycolum] #divide_f = feature[ divcolumn ] divide_f = 0 #print( 'code =' + code+ ' divide=' + str(divide_f) ) geom = feature.geometry() geomSingleType = QgsWkbTypes.isSingleType(geom.wkbType()) if divide_f == 0: if geom.type() == QgsWkbTypes.PolygonGeometry: if geomSingleType: x = geom.asPolygon() #print("Polygon: ", x, "Area: ", geom.area()) for xp in x: #print("xp:",xp ) #for xxp in xp: # print("xxp:",xxp) # 座標の場所を判定して位置関係を正規化したほうがいいかも # p0_1 = GetCyuuten(xp[0], xp[1]) p1_2 = GetCyuuten(xp[1], xp[2]) p2_3 = GetCyuuten(xp[2], xp[3]) p3_4 = GetCyuuten(xp[3], xp[4]) pC_C = GetCyuuten(p0_1, p2_3) # 新しいキーコード ncode1 = code + '-01' Polygon1 = QgsGeometry.fromPolygonXY([[ QgsPointXY(xp[0].x(), xp[0].y()), QgsPointXY(p0_1.x(), p0_1.y()), QgsPointXY(pC_C.x(), pC_C.y()), QgsPointXY(p3_4.x(), p3_4.y()) ]]) # add a feature fet = QgsFeature(pr1.fields()) fet.setGeometry(Polygon1) fet[keycolum] = ncode1 # fet[divcolumn] = divide_f # 新しい feature を作って別レイヤに格納する retc = pr1.addFeatures([fet]) #print("add new") #print( retc ) # 新しいキーコード ncode2 = code + '-02' Polygon2 = QgsGeometry.fromPolygonXY([[ QgsPointXY(p0_1.x(), p0_1.y()), QgsPointXY(xp[1].x(), xp[1].y()), QgsPointXY(p1_2.x(), p1_2.y()), QgsPointXY(pC_C.x(), pC_C.y()) ]]) fet2 = QgsFeature(pr1.fields()) fet2.setGeometry(Polygon2) fet2[keycolum] = ncode2 # fet2[divcolumn] = divide_f # 新しい feature を作って別レイヤに格納する retc = pr1.addFeatures([fet2]) # 新しいキーコード ncode3 = code + '-03' Polygon3 = QgsGeometry.fromPolygonXY([[ QgsPointXY(pC_C.x(), pC_C.y()), QgsPointXY(p1_2.x(), p1_2.y()), QgsPointXY(xp[2].x(), xp[2].y()), QgsPointXY(p2_3.x(), p2_3.y()) ]]) fet3 = QgsFeature(pr1.fields()) fet3.setGeometry(Polygon3) fet3[keycolum] = ncode3 # fet3[divcolumn] = divide_f # 新しい feature を作って別レイヤに格納する retc = pr1.addFeatures([fet3]) # 新しいキーコード ncode4 = code + '-04' Polygon4 = QgsGeometry.fromPolygonXY([[ QgsPointXY(p3_4.x(), p3_4.y()), QgsPointXY(pC_C.x(), pC_C.y()), QgsPointXY(p2_3.x(), p2_3.y()), QgsPointXY(xp[3].x(), xp[3].y()) ]]) fet4 = QgsFeature(pr1.fields()) fet4.setGeometry(Polygon4) fet4[keycolum] = ncode4 # fet4[divcolumn] = divide_f # 新しい feature を作って別レイヤに格納する retc = pr1.addFeatures([fet4]) #print(Polygon1) # print(Polygon2) #Poly #feat.setGeometry( QgsGeometry.fromPolygonXY([QgsPointXY(546016, 4760165), p2, p3])) #qPolygon1 = QgsGeometry.fromPolygonXY([ xp[0],p0_1, pC_C,xp[0]]) #print( qPolygon1 ) # 一点目 2点目の中点を求める 2 else: x = geom.asMultiPolygon() #print("MultiPolygon: ", x, "Area: ", geom.area()) else: print("geometry is not polygon!") #else: # 分割不要ポリゴンはそのまま書き込む # retc = pr1.addFeatures([feature]) vl1.updateExtents() vl1.endEditCommand() vl1.commitChanges() return vl1
def ogc_layer_name(self, layer: QgsVectorLayer) -> str: use_layer_id, _ = self.project().readBoolEntry("WMSUseLayerIDs", "/", False) if use_layer_id: return layer.id() return layer.shortName() or layer.name()
def nodeDuplicate(node,newname=None,position='bottom',target_node=None): import time if oeq_global.isStringOrUnicode(node): node = nodeByName(node) if len(node) == 0: return None node = node[0] if target_node == None: target_node = node.parent() else: if oeq_global.isStringOrUnicode(target_node): target_node = nodeByName(target_node) if len(target_node) == 0: return None target_node = target_node[0] # #print node.layer().name() #print newname layer = node.layer() # source of the layer provider = layer.dataProvider() #print "---------------------" #print provider.crs().authid() #print layer.crs().authid() #print "---------------------" # creation of the shapefiles: pathfile = os.path.join(oeq_global.OeQ_project_path(),newname+'.shp') ct_pathfile = os.path.join(oeq_global.OeQ_project_path(),newname+'.qml') writer = QgsVectorFileWriter(pathfile, "CP1250", provider.fields(), provider.geometryType(), layer.crs(), "ESRI Shapefile") #print writer outelem = QgsFeature() # iterating over the input layer for elem in layer.getFeatures(): outelem.setGeometry(elem.geometry() ) outelem.setAttributes(elem.attributes()) writer.addFeature(outelem) del writer oeq_global.OeQ_wait_for_file(pathfile) #time.sleep(1) newlayer = QgsVectorLayer(pathfile, newname, "ogr") #print layer.isValid() QgsMapLayerRegistry.instance().addMapLayer(newlayer, True) newlayer.setCrs(layer.crs()) #oeq_global.OeQ_wait_for_renderer(60000) #print newlayer.name() newnode = nodeByName(newlayer.name()) if len(newnode) == 0: return None newnode = newnode[0] # oeq_global.OeQ_unlockQgis() #time.sleep(1) newlayer.loadNamedStyle(ct_pathfile) nodeCollapse(newnode) #time.sleep(1) #position = nodePosition(node,target_node) newnode=nodeMove(newnode,position,target_node) #time.sleep(1) #oeq_global.OeQ_unlockQgis() #oeq_global.OeQ_wait(0.5) #print "+++++++++++++++" return newnode
def processAlgorithm(self, parameters, context, model_feedback): """ Here is where the processing itself takes place. """ results = {} csvfile = self.parameterAsFile(parameters, self.INPUT, context) if csvfile is None: raise QgsProcessingException(self.tr('csv file error')) #df = QgsVirtualLayerDefinition() enc = self.parameterAsInt(parameters, 'ENCODING', context) meshLayer = self.parameterAsVectorLayer(parameters, "meshlayer", context) if meshLayer is None: raise QgsProcessingException(self.tr('mesh layer missed')) meshidfields = self.parameterAsFields(parameters, 'meshid', context) limit_sample = self.parameterAsInt(parameters, 'limit_sample', context) maxdivide = self.parameterAsInt(parameters, 'maxdivide', context) uneven_div = self.parameterAsInt(parameters, 'uneven_div', context) popmeshLayer = self.parameterAsVectorLayer(parameters, "popmeshlayer", context) if popmeshLayer is None: raise QgsProcessingException(self.tr('popmes layer missed')) popmeshidfields = self.parameterAsFields(parameters, 'popmeshid', context) popmeshpopfields = self.parameterAsFields(parameters, 'popmeshpop', context) feedback = QgsProcessingMultiStepFeedback(9 + maxdivide, model_feedback) feedback.setCurrentStep(1) if feedback.isCanceled(): return {} # 住所別集計 alg_params = { 'addresslayer': parameters['addresslayer'], 'addressfield': parameters['addressfield'], 'INPUT': csvfile, 'ENCODING': enc, 'CRS': None, 'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT } #Stat_CSVAddressPolygon outputs_statv = processing.run('QGIS_stat:Stat_CSVAddressPolygon', alg_params, context=context, feedback=feedback, is_child_algorithm=True) if feedback.isCanceled(): return {} statv = outputs_statv["OUTPUT"] meshid = meshidfields[0] # 人口メッシュと行政界メッシュのUnion作成する new_popfield = 'pv' param_uni = { 'addresslayer': statv, 'addressfield': parameters['addressfield'][0], 'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT, 'popmeshlayer': popmeshLayer, 'popmeshid': popmeshidfields[0], 'popmeshpop': popmeshpopfields[0], 'POPCOLUMN': new_popfield } feedback.setCurrentStep(2) res_uni = processing.run('QGIS_stat:UnionAdmAndPopMeshAlgorithm', param_uni, context=context, feedback=feedback, is_child_algorithm=True) if feedback.isCanceled(): return {} feedback.pushConsoleInfo("csvs 1 union ok ") # union pop polygon res_unit["OUTPUT"] # population pv # address parameters['addressfield'][0] # 行政界別人口の算出 feedback.setCurrentStep(3) param_pop = { 'inputlayer': res_uni['OUTPUT'], 'agfield': parameters['addressfield'], 'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT, # 'OUTPUT':parameters['OUTPUT'], 'cfield': new_popfield } res_adpop = processing.run('QGIS_stat:AggreagteValueAlgorithm', param_pop, context=context, feedback=feedback, is_child_algorithm=True) if feedback.isCanceled(): return {} feedback.pushConsoleInfo("csvs 1 caliculate pop adm ok ") # UNION mesh と 行政界別 人口の結合 feedback.setCurrentStep(4) param_join = { 'DISCARD_NONMATCHING': False, 'FIELD': parameters['addressfield'], 'FIELDS_TO_COPY': [], 'FIELD_2': parameters['addressfield'], 'INPUT': res_uni['OUTPUT'], 'INPUT_2': res_adpop['OUTPUT'], 'METHOD': 1, 'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT, #'OUTPUT':parameters['OUTPUT'], 'PREFIX': 'op' } res_join = processing.run('qgis:joinattributestable', param_join, context=context, feedback=feedback, is_child_algorithm=True) if feedback.isCanceled(): return {} feedback.pushConsoleInfo("csvs 1 join union mesh and popof adm ok ") # UNION MESH 人口 と行政界人口の比率算出 feedback.setCurrentStep(5) param_ratio = { 'FIELD_LENGTH': 12, 'FIELD_NAME': 'pvratio', 'FIELD_PRECISION': 6, 'FIELD_TYPE': 0, 'FORMULA': ' \"pv\" / \"oppv\" ', 'INPUT': res_join["OUTPUT"], #'OUTPUT':parameters['OUTPUT'] 'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT, } res_ratio = processing.run('qgis:fieldcalculator', param_ratio, context=context, feedback=feedback, is_child_algorithm=True) if feedback.isCanceled(): return {} feedback.pushConsoleInfo( "csvs 1 calc ratio of adm pop and union polygon population ok ") # Union mesh の想定集計値を算出する 住所別集計値 × ( UNION MESH 人口 と行政界人口の比率算出) feedback.setCurrentStep(6) param_ratio2 = { 'FIELD_LENGTH': 12, 'FIELD_NAME': 'pvsum', 'FIELD_PRECISION': 6, 'FIELD_TYPE': 0, 'FORMULA': ' \"snum\" * \"pvratio\" ', 'INPUT': res_ratio["OUTPUT"], #'OUTPUT':parameters['OUTPUT'] 'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT } res_ratio2 = processing.run('qgis:fieldcalculator', param_ratio2, context=context, feedback=feedback, is_child_algorithm=True) if feedback.isCanceled(): return {} feedback.pushConsoleInfo("csvs 1 calc ratio of research sample ok ") #results["OUTPUT"] = res_ratio2["OUTPUT"] #return results # 入力メッシュとUnionメッシュのUnion feedback.setCurrentStep(7) #results["OUTPUT"] = res_ratio['OUTPUT'] #return results # 入力UNIONメッシュの保存 # レイヤをGeoPackage化 cnv_paramsg = { 'LAYERS': res_ratio2["OUTPUT"], 'OVERWRITE': True, 'SAVE_STYLES': False, 'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT #'OUTPUT':parameters['OUTPUT'] } input_c = processing.run('native:package', cnv_paramsg, context=context, feedback=feedback, is_child_algorithm=True) feedback.pushConsoleInfo("csvs 1 cahnge to geopackage ok ") #results["OUTPUT"] = input_c["OUTPUT"] #return results # 集計用 人口+行政界 UNION input_union = input_c["OUTPUT"] feedback.setCurrentStep(8) # create union poplation mesh and input mesh param1 = { 'INPUT': input_union, 'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT, 'pareafield': 'div_area', 'polsmpl': 'pvsum', 'meshid': meshid, 'meshlayer': meshLayer } #parameters['OUTPUT'] # res1 = processing.run('QGIS_stat:AggregatePopMeshbyMeshAlgorithm', param1, context=context, feedback=feedback, is_child_algorithm=True) if feedback.isCanceled(): return {} feedback.pushConsoleInfo( "csvs 1 AggregatePopMeshbyMeshAlgorithm ok ") numberof_under_limit = 0 #numberof_under_limit = res1["LIMITPOL"] # レイヤをGeoPackage化 alg_paramsg = { 'LAYERS': res1["OUTPUT"], 'OVERWRITE': True, 'SAVE_STYLES': False, 'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT } retg1 = processing.run('native:package', alg_paramsg, context=context, feedback=feedback, is_child_algorithm=True) last_output = retg1["OUTPUT"] new_mesh = retg1["OUTPUT"] mesh_layb = retg1["OUTPUT"] if type(mesh_layb) is str: mesh_layb = QgsVectorLayer(mesh_layb, "mesh", "ogr") numberof_under_limit = 0 # 作業用レイヤの作成 crs_str = mesh_layb.crs() layerURI = "Polygon?crs=" + crs_str.authid() #feedback.pushConsoleInfo( "work layer " + layerURI ) resLayer = QgsVectorLayer(layerURI, "mesh_result", "memory") appended = {} adfields = [] for field in mesh_layb.fields(): #print(field.name(), field.typeName()) adfields.append(field) #resLayer.addField(field) resLayer.dataProvider().addAttributes(adfields) resLayer.updateFields() lower_ids = [] value_column = "snum" # limit 値より小さい値のポリゴン数算出 for f in mesh_layb.getFeatures(): # feedback.pushConsoleInfo( "value " +str( f["value"]) ) if not f[value_column] is None: if f[value_column] > 0 and f[value_column] < limit_sample: numberof_under_limit += 1 lower_ids.append(f[meshid]) next_output = None stepi = 9 # 集計結果が最小サンプルより小さいものがある場合 if numberof_under_limit > 0: # 初回の場合は終了 feedback.pushConsoleInfo("最初の集計で指定値以下の集計値がありましたので集計を中止しました") results["OUTPUT"] = None return results if uneven_div: rmid = [] for tgid in (lower_ids): feedback.pushConsoleInfo("lower id " + str(tgid)) # next_output code の下3桁 削除 C27210-02 -> C27210 が last_output の code 番号 # next_output では last_output が同じ番号の最大4メッシュを削除する # リミットより小さいレコードは旧レコードを退避 # リミットにひっかかるレコードを再処理用リストから削除(同一親メッシュのものも削除) # 不均等分割でリミット以下のデータがある場合は last_output -> 分割不能抽出 next_output 分割不能削除 next_output -> last_output 代入 parent_code = tgid[0:-3] rmid.append(parent_code) addfeatures = [] alg_paramsg_n = { 'LAYERS': last_output, 'OVERWRITE': False, 'SAVE_STYLES': False, 'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT } lmesh = processing.run('native:package', alg_paramsg_n, context=context, feedback=feedback, is_child_algorithm=True) last_output = lmesh["OUTPUT"] if type(last_output) is str: last_output = QgsVectorLayer(last_output, "mesh", "ogr") last_output.selectAll() for lf in last_output.getFeatures(): for pcode in (rmid): # feedback.pushConsoleInfo( "pcode " + pcode+ " meshid =" + lf[meshid] ) if lf[meshid] == pcode: lf["fid"] = None if not lf[value_column]: lf[value_column] = 0.0 if lf[meshid] not in appended: addfeatures.append(lf) appended[lf[meshid]] = lf # feedback.pushConsoleInfo( "add feature " + pcode ) resLayer.dataProvider().addFeatures(addfeatures) deleteFeatures = [] if type(next_output) is str: next_output = QgsVectorLayer(next_output, "mesh", "ogr") # add check 20210310 if next_output is None: feedback.pushConsoleInfo("no next array") else: for nf in next_output.getFeatures(): for pcode in (rmid): if nf[meshid][0:-3] == pcode: deleteFeatures.append(nf.id()) feedback.pushConsoleInfo("delete id " + str(pcode)) next_output.dataProvider().deleteFeatures(deleteFeatures) last_output = next_output # 分割回数ループ for divide_c in range(1, maxdivide): feedback.setCurrentStep(stepi) stepi = stepi + 1 if numberof_under_limit > 0: # 均等分割の場合は終了 if not uneven_div: break if last_output is None: feedback.pushConsoleInfo("last output is none") else: if type(last_output) is str: feedback.pushConsoleInfo("last output " + last_output) else: feedback.pushConsoleInfo("last output " + last_output.name()) alg_paramsg_m = { 'LAYERS': last_output, 'OVERWRITE': True, 'SAVE_STYLES': False, 'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT } spmesh = processing.run('native:package', alg_paramsg_m, context=context, feedback=feedback, is_child_algorithm=True) new_mesh = agtools.SplitMeshLayer(spmesh["OUTPUT"], meshid) # statv 行政界別集計データ # 再度メッシュ集計 param2 = { 'INPUT': input_union, 'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT, 'pareafield': 'div_area', 'polsmpl': 'pvsum', 'meshid': meshid, 'meshlayer': new_mesh } res2 = processing.run('QGIS_stat:AggregatePopMeshbyMeshAlgorithm', param2, context=context, feedback=feedback, is_child_algorithm=True) #numberof_under_limit = res2["LIMITPOL"] numberof_under_limit = 0 # レイヤをGeoPackage化 alg_paramsg2 = { 'LAYERS': res2["OUTPUT"], 'OVERWRITE': True, 'SAVE_STYLES': False, 'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT } retg2 = processing.run('native:package', alg_paramsg2, context=context, feedback=feedback, is_child_algorithm=True) mesh_layb = retg2["OUTPUT"] if type(mesh_layb) is str: mesh_layb = QgsVectorLayer(mesh_layb, "mesh", "ogr") #features = mesh_layb.selectedFeatures() #feedback.pushConsoleInfo( "feature count " +str( len(features)) ) lower_ids = [] for f in mesh_layb.getFeatures(): # feedback.pushConsoleInfo( "value " +str( f["value"]) ) if not f[value_column] is None: if f[value_column] > 0 and f[value_column] < limit_sample: numberof_under_limit += 1 lower_ids.append(f[meshid]) if numberof_under_limit == 0: last_output = res2["OUTPUT"] next_output = retg2["OUTPUT"] else: # 不均等分割でリミット以下のデータがある場合は last_output -> 分割不能抽出 next_output 分割不能削除 next_output -> last_output 代入 # last_output = res2["OUTPUT"] next_output = retg2["OUTPUT"] # 集計結果が最小サンプルより小さいものがある場合 if numberof_under_limit > 0: # 均等分割の場合は終了 if not uneven_div: break # 不均等分割の場合は終了データを保全 それ以外のメッシュの分割 else: rmid = [] for tgid in (lower_ids): feedback.pushConsoleInfo("lower id " + str(tgid)) # next_output code の下3桁 削除 C27210-02 -> C27210 が last_output の code 番号 # next_output では last_output が同じ番号の最大4メッシュを削除する # リミットより小さいレコードは旧レコードを退避 # リミットにひっかかるレコードを再処理用リストから削除(同一親メッシュのものも削除) # 不均等分割でリミット以下のデータがある場合は last_output -> 分割不能抽出 next_output 分割不能削除 next_output -> last_output 代入 parent_code = tgid[0:-3] rmid.append(parent_code) addfeatures = [] #if type(last_output) is str: # last_output = QgsVectorLayer(last_output, "mesh", "ogr") alg_paramsg_n = { 'LAYERS': last_output, 'OVERWRITE': False, 'SAVE_STYLES': False, 'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT } lmesh = processing.run('native:package', alg_paramsg_n, context=context, feedback=feedback, is_child_algorithm=True) #last_output.removeSelection() last_output = lmesh["OUTPUT"] if type(last_output) is str: last_output = QgsVectorLayer(last_output, "mesh", "ogr") last_output.selectAll() for lf in last_output.getFeatures(): for pcode in (rmid): # feedback.pushConsoleInfo( "pcode " + pcode+ " meshid =" + lf[meshid] ) if lf[meshid] == pcode: lf["fid"] = None if not lf[value_column]: lf[value_column] = 0.0 if lf[meshid] not in appended: addfeatures.append(lf) appended[lf[meshid]] = lf #addfeatures.append(lf) feedback.pushConsoleInfo("add feature " + pcode) resLayer.dataProvider().addFeatures(addfeatures) deleteFeatures = [] if type(next_output) is str: next_output = QgsVectorLayer(next_output, "mesh", "ogr") for nf in next_output.getFeatures(): for pcode in (rmid): if nf[meshid][0:-3] == pcode: deleteFeatures.append(nf.id()) feedback.pushConsoleInfo("delete id " + str(pcode)) next_output.dataProvider().deleteFeatures(deleteFeatures) last_output = next_output # Return the results of the algorithm. In this case our only result is # the feature sink which contains the processed features, but some # algorithms may return multiple feature sinks, calculated numeric # statistics, etc. These should all be included in the returned # dictionary, with keys matching the feature corresponding parameter # or output names. # 不均等分割の場合 最終作業レイヤの地物がはいってないかも if uneven_div: alg_paramsg_n = { 'LAYERS': next_output, 'OVERWRITE': False, 'SAVE_STYLES': False, 'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT } lmesh = processing.run('native:package', alg_paramsg_n, context=context, feedback=feedback, is_child_algorithm=True) #last_output.removeSelection() last_output = lmesh["OUTPUT"] if type(last_output) is str: last_output = QgsVectorLayer(last_output, "mesh", "ogr") last_output.selectAll() addfeatures = [] for lf in last_output.getFeatures(): feedback.pushConsoleInfo("add features meshid =" + lf[meshid]) lf["fid"] = None if not lf[value_column]: lf[value_column] = 0.0 if lf[meshid] not in appended: addfeatures.append(lf) appended[lf[meshid]] = lf #addfeatures.append(lf) resLayer.dataProvider().addFeatures(addfeatures) # フォーマット変換(gdal_translate) alg_params = { 'INPUT': resLayer, 'OPTIONS': '', 'OUTPUT': parameters['OUTPUT'] } ocv = processing.run('gdal:convertformat', alg_params, context=context, feedback=feedback, is_child_algorithm=True) results["OUTPUT"] = ocv["OUTPUT"] return results # 均等分割の場合 else: # フォーマット変換(gdal_translate) alg_params = { 'INPUT': last_output, 'OPTIONS': '', 'OUTPUT': parameters['OUTPUT'] } ocv = processing.run('gdal:convertformat', alg_params, context=context, feedback=feedback, is_child_algorithm=True) results["OUTPUT"] = ocv["OUTPUT"] return results
destCrs = QgsCoordinateReferenceSystem(local_utm) tr = QgsCoordinateTransform(sourceCrs, destCrs, QgsProject.instance()) droneLocation.transform(tr) print("utm Lat", droneLocation.y()) print("utm Lon", droneLocation.x()) # create nadir layer nadirGeometry = QgsGeometry.fromPointXY( QgsPointXY(droneLocation.x(), droneLocation.y())) nadirLayer = QgsVectorLayer('Point?crs={}'.format(local_utm), 'nadir', 'memory') provider = nadirLayer.dataProvider() feature = QgsFeature() feature.setGeometry(nadirGeometry) provider.addFeatures([feature]) existingLayer = QgsProject.instance().mapLayersByShortName(nadirLayer.name()) if existingLayer: QgsProject.instance().removeMapLayer(existingLayer[0]) QgsProject.instance().addMapLayer(nadirLayer) #altitude_from_sealevel = exifTags['GPS GPSAltitude'].values[0].num / exifTags['GPS GPSAltitude'].values[0].den realFocalLength = exifTags['EXIF FocalLength'].values[0].num / exifTags[ 'EXIF FocalLength'].values[0].den teoreticFocalLength = exifTags['EXIF FocalLengthIn35mmFilm'].values[0] #print("GPSAltitude", GPSAltitude) print("realFocalLength", realFocalLength) print("35mmFocalLegth = ", teoreticFocalLength) exifImageWidth = exifTags['EXIF ExifImageWidth'].values[0] exifImageLength = exifTags['EXIF ExifImageLength'].values[0] imageRatio = float(exifImageWidth) / float(exifImageLength)
def geojson_to_memory(path, name): my_WkbType = { 'Unknown': 0, 'Point': 1, 'LineString': 2, 'Polygon': 3, 'MultiPoint': 4, 'MultiLineString': 5, 'MultiPolygon': 6, 'NoGeometry': 7, 'Point25D': 8, 'LineString25D': 9, 'Polygon25D': 10, 'MultiPoint25D': 11, 'MultiLineString25D': 12, 'MultiPolygon25D': 13} # for i,j in my_WkbType.items(): # #print i + " : " + str(j) my_rev_WkbType = {v: k for k, v in my_WkbType.items()} # for i,j in my_WkbType.items(): # #print i + " : " + str(j) #print 'Path to geojson: %s' % path input_layer=QgsVectorLayer(path, "input_layer", "ogr") print 'path: %s' % path print 'input_layer %s' % input_layer.name() dp = input_layer.dataProvider() QGisWKBType = dp.geometryType() #print 'QGisWKBType: ' + str(QGisWKBType) EPSG_code = int(dp.crs().authid().split(":")[1]) print str(EPSG_code) destination_layer = QgsVectorLayer( my_rev_WkbType[QGisWKBType] + '?crs=epsg:' + str(EPSG_code) + '&index=yes', name, 'memory') destination_layer_data_provider = destination_layer.dataProvider() input_layer_attrib_names = input_layer.dataProvider().fields() oldattributeList = input_layer.dataProvider().fields().toList() newattributeList = [] for attrib in oldattributeList: if destination_layer.fieldNameIndex(attrib.name()) == -1: newattributeList.append(QgsField(attrib.name(), attrib.type())) destination_layer_data_provider.addAttributes(newattributeList) destination_layer.updateFields() destination_layer.startEditing() # cfeature = QgsFeature() cfeatures = [] xfeatures = input_layer.getFeatures() for xfeature in xfeatures: xgeometry = xfeature.geometry() cfeature_Attributes = [] cfeature_Attributes.extend(xfeature.attributes()) cfeature = QgsFeature() cfeature.setGeometry(xgeometry) cfeature.setAttributes(cfeature_Attributes) cfeatures.append(cfeature) destination_layer.addFeatures(cfeatures) destination_layer.commitChanges() return destination_layer
class TestQgsLayerTreeView(unittest.TestCase): def __init__(self, methodName): """Run once on class initialization.""" unittest.TestCase.__init__(self, methodName) # setup a dummy project self.project = QgsProject() self.layer = QgsVectorLayer("Point?field=fldtxt:string", "layer1", "memory") self.layer2 = QgsVectorLayer("Point?field=fldtxt:string", "layer2", "memory") self.layer3 = QgsVectorLayer("Point?field=fldtxt:string", "layer3", "memory") self.layer4 = QgsVectorLayer("Point?field=fldtxt:string", "layer4", "memory") self.layer5 = QgsVectorLayer("Point?field=fldtxt:string", "layer5", "memory") self.project.addMapLayers([self.layer, self.layer2, self.layer3]) self.model = QgsLayerTreeModel(self.project.layerTreeRoot()) def nodeOrder(self, group): nodeorder = [] layerTree = QgsLayerTree() for node in group: if QgsLayerTree.isGroup(node): groupname = node.name() nodeorder.append(groupname) for child in self.nodeOrder(node.children()): nodeorder.append(groupname + '-' + child) elif QgsLayerTree.isLayer(node): nodeorder.append(node.layer().name()) return nodeorder def testSetModel(self): view = QgsLayerTreeView() # should not work string_list_model = QStringListModel() view.setModel(string_list_model) self.assertFalse(view.model()) # should work view.setModel(self.model) self.assertEqual(view.model(), self.model) def testSetCurrentLayer(self): view = QgsLayerTreeView() view.setModel(self.model) current_layer_changed_spy = QSignalSpy(view.currentLayerChanged) self.assertFalse(view.currentLayer()) view.setCurrentLayer(self.layer3) self.assertEqual(view.currentLayer(), self.layer3) self.assertEqual(len(current_layer_changed_spy), 1) view.setCurrentLayer(self.layer) self.assertEqual(view.currentLayer(), self.layer) self.assertEqual(len(current_layer_changed_spy), 2) view.setCurrentLayer(None) self.assertFalse(view.currentLayer()) self.assertEqual(len(current_layer_changed_spy), 3) def testDefaultActions(self): view = QgsLayerTreeView() view.setModel(self.model) actions = QgsLayerTreeViewDefaultActions(view) # show in overview action view.setCurrentLayer(self.layer) self.assertEqual(view.currentNode().customProperty('overview', 0), False) show_in_overview = actions.actionShowInOverview() show_in_overview.trigger() self.assertEqual(view.currentNode().customProperty('overview', 0), True) show_in_overview.trigger() self.assertEqual(view.currentNode().customProperty('overview', 0), False) def testMoveOutOfGroupActionLayer(self): """Test move out of group action on layer""" view = QgsLayerTreeView() group = self.project.layerTreeRoot().addGroup("embeddedgroup") group.addLayer(self.layer4) group.addLayer(self.layer5) groupname = group.name() view.setModel(self.model) actions = QgsLayerTreeViewDefaultActions(view) self.assertEqual( self.nodeOrder(self.project.layerTreeRoot().children()), [ self.layer.name(), self.layer2.name(), self.layer3.name(), groupname, groupname + '-' + self.layer4.name(), groupname + '-' + self.layer5.name(), ]) view.setCurrentLayer(self.layer5) moveOutOfGroup = actions.actionMoveOutOfGroup() moveOutOfGroup.trigger() self.assertEqual( self.nodeOrder(self.project.layerTreeRoot().children()), [ self.layer.name(), self.layer2.name(), self.layer3.name(), self.layer5.name(), groupname, groupname + '-' + self.layer4.name(), ]) def testMoveToTopActionLayer(self): """Test move to top action on layer""" view = QgsLayerTreeView() view.setModel(self.model) actions = QgsLayerTreeViewDefaultActions(view) self.assertEqual(self.project.layerTreeRoot().layerOrder(), [self.layer, self.layer2, self.layer3]) view.setCurrentLayer(self.layer3) movetotop = actions.actionMoveToTop() movetotop.trigger() self.assertEqual(self.project.layerTreeRoot().layerOrder(), [self.layer3, self.layer, self.layer2]) def testMoveToTopActionGroup(self): """Test move to top action on group""" view = QgsLayerTreeView() group = self.project.layerTreeRoot().addGroup("embeddedgroup") group.addLayer(self.layer4) group.addLayer(self.layer5) groupname = group.name() view.setModel(self.model) actions = QgsLayerTreeViewDefaultActions(view) self.assertEqual( self.nodeOrder(self.project.layerTreeRoot().children()), [ self.layer.name(), self.layer2.name(), self.layer3.name(), groupname, groupname + '-' + self.layer4.name(), groupname + '-' + self.layer5.name(), ]) nodeLayerIndex = self.model.node2index(group) view.setCurrentIndex(nodeLayerIndex) movetotop = actions.actionMoveToTop() movetotop.trigger() self.assertEqual( self.nodeOrder(self.project.layerTreeRoot().children()), [ groupname, groupname + '-' + self.layer4.name(), groupname + '-' + self.layer5.name(), self.layer.name(), self.layer2.name(), self.layer3.name(), ]) def testMoveToTopActionEmbeddedGroup(self): """Test move to top action on embeddedgroup layer""" view = QgsLayerTreeView() group = self.project.layerTreeRoot().addGroup("embeddedgroup") group.addLayer(self.layer4) group.addLayer(self.layer5) groupname = group.name() view.setModel(self.model) actions = QgsLayerTreeViewDefaultActions(view) self.assertEqual( self.nodeOrder(self.project.layerTreeRoot().children()), [ self.layer.name(), self.layer2.name(), self.layer3.name(), groupname, groupname + '-' + self.layer4.name(), groupname + '-' + self.layer5.name(), ]) view.setCurrentLayer(self.layer5) movetotop = actions.actionMoveToTop() movetotop.trigger() self.assertEqual( self.nodeOrder(self.project.layerTreeRoot().children()), [ self.layer.name(), self.layer2.name(), self.layer3.name(), groupname, groupname + '-' + self.layer5.name(), groupname + '-' + self.layer4.name(), ])
class UgQgis(object): """ interfaces an UnstructuredGrid object and Qgis layers """ def __init__(self,g): self.g = self.extend_grid(g) self.install_edge_quality() def install_edge_quality(self): if 'edge_quality' not in self.g.edges.dtype.names: edge_q=np.zeros(self.g.Nedges(),'f8') self.g.add_edge_field('edge_quality',edge_q) self.update_edge_quality() def update_edge_quality(self,edges=None): # First part is calculating the values if edges is None: edges=slice(None) g=self.g vc=g.cells_center() ec=g.edges_center() g.edge_to_cells() c2c=dist( vc[g.edges['cells'][edges,0]] - vc[g.edges['cells'][edges,1]] ) A=g.cells_area() Acc= A[g.edges['cells'][edges,:]].sum(axis=1) c2c=c2c / np.sqrt(Acc) # normalized c2c[ np.any(g.edges['cells'][edges,:]<0,axis=1) ] = np.inf g.edges['edge_quality'][edges]=c2c def extend_grid(self,g): g.add_node_field('feat_id',np.zeros(g.Nnodes(),'i4')-1) g.add_edge_field('feat_id',np.zeros(g.Nedges(),'i4')-1) g.add_cell_field('feat_id',np.zeros(g.Ncells(),'i4')-1) # install grid callbacks: if 1: # re-enabled. DBG - temp. disabled g.subscribe_after('modify_node',self.on_modify_node) g.subscribe_after('add_node',self.on_add_node) g.subscribe_after('add_edge',self.on_add_edge) g.subscribe_after('add_cell',self.on_add_cell) g.subscribe_before('delete_edge',self.on_delete_edge) g.subscribe_before('delete_node',self.on_delete_node) g.subscribe_before('delete_cell',self.on_delete_cell) return g def on_delete_node(self,g,func_name,n,**k): # self.log('got signal for delete node') self.nl.dataProvider().deleteFeatures([self.g.nodes['feat_id'][n]]) self.nl.triggerRepaint() def on_delete_edge(self,g,func_name,j,**k): # self.log('got signal for delete edge') self.el.dataProvider().deleteFeatures([self.g.edges['feat_id'][j]]) self.el.triggerRepaint() def on_delete_cell(self,g,func_name,c,**k): # this one isn't working, while the others are... feat_id=self.g.cells['feat_id'][c] self.log('got signal for delete cell %d, feat_id %s'%(c,feat_id)) self.cl.dataProvider().deleteFeatures([feat_id]) self.cl.triggerRepaint() # Callbacks installed on the grid # instrument the grid to propagate changes back to the UI def on_modify_node(self,g,func_name,n,**k): if 'x' in k: fid=self.g.nodes[n]['feat_id'] geom=self.node_geometry(n) self.nl.dataProvider().changeGeometryValues({fid:geom}) self.nl.triggerRepaint() # update cells first, so that edge_quality has fresh # cell center and area information cell_changes={} cells=self.g.node_to_cells(n) self.g.cells_center(refresh=cells) self.g.cells['_area'][cells]=np.nan # trigger recalc. cell_edges=set() for i in cells: # this was all sorts of messed up - don't understand how # it was working at all before... fid=self.g.cells[i]['feat_id'] geom=self.cell_geometry(i) cell_changes[fid]=geom cell_edges.update(self.g.cell_to_edges(i)) self.cl.dataProvider().changeGeometryValues(cell_changes) self.cl.triggerRepaint() edge_geom_changes={} # edge centers are not cached at this point, so don't # need to update them... for j in self.g.node_to_edges(n): fid=self.g.edges[j]['feat_id'] geom=self.edge_geometry(j) edge_geom_changes[fid]=geom self.el.dataProvider().changeGeometryValues(edge_geom_changes) # Edges for which a node or cell has changed: # this doesn't seem to be working now. edge_attr_changes={} edge_quality_idx=[i for i,attr in enumerate(self.e_attrs) if attr.name()=='edge_quality'][0] js=list(cell_edges) self.update_edge_quality(js) for j in js: # and update edge quality field - would be nice # to come up with a nice abstraction here... fid=self.g.edges[j]['feat_id'] edge_attr_changes[fid]={edge_quality_idx:float(self.g.edges[j]['edge_quality'])} self.el.dataProvider().changeAttributeValues(edge_attr_changes) self.el.triggerRepaint() def on_add_node(self,g,func_name,return_value,**k): n=return_value geom=self.node_geometry(n) feat = QgsFeature() # can't set feature_ids feat.setGeometry(geom) (res, outFeats) = self.nl.dataProvider().addFeatures([feat]) self.g.nodes['feat_id'][n] = outFeats[0].id() self.nl.triggerRepaint() def on_add_edge(self,g,func_name,return_value,**k): j=return_value feat=QgsFeature() feat.setGeometry(self.edge_geometry(j)) (res,outFeats) = self.el.dataProvider().addFeatures([feat]) self.g.edges['feat_id'][j] = outFeats[0].id() self.el.triggerRepaint() def on_add_cell(self,g,func_name,return_value,**k): c=return_value self.log('got signal for add cell') geom=self.cell_geometry(c) feat = QgsFeature() # can't set feature_ids feat.setGeometry(geom) (res, outFeats) = self.cl.dataProvider().addFeatures([feat]) self.g.cells['feat_id'][c] = outFeats[0].id() self.cl.triggerRepaint() def node_geometry(self,n): return QgsGeometry.fromPoint(QgsPoint(self.g.nodes['x'][n,0], self.g.nodes['x'][n,1])) def populate_nodes(self): layer=self.nl layer.dataProvider().deleteFeatures(layer.allFeatureIds()) # takes an existing point memory layer, adds in nodes from g feats=[] valid=[] for n in range(self.g.Nnodes()): valid.append(n) geom = self.node_geometry(n) feat = QgsFeature() # can't set feature_ids feat.setGeometry(geom) feats.append(feat) (res, outFeats) = layer.dataProvider().addFeatures(feats) self.g.nodes['feat_id'][valid] = [f.id() for f in outFeats] return res # callbacks from Qgis layers def on_node_geometry_changed(self,feat_id,geom): xy=geom.asPoint() # this should be sped up with a hash table n=np.nonzero( self.g.nodes['feat_id']==feat_id )[0][0] self.g.modify_node(n,x=xy) def edge_geometry(self,j): seg=self.g.nodes['x'][self.g.edges['nodes'][j]] pnts=[QgsPoint(seg[0,0],seg[0,1]), QgsPoint(seg[1,0],seg[1,1])] return QgsGeometry.fromPolyline(pnts) def populate_edges(self): layer=self.el layer.dataProvider().deleteFeatures(layer.allFeatureIds()) # takes an existing line memory layer, adds in nodes from g feats=[] valid=[] for j in self.g.valid_edge_iter(): geom=self.edge_geometry(j) valid.append(j) feat = QgsFeature() feat.initAttributes(len(self.e_attrs)) for idx,eattr in enumerate(self.e_attrs): name=eattr.name() typecode=eattr.type() if name=='edge_id': feat.setAttribute(idx,j) elif name=='c0': feat.setAttribute(idx,int(self.g.edges['cells'][j,0])) elif name=='c1': feat.setAttribute(idx,int(self.g.edges['cells'][j,1])) elif typecode==2: # integer feat.setAttribute(idx,int(self.g.edges[name][j])) elif typecode==6: # double feat.setAttribute(idx,float(self.g.edges[name][j])) else: continue # QGIS doesn't know about numpy types # feat.setAttribute(3,int(self.g.edges['mark'][j])) feat.setGeometry(geom) feats.append(feat) (res, outFeats) = layer.dataProvider().addFeatures(feats) self.g.edges['feat_id'][valid]=[f.id() for f in outFeats] return res def cell_geometry(self,i): pnts=[QgsPoint(self.g.nodes['x'][n,0], self.g.nodes['x'][n,1]) for n in self.g.cell_to_nodes(i)] return QgsGeometry.fromPolygon([pnts]) def populate_cells(self): layer=self.cl layer.dataProvider().deleteFeatures(layer.allFeatureIds()) # takes an existing line memory layer, adds in nodes from g feats=[] valid=[] for i in self.g.valid_cell_iter(): geom=self.cell_geometry(i) feat = QgsFeature() feat.setGeometry(geom) feats.append(feat) valid.append(i) (res, outFeats) = layer.dataProvider().addFeatures(feats) self.g.cells['feat_id'][valid]=[f.id() for f in outFeats] return res def clear_layers(self,canvas): # more for development - clear out old layers lr=QgsMapLayerRegistry.instance() layers=lr.mapLayers() to_remove=[] for layer_key in layers.keys(): if ( layer_key.startswith('edges') or layer_key.startswith('cells') or layer_key.startswith('nodes') ): to_remove.append(layer_key) lr.removeMapLayers( to_remove ) def on_node_layer_deleted(self): self.nl=None self.log("signal received: node layer deleted") # to avoid confusion, let the node layer removal trigger # everything, at least for now. self.graceful_deactivate() def on_edge_layer_deleted(self): self.el=None self.log("signal received: edge layer deleted") def on_cell_layer_deleted(self): self.cl=None self.log("signal received: cell layer deleted") # create the memory layers and populate accordingly def populate_all(self,iface): canvas=iface.mapCanvas() self.iface=iface self.clear_layers(canvas) crs="?crs=epsg:26910" # was 4326 # create layer self.nl = QgsVectorLayer("Point"+crs, "nodes", "memory") self.el = QgsVectorLayer("LineString"+crs,"edges","memory") self.cl = QgsVectorLayer("Polygon"+crs,"cells","memory") self.nl.layerDeleted.connect(self.on_node_layer_deleted) self.el.layerDeleted.connect(self.on_edge_layer_deleted) self.cl.layerDeleted.connect(self.on_cell_layer_deleted) pr = self.el.dataProvider() # add fields - eventually would be tied in with g.edge_dtype e_attrs=[QgsField("edge_id",QVariant.Int)] for fidx,fdesc in enumerate(self.g.edge_dtype.descr): # descr gives string reprs of the types, use dtype # to get back to an object. fname=fdesc[0] ; ftype=np.dtype(fdesc[1]) if len(fdesc)>2: fshape=fdesc[2] else: fshape=None if fname=='nodes': continue elif fname=='cells': e_attrs += [QgsField("c0", QVariant.Int), QgsField("c1", QVariant.Int)] else: if np.issubdtype(ftype,np.int): e_attrs.append( QgsField(fname,QVariant.Int) ) elif np.issubdtype(ftype,np.float): e_attrs.append( QgsField(fname,QVariant.Double) ) else: self.log("Not read other datatypes") self.e_attrs=e_attrs pr.addAttributes(e_attrs) self.el.updateFields() # tell the vector layer to fetch changes from the provider self.populate_nodes() self.populate_edges() self.populate_cells() # Create a group for the layers - li=iface.legendInterface() grp_name="grid001" for gidx,gname in enumerate(li.groups()): if gname==grp_name: li.removeGroup(gidx) group_index=li.addGroup("grid001") for layer in [self.cl,self.el,self.nl]: # add layer to the registry QgsMapLayerRegistry.instance().addMapLayer(layer) li.moveLayer(layer,group_index) # if this is omitted, be sure to also skip over # the disconnects. li.currentLayerChanged.connect(self.on_layer_changed) # set extent to the extent of our layer # skip while developing # canvas.setExtent(layer.extent()) self.tool=UgEditTool(canvas,self) canvas.setMapTool(self.tool) def graceful_deactivate(self): self.log("UgQgis deactivating") li=self.iface.legendInterface() li.currentLayerChanged.disconnect(self.on_layer_changed) self.log("currentLayerChanged callback disconnected") # remove map tool from the canvas canvas=self.iface.mapCanvas() if canvas.mapTool() == self.tool: self.log("active map tool is ours - how to remove??") self.tool=None # remove callbacks from the grid: self.log("Not ready for removing callbacks from the grid") def on_layer_changed(self,layer): if layer is not None: # Not sure why, but using layer.id() was triggering an error # about the layer being deleted. Hmm - this is still somehow # related to an error about the layer being deleted. self.log("About to check names") if layer.name()==self.nl.name(): # this happens, but doesn't seem to succeed self.log("Setting map tool to ours") self.iface.mapCanvas().setMapTool(self.tool) self.log("Done with setting map tool to ours") else: self.log("on_layer_changed, but to id=%s"%layer.name()) self.log("My node name=%s"%self.nl.name()) def log(self,s): with open(os.path.join(os.path.dirname(__file__),'log'),'a') as fp: fp.write(s+"\n") fp.flush()