1
0
mirror of https://github.com/gryf/wicd.git synced 2025-12-19 20:38:00 +01:00

Merged curses-uimod. It works well enough for me at the moment.

This commit is contained in:
Andrew Psaltis
2009-03-21 23:21:31 -04:00
14 changed files with 584 additions and 445 deletions

View File

@@ -14,15 +14,15 @@ All features that I plan on implementing (that are not mentioned above) are
listed the TODO file in this same directory. If you want any other features, listed the TODO file in this same directory. If you want any other features,
ask me. I try to be on the #wicd Freenode IRC channel most of the time. ask me. I try to be on the #wicd Freenode IRC channel most of the time.
Controls: Controls (most of these should be viewable in wicd-curses itself):
F5 : refresh wireless networks F5 : refresh wireless networks
F8 or Q or q: quit F8 Q q : quit
D : disconnect from all active networks D : disconnect from all active networks
ESC : if connecting to a network, stop doing so ESC : if connecting to a network, stop doing so
ENTER : Attempt connection to selected network ENTER C : Attempt connection to selected network
P : Display preferences dialog P : Display preferences dialog
C : Display network configuration for selected network right arrow : Display network configuration for selected network
A : Display "About" dialog A : Display "About" dialog
I : Raise the "Scan for hidden networks" dialog I : Raise the "Scan for hidden networks" dialog
H or h or ? : Raise help dialog H or h or ? : Raise help dialog
@@ -33,7 +33,7 @@ O : Raise ad-hoc network dialog
IN DIALOGS (Meta usually is "Alt"): IN DIALOGS (Meta usually is "Alt"):
ESC or Q: Quit dialog without saving information (if present) ESC or Q: Quit dialog without saving information (if present)
Meta+Left/Right: Change tabs Left/Right (if tabs present) Meta+[/]: Change tabs Left/Right (if tabs present)
Meta+Enter : Quit dialog and save information Meta+Enter : Quit dialog and save information
FAQ (WIP): FAQ (WIP):

View File

@@ -49,7 +49,12 @@ class SelText(urwid.Text):
"""Don't handle any keys.""" """Don't handle any keys."""
return key return key
# This class is annoying. ^_^ # ListBox that can't be selected.
class NSelListBox(urwid.ListBox):
def selectable(self):
return False
# This class is annoying. :/
class DynWrap(urwid.AttrWrap): class DynWrap(urwid.AttrWrap):
""" """
Makes an object have mutable selectivity. Attributes will change like Makes an object have mutable selectivity. Attributes will change like
@@ -136,7 +141,8 @@ class MaskingEdit(urwid.Edit):
Render edit widget and return canvas. Include cursor when in Render edit widget and return canvas. Include cursor when in
focus. focus.
""" """
# If we aren't masking anything ATM, then act like an Edit. No problems. # If we aren't masking anything ATM, then act like an Edit.
# No problems.
if self.mask_mode == "off" or (self.mask_mode == 'no_focus' and focus == True): if self.mask_mode == "off" or (self.mask_mode == 'no_focus' and focus == True):
canv = self.__super.render((maxcol,),focus) canv = self.__super.render((maxcol,),focus)
# The cache messes this thing up, because I am totally changing what # The cache messes this thing up, because I am totally changing what
@@ -165,9 +171,10 @@ class TabColumns(urwid.WidgetWrap):
attr = normal attributes attr = normal attributes
attrsel = attribute when active attrsel = attribute when active
""" """
def __init__(self,tab_str,tab_wid,title,bottom_part,attr=('body','focus'), # FIXME Make the bottom_part optional
def __init__(self,tab_str,tab_wid,title,bottom_part=None,attr=('body','focus'),
attrsel='tab active', attrtitle='header'): attrsel='tab active', attrtitle='header'):
self.bottom_part = bottom_part #self.bottom_part = bottom_part
#title_wid = urwid.Text((attrtitle,title),align='right') #title_wid = urwid.Text((attrtitle,title),align='right')
column_list = [] column_list = []
for w in tab_str: for w in tab_str:
@@ -189,7 +196,7 @@ class TabColumns(urwid.WidgetWrap):
self.pile = urwid.Pile([ self.pile = urwid.Pile([
('fixed',1,urwid.Filler(self.columns,'top')), ('fixed',1,urwid.Filler(self.columns,'top')),
urwid.Filler(lbox,'top',height=('relative',99)), urwid.Filler(lbox,'top',height=('relative',99)),
('fixed',1,urwid.Filler(self.bottom_part,'bottom')) #('fixed',1,urwid.Filler(self.bottom_part,'bottom'))
]) ])
if not firstrun: if not firstrun:
self.frame.set_body(self.pile) self.frame.set_body(self.pile)
@@ -199,12 +206,13 @@ class TabColumns(urwid.WidgetWrap):
return True return True
def keypress(self,size,key): def keypress(self,size,key):
self._w.keypress(size,key) if key == "meta [" or key == "meta ]":
if key == "meta left" or key == "meta right":
self._w.get_body().set_focus(0) self._w.get_body().set_focus(0)
self.keypress(size,key[5:]) newK = 'left' if key[-1] == '[' else 'right'
self.keypress(size,newK)
self._w.get_body().set_focus(1) self._w.get_body().set_focus(1)
else: else:
key = self._w.keypress(size,key)
wid = self.pile.get_focus().get_body() wid = self.pile.get_focus().get_body()
if wid == self.columns: if wid == self.columns:
# lw = self.listbox.body # lw = self.listbox.body
@@ -213,8 +221,20 @@ class TabColumns(urwid.WidgetWrap):
self.columns.get_focus().set_attr('tab active') self.columns.get_focus().set_attr('tab active')
self.active_tab = self.columns.get_focus() self.active_tab = self.columns.get_focus()
self.gen_pile(self.tab_map[self.active_tab]) self.gen_pile(self.tab_map[self.active_tab])
return key
return key
# self.listbox.body = lw # self.listbox.body = lw
def mouse_event(self,size,event,button,x,y,focus):
wid = self.pile.get_focus().get_body()
if wid == self.columns:
self.active_tab.set_attr('body')
self._w.mouse_event(size,event,button,x,y,focus)
if wid == self.columns:
self.active_tab.set_attr('body')
self.columns.get_focus().set_attr('tab active')
self.active_tab = self.columns.get_focus()
self.gen_pile(self.tab_map[self.active_tab])
### Combo box code begins here ### Combo box code begins here
@@ -340,7 +360,6 @@ class ComboBox(urwid.WidgetWrap):
def build_combobox(self,parent,ui,row): def build_combobox(self,parent,ui,row):
str,trash = self.label.get_text() str,trash = self.label.get_text()
self.cbox = DynWrap(SelText([self.list[self.focus]+' vvv']), self.cbox = DynWrap(SelText([self.list[self.focus]+' vvv']),
attrs=self.attrs,focus_attr=self.focus_attr) attrs=self.attrs,focus_attr=self.focus_attr)
if str != '': if str != '':
@@ -438,7 +457,8 @@ class Dialog2(urwid.WidgetWrap):
def run(self,ui,parent): def run(self,ui,parent):
ui.set_mouse_tracking() ui.set_mouse_tracking()
size = ui.get_cols_rows() size = ui.get_cols_rows()
overlay = urwid.Overlay(urwid.LineBox(self.view), parent, 'center', self.width, overlay = urwid.Overlay(urwid.LineBox(self.view),
parent, 'center', self.width,
'middle', self.height) 'middle', self.height)
try: try:
while True: while True:
@@ -512,3 +532,98 @@ class InputDialog(Dialog2):
def on_exit(self, exitcode): def on_exit(self, exitcode):
return exitcode, self.edit.get_edit_text() return exitcode, self.edit.get_edit_text()
class ClickCols(urwid.WidgetWrap):
def __init__(self,items,callback=None,args=None):
cols = urwid.Columns(items)
self.__super.__init__(cols)
self.callback = callback
self.args = args
def mouse_event(self,size,event,button,x,y,focus):
if event == "mouse press":
# The keypress dealie in wicd-curses.py expects a list of keystrokes
self.callback([self.args])
# htop-style menu menu-bar on the bottom of the screen
class OptCols(urwid.WidgetWrap):
# tuples = [(key,desc)], on_event gets passed a key
# attrs = (attr_key,attr_desc)
# mentions of 'left' and right will be converted to <- and -> respectively
def __init__(self,tuples,handler,attrs=('body','infobar'),debug=False):
# Find the longest string. Keys for this bar should be no greater than
# 2 characters long (e.g., -> for left)
#maxlen = 6
#for i in tuples:
# newmax = len(i[0])+len(i[1])
# if newmax > maxlen:
# maxlen = newmax
# Construct the texts
textList = []
i = 0
# callbacks map the text contents to its assigned callback.
self.callbacks = []
for cmd in tuples:
splitcmd = cmd[0].split()
key = ''
for part in splitcmd:
if part == 'ctrl':
key+='C^'
elif part == 'meta':
key+='M^'
else:
if part == 'left':
key += '<-'
elif part == 'right':
key += '->'
elif part == 'esc':
key += 'ESC'
else:
key += part
#theText = urwid.Text([(attrs[0],cmd[0]),(attrs[1],cmd[1])])
if debug:
callback = self.debugClick
args = cmd[1]
else:
callback = handler
args = cmd[0]
#self.callbacks.append(cmd[2])
col = ClickCols([
('fixed',len(key)+1,urwid.Text((attrs[0],key+':')) ),
urwid.AttrWrap(urwid.Text(cmd[1]),attrs[1])],
callback,args)
#if i != len(tuples)-1:
# textList.append(('fixed',maxlen,col))
#else: # The last one
textList.append(col)
i+=1
if debug:
self.debug = urwid.Text("DEBUG_MODE")
textList.append(('fixed',10,self.debug))
cols = urwid.Columns(textList)
self.__super.__init__(cols)
def debugClick(self,args):
self.debug.set_text(args)
def mouse_event(self,size,event,button,x,y,focus):
# Widgets are evenly long (as of current), so...
return self._w.mouse_event(size,event,button,x,y,focus)
"""
if self.debug:
if x > size[0]-10:
return
widsize = (size[0]-10)/len(self.callbacks)
else:
widsize = size[0]/len(self.callbacks)
widnum = x/widsize
if self.debug:
text = str(widnum)
if self.callbacks[widnum] == None:
text += " None"
self.debug.set_text(text)
elif self.callbacks[widnum] != None:
self.callbacks[widnum]()
"""

View File

@@ -82,13 +82,6 @@ class AdvancedSettingsDialog(urwid.WidgetWrap):
_blank = urwid.Text('') _blank = urwid.Text('')
# Buttons. These need to be added to the list in superclasses.
self.OK_PRESSED= False
self.CANCEL_PRESSED = False
self.ok_button = urwid.AttrWrap(urwid.Button('OK',self.ok_callback),'body','focus')
self.cancel_button = urwid.AttrWrap(urwid.Button('Cancel',self.cancel_callback),'body','focus')
self.button_cols = urwid.Columns([self.ok_button,self.cancel_button])
walker = urwid.SimpleListWalker([self.static_ip_cb, walker = urwid.SimpleListWalker([self.static_ip_cb,
self.ip_edit, self.ip_edit,
self.netmask_edit, self.netmask_edit,
@@ -103,16 +96,9 @@ class AdvancedSettingsDialog(urwid.WidgetWrap):
self._listbox = urwid.ListBox(walker) self._listbox = urwid.ListBox(walker)
#self._frame = urwid.Frame(self._listbox) #self._frame = urwid.Frame(self._listbox)
self._frame = urwid.Frame(self._listbox,footer=self.button_cols) self._frame = urwid.Frame(self._listbox)
self.__super.__init__(self._frame) self.__super.__init__(self._frame)
# Button callbacks
def ok_callback(self,button_object,user_data=None):
self.OK_PRESSED = True
def cancel_callback(self,button_object,user_data=None):
self.CANCEL_PRESSED = True
def static_ip_set_state(self,checkb,new_state,user_data=None): def static_ip_set_state(self,checkb,new_state,user_data=None):
for w in [ self.ip_edit,self.netmask_edit,self.gateway_edit ]: for w in [ self.ip_edit,self.netmask_edit,self.gateway_edit ]:
w.set_sensitive(new_state) w.set_sensitive(new_state)
@@ -164,54 +150,9 @@ class AdvancedSettingsDialog(urwid.WidgetWrap):
self.set_net_prop("dns1", '') self.set_net_prop("dns1", '')
self.set_net_prop("dns2", '') self.set_net_prop("dns2", '')
self.set_net_prop("dns3", '') self.set_net_prop("dns3", '')
# Prevent comboboxes from dying.
def prerun(self,ui,dim,display): def ready_widgets(self,ui,body):
pass pass
def run(self,ui,dim,display):
self.ui = ui
self.parent = display
width,height = ui.get_cols_rows()
self.overlay = urwid.Overlay(self, display, ('fixed left', 0),width
, ('fixed top',1), height-3)
self.prerun(ui,dim,display)
#self.ready_comboboxes(ui,overlay)
keys = True
while True:
if keys:
ui.draw_screen(dim, self.overlay.render(dim, True))
keys = ui.get_input()
for k in keys:
#Send key to underlying widget:
if urwid.is_mouse_event(k):
event, button, col, row = k
self.overlay.mouse_event( dim,
event, button, col, row,
focus=True)
else:
k = self.overlay.keypress(dim, k)
if k in ('up','page up'):
self._w.set_focus('body')
# Until I figure out a better way to do this, then this will
# have to do.
self._w.body.get_focus()[0].get_focus()._invalidate()
#self._w.body.keypress(dim,'down')
elif k in ('down','page down'):
self._w.set_focus('footer')
if "window resize" in keys:
dim = ui.get_cols_rows()
if "esc" in keys or 'Q' in keys:
return False
if "meta enter" in keys or self.OK_PRESSED:
self.OK_PRESSED = False
if self.save_settings():
return True
if self.CANCEL_PRESSED:
return False
class WiredSettingsDialog(AdvancedSettingsDialog): class WiredSettingsDialog(AdvancedSettingsDialog):
def __init__(self,name): def __init__(self,name):
@@ -270,7 +211,7 @@ class WirelessSettingsDialog(AdvancedSettingsDialog):
def __init__(self,networkID): def __init__(self,networkID):
global wireless, daemon global wireless, daemon
AdvancedSettingsDialog.__init__(self) AdvancedSettingsDialog.__init__(self)
self.networkID = networkID self.networkid = networkID
global_settings_t = language['global_settings'] global_settings_t = language['global_settings']
encryption_t = language['use_encryption'] encryption_t = language['use_encryption']
autoconnect_t = language['automatic_connect'] autoconnect_t = language['automatic_connect']
@@ -301,7 +242,7 @@ class WirelessSettingsDialog(AdvancedSettingsDialog):
def set_values(self): def set_values(self):
""" Set the various network settings to the right values. """ """ Set the various network settings to the right values. """
networkID = self.networkID networkID = self.networkid
self.ip_edit.set_edit_text(self.format_entry(networkID,"ip")) self.ip_edit.set_edit_text(self.format_entry(networkID,"ip"))
self.netmask_edit.set_edit_text(self.format_entry(networkID,"netmask")) self.netmask_edit.set_edit_text(self.format_entry(networkID,"netmask"))
self.gateway_edit.set_edit_text(self.format_entry(networkID,"gateway")) self.gateway_edit.set_edit_text(self.format_entry(networkID,"gateway"))
@@ -327,16 +268,12 @@ class WirelessSettingsDialog(AdvancedSettingsDialog):
# Throw the encryption stuff into a list # Throw the encryption stuff into a list
list = [] list = []
for x, enc_type in enumerate(self.encrypt_types):
list.append(enc_type[0])
self.encryption_combo.set_list(list)
self.change_encrypt_method()
activeID = -1 # Set the menu to this item when we are done activeID = -1 # Set the menu to this item when we are done
user_enctype = wireless.GetWirelessProperty(networkID, "enctype")
for x, enc_type in enumerate(self.encrypt_types): for x, enc_type in enumerate(self.encrypt_types):
if enc_type[1] == user_enctype: list.append(enc_type['name'])
if enc_type['type'] == wireless.GetWirelessProperty(networkID, "enctype"):
activeID = x activeID = x
self.encryption_combo.set_list(list)
self.encryption_combo.set_focus(activeID) self.encryption_combo.set_focus(activeID)
if activeID != -1: if activeID != -1:
@@ -346,9 +283,12 @@ class WirelessSettingsDialog(AdvancedSettingsDialog):
else: else:
self.encryption_combo.set_focus(0) self.encryption_combo.set_focus(0)
self.change_encrypt_method()
def set_net_prop(self, option, value): def set_net_prop(self, option, value):
""" Sets the given option to the given value for this network. """ """ Sets the given option to the given value for this network. """
wireless.SetWirelessProperty(self.networkID, option, value) wireless.SetWirelessProperty(self.networkid, option, value)
def format_entry(self, networkid, label): def format_entry(self, networkid, label):
""" Helper method for fetching/formatting wireless properties. """ """ Helper method for fetching/formatting wireless properties. """
@@ -359,25 +299,32 @@ class WirelessSettingsDialog(AdvancedSettingsDialog):
# Check encryption info # Check encryption info
if self.encryption_chkbox.get_state(): if self.encryption_chkbox.get_state():
#print "setting encryption info..." #print "setting encryption info..."
encryption_info = self.encryption_info encrypt_info = self.encryption_info
encrypt_methods = misc.LoadEncryptionMethods() encrypt_methods = self.encrypt_types
self.set_net_prop("enctype", self.set_net_prop("enctype",
encrypt_methods[self.encryption_combo.get_focus()[1] ][1]) encrypt_methods[self.encryption_combo.get_focus()[1] ]['type'])
for x in encryption_info: # Make sure all required fields are filled in.
if encryption_info[x].get_edit_text() == "": for entry_info in encrypt_info.itervalues():
error(self.ui, self.overlay,language['encrypt_info_missing']) if entry_info[0].get_edit_text() == "" \
and entry_info[1] == 'required':
error(self.ui, self.overlay,"%s (%s)" \
% (language['encrypt_info_missing'],
entry_info[0].get_captionabel() )
)
return False return False
self.set_net_prop(x, noneToString(encryption_info[x].
for entry_key, entry_info in encrypt_info.iteritems():
self.set_net_prop(entry_key, noneToString(entry_info[0].
get_edit_text())) get_edit_text()))
elif not self.encryption_chkbox.get_state() and \ elif not self.encryption_chkbox.get_state() and \
wireless.GetWirelessProperty(self.networkID, "encryption"): wireless.GetWirelessProperty(self.networkid, "encryption"):
# Encrypt checkbox is off, but the network needs it.
error(self.ui, self.overlay, language['enable_encryption']) error(self.ui, self.overlay, language['enable_encryption'])
return False return False
else: else:
#print 'encryption is ' + str(wireless.GetWirelessProperty(self.networkID,
# "encryption"))
#print "no encryption specified..."
self.set_net_prop("enctype", "None") self.set_net_prop("enctype", "None")
for entry in encrypt_info.iterkeys():
self.set_net_prop(entry[0].entry, "")
AdvancedSettingsDialog.save_settings(self) AdvancedSettingsDialog.save_settings(self)
# Save the autoconnect setting. This is not where it originally was # Save the autoconnect setting. This is not where it originally was
@@ -388,9 +335,9 @@ class WirelessSettingsDialog(AdvancedSettingsDialog):
self.set_net_prop('use_settings_globally', True) self.set_net_prop('use_settings_globally', True)
else: else:
self.set_net_prop('use_settings_globally', False) self.set_net_prop('use_settings_globally', False)
wireless.RemoveGlobalEssidEntry(self.networkID) wireless.RemoveGlobalEssidEntry(self.networkid)
wireless.SaveWirelessNetworkProfile(self.networkID) wireless.SaveWirelessNetworkProfile(self.networkid)
return True return True
# More or less ripped from netentry.py # More or less ripped from netentry.py
@@ -405,30 +352,35 @@ class WirelessSettingsDialog(AdvancedSettingsDialog):
# If nothing is selected, select the first entry. # If nothing is selected, select the first entry.
if ID == -1: if ID == -1:
self.encryption_combo.set_active(0) self.encryption_combo.set_focus(0)
ID = 0 ID = 0
opts = methods[ID][2]
theList = [] theList = []
for x in opts: for type_ in ['required', 'optional']:
edit = None fields = methods[ID][type_]
if language.has_key(opts[x][0]): for field in fields:
edit = MaskingEdit(('editcp',language[opts[x][0].lower().replace(' ','_')]+': '),mask_mode='no_focus') if language.has_key(field[1]):
else: edit = MaskingEdit(('editcp',language[field[1].lower().replace(' ','_')]+': '))
edit = MaskingEdit(('editcp',opts[x][0].replace('_',' ')+': '),mask_mode='no_focus') else:
theList.append(edit) edit = MaskingEdit(('editcp',field[1].replace('_',' ')+': '))
# Add the data to any array, so that the information edit.set_mask_mode('no_focus')
# can be easily accessed by giving the name of the wanted theList.append(edit)
# data. # Add the data to any array, so that the information
self.encryption_info[opts[x][1]] = edit # can be easily accessed by giving the name of the wanted
# data.
self.encryption_info[field[0]] = [edit, type_]
edit.set_edit_text(noneToBlankString( edit.set_edit_text(noneToBlankString(
wireless.GetWirelessProperty(self.networkID, opts[x][1]))) wireless.GetWirelessProperty(self.networkid, field[0])))
#FIXME: This causes the entire pile to light up upon use.
# Make this into a listbox?
self.pile_encrypt = DynWrap(urwid.Pile(theList),attrs=('editbx','editnfc')) self.pile_encrypt = DynWrap(urwid.Pile(theList),attrs=('editbx','editnfc'))
self._w.body.body.insert(self._w.body.body.__len__(),self.pile_encrypt) self._w.body.body.insert(self._w.body.body.__len__(),self.pile_encrypt)
#self._w.body.body.append(self.pile_encrypt) #self._w.body.body.append(self.pile_encrypt)
def prerun(self,ui,dim,display): def ready_widgets(self,ui,body):
self.encryption_combo.build_combobox(self.overlay,ui,14) self.ui = ui
self.body = body
self.encryption_combo.build_combobox(body,ui,14)
self.change_encrypt_method() self.change_encrypt_method()

View File

@@ -68,8 +68,8 @@ class PrefsDialog(urwid.WidgetWrap):
global_dns_cat_t = ('header',language['global_dns_servers']) global_dns_cat_t = ('header',language['global_dns_servers'])
global_dns_t = ('editcp',language['use_global_dns']) global_dns_t = ('editcp',language['use_global_dns'])
dns_dom_t = ('editcp',' DNS Domain: ') dns_dom_t = ('editcp',' '+language['dns_domain']+': ')
search_dom_t = ('editcp',' Search domain:') search_dom_t = ('editcp',' '+language['search_domain']+':')
dns1_t = ('editcp',' DNS server 1: ') dns1_t = ('editcp',' DNS server 1: ')
dns2_t = ('editcp',' DNS server 2: ') dns2_t = ('editcp',' DNS server 2: ')
dns3_t = ('editcp',' DNS server 3: ') dns3_t = ('editcp',' DNS server 3: ')
@@ -237,27 +237,10 @@ class PrefsDialog(urwid.WidgetWrap):
self.header2 : advancedLB} self.header2 : advancedLB}
#self.load_settings() #self.load_settings()
# Now for the buttons: self.tabs = TabColumns(headerList,lbList,language['preferences'])
ok_t = 'OK'
cancel_t = 'Cancel'
ok_button = urwid.AttrWrap(urwid.Button('OK',self.ok_callback),'body','focus')
cancel_button = urwid.AttrWrap(urwid.Button('Cancel',self.cancel_callback),'body','focus')
# Variables set by the buttons' callback functions
self.CANCEL_PRESSED = False
self.OK_PRESSED = False
self.button_cols = urwid.Columns([ok_button,cancel_button],
dividechars=1)
self.tabs = TabColumns(headerList,lbList,language['preferences'],self.button_cols)
self.__super.__init__(self.tabs) self.__super.__init__(self.tabs)
def load_settings(self): def load_settings(self):
# Reset the buttons
self.CANCEL_PRESSED = False
self.OK_PRESSED = False
### General Settings ### General Settings
# ComboBox does not like dbus.Strings as text markups. My fault. :/ # ComboBox does not like dbus.Strings as text markups. My fault. :/
@@ -322,7 +305,7 @@ class PrefsDialog(urwid.WidgetWrap):
self.debug_mode_checkb.set_state(daemon.GetDebugMode()) self.debug_mode_checkb.set_state(daemon.GetDebugMode())
self.use_dbm_checkb.set_state(daemon.GetSignalDisplayType()) self.use_dbm_checkb.set_state(daemon.GetSignalDisplayType())
def save_results(self): def save_settings(self):
""" Pushes the selected settings to the daemon. """ Pushes the selected settings to the daemon.
This exact order is found in prefs.py""" This exact order is found in prefs.py"""
daemon.SetUseGlobalDNS(self.global_dns_checkb.get_state()) daemon.SetUseGlobalDNS(self.global_dns_checkb.get_state())
@@ -378,45 +361,6 @@ class PrefsDialog(urwid.WidgetWrap):
for w in self.dns1,self.dns2,self.dns3,self.dns_dom,self.search_dom: for w in self.dns1,self.dns2,self.dns3,self.dns_dom,self.search_dom:
w.set_sensitive(new_state) w.set_sensitive(new_state)
# Button callbacks def ready_widgets(self,ui,body):
def ok_callback(self,button_object,user_data=None):
self.OK_PRESSED = True
def cancel_callback(self,button_object,user_data=None):
self.CANCEL_PRESSED = True
def ready_comboboxes(self,ui,body):
self.wpa_cbox.build_combobox(body,ui,4) self.wpa_cbox.build_combobox(body,ui,4)
self.backend_cbox.build_combobox(body,ui,8) self.backend_cbox.build_combobox(body,ui,8)
# Put the widget into an overlay, and run!
def run(self,ui, dim, display):
width,height = ui.get_cols_rows()
self.load_settings()
overlay = urwid.Overlay(self.tabs, display, ('fixed left', 0),width
, ('fixed top',1), height-3)
self.ready_comboboxes(ui,overlay)
keys = True
while True:
if keys:
ui.draw_screen(dim, overlay.render(dim, True))
keys = ui.get_input()
if "window resize" in keys:
dim = ui.get_cols_rows()
if "esc" in keys or 'Q' in keys:
return False
for k in keys:
#Send key to underlying widget:
overlay.keypress(dim, k)
if urwid.is_mouse_event(k):
event, button, col, row = k
overlay.mouse_event( dim,
event, button, col, row,
focus=True)
# Check if buttons are pressed.
if self.CANCEL_PRESSED:
return False
if self.OK_PRESSED or 'meta enter' in keys:
return True

View File

@@ -1,4 +1,5 @@
#!/usr/bin/env python #!/usr/bin/env python
# -* coding: utf-8 -*-
""" wicd-curses. (curses/urwid-based) console interface to wicd """ wicd-curses. (curses/urwid-based) console interface to wicd
@@ -50,14 +51,14 @@ from wicd import dbusmanager
# Internal Python stuff # Internal Python stuff
import sys import sys
from time import sleep from time import sleep, strftime, ctime
# Curses UIs for other stuff # Curses UIs for other stuff
from curses_misc import SelText,DynEdit,DynIntEdit,ComboBox,Dialog2,TextDialog,InputDialog,error from curses_misc import *
from prefs_curses import PrefsDialog from prefs_curses import PrefsDialog
import netentry_curses import netentry_curses
from netentry_curses import WirelessSettingsDialog, WiredSettingsDialog from netentry_curses import WirelessSettingsDialog, WiredSettingsDialog,AdvancedSettingsDialog
from optparse import OptionParser from optparse import OptionParser
@@ -100,8 +101,8 @@ class wrap_exceptions:
raise raise
except : except :
# Quit the loop # Quit the loop
if 'loop' in locals(): #if 'loop' in locals():
loop.quit() loop.quit()
# Zap the screen # Zap the screen
ui.stop() ui.stop()
# Print out standard notification: # Print out standard notification:
@@ -157,44 +158,11 @@ def check_for_wireless(iwconfig, wireless_ip, set_status):
return True return True
# Self explanitory, and not used until I can get some list sort function
# working...
# Also defunct.
# Current list header is STR,ESSID,ENCRYPT,BSSID,TYPE,CHANNEL
#def gen_list_header():
# return '%3s %4s %s %19s %s ' % ('NUM','STR','BSSID','CHANNEL','ESSID')
# Generate the list of networks. # Generate the list of networks.
# Mostly borrowed/stolen from wpa_cli, since I had no clue what all of those # Mostly borrowed/stolen from wpa_cli, since I had no clue what all of those
# DBUS interfaces do. ^_^ # DBUS interfaces do. ^_^
# Whatever calls this must be exception-wrapped if it is run if the UI is up # Whatever calls this must be exception-wrapped if it is run if the UI is up
def gen_network_list(): def gen_network_list():
# Pick which strength measure to use based on what the daemon says
if daemon.GetSignalDisplayType() == 0:
strenstr = 'quality'
gap = 3
else:
strenstr = 'strength'
gap = 5
id = 0
wiredL = []
#is_active = wireless.GetWirelessIP('') == None and wired.GetWiredIP('') != None
# This one makes a list of strings to put in a combo box.
#for profile in wired.GetWiredProfileList():
#theString = '%4s %25s' % (id, profile)
#### THIS IS wired.blah() in experimental
#print config.GetLastUsedWiredNetwork()
# Tag if no wireless IP present, and wired one is
#if is_active:
# theString = '>'+theString[1:]
#wiredL.append(urwid.AttrWrap(SelText(theString),'connected',
# 'connected focus'))
#else:
#wiredL.append(urwid.AttrWrap(SelText(theString),'body','focus'))
#wiredL.append(theString)
#id+=1
wiredL = wired.GetWiredProfileList() wiredL = wired.GetWiredProfileList()
wlessL = [] wlessL = []
# This one makes a list of NetLabels # This one makes a list of NetLabels
@@ -227,24 +195,62 @@ def about_dialog(body):
about = TextDialog(theText,16,55,header=('header','About Wicd')) about = TextDialog(theText,16,55,header=('header','About Wicd'))
about.run(ui,body) about.run(ui,body)
# Modeled after htop's help
def help_dialog(body): def help_dialog(body):
theText = [ textT = urwid.Text(('header','Wicd-curses help'),'right')
textSH = urwid.Text(['This is ',('blue','wicd-curses-'+CURSES_REVNO),' using wicd ',unicode(daemon.Hello()),'\n'])
textH = urwid.Text([
"For more detailed help, consult the wicd-curses(8) man page.\n", "For more detailed help, consult the wicd-curses(8) man page.\n",
"\n", "All controls are case sensitive\n", ('bold','->'),' and ',('bold','<-')," are the right and left arrows respectively.\n"])
('bold','H')," or ",('bold','h'),' or ',('bold','?')," Display this help dialog\n",
('bold','enter')," Connect to selected network\n", text1 = urwid.Text([
('bold','D')," Disconnect from all networks\n", ('bold',' H h ?'),": Display this help dialog\n",
('bold','ESC')," Stop a network connection in progress\n", ('bold','enter C'),": Connect to selected network\n",
('bold','F5')," or ", ('bold','R')," Refresh network list\n", ('bold',' D'),": Disconnect from all networks\n",
('bold','P')," Prefrences dialog\n", ('bold',' ESC'),": Stop a network connection in progress\n",
('bold','I')," Scan for hidden networks\n", ('bold',' F5 R'),": Refresh network list\n",
('bold','S')," Select scripts\n", ('bold',' P'),": Prefrences dialog\n",
('bold','O')," Set up Ad-hoc network\n", ])
('bold','C')," Configure Selected Network\n", text2 = urwid.Text([
('bold','A')," Display 'about' dialog\n" ('bold',' I'),": Scan for hidden networks\n",
] ('bold',' S'),": Select scripts\n",
help = TextDialog(theText,18,62,header=('header',"Wicd-Curses Help")) ('bold',' O'),": Set up Ad-hoc network\n",
help.run(ui,body) ('bold',' ->'),": Configure selected network\n",
('bold',' A'),": Display 'about' dialog\n",
('bold',' Q'),": Quit wicd-curses\n",
])
textF = urwid.Text('Press any key to return.')
# textJ = urwid.Text(('important','Nobody expects the Spanish Inquisition!'))
blank = urwid.Text('')
# Pile containing a text and columns?
cols = urwid.Columns([text1,text2])
pile = urwid.Pile([textH,cols])
fill = urwid.Filler(pile)
frame = urwid.Frame(fill,header=urwid.Pile([textT,textSH]),footer=textF)
dim = ui.get_cols_rows()
while True:
ui.draw_screen(dim, frame.render(dim, True))
keys = ui.get_input()
# Don't stop because someone let go of the mouse on the frame
mouse_release = False
for k in keys:
if urwid.is_mouse_event(k) and k[0] == "mouse release":
mouse_release = True
break
if mouse_release :
continue
if 'window resize' in keys:
dim = ui.get_cols_rows()
elif keys:
break
#elif keys != '':
# break
#help = TextDialog(theText,18,62,header=('header',"Wicd-Curses Help"))
#help.run(ui,body)
def run_configscript(parent,netname,nettype): def run_configscript(parent,netname,nettype):
configfile = wpath.etc+netname+'-settings.conf' configfile = wpath.etc+netname+'-settings.conf'
@@ -293,6 +299,15 @@ Once there, you can adjust (or add) the "beforescript", "afterscript", and "disc
main() main()
""" """
def gen_list_header():
if daemon.GetSignalDisplayType() == 0:
# Allocate 25 cols for the ESSID name
essidgap = 25
else:
# Need 3 more to accomodate dBm strings
essidgap = 28
return 'C %s %*s %9s %17s %6s %s' % ('STR ',essidgap,'ESSID','ENCRYPT','BSSID','MODE','CHNL')
######################################## ########################################
##### URWID SUPPORT CLASSES ##### URWID SUPPORT CLASSES
######################################## ########################################
@@ -300,13 +315,14 @@ Once there, you can adjust (or add) the "beforescript", "afterscript", and "disc
# Wireless network label # Wireless network label
class NetLabel(urwid.WidgetWrap): class NetLabel(urwid.WidgetWrap):
def __init__(self, id, is_active): def __init__(self, id, is_active):
# Pick which strength measure to use based on what the daemon says # Pick which strength measure to use based on what the daemon says
# gap allocates more space to the first module
if daemon.GetSignalDisplayType() == 0: if daemon.GetSignalDisplayType() == 0:
strenstr = 'quality' strenstr = 'quality'
gap = 3 gap = 4 # Allow for 100%
else: else:
strenstr = 'strength' strenstr = 'strength'
gap = 5 gap = 7 # -XX dbm = 7
self.id = id self.id = id
# All of that network property stuff # All of that network property stuff
self.stren = daemon.FormatSignalForPrinting( self.stren = daemon.FormatSignalForPrinting(
@@ -316,7 +332,7 @@ class NetLabel(urwid.WidgetWrap):
self.encrypt = wireless.GetWirelessProperty(id,'encryption_method') if wireless.GetWirelessProperty(id, 'encryption') else language['unsecured'] self.encrypt = wireless.GetWirelessProperty(id,'encryption_method') if wireless.GetWirelessProperty(id, 'encryption') else language['unsecured']
self.mode = wireless.GetWirelessProperty(id, 'mode') # Master, Ad-Hoc self.mode = wireless.GetWirelessProperty(id, 'mode') # Master, Ad-Hoc
self.channel = wireless.GetWirelessProperty(id, 'channel') self.channel = wireless.GetWirelessProperty(id, 'channel')
theString = ' %*s %25s %9s %17s %6s: %s' % (gap, theString = ' %-*s %25s %9s %17s %6s %4s' % (gap,
self.stren,self.essid,self.encrypt,self.bssid,self.mode,self.channel) self.stren,self.essid,self.encrypt,self.bssid,self.mode,self.channel)
if is_active: if is_active:
theString = '>'+theString[1:] theString = '>'+theString[1:]
@@ -481,6 +497,7 @@ class AdHocDialog(Dialog2):
self.key_edit.get_edit_text()) self.key_edit.get_edit_text())
return exitcode, data return exitcode, data
######################################## ########################################
##### APPLICATION INTERFACE CLASS ##### APPLICATION INTERFACE CLASS
######################################## ########################################
@@ -488,6 +505,7 @@ class AdHocDialog(Dialog2):
class appGUI(): class appGUI():
"""The UI itself, all glory belongs to it!""" """The UI itself, all glory belongs to it!"""
def __init__(self): def __init__(self):
global loop
self.size = ui.get_cols_rows() self.size = ui.get_cols_rows()
# Happy screen saying that you can't do anything because we're scanning # Happy screen saying that you can't do anything because we're scanning
# for networks. :-) # for networks. :-)
@@ -503,7 +521,8 @@ class appGUI():
header = urwid.AttrWrap(urwid.Text(self.TITLE,align='right'), 'header') header = urwid.AttrWrap(urwid.Text(self.TITLE,align='right'), 'header')
self.wiredH=urwid.Filler(urwid.Text("Wired Network(s)")) self.wiredH=urwid.Filler(urwid.Text("Wired Network(s)"))
self.wlessH=urwid.Filler(urwid.Text("Wireless Network(s)")) self.list_header=urwid.AttrWrap(urwid.Text(gen_list_header()),'listbar')
self.wlessH=NSelListBox([urwid.Text("Wireless Network(s)"),self.list_header])
#if wireless.GetNumberOfNetworks() == 0: #if wireless.GetNumberOfNetworks() == 0:
# wireless.Scan() # wireless.Scan()
@@ -511,7 +530,9 @@ class appGUI():
# These are empty to make sure that things go my way. # These are empty to make sure that things go my way.
wiredL,wlessL = [],[]# = gen_network_list() wiredL,wlessL = [],[]# = gen_network_list()
self.frame = None self.frame = None
self.diag = None
self.wiredCB = urwid.Filler(WiredComboBox(wiredL)) self.wiredCB = urwid.Filler(WiredComboBox(wiredL))
self.wlessLB = urwid.ListBox(wlessL) self.wlessLB = urwid.ListBox(wlessL)
@@ -525,17 +546,36 @@ class appGUI():
# spam,spam,spam,spam,spam,spam,spam,spam,spam,spam,spam,spam, # spam,spam,spam,spam,spam,spam,spam,spam,spam,spam,spam,spam,
# spam,spam,spam,spam] ] # spam,spam,spam,spam] ]
#self.spamLB = urwid.ListBox(spamL) #self.spamLB = urwid.ListBox(spamL)
# Keymappings proposed by nanotube in #wicd
keys = [
('H' ,'Help' ,None),
('right','Config',None),
#(' ',' ',None),
('C' ,'Connect',None),
('D' ,'Disconn',None),
('R' ,'Refresh',None),
('P' ,'Prefs',None),
('I' ,'Hidden',None),
('Q' ,'Quit',loop.quit)
]
self.footer1 = urwid.AttrWrap(urwid.Text("Something important will eventually go here."),'body') self.primaryCols = OptCols(keys,self.handle_keys)
self.footer2 = urwid.AttrWrap(urwid.Text("If you are seeing this, then something has gone wrong!"),'important') #self.time_label = urwid.Text(strftime('%H:%M:%S'))
self.footerList = urwid.ListBox([self.footer1,self.footer2]) self.time_label = \
urwid.AttrWrap(urwid.Text(strftime('%H:%M:%S')), 'timebar')
self.status_label = urwid.AttrWrap(urwid.Text('blah'),'important')
self.footer2 = urwid.Columns([self.status_label,('fixed', 8, self.time_label)])
self.footerList = urwid.Pile([self.primaryCols,self.footer2])
# Pop takes a number! # Pop takes a number!
#walker.pop(1) #walker.pop(1)
self.frame = urwid.Frame(self.thePile, self.frame = urwid.Frame(self.thePile,
header=header, header=header,
footer=urwid.BoxAdapter(self.footerList,2)) footer=self.footerList)
self.wiredCB.get_body().build_combobox(self.frame,ui,3) self.wiredCB.get_body().build_combobox(self.frame,ui,3)
# Init the other columns used in the program
self.init_other_optcols()
self.frame.set_body(self.thePile) self.frame.set_body(self.thePile)
# Booleans gallore! # Booleans gallore!
self.prev_state = False self.prev_state = False
@@ -548,6 +588,18 @@ class appGUI():
#self.dialog = PrefOverlay(self.frame,self.size) #self.dialog = PrefOverlay(self.frame,self.size)
def init_other_optcols(self):
# The "tabbed" preferences dialog
self.prefCols = OptCols( [('meta enter','OK'),
('esc','Cancel'),
('meta [','Tab Left',),
('meta ]','Tab Right')],self.handle_keys
)
self.confCols = OptCols( [
('meta enter','OK'),
('esc','Cancel')
],self.handle_keys)
# Does what it says it does # Does what it says it does
def lock_screen(self): def lock_screen(self):
self.frame.set_body(self.screen_locker) self.frame.set_body(self.screen_locker)
@@ -586,14 +638,19 @@ class appGUI():
where = self.thePile.get_focus().get_focus()[1] where = self.thePile.get_focus().get_focus()[1]
#where = self.wlessLB.get_focus()[1] #where = self.wlessLB.get_focus()[1]
self.focusloc = (wlessorwired,where) self.focusloc = (wlessorwired,where)
# Be clunky until I get to a later stage of development. # Be clunky until I get to a later stage of development.
# Update the list of networks. Usually called by DBus. # Update the list of networks. Usually called by DBus.
# TODO: Preserve current focus when updating the list.
@wrap_exceptions() @wrap_exceptions()
def update_netlist(self,state=None, x=None, force_check=False,firstrun=False): def update_netlist(self,state=None, x=None, force_check=False,firstrun=False):
# Run focus-collecting code if we are not running this for the first time # Don't even try to do this if we are running a dialog
if self.diag:
return
# Run focus-collecting code if we are not running this for the first
# time
if not firstrun: if not firstrun:
self.update_focusloc() self.update_focusloc()
self.list_header.set_text(gen_list_header())
""" Updates the overall network list.""" """ Updates the overall network list."""
if not state: if not state:
state, x = daemon.GetConnectionStatus() state, x = daemon.GetConnectionStatus()
@@ -615,7 +672,7 @@ class appGUI():
#if firstrun: #if firstrun:
self.thePile = urwid.Pile([('fixed',1,self.wiredH), self.thePile = urwid.Pile([('fixed',1,self.wiredH),
('fixed',1,self.wiredCB), ('fixed',1,self.wiredCB),
('fixed',1,self.wlessH), ('fixed',2,self.wlessH),
self.wlessLB] ) self.wlessLB] )
if not firstrun: if not firstrun:
self.frame.body = self.thePile self.frame.body = self.thePile
@@ -630,7 +687,7 @@ class appGUI():
else: else:
self.thePile.set_focus(self.wiredCB) self.thePile.set_focus(self.wiredCB)
else: else:
self.thePile = urwid.Pile([('fixed',1,self.wlessH),self.wlessLB] ) self.thePile = urwid.Pile([('fixed',2,self.wlessH),self.wlessLB] )
if not firstrun: if not firstrun:
self.frame.body = self.thePile self.frame.body = self.thePile
#if self.focusloc[0] == self.wlessLB: #if self.focusloc[0] == self.wlessLB:
@@ -688,9 +745,9 @@ class appGUI():
self.update_ui() self.update_ui()
return True return True
# Cheap little indicator stating that we are actually connecting # Cheap little indicator stating that we are actually connecting
twirl = ['|','/','-','\\'] twirl = ['|','/','-','\\']
tcount = 0 # Counter for said indicator
def set_status(self,text,from_idle=False): def set_status(self,text,from_idle=False):
# Set the status text, usually called by the update_status method # Set the status text, usually called by the update_status method
# from_idle : a check to see if we are being called directly from the # from_idle : a check to see if we are being called directly from the
@@ -701,6 +758,7 @@ class appGUI():
if from_idle and not self.connecting: if from_idle and not self.connecting:
#self.update_netlist() #self.update_netlist()
self.update_status() self.update_status()
self.tcount = 0
#self.update_ui() #self.update_ui()
return False return False
toAppend = '' toAppend = ''
@@ -708,26 +766,22 @@ class appGUI():
# the wheel. # the wheel.
if from_idle and self.connecting: if from_idle and self.connecting:
# This is probably the wrong way to do this, but it works for now. # This is probably the wrong way to do this, but it works for now.
toAppend=self.twirl[self.incr % 4] toAppend=self.twirl[self.tcount % 4]
self.footer2 = urwid.AttrWrap(urwid.Text(text+' '+toAppend),'important') self.tcount+=1
self.frame.set_footer(urwid.BoxAdapter( #self.footer2 = urwid.Columns([
urwid.ListBox([self.footer1,self.footer2]),2)) # urwid.AttrWrap(urwid.Text(text+' '+toAppend),'important'),
# ('fixed',8,urwid.Text(str(self.time),align='right'))])
self.status_label.set_text(text+' '+toAppend)
#self.frame.set_footer(urwid.BoxAdapter(
# urwid.ListBox([self.footer1,self.footer2]),2))
return True return True
# Make sure the screen is still working by providing a pretty counter. # Make sure the screen is still working by providing a pretty counter.
# Not necessary in the end, but I will be using footer1 for stuff in # Not necessary in the end, but I will be using footer1 for stuff in
# the long run, so I might as well put something there. # the long run, so I might as well put something there.
incr = 0 #@wrap_exceptions()
@wrap_exceptions() def update_time(self):
def idle_incr(self): self.time_label.set_text(strftime('%H:%M:%S'))
theText = " "
if self.connecting:
theText += "-- "+language['connecting']+' -- '+language["esc_to_cancel"]
else:
theText += "-- Press H or ? for Help"
quit_note = ' -- '+language["press_to_quit"]
self.footer1 = urwid.Text(str(self.incr) + theText+quit_note,wrap='clip')
self.incr+=1
return True return True
# Yeah, I'm copying code. Anything wrong with that? # Yeah, I'm copying code. Anything wrong with that?
@@ -743,91 +797,104 @@ class appGUI():
def dbus_scan_started(self): def dbus_scan_started(self):
self.lock_screen() self.lock_screen()
# Redraw the screen def restore_primary(self):
@wrap_exceptions() self.frame.set_body(self.thePile)
def update_ui(self): self.diag = None
#self.update_status() self.frame.set_footer(urwid.Pile([self.primaryCols,self.footer2]))
canvas = self.frame.render( (self.size),True ) self.update_ui()
### GRRRRRRRRRRRRRRRRRRRRR ->^^^^
# It looks like if I wanted to get the statusbar to update itself
# continuously, I would have to use overlay the canvasses and redirect
# the input. I'll try to get that working at a later time, if people
# want that "feature".
#canvaso = urwid.CanvasOverlay(self.dialog.render( (80,20),True),canvas,0,1)
ui.draw_screen((self.size),canvas)
keys = ui.get_input()
# Handle keystrokes def handle_keys(self,keys):
if "f8" in keys or 'Q' in keys or 'q' in keys: if not self.diag:
loop.quit() # Handle keystrokes
#return False if "f8" in keys or 'Q' in keys or 'q' in keys:
if "f5" in keys or 'R' in keys: loop.quit()
self.lock_screen() #return False
wireless.Scan(True) if "f5" in keys or 'R' in keys:
if "D" in keys: self.lock_screen()
# Disconnect from all networks. wireless.Scan(True)
daemon.Disconnect() if "D" in keys:
self.update_netlist() # Disconnect from all networks.
# Guess what! I actually need to put this here, else I'll have tons of daemon.Disconnect()
# references to self.frame lying around. ^_^ self.update_netlist()
if "enter" in keys: if 'right' in keys:
focus = self.frame.body.get_focus() focus = self.thePile.get_focus()
if focus == self.wiredCB: self.frame.set_footer(urwid.Pile([self.confCols,self.footer2]))
self.special = focus if focus == self.wiredCB:
self.connect("wired",0) self.diag = WiredSettingsDialog(self.wiredCB.get_body().get_selected_profile())
else: self.frame.set_body(self.diag)
# wless list only other option else:
wid,pos = self.thePile.get_focus().get_focus() # wireless list only other option
self.connect("wireless",pos) wid,pos = self.thePile.get_focus().get_focus()
self.diag = WirelessSettingsDialog(pos)
self.diag.ready_widgets(ui,self.frame)
self.frame.set_body(self.diag)
# Guess what! I actually need to put this here, else I'll have
# tons of references to self.frame lying around. ^_^
if "enter" in keys:
#pass
focus = self.frame.body.get_focus()
if focus == self.wiredCB:
self.special = focus
self.connect("wired",0)
else:
# wless list only other option
wid,pos = self.thePile.get_focus().get_focus()
self.connect("wireless",pos)
if "esc" in keys: if "esc" in keys:
# Force disconnect here if connection in progress # Force disconnect here if connection in progress
if self.connecting: if self.connecting:
daemon.CancelConnect() daemon.CancelConnect()
# Prevents automatic reconnecting if that option is enabled # Prevents automatic reconnecting if that option is enabled
daemon.SetForcedDisconnect(True) daemon.SetForcedDisconnect(True)
if "P" in keys: if "P" in keys:
if not self.pref: if not self.pref:
self.pref = PrefsDialog(self.frame,(0,1),ui, self.pref = PrefsDialog(self.frame,(0,1),ui,
dbusmanager.get_dbus_ifaces()) dbusmanager.get_dbus_ifaces())
if self.pref.run(ui,self.size,self.frame): self.pref.load_settings()
self.pref.save_results() self.pref.ready_widgets(ui,self.frame)
self.update_ui() self.frame.set_footer(urwid.Pile([self.prefCols,self.footer2]))
if "A" in keys: self.diag = self.pref
about_dialog(self.frame) self.frame.set_body(self.diag)
if "C" in keys: # Halt here, keypress gets passed to the dialog otherwise
focus = self.thePile.get_focus() return True
if focus == self.wiredCB: if "A" in keys:
WiredSettingsDialog(self.wiredCB.get_body(). about_dialog(self.frame)
get_selected_profile()).run(ui,self.size,self.frame) if "C" in keys:
else: # Same as "enter" for now
# wireless list only other option focus = self.frame.body.get_focus()
wid,pos = self.thePile.get_focus().get_focus() if focus == self.wiredCB:
WirelessSettingsDialog(pos).run(ui,self.size,self.frame) self.special = focus
#self.netentry = NetEntryBase(dbusmanager.get_dbus_ifaces()) self.connect("wired",0)
#self.netentry.run(ui,self.size,self.frame) else:
if "I" in keys: # wless list only other option
self.raise_hidden_network_dialog() wid,pos = self.thePile.get_focus().get_focus()
if "H" in keys or 'h' in keys or '?' in keys: self.connect("wireless",pos)
help_dialog(self.frame) if "I" in keys:
if "S" in keys: self.raise_hidden_network_dialog()
focus = self.thePile.get_focus() if "H" in keys or 'h' in keys or '?' in keys:
if focus == self.wiredCB: # FIXME I shouldn't need this, OptCols messes up this one
nettype = 'wired' # particular button
netname = self.wiredCB.get_body().get_selected_profile() if not self.diag:
else: help_dialog(self.frame)
nettype = 'wireless' if "S" in keys:
netname = str(self.wlessLB.get_focus()[1]) focus = self.thePile.get_focus()
run_configscript(self.frame,netname,nettype) if focus == self.wiredCB:
if "O" in keys: nettype = 'wired'
exitcode,data = AdHocDialog().run(ui,self.frame) netname = self.wiredCB.get_body().get_selected_profile()
#data = (essid,ip,channel,use_ics,use_encrypt,key_edit) else:
if exitcode == 1: nettype = 'wireless'
wireless.CreateAdHocNetwork(data[0], netname = str(self.wlessLB.get_focus()[1])
data[2], run_configscript(self.frame,netname,nettype)
data[1], "WEP", if "O" in keys:
data[5], exitcode,data = AdHocDialog().run(ui,self.frame)
data[4], False) #data = (essid,ip,channel,use_ics,use_encrypt,key_edit)
if exitcode == 1:
wireless.CreateAdHocNetwork(data[0],
data[2],
data[1], "WEP",
data[5],
data[4], False)
for k in keys: for k in keys:
if urwid.is_mouse_event(k): if urwid.is_mouse_event(k):
@@ -835,10 +902,35 @@ class appGUI():
self.frame.mouse_event( self.size, self.frame.mouse_event( self.size,
event, button, col, row, event, button, col, row,
focus=True) focus=True)
continue
if self.diag:
if k == 'esc':
self.restore_primary()
break
if k == 'meta enter':
self.diag.save_settings()
self.restore_primary()
break
self.frame.keypress(self.size,k)
if k == "window resize": if k == "window resize":
self.size = ui.get_cols_rows() self.size = ui.get_cols_rows()
continue continue
self.frame.keypress( self.size, k )
# Redraw the screen
@wrap_exceptions()
def update_ui(self):
#self.update_status()
canvas = self.frame.render( (self.size),True )
### GRRRRRRRRRRRRRRRRRRRRR ->^^^^
# It looks like if I want to get the statusbar to update itself
# continuously, I would have to use overlay the canvasses and redirect
# the input. I'll try to get that working at a later time, if people
# want that "feature".
#canvaso = urwid.CanvasOverlay(self.dialog.render( (80,20),True),canvas,0,1)
ui.draw_screen((self.size),canvas)
keys = ui.get_input()
self.handle_keys(keys)
return True return True
def connect(self, nettype, networkid, networkentry=None): def connect(self, nettype, networkid, networkentry=None):
@@ -859,7 +951,6 @@ class appGUI():
def main(): def main():
global ui global ui
# We are _not_ python. # We are _not_ python.
misc.RenameProcess('wicd-curses') misc.RenameProcess('wicd-curses')
@@ -876,33 +967,36 @@ def main():
# Default Color scheme. # Default Color scheme.
# Other potential color schemes can be found at: # Other potential color schemes can be found at:
# http://excess.org/urwid/wiki/RecommendedPalette # http://excess.org/urwid/wiki/RecommendedPalette
# Note: the current palette below is optimized for the linux console.
# For example, this looks particularly bad on a default-colored XTerm. # Thanks to nanotube on #wicd for helping with this
# NB: To find current terminal background use variable COLORFGBG
ui.register_palette([ ui.register_palette([
('body','default','default'), ('body','default','default'),
('focus','dark magenta','light gray'), ('focus','dark magenta','light gray'),
('header','light blue','default'), ('header','light blue','default'),
('important','light red','default'), ('important','light red','default'),
('connected','dark green','default'), ('connected','dark green','default'),
('connected focus','default','dark green'), ('connected focus','black','dark green'),
('editcp', 'default', 'default', 'standout'), ('editcp', 'default', 'default', 'standout'),
('editbx', 'light gray', 'dark blue'), ('editbx', 'light gray', 'dark blue'),
('editfc', 'white','dark blue', 'bold'), ('editfc', 'white','dark blue', 'bold'),
('editnfc','dark gray','default'), ('editnfc','brown','default','bold'),
('tab active','dark green','light gray'), ('tab active','dark green','light gray'),
('infobar','light gray','dark blue'),
('timebar','dark gray','default'),
('listbar','dark gray','default'),
# Simple colors around text # Simple colors around text
('green','dark green','default'), ('green','dark green','default'),
('blue','dark blue','default'), ('blue','light blue','default'),
('red','dark red','default'), ('red','dark red','default'),
('bold','white','black','bold')]) ('bold','white','black','bold')])
# This is a wrapper around a function that calls another a function that is a # This is a wrapper around a function that calls another a function that
# wrapper around a infinite loop. Fun. # is a wrapper around a infinite loop. Fun.
urwid.set_encoding('utf8') urwid.set_encoding('utf8')
ui.run_wrapper(run) ui.run_wrapper(run)
def run(): def run():
global loop global loop
loop = gobject.MainLoop()
ui.set_mouse_tracking() ui.set_mouse_tracking()
app = appGUI() app = appGUI()
@@ -915,12 +1009,11 @@ def run():
# I've left this commented out many times. # I've left this commented out many times.
bus.add_signal_receiver(app.update_netlist, 'StatusChanged', bus.add_signal_receiver(app.update_netlist, 'StatusChanged',
'org.wicd.daemon') 'org.wicd.daemon')
loop = gobject.MainLoop()
# Update what the interface looks like as an idle function # Update what the interface looks like as an idle function
gobject.idle_add(app.update_ui) gobject.idle_add(app.update_ui)
# Update the connection status on the bottom every 1.5 s. # Update the connection status on the bottom every 1.5 s.
gobject.timeout_add(1500,app.update_status) gobject.timeout_add(2000,app.update_status)
gobject.idle_add(app.idle_incr) gobject.timeout_add(1000,app.update_time)
# DEFUNCT: Terminate the loop if the UI is terminated. # DEFUNCT: Terminate the loop if the UI is terminated.
#gobject.idle_add(app.stop_loop) #gobject.idle_add(app.stop_loop)
loop.run() loop.run()
@@ -962,4 +1055,4 @@ if __name__ == '__main__':
main() main()
# Make sure that the terminal does not try to overwrite the last line of # Make sure that the terminal does not try to overwrite the last line of
# the program, so that everything looks pretty. # the program, so that everything looks pretty.
print "" #print ""

View File

@@ -1,7 +1,8 @@
name = EAP-FAST name = EAP-FAST
author = Adam Blackburn author = Adam Blackburn
version = 2 version = 2
require username *Username password *Password pac_file *Path_To_PAC_File require username *Username password *Password
optional pac_file *Path_To_PAC_File
----- -----
ctrl_interface=/var/run/wpa_supplicant ctrl_interface=/var/run/wpa_supplicant
network={ network={

View File

@@ -1,7 +1,9 @@
name = EAP-TLS name = EAP-TLS
author = Dan O'Reilly author = Dan O'Reilly
version = 1 version = 1
require identity *Identity ca_cert *Path_to_CA_Cert client_cert *Path_to_Client_Cert private_key *Private_Key private_key_passwd *Private_Key_Password require identity *Identity private_key *Private_Key private_key_passwd *Private_Key_Password
optional ca_cert *Path_to_CA_Cert client_cert *Path_to_Client_Cert
----- -----
ctrl_interface=/var/run/wpa_supplicant ctrl_interface=/var/run/wpa_supplicant
network={ network={

View File

@@ -1,7 +1,8 @@
name = PEAP with TKIP name = PEAP with TKIP/MSCHAPV2
author = Fralaltro author = Fralaltro
version = 1 version = 1
require identity *Identity password *Password ca_cert *Path_to_CA_Cert require identity *Identity password *Password
optional ca_cert *Path_to_CA_Cert
----- -----
ctrl_interface=/var/run/wpa_supplicant ctrl_interface=/var/run/wpa_supplicant
network={ network={

View File

@@ -1,4 +1,4 @@
name = WEP (Hex) name = WEP (Hex [0-9/A-F])
author = Adam Blackburn author = Adam Blackburn
version = 1 version = 1
require key *Key require key *Key

View File

@@ -52,7 +52,7 @@ Raise the "About wicd-curses" dialog
.\".PP .\".PP
.\"The following is a work in progress and might not be fully functional as of yet. .\"The following is a work in progress and might not be fully functional as of yet.
.TP .TP
.BR C .BR "C " or "enter"
Bring up network configuration controller for the selected network Bring up network configuration controller for the selected network
.TP .TP
.BR delete .BR delete

View File

@@ -28,7 +28,7 @@ import subprocess
VERSION_NUM = '1.6.0a1' VERSION_NUM = '1.6.0a1'
# REVISION_NUM is automatically updated # REVISION_NUM is automatically updated
REVISION_NUM = 'unknown' REVISION_NUM = 'unknown'
CURSES_REVNO = 'r279' CURSES_REVNO = 'uimod'
try: try:
if not os.path.exists('vcsinfo.py'): if not os.path.exists('vcsinfo.py'):

View File

@@ -632,9 +632,12 @@ class appGui(object):
# Make sure no entries are left blank # Make sure no entries are left blank
if entry.chkbox_encryption.get_active(): if entry.chkbox_encryption.get_active():
encryption_info = entry.encryption_info encryption_info = entry.encryption_info
for x in encryption_info: for entry_info in encryption_info.itervalues():
if encryption_info[x].get_text() == "": if entry_info[0].entry.get_text() == "" and \
error(self.window, language['encrypt_info_missing']) entry_info[1] == 'required':
error(self, "%s (%s)" % (language['encrypt_info_missing'],
entry_info[0].label.get_label())
)
return False return False
# Make sure the checkbox is checked when it should be # Make sure the checkbox is checked when it should be
elif not entry.chkbox_encryption.get_active() and \ elif not entry.chkbox_encryption.get_active() and \

View File

@@ -285,10 +285,6 @@ def LoadEncryptionMethods():
loaded, the template must be listed in the "active" file. loaded, the template must be listed in the "active" file.
""" """
def parse_ent(line, key):
return line.replace(key, "").replace("=", "").strip()
encryptionTypes = []
try: try:
enctypes = open(wpath.encryption + "active","r").readlines() enctypes = open(wpath.encryption + "active","r").readlines()
except IOError, e: except IOError, e:
@@ -296,49 +292,73 @@ def LoadEncryptionMethods():
raise IOError(e) raise IOError(e)
# Parse each encryption method # Parse each encryption method
for x in enctypes: encryptionTypes = []
x = x.strip() for enctype in enctypes:
try: parsed_template = _parse_enc_template(enctype.strip())
f = open(wpath.encryption + x, "r") if parsed_template:
except IOError: encryptionTypes.append(parsed_template)
print 'Failed to load encryption type ' + str(x)
continue
line = f.readlines()
f.close()
cur_type = {}
cur_type[0] = parse_ent(line[0], "name")
cur_type[1] = x
cur_type[2] = {}
# Find the line containing our required fields.
i = 1
try:
while not line[i].startswith("require"):
i += 1
except IndexError:
print "Bad encryption template: Couldn't find 'require' line"
requiredFields = parse_ent(line[i], "require")
requiredFields = requiredFields.split(" ")
# Get the required fields.
index = -1
for current in requiredFields:
# The pretty names will start with an * so we can
# separate them with that.
if current[0] == "*":
# Make underscores spaces
# and remove the *
cur_type[2][index][0] = current.replace("_", " ").lstrip("*")
else:
# Add to the list of things that are required.
index = len(cur_type[2])
cur_type[2][index] = {}
cur_type[2][index][1] = current
# Add the current type to the dict of encryption types.
encryptionTypes.append(cur_type)
return encryptionTypes return encryptionTypes
def __parse_field_ent(fields, field_type='require'):
fields = fields.split(" ")
ret = []
# We need an even number of entries in the line for it to be valid.
if (len(fields) % 2) != 0:
return None
else:
for val, disp_val in grouper(2, fields, fillvalue=None):
if val.startswith("*") or not disp_val.startswith("*"):
return None
ret.append([val, disp_val[1:]])
return ret
def _parse_enc_template(enctype):
""" Parse an encryption template. """
def parse_ent(line, key):
return line.replace(key, "").replace("=", "").strip()
try:
f = open(os.path.join(wpath.encryption, enctype), "r")
except IOError:
print "Failed to open template file %s" % enctype
return None
cur_type = {}
cur_type["type"] = enctype
cur_type["fields"] = []
cur_type['optional'] = []
cur_type['required'] = []
cur_type['name'] = ""
for index, line in enumerate(f):
if line.startswith("name") and not cur_type["name"]:
cur_type["name"] = parse_ent(line, "name")
elif line.startswith("require"):
cur_type["required"] = __parse_field_ent(parse_ent(line, "require"))
if not cur_type["required"]:
# An error occured parsing the require line.
print "Invalid 'required' line found in template %s" % enctype
continue
elif line.startswith("optional"):
cur_type["optional"] = __parse_field_ent(parse_ent(line,
"optional"),
field_type="optional")
if not cur_type["optional"]:
# An error occured parsing the optional line.
print "Invalid 'optional' line found in template %s" % enctype
continue
elif line.startswith("----"):
# We're done.
break
f.close()
if not cur_type["required"]:
print "Failed to find a 'require' line in template %s" % enctype
return None
if not cur_type["name"]:
print "Failed to find a 'name' line in template %s" % enctype
return None
else:
return cur_type
def noneToString(text): def noneToString(text):
""" Convert None, "None", or "" to string type "None" """ Convert None, "None", or "" to string type "None"

View File

@@ -308,8 +308,8 @@ class WirelessSettingsDialog(AdvancedSettingsDialog):
# Build the encryption menu # Build the encryption menu
activeID = -1 # Set the menu to this item when we are done activeID = -1 # Set the menu to this item when we are done
for x, enc_type in enumerate(self.encrypt_types): for x, enc_type in enumerate(self.encrypt_types):
self.combo_encryption.append_text(enc_type[0]) self.combo_encryption.append_text(enc_type['name'])
if enc_type[1] == wireless.GetWirelessProperty(networkID, "enctype"): if enc_type['type'] == wireless.GetWirelessProperty(networkID, "enctype"):
activeID = x activeID = x
self.combo_encryption.set_active(activeID) self.combo_encryption.set_active(activeID)
if activeID != -1: if activeID != -1:
@@ -384,7 +384,7 @@ class WirelessSettingsDialog(AdvancedSettingsDialog):
activeID = -1 # Set the menu to this item when we are done activeID = -1 # Set the menu to this item when we are done
user_enctype = wireless.GetWirelessProperty(networkID, "enctype") user_enctype = wireless.GetWirelessProperty(networkID, "enctype")
for x, enc_type in enumerate(self.encrypt_types): for x, enc_type in enumerate(self.encrypt_types):
if enc_type[1] == user_enctype: if enc_type['type'] == user_enctype:
activeID = x activeID = x
self.combo_encryption.set_active(activeID) self.combo_encryption.set_active(activeID)
@@ -400,24 +400,32 @@ class WirelessSettingsDialog(AdvancedSettingsDialog):
# Check encryption info # Check encryption info
if self.chkbox_encryption.get_active(): if self.chkbox_encryption.get_active():
print "setting encryption info..." print "setting encryption info..."
encryption_info = self.encryption_info encrypt_info = self.encryption_info
encrypt_methods = misc.LoadEncryptionMethods() encrypt_methods = self.encrypt_types
self.set_net_prop("enctype", self.set_net_prop("enctype",
encrypt_methods[self.combo_encryption.get_active()][1]) encrypt_methods[self.combo_encryption.get_active()]['type'])
for x in encryption_info: # Make sure all required fields are filled in.
if encryption_info[x].get_text() == "": for entry_info in encrypt_info.itervalues():
error(self, language['encrypt_info_missing']) if entry_info[0].entry.get_text() == "" and \
entry_info[1] == 'required':
error(self, "%s (%s)" % (language['encrypt_info_missing'],
entry_info[0].label.get_label())
)
return False return False
self.set_net_prop(x, noneToString(encryption_info[x].get_text())) # Now save all the entries.
for entry_key, entry_info in encrypt_info.iteritems():
self.set_net_prop(entry_key,
noneToString(entry_info[0].entry.get_text()))
elif not self.chkbox_encryption.get_active() and \ elif not self.chkbox_encryption.get_active() and \
wireless.GetWirelessProperty(networkid, "encryption"): wireless.GetWirelessProperty(networkid, "encryption"):
# Encrypt checkbox is off, but the network needs it.
error(self, language['enable_encryption']) error(self, language['enable_encryption'])
return False return False
else: else:
print "no encryption specified..." print "no encryption specified..."
self.set_net_prop("enctype", "None") self.set_net_prop("enctype", "None")
for x in self.encryption_info: for entry in encrypt_info.iterkeys():
self.set_net_prop(x, "") self.set_net_prop(entry[0].entry, "")
AdvancedSettingsDialog.save_settings(self) AdvancedSettingsDialog.save_settings(self)
if self.chkbox_global_settings.get_active(): if self.chkbox_global_settings.get_active():
@@ -444,7 +452,7 @@ class WirelessSettingsDialog(AdvancedSettingsDialog):
for z in self.vbox_encrypt_info: for z in self.vbox_encrypt_info:
z.destroy() # Remove stuff in there already z.destroy() # Remove stuff in there already
ID = self.combo_encryption.get_active() ID = self.combo_encryption.get_active()
methods = misc.LoadEncryptionMethods() methods = self.encrypt_types
self.encryption_info = {} self.encryption_info = {}
# If nothing is selected, select the first entry. # If nothing is selected, select the first entry.
@@ -452,22 +460,22 @@ class WirelessSettingsDialog(AdvancedSettingsDialog):
self.combo_encryption.set_active(0) self.combo_encryption.set_active(0)
ID = 0 ID = 0
opts = methods[ID][2] for type_ in ['required', 'optional']:
for x in opts: fields = methods[ID][type_]
box = None for field in fields:
if language.has_key(opts[x][0]): if language.has_key(field[1]):
box = LabelEntry(language[opts[x][0].lower().replace(' ','_')]) box = LabelEntry(language[field[1].lower().replace(' ','_')])
else: else:
box = LabelEntry(opts[x][0].replace('_',' ')) box = LabelEntry(field[1].replace('_',' '))
box.set_auto_hidden(True) box.set_auto_hidden(True)
self.vbox_encrypt_info.pack_start(box) self.vbox_encrypt_info.pack_start(box)
# Add the data to any array, so that the information # Add the data to a dict, so that the information
# can be easily accessed by giving the name of the wanted # can be easily accessed by giving the name of the wanted
# data. # data.
self.encryption_info[opts[x][1]] = box.entry self.encryption_info[field[0]] = [box, type_]
box.entry.set_text(noneToBlankString( box.entry.set_text(noneToBlankString(
wireless.GetWirelessProperty(self.networkID, opts[x][1]))) wireless.GetWirelessProperty(self.networkID, field[0])))
self.vbox_encrypt_info.show_all() self.vbox_encrypt_info.show_all()
@@ -740,7 +748,7 @@ class WirelessNetworkEntry(NetworkEntry):
self.set_encryption(wireless.GetWirelessProperty(networkID, self.set_encryption(wireless.GetWirelessProperty(networkID,
'encryption'), 'encryption'),
wireless.GetWirelessProperty(networkID, wireless.GetWirelessProperty(networkID,
'encryption_method')) 'encryption_method'))
self.set_channel(wireless.GetWirelessProperty(networkID, 'channel')) self.set_channel(wireless.GetWirelessProperty(networkID, 'channel'))
self.name_label.set_use_markup(True) self.name_label.set_use_markup(True)
self.name_label.set_label("%s %s %s %s" % (self._escape(self.essid), self.name_label.set_label("%s %s %s %s" % (self._escape(self.essid),