File: deviceeditor.py

package info (click to toggle)
syncthing-gtk 0.9.4.4%2Bds%2Bgit20221205%2B12a9702d29ab-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 2,888 kB
  • sloc: python: 8,077; sh: 259; xml: 134; makefile: 6
file content (163 lines) | stat: -rw-r--r-- 5,957 bytes parent folder | download | duplicates (2)
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
160
161
162
163
#!/usr/bin/env python3
"""
Syncthing-GTK - DeviceEditorDialog

Universal dialog handler for all Syncthing settings and editing
"""


import logging

from gi.repository import Gtk

from syncthing_gtk.editordialog import EditorDialog, strip_v
from syncthing_gtk.tools import _  # gettext function
from syncthing_gtk.tools import check_device_id


log = logging.getLogger("DeviceEditor")

COLOR_NEW = "#A0A0A0"
VALUES = ["vdeviceID", "vname", "vaddresses", "vcompression",
          "vfolders", "vintroducer"
          ]


class DeviceEditorDialog(EditorDialog):
    MESSAGES = {
        # Displayed when device id is invalid
        "vdeviceID": _("The entered device ID does not look valid. It "
                       "should be a 52 character string consisting of letters and "
                       "numbers, with spaces and dashes being optional."),
    }

    def __init__(self, app, is_new, id=None):
        EditorDialog.__init__(
            self, app, "device-edit.ui",
            "New Device" if is_new else "Edit Device")
        self.id = id
        self.is_new = is_new

    # @Overrides
    def get_value(self, key):
        if key == "addresses":
            return ",".join([strip_v(x) for x in self.values[key]])
        elif key == "deviceID":
            return EditorDialog.get_value(self, key).strip(" \r\n\t")
        elif key == "compression":
            val = EditorDialog.get_value(self, key)
            # For syncthing <= 0.10.25
            if val in (True, "true"):
                return "always"
            elif val in (False, "false"):
                return "never"
            else:
                return val
        else:
            return EditorDialog.get_value(self, key)

    # @Overrides
    def set_value(self, key, value):
        if key == "addresses":
            self.values[key] = [strip_v(x) for x in value.split(",")]
        else:
            return EditorDialog.set_value(self, key, value)

    # @Overrides
    def on_data_loaded(self):
        try:
            if self.is_new:
                self.values = {strip_v(x): "" for x in VALUES}
                self.set_value("addresses", "dynamic")
                self.set_value("compression", "metadata")
                self.checks = {
                    "vdeviceID": check_device_id,
                }
                if self.id is not None:
                    # Pre-fill device id, if provided
                    self.set_value("deviceID", self.id)
            else:
                self.values = [x for x in self.config["devices"]
                               if x["deviceID"] == self.id][0]
        except KeyError as e:
            # ID not found in configuration. This is practically impossible,
            # so it's handled only by self-closing dialog.
            log.exception(e)
            self.close()
            return
        return self.display_values(VALUES)

    # @Overrides
    def display_value(self, key, w):
        if key == "vfolders":
            # Even more special case
            rids = []
            # Get list of folders that share this device
            for r in self.config["folders"]:
                for n in r["devices"]:
                    if n["deviceID"] == self.id and r["id"] not in rids:
                        rids.append(r["id"])
            # Create CheckButtons
            for folder in reversed(sorted(self.app.folders.values(), key=lambda x: x["id"])):
                b = Gtk.CheckButton(folder["path"], False)
                b.set_tooltip_text(folder["id"])
                self["vfolders"].pack_start(b, False, False, 0)
                b.set_active(folder["id"] in rids)
            self["vfolders"].show_all()
        else:
            EditorDialog.display_value(self, key, w)

    # @Overrides
    def update_special_widgets(self, *a):
        self["vdeviceID"].set_sensitive(self.is_new)

    # @Overrides
    def on_save_requested(self):
        self.store_values(VALUES)
        if self.is_new:
            # Add new dict to configuration (edited dict is already there)
            self.config["devices"].append(self.values)
        # Post configuration back to daemon
        self.post_config()

    # @Overrides
    def store_value(self, key, w):
        if key == "vaddresses":
            addresses = [
                x.strip() if "://" in x or x.strip() == "dynamic" else "tcp://%s" % (x.strip(),)
                for x in w.get_text().split(",")]
            self.set_value("addresses", ",".join(addresses))
        elif key == "vfolders":
            # Generate dict of { folder_id : bool } where bool is True if
            # folder should be shared with this device
            folders = {}
            for b in self["vfolders"].get_children():
                folders[b.get_tooltip_text()] = b.get_active()
            # Go over all Folders/<folder>/Devices/<device> keys in config
            # and set them as needed
            nid = self.get_value("deviceID")
            for r in self.config["folders"]:
                rid = r["id"]
                found = False
                for n in r["devices"]:
                    if n["deviceID"] == nid:
                        if rid not in folders or not folders[rid]:
                            # Remove this /<device> key (unshare folder with device)
                            r["devices"].remove(n)
                            break
                        found = True
                if (not found) and (rid in folders) and folders[rid]:
                    # Add new /<device> key (share folder with device)
                    r["devices"].append({
                        "addresses": None,
                        "deviceID": nid,
                        "name": "",
                        "certName": "",
                        "compression": "metadata"
                    })
        else:
            EditorDialog.store_value(self, key, w)

    # @Overrides
    def on_saved(self):
        self.close()