File: application.py

package info (click to toggle)
secrets 11.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 3,744 kB
  • sloc: python: 6,509; xml: 7; makefile: 4
file content (159 lines) | stat: -rw-r--r-- 5,577 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# SPDX-License-Identifier: GPL-3.0-only
from __future__ import annotations

import logging
from gettext import gettext as _

from gi.repository import Adw, Gio, GLib, Gtk, GtkSource

from gsecrets import const
from gsecrets.widgets.mod import load_widgets
from gsecrets.widgets.window import Window


class Application(Adw.Application):
    development_mode = const.IS_DEVEL
    application_id = const.APP_ID
    settings = Gio.Settings.new(application_id)

    def __init__(self, *args, **_kwargs):
        super().__init__(
            *args,
            application_id=self.application_id,
            flags=Gio.ApplicationFlags.HANDLES_OPEN,
            resource_base_path="/org/gnome/World/Secrets",
            register_session=True,
        )

        # debug level logging option
        self.add_main_option(
            "debug",
            ord("d"),
            GLib.OptionFlags.NONE,
            GLib.OptionArg.NONE,
            _("Enable debug logging"),
            None,
        )

    def do_startup(self):  # pylint: disable=arguments-differ
        Adw.Application.do_startup(self)

        GtkSource.init()

        Gtk.Window.set_default_icon_name(const.APP_ID)

        self.setup_actions()
        self.add_global_accelerators()

        load_widgets()

    def do_open(self, gfile_list, _n_files, _hint):  # pylint: disable=arguments-differ
        for gfile in gfile_list:
            if not gfile.query_exists():
                logging.error("Error: File %s does not exist", gfile.get_path())
                if self.get_windows() is None:
                    self.quit()

            if self.is_safe_open(gfile.get_path()):
                logging.error("Error: Safe %s is already open", gfile.get_path())
            else:
                window = self.new_window()
                window.present()
                window.start_database_opening_routine(gfile.get_path())

    def new_window(self) -> Window:
        """Create a new window.

        The new window will be placed in its own group. This is done
        so that modal windows don't make other windows insensitive.
        """
        window_group = Gtk.WindowGroup()
        window = Window(application=self)

        window_group.add_window(window)
        return window

    def is_safe_open(self, filepath: str) -> bool:
        for window in self.get_windows():
            database = window.unlocked_db
            if not database:
                continue

            if database.database_manager.path == filepath:
                return True

        return False

    def do_handle_local_options(  # pylint: disable=arguments-differ
        self,
        options: GLib.VariantDict,
    ) -> int:
        """Handle cli arguments.

        :returns int: If you have handled your options and want to exit
        the process, return a non-negative option, 0 for success, and
        a positive value for failure. To continue, return -1 to let
        the default option processing continue.
        """
        #  convert GVariantDict -> GVariant -> dict
        options = options.end().unpack()

        # set up logging depending on the verbosity level
        loglevel = logging.INFO
        if self.development_mode or "debug" in options:
            loglevel = logging.DEBUG
            # Don't clutter our log output with debug msg of the
            # pykeepass module it is very noisy.
            pykeepass_logger = logging.getLogger("pykeepass")
            pykeepass_logger.setLevel(logging.INFO)

        logging.basicConfig(
            format="%(asctime)s | %(levelname)s | %(message)s",
            datefmt="%d-%m-%y %H:%M:%S",
            level=loglevel,
        )

        return -1

    def do_activate(self):  # pylint: disable=arguments-differ
        Adw.Application.do_activate(self)

        if window := self.get_active_window():
            window.present()
            return

        window = self.new_window()
        window.invoke_initial_screen()
        window.present()

    def setup_actions(self):
        quit_action = Gio.SimpleAction.new("quit", None)
        quit_action.connect("activate", self.on_quit_action)
        self.add_action(quit_action)

        new_window_action = Gio.SimpleAction.new("new-window", None)
        new_window_action.connect("activate", self.on_new_window_action)
        self.add_action(new_window_action)

    def on_quit_action(self, _action: Gio.Action, _param: GLib.Variant) -> None:
        for window in self.get_windows():
            window.close()

    def on_new_window_action(self, _action: Gio.Action, _param: GLib.Variant) -> None:
        window = self.new_window()
        window.invoke_initial_screen()
        window.present()

    def add_global_accelerators(self):
        self.set_accels_for_action("app.quit", ["<Control>q"])
        self.set_accels_for_action("app.new-window", ["<Control><Shift>n"])
        self.set_accels_for_action("win.settings", ["<Control>comma"])
        self.set_accels_for_action("win.open_database('')", ["<Control>o"])
        self.set_accels_for_action("win.new_database", ["<Control>n"])
        self.set_accels_for_action("win.db.save", ["<Control>s"])
        self.set_accels_for_action("win.db.search", ["<Control>f"])
        self.set_accels_for_action("win.db.lock", ["<Control>l"])
        self.set_accels_for_action("win.db.add_entry", ["<Control>e"])
        self.set_accels_for_action("win.db.add_group", ["<Control>p"])
        self.set_accels_for_action("win.go_back", ["Escape"])
        self.set_accels_for_action("window.close", ["<Control>w"])