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

Source Code for Module Gnumed.wxpython.gmGuiHelpers

  1  """GNUmed GUI helper classes and functions. 
  2   
  3  This module provides some convenient wxPython GUI 
  4  helper thingies that are widely used throughout 
  5  GnuMed. 
  6   
  7  This source code is protected by the GPL licensing scheme. 
  8  Details regarding the GPL are available at http://www.gnu.org 
  9  You may use and share it as long as you don't deny this right 
 10  to anybody else. 
 11  """ 
 12  # ======================================================================== 
 13  __version__ = "$Revision: 1.106 $" 
 14  __author__  = "K. Hilbert <Karsten.Hilbert@gmx.net>" 
 15  __license__ = "GPL (details at http://www.gnu.org)" 
 16   
 17  import os, logging 
 18   
 19   
 20  import wx 
 21   
 22   
 23  from Gnumed.pycommon import gmPG2 
 24  from Gnumed.pycommon import gmTools 
 25  from Gnumed.pycommon import gmI18N 
 26   
 27   
 28  _log = logging.getLogger('gm.main') 
 29  # ======================================================================== 
 30  from Gnumed.wxGladeWidgets import wxg2ButtonQuestionDlg 
 31   
32 -class c2ButtonQuestionDlg(wxg2ButtonQuestionDlg.wxg2ButtonQuestionDlg):
33
34 - def __init__(self, *args, **kwargs):
35 36 caption = kwargs['caption'] 37 question = kwargs['question'] 38 button_defs = kwargs['button_defs'][:2] 39 del kwargs['caption'] 40 del kwargs['question'] 41 del kwargs['button_defs'] 42 43 try: 44 show_checkbox = kwargs['show_checkbox'] 45 del kwargs['show_checkbox'] 46 except KeyError: 47 show_checkbox = False 48 49 try: 50 checkbox_msg = kwargs['checkbox_msg'] 51 del kwargs['checkbox_msg'] 52 except KeyError: 53 checkbox_msg = None 54 55 try: 56 checkbox_tooltip = kwargs['checkbox_tooltip'] 57 del kwargs['checkbox_tooltip'] 58 except KeyError: 59 checkbox_tooltip = None 60 61 wxg2ButtonQuestionDlg.wxg2ButtonQuestionDlg.__init__(self, *args, **kwargs) 62 63 self.SetTitle(title = caption) 64 self._LBL_question.SetLabel(label = question) 65 66 if not show_checkbox: 67 self._CHBOX_dont_ask_again.Hide() 68 else: 69 if checkbox_msg is not None: 70 self._CHBOX_dont_ask_again.SetLabel(checkbox_msg) 71 if checkbox_tooltip is not None: 72 self._CHBOX_dont_ask_again.SetToolTipString(checkbox_tooltip) 73 74 buttons = [self._BTN_1, self._BTN_2] 75 for idx in range(len(button_defs)): 76 buttons[idx].SetLabel(label = button_defs[idx]['label']) 77 buttons[idx].SetToolTipString(button_defs[idx]['tooltip']) 78 try: 79 if button_defs[idx]['default'] is True: 80 buttons[idx].SetDefault() 81 buttons[idx].SetFocus() 82 except KeyError: 83 pass 84 85 self.Fit()
86 #--------------------------------------------------------
87 - def checkbox_is_checked(self):
88 return self._CHBOX_dont_ask_again.IsChecked()
89 #-------------------------------------------------------- 90 # event handlers 91 #--------------------------------------------------------
92 - def _on_BTN_1_pressed(self, evt):
93 if self.IsModal(): 94 self.EndModal(wx.ID_YES) 95 else: 96 self.Close()
97 #--------------------------------------------------------
98 - def _on_BTN_2_pressed(self, evt):
99 if self.IsModal(): 100 self.EndModal(wx.ID_NO) 101 else: 102 self.Close()
103 # ======================================================================== 104 from Gnumed.wxGladeWidgets import wxg3ButtonQuestionDlg 105
106 -class c3ButtonQuestionDlg(wxg3ButtonQuestionDlg.wxg3ButtonQuestionDlg):
107
108 - def __init__(self, *args, **kwargs):
109 110 caption = kwargs['caption'] 111 question = kwargs['question'] 112 button_defs = kwargs['button_defs'][:3] 113 114 del kwargs['caption'] 115 del kwargs['question'] 116 del kwargs['button_defs'] 117 118 wxg3ButtonQuestionDlg.wxg3ButtonQuestionDlg.__init__(self, *args, **kwargs) 119 120 self.SetTitle(title = caption) 121 self._LBL_question.SetLabel(label = question) 122 123 buttons = [self._BTN_1, self._BTN_2, self._BTN_3] 124 for idx in range(len(button_defs)): 125 buttons[idx].SetLabel(label = button_defs[idx]['label']) 126 buttons[idx].SetToolTipString(button_defs[idx]['tooltip']) 127 try: 128 if button_defs[idx]['default'] is True: 129 buttons[idx].SetDefault() 130 buttons[idx].SetFocus() 131 except KeyError: 132 pass 133 134 self.Fit()
135 #-------------------------------------------------------- 136 # event handlers 137 #--------------------------------------------------------
138 - def _on_BTN_1_pressed(self, evt):
139 if self.IsModal(): 140 self.EndModal(wx.ID_YES) 141 else: 142 self.Close()
143 #--------------------------------------------------------
144 - def _on_BTN_2_pressed(self, evt):
145 if self.IsModal(): 146 self.EndModal(wx.ID_NO) 147 else: 148 self.Close()
149 # ======================================================================== 150 from Gnumed.wxGladeWidgets import wxgMultilineTextEntryDlg 151
152 -class cMultilineTextEntryDlg(wxgMultilineTextEntryDlg.wxgMultilineTextEntryDlg):
153 """Editor for a bit of text.""" 154
155 - def __init__(self, *args, **kwargs):
156 157 try: 158 title = kwargs['title'] 159 del kwargs['title'] 160 except KeyError: 161 title = None 162 163 try: 164 msg = kwargs['msg'] 165 del kwargs['msg'] 166 except KeyError: 167 msg = None 168 169 try: 170 data = kwargs['data'] 171 del kwargs['data'] 172 except KeyError: 173 data = None 174 175 try: 176 self.original_text = kwargs['text'] 177 del kwargs['text'] 178 except KeyError: 179 self.original_text = None 180 181 wxgMultilineTextEntryDlg.wxgMultilineTextEntryDlg.__init__(self, *args, **kwargs) 182 183 if title is not None: 184 self.SetTitle(title) 185 186 if self.original_text is not None: 187 self._TCTRL_text.SetValue(self.original_text) 188 self._BTN_restore.Enable(True) 189 190 if msg is None: 191 self._LBL_msg.Hide() 192 else: 193 self._LBL_msg.SetLabel(msg) 194 self.Layout() 195 self.Refresh() 196 197 if data is None: 198 self._TCTRL_data.Hide() 199 else: 200 self._TCTRL_data.SetValue(data) 201 self.Layout() 202 self.Refresh()
203 #--------------------------------------------------------
204 - def _get_value(self):
205 return self._TCTRL_text.GetValue()
206 207 value = property(_get_value, lambda x:x) 208 #-------------------------------------------------------- 209 # event handlers 210 #--------------------------------------------------------
211 - def _on_save_button_pressed(self, evt):
212 213 if self.IsModal(): 214 self.EndModal(wx.ID_SAVE) 215 else: 216 self.Close()
217 #--------------------------------------------------------
218 - def _on_clear_button_pressed(self, evt):
219 self._TCTRL_text.SetValue(u'')
220 #--------------------------------------------------------
221 - def _on_restore_button_pressed(self, evt):
222 if self.original_text is not None: 223 self._TCTRL_text.SetValue(self.original_text)
224 # ======================================================================== 225 from Gnumed.business import gmSurgery 226 from Gnumed.wxGladeWidgets import wxgGreetingEditorDlg 227
228 -class cGreetingEditorDlg(wxgGreetingEditorDlg.wxgGreetingEditorDlg):
229
230 - def __init__(self, *args, **kwargs):
231 wxgGreetingEditorDlg.wxgGreetingEditorDlg.__init__(self, *args, **kwargs) 232 233 self.surgery = gmSurgery.gmCurrentPractice() 234 self._TCTRL_message.SetValue(self.surgery.db_logon_banner)
235 #-------------------------------------------------------- 236 # event handlers 237 #--------------------------------------------------------
238 - def _on_save_button_pressed(self, evt):
239 self.surgery.db_logon_banner = self._TCTRL_message.GetValue().strip() 240 if self.IsModal(): 241 self.EndModal(wx.ID_SAVE) 242 else: 243 self.Close()
244 # ========================================================================
245 -class cTreeExpansionHistoryMixin:
246 """TreeCtrl mixin class to record expansion history."""
247 - def __init__(self):
248 if not isinstance(self, wx.TreeCtrl): 249 raise TypeError('[%s]: mixin can only be applied to wx.TreeCtrl, not [%s]' % (cTreeExpansionHistoryMixin, self.__class__.__name__)) 250 self.expansion_state = {}
251 #-------------------------------------------------------- 252 # public API 253 #--------------------------------------------------------
254 - def snapshot_expansion(self):
255 self.__record_subtree_expansion(start_node_id = self.GetRootItem())
256 #--------------------------------------------------------
257 - def restore_expansion(self):
258 if len(self.expansion_state) == 0: 259 return True 260 self.__restore_subtree_expansion(start_node_id = self.GetRootItem())
261 #--------------------------------------------------------
262 - def print_expansion(self):
263 if len(self.expansion_state) == 0: 264 print "currently no expansion snapshot available" 265 return True 266 print "last snapshot of state of expansion" 267 print "-----------------------------------" 268 print "listing expanded nodes:" 269 for node_id in self.expansion_state.keys(): 270 print "node ID:", node_id 271 print " selected:", self.expansion_state[node_id]
272 #-------------------------------------------------------- 273 # internal API 274 #--------------------------------------------------------
275 - def __record_subtree_expansion(self, start_node_id=None):
276 """This records node expansion states based on the item label. 277 278 A side effect of this is that identically named items can 279 become unduly synchronized in their expand state after a 280 snapshot/restore cycle. 281 282 Better choices might be 283 284 id(item.GetPyData()) or 285 item.GetPyData().get_tree_uid() 286 287 where get_tree_uid(): 288 289 '[%s:%s]' % (self.__class__.__name__, id(self)) 290 291 or some such. This would survive renaming of the item. 292 293 For database items it may be useful to include the 294 primary key which would - contrary to id() - survive 295 reloads from the database. 296 """ 297 # protect against empty tree where not even 298 # a root node exists 299 if not start_node_id.IsOk(): 300 return True 301 302 if not self.IsExpanded(start_node_id): 303 return True 304 305 self.expansion_state[self.GetItemText(start_node_id)] = self.IsSelected(start_node_id) 306 307 child_id, cookie = self.GetFirstChild(start_node_id) 308 while child_id.IsOk(): 309 self.__record_subtree_expansion(start_node_id = child_id) 310 child_id, cookie = self.GetNextChild(start_node_id, cookie) 311 312 return
313 #--------------------------------------------------------
314 - def __restore_subtree_expansion(self, start_node_id=None):
315 start_node_label = self.GetItemText(start_node_id) 316 try: 317 node_selected = self.expansion_state[start_node_label] 318 except KeyError: 319 return 320 321 self.Expand(start_node_id) 322 if node_selected: 323 self.SelectItem(start_node_id) 324 325 child_id, cookie = self.GetFirstChild(start_node_id) 326 while child_id.IsOk(): 327 self.__restore_subtree_expansion(start_node_id = child_id) 328 child_id, cookie = self.GetNextChild(start_node_id, cookie) 329 330 return
331 # ========================================================================
332 -class cFileDropTarget(wx.FileDropTarget):
333 """Generic file drop target class. 334 335 Protocol: 336 Widgets being declared file drop targets 337 must provide the method: 338 339 add_filenames(filenames) 340 """ 341 #-----------------------------------------------
342 - def __init__(self, target):
343 wx.FileDropTarget.__init__(self) 344 self.target = target
345 #-----------------------------------------------
346 - def OnDropFiles(self, x, y, filenames):
347 self.target.add_filenames(filenames)
348 # ========================================================================
349 -def file2scaled_image(filename=None, height=100):
350 img_data = None 351 bitmap = None 352 rescaled_height = height 353 try: 354 img_data = wx.Image(filename, wx.BITMAP_TYPE_ANY) 355 current_width = img_data.GetWidth() 356 current_height = img_data.GetHeight() 357 rescaled_width = (current_width / current_height) * rescaled_height 358 img_data.Rescale(rescaled_width, rescaled_height, quality = wx.IMAGE_QUALITY_HIGH) # w, h 359 bitmap = wx.BitmapFromImage(img_data) 360 del img_data 361 except StandardError: 362 _log.exception('cannot load visual progress note from [%s]', filename) 363 del img_data 364 del bitmap 365 return None 366 367 return bitmap
368 # ========================================================================
369 -def gm_show_error(aMessage = None, aTitle = None):
370 if aMessage is None: 371 aMessage = _('programmer forgot to specify error message') 372 373 aMessage += _("\n\nPlease consult the error log for all the gory details !") 374 375 if aTitle is None: 376 aTitle = _('generic error message') 377 378 dlg = wx.MessageDialog ( 379 parent = None, 380 message = aMessage, 381 caption = aTitle, 382 style = wx.OK | wx.ICON_ERROR | wx.STAY_ON_TOP 383 ) 384 dlg.ShowModal() 385 dlg.Destroy() 386 return True
387 #-------------------------------------------------------------------------
388 -def gm_show_info(aMessage = None, aTitle = None):
389 if aMessage is None: 390 aMessage = _('programmer forgot to specify info message') 391 392 if aTitle is None: 393 aTitle = _('generic info message') 394 395 dlg = wx.MessageDialog ( 396 parent = None, 397 message = aMessage, 398 caption = aTitle, 399 style = wx.OK | wx.ICON_INFORMATION | wx.STAY_ON_TOP 400 ) 401 dlg.ShowModal() 402 dlg.Destroy() 403 return True
404 #-------------------------------------------------------------------------
405 -def gm_show_warning(aMessage=None, aTitle=None):
406 if aMessage is None: 407 aMessage = _('programmer forgot to specify warning') 408 409 if aTitle is None: 410 aTitle = _('generic warning message') 411 412 dlg = wx.MessageDialog ( 413 parent = None, 414 message = aMessage, 415 caption = aTitle, 416 style = wx.OK | wx.ICON_EXCLAMATION | wx.STAY_ON_TOP 417 ) 418 dlg.ShowModal() 419 dlg.Destroy() 420 return True
421 #-------------------------------------------------------------------------
422 -def gm_show_question(aMessage='programmer forgot to specify question', aTitle='generic user question dialog', cancel_button=False):
423 if cancel_button: 424 style = wx.YES_NO | wx.CANCEL | wx.ICON_QUESTION | wx.STAY_ON_TOP 425 else: 426 style = wx.YES_NO | wx.ICON_QUESTION | wx.STAY_ON_TOP 427 428 dlg = wx.MessageDialog ( 429 None, 430 aMessage, 431 aTitle, 432 style 433 ) 434 btn_pressed = dlg.ShowModal() 435 dlg.Destroy() 436 437 if btn_pressed == wx.ID_YES: 438 return True 439 elif btn_pressed == wx.ID_NO: 440 return False 441 else: 442 return None
443 #====================================================================== 444