| 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 # ========================================================================
288 """TreeCtrl mixin class to record expansion history."""
290 if not isinstance(self, wx.TreeCtrl):
291 raise TypeError('[%s]: mixin can only be applied to wx.TreeCtrl, not [%s]' % (cTreeExpansionHistoryMixin, self.__class__.__name__))
292 self.expansion_state = {}
293 #--------------------------------------------------------
294 # public API
295 #--------------------------------------------------------
298 #--------------------------------------------------------
300 if len(self.expansion_state) == 0:
301 return True
302 self.__restore_subtree_expansion(start_node_id = self.GetRootItem())
303 #--------------------------------------------------------
305 if len(self.expansion_state) == 0:
306 print "currently no expansion snapshot available"
307 return True
308 print "last snapshot of state of expansion"
309 print "-----------------------------------"
310 print "listing expanded nodes:"
311 for node_id in self.expansion_state.keys():
312 print "node ID:", node_id
313 print " selected:", self.expansion_state[node_id]
314 #--------------------------------------------------------
315 # internal API
316 #--------------------------------------------------------
318 """This records node expansion states based on the item label.
319
320 A side effect of this is that identically named items can
321 become unduly synchronized in their expand state after a
322 snapshot/restore cycle.
323
324 Better choices might be
325
326 id(item.GetPyData()) or
327 item.GetPyData().get_tree_uid()
328
329 where get_tree_uid():
330
331 '[%s:%s]' % (self.__class__.__name__, id(self))
332
333 or some such. This would survive renaming of the item.
334
335 For database items it may be useful to include the
336 primary key which would - contrary to id() - survive
337 reloads from the database.
338 """
339 # protect against empty tree where not even
340 # a root node exists
341 if not start_node_id.IsOk():
342 return True
343
344 if not self.IsExpanded(start_node_id):
345 return True
346
347 self.expansion_state[self.GetItemText(start_node_id)] = self.IsSelected(start_node_id)
348
349 child_id, cookie = self.GetFirstChild(start_node_id)
350 while child_id.IsOk():
351 self.__record_subtree_expansion(start_node_id = child_id)
352 child_id, cookie = self.GetNextChild(start_node_id, cookie)
353
354 return
355 #--------------------------------------------------------
357 start_node_label = self.GetItemText(start_node_id)
358 try:
359 node_selected = self.expansion_state[start_node_label]
360 except KeyError:
361 return
362
363 self.Expand(start_node_id)
364 if node_selected:
365 self.SelectItem(start_node_id)
366
367 child_id, cookie = self.GetFirstChild(start_node_id)
368 while child_id.IsOk():
369 self.__restore_subtree_expansion(start_node_id = child_id)
370 child_id, cookie = self.GetNextChild(start_node_id, cookie)
371
372 return
373 # ========================================================================
375 """Generic file drop target class.
376
377 Protocol:
378 Widgets being declared file drop targets
379 must provide the method:
380
381 add_filenames(filenames)
382 """
383 #-----------------------------------------------
385 wx.FileDropTarget.__init__(self)
386 self.target = target
387 _log.debug('setting up [%s] as file drop target', target)
388 #-----------------------------------------------
391 # ========================================================================
393 img_data = None
394 bitmap = None
395 rescaled_height = height
396 try:
397 img_data = wx.Image(filename, wx.BITMAP_TYPE_ANY)
398 current_width = img_data.GetWidth()
399 current_height = img_data.GetHeight()
400 # if current_width == 0:
401 # current_width = 1
402 # if current_height == 0:
403 # current_height = 1
404 rescaled_width = (float(current_width) / current_height) * rescaled_height
405 img_data.Rescale(rescaled_width, rescaled_height, quality = wx.IMAGE_QUALITY_HIGH) # w, h
406 bitmap = wx.BitmapFromImage(img_data)
407 del img_data
408 except StandardError:
409 _log.exception('cannot load image from [%s]', filename)
410 del img_data
411 del bitmap
412 return None
413
414 return bitmap
415 # ========================================================================
417
418 if error is None:
419 error = aMessage
420 if error is None:
421 error = _('programmer forgot to specify error message')
422 error += _("\n\nPlease consult the error log for all the gory details !")
423
424 if title is None:
425 title = aTitle
426 if title is None:
427 title = _('generic error message')
428
429 dlg = wx.MessageDialog (
430 parent = None,
431 message = error,
432 caption = title,
433 style = wx.OK | wx.ICON_ERROR | wx.STAY_ON_TOP
434 )
435 dlg.ShowModal()
436 dlg.Destroy()
437 return True
438 #-------------------------------------------------------------------------
440
441 if info is None:
442 info = aMessage
443 if info is None:
444 info = _('programmer forgot to specify info message')
445
446 if title is None:
447 title = aTitle
448 if title is None:
449 title = _('generic info message')
450
451 dlg = wx.MessageDialog (
452 parent = None,
453 message = info,
454 caption = title,
455 style = wx.OK | wx.ICON_INFORMATION | wx.STAY_ON_TOP
456 )
457 dlg.ShowModal()
458 dlg.Destroy()
459 return True
460 #-------------------------------------------------------------------------
462 if aMessage is None:
463 aMessage = _('programmer forgot to specify warning')
464
465 if aTitle is None:
466 aTitle = _('generic warning message')
467
468 dlg = wx.MessageDialog (
469 parent = None,
470 message = aMessage,
471 caption = aTitle,
472 style = wx.OK | wx.ICON_EXCLAMATION | wx.STAY_ON_TOP
473 )
474 dlg.ShowModal()
475 dlg.Destroy()
476 return True
477 #-------------------------------------------------------------------------
478 -def gm_show_question(aMessage='programmer forgot to specify question', aTitle='generic user question dialog', cancel_button=False, question=None, title=None):
479 if cancel_button:
480 style = wx.YES_NO | wx.CANCEL | wx.ICON_QUESTION | wx.STAY_ON_TOP
481 else:
482 style = wx.YES_NO | wx.ICON_QUESTION | wx.STAY_ON_TOP
483
484 if question is None:
485 question = aMessage
486 if title is None:
487 title = aTitle
488
489 dlg = wx.MessageDialog(None, question, title, style)
490 btn_pressed = dlg.ShowModal()
491 dlg.Destroy()
492
493 if btn_pressed == wx.ID_YES:
494 return True
495 elif btn_pressed == wx.ID_NO:
496 return False
497 else:
498 return None
499
500 #======================================================================
501 if __name__ == '__main__':
502
503 if len(sys.argv) < 2:
504 sys.exit()
505
506 if sys.argv[1] != 'test':
507 sys.exit()
508
509 from Gnumed.pycommon import gmI18N
510 gmI18N.activate_locale()
511 gmI18N.install_domain(domain='gnumed')
512
513 #------------------------------------------------------------------
515 app = wx.App()
516 img = file2scaled_image(filename = sys.argv[2])
517 print img
518 print img.Height
519 print img.Width
520 #------------------------------------------------------------------
522 app = wx.PyWidgetTester(size = (200, 50))
523 prw = cThreeValuedLogicPhraseWheel(parent = app.frame, id = -1)
524 app.frame.Show(True)
525 app.MainLoop()
526
527 return True
528 #------------------------------------------------------------------
529 #test_scale_img()
530 test_sql_logic_prw()
531
532 #======================================================================
533
| Home | Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Sat Oct 5 03:56:57 2013 | http://epydoc.sourceforge.net |