|
39 | 39 |
|
40 | 40 |
|
41 | 41 | class DCORAid(QtWidgets.QMainWindow): |
| 42 | + progress_update_event = QtCore.pyqtSignal() |
| 43 | + |
42 | 44 | def __init__(self, *args, **kwargs): |
43 | 45 | """Initialize DCOR-Aid |
44 | 46 |
|
@@ -71,6 +73,11 @@ def __init__(self, *args, **kwargs): |
71 | 73 | QtCore.QEventLoop.ProcessEventsFlag.AllEvents, 300) |
72 | 74 | sys.exit(0) |
73 | 75 |
|
| 76 | + # Progressbar for database updates |
| 77 | + self._prog_update_db = None |
| 78 | + self._dbup_thread = None |
| 79 | + self._dbup_worker = None |
| 80 | + |
74 | 81 | #: DCOR-Aid settings |
75 | 82 | self.settings = QtCore.QSettings() |
76 | 83 | ref_ui = resources.files("dcoraid.gui") / "main.ui" |
@@ -201,40 +208,35 @@ def check_update_database(self, reset=False, force=False): |
201 | 208 | QtWidgets.QMessageBox.StandardButton.Yes) |
202 | 209 | doit = button_reply == QtWidgets.QMessageBox.StandardButton.Yes |
203 | 210 | if doit: |
204 | | - abort_event = threading.Event() |
205 | | - prog = QtWidgets.QProgressDialog( |
206 | | - "Performing database update, please wait..." + " "*20, |
| 211 | + self._prog_update_db = QtWidgets.QProgressDialog( |
| 212 | + "Performing database update, please wait...\n" + " " * 200, |
207 | 213 | "Abort", |
208 | 214 | 0, |
209 | 215 | 0, |
210 | 216 | self |
211 | 217 | ) |
212 | | - prog.canceled.connect(abort_event.set) |
213 | | - prog.setMinimumDuration(0) |
214 | | - prog.setModal(True) |
215 | | - prog.show() |
216 | | - |
217 | | - def prog_update_callback(data): |
218 | | - cdict = data["circle_current"] |
219 | | - new_ds = data["datasets_new"] |
220 | | - title = cdict.get("title") |
221 | | - if not title: |
222 | | - title = cdict.get("name") |
223 | | - if len(title) > 50: |
224 | | - title = title[:50] + "..." |
225 | | - prog.setLabelText(f"Fetching '{title}'\n" |
226 | | - f"Imported {new_ds} datasets so far.") |
227 | | - |
228 | | - thr = threading.Thread(target=self.database.update, |
229 | | - args=(reset, abort_event, |
230 | | - prog_update_callback)) |
231 | | - thr.start() |
232 | | - |
233 | | - while thr.is_alive(): |
| 218 | + self._prog_update_db.setMinimumDuration(0) |
| 219 | + self._prog_update_db.show() |
| 220 | + |
| 221 | + # This is hell of a lot of boilerplate for just one progress bar. |
| 222 | + self._dbup_thread = QtCore.QThread() |
| 223 | + self._dbup_worker = UpdateDatabaseWorker( |
| 224 | + update=self.database.update, reset=reset) |
| 225 | + self._dbup_worker.moveToThread(self._dbup_thread) |
| 226 | + self._dbup_thread.started.connect(self._dbup_worker.run) |
| 227 | + self._dbup_worker.finished.connect(self._dbup_thread.quit) |
| 228 | + self._dbup_worker.finished.connect(self._dbup_worker.deleteLater) |
| 229 | + self._dbup_worker.progress.connect(self.on_progress_db_update) |
| 230 | + self._prog_update_db.canceled.connect(self._dbup_worker.cancelled) |
| 231 | + self._dbup_thread.start() |
| 232 | + |
| 233 | + while self._dbup_thread.isRunning(): |
234 | 234 | QtWidgets.QApplication.processEvents( |
235 | 235 | QtCore.QEventLoop.ProcessEventsFlag.AllEvents, 300) |
236 | 236 | QtTest.QTest.qWait(500) |
237 | 237 |
|
| 238 | + self._prog_update_db.deleteLater() |
| 239 | + |
238 | 240 | self._last_asked_about_update = time.time() |
239 | 241 |
|
240 | 242 | @QtCore.pyqtSlot(QtCore.QEvent) |
@@ -338,12 +340,54 @@ def on_action_software(self): |
338 | 340 | def on_dataset_changed(self, ds_dict): |
339 | 341 | self.database.update_dataset(ds_dict) |
340 | 342 |
|
| 343 | + @QtCore.pyqtSlot(dict) |
| 344 | + def on_progress_db_update(self, data): |
| 345 | + cdict = data["circle_current"] |
| 346 | + new_ds = data["datasets_new"] |
| 347 | + title = cdict.get("title") |
| 348 | + if not title: |
| 349 | + title = cdict.get("name") |
| 350 | + if len(title) > 50: |
| 351 | + title = title[:50] + "..." |
| 352 | + if self._prog_update_db is not None: |
| 353 | + self._prog_update_db.setLabelText( |
| 354 | + f"Fetching '{title}'\n" |
| 355 | + f"Imported {new_ds} datasets so far.") |
| 356 | + circle_ids = [c["id"] for c in data["circles"]] |
| 357 | + cur_index = circle_ids.index(cdict["id"]) |
| 358 | + self._prog_update_db.setMaximum(len(circle_ids)) |
| 359 | + self._prog_update_db.setValue(cur_index + 1) |
| 360 | + else: |
| 361 | + self.logger.error("Progress dialog not defined") |
| 362 | + |
341 | 363 | @QtCore.pyqtSlot() |
342 | 364 | def on_wizard(self): |
343 | 365 | self.wizard = SetupWizard(self) |
344 | 366 | self.wizard.exec() |
345 | 367 |
|
346 | 368 |
|
| 369 | +class UpdateDatabaseWorker(QtCore.QObject): |
| 370 | + finished = QtCore.pyqtSignal() |
| 371 | + progress = QtCore.pyqtSignal(dict) |
| 372 | + |
| 373 | + def __init__(self, update, reset, *args, **kwargs): |
| 374 | + self.update = update |
| 375 | + self.reset = reset |
| 376 | + self.abort_event = threading.Event() |
| 377 | + super(UpdateDatabaseWorker, self).__init__(*args, **kwargs) |
| 378 | + |
| 379 | + @QtCore.pyqtSlot() |
| 380 | + def cancelled(self): |
| 381 | + self.abort_event.set() |
| 382 | + |
| 383 | + def run(self): |
| 384 | + """Long-running task.""" |
| 385 | + self.update(reset=self.reset, |
| 386 | + abort_event=self.abort_event, |
| 387 | + callback=self.progress.emit) |
| 388 | + self.finished.emit() |
| 389 | + |
| 390 | + |
347 | 391 | def excepthook(etype, value, trace): |
348 | 392 | """ |
349 | 393 | Handler for all unhandled exceptions. |
|
0 commit comments