Merge lp://staging/~nacl/wicd/1.6-urwid-0.9.9-compat into lp://staging/wicd/1.6

Proposed by Andrew Psaltis
Status: Rejected
Rejected by: Adam Blackburn
Proposed branch: lp://staging/~nacl/wicd/1.6-urwid-0.9.9-compat
Merge into: lp://staging/wicd/1.6
Diff against target: 1050 lines (+450/-205)
6 files modified
curses/curses_misc.py (+1/-1)
curses/netentry_curses.py (+4/-7)
curses/popup.py (+312/-0)
curses/prefs_curses.py (+19/-16)
curses/wicd-curses.py (+113/-181)
setup.py (+1/-0)
To merge this branch: bzr merge lp://staging/~nacl/wicd/1.6-urwid-0.9.9-compat
Reviewer Review Type Date Requested Status
Adam Blackburn Disapprove
Review via email: mp+15096@code.staging.launchpad.net
To post a comment you must log in.
Revision history for this message
Andrew Psaltis (nacl) wrote :

These are changes to wicd 1.6 that make wicd-curses more compatible with urwid 0.9.9. These changes break compatibility with urwid 0.9.8.*, and should be included in mainline once urwid 0.9.9 is mainstream in all major distributions.

353. By Andrew Psaltis

Added support for the new and improved DropDown that is based on Ian Ward's PopUpTarget.

354. By Andrew Psaltis

Trimmed some stuff.

355. By Andrew Psaltis

Pad the wpa driver DropDown correctly.

356. By Andrew Psaltis

Moved the padding code over to the DropDown itself and cleaned up some stuff.

357. By Andrew Psaltis

Added callback support to the DropDown and replaced the remaining ComboBoxes
in the big dialogs.

358. By Andrew Psaltis

Fix bug preventing mouse from working with the OptCols.

Revision history for this message
Andrew Psaltis (nacl) wrote :

> These are changes to wicd 1.6 that make wicd-curses more compatible with urwid
> 0.9.9. These changes break compatibility with urwid 0.9.8.*, and should be
> included in mainline once urwid 0.9.9 is mainstream in all major
> distributions.

This code went unstable the last time I modified it, so don't even try to merge it until
the new DropDowns are implemented.

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

Didn't look at the code, but we've decided not to merge this for 1.7.

review: Disapprove

Unmerged revisions

358. By Andrew Psaltis

Fix bug preventing mouse from working with the OptCols.

357. By Andrew Psaltis

Added callback support to the DropDown and replaced the remaining ComboBoxes
in the big dialogs.

356. By Andrew Psaltis

Moved the padding code over to the DropDown itself and cleaned up some stuff.

355. By Andrew Psaltis

Pad the wpa driver DropDown correctly.

354. By Andrew Psaltis

Trimmed some stuff.

353. By Andrew Psaltis

Added support for the new and improved DropDown that is based on Ian Ward's PopUpTarget.

352. By Andrew Psaltis

Fixed up the optcols, apparently, I dropped something. :P

351. By Andrew Psaltis

Merge mainline r463.

350. By Andrew Psaltis

Merge local formatting/print statement removal changes that didn't seem to make it.

349. By Andrew Psaltis

Merge r461 of mainline, providing some bugfixes (some wicd-curses stuff ignored).

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'curses/curses_misc.py'
2--- curses/curses_misc.py 2009-09-29 16:38:11 +0000
3+++ curses/curses_misc.py 2009-11-21 05:36:12 +0000
4@@ -547,7 +547,7 @@
5 def mouse_event(self,size,event,button,x,y,focus):
6 if event == "mouse press":
7 # The keypress dealie in wicd-curses.py expects a list of keystrokes
8- self.callback([self.args])
9+ self.callback([self.args],size=None)
10
11 # htop-style menu menu-bar on the bottom of the screen
12 class OptCols(urwid.WidgetWrap):
13
14=== modified file 'curses/netentry_curses.py'
15--- curses/netentry_curses.py 2009-07-19 02:18:21 +0000
16+++ curses/netentry_curses.py 2009-11-21 05:36:12 +0000
17@@ -23,6 +23,7 @@
18
19 import urwid
20 from curses_misc import TextDialog,DynWrap,MaskingEdit,ComboBox,error
21+from popup import DropDown
22 import wicd.misc as misc
23 from wicd.misc import noneToString, stringToNone, noneToBlankString, to_bool
24
25@@ -95,7 +96,6 @@
26
27
28 self._listbox = urwid.ListBox(walker)
29- #self._frame = urwid.Frame(self._listbox)
30 self._frame = urwid.Frame(self._listbox)
31 self.__super.__init__(self._frame)
32
33@@ -207,7 +207,6 @@
34 AdvancedSettingsDialog.save_settings(self)
35 if self.set_default.get_state():
36 wired.UnsetWiredDefault()
37- print self.set_default.get_state()
38 if self.set_default.get_state():
39 bool = True
40 else:
41@@ -236,7 +235,7 @@
42
43 self.global_settings_chkbox = urwid.CheckBox(global_settings_t)
44 self.encryption_chkbox = urwid.CheckBox(encryption_t,on_state_change=self.encryption_toggle)
45- self.encryption_combo = ComboBox(callback=self.combo_on_change)
46+ self.encryption_combo = DynWrap(DropDown(callback=self.combo_on_change))#ComboBox(callback=self.combo_on_change)
47 self.autoconnect_chkbox = urwid.CheckBox(autoconnect_t)
48 self.pile_encrypt = None
49 # _w is a Frame, _w.body is a ListBox, _w.body.body is the ListWalker :-)
50@@ -255,7 +254,7 @@
51 self.encryption_combo.set_sensitive(new_state)
52 self.pile_encrypt.set_sensitive(new_state)
53
54- def combo_on_change(self,combobox,new_index,user_data=None):
55+ def combo_on_change(self,lb,user_data=None):
56 self.change_encrypt_method()
57
58 def set_values(self):
59@@ -318,7 +317,6 @@
60 def save_settings(self):
61 # Check encryption info
62 if self.encryption_chkbox.get_state():
63- #print "setting encryption info..."
64 encrypt_info = self.encryption_info
65 encrypt_methods = self.encrypt_types
66 self.set_net_prop("enctype",
67@@ -395,10 +393,9 @@
68 # Make this into a listbox?
69 self.pile_encrypt = DynWrap(urwid.Pile(theList),attrs=('editbx','editnfc'))
70 self._w.body.body.insert(self._w.body.body.__len__(),self.pile_encrypt)
71- #self._w.body.body.append(self.pile_encrypt)
72
73 def ready_widgets(self,ui,body):
74 self.ui = ui
75 self.body = body
76- self.encryption_combo.build_combobox(body,ui,14)
77+ #self.encryption_combo.build_combobox(body,ui,14)
78 self.change_encrypt_method()
79
80=== added file 'curses/popup.py'
81--- curses/popup.py 1970-01-01 00:00:00 +0000
82+++ curses/popup.py 2009-11-21 05:36:12 +0000
83@@ -0,0 +1,312 @@
84+#!/usr/bin/env python
85+
86+# Much of this code has been placed into the public domain by its original
87+# author and urwid maintainer, Ian Ward. A very big thanks to him for making
88+# this available to me, it's going to make greatly simplify the wicd-curses
89+# code and make things easier for wicd-curses 2.0 when I actually start working
90+# on it. Urwid in general is fun to work with, and has proven to be a very
91+# robust library.
92+#
93+# ~ Andrew
94+
95+# NOTE:
96+# While much of this file is in the PUBLIC DOMAIN, the DropDown class is
97+# licensed under the GNU General Public License, Version 2 or higher.
98+#
99+# Standard License statement follows:
100+# Copyright (C) 2009 Andrew Psaltis
101+
102+# This file is a part of wicd.
103+#
104+# Wicd is free software; you can redistribute it and/or modify
105+# it under the terms of the GNU General Public License as published by
106+# the Free Software Foundation; either version 2 of the License, or
107+# (at your option) any later version.
108+#
109+# This program is distributed in the hope that it will be useful,
110+# but WITHOUT ANY WARRANTY; without even the implied warranty of
111+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
112+# GNU General Public License for more details.
113+#
114+# You should have received a copy of the GNU General Public License
115+# along with this program; if not, write to the Free Software
116+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
117+# MA 02110-1301, USA.
118+
119+import urwid
120+import urwid.raw_display
121+import sys
122+from curses_misc import SelText
123+
124+### BEGIN PUBLIC DOMAIN CODE ###
125+class PopUpTarget(urwid.WidgetWrap):
126+ def __init__(self, original_widget):
127+ self.__super.__init__(original_widget)
128+ self._pop_up = None
129+ self._current_widget = self._w
130+
131+ def render(self, size, focus=False):
132+ canv = self._current_widget.render(size, focus=focus)
133+ if 'pop_up' in canv.coords:
134+ x, y, (w, h, widget, set_close) = canv.coords['pop_up']
135+ if not self._pop_up:
136+ self._open_pop_up(x, y, w, h, widget)
137+ set_close(self.close_pop_up)
138+ else:
139+ self._update_pop_up(x, y, w, h)
140+ canv = self._current_widget.render(size, focus=focus)
141+
142+ return canv
143+
144+ def _open_pop_up(self, x, y, w, h, widget):
145+ assert not self._pop_up
146+ self._pop_up = widget
147+ self._update_pop_up(x, y, w, h)
148+
149+ def _update_pop_up(self, x, y, w, h):
150+ self._current_widget = urwid.Overlay(self._pop_up, self._w,
151+ ('fixed left', x), w, ('fixed top', y), h)
152+
153+ def close_pop_up(self):
154+ if self._pop_up:
155+ self._pop_up = None
156+ self._current_widget = self._w
157+ self._invalidate()
158+
159+ # use our current widget's methods
160+ selectable = property(lambda self:self._current_widget.selectable)
161+ get_cursor_coords = property(lambda self:self._current_widget.get_cursor_coords)
162+ get_pref_col = property(lambda self:self._current_widget.get_pref_col)
163+ keypress = property(lambda self:self._current_widget.keypress)
164+ move_cursor_to_coords = property(lambda self:self._current_widget.move_cursor_to_coords)
165+ mouse_event = property(lambda self:self._current_widget.mouse_event)
166+ sizing = property(lambda self:self._current_widget.sizing)
167+
168+### BEGIN GPL CODE ###
169+class DropDown(urwid.WidgetWrap):
170+ def __init__(self,items=[],show_indicator=True,popup_attr='body',popup_f_attr='focus',callback=None,user_args=None):
171+ self._popup_attr = popup_attr
172+ self._popup_f_attr = popup_f_attr
173+ self.callback = callback
174+ self.user_args = user_args
175+ self.set_list(items,init=True)
176+ self.lb = urwid.ListBox(self._walker)
177+
178+ if len(self._walker) != 0:
179+ self.text = self.lb.get_focus()[0].base_widget
180+ else:
181+ self.text = SelText("")
182+ self._open_pop_up = False
183+ if show_indicator:
184+ self._cols = urwid.Columns([self.text,('fixed',3,urwid.Padding(urwid.Text('[V]'),'right',3))],dividechars=1)
185+ self.__super.__init__(urwid.Padding(self._cols,'left',self._maxlen+4))
186+ else:
187+ self._cols = urwid.Columns([self.text])
188+ self.__super.__init__(urwid.Padding(self._cols,'left',self._maxlen))
189+
190+ def get_popup_attr(self):
191+ return self._popup_attr
192+ def get_popup_f_attr(self):
193+ return self._popup_f_attr
194+
195+ def set_popup_attr(self,attr):
196+ self._popup_attr = attr
197+ def set_popup_f_attr(self,attr):
198+ self._popup_f_attr = attr
199+
200+ def remove(self,text):
201+ """
202+ Remove the first item with text "text" from the DropDown.
203+
204+ Returns the text if it's in the DropDown, None otherwise
205+
206+ >>> d = DropDown(['one','rediculously','long','string'])
207+ >>> d._maxlen
208+ 12
209+ >>> len('rediculously')
210+ 12
211+ >>> d.remove('rediculously')
212+ 'rediculously'
213+ >>> d._maxlen
214+ 6
215+ >>> d.remove('rediculously')
216+ None
217+ """
218+ swap_out = False
219+ for txt in self._walker:
220+ if txt.text == text:
221+ if self.lb.get_focus()[0] == txt:
222+ swap_out = True
223+ self._walker.remove(txt)
224+ if txt.base_widget.pack()[0] == self._maxlen:
225+ self._adjust_and_align()
226+ if swap_out:
227+ self._cols.widget_list[0] = self.lb.get_focus()[0].base_widget
228+ return text
229+ return None
230+
231+ def _align(self):
232+ self._maxlen = 0
233+ #print >> sys.stderr, "len walker:",len(self._walker)
234+ for i in self._walker:
235+ #print >>sys.stderr, i.base_widget.pack()[0]
236+ if self._maxlen < i.base_widget.pack()[0]:
237+ #print >>sys.stderr, "New maxlen is '%s'" % i.text
238+ self._maxlen = i.base_widget.pack()[0]
239+
240+ def _adjust_and_align(self):
241+ #print >> sys.stderr, "ADJUST_AND_ALIGN"
242+ #print >> sys.stderr, "width is", self._w.width
243+ self._w.width -= self._maxlen
244+ #print >> sys.stderr, "maxlen is", self._maxlen
245+ #print >> sys.stderr, "width is", self._w.width
246+ self._align()
247+ self._w.width += self._maxlen
248+ #print >> sys.stderr, "width is", self._w.width
249+
250+ def get_focus(self):
251+ """
252+ Get the current focus of the widget.
253+
254+ """
255+ return self.lb.get_focus()
256+ def set_focus(self,idx):
257+ self.lb.set_focus(idx)
258+ focus = property(get_focus,set_focus)
259+
260+ def size(self):
261+ return len(self._walker)
262+
263+ def set_list(self,l,init=False):
264+ itexts = [urwid.AttrWrap(SelText(i),self._popup_attr,self._popup_f_attr) for i in l]
265+ self._walker = urwid.SimpleListWalker(itexts)
266+ if init:
267+ self._align()
268+ # Do additional stuff if this is not called from the constructor
269+ else:
270+ #print >>sys.stderr,"ddown says", self._w.width
271+ self.lb.body = self._walker
272+ self._adjust_and_align()
273+ if len(self._walker) != 0:
274+ self._cols.widget_list[0] = self.lb.get_focus()[0].base_widget
275+ else:
276+ self._cols.widget_list[0] = SelText("")
277+ #print >>sys.stderr,"ddown says", self._w.width
278+
279+
280+ def append_list(self,l):
281+ for i in l:
282+ self.append_item(i)
283+ return True
284+
285+ def append_item(self,text):
286+ return self.insert_item(text,len(self._walker))
287+
288+ def insert_item(self,text,idx):
289+ """
290+ Inserts a new item with text 'text' at index 'idx' by calling the
291+ 'insert' method of the DropDown's ListWalker.
292+
293+ This raises an IndexError if 'idx' is greater than the length of the
294+ list, but negative indices are accepted (and are actually used as the
295+ default value for idx). Be careful!
296+
297+ This also raises a TypeError if idx is not an integer
298+
299+ Return value: True
300+ """
301+ if idx > len(self._walker):
302+ raise IndexError("Index '%d' out of listwalker bounds" % idx)
303+ if type(idx) != type(0):
304+ raise TypeError("Index is of type %s, not an integer" % type(idx))
305+ wid = SelText(text)
306+ self._walker.insert(idx,urwid.AttrWrap(wid,self._popup_attr,self._popup_f_attr))
307+ if len(self._walker) == 1:
308+ self._cols.widget_list[0] = self.lb.get_focus()[0].base_widget
309+ if wid.pack()[0] > self._maxlen:
310+ self._w.width -= self._maxlen
311+ self._maxlen = wid.pack()[0]
312+ self._w.width += self._maxlen
313+
314+ return True
315+
316+ def _create_pop_up(self):
317+ class CPane(urwid.Frame):
318+ def __init__(self,body,callback):
319+ self.callback = callback
320+ self.__super.__init__(urwid.LineBox(body))
321+ def keypress(self,size,key):
322+ self.get_body().keypress(size,key)
323+ if key in [ 'enter' ]:
324+ self.do_close()
325+ self.callback()
326+ if key in [ 'esc' ]:
327+ self.do_close()
328+ self.callback(False)
329+ def callback(save=True):
330+ if save:
331+ self.sel_item,self.sel_index = self.lb.get_focus()
332+ self._cols.widget_list[0] = self.sel_item
333+ if self.callback != None:
334+ self.callback(self.lb,self.user_args)
335+ self._open_pop_up = False
336+ self._invalidate()
337+ popup_frame = CPane(self.lb,callback)
338+
339+ def set_close(fn):
340+ popup_frame.do_close = fn
341+ return (self._maxlen+2,len(self._walker)+2,popup_frame,set_close)
342+
343+ def render(self, size, focus=False):
344+ canv = self.__super.render(size, focus)
345+ if self._open_pop_up:
346+ canv = urwid.CompositeCanvas(canv)
347+ # same left column, one line below ourselves
348+ canv.coords['pop_up'] = (0, 1, self._pop_up_window)
349+ return canv
350+
351+ def keypress(self,size,key):
352+ if key in [ "enter", ' ' ]:
353+ self._pop_up_window = self._create_pop_up()
354+ self._open_pop_up = True
355+ self._invalidate()
356+ return key
357+
358+ui = urwid.raw_display.Screen()
359+ui.register_palette([('popbg', 'white', 'dark blue'),
360+ ('body','light gray','black'),
361+ ('focus','black','light gray')])
362+
363+def run():
364+ size = ui.get_cols_rows()
365+ l = ['zero','one','two','three','really_long_item']
366+ #d = DropDown(l)
367+ d = urwid.AttrWrap(DropDown(l),'body','popbg')
368+ #d = DropDown()
369+ fill = urwid.Filler(urwid.Padding(urwid.Columns([urwid.Text("Press space:"),d]), 'center', 40))
370+ #fill = urwid.Filler(ComboBox())
371+ target = PopUpTarget(fill)
372+ #print >>sys.stderr, d._maxlen
373+ #print >>sys.stderr, d._w.width
374+ i = 4
375+ while True:
376+ canvas = target.render(size, True)
377+ ui.draw_screen(size, canvas)
378+
379+ keys = ui.get_input()
380+ if "c" in keys:
381+ d.remove(l[i])
382+ i-=1
383+ for k in keys:
384+ target.keypress(size, k)
385+ if "window resize" in keys:
386+ size = ui.get_cols_rows()
387+
388+
389+if __name__ == '__main__':
390+ if len(sys.argv) > 1 and sys.argv[1] == "test":
391+ import doctest
392+ doctest.testmod()
393+ else:
394+ ui.run_wrapper(run)
395+### END GPL CODE ###
396
397=== modified file 'curses/prefs_curses.py'
398--- curses/prefs_curses.py 2009-10-31 03:52:30 +0000
399+++ curses/prefs_curses.py 2009-11-21 05:36:12 +0000
400@@ -21,7 +21,9 @@
401
402 import urwid
403 import urwid.curses_display
404+from popup import DropDown
405
406+import sys
407 from wicd import misc
408 from wicd import dbusmanager
409 from curses_misc import SelText,DynWrap,DynRadioButton,ComboBox,TabColumns
410@@ -216,11 +218,15 @@
411
412 #### Advanced settings
413 self.wpa_cat = urwid.Text(wpa_cat_t)
414- self.wpa_cbox = ComboBox(wpa_t)
415+ self.wpa_ddown = DropDown()
416+ wpa_txt = urwid.Text(wpa_t)
417+ self.wpa_cols = urwid.Columns([('fixed',wpa_txt.pack()[0],wpa_txt),urwid.AttrWrap(self.wpa_ddown,'body','focus')])
418 self.wpa_warn = urwid.Text(wpa_warn_t)
419
420 self.backend_cat = urwid.Text(backend_cat_t)
421- self.backend_cbox = ComboBox(backend_t)
422+ self.backend_ddown = DropDown()
423+ backend_txt = urwid.Text(backend_t)
424+ self.backend_cols = urwid.Columns([('fixed',backend_txt.pack()[0],backend_txt),urwid.AttrWrap(self.backend_ddown,'body','focus')])
425
426 self.debug_cat = urwid.Text(debug_cat_t)
427 self.debug_mode_checkb = urwid.CheckBox(debug_mode_t)
428@@ -230,9 +236,9 @@
429
430
431 advancedLB = urwid.ListBox([self.wpa_cat,
432- self.wpa_cbox,self.wpa_warn,_blank,
433+ self.wpa_cols,self.wpa_warn,_blank,
434 self.backend_cat,
435- self.backend_cbox,_blank,
436+ self.backend_cols,_blank,
437 self.debug_cat,
438 self.debug_mode_checkb, _blank,
439 self.wless_cat,
440@@ -298,23 +304,24 @@
441 self.wpadrivers.append("ralink_legacy")
442 # Same as above with the dbus.String
443 self.thedrivers = [unicode(w) for w in self.wpadrivers]
444- self.wpa_cbox.set_list(self.thedrivers)
445+ self.wpa_ddown.set_list(self.thedrivers)
446
447 # Pick where to begin first:
448 def_driver = daemon.GetWPADriver()
449 try:
450- self.wpa_cbox.set_focus(self.wpadrivers.index(def_driver))
451+ self.wpa_ddown.set_focus(self.wpadrivers.index(def_driver))
452 except ValueError:
453- pass # It defaults to 0 anyway (I hope)
454+ self.wpa_ddown.set_focus(0)
455+ #self.wpa_cols._invalidate()
456
457 self.backends = daemon.GetBackendList()
458 self.thebackends= [unicode(w) for w in self.backends]
459- self.backend_cbox.set_list(self.thebackends)
460+ self.backend_ddown.set_list(self.thebackends)
461 cur_backend = daemon.GetSavedBackend()
462 try:
463- self.backend_cbox.set_focus(self.thebackends.index(cur_backend))
464+ self.backend_ddown.set_focus(self.thebackends.index(cur_backend))
465 except ValueError:
466- self.backend_cbox.set_focus(0)
467+ self.backend_ddown.set_focus(0)
468
469 # Two last checkboxes
470 self.debug_mode_checkb.set_state(daemon.GetDebugMode())
471@@ -334,7 +341,7 @@
472 self.search_dom.get_edit_text())
473 daemon.SetWirelessInterface(self.wless_edit.get_edit_text())
474 daemon.SetWiredInterface(self.wired_edit.get_edit_text())
475- daemon.SetWPADriver(self.wpadrivers[self.wpa_cbox.get_focus()[1]])
476+ daemon.SetWPADriver(self.wpadrivers[self.wpa_ddown.get_focus()[1]])
477 daemon.SetAlwaysShowWiredInterface(self.always_show_wired_checkb.get_state())
478 daemon.SetAutoReconnect(self.auto_reconn_checkb.get_state())
479 daemon.SetDebugMode(self.debug_mode_checkb.get_state())
480@@ -347,7 +354,7 @@
481 else:
482 daemon.SetWiredAutoConnectMethod(1)
483
484- daemon.SetBackend(self.backends[self.backend_cbox.get_focus()[1]])
485+ daemon.SetBackend(self.backends[self.backend_ddown.get_focus()[1]])
486
487 # External Programs Tab
488 if self.dhcp0.get_state():
489@@ -382,7 +389,3 @@
490 def global_dns_trigger(self,check_box,new_state,user_data=None):
491 for w in self.dns1,self.dns2,self.dns3,self.dns_dom,self.search_dom:
492 w.set_sensitive(new_state)
493-
494- def ready_widgets(self,ui,body):
495- self.wpa_cbox.build_combobox(body,ui,4)
496- self.backend_cbox.build_combobox(body,ui,8)
497
498=== modified file 'curses/wicd-curses.py'
499--- curses/wicd-curses.py 2009-09-29 16:38:11 +0000
500+++ curses/wicd-curses.py 2009-11-21 05:36:12 +0000
501@@ -59,6 +59,7 @@
502 from curses_misc import *
503 from prefs_curses import PrefsDialog
504 import netentry_curses
505+from popup import DropDown, PopUpTarget
506
507 from netentry_curses import WirelessSettingsDialog, WiredSettingsDialog,AdvancedSettingsDialog
508
509@@ -78,47 +79,10 @@
510 from wicd.translations import language
511 for i in language.keys():
512 language[i] = language[i].decode('utf8')
513-
514-########################################
515-##### SUPPORT CLASSES
516-########################################
517-# Yay for decorators!
518-def wrap_exceptions(func):
519- def wrapper(*args, **kargs):
520- try:
521- return func(*args, **kargs)
522- except KeyboardInterrupt:
523- #gobject.source_remove(redraw_tag)
524- loop.quit()
525- ui.stop()
526- print >> sys.stderr, "\n"+language['terminated']
527- #raise
528- except DBusException:
529- #gobject.source_remove(redraw_tag)
530- loop.quit()
531- ui.stop()
532- print >> sys.stderr,"\n"+language['dbus_fail']
533- raise
534- except :
535- # Quit the loop
536- #if 'loop' in locals():
537- loop.quit()
538- # Zap the screen
539- ui.stop()
540- # Print out standard notification:
541- print >> sys.stderr, "\n" + language['exception']
542- # Flush the buffer so that the notification is always above the
543- # backtrace
544- sys.stdout.flush()
545- # Raise the exception
546- #sleep(2)
547- raise
548-
549- wrapper.__name__ = func.__name__
550- wrapper.__module__ = func.__module__
551- wrapper.__dict__ = func.__dict__
552- wrapper.__doc__ = func.__doc__
553- return wrapper
554+# Dummies
555+def handle_exit(f):
556+ return f
557+loop = None
558
559 ########################################
560 ##### SUPPORT FUNCTIONS
561@@ -126,7 +90,7 @@
562
563 # Look familiar? These two functions are clones of functions found in wicd's
564 # gui.py file, except that now set_status is a function passed to them.
565-@wrap_exceptions
566+@handle_exit
567 def check_for_wired(wired_ip,set_status):
568 """ Determine if wired is active, and if yes, set the status. """
569 if wired_ip and wired.CheckPluggedIn():
570@@ -135,7 +99,7 @@
571 else:
572 return False
573
574-@wrap_exceptions
575+@handle_exit
576 def check_for_wireless(iwconfig, wireless_ip, set_status):
577 """ Determine if wireless is active, and if yes, set the status. """
578 if not wireless_ip:
579@@ -485,9 +449,9 @@
580 self.key_edit.set_sensitive(new_state)
581
582 def unhandled_key(self, size, k):
583- if k in ('up','page up'):
584+ if k in ('up', 'page up'):
585 self.frame.set_focus('body')
586- if k in ('down','page down'):
587+ if k in ('down', 'page down'):
588 self.frame.set_focus('footer')
589 if k == 'enter':
590 # pass enter to the "ok" button
591@@ -508,15 +472,14 @@
592 ##### APPLICATION INTERFACE CLASS
593 ########################################
594 # The Whole Shebang
595-class appGUI():
596+class appGUI(urwid.WidgetWrap):
597 """The UI itself, all glory belongs to it!"""
598 def __init__(self):
599 global loop
600- self.size = ui.get_cols_rows()
601 # Happy screen saying that you can't do anything because we're scanning
602 # for networks. :-)
603- self.screen_locker = urwid.Filler(urwid.Text(('important',language['scanning_stand_by']), align='center'))
604- self.no_wlan = urwid.Filler(urwid.Text(('important',language['no_wireless_networks_found']), align='center'))
605+ self.screen_locker = urwid.Filler(urwid.Text(('important', language['scanning_stand_by']), align='center'))
606+ self.no_wlan = urwid.Filler(urwid.Text(('important', language['no_wireless_networks_found']), align='center'))
607 self.TITLE = language['wicd_curses']
608 self.WIRED_IDX = 1
609 self.WLESS_IDX = 3
610@@ -544,16 +507,16 @@
611
612 # Keymappings proposed by nanotube in #wicd
613 keys = [
614- ('H' ,'Help' ,None),
615- ('right','Config',None),
616 #(' ',' ',None),
617- ('C' ,'Connect',None),
618- ('D' ,'Disconn',None),
619- ('R' ,'Refresh',None),
620- ('P' ,'Prefs',None),
621- ('I' ,'Hidden',None),
622- ('A' ,'About',None),
623- ('Q' ,'Quit',loop.quit)
624+ ('H' ,'Help' , None),
625+ ('right','Config', None),
626+ ('C', 'Connect', None),
627+ ('D', 'Disconn', None),
628+ ('R', 'Refresh', None),
629+ ('P', 'Prefs', None),
630+ ('I', 'Hidden', None),
631+ ('A', 'About', None),
632+ ('Q', 'Quit', None)
633 ]
634
635 self.primaryCols = OptCols(keys,self.handle_keys)
636@@ -572,11 +535,13 @@
637 self.init_other_optcols()
638
639 self.frame.set_body(self.thePile)
640+ self.target = PopUpTarget(self.frame)
641+ urwid.WidgetWrap.__init__(self,self.target)
642 # Booleans gallore!
643 self.prev_state = False
644 self.connecting = False
645 self.screen_locked = False
646- self.do_diag_lock = False #Whether the screen is locked beneath a dialog
647+ self.do_diag_lock = False # Whether the screen is locked beneath a dialog
648 self.diag_type = 'none' # The type of dialog that is up
649 self.scanning = False
650
651@@ -584,19 +549,17 @@
652
653 self.update_status()
654
655- #self.max_wait = ui.max_wait
656-
657 def doScan(self, sync=False):
658 self.scanning = True
659 wireless.Scan(False)
660
661 def init_other_optcols(self):
662 # The "tabbed" preferences dialog
663- self.prefCols = OptCols( [ ('f10','OK'),
664- ('page up','Tab Left',),
665- ('page down', 'Tab Right'),
666- ('esc','Cancel') ], self.handle_keys)
667- self.confCols = OptCols( [ ('f10','OK'),
668+ self.prefCols = OptCols( [ ('f10','OK'),
669+ ('page up','Tab Left',),
670+ ('page down', 'Tab Right'),
671+ ('esc','Cancel') ], self.handle_keys)
672+ self.confCols = OptCols( [ ('f10','OK'),
673 ('esc','Cancel') ],self.handle_keys)
674
675 # Does what it says it does
676@@ -619,8 +582,9 @@
677 self.update_ui()
678
679 def raise_hidden_network_dialog(self):
680- dialog = InputDialog(('header',language["select_hidden_essid"]),7,30,language['scan'])
681- exitcode,hidden = dialog.run(ui,self.frame)
682+ dialog = InputDialog(
683+ ('header', language["select_hidden_essid"]), 7, 30, language['scan'])
684+ exitcode,hidden = dialog.run(ui, self.frame)
685 if exitcode != -1:
686 # That dialog will sit there for a while if I don't get rid of it
687 self.update_ui()
688@@ -641,13 +605,11 @@
689 where = None
690 else:
691 where = self.thePile.get_focus().get_focus()[1]
692- #where = self.wlessLB.get_focus()[1]
693 self.focusloc = [wlessorwired,where]
694
695- # Be clunky until I get to a later stage of development.
696 # Update the list of networks. Usually called by DBus.
697- @wrap_exceptions
698- def update_netlist(self,state=None, x=None, force_check=False,firstrun=False):
699+ @handle_exit
700+ def update_netlist(self, state=None, x=None, force_check=False, firstrun=False):
701 # Don't even try to do this if we are running a dialog
702 if self.diag:
703 return
704@@ -663,7 +625,7 @@
705 wiredL,wlessL = gen_network_list()
706
707 self.wiredCB.get_body().set_list(wiredL)
708- self.wiredCB.get_body().build_combobox(self.frame,ui,3)
709+ self.wiredCB.get_body().build_combobox(self.frame, ui, 3)
710 if len(wlessL) != 0:
711 if self.wlessLB == self.no_wlan:
712 self.wlessLB = urwid.ListBox(wlessL)
713@@ -688,7 +650,7 @@
714 else:
715 self.thePile.set_focus(self.wiredCB)
716 else:
717- self.thePile = urwid.Pile([('fixed',2,self.wlessH),self.wlessLB] )
718+ self.thePile = urwid.Pile([('fixed',2,self.wlessH), self.wlessLB] )
719 if not firstrun:
720 self.frame.body = self.thePile
721 if self.focusloc[1] == None:
722@@ -705,7 +667,7 @@
723
724 # Update the footer/status bar
725 conn_status = False
726- @wrap_exceptions
727+ @handle_exit
728 def update_status(self):
729 wired_connecting = wired.CheckIfWiredConnecting()
730 wireless_connecting = wireless.CheckIfWirelessConnecting()
731@@ -715,10 +677,10 @@
732 if self.connecting:
733 if not self.conn_status:
734 self.conn_status = True
735- gobject.timeout_add(250,self.set_connecting_status,fast)
736+ gobject.timeout_add(250, self.set_connecting_status, fast)
737 return True
738 else:
739- if check_for_wired(wired.GetWiredIP(''),self.set_status):
740+ if check_for_wired(wired.GetWiredIP(''), self.set_status):
741 return True
742 if not fast:
743 iwconfig = wireless.GetIwconfig()
744@@ -777,20 +739,17 @@
745 self.tcount+=1
746 toAppend=self.twirl[self.tcount % 4]
747 self.status_label.set_text(text+' '+toAppend)
748- self.update_ui()
749+ if loop is not None:
750+ self.update_ui()
751 return True
752
753- # Make sure the screen is still working by providing a pretty counter.
754- # Not necessary in the end, but I will be using footer1 for stuff in
755- # the long run, so I might as well put something there.
756- #@wrap_exceptions
757- def update_time(self):
758+ #@handle_exit
759+ def update_time(self,loop,data):
760 self.time_label.set_text(strftime('%H:%M:%S'))
761- self.update_ui()
762+ loop.set_alarm_in(0.5, self.update_time)
763 return True
764
765- # Yeah, I'm copying code. Anything wrong with that?
766- #@wrap_exceptions
767+ #@handle_exit
768 def dbus_scan_finished(self):
769 # I'm pretty sure that I'll need this later.
770 #if not self.connecting:
771@@ -798,8 +757,7 @@
772 self.unlock_screen()
773 self.scanning = False
774
775- # Same, same, same, same, same, same
776- #@wrap_exceptions
777+ #@handle_exit
778 def dbus_scan_started(self):
779 self.scanning = True
780 if self.diag_type == 'conf':
781@@ -817,11 +775,14 @@
782 self.frame.set_footer(urwid.Pile([self.primaryCols,self.footer2]))
783 self.update_ui()
784
785- def handle_keys(self,keys):
786+ def keypress(self,size,key):
787+ self.handle_keys([key],size)
788+ return key
789+ def handle_keys(self,keys,size=None):
790 if not self.diag:
791 # Handle keystrokes
792 if "f8" in keys or 'Q' in keys or 'q' in keys:
793- loop.quit()
794+ raise urwid.ExitMainLoop()
795 #return False
796 if "f5" in keys or 'R' in keys:
797 self.lock_screen()
798@@ -849,12 +810,12 @@
799 focus = self.frame.body.get_focus()
800 if focus == self.wiredCB:
801 self.special = focus
802- self.connect("wired",0)
803+ self.connect("wired", 0)
804 else:
805 # wless list only other option, if it is around
806 if self.wlessLB != self.no_wlan:
807 wid,pos = self.thePile.get_focus().get_focus()
808- self.connect("wireless",pos)
809+ self.connect("wireless", pos)
810 if "esc" in keys:
811 # Force disconnect here if connection in progress
812 if self.connecting:
813@@ -863,11 +824,10 @@
814 daemon.SetForcedDisconnect(True)
815 if "P" in keys:
816 if not self.pref:
817- self.pref = PrefsDialog(self.frame,(0,1),ui,
818+ self.pref = PrefsDialog(self.frame, (0,1), ui,
819 dbusmanager.get_dbus_ifaces())
820 self.pref.load_settings()
821- self.pref.ready_widgets(ui,self.frame)
822- self.frame.set_footer(urwid.Pile([self.prefCols,self.footer2]))
823+ self.frame.set_footer(urwid.Pile([self.prefCols, self.footer2]))
824 self.diag = self.pref
825 self.diag_type = 'pref'
826 self.frame.set_body(self.diag)
827@@ -890,9 +850,9 @@
828 else:
829 nettype = 'wireless'
830 netname = str(self.wlessLB.get_focus()[1])
831- run_configscript(self.frame,netname,nettype)
832+ run_configscript(self.frame, netname, nettype)
833 if "O" in keys:
834- exitcode,data = AdHocDialog().run(ui,self.frame)
835+ exitcode,data = AdHocDialog().run(ui, self.frame)
836 #data = (essid,ip,channel,use_ics,use_encrypt,key_edit)
837 if exitcode == 1:
838 wireless.CreateAdHocNetwork(data[0],
839@@ -901,53 +861,36 @@
840 data[5],
841 data[4], False)
842
843- for k in keys:
844- if urwid.is_mouse_event(k):
845- event, button, col, row = k
846- self.frame.mouse_event( self.size,
847- event, button, col, row,
848- focus=True)
849- continue
850- k = self.frame.keypress(self.size,k)
851- if self.diag:
852- if k == 'esc' or k == 'q' or k == 'Q':
853+ if size is not None:
854+ for k in keys:
855+ if urwid.is_mouse_event(k):
856+ event, button, col, row = k
857+ self.frame.mouse_event(size,
858+ event, button, col, row,
859+ focus=True)
860+ continue
861+ k = self.target.keypress(size, k)
862+ elif self.diag:
863+ for k in keys:
864+ # Hackish -> vvvvvvvvvvvvv
865+ k = self.target.keypress(ui.get_cols_rows(), k)
866+ if self.diag:
867+ for k in keys:
868+ if k == 'esc' or k == 'q' or k == 'Q':
869 self.restore_primary()
870 break
871 if k == 'f10':
872 self.diag.save_settings()
873 self.restore_primary()
874 break
875- if k == "window resize":
876- self.size = ui.get_cols_rows()
877- continue
878-
879- def call_update_ui(self,source,cb_condition):
880- self.update_ui(True)
881- return True
882
883 # Redraw the screen
884- @wrap_exceptions
885- def update_ui(self,from_key=False):
886- if not ui._started:
887- return False
888- canvas = self.frame.render( (self.size),True )
889-
890- # Update the screen
891- ui.draw_screen((self.size),canvas)
892- # Get the input data
893- input_data = ui.get_input_nonblocking()
894- max_wait = input_data[0]
895- keys = input_data[1]
896-
897- # Resolve any "alarms" in the waiting
898- if self.update_tag != None:
899- gobject.source_remove(self.update_tag)
900- if from_key:
901- max_wait = 20
902- self.update_tag = gobject.timeout_add(max_wait, \
903- self.update_ui,True)
904- self.handle_keys(keys)
905- return False
906+ @handle_exit
907+ def update_ui(self, from_key=True, from_alarm=False):
908+ global loop
909+ if not loop:
910+ loop._update()
911+ return True
912
913 def connect(self, nettype, networkid, networkentry=None):
914 """ Initiates the connection process in the daemon. """
915@@ -961,12 +904,8 @@
916 wired.ConnectWired()
917 self.update_status()
918
919-########################################
920-##### INITIALIZATION FUNCTIONS
921-########################################
922-
923 def main():
924- global ui, dlogger
925+ global ui, loop, dloggger, handle_exit, palette
926 # We are _not_ python.
927 misc.RenameProcess('wicd-curses')
928
929@@ -980,17 +919,11 @@
930 import urwid.curses_display
931 ui = urwid.curses_display.Screen()
932
933- #if options.debug:
934- # dlogger = logging.getLogger("Debug")
935- # dlogger.setLevel(logging.DEBUG)
936- # dlogger.debug("wicd-curses debug logging started")
937-
938 # Default Color scheme.
939 # Other potential color schemes can be found at:
940 # http://excess.org/urwid/wiki/RecommendedPalette
941-
942 # Thanks to nanotube on #wicd for helping with this
943- ui.register_palette([
944+ palette = [
945 ('body','default','default'),
946 ('focus','black','light gray'),
947 ('header','light blue','default'),
948@@ -1009,43 +942,45 @@
949 ('green','dark green','default'),
950 ('blue','light blue','default'),
951 ('red','dark red','default'),
952- ('bold','white','black','bold')])
953- # This is a wrapper around a function that calls another a function that
954- # is a wrapper around a infinite loop. Fun.
955+ ('bold','white','black','bold')]
956+
957 urwid.set_encoding('utf8')
958- ui.run_wrapper(run)
959-
960-@wrap_exceptions
961+ try:
962+ ui.run_wrapper(run)
963+ except KeyboardInterrupt:
964+ #gobject.source_remove(redraw_tag)
965+ ui.stop()
966+ print >> sys.stderr, language['terminated']
967+ except DBusException:
968+ #gobject.source_remove(redraw_tag)
969+ ui.stop()
970+ print >> sys.stderr, language['dbus_fail']+"\n"
971+ raise
972+ except :
973+ print >> sys.stderr, language['exception']+"\n"
974+ sys.stdout.flush()
975+ raise
976 def run():
977- global loop
978- loop = gobject.MainLoop()
979-
980- ui.set_mouse_tracking()
981+ global ui, loop, dloggger, handle_exit, palette
982 app = appGUI()
983-
984-
985- # Connect signals and whatnot to UI screen control functions
986+ loop = urwid.MainLoop(app, palette, ui,
987+ event_loop=urwid.GLibEventLoop())
988+
989 bus.add_signal_receiver(app.dbus_scan_finished, 'SendEndScanSignal',
990 'org.wicd.daemon.wireless')
991 bus.add_signal_receiver(app.dbus_scan_started, 'SendStartScanSignal',
992 'org.wicd.daemon.wireless')
993- # I've left this commented out many times.
994 bus.add_signal_receiver(app.update_netlist, 'StatusChanged',
995 'org.wicd.daemon')
996- # Update what the interface looks like as an idle function
997- #gobject.idle_add(app.update_ui)
998- # Update the connection status on the bottom every 1.5 s.
999+ #loop.add
1000 gobject.timeout_add(2000,app.update_status)
1001 # This will make sure that it is updated on the second.
1002- gobject.timeout_add(500,app.update_time)
1003-
1004- app.update_ui()
1005- # Get input file descriptors and add callbacks to the ui-updating function
1006- fds = ui.get_input_descriptors()
1007- for fd in fds:
1008- gobject.io_add_watch(fd, gobject.IO_IN,app.call_update_ui)
1009+ loop.set_alarm_in(0.5,app.update_time)
1010+ handle_exit = loop.event_loop.handle_exit
1011 loop.run()
1012
1013+
1014+
1015 # Mostly borrowed from gui.py
1016 def setup_dbus(force=True):
1017 global bus, daemon, wireless, wired, DBUS_AVAIL
1018@@ -1082,14 +1017,11 @@
1019 sys.exit(1)
1020 else:
1021 raise
1022- parser.set_defaults(screen='raw',debug=False)
1023- parser.add_option("-r", "--raw-screen",action="store_const",const='raw'
1024- ,dest='screen',help="use urwid's raw screen controller (default)")
1025- parser.add_option("-c", "--curses-screen",action="store_const",const='curses',dest='screen',help="use urwid's curses screen controller")
1026- parser.add_option("-d", "--debug",action="store_true"
1027- ,dest='debug',help="enable logging of wicd-curses (currently does nothing)")
1028+ parser.set_defaults(screen='raw', debug=False)
1029+ parser.add_option("-r", "--raw-screen", action="store_const", const='raw'
1030+ ,dest='screen', help="use urwid's raw screen controller (default)")
1031+ parser.add_option("-c", "--curses-screen", action="store_const",const='curses',dest='screen', help="use urwid's curses screen controller")
1032+ #parser.add_option("-d", "--debug",action="store_true"
1033+ # ,dest='debug',help="enable logging of wicd-curses (currently does nothing)")
1034 (options,args) = parser.parse_args()
1035 main()
1036- # Make sure that the terminal does not try to overwrite the last line of
1037- # the program, so that everything looks pretty.
1038- #print ""
1039
1040=== modified file 'setup.py'
1041--- setup.py 2009-07-28 02:09:18 +0000
1042+++ setup.py 2009-11-21 05:36:12 +0000
1043@@ -502,6 +502,7 @@
1044 data.append((wpath.lib, ['curses/wicd-curses.py']))
1045 data.append((wpath.lib, ['curses/netentry_curses.py']))
1046 data.append((wpath.lib, ['curses/configscript_curses.py']))
1047+ data.append((wpath.lib, ['curses/popup.py']))
1048 data.append((wpath.bin, ['scripts/wicd-curses']))
1049 if not wpath.no_install_man:
1050 data.append(( wpath.mandir + 'man8/', ['man/wicd-curses.8']))

Subscribers

People subscribed via source and target branches

to status/vote changes: