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

curses/curses_misc.py:

Refactored some ComboBox internals
  Renamed show_first to focus in ComboBox
  Added callback support
curses/netentry_curses.py:
  Renamed NetEntryBase to AdvancedSettingsDialog, and WirelessNetEntry to
    WirelessSettingsDialog
  The "WirelessSettingsDialog" is complete. :-)  Raise it by pressing "C" on a wireless
    network.  Much of the code was taken from netentry.py.  The buttons aren't pretty
    like they are in the Preferences Dialog, but they are fully functional.
curses/prefs_curses.py:
  Refactored to accommodate the ComboBox changes
  Added a warning about changing backends
curses/wicd-curses.py:
  Refactored to accommodate changes to the rest of the program
  Added a constantly displayed message saying how to exit the program, other than
    ctrl+c
curses/TODO: Removed a bunch of stuff that is already implemented, added some stuff that
    needs to be implemented
curses/README: Added/clearified some things
This commit is contained in:
Andrew Psaltis
2009-01-09 20:42:12 -05:00
parent 6fabed0974
commit d1846cb627
7 changed files with 210 additions and 95 deletions

View File

@@ -2,30 +2,33 @@ This is a curses-based client for wicd. It is designed to imitate wicd-client
as much as can be done with a console-based interface. It is written using the
Urwid (http://excess.org/urwid) toolkit, and thus requires it.
That's all there is to it, really. It installs unless you disable when you
call setup.py
That's all there is to it, really. It installs unless you disable it when you
call setup.py.
Right now, it lists current available networks, and whether you are connected
to anything or not, all of which is updated in real time. It will actually
connect you to networks now. Global preferences are now configurable from the
console. Per-network settings is a work in progress.
to anything or not, all of which is updated in real time. Other features
include the ability to connect to networks, global preferences controls, and
per-network settings for wireless networks.
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,
ask me. I try to be on the #wicd Freenode IRC channel most of the time.
Controls:
F5 : refresh wireless networks
F8 or Q: quit
D : disconnect from active network
D : disconnect from all active networks
ESC : if connecting to a network, stop doing so
ENTER : Attempt connection to selected network
P : Display preferences dialog
C : Display network configuration for selected network
C : Display network configuration for selected network (only works for
wireless at the moment)
A : Display "About" dialog
IN DIALOGS:
IN DIALOGS (Meta usually is "Alt"):
ESC or Q: Quit dialog without saving information (if present)
Meta+Left/Right: Change tabs Left/Right
Meta+Left/Right: Change tabs Left/Right (if tabs present)
Meta+Enter : Quit dialog and save information
~NaCl

View File

@@ -1,17 +1,10 @@
Things to do (in no particular order):
* Make a network config dialog for both wireless and wired interfaces
* Make an about dialog
* Make a network config dialog for wired interfaces
* Implement a keyhandler function for the overall frame
* Make keystrokes customizable
* Make color schemes customizable
* Integrate this with the my local copy of the experimental branch
* Give some indication of activity during the connection process
* Make a man page for the UI.
Oh, and most importantly:
* Tell people how they can quit the app in the app (F8 or Q, until I do all of
that stuff) :-)
Anything else? That's all I can think of now.
* Implement a "scan for hidden networks" dialog
* Implement a "make an ad-hoc network" dialog
* Implement a "help" dialog
* Perform a mass code cleanup

View File

@@ -261,7 +261,7 @@ class ComboBox(urwid.WidgetWrap):
#def get_size(self):
def __init__(self,label='',list=[],attrs=('body','editnfc'),focus_attr='focus',use_enter=True,show_first=0):
def __init__(self,label='',list=[],attrs=('body','editnfc'),focus_attr='focus',use_enter=True,focus=0,callback=None,user_args=None):
"""
label : bit of text that preceeds the combobox. If it is "", then
ignore it
@@ -269,13 +269,16 @@ class ComboBox(urwid.WidgetWrap):
body : parent widget
ui : the screen
row : where this object is to be found onscreen
show_first: index of the element in the list to pick first
focus : index of the element in the list to pick first
callback : function that takes (combobox,sel_index,user_args=None)
user_args : user_args in the callback
"""
self.label = urwid.Text(label)
self.attrs = attrs
self.focus_attr = focus_attr
self.list = list
str,trash = self.label.get_text()
self.overlay = None
@@ -290,26 +293,27 @@ class ComboBox(urwid.WidgetWrap):
# We need this to pick our keypresses
self.use_enter = use_enter
# Set the focus at the beginning to 0
self.show_first = show_first
# The Focus
self.focus = focus
# The callback and friends
self.callback = callback
self.user_args = user_args
def set_list(self,list):
self.list = list
def set_show_first(self,show_first):
self.show_first = show_first
def set_focus(self,index):
self.focus = index
def build_combobox(self,body,ui,row):
str,trash = self.label.get_text()
self.cbox = DynWrap(SelText([self.list[self.show_first]+' vvv']),attrs=self.attrs,focus_attr=self.focus_attr)
self.cbox = DynWrap(SelText([self.list[self.focus]+' vvv']),attrs=self.attrs,focus_attr=self.focus_attr)
if str != '':
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.focus,
pos=(len(str)+1,row))
else:
w = urwid.Columns([self.cbox])
self.overlay = self.ComboSpace(self.list,body,ui,self.show_first,
self.overlay = self.ComboSpace(self.list,body,ui,self.focus,
pos=(0,row))
self.set_w(w)
@@ -328,16 +332,18 @@ class ComboBox(urwid.WidgetWrap):
retval = self.overlay.show(self.ui,self.body)
if retval != None:
self.cbox.set_w(SelText(retval+' vvv'))
if self.callback != None:
self.callback(self,self.overlay._listbox.get_focus()[1],self.user_args)
return self._w.keypress(size,key)
# Most obvious thing ever. :-)
def selectable(self):
return self.cbox.selectable()
# Return the index of the selected element
def get_selected(self):
wid,pos = self.overlay._listbox.get_focus()
return (wid,pos)
def get_focus(self):
if self.overlay:
return self.overlay._listbox.get_focus()
else:
return None,self.focus
def get_sensitive(self):
return self.cbox.get_sensitive()

View File

@@ -31,13 +31,13 @@ def error(ui,parent,message):
# /\
# /!!\
# /____\
dialog = Dialog(message,[OK],('body','body','focus'),40,6)
dialog = Dialog([('important','ERROR: '),message],['OK'],('body','body','focus'),40,6,parent)
keys = True
dim = ui.get_cols_rows()
while True:
if keys:
ui.draw_screen(dim, about.render(dim, True))
ui.draw_screen(dim, dialog.render(dim, True))
keys = ui.get_input()
if "window resize" in keys:
@@ -61,10 +61,13 @@ def dbus_init(dbus_ifaces):
wired = dbus_ifaces['wired']
wireless = dbus_ifaces['wireless']
# Both the wired and the wireless NetEntries some of the same fields.
# This will be used to produce the individual network settings
class NetEntryBase(urwid.WidgetWrap):
# Both the wired and the wireless settings preferences dialogs use some of the
# same fields.
# This will be used to produce the individual network settings dialogs way far below
class AdvancedSettingsDialog(urwid.WidgetWrap):
def __init__(self):
self.ui=None
static_ip_t = language['use_static_ip']
ip_t = ('editcp',language['ip']+': ')
netmask_t = ('editcp',language['netmask']+':')
@@ -78,7 +81,7 @@ class NetEntryBase(urwid.WidgetWrap):
dns2_t = ('editcp',language['dns']+ ' ' + language['2']+':'+' '*8)
dns3_t = ('editcp',language['dns']+ ' ' + language['3']+':'+' '*8)
cancel_t = 'cancel'
cancel_t = 'Cancel'
ok_t = 'OK'
self.static_ip_cb = urwid.CheckBox(static_ip_t,
@@ -102,6 +105,12 @@ class NetEntryBase(urwid.WidgetWrap):
_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,
self.ip_edit,
@@ -113,11 +122,20 @@ class NetEntryBase(urwid.WidgetWrap):
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._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):
for w in [ self.ip_edit,self.netmask_edit,self.gateway_edit ]:
w.set_sensitive(new_state)
@@ -139,7 +157,7 @@ class NetEntryBase(urwid.WidgetWrap):
# Code totally yanked from netentry.py
def save_settings(self):
""" Save settings common to wired and wireless settings dialogs. """
if self.chkbox_static_ip.get_active():
if self.static_ip_cb.get_state():
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()))
@@ -148,17 +166,17 @@ class NetEntryBase(urwid.WidgetWrap):
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():
if self.static_dns_cb.get_state() and \
not self.global_dns_cb.get_state():
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('dns_domain', noneToString(self.dns_dom_edit.get_text()))
self.set_net_prop("search_domain", noneToString(self.search_dom_edit.get_text()))
self.set_net_prop("dns1", noneToString(self.dns1.get_text()))
self.set_net_prop("dns2", noneToString(self.dns2.get_text()))
self.set_net_prop("dns3", noneToString(self.dns3.get_text()))
elif self.static_dns_cb.get_state() and \
self.global_dns_cb.get_state():
self.set_net_prop('use_static_dns', True)
self.set_net_prop('use_global_dns', True)
else:
@@ -198,24 +216,35 @@ class NetEntryBase(urwid.WidgetWrap):
########################################
class WirelessNetEntry(NetEntryBase):
class WirelessSettingsDialog(AdvancedSettingsDialog):
def __init__(self,networkID):
NetEntryBase.__init__(self)
global wireless, daemon
AdvancedSettingsDialog.__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.encryption_combo = ComboBox(callback=self.combo_on_change)
self.pile_encrypt = None
# _w is a Frame, _w.body is a ListBox, _w.body.body is the ListWalker :-)
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._w.body.body.append(self.button_cols)
self.encrypt_types = misc.LoadEncryptionMethods()
self.set_values()
# Set the frame title so that people will always know what we're dealing with.
self._w.header = urwid.Text(('header',">Configuring preferences for wireless network \"%s\"" % wireless.GetWirelessProperty(networkID,'essid')),align='right' )
def encryption_toggle(self,chkbox,new_state,user_data=None):
self.encryption_combo.set_sensitive(new_state)
self.pile_encrypt.set_sensitive(new_state)
def combo_on_change(self,combobox,new_index,user_data=None):
self.change_encrypt_method()
def set_values(self):
""" Set the various network settings to the right values. """
@@ -238,9 +267,9 @@ class WirelessNetEntry(NetEntryBase):
#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')))
'encryption')),do_callback=False)
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")
@@ -248,14 +277,19 @@ class WirelessNetEntry(NetEntryBase):
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()
self.encryption_combo.set_focus(activeID)
if activeID != -1:
self.encryption_chkbox.set_state(True,do_callback=False)
self.encryption_combo.set_sensitive(True)
#self.lbox_encrypt_info.set_sensitive(True)
else:
self.encryption_combo.set_focus(0)
# Throw the encryption stuff into a 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()
def set_net_prop(self, option, value):
""" Sets the given option to the given value for this network. """
@@ -265,15 +299,85 @@ class WirelessNetEntry(NetEntryBase):
""" Helper method for fetching/formatting wireless properties. """
return noneToBlankString(wireless.GetWirelessProperty(networkid, label))
# Ripped from netentry.py
def save_settings(self, networkid):
# Check encryption info
if self.encryption_chkbox.get_state():
#print "setting encryption info..."
encryption_info = self.encryption_info
encrypt_methods = misc.LoadEncryptionMethods()
self.set_net_prop("enctype",
encrypt_methods[self.encryption_combo.get_focus()[1] ][1])
for x in encryption_info:
if encryption_info[x].get_edit_text() == "":
error(self.ui, self, language['encrypt_info_missing'])
return False
self.set_net_prop(x, noneToString(encryption_info[x].
get_edit_text()))
elif not self.encryption_chkbox.get_state() and \
wireless.GetWirelessProperty(networkid, "encryption"):
error(self.ui, self, language['enable_encryption'])
return False
else:
#print 'encryption is ' + str(wireless.GetWirelessProperty(networkid,
# "encryption"))
#print "no encryption specified..."
self.set_net_prop("enctype", "None")
AdvancedSettingsDialog.save_settings(self)
if self.global_settings_chkbox.get_state():
self.set_net_prop('use_settings_globally', True)
else:
self.set_net_prop('use_settings_globally', False)
wireless.RemoveGlobalEssidEntry(networkid)
wireless.SaveWirelessNetworkProfile(networkid)
return True
# More or less ripped from netentry.py
def change_encrypt_method(self):
#self.lbox_encrypt = urwid.ListBox()
wid,ID = self.encryption_combo.get_focus()
methods = misc.LoadEncryptionMethods()
self.encryption_info = {}
if self._w.body.body.__contains__(self.pile_encrypt):
self._w.body.body.pop(self._w.body.body.__len__()-2)
# If nothing is selected, select the first entry.
if ID == -1:
self.encryption_combo.set_active(0)
ID = 0
opts = methods[ID][2]
theList = []
for x in opts:
edit = None
if language.has_key(opts[x][0]):
edit = MaskingEdit(('editcp',language[opts[x][0].lower().replace(' ','_')]+': '),mask_mode='on_focus')
else:
edit = MaskingEdit(('editcp',opts[x][0].replace('_',' ')+': '),mask_mode='on_focus')
theList.append(edit)
# Add the data to any array, so that the information
# can be easily accessed by giving the name of the wanted
# data.
self.encryption_info[opts[x][1]] = edit
edit.set_edit_text(noneToBlankString(
wireless.GetWirelessProperty(self.networkID, opts[x][1])))
self.pile_encrypt = DynWrap(urwid.Pile(theList),attrs=('editbx','editnfc'))
self._w.body.body.insert(self._w.body.body.__len__()-1,self.pile_encrypt)
#self._w.body.body.append(self.pile_encrypt)
def run(self,ui,dim,display):
self.ui = ui
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)
#self.change_encrypt_method()
#self._w.body.body.append(self.pile_encrypt)
keys = True
while True:
@@ -281,15 +385,15 @@ class WirelessNetEntry(NetEntryBase):
ui.draw_screen(dim, overlay.render(dim, True))
keys = ui.get_input()
for k in keys:
#Send key to underlying widget:
overlay.keypress(dim, k)
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
if "meta enter" in keys or self.OK_PRESSED:
if self.save_settings(self.networkID):
return True
if self.CANCEL_PRESSED:
return False

View File

@@ -109,6 +109,7 @@ class PrefsDialog(urwid.WidgetWrap):
backend_cat_t = ('header',language['backend'])
backend_t = language['backend']+':'
backend_list = ['spam','double spam','triple spam','quadruple spam']
backend_warn_t = ('important','Changes to the backend (probably) requires a daemon restart')
debug_cat_t = ('header','Debugging')
debug_mode_t = language['use_debug_mode']
@@ -207,6 +208,7 @@ class PrefsDialog(urwid.WidgetWrap):
self.backend_cat = urwid.Text(backend_cat_t)
self.backend_cbox = ComboBox(backend_t)
self.backend_warn = urwid.Text(backend_warn_t)
self.debug_cat = urwid.Text(debug_cat_t)
self.debug_mode_checkb = urwid.CheckBox(debug_mode_t)
@@ -218,7 +220,7 @@ class PrefsDialog(urwid.WidgetWrap):
advancedLB = urwid.ListBox([self.wpa_cat,
self.wpa_cbox,self.wpa_warn,_blank,
self.backend_cat,
self.backend_cbox,_blank,
self.backend_cbox,self.backend_warn,_blank,
self.debug_cat,
self.debug_mode_checkb, _blank,
self.wless_cat,
@@ -315,7 +317,7 @@ class PrefsDialog(urwid.WidgetWrap):
# Pick where to begin first:
def_driver = daemon.GetWPADriver()
try:
self.wpa_cbox.set_show_first(self.wpadrivers.index(def_driver))
self.wpa_cbox.set_focus(self.wpadrivers.index(def_driver))
except ValueError:
pass # It defaults to 0 anyway
@@ -326,9 +328,9 @@ class PrefsDialog(urwid.WidgetWrap):
self.backend_cbox.set_list(self.thebackends)
cur_backend = daemon.GetSavedBackend()
try:
self.backend_cbox.set_show_first(self.thebackends.index(cur_backend))
self.backend_cbox.set_focus(self.thebackends.index(cur_backend))
except ValueError:
self.backend_cbox.set_show_first(0)
self.backend_cbox.set_focus(0)
# Two last checkboxes
self.debug_mode_checkb.set_state(daemon.GetDebugMode())

View File

@@ -56,7 +56,7 @@ from time import sleep
from curses_misc import SelText,ComboBox,Dialog
from prefs_curses import PrefsDialog
import netentry_curses
from netentry_curses import WirelessNetEntry
from netentry_curses import WirelessSettingsDialog
language = misc.get_language_list_gui()
@@ -303,7 +303,7 @@ class WiredComboBox(ComboBox):
wiredL.append(theString)
id+=1
self.__super.__init__(list=wiredL,use_enter=False)
self.set_show_first(theList.index(wired.GetDefaultWiredProfile()))
self.set_focus(theList.index(wired.GetDefaultWiredProfile()))
def keypress(self,size,key):
self.__super.keypress(size,key)
@@ -503,8 +503,9 @@ class appGUI():
def idle_incr(self):
theText = ""
if self.connecting:
theText = "-- Connecting -- Press ESC to cancel"
self.footer1 = urwid.Text(str(self.incr) + ' '+theText)
theText = "-- Connecting -- Press ESC to cancel "
quit_note = "-- Press F8 or Q to quit."
self.footer1 = urwid.Text(str(self.incr) + ' '+theText+quit_note)
self.incr+=1
return True
@@ -585,12 +586,10 @@ class appGUI():
focus = self.thePile.get_focus()
if focus == self.wiredCB:
pass
#self.connect("wired",0)
else:
# wless list only other option
# wireless list only other option
wid,pos = self.thePile.get_focus().get_focus()
WirelessNetEntry(pos).run(ui,self.size,self.frame)
#self.connect("wireless",pos)
WirelessSettingsDialog(pos).run(ui,self.size,self.frame)
#self.netentry = NetEntryBase(dbusmanager.get_dbus_ifaces())
#self.netentry.run(ui,self.size,self.frame)

View File

@@ -39,11 +39,19 @@ The following is a work in progress and might not be fully functional as of yet.
.BR C
Bring up network configuration controller for the selected network
.PP
The following is not implemented yet:
The following are not implemented yet:
.TP
.BR S
Bring up the script selector for the selected network (requires superuser privileges)
.TP
.BR I
Bring up hidden network scanning dialog
.TP
.BR R
Bring up script selector "dialog."
.TP
.BR H
Bring up a rather simplistic help dialog. Of course, it mentions this man page first. :-)
.SH "FILES"
These are not used yet.
.TP