diff --git a/dangerzone/__init__.py b/dangerzone/__init__.py index 880b9b2..69fb9db 100644 --- a/dangerzone/__init__.py +++ b/dangerzone/__init__.py @@ -1,11 +1,6 @@ import os import sys -import appdirs - -CONTAINER_NAME = "dangerzone.rocks/dangerzone" -APPDATA_PATH = appdirs.user_config_dir("dangerzone") - if "DANGERZONE_MODE" in os.environ: mode = os.environ["DANGERZONE_MODE"] else: diff --git a/dangerzone/cli.py b/dangerzone/cli.py index ee6f039..412703d 100644 --- a/dangerzone/cli.py +++ b/dangerzone/cli.py @@ -7,6 +7,7 @@ from colorama import Fore, Style from .global_common import GlobalCommon from .common import Common from .container import convert +import dangerzone.util as dzutil def print_header(s): @@ -73,14 +74,14 @@ def cli_main(output_filename, ocr_lang, filename): # Validate OCR language if ocr_lang: valid = False - for lang in global_common.ocr_languages: - if global_common.ocr_languages[lang] == ocr_lang: + for lang in dzutil.OCR_LANGUAGES: + if dzutil.OCR_LANGUAGES[lang] == ocr_lang: valid = True break if not valid: click.echo("Invalid OCR language code. Valid language codes:") - for lang in global_common.ocr_languages: - click.echo(f"{global_common.ocr_languages[lang]}: {lang}") + for lang in dzutil.OCR_LANGUAGES: + click.echo(f"{dzutil.OCR_LANGUAGES[lang]}: {lang}") return # Ensure container is installed diff --git a/dangerzone/common.py b/dangerzone/common.py index 7d1f4d9..52c99a0 100644 --- a/dangerzone/common.py +++ b/dangerzone/common.py @@ -1,10 +1,3 @@ -import os -import stat -import platform -import tempfile -import appdirs - - class Common(object): """ The Common class is a singleton of shared functionality throughout an open dangerzone window diff --git a/dangerzone/container.py b/dangerzone/container.py index 82ffc26..7ad0724 100644 --- a/dangerzone/container.py +++ b/dangerzone/container.py @@ -1,4 +1,3 @@ -import platform import subprocess import pipes import shutil @@ -6,23 +5,7 @@ import os import tempfile import appdirs -# What container tech is used for this platform? -if platform.system() == "Linux": - container_tech = "podman" -else: - # Windows, Darwin, and unknown use docker for now, dangerzone-vm eventually - container_tech = "docker" - -# Define startupinfo for subprocesses -if platform.system() == "Windows": - startupinfo = subprocess.STARTUPINFO() - startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW -else: - startupinfo = None - - -# Name of the dangerzone container -container_name = "dangerzone.rocks/dangerzone" +import dangerzone.util as dzutil def exec(args, stdout_callback=None): @@ -30,13 +13,13 @@ def exec(args, stdout_callback=None): print("> " + args_str) with subprocess.Popen( - args, - stdin=None, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - bufsize=1, - universal_newlines=True, - startupinfo=startupinfo, + args, + stdin=None, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + bufsize=1, + universal_newlines=True, + startupinfo=dzutil.get_subprocess_startupinfo(), ) as p: if stdout_callback: for line in p.stdout: @@ -47,12 +30,7 @@ def exec(args, stdout_callback=None): def exec_container(args, stdout_callback=None): - if container_tech == "podman": - container_runtime = shutil.which("podman") - else: - container_runtime = shutil.which("docker") - - args = [container_runtime] + args + args = [dzutil.CONTAINER_RUNTIME] + args return exec(args, stdout_callback) @@ -80,18 +58,18 @@ def convert(input_filename, output_filename, ocr_lang, stdout_callback): # Convert document to pixels args = ( - ["run", "--network", "none"] - + platform_args - + [ - "-v", - f"{input_filename}:/tmp/input_file", - "-v", - f"{pixel_dir}:/dangerzone", - container_name, - "/usr/bin/python3", - "/usr/local/bin/dangerzone.py", - "document-to-pixels", - ] + ["run", "--network", "none"] + + platform_args + + [ + "-v", + f"{input_filename}:/tmp/input_file", + "-v", + f"{pixel_dir}:/dangerzone", + dzutil.CONTAINER_NAME, + "/usr/bin/python3", + "/usr/local/bin/dangerzone.py", + "document-to-pixels", + ] ) ret = exec_container(args, stdout_callback) if ret != 0: @@ -101,22 +79,22 @@ def convert(input_filename, output_filename, ocr_lang, stdout_callback): # Convert pixels to safe PDF args = ( - ["run", "--network", "none"] - + platform_args - + [ - "-v", - f"{pixel_dir}:/dangerzone", - "-v", - f"{safe_dir}:/safezone", - "-e", - f"OCR={ocr}", - "-e", - f"OCR_LANGUAGE={ocr_lang}", - container_name, - "/usr/bin/python3", - "/usr/local/bin/dangerzone.py", - "pixels-to-pdf", - ] + ["run", "--network", "none"] + + platform_args + + [ + "-v", + f"{pixel_dir}:/dangerzone", + "-v", + f"{safe_dir}:/safezone", + "-e", + f"OCR={ocr}", + "-e", + f"OCR_LANGUAGE={ocr_lang}", + dzutil.CONTAINER_NAME, + "/usr/bin/python3", + "/usr/local/bin/dangerzone.py", + "pixels-to-pdf", + ] ) ret = exec_container(args, stdout_callback) if ret != 0: @@ -139,7 +117,6 @@ def convert(input_filename, output_filename, ocr_lang, stdout_callback): return success - # From global_common: # def validate_convert_to_pixel_output(self, common, output): diff --git a/dangerzone/global_common.py b/dangerzone/global_common.py index 524e4ce..e11072e 100644 --- a/dangerzone/global_common.py +++ b/dangerzone/global_common.py @@ -1,15 +1,11 @@ -import sys -import os -import inspect -import platform import subprocess -import shutil import gzip import colorama from colorama import Fore, Back, Style -from . import CONTAINER_NAME -from .settings import Settings +import dangerzone +from dangerzone.settings import Settings +import dangerzone.util as dzutil class GlobalCommon(object): @@ -18,182 +14,11 @@ class GlobalCommon(object): """ def __init__(self): - # Version - try: - with open(self.get_resource_path("version.txt")) as f: - self.version = f.read().strip() - except FileNotFoundError: - # In dev mode, in Windows, get_resource_path doesn't work properly for the container, but luckily - # it doesn't need to know the version - self.version = "unknown" + self.version = dzutil.VERSION # Initialize terminal colors colorama.init(autoreset=True) - # Languages supported by tesseract - self.ocr_languages = { - "Afrikaans": "ar", - "Albanian": "sqi", - "Amharic": "amh", - "Arabic": "ara", - "Arabic script": "Arabic", - "Armenian": "hye", - "Armenian script": "Armenian", - "Assamese": "asm", - "Azerbaijani": "aze", - "Azerbaijani (Cyrillic)": "aze_cyrl", - "Basque": "eus", - "Belarusian": "bel", - "Bengali": "ben", - "Bengali script": "Bengali", - "Bosnian": "bos", - "Breton": "bre", - "Bulgarian": "bul", - "Burmese": "mya", - "Canadian Aboriginal script": "Canadian_Aboriginal", - "Catalan": "cat", - "Cebuano": "ceb", - "Cherokee": "chr", - "Cherokee script": "Cherokee", - "Chinese - Simplified": "chi_sim", - "Chinese - Simplified (vertical)": "chi_sim_vert", - "Chinese - Traditional": "chi_tra", - "Chinese - Traditional (vertical)": "chi_tra_vert", - "Corsican": "cos", - "Croatian": "hrv", - "Cyrillic script": "Cyrillic", - "Czech": "ces", - "Danish": "dan", - "Devanagari script": "Devanagari", - "Divehi": "div", - "Dutch": "nld", - "Dzongkha": "dzo", - "English": "eng", - "English, Middle (1100-1500)": "enm", - "Esperanto": "epo", - "Estonian": "est", - "Ethiopic script": "Ethiopic", - "Faroese": "fao", - "Filipino": "fil", - "Finnish": "fin", - "Fraktur script": "Fraktur", - "Frankish": "frk", - "French": "fra", - "French, Middle (ca.1400-1600)": "frm", - "Frisian (Western)": "fry", - "Gaelic (Scots)": "gla", - "Galician": "glg", - "Georgian": "kat", - "Georgian script": "Georgian", - "German": "deu", - "Greek": "ell", - "Greek script": "Greek", - "Gujarati": "guj", - "Gujarati script": "Gujarati", - "Gurmukhi script": "Gurmukhi", - "Hangul script": "Hangul", - "Hangul (vertical) script": "Hangul_vert", - "Han - Simplified script": "HanS", - "Han - Simplified (vertical) script": "HanS_vert", - "Han - Traditional script": "HanT", - "Han - Traditional (vertical) script": "HanT_vert", - "Hatian": "hat", - "Hebrew": "heb", - "Hebrew script": "Hebrew", - "Hindi": "hin", - "Hungarian": "hun", - "Icelandic": "isl", - "Indonesian": "ind", - "Inuktitut": "iku", - "Irish": "gle", - "Italian": "ita", - "Italian - Old": "ita_old", - "Japanese": "jpn", - "Japanese script": "Japanese", - "Japanese (vertical)": "jpn_vert", - "Japanese (vertical) script": "Japanese_vert", - "Javanese": "jav", - "Kannada": "kan", - "Kannada script": "Kannada", - "Kazakh": "kaz", - "Khmer": "khm", - "Khmer script": "Khmer", - "Korean": "kor", - "Korean (vertical)": "kor_vert", - "Kurdish (Arabic)": "kur_ara", - "Kyrgyz": "kir", - "Lao": "lao", - "Lao script": "Lao", - "Latin": "lat", - "Latin script": "Latin", - "Latvian": "lav", - "Lithuanian": "lit", - "Luxembourgish": "ltz", - "Macedonian": "mkd", - "Malayalam": "mal", - "Malayalam script": "Malayalam", - "Malay": "msa", - "Maltese": "mlt", - "Maori": "mri", - "Marathi": "mar", - "Mongolian": "mon", - "Myanmar script": "Myanmar", - "Nepali": "nep", - "Norwegian": "nor", - "Occitan (post 1500)": "oci", - "Old Georgian": "kat_old", - "Oriya (Odia) script": "Oriya", - "Oriya": "ori", - "Pashto": "pus", - "Persian": "fas", - "Polish": "pol", - "Portuguese": "por", - "Punjabi": "pan", - "Quechua": "que", - "Romanian": "ron", - "Russian": "rus", - "Sanskrit": "san", - "script and orientation": "osd", - "Serbian (Latin)": "srp_latn", - "Serbian": "srp", - "Sindhi": "snd", - "Sinhala script": "Sinhala", - "Sinhala": "sin", - "Slovakian": "slk", - "Slovenian": "slv", - "Spanish, Castilian - Old": "spa_old", - "Spanish": "spa", - "Sundanese": "sun", - "Swahili": "swa", - "Swedish": "swe", - "Syriac script": "Syriac", - "Syriac": "syr", - "Tajik": "tgk", - "Tamil script": "Tamil", - "Tamil": "tam", - "Tatar": "tat", - "Telugu script": "Telugu", - "Telugu": "tel", - "Thaana script": "Thaana", - "Thai script": "Thai", - "Thai": "tha", - "Tibetan script": "Tibetan", - "Tibetan Standard": "bod", - "Tigrinya": "tir", - "Tonga": "ton", - "Turkish": "tur", - "Ukrainian": "ukr", - "Urdu": "urd", - "Uyghur": "uig", - "Uzbek (Cyrillic)": "uzb_cyrl", - "Uzbek": "uzb", - "Vietnamese script": "Vietnamese", - "Vietnamese": "vie", - "Welsh": "cym", - "Yiddish": "yid", - "Yoruba": "yor", - } - # Load settings self.settings = Settings() @@ -339,9 +164,9 @@ class GlobalCommon(object): + "│" ) print(Back.BLACK + Fore.YELLOW + Style.DIM + "│ │") - left_spaces = (15 - len(self.version) - 1) // 2 + left_spaces = (15 - len(dzutil.VERSION) - 1) // 2 right_spaces = left_spaces - if left_spaces + len(self.version) + 1 + right_spaces < 15: + if left_spaces + len(dzutil.VERSION) + 1 + right_spaces < 15: right_spaces += 1 print( Back.BLACK @@ -352,7 +177,7 @@ class GlobalCommon(object): + Back.BLACK + Fore.LIGHTWHITE_EX + Style.BRIGHT - + f"{' '*left_spaces}Dangerzone v{self.version}{' '*right_spaces}" + + f"{' '*left_spaces}Dangerzone v{dzutil.VERSION}{' '*right_spaces}" + Fore.YELLOW + Style.DIM + "│" @@ -372,48 +197,6 @@ class GlobalCommon(object): ) print(Back.BLACK + Fore.YELLOW + Style.DIM + "╰──────────────────────────╯") - @staticmethod - def get_container_runtime(): - if platform.system() == "Linux": - return shutil.which("podman") - else: - return shutil.which("docker") - - @staticmethod - def get_resource_path(filename): - if getattr(sys, "dangerzone_dev", False): - # Look for resources directory relative to python file - prefix = os.path.join( - os.path.dirname( - os.path.dirname( - os.path.abspath(inspect.getfile(inspect.currentframe())) - ) - ), - "share", - ) - else: - if platform.system() == "Darwin": - prefix = os.path.join( - os.path.dirname(os.path.dirname(sys.executable)), "Resources/share" - ) - elif platform.system() == "Linux": - prefix = os.path.join(sys.prefix, "share", "dangerzone") - else: - # Windows - prefix = os.path.join(os.path.dirname(sys.executable), "share") - - resource_path = os.path.join(prefix, filename) - return resource_path - - @staticmethod - def get_subprocess_startupinfo(): - if platform.system() == "Windows": - startupinfo = subprocess.STARTUPINFO() - startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW - return startupinfo - else: - return None - @staticmethod def install_container(): """ @@ -426,13 +209,13 @@ class GlobalCommon(object): print("Installing Dangerzone container image...") p = subprocess.Popen( - [GlobalCommon.get_container_runtime(), "load"], + [dzutil.CONTAINER_RUNTIME, "load"], stdin=subprocess.PIPE, - startupinfo=GlobalCommon.get_subprocess_startupinfo(), + startupinfo=dzutil.get_subprocess_startupinfo(), ) chunk_size = 10240 - compressed_container_path = GlobalCommon.get_resource_path("container.tar.gz") + compressed_container_path = dzutil.get_resource_path("container.tar.gz") with gzip.open(compressed_container_path) as f: while True: chunk = f.read(chunk_size) @@ -455,22 +238,22 @@ class GlobalCommon(object): See if the podman container is installed. Linux only. """ # Get the image id - with open(GlobalCommon.get_resource_path("image-id.txt")) as f: + with open(dzutil.get_resource_path("image-id.txt")) as f: expected_image_id = f.read().strip() # See if this image is already installed installed = False found_image_id = subprocess.check_output( [ - GlobalCommon.get_container_runtime(), + dzutil.CONTAINER_RUNTIME, "image", "list", "--format", "{{.ID}}", - CONTAINER_NAME, + dangerzone.util.CONTAINER_NAME, ], text=True, - startupinfo=GlobalCommon.get_subprocess_startupinfo(), + startupinfo=dzutil.get_subprocess_startupinfo(), ) found_image_id = found_image_id.strip() @@ -483,8 +266,8 @@ class GlobalCommon(object): try: subprocess.check_output( - [GlobalCommon.get_container_runtime(), "rmi", "--force", found_image_id], - startupinfo=GlobalCommon.get_subprocess_startupinfo(), + [dzutil.CONTAINER_RUNTIME, "rmi", "--force", found_image_id], + startupinfo=dzutil.get_subprocess_startupinfo(), ) except: print("Couldn't delete old container image, so leaving it there") diff --git a/dangerzone/gui/__init__.py b/dangerzone/gui/__init__.py index 0d0f899..c93edcb 100644 --- a/dangerzone/gui/__init__.py +++ b/dangerzone/gui/__init__.py @@ -53,7 +53,7 @@ def gui_main(filename): # Create the system tray # noinspection PyUnusedLocal - systray = SysTray(global_common, gui_common, app) + systray = SysTray(gui_common, app) closed_windows = {} windows = {} diff --git a/dangerzone/gui/common.py b/dangerzone/gui/common.py index f450c60..6993ffe 100644 --- a/dangerzone/gui/common.py +++ b/dangerzone/gui/common.py @@ -4,17 +4,14 @@ import subprocess import shlex import pipes from PySide6 import QtCore, QtGui, QtWidgets +from PySide6.QtGui import QIcon from colorama import Fore from . import Application from ..global_common import GlobalCommon +import dangerzone.util as dzutil -if platform.system() == "Darwin": - import plistlib - -elif platform.system() == "Linux": - import grp - import getpass +if platform.system() == "Linux": from xdg.DesktopEntry import DesktopEntry # type: ignore @@ -39,14 +36,6 @@ class GuiCommon(object): # Are we done waiting (for Docker Desktop to be installed, or for container to install) self.is_waiting_finished = False - @staticmethod - def get_window_icon(): - if platform.system() == "Windows": - path = GlobalCommon.get_resource_path("dangerzone.ico") - else: - path = GlobalCommon.get_resource_path("icon.png") - return QtGui.QIcon(path) - def open_pdf_viewer(self, filename: str): if platform.system() == "Darwin": # Open in Preview @@ -118,7 +107,7 @@ class Alert(QtWidgets.QDialog): ): super(Alert, self).__init__() self.setWindowTitle("dangerzone") - self.setWindowIcon(GuiCommon.get_window_icon()) + self.setWindowIcon(QIcon(dzutil.WINDOW_ICON_PATH)) self.setModal(True) flags = ( # TODO Mypy: unsupported left operand type for | ("WindowType") @@ -133,7 +122,7 @@ class Alert(QtWidgets.QDialog): logo = QtWidgets.QLabel() logo.setPixmap( QtGui.QPixmap.fromImage( - QtGui.QImage(GlobalCommon.get_resource_path("icon.png")) + QtGui.QImage(dzutil.get_resource_path("icon.png")) ) ) diff --git a/dangerzone/gui/main_window.py b/dangerzone/gui/main_window.py index 56ca217..4895029 100644 --- a/dangerzone/gui/main_window.py +++ b/dangerzone/gui/main_window.py @@ -5,8 +5,10 @@ import subprocess import json import shutil from PySide6 import QtCore, QtGui, QtWidgets +from PySide6.QtGui import QIcon from colorama import Style, Fore +import dangerzone.util as dzutil from . import GuiCommon from ..common import Common from ..container import convert @@ -24,7 +26,7 @@ class MainWindow(QtWidgets.QMainWindow): self.common = Common() self.setWindowTitle("Dangerzone") - self.setWindowIcon(self.gui_common.get_window_icon()) + self.setWindowIcon(QIcon(dzutil.WINDOW_ICON_PATH)) self.setMinimumWidth(600) self.setMinimumHeight(400) @@ -33,7 +35,7 @@ class MainWindow(QtWidgets.QMainWindow): logo = QtWidgets.QLabel() logo.setPixmap( QtGui.QPixmap.fromImage( - QtGui.QImage(self.global_common.get_resource_path("icon.png")) + QtGui.QImage(dzutil.get_resource_path("icon.png")) ) ) header_label = QtWidgets.QLabel("dangerzone") @@ -165,7 +167,7 @@ class WaitingWidget(QtWidgets.QWidget): [container_runtime, "image", "ls"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, - startupinfo=self.global_common.get_subprocess_startupinfo(), + startupinfo=dzutil.get_subprocess_startupinfo(), ) as p: p.communicate() if p.returncode != 0: @@ -361,8 +363,8 @@ class SettingsWidget(QtWidgets.QWidget): # 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]) + for k in dzutil.OCR_LANGUAGES: + self.ocr_combobox.addItem(k, dzutil.OCR_LANGUAGES[k]) ocr_layout = QtWidgets.QHBoxLayout() ocr_layout.addWidget(self.ocr_checkbox) ocr_layout.addWidget(self.ocr_combobox) @@ -499,7 +501,7 @@ class ConvertThread(QtCore.QThread): def run(self): if self.global_common.settings.get("ocr"): - ocr_lang = self.global_common.ocr_languages[ + ocr_lang = dzutil.OCR_LANGUAGES[ self.global_common.settings.get("ocr_language") ] else: @@ -557,7 +559,7 @@ class ConvertWidget(QtWidgets.QWidget): self.error_image = QtWidgets.QLabel() self.error_image.setPixmap( QtGui.QPixmap.fromImage( - QtGui.QImage(self.global_common.get_resource_path("error.png")) + QtGui.QImage(dzutil.get_resource_path("error.png")) ) ) self.error_image.hide() @@ -616,7 +618,7 @@ class ConvertWidget(QtWidgets.QWidget): subprocess.Popen( f'explorer.exe /select,"{dest_filename_windows}"', shell=True, - startupinfo=self.global_common.get_subprocess_startupinfo(), + startupinfo=dzutil.get_subprocess_startupinfo(), ) # Open diff --git a/dangerzone/gui/systray.py b/dangerzone/gui/systray.py index 080b4ef..ba7915e 100644 --- a/dangerzone/gui/systray.py +++ b/dangerzone/gui/systray.py @@ -1,19 +1,19 @@ from PySide6 import QtWidgets +from PySide6.QtGui import QIcon -from dangerzone.global_common import GlobalCommon from dangerzone.gui import GuiCommon, Application +import dangerzone.util as dzutil class SysTray(QtWidgets.QSystemTrayIcon): def __init__( - self, global_common: GlobalCommon, gui_common: GuiCommon, app: Application + self, gui_common: GuiCommon, app: Application ): super(SysTray, self).__init__() - self.global_common = global_common self.gui_common = gui_common self.app = app - self.setIcon(self.gui_common.get_window_icon()) + self.setIcon(QIcon(dzutil.WINDOW_ICON_PATH)) menu = QtWidgets.QMenu() diff --git a/dangerzone/settings.py b/dangerzone/settings.py index 2ffe341..eef7e6e 100644 --- a/dangerzone/settings.py +++ b/dangerzone/settings.py @@ -1,12 +1,12 @@ import os import json -from dangerzone import APPDATA_PATH +import dangerzone.util as dzutil class Settings: def __init__(self): - self.settings_filename = os.path.join(APPDATA_PATH, "settings.json") + self.settings_filename = os.path.join(dzutil.APPDATA_PATH, "settings.json") self.default_settings = { "save": True, "ocr": True, @@ -47,6 +47,6 @@ class Settings: self.save() def save(self): - os.makedirs(APPDATA_PATH, exist_ok=True) + os.makedirs(dzutil.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/util.py b/dangerzone/util.py new file mode 100644 index 0000000..2447121 --- /dev/null +++ b/dangerzone/util.py @@ -0,0 +1,230 @@ +import inspect +import os +import platform +import shutil +import subprocess +import sys +import appdirs + +# If a general-purpose function doesn't depend on anything else in the dangerzone package, then it belongs here. + + +def get_resource_path(filename): + if getattr(sys, "dangerzone_dev", False): + # Look for resources directory relative to python file + prefix = os.path.join( + os.path.dirname( + os.path.dirname( + os.path.abspath(inspect.getfile(inspect.currentframe())) + ) + ), + "share", + ) + else: + if platform.system() == "Darwin": + prefix = os.path.join( + os.path.dirname(os.path.dirname(sys.executable)), "Resources/share" + ) + elif platform.system() == "Linux": + prefix = os.path.join(sys.prefix, "share", "dangerzone") + else: + # Windows + prefix = os.path.join(os.path.dirname(sys.executable), "share") + resource_path = os.path.join(prefix, filename) + return resource_path + + +def get_subprocess_startupinfo(): + if platform.system() == "Windows": + startupinfo = subprocess.STARTUPINFO() + startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW + return startupinfo + else: + return None + + +def _get_version() -> str: + """Dangerzone version number. Prefer dangerzone.VERSION to this function.""" + try: + with open(get_resource_path("version.txt")) as f: + version = f.read().strip() + except FileNotFoundError: + # In dev mode, in Windows, get_resource_path doesn't work properly for the container, but luckily + # it doesn't need to know the version + version = "unknown" + return version + + +VERSION = _get_version() +APPDATA_PATH = appdirs.user_config_dir("dangerzone") +SYSTEM = platform.system() +CONTAINER_NAME = "dangerzone.rocks/dangerzone" +CONTAINER_COMMAND = "podman" if SYSTEM == "Linux" else "Docker" +CONTAINER_RUNTIME = shutil.which(CONTAINER_COMMAND) + +WINDOW_ICON_FILENAME = "dangerzone.ico" if SYSTEM == "Windows" else "icon.png" +WINDOW_ICON_PATH = get_resource_path(WINDOW_ICON_FILENAME) + +# Languages supported by tesseract +OCR_LANGUAGES = { + "Afrikaans": "ar", + "Albanian": "sqi", + "Amharic": "amh", + "Arabic": "ara", + "Arabic script": "Arabic", + "Armenian": "hye", + "Armenian script": "Armenian", + "Assamese": "asm", + "Azerbaijani": "aze", + "Azerbaijani (Cyrillic)": "aze_cyrl", + "Basque": "eus", + "Belarusian": "bel", + "Bengali": "ben", + "Bengali script": "Bengali", + "Bosnian": "bos", + "Breton": "bre", + "Bulgarian": "bul", + "Burmese": "mya", + "Canadian Aboriginal script": "Canadian_Aboriginal", + "Catalan": "cat", + "Cebuano": "ceb", + "Cherokee": "chr", + "Cherokee script": "Cherokee", + "Chinese - Simplified": "chi_sim", + "Chinese - Simplified (vertical)": "chi_sim_vert", + "Chinese - Traditional": "chi_tra", + "Chinese - Traditional (vertical)": "chi_tra_vert", + "Corsican": "cos", + "Croatian": "hrv", + "Cyrillic script": "Cyrillic", + "Czech": "ces", + "Danish": "dan", + "Devanagari script": "Devanagari", + "Divehi": "div", + "Dutch": "nld", + "Dzongkha": "dzo", + "English": "eng", + "English, Middle (1100-1500)": "enm", + "Esperanto": "epo", + "Estonian": "est", + "Ethiopic script": "Ethiopic", + "Faroese": "fao", + "Filipino": "fil", + "Finnish": "fin", + "Fraktur script": "Fraktur", + "Frankish": "frk", + "French": "fra", + "French, Middle (ca.1400-1600)": "frm", + "Frisian (Western)": "fry", + "Gaelic (Scots)": "gla", + "Galician": "glg", + "Georgian": "kat", + "Georgian script": "Georgian", + "German": "deu", + "Greek": "ell", + "Greek script": "Greek", + "Gujarati": "guj", + "Gujarati script": "Gujarati", + "Gurmukhi script": "Gurmukhi", + "Hangul script": "Hangul", + "Hangul (vertical) script": "Hangul_vert", + "Han - Simplified script": "HanS", + "Han - Simplified (vertical) script": "HanS_vert", + "Han - Traditional script": "HanT", + "Han - Traditional (vertical) script": "HanT_vert", + "Hatian": "hat", + "Hebrew": "heb", + "Hebrew script": "Hebrew", + "Hindi": "hin", + "Hungarian": "hun", + "Icelandic": "isl", + "Indonesian": "ind", + "Inuktitut": "iku", + "Irish": "gle", + "Italian": "ita", + "Italian - Old": "ita_old", + "Japanese": "jpn", + "Japanese script": "Japanese", + "Japanese (vertical)": "jpn_vert", + "Japanese (vertical) script": "Japanese_vert", + "Javanese": "jav", + "Kannada": "kan", + "Kannada script": "Kannada", + "Kazakh": "kaz", + "Khmer": "khm", + "Khmer script": "Khmer", + "Korean": "kor", + "Korean (vertical)": "kor_vert", + "Kurdish (Arabic)": "kur_ara", + "Kyrgyz": "kir", + "Lao": "lao", + "Lao script": "Lao", + "Latin": "lat", + "Latin script": "Latin", + "Latvian": "lav", + "Lithuanian": "lit", + "Luxembourgish": "ltz", + "Macedonian": "mkd", + "Malayalam": "mal", + "Malayalam script": "Malayalam", + "Malay": "msa", + "Maltese": "mlt", + "Maori": "mri", + "Marathi": "mar", + "Mongolian": "mon", + "Myanmar script": "Myanmar", + "Nepali": "nep", + "Norwegian": "nor", + "Occitan (post 1500)": "oci", + "Old Georgian": "kat_old", + "Oriya (Odia) script": "Oriya", + "Oriya": "ori", + "Pashto": "pus", + "Persian": "fas", + "Polish": "pol", + "Portuguese": "por", + "Punjabi": "pan", + "Quechua": "que", + "Romanian": "ron", + "Russian": "rus", + "Sanskrit": "san", + "script and orientation": "osd", + "Serbian (Latin)": "srp_latn", + "Serbian": "srp", + "Sindhi": "snd", + "Sinhala script": "Sinhala", + "Sinhala": "sin", + "Slovakian": "slk", + "Slovenian": "slv", + "Spanish, Castilian - Old": "spa_old", + "Spanish": "spa", + "Sundanese": "sun", + "Swahili": "swa", + "Swedish": "swe", + "Syriac script": "Syriac", + "Syriac": "syr", + "Tajik": "tgk", + "Tamil script": "Tamil", + "Tamil": "tam", + "Tatar": "tat", + "Telugu script": "Telugu", + "Telugu": "tel", + "Thaana script": "Thaana", + "Thai script": "Thai", + "Thai": "tha", + "Tibetan script": "Tibetan", + "Tibetan Standard": "bod", + "Tigrinya": "tir", + "Tonga": "ton", + "Turkish": "tur", + "Ukrainian": "ukr", + "Urdu": "urd", + "Uyghur": "uig", + "Uzbek (Cyrillic)": "uzb_cyrl", + "Uzbek": "uzb", + "Vietnamese script": "Vietnamese", + "Vietnamese": "vie", + "Welsh": "cym", + "Yiddish": "yid", + "Yoruba": "yor" +}