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

Checkpoint in WirelessNetEntry development

curses/curses_misc.py:
  Refactored some DynWrap internals
  Added MaskingEdit, a password edit
  Modified ComboBox to use a DynWrap internally instead of an AttrWrap
curses/netentry_curses.py:
  Added most of the WirelessNetEntry.  It doesn't save information yet, but it does
    load most of it.  Support for viewing the templated network settings is not
    implemented yet.
curses/wicd-curses.py:
  Activated support for the WirelessNetEntry configurator.  The wired one is not
    implemented yet.
This commit is contained in:
Andrew Psaltis
2009-01-06 19:02:27 -05:00
parent 2eaa3e3694
commit 4ab56b1183
4 changed files with 289 additions and 44 deletions

View File

@@ -5,7 +5,7 @@
wicd-curses. wicd-curses.
""" """
# Copyright (C) 2008-9 Andrew Psaltis # Copyright (C) 2008-2009 Andrew Psaltis
# This program is free software; you can redistribute it and/or modify # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@@ -53,7 +53,7 @@ class DynWrap(urwid.AttrWrap):
""" """
def __init__(self,w,sensitive=True,attrs=('editbx','editnfc'),focus_attr='editfc'): def __init__(self,w,sensitive=True,attrs=('editbx','editnfc'),focus_attr='editfc'):
self.attrs=attrs self._attrs=attrs
self._sensitive = sensitive self._sensitive = sensitive
cur_attr = attrs[0] if sensitive else attrs[1] cur_attr = attrs[0] if sensitive else attrs[1]
@@ -63,22 +63,78 @@ class DynWrap(urwid.AttrWrap):
def get_sensitive(self): def get_sensitive(self):
return self._sensitive return self._sensitive
def set_sensitive(self,state): def set_sensitive(self,state):
if state : if state:
self.set_attr(self.attrs[0]) self.set_attr(self._attrs[0])
else: else:
self.set_attr(self.attrs[1]) self.set_attr(self._attrs[1])
self._sensitive = state self._sensitive = state
property(get_sensitive,set_sensitive) property(get_sensitive,set_sensitive)
def get_attrs(self): def get_attrs(self):
return self._attrs return self._attrs
def set_attrs(self,attrs): def set_attrs(self,attrs):
self.attrs = attrs self._attrs = attrs
property(get_attrs,set_attrs) property(get_attrs,set_attrs)
def selectable(self): def selectable(self):
return self._sensitive return self._sensitive
class MaskingEditException(Exception):
pass
# Password-style edit
class MaskingEdit(urwid.Edit):
"""
mask_mode = one of:
"always" : everything is a '*' all of the time
"on_focus" : everything is a '*' only when not in focus
"off" : everything is always unmasked
mask_char = the single character that masks all other characters in the field
"""
def __init__(self, caption = "", edit_text = "", multiline = False,
align = 'left', wrap = 'space', allow_tab = False,
edit_pos = None, layout=None, mask_mode="masked",mask_char='*'):
self.mask_mode = mask_mode
if len(mask_char) > 1:
raise MaskingEditException('Masks of more than one character are not supported!')
self.mask_char = mask_char
self.__super.__init__(caption,edit_text,multiline,align,wrap,allow_tab,edit_pos,layout)
def get_mask_mode(self):
return self.mask_mode
def set_mask_mode(self,mode):
self.mask_mode = mode
def get_masked_text(self):
return self.mask_char*len(self.get_edit_text())
def render(self,(maxcol,), focus=False):
"""
Render edit widget and return canvas. Include cursor when in
focus.
"""
# If we aren't masking anything ATM, then act like an Edit. No problems.
if self.mask_mode == "off" or (self.mask_mode == 'on_focus' and focus == True):
canv = self.__super.render((maxcol,),focus)
# The cache messes this thing up, because I am totally changing what is
# displayed.
self._invalidate()
return canv
# Else, we have a slight mess to deal with...
self._shift_view_to_cursor = not not focus # force bool
text, attr = self.get_text()
text = text[:len(self.caption)]+self.get_masked_text()
trans = self.get_line_translation( maxcol, (text,attr) )
canv = urwid.canvas.apply_text_layout(text, attr, trans, maxcol)
if focus:
canv = urwid.CompositeCanvas(canv)
canv.cursor = self.get_cursor_coords((maxcol,))
return canv
# Tabbed interface, mostly for use in the Preferences Dialog # Tabbed interface, mostly for use in the Preferences Dialog
class TabColumns(urwid.WidgetWrap): class TabColumns(urwid.WidgetWrap):
""" """
@@ -146,6 +202,9 @@ class ComboBoxException(Exception):
# A "combo box" of SelTexts # A "combo box" of SelTexts
# I based this off of the code found here: # I based this off of the code found here:
# http://excess.org/urwid/browser/contrib/trunk/rbreu_menus.py # http://excess.org/urwid/browser/contrib/trunk/rbreu_menus.py
# This is a hack. It isn't without quirks, but it more or less works.
# We need to wait for changes in urwid's Canvas controls before we can actually
# make a real ComboBox.
class ComboBox(urwid.WidgetWrap): class ComboBox(urwid.WidgetWrap):
"""A ComboBox of text objects""" """A ComboBox of text objects"""
class ComboSpace(urwid.WidgetWrap): class ComboSpace(urwid.WidgetWrap):
@@ -202,7 +261,7 @@ class ComboBox(urwid.WidgetWrap):
#def get_size(self): #def get_size(self):
def __init__(self,label='',list=[],attr=('body','focus'),use_enter=True,show_first=0): def __init__(self,label='',list=[],attrs=('body','editnfc'),focus_attr='focus',use_enter=True,show_first=0):
""" """
label : bit of text that preceeds the combobox. If it is "", then label : bit of text that preceeds the combobox. If it is "", then
ignore it ignore it
@@ -214,13 +273,14 @@ class ComboBox(urwid.WidgetWrap):
""" """
self.label = urwid.Text(label) self.label = urwid.Text(label)
self.attr = attr self.attrs = attrs
self.focus_attr = focus_attr
self.list = list self.list = list
str,trash = self.label.get_text() str,trash = self.label.get_text()
self.overlay = None self.overlay = None
#w,sensitive=True,attrs=('editbx','editnfc'),focus_attr='editfc')
self.cbox = urwid.AttrWrap(SelText(' vvv'),attr[0],attr[1]) self.cbox = DynWrap(SelText(' vvv'),attrs=attrs,focus_attr=focus_attr)
# Unicode will kill me sooner or later. ^_^ # Unicode will kill me sooner or later. ^_^
if label != '': if label != '':
w = urwid.Columns([('fixed',len(str),self.label),self.cbox],dividechars=1) w = urwid.Columns([('fixed',len(str),self.label),self.cbox],dividechars=1)
@@ -242,8 +302,7 @@ class ComboBox(urwid.WidgetWrap):
def build_combobox(self,body,ui,row): def build_combobox(self,body,ui,row):
str,trash = self.label.get_text() str,trash = self.label.get_text()
self.cbox = urwid.AttrWrap(SelText([self.list[self.show_first]+' vvv']), self.cbox = DynWrap(SelText([self.list[self.show_first]+' vvv']),attrs=self.attrs,focus_attr=self.focus_attr)
self.attr[0],self.attr[1])
if str != '': if str != '':
w = urwid.Columns([('fixed',len(str),self.label),self.cbox],dividechars=1) w = urwid.Columns([('fixed',len(str),self.label),self.cbox],dividechars=1)
self.overlay = self.ComboSpace(self.list,body,ui,self.show_first, self.overlay = self.ComboSpace(self.list,body,ui,self.show_first,
@@ -273,13 +332,17 @@ class ComboBox(urwid.WidgetWrap):
# Most obvious thing ever. :-) # Most obvious thing ever. :-)
def selectable(self): def selectable(self):
return True return self.cbox.selectable()
# Return the index of the selected element # Return the index of the selected element
def get_selected(self): def get_selected(self):
wid,pos = self.overlay._listbox.get_focus() wid,pos = self.overlay._listbox.get_focus()
return (wid,pos) return (wid,pos)
def get_sensitive(self):
return self.cbox.get_sensitive()
def set_sensitive(self,state):
self.cbox.set_sensitive(state)
# Almost completely ripped from rbreu_filechooser.py: # Almost completely ripped from rbreu_filechooser.py:
# http://excess.org/urwid/browser/contrib/trunk/rbreu_menus.py # http://excess.org/urwid/browser/contrib/trunk/rbreu_menus.py

View File

@@ -1,4 +1,8 @@
#!/usr/bin/env python #!/usr/bin/env python
"""
netentry_curses -- everyone's favorite networks settings dialogs... in text
form!
"""
# Copyright (C) 2009 Andrew Psaltis # Copyright (C) 2009 Andrew Psaltis
@@ -18,14 +22,49 @@
# MA 02110-1301, USA. # MA 02110-1301, USA.
import urwid import urwid
from curses_misc import Dialog,DynWrap from curses_misc import Dialog,DynWrap,MaskingEdit,ComboBox
import wicd.misc as misc import wicd.misc as misc
from wicd.misc import noneToString, stringToNone, noneToBlankString, to_bool
def error(ui,parent,message):
"""Shows an error dialog (or something that resembles one)"""
# /\
# /!!\
# /____\
dialog = Dialog(message,[OK],('body','body','focus'),40,6)
keys = True
dim = ui.get_cols_rows()
while True:
if keys:
ui.draw_screen(dim, about.render(dim, True))
keys = ui.get_input()
if "window resize" in keys:
dim = ui.get_cols_rows()
if "esc" in keys:
return False
for k in keys:
dialog.keypress(dim, k)
if dialog.b_pressed == 'OK':
return False
language = misc.get_language_list_gui() language = misc.get_language_list_gui()
daemon = None
wired = None
wireless = None
# Call this first!
def dbus_init(dbus_ifaces):
global daemon,wired,wireless
daemon = dbus_ifaces['daemon']
wired = dbus_ifaces['wired']
wireless = dbus_ifaces['wireless']
# Both the wired and the wireless NetEntries some of the same fields. # Both the wired and the wireless NetEntries some of the same fields.
# This will be used to produce the individual network settings # This will be used to produce the individual network settings
class NetEntryBase(urwid.WidgetWrap): class NetEntryBase(urwid.WidgetWrap):
def __init__(self,dbus): def __init__(self):
static_ip_t = language['use_static_ip'] static_ip_t = language['use_static_ip']
ip_t = ('editcp',language['ip']+': ') ip_t = ('editcp',language['ip']+': ')
netmask_t = ('editcp',language['netmask']+':') netmask_t = ('editcp',language['netmask']+':')
@@ -49,12 +88,12 @@ class NetEntryBase(urwid.WidgetWrap):
self.gateway_edit=DynWrap(urwid.Edit(gateway_t),False) self.gateway_edit=DynWrap(urwid.Edit(gateway_t),False)
self.use_static_dns_cb = urwid.CheckBox(use_static_dns_t, self.static_dns_cb = urwid.CheckBox(use_static_dns_t,
on_state_change=self.dns_toggle) on_state_change=self.dns_toggle)
self.use_global_dns_cb = DynWrap(urwid.CheckBox(use_global_dns_t, self.global_dns_cb = DynWrap(urwid.CheckBox(use_global_dns_t,
on_state_change=self.dns_toggle),False,('body','editnfc'),None) on_state_change=self.dns_toggle),False,('body','editnfc'),None)
checkb_cols = urwid.Columns([self.use_static_dns_cb, checkb_cols = urwid.Columns([self.static_dns_cb,
self.use_global_dns_cb]) self.global_dns_cb])
self.dns_dom_edit = DynWrap(urwid.Edit(dns_dom_t) ,False) self.dns_dom_edit = DynWrap(urwid.Edit(dns_dom_t) ,False)
self.search_dom_edit = DynWrap(urwid.Edit(search_dom_t),False) self.search_dom_edit = DynWrap(urwid.Edit(search_dom_t),False)
self.dns1 = DynWrap(urwid.Edit(dns1_t) ,False) self.dns1 = DynWrap(urwid.Edit(dns1_t) ,False)
@@ -63,39 +102,73 @@ class NetEntryBase(urwid.WidgetWrap):
_blank = urwid.Text('') _blank = urwid.Text('')
self._listbox = urwid.ListBox([self.static_ip_cb,
self.ip_edit, walker = urwid.SimpleListWalker([self.static_ip_cb,
self.netmask_edit, self.ip_edit,
_blank, self.netmask_edit,
checkb_cols, self.gateway_edit,
self.dns_dom_edit,self.search_dom_edit, _blank,
self.dns1,self.dns2,self.dns3 checkb_cols,
]) self.dns_dom_edit,self.search_dom_edit,
self.dns1,self.dns2,self.dns3
])
self._listbox = urwid.ListBox(walker)
#self._frame = urwid.Frame(self._listbox) #self._frame = urwid.Frame(self._listbox)
self.__super.__init__(self._listbox) self._frame = urwid.Frame(self._listbox)
self.__super.__init__(self._frame)
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)
def dns_toggle(self,checkb,new_state,user_data=None): def dns_toggle(self,checkb,new_state,user_data=None):
if checkb == self.use_static_dns_cb: if checkb == self.static_dns_cb:
for w in [ self.dns_dom_edit,self.search_dom_edit, for w in [ self.dns_dom_edit,self.search_dom_edit,
self.dns1,self.dns2,self.dns3 ]: self.dns1,self.dns2,self.dns3 ]:
w.set_sensitive(new_state) w.set_sensitive(new_state)
if not new_state: if not new_state:
self.use_global_dns_cb.set_state(False,do_callback=False) self.global_dns_cb.set_state(False,do_callback=False)
self.use_global_dns_cb.set_sensitive(new_state) self.global_dns_cb.set_sensitive(new_state)
# use_global_dns_cb is DynWrapped # use_global_dns_cb is DynWrapped
if checkb == self.use_global_dns_cb.get_w(): if checkb == self.global_dns_cb.get_w():
for w in [ self.dns_dom_edit,self.search_dom_edit, for w in [ self.dns_dom_edit,self.search_dom_edit,
self.dns1,self.dns2,self.dns3 ]: self.dns1,self.dns2,self.dns3 ]:
w.set_sensitive(not new_state) w.set_sensitive(not new_state)
# We need a network ID for this, and I am not sure how to get it yet. # Code totally yanked from netentry.py
# TODO: Implement this def save_settings(self):
#def load_settings(self): """ Save settings common to wired and wireless settings dialogs. """
if self.chkbox_static_ip.get_active():
self.set_net_prop("ip", noneToString(self.ip_edit.get_edit_text()))
self.set_net_prop("netmask", noneToString(self.netmask_edit.get_edit_text()))
self.set_net_prop("gateway", noneToString(self.gateway_edit.get_edit_text()))
else:
self.set_net_prop("ip", '')
self.set_net_prop("netmask", '')
self.set_net_prop("gateway", '')
if self.chkbox_static_dns.get_active() and \
not self.chkbox_global_dns.get_active():
self.set_net_prop('use_static_dns', True)
self.set_net_prop('use_global_dns', False)
self.set_net_prop('dns_domain', noneToString(self.txt_domain.get_text()))
self.set_net_prop("search_domain", noneToString(self.txt_search_dom.get_text()))
self.set_net_prop("dns1", noneToString(self.dns_1.get_text()))
self.set_net_prop("dns2", noneToString(self.dns_2.get_text()))
self.set_net_prop("dns3", noneToString(self.dns_3.get_text()))
elif self.chkbox_static_dns.get_active() and \
self.chkbox_global_dns.get_active():
self.set_net_prop('use_static_dns', True)
self.set_net_prop('use_global_dns', True)
else:
self.set_net_prop('use_static_dns', False)
self.set_net_prop('use_global_dns', False)
self.set_net_prop('dns_domain', '')
self.set_net_prop("search_domain", '')
self.set_net_prop("dns1", '')
self.set_net_prop("dns2", '')
self.set_net_prop("dns3", '')
def run(self,ui,dim,display): def run(self,ui,dim,display):
width,height = ui.get_cols_rows() width,height = ui.get_cols_rows()
@@ -122,3 +195,101 @@ class NetEntryBase(urwid.WidgetWrap):
# return False # return False
#if self.OK_PRESSED or 'meta enter' in keys: #if self.OK_PRESSED or 'meta enter' in keys:
# return True # return True
########################################
class WirelessNetEntry(NetEntryBase):
def __init__(self,networkID):
NetEntryBase.__init__(self)
self.networkID = networkID
global_settings_t = language['global_settings']
encryption_t = language['use_encryption']
self.global_settings_chkbox = urwid.CheckBox(global_settings_t)
self.encryption_chkbox = urwid.CheckBox(encryption_t,on_state_change=self.encryption_toggle)
self.encryption_combo = ComboBox()
self._w.body.body.append(self.global_settings_chkbox)
self._w.body.body.append(self.encryption_chkbox)
self._w.body.body.append(self.encryption_combo)
self.encrypt_types = misc.LoadEncryptionMethods()
self.set_values()
def encryption_toggle(self,chkbox,new_state,user_data=None):
self.encryption_combo.set_sensitive(new_state)
def set_values(self):
""" Set the various network settings to the right values. """
networkID = self.networkID
self.ip_edit.set_edit_text(self.format_entry(networkID,"ip"))
self.netmask_edit.set_edit_text(self.format_entry(networkID,"netmask"))
self.gateway_edit.set_edit_text(self.format_entry(networkID,"gateway"))
self.global_dns_cb.set_state(bool(wireless.GetWirelessProperty(networkID,
'use_global_dns')))
self.static_dns_cb.set_state(bool(wireless.GetWirelessProperty(networkID,
'use_static_dns')))
self.dns1.set_edit_text(self.format_entry(networkID, "dns1"))
self.dns2.set_edit_text(self.format_entry(networkID, "dns2"))
self.dns3.set_edit_text(self.format_entry(networkID, "dns3"))
self.dns_dom_edit.set_edit_text(self.format_entry(networkID, "dns_domain"))
self.search_dom_edit.set_edit_text(self.format_entry(networkID, "search_domain"))
#self.reset_static_checkboxes()
self.encryption_chkbox.set_state(bool(wireless.GetWirelessProperty(networkID,
'encryption')))
self.global_settings_chkbox.set_state(bool(wireless.GetWirelessProperty(networkID,
'use_settings_globally')))
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):
if enc_type[1] == user_enctype:
activeID = x
#self.combo_encryption.set_active(activeID)
#if activeID != -1:
# self.chkbox_encryption.set_active(True)
# self.combo_encryption.set_sensitive(True)
# self.vbox_encrypt_info.set_sensitive(True)
#else:
# self.combo_encryption.set_active(0)
#self.change_encrypt_method()
def set_net_prop(self, option, value):
""" Sets the given option to the given value for this network. """
wireless.SetWirelessProperty(self.networkID, option, value)
def format_entry(self, networkid, label):
""" Helper method for fetching/formatting wireless properties. """
return noneToBlankString(wireless.GetWirelessProperty(networkid, label))
def run(self,ui,dim,display):
width,height = ui.get_cols_rows()
list = []
for x, enc_type in enumerate(self.encrypt_types):
list.append(enc_type[0])
self.encryption_combo.set_list(list)
overlay = urwid.Overlay(self, display, ('fixed left', 0),width
, ('fixed top',1), height-3)
self.encryption_combo.build_combobox(overlay,ui,14)
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)
# 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,6 +1,6 @@
#!/usr/bin/env python #!/usr/bin/env python
# Copyright (C) 2008-9 Andrew Psaltis # Copyright (C) 2008-2009 Andrew Psaltis
# This program is free software; you can redistribute it and/or modify # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -1,13 +1,13 @@
#!/usr/bin/env python #!/usr/bin/env python
""" wicd-curses -- a (curses-based) console interface to wicd """ wicd-curses. (curses/urwid-based) console interface to wicd
Provides the a console UI for wicd, so that people with broken X servers can Provides the a console UI for wicd, so that people with broken X servers can
at least get a network connection. Or those who don't like using X. :-) at least get a network connection. Or those who don't like using X. ;-)
""" """
# Copyright (C) 2008-9 Andrew Psaltis # Copyright (C) 2008-2009 Andrew Psaltis
# This program is free software; you can redistribute it and/or modify # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@@ -55,10 +55,10 @@ from time import sleep
# Curses UIs for other stuff # Curses UIs for other stuff
from curses_misc import SelText,ComboBox,Dialog from curses_misc import SelText,ComboBox,Dialog
from prefs_curses import PrefsDialog from prefs_curses import PrefsDialog
from netentry_curses import NetEntryBase import netentry_curses
from netentry_curses import WirelessNetEntry
language = misc.get_language_list_gui() language = misc.get_language_list_gui()
# Whew. Now on to more interesting stuff:
######################################## ########################################
##### SUPPORT CLASSES ##### SUPPORT CLASSES
@@ -582,8 +582,17 @@ class appGUI():
self.frame.keypress( self.size, k ) self.frame.keypress( self.size, k )
if "C" in keys: if "C" in keys:
self.netentry = NetEntryBase(dbusmanager.get_dbus_ifaces()) focus = self.thePile.get_focus()
self.netentry.run(ui,self.size,self.frame) if focus == self.wiredCB:
pass
#self.connect("wired",0)
else:
# wless list only other option
wid,pos = self.thePile.get_focus().get_focus()
WirelessNetEntry(pos).run(ui,self.size,self.frame)
#self.connect("wireless",pos)
#self.netentry = NetEntryBase(dbusmanager.get_dbus_ifaces())
#self.netentry.run(ui,self.size,self.frame)
if " " in keys: if " " in keys:
focus = self.thePile.get_focus() focus = self.thePile.get_focus()
@@ -678,7 +687,7 @@ def setup_dbus(force=True):
dbusmanager.connect_to_dbus() dbusmanager.connect_to_dbus()
except DBusException: except DBusException:
# I may need to be a little more verbose here. # I may need to be a little more verbose here.
# Suggestions as to what should go here # Suggestions as to what should go here, please?
print "Can't connect to the daemon. Are you sure it is running?" print "Can't connect to the daemon. Are you sure it is running?"
print "Please check the wicd log for error messages." print "Please check the wicd log for error messages."
#raise #raise
@@ -690,6 +699,8 @@ def setup_dbus(force=True):
wired = dbus_ifaces['wired'] wired = dbus_ifaces['wired']
DBUS_AVAIL = True DBUS_AVAIL = True
netentry_curses.dbus_init(dbus_ifaces)
return True return True
setup_dbus() setup_dbus()