mirror of
https://github.com/freedomofpress/dangerzone.git
synced 2025-04-29 02:12:36 +02:00

Allowing this would lead to several UI edge-cases related to where the files would be saved. Avoiding this is the easiest solution at the moment. In the future we should consider other options.
185 lines
6 KiB
Python
185 lines
6 KiB
Python
import logging
|
|
import os
|
|
import pipes
|
|
import platform
|
|
import shlex
|
|
import subprocess
|
|
from pathlib import Path
|
|
from typing import Dict
|
|
|
|
from colorama import Fore
|
|
from PySide2 import QtCore, QtGui, QtWidgets
|
|
|
|
if platform.system() == "Linux":
|
|
from xdg.DesktopEntry import DesktopEntry
|
|
|
|
from ..logic import DangerzoneCore
|
|
from ..settings import Settings
|
|
from ..util import get_resource_path
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
|
|
class DangerzoneGui(DangerzoneCore):
|
|
"""
|
|
Singleton of shared state / functionality for the GUI and core app logic
|
|
"""
|
|
|
|
def __init__(self, app: QtWidgets.QApplication) -> None:
|
|
super().__init__()
|
|
|
|
# Qt app
|
|
self.app = app
|
|
|
|
# Only one output dir is supported in the GUI
|
|
self.output_dir: str = ""
|
|
|
|
# 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()
|
|
|
|
# Are we done waiting (for Docker Desktop to be installed, or for container to install)
|
|
self.is_waiting_finished = False
|
|
|
|
def get_window_icon(self) -> QtGui.QIcon:
|
|
if platform.system() == "Windows":
|
|
path = get_resource_path("dangerzone.ico")
|
|
else:
|
|
path = get_resource_path("icon.png")
|
|
return QtGui.QIcon(path)
|
|
|
|
def open_pdf_viewer(self, filename: str) -> None:
|
|
if platform.system() == "Darwin":
|
|
# Open in Preview
|
|
args = ["open", "-a", "Preview.app", filename]
|
|
|
|
# Run
|
|
args_str = " ".join(pipes.quote(s) for s in args)
|
|
log.info(Fore.YELLOW + "> " + Fore.CYAN + args_str)
|
|
subprocess.run(args)
|
|
|
|
elif platform.system() == "Windows":
|
|
os.startfile(Path(filename)) # type: ignore [attr-defined]
|
|
|
|
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
|
|
args_str = " ".join(pipes.quote(s) for s in args)
|
|
log.info(Fore.YELLOW + "> " + Fore.CYAN + args_str)
|
|
subprocess.Popen(args)
|
|
|
|
def _find_pdf_viewers(self) -> Dict[str, str]:
|
|
pdf_viewers: Dict[str, str] = {}
|
|
if 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
|
|
|
|
|
|
class Alert(QtWidgets.QDialog):
|
|
def __init__(
|
|
self,
|
|
dangerzone: DangerzoneGui,
|
|
message: str,
|
|
ok_text: str = "Ok",
|
|
has_cancel: bool = True,
|
|
extra_button_text: str = None,
|
|
) -> None:
|
|
super(Alert, self).__init__()
|
|
self.dangerzone = dangerzone
|
|
|
|
self.setWindowTitle("dangerzone")
|
|
self.setWindowIcon(self.dangerzone.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(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)
|
|
|
|
buttons_layout = QtWidgets.QHBoxLayout()
|
|
buttons_layout.addStretch()
|
|
buttons_layout.addWidget(ok_button)
|
|
if extra_button_text:
|
|
buttons_layout.addWidget(extra_button)
|
|
if has_cancel:
|
|
cancel_button = QtWidgets.QPushButton("Cancel")
|
|
cancel_button.clicked.connect(self.clicked_cancel)
|
|
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) -> None:
|
|
self.done(QtWidgets.QDialog.Accepted)
|
|
|
|
def clicked_extra(self) -> None:
|
|
self.done(2)
|
|
|
|
def clicked_cancel(self) -> None:
|
|
self.done(QtWidgets.QDialog.Rejected)
|
|
|
|
def launch(self) -> int:
|
|
return self.exec_()
|