diff --git a/qubesmanager/backup.py b/qubesmanager/backup.py
index 0335648..9be8354 100644
--- a/qubesmanager/backup.py
+++ b/qubesmanager/backup.py
@@ -20,18 +20,14 @@
#
#
-import traceback
-
import signal
-import quamash
-
-from qubesadmin import Qubes, exc
+from qubesadmin import exc
from qubesadmin import utils as admin_utils
-from qubesadmin import events
from qubes.storage.file import get_disk_usage
from PyQt5 import QtCore # pylint: disable=import-error
from PyQt5 import QtWidgets # pylint: disable=import-error
+from PyQt5 import QtGui
from . import ui_backupdlg # pylint: disable=no-name-in-module
from . import multiselectwidget
@@ -393,57 +389,10 @@ class BackupVMsWindow(ui_backupdlg.Ui_Backup, QtWidgets.QWizard):
self.select_dir_page.completeChanged.emit()
-# Bases on the original code by:
-# Copyright (c) 2002-2007 Pascal Varet
-
-def handle_exception(exc_type, exc_value, exc_traceback):
- filename, line, dummy, dummy = traceback.extract_tb(exc_traceback).pop()
- filename = os.path.basename(filename)
- error = "%s: %s" % (exc_type.__name__, exc_value)
-
- QtWidgets.QMessageBox.critical(
- None,
- "Houston, we have a problem...",
- "Whoops. A critical error has occured. This is most likely a bug "
- "in Qubes Global Settings application.
%s" %
- error + "at line %d of file %s.
"
- % (line, filename))
-
-
-def loop_shutdown():
- pending = asyncio.Task.all_tasks()
- for task in pending:
- with suppress(asyncio.CancelledError):
- task.cancel()
-
-
def main():
- qt_app = QtWidgets.QApplication(sys.argv)
- qt_app.setOrganizationName("The Qubes Project")
- qt_app.setOrganizationDomain("http://qubes-os.org")
- qt_app.setApplicationName("Qubes Backup VMs")
- qt_app.lastWindowClosed.connect(loop_shutdown)
-
- sys.excepthook = handle_exception
-
- qubes_app = Qubes()
-
- loop = quamash.QEventLoop(qt_app)
- asyncio.set_event_loop(loop)
- dispatcher = events.EventsDispatcher(qubes_app)
-
- backup_window = BackupVMsWindow(qt_app, qubes_app, dispatcher)
- backup_window.show()
-
- try:
- loop.run_until_complete(
- asyncio.ensure_future(dispatcher.listen_for_events()))
- except asyncio.CancelledError:
- pass
- except Exception: # pylint: disable=broad-except
- loop_shutdown()
- exc_type, exc_value, exc_traceback = sys.exc_info()[:3]
- handle_exception(exc_type, exc_value, exc_traceback)
+ utils.run_asynchronous("Qubes Backup VMs",
+ QtGui.QIcon.fromTheme("qubes-manager"),
+ BackupVMsWindow)
if __name__ == "__main__":
diff --git a/qubesmanager/bootfromdevice.py b/qubesmanager/bootfromdevice.py
index e106dbe..24f9370 100644
--- a/qubesmanager/bootfromdevice.py
+++ b/qubesmanager/bootfromdevice.py
@@ -17,7 +17,7 @@
#
#
-import sys
+import functools
import subprocess
from . import utils
from . import ui_bootfromdevice # pylint: disable=no-name-in-module
@@ -28,7 +28,7 @@ from qubesadmin.tools import qvm_start
class VMBootFromDeviceWindow(ui_bootfromdevice.Ui_BootDialog,
QtWidgets.QDialog):
- def __init__(self, vm, qapp, parent=None):
+ def __init__(self, vm, qapp, qubesapp=None, parent=None):
super(VMBootFromDeviceWindow, self).__init__(parent)
self.vm = vm
@@ -147,19 +147,8 @@ def main(args=None):
args = parser.parse_args(args)
vm = args.domains.pop()
- qapp = QtWidgets.QApplication(sys.argv)
- qapp.setOrganizationName('Invisible Things Lab')
- qapp.setOrganizationDomain("https://www.qubes-os.org/")
- qapp.setApplicationName("Boot Qube From Device")
-
-# if not utils.is_debug(): #FIXME
-# sys.excepthook = handle_exception
-
- bootfromdevice_window = VMBootFromDeviceWindow(vm, qapp)
- bootfromdevice_window.show()
-
- qapp.exec_()
- qapp.exit()
+ utils.run_synchronous("Boot Qube From Device",
+ functools.partial(VMBootFromDeviceWindow, vm))
if __name__ == "__main__":
diff --git a/qubesmanager/global_settings.py b/qubesmanager/global_settings.py
index a1ec87f..1b2d027 100644
--- a/qubesmanager/global_settings.py
+++ b/qubesmanager/global_settings.py
@@ -20,14 +20,11 @@
#
#
-import sys
import os
import os.path
-import traceback
import subprocess
from PyQt5 import QtWidgets # pylint: disable=import-error
-from qubesadmin import Qubes
from qubesadmin.utils import parse_size
from . import ui_globalsettingsdlg # pylint: disable=no-name-in-module
@@ -406,39 +403,9 @@ class GlobalSettingsWindow(ui_globalsettingsdlg.Ui_GlobalSettings,
self.__apply_updates__()
self.__apply_repos__()
-# Bases on the original code by:
-# Copyright (c) 2002-2007 Pascal Varet
-
-def handle_exception(exc_type, exc_value, exc_traceback):
- filename, line, dummy, dummy = traceback.extract_tb(exc_traceback).pop()
- filename = os.path.basename(filename)
- error = "%s: %s" % (exc_type.__name__, exc_value)
-
- QtWidgets.QMessageBox.critical(
- None,
- "Houston, we have a problem...",
- "Whoops. A critical error has occured. This is most likely a bug "
- "in Qubes Global Settings application.
%s" %
- error + "at line %d of file %s.
"
- % (line, filename))
-
def main():
- qtapp = QtWidgets.QApplication(sys.argv)
- qtapp.setOrganizationName("The Qubes Project")
- qtapp.setOrganizationDomain("http://qubes-os.org")
- qtapp.setApplicationName("Qubes Global Settings")
-
- sys.excepthook = handle_exception
-
- app = Qubes()
-
- global_window = GlobalSettingsWindow(qtapp, app)
-
- global_window.show()
-
- qtapp.exec_()
- qtapp.exit()
+ utils.run_synchronous("Qubes Global Settings", GlobalSettingsWindow)
if __name__ == "__main__":
diff --git a/qubesmanager/qube_manager.py b/qubesmanager/qube_manager.py
index 4dd6b15..ccb1098 100644
--- a/qubesmanager/qube_manager.py
+++ b/qubesmanager/qube_manager.py
@@ -21,21 +21,13 @@
# with this program; if not, see .
#
#
-import sys
import os
import os.path
import subprocess
from datetime import datetime, timedelta
-import traceback
-from contextlib import suppress
-import quamash
-import asyncio
-
-from qubesadmin import Qubes
from qubesadmin import exc
from qubesadmin import utils
-from qubesadmin import events
from PyQt5 import QtWidgets, QtCore, QtGui # pylint: disable=import-error
@@ -1306,71 +1298,11 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtWidgets.QMainWindow):
log_dlg.exec_()
-# Bases on the original code by:
-# Copyright (c) 2002-2007 Pascal Varet
-
-def handle_exception(exc_type, exc_value, exc_traceback):
-
- filename, line, dummy, dummy = traceback.extract_tb(exc_traceback).pop()
- filename = os.path.basename(filename)
- error = "%s: %s" % (exc_type.__name__, exc_value)
-
- strace = ""
- stacktrace = traceback.extract_tb(exc_traceback)
- while stacktrace:
- (filename, line, func, txt) = stacktrace.pop()
- strace += "----\n"
- strace += "line: %s\n" % txt
- strace += "func: %s\n" % func
- strace += "line no.: %d\n" % line
- strace += "file: %s\n" % filename
-
- msg_box = QtWidgets.QMessageBox()
- msg_box.setDetailedText(strace)
- msg_box.setIcon(QtWidgets.QMessageBox.Critical)
- msg_box.setWindowTitle("Houston, we have a problem...")
- msg_box.setText("Whoops. A critical error has occured. "
- "This is most likely a bug in Qubes Manager.
"
- "%s" % error +
- "
at line %d
of file %s.
"
- % (line, filename))
-
- msg_box.exec_()
-
-
-def loop_shutdown():
- pending = asyncio.Task.all_tasks()
- for task in pending:
- with suppress(asyncio.CancelledError):
- task.cancel()
-
-
def main():
- qt_app = QtWidgets.QApplication(sys.argv)
- qt_app.setOrganizationName("The Qubes Project")
- qt_app.setOrganizationDomain("http://qubes-os.org")
- qt_app.setApplicationName("Qube Manager")
- qt_app.setWindowIcon(QtGui.QIcon.fromTheme("qubes-manager"))
- qt_app.lastWindowClosed.connect(loop_shutdown)
-
- qubes_app = Qubes()
-
- loop = quamash.QEventLoop(qt_app)
- asyncio.set_event_loop(loop)
- dispatcher = events.EventsDispatcher(qubes_app)
-
- manager_window = VmManagerWindow(qt_app, qubes_app, dispatcher)
- manager_window.show()
-
- try:
- loop.run_until_complete(
- asyncio.ensure_future(dispatcher.listen_for_events()))
- except asyncio.CancelledError:
- pass
- except Exception: # pylint: disable=broad-except
- loop_shutdown()
- exc_type, exc_value, exc_traceback = sys.exc_info()[:3]
- handle_exception(exc_type, exc_value, exc_traceback)
+ manager_utils.run_asynchronous(
+ "Qube Manager",
+ QtGui.QIcon.fromTheme("qubes-manager"),
+ VmManagerWindow)
if __name__ == "__main__":
diff --git a/qubesmanager/restore.py b/qubesmanager/restore.py
index a38f46f..48f7531 100644
--- a/qubesmanager/restore.py
+++ b/qubesmanager/restore.py
@@ -20,11 +20,9 @@
#
#
-import sys
from PyQt5 import QtCore, QtWidgets # pylint: disable=import-error
import os
import os.path
-import traceback
import logging
import logging.handlers
@@ -33,6 +31,7 @@ from qubes import backup
from . import ui_restoredlg # pylint: disable=no-name-in-module
from . import multiselectwidget
from . import backup_utils
+from . import utils
from multiprocessing import Queue
from queue import Empty
@@ -292,39 +291,8 @@ class RestoreVMsWindow(ui_restoredlg.Ui_Restore, QtWidgets.QWizard):
self.select_dir_page.completeChanged.emit()
-# Bases on the original code by:
-# Copyright (c) 2002-2007 Pascal Varet
-
-def handle_exception(exc_type, exc_value, exc_traceback):
-
- filename, line, dummy, dummy = traceback.extract_tb(exc_traceback).pop()
- filename = os.path.basename(filename)
- error = "%s: %s" % (exc_type.__name__, exc_value)
-
- QtWidgets.QMessageBox.critical(
- None, "Houston, we have a problem...",
- "Whoops. A critical error has occured. This is most likely a bug "
- "in Qubes Restore VMs application.
%s" % error +
- "at line %d of file %s.
" % (line, filename))
-
-
def main():
-
- qt_app = QtWidgets.QApplication(sys.argv)
- qt_app.setOrganizationName("The Qubes Project")
- qt_app.setOrganizationDomain("http://qubes-os.org")
- qt_app.setApplicationName("Qubes Restore VMs")
-
- sys.excepthook = handle_exception
-
- qubes_app = Qubes()
-
- restore_window = RestoreVMsWindow(qt_app, qubes_app)
-
- restore_window.show()
-
- qt_app.exec_()
- qt_app.exit()
+ utils.run_synchronous("Qubes Restore VMs", RestoreVMsWindow)
if __name__ == "__main__":
diff --git a/qubesmanager/settings.py b/qubesmanager/settings.py
index 256845f..7bcfd5e 100644
--- a/qubesmanager/settings.py
+++ b/qubesmanager/settings.py
@@ -23,12 +23,10 @@
#
import collections
-import os.path
-import os
+import functools
import re
import subprocess
import traceback
-import sys
from qubesadmin.tools import QubesArgumentParser
from qubesadmin import devices
from qubesadmin import utils as admin_utils
@@ -128,11 +126,13 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtWidgets.QDialog):
('services', 5),
))
- def __init__(self, vm, qapp, init_page="basic", parent=None):
+ def __init__(self, vm, init_page="basic", qapp=None, qubesapp=None,
+ parent=None):
super(VMSettingsWindow, self).__init__(parent)
self.vm = vm
self.qapp = qapp
+ self.qubesapp = qubesapp
self.threads_list = []
self.progress = None
self.thread_closes = False
@@ -1218,38 +1218,6 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtWidgets.QDialog):
self.fw_model.remove_child(i)
-# Bases on the original code by:
-# Copyright (c) 2002-2007 Pascal Varet
-
-def handle_exception(exc_type, exc_value, exc_traceback):
-
- filename, line, dummy, dummy = traceback.extract_tb(exc_traceback).pop()
- filename = os.path.basename(filename)
- error = "%s: %s" % (exc_type.__name__, exc_value)
-
- strace = ""
- stacktrace = traceback.extract_tb(exc_traceback)
- while stacktrace:
- (filename, line, func, txt) = stacktrace.pop()
- strace += "----\n"
- strace += "line: %s\n" % txt
- strace += "func: %s\n" % func
- strace += "line no.: %d\n" % line
- strace += "file: %s\n" % filename
-
- msg_box = QtWidgets.QMessageBox()
- msg_box.setDetailedText(strace)
- msg_box.setIcon(QtWidgets.QMessageBox.Critical)
- msg_box.setWindowTitle("Houston, we have a problem...")
- msg_box.setText("Whoops. A critical error has occured. "
- "This is most likely a bug in Qubes Manager.
"
- "%s" % error +
- "
at line %d
of file %s.
"
- % (line, filename))
-
- msg_box.exec_()
-
-
parser = QubesArgumentParser(vmname_nargs=1)
parser.add_argument('--tab', metavar='TAB',
@@ -1265,19 +1233,8 @@ def main(args=None):
args = parser.parse_args(args)
vm = args.domains.pop()
- qapp = QtWidgets.QApplication(sys.argv)
- qapp.setOrganizationName('Invisible Things Lab')
- qapp.setOrganizationDomain("https://www.qubes-os.org/")
- qapp.setApplicationName("Qube Settings")
-
- if not utils.is_debug():
- sys.excepthook = handle_exception
-
- settings_window = VMSettingsWindow(vm, qapp, args.tab)
- settings_window.show()
-
- qapp.exec_()
- qapp.exit()
+ utils.run_synchronous("Qube Settings",
+ functools.partial(VMSettingsWindow, vm, args.tab))
if __name__ == "__main__":
diff --git a/qubesmanager/template_manager.py b/qubesmanager/template_manager.py
index 31ff0a9..cc85837 100644
--- a/qubesmanager/template_manager.py
+++ b/qubesmanager/template_manager.py
@@ -20,21 +20,12 @@
#
#
-import sys
-import os
-import os.path
-import traceback
-import quamash
-import asyncio
-from contextlib import suppress
-
-from qubesadmin import Qubes
from qubesadmin import exc
-from qubesadmin import events
from PyQt5 import QtWidgets, QtGui, QtCore # pylint: disable=import-error
from . import ui_templatemanager # pylint: disable=no-name-in-module
+from . import utils
column_names = ['State', 'Qube', 'Current template', 'New template']
@@ -385,72 +376,11 @@ class VMRow:
row, column_names.index('State'))
self.checkbox = None
-# Bases on the original code by:
-# Copyright (c) 2002-2007 Pascal Varet
-
-
-def handle_exception(exc_type, exc_value, exc_traceback):
-
- filename, line, dummy, dummy = traceback.extract_tb(exc_traceback).pop()
- filename = os.path.basename(filename)
- error = "%s: %s" % (exc_type.__name__, exc_value)
-
- strace = ""
- stacktrace = traceback.extract_tb(exc_traceback)
- while stacktrace:
- (filename, line, func, txt) = stacktrace.pop()
- strace += "----\n"
- strace += "line: %s\n" % txt
- strace += "func: %s\n" % func
- strace += "line no.: %d\n" % line
- strace += "file: %s\n" % filename
-
- msg_box = QtWidgets.QMessageBox()
- msg_box.setDetailedText(strace)
- msg_box.setIcon(QtWidgets.QMessageBox.Critical)
- msg_box.setWindowTitle("Houston, we have a problem...")
- msg_box.setText("Whoops. A critical error has occured. "
- "This is most likely a bug in Qubes Manager.
"
- "%s" % error +
- "
at line %d
of file %s.
"
- % (line, filename))
-
- msg_box.exec_()
-
-
-def loop_shutdown():
- pending = asyncio.Task.all_tasks()
- for task in pending:
- with suppress(asyncio.CancelledError):
- task.cancel()
-
def main():
- qt_app = QtWidgets.QApplication(sys.argv)
- qt_app.setOrganizationName("The Qubes Project")
- qt_app.setOrganizationDomain("http://qubes-os.org")
- qt_app.setApplicationName("Qube Manager")
- qt_app.setWindowIcon(QtGui.QIcon.fromTheme("qubes-manager"))
- qt_app.lastWindowClosed.connect(loop_shutdown)
-
- qubes_app = Qubes()
-
- loop = quamash.QEventLoop(qt_app)
- asyncio.set_event_loop(loop)
- dispatcher = events.EventsDispatcher(qubes_app)
-
- manager_window = TemplateManagerWindow(qt_app, qubes_app, dispatcher)
- manager_window.show()
-
- try:
- loop.run_until_complete(
- asyncio.ensure_future(dispatcher.listen_for_events()))
- except asyncio.CancelledError:
- pass
- except Exception: # pylint: disable=broad-except
- loop_shutdown()
- exc_type, exc_value, exc_traceback = sys.exc_info()[:3]
- handle_exception(exc_type, exc_value, exc_traceback)
+ utils.run_asynchronous("Template Manager",
+ QtGui.QIcon.fromTheme("qubes-manager"),
+ TemplateManagerWindow)
if __name__ == "__main__":
diff --git a/qubesmanager/utils.py b/qubesmanager/utils.py
index 2edeb3b..5b12256 100644
--- a/qubesmanager/utils.py
+++ b/qubesmanager/utils.py
@@ -23,7 +23,14 @@ import itertools
import os
import re
import qubesadmin
+import traceback
+import asyncio
+from contextlib import suppress
+import sys
+import quamash
+from qubesadmin import events
+from PyQt5 import QtWidgets
from PyQt5.QtGui import QIcon # pylint: disable=import-error
@@ -215,3 +222,87 @@ def format_dependencies_list(dependencies):
prop, holder.name)
return list_text
+
+
+def loop_shutdown():
+ pending = asyncio.Task.all_tasks()
+ for task in pending:
+ with suppress(asyncio.CancelledError):
+ task.cancel()
+
+
+# Bases on the original code by:
+# Copyright (c) 2002-2007 Pascal Varet
+def handle_exception(exc_type, exc_value, exc_traceback):
+
+ filename, line, dummy, dummy = traceback.extract_tb(exc_traceback).pop()
+ filename = os.path.basename(filename)
+ error = "%s: %s" % (exc_type.__name__, exc_value)
+
+ strace = ""
+ stacktrace = traceback.extract_tb(exc_traceback)
+ while stacktrace:
+ (filename, line, func, txt) = stacktrace.pop()
+ strace += "----\n"
+ strace += "line: %s\n" % txt
+ strace += "func: %s\n" % func
+ strace += "line no.: %d\n" % line
+ strace += "file: %s\n" % filename
+
+ msg_box = QtWidgets.QMessageBox()
+ msg_box.setDetailedText(strace)
+ msg_box.setIcon(QtWidgets.QMessageBox.Critical)
+ msg_box.setWindowTitle("Houston, we have a problem...")
+ msg_box.setText("Whoops. A critical error has occured. "
+ "This is most likely a bug in Qubes Manager.
"
+ "%s" % error +
+ "
at line %d
of file %s.
"
+ % (line, filename))
+
+ msg_box.exec_()
+
+
+def run_asynchronous(app_name, icon, window_class):
+ qt_app = QtWidgets.QApplication(sys.argv)
+ qt_app.setOrganizationName("The Qubes Project")
+ qt_app.setOrganizationDomain("http://qubes-os.org")
+ qt_app.setApplicationName(app_name)
+ qt_app.setWindowIcon(icon)
+ qt_app.lastWindowClosed.connect(loop_shutdown)
+
+ qubes_app = qubesadmin.Qubes()
+
+ loop = quamash.QEventLoop(qt_app)
+ asyncio.set_event_loop(loop)
+ dispatcher = events.EventsDispatcher(qubes_app)
+
+ window = window_class(qt_app, qubes_app, dispatcher)
+ window.show()
+
+ try:
+ loop.run_until_complete(
+ asyncio.ensure_future(dispatcher.listen_for_events()))
+ except asyncio.CancelledError:
+ pass
+ except Exception: # pylint: disable=broad-except
+ loop_shutdown()
+ exc_type, exc_value, exc_traceback = sys.exc_info()[:3]
+ handle_exception(exc_type, exc_value, exc_traceback)
+
+
+def run_synchronous(app_name, window_class):
+ qt_app = QtWidgets.QApplication(sys.argv)
+ qt_app.setOrganizationName("The Qubes Project")
+ qt_app.setOrganizationDomain("http://qubes-os.org")
+ qt_app.setApplicationName(app_name)
+
+ sys.excepthook = handle_exception
+
+ qubes_app = qubesadmin.Qubes()
+
+ window = window_class(qt_app, qubes_app)
+
+ window.show()
+
+ qt_app.exec_()
+ qt_app.exit()