Package Gnumed :: Package wxpython :: Module gmPlugin
[frames] | no frames]

Source Code for Module Gnumed.wxpython.gmPlugin

  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  #============================================================================== 
27 -class cLoadProgressBar (wx.ProgressDialog):
28 - def __init__(self, nr_plugins):
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 #----------------------------------------------------------
50 - def Update (self, result, plugin):
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 #==================================================================
71 -class cNotebookPlugin:
72 """Base class for plugins which provide a full notebook page. 73 """
74 - def __init__(self):
75 self.gb = gmGuiBroker.GuiBroker() 76 self._set = 'gui' 77 self._widget = None 78 self.__register_events()
79 #----------------------------------------------------- 80 # plugin load API 81 #-----------------------------------------------------
82 - def register(self):
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 #-----------------------------------------------------
128 - def unregister(self):
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 #-----------------------------------------------------
152 - def name(self):
153 return 'plugin <%s>' % self.__class__.__name__
154 #-----------------------------------------------------
155 - def MenuInfo(self):
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 #-----------------------------------------------------
172 - def can_receive_focus(self):
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 #-----------------------------------------------------
181 - def receive_focus(self):
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 #-----------------------------------------------------
191 - def _verify_patient_avail(self):
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 #-----------------------------------------------------
204 - def Raise(self):
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 #-----------------------------------------------------
212 - def _on_raise_by_menu(self, event):
213 if not self.can_receive_focus(): 214 return False 215 self.Raise() 216 return True
217 #-----------------------------------------------------
218 - def _on_raise_by_signal(self, **kwds):
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
225 - def on_load(self, evt):
226 # FIXME: talk to the configurator so we're loaded next time 227 self.register()
228 # FIXME: raise ? 229 # -----------------------------------------------------
230 - def OnShow(self, evt):
231 self.register() # register without changing configuration
232 # -----------------------------------------------------
233 - def __register_events(self):
234 gmDispatcher.connect(signal = 'display_widget', receiver = self._on_raise_by_signal)
235 #==================================================================
236 -class cPatientChange_PluginMixin:
237 """This mixin adds listening to patient change signals."""
238 - def __init__(self):
239 gmDispatcher.connect(self._pre_patient_selection, u'pre_patient_selection') 240 gmDispatcher.connect(self._post_patient_selection, u'post_patient_selection')
241 # -----------------------------------------------------
242 - def _pre_patient_selection(self, **kwds):
243 print "%s._pre_patient_selection() not implemented" % self.__class__.__name__ 244 print "should usually be used to commit unsaved data"
245 # -----------------------------------------------------
246 - def _post_patient_selection(self, **kwds):
247 print "%s._post_patient_selection() not implemented" % self.__class__.__name__ 248 print "should usually be used to initialize state"
249 #================================================================== 250 # some convenience functions 251 #------------------------------------------------------------------
252 -def __gm_import(module_name):
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 #------------------------------------------------------------------
268 -def instantiate_plugin(aPackage='xxxDEFAULTxxx', plugin_name='xxxDEFAULTxxx'):
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 #------------------------------------------------------------------
310 -def get_installed_plugins(plugin_dir=''):
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 #------------------------------------------------------------------
341 -def GetPluginLoadList(option, plugin_dir = '', defaults = None, workplace=None):
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 #------------------------------------------------------------------
388 -def UnloadPlugin (set, name):
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