Add more error handling
offlate/ui/editor.py
| 181 | 181 | ||
| 182 | 182 | worker = [] | |
| 183 | 183 | for f in files: | |
| 184 | - | worker.append(ExternalRunnable(f)) | |
| 184 | + | worker.append(ExternalRunnable(self, f)) | |
| 185 | 185 | ||
| 186 | - | worker2 = WatchRunnable(self.project, len(worker)) | |
| 186 | + | worker2 = WatchRunnable(self, self.project, len(worker)) | |
| 187 | 187 | worker2.signals.finished.connect(self.editedExternals) | |
| 188 | 188 | worker2.signals.progress.connect(self.intermediateReloadContent) | |
| 189 | 189 | for i in range(0, len(worker)): | |
… | |||
| 446 | 446 | self.setLabels(self.tr("Uploading {}...").format(self.tabs.currentWidget().project.name)) | |
| 447 | 447 | worker = UploadRunnable(self.tabs.currentWidget()) | |
| 448 | 448 | worker.signals.finished.connect(self.sent) | |
| 449 | + | worker.signals.error.connect(self.reportError) | |
| 449 | 450 | self.threadpool.start(worker) | |
| 450 | 451 | ||
| 451 | 452 | def sent(self, name): | |
… | |||
| 457 | 458 | worker = UpdateRunnable(self.tabs.currentWidget()) | |
| 458 | 459 | worker.signals.finished.connect(self.updated) | |
| 459 | 460 | worker.signals.progress.connect(self.reportProgress) | |
| 461 | + | worker.signals.error.connect(self.reportError) | |
| 460 | 462 | self.threadpool.start(worker) | |
| 461 | 463 | ||
| 462 | 464 | def updated(self, name): | |
… | |||
| 468 | 470 | def reportProgress(self, name, progress): | |
| 469 | 471 | self.setProgresses(progress) | |
| 470 | 472 | ||
| 473 | + | def reportError(self, name, error): | |
| 474 | + | dialog = QMessageBox() | |
| 475 | + | dialog.setText(error) | |
| 476 | + | dialog.exec_() | |
| 477 | + | ||
| 471 | 478 | def setLabels(self, value): | |
| 472 | 479 | self.actionLabel.setText(value) | |
| 473 | 480 | self.projectManagerWindow.projectManagerWidget.actionLabel.setText(value) | |
… | |||
| 614 | 621 | self.setGeometry(0, 0, 800, 600) | |
| 615 | 622 | self.setWindowTitle('Offlate') | |
| 616 | 623 | ||
| 617 | - | class UploadRunnable(QRunnable, RunnableCallback): | |
| 618 | - | def __init__(self, widget): | |
| 624 | + | class UploadRunnable(RunnableCallback): | |
| 625 | + | def __init__(self, parent, widget): | |
| 619 | 626 | super().__init__() | |
| 620 | 627 | self.widget = widget | |
| 628 | + | self.parent = widget | |
| 621 | 629 | self.signals = RunnableSignals() | |
| 622 | 630 | self.oldamount = -1 | |
| 623 | 631 | self.error = None | |
| 624 | 632 | self.name = self.widget.project.name | |
| 625 | 633 | ||
| 626 | - | def run(self): | |
| 634 | + | def do_run(self): | |
| 627 | 635 | self.widget.send() | |
| 636 | + | ||
| 637 | + | def do_finish(self): | |
| 628 | 638 | self.signals.finished.emit(self.name) | |
| 629 | 639 | ||
| 630 | - | class UpdateRunnable(QRunnable, RunnableCallback): | |
| 640 | + | class UpdateRunnable(RunnableCallback): | |
| 631 | 641 | def __init__(self, widget): | |
| 632 | 642 | super().__init__() | |
| 633 | 643 | self.widget = widget | |
| 644 | + | self.parent = widget | |
| 634 | 645 | self.signals = RunnableSignals() | |
| 635 | 646 | self.oldamount = -1 | |
| 636 | 647 | self.error = None | |
| 637 | 648 | self.name = self.widget.project.name | |
| 638 | 649 | ||
| 639 | - | def run(self): | |
| 650 | + | def do_run(self): | |
| 640 | 651 | self.widget.update(Interface()) | |
| 652 | + | ||
| 653 | + | def do_finish(self): | |
| 641 | 654 | self.signals.finished.emit(self.name) | |
| 642 | 655 | ||
| 643 | - | class ExternalRunnable(QRunnable, RunnableCallback): | |
| 644 | - | def __init__(self, mfile): | |
| 656 | + | class ExternalRunnable(RunnableCallback): | |
| 657 | + | def __init__(self, parent, mfile): | |
| 645 | 658 | super().__init__() | |
| 646 | 659 | self.mfile = mfile | |
| 660 | + | self.parent = parent | |
| 647 | 661 | self.signals = RunnableSignals() | |
| 648 | 662 | self.oldamount = -1 | |
| 649 | 663 | self.error = None | |
| 650 | 664 | self.name = "" | |
| 651 | 665 | ||
| 652 | - | def run(self): | |
| 653 | - | # Try to open file with the default application | |
| 654 | - | try: | |
| 655 | - | if platform.system() == 'Darwin': | |
| 656 | - | subprocess.run(['open', self.mfile]) | |
| 657 | - | elif platform.system() == 'Windows': | |
| 658 | - | subprocess.run(['start', self.mfile]) | |
| 659 | - | else: | |
| 660 | - | subprocess.run(['xdg-open', self.mfile]) | |
| 661 | - | except: | |
| 662 | - | print(sys.exc_info()) | |
| 663 | - | pass | |
| 666 | + | def do_run(self): | |
| 667 | + | if platform.system() == 'Darwin': | |
| 668 | + | subprocess.run(['open', self.mfile]) | |
| 669 | + | elif platform.system() == 'Windows': | |
| 670 | + | subprocess.run(['start', self.mfile]) | |
| 671 | + | else: | |
| 672 | + | subprocess.run(['xdg-open', self.mfile]) | |
| 673 | + | ||
| 674 | + | def do_finish(self): | |
| 664 | 675 | self.signals.finished.emit("") | |
| 665 | 676 | ||
| 666 | 677 | class MyHandler(FileSystemEventHandler): | |
… | |||
| 671 | 682 | def on_modified(self, event): | |
| 672 | 683 | self.parent.signals.progress.emit("", 0) | |
| 673 | 684 | ||
| 674 | - | class WatchRunnable(QRunnable, RunnableCallback): | |
| 675 | - | def __init__(self, project, size): | |
| 685 | + | class WatchRunnable(RunnableCallback): | |
| 686 | + | def __init__(self, parent, project, size): | |
| 676 | 687 | super().__init__() | |
| 688 | + | self.parent = parent | |
| 677 | 689 | self.project = project | |
| 678 | 690 | self.signals = RunnableSignals() | |
| 679 | 691 | self.oldamount = -1 | |
… | |||
| 689 | 701 | for f in files: | |
| 690 | 702 | self.observer.schedule(event_handler, str(Path(f).parent), recursive=True) | |
| 691 | 703 | ||
| 692 | - | def run(self): | |
| 704 | + | def do_run(self): | |
| 693 | 705 | self.observer.start() | |
| 694 | 706 | while self.size > 0: | |
| 695 | 707 | sleep(0.2) | |
| 696 | 708 | self.observer.stop() | |
| 697 | 709 | self.observer.join() | |
| 710 | + | ||
| 711 | + | def do_finish(self): | |
| 698 | 712 | self.signals.finished.emit("") | |
| 699 | 713 | ||
| 700 | 714 | def stop(self, name): | |
offlate/ui/manager.py
| 283 | 283 | worker.signals.finished.connect(self.finishReport) | |
| 284 | 284 | self.threadpool.start(worker) | |
| 285 | 285 | ||
| 286 | - | class NewRunnable(QRunnable, RunnableCallback): | |
| 286 | + | class NewRunnable(RunnableCallback): | |
| 287 | 287 | def __init__(self, parent, name, lang, system, info): | |
| 288 | 288 | super().__init__() | |
| 289 | 289 | self.name = name | |
… | |||
| 305 | 305 | self.info, self.error) | |
| 306 | 306 | self.parent.filter() | |
| 307 | 307 | ||
| 308 | - | class EditRunnable(QRunnable, RunnableCallback): | |
| 308 | + | class EditRunnable(RunnableCallback): | |
| 309 | 309 | def __init__(self, parent, name, lang, system, info): | |
| 310 | 310 | super().__init__() | |
| 311 | 311 | self.name = name | |
offlate/ui/parallel.py
| 15 | 15 | #### | |
| 16 | 16 | ||
| 17 | 17 | from PyQt5.QtCore import * | |
| 18 | + | from PyQt5.QtWidgets import * | |
| 19 | + | ||
| 18 | 20 | from ..formats.exception import UnsupportedFormatException | |
| 19 | 21 | from ..systems.exception import ProjectNotFoundSystemException | |
| 20 | 22 | from ..systems.callback import SystemCallback | |
| 21 | 23 | ||
| 22 | - | class RunnableCallback(SystemCallback): | |
| 24 | + | import sys | |
| 25 | + | ||
| 26 | + | class RunnableCallback(SystemCallback, QRunnable): | |
| 27 | + | def run(self): | |
| 28 | + | try: | |
| 29 | + | self.do_run() | |
| 30 | + | except: | |
| 31 | + | info = sys.exc_info() | |
| 32 | + | self.reportError(info[1], info[2]) | |
| 33 | + | self.do_finish() | |
| 34 | + | ||
| 23 | 35 | def reportProgress(self, amount): | |
| 24 | 36 | if int(round(amount)) > self.oldamount: | |
| 25 | 37 | self.oldamount = int(round(amount)) | |
| 26 | 38 | self.signals.progress.emit(self.name, amount) | |
| 27 | 39 | ||
| 40 | + | def reportError(self, error, trace): | |
| 41 | + | traceback = '' | |
| 42 | + | while trace is not None: | |
| 43 | + | traceback = traceback + str(trace.tb_frame) + "\n" | |
| 44 | + | trace = trace.tb_next | |
| 45 | + | ||
| 46 | + | self.error = self.parent.tr('This action did not complete correctly. \ | |
| 47 | + | We received the following error message: {}.\n\nTraceback:\n\n{}\nTry \ | |
| 48 | + | again?'.format(error, traceback)) | |
| 49 | + | self.signals.error.emit(self.name, self.error) | |
| 50 | + | ||
| 28 | 51 | def project_exists(self): | |
| 29 | 52 | self.error = self.parent.tr('A project with the same name already exists. \ | |
| 30 | 53 | The new project was not created. You should first remove the same-named project.') |