Skip to content

Commit

Permalink
[gui] Add Delete Basket support; introduce ili2db_utils module to exe…
Browse files Browse the repository at this point in the history
…cute common ili2db operations via Model Baker Library
  • Loading branch information
gacarrillor committed Sep 29, 2024
1 parent 67f47c7 commit c074485
Show file tree
Hide file tree
Showing 5 changed files with 221 additions and 94 deletions.
129 changes: 105 additions & 24 deletions QgisModelBaker/gui/basket_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,37 @@
***************************************************************************/
"""

from qgis.core import QgsApplication
from qgis.core import QgsApplication, QgsProject
from qgis.PyQt.QtWidgets import QDialog, QMessageBox

from QgisModelBaker.gui.create_baskets import CreateBasketDialog
from QgisModelBaker.gui.edit_basket import EditBasketDialog
from QgisModelBaker.gui.panel.summary_basket_panel import SummaryBasketPanel
from QgisModelBaker.libs.modelbaker.iliwrapper.ili2dbconfig import (
Ili2DbCommandConfiguration,
)
from QgisModelBaker.utils import gui_utils
from QgisModelBaker.utils.ili2db_utils import Ili2DbUtils

DIALOG_UI = gui_utils.get_ui_class("basket_manager.ui")


class BasketManagerDialog(QDialog, DIALOG_UI):
def __init__(self, parent=None, db_connector=None, datasetname=None):
def __init__(
self,
iface,
parent=None,
db_connector=None,
datasetname=None,
configuration: Ili2DbCommandConfiguration = None,
):
QDialog.__init__(self, parent)
self.setupUi(self)

self.iface = iface
self.datasetname = datasetname
self.db_connector = db_connector
self.configuration = configuration

self.buttonBox.accepted.connect(self.accept)

Expand Down Expand Up @@ -96,6 +109,17 @@ def _edit_basket(self) -> None:

def _delete_basket(self) -> None:
if self._valid_selection():
if not self.db_connector.get_basket_handling():
QMessageBox.warning(
self,
self.tr("Delete Basket"),
self.tr(
"Delete baskets is only available for database schemas created with --createBasketCol parameter."
),
QMessageBox.Close,
)
return

if (
QMessageBox.warning(
self,
Expand All @@ -107,25 +131,82 @@ def _delete_basket(self) -> None:
)
== QMessageBox.Yes
):
print("DELETED! (TODO)")

# def _accepted(self):
# feedbacks = self.baskets_panel.save_basket_config(
# self.db_connector, self.datasetname
# )
# negative_feedbacks = [
# feedback for feedback in feedbacks if feedback[0] is False
# ]
# if negative_feedbacks:
# warning_box = QMessageBox(self)
# warning_box.setIcon(QMessageBox.Critical)
# warning_title = self.tr("Creating baskets failed")
# warning_box.setWindowTitle(warning_title)
# warning_box.setText(
# "{}{}".format(
# "\n".join([feedback[1] for feedback in negative_feedbacks]),
# "\n(The problem is often an incorrectly formatted BID)",
# )
# )
# warning_box.exec_()
# self.close()
basket_config = self.baskets_panel.selected_basket_settings()
res, msg = self._do_delete_basket(basket_config)

if res:
# After deletion, make sure canvas is refreshed
self._refresh_map_layers()

# Refresh existing baskets in basket manager after deletion
self.baskets_panel.bid_model.load_basket_config(
self.db_connector, self.datasetname
)

warning_box = QMessageBox(self)
warning_box.setIcon(
QMessageBox.Information if res else QMessageBox.Warning
)
warning_box.setWindowTitle(self.tr("Delete Basket"))
warning_box.setText(msg)
warning_box.exec_()

def _refresh_map_layers(self):
# Refresh layer data sources and also their symbology (including feature count)
layer_tree_view = self.iface.layerTreeView()
for tree_layer in QgsProject.instance().layerTreeRoot().findLayers():
layer = tree_layer.layer()
layer.dataProvider().reloadData()
layer_tree_view.refreshLayerSymbology(layer.id())

def _do_delete_basket(self, basket_config):
# Keep original values just in case we need to go back to them
original_dataset_id = basket_config["dataset_t_id"]
original_dataset_name = basket_config["datasetname"]

# Create temporary dataset
tmp_dataset_id, tmp_dataset_name = "", "_tmp_dataset_tmp_"
res, msg = self.db_connector.create_dataset(tmp_dataset_name)
for _dataset in self.db_connector.get_datasets_info():
if _dataset["datasetname"] == tmp_dataset_name:
tmp_dataset_id = _dataset["t_id"]
break

if tmp_dataset_id == "":
return False, self.tr(
"Delete basket failed! Internal error modifying dataset/basket tables."
)

# Move basket to temporary dataset
basket_config["dataset_t_id"] = tmp_dataset_id
basket_config["datasetname"] = tmp_dataset_name

res, msg = self.db_connector.edit_basket(basket_config)
if not res:
return False, self.tr(
"Delete basket failed! Internal error modifying basket."
)

# Remove temporary dataset
res, msg = Ili2DbUtils().delete_dataset(tmp_dataset_name, self.configuration)

# If anything went bad, leave everything as the original status,
# i.e., move the basket to its original dataset
if not res:
msg = self.tr(
"Delete basket failed! Internal error deleting dataset/basket records."
)
basket_config["dataset_t_id"] = original_dataset_id
basket_config["datasetname"] = original_dataset_name
_res, _msg = self.db_connector.edit_basket(basket_config)
if not _res:
# We shouldn't reach this, the basket is in another dataset!
msg = self.tr("The basket (t_id: {}) couldn't be deleted!").format(
basket_config["basket_t_id"]
)
else:
msg = self.tr("Basket (t_id: {}) successfully deleted!").format(
basket_config["basket_t_id"]
)

return res, msg
77 changes: 12 additions & 65 deletions QgisModelBaker/gui/dataset_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,13 @@
from QgisModelBaker.gui.basket_manager import BasketManagerDialog
from QgisModelBaker.gui.edit_dataset_name import EditDatasetDialog
from QgisModelBaker.libs.modelbaker.db_factory.db_simple_factory import DbSimpleFactory
from QgisModelBaker.libs.modelbaker.iliwrapper import ilideleter
from QgisModelBaker.libs.modelbaker.iliwrapper.globals import DbIliMode
from QgisModelBaker.libs.modelbaker.iliwrapper.ili2dbconfig import (
DeleteConfiguration,
Ili2DbCommandConfiguration,
)
from QgisModelBaker.utils import gui_utils
from QgisModelBaker.utils.gui_utils import DatasetModel
from QgisModelBaker.utils.ili2db_utils import Ili2DbUtils

DIALOG_UI = gui_utils.get_ui_class("dataset_manager.ui")

Expand Down Expand Up @@ -191,16 +190,10 @@ def _delete_dataset(self):
dataset = self.dataset_tableview.selectedIndexes()[0].data(
int(DatasetModel.Roles.DATASETNAME)
)
res, msg = self._do_delete(dataset)
res, msg = Ili2DbUtils().delete_dataset(dataset, self.configuration)
if res:
# Refresh layer data sources and also their symbology (including feature count)
layer_tree_view = self.iface.layerTreeView()
for tree_layer in (
QgsProject.instance().layerTreeRoot().findLayers()
):
layer = tree_layer.layer()
layer.dataProvider().reloadData()
layer_tree_view.refreshLayerSymbology(layer.id())
# After deletion, make sure canvas is refreshed
self._refresh_map_layers()

# Refresh dataset table view
self._refresh_datasets()
Expand All @@ -213,59 +206,13 @@ def _delete_dataset(self):
warning_box.setText(msg)
warning_box.exec_()

def _do_delete(self, dataset):
from qgis.core import Qgis, QgsMessageLog

from QgisModelBaker.libs.modelbaker.iliwrapper.ili2dbutils import (
JavaNotFoundError,
)
from QgisModelBaker.libs.modelbaker.utils.qt_utils import OverrideCursor

deleter = ilideleter.Deleter()
deleter.tool = self.configuration.tool
deleter.configuration = DeleteConfiguration(self.configuration)
deleter.configuration.dataset = dataset

with OverrideCursor(Qt.WaitCursor):
self._connect_ili_executable_signals(deleter)
self._log = ""

res = True
msg = self.tr("Dataset '{}' successfully deleted!").format(dataset)
try:
if deleter.run() != ilideleter.Deleter.SUCCESS:
msg = self.tr(
"An error occurred when deleting the dataset '{}' from the DB (check the QGIS log panel)."
).format(dataset)
res = False
QgsMessageLog.logMessage(
self._log, self.tr("Delete dataset from DB"), Qgis.Critical
)
except JavaNotFoundError as e:
msg = e.error_string
res = False

self._disconnect_ili_executable_signals(deleter)

return res, msg

def _connect_ili_executable_signals(self, ili_executable):
# ili_executable.stderr.connect(self.stderr)
# ili_executable.stdout.connect(self.stdout)
ili_executable.process_started.connect(self._on_process_started)
ili_executable.stderr.connect(self._on_stderr)

def _disconnect_ili_executable_signals(self, ili_executable):
# ili_executable.stderr.disconnect(self.stderr)
# ili_executable.stdout.disconnect(self.stdout)
ili_executable.process_started.disconnect(self._on_process_started)
ili_executable.stderr.disconnect(self._on_stderr)

def _on_process_started(self, command):
self._log += command + "\n"

def _on_stderr(self, text):
self._log += text
def _refresh_map_layers(self):
# Refresh layer data sources and also their symbology (including feature count)
layer_tree_view = self.iface.layerTreeView()
for tree_layer in QgsProject.instance().layerTreeRoot().findLayers():
layer = tree_layer.layer()
layer.dataProvider().reloadData()
layer_tree_view.refreshLayerSymbology(layer.id())

def _open_basket_manager(self):
if self._valid_selection():
Expand All @@ -275,7 +222,7 @@ def _open_basket_manager(self):
int(DatasetModel.Roles.DATASETNAME)
)
basket_manager_dialog = BasketManagerDialog(
self, db_connector, datasetname
self.iface, self, db_connector, datasetname, self.configuration
)
basket_manager_dialog.exec_()

Expand Down
2 changes: 1 addition & 1 deletion QgisModelBaker/gui/edit_basket.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def __init__(
self.txtTopic.setText(self._basket_info["topic"])
self.txtBidOidType.setText(self._basket_info["bid_domain"])
self.txtBidValue.setText(self._basket_info["bid_value"])
self.txtAttachmentKey.setText(self._basket_info["attachment_key"])
self.txtAttachmentKey.setText(self._basket_info["attachmentkey"])

# Fill filtered datasets
for t_id, dataset_data in self._get_filtered_datasets().items():
Expand Down
8 changes: 4 additions & 4 deletions QgisModelBaker/gui/panel/summary_basket_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,15 +82,15 @@ def data(self, index, role):
if role == int(Qt.DisplayRole) or role == int(Qt.EditRole):
key = list(self.basket_settings.keys())[index.row()]
if index.column() == BasketModel.Columns.DATASET:
return self.basket_settings[key]["dataset"]
return self.basket_settings[key]["datasetname"]
if index.column() == BasketModel.Columns.TOPIC:
return key
if index.column() == BasketModel.Columns.BID_DOMAIN:
return self.basket_settings[key]["bid_domain"] or "---"
if index.column() == BasketModel.Columns.BID_VALUE:
return self.basket_settings[key]["bid_value"]
if index.column() == BasketModel.Columns.ATTACHMENT_KEY:
return self.basket_settings[key]["attachment_key"]
return self.basket_settings[key]["attachmentkey"]
elif role == int(Qt.ToolTipRole):
key = list(self.basket_settings.keys())[index.row()]
if index.column() == BasketModel.Columns.DATASET:
Expand Down Expand Up @@ -156,8 +156,8 @@ def load_basket_config(self, db_connector, dataset):
and topic_key == basket_record["topic"]
):
basket_setting["bid_value"] = basket_record["basket_t_ili_tid"]
basket_setting["attachment_key"] = basket_record["attachmentkey"]
basket_setting["dataset"] = basket_record["datasetname"]
basket_setting["attachmentkey"] = basket_record["attachmentkey"]
basket_setting["datasetname"] = basket_record["datasetname"]
basket_setting["bid_domain"] = topic_record["bid_domain"]

# Additional basket info, not displayed by the view, but useful
Expand Down
Loading

0 comments on commit c074485

Please sign in to comment.