class AttributeEditorSample(QgsMapTool):
    def start(self):
        self.layer = self.iface.activeLayer()

        features = self.layer.selectedFeatures()
        if len(features) == 0:
            return

        self.layer.startEditing()  # レイヤを編集状態にする

        # 選択しているフューチャーの属性フォーム表示
        self.attdlg = self.iface.getFeatureForm(self.layer, features[0])
        self.attdlg.setMode(QgsAttributeEditorContext.SingleEditMode)
        self.attdlg.finished.connect(self.commitEdit)
        self.attdlg.show()

    def commitEdit(self, result):
        if result == 1:
            self.layer.commitChanges()
        else:
            self.layer.rollBack()
        self.attdlg.finished.disconnect(self.commitEdit)

    def finish(self):
        self.canvas.mapToolSet.disconnect(self.unsetTool)

    def __init__(self, iface):
        self.plugin_name = '属性編集ダイアログサンプル'  # プラグイン名
        self.menu_pos = 'サンプル'  # プラグインの登録場所
        self.toolbar = True  # Trueならツールバーにアイコンを表示する
        self.checkable = False  # Trueならプラグイン実行中はアイコンが凹んだままになる

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

        QgsMapTool.__init__(self, self.canvas)

    # このプラグイン実行中に他のアイコンが押された場合、アイコンを元の状態に戻す
    def unsetTool(self, tool):
        if not isinstance(tool, AttributeEditorSample):
            self.finish()
            self.action.setChecked(False)

    def initGui(self):
        icon = QIcon(os.path.dirname(__file__) + '/icon.png')
        self.action = QAction(icon, self.plugin_name, self.iface.mainWindow())
        self.action.triggered.connect(
            self.execSample)  # アイコンを押下した時に実行されるメソッドを登録
        self.action.setCheckable(
            self.checkable)  # Trueだとアイコンを押下したら次に押下するまで凹んだままになる
        if self.toolbar:
            self.iface.addToolBarIcon(self.action)  # ツールバーにこのツールのアイコンを表示する
        self.iface.addPluginToMenu(self.menu_pos, self.action)

    # このプラグインを無効にしたときに呼ばれる
    def unload(self):
        self.iface.removePluginMenu(self.menu_pos, self.action)
        self.iface.removeToolBarIcon(self.action)

    # このツールのアイコンを押下したときに呼ばれる
    def execSample(self):
        if self.checkable:
            if self.action.isChecked():  # 凹状態になった
                self.previousMapTool = self.canvas.mapTool()  # 現在のマップツールを退避
                self.start()
            else:  # 凸状態になった
                self.finish()
                self.canvas.setMapTool(self.previousMapTool)  # このツール実行前に戻す
        else:
            self.start()
Beispiel #2
0
class ProductionFrame(QFrame, FORM_CLASS):
    def __init__(self, dockwidget, parent=None):
        """Constructor."""
        super(ProductionFrame, self).__init__(parent)
        self.setupUi(self)
        self.dockwidget = dockwidget
        self.layer_registry = LayerRegistry()
        self.db = db
        self.db.connect()
        self.building_layer = QgsVectorLayer()
        self.add_outlines()
        # Set up edit dialog
        self.edit_dialog = EditDialog(self)
        self.change_instance = None

        self.cb_production.setChecked(True)

        # set up signals and slots
        self.btn_exit.clicked.connect(self.exit_clicked)
        self.cb_production.clicked.connect(self.cb_production_clicked)
        QgsProject.instance().layerWillBeRemoved.connect(self.layers_removed)

        self.setup_toolbar()

    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 add_outlines(self):
        """
            Add building outlines to canvas
        """
        path = os.path.join(os.path.dirname(os.path.dirname(__file__)),
                            "styles/")
        self.layer_registry.remove_layer(self.building_layer)
        self.building_historic = self.layer_registry.add_postgres_layer(
            "historic_outlines", "building_outlines", "shape", "buildings", "",
            "end_lifespan is not NULL")
        self.building_historic.loadNamedStyle(path + "building_historic.qml")
        self.building_layer = None
        self.building_layer = self.layer_registry.add_postgres_layer(
            "building_outlines", "building_outlines", "shape", "buildings", "",
            "end_lifespan is NULL")
        self.building_layer.loadNamedStyle(path + "building_blue.qml")
        iface.setActiveLayer(self.building_layer)

    @pyqtSlot(bool)
    def cb_production_clicked(self, checked):
        group = QgsProject.instance().layerTreeRoot().findGroup(
            "Building Tool Layers")
        if checked:
            group.setItemVisibilityCheckedRecursive(True)
        else:
            group.setItemVisibilityCheckedRecursive(False)

    def canvas_add_outline(self):
        """
            When add outline radio button toggled
        """
        self.edit_dialog.show()
        self.edit_dialog.add_outline()
        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()

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

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

    def close_frame(self):
        """
        Clean up and remove the edit production frame.
        """
        if self.change_instance is not None:
            self.edit_dialog.close()
        iface.actionCancelEdits().trigger()
        QgsProject.instance().layerWillBeRemoved.disconnect(
            self.layers_removed)
        self.layer_registry.remove_layer(self.building_layer)
        self.layer_registry.remove_layer(self.building_historic)
        # reset toolbar
        for action in iface.building_toolbar.actions():
            if action.objectName() not in ["mActionPan"]:
                iface.building_toolbar.removeAction(action)
        iface.building_toolbar.hide()

        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 edit_cancel_clicked(self):
        if len(QgsProject.instance().mapLayersByName("building_outlines")) > 0:
            if isinstance(self.change_instance,
                          production_changes.EditAttribute):
                try:
                    self.building_layer.selectionChanged.disconnect(
                        self.change_instance.selection_changed)
                except TypeError:
                    pass
            elif isinstance(self.change_instance,
                            production_changes.EditGeometry):
                try:
                    self.building_layer.geometryChanged.disconnect()
                except TypeError:
                    pass
            elif isinstance(self.change_instance,
                            production_changes.AddProduction):
                try:
                    self.building_layer.featureAdded.disconnect()
                except TypeError:
                    pass
                try:
                    self.building_layer.featureDeleted.disconnect()
                except TypeError:
                    pass
                try:
                    self.building_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(str)
    def layers_removed(self, layerids):
        self.layer_registry.update_layers()
        for layer in ["building_outlines", "historic_outlines"]:
            if layer in layerids:
                self.cb_production.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
Beispiel #3
0
class ProcessingPlugin:
    def __init__(self, iface):
        self.iface = iface
        self.options_factory = ProcessingOptionsFactory()
        self.options_factory.setTitle(self.tr('Processing'))
        iface.registerOptionsWidgetFactory(self.options_factory)
        self.drop_handler = ProcessingDropHandler()
        iface.registerCustomDropHandler(self.drop_handler)
        self.item_provider = ProcessingDataItemProvider()
        QgsApplication.dataItemProviderRegistry().addProvider(
            self.item_provider)
        self.locator_filter = AlgorithmLocatorFilter()
        iface.registerLocatorFilter(self.locator_filter)
        # Invalidate the locator filter for in-place when active layer changes
        iface.currentLayerChanged.connect(
            lambda _: self.iface.invalidateLocatorResults())
        self.edit_features_locator_filter = InPlaceAlgorithmLocatorFilter()
        iface.registerLocatorFilter(self.edit_features_locator_filter)
        Processing.initialize()

    def initGui(self):
        self.toolbox = ProcessingToolbox()
        self.iface.addDockWidget(Qt.RightDockWidgetArea, self.toolbox)
        self.toolbox.hide()
        self.toolbox.visibilityChanged.connect(self.toolboxVisibilityChanged)

        self.resultsDock = ResultsDock()
        self.iface.addDockWidget(Qt.RightDockWidgetArea, self.resultsDock)
        self.resultsDock.hide()

        self.menu = QMenu(self.iface.mainWindow().menuBar())
        self.menu.setObjectName('processing')
        self.menu.setTitle(self.tr('Pro&cessing'))

        self.toolboxAction = QAction(self.tr('&Toolbox'),
                                     self.iface.mainWindow())
        self.toolboxAction.setCheckable(True)
        self.toolboxAction.setObjectName('toolboxAction')
        self.toolboxAction.setIcon(
            QgsApplication.getThemeIcon("/processingAlgorithm.svg"))
        self.iface.registerMainWindowAction(
            self.toolboxAction,
            QKeySequence('Ctrl+Alt+T').toString(QKeySequence.NativeText))
        self.toolboxAction.toggled.connect(self.openToolbox)
        self.iface.attributesToolBar().insertAction(
            self.iface.actionOpenStatisticalSummary(), self.toolboxAction)
        self.menu.addAction(self.toolboxAction)

        self.modelerAction = QAction(
            QgsApplication.getThemeIcon("/processingModel.svg"),
            QCoreApplication.translate('ProcessingPlugin',
                                       'Graphical &Modeler…'),
            self.iface.mainWindow())
        self.modelerAction.setObjectName('modelerAction')
        self.modelerAction.triggered.connect(self.openModeler)
        self.iface.registerMainWindowAction(
            self.modelerAction,
            QKeySequence('Ctrl+Alt+M').toString(QKeySequence.NativeText))
        self.menu.addAction(self.modelerAction)

        self.historyAction = QAction(
            QgsApplication.getThemeIcon("/mIconHistory.svg"),
            QCoreApplication.translate('ProcessingPlugin', '&History…'),
            self.iface.mainWindow())
        self.historyAction.setObjectName('historyAction')
        self.historyAction.triggered.connect(self.openHistory)
        self.iface.registerMainWindowAction(
            self.historyAction,
            QKeySequence('Ctrl+Alt+H').toString(QKeySequence.NativeText))
        self.menu.addAction(self.historyAction)
        self.toolbox.processingToolbar.addAction(self.historyAction)

        self.resultsAction = QAction(
            QgsApplication.getThemeIcon("/processingResult.svg"),
            self.tr('&Results Viewer'), self.iface.mainWindow())
        self.resultsAction.setCheckable(True)
        self.iface.registerMainWindowAction(
            self.resultsAction,
            QKeySequence('Ctrl+Alt+R').toString(QKeySequence.NativeText))

        self.menu.addAction(self.resultsAction)
        self.toolbox.processingToolbar.addAction(self.resultsAction)
        self.resultsDock.visibilityChanged.connect(
            self.resultsAction.setChecked)
        self.resultsAction.toggled.connect(self.resultsDock.setUserVisible)

        self.toolbox.processingToolbar.addSeparator()

        self.editInPlaceAction = QAction(
            QgsApplication.getThemeIcon("/mActionProcessSelected.svg"),
            self.tr('Edit Features In-Place'), self.iface.mainWindow())
        self.editInPlaceAction.setObjectName('editInPlaceFeatures')
        self.editInPlaceAction.setCheckable(True)
        self.editInPlaceAction.toggled.connect(self.editSelected)
        self.toolbox.processingToolbar.addAction(self.editInPlaceAction)

        self.toolbox.processingToolbar.addSeparator()

        self.optionsAction = QAction(
            QgsApplication.getThemeIcon("/mActionOptions.svg"),
            self.tr('Options'), self.iface.mainWindow())
        self.optionsAction.setObjectName('optionsAction')
        self.optionsAction.triggered.connect(self.openProcessingOptions)
        self.toolbox.processingToolbar.addAction(self.optionsAction)

        menuBar = self.iface.mainWindow().menuBar()
        menuBar.insertMenu(self.iface.firstRightStandardMenu().menuAction(),
                           self.menu)

        self.menu.addSeparator()

        initializeMenus()
        createMenus()

        # In-place editing button state sync
        self.iface.currentLayerChanged.connect(self.sync_in_place_button_state)
        self.iface.mapCanvas().selectionChanged.connect(
            self.sync_in_place_button_state)
        self.iface.actionToggleEditing().triggered.connect(
            partial(self.sync_in_place_button_state, None))
        self.sync_in_place_button_state()

    def sync_in_place_button_state(self, layer=None):
        """Synchronise the button state with layer state"""

        if layer is None:
            layer = self.iface.activeLayer()

        old_enabled_state = self.editInPlaceAction.isEnabled()

        new_enabled_state = layer is not None and layer.type(
        ) == QgsMapLayer.VectorLayer
        self.editInPlaceAction.setEnabled(new_enabled_state)

        if new_enabled_state != old_enabled_state:
            self.toolbox.set_in_place_edit_mode(
                new_enabled_state and self.editInPlaceAction.isChecked())

    def openProcessingOptions(self):
        self.iface.showOptionsDialog(self.iface.mainWindow(),
                                     currentPage='processingOptions')

    def unload(self):
        self.toolbox.setVisible(False)
        self.iface.removeDockWidget(self.toolbox)
        self.iface.attributesToolBar().removeAction(self.toolboxAction)

        self.resultsDock.setVisible(False)
        self.iface.removeDockWidget(self.resultsDock)

        self.toolbox.deleteLater()
        self.menu.deleteLater()

        # delete temporary output files
        folder = QgsProcessingUtils.tempFolder()
        if QDir(folder).exists():
            shutil.rmtree(folder, True)

        # also delete temporary help files
        folder = tempHelpFolder()
        if QDir(folder).exists():
            shutil.rmtree(folder, True)

        self.iface.unregisterMainWindowAction(self.toolboxAction)
        self.iface.unregisterMainWindowAction(self.modelerAction)
        self.iface.unregisterMainWindowAction(self.historyAction)
        self.iface.unregisterMainWindowAction(self.resultsAction)

        self.iface.unregisterOptionsWidgetFactory(self.options_factory)
        self.iface.deregisterLocatorFilter(self.locator_filter)
        self.iface.deregisterLocatorFilter(self.edit_features_locator_filter)
        self.iface.unregisterCustomDropHandler(self.drop_handler)
        QgsApplication.dataItemProviderRegistry().removeProvider(
            self.item_provider)

        removeMenus()
        Processing.deinitialize()

    def openToolbox(self, show):
        self.toolbox.setUserVisible(show)

    def toolboxVisibilityChanged(self, visible):
        self.toolboxAction.setChecked(visible)

    def openModeler(self):
        dlg = ModelerDialog()
        dlg.update_model.connect(self.updateModel)
        dlg.show()

    def updateModel(self):
        model_provider = QgsApplication.processingRegistry().providerById(
            'model')
        model_provider.refreshAlgorithms()

    def openResults(self):
        if self.resultsDock.isVisible():
            self.resultsDock.hide()
        else:
            self.resultsDock.show()

    def openHistory(self):
        dlg = HistoryDialog()
        dlg.exec_()

    def tr(self, message):
        return QCoreApplication.translate('ProcessingPlugin', message)

    def editSelected(self, enabled):
        self.toolbox.set_in_place_edit_mode(enabled)
Beispiel #4
0
class WebGisPlugin(object):

    dialog = None
    project = None
    ws = None

    def __init__(self, iface):
        # Save reference to the QGIS interface
        self.iface = iface
        # initialize plugin directory
        self.plugin_dir = os.path.dirname(__file__)
        # initialize locale
        locale = QSettings().value("locale/userLocale")[0:2]
        localePath = os.path.join(self.plugin_dir, 'i18n',
                                  'gisquick_{}.qm'.format(locale))

        if os.path.exists(localePath):
            self.translator = QTranslator()
            self.translator.load(localePath)

            if qVersion() > '4.3.3':
                QCoreApplication.installTranslator(self.translator)

    def initGui(self):
        # Create action that will start plugin configuration
        self.action = QAction(QIcon(":/plugins/gisquick2/img/icon.svg"),
                              u"Publish in Gisquick", self.iface.mainWindow())
        self.action.setCheckable(True)
        # connect the action to the run method
        self.action.triggered.connect(self.toggle_tool)

        self.settings_action = QAction(
            QIcon(":/plugins/gisquick2/img/settings.svg"), u"Configure",
            self.iface.mainWindow())
        # connect the action to the run method
        self.settings_action.triggered.connect(self.show_settings)

        # Add toolbar button and menu item
        # self.iface.addToolBarIcon(self.action)
        self.iface.addWebToolBarIcon(self.action)
        self.iface.addPluginToWebMenu(u"&Gisquick2", self.action)
        self.iface.addPluginToWebMenu(u"&Gisquick2", self.settings_action)

    def unload(self):
        if self.ws:
            gisquick_ws.stop()
            self.ws = None

        # Remove the plugin menu item and icon
        self.iface.removePluginWebMenu(u"&Gisquick2", self.action)
        self.iface.removePluginWebMenu(u"&Gisquick2", self.settings_action)
        self.iface.removeWebToolBarIcon(self.action)

    def is_overlay_layer_for_publish(self, layer):
        """Checks whether layer can be published as an overlay layer.

        Args:
            layer (qgis.core.QgsMapLayer): project layer
 
        Returns:
            bool: True if a layer can be published as an overlay layer
        """
        return (layer.type() == QgsMapLayer.VectorLayer
                or (layer.type() == QgsMapLayer.RasterLayer
                    and layer.providerType() != "wms"))

    def is_base_layer_for_publish(self, layer):
        """Checks whether layer could be published as a base layer.

        Args:
            layer (qgis.core.QgsMapLayer): project layer
 
        Returns:
            bool: True if a layer can be published as a base layer
        """
        return layer.type() == QgsMapLayer.RasterLayer and layer.providerType(
        ) == "wms"

    def map_units(self):
        """Returns units name of the project (map).

        Returns:
            str: map units name ('meters', 'feet', 'degrees', 'miles' or 'unknown')
        """
        return {
            0: 'meters',
            1: 'feet',
            2: 'degrees',
            3: 'unknown',
            7: 'miles'
        }[self.iface.mapCanvas().mapUnits()]

    def scales_to_resolutions(self, scales):
        """Converts map scales to tile resolutions (with fixed DPI=96).

        Args:
            scales (List[int]): array of map scales

        Returns:
            List[Decimal]: array of computed tile resolutions
        """
        return scales_to_resolutions(scales, self.map_units())

    def resolutions_to_scales(self, resolutions):
        """Converts tile resolutions to map scales (with fixed DPI=96).

        Args:
            resolutions (List[Decimal]): array of tile resolutions

        Returns:
            List[int]: array of computed map scales
        """
        return resolutions_to_scales(resolutions, self.map_units())

    def filter_visible_resolutions(self, resolutions, layer):
        """Filters given tile resolutions by layer's visibility settings.

        Args:
            resolutions (List[Decimal]): array of tile resolutions
            layer (qgis.core.QgsMapLayer): map layer

        Returns:
            List[Decimal]: array of visible tile resolutions
        """
        if layer.hasScaleBasedVisibility():
            max_scale_exclusive = layer.maximumScale()
            min_scale_inclusive = layer.minimumScale()
            max_res_exclusive, min_res_inclusive = self.scales_to_resolutions(
                [max_scale_exclusive, min_scale_inclusive])
            return [
                res for res in resolutions
                if res >= min_res_inclusive and res < max_res_exclusive
            ]
        return resolutions

    def wmsc_layer_resolutions(self, layer):
        """Returns visible resolutions of given WMSC layer.

        Args:
            layer (qgis.core.QgsRasterLayer): raster layer (WMSC)

        Returns:
            List[Decimal]: array of layer's visible tile resolutions
        """
        layer_resolutions = layer.dataProvider().property('resolutions')
        if layer_resolutions:
            layer_resolutions = to_decimal_array(layer_resolutions)
            if layer.hasScaleBasedVisibility():
                layer_resolutions = self.filter_visible_resolutions(
                    layer_resolutions, layer)
            if layer_resolutions:
                return sorted(layer_resolutions, reverse=True)
            return []
        return None

    def project_layers_resolutions(self):
        """Returns list of possible tile resolutions for current project.

        Returns:
            List[Decimal]: project tile resolutions
        """
        # compute resolutions as an union of resolutions calculated from project's
        # map scales and resolutions of all WMSC layers.
        project_tile_resolutions = set()

        # collect set of all resolutions from WMSC base layers
        base_layers = {
            layer.id(): layer
            for layer in QgsProject.instance().mapLayers().values()
            if self.is_base_layer_for_publish(layer)
        }
        for layer in list(base_layers.values()):
            layer_resolutions = self.wmsc_layer_resolutions(layer)
            if layer_resolutions:
                project_tile_resolutions.update(layer_resolutions)

        wmsc_layers_scales = self.resolutions_to_scales(
            project_tile_resolutions)
        scales, ok = self.project.readListEntry("Scales", "/ScalesList")
        if ok and scales:
            scales = [int(scale.split(":")[-1]) for scale in scales]
            # filter duplicit scales
            scales = [
                scale for scale in scales if scale not in wmsc_layers_scales
            ]
            project_tile_resolutions.update(
                self.scales_to_resolutions(sorted(scales, reverse=True)))

        project_tile_resolutions = sorted(project_tile_resolutions,
                                          reverse=True)
        return project_tile_resolutions

    def layers_list(self):
        """Returns array of all project's layers.

        Returns:
            List[qgis.core.QgsMapLayer]: project's layers
        """
        # legend_iface = self.iface.legendInterface().layers()
        return [
            tree_layer.layer() for tree_layer in
            QgsProject.instance().layerTreeRoot().findLayers()
        ]

    def get_layer_attributes(self, layer):
        fields = layer.fields()
        attributes_data = []
        excluded_attributes = layer.excludeAttributesWfs()
        conversion_types = {
            'BIGINT': 'INTEGER',
            'INTEGER64': 'INTEGER',
            'REAL': 'DOUBLE',
            'STRING': 'TEXT',
            'INT2': 'INTEGER',
            'INT4': 'INTEGER',
            'INT8': 'INTEGER',
            'NUMERIC': 'DOUBLE',
            'FLOAT8': 'DOUBLE',
            'VARCHAR': 'TEXT',
            'CHARACTER': 'TEXT'
        }
        for field in fields:
            if field.name() in excluded_attributes:
                continue
            field_type = field.typeName().upper()
            if field_type in conversion_types:
                field_type = conversion_types[field_type]
            attribute_data = {
                'name': field.name(),
                'type': field_type,
                #'length': field.length(),
                #'precision': field.precision()
            }
            if field.comment():
                attribute_data['comment'] = field.comment()
            alias = layer.attributeAlias(fields.indexFromName(field.name()))
            if alias:
                attribute_data['alias'] = alias
            attributes_data.append(attribute_data)

        return attributes_data

    def get_project_layers(self, skip_layers_with_error=False):
        dbname_pattern = re.compile("dbname='([^']+)'")
        project = QgsProject.instance()
        project_dir = project.absolutePath() + os.path.sep

        non_identifiable_layers = project.readListEntry(
            "Identify", "/disabledLayers")[0] or []
        wfs_layers = project.readListEntry("WFSLayers", "/")[0] or []
        map_canvas = self.iface.mapCanvas()
        map_settings = map_canvas.mapSettings()

        if project.layerTreeRoot().hasCustomLayerOrder():
            layers_order = project.layerTreeRoot().customLayerOrder()
        else:
            layers_order = self.layers_list()

        def visit_node(tree_node):
            if isinstance(tree_node, QgsLayerTreeLayer):
                layer = tree_node.layer()
                layer_type = {
                    0: "vector",
                    1: "raster",
                    # 2: PluginLayer
                    # 3: MeshLayer
                }[layer.type()]
                source = layer.source()
                provider_type = layer.providerType()
                uri = ""

                if provider_type == "wms":
                    source_params = parse_qs(source)
                    uri = source_params["url"][0]
                elif provider_type == "postgres":
                    dp = layer.dataProvider()
                    uri = "postgresql://%s:%s" % (dp.uri().host(),
                                                  dp.uri().port())
                elif provider_type in ("ogr", "gdal"):
                    uri = "file://%s" % source.split("|")[0]
                elif provider_type == "spatialite":
                    match = dbname_pattern.search(source)
                    if match:
                        uri = "file://%s" % match.group(1)
                else:
                    uri = source

                extent = layer.extent()
                if not extent.isEmpty():
                    extent = map_settings.layerExtentToOutputExtent(
                        layer, layer.extent()).toRectF().getCoords()
                else:
                    extent = None
                info = {
                    "id":
                    layer.id(),
                    "name":
                    layer.name(),
                    "serverName":
                    layer.shortName()
                    if hasattr(layer, "shortName") else layer.name(),
                    "wfs":
                    layer.id() in wfs_layers,
                    "provider_type":
                    provider_type,
                    "projection":
                    layer.crs().authid(),
                    "type":
                    layer_type,
                    "source":
                    uri,
                    "extent":
                    extent,
                    "visible":
                    project.layerTreeRoot().findLayer(layer.id()).isVisible(),
                    "metadata": {
                        "title": layer.title(),
                        "abstract": layer.abstract(),
                        "keyword_list": layer.keywordList()
                    }
                }
                legend_url = layer.legendUrl()
                if legend_url:
                    info["legend_url"] = legend_url
                # if layer.isSpatial()
                if layer_type == "vector":
                    info["geom_type"] = ('POINT', 'LINE', 'POLYGON', None,
                                         None)[layer.geometryType()]
                    info["wkb_type"] = QgsWkbTypes.displayString(
                        layer.wkbType())
                    info["labels"] = layer.labelsEnabled()
                    info["attributes"] = self.get_layer_attributes(layer)
                    info["queryable"] = bool(info["attributes"]) and layer.id(
                    ) not in non_identifiable_layers and layer.id(
                    ) in wfs_layers
                    if info["attributes"]:
                        fields = layer.fields()
                        info["pk_attributes"] = [
                            fields.at(index).name() for index in
                            layer.dataProvider().pkAttributeIndexes()
                        ]

                if provider_type == "wms":
                    info["url"] = source_params["url"][0]
                    img_format = source_params.get("format", [None])[0]
                    if not img_format:
                        img_format = os.path.splitext(info["url"])[1].replace(
                            ".", "image/")

                    info["format"] = img_format

                    info["dpi"] = layer.dataProvider().dpi()
                    if "layers" in source_params:
                        info["wms_layers"] = source_params["layers"]

                if layer in layers_order:
                    info["drawing_order"] = layers_order.index(layer)
                if layer.attribution():
                    info["attribution"] = {
                        "title": layer.attribution(),
                        "url": layer.attributionUrl()
                    }
                return info
            else:
                children = []
                for child_tree_node in tree_node.children():
                    try:
                        info = visit_node(child_tree_node)
                        if info:
                            children.append(info)
                    except Exception as e:
                        if not skip_layers_with_error:
                            msg = "Failed to gather info from layer: '%s'" % child_tree_node.name(
                            )
                            raise WsError(msg, 405) from e
                return {"name": tree_node.name(), "layers": children}

        root_node = self.iface.layerTreeView().layerTreeModel().rootGroup()
        return visit_node(root_node)["layers"]

    def get_print_templates(self):
        composer_templates = []
        project_layout_manager = QgsProject.instance().layoutManager()
        for layout in project_layout_manager.layouts():
            map = layout.referenceMap()
            units_conversion = map.mapUnitsToLayoutUnits()
            composer_data = {
                'name':
                layout.name(),
                'width':
                layout.layoutBounds().width(),
                'height':
                layout.layoutBounds().height(),
                'map': {
                    'name': 'map0',
                    'x': map.pagePos().x(),
                    'y': map.pagePos().y(),
                    'width': map.extent().width() * units_conversion,
                    'height': map.extent().height() * units_conversion
                },
                'labels': [
                    item.id() for item in list(layout.items())
                    if isinstance(item, QgsLayoutItemLabel) and item.id()
                ]
            }
            grid = map.grid()
            if grid.enabled():
                composer_data['map']['grid'] = {
                    'intervalX': grid.intervalX(),
                    'intervalY': grid.intervalY(),
                }
            composer_templates.append(composer_data)
        return composer_templates

    def get_project_info(self, skip_layers_with_error=False):
        project = QgsProject.instance()
        project_crs = project.crs()
        map_canvas = self.iface.mapCanvas()

        # scales, _ = project.readListEntry("Scales", "/ScalesList")
        # scales = [int(s.split(":")[1]) for s in scales]

        view_settings = project.viewSettings()
        scales = view_settings.mapScales()

        projections = {}
        crs_list = [project_crs
                    ] + [l.crs() for l in project.mapLayers().values()]
        for crs in crs_list:
            if crs.authid() not in projections:
                projections[crs.authid()] = {
                    "is_geographic": crs.isGeographic(),
                    "proj4": crs.toProj4()
                }
        data = {
            "file":
            project.absoluteFilePath(),
            "directory":
            project.absolutePath(),
            "title":
            project.title() or project.readEntry("WMSServiceTitle", "/")[0],
            "layers":
            self.get_project_layers(skip_layers_with_error),
            "composer_templates":
            self.get_print_templates(),
            "projection": {
                "code": project_crs.authid(),
                "is_geographic": project_crs.isGeographic(),
                "proj4": project_crs.toProj4()
            },
            "units":
            self.map_units(),
            "scales":
            scales,
            "position_precision": {
                "automatic":
                project.readBoolEntry("PositionPrecision", "/Automatic")[0],
                "decimal_places":
                project.readNumEntry("PositionPrecision", "/DecimalPlaces")[0]
            },
            "extent":
            map_canvas.fullExtent().toRectF().getCoords(),
            # "default_view_extent": view_settings.defaultViewExtent(),
            "server": {
                "wms_add_geometry":
                project.readBoolEntry("WMSAddWktGeometry", "")[0]
            },
            "projections":
            projections
        }
        return data

    def get_settings(self):
        return QSettings(QSettings.IniFormat, QSettings.UserScope, "Gisquick",
                         "gisquick2")

    def show_settings(self):
        settings = self.get_settings()
        dialog_filename = os.path.join(self.plugin_dir, "ui", "settings.ui")
        dialog = PyQt5.uic.loadUi(dialog_filename)
        dialog.server_url.setText(settings.value("server_url", ""))
        dialog.username.setText(settings.value("username", ""))
        dialog.password.setText(settings.value("password", ""))

        dialog.show()
        res = dialog.exec_()
        if res == 1:
            settings.setValue("server_url",
                              dialog.server_url.text().rstrip("/"))
            settings.setValue("username", dialog.username.text())
            settings.setValue("password", dialog.password.text())

    def on_project_change(self, *args):
        gisquick_ws.send("ProjectChanged")

    def on_project_closed(self, *args):
        def debounced():
            # filter events caused by switching between projects
            if not QgsProject.instance().absoluteFilePath():
                gisquick_ws.send("ProjectChanged")

        QTimer.singleShot(300, debounced)

    def toggle_tool(self, active):
        """Display dialog window for publishing current project.

        During a configuration process (wizard setup), plugin will hold actual metadata
        object in 'WebGisPlugin.metadata' property. If metadata from previous publishing
        still exist, they will be loaded and stored in 'WebGisPlugin.last_metadata' property.
        """
        def callback(msg):
            msg_type = msg["type"]
            data = msg.get("data")
            if msg_type == "ProjectInfo":
                if QgsProject.instance().absolutePath():
                    if data:
                        skip_layers_with_error = data.get(
                            "skip_layers_with_error", False)
                    return self.get_project_info(
                        skip_layers_with_error=skip_layers_with_error)
                raise WsError("Project is not opened", 404)

            elif msg_type == "ProjectDirectory":
                dir_path = QgsProject.instance().absolutePath()
                if dir_path:
                    return dir_path
                raise WsError("Project is not opened", 404)
            else:
                raise ValueError("Unknown message type: %s" % msg_type)

        def on_connection_estabilished():
            # self.iface.messageBar().pushMessage("Gisquick", "plugin is connected to server: %s" % server_url, level=Qgis.Success)

            def open_browser():
                import webbrowser
                webbrowser.open(urljoin(server_url, '/user/'))

            widget = self.iface.messageBar().createMessage(
                "Gisquick",
                "successfully connected to server: %s" % server_url)
            button = QPushButton(widget)
            button.setText("Open Browser")
            button.pressed.connect(open_browser)
            widget.layout().addWidget(button)
            self.iface.messageBar().pushWidget(widget, Qgis.Success)
            self.active_notification_widget = widget

        project = QgsProject.instance()
        if active:
            self.active_notification_widget = None
            settings = self.get_settings()
            server_url = settings.value("server_url")
            username = settings.value("username")
            password = settings.value("password")
            if not server_url or not username or not password:
                self.show_settings()
                server_url = settings.value("server_url")
                username = settings.value("username")
                password = settings.value("password")

            plugin_ver = __metadata__["general"].get("version")
            client_info = "GisquickPlugin/%s (%s %s; QGIS %s)" % (
                plugin_ver, platform.system(), platform.machine(),
                Qgis.QGIS_VERSION)

            class WebsocketServer(QThread):
                finished = QtCore.pyqtSignal(int)
                success = QtCore.pyqtSignal()

                def run(self):
                    # print("Starting WS", "server:", server_url, "user:", username)
                    def on_success():
                        self.success.emit()

                    res = gisquick_ws.start(server_url, username, password,
                                            client_info, callback, on_success)
                    self.finished.emit(res)

            def on_finished(res):
                self.ws = None
                if self.action.isChecked():
                    self.action.setChecked(False)
                if res != 0:
                    QMessageBox.warning(None, 'Warning', 'Failed to connect!')
                else:
                    if self.iface.messageBar().currentItem(
                    ) == self.active_notification_widget:
                        self.iface.messageBar().popWidget(
                            self.active_notification_widget)
                    self.active_notification_widget = None

            self.ws = WebsocketServer()
            self.ws.finished.connect(on_finished)
            self.ws.success.connect(on_connection_estabilished)
            r = self.ws.start()

            # project.isDirtyChanged.connect(self.on_project_change)
            project.readProject.connect(self.on_project_change)
            project.projectSaved.connect(self.on_project_change)
            project.cleared.connect(self.on_project_closed)
        else:
            gisquick_ws.stop()
            project.readProject.disconnect(self.on_project_change)
            project.projectSaved.disconnect(self.on_project_change)
            project.cleared.disconnect(self.on_project_closed)
Beispiel #5
0
class proposalsPanel(RestrictionTypeUtilsMixin):
    def __init__(self, iface, TOMsToolBar):
        #def __init__(self, iface, TOMsMenu, proposalsManager):

        # Save reference to the QGIS interface
        self.iface = iface
        self.canvas = self.iface.mapCanvas()
        self.TOMsToolBar = TOMsToolBar

        self.actionProposalsPanel = QAction(
            QIcon(":/plugins/TOMs/resources/TOMsStart.png"),
            QCoreApplication.translate("MyPlugin", "Start TOMs"),
            self.iface.mainWindow())
        self.actionProposalsPanel.setCheckable(True)

        self.TOMsToolBar.addAction(self.actionProposalsPanel)

        self.actionProposalsPanel.triggered.connect(self.onInitProposalsPanel)

        self.newProposalRequired = False

        self.proposalsManager = TOMsProposalsManager(self.iface)
        self.tableNames = self.proposalsManager.tableNames

        # Now set up the toolbar

        self.RestrictionTools = manageRestrictionDetails(
            self.iface, self.TOMsToolBar, self.proposalsManager)
        self.RestrictionTools.disableTOMsToolbarItems()
        self.searchBar = searchBar(self.iface, self.TOMsToolBar,
                                   self.proposalsManager)
        self.searchBar.disableSearchBar()

        TOMsMessageLog.logMessage("Finished proposalsPanel init ...",
                                  level=Qgis.Warning)

    def onInitProposalsPanel(self):
        """Filter main layer based on date and state options"""

        TOMsMessageLog.logMessage("In onInitProposalsPanel", level=Qgis.Info)

        #print "** STARTING ProposalPanel"

        # dockwidget may not exist if:
        #    first run of plugin
        #    removed on close (see self.onClosePlugin method)

        # self.TOMSLayers.TOMsStartupFailure.connect(self.setCloseTOMsFlag)
        #self.RestrictionTypeUtilsMixin.tableNames.TOMsStartupFailure.connect(self.closeTOMsTools)

        if self.actionProposalsPanel.isChecked():

            TOMsMessageLog.logMessage(
                "In onInitProposalsPanel. Activating ...", level=Qgis.Info)

            self.openTOMsTools()

        else:

            TOMsMessageLog.logMessage(
                "In onInitProposalsPanel. Deactivating ...", level=Qgis.Info)

            self.closeTOMsTools()

        pass

    def openTOMsTools(self):
        # actions when the Proposals Panel is closed or the toolbar "start" is toggled

        TOMsMessageLog.logMessage("In openTOMsTools. Activating ...",
                                  level=Qgis.Info)
        self.closeTOMs = False

        # Check that tables are present
        TOMsMessageLog.logMessage("In onInitProposalsPanel. Checking tables",
                                  level=Qgis.Info)
        self.tableNames.TOMsLayersNotFound.connect(self.setCloseTOMsFlag)

        self.tableNames.getLayers()

        if self.closeTOMs:
            QMessageBox.information(self.iface.mainWindow(), "ERROR",
                                    ("Unable to start TOMs ..."))
            self.actionProposalsPanel.setChecked(False)
            return

            # QMessageBox.information(self.iface.mainWindow(), "ERROR", ("TOMsActivated about to emit"))
        self.proposalsManager.TOMsActivated.emit()

        self.dock = ProposalPanelDockWidget()
        self.iface.addDockWidget(Qt.LeftDockWidgetArea, self.dock)

        # set up tabbing for Panels
        self.setupPanelTabs(self.iface, self.dock)

        self.proposalsManager.dateChanged.connect(self.onDateChanged)
        self.dock.filterDate.setDisplayFormat("dd-MM-yyyy")
        self.dock.filterDate.setDate(QDate.currentDate())

        self.Proposals = self.tableNames.setLayer("Proposals")

        # Set up field details for table  ** what about errors here **
        idxProposalID = self.Proposals.fields().indexFromName("ProposalID")
        self.idxProposalTitle = self.Proposals.fields().indexFromName(
            "ProposalTitle")
        self.idxCreateDate = self.Proposals.fields().indexFromName(
            "ProposalCreateDate")
        self.idxOpenDate = self.Proposals.fields().indexFromName(
            "ProposalOpenDate")
        self.idxProposalStatusID = self.Proposals.fields().indexFromName(
            "ProposalStatusID")

        self.createProposalcb()

        # set CurrentProposal to be 0

        #self.proposalsManager.setCurrentProposal(0)

        # set up action for when the date is changed from the user interface
        self.dock.filterDate.dateChanged.connect(
            lambda: self.proposalsManager.setDate(self.dock.filterDate.date()))

        # set up action for "New Proposal"
        self.dock.btn_NewProposal.clicked.connect(self.onNewProposal)

        # set up action for "View Proposal"
        self.dock.btn_ViewProposal.clicked.connect(self.onProposalDetails)

        self.proposalsManager.newProposalCreated.connect(
            self.onNewProposalCreated)

        # Create a transaction object for the Proposals

        self.proposalTransaction = TOMsTransaction(self.iface,
                                                   self.proposalsManager)

        self.RestrictionTools.enableTOMsToolbarItems(self.proposalTransaction)
        self.searchBar.enableSearchBar()

        # setup use of "Escape" key to deactive map tools - https://gis.stackexchange.com/questions/133228/how-to-deactivate-my-custom-tool-by-pressing-the-escape-key-using-pyqgis
        """shortcutEsc = QShortcut(QKeySequence(Qt.Key_Escape), self.iface.mainWindow())
        shortcutEsc.setContext(Qt.ApplicationShortcut)
        shortcutEsc.activated.connect(self.iface.mapCanvas().unsetMapTool(self.mapTool))"""
        self.proposalsManager.setCurrentProposal(0)

        # TODO: Deal with the change of project ... More work required on this
        # self.TOMsProject = QgsProject.instance()
        # self.TOMsProject.cleared.connect(self.closeTOMsTools)

    def setCloseTOMsFlag(self):
        self.closeTOMs = True

    def closeTOMsTools(self):
        # actions when the Proposals Panel is closed or the toolbar "start" is toggled

        TOMsMessageLog.logMessage("In closeTOMsTools. Deactivating ...",
                                  level=Qgis.Info)

        # TODO: Delete any objects that are no longer needed

        self.proposalTransaction.rollBackTransactionGroup()
        del self.proposalTransaction  # There is another call to this function from the dock.close()

        # Now disable the items from the Toolbar

        self.RestrictionTools.disableTOMsToolbarItems()
        self.searchBar.disableSearchBar()

        self.actionProposalsPanel.setChecked(False)

        # Now close the proposals panel

        self.dock.close()

        # Now clear the filters

        self.proposalsManager.clearRestrictionFilters()

        pass

    def createProposalcb(self):

        TOMsMessageLog.logMessage("In createProposalcb", level=Qgis.Info)
        # set up a "NULL" field for "No proposals to be shown"

        #self.dock.cb_ProposalsList.currentIndexChanged.connect(self.onProposalListIndexChanged)
        #self.dock.cb_ProposalsList.currentIndexChanged.disconnect(self.onProposalListIndexChanged)

        self.dock.cb_ProposalsList.clear()

        currProposalID = 0
        currProposalTitle = "0 - No proposal shown"

        TOMsMessageLog.logMessage("In createProposalcb: Adding 0",
                                  level=Qgis.Info)

        self.dock.cb_ProposalsList.addItem(currProposalTitle, currProposalID)

        for (currProposalID, currProposalTitle, currProposalStatusID,
             currProposalOpenDate, currProposal) in sorted(
                 self.proposalsManager.getProposalsListWithStatus(
                     ProposalStatus.IN_PREPARATION),
                 key=lambda f: f[1]):
            TOMsMessageLog.logMessage("In createProposalcb: proposalID: " +
                                      str(currProposalID) + ":" +
                                      currProposalTitle,
                                      level=Qgis.Info)
            self.dock.cb_ProposalsList.addItem(currProposalTitle,
                                               currProposalID)

        # set up action for when the proposal is changed
        self.dock.cb_ProposalsList.currentIndexChanged.connect(
            self.onProposalListIndexChanged)

    def onChangeProposal(self):
        TOMsMessageLog.logMessage("In onChangeProposal", level=Qgis.Info)

        # https://gis.stackexchange.com/questions/94135/how-to-populate-a-combobox-with-layers-in-toc
        newProposal_cbIndex = self.dock.cb_ProposalsList.currentIndex()
        newProposalID = self.dock.cb_ProposalsList.itemData(
            newProposal_cbIndex)
        newProposalTitle = self.dock.cb_ProposalsList.currentText()

        self.setCurrentProposal(newProposalID)
        TOMsMessageLog.logMessage("In onChangeProposal. newProposalID: " +
                                  str(newProposalID) + " newProposalTitle: " +
                                  str(newProposalTitle),
                                  level=Qgis.Info)

        # Set the project variable

        reply = QMessageBox.information(self.iface.mainWindow(), "Information",
                                        "All changes will be rolled back",
                                        QMessageBox.Ok)

    def onNewProposal(self):
        TOMsMessageLog.logMessage("In onNewProposal", level=Qgis.Info)

        # set up a transaction
        self.proposalTransaction.startTransactionGroup()

        # create a new Proposal
        """self.newProposal = QgsFeature(self.Proposals.fields())
        #newProposal.setGeometry(QgsGeometry())

        self.newProposal[self.idxProposalTitle] = ''   #str(uuid.uuid4())
        self.newProposal[self.idxCreateDate] = self.proposalsManager.date()
        self.newProposal[self.idxOpenDate] = self.proposalsManager.date()
        self.newProposal[self.idxProposalStatusID] = ProposalStatus.IN_PREPARATION
        self.newProposal.setGeometry(QgsGeometry())

        self.Proposals.addFeature(self.newProposal)  # TH (added for v3)"""
        self.newProposalObject = self.proposalsManager.currentProposalObject(
        ).initialiseProposal()
        self.newProposal = self.proposalsManager.currentProposalObject(
        ).getProposalRecord()

        self.proposalDialog = self.iface.getFeatureForm(
            self.Proposals, self.newProposal)

        #self.proposalDialog.attributeForm().disconnectButtonBox()
        self.button_box = self.proposalDialog.findChild(
            QDialogButtonBox, "button_box")

        if self.button_box is None:
            TOMsMessageLog.logMessage("In onNewProposal. button box not found",
                                      level=Qgis.Info)

            #self.button_box.accepted.disconnect()
        self.button_box.accepted.connect(
            functools.partial(self.onSaveProposalFormDetails, self.newProposal,
                              self.newProposalObject, self.Proposals,
                              self.proposalDialog, self.proposalTransaction))

        #self.button_box.rejected.disconnect()
        self.button_box.rejected.connect(self.onRejectProposalDetailsFromForm)

        self.proposalDialog.attributeForm().attributeChanged.connect(
            functools.partial(self.onAttributeChangedClass2, self.newProposal,
                              self.Proposals))

        self.proposalDialog.show()

        #self.iface.openFeatureForm(self.Proposals, newProposal, False, True)

        #self.createProposalcb()
        pass

    def onNewProposalCreated(self, proposal):
        TOMsMessageLog.logMessage("In onNewProposalCreated. New proposal = " +
                                  str(proposal),
                                  level=Qgis.Info)

        self.createProposalcb()

        # change the list to show the new proposal

        for currIndex in range(self.dock.cb_ProposalsList.count()):
            currProposalID = self.dock.cb_ProposalsList.itemData(currIndex)
            #TOMsMessageLog.logMessage("In onNewProposalSaved. checking index = " + str(currIndex), level=Qgis.Info)
            if currProposalID == proposal:
                TOMsMessageLog.logMessage(
                    "In onNewProposalCreated. index found as " +
                    str(currIndex),
                    level=Qgis.Info)
                self.dock.cb_ProposalsList.setCurrentIndex(currIndex)
                return

        return

        #def onSaveProposalDetailsFromForm(self):
        #self.onSaveProposalFormDetails(self.newProposal, self.Proposals, self.proposalDialog, self.currTransaction)

    def onRejectProposalDetailsFromForm(self):

        self.Proposals.destroyEditCommand()
        self.proposalDialog.reject()

        #self.rollbackCurrentEdits()

        self.proposalTransaction.rollBackTransactionGroup()

        pass

    def onProposalDetails(self):
        TOMsMessageLog.logMessage("In onProposalDetails", level=Qgis.Info)

        # set up transaction
        self.proposalTransaction.startTransactionGroup()

        # https://gis.stackexchange.com/questions/94135/how-to-populate-a-combobox-with-layers-in-toc
        currProposal_cbIndex = self.dock.cb_ProposalsList.currentIndex()

        if currProposal_cbIndex == 0:
            return  # there is nothing to see

        currProposalID = self.dock.cb_ProposalsList.itemData(
            currProposal_cbIndex)

        # self.currProposal = self.getProposal(currProposalID)
        self.currProposalObject = self.proposalsManager.currentProposalObject()
        self.currProposal = self.proposalsManager.currentProposalObject(
        ).getProposalRecord()
        self.proposalDialog = self.iface.getFeatureForm(
            self.Proposals, self.currProposal)

        #self.proposalDialog.attributeForm().disconnectButtonBox()
        self.button_box = self.proposalDialog.findChild(
            QDialogButtonBox, "button_box")

        if self.button_box is None:
            TOMsMessageLog.logMessage("In onNewProposal. button box not found",
                                      level=Qgis.Info)

        self.button_box.accepted.disconnect()
        self.button_box.accepted.connect(
            functools.partial(self.onSaveProposalFormDetails,
                              self.currProposal, self.currProposalObject,
                              self.Proposals, self.proposalDialog,
                              self.proposalTransaction))

        self.button_box.rejected.disconnect()
        self.button_box.rejected.connect(self.onRejectProposalDetailsFromForm)

        self.proposalDialog.attributeForm().attributeChanged.connect(
            functools.partial(self.onAttributeChangedClass2, self.currProposal,
                              self.Proposals))

        self.proposalDialog.show()

        pass

    def onProposalListIndexChanged(self):
        TOMsMessageLog.logMessage("In onProposalListIndexChanged.",
                                  level=Qgis.Info)
        #currProposal = self.proposalsManager.currentProposal()
        #currProposalIdx = self.dock.cb_ProposalsList.findData(currProposal)
        #self.dock.cb_ProposalsList.setCurrentIndex(currProposalIdx)

        currProposal_cbIndex = self.dock.cb_ProposalsList.currentIndex()
        TOMsMessageLog.logMessage(
            "In onProposalListIndexChanged. Current Index = " +
            str(currProposal_cbIndex),
            level=Qgis.Info)
        currProposalID = self.dock.cb_ProposalsList.itemData(
            currProposal_cbIndex)
        self.proposalsManager.setCurrentProposal(currProposalID)

        TOMsMessageLog.logMessage("In onProposalChanged. Zoom to extents",
                                  level=Qgis.Info)
        """if self.proposalsManager.getProposalBoundingBox():
            TOMsMessageLog.logMessage("In onProposalChanged. Bounding box found", level=Qgis.Info)
            self.iface.mapCanvas().setExtent(self.proposalsManager.getProposalBoundingBox())
            self.iface.mapCanvas().refresh()"""

    def updateCurrentProposal(self):
        TOMsMessageLog.logMessage("In updateCurrentProposal.", level=Qgis.Info)
        """Will be called whenever a new entry is selected in the combobox"""

        # Can we check to see if there are any outstanding edits?!!
        """reply = QMessageBox.information(self.iface.mainWindow(), "Information", "All changes will be rolled back",
                                        QMessageBox.Ok)

        if reply:

            self.iface.actionRollbackAllEdits().trigger()
            self.iface.actionCancelAllEdits().trigger()

        pass"""

        currProposal_cbIndex = self.dock.cb_ProposalsList.currentIndex()
        currProposalID = self.dock.cb_ProposalsList.itemData(
            currProposal_cbIndex)
        self.proposalsManager.setCurrentProposal(currProposalID)

    def onDateChanged(self):
        TOMsMessageLog.logMessage("In onDateChanged.", level=Qgis.Info)
        date = self.proposalsManager.date()
        self.dock.filterDate.setDate(date)
        """ onChangeProposalStatus(self):
        TOMsMessageLog.logMessage("In onChangeProposalStatus. Proposed status: " + str(self.Proposals.fields().indexFromName("ProposalStatusID")), level=Qgis.Info)

        # check to see if the proposal is "Accepted"
        acceptProposal = False

        newProposalStatus = int(self.Proposals.fields().indexFromName("ProposalStatusID"))

        if newProposalStatus == 1:    # should be 2 but with list ...

            # if so, check to see if this was intended

            reply = QMessageBox.question(self.iface.mainWindow(), 'Confirm changes to Proposal',
                                         'Are you you want to accept this proposal?. Accepting will make all the proposed changes permanent.', QMessageBox.Yes, QMessageBox.No)
            if reply == QMessageBox.Yes:
                # make the changes permanent
                acceptProposal = True

        # bring the Proposals dislog back to the front

        self.dlg.activateWindow()

        return acceptProposal"""
        """def getRestrictionLayerTableID(self, currRestLayer):
        TOMsMessageLog.logMessage("In getRestrictionLayerTableID.", level=Qgis.Info)
        # find the ID for the layer within the table "

        RestrictionsLayers = QgsMapLayerRegistry.instance().mapLayersByName("RestrictionLayers2")[0]

        layersTableID = 0

        # not sure if there is better way to search for something, .e.g., using SQL ??

        for layer in RestrictionsLayers.getFeatures():
            if layer.attribute("RestrictionLayerName") == str(currRestLayer.name()):
                layersTableID = layer.attribute("id")

        TOMsMessageLog.logMessage("In getRestrictionLayerTableID. layersTableID: " + str(layersTableID), level=Qgis.Info)

        return layersTableID"""

    def getProposal(self, proposalID):
        TOMsMessageLog.logMessage("In getProposal.", level=Qgis.Info)

        # proposalsLayer = QgsMapLayerRegistry.instance().mapLayersByName("Proposals")[0]  -- v2
        proposalsLayer = QgsProject.instance().mapLayersByName("Proposals")[0]

        # not sure if there is better way to search for something, .e.g., using SQL ??

        for currProposal in proposalsLayer.getFeatures():
            if currProposal.attribute("ProposalID") == proposalID:
                return currProposal

        return None

        pass
class LayerTreeViewSample(QgsMapTool):
    def changeLayer(self, layer):

        if (layer == None):  # レイヤウィンドウに何も無い状態
            self.currentlayer = None
            self.cleared.emit()
            return

        if self.currentlayer != None:
            print(self.currentlayer.name() + 'が非アクティブになりました。')

        print(layer.name() + 'がアクティブになりました。')
        self.currentlayer = layer

    def start(self):
        self.currentlayer = self.iface.layerTreeView().currentLayer()
        self.iface.layerTreeView().currentLayerChanged.connect(
            self.changeLayer)

        maptool = self  # 場合によって書き換えて

        self.canvas.setMapTool(maptool)
        self.canvas.mapToolSet.connect(
            self.unsetTool)  # このサンプル実行中に他のアイコンを押した場合

    def finish(self):
        self.iface.layerTreeView().currentLayerChanged.disconnect(
            self.changeLayer)

        self.canvas.mapToolSet.disconnect(self.unsetTool)

    def __init__(self, iface):
        self.plugin_name = 'ダイアログ無し雛形'  # プラグイン名
        self.menu_pos = '雛形'  # プラグインの登録場所(このサンプルの場合、メニューの「プラグイン/雛形/ダイアログ無し雛形」)
        self.toolbar = True  # Trueならツールバーにアイコンを表示する
        self.checkable = True  # Trueならプラグイン実行中はアイコンが凹んだままになる

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

        QgsMapTool.__init__(self, self.canvas)

    # このプラグイン実行中に他のアイコンが押された場合、アイコンを元の状態に戻す
    def unsetTool(self, tool):
        if not isinstance(tool, LayerTreeViewSample):
            self.finish()
            self.action.setChecked(False)

    def initGui(self):
        icon = QIcon(os.path.dirname(__file__) + '/icon.png')
        self.action = QAction(icon, self.plugin_name, self.iface.mainWindow())
        self.action.triggered.connect(
            self.execSample)  # アイコンを押下した時に実行されるメソッドを登録
        self.action.setCheckable(
            self.checkable)  # Trueだとアイコンを押下したら次に押下するまで凹んだままになる
        if self.toolbar:
            self.iface.addToolBarIcon(self.action)  # ツールバーにこのツールのアイコンを表示する
        self.iface.addPluginToMenu(self.menu_pos, self.action)

    # このプラグインを無効にしたときに呼ばれる
    def unload(self):
        self.iface.removePluginMenu(self.menu_pos, self.action)
        self.iface.removeToolBarIcon(self.action)

    # このツールのアイコンを押下したときに呼ばれる
    def execSample(self):
        if self.checkable:
            if self.action.isChecked():  # 凹状態になった
                self.previousMapTool = self.canvas.mapTool()  # 現在のマップツールを退避
                self.start()
            else:  # 凸状態になった
                self.finish()
                self.canvas.setMapTool(self.previousMapTool)  # このツール実行前に戻す
        else:
            self.start()
class captureGPSFeatures(FieldRestrictionTypeUtilsMixin):

    def __init__(self, iface, featuresWithGPSToolbar):

        TOMsMessageLog.logMessage("In captureGPSFeatures::init", level=Qgis.Info)

        FieldRestrictionTypeUtilsMixin.__init__(self, iface)

        # Save reference to the QGIS interface
        self.iface = iface
        self.canvas = self.iface.mapCanvas()

        self.featuresWithGPSToolbar = featuresWithGPSToolbar
        self.gpsMapTool = False
        self.marker = None

        # This will set up the items on the toolbar
        # Create actions

        self.gnssToolGroup = QActionGroup(featuresWithGPSToolbar)
        self.actionCreateRestriction = QAction(QIcon(":/plugins/featureswithgps/resources/mActionAddTrack.svg"),
                               QCoreApplication.translate("MyPlugin", "Create Restriction"),
                               self.iface.mainWindow())
        self.actionCreateRestriction.setCheckable(True)

        self.actionAddGPSLocation = QAction(QIcon(":/plugins/featureswithgps/resources/greendot3.png"),
                               QCoreApplication.translate("MyPlugin", "Add vertex from gnss"),
                               self.iface.mainWindow())
        #self.actionAddGPSLocation.setCheckable(True)

        self.actionRemoveRestriction = QAction(QIcon(":plugins/featureswithgps/resources/mActionDeleteTrack.svg"),
                                        QCoreApplication.translate("MyPlugin", "Remove Restriction"),
                                        self.iface.mainWindow())
        self.actionRemoveRestriction.setCheckable(True)

        self.actionRestrictionDetails = QAction(QIcon(":/plugins/featureswithgps/resources/mActionGetInfo.svg"),
                                         QCoreApplication.translate("MyPlugin", "Get Restriction Details"),
                                         self.iface.mainWindow())
        self.actionRestrictionDetails.setCheckable(True)
        self.gnssToolGroup.addAction(self.actionRestrictionDetails)

        self.actionCreateSign = QAction(QIcon(":/plugins/featureswithgps/resources/mActionSetEndPoint.svg"),
                                                    QCoreApplication.translate("MyPlugin", "Create sign from gnss"),
                                                    self.iface.mainWindow())
        self.actionCreateSign.setCheckable(True)

        self.actionCreateMTR = QAction(QIcon(":/plugins/featureswithgps/resources/UK_traffic_sign_606F.svg"),
                                                    QCoreApplication.translate("MyPlugin", "Create moving traffic restriction"),
                                                    self.iface.mainWindow())
        self.actionCreateMTR.setCheckable(True)

        self.actionMoveFeatureToDifferentLayer = QAction(QIcon(""),
                                         QCoreApplication.translate("MyPlugin", "Move feature to different layer"),
                                         self.iface.mainWindow())
        self.actionMoveFeatureToDifferentLayer.setCheckable(True)
        self.gnssToolGroup.addAction(self.actionMoveFeatureToDifferentLayer)

        # Add actions to the toolbar

        self.featuresWithGPSToolbar.addAction(self.actionCreateRestriction)
        self.featuresWithGPSToolbar.addAction(self.actionAddGPSLocation)
        self.featuresWithGPSToolbar.addAction(self.actionRestrictionDetails)
        #self.featuresWithGPSToolbar.addAction(self.actionRemoveRestriction)
        self.featuresWithGPSToolbar.addAction(self.actionCreateSign)
        #self.featuresWithGPSToolbar.addAction(self.actionCreateMTR)
        self.featuresWithGPSToolbar.addAction(self.actionMoveFeatureToDifferentLayer)

        self.gnssToolGroup.addAction(self.actionCreateRestriction)
        #self.gnssToolGroup.addAction(self.actionAddGPSLocation)
        #self.gnssToolGroup.addAction(self.actionRemoveRestriction)
        self.gnssToolGroup.addAction(self.actionRestrictionDetails)
        #self.gnssToolGroup.addAction(self.actionCreateSign)
        #self.gnssToolGroup.addAction(self.actionCreateMTR)
        self.gnssToolGroup.addAction(self.actionMoveFeatureToDifferentLayer)

        self.gnssToolGroup.setExclusive(True)
        self.gnssToolGroup.triggered.connect(self.onGroupTriggered)

        # Connect action signals to slots

        self.actionCreateRestriction.triggered.connect(self.doCreateRestriction)
        self.actionAddGPSLocation.triggered.connect(self.doAddGPSLocation)
        self.actionRestrictionDetails.triggered.connect(self.doRestrictionDetails)
        #self.actionRemoveRestriction.triggered.connect(self.doRemoveRestriction)
        self.actionCreateSign.triggered.connect(self.doCreateSign)
        #self.actionCreateMTR.triggered.connect(self.doCreateMTR)
        self.actionMoveFeatureToDifferentLayer.triggered.connect(self.doMoveFeatureToDifferentLayer)

        self.actionCreateRestriction.setEnabled(False)
        self.actionAddGPSLocation.setEnabled(False)
        self.actionRestrictionDetails.setEnabled(False)
        #self.actionRemoveRestriction.setEnabled(False)
        self.actionCreateSign.setEnabled(False)
        #self.actionCreateMTR.setEnabled(False)
        self.actionMoveFeatureToDifferentLayer.setEnabled(False)

        self.searchBar = searchBar(self.iface, self.featuresWithGPSToolbar)
        self.searchBar.disableSearchBar()

        self.mapTool = None
        self.currGnssAction = None
        self.gpsConnection = None
        self.createMapToolDict = {}

    def enableFeaturesWithGPSToolbarItems(self):

        TOMsMessageLog.logMessage("In enablefeaturesWithGPSToolbarItems", level=Qgis.Warning)
        self.gpsAvailable = False
        self.closeTOMs = False

        self.tableNames = TOMsLayers(self.iface)
        self.params = gpsParams()

        self.tableNames.TOMsLayersNotFound.connect(self.setCloseTOMsFlag)
        #self.tableNames.gpsLayersNotFound.connect(self.setCloseCaptureGPSFeaturesFlag)
        self.params.TOMsParamsNotFound.connect(self.setCloseCaptureGPSFeaturesFlag)

        self.TOMsConfigFileObject = TOMsConfigFile()
        self.TOMsConfigFileObject.TOMsConfigFileNotFound.connect(self.setCloseTOMsFlag)
        self.TOMsConfigFileObject.initialiseTOMsConfigFile()

        self.tableNames.getLayers(self.TOMsConfigFileObject)

        self.prj = QgsProject().instance()
        self.dest_crs = self.prj.crs()
        TOMsMessageLog.logMessage("In captureGPSFeatures::init project CRS is " + self.dest_crs.description(),
                                 level=Qgis.Warning)
        self.transformation = QgsCoordinateTransform(QgsCoordinateReferenceSystem("EPSG:4326"), self.dest_crs,
                                                     self.prj)

        self.params.getParams()

        if self.closeTOMs:
            QMessageBox.information(self.iface.mainWindow(), "ERROR", ("Unable to start editing tool ..."))
            #self.actionProposalsPanel.setChecked(False)
            return   # TODO: allow function to continue without GPS enabled ...

        # Now check to see if the port is set. If not assume that just normal tools

        gpsPort = self.params.setParam("gpsPort")
        TOMsMessageLog.logMessage("In enableFeaturesWithGPSToolbarItems: GPS port is: {}".format(gpsPort), level=Qgis.Warning)
        self.gpsConnection = None

        if gpsPort:
            self.gpsAvailable = True

        if self.gpsAvailable == True:
            self.curr_gps_location = None
            self.curr_gps_info = None

            TOMsMessageLog.logMessage("In enableFeaturesWithGPSToolbarItems - GPS port is specified ",
                                     level=Qgis.Info)
            self.gps_thread = GPS_Thread(self.dest_crs, gpsPort)
            thread = QThread()
            self.gps_thread.moveToThread(thread)
            self.gps_thread.gpsActivated.connect(self.gpsStarted)
            self.gps_thread.gpsPosition.connect(self.gpsPositionProvided)
            self.gps_thread.gpsDeactivated.connect(functools.partial(self.gpsStopped))
            self.gps_thread.gpsError.connect(self.gpsErrorEncountered)
            #self.gps_thread.progress.connect(progressBar.setValue)
            thread.started.connect(self.gps_thread.startGPS)
            #thread.finished.connect(functools.partial(self.gpsStopped, thread))
            thread.start()
            self.thread = thread

            TOMsMessageLog.logMessage("In enableFeaturesWithGPSToolbarItems - attempting connection ",
                                     level=Qgis.Info)

            time.sleep(1.0)

            try:
                self.roamDistance = float(self.params.setParam("roamDistance"))
            except Exception as e:
                TOMsMessageLog.logMessage("In enableFeaturesWithGPSToolbarItems:init: roamDistance issue: {}".format(e), level=Qgis.Warning)
                self.roamDistance = 5.0

        self.enableToolbarItems()

        self.createMapToolDict = {}

    def enableToolbarItems(self):
        TOMsMessageLog.logMessage("In enableToolbarItems", level=Qgis.Warning)
        self.actionCreateRestriction.setEnabled(True)
        self.actionRestrictionDetails.setEnabled(True)
        #self.actionRemoveRestriction.setEnabled(True)
        #self.actionCreateSign.setEnabled(True)
        #self.actionCreateMTR.setEnabled(True)
        self.actionMoveFeatureToDifferentLayer.setEnabled(True)

        self.searchBar.enableSearchBar()

        self.currMapTool = None
        self.theCurrentMapTool = None

        self.iface.currentLayerChanged.connect(self.changeCurrLayer2)
        self.canvas.mapToolSet.connect(self.changeMapTool2)
        self.canvas.extentsChanged.connect(self.changeExtents)

        # transaction for move ...
        self.localTransaction = MoveLayerTransaction(self.iface)

    def enableGnssToolbarItem(self):
        if self.gpsConnection:
            self.actionAddGPSLocation.setEnabled(True)
            self.actionCreateSign.setEnabled(True)
            self.lastCentre = QgsPointXY(0,0)

    def disableGnssToolbarItem(self):
        self.actionAddGPSLocation.setEnabled(False)
        self.actionCreateSign.setEnabled(False)

    def disableToolbarItems(self):

        self.actionCreateRestriction.setEnabled(False)
        self.actionRestrictionDetails.setEnabled(False)
        self.actionRemoveRestriction.setEnabled(False)
        self.actionCreateSign.setEnabled(False)
        #self.actionCreateMTR.setEnabled(False)
        self.actionMoveFeatureToDifferentLayer.setEnabled(False)

        self.searchBar.disableSearchBar()

        """if self.gpsConnection:
            self.actionAddGPSLocation.setEnabled(False)"""

    def setCloseTOMsFlag(self):
        self.closeTOMs = True
        QMessageBox.information(self.iface.mainWindow(), "ERROR", ("Now closing TOMs ..."))

    def disableFeaturesWithGPSToolbarItems(self):

        TOMsMessageLog.logMessage("In disablefeaturesWithGPSToolbarItems", level=Qgis.Warning)
        if self.gpsConnection and not self.closeTOMs:
            self.gps_thread.endGPS()

        self.disableToolbarItems()

        # TODO: Need to delete any tools ...
        for layer, mapTool in self.createMapToolDict.items  ():
            try:
                status = layer.rollBack()
            except Exception as e:
                None
                """reply = QMessageBox.information(None, "Information",
                                                    "Problem rolling back changes" + str(self.currLayer.commitErrors()),
                                                    QMessageBox.Ok)"""
            del mapTool

        self.createMapToolDict = {}

        try:
            self.iface.currentLayerChanged.disconnect(self.changeCurrLayer2)
        except Exception as e:
            TOMsMessageLog.logMessage(
                "In disableFeaturesWithGPSToolbarItems. Issue with disconnects for currentLayerChanged {}".format(e),
                level=Qgis.Warning)

        try:
            self.canvas.mapToolSet.disconnect(self.changeMapTool2)
        except Exception as e:
            TOMsMessageLog.logMessage(
                "In disableFeaturesWithGPSToolbarItems. Issue with disconnects for mapToolSet {}".format(
                    e),
                level=Qgis.Warning)

        try:
            self.canvas.extentsChanged.disconnect(self.changeExtents)
        except Exception as e:
            TOMsMessageLog.logMessage(
                "In disableFeaturesWithGPSToolbarItems. Issue with disconnects for extentsChanged {}".format(
                    e),
                level=Qgis.Warning)

        self.tableNames.removePathFromLayerForms()

    def setCloseCaptureGPSFeaturesFlag(self):
        self.closeCaptureGPSFeatures = True
        self.gpsAvailable = True

    def onGroupTriggered(self, action):
        # hold the current action
        self.currGnssAction = action
        TOMsMessageLog.logMessage("In onGroupTriggered: curr action is {}".format(action.text()), level=Qgis.Info)

    """ 
        Using signals for ChangeTool and ChangeLayer to manage the tools - with the following functions
    """
    def isGnssTool(self, mapTool):

        if (isinstance(mapTool, CreateRestrictionTool) or
           isinstance(mapTool, GeometryInfoMapTool) or
           isinstance(mapTool, RemoveRestrictionTool)):
            return True

        return False

    def changeMapTool2(self):
        TOMsMessageLog.logMessage(
            "In changeMapTool2 ...", level=Qgis.Info)

        currMapTool = self.iface.mapCanvas().mapTool()

        if not self.isGnssTool(currMapTool):
            TOMsMessageLog.logMessage(
                "In changeMapTool2. Unchecking action ...", level=Qgis.Info)
            if self.currGnssAction:
                self.currGnssAction.setChecked(False)
        else:
            TOMsMessageLog.logMessage(
            "In changeMapTool2. No action for gnssTools.", level=Qgis.Info)

        TOMsMessageLog.logMessage(
            "In changeMapTool2. finished.", level=Qgis.Info)
        #print('tool unset')

    def changeCurrLayer2(self):
        TOMsMessageLog.logMessage("In changeLayer2 ... ", level=Qgis.Info)

        try:
            currMapTool = self.iface.mapCanvas().mapTool()
            self.currGnssAction.setChecked(False)
        except Exception as e:
            None

        """if self.isGnssTool(currMapTool):
            TOMsMessageLog.logMessage("In changeLayer2. Action triggered ... ", level=Qgis.Info)
            self.currGnssAction.trigger()  # assumption is that there is an action associated with the tool
        else:
            TOMsMessageLog.logMessage(
            "In changeLayer2. No action for currentMapTool.", level=Qgis.Info)"""

        TOMsMessageLog.logMessage(
            "In changeLayer2. finished.", level=Qgis.Info)
        print('layer changed')


    def doCreateRestriction(self):

        TOMsMessageLog.logMessage("In doCreateRestriction", level=Qgis.Info)

        self.currLayer = self.iface.activeLayer()
        if not self.currLayer:
            reply = QMessageBox.information(self.iface.mainWindow(), "Information", "Please choose a layer ...",
                                            QMessageBox.Ok)
            return

        # TODO: Check that this is a restriction layer

        if self.actionCreateRestriction.isChecked():

            TOMsMessageLog.logMessage("In doCreateRestriction - tool activated", level=Qgis.Info)
            TOMsMessageLog.logMessage(
                "In doCreateRestriction: current map tool {}".format(type(self.iface.mapCanvas().mapTool()).__name__),
                level=Qgis.Info)

            self.createRestrictionMapTool = self.createMapToolDict.get(self.currLayer)

            if not self.createRestrictionMapTool:
                TOMsMessageLog.logMessage("In doCreateRestriction. creating new map tool", level=Qgis.Info)
                self.createRestrictionMapTool = CreateRestrictionTool(self.iface, self.currLayer)
                self.createMapToolDict[self.currLayer] = self.createRestrictionMapTool

            TOMsMessageLog.logMessage("In doCreateRestriction. Here 1", level=Qgis.Info)

            self.iface.mapCanvas().setMapTool(self.createRestrictionMapTool)

            TOMsMessageLog.logMessage("In doCreateRestriction. Here 2", level=Qgis.Info)

            if not self.createRestrictionMapTool.isCapturing():
                if self.currLayer.isEditable() == True:
                    if self.currLayer.commitChanges() == False:
                        reply = QMessageBox.information(None, "Information",
                                                        "Problem committing changes" + str(self.currLayer.commitErrors()),
                                                        QMessageBox.Ok)
                    else:
                        TOMsMessageLog.logMessage("In doCreateRestriction: changes committed", level=Qgis.Info)

                if self.currLayer.readOnly() == True:
                    TOMsMessageLog.logMessage("In doCreateRestriction - Not able to start transaction ...",
                                             level=Qgis.Info)
                else:
                    if self.currLayer.startEditing() == False:
                        reply = QMessageBox.information(None, "Information",
                                                        "Could not start transaction on " + self.currLayer.name(),
                                                        QMessageBox.Ok)
                        return

            TOMsMessageLog.logMessage("In doCreateRestriction. Here 3", level=Qgis.Info)

        else:

            TOMsMessageLog.logMessage("In doCreateRestriction - tool deactivated", level=Qgis.Info)

            if self.createRestrictionMapTool:
                self.iface.mapCanvas().unsetMapTool(self.createRestrictionMapTool)

            self.currMapTool = None
            self.currentlySelectedLayer = None

            self.actionCreateRestriction.setChecked(False)

            # TODO: stop editting on layers??

        TOMsMessageLog.logMessage("In doCreateRestriction. Here 4", level=Qgis.Info)



    # -- end of tools for signals

    def changeExtents(self):
        TOMsMessageLog.logMessage("In changeExtents ... ", level=Qgis.Info)

    def doAddGPSLocation(self):

        # need to have a addPointFromGPS function within each tool

        TOMsMessageLog.logMessage("In doAddGPSLocation", level=Qgis.Info)

        if self.gpsConnection:

            if self.curr_gps_location:
                try:
                    status = self.createRestrictionMapTool.addPointFromGPS(self.curr_gps_location, self.curr_gps_info)
                except Exception as e:
                    TOMsMessageLog.logMessage("In doAddGPSLocation: Problem adding gnss location: {}".format(e), level=Qgis.Warning)
                    reply = QMessageBox.information(self.iface.mainWindow(), "Error",
                                                    "Problem adding gnss location ... ",
                                                    QMessageBox.Ok)
            else:
                reply = QMessageBox.information(self.iface.mainWindow(), "Information",
                                                "No position found ...",
                                                QMessageBox.Ok)
        else:

            reply = QMessageBox.information(self.iface.mainWindow(), "Information", "You need to activate the tool first ...",
                                            QMessageBox.Ok)

    def doRestrictionDetails(self):
        """
            Select point and then display details. Assume that there is only one of these map tools in existence at any one time ??
        """
        TOMsMessageLog.logMessage("In doRestrictionDetails", level=Qgis.Info)

        # TODO: Check whether or not there is a create maptool available. If so, stop this and finish using that/those tools

        if not self.iface.activeLayer():
            reply = QMessageBox.information(self.iface.mainWindow(), "Information", "Please choose a layer ...",
                                            QMessageBox.Ok)
            return

        if self.actionRestrictionDetails.isChecked():

            TOMsMessageLog.logMessage("In doRestrictionDetails - tool activated", level=Qgis.Warning)

            self.showRestrictionMapTool = GeometryInfoMapTool(self.iface)
            self.iface.mapCanvas().setMapTool(self.showRestrictionMapTool)
            self.showRestrictionMapTool.notifyFeatureFound.connect(self.showRestrictionDetails)

        else:

            TOMsMessageLog.logMessage("In doRestrictionDetails - tool deactivated", level=Qgis.Warning)

            if self.showRestrictionMapTool:
                self.iface.mapCanvas().unsetMapTool(self.showRestrictionMapTool)

            self.actionRestrictionDetails.setChecked(False)

    #@pyqtSlot(str)
    def showRestrictionDetails(self, closestLayer, closestFeature):

        TOMsMessageLog.logMessage(
            "In showRestrictionDetails ... Layer: " + str(closestLayer.name()),
            level=Qgis.Info)

        self.showRestrictionMapTool.notifyFeatureFound.disconnect(self.showRestrictionDetails)

        # TODO: could improve ... basically check to see if transaction in progress ...
        if closestLayer.isEditable() == True:
            reply = QMessageBox.question(None, "Information",
                                            "There is a transaction in progress on this layer. This action will rollback back any changes. Do you want to continue?",
                                            QMessageBox.Yes, QMessageBox.No)
            if reply == QMessageBox.No:
                return
            if closestLayer.commitChanges() == False:
                reply = QMessageBox.information(None, "Information",
                                                "Problem committing changes" + str(closestLayer.commitErrors()),
                                                QMessageBox.Ok)
            else:
                TOMsMessageLog.logMessage("In showRestrictionDetails: changes committed", level=Qgis.Info)

        """if self.iface.activeLayer().readOnly() == True:
            TOMsMessageLog.logMessage("In showSignDetails - Not able to start transaction ...",
                                     level=Qgis.Info)
        else:
            if self.iface.activeLayer().startEditing() == False:
                reply = QMessageBox.information(None, "Information",
                                                "Could not start transaction on " + self.currLayer.name(),
                                                QMessageBox.Ok)
                return"""

        self.dialog = self.iface.getFeatureForm(closestLayer, closestFeature)
        #self.TOMsUtils.setupRestrictionDialog(self.dialog, closestLayer, closestFeature)
        self.setupFieldRestrictionDialog(self.dialog, closestLayer, closestFeature)

        self.dialog.show()

    """
        Decided that it is best to use the QGIS select/delete tools to manage removals. So these functions are not used
    """
    def doRemoveRestriction(self):

        TOMsMessageLog.logMessage("In doRemoveRestriction", level=Qgis.Info)

        self.currLayer = self.iface.activeLayer()

        if not self.currLayer:
            reply = QMessageBox.information(self.iface.mainWindow(), "Information", "Please choose a layer ...",
                                            QMessageBox.Ok)
            return

        if self.currLayer.readOnly() == True:
            """reply = QMessageBox.information(None, "Information",
                                            "Could not start transaction on " + self.currLayer.name(), QMessageBox.Ok)"""
            TOMsMessageLog.logMessage("In doRemoveRestriction - Not able to start transaction ...", level=Qgis.Info)
            self.actionRemoveRestriction.setChecked(False)
            return

        if self.actionRemoveRestriction.isChecked():

            TOMsMessageLog.logMessage("In doRemoveRestriction - tool activated", level=Qgis.Warning)

            """self.mapTool = self.deleteMapToolDict.get(self.currLayer)

            if not self.mapTool:
                self.mapTool = RemoveRestrictionTool(self.iface)
                self.deleteMapToolDict[self.currLayer] =  self.mapTool"""

            self.mapTool = RemoveRestrictionTool(self.iface)
            #self.removeRestrictionMapTool.setAction(self.actionRemoveRestriction)
            self.iface.mapCanvas().setMapTool(self.removeRestrictionMapTool)
            #self.gpsMapTool = True
            #self.removeRestrictionMapTool.deactivated.connect(functools.partial(self.deactivateAction, self.actionRemoveRestriction))
            #self.iface.currentLayerChanged.connect(self.changeCurrLayer)
            #self.canvas.mapToolSet.connect(self.changeMapTool)

            self.removeRestrictionMapTool.notifyFeatureFound.connect(self.removeRestriction)

        else:

            TOMsMessageLog.logMessage("In doRemoveRestriction - tool deactivated", level=Qgis.Warning)

            self.removeRestrictionMapTool.notifyFeatureFound.disconnect(self.removeRestriction)

            #self.canvas.mapToolSet.disconnect(self.changeMapTool)
            #self.iface.currentLayerChanged.disconnect(self.changeCurrLayer)

            self.iface.mapCanvas().unsetMapTool(self.removeRestrictionMapTool)
            #self.removeRestrictionMapTool.deactivate()
            #self.mapTool = None
            self.actionRemoveRestriction.setChecked(False)

    #@pyqtSlot(str)
    def removeRestriction(self, closestLayer, closestFeature):

        TOMsMessageLog.logMessage(
            "In removeRestriction ... Layer: " + str(closestLayer.name()),
            level=Qgis.Info)

        if closestLayer.isEditable() == True:
            if closestLayer.commitChanges() == False:
                reply = QMessageBox.information(None, "Information",
                                                "Problem committing changes" + str(closestLayer.commitErrors()),
                                                QMessageBox.Ok)
            else:
                TOMsMessageLog.logMessage("In removeRestriction: changes committed", level=Qgis.Info)

        if self.currLayer.startEditing() == False:
            reply = QMessageBox.information(None, "Information",
                                            "Could not start transaction on " + self.currLayer.name(),
                                            QMessageBox.Ok)
            return

        # TODO: Sort out this for UPDATE
        # self.setDefaultRestrictionDetails(closestFeature, closestLayer)

        closestLayer.deleteFeature(closestFeature.id())

        if closestLayer.commitChanges() == False:
            reply = QMessageBox.information(None, "Information",
                                            "Problem committing changes" + str(closestLayer.commitErrors()),
                                            QMessageBox.Ok)
        else:
            TOMsMessageLog.logMessage("In removeRestriction: changes committed", level=Qgis.Info)

    """
        This is a tool for adding a point feature. currently only used for signs, but could be used for any point
    """
    def doCreateSign(self):

        TOMsMessageLog.logMessage("In doCreateSign", level=Qgis.Info)

        if self.actionCreateSign.isChecked():

            self.currMapTool = self.canvas.mapTool()
            self.currentlySelectedLayer = self.iface.activeLayer()
            self.signsLayer = self.tableNames.setLayer("Signs")

            self.iface.setActiveLayer(self.signsLayer)

            self.createPointMapTool = CreatePointTool(self.iface, self.signsLayer)

            TOMsMessageLog.logMessage("In doCreateSign - tool activated", level=Qgis.Info)

            self.signsLayer.editingStopped.connect(self.reinstateMapTool)

            self.actionCreateSign.setChecked(False)

            self.iface.mapCanvas().setMapTool(self.createPointMapTool)

            """ add the point from the gnss """
            try:
                status = self.canvas.mapTool().addPointFromGPS(self.curr_gps_location, self.curr_gps_info)
            except Exception as e:
                TOMsMessageLog.logMessage("In doCreateSign: Problem adding gnss location: {}".format(e),
                                          level=Qgis.Warning)
                reply = QMessageBox.information(self.iface.mainWindow(), "Error",
                                                "Problem adding gnss location ... ",
                                                QMessageBox.Ok)

    """
        Not currently used, but want to develop ...
    """
    def doCreateMTR(self):

        TOMsMessageLog.logMessage("In doCreateMTR", level=Qgis.Info)

        if self.actionCreateMTR.isChecked():

            TOMsMessageLog.logMessage("In doCreateMTR - tool activated", level=Qgis.Info)

            # Open MTR form ...

            try:
                self.thisMtrForm
            except AttributeError:
                self.thisMtrForm = mtrForm(self.iface)

            #res = mtrFormFactory.prepareForm(self.iface, self.dbConn, self.dialog)
            #self.mtrTypeCB = self.dialog.findChild(QComboBox, "cmb_MTR_list")
            #self.mtrTypeCB.activated[str].connect(self.onLocalChanged)
            #self.currDialog.findChild(QComboBox, "cmb_MTR_list").activated[str].connect(self.onChanged)


            """ Need to setup dialog:
                a. create drop down
                b. link structure of form to different options from drop down, e.g., Access Restriction needs ?? attributes and one point, Turn Restriction needs ?? attributes and two points
                c. link getPoint actions to buttons
            """
            status = self.thisMtrForm.show()
            # Run the dialog event loop
            result = self.thisMtrForm.exec_()
            #

        else:

            TOMsMessageLog.logMessage("In doCreateMTR - tool deactivated", level=Qgis.Info)

            #self.iface.mapCanvas().unsetMapTool(self.mapTool)
            #self.mapTool = None
            self.actionCreateMTR.setChecked(False)
            self.gpsMapTool = False

    def onLocalChanged(self, text):
        TOMsMessageLog.logMessage(
            "In generateFirstStageForm::selectionchange.  " + text, level=Qgis.Info)
        res = mtrFormFactory.prepareForm(self.iface, self.dbConn, self.dialog, text)

    """
        Used with the createSign tool to reinstate the last used maptool, i.e., to allow the interupt of feature creation
    """

    def reinstateMapTool(self):

        TOMsMessageLog.logMessage("In reinstateMapTool ... ", level=Qgis.Info)
        self.iface.activeLayer().editingStopped.disconnect(self.reinstateMapTool)

        if self.currMapTool:

            TOMsMessageLog.logMessage(
                "In reinstateMapTool. layer to be reinstated {} using tool {}".format(self.currentlySelectedLayer.name(), self.currMapTool.toolName()),
                level=Qgis.Warning)
            # now reinstate
            if self.currentlySelectedLayer:
                self.iface.setActiveLayer(self.currentlySelectedLayer)

            self.iface.mapCanvas().setMapTool(self.currMapTool)


    def doMoveFeatureToDifferentLayer(self):
        """
            Select point and then display details. Assume that there is only one of these map tools in existence at any one time ??
        """
        TOMsMessageLog.logMessage("In doMoveFeatureToDifferentLayer", level=Qgis.Info)

        # TODO: Check whether or not there is a create maptool available. If so, stop this and finish using that/those tools

        if not self.iface.activeLayer():
            reply = QMessageBox.information(self.iface.mainWindow(), "Information", "Please choose a layer ...",
                                            QMessageBox.Ok)
            return

        if self.actionMoveFeatureToDifferentLayer.isChecked():

            TOMsMessageLog.logMessage("In doMoveFeatureToDifferentLayer - tool activated", level=Qgis.Warning)

            self.moveFeatureToDifferentLayerMapTool = ChangeLayerMapTool(self.iface, self.localTransaction)
            self.iface.mapCanvas().setMapTool(self.moveFeatureToDifferentLayerMapTool)
            #self.showRestrictionMapTool.notifyFeatureFound.connect(self.showRestrictionDetails)

        else:

            TOMsMessageLog.logMessage("In doMoveFeatureToDifferentLayer - tool deactivated", level=Qgis.Warning)

            if self.moveFeatureToDifferentLayerMapTool:
                self.iface.mapCanvas().unsetMapTool(self.moveFeatureToDifferentLayerMapTool)

            self.actionMoveFeatureToDifferentLayer.setChecked(False)


    #@pyqtSlot(QgsGpsConnection)
    def gpsStarted(self, connection):
        TOMsMessageLog.logMessage("In enableTools - GPS connection found ",
                                     level=Qgis.Info)

        self.gpsConnection = connection

        # marker
        self.marker = QgsVertexMarker(self.canvas)
        self.marker.setColor(QColor(255, 0, 0))  # (R,G,B)
        self.marker.setIconSize(10)
        self.marker.setIconType(QgsVertexMarker.ICON_CIRCLE)
        self.marker.setPenWidth(3)

        self.enableGnssToolbarItem()
        reply = QMessageBox.information(None, "Information",
                                            "Connection found",
                                            QMessageBox.Ok)

    #@pyqtSlot()
    def gpsStopped(self):
        TOMsMessageLog.logMessage("In enableTools - GPS connection stopped ",
                                     level=Qgis.Warning)

        self.gps_thread.deleteLater()
        self.thread.quit()
        self.thread.wait()
        self.thread.deleteLater()

        if self.gpsConnection:
            if self.canvas is not None:
                self.marker.hide()
                self.canvas.scene().removeItem(self.marker)

        self.gpsConnection = None
        self.disableGnssToolbarItem()

    #@pyqtSlot()
    def gpsPositionProvided(self, mapPointXY, gpsInfo):
        """reply = QMessageBox.information(None, "Information",
                                            "Position provided",
                                            QMessageBox.Ok)"""
        TOMsMessageLog.logMessage("In enableTools - ******** initial GPS location provided " + mapPointXY.asWkt(),
                                     level=Qgis.Info)

        self.curr_gps_location = mapPointXY
        self.curr_gps_info = gpsInfo

        wgs84_pointXY = QgsPointXY(gpsInfo.longitude, gpsInfo.latitude)
        wgs84_point = QgsPoint(wgs84_pointXY)
        wgs84_point.transform(self.transformation)
        x = wgs84_point.x()
        y = wgs84_point.y()
        new_mapPointXY = QgsPointXY(x, y)

        TOMsMessageLog.logMessage("In enableTools - ******** transformed GPS location provided " + str(gpsInfo.longitude) + ":" + str(gpsInfo.latitude) + "; " + new_mapPointXY.asWkt(),
                                     level=Qgis.Info)

        if gpsInfo.pdop >= 1:  # gps ok
            self.marker.setColor(QColor(0, 200, 0))
        else:
            self.marker.setColor(QColor(255, 0, 0))
        self.marker.setCenter(mapPointXY)
        self.marker.show()
        #self.canvas.setCenter(mapPointXY)

        """TOMsMessageLog.logMessage("In enableTools: distance from last fix: {}".format(self.lastCentre.distance(mapPointXY)),
                                     level=Qgis.Info)"""
        if self.lastCentre.distance(mapPointXY) > self.roamDistance:
            self.lastCentre = mapPointXY
            self.canvas.setCenter(mapPointXY)
            TOMsMessageLog.logMessage(
                "In enableTools: distance from last fix: {}".format(self.lastCentre.distance(mapPointXY)),
                level=Qgis.Warning)
            self.canvas.refresh()

        # TODO: populate message bar with details about satellites, etc

    #@pyqtSlot(Exception, str)
    def gpsErrorEncountered(self, e):
        TOMsMessageLog.logMessage("In enableTools - GPS connection has error {}".format(e),
                                     level=Qgis.Warning)
        """self.actionCreateRestriction.setEnabled(False)
        self.actionAddGPSLocation.setEnabled(False)"""
        self.disableGnssToolbarItem()
class MultiObjectEditSample(QgsMapTool):

    def selectedFeature(self, feature):        
        self.maptool.setFeature(feature)


    def start(self):
        self.maptool = MultiObjectEditClass(self.iface, self.canvas, 'move') # 移動の場合
        self.maptool.setLayer(self.iface.activeLayer())
        self.maptool.featureIdentified.connect(self.selectedFeature)

        self.canvas.setMapTool(self.maptool)
        self.canvas.mapToolSet.connect(self.unsetTool) # このサンプル実行中に他のアイコンを押した場合


    def finish(self):
        self.canvas.mapToolSet.disconnect(self.unsetTool)


    def __init__(self, iface):
        self.plugin_name = 'マルチオブジェクト編集サンプル' # プラグイン名
        self.menu_pos    = 'サンプル'               # プラグインの登録場所(このサンプルの場合、メニューの「プラグイン/雛形/ダイアログ無し雛形」)
        self.toolbar     = True                 # Trueならツールバーにアイコンを表示する
        self.checkable   = True                 # Trueならプラグイン実行中はアイコンが凹んだままになる

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

        QgsMapTool.__init__(self, self.canvas)


    # このプラグイン実行中に他のアイコンが押された場合、アイコンを元の状態に戻す
    def unsetTool(self, tool):
        if not isinstance(tool, MultiObjectEditSample):
            self.finish()
            self.action.setChecked(False)


    def initGui(self):
        icon = QIcon(os.path.dirname(__file__)+'/icon.png')
        self.action = QAction(icon, self.plugin_name, self.iface.mainWindow())
        self.action.triggered.connect(self.execSample) # アイコンを押下した時に実行されるメソッドを登録
        self.action.setCheckable(self.checkable)       # Trueだとアイコンを押下したら次に押下するまで凹んだままになる
        if self.toolbar:
            self.iface.addToolBarIcon(self.action)     # ツールバーにこのツールのアイコンを表示する
        self.iface.addPluginToMenu(self.menu_pos, self.action)
        

    # このプラグインを無効にしたときに呼ばれる
    def unload(self):
        self.iface.removePluginMenu(self.menu_pos, self.action)
        self.iface.removeToolBarIcon(self.action)


    # このツールのアイコンを押下したときに呼ばれる
    def execSample(self):
        if self.checkable:
            if self.action.isChecked(): # 凹状態になった
                self.previousMapTool = self.canvas.mapTool()  # 現在のマップツールを退避
                self.start()
            else:                       # 凸状態になった
                self.finish()
                self.canvas.setMapTool(self.previousMapTool)  # このツール実行前に戻す
        else:
            self.start()
Beispiel #9
0
class GraphSample(QgsMapTool):

    # lineLLを垂直に横断する点列を作成する
    def addOdansen(self, lineLL, key):

        def angle(a, b):
            return math.atan2(b.y() - a.y(), b.x() - a.x())

        # startからrad方向にn進んだ位置を返す
        def destination(start, rad, n):
            return QgsPointXY(n * math.cos(rad) + start.x(), n * math.sin(rad) + start.y())

        def transformCRS(obj, src, dst):
            newobj = QgsGeometry(obj)
            srcCrs = QgsCoordinateReferenceSystem(src)
            dstCrs = QgsCoordinateReferenceSystem(dst)
            tr = QgsCoordinateTransform(srcCrs, dstCrs, QgsProject.instance())
            newobj.transform(tr)
            return newobj

        # startpnt、endpntが成す線分の、startpntからlength分進んだ位置を中心に、線分を横断する線を作成する。
        # cntは番号付けのために使っている。
        def odansen(startpnt, endpnt, length, cnt):
            center = destination(startpnt, angle(startpnt, endpnt), length)
            rad = angle(startpnt, endpnt) + (-90 * math.pi / 180)

            for i in range(-self._odanlinelength, self._odanlinelength + self._odanpointspan, self._odanpointspan):
                xypnt = QgsGeometry().fromPointXY(destination(center, rad, i))
                llpnt = transformCRS(xypnt, self._xycrs, self._llcrs)

                elev = self.gr.getValueInterpolation(llpnt.asPoint())
                self.addFeature(self.hol, llpnt, [key, cnt, i, elev])

         
        lineXY = transformCRS(lineLL, self._llcrs, self._xycrs) # 描画したラインは緯度経度の座標なので、平面直角座標に変換する
        judanLen = lineXY.length()
        pnts = [pnt for pnt in lineXY.asPolyline()]

        # 縦断線の始点を横断する線
        odansen(pnts[0], pnts[1], 0, 0)

        cnt = 1
        nextpos = self._odanlinespan * cnt

        while judanLen > nextpos:

            for i in range(1, len(pnts)):

                nodelength = pnts[i-1].distance(pnts[i])
                # この線分上に横断線引ける?
                # 引けない
                if (nextpos - nodelength) > 0:
                    nextpos -= nodelength
                # 引ける
                else:
                    odansen(pnts[i - 1], pnts[i], nextpos, cnt)

                    cnt += 1
                    nextpos = self._odanlinespan * cnt
                    break

        # 縦断線の終点を横断する線
        odansen(pnts[-2], pnts[-1], pnts[-1].distance(pnts[-2]), cnt)


    def setFeature(self, geom):
        def getNumber(feature):
            return feature['pointcount']

        key = datetime.datetime.now().strftime('%Y%m%d%H%M%S') # 縦断線と横断線を紐付けるキー
        self.addFeature(self.ver, geom, [key]) # 縦断線レイヤに、描画したラインを追加
        self.addOdansen(geom, key)             # 描画したラインを横断する点列を横断戦レイヤに追加
        
        # グラフ作成
        features = list(self.hol.getFeatures(QgsFeatureRequest().setFilterExpression('"key"='+'\'' + key + '\'')))
        linenumbers = sorted(set([f['linecount'] for f in features]))
        for linenumber in linenumbers:
            linenode = sorted([f for f in features if f['linecount'] == linenumber], key=getNumber) # 'pointcount'の値順に並び変える

            fig, ax = plt.subplots()
            y = np.array([l['elev'] for l in linenode])
            x = np.array([l['pointcount'] for l in linenode])
            ax.set_title(str(linenode[0]['key']) + '_' + str(linenumber))
            ax.plot(x, y, '-')
            plt.savefig(self._savedir + str(linenode[0]['key']) + '_' + str(linenumber) + '.png')


    # 一時レイヤ作成
    def createTemporaryLayer(self, layername, type, fieldsstr):
        epsg = self.iface.mapCanvas().mapSettings().destinationCrs().authid()
        layer = QgsVectorLayer(type + '?&crs='+epsg+fieldsstr, layername, 'memory')

        QgsProject.instance().addMapLayer(layer)
        return layer


    # レイヤにレコード追加
    def addFeature(self, layer, geometry, attrs):
        qf = QgsFields()
        for field in layer.fields():
            qf.append(QgsField(str(field.name()), typeName=field.typeName()))
        record = QgsFeature(qf) 

        # 地物をセットする
        record.setGeometry(geometry) 

        # 属性をセットする
        record.setAttributes(attrs)

        # 作成したレコードをレイヤに追加
        layer.dataProvider().addFeatures([record])
        layer.updateExtents() # これが無いと『レイヤの領域にズーム』した時に、レイヤの最初のオブジェクト部分しかズームされない

        self.canvas.refreshAllLayers()


    def start(self):
        # このプログラム使うときはこの辺を調整してください
        self._llcrs = 4326
        self._xycrs = 2451 # 千葉県のDEMでテストしたので9系になってます。
        self._savedir = 'c:\\users\\〇〇\\desktop\\pic\\' # 横断図の保存先
        self._odanlinespan   = 100 # 横断線の間隔
        self._odanlinelength = 200 # 横断線の片側の長さ
        self._odanpointspan  = 10  # 横断線上のサンプリング間隔

        layer = self.iface.activeLayer()
        if type(layer) != qgis.core.QgsRasterLayer:
            QMessageBox.about(None, 'エラー', 'ラスタレイヤを選択してから実行してください。')
            self.action.setChecked(False)
            self.canvas.setMapTool(self.previousMapTool)  # このツール実行前に戻す
            return
        self.gr = GetRasterPixelValue(layer)

        maptool = RubberBand(self.iface, self.canvas, QgsWkbTypes.LineGeometry)
        maptool.getObject.connect(self.setFeature)

        if len(QgsProject.instance().mapLayersByName('縦断線')) == 0:
            self.ver = self.createTemporaryLayer('縦断線', 'LineString', '&field=key:string')
        else:
            self.ver = QgsProject.instance().mapLayersByName('縦断線')[0]

        if len(QgsProject.instance().mapLayersByName('横断線')) == 0:
            self.hol = self.createTemporaryLayer('横断線', 'Point', '&field=key:string&field=linecount:integer&field=pointcount:integer&field=elev:double')
        else:
            self.hol = QgsProject.instance().mapLayersByName('横断線')[0]

        self.canvas.setMapTool(maptool)
        self.canvas.mapToolSet.connect(self.unsetTool) # このサンプル実行中に他のアイコンを押した場合


    def finish(self):
    
        self.ver = None
        self.hol = None
        self.gr = None

        self.canvas.mapToolSet.disconnect(self.unsetTool)


    def __init__(self, iface):
        self.plugin_name = 'グラフサンプル' # プラグイン名
        self.menu_pos    = 'サンプル'               # プラグインの登録場所(このサンプルの場合、メニューの「プラグイン/雛形/ダイアログ無し雛形」)
        self.toolbar     = True                 # Trueならツールバーにアイコンを表示する
        self.checkable   = True                 # Trueならプラグイン実行中はアイコンが凹んだままになる

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

        QgsMapTool.__init__(self, self.canvas)


    # このプラグイン実行中に他のアイコンが押された場合、アイコンを元の状態に戻す
    def unsetTool(self, tool):
        if not isinstance(tool, GraphSample):
            self.finish()
            self.action.setChecked(False)


    def initGui(self):
        icon = QIcon(os.path.dirname(__file__)+'/icon.png')
        self.action = QAction(icon, self.plugin_name, self.iface.mainWindow())
        self.action.triggered.connect(self.execSample) # アイコンを押下した時に実行されるメソッドを登録
        self.action.setCheckable(self.checkable)       # Trueだとアイコンを押下したら次に押下するまで凹んだままになる
        if self.toolbar:
            self.iface.addToolBarIcon(self.action)     # ツールバーにこのツールのアイコンを表示する
        self.iface.addPluginToMenu(self.menu_pos, self.action)
        

    # このプラグインを無効にしたときに呼ばれる
    def unload(self):
        self.iface.removePluginMenu(self.menu_pos, self.action)
        self.iface.removeToolBarIcon(self.action)


    # このツールのアイコンを押下したときに呼ばれる
    def execSample(self):
        if self.checkable:
            if self.action.isChecked(): # 凹状態になった
                self.previousMapTool = self.canvas.mapTool()  # 現在のマップツールを退避
                self.start()
            else:                       # 凸状態になった
                self.finish()
                self.canvas.setMapTool(self.previousMapTool)  # このツール実行前に戻す
        else:
            self.start()
Beispiel #10
0
class featuresWithGPS:
    """QGIS Plugin Implementation."""
    def __init__(self, iface):

        QgsMessageLog.logMessage("Starting featuresWithGPS ... ",
                                 tag="TOMs panel")
        """Constructor.
        
        :param iface: An interface instance that will be passed to this class
            which provides the hook by which you can manipulate the QGIS
            application at run time.
        :type iface: QgsInterface
        """
        # Save reference to the QGIS interface
        self.iface = iface
        # initialize plugin directory
        self.plugin_dir = os.path.dirname(__file__)

        self.actions = []  # ?? check - assume it initialises array of actions

        self.closeGPSToolsFlag = False
        # Set up log file and collect any relevant messages
        logFilePath = os.environ.get('QGIS_LOGFILE_PATH')

        if logFilePath:

            QgsMessageLog.logMessage("LogFilePath: " + str(logFilePath),
                                     tag="TOMs panel")

            logfile = 'qgis_' + datetime.date.today().strftime(
                "%Y%m%d") + '.log'
            self.filename = os.path.join(logFilePath, logfile)
            QgsMessageLog.logMessage("Sorting out log file" + self.filename,
                                     tag="TOMs panel")
            QgsApplication.instance().messageLog().messageReceived.connect(
                self.write_log_message)

        # Set up local logging
        #loggingUtils = TOMsMessageLog()
        #loggingUtils.setLogFile()

        QgsMessageLog.logMessage("Finished init", tag="TOMs panel")
        #self.toolbar = self.iface.addToolBar(u'Test5Class')
        #self.toolbar.setObjectName(u'Test5Class')

    def write_log_message(self, message, tag, level):
        #filename = os.path.join('C:\Users\Tim\Documents\MHTC', 'qgis.log')
        with open(self.filename, 'a') as logfile:
            logfile.write('{dateDetails}:: {message}\n'.format(
                dateDetails=time.strftime("%Y%m%d:%H%M%S"), message=message))

    def initGui(self):
        """Create the menu entries and toolbar icons inside the QGIS GUI."""
        QgsMessageLog.logMessage("Registering expression functions ... ",
                                 tag="TOMs panel")

        #self.hideMenusToolbars()

        # set up menu. Is there a generic way to do this? from an xml file?

        QgsMessageLog.logMessage("Adding toolbar", tag="TOMs panel")

        # Add toolbar
        self.featuresWithGPSToolbar = self.iface.addToolBar(
            "featuresWithGPS Toolbar")
        self.featuresWithGPSToolbar.setObjectName(
            "featuresWithGPSToolbar Toolbar")

        self.actionGPSToolbar = QAction(
            QIcon(":/plugins/featureswithgps/resources/GPS.png"),
            QCoreApplication.translate("MyPlugin", "Start GPS Tools"),
            self.iface.mainWindow())
        self.actionGPSToolbar.setCheckable(True)

        self.featuresWithGPSToolbar.addAction(self.actionGPSToolbar)

        self.actionGPSToolbar.triggered.connect(self.onInitGPSTools)

        #self.currGPSManager = gpsManager(self.iface)
        #self.tableNames = self.gpsManager.tableNames

        # Now set up the toolbar

        self.gpsTools = captureGPSFeatures(self.iface,
                                           self.featuresWithGPSToolbar)
        #self.gpsTools.disableFeaturesWithGPSToolbarItems()

    def onInitGPSTools(self):

        QgsMessageLog.logMessage("In onInitGPSTools", tag="TOMs panel")

        if self.actionGPSToolbar.isChecked():

            QgsMessageLog.logMessage("In onInitGPSTools. Activating ...",
                                     tag="TOMs panel")
            self.openGPSTools()

        else:

            QgsMessageLog.logMessage("In onInitGPSTools. Deactivating ...",
                                     tag="TOMs panel")
            self.closeGPSTools()

    def openGPSTools(self):
        # actions when the Proposals Panel is closed or the toolbar "start" is toggled

        QgsMessageLog.logMessage("In openGPSTools. Activating ...",
                                 tag="TOMs panel")

        if self.closeGPSToolsFlag:
            QMessageBox.information(self.iface.mainWindow(), "ERROR",
                                    ("Unable to start GPSTools ..."))
            self.actionGPSToolbar.setChecked(False)
            return

        self.gpsTools.enableFeaturesWithGPSToolbarItems()
        # TODO: connect close project signal to closeGPSTools

    def setCloseGPSToolsFlag(self):
        self.closeGPSToolsFlag = True

    def closeGPSTools(self):
        # actions when the Proposals Panel is closed or the toolbar "start" is toggled

        QgsMessageLog.logMessage("In closeGPSTools. Deactivating ...",
                                 tag="TOMs panel")

        # TODO: Delete any objects that are no longer needed

        #self.proposalTransaction.rollBackTransactionGroup()
        #del self.proposalTransaction  # There is another call to this function from the dock.close()

        # Now disable the items from the Toolbar

        self.gpsTools.disableFeaturesWithGPSToolbarItems()

    def unload(self):
        """Removes the plugin menu item and icon from QGIS GUI."""

        # remove the toolbar
        QgsMessageLog.logMessage("Clearing toolbar ... ", tag="TOMs panel")
        self.featuresWithGPSToolbar.clear()
        QgsMessageLog.logMessage("Deleting toolbar ... ", tag="TOMs panel")
        del self.featuresWithGPSToolbar
        #self.restoreMenusToolbars()

        QgsMessageLog.logMessage("Unload comnpleted ... ", tag="TOMs panel")
Beispiel #11
0
class RubberbandSample(QgsMapTool):
    def printGeometry(self, geom):
        print(geom)

    def start(self):
        maptool = RubberBandClass(self.iface, self.canvas, self.objtype)
        maptool.getObject.connect(self.printGeometry)

        self.canvas.setMapTool(maptool)
        self.canvas.mapToolSet.connect(
            self.unsetTool)  # このサンプル実行中に他のアイコンを押した場合

    def finish(self):
        self.canvas.mapToolSet.disconnect(self.unsetTool)

    def __init__(self, iface):
        self.objtype = QgsWkbTypes.LineGeometry  # QgsWkbTypes.PointGeometry, QgsWkbTypes.LineGeometry, QgsWkbTypes.PolygonGeometry

        self.plugin_name = 'ラバーバンドサンプル'  # プラグイン名
        self.menu_pos = 'サンプル'  # プラグインの登録場所
        self.toolbar = True  # Trueならツールバーにアイコンを表示する
        self.checkable = True  # Trueならプラグイン実行中はアイコンが凹んだままになる

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

        QgsMapTool.__init__(self, self.canvas)

    # このプラグイン実行中に他のアイコンが押された場合、アイコンを元の状態に戻す
    def unsetTool(self, tool):
        if not isinstance(tool, RubberbandSample):
            self.finish()
            self.action.setChecked(False)

    def initGui(self):
        icon = QIcon(os.path.dirname(__file__) + '/icon.png')
        self.action = QAction(icon, self.plugin_name, self.iface.mainWindow())
        self.action.triggered.connect(
            self.execSample)  # アイコンを押下した時に実行されるメソッドを登録
        self.action.setCheckable(
            self.checkable)  # Trueだとアイコンを押下したら次に押下するまで凹んだままになる
        if self.toolbar:
            self.iface.addToolBarIcon(self.action)  # ツールバーにこのツールのアイコンを表示する
        self.iface.addPluginToMenu(self.menu_pos, self.action)

    # このプラグインを無効にしたときに呼ばれる
    def unload(self):
        self.iface.removePluginMenu(self.menu_pos, self.action)
        self.iface.removeToolBarIcon(self.action)

    # このツールのアイコンを押下したときに呼ばれる
    def execSample(self):
        if self.checkable:
            if self.action.isChecked():  # 凹状態になった
                self.previousMapTool = self.canvas.mapTool()  # 現在のマップツールを退避
                self.start()
            else:  # 凸状態になった
                self.finish()
                self.canvas.setMapTool(self.previousMapTool)  # このツール実行前に戻す
        else:
            self.start()
Beispiel #12
0
class MainPlugin(object):
    def __init__(self, iface):
        self.name = "groupLayers"
        self.iface = iface
        self.project = QgsProject.instance()
        self.treeBeforeSave = None

    def initGui(self):
        self.action = QAction(
            QIcon(os.path.dirname(os.path.realpath(__file__)) + "/icon.png"),
            u"Group Layers by similar type (keep visibility)",
            self.iface.mainWindow()
        )
        self.action.setObjectName("groupAction")
        self.action.setWhatsThis("Group/ungroup layers by type")
        self.action.setStatusTip("Group/ungroup layers by type")
        self.action.setCheckable(True)
        self.action.triggered.connect(self.run)

        self.resetAction = QAction("Group and make all layers visible")
        self.resetAction.triggered.connect(self.run_reset_visibility)

        # the icon pressed status could be used, but it is already
        # changed when run method is called, so this is ambiguous
        # therefore a dedicated boolean status is used
        self.grouped = False
        self.groupAdditionalTypes = False
        self.defSelection = groupHierarchies.keys().__iter__().__next__()
        self.hierarchyDefinition = groupHierarchies[self.defSelection]

        # add toolbar button and menu item
        layersDock = self.iface.mainWindow().findChild(QDockWidget, "Layers")
        self.layersToolBar = layersDock.widget().layout().itemAt(0).widget()
        assert isinstance(self.layersToolBar, QToolBar)
        self.layersToolBar.addAction(self.action)
        self.menuButton = [btn for btn in self.layersToolBar.children()
                           if isinstance(btn, QToolButton)
                           if self.action in btn.actions()][0]
        self.buttonMenu = QMenu()
        self.menuButton.setMenu(self.buttonMenu)
        self.menuButton.setPopupMode(QToolButton.MenuButtonPopup)
        self.buttonMenu.addAction(self.action)
        self.buttonMenu.addAction(self.resetAction)
        # self.iface.addToolBarIcon(self.action)
        self.iface.addPluginToMenu("&Group Layers", self.action)

        self.defSelector = QAction(
            u"Select hierarchy definitions",
            self.iface.mainWindow()
        )
        self.defSelector.setObjectName("defSelector")
        self.defSelector.triggered.connect(self.selectDefs)
        self.iface.addPluginToMenu("&Group Layers", self.defSelector)
        # connect hook to reset the plugin state
        # when a new or existing project is opened
        self.project.cleared.connect(self.reset_state)
        self.project.writeProject.connect(self.write)
        self.project.projectSaved.connect(self.saved)

    def unload(self):
        # remove the plugin menu item and icon
        self.iface.removePluginMenu("&Group Layers", self.action)
        self.iface.removePluginMenu("&Group Layers", self.defSelector)
        self.layersToolBar.removeAction(self.action)
        self.project.cleared.disconnect(self.reset_state)
        self.project.writeProject.disconnect(self.write)
        self.project.projectSaved.disconnect(self.saved)
        try:
            self.project.layerWasAdded.disconnect(self.add_layer_sync)
        except Exception:
            print('could not disconnect add_layer_sync in unload')
        try:
            self.project.layerRemoved.disconnect(self.remove_layer_sync)
        except Exception:
            print('could not disconnect remove_layer_sync in unload')
        # self.iface.removeToolBarIcon(self.action)

    def selectDefs(self):
        dialog = DefSelectDialog(self.defSelection, self.groupAdditionalTypes)
        if dialog.exec_():
            self.defSelection = dialog.comboBox.currentText()
            self.hierarchyDefinition = groupHierarchies[self.defSelection]
            self.groupAdditionalTypes = dialog.checkBox.isChecked()

    def run(self, checked=False, reset=False):
        try:
            if self.grouped:
                try:
                    self.project.layerWasAdded.disconnect(self.add_layer_sync)
                except Exception:
                    print('could not disconnect add_layer_sync')
                try:
                    self.project.layerRemoved.disconnect(self.remove_layer_sync)
                except Exception:
                    print('could not disconnect remove_layer_sync')
                self.groupToTree(reset_initial_visibility=reset)
                self.resetAction.setText("Group and make all layers visible")
            else:
                self.treeToGroup(all_visible=reset)
                self.resetAction.setText("Ungroup and restore initial (ungrouped) visibility")
                self.project.layerWasAdded.connect(self.add_layer_sync)
                self.project.layerRemoved.connect(self.remove_layer_sync)
        except Exception as e:
            raise(e)
        finally:
            # synchronize plugin state with button state in case of exceptions
            self.grouped = checked

    def run_reset_visibility(self):
        self.action.toggle()
        self.run(checked=self.action.isChecked(), reset=True)

    def reset_state(self):
        self.action.setChecked(False)
        self.grouped = False

    def write(self):
        if self.grouped:
            answer = QMessageBox.question(self.iface.mainWindow(),
                                          "Save ungrouped state",
                                          "The layers are currently grouped by the "
                                          "groupLayers plugin\n\n"
                                          "Would you like to save the initial (ungrouped) state?\n"
                                          "(save current (grouped) layer tree if answer = NO)",
                                          QMessageBox.Yes|QMessageBox.No)
            if answer == QMessageBox.Yes:
                self.treeBeforeSave = self.iface.layerTreeCanvasBridge().rootGroup().clone()
                self.groupToTree(reset_initial_visibility=True)
                self.iface.messageBar().pushMessage(
                    'CAUTION: The layer tree has been saved in its original format, '
                    'check options if you want to change this behavior.', Qgis.Info
                )

    def saved(self):
        if self.treeBeforeSave is not None:
            tempOldTree = self.oldTree
            self.oldTree = self.treeBeforeSave
            self.groupToTree(reset_initial_visibility=True)
            self.oldTree = tempOldTree
        self.treeBeforeSave = None

    def add_layer_sync(self, addedLayer):
        self.oldTree.addLayer(addedLayer)

    def remove_layer_sync(self, removedLayerId):
        removedLayer = self.oldTree.findLayer(removedLayerId)
        self.recursiveRemoveFromGroup(self.oldTree, removedLayer)

    def recursiveRemoveFromGroup(self, group, layer):
        group.removeChildNode(layer)
        for subGroup in group.findGroups():
            self.recursiveRemoveFromGroup(subGroup, layer)

    def initTreeRec(self, hierarchyDefinition, tree):
        for (k, v) in hierarchyDefinition.items():
            if "groupCriteria" in v:
                tree[k] = {}
                self.initTreeRec(v["values"], tree[k])
            else:
                tree[k] = []

    def treeToGroup(self, all_visible=True):
        self.layerDict = {}
        self.treeRoot = self.project.layerTreeRoot()
        self.initTreeRec(self.hierarchyDefinition['values'], self.layerDict)
        layerTree = self.iface.layerTreeCanvasBridge().rootGroup()
        self.oldTree = layerTree.clone()
        self.parseTreeRec(layerTree)  # into self.layerDict
        self.layerDict = self.cleanTree(self.layerDict)
        oldLen = len(layerTree.children())
        self.layerDictToTree(self.layerDict, layerTree, all_visible)

        # caution: commented instruction below removes all layers !!
        # iface.layerTreeCanvasBridge().rootGroup().clear()
        layerTree.removeChildren(0, oldLen)

    def groupToTree(self, reset_initial_visibility=True):
        self.treeRoot = self.project.layerTreeRoot()
        layerTree = self.iface.layerTreeCanvasBridge().rootGroup()
        oldLen = len(layerTree.children())
        self.insertInto(self.oldTree, layerTree, reset_initial_visibility)
        layerTree.removeChildren(0, oldLen)

    def layerDictToTree(self, layerDict, destinationGroup, all_visible):
        if isinstance(layerDict, dict):
            for (layerType, layers) in layerDict.items():
                grp = destinationGroup.addGroup(layerType)
                self.layerDictToTree(layers, grp, all_visible)
        elif isinstance(layerDict, list):
            for l in layerDict:
                isVisible = self.treeRoot.findLayer(l).isVisible()
                node = destinationGroup.addLayer(l)
                if not all_visible:
                    node.setItemVisibilityChecked(isVisible)

        else:
            raise Exception("Tree dictionary has been initialized incorrectly.")

    def insertInto(self, origin, destination, reset_initial_visibility):
        for el in origin.children():
            if QgsLayerTree.isLayer(el):
                node = destination.addLayer(el.layer())
                node.setItemVisibilityChecked(
                    self.treeRoot.findLayer(el.layer()).isVisible()
                )
            elif QgsLayerTree.isGroup(el):
                node = destination.addGroup(el.name())
                self.insertInto(el, node, reset_initial_visibility)
            if reset_initial_visibility:
                # overwrite visibility with previously saved visibility
                node.setItemVisibilityChecked(el.itemVisibilityChecked())

    def parseTreeRec(self, treeLeaf):
        for el in treeLeaf.children():
            if QgsLayerTree.isLayer(el):
                l = el.layer()
                self.sortInto(l, self.layerDict, self.hierarchyDefinition)
            elif QgsLayerTree.isGroup(el):
                self.parseTreeRec(el)

    def sortInto(self, layer, destination, definitions):
        if "groupCriteria" in definitions:
            groupValue = layer.__getattribute__(definitions["groupCriteria"])()
            itemFound = False
            for (label, criteria) in definitions["values"].items():
                if groupValue == criteria["value"]:
                    itemFound = True
                    self.sortInto(layer, destination[label], criteria)
            if not itemFound:
                if self.groupAdditionalTypes:
                    groupName = "others"
                else:
                    groupName = str(groupValue)
                try:
                    destination[groupName].append(layer)
                except KeyError:
                    destination[groupName] = [layer]
        else:
            destination.append(layer)

    def cleanTree(self, sourceTree):
        # remove all branches without end leaves
        if isinstance(sourceTree, dict):
            groupContents = {}
            for (layerType, layers) in sourceTree.items():
                groupLayers = self.cleanTree(layers)
                if groupLayers:
                    groupContents[layerType] = groupLayers
            return groupContents
        elif isinstance(sourceTree, list):
            return sourceTree
        else:
            raise Exception("Tree dictionary has been initialized incorrectly.")
Beispiel #13
0
class BoundingBoxSample(QgsMapTool):
    def start(self):
        # バウンディングボックス作成元
        srclayer = self.iface.activeLayer()
        if (srclayer == None) or (type(srclayer) is not QgsVectorLayer):
            QMessageBox.about(None, '警告', 'ベクタレイヤを選択してから実行してください')
            self.action.setChecked(False)
            return
        # バウンディングボックス投入先
        fieldstr = ''
        for field in srclayer.fields():
            fieldstr = fieldstr + '&field=' + str(field.name()) + ':' + str(
                field.typeName())
        crsstr = srclayer.sourceCrs().authid()
        dstlayer = QgsVectorLayer("Polygon?crs=" + crsstr + fieldstr,
                                  "サンプルレイヤ", "memory")

        for f in srclayer.getFeatures():

            # 属性
            qf = QgsFields()
            ## フィールド
            for field in srclayer.fields():
                qf.append(
                    QgsField(str(field.name()), typeName=field.typeName()))
            record = QgsFeature(qf)
            ## 値投入
            for i in range(0, f.fields().count()):
                record[i] = f[i]
            # オブジェクト
            mpol = f.geometry().asMultiPolygon()
            bnds = []
            for i in range(0, len(mpol)):
                bnds.append(
                    QgsGeometry.fromRect(QgsGeometry().fromPolygonXY(
                        mpol[i]).boundingBox()).asPolygon())
            newobj = QgsGeometry.fromMultiPolygonXY(bnds)
            record.setGeometry(newobj)
            # レイヤに追加
            dstlayer.dataProvider().addFeatures([record])
            dstlayer.updateExtents()

        # キャンバスにオブジェクトを表示する
        QgsProject.instance().addMapLayers([dstlayer])
        self.canvas.refreshAllLayers()

    def finish(self):
        self.canvas.mapToolSet.disconnect(self.unsetTool)

    def __init__(self, iface):
        self.plugin_name = 'バウンディングボックス作成サンプル'  # プラグイン名
        self.menu_pos = 'サンプル'  # プラグインの登録場所
        self.toolbar = True  # Trueならツールバーにアイコンを表示する
        self.checkable = False  # Trueならプラグイン実行中はアイコンが凹んだままになる

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

        QgsMapTool.__init__(self, self.canvas)

    # このプラグイン実行中に他のアイコンが押された場合、アイコンを元の状態に戻す
    def unsetTool(self, tool):
        if not isinstance(tool, BoundingBoxSample):
            self.finish()
            self.action.setChecked(False)

    def initGui(self):
        icon = QIcon(os.path.dirname(__file__) + '/icon.png')
        self.action = QAction(icon, self.plugin_name, self.iface.mainWindow())
        self.action.triggered.connect(
            self.execSample)  # アイコンを押下した時に実行されるメソッドを登録
        self.action.setCheckable(
            self.checkable)  # Trueだとアイコンを押下したら次に押下するまで凹んだままになる
        if self.toolbar:
            self.iface.addToolBarIcon(self.action)  # ツールバーにこのツールのアイコンを表示する
        self.iface.addPluginToMenu(self.menu_pos, self.action)

    # このプラグインを無効にしたときに呼ばれる
    def unload(self):
        self.iface.removePluginMenu(self.menu_pos, self.action)
        self.iface.removeToolBarIcon(self.action)

    # このツールのアイコンを押下したときに呼ばれる
    def execSample(self):
        if self.checkable:
            if self.action.isChecked():  # 凹状態になった
                self.previousMapTool = self.canvas.mapTool()  # 現在のマップツールを退避
                self.start()
            else:  # 凸状態になった
                self.finish()
                self.canvas.setMapTool(self.previousMapTool)  # このツール実行前に戻す
        else:
            self.start()
Beispiel #14
0
class featuresWithGPS:
    """QGIS Plugin Implementation."""
    def __init__(self, iface):

        QgsMessageLog.logMessage("Starting featuresWithGPS ... ",
                                 tag="TOMs panel")
        """Constructor.
        
        :param iface: An interface instance that will be passed to this class
            which provides the hook by which you can manipulate the QGIS
            application at run time.
        :type iface: QgsInterface
        """
        # Save reference to the QGIS interface
        self.iface = iface
        # initialize plugin directory
        self.plugin_dir = os.path.dirname(__file__)

        self.actions = []  # ?? check - assume it initialises array of actions

        self.closeGPSToolsFlag = False

        # Set up local logging
        loggingUtils = TOMsMessageLog()
        loggingUtils.setLogFile()

        QgsMessageLog.logMessage("In featuresWithGPS. Finished init",
                                 tag="TOMs panel")

    def initGui(self):
        """Create the menu entries and toolbar icons inside the QGIS GUI."""
        QgsMessageLog.logMessage("Registering expression functions ... ",
                                 tag="TOMs panel")

        #self.hideMenusToolbars()
        self.expressionsObject = operatorExpressions()
        #self.expressionsObject.registerFunctions()   # Register the Expression functions that we need

        # set up menu. Is there a generic way to do this? from an xml file?

        QgsMessageLog.logMessage("Adding toolbar", tag="TOMs panel")

        # Add toolbar
        self.featuresWithGPSToolbar = self.iface.addToolBar(
            "featuresWithGPS Toolbar")
        self.featuresWithGPSToolbar.setObjectName(
            "featuresWithGPSToolbar Toolbar")

        self.actionGPSToolbar = QAction(
            QIcon(":/plugins/featureswithgps/resources/GPS.png"),
            QCoreApplication.translate("MyPlugin", "Start GPS Tools"),
            self.iface.mainWindow())
        self.actionGPSToolbar.setCheckable(True)

        self.featuresWithGPSToolbar.addAction(self.actionGPSToolbar)

        self.actionGPSToolbar.triggered.connect(self.onInitGPSTools)

        #self.currGPSManager = gpsManager(self.iface)
        #self.tableNames = self.gpsManager.tableNames

        # Now set up the toolbar

        self.gpsTools = captureGPSFeatures(self.iface,
                                           self.featuresWithGPSToolbar)
        #self.gpsTools.disableFeaturesWithGPSToolbarItems()

    def onInitGPSTools(self):

        QgsMessageLog.logMessage("In onInitGPSTools", tag="TOMs panel")

        if self.actionGPSToolbar.isChecked():

            QgsMessageLog.logMessage("In onInitGPSTools. Activating ...",
                                     tag="TOMs panel")
            self.openGPSTools()

        else:

            QgsMessageLog.logMessage("In onInitGPSTools. Deactivating ...",
                                     tag="TOMs panel")
            self.closeGPSTools()

    def openGPSTools(self):
        # actions when the Proposals Panel is closed or the toolbar "start" is toggled

        QgsMessageLog.logMessage("In openGPSTools. Activating ...",
                                 tag="TOMs panel")

        if self.closeGPSToolsFlag:
            QMessageBox.information(self.iface.mainWindow(), "ERROR",
                                    ("Unable to start GPSTools ..."))
            self.actionGPSToolbar.setChecked(False)
            return

        self.gpsTools.enableFeaturesWithGPSToolbarItems()
        # TODO: connect close project signal to closeGPSTools

    def setCloseGPSToolsFlag(self):
        self.closeGPSToolsFlag = True

    def closeGPSTools(self):
        # actions when the Proposals Panel is closed or the toolbar "start" is toggled

        QgsMessageLog.logMessage("In closeGPSTools. Deactivating ...",
                                 tag="TOMs panel")

        # TODO: Delete any objects that are no longer needed

        #self.proposalTransaction.rollBackTransactionGroup()
        #del self.proposalTransaction  # There is another call to this function from the dock.close()

        # Now disable the items from the Toolbar

        self.gpsTools.disableFeaturesWithGPSToolbarItems()

    def unload(self):
        """Removes the plugin menu item and icon from QGIS GUI."""

        #self.expressionsObject.unregisterFunctions()  # unregister all the Expression functions used

        # remove the toolbar
        QgsMessageLog.logMessage("Clearing toolbar ... ", tag="TOMs panel")
        self.featuresWithGPSToolbar.clear()
        QgsMessageLog.logMessage("Deleting toolbar ... ", tag="TOMs panel")
        del self.featuresWithGPSToolbar
        #self.restoreMenusToolbars()

        QgsMessageLog.logMessage("Unload comnpleted ... ", tag="TOMs panel")
Beispiel #15
0
class RelationSample(QgsMapTool):
    def showChildren(self):
        parent = self.rel.referencedLayer()
        child = self.rel.referencingLayer()

        features = parent.selectedFeatures()
        if len(features) == 0:
            return

        child.removeSelection()  # クリアしないと、属性テーブルに余計に表示されるから
        for c in self.rel.getRelatedFeatures(features[0]):
            child.select(c.id())

        selectedlayer = self.iface.activeLayer()  # 現在のアクティブレイヤ退避
        try:
            # このプログラム実行中は属性テーブルは選択中のフューチャーしか表示しないように設定する
            self.oldsetting = QSettings().value(
                '/Qgis/attributeTableBehaviour')
            QSettings().setValue('/Qgis/attributeTableBehavior',
                                 'ShowSelected')
            # テーブル表示
            self.iface.setActiveLayer(child)
            self.iface.mainWindow().findChild(QtWidgets.QAction,
                                              'mActionOpenTable').trigger()
        finally:
            # 設定を戻す
            self.iface.setActiveLayer(selectedlayer)
            QSettings().setValue('/Qgis/attributeTableBehavior',
                                 self.oldsetting)

    def start(self):
        self.referencedLayer = QgsProject.instance().mapLayersByName(
            self.referencedLayerName)[0]
        self.referencingLayer = QgsProject.instance().mapLayersByName(
            self.referencingLayerName)[0]
        self.rel = QgsRelation()

        self.rel.setReferencingLayer(self.referencingLayer.id())
        self.rel.setReferencedLayer(self.referencedLayer.id())
        self.rel.addFieldPair(self.referencingField, self.referencedField)
        self.rel.setId('適当なID')
        self.rel.setName('適当な名前')
        QgsProject.instance().relationManager().addRelation(self.rel)

        self.referencedLayer.selectionChanged.connect(self.showChildren)

    def finish(self):
        QgsProject.instance().relationManager().removeRelation(self.rel)
        self.referencedLayer.selectionChanged.disconnect(self.showChildren)

    def __init__(self, iface):
        self.plugin_name = 'リレーションサンプル'  # プラグイン名
        self.menu_pos = 'サンプル'  # プラグインの登録場所
        self.toolbar = True  # Trueならツールバーにアイコンを表示する
        self.checkable = True  # Trueならプラグイン実行中はアイコンが凹んだままになる

        self.referencedLayerName = '〇〇〇'  # 被参照のレイヤ名
        self.referencingLayerName = '□□□'  # 参照元のレイヤ名
        self.referencedField = '△△△'  # 参照元とのリンクに使うフィールド名
        self.referencingField = '×××'  # 被参照とのリンクに使うフィールド名

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

        QgsMapTool.__init__(self, self.canvas)

    # このプラグイン実行中に他のアイコンが押された場合、アイコンを元の状態に戻す
    def unsetTool(self, tool):
        if not isinstance(tool, RelationSample):
            self.finish()
            self.action.setChecked(False)

    def initGui(self):
        icon = QIcon(os.path.dirname(__file__) + '/icon.png')
        self.action = QAction(icon, self.plugin_name, self.iface.mainWindow())
        self.action.triggered.connect(
            self.execSample)  # アイコンを押下した時に実行されるメソッドを登録
        self.action.setCheckable(
            self.checkable)  # Trueだとアイコンを押下したら次に押下するまで凹んだままになる
        if self.toolbar:
            self.iface.addToolBarIcon(self.action)  # ツールバーにこのツールのアイコンを表示する
        self.iface.addPluginToMenu(self.menu_pos, self.action)

    # このプラグインを無効にしたときに呼ばれる
    def unload(self):
        self.iface.removePluginMenu(self.menu_pos, self.action)
        self.iface.removeToolBarIcon(self.action)

    # このツールのアイコンを押下したときに呼ばれる
    def execSample(self):
        if self.checkable:
            if self.action.isChecked():  # 凹状態になった
                self.previousMapTool = self.canvas.mapTool()  # 現在のマップツールを退避
                self.start()
            else:  # 凸状態になった
                self.finish()
                self.canvas.setMapTool(self.previousMapTool)  # このツール実行前に戻す
        else:
            self.start()
class TemporaryLayerSample(QgsMapTool):
    def setGeometry(self, geom):
        qf = QgsFields()
        for field in self.tmplayer.fields():
            qf.append(QgsField(str(field.name()), typeName=field.typeName()))
        record = QgsFeature(qf)
        # 地物をセットする
        record.setGeometry(geom)
        # 属性をセットする
        record.setAttributes([])
        # 作成したレコードをレイヤに追加
        self.tmplayer.dataProvider().addFeatures([record])
        self.tmplayer.updateExtents()
        self.canvas.refreshAllLayers()

    def start(self):
        # 一時レイヤ作成
        typestr = 'Polygon?'
        fieldstr = '&field=〇〇:string&field=□□:double&field=××:date'
        crsstr = '&crs=' + str(QgsProject.instance().crs().authid())
        layername = '一時レイヤ'
        self.tmplayer = QgsVectorLayer(typestr + crsstr + fieldstr, layername,
                                       "memory")
        QgsProject.instance().addMapLayer(self.tmplayer)

        # ラバーバンドのための設定
        self.objtype = QgsWkbTypes.PolygonGeometry  # QgsWkbTypes.PointGeometry, QgsWkbTypes.LineGeometry, QgsWkbTypes.PolygonGeometry

        maptool = RubberBandClass(self.iface, self.canvas, self.objtype)
        maptool.getObject.connect(self.setGeometry)

        self.canvas.setMapTool(maptool)
        self.canvas.mapToolSet.connect(
            self.unsetTool)  # このサンプル実行中に他のアイコンを押した場合

    def finish(self):
        self.canvas.mapToolSet.disconnect(self.unsetTool)

    def __init__(self, iface):
        self.plugin_name = '一時レイヤ作成サンプル'  # プラグイン名
        self.menu_pos = 'サンプル'  # プラグインの登録場所
        self.toolbar = True  # Trueならツールバーにアイコンを表示する
        self.checkable = True  # Trueならプラグイン実行中はアイコンが凹んだままになる

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

        QgsMapTool.__init__(self, self.canvas)

    # このプラグイン実行中に他のアイコンが押された場合、アイコンを元の状態に戻す
    def unsetTool(self, tool):
        if not isinstance(tool, TemporaryLayerSample):
            self.finish()
            self.action.setChecked(False)

    def initGui(self):
        icon = QIcon(os.path.dirname(__file__) + '/icon.png')
        self.action = QAction(icon, self.plugin_name, self.iface.mainWindow())
        self.action.triggered.connect(
            self.execSample)  # アイコンを押下した時に実行されるメソッドを登録
        self.action.setCheckable(
            self.checkable)  # Trueだとアイコンを押下したら次に押下するまで凹んだままになる
        if self.toolbar:
            self.iface.addToolBarIcon(self.action)  # ツールバーにこのツールのアイコンを表示する
        self.iface.addPluginToMenu(self.menu_pos, self.action)

    # このプラグインを無効にしたときに呼ばれる
    def unload(self):
        self.iface.removePluginMenu(self.menu_pos, self.action)
        self.iface.removeToolBarIcon(self.action)

    # このツールのアイコンを押下したときに呼ばれる
    def execSample(self):
        if self.checkable:
            if self.action.isChecked():  # 凹状態になった
                self.previousMapTool = self.canvas.mapTool()  # 現在のマップツールを退避
                self.start()
            else:  # 凸状態になった
                self.finish()
                self.canvas.setMapTool(self.previousMapTool)  # このツール実行前に戻す
        else:
            self.start()
Beispiel #17
0
class PgMetadataDock(QDockWidget, DOCK_CLASS):

    def __init__(self, parent=None):
        _ = parent
        super().__init__()
        self.setupUi(self)
        self.settings = QgsSettings()

        self.current_datasource_uri = None
        self.current_connection = None

        self.viewer.page().setLinkDelegationPolicy(QWebPage.DelegateAllLinks)
        self.viewer.page().linkClicked.connect(self.open_link)

        # Help button
        self.external_help.setText('')
        self.external_help.setIcon(QIcon(QgsApplication.iconPath('mActionHelpContents.svg')))
        self.external_help.clicked.connect(self.open_external_help)

        # Flat table button
        self.flatten_dataset_table.setText('')
        self.flatten_dataset_table.setToolTip(tr("Add the catalog table"))
        self.flatten_dataset_table.setIcon(QgsApplication.getThemeIcon("/mActionAddHtml.svg"))
        self.flatten_dataset_table.clicked.connect(self.add_flatten_dataset_table)

        # Settings menu
        self.config.setAutoRaise(True)
        self.config.setToolTip(tr("Settings"))
        self.config.setPopupMode(QToolButton.InstantPopup)
        self.config.setIcon(QgsApplication.getThemeIcon("/mActionOptions.svg"))

        self.auto_open_dock_action = QAction(
            tr('Auto open dock from locator'),
            iface.mainWindow())
        self.auto_open_dock_action.setCheckable(True)
        self.auto_open_dock_action.setChecked(
            self.settings.value("pgmetadata/auto_open_dock", True, type=bool)
        )
        self.auto_open_dock_action.triggered.connect(self.save_auto_open_dock)
        menu = QMenu()
        menu.addAction(self.auto_open_dock_action)
        self.config.setMenu(menu)

        # Setting PDF/HTML menu
        self.save_button.setAutoRaise(True)
        self.save_button.setToolTip(tr("Save metadata"))
        self.save_button.setPopupMode(QToolButton.InstantPopup)
        self.save_button.setIcon(QIcon(QgsApplication.iconPath('mActionFileSave.svg')))

        self.save_as_pdf = QAction(
            tr('Save as PDF') + '…',
            iface.mainWindow())
        self.save_as_pdf.triggered.connect(partial(self.export_dock_content, OutputFormats.PDF))

        self.save_as_html = QAction(
            tr('Save as HTML') + '…',
            iface.mainWindow())
        self.save_as_html.triggered.connect(partial(self.export_dock_content, OutputFormats.HTML))

        self.save_as_dcat = QAction(
            tr('Save as DCAT') + '…',
            iface.mainWindow())
        self.save_as_dcat.triggered.connect(partial(self.export_dock_content, OutputFormats.DCAT))

        self.menu_save = QMenu()
        self.menu_save.addAction(self.save_as_pdf)
        self.menu_save.addAction(self.save_as_html)
        self.menu_save.addAction(self.save_as_dcat)
        self.save_button.setMenu(self.menu_save)
        self.save_button.setEnabled(False)

        self.metadata = QgsProviderRegistry.instance().providerMetadata('postgres')

        # Display message in the dock
        if not settings_connections_names():
            self.default_html_content_not_installed()
        else:
            self.default_html_content_not_pg_layer()

        iface.layerTreeView().currentLayerChanged.connect(self.layer_changed)

    def export_dock_content(self, output_format: OutputFormats):
        """ Export the current displayed metadata sheet to the given format. """
        layer_name = iface.activeLayer().name()

        file_path = os.path.join(
            self.settings.value("UI/lastFileNameWidgetDir"),
            '{name}.{ext}'.format(name=layer_name, ext=output_format.ext)
        )
        output_file = QFileDialog.getSaveFileName(
            self,
            tr("Save File as {format}").format(format=output_format.label),
            file_path,
            "{label} (*.{ext})".format(
                label=output_format.label,
                ext=output_format.ext,
            )
        )
        if output_file[0] == '':
            return

        self.settings.setValue("UI/lastFileNameWidgetDir", os.path.dirname(output_file[0]))

        output_file_path = output_file[0]
        parent_folder = str(Path(output_file_path).parent)

        if output_format == OutputFormats.PDF:
            printer = QPrinter()
            printer.setOutputFormat(QPrinter.PdfFormat)
            printer.setPageMargins(20, 20, 20, 20, QPrinter.Millimeter)
            printer.setOutputFileName(output_file_path)
            self.viewer.print(printer)
            iface.messageBar().pushSuccess(
                tr("Export PDF"),
                tr(
                    "The metadata has been exported as PDF successfully in "
                    "<a href=\"{}\">{}</a>").format(parent_folder, output_file_path)
            )

        elif output_format in [OutputFormats.HTML, OutputFormats.DCAT]:
            if output_format == OutputFormats.HTML:
                data_str = self.viewer.page().currentFrame().toHtml()
            else:
                sql = self.sql_for_layer(
                    self.current_datasource_uri, output_format=OutputFormats.DCAT)
                data = self.current_connection.executeSql(sql)
                with open(resources_path('xml', 'dcat.xml')) as xml_file:
                    xml_template = xml_file.read()

                locale = QgsSettings().value("locale/userLocale", QLocale().name())
                locale = locale.split('_')[0].lower()

                xml = parseString(xml_template.format(locale=locale, content=data[0][0]))
                data_str = xml.toprettyxml()

            with open(output_file[0], "w") as file_writer:
                file_writer.write(data_str)
            iface.messageBar().pushSuccess(
                tr("Export") + ' ' + output_format.label,
                tr(
                    "The metadata has been exported as {format} successfully in "
                    "<a href=\"{folder}\">{path}</a>").format(
                    format=output_format.label, folder=parent_folder, path=output_file_path)
            )

    def save_auto_open_dock(self):
        """ Save settings about the dock. """
        self.settings.setValue("pgmetadata/auto_open_dock", self.auto_open_dock_action.isChecked())

    @staticmethod
    def sql_for_layer(uri, output_format: OutputFormats):
        """ Get the SQL query for a given layer and output format. """
        locale = QgsSettings().value("locale/userLocale", QLocale().name())
        locale = locale.split('_')[0].lower()

        if output_format == OutputFormats.HTML:
            sql = (
                "SELECT pgmetadata.get_dataset_item_html_content('{schema}', '{table}', '{locale}');"
            ).format(schema=uri.schema(), table=uri.table(), locale=locale)
        elif output_format == OutputFormats.DCAT:
            sql = (
                "SELECT dataset FROM pgmetadata.get_datasets_as_dcat_xml("
                "    '{locale}',"
                "    ("
                "    SELECT array_agg(uid)"
                "    FROM pgmetadata.dataset AS d"
                "    WHERE d.schema_name = '{schema}' "
                "    AND d.table_name = '{table}'"
                "    )"
                ") "

            ).format(schema=uri.schema(), table=uri.table(), locale=locale)
        else:
            raise NotImplementedError('Output format is not yet implemented.')

        return sql

    def layer_changed(self, layer):
        """ When the layer has changed in the legend, we must check this new layer. """
        self.save_button.setEnabled(False)
        self.current_datasource_uri = None
        self.current_connection = None

        if not settings_connections_names():
            self.default_html_content_not_installed()
            return

        if not isinstance(layer, QgsVectorLayer):
            self.default_html_content_not_pg_layer()
            return

        uri = layer.dataProvider().uri()
        if not uri.schema() or not uri.table():
            self.default_html_content_not_pg_layer()
            return

        connections, message = connections_list()
        if not connections:
            LOGGER.critical(message)
            self.set_html_content('PgMetadata', message)
            return

        # TODO, find the correct connection to query according to the datasource
        # The metadata HTML is wrong if there are many pgmetadata in different databases

        for connection_name in connections:
            connection = self.metadata.findConnection(connection_name)
            if not connection:
                LOGGER.critical("The global variable pgmetadata_connection_names is not correct.")
                self.default_html_content_not_installed()
                continue

            if not check_pgmetadata_is_installed(connection_name):
                LOGGER.critical(tr('PgMetadata is not installed on {}').format(connection_name))
                continue

            sql = self.sql_for_layer(uri, output_format=OutputFormats.HTML)

            try:
                data = connection.executeSql(sql)
            except QgsProviderConnectionException as e:
                LOGGER.critical(tr('Error when querying the database : ') + str(e))
                self.default_html_content_not_installed()
                return

            if not data:
                # Go to the next database
                continue

            if data[0] == NULL or data[0][0] == NULL:
                continue

            self.set_html_content(body=data[0][0])
            self.save_button.setEnabled(True)
            self.current_datasource_uri = uri
            self.current_connection = connection

            break

        else:
            origin = uri.database() if uri.database() else uri.service()
            self.set_html_content(
                'Missing metadata',
                tr('The layer {origin} {schema}.{table} is missing metadata.').format(
                    origin=origin, schema=uri.schema(), table=uri.table())
            )

    def add_flatten_dataset_table(self):
        """ Add a flatten dataset table with all links and contacts. """
        connections, message = connections_list()
        if not connections:
            LOGGER.critical(message)
            self.set_html_content('PgMetadata', message)
            return

        if len(connections) > 1:
            dialog = QInputDialog()
            dialog.setComboBoxItems(connections)
            dialog.setWindowTitle(tr("Database"))
            dialog.setLabelText(tr("Choose the database to add the catalog"))
            if not dialog.exec_():
                return
            connection_name = dialog.textValue()
        else:
            connection_name = connections[0]

        metadata = QgsProviderRegistry.instance().providerMetadata('postgres')
        connection = metadata.findConnection(connection_name)

        locale = QgsSettings().value("locale/userLocale", QLocale().name())
        locale = locale.split('_')[0].lower()

        uri = QgsDataSourceUri(connection.uri())
        uri.setTable(f'(SELECT * FROM pgmetadata.export_datasets_as_flat_table(\'{locale}\'))')
        uri.setKeyColumn('uid')

        layer = QgsVectorLayer(uri.uri(), '{} - {}'.format(tr("Catalog"), connection_name), 'postgres')
        QgsProject.instance().addMapLayer(layer)

    @staticmethod
    def open_external_help():
        QDesktopServices.openUrl(QUrl('https://docs.3liz.org/qgis-pgmetadata-plugin/'))

    @staticmethod
    def open_link(url):
        QDesktopServices.openUrl(url)

    def set_html_content(self, title=None, body=None):
        """ Set the content in the dock. """

        css_file = resources_path('css', 'dock.css')
        with open(css_file, 'r') as f:
            css = f.read()

        html = '<html><head><style>{css}</style></head><body>'.format(css=css)

        if title:
            html += '<h2>{title}</h2>'.format(title=title)

        if body:
            html += body

        html += '</body></html>'

        # It must be a file, even if it does not exist on the file system.
        base_url = QUrl.fromLocalFile(resources_path('images', 'must_be_a_file.png'))
        self.viewer.setHtml(html, base_url)

    def default_html_content_not_installed(self):
        """ When PgMetadata is not installed correctly or not at all. """
        message = "<p>"
        message += tr("The 'pgmetadata' schema is not installed or configured.")
        message += "</p>"
        message += "<p>"
        message += tr(
            "Either install PgMetadata on a database (Processing → Database → Installation of the "
            "database structure) or make the link to an existing PgMetadata database (Processing → "
            "Administration → Set connections to database)."
        )
        message += "</p>"
        message += "<p>"
        message += tr(
            "Visit the documentation on <a href=\"https://docs.3liz.org/qgis-pgmetadata-plugin/\">"
            "docs.3liz.org</a> to check how to setup PgMetadata."
        )
        message += "</p>"
        self.set_html_content('PgMetadata', message)

    def default_html_content_not_pg_layer(self):
        """ When it's not a PostgreSQL layer. """
        self.set_html_content(
            'PgMetadata', tr('You should click on a layer in the legend which is stored in PostgreSQL.'))
class manageRestrictionDetails(RestrictionTypeUtilsMixin):
    def __init__(self, iface, TOMsToolbar, proposalsManager):

        TOMsMessageLog.logMessage("In manageRestrictionDetails::init",
                                  level=Qgis.Info)

        # Save reference to the QGIS interface
        self.iface = iface
        self.canvas = self.iface.mapCanvas()
        self.proposalsManager = proposalsManager
        self.TOMsToolbar = TOMsToolbar

        #self.constants = TOMsConstants()

        #self.restrictionTypeUtils = RestrictionTypeUtilsClass(self.iface)

        # This will set up the items on the toolbar
        # Create actions
        self.actionSelectRestriction = QAction(
            QIcon(":/plugins/TOMs/resources/mActionSelect.png"),
            QCoreApplication.translate("MyPlugin", "Select"),
            self.iface.mainWindow())
        self.actionSelectRestriction.setCheckable(True)

        self.actionRestrictionDetails = QAction(
            QIcon(":/plugins/TOMs/resources/mActionGetInfo.svg"),
            QCoreApplication.translate("MyPlugin", "Get Details"),
            self.iface.mainWindow())
        #self.actionRestrictionDetails.setCheckable(True)

        self.actionCreateBayRestriction = QAction(
            QIcon(":/plugins/TOMs/resources/mActionAddTrack.svg"),
            QCoreApplication.translate("MyPlugin", "Create Bay"),
            self.iface.mainWindow())
        self.actionCreateBayRestriction.setCheckable(True)

        self.actionCreateLineRestriction = QAction(
            QIcon(":/plugins/TOMs/resources/mActionAddLine.svg"),
            QCoreApplication.translate("MyPlugin", "Create Line"),
            self.iface.mainWindow())
        self.actionCreateLineRestriction.setCheckable(True)

        self.actionCreatePolygonRestriction = QAction(
            QIcon(":/plugins/TOMs/resources/rpolygonBy2Corners.svg"),
            QCoreApplication.translate("MyPlugin", "Create Polygon"),
            self.iface.mainWindow())
        self.actionCreatePolygonRestriction.setCheckable(True)

        self.actionCreateSignRestriction = QAction(
            QIcon(":/plugins/TOMs/resources/mActionSetEndPoint.svg"),
            QCoreApplication.translate("MyPlugin", "Create Sign"),
            self.iface.mainWindow())
        self.actionCreateSignRestriction.setCheckable(True)

        self.actionRemoveRestriction = QAction(
            QIcon(":/plugins/TOMs/resources/mActionDeleteTrack.svg"),
            QCoreApplication.translate("MyPlugin", "Remove Restriction"),
            self.iface.mainWindow())
        #self.actionRemoveRestriction.setCheckable(True)

        self.actionEditRestriction = QAction(
            QIcon(":/plugins/TOMs/resources/mActionEdit.svg"),
            QCoreApplication.translate("MyPlugin", "Edit Restriction"),
            self.iface.mainWindow())
        self.actionEditRestriction.setCheckable(True)

        self.actionSplitRestriction = QAction(
            QIcon(":/plugins/TOMs/resources/scissors.png"),
            QCoreApplication.translate("MyPlugin", "Split Restriction"),
            self.iface.mainWindow())
        self.actionSplitRestriction.setCheckable(True)

        self.actionCreateConstructionLine = QAction(
            QIcon(":/plugins/TOMs/resources/CreateConstructionLine.svg"),
            QCoreApplication.translate("MyPlugin", "Create construction line"),
            self.iface.mainWindow())
        self.actionCreateConstructionLine.setCheckable(True)

        # Add actions to the toolbar
        self.TOMsToolbar.addAction(self.actionSelectRestriction)
        self.TOMsToolbar.addAction(self.actionRestrictionDetails)
        self.TOMsToolbar.addAction(self.actionCreateBayRestriction)
        self.TOMsToolbar.addAction(self.actionCreateLineRestriction)
        self.TOMsToolbar.addAction(self.actionCreatePolygonRestriction)
        self.TOMsToolbar.addAction(self.actionCreateSignRestriction)
        self.TOMsToolbar.addAction(self.actionRemoveRestriction)
        self.TOMsToolbar.addAction(self.actionEditRestriction)
        self.TOMsToolbar.addAction(self.actionSplitRestriction)
        self.TOMsToolbar.addAction(self.actionCreateConstructionLine)

        # Connect action signals to slots
        self.actionSelectRestriction.triggered.connect(
            self.doSelectRestriction)
        self.actionRestrictionDetails.triggered.connect(
            self.doRestrictionDetails)
        self.actionCreateBayRestriction.triggered.connect(
            self.doCreateBayRestriction)
        self.actionCreateLineRestriction.triggered.connect(
            self.doCreateLineRestriction)
        self.actionCreatePolygonRestriction.triggered.connect(
            self.doCreatePolygonRestriction)
        self.actionCreateSignRestriction.triggered.connect(
            self.doCreateSignRestriction)
        self.actionRemoveRestriction.triggered.connect(
            self.doRemoveRestriction)
        self.actionEditRestriction.triggered.connect(self.doEditRestriction)
        self.actionSplitRestriction.triggered.connect(self.doSplitRestriction)
        self.actionCreateConstructionLine.triggered.connect(
            self.doCreateConstructionLine)

        pass

    def enableTOMsToolbarItems(self, restrictionTransaction):

        TOMsMessageLog.logMessage("In enableTOMsToolbarItems", level=Qgis.Info)

        self.actionSelectRestriction.setEnabled(True)
        self.actionRestrictionDetails.setEnabled(True)
        self.actionCreateBayRestriction.setEnabled(True)
        self.actionCreateLineRestriction.setEnabled(True)
        self.actionCreatePolygonRestriction.setEnabled(True)
        self.actionCreateSignRestriction.setEnabled(True)
        self.actionRemoveRestriction.setEnabled(True)
        self.actionEditRestriction.setEnabled(True)
        self.actionSplitRestriction.setEnabled(True)
        self.actionCreateConstructionLine.setEnabled(True)

        # set up a Transaction object
        # self.tableNames = TOMSLayers(self.iface)
        # self.tableNames.getLayers()
        self.restrictionTransaction = restrictionTransaction
        """self.proposalsManager.TOMsToolChanged.connect(
            functools.partial(self.restrictionTransaction.commitTransactionGroup, self.tableNames.PROPOSALS))"""

        #self.iface.mapCanvas().mapToolSet.connect(self.unCheckNodeTool)

        pass

    def unCheckNodeTool(self):
        self.actionEditRestriction.setChecked(False)

    def disableTOMsToolbarItems(self):

        TOMsMessageLog.logMessage("In disableTOMsToolbarItems",
                                  level=Qgis.Info)

        self.actionSelectRestriction.setEnabled(False)
        self.actionRestrictionDetails.setEnabled(False)
        self.actionCreateBayRestriction.setEnabled(False)
        self.actionCreateLineRestriction.setEnabled(False)
        self.actionCreatePolygonRestriction.setEnabled(False)
        self.actionCreateSignRestriction.setEnabled(False)
        self.actionRemoveRestriction.setEnabled(False)
        self.actionEditRestriction.setEnabled(False)
        self.actionSplitRestriction.setEnabled(False)
        self.actionCreateConstructionLine.setEnabled(False)

        pass

    def doSelectRestriction(self):
        """ Select point and then display details
        """

        TOMsMessageLog.logMessage("In doSelectRestriction", level=Qgis.Info)

        self.proposalsManager.TOMsToolChanged.emit()

        if not self.actionSelectRestriction.isChecked():
            self.actionSelectRestriction.setChecked(False)
            self.iface.mapCanvas().unsetMapTool(self.mapTool)
            self.mapTool = None
            # self.actionPan.connect()
            return

        self.actionSelectRestriction.setChecked(True)

        self.mapTool = GeometryInfoMapTool(self.iface)
        self.mapTool.setAction(self.actionSelectRestriction)
        self.iface.mapCanvas().setMapTool(self.mapTool)

    def doRestrictionDetails(self):
        """ Select point and then display details
        """
        TOMsMessageLog.logMessage("In doRestrictionDetails", level=Qgis.Info)

        self.proposalsManager.TOMsToolChanged.emit()

        # Get the current proposal from the session variables
        currProposalID = self.proposalsManager.currentProposal()

        currRestrictionLayer = self.iface.activeLayer()

        if currRestrictionLayer:

            TOMsMessageLog.logMessage(
                "In doRestrictionDetails. currLayer: " +
                str(currRestrictionLayer.name() + " Nr feats: " +
                    str(currRestrictionLayer.selectedFeatureCount())),
                level=Qgis.Info)

            if currRestrictionLayer.selectedFeatureCount() > 0:

                if currProposalID == 0:
                    # Ensure that no updates can occur for Proposal = 0
                    self.restrictionTransaction.rollBackTransactionGroup(
                    )  # stop any editing
                else:
                    self.restrictionTransaction.startTransactionGroup(
                    )  # start editing

                selectedRestrictions = currRestrictionLayer.selectedFeatures()
                for currRestriction in selectedRestrictions:
                    #self.restrictionForm = BayRestrictionForm(currRestrictionLayer, currRestriction)
                    #self.restrictionForm.show()

                    TOMsMessageLog.logMessage(
                        "In restrictionFormOpen. currRestrictionLayer: " +
                        str(currRestrictionLayer.name()),
                        level=Qgis.Info)

                    dialog = self.iface.getFeatureForm(currRestrictionLayer,
                                                       currRestriction)

                    self.setupRestrictionDialog(
                        dialog, currRestrictionLayer, currRestriction,
                        self.restrictionTransaction)  # connects signals

                    dialog.show()

                    #self.iface.openFeatureForm(self.currRestrictionLayer, self.currRestriction)

                    # Disconnect the signal that QGIS has wired up for the dialog to the button box.
                    # button_box.accepted.disconnect(restrictionsDialog.accept)
                    # Wire up our own signals.

                    #button_box.accepted.connect(self.restrictionTypeUtils.onSaveRestrictionDetails, currRestriction,
                    #                            currRestrictionLayer, self.dialog))

            else:

                reply = QMessageBox.information(
                    self.iface.mainWindow(), "Information",
                    "Select restriction first and then choose information button",
                    QMessageBox.Ok)

            pass

            #currRestrictionLayer.deselect(currRestriction.id())

        else:

            reply = QMessageBox.information(
                self.iface.mainWindow(), "Information",
                "Select restriction first and then choose information button",
                QMessageBox.Ok)

        pass

    def doCreateBayRestriction(self):

        TOMsMessageLog.logMessage("In doCreateBayRestriction", level=Qgis.Info)

        self.proposalsManager.TOMsToolChanged.emit()

        self.mapTool = None

        # Get the current proposal from the session variables
        currProposalID = self.proposalsManager.currentProposal()

        if currProposalID > 0:

            if self.actionCreateBayRestriction.isChecked():
                # self.iface.mapCanvas().setMapTool(CreateRestrictionTool)
                # self.actionCreateRestiction.setChecked(True)

                # set TOMs layer as active layer (for editing)...

                TOMsMessageLog.logMessage(
                    "In doCreateBayRestriction - tool activated",
                    level=Qgis.Info)

                # self.restrictionTransaction.startTransactionGroup()  # start editing

                #self.currLayer = QgsMapLayerRegistry.instance().mapLayersByName("Bays")[0]
                #currLayer = self.tableNames.BAYS
                currLayer = self.proposalsManager.tableNames.TOMsLayerDict.get(
                    "Bays")
                self.iface.setActiveLayer(currLayer)

                self.restrictionTransaction.startTransactionGroup(
                )  # start editing

                self.mapTool = CreateRestrictionTool(
                    self.iface, currLayer, self.proposalsManager,
                    self.restrictionTransaction)

                self.mapTool.setAction(self.actionCreateBayRestriction)
                self.iface.mapCanvas().setMapTool(self.mapTool)

                #self.currLayer.featureAdded.connect(self.proposalsManager.updateMapCanvas)

                #self.currLayer.editingStopped.connect (self.proposalsManager.updateMapCanvas)

            else:

                TOMsMessageLog.logMessage(
                    "In doCreateBayRestriction - tool deactivated",
                    level=Qgis.Info)

                self.iface.mapCanvas().unsetMapTool(self.mapTool)
                self.mapTool = None
                self.actionCreateBayRestriction.setChecked(False)

                #self.currLayer.featureAdded.disconnect(self.proposalsManager.updateMapCanvas)

                #self.currLayer.editingStopped()

        else:

            if self.actionCreateBayRestriction.isChecked():
                self.actionCreateBayRestriction.setChecked(False)
                if self.mapTool == None:
                    self.actionCreateBayRestriction.setChecked(False)

            reply = QMessageBox.information(
                self.iface.mainWindow(), "Information",
                "Changes to current data is not allowed. Changes are made via Proposals",
                QMessageBox.Ok)

        pass

    def doCreateLineRestriction(self):

        TOMsMessageLog.logMessage("In doCreateLineRestriction",
                                  level=Qgis.Info)

        self.proposalsManager.TOMsToolChanged.emit()

        self.mapTool = None

        # Get the current proposal from the session variables
        currProposalID = self.proposalsManager.currentProposal()

        if currProposalID > 0:

            if self.actionCreateLineRestriction.isChecked():
                # self.iface.mapCanvas().setMapTool(CreateRestrictionTool)
                # self.actionCreateRestiction.setChecked(True)

                # set TOMs layer as active layer (for editing)...

                TOMsMessageLog.logMessage(
                    "In doCreateLineRestriction - tool activated",
                    level=Qgis.Info)

                # self.restrictionTransaction.startTransactionGroup()  # start editing

                #self.currLayer = QgsMapLayerRegistry.instance().mapLayersByName("Lines")[0]
                #currLayer = self.tableNames.LINES
                currLayer = self.proposalsManager.tableNames.TOMsLayerDict.get(
                    "Lines")
                self.iface.setActiveLayer(currLayer)

                self.restrictionTransaction.startTransactionGroup(
                )  # start editing

                self.mapTool = CreateRestrictionTool(
                    self.iface, currLayer, self.proposalsManager,
                    self.restrictionTransaction)

                self.mapTool.setAction(self.actionCreateLineRestriction)
                self.iface.mapCanvas().setMapTool(self.mapTool)

                #self.currLayer.editingStopped.connect (self.proposalsManager.updateMapCanvas)

            else:

                TOMsMessageLog.logMessage(
                    "In doCreateLineRestriction - tool deactivated",
                    level=Qgis.Info)

                self.iface.mapCanvas().unsetMapTool(self.mapTool)
                self.mapTool = None
                self.actionCreateLineRestriction.setChecked(False)

        else:

            if self.actionCreateLineRestriction.isChecked():
                self.actionCreateLineRestriction.setChecked(False)
                if self.mapTool == None:
                    self.actionCreateLineRestriction.setChecked(False)

            reply = QMessageBox.information(
                self.iface.mainWindow(), "Information",
                "Changes to current data is not allowed. Changes are made via Proposals",
                QMessageBox.Ok)

        pass

    def doCreatePolygonRestriction(self):

        TOMsMessageLog.logMessage("In doCreatePolygonRestriction",
                                  level=Qgis.Info)

        self.proposalsManager.TOMsToolChanged.emit()

        self.mapTool = None

        # Get the current proposal from the session variables
        currProposalID = self.proposalsManager.currentProposal()

        if currProposalID > 0:

            if self.actionCreatePolygonRestriction.isChecked():
                # self.iface.mapCanvas().setMapTool(CreateRestrictionTool)
                # self.actionCreateRestiction.setChecked(True)

                # set TOMs layer as active layer (for editing)...

                TOMsMessageLog.logMessage(
                    "In doCreatePolygonRestriction - tool activated",
                    level=Qgis.Info)

                #self.currLayer = QgsMapLayerRegistry.instance().mapLayersByName("RestrictionPolygons")[0]
                #currLayer = self.tableNames.RESTRICTION_POLYGONS
                currLayer = self.proposalsManager.tableNames.TOMsLayerDict.get(
                    "RestrictionPolygons")
                self.iface.setActiveLayer(currLayer)
                self.restrictionTransaction.startTransactionGroup()

                self.mapTool = CreateRestrictionTool(
                    self.iface, currLayer, self.proposalsManager,
                    self.restrictionTransaction)

                self.mapTool.setAction(self.actionCreatePolygonRestriction)
                self.iface.mapCanvas().setMapTool(self.mapTool)

                #self.currLayer.editingStopped.connect (self.proposalsManager.updateMapCanvas)

            else:

                TOMsMessageLog.logMessage(
                    "In doCreatePolygonRestriction - tool deactivated",
                    level=Qgis.Info)

                self.iface.mapCanvas().unsetMapTool(self.mapTool)
                self.mapTool = None
                self.actionCreatePolygonRestriction.setChecked(False)

        else:

            if self.actionCreatePolygonRestriction.isChecked():
                self.actionCreatePolygonRestriction.setChecked(False)
                if self.mapTool == None:
                    self.actionCreatePolygonRestriction.setChecked(False)

            reply = QMessageBox.information(
                self.iface.mainWindow(), "Information",
                "Changes to current data is not allowed. Changes are made via Proposals",
                QMessageBox.Ok)

        pass

    def doCreateSignRestriction(self):

        TOMsMessageLog.logMessage("In doCreateSignRestriction",
                                  level=Qgis.Info)

        self.proposalsManager.TOMsToolChanged.emit()

        self.mapTool = None

        # Get the current proposal from the session variables
        currProposalID = self.proposalsManager.currentProposal()

        if currProposalID > 0:

            if self.actionCreateSignRestriction.isChecked():
                # self.iface.mapCanvas().setMapTool(CreateRestrictionTool)
                # self.actionCreateRestiction.setChecked(True)

                # set TOMs layer as active layer (for editing)...

                TOMsMessageLog.logMessage(
                    "In doCreateSignRestriction - tool activated",
                    level=Qgis.Info)

                # self.restrictionTransaction.startTransactionGroup()

                #self.currLayer = QgsMapLayerRegistry.instance().mapLayersByName("Signs")[0]
                #currLayer = self.tableNames.SIGNS
                currLayer = self.proposalsManager.tableNames.TOMsLayerDict.get(
                    "Signs")
                self.iface.setActiveLayer(currLayer)

                self.restrictionTransaction.startTransactionGroup()

                self.mapTool = CreateRestrictionTool(
                    self.iface, currLayer, self.proposalsManager,
                    self.restrictionTransaction)

                self.mapTool.setAction(self.actionCreateSignRestriction)
                self.iface.mapCanvas().setMapTool(self.mapTool)

                #self.currLayer.editingStopped.connect (self.proposalsManager.updateMapCanvas)

            else:

                TOMsMessageLog.logMessage(
                    "In doCreateSignRestriction - tool deactivated",
                    level=Qgis.Info)

                self.iface.mapCanvas().unsetMapTool(self.mapTool)
                self.mapTool = None
                self.actionCreateSignRestriction.setChecked(False)

                #self.currLayer.editingStopped()

        else:

            if self.actionCreateSignRestriction.isChecked():
                self.actionCreateSignRestriction.setChecked(False)
                if self.mapTool == None:
                    self.actionCreateSignRestriction.setChecked(False)

            reply = QMessageBox.information(
                self.iface.mainWindow(), "Information",
                "Changes to current data is not allowed. Changes are made via Proposals",
                QMessageBox.Ok)

        pass

    def doCreateConstructionLine(self):

        TOMsMessageLog.logMessage("In doCreateConstructionLine",
                                  level=Qgis.Info)

        self.proposalsManager.TOMsToolChanged.emit()

        self.mapTool = None

        if self.actionCreateConstructionLine.isChecked():
            # self.iface.mapCanvas().setMapTool(CreateRestrictionTool)
            # self.actionCreateRestiction.setChecked(True)

            # set TOMs layer as active layer (for editing)...

            TOMsMessageLog.logMessage(
                "In doCreateConstructionLine - tool activated",
                level=Qgis.Info)

            self.currLayer = QgsProject.instance().mapLayersByName(
                "ConstructionLines")[0]
            self.iface.setActiveLayer(self.currLayer)

            self.currLayer.startEditing()

            self.mapTool = CreateRestrictionTool(self.iface, self.currLayer,
                                                 self.proposalsManager,
                                                 self.restrictionTransaction)
            self.mapTool.setAction(self.actionCreateConstructionLine)
            self.iface.mapCanvas().setMapTool(self.mapTool)

            #self.currLayer.editingStopped.connect (self.proposalsManager.updateMapCanvas)

        else:

            TOMsMessageLog.logMessage(
                "In doCreateConstructionLine - tool deactivated",
                level=Qgis.Info)

            self.iface.mapCanvas().unsetMapTool(self.mapTool)
            self.mapTool = None
            self.actionCreateConstructionLine.setChecked(False)

            #self.currLayer.editingStopped ()

        pass

        #def onCreateRestriction(self, newRestriction):
        """ Called by map tool when a restriction is created
        """
        #TOMsMessageLog.logMessage("In onCreateRestriction - after shape created", level=Qgis.Info)

        #self.TOMslayer = QgsMapLayerRegistry.instance().mapLayersByName("TOMs_Layer")[0]

        # Obtain all the details for the restriction

        # Create the dislay geometry ...

    def doRemoveRestriction(self):
        # pass control to MapTool and then deal with Proposals issues from there ??
        TOMsMessageLog.logMessage("In doRemoveRestriction", level=Qgis.Info)

        self.proposalsManager.TOMsToolChanged.emit()

        #self.mapTool = None

        # Get the current proposal from the session variables
        self.currProposalID = self.proposalsManager.currentProposal()

        if self.currProposalID > 0:
            '''
            if self.actionRemoveRestriction.isChecked():
                # self.iface.mapCanvas().setMapTool(CreateRestrictionTool)
                # self.actionCreateRestiction.setChecked(True)

                # set TOMs layer as active layer (for editing)...

                TOMsMessageLog.logMessage("In doRemoveRestriction - tool activated", level=Qgis.Info)

                #self.TOMslayer = QgsMapLayerRegistry.instance().mapLayersByName("TOMs_Layer")[0]
                #iface.setActiveLayer(self.TOMslayer)

                self.mapTool = RemoveRestrictionTool(self.iface, self.onRemoveRestriction)
                self.mapTool.setAction(self.actionRemoveRestriction)
                self.iface.mapCanvas().setMapTool(self.mapTool)

                # self.currLayer.editingStopped.connect (self.proposalsManager.updateMapCanvas)

            else:

                TOMsMessageLog.logMessage("In doRemoveRestriction - tool deactivated", level=Qgis.Info)

                self.iface.mapCanvas().unsetMapTool(self.mapTool)
                self.mapTool = None
                self.actionRemoveRestriction.setChecked(False)
            '''

            currRestrictionLayer = self.iface.activeLayer()

            #currRestrictionLayer.editingStopped.connect(self.proposalsManager.updateMapCanvas)

            if currRestrictionLayer:

                TOMsMessageLog.logMessage(
                    "In doRemoveRestriction. currLayer: " +
                    str(currRestrictionLayer.name()),
                    level=Qgis.Info)

                if currRestrictionLayer.selectedFeatureCount() > 0:

                    selectedRestrictions = currRestrictionLayer.selectedFeatures(
                    )

                    self.restrictionTransaction.startTransactionGroup()

                    for currRestriction in selectedRestrictions:
                        self.onRemoveRestriction(currRestrictionLayer,
                                                 currRestriction)

                else:

                    reply = QMessageBox.information(
                        self.iface.mainWindow(), "Information",
                        "Select restriction for delete", QMessageBox.Ok)

            pass

        else:
            """if self.actionRemoveRestriction.isChecked():
                self.actionRemoveRestriction.setChecked(False)
                if self.mapTool == None:
                    self.actionRemoveRestriction.setChecked(False)"""

            reply = QMessageBox.information(
                self.iface.mainWindow(), "Information",
                "Changes to current data are not allowed. Changes are made via Proposals",
                QMessageBox.Ok)

        pass

    def onRemoveRestriction(self, currRestrictionLayer, currRestriction):
        TOMsMessageLog.logMessage("In onRemoveRestriction. currLayer: " +
                                  str(currRestrictionLayer.id()) +
                                  " CurrFeature: " + str(currRestriction.id()),
                                  level=Qgis.Info)

        #self.currRestrictionLayer = currRestrictionLayer
        #self.currRestriction = currRestriction

        currProposalID = self.proposalsManager.currentProposal()

        currRestrictionLayerID = self.getRestrictionLayerTableID(
            currRestrictionLayer)

        idxRestrictionID = currRestriction.fields().indexFromName(
            "RestrictionID")

        if self.restrictionInProposal(currRestriction[idxRestrictionID],
                                      currRestrictionLayerID, currProposalID):
            # remove the restriction from the RestrictionsInProposals table - and from the currLayer, i.e., it is totally removed.
            # NB: This is the only case of a restriction being truly deleted

            TOMsMessageLog.logMessage(
                "In onRemoveRestriction. Removing from RestrictionsInProposals and currLayer.",
                level=Qgis.Info)

            # Delete from RestrictionsInProposals
            result = self.deleteRestrictionInProposal(
                currRestriction[idxRestrictionID], currRestrictionLayerID,
                currProposalID)

            if result:
                TOMsMessageLog.logMessage(
                    "In onRemoveRestriction. Deleting restriction id: " +
                    str(currRestriction.id()),
                    level=Qgis.Info)
                deleteStatus = currRestrictionLayer.deleteFeature(
                    currRestriction.id())
                TOMsMessageLog.logMessage(
                    "In onRemoveRestriction. deleteStatus: " +
                    str(deleteStatus),
                    level=Qgis.Info)

            else:
                QMessageBox.information(None, "ERROR",
                                        ("Error deleting restriction ..."))

        else:
            # need to:
            #    - enter the restriction into the table RestrictionInProposals as closed, and
            #
            TOMsMessageLog.logMessage(
                "In onRemoveRestriction. Closing existing restriction.",
                level=Qgis.Info)

            self.addRestrictionToProposal(currRestriction[idxRestrictionID],
                                          currRestrictionLayerID,
                                          currProposalID,
                                          RestrictionAction.OPEN)  # 2 = Close

        # Now save all changes

        # Trying to unset map tool to force updates ...
        #self.iface.mapCanvas().unsetMapTool(self.iface.mapCanvas().mapTool())

        self.restrictionTransaction.commitTransactionGroup(None)
        #self.restrictionTransaction.deleteTransactionGroup()

        #currRestrictionLayer.triggerRepaint()  # This shouldn't be required ...

    def doEditRestriction(self):

        TOMsMessageLog.logMessage("In doEditRestriction - starting",
                                  level=Qgis.Info)

        self.proposalsManager.TOMsToolChanged.emit()

        self.mapTool = None

        # Get the current proposal from the session variables
        currProposalID = self.proposalsManager.currentProposal()

        if currProposalID > 0:

            if self.actionEditRestriction.isChecked():

                TOMsMessageLog.logMessage(
                    "In actionEditRestriction - tool being activated",
                    level=Qgis.Info)

                # Need to clear any other maptools ....   ********

                currRestrictionLayer = self.iface.activeLayer()

                if currRestrictionLayer:

                    TOMsMessageLog.logMessage(
                        "In doEditRestriction. currLayer: " +
                        str(currRestrictionLayer.name()),
                        level=Qgis.Info)

                    if currRestrictionLayer.selectedFeatureCount() > 0:

                        self.restrictionTransaction.startTransactionGroup()
                        """currRestriction = currRestrictionLayer.selectedFeatures()[0]
                        restrictionForEdit = self.prepareRestrictionForEdit (currRestriction, currRestrictionLayer)
                        currRestrictionLayer.deselect(currRestriction.id())
                        currRestrictionLayer.select(restrictionForEdit.id())
                        #currRestrictionLayer.selectByIds([editFeature.id()])"""

                        #self.actionEditRestriction.setChecked(True)
                        self.mapTool = TOMsNodeTool(
                            self.iface, self.proposalsManager,
                            self.restrictionTransaction
                        )  # This is where we use the Node Tool ... need canvas and panel??
                        """self.mapTool = TOMsNodeTool(self.iface,
                                                    self.proposalsManager, self.restrictionTransaction, restrictionForEdit, currRestrictionLayer)  # This is where we use the Node Tool ... need canvas and panel??"""
                        self.mapTool.setAction(self.actionEditRestriction)
                        self.iface.mapCanvas().setMapTool(self.mapTool)

                        #currRestrictionLayer.editingStopped.connect(self.proposalsManager.updateMapCanvas)

                    else:

                        reply = QMessageBox.information(
                            self.iface.mainWindow(), "Information",
                            "Select restriction for edit", QMessageBox.Ok)

                        self.actionEditRestriction.setChecked(False)
                        self.iface.mapCanvas().unsetMapTool(self.mapTool)
                        self.mapTool = None

                else:

                    reply = QMessageBox.information(
                        self.iface.mainWindow(), "Information",
                        "Select restriction for edit", QMessageBox.Ok)
                    self.actionEditRestriction.setChecked(False)
                    self.iface.mapCanvas().unsetMapTool(self.mapTool)
                    self.mapTool = None

            else:

                TOMsMessageLog.logMessage(
                    "In doEditRestriction - tool deactivated", level=Qgis.Info)

                self.actionEditRestriction.setChecked(False)
                self.iface.mapCanvas().unsetMapTool(self.mapTool)
                self.mapTool = None

            pass

        else:
            """if self.actionEditRestriction.isChecked():
                self.actionEditRestriction.setChecked(False)
                if self.mapTool == None:
                    self.actionEditRestriction.setChecked(False)"""

            reply = QMessageBox.information(
                self.iface.mainWindow(), "Information",
                "Changes to current data are not allowed. Changes are made via Proposals",
                QMessageBox.Ok)
            self.actionEditRestriction.setChecked(False)
            self.iface.mapCanvas().unsetMapTool(self.mapTool)
            self.mapTool = None

        pass

        TOMsMessageLog.logMessage("In doEditRestriction - leaving",
                                  level=Qgis.Info)

        pass

    def doSplitRestriction(self):

        TOMsMessageLog.logMessage("In doSplitRestriction - starting",
                                  level=Qgis.Info)

        self.proposalsManager.TOMsToolChanged.emit()

        self.mapTool = None

        # Get the current proposal from the session variables
        currProposalID = self.proposalsManager.currentProposal()

        if currProposalID > 0:

            if self.actionSplitRestriction.isChecked():

                TOMsMessageLog.logMessage(
                    "In doSplitRestriction - tool being activated",
                    level=Qgis.Info)

                # Need to clear any other maptools ....   ********

                currRestrictionLayer = self.iface.activeLayer()

                if currRestrictionLayer:

                    TOMsMessageLog.logMessage(
                        "In doSplitRestriction. currLayer: " +
                        str(currRestrictionLayer.name()),
                        level=Qgis.Info)

                    if currRestrictionLayer.selectedFeatureCount() > 0:

                        self.restrictionTransaction.startTransactionGroup()
                        """currRestriction = currRestrictionLayer.selectedFeatures()[0]
                        restrictionForEdit = self.prepareRestrictionForEdit (currRestriction, currRestrictionLayer)
                        currRestrictionLayer.deselect(currRestriction.id())
                        currRestrictionLayer.select(restrictionForEdit.id())
                        #currRestrictionLayer.selectByIds([editFeature.id()])"""

                        #self.actionEditRestriction.setChecked(True)
                        self.mapTool = TOMsSplitRestrictionTool(
                            self.iface, currRestrictionLayer,
                            self.proposalsManager, self.restrictionTransaction
                        )  # This is where we use the Node Tool ... need canvas and panel??
                        """self.mapTool = TOMsNodeTool(self.iface,
                                                    self.proposalsManager, self.restrictionTransaction, restrictionForEdit, currRestrictionLayer)  # This is where we use the Node Tool ... need canvas and panel??"""
                        self.mapTool.setAction(self.actionSplitRestriction)
                        self.iface.mapCanvas().setMapTool(self.mapTool)

                        #currRestrictionLayer.editingStopped.connect(self.proposalsManager.updateMapCanvas)

                    else:

                        reply = QMessageBox.information(
                            self.iface.mainWindow(), "Information",
                            "Select restriction for edit", QMessageBox.Ok)

                        self.actionSplitRestriction.setChecked(False)
                        self.iface.mapCanvas().unsetMapTool(self.mapTool)
                        self.mapTool = None

                else:

                    reply = QMessageBox.information(
                        self.iface.mainWindow(), "Information",
                        "Select restriction for edit", QMessageBox.Ok)
                    self.actionSplitRestriction.setChecked(False)
                    self.iface.mapCanvas().unsetMapTool(self.mapTool)
                    self.mapTool = None

            else:

                TOMsMessageLog.logMessage(
                    "In doSplitRestriction - tool deactivated",
                    level=Qgis.Info)

                self.actionSplitRestriction.setChecked(False)
                self.iface.mapCanvas().unsetMapTool(self.mapTool)
                self.mapTool = None

            pass

        else:
            """if self.actionEditRestriction.isChecked():
                self.actionEditRestriction.setChecked(False)
                if self.mapTool == None:
                    self.actionEditRestriction.setChecked(False)"""

            reply = QMessageBox.information(
                self.iface.mainWindow(), "Information",
                "Changes to current data are not allowed. Changes are made via Proposals",
                QMessageBox.Ok)
            self.actionSplitRestriction.setChecked(False)
            self.iface.mapCanvas().unsetMapTool(self.mapTool)
            self.mapTool = None

        pass

        TOMsMessageLog.logMessage("In doSplitRestriction - leaving",
                                  level=Qgis.Info)

        pass
Beispiel #19
0
class RulebaseSample(QgsMapTool):

    def start(self):
        maptool = self

        self.canvas.setMapTool(maptool)
        self.canvas.mapToolSet.connect(self.unsetTool) # このサンプル実行中に他のアイコンを押した場合

        self.layer = self.iface.activeLayer()

        # 元の設定を保存
        self.oldrenderer = self.layer.renderer().clone()

        # 設定
        self.renderer = QgsRuleBasedRenderer(QgsSymbol.defaultSymbol(self.layer.geometryType()))
        self.root_rule = self.renderer.rootRule()
        for label, expression, color_name in self.style_rules:
            rule = self.root_rule.children()[0].clone() # ラベル、フィルタ、色以外はデフォルト 
            rule.setLabel(label)
            rule.setFilterExpression(expression)
            rule.symbol().setColor(QColor(color_name))
            self.root_rule.appendChild(rule)
        self.root_rule.removeChildAt(0)

        self.layer.setRenderer(self.renderer)
        self.layer.triggerRepaint()


    def finish(self):
        # 元の設定に戻す
        self.layer.setRenderer(self.oldrenderer)
        self.layer.triggerRepaint()

        self.canvas.mapToolSet.disconnect(self.unsetTool)


    def __init__(self, iface):
        self.plugin_name = 'ルールによる色設定サンプル' # プラグイン名
        self.menu_pos    = 'サンプル'           # プラグインの登録場所
        self.toolbar     = True                 # Trueならツールバーにアイコンを表示する
        self.checkable   = True                 # Trueならプラグイン実行中はアイコンが凹んだままになる

        # ルール (ラベル, 式, 色)
        self.style_rules = (
            ('設定1', '"フィールド名" = \'〇〇\'', '#ff0000'), # この設定では赤
            ('設定2', '"フィールド名" = \'□□\'', '#00ff00'), # この設定では緑
            ('その他',  'ELSE',    '#ffffff')                  # それ以外は白
        )

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

        QgsMapTool.__init__(self, self.canvas)


    # このプラグイン実行中に他のアイコンが押された場合、アイコンを元の状態に戻す
    def unsetTool(self, tool):
        if not isinstance(tool, RulebaseSample):
            self.finish()
            self.action.setChecked(False)


    def initGui(self):
        icon = QIcon(os.path.dirname(__file__)+'/icon.png')
        self.action = QAction(icon, self.plugin_name, self.iface.mainWindow())
        self.action.triggered.connect(self.execSample) # アイコンを押下した時に実行されるメソッドを登録
        self.action.setCheckable(self.checkable)       # Trueだとアイコンを押下したら次に押下するまで凹んだままになる
        if self.toolbar:
            self.iface.addToolBarIcon(self.action)     # ツールバーにこのツールのアイコンを表示する
        self.iface.addPluginToMenu(self.menu_pos, self.action)
        

    # このプラグインを無効にしたときに呼ばれる
    def unload(self):
        self.iface.removePluginMenu(self.menu_pos, self.action)
        self.iface.removeToolBarIcon(self.action)


    # このツールのアイコンを押下したときに呼ばれる
    def execSample(self):
        if self.checkable:
            if self.action.isChecked(): # 凹状態になった
                self.previousMapTool = self.canvas.mapTool()  # 現在のマップツールを退避
                self.start()
            else:                       # 凸状態になった
                self.finish()
                self.canvas.setMapTool(self.previousMapTool)  # このツール実行前に戻す
        else:
            self.start()
Beispiel #20
0
class PetroProfileDialog(QtWidgets.QDialog, FORM_CLASS):
    """Dialog to show the petrographic drilling profiles"""

    def __init__(self, iface, parent=None):
        """Constructor."""
        super(PetroProfileDialog, self).__init__(parent)
        # Set up the user interface from Designer through FORM_CLASS.
        # After self.setupUi() you can access any designer object by doing
        # self.<objectname>, and you can use autoconnect slots - see
        # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html
        # #widgets-and-dialogs-with-auto-connect
        self.setupUi(self)
        self.iface = iface
        self._setupScene()
        self._setupGeoDirectionActions()
        self._xFac = None
        self._yFac = None

    def _setupScene(self):
        """Set up a new scene"""
        self.scene = QtWidgets.QGraphicsScene()
        self.view = self.findChild(QtWidgets.QGraphicsView, "graphicsView")
        self.view.setScene(self.scene)
        self.view.viewport().installEventFilter(self)

    def _setupGeoDirectionActions(self):
        """Set up actions for geo-directions"""
        self._nsAction = QAction("North \u2794 South", self)
        self._nsAction.triggered.connect(self.drawProfilesNorthSouth)
        self._nsAction.setEnabled(True)
        self._nsAction.setCheckable(True)

        self._snAction = QAction("South \u2794 North", self)
        self._snAction.triggered.connect(self.drawProfilesSouthNorth)
        self._snAction.setEnabled(True)
        self._snAction.setCheckable(True)

        self._weAction = QAction("West \u2794 East", self)
        self._weAction.triggered.connect(self.drawProfilesWestEast)
        self._weAction.setEnabled(True)
        self._weAction.setCheckable(True)

        self._ewAction = QAction("East \u2794 West", self)
        self._ewAction.triggered.connect(self.drawProfilesEastWest)
        self._ewAction.setEnabled(True)
        self._ewAction.setCheckable(True)

    def _getActions(self):
        """Get actions that are displayed in the context menu"""
        actions = []

        scaleAction = QAction("Scale...", self)
        scaleAction.triggered.connect(self._scale)
        scaleAction.setEnabled(True)
        actions.append(scaleAction)

        exportAction = QAction("Export as...", self)
        exportAction.triggered.connect(self._exportToFile)
        exportAction.setEnabled(True)
        actions.append(exportAction)

        sep = QAction("", self)
        sep.setSeparator(True)
        actions.append(sep)

        group = QActionGroup(self)

        group.addAction(self._nsAction)
        actions.append(self._nsAction)

        group.addAction(self._snAction)
        actions.append(self._snAction)

        group.addAction(self._weAction)
        actions.append(self._weAction)

        group.addAction(self._ewAction)
        actions.append(self._ewAction)

        sepAbout = QAction("", self)
        sepAbout.setSeparator(True)
        actions.append(sepAbout)

        manualAction = QAction("Manual...", self)
        manualAction.triggered.connect(self._openManual)
        manualAction.setEnabled(True)
        actions.append(manualAction)

        aboutAction = QAction("About...", self)
        aboutAction.triggered.connect(self._aboutPlugin)
        aboutAction.setEnabled(True)
        actions.append(aboutAction)

        return actions

    def contextMenuEvent(self, e):
        """Show context menu"""
        m = QMenu()
        for a in self._getActions():
            m.addAction(a)
        m.exec(e.globalPos())
        e.setAccepted(True)

    def showEvent(self, e):
        """Override showEvent"""
        super().showEvent(e)
        self.drawProfilesNorthSouth()

    def wheelEvent(self, e):
        """Zoom in/out"""
        delta = e.angleDelta()
        if delta.isNull():
            return
        s =  1.0
        if delta.y() > 0:
            s = 1.15
        else:
            s = 0.85
        self.view.scale(s, s)

    def eventFilter(self, obj, e):
        """Filter wheel event"""
        if e.type() == QEvent.Wheel:
            return True

        return super().eventFilter(obj, e)

    def _scale(self):
        """Provide scaling factor"""
        dlg = ScaleDialog(self._xFac, self._yFac, self)
        dlg.show()
        result = dlg.exec_() # Run the dialog event loop
        if result:
            self._xFac = dlg.xFac()
            self._yFac = dlg.yFac()
            if self._nsAction.isChecked():
                self.drawProfilesNorthSouth()
            elif self._snAction.isChecked():
                self.drawProfilesSouthNorth()
            elif self._weAction.isChecked():
                self.drawProfilesWestEast()
            elif self._ewAction.isChecked():
                self.drawProfilesEastWest()

    def _exportToFile(self):
        """Export drawing to file"""
        name = self._getFilename()
        if (name is None) or (len(name) == 0):
            return

        self._exportWithPainter(name)

    def _svgPaintDevice(self, name, sourceRect, targetRect):
        """Get QSvgGenerator as paint device"""
        generator = QSvgGenerator()
        generator.setDescription("This SVG was generated with the geoCore "
            "plugin of QGIS, written by T-Systems on site services GmbH")
        generator.setTitle("geoCore")
        generator.setSize(sourceRect.size().toSize())
        generator.setViewBox(targetRect)
        generator.setFileName(name)
        return generator

    def _imgPaintDevice(self, sourceRect):
        """Get QImage as paint device"""
        img = QImage(sourceRect.width(), sourceRect.height(),
            QImage.Format_ARGB32)
        img.fill(QColor("transparent"))
        return img

    def _getSourceAndTargetRect(self):
        """Returns the source and target rect for export"""
        self.scene.clearSelection()
        margin = 5
        sourceRect = self.scene.itemsBoundingRect()
        sourceRect.adjust(-margin, -margin, margin, margin)
        targetRect = QRectF(0, 0, sourceRect.width(), sourceRect.height())
        return sourceRect, targetRect

    def _exportWithPainter(self, name):
        """Export as image file"""
        try:
            sourceRect, targetRect = self._getSourceAndTargetRect()

            pd = None
            if Path(name).suffix.upper() == ".SVG":
                pd = self._svgPaintDevice(name, sourceRect, targetRect)
            else:
                pd = self._imgPaintDevice(sourceRect)

            painter = QPainter()
            painter.begin(pd)
            painter.setRenderHint(QPainter.Antialiasing)
            self.scene.render(painter, targetRect, sourceRect)
            painter.end()
            if hasattr(pd, 'save') and callable(pd.save):
                pd.save(name)
            QgsMessageLog.logMessage("exported to {}".format(name),
                level=Qgis.Info)
        except IOError:
            self.showMessage("Error", "Failed to export to {}".format(name),
                Qgis.Critical)

    def _getFilename(self):
        """Get file name via file dialog"""
        home = str(Path.home())
        name = QFileDialog.getSaveFileName(self, "Export to file", home,
            "Vector graphics (*.svg);;Images (*.png *.jpg)")

        if (name is None) or (len(name[0]) == 0):
            return None

        filename = name[0]
        suffix = Path(filename).suffix
        if len(suffix) == 0:
            if "svg" in name[1]:
                filename = filename + ".svg"
            else:
                filename = filename + ".png"

        return filename

    def drawProfilesNorthSouth(self):
        """Draw profiles in direction from north to south"""
        self._nsAction.setChecked(True)
        crit = lambda f: -f.attribute('ycoord') # north -> south
        self._drawProfiles(crit)

    def drawProfilesSouthNorth(self):
        """Draw profiles in direction from south to north"""
        self._snAction.setChecked(True)
        crit = lambda f: f.attribute('ycoord') # south -> north
        self._drawProfiles(crit)

    def drawProfilesWestEast(self):
        """Draw profiles in direction from west to east"""
        self._weAction.setChecked(True)
        crit = lambda f: f.attribute('xcoord') # west -> east
        self._drawProfiles(crit)

    def drawProfilesEastWest(self):
        """Draw profiles in direction from east to west"""
        self._ewAction.setChecked(True)
        crit = lambda f: -f.attribute('xcoord') # east -> west
        self._drawProfiles(crit)

    def _drawProfiles(self, sortCrit):
        """Draw the selected drilling profiles"""
        self.scene.clear()
        features = self._getSortedDrillingPositions(sortCrit)
        builder = ProfileBuilder(self.iface.activeLayer().name(),
            self.showMessage)
        pac = builder.getProfilesAndConnectors(features)
        painter = ProfilePainter(self.scene, self.view.width(), self.view.height())
        painter.applyScale(self._xFac, self._yFac)
        painter.paint(pac, len(pac) == 1)
        self.view.resetTransform()
        self.view.setSceneRect(self.scene.itemsBoundingRect())

    def _getSortedDrillingPositions(self, crit):
        """Sort profiles using given criterium"""
        features = self.iface.activeLayer().selectedFeatures()
        return sorted(features, key=crit)

    def _aboutPlugin(self):
        """Show the about dialog"""
        QMessageBox.about(self, "About",
            """<h1>geoCore</h1>
            <p>
            Copyright (C) 2019-2021  Gerrit Bette, T-Systems on site services GmbH<br>
            This program comes with ABSOLUTELY NO WARRANTY.
            This is free software, and you are welcome to redistribute it
            under certain conditions; see
            <a href="https://www.gnu.org/licenses/gpl-3.0-standalone.html">
            https://www.gnu.org/licenses</a> for details.
            </p>
            <p>
            Citation: G. Bette & M. Mennenga 2021:  t-systems-on-site-services-gmbh/geoCore v0.8 (Version v0.8).
            Zenodo. <a href=" http://doi.org/10.5281/zenodo.4548887"> http://doi.org/10.5281/zenodo.4548887</a>
            </p>
            <p>
            <a href="https://github.com/t-systems-on-site-services-gmbh/geoCore/blob/master/geoCore/help/usage.md">
            Manual</a>
            </p>
            """)

    def _openManual(self):
        """Open the user manual"""
        script_dir = os.path.dirname(__file__)
        rel_path = "help/usage.html"
        abs_file_path = os.path.join(script_dir, rel_path)
        os.system("start " + abs_file_path)

    def showMessage(self, title, message, level):
        """Display a message in the main window's messageBar"""
        self.iface.messageBar().pushMessage(title, message, level)
Beispiel #21
0
class OsCertificateStore:
    def __init__(self, iface):
        self.iface = iface
        self.action_setting = None
        self.action_about = None
        self.action_run = None
        if not self.is_supported():
            return

        # noinspection PyBroadException
        try:
            # noinspection PyPackageRequirements,PyUnresolvedReferences
            from .tests import testerplugin
            # noinspection PyUnresolvedReferences
            from qgistester.tests import addTestModule
            addTestModule(testerplugin, "OS Certificate Store")
        except:
            pass

    @staticmethod
    def log(msg, level=Qgis.Info):
        QgsMessageLog.logMessage(msg, "OS Certificate Store", level=level)

    @staticmethod
    def is_supported():
        """Check wether this plugin can run in this platform"""
        if platform == "linux" or platform == "linux2":
            # linux
            return False or TEST_ON_LINUX
        elif platform == "darwin":
            # OS X
            return False
        elif platform == "win32":
            # Windows...
            return True
        else:
            return False

    # noinspection PyPep8Naming
    def initGui(self):
        if not self.is_supported():
            return

        self.action_setting = QAction(
            self.tr("Import Windows intermediate certificate authorities "
                    "on startup"), self.iface.mainWindow())
        self.action_setting.setObjectName("enableoscertstore")
        self.action_setting.setCheckable(True)
        self.action_setting.setChecked(QgsSettings().value(SETTINGS_KEY +
                                                           '/import_enabled',
                                                           True,
                                                           type=bool))
        # noinspection PyUnresolvedReferences
        self.action_setting.changed.connect(self.setting_changed)
        self.iface.addPluginToMenu(self.tr("OS Certificate Store"),
                                   self.action_setting)

        icon_run = QIcon(os.path.dirname(__file__) + "/icons/certificate.svg")
        if QgsSettings().value(
                SETTINGS_KEY + '/import_successfully_run', True, type=bool) \
                or TEST_ON_LINUX:
            self.action_run = QAction(
                icon_run,
                self.tr(
                    "Reimport Windows intermediate certificate authorities"),
                self.iface.mainWindow())
            self.action_run.setObjectName("enableoscertstore")
            # noinspection PyUnresolvedReferences
            self.action_run.triggered.connect(partial(self.run_triggered,
                                                      True))
            self.iface.addPluginToMenu(self.tr("OS Certificate Store"),
                                       self.action_run)

        # noinspection PyArgumentList,PyCallByClass
        self.action_about = QAction(
            QgsApplication.getThemeIcon('/mActionHelpContents.svg'),
            "About...", self.iface.mainWindow())
        self.action_about.setObjectName("oscertstoreabout")
        # noinspection PyUnresolvedReferences
        self.action_about.triggered.connect(self.about_triggered)
        self.iface.addPluginToMenu(self.tr("OS Certificate Store"),
                                   self.action_about)

        # No toolbar and other menus
        # self.iface.addToolBarIcon(self.action)

        # Run on startup
        if QgsSettings().value(SETTINGS_KEY + '/import_enabled',
                               True,
                               type=bool):
            self.run_triggered(False)

    def unload(self):
        if not self.is_supported():
            return
        # noinspection PyBroadException
        try:
            # noinspection PyPackageRequirements,PyUnresolvedReferences
            from .tests import testerplugin
            # noinspection PyUnresolvedReferences
            from qgistester.tests import removeTestModule
            removeTestModule(testerplugin, self.tr("OS Certificate Store"))
        except:
            pass

        # noinspection PyBroadException
        try:
            # noinspection PyUnresolvedReferences
            from lessons import removeLessonsFolder
            folder = os.path.join(os.path.dirname(__file__), "_lessons")
            removeLessonsFolder(folder)
        except:
            pass

        self.iface.removePluginMenu(self.tr("OS Certificate Store"),
                                    self.action_about)
        self.iface.removePluginMenu(self.tr("OS Certificate Store"),
                                    self.action_setting)
        if self.action_run is not None:
            self.iface.removePluginMenu(self.tr("OS Certificate Store"),
                                        self.action_run)

    def setting_changed(self):
        if not self.is_supported():
            return
        self.log("Import at startup: %s" % self.action_setting.isChecked())
        QgsSettings().setValue(SETTINGS_KEY + '/import_enabled',
                               self.action_setting.isChecked())

    def run_triggered(self, notify):
        self.log("Importing intermediate certificates ...")
        try:
            from .certs_importer import run
            QgsSettings().setValue(SETTINGS_KEY + '/import_successfully_run',
                                   run(self))
            if notify:
                self.iface.messageBar().pushMessage(
                    self.tr("Success"),
                    self.tr("Intermediate certificates imported correctly "
                            "(see logs for details)."),
                    level=Qgis.Info)
        except Exception as ex:
            self.log("Error importing intermediate certificates: %s" % ex)
            QgsSettings().setValue(SETTINGS_KEY + '/import_successfully_run',
                                   False)
            if notify:
                self.iface.messageBar().pushMessage(
                    self.tr("Error"),
                    self.tr("There was an error importing intermediate "
                            "certificates (see the logs for details)."),
                    level=Qgis.Critical)

    def about_triggered(self):
        # noinspection PyArgumentList
        dlg = QgsMessageOutput.createMessageOutput()
        dlg.setTitle(self.tr("Plugin info"))
        dlg.setMessage(self._plugin_details("oscertstore"),
                       QgsMessageOutput.MessageHtml)
        dlg.showMessage()

    @staticmethod
    def tr(msg):
        return msg

    # noinspection PyUnusedLocal
    def _plugin_details(self, namespace):
        config = DictParser()
        config.read_file(
            open(
                os.path.join(os.path.realpath(os.path.dirname(__file__)),
                             'metadata.txt')))
        plugin = config.as_dict()['general']

        html = '<style>body, table {padding:0px; margin:0px; ' \
               'font-family:verdana; font-size: 1.1em;}</style>'
        html += '<body>'
        html += '<table cellspacing="4" width="100%"><tr><td>'
        html += '<h1>{}</h1>'.format(plugin.get('name'))
        html += '<h3>{}</h3>'.format(plugin.get('description'))

        if plugin.get('about'):
            html += plugin.get('about').replace('\n', '<br/>')

        html += '<br/><br/>'

        if plugin.get('category'):
            html += '{}: {} <br/>'.format(self.tr('Category'),
                                          plugin.get('category'))

        if plugin.get('tags'):
            html += '{}: {} <br/>'.format(self.tr('Tags'), plugin.get('tags'))

        if (plugin.get('homepage') or plugin.get('tracker')
                or plugin.get('code_repository')):
            html += self.tr('More info:')

            if plugin.get('homepage'):
                html += '<a href="{}">{}</a> &nbsp;'.format(
                    plugin.get('homepage'), self.tr('homepage'))

            if plugin.get('tracker'):
                html += '<a href="{}">{}</a> &nbsp;'.format(
                    plugin.get('tracker'), self.tr('bug_tracker'))

            if plugin.get('code_repository'):
                html += '<a href="{}">{}</a> &nbsp;'.format(
                    plugin.get('code_repository'), self.tr('code_repository'))

            html += '<br/>'

        html += '<br/>'

        if plugin.get('author_email'):
            html += '{}: <a href="mailto:{}">{}</a>'.format(
                self.tr('Author email'), plugin.get('author_email'),
                plugin.get('author_name'))
            html += '<br/><br/>'
        elif plugin.get('author'):
            html += '{}: {}'.format(self.tr('Author'), plugin.get('author'))
            html += '<br/><br/>'

        if plugin.get('version_installed'):
            ver = plugin.get('version_installed')
            if ver == '-1':
                ver = '?'

            html += self.tr('Installed version: {} (in {})<br/>'.format(
                ver, plugin.get('library')))

        if plugin.get('version_available'):
            html += self.tr('Available version: {} (in {})<br/>'.format(
                plugin.get('version_available'), plugin.get('zip_repository')))

        if plugin.get('changelog'):
            html += '<br/>'
            changelog = self.tr('Changelog:<br/>{} <br/>'.format(
                plugin.get('changelog')))
            html += changelog.replace('\n', '<br/>')

        html += '</td></tr></table>'
        html += '</body>'

        return html
class GetRasterPixelValueSample(QgsMapTool):
    def canvasMoveEvent(self, event):
        print(
            str(
                self.gr.getValueInterpolation(
                    self.toMapCoordinates(event.pos()))))

    def start(self):
        self.gr = GetRasterPixelValueClass(self.iface.activeLayer())

        maptool = self

        self.canvas.setMapTool(maptool)
        self.canvas.mapToolSet.connect(
            self.unsetTool)  # このサンプル実行中に他のアイコンを押した場合

    def finish(self):
        self.canvas.mapToolSet.disconnect(self.unsetTool)

    def __init__(self, iface):
        self.plugin_name = 'ピクセル値取得サンプル'  # プラグイン名
        self.menu_pos = 'サンプル'  # プラグインの登録場所(このサンプルの場合、メニューの「プラグイン/雛形/ダイアログ無し雛形」)
        self.toolbar = True  # Trueならツールバーにアイコンを表示する
        self.checkable = True  # Trueならプラグイン実行中はアイコンが凹んだままになる

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

        QgsMapTool.__init__(self, self.canvas)

    # このプラグイン実行中に他のアイコンが押された場合、アイコンを元の状態に戻す
    def unsetTool(self, tool):
        if not isinstance(tool, GetRasterPixelValueSample):
            self.finish()
            self.action.setChecked(False)

    def initGui(self):
        icon = QIcon(os.path.dirname(__file__) + '/icon.png')
        self.action = QAction(icon, self.plugin_name, self.iface.mainWindow())
        self.action.triggered.connect(
            self.execSample)  # アイコンを押下した時に実行されるメソッドを登録
        self.action.setCheckable(
            self.checkable)  # Trueだとアイコンを押下したら次に押下するまで凹んだままになる
        if self.toolbar:
            self.iface.addToolBarIcon(self.action)  # ツールバーにこのツールのアイコンを表示する
        self.iface.addPluginToMenu(self.menu_pos, self.action)

    # このプラグインを無効にしたときに呼ばれる
    def unload(self):
        self.iface.removePluginMenu(self.menu_pos, self.action)
        self.iface.removeToolBarIcon(self.action)

    # このツールのアイコンを押下したときに呼ばれる
    def execSample(self):
        if self.checkable:
            if self.action.isChecked():  # 凹状態になった
                self.previousMapTool = self.canvas.mapTool()  # 現在のマップツールを退避
                self.start()
            else:  # 凸状態になった
                self.finish()
                self.canvas.setMapTool(self.previousMapTool)  # このツール実行前に戻す
        else:
            self.start()
Beispiel #23
0
class FeatureSelectSample:
    def __init__(self, iface):

        # Save reference to the QGIS interface
        self.iface = iface
        self.canvas = self.iface.mapCanvas()
        # initialize plugin directory
        self.plugin_dir = os.path.dirname(__file__)

        # プラグインの登録場所
        self.menu_pos = 'サンプル フューチャー選択'
        # キャンバスウィンドウ上でのマウスイベントの設定
        self.mouseEventSample = FeatureSelectionTool(self.canvas)

    def initGui(self):
        icon = QIcon(self.plugin_dir + '/icon.png')
        self.action = QAction(icon, '一つ選択→属性編集', self.iface.mainWindow())
        self.action.triggered.connect(
            self.execSample)  # アイコンを押下した時に実行されるメソッドを登録
        self.action.setCheckable(True)  # Trueだとアイコンを押下したら次に押下するまで凹んだままになる。
        #self.iface.addToolBarIcon(self.action)         # ツールバーにアイコンを表示させたいなら#外して
        self.iface.addPluginToMenu(self.menu_pos, self.action)

    # このサンプル以外のアイコンが押された場合、アイコンを元の状態に戻す
    def unsetTool(self, tool):
        if not isinstance(tool, FeatureSelectSample):
            try:
                self.mouseEventSample.featureIdentified.disconnect(
                    self.editAttribute)
            except Exception:
                pass

            self.iface.layerTreeView().currentLayerChanged.disconnect(
                self.changeLayer)

            self.canvas.mapToolSet.disconnect(self.unsetTool)
            self.canvas.unsetMapTool(self.mouseEventSample)

            self.action.setChecked(False)

    def execSample(self):
        if self.action.isChecked():
            self.layer = self.iface.activeLayer()

            if (self.layer == None) or (type(self.layer)
                                        is not qgis._core.QgsVectorLayer):
                QMessageBox.about(None, '警告', 'ベクタレイヤを選択してから実行してください')
                self.action.setChecked(False)
                return

            self.previousMapTool = self.canvas.mapTool()
            self.canvas.setMapTool(self.mouseEventSample)
            self.canvas.mapToolSet.connect(self.unsetTool)

            self.iface.layerTreeView().currentLayerChanged.connect(
                self.changeLayer)  # アクティブレイヤが変更された時に呼ぶメソッドを登録
            self.mouseEventSample.setLayer(self.iface.activeLayer())
            self.mouseEventSample.featureIdentified.connect(self.editAttribute)
        else:
            self.mouseEventSample.featureIdentified.disconnect(
                self.editAttribute)
            self.iface.layerTreeView().currentLayerChanged.disconnect(
                self.changeLayer)
            self.canvas.mapToolSet.disconnect(self.unsetTool)
            self.canvas.unsetMapTool(self.mouseEventSample)
            self.canvas.setMapTool(self.previousMapTool)

    # フューチャーを一つ選択した時に呼ばれる。
    def editAttribute(self, feature):
        self.layer.removeSelection()
        self.layer.select(feature.id())

        self.layer.startEditing()  # レイヤを編集状態にする

        # 選択しているフューチャーの属性フォーム表示
        self.attdlg = self.iface.getFeatureForm(self.layer, feature)
        self.attdlg.setMode(qgis.gui.QgsAttributeEditorContext.SingleEditMode)
        self.attdlg.finished.connect(self.commitEdit)
        self.attdlg.show()

    def commitEdit(self, result):
        if result == 1:
            self.layer.commitChanges()
        else:
            self.layer.rollBack()
        self.attdlg.finished.disconnect(self.commitEdit)

    # レイヤウィンドウでレイヤを選択したときに呼ばれる
    def changeLayer(self, layer):
        if (layer == None) or (type(layer) is not qgis.core.QgsVectorLayer):
            return

        self.layer.removeSelection()
        self.layer = layer
        self.mouseEventSample.setLayer(self.layer)
class SplitFeaturesOnSteroidsPlugin(object):
    mapTool = None

    def __init__(self, iface):
        self.iface = iface

    def initGui(self):
        self.toolbar = self.iface.addToolBar(name)
        self.toolbar.setObjectName(name)

        icon = QIcon(":/plugins/SplitPolygonShowingAreas/icon.png")
        self.action = QAction(icon, name, self.iface.mainWindow())
        self.action.setCheckable(True)
        self.action.triggered.connect(self.onClick)
        self.toolbar.addAction(self.action)

        self.actionMoveVertices = QAction(
            QIcon(":/plugins/SplitPolygonShowingAreas/moveVertices.png"),
            moveVerticesName, self.iface.mainWindow())
        self.actionMoveVertices.setCheckable(True)
        self.actionMoveVertices.triggered.connect(self.onClickMoveVertices)
        self.toolbar.addAction(self.actionMoveVertices)

        self.actionAddVertices = QAction(
            QIcon(":/plugins/SplitPolygonShowingAreas/addVertices.png"),
            addVerticesName, self.iface.mainWindow())
        self.actionAddVertices.setCheckable(True)
        self.actionAddVertices.triggered.connect(self.onClickAddVertices)
        self.toolbar.addAction(self.actionAddVertices)

        self.actionRemoveVertices = QAction(
            QIcon(":/plugins/SplitPolygonShowingAreas/removeVertices.png"),
            removeVerticesName, self.iface.mainWindow())
        self.actionRemoveVertices.setCheckable(True)
        self.actionRemoveVertices.triggered.connect(self.onClickRemoveVertices)
        self.toolbar.addAction(self.actionRemoveVertices)

        self.actionMoveSegment = QAction(
            QIcon(":/plugins/SplitPolygonShowingAreas/moveSegment.png"),
            moveSegmentName, self.iface.mainWindow())
        self.actionMoveSegment.setCheckable(True)
        self.actionMoveSegment.triggered.connect(self.onClickMoveSegment)
        self.toolbar.addAction(self.actionMoveSegment)

        self.actionLineClose = QAction(
            QIcon(":/plugins/SplitPolygonShowingAreas/lineClose.png"),
            closeLineName, self.iface.mainWindow())
        self.actionLineClose.setCheckable(False)
        self.actionLineClose.triggered.connect(self.onClickLineClose)
        self.toolbar.addAction(self.actionLineClose)

        self.actionLineOpen = QAction(
            QIcon(":/plugins/SplitPolygonShowingAreas/lineOpen.png"),
            openLineName, self.iface.mainWindow())
        self.actionLineOpen.setCheckable(False)
        self.actionLineOpen.triggered.connect(self.onClickLineOpen)
        self.toolbar.addAction(self.actionLineOpen)

        self.actionMoveLine = QAction(
            QIcon(":/plugins/SplitPolygonShowingAreas/moveLine.png"),
            moveLineName, self.iface.mainWindow())
        self.actionMoveLine.setCheckable(True)
        self.actionMoveLine.triggered.connect(self.onClickMoveLine)
        self.toolbar.addAction(self.actionMoveLine)

        self.iface.addPluginToMenu(name, self.action)
        self.iface.addPluginToMenu(name, self.actionMoveVertices)
        self.iface.addPluginToMenu(name, self.actionAddVertices)
        self.iface.addPluginToMenu(name, self.actionRemoveVertices)
        self.iface.addPluginToMenu(name, self.actionMoveSegment)
        self.iface.addPluginToMenu(name, self.actionLineClose)
        self.iface.addPluginToMenu(name, self.actionLineOpen)
        self.iface.addPluginToMenu(name, self.actionMoveLine)
        self.help_action = QAction("Help", self.iface.mainWindow())
        self.help_action.triggered.connect(self.onHelp)
        self.iface.addPluginToMenu(name, self.help_action)

        self.iface.currentLayerChanged.connect(self.currentLayerChanged)

        self.enableTool()

    def disableAll(self):
        self.actionMoveVertices.setChecked(False)
        self.actionMoveVertices.setEnabled(False)
        self.actionAddVertices.setChecked(False)
        self.actionAddVertices.setEnabled(False)
        self.actionRemoveVertices.setChecked(False)
        self.actionRemoveVertices.setEnabled(False)
        self.actionMoveSegment.setChecked(False)
        self.actionMoveSegment.setEnabled(False)
        self.actionLineClose.setEnabled(False)
        self.actionLineOpen.setEnabled(False)
        self.actionMoveLine.setChecked(False)
        self.actionMoveLine.setEnabled(False)

    def unload(self):
        self.iface.removePluginMenu(name, self.action)
        self.iface.removePluginMenu(name, self.actionMoveVertices)
        self.iface.removePluginMenu(name, self.actionAddVertices)
        self.iface.removePluginMenu(name, self.actionRemoveVertices)
        self.iface.removePluginMenu(name, self.actionMoveSegment)
        self.iface.removePluginMenu(name, self.actionLineClose)
        self.iface.removePluginMenu(name, self.actionLineOpen)
        self.iface.removePluginMenu(name, self.actionMoveLine)
        self.iface.removePluginMenu(name, self.help_action)
        self.iface.removeToolBarIcon(self.action)
        self.iface.removeToolBarIcon(self.actionMoveVertices)
        self.iface.removeToolBarIcon(self.actionAddVertices)
        self.iface.removeToolBarIcon(self.actionRemoveVertices)
        self.iface.removeToolBarIcon(self.actionMoveSegment)
        self.iface.removeToolBarIcon(self.actionLineClose)
        self.iface.removeToolBarIcon(self.actionLineOpen)
        self.iface.removeToolBarIcon(self.actionMoveLine)

    def onHelp(self):
        qgis.utils.showPluginHelp(filename="index")

    def onClick(self):
        self.disableAll()
        if not self.action.isChecked():
            if self.mapTool != None and len(self.mapTool.capturedPoints) >= 2:
                reply = QMessageBox.question(
                    self.iface.mapCanvas(), "Cancel splitting line?",
                    "Your splitting line has " +
                    str(len(self.mapTool.capturedPoints)) +
                    " points. Do you want to remove it?", QMessageBox.Yes,
                    QMessageBox.No)
                if reply == QMessageBox.No:
                    self.action.setChecked(True)
                    self.mapTool.restoreAction()
                    return

            if self.mapTool != None:
                self.mapTool.stopCapturing()
            self.iface.mapCanvas().unsetMapTool(self.mapTool)
            self.mapTool = None
            return
        layer = self.iface.activeLayer()
        if layer == None or not isinstance(layer, QgsVectorLayer) or (
                layer.wkbType() != QgsWkbTypes.Polygon
                and layer.wkbType() != QgsWkbTypes.MultiPolygon
                and layer.wkbType() != QgsWkbTypes.Polygon25D
                and layer.wkbType() != QgsWkbTypes.MultiPolygon25D):
            self.iface.messageBar().pushMessage(
                "No Polygon Vectorial Layer Selected",
                "Select a Polygon Vectorial Layer first",
                level=QgsMessageBar.WARNING)
            self.action.setChecked(False)
            return
        selectedFeatures = layer.selectedFeatures()
        if selectedFeatures == None or len(selectedFeatures) == 0:
            self.iface.messageBar().pushMessage("No Features Selected",
                                                "Select some features first",
                                                level=QgsMessageBar.WARNING)
            self.action.setChecked(False)
            return

        self.action.setChecked(True)
        self.mapTool = SplitMapTool(
            self.iface.mapCanvas(), layer, self.actionMoveVertices,
            self.actionAddVertices, self.actionRemoveVertices,
            self.actionMoveSegment, self.actionLineClose, self.actionLineOpen,
            self.actionMoveLine)
        self.mapTool.setAction(self.action)
        self.iface.mapCanvas().setMapTool(self.mapTool)
        self.mapTool.redrawActions()

    def onClickMoveVertices(self):
        if not self.actionMoveVertices.isChecked():
            if self.mapTool != None:
                self.mapTool.stopMovingVertices()
            return

        self.mapTool.startMovingVertices()

    def onClickAddVertices(self):
        if not self.actionAddVertices.isChecked():
            if self.mapTool != None:
                self.mapTool.stopAddingVertices()
            return

        self.actionAddVertices.setChecked(True)
        self.mapTool.startAddingVertices()

    def onClickRemoveVertices(self):
        if not self.actionRemoveVertices.isChecked():
            if self.mapTool != None:
                self.mapTool.stopRemovingVertices()
            return

        self.actionRemoveVertices.setChecked(True)
        self.mapTool.startRemovingVertices()

    def onClickMoveSegment(self):
        if not self.actionMoveSegment.isChecked():
            if self.mapTool != None:
                self.mapTool.stopMovingSegment()
            return

        self.actionMoveSegment.setChecked(True)
        self.mapTool.startMovingSegment()

    def onClickLineClose(self):
        self.mapTool.lineClose()

    def onClickLineOpen(self):
        self.mapTool.lineOpen()

    def onClickMoveLine(self):
        if not self.actionMoveLine.isChecked():
            if self.mapTool != None:
                self.mapTool.stopMovingLine()
            return

        self.actionMoveLine.setChecked(True)
        self.mapTool.startMovingLine()

    def currentLayerChanged(self):
        if self.mapTool != None:
            self.mapTool.stopCapturing()

        layer = self.iface.activeLayer()
        if layer != None:
            try:
                layer.editingStarted.disconnect(self.layerEditingChanged)
            except:
                pass
            try:
                layer.editingStopped.disconnect(self.layerEditingChanged)
            except:
                pass
            try:
                layer.selectionChanged.disconnect(self.layerEditingChanged)
            except:
                pass

            if isinstance(layer, QgsVectorLayer):
                layer.editingStarted.connect(self.layerEditingChanged)
                layer.editingStopped.connect(self.layerEditingChanged)
                layer.selectionChanged.connect(self.layerSelectionChanged)

        self.enableTool()

    def layerEditingChanged(self):
        if self.mapTool != None:
            self.mapTool.stopCapturing()
        self.enableTool()

    def layerSelectionChanged(self):
        if self.mapTool != None:
            self.mapTool.stopCapturing()
        self.enableTool()

    def enableTool(self):
        self.disableAll()
        self.action.setEnabled(False)
        layer = self.iface.activeLayer()

        if layer != None and isinstance(layer, QgsVectorLayer):
            selectedFeatures = layer.selectedFeatures()
            if isinstance(layer, QgsVectorLayer) and (
                    layer.wkbType() == QgsWkbTypes.Polygon
                    or layer.wkbType() == QgsWkbTypes.MultiPolygon
                    or layer.wkbType() == QgsWkbTypes.Polygon25D
                    or layer.wkbType() == QgsWkbTypes.MultiPolygon25D
            ) and selectedFeatures != None and len(
                    selectedFeatures) > 0 and layer.isEditable():
                self.action.setEnabled(True)
Beispiel #25
0
class ProcessingPlugin(QObject):

    def __init__(self, iface):
        super().__init__()
        self.iface = iface
        self.options_factory = None
        self.drop_handler = None
        self.item_provider = None
        self.locator_filter = None
        self.edit_features_locator_filter = None
        self.initialized = False
        self.initProcessing()

    def initProcessing(self):
        if not self.initialized:
            self.initialized = True
            Processing.initialize()

    def initGui(self):
        # port old log, ONCE ONLY!
        settings = QgsSettings()
        if not settings.value("/Processing/hasPortedOldLog", False, bool):
            processing_history_provider = QgsGui.historyProviderRegistry().providerById('processing')
            if processing_history_provider:
                processing_history_provider.portOldLog()
                settings.setValue("/Processing/hasPortedOldLog", True)

        self.options_factory = ProcessingOptionsFactory()
        self.options_factory.setTitle(self.tr('Processing'))
        iface.registerOptionsWidgetFactory(self.options_factory)
        self.drop_handler = ProcessingDropHandler()
        iface.registerCustomDropHandler(self.drop_handler)
        self.item_provider = ProcessingDataItemProvider()
        QgsApplication.dataItemProviderRegistry().addProvider(self.item_provider)
        self.locator_filter = AlgorithmLocatorFilter()
        iface.registerLocatorFilter(self.locator_filter)
        # Invalidate the locator filter for in-place when active layer changes
        iface.currentLayerChanged.connect(lambda _: self.iface.invalidateLocatorResults())
        self.edit_features_locator_filter = InPlaceAlgorithmLocatorFilter()
        iface.registerLocatorFilter(self.edit_features_locator_filter)

        self.toolbox = ProcessingToolbox()
        self.iface.addDockWidget(Qt.RightDockWidgetArea, self.toolbox)
        self.toolbox.hide()
        self.toolbox.visibilityChanged.connect(self.toolboxVisibilityChanged)

        self.toolbox.executeWithGui.connect(self.executeAlgorithm)

        self.resultsDock = ResultsDock()
        self.iface.addDockWidget(Qt.RightDockWidgetArea, self.resultsDock)
        self.resultsDock.hide()

        self.menu = QMenu(self.iface.mainWindow().menuBar())
        self.menu.setObjectName('processing')
        self.menu.setTitle(self.tr('Pro&cessing'))

        self.toolboxAction = QAction(self.tr('&Toolbox'), self.iface.mainWindow())
        self.toolboxAction.setCheckable(True)
        self.toolboxAction.setObjectName('toolboxAction')
        self.toolboxAction.setIcon(
            QgsApplication.getThemeIcon("/processingAlgorithm.svg"))
        self.iface.registerMainWindowAction(self.toolboxAction,
                                            QKeySequence('Ctrl+Alt+T').toString(QKeySequence.NativeText))
        self.toolboxAction.toggled.connect(self.openToolbox)
        self.iface.attributesToolBar().insertAction(self.iface.actionOpenStatisticalSummary(), self.toolboxAction)
        self.menu.addAction(self.toolboxAction)

        self.modelerAction = QAction(
            QgsApplication.getThemeIcon("/processingModel.svg"),
            QCoreApplication.translate('ProcessingPlugin', '&Graphical Modeler…'), self.iface.mainWindow())
        self.modelerAction.setObjectName('modelerAction')
        self.modelerAction.triggered.connect(self.openModeler)
        self.iface.registerMainWindowAction(self.modelerAction,
                                            QKeySequence('Ctrl+Alt+G').toString(QKeySequence.NativeText))
        self.menu.addAction(self.modelerAction)

        self.historyAction = QAction(
            QgsApplication.getThemeIcon("/mIconHistory.svg"),
            QCoreApplication.translate('ProcessingPlugin', '&History…'), self.iface.mainWindow())
        self.historyAction.setObjectName('historyAction')
        self.historyAction.triggered.connect(self.openHistory)
        self.iface.registerMainWindowAction(self.historyAction,
                                            QKeySequence('Ctrl+Alt+H').toString(QKeySequence.NativeText))
        self.menu.addAction(self.historyAction)
        self.toolbox.processingToolbar.addAction(self.historyAction)

        self.resultsAction = QAction(
            QgsApplication.getThemeIcon("/processingResult.svg"),
            self.tr('&Results Viewer'), self.iface.mainWindow())
        self.resultsAction.setObjectName('resultsViewer')
        self.resultsAction.setCheckable(True)
        self.iface.registerMainWindowAction(self.resultsAction,
                                            QKeySequence('Ctrl+Alt+R').toString(QKeySequence.NativeText))

        self.menu.addAction(self.resultsAction)
        self.toolbox.processingToolbar.addAction(self.resultsAction)
        self.resultsDock.visibilityChanged.connect(self.resultsAction.setChecked)
        self.resultsAction.toggled.connect(self.resultsDock.setUserVisible)

        self.toolbox.processingToolbar.addSeparator()

        self.editInPlaceAction = QAction(
            QgsApplication.getThemeIcon("/mActionProcessSelected.svg"),
            self.tr('Edit Features In-Place'), self.iface.mainWindow())
        self.editInPlaceAction.setObjectName('editInPlaceFeatures')
        self.editInPlaceAction.setCheckable(True)
        self.editInPlaceAction.toggled.connect(self.editSelected)
        self.menu.addAction(self.editInPlaceAction)
        self.toolbox.processingToolbar.addAction(self.editInPlaceAction)

        self.toolbox.processingToolbar.addSeparator()

        self.optionsAction = QAction(
            QgsApplication.getThemeIcon("/mActionOptions.svg"),
            self.tr('Options'), self.iface.mainWindow())
        self.optionsAction.setObjectName('optionsAction')
        self.optionsAction.triggered.connect(self.openProcessingOptions)
        self.toolbox.processingToolbar.addAction(self.optionsAction)

        menuBar = self.iface.mainWindow().menuBar()
        menuBar.insertMenu(
            self.iface.firstRightStandardMenu().menuAction(), self.menu)

        self.menu.addSeparator()

        initializeMenus()
        createMenus()
        createButtons()

        # In-place editing button state sync
        self.iface.currentLayerChanged.connect(self.sync_in_place_button_state)
        self.iface.mapCanvas().selectionChanged.connect(self.sync_in_place_button_state)
        self.iface.actionToggleEditing().triggered.connect(partial(self.sync_in_place_button_state, None))
        self.sync_in_place_button_state()

        # Sync project models
        self.projectModelsMenu = None
        self.projectMenuAction = None
        self.projectMenuSeparator = None

        self.projectProvider = QgsApplication.instance().processingRegistry().providerById("project")
        self.projectProvider.algorithmsLoaded.connect(self.updateProjectModelMenu)

    def updateProjectModelMenu(self):
        """Add projects models to menu"""

        if self.projectMenuAction is None:
            self.projectModelsMenu = QMenu(self.tr("Models"))
            self.projectMenuAction = self.iface.projectMenu().insertMenu(self.iface.projectMenu().children()[-1], self.projectModelsMenu)
            self.projectMenuAction.setParent(self.projectModelsMenu)
            self.iface.projectMenu().insertSeparator(self.projectMenuAction)

        self.projectModelsMenu.clear()

        for model in self.projectProvider.algorithms():
            modelSubMenu = self.projectModelsMenu.addMenu(model.name())
            modelSubMenu.setParent(self.projectModelsMenu)
            action = QAction(self.tr("Execute…"), modelSubMenu)
            action.triggered.connect(partial(self.executeAlgorithm, model.id(), self.projectModelsMenu, self.toolbox.in_place_mode))
            modelSubMenu.addAction(action)
            if model.flags() & QgsProcessingAlgorithm.FlagSupportsBatch:
                action = QAction(self.tr("Execute as Batch Process…"), modelSubMenu)
                modelSubMenu.addAction(action)
                action.triggered.connect(partial(self.executeAlgorithm, model.id(), self.projectModelsMenu, self.toolbox.in_place_mode, True))

    @pyqtSlot(str, QWidget, bool, bool)
    def executeAlgorithm(self, alg_id, parent, in_place=False, as_batch=False):
        """Executes a project model with GUI interaction if needed.

        :param alg_id: algorithm id
        :type alg_id: string
        :param parent: parent widget
        :type parent: QWidget
        :param in_place: in place flag, defaults to False
        :type in_place: bool, optional
        :param as_batch: execute as batch flag, defaults to False
        :type as_batch: bool, optional
        """

        config = {}
        if in_place:
            config['IN_PLACE'] = True

        alg = QgsApplication.instance().processingRegistry().createAlgorithmById(alg_id, config)

        if alg is not None:

            ok, message = alg.canExecute()
            if not ok:
                dlg = MessageDialog()
                dlg.setTitle(self.tr('Error executing algorithm'))
                dlg.setMessage(
                    self.tr('<h3>This algorithm cannot '
                            'be run :-( </h3>\n{0}').format(message))
                dlg.exec_()
                return

            if as_batch:
                dlg = BatchAlgorithmDialog(alg, iface.mainWindow())
                dlg.show()
                dlg.exec_()
            else:
                in_place_input_parameter_name = 'INPUT'
                if hasattr(alg, 'inputParameterName'):
                    in_place_input_parameter_name = alg.inputParameterName()

                if in_place and not [d for d in alg.parameterDefinitions() if d.name() not in (in_place_input_parameter_name, 'OUTPUT')]:
                    parameters = {}
                    feedback = MessageBarProgress(algname=alg.displayName())
                    ok, results = execute_in_place(alg, parameters, feedback=feedback)
                    if ok:
                        iface.messageBar().pushSuccess('', self.tr('{algname} completed. %n feature(s) processed.', n=results['__count']).format(algname=alg.displayName()))
                    feedback.close()
                    # MessageBarProgress handles errors
                    return

                if alg.countVisibleParameters() > 0:
                    dlg = alg.createCustomParametersWidget(parent)

                    if not dlg:
                        dlg = AlgorithmDialog(alg, in_place, iface.mainWindow())
                    canvas = iface.mapCanvas()
                    prevMapTool = canvas.mapTool()
                    dlg.show()
                    dlg.exec_()
                    if canvas.mapTool() != prevMapTool:
                        try:
                            canvas.mapTool().reset()
                        except Exception:
                            pass
                        canvas.setMapTool(prevMapTool)
                else:
                    feedback = MessageBarProgress(algname=alg.displayName())
                    context = dataobjects.createContext(feedback)
                    parameters = {}
                    ret, results = execute(alg, parameters, context, feedback)
                    handleAlgorithmResults(alg, context, feedback)
                    feedback.close()

    def sync_in_place_button_state(self, layer=None):
        """Synchronise the button state with layer state"""

        if layer is None:
            layer = self.iface.activeLayer()

        old_enabled_state = self.editInPlaceAction.isEnabled()

        new_enabled_state = layer is not None and layer.type() == QgsMapLayerType.VectorLayer
        self.editInPlaceAction.setEnabled(new_enabled_state)

        if new_enabled_state != old_enabled_state:
            self.toolbox.set_in_place_edit_mode(new_enabled_state and self.editInPlaceAction.isChecked())

    def openProcessingOptions(self):
        self.iface.showOptionsDialog(self.iface.mainWindow(), currentPage='processingOptions')

    def unload(self):
        self.toolbox.setVisible(False)
        self.iface.removeDockWidget(self.toolbox)
        self.iface.attributesToolBar().removeAction(self.toolboxAction)

        self.resultsDock.setVisible(False)
        self.iface.removeDockWidget(self.resultsDock)

        self.toolbox.deleteLater()
        self.menu.deleteLater()

        # also delete temporary help files
        folder = tempHelpFolder()
        if QDir(folder).exists():
            shutil.rmtree(folder, True)

        self.iface.unregisterMainWindowAction(self.toolboxAction)
        self.iface.unregisterMainWindowAction(self.modelerAction)
        self.iface.unregisterMainWindowAction(self.historyAction)
        self.iface.unregisterMainWindowAction(self.resultsAction)

        self.iface.unregisterOptionsWidgetFactory(self.options_factory)
        self.iface.deregisterLocatorFilter(self.locator_filter)
        self.iface.deregisterLocatorFilter(self.edit_features_locator_filter)
        self.iface.unregisterCustomDropHandler(self.drop_handler)
        QgsApplication.dataItemProviderRegistry().removeProvider(self.item_provider)

        removeButtons()
        removeMenus()

        if self.projectMenuAction is not None:
            self.iface.projectMenu().removeAction(self.projectMenuAction)
            self.projectMenuAction = None
        if self.projectMenuSeparator is not None:
            self.iface.projectMenu().removeAction(self.projectMenuSeparator)
            self.projectMenuSeparator = None

        Processing.deinitialize()

    def openToolbox(self, show):
        self.toolbox.setUserVisible(show)

    def toolboxVisibilityChanged(self, visible):
        self.toolboxAction.setChecked(visible)

    def openModeler(self):
        dlg = ModelerDialog.create()
        dlg.update_model.connect(self.updateModel)
        dlg.show()

    def updateModel(self):
        model_provider = QgsApplication.processingRegistry().providerById('model')
        model_provider.refreshAlgorithms()

    def openResults(self):
        if self.resultsDock.isVisible():
            self.resultsDock.hide()
        else:
            self.resultsDock.show()

    def openHistory(self):
        dlg = HistoryDialog()
        dlg.exec_()

    def tr(self, message, disambiguation=None, n=-1):
        return QCoreApplication.translate('ProcessingPlugin', message, disambiguation=disambiguation, n=n)

    def editSelected(self, enabled):
        self.toolbox.set_in_place_edit_mode(enabled)
class LockZoomToTiles:
    def __init__(self, iface):
        self.iface = iface
        self.canvas = iface.mapCanvas()
        self.epsg3857 = QgsCoordinateReferenceSystem('EPSG:3857')
        self.epsg4326 = QgsCoordinateReferenceSystem('EPSG:4326')
        self.islocking = False

    def initGui(self):
        '''Initialize Lock Zoom to Tiles GUI.'''

        icon = QIcon()
        icon.addFile(os.path.dirname(__file__) + "/images/zoomUnlocked.svg", state=QIcon.Off)
        icon.addFile(os.path.dirname(__file__) + "/images/zoomLocked.svg", state=QIcon.On)
        self.action = QAction(icon, "Lock zoom scale", self.iface.mainWindow())
        self.action.setObjectName('lockZoom')
        self.action.triggered.connect(self.lockIt)
        self.action.setCheckable(True)
        self.iface.addPluginToMenu("Lock zoom to tile scale", self.action)
        self.iface.addToolBarIcon(self.action)

        icon = QIcon(os.path.dirname(__file__) + '/images/help.svg')
        self.helpAction = QAction(icon, "Help", self.iface.mainWindow())
        self.helpAction.triggered.connect(self.help)
        self.iface.addPluginToMenu('Lock zoom to tile scale', self.helpAction)
        
        self.checkCrs()
        self.canvas.destinationCrsChanged.connect(self.checkCrs)
        self.canvas.layersChanged.connect(self.checkCrs)

    def unload(self):
        '''Unload from the QGIS interface'''
        self.iface.removePluginMenu('Lock zoom to tile scale', self.action)
        self.iface.removeToolBarIcon(self.action)
        self.iface.removePluginMenu("Lock zoom to tile scale", self.helpAction)
        self.canvas.destinationCrsChanged.disconnect(self.checkCrs)
        if self.islocking == True:
            try:
                self.canvas.scaleChanged.disconnect(self.lockIt)
            except Exception:
                pass
        
    def help(self):
        '''Display a help page'''
        url = QUrl.fromLocalFile(os.path.dirname(__file__) + "/index.html").toString()
        webbrowser.open(url, new=2)

    def lockIt(self):
        '''Set the focus of the copy coordinate tool'''
        if self.action.isChecked():
            self.zoomTo()
            if self.islocking == False:
                self.islocking = True
                self.canvas.scaleChanged.connect(self.zoomTo)
                self.action.setText("Unlock zoom scale")
                self.action.setIconText("Unlock zoom scale")
        else:
            if self.islocking == True:
                self.canvas.scaleChanged.disconnect(self.zoomTo)
                self.islocking = False
                self.action.setText("Lock zoom scale")
                self.action.setIconText("Lock zoom scale")

    def zoomTo(self):
        crs = self.canvas.mapSettings().destinationCrs()
        mupp = self.canvas.mapUnitsPerPixel()
        if crs == self.epsg3857:
            r = 0
            for i in range(0, len(r3857)):
                r = i
                if r3857[i] > mupp:
                    if i > 0 and (r3857[i]-mupp > mupp-r3857[i-1]):
                        r = i-1
                    break
            if not math.isclose(r3857[r], mupp, rel_tol=1e-5):
                self.canvas.zoomByFactor(r3857[r] / self.canvas.mapUnitsPerPixel())
        else:
            r = 0
            for i in range(0, len(r4326)):
                r = i
                if r4326[i] > mupp:
                    if i > 0 and (r4326[i]-mupp > mupp-r4326[i-1]):
                        r = i-1
                    break
            if not math.isclose(r4326[r], mupp, rel_tol=1e-5):
                self.canvas.zoomByFactor(r4326[r] / self.canvas.mapUnitsPerPixel())
        
    def checkCrs(self):
        crs = self.canvas.mapSettings().destinationCrs()
        numlayers = self.canvas.layerCount()
        if (crs == self.epsg3857 or crs == self.epsg4326) and numlayers > 0:
            self.action.setEnabled(True)
        else:
            self.action.setEnabled(False)
            self.action.setChecked(False)
        self.lockIt()
Beispiel #27
0
class PhotoViewer(QScrollArea):
    """
    Widget for viewing images by incorporating basic navigation options.
    """
    def __init__(self, parent=None, photo_path=""):
        QScrollArea.__init__(self, parent)
        self.setBackgroundRole(QPalette.Dark)

        self._printer = QPrinter()

        self._lbl_photo = QLabel()
        self._lbl_photo.setBackgroundRole(QPalette.Base)
        self._lbl_photo.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)
        self._lbl_photo.setScaledContents(True)

        self.setWidget(self._lbl_photo)

        self._photo_path = photo_path
        self._ph_image = None
        self._scale_factor = 1.0
        self._aspect_ratio = -1

        self._create_actions()

        if self._photo_path:
            self.load_document(self._photo_path)

    def _create_actions(self):
        """
        Create actions for basic image navigation.
        """
        self._zoom_in_act = QAction(
            QApplication.translate("PhotoViewer", "Zoom &In (25%)"), self)
        self._zoom_in_act.setShortcut(
            QApplication.translate("PhotoViewer", "Ctrl++"))
        self._zoom_in_act.setEnabled(False)
        self._zoom_in_act.triggered.connect(self.zoom_in)

        self._zoom_out_act = QAction(
            QApplication.translate("PhotoViewer", "Zoom &Out (25%)"), self)
        self._zoom_out_act.setShortcut(
            QApplication.translate("PhotoViewer", "Ctrl+-"))
        self._zoom_out_act.setEnabled(False)
        self._zoom_out_act.triggered.connect(self.zoom_out)

        self._normal_size_act = QAction(
            QApplication.translate("PhotoViewer", "&Normal Size"), self)
        self._normal_size_act.setShortcut(
            QApplication.translate("PhotoViewer", "Ctrl+S"))
        self._normal_size_act.setEnabled(False)
        self._normal_size_act.triggered.connect(self.normal_size)

        self._fit_to_window_act = QAction(
            QApplication.translate("PhotoViewer", "&Fit to Window"), self)
        self._fit_to_window_act.setShortcut(
            QApplication.translate("PhotoViewer", "Ctrl+F"))
        self._fit_to_window_act.setEnabled(False)
        self._fit_to_window_act.setCheckable(True)
        self._fit_to_window_act.triggered.connect(self.fit_to_window)

        self._print_act = QAction(
            QApplication.translate("PhotoViewer", "&Print"), self)
        self._print_act.setShortcut(
            QApplication.translate("PhotoViewer", "Ctrl+P"))
        self._print_act.setEnabled(False)
        self._print_act.triggered.connect(self.print_photo)

    def zoom_in(self):
        self.scale_photo(1.25)

    def zoom_out(self):
        self.scale_photo(0.8)

    def normal_size(self):
        self._lbl_photo.adjustSize()
        self._scale_factor = 1.0

    def fit_to_window(self):
        fit_to_win = self._fit_to_window_act.isChecked()
        self.setWidgetResizable(fit_to_win)

        if not fit_to_win:
            self.normal_size()

        self.update_actions()

    def print_photo(self):
        print_dialog = QPrintDialog(self._printer, self)

        if print_dialog.exec_() == QDialog.Accepted:
            painter = QPainter(self._printer)
            rect = painter.viewport()
            size = self._lbl_photo.pixmap().size()
            size.scale(rect.size(), Qt.KeepAspectRatio)
            painter.setViewport(rect.x(), rect.y(), size.width(),
                                size.height())
            painter.setWindow(self._lbl_photo.pixmap().rect())
            painter.drawPixmap(0, 0, self._lbl_photo.pixmap())

    def wheelEvent(self, event):
        """
        Zoom the image based on the mouse wheel rotation action.
        :param event: Event containing the wheel rotation info.
        :type event: QWheelEvent
        """
        degrees = event.delta() / 8
        num_steps = degrees / 15

        if num_steps < 0:
            abs_num_steps = abs(num_steps)
            zoom_factor = 1 + (abs_num_steps * 0.25)

        else:
            zoom_factor = 1 - (num_steps * 0.2)

        self.scale_photo(zoom_factor)

    def heightForWidth(self, width):
        if self._aspect_ratio != -1:
            return width / self._aspect_ratio

        else:
            return -1

    def resizeEvent(self, event):
        """
        Event for resizing the widget based on the pixmap's aspect ratio.
        :param event: Contains event parameters for the resize event.
        :type event: QResizeEvent
        """
        super(PhotoViewer, self).resizeEvent(event)

    def update_actions(self):
        self._zoom_out_act.setEnabled(not self._fit_to_window_act.isChecked())
        self._zoom_in_act.setEnabled(not self._fit_to_window_act.isChecked())
        self._normal_size_act.setEnabled(
            not self._fit_to_window_act.isChecked())

    def scale_photo(self, factor):
        """
        :param factor: Value by which the image will be increased/decreased in the view.
        :type factor: float
        """
        if not self._lbl_photo.pixmap().isNull():
            self._scale_factor *= factor
            self._lbl_photo.resize(self._scale_factor *
                                   self._lbl_photo.pixmap().size())

            self._adjust_scroll_bar(self.horizontalScrollBar(), factor)
            self._adjust_scroll_bar(self.verticalScrollBar(), factor)

            self._zoom_in_act.setEnabled(self._scale_factor < 3.0)
            self._zoom_out_act.setEnabled(self._scale_factor > 0.333)

    def _adjust_scroll_bar(self, scroll_bar, factor):
        scroll_bar.setValue(
            int(factor * scroll_bar.value() +
                ((factor - 1) * scroll_bar.pageStep() / 2)))

    def load_document(self, photo_path):
        if photo_path:
            self._ph_image = QImage(photo_path)

            if self._ph_image.isNull():
                return False

            self._photo_path = photo_path

            ph_pixmap = QPixmap.fromImage(self._ph_image)

            self._lbl_photo.setPixmap(ph_pixmap)
            self._scale_factor = 1.0

            self._aspect_ratio = ph_pixmap.width() / ph_pixmap.height()

            self._fit_to_window_act.setEnabled(True)
            self._print_act.setEnabled(True)
            self._fit_to_window_act.trigger()

            self.update_actions()
            return ph_pixmap

        return True

    def photo_location(self):
        """
        :returns: Absolute path of the photo in the central document repository.
        """
        return self._photo_path

    def set_actions(self, menu):
        """
        Add custom actions to the sub-window menu
        """
        menu.addSeparator()
        menu.addAction(self._zoom_in_act)
        menu.addAction(self._zoom_out_act)
        menu.addAction(self._normal_size_act)
        menu.addAction(self._fit_to_window_act)
        menu.addSeparator()
        menu.addAction(self._print_act)
Beispiel #28
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)
Beispiel #29
0
class ProcessingPlugin:

    def __init__(self, iface):
        self.iface = iface
        self.options_factory = None
        self.drop_handler = None
        self.item_provider = None
        self.locator_filter = None
        self.edit_features_locator_filter = None
        self.initialized = False
        self.initProcessing()

    def initProcessing(self):
        if not self.initialized:
            self.initialized = True
            Processing.initialize()

    def initGui(self):
        self.options_factory = ProcessingOptionsFactory()
        self.options_factory.setTitle(self.tr('Processing'))
        iface.registerOptionsWidgetFactory(self.options_factory)
        self.drop_handler = ProcessingDropHandler()
        iface.registerCustomDropHandler(self.drop_handler)
        self.item_provider = ProcessingDataItemProvider()
        QgsApplication.dataItemProviderRegistry().addProvider(self.item_provider)
        self.locator_filter = AlgorithmLocatorFilter()
        iface.registerLocatorFilter(self.locator_filter)
        # Invalidate the locator filter for in-place when active layer changes
        iface.currentLayerChanged.connect(lambda _: self.iface.invalidateLocatorResults())
        self.edit_features_locator_filter = InPlaceAlgorithmLocatorFilter()
        iface.registerLocatorFilter(self.edit_features_locator_filter)

        self.toolbox = ProcessingToolbox()
        self.iface.addDockWidget(Qt.RightDockWidgetArea, self.toolbox)
        self.toolbox.hide()
        self.toolbox.visibilityChanged.connect(self.toolboxVisibilityChanged)

        self.resultsDock = ResultsDock()
        self.iface.addDockWidget(Qt.RightDockWidgetArea, self.resultsDock)
        self.resultsDock.hide()

        self.menu = QMenu(self.iface.mainWindow().menuBar())
        self.menu.setObjectName('processing')
        self.menu.setTitle(self.tr('Pro&cessing'))

        self.toolboxAction = QAction(self.tr('&Toolbox'), self.iface.mainWindow())
        self.toolboxAction.setCheckable(True)
        self.toolboxAction.setObjectName('toolboxAction')
        self.toolboxAction.setIcon(
            QgsApplication.getThemeIcon("/processingAlgorithm.svg"))
        self.iface.registerMainWindowAction(self.toolboxAction,
                                            QKeySequence('Ctrl+Alt+T').toString(QKeySequence.NativeText))
        self.toolboxAction.toggled.connect(self.openToolbox)
        self.iface.attributesToolBar().insertAction(self.iface.actionOpenStatisticalSummary(), self.toolboxAction)
        self.menu.addAction(self.toolboxAction)

        self.modelerAction = QAction(
            QgsApplication.getThemeIcon("/processingModel.svg"),
            QCoreApplication.translate('ProcessingPlugin', 'Graphical &Modeler…'), self.iface.mainWindow())
        self.modelerAction.setObjectName('modelerAction')
        self.modelerAction.triggered.connect(self.openModeler)
        self.iface.registerMainWindowAction(self.modelerAction,
                                            QKeySequence('Ctrl+Alt+M').toString(QKeySequence.NativeText))
        self.menu.addAction(self.modelerAction)

        self.historyAction = QAction(
            QgsApplication.getThemeIcon("/mIconHistory.svg"),
            QCoreApplication.translate('ProcessingPlugin', '&History…'), self.iface.mainWindow())
        self.historyAction.setObjectName('historyAction')
        self.historyAction.triggered.connect(self.openHistory)
        self.iface.registerMainWindowAction(self.historyAction,
                                            QKeySequence('Ctrl+Alt+H').toString(QKeySequence.NativeText))
        self.menu.addAction(self.historyAction)
        self.toolbox.processingToolbar.addAction(self.historyAction)

        self.resultsAction = QAction(
            QgsApplication.getThemeIcon("/processingResult.svg"),
            self.tr('&Results Viewer'), self.iface.mainWindow())
        self.resultsAction.setCheckable(True)
        self.iface.registerMainWindowAction(self.resultsAction,
                                            QKeySequence('Ctrl+Alt+R').toString(QKeySequence.NativeText))

        self.menu.addAction(self.resultsAction)
        self.toolbox.processingToolbar.addAction(self.resultsAction)
        self.resultsDock.visibilityChanged.connect(self.resultsAction.setChecked)
        self.resultsAction.toggled.connect(self.resultsDock.setUserVisible)

        self.toolbox.processingToolbar.addSeparator()

        self.editInPlaceAction = QAction(
            QgsApplication.getThemeIcon("/mActionProcessSelected.svg"),
            self.tr('Edit Features In-Place'), self.iface.mainWindow())
        self.editInPlaceAction.setObjectName('editInPlaceFeatures')
        self.editInPlaceAction.setCheckable(True)
        self.editInPlaceAction.toggled.connect(self.editSelected)
        self.menu.addAction(self.editInPlaceAction)
        self.toolbox.processingToolbar.addAction(self.editInPlaceAction)

        self.toolbox.processingToolbar.addSeparator()

        self.optionsAction = QAction(
            QgsApplication.getThemeIcon("/mActionOptions.svg"),
            self.tr('Options'), self.iface.mainWindow())
        self.optionsAction.setObjectName('optionsAction')
        self.optionsAction.triggered.connect(self.openProcessingOptions)
        self.toolbox.processingToolbar.addAction(self.optionsAction)

        menuBar = self.iface.mainWindow().menuBar()
        menuBar.insertMenu(
            self.iface.firstRightStandardMenu().menuAction(), self.menu)

        self.menu.addSeparator()

        initializeMenus()
        createMenus()

        # In-place editing button state sync
        self.iface.currentLayerChanged.connect(self.sync_in_place_button_state)
        self.iface.mapCanvas().selectionChanged.connect(self.sync_in_place_button_state)
        self.iface.actionToggleEditing().triggered.connect(partial(self.sync_in_place_button_state, None))
        self.sync_in_place_button_state()

    def sync_in_place_button_state(self, layer=None):
        """Synchronise the button state with layer state"""

        if layer is None:
            layer = self.iface.activeLayer()

        old_enabled_state = self.editInPlaceAction.isEnabled()

        new_enabled_state = layer is not None and layer.type() == QgsMapLayerType.VectorLayer
        self.editInPlaceAction.setEnabled(new_enabled_state)

        if new_enabled_state != old_enabled_state:
            self.toolbox.set_in_place_edit_mode(new_enabled_state and self.editInPlaceAction.isChecked())

    def openProcessingOptions(self):
        self.iface.showOptionsDialog(self.iface.mainWindow(), currentPage='processingOptions')

    def unload(self):
        self.toolbox.setVisible(False)
        self.iface.removeDockWidget(self.toolbox)
        self.iface.attributesToolBar().removeAction(self.toolboxAction)

        self.resultsDock.setVisible(False)
        self.iface.removeDockWidget(self.resultsDock)

        self.toolbox.deleteLater()
        self.menu.deleteLater()

        # delete temporary output files
        folder = QgsProcessingUtils.tempFolder()
        if QDir(folder).exists():
            shutil.rmtree(folder, True)

        # also delete temporary help files
        folder = tempHelpFolder()
        if QDir(folder).exists():
            shutil.rmtree(folder, True)

        self.iface.unregisterMainWindowAction(self.toolboxAction)
        self.iface.unregisterMainWindowAction(self.modelerAction)
        self.iface.unregisterMainWindowAction(self.historyAction)
        self.iface.unregisterMainWindowAction(self.resultsAction)

        self.iface.unregisterOptionsWidgetFactory(self.options_factory)
        self.iface.deregisterLocatorFilter(self.locator_filter)
        self.iface.deregisterLocatorFilter(self.edit_features_locator_filter)
        self.iface.unregisterCustomDropHandler(self.drop_handler)
        QgsApplication.dataItemProviderRegistry().removeProvider(self.item_provider)

        removeMenus()
        Processing.deinitialize()

    def openToolbox(self, show):
        self.toolbox.setUserVisible(show)

    def toolboxVisibilityChanged(self, visible):
        self.toolboxAction.setChecked(visible)

    def openModeler(self):
        dlg = ModelerDialog()
        dlg.update_model.connect(self.updateModel)
        dlg.show()

    def updateModel(self):
        model_provider = QgsApplication.processingRegistry().providerById('model')
        model_provider.refreshAlgorithms()

    def openResults(self):
        if self.resultsDock.isVisible():
            self.resultsDock.hide()
        else:
            self.resultsDock.show()

    def openHistory(self):
        dlg = HistoryDialog()
        dlg.exec_()

    def tr(self, message):
        return QCoreApplication.translate('ProcessingPlugin', message)

    def editSelected(self, enabled):
        self.toolbox.set_in_place_edit_mode(enabled)
Beispiel #30
0
class ScreenShotSample(QgsMapTool):
    def exportMap(self):
        self.canvas.saveAsImage(self.outputdir +
                                '\{}.png'.format(self.layername))
        QgsProject.instance().removeMapLayer(qgis.utils.iface.activeLayer())
        if len(self.filelist) > self.count:
            self.setNextFeatureExtent()
        else:
            self.canvas.mapCanvasRefreshed.disconnect(self.exportMap)

    def setNextFeatureExtent(self):
        self.layername, ext = os.path.splitext(
            os.path.basename(self.filelist[self.count]))
        self.layer = self.iface.addVectorLayer(self.filelist[self.count],
                                               self.layername, "ogr")
        self.iface.zoomToActiveLayer()
        self.count += 1

    def start(self):
        self.ext = '.shp'
        self.inputdir = 'shpが格納されているフォルダパス'
        self.outputdir = '画像の保存先のファイルパス'

        self.filelist = glob.glob(self.inputdir + "\*" + self.ext)
        if len(self.filelist) == 0: return
        self.count = 0
        self.canvas.mapCanvasRefreshed.connect(self.exportMap)
        self.setNextFeatureExtent()

    def finish(self):
        self.canvas.mapToolSet.disconnect(self.unsetTool)

    def __init__(self, iface):
        self.plugin_name = 'ファイル毎にスクリーンショット'  # プラグイン名
        self.menu_pos = 'サンプル'  # プラグインの登録場所
        self.toolbar = True  # Trueならツールバーにアイコンを表示する
        self.checkable = False  # Trueならプラグイン実行中はアイコンが凹んだままになる

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

        QgsMapTool.__init__(self, self.canvas)

    # このプラグイン実行中に他のアイコンが押された場合、アイコンを元の状態に戻す
    def unsetTool(self, tool):
        if not isinstance(tool, ScreenShotSample):
            self.finish()
            self.action.setChecked(False)

    def initGui(self):
        icon = QIcon(os.path.dirname(__file__) + '/icon.png')
        self.action = QAction(icon, self.plugin_name, self.iface.mainWindow())
        self.action.triggered.connect(
            self.execSample)  # アイコンを押下した時に実行されるメソッドを登録
        self.action.setCheckable(
            self.checkable)  # Trueだとアイコンを押下したら次に押下するまで凹んだままになる
        if self.toolbar:
            self.iface.addToolBarIcon(self.action)  # ツールバーにこのツールのアイコンを表示する
        self.iface.addPluginToMenu(self.menu_pos, self.action)

    # このプラグインを無効にしたときに呼ばれる
    def unload(self):
        self.iface.removePluginMenu(self.menu_pos, self.action)
        self.iface.removeToolBarIcon(self.action)

    # このツールのアイコンを押下したときに呼ばれる
    def execSample(self):
        if self.checkable:
            if self.action.isChecked():  # 凹状態になった
                self.previousMapTool = self.canvas.mapTool()  # 現在のマップツールを退避
                self.start()
            else:  # 凸状態になった
                self.finish()
                self.canvas.setMapTool(self.previousMapTool)  # このツール実行前に戻す
        else:
            self.start()