Deltares / Ribasim

Water resources modeling
https://ribasim.org/
MIT License
39 stars 5 forks source link

Add a button to synchronize the QGIS plugin with the QGIS project #1687

Open Huite opened 1 month ago

Huite commented 1 month ago

Problem

To illustrate:

Open QGIS and the Ribasim plugin. Click New and create a new model called test.toml test is added as a group in the Layers panel Save the project as test-ribasim.qgz Close QGIS

Reopen QGIS and the Ribasim plugin Go to Project > Open project, open test-ribasim.qgz Note that test is still in the Layers panel Note that the QGIS plugin is empty (it's not synchronized with the project)

To get the plugin up and running again: click open and open test.toml Note that are now two "test" layer groups in the Layers Panel

Solution

There's no trivially simple solution to this. Ideally, you would open a project, the plugin recognizes the Layers panel group, recognizes the layers; re-associates with the layers, and re-adds layers from the geopackage that have been (accidentally) deleted by the user prior to saving the QGIS project. I've tried implementing this before, and I created a lot of complexity. What I decided on instead is to register the input group and the model path in the QGS project instead, and add a "Restore" button which uses those entries to re-create the input group with all Layers. This isn't fancy, but it's simple, robust, and does what you want >95% of the time.

    def open_model_from_toml(self, path) -> None:
        """Open a Ribasim model file."""
        self.dataset_line_edit.setText(path)
        self.load_geopackage()
        self.ribasim_widget.toggle_node_buttons(True)
        self.refresh_results()
        self.dataset_tree.sortByColumn(0, Qt.SortOrder.AscendingOrder)

def open_model(self) -> None:
        """Open a Ribasim model file."""
        self.dataset_tree.clear()
        path, _ = QFileDialog.getOpenFileName(self, "Select file", "", "*.toml")
        if path != "":  # Empty string in case of cancel button press
             self.open_model_from_toml(path)

Improved functionality

After implementing this:

Reopen QGIS and the Ribasim plugin Go to Project > Open project, open test-ribasim.qgz Note that test is still in the Layers panel Note that the QGIS plugin is empty (it's not synchronized with the project)

To get the plugin up and running again: Click restore Click Yes to recreate the input group in the layers panel

It doesn't save a lot of clicks, but somehow it's far less frustrating.

Weaknesses

Uh, the name "Restore" is probably to general? Synchronize could work too? But it's not specific enough. If we add the buttons to a new row (like the example above), we could probably spell it out? i.e. "Synchronize with project"?

A remaining weakness of this method is that this will not keep non-default styling of input layers, since it recreates the layers fully. This is another argument for storing styling information in the geopackage instead of relying on the default layer_styling provided by the QGIS plugin.

The problem with checking for the existence of layers is that all kinds of thing may have changed in them. A user can freely change the name in the Layers Panel (since it's just cosmetic). Layers may have been moved to other Layers groups entirely. The group may have been deleted entirely. It's all doable, but I don't think it's worth the hassle.

Some other thoughts:

visr commented 1 month ago

This is another argument for storing styling information in the geopackage

We plan to do this soon: https://github.com/Deltares/Ribasim/issues/610