Package Gnumed :: Package wxpython :: Module gmDateTimeInput
[frames] | no frames]

Source Code for Module Gnumed.wxpython.gmDateTimeInput

  1  """GNUmed date input widget 
  2   
  3  All GNUmed date input should happen via classes in 
  4  this module. Initially this is just a plain text box 
  5  but using this throughout GNUmed will allow us to 
  6  transparently add features. 
  7   
  8  @copyright: author(s) 
  9  """ 
 10  #============================================================================== 
 11  __version__ = "$Revision: 1.66 $" 
 12  __author__  = "K. Hilbert <Karsten.Hilbert@gmx.net>" 
 13  __licence__ = "GPL (details at http://www.gnu.org)" 
 14   
 15  import re, string, sys, time, datetime as pyDT, logging 
 16   
 17   
 18  import mx.DateTime as mxDT, wx 
 19   
 20   
 21  # GNUmed specific 
 22  if __name__ == '__main__': 
 23          sys.path.insert(0, '../../') 
 24  from Gnumed.pycommon import gmMatchProvider, gmDateTime 
 25  from Gnumed.wxpython import gmPhraseWheel, gmGuiHelpers 
 26   
 27  _log = logging.getLogger('gm.ui') 
 28   
 29  #============================================================ 
30 -class cMatchProvider_FuzzyTimestamp(gmMatchProvider.cMatchProvider):
31 - def __init__(self):
32 self.__allow_past = 1 33 self.__shifting_base = None 34 35 gmMatchProvider.cMatchProvider.__init__(self) 36 37 self.setThresholds(aPhrase = 1, aWord = 998, aSubstring = 999) 38 self.word_separators = None
39 # self.ignored_chars("""[?!."'\\(){}\[\]<>~#*$%^_]+""") 40 #-------------------------------------------------------- 41 # external API 42 #-------------------------------------------------------- 43 #-------------------------------------------------------- 44 # base class API 45 #-------------------------------------------------------- 46 # internal matching algorithms 47 # 48 # if we end up here: 49 # - aFragment will not be "None" 50 # - aFragment will be lower case 51 # - we _do_ deliver matches (whether we find any is a different story) 52 #--------------------------------------------------------
53 - def getMatchesByPhrase(self, aFragment):
54 """Return matches for aFragment at start of phrases.""" 55 self.__now = mxDT.now() 56 matches = gmDateTime.str2fuzzy_timestamp_matches(aFragment.strip()) 57 if len(matches) > 0: 58 return (True, matches) 59 else: 60 return (False, [])
61 #--------------------------------------------------------
62 - def getMatchesByWord(self, aFragment):
63 """Return matches for aFragment at start of words inside phrases.""" 64 return self.getMatchesByPhrase(aFragment)
65 #--------------------------------------------------------
66 - def getMatchesBySubstr(self, aFragment):
67 """Return matches for aFragment as a true substring.""" 68 return self.getMatchesByPhrase(aFragment)
69 #--------------------------------------------------------
70 - def getAllMatches(self):
71 """Return all items.""" 72 # FIXME: popup calendar to pick from 73 return (False, [])
74 #==================================================
75 -class cFuzzyTimestampInput(gmPhraseWheel.cPhraseWheel):
76
77 - def __init__(self, *args, **kwargs):
78 79 gmPhraseWheel.cPhraseWheel.__init__(self, *args, **kwargs) 80 81 self.matcher = cMatchProvider_FuzzyTimestamp() 82 self.phrase_separators = None 83 self.selection_only = True 84 self.selection_only_error_msg = _('Cannot interpret input as timestamp.')
85 #-------------------------------------------------------- 86 # internal helpers 87 #--------------------------------------------------------
88 - def __text2timestamp(self, val=None):
89 90 if val is None: 91 val = self.GetValue().strip() 92 93 success, matches = self.matcher.getMatchesByPhrase(val) 94 #matches = gmDateTime.str2fuzzy_timestamp_matches(str2parse=val) 95 if len(matches) == 1: 96 return matches[0]['data'] 97 98 return None
99 #-------------------------------------------------------- 100 # phrasewheel internal API 101 #--------------------------------------------------------
102 - def _on_lose_focus(self, event):
103 # are we valid ? 104 if self.data is None: 105 # no, so try 106 self.data = self.__text2timestamp() 107 108 # let the base class do its thing 109 gmPhraseWheel.cPhraseWheel._on_lose_focus(self, event)
110 #--------------------------------------------------------
112 data = self._picklist.GetSelectedItemData() 113 if data is not None: 114 return data.format_accurately() 115 return self._picklist.get_selected_item_label()
116 #-------------------------------------------------------- 117 # external API 118 #--------------------------------------------------------
119 - def SetText(self, value=u'', data=None, suppress_smarts=False):
120 121 if data is not None: 122 if isinstance(data, pyDT.datetime): 123 data = gmDateTime.cFuzzyTimestamp(timestamp=data) 124 if value.strip() == u'': 125 value = data.format_accurately() 126 127 gmPhraseWheel.cPhraseWheel.SetText(self, value = value, data = data, suppress_smarts = suppress_smarts)
128 #--------------------------------------------------------
129 - def SetData(self, data=None):
130 if data is None: 131 gmPhraseWheel.cPhraseWheel.SetText(self, u'', None) 132 else: 133 if isinstance(data, pyDT.datetime): 134 data = gmDateTime.cFuzzyTimestamp(timestamp=data) 135 gmPhraseWheel.cPhraseWheel.SetText(self, value = data.format_accurately(), data = data)
136 #--------------------------------------------------------
137 - def is_valid_timestamp(self):
138 if self.data is not None: 139 return True 140 141 # skip empty value 142 if self.GetValue().strip() == u'': 143 return True 144 145 self.data = self.__text2timestamp() 146 if self.data is None: 147 return False 148 149 return True
150 #==================================================
151 -class cTimeInput(wx.TextCtrl):
152 - def __init__(self, parent, *args, **kwargs):
153 if len(args) < 2: 154 if not kwargs.has_key('value'): 155 kwargs['value'] = _('enter time here') 156 wx.TextCtrl.__init__( 157 self, 158 parent, 159 *args, 160 **kwargs 161 )
162 #==================================================
163 -class cDateInputCtrl(wx.DatePickerCtrl):
164 165 #----------------------------------------------
166 - def SetValue(self, value):
167 """Set either datetime.datetime or wx.DateTime""" 168 169 if isinstance(value, (pyDT.date, pyDT.datetime)): 170 value = gmDateTime.py_dt2wxDate(py_dt = value, wx = wx) 171 172 elif value is None: 173 value = wx.DefaultDateTime 174 175 wx.DatePickerCtrl.SetValue(self, value)
176 #----------------------------------------------
177 - def GetValue(self, as_pydt=False, invalid_as_none=False):
178 """Returns datetime.datetime values""" 179 180 # datepicker can fail to pick up user changes by keyboard until 181 # it has lost focus, so do that but also set the focus back to 182 # us, now this is a side-effect (after GetValue() focus will be 183 # here) but at least it is predictable ... 184 self.Navigate() 185 self.SetFocus() 186 value = wx.DatePickerCtrl.GetValue(self) 187 188 if value is None: 189 return None 190 191 # manage null dates (useful when wx.DP_ALLOWNONE is set) 192 if not value.IsValid(): 193 if invalid_as_none: 194 return None 195 else: 196 return value 197 198 self.SetBackgroundColour(gmPhraseWheel.color_prw_valid) 199 self.Refresh() 200 201 if not as_pydt: 202 return value 203 204 return gmDateTime.wxDate2py_dt(value)
205 #---------------------------------------------- 206 # def convenience wrapper 207 #----------------------------------------------
208 - def is_valid_timestamp(self, allow_none=True, invalid_as_none=False):
209 val = self.GetValue(as_pydt = False, invalid_as_none = invalid_as_none) 210 211 if val is None: 212 if allow_none: 213 valid = True 214 else: 215 valid = False 216 else: 217 valid = val.IsValid() 218 219 if valid: 220 self.SetBackgroundColour(gmPhraseWheel.color_prw_valid) 221 else: 222 self.SetBackgroundColour(gmPhraseWheel.color_prw_invalid) 223 224 self.Refresh() 225 return valid
226 #----------------------------------------------
227 - def get_pydt(self):
228 return self.GetValue(as_pydt = True)
229 #----------------------------------------------
230 - def display_as_valid(self, valid=True):
231 if valid is True: 232 self.SetBackgroundColour(gmPhraseWheel.color_prw_valid) 233 else: 234 self.SetBackgroundColour(gmPhraseWheel.color_prw_invalid) 235 self.Refresh()
236 #================================================== 237 # main 238 #-------------------------------------------------- 239 if __name__ == '__main__': 240 241 if (len(sys.argv) > 1) and (sys.argv[1] == 'test'): 242 from Gnumed.pycommon import gmI18N 243 gmI18N.activate_locale() 244 gmI18N.install_domain(domain='gnumed') 245 gmDateTime.init() 246 247 #----------------------------------------------------
248 - def test_cli():
249 mp = cMatchProvider_FuzzyTimestamp() 250 mp.word_separators = None 251 mp.setThresholds(aWord = 998, aSubstring = 999) 252 val = None 253 while val != 'exit': 254 print "************************************" 255 val = raw_input('Enter date fragment: ') 256 found, matches = mp.getMatches(aFragment=val) 257 for match in matches: 258 print match['label'] 259 print match['data'] 260 print "---------------"
261 #--------------------------------------------------------
262 - def test_gui():
263 app = wx.PyWidgetTester(size = (200, 300)) 264 app.SetWidget(cFuzzyTimestampInput, id=-1, size=(180,20), pos=(10,20)) 265 app.MainLoop()
266 #--------------------------------------------------------
267 - def test_picker():
268 app = wx.PyWidgetTester(size = (200, 300)) 269 app.SetWidget(cDateInputCtrl, id=-1, size=(180,20), pos=(10,20)) 270 app.MainLoop()
271 #-------------------------------------------------------- 272 #test_cli() 273 #test_gui() 274 test_picker() 275 276 #================================================== 277 # - free text input: start string with " 278 #================================================== 279