mirror of
https://github.com/gryf/wicd.git
synced 2025-12-24 07:02:29 +01:00
Merged NaCl's curses branch into this.
This commit is contained in:
28
curses/README
Normal file
28
curses/README
Normal file
@@ -0,0 +1,28 @@
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
Controls:
|
||||
|
||||
F5 : refresh wireless networks
|
||||
F8 or Q: quit
|
||||
D : disconnect from active network
|
||||
ESC : if connecting to a network, stop doing so
|
||||
ENTER : Attempt connection to selected network
|
||||
P : Display preferences dialog
|
||||
A : Display "About" dialog
|
||||
|
||||
IN DIALOGS:
|
||||
ESC or Q: Quit dialog without saving information (if present)
|
||||
|
||||
|
||||
|
||||
~NaCl
|
||||
17
curses/TODO
Normal file
17
curses/TODO
Normal file
@@ -0,0 +1,17 @@
|
||||
Things to do (in no particular order):
|
||||
|
||||
* Make a network config dialog for both wireless and wired interfaces
|
||||
* Make an about dialog
|
||||
* 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.
|
||||
346
curses/curses_misc.py
Normal file
346
curses/curses_misc.py
Normal file
@@ -0,0 +1,346 @@
|
||||
#!/usr/bin/env python
|
||||
# -* coding: utf-8 -*-
|
||||
|
||||
""" curses_misc.py: Module for various widgets that are used throughout
|
||||
wicd-curses.
|
||||
"""
|
||||
|
||||
# Copyright (C) 2008-9 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
|
||||
|
||||
# My savior. :-)
|
||||
# Although I could have made this myself pretty easily, just want to give credit where
|
||||
# its due.
|
||||
# http://excess.org/urwid/browser/contrib/trunk/rbreu_filechooser.py
|
||||
class SelText(urwid.Text):
|
||||
"""A selectable text widget. See urwid.Text."""
|
||||
|
||||
def selectable(self):
|
||||
"""Make widget selectable."""
|
||||
return True
|
||||
|
||||
|
||||
def keypress(self, size, key):
|
||||
"""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)
|
||||
|
||||
# Kinda like the thing in PyGTK
|
||||
def set_sensitive(self,state):
|
||||
self.sensitive=state
|
||||
if state:
|
||||
self._w.set_attr('editbx')
|
||||
else:
|
||||
self._w.set_attr('body')
|
||||
|
||||
def set_edit_text(self,text):
|
||||
self._w.set_edit_text(text)
|
||||
|
||||
def get_edit_text(self):
|
||||
return self._w.get_edit_text()
|
||||
|
||||
# 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)
|
||||
|
||||
# Tabbed interface, mostly for use in the Preferences Dialog
|
||||
class TabColumns(urwid.WidgetWrap):
|
||||
"""
|
||||
titles_dict = dictionary of tab_contents (a SelText) : tab_widget (box)
|
||||
attr = normal attributes
|
||||
attrsel = attribute when active
|
||||
"""
|
||||
def __init__(self,tab_str,tab_wid,title,bottom_part,attr=('body','focus'),
|
||||
attrsel='tab active', attrtitle='header'):
|
||||
self.bottom_part = bottom_part
|
||||
#title_wid = urwid.Text((attrtitle,title),align='right')
|
||||
column_list = []
|
||||
for w in tab_str:
|
||||
text,trash = w.get_text()
|
||||
column_list.append(('fixed',len(text),w))
|
||||
column_list.append(urwid.Text((attrtitle,title),align='right'))
|
||||
|
||||
self.tab_map = dict(zip(tab_str,tab_wid))
|
||||
self.active_tab = tab_str[0]
|
||||
self.columns = urwid.Columns(column_list,dividechars=1)
|
||||
#walker = urwid.SimpleListWalker([self.columns,tab_wid[0]])
|
||||
#self.listbox = urwid.ListBox(walker)
|
||||
self.gen_pile(tab_wid[0],True)
|
||||
self.frame = urwid.Frame(self.pile)
|
||||
self.__super.__init__(self.frame)
|
||||
|
||||
# Make the pile in the middle
|
||||
def gen_pile(self,lbox,firstrun=False):
|
||||
self.pile = urwid.Pile([
|
||||
('fixed',1,urwid.Filler(self.columns,'top')),
|
||||
urwid.Filler(lbox,'top',height=('relative',99)),
|
||||
('fixed',1,urwid.Filler(self.bottom_part,'bottom'))
|
||||
])
|
||||
if not firstrun:
|
||||
self.frame.set_body(self.pile)
|
||||
self.set_w(self.frame)
|
||||
|
||||
def selectable(self):
|
||||
return True
|
||||
|
||||
def keypress(self,size,key):
|
||||
self._w.keypress(size,key)
|
||||
wid = self.pile.get_focus().get_body()
|
||||
if wid == self.columns:
|
||||
# lw = self.listbox.body
|
||||
# lw.pop(1)
|
||||
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])
|
||||
return key
|
||||
# self.listbox.body = lw
|
||||
|
||||
|
||||
### Combo box code begins here
|
||||
|
||||
class ComboBoxException(Exception):
|
||||
pass
|
||||
|
||||
# A "combo box" of SelTexts
|
||||
# I based this off of the code found here:
|
||||
# http://excess.org/urwid/browser/contrib/trunk/rbreu_menus.py
|
||||
class ComboBox(urwid.WidgetWrap):
|
||||
"""A ComboBox of text objects"""
|
||||
class ComboSpace(urwid.WidgetWrap):
|
||||
"""The actual menu-like space that comes down from the ComboText"""
|
||||
def __init__(self,list,body,ui,show_first=0,pos=(0,0),attr=('body','focus')):
|
||||
"""
|
||||
body : parent widget
|
||||
list : stuff to include in the combobox
|
||||
ui : the screen
|
||||
show_first: index of the element in the list to pick first
|
||||
pos : a tuple of (row,col) where to put the list
|
||||
attr : a tuple of (attr_no_focus,attr_focus)
|
||||
"""
|
||||
|
||||
#Calculate width and height of the menu widget:
|
||||
height = len(list)
|
||||
width = 0
|
||||
for entry in list:
|
||||
if len(entry) > width:
|
||||
width = len(entry)
|
||||
content = [urwid.AttrWrap(SelText(w), attr[0], attr[1])
|
||||
for w in list]
|
||||
self._listbox = urwid.ListBox(content)
|
||||
|
||||
overlay = urwid.Overlay(self._listbox, body, ('fixed left', pos[0]),
|
||||
width + 2, ('fixed top', pos[1]), height)
|
||||
self.__super.__init__(overlay)
|
||||
|
||||
def show(self,ui,display):
|
||||
|
||||
dim = ui.get_cols_rows()
|
||||
keys = True
|
||||
|
||||
#Event loop:
|
||||
while True:
|
||||
if keys:
|
||||
ui.draw_screen(dim, self.render(dim, True))
|
||||
|
||||
keys = ui.get_input()
|
||||
|
||||
if "window resize" in keys:
|
||||
dim = ui.get_cols_rows()
|
||||
if "esc" in keys:
|
||||
return None
|
||||
if "enter" in keys:
|
||||
(wid,pos) = self._listbox.get_focus()
|
||||
(text,attr) = wid.get_text()
|
||||
return text
|
||||
|
||||
for k in keys:
|
||||
#Send key to underlying widget:
|
||||
self._w.keypress(dim, k)
|
||||
|
||||
#def get_size(self):
|
||||
|
||||
def __init__(self,label='',list=[],attr=('body','focus'),use_enter=True,show_first=0):
|
||||
"""
|
||||
label : bit of text that preceeds the combobox. If it is "", then
|
||||
ignore it
|
||||
list : stuff to include in the combobox
|
||||
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
|
||||
"""
|
||||
|
||||
self.label = urwid.Text(label)
|
||||
self.attr = attr
|
||||
self.list = list
|
||||
str,trash = self.label.get_text()
|
||||
|
||||
self.overlay = None
|
||||
|
||||
self.cbox = urwid.AttrWrap(SelText(' vvv'),attr[0],attr[1])
|
||||
# Unicode will kill me sooner or later. ^_^
|
||||
if label != '':
|
||||
w = urwid.Columns([('fixed',len(str),self.label),self.cbox],dividechars=1)
|
||||
else:
|
||||
w = urwid.Columns([self.cbox])
|
||||
self.__super.__init__(w)
|
||||
|
||||
# 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
|
||||
|
||||
def set_list(self,list):
|
||||
self.list = list
|
||||
|
||||
def set_show_first(self,show_first):
|
||||
self.show_first = show_first
|
||||
|
||||
def build_combobox(self,body,ui,row,show_first=0):
|
||||
str,trash = self.label.get_text()
|
||||
self.cbox = urwid.AttrWrap(SelText([self.list[show_first]+' vvv']),
|
||||
self.attr[0],self.attr[1])
|
||||
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,
|
||||
pos=(len(str)+1,row))
|
||||
else:
|
||||
w = urwid.Columns([self.cbox])
|
||||
self.overlay = self.ComboSpace(self.list,body,ui,self.show_first,
|
||||
pos=(0,row))
|
||||
|
||||
self.set_w(w)
|
||||
self.body = body
|
||||
self.ui = ui
|
||||
|
||||
# If we press space or enter, be a combo box!
|
||||
def keypress(self,size,key):
|
||||
activate = key == ' '
|
||||
if self.use_enter:
|
||||
activate = activate or key == 'enter'
|
||||
if activate:
|
||||
# Die if the user didn't prepare the combobox overlay
|
||||
if self.overlay == None:
|
||||
raise ComboBoxException('ComboBox must be built before use!')
|
||||
retval = self.overlay.show(self.ui,self.body)
|
||||
if retval != None:
|
||||
self.cbox.set_w(SelText(retval+' vvv'))
|
||||
return self._w.keypress(size,key)
|
||||
|
||||
# Most obvious thing ever. :-)
|
||||
def selectable(self):
|
||||
return True
|
||||
|
||||
# Return the index of the selected element
|
||||
def get_selected(self):
|
||||
wid,pos = self.overlay._listbox.get_focus()
|
||||
return pos
|
||||
|
||||
|
||||
# Almost completely ripped from rbreu_filechooser.py:
|
||||
# http://excess.org/urwid/browser/contrib/trunk/rbreu_menus.py
|
||||
class Dialog(urwid.WidgetWrap):
|
||||
"""
|
||||
Creates a BoxWidget that displays a message
|
||||
|
||||
Attributes:
|
||||
|
||||
b_pressed -- Contains the label of the last button pressed or None if no
|
||||
button has been pressed.
|
||||
edit_text -- After a button is pressed, this contains the text the user
|
||||
has entered in the edit field
|
||||
"""
|
||||
|
||||
b_pressed = None
|
||||
edit_text = None
|
||||
|
||||
_blank = urwid.Text("")
|
||||
_edit_widget = None
|
||||
_mode = None
|
||||
|
||||
def __init__(self, msg, buttons, attr, width, height, body, ):
|
||||
"""
|
||||
msg -- content of the message widget, one of:
|
||||
plain string -- string is displayed
|
||||
(attr, markup2) -- markup2 is given attribute attr
|
||||
[markupA, markupB, ... ] -- list items joined together
|
||||
buttons -- a list of strings with the button labels
|
||||
attr -- a tuple (background, button, active_button) of attributes
|
||||
width -- width of the message widget
|
||||
height -- height of the message widget
|
||||
body -- widget displayed beneath the message widget
|
||||
"""
|
||||
|
||||
# Text widget containing the message:
|
||||
msg_widget = urwid.Padding(urwid.Text(msg), 'center', width - 4)
|
||||
|
||||
# GridFlow widget containing all the buttons:
|
||||
button_widgets = []
|
||||
|
||||
for button in buttons:
|
||||
button_widgets.append(urwid.AttrWrap(
|
||||
urwid.Button(button, self._action), attr[1], attr[2]))
|
||||
|
||||
button_grid = urwid.GridFlow(button_widgets, 12, 2, 1, 'center')
|
||||
|
||||
# Combine message widget and button widget:
|
||||
widget_list = [msg_widget, self._blank, button_grid]
|
||||
self._combined = urwid.AttrWrap(urwid.Filler(
|
||||
urwid.Pile(widget_list, 2)), attr[0])
|
||||
|
||||
# This was the real thing I added to this class
|
||||
self._linebox = urwid.LineBox(self._combined)
|
||||
# Place the dialog widget on top of body:
|
||||
# Width and height are increased to accomidate the linebox
|
||||
overlay = urwid.Overlay(self._linebox, body, 'center', width+2,
|
||||
'middle', height+2)
|
||||
|
||||
urwid.WidgetWrap.__init__(self, overlay)
|
||||
|
||||
|
||||
def _action(self, button):
|
||||
"""
|
||||
Function called when a button is pressed.
|
||||
Should not be called manually.
|
||||
"""
|
||||
|
||||
self.b_pressed = button.get_label()
|
||||
if self._edit_widget:
|
||||
self.edit_text = self._edit_widget.get_edit_text()
|
||||
466
curses/prefs_curses.py
Normal file
466
curses/prefs_curses.py
Normal file
@@ -0,0 +1,466 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Copyright (C) 2008-9 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
|
||||
import urwid.curses_display
|
||||
|
||||
from wicd import misc
|
||||
from wicd import dbusmanager
|
||||
from curses_misc import SelText,ToggleEdit,ComboBox,TabColumns
|
||||
|
||||
daemon = None
|
||||
wireless = None
|
||||
wired = None
|
||||
# Will work for now, I guess.
|
||||
language = misc.get_language_list_gui()
|
||||
|
||||
class PrefsDialog(urwid.WidgetWrap):
|
||||
def __init__(self,body,pos,ui,dbus=None):
|
||||
global daemon, wireless, wired
|
||||
|
||||
daemon = dbus['daemon']
|
||||
wireless = dbus['wireless']
|
||||
wired = dbus['wired']
|
||||
|
||||
width,height = ui.get_cols_rows()
|
||||
height -= 3
|
||||
#width = 80
|
||||
#height = 20
|
||||
# Stuff that goes at the top
|
||||
|
||||
header0_t = language["gen_settings"]
|
||||
header1_t = language["ext_programs"]
|
||||
header2_t = language["advanced_settings"]
|
||||
self.header0 = urwid.AttrWrap(SelText(header0_t),'tab active','focus')
|
||||
self.header1 = urwid.AttrWrap(SelText(header1_t),'body','focus')
|
||||
self.header2 = urwid.AttrWrap(SelText(header2_t),'body','focus')
|
||||
title = language['preferences']
|
||||
|
||||
# Blank line
|
||||
_blank = urwid.Text('')
|
||||
|
||||
####
|
||||
#### Text in the widgets
|
||||
####
|
||||
|
||||
# General Settings
|
||||
net_cat_t = ('header','Network Interfaces')
|
||||
wired_t = ('editcp',language['wired_interface']+': ')
|
||||
wless_t = ('editcp',language['wireless_interface']+':')
|
||||
always_show_wired_t = 'Always show wired interface'
|
||||
|
||||
global_dns_cat_t = ('header','Global DNS Servers')
|
||||
global_dns_t = ('editcp',language['use_global_dns'])
|
||||
dns_dom_t = ('editcp',' DNS Domain: ')
|
||||
search_dom_t = ('editcp',' Search domain:')
|
||||
dns1_t = ('editcp',' DNS server 1: ')
|
||||
dns2_t = ('editcp',' DNS server 2: ')
|
||||
dns3_t = ('editcp',' DNS server 3: ')
|
||||
|
||||
|
||||
wired_auto_cat_t= ('header','Wired Autoconnect Settings')
|
||||
wired_auto_1_t = language['use_default_profile']
|
||||
wired_auto_2_t = language['show_wired_list']
|
||||
wired_auto_3_t = language['use_last_used_profile']
|
||||
|
||||
#### External Programs
|
||||
automatic_t = language['wicd_auto_config']
|
||||
|
||||
dhcp_header_t = ('header',language["dhcp_client"])
|
||||
# Automatic
|
||||
dhcp1_t = 'dhclient'
|
||||
dhcp2_t = 'dhcpcd'
|
||||
dhcp3_t = 'pump'
|
||||
|
||||
wired_detect_header_t = ('header',language["wired_detect"])
|
||||
wired1_t = 'ethtool'
|
||||
wired2_t = 'mii-tool'
|
||||
|
||||
flush_header_t = ('header',language["route_flush"])
|
||||
flush1_t = 'ip'
|
||||
flush2_t = 'route'
|
||||
|
||||
#### Advanced Settings
|
||||
#wpa_t=('editcp',language['wpa_supplicant_driver']+':')
|
||||
wpa_cat_t=('header','WPA_Supplicant')
|
||||
wpa_t=('editcp','Driver:')
|
||||
wpa_list = ['spam','double spam','triple spam','quadruple spam']
|
||||
wpa_warn_t = ('important','You should almost always use wext as the WPA Supplicant Driver')
|
||||
|
||||
backend_cat_t = ('header',language['backend'])
|
||||
backend_t = language['backend']+':'
|
||||
backend_list = ['spam','double spam','triple spam','quadruple spam']
|
||||
|
||||
debug_cat_t = ('header','Debugging')
|
||||
debug_mode_t = language['use_debug_mode']
|
||||
|
||||
wless_cat_t = ('header','Wireless Interface')
|
||||
use_dbm_t = language['display_type_dialog']
|
||||
|
||||
auto_reconn_cat_t = ('header','Automatic Reconnect')
|
||||
auto_reconn_t = 'Automatically reconnect on connection loss'
|
||||
|
||||
|
||||
####
|
||||
#### UI Widgets
|
||||
####
|
||||
|
||||
# General Settings
|
||||
self.net_cat = urwid.Text(net_cat_t)
|
||||
self.wired_edit = urwid.AttrWrap(urwid.Edit(wired_t),'editbx','editfc')
|
||||
self.wless_edit = urwid.AttrWrap(urwid.Edit(wless_t),'editbx','editfc')
|
||||
|
||||
self.global_dns_cat = urwid.Text(global_dns_cat_t)
|
||||
# Default the global DNS settings to off. They will be reenabled later
|
||||
# if so required.
|
||||
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.always_show_wired_checkb = urwid.CheckBox(always_show_wired_t)
|
||||
|
||||
self.wired_auto_l = []
|
||||
self.wired_auto_cat = urwid.Text(wired_auto_cat_t)
|
||||
self.wired_auto_1 = urwid.RadioButton(self.wired_auto_l,wired_auto_1_t)
|
||||
self.wired_auto_2 = urwid.RadioButton(self.wired_auto_l,wired_auto_2_t)
|
||||
self.wired_auto_3 = urwid.RadioButton(self.wired_auto_l,wired_auto_3_t)
|
||||
generalLB = urwid.ListBox([self.net_cat,
|
||||
self.wless_edit,#_blank,
|
||||
self.wired_edit,
|
||||
self.always_show_wired_checkb,_blank,
|
||||
self.global_dns_cat,
|
||||
self.global_dns_checkb,#_blank,
|
||||
self.search_dom,self.dns_dom,
|
||||
self.dns1,self.dns2,self.dns3,_blank,
|
||||
self.wired_auto_cat,
|
||||
self.wired_auto_1,
|
||||
self.wired_auto_2,
|
||||
self.wired_auto_3
|
||||
])
|
||||
|
||||
#### External Programs tab
|
||||
automatic_t = language['wicd_auto_config']
|
||||
|
||||
self.dhcp_header = urwid.Text(dhcp_header_t)
|
||||
self.dhcp_l = []
|
||||
# Automatic
|
||||
self.dhcp0 = urwid.RadioButton(self.dhcp_l,automatic_t)
|
||||
self.dhcp1 = urwid.RadioButton(self.dhcp_l,dhcp1_t)
|
||||
self.dhcp2 = urwid.RadioButton(self.dhcp_l,dhcp2_t)
|
||||
self.dhcp3 = urwid.RadioButton(self.dhcp_l,dhcp3_t)
|
||||
|
||||
self.wired_l = []
|
||||
self.wired_detect_header = urwid.Text(wired_detect_header_t)
|
||||
self.wired0 = urwid.RadioButton(self.wired_l,automatic_t)
|
||||
self.wired1 = urwid.RadioButton(self.wired_l,wired1_t)
|
||||
self.wired2 = urwid.RadioButton(self.wired_l,wired2_t)
|
||||
|
||||
self.flush_l = []
|
||||
self.flush_header = urwid.Text(flush_header_t)
|
||||
self.flush0 = urwid.RadioButton(self.flush_l,automatic_t)
|
||||
self.flush1 = urwid.RadioButton(self.flush_l,flush1_t)
|
||||
self.flush2 = urwid.RadioButton(self.flush_l,flush2_t)
|
||||
|
||||
externalLB = urwid.ListBox([self.dhcp_header,
|
||||
self.dhcp0,self.dhcp1,self.dhcp2,self.dhcp3,
|
||||
_blank,
|
||||
self.wired_detect_header,
|
||||
self.wired0,self.wired1,self.wired2,
|
||||
_blank,
|
||||
self.flush_header,
|
||||
self.flush0,self.flush1,self.flush2
|
||||
])
|
||||
|
||||
|
||||
#### Advanced settings
|
||||
self.wpa_cat = urwid.Text(wpa_cat_t)
|
||||
self.wpa_cbox = ComboBox(wpa_t)
|
||||
self.wpa_warn = urwid.Text(wpa_warn_t)
|
||||
|
||||
self.backend_cat = urwid.Text(backend_cat_t)
|
||||
self.backend_cbox = ComboBox(backend_t)
|
||||
|
||||
self.debug_cat = urwid.Text(debug_cat_t)
|
||||
self.debug_mode_checkb = urwid.CheckBox(debug_mode_t)
|
||||
|
||||
self.wless_cat = urwid.Text(wless_cat_t)
|
||||
self.use_dbm_checkb = urwid.CheckBox(use_dbm_t)
|
||||
|
||||
self.auto_reconn_cat = urwid.Text(auto_reconn_cat_t)
|
||||
self.auto_reconn_checkb = urwid.CheckBox(auto_reconn_t)
|
||||
|
||||
advancedLB = urwid.ListBox([self.wpa_cat,
|
||||
self.wpa_cbox,self.wpa_warn,_blank,
|
||||
self.backend_cat,
|
||||
self.backend_cbox,_blank,
|
||||
self.debug_cat,
|
||||
self.debug_mode_checkb, _blank,
|
||||
self.wless_cat,
|
||||
self.use_dbm_checkb, _blank,
|
||||
self.auto_reconn_cat,
|
||||
self.auto_reconn_checkb])
|
||||
|
||||
|
||||
headerList = [self.header0,self.header1,self.header2]
|
||||
lbList = [generalLB,externalLB,advancedLB]
|
||||
self.tab_map = {self.header0 : generalLB,
|
||||
self.header1 : externalLB,
|
||||
self.header2 : advancedLB}
|
||||
#self.load_settings()
|
||||
|
||||
# Now for the buttons:
|
||||
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.active_tab = self.header0
|
||||
|
||||
#self.columns = urwid.Columns([('fixed',len(header0_t),self.header0),
|
||||
# ('fixed',len(header1_t),self.header1),
|
||||
# ('fixed',len(header2_t),self.header2),
|
||||
# urwid.Text(('header',title),align='right')],
|
||||
# dividechars=1)
|
||||
|
||||
#content = [self.columns,generalPile]
|
||||
#self._label = urwid.AttrWrap(SelText(titles),attr[0],attr[1])
|
||||
#self.walker = urwid.SimpleListWalker(content)
|
||||
#self.listbox = urwid.ListBox(self.walker)
|
||||
#self._linebox = urwid.LineBox(self._listbox)
|
||||
self.tabs = TabColumns(headerList,lbList,'Preferences',self.button_cols)
|
||||
#overlay = urwid.Overlay(self.tabs, body, ('fixed left', pos[0]),
|
||||
# width, ('fixed top', pos[1]), height)
|
||||
self.__super.__init__(self.tabs)
|
||||
|
||||
def load_settings(self):
|
||||
### General Settings
|
||||
# Urwid does not like dbus.Strings as text markups
|
||||
wless_iface = unicode(daemon.GetWirelessInterface())
|
||||
wired_iface = unicode(daemon.GetWiredInterface())
|
||||
self.wless_edit.set_edit_text(wless_iface)
|
||||
self.wired_edit.set_edit_text(wired_iface)
|
||||
|
||||
self.always_show_wired_checkb.set_state(
|
||||
daemon.GetAlwaysShowWiredInterface())
|
||||
|
||||
# DNS
|
||||
self.global_dns_checkb.set_state(daemon.GetUseGlobalDNS())
|
||||
theDNS = daemon.GetGlobalDNSAddresses()
|
||||
|
||||
i = 0
|
||||
for w in self.dns1,self.dns2,self.dns3,self.dns_dom,self.search_dom :
|
||||
w.set_edit_text(misc.noneToBlankString(theDNS[i]))
|
||||
i+=1
|
||||
|
||||
# Wired Automatic Connection
|
||||
self.wired_auto_l[daemon.GetWiredAutoConnectMethod()-1]
|
||||
|
||||
### External Programs
|
||||
dhcp_method = daemon.GetDHCPClient()
|
||||
self.dhcp_l[dhcp_method].set_state(True)
|
||||
|
||||
wired_link_method = daemon.GetLinkDetectionTool()
|
||||
self.wired_l[wired_link_method].set_state(True)
|
||||
|
||||
flush_method = daemon.GetFlushTool()
|
||||
self.flush_l[flush_method].set_state(True)
|
||||
|
||||
### Advanced settings
|
||||
# wpa_supplicant janx
|
||||
self.wpadrivers = ["wext", "hostap", "madwifi", "atmel",
|
||||
"ndiswrapper", "ipw"]
|
||||
self.wpadrivers = wireless.GetWpaSupplicantDrivers(self.wpadrivers)
|
||||
self.wpadrivers.append("ralink_legacy")
|
||||
# Same as above with the dbus.String
|
||||
self.thedrivers = [unicode(w) for w in self.wpadrivers]
|
||||
self.wpa_cbox.set_list(self.thedrivers)
|
||||
|
||||
# Pick where to begin first:
|
||||
def_driver = daemon.GetWPADriver()
|
||||
try:
|
||||
self.wpa_cbox.set_show_first(self.wpadrivers.index(def_driver))
|
||||
except ValueError:
|
||||
pass # It defaults to 0 anyway
|
||||
|
||||
self.backends = daemon.GetBackendList()
|
||||
# Remove the blank string b/c of some dbus mess
|
||||
self.backends.remove('')
|
||||
self.thebackends= [unicode(w) for w in self.backends]
|
||||
self.backend_cbox.set_list(self.thebackends)
|
||||
|
||||
# Three last checkboxes
|
||||
self.debug_mode_checkb.set_state(daemon.GetDebugMode())
|
||||
self.use_dbm_checkb.set_state(daemon.GetSignalDisplayType())
|
||||
self.auto_reconn_checkb.set_state(daemon.GetAutoReconnect())
|
||||
|
||||
def save_results(self):
|
||||
""" Pushes the selected settings to the daemon.
|
||||
This exact order is found in prefs.py"""
|
||||
daemon.SetUseGlobalDNS(self.global_dns_checkb.get_state())
|
||||
daemon.SetGlobalDNS(self.dns1.get_edit_text(), self.dns2.get_edit_text(),
|
||||
self.dns3.get_edit_text(), self.dns_dom.get_edit_text(),
|
||||
self.search_dom.get_edit_text())
|
||||
daemon.SetWirelessInterface(self.wless_edit.get_edit_text())
|
||||
daemon.SetWiredInterface(self.wired_edit.get_edit_text())
|
||||
daemon.SetWPADriver(self.wpadrivers[self.wpa_cbox.get_selected()])
|
||||
daemon.SetAlwaysShowWiredInterface(self.always_show_wired_checkb.get_state())
|
||||
daemon.SetAutoReconnect(self.auto_reconn_checkb.get_state())
|
||||
daemon.SetDebugMode(self.debug_mode_checkb.get_state())
|
||||
daemon.SetSignalDisplayType(int(self.use_dbm_checkb.get_state()))
|
||||
if self.wired_auto_2.get_state():
|
||||
daemon.SetWiredAutoConnectMethod(2)
|
||||
elif self.wired_auto_3.get_state():
|
||||
daemon.SetWiredAutoConnectMethod(3)
|
||||
else:
|
||||
daemon.SetWiredAutoConnectMethod(1)
|
||||
|
||||
daemon.SetBackend(self.backends[self.backend_cbox.get_selected()])
|
||||
|
||||
# External Programs Tab
|
||||
if self.dhcp0.get_state():
|
||||
dhcp_client = misc.AUTO
|
||||
elif self.dhcp1.get_state():
|
||||
dhcp_client = misc.DHCLIENT
|
||||
elif self.dhcp2.get_state():
|
||||
dhcp_client = misc.DHCPCD
|
||||
else:
|
||||
dhcp_client = misc.PUMP
|
||||
daemon.SetDHCPClient(dhcp_client)
|
||||
|
||||
if self.wired0.get_state():
|
||||
link_tool = misc.AUTO
|
||||
elif self.wired1.get_state():
|
||||
link_tool = misc.ETHTOOL
|
||||
else:
|
||||
link_tool = misc.MIITOOL
|
||||
daemon.SetLinkDetectionTool(link_tool)
|
||||
|
||||
if self.flush0.get_state():
|
||||
flush_tool = misc.AUTO
|
||||
elif self.flush1.get_state():
|
||||
flush_tool = misc.IP
|
||||
else:
|
||||
flush_tool = misc.ROUTE
|
||||
daemon.SetFlushTool(flush_tool)
|
||||
|
||||
# DNS CheckBox callback
|
||||
def global_dns_trigger(self,check_box,new_state,user_data=None):
|
||||
for w in self.dns1,self.dns2,self.dns3,self.dns_dom,self.search_dom:
|
||||
w.set_sensitive(new_state)
|
||||
|
||||
# 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 ready_comboboxes(self,ui,body):
|
||||
self.wpa_cbox.build_combobox(body,ui,4)
|
||||
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()
|
||||
# TODO: The below, if things go 'well'
|
||||
# If we are small, "tabbify" the interface
|
||||
# Else, pile it together
|
||||
|
||||
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 self.CANCEL_PRESSED:
|
||||
return False
|
||||
if self.OK_PRESSED in keys:
|
||||
return True
|
||||
|
||||
|
||||
###
|
||||
### EXTERNAL ENTRY POINT STUFF
|
||||
###
|
||||
def run_it():
|
||||
dialog = PrefsDialog(None,(0,0),ui,dbusmanager.get_dbus_ifaces())
|
||||
keys = True
|
||||
dim = ui.get_cols_rows()
|
||||
dialog.load_settings()
|
||||
dialog.ready_comboboxes(ui,dialog)
|
||||
while True:
|
||||
if keys:
|
||||
ui.draw_screen(dim, dialog.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:
|
||||
dialog.keypress(dim, k)
|
||||
if dialog.CANCEL_PRESSED:
|
||||
return False
|
||||
if dialog.OK_PRESSED:
|
||||
dialog.save_results()
|
||||
return True
|
||||
|
||||
if __name__=='__main__':
|
||||
try:
|
||||
dbusmanager.connect_to_dbus()
|
||||
except DBusException:
|
||||
# I may need to be a little more verbose here.
|
||||
# Suggestions as to what should go here
|
||||
print "Can't connect to the daemon. Are you sure it is running?"
|
||||
print "Please check the wicd log for error messages."
|
||||
raise
|
||||
ui = urwid.curses_display.Screen()
|
||||
ui.register_palette([
|
||||
('body','light gray','default'),
|
||||
('focus','dark magenta','light gray'),
|
||||
('header','light blue','default'),
|
||||
('important','light red','default'),
|
||||
('connected','dark green','default'),
|
||||
('connected focus','default','dark green'),
|
||||
('editcp', 'default', 'default', 'standout'),
|
||||
('editbx', 'light gray', 'dark blue'),
|
||||
('editfc', 'white','dark blue', 'bold'),
|
||||
('tab active','dark green','light gray')])
|
||||
ui.run_wrapper(run_it)
|
||||
625
curses/wicd-curses.py
Normal file
625
curses/wicd-curses.py
Normal file
@@ -0,0 +1,625 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
""" wicd-curses -- a (curses-based) console interface to wicd
|
||||
|
||||
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. :-)
|
||||
|
||||
"""
|
||||
|
||||
# Copyright (C) 2008-9 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.
|
||||
|
||||
"""
|
||||
This contains/will contain A LOT of code from the other parts of wicd.
|
||||
|
||||
This is probably due to the fact that I did not really know what I was doing
|
||||
when I started writing this. It works, so I guess that's all that matters.
|
||||
|
||||
Comments, criticisms, patches, bug reports all welcome!
|
||||
"""
|
||||
|
||||
# UI stuff
|
||||
#import urwid.raw_display
|
||||
import urwid.curses_display
|
||||
import urwid
|
||||
|
||||
# DBus communication stuff
|
||||
from dbus import DBusException
|
||||
from dbus import version as dbus_version
|
||||
# It took me a while to figure out that I have to use this.
|
||||
import gobject
|
||||
|
||||
# Other important wicd-related stuff
|
||||
import wicd.misc as misc
|
||||
from wicd import dbusmanager
|
||||
|
||||
# Internal Python stuff
|
||||
import sys
|
||||
from time import sleep
|
||||
|
||||
# Curses UIs for other stuff
|
||||
from curses_misc import SelText,ComboBox,Dialog
|
||||
import prefs_curses
|
||||
from prefs_curses import PrefsDialog
|
||||
|
||||
language = misc.get_language_list_gui()
|
||||
# Whew. Now on to more interesting stuff:
|
||||
|
||||
########################################
|
||||
##### SUPPORT CLASSES
|
||||
########################################
|
||||
# A hack to get any errors that pop out of the program to appear ***AFTER*** the
|
||||
# program exits.
|
||||
# I also may have been a bit overkill about using this too, I guess I'll find
|
||||
# that out soon enough.
|
||||
# I learned about this from this example:
|
||||
# http://blog.lutzky.net/2007/09/16/exception-handling-decorators-and-python/
|
||||
class wrap_exceptions:
|
||||
def __call__(self, f):
|
||||
def wrap_exceptions(*args, **kargs):
|
||||
try:
|
||||
return f(*args, **kargs)
|
||||
except KeyboardInterrupt:
|
||||
gobject.source_remove(redraw_tag)
|
||||
loop.quit()
|
||||
ui.stop()
|
||||
print "\nTerminated by user."
|
||||
raise
|
||||
except :
|
||||
# If the UI isn't inactive (redraw_tag wouldn't normally be
|
||||
# set), then don't try to stop it, just gracefully die.
|
||||
if redraw_tag != -1:
|
||||
# Remove update_ui from the event queue
|
||||
gobject.source_remove(redraw_tag)
|
||||
# Quit the loop
|
||||
loop.quit()
|
||||
# Zap the screen
|
||||
ui.stop()
|
||||
# Print out standard notification:
|
||||
print "\nEXCEPTION!"
|
||||
print "Please report this to the maintainer and/or file a bug report with the backtrace below:"
|
||||
print redraw_tag
|
||||
# Flush the buffer so that the notification is always above the
|
||||
# backtrace
|
||||
sys.stdout.flush()
|
||||
# Raise the exception
|
||||
#sleep(2)
|
||||
raise
|
||||
|
||||
return wrap_exceptions
|
||||
|
||||
########################################
|
||||
##### SUPPORT FUNCTIONS
|
||||
########################################
|
||||
|
||||
# Look familiar? These two functions are clones of functions found in wicd's
|
||||
# gui.py file, except that now set_status is a function passed to them.
|
||||
@wrap_exceptions()
|
||||
def check_for_wired(wired_ip,set_status):
|
||||
""" Determine if wired is active, and if yes, set the status. """
|
||||
if wired_ip and wired.CheckPluggedIn():
|
||||
set_status(language['connected_to_wired'].replace('$A',wired_ip))
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
@wrap_exceptions()
|
||||
def check_for_wireless(iwconfig, wireless_ip, set_status):
|
||||
""" Determine if wireless is active, and if yes, set the status. """
|
||||
if not wireless_ip:
|
||||
return False
|
||||
|
||||
network = wireless.GetCurrentNetwork(iwconfig)
|
||||
if not network:
|
||||
return False
|
||||
|
||||
network = str(network)
|
||||
if daemon.GetSignalDisplayType() == 0:
|
||||
strength = wireless.GetCurrentSignalStrength(iwconfig)
|
||||
else:
|
||||
strength = wireless.GetCurrentDBMStrength(iwconfig)
|
||||
|
||||
if strength is None:
|
||||
return False
|
||||
strength = str(strength)
|
||||
ip = str(wireless_ip)
|
||||
set_status(language['connected_to_wireless'].replace
|
||||
('$A', network).replace
|
||||
('$B', daemon.FormatSignalForPrinting(strength)).replace
|
||||
('$C', wireless_ip))
|
||||
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.
|
||||
# Mostly borrowed/stolen from wpa_cli, since I had no clue what all of those
|
||||
# DBUS interfaces do. ^_^
|
||||
# Whatever calls this must be exception-wrapped if it is run if the UI is up
|
||||
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 = []
|
||||
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
|
||||
is_active = wireless.GetWirelessIP('') == None and wired.GetWiredIP('') != None
|
||||
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
|
||||
|
||||
wlessL = []
|
||||
for network_id in range(0, wireless.GetNumberOfNetworks()):
|
||||
# ?: in python
|
||||
encryption = wireless.GetWirelessProperty(network_id, 'encryption_method') if wireless.GetWirelessProperty(network_id, 'encryption') else 'Unsecured'
|
||||
theString = ' %*s %25s %9s %17s %6s: %s' % ( gap,
|
||||
daemon.FormatSignalForPrinting(
|
||||
str(wireless.GetWirelessProperty(network_id, strenstr))),
|
||||
wireless.GetWirelessProperty(network_id, 'essid'),
|
||||
#wireless.GetWirelessProperty(network_id, 'encryption_method'),
|
||||
encryption,
|
||||
wireless.GetWirelessProperty(network_id, 'bssid'),
|
||||
wireless.GetWirelessProperty(network_id, 'mode'), # Master, Ad-Hoc
|
||||
wireless.GetWirelessProperty(network_id, 'channel')
|
||||
)
|
||||
is_active = wireless.GetCurrentSignalStrength("") != 0 and wireless.GetCurrentNetworkID(wireless.GetIwconfig())==network_id
|
||||
if is_active:
|
||||
theString = '>'+theString[1:]
|
||||
wlessL.append(urwid.AttrWrap(SelText(theString),'connected','connected focus'))
|
||||
else:
|
||||
wlessL.append(urwid.AttrWrap(SelText(theString),'body','focus'))
|
||||
return (wiredL,wlessL)
|
||||
|
||||
def about_dialog(body):
|
||||
# This looks A LOT better when it is actually displayed. I promise :-).
|
||||
# The ASCII Art "Wicd" was made from the "smslant" font on one of those
|
||||
# online ASCII big text generators.
|
||||
theText = [
|
||||
('green'," /// \\\\\\")," _ ___ __\n",
|
||||
('green'," /// \\\\\\")," | | /| / (_)______/ /\n",
|
||||
('green'," /// \\\\\\")," | |/ |/ / / __/ _ / \n",
|
||||
('green',"/|| // \\\\ ||\\")," |__/|__/_/\__/\_,_/ \n",
|
||||
('green',"||| ||"),"(|^|)",('green',"|| |||"),
|
||||
" ($VERSION) \n".replace("$VERSION",daemon.Hello()),
|
||||
|
||||
('green',"\\|| \\\\")," |+| ",('green',"// ||/ \n"),
|
||||
('green'," \\\\\\")," |+| ",('green',"///")," http://wicd.net \n",
|
||||
('green'," \\\\\\")," |+| ",('green',"///")," Brought to you by:\n",
|
||||
('green'," \\\\\\")," |+| ",('green',"///")," Adam Blackburn (wicd)\n",
|
||||
" ___|+|___ Dan O'Reilly (wicd)\n",
|
||||
" |---------| Andrew Psaltis (this ui)\n",
|
||||
"---------------------------------------------------"]
|
||||
about = Dialog(theText,['OK'],('body','body','focus'),55,14,body)
|
||||
|
||||
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:
|
||||
about.keypress(dim, k)
|
||||
if about.b_pressed == 'OK':
|
||||
return False
|
||||
|
||||
########################################
|
||||
##### APPLICATION INTERFACE CLASS
|
||||
########################################
|
||||
# The Whole Shebang
|
||||
class appGUI():
|
||||
"""The UI itself, all glory belongs to it!"""
|
||||
def __init__(self):
|
||||
self.size = ui.get_cols_rows()
|
||||
# Happy screen saying that you can't do anything because we're scanning
|
||||
# for networks. :-)
|
||||
# Will need a translation sooner or later
|
||||
self.screen_locker = urwid.Filler(urwid.Text(('important',"Scanning networks... stand by..."), align='center'))
|
||||
self.TITLE = 'Wicd Curses Interface'
|
||||
|
||||
#wrap1 = urwid.AttrWrap(txt, 'black')
|
||||
#fill = urwid.Filler(txt)
|
||||
|
||||
header = urwid.AttrWrap(urwid.Text(self.TITLE,align='right'), 'header')
|
||||
self.wiredH=urwid.Filler(urwid.Text("Wired Network(s)"))
|
||||
self.wlessH=urwid.Filler(urwid.Text("Wireless Network(s)"))
|
||||
|
||||
wiredL,wlessL = gen_network_list()
|
||||
self.wiredCB = urwid.Filler(ComboBox(list=wiredL,use_enter=False))
|
||||
self.wlessLB = urwid.ListBox(wlessL)
|
||||
# Stuff I used to simulate large lists
|
||||
#spam = SelText('spam')
|
||||
#spamL = [ urwid.AttrWrap( w, None, 'focus' ) for w in [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,spam,spam,spam,spam,spam,spam,spam,
|
||||
# spam,spam,spam,spam] ]
|
||||
#self.spamLB = urwid.ListBox(spamL)
|
||||
|
||||
# Choose whether to show the wired part of the interface.
|
||||
if daemon.GetAlwaysShowWiredInterface():
|
||||
self.thePile = urwid.Pile([('fixed',1,self.wiredH),
|
||||
('fixed',1,self.wiredCB),
|
||||
('fixed',1,self.wlessH),
|
||||
self.wlessLB] )
|
||||
else:
|
||||
self.thePile = urwid.Pile([('fixed',1,self.wlessH),self.wlessLB] )
|
||||
self.footer1 = urwid.AttrWrap(urwid.Text("Something important will eventually go here."),'body')
|
||||
self.footer2 = urwid.AttrWrap(urwid.Text("If you are seeing this, then something has gone wrong!"),'important')
|
||||
self.footerList = urwid.ListBox([self.footer1,self.footer2])
|
||||
# Pop takes a number!
|
||||
#walker.pop(1)
|
||||
nothingness = urwid.Filler(urwid.Text('Hello, world!'))
|
||||
self.frame = urwid.Frame(self.thePile,
|
||||
header=header,
|
||||
footer=urwid.BoxAdapter(self.footerList,2))
|
||||
self.wiredCB.get_body().build_combobox(self.frame,ui,3)
|
||||
|
||||
self.frame.set_body(self.thePile)
|
||||
# Booleans gallore!
|
||||
self.prev_state = False
|
||||
self.connecting = False
|
||||
self.screen_locked = False
|
||||
self.connecting = False
|
||||
self.always_show_wired = daemon.GetAlwaysShowWiredInterface()
|
||||
self.update_status()
|
||||
|
||||
#self.dialog = PrefOverlay(self.frame,self.size)
|
||||
|
||||
# Does what it says it does
|
||||
def lock_screen(self):
|
||||
self.frame.set_body(self.screen_locker)
|
||||
self.screen_locked = True
|
||||
|
||||
def unlock_screen(self):
|
||||
self.update_netlist(force_check=True)
|
||||
self.frame.set_body(self.thePile)
|
||||
self.screen_locked = False
|
||||
# I'm hoping that this will get rid of Adam's problem with the ListBox not
|
||||
# redisplaying itself immediately upon completion.
|
||||
self.update_ui()
|
||||
|
||||
# Be clunky until I get to a later stage of development.
|
||||
# Update the list of networks. Usually called by DBus.
|
||||
# TODO: Preserve current focus when updating the list.
|
||||
@wrap_exceptions()
|
||||
def update_netlist(self,state=None, x=None, force_check=False):
|
||||
""" Updates the overall network list."""
|
||||
if not state:
|
||||
state, x = daemon.GetConnectionStatus()
|
||||
if self.prev_state != state or force_check:
|
||||
wiredL,wlessL = gen_network_list()
|
||||
#self.wiredCB = urwid.Filler(ComboBox(wiredL,self.frame,ui,3,
|
||||
# use_enter=False))
|
||||
self.wiredCB.get_body().set_list(wiredL)
|
||||
self.wiredCB.get_body().build_combobox(self.frame,ui,3)
|
||||
self.wlessLB.body = urwid.SimpleListWalker(wlessL)
|
||||
# If the "Always Show Wired" part of the interface changes, change
|
||||
# along with it.
|
||||
if daemon.GetAlwaysShowWiredInterface() != self.always_show_wired:
|
||||
if daemon.GetAlwaysShowWiredInterface():
|
||||
self.thePile = urwid.Pile([('fixed',1,self.wiredH),
|
||||
('fixed',1,self.wiredCB),
|
||||
('fixed',1,self.wlessH),
|
||||
self.wlessLB] )
|
||||
else:
|
||||
self.thePile = urwid.Pile([('fixed',1,self.wlessH),self.wlessLB] )
|
||||
self.frame.body = self.thePile
|
||||
self.always_show_wired = not self.always_show_wired
|
||||
self.prev_state = state
|
||||
|
||||
# Update the footer/status bar
|
||||
@wrap_exceptions()
|
||||
def update_status(self):
|
||||
wired_connecting = wired.CheckIfWiredConnecting()
|
||||
wireless_connecting = wireless.CheckIfWirelessConnecting()
|
||||
self.connecting = wired_connecting or wireless_connecting
|
||||
|
||||
fast = not daemon.NeedsExternalCalls()
|
||||
if self.connecting:
|
||||
#self.lock_screen()
|
||||
#if self.statusID:
|
||||
# gobject.idle_add(self.status_bar.remove, 1, self.statusID)
|
||||
if wireless_connecting:
|
||||
if not fast:
|
||||
iwconfig = wireless.GetIwconfig()
|
||||
else:
|
||||
iwconfig = ''
|
||||
# set_status is rigged to return false when it is not
|
||||
# connecting to anything, so this should work.
|
||||
gobject.idle_add(self.set_status, wireless.GetCurrentNetwork(iwconfig) +
|
||||
': ' +
|
||||
language[str(wireless.CheckWirelessConnectingMessage())],
|
||||
True )
|
||||
if wired_connecting:
|
||||
gobject.idle_add(self.set_status, language['wired_network'] +
|
||||
': ' +
|
||||
language[str(wired.CheckWiredConnectingMessage())],
|
||||
True)
|
||||
return True
|
||||
else:
|
||||
if check_for_wired(wired.GetWiredIP(''),self.set_status):
|
||||
return True
|
||||
if not fast:
|
||||
iwconfig = wireless.GetIwconfig()
|
||||
else:
|
||||
iwconfig = ''
|
||||
if check_for_wireless(iwconfig, wireless.GetWirelessIP(""),
|
||||
self.set_status):
|
||||
return True
|
||||
else:
|
||||
self.set_status(language['not_connected'])
|
||||
return True
|
||||
|
||||
|
||||
# Cheap little indicator stating that we are actually connecting
|
||||
twirl = ['|','/','-','\\']
|
||||
def set_status(self,text,from_idle=False):
|
||||
# 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
|
||||
# mainloop
|
||||
# If we are being called as the result of trying to connect to
|
||||
# something, and we aren't connecting to something, return False
|
||||
# immediately.
|
||||
if from_idle and not self.connecting:
|
||||
return False
|
||||
toAppend = ''
|
||||
# If we are connecting and being called from the idle function, spin
|
||||
# the wheel.
|
||||
if from_idle and self.connecting:
|
||||
# This is probably the wrong way to do this, but ir works for now.
|
||||
toAppend=self.twirl[self.incr % 4]
|
||||
self.footer2 = urwid.AttrWrap(urwid.Text(text+' '+toAppend),'important')
|
||||
self.frame.set_footer(urwid.BoxAdapter(
|
||||
urwid.ListBox([self.footer1,self.footer2]),2))
|
||||
return True
|
||||
|
||||
# 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
|
||||
# the long run, so I might as well put something there.
|
||||
incr = 0
|
||||
def idle_incr(self):
|
||||
theText = ""
|
||||
if self.connecting:
|
||||
theText = "-- Connecting -- Press ESC to cancel"
|
||||
self.footer1 = urwid.Text(str(self.incr) + ' '+theText)
|
||||
self.incr+=1
|
||||
return True
|
||||
|
||||
# Yeah, I'm copying code. Anything wrong with that?
|
||||
#@wrap_exceptions()
|
||||
def dbus_scan_finished(self):
|
||||
# I'm pretty sure that I'll need this later.
|
||||
#if not self.connecting:
|
||||
#self.refresh_networks(fresh=False)
|
||||
self.unlock_screen()
|
||||
# I'm hoping that this will resolve Adam's problem with the screen lock
|
||||
# remaining onscreen until a key is pressed. It goes away perfectly well
|
||||
# here.
|
||||
self.update_ui()
|
||||
|
||||
# Same, same, same, same, same, same
|
||||
#@wrap_exceptions()
|
||||
def dbus_scan_started(self):
|
||||
self.lock_screen()
|
||||
|
||||
# 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 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()
|
||||
# Should make a keyhandler method, but this will do until I get around to
|
||||
# that stage
|
||||
if "f8" in keys or 'Q' in keys:
|
||||
loop.quit()
|
||||
return False
|
||||
if "f5" in keys:
|
||||
wireless.Scan()
|
||||
if "enter" in keys:
|
||||
# Should be a function of the labels, I think.
|
||||
self.call_connect()
|
||||
if "D" in keys:
|
||||
# Disconnect from all networks.
|
||||
daemon.Disconnect()
|
||||
self.update_netlist()
|
||||
if "esc" in keys:
|
||||
# Force disconnect here if connection in progress
|
||||
if self.connecting:
|
||||
daemon.CancelConnect()
|
||||
# Prevents automatic reconnecting if that option is enabled
|
||||
daemon.SetForcedDisconnect(True)
|
||||
if "P" in keys:
|
||||
dialog = PrefsDialog(self.frame,(0,1),ui,
|
||||
dbusmanager.get_dbus_ifaces())
|
||||
# There is some lag in using the buttons. Not my fault.
|
||||
if dialog.run(ui,self.size,self.frame):
|
||||
dialog.save_results()
|
||||
self.update_ui()
|
||||
if "A" in keys:
|
||||
about_dialog(self.frame)
|
||||
for k in keys:
|
||||
if k == "window resize":
|
||||
self.size = ui.get_cols_rows()
|
||||
continue
|
||||
self.frame.keypress( self.size, k )
|
||||
|
||||
if " " in keys:
|
||||
#self.set_status('space pressed on wiredCB!')
|
||||
wid,pos = self.wiredCB.get_body().get_selected()
|
||||
text,attr = wid.get_text()
|
||||
wired.ReadWiredNetworkProfile(text)
|
||||
# Make sure our internal reference to the combobox matches the
|
||||
# one found in the pile.
|
||||
self.wiredCB = self.thePile.get_focus()
|
||||
|
||||
return True
|
||||
|
||||
# Bring back memories, anyone?
|
||||
def call_connect(self):
|
||||
wid = self.thePile.get_focus()
|
||||
if wid is self.wiredCB:
|
||||
#wid2,pos = self.wiredCB.get_focus()
|
||||
# Apparently, connect() doesn't care about the networkid
|
||||
self.connect(self,'wired',0)
|
||||
#return "Wired network %i" % pos
|
||||
elif wid is self.wlessLB:
|
||||
#self.footer1 = urwid.Text("Wireless!")
|
||||
wid2,pos = self.wlessLB.get_focus()
|
||||
self.connect(self,'wireless',pos)
|
||||
else:
|
||||
self.set_status("call_connect() failed! This is definitely a bug!")
|
||||
#return "Failure!"
|
||||
|
||||
def connect(self, event, nettype, networkid):
|
||||
""" Initiates the connection process in the daemon. """
|
||||
if nettype == "wireless":
|
||||
# I need to do something that is similar to this in this UI, but
|
||||
# I don't have an "advanced settings" dialog yet.
|
||||
#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
|
||||
########################################
|
||||
|
||||
def main():
|
||||
global ui
|
||||
|
||||
# We are _not_ python.
|
||||
misc.RenameProcess('wicd-curses')
|
||||
|
||||
ui = urwid.curses_display.Screen()
|
||||
# Color scheme.
|
||||
# Other potential color schemes can be found at:
|
||||
# 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.
|
||||
# NB: To find current terminal background use variable COLORFGBG
|
||||
ui.register_palette([
|
||||
('body','light gray','default'),
|
||||
('focus','dark magenta','light gray'),
|
||||
('header','light blue','default'),
|
||||
('important','light red','default'),
|
||||
('connected','dark green','default'),
|
||||
('connected focus','default','dark green'),
|
||||
('editcp', 'default', 'default', 'standout'),
|
||||
('editbx', 'light gray', 'dark blue'),
|
||||
('editfc', 'white','dark blue', 'bold'),
|
||||
('tab active','dark green','light gray'),
|
||||
# Simple colors around text
|
||||
('green','dark green','default'),
|
||||
('blue','dark blue','default'),
|
||||
('red','dark red','default')])
|
||||
# This is a wrapper around a function that calls another a function that is a
|
||||
# wrapper around a infinite loop. Fun.
|
||||
ui.run_wrapper(run)
|
||||
|
||||
def run():
|
||||
global loop,redraw_tag
|
||||
|
||||
redraw_tag = -1
|
||||
app = appGUI()
|
||||
|
||||
# Connect signals and whatnot to UI screen control functions
|
||||
bus.add_signal_receiver(app.dbus_scan_finished, 'SendEndScanSignal',
|
||||
'org.wicd.daemon.wireless')
|
||||
bus.add_signal_receiver(app.dbus_scan_started, 'SendStartScanSignal',
|
||||
'org.wicd.daemon.wireless')
|
||||
# I've left this commented out many times.
|
||||
bus.add_signal_receiver(app.update_netlist, 'StatusChanged',
|
||||
'org.wicd.daemon')
|
||||
loop = gobject.MainLoop()
|
||||
# Update what the interface looks like as an idle function
|
||||
redraw_tag = gobject.idle_add(app.update_ui)
|
||||
# Update the connection status on the bottom every 1.5 s.
|
||||
gobject.timeout_add(1500,app.update_status)
|
||||
gobject.idle_add(app.idle_incr)
|
||||
# DEFUNCT: Terminate the loop if the UI is terminated.
|
||||
#gobject.idle_add(app.stop_loop)
|
||||
loop.run()
|
||||
|
||||
# Mostly borrowed from gui.py
|
||||
def setup_dbus(force=True):
|
||||
global bus, daemon, wireless, wired, DBUS_AVAIL
|
||||
try:
|
||||
dbusmanager.connect_to_dbus()
|
||||
except DBusException:
|
||||
# I may need to be a little more verbose here.
|
||||
# Suggestions as to what should go here
|
||||
print "Can't connect to the daemon. Are you sure it is running?"
|
||||
print "Please check the wicd log for error messages."
|
||||
raise
|
||||
# return False # <- Will need soon.
|
||||
bus = dbusmanager.get_bus()
|
||||
dbus_ifaces = dbusmanager.get_dbus_ifaces()
|
||||
daemon = dbus_ifaces['daemon']
|
||||
wireless = dbus_ifaces['wireless']
|
||||
wired = dbus_ifaces['wired']
|
||||
DBUS_AVAIL = True
|
||||
|
||||
return True
|
||||
|
||||
setup_dbus()
|
||||
|
||||
########################################
|
||||
##### MAIN ENTRY POINT
|
||||
########################################
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
# Make sure that the terminal does not try to overwrite the last line of
|
||||
# the program, so that everything looks pretty.
|
||||
print ""
|
||||
Reference in New Issue
Block a user