Home | Trees | Indices | Help |
|
---|
|
1 # This program is free software: you can redistribute it and/or modify 2 # it under the terms of the GNU General Public License as published by 3 # the Free Software Foundation, either version 3 of the License, or 4 # (at your option) any later version. 5 # 6 # This program is distributed in the hope that it will be useful, 7 # but WITHOUT ANY WARRANTY; without even the implied warranty of 8 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 9 # GNU General Public License for more details. 10 # 11 # You should have received a copy of the GNU General Public License 12 # along with this program. If not, see <http://www.gnu.org/licenses/>. 13 14 # The base Converter class. Not to be used directly. 15 # For a commented example on how to write general converter modules, see the 16 # file BaseConverter.py. But first, please, read below if a RatioConverter isn't 17 # well suitable for your desired task. 1820 """The base class for the converters. The converters look after maintaining 21 the list of currently shown values - initialising, accepting keyboard input, 22 etc..""" 23 24 # the name of the class 25 __name__ = 'Converter' 26 # a short description to be used for selecting the converter 27 __title__ = 'Base' 28 29 # the number of fields shown on the display between 2 and 4 30 num_fields = 0 31 # field captions up to 4 chars long 32 field_names = [] 33 # zero-based index of field having input focus 34 active_field = 0 35 # the list of currently shown 'values'. They should always be strings. 36 values = [] 37 # replace: True = replace all the input by next keypress 38 replace = True 39 40 # initialize the list of values and fill it with defaults (strings!). 41 # Override this if you don't want then be '0's.141 142 143 # A subclass of Converter representing numerical converters whose field are 144 # bound by a simple linear relation. It cares about float value input and output 145 # and conversion, so the developer who wants to use it doesn't need to provide 146 # any functions. Besides the __anything__, num_fields and field_names variables, 147 # he must only provide a list describing desired ratios (see below). 148 # Not to be used directly. See LengthConverter for a commented example. 14943 self.values = [] 44 for i in range(self.num_fields): 45 self.values.append('0') 46 self.active_field = 04749 """If accepted, appends the pressed key to the value in the currently 50 active field.""" 51 translate_dict = {'comma': '.', 'period': '.', 'Add': '+', 'plus': '+', 52 'Subtract': '-', 'minus': '-'} 53 if key[:3] == 'KP_': 54 key = key[3:] # keys from numerical keypad come as digits 55 if translate_dict.has_key(key): 56 key = translate_dict[key] 57 if key == 'BackSpace': # try to guess :-) 58 self.values[self.active_field] = self.values[self.active_field][:-1] 59 elif key == 'Escape': # clean the field 60 self.values[self.active_field] = '' 61 elif key == 'Down': # move field focus 62 if self.active_field < self.num_fields - 1: 63 self.active_field += 1 64 self.replace = True # after a change, don't append next pressed 65 return True # key but start over 66 return False 67 elif key == 'Up': 68 if self.active_field > 0: 69 self.active_field -= 1 70 self.replace = True 71 return True 72 return False 73 elif key == 'Tab': 74 self.active_field += 1 75 self.active_field %= self.num_fields 76 self.replace = True 77 return True 78 else: # leave other keys unchanged 79 if not self.filter_key(key): 80 return False 81 if self.replace: 82 self.values[self.active_field] = key 83 # limit input length to 10 characters 84 elif len(self.values[self.active_field]) < 10: 85 self.values[self.active_field] = \ 86 self.values[self.active_field] + key 87 self.replace = False 88 self.neaten_input() 89 self.convert() 90 return True91 92 # You can use this function instead of str or fixed-width % - it leaves 93 # 3 digits after the decimal point for floats, and no decimal part if the 94 # number is integer. 95 # Serves good if the same converter can be used for both ints ant floats, 96 # so that the user doesn't get '1.000' when not necessary, also for showing 97 # '0' instead of '0.000' in all cases. 103 104 # Overridable functions: 105 106 # neaten_input: see the docstring 107 # Return value: none 108 # If you don't want such function, override it in your converter with pass. 109 # If you override it by something more complicated, be careful not to modify 110 # the current value so that it breaks the input.112 """Replaces an empty value with '0' and again removes leading '0' in 113 a non-empty string.""" 114 # This version is aware of the possibility of negative input values, 115 # but you must allow + and - keys in filter_key and avoid an error when 116 # the input is '-'. See TemperatureConverter for an example. 117 if self.values[self.active_field] == '' or \ 118 self.values[self.active_field][-1] == '+': 119 self.values[self.active_field] = '0' 120 elif self.values[self.active_field][-1] == '-': 121 self.values[self.active_field] = '-' 122 if len(self.values[self.active_field]) > 1 and \ 123 self.values[self.active_field][0] == '0': 124 self.values[self.active_field] = self.values[self.active_field][1:]125 126 # filter_key: decides if pressed key can be appended to current value. 127 # "key" is the GDK name of the key pressed by user 128 # Return value: True - accept key, False - reject it. 129 # There is no way to modify the value of key. 130 # Be prepared for various "keys", e.g., 'apostrophe' must not match 'a'. 134 135 # convert: actualizes field values to reflect input 136 # Return value: none 137 # Active value can be modified, but not so that it breaks the input.151 """A base class of converters having linear dependances between their 152 fields.""" 153 154 __name__ = 'RatioConverter' 155 __title__ = 'Base / Ratio' 156 157 # The list of relative weights of the individual fields. The length of this 158 # list must be equal to num_fields. The ratio between two fields will be 159 # inverse to the ratio of corresponding entries in this list. For example, 160 # see LengthConverter. One may ask whether not to better use relative 161 # ratios, i.e., ratios between fields = ratio between entries, the answer is 162 # that this approach is more intuitive. You would set 1 for some unit and 163 # 1000 for the corresponding kilo-unit this way. 164 # The above implies that the values in this list are relative to whichever 165 # one you would choose, e.g., [10, 5, 1] (will be converted to float) is 166 # equivalent to [2.0, 1.0, 0.2]. Actually, integer (exact) values are 167 # preferred if they reflect the logic of the conversion. 168 weights = [] 169189 # Note: if you don't like the Converter.str() function used above which 190 # tries to always display integers as integers, you can provide your own, 191 # e.g., def str(self, val): return '%.3f' % val 192171 # Accept digits 172 if key.isdigit(): 173 return True 174 # Also accept a decimal point if there is no one yet 175 elif key == '.': 176 return not ('.' in self.values[self.active_field]) 177 else: 178 return False179181 # A multiply-then-divide approach is used to help avoiding little 182 # inaccuracies arising in operations like (3/10)*100. 183 val = float(self.values[self.active_field]) \ 184 * self.weights[self.active_field] 185 for i in range(self.num_fields): 186 if i == self.active_field: 187 continue 188 self.values[i] = self.str(val / float(self.weights[i]))
Home | Trees | Indices | Help |
|
---|
Generated by Epydoc 3.0.1 on Wed Jan 4 16:58:27 2012 | http://epydoc.sourceforge.net |