• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

dynobo / normcap / 14280746188

05 Apr 2025 09:50AM UTC coverage: 84.841% (-2.2%) from 87.002%
14280746188

Pull #690

github

web-flow
Merge d28da9558 into c7b17ed4a
Pull Request #690: feature/add-qr-support

318 of 410 new or added lines in 35 files covered. (77.56%)

5 existing lines in 2 files now uncovered.

2569 of 3028 relevant lines covered (84.84%)

3.24 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

83.33
/normcap/app.py
1
"""Start main application logic."""
2

3
import logging
4✔
4
import os
4✔
5
import signal
4✔
6
import sys
4✔
7
from argparse import Namespace
4✔
8
from typing import NoReturn
4✔
9

10
from PySide6 import QtCore, QtWidgets
4✔
11

12
from normcap import __version__, utils
4✔
13
from normcap.detection.ocr import tesseract
4✔
14
from normcap.gui import system_info
4✔
15
from normcap.gui.tray import SystemTray
4✔
16

17

18
def _get_args() -> Namespace:
4✔
19
    """Parse command line arguments.
20

21
    Exit if NormCap was started with --version flag.
22

23
    Auto-enable tray for "background mode", which starts NormCap in tray without
24
    immediately opening the select-region window.
25
    """
26
    args = utils.create_argparser().parse_args()
4✔
27

28
    if args.version:
4✔
29
        print(f"NormCap {__version__}")  # noqa: T201
4✔
30
        sys.exit(0)
4✔
31

32
    if args.background_mode:
4✔
33
        args.tray = True
4✔
34

35
    return args
4✔
36

37

38
def _prepare_logging(log_level: str) -> None:
4✔
39
    """Initialize the logger with the given log level.
40

41
    This function wraps the QT logger to control the output in the Python logger.
42
    For all log levels except DEBUG, an exception hook is used to improve the stack
43
    trace output for bug reporting on Github.
44

45
    Args:
46
        log_level: Valid Python log level (debug, warning, error)
47
    """
48
    sys.excepthook = utils.hook_exceptions
4✔
49

50
    utils.init_logger(log_level=log_level.upper())
4✔
51
    logger = logging.getLogger("normcap")
4✔
52
    logger.info("Start NormCap v%s", __version__)
4✔
53

54
    # Wrap QT logging output
55
    QtCore.qInstallMessageHandler(utils.qt_log_wrapper)
4✔
56

57

58
def _prepare_envs() -> None:
4✔
59
    """Prepare environment variables depending on setup and system.
60

61
    Enable exiting via CTRL+C in Terminal.
62
    """
63
    # Allow closing QT app with CTRL+C in terminal
64
    signal.signal(signal.SIGINT, signal.SIG_DFL)
4✔
65

66
    # Silence opencv warnings
67
    os.environ["OPENCV_LOG_LEVEL"] = "OFF"
4✔
68

69
    if system_info.display_manager_is_wayland():
4✔
70
        utils.set_environ_for_wayland()
×
71
    if system_info.is_flatpak_package():
4✔
72
        utils.set_environ_for_flatpak()
×
73
    if system_info.is_appimage_package():
4✔
74
        utils.set_environ_for_appimage()
×
75

76

77
def _get_application() -> QtWidgets.QApplication:
4✔
78
    """Get a QApplication instance that doesn't exit on window close."""
79
    app = QtWidgets.QApplication.instance() or QtWidgets.QApplication([])
4✔
80
    app.setQuitOnLastWindowClosed(False)
4✔
81
    return app
4✔
82

83

84
def _prepare() -> tuple[QtWidgets.QApplication, SystemTray]:
4✔
85
    """Prepares the application and system tray without executing.
86

87
    Returns:
88
        A tuple containing the QApplication ready for execution
89
            and the not yet visible SystemTray.
90
    """
91
    args = _get_args()
4✔
92

93
    _prepare_logging(log_level=str(getattr(args, "verbosity", "ERROR")))
4✔
94
    _prepare_envs()
4✔
95

96
    if system_info.is_prebuilt_package():
4✔
NEW
97
        tessdata_path = tesseract.get_tessdata_path(
×
98
            config_directory=system_info.config_directory(),
99
            is_briefcase_package=system_info.is_briefcase_package(),
100
            is_flatpak_package=system_info.is_flatpak_package(),
101
        )
NEW
102
        utils.copy_traineddata_files(target_dir=tessdata_path)
×
103

104
    app = _get_application()
4✔
105
    tray = SystemTray(app, vars(args))
4✔
106

107
    return app, tray
4✔
108

109

110
def run() -> NoReturn:
4✔
111
    """Run the main application."""
112
    app, tray = _prepare()
×
113
    tray.show()
×
114
    sys.exit(app.exec())
×
115

116

117
if __name__ == "__main__":
4✔
118
    run()
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc