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
18 import logging
19 import sys
20
21
22 import wx
23
24
25 if __name__ == '__main__':
26 sys.path.insert(0, '../../')
27
28 from Gnumed.pycommon import gmPG2
29 from Gnumed.pycommon import gmTools
30 from Gnumed.pycommon import gmI18N
31
32
33 _log = logging.getLogger('gm.main')
34
35 from Gnumed.wxGladeWidgets import wxg2ButtonQuestionDlg
36
108
109 from Gnumed.wxGladeWidgets import wxg3ButtonQuestionDlg
110
154
155 from Gnumed.wxGladeWidgets import wxgMultilineTextEntryDlg
156
157 -class cMultilineTextEntryDlg(wxgMultilineTextEntryDlg.wxgMultilineTextEntryDlg):
158 """Editor for a bit of text."""
159
160 - def __init__(self, *args, **kwargs):
161
162 try:
163 title = kwargs['title']
164 del kwargs['title']
165 except KeyError:
166 title = None
167
168 try:
169 msg = kwargs['msg']
170 del kwargs['msg']
171 except KeyError:
172 msg = None
173
174 try:
175 data = kwargs['data']
176 del kwargs['data']
177 except KeyError:
178 data = None
179
180 try:
181 self.original_text = kwargs['text']
182 del kwargs['text']
183 except KeyError:
184 self.original_text = None
185
186 wxgMultilineTextEntryDlg.wxgMultilineTextEntryDlg.__init__(self, *args, **kwargs)
187
188 if title is not None:
189 self.SetTitle(title)
190
191 if self.original_text is not None:
192 self._TCTRL_text.SetValue(self.original_text)
193 self._BTN_restore.Enable(True)
194
195 if msg is None:
196 self._LBL_msg.Hide()
197 else:
198 self._LBL_msg.SetLabel(msg)
199 self.Layout()
200 self.Refresh()
201
202 if data is None:
203 self._TCTRL_data.Hide()
204 else:
205 self._TCTRL_data.SetValue(data)
206 self.Layout()
207 self.Refresh()
208
209
210
211 - def _get_value(self):
212 return self._TCTRL_text.GetValue()
213
214 value = property(_get_value, lambda x:x)
215
217 return self._CHBOX_is_already_formatted.IsChecked()
218
219 is_user_formatted = property(_get_is_user_formatted, lambda x:x)
220
222 self._CHBOX_is_already_formatted.Enable(value)
223
224 enable_user_formatting = property(lambda x:x, _set_enable_user_formatting)
225
226
227
229
230 if self.IsModal():
231 self.EndModal(wx.ID_SAVE)
232 else:
233 self.Close()
234
237
239 if self.original_text is not None:
240 self._TCTRL_text.SetValue(self.original_text)
241
242 from Gnumed.business import gmSurgery
243 from Gnumed.wxGladeWidgets import wxgGreetingEditorDlg
244
261
263 """TreeCtrl mixin class to record expansion history."""
264 - def __init__(self):
265 if not isinstance(self, wx.TreeCtrl):
266 raise TypeError('[%s]: mixin can only be applied to wx.TreeCtrl, not [%s]' % (cTreeExpansionHistoryMixin, self.__class__.__name__))
267 self.expansion_state = {}
268
269
270
272 self.__record_subtree_expansion(start_node_id = self.GetRootItem())
273
275 if len(self.expansion_state) == 0:
276 return True
277 self.__restore_subtree_expansion(start_node_id = self.GetRootItem())
278
279 - def print_expansion(self):
280 if len(self.expansion_state) == 0:
281 print "currently no expansion snapshot available"
282 return True
283 print "last snapshot of state of expansion"
284 print "-----------------------------------"
285 print "listing expanded nodes:"
286 for node_id in self.expansion_state.keys():
287 print "node ID:", node_id
288 print " selected:", self.expansion_state[node_id]
289
290
291
292 - def __record_subtree_expansion(self, start_node_id=None):
293 """This records node expansion states based on the item label.
294
295 A side effect of this is that identically named items can
296 become unduly synchronized in their expand state after a
297 snapshot/restore cycle.
298
299 Better choices might be
300
301 id(item.GetPyData()) or
302 item.GetPyData().get_tree_uid()
303
304 where get_tree_uid():
305
306 '[%s:%s]' % (self.__class__.__name__, id(self))
307
308 or some such. This would survive renaming of the item.
309
310 For database items it may be useful to include the
311 primary key which would - contrary to id() - survive
312 reloads from the database.
313 """
314
315
316 if not start_node_id.IsOk():
317 return True
318
319 if not self.IsExpanded(start_node_id):
320 return True
321
322 self.expansion_state[self.GetItemText(start_node_id)] = self.IsSelected(start_node_id)
323
324 child_id, cookie = self.GetFirstChild(start_node_id)
325 while child_id.IsOk():
326 self.__record_subtree_expansion(start_node_id = child_id)
327 child_id, cookie = self.GetNextChild(start_node_id, cookie)
328
329 return
330
331 - def __restore_subtree_expansion(self, start_node_id=None):
332 start_node_label = self.GetItemText(start_node_id)
333 try:
334 node_selected = self.expansion_state[start_node_label]
335 except KeyError:
336 return
337
338 self.Expand(start_node_id)
339 if node_selected:
340 self.SelectItem(start_node_id)
341
342 child_id, cookie = self.GetFirstChild(start_node_id)
343 while child_id.IsOk():
344 self.__restore_subtree_expansion(start_node_id = child_id)
345 child_id, cookie = self.GetNextChild(start_node_id, cookie)
346
347 return
348
350 """Generic file drop target class.
351
352 Protocol:
353 Widgets being declared file drop targets
354 must provide the method:
355
356 add_filenames(filenames)
357 """
358
360 wx.FileDropTarget.__init__(self)
361 self.target = target
362
365
367 img_data = None
368 bitmap = None
369 rescaled_height = height
370 try:
371 img_data = wx.Image(filename, wx.BITMAP_TYPE_ANY)
372 current_width = img_data.GetWidth()
373 current_height = img_data.GetHeight()
374
375
376
377
378 rescaled_width = (current_width / current_height) * rescaled_height
379 img_data.Rescale(rescaled_width, rescaled_height, quality = wx.IMAGE_QUALITY_HIGH)
380 bitmap = wx.BitmapFromImage(img_data)
381 del img_data
382 except StandardError:
383 _log.exception('cannot load image from [%s]', filename)
384 del img_data
385 del bitmap
386 return None
387
388 return bitmap
389
391 if aMessage is None:
392 aMessage = _('programmer forgot to specify error message')
393
394 aMessage += _("\n\nPlease consult the error log for all the gory details !")
395
396 if aTitle is None:
397 aTitle = _('generic error message')
398
399 dlg = wx.MessageDialog (
400 parent = None,
401 message = aMessage,
402 caption = aTitle,
403 style = wx.OK | wx.ICON_ERROR | wx.STAY_ON_TOP
404 )
405 dlg.ShowModal()
406 dlg.Destroy()
407 return True
408
410 if aMessage is None:
411 aMessage = _('programmer forgot to specify info message')
412
413 if aTitle is None:
414 aTitle = _('generic info message')
415
416 dlg = wx.MessageDialog (
417 parent = None,
418 message = aMessage,
419 caption = aTitle,
420 style = wx.OK | wx.ICON_INFORMATION | wx.STAY_ON_TOP
421 )
422 dlg.ShowModal()
423 dlg.Destroy()
424 return True
425
427 if aMessage is None:
428 aMessage = _('programmer forgot to specify warning')
429
430 if aTitle is None:
431 aTitle = _('generic warning message')
432
433 dlg = wx.MessageDialog (
434 parent = None,
435 message = aMessage,
436 caption = aTitle,
437 style = wx.OK | wx.ICON_EXCLAMATION | wx.STAY_ON_TOP
438 )
439 dlg.ShowModal()
440 dlg.Destroy()
441 return True
442
443 -def gm_show_question(aMessage='programmer forgot to specify question', aTitle='generic user question dialog', cancel_button=False):
444 if cancel_button:
445 style = wx.YES_NO | wx.CANCEL | wx.ICON_QUESTION | wx.STAY_ON_TOP
446 else:
447 style = wx.YES_NO | wx.ICON_QUESTION | wx.STAY_ON_TOP
448
449 dlg = wx.MessageDialog (
450 None,
451 aMessage,
452 aTitle,
453 style
454 )
455 btn_pressed = dlg.ShowModal()
456 dlg.Destroy()
457
458 if btn_pressed == wx.ID_YES:
459 return True
460 elif btn_pressed == wx.ID_NO:
461 return False
462 else:
463 return None
464
465
466 if __name__ == '__main__':
467
468 if len(sys.argv) < 2:
469 sys.exit()
470
471 if sys.argv[1] != 'test':
472 sys.exit()
473
474 app = wx.App()
475 img = file2scaled_image(filename = sys.argv[2])
476 print img
477 print img.Height
478 print img.Width
479