Refactor dangerzone to move GUI code into its own module

This commit is contained in:
Micah Lee 2021-06-09 15:24:03 -07:00
parent 12b3bde03d
commit 6ff68f88ea
No known key found for this signature in database
GPG key ID: 403C2657CD994F73
13 changed files with 350 additions and 321 deletions

View file

@ -3,11 +3,14 @@ import sys
dangerzone_version = "0.1.5" dangerzone_version = "0.1.5"
# This is a hack for Windows and Mac to be able to run dangerzone-container, even though # Depending on the filename, decide if we want to run:
# PyInstaller builds a single binary # dangerzone, dangerzone-cli, or dangerzone-container
basename = os.path.basename(sys.argv[0]) basename = os.path.basename(sys.argv[0])
if basename == "dangerzone-container" or basename == "dangerzone-container.exe": if basename == "dangerzone-container" or basename == "dangerzone-container.exe":
from .container import container_main as main from .container import container_main as main
elif basename == "dangerzone-cli" or basename == "dangerzone-cli.exe":
from .cli import cli_main as main
else: else:
# If the binary isn't "dangerzone-contatiner", then launch the GUI
from .gui import gui_main as main from .gui import gui_main as main

8
dangerzone/cli.py Normal file
View file

@ -0,0 +1,8 @@
import click
@click.command()
@click.option("--custom-container") # Use this container instead of flmcode/dangerzone
@click.argument("filename", required=False)
def cli_main(custom_container, filename):
pass

View file

@ -1,26 +1,13 @@
import sys import sys
import os import os
import inspect import inspect
import tempfile
import appdirs import appdirs
import platform import platform
import subprocess import subprocess
import shlex
import pipes import pipes
from PySide2 import QtCore, QtGui, QtWidgets from PySide2 import QtCore, QtGui, QtWidgets
if platform.system() == "Darwin":
import CoreServices
import LaunchServices
import plistlib
elif platform.system() == "Linux":
import grp
import getpass
from xdg.DesktopEntry import DesktopEntry
from .settings import Settings from .settings import Settings
from .docker_installer import is_docker_ready
class GlobalCommon(object): class GlobalCommon(object):
@ -28,19 +15,7 @@ class GlobalCommon(object):
The GlobalCommon class is a singleton of shared functionality throughout the app The GlobalCommon class is a singleton of shared functionality throughout the app
""" """
def __init__(self, app): def __init__(self):
# Qt app
self.app = app
# Name of input file
self.document_filename = None
# Name of output file
self.save_filename = None
# Preload font
self.fixed_font = QtGui.QFontDatabase.systemFont(QtGui.QFontDatabase.FixedFont)
# App data folder # App data folder
self.appdata_path = appdirs.user_config_dir("dangerzone") self.appdata_path = appdirs.user_config_dir("dangerzone")
@ -50,9 +25,6 @@ class GlobalCommon(object):
# dangerzone-container path # dangerzone-container path
self.dz_container_path = self.get_dangerzone_container_path() self.dz_container_path = self.get_dangerzone_container_path()
# Preload list of PDF viewers on computer
self.pdf_viewers = self._find_pdf_viewers()
# Languages supported by tesseract # Languages supported by tesseract
self.ocr_languages = { self.ocr_languages = {
"Afrikaans": "ar", "Afrikaans": "ar",
@ -295,187 +267,6 @@ class GlobalCommon(object):
stderr=subprocess.PIPE, stderr=subprocess.PIPE,
) )
def get_window_icon(self):
if platform.system() == "Windows":
path = self.get_resource_path("dangerzone.ico")
else:
path = self.get_resource_path("icon.png")
return QtGui.QIcon(path)
def open_pdf_viewer(self, filename):
if self.settings.get("open_app") in self.pdf_viewers:
if platform.system() == "Darwin":
# Get the PDF reader bundle command
bundle_identifier = self.pdf_viewers[self.settings.get("open_app")]
args = ["open", "-b", bundle_identifier, filename]
# Run
print(f"Executing: {' '.join(args)}")
subprocess.run(args)
elif platform.system() == "Linux":
# Get the PDF reader command
args = shlex.split(self.pdf_viewers[self.settings.get("open_app")])
# %f, %F, %u, and %U are filenames or URLS -- so replace with the file to open
for i in range(len(args)):
if (
args[i] == "%f"
or args[i] == "%F"
or args[i] == "%u"
or args[i] == "%U"
):
args[i] = filename
# Open as a background process
print(f"Executing: {' '.join(args)}")
subprocess.Popen(args)
def _find_pdf_viewers(self):
pdf_viewers = {}
if platform.system() == "Darwin":
# Get all installed apps that can open PDFs
bundle_identifiers = LaunchServices.LSCopyAllRoleHandlersForContentType(
"com.adobe.pdf", CoreServices.kLSRolesAll
)
for bundle_identifier in bundle_identifiers:
# Get the filesystem path of the app
res = LaunchServices.LSCopyApplicationURLsForBundleIdentifier(
bundle_identifier, None
)
if res[0] is None:
continue
app_url = res[0][0]
app_path = str(app_url.path())
# Load its plist file
plist_path = os.path.join(app_path, "Contents/Info.plist")
# Skip if there's not an Info.plist
if not os.path.exists(plist_path):
continue
with open(plist_path, "rb") as f:
plist_data = f.read()
plist_dict = plistlib.loads(plist_data)
if (
plist_dict.get("CFBundleName")
and plist_dict["CFBundleName"] != "Dangerzone"
):
pdf_viewers[plist_dict["CFBundleName"]] = bundle_identifier
elif platform.system() == "Linux":
# Find all .desktop files
for search_path in [
"/usr/share/applications",
"/usr/local/share/applications",
os.path.expanduser("~/.local/share/applications"),
]:
try:
for filename in os.listdir(search_path):
full_filename = os.path.join(search_path, filename)
if os.path.splitext(filename)[1] == ".desktop":
# See which ones can open PDFs
desktop_entry = DesktopEntry(full_filename)
if (
"application/pdf" in desktop_entry.getMimeTypes()
and desktop_entry.getName() != "dangerzone"
):
pdf_viewers[
desktop_entry.getName()
] = desktop_entry.getExec()
except FileNotFoundError:
pass
return pdf_viewers
def ensure_docker_group_preference(self):
# If the user prefers typing their password
if self.settings.get("linux_prefers_typing_password") == True:
return True
# Get the docker group
try:
groupinfo = grp.getgrnam("docker")
except:
# Ignore if group is not found
return True
# See if the user is in the group
username = getpass.getuser()
if username not in groupinfo.gr_mem:
# User is not in the docker group, ask if they prefer typing their password
message = "<b>Dangerzone requires Docker</b><br><br>In order to use Docker, your user must be in the 'docker' group or you'll need to type your password each time you run dangerzone.<br><br><b>Adding your user to the 'docker' group is more convenient but less secure</b>, and will require just typing your password once. Which do you prefer?"
return_code = Alert(
self,
message,
ok_text="I'll type my password each time",
extra_button_text="Add my user to the 'docker' group",
).launch()
if return_code == QtWidgets.QDialog.Accepted:
# Prefers typing password
self.settings.set("linux_prefers_typing_password", True)
self.settings.save()
return True
elif return_code == 2:
# Prefers being in the docker group
self.settings.set("linux_prefers_typing_password", False)
self.settings.save()
# Add user to the docker group
p = subprocess.run(
[
"/usr/bin/pkexec",
"/usr/sbin/usermod",
"-a",
"-G",
"docker",
username,
]
)
if p.returncode == 0:
message = "Great! Now you must log out of your computer and log back in, and then you can use Dangerzone."
Alert(self, message).launch()
else:
message = "Failed to add your user to the 'docker' group, quitting."
Alert(self, message).launch()
return False
else:
# Cancel
return False
return True
def ensure_docker_service_is_started(self):
if not is_docker_ready(self):
message = "<b>Dangerzone requires Docker</b><br><br>Docker should be installed, but it looks like it's not running in the background.<br><br>Click Ok to try starting the docker service. You will have to type your login password."
if Alert(self, message).launch() == QtWidgets.QDialog.Accepted:
p = subprocess.run(
[
"/usr/bin/pkexec",
self.get_resource_path("enable_docker_service.sh"),
]
)
if p.returncode == 0:
# Make sure docker is now ready
if is_docker_ready(self):
return True
else:
message = "Restarting docker appeared to work, but the service still isn't responding, quitting."
Alert(self, message).launch()
else:
message = "Failed to start the docker service, quitting."
Alert(self, message).launch()
return False
return True
def get_subprocess_startupinfo(self): def get_subprocess_startupinfo(self):
if platform.system() == "Windows": if platform.system() == "Windows":
startupinfo = subprocess.STARTUPINFO() startupinfo = subprocess.STARTUPINFO()
@ -483,71 +274,3 @@ class GlobalCommon(object):
return startupinfo return startupinfo
else: else:
return None return None
class Alert(QtWidgets.QDialog):
def __init__(self, common, message, ok_text="Ok", extra_button_text=None):
super(Alert, self).__init__()
self.common = common
self.setWindowTitle("dangerzone")
self.setWindowIcon(self.common.get_window_icon())
self.setModal(True)
flags = (
QtCore.Qt.CustomizeWindowHint
| QtCore.Qt.WindowTitleHint
| QtCore.Qt.WindowSystemMenuHint
| QtCore.Qt.WindowCloseButtonHint
| QtCore.Qt.WindowStaysOnTopHint
)
self.setWindowFlags(flags)
logo = QtWidgets.QLabel()
logo.setPixmap(
QtGui.QPixmap.fromImage(
QtGui.QImage(self.common.get_resource_path("icon.png"))
)
)
label = QtWidgets.QLabel()
label.setText(message)
label.setWordWrap(True)
message_layout = QtWidgets.QHBoxLayout()
message_layout.addWidget(logo)
message_layout.addSpacing(10)
message_layout.addWidget(label, stretch=1)
ok_button = QtWidgets.QPushButton(ok_text)
ok_button.clicked.connect(self.clicked_ok)
if extra_button_text:
extra_button = QtWidgets.QPushButton(extra_button_text)
extra_button.clicked.connect(self.clicked_extra)
cancel_button = QtWidgets.QPushButton("Cancel")
cancel_button.clicked.connect(self.clicked_cancel)
buttons_layout = QtWidgets.QHBoxLayout()
buttons_layout.addStretch()
buttons_layout.addWidget(ok_button)
if extra_button_text:
buttons_layout.addWidget(extra_button)
buttons_layout.addWidget(cancel_button)
layout = QtWidgets.QVBoxLayout()
layout.addLayout(message_layout)
layout.addSpacing(10)
layout.addLayout(buttons_layout)
self.setLayout(layout)
def clicked_ok(self):
self.done(QtWidgets.QDialog.Accepted)
def clicked_extra(self):
self.done(2)
def clicked_cancel(self):
self.done(QtWidgets.QDialog.Rejected)
def launch(self):
return self.exec_()

View file

@ -3,21 +3,19 @@ import sys
import signal import signal
import platform import platform
import click import click
import time
import uuid import uuid
import subprocess
from PySide2 import QtCore, QtWidgets from PySide2 import QtCore, QtWidgets
from .global_common import GlobalCommon from .common import GuiCommon
from .main_window import MainWindow from .main_window import MainWindow
from .docker_installer import ( from .docker_installer import (
is_docker_installed, is_docker_installed,
is_docker_ready, is_docker_ready,
launch_docker_windows,
DockerInstaller, DockerInstaller,
AuthorizationFailed, AuthorizationFailed,
) )
from .container import container_runtime from ..global_common import GlobalCommon
from ..container import container_runtime
# For some reason, Dangerzone segfaults if I inherit from QApplication directly, so instead # For some reason, Dangerzone segfaults if I inherit from QApplication directly, so instead
@ -59,8 +57,9 @@ def gui_main(custom_container, filename):
app_wrapper = ApplicationWrapper() app_wrapper = ApplicationWrapper()
app = app_wrapper.app app = app_wrapper.app
# GlobalCommon object # Common objects
global_common = GlobalCommon(app) global_common = GlobalCommon()
gui_common = GuiCommon(app, global_common)
if custom_container: if custom_container:
# Do we have this container? # Do we have this container?
@ -89,10 +88,10 @@ def gui_main(custom_container, filename):
# 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 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 platform.system() == "Linux":
if not global_common.ensure_docker_group_preference(): if not gui_common.ensure_docker_group_preference():
return return
try: try:
if not global_common.ensure_docker_service_is_started(): if not gui_common.ensure_docker_service_is_started():
click.echo("Failed to start docker service") click.echo("Failed to start docker service")
return return
except AuthorizationFailed: except AuthorizationFailed:
@ -101,10 +100,10 @@ def gui_main(custom_container, filename):
# See if we need to install Docker... # See if we need to install Docker...
if (platform.system() == "Darwin" or platform.system() == "Windows") and ( if (platform.system() == "Darwin" or platform.system() == "Windows") and (
not is_docker_installed(global_common) or not is_docker_ready(global_common) not is_docker_installed() or not is_docker_ready(global_common)
): ):
click.echo("Docker is either not installed or not running") click.echo("Docker is either not installed or not running")
docker_installer = DockerInstaller(global_common) docker_installer = DockerInstaller(gui_common)
docker_installer.start() docker_installer.start()
return return
@ -124,7 +123,7 @@ def gui_main(custom_container, filename):
window = windows[list(windows.keys())[0]] window = windows[list(windows.keys())[0]]
else: else:
window_id = uuid.uuid4().hex window_id = uuid.uuid4().hex
window = MainWindow(global_common, window_id) window = MainWindow(global_common, gui_common, window_id)
window.delete_window.connect(delete_window) window.delete_window.connect(delete_window)
windows[window_id] = window windows[window_id] = window

295
dangerzone/gui/common.py Normal file
View file

@ -0,0 +1,295 @@
import os
import platform
import subprocess
import shlex
from PySide2 import QtCore, QtGui, QtWidgets
if platform.system() == "Darwin":
import CoreServices
import LaunchServices
import plistlib
elif platform.system() == "Linux":
import grp
import getpass
from xdg.DesktopEntry import DesktopEntry
from .docker_installer import is_docker_ready
from ..settings import Settings
class GuiCommon(object):
"""
The GuiCommon class is a singleton of shared functionality for the GUI
"""
def __init__(self, app, global_common):
# Qt app
self.app = app
# Global common singleton
self.global_common = global_common
# Preload font
self.fixed_font = QtGui.QFontDatabase.systemFont(QtGui.QFontDatabase.FixedFont)
# Preload list of PDF viewers on computer
self.pdf_viewers = self._find_pdf_viewers()
def get_window_icon(self):
if platform.system() == "Windows":
path = self.global_common.get_resource_path("dangerzone.ico")
else:
path = self.global_common.get_resource_path("icon.png")
return QtGui.QIcon(path)
def open_pdf_viewer(self, filename):
if self.global_common.settings.get("open_app") in self.pdf_viewers:
if platform.system() == "Darwin":
# Get the PDF reader bundle command
bundle_identifier = self.pdf_viewers[self.global_common.settings.get("open_app")]
args = ["open", "-b", bundle_identifier, filename]
# Run
print(f"Executing: {' '.join(args)}")
subprocess.run(args)
elif platform.system() == "Linux":
# Get the PDF reader command
args = shlex.split(self.pdf_viewers[self.global_common.settings.get("open_app")])
# %f, %F, %u, and %U are filenames or URLS -- so replace with the file to open
for i in range(len(args)):
if (
args[i] == "%f"
or args[i] == "%F"
or args[i] == "%u"
or args[i] == "%U"
):
args[i] = filename
# Open as a background process
print(f"Executing: {' '.join(args)}")
subprocess.Popen(args)
def _find_pdf_viewers(self):
pdf_viewers = {}
if platform.system() == "Darwin":
# Get all installed apps that can open PDFs
bundle_identifiers = LaunchServices.LSCopyAllRoleHandlersForContentType(
"com.adobe.pdf", CoreServices.kLSRolesAll
)
for bundle_identifier in bundle_identifiers:
# Get the filesystem path of the app
res = LaunchServices.LSCopyApplicationURLsForBundleIdentifier(
bundle_identifier, None
)
if res[0] is None:
continue
app_url = res[0][0]
app_path = str(app_url.path())
# Load its plist file
plist_path = os.path.join(app_path, "Contents/Info.plist")
# Skip if there's not an Info.plist
if not os.path.exists(plist_path):
continue
with open(plist_path, "rb") as f:
plist_data = f.read()
plist_dict = plistlib.loads(plist_data)
if (
plist_dict.get("CFBundleName")
and plist_dict["CFBundleName"] != "Dangerzone"
):
pdf_viewers[plist_dict["CFBundleName"]] = bundle_identifier
elif platform.system() == "Linux":
# Find all .desktop files
for search_path in [
"/usr/share/applications",
"/usr/local/share/applications",
os.path.expanduser("~/.local/share/applications"),
]:
try:
for filename in os.listdir(search_path):
full_filename = os.path.join(search_path, filename)
if os.path.splitext(filename)[1] == ".desktop":
# See which ones can open PDFs
desktop_entry = DesktopEntry(full_filename)
if (
"application/pdf" in desktop_entry.getMimeTypes()
and desktop_entry.getName() != "dangerzone"
):
pdf_viewers[
desktop_entry.getName()
] = desktop_entry.getExec()
except FileNotFoundError:
pass
return pdf_viewers
def ensure_docker_group_preference(self):
# If the user prefers typing their password
if self.global_common.settings.get("linux_prefers_typing_password") == True:
return True
# Get the docker group
try:
groupinfo = grp.getgrnam("docker")
except:
# Ignore if group is not found
return True
# See if the user is in the group
username = getpass.getuser()
if username not in groupinfo.gr_mem:
# User is not in the docker group, ask if they prefer typing their password
message = "<b>Dangerzone requires Docker</b><br><br>In order to use Docker, your user must be in the 'docker' group or you'll need to type your password each time you run dangerzone.<br><br><b>Adding your user to the 'docker' group is more convenient but less secure</b>, and will require just typing your password once. Which do you prefer?"
return_code = Alert(
self,
self.global_common,
message,
ok_text="I'll type my password each time",
extra_button_text="Add my user to the 'docker' group",
).launch()
if return_code == QtWidgets.QDialog.Accepted:
# Prefers typing password
self.global_common.settings.set("linux_prefers_typing_password", True)
self.global_common.settings.save()
return True
elif return_code == 2:
# Prefers being in the docker group
self.global_common.settings.set("linux_prefers_typing_password", False)
self.global_common.settings.save()
# Add user to the docker group
p = subprocess.run(
[
"/usr/bin/pkexec",
"/usr/sbin/usermod",
"-a",
"-G",
"docker",
username,
]
)
if p.returncode == 0:
message = "Great! Now you must log out of your computer and log back in, and then you can use Dangerzone."
Alert(self, self.global_common, message).launch()
else:
message = "Failed to add your user to the 'docker' group, quitting."
Alert(self, self.global_common, message).launch()
return False
else:
# Cancel
return False
return True
def ensure_docker_service_is_started(self):
if not is_docker_ready(self):
message = "<b>Dangerzone requires Docker</b><br><br>Docker should be installed, but it looks like it's not running in the background.<br><br>Click Ok to try starting the docker service. You will have to type your login password."
if (
Alert(self, self.global_common, message).launch()
== QtWidgets.QDialog.Accepted
):
p = subprocess.run(
[
"/usr/bin/pkexec",
self.global_common.get_resource_path(
"enable_docker_service.sh"
),
]
)
if p.returncode == 0:
# Make sure docker is now ready
if is_docker_ready(self):
return True
else:
message = "Restarting docker appeared to work, but the service still isn't responding, quitting."
Alert(self, self.global_common, message).launch()
else:
message = "Failed to start the docker service, quitting."
Alert(self, self.global_common, message).launch()
return False
return True
class Alert(QtWidgets.QDialog):
def __init__(
self, global_common, gui_common, message, ok_text="Ok", extra_button_text=None
):
super(Alert, self).__init__()
self.global_common = global_common
self.gui_common = gui_common
self.setWindowTitle("dangerzone")
self.setWindowIcon(self.gui_common.get_window_icon())
self.setModal(True)
flags = (
QtCore.Qt.CustomizeWindowHint
| QtCore.Qt.WindowTitleHint
| QtCore.Qt.WindowSystemMenuHint
| QtCore.Qt.WindowCloseButtonHint
| QtCore.Qt.WindowStaysOnTopHint
)
self.setWindowFlags(flags)
logo = QtWidgets.QLabel()
logo.setPixmap(
QtGui.QPixmap.fromImage(
QtGui.QImage(self.global_common.get_resource_path("icon.png"))
)
)
label = QtWidgets.QLabel()
label.setText(message)
label.setWordWrap(True)
message_layout = QtWidgets.QHBoxLayout()
message_layout.addWidget(logo)
message_layout.addSpacing(10)
message_layout.addWidget(label, stretch=1)
ok_button = QtWidgets.QPushButton(ok_text)
ok_button.clicked.connect(self.clicked_ok)
if extra_button_text:
extra_button = QtWidgets.QPushButton(extra_button_text)
extra_button.clicked.connect(self.clicked_extra)
cancel_button = QtWidgets.QPushButton("Cancel")
cancel_button.clicked.connect(self.clicked_cancel)
buttons_layout = QtWidgets.QHBoxLayout()
buttons_layout.addStretch()
buttons_layout.addWidget(ok_button)
if extra_button_text:
buttons_layout.addWidget(extra_button)
buttons_layout.addWidget(cancel_button)
layout = QtWidgets.QVBoxLayout()
layout.addLayout(message_layout)
layout.addSpacing(10)
layout.addLayout(buttons_layout)
self.setLayout(layout)
def clicked_ok(self):
self.done(QtWidgets.QDialog.Accepted)
def clicked_extra(self):
self.done(2)
def clicked_cancel(self):
self.done(QtWidgets.QDialog.Rejected)
def launch(self):
return self.exec_()

View file

@ -8,14 +8,14 @@ import time
import platform import platform
from PySide2 import QtCore, QtGui, QtWidgets from PySide2 import QtCore, QtGui, QtWidgets
from .container import container_runtime from ..container import container_runtime
class AuthorizationFailed(Exception): class AuthorizationFailed(Exception):
pass pass
def is_docker_installed(global_common): def is_docker_installed():
if platform.system() == "Darwin": if platform.system() == "Darwin":
# Does the docker binary exist? # Does the docker binary exist?
if os.path.isdir("/Applications/Docker.app") and os.path.exists( if os.path.isdir("/Applications/Docker.app") and os.path.exists(
@ -55,12 +55,11 @@ def launch_docker_windows(global_common):
class DockerInstaller(QtWidgets.QDialog): class DockerInstaller(QtWidgets.QDialog):
def __init__(self, global_common): def __init__(self, gui_common):
super(DockerInstaller, self).__init__() super(DockerInstaller, self).__init__()
self.global_common = global_common
self.setWindowTitle("dangerzone") self.setWindowTitle("dangerzone")
self.setWindowIcon(self.global_common.get_window_icon()) self.setWindowIcon(gui_common.get_window_icon())
# self.setMinimumHeight(170) # self.setMinimumHeight(170)
label = QtWidgets.QLabel() label = QtWidgets.QLabel()

View file

@ -6,20 +6,21 @@ from PySide2 import QtCore, QtGui, QtWidgets
from .doc_selection_widget import DocSelectionWidget from .doc_selection_widget import DocSelectionWidget
from .settings_widget import SettingsWidget from .settings_widget import SettingsWidget
from .tasks_widget import TasksWidget from .tasks_widget import TasksWidget
from .common import Common from ..common import Common
class MainWindow(QtWidgets.QMainWindow): class MainWindow(QtWidgets.QMainWindow):
delete_window = QtCore.Signal(str) delete_window = QtCore.Signal(str)
def __init__(self, global_common, window_id): def __init__(self, global_common, gui_common, window_id):
super(MainWindow, self).__init__() super(MainWindow, self).__init__()
self.global_common = global_common self.global_common = global_common
self.gui_common = gui_common
self.window_id = window_id self.window_id = window_id
self.common = Common() self.common = Common()
self.setWindowTitle("dangerzone") self.setWindowTitle("dangerzone")
self.setWindowIcon(self.global_common.get_window_icon()) self.setWindowIcon(self.gui_common.get_window_icon())
self.setMinimumWidth(600) self.setMinimumWidth(600)
self.setMinimumHeight(400) self.setMinimumHeight(400)
@ -32,7 +33,7 @@ class MainWindow(QtWidgets.QMainWindow):
) )
) )
header_label = QtWidgets.QLabel("dangerzone") header_label = QtWidgets.QLabel("dangerzone")
header_label.setFont(self.global_common.fixed_font) header_label.setFont(self.gui_common.fixed_font)
header_label.setStyleSheet("QLabel { font-weight: bold; font-size: 50px; }") header_label.setStyleSheet("QLabel { font-weight: bold; font-size: 50px; }")
header_layout = QtWidgets.QHBoxLayout() header_layout = QtWidgets.QHBoxLayout()
header_layout.addStretch() header_layout.addStretch()
@ -47,7 +48,9 @@ class MainWindow(QtWidgets.QMainWindow):
self.doc_selection_widget.show() self.doc_selection_widget.show()
# Settings # Settings
self.settings_widget = SettingsWidget(self.global_common, self.common) self.settings_widget = SettingsWidget(
self.global_common, self.gui_common, self.common
)
self.doc_selection_widget.document_selected.connect( self.doc_selection_widget.document_selected.connect(
self.settings_widget.document_selected self.settings_widget.document_selected
) )
@ -59,7 +62,9 @@ class MainWindow(QtWidgets.QMainWindow):
) )
# Tasks # Tasks
self.tasks_widget = TasksWidget(self.global_common, self.common) self.tasks_widget = TasksWidget(
self.global_common, self.gui_common, self.common
)
self.tasks_widget.close_window.connect(self.close) self.tasks_widget.close_window.connect(self.close)
self.doc_selection_widget.document_selected.connect( self.doc_selection_widget.document_selected.connect(
self.tasks_widget.document_selected self.tasks_widget.document_selected
@ -93,4 +98,4 @@ class MainWindow(QtWidgets.QMainWindow):
self.delete_window.emit(self.window_id) self.delete_window.emit(self.window_id)
if platform.system() != "Darwin": if platform.system() != "Darwin":
self.global_common.app.quit() self.gui_common.app.quit()

View file

@ -1,5 +1,4 @@
import os import os
import subprocess
import platform import platform
from PySide2 import QtCore, QtGui, QtWidgets from PySide2 import QtCore, QtGui, QtWidgets
@ -8,9 +7,10 @@ class SettingsWidget(QtWidgets.QWidget):
start_clicked = QtCore.Signal() start_clicked = QtCore.Signal()
close_window = QtCore.Signal() close_window = QtCore.Signal()
def __init__(self, global_common, common): def __init__(self, global_common, gui_common, common):
super(SettingsWidget, self).__init__() super(SettingsWidget, self).__init__()
self.global_common = global_common self.global_common = global_common
self.gui_common = gui_common
self.common = common self.common = common
# Dangerous document label # Dangerous document label
@ -49,8 +49,8 @@ class SettingsWidget(QtWidgets.QWidget):
) )
self.open_checkbox.clicked.connect(self.update_ui) self.open_checkbox.clicked.connect(self.update_ui)
self.open_combobox = QtWidgets.QComboBox() self.open_combobox = QtWidgets.QComboBox()
for k in self.global_common.pdf_viewers: for k in self.gui_common.pdf_viewers:
self.open_combobox.addItem(k, self.global_common.pdf_viewers[k]) self.open_combobox.addItem(k, self.gui_common.pdf_viewers[k])
open_layout = QtWidgets.QHBoxLayout() open_layout = QtWidgets.QHBoxLayout()
open_layout.addWidget(self.open_checkbox) open_layout.addWidget(self.open_checkbox)
open_layout.addWidget(self.open_combobox) open_layout.addWidget(self.open_combobox)

View file

@ -5,15 +5,16 @@ import platform
import subprocess import subprocess
from PySide2 import QtCore, QtGui, QtWidgets from PySide2 import QtCore, QtGui, QtWidgets
from .tasks import PullImageTask, ConvertToPixels, ConvertToPDF from ..tasks import PullImageTask, ConvertToPixels, ConvertToPDF
class TasksWidget(QtWidgets.QWidget): class TasksWidget(QtWidgets.QWidget):
close_window = QtCore.Signal() close_window = QtCore.Signal()
def __init__(self, global_common, common): def __init__(self, global_common, gui_common, common):
super(TasksWidget, self).__init__() super(TasksWidget, self).__init__()
self.global_common = global_common self.global_common = global_common
self.gui_common = gui_common
self.common = common self.common = common
# Dangerous document label # Dangerous document label
@ -31,7 +32,7 @@ class TasksWidget(QtWidgets.QWidget):
self.task_details.setStyleSheet( self.task_details.setStyleSheet(
"QLabel { background-color: #ffffff; font-size: 12px; padding: 10px; }" "QLabel { background-color: #ffffff; font-size: 12px; padding: 10px; }"
) )
self.task_details.setFont(self.global_common.fixed_font) self.task_details.setFont(self.gui_common.fixed_font)
self.task_details.setAlignment(QtCore.Qt.AlignTop) self.task_details.setAlignment(QtCore.Qt.AlignTop)
self.details_scrollarea = QtWidgets.QScrollArea() self.details_scrollarea = QtWidgets.QScrollArea()
@ -111,7 +112,7 @@ class TasksWidget(QtWidgets.QWidget):
# Open # Open
if self.global_common.settings.get("open"): if self.global_common.settings.get("open"):
self.global_common.open_pdf_viewer(dest_filename) self.gui_common.open_pdf_viewer(dest_filename)
# Clean up # Clean up
self.common.pixel_dir.cleanup() self.common.pixel_dir.cleanup()
@ -122,7 +123,7 @@ class TasksWidget(QtWidgets.QWidget):
# In macOS, just close the window # In macOS, just close the window
self.close_window.emit() self.close_window.emit()
else: else:
self.global_common.app.quit() self.gui_common.app.quit()
def scroll_to_bottom(self, minimum, maximum): def scroll_to_bottom(self, minimum, maximum):
self.details_scrollarea.verticalScrollBar().setValue(maximum) self.details_scrollarea.verticalScrollBar().setValue(maximum)

View file

@ -7,18 +7,12 @@ class Settings:
def __init__(self, common): def __init__(self, common):
self.common = common self.common = common
self.settings_filename = os.path.join(self.common.appdata_path, "settings.json") self.settings_filename = os.path.join(self.common.appdata_path, "settings.json")
if len(self.common.pdf_viewers) == 0:
default_pdf_viewer = None
else:
default_pdf_viewer = list(self.common.pdf_viewers)[0]
self.default_settings = { self.default_settings = {
"save": True, "save": True,
"ocr": True, "ocr": True,
"ocr_language": "English", "ocr_language": "English",
"open": True, "open": True,
"open_app": default_pdf_viewer, "open_app": None,
"update_container": True, "update_container": True,
"linux_prefers_typing_password": None, "linux_prefers_typing_password": None,
} }

1
dev_scripts/dangerzone-cli Symbolic link
View file

@ -0,0 +1 @@
dangerzone

View file

@ -27,6 +27,7 @@ black = "^21.5b2"
[tool.poetry.scripts] [tool.poetry.scripts]
dangerzone = 'dangerzone:main' dangerzone = 'dangerzone:main'
dangerzone-container = 'dangerzone:main' dangerzone-container = 'dangerzone:main'
dangerzone-cli = 'dangerzone:main'
[build-system] [build-system]
requires = ["poetry>=1.1.4"] requires = ["poetry>=1.1.4"]