Skip to content

Commit

Permalink
Add a restore geopackage button to restore plugin state from QGIS pro…
Browse files Browse the repository at this point in the history
…ject

Fixes #127
  • Loading branch information
Huite committed Oct 27, 2023
1 parent 8422f79 commit 8377509
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 23 deletions.
66 changes: 55 additions & 11 deletions plugin/qgistim/widgets/dataset_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
QCheckBox,
QComboBox,
QFileDialog,
QGroupBox,
QHBoxLayout,
QHeaderView,
QLineEdit,
Expand Down Expand Up @@ -272,14 +273,16 @@ def __init__(self, parent):
self.new_geopackage_button = QPushButton("New")
self.open_geopackage_button = QPushButton("Open")
self.copy_geopackage_button = QPushButton("Copy")
self.restore_geopackage_button = QPushButton("Restore")
self.transient_combo_box = QComboBox()
self.transient_combo_box.addItems(["Steady-state", "Transient"])
self.transient_combo_box.currentTextChanged.connect(self.on_transient_changed)
self.remove_button = QPushButton("Remove from GeoPackage")
self.remove_button = QPushButton("Remove from Model")
self.add_button = QPushButton("Add to QGIS")
self.new_geopackage_button.clicked.connect(self.new_geopackage)
self.open_geopackage_button.clicked.connect(self.open_geopackage)
self.copy_geopackage_button.clicked.connect(self.copy_geopackage)
self.restore_geopackage_button.clicked.connect(self.restore_geopackage)
self.suppress_popup_checkbox = QCheckBox("Suppress attribute form pop-up")
self.suppress_popup_checkbox.stateChanged.connect(self.suppress_popup_changed)
self.remove_button.clicked.connect(self.remove_geopackage_layer)
Expand All @@ -288,18 +291,29 @@ def __init__(self, parent):
self.convert_button.clicked.connect(self.convert_to_python)
# Layout
dataset_layout = QVBoxLayout()

# Add geopackage management
geopackage_group = QGroupBox("GeoPackage")
geopackage_layout = QVBoxLayout()
geopackage_group.setLayout(geopackage_layout)
geopackage_layout.addWidget(self.dataset_line_edit)
geopackage_row = QHBoxLayout()
geopackage_row.addWidget(self.open_geopackage_button)
geopackage_row.addWidget(self.new_geopackage_button)
geopackage_row.addWidget(self.copy_geopackage_button)
geopackage_row.addWidget(self.restore_geopackage_button)
geopackage_layout.addLayout(geopackage_row)
dataset_layout.addWidget(geopackage_group)

# Transient versus steady-state selector
mode_row = QHBoxLayout()
dataset_row = QHBoxLayout()
layer_row = QHBoxLayout()
dataset_row.addWidget(self.dataset_line_edit)
dataset_row.addWidget(self.open_geopackage_button)
dataset_row.addWidget(self.new_geopackage_button)
dataset_row.addWidget(self.copy_geopackage_button)
dataset_layout.addLayout(dataset_row)
mode_row.addWidget(self.transient_combo_box)
dataset_layout.addLayout(mode_row)
# Dataset table and suppression checkbox
dataset_layout.addWidget(self.dataset_tree)
# Assorted widgets
dataset_layout.addWidget(self.suppress_popup_checkbox)
layer_row = QHBoxLayout()
layer_row.addWidget(self.add_button)
layer_row.addWidget(self.remove_button)
dataset_layout.addLayout(layer_row)
Expand Down Expand Up @@ -348,15 +362,17 @@ def add_selection_to_qgis(self) -> None:
self.add_item_to_qgis(item)
return

def load_geopackage(self) -> None:
def load_geopackage(
self, input_group: str = None, output_group: str = None
) -> None:
"""
Load the layers of a GeoPackage into the Layers Panel
"""
self.dataset_tree.clear()

name = str(Path(self.path).stem)
self.parent.create_input_group(name)
self.parent.create_output_group(name)
self.parent.create_input_group(name, input_group)
self.parent.create_output_group(name, output_group)

elements = load_elements_from_geopackage(self.path)
for element in elements:
Expand All @@ -372,6 +388,7 @@ def load_geopackage(self) -> None:
self.on_transient_changed()

self.model_crs = self.domain_item().element.timml_layer.crs()
self.parent.qgs_project.writeEntry("qgistim", "geopackage_path", self.path)
return

def new_geopackage(self) -> None:
Expand Down Expand Up @@ -420,6 +437,9 @@ def copy_geopackage(self) -> None:
"""
Copy a GeoPackage file, containing qgis-tim, and open it.
"""
# Do nothing if there's nothing to copy.
if self.path == "":
return
self.dataset_tree.clear()
target_path, _ = QFileDialog.getSaveFileName(self, "Select file", "", "*.gpkg")
if target_path != "": # Empty string in case of cancel button press
Expand All @@ -437,6 +457,30 @@ def copy_geopackage(self) -> None:
self.load_geopackage()
return

def restore_geopackage(self) -> None:
qgs_project = self.parent.qgs_project
geopackage_path, success = qgs_project.readEntry("qgistim", "geopackage_path")
if not success:
self.parent.message_bar.pushMessage(
title="Error",
text="Could not find a QGIS-Tim GeoPackage in this QGS Project.",
level=Qgis.Critical,
)
return

if not Path(geopackage_path).exists():
self.parent.message_bar.pushMessage(
title="Error",
text=f"QGIS-Tim Geopackage {geopackage_path} does not exist.",
level=Qgis.Critical,
)

input_group_name, _ = qgs_project.readEntry("qgistim", "input_group")
output_group_name, _ = qgs_project.readEntry("qgistim", "output_group")
self.dataset_line_edit.setText(geopackage_path)
self.load_geopackage(input_group_name, output_group_name)
return

def remove_geopackage_layer(self) -> None:
"""
Remove layers from:
Expand Down
52 changes: 40 additions & 12 deletions plugin/qgistim/widgets/tim_widget.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
"""
This module forms the high level DockWidget.
It ensures the underlying widgets can talk to each other. It also manages the
It ensures the underlying widgets can talk to each other. It also manages the
connection to the QGIS Layers Panel, and ensures there is a group for the Tim
layers there.
"""
from typing import Any, Dict, Union
from typing import Any, Dict, Optional, Union

from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (
Expand All @@ -15,7 +15,13 @@
QVBoxLayout,
QWidget,
)
from qgis.core import QgsApplication, QgsEditFormConfig, QgsMapLayer, QgsProject
from qgis.core import (
QgsApplication,
QgsEditFormConfig,
QgsLayerTreeGroup,
QgsMapLayer,
QgsProject,
)
from qgistim.core.server_handler import ServerHandler
from qgistim.core.task import BaseServerTask
from qgistim.widgets.compute_widget import ComputeWidget
Expand All @@ -32,13 +38,19 @@ def __init__(
self,
root,
name: str,
group_name: Optional[QgsLayerTreeGroup] = None,
):
self.name = name
self.root = root
self.subgroups = {}
self.create_group()

def create_group(self):
self.create_group(group_name)

def _create_group(self, group_name: str):
if group_name is not None:
self.group = self.root.findGroup(group_name)
if self.group is not None:
self.group.removeAllChildren()
return
self.group = self.root.addGroup(self.name)
return

Expand Down Expand Up @@ -147,6 +159,18 @@ def add_layer(
return maplayer


class InputGroup(LayersPanelGroup):
def create_group(self, group=None):
QgsProject.instance().writeEntry("qgistim", "input_group", self.name)
self._create_group(group)


class OutputGroup(LayersPanelGroup):
def create_group(self, group=None):
QgsProject.instance().writeEntry("qgistim", "output_group", self.name)
self._create_group(group)


class StartTask(BaseServerTask):
@property
def task_description(self):
Expand Down Expand Up @@ -208,6 +232,10 @@ def __init__(self, parent, iface):
# QGIS Layers Panel groups
self.input_group = None
self.output_group = None

# Connect to the project saved signal.
# Note that the project is a singleton instance, so it's always up to date.
self.qgs_project = QgsProject.instance()
return

# Inter-widget communication
Expand Down Expand Up @@ -293,16 +321,16 @@ def add_element(self, element: Any):

# QGIS layers
# -----------
def create_input_group(self, name: str) -> None:
root = QgsProject.instance().layerTreeRoot()
self.input_group = LayersPanelGroup(root, f"{name} input")
def create_input_group(self, name: str, group: str = None) -> None:
root = self.qgs_project.layerTreeRoot()
self.input_group = InputGroup(root, f"{name} input", group)
self.input_group.create_subgroup("timml")
self.input_group.create_subgroup("ttim")
return

def create_output_group(self, name: str) -> None:
root = QgsProject.instance().layerTreeRoot()
self.output_group = LayersPanelGroup(root, f"{name} output")
def create_output_group(self, name: str, group: str = None) -> None:
root = self.qgs_project.layerTreeRoot()
self.output_group = OutputGroup(root, f"{name} output", group)
# Pre-create the groups here to make sure the vector group ends up on top.
# Apparently moving it destroys the group?
self.output_group.create_subgroup("vector")
Expand Down

0 comments on commit 8377509

Please sign in to comment.