Skip to content

Commit 9f25944

Browse files
authored
Update module informations when db changes (#30)
* Update module informations when db changes * Better display long ongoing operations (fix #21) * Asynchrone version loader
1 parent 8075ef8 commit 9f25944

File tree

4 files changed

+194
-81
lines changed

4 files changed

+194
-81
lines changed
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
from enum import Enum
2+
3+
from qgis.PyQt.QtCore import QThread
4+
5+
6+
class ModuleVersionLoaderCanceled(Exception):
7+
pass
8+
9+
10+
class ModuleVersionLoader(QThread):
11+
12+
class Mode(Enum):
13+
NORMAL = 1
14+
DEVELOPMENT = 2
15+
16+
def __init__(self, parent=None):
17+
super().__init__(parent)
18+
self.__module = None
19+
self.__mode = self.Mode.NORMAL
20+
21+
self.lastError = None
22+
23+
def start_load_versions(self, module, mode: Mode = Mode.NORMAL):
24+
if self.isRunning():
25+
self.cancel()
26+
self.wait()
27+
28+
self.__module = module
29+
self.__mode = mode
30+
31+
self.start()
32+
33+
def run(self):
34+
self.lastError = None
35+
try:
36+
if self.__mode == self.Mode.NORMAL:
37+
self.__module.load_versions()
38+
elif self.__mode == self.Mode.DEVELOPMENT:
39+
self.__module.load_development_versions()
40+
41+
except Exception as e:
42+
self.lastError = e

oqtopus/gui/about_dialog.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ def __init__(self, parent=None):
5353
self.qgisMinimumVersionLabel.setText(qgisMinimumVersion)
5454

5555
scaled_logo = QPixmap(PluginUtils.get_plugin_icon_path("oqtopus-logo.png")).scaled(
56-
254, 254, aspectRatioMode=1, transformMode=Qt.TransformationMode.SmoothTransformation
56+
254,
57+
254,
58+
aspectRatioMode=Qt.AspectRatioMode.KeepAspectRatio,
59+
transformMode=Qt.TransformationMode.SmoothTransformation,
5760
)
5861
self.iconLabel.setPixmap(scaled_logo)

oqtopus/gui/module_selection_widget.py

Lines changed: 101 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
from qgis.PyQt.QtCore import Qt, QUrl, pyqtSignal
22
from qgis.PyQt.QtGui import QDesktopServices
3-
from qgis.PyQt.QtWidgets import QFileDialog, QMessageBox, QWidget
3+
from qgis.PyQt.QtWidgets import QApplication, QFileDialog, QMessageBox, QWidget
44

55
from ..core.module import Module
66
from ..core.module_package import ModulePackage
7+
from ..core.module_version_loader import (
8+
ModuleVersionLoader,
9+
ModuleVersionLoaderCanceled,
10+
)
711
from ..core.package_prepare_task import PackagePrepareTask, PackagePrepareTaskCanceled
812
from ..utils.plugin_utils import PluginUtils, logger
913
from ..utils.qt_utils import CriticalMessageBox, OverrideCursor, QtUtils
@@ -49,13 +53,19 @@ def __init__(self, modules_config, parent=None):
4953
self.module_seeChangeLog_pushButton.clicked.connect(self.__seeChangeLogClicked)
5054
self.module_browseZip_toolButton.clicked.connect(self.__moduleBrowseZipClicked)
5155

56+
self.__version_loader = ModuleVersionLoader(self)
57+
self.__version_loader.finished.connect(self.__loadVersionsFinished)
58+
5259
self.__packagePrepareTask = PackagePrepareTask(self)
5360
self.__packagePrepareTask.finished.connect(self.__packagePrepareTaskFinished)
5461
self.__packagePrepareTask.signalPackagingProgress.connect(
5562
self.__packagePrepareTaskProgress
5663
)
5764

5865
def close(self):
66+
if self.__version_loader.isRunning():
67+
self.__version_loader.wait()
68+
5969
if self.__packagePrepareTask.isRunning():
6070
self.__packagePrepareTask.cancel()
6171
self.__packagePrepareTask.wait()
@@ -83,64 +93,13 @@ def __moduleChanged(self, index):
8393
if self.__current_module is None:
8494
return
8595

86-
try:
87-
with OverrideCursor(Qt.CursorShape.WaitCursor):
88-
if self.__current_module.versions == list():
89-
self.__current_module.load_versions()
90-
91-
for module_package in self.__current_module.versions:
92-
self.module_package_comboBox.addItem(
93-
module_package.display_name(), module_package
94-
)
95-
96-
if self.__current_module.latest_version is not None:
97-
self.module_latestVersion_label.setText(
98-
f"Latest: {self.__current_module.latest_version.name}"
99-
)
100-
101-
except Exception as exception:
102-
error_message = str(exception)
103-
if "rate limit exceeded for url" in error_message.lower():
104-
CriticalMessageBox(
105-
self.tr("GitHub API Rate Limit Exceeded"),
106-
self.tr(
107-
"Oqtopus needs to download release data from GitHub to work properly.<br><br>"
108-
"GitHub limits the number of requests that can be made without authentication. "
109-
"You have reached the maximum number of requests allowed for unauthenticated users.<br><br>"
110-
"To continue using this feature, please create a free GitHub personal access token and enter it in the Settings dialog.<br><br>"
111-
"This will increase your request limit.<br><br>"
112-
"<b>How to get a token:</b><br>"
113-
"1. Go to <a href='https://github.com/settings/tokens'>GitHub Personal Access Tokens</a>.<br>"
114-
"2. Click <b>Generate new token</b> and select the <code>repo</code> scope.<br>"
115-
"3. Copy the generated token and paste it in the Settings dialog of this application."
116-
),
117-
exception,
118-
self,
119-
).exec()
120-
else:
121-
CriticalMessageBox(
122-
self.tr("Error"), self.tr("Can't load module versions:"), exception, self
123-
).exec()
124-
return
125-
126-
self.module_package_comboBox.insertSeparator(self.module_package_comboBox.count())
127-
self.module_package_comboBox.addItem(
128-
self.tr("Load from ZIP file"),
129-
ModulePackage(
130-
module=self.__current_module,
131-
organisation=self.__current_module.organisation,
132-
repository=self.__current_module.repository,
133-
json_payload=None,
134-
type=ModulePackage.Type.FROM_ZIP,
135-
),
136-
)
137-
138-
self.module_package_comboBox.insertSeparator(self.module_package_comboBox.count())
139-
self.module_package_comboBox.addItem(
140-
self.tr("Load development branches"), self.module_package_SPECIAL_LOAD_DEVELOPMENT
141-
)
96+
self.module_progressBar.setVisible(True)
97+
QApplication.processEvents()
14298

143-
logger.info(f"Versions loaded for module '{self.__current_module.name}'.")
99+
if self.__current_module.versions == list():
100+
self.__version_loader.start_load_versions(
101+
module=self.__current_module, mode=ModuleVersionLoader.Mode.NORMAL
102+
)
144103

145104
def __moduleVersionChanged(self, index):
146105

@@ -311,3 +270,87 @@ def __seeChangeLogClicked(self):
311270
changelog_url = self.__current_module_package.html_url
312271
logger.info(f"Opening changelog URL: {changelog_url}")
313272
QDesktopServices.openUrl(QUrl(changelog_url))
273+
274+
def __loadVersionsFinished(self):
275+
logger.info("Loading versions finished")
276+
277+
self.signal_loadingFinished.emit()
278+
self.module_progressBar.setVisible(False)
279+
280+
if isinstance(self.__version_loader.lastError, ModuleVersionLoaderCanceled):
281+
logger.info("Load versions task was canceled by user.")
282+
self.module_information_label.setText(self.tr("Versions loading canceled."))
283+
QtUtils.setForegroundColor(self.module_information_label, PluginUtils.COLOR_WARNING)
284+
return
285+
286+
if self.__version_loader.lastError is not None:
287+
error_text = self.tr("Can't load module versions:")
288+
CriticalMessageBox(
289+
self.tr("Error"), error_text, self.__version_loader.lastError, self
290+
).exec()
291+
self.module_information_label.setText(error_text)
292+
QtUtils.setForegroundColor(self.module_information_label, PluginUtils.COLOR_WARNING)
293+
return
294+
295+
try:
296+
with OverrideCursor(Qt.CursorShape.WaitCursor):
297+
QApplication.processEvents()
298+
299+
if self.__current_module.versions == list():
300+
self.__version_loader.start_load_versions()
301+
302+
for module_package in self.__current_module.versions:
303+
self.module_package_comboBox.addItem(
304+
module_package.display_name(), module_package
305+
)
306+
307+
if self.__current_module.latest_version is not None:
308+
self.module_latestVersion_label.setText(
309+
f"Latest: {self.__current_module.latest_version.name}"
310+
)
311+
312+
except Exception as exception:
313+
self.module_progressBar.setVisible(False)
314+
error_message = str(exception)
315+
if "rate limit exceeded for url" in error_message.lower():
316+
CriticalMessageBox(
317+
self.tr("GitHub API Rate Limit Exceeded"),
318+
self.tr(
319+
"Oqtopus needs to download release data from GitHub to work properly.<br><br>"
320+
"GitHub limits the number of requests that can be made without authentication. "
321+
"You have reached the maximum number of requests allowed for unauthenticated users.<br><br>"
322+
"To continue using this feature, please create a free GitHub personal access token and enter it in the Settings dialog.<br><br>"
323+
"This will increase your request limit.<br><br>"
324+
"<b>How to get a token:</b><br>"
325+
"1. Go to <a href='https://github.com/settings/tokens'>GitHub Personal Access Tokens</a>.<br>"
326+
"2. Click <b>Generate new token</b> and select the <code>repo</code> scope.<br>"
327+
"3. Copy the generated token and paste it in the Settings dialog of this application."
328+
),
329+
exception,
330+
self,
331+
).exec()
332+
else:
333+
CriticalMessageBox(
334+
self.tr("Error"), self.tr("Can't load module versions:"), exception, self
335+
).exec()
336+
return
337+
338+
self.module_package_comboBox.insertSeparator(self.module_package_comboBox.count())
339+
self.module_package_comboBox.addItem(
340+
self.tr("Load from ZIP file"),
341+
ModulePackage(
342+
module=self.__current_module,
343+
organisation=self.__current_module.organisation,
344+
repository=self.__current_module.repository,
345+
json_payload=None,
346+
type=ModulePackage.Type.FROM_ZIP,
347+
),
348+
)
349+
350+
self.module_package_comboBox.insertSeparator(self.module_package_comboBox.count())
351+
self.module_package_comboBox.addItem(
352+
self.tr("Load development branches"), self.module_package_SPECIAL_LOAD_DEVELOPMENT
353+
)
354+
355+
self.module_progressBar.setVisible(False)
356+
logger.info(f"Versions loaded for module '{self.__current_module.name}'.")

oqtopus/gui/module_widget.py

Lines changed: 47 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,11 @@ def __init__(self, parent=None):
3535
def setModulePackage(self, module_package: Module):
3636
self.__current_module_package = module_package
3737
self.__packagePrepareGetPUMConfig()
38+
self.__updateModuleInfo()
3839

3940
def setDatabaseConnection(self, connection: psycopg.Connection):
4041
self.__database_connection = connection
42+
self.__updateModuleInfo()
4143

4244
def __packagePrepareGetPUMConfig(self):
4345
package_dir = self.__current_module_package.package_dir
@@ -85,28 +87,6 @@ def __packagePrepareGetPUMConfig(self):
8587
for demo_data_name, demo_data_file in self.__pum_config.demo_data().items():
8688
self.db_demoData_comboBox.addItem(demo_data_name, demo_data_file)
8789

88-
sm = SchemaMigrations(self.__pum_config)
89-
migrationVersion = "0.0.0"
90-
if not self.__database_connection:
91-
self.moduleInfo_label.setText(self.tr("No database connection available"))
92-
QtUtils.setForegroundColor(self.moduleInfo_label, PluginUtils.COLOR_WARNING)
93-
elif sm.exists(self.__database_connection):
94-
baseline_version = sm.baseline(self.__database_connection)
95-
self.moduleInfo_label.setText(self.tr(f"Version {baseline_version} found"))
96-
QtUtils.resetForegroundColor(self.moduleInfo_label)
97-
self.moduleInfo_upgrade_pushButton.setText(self.tr(f"Upgrade to {migrationVersion}"))
98-
99-
self.moduleInfo_stackedWidget.setCurrentWidget(
100-
self.moduleInfo_stackedWidget_pageUpgrade
101-
)
102-
else:
103-
self.moduleInfo_label.setText(self.tr("No module found"))
104-
QtUtils.resetForegroundColor(self.moduleInfo_label)
105-
self.moduleInfo_install_pushButton.setText(self.tr(f"Install {migrationVersion}"))
106-
self.moduleInfo_stackedWidget.setCurrentWidget(
107-
self.moduleInfo_stackedWidget_pageInstall
108-
)
109-
11090
def __installModuleClicked(self):
11191

11292
if self.__current_module_package is None:
@@ -165,10 +145,55 @@ def __installModuleClicked(self):
165145
f"Module '{self.__current_module_package.module.name}' version '{self.__current_module_package.name}' has been successfully installed."
166146
)
167147

148+
self.__updateModuleInfo()
149+
168150
def __upgradeModuleClicked(self):
169151
QMessageBox.critical(
170152
self,
171153
self.tr("Not implemented"),
172154
self.tr("Upgrade module is not implemented yet."),
173155
)
174156
return
157+
158+
def __updateModuleInfo(self):
159+
if self.__current_module_package is None:
160+
self.moduleInfo_label.setText(self.tr("No module package selected"))
161+
QtUtils.setForegroundColor(self.moduleInfo_label, PluginUtils.COLOR_WARNING)
162+
return
163+
164+
if self.__database_connection is None:
165+
self.moduleInfo_label.setText(self.tr("No database connection available"))
166+
QtUtils.setForegroundColor(self.moduleInfo_label, PluginUtils.COLOR_WARNING)
167+
return
168+
169+
if self.__pum_config is None:
170+
self.moduleInfo_label.setText(self.tr("No PUM config available"))
171+
QtUtils.setForegroundColor(self.moduleInfo_label, PluginUtils.COLOR_WARNING)
172+
return
173+
174+
migrationVersion = self.__pum_config.last_version()
175+
sm = SchemaMigrations(self.__pum_config)
176+
177+
if sm.exists(self.__database_connection):
178+
# Case upgrade
179+
baseline_version = sm.baseline(self.__database_connection)
180+
self.moduleInfo_label.setText(self.tr(f"Version {baseline_version} found"))
181+
QtUtils.resetForegroundColor(self.moduleInfo_label)
182+
self.moduleInfo_upgrade_pushButton.setText(self.tr(f"Upgrade to {migrationVersion}"))
183+
184+
self.moduleInfo_stackedWidget.setCurrentWidget(
185+
self.moduleInfo_stackedWidget_pageUpgrade
186+
)
187+
188+
logger.info(
189+
f"Migration table details: {sm.migration_details(self.__database_connection)}"
190+
)
191+
192+
else:
193+
# Case install
194+
self.moduleInfo_label.setText(self.tr("No module found"))
195+
QtUtils.resetForegroundColor(self.moduleInfo_label)
196+
self.moduleInfo_install_pushButton.setText(self.tr(f"Install {migrationVersion}"))
197+
self.moduleInfo_stackedWidget.setCurrentWidget(
198+
self.moduleInfo_stackedWidget_pageInstall
199+
)

0 commit comments

Comments
 (0)