1
0
mirror of https://github.com/gryf/wicd.git synced 2025-12-19 20:38:00 +01:00
Files
wicd/curses/curses_misc.py
Andrew Psaltis 0b0f3e0968 curses/curses_misc.py:
meta+right or meta+left now move the selected tab right and left respectively.  Focus goes back to the tabs, though.
  Fixed a bug in ComboBox where show_first does nothing
  Restored get_selected to its original state
curses/prefs_curses.py:
  Moved the automatic reconnect category to "General Settings"
  Made the backend selector actually select the selected backend at first
  Reset the button statuses each time we load the settings
  meta+enter now saves+closes the preferences dialog
curses/wicd-curses.py:
  Turned the wired list into a list of custom SelTexts, so that they can do the connecting/script-choosing/configuring/etc, instead of the dialog itself
  Offset the version in the about dialog a little less
  Recycle the old preferences dialog instead of making a new one if we run it more than once
2009-01-02 22:12:58 -05:00

352 lines
12 KiB
Python

#!/usr/bin/env python
# -* coding: utf-8 -*-
""" curses_misc.py: Module for various widgets that are used throughout
wicd-curses.
"""
# Copyright (C) 2008-9 Andrew Psaltis
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301, USA.
import urwid
# My savior. :-)
# Although I could have made this myself pretty easily, just want to give credit where
# its due.
# http://excess.org/urwid/browser/contrib/trunk/rbreu_filechooser.py
class SelText(urwid.Text):
"""A selectable text widget. See urwid.Text."""
def selectable(self):
"""Make widget selectable."""
return True
def keypress(self, size, key):
"""Don't handle any keys."""
return key
class ToggleEdit(urwid.WidgetWrap):
"""A edit that can be rendered unselectable by somethhing like a checkbox"""
def __init__(self, caption='', state=True,
attr=('editbx','editfc'),attrnsens='body'):
"""
caption : the Edit's caption
state : the Edit's current sensitivity
attr : tuple of (attr_no_focus, attr_focus)
attrnsens: attr to use when not sensitive
"""
edit = urwid.Edit(caption)
curattr = attr[0] if state == True else attrnsens
w = urwid.AttrWrap(edit,curattr,attr[1])
self.sensitive=state
self.__super.__init__(w)
# Kinda like the thing in PyGTK
def set_sensitive(self,state):
self.sensitive=state
if state:
self._w.set_attr('editbx')
else:
self._w.set_attr('body')
def set_edit_text(self,text):
self._w.set_edit_text(text)
def get_edit_text(self):
return self._w.get_edit_text()
# If we aren't sensitive, don't be selectable
def selectable(self):
return self.sensitive
# Do what an edit does with keys
def keypress(self,size,key):
return self._w.keypress(size,key)
# Tabbed interface, mostly for use in the Preferences Dialog
class TabColumns(urwid.WidgetWrap):
"""
titles_dict = dictionary of tab_contents (a SelText) : tab_widget (box)
attr = normal attributes
attrsel = attribute when active
"""
def __init__(self,tab_str,tab_wid,title,bottom_part,attr=('body','focus'),
attrsel='tab active', attrtitle='header'):
self.bottom_part = bottom_part
#title_wid = urwid.Text((attrtitle,title),align='right')
column_list = []
for w in tab_str:
text,trash = w.get_text()
column_list.append(('fixed',len(text),w))
column_list.append(urwid.Text((attrtitle,title),align='right'))
self.tab_map = dict(zip(tab_str,tab_wid))
self.active_tab = tab_str[0]
self.columns = urwid.Columns(column_list,dividechars=1)
#walker = urwid.SimpleListWalker([self.columns,tab_wid[0]])
#self.listbox = urwid.ListBox(walker)
self.gen_pile(tab_wid[0],True)
self.frame = urwid.Frame(self.pile)
self.__super.__init__(self.frame)
# Make the pile in the middle
def gen_pile(self,lbox,firstrun=False):
self.pile = urwid.Pile([
('fixed',1,urwid.Filler(self.columns,'top')),
urwid.Filler(lbox,'top',height=('relative',99)),
('fixed',1,urwid.Filler(self.bottom_part,'bottom'))
])
if not firstrun:
self.frame.set_body(self.pile)
self.set_w(self.frame)
def selectable(self):
return True
def keypress(self,size,key):
self._w.keypress(size,key)
if key == "meta left" or key == "meta right":
self._w.get_body().set_focus(0)
self.keypress(size,key[5:])
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
class ComboBox(urwid.WidgetWrap):
"""A ComboBox of text objects"""
class ComboSpace(urwid.WidgetWrap):
"""The actual menu-like space that comes down from the ComboText"""
def __init__(self,list,body,ui,show_first,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=[],attr=('body','focus'),use_enter=True,show_first=0):
"""
label : bit of text that preceeds the combobox. If it is "", then
ignore it
list : stuff to include in the combobox
body : parent widget
ui : the screen
row : where this object is to be found onscreen
show_first: index of the element in the list to pick first
"""
self.label = urwid.Text(label)
self.attr = attr
self.list = list
str,trash = self.label.get_text()
self.overlay = None
self.cbox = urwid.AttrWrap(SelText(' vvv'),attr[0],attr[1])
# Unicode will kill me sooner or later. ^_^
if label != '':
w = urwid.Columns([('fixed',len(str),self.label),self.cbox],dividechars=1)
else:
w = urwid.Columns([self.cbox])
self.__super.__init__(w)
# We need this to pick our keypresses
self.use_enter = use_enter
# Set the focus at the beginning to 0
self.show_first = show_first
def set_list(self,list):
self.list = list
def set_show_first(self,show_first):
self.show_first = show_first
def build_combobox(self,body,ui,row):
str,trash = self.label.get_text()
self.cbox = urwid.AttrWrap(SelText([self.list[self.show_first]+' vvv']),
self.attr[0],self.attr[1])
if str != '':
w = urwid.Columns([('fixed',len(str),self.label),self.cbox],dividechars=1)
self.overlay = self.ComboSpace(self.list,body,ui,self.show_first,
pos=(len(str)+1,row))
else:
w = urwid.Columns([self.cbox])
self.overlay = self.ComboSpace(self.list,body,ui,self.show_first,
pos=(0,row))
self.set_w(w)
self.body = body
self.ui = ui
# If we press space or enter, be a combo box!
def keypress(self,size,key):
activate = key == ' '
if self.use_enter:
activate = activate or key == 'enter'
if activate:
# Die if the user didn't prepare the combobox overlay
if self.overlay == None:
raise ComboBoxException('ComboBox must be built before use!')
retval = self.overlay.show(self.ui,self.body)
if retval != None:
self.cbox.set_w(SelText(retval+' vvv'))
return self._w.keypress(size,key)
# Most obvious thing ever. :-)
def selectable(self):
return True
# Return the index of the selected element
def get_selected(self):
wid,pos = self.overlay._listbox.get_focus()
return (wid,pos)
# Almost completely ripped from rbreu_filechooser.py:
# http://excess.org/urwid/browser/contrib/trunk/rbreu_menus.py
class Dialog(urwid.WidgetWrap):
"""
Creates a BoxWidget that displays a message
Attributes:
b_pressed -- Contains the label of the last button pressed or None if no
button has been pressed.
edit_text -- After a button is pressed, this contains the text the user
has entered in the edit field
"""
b_pressed = None
edit_text = None
_blank = urwid.Text("")
_edit_widget = None
_mode = None
def __init__(self, msg, buttons, attr, width, height, body, ):
"""
msg -- content of the message widget, one of:
plain string -- string is displayed
(attr, markup2) -- markup2 is given attribute attr
[markupA, markupB, ... ] -- list items joined together
buttons -- a list of strings with the button labels
attr -- a tuple (background, button, active_button) of attributes
width -- width of the message widget
height -- height of the message widget
body -- widget displayed beneath the message widget
"""
# Text widget containing the message:
msg_widget = urwid.Padding(urwid.Text(msg), 'center', width - 4)
# GridFlow widget containing all the buttons:
button_widgets = []
for button in buttons:
button_widgets.append(urwid.AttrWrap(
urwid.Button(button, self._action), attr[1], attr[2]))
button_grid = urwid.GridFlow(button_widgets, 12, 2, 1, 'center')
# Combine message widget and button widget:
widget_list = [msg_widget, self._blank, button_grid]
self._combined = urwid.AttrWrap(urwid.Filler(
urwid.Pile(widget_list, 2)), attr[0])
# This was the real thing I added to this class
self._linebox = urwid.LineBox(self._combined)
# Place the dialog widget on top of body:
# Width and height are increased to accomidate the linebox
overlay = urwid.Overlay(self._linebox, body, 'center', width+2,
'middle', height+2)
urwid.WidgetWrap.__init__(self, overlay)
def _action(self, button):
"""
Function called when a button is pressed.
Should not be called manually.
"""
self.b_pressed = button.get_label()
if self._edit_widget:
self.edit_text = self._edit_widget.get_edit_text()