Browse Source
new config script uses the very good urwid library. works on non ncurses platforms like windows, too. works with small screensmaster

64 changed files with 15458 additions and 4868 deletions
@ -1,52 +0,0 @@
|
||||
#!/usr/bin/python |
||||
|
||||
from .npyssafewrapper import wrapper, wrapper_basic |
||||
|
||||
from .npysThemeManagers import ThemeManager, disableColor, enableColor |
||||
from . import npysThemes as Themes |
||||
from .apNPSApplication import NPSApp |
||||
from .apNPSApplicationManaged import NPSAppManaged |
||||
from .proto_fm_screen_area import setTheme |
||||
from .fmForm import FormBaseNew, Form, TitleForm, TitleFooterForm, SplitForm |
||||
from .fmActionForm import ActionForm |
||||
from .fmFormWithMenus import FormWithMenus, ActionFormWithMenus, FormBaseNewWithMenus |
||||
from .fmPopup import Popup, MessagePopup, ActionPopup |
||||
from .fmFormMutt import FormMutt |
||||
|
||||
from .wgbutton import MiniButton |
||||
from .wgbutton import MiniButtonPress |
||||
from .wgbutton import MiniButton as Button |
||||
from .wgbutton import MiniButtonPress as ButtonPress |
||||
|
||||
from .wgtextbox import Textfield, FixedText |
||||
from .wgtitlefield import TitleText, TitleFixedText |
||||
from .wgpassword import PasswordEntry, TitlePassword |
||||
|
||||
from .wgslider import Slider, TitleSlider |
||||
|
||||
from .wgwidget import DummyWidget |
||||
|
||||
from .wgmultiline import MultiLine, Pager, TitleMultiLine |
||||
from .wgmultiselect import MultiSelect, TitleMultiSelect, MultiSelectFixed, TitleMultiSelectFixed |
||||
from .wgeditmultiline import MultiLineEdit |
||||
from .wgcombobox import ComboBox, TitleCombo |
||||
from .wgcheckbox import Checkbox, RoundCheckBox |
||||
from .wgFormControlCheckbox import FormControlCheckbox |
||||
from .wgautocomplete import TitleFilename, Filename, Autocomplete |
||||
from .muMenu import Menu |
||||
from .wgselectone import SelectOne, TitleSelectOne |
||||
from .wgdatecombo import DateCombo, TitleDateCombo |
||||
|
||||
from .wgmonthbox import MonthBox |
||||
from .wggrid import SimpleGrid |
||||
from .wggridcoltitles import GridColTitles |
||||
|
||||
|
||||
from .muNewMenu import NewMenu, MenuItem |
||||
from .wgNMenuDisplay import MenuDisplay, MenuDisplayScreen |
||||
|
||||
from .npyspmfuncs import CallSubShell |
||||
|
||||
|
||||
|
||||
|
@ -1,27 +0,0 @@
|
||||
#!/usr/bin/env python |
||||
import curses |
||||
import locale |
||||
import _curses |
||||
|
||||
from . import npyssafewrapper |
||||
|
||||
|
||||
class AlreadyOver(Exception): |
||||
pass |
||||
|
||||
class NPSApp(object): |
||||
_run_called = 0 |
||||
def main(self): |
||||
"""Overload this method to create your application""" |
||||
|
||||
def __remove_argument_call_main(self, screen): |
||||
# screen disgarded. |
||||
del screen |
||||
return self.main() |
||||
|
||||
def run(self, fork=None): |
||||
"""Run application. Calls Mainloop wrapped properly.""" |
||||
if fork is None: |
||||
return npyssafewrapper.wrapper(self.__remove_argument_call_main) |
||||
else: |
||||
return npyssafewrapper.wrapper(self.__remove_argument_call_main, fork=fork) |
@ -1,140 +0,0 @@
|
||||
#!/usr/bin/env python |
||||
# encoding: utf-8 |
||||
""" |
||||
NPSAppManaged.py |
||||
""" |
||||
from . import apNPSApplication |
||||
from . import fmForm |
||||
import weakref |
||||
|
||||
class NPSAppManaged(apNPSApplication.NPSApp): |
||||
"""This class is intended to make it easier to program applications with many screens: |
||||
|
||||
1. The programmer should not now select which 'Form' to display himself. Instead, he should set the NEXT_ACTIVE_FORM class variable. |
||||
See the registerForm method for details. |
||||
|
||||
Doing this will avoid accidentally exceeding the maximum recursion depth. Forms themselves should be placed under the management |
||||
of the class using the 'addForm' or 'addFormClass' method. |
||||
|
||||
2. Forms that are managed by this class can access a proxy to the parent application through their ".parentApp" attribute, which is |
||||
created by this class. |
||||
|
||||
3. a Optionally, Forms managed by this class may be given an .activate method, which will be called instead of their .edit loop |
||||
|
||||
b If not given an .activate method, any .afterEditing method which a form possesses will be called after .edit() has exited. |
||||
3b is the preferred method to change NEXT_ACTIVE_FORM |
||||
|
||||
4. The method onInMainLoop is called after each screen has exited. This can be overridden. |
||||
|
||||
5. This method should be able to see which screen was last active using the self._LAST_NEXT_ACTIVE_FORM attribute, which is only set |
||||
just before each screen is displayed. |
||||
|
||||
6. Unless you override the attribute STARTING_FORM, the first form to be called should be named 'MAIN' |
||||
|
||||
7. Do override the onStart and onCleanExit functions if you wish. |
||||
|
||||
""" |
||||
|
||||
STARTING_FORM = "MAIN" |
||||
|
||||
def __init__(self): |
||||
super(NPSAppManaged, self).__init__() |
||||
self.NEXT_ACTIVE_FORM = self.__class__.STARTING_FORM |
||||
self._LAST_NEXT_ACTIVE_FORM = None |
||||
self._Forms = {} |
||||
|
||||
def addFormClass(self, f_id, FormClass, *args, **keywords): |
||||
self._Forms[f_id] = [FormClass, args, keywords] |
||||
|
||||
def addForm(self, f_id, FormClass, *args, **keywords): |
||||
"""Create a form of the given class. f_id should be a string which will uniquely identify the form. *args will be passed to the Form constructor. |
||||
Forms created in this way are handled entirely by the NPSAppManaged class.""" |
||||
fm = FormClass( parentApp=self, *args, **keywords) |
||||
self.registerForm(f_id, fm) |
||||
return weakref.proxy(fm) |
||||
|
||||
def registerForm(self, f_id, fm): |
||||
"""f_id should be a string which should uniquely identify the form. fm should be a Form.""" |
||||
fm.parentApp = weakref.proxy(self) |
||||
self._Forms[f_id] = fm |
||||
|
||||
def removeForm(self, f_id): |
||||
del self._Forms[f_id].parentApp |
||||
del self._Forms[f_id] |
||||
|
||||
def getForm(self, name): |
||||
f = self._Forms[name] |
||||
try: |
||||
return weakref.proxy(f) |
||||
except: |
||||
return f |
||||
|
||||
def setNextForm(self, fmid): |
||||
"""Set the form that will be selected when the current one exits.""" |
||||
self.NEXT_ACTIVE_FORM = fmid |
||||
|
||||
def switchForm(self, fmid): |
||||
"""Immediately switch to the form specified by fmid.""" |
||||
self._THISFORM.editing = False |
||||
self.NEXT_ACTIVE_FORM = fmid |
||||
try: |
||||
self._THISFORM._widgets__[self._THISFORM.editw].editing = False |
||||
except: |
||||
pass |
||||
|
||||
|
||||
|
||||
def main(self): |
||||
"""Call this function to start your application. You should not override this function, but override the onInMainLoop, onStart and |
||||
onCleanExit methods instead, if you need to modify the application's behaviour. |
||||
|
||||
When this method is called, it will activate the form named by the class variable STARTING_FORM. By default this Form will be called |
||||
'MAIN'. |
||||
|
||||
When that form exits (user selecting an ok button or the like), the form named by object variable NEXT_ACTIVE_FORM will be activated. |
||||
|
||||
If NEXT_ACTIVE_FORM is None, the main() loop will exit. |
||||
|
||||
The form selected will be edited using it's .edit() method UNLESS it has been provided with an .activate() method, |
||||
in which case that method will be called instead. This is done so that the same class of form can be made |
||||
NPSAppManaged aware and have the normal non-NPSAppManaged edit loop. |
||||
|
||||
After a Form has been edited, if it has an .afterEditing method, this will be called, unless it was invoked with the activate() method. |
||||
A similar .beforeEditing method will be called if it exists before editing the form. Again, the presence of a .activate method |
||||
will override this behaviour. |
||||
|
||||
Note that NEXT_ACTIVE_FORM is a string that is the name of the form that was specified when .addForm or .registerForm was called. |
||||
""" |
||||
|
||||
self.onStart() |
||||
while self.NEXT_ACTIVE_FORM != "" and self.NEXT_ACTIVE_FORM != None: |
||||
self._LAST_NEXT_ACTIVE_FORM = self._Forms[self.NEXT_ACTIVE_FORM] |
||||
self.LAST_ACTIVE_FORM_NAME = self.NEXT_ACTIVE_FORM |
||||
try: |
||||
Fm, a, k = self._Forms[self.NEXT_ACTIVE_FORM] |
||||
self._THISFORM = Fm( parentApp = self, *a, **k ) |
||||
except TypeError: |
||||
self._THISFORM = self._Forms[self.NEXT_ACTIVE_FORM] |
||||
if hasattr(self._THISFORM, "activate"): |
||||
self._THISFORM.activate() |
||||
else: |
||||
if hasattr(self._THISFORM, "beforeEditing"): |
||||
self._THISFORM.beforeEditing() |
||||
self._THISFORM.edit() |
||||
if hasattr(self._THISFORM, "afterEditing"): |
||||
self._THISFORM.afterEditing() |
||||
|
||||
self.onInMainLoop() |
||||
self.onCleanExit() |
||||
|
||||
def onInMainLoop(self): |
||||
"""Called between each screen while the application is running. Not called before the first screen. Override at will""" |
||||
|
||||
def onStart(self): |
||||
"""Override this method to perform any initialisation.""" |
||||
pass |
||||
|
||||
def onCleanExit(self): |
||||
"""Override this method to perform any cleanup when application is exiting without error.""" |
||||
|
||||
|
@ -1,84 +0,0 @@
|
||||
#!/usr/bin/python |
||||
from . import fmForm |
||||
from . import wgwidget as widget |
||||
class ActionForm(fmForm.Form): |
||||
"""A form with OK and Cancel buttons. Users should override the on_ok and on_cancel methods.""" |
||||
CANCEL_BUTTON_BR_OFFSET = (2, 12) |
||||
|
||||
def set_up_exit_condition_handlers(self): |
||||
super(ActionForm, self).set_up_exit_condition_handlers() |
||||
self.how_exited_handers.update({ |
||||
widget.EXITED_ESCAPE: self.find_cancel_button |
||||
}) |
||||
|
||||
def find_cancel_button(self): |
||||
self.editw = len(self._widgets__)-2 |
||||
|
||||
def edit(self): |
||||
self.editing=True |
||||
if self.editw < 0: self.editw=0 |
||||
if self.editw > len(self._widgets__)-1: |
||||
self.editw = len(self._widgets__)-1 |
||||
|
||||
if not self._widgets__[self.editw].editable: self.find_next_editable() |
||||
# Add ok and cancel buttons. Will remove later |
||||
tmp_rely, tmp_relx = self.nextrely, self.nextrelx |
||||
|
||||
c_button_text = "Cancel" |
||||
cmy, cmx = self.curses_pad.getmaxyx() |
||||
cmy -= self.__class__.CANCEL_BUTTON_BR_OFFSET[0] |
||||
cmx -= len(c_button_text)+self.__class__.CANCEL_BUTTON_BR_OFFSET[1] |
||||
self.c_button = self.add_widget(self.__class__.OKBUTTON_TYPE, name=c_button_text, rely=cmy, relx=cmx, use_max_space=True) |
||||
c_button_postion = len(self._widgets__)-1 |
||||
self.c_button.update() |
||||
|
||||
my, mx = self.curses_pad.getmaxyx() |
||||
ok_button_text = "OK" |
||||
my -= self.__class__.OK_BUTTON_BR_OFFSET[0] |
||||
mx -= len(ok_button_text)+self.__class__.OK_BUTTON_BR_OFFSET[1] |
||||
self.ok_button = self.add_widget(self.__class__.OKBUTTON_TYPE, name=ok_button_text, rely=my, relx=mx, use_max_space=True) |
||||
ok_button_postion = len(self._widgets__)-1 |
||||
self.ok_button.update() |
||||
|
||||
self.display() |
||||
|
||||
while not self._widgets__[self.editw].editable: |
||||
self.editw += 1 |
||||
if self.editw > len(self._widgets__)-2: |
||||
self.editing = False |
||||
return False |
||||
|
||||
while self.editing: |
||||
if not self.ALL_SHOWN: self.on_screen() |
||||
self.while_editing() |
||||
self._widgets__[self.editw].edit() |
||||
self._widgets__[self.editw].display() |
||||
|
||||
self.handle_exiting_widgets(self._widgets__[self.editw].how_exited) |
||||
|
||||
if self.editw > len(self._widgets__)-1: self.editw = len(self._widgets__)-1 |
||||
if self.ok_button.value or self.c_button.value: |
||||
self.editing = False |
||||
|
||||
if self.ok_button.value: |
||||
self.edit_return_value = self.on_ok() |
||||
elif self.c_button.value: |
||||
self.edit_return_value = self.on_cancel() |
||||
|
||||
self.ok_button.destroy() |
||||
self.c_button.destroy() |
||||
del self._widgets__[ok_button_postion] |
||||
del self.ok_button |
||||
del self._widgets__[c_button_postion] |
||||
del self.c_button |
||||
self.nextrely, self.nextrelx = tmp_rely, tmp_relx |
||||
self.display() |
||||
self.editing = False |
||||
return self.edit_return_value |
||||
|
||||
def on_cancel(self): |
||||
pass |
||||
|
||||
def on_ok(self): |
||||
pass |
||||
|
@ -1,366 +0,0 @@
|
||||
#!/usr/bin/python |
||||
from . import proto_fm_screen_area |
||||
from . import wgwidget as widget |
||||
from . import wgbutton as button |
||||
import weakref |
||||
from . import npyspmfuncs as pmfuncs |
||||
#import Menu |
||||
import curses |
||||
from . import npysGlobalOptions |
||||
from . import fm_form_edit_loop as form_edit_loop |
||||
|
||||
class _FormBase(proto_fm_screen_area.ScreenArea, widget.InputHandler,): |
||||
BLANK_COLUMNS_RIGHT= 2 |
||||
BLANK_LINES_BASE = 2 |
||||
OK_BUTTON_BR_OFFSET = (2,6) |
||||
OKBUTTON_TYPE = button.MiniButton |
||||
DEFAULT_X_OFFSET = 2 |
||||
PRESERVE_SELECTED_WIDGET_DEFAULT = False # Preserve cursor location between displays? |
||||
FRAMED = True |
||||
def __init__(self, name=None, parentApp=None, framed=FRAMED, help=None, color='FORMDEFAULT', |
||||
widget_list=None, cycle_widgets=False, *args, **keywords): |
||||
super(_FormBase, self).__init__(*args, **keywords) |
||||
self.preserve_selected_widget = self.__class__.PRESERVE_SELECTED_WIDGET_DEFAULT |
||||
if parentApp: |
||||
try: |
||||
self.parentApp = weakref.proxy(parentApp) |
||||
except: |
||||
self.parentApp = parentApp |
||||
self.framed = framed |
||||
self.name=name |
||||
self.editing = False |
||||
## OLD MENU CODE REMOVED self.__menus = [] |
||||
self._clear_all_widgets() |
||||
|
||||
self.help = help |
||||
|
||||
self.color = color |
||||
|
||||
self.cycle_widgets = cycle_widgets |
||||
|
||||
self.set_up_handlers() |
||||
self.set_up_exit_condition_handlers() |
||||
if hasattr(self, 'initialWidgets'): |
||||
self.create_widgets_from_list(self.__class__.initialWidgets) |
||||
if widget_list: |
||||
self.create_widgets_from_list(widget_list) |
||||
self.create() |
||||
|
||||
def _clear_all_widgets(self, ): |
||||
self._widgets__ = [] |
||||
self._widgets_by_id = {} |
||||
self._next_w_id = 0 |
||||
self.nextrely = self.DEFAULT_NEXTRELY |
||||
self.nextrelx = self.DEFAULT_X_OFFSET |
||||
self.editw = 0 # Index of widget to edit. |
||||
|
||||
def create_widgets_from_list(self, widget_list): |
||||
# This code is currently experimental, and the API may change in future releases |
||||
# (npyscreen.TextBox, {'rely': 2, 'relx': 7, 'editable': False}) |
||||
for line in widget_list: |
||||
w_type = line[0] |
||||
keywords = line[1] |
||||
self.add_widget(w_type, **keywords) |
||||
|
||||
def set_value(self, value): |
||||
self.value = value |
||||
for _w in self._widgets__: |
||||
if hasattr(_w, 'when_parent_changes_value'): |
||||
_w.when_parent_changes_value() |
||||
|
||||
|
||||
def create(self): |
||||
"""Programmers should over-ride this in derived classes, creating widgets here""" |
||||
pass |
||||
|
||||
def set_up_handlers(self): |
||||
self.complex_handlers = [] |
||||
self.handlers = { |
||||
curses.KEY_F1: self.h_display_help, |
||||
"KEY_F(1)": self.h_display_help, |
||||
"!h": self.h_display_help, |
||||
"^L": self.h_display, |
||||
#curses.KEY_RESIZE: self.h_display, |
||||
} |
||||
|
||||
def set_up_exit_condition_handlers(self): |
||||
# What happens when widgets exit? |
||||
# each widget will set it's how_exited value: this should |
||||
# be used to look up the following table. |
||||
|
||||
self.how_exited_handers = { |
||||
widget.EXITED_DOWN: self.find_next_editable, |
||||
widget.EXITED_RIGHT: self.find_next_editable, |
||||
widget.EXITED_UP: self.find_previous_editable, |
||||
widget.EXITED_LEFT: self.find_previous_editable, |
||||
widget.EXITED_ESCAPE: self.do_nothing, |
||||
True: self.find_next_editable, # A default value |
||||
widget.EXITED_MOUSE: self.get_and_use_mouse_event, |
||||
False: self.do_nothing, |
||||
} |
||||
|
||||
def handle_exiting_widgets(self, condition): |
||||
self.how_exited_handers[condition]() |
||||
|
||||
def do_nothing(self, *args, **keywords): |
||||
pass |
||||
|
||||
def exit_editing(self, *args, **keywords): |
||||
self.editing = False |
||||
|
||||
def adjust_widgets(self): |
||||
"""This method can be overloaded by derived classes. It is called when editing any widget, as opposed to |
||||
the while_editing() method, which may only be called when moving between widgets. Since it is called for |
||||
every keypress, and perhaps more, be careful when selecting what should be done here.""" |
||||
|
||||
|
||||
def while_editing(self, *args, **keywords): |
||||
"""This function gets called during the edit loop, on each iteration |
||||
of the loop. It does nothing: it is here to make customising the loop |
||||
as easy as overriding this function. A proxy to the currently selected widget is |
||||
passed to the function.""" |
||||
|
||||
def on_screen(self): |
||||
# is the widget in editw on sreen at the moment? |
||||
# if not, alter screen so that it is. |
||||
|
||||
w = weakref.proxy(self._widgets__[self.editw]) |
||||
|
||||
max_y, max_x = self._max_physical() |
||||
|
||||
w_my, w_mx = w.calculate_area_needed() |
||||
|
||||
# always try to show the top of the screen. |
||||
self.show_from_y = 0 |
||||
self.show_from_x = 0 |
||||
|
||||
while w.rely + w_my -1 > self.show_from_y + max_y: |
||||
self.show_from_y += 1 |
||||
|
||||
while w.rely < self.show_from_y: |
||||
self.show_from_y -= 1 |
||||
|
||||
|
||||
while w.relx + w_mx -1 > self.show_from_x + max_x: |
||||
self.show_from_x += 1 |
||||
|
||||
while w.relx < self.show_from_x: |
||||
self.show_from_x -= 1 |
||||
|
||||
## REMOVING OLD MENU CODE def menuOfMenus(self, *args, **keywords): |
||||
## REMOVING OLD MENU CODE """DEPRICATED""" |
||||
## REMOVING OLD MENU CODE tmpmnu = Menu.Menu(name = "All Menus", show_aty=2, show_atx=2) |
||||
## REMOVING OLD MENU CODE #tmpmnu.before_item_select = self.display |
||||
## REMOVING OLD MENU CODE for mnu in self.__menus: |
||||
## REMOVING OLD MENU CODE text = "" |
||||
## REMOVING OLD MENU CODE if mnu.name: text += mnu.name |
||||
## REMOVING OLD MENU CODE for keypress in self.handlers.keys(): |
||||
## REMOVING OLD MENU CODE if self.handlers[keypress] == mnu.edit: |
||||
## REMOVING OLD MENU CODE if keypress: text += " (%s)" % keypress |
||||
## REMOVING OLD MENU CODE text += " >" |
||||
## REMOVING OLD MENU CODE tmpmnu.add_item(text, mnu.edit) |
||||
## REMOVING OLD MENU CODE tmpmnu.edit() |
||||
## REMOVING OLD MENU CODE |
||||
## REMOVING OLD MENU CODE def add_menu(self, menu=None, key=None, *args, **keywords): |
||||
## REMOVING OLD MENU CODE """DEPRICATED""" |
||||
## REMOVING OLD MENU CODE if menu is None: |
||||
## REMOVING OLD MENU CODE mu = Menu.Menu(*args, **keywords) |
||||
## REMOVING OLD MENU CODE self.__menus.append(mu) |
||||
## REMOVING OLD MENU CODE else: |
||||
## REMOVING OLD MENU CODE mu = menu |
||||
## REMOVING OLD MENU CODE self.__menus.append(mu) |
||||
## REMOVING OLD MENU CODE self.add_handlers({key: mu.edit}) |
||||
## REMOVING OLD MENU CODE return weakref.proxy(mu) |
||||
|
||||
|
||||
def h_display_help(self, input): |
||||
if self.help == None: return |
||||
if self.name: |
||||
help_name="%s Help" %(self.name) |
||||
else: help_name=None |
||||
curses.flushinp() |
||||
select.ViewText(self.help, name=help_name) |
||||
self.display() |
||||
return True |
||||
|
||||
def h_display(self, input): |
||||
self.curses_pad.redrawwin() |
||||
self.display() |
||||
|
||||
def get_and_use_mouse_event(self): |
||||
curses.beep() |
||||
|
||||
|
||||
def find_next_editable(self, *args): |
||||
if not self.editw == len(self._widgets__): |
||||
if not self.cycle_widgets: |
||||
r = list(range(self.editw+1, len(self._widgets__))) |
||||
else: |
||||
r = list(range(self.editw+1, len(self._widgets__))) + list(range(0, self.editw)) |
||||
for n in r: |
||||
if self._widgets__[n].editable and not self._widgets__[n].hidden: |
||||
self.editw = n |
||||
break |
||||
self.display() |
||||
|
||||
|
||||
def find_previous_editable(self, *args): |
||||
if not self.editw == 0: |
||||
# remember that xrange does not return the 'last' value, |
||||
# so go to -1, not 0! (fence post error in reverse) |
||||
for n in range(self.editw-1, -1, -1 ): |
||||
if self._widgets__[n].editable and not self._widgets__[n].hidden: |
||||
self.editw = n |
||||
break |
||||
|
||||
#def widget_useable_space(self, rely=0, relx=0): |
||||
# #Slightly misreports space available. |
||||
# mxy, mxx = self.lines-1, self.columns-1 |
||||
# return (mxy-1-rely, mxx-1-relx) |
||||
|
||||
def center_on_display(self): |
||||
my, mx = self._max_physical() |
||||
if self.lines < my: |
||||
self.show_aty = (my - self.lines) // 2 |
||||
else: |
||||
self.show_aty = 0 |
||||
|
||||
if self.columns < mx: |
||||
self.show_atx = (mx - self.columns) // 2 |
||||
else: |
||||
self.show_atx = 0 |
||||
|
||||
|
||||
def display(self, clear=False): |
||||
#APPLICATION_THEME_MANAGER.setTheme(self) |
||||
if curses.has_colors() and not npysGlobalOptions.DISABLE_ALL_COLORS: |
||||
color_attribute = self.theme_manager.findPair(self) |
||||
self.curses_pad.bkgdset(' ', color_attribute) |
||||
self.curses_pad.attron(color_attribute) |
||||
self.curses_pad.erase() |
||||
self.draw_form() |
||||
for w in self._widgets__: |
||||
if w.hidden: |
||||
w.clear() |
||||
else: |
||||
w.update(clear=clear) |
||||
|
||||
self.refresh() |
||||
|
||||
def draw_form(self): |
||||
if self.framed: |
||||
self.curses_pad.border() |
||||
|
||||
try: |
||||
if self.name: |
||||
_title = self.name[:(self.columns-4)] |
||||
self.curses_pad.addstr(0,1, ' '+str(_title)+' ') |
||||
except: |
||||
pass |
||||
|
||||
if self.help and self.editing: |
||||
try: |
||||
help_advert = " Help: F1 or M-h " |
||||
self.curses_pad.addstr( |
||||
0, self.curses_pad.getmaxyx()[1]-len(help_advert)-2, help_advert |
||||
) |
||||
except: |
||||
pass |
||||
|
||||
def add_widget(self, widgetClass, w_id=None, max_height=None, rely=None, relx=None, *args, **keywords): |
||||
"""Add a widget to the form. The form will do its best to decide on placing, unless you override it. |
||||
The form of this function is add_widget(WidgetClass, ....) with any arguments or keywords supplied to |
||||
the widget. The wigdet will be added to self._widgets__ |
||||
|
||||
It is safe to use the return value of this function to keep hold of the widget, since that is a weak |
||||
reference proxy, but it is not safe to keep hold of self._widgets__""" |
||||
|
||||
if rely is None: |
||||
rely = self.nextrely |
||||
if relx is None: |
||||
relx = self.nextrelx |
||||
|
||||
if max_height is False: |
||||
max_height = self.curses_pad.getmaxyx()[0] - rely - 1 |
||||
|
||||
_w = widgetClass(self, |
||||
rely=rely, |
||||
relx=relx, |
||||
max_height=max_height, |
||||
*args, **keywords) |
||||
|
||||
self.nextrely = _w.height + _w.rely |
||||
self._widgets__.append(_w) |
||||
w_proxy = weakref.proxy(_w) |
||||
if not w_id: |
||||
w_id = self._next_w_id |
||||
self._next_w_id += 1 |
||||
self._widgets_by_id[w_id] = w_proxy |
||||
|
||||
return w_proxy |
||||
|
||||
def get_widget(self, w_id): |
||||
return self._widgets_by_id[w_id] |
||||
|
||||
add = add_widget |
||||
|
||||
class FormBaseNew(form_edit_loop.FormNewEditLoop, _FormBase): |
||||
# use the new-style edit loop. |
||||
pass |
||||
|
||||
class Form(form_edit_loop.FormDefaultEditLoop, _FormBase, ): |
||||
#use the old-style edit loop |
||||
pass |
||||
|
||||
class TitleForm(Form): |
||||
"""A form without a box, just a title line""" |
||||
BLANK_LINES_BASE = 1 |
||||
DEFAULT_X_OFFSET = 1 |
||||
DEFAULT_NEXTRELY = 1 |
||||
BLANK_COLUMNS_RIGHT = 0 |
||||
OK_BUTTON_BR_OFFSET = (1,6) |
||||
#OKBUTTON_TYPE = button.MiniButton |
||||
#DEFAULT_X_OFFSET = 1 |
||||
def draw_form(self): |
||||
MAXY, MAXX = self.curses_pad.getmaxyx() |
||||
self.curses_pad.hline(0, 0, curses.ACS_HLINE, MAXX) |
||||
try: |
||||
if self.name: |
||||
self.curses_pad.addstr(0,1, ' '+str(self.name)+' ') |
||||
except: |
||||
pass |
||||
|
||||
if self.help and self.editing: |
||||
try: |
||||
help_advert = " Help: F1 or M-h " |
||||
self.curses_pad.addstr( |
||||
0, self.curses_pad.MAXX-len(help_advert)-2, help_advert |
||||
) |
||||
except: |
||||
pass |
||||
|
||||
class TitleFooterForm(TitleForm): |
||||
BLANK_LINES_BASE=1 |
||||
def draw_form(self): |
||||
MAXY, MAXX = self.curses_pad.getmaxyx() |
||||
|
||||
if self.editing: |
||||
self.curses_pad.hline(MAXY-1, 0, curses.ACS_HLINE, |
||||
MAXX - self.__class__.OK_BUTTON_BR_OFFSET[1] - 1) |
||||
else: |
||||
self.curses_pad.hline(MAXY-1, 0, curses.ACS_HLINE, MAXX-1) |
||||
|
||||
super(TitleFooterForm, self).draw_form() |
||||
|
||||
class SplitForm(Form): |
||||
"""Just the same as the Title Form, but with a horizontal line""" |
||||
def draw_form(self): |
||||
MAXY, MAXX = self.curses_pad.getmaxyx() |
||||
super(SplitForm, self).draw_form() |
||||
self.curses_pad.hline(MAXY//2-1, 1, curses.ACS_HLINE, MAXX-2) |
||||
|
||||
def get_half_way(self): |
||||
return self.curses_pad.getmaxyx()[0] // 2 |
||||
|
||||
|
||||
|
@ -1,40 +0,0 @@
|
||||
#/usr/bin/env python |
||||
import curses |
||||
from . import fmForm |
||||
from . import fmFormWithMenus |
||||
from . import wgtextbox |
||||
from . import wgmultiline |
||||
#import grid |
||||
#import editmultiline |
||||
|
||||
|
||||
class FormMutt(fmForm.FormBaseNew): |
||||
BLANK_LINES_BASE = 0 |
||||
BLANK_COLUMNS_RIGHT = 0 |
||||
DEFAULT_X_OFFSET = 2 |
||||
FRAMED = False |
||||
MAIN_WIDGET_CLASS = wgmultiline.MultiLine |
||||
STATUS_WIDGET_CLASS = wgtextbox.Textfield |
||||
COMMAND_WIDGET_CLASS= wgtextbox.Textfield |
||||
#MAIN_WIDGET_CLASS = grid.SimpleGrid |
||||
#MAIN_WIDGET_CLASS = editmultiline.MultiLineEdit |
||||
def __init__(self, cycle_widgets = True, *args, **keywords): |
||||
super(FormMutt, self).__init__(cycle_widgets=cycle_widgets, *args, **keywords) |
||||
|
||||
|
||||
def draw_form(self): |
||||
MAXY, MAXX = self.lines, self.columns #self.curses_pad.getmaxyx() |
||||
self.curses_pad.hline(0, 0, curses.ACS_HLINE, MAXX-1) |
||||
self.curses_pad.hline(MAXY-2, 0, curses.ACS_HLINE, MAXX-1) |
||||
|
||||
def create(self): |
||||
MAXY, MAXX = self.lines, self.columns |
||||
self.wStatus1 = self.add(self.__class__.STATUS_WIDGET_CLASS, rely=0, relx=0, editable=False, ) |
||||
self.wMain = self.add(self.__class__.MAIN_WIDGET_CLASS, rely=1, relx=0, max_height = -2, ) |
||||
self.wStatus2 = self.add(self.__class__.STATUS_WIDGET_CLASS, rely=MAXY-2, relx=0, editable=False, ) |
||||
self.wCommand = self.add(self.__class__.COMMAND_WIDGET_CLASS, rely = MAXY-1, relx=0,) |
||||
self.wStatus1.important = True |
||||
self.wStatus2.important = True |
||||
self.nextrely = 2 |
||||
|
||||
|
@ -1,66 +0,0 @@
|
||||
#!/usr/bin/env python |
||||
# encoding: utf-8 |
||||
|
||||
from . import fmForm |
||||
from . import fmActionForm |
||||
from . import wgNMenuDisplay |
||||
|
||||
class FormBaseNewWithMenus(fmForm.FormBaseNew, wgNMenuDisplay.HasMenus): |
||||
"""The FormBaseNew class, but with a handling system for menus as well. See the HasMenus class for details.""" |
||||
def __init__(self, *args, **keywords): |
||||
super(FormBaseNewWithMenus, self).__init__(*args, **keywords) |
||||
self.initialize_menus() |
||||
|
||||
def display_menu_advert_at(self): |
||||
return self.lines-1, 1 |
||||
|
||||
def draw_form(self): |
||||
super(FormBaseNewWithMenus, self).draw_form() |
||||
menu_advert = " " + self.__class__.MENU_KEY + ": Menu " |
||||
y, x = self.display_menu_advert_at() |
||||
self.curses_pad.addnstr(y, x, menu_advert, self.columns - x - 1) |
||||
|
||||
|
||||
class FormWithMenus(fmForm.Form, wgNMenuDisplay.HasMenus): |
||||
"""The Form class, but with a handling system for menus as well. See the HasMenus class for details.""" |
||||
def __init__(self, *args, **keywords): |
||||
super(FormWithMenus, self).__init__(*args, **keywords) |
||||
self.initialize_menus() |
||||
|
||||
def display_menu_advert_at(self): |
||||
return self.lines-1, 1 |
||||
|
||||
def draw_form(self): |
||||
super(FormWithMenus, self).draw_form() |
||||
menu_advert = " " + self.__class__.MENU_KEY + ": Menu " |
||||
y, x = self.display_menu_advert_at() |
||||
self.curses_pad.addnstr(y, x, menu_advert, self.columns - x - 1) |
||||
|
||||
# The following class does not inherit from FormWithMenus and so some code is duplicated. |
||||
# The pig is getting to inherit edit() from ActionForm, but draw_form from FormWithMenus |
||||
class ActionFormWithMenus(fmActionForm.ActionForm, wgNMenuDisplay.HasMenus): |
||||
def __init__(self, *args, **keywords): |
||||
super(ActionFormWithMenus, self).__init__(*args, **keywords) |
||||
self.initialize_menus() |
||||
def display_menu_advert_at(self): |
||||
return self.lines-1, 1 |
||||
|
||||
def draw_form(self): |
||||
super(ActionFormWithMenus, self).draw_form() |
||||
menu_advert = " " + self.__class__.MENU_KEY + ": Menu " |
||||
y, x = self.display_menu_advert_at() |
||||
self.curses_pad.addnstr(y, x, menu_advert, self.columns - x - 1) |
||||
|
||||
class SplitFormWithMenus(FormWithMenus): |
||||
"""Just the same as the Title Form, but with a horizontal line""" |
||||
def draw_form(self): |
||||
MAXY, MAXX = self.curses_pad.getmaxyx() |
||||
super(SplitFormWithMenus, self).draw_form() |
||||
self.curses_pad.hline(MAXY//2-1, 1, curses.ACS_HLINE, MAXX-2) |
||||
|
||||
def get_half_way(self): |
||||
return self.curses_pad.getmaxyx()[0] // 2 |
||||
|
||||
|
||||
|
||||
|
@ -1,31 +0,0 @@
|
||||
#!/usr/bin/python |
||||
# encoding: utf-8 |
||||
|
||||
from . import fmForm |
||||
from . import fmActionForm |
||||
import curses |
||||
|
||||
|
||||
class Popup(fmForm.Form): |
||||
def __init__(self, |
||||
lines = 12, |
||||
columns=60, |
||||
minimum_lines=None, |
||||
minimum_columns=None, |
||||
*args, **keywords): |
||||
super(Popup, self).__init__(lines = lines, columns=columns, |
||||
*args, **keywords) |
||||
self.show_atx = 10 |
||||
self.show_aty = 2 |
||||
|
||||
class ActionPopup(fmActionForm.ActionForm, Popup): |
||||
def __init__(self, *args, **keywords): |
||||
Popup.__init__(self, *args, **keywords) |
||||
|
||||
class MessagePopup(Popup): |
||||
def __init__(self, *args, **keywords): |
||||
import multiline |
||||
super(MessagePopup, self).__init__(*args, **keywords) |
||||
self.TextWidget = self.add(multiline.Pager, scroll_exit=True, max_height=self.widget_useable_space()[0]-2) |
||||
|
||||
|
@ -1,100 +0,0 @@
|
||||
#!/usr/bin/env python |
||||
# encoding: utf-8 |
||||
""" |
||||
form_edit_loop.py |
||||
|
||||
Created by Nicholas Cole on 2008-03-31. |
||||
Copyright (c) 2008 __MyCompanyName__. All rights reserved. |
||||
""" |
||||
|
||||
import sys |
||||
import os |
||||
import weakref |
||||
|
||||
class FormNewEditLoop(object): |
||||
"Edit Fields .editing = False" |
||||
def pre_edit_loop(self): |
||||
pass |
||||
def post_edit_loop(self): |
||||
pass |
||||
def _during_edit_loop(self): |
||||
pass |
||||
|
||||
def edit_loop(self): |
||||
self.editing = True |
||||
self.display() |
||||
while not self._widgets__[self.editw].editable: |
||||
self.editw += 1 |
||||
if self.editw > len(self._widgets__)-1: |
||||
self.editing = False |
||||
return False |
||||
|
||||
while self.editing: |
||||
if not self.ALL_SHOWN: self.on_screen() |
||||
self.while_editing(weakref.proxy(self._widgets__[self.editw])) |
||||
self._during_edit_loop() |
||||
if not self.editing: |
||||
break |
||||
self._widgets__[self.editw].edit() |
||||
self._widgets__[self.editw].display() |
||||
|
||||
self.handle_exiting_widgets(self._widgets__[self.editw].how_exited) |
||||
|
||||
if self.editw > len(self._widgets__)-1: self.editw = len(self._widgets__)-1 |
||||
|
||||
def edit(self): |
||||
self.pre_edit_loop() |
||||
self.edit_loop() |
||||
self.post_edit_loop() |
||||
|
||||
class FormDefaultEditLoop(object): |
||||
def edit(self): |
||||
"""Edit the fields until the user selects the ok button added in the lower right corner. Button will |
||||
be removed when editing finishes""" |
||||
self.editing=True |
||||
if self.editw < 0: self.editw=0 |
||||
if self.editw > len(self._widgets__)-1: |
||||
self.editw = len(self._widgets__)-1 |
||||
if not self.preserve_selected_widget: |
||||
self.editw = 0 |
||||
# Add ok button. Will remove later |
||||
tmp_rely, tmp_relx = self.nextrely, self.nextrelx |
||||
my, mx = self.curses_pad.getmaxyx() |
||||
ok_button_text = "OK" |
||||
my -= self.__class__.OK_BUTTON_BR_OFFSET[0] |
||||
mx -= len(ok_button_text)+self.__class__.OK_BUTTON_BR_OFFSET[1] |
||||
self.ok_button = self.add_widget(self.__class__.OKBUTTON_TYPE, name=ok_button_text, rely=my, relx=mx, use_max_space=True) |
||||
ok_button_postion = len(self._widgets__)-1 |
||||
self.ok_button.update() |
||||
if not self._widgets__[self.editw].editable: self.find_next_editable() |
||||
|
||||
self.display() |
||||
|
||||
while not self._widgets__[self.editw].editable: |
||||
self.editw += 1 |
||||
if self.editw > len(self._widgets__)-1: |
||||
self.editing = False |
||||
return False |
||||
|
||||
while self.editing: |
||||
if not self.ALL_SHOWN: self.on_screen() |
||||
self.while_editing(weakref.proxy(self._widgets__[self.editw])) |
||||
if not self.editing: |
||||
break |
||||
self._widgets__[self.editw].edit() |
||||
self._widgets__[self.editw].display() |
||||
|
||||
self.handle_exiting_widgets(self._widgets__[self.editw].how_exited) |
||||
|
||||
if self.editw > len(self._widgets__)-1: self.editw = len(self._widgets__)-1 |
||||
if self.ok_button.value: |
||||
self.editing = False |
||||
|
||||
self.ok_button.destroy() |
||||
del self._widgets__[ok_button_postion] |
||||
del self.ok_button |
||||
self.nextrely, self.nextrelx = tmp_rely, tmp_relx |
||||
self.display() |
||||
|
||||
self.editing = False |
||||
self.erase() |
@ -1,70 +0,0 @@
|
||||
#!/usr/bin/python |
||||
# encoding: utf-8 |
||||
|
||||
import sys |
||||
import os |
||||
from . import wgmultiline |
||||
from . import fmForm |
||||
import weakref |
||||
|
||||
|
||||
class Menu(object): |
||||
"This class is obsolete and Depricated. Use NewMenu instead." |
||||
|
||||
def __init__(self, name=None, show_atx=None, show_aty=None): |
||||
self.__menu_items = [] |
||||
self.name = name |
||||
self.__show_atx = show_atx |
||||
self.__show_aty = show_aty |
||||
|
||||
def before_item_select(self): |
||||
pass |
||||
|
||||
def add_item(self, text, func): |
||||
self.__menu_items.append((text, func)) |
||||
|
||||
def set_menu(self, pairs): |
||||
"""Pass in a list of pairs of text labels and functions""" |
||||
self.__menu_items = [] |
||||
for pair in pairs: |
||||
self.add_item(pair[0], pair[1]) |
||||
|
||||
def edit(self, *args, **keywords): |
||||
"""Display choice to user, execute function associated""" |
||||
|
||||
menu_text = [x[0] for x in self.__menu_items] |
||||
|
||||
longest_text = 0 |
||||
#Slightly different layout if we are showing a title |
||||
if self.name: longest_text=len(self.name)+2 |
||||
for item in menu_text: |
||||
if len(item) > longest_text: |
||||
longest_text = len(item) |
||||
|
||||
height = len(menu_text) |
||||
if self.name: |
||||
height +=3 |
||||
else: |
||||
height +=2 |
||||
|
||||
if height > 14: |
||||
height = 13 < |