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)
Example #4
0
 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
Example #6
0
    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)
Example #7
0
    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()
Example #9
0
    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()
Example #10
0
    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))
Example #13
0
    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)
Example #15
0
    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)