File: deviceeditor.py

package info (click to toggle)
syncthing-gtk 0.9.4.4%2Bds%2Bgit20201209%2Bc46fbd8-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 3,260 kB
  • sloc: python: 7,592; sh: 259; xml: 115; makefile: 2
file content (158 lines) | stat: -rw-r--r-- 4,741 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
#!/usr/bin/env python3
"""
Syncthing-GTK - DeviceEditorDialog

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


from gi.repository import Gtk
from syncthing_gtk.tools import check_device_id
from syncthing_gtk.tools import _ # gettext function
from syncthing_gtk.editordialog import EditorDialog, strip_v
import logging
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.glade",
			"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 != 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 not rid 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()