diff --git a/QgisModelBaker/gui/workflow_wizard/database_selection_page.py b/QgisModelBaker/gui/workflow_wizard/database_selection_page.py index b7f51c5c..8388630c 100644 --- a/QgisModelBaker/gui/workflow_wizard/database_selection_page.py +++ b/QgisModelBaker/gui/workflow_wizard/database_selection_page.py @@ -159,5 +159,24 @@ def is_valid(self): ) return res + def help_text(self): + logline = self.tr( + "Here you have to set the connection parameters for your datasource..." + ) + help_paragraphs = self.tr( + """ +

On GeoPackage

+

You can select a gpkg file.
+ Or if you want to create a new one, just type the desired name on an existing path (and it will be created).

+

On PostgreSQL

+

For a detailed description of each parameter, see the documentation

+

A superuser login must be configured in the Model Baker settings Database < Model Baker < Settings. + """ + ) + docutext = self.tr( + 'Find more information about the database settings in the documentation...' + ) + return logline, help_paragraphs, docutext + def nextId(self): return self.workflow_wizard.next_id() diff --git a/QgisModelBaker/gui/workflow_wizard/default_baskets_page.py b/QgisModelBaker/gui/workflow_wizard/default_baskets_page.py index 8c97c48f..6f62db36 100644 --- a/QgisModelBaker/gui/workflow_wizard/default_baskets_page.py +++ b/QgisModelBaker/gui/workflow_wizard/default_baskets_page.py @@ -103,3 +103,19 @@ def _skip(self): self.skip_button.setDisabled(True) self.baskets_panel.setDisabled(True) self.setComplete(True) + + def help_text(self): + logline = self.tr( + "Honestly, I don't know if you want to create the baskets or skip this step.
See below..." + ) + help_paragraphs = self.tr( + """ +

If you plan to import data later (from xtf or xml), the necessary baskets will be created on import anyway.

+

However, if you have no data to import and want to collect the data fresh, you may need to create the baskets.

+

The checked baskets are those that Model Baker has identified as relevant according to the recognised inheritance.

+ """ + ) + docutext = self.tr( + 'Find more information about this in the documentation and about baskets and datasets in general here...' + ) + return logline, help_paragraphs, docutext diff --git a/QgisModelBaker/gui/workflow_wizard/execution_page.py b/QgisModelBaker/gui/workflow_wizard/execution_page.py index 267bf25c..35779911 100644 --- a/QgisModelBaker/gui/workflow_wizard/execution_page.py +++ b/QgisModelBaker/gui/workflow_wizard/execution_page.py @@ -199,3 +199,19 @@ def _on_process_finished(self, exit_code, result): message = self.tr("Finished with errors!") self.workflow_wizard.log_panel.print_info(message, level) + + def help_text(self): + logline = self.tr("Run, skip or edit the required ili2db sessions...") + help_paragraphs = self.tr( + """ +

With the small triangle next to run, you can expand the possiblities.

+

Usually the required ili2db sessions are detected, you should not need to skip them.

+

You might need to edit the command in case your system requires it. But you would know, if you need to.

+

A pretty common use case is, that you want to import invalid data, to fix 'em in QGIS.
+ So you can create schemas without constraints and/or import data without validation.

+ """ + ) + docutext = self.tr( + 'Find more information about this in the documentation...' + ) + return logline, help_paragraphs, docutext diff --git a/QgisModelBaker/gui/workflow_wizard/export_data_configuration_page.py b/QgisModelBaker/gui/workflow_wizard/export_data_configuration_page.py index 9b1c11a8..d3aa3337 100644 --- a/QgisModelBaker/gui/workflow_wizard/export_data_configuration_page.py +++ b/QgisModelBaker/gui/workflow_wizard/export_data_configuration_page.py @@ -92,3 +92,21 @@ def _set_current_export_target(self, text): == QValidator.Acceptable ) self.workflow_wizard.current_export_target = text + + def help_text(self): + logline = self.tr( + "You want to export your data to an xml-file? There are two big options..." + ) + help_paragraphs = self.tr( + """ +

Filter

+

You can filter your data by the models, datasets or baskets in which it is stored.

+

Format

+

Still you can choose Export data in another model, which allows you to select a base model as the data format.
+ Even if the data is stored in an extended model.

+ """ + ) + docutext = self.tr( + 'Find more information about exporting data in the documentation...' + ) + return logline, help_paragraphs, docutext diff --git a/QgisModelBaker/gui/workflow_wizard/import_data_configuration_page.py b/QgisModelBaker/gui/workflow_wizard/import_data_configuration_page.py index 79aff9c1..620242ae 100644 --- a/QgisModelBaker/gui/workflow_wizard/import_data_configuration_page.py +++ b/QgisModelBaker/gui/workflow_wizard/import_data_configuration_page.py @@ -454,3 +454,24 @@ def _datasetmanager_dialog_finished(self): gui_utils.SourceModel.Columns.DATASET, DatasetComboDelegate(self, self.db_connector), ) + + def help_text(self): + logline = self.tr( + "Now you can see all the datafiles to import into your database..." + ) + help_paragraphs = self.tr( + """ +

The list

+

Those are the datafiles you've chosen for import or were detected automatically. If one shouldn't be there, you can remove it with -.

+

Maybe you want to add referenced data file from the repositories (ilidata.xml).

+

Or you may want to change the order of the imports (perhaps the user data depends on the catalogue data, etc.),
which you can do by dragging and dropping with the arrows on the left.

+

Delete

+

If you choose to delete, the existing data will be deleted before the new data is imported.
Usually this makes no difference when using baskets, as an update will also replace the data.

+

Dataset

+

Choose the dataset. If you need another, then create a new one via the Dataset manager.

+ """ + ) + docutext = self.tr( + 'Find more information about this page in the documentation and about baskets and datasets in general here ...' + ) + return logline, help_paragraphs, docutext diff --git a/QgisModelBaker/gui/workflow_wizard/import_schema_configuration_page.py b/QgisModelBaker/gui/workflow_wizard/import_schema_configuration_page.py index 66636770..837f2ee6 100644 --- a/QgisModelBaker/gui/workflow_wizard/import_schema_configuration_page.py +++ b/QgisModelBaker/gui/workflow_wizard/import_schema_configuration_page.py @@ -578,3 +578,28 @@ def _load_metaconfig(self): self.workflow_wizard.refresh_import_models() self.workflow_wizard.busy(self, False) + + def help_text(self): + logline = self.tr( + "Now the given models are detected. You may not need all of 'em..." + ) + help_paragraphs = self.tr( + """ +

There are several ways the Model Baker wizard detects INTERLIS models: +

+

You can check or uncheck the models you want to import to a physical schema.

+

As well you can select a Metaconfiguration file from the repositories to load ili2db settings and styling properties into QGIS project.
+ More information about those metaconfigurations in the documentation.

+

The Advanced Options allow you to edit the most important ili2db settings

+ """ + ) + docutext = self.tr( + 'Find more information about this in the documentation...' + ) + return logline, help_paragraphs, docutext diff --git a/QgisModelBaker/gui/workflow_wizard/import_source_selection_page.py b/QgisModelBaker/gui/workflow_wizard/import_source_selection_page.py index 7dcb34a1..9457143d 100644 --- a/QgisModelBaker/gui/workflow_wizard/import_source_selection_page.py +++ b/QgisModelBaker/gui/workflow_wizard/import_source_selection_page.py @@ -220,3 +220,18 @@ def _clear_cache_button_clicked(self): IliToppingFileCache.CACHE_PATH, str(exception) ), ) + + def help_text(self): + logline = self.tr( + "Here you need to add the models and/or files you want to use..." + ) + help_paragraphs = self.tr( + """ +

You can select a model from the repository and add it with the +.

+

You can add local files (ili, xtf, xml, toml etc.) via the file browser or with drag and drop.

+ """ + ) + docutext = self.tr( + 'Find more information about the source selection in the documentation...' + ) + return logline, help_paragraphs, docutext diff --git a/QgisModelBaker/gui/workflow_wizard/intro_page.py b/QgisModelBaker/gui/workflow_wizard/intro_page.py index 8743d14e..317cac36 100644 --- a/QgisModelBaker/gui/workflow_wizard/intro_page.py +++ b/QgisModelBaker/gui/workflow_wizard/intro_page.py @@ -55,3 +55,23 @@ def _on_generate(self): def _on_export(self): self.next_id = gui_utils.PageIds.ExportDatabaseSelection self.workflow_wizard.next() + + def help_text(self): + logline = self.tr( + "You have just opened the Workflow Wizard, now you need to choose your plans..." + ) + help_paragraphs = self.tr( + """ +

> Choose data files and models to import or generate a new database

+

If you want to create a physical database based on an INTERLIS model, regardless of whether it is based on an ili-file or a model from the repository.

+

Or if you want to import data (catalogues or user data), regardless of whether the database already exists or not.

+

> Generate a QGIS Project from an existing database

+

If you want to select a database from which to create a QGIS project.

+

> Export data from an existing database

+

If you want to export data to an XTF file.

+ """ + ) + docutext = self.tr( + 'Find more information about the workflow wizard in the documentation...' + ) + return logline, help_paragraphs, docutext diff --git a/QgisModelBaker/gui/workflow_wizard/project_creation_page.py b/QgisModelBaker/gui/workflow_wizard/project_creation_page.py index 95bf5d73..013a20e8 100644 --- a/QgisModelBaker/gui/workflow_wizard/project_creation_page.py +++ b/QgisModelBaker/gui/workflow_wizard/project_creation_page.py @@ -711,3 +711,22 @@ def _inheritance(self): for setting_record in setting_records: if setting_record["tag"] == "ch.ehi.ili2db.inheritanceTrafo": return setting_record["setting"] + + def help_text(self): + logline = self.tr( + "Most of the time you won't need to change anything here.
Just press Generate :-)" + ) + help_paragraphs = self.tr( + """ +

Project Topping

+

If your database was created using a metaconfiguration (you'd know this), it will now be recognised.

+

If not, you may still be able to choose a project topping from the repositories.

+

Project Optimization

+

The project is optimized depending on the inheritance structure of the INTERLIS model on which it is based.
+ Means it hides unused layers etc. Read more about optimization strategies here.

+ """ + ) + docutext = self.tr( + 'Find more information about this page in the documentation...' + ) + return logline, help_paragraphs, docutext diff --git a/QgisModelBaker/gui/workflow_wizard/tid_configuration_page.py b/QgisModelBaker/gui/workflow_wizard/tid_configuration_page.py index 20c19855..b9429964 100644 --- a/QgisModelBaker/gui/workflow_wizard/tid_configuration_page.py +++ b/QgisModelBaker/gui/workflow_wizard/tid_configuration_page.py @@ -68,3 +68,21 @@ def _set_tid_configuration(self): self.workflow_wizard.log_panel.print_info(message, LogLevel.WARNING) self.progress_bar.setValue(100) self.setStyleSheet(gui_utils.ERROR_STYLE) + + def help_text(self): + logline = self.tr( + "OIDs can be a pain to fill up - let Model Baker do it for you..." + ) + help_paragraphs = self.tr( + """ +

Model Baker recognized the OID Type according to the model and proposed default expressions.

+

You still can change them. In case of STANDARDOID you have to set your own prefix.

+

Reset the t_id value

+

When using STANDARDOID or I32OID we need a sequence. Here we take the one from the t_id.
+ When you change it here, be aware that you don't set it lower than a currently used t_id.

+ """ + ) + docutext = self.tr( + 'Find more information about this page in the documentation and about OID settings in general here' + ) + return logline, help_paragraphs, docutext diff --git a/QgisModelBaker/gui/workflow_wizard/workflow_wizard.py b/QgisModelBaker/gui/workflow_wizard/workflow_wizard.py index 44d1ccee..af9c450d 100644 --- a/QgisModelBaker/gui/workflow_wizard/workflow_wizard.py +++ b/QgisModelBaker/gui/workflow_wizard/workflow_wizard.py @@ -22,6 +22,7 @@ import re from qgis.PyQt.QtCore import QEventLoop, QSize, Qt, QTimer +from qgis.PyQt.QtGui import QPixmap from qgis.PyQt.QtWidgets import QDialog, QSplitter, QVBoxLayout, QWizard import QgisModelBaker.libs.modelbaker.utils.db_utils as db_utils @@ -81,7 +82,7 @@ def __init__(self, iface, base_config, parent): self.setWindowTitle(self.tr("QGIS Model Baker Wizard")) self.setWizardStyle(QWizard.ModernStyle) - self.setOption(QWizard.NoCancelButtonOnLastPage) + self.setOptions(QWizard.NoCancelButtonOnLastPage | QWizard.HaveHelpButton) self.current_id = 0 @@ -215,6 +216,9 @@ def __init__(self, iface, base_config, parent): self.currentIdChanged.connect(self.id_changed) + # on pressing the help button + self.helpRequested.connect(self._show_help) + def sizeHint(self): return QSize( self.fontMetrics().lineSpacing() * 48, self.fontMetrics().lineSpacing() * 48 @@ -694,6 +698,34 @@ def append_dropped_files(self, dropped_files, dropped_ini_files): dropped_ini_files[0] ) + def _show_help(self): + current_id = self.currentId() + title = self.tr("Help at {}".format(self._current_page_title(current_id))) + logline, help_paragraphs, docutext = self.currentPage().help_text() + text = """
+ {help_paragraphs} +
+ {docu_and_community_paragraphs} + """.format( + help_paragraphs=help_paragraphs, + docutext=docutext, + docu_and_community_paragraphs=self.tr( + """ +

{docutext}

+

...or get community help at {forum} or at {github}

+ """ + ).format( + docutext=docutext, + forum='Model Baker @ INTERLIS Forum', + github='GitHub', + ), + ) + log_paragraph = f'

< {logline}

' + + self.help_dlg = HelpDialog(self, title, log_paragraph, text) + self.help_dlg.setAttribute(Qt.WA_DeleteOnClose) + self.help_dlg.show() + def busy(self, page, busy, text="Busy..."): page.setEnabled(not busy) self.log_panel.busy_bar.setVisible(busy) @@ -732,3 +764,29 @@ def append_dropped_files(self, dropped_files, dropped_ini_files): self.workflow_wizard.append_dropped_files(dropped_files, dropped_ini_files) self.workflow_wizard.restart() self.workflow_wizard.next() + + +class HelpDialog(QDialog, gui_utils.get_ui_class("help_dialog.ui")): + def __init__( + self, + parent=None, + title="Help", + logline="I need somebody", + text="Not just anybody", + ): + QDialog.__init__(self, parent) + self.setupUi(self) + + self.setWindowTitle(title) + scaled_pixmap = QPixmap( + os.path.join( + os.path.dirname(__file__), "../../images/QgisModelBaker-icon.svg" + ) + ).scaled( + int(self.fontMetrics().lineSpacing() * 4.5), + self.fontMetrics().lineSpacing() * 5, + ) + + self.imagelabel.setPixmap(scaled_pixmap) + self.loglinelabel.setText(logline) + self.textlabel.setText(text) diff --git a/QgisModelBaker/qgismodelbaker.py b/QgisModelBaker/qgismodelbaker.py index b0df8b53..4aab158f 100644 --- a/QgisModelBaker/qgismodelbaker.py +++ b/QgisModelBaker/qgismodelbaker.py @@ -40,7 +40,7 @@ QTranslator, QUrl, ) -from qgis.PyQt.QtGui import QDesktopServices, QIcon +from qgis.PyQt.QtGui import QDesktopServices, QIcon, QPixmap from qgis.PyQt.QtWidgets import QAction, QMessageBox from qgis.utils import available_plugins @@ -399,7 +399,13 @@ def show_help_documentation(self): def show_about_dialog(self): self.msg = QMessageBox() - self.msg.setIcon(QMessageBox.Information) + pixmap = QPixmap( + os.path.join(os.path.dirname(__file__), "images/QgisModelBaker-icon.svg") + ).scaled( + int(self.msg.fontMetrics().lineSpacing() * 4.5), + self.msg.fontMetrics().lineSpacing() * 5, + ) + self.msg.setIconPixmap(pixmap) self.msg.setTextFormat(Qt.RichText) self.msg.setWindowTitle(self.tr("About Model Baker")) self.msg.setText( diff --git a/QgisModelBaker/ui/help_dialog.ui b/QgisModelBaker/ui/help_dialog.ui new file mode 100644 index 00000000..2280e477 --- /dev/null +++ b/QgisModelBaker/ui/help_dialog.ui @@ -0,0 +1,132 @@ + + + Dialog + + + + 0 + 0 + 398 + 145 + + + + + 0 + 0 + + + + Help + + + + + + + + + 0 + 0 + + + + <html><head/><body><p>icon</p></body></html> + + + Qt::RichText + + + + + + + + 0 + 0 + + + + help logline + + + true + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + <html><head/><body><p>help text</p></body></html> + + + Qt::RichText + + + true + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Close + + + + + + + + + buttonBox + accepted() + Dialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + Dialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + +