mirror of
https://github.com/freedomofpress/dangerzone.git
synced 2025-04-30 10:42:37 +02:00
Unwrap QApplication
With Qt 6, subclassing QApplication no longer seems to segfault
This commit is contained in:
parent
bd33f16af4
commit
fc8d2af23b
2 changed files with 30 additions and 29 deletions
|
@ -2,9 +2,13 @@ import os
|
||||||
import sys
|
import sys
|
||||||
import signal
|
import signal
|
||||||
import platform
|
import platform
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
import click
|
import click
|
||||||
import uuid
|
import uuid
|
||||||
from PySide6 import QtCore, QtWidgets
|
from PySide6 import QtCore
|
||||||
|
from PySide6.QtCore import QEvent
|
||||||
|
from PySide6.QtWidgets import QApplication
|
||||||
|
|
||||||
from .common import GuiCommon
|
from .common import GuiCommon
|
||||||
from .main_window import MainWindow
|
from .main_window import MainWindow
|
||||||
|
@ -12,21 +16,17 @@ from .systray import SysTray
|
||||||
from ..global_common import GlobalCommon
|
from ..global_common import GlobalCommon
|
||||||
|
|
||||||
|
|
||||||
# For some reason, Dangerzone segfaults if I inherit from QApplication directly, so instead
|
class Application(QApplication):
|
||||||
# this is a class whose job is to hold a QApplication object and customize it
|
|
||||||
class ApplicationWrapper(QtCore.QObject):
|
|
||||||
document_selected = QtCore.Signal(str)
|
document_selected = QtCore.Signal(str)
|
||||||
new_window = QtCore.Signal()
|
new_window = QtCore.Signal()
|
||||||
application_activated = QtCore.Signal()
|
application_activated = QtCore.Signal()
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(ApplicationWrapper, self).__init__()
|
super(Application, self).__init__()
|
||||||
self.app = QtWidgets.QApplication()
|
self.setQuitOnLastWindowClosed(False)
|
||||||
self.app.setQuitOnLastWindowClosed(False)
|
self.original_event = self.event
|
||||||
|
|
||||||
self.original_event = self.app.event
|
def monkeypatch_event(event: QEvent):
|
||||||
|
|
||||||
def monkeypatch_event(event):
|
|
||||||
# In macOS, handle the file open event
|
# In macOS, handle the file open event
|
||||||
if event.type() == QtCore.QEvent.FileOpen:
|
if event.type() == QtCore.QEvent.FileOpen:
|
||||||
# Skip file open events in dev mode
|
# Skip file open events in dev mode
|
||||||
|
@ -36,10 +36,9 @@ class ApplicationWrapper(QtCore.QObject):
|
||||||
elif event.type() == QtCore.QEvent.ApplicationActivate:
|
elif event.type() == QtCore.QEvent.ApplicationActivate:
|
||||||
self.application_activated.emit()
|
self.application_activated.emit()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
return self.original_event(event)
|
return self.original_event(event)
|
||||||
|
|
||||||
self.app.event = monkeypatch_event
|
self.event = monkeypatch_event
|
||||||
|
|
||||||
|
|
||||||
@click.command()
|
@click.command()
|
||||||
|
@ -70,8 +69,7 @@ def gui_main(filename):
|
||||||
sys.stderr = StdoutFilter(sys.stderr)
|
sys.stderr = StdoutFilter(sys.stderr)
|
||||||
|
|
||||||
# Create the Qt app
|
# Create the Qt app
|
||||||
app_wrapper = ApplicationWrapper()
|
app = Application()
|
||||||
app = app_wrapper.app
|
|
||||||
|
|
||||||
# Common objects
|
# Common objects
|
||||||
global_common = GlobalCommon()
|
global_common = GlobalCommon()
|
||||||
|
@ -81,7 +79,7 @@ def gui_main(filename):
|
||||||
signal.signal(signal.SIGINT, signal.SIG_DFL)
|
signal.signal(signal.SIGINT, signal.SIG_DFL)
|
||||||
|
|
||||||
# Create the system tray
|
# Create the system tray
|
||||||
systray = SysTray(global_common, gui_common, app, app_wrapper)
|
SysTray(global_common, gui_common, app)
|
||||||
|
|
||||||
closed_windows = {}
|
closed_windows = {}
|
||||||
windows = {}
|
windows = {}
|
||||||
|
@ -91,10 +89,10 @@ def gui_main(filename):
|
||||||
del windows[window_id]
|
del windows[window_id]
|
||||||
|
|
||||||
# Open a document in a window
|
# Open a document in a window
|
||||||
def select_document(filename=None):
|
def select_document(path: Optional[str] = None):
|
||||||
if (
|
if (
|
||||||
len(windows) == 1
|
len(windows) == 1
|
||||||
and windows[list(windows.keys())[0]].common.input_filename == None
|
and windows[list(windows.keys())[0]].common.input_filename is None
|
||||||
):
|
):
|
||||||
window = windows[list(windows.keys())[0]]
|
window = windows[list(windows.keys())[0]]
|
||||||
else:
|
else:
|
||||||
|
@ -103,18 +101,18 @@ def gui_main(filename):
|
||||||
window.delete_window.connect(delete_window)
|
window.delete_window.connect(delete_window)
|
||||||
windows[window_id] = window
|
windows[window_id] = window
|
||||||
|
|
||||||
if filename:
|
if path is not None:
|
||||||
# Validate filename
|
# Validate path
|
||||||
filename = os.path.abspath(os.path.expanduser(filename))
|
path = os.path.abspath(os.path.expanduser(path))
|
||||||
try:
|
try:
|
||||||
open(filename, "rb")
|
open(path, "rb")
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
click.echo("File not found")
|
click.echo("File not found")
|
||||||
return False
|
return False
|
||||||
except PermissionError:
|
except PermissionError:
|
||||||
click.echo("Permission denied")
|
click.echo("Permission denied")
|
||||||
return False
|
return False
|
||||||
window.common.input_filename = filename
|
window.common.input_filename = path
|
||||||
window.content_widget.doc_selection_widget.document_selected.emit()
|
window.content_widget.doc_selection_widget.document_selected.emit()
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
@ -133,11 +131,11 @@ def gui_main(filename):
|
||||||
select_document()
|
select_document()
|
||||||
|
|
||||||
# If we get a file open event, open it
|
# If we get a file open event, open it
|
||||||
app_wrapper.document_selected.connect(select_document)
|
app.document_selected.connect(select_document)
|
||||||
app_wrapper.new_window.connect(select_document)
|
app.new_window.connect(select_document)
|
||||||
|
|
||||||
# If the application is activated and all windows are closed, open a new one
|
# If the application is activated and all windows are closed, open a new one
|
||||||
app_wrapper.application_activated.connect(application_activated)
|
app.application_activated.connect(application_activated)
|
||||||
|
|
||||||
# Launch the GUI
|
# Launch the GUI
|
||||||
ret = app.exec_()
|
ret = app.exec_()
|
||||||
|
|
|
@ -1,14 +1,17 @@
|
||||||
import platform
|
|
||||||
from PySide6 import QtWidgets
|
from PySide6 import QtWidgets
|
||||||
|
|
||||||
|
from dangerzone.global_common import GlobalCommon
|
||||||
|
from dangerzone.gui import Application, GuiCommon
|
||||||
|
|
||||||
|
|
||||||
class SysTray(QtWidgets.QSystemTrayIcon):
|
class SysTray(QtWidgets.QSystemTrayIcon):
|
||||||
def __init__(self, global_common, gui_common, app, app_wrapper):
|
def __init__(
|
||||||
|
self, global_common: GlobalCommon, gui_common: GuiCommon, app: Application
|
||||||
|
):
|
||||||
super(SysTray, self).__init__()
|
super(SysTray, self).__init__()
|
||||||
self.global_common = global_common
|
self.global_common = global_common
|
||||||
self.gui_common = gui_common
|
self.gui_common = gui_common
|
||||||
self.app = app
|
self.app = app
|
||||||
self.app_wrapper = app_wrapper
|
|
||||||
|
|
||||||
self.setIcon(self.gui_common.get_window_icon())
|
self.setIcon(self.gui_common.get_window_icon())
|
||||||
|
|
||||||
|
@ -24,7 +27,7 @@ class SysTray(QtWidgets.QSystemTrayIcon):
|
||||||
self.show()
|
self.show()
|
||||||
|
|
||||||
def new_window(self):
|
def new_window(self):
|
||||||
self.app_wrapper.new_window.emit()
|
self.app.new_window.emit()
|
||||||
|
|
||||||
def quit_clicked(self):
|
def quit_clicked(self):
|
||||||
self.app.quit()
|
self.app.quit()
|
||||||
|
|
Loading…
Reference in a new issue