示例#1
0
class ChangesPerParcelPanelWidget(QgsPanelWidget, WIDGET_UI):
    def __init__(self,
                 parent,
                 utils,
                 parcel_number=None,
                 collected_parcel_t_id=None):
        QgsPanelWidget.__init__(self, None)
        self.setupUi(self)
        self.parent = parent
        self.utils = utils
        self.logger = Logger()

        self.setDockMode(True)
        self.setPanelTitle(
            QCoreApplication.translate("ChangesPerParcelPanelWidget",
                                       "Change detection per parcel"))

        self._current_supplies_substring = ""
        self._current_substring = ""

        self.utils.add_layers()
        self.fill_combos()

        # Remove selection in plot layers
        self.utils._layers[self.utils._db.names.LC_PLOT_T].removeSelection()
        self.utils._supplies_layers[
            self.utils._supplies_db.names.GC_PLOT_T].removeSelection()

        # Map tool before activate map swipe tool
        self.init_map_tool = self.utils.canvas.mapTool()

        self.active_map_tool_before_custom = None
        self.btn_identify_plot.setIcon(
            QIcon(":/Asistente-LADM-COL/resources/images/spatial_unit.png"))
        self.btn_identify_plot.clicked.connect(self.btn_plot_toggled)

        # Create maptool
        self.maptool_identify = QgsMapToolIdentifyFeature(self.utils.canvas)

        # Set connections
        self.btn_alphanumeric_query.clicked.connect(self.alphanumeric_query)
        self.chk_show_all_plots.toggled.connect(self.show_all_plots)
        self.cbo_parcel_fields.currentIndexChanged.connect(
            self.search_field_updated)
        self.panelAccepted.connect(self.initialize_tools_and_layers)
        self.tbl_changes_per_parcel.itemDoubleClicked.connect(
            self.call_party_panel)

        self.initialize_field_values_line_edit()
        self.initialize_tools_and_layers()

        if parcel_number is not None:  # Do a search!
            self.txt_alphanumeric_query.setValue(parcel_number)
            if collected_parcel_t_id is not None:  # Search data for a duplicated parcel_number, so, take the t_id into account!
                self.search_data(parcel_number=parcel_number,
                                 collected_parcel_t_id=collected_parcel_t_id)
            else:
                self.search_data(parcel_number=parcel_number)

    def btn_plot_toggled(self):
        self.clear_result_table()

        if self.btn_identify_plot.isChecked():
            self.prepare_identify_plot()
        else:
            # The button was toggled and deactivated, go back to the previous tool
            self.utils.canvas.setMapTool(self.active_map_tool_before_custom)

    def clear_result_table(self):
        self.tbl_changes_per_parcel.clearContents()
        self.tbl_changes_per_parcel.setRowCount(0)

    def prepare_identify_plot(self):
        """
            Custom Identify tool was activated, prepare everything for identifying plots
        """
        self.active_map_tool_before_custom = self.utils.canvas.mapTool()

        self.btn_identify_plot.setChecked(True)

        self.utils.canvas.mapToolSet.connect(self.initialize_maptool)

        if self.utils._supplies_layers[
                self.utils._supplies_db.names.GC_PLOT_T] is None:
            self.utils.add_layers()

        self.maptool_identify.setLayer(self.utils._supplies_layers[
            self.utils._supplies_db.names.GC_PLOT_T])
        cursor = QCursor()
        cursor.setShape(Qt.PointingHandCursor)
        self.maptool_identify.setCursor(cursor)
        self.utils.canvas.setMapTool(self.maptool_identify)

        try:
            self.maptool_identify.featureIdentified.disconnect()
        except TypeError as e:
            pass
        self.maptool_identify.featureIdentified.connect(self.get_info_by_plot)

    def get_info_by_plot(self, plot_feature):
        """
        :param plot_feature: from supplies db
        """
        plot_t_id = plot_feature[self.utils._supplies_db.names.T_ID_F]

        self.utils.canvas.flashFeatureIds(self.utils._supplies_layers[
            self.utils._supplies_db.names.GC_PLOT_T], [plot_feature.id()],
                                          QColor(255, 0, 0, 255),
                                          QColor(255, 0, 0, 0),
                                          flashes=1,
                                          duration=500)

        if not self.isVisible():
            self.show()

        self.spatial_query(plot_t_id)
        self.utils._supplies_layers[
            self.utils._supplies_db.names.GC_PLOT_T].selectByIds(
                [plot_feature.id()])

    def spatial_query(self, plot_id):
        if plot_id:
            parcel_number = self.utils.ladm_data.get_parcels_related_to_plots_supplies(
                self.utils._supplies_db, [plot_id],
                self.utils._supplies_db.names.GC_PARCEL_T_PARCEL_NUMBER_F)
            if parcel_number:  # Delegate handling of duplicates to search_data() method
                self.search_data(parcel_number=parcel_number[0])

    def call_party_panel(self, item):
        row = item.row()
        if self.tbl_changes_per_parcel.item(row, 0).text(
        ) == DICT_ALIAS_KEYS_CHANGE_DETECTION[DICT_KEY_PARTIES]:
            data = {
                SUPPLIES_DB_SOURCE:
                self.tbl_changes_per_parcel.item(row, 1).data(Qt.UserRole),
                COLLECTED_DB_SOURCE:
                self.tbl_changes_per_parcel.item(row, 2).data(Qt.UserRole)
            }
            self.parent.show_party_panel(data)

    def search_field_updated(self, index=None):
        self.initialize_field_values_line_edit()

    def initialize_field_values_line_edit(self):
        # We search for alphanumeric data in supplies data source
        self.txt_alphanumeric_query.setLayer(self.utils._supplies_layers[
            self.utils._supplies_db.names.GC_PARCEL_T])
        search_option = self.cbo_parcel_fields.currentData()
        search_field_supplies = get_supplies_search_options(
            self.utils._supplies_db.names)[search_option]
        idx = self.utils._supplies_layers[
            self.utils._supplies_db.names.GC_PARCEL_T].fields().indexOf(
                search_field_supplies)
        self.txt_alphanumeric_query.setAttributeIndex(idx)

    def fill_combos(self):
        self.cbo_parcel_fields.clear()
        self.cbo_parcel_fields.addItem(
            QCoreApplication.translate("DockWidgetChanges", "Parcel Number"),
            PARCEL_NUMBER_SEARCH_KEY)
        self.cbo_parcel_fields.addItem(
            QCoreApplication.translate("DockWidgetChanges",
                                       "Previous Parcel Number"),
            PREVIOUS_PARCEL_NUMBER_SEARCH_KEY)
        self.cbo_parcel_fields.addItem(
            QCoreApplication.translate("DockWidgetChanges",
                                       "Folio de Matrícula Inmobiliaria"),
            FMI_PARCEL_SEARCH_KEY)

    @_with_override_cursor
    def search_data(self, **kwargs):
        """
        Get plot geometries associated with parcels, both collected and supplies, zoom to them, fill comparison table
        and activate map swipe tool.

        To fill the comparison table we build two search dicts, one for supplies (already given because the alphanumeric
        search is on supplies db source), and another one for collected. For the latter, we have 3 cases. We specify
        them below (inline).

        :param kwargs: key-value (field name-field value) to search in parcel tables, both collected and supplies
                       Normally, keys are parcel_number, old_parcel_number or FMI, but if duplicates are found, an
                       additional t_id disambiguates only for the collected source. In the supplies source we assume
                       we will not find duplicates, if there are, we will choose the first record found an will not deal
                       with letting the user choose one of the duplicates by hand (as we do for the collected source).
        """
        self.chk_show_all_plots.setEnabled(False)
        self.chk_show_all_plots.setChecked(True)
        self.initialize_tools_and_layers()  # Reset any filter on layers

        plots_supplies = list()
        plots_collected = list()
        self.clear_result_table()

        search_option = self.cbo_parcel_fields.currentData()
        search_field_supplies = get_supplies_search_options(
            self.utils._supplies_db.names)[search_option]
        search_field_collected = get_collected_search_options(
            self.utils._db.names)[search_option]
        search_value = list(kwargs.values())[0]

        # Build search criterion for both supplies and collected
        search_criterion_supplies = {search_field_supplies: search_value}

        # Get supplies parcel's t_id and get related plot(s)
        expression_supplies = QgsExpression("{}='{}'".format(
            search_field_supplies, search_value))
        request = QgsFeatureRequest(expression_supplies)
        field_idx = self.utils._supplies_layers[
            self.utils._supplies_db.names.GC_PARCEL_T].fields().indexFromName(
                self.utils._supplies_db.names.T_ID_F)
        request.setFlags(QgsFeatureRequest.NoGeometry)
        request.setSubsetOfAttributes([field_idx
                                       ])  # Note: this adds a new flag
        supplies_parcels = [
            feature for feature in self.utils._supplies_layers[
                self.utils._supplies_db.names.GC_PARCEL_T].getFeatures(request)
        ]

        if len(supplies_parcels) > 1:
            # We do not expect duplicates in the supplies source!
            pass  # We'll choose the first one anyways
        elif len(supplies_parcels) == 0:
            self.logger.info(
                __name__, "No supplies parcel found! Search: {}={}".format(
                    search_field_supplies, search_value))

        supplies_plot_t_ids = []
        if supplies_parcels:
            supplies_plot_t_ids = self.utils.ladm_data.get_plots_related_to_parcels_supplies(
                self.utils._supplies_db,
                [supplies_parcels[0][self.utils._supplies_db.names.T_ID_F]],
                self.utils._supplies_db.names.T_ID_F,
                self.utils._supplies_layers[
                    self.utils._supplies_db.names.GC_PLOT_T])

            if supplies_plot_t_ids:
                self._current_supplies_substring = "\"{}\" IN ('{}')".format(
                    self.utils._supplies_db.names.T_ID_F,
                    "','".join([str(t_id) for t_id in supplies_plot_t_ids]))
                plots_supplies = self.utils.ladm_data.get_features_from_t_ids(
                    self.utils._supplies_layers[
                        self.utils._supplies_db.names.GC_PLOT_T],
                    self.utils._supplies_db.names.T_ID_F, supplies_plot_t_ids,
                    True)

        # Now get COLLECTED parcel's t_id to build the search dict for collected
        collected_parcel_t_id = None
        if 'collected_parcel_t_id' in kwargs:
            # This is the case when this panel is called and we already know the parcel number is duplicated
            collected_parcel_t_id = kwargs['collected_parcel_t_id']
            search_criterion_collected = {
                self.utils._db.names.T_ID_F: collected_parcel_t_id
            }  # As there are duplicates, we need to use t_ids
        else:
            # This is the case when:
            #   + Either this panel was called and we know the parcel number is not duplicated, or
            #   + This panel was shown without knowing about duplicates (e.g., individual parcel search) and we still
            #     need to discover whether we have duplicates for this search criterion
            search_criterion_collected = {search_field_collected: search_value}

            expression_collected = QgsExpression("{}='{}'".format(
                search_field_collected, search_value))
            request = QgsFeatureRequest(expression_collected)
            request.setFlags(QgsFeatureRequest.NoGeometry)
            request.setSubsetOfAttributes(
                [self.utils._db.names.T_ID_F],
                self.utils._layers[self.utils._db.names.LC_PARCEL_T].fields(
                ))  # Note this adds a new flag
            collected_parcels = self.utils._layers[
                self.utils._db.names.LC_PARCEL_T].getFeatures(request)
            collected_parcels_t_ids = [
                feature[self.utils._db.names.T_ID_F]
                for feature in collected_parcels
            ]

            if collected_parcels_t_ids:
                collected_parcel_t_id = collected_parcels_t_ids[0]
                if len(collected_parcels_t_ids
                       ) > 1:  # Duplicates in collected source after a search
                    QApplication.restoreOverrideCursor(
                    )  # Make sure cursor is not waiting (it is if on an identify)
                    QCoreApplication.processEvents()
                    dlg_select_parcel = SelectDuplicateParcelDialog(
                        self.utils, collected_parcels_t_ids, self.parent)
                    dlg_select_parcel.exec_()

                    if dlg_select_parcel.parcel_t_id:  # User selected one of the duplicated parcels
                        collected_parcel_t_id = dlg_select_parcel.parcel_t_id
                        search_criterion_collected = {
                            self.utils._db.names.T_ID_F: collected_parcel_t_id
                        }
                    else:
                        return  # User just cancelled the dialog, there is nothing more to do

        self.fill_table(search_criterion_supplies, search_criterion_collected)

        # Now get related plot(s) for both collected and supplies,
        if collected_parcel_t_id is not None:
            plot_t_ids = self.utils.ladm_data.get_plots_related_to_parcels(
                self.utils._db, [collected_parcel_t_id],
                self.utils._db.names.T_ID_F,
                plot_layer=self.utils._layers[self.utils._db.names.LC_PLOT_T],
                uebaunit_table=self.utils._layers[
                    self.utils._db.names.COL_UE_BAUNIT_T])

            if plot_t_ids:
                self._current_substring = "{} IN ('{}')".format(
                    self.utils._db.names.T_ID_F,
                    "','".join([str(t_id) for t_id in plot_t_ids]))
                plots_collected = self.utils.ladm_data.get_features_from_t_ids(
                    self.utils._layers[self.utils._db.names.LC_PLOT_T],
                    self.utils._db.names.T_ID_F, plot_t_ids, True)

        # Zoom to combined extent
        plot_features = plots_supplies + plots_collected  # Feature list
        plots_extent = QgsRectangle()
        for plot in plot_features:
            plots_extent.combineExtentWith(plot.geometry().boundingBox())

        if not plots_extent.isEmpty():
            self.utils.iface.mapCanvas().zoomToFeatureExtent(plots_extent)

            if plots_supplies and plots_collected:  # Otherwise the map swipe tool doesn't add any value :)
                # Activate Swipe Tool
                self.utils.app.gui.activate_layer(self.utils._supplies_layers[
                    self.utils._supplies_db.names.GC_PLOT_T])
                self.parent.activate_map_swipe_tool()

                # Send a custom mouse move on the map to make the map swipe tool's limit appear on the canvas
                coord_x = plots_extent.xMaximum() - (plots_extent.xMaximum(
                ) - plots_extent.xMinimum()) / 9  # 90%
                coord_y = plots_extent.yMaximum() - (plots_extent.yMaximum(
                ) - plots_extent.yMinimum()) / 2  # 50%

                coord_transform = self.utils.iface.mapCanvas(
                ).getCoordinateTransform()
                map_point = coord_transform.transform(coord_x, coord_y)
                widget_point = map_point.toQPointF().toPoint()
                global_point = self.utils.canvas.mapToGlobal(widget_point)

                self.utils.canvas.mousePressEvent(
                    QMouseEvent(QEvent.MouseButtonPress, global_point,
                                Qt.LeftButton, Qt.LeftButton, Qt.NoModifier))
                self.utils.canvas.mouseMoveEvent(
                    QMouseEvent(QEvent.MouseMove, widget_point + QPoint(1, 0),
                                Qt.NoButton, Qt.LeftButton, Qt.NoModifier))
                self.utils.canvas.mouseReleaseEvent(
                    QMouseEvent(QEvent.MouseButtonRelease,
                                widget_point + QPoint(1, 0), Qt.LeftButton,
                                Qt.LeftButton, Qt.NoModifier))

        # Once the query is done, activate the checkbox to alternate all plots/only selected plot
        self.chk_show_all_plots.setEnabled(True)

    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:
            Symbology().get_style_group_layer_modifiers(
                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 fill_row(self, field_name, supplies_value, collected_value, row,
                 plural):
        item = QTableWidgetItem(field_name)
        # item.setData(Qt.UserRole, parcel_attrs[self.names.T_ID_F])
        self.tbl_changes_per_parcel.setItem(row, 0, item)

        if field_name == DICT_ALIAS_KEYS_CHANGE_DETECTION[DICT_KEY_PARTIES]:
            item = self.fill_party_item(supplies_value)
            self.tbl_changes_per_parcel.setItem(row, 1, item)

            item = self.fill_party_item(collected_value)
            self.tbl_changes_per_parcel.setItem(row, 2, item)

            self.tbl_changes_per_parcel.setItem(row, 3, QTableWidgetItem())
            self.tbl_changes_per_parcel.item(row, 3).setBackground(
                Qt.green if supplies_value == collected_value else Qt.red)
        else:
            item = QTableWidgetItem(
                str(supplies_value) if supplies_value != NULL else '')
            #item.setData(Qt.UserRole, parcel_attrs[self.names.T_ID_F])
            self.tbl_changes_per_parcel.setItem(row, 1, item)

            item = QTableWidgetItem(
                str(collected_value) if collected_value != NULL else '')
            # item.setData(Qt.UserRole, parcel_attrs[self.names.T_ID_F])
            self.tbl_changes_per_parcel.setItem(row, 2, item)

            self.tbl_changes_per_parcel.setItem(row, 3, QTableWidgetItem())
            self.tbl_changes_per_parcel.item(row, 3).setBackground(
                Qt.green if supplies_value == collected_value else Qt.red)

    def fill_party_item(self, value):
        # Party's info comes in a list or a list of lists if it's a group party
        display_value = ''

        if value != NULL:
            if type(value) is list and value:
                display_value = "{} {}".format(
                    len(value),
                    QCoreApplication.translate("DockWidgetChanges", "parties")
                    if len(value) > 1 else QCoreApplication.translate(
                        "DockWidgetChanges", "party"))
        #else:
        #    display_value = QCoreApplication.translate("DockWidgetChanges", "0 parties")

        item = QTableWidgetItem(display_value)
        item.setData(Qt.UserRole, value)
        return item

    def fill_geometry_row(self, field_name, supplies_geom, collected_geom,
                          row):
        self.tbl_changes_per_parcel.setItem(
            row, 0,
            QTableWidgetItem(
                QCoreApplication.translate("DockWidgetChanges", "Geometry")))
        self.tbl_changes_per_parcel.setItem(
            row, 1,
            QTableWidgetItem(self.get_geometry_type_name(supplies_geom)))
        self.tbl_changes_per_parcel.setItem(
            row, 2,
            QTableWidgetItem(self.get_geometry_type_name(collected_geom)))

        self.tbl_changes_per_parcel.setItem(row, 3, QTableWidgetItem())
        self.tbl_changes_per_parcel.item(row, 3).setBackground(
            Qt.green if self.utils.compare_features_geometries(
                collected_geom, supplies_geom) else Qt.red)

    @staticmethod
    def get_geometry_type_name(geometry):
        if geometry is None:
            return QCoreApplication.translate("DockWidgetChanges",
                                              "No associated plot")
        elif geometry.type() == QgsWkbTypes.UnknownGeometry:
            return ''
        elif geometry.type() == QgsWkbTypes.PolygonGeometry:
            return QCoreApplication.translate("DockWidgetChanges", "Polygon")
        else:
            return "Type: {}".format(geometry.type())

    def alphanumeric_query(self):
        """
        Alphanumeric query (On supplies db)
        """
        option = self.cbo_parcel_fields.currentData()
        query = self.txt_alphanumeric_query.value()
        if query:
            if option == FMI_PARCEL_SEARCH_KEY:
                self.search_data(parcel_fmi=query)
            elif option == PARCEL_NUMBER_SEARCH_KEY:
                self.search_data(parcel_number=query)
            else:  # previous_parcel_number
                self.search_data(previous_parcel_number=query)

        else:
            self.utils.iface.messageBar().pushMessage(
                "Asistente LADM-COL",
                QCoreApplication.translate("DockWidgetChanges",
                                           "First enter a query"))

    def show_all_plots(self, state):
        try:
            self.utils._supplies_layers[
                self.utils._supplies_db.names.GC_PLOT_T].setSubsetString(
                    self._current_supplies_substring if not state else "")
        except RuntimeError:  # If the layer was previously removed
            pass

        try:
            self.utils._layers[self.utils._db.names.LC_PLOT_T].setSubsetString(
                self._current_substring if not state else "")
        except RuntimeError:  # If the layer was previously removed
            pass

    def initialize_tools_and_layers(self, panel=None):
        self.parent.deactivate_map_swipe_tool()
        self.show_all_plots(True)

    def initialize_maptool(self, new_tool, old_tool):
        if self.maptool_identify == old_tool:
            # custom identify was deactivated
            try:
                self.utils.canvas.mapToolSet.disconnect(
                    self.initialize_maptool)
            except TypeError as e:
                pass

            self.btn_identify_plot.setChecked(False)
        else:
            # custom identify was activated
            pass

    def close_panel(self):
        self.show_all_plots(
            True
        )  # Remove filter in plots layers if it was activate and panel is closed
        # custom identify was deactivated
        try:
            self.utils.canvas.mapToolSet.disconnect(self.initialize_maptool)
        except TypeError as e:
            pass

        self.utils.canvas.setMapTool(self.init_map_tool)
class TransfoPtToPlot(QDialog, gui_dlg_transfo_pttoplot):
    
    def __init__(self, canvas, project, l_vertex, l_edge, parent=None):

        super(TransfoPtToPlot, self).__init__(parent)
        self.setupUi(self)

        self.canvas = canvas
        self.project = project
        self.l_edge = l_edge
        self.l_vertex = l_vertex
        
        self.sel_nw_vtx = None
                
        self.resize_dlg = ResizeDlg(self, "dlg_transfo_pt_to_plots")
        self.resize_params = self.resize_dlg.load_dlgresize()
        self.resize_on = self.resize_params["dlg_transfo_pt_to_plots"]
        
        self.buttValid.clicked.connect(self.close)
        self.buttResize.clicked.connect(self.resize_dlg.dlg_ch_resize)
        self.selrfuvtxnearButt.clicked.connect(self.sel_nwvtxnear_rfu)
        self.nearvtxvalButt.clicked.connect(self.nwvtx_valid)
        self.selnwvxtButt.clicked.connect(self.sel_nwvtxfar)
        self.selrfuvtxfarButt.clicked.connect(self.sel_rfuvtxfar)
        self.nearvtxTbv.clicked.connect(self.tbv_sel)
        
        # Delete Widget on close event
        self.setAttribute(Qt.WA_DeleteOnClose)
 
    # Zoom to 2 new + RFU vertices if a line is selected in the tableview
    def tbv_sel(self):
        # Find the selected cell (considering only the first selected cell)
        idx = self.nearvtxTbv.selectedIndexes()[0].row()
        # Find the new vertex feature and the near RFU vertex feature
        self.sel_nw_vtx = self.nr_feats[idx]
        id_rfu_vtx = self.nr_feats[idx]["point_rfu_proche"]
        rfu_vtx = feats_by_cond(self.l_vertex, r"@id_noeud", id_rfu_vtx)[0]
        # Zoom to the 2 features
        self.canvas.zoomToFeatureIds(self.l_vertex, [self.sel_nw_vtx.id(), rfu_vtx.id()])

    # Let the user select the new vertex to transform into a plot
    def sel_nwvtxfar(self):
        # Selection in the canvas
        self.hide()
        self.identify_nwvtxfar_vtx = QgsMapToolIdentifyFeature(self.canvas, self.l_vertex)
        self.identify_nwvtxfar_vtx.setCursor(QCursor(Qt.PointingHandCursor))
        self.identify_nwvtxfar_vtx.featureIdentified.connect(self.far_nwvtx_identified)
        self.canvas.setMapTool(self.identify_nwvtxfar_vtx)

    def far_nwvtx_identified(self, feat):
        self.l_vertex.selectByIds([feat.id()])
        # Check if the point selected is a new vertex
        if not feat[r"@id_noeud"]:
            self.sel_nw_vtx = feat
            self.canvas.unsetMapTool(self.identify_nwvtxfar_vtx)
            self.dlg_show()
        else:
            QMessageBox.warning(self, tr_vtxplt_notnwvtx_msg[0], tr_vtxplt_notnwvtx_msg[1])
       
    
    # Let the user select the RFU vertex to use with the far new vertex
    def sel_rfuvtxfar(self):
        # Selection in the canvas
        if self.sel_nw_vtx:
            self.hide()
            self.identify_rfuvtxfar_vtx = QgsMapToolIdentifyFeature(self.canvas, self.l_vertex)
            self.identify_rfuvtxfar_vtx.setCursor(QCursor(Qt.PointingHandCursor))
            self.identify_rfuvtxfar_vtx.featureIdentified.connect(partial(self.rfu_vtx_identified, "far"))
            self.canvas.setMapTool(self.identify_rfuvtxfar_vtx)
        # Message if no line selected in the tableview
        else:
            QMessageBox.warning(self, tr_vtxplt_sel_nonwvtxsel_msg[0], tr_vtxplt_sel_nonwvtxsel_msg[1])  

    # Let the user select the RFU vertex near the new vertex
    def sel_nwvtxnear_rfu(self):
        # Selection in the canvas
        if self.sel_nw_vtx:
            self.hide()
            self.identify_rfu_vtx = QgsMapToolIdentifyFeature(self.canvas, self.l_vertex)
            self.identify_rfu_vtx.setCursor(QCursor(Qt.PointingHandCursor))
            self.identify_rfu_vtx.featureIdentified.connect(partial(self.rfu_vtx_identified, "near"))
            self.canvas.setMapTool(self.identify_rfu_vtx)
        # Message if no line selected in the tablview
        else:
            QMessageBox.warning(self, tr_vtxplt_sel_nolinesel_msg[0], tr_vtxplt_sel_nolinesel_msg[1])
        
    def rfu_vtx_identified(self, vtx_type, feat):
        self.vtx_type = vtx_type
        self.l_vertex.selectByIds([feat.id()])
        if self.vtx_type == "near":
            self.canvas.unsetMapTool(self.identify_rfu_vtx)
        else:
            self.canvas.unsetMapTool(self.identify_rfuvtxfar_vtx)
        # Check if the point selected is a RFU vertex
        if feat[r"@id_noeud"]:
            id_node = feat[r"@id_noeud"]
            # Tolerance in cm
            tol = feat[r"som_tolerance"]*100
            nw_coord_e = self.sel_nw_vtx["som_coord_est"]
            nw_coord_n = self.sel_nw_vtx["som_coord_nord"]
            nw_rep_plane = self.sel_nw_vtx["som_representation_plane"]
            nw_pt_cc = QgsPointXY(self.sel_nw_vtx["som_coord_est"], self.sel_nw_vtx["som_coord_nord"])
            rfu_pt_cc = QgsPointXY(feat["som_coord_est"], feat["som_coord_nord"])
            # Distance between the 2 points in cm
            dist_vtx = dist_2_pts(nw_pt_cc, rfu_pt_cc)*100
            if dist_vtx < tol:
                self.vtx_type = "near"
            # Check if the 2 points have the same som_representation_plane
            # Otherwise, cancel the process
            if nw_rep_plane == feat["som_representation_plane"]:
                if self.vtx_type == "near":
                    tl_msg = tr_vtxplt_confirm_msg[0]
                    txt_msg = tr_vtxplt_confirm_msg[1].format(nw_coord_e, nw_coord_n, id_node)
                else:
                    tl_msg = tr_vtxplt_attest_msg[0]
                    txt_msg = tr_vtxplt_attest_msg[1].format(nw_coord_e, nw_coord_n, id_node, dist_vtx, tol)
                confirm = QMessageBox.question( self, tl_msg, txt_msg, 
                                                QMessageBox.Yes | QMessageBox.No)
                if confirm == QMessageBox.Yes:
                    nw_vals = {}
                    for att in tr_toplot_atts:
                        id_att = self.l_vertex.fields().indexFromName(att)
                        nw_vals[id_att] = self.sel_nw_vtx[att]
                    # Change the atteste_qualite value
                    if self.vtx_type == "far":
                        id_att = self.l_vertex.fields().indexFromName("attestation_qualite")
                        nw_vals[id_att] = "true"
                    self.l_vertex.changeAttributeValues(feat.id(), nw_vals)
                    self.l_vertex.deleteFeature(self.sel_nw_vtx.id())
                    self.tr_edges(self.sel_nw_vtx.geometry(), feat.geometry())
                    self.canvas.refresh()
                    QMessageBox.information(
                                self, 
                                tr_vtxplot_transfok_msg[0], 
                                tr_vtxplot_transfok_msg[1].format(nw_coord_e, nw_coord_n, id_node))
                # Process canceled by the user    
                else:
                    QMessageBox.information(self, tr_vtxplt_canceld_msg[0], tr_vtxplt_canceld_msg[1])
            # Case of no same som_representation_plane
            else:
                QMessageBox.warning(self, tr_vtxplot_nosamerp_msg[0], tr_vtxplot_nosamerp_msg[1])
            self.nearvtxTbv.clearSelection()
            self.sel_nw_vtx = None
            # Deselect point
            self.l_vertex.selectByIds([])
            self.dlg_show()
        else:
            QMessageBox.warning(self, tr_vtxplt_notrfuvtx_msg[0], tr_vtxplt_notrfuvtx_msg[1])
            if self.vtx_type == "near":
                self.sel_nwvtxnear_rfu()
            else:
                self.sel_rfuvtxfar()
        
    # Move edges if they are linked to a new vertex transformed into plot
    def tr_edges(self, old_geom, nw_geom):
        # Transformations to obtain the WGS84 or the CC coordinates
        coords_tr_wgs, coords_tr_cc = crs_trans_params(self.canvas, self.project)
        old_geom_pt = old_geom.asPoint()
        nw_geom_pt = nw_geom.asPoint()
        old_geom_cc = coords_tr_cc.transform(old_geom_pt)
        # Process only new edges
        nw_edges = feats_by_cond(self.l_edge, "@id_arc", NULL)
        if len(nw_edges) > 0:
            for edge_ft in nw_edges:
                ch_geom = False
                edge_ft_line = edge_ft.geometry().asPolyline()
                start_pt = edge_ft_line[0]
                end_pt = edge_ft_line[-1]
                # Comparison done on cc coordinates
                start_pt_cc = coords_tr_cc.transform(start_pt)
                end_pt_cc = coords_tr_cc.transform(end_pt)  
                # Case of start point to move
                if check_identical_pts(old_geom_cc, start_pt_cc, 2):
                    self.l_edge.moveVertex(nw_geom_pt.x(), nw_geom_pt.y(), edge_ft.id(), 0)
                    nw_line_g = QgsGeometry.fromPolylineXY([nw_geom_pt, end_pt])
                    ch_geom = True
                # Case of end point to move
                if check_identical_pts(old_geom_cc, end_pt_cc, 2):
                    self.l_edge.moveVertex(nw_geom_pt.x(), nw_geom_pt.y(), edge_ft.id(), 1)
                    nw_line_g = QgsGeometry.fromPolylineXY([start_pt, nw_geom_pt])
                    ch_geom = True
                # Check if new line is the same as an existing edge_ft
                # In this case, delete the new line
                if ch_geom:
                    for old_edge_ft in self.l_edge.getFeatures():
                        if old_edge_ft.id() != edge_ft.id() and \
                            check_identical_lines(old_edge_ft.geometry().asPolyline(), nw_line_g.asPolyline(), 12):
                            self.l_edge.deleteFeature(edge_ft.id())
    
    
    # Let the user valid the new vertex
    def nwvtx_valid(self):       
        # Reset the point_rfu_proche field
        if self.sel_nw_vtx:
            self.l_vertex.changeAttributeValue(self.sel_nw_vtx.id(), 10, NULL)
            # self.l_vertex.commitChanges()
            self.canvas.refresh()
            QMessageBox.information(self, tr_vtxplt_valid_msg[0], tr_vtxplt_valid_msg[1].format(self.sel_nw_vtx["som_coord_est"], self.sel_nw_vtx["som_coord_nord"]))
            self.nearvtxTbv.clearSelection()
            self.sel_nw_vtx = None
            self.hide()
            self.dlg_show()
        # Message if no line selected in the tablview
        else:
            QMessageBox.warning(self, tr_vtxplt_nolinesel_msg[0], tr_vtxplt_nolinesel_msg[1])

    
    # Launch the dlg appearence
    def dlg_show(self):
                                 
        self.nr_feats = []
        # Create the tableview
        self.tr_vtxtbl_data = []
        tr_vtxtbl_hd = []
        # Build the header
        for fld_name in tr_vtx_atts:
            tr_vtxtbl_hd.append(fld_name)
        # Build the contents
        nb_rows = 0
        for obj in self.l_vertex.getFeatures():
            if obj['point_rfu_proche']:
                tr_vtxtbl_row = []
                for fld_name in tr_vtx_atts:
                    tr_vtxtbl_row.append(str(obj[fld_name]))
                self.tr_vtxtbl_data.append(tr_vtxtbl_row)
                self.nr_feats.append(obj)
                nb_rows += 1
        if nb_rows != 0:
            tr_vtxtbl_model=MyTableModel(self, self.tr_vtxtbl_data, tr_vtxtbl_hd)
            # Populate data in the tableview
            self.nearvtxTbv.setModel(tr_vtxtbl_model)
            self.height_tbv = 0
            self.width_tbv = 0
            # Set column width to fit contents
            self.nearvtxTbv.resizeColumnsToContents()
            # Increase a little bit the width of the columns
            for id_col, val_col in enumerate(tr_vtxtbl_hd):
                nw_size = self.nearvtxTbv.columnWidth(id_col) + 5
                self.nearvtxTbv.setColumnWidth(id_col, nw_size)
                self.width_tbv += nw_size
            # Set row height
            self.nearvtxTbv.resizeRowsToContents()
            self.height_tbv = (self.nearvtxTbv.rowHeight(0)) * (nb_rows+1)
            self.width_tbv += 45
            self.height_tbv += 330
            self.resize_dlg.wtbv = self.width_tbv
            self.resize_dlg.htbv = self.height_tbv
            # Hide vertical header
            vh = self.nearvtxTbv.verticalHeader()
            vh.setVisible(False)
        else:
            self.nearvtxGp.hide()
            self.width_tbv = dlg_transfo_pt_to_plots_sw
            self.height_tbv = 176
            self.resize_dlg.wtbv = self.width_tbv
            self.resize_dlg.htbv = self.height_tbv
        if self.resize_on:
            self.resize_dlg.dlg_auto_resize()
        self.show()
        
   
    def to_close(self):
        self.close()
class EdgeCreator(QDockWidget, gui_dckwdgt_edge_creator):
    def __init__(self,
                 canvas,
                 l_vertex,
                 l_edge,
                 user=None,
                 auth_creator=[],
                 parent=None):

        super(EdgeCreator, self).__init__(parent)
        self.setupUi(self)

        # Delete Widget on close event..
        self.setAttribute(Qt.WA_DeleteOnClose)

        self.save = False

        self.canvas = canvas
        self.l_edge = l_edge
        self.l_vertex = l_vertex
        self.user = user
        self.auth_creator = auth_creator

        self.vertices = self.l_vertex.getFeatures()
        self.vtx_start = None
        self.vtx_end = None
        self.selected_vertices = [None, None]

        self.edge = None

        for i, vertex in enumerate(self.vertices):

            self.startVertexComboBox.insertItem(i, str(vertex.id()))
            self.startVertexComboBox.setItemData(i, vertex, 32)
            self.startVertexComboBox.setCurrentIndex(-1)

            self.endVertexComboBox.insertItem(i, str(vertex.id()))
            self.endVertexComboBox.setItemData(i, vertex, 32)
            self.endVertexComboBox.setCurrentIndex(-1)

        # Attribute: `som_createur`
        for i, e in enumerate(self.auth_creator):
            self.creatorComboBox.addItem(u"%s (%s)" % (e[1], e[0]))
            if self.user == e[0]:
                self.creatorComboBox.setCurrentIndex(i)

        self.startVertextoolButton.clicked.connect(
            self.select_start_vertex_on_canvas)
        self.endVertextoolButton.clicked.connect(
            self.select_end_vertex_on_canvas)

        self.startVertexComboBox.highlighted.connect(self.on_vtx_start_pressed)
        self.endVertexComboBox.highlighted.connect(self.on_vtx_end_pressed)
        self.startVertexComboBox.currentIndexChanged.connect(
            self.on_vtx_start_pressed)
        self.endVertexComboBox.currentIndexChanged.connect(
            self.on_vtx_end_pressed)

        self.startVertexComboBox.highlighted.connect(self.create_edge)
        self.endVertexComboBox.highlighted.connect(self.create_edge)
        self.startVertexComboBox.currentIndexChanged.connect(self.create_edge)
        self.endVertexComboBox.currentIndexChanged.connect(self.create_edge)

        self.buttonBox.accepted.connect(self.on_accepted)
        self.buttonBox.rejected.connect(self.on_rejected)
        self.buttonBox.button(QDialogButtonBox.Reset).clicked.connect(
            self.on_reset)

    def closeEvent(self, event):
        if not self.save:
            self.on_rejected()

    def select_start_vertex_on_canvas(self):

        self.identify_start_vertex = QgsMapToolIdentifyFeature(
            self.canvas, self.l_vertex)
        self.identify_start_vertex.setCursor(QCursor(Qt.PointingHandCursor))
        self.identify_start_vertex.featureIdentified.connect(
            self.on_start_vertex_identified)
        self.canvas.setMapTool(self.identify_start_vertex)

    def select_end_vertex_on_canvas(self):

        self.identify_end_vertex = QgsMapToolIdentifyFeature(
            self.canvas, self.l_vertex)
        self.identify_end_vertex.setCursor(QCursor(Qt.PointingHandCursor))
        self.identify_end_vertex.featureIdentified.connect(
            self.on_end_vertex_identified)
        self.canvas.setMapTool(self.identify_end_vertex)

    def on_start_vertex_identified(self, feature):

        cb = self.startVertexComboBox
        items = [cb.itemText(i) for i in range(cb.count())]
        for i, e in enumerate(items):
            if int(feature.id()) == int(e):
                cb.setCurrentIndex(i)

    def on_end_vertex_identified(self, feature):

        cb = self.endVertexComboBox
        items = [cb.itemText(i) for i in range(cb.count())]
        for i, e in enumerate(items):
            if int(feature.id()) == int(e):
                cb.setCurrentIndex(i)

    def on_vtx_start_pressed(self, idx):

        self.vtx_start = self.startVertexComboBox.itemData(idx, 32)
        self.select_vertices(self.vtx_start, 0)

        self.endVertexComboBox.setEnabled(True)
        self.endVertextoolButton.setEnabled(True)

    def on_vtx_end_pressed(self, idx):

        self.vtx_end = self.endVertexComboBox.itemData(idx, 32)
        self.select_vertices(self.vtx_end, 1)

        self.creatorComboBox.setEnabled(True)

    def select_vertices(self, feature, i):
        if feature:
            self.selected_vertices[i] = feature.id()
        else:
            self.selected_vertices[i] = None
        self.l_vertex.setSelectedFeatures(self.selected_vertices)

    def unselect_vertices(self):
        self.l_vertex.setSelectedFeatures([])

    def create_edge(self):

        # If edge already exists, delete it..
        if self.edge:
            self.l_edge.deleteFeature(self.edge.id())

        # Two vertices are needed..
        if not self.vtx_start or not self.vtx_end:
            return self.canvas.refresh()

        # Two DIFFERENT vertices..
        if self.vtx_start == self.vtx_end:
            return self.canvas.refresh()

        # Create line geometry..
        line = QgsGeometry.fromPolyline([
            self.vtx_start.geometry().asPoint(),
            self.vtx_end.geometry().asPoint()
        ])

        # Create the feature..
        self.edge = QgsFeature()
        self.edge.setGeometry(line)
        self.edge.setFields(self.l_edge.pendingFields())
        self.edge.setAttributes(
            [QPyNullVariant(int),
             QPyNullVariant(int),
             QPyNullVariant(int)])

        # Add feature to layer..
        self.l_edge.addFeature(self.edge)
        self.canvas.refresh()

    def on_accepted(self):

        if not self.edge:
            return False

        self.lim_ge_createur = self.auth_creator[
            self.creatorComboBox.currentIndex()][0]
        self.edge.setAttributes(
            [QPyNullVariant(int),
             QPyNullVariant(int), self.lim_ge_createur])
        self.l_edge.updateFeature(self.edge)
        self.canvas.refresh()
        self.save = True
        self.close()

    def on_rejected(self):

        # Do not save the feature..
        if self.edge:
            self.l_edge.deleteFeature(self.edge.id())

        self.unselect_vertices()
        self.canvas.refresh()
        self.close()

    def on_reset(self):

        self.startVertexComboBox.setCurrentIndex(0)
        # self.startVertexComboBox.setEnabled(True)
        # self.startVertexLabel.setEnabled(True)

        self.endVertexComboBox.setCurrentIndex(0)
        self.endVertexComboBox.setEnabled(False)
        self.endVertexLabel.setEnabled(False)
        self.endVertextoolButton.setEnabled(False)

        for i, e in enumerate(self.auth_creator):
            if self.user == e[0]:
                self.creatorComboBox.setCurrentIndex(i)
        self.creatorComboBox.setEnabled(False)
        self.creatorLabel.setEnabled(False)

        self.unselect_vertices()
        self.canvas.refresh()
class DockWidgetQueries(QgsDockWidget, DOCKWIDGET_UI):

    zoom_to_features_requested = pyqtSignal(QgsVectorLayer, list, dict,
                                            int)  # layer, ids, t_ids, duration

    def __init__(self, iface, db, qgis_utils, ladm_data, parent=None):
        super(DockWidgetQueries, self).__init__(None)
        self.setupUi(self)
        self.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)
        self.iface = iface
        self._db = db
        self.qgis_utils = qgis_utils
        self.ladm_data = ladm_data
        self.logger = Logger()
        self.canvas = iface.mapCanvas()
        self.active_map_tool_before_custom = None
        self.names = self._db.names

        self.clipboard = QApplication.clipboard()

        # Required layers
        self.restart_dict_of_layers()

        self._identify_tool = None

        self.add_layers()
        self.fill_combos()

        self.btn_identify_plot.setIcon(
            QIcon(":/Asistente-LADM_COL/resources/images/spatial_unit.png"))

        # Set connections
        self.btn_alphanumeric_query.clicked.connect(self.alphanumeric_query)
        self.cbo_parcel_fields.currentIndexChanged.connect(
            self.search_field_updated)
        self.btn_identify_plot.clicked.connect(self.btn_plot_toggled)

        # Context menu
        self._set_context_menus()

        # Create maptool
        self.maptool_identify = QgsMapToolIdentifyFeature(self.canvas)

        self.initialize_field_values_line_edit()

    def search_field_updated(self, index=None):
        self.initialize_field_values_line_edit()

    def initialize_field_values_line_edit(self):
        self.txt_alphanumeric_query.setLayer(
            self._layers[self.names.OP_PARCEL_T][LAYER])
        idx = self._layers[self.names.OP_PARCEL_T][LAYER].fields().indexOf(
            self.cbo_parcel_fields.currentData())
        self.txt_alphanumeric_query.setAttributeIndex(idx)

    def _set_context_menus(self):
        self.tree_view_basic.setContextMenuPolicy(Qt.CustomContextMenu)
        self.tree_view_basic.customContextMenuRequested.connect(
            self.show_context_menu)

        self.tree_view_legal.setContextMenuPolicy(Qt.CustomContextMenu)
        self.tree_view_legal.customContextMenuRequested.connect(
            self.show_context_menu)

        self.tree_view_property_record_card.setContextMenuPolicy(
            Qt.CustomContextMenu)
        self.tree_view_property_record_card.customContextMenuRequested.connect(
            self.show_context_menu)

        self.tree_view_physical.setContextMenuPolicy(Qt.CustomContextMenu)
        self.tree_view_physical.customContextMenuRequested.connect(
            self.show_context_menu)

        self.tree_view_economic.setContextMenuPolicy(Qt.CustomContextMenu)
        self.tree_view_economic.customContextMenuRequested.connect(
            self.show_context_menu)

    def restart_dict_of_layers(self):
        self._layers = {
            self.names.OP_PLOT_T: {
                'name': self.names.OP_PLOT_T,
                'geometry': QgsWkbTypes.PolygonGeometry,
                LAYER: None
            },
            self.names.OP_PARCEL_T: {
                'name': self.names.OP_PARCEL_T,
                'geometry': None,
                LAYER: None
            },
            self.names.COL_UE_BAUNIT_T: {
                'name': self.names.COL_UE_BAUNIT_T,
                'geometry': None,
                LAYER: None
            }
        }

    def add_layers(self):
        self.qgis_utils.get_layers(self._db, self._layers, load=True)
        if not self._layers:
            self.restart_dict_of_layers()  # Let it ready for the next call
            return None

        # Layer was found, listen to its removal so that we can deactivate the custom tool when that occurs
        try:
            self._layers[self.names.OP_PLOT_T][LAYER].willBeDeleted.disconnect(
                self.layer_removed)
        except TypeError as e:
            pass
        self._layers[self.names.OP_PLOT_T][LAYER].willBeDeleted.connect(
            self.layer_removed)

        # Layer was found, listen to its removal so that we can update the variable properly
        try:
            self._layers[
                self.names.OP_PARCEL_T][LAYER].willBeDeleted.disconnect(
                    self.parcel_layer_removed)
        except TypeError as e:
            pass
        self._layers[self.names.OP_PARCEL_T][LAYER].willBeDeleted.connect(
            self.parcel_layer_removed)

        # Layer was found, listen to its removal so that we can update the variable properly
        try:
            self._layers[
                self.names.COL_UE_BAUNIT_T][LAYER].willBeDeleted.disconnect(
                    self.uebaunit_table_removed)
        except TypeError as e:
            pass
        self._layers[self.names.COL_UE_BAUNIT_T][LAYER].willBeDeleted.connect(
            self.uebaunit_table_removed)

    def initialize_tool(self):
        self._layers[self.names.OP_PLOT_T][LAYER] = None
        self.initialize_tools(new_tool=None, old_tool=self.maptool_identify)
        self.btn_plot_toggled()

    def update_db_connection(self, db, ladm_col_db, db_source):
        self._db = db
        self.initialize_tool()

        if not ladm_col_db:
            self.setVisible(False)

    def layer_removed(self):
        # The required layer was removed, deactivate custom tool
        self.initialize_tool()

    def parcel_layer_removed(self):
        self._layers[self.names.OP_PARCEL_T][LAYER] = None

    def uebaunit_table_removed(self):
        self._layers[self.names.COL_UE_BAUNIT_T][LAYER] = None

    def fill_combos(self):
        self.cbo_parcel_fields.clear()

        self.cbo_parcel_fields.addItem(
            QCoreApplication.translate("DockWidgetQueries", "Parcel Number"),
            self.names.OP_PARCEL_T_PARCEL_NUMBER_F)
        self.cbo_parcel_fields.addItem(
            QCoreApplication.translate("DockWidgetQueries",
                                       "Previous Parcel Number"),
            self.names.OP_PARCEL_T_PREVIOUS_PARCEL_NUMBER_F)
        self.cbo_parcel_fields.addItem(
            QCoreApplication.translate("DockWidgetQueries",
                                       "Folio de Matrícula Inmobiliaria"),
            self.names.OP_PARCEL_T_FMI_F)

    def initialize_tools(self, new_tool, old_tool):
        if self.maptool_identify == old_tool:
            # custom identify was deactivated
            try:
                self.canvas.mapToolSet.disconnect(self.initialize_tools)
            except TypeError as e:
                pass
            self.btn_identify_plot.setChecked(False)
        else:
            # custom identify was activated
            pass

    def btn_plot_toggled(self):
        if self.btn_identify_plot.isChecked():
            self.prepare_identify_plot()
        else:
            # The button was toggled and deactivated, go back to the previous tool
            self.canvas.setMapTool(self.active_map_tool_before_custom)

    def prepare_identify_plot(self):
        """
            Custom Identify tool was activated, prepare everything for identifying plots
        """
        self.active_map_tool_before_custom = self.canvas.mapTool()

        self.btn_identify_plot.setChecked(True)

        self.canvas.mapToolSet.connect(self.initialize_tools)

        if self._layers[self.names.OP_PLOT_T][LAYER] is None:
            self.add_layers()

        self.maptool_identify.setLayer(
            self._layers[self.names.OP_PLOT_T][LAYER])
        cursor = QCursor()
        cursor.setShape(Qt.PointingHandCursor)
        self.maptool_identify.setCursor(cursor)
        self.canvas.setMapTool(self.maptool_identify)

        try:
            self.maptool_identify.featureIdentified.disconnect()
        except TypeError as e:
            pass
        self.maptool_identify.featureIdentified.connect(self.get_info_by_plot)

    def get_info_by_plot(self, plot_feature):
        plot_t_id = plot_feature[self.names.T_ID_F]
        self.canvas.flashFeatureIds(self._layers[self.names.OP_PLOT_T][LAYER],
                                    [plot_feature.id()],
                                    QColor(255, 0, 0, 255),
                                    QColor(255, 0, 0, 0),
                                    flashes=1,
                                    duration=500)

        with OverrideCursor(Qt.WaitCursor):
            if not self.isVisible():
                self.show()

            self.search_data_by_component(plot_t_id=plot_t_id,
                                          zoom_and_select=False)
            self._layers[self.names.OP_PLOT_T][LAYER].selectByIds(
                [plot_feature.id()])

    def search_data_by_component(self, **kwargs):
        self._layers[self.names.OP_PLOT_T][LAYER].removeSelection()

        # Read zoom_and_select parameter and remove it from kwargs
        bZoom = False
        if 'zoom_and_select' in kwargs:
            bZoom = kwargs['zoom_and_select']
            del kwargs['zoom_and_select']

        records = self._db.get_igac_basic_info(**kwargs)
        self.setup_tree_view(self.tree_view_basic, records)

        if bZoom:
            # Zoom to resulting plots
            plot_t_ids = self.get_plot_t_ids_from_basic_info(records)
            if plot_t_ids:
                features = self.ladm_data.get_features_from_t_ids(
                    self._layers[self.names.OP_PLOT_T][LAYER],
                    self.names.T_ID_F, plot_t_ids, True, True)
                plot_ids = [feature.id() for feature in features]
                self.zoom_to_features_requested.emit(
                    self._layers[self.names.OP_PLOT_T][LAYER], plot_ids,
                    dict(), 500)
                self._layers[self.names.OP_PLOT_T][LAYER].selectByIds(plot_ids)

        records = self._db.get_igac_legal_info(**kwargs)
        self.setup_tree_view(self.tree_view_legal, records)

        records = self._db.get_igac_property_record_card_info(**kwargs)
        self.setup_tree_view(self.tree_view_property_record_card, records)

        records = self._db.get_igac_physical_info(**kwargs)
        self.setup_tree_view(self.tree_view_physical, records)

        records = self._db.get_igac_economic_info(**kwargs)
        self.setup_tree_view(self.tree_view_economic, records)

    def setup_tree_view(self, tree_view, records):
        """
        Configure result tree views

        :param tree_view:
        :return:
        """
        tree_view.setModel(TreeModel(self.names, data=records))
        tree_view.expandAll()
        self.add_thumbnails_to_tree_view(tree_view)

    def add_thumbnails_to_tree_view(self, tree_view):
        """
        Gets a list of model indexes corresponding to extFiles objects to show a preview

        :param model:
        :return:
        """
        model = tree_view.model()
        indexes = model.getPixmapIndexList()
        for idx in indexes:
            url = model.data(idx, Qt.UserRole)['url']
            res, image = self.download_image("{}{}".format(
                url, SUFFIX_GET_THUMBNAIL))
            if res:
                pixmap = QPixmap()
                pixmap.loadFromData(image)
                label = QLabel()
                label.setPixmap(pixmap)
                tree_view.setIndexWidget(idx, label)

    def get_plot_t_ids_from_basic_info(self, records):
        res = []
        if records:
            for record in records:
                if self.names.OP_PLOT_T in record:
                    for element in record[self.names.OP_PLOT_T]:
                        res.append(element['id'])

        return res

    def alphanumeric_query(self):
        """
        Alphanumeric query
        """
        option = self.cbo_parcel_fields.currentData()
        query = self.txt_alphanumeric_query.value()
        if query:
            if option == self.names.OP_PARCEL_T_FMI_F:
                self.search_data_by_component(parcel_fmi=query,
                                              zoom_and_select=True)
            elif option == self.names.OP_PARCEL_T_PARCEL_NUMBER_F:
                self.search_data_by_component(parcel_number=query,
                                              zoom_and_select=True)
            else:  # previous_parcel_number
                self.search_data_by_component(previous_parcel_number=query,
                                              zoom_and_select=True)
        else:
            self.iface.messageBar().pushMessage(
                "Asistente LADM_COL",
                QCoreApplication.translate("DockWidgetQueries",
                                           "First enter a query"))

    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 copy_value(self, value):
        self.clipboard.setText(str(value))

    def open_url(self, url):
        webbrowser.open(url)

    def zoom_to_feature(self, layer, t_id):
        feature = self.get_feature_from_t_id(layer, t_id)
        self.iface.mapCanvas().zoomToFeatureIds(layer, [feature.id()])
        self.canvas.flashFeatureIds(layer, [feature.id()],
                                    QColor(255, 0, 0, 255),
                                    QColor(255, 0, 0, 0),
                                    flashes=1,
                                    duration=500)

    def open_feature_form(self, layer, t_id):
        feature = self.get_feature_from_t_id(layer, t_id)
        self.iface.openFeatureForm(layer, feature)

    def get_feature_from_t_id(self, layer, t_id):
        field_idx = layer.fields().indexFromName(self.names.T_ID_F)
        request = QgsFeatureRequest(
            QgsExpression("{}={}".format(self.names.T_ID_F, t_id)))
        request.setFlags(QgsFeatureRequest.NoGeometry)

        iterator = layer.getFeatures(request)
        feature = QgsFeature()
        res = iterator.nextFeature(feature)
        if res:
            return feature

        return None

    def zoom_to_plots(self, plot_ids):
        self.iface.mapCanvas().zoomToFeatureIds(
            self._layers[self.names.OP_PLOT_T][LAYER], plot_ids)
        self.canvas.flashFeatureIds(self._layers[self.names.OP_PLOT_T][LAYER],
                                    plot_ids,
                                    QColor(255, 0, 0, 255),
                                    QColor(255, 0, 0, 0),
                                    flashes=1,
                                    duration=500)

    def closeEvent(self, event):
        try:
            self.canvas.mapToolSet.disconnect(self.initialize_tools)
        except TypeError as e:
            pass
        self.canvas.setMapTool(self.active_map_tool_before_custom)

    def download_image(self, url):
        res = False
        img = None
        msg = {'text': '', 'level': Qgis.Warning}
        if url:
            self.logger.info(__name__, "Downloading file from {}".format(url))
            msg = "Downloading image from document repository (this might take a while)..."
            with ProcessWithStatus(msg):
                if self.qgis_utils.is_connected(TEST_SERVER):

                    nam = QNetworkAccessManager()
                    request = QNetworkRequest(QUrl(url))
                    reply = nam.get(request)

                    loop = QEventLoop()
                    reply.finished.connect(loop.quit)
                    loop.exec_()

                    status = reply.attribute(
                        QNetworkRequest.HttpStatusCodeAttribute)
                    if status == 200:
                        res = True
                        img = reply.readAll()
                    else:
                        res = False
                        msg['text'] = QCoreApplication.translate(
                            "SettingsDialog",
                            "There was a problem connecting to the server. The server might be down or the service cannot be reached at the given URL."
                        )
                else:
                    res = False
                    msg['text'] = QCoreApplication.translate(
                        "SettingsDialog",
                        "There was a problem connecting to Internet.")

        else:
            res = False
            msg['text'] = QCoreApplication.translate("SettingsDialog",
                                                     "Not valid URL")

        if not res:
            self.logger.log_message(__name__, msg['text'], msg['level'])
        return (res, img)
class EdgeCreator(QDockWidget, gui_dckwdgt_edge_creator):
    def __init__(self,
                 iface,
                 canvas,
                 l_vertex,
                 l_edge,
                 typo_nature_lim=[],
                 user=None,
                 auth_creator=[],
                 parent=None):

        super(EdgeCreator, self).__init__(parent)
        self.setupUi(self)

        # Delete Widget on close event..
        self.setAttribute(Qt.WA_DeleteOnClose)

        self.save = False

        self.iface = iface
        self.canvas = canvas
        self.l_edge = l_edge
        self.l_vertex = l_vertex
        self.typo_nature_lim = typo_nature_lim
        self.user = user
        self.auth_creator = auth_creator

        self.vertices = self.l_vertex.getFeatures()
        self.vtx_start = None
        self.vtx_end = None
        self.selected_vertices = [None, None]

        self.edge = None

        for i, vertex in enumerate(self.vertices):

            self.start_vtx_cmb.insertItem(i, str(vertex.id()))
            self.start_vtx_cmb.setItemData(i, vertex, 32)
            self.start_vtx_cmb.setCurrentIndex(-1)

            self.end_vtx_cmb.insertItem(i, str(vertex.id()))
            self.end_vtx_cmb.setItemData(i, vertex, 32)
            self.end_vtx_cmb.setCurrentIndex(-1)

        # Attribute: `lim_typologie_nature`
        for e in self.typo_nature_lim:
            self.typo_nat_cmb.addItem(e)

        # Attribute: `som_createur`
        for i, e in enumerate(self.auth_creator):
            self.createur_cmb.addItem(u"%s (%s)" % (e[1], e[0]))
            if self.user == e[0]:
                self.createur_cmb.setCurrentIndex(i)

        self.start_vtx_tb.clicked.connect(self.select_start_vertex_on_canvas)
        self.end_vtx_tb.clicked.connect(self.select_end_vertex_on_canvas)

        self.start_vtx_cmb.highlighted.connect(self.on_vtx_start_pressed)
        self.end_vtx_cmb.highlighted.connect(self.on_vtx_end_pressed)
        self.start_vtx_cmb.currentIndexChanged.connect(
            self.on_vtx_start_pressed)
        self.end_vtx_cmb.currentIndexChanged.connect(self.on_vtx_end_pressed)

        self.start_vtx_cmb.highlighted.connect(self.create_edge)
        self.end_vtx_cmb.highlighted.connect(self.create_edge)
        self.start_vtx_cmb.currentIndexChanged.connect(self.create_edge)
        self.end_vtx_cmb.currentIndexChanged.connect(self.create_edge)

        # Manage delim_pub_chk text
        self.delim_pub_chk.stateChanged.connect(self.settext_delim_pub_chk)

        self.valid_btn.accepted.connect(self.on_accepted)
        self.valid_btn.rejected.connect(self.on_rejected)
        self.valid_btn.button(QDialogButtonBox.Reset).clicked.connect(
            self.on_reset)

        # Set typo_nature to Limite privée (by default)
        self.typo_nat_cmb.setCurrentText('Limite privée')

        # Prompt message
        self.iface.messageBar().pushMessage(edge_crea_txt[0],
                                            edge_crea_txt[1],
                                            Qgis.Info,
                                            duration=10)

        # Launch the choice of first vertex
        self.start_vtx_tb.click()

    # Change the text of the delim_pub checkbox
    def settext_delim_pub_chk(self):
        if self.delim_pub_chk.isChecked():
            self.delim_pub_chk.setText('oui')
        else:
            self.delim_pub_chk.setText('non')

    def closeEvent(self, event):
        if not self.save:
            self.on_rejected()

    def select_start_vertex_on_canvas(self):

        self.identify_start_vertex = QgsMapToolIdentifyFeature(
            self.canvas, self.l_vertex)
        self.identify_start_vertex.setCursor(QCursor(Qt.PointingHandCursor))
        self.identify_start_vertex.featureIdentified.connect(
            self.on_start_vertex_identified)
        self.canvas.setMapTool(self.identify_start_vertex)

    def select_end_vertex_on_canvas(self):

        self.identify_end_vertex = QgsMapToolIdentifyFeature(
            self.canvas, self.l_vertex)
        self.identify_end_vertex.setCursor(QCursor(Qt.PointingHandCursor))
        self.identify_end_vertex.featureIdentified.connect(
            self.on_end_vertex_identified)
        self.canvas.setMapTool(self.identify_end_vertex)

    def on_start_vertex_identified(self, feature):

        cb = self.start_vtx_cmb
        items = [cb.itemText(i) for i in range(cb.count())]
        for i, e in enumerate(items):
            if int(feature.id()) == int(e):
                cb.setCurrentIndex(i)
        self.end_vtx_tb.click()

    def on_end_vertex_identified(self, feature):

        cb = self.end_vtx_cmb
        items = [cb.itemText(i) for i in range(cb.count())]
        for i, e in enumerate(items):
            if int(feature.id()) == int(e):
                cb.setCurrentIndex(i)

    def on_vtx_start_pressed(self, idx):

        self.vtx_start = self.start_vtx_cmb.itemData(idx, 32)
        self.select_vertices(self.vtx_start, 0)

        self.end_vtx_cmb.setEnabled(True)
        self.end_vtx_tb.setEnabled(True)

    def on_vtx_end_pressed(self, idx):

        self.vtx_end = self.end_vtx_cmb.itemData(idx, 32)
        self.select_vertices(self.vtx_end, 1)

        self.createur_cmb.setEnabled(True)

    def select_vertices(self, feature, i):
        if feature:
            self.selected_vertices[i] = feature.id()
        else:
            self.selected_vertices[i] = None

        if not None in self.selected_vertices:
            self.l_vertex.selectByIds(self.selected_vertices)
        elif feature:
            self.l_vertex.selectByIds([feature.id()])

    def unselect_vertices(self):
        self.l_vertex.selectByIds([])

    def create_edge(self):

        # If edge already exists, delete it..
        if self.edge:
            self.l_edge.deleteFeature(self.edge.id())

        # Two vertices are needed..
        if not self.vtx_start or not self.vtx_end:
            return self.canvas.refresh()

        # Two DIFFERENT vertices..
        if self.vtx_start == self.vtx_end:
            return self.canvas.refresh()

        self.lim_ge_createur = self.auth_creator[
            self.createur_cmb.currentIndex()][0]
        lim_typologie_nature = self.typo_nat_cmb.currentText()

        # Create line geometry..
        line = QgsGeometry.fromPolylineXY([
            self.vtx_start.geometry().asPoint(),
            self.vtx_end.geometry().asPoint()
        ])
        self.original_l_edge = self.l_edge
        # Check if the lines intersects
        # Transform the delim_pub checkbox into the correct value
        lim_delim_pub = chkbox_to_truefalse(self.delim_pub_chk)
        to_create = check_limit_cross(line, self.original_l_edge,
                                      self.lim_ge_createur, lim_delim_pub,
                                      lim_typologie_nature, self.canvas, False)
        # Creation of the RFU objects in the layer
        if to_create:
            # Create the feature..
            self.edge = create_nw_feat(self.l_edge, line,
                                       [NULL, NULL, NULL, NULL, NULL])
        else:
            self.on_reset()
        self.canvas.refresh()

    def on_accepted(self):

        if not self.edge:
            return False

        self.lim_ge_createur = self.auth_creator[
            self.createur_cmb.currentIndex()][0]

        # Transform the delim_pub checkbox into the correct value
        lim_delim_pub = chkbox_to_truefalse(self.delim_pub_chk)

        lim_typologie_nature = self.typo_nat_cmb.currentText()

        self.edge.setAttributes([
            NULL, NULL, self.lim_ge_createur, lim_delim_pub,
            lim_typologie_nature
        ])
        self.l_edge.updateFeature(self.edge)
        self.l_vertex.removeSelection()
        self.canvas.refresh()
        self.save = True
        self.close()

    def on_rejected(self):

        # Do not save the feature..
        if self.edge:
            self.l_edge.deleteFeature(self.edge.id())

        self.unselect_vertices()
        self.canvas.refresh()
        self.close()

    def on_reset(self):

        self.start_vtx_cmb.setCurrentIndex(-1)

        self.end_vtx_cmb.setCurrentIndex(-1)
        self.end_vtx_cmb.setEnabled(False)
        self.end_vtx_lab.setEnabled(False)
        self.end_vtx_tb.setEnabled(False)

        for i, e in enumerate(self.auth_creator):
            if self.user == e[0]:
                self.createur_cmb.setCurrentIndex(i)
        self.createur_cmb.setEnabled(False)
        self.createur_lab.setEnabled(False)

        self.unselect_vertices()
        self.canvas.refresh()
        self.start_vtx_tb.click()
示例#6
0
class DockWidgetQueries(QgsDockWidget, DOCKWIDGET_UI):
    def __init__(self, iface, controller, parent=None):
        super(DockWidgetQueries, self).__init__(None)
        self.setupUi(self)
        self.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)
        self.iface = iface
        self._controller = controller

        self.logger = Logger()
        self.app = AppInterface()

        self.canvas = iface.mapCanvas()
        self.active_map_tool_before_custom = None

        self._identify_tool = None

        self._fill_combos()

        self.btn_identify_plot.setIcon(
            QIcon(":/Asistente-LADM-COL/resources/images/spatial_unit.png"))

        self.tab_results.setTabEnabled(
            TAB_BASIC_INFO_INDEX,
            False)  # TODO: Remove when queries support LevCat 1.2
        self.tab_results.setTabEnabled(
            TAB_PHYSICAL_INFO_INDEX,
            False)  # TODO: Remove when queries support LevCat 1.2
        self.tab_results.setTabEnabled(
            TAB_ECONOMIC_INFO_INDEX,
            False)  # TODO: Remove when queries support LevCat 1.2
        self.tab_results.setCurrentIndex(
            TAB_LEGAL_INFO_INDEX
        )  # TODO: Remove when queries support LevCat 1.2

        # Set connections
        self._controller.close_view_requested.connect(self._close_dock_widget)

        self.btn_alphanumeric_query.clicked.connect(self._alphanumeric_query)
        self.cbo_parcel_fields.currentIndexChanged.connect(
            self._search_field_updated)
        self.btn_identify_plot.clicked.connect(self._btn_plot_toggled)
        self.btn_query_informality.clicked.connect(self._query_informality)
        self.btn_next_informal_parcel.clicked.connect(
            self._query_next_informal_parcel)
        self.btn_previous_informal_parcel.clicked.connect(
            self._query_previous_informal_parcel)

        # Context menu
        self._set_context_menus()

        # Create maptool
        self.maptool_identify = QgsMapToolIdentifyFeature(self.canvas)

        self._initialize_field_values_line_edit()
        self._update_informal_controls()

    def _search_field_updated(self, index=None):
        self._initialize_field_values_line_edit()

    def _initialize_field_values_line_edit(self):
        self.txt_alphanumeric_query.setLayer(self._controller.parcel_layer())
        idx = self._controller.parcel_layer().fields().indexOf(
            self.cbo_parcel_fields.currentData())
        self.txt_alphanumeric_query.setAttributeIndex(idx)

    def _set_context_menus(self):
        self.tree_view_basic.setContextMenuPolicy(Qt.CustomContextMenu)
        self.tree_view_basic.customContextMenuRequested.connect(
            self._show_context_menu)

        self.tree_view_legal.setContextMenuPolicy(Qt.CustomContextMenu)
        self.tree_view_legal.customContextMenuRequested.connect(
            self._show_context_menu)

        self.tree_view_physical.setContextMenuPolicy(Qt.CustomContextMenu)
        self.tree_view_physical.customContextMenuRequested.connect(
            self._show_context_menu)

        self.tree_view_economic.setContextMenuPolicy(Qt.CustomContextMenu)
        self.tree_view_economic.customContextMenuRequested.connect(
            self._show_context_menu)

    def _close_dock_widget(self):
        # Deactivate custom tool and close dockwidget
        self._controller.disconnect_plot_layer()
        self._controller.disconnect_parcel_layer()

        self._initialize_tools(new_tool=None, old_tool=self.maptool_identify)
        self._btn_plot_toggled()
        self.close(
        )  # The user needs to use the menus again, which will start everything from scratch

    def _fill_combos(self):
        self.cbo_parcel_fields.clear()
        self.cbo_parcel_fields.addItem(
            QCoreApplication.translate("DockWidgetQueries", "Parcel Number"),
            self._controller.parcel_number_name())
        self.cbo_parcel_fields.addItem(
            QCoreApplication.translate("DockWidgetQueries",
                                       "Previous Parcel Number"),
            self._controller.previous_parcel_number_name())
        self.cbo_parcel_fields.addItem(
            QCoreApplication.translate("DockWidgetQueries",
                                       "Folio de Matrícula Inmobiliaria"),
            self._controller.fmi_name())

    def _initialize_tools(self, new_tool, old_tool):
        if self.maptool_identify == old_tool:
            # custom identify was deactivated
            try:
                self.canvas.mapToolSet.disconnect(self._initialize_tools)
            except TypeError as e:
                pass
            self.btn_identify_plot.setChecked(False)
        else:
            # custom identify was activated
            pass

    def _btn_plot_toggled(self):
        if self.btn_identify_plot.isChecked():
            self._prepare_identify_plot()
        else:
            # The button was toggled and deactivated, go back to the previous tool
            self.canvas.setMapTool(self.active_map_tool_before_custom)

    def _prepare_identify_plot(self):
        """
        Custom Identify tool was activated, prepare everything for identifying plots
        """
        self.active_map_tool_before_custom = self.canvas.mapTool()
        self.btn_identify_plot.setChecked(True)

        self.canvas.mapToolSet.connect(self._initialize_tools)

        self.maptool_identify.setLayer(self._controller.plot_layer())
        cursor = QCursor()
        cursor.setShape(Qt.PointingHandCursor)
        self.maptool_identify.setCursor(cursor)
        self.canvas.setMapTool(self.maptool_identify)

        try:
            self.maptool_identify.featureIdentified.disconnect()
        except TypeError as e:
            pass
        self.maptool_identify.featureIdentified.connect(
            self._search_data_by_plot)

    def _search_data_by_plot(self, plot_feature):
        plot_t_id = plot_feature[self._controller.t_id_name()]
        self.app.gui.flash_features(self._controller.plot_layer(),
                                    [plot_feature.id()])

        with OverrideCursor(Qt.WaitCursor):
            if not self.isVisible():
                self.show()

            self._search_data_by_component(plot_t_ids=[plot_t_id],
                                           zoom_and_select=False)
            self._controller.plot_layer().selectByIds([plot_feature.id()])

    def _search_data_by_component(self, **kwargs):
        """
        Perform the searches by component and fill tree views

        :param kwargs: A dict with search criteria.
        """
        self._controller.plot_layer().removeSelection()

        # Read zoom_and_select parameter and remove it from kwargs
        bZoom = False
        if 'zoom_and_select' in kwargs:
            bZoom = kwargs['zoom_and_select']
            del kwargs['zoom_and_select']

        if 'parcel_number' in kwargs and kwargs['parcel_number'] == NULL:
            self.logger.warning(
                __name__,
                QCoreApplication.translate(
                    "DockWidgetQueries",
                    "The parcel number is NULL! We cannot retrieve data for parcels with NULL parcel numbers."
                ))

        # records = self._controller.search_data_basic_info(**kwargs)
        # if bZoom:
        #     self._controller.zoom_to_resulting_plots(records)

        # self._setup_tree_view(self.tree_view_basic, records)

        records = self._controller.search_data_legal_info(**kwargs)
        self._setup_tree_view(self.tree_view_legal, records)

        # records = self._controller.search_data_physical_info(**kwargs)
        # self._setup_tree_view(self.tree_view_physical, records)

        # records = self._controller.search_data_economic_info(**kwargs)
        # self._setup_tree_view(self.tree_view_economic, records)

    def _setup_tree_view(self, tree_view, records):
        """
        Configure result tree views

        :param tree_view: Tree view to be updated
        :param records: List of dicts. A dict per plot: {id: 21, attributes: {...}}
        """
        tree_view.setModel(self._controller.create_model(records))
        self._collapse_tree_view_items(tree_view)
        self._add_thumbnails_to_tree_view(tree_view)

    def _collapse_tree_view_items(self, tree_view):
        """
        Collapse tree view items based on a property
        """
        tree_view.expandAll()
        for idx in tree_view.model().getCollapseIndexList():
            tree_view.collapse(idx)

    def _add_thumbnails_to_tree_view(self, tree_view):
        """
        Gets a list of model indexes corresponding to extFiles objects to show a preview
        """
        model = tree_view.model()
        for idx in model.getPixmapIndexList():
            url = model.data(idx, Qt.UserRole)['url']
            res, image = self._controller.download_image("{}{}".format(
                url, SUFFIX_GET_THUMBNAIL))
            if res:
                pixmap = QPixmap()
                pixmap.loadFromData(image)
                label = QLabel()
                label.setPixmap(pixmap)
                tree_view.setIndexWidget(idx, label)

    def _alphanumeric_query(self):
        option = self.cbo_parcel_fields.currentData()
        query = self.txt_alphanumeric_query.value()
        if query:
            if option == self._controller.fmi_name():
                self._search_data_by_component(parcel_fmi=query,
                                               zoom_and_select=True)
            elif option == self._controller.parcel_number_name():
                self._search_data_by_component(parcel_number=query,
                                               zoom_and_select=True)
            else:  # previous_parcel_number
                self._search_data_by_component(previous_parcel_number=query,
                                               zoom_and_select=True)
        else:
            self.logger.info_msg(
                __name__,
                QCoreApplication.translate("DockWidgetQueries",
                                           "First enter a query"))

    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._controller.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._controller.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"]
            t_id = index_data["id"]

            if table_name == self._controller.parcel_layer_name():
                layer = self._controller.parcel_layer()
                self.app.core.activate_layer_requested.emit(layer)
            else:
                layer = self._controller.get_layer(table_name)

            if layer is not None:
                if layer.isSpatial():
                    action_zoom_to_feature = QAction(
                        QCoreApplication.translate(
                            "DockWidgetQueries",
                            "Zoom to {} with {}={}").format(
                                table_name, self._controller.t_id_name(),
                                t_id))
                    action_zoom_to_feature.triggered.connect(
                        partial(self._controller.zoom_to_feature, layer, t_id))
                    context_menu.addAction(action_zoom_to_feature)

                if table_name == self._controller.parcel_layer_name():
                    # We show a handy option to zoom to related plots
                    plot_ids = self._controller.get_plots_related_to_parcel(
                        t_id)
                    if plot_ids:
                        action_zoom_to_plots = QAction(
                            QCoreApplication.translate(
                                "DockWidgetQueries",
                                "Zoom to related plot(s)"))
                        action_zoom_to_plots.triggered.connect(
                            partial(self._controller.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._controller.t_id_name(), t_id))
                action_open_feature_form.triggered.connect(
                    partial(self._controller.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 _query_informality(self):
        first_parcel_number, current, total = self._controller.query_informal_parcels(
        )
        self._search_data_by_component(parcel_number=first_parcel_number,
                                       zoom_and_select=True)
        self._update_informal_controls(first_parcel_number, current, total)

        if not total:
            self.logger.info_msg(
                __name__,
                QCoreApplication.translate(
                    "DockWidgetQueries",
                    "There are no informal parcels in this database!"))

    def _update_informal_controls(self, parcel_number='', current=0, total=0):
        """
        Update controls (reset labels, enable buttons if we have informality)
        """
        self._update_informal_labels(parcel_number, current, total)
        self.btn_query_informality.setText(
            QCoreApplication.translate("DockWidgetQueries", "Restart"
                                       ) if current else QCoreApplication.
            translate("DockWidgetQueries", "Start"))

        enable = total > 1  # At least 2 to enable buttons that traverse the parcels
        self.btn_next_informal_parcel.setEnabled(enable)
        self.btn_previous_informal_parcel.setEnabled(enable)

    def _update_informal_labels(self, parcel_number='', current=0, total=0):
        self.lbl_informal_parcel_number.setText(
            parcel_number if parcel_number != NULL else 'NULL')
        out_of = ''
        if current and total:
            out_of = QCoreApplication.translate("DockWidgetQueries",
                                                "{} out of {}").format(
                                                    current, total)
        self.lbl_informal_out_of_total.setText(out_of)

    def _query_next_informal_parcel(self):
        parcel_number, current, total = self._controller.get_next_informal_parcel(
        )
        self._search_data_by_component(parcel_number=parcel_number,
                                       zoom_and_select=True)
        self._update_informal_controls(parcel_number, current, total)

    def _query_previous_informal_parcel(self):
        parcel_number, current, total = self._controller.get_previous_informal_parcel(
        )
        self._search_data_by_component(parcel_number=parcel_number,
                                       zoom_and_select=True)
        self._update_informal_controls(parcel_number, current, total)

    def closeEvent(self, event):
        try:
            self.canvas.mapToolSet.disconnect(self._initialize_tools)
        except TypeError as e:
            pass
        self.canvas.setMapTool(self.active_map_tool_before_custom)
示例#7
0
class DockWidgetQueries(QgsDockWidget, DOCKWIDGET_UI):
    def __init__(self, iface, db, qgis_utils, ladm_data, parent=None):
        super(DockWidgetQueries, self).__init__(None)
        self.setupUi(self)
        self.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)
        self.iface = iface
        self.canvas = iface.mapCanvas()
        self._db = db
        self.qgis_utils = qgis_utils
        self.ladm_data = ladm_data
        self.selection_color = None
        self.active_map_tool_before_custom = None

        self.clipboard = QApplication.clipboard()

        # Required layers
        self._plot_layer = None
        self._parcel_layer = None
        self._uebaunit_table = None

        self._identify_tool = None

        self.add_layers()
        self.fill_combos()

        self.btn_identify_plot.setIcon(
            QIcon(":/Asistente-LADM_COL/resources/images/spatial_unit.png"))

        # Set connections
        self.btn_alphanumeric_query.clicked.connect(self.alphanumeric_query)
        self.btn_clear_alphanumeric_query.clicked.connect(
            self.clear_alphanumeric_query)
        self.btn_identify_plot.clicked.connect(self.btn_plot_toggled)

        # Context menu
        self._set_context_menus()

        # Create maptool
        self.maptool_identify = QgsMapToolIdentifyFeature(self.canvas)

    def _set_context_menus(self):
        self.tree_view_basic.setContextMenuPolicy(Qt.CustomContextMenu)
        self.tree_view_basic.customContextMenuRequested.connect(
            self.show_context_menu)

        self.tree_view_legal.setContextMenuPolicy(Qt.CustomContextMenu)
        self.tree_view_legal.customContextMenuRequested.connect(
            self.show_context_menu)

        self.tree_view_property_record_card.setContextMenuPolicy(
            Qt.CustomContextMenu)
        self.tree_view_property_record_card.customContextMenuRequested.connect(
            self.show_context_menu)

        self.tree_view_physical.setContextMenuPolicy(Qt.CustomContextMenu)
        self.tree_view_physical.customContextMenuRequested.connect(
            self.show_context_menu)

        self.tree_view_economic.setContextMenuPolicy(Qt.CustomContextMenu)
        self.tree_view_economic.customContextMenuRequested.connect(
            self.show_context_menu)

    def add_layers(self):
        res_layers = self.qgis_utils.get_layers(self._db, {
            PLOT_TABLE: {
                'name': PLOT_TABLE,
                'geometry': QgsWkbTypes.PolygonGeometry
            },
            PARCEL_TABLE: {
                'name': PARCEL_TABLE,
                'geometry': None
            },
            UEBAUNIT_TABLE: {
                'name': UEBAUNIT_TABLE,
                'geometry': None
            }
        },
                                                load=True)

        self._plot_layer = res_layers[PLOT_TABLE]
        if self._plot_layer is None:
            self.iface.messageBar().pushMessage(
                "Asistente LADM_COL",
                QCoreApplication.translate(
                    "DockWidgetQueries",
                    "Plot layer couldn't be found... {}").format(
                        self._db.get_description()), Qgis.Warning)
        else:
            # Layer was found, listen to its removal so that we can deactivate the custom tool when that occurs
            try:
                self._plot_layer.willBeDeleted.disconnect(self.layer_removed)
            except TypeError as e:
                pass
            self._plot_layer.willBeDeleted.connect(self.layer_removed)

        self._parcel_layer = res_layers[PARCEL_TABLE]
        if self._parcel_layer is None:
            self.iface.messageBar().pushMessage(
                "Asistente LADM_COL",
                QCoreApplication.translate(
                    "DockWidgetQueries",
                    "Parcel layer couldn't be found... {}").format(
                        self._db.get_description()), Qgis.Warning)
        else:
            # Layer was found, listen to its removal so that we can update the variable properly
            try:
                self._parcel_layer.willBeDeleted.disconnect(
                    self.parcel_layer_removed)
            except TypeError as e:
                pass
            self._parcel_layer.willBeDeleted.connect(self.parcel_layer_removed)

        self._uebaunit_table = res_layers[UEBAUNIT_TABLE]
        if self._uebaunit_table is None:
            self.iface.messageBar().pushMessage(
                "Asistente LADM_COL",
                QCoreApplication.translate(
                    "DockWidgetQueries",
                    "UEBAUnit table couldn't be found... {}").format(
                        self._db.get_description()), Qgis.Warning)
        else:
            # Layer was found, listen to its removal so that we can update the variable properly
            try:
                self._uebaunit_table.willBeDeleted.disconnect(
                    self.uebaunit_table_removed)
            except TypeError as e:
                pass
            self._uebaunit_table.willBeDeleted.connect(
                self.uebaunit_table_removed)

    def initialize_tool(self):
        self._plot_layer = None
        self.initialize_tools(new_tool=None, old_tool=self.maptool_identify)
        self.btn_plot_toggled()

    def update_db_connection(self, db, ladm_col_db):
        self._db = db
        self.initialize_tool()

        if not ladm_col_db:
            self.setVisible(False)

    def layer_removed(self):
        # The required layer was removed, deactivate custom tool
        self.initialize_tool()

    def parcel_layer_removed(self):
        self._parcel_layer = None

    def uebaunit_table_removed(self):
        self._uebaunit_table = None

    def fill_combos(self):
        self.cbo_parcel_fields.clear()

        if self._parcel_layer is not None:
            self.cbo_parcel_fields.addItem(
                QCoreApplication.translate("DockWidgetQueries",
                                           "Parcel Number"), 'parcel_number')
            self.cbo_parcel_fields.addItem(
                QCoreApplication.translate("DockWidgetQueries",
                                           "Previous Parcel Number"),
                'previous_parcel_number')
            self.cbo_parcel_fields.addItem(
                QCoreApplication.translate("DockWidgetQueries",
                                           "Folio de Matrícula Inmobiliaria"),
                'fmi')
        else:
            self.add_layers()

    def initialize_tools(self, new_tool, old_tool):
        if self.maptool_identify == old_tool:
            # custom identify was deactivated
            try:
                self.canvas.mapToolSet.disconnect(self.initialize_tools)
            except TypeError as e:
                pass

            if self.selection_color is not None:
                self.canvas.setSelectionColor(
                    self.selection_color
                )  # Original selection color set in QGIS

            self.btn_identify_plot.setChecked(False)
        else:
            # custom identify was activated
            pass

    def btn_plot_toggled(self):
        if self.btn_identify_plot.isChecked():
            self.prepare_identify_plot()
        else:
            # The button was toggled and deactivated, go back to the previous tool
            self.canvas.setMapTool(self.active_map_tool_before_custom)

    def prepare_identify_plot(self):
        """
            Custom Identify tool was activated, prepare everything for identifying plots
        """
        self.active_map_tool_before_custom = self.canvas.mapTool()
        self.selection_color = self.canvas.selectionColor(
        )  # Probably QColor('#ffff00')

        self.btn_identify_plot.setChecked(True)

        self.canvas.mapToolSet.connect(self.initialize_tools)
        self.canvas.setSelectionColor(QColor("red"))

        if self._plot_layer is None:
            self.add_layers()

        self.maptool_identify.setLayer(self._plot_layer)
        cursor = QCursor()
        cursor.setShape(Qt.PointingHandCursor)
        self.maptool_identify.setCursor(cursor)
        self.canvas.setMapTool(self.maptool_identify)

        try:
            self.maptool_identify.featureIdentified.disconnect()
        except TypeError as e:
            pass
        self.maptool_identify.featureIdentified.connect(self.get_info_by_plot)

    def get_info_by_plot(self, plot_feature):
        plot_t_id = plot_feature[ID_FIELD]
        self.canvas.flashFeatureIds(self._plot_layer, [plot_feature.id()],
                                    QColor(255, 0, 0, 255),
                                    QColor(255, 0, 0, 0),
                                    flashes=1,
                                    duration=500)

        with OverrideCursor(Qt.WaitCursor):
            self._plot_layer.selectByIds([plot_feature.id()])
            if not self.isVisible():
                self.show()

            self.search_data_by_component(plot_t_id=plot_t_id)

    def search_data_by_component(self, **kwargs):
        records = self._db.get_igac_basic_info(**kwargs)
        self.tree_view_basic.setModel(TreeModel(data=records))
        self.tree_view_basic.expandAll()

        records = self._db.get_igac_legal_info(**kwargs)
        self.tree_view_legal.setModel(TreeModel(data=records))
        self.tree_view_legal.expandAll()

        records = self._db.get_igac_property_record_card_info(**kwargs)
        self.tree_view_property_record_card.setModel(TreeModel(data=records))
        self.tree_view_property_record_card.expandAll()

        records = self._db.get_igac_physical_info(**kwargs)
        self.tree_view_physical.setModel(TreeModel(data=records))
        self.tree_view_physical.expandAll()

        records = self._db.get_igac_economic_info(**kwargs)
        self.tree_view_economic.setModel(TreeModel(data=records))
        self.tree_view_economic.expandAll()

    def alphanumeric_query(self):
        """
        Alphanumeric query
        """
        option = self.cbo_parcel_fields.currentData()
        query = self.txt_alphanumeric_query.text().strip()
        if query:
            if option == 'fmi':
                self.search_data_by_component(parcel_fmi=query)
            elif option == 'parcel_number':
                self.search_data_by_component(parcel_number=query)
            else:  # previous_parcel_number
                self.search_data_by_component(previous_parcel_number=query)

        else:
            self.iface.messageBar().pushMessage(
                "Asistente LADM_COL",
                QCoreApplication.translate("DockWidgetQueries",
                                           "First enter a query"))

    def clear_alphanumeric_query(self):
        self.txt_alphanumeric_query.setText('')

    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()

        # Configure actions for tables/layers
        if "type" in index_data and "id" in index_data:
            table_name = index_data["type"]
            t_id = index_data["id"]
            geometry_type = None
            if table_name in DICT_TABLE_PACKAGE and DICT_TABLE_PACKAGE[
                    table_name] == SPATIAL_UNIT_PACKAGE:
                # Layers in Spatial Unit package have double geometry, we need the polygon one
                geometry_type = QgsWkbTypes.PolygonGeometry

            if table_name == PARCEL_TABLE:
                if self._parcel_layer is None or self._plot_layer is None or self._uebaunit_table is None:
                    self.add_layers()
                layer = self._parcel_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, ID_FIELD, 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 == PARCEL_TABLE:
                    # We show a handy option to zoom to related plots
                    plot_ids = self.ladm_data.get_plots_related_to_parcel(
                        self._db, t_id, None, self._plot_layer,
                        self._uebaunit_table)
                    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, ID_FIELD, 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 copy_value(self, value):
        self.clipboard.setText(str(value))

    def zoom_to_feature(self, layer, t_id):
        feature = self.get_feature_from_t_id(layer, t_id)
        self.iface.mapCanvas().zoomToFeatureIds(layer, [feature.id()])
        self.canvas.flashFeatureIds(layer, [feature.id()],
                                    QColor(255, 0, 0, 255),
                                    QColor(255, 0, 0, 0),
                                    flashes=1,
                                    duration=500)

    def open_feature_form(self, layer, t_id):
        feature = self.get_feature_from_t_id(layer, t_id)
        self.iface.openFeatureForm(layer, feature)

    def get_feature_from_t_id(self, layer, t_id):
        field_idx = layer.fields().indexFromName(ID_FIELD)
        request = QgsFeatureRequest(
            QgsExpression("{}={}".format(
                ID_FIELD, t_id))).setSubsetOfAttributes([field_idx])
        request.setFlags(QgsFeatureRequest.NoGeometry)

        iterator = layer.getFeatures(request)
        feature = QgsFeature()
        res = iterator.nextFeature(feature)
        if res:
            return feature

        return None

    def zoom_to_plots(self, plot_ids):
        self.iface.mapCanvas().zoomToFeatureIds(self._plot_layer, plot_ids)
        self.canvas.flashFeatureIds(self._plot_layer,
                                    plot_ids,
                                    QColor(255, 0, 0, 255),
                                    QColor(255, 0, 0, 0),
                                    flashes=1,
                                    duration=500)
class EdgeCreator(QDockWidget, gui_dckwdgt_edge_creator):

    def __init__(self, canvas, l_vertex, l_edge,
                 user=None, auth_creator=[], parent=None):

        super(EdgeCreator, self).__init__(parent)
        self.setupUi(self)

        # Delete Widget on close event..
        self.setAttribute(Qt.WA_DeleteOnClose)

        self.save = False

        self.canvas = canvas
        self.l_edge = l_edge
        self.l_vertex = l_vertex
        self.user = user
        self.auth_creator = auth_creator

        self.vertices = self.l_vertex.getFeatures()
        self.vtx_start = None
        self.vtx_end = None
        self.selected_vertices = [None, None]

        self.edge = None

        for i, vertex in enumerate(self.vertices):

            self.startVertexComboBox.insertItem(i, str(vertex.id()))
            self.startVertexComboBox.setItemData(i, vertex, 32)
            self.startVertexComboBox.setCurrentIndex(-1)

            self.endVertexComboBox.insertItem(i, str(vertex.id()))
            self.endVertexComboBox.setItemData(i, vertex, 32)
            self.endVertexComboBox.setCurrentIndex(-1)

        # Attribute: `som_createur`
        for i, e in enumerate(self.auth_creator):
            self.creatorComboBox.addItem(u"%s (%s)" % (e[1], e[0]))
            if self.user == e[0]:
                self.creatorComboBox.setCurrentIndex(i)

        self.startVertextoolButton.clicked.connect(self.select_start_vertex_on_canvas)
        self.endVertextoolButton.clicked.connect(self.select_end_vertex_on_canvas)

        self.startVertexComboBox.highlighted.connect(self.on_vtx_start_pressed)
        self.endVertexComboBox.highlighted.connect(self.on_vtx_end_pressed)
        self.startVertexComboBox.currentIndexChanged.connect(self.on_vtx_start_pressed)
        self.endVertexComboBox.currentIndexChanged.connect(self.on_vtx_end_pressed)

        self.startVertexComboBox.highlighted.connect(self.create_edge)
        self.endVertexComboBox.highlighted.connect(self.create_edge)
        self.startVertexComboBox.currentIndexChanged.connect(self.create_edge)
        self.endVertexComboBox.currentIndexChanged.connect(self.create_edge)

        self.buttonBox.accepted.connect(self.on_accepted)
        self.buttonBox.rejected.connect(self.on_rejected)
        self.buttonBox.button(QDialogButtonBox.Reset).clicked.connect(self.on_reset)

    def closeEvent(self, event):
        if not self.save:
            self.on_rejected()

    def select_start_vertex_on_canvas(self):

        self.identify_start_vertex = QgsMapToolIdentifyFeature(self.canvas, self.l_vertex)
        self.identify_start_vertex.setCursor(QCursor(Qt.PointingHandCursor))
        self.identify_start_vertex.featureIdentified.connect(self.on_start_vertex_identified)
        self.canvas.setMapTool(self.identify_start_vertex)

    def select_end_vertex_on_canvas(self):

        self.identify_end_vertex = QgsMapToolIdentifyFeature(self.canvas, self.l_vertex)
        self.identify_end_vertex.setCursor(QCursor(Qt.PointingHandCursor))
        self.identify_end_vertex.featureIdentified.connect(self.on_end_vertex_identified)
        self.canvas.setMapTool(self.identify_end_vertex)

    def on_start_vertex_identified(self, feature):

        cb = self.startVertexComboBox
        items = [cb.itemText(i) for i in range(cb.count())]
        for i, e in enumerate(items):
            if int(feature.id()) == int(e):
                cb.setCurrentIndex(i)

    def on_end_vertex_identified(self, feature):

        cb = self.endVertexComboBox
        items = [cb.itemText(i) for i in range(cb.count())]
        for i, e in enumerate(items):
            if int(feature.id()) == int(e):
                cb.setCurrentIndex(i)

    def on_vtx_start_pressed(self, idx):

        self.vtx_start = self.startVertexComboBox.itemData(idx, 32)
        self.select_vertices(self.vtx_start, 0)

        self.endVertexComboBox.setEnabled(True)
        self.endVertextoolButton.setEnabled(True)

    def on_vtx_end_pressed(self, idx):

        self.vtx_end = self.endVertexComboBox.itemData(idx, 32)
        self.select_vertices(self.vtx_end, 1)

        self.creatorComboBox.setEnabled(True)

    def select_vertices(self, feature, i):
        if feature:
            self.selected_vertices[i] = feature.id()
        else:
            self.selected_vertices[i] = None
        self.l_vertex.setSelectedFeatures(self.selected_vertices)

    def unselect_vertices(self):
        self.l_vertex.setSelectedFeatures([])

    def create_edge(self):

        # If edge already exists, delete it..
        if self.edge:
            self.l_edge.deleteFeature(self.edge.id())

        # Two vertices are needed..
        if not self.vtx_start or not self.vtx_end:
            return self.canvas.refresh()

        # Two DIFFERENT vertices..
        if self.vtx_start == self.vtx_end:
            return self.canvas.refresh()

        # Create line geometry..
        line = QgsGeometry.fromPolyline([self.vtx_start.geometry().asPoint(),
                                         self.vtx_end.geometry().asPoint()])

        # Create the feature..
        self.edge = QgsFeature()
        self.edge.setGeometry(line)
        self.edge.setFields(self.l_edge.pendingFields())
        self.edge.setAttributes(
                [QPyNullVariant(int), QPyNullVariant(int), QPyNullVariant(int)])

        # Add feature to layer..
        self.l_edge.addFeature(self.edge)
        self.canvas.refresh()

    def on_accepted(self):

        if not self.edge:
            return False

        self.lim_ge_createur = self.auth_creator[self.creatorComboBox.currentIndex()][0]
        self.edge.setAttributes(
                [QPyNullVariant(int), QPyNullVariant(int), self.lim_ge_createur])
        self.l_edge.updateFeature(self.edge)
        self.canvas.refresh()
        self.save = True
        self.close()

    def on_rejected(self):

        # Do not save the feature..
        if self.edge:
            self.l_edge.deleteFeature(self.edge.id())

        self.unselect_vertices()
        self.canvas.refresh()
        self.close()

    def on_reset(self):

        self.startVertexComboBox.setCurrentIndex(0)
        # self.startVertexComboBox.setEnabled(True)
        # self.startVertexLabel.setEnabled(True)

        self.endVertexComboBox.setCurrentIndex(0)
        self.endVertexComboBox.setEnabled(False)
        self.endVertexLabel.setEnabled(False)
        self.endVertextoolButton.setEnabled(False)

        for i, e in enumerate(self.auth_creator):
            if self.user == e[0]:
                self.creatorComboBox.setCurrentIndex(i)
        self.creatorComboBox.setEnabled(False)
        self.creatorLabel.setEnabled(False)

        self.unselect_vertices()
        self.canvas.refresh()
class EditorRFUGeofoncier:
    def __init__(self, iface):

        # Save reference to the QGIS interface
        self.iface = iface

        self.canvas = self.iface.mapCanvas()
        self.project = QgsProject.instance()

        # Initialize plugin directory
        self.plugin_dir = os.path.dirname(__file__)

        self.conn = None
        self.rfu = None
        self.edge_creator = None
        self.tol_spt = 0.0
        self.dxf2rfu_import = None
        self.csv2rfu_import = None
        self.show_ptplots = None

    def unload(self):

        # Remove the plugin menu and toolbar
        if self.rfu_menu != None:
            self.iface.mainWindow().menuBar().removeAction(
                self.rfu_menu.menuAction())
            self.rfu_menu.deleteLater()
            self.iface.mainWindow().removeToolBar(self.toolbar)
        else:
            self.iface.removePluginMenu("&RFU", self.rfu_menu.menuAction())
            self.rfu_menu.deleteLater()

        # Remove RFU dockwidgets
        if self.rfu:
            self.iface.removeDockWidget(self.rfu)
        if self.edge_creator:
            self.iface.removeDockWidget(self.edge_creator)

    def initGui(self):

        # Add specific menu to QGIS menu
        self.rfu_menu = QMenu(QCoreApplication.translate("RFU", mnu_title_txt))
        self.iface.mainWindow().menuBar().insertMenu(
            self.iface.firstRightStandardMenu().menuAction(), self.rfu_menu)

        # Add specific toolbar
        self.toolbar = self.iface.addToolBar(mnu_title_txt)
        self.toolbar.setObjectName("GeofoncierRfuEditorToolBar")

        # Create actions
        self.action_login = QAction(QIcon(r":/resources/rfu_btn_log_in"),
                                    "S'identifer", self.iface.mainWindow())
        self.action_login.setEnabled(True)
        self.action_login.setCheckable(True)

        self.action_connector = QAction(QIcon(r":/resources/rfu_btn_conn_rfu"),
                                        "Connection à l'API Géofoncier",
                                        self.iface.mainWindow())
        self.action_connector.setEnabled(False)
        self.action_connector.setCheckable(True)

        self.action_vtx_creator = QAction(
            QIcon(r":/resources/rfu_btn_add_vtx"), "Ajouter un sommet RFU",
            self.iface.mainWindow())

        self.action_edge_creator = QAction(
            QIcon(r":/resources/rfu_btn_add_edge"), "Ajouter une limite RFU",
            self.iface.mainWindow())
        self.action_edge_creator.setCheckable(True)

        self.action_import_csv2rfu = QAction(
            QIcon(r":/resources/rfu_btn_import_csvrfu"),
            "Importer un fichier CSV spécifique RFU", self.iface.mainWindow())

        self.action_import_dxf2rfu = QAction(
            QIcon(r":/resources/rfu_btn_import_dxf2rfu"),
            "Importer un fichier DXF filtré pour le RFU",
            self.iface.mainWindow())

        self.action_cut_oldlimit = QAction(
            QIcon(r":/resources/rfu_btn_cut_oldlimit"),
            "Couper une limite existante par un ou plusieurs sommets nouveaux",
            self.iface.mainWindow())

        self.action_transfo_pt_to_plot = QAction(
            QIcon(r":/resources/rfu_btn_pt_to_plot"),
            "Traiter les sommets proches à transformer en détermination",
            self.iface.mainWindow())

        self.action_del_ptplot = QAction(
            QIcon(r":/resources/rfu_btn_del_ptplot"),
            "Supprimer une détermination d'un sommet", self.iface.mainWindow())

        self.action_show_ptplots = QAction(
            QIcon(r":/resources/rfu_btn_show_ptplots"),
            "Consulter les déterminations d'un sommet",
            self.iface.mainWindow())

        self.action_show_capabilities = QAction(
            QIcon(r":/resources/rfu_btn_show_capabilities"),
            "Visualiser les paramètres de l'application",
            self.iface.mainWindow())
        self.action_show_capabilities.setEnabled(False)

        # Deactivate creation and import tools
        self.allow_creation(False)

        # Add actions to the toolbar
        self.toolbar.addActions([
            self.action_login, self.action_connector, self.action_vtx_creator,
            self.action_edge_creator, self.action_import_csv2rfu,
            self.action_import_dxf2rfu, self.action_cut_oldlimit,
            self.action_transfo_pt_to_plot, self.action_del_ptplot,
            self.action_show_ptplots, self.action_show_capabilities
        ])

        # Add actions to the menu
        self.rfu_menu.addActions([
            self.action_login, self.action_connector, self.action_vtx_creator,
            self.action_edge_creator, self.action_import_csv2rfu,
            self.action_import_dxf2rfu, self.action_cut_oldlimit,
            self.action_transfo_pt_to_plot, self.action_del_ptplot,
            self.action_show_ptplots, self.action_show_capabilities
        ])

        # Manage signals..
        self.iface.currentLayerChanged.connect(self.on_toggled)
        self.project.layersRemoved.connect(self.on_layers_removed)

        self.action_login.triggered.connect(self.tool_login_on_triggered)
        self.action_connector.triggered[bool].connect(
            self.tool_rfu_on_triggered)
        self.action_vtx_creator.triggered.connect(
            self.tool_vtx_creator_on_triggered)
        self.action_edge_creator.triggered[bool].connect(
            self.tool_edge_creator_on_triggered)
        self.action_import_csv2rfu.triggered.connect(self.tool_import_csvrfu)
        self.action_import_dxf2rfu.triggered.connect(self.tool_import_dxf2rfu)
        self.action_cut_oldlimit.triggered.connect(self.tool_cut_oldlimit)
        self.action_transfo_pt_to_plot.triggered.connect(
            self.tool_transfo_pt_to_plot)
        self.action_del_ptplot.triggered.connect(
            partial(self.tool_select_pt_to_plot, "del"))
        self.action_show_ptplots.triggered.connect(
            partial(self.tool_select_pt_to_plot, "info"))
        self.action_show_capabilities.triggered.connect(
            self.tool_show_capabilities)
        # Initialize current layer to None (See switch_editing())..
        self.current_layer = None

    # On iface Signals
    # ================

    def on_toggled(self):

        layer = self.canvas.currentLayer()

        if not layer or not self.rfu:
            return

        if layer.isEditable() and layer == self.rfu.l_vertex:
            self.switch_editing(layer)
        elif layer.isEditable() and layer == self.rfu.l_edge:
            self.switch_editing(layer)

    def switch_editing(self, layer):

        old_layer = None

        if self.current_layer is not None:
            old_layer = self.current_layer
            old_layer.committedFeaturesAdded.disconnect(
                self.on_committed_features_added)
            old_layer.committedFeaturesRemoved.disconnect(
                self.on_committed_features_removed)
            old_layer.attributeValueChanged.disconnect(
                self.on_attribute_value_changed)
            old_layer.geometryChanged.disconnect(self.on_geometry_changed)

        self.current_layer = layer
        layer.committedFeaturesAdded.connect(self.on_committed_features_added)
        layer.committedFeaturesRemoved.connect(
            self.on_committed_features_removed)
        layer.attributeValueChanged.connect(self.on_attribute_value_changed)
        layer.geometryChanged.connect(self.on_geometry_changed)

    def on_committed_features_added(self, layer_id, features):
        self.rfu.add_features(layer_id, features)

    def on_committed_features_removed(self, layer_id, ft_id_list):
        self.rfu.remove_features(layer_id, ft_id_list)

    def on_geometry_changed(self, fid, geom):
        feature = tools.get_feature_by_id(self.current_layer, fid)
        self.rfu.modify_feature(self.current_layer.id(), feature)

    def on_attribute_value_changed(self, fid, field_idx, value):
        feature = tools.get_feature_by_id(self.current_layer, fid)
        self.rfu.modify_feature(self.current_layer.id(), feature)

    # On map layer registry signals
    # =============================

    def on_layers_removed(self, layers):
        self.current_layer = None

    # Login/logout
    # ============

    def open_connection(self):

        dlg_login = GeoFoncierAPILogin()
        dlg_login.closed.connect(self.dlg_login_on_closed)
        dlg_login.opened.connect(self.dlg_login_on_opened)
        dlg_login.show()

        if not dlg_login.exec_():
            return None

        self.conn = dlg_login.conn
        self.action_connector.setEnabled(True)
        self.action_show_capabilities.setEnabled(True)

        self.iface.messageBar().pushMessage("Géofoncier",
                                            "Bonjour %s %s." %
                                            (self.conn.prenom, self.conn.nom),
                                            Qgis.Info,
                                            duration=6)

    def close_connection(self):

        msg = ("Voulez-vous fermer votre session ?\n"
               "Attention, toute modification sera perdue.")
        resp = QMessageBox.question(self.iface.mainWindow(), r"Question", msg,
                                    QMessageBox.Yes, QMessageBox.No)
        if resp != QMessageBox.Yes:
            self.dlg_login_on_closed()
            return False

        # Close connection
        if self.rfu:
            if self.rfu:
                self.rfu.reset()
                try:
                    self.rfu.disconn_scale_limit()
                except:
                    pass
                self.rfu.close()
            self.action_connector.setChecked(False)
            self.action_connector.setEnabled(False)
            self.action_show_capabilities.setEnabled(False)
            self.allow_creation(False)

        self.conn = None

        self.iface.messageBar().pushMessage("Géofoncier",
                                            "À bientôt.",
                                            Qgis.Info,
                                            duration=6)

    # On action signals
    # =================

    def dlg_login_on_closed(self):

        if self.conn == None:
            self.action_login.setChecked(False)
        else:
            self.action_login.setChecked(True)

    def dlg_login_on_opened(self):

        self.action_login.setChecked(True)

    def tool_login_on_triggered(self, checked):

        if checked:
            self.open_connection()
        else:
            self.close_connection()

    def tool_rfu_on_triggered(self, checked):

        if checked and not self.rfu:
            self.rfu = RFUDockWidget(self.iface,
                                     self.canvas,
                                     self.project,
                                     conn=self.conn)
            self.rfu.setObjectName(r"RFUDockWidget")
            self.iface.addDockWidget(Qt.TopDockWidgetArea, self.rfu)
            self.rfu.closed.connect(self.rfu_on_closed)
            self.rfu.uploaded.connect(self.rfu_on_uploaded)
            self.rfu.downloaded.connect(self.rfu_on_downloaded)
            self.rfu.rfureset.connect(self.rfu_on_reset)

        if checked and self.rfu:
            self.rfu.show()

        if not checked:
            self.rfu.hide()

    def rfu_on_closed(self):

        self.action_connector.setChecked(False)

    def rfu_on_uploaded(self):

        if self.edge_creator:
            self.on_edge_creator_destroyed()

        # Change the current layer
        self.iface.setActiveLayer(self.rfu.l_edge)
        self.iface.setActiveLayer(self.rfu.l_vertex)

    def rfu_on_downloaded(self):

        # Allow creation and import
        self.allow_creation(True)
        # Change the current layer
        self.iface.setActiveLayer(self.rfu.l_edge)
        self.iface.setActiveLayer(self.rfu.l_vertex)

    def rfu_on_reset(self):
        # Allow creation and import
        self.allow_creation(False)

    def tool_vtx_creator_on_triggered(self):
        # Set the layer l_vertex current
        self.iface.setActiveLayer(self.rfu.l_vertex)
        self.project.layerTreeRoot().findLayer(
            self.rfu.l_vertex.id()).setItemVisibilityChecked(True)
        self.canvas.refresh()
        # Check the editable mode
        if not self.rfu.l_vertex.isEditable():
            self.rfu.l_vertex.startEditing()

        if not self.rfu.dflt_ellips_acronym:
            self.rfu.selected_ellips_acronym = self.rfu.dflt_ellips_acronym

        dlg_vtx_creator = VertexCreator(
            self.canvas,
            self.project,
            self.rfu.layers[0],
            user=self.rfu.conn.user,
            precision_class=self.rfu.precision_class,
            ellips_acronym=self.rfu.ellips_acronym,
            selected_ellips_acronym=self.rfu.selected_ellips_acronym,
            typo_nature_som=self.rfu.typo_nature_som,
            auth_creator=self.rfu.auth_creator,
            tol_spt=self.rfu.tol_same_pt)

        dlg_vtx_creator.show()

        if not dlg_vtx_creator.exec_():
            return None

    def tool_edge_creator_on_triggered(self, checked=False):
        if not checked:
            self.edge_creator.close()
            self.edge_creator = None

        if checked:
            # Set the layer l_edge current
            self.iface.setActiveLayer(self.rfu.l_edge)
            self.project.layerTreeRoot().findLayer(
                self.rfu.l_edge.id()).setItemVisibilityChecked(True)
            self.canvas.refresh()
            # Check the editable mode
            if not self.rfu.l_edge.isEditable():
                self.rfu.l_edge.startEditing()

            self.edge_creator = EdgeCreator(
                self.iface,
                self.canvas,
                self.rfu.layers[0],
                self.rfu.layers[1],
                typo_nature_lim=self.rfu.typo_nature_lim,
                user=self.rfu.conn.user,
                auth_creator=self.rfu.auth_creator)

            self.edge_creator.setObjectName(r"EdgeCreatorDockWidget")
            self.edge_creator.destroyed.connect(self.on_edge_creator_destroyed)
            self.iface.addDockWidget(Qt.LeftDockWidgetArea, self.edge_creator)

    def on_edge_creator_destroyed(self):

        self.edge_creator = None
        return self.action_edge_creator.setChecked(False)

    # Launch the import csv tool
    def tool_import_csvrfu(self):
        if self.rfu:
            self.csv2rfu_import = ImportCsvRfu(
                self.iface,
                self.canvas,
                self.project,
                self.rfu.layers[0],
                self.rfu.layers[1],
                user=self.rfu.conn.user,
                auth_creator=self.rfu.auth_creator,
                precision_class=self.rfu.precision_class,
                ellips_acronym=self.rfu.ellips_acronym,
                selected_ellips_acronym=self.rfu.selected_ellips_acronym,
                typo_nature_som=self.rfu.typo_nature_som,
                typo_nature_lim=self.rfu.typo_nature_lim,
                tol_spt=self.rfu.tol_same_pt)
            self.csv2rfu_import.import_file()
        else:
            QMessageBox.information(self.iface.mainWindow(), tl_imp_canc,
                                    txt_csvimp_norfu_canc)

    # Launch the import dxf tool
    def tool_import_dxf2rfu(self):
        if self.rfu:
            self.dxf2rfu_import = ImportDxf2Rfu(
                self.iface,
                self.canvas,
                self.project,
                self.rfu.layers[0],
                self.rfu.layers[1],
                user=self.rfu.conn.user,
                auth_creator=self.rfu.auth_creator,
                precision_class=self.rfu.precision_class,
                ellips_acronym=self.rfu.ellips_acronym,
                selected_ellips_acronym=self.rfu.selected_ellips_acronym,
                typo_nature_som=self.rfu.typo_nature_som,
                typo_nature_lim=self.rfu.typo_nature_lim,
                tol_spt=self.rfu.tol_same_pt)
            self.dxf2rfu_import.import_file()
        else:
            QMessageBox.information(self.iface.mainWindow(), tl_imp_canc,
                                    txt_dxfimp_norfu_canc)

    # Cut an old limit at the point of a new vertex
    def tool_cut_oldlimit(self):
        if self.rfu and self.rfu.layers[0]:
            # Set the layer l_vertex current
            self.iface.setActiveLayer(self.rfu.l_vertex)
            self.project.layerTreeRoot().findLayer(
                self.rfu.l_vertex.id()).setItemVisibilityChecked(True)
            self.canvas.refresh()
            # Check the editable mode
            if not self.rfu.l_vertex.isEditable():
                self.rfu.l_vertex.startEditing()
            self.tr_cut_oldlimit = CutOldLimit(
                self.canvas,
                self.project,
                self.rfu.layers[0],
                self.rfu.layers[1],
            )
            # # Modal window
            # self.tr_pt_to_plot.setWindowModality(Qt.ApplicationModal)
            self.tr_cut_oldlimit.show()
        else:
            QMessageBox.information(self.iface.mainWindow(),
                                    tr_pttoplot_imp_msg[0],
                                    tr_pttoplot_imp_msg[1])

    # Management of the new vertices to transform into plots
    def tool_transfo_pt_to_plot(self):
        if self.rfu and self.rfu.layers[0]:
            # Set the layer l_vertex current
            self.iface.setActiveLayer(self.rfu.l_vertex)
            self.project.layerTreeRoot().findLayer(
                self.rfu.l_vertex.id()).setItemVisibilityChecked(True)
            self.canvas.refresh()
            # Check the editable mode
            if not self.rfu.l_vertex.isEditable():
                self.rfu.l_vertex.startEditing()
            self.tr_pt_to_plot = TransfoPtToPlot(
                self.canvas,
                self.project,
                self.rfu.layers[0],
                self.rfu.layers[1],
            )
            # # Modal window
            # self.tr_pt_to_plot.setWindowModality(Qt.ApplicationModal)
            self.tr_pt_to_plot.dlg_show()
        else:
            QMessageBox.information(self.iface.mainWindow(),
                                    tr_pttoplot_imp_msg[0],
                                    tr_pttoplot_imp_msg[1])

    # Let the user choose a point to show the point plots
    def tool_select_pt_to_plot(self, type_fnc):

        self.plot_fnc_mode = type_fnc
        if self.conn and self.rfu and self.rfu.zone:
            # Prompt message
            self.iface.messageBar().pushMessage(plot_dif_txt[type_fnc][0],
                                                plot_dif_txt[type_fnc][1],
                                                Qgis.Info,
                                                duration=10)
            # Pointer to choose the vertex
            # Set the layer l_vertex current
            self.iface.setActiveLayer(self.rfu.l_vertex)
            self.project.layerTreeRoot().findLayer(
                self.rfu.l_vertex.id()).setItemVisibilityChecked(True)
            self.canvas.refresh()
            self.identify_pttoplot = QgsMapToolIdentifyFeature(
                self.canvas, self.rfu.l_vertex)
            self.identify_pttoplot.setCursor(QCursor(Qt.WhatsThisCursor))
            self.identify_pttoplot.featureIdentified.connect(
                self.pt_to_plot_identified)
            self.canvas.setMapTool(self.identify_pttoplot)

    # Prepare and show the point plots dlg
    def pt_to_plot_identified(self, pt_feat):
        # Select the point
        self.rfu.l_vertex.selectByIds([pt_feat.id()])
        id_node = pt_feat["@id_noeud"]
        # Check the selected point is a RFU vertex
        if id_node:
            resp_plots = None
            # Get the pt plots infos
            resp = self.conn.get_ptplots(id_node, self.rfu.zone)
            resp_plots = resp.read()
            tree = ElementTree.fromstring(resp_plots)
            if resp.code != 200:
                # Catch the error specified by the API
                elt_err = tree.find(r"./log")
                if elt_err.text:
                    msg = elt_err.text
                else:
                    # Error returned by the server (all other cases)
                    msg = str(resp_plots)
                # Display the error in a message box
                return QMessageBox.warning(self.iface.mainWindow(),
                                           msg_obt_det_imp, msg)
            else:
                ptplot = tree.find(r"./sommet/determination")
                # Case of no plots
                if 'Message' in ptplot.attrib:
                    msg = ptplot.attrib["Message"]
                    QMessageBox.warning(self.iface.mainWindow(),
                                        msg_obt_det_imp, msg)
                else:
                    # DEBUG
                    # urlresp_to_file(resp_plots)

                    # Prepare and show the dlg
                    self.show_ptplots = ShowPtPlots(self.conn, self.rfu.zone,
                                                    resp_plots,
                                                    self.plot_fnc_mode,
                                                    self.iface.mainWindow())
                    # Modal window
                    self.show_ptplots.setWindowModality(Qt.ApplicationModal)
                    self.show_ptplots.ptplotsNwPtSelect.connect(
                        partial(self.tool_select_pt_to_plot, "info"))
                    self.show_ptplots.plots_show()
        # Case of selected point is not a RFU vertex
        else:
            QMessageBox.warning(self.iface.mainWindow(), plot_notrfusel_msg[0],
                                plot_notrfusel_msg[1])

    # Lets appear the show capabilities dlg
    def tool_show_capabilities(self):
        resp_mycap = None
        resp_cap = None
        # Get C1 capabilities
        if self.conn:
            resp = self.conn.get_my_capabilities()
            resp_mycap = resp.read()
            if resp.code != 200:
                # Catch the error specified by the API
                tree = ElementTree.fromstring(resp_mycap)
                elt_err = tree.find(r"./log")
                if elt_err.text:
                    msg = elt_err.text
                else:
                    # Error returned by the server (all other cases)..
                    msg = str(resp_mycap)
                # Display the error in a message box
                return QMessageBox.warning(self.iface.mainWindow(),
                                           msg_obt_cap_imp, msg)
            if self.rfu and self.rfu.zone:
                resp = self.conn.get_capabilities(self.rfu.zone)
                resp_cap = resp.read()
                # DEBUG: Export response as a text file
                # urlresp_to_file(resp_ap)
                if resp.code != 200:
                    # Catch the error specified by the API
                    tree = ElementTree.fromstring(resp_cap)
                    elt_err = tree.find(r"./log")
                    if elt_err.text:
                        msg = elt_err.text
                    else:
                        # Error returned by the server (all other cases)
                        msg = str(resp_cap)
                    # Display the error in a message box
                    return QMessageBox.warning(self.iface.mainWindow(),
                                               msg_obt_cap_imp, msg)
            # Prepare and show the dlg
            self.show_capa = ShowCapabilities(resp_cap, resp_mycap)
            self.show_capa.show()
        else:
            # No connection: alert message
            return QMessageBox.warning(self.iface.mainWindow(),
                                       msg_obt_cap_imp, msg_obt_cap_ident)

    # Allow (or disallow) creation and import
    def allow_creation(self, state):
        self.action_vtx_creator.setEnabled(state)
        self.action_edge_creator.setEnabled(state)
        self.action_import_csv2rfu.setEnabled(state)
        self.action_import_dxf2rfu.setEnabled(state)
        self.action_cut_oldlimit.setEnabled(state)
        self.action_transfo_pt_to_plot.setEnabled(state)
        self.action_del_ptplot.setEnabled(state)
        self.action_show_ptplots.setEnabled(state)
示例#10
0
class CutOldLimit(QDialog, gui_dlg_cut_oldlimit):
    def __init__(self, canvas, project, l_vertex, l_edge, parent=None):

        super(CutOldLimit, self).__init__(parent)
        self.setupUi(self)

        self.canvas = canvas
        self.project = project
        self.l_edge = l_edge
        self.l_vertex = l_vertex
        self.parent = parent

        self.sel_nw_vtx = None

        self.resize_dlg = ResizeDlg(self, "dlg_cut_oldlimit")
        self.resize_params = self.resize_dlg.load_dlgresize()
        self.resize_on = self.resize_params["dlg_cut_oldlimit"]

        self.valid_btn.clicked.connect(self.close)
        self.resize_btn.clicked.connect(self.resize_dlg.dlg_ch_resize)
        self.sel_oldlim_btn.clicked.connect(self.sel_oldlim)
        self.sel_nwvtx_btn.clicked.connect(self.sel_nwvtx)
        self.validop_btn.clicked.connect(self.validop)
        # Delete Widget on close event
        self.setAttribute(Qt.WA_DeleteOnClose)

    # Let the user select the RFU old limit to cut
    def sel_oldlim(self):
        # Selection in the canvas
        self.hide()
        self.l_edge.removeSelection()
        self.identify_oldlim = QgsMapToolIdentifyFeature(
            self.canvas, self.l_edge)
        self.identify_oldlim.setCursor(QCursor(Qt.PointingHandCursor))
        self.identify_oldlim.featureIdentified.connect(self.oldlim_identified)
        self.canvas.setMapTool(self.identify_oldlim)

    # Let the user select the new vertices used to cut the old lmit
    def sel_nwvtx(self):
        # Selection in the canvas
        self.hide()
        self.identify_nwvtx = MultiSelNwVtxTool(self.parent, self.canvas,
                                                self.l_vertex)
        # self.identify_nwvtx.setCursor(QCursor(Qt.PointingHandCursor))
        self.identify_nwvtx.selected_feats.connect(self.nwvtx_identified)
        self.canvas.setMapTool(self.identify_nwvtx)

    # Check of the limit after selection
    def oldlim_identified(self, feat):
        self.l_edge.selectByIds([feat.id()])
        self.canvas.unsetMapTool(self.identify_oldlim)
        # Check if the limit selected is an old RFU limit
        if feat[r"@id_arc"]:
            self.show()
        else:
            QMessageBox.warning(self, cutlim_notoldlim_msg[0],
                                cutlim_notoldlim_msg[1])
            self.l_edge.removeSelection()
            self.sel_oldlim()

    # Terminate the vertices selection
    def nwvtx_identified(self, lyr, feats):
        self.canvas.unsetMapTool(self.identify_nwvtx)
        self.show()

    # Cut operation
    def validop(self):
        self.hide()
        # Transformations to obtain the WGS84 or the CC coordinates
        coords_tr_wgs, coords_tr_cc = crs_trans_params(self.canvas,
                                                       self.project)
        # Message if no limit selected
        if len(self.l_edge.selectedFeatures()) == 0:
            QMessageBox.information(self, cutlim_nolim_msg[0],
                                    cutlim_nolim_msg[1])
            self.show()
        # Message if more than one limit selected
        elif len(self.l_edge.selectedFeatures()) > 1:
            QMessageBox.information(self, cutlim_toomuchlim_msg[0],
                                    cutlim_toomuchlim_msg[1])
            self.l_edge.removeSelection()
            self.show()
        # Message if no vertex selected
        elif len(self.l_vertex.selectedFeatures()) == 0:
            QMessageBox.information(self, cutlim_nonwvtx_msg[0],
                                    cutlim_nonwvtx_msg[1])
            self.show()
        # Do the job
        else:
            oldlim = self.l_edge.selectedFeatures()[0]
            # Find the att values
            lim_delim_pub = oldlim["lim_delimitation_publique"]
            lim_typologie_nature = oldlim["lim_typologie_nature"]
            oldlim_geom = oldlim.geometry()
            oldlim_geom_pl = oldlim_geom.asPolyline()
            start_lim_pt = oldlim_geom_pl[0]
            end_lim_pt = oldlim_geom_pl[-1]
            nw_pt_lst = []
            # Manage each new vertex
            for nwpt in self.l_vertex.selectedFeatures():
                # Find the creator
                ge_createur = nwpt["som_ge_createur"]
                nwpt_geom = nwpt.geometry()
                nwpt_geom_pt = nwpt_geom.asPoint()
                nw_pt_onlim = oldlim_geom.nearestPoint(nwpt_geom)
                dist_to_lim = dist_2_pts(
                    coords_tr_cc.transform(nwpt_geom_pt),
                    coords_tr_cc.transform(nw_pt_onlim.asPoint()))
                dist_pr_st = dist_2_pts(
                    coords_tr_cc.transform(start_lim_pt),
                    coords_tr_cc.transform(nw_pt_onlim.asPoint()))
                dist_pr_en = dist_2_pts(
                    coords_tr_cc.transform(end_lim_pt),
                    coords_tr_cc.transform(nw_pt_onlim.asPoint()))
                # Check if the new vertex is out of the old limit
                if dist_pr_en == 0 or dist_pr_st == 0:
                    QMessageBox.information(
                        self, cutlim_vtxout_msg[0],
                        cutlim_vtxout_msg[1].format(nwpt.id()))
                else:
                    # Create the list of new points to use for the new lmits
                    nw_pt_lst.append(
                        [dist_pr_st,
                         nwpt.id(), dist_to_lim, nwpt_geom_pt])
            # Sot the list of new points by their distance to the start vertex
            nw_pt_lst.sort()
            msg = ""
            if len(nw_pt_lst) > 0:
                # Create a message showing the distances, and asking to continue
                for nw_pt_info in nw_pt_lst:
                    msg += msg_dist.format(nw_pt_info[1], float(nw_pt_info[2]))
                q_ok = QMessageBox.question(self, cutlim_vtxdist_msg[0],
                                            cutlim_vtxdist_msg[1].format(msg),
                                            QMessageBox.Yes | QMessageBox.No)
                # The user continues
                if q_ok == QMessageBox.Yes:
                    for id, pt in enumerate(nw_pt_lst):
                        end_vtx = pt[3]
                        if id == 0:
                            st_vtx = start_lim_pt
                        line = QgsGeometry.fromPolylineXY([st_vtx, end_vtx])
                        st_vtx = pt[3]
                        nw_attvals = [
                            NULL, NULL, ge_createur, lim_delim_pub,
                            lim_typologie_nature
                        ]
                        # Create the feature
                        create_nw_feat(self.l_edge, line, nw_attvals)
                        # Case of the last limit to create
                        if id == (len(nw_pt_lst) - 1):
                            line = QgsGeometry.fromPolylineXY(
                                [end_vtx, end_lim_pt])
                            create_nw_feat(self.l_edge, line, nw_attvals)
                    self.l_edge.deleteFeature(oldlim.id())
                    self.l_edge.removeSelection()
                    self.l_vertex.removeSelection()
                    QMessageBox.information(self, cutlim_end_msg[0],
                                            cutlim_end_msg[1])
                else:
                    self.show()
            # No new limit to create
            else:
                QMessageBox.information(self, cutlim_noncre_msg[0],
                                        cutlim_noncre_msg[1])
                self.show()

    def closeEvent(self, event):
        self.l_vertex.removeSelection()
        self.l_edge.removeSelection()
        self.close()
class AssociateExtAddressWizard(QWizard, WIZARD_UI):
    def __init__(self, iface, db, qgis_utils, parent=None):
        QWizard.__init__(self, parent)
        self.setupUi(self)
        self.iface = iface
        self.log = QgsApplication.messageLog()
        self._db = db
        self.qgis_utils = qgis_utils
        self.canvas = self.iface.mapCanvas()
        self.maptool = self.canvas.mapTool()
        self.maptool_identify = None
        self.help_strings = HelpStrings()
        self.translatable_config_strings = TranslatableConfigStrings()
        self._extaddress_layer = None
        self._plot_layer = None
        self._building_layer = None
        self._building_unit_layer = None
        self._current_layer = None

        self._feature_tid = None

        self.restore_settings()

        self.rad_to_plot.toggled.connect(self.adjust_page_1_controls)
        self.rad_to_building.toggled.connect(self.adjust_page_1_controls)
        self.rad_to_building_unit.toggled.connect(self.adjust_page_1_controls)
        self.adjust_page_1_controls()
        self.button(QWizard.NextButton).clicked.connect(self.prepare_selection)
        self.button(QWizard.FinishButton).clicked.connect(self.finished_dialog)
        self.button(QWizard.HelpButton).clicked.connect(self.show_help)

        self.mMapLayerComboBox.setFilters(QgsMapLayerProxyModel.PolygonLayer)

        self.bar = QgsMessageBar()
        self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed)
        self.setLayout(QGridLayout())
        self.layout().addWidget(self.bar, 0, 0, Qt.AlignTop)

    def adjust_page_1_controls(self):
        self.cbo_mapping.clear()
        self.cbo_mapping.addItem("")
        self.cbo_mapping.addItems(
            self.qgis_utils.get_field_mappings_file_names(EXTADDRESS_TABLE))

        if self.rad_refactor.isChecked():
            self.lbl_refactor_source.setEnabled(True)
            self.mMapLayerComboBox.setEnabled(True)
            self.lbl_field_mapping.setEnabled(True)
            self.cbo_mapping.setEnabled(True)
            disable_next_wizard(self)
            FinishButton_text = QCoreApplication.translate(
                "AssociateExtAddressWizard", "Import")
            self.txt_help_page_1.setHtml(
                self.help_strings.get_refactor_help_string(
                    EXTADDRESS_TABLE, True))
            self.wizardPage1.setFinalPage(True)
            self.wizardPage1.setButtonText(
                QWizard.FinishButton,
                QCoreApplication.translate("AssociateExtAddressWizard",
                                           FinishButton_text))

        elif self.rad_to_plot.isChecked():
            self.lbl_refactor_source.setEnabled(False)
            self.mMapLayerComboBox.setEnabled(False)
            self.lbl_field_mapping.setEnabled(False)
            self.cbo_mapping.setEnabled(False)
            self.wizardPage1.setFinalPage(False)
            enable_next_wizard(self)
            FinishButton_text = QCoreApplication.translate(
                "AssociateExtAddressWizard", "Associate Plot ExtAddress")
            self.txt_help_page_1.setHtml(
                self.help_strings.
                WIZ_ASSOCIATE_EXTADDRESS_CADASTRE_PAGE_1_OPTION_1)

        elif self.rad_to_building.isChecked():
            self.lbl_refactor_source.setEnabled(False)
            self.mMapLayerComboBox.setEnabled(False)
            self.lbl_field_mapping.setEnabled(False)
            self.cbo_mapping.setEnabled(False)
            self.wizardPage1.setFinalPage(False)
            enable_next_wizard(self)
            FinishButton_text = QCoreApplication.translate(
                "AssociateExtAddressWizard", "Associate Building ExtAddress")
            self.txt_help_page_1.setHtml(
                self.help_strings.
                WIZ_ASSOCIATE_EXTADDRESS_CADASTRE_PAGE_1_OPTION_2)

        else:  #self.rad_to_building_unit.isChecked():
            self.lbl_refactor_source.setEnabled(False)
            self.mMapLayerComboBox.setEnabled(False)
            self.lbl_field_mapping.setEnabled(False)
            self.cbo_mapping.setEnabled(False)
            self.wizardPage1.setFinalPage(False)
            enable_next_wizard(self)
            FinishButton_text = QCoreApplication.translate(
                "AssociateExtAddressWizard",
                "Associate Building Unit ExtAddress")
            self.txt_help_page_1.setHtml(
                self.help_strings.
                WIZ_ASSOCIATE_EXTADDRESS_CADASTRE_PAGE_1_OPTION_3)

        self.wizardPage2.setButtonText(
            QWizard.FinishButton,
            QCoreApplication.translate('AssociateExtAddressWizard',
                                       FinishButton_text))

    def prepare_selection(self):
        self.button(self.FinishButton).setDisabled(True)
        if self.rad_to_plot.isChecked():
            self.btn_select.setText(
                QCoreApplication.translate("AssociateExtAddressWizard",
                                           "Select Plot"))
            self.txt_help_page_2.setHtml(
                self.help_strings.
                WIZ_ASSOCIATE_EXTADDRESS_CADASTRE_PAGE_2_OPTION_1)
            # Load layers
            res_layers = self.qgis_utils.get_layers(self._db, {
                EXTADDRESS_TABLE: {
                    'name': EXTADDRESS_TABLE,
                    'geometry': QgsWkbTypes.PointGeometry
                },
                PLOT_TABLE: {
                    'name': PLOT_TABLE,
                    'geometry': QgsWkbTypes.PolygonGeometry
                }
            },
                                                    load=True)

            self._extaddress_layer = res_layers[EXTADDRESS_TABLE]
            self._plot_layer = res_layers[PLOT_TABLE]
            self._current_layer = self._plot_layer

        elif self.rad_to_building.isChecked():
            self.btn_select.setText(
                QCoreApplication.translate("AssociateExtAddressWizard",
                                           "Select Building"))
            self.txt_help_page_2.setHtml(
                self.help_strings.
                WIZ_ASSOCIATE_EXTADDRESS_CADASTRE_PAGE_2_OPTION_2)

            # Load layers
            res_layers = self.qgis_utils.get_layers(self._db, {
                EXTADDRESS_TABLE: {
                    'name': EXTADDRESS_TABLE,
                    'geometry': QgsWkbTypes.PointGeometry
                },
                BUILDING_TABLE: {
                    'name': BUILDING_TABLE,
                    'geometry': QgsWkbTypes.PolygonGeometry
                }
            },
                                                    load=True)

            self._extaddress_layer = res_layers[EXTADDRESS_TABLE]
            self._building_layer = res_layers[BUILDING_TABLE]
            self._current_layer = self._building_layer

        else:  #self.rad_to_building_unit.isChecked():
            self.btn_select.setText(
                QCoreApplication.translate("AssociateExtAddressWizard",
                                           "Select Building Unit"))
            self.txt_help_page_2.setHtml(
                self.help_strings.
                WIZ_ASSOCIATE_EXTADDRESS_CADASTRE_PAGE_2_OPTION_3)

            # Load layers
            res_layers = self.qgis_utils.get_layers(self._db, {
                EXTADDRESS_TABLE: {
                    'name': EXTADDRESS_TABLE,
                    'geometry': QgsWkbTypes.PointGeometry
                },
                BUILDING_UNIT_TABLE: {
                    'name': BUILDING_UNIT_TABLE,
                    'geometry': QgsWkbTypes.PolygonGeometry
                }
            },
                                                    load=True)

            self._extaddress_layer = res_layers[EXTADDRESS_TABLE]
            self._building_unit_layer = res_layers[BUILDING_UNIT_TABLE]
            self._current_layer = self._building_unit_layer

        self.iface.setActiveLayer(self._current_layer)
        self.check_selected_features()
        self.btn_select.clicked.connect(self.select_feature)
        self.btn_select_by_expression.clicked.connect(
            self.select_feature_by_expression)

    def check_selected_features(self):
        self.bar.clearWidgets()

        if self._current_layer.selectedFeatureCount() == 1:
            self.lbl_selected.setText(
                QCoreApplication.translate("AssociateExtAddressWizard",
                                           "1 Feature Selected"))
            self.button(self.FinishButton).setDisabled(False)
            self._feature_tid = self._current_layer.selectedFeatures(
            )[0][ID_FIELD]
            self.canvas.zoomToSelected(self._current_layer)
        elif self._current_layer.selectedFeatureCount() > 1:
            self.show_message(
                QCoreApplication.translate("AssociateExtAddressWizard",
                                           "Please select just one feature"),
                Qgis.Warning)
            self.lbl_selected.setText(
                QCoreApplication.translate(
                    "AssociateExtAddressWizard",
                    "{} Feature(s) Selected".format(
                        self._current_layer.selectedFeatureCount())))
            self.button(self.FinishButton).setDisabled(True)
        else:
            self.lbl_selected.setText(
                QCoreApplication.translate("AssociateExtAddressWizard",
                                           "0 Features Selected"))
            self.button(self.FinishButton).setDisabled(True)

    def select_feature_by_expression(self):
        Dlg_expression_selection = QgsExpressionSelectionDialog(
            self._current_layer)
        self._current_layer.selectionChanged.connect(
            self.check_selected_features)
        Dlg_expression_selection.exec()
        self._current_layer.selectionChanged.disconnect(
            self.check_selected_features)

    def select_feature(self):
        self.setVisible(False)  # Make wizard disappear

        # Create maptool
        self.maptool_identify = QgsMapToolIdentifyFeature(self.canvas)
        self.maptool_identify.setLayer(self._current_layer)
        cursor = QCursor()
        cursor.setShape(Qt.CrossCursor)
        self.maptool_identify.setCursor(cursor)
        self.canvas.setMapTool(self.maptool_identify)
        self.maptool_identify.featureIdentified.connect(self.get_feature_id)

        # TODO: Take into account that a user can select another tool

    def get_feature_id(self, feature):
        self.setVisible(True)  # Make wizard appear
        if feature:
            self.lbl_selected.setText(
                QCoreApplication.translate("AssociateExtAddressWizard",
                                           "1 Feature Selected"))
            self._current_layer.selectByIds([feature.id()])

        self.canvas.setMapTool(self.maptool)
        self.check_selected_features()

        self.maptool_identify.featureIdentified.disconnect(self.get_feature_id)
        self.log.logMessage(
            "Spatial Unit's featureIdentified SIGNAL disconnected",
            PLUGIN_NAME, Qgis.Info)

    def finished_dialog(self):
        self.save_settings()

        if self.rad_refactor.isChecked():
            if self.mMapLayerComboBox.currentLayer() is not None:
                field_mapping = self.cbo_mapping.currentText()
                res_etl_model = self.qgis_utils.show_etl_model(
                    self._db,
                    self.mMapLayerComboBox.currentLayer(),
                    EXTADDRESS_TABLE,
                    field_mapping=field_mapping)

                if res_etl_model:
                    if field_mapping:
                        self.qgis_utils.delete_old_field_mapping(field_mapping)

                    self.qgis_utils.save_field_mapping(EXTADDRESS_TABLE)

            else:
                self.iface.messageBar().pushMessage(
                    'Asistente LADM_COL',
                    QCoreApplication.translate(
                        "AssociateExtAddressWizard",
                        "Select a source layer to set the field mapping to '{}'."
                    ).format(EXTADDRESS_TABLE), Qgis.Warning)

        else:
            self.prepare_extaddress_creation()

    def prepare_extaddress_creation(self):
        # Don't suppress (i.e., show) feature form
        form_config = self._extaddress_layer.editFormConfig()
        form_config.setSuppress(QgsEditFormConfig.SuppressOff)
        self._extaddress_layer.setEditFormConfig(form_config)

        self.edit_extaddress()

    def edit_extaddress(self):
        if self._current_layer.selectedFeatureCount() == 1:
            # Open Form
            self.iface.layerTreeView().setCurrentLayer(self._extaddress_layer)
            self._extaddress_layer.startEditing()
            self.iface.actionAddFeature().trigger()

            # Create connections to react when a feature is added to buffer and
            # when it gets stored into the DB
            self._extaddress_layer.featureAdded.connect(
                self.call_extaddress_commit)

        else:
            self.iface.messageBar().pushMessage(
                "Asistente LADM_COL",
                QCoreApplication.translate("AssociateExtAddressWizard",
                                           "Please select a feature"),
                Qgis.Warning)

    def call_extaddress_commit(self, fid):
        plot_field_idx = self._extaddress_layer.getFeature(fid).fieldNameIndex(
            EXTADDRESS_PLOT_FIELD)
        building_field_idx = self._extaddress_layer.getFeature(
            fid).fieldNameIndex(EXTADDRESS_BUILDING_FIELD)
        building_unit_field_idx = self._extaddress_layer.getFeature(
            fid).fieldNameIndex(EXTADDRESS_BUILDING_UNIT_FIELD)

        if self._current_layer.name() == PLOT_TABLE:
            self._extaddress_layer.changeAttributeValue(
                fid, plot_field_idx, self._feature_tid)
        elif self._current_layer.name() == BUILDING_TABLE:
            self._extaddress_layer.changeAttributeValue(
                fid, building_field_idx, self._feature_tid)
        else:  #self._current_layer.name() == BUILDING_UNIT_TABLE:
            self._extaddress_layer.changeAttributeValue(
                fid, building_unit_field_idx, self._feature_tid)

        self._extaddress_layer.featureAdded.disconnect(
            self.call_extaddress_commit)
        self.log.logMessage("Extaddres's featureAdded SIGNAL disconnected",
                            PLUGIN_NAME, Qgis.Info)
        res = self._extaddress_layer.commitChanges()
        self._current_layer.removeSelection()

    def show_message(self, message, level):
        self.bar.pushMessage(message, level, 0)

    def save_settings(self):
        settings = QSettings()

        load_data_type = 'refactor'
        if self.rad_to_plot.isChecked():
            load_data_type = 'to_plot'
        elif self.rad_to_building.isChecked():
            load_data_type = 'to_building'
        else:  #self.rad_to_building_unit.isChecked():
            load_data_type = 'to_building_unit'

        settings.setValue(
            'Asistente-LADM_COL/wizards/ext_address_load_data_type',
            load_data_type)

    def restore_settings(self):
        settings = QSettings()

        load_data_type = settings.value(
            'Asistente-LADM_COL/wizards/ext_address_load_data_type', 'to_plot')
        if load_data_type == 'refactor':
            self.rad_refactor.setChecked(True)
        elif load_data_type == 'to_plot':
            self.rad_to_plot.setChecked(True)
        elif load_data_type == 'to_building':
            self.rad_to_building.setChecked(True)
        else:  #load_data_type == 'to_building_unit':
            self.rad_to_building_unit.setChecked(True)

    def show_help(self):
        self.qgis_utils.show_help("associate_ext_address")