diff options
Diffstat (limited to 'rapid/ValidatedEntry.py')
-rw-r--r-- | rapid/ValidatedEntry.py | 383 |
1 files changed, 0 insertions, 383 deletions
diff --git a/rapid/ValidatedEntry.py b/rapid/ValidatedEntry.py deleted file mode 100644 index cb453f4..0000000 --- a/rapid/ValidatedEntry.py +++ /dev/null @@ -1,383 +0,0 @@ -# Copyright (c) 2006, Daniel J. Popowich -# -# Permission is hereby granted, free of charge, to any person -# obtaining a copy of this software and associated documentation files -# (the "Software"), to deal in the Software without restriction, -# including without limitation the rights to use, copy, modify, merge, -# publish, distribute, sublicense, and/or sell copies of the Software, -# and to permit persons to whom the Software is furnished to do so, -# subject to the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# -# Send bug reports and contributions to: -# -# dpopowich AT astro dot umass dot edu -# - -''' -ValidatedEntry.py - -Provides ValidatedEntry, a subclass of gtk.Entry which validates -input. - -Usage: create an instance of ValidatedEntry, specifying the function -to validate input. E.g.: - - : def money(text): - : "validate input to be monetary value" - : ... - : - : money_entry = ValidatedEntry(money) - -Validation functions must accept one argument, the text to be -validated, and must return one of: - - 1: the input is valid. - 0: the input is invalid and should not be displayed. - -1: the input is partially valid and will be displayed (and by - default with a different background color). - -Three module-level variables are defined for the convenience of -validation function writers: VALID (1), INVALID (0), PARTIAL (-1). - -There is one public method, isvalid(), which will return True if the -current text is valid. - -Note: care should be taken when implementing validation functions to -allow empty strings to be VALID or at least PARTIAL. An empty string -should never be INVALID. - -Note: the hooks for calling the validation function are implemented by -connecting the object to handlers for the gtk.Editable "insert-text" -and "delete-text" signals. These handlers are connected to instances -in the constructor, so will, by default, be called before other -handlers connected to the widgets for "*-text" signals. When input is -INVALID, stop_emission() is called, so later handlers for "*-text" -signals will not be called. - -See the doc string for ValidatedEntry.__init__ for more details. - -''' - -import pygtk -pygtk.require('2.0') - -import gtk -import gtk.gdk - -if gtk.gtk_version < (2, 8): - import warnings - - msg ='''This module was developed and tested with version 2.8.9 of gtk. -You are using version %d.%d.%d. Your milage may vary''' % gtk.gtk_version - warnings.warn(msg) - -# major, minor, patch -version = 1, 0, 4 - -PARTIAL, INVALID, VALID = range(-1,2) - -class ValidatedEntry(gtk.Entry): - - white = gtk.gdk.color_parse('white') - yellow = gtk.gdk.color_parse('yellow') - - def __init__(self, valid_func, - max=0, - use_bg=True, valid_bg=white, partial_bg=yellow, - error_func=None): - ''' - Create instance of validating gtk.Entry. - - valid_func: the function to validate input. See module doc - string for details. - - max: passed to gtk.Entry constructor. (default: 0) - - use_bg: if True (the default) set the base color of the - widget to indicate validity; see valid_bg and partial_bg. - - valid_bg: a gtk.gdk.Color; the base color of the widget when - the input is valid. (default: white) - - partial_bg: a gtk.gdk.Color; the base color of the widget when - the input is partially valid. (default: yellow) - - error_func: a function to call (with no arguments) when - valid_func returns INVALID. If None (the default) - the default action will be to emit a short beep. - ''' - - assert valid_func('') != INVALID, 'valid_func cannot return INVALID for an empty string' - - gtk.Entry.__init__(self, max) - - self.__valid_func = valid_func - self.__use_bg = use_bg - self.__valid_bg = valid_bg - self.__partial_bg = partial_bg - self.__error_func = (error_func or - gtk.gdk.display_get_default().beep) - - self.connect('insert-text', self.__insert_text_cb) - self.connect('delete-text', self.__delete_text_cb) - - # bootstrap with an empty string (so the box will appear with - # the partial_bg if an empty string is PARTIAL) - self.insert_text('') - - def isvalid(self): - return self.__isvalid - - def __insert_text_cb(self, entry, text, length, position): - 'callback for "insert-text" signal' - - # generate what the new text will be - text = text[:length] - pos = self.get_position() - old = self.get_text() - new = old[:pos] + text + old[pos:] - - # validate the new text - self.__validate(new, 'insert-text') - - def __delete_text_cb(self, entry, start, end): - 'callback for "delete-text" signal' - - # generate what the new text will be - old = self.get_text() - new = old[:start] + old[end:] - - # validate the new text - self.__validate(new, 'delete-text') - - def __validate(self, text, signal): - 'calls the user-provided validation function' - - # validate - r = self.__valid_func(text) - if r == VALID: - self.__isvalid = True - if self.__use_bg: - self.modify_base(gtk.STATE_NORMAL, self.__valid_bg) - elif r == PARTIAL: - self.__isvalid = False - if self.__use_bg: - self.modify_base(gtk.STATE_NORMAL, self.__partial_bg) - else: - # don't set self.__isvalid: since we're not displaying the - # new value, the validity should be whatever it was before - self.stop_emission(signal) - self.__error_func() - - -###################################################################### -# -# Sample validation functions to use with ValidatedEntry -# -###################################################################### - -import re - - -# STRING (non-empty after stripping) -def v_nonemptystring(value): - ''' - VALID: non-empty string after stripping whitespace - PARTAL: empty or all whitespace - INVALID: N/A - ''' - if value.strip(): - return VALID - return PARTIAL - -# INT -def v_int(value): - ''' - VALID: any postive or negative integer - PARTAL: empty or leading "-" - INVALID: non-numeral - ''' - v = value.strip() - if not v or v == '-': - return PARTIAL - try: - int(value) - return VALID - except: - return INVALID - -# FLOAT -def v_float(value): - ''' - VALID: any postive or negative floating point - PARTAL: empty or leading "-", "." - INVALID: non-numeral - ''' - v = value.strip() - if not v or v in ('-', '.', '-.'): - return PARTIAL - try: - float(value) - return VALID - except: - return INVALID - - -# ISBN -_isbnpartial = re.compile('[0-9]{0,9}[0-9xX]?$') -def v_isbn(v): - - '''Validate ISBN input. - - From the isbn manual, section 4.4: - - The check digit is the last digit of an ISBN. It is calculated on - a modulus 11 with weights 10-2, using X in lieu of 10 where ten - would occur as a check digit. This means that each of the first - nine digits of the ISBN -- excluding the check digit itself -- is - multiplied by a number ranging from 10 to 2 and that the resulting - sum of the products, plus the check digit, must be divisible by 11 - without a remainder.''' - - - if _isbnpartial.match(v): - # isbn is ten characters in length - if len(v) < 10: - return PARTIAL - - s = 0 - - for i, c in enumerate(v): - s += (c in 'xX' and 10 or int(c)) * (10 - i) - - if s % 11 == 0: - return VALID - - return INVALID - -# MONEY -# re for (possibly negative) money -_money_re = re.compile('-?\d*(\.\d{1,2})?$') -# validation function for money -def v_money(value): - ''' - VALID: any postive or negative floating point with at most two - digits after the decimal point. - PARTAL: empty or leading "-", "." - INVALID: non-numeral or more than two digits after the decimal - point. - ''' - if not value or value == '-' or value[-1] == '.': - return PARTIAL - - if _money_re.match(value): - return VALID - - return INVALID - -# PHONE -# the characters in a phone number -_phonechars = re.compile('[- 0-9]*$') -# valid phone number: [AC +]EXT-LINE -_phone = re.compile('([2-9][0-8][0-9]\s+)?[2-9][0-9]{2}-[0-9]{4}$') -def v_phone(value): - ''' - VALID: any phone number of the form: EXT-LINE -or- AC EXT-LINE. - PARTAL: any characters that make up a valid #. - INVALID: characters that are not used in a phone #. - ''' - if _phone.match(value): - return VALID - if _phonechars.match(value): - return PARTIAL - return INVALID - -def empty_valid(vfunc): - - ''' - empty_valid is a factory function returning a validation function. - All of the validation functions in this module return PARTIAL for - empty strings which, in effect, forces non-empty input. There may - be a case where, e.g., you want money input to be optional, but - v_money will not consider empty input VALID. Instead of writing - another validation function you can instead use empty_valid(). By - wrapping a validation function with empty_valid(), input (after - stripping), if empty, will be considered VALID. E.g.: - - ventry = ValidatedEntry(empty_valid(v_money)) - - It is recommended that all your validation functions treat empty - input as PARTIAL, for consistency across all validation functions - and for use with empty_valid(). - ''' - - def validate(value): - if not value.strip(): - return VALID - return vfunc(value) - - return validate - - -def bounded(vfunc, conv, minv=None, maxv=None): - - ''' - bounded is a factory function returning a validation function - providing bounded input. E.g., you may want an entry that accepts - integers, but within a range, say, a score on a test graded in - whole numbers from 0 to 100: - - score_entry = ValidatedEntry(bounded(v_int, int, 0, 100)) - - Arguments: - - vfunc: A validation function. - conv: A callable that accepts a string argument (the text in - the entry) and returns a value to be compared to minv - and maxv. - minv: None or a value of the same type returned by conv. If - None, there is no minimum value enforced. If a value, - it will be the minimum value considered VALID. - maxv: None or a value of the same type returned by conv. If - None, there is no maximum value enforced. If a value, - it will be the maximum value considered VALID. - - One or both of minv/maxv must be specified. - - The function returned will call vfunc on entry input and if vfunc - returns VALID, the input will be converted by conv and compared to - minv/maxv. If the converted value is within the bounds of - minv/maxv then VALID will be returned, else PARTIAL will be - returned. - - ''' - - assert minv is not None or maxv is not None, \ - 'One of minv/maxv must be specified' - - def F(value): - - r = vfunc(value) - if r == VALID: - v = conv(value) - if minv is not None and v < minv: - return PARTIAL - if maxv is not None and v > maxv: - return PARTIAL - return r - - return F - - |