diff --git a/QgisModelBaker/gui/dataset_manager.py b/QgisModelBaker/gui/dataset_manager.py index 31c5cc4d5..74c9ee7bb 100644 --- a/QgisModelBaker/gui/dataset_manager.py +++ b/QgisModelBaker/gui/dataset_manager.py @@ -105,6 +105,7 @@ def _close_editing(self): if layer.isEditable(): editable_layers.append(layer) if editable_layers: + # in case it could not close it automatically warning_box = QMessageBox(self) warning_box.setIcon(QMessageBox.Warning) warning_title = self.tr("Layers still editable") diff --git a/QgisModelBaker/gui/panel/layer_tids_panel.py b/QgisModelBaker/gui/panel/layer_tids_panel.py new file mode 100644 index 000000000..cd21e026c --- /dev/null +++ b/QgisModelBaker/gui/panel/layer_tids_panel.py @@ -0,0 +1,263 @@ +""" +/*************************************************************************** + ------------------- + begin : 17.11.2023 + git sha : :%H$ + copyright : (C) 2023 by Dave Signer + email : david at opengis ch + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +""" + + +from enum import Enum, IntEnum + +from qgis.core import QgsProject +from qgis.gui import QgsFieldExpressionWidget +from qgis.PyQt.QtCore import QAbstractTableModel, QModelIndex, Qt +from qgis.PyQt.QtGui import QPixmap +from qgis.PyQt.QtWidgets import ( + QAbstractItemView, + QHeaderView, + QStyledItemDelegate, + QWidget, +) + +import QgisModelBaker.utils.gui_utils as gui_utils +from QgisModelBaker.libs.modelbaker.utils.qgis_utils import QgisProjectUtils +from QgisModelBaker.utils.gui_utils import CheckDelegate + +WIDGET_UI = gui_utils.get_ui_class("layer_tids_panel.ui") + + +class TIDModel(QAbstractTableModel): + """ + ItemModel providing all TIDs and default values of the passed project + + oid_settings is a dictionary like: + { + "Strasse": + { + "oid_domain": "STANDARDOID", + "interlis_topic" : "OIDMadness_V1", + "default_value_expression": "uuid()", + "in_form": True + } + [...] + } + """ + + class Roles(Enum): + LAYER = Qt.UserRole + 1 + + def __int__(self): + return self.value + + class Columns(IntEnum): + NAME = 0 + OID_DOMAIN = 1 + DEFAULT_VALUE = 2 + IN_FORM = 3 + + def __init__(self): + super().__init__() + self.oid_settings = {} + + def columnCount(self, parent): + return len(TIDModel.Columns) + + def rowCount(self, parent): + return len(self.oid_settings.keys()) + + def flags(self, index): + if index.column() == TIDModel.Columns.IN_FORM: + return Qt.ItemIsEnabled + if index.column() == TIDModel.Columns.DEFAULT_VALUE: + return Qt.ItemIsEditable | Qt.ItemIsEnabled + return Qt.ItemIsSelectable | Qt.ItemIsEnabled + + def index(self, row: int, column: int, parent: QModelIndex = ...) -> QModelIndex: + """ + default override + """ + return super().createIndex(row, column, parent) + + def parent(self, index): + """ + default override + """ + return index + + def headerData(self, section, orientation, role): + if orientation == Qt.Horizontal and role == Qt.DisplayRole: + if section == TIDModel.Columns.NAME: + return self.tr("Layer") + if section == TIDModel.Columns.OID_DOMAIN: + return self.tr("TID (OID Type)") + if section == TIDModel.Columns.DEFAULT_VALUE: + return self.tr("Default Value Expression") + if section == TIDModel.Columns.IN_FORM: + return self.tr("Show") + + def data(self, index, role): + if role == int(Qt.DisplayRole) or role == int(Qt.EditRole): + key = list(self.oid_settings.keys())[index.row()] + if index.column() == TIDModel.Columns.NAME: + return f"{key} ({self.oid_settings[key]['interlis_topic']})" + if index.column() == TIDModel.Columns.OID_DOMAIN: + return self.oid_settings[key]["oid_domain"] + if index.column() == TIDModel.Columns.DEFAULT_VALUE: + return self.oid_settings[key]["default_value_expression"] + if index.column() == TIDModel.Columns.IN_FORM: + return self.oid_settings[key]["in_form"] + elif role == int(Qt.ToolTipRole): + key = list(self.oid_settings.keys())[index.row()] + if index.column() == TIDModel.Columns.NAME: + return f"{key} ({self.oid_settings[key]['interlis_topic']})" + if index.column() == TIDModel.Columns.OID_DOMAIN: + message = self.tr( + "
The OID format is not defined, you can use whatever you want, but it should always start with an underscore _
or an alphanumeric value.
The OID should be an Universally Unique Identifier (OID TEXT*36).
" + ) + elif oid_domain[-11:] == "STANDARDOID": + message = self.tr( + """ + ++ The OID format requireds an 8 char prefix and 8 char postfix. +
+Prefix (2 + 6 chars): Country identifier + a 'global' identification part assigned once by the official authority.
+Postfix (8 chars): Sequence (numeric or alphanumeric) of your system as 'local' identification part.
+ + + """ + ) + elif oid_domain[-6:] == "I32OID": + message = self.tr( + "The OID must be an integer value (OID 0 .. 2147483647).
" + ) + elif oid_domain[-6:] == "ANYOID": + message = self.tr( + "The OID format could vary depending in what basket the object (entry) is located.
These objects could be in the following topics: {topics}".format(
+ topics=self.oid_settings[key]["interlis_topic"]
+ )
+ )
+ return message
+ if index.column() == TIDModel.Columns.DEFAULT_VALUE:
+ return self.oid_settings[key]["default_value_expression"]
+ if index.column() == TIDModel.Columns.IN_FORM:
+ return self.tr("Show t_ili_tid field (OID) in attribute form.")
+ elif role == int(TIDModel.Roles.LAYER):
+ key = list(self.oid_settings.keys())[index.row()]
+ return self.oid_settings[key]["layer"]
+ return None
+
+ def setData(self, index, data, role):
+ if role == int(Qt.EditRole):
+ if index.column() == TIDModel.Columns.DEFAULT_VALUE:
+ key = list(self.oid_settings.keys())[index.row()]
+ self.oid_settings[key]["default_value_expression"] = data
+ self.dataChanged.emit(index, index)
+ if index.column() == TIDModel.Columns.IN_FORM:
+ key = list(self.oid_settings.keys())[index.row()]
+ self.oid_settings[key]["in_form"] = data
+ self.dataChanged.emit(index, index)
+ return True
+
+ def load_tid_config(self, qgis_project=None):
+ self.beginResetModel()
+ self.oid_settings = QgisProjectUtils(qgis_project).get_oid_settings()
+ self.endResetModel()
+
+ def save_tid_config(self, qgis_project=None):
+ if qgis_project:
+ QgisProjectUtils(qgis_project).set_oid_settings(self.oid_settings)
+
+
+class FieldExpressionDelegate(QStyledItemDelegate):
+ def __init__(self, parent):
+ super().__init__(parent)
+ self.parent = parent
+ self.editor = None
+
+ def createEditor(self, parent, option, index):
+ self.editor = QgsFieldExpressionWidget(parent)
+ layer = index.data(int(TIDModel.Roles.LAYER))
+ self.editor.setLayer(layer)
+ return self.editor
+
+ def setEditorData(self, editor, index):
+ value = index.data(int(Qt.DisplayRole))
+ self.editor.setExpression(value)
+
+ def setModelData(self, editor, model, index):
+ value = editor.expression()
+ print(f"new exp{value}")
+ model.setData(index, value, int(Qt.EditRole))
+
+ def updateEditorGeometry(self, editor, option, index):
+ self.editor.setGeometry(option.rect)
+
+ def paint(self, painter, option, index):
+ opt = self.createEditor(self.parent, option, index)
+ opt.editable = False
+ value = index.data(int(Qt.DisplayRole))
+ opt.setExpression(value)
+ opt.resize(option.rect.width(), option.rect.height())
+ pixmap = QPixmap(opt.width(), opt.height())
+ opt.render(pixmap)
+ painter.drawPixmap(option.rect, pixmap)
+ painter.restore()
+
+
+class LayerTIDsPanel(QWidget, WIDGET_UI):
+ def __init__(self, parent=None):
+ QWidget.__init__(self, parent)
+ self.setupUi(self)
+ self.parent = parent
+ self.tid_model = TIDModel()
+ self.layer_tids_view.setModel(self.tid_model)
+
+ self.layer_tids_view.horizontalHeader().setSectionResizeMode(
+ TIDModel.Columns.NAME, QHeaderView.Stretch
+ )
+ self.layer_tids_view.horizontalHeader().setSectionResizeMode(
+ TIDModel.Columns.OID_DOMAIN, QHeaderView.ResizeToContents
+ )
+ self.layer_tids_view.horizontalHeader().setSectionResizeMode(
+ TIDModel.Columns.DEFAULT_VALUE, QHeaderView.ResizeToContents
+ )
+ self.layer_tids_view.horizontalHeader().setSectionResizeMode(
+ TIDModel.Columns.IN_FORM, QHeaderView.ResizeToContents
+ )
+
+ self.layer_tids_view.setItemDelegateForColumn(
+ TIDModel.Columns.IN_FORM,
+ CheckDelegate(self, Qt.EditRole),
+ )
+ self.layer_tids_view.setItemDelegateForColumn(
+ TIDModel.Columns.DEFAULT_VALUE,
+ FieldExpressionDelegate(self),
+ )
+ self.layer_tids_view.setEditTriggers(QAbstractItemView.AllEditTriggers)
+
+ def load_tid_config(self, qgis_project=QgsProject.instance()):
+ self.tid_model.load_tid_config(qgis_project)
+
+ def save_tid_config(self, qgis_project=QgsProject.instance()):
+ # if a cell is still edited, we need to store it in model by force
+ index = self.layer_tids_view.currentIndex()
+ self.layer_tids_view.currentChanged(index, index)
+ self.tid_model.save_tid_config(qgis_project)
diff --git a/QgisModelBaker/gui/panel/set_sequence_panel.py b/QgisModelBaker/gui/panel/set_sequence_panel.py
new file mode 100644
index 000000000..344891822
--- /dev/null
+++ b/QgisModelBaker/gui/panel/set_sequence_panel.py
@@ -0,0 +1,46 @@
+"""
+/***************************************************************************
+ -------------------
+ begin : 17.11.2023
+ git sha : :%H$
+ copyright : (C) 2023 by Dave Signer
+ email : david at opengis ch
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+"""
+
+
+from qgis.PyQt.QtWidgets import QWidget
+
+import QgisModelBaker.utils.gui_utils as gui_utils
+
+WIDGET_UI = gui_utils.get_ui_class("set_sequence_panel.ui")
+
+
+class SetSequencePanel(QWidget, WIDGET_UI):
+ def __init__(self, parent=None):
+ QWidget.__init__(self, parent)
+ self.setupUi(self)
+
+ def load_sequence(self, db_connector=None):
+ if db_connector:
+ sequence_value = db_connector.get_ili2db_sequence_value()
+ self.sequence_value_edit.setValue(sequence_value)
+
+ def save_sequence(self, db_connector=None):
+ if self.sequence_group.isChecked():
+ if db_connector:
+ return db_connector.set_ili2db_sequence_value(
+ self.sequence_value_edit.value()
+ )
+ return False, self.tr("Could not reset T_Id - no db_connector...")
+ else:
+ return True, self.tr("T_Id not set.")
diff --git a/QgisModelBaker/gui/panel/tid_configurator_panel.py b/QgisModelBaker/gui/panel/tid_configurator_panel.py
new file mode 100644
index 000000000..9ea585b3d
--- /dev/null
+++ b/QgisModelBaker/gui/panel/tid_configurator_panel.py
@@ -0,0 +1,83 @@
+"""
+/***************************************************************************
+ -------------------
+ begin : 17.11.2023
+ git sha : :%H$
+ copyright : (C) 2023 by Dave Signer
+ email : david at opengis ch
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+"""
+
+
+from qgis.PyQt.QtWidgets import QWidget
+
+import QgisModelBaker.libs.modelbaker.utils.db_utils as db_utils
+from QgisModelBaker.gui.panel.layer_tids_panel import LayerTIDsPanel
+from QgisModelBaker.gui.panel.set_sequence_panel import SetSequencePanel
+from QgisModelBaker.libs.modelbaker.iliwrapper.ili2dbconfig import (
+ Ili2DbCommandConfiguration,
+)
+from QgisModelBaker.utils import gui_utils
+
+WIDGET_UI = gui_utils.get_ui_class("tid_configurator_panel.ui")
+
+
+class TIDConfiguratorPanel(QWidget, WIDGET_UI):
+ def __init__(self, parent=None):
+ QWidget.__init__(self, parent)
+ self.setupUi(self)
+ self.parent = parent
+
+ self.layer_tids_panel = LayerTIDsPanel(self.parent)
+ self.layer_tids_layout.addWidget(self.layer_tids_panel)
+
+ self.set_sequence_panel = SetSequencePanel(self.parent)
+ self.set_sequence_layout.addWidget(self.set_sequence_panel)
+
+ self.reset_layer_tids_button.clicked.connect(self._reset_tid_configuration)
+
+ self.qgis_project = None
+ self.db_connector = None
+
+ def setup_dialog(self, qgis_project, db_connector=None):
+ self.qgis_project = qgis_project
+
+ if self.qgis_project:
+ if db_connector:
+ self.db_connector = db_connector
+ else:
+ # getting the data source of the first layer in the layer tree
+ layers = qgis_project.layerTreeRoot().findLayers()
+ if layers:
+ first_tree_layer = layers[0]
+ configuration = Ili2DbCommandConfiguration()
+ source_provider = first_tree_layer.layer().dataProvider()
+ valid, mode = db_utils.get_configuration_from_sourceprovider(
+ source_provider, configuration
+ )
+ if valid:
+ configuration.tool = mode
+ self.db_connector = db_utils.get_db_connector(configuration)
+
+ self._reset_tid_configuration()
+
+ def _reset_tid_configuration(self):
+ self.layer_tids_panel.load_tid_config(self.qgis_project)
+ self.set_sequence_panel.load_sequence(self.db_connector)
+
+ def set_tid_configuration(self):
+ result, message = self.set_sequence_panel.save_sequence(self.db_connector)
+ # only set the project settings when the sequence part succeeds (or is not performed)
+ if result:
+ self.layer_tids_panel.save_tid_config(self.qgis_project)
+ return True, message
+ return False, message
diff --git a/QgisModelBaker/gui/tid_manager.py b/QgisModelBaker/gui/tid_manager.py
new file mode 100644
index 000000000..5987c5f84
--- /dev/null
+++ b/QgisModelBaker/gui/tid_manager.py
@@ -0,0 +1,81 @@
+"""
+/***************************************************************************
+ begin : 10.08.2021
+ git sha : :%H$
+ copyright : (C) 2021 by Dave Signer
+ email : david at opengis ch
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+"""
+
+from qgis.core import QgsMapLayer, QgsProject
+from qgis.PyQt.QtWidgets import QDialog, QMessageBox
+
+from QgisModelBaker.gui.panel.tid_configurator_panel import TIDConfiguratorPanel
+from QgisModelBaker.utils import gui_utils
+
+DIALOG_UI = gui_utils.get_ui_class("tid_manager.ui")
+
+
+class TIDManagerDialog(QDialog, DIALOG_UI):
+ def __init__(self, iface, parent=None):
+
+ QDialog.__init__(self, parent)
+ self.iface = iface
+ self._close_editing()
+ self.parent = parent
+
+ self.setupUi(self)
+
+ self.tid_configurator_panel = TIDConfiguratorPanel(self.parent)
+ self.tid_configurator_layout.addWidget(self.tid_configurator_panel)
+
+ self.buttonBox.accepted.connect(self._accepted)
+ self.buttonBox.rejected.connect(self._rejected)
+
+ self.setStyleSheet(gui_utils.DEFAULT_STYLE)
+
+ self.tid_configurator_panel.setup_dialog(QgsProject.instance())
+
+ def _close_editing(self):
+ editable_layers = []
+ for layer in QgsProject.instance().mapLayers().values():
+ if layer.type() == QgsMapLayer.VectorLayer:
+ self.iface.vectorLayerTools().stopEditing(layer)
+ if layer.isEditable():
+ editable_layers.append(layer)
+ if editable_layers:
+ # in case it could not close it automatically
+ warning_box = QMessageBox(self)
+ warning_box.setIcon(QMessageBox.Warning)
+ warning_title = self.tr("Layers still editable")
+ warning_box.setWindowTitle(warning_title)
+ warning_box.setText(
+ self.tr(
+ "You still have layers in edit mode.\nIn case you modify the sequence in the database of those layers, it could lead to database locks.\nEditable layers are:\n - {}"
+ ).format("\n - ".join([layer.name() for layer in editable_layers]))
+ )
+ warning_box.exec_()
+
+ def _accepted(self):
+ result, message = self.tid_configurator_panel.set_tid_configuration()
+ if not result:
+ error_box = QMessageBox(self)
+ error_box.setIcon(QMessageBox.Error)
+ warning_title = self.tr("Problems on setting T_Id sequence.")
+ error_box.setWindowTitle(warning_title)
+ error_box.setText(message)
+ error_box.exec_()
+ else:
+ self.close()
+
+ def _rejected(self):
+ self.close()
diff --git a/QgisModelBaker/gui/topping_wizard/ili2dbsettings_page.py b/QgisModelBaker/gui/topping_wizard/ili2dbsettings_page.py
index 2e2656e82..b4c485aa5 100644
--- a/QgisModelBaker/gui/topping_wizard/ili2dbsettings_page.py
+++ b/QgisModelBaker/gui/topping_wizard/ili2dbsettings_page.py
@@ -86,6 +86,7 @@ def data(self, index, role):
return self.parameters.get(key, "")
return None
+ # this is unusual that it's not first data and then role (could be changed)
def setData(self, index, role, data):
if role == int(Qt.EditRole):
if index.column() == ParametersModel.Columns.NAME:
diff --git a/QgisModelBaker/gui/topping_wizard/layers_page.py b/QgisModelBaker/gui/topping_wizard/layers_page.py
index ee075182a..4b57f51a5 100644
--- a/QgisModelBaker/gui/topping_wizard/layers_page.py
+++ b/QgisModelBaker/gui/topping_wizard/layers_page.py
@@ -207,6 +207,7 @@ def data(self, index, role):
return QgsLayerTreeModel.data(self, index, role)
+ # this is unusual that it's not first data and then role (could be changed)
def setData(self, index, role, data):
if role == Qt.CheckStateRole:
node = self.index2node(index)
diff --git a/QgisModelBaker/gui/workflow_wizard/import_data_configuration_page.py b/QgisModelBaker/gui/workflow_wizard/import_data_configuration_page.py
index 9a4b2f7a1..79876c277 100644
--- a/QgisModelBaker/gui/workflow_wizard/import_data_configuration_page.py
+++ b/QgisModelBaker/gui/workflow_wizard/import_data_configuration_page.py
@@ -19,18 +19,15 @@
import os
-from PyQt5.QtWidgets import QApplication
from qgis.core import QgsApplication
-from qgis.PyQt.QtCore import QEvent, Qt
-from qgis.PyQt.QtGui import QIcon
+from qgis.PyQt.QtCore import Qt
+from qgis.PyQt.QtGui import QIcon, QPixmap
from qgis.PyQt.QtWidgets import (
+ QAbstractItemView,
QComboBox,
QCompleter,
QHeaderView,
- QStyle,
QStyledItemDelegate,
- QStyleOptionButton,
- QStyleOptionComboBox,
QWizardPage,
)
@@ -42,7 +39,7 @@
MetaConfigCompleterDelegate,
)
from QgisModelBaker.utils.globals import CATALOGUE_DATASETNAME, DEFAULT_DATASETNAME
-from QgisModelBaker.utils.gui_utils import LogColor
+from QgisModelBaker.utils.gui_utils import CheckDelegate, LogColor
PAGE_UI = gui_utils.get_ui_class("workflow_wizard/import_data_configuration.ui")
@@ -50,6 +47,7 @@
class DatasetComboDelegate(QStyledItemDelegate):
def __init__(self, parent, db_connector):
super().__init__(parent)
+ self.parent = parent
self.refresh_datasets(db_connector)
def refresh_datasets(self, db_connector):
@@ -79,36 +77,16 @@ def updateEditorGeometry(self, editor, option, index):
editor.setGeometry(option.rect)
def paint(self, painter, option, index):
- """
- Here it paints only the lable without a StyleItem for the ComboBox, because to edit it needs multiple clicks and the behavior gets confusing.
- """
- opt = QStyleOptionComboBox()
+ opt = self.createEditor(self.parent, option, index)
opt.editable = False
- opt.rect = option.rect
- value = index.data(int(Qt.DisplayRole))
- opt.currentText = value
- QApplication.style().drawControl(QStyle.CE_ComboBoxLabel, opt, painter)
-
-
-class CatalogueCheckDelegate(QStyledItemDelegate):
- def __init__(self, parent):
- super().__init__(parent)
-
- def editorEvent(self, event, model, option, index):
- if event.type() == QEvent.MouseButtonRelease:
- value = index.data(int(gui_utils.SourceModel.Roles.IS_CATALOGUE)) or False
- model.setData(
- index, not value, int(gui_utils.SourceModel.Roles.IS_CATALOGUE)
- )
- return True
- return super().editorEvent(event, model, option, index)
-
- def paint(self, painter, option, index):
- opt = QStyleOptionButton()
- opt.rect = option.rect
- value = index.data(int(gui_utils.SourceModel.Roles.IS_CATALOGUE)) or False
- opt.state |= QStyle.State_On if value else QStyle.State_Off
- QApplication.style().drawControl(QStyle.CE_CheckBox, opt, painter)
+ value = index.data(int(gui_utils.SourceModel.Roles.DATASET_NAME))
+ num = self.items.index(value) if value in self.items else 0
+ opt.setCurrentIndex(num)
+ opt.resize(option.rect.width(), option.rect.height())
+ pixmap = QPixmap(opt.width(), opt.height())
+ opt.render(pixmap)
+ painter.drawPixmap(option.rect, pixmap)
+ painter.restore()
class ImportDataConfigurationPage(QWizardPage, PAGE_UI):
@@ -173,6 +151,7 @@ def __init__(self, parent, title):
gui_utils.SourceModel.Columns.DATASET, QHeaderView.ResizeToContents
)
+ self.file_table_view.setEditTriggers(QAbstractItemView.AllEditTriggers)
self.file_table_view.verticalHeader().setSectionsMovable(True)
self.file_table_view.verticalHeader().setDragEnabled(True)
self.file_table_view.verticalHeader().setDragDropMode(QHeaderView.InternalMove)
@@ -269,7 +248,7 @@ def _set_basket_defaults(self):
self.file_table_view.setItemDelegateForColumn(
gui_utils.SourceModel.Columns.IS_CATALOGUE,
- CatalogueCheckDelegate(self),
+ CheckDelegate(self, gui_utils.SourceModel.Roles.IS_CATALOGUE),
)
self.file_table_view.setItemDelegateForColumn(
gui_utils.SourceModel.Columns.DATASET,
diff --git a/QgisModelBaker/gui/workflow_wizard/project_creation_page.py b/QgisModelBaker/gui/workflow_wizard/project_creation_page.py
index 2e94ae094..abd006991 100644
--- a/QgisModelBaker/gui/workflow_wizard/project_creation_page.py
+++ b/QgisModelBaker/gui/workflow_wizard/project_creation_page.py
@@ -45,7 +45,6 @@ def __init__(self, parent, title):
self.workflow_wizard = parent
self.setupUi(self)
- self.setFinalPage(True)
self.setTitle(title)
self.setStyleSheet(gui_utils.DEFAULT_STYLE)
@@ -63,6 +62,16 @@ def __init__(self, parent, title):
self.create_project_button.clicked.connect(self._create_project)
+ self.is_complete = False
+
+ def isComplete(self):
+ return self.is_complete
+
+ def setComplete(self, complete):
+ self.is_complete = complete
+ self.create_project_button.setDisabled(complete)
+ self.completeChanged.emit()
+
def set_configuration(self, configuration):
self.configuration = configuration
@@ -349,6 +358,7 @@ def _create_project(self):
self.progress_bar.setValue(100)
self.setStyleSheet(gui_utils.SUCCESS_STYLE)
self.workflow_wizard.log_panel.print_info(self.tr("It's served!"))
+ self.setComplete(True)
def ilidata_path_resolver(self, base_path, path):
if "ilidata:" in path or "file:" in path:
diff --git a/QgisModelBaker/gui/workflow_wizard/tid_configuration_page.py b/QgisModelBaker/gui/workflow_wizard/tid_configuration_page.py
new file mode 100644
index 000000000..c1635addc
--- /dev/null
+++ b/QgisModelBaker/gui/workflow_wizard/tid_configuration_page.py
@@ -0,0 +1,72 @@
+"""
+/***************************************************************************
+ -------------------
+ begin : 17.11.2023
+ git sha : :%H$
+ copyright : (C) 2023 by Dave Signer
+ email : david at opengis ch
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+"""
+
+
+from qgis.core import QgsProject
+from qgis.PyQt.QtWidgets import QWizardPage
+
+import QgisModelBaker.libs.modelbaker.utils.db_utils as db_utils
+from QgisModelBaker.gui.panel.tid_configurator_panel import TIDConfiguratorPanel
+from QgisModelBaker.utils import gui_utils
+
+PAGE_UI = gui_utils.get_ui_class("workflow_wizard/tid_configuration.ui")
+
+
+class TIDConfigurationPage(QWizardPage, PAGE_UI):
+ def __init__(self, parent, title):
+ QWizardPage.__init__(self, parent)
+
+ self.workflow_wizard = parent
+
+ self.setupUi(self)
+ self.setFinalPage(True)
+ self.setTitle(title)
+ self.setStyleSheet(gui_utils.DEFAULT_STYLE)
+
+ self.tid_configurator_panel = TIDConfiguratorPanel(self.workflow_wizard)
+ self.tid_configurator_layout.addWidget(self.tid_configurator_panel)
+
+ self.set_layer_tids_and_sequence_button.clicked.connect(
+ self._set_tid_configuration
+ )
+
+ self.configuration = None
+
+ def set_configuration(self, configuration):
+ self.configuration = configuration
+ db_connector = db_utils.get_db_connector(self.configuration)
+ self.tid_configurator_panel.setup_dialog(QgsProject.instance(), db_connector)
+
+ def _set_tid_configuration(self):
+ self.progress_bar.setValue(0)
+ # we store the settings to project and db
+ result, message = self.tid_configurator_panel.set_tid_configuration()
+ if result:
+ self.workflow_wizard.log_panel.print_info(
+ self.tr("Stored TID configurations to current project")
+ )
+ self.workflow_wizard.log_panel.print_info(
+ self.tr("Stored the sequence value to current database")
+ )
+ self.progress_bar.setValue(100)
+ self.setStyleSheet(gui_utils.SUCCESS_STYLE)
+ else:
+ self.workflow_wizard.log_panel.print_info(message)
+ self.progress_bar.setValue(0)
+ self.setStyleSheet(gui_utils.ERROR_STYLE)
diff --git a/QgisModelBaker/gui/workflow_wizard/workflow_wizard.py b/QgisModelBaker/gui/workflow_wizard/workflow_wizard.py
index 3db32c7d8..b90da69ed 100644
--- a/QgisModelBaker/gui/workflow_wizard/workflow_wizard.py
+++ b/QgisModelBaker/gui/workflow_wizard/workflow_wizard.py
@@ -44,6 +44,9 @@
)
from QgisModelBaker.gui.workflow_wizard.intro_page import IntroPage
from QgisModelBaker.gui.workflow_wizard.project_creation_page import ProjectCreationPage
+from QgisModelBaker.gui.workflow_wizard.tid_configuration_page import (
+ TIDConfigurationPage,
+)
from QgisModelBaker.libs.modelbaker.iliwrapper.ili2dbconfig import (
ExportConfiguration,
ImportDataConfiguration,
@@ -161,6 +164,9 @@ def __init__(self, iface, base_config, parent):
self.project_creation_page = ProjectCreationPage(
self, self._current_page_title(PageIds.ProjectCreation)
)
+ self.tid_configuration_page = TIDConfigurationPage(
+ self, self._current_page_title(PageIds.TIDConfiguration)
+ )
self.generate_database_selection_page = DatabaseSelectionPage(
self,
self._current_page_title(PageIds.GenerateDatabaseSelection),
@@ -189,6 +195,7 @@ def __init__(self, iface, base_config, parent):
self.setPage(PageIds.ImportDataConfiguration, self.data_configuration_page)
self.setPage(PageIds.ImportDataExecution, self.import_data_execution_page)
self.setPage(PageIds.ProjectCreation, self.project_creation_page)
+ self.setPage(PageIds.TIDConfiguration, self.tid_configuration_page)
self.setPage(
PageIds.GenerateDatabaseSelection, self.generate_database_selection_page
)
@@ -316,6 +323,9 @@ def next_id(self):
if self.current_id == PageIds.ExportDataConfiguration:
return PageIds.ExportDataExecution
+ if self.current_id == PageIds.ProjectCreation:
+ return PageIds.TIDConfiguration
+
return self.current_id
def id_changed(self, new_id):
@@ -369,6 +379,11 @@ def id_changed(self, new_id):
self.import_schema_configuration
)
+ if self.current_id == PageIds.TIDConfiguration:
+ self.tid_configuration_page.set_configuration(
+ self.import_schema_configuration
+ )
+
if self.current_id == PageIds.ImportDataConfiguration:
self.data_configuration_page.setup_dialog(
self._basket_handling(self.import_data_configuration)
@@ -453,6 +468,8 @@ def _current_page_title(self, id):
return self.tr("Data Export Sessions")
elif id == PageIds.ProjectCreation:
return self.tr("Generate a QGIS Project")
+ elif id == PageIds.TIDConfiguration:
+ return self.tr("Configure OID Generation")
else:
return self.tr("Model Baker - Workflow Wizard")
diff --git a/QgisModelBaker/images/QgisModelBaker-tidmanager-icon.svg b/QgisModelBaker/images/QgisModelBaker-tidmanager-icon.svg
new file mode 100644
index 000000000..f98a61e85
--- /dev/null
+++ b/QgisModelBaker/images/QgisModelBaker-tidmanager-icon.svg
@@ -0,0 +1,2 @@
+
+
diff --git a/QgisModelBaker/qgismodelbaker.py b/QgisModelBaker/qgismodelbaker.py
index cd74c2c06..976b74d7b 100644
--- a/QgisModelBaker/qgismodelbaker.py
+++ b/QgisModelBaker/qgismodelbaker.py
@@ -48,6 +48,7 @@
from QgisModelBaker.gui.drop_message import DropMessageDialog
from QgisModelBaker.gui.options import OptionsDialog
from QgisModelBaker.gui.panel.dataset_selector import DatasetSelector
+from QgisModelBaker.gui.tid_manager import TIDManagerDialog
from QgisModelBaker.gui.topping_wizard.topping_wizard import ToppingWizardDialog
from QgisModelBaker.gui.validate import ValidateDock
from QgisModelBaker.gui.workflow_wizard.workflow_wizard import WorkflowWizardDialog
@@ -65,10 +66,12 @@ def __init__(self, iface):
self.workflow_wizard_dlg = None
self.datasetmanager_dlg = None
+ self.tidmanager_dlg = None
self.topping_wizard_dlg = None
self.__workflow_wizard_action = None
self.__datasetmanager_action = None
+ self.__tidmanager_action = None
self.__validate_action = None
self.__topping_wizard_action = None
self.__configure_action = None
@@ -131,6 +134,16 @@ def initGui(self):
self.tr("Dataset Manager"),
None,
)
+ self.__tidmanager_action = QAction(
+ QIcon(
+ os.path.join(
+ os.path.dirname(__file__),
+ "images/QgisModelBaker-tidmanager-icon.svg",
+ )
+ ),
+ self.tr("TID (OID) Manager"),
+ None,
+ )
self.__validate_action = QAction(
QIcon(
os.path.join(
@@ -172,11 +185,13 @@ def initGui(self):
# set these actions checkable to visualize that the dialog is open
self.__workflow_wizard_action.setCheckable(True)
self.__datasetmanager_action.setCheckable(True)
+ self.__tidmanager_action.setCheckable(True)
self.__validate_action.setCheckable(True)
self.__topping_wizard_action.setCheckable(True)
self.__configure_action.triggered.connect(self.show_options_dialog)
self.__datasetmanager_action.triggered.connect(self.show_datasetmanager_dialog)
+ self.__tidmanager_action.triggered.connect(self.show_tidmanager_dialog)
self.__validate_action.triggered.connect(self.show_validate_dock)
self.__workflow_wizard_action.triggered.connect(
self.show_workflow_wizard_dialog
@@ -198,6 +213,9 @@ def initGui(self):
self.iface.addPluginToDatabaseMenu(
self.tr("Model Baker"), self.__datasetmanager_action
)
+ self.iface.addPluginToDatabaseMenu(
+ self.tr("Model Baker"), self.__tidmanager_action
+ )
self.iface.addPluginToDatabaseMenu(
self.tr("Model Baker"), self.__topping_wizard_action
)
@@ -239,6 +257,9 @@ def unload(self):
self.iface.removePluginDatabaseMenu(
self.tr("Model Baker"), self.__datasetmanager_action
)
+ self.iface.removePluginDatabaseMenu(
+ self.tr("Model Baker"), self.__tidmanager_action
+ )
self.iface.removePluginDatabaseMenu(
self.tr("Model Baker"), self.__validate_action
)
@@ -257,6 +278,7 @@ def unload(self):
)
del self.__workflow_wizard_action
del self.__datasetmanager_action
+ del self.__tidmanager_action
del self.__validate_action
del self.__configure_action
del self.__help_action
@@ -334,6 +356,23 @@ def datasetmanager_dialog_finished(self):
self.__datasetmanager_action.setChecked(False)
self.datasetmanager_dlg = None
+ def show_tidmanager_dialog(self):
+ if self.tidmanager_dlg:
+ self.tidmanager_dlg.reject()
+ else:
+ self.tidmanager_dlg = TIDManagerDialog(self.iface, self.iface.mainWindow())
+ self.tidmanager_dlg.setAttribute(Qt.WA_DeleteOnClose)
+ self.tidmanager_dlg.setWindowFlags(
+ self.tidmanager_dlg.windowFlags() | Qt.Tool
+ )
+ self.tidmanager_dlg.show()
+ self.tidmanager_dlg.finished.connect(self.tidmanager_dialog_finished)
+ self.__tidmanager_action.setChecked(True)
+
+ def tidmanager_dialog_finished(self):
+ self.__tidmanager_action.setChecked(False)
+ self.tidmanager_dlg = None
+
def show_validate_dock(self):
self.__validate_dock.setVisible(not self.__validate_dock.isVisible())
diff --git a/QgisModelBaker/ui/layer_tids_panel.ui b/QgisModelBaker/ui/layer_tids_panel.ui
new file mode 100644
index 000000000..20e792118
--- /dev/null
+++ b/QgisModelBaker/ui/layer_tids_panel.ui
@@ -0,0 +1,40 @@
+
+