diff --git a/curses/README b/curses/README index 7586196..d443845 100644 --- a/curses/README +++ b/curses/README @@ -2,8 +2,8 @@ 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's not going to install itself until I -work on it more and figure out how to use distutils. +That's all there is to it, really. It installs unless you disable 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 @@ -18,10 +18,13 @@ D : disconnect from active network 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 A : Display "About" dialog IN DIALOGS: ESC or Q: Quit dialog without saving information (if present) +Meta+Left/Right: Change tabs Left/Right +Meta+Enter : Quit dialog and save information diff --git a/curses/curses_misc.py b/curses/curses_misc.py index 4ed8251..78f0945 100644 --- a/curses/curses_misc.py +++ b/curses/curses_misc.py @@ -40,43 +40,44 @@ class SelText(urwid.Text): """Don't handle any keys.""" return key -class ToggleEdit(urwid.WidgetWrap): - """A edit that can be rendered unselectable by somethhing like a checkbox""" - def __init__(self, caption='', state=True, - attr=('editbx','editfc'),attrnsens='body'): - """ - caption : the Edit's caption - state : the Edit's current sensitivity - attr : tuple of (attr_no_focus, attr_focus) - attrnsens: attr to use when not sensitive - """ - edit = urwid.Edit(caption) - curattr = attr[0] if state == True else attrnsens - w = urwid.AttrWrap(edit,curattr,attr[1]) - self.sensitive=state - self.__super.__init__(w) +# This class is annoying. ^_^ +class DynWrap(urwid.AttrWrap): + """ + Makes an object have mutable selectivity. Attributes will change like + those in an AttrWrap - # Kinda like the thing in PyGTK + w = widget to wrap + sensitive = current selectable state + attrs = tuple of (attr_sens,attr_not_sens) + attrfoc = attributes when in focus, defaults to nothing + """ + + def __init__(self,w,sensitive=True,attrs=('editbx','editnfc'),focus_attr='editfc'): + self.attrs=attrs + self._sensitive = sensitive + + cur_attr = attrs[0] if sensitive else attrs[1] + + self.__super.__init__(w,cur_attr,focus_attr) + + def get_sensitive(self): + return self._sensitive def set_sensitive(self,state): - self.sensitive=state - if state: - self._w.set_attr('editbx') + if state : + self.set_attr(self.attrs[0]) else: - self._w.set_attr('body') + self.set_attr(self.attrs[1]) + self._sensitive = state + property(get_sensitive,set_sensitive) - def set_edit_text(self,text): - self._w.set_edit_text(text) - - def get_edit_text(self): - return self._w.get_edit_text() + def get_attrs(self): + return self._attrs + def set_attrs(self,attrs): + self.attrs = attrs + property(get_attrs,set_attrs) - # If we aren't sensitive, don't be selectable def selectable(self): - return self.sensitive - - # Do what an edit does with keys - def keypress(self,size,key): - return self._w.keypress(size,key) + return self._sensitive # Tabbed interface, mostly for use in the Preferences Dialog class TabColumns(urwid.WidgetWrap): diff --git a/curses/netentry_curses.py b/curses/netentry_curses.py new file mode 100644 index 0000000..2eb4d8f --- /dev/null +++ b/curses/netentry_curses.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python + +# Copyright (C) 2009 Andrew Psaltis + +# 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 +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301, USA. + +import urwid +from curses_misc import Dialog,DynWrap +import wicd.misc as misc + +language = misc.get_language_list_gui() +# 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): + def __init__(self,dbus): + static_ip_t = language['use_static_ip'] + ip_t = ('editcp',language['ip']+': ') + netmask_t = ('editcp',language['netmask']+':') + gateway_t = ('editcp',language['gateway']+':') + + use_static_dns_t = language['use_static_dns'] + use_global_dns_t = language['use_global_dns'] + dns_dom_t = ('editcp',language['dns_domain']+': ') + search_dom_t = ('editcp',language['search_domain']+':') + dns1_t = ('editcp',language['dns']+ ' ' + language['1']+':'+' '*8) + dns2_t = ('editcp',language['dns']+ ' ' + language['2']+':'+' '*8) + dns3_t = ('editcp',language['dns']+ ' ' + language['3']+':'+' '*8) + + cancel_t = 'cancel' + ok_t = 'OK' + + self.static_ip_cb = urwid.CheckBox(static_ip_t, + on_state_change=self.static_ip_set_state) + self.ip_edit =DynWrap(urwid.Edit(ip_t),False) + self.netmask_edit=DynWrap(urwid.Edit(netmask_t),False) + self.gateway_edit=DynWrap(urwid.Edit(gateway_t),False) + + + self.use_static_dns_cb = urwid.CheckBox(use_static_dns_t, + on_state_change=self.dns_toggle) + self.use_global_dns_cb = DynWrap(urwid.CheckBox(use_global_dns_t, + on_state_change=self.dns_toggle),False,('body','editnfc'),None) + checkb_cols = urwid.Columns([self.use_static_dns_cb, + self.use_global_dns_cb]) + self.dns_dom_edit = DynWrap(urwid.Edit(dns_dom_t) ,False) + self.search_dom_edit = DynWrap(urwid.Edit(search_dom_t),False) + self.dns1 = DynWrap(urwid.Edit(dns1_t) ,False) + self.dns2 = DynWrap(urwid.Edit(dns2_t) ,False) + self.dns3 = DynWrap(urwid.Edit(dns3_t) ,False) + + _blank = urwid.Text('') + + self._listbox = urwid.ListBox([self.static_ip_cb, + self.ip_edit, + self.netmask_edit, + _blank, + checkb_cols, + self.dns_dom_edit,self.search_dom_edit, + self.dns1,self.dns2,self.dns3 + ]) + + #self._frame = urwid.Frame(self._listbox) + self.__super.__init__(self._listbox) + + 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) + + def dns_toggle(self,checkb,new_state,user_data=None): + if checkb == self.use_static_dns_cb: + for w in [ self.dns_dom_edit,self.search_dom_edit, + self.dns1,self.dns2,self.dns3 ]: + w.set_sensitive(new_state) + if not new_state: + self.use_global_dns_cb.set_state(False,do_callback=False) + self.use_global_dns_cb.set_sensitive(new_state) + # use_global_dns_cb is DynWrapped + if checkb == self.use_global_dns_cb.get_w(): + for w in [ self.dns_dom_edit,self.search_dom_edit, + self.dns1,self.dns2,self.dns3 ]: + w.set_sensitive(not new_state) + + # We need a network ID for this, and I am not sure how to get it yet. + # TODO: Implement this + #def load_settings(self): + + def run(self,ui,dim,display): + width,height = ui.get_cols_rows() + + overlay = urwid.Overlay(self, 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) + # Check if buttons are pressed. + #if self.CANCEL_PRESSED: + # return False + #if self.OK_PRESSED or 'meta enter' in keys: + # return True diff --git a/curses/prefs_curses.py b/curses/prefs_curses.py index 3a191a3..8ba6461 100755 --- a/curses/prefs_curses.py +++ b/curses/prefs_curses.py @@ -22,7 +22,7 @@ import urwid.curses_display from wicd import misc from wicd import dbusmanager -from curses_misc import SelText,ToggleEdit,ComboBox,TabColumns +from curses_misc import SelText,DynWrap,ComboBox,TabColumns daemon = None wireless = None @@ -133,11 +133,12 @@ class PrefsDialog(urwid.WidgetWrap): global_dns_state = False self.global_dns_checkb = urwid.CheckBox(global_dns_t,global_dns_state, on_state_change=self.global_dns_trigger) - self.search_dom = ToggleEdit(search_dom_t,global_dns_state) - self.dns_dom = ToggleEdit(dns_dom_t,global_dns_state) - self.dns1 = ToggleEdit(dns1_t,global_dns_state) - self.dns2 = ToggleEdit(dns2_t,global_dns_state) - self.dns3 = ToggleEdit(dns3_t,global_dns_state) + self.search_dom = DynWrap(urwid.Edit(search_dom_t),global_dns_state) + self.dns_dom = DynWrap(urwid.Edit(dns_dom_t),global_dns_state) + self.dns1 = DynWrap(urwid.Edit(dns1_t),global_dns_state) + self.dns2 = DynWrap(urwid.Edit(dns2_t),global_dns_state) + self.dns3 = DynWrap(urwid.Edit(dns3_t),global_dns_state) + self.always_show_wired_checkb = urwid.CheckBox(always_show_wired_t) diff --git a/curses/wicd-curses.py b/curses/wicd-curses.py index 63da620..7133dd0 100644 --- a/curses/wicd-curses.py +++ b/curses/wicd-curses.py @@ -54,8 +54,8 @@ from time import sleep # Curses UIs for other stuff from curses_misc import SelText,ComboBox,Dialog -import prefs_curses from prefs_curses import PrefsDialog +from netentry_curses import NetEntryBase language = misc.get_language_list_gui() # Whew. Now on to more interesting stuff: @@ -265,16 +265,16 @@ class NetLabel(urwid.WidgetWrap): def selectable(self): return True def keypress(self,size,key): - self._w.keypress(size,key) - if key == 'C': - # Configure the network - pass - elif key == 'S': + return self._w.keypress(size,key) + #if key == 'C': + # conf = NetEntryBase(dbusmanager.get_dbus_ifaces()) + # conf.run(ui,ui.get_cols_rows(),) + #elif key == 'S': # Configure scripts - pass - elif key == 'enter': - self.connect() - return key + # pass + #elif key == 'enter': + # self.connect() + #return key def connect(self): # This should work. wireless.ConnectWireless(self.id) @@ -307,15 +307,15 @@ class WiredComboBox(ComboBox): def keypress(self,size,key): self.__super.keypress(size,key) - if key == 'C': + #if key == 'C': # Configure the network - pass - elif key == 'S': + # pass + #elif key == 'S': # Configure scripts - pass - elif key == 'enter': - self.connect() - return key + # pass + #elif key == 'enter': + # self.connect() + #return key def connect(self): wired.ConnectWired() @@ -345,7 +345,7 @@ class appGUI(): self.wlessH=urwid.Filler(urwid.Text("Wireless Network(s)")) wiredL,wlessL = gen_network_list() - self.wiredCB = urwid.Filler(WiredComboBox(list=wiredL)) + self.wiredCB = urwid.Filler(ComboBox(list=wiredL)) self.wlessLB = urwid.ListBox(wlessL) # Stuff I used to simulate large lists #spam = SelText('spam') @@ -549,6 +549,17 @@ class appGUI(): # Disconnect from all networks. daemon.Disconnect() self.update_netlist() + # 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: + focus = self.thePile.get_focus() + if focus == self.wiredCB: + 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: # Force disconnect here if connection in progress if self.connecting: @@ -570,6 +581,10 @@ class appGUI(): continue self.frame.keypress( self.size, k ) + if "C" in keys: + self.netentry = NetEntryBase(dbusmanager.get_dbus_ifaces()) + self.netentry.run(ui,self.size,self.frame) + if " " in keys: focus = self.thePile.get_focus() if focus == self.wiredCB: @@ -582,6 +597,18 @@ class appGUI(): #self.wiredCB = self.thePile.get_focus() return True + # TODO: Update this to use the networkentry stuff + def connect(self, nettype, networkid, networkentry=None): + """ Initiates the connection process in the daemon. """ + if nettype == "wireless": + #if not self.check_encryption_valid(networkid, + # networkentry.advanced_dialog): + # self.edit_advanced(None, None, nettype, networkid, networkentry) + # return False + wireless.ConnectWireless(networkid) + elif nettype == "wired": + wired.ConnectWired() + self.update_status() ######################################## ##### INITIALIZATION FUNCTIONS @@ -610,6 +637,7 @@ def main(): ('editcp', 'default', 'default', 'standout'), ('editbx', 'light gray', 'dark blue'), ('editfc', 'white','dark blue', 'bold'), + ('editnfc','dark gray','default'), ('tab active','dark green','light gray'), # Simple colors around text ('green','dark green','default'), diff --git a/in/man=wicd-curses.8.in b/in/man=wicd-curses.8.in index a2fa070..d3846d9 100644 --- a/in/man=wicd-curses.8.in +++ b/in/man=wicd-curses.8.in @@ -34,10 +34,12 @@ Refresh the network list .BR P Bring up the preferences controller .PP -The following are not implemented yet: +The following is a work in progress and might not be fully functional as of yet. .TP .BR C Bring up network configuration controller for the selected network +.PP +The following is not implemented yet: .TP .BR S Bring up the script selector for the selected network (requires superuser privileges) diff --git a/setup.py b/setup.py index 38a9244..293f2bf 100755 --- a/setup.py +++ b/setup.py @@ -398,8 +398,10 @@ try: data.append(( wpath.lib, ['curses/curses_misc.py'])) data.append(( wpath.lib, ['curses/prefs_curses.py'])) data.append(( wpath.lib, ['curses/wicd-curses.py'])) + data.append(( wpath.lib, ['curses/netentry_curses.py'])) data.append(( wpath.bin, ['scripts/wicd-curses'])) - data.append(( wpath.mandir + 'man8', ['man/wicd-curses.8'])) + if not wpath.no_install_man: + data.append(( wpath.mandir + 'man8', ['man/wicd-curses.8'])) piddir = os.path.dirname(wpath.pidfile) if not piddir.endswith('/'): piddir += '/'