From c9e32ef82dbe6644487cbdc0f231068faa5f9133 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Tue, 7 Jan 2020 15:32:21 -0800 Subject: [PATCH] Allow selecting a document, then show settings --- Pipfile | 2 + dangerzone/common.py | 40 +++++++++++++++++-- dangerzone/doc_selection_widget.py | 41 +++++++++++++++++++ dangerzone/main_window.py | 16 +++++++- dangerzone/settings.py | 55 +++++++++++++++++++++++++ dangerzone/settings_widget.py | 64 +++++++++++++++++++++++------- 6 files changed, 200 insertions(+), 18 deletions(-) create mode 100644 dangerzone/doc_selection_widget.py create mode 100644 dangerzone/settings.py diff --git a/Pipfile b/Pipfile index f6abad6..3d376ac 100644 --- a/Pipfile +++ b/Pipfile @@ -6,6 +6,8 @@ name = "pypi" [packages] PyQt5 = "*" click = "*" +appdirs = "*" +pyxdg = "*" [dev-packages] black = "*" diff --git a/dangerzone/common.py b/dangerzone/common.py index fc06ed8..59ddc4b 100644 --- a/dangerzone/common.py +++ b/dangerzone/common.py @@ -2,7 +2,11 @@ import sys import os import inspect import tempfile +import appdirs from PyQt5 import QtGui +from xdg.DesktopEntry import DesktopEntry + +from .settings import Settings class Common(object): @@ -14,13 +18,17 @@ class Common(object): # Temporary directory to store pixel data self.pixel_dir = tempfile.TemporaryDirectory() self.safe_dir = tempfile.TemporaryDirectory() - print(f"pixel_dir is: {self.pixel_dir.name}") - print(f"safe_dir is: {self.safe_dir.name}") + print( + f"Temporary directories created, dangerous={self.pixel_dir.name}, safe={self.safe_dir.name}" + ) self.document_filename = None - self.fixed_font = QtGui.QFontDatabase.systemFont(QtGui.QFontDatabase.FixedFont) + self.appdata_path = appdirs.user_config_dir("dangerzone") + + self.pdf_viewers = self._find_pdf_viewers() + self.ocr_languages = { "Afrikaans": "ar", "Amharic": "amh", @@ -184,6 +192,8 @@ class Common(object): "Vietnamese script": "Vietnamese", } + self.settings = Settings(self) + def set_document_filename(self, filename): self.document_filename = filename @@ -203,3 +213,27 @@ class Common(object): resource_path = os.path.join(prefix, filename) return resource_path + + def _find_pdf_viewers(self): + pdf_viewers = {} + + 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": + + desktop_entry = DesktopEntry(full_filename) + if "application/pdf" in desktop_entry.getMimeTypes(): + pdf_viewers[ + desktop_entry.getName() + ] = desktop_entry.getExec() + + except FileNotFoundError: + pass + + return pdf_viewers diff --git a/dangerzone/doc_selection_widget.py b/dangerzone/doc_selection_widget.py new file mode 100644 index 0000000..ecc0aaf --- /dev/null +++ b/dangerzone/doc_selection_widget.py @@ -0,0 +1,41 @@ +from PyQt5 import QtCore, QtGui, QtWidgets + + +class DocSelectionWidget(QtWidgets.QWidget): + document_selected = QtCore.pyqtSignal(str) + + def __init__(self, common): + super(DocSelectionWidget, self).__init__() + self.common = common + + # Dangerous document selection + self.dangerous_doc_label = QtWidgets.QLabel() + self.dangerous_doc_label.hide() + self.dangerous_doc_button = QtWidgets.QPushButton( + "Select dangerous document ..." + ) + self.dangerous_doc_button.setStyleSheet( + "QPushButton { font-weight: bold; padding: 10px; }" + ) + self.dangerous_doc_button.clicked.connect(self.dangerous_doc_button_clicked) + + dangerous_doc_layout = QtWidgets.QHBoxLayout() + dangerous_doc_layout.addStretch() + dangerous_doc_layout.addWidget(self.dangerous_doc_button) + dangerous_doc_layout.addStretch() + + # Layout + layout = QtWidgets.QVBoxLayout() + layout.addStretch() + layout.addLayout(dangerous_doc_layout) + layout.addStretch() + self.setLayout(layout) + + def dangerous_doc_button_clicked(self): + filename = QtWidgets.QFileDialog.getOpenFileName( + self, "Open document", filter="Documents (*.pdf *.docx *.xlsx)", + ) + if filename[0] != "": + filename = filename[0] + self.common.set_document_filename(filename) + self.document_selected.emit(filename) diff --git a/dangerzone/main_window.py b/dangerzone/main_window.py index 5d9bd25..34f911c 100644 --- a/dangerzone/main_window.py +++ b/dangerzone/main_window.py @@ -2,6 +2,7 @@ import shutil import os from PyQt5 import QtCore, QtGui, QtWidgets +from .doc_selection_widget import DocSelectionWidget from .settings_widget import SettingsWidget from .tasks_widget import TasksWidget @@ -33,9 +34,17 @@ class MainWindow(QtWidgets.QMainWindow): header_layout.addWidget(header_label) header_layout.addStretch() + # Doc selection widget + self.doc_selection_widget = DocSelectionWidget(self.common) + self.doc_selection_widget.document_selected.connect(self.document_selected) + self.doc_selection_widget.show() + # Settings self.settings_widget = SettingsWidget(self.common) - self.settings_widget.show() + self.doc_selection_widget.document_selected.connect( + self.settings_widget.document_selected + ) + self.settings_widget.hide() # Tasks self.tasks_widget = TasksWidget(self.common) @@ -44,6 +53,7 @@ class MainWindow(QtWidgets.QMainWindow): # Layout layout = QtWidgets.QVBoxLayout() layout.addLayout(header_layout) + layout.addWidget(self.doc_selection_widget, stretch=1) layout.addWidget(self.settings_widget, stretch=1) layout.addWidget(self.tasks_widget, stretch=1) @@ -53,6 +63,10 @@ class MainWindow(QtWidgets.QMainWindow): self.show() + def document_selected(self, filename): + self.doc_selection_widget.hide() + self.settings_widget.show() + def closeEvent(self, e): e.accept() self.app.quit() diff --git a/dangerzone/settings.py b/dangerzone/settings.py new file mode 100644 index 0000000..77a37ec --- /dev/null +++ b/dangerzone/settings.py @@ -0,0 +1,55 @@ +import os +import json +import appdirs + + +class Settings: + def __init__(self, common): + self.common = common + self.settings_filename = os.path.join(self.common.appdata_path, "settings.json") + + self.default_settings = { + "save": True, + "ocr": True, + "ocr_language": "English", + "open": True, + "open_app": list(self.common.pdf_viewers)[0], + "update_container": True, + } + + self.load() + + def get(self, key): + return self.settings[key] + + def set(self, key, val): + self.settings[key] = val + self.settings.save() + + def load(self): + if os.path.isfile(self.settings_filename): + # If the settings file exists, load it + try: + with open(self.settings_filename, "r") as settings_file: + self.settings = json.load(settings_file) + + # If it's missing any fields, add them from the default settings + for key in self.default_settings: + if key not in self.settings: + self.settings[key] = self.default_settings[key] + + except: + print("Error loading settings, falling back to default") + self.settings = self.default_settings + + else: + # Save with default settings + print("Settings file doesn't exist, starting with default") + self.settings = self.default_settings + + self.save() + + def save(self): + os.makedirs(self.common.appdata_path, exist_ok=True) + with open(self.settings_filename, "w") as settings_file: + json.dump(self.settings, settings_file, indent=4) diff --git a/dangerzone/settings_widget.py b/dangerzone/settings_widget.py index 4724791..e325222 100644 --- a/dangerzone/settings_widget.py +++ b/dangerzone/settings_widget.py @@ -1,3 +1,4 @@ +import os from PyQt5 import QtCore, QtGui, QtWidgets @@ -6,37 +7,30 @@ class SettingsWidget(QtWidgets.QWidget): super(SettingsWidget, self).__init__() self.common = common - # Dangerous document selection + # Dangerous document self.dangerous_doc_label = QtWidgets.QLabel() - self.dangerous_doc_label.hide() - self.dangerous_doc_button = QtWidgets.QPushButton( - "Select dangerous document ..." + self.dangerous_doc_label.setAlignment(QtCore.Qt.AlignCenter) + self.dangerous_doc_label.setStyleSheet( + "QLabel { font-size: 16px; font-weight: bold; color: #572606; padding: 10px; }" ) - self.dangerous_doc_button.setStyleSheet("QPushButton { font-weight: bold }") - - dangerous_doc_layout = QtWidgets.QHBoxLayout() - dangerous_doc_layout.addWidget(self.dangerous_doc_label) - dangerous_doc_layout.addWidget(self.dangerous_doc_button) - dangerous_doc_layout.addStretch() # Save safe version self.save_checkbox = QtWidgets.QCheckBox("Save safe PDF") self.save_lineedit = QtWidgets.QLineEdit() self.save_lineedit.setReadOnly(True) self.save_browse_button = QtWidgets.QPushButton("Save as...") - save_layout = QtWidgets.QHBoxLayout() save_layout.addWidget(self.save_checkbox) save_layout.addWidget(self.save_lineedit) save_layout.addWidget(self.save_browse_button) save_layout.addStretch() + self.save_location = None # OCR document self.ocr_checkbox = QtWidgets.QCheckBox("OCR document, language") self.ocr_combobox = QtWidgets.QComboBox() for k in self.common.ocr_languages: self.ocr_combobox.addItem(k, QtCore.QVariant(self.common.ocr_languages[k])) - ocr_layout = QtWidgets.QHBoxLayout() ocr_layout.addWidget(self.ocr_checkbox) ocr_layout.addWidget(self.ocr_combobox) @@ -45,7 +39,8 @@ class SettingsWidget(QtWidgets.QWidget): # Open safe document self.open_checkbox = QtWidgets.QCheckBox("Open safe document") self.open_combobox = QtWidgets.QComboBox() - + for k in self.common.pdf_viewers: + self.open_combobox.addItem(k, QtCore.QVariant(self.common.pdf_viewers[k])) open_layout = QtWidgets.QHBoxLayout() open_layout.addWidget(self.open_checkbox) open_layout.addWidget(self.open_combobox) @@ -69,7 +64,7 @@ class SettingsWidget(QtWidgets.QWidget): # Layout layout = QtWidgets.QVBoxLayout() - layout.addLayout(dangerous_doc_layout) + layout.addWidget(self.dangerous_doc_label) layout.addLayout(save_layout) layout.addLayout(ocr_layout) layout.addLayout(open_layout) @@ -77,3 +72,44 @@ class SettingsWidget(QtWidgets.QWidget): layout.addLayout(button_layout) layout.addStretch() self.setLayout(layout) + + # Load values from settings + if self.common.settings.get("save"): + self.save_checkbox.setCheckState(QtCore.Qt.Checked) + else: + self.save_checkbox.setCheckState(QtCore.Qt.Unchecked) + + if self.common.settings.get("ocr"): + self.ocr_checkbox.setCheckState(QtCore.Qt.Checked) + else: + self.ocr_checkbox.setCheckState(QtCore.Qt.Unchecked) + + index = self.ocr_combobox.findText(self.common.settings.get("ocr_language")) + if index != -1: + self.ocr_combobox.setCurrentIndex(index) + + if self.common.settings.get("open"): + self.open_checkbox.setCheckState(QtCore.Qt.Checked) + else: + self.open_checkbox.setCheckState(QtCore.Qt.Unchecked) + + index = self.open_combobox.findText(self.common.settings.get("open_app")) + if index != -1: + self.open_combobox.setCurrentIndex(index) + + if self.common.settings.get("update_container"): + self.update_checkbox.setCheckState(QtCore.Qt.Checked) + else: + self.update_checkbox.setCheckState(QtCore.Qt.Unchecked) + + def document_selected(self, filename): + # Update the danger doc label + self.dangerous_doc_label.setText( + f"Dangerous: {os.path.basename(self.common.document_filename)}" + ) + + # Update the save location + self.save_location = ( + f"{os.path.splitext(self.common.document_filename)[0]}-safe.pdf" + ) + self.save_lineedit.setText(os.path.basename(self.save_location))