| Trees | Indices | Help |
|
|---|
|
|
1 """gmPlugin - base classes for GnuMed Horst space notebook plugins.
2
3 @copyright: author
4 """
5 #==================================================================
6 # $Source: /cvsroot/gnumed/gnumed/gnumed/client/wxpython/gmPlugin.py,v $
7 # $Id: gmPlugin.py,v 1.85 2009/07/23 20:04:48 ncq Exp $
8 __version__ = "$Revision: 1.85 $"
9 __author__ = "H.Herb, I.Haywood, K.Hilbert"
10 __license__ = 'GPL (details at http://www.gnu.org)'
11
12 import os, sys, re, glob, logging
13
14
15 import wx
16
17
18 if __name__ == '__main__':
19 sys.path.insert(0, '../../')
20 from Gnumed.pycommon import gmExceptions, gmGuiBroker, gmCfg, gmDispatcher, gmTools
21 from Gnumed.business import gmPerson, gmSurgery
22
23 _log = logging.getLogger('gm.ui')
24 _log.info(__version__)
25
26 #==============================================================================
29 wx.ProgressDialog.__init__(
30 self,
31 title = _("GNUmed: configuring [%s] (%s plugins)") % (gmSurgery.gmCurrentPractice().active_workplace, nr_plugins),
32 message = _("loading list of plugins "),
33 maximum = nr_plugins,
34 parent = None,
35 style = wx.PD_ELAPSED_TIME
36 )
37 # set window icon
38 paths = gmTools.gmPaths(app_name = u'gnumed', wx = wx)
39 png_fname = os.path.join(paths.system_app_data_dir, 'bitmaps', 'serpent.png')
40 icon = wx.EmptyIcon()
41 try:
42 icon.LoadFile(png_fname, wx.BITMAP_TYPE_PNG)
43 except:
44 _log.warning('wx.Icon.LoadFile() not supported')
45 self.SetIcon(icon)
46 self.idx = 0
47 self.nr_plugins = nr_plugins
48 self.prev_plugin = ""
49 #----------------------------------------------------------
51 if result == -1:
52 result = ""
53 elif result == 0:
54 result = _("failed")
55 else:
56 result = _("success")
57 wx.ProgressDialog.Update (self,
58 self.idx,
59 _("previous: %s (%s)\ncurrent (%s/%s): %s") % (
60 self.prev_plugin,
61 result,
62 (self.idx+1),
63 self.nr_plugins,
64 plugin))
65 self.prev_plugin = plugin
66 self.idx += 1
67 #==================================================================
68 # This is for NOTEBOOK plugins. Please write other base
69 # classes for other types of plugins.
70 #==================================================================
72 """Base class for plugins which provide a full notebook page.
73 """
75 self.gb = gmGuiBroker.GuiBroker()
76 self._set = 'gui'
77 self._widget = None
78 self.__register_events()
79 #-----------------------------------------------------
80 # plugin load API
81 #-----------------------------------------------------
83 """Register ourselves with the main notebook widget."""
84
85 _log.info("set: [%s] class: [%s] name: [%s]" % (self._set, self.__class__.__name__, self.name()))
86
87 # create widget
88 nb = self.gb['horstspace.notebook']
89 widget = self.GetWidget(nb)
90
91 # create toolbar
92 #top_panel = self.gb['horstspace.top_panel']
93 #tb = top_panel.CreateBar()
94 #self.populate_toolbar(tb, widget)
95 #tb.Realize()
96 # place bar in top panel
97 # (pages that don't want a toolbar must install a blank one
98 # otherwise the previous page's toolbar would be visible)
99 #top_panel.AddBar(key=self.__class__.__name__, bar=tb)
100 #self.gb['toolbar.%s' % self.__class__.__name__] = tb
101
102 # add ourselves to the main notebook
103 nb.AddPage(widget, self.name())
104
105 # so notebook can find this widget
106 self.gb['horstspace.notebook.%s' % self._set][self.__class__.__name__] = self
107 self.gb['horstspace.notebook.pages'].append(self)
108
109 # and put ourselves into the menu structure
110 menu_info = self.MenuInfo()
111 if menu_info is None:
112 # register with direct access menu only
113 gmDispatcher.send(signal = u'plugin_loaded', plugin_name = self.name(), class_name = self.__class__.__name__)
114 else:
115 name_of_menu, menu_item_name = menu_info
116 gmDispatcher.send (
117 signal = u'plugin_loaded',
118 plugin_name = menu_item_name,
119 class_name = self.__class__.__name__,
120 menu_name = name_of_menu,
121 menu_item_name = menu_item_name,
122 # FIXME: this shouldn't be self.name() but rather self.menu_help_string()
123 menu_help_string = self.name()
124 )
125
126 return True
127 #-----------------------------------------------------
129 """Remove ourselves."""
130 del self.gb['horstspace.notebook.%s' % self._set][self.__class__.__name__]
131 _log.info("plugin: [%s] (class: [%s]) set: [%s]" % (self.name(), self.__class__.__name__, self._set))
132
133 # delete menu item
134 menu_info = self.MenuInfo()
135 if menu_info is not None:
136 menu = self.gb['main.%smenu' % menu_info[0]]
137 menu.Delete(self.menu_id)
138
139 # delete toolbar
140 #top_panel = self.gb['main.top_panel']
141 #top_panel.DeleteBar(self.__class__.__name__)
142
143 # correct the notebook page list
144 nb_pages = self.gb['horstspace.notebook.pages']
145 nb_page_num = nb_pages.index(self)
146 del nb_pages[nb_page_num]
147
148 # delete notebook page
149 nb = self.gb['horstspace.notebook']
150 nb.DeletePage(nb_page_num)
151 #-----------------------------------------------------
154 #-----------------------------------------------------
156 """Return tuple of (menuname, menuitem).
157
158 None: no menu entry wanted
159 """
160 return None
161 #-----------------------------------------------------
162 # def populate_toolbar (self, tb, widget):
163 # """Populates the toolbar for this widget.
164 #
165 # - tb is the toolbar to populate
166 # - widget is the widget returned by GetWidget() # FIXME: is this really needed ?
167 # """
168 # pass
169 #-----------------------------------------------------
170 # activation API
171 #-----------------------------------------------------
173 """Called when this plugin is *about to* receive focus.
174
175 If None returned from here (or from overriders) the
176 plugin activation will be veto()ed (if it can be).
177 """
178 # FIXME: fail if locked
179 return True
180 #-----------------------------------------------------
182 """We *are* receiving focus via wx.EVT_NotebookPageChanged.
183
184 This can be used to populate the plugin widget on receiving focus.
185 """
186 if hasattr(self._widget, 'repopulate_ui'):
187 self._widget.repopulate_ui()
188 # else apparently it doesn't need it
189 return True
190 #-----------------------------------------------------
192 """Check for patient availability.
193
194 - convenience method for your can_receive_focus() handlers
195 """
196 # fail if no patient selected
197 pat = gmPerson.gmCurrentPatient()
198 if not pat.connected:
199 # FIXME: people want an optional red backgound here
200 gmDispatcher.send('statustext', msg = _('Cannot switch to [%s]: no patient selected') % self.name())
201 return None
202 return 1
203 #-----------------------------------------------------
205 """Raise ourselves."""
206 nb_pages = self.gb['horstspace.notebook.pages']
207 plugin_page = nb_pages.index(self)
208 nb = self.gb['horstspace.notebook']
209 nb.SetSelection(plugin_page)
210 return True
211 #-----------------------------------------------------
217 #-----------------------------------------------------
219 # does this signal concern us ?
220 if kwds['name'] not in [self.__class__.__name__, self.name()]:
221 return False
222 return self._on_raise_by_menu(None)
223 # -----------------------------------------------------
224 # event handlers for the popup window
228 # FIXME: raise ?
229 # -----------------------------------------------------
231 self.register() # register without changing configuration
232 # -----------------------------------------------------
235 #==================================================================
237 """This mixin adds listening to patient change signals."""
239 gmDispatcher.connect(self._pre_patient_selection, u'pre_patient_selection')
240 gmDispatcher.connect(self._post_patient_selection, u'post_patient_selection')
241 # -----------------------------------------------------
243 print "%s._pre_patient_selection() not implemented" % self.__class__.__name__
244 print "should usually be used to commit unsaved data"
245 # -----------------------------------------------------
249 #==================================================================
250 # some convenience functions
251 #------------------------------------------------------------------
253 """Import a module.
254
255 I am not sure *why* we need this. But the docs
256 and Google say so. It's got something to do with
257 package imports returning the toplevel package name."""
258 try:
259 mod = __import__(module_name)
260 except ImportError:
261 _log.exception ('Cannot __import__() module [%s].' % module_name)
262 return None
263 components = module_name.split('.')
264 for component in components[1:]:
265 mod = getattr(mod, component)
266 return mod
267 #------------------------------------------------------------------
269 """Instantiates a plugin object from a package directory, returning the object.
270
271 NOTE: it does NOT call register() for you !!!!
272
273 - "set" specifies the subdirectory in which to find the plugin
274 - this knows nothing of databases, all it does is instantiate a named plugin
275
276 There will be a general 'gui' directory for large GUI
277 components: prescritions, etc., then several others for more
278 specific types: export/import filters, crypto algorithms
279 guibroker, dbbroker are broker objects provided
280 defaults are the default set of plugins to be loaded
281
282 FIXME: we should inform the user about failing plugins
283 """
284 # we do need brokers, else we are useless
285 gb = gmGuiBroker.GuiBroker()
286
287 # bean counting ! -> loaded plugins
288 if not ('horstspace.notebook.%s' % aPackage) in gb.keylist():
289 gb['horstspace.notebook.%s' % aPackage] = {}
290 if not 'horstspace.notebook.pages' in gb.keylist():
291 gb['horstspace.notebook.pages'] = []
292
293 module_from_package = __gm_import('Gnumed.wxpython.%s.%s' % (aPackage, plugin_name))
294 # find name of class of plugin (must be the same as the plugin module filename)
295 plugin_class = module_from_package.__dict__[plugin_name]
296
297 if not issubclass(plugin_class, cNotebookPlugin):
298 _log.error("[%s] not a subclass of cNotebookPlugin" % plugin_name)
299 return None
300
301 _log.info(plugin_name)
302 try:
303 plugin = plugin_class()
304 except:
305 _log.exception('Cannot open module "%s.%s".' % (aPackage, plugin_name))
306 return None
307
308 return plugin
309 #------------------------------------------------------------------
311 """Looks for installed plugins in the filesystem.
312
313 The first directory in sys.path which contains a wxpython/gui/
314 is considered the one -- because that's where the import will
315 get it from.
316 """
317 search_path = None
318 for path in sys.path:
319 tmp = os.path.join(path, 'Gnumed', 'wxpython', plugin_dir)
320 if os.path.exists(tmp):
321 search_path = tmp
322 break
323 if search_path is None:
324 _log.error('unable to find any candidate directory matching [$candidate/Gnumed/wxpython/%s/]' % plugin_dir)
325 _log.error('candidates: %s' % str(sys.path))
326 return []
327
328 _log.info("scanning plugin directory [%s]" % search_path)
329
330 files = glob.glob(os.path.join(search_path, 'gm*.py'))
331 plugins = []
332 for file in files:
333 path, fname = os.path.split(file)
334 mod_name, ext = os.path.splitext(fname)
335 plugins.append(mod_name)
336
337 _log.debug("plugins found: %s" % str(plugins))
338
339 return plugins
340 #------------------------------------------------------------------
342 """Get a list of plugins to load.
343
344 1) from database if option is not None
345 2) from list of defaults
346 3) if 2 is None, from source directory (then stored in database)
347
348 FIXME: NOT from files in directories (important for py2exe)
349 """
350 if workplace == u'System Fallback':
351 return [u'gmProviderInboxPlugin', u'gmDataMiningPlugin']
352
353 if workplace is None:
354 workplace = gmSurgery.gmCurrentPractice().active_workplace
355
356 p_list = None
357
358 if option is not None:
359 dbcfg = gmCfg.cCfgSQL()
360 p_list = dbcfg.get2 (
361 option = option,
362 workplace = workplace,
363 bias = 'workplace',
364 default = defaults
365 )
366
367 if p_list is not None:
368 return p_list
369
370 if defaults is None:
371 p_list = get_installed_plugins(plugin_dir = plugin_dir)
372 if (len(p_list) == 0):
373 _log.error('cannot find plugins by scanning plugin directory ?!?')
374 return defaults
375 else:
376 p_list = defaults
377
378 # store for current user/current workplace
379 dbcfg.set (
380 option = option,
381 value = p_list,
382 workplace = workplace
383 )
384
385 _log.debug("plugin load list stored: %s" % str(p_list))
386 return p_list
387 #------------------------------------------------------------------
389 """
390 Unloads the named plugin
391 """
392 gb = gmGuiBroker.GuiBroker()
393 plugin = gb['horstspace.notebook.%s' % set][name]
394 plugin.unregister()
395 #==================================================================
396 # Main
397 #------------------------------------------------------------------
398 if __name__ == '__main__':
399
400 if len(sys.argv) > 1 and sys.argv[1] == 'test':
401 print get_installed_plugins('gui')
402
403 #==================================================================
404 # $Log: gmPlugin.py,v $
405 # Revision 1.85 2009/07/23 20:04:48 ncq
406 # - if workplace name is System-Fallback then return fixed list of plugins
407 #
408 # Revision 1.84 2009/07/17 09:28:08 ncq
409 # - plugin menu placement now done by signal *only*
410 #
411 # Revision 1.83 2009/07/09 16:47:22 ncq
412 # - cleanup
413 #
414 # Revision 1.82 2009/07/01 17:10:58 ncq
415 # - send along class name when loading plugin
416 #
417 # Revision 1.81 2009/06/29 15:10:21 ncq
418 # - improved naming of plugins in GNUmed / Go to plugin menu
419 #
420 # Revision 1.80 2009/04/14 18:34:25 ncq
421 # - minor cleanup
422 #
423 # Revision 1.79 2009/02/05 21:12:28 ncq
424 # - support "plugin loaded" signal
425 #
426 # Revision 1.78 2008/07/10 20:54:52 ncq
427 # - comment out toolbar handling
428 #
429 # Revision 1.77 2008/03/05 22:30:14 ncq
430 # - new style logging
431 #
432 # Revision 1.76 2007/12/11 12:49:26 ncq
433 # - explicit signal handling
434 #
435 # Revision 1.75 2007/11/23 23:35:47 ncq
436 # - cleanup
437 # - fix get_installed_plugins()
438 # - add workplace option to GetPluginLoadList()
439 # - rig test suite
440 #
441 # Revision 1.74 2007/10/29 13:18:35 ncq
442 # - only call repopulate_ui on widgets if they have one as some
443 # won't need it as they update ON_PAINT
444 #
445 # Revision 1.73 2007/10/08 13:07:19 ncq
446 # - factor out get_installed_plugins() even though it doesn't work yet
447 #
448 # Revision 1.72 2007/08/12 00:12:41 ncq
449 # - no more gmSignals.py
450 #
451 # Revision 1.71 2007/08/07 21:42:40 ncq
452 # - cPaths -> gmPaths
453 #
454 # Revision 1.70 2007/05/08 11:16:32 ncq
455 # - need to import gmTools
456 #
457 # Revision 1.69 2007/05/07 12:35:20 ncq
458 # - improve use of gmTools.cPaths()
459 #
460 # Revision 1.68 2007/04/11 20:47:13 ncq
461 # - no more 'resource dir' and 'gnumed_dir'
462 #
463 # Revision 1.67 2007/03/02 15:40:58 ncq
464 # - status text now set by signal
465 #
466 # Revision 1.66 2007/02/17 14:13:11 ncq
467 # - gmPerson.gmCurrentProvider().workplace now property
468 #
469 # Revision 1.65 2006/11/07 00:34:52 ncq
470 # - fix logic error in _on_raise_by_signal()
471 #
472 # Revision 1.64 2006/10/08 11:07:01 ncq
473 # - simplify wx import
474 # - properly use db cfg in GetPluginLoadList()
475 #
476 # Revision 1.63 2006/07/19 20:29:50 ncq
477 # - import cleanup
478 #
479 # Revision 1.62 2006/05/28 15:59:16 ncq
480 # - cleanup
481 # - receive_focus() now calls self._widget.repopulate_ui()
482 #
483 # Revision 1.61 2006/05/20 18:54:49 ncq
484 # - provide default receive_focus() and document it
485 # - remove get_instance()
486 #
487 # Revision 1.60 2006/05/15 13:38:52 ncq
488 # - remove "set" argument from notebook plugin __init__
489 # - cPatientChange_PluginMixin
490 # - inherit from this to listen to patient change signals
491 # - add depreciation warning to raise_notebook_plugin()
492 #
493 # Revision 1.59 2006/05/15 07:05:07 ncq
494 # - must import gmPerson now
495 #
496 # Revision 1.58 2006/05/14 21:44:22 ncq
497 # - add get_workplace() to gmPerson.gmCurrentProvider and make use thereof
498 # - remove use of gmWhoAmI.py
499 #
500 # Revision 1.57 2006/05/12 22:01:02 ncq
501 # - add _on_raise_by_signal()
502 # - connect to "display_widget" signal
503 #
504 # Revision 1.56 2006/05/12 12:18:11 ncq
505 # - whoami -> whereami cleanup
506 # - use gmCurrentProvider()
507 #
508 # Revision 1.55 2005/12/26 08:57:26 sjtan
509 #
510 # repaint may not be signalled on some platforms ( gtk ? ); repaint occurs if 1) the emrbrowser is the selected notebook page AND
511 # 2) the frame is re-sized. This suggests repaint is best done on notebook page changed. This workaround goes to
512 # the demographic page on a new patient select - let's the user confirm they have selected the right patient; then when
513 # switch to emrbrowser, this signals data_reget. seems to work.
514 #
515 # Revision 1.54 2005/11/01 08:51:43 ncq
516 # - wx.python -> wx.python
517 #
518 # Revision 1.53 2005/09/28 21:27:30 ncq
519 # - a lot of wx2.6-ification
520 #
521 # Revision 1.52 2005/09/28 15:57:48 ncq
522 # - a whole bunch of wx.Foo -> wx.Foo
523 #
524 # Revision 1.51 2005/09/26 18:01:51 ncq
525 # - use proper way to import wx26 vs wx2.4
526 # - note: THIS WILL BREAK RUNNING THE CLIENT IN SOME PLACES
527 # - time for fixup
528 #
529 # Revision 1.50 2005/08/14 16:20:44 ncq
530 # - missing "Gnumed" directory
531 #
532 # Revision 1.49 2005/08/14 16:03:00 ncq
533 # - improved logging in case of error
534 #
535 # Revision 1.48 2005/08/14 15:00:08 ncq
536 # - fix plugin directory scanning
537 #
538 # Revision 1.47 2005/07/21 16:21:29 ncq
539 # - remove debugging cruft
540 #
541 # Revision 1.46 2005/07/18 17:13:38 ncq
542 # - improved import works but... better do what the docs tell us to do
543 #
544 # Revision 1.45 2005/07/18 16:48:26 ncq
545 # - hopefully improve __import__ of modules
546 #
547 # Revision 1.44 2005/07/16 22:49:52 ncq
548 # - cleanup
549 #
550 # Revision 1.43 2005/06/30 10:11:51 cfmoro
551 # String corrections
552 #
553 # Revision 1.42 2005/06/12 22:17:24 ncq
554 # - raise by menu only if activatable
555 #
556 # Revision 1.41 2005/03/29 07:28:20 ncq
557 # - add FIXME on plugin scanning
558 #
559 # Revision 1.40 2005/02/01 10:16:07 ihaywood
560 # refactoring of gmDemographicRecord and follow-on changes as discussed.
561 #
562 # gmTopPanel moves to gmHorstSpace
563 # gmRichardSpace added -- example code at present, haven't even run it myself
564 # (waiting on some icon .pngs from Richard)
565 #
566 # Revision 1.39 2005/01/31 10:37:26 ncq
567 # - gmPatient.py -> gmPerson.py
568 #
569 # Revision 1.38 2004/11/21 20:56:14 ncq
570 # - remove cruft
571 #
572 # Revision 1.37 2004/10/14 12:14:51 ncq
573 # - rearrange register() internally so we won't end up with
574 # half-baked but registered plugins
575 #
576 # Revision 1.36 2004/09/13 19:27:27 ncq
577 # - load "horstspace.notebook.plugin_load_order" instead of
578 # "plugin load order" with cookie "gui"
579 #
580 # Revision 1.35 2004/09/13 09:25:46 ncq
581 # - fix plugin raise code
582 #
583 # Revision 1.34 2004/09/06 22:23:03 ncq
584 # - properly use setDBParam()
585 #
586 # Revision 1.33 2004/08/20 13:34:48 ncq
587 # - getFirstMatchingDBSet() -> getDBParam()
588 #
589 # Revision 1.32 2004/08/04 17:16:02 ncq
590 # - wxNotebookPlugin -> cNotebookPlugin
591 # - derive cNotebookPluginOld from cNotebookPlugin
592 # - make cNotebookPluginOld warn on use and implement old
593 # explicit "main.notebook.raised_plugin"/ReceiveFocus behaviour
594 # - ReceiveFocus() -> receive_focus()
595 #
596 # Revision 1.31 2004/07/24 17:21:49 ncq
597 # - some cleanup, also re from wxPython import wx
598 # - factored out Horst space layout manager into it's own
599 # wx.Panel child class
600 # - subsequently renamed
601 # 'main.notebook.plugins' -> 'horstspace.notebook.pages'
602 # 'modules.gui' -> 'horstspace.notebook.gui' (to be renamed horstspace.notebook.plugins later)
603 # - adapt to said changes
604 #
605 # Revision 1.30 2004/07/19 16:17:55 ncq
606 # - missing GuiBroker reference added
607 #
608 # Revision 1.29 2004/07/19 13:54:25 ncq
609 # - simplify getPluginLoadList()
610 #
611 # Revision 1.28 2004/07/19 11:50:43 ncq
612 # - cfg: what used to be called "machine" really is "workplace", so fix
613 #
614 # Revision 1.27 2004/07/18 19:51:42 ncq
615 # - better logging
616 #
617 # Revision 1.26 2004/07/15 20:37:56 ncq
618 # - I really believe we should keep plugin code nicely separated
619 # - go back to plain notebook plugins, not super-plugins again
620 #
621 # Revision 1.24 2004/07/15 06:15:55 ncq
622 # - fixed typo patch -> path
623 #
624 # Revision 1.23 2004/07/15 05:17:43 ncq
625 # - better/correct logging in GetPluginLoadList()
626 #
627 # Revision 1.22 2004/06/26 23:09:22 ncq
628 # - better comments
629 #
630 # Revision 1.21 2004/06/25 14:39:35 ncq
631 # - make right-click runtime load/drop of plugins work again
632 #
633 # Revision 1.20 2004/06/25 13:28:00 ncq
634 # - logically separate notebook and clinical window plugins completely
635 #
636 # Revision 1.19 2004/06/25 12:51:23 ncq
637 # - InstPlugin() -> instantiate_plugin()
638 #
639 # Revision 1.18 2004/06/13 22:14:39 ncq
640 # - extensive cleanup/comments
641 # - deprecate self.internal_name in favour of self.__class__.__name__
642 # - introduce gb['main.notebook.raised_plugin']
643 # - add populate_with_data()
644 # - DoToolbar() -> populate_toolbar()
645 # - remove set_widget_reference()
646 #
647 # Revision 1.17 2004/03/10 13:57:45 ncq
648 # - unconditionally do shadow
649 #
650 # Revision 1.16 2004/03/10 12:56:01 ihaywood
651 # fixed sudden loss of main.shadow
652 # more work on referrals,
653 #
654 # Revision 1.15 2004/03/04 19:23:24 ncq
655 # - moved here from pycommon
656 #
657 # Revision 1.1 2004/02/25 09:30:13 ncq
658 # - moved here from python-common
659 #
660 # Revision 1.68 2004/02/12 23:54:39 ncq
661 # - add wx.Bell to can_receive_focus()
662 # - move raise_plugin out of class gmPlugin
663 #
664 # Revision 1.67 2004/01/17 10:37:24 ncq
665 # - don't ShowBar() in Raise() as GuiMain.OnNotebookPageChanged()
666 # takes care of that
667 #
668 # Revision 1.66 2004/01/17 09:59:02 ncq
669 # - enable Raise() to raise arbitrary plugins
670 #
671 # Revision 1.65 2004/01/06 23:44:40 ncq
672 # - __default__ -> xxxDEFAULTxxx
673 #
674 # Revision 1.64 2003/12/29 16:33:23 uid66147
675 # - use whoami.get_workplace()/gmPG.run_commit()
676 #
677 # Revision 1.63 2003/11/18 23:29:57 ncq
678 # - remove duplicate Version line
679 #
680 # Revision 1.62 2003/11/18 19:06:26 hinnef
681 # gmTmpPatient->gmPatient, again
682 #
683 # Revision 1.61 2003/11/17 10:56:37 sjtan
684 #
685 # synced and commiting.
686 #
687 # Revision 1.60 2003/11/09 14:26:41 ncq
688 # - if we have set_status_txt() do use it, too
689 #
690 # Revision 1.59 2003/11/08 10:48:36 shilbert
691 # - added convenience function _set_status_txt()
692 #
693 # Revision 1.58 2003/10/26 01:38:06 ncq
694 # - gmTmpPatient -> gmPatient, cleanup
695 #
696 # Revision 1.57 2003/09/24 10:32:54 ncq
697 # - whitespace cleanup
698 #
699 # Revision 1.56 2003/09/03 17:31:05 hinnef
700 # cleanup in GetPluginLoadList, make use of gmWhoAmI
701 #
702 # Revision 1.55 2003/07/21 20:57:42 ncq
703 # - cleanup
704 #
705 # Revision 1.54 2003/06/29 14:20:45 ncq
706 # - added TODO item
707 #
708 # Revision 1.53 2003/06/26 21:35:23 ncq
709 # - fatal->verbose
710 #
711 # Revision 1.52 2003/06/19 15:26:02 ncq
712 # - cleanup bits
713 # - add can_receive_focus() helper to wxNotebookPlugin()
714 # - in default can_receive_focus() veto() plugin activation on "no patient selected"
715 #
716 # Revision 1.51 2003/04/28 12:03:15 ncq
717 # - introduced internal_name() helper, adapted to use thereof
718 # - leaner logging
719 #
720 # Revision 1.50 2003/04/20 15:38:50 ncq
721 # - clean out some excessive logging
722 #
723 # Revision 1.49 2003/04/09 13:06:03 ncq
724 # - some cleanup
725 #
726 # Revision 1.48 2003/04/05 01:09:03 ncq
727 # - forgot that one in the big patient -> clinical clean up
728 #
729 # Revision 1.47 2003/02/24 12:35:55 ncq
730 # - renamed some function local variables to further my understanding of the code
731 #
732 # Revision 1.46 2003/02/17 16:18:29 ncq
733 # - fix whitespace on comments
734 #
735 # Revision 1.45 2003/02/13 12:58:05 sjtan
736 #
737 # remove unneded import.
738 #
739 # Revision 1.44 2003/02/11 18:23:39 ncq
740 # - removed unneeded import
741 #
742 # Revision 1.43 2003/02/11 12:27:07 sjtan
743 #
744 # suspect this is not the preferred way to get a handle on the plugin. Probably from guiBroker?
745 #
746 # Revision 1.42 2003/02/09 20:00:06 ncq
747 # - on notebook plugins rename Shown() to ReceiveFocus() as that's what this does, not only display itself
748 #
749 # Revision 1.41 2003/02/09 11:52:28 ncq
750 # - just one more silly cvs keyword
751 #
752 # Revision 1.40 2003/02/09 09:41:57 sjtan
753 #
754 # clean up new code, make it less intrusive.
755 #
756 # Revision 1.39 2003/02/07 12:47:15 sjtan
757 #
758 # using gmGuiBroker for more dynamic handler loading. (e.g. can use subclassed instances of EditAreaHandler classes).
759 # ~
760 #
761 # Revision 1.38 2003/02/07 08:16:16 ncq
762 # - some cosmetics
763 #
764 # Revision 1.37 2003/02/07 05:08:08 sjtan
765 #
766 # added few lines to hook in the handler classes from EditAreaHandler.
767 # EditAreaHandler was generated with editarea_gen_listener in wxPython directory.
768 #
769 # Revision 1.36 2003/01/16 14:45:04 ncq
770 # - debianized
771 #
772 # Revision 1.35 2003/01/16 09:18:11 ncq
773 # - cleanup
774 #
775 # Revision 1.34 2003/01/12 17:30:19 ncq
776 # - consistently return None if no plugins found by GetPluginLoadList()
777 #
778 # Revision 1.33 2003/01/12 01:45:12 ncq
779 # - typo, "IS None" not "== None"
780 #
781 # Revision 1.32 2003/01/11 22:03:30 hinnef
782 # removed gmConf
783 #
784 # Revision 1.31 2003/01/06 12:53:26 ncq
785 # - some cleanup bits
786 #
787 # Revision 1.30 2003/01/06 04:52:55 ihaywood
788 # resurrected gmDemographics.py
789 #
790 # Revision 1.29 2003/01/05 10:00:38 ncq
791 # - better comments
792 # - implement database plugin configuration loading/storing
793 #
794 # Revision 1.28 2003/01/04 07:43:55 ihaywood
795 # Popup menus on notebook tabs
796 #
797 # Revision 1.27 2002/11/13 09:14:17 ncq
798 # - document a few more todo's but don't do them before OSHCA
799 #
800 # Revision 1.26 2002/11/12 23:03:25 hherb
801 # further changes towards customization of plugin loading order
802 #
803 # Revision 1.25 2002/11/12 20:30:10 hherb
804 # Uses an optional config file in each plugin directory determining the order plugins are loaded as well as which plugins are loaded
805 #
806 # Revision 1.24 2002/09/26 13:10:43 ncq
807 # - silly ommitance
808 #
809 # Revision 1.23 2002/09/26 13:08:51 ncq
810 # - log version on import
811 # - TODO -> FIXME
812 #
813 # Revision 1.22 2002/09/09 00:50:28 ncq
814 # - return success or failure on LoadPlugin()
815 #
816 # @change log:
817 # 08.03.2002 hherb first draft, untested
818
| Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Tue Feb 9 04:02:37 2010 | http://epydoc.sourceforge.net |