From 2e477b8a12cf46bf3690a350f3f62fea1a513431 Mon Sep 17 00:00:00 2001 From: deeplow Date: Tue, 27 Sep 2022 19:33:12 +0100 Subject: [PATCH] Initial refactor: GUI one-window multi-document support Allows the user to: a) specify filenames via the terminal (for the GUI) b) select multiple documents via the GUI The conversion process can't yet be started since the settings are broken and disabled (expect mypy complaints). --- dangerzone/gui/__init__.py | 17 ++----- dangerzone/gui/main_window.py | 86 +++++++++++++++++------------------ dangerzone/logic.py | 3 ++ 3 files changed, 49 insertions(+), 57 deletions(-) diff --git a/dangerzone/gui/__init__.py b/dangerzone/gui/__init__.py index 798d52a..4eff8a3 100644 --- a/dangerzone/gui/__init__.py +++ b/dangerzone/gui/__init__.py @@ -92,22 +92,15 @@ def gui_main(filenames: Optional[List[str]]) -> bool: del windows[window_id] # Open a document in a window - def new_window(input_filename: Optional[str] = None) -> None: - document = Document(input_filename) + def new_window(filenames: Optional[List[str]] = []) -> None: window_id = uuid.uuid4().hex - window = MainWindow(dangerzone, window_id, document) + window = MainWindow(dangerzone, window_id) + if filenames: + window.content_widget.doc_selection_widget.document_selected.emit(filenames) window.delete_window.connect(delete_window) windows[window_id] = window - if input_filename: - window.content_widget.doc_selection_widget.document_selected.emit() - - # Open a new window if not filename is passed - if filenames is None: - new_window() - else: - for filename in filenames: - new_window(filename) + new_window(filenames) # Open a new window, if all windows are closed def application_activated() -> None: diff --git a/dangerzone/gui/main_window.py b/dangerzone/gui/main_window.py index 3ab6314..f5bd965 100644 --- a/dangerzone/gui/main_window.py +++ b/dangerzone/gui/main_window.py @@ -5,7 +5,7 @@ import platform import shutil import subprocess import tempfile -from typing import Optional +from typing import List, Optional from colorama import Fore, Style from PySide2 import QtCore, QtGui, QtWidgets @@ -25,13 +25,11 @@ class MainWindow(QtWidgets.QMainWindow): def __init__( self, dangerzone: DangerzoneGui, - window_id: str, - document: Document, + window_id: str ) -> None: super(MainWindow, self).__init__() self.dangerzone = dangerzone self.window_id = window_id - self.document = document self.setWindowTitle("Dangerzone") self.setWindowIcon(self.dangerzone.get_window_icon()) @@ -59,7 +57,7 @@ class MainWindow(QtWidgets.QMainWindow): self.waiting_widget.finished.connect(self.waiting_finished) # Content widget, contains all the window content except waiting widget - self.content_widget = ContentWidget(self.dangerzone, self.document) + self.content_widget = ContentWidget(self.dangerzone) self.content_widget.close_window.connect(self.close) # Only use the waiting widget if container runtime isn't available @@ -202,27 +200,25 @@ class WaitingWidget(QtWidgets.QWidget): class ContentWidget(QtWidgets.QWidget): close_window = QtCore.Signal() - def __init__(self, dangerzone: DangerzoneGui, document: Document) -> None: + def __init__(self, dangerzone: DangerzoneGui) -> None: super(ContentWidget, self).__init__() - self.dangerzone = dangerzone - self.document = document # Doc selection widget - self.doc_selection_widget = DocSelectionWidget(self.document) + self.doc_selection_widget = DocSelectionWidget() self.doc_selection_widget.document_selected.connect(self.document_selected) # Settings - # self.settings_widget = SettingsWidget(self.dangerzone, self.document) + # self.settings_widget = SettingsWidget(self.dangerzone, self.documents) # self.doc_selection_widget.document_selected.connect( - # self.settings_widget.document_selected + # self.settings_widget.document_selected # ) # self.settings_widget.start_clicked.connect(self.start_clicked) # self.settings_widget.close_window.connect(self._close_window) # self.settings_widget.hide() # Convert - self.documents_list = DocumentsListWidget(self.dangerzone, self.document) + self.documents_list = DocumentsListWidget(self.dangerzone) self.documents_list.close_window.connect(self._close_window) self.doc_selection_widget.document_selected.connect( self.documents_list.document_selected @@ -250,11 +246,10 @@ class ContentWidget(QtWidgets.QWidget): class DocSelectionWidget(QtWidgets.QWidget): - document_selected = QtCore.Signal() + document_selected = QtCore.Signal(list) - def __init__(self, document: Document) -> None: + def __init__(self) -> None: super(DocSelectionWidget, self).__init__() - self.document = document # Dangerous document selection self.dangerous_doc_label = QtWidgets.QLabel() @@ -280,24 +275,26 @@ class DocSelectionWidget(QtWidgets.QWidget): self.setLayout(layout) def dangerous_doc_button_clicked(self) -> None: - (filename, _) = QtWidgets.QFileDialog.getOpenFileName( + (filenames, _) = QtWidgets.QFileDialog.getOpenFileNames( self, - "Open document", + "Open documents", filter="Documents (*.pdf *.docx *.doc *.docm *.xlsx *.xls *.pptx *.ppt *.odt *.odg *.odp *.ods *.jpg *.jpeg *.gif *.png *.tif *.tiff)", ) - if filename != "": - self.document.input_filename = filename - self.document_selected.emit() + if filenames == []: + # no files selected + return + + self.document_selected.emit(filenames) class SettingsWidget(QtWidgets.QWidget): start_clicked = QtCore.Signal() close_window = QtCore.Signal() - def __init__(self, dangerzone: DangerzoneGui, document: Document) -> None: + def __init__(self, dangerzone: DangerzoneGui, documents: List[Document]) -> None: super(SettingsWidget, self).__init__() self.dangerzone = dangerzone - self.document = document + self.documents = documents # Dangerous document label self.dangerous_doc_label = QtWidgets.QLabel() @@ -431,26 +428,26 @@ class SettingsWidget(QtWidgets.QWidget): def document_selected(self) -> None: # Update the danger doc label self.dangerous_doc_label.setText( - f"Suspicious: {os.path.basename(self.document.input_filename)}" + f"Suspicious: {os.path.basename(self.documents.input_filename)}" ) - self.save_lineedit.setText(os.path.basename(self.document.output_filename)) + self.save_lineedit.setText(os.path.basename(self.documents.output_filename)) def save_browse_button_clicked(self) -> None: filename = QtWidgets.QFileDialog.getSaveFileName( self, "Save safe PDF as...", - self.document.output_filename, + self.documents.output_filename, filter="Documents (*.pdf)", ) if filename[0] != "": - self.document.output_filename = filename[0] - self.save_lineedit.setText(os.path.basename(self.document.output_filename)) + self.documents.output_filename = filename[0] + self.save_lineedit.setText(os.path.basename(self.documents.output_filename)) def start_button_clicked(self) -> None: if self.save_checkbox.checkState() == QtCore.Qt.Unchecked: # If not saving, then save it to a temp file instead tmp = tempfile.mkstemp(suffix=".pdf", prefix="dangerzone_") - self.document.output_filename = tmp[1] + self.documents.output_filename = tmp[1] # Update settings self.dangerzone.settings.set( @@ -509,20 +506,22 @@ class ConvertThread(QtCore.QThread): class DocumentsListWidget(QtWidgets.QListWidget): close_window = QtCore.Signal() - def __init__(self, dangerzone: DangerzoneGui, document: Document) -> None: + def __init__(self, dangerzone: DangerzoneGui) -> None: super().__init__() - self.document_widgets = [] + self.dangerzone = dangerzone + self.document_widgets: List[DocumentWidget] = [] - item = QtWidgets.QListWidgetItem() - item.setSizeHint(QtCore.QSize(500, 50)) - widget = DocumentWidget(dangerzone, document) - self.document_widgets.append(widget) - self.addItem(item) - self.setItemWidget(item, widget) + def document_selected(self, filenames: list) -> None: + for filename in filenames: + self.dangerzone.add_document(filename) - def document_selected(self) -> None: - for item in self.document_widgets: - item.document_selected() + for document in self.dangerzone.get_unsafe_documents(): + item = QtWidgets.QListWidgetItem() + item.setSizeHint(QtCore.QSize(500, 50)) + widget = DocumentWidget(self.dangerzone, document) + self.addItem(item) + self.setItemWidget(item, widget) + self.document_widgets.append(widget) def start(self) -> None: for item in self.document_widgets: @@ -549,6 +548,9 @@ class DocumentWidget(QtWidgets.QWidget): self.dangerous_doc_label.setStyleSheet( "QLabel { font-size: 16px; font-weight: bold; }" ) + self.dangerous_doc_label.setText( + f"Suspicious: {os.path.basename(self.document.input_filename)}" + ) # Label self.error_image = QtWidgets.QLabel() @@ -580,12 +582,6 @@ class DocumentWidget(QtWidgets.QWidget): layout.addStretch() self.setLayout(layout) - def document_selected(self) -> None: - # Update the danger doc label - self.dangerous_doc_label.setText( - f"Suspicious: {os.path.basename(self.document.input_filename)}" - ) - def start(self) -> None: self.convert_t = ConvertThread(self.dangerzone, self.document) self.convert_t.update.connect(self.update_progress) diff --git a/dangerzone/logic.py b/dangerzone/logic.py index b92870b..1aa2f39 100644 --- a/dangerzone/logic.py +++ b/dangerzone/logic.py @@ -61,6 +61,9 @@ class DangerzoneCore(object): with concurrent.futures.ThreadPoolExecutor(max_workers=max_jobs) as executor: executor.map(convert_doc, self.documents) + def get_unsafe_documents(self) -> List[Document]: + return [doc for doc in self.documents if doc.is_unsafe()] + def get_safe_documents(self) -> List[Document]: return [doc for doc in self.documents if doc.is_safe()]