def check_selected_features(self): constraint_types_of_parcels = LayerConfig.get_constraint_types_of_parcels(self.names) self.lb_plot.setText(QCoreApplication.translate("WizardTranslations", "<b>Plot(s)</b>: {count} Feature(s) Selected").format(count=self._layers[self.names.OP_PLOT_T][LAYER].selectedFeatureCount())) self.lb_plot.setStyleSheet(CSS_COLOR_OKAY_LABEL) # Default color self.lb_building.setText(QCoreApplication.translate("WizardTranslations","<b>Building(s)</b>: {count} Feature(s) Selected").format(count=self._layers[self.names.OP_BUILDING_T][LAYER].selectedFeatureCount())) self.lb_building.setStyleSheet(CSS_COLOR_OKAY_LABEL) # Default color self.lb_building_unit.setText(QCoreApplication.translate("WizardTranslations","<b>Building unit(s)</b>: {count} Feature(s) Selected").format(count=self._layers[self.names.OP_BUILDING_UNIT_T][LAYER].selectedFeatureCount())) self.lb_building_unit.setStyleSheet(CSS_COLOR_OKAY_LABEL) # Default color parcel_type = self.dict_parcel_type[self.cb_parcel_type.currentText()] for spatial_unit in constraint_types_of_parcels[parcel_type]: _layer = self._spatial_unit_layers[spatial_unit] _color = CSS_COLOR_OKAY_LABEL if constraint_types_of_parcels[parcel_type][spatial_unit] == 1 and not _layer.selectedFeatureCount() == 1: _color = CSS_COLOR_ERROR_LABEL elif constraint_types_of_parcels[parcel_type][spatial_unit] == '+' and _layer.selectedFeatureCount() < 1: _color = CSS_COLOR_ERROR_LABEL elif constraint_types_of_parcels[parcel_type][spatial_unit] is None: _color = CSS_COLOR_INACTIVE_LABEL if spatial_unit == self.names.OP_PLOT_T: self.lb_plot.setStyleSheet(_color) elif spatial_unit == self.names.OP_BUILDING_T: self.lb_building.setStyleSheet(_color) elif spatial_unit == self.names.OP_BUILDING_UNIT_T: self.lb_building_unit.setStyleSheet(_color) self.button(self.FinishButton).setEnabled(self.is_constraint_satisfied(parcel_type))
def validate_type_of_parcel(self, parcel_type): constraint_types_of_parcels = LayerConfig.get_constraint_types_of_parcels(self.names) # Activate all push buttons self.btn_plot_map.setEnabled(True) self.btn_plot_expression.setEnabled(True) self.btn_building_map.setEnabled(True) self.btn_building_expression.setEnabled(True) self.btn_building_unit_map.setEnabled(True) self.btn_building_unit_expression.setEnabled(True) parcel_type = self.dict_parcel_type[parcel_type] # Disable labels/controls depending on parcel_type for spatial_unit in constraint_types_of_parcels[parcel_type]: if constraint_types_of_parcels[parcel_type][spatial_unit] is None: if spatial_unit == self.names.OP_PLOT_T: self.btn_plot_map.setEnabled(False) self.btn_plot_expression.setEnabled(False) elif spatial_unit == self.names.OP_BUILDING_T: self.btn_building_map.setEnabled(False) self.btn_building_expression.setEnabled(False) elif spatial_unit == self.names.OP_BUILDING_UNIT_T: self.btn_building_unit_map.setEnabled(False) self.btn_building_unit_expression.setEnabled(False) self.update_help_message(parcel_type) self.check_selected_features()
def fill_collection(self, key, collection, parent, plural, icons): """ Fill a collection of LADM_COL objects """ parent.insertChildren(parent.childCount(), 1, self.rootItem.columnCount()) collection_parent = parent.child(parent.childCount() - 1) collection_parent.setData( 0, "{} ({})".format(plural[key] if key in plural else key, len(collection))) collection_parent.setData(0, {"type": key}, Qt.UserRole) dict_table_package = LayerConfig.get_dict_table_package(self.names) res = collection_parent.setData( 0, QIcon(icons[dict_table_package[key]]) if key in dict_table_package else None, Qt.DecorationRole) for object in collection: # Fill LADM_COL object collection_parent.insertChildren(collection_parent.childCount(), 1, self.rootItem.columnCount()) object_parent = collection_parent.child( collection_parent.childCount() - 1) object_parent.setData(0, "t_id: {}".format(object['id'])) object_parent.setData(0, { "type": key, "id": object['id'], "value": object['id'] }, Qt.UserRole) object_parent.setData(0, key, Qt.ToolTipRole) font = QFont() font.setBold(True) object_parent.setData(0, font, Qt.FontRole) self.fill_model(object['attributes'], object_parent)
def load_parties_data(self): expression = QgsExpression(LayerConfig.get_dict_display_expressions(self.names, [LADMNames.SURVEY_MODEL_KEY])[self.names.LC_PARTY_T]) context = QgsExpressionContext() data = dict() for feature in self._layers[self.names.LC_PARTY_T].getFeatures(): context.setFeature(feature) expression.prepare(context) value = expression.evaluate(context) data[feature[self.names.T_ID_F]] = [value if value != NULL else None, 0, 0] self.set_parties_data(data)
def is_constraint_satisfied(self, parcel_type): constraint_types_of_parcels = LayerConfig.get_constraint_types_of_parcels(self.names) result = True for spatial_unit in constraint_types_of_parcels[parcel_type]: _layer = self._spatial_unit_layers[spatial_unit] if constraint_types_of_parcels[parcel_type][spatial_unit] == 1 and not _layer.selectedFeatureCount() == 1: result = False elif constraint_types_of_parcels[parcel_type][spatial_unit] == '+' and _layer.selectedFeatureCount() < 1: result = False return result
def fill_table(self, search_criterion_supplies, search_criterion_collected): """ Shouldn't handle 'inverse' mode as we won't switch table columns at runtime. :param search_criterion_supplies: key-value pair to build an expression to search data in the supplies source :param search_criterion_collected: key-value pair to build an expression to search data in the collected source :return: """ plural = LayerConfig.get_dict_plural(self.utils._db.names) dict_collected_parcels = self.utils.ladm_data.get_parcel_data_to_compare_changes(self.utils._db, search_criterion_collected) # Custom layer modifiers layer_modifiers = { LayerConfig.PREFIX_LAYER_MODIFIERS: LayerConfig.SUPPLIES_DB_PREFIX, LayerConfig.SUFFIX_LAYER_MODIFIERS: LayerConfig.SUPPLIES_DB_SUFFIX, LayerConfig.STYLE_GROUP_LAYER_MODIFIERS: self.symbology.get_supplies_style_group(self.utils._supplies_db.names) } dict_supplies_parcels = self.utils.ladm_data.get_parcel_data_to_compare_changes_supplies(self.utils._supplies_db, search_criterion_supplies, layer_modifiers=layer_modifiers) # Before filling the table we make sure we get one and only one parcel attrs dict collected_attrs = dict() if dict_collected_parcels: collected_parcel_number = list(dict_collected_parcels.keys())[0] collected_attrs = dict_collected_parcels[collected_parcel_number][0] del collected_attrs[self.utils._db.names.T_ID_F] # Remove this line if self.utils._db.names.T_ID_F is somehow needed supplies_attrs = dict() if dict_supplies_parcels: supplies_parcel_number = list(dict_supplies_parcels.keys())[0] supplies_attrs = dict_supplies_parcels[supplies_parcel_number][0] del supplies_attrs[self.utils._supplies_db.names.T_ID_F] # Remove this line if self.utils._supplies_db.names,T_ID_F is somehow needed number_of_rows = len(collected_attrs) or len(supplies_attrs) self.tbl_changes_per_parcel.setRowCount(number_of_rows) # t_id shouldn't be counted self.tbl_changes_per_parcel.setSortingEnabled(False) field_names = list(collected_attrs.keys()) if collected_attrs else list(supplies_attrs.keys()) if PLOT_GEOMETRY_KEY in field_names: field_names.remove(PLOT_GEOMETRY_KEY) # We'll handle plot geometry separately for row, field_name in enumerate(field_names): supplies_value = supplies_attrs[field_name] if field_name in supplies_attrs else NULL collected_value = collected_attrs[field_name] if field_name in collected_attrs else NULL field_alias = DICT_ALIAS_KEYS_CHANGE_DETECTION[field_name] if field_name in DICT_ALIAS_KEYS_CHANGE_DETECTION else field_name self.fill_row(field_alias, supplies_value, collected_value, row, plural) if number_of_rows: # At least one row in the table? self.fill_geometry_row(PLOT_GEOMETRY_KEY, supplies_attrs[PLOT_GEOMETRY_KEY] if PLOT_GEOMETRY_KEY in supplies_attrs else QgsGeometry(), collected_attrs[PLOT_GEOMETRY_KEY] if PLOT_GEOMETRY_KEY in collected_attrs else QgsGeometry(), number_of_rows - 1) self.tbl_changes_per_parcel.setSortingEnabled(True)
def __init__(self, db, layers, editing_layer): self.__db = db self.__layers = layers self.__editing_layer = editing_layer self.__constraint_types_of_parcels = LayerConfig.get_constraint_types_of_parcels( self.__db.names) self.parcel_type_ili_code = None self.__relatable_layers = dict() self.__init_selectable_layer_by_type()
def __init__(self, db, parent=None): QDialog.__init__(self, parent) self.setupUi(self) self._db = db self.app = AppInterface() self.names = self._db.names self.models_tree = dict() self.selected_items_dict = dict() self.icon_names = [ 'points.png', 'lines.png', 'polygons.png', 'tables.png', 'domains.png', 'structures.png', 'relationships.svg' ] self.txt_search_text.addAction( QIcon(":/Asistente-LADM-COL/resources/images/search.png"), QLineEdit.LeadingPosition) # Fill predefined tables combobox self.cbo_select_predefined_tables.clear() self.cbo_select_predefined_tables.setInsertPolicy( QComboBox.InsertAlphabetically) self.cbo_select_predefined_tables.addItem("", []) # By default for name, layer_list in LayerConfig.get_layer_sets( self.names, self.app.core.get_active_models_per_db(db)).items(): self.cbo_select_predefined_tables.addItem(name, layer_list) self.cbo_select_predefined_tables.currentIndexChanged.connect( self.__select_predefined_changed) # Set connections self.buttonBox.accepted.connect(self.accepted) self.buttonBox.rejected.connect(self.rejected) self.buttonBox.helpRequested.connect(self.__show_help) self.txt_search_text.textChanged.connect(self.__search_text_changed) self.chk_show_domains.toggled.connect(self.__show_table_type_changed) self.chk_show_structures.toggled.connect( self.__show_table_type_changed) self.chk_show_associations.toggled.connect( self.__show_table_type_changed) self.trw_layers.itemSelectionChanged.connect(self.__selection_changed) # Reload latest settings self.__restore_settings() # Load layers from the db self.__load_available_layers()
def adjust_page_2_controls(self): constraint_types_of_parcels = LayerConfig.get_constraint_types_of_parcels( self.names) self.button(self.FinishButton).setDisabled(True) self.disconnect_signals() # Load layers result = self.prepare_feature_creation_layers() if result is None: self.close_wizard(show_message=False) self.dict_parcel_type = dict() for feature in self._layers[ self.names.LC_CONDITION_PARCEL_TYPE_D].getFeatures(): self.dict_parcel_type[feature[ self.names.DISPLAY_NAME_F]] = feature[self.names.ILICODE_F] if self.cb_parcel_type.count() == 0: for feature in self._layers[ self.names.LC_CONDITION_PARCEL_TYPE_D].getFeatures(): if feature[ self.names.ILICODE_F] in constraint_types_of_parcels: self.cb_parcel_type.addItem( feature[self.names.DISPLAY_NAME_F], feature[self.names.T_ID_F]) # Select previous option saved if self.type_of_parcel_selected: index = self.cb_parcel_type.findText( self.type_of_parcel_selected) if index != -1: self.cb_parcel_type.setCurrentIndex(index) self.cb_parcel_type.currentTextChanged.connect( self.validate_type_of_parcel) self.cb_parcel_type.currentTextChanged.emit( self.cb_parcel_type.currentText()) # Check if a previous feature is selected self.check_selected_features() # Register select features by expression if isinstance(self, SelectFeatureByExpressionDialogWrapper): self.register_select_features_by_expression() # Register select features on map if isinstance(self, SelectFeaturesOnMapWrapper): self.register_select_feature_on_map()
def fill_collection(self, key, collection, parent, plural, icons): """ Fill a collection of LADM-COL objects """ display_name = self._normalize_display(key, plural) key = self._normalize_key(key) collection_parent = self._create_new_item(parent) collection_parent.setData( 0, "{} ({})".format(display_name, len(collection))) collection_parent.setData( 0, { "type": key, "collapse": key not in [self.names.LC_PLOT_T, self.names.LC_PARCEL_T] }, Qt.UserRole) dict_table_package = LayerConfig.get_dict_table_package(self.names) res = collection_parent.setData( 0, QIcon(icons[dict_table_package[key]]) if key in dict_table_package else None, Qt.DecorationRole) for object in collection: # Fill LADM-COL object object_parent = self._create_new_item(collection_parent) object_parent.setData(0, "t_id: {}".format(object['id'])) object_parent.setData(0, { "type": key, "id": object['id'], "value": object['id'] }, Qt.UserRole) object_parent.setData(0, key, Qt.ToolTipRole) font = QFont() font.setBold(True) object_parent.setData(0, font, Qt.FontRole) self.fill_model(object['attributes'], object_parent)
def post_save(self, features): constraint_types_of_parcels = LayerConfig.get_constraint_types_of_parcels(self.names) message = QCoreApplication.translate("WizardTranslations", "'{}' tool has been closed because an error occurred while trying to save the data.").format(self.WIZARD_TOOL_NAME) if len(features) != 1: message = QCoreApplication.translate("WizardTranslations", "'{}' tool has been closed. We should have got only one {} by we have {}").format(self.WIZARD_TOOL_NAME, self.WIZARD_FEATURE_NAME, len(features)) self.logger.warning(__name__, "We should have got only one {}, but we have {}".format(self.WIZARD_FEATURE_NAME, len(features))) else: fid = features[0].id() if not self._layers[self.EDITING_LAYER_NAME][LAYER].getFeature(fid).isValid(): self.logger.warning(__name__, "Feature not found in layer {}...".format(self.EDITING_LAYER_NAME)) else: parcel_id = self._layers[self.EDITING_LAYER_NAME][LAYER].getFeature(fid)[self.names.T_ID_F] plot_ids = list() building_ids = list() building_unit_ids = list() # Apply restriction to the selection if self.names.OP_PLOT_T in constraint_types_of_parcels[self.dict_parcel_type[self.cb_parcel_type.currentText()]]: if constraint_types_of_parcels[self.dict_parcel_type[self.cb_parcel_type.currentText()]][self.names.OP_PLOT_T] is not None: plot_ids = [f[self.names.T_ID_F] for f in self._layers[self.names.OP_PLOT_T][LAYER].selectedFeatures()] else: plot_ids = [f[self.names.T_ID_F] for f in self._layers[self.names.OP_PLOT_T][LAYER].selectedFeatures()] if self.names.OP_BUILDING_T in constraint_types_of_parcels[self.dict_parcel_type[self.cb_parcel_type.currentText()]]: if constraint_types_of_parcels[self.dict_parcel_type[self.cb_parcel_type.currentText()]][self.names.OP_BUILDING_T] is not None: building_ids = [f[self.names.T_ID_F] for f in self._layers[self.names.OP_BUILDING_T][LAYER].selectedFeatures()] else: building_ids = [f[self.names.T_ID_F] for f in self._layers[self.names.OP_BUILDING_T][LAYER].selectedFeatures()] if self.names.OP_BUILDING_UNIT_T in constraint_types_of_parcels[self.dict_parcel_type[self.cb_parcel_type.currentText()]]: if constraint_types_of_parcels[self.dict_parcel_type[self.cb_parcel_type.currentText()]][self.names.OP_BUILDING_UNIT_T] is not None: building_unit_ids = [f[self.names.T_ID_F] for f in self._layers[self.names.OP_BUILDING_UNIT_T][LAYER].selectedFeatures()] else: building_unit_ids = [f[self.names.T_ID_F] for f in self._layers[self.names.OP_BUILDING_UNIT_T][LAYER].selectedFeatures()] # Fill uebaunit table new_features = [] for plot_id in plot_ids: new_feature = QgsVectorLayerUtils().createFeature(self._layers[self.names.COL_UE_BAUNIT_T][LAYER]) new_feature.setAttribute(self.names.COL_UE_BAUNIT_T_OP_PLOT_F, plot_id) new_feature.setAttribute(self.names.COL_UE_BAUNIT_T_PARCEL_F, parcel_id) self.logger.info(__name__, "Saving Plot-Parcel: {}-{}".format(plot_id, parcel_id)) new_features.append(new_feature) for building_id in building_ids: new_feature = QgsVectorLayerUtils().createFeature(self._layers[self.names.COL_UE_BAUNIT_T][LAYER]) new_feature.setAttribute(self.names.COL_UE_BAUNIT_T_OP_BUILDING_F, building_id) new_feature.setAttribute(self.names.COL_UE_BAUNIT_T_PARCEL_F, parcel_id) self.logger.info(__name__, "Saving Building-Parcel: {}-{}".format(building_id, parcel_id)) new_features.append(new_feature) for building_unit_id in building_unit_ids: new_feature = QgsVectorLayerUtils().createFeature(self._layers[self.names.COL_UE_BAUNIT_T][LAYER]) new_feature.setAttribute(self.names.COL_UE_BAUNIT_T_OP_BUILDING_UNIT_F, building_unit_id) new_feature.setAttribute(self.names.COL_UE_BAUNIT_T_PARCEL_F, parcel_id) self.logger.info(__name__, "Saving Building Unit-Parcel: {}-{}".format(building_unit_id, parcel_id)) new_features.append(new_feature) self._layers[self.names.COL_UE_BAUNIT_T][LAYER].dataProvider().addFeatures(new_features) if plot_ids and building_ids and building_unit_ids: message = QCoreApplication.translate("WizardTranslations", "The new parcel (t_id={}) was successfully created and associated with its corresponding Plot (t_id={}) and Building(s) (t_id={}) and Building Unit(s) (t_id={})!").format(parcel_id, ", ".join([str(b) for b in plot_ids]), ", ".join([str(b) for b in building_ids]), ", ".join([str(b) for b in building_unit_ids])) elif plot_ids and building_ids and not building_unit_ids: message = QCoreApplication.translate("WizardTranslations", "The new parcel (t_id={}) was successfully created and associated with its corresponding Plot (t_id={}) and Building(s) (t_id={})!").format(parcel_id, ", ".join([str(b) for b in plot_ids]), ", ".join([str(b) for b in building_ids])) elif plot_ids and not building_ids and building_unit_ids: message = QCoreApplication.translate("WizardTranslations", "The new parcel (t_id={}) was successfully created and associated with its corresponding Plot (t_id={}) and Building Unit(s) (t_id={})!").format(parcel_id, ", ".join([str(b) for b in plot_ids]), ", ".join([str(b) for b in building_unit_ids])) elif plot_ids and not building_ids and not building_unit_ids: message = QCoreApplication.translate("WizardTranslations", "The new parcel (t_id={}) was successfully created and associated with its corresponding Plot (t_id={})!").format(parcel_id, ", ".join([str(b) for b in plot_ids])) elif not plot_ids and building_ids and not building_unit_ids: message = QCoreApplication.translate("WizardTranslations", "The new parcel (t_id={}) was successfully created and associated with its corresponding Building(s) (t_id={})!").format(parcel_id, ", ".join([str(b) for b in building_ids])) elif not plot_ids and building_ids and building_unit_ids: message = QCoreApplication.translate("WizardTranslations", "The new parcel (t_id={}) was successfully created and associated with its corresponding Building(s) (t_id={}) and Building Unit(s) (t_id={})!").format(parcel_id, ", ".join([str(b) for b in building_ids]), ", ".join([str(b) for b in building_unit_ids])) elif not plot_ids and not building_ids and building_unit_ids: message = QCoreApplication.translate("WizardTranslations", "The new parcel (t_id={}) was successfully created and associated with its corresponding Building Unit(s) (t_id={})!").format(parcel_id, ", ".join([str(b) for b in building_unit_ids])) elif not plot_ids and not building_ids and not building_unit_ids: message = QCoreApplication.translate("WizardTranslations", "The new parcel (t_id={}) was successfully created but this one wasn't associated with a spatial unit").format(parcel_id) return message
def show_context_menu(self, point): tree_view = self.sender() index = tree_view.indexAt(point) context_menu = QMenu("Context menu") index_data = index.data(Qt.UserRole) if index_data is None: return if "value" in index_data: action_copy = QAction( QCoreApplication.translate("DockWidgetQueries", "Copy value")) action_copy.triggered.connect( partial(self.copy_value, index_data["value"])) context_menu.addAction(action_copy) context_menu.addSeparator() if "url" in index_data: action_open_url = QAction( QCoreApplication.translate("DockWidgetQueries", "Open URL")) action_open_url.triggered.connect( partial(self.open_url, index_data["url"])) context_menu.addAction(action_open_url) context_menu.addSeparator() # Configure actions for tables/layers if "type" in index_data and "id" in index_data: table_name = index_data["type"] table_package = LayerConfig.get_dict_table_package(self.names) t_id = index_data["id"] geometry_type = None if table_name in table_package and table_package[ table_name] == LADMNames.SPATIAL_UNIT_PACKAGE: # Layers in Spatial Unit package have double geometry, we need the polygon one geometry_type = QgsWkbTypes.PolygonGeometry if table_name == self.names.OP_PARCEL_T: if self._layers[ self.names.OP_PARCEL_T][LAYER] is None or self._layers[ self.names. OP_PLOT_T][LAYER] is None or self._layers[ self.names.COL_UE_BAUNIT_T][LAYER] is None: self.add_layers() layer = self._layers[self.names.OP_PARCEL_T][LAYER] self.iface.layerTreeView().setCurrentLayer(layer) else: layer = self.qgis_utils.get_layer(self._db, table_name, geometry_type, True) if layer is not None: if layer.isSpatial(): action_zoom_to_feature = QAction( QCoreApplication.translate( "DockWidgetQueries", "Zoom to {} with {}={}").format( table_name, self.names.T_ID_F, t_id)) action_zoom_to_feature.triggered.connect( partial(self.zoom_to_feature, layer, t_id)) context_menu.addAction(action_zoom_to_feature) if table_name == self.names.OP_PARCEL_T: # We show a handy option to zoom to related plots plot_ids = self.ladm_data.get_plots_related_to_parcels( self._db, [t_id], None, self._layers[self.names.OP_PLOT_T][LAYER], self._layers[self.names.COL_UE_BAUNIT_T][LAYER]) if plot_ids: action_zoom_to_plots = QAction( QCoreApplication.translate( "DockWidgetQueries", "Zoom to related plot(s)")) action_zoom_to_plots.triggered.connect( partial(self.zoom_to_plots, plot_ids)) context_menu.addAction(action_zoom_to_plots) action_open_feature_form = QAction( QCoreApplication.translate( "DockWidgetQueries", "Open form for {} with {}={}").format( table_name, self.names.T_ID_F, t_id)) action_open_feature_form.triggered.connect( partial(self.open_feature_form, layer, t_id)) context_menu.addAction(action_open_feature_form) if context_menu.actions(): context_menu.exec_(tree_view.mapToGlobal(point))
def fill_model(self, record, parent): """ Fill data in the treeview depending on the structure. It expects JSON data. The JSON data may contain LADM-COL object collections in the form: "ladm_col_table_name" : [{"id": 5, "attributes":{k,v pairs}}, {"id": 8, "attributes":{k,v pairs}}, ...] """ plural = LayerConfig.get_dict_plural(self.names) icons = LayerConfig.get_dict_package_icon() dict_table_package = LayerConfig.get_dict_table_package(self.names) for key, values in record.items(): # either tuple or dict if type(values) is list: if not len(values): # Empty object kv_item = self._create_new_item(parent) kv_item.setData( 0, "{} (0)".format(plural[key] if key in plural else key)) kv_item.setData(0, QBrush(Qt.lightGray), Qt.ForegroundRole) kv_item.setData(0, {"type": key}, Qt.UserRole) kv_item.setData( 0, QIcon(icons[dict_table_package[key]]) if key in dict_table_package else None, Qt.DecorationRole) continue for value in values: if type(value) is dict: if len( value ) == 2 and 'id' in value and 'attributes' in value: # We have a list of LADM-COL model objects, we deal differently with them... self.fill_collection(key, values, parent, plural, icons) break elif type(values) is dict: if key == 'attributes': # Dict of key-value pairs, reuse the function self.fill_model(values, parent) else: # Non-LADM object (e.g., external boundaries) kv_item = self._create_new_item(parent) kv_item.setData(0, "{}:".format(key)) self.fill_model(values, kv_item) else: # Simple key-value pair kv_item = self._create_new_item(parent) kv_text = "{}: {}".format(key, values) kv_item.setData(0, kv_text) value_user_role = {"value": values} if key.startswith("Archivo fuente"): value_user_role.update({'url': values}) kv_item.setData(0, value_user_role, Qt.UserRole) if values is None: kv_item.setData(0, QBrush(Qt.lightGray), Qt.ForegroundRole) else: kv_item.setData(0, kv_text, Qt.ToolTipRole) # Additional item for a file preview if key.startswith("Archivo fuente"): if values: if values.startswith(DEFAULT_ENDPOINT_SOURCE_SERVICE ): # We want the thumbnail kv_subitem = self._create_new_item(kv_item) kv_subitem.setData(0, { 'type': 'img', 'url': values }, Qt.UserRole)
def __check_duplicate_records_in_table(self, db, table, rule_code): fields = LayerConfig.get_logic_consistency_tables(db.names).get(table) return self.logic_quality_rules.check_duplicate_records_in_a_table( db, table, fields, rule_code)
def convert_to_offline(self, db, surveyor_expression_dict, export_dir): sys.path.append(PLUGINS_DIR) from qfieldsync.core.layer import LayerSource, SyncAction from qfieldsync.core.offline_converter import OfflineConverter from qfieldsync.core.project import ProjectConfiguration project = QgsProject.instance() extent = QgsRectangle() offline_editing = QgsOfflineEditing() # Configure project project_configuration = ProjectConfiguration(project) project_configuration.create_base_map = False project_configuration.offline_copy_only_aoi = False project_configuration.use_layer_selection = True # Layer config layer_sync_action = LayerConfig.get_field_data_capture_layer_config( db.names) total_projects = len(surveyor_expression_dict) current_progress = 0 for surveyor, layer_config in surveyor_expression_dict.items(): export_folder = os.path.join(export_dir, surveyor) # Get layers (cannot be done out of this for loop because the project is closed and layers are deleted) layers = { layer_name: None for layer_name, _ in layer_sync_action.items() } self.app.core.get_layers(db, layers, True) if not layers: return False, QCoreApplication.translate( "FieldDataCapture", "At least one layer could not be found.") # Configure layers for layer_name, layer in layers.items(): layer_source = LayerSource(layer) layer_source.action = layer_sync_action[layer_name] if layer_name in layer_config: layer_source.select_expression = layer_config[layer_name] layer_source.apply() offline_converter = OfflineConverter(project, export_folder, extent, offline_editing) offline_converter.convert() offline_editing.layerProgressUpdated.disconnect( offline_converter.on_offline_editing_next_layer) offline_editing.progressModeSet.disconnect( offline_converter.on_offline_editing_max_changed) offline_editing.progressUpdated.disconnect( offline_converter.offline_editing_task_progress) current_progress += 1 self.total_progress_updated.emit( int(100 * current_progress / total_projects)) return True, QCoreApplication.translate( "FieldDataCapture", "{count} offline projects have been successfully created in <a href='file:///{normalized_path}'>{path}</a>!" ).format(count=total_projects, normalized_path=normalize_local_url(export_dir), path=export_dir)