Merge remote-tracking branch 'origin/pr/200'

* origin/pr/200:
  Pylint fixes
  Code deduplication and cleanup
  Removed unused line in GUI Backup
This commit is contained in:
Marek Marczykowski-Górecki 2019-09-30 03:51:44 +02:00
commit fcec3d7464
No known key found for this signature in database
GPG Key ID: 063938BA42CFA724
10 changed files with 123 additions and 345 deletions

View File

@ -20,18 +20,12 @@
# #
# #
import traceback
import signal import signal
import quamash from qubesadmin import exc
from qubesadmin import Qubes, exc
from qubesadmin import utils as admin_utils from qubesadmin import utils as admin_utils
from qubesadmin import events
from qubes.storage.file import get_disk_usage from qubes.storage.file import get_disk_usage
from PyQt5 import QtCore # pylint: disable=import-error from PyQt5 import QtCore, QtWidgets, QtGui # pylint: disable=import-error
from PyQt5 import QtWidgets # pylint: disable=import-error
from . import ui_backupdlg # pylint: disable=no-name-in-module from . import ui_backupdlg # pylint: disable=no-name-in-module
from . import multiselectwidget from . import multiselectwidget
@ -40,10 +34,7 @@ from . import utils
import grp import grp
import pwd import pwd
import sys
import os import os
import asyncio
from contextlib import suppress
# pylint: disable=too-few-public-methods # pylint: disable=too-few-public-methods
@ -393,57 +384,10 @@ class BackupVMsWindow(ui_backupdlg.Ui_Backup, QtWidgets.QWizard):
self.select_dir_page.completeChanged.emit() self.select_dir_page.completeChanged.emit()
# Bases on the original code by:
# Copyright (c) 2002-2007 Pascal Varet <p.varet@gmail.com>
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.<br><br><b><i>%s</i></b>" %
error + "at <b>line %d</b> of file <b>%s</b>.<br/><br/>"
% (line, filename))
def loop_shutdown():
pending = asyncio.Task.all_tasks()
for task in pending:
with suppress(asyncio.CancelledError):
task.cancel()
def main(): def main():
qt_app = QtWidgets.QApplication(sys.argv) utils.run_asynchronous("Qubes Backup VMs",
qt_app.setOrganizationName("The Qubes Project") QtGui.QIcon.fromTheme("qubes-manager"),
qt_app.setOrganizationDomain("http://qubes-os.org") BackupVMsWindow)
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)
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -76,7 +76,6 @@ def select_path_button_clicked(dialog, select_file=False, read_only=False):
try: try:
if vm.name == socket.gethostname(): if vm.name == socket.gethostname():
file_dialog = QtWidgets.QFileDialog() file_dialog = QtWidgets.QFileDialog()
file_dialog.setReadOnly(True)
if select_file: if select_file:
file_dialog_function = file_dialog.getOpenFileName file_dialog_function = file_dialog.getOpenFileName

View File

@ -17,7 +17,7 @@
# #
# #
import sys import functools
import subprocess import subprocess
from . import utils from . import utils
from . import ui_bootfromdevice # pylint: disable=no-name-in-module from . import ui_bootfromdevice # pylint: disable=no-name-in-module
@ -28,11 +28,12 @@ from qubesadmin.tools import qvm_start
class VMBootFromDeviceWindow(ui_bootfromdevice.Ui_BootDialog, class VMBootFromDeviceWindow(ui_bootfromdevice.Ui_BootDialog,
QtWidgets.QDialog): QtWidgets.QDialog):
def __init__(self, vm, qapp, parent=None): def __init__(self, vm, qapp, qubesapp=None, parent=None):
super(VMBootFromDeviceWindow, self).__init__(parent) super(VMBootFromDeviceWindow, self).__init__(parent)
self.vm = vm self.vm = vm
self.qapp = qapp self.qapp = qapp
self.qubesapp = qubesapp
self.setupUi(self) self.setupUi(self)
self.setWindowTitle( self.setWindowTitle(
@ -147,19 +148,8 @@ def main(args=None):
args = parser.parse_args(args) args = parser.parse_args(args)
vm = args.domains.pop() vm = args.domains.pop()
qapp = QtWidgets.QApplication(sys.argv) utils.run_synchronous("Boot Qube From Device",
qapp.setOrganizationName('Invisible Things Lab') functools.partial(VMBootFromDeviceWindow, vm))
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()
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -326,8 +326,7 @@ class QubesFirewallRulesModel(QtCore.QAbstractItemModel):
if rule.action == 'accept': if rule.action == 'accept':
conf['rules'].insert(0, rule) conf['rules'].insert(0, rule)
continue continue
else: raise FirewallModifiedOutsideError('No blacklist support.')
raise FirewallModifiedOutsideError('No blacklist support.')
if rule.expire is not None and rule.dsthost is None \ if rule.expire is not None and rule.dsthost is None \
and rule.proto is None: and rule.proto is None:

View File

@ -20,14 +20,11 @@
# #
# #
import sys
import os import os
import os.path import os.path
import traceback
import subprocess import subprocess
from PyQt5 import QtWidgets # pylint: disable=import-error from PyQt5 import QtWidgets # pylint: disable=import-error
from qubesadmin import Qubes
from qubesadmin.utils import parse_size from qubesadmin.utils import parse_size
from . import ui_globalsettingsdlg # pylint: disable=no-name-in-module from . import ui_globalsettingsdlg # pylint: disable=no-name-in-module
@ -43,7 +40,8 @@ def _run_qrexec_repo(service, arg=''):
p = subprocess.run( p = subprocess.run(
['sudo', cmd, arg], ['sudo', cmd, arg],
stdout=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.PIPE stderr=subprocess.PIPE,
check=False
) )
if p.stderr: if p.stderr:
raise RuntimeError('qrexec call stderr was not empty', raise RuntimeError('qrexec call stderr was not empty',
@ -406,39 +404,9 @@ class GlobalSettingsWindow(ui_globalsettingsdlg.Ui_GlobalSettings,
self.__apply_updates__() self.__apply_updates__()
self.__apply_repos__() self.__apply_repos__()
# Bases on the original code by:
# Copyright (c) 2002-2007 Pascal Varet <p.varet@gmail.com>
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.<br><br><b><i>%s</i></b>" %
error + "at <b>line %d</b> of file <b>%s</b>.<br/><br/>"
% (line, filename))
def main(): def main():
qtapp = QtWidgets.QApplication(sys.argv) utils.run_synchronous("Qubes Global Settings", GlobalSettingsWindow)
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()
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -21,21 +21,13 @@
# with this program; if not, see <http://www.gnu.org/licenses/>. # with this program; if not, see <http://www.gnu.org/licenses/>.
# #
# #
import sys
import os import os
import os.path import os.path
import subprocess import subprocess
from datetime import datetime, timedelta 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 exc
from qubesadmin import utils from qubesadmin import utils
from qubesadmin import events
from PyQt5 import QtWidgets, QtCore, QtGui # pylint: disable=import-error from PyQt5 import QtWidgets, QtCore, QtGui # pylint: disable=import-error
@ -672,7 +664,7 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtWidgets.QMainWindow):
QtCore.QSize(1100, 600))) QtCore.QSize(1100, 600)))
def get_vms_list(self): def get_vms_list(self):
return [vm for vm in self.qubes_app.domains] return list(self.qubes_app.domains)
def fill_table(self): def fill_table(self):
self.table.setSortingEnabled(False) self.table.setSortingEnabled(False)
@ -1306,71 +1298,11 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtWidgets.QMainWindow):
log_dlg.exec_() log_dlg.exec_()
# Bases on the original code by:
# Copyright (c) 2002-2007 Pascal Varet <p.varet@gmail.com>
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.<br><br>"
"<b><i>%s</i></b>" % error +
"<br/>at line <b>%d</b><br/>of file %s.<br/><br/>"
% (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(): def main():
qt_app = QtWidgets.QApplication(sys.argv) manager_utils.run_asynchronous(
qt_app.setOrganizationName("The Qubes Project") "Qube Manager",
qt_app.setOrganizationDomain("http://qubes-os.org") QtGui.QIcon.fromTheme("qubes-manager"),
qt_app.setApplicationName("Qube Manager") VmManagerWindow)
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)
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -20,11 +20,9 @@
# #
# #
import sys
from PyQt5 import QtCore, QtWidgets # pylint: disable=import-error from PyQt5 import QtCore, QtWidgets # pylint: disable=import-error
import os import os
import os.path import os.path
import traceback
import logging import logging
import logging.handlers import logging.handlers
@ -33,10 +31,11 @@ from qubes import backup
from . import ui_restoredlg # pylint: disable=no-name-in-module from . import ui_restoredlg # pylint: disable=no-name-in-module
from . import multiselectwidget from . import multiselectwidget
from . import backup_utils from . import backup_utils
from . import utils
from multiprocessing import Queue from multiprocessing import Queue
from queue import Empty from queue import Empty
from qubesadmin import Qubes, exc from qubesadmin import exc
from qubesadmin.backup import restore from qubesadmin.backup import restore
@ -292,39 +291,8 @@ class RestoreVMsWindow(ui_restoredlg.Ui_Restore, QtWidgets.QWizard):
self.select_dir_page.completeChanged.emit() self.select_dir_page.completeChanged.emit()
# Bases on the original code by:
# Copyright (c) 2002-2007 Pascal Varet <p.varet@gmail.com>
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.<br><br><b><i>%s</i></b>" % error +
"at <b>line %d</b> of file <b>%s</b>.<br/><br/>" % (line, filename))
def main(): def main():
utils.run_synchronous("Qubes Restore VMs", RestoreVMsWindow)
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()
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -23,12 +23,10 @@
# #
import collections import collections
import os.path import functools
import os
import re import re
import subprocess import subprocess
import traceback import traceback
import sys
from qubesadmin.tools import QubesArgumentParser from qubesadmin.tools import QubesArgumentParser
from qubesadmin import devices from qubesadmin import devices
from qubesadmin import utils as admin_utils from qubesadmin import utils as admin_utils
@ -128,11 +126,13 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtWidgets.QDialog):
('services', 5), ('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) super(VMSettingsWindow, self).__init__(parent)
self.vm = vm self.vm = vm
self.qapp = qapp self.qapp = qapp
self.qubesapp = qubesapp
self.threads_list = [] self.threads_list = []
self.progress = None self.progress = None
self.thread_closes = False self.thread_closes = False
@ -1219,38 +1219,6 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtWidgets.QDialog):
self.fw_model.remove_child(i) self.fw_model.remove_child(i)
# Bases on the original code by:
# Copyright (c) 2002-2007 Pascal Varet <p.varet@gmail.com>
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.<br><br>"
"<b><i>%s</i></b>" % error +
"<br/>at line <b>%d</b><br/>of file %s.<br/><br/>"
% (line, filename))
msg_box.exec_()
parser = QubesArgumentParser(vmname_nargs=1) parser = QubesArgumentParser(vmname_nargs=1)
parser.add_argument('--tab', metavar='TAB', parser.add_argument('--tab', metavar='TAB',
@ -1266,19 +1234,8 @@ def main(args=None):
args = parser.parse_args(args) args = parser.parse_args(args)
vm = args.domains.pop() vm = args.domains.pop()
qapp = QtWidgets.QApplication(sys.argv) utils.run_synchronous("Qube Settings",
qapp.setOrganizationName('Invisible Things Lab') functools.partial(VMSettingsWindow, vm, args.tab))
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()
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -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 exc
from qubesadmin import events
from PyQt5 import QtWidgets, QtGui, QtCore # pylint: disable=import-error from PyQt5 import QtWidgets, QtGui, QtCore # pylint: disable=import-error
from . import ui_templatemanager # pylint: disable=no-name-in-module from . import ui_templatemanager # pylint: disable=no-name-in-module
from . import utils
column_names = ['State', 'Qube', 'Current template', 'New template'] column_names = ['State', 'Qube', 'Current template', 'New template']
@ -385,72 +376,11 @@ class VMRow:
row, column_names.index('State')) row, column_names.index('State'))
self.checkbox = None self.checkbox = None
# Bases on the original code by:
# Copyright (c) 2002-2007 Pascal Varet <p.varet@gmail.com>
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.<br><br>"
"<b><i>%s</i></b>" % error +
"<br/>at line <b>%d</b><br/>of file %s.<br/><br/>"
% (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(): def main():
qt_app = QtWidgets.QApplication(sys.argv) utils.run_asynchronous("Template Manager",
qt_app.setOrganizationName("The Qubes Project") QtGui.QIcon.fromTheme("qubes-manager"),
qt_app.setOrganizationDomain("http://qubes-os.org") TemplateManagerWindow)
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)
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -23,7 +23,14 @@ import itertools
import os import os
import re import re
import qubesadmin import qubesadmin
import traceback
import asyncio
from contextlib import suppress
import sys
import quamash
from qubesadmin import events
from PyQt5 import QtWidgets # pylint: disable=import-error
from PyQt5.QtGui import QIcon # pylint: disable=import-error from PyQt5.QtGui import QIcon # pylint: disable=import-error
@ -215,3 +222,87 @@ def format_dependencies_list(dependencies):
prop, holder.name) prop, holder.name)
return list_text 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 <p.varet@gmail.com>
def handle_exception(exc_type, exc_value, exc_traceback):
filename, line, _, _ = 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.<br><br>"
"<b><i>%s</i></b>" % error +
"<br/>at line <b>%d</b><br/>of file %s.<br/><br/>"
% (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()