| Home | Trees | Indices | Help |
|
|---|
|
|
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 # ========================================================================
8 __author__ = "K. Hilbert <Karsten.Hilbert@gmx.net>"
9 __license__ = "GPL v2 or later (details at http://www.gnu.org)"
10
11 import os
12 import logging
13 import sys
14
15
16 import wx
17
18
19 if __name__ == '__main__':
20 sys.path.insert(0, '../../')
21 from Gnumed.pycommon import gmMatchProvider
22 from Gnumed.pycommon import gmExceptions
23 from Gnumed.pycommon import gmLog2
24 from Gnumed.pycommon import gmTools
25 from Gnumed.wxpython import gmPhraseWheel
26
27
28 _log = logging.getLogger('gm.main')
29 # ========================================================================
31
33
34 gmPhraseWheel.cPhraseWheel.__init__(self, *args, **kwargs)
35
36 items = [
37 {'list_label': _('Yes: + / ! / 1'), 'field_label': _('yes'), 'data': True, 'weight': 0},
38 {'list_label': _('No: - / 0'), 'field_label': _('no'), 'data': False, 'weight': 1},
39 {'list_label': _('Unknown: ?'), 'field_label': _('unknown'), 'data': None, 'weight': 2},
40 ]
41 mp = gmMatchProvider.cMatchProvider_FixedList(items)
42 mp.setThresholds(1, 1, 2)
43 mp.word_separators = '[ :/]+'
44 mp.word_separators = None
45 mp.ignored_chars = r"[.'\\(){}\[\]<>~#*$%^_=&@\t23456]+" + r'"'
46
47 self.matcher = mp
48 # ========================================================================
49 from Gnumed.wxGladeWidgets import wxg2ButtonQuestionDlg
50
52
54
55 caption = kwargs['caption']
56 question = kwargs['question']
57 button_defs = kwargs['button_defs'][:2]
58 del kwargs['caption']
59 del kwargs['question']
60 del kwargs['button_defs']
61
62 try:
63 show_checkbox = kwargs['show_checkbox']
64 del kwargs['show_checkbox']
65 except KeyError:
66 show_checkbox = False
67
68 try:
69 checkbox_msg = kwargs['checkbox_msg']
70 del kwargs['checkbox_msg']
71 except KeyError:
72 checkbox_msg = None
73
74 try:
75 checkbox_tooltip = kwargs['checkbox_tooltip']
76 del kwargs['checkbox_tooltip']
77 except KeyError:
78 checkbox_tooltip = None
79
80 wxg2ButtonQuestionDlg.wxg2ButtonQuestionDlg.__init__(self, *args, **kwargs)
81
82 self.SetTitle(title = caption)
83 self._LBL_question.SetLabel(label = question)
84
85 if not show_checkbox:
86 self._CHBOX_dont_ask_again.Hide()
87 else:
88 if checkbox_msg is not None:
89 self._CHBOX_dont_ask_again.SetLabel(checkbox_msg)
90 if checkbox_tooltip is not None:
91 self._CHBOX_dont_ask_again.SetToolTipString(checkbox_tooltip)
92
93 buttons = [self._BTN_1, self._BTN_2]
94 for idx in range(len(button_defs)):
95 buttons[idx].SetLabel(label = button_defs[idx]['label'])
96 buttons[idx].SetToolTipString(button_defs[idx]['tooltip'])
97 try:
98 if button_defs[idx]['default'] is True:
99 buttons[idx].SetDefault()
100 buttons[idx].SetFocus()
101 except KeyError:
102 pass
103
104 self.Fit()
105 #--------------------------------------------------------
108 #--------------------------------------------------------
109 # event handlers
110 #--------------------------------------------------------
116 #--------------------------------------------------------
122 # ========================================================================
123 from Gnumed.wxGladeWidgets import wxg3ButtonQuestionDlg
124
126
128
129 caption = kwargs['caption']
130 question = kwargs['question']
131 button_defs = kwargs['button_defs'][:3]
132 del kwargs['caption']
133 del kwargs['question']
134 del kwargs['button_defs']
135
136 try:
137 show_checkbox = kwargs['show_checkbox']
138 del kwargs['show_checkbox']
139 except KeyError:
140 show_checkbox = False
141
142 try:
143 checkbox_msg = kwargs['checkbox_msg']
144 del kwargs['checkbox_msg']
145 except KeyError:
146 checkbox_msg = None
147
148 try:
149 checkbox_tooltip = kwargs['checkbox_tooltip']
150 del kwargs['checkbox_tooltip']
151 except KeyError:
152 checkbox_tooltip = None
153
154 wxg3ButtonQuestionDlg.wxg3ButtonQuestionDlg.__init__(self, *args, **kwargs)
155
156 self.SetTitle(title = caption)
157 self._LBL_question.SetLabel(label = question)
158
159 if not show_checkbox:
160 self._CHBOX_dont_ask_again.Hide()
161 else:
162 if checkbox_msg is not None:
163 self._CHBOX_dont_ask_again.SetLabel(checkbox_msg)
164 if checkbox_tooltip is not None:
165 self._CHBOX_dont_ask_again.SetToolTipString(checkbox_tooltip)
166
167 buttons = [self._BTN_1, self._BTN_2, self._BTN_3]
168 for idx in range(len(button_defs)):
169 buttons[idx].SetLabel(label = button_defs[idx]['label'])
170 buttons[idx].SetToolTipString(button_defs[idx]['tooltip'])
171 try:
172 if button_defs[idx]['default'] is True:
173 buttons[idx].SetDefault()
174 buttons[idx].SetFocus()
175 except KeyError:
176 pass
177
178 self.Fit()
179 #--------------------------------------------------------
182 #--------------------------------------------------------
183 # event handlers
184 #--------------------------------------------------------
190 #--------------------------------------------------------
196 # ========================================================================
197 from Gnumed.wxGladeWidgets import wxgMultilineTextEntryDlg
198
200 """Editor for a bit of text."""
201
203
204 try:
205 title = kwargs['title']
206 del kwargs['title']
207 except KeyError:
208 title = None
209
210 try:
211 msg = kwargs['msg']
212 del kwargs['msg']
213 except KeyError:
214 msg = None
215
216 try:
217 data = kwargs['data']
218 del kwargs['data']
219 except KeyError:
220 data = None
221
222 try:
223 self.original_text = kwargs['text']
224 del kwargs['text']
225 except KeyError:
226 self.original_text = None
227
228 wxgMultilineTextEntryDlg.wxgMultilineTextEntryDlg.__init__(self, *args, **kwargs)
229
230 if title is not None:
231 self.SetTitle(title)
232
233 if self.original_text is not None:
234 self._TCTRL_text.SetValue(self.original_text)
235 self._BTN_restore.Enable(True)
236
237 if msg is None:
238 self._LBL_msg.Hide()
239 else:
240 self._LBL_msg.SetLabel(msg)
241 self.Layout()
242 self.Refresh()
243
244 if data is None:
245 self._TCTRL_data.Hide()
246 else:
247 self._TCTRL_data.SetValue(data)
248 self.Layout()
249 self.Refresh()
250
251 self._TCTRL_text.SetFocus()
252 #--------------------------------------------------------
253 # properties
254 #--------------------------------------------------------
256 return self._TCTRL_text.GetValue()
257
258 value = property(_get_value, lambda x:x)
259 #--------------------------------------------------------
262
263 is_user_formatted = property(_get_is_user_formatted, lambda x:x)
264 #--------------------------------------------------------
266 self._CHBOX_is_already_formatted.Enable(value)
267
268 enable_user_formatting = property(lambda x:x, _set_enable_user_formatting)
269 #--------------------------------------------------------
270 # event handlers
271 #--------------------------------------------------------
278 #--------------------------------------------------------
281 #--------------------------------------------------------
285 # ========================================================================
286 from Gnumed.business import gmSurgery
287 from Gnumed.wxGladeWidgets import wxgGreetingEditorDlg
288
290
292 wxgGreetingEditorDlg.wxgGreetingEditorDlg.__init__(self, *args, **kwargs)
293
294 self.surgery = gmSurgery.gmCurrentPractice()
295 self._TCTRL_message.SetValue(self.surgery.db_logon_banner)
296 #--------------------------------------------------------
297 # event handlers
298 #--------------------------------------------------------
305 # ========================================================================
307 """TreeCtrl mixin class to record expansion history."""
309 if not isinstance(self, wx.TreeCtrl):
310 raise TypeError('[%s]: mixin can only be applied to wx.TreeCtrl, not [%s]' % (cTreeExpansionHistoryMixin, self.__class__.__name__))
311 self.expansion_state = {}
312 #--------------------------------------------------------
313 # public API
314 #--------------------------------------------------------
317 #--------------------------------------------------------
319 if len(self.expansion_state) == 0:
320 return True
321 self.__restore_subtree_expansion(start_node_id = self.GetRootItem())
322 #--------------------------------------------------------
324 if len(self.expansion_state) == 0:
325 print "currently no expansion snapshot available"
326 return True
327 print "last snapshot of state of expansion"
328 print "-----------------------------------"
329 print "listing expanded nodes:"
330 for node_id in self.expansion_state.keys():
331 print "node ID:", node_id
332 print " selected:", self.expansion_state[node_id]
333 #--------------------------------------------------------
334 # internal API
335 #--------------------------------------------------------
337 """This records node expansion states based on the item label.
338
339 A side effect of this is that identically named items can
340 become unduly synchronized in their expand state after a
341 snapshot/restore cycle.
342
343 Better choices might be
344
345 id(item.GetPyData()) or
346 item.GetPyData().get_tree_uid()
347
348 where get_tree_uid():
349
350 '[%s:%s]' % (self.__class__.__name__, id(self))
351
352 or some such. This would survive renaming of the item.
353
354 For database items it may be useful to include the
355 primary key which would - contrary to id() - survive
356 reloads from the database.
357 """
358 # protect against empty tree where not even
359 # a root node exists
360 if not start_node_id.IsOk():
361 return True
362
363 if not self.IsExpanded(start_node_id):
364 return True
365
366 self.expansion_state[self.GetItemText(start_node_id)] = self.IsSelected(start_node_id)
367
368 child_id, cookie = self.GetFirstChild(start_node_id)
369 while child_id.IsOk():
370 self.__record_subtree_expansion(start_node_id = child_id)
371 child_id, cookie = self.GetNextChild(start_node_id, cookie)
372
373 return
374 #--------------------------------------------------------
376 start_node_label = self.GetItemText(start_node_id)
377 try:
378 node_selected = self.expansion_state[start_node_label]
379 except KeyError:
380 return
381
382 self.Expand(start_node_id)
383 if node_selected:
384 self.SelectItem(start_node_id)
385
386 child_id, cookie = self.GetFirstChild(start_node_id)
387 while child_id.IsOk():
388 self.__restore_subtree_expansion(start_node_id = child_id)
389 child_id, cookie = self.GetNextChild(start_node_id, cookie)
390
391 return
392 # ========================================================================
394 """Generic file drop target class.
395
396 Protocol:
397 Widgets being declared file drop targets
398 must provide the method:
399
400 add_filenames(filenames)
401 """
402 #-----------------------------------------------
404 wx.FileDropTarget.__init__(self)
405 self.target = target
406 _log.debug('setting up [%s] as file drop target', target)
407 #-----------------------------------------------
410 # ========================================================================
412 img_data = None
413 bitmap = None
414 rescaled_height = height
415 try:
416 img_data = wx.Image(filename, wx.BITMAP_TYPE_ANY)
417 current_width = img_data.GetWidth()
418 current_height = img_data.GetHeight()
419 # if current_width == 0:
420 # current_width = 1
421 # if current_height == 0:
422 # current_height = 1
423 rescaled_width = (float(current_width) / current_height) * rescaled_height
424 img_data.Rescale(rescaled_width, rescaled_height, quality = wx.IMAGE_QUALITY_HIGH) # w, h
425 bitmap = wx.BitmapFromImage(img_data)
426 del img_data
427 except StandardError:
428 _log.exception('cannot load image from [%s]', filename)
429 del img_data
430 del bitmap
431 return None
432
433 return bitmap
434 # ========================================================================
436 if aMessage is None:
437 aMessage = _('programmer forgot to specify error message')
438
439 aMessage += _("\n\nPlease consult the error log for all the gory details !")
440
441 if aTitle is None:
442 aTitle = _('generic error message')
443
444 dlg = wx.MessageDialog (
445 parent = None,
446 message = aMessage,
447 caption = aTitle,
448 style = wx.OK | wx.ICON_ERROR | wx.STAY_ON_TOP
449 )
450 dlg.ShowModal()
451 dlg.Destroy()
452 return True
453 #-------------------------------------------------------------------------
455 if aMessage is None:
456 aMessage = _('programmer forgot to specify info message')
457
458 if aTitle is None:
459 aTitle = _('generic info message')
460
461 dlg = wx.MessageDialog (
462 parent = None,
463 message = aMessage,
464 caption = aTitle,
465 style = wx.OK | wx.ICON_INFORMATION | wx.STAY_ON_TOP
466 )
467 dlg.ShowModal()
468 dlg.Destroy()
469 return True
470 #-------------------------------------------------------------------------
472 if aMessage is None:
473 aMessage = _('programmer forgot to specify warning')
474
475 if aTitle is None:
476 aTitle = _('generic warning message')
477
478 dlg = wx.MessageDialog (
479 parent = None,
480 message = aMessage,
481 caption = aTitle,
482 style = wx.OK | wx.ICON_EXCLAMATION | wx.STAY_ON_TOP
483 )
484 dlg.ShowModal()
485 dlg.Destroy()
486 return True
487 #-------------------------------------------------------------------------
488 -def gm_show_question(aMessage='programmer forgot to specify question', aTitle='generic user question dialog', cancel_button=False, question=None, title=None):
489 if cancel_button:
490 style = wx.YES_NO | wx.CANCEL | wx.ICON_QUESTION | wx.STAY_ON_TOP
491 else:
492 style = wx.YES_NO | wx.ICON_QUESTION | wx.STAY_ON_TOP
493
494 if question is None:
495 question = aMessage
496 if title is None:
497 title = aTitle
498
499 dlg = wx.MessageDialog(None, question, title, style)
500 btn_pressed = dlg.ShowModal()
501 dlg.Destroy()
502
503 if btn_pressed == wx.ID_YES:
504 return True
505 elif btn_pressed == wx.ID_NO:
506 return False
507 else:
508 return None
509
510 #======================================================================
511 if __name__ == '__main__':
512
513 if len(sys.argv) < 2:
514 sys.exit()
515
516 if sys.argv[1] != 'test':
517 sys.exit()
518
519 from Gnumed.pycommon import gmI18N
520 gmI18N.activate_locale()
521 gmI18N.install_domain(domain='gnumed')
522
523 #------------------------------------------------------------------
525 app = wx.App()
526 img = file2scaled_image(filename = sys.argv[2])
527 print img
528 print img.Height
529 print img.Width
530 #------------------------------------------------------------------
532 app = wx.PyWidgetTester(size = (200, 50))
533 prw = cThreeValuedLogicPhraseWheel(parent = app.frame, id = -1)
534 app.frame.Show(True)
535 app.MainLoop()
536
537 return True
538 #------------------------------------------------------------------
539 #test_scale_img()
540 test_sql_logic_prw()
541
542 #======================================================================
543
| Home | Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Fri Feb 1 03:56:50 2013 | http://epydoc.sourceforge.net |