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
14
15 __version__ = "$Revision: 1.106 $"
16 __author__ = "K. Hilbert <Karsten.Hilbert@gmx.net>"
17 __license__ = "GPL (details at http://www.gnu.org)"
18
19 import os
20
21
22 import wx
23
24
25 from Gnumed.business import gmSurgery
26 from Gnumed.wxGladeWidgets import wxg3ButtonQuestionDlg, wxg2ButtonQuestionDlg, wxgGreetingEditorDlg
27
28
100
144
145 from Gnumed.wxGladeWidgets import wxgMultilineTextEntryDlg
146
147 -class cMultilineTextEntryDlg(wxgMultilineTextEntryDlg.wxgMultilineTextEntryDlg):
148 """Editor for a bit of text."""
149
150 - def __init__(self, *args, **kwargs):
151
152 try:
153 title = kwargs['title']
154 del kwargs['title']
155 except KeyError:
156 title = None
157
158 try:
159 msg = kwargs['msg']
160 del kwargs['msg']
161 except KeyError:
162 msg = None
163
164 try:
165 data = kwargs['data']
166 del kwargs['data']
167 except KeyError:
168 data = None
169
170 try:
171 self.original_text = kwargs['text']
172 del kwargs['text']
173 except KeyError:
174 self.original_text = None
175
176 wxgMultilineTextEntryDlg.wxgMultilineTextEntryDlg.__init__(self, *args, **kwargs)
177
178 if title is not None:
179 self.SetTitle(title)
180
181 if self.original_text is not None:
182 self._TCTRL_text.SetValue(self.original_text)
183 self._BTN_restore.Enable(True)
184
185 if msg is None:
186 self._LBL_msg.Hide()
187 else:
188 self._LBL_msg.SetLabel(msg)
189 self.Layout()
190 self.Refresh()
191
192 if data is None:
193 self._TCTRL_data.Hide()
194 else:
195 self._TCTRL_data.SetValue(data)
196 self.Layout()
197 self.Refresh()
198
199 - def _get_value(self):
200 return self._TCTRL_text.GetValue()
201
202 value = property(_get_value, lambda x:x)
203
204
205
207
208 if self.IsModal():
209 self.EndModal(wx.ID_SAVE)
210 else:
211 self.Close()
212
215
217 if self.original_text is not None:
218 self._TCTRL_text.SetValue(self.original_text)
219
236
238 """TreeCtrl mixin class to record expansion history."""
239 - def __init__(self):
240 if not isinstance(self, wx.TreeCtrl):
241 raise TypeError('[%s]: mixin can only be applied to wx.TreeCtrl, not [%s]' % (cTreeExpansionHistoryMixin, self.__class__.__name__))
242 self.expansion_state = {}
243
244
245
247 self.__record_subtree_expansion(start_node_id = self.GetRootItem())
248
250 if len(self.expansion_state) == 0:
251 return True
252 self.__restore_subtree_expansion(start_node_id = self.GetRootItem())
253
254 - def print_expansion(self):
255 if len(self.expansion_state) == 0:
256 print "currently no expansion snapshot available"
257 return True
258 print "last snapshot of state of expansion"
259 print "-----------------------------------"
260 print "listing expanded nodes:"
261 for node_id in self.expansion_state.keys():
262 print "node ID:", node_id
263 print " selected:", self.expansion_state[node_id]
264
265
266
267 - def __record_subtree_expansion(self, start_node_id=None):
268 """This records node expansion states based on the item label.
269
270 A side effect of this is that identically named items can
271 become unduly synchronized in their expand state after a
272 snapshot/restore cycle.
273
274 Better choices might be
275
276 id(item.GetPyData()) or
277 item.GetPyData().get_tree_uid()
278
279 where get_tree_uid():
280
281 '[%s:%s]' % (self.__class__.__name__, id(self))
282
283 or some such. This would survive renaming of the item.
284
285 For database items it may be useful to include the
286 primary key which would - contrary to id() - survive
287 reloads from the database.
288 """
289
290
291 if not start_node_id.IsOk():
292 return True
293
294 if not self.IsExpanded(start_node_id):
295 return True
296
297 self.expansion_state[self.GetItemText(start_node_id)] = self.IsSelected(start_node_id)
298
299 child_id, cookie = self.GetFirstChild(start_node_id)
300 while child_id.IsOk():
301 self.__record_subtree_expansion(start_node_id = child_id)
302 child_id, cookie = self.GetNextChild(start_node_id, cookie)
303
304 return
305
306 - def __restore_subtree_expansion(self, start_node_id=None):
307 start_node_label = self.GetItemText(start_node_id)
308 try:
309 node_selected = self.expansion_state[start_node_label]
310 except KeyError:
311 return
312
313 self.Expand(start_node_id)
314 if node_selected:
315 self.SelectItem(start_node_id)
316
317 child_id, cookie = self.GetFirstChild(start_node_id)
318 while child_id.IsOk():
319 self.__restore_subtree_expansion(start_node_id = child_id)
320 child_id, cookie = self.GetNextChild(start_node_id, cookie)
321
322 return
323
325 """Generic file drop target class.
326
327 Protocol:
328 Widgets being declared file drop targets
329 must provide the method:
330
331 add_filenames(filenames)
332 """
333
335 wx.FileDropTarget.__init__(self)
336 self.target = target
337
340
342 if aMessage is None:
343 aMessage = _('programmer forgot to specify error message')
344
345 aMessage += _("\n\nPlease consult the error log for all the gory details !")
346
347 if aTitle is None:
348 aTitle = _('generic error message')
349
350 message = aMessage
351 print message
352
353
354
355
356
357
358
359
360
361
362
364 if aMessage is None:
365 aMessage = _('programmer forgot to specify info message')
366
367 if aTitle is None:
368 aTitle = _('generic info message')
369
370 dlg = wx.MessageDialog (
371 parent = None,
372 message = aMessage,
373 caption = aTitle,
374 style = wx.OK | wx.ICON_INFORMATION | wx.STAY_ON_TOP
375 )
376 dlg.ShowModal()
377 dlg.Destroy()
378 return True
379
381 if aMessage is None:
382 aMessage = _('programmer forgot to specify warning')
383
384 if aTitle is None:
385 aTitle = _('generic warning message')
386
387 dlg = wx.MessageDialog (
388 parent = None,
389 message = aMessage,
390 caption = aTitle,
391 style = wx.OK | wx.ICON_EXCLAMATION | wx.STAY_ON_TOP
392 )
393 dlg.ShowModal()
394 dlg.Destroy()
395 return True
396
397 -def gm_show_question(aMessage='programmer forgot to specify question', aTitle='generic user question dialog', cancel_button=False):
398 if cancel_button:
399 style = wx.YES_NO | wx.CANCEL | wx.ICON_QUESTION | wx.STAY_ON_TOP
400 else:
401 style = wx.YES_NO | wx.ICON_QUESTION | wx.STAY_ON_TOP
402
403 dlg = wx.MessageDialog (
404 None,
405 aMessage,
406 aTitle,
407 style
408 )
409 btn_pressed = dlg.ShowModal()
410 dlg.Destroy()
411
412 if btn_pressed == wx.ID_YES:
413 return True
414 elif btn_pressed == wx.ID_NO:
415 return False
416 else:
417 return None
418
419 -def makePageTitle(wizPg, title):
420 """
421 Utility function to create the main sizer of a wizard's page.
422
423 @param wizPg The wizard page widget
424 @type wizPg A wx.WizardPageSimple instance
425 @param title The wizard page's descriptive title
426 @type title A StringType instance
427 """
428 sizer = wx.BoxSizer(wx.VERTICAL)
429 wizPg.SetSizer(sizer)
430 title = wx.StaticText(wizPg, -1, title)
431 title.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.BOLD))
432 sizer.Add(title, 0, wx.ALIGN_CENTRE|wx.ALL, 2)
433 sizer.Add(wx.StaticLine(wizPg, -1), 0, wx.EXPAND|wx.ALL, 2)
434 return sizer
435
436