From 84011fb46d487bbfa12f2bd37b723de2a9118441 Mon Sep 17 00:00:00 2001 From: Jocelyn Le Sage Date: Tue, 20 Jun 2017 12:04:38 -0400 Subject: [PATCH] Handle OS termination signals. (#425) * Handle OS termination signals. * Added comment about why a timer is required to handle OS signals. --- qt/app.py | 6 ++++++ run.py | 27 +++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/qt/app.py b/qt/app.py index cc3077f8..65cc40f6 100644 --- a/qt/app.py +++ b/qt/app.py @@ -68,6 +68,8 @@ class DupeGuru(QObject): self.directories_dialog.show() self.model.load() + self.SIGTERM.connect(self.handleSIGTERM) + # The timer scheme is because if the nag is not shown before the application is # completely initialized, the nag will be shown before the app shows up in the task bar # In some circumstances, the nag is hidden by other window, which may make the user think @@ -166,6 +168,7 @@ class DupeGuru(QObject): #--- Signals willSavePrefs = pyqtSignal() + SIGTERM = pyqtSignal() #--- Events def finishedLaunching(self): @@ -216,6 +219,9 @@ class DupeGuru(QObject): url = QUrl('https://www.hardcoded.net/dupeguru/help/en/') QDesktopServices.openUrl(url) + def handleSIGTERM(self): + self.shutdown() + #--- model --> view def get_default(self, key): return self.prefs.get_value(key) diff --git a/run.py b/run.py index 4d80dcf2..6dfcf752 100644 --- a/run.py +++ b/run.py @@ -20,6 +20,23 @@ from qt import dg_rc from qt.platform import BASE_PATH from core import __version__, __appname__ +from signal import signal, SIGINT, SIGTERM, SIGQUIT + +global dgapp +dgapp = None + +def signalHandler(sig, frame): + global dgapp + if dgapp is None: + return + if sig in (SIGINT, SIGTERM, SIGQUIT): + dgapp.SIGTERM.emit() + +def setUpSignals(): + signal(SIGINT, signalHandler) + signal(SIGTERM, signalHandler) + signal(SIGQUIT, signalHandler) + def main(): app = QApplication(sys.argv) QCoreApplication.setOrganizationName('Hardcoded Software') @@ -30,10 +47,20 @@ def main(): lang = settings.value('Language') locale_folder = op.join(BASE_PATH, 'locale') install_gettext_trans_under_qt(locale_folder, lang) + # Handle OS signals + setUpSignals() + # Let the Python interpreter runs every 500ms to handle signals. This is + # required because Python cannot handle signals while the Qt event loop is + # running. + from PyQt5.QtCore import QTimer + timer = QTimer() + timer.start(500) + timer.timeout.connect(lambda: None) # Many strings are translated at import time, so this is why we only import after the translator # has been installed from qt.app import DupeGuru app.setWindowIcon(QIcon(QPixmap(":/{0}".format(DupeGuru.LOGO_NAME)))) + global dgapp dgapp = DupeGuru() install_excepthook('https://github.com/hsoft/dupeguru/issues') result = app.exec()