| 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 import io
15
16
17 import wx
18
19
20 if __name__ == '__main__':
21 sys.path.insert(0, '../../')
22 from Gnumed.pycommon import gmMatchProvider
23 from Gnumed.pycommon import gmExceptions
24 from Gnumed.pycommon import gmLog2
25 from Gnumed.pycommon import gmTools
26 from Gnumed.pycommon import gmDispatcher
27 from Gnumed.wxpython import gmPhraseWheel
28
29
30 _log = logging.getLogger('gm.main')
31 # ========================================================================
33
35
36 gmPhraseWheel.cPhraseWheel.__init__(self, *args, **kwargs)
37
38 items = [
39 {'list_label': _('Yes: + / ! / 1'), 'field_label': _('yes'), 'data': True, 'weight': 0},
40 {'list_label': _('No: - / 0'), 'field_label': _('no'), 'data': False, 'weight': 1},
41 {'list_label': _('Unknown: ?'), 'field_label': _('unknown'), 'data': None, 'weight': 2},
42 ]
43 mp = gmMatchProvider.cMatchProvider_FixedList(items)
44 mp.setThresholds(1, 1, 2)
45 mp.word_separators = '[ :/]+'
46 mp.word_separators = None
47 mp.ignored_chars = r"[.'\\(){}\[\]<>~#*$%^_=&@\t23456]+" + r'"'
48
49 self.matcher = mp
50 # ========================================================================
51 from Gnumed.wxGladeWidgets import wxg2ButtonQuestionDlg
52
54
56
57 caption = kwargs['caption']
58 question = kwargs['question']
59 button_defs = kwargs['button_defs'][:2]
60 del kwargs['caption']
61 del kwargs['question']
62 del kwargs['button_defs']
63
64 try:
65 show_checkbox = kwargs['show_checkbox']
66 del kwargs['show_checkbox']
67 except KeyError:
68 show_checkbox = False
69
70 try:
71 checkbox_msg = kwargs['checkbox_msg']
72 del kwargs['checkbox_msg']
73 except KeyError:
74 checkbox_msg = None
75
76 try:
77 checkbox_tooltip = kwargs['checkbox_tooltip']
78 del kwargs['checkbox_tooltip']
79 except KeyError:
80 checkbox_tooltip = None
81
82 wxg2ButtonQuestionDlg.wxg2ButtonQuestionDlg.__init__(self, *args, **kwargs)
83
84 if not caption.startswith('GMd: '):
85 caption = 'GMd: %s' % caption
86 self.SetTitle(title = caption)
87 self._LBL_question.SetLabel(label = question)
88
89 if not show_checkbox:
90 self._CHBOX_dont_ask_again.Hide()
91 else:
92 if checkbox_msg is not None:
93 self._CHBOX_dont_ask_again.SetLabel(checkbox_msg)
94 if checkbox_tooltip is not None:
95 self._CHBOX_dont_ask_again.SetToolTip(checkbox_tooltip)
96
97 buttons = [self._BTN_1, self._BTN_2]
98 for idx in range(len(button_defs)):
99 buttons[idx].SetLabel(label = button_defs[idx]['label'])
100 buttons[idx].SetToolTip(button_defs[idx]['tooltip'])
101 try:
102 if button_defs[idx]['default'] is True:
103 buttons[idx].SetDefault()
104 buttons[idx].SetFocus()
105 except KeyError:
106 pass
107
108 self.Fit()
109 #--------------------------------------------------------
112 #--------------------------------------------------------
113 # event handlers
114 #--------------------------------------------------------
120 #--------------------------------------------------------
126
127 # ========================================================================
128 from Gnumed.wxGladeWidgets import wxg3ButtonQuestionDlg
129
131
133
134 caption = kwargs['caption']
135 question = kwargs['question']
136 button_defs = kwargs['button_defs'][:3]
137 del kwargs['caption']
138 del kwargs['question']
139 del kwargs['button_defs']
140
141 try:
142 show_checkbox = kwargs['show_checkbox']
143 del kwargs['show_checkbox']
144 except KeyError:
145 show_checkbox = False
146
147 try:
148 checkbox_msg = kwargs['checkbox_msg']
149 del kwargs['checkbox_msg']
150 except KeyError:
151 checkbox_msg = None
152
153 try:
154 checkbox_tooltip = kwargs['checkbox_tooltip']
155 del kwargs['checkbox_tooltip']
156 except KeyError:
157 checkbox_tooltip = None
158
159 wxg3ButtonQuestionDlg.wxg3ButtonQuestionDlg.__init__(self, *args, **kwargs)
160
161 if not caption.startswith('GMd: '):
162 caption = 'GMd: %s' % caption
163 self.SetTitle(title = caption)
164 self._LBL_question.SetLabel(label = question)
165
166 if not show_checkbox:
167 self._CHBOX_dont_ask_again.Hide()
168 else:
169 if checkbox_msg is not None:
170 self._CHBOX_dont_ask_again.SetLabel(checkbox_msg)
171 if checkbox_tooltip is not None:
172 self._CHBOX_dont_ask_again.SetToolTip(checkbox_tooltip)
173
174 buttons = [self._BTN_1, self._BTN_2, self._BTN_3]
175 for idx in range(len(button_defs)):
176 buttons[idx].SetLabel(label = button_defs[idx]['label'])
177 buttons[idx].SetToolTip(button_defs[idx]['tooltip'])
178 try:
179 if button_defs[idx]['default'] is True:
180 buttons[idx].SetDefault()
181 buttons[idx].SetFocus()
182 except KeyError:
183 pass
184
185 self.Fit()
186 #--------------------------------------------------------
189 #--------------------------------------------------------
190 # event handlers
191 #--------------------------------------------------------
197 #--------------------------------------------------------
203
204 # ========================================================================
205 from Gnumed.wxGladeWidgets import wxgMultilineTextEntryDlg
206
208 """Editor for a bit of text."""
209
211
212 try:
213 title = kwargs['title']
214 del kwargs['title']
215 except KeyError:
216 title = None
217
218 try:
219 msg = kwargs['msg']
220 del kwargs['msg']
221 except KeyError:
222 msg = None
223
224 try:
225 data = kwargs['data']
226 del kwargs['data']
227 except KeyError:
228 data = None
229
230 try:
231 self.original_text = kwargs['text']
232 del kwargs['text']
233 except KeyError:
234 self.original_text = None
235
236 wxgMultilineTextEntryDlg.wxgMultilineTextEntryDlg.__init__(self, *args, **kwargs)
237
238 if title is not None:
239 if not title.startswith('GMd: '):
240 title = 'GMd: %s' % title
241 self.SetTitle(title)
242
243 if self.original_text is not None:
244 self._TCTRL_text.SetValue(self.original_text)
245 self._BTN_restore.Enable(True)
246
247 if msg is None:
248 self._LBL_msg.Hide()
249 else:
250 self._LBL_msg.SetLabel(msg)
251 self.Layout()
252 self.Refresh()
253
254 if data is None:
255 self._TCTRL_data.Hide()
256 else:
257 self._TCTRL_data.SetValue(data)
258 self.Layout()
259 self.Refresh()
260
261 self._TCTRL_text.SetFocus()
262 #--------------------------------------------------------
263 # properties
264 #--------------------------------------------------------
266 return self._TCTRL_text.GetValue()
267
268 value = property(_get_value, lambda x:x)
269 #--------------------------------------------------------
272
273 is_user_formatted = property(_get_is_user_formatted, lambda x:x)
274 #--------------------------------------------------------
277
278 enable_user_formatting = property(lambda x:x, _set_enable_user_formatting)
279 #--------------------------------------------------------
280 # event handlers
281 #--------------------------------------------------------
288 #--------------------------------------------------------
291 #--------------------------------------------------------
295
296 # ========================================================================
298
299 if wx.TheClipboard.IsOpened():
300 return False
301
302 if not wx.TheClipboard.Open():
303 return False
304
305 data_obj = wx.TextDataObject()
306 got_it = wx.TheClipboard.GetData(data_obj)
307 if got_it:
308 txt = data_obj.Text
309 wx.TheClipboard.Close()
310 return txt
311
312 wx.TheClipboard.Close()
313 return None
314
315 #-------------------------------------------------------------------------
317
318 if wx.TheClipboard.IsOpened():
319 return False
320
321 if not wx.TheClipboard.Open():
322 return False
323
324 data_obj = wx.TextDataObject()
325 got_it = wx.TheClipboard.GetData(data_obj)
326 if got_it:
327 clipboard_text_content = data_obj.Text
328 wx.TheClipboard.Close()
329 if check_for_filename:
330 try:
331 io.open(clipboard_text_content).close()
332 return clipboard_text_content
333 except IOError:
334 _log.exception('clipboard does not seem to hold filename: %s', clipboard_text_content)
335 fname = gmTools.get_unique_filename(prefix = 'gm-clipboard-', suffix = '.txt')
336 target_file = io.open(fname, mode = 'wt', encoding = 'utf8')
337 target_file.write(clipboard_text_content)
338 target_file.close()
339 return fname
340
341 data_obj = wx.BitmapDataObject()
342 got_it = wx.TheClipboard.GetData(data_obj)
343 if got_it:
344 fname = gmTools.get_unique_filename(prefix = 'gm-clipboard-', suffix = '.png')
345 bmp = data_obj.Bitmap.SaveFile(fname, wx.BITMAP_TYPE_PNG)
346 wx.TheClipboard.Close()
347 return fname
348
349 wx.TheClipboard.Close()
350 return None
351
352 #-------------------------------------------------------------------------
354 if wx.TheClipboard.IsOpened():
355 return False
356 if not wx.TheClipboard.Open():
357 return False
358 data_obj = wx.TextDataObject()
359 data_obj.SetText(text)
360 wx.TheClipboard.SetData(data_obj)
361 wx.TheClipboard.Close()
362 if announce_result:
363 gmDispatcher.send(signal = 'statustext', msg = _('The text has been copied into the clipboard.'), beep = False)
364 return True
365
366 #-------------------------------------------------------------------------
368 f = io.open(filename, mode = 'rt', encoding = 'utf8')
369 result = text2clipboard(text = f.read(), announce_result = False)
370 f.close()
371 if announce_result:
372 gm_show_info (
373 title = _('file2clipboard'),
374 info = _('The file [%s] has been copied into the clipboard.') % filename
375 )
376 return result
377
378 # ========================================================================
380 """Generic file drop target class.
381
382 Protocol:
383 Widgets being declared file drop targets
384 must provide the method:
385
386 def _drop_target_consume_filenames(self, filenames)
387
388 or declare a callback during __init__() of this class.
389 """
390 #-----------------------------------------------
392 if target is not None:
393 try:
394 on_drop_callback = getattr(target, '_drop_target_consume_filenames')
395 except AttributeError:
396 _log.exception('[%s._drop_target_consume_filenames()] does not exist, cannot set as drop target callback', target)
397 raise
398 if not callable(on_drop_callback):
399 _log.error('[%s] not callable, cannot set as drop target callback', on_drop_callback)
400 raise AttributeError('[%s] not callable, cannot set as drop target callback', on_drop_callback)
401 self._on_drop_callback = on_drop_callback
402 wx.FileDropTarget.__init__(self)
403 _log.debug('setting up [%s] as file drop target', self._on_drop_callback)
404
405 #-----------------------------------------------
408
409 # ========================================================================
411 img_data = None
412 bitmap = None
413 rescaled_height = height
414 try:
415 img_data = wx.Image(filename, wx.BITMAP_TYPE_ANY)
416 current_width = img_data.GetWidth()
417 current_height = img_data.GetHeight()
418 # if current_width == 0:
419 # current_width = 1
420 # if current_height == 0:
421 # current_height = 1
422 rescaled_width = (float(current_width) / current_height) * rescaled_height
423 img_data.Rescale(rescaled_width, rescaled_height, quality = wx.IMAGE_QUALITY_HIGH) # w, h
424 bitmap = wx.Bitmap(img_data)
425 del img_data
426 except Exception:
427 _log.exception('cannot load image from [%s]', filename)
428 del img_data
429 del bitmap
430 return None
431 return bitmap
432
433 # ========================================================================
435
436 if error is None:
437 error = aMessage
438 if error is None:
439 error = _('programmer forgot to specify error message')
440 error += _("\n\nPlease consult the error log for all the gory details !")
441
442 if title is None:
443 title = aTitle
444 if title is None:
445 title = _('generic error message')
446 if not title.startswith('GMd: '):
447 title = 'GMd: %s' % title
448
449 dlg = wx.MessageDialog (
450 parent = None,
451 message = error,
452 caption = title,
453 style = wx.OK | wx.ICON_ERROR | wx.STAY_ON_TOP
454 )
455 dlg.ShowModal()
456 dlg.Destroy()
457 return True
458
459 #-------------------------------------------------------------------------
461
462 if info is None:
463 info = aMessage
464 if info is None:
465 info = _('programmer forgot to specify info message')
466
467 if title is None:
468 title = aTitle
469 if title is None:
470 title = _('generic info message')
471 if not title.startswith('GMd: '):
472 title = 'GMd: %s' % title
473
474 dlg = wx.MessageDialog (
475 parent = None,
476 message = info,
477 caption = title,
478 style = wx.OK | wx.ICON_INFORMATION | wx.STAY_ON_TOP
479 )
480 dlg.ShowModal()
481 dlg.Destroy()
482 return True
483
484 #-------------------------------------------------------------------------
486 if aMessage is None:
487 aMessage = _('programmer forgot to specify warning')
488
489 if aTitle is None:
490 aTitle = _('generic warning message')
491 if not aTitle.startswith('GMd: '):
492 aTitle = 'GMd: %s' % aTitle
493
494 dlg = wx.MessageDialog (
495 parent = None,
496 message = aMessage,
497 caption = aTitle,
498 style = wx.OK | wx.ICON_EXCLAMATION | wx.STAY_ON_TOP
499 )
500 dlg.ShowModal()
501 dlg.Destroy()
502 return True
503
504 #-------------------------------------------------------------------------
505 -def gm_show_question(aMessage='programmer forgot to specify question', aTitle='generic user question dialog', cancel_button=False, question=None, title=None):
506 if cancel_button:
507 style = wx.YES_NO | wx.CANCEL | wx.ICON_QUESTION | wx.STAY_ON_TOP
508 else:
509 style = wx.YES_NO | wx.ICON_QUESTION | wx.STAY_ON_TOP
510
511 if question is None:
512 question = aMessage
513 if title is None:
514 title = aTitle
515 if not title.startswith('GMd: '):
516 title = 'GMd: %s' % title
517
518 dlg = wx.MessageDialog(None, question, title, style)
519 btn_pressed = dlg.ShowModal()
520 dlg.Destroy()
521
522 if btn_pressed == wx.ID_YES:
523 return True
524 elif btn_pressed == wx.ID_NO:
525 return False
526 else:
527 return None
528
529 #======================================================================
530 if __name__ == '__main__':
531
532 if len(sys.argv) < 2:
533 sys.exit()
534
535 if sys.argv[1] != 'test':
536 sys.exit()
537
538 from Gnumed.pycommon import gmI18N
539 gmI18N.activate_locale()
540 gmI18N.install_domain(domain='gnumed')
541
542 #------------------------------------------------------------------
544 app = wx.App()
545 img = file2scaled_image(filename = sys.argv[2])
546 print(img)
547 print(img.Height)
548 print(img.Width)
549 #------------------------------------------------------------------
551 app = wx.PyWidgetTester(size = (200, 50))
552 prw = cThreeValuedLogicPhraseWheel(app.frame, -1)
553 app.frame.Show(True)
554 app.MainLoop()
555
556 return True
557 #------------------------------------------------------------------
559 app = wx.PyWidgetTester(size = (200, 50))
560 result = clipboard2file()
561 if result is False:
562 print("problem opening clipboard")
563 return
564 if result is None:
565 print("no data in clipboard")
566 return
567 print("file:", result)
568 #------------------------------------------------------------------
569 #test_scale_img()
570 #test_sql_logic_prw()
571 test_clipboard()
572
573 #======================================================================
574
| Home | Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Fri Jan 25 02:55:27 2019 | http://epydoc.sourceforge.net |