mirror of
https://github.com/gryf/wicd.git
synced 2025-12-24 07:02:29 +01:00
Merged NaCl's curses branch
This commit is contained in:
56
curses/README
Normal file
56
curses/README
Normal file
@@ -0,0 +1,56 @@
|
||||
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 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. 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 or q: quit
|
||||
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
|
||||
A : Display "About" dialog
|
||||
I : Raise the "Scan for hidden networks" dialog
|
||||
H or h or ? : Raise help dialog
|
||||
S : Provide instructions for configuring scripts
|
||||
delete : Delete selected wired network profile (from the wired ComboBox)
|
||||
F2 : Rename selected wired network profile (from the wired ComboBox)
|
||||
O : Raise ad-hoc network dialog
|
||||
|
||||
IN DIALOGS (Meta usually is "Alt"):
|
||||
ESC or Q: Quit dialog without saving information (if present)
|
||||
Meta+Left/Right: Change tabs Left/Right (if tabs present)
|
||||
Meta+Enter : Quit dialog and save information
|
||||
|
||||
FAQ (WIP):
|
||||
|
||||
What is wicd-curses?
|
||||
See above. :-)
|
||||
|
||||
Why didn't you call it wicd-urwid? There is a hachoir-urwid package out there.
|
||||
I first called this "urwicd". However, due to the relative obscurity of
|
||||
the urwid package, and the fact that many more people know what "curses"
|
||||
is, I named it wicd-curses. After all, it _does_ use curses (by default,
|
||||
anyway).
|
||||
|
||||
Why don't you support lower-case keybindings for most of the commands?
|
||||
I was trying to prevent mass chaos from happening because of mashing keys.
|
||||
Of course, if you unwittingly have caps-lock on, that's going to cause said
|
||||
chaos, too, so you might want to check that (or ask me about changing the
|
||||
keymaps to ctrl/meta+KEY)
|
||||
|
||||
~NaCl
|
||||
6
curses/TODO
Normal file
6
curses/TODO
Normal file
@@ -0,0 +1,6 @@
|
||||
Things to do (in no particular order):
|
||||
|
||||
* Implement a keyhandler function for the overall frame
|
||||
* Make keystrokes customizable
|
||||
* Make color schemes customizable
|
||||
* Perform a mass code cleanup
|
||||
139
curses/configscript_curses.py
Executable file
139
curses/configscript_curses.py
Executable file
@@ -0,0 +1,139 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""configscript_curses.py
|
||||
Kind of like configscript.py, except written using urwid.
|
||||
|
||||
Also recycles a lot of configscript.py, too. :-)
|
||||
"""
|
||||
|
||||
# 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.
|
||||
|
||||
from wicd import misc
|
||||
import configscript
|
||||
from configscript import write_scripts,get_script_info,get_val,none_to_blank,blank_to_none
|
||||
|
||||
import urwid
|
||||
import urwid.curses_display
|
||||
import sys
|
||||
import os
|
||||
|
||||
_ = misc.get_gettext()
|
||||
|
||||
language = {}
|
||||
language['configure_scripts'] = _("Configure Scripts")
|
||||
language['before_script'] = _("Pre-connection Script")
|
||||
language['after_script'] = _("Post-connection Script")
|
||||
language['disconnect_script'] = _("Disconnection Script")
|
||||
|
||||
def main(argv):
|
||||
global ui,frame
|
||||
if len(argv) < 2:
|
||||
print 'Network id to configure is missing, aborting.'
|
||||
sys.exit(1)
|
||||
|
||||
ui = urwid.curses_display.Screen()
|
||||
ui.register_palette( [
|
||||
('body','default','default'),
|
||||
('focus','dark magenta','light gray'),
|
||||
('editcp', 'default', 'default', 'standout'),
|
||||
('editbx', 'light gray', 'dark blue'),
|
||||
('editfc', 'white','dark blue', 'bold')] )
|
||||
|
||||
network = argv[1]
|
||||
network_type = argv[2]
|
||||
|
||||
script_info = get_script_info(network, network_type)
|
||||
|
||||
blank = urwid.Text('')
|
||||
pre_entry_t = ('body',language['before_script']+': ')
|
||||
post_entry_t = ('body',language['after_script']+': ')
|
||||
disconnect_entry_t = ('body',language['disconnect_script']+': ')
|
||||
|
||||
global pre_entry,post_entry,disconnect_entry
|
||||
pre_entry = urwid.AttrWrap(urwid.Edit(pre_entry_t,
|
||||
none_to_blank(script_info.get('pre_entry'))),'editbx','editfc' )
|
||||
post_entry = urwid.AttrWrap(urwid.Edit(post_entry_t,
|
||||
none_to_blank(script_info.get('post_entry'))),'editbx','editfc' )
|
||||
|
||||
disconnect_entry = urwid.AttrWrap(urwid.Edit(disconnect_entry_t,
|
||||
none_to_blank(script_info.get('disconnect_entry'))),'editbx','editfc' )
|
||||
|
||||
# The buttons
|
||||
ok_button = urwid.AttrWrap(urwid.Button('OK',ok_callback),'body','focus')
|
||||
cancel_button = urwid.AttrWrap(urwid.Button('Cancel',cancel_callback),'body','focus')
|
||||
|
||||
button_cols = urwid.Columns([ok_button,cancel_button],dividechars=1)
|
||||
|
||||
lbox = urwid.Pile([('fixed',2,urwid.Filler(pre_entry)),
|
||||
#('fixed',urwid.Filler(blank),1),
|
||||
('fixed',2,urwid.Filler(post_entry)),
|
||||
('fixed',2,urwid.Filler(disconnect_entry)),
|
||||
#blank,blank,blank,blank,blank,
|
||||
urwid.Filler(button_cols,'bottom')
|
||||
])
|
||||
frame = urwid.Frame(lbox)
|
||||
result = ui.run_wrapper(run)
|
||||
|
||||
if result == True:
|
||||
script_info["pre_entry"] = blank_to_none(pre_entry.get_edit_text())
|
||||
script_info["post_entry"] = blank_to_none(post_entry.get_edit_text())
|
||||
script_info["disconnect_entry"] = blank_to_none(disconnect_entry.get_edit_text())
|
||||
write_scripts(network, network_type, script_info)
|
||||
|
||||
OK_PRESSED = False
|
||||
CANCEL_PRESSED = False
|
||||
def ok_callback(button_object,user_data=None):
|
||||
global OK_PRESSED
|
||||
OK_PRESSED = True
|
||||
def cancel_callback(button_object,user_data=None):
|
||||
global CANCEL_PRESSED
|
||||
CANCEL_PRESSED = True
|
||||
def run():
|
||||
dim = ui.get_cols_rows()
|
||||
ui.set_mouse_tracking()
|
||||
|
||||
keys = True
|
||||
while True:
|
||||
if keys:
|
||||
ui.draw_screen(dim, frame.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:
|
||||
if urwid.is_mouse_event(k):
|
||||
event, button, col, row = k
|
||||
frame.mouse_event( dim,
|
||||
event, button, col, row,
|
||||
focus=True)
|
||||
else:
|
||||
frame.keypress(dim, k)
|
||||
# Check if buttons are pressed.
|
||||
if CANCEL_PRESSED:
|
||||
return False
|
||||
if OK_PRESSED or 'meta enter' in keys:
|
||||
return True
|
||||
|
||||
if __name__ == '__main__':
|
||||
if os.getuid() != 0:
|
||||
print "Root privileges are required to configure scripts. Exiting."
|
||||
sys.exit(0)
|
||||
main(sys.argv)
|
||||
516
curses/curses_misc.py
Normal file
516
curses/curses_misc.py
Normal file
@@ -0,0 +1,516 @@
|
||||
#!/usr/bin/env python
|
||||
# -* coding: utf-8 -*-
|
||||
|
||||
""" curses_misc.py: Module for various widgets that are used throughout
|
||||
wicd-curses.
|
||||
"""
|
||||
|
||||
# Copyright (C) 2008-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
|
||||
|
||||
# Uses code that is towards the bottom
|
||||
def error(ui,parent,message):
|
||||
"""Shows an error dialog (or something that resembles one)"""
|
||||
# /\
|
||||
# /!!\
|
||||
# /____\
|
||||
dialog = TextDialog(message,6,40,('important',"ERROR"))
|
||||
return dialog.run(ui,parent)
|
||||
|
||||
# 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
|
||||
|
||||
# This class is annoying. ^_^
|
||||
class DynWrap(urwid.AttrWrap):
|
||||
"""
|
||||
Makes an object have mutable selectivity. Attributes will change like
|
||||
those in an AttrWrap
|
||||
|
||||
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):
|
||||
if state:
|
||||
self.set_attr(self._attrs[0])
|
||||
else:
|
||||
self.set_attr(self._attrs[1])
|
||||
self._sensitive = state
|
||||
property(get_sensitive,set_sensitive)
|
||||
|
||||
def get_attrs(self):
|
||||
return self._attrs
|
||||
def set_attrs(self,attrs):
|
||||
self._attrs = attrs
|
||||
property(get_attrs,set_attrs)
|
||||
|
||||
def selectable(self):
|
||||
return self._sensitive
|
||||
|
||||
# Just an Edit Dynwrapped to the most common specifications
|
||||
class DynEdit(DynWrap):
|
||||
def __init__(self,caption='',edit_text='',sensitive=True,attrs=('editbx','editnfc'),focus_attr='editfc'):
|
||||
caption = ('editcp',caption + ': ')
|
||||
edit = urwid.Edit(caption,edit_text)
|
||||
self.__super.__init__(edit,sensitive,attrs,focus_attr)
|
||||
|
||||
# Just an IntEdit Dynwrapped to the most common specifications
|
||||
class DynIntEdit(DynWrap):
|
||||
def __init__(self,caption='',edit_text='',sensitive=True,attrs=('editbx','editnfc'),focus_attr='editfc'):
|
||||
caption = ('editcp',caption + ':')
|
||||
edit = urwid.IntEdit(caption,edit_text)
|
||||
self.__super.__init__(edit,sensitive,attrs,focus_attr)
|
||||
|
||||
class MaskingEditException(Exception):
|
||||
pass
|
||||
|
||||
# Password-style edit
|
||||
class MaskingEdit(urwid.Edit):
|
||||
"""
|
||||
mask_mode = one of:
|
||||
"always" : everything is a '*' all of the time
|
||||
"on_focus" : everything is a '*' only when not in focus
|
||||
"off" : everything is always unmasked
|
||||
mask_char = the single character that masks all other characters in the field
|
||||
"""
|
||||
def __init__(self, caption = "", edit_text = "", multiline = False,
|
||||
align = 'left', wrap = 'space', allow_tab = False,
|
||||
edit_pos = None, layout=None, mask_mode="masked",mask_char='*'):
|
||||
self.mask_mode = mask_mode
|
||||
if len(mask_char) > 1:
|
||||
raise MaskingEditException('Masks of more than one character are not supported!')
|
||||
self.mask_char = mask_char
|
||||
self.__super.__init__(caption,edit_text,multiline,align,wrap,allow_tab,edit_pos,layout)
|
||||
|
||||
def get_mask_mode(self):
|
||||
return self.mask_mode
|
||||
def set_mask_mode(self,mode):
|
||||
self.mask_mode = mode
|
||||
|
||||
def get_masked_text(self):
|
||||
return self.mask_char*len(self.get_edit_text())
|
||||
|
||||
def render(self,(maxcol,), focus=False):
|
||||
"""
|
||||
Render edit widget and return canvas. Include cursor when in
|
||||
focus.
|
||||
"""
|
||||
# If we aren't masking anything ATM, then act like an Edit. No problems.
|
||||
if self.mask_mode == "off" or (self.mask_mode == 'on_focus' and focus == True):
|
||||
canv = self.__super.render((maxcol,),focus)
|
||||
# The cache messes this thing up, because I am totally changing what is
|
||||
# displayed.
|
||||
self._invalidate()
|
||||
return canv
|
||||
# Else, we have a slight mess to deal with...
|
||||
|
||||
self._shift_view_to_cursor = not not focus # force bool
|
||||
|
||||
text, attr = self.get_text()
|
||||
text = text[:len(self.caption)]+self.get_masked_text()
|
||||
trans = self.get_line_translation( maxcol, (text,attr) )
|
||||
canv = urwid.canvas.apply_text_layout(text, attr, trans, maxcol)
|
||||
|
||||
if focus:
|
||||
canv = urwid.CompositeCanvas(canv)
|
||||
canv.cursor = self.get_cursor_coords((maxcol,))
|
||||
|
||||
return canv
|
||||
|
||||
# Tabbed interface, mostly for use in the Preferences Dialog
|
||||
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)
|
||||
if key == "meta left" or key == "meta right":
|
||||
self._w.get_body().set_focus(0)
|
||||
self.keypress(size,key[5:])
|
||||
self._w.get_body().set_focus(1)
|
||||
else:
|
||||
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
|
||||
# This is a hack. It isn't without quirks, but it more or less works.
|
||||
# We need to wait for changes in urwid's Canvas controls before we can actually
|
||||
# make a real ComboBox.
|
||||
class ComboBox(urwid.WidgetWrap):
|
||||
"""A ComboBox of text objects"""
|
||||
class ComboSpace(urwid.WidgetWrap):
|
||||
"""The actual menu-like space that comes down from the ComboBox"""
|
||||
def __init__(self,list,body,ui,show_first,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)
|
||||
self._listbox.set_focus(show_first)
|
||||
|
||||
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=[],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
|
||||
list : stuff to include in the combobox
|
||||
body : parent widget
|
||||
ui : the screen
|
||||
row : where this object is to be found onscreen
|
||||
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
|
||||
#w,sensitive=True,attrs=('editbx','editnfc'),focus_attr='editfc')
|
||||
self.cbox = DynWrap(SelText(' vvv'),attrs=attrs,focus_attr=focus_attr)
|
||||
# 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
|
||||
# The Focus
|
||||
self.focus = focus
|
||||
|
||||
# The callback and friends
|
||||
self.callback = callback
|
||||
self.user_args = user_args
|
||||
|
||||
# Widget references to simplify some things
|
||||
self.parent = None
|
||||
self.ui = None
|
||||
self.row = None
|
||||
def set_list(self,list):
|
||||
self.list = list
|
||||
|
||||
def set_focus(self,index):
|
||||
self.focus = index
|
||||
self.cbox.set_w(SelText(self.list[index]+' vvv'))
|
||||
if self.overlay:
|
||||
self.overlay._listbox.set_focus(index)
|
||||
|
||||
def rebuild_combobox(self):
|
||||
self.build_combobox(self.parent,self.ui,self.row)
|
||||
def build_combobox(self,parent,ui,row):
|
||||
str,trash = self.label.get_text()
|
||||
|
||||
|
||||
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,parent,ui,self.focus,
|
||||
pos=(len(str)+1,row))
|
||||
else:
|
||||
w = urwid.Columns([self.cbox])
|
||||
self.overlay = self.ComboSpace(self.list,parent,ui,self.focus,
|
||||
pos=(0,row))
|
||||
|
||||
self.set_w(w)
|
||||
self.parent = parent
|
||||
self.ui = ui
|
||||
self.row = row
|
||||
|
||||
# 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.parent)
|
||||
if retval != None:
|
||||
self.set_focus(self.list.index(retval))
|
||||
#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)
|
||||
|
||||
def selectable(self):
|
||||
return self.cbox.selectable()
|
||||
|
||||
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()
|
||||
def set_sensitive(self,state):
|
||||
self.cbox.set_sensitive(state)
|
||||
|
||||
# This is a h4x3d copy of some of the code in Ian Ward's dialog.py example.
|
||||
class DialogExit(Exception):
|
||||
pass
|
||||
|
||||
class Dialog2(urwid.WidgetWrap):
|
||||
def __init__(self, text, height,width, body=None ):
|
||||
self.width = int(width)
|
||||
if width <= 0:
|
||||
self.width = ('relative', 80)
|
||||
self.height = int(height)
|
||||
if height <= 0:
|
||||
self.height = ('relative', 80)
|
||||
|
||||
self.body = body
|
||||
if body is None:
|
||||
# fill space with nothing
|
||||
body = urwid.Filler(urwid.Divider(),'top')
|
||||
|
||||
self.frame = urwid.Frame( body, focus_part='footer')
|
||||
if text is not None:
|
||||
self.frame.header = urwid.Pile( [urwid.Text(text,align='right'),
|
||||
urwid.Divider()] )
|
||||
w = self.frame
|
||||
self.view = w
|
||||
|
||||
# pad area around listbox
|
||||
#w = urwid.Padding(w, ('fixed left',2), ('fixed right',2))
|
||||
#w = urwid.Filler(w, ('fixed top',1), ('fixed bottom',1))
|
||||
#w = urwid.AttrWrap(w, 'body')
|
||||
# buttons: tuple of name,exitcode
|
||||
def add_buttons(self, buttons):
|
||||
l = []
|
||||
for name, exitcode in buttons:
|
||||
b = urwid.Button( name, self.button_press )
|
||||
b.exitcode = exitcode
|
||||
b = urwid.AttrWrap( b, 'body','focus' )
|
||||
l.append( b )
|
||||
self.buttons = urwid.GridFlow(l, 10, 3, 1, 'center')
|
||||
self.frame.footer = urwid.Pile( [ urwid.Divider(),
|
||||
self.buttons ], focus_item = 1)
|
||||
|
||||
def button_press(self, button):
|
||||
raise DialogExit(button.exitcode)
|
||||
|
||||
def run(self,ui,parent):
|
||||
ui.set_mouse_tracking()
|
||||
size = ui.get_cols_rows()
|
||||
overlay = urwid.Overlay(urwid.LineBox(self.view), parent, 'center', self.width,
|
||||
'middle', self.height)
|
||||
try:
|
||||
while True:
|
||||
canvas = overlay.render( size, focus=True )
|
||||
ui.draw_screen( size, canvas )
|
||||
keys = None
|
||||
while not keys:
|
||||
keys = ui.get_input()
|
||||
for k in keys:
|
||||
if urwid.is_mouse_event(k):
|
||||
event, button, col, row = k
|
||||
overlay.mouse_event( size,
|
||||
event, button, col, row,
|
||||
focus=True)
|
||||
else:
|
||||
if k == 'window resize':
|
||||
size = ui.get_cols_rows()
|
||||
k = self.view.keypress( size, k )
|
||||
if k == 'esc':
|
||||
raise DialogExit(-1)
|
||||
if k:
|
||||
self.unhandled_key( size, k)
|
||||
except DialogExit, e:
|
||||
return self.on_exit( e.args[0] )
|
||||
|
||||
def on_exit(self, exitcode):
|
||||
return exitcode, ""
|
||||
|
||||
def unhandled_key(self, size, key):
|
||||
pass
|
||||
|
||||
# Simple dialog with text in it and "OK"
|
||||
class TextDialog(Dialog2):
|
||||
def __init__(self, text, height, width, header=None,align='left'):
|
||||
l = [urwid.Text(text)]
|
||||
#for line in text:
|
||||
# l.append( urwid.Text( line,align=align))
|
||||
body = urwid.ListBox(l)
|
||||
body = urwid.AttrWrap(body, 'body')
|
||||
|
||||
Dialog2.__init__(self, header, height+2, width+2, body)
|
||||
self.add_buttons([('OK',1)])
|
||||
|
||||
|
||||
def unhandled_key(self, size, k):
|
||||
if k in ('up','page up','down','page down'):
|
||||
self.frame.set_focus('body')
|
||||
self.view.keypress( size, k )
|
||||
self.frame.set_focus('footer')
|
||||
|
||||
class InputDialog(Dialog2):
|
||||
def __init__(self, text, height, width,ok_name='OK',edit_text=''):
|
||||
self.edit = urwid.Edit(wrap='clip',edit_text=edit_text)
|
||||
body = urwid.ListBox([self.edit])
|
||||
body = urwid.AttrWrap(body, 'editbx','editfc')
|
||||
|
||||
Dialog2.__init__(self, text, height, width, body)
|
||||
|
||||
self.frame.set_focus('body')
|
||||
self.add_buttons([(ok_name,0),('Cancel',-1)])
|
||||
|
||||
def unhandled_key(self, size, k):
|
||||
if k in ('up','page up'):
|
||||
self.frame.set_focus('body')
|
||||
if k in ('down','page down'):
|
||||
self.frame.set_focus('footer')
|
||||
if k == 'enter':
|
||||
# pass enter to the "ok" button
|
||||
self.frame.set_focus('footer')
|
||||
self.view.keypress( size, k )
|
||||
|
||||
def on_exit(self, exitcode):
|
||||
return exitcode, self.edit.get_edit_text()
|
||||
|
||||
# Pile that has an edit and a label saying that the file at the path specified
|
||||
# does not exist
|
||||
#class FileGuessEdit(urwid.WidgetWrap):
|
||||
# def __init__(self,caption='',
|
||||
418
curses/netentry_curses.py
Normal file
418
curses/netentry_curses.py
Normal file
@@ -0,0 +1,418 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
netentry_curses -- everyone's favorite networks settings dialogs... in text
|
||||
form!
|
||||
"""
|
||||
|
||||
# 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 TextDialog,DynWrap,MaskingEdit,ComboBox,error
|
||||
import wicd.misc as misc
|
||||
from wicd.misc import noneToString, stringToNone, noneToBlankString, to_bool
|
||||
|
||||
|
||||
|
||||
language = misc.get_language_list_gui()
|
||||
|
||||
daemon = None
|
||||
wired = None
|
||||
wireless = None
|
||||
# Call this first!
|
||||
def dbus_init(dbus_ifaces):
|
||||
global daemon,wired,wireless
|
||||
daemon = dbus_ifaces['daemon']
|
||||
wired = dbus_ifaces['wired']
|
||||
wireless = dbus_ifaces['wireless']
|
||||
|
||||
# Both the wired and the wireless 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']+':')
|
||||
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.static_dns_cb = urwid.CheckBox(use_static_dns_t,
|
||||
on_state_change=self.dns_toggle)
|
||||
self.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.static_dns_cb,
|
||||
self.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('')
|
||||
|
||||
# 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,
|
||||
self.netmask_edit,
|
||||
self.gateway_edit,
|
||||
_blank,
|
||||
checkb_cols,
|
||||
self.dns_dom_edit,self.search_dom_edit,
|
||||
self.dns1,self.dns2,self.dns3
|
||||
])
|
||||
|
||||
|
||||
|
||||
self._listbox = urwid.ListBox(walker)
|
||||
#self._frame = urwid.Frame(self._listbox)
|
||||
self._frame = urwid.Frame(self._listbox)
|
||||
self.__super.__init__(self._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)
|
||||
|
||||
def dns_toggle(self,checkb,new_state,user_data=None):
|
||||
if checkb == self.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.global_dns_cb.set_state(False,do_callback=False)
|
||||
self.global_dns_cb.set_sensitive(new_state)
|
||||
# use_global_dns_cb is DynWrapped
|
||||
if checkb == self.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)
|
||||
|
||||
# Code totally yanked from netentry.py
|
||||
def save_settings(self):
|
||||
""" Save settings common to wired and wireless settings dialogs. """
|
||||
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()))
|
||||
else:
|
||||
self.set_net_prop("ip", '')
|
||||
self.set_net_prop("netmask", '')
|
||||
self.set_net_prop("gateway", '')
|
||||
|
||||
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.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:
|
||||
self.set_net_prop('use_static_dns', False)
|
||||
self.set_net_prop('use_global_dns', False)
|
||||
self.set_net_prop('dns_domain', '')
|
||||
self.set_net_prop("search_domain", '')
|
||||
self.set_net_prop("dns1", '')
|
||||
self.set_net_prop("dns2", '')
|
||||
self.set_net_prop("dns3", '')
|
||||
|
||||
def prerun(self,ui,dim,display):
|
||||
pass
|
||||
def run(self,ui,dim,display):
|
||||
self.ui = ui
|
||||
self.parent = display
|
||||
width,height = ui.get_cols_rows()
|
||||
|
||||
self.overlay = urwid.Overlay(self, display, ('fixed left', 0),width
|
||||
, ('fixed top',1), height-3)
|
||||
self.prerun(ui,dim,display)
|
||||
#self.ready_comboboxes(ui,overlay)
|
||||
|
||||
keys = True
|
||||
while True:
|
||||
if keys:
|
||||
ui.draw_screen(dim, self.overlay.render(dim, True))
|
||||
keys = ui.get_input()
|
||||
|
||||
for k in keys:
|
||||
#Send key to underlying widget:
|
||||
if urwid.is_mouse_event(k):
|
||||
event, button, col, row = k
|
||||
self.overlay.mouse_event( dim,
|
||||
event, button, col, row,
|
||||
focus=True)
|
||||
self.overlay.keypress(dim, k)
|
||||
if "window resize" in keys:
|
||||
dim = ui.get_cols_rows()
|
||||
if "esc" in keys or 'Q' in keys:
|
||||
return False
|
||||
if "meta enter" in keys or self.OK_PRESSED:
|
||||
self.OK_PRESSED = False
|
||||
if self.save_settings():
|
||||
return True
|
||||
if self.CANCEL_PRESSED:
|
||||
return False
|
||||
|
||||
class WiredSettingsDialog(AdvancedSettingsDialog):
|
||||
def __init__(self,name):
|
||||
global wired, daemon
|
||||
AdvancedSettingsDialog.__init__(self)
|
||||
self.set_default = urwid.CheckBox(language['default_wired'])
|
||||
#self.cur_default =
|
||||
# Add widgets to listbox
|
||||
self._w.body.body.append(self.set_default)
|
||||
self._w.body.body.append(self.button_cols)
|
||||
|
||||
self.prof_name = name
|
||||
title = ">"+language['configuring_wired'].replace('$A',self.prof_name)
|
||||
self._w.header = urwid.Text( ('header',title),align='right' )
|
||||
|
||||
self.set_values()
|
||||
def set_net_prop(self,option,value):
|
||||
wired.SetWiredProperty(option,value)
|
||||
def set_values(self):
|
||||
self.ip_edit.set_edit_text(self.format_entry("ip"))
|
||||
self.netmask_edit.set_edit_text(self.format_entry("netmask"))
|
||||
self.gateway_edit.set_edit_text(self.format_entry("gateway"))
|
||||
|
||||
self.global_dns_cb.set_state(bool(wired.GetWiredProperty('use_global_dns')))
|
||||
self.static_dns_cb.set_state(bool(wired.GetWiredProperty('use_static_dns')))
|
||||
|
||||
self.dns1.set_edit_text(self.format_entry( "dns1"))
|
||||
self.dns2.set_edit_text(self.format_entry( "dns2"))
|
||||
self.dns3.set_edit_text(self.format_entry( "dns3"))
|
||||
self.dns_dom_edit.set_edit_text(self.format_entry("dns_domain"))
|
||||
self.search_dom_edit.set_edit_text(self.format_entry("search_domain"))
|
||||
|
||||
self.set_default.set_state(to_bool(wired.GetWiredProperty("default")))
|
||||
|
||||
def save_settings(self):
|
||||
AdvancedSettingsDialog.save_settings(self)
|
||||
if self.set_default.get_state():
|
||||
wired.UnsetWiredDefault()
|
||||
print self.set_default.get_state()
|
||||
if self.set_default.get_state():
|
||||
bool = True
|
||||
else:
|
||||
bool = False
|
||||
wired.SetWiredProperty("default",bool)
|
||||
wired.SaveWiredNetworkProfile(self.prof_name)
|
||||
return True
|
||||
|
||||
def format_entry(self, label):
|
||||
""" Helper method to fetch and format wired properties. """
|
||||
return noneToBlankString(wired.GetWiredProperty(label))
|
||||
def prerun(self,ui,dim,display):
|
||||
pass
|
||||
|
||||
########################################
|
||||
|
||||
class WirelessSettingsDialog(AdvancedSettingsDialog):
|
||||
def __init__(self,networkID):
|
||||
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(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()
|
||||
|
||||
title = ">"+language['configuring_wireless'].replace('$A',wireless.GetWirelessProperty(networkID,'essid')).replace('$B',wireless.GetWirelessProperty(networkID,'bssid'))
|
||||
self._w.header = urwid.Text(('header',title),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. """
|
||||
networkID = self.networkID
|
||||
self.ip_edit.set_edit_text(self.format_entry(networkID,"ip"))
|
||||
self.netmask_edit.set_edit_text(self.format_entry(networkID,"netmask"))
|
||||
self.gateway_edit.set_edit_text(self.format_entry(networkID,"gateway"))
|
||||
|
||||
self.global_dns_cb.set_state(bool(wireless.GetWirelessProperty(networkID,
|
||||
'use_global_dns')))
|
||||
self.static_dns_cb.set_state(bool(wireless.GetWirelessProperty(networkID,
|
||||
'use_static_dns')))
|
||||
|
||||
self.dns1.set_edit_text(self.format_entry(networkID, "dns1"))
|
||||
self.dns2.set_edit_text(self.format_entry(networkID, "dns2"))
|
||||
self.dns3.set_edit_text(self.format_entry(networkID, "dns3"))
|
||||
self.dns_dom_edit.set_edit_text(self.format_entry(networkID, "dns_domain"))
|
||||
self.search_dom_edit.set_edit_text(self.format_entry(networkID, "search_domain"))
|
||||
|
||||
|
||||
#self.reset_static_checkboxes()
|
||||
self.encryption_chkbox.set_state(bool(wireless.GetWirelessProperty(networkID,
|
||||
'encryption')),do_callback=False)
|
||||
self.global_settings_chkbox.set_state(bool(wireless.GetWirelessProperty(networkID
|
||||
,'use_settings_globally')))
|
||||
|
||||
# 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()
|
||||
activeID = -1 # Set the menu to this item when we are done
|
||||
user_enctype = wireless.GetWirelessProperty(networkID, "enctype")
|
||||
for x, enc_type in enumerate(self.encrypt_types):
|
||||
if enc_type[1] == user_enctype:
|
||||
activeID = x
|
||||
|
||||
self.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)
|
||||
|
||||
def set_net_prop(self, option, value):
|
||||
""" Sets the given option to the given value for this network. """
|
||||
wireless.SetWirelessProperty(self.networkID, option, value)
|
||||
|
||||
def format_entry(self, networkid, label):
|
||||
""" Helper method for fetching/formatting wireless properties. """
|
||||
return noneToBlankString(wireless.GetWirelessProperty(networkid, label))
|
||||
|
||||
# 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.overlay,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.overlay, 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 prerun(self,ui,dim,display):
|
||||
self.encryption_combo.build_combobox(self.overlay,ui,14)
|
||||
self.change_encrypt_method()
|
||||
490
curses/prefs_curses.py
Executable file
490
curses/prefs_curses.py
Executable file
@@ -0,0 +1,490 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Copyright (C) 2008-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
|
||||
import urwid.curses_display
|
||||
|
||||
from wicd import misc
|
||||
from wicd import dbusmanager
|
||||
from curses_misc import SelText,DynWrap,ComboBox,TabColumns
|
||||
|
||||
daemon = None
|
||||
wireless = None
|
||||
wired = None
|
||||
|
||||
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',language['network_interfaces'])
|
||||
wired_t = ('editcp',language['wired_interface']+': ')
|
||||
wless_t = ('editcp',language['wireless_interface']+':')
|
||||
always_show_wired_t = language['wired_always_on']
|
||||
prefer_wired_t = language['always_switch_to_wired']
|
||||
|
||||
global_dns_cat_t = ('header',language['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',language['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']
|
||||
|
||||
auto_reconn_cat_t = ('header',language['automatic_reconnection'])
|
||||
auto_reconn_t = language['auto_reconnect']
|
||||
|
||||
#### 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',language['wpa_supplicant'])
|
||||
wpa_t=('editcp','Driver:')
|
||||
wpa_list = ['spam','double spam','triple spam','quadruple spam']
|
||||
wpa_warn_t = ('important',language['always_use_wext'])
|
||||
|
||||
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',language['debugging'])
|
||||
debug_mode_t = language['use_debug_mode']
|
||||
|
||||
wless_cat_t = ('header',language['wireless_interface'])
|
||||
use_dbm_t = language['display_type_dialog']
|
||||
|
||||
|
||||
|
||||
####
|
||||
#### 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.prefer_wired_chkbx = urwid.CheckBox(prefer_wired_t)
|
||||
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 = 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)
|
||||
|
||||
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)
|
||||
|
||||
self.auto_reconn_cat = urwid.Text(auto_reconn_cat_t)
|
||||
self.auto_reconn_checkb = urwid.CheckBox(auto_reconn_t)
|
||||
generalLB = urwid.ListBox([self.net_cat,
|
||||
self.wless_edit,#_blank,
|
||||
self.wired_edit,
|
||||
self.always_show_wired_checkb,
|
||||
self.prefer_wired_chkbx,_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, _blank,
|
||||
self.auto_reconn_cat,
|
||||
self.auto_reconn_checkb
|
||||
])
|
||||
|
||||
#### 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)
|
||||
|
||||
|
||||
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
|
||||
])
|
||||
|
||||
|
||||
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,language['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):
|
||||
# Reset the buttons
|
||||
self.CANCEL_PRESSED = False
|
||||
self.OK_PRESSED = False
|
||||
|
||||
### 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())
|
||||
self.prefer_wired_chkbx.set_state(daemon.GetPreferWiredNetwork())
|
||||
# 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]
|
||||
|
||||
self.auto_reconn_checkb.set_state(daemon.GetAutoReconnect())
|
||||
|
||||
### 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_focus(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)
|
||||
cur_backend = daemon.GetSavedBackend()
|
||||
try:
|
||||
self.backend_cbox.set_focus(self.thebackends.index(cur_backend))
|
||||
except ValueError:
|
||||
self.backend_cbox.set_focus(0)
|
||||
|
||||
# Two last checkboxes
|
||||
self.debug_mode_checkb.set_state(daemon.GetDebugMode())
|
||||
self.use_dbm_checkb.set_state(daemon.GetSignalDisplayType())
|
||||
|
||||
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_focus()[1]])
|
||||
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()))
|
||||
daemon.SetPreferWiredNetwork(bool(self.prefer_wired_chkbx.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_focus()[1]])
|
||||
|
||||
# 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:
|
||||
if urwid.is_mouse_event(k):
|
||||
event, button, col, row = k
|
||||
overlay.mouse_event( dim,
|
||||
event, button, col, row,
|
||||
focus=True)
|
||||
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
|
||||
|
||||
|
||||
###
|
||||
### 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)
|
||||
967
curses/wicd-curses.py
Normal file
967
curses/wicd-curses.py
Normal file
@@ -0,0 +1,967 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
""" wicd-curses. (curses/urwid-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-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.
|
||||
|
||||
"""
|
||||
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
|
||||
# This library is the only reason why I wrote this program.
|
||||
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
|
||||
from wicd import wpath
|
||||
from wicd import misc
|
||||
from wicd import dbusmanager
|
||||
|
||||
# Internal Python stuff
|
||||
import sys
|
||||
from time import sleep
|
||||
|
||||
# Curses UIs for other stuff
|
||||
from curses_misc import SelText,DynEdit,DynIntEdit,ComboBox,Dialog2,TextDialog,InputDialog,error
|
||||
from prefs_curses import PrefsDialog
|
||||
import netentry_curses
|
||||
|
||||
from netentry_curses import WirelessSettingsDialog, WiredSettingsDialog
|
||||
|
||||
from optparse import OptionParser
|
||||
|
||||
# Stuff about getting the script configurer running
|
||||
#from grp import getgrgid
|
||||
#from os import getgroups,system
|
||||
|
||||
CURSES_REVNO=wpath.curses_revision
|
||||
|
||||
language = misc.get_language_list_gui()
|
||||
# We need 'Connecting' without the '...'
|
||||
language['connecting']=misc.get_language_list_tray()['connecting']
|
||||
|
||||
########################################
|
||||
##### 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 "\n"+language['terminated']
|
||||
#raise
|
||||
except DBusException:
|
||||
gobject.source_remove(redraw_tag)
|
||||
# Quit the loop
|
||||
loop.quit()
|
||||
# Zap the screen
|
||||
ui.stop()
|
||||
print "\n"+language['dbus_fail']
|
||||
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 "\n" + language['exception']
|
||||
# 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 = []
|
||||
#is_active = wireless.GetWirelessIP('') == None and wired.GetWiredIP('') != None
|
||||
# This one makes a list of strings to put in a combo box.
|
||||
#for profile in wired.GetWiredProfileList():
|
||||
#theString = '%4s %25s' % (id, profile)
|
||||
#### THIS IS wired.blah() in experimental
|
||||
#print config.GetLastUsedWiredNetwork()
|
||||
# Tag if no wireless IP present, and wired one is
|
||||
#if is_active:
|
||||
# theString = '>'+theString[1:]
|
||||
|
||||
#wiredL.append(urwid.AttrWrap(SelText(theString),'connected',
|
||||
# 'connected focus'))
|
||||
#else:
|
||||
#wiredL.append(urwid.AttrWrap(SelText(theString),'body','focus'))
|
||||
#wiredL.append(theString)
|
||||
#id+=1
|
||||
wiredL = wired.GetWiredProfileList()
|
||||
wlessL = []
|
||||
# This one makes a list of NetLabels
|
||||
for network_id in range(0, wireless.GetNumberOfNetworks()):
|
||||
is_active = wireless.GetCurrentSignalStrength("") != 0 and wireless.GetCurrentNetworkID(wireless.GetIwconfig())==network_id and wireless.GetWirelessIP('') != None
|
||||
|
||||
label = NetLabel(network_id,is_active)
|
||||
wlessL.append(label)
|
||||
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',"///")," ",language["brought_to_you"],"\n",
|
||||
('green'," \\\\\\")," |+| ",('green',"///")," Adam Blackburn (wicd)\n",
|
||||
" ___|+|___ Dan O'Reilly (wicd)\n",
|
||||
" |---------| Andrew Psaltis (this ui)\n",
|
||||
"-----------------------------------------------------"]
|
||||
about = TextDialog(theText,16,55,header=('header','About Wicd'))
|
||||
about.run(ui,body)
|
||||
|
||||
def help_dialog(body):
|
||||
theText = [
|
||||
"For more detailed help, consult the wicd-curses(8) man page.\n",
|
||||
"\n", "All controls are case sensitive\n",
|
||||
('bold','H')," or ",('bold','h'),' or ',('bold','?')," Display this help dialog\n",
|
||||
('bold','enter')," Connect to selected network\n",
|
||||
('bold','D')," Disconnect from all networks\n",
|
||||
('bold','ESC')," Stop a network connection in progress\n",
|
||||
('bold','F5')," or ", ('bold','R')," Refresh network list\n",
|
||||
('bold','P')," Prefrences dialog\n",
|
||||
('bold','I')," Scan for hidden networks\n",
|
||||
('bold','S')," Select scripts\n",
|
||||
('bold','O')," Set up Ad-hoc network\n",
|
||||
('bold','C')," Configure Selected Network\n"
|
||||
]
|
||||
help = TextDialog(theText,17,62,header=('header',"Wicd-Curses Help"))
|
||||
help.run(ui,body)
|
||||
|
||||
def run_configscript(parent,netname,nettype):
|
||||
configfile = wpath.etc+netname+'-settings.conf'
|
||||
header = 'profile' if nettype == 'wired' else 'BSSID'
|
||||
profname = netname if nettype == 'wired' else wireless.GetWirelessProperty(
|
||||
int(netname),'bssid')
|
||||
theText = [
|
||||
language['cannot_edit_scripts_1'].replace('$A',configfile).replace('$B',header),
|
||||
"\n\n["+profname+"]\n\n",
|
||||
# Translation needs to be changed to accomidate this text below.
|
||||
"""You can also configure the wireless networks by looking for the "[<ESSID>]" field in the config file.
|
||||
|
||||
Once there, you can adjust (or add) the "beforescript", "afterscript", and "disconnectscript" variables as needed, to change the preconnect, postconnect, and disconnect scripts respectively. Note that you will be specifying the full path to the scripts - not the actual script contents. You will need to add/edit the script contents separately. Refer to the wicd manual page for more information."""]
|
||||
dialog = TextDialog(theText,20,80)
|
||||
dialog.run(ui,parent)
|
||||
# This code works with many distributions, but not all of them. So, to
|
||||
# limit complications, it has been deactivated. If you want to run it,
|
||||
# be my guest. Be sure to deactivate the above stuff first.
|
||||
"""
|
||||
loop.quit()
|
||||
ui.stop()
|
||||
argv = netname + ' ' +nettype
|
||||
|
||||
#cmd = '/usr/lib/configscript_curses.py '+argv
|
||||
cmd = wpath.lib+'configscript_curses.py '+argv
|
||||
# Check whether we can sudo. Hopefully this is complete
|
||||
glist = []
|
||||
for i in getgroups():
|
||||
glist.append(getgrgid(i)[0])
|
||||
if 'root' in glist:
|
||||
precmd = ''
|
||||
precmdargv = ''
|
||||
postcmd = ''
|
||||
elif 'admin' in glist or 'wheel' in glist or 'sudo' in glist:
|
||||
precmd = 'sudo'
|
||||
precmdargv = ''
|
||||
postcmd = ''
|
||||
else:
|
||||
precmd = 'su'
|
||||
precmdargv = ' -c "'
|
||||
postcmd = '"'
|
||||
print "Calling command: " + precmd + precmdargv + cmd + postcmd
|
||||
sys.stdout.flush()
|
||||
system(precmd+precmdargv+cmd+postcmd)
|
||||
raw_input("Press enter!")
|
||||
main()
|
||||
"""
|
||||
|
||||
########################################
|
||||
##### URWID SUPPORT CLASSES
|
||||
########################################
|
||||
|
||||
# Wireless network label
|
||||
class NetLabel(urwid.WidgetWrap):
|
||||
def __init__(self, id, is_active):
|
||||
# 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
|
||||
self.id = id
|
||||
# All of that network property stuff
|
||||
self.stren = daemon.FormatSignalForPrinting(
|
||||
str(wireless.GetWirelessProperty(id, strenstr)))
|
||||
self.essid = wireless.GetWirelessProperty(id, 'essid')
|
||||
self.bssid = wireless.GetWirelessProperty(id, 'bssid')
|
||||
self.encrypt = wireless.GetWirelessProperty(id,'encryption_method') if wireless.GetWirelessProperty(id, 'encryption') else language['unsecured']
|
||||
self.mode = wireless.GetWirelessProperty(id, 'mode') # Master, Ad-Hoc
|
||||
self.channel = wireless.GetWirelessProperty(id, 'channel')
|
||||
theString = ' %*s %25s %9s %17s %6s: %s' % (gap,
|
||||
self.stren,self.essid,self.encrypt,self.bssid,self.mode,self.channel)
|
||||
if is_active:
|
||||
theString = '>'+theString[1:]
|
||||
w = urwid.AttrWrap(SelText(theString),'connected','connected focus')
|
||||
else:
|
||||
w = urwid.AttrWrap(SelText(theString),'body','focus')
|
||||
|
||||
self.__super.__init__(w)
|
||||
def selectable(self):
|
||||
return True
|
||||
def keypress(self,size,key):
|
||||
return self._w.keypress(size,key)
|
||||
def connect(self):
|
||||
# This should work.
|
||||
wireless.ConnectWireless(self.id)
|
||||
|
||||
class WiredComboBox(ComboBox):
|
||||
"""
|
||||
list : the list of wired network profiles. The rest is self-explanitory.
|
||||
"""
|
||||
def __init__(self,list):
|
||||
self.ADD_PROFILE = '---'+language["add_new_profile"]+'---'
|
||||
self.__super.__init__(use_enter=False)
|
||||
self.set_list(list)
|
||||
#self.set_focus(self.theList.index(wired.GetDefaultProfile()))
|
||||
|
||||
def set_list(self,list):
|
||||
self.theList = list
|
||||
id=0
|
||||
wiredL=[]
|
||||
is_active = wireless.GetWirelessIP('') == None and wired.GetWiredIP('') != None
|
||||
for profile in list:
|
||||
theString = '%4s %25s' % (id, profile)
|
||||
#### THIS IS wired.blah() in experimental
|
||||
#print config.GetLastUsedWiredNetwork()
|
||||
# Tag if no wireless IP present, and wired one is
|
||||
if is_active:
|
||||
theString = '>'+theString[1:]
|
||||
|
||||
#wiredL.append(urwid.AttrWrap(SelText(theString),'connected',
|
||||
# 'connected focus'))
|
||||
#else:
|
||||
# wiredL.append(urwid.AttrWrap(SelText(theString),'body','focus'))
|
||||
wiredL.append(theString)
|
||||
id+=1
|
||||
wiredL.append(self.ADD_PROFILE)
|
||||
if is_active:
|
||||
self.attrs = ('connected','editnfc')
|
||||
self.focus_attr = 'connected focus'
|
||||
else :
|
||||
self.attrs = ('body','editnfc')
|
||||
self.focus_attr = 'focus'
|
||||
self.list = wiredL
|
||||
if self.theList != []:
|
||||
wired.ReadWiredNetworkProfile(self.get_selected_profile())
|
||||
|
||||
#def rebuild_combobox(self):
|
||||
# pass
|
||||
def keypress(self,size,key):
|
||||
prev_focus = self.get_focus()[1]
|
||||
key = self.__super.keypress(size,key)
|
||||
if self.get_focus()[1] == len(self.list)-1:
|
||||
dialog = InputDialog(('header',language["add_new_wired_profile"]),7,30)
|
||||
|
||||
exitcode,name = dialog.run(ui,self.parent)
|
||||
if exitcode == 0:
|
||||
wired.CreateWiredNetworkProfile(name,False)
|
||||
self.set_list(wired.GetWiredProfileList())
|
||||
self.rebuild_combobox()
|
||||
self.set_focus(prev_focus)
|
||||
else:
|
||||
wired.ReadWiredNetworkProfile(self.get_selected_profile())
|
||||
if key == 'delete':
|
||||
if len(self.theList) == 1:
|
||||
error(self.ui,self.parent,language["no_delete_last_profile"])
|
||||
return key
|
||||
wired.DeleteWiredNetworkProfile(self.get_selected_profile())
|
||||
# Return to the top of the list if something is deleted.
|
||||
|
||||
if wired.GetDefaultWiredNetwork() != None:
|
||||
self.set_focus(self.theList.index(wired.GetDefaultWiredNetwork()))
|
||||
else:
|
||||
prev_focus -= 1
|
||||
self.set_focus(prev_focus)
|
||||
self.set_list(wired.GetWiredProfileList())
|
||||
self.rebuild_combobox()
|
||||
if key == 'f2':
|
||||
dialog = InputDialog(('header',language["rename_wired_profile"]),7,30,
|
||||
edit_text=unicode(self.get_selected_profile()))
|
||||
exitcode,name = dialog.run(ui,self.parent)
|
||||
if exitcode == 0:
|
||||
# Save the new one, then kill the old one
|
||||
wired.SaveWiredNetworkProfile(name)
|
||||
wired.DeleteWiredNetworkProfile(self.get_selected_profile())
|
||||
self.set_list(wired.GetWiredProfileList())
|
||||
self.set_focus(self.theList.index(name))
|
||||
self.rebuild_combobox()
|
||||
return key
|
||||
|
||||
def get_selected_profile(self):
|
||||
"""Get the selected wired profile"""
|
||||
loc = self.get_focus()[1]
|
||||
return self.theList[loc]
|
||||
|
||||
# Dialog2 that initiates an Ad-Hoc network connection
|
||||
class AdHocDialog(Dialog2):
|
||||
def __init__(self):
|
||||
essid_t = language['essid']
|
||||
ip_t = language['ip']
|
||||
channel_t = language['channel']
|
||||
key_t = " " + language['key']
|
||||
use_ics_t = language['use_ics']
|
||||
use_encrypt_t = language['use_wep_encryption']
|
||||
|
||||
self.essid_edit = DynEdit(essid_t)
|
||||
self.ip_edit = DynEdit(ip_t)
|
||||
self.channel_edit = DynIntEdit(channel_t)
|
||||
self.key_edit = DynEdit(key_t,sensitive=False)
|
||||
|
||||
self.use_ics_chkb = urwid.CheckBox(use_ics_t)
|
||||
self.use_encrypt_chkb = urwid.CheckBox(use_encrypt_t,
|
||||
on_state_change=self.encrypt_callback)
|
||||
|
||||
blank = urwid.Text('')
|
||||
|
||||
# Set defaults
|
||||
self.essid_edit.set_edit_text("My_Adhoc_Network")
|
||||
self.ip_edit.set_edit_text("169.254.12.10")
|
||||
self.channel_edit.set_edit_text("3")
|
||||
|
||||
l = [self.essid_edit,self.ip_edit,self.channel_edit,blank,
|
||||
self.use_ics_chkb,self.use_encrypt_chkb,self.key_edit]
|
||||
#for line in text:
|
||||
# l.append( urwid.Text( line,align=align))
|
||||
body = urwid.ListBox(l)
|
||||
#body = urwid.AttrWrap(body, 'body')
|
||||
|
||||
header = ('header',language['create_adhoc_network'])
|
||||
Dialog2.__init__(self, header, 15, 50, body)
|
||||
self.add_buttons([('OK',1),('Cancel',-1)])
|
||||
self.frame.set_focus('body')
|
||||
|
||||
def encrypt_callback(self,chkbox,new_state,user_info=None):
|
||||
self.key_edit.set_sensitive(new_state)
|
||||
|
||||
def unhandled_key(self, size, k):
|
||||
if k in ('up','page up'):
|
||||
self.frame.set_focus('body')
|
||||
if k in ('down','page down'):
|
||||
self.frame.set_focus('footer')
|
||||
if k == 'enter':
|
||||
# pass enter to the "ok" button
|
||||
self.frame.set_focus('footer')
|
||||
self.buttons.set_focus(0)
|
||||
self.view.keypress( size, k )
|
||||
def on_exit(self,exitcode):
|
||||
data = ( self.essid_edit.get_edit_text(),
|
||||
self.ip_edit.get_edit_text(),
|
||||
self.channel_edit.get_edit_text(),
|
||||
self.use_ics_chkb.get_state(),
|
||||
self.use_encrypt_chkb.get_state(),
|
||||
self.key_edit.get_edit_text())
|
||||
|
||||
return exitcode, data
|
||||
########################################
|
||||
##### 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',language['scanning_stand_by']), align='center'))
|
||||
self.no_wlan = urwid.Filler(urwid.Text(('important',language['no_wireless_networks_found']), align='center'))
|
||||
self.TITLE = language['wicd_curses']
|
||||
self.WIRED_IDX = 1
|
||||
self.WLESS_IDX = 3
|
||||
|
||||
#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)"))
|
||||
|
||||
#if wireless.GetNumberOfNetworks() == 0:
|
||||
# wireless.Scan()
|
||||
self.focusloc = (1,0)
|
||||
|
||||
# These are empty to make sure that things go my way.
|
||||
wiredL,wlessL = [],[]# = gen_network_list()
|
||||
self.frame = None
|
||||
|
||||
self.wiredCB = urwid.Filler(WiredComboBox(wiredL))
|
||||
self.wlessLB = urwid.ListBox(wlessL)
|
||||
self.update_netlist(force_check=True,firstrun=True)
|
||||
|
||||
# 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)
|
||||
|
||||
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)
|
||||
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.always_show_wired = daemon.GetAlwaysShowWiredInterface()
|
||||
|
||||
self.pref = None
|
||||
|
||||
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
|
||||
self.update_ui()
|
||||
|
||||
def unlock_screen(self):
|
||||
self.update_netlist(force_check=True)
|
||||
self.frame.set_body(self.thePile)
|
||||
self.screen_locked = False
|
||||
self.update_ui()
|
||||
|
||||
def raise_hidden_network_dialog(self):
|
||||
dialog = InputDialog(('header',language["select_hidden_essid"]),7,30,language['scan'])
|
||||
exitcode,hidden = dialog.run(ui,self.frame)
|
||||
if exitcode != -1:
|
||||
# That dialog will sit there for a while if I don't get rid of it
|
||||
self.update_ui()
|
||||
wireless.SetHiddenNetworkESSID(misc.noneToString(hidden))
|
||||
wireless.Scan(True)
|
||||
wireless.SetHiddenNetworkESSID("")
|
||||
|
||||
def update_focusloc(self):
|
||||
# Location of last known focus is remapped to current location.
|
||||
# This might need to be cleaned up later.
|
||||
|
||||
#self.set_status(str(self.frame.get_body().get_focus())+ ' '+ str(self.wiredCB))
|
||||
if self.thePile.get_focus() == self.wiredCB:
|
||||
wlessorwired = self.WIRED_IDX
|
||||
where = self.thePile.get_focus().get_body().get_focus()[1]
|
||||
else: #self.thePile.get_focus() == self.wlessLB :
|
||||
wlessorwired = self.WLESS_IDX
|
||||
if self.wlessLB == self.no_wlan:
|
||||
where = None
|
||||
else:
|
||||
where = self.thePile.get_focus().get_focus()[1]
|
||||
#where = self.wlessLB.get_focus()[1]
|
||||
self.focusloc = (wlessorwired,where)
|
||||
# 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,firstrun=False):
|
||||
# Run focus-collecting code if we are not running this for the first time
|
||||
if not firstrun:
|
||||
self.update_focusloc()
|
||||
""" Updates the overall network list."""
|
||||
if not state:
|
||||
state, x = daemon.GetConnectionStatus()
|
||||
if force_check or self.prev_state != state:
|
||||
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)
|
||||
if len(wlessL) != 0:
|
||||
if self.wlessLB == self.no_wlan:
|
||||
self.wlessLB = urwid.ListBox(wlessL)
|
||||
else:
|
||||
self.wlessLB.body = urwid.SimpleListWalker(wlessL)
|
||||
else:
|
||||
self.wlessLB = self.no_wlan
|
||||
if daemon.GetAlwaysShowWiredInterface() or wired.CheckPluggedIn():
|
||||
#if daemon.GetAlwaysShowWiredInterface():
|
||||
#if firstrun:
|
||||
self.thePile = urwid.Pile([('fixed',1,self.wiredH),
|
||||
('fixed',1,self.wiredCB),
|
||||
('fixed',1,self.wlessH),
|
||||
self.wlessLB] )
|
||||
if not firstrun:
|
||||
self.frame.body = self.thePile
|
||||
#self.focusloc = (self.thePile.get_focus(),
|
||||
# self.thePile.get_focus().get_focus()[1])
|
||||
self.thePile.set_focus(self.focusloc[0])
|
||||
if self.focusloc[0] == self.WIRED_IDX:
|
||||
self.thePile.get_focus().get_body().set_focus(self.focusloc[1])
|
||||
else:
|
||||
if self.wlessLB is not self.no_wlan:
|
||||
self.thePile.get_focus().set_focus(self.focusloc[1])
|
||||
else:
|
||||
self.thePile.set_focus(self.wiredCB)
|
||||
else:
|
||||
self.thePile = urwid.Pile([('fixed',1,self.wlessH),self.wlessLB] )
|
||||
if not firstrun:
|
||||
self.frame.body = self.thePile
|
||||
#if self.focusloc[0] == self.wlessLB:
|
||||
self.wlessLB.set_focus(self.focusloc[1])
|
||||
#self.thePile.get_focus().set_focus(self.focusloc[1])
|
||||
#self.always_show_wired = not self.always_show_wired
|
||||
self.prev_state = state
|
||||
if not firstrun:
|
||||
self.update_ui()
|
||||
if firstrun:
|
||||
if wired.GetDefaultWiredNetwork() != None:
|
||||
self.wiredCB.get_body().set_focus(wired.GetWiredProfileList().index(wired.GetDefaultWiredNetwork()))
|
||||
|
||||
# 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'])
|
||||
self.update_ui()
|
||||
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:
|
||||
self.update_netlist()
|
||||
self.update_status()
|
||||
self.update_ui()
|
||||
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 it 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
|
||||
@wrap_exceptions()
|
||||
def idle_incr(self):
|
||||
theText = " "
|
||||
#if self.special != None:
|
||||
# theText += self.special
|
||||
if self.connecting:
|
||||
theText += "-- "+language['connecting']+' -- '+language["esc_to_cancel"]
|
||||
quit_note = ' -- '+language["press_to_quit"]
|
||||
self.footer1 = urwid.Text(str(self.incr) + theText+quit_note,wrap='clip')
|
||||
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:
|
||||
# gobject.idle_add(self.refresh_networks, None, False, None)
|
||||
self.unlock_screen()
|
||||
|
||||
# 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 or 'q' in keys:
|
||||
loop.quit()
|
||||
return False
|
||||
if "f5" in keys or 'R' in keys:
|
||||
self.lock_screen()
|
||||
wireless.Scan(True)
|
||||
if "D" in keys:
|
||||
# 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.frame.body.get_focus()
|
||||
if focus == self.wiredCB:
|
||||
self.special = focus
|
||||
self.connect("wired",0)
|
||||
else:
|
||||
# wless list only other option
|
||||
wid,pos = self.thePile.get_focus().get_focus()
|
||||
self.connect("wireless",pos)
|
||||
|
||||
if "esc" in keys:
|
||||
# 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:
|
||||
if not self.pref:
|
||||
self.pref = PrefsDialog(self.frame,(0,1),ui,
|
||||
dbusmanager.get_dbus_ifaces())
|
||||
if self.pref.run(ui,self.size,self.frame):
|
||||
self.pref.save_results()
|
||||
self.update_ui()
|
||||
if "A" in keys:
|
||||
about_dialog(self.frame)
|
||||
if "C" in keys:
|
||||
focus = self.thePile.get_focus()
|
||||
if focus == self.wiredCB:
|
||||
WiredSettingsDialog(self.wiredCB.get_body().
|
||||
get_selected_profile()).run(ui,self.size,self.frame)
|
||||
else:
|
||||
# wireless list only other option
|
||||
wid,pos = self.thePile.get_focus().get_focus()
|
||||
WirelessSettingsDialog(pos).run(ui,self.size,self.frame)
|
||||
#self.netentry = NetEntryBase(dbusmanager.get_dbus_ifaces())
|
||||
#self.netentry.run(ui,self.size,self.frame)
|
||||
if "I" in keys:
|
||||
self.raise_hidden_network_dialog()
|
||||
if "H" in keys or 'h' in keys or '?' in keys:
|
||||
help_dialog(self.frame)
|
||||
if "S" in keys:
|
||||
focus = self.thePile.get_focus()
|
||||
if focus == self.wiredCB:
|
||||
nettype = 'wired'
|
||||
netname = self.wiredCB.get_body().get_selected_profile()
|
||||
else:
|
||||
nettype = 'wireless'
|
||||
netname = str(self.wlessLB.get_focus()[1])
|
||||
run_configscript(self.frame,netname,nettype)
|
||||
if "O" in keys:
|
||||
exitcode,data = AdHocDialog().run(ui,self.frame)
|
||||
#data = (essid,ip,channel,use_ics,use_encrypt,key_edit)
|
||||
if exitcode == 1:
|
||||
wireless.CreateAdHocNetwork(data[0],
|
||||
data[2],
|
||||
data[1], "WEP",
|
||||
data[5],
|
||||
data[4], False)
|
||||
|
||||
for k in keys:
|
||||
if urwid.is_mouse_event(k):
|
||||
event, button, col, row = k
|
||||
self.frame.mouse_event( self.size,
|
||||
event, button, col, row,
|
||||
focus=True)
|
||||
if k == "window resize":
|
||||
self.size = ui.get_cols_rows()
|
||||
continue
|
||||
self.frame.keypress( self.size, k )
|
||||
return True
|
||||
|
||||
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
|
||||
########################################
|
||||
|
||||
def main():
|
||||
global ui
|
||||
|
||||
# We are _not_ python.
|
||||
misc.RenameProcess('wicd-curses')
|
||||
|
||||
# Import the screen based on whatever the user picked.
|
||||
# The raw_display will have some features that may be useful to users
|
||||
# later
|
||||
if options.rawscreen:
|
||||
import urwid.raw_display
|
||||
ui = urwid.raw_display.Screen()
|
||||
else:
|
||||
import urwid.curses_display
|
||||
ui = urwid.curses_display.Screen()
|
||||
# Default 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','default','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'),
|
||||
('editnfc','dark gray','default'),
|
||||
('tab active','dark green','light gray'),
|
||||
# Simple colors around text
|
||||
('green','dark green','default'),
|
||||
('blue','dark blue','default'),
|
||||
('red','dark red','default'),
|
||||
('bold','white','default','bold')])
|
||||
# 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
|
||||
|
||||
ui.set_mouse_tracking()
|
||||
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, please?
|
||||
print language['cannot_connect_to_daemon']
|
||||
#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
|
||||
|
||||
|
||||
netentry_curses.dbus_init(dbus_ifaces)
|
||||
return True
|
||||
|
||||
setup_dbus()
|
||||
|
||||
########################################
|
||||
##### MAIN ENTRY POINT
|
||||
########################################
|
||||
if __name__ == '__main__':
|
||||
parser = OptionParser(version="wicd-curses-%s (using wicd %s)" % (CURSES_REVNO,daemon.Hello()))
|
||||
parser.add_option("-r", "--raw-screen",action="store_true",dest='rawscreen',
|
||||
help="use urwid's raw screen controller")
|
||||
(options,args) = parser.parse_args()
|
||||
main()
|
||||
# Make sure that the terminal does not try to overwrite the last line of
|
||||
# the program, so that everything looks pretty.
|
||||
print ""
|
||||
@@ -49,4 +49,3 @@ case $1 in
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
|
||||
95
in/man=wicd-curses.8.in
Normal file
95
in/man=wicd-curses.8.in
Normal file
@@ -0,0 +1,95 @@
|
||||
.\" First revision was r203
|
||||
.TH WICD-CURSES "8" "January 2009" "wicd-curses-%CURSES_REVNO%"
|
||||
.SH NAME
|
||||
.B wicd-curses
|
||||
\- curses-based wicd(8) controller
|
||||
.SH DESCRIPTION
|
||||
wicd-curses is a curses-based network controller that uses the Wired/Wireless Internet Connection Daemon (wicd) to control your network connections. It is suitable to run in terminal multiplexers like screen(1).
|
||||
|
||||
It is designed to imitate the GTK-based wicd-client(1) as much as possible, and uses the Urwid (http://excess.org/urwid) console widget library to vastly simplify development.
|
||||
|
||||
This man page only documents the current status of wicd-curses. This may/may not be the most up-to-date document.
|
||||
.SH "ARGUMENTS"
|
||||
.TP
|
||||
.BR "\-r" , " \-\-raw\-screen"
|
||||
Use Urwid's raw console display, instead of the (faster) curses-based one. This may be useful if you are experiencing unicode problems.
|
||||
.SH CONTROLS
|
||||
All of these are case sensitive.
|
||||
.TP
|
||||
.BR enter
|
||||
Connect to selected network
|
||||
.TP
|
||||
.BR "F8 " or " Q " or " q"
|
||||
Quit the client.
|
||||
.TP
|
||||
.BR D
|
||||
Disconnect all devices from network connections
|
||||
.TP
|
||||
.BR ESC
|
||||
If connecting to a network, stop doing so
|
||||
.TP
|
||||
.BR "F5 " or " R"
|
||||
Refresh the network list
|
||||
.TP
|
||||
.BR P
|
||||
Bring up the preferences controller
|
||||
.TP
|
||||
.BR I
|
||||
Bring up hidden network scanning dialog
|
||||
.TP
|
||||
.BR "H " or " h " or " ?"
|
||||
Bring up a rather simplistic help dialog. Of course, it mentions this man page first. :-)
|
||||
.\".PP
|
||||
.\"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
|
||||
.TP
|
||||
.BR delete
|
||||
Delete the selected wired network profile (from the wired network combo box at the top)
|
||||
.TP
|
||||
.BR F2
|
||||
Rename the selected wired network profile (from the wired network combo box at the top)
|
||||
.\".PP
|
||||
.\"The following are not implemented yet:
|
||||
.TP
|
||||
.BR S
|
||||
.\"Bring up the script selector for the selected network (requires superuser privileges)
|
||||
Bring up instructions on how to edit the scripts. I have implemented a way to do this in the interface itself, but making it function with all Linux distros would be difficult. Since you are reading this, you should know how to do what I suggest. ;-)
|
||||
.TP
|
||||
.BR O
|
||||
Raise the Ad-Hoc network creation dialog
|
||||
|
||||
.SH "FILES"
|
||||
These are not used yet.
|
||||
.TP
|
||||
.I ~/.wicd/WHEREAREMYFILES
|
||||
Reminder that your network configuration files are not here ;-)
|
||||
.TP
|
||||
.I %LIB%keymap.py
|
||||
Tentative location of the system keymap
|
||||
.TP
|
||||
.I %LIB%colors.py
|
||||
Tentative location of the system color schemes
|
||||
.TP
|
||||
.I ~/.wicd/keymap.py
|
||||
Custom keybindings. Also where you can (later) disable the mouse.
|
||||
.TP
|
||||
.I ~/.wicd/colors.py
|
||||
Custom color schemes.
|
||||
.SH "SEE ALSO"
|
||||
.BR wicd-client (1),
|
||||
.BR wicd (8)
|
||||
|
||||
.SH BUGS
|
||||
Probably lots. ;-)
|
||||
|
||||
If you happen to find one, ask about it on #wicd on freenode, or submit a bug report to http://launchpad.net/wicd, branch experimental-nacl.
|
||||
|
||||
.SH WICD-CURSES AUTHOR
|
||||
Andrew Psaltis <ampsaltis@gmail.com>
|
||||
|
||||
.SH WICD AUTHORS
|
||||
Adam Blackburn <compwiz18@gmail.com>
|
||||
.br
|
||||
Dan O'Reilly <oreilldf@gmail.com>
|
||||
16
in/other=WHEREAREMYFILES.in
Normal file
16
in/other=WHEREAREMYFILES.in
Normal file
@@ -0,0 +1,16 @@
|
||||
WHERE ARE MY FILES?!
|
||||
|
||||
If you are reading this, you are probably wondering why your Wicd configuration
|
||||
files are not here. What follows is a summary of the folders that Wicd uses.
|
||||
|
||||
For a more detailed (and complete) description what is in each directory,
|
||||
consult the man pages for wicd(8) and wicd-curses(8).
|
||||
|
||||
~/.wicd
|
||||
User-dependent configuration files, only used by wicd-curses
|
||||
|
||||
%ETC%
|
||||
Global configuration files
|
||||
|
||||
%NETWORKS%
|
||||
Individual network configurations
|
||||
@@ -1,2 +1,36 @@
|
||||
#!/bin/bash
|
||||
BOLD=$(tput bold)
|
||||
BLUE=$(tput setaf 4)
|
||||
NC=$(tput sgr0)
|
||||
# check_firstrun()
|
||||
if [ ! -d "~/.wicd" ]; then
|
||||
mkdir -p "~/.wicd"
|
||||
fi
|
||||
# Make sure the user knows WHEREAREMYFILES ;-)
|
||||
if [ -e "%DOCDIR%WHEREAREMYFILES" ] && [ ! -L "~/.wicd/WHEREAREMYFILES" ]; then
|
||||
ln -s "%DOCDIR%WHEREAREMYFILES" "~/.wicd/WHEREAREMYFILES"
|
||||
fi
|
||||
if [ "$DISPLAY" = "" ] && [ -x "%BIN%wicd-curses" ]; then
|
||||
if [ ! -f "~/.wicd/CLIENT_CURSES_WARNING" ]; then
|
||||
printf "NOTICE: You do not have an X server active on this console, \n"
|
||||
printf "so ${BOLD}${BLUE}wicd-curses${NC} will be started instead. \n"
|
||||
printf "Please see the wicd-client and/or wicd-curses manual pages \n"
|
||||
printf "for more information about this error and resulting message. \n"
|
||||
printf "\n"
|
||||
printf "This message will not be displayed again. \n"
|
||||
printf "Press enter to continue... \n"
|
||||
|
||||
read _junk
|
||||
cat >> "~/.wicd/CLIENT_CURSES_WARNING" << EOF
|
||||
The wicd-client script checks for the existence of this file to determine
|
||||
whether it should warn the user before launching wicd-curses instead, in
|
||||
the event of the gui client being launched outside of the X Window environment.
|
||||
|
||||
If you delete this file, then wicd-client will print the warning if it is
|
||||
launched outside of X (and then recreate this file again).
|
||||
EOF
|
||||
fi
|
||||
exec %BIN%wicd-curses
|
||||
fi
|
||||
|
||||
exec python -O %LIB%wicd-client.py $@
|
||||
|
||||
2
in/scripts=wicd-curses.in
Executable file
2
in/scripts=wicd-curses.in
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
exec python -O %LIB%wicd-curses.py $@
|
||||
@@ -19,6 +19,7 @@ current = os.path.dirname(os.path.realpath(__file__)) + '/'
|
||||
|
||||
version = '%VERSION%'
|
||||
revision = '%REVNO%'
|
||||
curses_revision = '%CURSES_REVNO%'
|
||||
|
||||
# DIRECTORIES
|
||||
|
||||
@@ -64,6 +65,7 @@ no_install_man = %NO_INSTALL_MAN%
|
||||
no_install_kde = %NO_INSTALL_KDE%
|
||||
no_install_acpi = %NO_INSTALL_ACPI%
|
||||
no_install_docs = %NO_INSTALL_DOCS%
|
||||
no_install_ncurses = %NO_INSTALL_NCURSES%
|
||||
|
||||
def chdir(file):
|
||||
"""Change directory to the location of the specified file.
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
wicd-client \- manual page for wicd-client
|
||||
.SH DESCRIPTION
|
||||
wireless (and wired) connection daemon front\-end.
|
||||
|
||||
If wicd-curses(8) is installed, and you attempt to run wicd-client without
|
||||
an active X server on the current terminal, wicd-client will attempt to run
|
||||
wicd-curses(8) instead. It will warn you the first time this happens.
|
||||
.SS "Arguments:"
|
||||
.TP
|
||||
\fB\-n\fR \fB\-\-no\-tray\fR
|
||||
|
||||
43
setup.py
43
setup.py
@@ -1,3 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2007 - 2008 Adam Blackburn
|
||||
# Copyright (C) 2007 - 2008 Dan O'Reilly
|
||||
@@ -26,6 +27,7 @@ import subprocess
|
||||
# VERSIONNUMBER
|
||||
VERSION_NUM = '1.6.0'
|
||||
REVISION_NUM = 'unknown'
|
||||
CURSES_REVNO = 'r269'
|
||||
|
||||
try:
|
||||
if not os.path.exists('vcsinfo.py'):
|
||||
@@ -84,7 +86,8 @@ class configure(Command):
|
||||
('no-install-kde', None, 'do not install the kde autostart file'),
|
||||
('no-install-acpi', None, 'do not install the suspend.d and resume.d acpi scripts'),
|
||||
('no-install-pmutils', None, 'do not install the pm-utils hooks'),
|
||||
('no-install-docs', None, 'do not install the auxiliary documentation')
|
||||
('no-install-docs', None, 'do not install the auxiliary documentation'),
|
||||
('no-install-ncurses', None, 'do not install the ncurses client')
|
||||
]
|
||||
|
||||
|
||||
@@ -117,6 +120,7 @@ class configure(Command):
|
||||
self.no_install_acpi = False
|
||||
self.no_install_pmutils = False
|
||||
self.no_install_docs = False
|
||||
self.no_install_ncurses = False
|
||||
|
||||
# Determine the default init file location on several different distros
|
||||
|
||||
@@ -151,6 +155,8 @@ class configure(Command):
|
||||
elif os.path.exists('/etc/pld-release'):
|
||||
self.init = '/etc/rc.d/init.d/'
|
||||
self.initfile = 'init/pld/wicd'
|
||||
elif os.path.exists('/usr/bin/crux'):
|
||||
self.init = '/etc/rc.d/'
|
||||
else:
|
||||
self.init = 'FAIL'
|
||||
self.initfile = 'FAIL'
|
||||
@@ -187,13 +193,22 @@ class configure(Command):
|
||||
else:
|
||||
self.kdedir = kdedir_candidate + '/share/autostart'
|
||||
except (OSError, ValueError):
|
||||
# If kde-config isn't present or returns an error, then we can
|
||||
# assume that kde isn't installed on the user's system
|
||||
self.no_install_kde = True
|
||||
# If it turns out that the assumption above is wrong, then we'll
|
||||
# do this instead:
|
||||
#pass # use our default
|
||||
|
||||
# If kde-config isn't present, we'll check for kde-4.x
|
||||
try:
|
||||
kde4temp = subprocess.Popen(["kde4-config","--prefix"], stdout=subprocess.PIPE)
|
||||
returncode = kde4temp.wait() # let it finish, and get the exit code
|
||||
kde4dir_candidate = kde4temp.stdout.readline().strip() # read stdout
|
||||
if len(kde4dir_candidate) == 0 or returncode != 0 or not os.path.isabs(kde4dir_candidate):
|
||||
raise ValueError
|
||||
else:
|
||||
self.kdedir = kde4dir_candidate + '/share/autostart'
|
||||
except (OSError, ValueError):
|
||||
# If neither kde-config nor kde4-config are not present or
|
||||
# return an error, then we can assume that kde isn't installed
|
||||
# on the user's system
|
||||
self.no_install_kde = True
|
||||
# If the assumption above turns out to be wrong, do this:
|
||||
#pass # use our default
|
||||
|
||||
self.python = '/usr/bin/python'
|
||||
self.pidfile = '/var/run/wicd/wicd.pid'
|
||||
@@ -254,6 +269,7 @@ class configure(Command):
|
||||
# other things to replace that aren't arguments
|
||||
line = line.replace('%VERSION%', str(VERSION_NUM))
|
||||
line = line.replace('%REVNO%', str(REVISION_NUM))
|
||||
line = line.replace('%CURSES_REVNO%', str(CURSES_REVNO))
|
||||
|
||||
item_out.write(line)
|
||||
|
||||
@@ -392,12 +408,21 @@ try:
|
||||
(wpath.backends, ['wicd/backends/be-external.py', 'wicd/backends/be-ioctl.py']),
|
||||
(wpath.autostart, ['other/wicd-tray.desktop', ]),
|
||||
]
|
||||
if not wpath.no_install_ncurses:
|
||||
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.lib, ['curses/configscript_curses.py']))
|
||||
data.append(( wpath.bin, ['scripts/wicd-curses']))
|
||||
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 += '/'
|
||||
data.append (( piddir, [] ))
|
||||
if not wpath.no_install_docs:
|
||||
data.append(( wpath.docdir, [ 'INSTALL', 'LICENSE', 'AUTHORS', 'README', 'CHANGES' ]))
|
||||
data.append(( wpath.docdir, [ 'INSTALL', 'LICENSE', 'AUTHORS', 'README', 'CHANGES','other/WHEREAREMYFILES' ]))
|
||||
if not wpath.no_install_kde:
|
||||
data.append(( wpath.kdedir, [ 'other/wicd-tray.desktop' ]))
|
||||
if not wpath.no_install_init:
|
||||
|
||||
10
wicd/misc.py
10
wicd/misc.py
@@ -292,7 +292,7 @@ def noneToString(text):
|
||||
return "None"
|
||||
else:
|
||||
return str(text)
|
||||
|
||||
|
||||
def get_gettext():
|
||||
""" Set up gettext for translations. """
|
||||
# Borrowed from an excellent post on how to do this at
|
||||
@@ -543,7 +543,7 @@ def get_language_list_gui():
|
||||
language['lost_dbus'] = _("The wicd daemon has shut down, the UI will not function properly until it is restarted.")
|
||||
language['configuring_wireless'] = _("Configuring preferences for wireless network \"$A\" ($B)")
|
||||
language['configuring_wired'] = _("Configuring preferences for wired profile \"$A\"")
|
||||
|
||||
language['scan'] = _('Scan')
|
||||
language['always_switch_to_wired'] = _("Always switch to wired connection when available")
|
||||
language['wired_autoconnect_settings'] = _("Wired Autoconnect Settings")
|
||||
language['always_use_wext'] = _("You should almost always use wext as the WPA supplicant driver")
|
||||
@@ -555,7 +555,6 @@ def get_language_list_gui():
|
||||
language['connecting_to_daemon'] = _("Connecting to daemon...")
|
||||
language['cannot_connect_to_daemon'] = _("Can't connect to the daemon, trying to start it automatically...")
|
||||
language['could_not_connect'] = _("Could not connect to wicd's D-Bus interface. Check the wicd log for error messages.")
|
||||
|
||||
language["exception"] = _("EXCEPTION! Please report this to the maintainer and file a bug report with the backtrace below:")
|
||||
language["brought_to_you"] = _("Brought to you by:")
|
||||
language["cannot_edit_scripts_1"] = _('To avoid various complications, wicd-curses does not support directly editing the scripts directly. However, you can edit them manually. First, (as root), open the "$A" config file, and look for the section labeled by the $B in question. In this case, this is:')
|
||||
@@ -568,6 +567,11 @@ def get_language_list_gui():
|
||||
language["esc_to_cancel"] = _("Press ESC to cancel")
|
||||
language["press_to_quit"] = _("Press F8 or Q to quit.")
|
||||
|
||||
language['terminated'] = _("Terminated by user")
|
||||
language['wicd_curses'] = _("Wicd Curses Interface")
|
||||
language['dbus_fail'] = _("DBus failure! This is most likely caused by the wicd daemon stopping while wicd-curses is running. Please restart the daemon, and then restart wicd-curses.")
|
||||
|
||||
|
||||
return language
|
||||
|
||||
def get_language_list_tray():
|
||||
|
||||
Reference in New Issue
Block a user