mirror of
https://github.com/freedomofpress/dangerzone.git
synced 2025-04-28 18:02:38 +02:00
166 lines
5.4 KiB
Python
166 lines
5.4 KiB
Python
import os
|
|
import sys
|
|
import signal
|
|
import platform
|
|
import click
|
|
import time
|
|
import uuid
|
|
import subprocess
|
|
from PySide2 import QtCore, QtWidgets
|
|
|
|
from .global_common import GlobalCommon
|
|
from .main_window import MainWindow
|
|
from .docker_installer import (
|
|
is_docker_installed,
|
|
is_docker_ready,
|
|
launch_docker_windows,
|
|
DockerInstaller,
|
|
AuthorizationFailed,
|
|
)
|
|
from .container import container_runtime
|
|
|
|
|
|
# For some reason, Dangerzone segfaults if I inherit from QApplication directly, so instead
|
|
# this is a class whose job is to hold a QApplication object and customize it
|
|
class ApplicationWrapper(QtCore.QObject):
|
|
document_selected = QtCore.Signal(str)
|
|
application_activated = QtCore.Signal()
|
|
|
|
def __init__(self):
|
|
super(ApplicationWrapper, self).__init__()
|
|
self.app = QtWidgets.QApplication()
|
|
self.app.setQuitOnLastWindowClosed(False)
|
|
|
|
self.original_event = self.app.event
|
|
|
|
def monkeypatch_event(event):
|
|
# In macOS, handle the file open event
|
|
if event.type() == QtCore.QEvent.FileOpen:
|
|
self.document_selected.emit(event.file())
|
|
return True
|
|
elif event.type() == QtCore.QEvent.ApplicationActivate:
|
|
self.application_activated.emit()
|
|
return True
|
|
|
|
return self.original_event(event)
|
|
|
|
self.app.event = monkeypatch_event
|
|
|
|
|
|
@click.command()
|
|
@click.option("--custom-container") # Use this container instead of flmcode/dangerzone
|
|
@click.argument("filename", required=False)
|
|
def gui_main(custom_container, filename):
|
|
# Required for macOS Big Sur: https://stackoverflow.com/a/64878899
|
|
if platform.system() == "Darwin":
|
|
os.environ["QT_MAC_WANTS_LAYER"] = "1"
|
|
|
|
# Create the Qt app
|
|
app_wrapper = ApplicationWrapper()
|
|
app = app_wrapper.app
|
|
|
|
# GlobalCommon object
|
|
global_common = GlobalCommon(app)
|
|
|
|
if custom_container:
|
|
# Do we have this container?
|
|
with global_common.exec_dangerzone_container(
|
|
["ls", "--container-name", custom_container]
|
|
) as p:
|
|
stdout_data, stderr_data = p.communicate()
|
|
|
|
# The user canceled, or permission denied
|
|
if p.returncode == 126 or p.returncode == 127:
|
|
click.echo("Authorization failed")
|
|
return
|
|
elif p.returncode != 0:
|
|
click.echo("Container error")
|
|
return
|
|
|
|
# Check the output
|
|
if custom_container.encode() not in stdout_data:
|
|
click.echo(f"Container '{custom_container}' not found")
|
|
return
|
|
|
|
global_common.custom_container = custom_container
|
|
|
|
# Allow Ctrl-C to smoothly quit the program instead of throwing an exception
|
|
signal.signal(signal.SIGINT, signal.SIG_DFL)
|
|
|
|
# If we're using Linux and docker, see if we need to add the user to the docker group or if the user prefers typing their password
|
|
if platform.system() == "Linux":
|
|
if not global_common.ensure_docker_group_preference():
|
|
return
|
|
try:
|
|
if not global_common.ensure_docker_service_is_started():
|
|
click.echo("Failed to start docker service")
|
|
return
|
|
except AuthorizationFailed:
|
|
click.echo("Authorization failed")
|
|
return
|
|
|
|
# See if we need to install Docker...
|
|
if (platform.system() == "Darwin" or platform.system() == "Windows") and (
|
|
not is_docker_installed(global_common) or not is_docker_ready(global_common)
|
|
):
|
|
click.echo("Docker is either not installed or not running")
|
|
docker_installer = DockerInstaller(global_common)
|
|
docker_installer.start()
|
|
return
|
|
|
|
closed_windows = {}
|
|
windows = {}
|
|
|
|
def delete_window(window_id):
|
|
closed_windows[window_id] = windows[window_id]
|
|
del windows[window_id]
|
|
|
|
# Open a document in a window
|
|
def select_document(filename=None):
|
|
if (
|
|
len(windows) == 1
|
|
and windows[list(windows.keys())[0]].common.document_filename == None
|
|
):
|
|
window = windows[list(windows.keys())[0]]
|
|
else:
|
|
window_id = uuid.uuid4().hex
|
|
window = MainWindow(global_common, window_id)
|
|
window.delete_window.connect(delete_window)
|
|
windows[window_id] = window
|
|
|
|
if filename:
|
|
# Validate filename
|
|
filename = os.path.abspath(os.path.expanduser(filename))
|
|
try:
|
|
open(filename, "rb")
|
|
except FileNotFoundError:
|
|
click.echo("File not found")
|
|
return False
|
|
except PermissionError:
|
|
click.echo("Permission denied")
|
|
return False
|
|
window.common.document_filename = filename
|
|
window.doc_selection_widget.document_selected.emit()
|
|
|
|
return True
|
|
|
|
# Open a new window if not filename is passed
|
|
if filename is None:
|
|
select_document()
|
|
else:
|
|
# If filename is passed as an argument, open it
|
|
if not select_document(filename):
|
|
return True
|
|
|
|
# Open a new window, if all windows are closed
|
|
def application_activated():
|
|
if len(windows) == 0:
|
|
select_document()
|
|
|
|
# If we get a file open event, open it
|
|
app_wrapper.document_selected.connect(select_document)
|
|
|
|
# If the application is activated and all windows are closed, open a new one
|
|
app_wrapper.application_activated.connect(application_activated)
|
|
|
|
sys.exit(app.exec_())
|