Merge lp://staging/~oreilldf/wicd/1.6-dan into lp://staging/wicd/1.6

Proposed by Dan O'Reilly
Status: Merged
Approved by: Adam Blackburn
Approved revision: 404
Merged at revision: not available
Proposed branch: lp://staging/~oreilldf/wicd/1.6-dan
Merge into: lp://staging/wicd/1.6
Diff against target: None lines
To merge this branch: bzr merge lp://staging/~oreilldf/wicd/1.6-dan
Reviewer Review Type Date Requested Status
Adam Blackburn Approve
Review via email: mp+6839@code.staging.launchpad.net
To post a comment you must log in.
Revision history for this message
Dan O'Reilly (oreilldf) wrote :

- Make the GUI behave better when a disconnect button is pushed.
- Move some of the libnotify logic to guiutil.py and add support for displaying some error messages in a libnotify pop-up.
- Apply some patches provided by sunseraph. Tweak to the channel regex and checking for a valid AP bssid when monitoring a wireless connection. Set essid, bssid, and channel in separate calls to iwconfig.
- Add caching for ifconfig and iwconfig results in wnettools.py. That way we're not needlessly calling the same command a bunch of times in a short period of time (2 seconds). This removes the need for us to pass around iwconfig/ifconfig output elsewhere, though I've left it in for now.
- Remove unneeded BackendManager instance from networking.py
- Fix last used wired networking autoconnection method
- Try to recover if we load an invalid/nonexistent backend.

Revision history for this message
Adam Blackburn (adamblackburn) wrote :

Looks fine, runs fine here. I don't see any reason not to merge.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'wicd/gui.py'
2--- wicd/gui.py 2009-05-22 03:29:12 +0000
3+++ wicd/gui.py 2009-05-22 19:43:14 +0000
4@@ -286,7 +286,11 @@
5
6 def disconnect_all(self, widget=None):
7 """ Disconnects from any active network. """
8- daemon.Disconnect()
9+ def handler(*args):
10+ gobject.idle_add(self.network_list.set_sensitive, True)
11+
12+ self.network_list.set_sensitive(False)
13+ daemon.Disconnect(reply_handler=handler, error_handler=handler)
14
15 def about_dialog(self, widget, event=None):
16 """ Displays an about dialog. """
17@@ -649,19 +653,41 @@
18 return False
19 return True
20
21+ def _wait_for_connect_thread_start(self):
22+ self.wTree.get_widget("progressbar").pulse()
23+ if not self._connect_thread_started:
24+ return True
25+ else:
26+ misc.timeout_add(2, self.update_statusbar)
27+ self.update_statusbar()
28+ return False
29+
30 def connect(self, widget, nettype, networkid, networkentry):
31 """ Initiates the connection process in the daemon. """
32+ def handler(*args):
33+ self._connect_thread_started = True
34+
35 cancel_button = self.wTree.get_widget("cancel_button")
36 cancel_button.set_sensitive(True)
37+ self.network_list.set_sensitive(False)
38+ if self.statusID:
39+ gobject.idle_add(self.status_bar.remove, 1, self.statusID)
40+ gobject.idle_add(self.set_status, language["disconnecting_active"])
41+ gobject.idle_add(self.status_area.show_all)
42+ self.wait_for_events()
43+ self._connect_thread_started = False
44 if nettype == "wireless":
45 if not self.check_encryption_valid(networkid,
46 networkentry.advanced_dialog):
47 self.edit_advanced(None, None, nettype, networkid, networkentry)
48 return False
49- wireless.ConnectWireless(networkid)
50+ wireless.ConnectWireless(networkid, reply_handler=handler,
51+ error_handler=handler)
52 elif nettype == "wired":
53- wired.ConnectWired()
54- self.update_statusbar()
55+ wired.ConnectWired(reply_handler=handler, error_handler=handler)
56+
57+ gobject.source_remove(self.update_cb)
58+ misc.timeout_add(100, self._wait_for_connect_thread_start, milli=True)
59
60 def disconnect(self, widget, nettype, networkid, networkentry):
61 """ Disconnects from the given network.
62@@ -674,13 +700,18 @@
63 networkentry -- The NetworkEntry containing the disconnect button.
64
65 """
66+ def handler(*args):
67+ gobject.idle_add(self.network_list.set_sensitive, True)
68+
69 widget.hide()
70 networkentry.connect_button.show()
71 daemon.SetForcedDisconnect(True)
72+ self.network_list.set_sensitive(False)
73 if nettype == "wired":
74- wired.DisconnectWired()
75+ wired.DisconnectWired(reply_handler=handler, error_handler=handler)
76 else:
77- wireless.DisconnectWireless()
78+ wireless.DisconnectWireless(reply_handler=handler,
79+ error_handler=handler)
80
81 def wait_for_events(self, amt=0):
82 """ Wait for any pending gtk events to finish before moving on.
83
84=== modified file 'wicd/guiutil.py'
85--- wicd/guiutil.py 2009-05-10 14:51:49 +0000
86+++ wicd/guiutil.py 2009-05-22 19:43:14 +0000
87@@ -17,11 +17,39 @@
88 #
89
90 import gtk
91-
92+import os.path
93+
94+import wpath
95+
96+HAS_NOTIFY = True
97+try:
98+ import pynotify
99+ if not pynotify.init("Wicd"):
100+ print 'Could not initalize pynotify'
101+ HAS_NOTIFY = False
102+except ImportError:
103+ print "Importing pynotify failed, notifications disabled."
104+ HAS_NOTIFY = False
105+
106+print "Has notifications support", HAS_NOTIFY
107+
108+if wpath.no_use_notifications:
109+ print 'Notifications disabled during setup.py configure'
110+
111+def can_use_notify():
112+ use_notify = os.path.exists(os.path.join(os.path.expanduser('~/.wicd'),
113+ 'USE_NOTIFICATIONS')
114+ )
115+ return use_notify and HAS_NOTIFY and not wpath.no_use_notifications
116+
117 def error(parent, message, block=True):
118 """ Shows an error dialog. """
119 def delete_event(dialog, id):
120 dialog.destroy()
121+ if can_use_notify() and not block:
122+ notification = pynotify.Notification("ERROR", message, "error")
123+ notification.show()
124+ return
125 dialog = gtk.MessageDialog(parent, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR,
126 gtk.BUTTONS_OK)
127 dialog.set_markup(message)
128
129=== modified file 'wicd/misc.py'
130--- wicd/misc.py 2009-04-12 02:41:34 +0000
131+++ wicd/misc.py 2009-05-22 19:43:14 +0000
132@@ -492,7 +492,7 @@
133 def checkboxTextboxToggle(checkbox, textboxes):
134 for textbox in textboxes:
135 textbox.set_sensitive(checkbox.get_active())
136-
137+
138 def threaded(f):
139 """ A decorator that will make any function run in a new thread. """
140
141
142=== modified file 'wicd/monitor.py'
143--- wicd/monitor.py 2009-04-27 23:17:01 +0000
144+++ wicd/monitor.py 2009-05-22 19:43:14 +0000
145@@ -174,6 +174,9 @@
146 self.iwconfig = ''
147 # Reset this, just in case.
148 self.tried_reconnect = False
149+ bssid = wireless.GetApBssid()
150+ if not bssid:
151+ return False
152
153 wifi_signal = self._get_printable_sig_strength()
154 if wifi_signal == 0:
155
156=== modified file 'wicd/networking.py'
157--- wicd/networking.py 2009-04-20 01:13:58 +0000
158+++ wicd/networking.py 2009-05-22 19:43:14 +0000
159@@ -154,7 +154,6 @@
160 self.disconnect_script = None
161 self.driver = None
162 self.iface = None
163- self.backend_manager = BackendManager()
164
165 def get_debug(self): return self._debug
166 def set_debug(self, value):
167
168=== modified file 'wicd/translations.py'
169--- wicd/translations.py 2009-05-05 04:56:09 +0000
170+++ wicd/translations.py 2009-05-22 19:43:14 +0000
171@@ -55,7 +55,7 @@
172 _ = lang.gettext
173 return _
174
175-# Generated automatically on Mon, 04 May 2009 23:56:04 CDT
176+# Generated automatically on Sun, 17 May 2009 19:17:27 CDT
177 _ = get_gettext()
178 language = {}
179 language['resetting_ip_address'] = _('''Resetting IP address...''')
180@@ -215,3 +215,4 @@
181 language['establishing_connection'] = _('''Establishing connection...''')
182 language['association_failed'] = _('''Connection failed: Could not contact the wireless access point.''')
183 language['access_denied'] = _('''Unable to contact the wicd dameon due to an access denied error from DBus. Please check your DBus configuration.''')
184+language['disconnecting_active'] = _('''Disconnecting active connections...''')
185
186=== modified file 'wicd/wicd-client.py'
187--- wicd/wicd-client.py 2009-05-10 17:53:54 +0000
188+++ wicd/wicd-client.py 2009-05-22 19:43:14 +0000
189@@ -43,16 +43,15 @@
190 import atexit
191 from dbus import DBusException
192
193+import pygtk
194+pygtk.require('2.0')
195+
196 HAS_NOTIFY = True
197 try:
198- import pygtk
199- pygtk.require('2.0')
200 import pynotify
201 if not pynotify.init("Wicd"):
202- print 'could not initalize pynotify'
203 HAS_NOTIFY = False
204 except ImportError:
205- print 'import failed'
206 HAS_NOTIFY = False
207
208 # Wicd specific imports
209@@ -60,7 +59,7 @@
210 from wicd import misc
211 from wicd import gui
212 from wicd import dbusmanager
213-from wicd.guiutil import error
214+from wicd.guiutil import error, can_use_notify
215
216 from wicd.translations import language
217
218@@ -75,11 +74,6 @@
219 print 'Unable to load tray icon: Missing both egg.trayicon and gtk.StatusIcon modules.'
220 ICON_AVAIL = False
221
222-print "Has notifications support", HAS_NOTIFY
223-
224-if wpath.no_use_notifications:
225- print 'Notifications disabled during setup.py configure'
226-
227 misc.RenameProcess("wicd-client")
228
229 if __name__ == '__main__':
230@@ -163,10 +157,6 @@
231 self.last_state = None
232 self.should_notify = True
233
234- self.use_notify = os.path.exists(os.path.join(
235- os.path.expanduser('~/.wicd'),
236- 'USE_NOTIFICATIONS'))
237-
238 if DBUS_AVAIL:
239 self.update_tray_icon()
240 else:
241@@ -272,10 +262,8 @@
242 [state, info] = daemon.GetConnectionStatus()
243
244 # should this state change display a notification?
245- self.should_notify = not wpath.no_use_notifications and \
246- (self.last_state != state) and \
247- HAS_NOTIFY and \
248- self.use_notify
249+ self.should_notify = (can_use_notify() and
250+ self.last_state != state)
251
252 self.last_state = state
253
254
255=== modified file 'wicd/wicd-daemon.py'
256--- wicd/wicd-daemon.py 2009-05-03 13:58:11 +0000
257+++ wicd/wicd-daemon.py 2009-05-24 21:11:14 +0000
258@@ -203,6 +203,16 @@
259 def SetBackend(self, backend):
260 """ Sets a new backend. """
261 print "setting backend to %s" % backend
262+ backends = networking.BACKEND_MGR.get_available_backends()
263+ if backend not in backends:
264+ print "backend %s not available, trying to fallback to another" % backend
265+ try:
266+ backend = backends[0]
267+ except IndexError:
268+ print "ERROR: no backends available!"
269+ return
270+ else:
271+ print "Fell back to backend %s" % backend
272 self.config.set("Settings", "backend", backend, write=True)
273 if backend != self.GetCurrentBackend():
274 self.suspended = True
275@@ -1300,6 +1310,7 @@
276 self.daemon = daemon
277 self.wired = wired
278 self._debug_mode = debug
279+ self._cur_wired_prof_name = ""
280 self.WiredNetwork = {}
281 self.config = ConfigManager(os.path.join(wpath.etc,
282 "wired-settings.conf"),
283@@ -1413,6 +1424,8 @@
284 self.wired.disconnect_script = self.GetWiredProperty("disconnectscript")
285 self.daemon.wireless_bus.wifi.Disconnect()
286 self.daemon.SetForcedDisconnect(False)
287+ self.UnsetWiredLastUsed()
288+ self.config.set(self._cur_wired_prof_name, "lastused", True, write=True)
289 self.wired.Connect(self.WiredNetwork, debug=self.debug_mode)
290 self.daemon.UpdateState()
291
292@@ -1511,8 +1524,10 @@
293 profile['use_global_dns'] = bool(profile.get('use_global_dns'))
294 profile['use_static_dns'] = bool(profile.get('use_static_dns'))
295 self.WiredNetwork = profile
296+ self._cur_wired_prof_name = profilename
297 return "100: Loaded Profile"
298 else:
299+ self._cur_wired_prof_name = ""
300 self.WiredNetwork = {}
301 return "500: Profile Not Found"
302
303
304=== modified file 'wicd/wnettools.py'
305--- wicd/wnettools.py 2009-05-19 23:12:58 +0000
306+++ wicd/wnettools.py 2009-05-22 19:43:14 +0000
307@@ -44,7 +44,7 @@
308 _re_mode = (re.I | re.M | re.S)
309 essid_pattern = re.compile('.*ESSID:"?(.*?)"?\s*\n', _re_mode)
310 ap_mac_pattern = re.compile('.*Address: (.*?)\n', _re_mode)
311-channel_pattern = re.compile('.*Channel:? ?(\d\d?)', _re_mode)
312+channel_pattern = re.compile('.*Channel:?=? ?(\d\d?)', _re_mode)
313 strength_pattern = re.compile('.*Quality:?=? ?(\d+)\s*/?\s*(\d*)', _re_mode)
314 altstrength_pattern = re.compile('.*Signal level:?=? ?(\d+)\s*/?\s*(\d*)', _re_mode)
315 signaldbm_pattern = re.compile('.*Signal level:?=? ?(-\d\d*)', _re_mode)
316@@ -83,6 +83,31 @@
317 return translate(str(string), blank_trans, blacklist_strict)
318 else:
319 return string
320+
321+_cache = {}
322+def timedcache(duration=5):
323+ """ A caching decorator for use with wnettools methods.
324+
325+ Caches the results of a function for a given number of
326+ seconds (defaults to 5).
327+
328+ """
329+ def _timedcache(f):
330+ def __timedcache(self, *args, **kwargs):
331+ key = str(args) + str(kwargs) + str(f)
332+ if hasattr(self, 'iface'):
333+ key += self.iface
334+ if (key in _cache and
335+ (time.time() - _cache[key]['time']) < duration):
336+ return _cache[key]['value']
337+ else:
338+ value = f(self, *args, **kwargs)
339+ _cache[key] = { 'time' : time.time(), 'value' : value }
340+ return value
341+
342+ return __timedcache
343+
344+ return _timedcache
345
346 def GetDefaultGateway():
347 """ Attempts to determine the default gateway by parsing route -n. """
348@@ -349,6 +374,14 @@
349 if self.verbose: print cmd
350 misc.Run(cmd)
351 return True
352+
353+ @timedcache(2)
354+ @neediface("")
355+ def GetIfconfig(self):
356+ """ Runs ifconfig and returns the output. """
357+ cmd = "ifconfig %s" % self.iface
358+ if self.verbose: print cmd
359+ return misc.Run(cmd)
360
361 @neediface("")
362 def SetAddress(self, ip=None, netmask=None, broadcast=None):
363@@ -596,9 +629,7 @@
364
365 """
366 if not ifconfig:
367- cmd = 'ifconfig ' + self.iface
368- if self.verbose: print cmd
369- output = misc.Run(cmd)
370+ output = self.GetIfconfig()
371 else:
372 output = ifconfig
373 return misc.RunRegex(ip_pattern, output)
374@@ -635,9 +666,7 @@
375 def _slow_is_up(self, ifconfig=None):
376 """ Determine if an interface is up using ifconfig. """
377 if not ifconfig:
378- cmd = "ifconfig " + self.iface
379- if self.verbose: print cmd
380- output = misc.Run(cmd)
381+ output = self.GetIfconfig()
382 else:
383 output = ifconfig
384 lines = output.split('\n')
385@@ -800,6 +829,7 @@
386
387 return radiostatus
388
389+ @timedcache(2)
390 @neediface(False)
391 def GetIwconfig(self):
392 """ Returns the output of iwconfig for this interface. """
393@@ -965,12 +995,17 @@
394
395 """
396 cmd = ['iwconfig', self.iface, 'essid', essid]
397+ if self.verbose: print str(cmd)
398+ misc.Run(cmd)
399+ base = "iwconfig %s" % self.iface
400 if channel and str(channel).isdigit():
401- cmd.extend(['channel', str(channel)])
402+ cmd = "%s channel %s" % (base, str(channel))
403+ if self.verbose: print cmd
404+ misc.Run(cmd)
405 if bssid:
406- cmd.extend(['ap', bssid])
407- if self.verbose: print str(cmd)
408- misc.Run(cmd)
409+ cmd = "%s ap %s" % (base, bssid)
410+ if self.verbose: print cmd
411+ misc.Run(cmd)
412
413 def GeneratePSK(self, network):
414 """ Generate a PSK using wpa_passphrase.
415@@ -1237,9 +1272,7 @@
416 def GetBSSID(self, iwconfig=None):
417 """ Get the MAC address for the interface. """
418 if not iwconfig:
419- cmd = 'iwconfig ' + self.iface
420- if self.verbose: print cmd
421- output = misc.Run(cmd)
422+ output = self.GetIwconfig()
423 else:
424 output = iwconfig
425
426@@ -1250,9 +1283,7 @@
427 def GetCurrentBitrate(self, iwconfig=None):
428 """ Get the current bitrate for the interface. """
429 if not iwconfig:
430- cmd = 'iwconfig ' + self.iface
431- if self.verbose: print cmd
432- output = misc.Run(cmd)
433+ output = self.GetIwconfig()
434 else:
435 output = iwconfig
436
437@@ -1263,9 +1294,7 @@
438 def GetOperationalMode(self, iwconfig=None):
439 """ Get the operational mode for the interface. """
440 if not iwconfig:
441- cmd = 'iwconfig ' + self.iface
442- if self.verbose: print cmd
443- output = misc.Run(cmd)
444+ output = self.GetIwconfig()
445 else:
446 output = iwconfig
447
448@@ -1313,9 +1342,7 @@
449
450 """
451 if not iwconfig:
452- cmd = 'iwconfig ' + self.iface
453- if self.verbose: print cmd
454- output = misc.Run(cmd)
455+ output = self.GetIwconfig()
456 else:
457 output = iwconfig
458 return self._get_link_quality(output)
459@@ -1329,9 +1356,7 @@
460
461 """
462 if not iwconfig:
463- cmd = 'iwconfig ' + self.iface
464- if self.verbose: print cmd
465- output = misc.Run(cmd)
466+ output = self.GetIwconfig()
467 else:
468 output = iwconfig
469 signaldbm_pattern = re.compile('.*Signal level:?=? ?(-\d\d*)',
470@@ -1348,9 +1373,7 @@
471
472 """
473 if not iwconfig:
474- cmd = 'iwconfig ' + self.iface
475- if self.verbose: print cmd
476- output = misc.Run(cmd)
477+ output = self.GetIwconfig()
478 else:
479 output = iwconfig
480 network = misc.RunRegex(re.compile('.*ESSID:"(.*?)"',

Subscribers

People subscribed via source and target branches

to status/vote changes: