Ejemplo n.º 1
0
class NewCaptureSourceArea(QFrame, FORM_CLASS):
    def __init__(self, dockwidget, parent=None):
        """Constructor."""
        super(NewCaptureSourceArea, self).__init__(parent)
        self.setupUi(self)

        self.db = db
        self.db.connect()

        self.dockwidget = dockwidget
        self.layer_registry = LayerRegistry()
        self.error_dialog = None
        self.current_layer = None

        self.added_building_ids = []
        self.geom = None

        self.add_capture_source_area_layer()
        self.init_table()
        self.setup_toolbar()

        self.le_area_title.setDisabled(True)
        self.le_external_id.setDisabled(True)
        self.mcb_selection_layer.setDisabled(True)
        self.mcb_selection_layer.setExceptedLayerList(
            [self.capture_source_area])
        self.rb_select_from_layer.setChecked(False)

        self.capture_source_area.featureAdded.connect(
            self.creator_feature_added)
        self.capture_source_area.featureDeleted.connect(
            self.creator_feature_deleted)
        self.capture_source_area.geometryChanged.connect(
            self.creator_geometry_changed)

        self.rb_select_from_layer.toggled.connect(
            self.rb_select_from_layer_clicked)

        self.btn_save.clicked.connect(
            partial(self.save_clicked, commit_status=True))
        self.btn_reset.clicked.connect(self.reset_clicked)
        self.btn_exit.clicked.connect(self.exit_clicked)

        QgsProject.instance().layerWillBeRemoved.connect(self.layers_removed)

        iface.actionToggleEditing().trigger()
        iface.actionAddFeature().trigger()

    def rb_select_from_layer_clicked(self, checked):
        """PyqtSlot: When the select from layer radio button is clicked"""
        self.l_wrong_projection.setText("")
        if checked:
            self.mcb_selection_layer.showPopup()
            self.mcb_selection_layer.setEnabled(True)
            iface.actionSelect().trigger()
            self.mcb_selection_layer.layerChanged.connect(
                self.mcb_selection_layer_changed)
        else:
            self.mcb_selection_layer.layerChanged.disconnect(
                self.mcb_selection_layer_changed)
            if self.current_layer is not None:
                self.current_layer.removeSelection()
                self.current_layer.selectionChanged.disconnect(
                    self.current_layer_selection_changed)

            self.mcb_selection_layer.setDisabled(True)
            iface.actionAddFeature().trigger()
            self.current_layer = None
            iface.setActiveLayer(self.current_layer)

    def mcb_selection_layer_changed(self, current_layer):
        """PyQtSlot: When the multi-combobox layer to select from is changed"""
        if current_layer is None:
            return
        if not self.check_projection(current_layer):
            self.l_wrong_projection.setText("ERROR: Incorrect Projection")
            self.is_wrong_projection = True
        else:
            self.l_wrong_projection.setText("")
            self.is_wrong_projection = False

        if self.current_layer is not None:
            self.current_layer.removeSelection()
            try:
                self.current_layer.selectionChanged.disconnect(
                    self.current_layer_selection_changed)
            except TypeError:
                pass
        self.current_layer = current_layer
        iface.setActiveLayer(current_layer)
        self.current_layer.selectionChanged.connect(
            self.current_layer_selection_changed)

    def current_layer_selection_changed(self):
        """PyqtSlot: When the selection of the current layer is changed"""
        if self.is_wrong_projection:
            self.projection_error()
            return
        selection = self.current_layer.selectedFeatures()
        if len(selection) == 0:
            self.le_external_id.setDisabled(True)
            self.le_area_title.setDisabled(True)
        elif len(selection) > 1:
            self.le_external_id.setDisabled(True)
            self.le_area_title.setDisabled(True)
            iface.messageBar().pushMessage(
                "INFO",
                "More than one feature selected, please re-select.",
                level=Qgis.Info,
                duration=3)
        elif len(selection) == 1:
            new_geometry = selection[0].geometry()
            # error pops up if geometry type is not polygon or multipolygon
            if new_geometry.wkbType() not in [
                    QgsWkbTypes.Polygon, QgsWkbTypes.MultiPolygon
            ]:
                self.error_dialog = ErrorDialog()
                self.error_dialog.fill_report(
                    "\n -------------------- WRONG GEOMETRY TYPE ------"
                    "-------------- \n\nInserted capture source area "
                    "should be either polygon or multipolygon.")
                self.error_dialog.show()
                return
            self.le_external_id.setEnabled(True)
            self.le_area_title.setEnabled(True)
            # convert to correct format
            if new_geometry.wkbType() == QgsWkbTypes.Polygon:
                new_geometry = QgsGeometry.fromMultiPolygonXY(
                    [new_geometry.asPolygon()])
            wkt = new_geometry.asWkt()
            sql = general_select.convert_geometry
            result = self.db.execute_return(sql, (wkt, ))
            self.geom = result.fetchall()[0][0]

    def check_projection(self, layer):
        """Ensure layer has correct projection"""
        if layer.crs().authid() != "EPSG:2193":
            self.projection_error()
            return False
        return True

    def projection_error(self):
        """Error dialog on incorrect projection of layer"""
        self.error_dialog = ErrorDialog()
        self.error_dialog.fill_report(
            "\n -------------------- INCORRECT CRS-------------"
            "------- \n\nThe Coordinate Reference System is not NTZM 2000. "
            "Please resolve and reattempt.")
        self.error_dialog.show()

    def add_capture_source_area_layer(self):
        """Called on opening of frame to add capture source area layer"""
        path = os.path.join(os.path.dirname(os.path.dirname(__file__)),
                            "styles/")
        # add layer
        self.capture_source_area = self.layer_registry.add_postgres_layer(
            "capture_source_area", "capture_source_area", "shape",
            "buildings_reference", "", "")
        # set style
        self.capture_source_area.loadNamedStyle(path + "capture_source.qml")
        # make capture source area the active layer
        iface.setActiveLayer(self.capture_source_area)

    def init_table(self):
        """Set up capture source area table"""
        tbl = self.tbl_capture_source_area
        tbl.setRowCount(0)
        tbl.setColumnCount(2)
        tbl.setHorizontalHeaderItem(0, QTableWidgetItem("Id"))
        tbl.setHorizontalHeaderItem(1, QTableWidgetItem("Area Title"))
        tbl.horizontalHeader().setSectionResizeMode(
            QHeaderView.ResizeToContents)
        tbl.verticalHeader().setVisible(False)
        tbl.setSelectionBehavior(QAbstractItemView.SelectRows)
        tbl.setSelectionMode(QAbstractItemView.SingleSelection)
        tbl.setShowGrid(True)
        sql_csa = reference_select.capture_source_area_id_and_name
        result = self.db.execute_return(sql_csa)
        for (polygon_id, area_title) in result.fetchall():
            row_tbl = tbl.rowCount()
            tbl.setRowCount(row_tbl + 1)
            tbl.setItem(row_tbl, 0, QTableWidgetItem("%s" % polygon_id))
            tbl.setItem(row_tbl, 1, QTableWidgetItem("%s" % area_title))
        tbl.sortItems(0)

    def setup_toolbar(self):
        """Called on opening of from to set up the buildings toolbar for selection only"""
        selecttools = iface.attributesToolBar().findChildren(QToolButton)
        # selection actions
        iface.building_toolbar.addSeparator()
        for sel in selecttools:
            if sel.text() == "Select Feature(s)":
                for a in sel.actions()[0:3]:
                    iface.building_toolbar.addAction(a)
        # editing actions
        iface.building_toolbar.addSeparator()
        for dig in iface.digitizeToolBar().actions():
            if dig.objectName() in [
                    "mActionAddFeature", "mActionNodeTool",
                    "mActionMoveFeature"
            ]:
                iface.building_toolbar.addAction(dig)
        # advanced Actions
        iface.building_toolbar.addSeparator()
        for adv in iface.advancedDigitizeToolBar().actions():
            if adv.objectName() in [
                    "mActionUndo", "mActionRedo", "mActionReshapeFeatures",
                    "mActionOffsetCurve"
            ]:
                iface.building_toolbar.addAction(adv)
        iface.building_toolbar.show()

    def creator_feature_added(self, qgsfId):
        """
           Called when feature is added
           @param qgsfId:      Id of added feature
           @type  qgsfId:      qgis.core.QgsFeature.QgsFeatureId
        """
        if qgsfId not in self.added_building_ids:
            self.added_building_ids.append(qgsfId)
        # get new feature geom
        request = QgsFeatureRequest().setFilterFid(qgsfId)
        new_feature = next(self.capture_source_area.getFeatures(request))
        new_geometry = new_feature.geometry()
        # convert to correct format
        if new_geometry.wkbType() == QgsWkbTypes.Polygon:
            new_geometry = QgsGeometry.fromMultiPolygonXY(
                [new_geometry.asPolygon()])
        wkt = new_geometry.asWkt()
        sql = general_select.convert_geometry
        result = self.db.execute_return(sql, (wkt, ))
        self.geom = result.fetchall()[0][0]
        self.le_area_title.setEnabled(True)
        self.le_external_id.setEnabled(True)

    def creator_feature_deleted(self, qgsfId):
        """
            Called when a Feature is Deleted
            @param qgsfId:      Id of deleted feature
            @type  qgsfId:      qgis.core.QgsFeature.QgsFeatureId
        """
        if qgsfId in self.added_building_ids:
            self.added_building_ids.remove(qgsfId)
            if self.added_building_ids == []:
                self.le_area_title.setDisabled(True)
                self.le_external_id.setDisabled(True)
                self.geom = None

    def creator_geometry_changed(self, qgsfId, geom):
        """
           Called when feature is changed
           @param qgsfId:      Id of added feature
           @type  qgsfId:      qgis.core.QgsFeature.QgsFeatureId
           @param geom:        geometry of added feature
           @type  geom:        qgis.core.QgsGeometry
        """
        if qgsfId in self.added_building_ids:
            if geom.wkbType() == QgsWkbTypes.Polygon:
                geom = QgsGeometry.fromMultiPolygonXY([geom.asPolygon()])
            wkt = geom.asWkt()
            if not wkt:
                self.disable_UI_functions()
                self.geom = None
                return
            sql = general_select.convert_geometry
            result = self.db.execute_return(sql, (wkt, ))
            self.geom = result.fetchall()[0][0]
        else:
            self.error_dialog = ErrorDialog()
            self.error_dialog.fill_report(
                "\n -------------------- WRONG GEOMETRY EDITED ------"
                "-------------- \n\nOnly current added outline can "
                "be edited. Please go to [Edit Geometry] to edit "
                "existing outlines.")
            self.error_dialog.show()

    def save_clicked(self, commit_status):
        """PyqtSlot: Called when save is clicked"""

        if self.le_area_title.text() == "" or self.le_external_id.text() == "":
            self.error_dialog = ErrorDialog()
            self.error_dialog.fill_report(
                "\n -------------------- Empty Area Title ------"
                "-------------- \n\nPlease add the title and "
                "external id for the newly created capture "
                "source area.")
            self.error_dialog.show()
            return

        self.db.open_cursor()

        area_title = self.le_area_title.text()
        external_id = self.le_external_id.text()
        geom = self.geom
        sql = "SELECT buildings_reference.capture_source_area_insert(%s, %s, %s)"
        self.db.execute_no_commit(sql, (external_id, area_title, geom))

        self.init_table()
        self.le_area_title.clear()
        self.le_external_id.clear()
        self.le_area_title.setDisabled(True)
        self.le_external_id.setDisabled(True)

        if commit_status:
            self.db.commit_open_cursor()
            self.geom = None
            self.added_building_ids = []

    def reset_clicked(self):
        """Called When reset is clicked"""
        self.geom = None
        self.added_building_ids = []
        self.le_area_title.clear()
        self.le_area_title.setDisabled(True)
        self.le_external_id.setDisabled(True)
        self.rb_select_from_layer.setChecked(False)
        self.mcb_selection_layer.setDisabled(True)
        self.l_wrong_projection.setText("")

        iface.setActiveLayer(self.capture_source_area)
        self.capture_source_area.geometryChanged.disconnect(
            self.creator_geometry_changed)
        iface.actionCancelEdits().trigger()
        self.capture_source_area.geometryChanged.connect(
            self.creator_geometry_changed)
        # restart editing
        iface.actionToggleEditing().trigger()
        iface.actionAddFeature().trigger()

    def exit_clicked(self):
        """Called when exit is clicked"""
        self.close_frame()

    def close_frame(self):
        """Close the frame"""
        self.rb_select_from_layer.setChecked(False)
        self.mcb_selection_layer.setDisabled(True)
        self.geom = None
        self.added_building_ids = []
        self.current_layer = None
        QgsProject.instance().layerWillBeRemoved.disconnect(
            self.layers_removed)
        self.layer_registry.remove_layer(self.capture_source_area)
        from buildings.gui.new_capture_source import NewCaptureSource

        dw = self.dockwidget
        dw.stk_options.removeWidget(dw.stk_options.currentWidget())
        dw.new_widget(NewCaptureSource(dw))

    def layers_removed(self, layerids):
        """Check no necessary layers are removed from the map canvas"""
        self.layer_registry.update_layers()
        if "capture_source_area" in layerids:
            self.le_area_title.setDisabled(1)
            self.le_external_id.setDisabled(1)
            self.btn_save.setDisabled(1)
            self.btn_reset.setDisabled(1)
            self.tbl_capture_source_area.setDisabled(1)
            iface.messageBar().pushMessage(
                "ERROR",
                "Required layer Removed! Please reload the buildings plugin or the current frame before continuing",
                level=Qgis.Critical,
                duration=5,
            )
            return
Ejemplo n.º 2
0
class EditAttribute(ProductionChanges):
    """
        Class to edit attributes in buildings.building_outlines
        Inherits ProductionChanges
    """
    def __init__(self, edit_dialog):
        """Constructor"""
        ProductionChanges.__init__(self, edit_dialog)
        # set editing to edit polygon
        iface.actionSelect().trigger()
        selecttools = iface.attributesToolBar().findChildren(QToolButton)
        # selection actions
        iface.building_toolbar.addSeparator()
        for sel in selecttools:
            if sel.text() == "Select Feature(s)":
                for a in sel.actions()[0:3]:
                    iface.building_toolbar.addAction(a)
        iface.building_toolbar.show()
        self.msgbox_remove = self.confirmation_dialog_box("remove")

        self.disable_UI_functions()

        if len(self.editing_layer.selectedFeatures()) > 0:
            if self.is_correct_selections():
                self.get_selections()
                self.enable_UI_functions()
                self.populate_edit_comboboxes()
                self.select_comboboxes_value()
            else:
                self.edit_dialog.ids = []
                self.edit_dialog.building_outline_id = None
                self.disable_UI_functions()

    def edit_save_clicked(self, commit_status):
        """
            When production frame btn_edit_save clicked
        """
        self.edit_dialog.db.open_cursor()

        capture_method_id, capture_source_id, lifecycle_stage_id, suburb, town, t_a = self.get_comboboxes_values(
        )

        if len(self.edit_dialog.ids) > 0:
            for i in self.edit_dialog.ids:
                sql = "SELECT buildings.building_outlines_update_attributes(%s, %s, %s, %s, %s, %s, %s);"
                self.edit_dialog.db.execute_no_commit(
                    sql, (i, capture_method_id, capture_source_id,
                          lifecycle_stage_id, suburb, town, t_a))
                sql = "SELECT buildings.building_outlines_update_modified_date(%s);"
                self.edit_dialog.db.execute_no_commit(sql, (i, ))
        self.disable_UI_functions()

        if commit_status:
            self.edit_dialog.db.commit_open_cursor()
            self.edit_dialog.ids = []
            self.edit_dialog.building_outline_id = None

    def edit_reset_clicked(self):
        """
            When production frame btn_edit_reset clicked
        """
        self.edit_dialog.ids = []
        self.edit_dialog.building_outline_id = None
        # restart editing
        iface.actionSelect().trigger()
        iface.activeLayer().removeSelection()
        # reset and disable comboboxes
        self.disable_UI_functions()

    def selection_changed(self, added, removed, cleared):
        """
           Called when feature is selected
        """
        # If no outlines are selected the function will return
        if len(self.editing_layer.selectedFeatures()) == 0:
            self.edit_dialog.ids = []
            self.edit_dialog.building_outline_id = None
            self.disable_UI_functions()
            return
        if self.is_correct_selections():
            self.get_selections()
            self.enable_UI_functions()
            self.populate_edit_comboboxes()
            self.select_comboboxes_value()
        else:
            self.edit_dialog.ids = []
            self.edit_dialog.building_outline_id = None
            self.disable_UI_functions()

    def end_lifespan(self, commit_status):
        """ end the lifespan of building"""
        # get the dataset id and dates of the most recent supplied dataset
        if not self.confirm(self.msgbox_remove):
            return
        dates = self.edit_dialog.db.execute_return(
            bulk_load_select.supplied_dataset_latest_id_and_dates)
        dates = dates.fetchone()

        # get list of building_ids from building_outline_ids
        building_ids = []
        for outline in self.edit_dialog.ids:
            result = self.edit_dialog.db.execute_return(
                buildings_select.building_id_by_building_outline_id,
                (outline, ))
            building_ids.append(result.fetchone()[0])

        # if the current supplied dataset is not in compare
        is_bulk_loaded = dates[1] is None and dates[2] is None
        is_compared = dates[1] is not None and dates[2] is None
        is_published = dates[1] is not None and dates[2] is not None
        if is_bulk_loaded or is_published:
            if self.edit_dialog.db._open_cursor is None:
                self.edit_dialog.db.open_cursor()
            # end lifespan in use table
            sql = "SELECT buildings.building_use_update_end_lifespan(%s);"
            self.edit_dialog.db.execute_no_commit(sql, (building_ids, ))
            # end lifespan in name table
            sql = "SELECT buildings.building_name_update_end_lifespan(%s);"
            self.edit_dialog.db.execute_no_commit(sql, (building_ids, ))
            # end lifespan in building outlines table
            sql = "SELECT buildings.building_outlines_update_end_lifespan(%s);"
            result = self.edit_dialog.db.execute_no_commit(
                sql, (self.edit_dialog.ids, ))
            # end lifespan in buildings table
            sql = "SELECT buildings.buildings_update_end_lifespan(%s);"
            self.edit_dialog.db.execute_no_commit(sql, (building_ids, ))
            if commit_status:
                self.edit_dialog.db.commit_open_cursor()
                self.edit_dialog.ids = []
                self.edit_dialog.building_outline_id = None
                self.editing_layer.removeSelection()
                iface.mapCanvas().refreshAllLayers()

        # if current is in compare
        elif is_compared:
            bool_delete = True
            for outline in self.edit_dialog.ids:
                # see if outline in existing_subset_extracts
                dataset = self.edit_dialog.db.execute_return(
                    bulk_load_select.
                    existing_subset_extracts_dataset_by_building_outline_id,
                    (outline, ))
                dataset = dataset.fetchone()
                # if the outline is in existing_subset_extracts
                if dataset:
                    # if the dataset the outline relates to is the current dataset
                    if dataset[0] == dates[0]:
                        # check if the bulk_loaded_outline is in removed table
                        removed_count = self.edit_dialog.db.execute_return(
                            bulk_load_select.
                            removed_count_by_building_outline_id, (outline, ))
                        removed_count = removed_count.fetchone()
                        if removed_count[0] == 0:
                            # if it isn't error
                            self.error_dialog = ErrorDialog()
                            self.error_dialog.fill_report(
                                "\n -------------------- BUILDING HAS RELATIONSHIP ------"
                                "-------------- \n\nYou cannot delete this outline as it has"
                                " a relationship with a current bulk loaded outline, first remove "
                                "this relationship and then try again.")
                            self.error_dialog.show()
                            bool_delete = False
                            break
            # if able to delete outlines
            if bool_delete:
                if self.edit_dialog.db._open_cursor is None:
                    self.edit_dialog.db.open_cursor()
                # end lifespan in use table
                sql = "SELECT buildings.building_use_update_end_lifespan(%s);"
                self.edit_dialog.db.execute_no_commit(sql, (building_ids, ))
                # end lifespan in name table
                sql = "SELECT buildings.building_name_update_end_lifespan(%s);"
                self.edit_dialog.db.execute_no_commit(sql, (building_ids, ))
                # remove outline from removed table
                sql = "SELECT buildings_bulk_load.removed_delete_existing_outlines(%s);"
                self.edit_dialog.db.execute_no_commit(sql,
                                                      (self.edit_dialog.ids, ))
                # remove outline from existing subset extracts table
                sql = "SELECT buildings_bulk_load.existing_subset_extracts_remove_by_building_outline_id(%s);"
                self.edit_dialog.db.execute_no_commit(sql,
                                                      (self.edit_dialog.ids, ))
                # end lifespan in building outlines table
                sql = "SELECT buildings.building_outlines_update_end_lifespan(%s);"
                result = self.edit_dialog.db.execute_no_commit(
                    sql, (self.edit_dialog.ids, ))
                # end lifespan in buildings table
                sql = "SELECT buildings.buildings_update_end_lifespan(%s);"
                self.edit_dialog.db.execute_no_commit(sql, (building_ids, ))
                if commit_status:
                    self.edit_dialog.db.commit_open_cursor()
                    self.edit_dialog.ids = []
                    self.edit_dialog.building_outline_id = None
                    self.editing_layer.removeSelection()
                    iface.mapCanvas().refreshAllLayers()

    def is_correct_selections(self):
        """
            Check if the selections meet the requirement
        """
        feats = []
        for feature in self.editing_layer.selectedFeatures():
            ls = []
            ls.append(feature.attributes()[2])
            ls.append(feature.attributes()[3])
            ls.append(feature.attributes()[4])
            ls.append(feature.attributes()[5])
            ls.append(feature.attributes()[6])
            ls.append(feature.attributes()[7])
            if ls not in feats:
                feats.append(ls)
        # if selected features have different attributes (not allowed)
        if len(feats) > 1:
            self.error_dialog = ErrorDialog()
            self.error_dialog.fill_report(
                "\n ---- MULTIPLE NON IDENTICAL FEATURES SELECTED"
                " ---- \n\n Can only edit attributes of multiple"
                " features when all existing attributes a"
                "re identical.")
            self.error_dialog.show()
            return False
        # if all selected features have the same attributes (allowed)
        elif len(feats) == 1:
            return True
        return False

    def get_selections(self):
        """
            Return the selection values
        """
        self.edit_dialog.ids = [
            feat.id() for feat in self.editing_layer.selectedFeatures()
        ]
        self.edit_dialog.building_outline_id = [
            feat.id() for feat in self.editing_layer.selectedFeatures()
        ][0]
        building_feat = [
            feat for feat in self.editing_layer.selectedFeatures()
        ][0]
        building_geom = building_feat.geometry()
        # convert to correct format
        wkt = building_geom.asWkt()
        sql = general_select.convert_geometry
        result = self.edit_dialog.db.execute_return(sql, (wkt, ))
        self.edit_dialog.geom = result.fetchall()[0][0]

    def select_comboboxes_value(self):
        """
            Select the correct combobox value for the geometry
        """
        # lifecycle stage
        result = self.edit_dialog.db.execute_return(
            buildings_select.lifecycle_stage_value_by_building_outline_id,
            (self.edit_dialog.building_outline_id, ))
        result = result.fetchall()[0][0]
        self.edit_dialog.cmb_lifecycle_stage.setCurrentIndex(
            self.edit_dialog.cmb_lifecycle_stage.findText(result))

        # capture method
        result = self.edit_dialog.db.execute_return(
            common_select.capture_method_value_by_building_outline_id,
            (self.edit_dialog.building_outline_id, ))
        result = result.fetchall()[0][0]
        self.edit_dialog.cmb_capture_method.setCurrentIndex(
            self.edit_dialog.cmb_capture_method.findText(result))

        # capture source
        result = self.edit_dialog.db.execute_return(
            common_select.
            capture_source_group_value_external_by_building_outline_id,
            (self.edit_dialog.building_outline_id, ))
        result = result.fetchall()[0]
        text = "- ".join(result)
        self.edit_dialog.cmb_capture_source.setCurrentIndex(
            self.edit_dialog.cmb_capture_source.findText(text))

        # suburb
        result = self.edit_dialog.db.execute_return(
            reference_select.suburb_locality_suburb_4th_by_building_outline_id,
            (self.edit_dialog.building_outline_id, ))
        result = result.fetchall()[0][0]
        self.edit_dialog.cmb_suburb.setCurrentIndex(
            self.edit_dialog.cmb_suburb.findText(result))

        # town city
        result = self.edit_dialog.db.execute_return(
            reference_select.town_city_name_by_building_outline_id,
            (self.edit_dialog.building_outline_id, ))
        result = result.fetchall()
        if result:
            self.edit_dialog.cmb_town.setCurrentIndex(
                self.edit_dialog.cmb_town.findText(result[0][0]))
        else:
            self.edit_dialog.cmb_town.setCurrentIndex(0)

        # territorial Authority
        result = self.edit_dialog.db.execute_return(
            reference_select.territorial_authority_name_by_building_outline_id,
            (self.edit_dialog.building_outline_id, ))
        result = result.fetchall()[0][0]
        self.edit_dialog.cmb_ta.setCurrentIndex(
            self.edit_dialog.cmb_ta.findText(result))
Ejemplo n.º 3
0
class EditGeometry(BulkLoadChanges):
    """Class to edit outline's geometry in buildings_bulk_load.bulk_load_outlines Inherits BulkLoadChanges"""
    def __init__(self, edit_dialog):
        """Constructor"""
        BulkLoadChanges.__init__(self, edit_dialog)
        iface.actionToggleEditing().trigger()
        # set editing to edit polygon
        iface.actionVertexTool().trigger()
        selecttools = iface.attributesToolBar().findChildren(QToolButton)
        # selection actions
        iface.building_toolbar.addSeparator()
        for sel in selecttools:
            if sel.text() == "Select Feature(s)":
                for a in sel.actions()[0:3]:
                    iface.building_toolbar.addAction(a)
        # editing actions
        iface.building_toolbar.addSeparator()
        for dig in iface.digitizeToolBar().actions():
            if dig.objectName() in ["mActionVertexTool", "mActionMoveFeature"]:
                iface.building_toolbar.addAction(dig)
        # advanced Actions
        iface.building_toolbar.addSeparator()
        for adv in iface.advancedDigitizeToolBar().actions():
            if adv.objectName() in [
                    "mActionUndo",
                    "mActionRedo",
                    "mActionReshapeFeatures",
                    "mActionOffsetCurve",
                    "mActionSplitFeatures",
            ]:
                iface.building_toolbar.addAction(adv)
        iface.building_toolbar.show()

        self.disable_UI_functions()
        self.new_attrs = {}

    # @pyqtSlot(bool)
    def edit_save_clicked(self, commit_status):
        """When bulk load frame btn_edit_save clicked"""
        self.edit_dialog.db.open_cursor()

        _, capture_method_id, _, _, _, _ = self.get_comboboxes_values()

        self.edit_dialog.edit_geometry_saved.emit(
            list(self.edit_dialog.geoms.keys()))

        if len(self.edit_dialog.split_geoms) > 0:

            # insert into bulk_load_outlines table
            for qgsfId, geom in list(self.edit_dialog.split_geoms.items()):
                attributes = self.new_attrs[qgsfId]
                if not attributes[7]:
                    attributes[7] = None
                sql = "SELECT buildings_bulk_load.bulk_load_outlines_insert(%s, NULL, 2, %s, %s, %s, %s, %s, %s);"
                result = self.edit_dialog.db.execute_no_commit(
                    sql,
                    (
                        self.edit_dialog.current_dataset,
                        capture_method_id,
                        attributes[5],
                        attributes[6],
                        attributes[7],
                        attributes[8],
                        geom,
                    ),
                )
                self.edit_dialog.outline_id = result.fetchall()[0][0]

                # insert into added table
                result = self.edit_dialog.db.execute_return(
                    bulk_load_select.
                    supplied_dataset_processed_date_by_dataset_id,
                    (self.edit_dialog.current_dataset, ),
                )
                processed_date = result.fetchall()[0][0]

                if processed_date:
                    sql = "SELECT buildings_bulk_load.added_insert_bulk_load_outlines(%s, %s);"
                    self.edit_dialog.db.execute_no_commit(
                        sql, (self.edit_dialog.outline_id, 1))

        for key in self.edit_dialog.geoms:
            sql = "SELECT buildings_bulk_load.bulk_load_outlines_update_shape(%s, %s);"
            self.edit_dialog.db.execute_no_commit(
                sql, (self.edit_dialog.geoms[key], key))
            self.edit_dialog.db.execute_no_commit(
                "SELECT buildings_bulk_load.bulk_load_outlines_update_capture_method(%s, %s)",
                (key, capture_method_id),
            )

        if self.parent_frame.__class__.__name__ == "AlterRelationships":
            self.parent_frame.repaint_view()
        self.disable_UI_functions()

        if commit_status:
            self.edit_dialog.db.commit_open_cursor()
            self.edit_dialog.geoms = {}
            self.new_attrs = {}
            self.edit_dialog.editing_layer.triggerRepaint()

        if len(self.edit_dialog.split_geoms) > 0:
            self.edit_reset_clicked()
            self.parent_frame.reload_bulk_load_layer()
            self.edit_dialog.split_geoms = {}

    # @pyqtSlot()
    def edit_reset_clicked(self):
        """When bulk load frame btn_reset_save clicked"""
        self.editing_layer.geometryChanged.disconnect(self.geometry_changed)
        iface.actionCancelEdits().trigger()
        self.editing_layer.geometryChanged.connect(self.geometry_changed)
        self.edit_dialog.geoms = {}
        self.edit_dialog.split_geoms = {}
        self.new_attrs = {}
        # restart editing
        iface.actionToggleEditing().trigger()
        iface.actionVertexTool().trigger()
        iface.activeLayer().removeSelection()
        # reset and disable comboboxes
        self.disable_UI_functions()

    # @pyqtSlot(int, QgsGeometry)
    def geometry_changed(self, qgsfId, geom):
        """
           Called when feature is changed
           @param qgsfId:      Id of added feature
           @type  qgsfId:      qgis.core.QgsFeature.QgsFeatureId
           @param geom:        geometry of added feature
           @type  geom:        qgis.core.QgsGeometry
        """
        # get new feature geom and convert to correct format
        result = self.edit_dialog.db.execute_return(
            bulk_load_select.bulk_load_status_id_by_outline_id, (qgsfId, ))
        result = result.fetchone()
        if result is not None:
            if result[0] == 3:
                iface.messageBar().pushMessage(
                    "INFO",
                    "You cannot edit the geometry of a removed outline.",
                    level=Qgis.Info,
                    duration=3,
                )
                self.disable_UI_functions()
                self.edit_dialog.btn_edit_reset.setEnabled(1)
                return
        wkt = geom.asWkt()
        sql = general_select.convert_geometry
        result = self.edit_dialog.db.execute_return(sql, (wkt, ))
        self.edit_dialog.geom = result.fetchall()[0][0]
        result = self.edit_dialog.db.execute_return(
            bulk_load_select.bulk_load_outline_shape_by_id, (qgsfId, ))
        area = geom.area()
        if area < 10:
            iface.messageBar().pushMessage(
                "INFO",
                "You've edited the outline to less than 10sqm, are you sure this is correct?",
                level=Qgis.Info,
                duration=3,
            )
        result = result.fetchall()
        if len(result) == 0:
            iface.messageBar().pushMessage(
                "CANNOT SPLIT/EDIT A NEWLY ADDED FEATURE",
                "You've tried to split/edit an outline that has just been created. You must first save this new outline to the db before splitting/editing it again.",
                level=Qgis.Warning,
                duration=5,
            )
            self.edit_dialog.btn_edit_save.setDisabled(1)
            self.disable_UI_functions()
            self.edit_dialog.btn_edit_reset.setEnabled(1)
            return
        else:
            result = result[0][0]
            if self.edit_dialog.geom == result:
                if qgsfId in list(self.edit_dialog.geoms.keys()):
                    del self.edit_dialog.geoms[qgsfId]
                self.disable_UI_functions()
            else:
                self.edit_dialog.geoms[qgsfId] = self.edit_dialog.geom
                self.enable_UI_functions()
                self.populate_edit_comboboxes()
                self.select_comboboxes_value()

        self.edit_dialog.activateWindow()
        self.edit_dialog.btn_edit_save.setDefault(True)

    # @pyqtSlot(int)
    def creator_feature_added(self, qgsfId):
        # get new feature geom
        request = QgsFeatureRequest().setFilterFid(qgsfId)
        new_feature = next(self.editing_layer.getFeatures(request))
        self.new_attrs[qgsfId] = new_feature.attributes()
        if not self.new_attrs[qgsfId][5]:
            self.error_dialog = ErrorDialog()
            self.error_dialog.fill_report(
                "\n -------------------- CANNOT ADD NEW FEATURE ------"
                "-------------- \n\nYou've added a new feature, "
                "this can't be done in edit geometry, "
                "please switch to add outline.")
            self.error_dialog.show()
            self.disable_UI_functions()
            self.edit_dialog.btn_edit_reset.setEnabled(1)
            return
        new_geometry = new_feature.geometry()
        # calculate area
        area = new_geometry.area()
        if area < 10:
            iface.messageBar().pushMessage(
                "INFO",
                "You've created an outline that is less than 10sqm, are you sure this is correct?",
                level=Qgis.Info,
                duration=3,
            )

        # convert to correct format
        wkt = new_geometry.asWkt()
        sql = general_select.convert_geometry
        result = self.edit_dialog.db.execute_return(sql, (wkt, ))
        self.edit_dialog.split_geoms[qgsfId] = result.fetchall()[0][0]

    def select_comboboxes_value(self):
        """Select the correct combobox value for the geometry"""
        self.edit_dialog.cmb_capture_method.setCurrentIndex(
            self.edit_dialog.cmb_capture_method.findText(
                "Trace Orthophotography"))
Ejemplo n.º 4
0
class EditAttribute(BulkLoadChanges):
    """Class to edit Attribute in buildings_bulk_load.bulk_load_outlines Inherits BulkLoadChanges"""
    def __init__(self, edit_dialog):
        """Constructor"""
        BulkLoadChanges.__init__(self, edit_dialog)
        # set editing to edit polygon
        iface.actionSelect().trigger()
        selecttools = iface.attributesToolBar().findChildren(QToolButton)
        # selection actions
        iface.building_toolbar.addSeparator()
        for sel in selecttools:
            if sel.text() == "Select Feature(s)":
                for a in sel.actions()[0:3]:
                    iface.building_toolbar.addAction(a)
        iface.building_toolbar.show()

        self.disable_UI_functions()
        if len(iface.activeLayer().selectedFeatures()) > 0:
            if self.is_correct_selections():
                self.get_selections()
                self.enable_UI_functions()
                self.populate_edit_comboboxes()
                self.select_comboboxes_value()
            else:
                self.edit_dialog.ids = []
                self.edit_dialog.building_outline_id = None
                self.disable_UI_functions()

    # @pyqtSlot(bool)
    def edit_save_clicked(self, commit_status):
        """When bulk load frame btn_edit_save clicked"""
        self.edit_dialog.db.open_cursor()

        bulk_load_status_id, capture_method_id, capture_source_id, suburb, town, t_a = (
            self.get_comboboxes_values())

        # bulk load status
        ls_relationships = {"added": [], "matched": [], "related": []}
        if self.edit_dialog.cmb_status.currentText() == "Deleted During QA":
            # can only delete outlines if no relationship
            self.edit_dialog.description_del = (
                self.edit_dialog.le_deletion_reason.text())
            if len(self.edit_dialog.description_del) == 0:
                self.error_dialog = ErrorDialog()
                self.error_dialog.fill_report(
                    "\n -------------------- EMPTY VALUE FIELD ------"
                    '-------------- \n\n There are no "reason for deletion" entries '
                )
                self.error_dialog.show()
                self.disable_UI_functions()
                return
            ls_relationships = self.remove_compared_outlines()
            if (len(ls_relationships["matched"]) == 0
                    and len(ls_relationships["related"]) == 0):
                if len(self.edit_dialog.ids) > 0:
                    # Send signal to LIQA through edit dialog
                    self.edit_dialog.delete_outline_saved.emit(
                        self.edit_dialog.ids, self.edit_dialog.description_del)
                    for i in self.edit_dialog.ids:
                        # check current status of building
                        sql = bulk_load_select.bulk_load_status_id_by_outline_id
                        current_status = self.edit_dialog.db.execute_no_commit(
                            sql, (i, ))
                        current_status = current_status.fetchall()
                        if current_status[0][0] == 3:
                            sql = "SELECT buildings_bulk_load.delete_deleted_description(%s);"
                            self.edit_dialog.db.execute_no_commit(sql, (i, ))
                        sql = "SELECT buildings_bulk_load.deletion_description_insert(%s, %s);"
                        self.edit_dialog.db.execute_no_commit(
                            sql, (i, self.edit_dialog.description_del))
                        # remove outline from added table
                        sql = "SELECT buildings_bulk_load.added_delete_bulk_load_outlines(%s);"
                        self.edit_dialog.db.execute_no_commit(sql, (i, ))
                        sql = "SELECT buildings_bulk_load.bulk_load_outlines_update_attributes(%s, %s, %s, %s, %s, %s, %s);"
                        self.edit_dialog.db.execute_no_commit(
                            sql,
                            (
                                i,
                                bulk_load_status_id,
                                capture_method_id,
                                capture_source_id,
                                suburb,
                                town,
                                t_a,
                            ),
                        )
                    self.editing_layer.removeSelection()
        else:
            for i in self.edit_dialog.ids:
                # check current status of building
                sql = bulk_load_select.bulk_load_status_id_by_outline_id
                current_status = self.edit_dialog.db.execute_no_commit(
                    sql, (i, ))
                current_status = current_status.fetchall()
                if current_status[0][0] == 3:
                    sql = "SELECT buildings_bulk_load.delete_deleted_description(%s);"
                    self.edit_dialog.db.execute_no_commit(sql, (i, ))
                # change attributes
                sql = "SELECT buildings_bulk_load.bulk_load_outlines_update_attributes(%s, %s, %s, %s, %s, %s, %s);"
                self.edit_dialog.db.execute_no_commit(
                    sql,
                    (
                        i,
                        bulk_load_status_id,
                        capture_method_id,
                        capture_source_id,
                        suburb,
                        town,
                        t_a,
                    ),
                )
            self.editing_layer.removeSelection()
        self.disable_UI_functions()
        self.edit_dialog.completer_box()

        if commit_status:
            self.edit_dialog.db.commit_open_cursor()
            self.edit_dialog.ids = []
            self.edit_dialog.building_outline_id = None

    # @pyqtSlot()
    def edit_reset_clicked(self):
        """When bulk load frame btn_reset_save clicked"""
        self.edit_dialog.ids = []
        self.edit_dialog.building_outline_id = None
        iface.actionSelect().trigger()
        iface.activeLayer().removeSelection()
        # reset and disable comboboxes
        self.edit_dialog.circle_tool = None
        self.disable_UI_functions()

    # @pyqtSlot(list, list, bool)
    def selection_changed(self, added, removed, cleared):
        """Called when feature is selected"""
        # If no outlines are selected the function will return
        if len(self.editing_layer.selectedFeatures()) == 0:
            self.edit_dialog.ids = []
            self.edit_dialog.building_outline_id = None
            self.disable_UI_functions()
            return
        if self.is_correct_selections():
            self.get_selections()
            self.enable_UI_functions()
            self.populate_edit_comboboxes()
            self.select_comboboxes_value()
        else:
            self.edit_dialog.ids = []
            self.edit_dialog.building_outline_id = None
            self.disable_UI_functions()

    def is_correct_selections(self):
        """Check if the selections meet the requirement"""
        feats = []
        for feature in self.editing_layer.selectedFeatures():
            ls = []
            ls.append(feature.attributes()[3])
            ls.append(feature.attributes()[4])
            ls.append(feature.attributes()[5])
            ls.append(feature.attributes()[6])
            ls.append(feature.attributes()[7])
            ls.append(feature.attributes()[8])
            if ls not in feats:
                feats.append(ls)
        # if selected features have different attributes (not allowed)
        if len(feats) > 1:
            self.error_dialog = ErrorDialog()
            self.error_dialog.fill_report(
                "\n ---- MULTIPLE NON IDENTICAL FEATURES SELECTED"
                " ---- \n\n Can only edit attributes of multiple"
                "features when all existing attributes a"
                "re identical.")
            self.error_dialog.show()
            return False
        # if all selected features have the same attributes (allowed)
        elif len(feats) == 1:
            deleted = 0
            reasons = []
            for feature in self.editing_layer.selectedFeatures():
                sql = bulk_load_select.bulk_load_status_id_by_outline_id
                result = self.edit_dialog.db.execute_return(
                    sql, (feature["bulk_load_outline_id"], ))
                bl_status = result.fetchall()[0][0]
                if bl_status == 3:
                    deleted = deleted + 1
                    sql = bulk_load_select.deletion_description_by_bulk_load_id
                    result = self.edit_dialog.db.execute_return(
                        sql, (feature["bulk_load_outline_id"], ))
                    reason = result.fetchall()[0][0]
                    if reason not in reasons:
                        reasons.append(reason)
            if deleted > 0:
                if deleted == len(self.editing_layer.selectedFeatures()):
                    if self.parent_frame.btn_compare_outlines.isEnabled():
                        if len(reasons) <= 1:
                            return True
                        else:
                            self.error_dialog = ErrorDialog()
                            self.error_dialog.fill_report(
                                "\n ---- DIFFERING DELETION REASONS ---- \n\n"
                                "Cannot edit deleted features as have differing"
                                " reasons for deletion. Please edit individually.\n"
                            )
                            self.error_dialog.show()
                            return False
                    else:
                        self.error_dialog = ErrorDialog()
                        self.error_dialog.fill_report(
                            "\n ---- CANNOT EDIT DELETED FEATURE ---- \n\n"
                            "Cannot edit deleted feature after comparison has been"
                            " run, instead please add this feature manually.\n"
                            "Note: Don't forget to update the relationship too!"
                        )
                        self.error_dialog.show()
                        return False
            else:
                return True
        return False

    def get_selections(self):
        """Return the selection values"""
        self.edit_dialog.ids = [
            feat.id() for feat in self.editing_layer.selectedFeatures()
        ]
        self.edit_dialog.bulk_load_outline_id = self.edit_dialog.ids[0]
        bulk_load_feat = [
            feat for feat in self.editing_layer.selectedFeatures()
        ][0]
        bulk_load_geom = bulk_load_feat.geometry()
        # convert to correct format
        wkt = bulk_load_geom.asWkt()
        sql = general_select.convert_geometry
        result = self.edit_dialog.db.execute_return(sql, (wkt, ))
        self.edit_dialog.geom = result.fetchall()[0][0]

    def select_comboboxes_value(self):
        """Select the correct combobox value for the geometry"""
        # bulk load status
        result = self.edit_dialog.db.execute_return(
            bulk_load_select.bulk_load_status_value_by_outline_id,
            (self.edit_dialog.bulk_load_outline_id, ),
        )
        result = result.fetchall()[0][0]
        self.edit_dialog.cmb_status.setCurrentIndex(
            self.edit_dialog.cmb_status.findText(result))

        # reason for deletion
        if self.edit_dialog.cmb_status.currentText() == "Deleted During QA":
            reason = bulk_load_select.deletion_description_by_bulk_load_id
            reason = self.edit_dialog.db.execute_return(
                reason, (self.edit_dialog.bulk_load_outline_id, ))
            reason = reason.fetchall()[0][0]
            self.edit_dialog.le_deletion_reason.setText(reason)

        # capture method
        result = self.edit_dialog.db.execute_return(
            common_select.capture_method_value_by_bulk_outline_id,
            (self.edit_dialog.bulk_load_outline_id, ),
        )
        result = result.fetchall()[0][0]
        self.edit_dialog.cmb_capture_method.setCurrentIndex(
            self.edit_dialog.cmb_capture_method.findText(result))

        # capture source
        result = self.edit_dialog.db.execute_return(
            common_select.
            capture_source_group_value_external_by_bulk_outline_id,
            (self.edit_dialog.bulk_load_outline_id, ),
        )
        result = result.fetchall()[0]
        text = "- ".join(result)
        self.edit_dialog.cmb_capture_source.setCurrentIndex(
            self.edit_dialog.cmb_capture_source.findText(text))

        # suburb
        result = self.edit_dialog.db.execute_return(
            reference_select.suburb_locality_suburb_4th_by_bulk_outline_id,
            (self.edit_dialog.bulk_load_outline_id, ),
        )
        result = result.fetchall()[0][0]
        self.edit_dialog.cmb_suburb.setCurrentIndex(
            self.edit_dialog.cmb_suburb.findText(result))

        # town city
        result = self.edit_dialog.db.execute_return(
            reference_select.town_city_name_by_bulk_outline_id,
            (self.edit_dialog.bulk_load_outline_id, ),
        )
        result = result.fetchall()
        if result:
            self.edit_dialog.cmb_town.setCurrentIndex(
                self.edit_dialog.cmb_town.findText(result[0][0]))
        else:
            self.edit_dialog.cmb_town.setCurrentIndex(0)

        # territorial Authority
        result = self.edit_dialog.db.execute_return(
            reference_select.territorial_authority_name_by_bulk_outline_id,
            (self.edit_dialog.bulk_load_outline_id, ),
        )
        result = result.fetchall()[0][0]
        self.edit_dialog.cmb_ta.setCurrentIndex(
            self.edit_dialog.cmb_ta.findText(result))

    def remove_compared_outlines(self):
        """called to check can mark outline for deletion"""
        added_outlines = self.edit_dialog.db.execute_no_commit(
            bulk_load_select.added_outlines_by_dataset_id,
            (self.edit_dialog.current_dataset, ),
        )
        added_outlines = added_outlines.fetchall()
        matched_outlines = self.edit_dialog.db.execute_no_commit(
            bulk_load_select.matched_outlines_by_dataset_id,
            (self.edit_dialog.current_dataset, ),
        )
        matched_outlines = matched_outlines.fetchall()
        related_outlines = self.edit_dialog.db.execute_no_commit(
            bulk_load_select.related_outlines_by_dataset_id,
            (self.edit_dialog.current_dataset, ),
        )
        related_outlines = related_outlines.fetchall()
        if len(self.edit_dialog.ids) > 0:
            # if there is more than one feature to update
            ls_relationships = {"added": [], "matched": [], "related": []}
            for item in self.edit_dialog.ids:
                # added
                if (item, ) in added_outlines:
                    ls_relationships["added"].append(item)
                # matched
                if (item, ) in matched_outlines:
                    self.error_dialog = ErrorDialog()
                    self.error_dialog.fill_report(
                        "\n --------------- RELATIONSHIP EXISTS ---------"
                        "-------\n\nCan only mark for deletion outline if"
                        " no relationship exists")
                    self.error_dialog.show()
                    ls_relationships["matched"].append(item)
                    break
                # related
                if (item, ) in related_outlines:
                    self.error_dialog = ErrorDialog()
                    self.error_dialog.fill_report(
                        "\n ------------------- RELATIONSHIP EXISTS ---------"
                        "---------- \n\nCan only mark for deletion outline if"
                        " no relationship exists")
                    self.error_dialog.show()
                    ls_relationships["related"].append(item)
                    break
        return ls_relationships
Ejemplo n.º 5
0
class BulkLoadFrame(QFrame, FORM_CLASS):
    """Bulk Load outlines frame class"""

    closed = pyqtSignal()

    def __init__(self, dockwidget, parent=None):
        """Constructor."""

        super(BulkLoadFrame, self).__init__(parent)
        self.setupUi(self)
        # Frame fields
        self.dockwidget = dockwidget
        self.layer_registry = LayerRegistry()
        # Set up pop-up dialog
        self.check_dialog = CheckDialog()
        self.error_dialog = None
        self.edit_dialog = None
        # bulk load changes instance
        self.change_instance = None
        # layer set up
        self.historic_layer = None
        self.bulk_load_layer = None
        # database setup
        self.db = db
        db.connect()
        # selection colour
        iface.mapCanvas().setSelectionColor(QColor("Yellow"))
        # set up confirmation message box
        self.msgbox_bulk_load = self.confirmation_dialog_box("bulk load")
        self.msgbox_compare = self.confirmation_dialog_box("compare")
        self.msgbox_publish = self.confirmation_dialog_box("publish")
        self.grpb_layers.hide()

        # Find current supplied dataset
        result = self.db._execute(
            bulk_load_select.supplied_dataset_count_processed_date_is_null)
        result = result.fetchall()[0][0]
        # if there is an unprocessed dataset
        if result > 1:
            # error
            self.error_dialog = ErrorDialog()
            self.error_dialog.fill_report(
                "\n ---------------------- DATASET ERROR ---------"
                "----------------- \n\nThere are multiple not processed"
                " datasets. Please fix database tables before continuing")
            self.error_dialog.show()
            self.display_dataset_error()

        elif result == 1:
            p_result = self.db._execute(
                bulk_load_select.supplied_dataset_processed_date_is_null)
            self.current_dataset = p_result.fetchall()[0][0]
            self.lb_dataset_id.setText(str(self.current_dataset))
            self.add_outlines()
            self.display_current_bl_not_compared()
            self.grpb_layers.show()
            # Setup edit dialog
            self.edit_dialog = EditDialog(self)

        # if all datasets are processed
        else:
            result2 = self.db._execute(
                bulk_load_select.supplied_dataset_count_transfer_date_is_null)
            result2 = result2.fetchall()[0][0]

            # if there is a processed but not transferred dataset
            if result > 1:
                # error
                self.error_dialog = ErrorDialog()
                self.error_dialog.fill_report(
                    "\n ---------------------- DATASET ERROR ---------"
                    "----------------- \n\nThere are multiple not transferred"
                    " datasets. Please fix database tables before continuing")
                self.error_dialog.show()
                self.display_dataset_error()

            elif result2 == 1:
                t_result = self.db._execute(
                    bulk_load_select.supplied_dataset_transfer_date_is_null)
                self.current_dataset = t_result.fetchall()[0][0]
                self.lb_dataset_id.setText(str(self.current_dataset))
                self.add_outlines()
                self.display_not_published()
                self.grpb_layers.show()
                # Setup edit dialog
                self.edit_dialog = EditDialog(self)

            # No current dataset is being worked on
            else:
                self.current_dataset = None
                self.lb_dataset_id.setText("None")
                self.display_no_bulk_load()
                self.cmb_capture_src_grp.currentIndexChanged.connect(
                    self.cmb_capture_src_grp_changed)

        # initiate le_data_description
        self.le_data_description.setMaxLength(250)
        self.le_data_description.setPlaceholderText("Data Description")

        # set up signals and slots
        self.rad_external_id.toggled.connect(
            partial(bulk_load.enable_external_bulk, self))
        self.ml_outlines_layer.currentIndexChanged.connect(
            partial(bulk_load.populate_external_fcb, self))
        self.btn_bl_save.clicked.connect(
            partial(self.bulk_load_save_clicked, True))
        self.btn_bl_reset.clicked.connect(self.bulk_load_reset_clicked)

        self.btn_compare_outlines.clicked.connect(
            partial(self.compare_outlines_clicked, True))

        self.btn_alter_rel.clicked.connect(self.alter_relationships_clicked)
        self.btn_publish.clicked.connect(partial(self.publish_clicked, True))
        self.btn_exit.clicked.connect(self.exit_clicked)

        self.cb_bulk_load.clicked.connect(self.cb_bulk_load_clicked)
        self.cb_removed.clicked.connect(self.cb_removed_clicked)
        self.cb_added.clicked.connect(self.cb_added_clicked)

        QgsProject.instance().layerWillBeRemoved.connect(self.layers_removed)

    def confirmation_dialog_box(self, button_text):
        return QMessageBox(
            QMessageBox.Question,
            button_text.upper(),
            "Are you sure you want to %s outlines?" % button_text,
            buttons=QMessageBox.No | QMessageBox.Yes,
        )

    def confirm(self, msgbox):
        reply = msgbox.exec_()
        if reply == QMessageBox.Yes:
            return True
        return False

    def setup_toolbar(self):

        if "Add Outline" not in (
                action.text() for action in iface.building_toolbar.actions()):
            image_dir = os.path.join(__location__, "..", "icons")
            icon_path = os.path.join(image_dir, "plus.png")
            icon = QIcon()
            icon.addFile(icon_path, QSize(8, 8))
            self.add_action = QAction(icon, "Add Outline",
                                      iface.building_toolbar)
            iface.registerMainWindowAction(self.add_action, "Ctrl+1")
            self.add_action.triggered.connect(self.canvas_add_outline)
            iface.building_toolbar.addAction(self.add_action)

        if "Edit Geometry" not in (
                action.text() for action in iface.building_toolbar.actions()):
            image_dir = os.path.join(__location__, "..", "icons")
            icon_path = os.path.join(image_dir, "edit_geometry.png")
            icon = QIcon()
            icon.addFile(icon_path, QSize(8, 8))
            self.edit_geom_action = QAction(icon, "Edit Geometry",
                                            iface.building_toolbar)
            iface.registerMainWindowAction(self.edit_geom_action, "Ctrl+2")
            self.edit_geom_action.triggered.connect(self.canvas_edit_geometry)
            iface.building_toolbar.addAction(self.edit_geom_action)

        if "Edit Attributes" not in (
                action.text() for action in iface.building_toolbar.actions()):
            image_dir = os.path.join(__location__, "..", "icons")
            icon_path = os.path.join(image_dir, "edit_attributes.png")
            icon = QIcon()
            icon.addFile(icon_path, QSize(8, 8))
            self.edit_attrs_action = QAction(icon, "Edit Attributes",
                                             iface.building_toolbar)
            iface.registerMainWindowAction(self.edit_attrs_action, "Ctrl+3")
            self.edit_attrs_action.triggered.connect(
                self.canvas_edit_attribute)
            iface.building_toolbar.addAction(self.edit_attrs_action)

        iface.building_toolbar.show()

    def display_dataset_error(self):
        """UI Display when there are multiple supplied datasets."""

        self.current_dataset = None
        self.lb_dataset_id.setText("None")

        self.grpb_bulk_load.hide()
        iface.building_toolbar.hide()

        self.btn_compare_outlines.setDisabled(1)
        self.btn_alter_rel.setDisabled(1)
        self.btn_publish.setDisabled(1)

    def display_no_bulk_load(self):
        """UI Display When there is no Current dataset."""

        self.grpb_bulk_load.show()
        bulk_load.populate_bulk_comboboxes(self)
        self.ml_outlines_layer.setEnabled(1)
        self.rad_external_id.setEnabled(1)
        self.rad_external_id.setChecked(False)
        self.fcb_external_id.setDisabled(1)
        self.cmb_capture_src_grp.setEnabled(1)
        self.cmb_capture_src_grp.setCurrentIndex(0)
        self.cmb_cap_src_area.setEnabled(1)
        self.le_data_description.setEnabled(1)
        self.le_data_description.clear()
        self.cmb_capture_method.setEnabled(1)
        self.cmb_capture_method.setCurrentIndex(0)
        self.cmb_organisation.setEnabled(1)
        self.cmb_organisation.setCurrentIndex(0)
        self.btn_bl_save.show()
        self.btn_bl_reset.show()

        self.current_dataset = None
        self.lb_dataset_id.setText("None")

        self.btn_compare_outlines.setDisabled(1)
        self.btn_alter_rel.setDisabled(1)
        self.btn_publish.setDisabled(1)

        self.add_historic_outlines()

        self.l_cs_area_title.setText("")

        iface.building_toolbar.hide()

    def display_data_exists(self):
        """
            Display setup when data has been bulk loaded
            - subfunction of: display_not_published &
              display_current_bl_not_compared
        """
        bulk_load.populate_bulk_comboboxes(self)
        bulk_load.load_current_fields(self)

        self.grpb_bulk_load.show()
        self.ml_outlines_layer.setDisabled(1)
        self.rad_external_id.setDisabled(1)
        self.fcb_external_id.setDisabled(1)
        self.cmb_capture_src_grp.setDisabled(1)
        self.cmb_cap_src_area.setDisabled(1)
        self.le_data_description.setDisabled(1)
        self.cmb_capture_method.setDisabled(1)
        self.cmb_organisation.setDisabled(1)
        self.btn_bl_save.hide()
        self.btn_bl_reset.hide()

        sql = reference_select.capture_source_area_name_by_supplied_dataset
        area_id = self.db._execute(sql, (self.current_dataset, ))

        area_id = area_id.fetchall()
        if area_id is not None:
            self.l_cs_area_title.setText(area_id[0][0])
        else:
            self.l_cs_area_title.setText("")

    def display_not_published(self):
        """
            UI display when there is a dataset that hasn't been published.
        """
        self.display_data_exists()
        self.btn_compare_outlines.setDisabled(1)
        self.btn_publish.setEnabled(1)
        self.setup_toolbar()

    def display_current_bl_not_compared(self):
        """
            UI Display when there is a dataset that hasn't been compared.
        """

        self.display_data_exists()
        self.btn_compare_outlines.setEnabled(1)
        sql = reference_select.capture_source_area_name_by_supplied_dataset
        area_id = self.db._execute(sql, (self.current_dataset, ))
        if area_id is not None:
            self.area_id = area_id.fetchall()
        if len(self.area_id) > 0:
            self.area_id = self.area_id[0][0]
            self.l_cs_area_title.setText(self.area_id)
        else:
            self.area_id = None
            self.l_cs_area_title.setText("")
            self.error_dialog = ErrorDialog()
            self.error_dialog.fill_report(
                "\n ---------------------- NO CAPTURE SOURCE AREA ---------"
                "----------------- \n\nThere is no area id, please fix in database"
            )
            self.error_dialog.show()
            self.display_dataset_error()
            self.btn_compare_outlines.setDisabled(1)
            return
        self.btn_alter_rel.setDisabled(1)
        self.btn_publish.setDisabled(1)
        self.setup_toolbar()

    def add_outlines(self):
        """
            Add bulk load outlines of current dataset to canvas.
        """

        path = os.path.join(os.path.dirname(os.path.dirname(__file__)),
                            "styles/")
        # add the bulk_load_outlines to the layer registry
        self.bulk_load_layer = self.layer_registry.add_postgres_layer(
            "bulk_load_outlines",
            "bulk_load_outlines",
            "shape",
            "buildings_bulk_load",
            "",
            "supplied_dataset_id = {0}".format(self.current_dataset),
        )
        self.bulk_load_layer.loadNamedStyle(path + "building_editing.qml")
        iface.setActiveLayer(self.bulk_load_layer)

    def add_historic_outlines(self):
        path = os.path.join(os.path.dirname(os.path.dirname(__file__)),
                            "styles/")
        self.historic_layer = self.layer_registry.add_postgres_layer(
            "loaded_datasets", "bulk_load_outlines", "shape",
            "buildings_bulk_load", "", "")
        self.historic_layer.loadNamedStyle(path + "building_historic.qml")

    @pyqtSlot(int)
    def cmb_capture_src_grp_changed(self, index):
        self.cmb_cap_src_area.clear()
        id_capture_src_grp = self.ids_capture_src_grp[index]
        result = self.db._execute(
            common_select.
            capture_source_external_id_and_area_title_by_group_id,
            (id_capture_src_grp, ))
        ls = result.fetchall()
        for (external_id, area_title) in reversed(ls):
            text = external_id + "- " + area_title
            self.cmb_cap_src_area.addItem(text)

    @pyqtSlot(bool)
    def cb_bulk_load_clicked(self, checked):
        layer_tree_layer = QgsProject.instance().layerTreeRoot().findLayer(
            self.bulk_load_layer.id())
        layer_tree_model = iface.layerTreeView().model()
        categories = layer_tree_model.layerLegendNodes(layer_tree_layer)
        bulk_category = [
            ln for ln in categories if ln.data(Qt.DisplayRole) == "Bulk Loaded"
        ]
        if checked:
            bulk_category[0].setData(Qt.Checked, Qt.CheckStateRole)
        else:
            bulk_category[0].setData(Qt.Unchecked, Qt.CheckStateRole)

    @pyqtSlot(bool)
    def cb_added_clicked(self, checked):
        layer_tree_layer = QgsProject.instance().layerTreeRoot().findLayer(
            self.bulk_load_layer.id())
        layer_tree_model = iface.layerTreeView().model()
        categories = layer_tree_model.layerLegendNodes(layer_tree_layer)
        added_category = [
            ln for ln in categories
            if ln.data(Qt.DisplayRole) == "Added During QA"
        ]
        added_edit_category = [
            ln for ln in categories
            if ln.data(Qt.DisplayRole) == "Added- to be saved"
        ]
        if checked:
            added_category[0].setData(Qt.Checked, Qt.CheckStateRole)
            added_edit_category[0].setData(Qt.Checked, Qt.CheckStateRole)
        else:
            added_category[0].setData(Qt.Unchecked, Qt.CheckStateRole)
            added_edit_category[0].setData(Qt.Unchecked, Qt.CheckStateRole)

    @pyqtSlot(bool)
    def cb_removed_clicked(self, checked):
        layer_tree_layer = QgsProject.instance().layerTreeRoot().findLayer(
            self.bulk_load_layer.id())
        layer_tree_model = iface.layerTreeView().model()
        categories = layer_tree_model.layerLegendNodes(layer_tree_layer)
        removed_category = [
            ln for ln in categories
            if ln.data(Qt.DisplayRole) == "Removed During QA"
        ]
        if checked:
            removed_category[0].setData(Qt.Checked, Qt.CheckStateRole)
        else:
            removed_category[0].setData(Qt.Unchecked, Qt.CheckStateRole)

    @pyqtSlot(bool)
    def bulk_load_save_clicked(self, commit_status):
        """
            When bulk load outlines save clicked
        """
        if self.confirm(self.msgbox_bulk_load):
            QApplication.setOverrideCursor(Qt.WaitCursor)
            bulk_load.bulk_load(self, commit_status)
            # find if adding was successful
            result = self.db._execute(
                bulk_load_select.supplied_dataset_count_both_dates_are_null)
            result = result.fetchall()[0][0]
            # if bulk loading completed without errors
            if result == 1:
                QgsProject.instance().layerWillBeRemoved.disconnect(
                    self.layers_removed)
                self.layer_registry.remove_layer(self.historic_layer)
                QgsProject.instance().layerWillBeRemoved.connect(
                    self.layers_removed)
                self.cmb_capture_src_grp.currentIndexChanged.disconnect(
                    self.cmb_capture_src_grp_changed)
                self.add_outlines()
                self.display_current_bl_not_compared()
            QApplication.restoreOverrideCursor()
            self.edit_dialog = EditDialog(self)

    @pyqtSlot()
    def bulk_load_reset_clicked(self):
        """
            When bulk Load reset clicked
        """
        self.cmb_capture_method.setCurrentIndex(0)
        self.ml_outlines_layer.setCurrentIndex(0)
        self.cmb_organisation.setCurrentIndex(0)
        self.le_data_description.clear()
        self.rad_external_id.setChecked(False)

    @pyqtSlot(bool)
    def compare_outlines_clicked(self, commit_status):
        """
            When compare outlines clicked
        """
        if self.confirm(self.msgbox_compare):
            QApplication.setOverrideCursor(Qt.WaitCursor)
            self.edit_cancel_clicked()
            comparisons.compare_outlines(self, commit_status)
            self.btn_publish.setEnabled(1)
            self.btn_compare_outlines.setDisabled(1)
            self.btn_alter_rel.setEnabled(1)
            QApplication.restoreOverrideCursor()

    def canvas_add_outline(self):
        """
            When add outline radio button toggled
        """
        self.edit_dialog.add_outline()
        self.edit_dialog.show()
        self.change_instance = self.edit_dialog.get_change_instance()

        self.circle_tool = None
        self.polyline = None
        # setup circle button
        image_dir = os.path.join(__location__, "..", "icons")
        icon_path = os.path.join(image_dir, "circle.png")
        icon = QIcon()
        icon.addFile(icon_path, QSize(8, 8))
        self.circle_action = QAction(icon, "Draw Circle",
                                     iface.building_toolbar)
        iface.registerMainWindowAction(self.circle_action, "Ctrl+0")
        self.circle_action.triggered.connect(self.circle_tool_clicked)
        self.circle_action.setCheckable(True)
        iface.building_toolbar.addAction(self.circle_action)

    def circle_tool_clicked(self):
        if self.circle_action.isChecked():
            circle_tool.setup_circle(self)
        else:
            iface.actionAddFeature().trigger()

    def canvas_edit_attribute(self):
        """
            When edit outline radio button toggled
        """
        self.edit_dialog.show()
        self.edit_dialog.edit_attribute()
        self.change_instance = self.edit_dialog.get_change_instance()
        self.change_instance.populate_edit_comboboxes()

    def canvas_edit_geometry(self):
        """
            When edit geometry radio button toggled
        """
        self.edit_dialog.edit_geometry()
        self.edit_dialog.show()
        self.change_instance = self.edit_dialog.get_change_instance()

    def edit_cancel_clicked(self):
        """
            When cancel clicked
        """
        if len(QgsProject.instance().mapLayersByName(
                "bulk_load_outlines")) > 0:
            if isinstance(self.change_instance,
                          bulk_load_changes.EditAttribute):
                try:
                    self.bulk_load_layer.selectionChanged.disconnect(
                        self.change_instance.selection_changed)
                except TypeError:
                    pass
            elif isinstance(self.change_instance,
                            bulk_load_changes.EditGeometry):
                try:
                    self.bulk_load_layer.geometryChanged.disconnect(
                        self.change_instance.geometry_changed)
                except TypeError:
                    pass
                try:
                    self.bulk_load_layer.featureAdded.disconnect()
                except TypeError:
                    pass
            elif isinstance(self.change_instance,
                            bulk_load_changes.AddBulkLoad):
                try:
                    self.bulk_load_layer.featureAdded.disconnect()
                except TypeError:
                    pass
                try:
                    self.bulk_load_layer.featureDeleted.disconnect()
                except TypeError:
                    pass
                try:
                    self.bulk_load_layer.geometryChanged.disconnect()
                except TypeError:
                    pass
                if self.polyline:
                    self.polyline.reset()
                if isinstance(self.circle_tool, PointTool):
                    self.circle_tool.canvas_clicked.disconnect()
                    self.circle_tool.mouse_moved.disconnect()
                    self.circle_tool.deactivate()
                iface.actionPan().trigger()

        iface.actionCancelEdits().trigger()

        self.setup_toolbar()

        self.change_instance = None

    @pyqtSlot()
    def alter_relationships_clicked(self):
        """
            When alter relationships button clicked
            open alter relationships frame
        """

        if self.change_instance is not None:
            self.edit_dialog.close()
        self.db.close_connection()
        QgsProject.instance().layerWillBeRemoved.disconnect(
            self.layers_removed)
        self.layer_registry.remove_layer(self.bulk_load_layer)
        for action in iface.building_toolbar.actions():
            if action.objectName() not in ["mActionPan"]:
                iface.building_toolbar.removeAction(action)
        iface.building_toolbar.hide()
        dw = self.dockwidget
        dw.stk_options.removeWidget(dw.stk_options.currentWidget())
        dw.new_widget(AlterRelationships(dw, self.current_dataset))

    @pyqtSlot(bool)
    def publish_clicked(self, commit_status):
        """
            When publish button clicked
        """
        if not self.check_duplicate_ids():
            return
        if self.confirm(self.msgbox_publish):
            QApplication.setOverrideCursor(Qt.WaitCursor)
            if self.change_instance is not None:
                self.edit_dialog.close()
            self.db.open_cursor()
            sql = "SELECT buildings_bulk_load.load_building_outlines(%s);"
            self.db.execute_no_commit(sql, (self.current_dataset, ))
            if commit_status:
                self.db.commit_open_cursor()
            self.display_no_bulk_load()
            self.cmb_capture_src_grp.currentIndexChanged.connect(
                self.cmb_capture_src_grp_changed)
            self.current_dataset = None
            self.lb_dataset_id.setText("None")
            QgsProject.instance().layerWillBeRemoved.disconnect(
                self.layers_removed)
            self.layer_registry.remove_layer(self.bulk_load_layer)
            self.add_historic_outlines()
            QApplication.restoreOverrideCursor()
            self.grpb_layers.hide()
            QgsProject.instance().layerWillBeRemoved.connect(
                self.layers_removed)

    def check_duplicate_ids(self):
        """
            Check same ids in different tables (added/matched/related)
        """
        result = self.run_check()
        if not result:
            return True
        else:
            self.check_dialog.show()
            self.check_dialog.set_message("FAILED: duplicate id(s) found.")
            self.check_dialog.set_data(result)
            return False

    def run_check(self):
        """
            Run check and return the output data
        """
        result = self.db._execute(
            bulk_load_select.added_outlines_by_dataset_id,
            (self.current_dataset, ))
        added_outlines = result.fetchall()
        result = self.db._execute(
            bulk_load_select.matched_outlines_by_dataset_id,
            (self.current_dataset, ))
        matched_outlines = result.fetchall()
        result = self.db._execute(
            bulk_load_select.related_outlines_by_dataset_id,
            (self.current_dataset, ))
        related_outlines = result.fetchall()
        ids_added_matched = self.find_match_ids(added_outlines,
                                                matched_outlines)
        ids_added_related = self.find_match_ids(added_outlines,
                                                related_outlines)
        ids_matched_related = self.find_match_ids(matched_outlines,
                                                  related_outlines)
        data = self.get_error_data(ids_added_matched, ids_added_related,
                                   ids_matched_related)
        return data

    def find_match_ids(self, ids_1, ids_2):
        return list(set(ids_1) & set(ids_2))

    def get_error_data(self, ids_added_matched, ids_added_related,
                       ids_matched_related):
        """
            Return the output data
        """
        data = []
        for (feat_id, ) in ids_added_matched:
            data.append((feat_id, "Added", "Matched"))
        for (feat_id, ) in ids_added_related:
            data.append((feat_id, "Added", "Related"))
        for (feat_id, ) in ids_matched_related:
            data.append((feat_id, "Matched", "Related"))
        return data

    @pyqtSlot()
    def exit_clicked(self):
        """
            Called when bulk load frame exit button clicked.
        """
        self.close_frame()
        self.dockwidget.lst_sub_menu.clearSelection()

    def close_frame(self):
        """
            Clean up and remove the bulk load frame.
        """
        if self.change_instance is not None:
            self.edit_dialog.close()
        QgsProject.instance().layerWillBeRemoved.disconnect(
            self.layers_removed)
        iface.actionCancelEdits().trigger()
        if self.historic_layer is not None:
            self.layer_registry.remove_layer(self.historic_layer)
        if self.bulk_load_layer is not None:
            self.layer_registry.remove_layer(self.bulk_load_layer)
        from buildings.gui.menu_frame import MenuFrame

        dw = self.dockwidget
        dw.stk_options.removeWidget(dw.stk_options.currentWidget())
        dw.new_widget(MenuFrame(dw))
        for action in iface.building_toolbar.actions():
            if action.text() not in ["Pan Map"]:
                iface.building_toolbar.removeAction(action)
        iface.building_toolbar.hide()

    @pyqtSlot(str)
    def layers_removed(self, layerids):
        self.layer_registry.update_layers()
        if "bulk_load_outlines" in layerids:
            self.btn_compare_outlines.setDisabled(1)
            self.btn_alter_rel.setDisabled(1)
            self.btn_publish.setDisabled(1)
            self.cb_bulk_load.setDisabled(1)
            self.cb_added.setDisabled(1)
            self.cb_removed.setDisabled(1)
            for action in iface.building_toolbar.actions():
                if action.text() not in [
                        "Pan Map", "Add Outline", "Edit Geometry",
                        "Edit Attributes"
                ]:
                    iface.building_toolbar.removeAction(action)
                if action.text() in [
                        "Add Outline", "Edit Geometry", "Edit Attributes"
                ]:
                    action.setDisabled(True)
                else:
                    action.setEnabled(True)
            iface.messageBar().pushMessage(
                "ERROR",
                "Required layer Removed! Please reload the buildings plugin or the current frame before continuing",
                level=Qgis.Critical,
                duration=5,
            )
            return

        if "loaded_datasets" in layerids:
            iface.messageBar().pushMessage(
                "ERROR",
                "Required layer Removed! Please reload the buildings plugin or the current frame before continuing",
                level=Qgis.Critical,
                duration=5,
            )
            # disable bulk loading buttons
            self.btn_bl_save.setDisabled(1)
            self.btn_bl_reset.setDisabled(1)
            return

    def reload_bulk_load_layer(self):
        """To ensure QGIS has most up to date ID for the newly split feature see #349"""
        self.cb_added_clicked(False)
        self.cb_added_clicked(True)
Ejemplo n.º 6
0
class UpdateReferenceData(QFrame, FORM_CLASS):
    def __init__(self, dockwidget, parent=None):
        """Constructor."""
        super(UpdateReferenceData, self).__init__(parent)
        self.setupUi(self)
        self.dockwidget = dockwidget
        self.db = db
        self.db.connect()
        self.error_dialog = None
        self.message = ""
        self.msgbox = self.message_box()
        self.btn_view_key.setIcon(
            QIcon(
                os.path.join(__location__, "..", "icons",
                             "view_password.png")))

        # disable all check boxes if a curret dataset exists
        sql = bulk_load_select.supplied_dataset_latest_id_and_dates
        result = self.db.execute_return(sql)
        if result is None:
            self.enable_checkboxes()
            self.le_key.setDisabled(1)
            self.btn_view_key.setDisabled(1)
        else:
            result = result.fetchone()
            process = result[1]
            transfer = result[2]
            if process is not None and transfer is not None:
                self.enable_checkboxes()
                self.le_key.setDisabled(1)
                self.btn_view_key.setDisabled(1)
            else:
                self.disable_checkboxes()

        # set up signals and slots
        self.btn_view_key.pressed.connect(self.view_key)
        self.btn_view_key.released.connect(self.hide_key)
        self.le_key.editingFinished.connect(self.hide_key)
        self.grbx_topo.toggled.connect(self.check_all_topo)
        self.grbx_admin.toggled.connect(self.check_all_admin)
        self.btn_exit.clicked.connect(self.exit_clicked)
        self.btn_update.clicked.connect(
            partial(self.update_clicked, commit_status=True))
        for box in self.grbx_topo.findChildren(QCheckBox):
            box.clicked.connect(self.chbx_clicked)

    def close_cursor(self):
        self.db.close_cursor()

    def connect(self):
        self.db.connect()

    def enable_checkboxes(self):
        """Enable frame"""
        self.grbx_topo.setEnabled(1)
        self.grbx_admin.setEnabled(1)
        self.chbx_canals.setEnabled(1)
        self.chbx_coastline_and_islands.setEnabled(1)
        self.chbx_lagoons.setEnabled(1)
        self.chbx_lakes.setEnabled(1)
        self.chbx_ponds.setEnabled(1)
        self.chbx_rivers.setEnabled(1)
        self.chbx_swamps.setEnabled(1)
        self.chbx_huts.setEnabled(1)
        self.chbx_shelters.setEnabled(1)
        self.chbx_bivouacs.setEnabled(1)
        self.chbx_protected_areas.setEnabled(1)
        self.chbx_suburbs.setEnabled(1)
        self.chbx_town.setEnabled(1)
        self.chbx_ta.setEnabled(1)
        self.btn_update.setEnabled(1)
        # clear message
        self.lb_message.setText("")

    def disable_checkboxes(self):
        """Disable frame (when outlines dataset in progress)"""
        self.le_key.setDisabled(1)
        self.grbx_topo.setDisabled(1)
        self.grbx_admin.setDisabled(1)
        self.chbx_canals.setDisabled(1)
        self.chbx_coastline_and_islands.setDisabled(1)
        self.chbx_lagoons.setDisabled(1)
        self.chbx_lakes.setDisabled(1)
        self.chbx_ponds.setDisabled(1)
        self.chbx_rivers.setDisabled(1)
        self.chbx_swamps.setDisabled(1)
        self.chbx_huts.setDisabled(1)
        self.chbx_shelters.setDisabled(1)
        self.chbx_bivouacs.setDisabled(1)
        self.chbx_protected_areas.setDisabled(1)
        self.chbx_suburbs.setDisabled(1)
        self.chbx_town.setDisabled(1)
        self.chbx_ta.setDisabled(1)
        self.btn_view_key.setDisabled(1)
        self.btn_update.setDisabled(1)
        # add message
        self.lb_message.setText(
            "\nNOTE: You can't update reference data with\n             a dataset in progress \n"
        )

    @pyqtSlot()
    def view_key(self):
        """Called when view key button pressed"""
        self.le_key.setEchoMode(QLineEdit.Normal)

    @pyqtSlot()
    def hide_key(self):
        """Called when view key button released/editing of text finished"""
        self.le_key.setEchoMode(QLineEdit.Password)

    @pyqtSlot()
    def update_clicked(self, commit_status=True):
        """Called when update btn clicked"""
        # set cursor to busy
        QApplication.setOverrideCursor(Qt.WaitCursor)
        # setup
        self.message = ""
        self.api_key = self.le_key.text()
        self.updates = []
        # canals
        if self.chbx_canals.isChecked():
            self.topo_layer_processing("canal_polygons")
        # lagoon
        if self.chbx_lagoons.isChecked():
            self.topo_layer_processing("lagoon_polygons")
        # lake
        if self.chbx_lakes.isChecked():
            self.topo_layer_processing("lake_polygons")
        # pond
        if self.chbx_ponds.isChecked():
            self.topo_layer_processing("pond_polygons")
        # rivers
        if self.chbx_rivers.isChecked():
            self.topo_layer_processing("river_polygons")
        # swamp
        if self.chbx_swamps.isChecked():
            self.topo_layer_processing("swamp_polygons")
        # huts
        if self.chbx_huts.isChecked():
            self.topo_layer_processing("hut_points")
        # shelters
        if self.chbx_shelters.isChecked():
            self.topo_layer_processing("shelter_points")
        # bivouacs
        if self.chbx_bivouacs.isChecked():
            self.topo_layer_processing("bivouac_points")
        # protected areas
        if self.chbx_protected_areas.isChecked():
            self.topo_layer_processing("protected_areas_polygons")
        # coastlines and islands (placeholder)
        if self.chbx_coastline_and_islands.isChecked():
            self.message += "The coastlines and islands table must be updated manually"
        if self.db._open_cursor is None:
            self.db.open_cursor()
        # suburb localities
        if self.chbx_suburbs.isChecked():
            # update building_outlines suburb values (changed, deleted & added)
            # delete remove suburbs and update modified suburbs
            db.execute_no_commit(
                "SELECT buildings_reference.building_outlines_update_changed_and_deleted_suburb();"
            )
            # add new suburbs and update building outlines
            db.execute_no_commit(
                "SELECT buildings_reference.building_outlines_update_added_suburb();"
            )
            # update messages and log
            self.update_message("updated", "suburb_locality")
            self.updates.append("suburb_locality")
        # town_city
        if self.chbx_town.isChecked():
            town_list = []
            # delete existing areas where the external id is no longer in the town_city table
            result = db.execute_no_commit(
                "SELECT buildings_reference.town_city_delete_removed_areas();")
            if result is not None:
                town_list.extend(result.fetchone()[0])
            # modify all existing areas to check they are up to date
            result = db.execute_no_commit(
                "SELECT buildings_reference.town_city_insert_new_areas();")
            if result is not None:
                town_list.extend(result.fetchone()[0])
            # insert into table ids in nz_localities that are not in town_city
            result = db.execute_no_commit(
                "SELECT buildings_reference.town_city_update_areas();")
            if result is not None:
                town_list.extend(result.fetchone()[0])
            # update bulk_load_outlines town/city values
            db.execute_no_commit(
                "SELECT buildings_bulk_load.bulk_load_outlines_update_all_town_cities(%s);",
                (town_list, ),
            )
            # update building outlines town/city values
            db.execute_no_commit(
                "SELECT buildings.building_outlines_update_town_city(%s);",
                (town_list, ))
            # update messages and log
            self.update_message("updated", "town_city")
            self.updates.append("town_city")
        # territorial authority and grid
        if self.chbx_ta.isChecked():
            ta_list = []
            # delete removed TA areas
            result = db.execute_no_commit(
                "SELECT buildings_reference.territorial_auth_delete_areas();")
            if result is not None:
                ta_list.extend(result.fetchone()[0])
            # Insert TA areas
            result = db.execute_no_commit(
                "SELECT buildings_reference.territorial_auth_insert_areas();")
            if result is not None:
                ta_list.extend(result.fetchone()[0])
            # Update new TA areas
            result = db.execute_no_commit(
                "SELECT buildings_reference.territorial_auth_update_areas();")
            if result is not None:
                ta_list.extend(result.fetchone()[0])
            # update bulk_load_outlines territorial authority values
            db.execute_no_commit(
                "SELECT buildings_bulk_load.bulk_load_outlines_update_all_territorial_authorities(%s);",
                (ta_list, ),
            )
            # update building outlines territorial authority values
            db.execute_no_commit(
                "SELECT buildings.building_outlines_update_territorial_authority(%s);",
                (ta_list, ),
            )
            # update message and log
            self.update_message("updated", "territorial_authority")
            self.updates.append("territorial_authority")
            # refresh grid
            db.execute_no_commit(reference_select.refresh_ta_grid_view)
            self.update_message("updated", "territorial_authority_grid")
            self.updates.append("territorial_authority_grid")

        # create log for this update
        if len(self.updates) > 0:
            sql = "SELECT buildings_reference.reference_update_log_insert_log(%s);"
            self.db.execute_no_commit(sql, (self.updates, ))
        # restore cursor
        QApplication.restoreOverrideCursor()
        # final message box
        if self.message == "":
            self.message = "No layers were updated."
        self.msgbox.setText(self.message)
        self.msgbox.exec_()
        if commit_status:
            self.db.commit_open_cursor()

    @pyqtSlot()
    def exit_clicked(self):
        """
        Called when new entry exit button clicked.
        """
        self.close_frame()
        self.dockwidget.lst_sub_menu.clearSelection()

    def close_frame(self):
        """
        Clean up and remove the new entry frame.
        """
        self.db.close_connection()
        from buildings.gui.menu_frame import MenuFrame

        dw = self.dockwidget
        dw.stk_options.removeWidget(dw.stk_options.currentWidget())
        dw.new_widget(MenuFrame(dw))

    @pyqtSlot()
    def check_all_topo(self):
        """ Called when combobox to check all topo layers is toggled"""
        if self.grbx_topo.isChecked():
            for box in self.grbx_topo.findChildren(QCheckBox):
                box.setChecked(True)
                box.setEnabled(1)
                self.chbx_clicked()
        else:
            for box in self.grbx_topo.findChildren(QCheckBox):
                box.setChecked(False)
                box.setEnabled(1)
                self.chbx_clicked()

    @pyqtSlot()
    def chbx_clicked(self):
        """Called when topo checkboxes are checked"""
        if not self.loop_topo_boxes():
            self.le_key.setDisabled(1)
            self.btn_view_key.setDisabled(1)

    def loop_topo_boxes(self):
        """loops through topo check boxes returns true if one is checked and enables api key features"""
        for box in self.grbx_topo.findChildren(QCheckBox):
            if box.isChecked():
                self.le_key.setEnabled(1)
                self.btn_view_key.setEnabled(1)
                return True
        return False

    @pyqtSlot()
    def check_all_admin(self):
        """ Called when combobox to check all admin layers is toggled"""
        if self.grbx_admin.isChecked():
            for box in self.grbx_admin.findChildren(QCheckBox):
                box.setChecked(True)
                box.setEnabled(1)
        else:
            for box in self.grbx_admin.findChildren(QCheckBox):
                box.setChecked(False)
                box.setEnabled(1)

    def message_box(self):
        return QMessageBox(QMessageBox.Information,
                           "Note",
                           self.message,
                           buttons=QMessageBox.Ok)

    def request_error(self):
        """Called when failure to request a changeset"""
        self.error_dialog = ErrorDialog()
        self.error_dialog.fill_report(
            "\n ---------------------- REQUEST ERROR ---------"
            "----------------- \n\nSomething appears to have gone"
            " wrong with requesting the changeset, first please"
            " check you entered the correct api key if this is correct"
            " then please inform a developer.")
        self.error_dialog.show()
        QApplication.restoreOverrideCursor()

    def topo_layer_processing(self, layer):
        """Processes to run for all topo layers"""
        if not self.check_api_key():
            return
        status = topo50.update_topo50(self.api_key, layer)
        self.update_message(status, "{}_polygons".format(layer))
        if status != "error":
            self.updates.append(layer)

    def check_api_key(self):
        # check for API key
        if self.api_key == "":
            self.error_dialog = ErrorDialog()
            self.error_dialog.fill_report(
                "\n------------- NO API KEY -------------"
                "\n\nPlease enter a koordinates api key to"
                " update the reference data.")
            self.error_dialog.show()
            QApplication.restoreOverrideCursor()
            return False
        return True

    def update_message(self, status, name):
        """add to message for display at end of processing"""
        if status == "current":
            self.message += "The {} table was up to date\n".format(name)
        if status == "updated":
            self.message += "The {} table has been updated\n".format(name)
        if status == "error":
            self.message += "The request errored on the {} table\n".format(
                name)
            self.request_error()
Ejemplo n.º 7
0
class NewEntry(QFrame, FORM_CLASS):

    value = ""
    new_type = ""

    def __init__(self, dockwidget, parent=None):
        """Constructor."""
        super(NewEntry, self).__init__(parent)
        self.setupUi(self)
        self.dockwidget = dockwidget
        self.db = db
        self.db.connect()

        # set up signals and slots
        self.organisation_id = None
        self.lifecycle_stage_id = None
        self.capture_method_id = None
        self.capture_source_group_id = None
        self.btn_ok.clicked.connect(
            partial(self.save_clicked, commit_status=True))
        self.btn_exit.clicked.connect(self.exit_clicked)
        self.le_description.setDisabled(1)
        self.cmb_new_type_selection.currentIndexChanged.connect(
            self.set_new_type)

    def close_cursor(self):
        """close db cursor"""
        db.close_cursor()

    def connect(self):
        """Connect to db"""
        db.connect()

    def get_comments(self):
        """
        Get comments from comment box, return default if empty
        """
        if self.le_new_entry.text() == "":
            self.error_dialog = ErrorDialog()
            self.error_dialog.fill_report(
                "\n -------------------- EMPTY VALUE FIELD ------"
                "-------------- \n\n Null values not allowed")
            self.error_dialog.show()
            return
        if len(self.le_new_entry.text()) >= 40:
            self.error_dialog = ErrorDialog()
            self.error_dialog.fill_report(
                "\n -------------------- VALUE TOO LONG ---------"
                "----------- \n\n Enter less than 40 characters")
            self.error_dialog.show()
            return
        return self.le_new_entry.text()

    def get_description(self):
        """
        Returns description input
        This is only required if the type to add is
        capture source group
        """
        if self.new_type != "Capture Source Group":
            return
        else:
            if self.le_description.text() == "":
                self.error_dialog = ErrorDialog()
                self.error_dialog.fill_report(
                    "\n -------------------- EMPTY DESCRIPTION FIELD "
                    "-------------------- \n\n Null values not allowed")
                self.error_dialog.show()
                return
            if len(self.le_description.text()) >= 40:
                self.error_dialog = ErrorDialog()
                self.error_dialog.fill_report(
                    "\n -------------------- DESCRIPTION TOO LONG ---"
                    "----------------- \n\n Enter less than 40 characters")
                self.error_dialog.show()
                return
            return self.le_description.text()

    def get_combobox_value(self):
        """
        Get the type to add from the combo box
        """
        return self.cmb_new_type_selection.currentText()

    @pyqtSlot()
    def set_new_type(self):
        """
        Called when type to add combobox index is chaged
        """
        self.new_type = self.cmb_new_type_selection.currentText()
        if self.new_type == "Capture Source Group":
            self.le_description.setEnabled(1)
        else:
            self.le_description.setDisabled(1)

    @pyqtSlot(bool)
    def save_clicked(self, commit_status):
        """When save button is clicked"""
        self.value = self.get_comments()
        # get type
        self.new_type = self.get_combobox_value()
        self.status = False
        # call insert depending on type
        if self.value is not None:
            if self.new_type == "Organisation":
                self.status = self.new_organisation(self.value, commit_status)

            elif self.new_type == "Lifecycle Stage":
                self.status = self.new_lifecycle_stage(self.value,
                                                       commit_status)

            elif self.new_type == "Capture Method":
                self.status = self.new_capture_method(self.value,
                                                      commit_status)

            elif self.new_type == "Capture Source Group":
                self.description = self.get_description()
                if self.description is not None:
                    self.status = self.new_capture_source_group(
                        self.value, self.description, commit_status)
        if self.status:
            iface.messageBar().pushMessage("SUCCESS",
                                           "You've added a new {}!".format(
                                               self.new_type),
                                           level=Qgis.Success,
                                           duration=3)

    @pyqtSlot()
    def exit_clicked(self):
        """
        Called when new entry exit button clicked.
        """
        self.close_frame()
        self.dockwidget.lst_sub_menu.clearSelection()

    def close_frame(self):
        """
        Clean up and remove the new entry frame.
        """
        self.db.close_connection()
        from buildings.gui.menu_frame import MenuFrame

        dw = self.dockwidget
        dw.stk_options.removeWidget(dw.stk_options.currentWidget())
        dw.new_widget(MenuFrame(dw))

    def new_organisation(self, organisation, commit_status):
        """
            update the organisation table.
            value output = organisation auto generate id
        """
        # check if organisation in buildings_bulk_load.organisation table
        result = self.db.execute_return(bulk_load_select.organisation_by_value,
                                        (organisation, ))
        ls = result.fetchall()
        # if it is in the table return dialog box and exit
        if len(ls) > 0:
            self.error_dialog = ErrorDialog()
            self.error_dialog.fill_report(" ")
            self.error_dialog.fill_report(
                "\n -------------------- ORGANISATION EXISTS ----"
                "---------------- \n\n Value entered exists in table")
            self.error_dialog.show()
            return False
        # if it isn't in the table add to table
        elif len(ls) == 0:
            # enter but don't commit
            self.db.open_cursor()
            sql = "SELECT buildings_bulk_load.organisation_insert(%s);"
            result = self.db.execute_no_commit(sql, (organisation, ))
            self.organisation_id = result.fetchall()[0][0]
            if commit_status:
                self.db.commit_open_cursor()
            self.le_new_entry.clear()
            return True

    def new_lifecycle_stage(self, lifecycle_stage, commit_status):
        """
        update the lifecycle stage table
        value = lifecycle stage auto generate id
        """
        # check if lifecycle stage in buildings.lifecycle_stage table
        result = self.db.execute_return(
            buildings_select.lifecycle_stage_by_value, (lifecycle_stage, ))
        ls = result.fetchall()
        # if it is in the table return dialog box and exit
        if len(ls) > 0:
            self.error_dialog = ErrorDialog()
            self.error_dialog.fill_report(" ")
            self.error_dialog.fill_report(
                "\n -------------------- LIFECYCLE STAGE EXISTS -"
                "------------------- \n\n Value entered exists in table")
            self.error_dialog.show()
            return False
        # if it isn't in the table add to table
        elif len(ls) == 0:
            # enter but don't commit
            self.db.open_cursor()
            sql = "SELECT buildings.lifecycle_stage_insert(%s);"
            result = self.db.execute_no_commit(sql, (lifecycle_stage, ))
            self.lifecycle_stage_id = result.fetchall()[0][0]
            if commit_status:
                self.db.commit_open_cursor()
            self.le_new_entry.clear()
            return True

    def new_capture_method(self, capture_method, commit_status):
        """
        update the capture method table
        value = capture method autogenerate id
        """

        # check if capture method in buildings_common.capture_method table
        result = self.db.execute_return(common_select.capture_method_by_value,
                                        (capture_method, ))
        ls = result.fetchall()
        # if it is in the table return dialog box and exit
        if len(ls) > 0:
            self.error_dialog = ErrorDialog()
            self.error_dialog.fill_report(" ")
            self.error_dialog.fill_report(
                "\n -------------------- CAPTURE METHOD EXISTS --"
                "------------------ \n\n Value entered exists in table")
            self.error_dialog.show()
            return False
        # if it isn't in the table add to table
        elif len(ls) == 0:
            # enter but don't commit
            self.db.open_cursor()
            sql = "SELECT buildings_common.capture_method_insert(%s);"
            result = self.db.execute_no_commit(sql, (capture_method, ))
            self.capture_method_id = result.fetchall()[0][0]
            if commit_status:
                self.db.commit_open_cursor()
            self.le_new_entry.clear()
            return True

    def new_capture_source_group(self, capture_source_group, description,
                                 commit_status):
        """
        update the capture source group table
        value = capture source group autogenerate id
        """
        # Check if capture source group in buildings
        # _common.capture_source_group table
        result = self.db.execute_return(
            common_select.capture_source_group_by_value_and_description,
            (capture_source_group, description))
        ls = result.fetchall()
        # if it is in the table return dialog box and exit
        if len(ls) > 0:
            self.error_dialog = ErrorDialog()
            self.error_dialog.fill_report(" ")
            self.error_dialog.fill_report(
                "\n ---------------- CAPTURE SOURCE GROUP "
                "---------------- \n\n Value entered exists in table")
            self.error_dialog.show()
            return False
        elif len(ls) == 0:
            # enter but don't commit
            self.db.open_cursor()
            sql = "SELECT buildings_common.capture_source_group_insert(%s, %s);"
            result = self.db.execute_no_commit(
                sql, (capture_source_group, description))
            self.capture_source_group_id = result.fetchall()[0][0]
            if commit_status:
                self.db.commit_open_cursor()
            self.le_new_entry.clear()
            self.le_description.clear()
            return True