diff --git a/dangerzone/global_common.py b/dangerzone/global_common.py index f7de028..53f259f 100644 --- a/dangerzone/global_common.py +++ b/dangerzone/global_common.py @@ -38,6 +38,9 @@ class GlobalCommon(object): # dangerzone-container path self.dz_container_path = self.get_dangerzone_container_path() + # VM object, if available + self.vm = None + # Languages supported by tesseract self.ocr_languages = { "Afrikaans": "ar", diff --git a/dangerzone/gui/__init__.py b/dangerzone/gui/__init__.py index 1714919..c62cf23 100644 --- a/dangerzone/gui/__init__.py +++ b/dangerzone/gui/__init__.py @@ -105,11 +105,12 @@ def gui_main(custom_container, filename): # The dangerzone VM (Mac-only) if platform.system() == "Darwin": vm = Vm(global_common) + global_common.vm = vm else: vm = None # Create the system tray - systray = SysTray(global_common, gui_common, app, vm) + systray = SysTray(global_common, gui_common, app) # Start the VM if vm: @@ -131,7 +132,7 @@ def gui_main(custom_container, filename): window = windows[list(windows.keys())[0]] else: window_id = uuid.uuid4().hex - window = MainWindow(global_common, gui_common, vm, window_id) + window = MainWindow(global_common, gui_common, window_id) window.delete_window.connect(delete_window) windows[window_id] = window diff --git a/dangerzone/gui/doc_selection_widget.py b/dangerzone/gui/doc_selection_widget.py deleted file mode 100644 index c7d8506..0000000 --- a/dangerzone/gui/doc_selection_widget.py +++ /dev/null @@ -1,43 +0,0 @@ -from PySide2 import QtCore, QtGui, QtWidgets - - -class DocSelectionWidget(QtWidgets.QWidget): - document_selected = QtCore.Signal() - - 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 *.doc *.docm *.xlsx *.xls *.pptx *.ppt *.odt *.odg *.odp *.ods *.jpg *.jpeg *.gif *.png *.tif *.tiff)", - ) - if filename[0] != "": - filename = filename[0] - self.common.document_filename = filename - self.document_selected.emit() diff --git a/dangerzone/gui/main_window.py b/dangerzone/gui/main_window.py index ed0235c..b82ef50 100644 --- a/dangerzone/gui/main_window.py +++ b/dangerzone/gui/main_window.py @@ -1,23 +1,19 @@ +from dangerzone import global_common import shutil import os import platform from PySide2 import QtCore, QtGui, QtWidgets -from .waiting_widget import WaitingWidget -from .doc_selection_widget import DocSelectionWidget -from .settings_widget import SettingsWidget -from .tasks_widget import TasksWidget from ..common import Common class MainWindow(QtWidgets.QMainWindow): delete_window = QtCore.Signal(str) - def __init__(self, global_common, gui_common, vm, window_id): + def __init__(self, global_common, gui_common, window_id): super(MainWindow, self).__init__() self.global_common = global_common self.gui_common = gui_common - self.vm = vm self.window_id = window_id self.common = Common() @@ -45,7 +41,7 @@ class MainWindow(QtWidgets.QMainWindow): header_layout.addStretch() # Waiting widget - self.waiting_widget = WaitingWidget(self.gui_common, self.vm) + self.waiting_widget = WaitingWidget(self.global_common, self.gui_common) self.waiting_widget.vm_started.connect(self.vm_started) # Doc selection widget @@ -53,7 +49,7 @@ class MainWindow(QtWidgets.QMainWindow): self.doc_selection_widget.document_selected.connect(self.document_selected) # Only use the waiting widget if we have a VM - if self.vm: + if self.global_common.vm: self.waiting_widget.show() self.doc_selection_widget.hide() else: @@ -114,3 +110,380 @@ class MainWindow(QtWidgets.QMainWindow): if platform.system() != "Darwin": self.gui_common.app.quit() + + +class WaitingWidget(QtWidgets.QWidget): + vm_started = QtCore.Signal() + + def __init__(self, global_common, gui_common): + super(WaitingWidget, self).__init__() + self.global_common = global_common + self.gui_common = gui_common + + self.global_common.vm.vm_state_change.connect(self.vm_state_change) + + self.label = QtWidgets.QLabel( + "Waiting for the Dangerzone virtual machine to start..." + ) + self.label.setAlignment(QtCore.Qt.AlignCenter) + self.label.setStyleSheet("QLabel { font-size: 20px; }") + + # Layout + layout = QtWidgets.QVBoxLayout() + layout.addStretch() + layout.addWidget(self.label) + layout.addStretch() + self.setLayout(layout) + + def vm_state_change(self, state): + if state == self.global_common.vm.STATE_ON: + self.vm_started.emit() + elif state == self.global_common.vm.STATE_FAIL: + self.label.setText("Dangerzone virtual machine failed to start :(") + + +class DocSelectionWidget(QtWidgets.QWidget): + document_selected = QtCore.Signal() + + 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 *.doc *.docm *.xlsx *.xls *.pptx *.ppt *.odt *.odg *.odp *.ods *.jpg *.jpeg *.gif *.png *.tif *.tiff)", + ) + if filename[0] != "": + filename = filename[0] + self.common.document_filename = filename + self.document_selected.emit() + + +class SettingsWidget(QtWidgets.QWidget): + start_clicked = QtCore.Signal() + close_window = QtCore.Signal() + + def __init__(self, global_common, gui_common, common): + super(SettingsWidget, self).__init__() + self.global_common = global_common + self.gui_common = gui_common + self.common = common + + # Dangerous document label + self.dangerous_doc_label = QtWidgets.QLabel() + self.dangerous_doc_label.setAlignment(QtCore.Qt.AlignCenter) + self.dangerous_doc_label.setStyleSheet( + "QLabel { font-size: 16px; font-weight: bold; color: #572606; }" + ) + + # Save safe version + self.save_checkbox = QtWidgets.QCheckBox("Save safe PDF") + self.save_checkbox.clicked.connect(self.update_ui) + self.save_label = QtWidgets.QLabel("Save safe PDF") # For Windows + self.save_label.hide() + if platform.system() == "Windows": + # In Windows, users must save the PDF, since they can't open it + self.save_checkbox.setCheckState(QtCore.Qt.Checked) + self.save_checkbox.setEnabled(False) + self.save_checkbox.hide() + self.save_label.show() + self.save_lineedit = QtWidgets.QLineEdit() + self.save_lineedit.setReadOnly(True) + self.save_browse_button = QtWidgets.QPushButton("Save as...") + self.save_browse_button.clicked.connect(self.save_browse_button_clicked) + save_layout = QtWidgets.QHBoxLayout() + save_layout.addWidget(self.save_checkbox) + save_layout.addWidget(self.save_label) + save_layout.addWidget(self.save_lineedit) + save_layout.addWidget(self.save_browse_button) + save_layout.addStretch() + + # Open safe document + if platform.system() == "Darwin": + self.open_checkbox = QtWidgets.QCheckBox( + "Open safe document after converting" + ) + self.open_checkbox.clicked.connect(self.update_ui) + + elif platform.system() != "Linux": + self.open_checkbox = QtWidgets.QCheckBox( + "Open safe document after converting, using" + ) + self.open_checkbox.clicked.connect(self.update_ui) + self.open_combobox = QtWidgets.QComboBox() + for k in self.gui_common.pdf_viewers: + self.open_combobox.addItem(k, self.gui_common.pdf_viewers[k]) + + if platform.system() == "Darwin" or platform.system() == "Linux": + open_layout = QtWidgets.QHBoxLayout() + open_layout.addWidget(self.open_checkbox) + if platform.system() == "Linux": + open_layout.addWidget(self.open_combobox) + open_layout.addStretch() + + # OCR document + self.ocr_checkbox = QtWidgets.QCheckBox("OCR document, language") + self.ocr_combobox = QtWidgets.QComboBox() + for k in self.global_common.ocr_languages: + self.ocr_combobox.addItem(k, self.global_common.ocr_languages[k]) + ocr_layout = QtWidgets.QHBoxLayout() + ocr_layout.addWidget(self.ocr_checkbox) + ocr_layout.addWidget(self.ocr_combobox) + ocr_layout.addStretch() + + # Button + self.start_button = QtWidgets.QPushButton("Convert to Safe Document") + self.start_button.clicked.connect(self.start_button_clicked) + self.start_button.setStyleSheet( + "QPushButton { font-size: 16px; font-weight: bold; }" + ) + button_layout = QtWidgets.QHBoxLayout() + button_layout.addStretch() + button_layout.addWidget(self.start_button) + button_layout.addStretch() + + # Layout + layout = QtWidgets.QVBoxLayout() + layout.addWidget(self.dangerous_doc_label) + layout.addSpacing(20) + layout.addLayout(save_layout) + if platform.system() != "Windows": + layout.addLayout(open_layout) + layout.addLayout(ocr_layout) + layout.addSpacing(20) + layout.addLayout(button_layout) + layout.addStretch() + self.setLayout(layout) + + # Load values from settings + if self.global_common.settings.get("save"): + self.save_checkbox.setCheckState(QtCore.Qt.Checked) + else: + self.save_checkbox.setCheckState(QtCore.Qt.Unchecked) + + if self.global_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.global_common.settings.get("ocr_language") + ) + if index != -1: + self.ocr_combobox.setCurrentIndex(index) + + if platform.system() == "Darwin" or platform.system() == "Linux": + if self.global_common.settings.get("open"): + self.open_checkbox.setCheckState(QtCore.Qt.Checked) + else: + self.open_checkbox.setCheckState(QtCore.Qt.Unchecked) + + if platform.system() == "Linux": + index = self.open_combobox.findText( + self.global_common.settings.get("open_app") + ) + if index != -1: + self.open_combobox.setCurrentIndex(index) + + def update_ui(self): + if platform.system() == "Windows": + # Because the save checkbox is always checked in Windows, the + # start button can be enabled + self.start_button.setEnabled(True) + else: + # Either save or open must be checked + if ( + self.save_checkbox.checkState() == QtCore.Qt.Checked + or self.open_checkbox.checkState() == QtCore.Qt.Checked + ): + self.start_button.setEnabled(True) + else: + self.start_button.setEnabled(False) + + def document_selected(self): + # Update the danger doc label + self.dangerous_doc_label.setText( + f"Dangerous: {os.path.basename(self.common.document_filename)}" + ) + + # Update the save location + save_filename = f"{os.path.splitext(self.common.document_filename)[0]}-safe.pdf" + self.common.save_filename = save_filename + self.save_lineedit.setText(os.path.basename(save_filename)) + + def save_browse_button_clicked(self): + filename = QtWidgets.QFileDialog.getSaveFileName( + self, + "Save safe PDF as...", + self.common.save_filename, + filter="Documents (*.pdf)", + ) + if filename[0] != "": + self.common.save_filename = filename[0] + self.save_lineedit.setText(os.path.basename(self.common.save_filename)) + + def start_button_clicked(self): + # Update settings + self.global_common.settings.set( + "save", self.save_checkbox.checkState() == QtCore.Qt.Checked + ) + self.global_common.settings.set( + "ocr", self.ocr_checkbox.checkState() == QtCore.Qt.Checked + ) + self.global_common.settings.set("ocr_language", self.ocr_combobox.currentText()) + if platform.system() == "Darwin" or platform.system() == "Linux": + self.global_common.settings.set( + "open", self.open_checkbox.checkState() == QtCore.Qt.Checked + ) + if platform.system() == "Linux": + self.global_common.settings.set( + "open_app", self.open_combobox.currentText() + ) + self.global_common.settings.save() + + # Start! + self.start_clicked.emit() + + +class TasksWidget(QtWidgets.QWidget): + close_window = QtCore.Signal() + + def __init__(self, global_common, gui_common, common): + super(TasksWidget, self).__init__() + self.global_common = global_common + self.gui_common = gui_common + self.common = common + + # Dangerous document label + self.dangerous_doc_label = QtWidgets.QLabel() + self.dangerous_doc_label.setAlignment(QtCore.Qt.AlignCenter) + self.dangerous_doc_label.setStyleSheet( + "QLabel { font-size: 16px; font-weight: bold; color: #572606; }" + ) + + self.task_label = QtWidgets.QLabel() + self.task_label.setAlignment(QtCore.Qt.AlignCenter) + self.task_label.setStyleSheet("QLabel { font-weight: bold; font-size: 20px; }") + + self.task_details = QtWidgets.QLabel() + self.task_details.setStyleSheet( + "QLabel { background-color: #ffffff; font-size: 12px; padding: 10px; }" + ) + self.task_details.setFont(self.gui_common.fixed_font) + self.task_details.setAlignment(QtCore.Qt.AlignTop) + + self.details_scrollarea = QtWidgets.QScrollArea() + self.details_scrollarea.setWidgetResizable(True) + self.details_scrollarea.setWidget(self.task_details) + self.details_scrollarea.verticalScrollBar().rangeChanged.connect( + self.scroll_to_bottom + ) + + # Layout + layout = QtWidgets.QVBoxLayout() + layout.addWidget(self.dangerous_doc_label) + layout.addSpacing(20) + layout.addWidget(self.task_label) + layout.addWidget(self.details_scrollarea) + self.setLayout(layout) + + self.tasks = [] + + def document_selected(self): + # Update the danger doc label + self.dangerous_doc_label.setText( + f"Dangerous: {os.path.basename(self.common.document_filename)}" + ) + + def start(self): + self.tasks += [ConvertToPixels, ConvertToPDF] + self.next_task() + + def next_task(self): + if len(self.tasks) == 0: + self.all_done() + return + + self.task_details.setText("") + + self.current_task = self.tasks.pop(0)(self.global_common, self.common) + self.current_task.update_label.connect(self.update_label) + self.current_task.update_details.connect(self.update_details) + self.current_task.task_finished.connect(self.next_task) + self.current_task.task_failed.connect(self.task_failed) + self.current_task.start() + + def update_label(self, s): + self.task_label.setText(s) + + def update_details(self, s): + self.task_details.setText(s) + + def task_failed(self, err): + self.task_label.setText("Failed :(") + self.task_details.setWordWrap(True) + text = self.task_details.text() + self.task_details.setText( + f"{text}\n\n--\n\nDirectory with pixel data: {self.common.pixel_dir.name}\n\n{err}" + ) + + def all_done(self): + # Save safe PDF + source_filename = f"{self.common.safe_dir.name}/safe-output-compressed.pdf" + if self.global_common.settings.get("save"): + dest_filename = self.common.save_filename + else: + # If not saving, then save it to a temp file instead + tmp = tempfile.mkstemp(suffix=".pdf", prefix="dangerzone_") + dest_filename = tmp[1] + shutil.move(source_filename, dest_filename) + + # In Windows, open Explorer with the safe PDF in focus + if platform.system() == "Windows": + dest_filename_windows = dest_filename.replace("/", "\\") + subprocess.Popen( + f'explorer.exe /select,"{dest_filename_windows}"', shell=True + ) + + # Open + if self.global_common.settings.get("open"): + self.gui_common.open_pdf_viewer(dest_filename) + + # Clean up + self.common.pixel_dir.cleanup() + self.common.safe_dir.cleanup() + + # Quit + if platform.system() == "Darwin": + # In macOS, just close the window + self.close_window.emit() + else: + self.gui_common.app.quit() + + def scroll_to_bottom(self, minimum, maximum): + self.details_scrollarea.verticalScrollBar().setValue(maximum) diff --git a/dangerzone/gui/settings_widget.py b/dangerzone/gui/settings_widget.py deleted file mode 100644 index eeb99cf..0000000 --- a/dangerzone/gui/settings_widget.py +++ /dev/null @@ -1,189 +0,0 @@ -import os -import platform -from PySide2 import QtCore, QtGui, QtWidgets - - -class SettingsWidget(QtWidgets.QWidget): - start_clicked = QtCore.Signal() - close_window = QtCore.Signal() - - def __init__(self, global_common, gui_common, common): - super(SettingsWidget, self).__init__() - self.global_common = global_common - self.gui_common = gui_common - self.common = common - - # Dangerous document label - self.dangerous_doc_label = QtWidgets.QLabel() - self.dangerous_doc_label.setAlignment(QtCore.Qt.AlignCenter) - self.dangerous_doc_label.setStyleSheet( - "QLabel { font-size: 16px; font-weight: bold; color: #572606; }" - ) - - # Save safe version - self.save_checkbox = QtWidgets.QCheckBox("Save safe PDF") - self.save_checkbox.clicked.connect(self.update_ui) - self.save_label = QtWidgets.QLabel("Save safe PDF") # For Windows - self.save_label.hide() - if platform.system() == "Windows": - # In Windows, users must save the PDF, since they can't open it - self.save_checkbox.setCheckState(QtCore.Qt.Checked) - self.save_checkbox.setEnabled(False) - self.save_checkbox.hide() - self.save_label.show() - self.save_lineedit = QtWidgets.QLineEdit() - self.save_lineedit.setReadOnly(True) - self.save_browse_button = QtWidgets.QPushButton("Save as...") - self.save_browse_button.clicked.connect(self.save_browse_button_clicked) - save_layout = QtWidgets.QHBoxLayout() - save_layout.addWidget(self.save_checkbox) - save_layout.addWidget(self.save_label) - save_layout.addWidget(self.save_lineedit) - save_layout.addWidget(self.save_browse_button) - save_layout.addStretch() - - # Open safe document - if platform.system() == "Darwin": - self.open_checkbox = QtWidgets.QCheckBox( - "Open safe document after converting" - ) - self.open_checkbox.clicked.connect(self.update_ui) - - elif platform.system() != "Linux": - self.open_checkbox = QtWidgets.QCheckBox( - "Open safe document after converting, using" - ) - self.open_checkbox.clicked.connect(self.update_ui) - self.open_combobox = QtWidgets.QComboBox() - for k in self.gui_common.pdf_viewers: - self.open_combobox.addItem(k, self.gui_common.pdf_viewers[k]) - - if platform.system() == "Darwin" or platform.system() == "Linux": - open_layout = QtWidgets.QHBoxLayout() - open_layout.addWidget(self.open_checkbox) - if platform.system() == "Linux": - open_layout.addWidget(self.open_combobox) - open_layout.addStretch() - - # OCR document - self.ocr_checkbox = QtWidgets.QCheckBox("OCR document, language") - self.ocr_combobox = QtWidgets.QComboBox() - for k in self.global_common.ocr_languages: - self.ocr_combobox.addItem(k, self.global_common.ocr_languages[k]) - ocr_layout = QtWidgets.QHBoxLayout() - ocr_layout.addWidget(self.ocr_checkbox) - ocr_layout.addWidget(self.ocr_combobox) - ocr_layout.addStretch() - - # Button - self.start_button = QtWidgets.QPushButton("Convert to Safe Document") - self.start_button.clicked.connect(self.start_button_clicked) - self.start_button.setStyleSheet( - "QPushButton { font-size: 16px; font-weight: bold; }" - ) - button_layout = QtWidgets.QHBoxLayout() - button_layout.addStretch() - button_layout.addWidget(self.start_button) - button_layout.addStretch() - - # Layout - layout = QtWidgets.QVBoxLayout() - layout.addWidget(self.dangerous_doc_label) - layout.addSpacing(20) - layout.addLayout(save_layout) - if platform.system() != "Windows": - layout.addLayout(open_layout) - layout.addLayout(ocr_layout) - layout.addSpacing(20) - layout.addLayout(button_layout) - layout.addStretch() - self.setLayout(layout) - - # Load values from settings - if self.global_common.settings.get("save"): - self.save_checkbox.setCheckState(QtCore.Qt.Checked) - else: - self.save_checkbox.setCheckState(QtCore.Qt.Unchecked) - - if self.global_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.global_common.settings.get("ocr_language") - ) - if index != -1: - self.ocr_combobox.setCurrentIndex(index) - - if platform.system() == "Darwin" or platform.system() == "Linux": - if self.global_common.settings.get("open"): - self.open_checkbox.setCheckState(QtCore.Qt.Checked) - else: - self.open_checkbox.setCheckState(QtCore.Qt.Unchecked) - - if platform.system() == "Linux": - index = self.open_combobox.findText( - self.global_common.settings.get("open_app") - ) - if index != -1: - self.open_combobox.setCurrentIndex(index) - - def update_ui(self): - if platform.system() == "Windows": - # Because the save checkbox is always checked in Windows, the - # start button can be enabled - self.start_button.setEnabled(True) - else: - # Either save or open must be checked - if ( - self.save_checkbox.checkState() == QtCore.Qt.Checked - or self.open_checkbox.checkState() == QtCore.Qt.Checked - ): - self.start_button.setEnabled(True) - else: - self.start_button.setEnabled(False) - - def document_selected(self): - # Update the danger doc label - self.dangerous_doc_label.setText( - f"Dangerous: {os.path.basename(self.common.document_filename)}" - ) - - # Update the save location - save_filename = f"{os.path.splitext(self.common.document_filename)[0]}-safe.pdf" - self.common.save_filename = save_filename - self.save_lineedit.setText(os.path.basename(save_filename)) - - def save_browse_button_clicked(self): - filename = QtWidgets.QFileDialog.getSaveFileName( - self, - "Save safe PDF as...", - self.common.save_filename, - filter="Documents (*.pdf)", - ) - if filename[0] != "": - self.common.save_filename = filename[0] - self.save_lineedit.setText(os.path.basename(self.common.save_filename)) - - def start_button_clicked(self): - # Update settings - self.global_common.settings.set( - "save", self.save_checkbox.checkState() == QtCore.Qt.Checked - ) - self.global_common.settings.set( - "ocr", self.ocr_checkbox.checkState() == QtCore.Qt.Checked - ) - self.global_common.settings.set("ocr_language", self.ocr_combobox.currentText()) - if platform.system() == "Darwin" or platform.system() == "Linux": - self.global_common.settings.set( - "open", self.open_checkbox.checkState() == QtCore.Qt.Checked - ) - if platform.system() == "Linux": - self.global_common.settings.set( - "open_app", self.open_combobox.currentText() - ) - self.global_common.settings.save() - - # Start! - self.start_clicked.emit() diff --git a/dangerzone/gui/systray.py b/dangerzone/gui/systray.py index 4dcfce3..49d4af0 100644 --- a/dangerzone/gui/systray.py +++ b/dangerzone/gui/systray.py @@ -3,12 +3,11 @@ from PySide2 import QtWidgets class SysTray(QtWidgets.QSystemTrayIcon): - def __init__(self, global_common, gui_common, app, vm): + def __init__(self, global_common, gui_common, app): super(SysTray, self).__init__() self.global_common = global_common self.gui_common = gui_common self.app = app - self.vm = vm self.setIcon(self.gui_common.get_window_icon()) @@ -27,22 +26,22 @@ class SysTray(QtWidgets.QSystemTrayIcon): self.setContextMenu(menu) self.show() - if self.vm: - self.vm.vm_state_change.connect(self.vm_state_change) + if self.global_common.vm: + self.global_common.vm.vm_state_change.connect(self.vm_state_change) def vm_state_change(self, state): - if state == self.vm.STATE_OFF: + if state == self.global_common.vm.STATE_OFF: self.status_action.setText("Dangerzone VM is off") self.restart_action.setEnabled(True) - elif state == self.vm.STATE_STARTING: + elif state == self.global_common.vm.STATE_STARTING: self.status_action.setText("Dangerzone VM is starting...") self.restart_action.setEnabled(False) - elif state == self.vm.STATE_ON: + elif state == self.global_common.vm.STATE_ON: self.status_action.setText("Dangerzone VM is running") self.restart_action.setEnabled(True) def restart_clicked(self): - self.vm.restart() + self.global_common.vm.restart() def quit_clicked(self): self.app.quit() diff --git a/dangerzone/gui/tasks_widget.py b/dangerzone/gui/tasks_widget.py deleted file mode 100644 index c05b148..0000000 --- a/dangerzone/gui/tasks_widget.py +++ /dev/null @@ -1,127 +0,0 @@ -import shutil -import tempfile -import os -import platform -import subprocess -from PySide2 import QtCore, QtGui, QtWidgets - -from .tasks import ConvertToPixels, ConvertToPDF - - -class TasksWidget(QtWidgets.QWidget): - close_window = QtCore.Signal() - - def __init__(self, global_common, gui_common, common): - super(TasksWidget, self).__init__() - self.global_common = global_common - self.gui_common = gui_common - self.common = common - - # Dangerous document label - self.dangerous_doc_label = QtWidgets.QLabel() - self.dangerous_doc_label.setAlignment(QtCore.Qt.AlignCenter) - self.dangerous_doc_label.setStyleSheet( - "QLabel { font-size: 16px; font-weight: bold; color: #572606; }" - ) - - self.task_label = QtWidgets.QLabel() - self.task_label.setAlignment(QtCore.Qt.AlignCenter) - self.task_label.setStyleSheet("QLabel { font-weight: bold; font-size: 20px; }") - - self.task_details = QtWidgets.QLabel() - self.task_details.setStyleSheet( - "QLabel { background-color: #ffffff; font-size: 12px; padding: 10px; }" - ) - self.task_details.setFont(self.gui_common.fixed_font) - self.task_details.setAlignment(QtCore.Qt.AlignTop) - - self.details_scrollarea = QtWidgets.QScrollArea() - self.details_scrollarea.setWidgetResizable(True) - self.details_scrollarea.setWidget(self.task_details) - self.details_scrollarea.verticalScrollBar().rangeChanged.connect( - self.scroll_to_bottom - ) - - # Layout - layout = QtWidgets.QVBoxLayout() - layout.addWidget(self.dangerous_doc_label) - layout.addSpacing(20) - layout.addWidget(self.task_label) - layout.addWidget(self.details_scrollarea) - self.setLayout(layout) - - self.tasks = [] - - def document_selected(self): - # Update the danger doc label - self.dangerous_doc_label.setText( - f"Dangerous: {os.path.basename(self.common.document_filename)}" - ) - - def start(self): - self.tasks += [ConvertToPixels, ConvertToPDF] - self.next_task() - - def next_task(self): - if len(self.tasks) == 0: - self.all_done() - return - - self.task_details.setText("") - - self.current_task = self.tasks.pop(0)(self.global_common, self.common) - self.current_task.update_label.connect(self.update_label) - self.current_task.update_details.connect(self.update_details) - self.current_task.task_finished.connect(self.next_task) - self.current_task.task_failed.connect(self.task_failed) - self.current_task.start() - - def update_label(self, s): - self.task_label.setText(s) - - def update_details(self, s): - self.task_details.setText(s) - - def task_failed(self, err): - self.task_label.setText("Failed :(") - self.task_details.setWordWrap(True) - text = self.task_details.text() - self.task_details.setText( - f"{text}\n\n--\n\nDirectory with pixel data: {self.common.pixel_dir.name}\n\n{err}" - ) - - def all_done(self): - # Save safe PDF - source_filename = f"{self.common.safe_dir.name}/safe-output-compressed.pdf" - if self.global_common.settings.get("save"): - dest_filename = self.common.save_filename - else: - # If not saving, then save it to a temp file instead - tmp = tempfile.mkstemp(suffix=".pdf", prefix="dangerzone_") - dest_filename = tmp[1] - shutil.move(source_filename, dest_filename) - - # In Windows, open Explorer with the safe PDF in focus - if platform.system() == "Windows": - dest_filename_windows = dest_filename.replace("/", "\\") - subprocess.Popen( - f'explorer.exe /select,"{dest_filename_windows}"', shell=True - ) - - # Open - if self.global_common.settings.get("open"): - self.gui_common.open_pdf_viewer(dest_filename) - - # Clean up - self.common.pixel_dir.cleanup() - self.common.safe_dir.cleanup() - - # Quit - if platform.system() == "Darwin": - # In macOS, just close the window - self.close_window.emit() - else: - self.gui_common.app.quit() - - def scroll_to_bottom(self, minimum, maximum): - self.details_scrollarea.verticalScrollBar().setValue(maximum) diff --git a/dangerzone/gui/waiting_widget.py b/dangerzone/gui/waiting_widget.py deleted file mode 100644 index dc0884e..0000000 --- a/dangerzone/gui/waiting_widget.py +++ /dev/null @@ -1,31 +0,0 @@ -from PySide2 import QtCore, QtWidgets - - -class WaitingWidget(QtWidgets.QWidget): - vm_started = QtCore.Signal() - - def __init__(self, gui_common, vm): - super(WaitingWidget, self).__init__() - self.gui_common = gui_common - self.vm = vm - - self.vm.vm_state_change.connect(self.vm_state_change) - - self.label = QtWidgets.QLabel( - "Waiting for the Dangerzone virtual machine to start..." - ) - self.label.setAlignment(QtCore.Qt.AlignCenter) - self.label.setStyleSheet("QLabel { font-size: 20px; }") - - # Layout - layout = QtWidgets.QVBoxLayout() - layout.addStretch() - layout.addWidget(self.label) - layout.addStretch() - self.setLayout(layout) - - def vm_state_change(self, state): - if state == self.vm.STATE_ON: - self.vm_started.emit() - elif state == self.vm.STATE_FAIL: - self.label.setText("Dangerzone virtual machine failed to start :(")