432
by Evan Dandrea, Colin Watson, Evan Dandrea, Brian Murray, Luke Yelavich, Mario Limonciello
[ Colin Watson ] |
1 |
import subprocess |
508
by Stéphane Graber, James M. Leddy, Colin Watson, Stéphane Graber, Kent Baxley, Harald Sitter
[ James M. Leddy ] |
2 |
import string |
470
by Colin Watson
Cope with pygobject returning unicode objects rather than UTF-8-encoded |
3 |
|
432
by Evan Dandrea, Colin Watson, Evan Dandrea, Brian Murray, Luke Yelavich, Mario Limonciello
[ Colin Watson ] |
4 |
import dbus |
5 |
from dbus.mainloop.glib import DBusGMainLoop |
|
6 |
DBusGMainLoop(set_as_default=True) |
|
7 |
from gi.repository import Gtk, GObject |
|
8 |
||
470
by Colin Watson
Cope with pygobject returning unicode objects rather than UTF-8-encoded |
9 |
from ubiquity.misc import utf8 |
10 |
||
432
by Evan Dandrea, Colin Watson, Evan Dandrea, Brian Murray, Luke Yelavich, Mario Limonciello
[ Colin Watson ] |
11 |
NM = 'org.freedesktop.NetworkManager' |
12 |
NM_DEVICE = 'org.freedesktop.NetworkManager.Device' |
|
13 |
NM_DEVICE_WIFI = 'org.freedesktop.NetworkManager.Device.Wireless' |
|
14 |
NM_AP = 'org.freedesktop.NetworkManager.AccessPoint' |
|
15 |
NM_SETTINGS = 'org.freedesktop.NetworkManager.Settings' |
|
16 |
NM_SETTINGS_CONN = 'org.freedesktop.NetworkManager.Settings.Connection' |
|
17 |
NM_SETTINGS_PATH = '/org/freedesktop/NetworkManager/Settings' |
|
18 |
NM_ERROR_NOSECRETS = 'org.freedesktop.NetworkManager.AgentManager.NoSecrets' |
|
19 |
DEVICE_TYPE_WIFI = 2 |
|
20 |
NM_STATE_DISCONNECTED = 20 |
|
21 |
NM_STATE_CONNECTING = 40 |
|
22 |
NM_STATE_CONNECTED_GLOBAL = 70 |
|
23 |
||
24 |
||
25 |
# TODO: DBus exceptions. Catch 'em all.
|
|
26 |
||
27 |
def decode_ssid(characters): |
|
477
by Colin Watson
* Cope with stricter dbus.Byte.__str__ implementation in dbus-python 1.0.0 |
28 |
ssid = ''.join([chr(int(char)) for char in characters]) |
470
by Colin Watson
Cope with pygobject returning unicode objects rather than UTF-8-encoded |
29 |
return utf8(ssid, errors='replace') |
432
by Evan Dandrea, Colin Watson, Evan Dandrea, Brian Murray, Luke Yelavich, Mario Limonciello
[ Colin Watson ] |
30 |
|
31 |
def get_prop(obj, iface, prop): |
|
445
by Evan Dandrea
* Add power indicator to the installer panel. |
32 |
try: |
33 |
return obj.Get(iface, prop, dbus_interface=dbus.PROPERTIES_IFACE) |
|
34 |
except dbus.DBusException, e: |
|
35 |
if e.get_dbus_name() == 'org.freedesktop.DBus.Error.UnknownMethod': |
|
36 |
return None |
|
37 |
else: |
|
38 |
raise
|
|
432
by Evan Dandrea, Colin Watson, Evan Dandrea, Brian Murray, Luke Yelavich, Mario Limonciello
[ Colin Watson ] |
39 |
|
40 |
def get_vendor_and_model(udi): |
|
41 |
vendor = '' |
|
42 |
model = '' |
|
433
by Evan Dandrea, Colin Watson, Evan Dandrea, Jeremy Bicha
[ Colin Watson ] |
43 |
cmd = ['/sbin/udevadm', 'info', '--path=%s' % udi, '--query=property'] |
432
by Evan Dandrea, Colin Watson, Evan Dandrea, Brian Murray, Luke Yelavich, Mario Limonciello
[ Colin Watson ] |
44 |
with open('/dev/null', 'w') as devnull: |
45 |
out = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=devnull) |
|
46 |
out = out.communicate() |
|
47 |
if not out[1]: |
|
48 |
for prop in out[0].split('\n'): |
|
49 |
if prop.startswith('ID_VENDOR_FROM_DATABASE'): |
|
50 |
vendor = prop.split('ID_VENDOR_FROM_DATABASE=')[1] |
|
51 |
elif prop.startswith('ID_MODEL_FROM_DATABASE'): |
|
52 |
model = prop.split('ID_MODEL_FROM_DATABASE=')[1] |
|
53 |
return (vendor, model) |
|
54 |
||
55 |
def wireless_hardware_present(): |
|
56 |
# NetworkManager keeps DBus objects for wireless devices around even when
|
|
57 |
# the hardware switch is off.
|
|
58 |
bus = dbus.SystemBus() |
|
59 |
manager = bus.get_object(NM, '/org/freedesktop/NetworkManager') |
|
478
by Colin Watson
* Bump fallback Ubuntu version number in ubi-language to 12.04. |
60 |
try: |
61 |
devices = manager.GetDevices() |
|
62 |
except dbus.DBusException: |
|
63 |
return False |
|
432
by Evan Dandrea, Colin Watson, Evan Dandrea, Brian Murray, Luke Yelavich, Mario Limonciello
[ Colin Watson ] |
64 |
for device_path in devices: |
65 |
device_obj = bus.get_object(NM, device_path) |
|
66 |
if get_prop(device_obj, NM_DEVICE, 'DeviceType') == DEVICE_TYPE_WIFI: |
|
67 |
return True |
|
68 |
return False |
|
69 |
||
70 |
class NetworkManager: |
|
71 |
def __init__(self, model, state_changed=None): |
|
72 |
self.model = model |
|
73 |
self.timeout_id = 0 |
|
74 |
self.start(state_changed) |
|
433
by Evan Dandrea, Colin Watson, Evan Dandrea, Jeremy Bicha
[ Colin Watson ] |
75 |
self.active_connection = None |
432
by Evan Dandrea, Colin Watson, Evan Dandrea, Brian Murray, Luke Yelavich, Mario Limonciello
[ Colin Watson ] |
76 |
|
77 |
def start(self, state_changed=None): |
|
78 |
self.bus = dbus.SystemBus() |
|
79 |
self.manager = self.bus.get_object(NM, '/org/freedesktop/NetworkManager') |
|
80 |
add = self.bus.add_signal_receiver |
|
81 |
add(self.queue_build_cache, 'AccessPointAdded', NM_DEVICE_WIFI, NM) |
|
82 |
add(self.queue_build_cache, 'AccessPointRemoved', NM_DEVICE_WIFI, NM) |
|
83 |
if state_changed: |
|
84 |
add(state_changed, 'StateChanged', NM, NM) |
|
85 |
add(self.queue_build_cache, 'DeviceAdded', NM, NM) |
|
86 |
add(self.queue_build_cache, 'DeviceRemoved', NM, NM) |
|
87 |
add(self.properties_changed, 'PropertiesChanged', NM_AP, |
|
88 |
path_keyword='path') |
|
89 |
self.build_cache() |
|
90 |
self.build_passphrase_cache() |
|
91 |
||
433
by Evan Dandrea, Colin Watson, Evan Dandrea, Jeremy Bicha
[ Colin Watson ] |
92 |
def get_state(self): |
93 |
return self.manager.state() |
|
94 |
||
95 |
def is_connected(self, device, ap): |
|
96 |
device_obj = self.bus.get_object(NM, device) |
|
97 |
connectedap = get_prop(device_obj, NM_DEVICE_WIFI, 'ActiveAccessPoint') |
|
98 |
if not connectedap: |
|
99 |
return False |
|
100 |
connect_obj = self.bus.get_object(NM, connectedap) |
|
445
by Evan Dandrea
* Add power indicator to the installer panel. |
101 |
ssid = get_prop(connect_obj, NM_AP, 'Ssid') |
102 |
if ssid: |
|
103 |
return ap == decode_ssid(ssid) |
|
104 |
else: |
|
105 |
return False |
|
433
by Evan Dandrea, Colin Watson, Evan Dandrea, Jeremy Bicha
[ Colin Watson ] |
106 |
|
432
by Evan Dandrea, Colin Watson, Evan Dandrea, Brian Murray, Luke Yelavich, Mario Limonciello
[ Colin Watson ] |
107 |
def connect_to_ap(self, device, ap, passphrase=None): |
108 |
device_obj = self.bus.get_object(NM, device) |
|
109 |
ap_list = device_obj.GetAccessPoints(dbus_interface=NM_DEVICE_WIFI) |
|
110 |
saved_strength = 0 |
|
111 |
saved_path = '' |
|
112 |
for ap_path in ap_list: |
|
113 |
ap_obj = self.bus.get_object(NM, ap_path) |
|
445
by Evan Dandrea
* Add power indicator to the installer panel. |
114 |
ssid = get_prop(ap_obj, NM_AP, 'Ssid') |
115 |
if ssid: |
|
116 |
strength = get_prop(ap_obj, NM_AP, 'Strength') |
|
117 |
if decode_ssid(ssid) == ap and saved_strength < strength: |
|
118 |
# Connect to the strongest AP.
|
|
119 |
saved_strength = strength |
|
120 |
saved_path = ap_path |
|
432
by Evan Dandrea, Colin Watson, Evan Dandrea, Brian Murray, Luke Yelavich, Mario Limonciello
[ Colin Watson ] |
121 |
if not saved_path: |
122 |
return
|
|
123 |
||
124 |
obj = dbus.Dictionary(signature='sa{sv}') |
|
125 |
if passphrase: |
|
126 |
obj['802-11-wireless-security'] = { 'psk' : passphrase } |
|
433
by Evan Dandrea, Colin Watson, Evan Dandrea, Jeremy Bicha
[ Colin Watson ] |
127 |
self.active_connection = self.manager.AddAndActivateConnection( |
128 |
obj, dbus.ObjectPath(device), dbus.ObjectPath(saved_path))[1] |
|
129 |
||
130 |
def disconnect_from_ap(self): |
|
131 |
if self.active_connection is not None: |
|
132 |
self.manager.DeactivateConnection(self.active_connection) |
|
432
by Evan Dandrea, Colin Watson, Evan Dandrea, Brian Murray, Luke Yelavich, Mario Limonciello
[ Colin Watson ] |
133 |
|
134 |
def build_passphrase_cache(self): |
|
135 |
self.passphrases_cache = {} |
|
136 |
settings_obj = self.bus.get_object(NM, NM_SETTINGS_PATH) |
|
137 |
for conn in settings_obj.ListConnections(dbus_interface=NM_SETTINGS): |
|
138 |
conn_obj = self.bus.get_object(NM, conn) |
|
139 |
props = conn_obj.GetSettings(dbus_interface=NM_SETTINGS_CONN) |
|
140 |
if '802-11-wireless-security' in props: |
|
141 |
try: |
|
142 |
sec = conn_obj.GetSecrets('802-11-wireless-security', |
|
143 |
dbus_interface=NM_SETTINGS_CONN) |
|
144 |
sec = sec['802-11-wireless-security'].values()[0] |
|
145 |
ssid = decode_ssid(props['802-11-wireless']['ssid']) |
|
146 |
self.passphrases_cache[ssid] = sec |
|
147 |
except dbus.exceptions.DBusException, e: |
|
148 |
if e.get_dbus_name() != NM_ERROR_NOSECRETS: |
|
149 |
raise
|
|
150 |
||
151 |
def ssid_in_model(self, iterator, ssid, security): |
|
152 |
i = self.model.iter_children(iterator) |
|
153 |
while i: |
|
154 |
row = self.model[i] |
|
155 |
if row[0] == ssid and row[1] == security: |
|
156 |
return i |
|
157 |
i = self.model.iter_next(i) |
|
158 |
return None |
|
159 |
||
160 |
def prune(self, iterator, ssids): |
|
161 |
to_remove = [] |
|
162 |
while iterator: |
|
163 |
ssid = self.model[iterator][0] |
|
164 |
if ssid not in ssids: |
|
165 |
to_remove.append(iterator) |
|
166 |
iterator = self.model.iter_next(iterator) |
|
167 |
for iterator in to_remove: |
|
168 |
self.model.remove(iterator) |
|
169 |
||
170 |
def queue_build_cache(self, *args): |
|
171 |
if self.timeout_id: |
|
172 |
GObject.source_remove(self.timeout_id) |
|
173 |
self.timeout_id = GObject.timeout_add(500, self.build_cache) |
|
471
by Colin Watson
* Handle interface change in ICU 4.8: unknown time zones result in |
174 |
|
432
by Evan Dandrea, Colin Watson, Evan Dandrea, Brian Murray, Luke Yelavich, Mario Limonciello
[ Colin Watson ] |
175 |
def properties_changed(self, props, path=None): |
176 |
if 'Strength' in props: |
|
177 |
ap_obj = self.bus.get_object(NM, path) |
|
445
by Evan Dandrea
* Add power indicator to the installer panel. |
178 |
ssid = get_prop(ap_obj, NM_AP, 'Ssid') |
179 |
if ssid: |
|
180 |
ssid = decode_ssid(ssid) |
|
479
by Colin Watson, Colin Watson, Brian Murray
[ Colin Watson ] |
181 |
security = (get_prop(ap_obj, NM_AP, 'WpaFlags') != 0 or |
182 |
get_prop(ap_obj, NM_AP, 'RsnFlags') != 0) |
|
445
by Evan Dandrea
* Add power indicator to the installer panel. |
183 |
strength = int(props['Strength']) |
184 |
iterator = self.model.get_iter_first() |
|
185 |
while iterator: |
|
186 |
i = self.ssid_in_model(iterator, ssid, security) |
|
187 |
if i: |
|
471
by Colin Watson
* Handle interface change in ICU 4.8: unknown time zones result in |
188 |
self.model.set_value(i, 2, strength) |
445
by Evan Dandrea
* Add power indicator to the installer panel. |
189 |
iterator = self.model.iter_next(iterator) |
432
by Evan Dandrea, Colin Watson, Evan Dandrea, Brian Murray, Luke Yelavich, Mario Limonciello
[ Colin Watson ] |
190 |
|
191 |
def build_cache(self): |
|
192 |
devices = self.manager.GetDevices() |
|
193 |
for device_path in devices: |
|
194 |
device_obj = self.bus.get_object(NM, device_path) |
|
195 |
if get_prop(device_obj, NM_DEVICE, 'DeviceType') != DEVICE_TYPE_WIFI: |
|
196 |
continue
|
|
197 |
iterator = None |
|
198 |
i = self.model.get_iter_first() |
|
199 |
while i: |
|
200 |
if self.model[i][0] == device_path: |
|
201 |
iterator = i |
|
202 |
break
|
|
203 |
i = self.model.iter_next(i) |
|
204 |
if not iterator: |
|
205 |
udi = get_prop(device_obj, NM_DEVICE, 'Udi') |
|
445
by Evan Dandrea
* Add power indicator to the installer panel. |
206 |
if udi: |
207 |
vendor, model = get_vendor_and_model(udi) |
|
208 |
else: |
|
209 |
vendor, model = ('', '') |
|
432
by Evan Dandrea, Colin Watson, Evan Dandrea, Brian Murray, Luke Yelavich, Mario Limonciello
[ Colin Watson ] |
210 |
iterator = self.model.append(None, [device_path, vendor, model]) |
211 |
ap_list = device_obj.GetAccessPoints(dbus_interface=NM_DEVICE_WIFI) |
|
212 |
ssids = [] |
|
213 |
for ap_path in ap_list: |
|
214 |
ap_obj = self.bus.get_object(NM, ap_path) |
|
445
by Evan Dandrea
* Add power indicator to the installer panel. |
215 |
ssid = get_prop(ap_obj, NM_AP, 'Ssid') |
216 |
if ssid: |
|
217 |
ssid = decode_ssid(ssid) |
|
218 |
strength = int(get_prop(ap_obj, NM_AP, 'Strength') or 0) |
|
479
by Colin Watson, Colin Watson, Brian Murray
[ Colin Watson ] |
219 |
security = (get_prop(ap_obj, NM_AP, 'WpaFlags') != 0 or |
220 |
get_prop(ap_obj, NM_AP, 'RsnFlags') != 0) |
|
445
by Evan Dandrea
* Add power indicator to the installer panel. |
221 |
i = self.ssid_in_model(iterator, ssid, security) |
222 |
if not i: |
|
223 |
self.model.append(iterator, [ssid, security, strength]) |
|
224 |
else: |
|
471
by Colin Watson
* Handle interface change in ICU 4.8: unknown time zones result in |
225 |
self.model.set_value(i, 2, strength) |
445
by Evan Dandrea
* Add power indicator to the installer panel. |
226 |
ssids.append(ssid) |
432
by Evan Dandrea, Colin Watson, Evan Dandrea, Brian Murray, Luke Yelavich, Mario Limonciello
[ Colin Watson ] |
227 |
i = self.model.iter_children(iterator) |
228 |
self.prune(i, ssids) |
|
229 |
i = self.model.get_iter_first() |
|
230 |
self.prune(i, devices) |
|
231 |
return False |
|
232 |
||
233 |
class NetworkManagerTreeView(Gtk.TreeView): |
|
234 |
__gtype_name__ = 'NetworkManagerTreeView' |
|
235 |
def __init__(self, password_entry=None, state_changed=None): |
|
236 |
Gtk.TreeView.__init__(self) |
|
237 |
self.password_entry = password_entry |
|
238 |
self.configure_icons() |
|
239 |
model = Gtk.TreeStore(str, object, object) |
|
240 |
model.set_sort_column_id(0, Gtk.SortType.ASCENDING) |
|
241 |
# TODO eventually this will subclass GenericTreeModel.
|
|
242 |
self.wifi_model = NetworkManager(model, state_changed) |
|
243 |
self.set_model(model) |
|
244 |
||
245 |
ssid_column = Gtk.TreeViewColumn('') |
|
246 |
cell_pixbuf = Gtk.CellRendererPixbuf() |
|
247 |
cell_text = Gtk.CellRendererText() |
|
248 |
ssid_column.pack_start(cell_pixbuf, False) |
|
249 |
ssid_column.pack_start(cell_text, True) |
|
250 |
ssid_column.set_cell_data_func(cell_text, self.data_func) |
|
251 |
ssid_column.set_cell_data_func(cell_pixbuf, self.pixbuf_func) |
|
252 |
self.connect('row-activated', self.row_activated) |
|
253 |
||
254 |
self.append_column(ssid_column) |
|
255 |
self.set_headers_visible(False) |
|
462
by Evan Dandrea
* Expand the list of wireless networks under each card automatically, |
256 |
self.setup_row_expansion_handling(model) |
257 |
||
258 |
def setup_row_expansion_handling(self, model): |
|
259 |
"""
|
|
260 |
If the user collapses a row, save that state. If all the APs go away
|
|
261 |
and then return, such as when the user toggles the wifi kill switch,
|
|
262 |
the UI should keep the row collapsed if it already was, or expand it.
|
|
263 |
"""
|
|
432
by Evan Dandrea, Colin Watson, Evan Dandrea, Brian Murray, Luke Yelavich, Mario Limonciello
[ Colin Watson ] |
264 |
self.expand_all() |
462
by Evan Dandrea
* Expand the list of wireless networks under each card automatically, |
265 |
self.rows_changed_id = None |
266 |
def queue_rows_changed(*args): |
|
267 |
if self.rows_changed_id: |
|
268 |
GObject.source_remove(self.rows_changed_id) |
|
269 |
self.rows_changed_id = GObject.idle_add(self.rows_changed) |
|
270 |
model.connect('row-inserted', queue_rows_changed) |
|
271 |
model.connect('row-deleted', queue_rows_changed) |
|
272 |
||
273 |
self.user_collapsed = {} |
|
274 |
def collapsed(self, iterator, path, collapse): |
|
275 |
udi = model[iterator][0] |
|
276 |
self.user_collapsed[udi] = collapse |
|
277 |
self.connect('row-collapsed', collapsed, True) |
|
278 |
self.connect('row-expanded', collapsed, False) |
|
279 |
||
280 |
def rows_changed(self, *args): |
|
281 |
model = self.get_model() |
|
282 |
i = model.get_iter_first() |
|
283 |
while i: |
|
284 |
udi = model[i][0] |
|
285 |
try: |
|
286 |
if not self.user_collapsed[udi]: |
|
287 |
path = model.get_path(i) |
|
288 |
self.expand_row(path, False) |
|
289 |
except KeyError: |
|
290 |
path = model.get_path(i) |
|
291 |
self.expand_row(path, False) |
|
292 |
i = model.iter_next(i) |
|
432
by Evan Dandrea, Colin Watson, Evan Dandrea, Brian Murray, Luke Yelavich, Mario Limonciello
[ Colin Watson ] |
293 |
|
433
by Evan Dandrea, Colin Watson, Evan Dandrea, Jeremy Bicha
[ Colin Watson ] |
294 |
def get_state(self): |
295 |
return self.wifi_model.get_state() |
|
296 |
||
297 |
def disconnect_from_ap(self): |
|
298 |
self.wifi_model.disconnect_from_ap() |
|
299 |
||
432
by Evan Dandrea, Colin Watson, Evan Dandrea, Brian Murray, Luke Yelavich, Mario Limonciello
[ Colin Watson ] |
300 |
def row_activated(self, unused, path, column): |
301 |
passphrase = None |
|
302 |
if self.password_entry: |
|
303 |
passphrase = self.password_entry.get_text() |
|
304 |
self.connect_to_selection(passphrase) |
|
305 |
||
306 |
def configure_icons(self): |
|
307 |
it = Gtk.IconTheme() |
|
308 |
default = Gtk.IconTheme.get_default() |
|
309 |
default = default.load_icon(Gtk.STOCK_MISSING_IMAGE, 22, 0) |
|
310 |
it.set_custom_theme('ubuntu-mono-light') |
|
311 |
self.icons = [] |
|
312 |
for n in ['nm-signal-00', |
|
313 |
'nm-signal-25', |
|
314 |
'nm-signal-50', |
|
315 |
'nm-signal-75', |
|
316 |
'nm-signal-100', |
|
317 |
'nm-signal-00-secure', |
|
318 |
'nm-signal-25-secure', |
|
319 |
'nm-signal-50-secure', |
|
320 |
'nm-signal-75-secure', |
|
321 |
'nm-signal-100-secure']: |
|
322 |
ico = it.lookup_icon(n, 22, 0) |
|
323 |
if ico: |
|
324 |
ico = ico.load_icon() |
|
325 |
else: |
|
326 |
ico = default |
|
327 |
self.icons.append(ico) |
|
328 |
||
329 |
def pixbuf_func(self, column, cell, model, iterator, data): |
|
330 |
if not model.iter_parent(iterator): |
|
331 |
cell.set_property('pixbuf', None) |
|
332 |
return
|
|
333 |
strength = model[iterator][2] |
|
334 |
if strength < 30: |
|
335 |
icon = 0 |
|
336 |
elif strength < 50: |
|
337 |
icon = 1 |
|
338 |
elif strength < 70: |
|
339 |
icon = 2 |
|
340 |
elif strength < 90: |
|
341 |
icon = 3 |
|
342 |
else: |
|
343 |
icon = 4 |
|
344 |
if model[iterator][1]: |
|
345 |
icon += 5 |
|
346 |
cell.set_property('pixbuf', self.icons[icon]) |
|
347 |
||
348 |
def data_func(self, column, cell, model, iterator, data): |
|
349 |
ssid = model[iterator][0] |
|
350 |
||
351 |
if not model.iter_parent(iterator): |
|
352 |
txt = '%s %s' % (model[iterator][1], model[iterator][2]) |
|
353 |
cell.set_property('text', txt) |
|
354 |
else: |
|
355 |
cell.set_property('text', ssid) |
|
356 |
||
357 |
def get_passphrase(self, ssid): |
|
358 |
try: |
|
359 |
cached = self.wifi_model.passphrases_cache[ssid] |
|
360 |
except KeyError: |
|
361 |
return '' |
|
362 |
return cached |
|
363 |
||
460
by Evan Dandrea
* Don't crash if the user selects the wireless card header and presses |
364 |
def is_row_an_ap(self): |
365 |
model, iterator = self.get_selection().get_selected() |
|
366 |
if iterator is None: |
|
367 |
return False |
|
368 |
return model.iter_parent(iterator) is not None |
|
471
by Colin Watson
* Handle interface change in ICU 4.8: unknown time zones result in |
369 |
|
433
by Evan Dandrea, Colin Watson, Evan Dandrea, Jeremy Bicha
[ Colin Watson ] |
370 |
def is_row_connected(self): |
371 |
model, iterator = self.get_selection().get_selected() |
|
460
by Evan Dandrea
* Don't crash if the user selects the wireless card header and presses |
372 |
if iterator is None: |
373 |
return False |
|
433
by Evan Dandrea, Colin Watson, Evan Dandrea, Jeremy Bicha
[ Colin Watson ] |
374 |
ssid = model[iterator][0] |
375 |
parent = model.iter_parent(iterator) |
|
376 |
if parent and self.wifi_model.is_connected(model[parent][0], ssid): |
|
377 |
return True |
|
378 |
else: |
|
379 |
return False |
|
380 |
||
432
by Evan Dandrea, Colin Watson, Evan Dandrea, Brian Murray, Luke Yelavich, Mario Limonciello
[ Colin Watson ] |
381 |
def connect_to_selection(self, passphrase): |
382 |
model, iterator = self.get_selection().get_selected() |
|
383 |
ssid = model[iterator][0] |
|
384 |
parent = model.iter_parent(iterator) |
|
385 |
if parent: |
|
386 |
self.wifi_model.connect_to_ap(model[parent][0], ssid, passphrase) |
|
471
by Colin Watson
* Handle interface change in ICU 4.8: unknown time zones result in |
387 |
|
432
by Evan Dandrea, Colin Watson, Evan Dandrea, Brian Murray, Luke Yelavich, Mario Limonciello
[ Colin Watson ] |
388 |
|
389 |
GObject.type_register(NetworkManagerTreeView) |
|
390 |
||
480
by Colin Watson
* Convert from deprecated GtkHBox/GtkVBox to GtkBox, and from |
391 |
class NetworkManagerWidget(Gtk.Box): |
432
by Evan Dandrea, Colin Watson, Evan Dandrea, Brian Murray, Luke Yelavich, Mario Limonciello
[ Colin Watson ] |
392 |
__gtype_name__ = 'NetworkManagerWidget' |
393 |
__gsignals__ = { 'connection' : (GObject.SignalFlags.RUN_FIRST, |
|
433
by Evan Dandrea, Colin Watson, Evan Dandrea, Jeremy Bicha
[ Colin Watson ] |
394 |
GObject.TYPE_NONE, (GObject.TYPE_UINT,)), |
395 |
'selection_changed' : (GObject.SignalFlags.RUN_FIRST, |
|
508
by Stéphane Graber, James M. Leddy, Colin Watson, Stéphane Graber, Kent Baxley, Harald Sitter
[ James M. Leddy ] |
396 |
GObject.TYPE_NONE, ()), |
397 |
'pw_validated' : (GObject.SignalFlags.RUN_FIRST, |
|
398 |
GObject.TYPE_NONE, (GObject.TYPE_BOOLEAN,))} |
|
432
by Evan Dandrea, Colin Watson, Evan Dandrea, Brian Murray, Luke Yelavich, Mario Limonciello
[ Colin Watson ] |
399 |
def __init__(self): |
480
by Colin Watson
* Convert from deprecated GtkHBox/GtkVBox to GtkBox, and from |
400 |
Gtk.Box.__init__(self) |
401 |
self.set_orientation(Gtk.Orientation.VERTICAL) |
|
432
by Evan Dandrea, Colin Watson, Evan Dandrea, Brian Murray, Luke Yelavich, Mario Limonciello
[ Colin Watson ] |
402 |
self.set_spacing(12) |
403 |
self.password_entry = Gtk.Entry() |
|
404 |
self.view = NetworkManagerTreeView(self.password_entry, |
|
405 |
self.state_changed) |
|
406 |
scrolled_window = Gtk.ScrolledWindow() |
|
407 |
scrolled_window.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) |
|
408 |
scrolled_window.set_shadow_type(Gtk.ShadowType.IN) |
|
409 |
scrolled_window.add(self.view) |
|
480
by Colin Watson
* Convert from deprecated GtkHBox/GtkVBox to GtkBox, and from |
410 |
self.pack_start(scrolled_window, True, True, 0) |
411 |
self.hbox = Gtk.Box(spacing=6) |
|
432
by Evan Dandrea, Colin Watson, Evan Dandrea, Brian Murray, Luke Yelavich, Mario Limonciello
[ Colin Watson ] |
412 |
self.pack_start(self.hbox, False, True, 0) |
462
by Evan Dandrea
* Expand the list of wireless networks under each card automatically, |
413 |
self.password_label = Gtk.Label('Password:') |
432
by Evan Dandrea, Colin Watson, Evan Dandrea, Brian Murray, Luke Yelavich, Mario Limonciello
[ Colin Watson ] |
414 |
self.password_entry.set_visibility(False) |
415 |
self.password_entry.connect('activate', self.connect_to_ap) |
|
508
by Stéphane Graber, James M. Leddy, Colin Watson, Stéphane Graber, Kent Baxley, Harald Sitter
[ James M. Leddy ] |
416 |
self.password_entry.connect('changed', self.password_entry_changed) |
432
by Evan Dandrea, Colin Watson, Evan Dandrea, Brian Murray, Luke Yelavich, Mario Limonciello
[ Colin Watson ] |
417 |
self.display_password = Gtk.CheckButton('Display password') |
418 |
self.display_password.connect('toggled', self.display_password_toggled) |
|
462
by Evan Dandrea
* Expand the list of wireless networks under each card automatically, |
419 |
self.hbox.pack_start(self.password_label, False, True, 0) |
432
by Evan Dandrea, Colin Watson, Evan Dandrea, Brian Murray, Luke Yelavich, Mario Limonciello
[ Colin Watson ] |
420 |
self.hbox.pack_start(self.password_entry, True, True, 0) |
421 |
self.hbox.pack_start(self.display_password, False, True, 0) |
|
433
by Evan Dandrea, Colin Watson, Evan Dandrea, Jeremy Bicha
[ Colin Watson ] |
422 |
self.hbox.set_sensitive(False) |
423 |
self.selection = self.view.get_selection() |
|
424 |
self.selection.connect('changed', self.changed) |
|
432
by Evan Dandrea, Colin Watson, Evan Dandrea, Brian Murray, Luke Yelavich, Mario Limonciello
[ Colin Watson ] |
425 |
self.show_all() |
462
by Evan Dandrea
* Expand the list of wireless networks under each card automatically, |
426 |
|
427 |
def translate(self, password_label_text, display_password_text): |
|
428 |
self.password_label.set_label(password_label_text) |
|
429 |
self.display_password.set_label(display_password_text) |
|
471
by Colin Watson
* Handle interface change in ICU 4.8: unknown time zones result in |
430 |
|
433
by Evan Dandrea, Colin Watson, Evan Dandrea, Jeremy Bicha
[ Colin Watson ] |
431 |
def get_state(self): |
432 |
return self.view.get_state() |
|
433 |
||
460
by Evan Dandrea
* Don't crash if the user selects the wireless card header and presses |
434 |
def is_row_an_ap(self): |
435 |
return self.view.is_row_an_ap() |
|
436 |
||
433
by Evan Dandrea, Colin Watson, Evan Dandrea, Jeremy Bicha
[ Colin Watson ] |
437 |
def is_row_connected(self): |
438 |
return self.view.is_row_connected() |
|
439 |
||
440 |
def select_usable_row(self): |
|
441 |
self.selection.select_path('0:0') |
|
442 |
||
432
by Evan Dandrea, Colin Watson, Evan Dandrea, Brian Murray, Luke Yelavich, Mario Limonciello
[ Colin Watson ] |
443 |
def state_changed(self, state): |
444 |
self.emit('connection', state) |
|
445 |
||
508
by Stéphane Graber, James M. Leddy, Colin Watson, Stéphane Graber, Kent Baxley, Harald Sitter
[ James M. Leddy ] |
446 |
def password_is_valid(self): |
447 |
passphrase = self.password_entry.get_text() |
|
448 |
if len(passphrase) >= 8 and \ |
|
449 |
len(passphrase) < 64 : |
|
450 |
return True |
|
451 |
if len(passphrase) == 64: |
|
452 |
for c in passphrase: |
|
453 |
if not c in string.hexdigits: return False |
|
454 |
return True |
|
455 |
else: |
|
456 |
return False |
|
457 |
||
432
by Evan Dandrea, Colin Watson, Evan Dandrea, Brian Murray, Luke Yelavich, Mario Limonciello
[ Colin Watson ] |
458 |
def connect_to_ap(self, *args): |
508
by Stéphane Graber, James M. Leddy, Colin Watson, Stéphane Graber, Kent Baxley, Harald Sitter
[ James M. Leddy ] |
459 |
if self.password_is_valid(): |
460 |
passphrase = self.password_entry.get_text() |
|
461 |
self.view.connect_to_selection(passphrase) |
|
432
by Evan Dandrea, Colin Watson, Evan Dandrea, Brian Murray, Luke Yelavich, Mario Limonciello
[ Colin Watson ] |
462 |
|
433
by Evan Dandrea, Colin Watson, Evan Dandrea, Jeremy Bicha
[ Colin Watson ] |
463 |
def disconnect_from_ap(self): |
464 |
self.view.disconnect_from_ap() |
|
508
by Stéphane Graber, James M. Leddy, Colin Watson, Stéphane Graber, Kent Baxley, Harald Sitter
[ James M. Leddy ] |
465 |
|
466 |
def password_entry_changed(self, *args): |
|
467 |
self.emit('pw_validated', self.password_is_valid()) |
|
433
by Evan Dandrea, Colin Watson, Evan Dandrea, Jeremy Bicha
[ Colin Watson ] |
468 |
|
432
by Evan Dandrea, Colin Watson, Evan Dandrea, Brian Murray, Luke Yelavich, Mario Limonciello
[ Colin Watson ] |
469 |
def display_password_toggled(self, *args): |
470 |
self.password_entry.set_visibility(self.display_password.get_active()) |
|
471 |
||
472 |
def changed(self, selection): |
|
473 |
iterator = selection.get_selected()[1] |
|
474 |
if not iterator: |
|
475 |
return
|
|
476 |
row = selection.get_tree_view().get_model()[iterator] |
|
477 |
secure = row[1] |
|
478 |
ssid = row[0] |
|
479 |
if secure: |
|
480 |
self.hbox.set_sensitive(True) |
|
481 |
passphrase = self.view.get_passphrase(ssid) |
|
482 |
self.password_entry.set_text(passphrase) |
|
508
by Stéphane Graber, James M. Leddy, Colin Watson, Stéphane Graber, Kent Baxley, Harald Sitter
[ James M. Leddy ] |
483 |
self.emit('pw_validated', False) |
432
by Evan Dandrea, Colin Watson, Evan Dandrea, Brian Murray, Luke Yelavich, Mario Limonciello
[ Colin Watson ] |
484 |
else: |
485 |
self.hbox.set_sensitive(False) |
|
486 |
self.password_entry.set_text('') |
|
508
by Stéphane Graber, James M. Leddy, Colin Watson, Stéphane Graber, Kent Baxley, Harald Sitter
[ James M. Leddy ] |
487 |
self.emit('pw_validated', True) |
433
by Evan Dandrea, Colin Watson, Evan Dandrea, Jeremy Bicha
[ Colin Watson ] |
488 |
self.emit('selection_changed') |
432
by Evan Dandrea, Colin Watson, Evan Dandrea, Brian Murray, Luke Yelavich, Mario Limonciello
[ Colin Watson ] |
489 |
|
508
by Stéphane Graber, James M. Leddy, Colin Watson, Stéphane Graber, Kent Baxley, Harald Sitter
[ James M. Leddy ] |
490 |
|
432
by Evan Dandrea, Colin Watson, Evan Dandrea, Brian Murray, Luke Yelavich, Mario Limonciello
[ Colin Watson ] |
491 |
GObject.type_register(NetworkManagerWidget) |
492 |
||
493 |
if __name__ == '__main__': |
|
494 |
window = Gtk.Window() |
|
495 |
window.connect('destroy', Gtk.main_quit) |
|
496 |
window.set_size_request(300, 300) |
|
497 |
window.set_border_width(12) |
|
498 |
nm = NetworkManagerWidget() |
|
499 |
window.add(nm) |
|
500 |
window.show_all() |
|
501 |
Gtk.main() |
|
502 |