def _load_editor_dialog(self, recid, rownumber): ''' Load editor dialog based on the selected model instance with the given ID. ''' model_obj = self._model_from_id(recid, rownumber) # show GPS editor if geometry if self._entity.has_geometry_column(): self.sp_unit_manager.active_layer_source() gps_tool = GPSToolDialog(iface, self._entity, self._entity.name, self.sp_unit_manager.active_sp_col, model=model_obj, reload=False, row_number=rownumber, entity_browser=self) editor_trans = self.tr('Editor') title = u'{0} {1}'.format(format_name(self._entity.short_name), editor_trans) gps_tool.setWindowTitle(title) result = gps_tool.exec_() else: #Load editor dialog edit_entity_dlg = self._editor_dlg( self._entity, model=model_obj, parent=self, parent_entity=self.parent_entity) result = edit_entity_dlg.exec_() if result == QDialog.Accepted: if self._entity.has_geometry_column(): edit_entity_dlg = gps_tool.entity_editor updated_model_obj = edit_entity_dlg.model() if not edit_entity_dlg.is_valid: return for i, attr in enumerate(self._entity_attrs): prop_idx = self._tableModel.index(rownumber, i) attr_val = getattr(updated_model_obj, attr) ''' Check if there are display formatters and apply if one exists for the given attribute. ''' if attr in self._cell_formatters: formatter = self._cell_formatters[attr] attr_val = formatter.format_column_value(attr_val) self._tableModel.setData(prop_idx, attr_val)
def _load_editor_dialog(self, recid, rownumber): ''' Load editor dialog based on the selected model instance with the given ID. ''' model_obj = self._model_from_id(recid, rownumber) # show GPS editor if geometry if self._entity.has_geometry_column(): self.sp_unit_manager.active_layer_source() gps_tool = GPSToolDialog( iface, self._entity, self._entity.name, self.sp_unit_manager.active_sp_col, model=model_obj, reload=False, row_number=rownumber, entity_browser=self ) result = gps_tool.exec_() else: #Load editor dialog edit_entity_dlg = self._editor_dlg(self._entity, model=model_obj, parent=self, parent_entity=self.parent_entity, plugin=self.plugin) result = edit_entity_dlg.exec_() if result == QDialog.Accepted: if self._entity.has_geometry_column(): edit_entity_dlg = gps_tool.entity_editor updated_model_obj = edit_entity_dlg.model() if not edit_entity_dlg.is_valid: return for i, attr in enumerate(self._entity_attrs): prop_idx = self._tableModel.index(rownumber, i) attr_val = getattr(updated_model_obj, attr) ''' Check if there are display formatters and apply if one exists for the given attribute. ''' if attr in self._cell_formatters: formatter = self._cell_formatters[attr] attr_val = formatter.format_column_value(attr_val) self._tableModel.setData(prop_idx, attr_val)
def onNewEntity(self): ''' Load editor dialog for adding a new record. ''' self._notifBar.clear() if not self._can_add_edit(): msg = QApplication.translate( 'EntityBrowserWithEditor', 'There are no user-defined columns for this entity.') self._notifBar.insertErrorNotification(msg) return if self._entity.has_geometry_column(): self.sp_unit_manager.active_layer_source() gps_tool = GPSToolDialog(iface, self._entity, self._entity.name, self.sp_unit_manager.active_sp_col, reload=False, entity_browser=self) editor_trans = self.tr('Editor') title = u'{0} {1}'.format(format_name(self._entity.short_name), editor_trans) gps_tool.setWindowTitle(title) result = gps_tool.exec_() result = False # a workaround to avoid duplicate model insert self.addEntityDlg = gps_tool.entity_editor else: self.addEntityDlg = self._editor_dlg( self._entity, parent=self, parent_entity=self.parent_entity) self.addEntityDlg.addedModel.connect(self.on_save_and_new) result = self.addEntityDlg.exec_() if result == QDialog.Accepted: model_obj = self.addEntityDlg.model() if self.addEntityDlg.is_valid: if self.parent_entity is None: self.addModelToView(model_obj) self.recomputeRecordCount()
def onNewEntity(self): ''' Load editor dialog for adding a new record. ''' self._notifBar.clear() if not self._can_add_edit(): msg = QApplication.translate( 'EntityBrowserWithEditor', 'There are no user-defined columns for this entity.' ) self._notifBar.insertErrorNotification(msg) return if self._entity.has_geometry_column(): self.sp_unit_manager.active_layer_source() gps_tool = GPSToolDialog( iface, self._entity, self._entity.name, self.sp_unit_manager.active_sp_col, reload=False, entity_browser=self ) result = gps_tool.exec_() result = False # a workaround to avoid duplicate model insert self.addEntityDlg = gps_tool.entity_editor else: self.addEntityDlg = self._editor_dlg( self._entity, parent=self, parent_entity=self.parent_entity, plugin=self.plugin ) self.addEntityDlg.addedModel.connect(self.on_save_and_new) result = self.addEntityDlg.exec_() if result == QDialog.Accepted: model_obj = self.addEntityDlg.model() if self.addEntityDlg.is_valid: if self.parent_entity is None: self.addModelToView(model_obj) self.recomputeRecordCount()
def import_gpx_file(self): """ Method to load GPS dialog """ source_status = self.active_layer_source() layer_map = QgsProject.instance().mapLayers() error_title = QApplication.translate( 'SpatialUnitManagerDockWidget', 'GPS Feature Import Loading Error') if len(layer_map) > 0: if source_status is None: QMessageBox.critical( self, error_title, QApplication.translate( 'SpatialUnitManagerDockWidget', 'You have not selected a layer.\n ' 'Please select a valid layer to import GPS features.')) elif source_status is False: QMessageBox.critical( self, error_title, QApplication.translate( 'SpatialUnitManagerDockWidget', 'You have selected a non-STDM entity layer.\n ' 'Please select a valid layer to import GPS features.')) elif source_status is True: self.gps_tool_dialog = GPSToolDialog(self.iface, self.active_entity, self.active_table, self.active_sp_col) self.gps_tool_dialog.show() else: QMessageBox.critical( self, error_title, QApplication.translate( 'SpatialUnitManagerDockWidget', 'You must add an entity layer from Spatial Unit Manager\n' 'and select it to import GPS Features.'))
class SpatialUnitManagerDockWidget(WIDGET, BASE): onLayerAdded = pyqtSignal(str, object) def __init__(self, iface, plugin=None): QDockWidget.__init__(self, iface.mainWindow()) # Set up the user interface from Designer. self.setupUi(self) self.iface = iface self._plugin = plugin self.gps_tool_dialog = None # properties of last added layer self.curr_lyr_table = None self.curr_lyr_sp_col = None # properties of the active layer self.active_entity = None self.active_table = None self.active_sp_col = None self.style_updated = None self.setMaximumHeight(300) self._curr_profile = current_profile() self._profile_spatial_layers = [] self.stdm_fields = STDMFieldWidget(plugin) self._populate_layers() self._adjust_layer_drop_down_width() self.spatial_unit = None self.iface.currentLayerChanged.connect(self.control_digitize_toolbar) self.onLayerAdded.connect(self.init_spatial_form) self.add_to_canvas_button.clicked.connect( self.on_add_to_canvas_button_clicked) self.set_display_name_button.clicked.connect( self.set_display_name_button_clicked) self.import_gpx_file_button.clicked.connect(self.import_gpx_file) self.iface.projectRead.connect(self.on_project_opened) def on_project_opened(self): for _, layer in QgsProject.instance().mapLayers().items(): source = self.layer_source(layer) if source is not bool and source is not None: self.init_spatial_form(self.active_sp_col, layer) def get_column_config(self, config, name): """ Gets joined column name config. :param config: The config object :type config: ColumnConfig :param name: The column name :type name:String :return: :rtype: """ configs = [c for c in config.columns() if c.name == name] if len(configs) > 0: return configs[0] else: return None def sort_joined_columns(self, layer, fk_fields): """ Sort joined columns using the order in the configuration :param layer: The layer containing joined layers :type layer: QgsVectorLayer :return: :rtype: """ if not hasattr(layer, 'attributeTableConfig'): return entity = self._curr_profile.entity_by_name(self.curr_lyr_table) config = layer.attributeTableConfig() columns = config.columns() updated_columns = [] for column in columns: if column.name not in entity.columns.keys(): continue if column.name in fk_fields.keys(): # hide the lookup id column column.hidden = True header = entity.columns[column.name].header() joined_column_name = '{} {}'.format(header, fk_fields[column.name]) joined_column = self.get_column_config(config, joined_column_name) if joined_column is not None: updated_columns.append(joined_column) updated_columns.append(column) else: updated_columns.append(column) config.setColumns(updated_columns) layer.setAttributeTableConfig(config) @staticmethod def execute_layers_join(layer, layer_field, column_header, fk_layer, fk_field): """ Joins two layers with specified field. :param layer: The destination layer of the merge. :type layer: QgsVectorLayer :param layer_field: The source layer of the merge. :type layer_field: String :param fk_layer: The foreign key layer object. :type fk_layer: QgsVectorLayer :param fk_field: The foreign key layer field name. :type fk_field: String :return: :rtype: """ join = QgsVectorLayerJoinInfo() join.joinLayerId = fk_layer.id() join.joinFieldName = 'id' join.setJoinFieldNamesSubset([fk_field]) join.targetFieldName = layer_field join.memoryCache = True join.prefix = '{} '.format(column_header) layer.addJoin(join) def column_to_fk_layer_join(self, column, layer, join_field): """ Creates and executes the join by creating fk layer and running the join method using a column object. :param column: The column object :type column: Object :param layer: The layer to contain the joined fk layer :type layer: QgsVectorLayer :param join_field: The join field that is in the fk layer :type join_field: String """ fk_entity = column.entity_relation.parent fk_layer = vector_layer(fk_entity.name, layer_name=fk_entity.name) QgsProject.instance().addMapLayer(fk_layer, False) # hide the fk id column column.hidden = True header = column.header() self.execute_layers_join(layer, column.name, header, fk_layer, join_field) def join_fk_layer(self, layer, entity): """ Joins foreign key to the layer by creating and choosing join fields. :param layer: The layer to contain the joined fk layer :type layer: QgsVectorLayer :param entity: The layer entity object :type entity: Object :return: A dictionary containing fk_field and column object :rtype: OrderedDict """ if entity is None: return fk_columns = OrderedDict() for column in entity.columns.values(): if column.TYPE_INFO == 'LOOKUP': fk_column = 'value' elif column.TYPE_INFO == 'ADMIN_SPATIAL_UNIT': fk_column = 'name' elif column.TYPE_INFO == 'FOREIGN_KEY': display_cols = column.entity_relation.display_cols if len(display_cols) > 0: fk_column = display_cols[0] else: fk_column = 'id' else: fk_column = None if fk_column is not None: self.column_to_fk_layer_join(column, layer, fk_column) fk_columns[column.name] = fk_column return fk_columns def _adjust_layer_drop_down_width(self): """ Adjusts the layers combobox drop down to expand based on the layer name. """ if len(self._profile_spatial_layers) > 0: longest_item = max(self._profile_spatial_layers, key=len) font_meter = QFontMetrics(self.fontMetrics()) item_width = font_meter.width(longest_item) + 80 self.stdm_layers_combo.setStyleSheet('''* QComboBox QAbstractItemView{ min-width: 60px; width: %s px; } ''' % item_width) def _populate_layers(self): self.stdm_layers_combo.clear() if self._curr_profile is None: return self.spatial_units = self._curr_profile.social_tenure.spatial_units # Get entities containing geometry # columns based on the config info config_entities = self._curr_profile.entities self.geom_entities = [ ge for ge in config_entities.values() if ge.TYPE_INFO == 'ENTITY' and ge.has_geometry_column() ] self._profile_spatial_layers = [] self.sp_tables = spatial_tables() for e in self.geom_entities: table_name = e.name if table_name in self.sp_tables: for i, gc in enumerate(e.geometry_columns()): column_name = gc.name display_name = gc.layer_display() if i > 0: display_name = '{}.{}'.format(display_name, gc.name) self._add_geometry_column_to_combo(table_name, column_name, display_name, gc) # Add geometry entity to the collection self._profile_spatial_layers.append(table_name) # Append the corresponding(profile) view to the list of entity names str_views = list(self._curr_profile.social_tenure.views.keys()) for str_view in str_views: if str_view in self.sp_tables: self.str_view_geom_columns = table_column_names(str_view, True) if len(self.str_view_geom_columns) > 0: # Pick the first column for i, geom_col in enumerate(self.str_view_geom_columns): view_layer_name = str_view if i > 0: view_layer_name = '{}.{}'.format( view_layer_name, geom_col) self._add_geometry_column_to_combo( str_view, geom_col, view_layer_name, self._curr_profile.social_tenure) # Append view to the list of spatial layers self._profile_spatial_layers.append(str_view) # add old config views and custom views. for sp_table in self.sp_tables: if sp_table in pg_views() and sp_table not in str_views and \ sp_table in profile_and_user_views( self._curr_profile): view_geom_columns = table_column_names(sp_table, True) for geom_col in view_geom_columns: view_layer_name = '{}.{}'.format(sp_table, geom_col) self._add_geometry_column_to_combo(sp_table, geom_col, view_layer_name, geom_col) def control_digitize_toolbar(self, curr_layer): if curr_layer is not None: table, column = self._layer_table_column(curr_layer) if curr_layer.isSpatial() and table not in pg_views(): # Make sure digitizing toolbar is enabled self.iface.digitizeToolBar().setEnabled(True) self.set_canvas_crs(curr_layer) elif table in pg_views(): self.iface.digitizeToolBar().setEnabled(False) def set_canvas_crs(self, layer): # Sets canvas CRS # get srid with EPSG text if layer.isValid(): full_srid = layer.crs().authid().split(':') srid = int(full_srid[1]) layer_crs = QgsCoordinateReferenceSystem( srid, QgsCoordinateReferenceSystem.EpsgCrsId) self.iface.mapCanvas().mapSettings().setDestinationCrs(layer_crs) def init_spatial_form(self, spatial_column, curr_layer): """ Initializes the Layer form. :param curr_layer: The layer for which the widgets are set. :type curr_layer: QgsVectorLayer :return: None :rtype: NoneType """ table, column = self._layer_table_column(curr_layer) if table not in pg_views() and curr_layer is not None: self.stdm_fields.init_form(table, spatial_column, curr_layer) def _format_layer_display_name(self, col, table): return '{0}.{1}'.format(table, col) def _add_geometry_column_to_combo(self, table_name, column_name, display, item): icon = self._geom_icon(table_name, column_name) self.stdm_layers_combo.addItem(icon, display, { 'table_name': table_name, 'column_name': column_name, 'item': item }) for spatial_unit in self.spatial_units: table = spatial_unit.name spatial_column = [ c.name for c in spatial_unit.columns.values() if c.TYPE_INFO == 'GEOMETRY' ] spatial_unit_item = str(table + '.' + spatial_column[0]) index = self.stdm_layers_combo.findText(spatial_unit_item, Qt.MatchFixedString) if index >= 0: self.stdm_layers_combo.setCurrentIndex(index) def _layer_info_from_table_column(self, table, column): # Returns the index and item # data from the given table and column name idx, layer_info = -1, None for i in range(self.stdm_layers_combo.count()): layer_info = self.stdm_layers_combo.itemData(i) if layer_info['table_name'] == table and \ layer_info['column_name'] == column: idx, layer_info = i, layer_info break return idx, layer_info def _geom_icon(self, table, column): # Get column type and apply the appropriate icon geometry_typ = str(geometryType(table, column)[0]) icon = None if geometry_typ == 'POLYGON': icon = GuiUtils.get_icon('layer_polygon.png') elif geometry_typ == 'LINESTRING': icon = GuiUtils.get_icon('layer_line.png') elif geometry_typ == 'POINT': icon = GuiUtils.get_icon('layer_point.png') elif geometry_typ == 'MULTIPOLYGON': icon = GuiUtils.get_icon('layer_polygon.png') elif geometry_typ == 'MULTILINESTRING': icon = GuiUtils.get_icon('layer_line.png') else: icon = GuiUtils.get_icon('table.png') return icon def add_layer_by_name(self, layer_name): """ Add a layer when a name is supplied. :param layer_name: The stdm layer name :type layer_name: String """ index = self.stdm_layers_combo.findText(layer_name, Qt.MatchFixedString) if index >= 0: self.stdm_layers_combo.setCurrentIndex(index) # add spatial unit layer. self.on_add_to_canvas_button_clicked() def geom_col_layer_name(self, table, col): """ Returns the layer name based on geom column object. :param col: Column Object :type col: Object :param table: Table name :type table: String :return: Layer name :rtype: String """ # Check if the geom has display name, if not, # get layer name with default naming. if col is None: return if isinstance(col, str): spatial_layer_item = '{}.{}'.format(table, col) elif isinstance(col, SocialTenure): spatial_layer_item = col.view_name elif col.layer_display_name == '': spatial_layer_item = '{0}'.format(col.entity.short_name) # use the layer_display_name else: spatial_layer_item = col.layer_display_name return spatial_layer_item def on_add_to_canvas_button_clicked(self): """ Add STDM layer to map canvas. """ if self.stdm_layers_combo.count() == 0: return sp_col_info = self.stdm_layers_combo.itemData( self.stdm_layers_combo.currentIndex()) if sp_col_info is None: title = QApplication.translate('SpatialUnitManagerDockWidget', 'Spatial Unit Manager') msg = QApplication.translate( 'SpatialUnitManagerDockWidget', 'Spatial Column Layer Could not be found') # Message: Spatial column information # could not be found QMessageBox.warning(self.iface.mainWindow(), title, msg) table_name, spatial_column = sp_col_info["table_name"], \ sp_col_info["column_name"] # Check if the layer has already been layer_item = sp_col_info.get('item', None) layer_name = self.geom_col_layer_name(table_name, layer_item) if layer_name in self._map_registry_layer_names(): layer = QgsProject.instance().mapLayersByName(layer_name)[0] self.iface.setActiveLayer(layer) return self.curr_lyr_table = table_name self.curr_lyr_sp_col = spatial_column if layer_item is not None: if isinstance(layer_item, str): layer_name = layer_item else: layer_name = layer_item.layer_display() entity = self._curr_profile.entity_by_name(table_name) if entity is not None: geom_col_obj = entity.columns[spatial_column] srid = None if geom_col_obj.srid >= 100000: srid = geom_col_obj.srid curr_layer = vector_layer(table_name, geom_column=spatial_column, layer_name=layer_name, proj_wkt=srid) else: curr_layer = vector_layer(table_name, geom_column=spatial_column, layer_name=layer_name, proj_wkt=None) # for lookup layer. else: curr_layer = vector_layer(table_name, geom_column=spatial_column) if curr_layer is not None and curr_layer.isValid(): if curr_layer.name() in self._map_registry_layer_names(): return QgsProject.instance().addMapLayer(curr_layer) LayerUtils.tag_layer_as_stdm_layer(curr_layer) self.zoom_to_layer() self.onLayerAdded.emit(spatial_column, curr_layer) self.toggle_entity_multi_layers(curr_layer) self.set_canvas_crs(curr_layer) # Required in order for the layer name to be set if layer_name is not None: QTimer.singleShot( 100, lambda: self._set_layer_display_name( curr_layer, layer_name)) entity = self._curr_profile.entity_by_name(self.curr_lyr_table) fk_fields = self.join_fk_layer(curr_layer, entity) if entity is not None: self.sort_joined_columns(curr_layer, fk_fields) self.set_field_alias(curr_layer, entity, fk_fields) elif curr_layer is not None: msg = QApplication.translate( "Spatial Unit Manager", "'{0}.{1}' layer is invalid, it cannot " "be added to the map view.".format(table_name, spatial_column)) QMessageBox.critical(self.iface.mainWindow(), 'Spatial Unit Manager', msg) def set_field_alias(self, layer, entity, fk_fields): """ Set the field alia for fk joined fields so that they are same as the child columns. :param layer: The layer containing the join :type layer: QgsVectorLayer :param entity: The entity of the layer :type entity: Object :param fk_fields: The dictionary containing the parent and child fields :type fk_fields: OrderedDict :return: :rtype: """ for column, fk_field in fk_fields.items(): header = entity.columns[column].header() f_index = layer.fields().indexFromName('{} {}'.format( header, fk_field)) alias = '{} Value'.format(header) layer.setFieldAlias(f_index, alias) def zoom_to_layer(self): """ Zooms the map canvas to the extent the active layer. :return: :rtype: """ layer = self.iface.activeLayer() if layer is not None: self.iface.mapCanvas().setExtent(layer.extent()) self.iface.mapCanvas().refresh() def geom_columns(self, entity): """ Returns the geometry columns of an entity. :param entity: The entity object. :type entity: Object :return: List of Geometry column objects :rtype: List """ geom_column = [ column for column in entity.columns.values() if column.TYPE_INFO == 'GEOMETRY' ] return geom_column def same_entity_layers(self): """ Returns layer names of an entity if they are more than one in one entity. :return: List in a list :rtype: List """ entity_layers = [] for entity in self.geom_entities: layer_list = self.entity_layer_names(entity) entity_layers.append(layer_list) return entity_layers def entity_layer_names(self, entity): """ Returns layer names of an entity if they are more than one in one entity. :param entity: The Entity object :param type: Object :return: List in a list :rtype: List """ cols = self.geom_columns(entity) layer_list = [] for col in cols: lyr_name = self.geom_col_layer_name(entity.name, col) layer_list.append(lyr_name) return layer_list def layer_entity_children(self, sel_lyr_name): layer_lists = [ layer_list for layer_list in self.same_entity_layers() if sel_lyr_name in layer_list ] str_view = self._curr_profile.social_tenure.view_name if len(layer_lists) < 1: geom_columns = table_column_names(str_view, True) layer_lists = [geom_columns] return layer_lists def toggle_entity_multi_layers(self, new_layer): """ Removes other layers created from the entity of the new layer. :param new_layer: The new layer added :type new_layer: QgsVectorLayer :return: None :rtype: NoneType """ sel_lyr_name = new_layer.name() layer_lists = self.layer_entity_children(sel_lyr_name) # Include layers for toggling whose entity # has more than one geometry if len(layer_lists) < 1: return # if the layer_list is the # parent of selected layer for layer_name in layer_lists[0]: # remove other layers # of the same entity if layer_name != sel_lyr_name: layer_objects = QgsProject. \ instance().mapLayersByName(layer_name) if len(layer_objects) > 0: for layer in layer_objects: layer_id = layer.id() QgsProject. \ instance().removeMapLayer(layer_id) # Change the crs of the canvas based on the new layer layer_list = QgsProject.instance(). \ mapLayersByName(sel_lyr_name) if len(layer_list) > 0: self.set_canvas_crs(layer_list[0]) def _set_layer_display_name(self, layer, name): try: layer.setName(name) except RuntimeError: pass def _layer_table_column(self, layer): # Returns the table and column name # that a layer belongs to. table, column = '', '' if hasattr(layer, 'dataProvider'): if layer.dataProvider().name() == 'postgres': layerConnStr = layer.dataProvider().dataSourceUri() dataSourceURI = QgsDataSourceUri(layerConnStr) table, column = dataSourceURI.table(), \ dataSourceURI.geometryColumn() return table, column def _map_registry_layer_names(self): """ Returns a list of layers names. """ layers = QgsProject.instance().mapLayers() layer_names = [lyr.name() for lyr in layers.values()] return layer_names def set_display_name_button_clicked(self): """ Method to change display name """ layer_names_ids = pg_layerNamesIDMapping().reverse layer = self.iface.activeLayer() if layer is not None: table_name = layer_names_ids.get(layer.id(), '') if table_name: # Check if the table name is in the current profile if table_name in self._profile_spatial_layers: prompt = \ "Set the display name for '{0}' layer".format( layer.name() ) display_name, ok = QInputDialog.getText( self, 'Spatial Unit ' 'Manager', prompt) if ok and display_name: # Get layer table and columns names table, column = self._layer_table_column(layer) if table and column: idx, layer_info = \ self._layer_info_from_table_column( table, column ) # Get item in the combo corresponding to the layer if idx != -1: self.stdm_layers_combo.setItemText( idx, display_name) layer.setName(display_name) # Update configuration item config_item = layer_info.get('item', None) if config_item is not None: config_item.layer_display_name = \ display_name # Update configuration save_configuration() else: msg = QApplication.translate( "Spatial Unit Manager", "The layer does not " "belong in the '{0}' " "profile.\nThe display name " "will not be set." "".format(self._curr_profile.name)) QMessageBox.critical(self.iface.mainWindow(), 'Spatial Unit Manager', msg) def active_layer_source(self): """ Get the layer table name if the source is from the database. :return: The a Boolean True if a valid source is found or False if not. Alternatively, None if there is no active layer. :rtype: Boolean or NoneType """ active_layer = self.iface.activeLayer() return self.layer_source(active_layer) def layer_source(self, layer): """ Gets the layer source. :param layer: The layer :type layer: Any :return: Layer Source or None :rtype: """ if layer is None: return None source = layer.source() if source is None: return False source_value = dict(re.findall('(\\S+)="?(.*?)"? ', source)) try: table = source_value['table'].split('.') table_name = table[1].strip('"') if table_name in pg_views(): return False entity = self._curr_profile.entity_by_name(table_name) if entity is None: return False else: self.active_entity = entity self.active_table = table_name # get all spatial columns of the entity. spatial_columns = [ c.name for c in entity.columns.values() if c.TYPE_INFO == 'GEOMETRY' ] # get all fields excluding the geometry. layer_fields = [field.name() for field in layer.fields()] # get the currently being used geometry column active_sp_cols = [ col for col in spatial_columns if col not in layer_fields ] if len(active_sp_cols) == 1: self.active_sp_col = active_sp_cols[0] return True except KeyError: return False def import_gpx_file(self): """ Method to load GPS dialog """ source_status = self.active_layer_source() layer_map = QgsProject.instance().mapLayers() error_title = QApplication.translate( 'SpatialUnitManagerDockWidget', 'GPS Feature Import Loading Error') if len(layer_map) > 0: if source_status is None: QMessageBox.critical( self, error_title, QApplication.translate( 'SpatialUnitManagerDockWidget', 'You have not selected a layer.\n ' 'Please select a valid layer to import GPS features.')) elif source_status is False: QMessageBox.critical( self, error_title, QApplication.translate( 'SpatialUnitManagerDockWidget', 'You have selected a non-STDM entity layer.\n ' 'Please select a valid layer to import GPS features.')) elif source_status is True: self.gps_tool_dialog = GPSToolDialog(self.iface, self.active_entity, self.active_table, self.active_sp_col) self.gps_tool_dialog.show() else: QMessageBox.critical( self, error_title, QApplication.translate( 'SpatialUnitManagerDockWidget', 'You must add an entity layer from Spatial Unit Manager\n' 'and select it to import GPS Features.')) def _valid_entity(self): """ Checks if the current active layer in the layer panel represents a valid entity in the current profile :return: Error object :rtype: Object """ entity_profile = current_profile() entity_obj = entity_profile.entity_by_name(self.curr_lyr_table) if entity_obj is None: return None return entity_obj def closeEvent(self, event): """ On close of the dock window, this event is executed to run close_dock method :param event: The close event :type QCloseEvent :return: None """ self._plugin.spatialLayerManager.setChecked(False)