oqtopus 0.1.16__py3-none-any.whl → 0.1.18__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -14,3 +14,5 @@ class ModuleAsset:
14
14
  self.download_url = download_url
15
15
  self.size = size
16
16
  self.type = type
17
+ self.package_zip = None
18
+ self.package_dir = None
@@ -25,6 +25,8 @@ class ModulePackage:
25
25
  branch=None,
26
26
  ):
27
27
  self.module = module
28
+ self.organisation = organisation
29
+ self.repository = repository
28
30
  self.type = type
29
31
  self.name = name
30
32
  self.branch = branch
@@ -50,12 +52,10 @@ class ModulePackage:
50
52
  if self.type == ModulePackage.Type.RELEASE:
51
53
  type = "tags"
52
54
 
53
- self.download_url = (
54
- f"https://github.com/{organisation}/{repository}/archive/refs/{type}/{self.branch}.zip"
55
- )
55
+ self.download_url = f"https://github.com/{self.organisation}/{self.repository}/archive/refs/{type}/{self.branch}.zip"
56
56
 
57
- self.zip_file = None
58
- self.package_dir = None
57
+ self.source_package_zip = None
58
+ self.source_package_dir = None
59
59
 
60
60
  def display_name(self):
61
61
  if self.prerelease:
@@ -25,6 +25,8 @@ class PackagePrepareTask(QThread):
25
25
 
26
26
  self.module_package = None
27
27
 
28
+ self.__destination_directory = None
29
+
28
30
  self.__canceled = False
29
31
  self.lastError = None
30
32
 
@@ -53,6 +55,8 @@ class PackagePrepareTask(QThread):
53
55
  if self.module_package is None:
54
56
  raise Exception(self.tr("No module version provided."))
55
57
 
58
+ self.__destination_directory = self.__prepareDestinationDirectory()
59
+
56
60
  self.__download_module_assets(self.module_package)
57
61
  self.lastError = None
58
62
 
@@ -61,13 +65,29 @@ class PackagePrepareTask(QThread):
61
65
  logger.critical(f"Package prepare task error: {e}")
62
66
  self.lastError = e
63
67
 
68
+ def __prepareDestinationDirectory(self):
69
+ """
70
+ Prepare the destination directory for the module package.
71
+ This method creates a temporary directory for the package.
72
+ """
73
+ temp_dir = PluginUtils.plugin_temp_path()
74
+ destination_directory = os.path.join(
75
+ temp_dir,
76
+ self.module_package.organisation,
77
+ self.module_package.repository,
78
+ self.module_package.name,
79
+ )
80
+ os.makedirs(destination_directory, exist_ok=True)
81
+
82
+ return destination_directory
83
+
64
84
  def __download_module_assets(self, module_package):
65
85
 
66
86
  # Download the source
67
87
  zip_file = self.__download_module_asset(module_package.download_url, "source.zip")
68
- module_package.zip_file = zip_file
88
+ module_package.source_package_zip = zip_file
69
89
  package_dir = self.__extract_zip_file(zip_file)
70
- module_package.package_dir = package_dir
90
+ module_package.source_package_dir = package_dir
71
91
 
72
92
  # Download the release assets
73
93
  self.__checkForCanceled()
@@ -77,6 +97,7 @@ class PackagePrepareTask(QThread):
77
97
  module_package.asset_project.type.value + ".zip",
78
98
  )
79
99
  package_dir = self.__extract_zip_file(zip_file)
100
+ module_package.asset_project.package_zip = zip_file
80
101
  module_package.asset_project.package_dir = package_dir
81
102
 
82
103
  self.__checkForCanceled()
@@ -86,15 +107,12 @@ class PackagePrepareTask(QThread):
86
107
  module_package.asset_plugin.type.value + ".zip",
87
108
  )
88
109
  package_dir = self.__extract_zip_file(zip_file)
110
+ module_package.asset_plugin.package_zip = zip_file
89
111
  module_package.asset_plugin.package_dir = package_dir
90
112
 
91
113
  def __download_module_asset(self, url: str, filename: str):
92
114
 
93
- temp_dir = PluginUtils.plugin_temp_path()
94
- destination_directory = os.path.join(temp_dir, "Downloads")
95
- os.makedirs(destination_directory, exist_ok=True)
96
-
97
- zip_file = os.path.join(destination_directory, filename)
115
+ zip_file = os.path.join(self.__destination_directory, filename)
98
116
 
99
117
  # Streaming, so we can iterate over the response.
100
118
  response = requests.get(url, allow_redirects=True, stream=True)
@@ -121,19 +139,17 @@ class PackagePrepareTask(QThread):
121
139
  return zip_file
122
140
 
123
141
  def __extract_zip_file(self, zip_file):
124
- temp_dir = PluginUtils.plugin_temp_path()
125
-
126
142
  # Unzip the file to plugin temp dir
127
143
  try:
128
144
  with zipfile.ZipFile(zip_file, "r") as zip_ref:
129
145
  # Find the top-level directory
130
146
  zip_dirname = zip_ref.namelist()[0].split("/")[0]
131
- package_dir = os.path.join(temp_dir, zip_dirname)
147
+ package_dir = os.path.join(self.__destination_directory, zip_dirname)
132
148
 
133
149
  if os.path.exists(package_dir):
134
150
  shutil.rmtree(package_dir)
135
151
 
136
- zip_ref.extractall(temp_dir)
152
+ zip_ref.extractall(self.__destination_directory)
137
153
 
138
154
  except zipfile.BadZipFile:
139
155
  raise Exception(self.tr(f"The selected file '{zip_file}' is not a valid zip archive."))
@@ -60,6 +60,15 @@ class DatabaseConnectionWidget(QWidget, DIALOG_UI):
60
60
  """
61
61
  return self.__database_connection
62
62
 
63
+ def getService(self):
64
+ """
65
+ Returns the current service name.
66
+ If no service is selected, returns None.
67
+ """
68
+ if self.db_services_comboBox.currentText() == "":
69
+ return None
70
+ return self.db_services_comboBox.currentText()
71
+
63
72
  def __loadDatabaseInformations(self):
64
73
  pg_service_conf_path = pgserviceparser_conf_path()
65
74
  self.db_servicesConfigFilePath_label.setText(
@@ -35,6 +35,11 @@ from ..utils.qt_utils import OverrideCursor
35
35
  DIALOG_UI = PluginUtils.get_ui_class("database_create_dialog.ui")
36
36
 
37
37
 
38
+ DEFAULT_PG_PORT = "5432"
39
+ DEFAULT_PG_DB = "postgres"
40
+ DEFAULT_PG_HOST = "localhost"
41
+
42
+
38
43
  class DatabaseCreateDialog(QDialog, DIALOG_UI):
39
44
  def __init__(self, selected_service=None, parent=None):
40
45
  QDialog.__init__(self, parent)
@@ -62,6 +67,11 @@ class DatabaseCreateDialog(QDialog, DIALOG_UI):
62
67
  self.parameters_ssl_comboBox.addItem("require", "require")
63
68
  self.parameters_ssl_comboBox.addItem("verify-ca", "verify-ca")
64
69
  self.parameters_ssl_comboBox.addItem("verify-full", "verify-full")
70
+ self.parameters_ssl_comboBox.setCurrentIndex(2) # Default to 'prefer'
71
+
72
+ self.parameters_host_lineEdit.setPlaceholderText(DEFAULT_PG_HOST)
73
+ self.parameters_port_lineEdit.setPlaceholderText(DEFAULT_PG_PORT)
74
+ self.parameters_database_lineEdit.setPlaceholderText(DEFAULT_PG_DB)
65
75
 
66
76
  self.database_lineEdit.textChanged.connect(self._databaseTextChanged)
67
77
 
@@ -91,8 +101,7 @@ class DatabaseCreateDialog(QDialog, DIALOG_UI):
91
101
  self.parameters_ssl_comboBox.setCurrentIndex(parameter_ssl_index)
92
102
  self.parameters_user_lineEdit.setText(service_user)
93
103
  self.parameters_password_lineEdit.setText(service_password)
94
-
95
- self.database_lineEdit.setText(service_dbname)
104
+ self.parameters_database_lineEdit.setText(service_dbname)
96
105
 
97
106
  def _enterManuallyToggled(self, checked):
98
107
  self.parameters_frame.setEnabled(checked)
@@ -195,16 +204,16 @@ class DatabaseCreateDialog(QDialog, DIALOG_UI):
195
204
 
196
205
  # Collect parameters from manual input fields
197
206
  if self.parameters_host_lineEdit.text():
198
- parameters["host"] = self.parameters_host_lineEdit.text()
207
+ parameters["host"] = self.parameters_host_lineEdit.text() or DEFAULT_PG_HOST
199
208
  if self.parameters_port_lineEdit.text():
200
- parameters["port"] = self.parameters_port_lineEdit.text()
209
+ parameters["port"] = self.parameters_port_lineEdit.text() or DEFAULT_PG_PORT
201
210
  if self.parameters_ssl_comboBox.currentData():
202
211
  parameters["sslmode"] = self.parameters_ssl_comboBox.currentData()
203
212
  if self.parameters_user_lineEdit.text():
204
213
  parameters["user"] = self.parameters_user_lineEdit.text()
205
214
  if self.parameters_password_lineEdit.text():
206
215
  parameters["password"] = self.parameters_password_lineEdit.text()
207
- if self.database_lineEdit.text():
208
- parameters["dbname"] = self.database_lineEdit.text()
216
+ if self.parameters_database_lineEdit.text():
217
+ parameters["dbname"] = self.parameters_database_lineEdit.text() or DEFAULT_PG_DB
209
218
 
210
219
  return parameters
@@ -45,6 +45,7 @@ from .database_connection_widget import DatabaseConnectionWidget # noqa: E402
45
45
  from .logs_widget import LogsWidget # noqa: E402
46
46
  from .module_selection_widget import ModuleSelectionWidget # noqa: E402
47
47
  from .module_widget import ModuleWidget # noqa: E402
48
+ from .plugin_widget import PluginWidget # noqa: E402
48
49
  from .project_widget import ProjectWidget # noqa: E402
49
50
 
50
51
  DIALOG_UI = PluginUtils.get_ui_class("main_dialog.ui")
@@ -52,7 +53,7 @@ DIALOG_UI = PluginUtils.get_ui_class("main_dialog.ui")
52
53
 
53
54
  class MainDialog(QDialog, DIALOG_UI):
54
55
 
55
- def __init__(self, modules_config, parent=None):
56
+ def __init__(self, modules_config_path, parent=None):
56
57
  QDialog.__init__(self, parent)
57
58
  self.setupUi(self)
58
59
 
@@ -60,7 +61,7 @@ class MainDialog(QDialog, DIALOG_UI):
60
61
  self.buttonBox.helpRequested.connect(self.__helpRequested)
61
62
 
62
63
  # Init GUI Modules
63
- self.__moduleSelectionWidget = ModuleSelectionWidget(modules_config, self)
64
+ self.__moduleSelectionWidget = ModuleSelectionWidget(modules_config_path, self)
64
65
  self.moduleSelection_groupBox.layout().addWidget(self.__moduleSelectionWidget)
65
66
 
66
67
  # Init GUI Database
@@ -75,6 +76,10 @@ class MainDialog(QDialog, DIALOG_UI):
75
76
  self.__projectWidget = ProjectWidget(self)
76
77
  self.project_tab.layout().addWidget(self.__projectWidget)
77
78
 
79
+ # Init GUI Plugin
80
+ self.__pluginWidget = PluginWidget(self)
81
+ self.plugin_tab.layout().addWidget(self.__pluginWidget)
82
+
78
83
  # Init GUI Logs
79
84
  self.__logsWidget = LogsWidget(self)
80
85
  self.logs_groupBox.layout().addWidget(self.__logsWidget)
@@ -108,6 +113,7 @@ class MainDialog(QDialog, DIALOG_UI):
108
113
  self.__databaseConnectionWidget.signal_connectionChanged.connect(
109
114
  self.__databaseConnectionWidget_connectionChanged
110
115
  )
116
+ self.__databaseConnectionWidget_connectionChanged()
111
117
 
112
118
  self.module_tab.setEnabled(False)
113
119
  self.plugin_tab.setEnabled(False)
@@ -164,5 +170,11 @@ class MainDialog(QDialog, DIALOG_UI):
164
170
  self.__moduleSelectionWidget.getSelectedModulePackage()
165
171
  )
166
172
 
173
+ self.__pluginWidget.setModulePackage(
174
+ self.__moduleSelectionWidget.getSelectedModulePackage()
175
+ )
176
+
167
177
  def __databaseConnectionWidget_connectionChanged(self):
168
178
  self.__moduleWidget.setDatabaseConnection(self.__databaseConnectionWidget.getConnection())
179
+
180
+ self.__projectWidget.setService(self.__databaseConnectionWidget.getService())
@@ -1,9 +1,11 @@
1
+ import yaml
1
2
  from qgis.PyQt.QtCore import Qt, QUrl, pyqtSignal
2
3
  from qgis.PyQt.QtGui import QDesktopServices
3
4
  from qgis.PyQt.QtWidgets import QApplication, QFileDialog, QMessageBox, QWidget
4
5
 
5
6
  from ..core.module import Module
6
7
  from ..core.module_package import ModulePackage
8
+ from ..core.modules_config import ModulesConfig
7
9
  from ..core.package_prepare_task import PackagePrepareTask, PackagePrepareTaskCanceled
8
10
  from ..utils.plugin_utils import PluginUtils, logger
9
11
  from ..utils.qt_utils import CriticalMessageBox, OverrideCursor, QtUtils
@@ -18,28 +20,44 @@ class ModuleSelectionWidget(QWidget, DIALOG_UI):
18
20
  signal_loadingStarted = pyqtSignal()
19
21
  signal_loadingFinished = pyqtSignal()
20
22
 
21
- def __init__(self, modules_config, parent=None):
23
+ def __init__(self, modules_config_path, parent=None):
22
24
  QWidget.__init__(self, parent)
23
25
  self.setupUi(self)
24
26
 
25
27
  self.__current_module = None
26
28
  self.__current_module_package = None
27
- self.__modules_config = modules_config
29
+ self.__modules_config = None
30
+
31
+ try:
32
+ with modules_config_path.open() as f:
33
+ data = yaml.safe_load(f)
34
+ self.__modules_config = ModulesConfig(**data)
35
+ except Exception as e:
36
+ logger.error(f"Error loading modules config from {modules_config_path}: {e}")
37
+ QMessageBox.critical(
38
+ self,
39
+ self.tr("Error"),
40
+ self.tr(f"Can't load modules configuration from '{modules_config_path}': {e}"),
41
+ )
42
+ self.__modules_config = None
28
43
 
29
44
  self.module_progressBar.setVisible(False)
30
45
 
31
46
  self.module_module_comboBox.clear()
32
47
  self.module_module_comboBox.addItem(self.tr("Please select a module"), None)
33
- for config_module in self.__modules_config.modules:
34
- module = Module(
35
- name=config_module.name,
36
- organisation=config_module.organisation,
37
- repository=config_module.repository,
38
- parent=self,
39
- )
40
- self.module_module_comboBox.addItem(module.name, module)
41
- module.signal_versionsLoaded.connect(self.__loadVersionsFinished)
42
- module.signal_developmentVersionsLoaded.connect(self.__loadDevelopmentVersionsFinished)
48
+ if self.__modules_config is not None:
49
+ for config_module in self.__modules_config.modules:
50
+ module = Module(
51
+ name=config_module.name,
52
+ organisation=config_module.organisation,
53
+ repository=config_module.repository,
54
+ parent=self,
55
+ )
56
+ self.module_module_comboBox.addItem(module.name, module)
57
+ module.signal_versionsLoaded.connect(self.__loadVersionsFinished)
58
+ module.signal_developmentVersionsLoaded.connect(
59
+ self.__loadDevelopmentVersionsFinished
60
+ )
43
61
 
44
62
  self.module_latestVersion_label.setText("")
45
63
  QtUtils.setForegroundColor(self.module_latestVersion_label, PluginUtils.COLOR_GREEN)
@@ -190,20 +208,26 @@ class ModuleSelectionWidget(QWidget, DIALOG_UI):
190
208
  QtUtils.setForegroundColor(self.module_information_label, PluginUtils.COLOR_WARNING)
191
209
  return
192
210
 
193
- package_dir = self.module_package_comboBox.currentData().package_dir
211
+ package_dir = self.module_package_comboBox.currentData().source_package_dir
194
212
  logger.info(f"Package loaded into '{package_dir}'")
195
- self.module_information_label.setText(package_dir)
196
213
  QtUtils.resetForegroundColor(self.module_information_label)
214
+ self.module_information_label.setText(
215
+ f"<a href='file://{package_dir}'>{package_dir}</a>",
216
+ )
197
217
 
198
218
  asset_project = self.module_package_comboBox.currentData().asset_project
199
219
  if asset_project:
200
- self.module_informationProject_label.setText(asset_project.package_dir)
220
+ self.module_informationProject_label.setText(
221
+ f"<a href='file://{asset_project.package_dir}'>{asset_project.package_dir}</a>",
222
+ )
201
223
  else:
202
224
  self.module_informationProject_label.setText("No asset available")
203
225
 
204
226
  asset_plugin = self.module_package_comboBox.currentData().asset_plugin
205
227
  if asset_plugin:
206
- self.module_informationPlugin_label.setText(asset_plugin.package_dir)
228
+ self.module_informationPlugin_label.setText(
229
+ f"<a href='file://{asset_plugin.package_dir}'>{asset_plugin.package_dir}</a>",
230
+ )
207
231
  else:
208
232
  self.module_informationPlugin_label.setText("No asset available")
209
233
 
@@ -42,13 +42,13 @@ class ModuleWidget(QWidget, DIALOG_UI):
42
42
  self.__updateModuleInfo()
43
43
 
44
44
  def __packagePrepareGetPUMConfig(self):
45
- package_dir = self.__current_module_package.package_dir
45
+ package_dir = self.__current_module_package.source_package_dir
46
46
 
47
47
  if package_dir is None:
48
48
  CriticalMessageBox(
49
49
  self.tr("Error"),
50
50
  self.tr(
51
- f"The selected file '{self.__current_module_package.zip_file}' does not contain a valid package directory."
51
+ f"The selected file '{self.__current_module_package.source_package_zip}' does not contain a valid package directory."
52
52
  ),
53
53
  None,
54
54
  self,
@@ -61,7 +61,7 @@ class ModuleWidget(QWidget, DIALOG_UI):
61
61
  CriticalMessageBox(
62
62
  self.tr("Error"),
63
63
  self.tr(
64
- f"The selected file '{self.__current_module_package.zip_file}' does not contain a valid .pum.yaml file."
64
+ f"The selected file '{self.__current_module_package.source_package_zip}' does not contain a valid .pum.yaml file."
65
65
  ),
66
66
  None,
67
67
  self,
@@ -0,0 +1,155 @@
1
+ import os
2
+ import shutil
3
+
4
+ from qgis.PyQt.QtCore import QUrl
5
+ from qgis.PyQt.QtGui import QDesktopServices
6
+ from qgis.PyQt.QtWidgets import QFileDialog, QMessageBox, QWidget
7
+
8
+ from ..core.module_package import ModulePackage
9
+ from ..utils.plugin_utils import PluginUtils, logger
10
+ from ..utils.qt_utils import QtUtils
11
+
12
+ DIALOG_UI = PluginUtils.get_ui_class("plugin_widget.ui")
13
+
14
+
15
+ class PluginWidget(QWidget, DIALOG_UI):
16
+
17
+ def __init__(self, parent=None):
18
+ QWidget.__init__(self, parent)
19
+ self.setupUi(self)
20
+
21
+ self.install_pushButton.clicked.connect(self.__installClicked)
22
+ self.seeChangelog_pushButton.clicked.connect(self.__seeChangelogClicked)
23
+ self.copyZipToDirectory_pushButton.clicked.connect(self.__copyZipToDirectoryClicked)
24
+
25
+ self.__current_module_package = None
26
+
27
+ def setModulePackage(self, module_package: ModulePackage):
28
+ self.__current_module_package = module_package
29
+ self.__packagePrepareGetPluginFilename()
30
+
31
+ def __packagePrepareGetPluginFilename(self):
32
+ asset_plugin = self.__current_module_package.asset_plugin
33
+ if asset_plugin is None:
34
+ self.info_label.setText(self.tr("No plugin asset available for this module version."))
35
+ QtUtils.setForegroundColor(self.info_label, PluginUtils.COLOR_WARNING)
36
+ QtUtils.setFontItalic(self.info_label, True)
37
+ return
38
+
39
+ # Check if the package exists
40
+ if not os.path.exists(asset_plugin.package_zip):
41
+ self.info_label.setText(
42
+ self.tr(f"Plugin zip file '{asset_plugin.package_zip}' does not exist.")
43
+ )
44
+ QtUtils.setForegroundColor(self.info_label, PluginUtils.COLOR_WARNING)
45
+ QtUtils.setFontItalic(self.info_label, True)
46
+ return
47
+
48
+ QtUtils.resetForegroundColor(self.info_label)
49
+ QtUtils.setFontItalic(self.info_label, False)
50
+ self.info_label.setText(
51
+ f"<a href='file://{asset_plugin.package_zip}'>{asset_plugin.package_zip}</a>",
52
+ )
53
+
54
+ def __installClicked(self):
55
+ if self.__current_module_package is None:
56
+ QMessageBox.warning(
57
+ self,
58
+ self.tr("Error"),
59
+ self.tr("Please select a module and version first."),
60
+ )
61
+ return
62
+
63
+ # Check if the package exists
64
+ asset_plugin = self.__current_module_package.asset_plugin
65
+ if not os.path.exists(asset_plugin.package_zip):
66
+ self.info_label.setText(
67
+ self.tr(f"Plugin zip file '{asset_plugin.package_zip}' does not exist.")
68
+ )
69
+ QtUtils.setForegroundColor(self.info_label, PluginUtils.COLOR_WARNING)
70
+ QtUtils.setFontItalic(self.info_label, True)
71
+ return
72
+
73
+ QMessageBox.warning(
74
+ self,
75
+ self.tr("Not implemented"),
76
+ self.tr("Installation is not implemented yet."),
77
+ )
78
+ return
79
+
80
+ def __seeChangelogClicked(self):
81
+ if self.__current_module_package is None:
82
+ QMessageBox.warning(
83
+ self,
84
+ self.tr("Can't open changelog"),
85
+ self.tr("Please select a module and version first."),
86
+ )
87
+ return
88
+
89
+ if self.__current_module_package.type == ModulePackage.Type.FROM_ZIP:
90
+ QMessageBox.warning(
91
+ self,
92
+ self.tr("Can't open changelog"),
93
+ self.tr("Changelog is not available for Zip packages."),
94
+ )
95
+ return
96
+
97
+ if self.__current_module_package.html_url is None:
98
+ QMessageBox.warning(
99
+ self,
100
+ self.tr("Can't open changelog"),
101
+ self.tr(
102
+ f"Changelog not available for version '{self.__current_module_package.display_name()}'."
103
+ ),
104
+ )
105
+ return
106
+
107
+ changelog_url = self.__current_module_package.html_url
108
+ logger.info(f"Opening changelog URL: {changelog_url}")
109
+ QDesktopServices.openUrl(QUrl(changelog_url))
110
+
111
+ def __copyZipToDirectoryClicked(self):
112
+ if self.__current_module_package is None:
113
+ QMessageBox.warning(
114
+ self,
115
+ self.tr("Error"),
116
+ self.tr("Please select a module and version first."),
117
+ )
118
+ return
119
+
120
+ # Check if the package exists
121
+ asset_plugin = self.__current_module_package.asset_plugin
122
+ if not os.path.exists(asset_plugin.package_zip):
123
+ self.info_label.setText(
124
+ self.tr(f"Plugin zip file '{asset_plugin.package_zip}' does not exist.")
125
+ )
126
+ QtUtils.setForegroundColor(self.info_label, PluginUtils.COLOR_WARNING)
127
+ QtUtils.setFontItalic(self.info_label, True)
128
+ return
129
+
130
+ install_destination = QFileDialog.getExistingDirectory(
131
+ self,
132
+ self.tr("Select installation directory"),
133
+ "",
134
+ QFileDialog.Option.ShowDirsOnly,
135
+ )
136
+
137
+ if not install_destination:
138
+ return
139
+
140
+ # Copy the plugin package to the selected directory
141
+ try:
142
+ shutil.copy2(asset_plugin.package_zip, install_destination)
143
+
144
+ QMessageBox.information(
145
+ self,
146
+ self.tr("Plugin copied"),
147
+ self.tr(f"Plugin package has been copied to '{install_destination}'."),
148
+ )
149
+ except Exception as e:
150
+ QMessageBox.critical(
151
+ self,
152
+ self.tr("Error"),
153
+ self.tr(f"Failed to copy plugin package: {e}"),
154
+ )
155
+ return
@@ -1,4 +1,5 @@
1
1
  import os
2
+ import re
2
3
  import shutil
3
4
 
4
5
  from qgis.PyQt.QtCore import QUrl
@@ -22,11 +23,15 @@ class ProjectWidget(QWidget, DIALOG_UI):
22
23
  self.project_seeChangelog_pushButton.clicked.connect(self.__projectSeeChangelogClicked)
23
24
 
24
25
  self.__current_module_package = None
26
+ self.__current_service = None
25
27
 
26
28
  def setModulePackage(self, module_package: ModulePackage):
27
29
  self.__current_module_package = module_package
28
30
  self.__packagePrepareGetProjectFilename()
29
31
 
32
+ def setService(self, service):
33
+ self.__current_service = service
34
+
30
35
  def __packagePrepareGetProjectFilename(self):
31
36
  asset_project = self.__current_module_package.asset_project
32
37
  if asset_project is None:
@@ -110,6 +115,24 @@ class ProjectWidget(QWidget, DIALOG_UI):
110
115
 
111
116
  if os.path.isdir(source_path):
112
117
  shutil.copytree(source_path, destination_path, dirs_exist_ok=True)
118
+
119
+ elif item.endswith(".qgs"):
120
+ with open(source_path) as original_project:
121
+ contents = original_project.read()
122
+
123
+ if self.__current_service is not None:
124
+ contents = re.sub(
125
+ r"service='[^']+'", f"service='{self.__current_service}'", contents
126
+ )
127
+ else:
128
+ logger.warning(
129
+ "No service set, skipping service replacement in project file."
130
+ )
131
+
132
+ installed_path = os.path.join(install_destination, item)
133
+ with open(installed_path, "w") as output_file:
134
+ output_file.write(contents)
135
+
113
136
  else:
114
137
  shutil.copy2(source_path, destination_path)
115
138
 
oqtopus/oqtopus.py CHANGED
@@ -2,8 +2,6 @@ import sys
2
2
  import types
3
3
  from pathlib import Path
4
4
 
5
- import yaml
6
-
7
5
  # Create fake qgis.PyQt modules that point to PyQt5 modules
8
6
  try:
9
7
  pyqt_core = __import__("PyQt6.QtCore", fromlist=[""])
@@ -38,7 +36,6 @@ sys.modules["qgis.PyQt.uic"] = pyqt_uic
38
36
 
39
37
  from qgis.PyQt.QtGui import QIcon # noqa: E402
40
38
 
41
- from .core.modules_config import ModulesConfig # noqa: E402
42
39
  from .gui.main_dialog import MainDialog # noqa: E402
43
40
  from .utils.plugin_utils import PluginUtils # noqa: E402
44
41
 
@@ -52,11 +49,7 @@ def main():
52
49
 
53
50
  conf_path = Path(__file__).parent / "default_config.yaml"
54
51
 
55
- with conf_path.open() as f:
56
- data = yaml.safe_load(f)
57
- modules_config = ModulesConfig(**data)
58
-
59
- dialog = MainDialog(modules_config)
52
+ dialog = MainDialog(modules_config_path=conf_path)
60
53
  dialog.setWindowIcon(icon)
61
54
  dialog.show()
62
55
 
oqtopus/oqtopus_plugin.py CHANGED
@@ -1,11 +1,8 @@
1
1
  from pathlib import Path
2
2
 
3
- import yaml
4
3
  from qgis.PyQt.QtGui import QIcon
5
4
  from qgis.PyQt.QtWidgets import QAction, QApplication
6
5
 
7
- from oqtopus.core.modules_config import ModulesConfig
8
-
9
6
  from .gui.about_dialog import AboutDialog
10
7
  from .gui.main_dialog import MainDialog
11
8
  from .utils.plugin_utils import PluginUtils, logger
@@ -35,12 +32,6 @@ class OqtopusPlugin:
35
32
  self.actions = []
36
33
  self.main_menu_name = self.tr(f"&{PluginUtils.PLUGIN_NAME}")
37
34
 
38
- conf_path = Path(__file__).parent / "default_config.yaml"
39
-
40
- with conf_path.open() as f:
41
- data = yaml.safe_load(f)
42
- self.modules_config = ModulesConfig(**data)
43
-
44
35
  # noinspection PyMethodMayBeStatic
45
36
  def tr(self, source_text):
46
37
  """
@@ -159,7 +150,9 @@ class OqtopusPlugin:
159
150
  self.iface.removeToolBarIcon(action)
160
151
 
161
152
  def show_main_dialog(self):
162
- main_dialog = MainDialog(self.modules_config, self.iface.mainWindow())
153
+ conf_path = Path(__file__).parent / "default_config.yaml"
154
+
155
+ main_dialog = MainDialog(modules_config_path=conf_path, parent=self.iface.mainWindow())
163
156
  main_dialog.exec()
164
157
 
165
158
  def show_logs_folder(self):
@@ -62,13 +62,23 @@
62
62
  <enum>QFrame::Raised</enum>
63
63
  </property>
64
64
  <layout class="QGridLayout" name="gridLayout_5">
65
- <item row="2" column="0">
66
- <widget class="QLabel" name="label_10">
65
+ <item row="5" column="1">
66
+ <widget class="QLineEdit" name="parameters_password_lineEdit">
67
+ <property name="clearButtonEnabled">
68
+ <bool>true</bool>
69
+ </property>
70
+ </widget>
71
+ </item>
72
+ <item row="5" column="0">
73
+ <widget class="QLabel" name="label_12">
67
74
  <property name="text">
68
- <string>Port</string>
75
+ <string>Password</string>
69
76
  </property>
70
77
  </widget>
71
78
  </item>
79
+ <item row="3" column="1">
80
+ <widget class="QComboBox" name="parameters_ssl_comboBox"/>
81
+ </item>
72
82
  <item row="3" column="0">
73
83
  <widget class="QLabel" name="label_11">
74
84
  <property name="text">
@@ -76,38 +86,11 @@
76
86
  </property>
77
87
  </widget>
78
88
  </item>
79
- <item row="3" column="1">
80
- <widget class="QComboBox" name="parameters_ssl_comboBox">
81
- <item>
82
- <property name="text">
83
- <string>disabled</string>
84
- </property>
85
- </item>
86
- <item>
87
- <property name="text">
88
- <string>allow</string>
89
- </property>
90
- </item>
91
- <item>
92
- <property name="text">
93
- <string>prefer</string>
94
- </property>
95
- </item>
96
- <item>
97
- <property name="text">
98
- <string>require</string>
99
- </property>
100
- </item>
101
- <item>
102
- <property name="text">
103
- <string>verify-ca</string>
104
- </property>
105
- </item>
106
- <item>
107
- <property name="text">
108
- <string>verify-full</string>
109
- </property>
110
- </item>
89
+ <item row="1" column="1">
90
+ <widget class="QLineEdit" name="parameters_host_lineEdit">
91
+ <property name="clearButtonEnabled">
92
+ <bool>true</bool>
93
+ </property>
111
94
  </widget>
112
95
  </item>
113
96
  <item row="2" column="1">
@@ -117,45 +100,51 @@
117
100
  </property>
118
101
  </widget>
119
102
  </item>
120
- <item row="1" column="1">
121
- <widget class="QLineEdit" name="parameters_host_lineEdit">
103
+ <item row="4" column="1">
104
+ <widget class="QLineEdit" name="parameters_user_lineEdit">
122
105
  <property name="clearButtonEnabled">
123
106
  <bool>true</bool>
124
107
  </property>
125
108
  </widget>
126
109
  </item>
127
- <item row="1" column="0">
128
- <widget class="QLabel" name="label_9">
110
+ <item row="4" column="0">
111
+ <widget class="QLabel" name="label_8">
129
112
  <property name="text">
130
- <string>Host</string>
113
+ <string>User</string>
131
114
  </property>
132
115
  </widget>
133
116
  </item>
134
- <item row="4" column="0">
135
- <widget class="QLabel" name="label_8">
117
+ <item row="2" column="0">
118
+ <widget class="QLabel" name="label_10">
136
119
  <property name="text">
137
- <string>User</string>
120
+ <string>Port</string>
138
121
  </property>
139
122
  </widget>
140
123
  </item>
141
- <item row="4" column="1">
142
- <widget class="QLineEdit" name="parameters_user_lineEdit">
143
- <property name="clearButtonEnabled">
144
- <bool>true</bool>
124
+ <item row="1" column="0">
125
+ <widget class="QLabel" name="label_9">
126
+ <property name="text">
127
+ <string>Host</string>
145
128
  </property>
146
129
  </widget>
147
130
  </item>
148
- <item row="5" column="0">
149
- <widget class="QLabel" name="label_12">
131
+ <item row="6" column="0">
132
+ <widget class="QLabel" name="label_3">
150
133
  <property name="text">
151
- <string>Password</string>
134
+ <string>Database</string>
152
135
  </property>
153
136
  </widget>
154
137
  </item>
155
- <item row="5" column="1">
156
- <widget class="QLineEdit" name="parameters_password_lineEdit">
157
- <property name="clearButtonEnabled">
158
- <bool>true</bool>
138
+ <item row="6" column="1">
139
+ <widget class="QLineEdit" name="parameters_database_lineEdit">
140
+ <property name="toolTip">
141
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;This is the database used to connect to the cluster. It must already exist.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
142
+ </property>
143
+ <property name="text">
144
+ <string/>
145
+ </property>
146
+ <property name="placeholderText">
147
+ <string>postgres</string>
159
148
  </property>
160
149
  </widget>
161
150
  </item>
oqtopus/ui/main_dialog.ui CHANGED
@@ -63,77 +63,7 @@
63
63
  <attribute name="title">
64
64
  <string>Plugin</string>
65
65
  </attribute>
66
- <layout class="QGridLayout" name="gridLayout_6">
67
- <item row="1" column="1">
68
- <widget class="QLabel" name="label_8">
69
- <property name="font">
70
- <font>
71
- <italic>true</italic>
72
- </font>
73
- </property>
74
- <property name="text">
75
- <string>no current version</string>
76
- </property>
77
- </widget>
78
- </item>
79
- <item row="2" column="0">
80
- <widget class="QPushButton" name="pushButton_5">
81
- <property name="text">
82
- <string>Install 1.6.3</string>
83
- </property>
84
- </widget>
85
- </item>
86
- <item row="0" column="0">
87
- <widget class="QLabel" name="label_6">
88
- <property name="text">
89
- <string>Current QGIS profile</string>
90
- </property>
91
- </widget>
92
- </item>
93
- <item row="1" column="0">
94
- <widget class="QLabel" name="label_5">
95
- <property name="text">
96
- <string>Current version</string>
97
- </property>
98
- </widget>
99
- </item>
100
- <item row="3" column="0">
101
- <widget class="QPushButton" name="pushButton_8">
102
- <property name="text">
103
- <string>Copy ZIP to directory</string>
104
- </property>
105
- </widget>
106
- </item>
107
- <item row="2" column="1">
108
- <widget class="QPushButton" name="pushButton_11">
109
- <property name="text">
110
- <string>See changelog</string>
111
- </property>
112
- </widget>
113
- </item>
114
- <item row="0" column="1">
115
- <widget class="QLabel" name="label_7">
116
- <property name="font">
117
- <font>
118
- <italic>true</italic>
119
- </font>
120
- </property>
121
- <property name="text">
122
- <string>tww_user_profile</string>
123
- </property>
124
- </widget>
125
- </item>
126
- <item row="4" column="0">
127
- <spacer name="verticalSpacer_6">
128
- <property name="sizeHint" stdset="0">
129
- <size>
130
- <width>20</width>
131
- <height>40</height>
132
- </size>
133
- </property>
134
- </spacer>
135
- </item>
136
- </layout>
66
+ <layout class="QGridLayout" name="gridLayout_6"/>
137
67
  </widget>
138
68
  </widget>
139
69
  </item>
@@ -26,6 +26,12 @@
26
26
  <property name="text">
27
27
  <string>-</string>
28
28
  </property>
29
+ <property name="openExternalLinks">
30
+ <bool>true</bool>
31
+ </property>
32
+ <property name="textInteractionFlags">
33
+ <set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
34
+ </property>
29
35
  </widget>
30
36
  </item>
31
37
  <item row="0" column="0">
@@ -54,6 +60,12 @@
54
60
  <property name="text">
55
61
  <string>-</string>
56
62
  </property>
63
+ <property name="openExternalLinks">
64
+ <bool>true</bool>
65
+ </property>
66
+ <property name="textInteractionFlags">
67
+ <set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
68
+ </property>
57
69
  </widget>
58
70
  </item>
59
71
  <item row="2" column="0" colspan="3">
@@ -111,8 +123,11 @@
111
123
  <property name="text">
112
124
  <string>-</string>
113
125
  </property>
126
+ <property name="openExternalLinks">
127
+ <bool>true</bool>
128
+ </property>
114
129
  <property name="textInteractionFlags">
115
- <set>Qt::NoTextInteraction</set>
130
+ <set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
116
131
  </property>
117
132
  </widget>
118
133
  </item>
@@ -0,0 +1,96 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <ui version="4.0">
3
+ <class>Form</class>
4
+ <widget class="QWidget" name="Form">
5
+ <property name="geometry">
6
+ <rect>
7
+ <x>0</x>
8
+ <y>0</y>
9
+ <width>400</width>
10
+ <height>300</height>
11
+ </rect>
12
+ </property>
13
+ <property name="windowTitle">
14
+ <string>Form</string>
15
+ </property>
16
+ <layout class="QGridLayout" name="gridLayout">
17
+ <item row="2" column="0">
18
+ <widget class="QPushButton" name="install_pushButton">
19
+ <property name="text">
20
+ <string>Install</string>
21
+ </property>
22
+ </widget>
23
+ </item>
24
+ <item row="0" column="0">
25
+ <widget class="QLabel" name="label">
26
+ <property name="text">
27
+ <string>Current QGIS profile</string>
28
+ </property>
29
+ </widget>
30
+ </item>
31
+ <item row="0" column="1">
32
+ <widget class="QLabel" name="qgisProfile_label">
33
+ <property name="text">
34
+ <string>-</string>
35
+ </property>
36
+ </widget>
37
+ </item>
38
+ <item row="1" column="1">
39
+ <widget class="QLabel" name="currentVersion_label">
40
+ <property name="text">
41
+ <string>no current version</string>
42
+ </property>
43
+ </widget>
44
+ </item>
45
+ <item row="2" column="1">
46
+ <widget class="QPushButton" name="seeChangelog_pushButton">
47
+ <property name="text">
48
+ <string>See changelog</string>
49
+ </property>
50
+ </widget>
51
+ </item>
52
+ <item row="5" column="0">
53
+ <spacer name="verticalSpacer">
54
+ <property name="orientation">
55
+ <enum>Qt::Vertical</enum>
56
+ </property>
57
+ <property name="sizeHint" stdset="0">
58
+ <size>
59
+ <width>20</width>
60
+ <height>133</height>
61
+ </size>
62
+ </property>
63
+ </spacer>
64
+ </item>
65
+ <item row="3" column="0">
66
+ <widget class="QPushButton" name="copyZipToDirectory_pushButton">
67
+ <property name="text">
68
+ <string>Copy ZIP to directory</string>
69
+ </property>
70
+ </widget>
71
+ </item>
72
+ <item row="1" column="0">
73
+ <widget class="QLabel" name="label_3">
74
+ <property name="text">
75
+ <string>Current version</string>
76
+ </property>
77
+ </widget>
78
+ </item>
79
+ <item row="4" column="0" colspan="2">
80
+ <widget class="QLabel" name="info_label">
81
+ <property name="text">
82
+ <string>-</string>
83
+ </property>
84
+ <property name="openExternalLinks">
85
+ <bool>true</bool>
86
+ </property>
87
+ <property name="textInteractionFlags">
88
+ <set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
89
+ </property>
90
+ </widget>
91
+ </item>
92
+ </layout>
93
+ </widget>
94
+ <resources/>
95
+ <connections/>
96
+ </ui>
@@ -17,7 +17,7 @@
17
17
  <item row="0" column="0">
18
18
  <widget class="QPushButton" name="project_install_pushButton">
19
19
  <property name="text">
20
- <string>Install demo project</string>
20
+ <string>Install template project</string>
21
21
  </property>
22
22
  </widget>
23
23
  </item>
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: oqtopus
3
- Version: 0.1.16
3
+ Version: 0.1.18
4
4
  Summary: A QGIS module manager
5
5
  Author-email: Damiano Lombardi <damiano@opengis.ch>
6
6
  License: GNU GENERAL PUBLIC LICENSE
@@ -1,43 +1,45 @@
1
1
  oqtopus/__init__.py,sha256=PUl5ObSgoyF6tcNphBip9Rff8lul0t9VobiwsLKwgFA,104
2
- oqtopus/oqtopus.py,sha256=e70YIN0xAB33jHOmfoK8-zP0CeZc6jCV5dAf8rAIbB4,2032
3
- oqtopus/oqtopus_plugin.py,sha256=yzrM_sJyZQ-MVYhvG-bILdPF6jH415z9LK9xKEpT5Sg,5995
2
+ oqtopus/oqtopus.py,sha256=BF_JSF2oOCzc8Qr7Z0B7FJdYrdAR3FR9L7oXh3QatL4,1860
3
+ oqtopus/oqtopus_plugin.py,sha256=Mpyk6xIgZ1wehBzv70xc6OfddiHQYfXnU6-2E6dDihs,5815
4
4
  oqtopus/core/module.py,sha256=XOGI7R_2LyoscXAA-hCTKu7KjJ6ppAPgVFwrtSBiWTA,4631
5
- oqtopus/core/module_asset.py,sha256=gMHauU5AdAK9gKlsjN1cmbXIca_Xwzb0QcnLBBrJ6f4,403
6
- oqtopus/core/module_package.py,sha256=15kqjw0LOx8Iy9N3zMwKhNee4k5q_2g1atu19dC12wg,3645
5
+ oqtopus/core/module_asset.py,sha256=qr_wwriJ_rZd86EuBo_Rx-MDCDJNYA6odhk6F-Z6YFA,467
6
+ oqtopus/core/module_package.py,sha256=ilMWlArVmvULhoKHEXg7hNwiE6pLUsAMkLwtOes4j5A,3726
7
7
  oqtopus/core/modules_config.py,sha256=iEN_JYuFuGpF4dyfnmcJPfp_bIzrn_PNbq9G1DElyCg,186
8
- oqtopus/core/package_prepare_task.py,sha256=Eoq9i6tpaik8dpnMef8CKBlmEdXs16krogrQU6vobXI,4839
8
+ oqtopus/core/package_prepare_task.py,sha256=YqIjUbCqDyCd5t0Un71ECgY0LW_uFFxuXyO701nXZ_M,5483
9
9
  oqtopus/gui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
10
  oqtopus/gui/about_dialog.py,sha256=dDNwHxKf_M82Z-TKmXW1fXmnI_WSV_7MShqz05trzRw,2345
11
- oqtopus/gui/database_connection_widget.py,sha256=Uyhwj_jUY5nM5UTv95zkXBoBwbTwX4HsNvVuUzkcY7o,6096
12
- oqtopus/gui/database_create_dialog.py,sha256=klegVkrK9_7-aWWX0Fzue-mOAPyB09Ao1DJeLXdoNF8,8580
11
+ oqtopus/gui/database_connection_widget.py,sha256=7wFO1ysGwoNoXFFakNz6TktwOm28z3dRmbVxavIXX0E,6375
12
+ oqtopus/gui/database_create_dialog.py,sha256=afltzI1s9B0QGnZl6mgsX-0EvwOUArMu1Vxar4RsYvs,9055
13
13
  oqtopus/gui/database_duplicate_dialog.py,sha256=Oz8pob6HxZHbV5Thcrhy4dPvGEI4_brSxw9KIcTc2ZE,4017
14
14
  oqtopus/gui/logs_widget.py,sha256=B9Kbwt6cD40CV5mfcyaHZ5foJIPvWRednbxIRdeRgpU,6593
15
- oqtopus/gui/main_dialog.py,sha256=6nW76FzOg1w0B4bQl6l21YW03xfEf40fOxYb1Jv5WQI,5886
16
- oqtopus/gui/module_selection_widget.py,sha256=cWQFKDCslXYQL1vbfPOQwFYMkeRxxdThajY-dbpZc-w,15169
17
- oqtopus/gui/module_widget.py,sha256=g86mgctjfgkkGr57ynEb98jWkQRNtbDbDLpXwARSgO8,7591
15
+ oqtopus/gui/main_dialog.py,sha256=7nxn4vL5fIege0qBPP1mrOp5jP0YWXFJ_k_ywGeKD8M,6362
16
+ oqtopus/gui/module_selection_widget.py,sha256=57M9sM_VhD5lAfxqOxEPWUHiB2Ty6EQQkRnvAZ0VSv8,16116
17
+ oqtopus/gui/module_widget.py,sha256=ev8LoYVREg45mLLU9qu5bPhS4uDiayFAAy8e2zoLk-c,7618
18
18
  oqtopus/gui/parameters_groupbox.py,sha256=Lgwv76epIvZOZA0y9sxNcbuZ0Tun-ObUzvOa6eM3EzM,2842
19
- oqtopus/gui/project_widget.py,sha256=qAUF7pJ3B-mBv3AMC9lg3kdQvt6c4Z5xi4zl-cvpx2g,5796
19
+ oqtopus/gui/plugin_widget.py,sha256=BDtheJ35yrk55Th0vHulHe99jsJUMY11lKBgrHHmkiE,5622
20
+ oqtopus/gui/project_widget.py,sha256=T34MyHzHgKw1Dl6V67MKPneSd9DDgrWhuhj7mrcvjSg,6696
20
21
  oqtopus/gui/settings_dialog.py,sha256=wgwVCuAIBh9iLrs9y5HfE99LrTV0rEYbL3frMBlW0cQ,1547
21
22
  oqtopus/ui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
23
  oqtopus/ui/about_dialog.ui,sha256=2oa5u3LIvN3prHyELUG-bwDuEHlBn9-uuA4CwYsEARo,6236
23
24
  oqtopus/ui/database_connection_widget.ui,sha256=0hLBaOx0KcLTH6RlkziVj-tsczjHDUGC-3EXQYgcTuE,3729
24
- oqtopus/ui/database_create_dialog.ui,sha256=Zu_YVSIL6MMOkg-1gPx5DQU-h-I93mhE5lpuViCFP7E,8295
25
+ oqtopus/ui/database_create_dialog.ui,sha256=wM_x54bfgdSaShdx6MwBgDx_R-O_ckeoynEhFjs-Sws,8261
25
26
  oqtopus/ui/database_duplicate_dialog.ui,sha256=EzMRYhlxsiP_sr9ixBJn4lnefM5R_p1oXx4RCyMAj9U,3826
26
27
  oqtopus/ui/logs_widget.ui,sha256=oAgEtRUBXB-DzLC0vmBP-PEA-Uu3d3ppFm0ahs1jHQI,2785
27
- oqtopus/ui/main_dialog.ui,sha256=idp-jcLKdxbI22JrmXHsZtgmfT9YvOXkngMKxqqOJF0,4682
28
- oqtopus/ui/module_selection_widget.ui,sha256=AqLPBtX1B8Q03s-JB75lDP__OkhGH04cFVjZnoFwurw,4849
28
+ oqtopus/ui/main_dialog.ui,sha256=mB_VeJ-4wXJm3UTS5leGg_ZgFwgBJaS1QruBqnYMh6U,2650
29
+ oqtopus/ui/module_selection_widget.ui,sha256=IWfoWT5vHoayQPoOPIHOJlg4JdNmVX8DHFQnTIv-Hdk,5646
29
30
  oqtopus/ui/module_widget.ui,sha256=2sm0J-qb4CRiKaGk5lyg6AMWlq0d2hE0IW5OSYmJQZo,5662
30
- oqtopus/ui/project_widget.ui,sha256=flrADzGgDL04l2VdcTltn1IyrmE42tEjYtWXAReKdvc,1596
31
+ oqtopus/ui/plugin_widget.ui,sha256=osJ_QwzmXahV5fEHk4WfUjBBQ7jdsrL4pixiMF2jURA,2570
32
+ oqtopus/ui/project_widget.ui,sha256=5YqSjHR8mQFmHzbSB2M6JnNfrpkqhlRC0N9MSlgcXY8,1600
31
33
  oqtopus/ui/settings_dialog.ui,sha256=3PqxTMo22Ola1zl6XkwhXCi6G-uum6g_1-nbjSXWilI,2216
32
34
  oqtopus/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
33
35
  oqtopus/utils/plugin_utils.py,sha256=v-Oxu2zs8tQWzEdHnwEl1mseapyvpPS-lHimJNK2zHY,5702
34
36
  oqtopus/utils/qt_utils.py,sha256=HPe9tOQQH9R9xZp4rGphVhSJO7220q368xmreDu5-6g,3243
35
37
  oqtopus/utils/tmmtlogging.py,sha256=BSAPrhQGCuH2boMG4bP8QFyLfoss1uR4pO_pXjTA1eQ,1733
36
38
  oqtopus/utils/translation.py,sha256=p1d5N6CYIf94fGYdPQnJamdum9MVBlPkJ24c557rqdg,2647
37
- oqtopus-0.1.16.dist-info/licenses/LICENSE,sha256=gXf5dRMhNSbfLPYYTY_5hsZ1r7UU1OaKQEAQUhuIBkM,18092
39
+ oqtopus-0.1.18.dist-info/licenses/LICENSE,sha256=gXf5dRMhNSbfLPYYTY_5hsZ1r7UU1OaKQEAQUhuIBkM,18092
38
40
  tests/__init__.py,sha256=z5CxS92efenLcDm64Sifx26EjZBCWPO4oVvaEEHJJ6w,444
39
41
  tests/test_plugin_load.py,sha256=HuVLdrsn2PSjKIrvcLj0EH7vNE8-0jBMmHZHihsqB3Q,517
40
- oqtopus-0.1.16.dist-info/METADATA,sha256=g0Vr6WBe9SvnbKZEckDwXQbqwv8dPjdR_0c0nH8WIsY,21475
41
- oqtopus-0.1.16.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
42
- oqtopus-0.1.16.dist-info/top_level.txt,sha256=i4DHi21kcGIzrF8DlgsKj-UCENHg_NebTRac7cwt32A,14
43
- oqtopus-0.1.16.dist-info/RECORD,,
42
+ oqtopus-0.1.18.dist-info/METADATA,sha256=qk2WDV_BKgW05EmceSuaW1IwRFs-ChcbsxX5Eof4QbY,21475
43
+ oqtopus-0.1.18.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
44
+ oqtopus-0.1.18.dist-info/top_level.txt,sha256=i4DHi21kcGIzrF8DlgsKj-UCENHg_NebTRac7cwt32A,14
45
+ oqtopus-0.1.18.dist-info/RECORD,,