Gnumed.wxpython.gmHorstSpace

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

# Source Code for Module Gnumed.wxpython.gmHorstSpace

      1  """GNUmed Horst-space inner-frame layout manager.
      2
      3  This implements the simple wx.Notebook based layout as
      4  originally suggested by Horst Herb.
      5
      6  copyright: authors
      7  """
      8  #==============================================================================
      9  __author__  = "H. Herb <hherb@gnumed.net>,\
     10                             K. Hilbert <Karsten.Hilbert@gmx.net>,\
     11                             I. Haywood <i.haywood@ugrad.unimelb.edu.au>"
     12  __license__ = 'GPL v2 or later (details at http://www.gnu.org)'
     13
     14  import os.path, os, sys, logging
     15
     16
     17  import wx
     18
     19
     20  from Gnumed.pycommon import gmGuiBroker, gmI18N, gmDispatcher, gmCfg, gmLog2
     21  from Gnumed.wxpython import gmPlugin, gmTopPanel, gmGuiHelpers
     22  from Gnumed.business import gmPerson, gmPraxis
     23
     24
     25  _log = logging.getLogger('gm.ui')
     26
     27  #==============================================================================
     28 -class cHorstSpaceNotebook(wx.Notebook):                 # wx.BestBook ?
     29
     30 -        def __init__(self, *args, **kwargs):
     31
     32                  kwargs['style'] = wx.NB_BOTTOM
     33                  kwargs['id'] = -1
     34                  wx.Notebook.__init__(self, *args, **kwargs)
     35
     36                  _log.debug('created wx.Notebook: %s with ID %s', self.__class__.__name__, self.Id)
     37
     38                  #self.__register_events()
     39
     40          #----------------------------------------------
     41          # internal API
     42          #----------------------------------------------
     43 -        def __register_events(self):
     44                  # because of
     45                  #       https://www.wiki.wxpython.org/self.Bind%20vs.%20self.button.Bind
     46                  # do self.Bind() rather than self.nb.Bind()
     47                  # - notebook page is about to change
     48                  #self.nb.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGING, self._on_notebook_page_changing)
     49                  #self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGING, self._on_notebook_page_changing, self)
     50                  self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGING, self._on_notebook_page_changing)
     51                  # - notebook page has been changed
     52                  #self.nb.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self._on_notebook_page_changed)
     53                  #self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self._on_notebook_page_changed, self)
     54                  self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self._on_notebook_page_changed)
     55                  # - popup menu on right click in notebook
     56                  #wx.EVT_RIGHT_UP(self.nb, self._on_right_click)
     57
     58          #----------------------------------------------
     59          # event handlers
     60          #----------------------------------------------
     61 -        def _on_notebook_page_changing(self, event):
     62                  """Called before notebook page change is processed."""
     63
     64                  _log.debug('just before switching notebook tabs')
     65
     66                  _log.debug('id: %s', event.Id)
     67                  _log.debug('event object (= source notebook): %s = %s', event.EventObject.Id, event.EventObject)
     68                  _log.debug('this notebook (= event receiver): %s = %s', self.Id, self)
     69                  if event.EventObject.Id != self.Id:
     70                          _log.error('this event came from another notebook')
     71
     72                  self.__target_page_already_checked = False
     73
     74                  self.__id_nb_page_before_switch = self.GetSelection()
     75                  self.__id_evt_page_before_switch = event.GetOldSelection()
     76                  __id_evt_page_after_switch = event.GetSelection()
     77
     78                  _log.debug('source/target page state in EVT_NOTEBOOK_PAGE_CHANGING:')
     79                  _log.debug(' #1 - notebook current page: %s (= notebook.GetSelection())', self.__id_nb_page_before_switch)
     80                  _log.debug(' #2 - event source page: %s (= page event says it is coming from, event.GetOldSelection())', self.__id_evt_page_before_switch)
     81                  _log.debug(' #3 - event target page: %s (= page event wants to go to, event.GetSelection())', __id_evt_page_after_switch)
     82                  if self.__id_evt_page_before_switch != self.__id_nb_page_before_switch:
     83                          _log.warning(' problem: #1 and #2 really should match but do not')
     84
     85                  # can we check the target page ?
     86                  if __id_evt_page_after_switch == self.__id_evt_page_before_switch:
     87                          # no, so complain
     88                          # (the docs say that on Windows GetSelection() returns the
     89                          #  old page ID, eg. the same value GetOldSelection() returns)
     90                          _log.debug('this system is: sys: [%s] wx: [%s]', sys.platform, wx.Platform)
     91                          _log.debug('it seems to be one of those platforms that have no clue which notebook page they are switching to')
     92                          _log.debug('(Windows is documented to return the old page from both evt.GetOldSelection() and evt.GetSelection())')
     93                          _log.debug('current notebook page : %s', self.__id_nb_page_before_switch)
     94                          _log.debug('source page from event: %s', self.__id_evt_page_before_switch)
     95                          _log.debug('target page from event: %s', __id_evt_page_after_switch)
     96                          _log.warning('cannot check whether notebook page change needs to be vetoed')
     97                          # but let's do a basic check anyways
     98                          pat = gmPerson.gmCurrentPatient()
     99                          if not pat.connected:
    100                                  gmDispatcher.send(signal = 'statustext', msg =_('Cannot change notebook tabs. No active patient.'))
    101                                  event.Veto()
    102                                  return
    103                          # that test passed, so let's hope things are fine
    104                          event.Allow()           # redundant ?
    105                          event.Skip()
    106                          return
    107
    108                  # check target page
    109                  target_page = self.__gb['horstspace.notebook.pages'][__id_evt_page_after_switch]
    110                  _log.debug('checking event target page for focussability: %s', target_page)
    111                  if not target_page.can_receive_focus():
    112                          _log.warning('veto()ing page change')
    113                          event.Veto()
    114                          return
    115
    116                  # everything seems fine so switch
    117                  _log.debug('event target page seems focussable')
    118                  self.__target_page_already_checked = True
    119                  event.Allow()           # redundant ?
    120                  event.Skip()
    121                  return
    122
    123          #----------------------------------------------
    124 -        def _on_notebook_page_changed(self, event):
    125                  """Called when notebook page changes.
    126
    127                          Date: Wed, 15 May 2019 09:03:49 -0700 (PDT)
    128                          From: Robin Dunn <robin@alldunn.com>
    129                          To: wxPython-users <wxpython-users@googlegroups.com>
    130                          Subject: [wxPython-users] Re: wx.Notebook events work differently on Mac vs Linux and Windows
    131
    132                          While in the _CHANGED event the notebook's current page (what you get from
    133                          GetCurrentPage) still hasn't been updated. I agree that this seems
    134                          unintuitive but it's always been that way. There may be a good reason for
    135                          it, but I don't know what it is.
    136
    137                          Instead, you can use the event's GetSelection to get the index of the page
    138                          being changed to, and then use the notebook's GetPage to get the page object.
    139
    140                          Also, you should call event.Skip() in your _CHANGED handler. I think there
    141                          is some layout things happening in the default handler on one or more of
    142                          the platforms, so you want to ensure that can still happen.
    143                          --
    144                          Robin
    145                  """
    146                  _log.debug('just after switching notebook tabs')
    147
    148                  event.Skip()
    149
    150                  _log.debug('id: %s', event.Id)
    151                  _log.debug('event object (= source notebook): %s = %s', event.EventObject.Id, event.EventObject)
    152                  _log.debug('this notebook (= event receiver): %s = %s', self.Id, self)
    153                  if event.EventObject.Id != self.Id:
    154                          _log.error('this event came from another notebook')
    155
    156                  id_nb_page_after_switch = self.GetSelection()
    157                  id_evt_page_before_switch = event.GetOldSelection()
    158                  id_evt_page_after_switch = event.GetSelection()
    159
    160                  _log.debug('source/target page state in EVT_NOTEBOOK_PAGE_CHANGED:')
    161                  _log.debug(' #1 - current notebook page: %s (notebook.GetSelection())', id_nb_page_after_switch)
    162                  _log.debug(' #2 - event source page: %s (= page event says it is coming from, event.GetOldSelection())', id_evt_page_before_switch)
    163                  _log.debug(' #3 - event target page: %s (= page event wants to go to, event.GetSelection())', id_evt_page_after_switch)
    164
    165                  if self.__id_nb_page_before_switch != id_evt_page_before_switch:
    166                          _log.warning('those two really *should* match:')
    167                          _log.warning(' wx.Notebook.GetSelection(): %s (notebook current page before switch) ', self.__id_nb_page_before_switch)
    168                          _log.warning(' EVT_NOTEBOOK_PAGE_CHANGED.GetOldSelection(): %s (event source page)' % id_evt_page_before_switch)
    169
    170                  target_page = self.__gb['horstspace.notebook.pages'][id_evt_page_after_switch]
    171
    172                  # well-behaving wxPython port ?
    173                  if self.__target_page_already_checked:
    174                          _log.debug('target page (evt=%s, nb=%s) claims to have been checked for focussability already: %s', id_evt_page_after_switch, id_nb_page_after_switch, target_page)
    175                          target_page.receive_focus()
    176                          self.__target_page_already_checked = False
    177                          return
    178
    179                  # no, complain
    180                  _log.debug('target page not checked for focussability yet: %s', target_page)
    181                  _log.debug('EVT_NOTEBOOK_PAGE_CHANGED.GetOldSelection(): %s' % id_evt_page_before_switch)
    182                  _log.debug('EVT_NOTEBOOK_PAGE_CHANGED.GetSelection()   : %s' % id_evt_page_after_switch)
    183                  _log.debug('wx.Notebook.GetSelection() (after switch)  : %s' % id_nb_page_after_switch)
    184
    185                  # check the new page just for good measure
    186                  if target_page.can_receive_focus():
    187                          _log.debug('we are lucky: target page *can* receive focus anyway')
    188                          target_page.receive_focus()
    189                          return
    190
    191                  _log.error('target page cannot receive focus but too late for veto')
    192                  return
    193
    194  #==============================================================================
    195  # finding the visible page from a notebook page: self.GetParent.GetCurrentPage == self
    196 -class cHorstSpaceLayoutMgr(wx.Panel):
    197          """GNUmed inner-frame layout manager.
    198
    199          This implements a Horst-space notebook-only
    200          "inner-frame" layout manager.
    201          """
    202 -        def __init__(self, parent, id):
    203                  # main panel
    204                  wx.Panel.__init__(
    205                          self,
    206                          parent = parent,
    207                          id = id,
    208                          pos = wx.DefaultPosition,
    209                          size = wx.DefaultSize,
    210                          style = wx.NO_BORDER,
    211                          name = 'HorstSpace.LayoutMgrPnl'
    212                  )
    213
    214                  # top "row": important patient data is displayed there continually
    215                  self.top_panel = gmTopPanel.cTopPnl(self, -1)
    216
    217                  # notebook
    218                  self.nb = cHorstSpaceNotebook(parent = self)
    219
    220                  # plugins
    221                  self.__gb = gmGuiBroker.GuiBroker()
    222                  self.__gb['horstspace.top_panel'] = self.top_panel
    223                  self.__gb['horstspace.notebook'] = self.nb # FIXME: remove per Ian's API suggestion
    224                  self.__load_plugins()
    225
    226                  # layout handling
    227                  self.main_szr = wx.BoxSizer(wx.VERTICAL)
    228                  self.main_szr.Add(self.top_panel, 0, wx.EXPAND)
    229                  self.main_szr.Add(self.nb, 1, wx.EXPAND)
    230                  self.SetSizer(self.main_szr)
    231  #               self.SetSizerAndFit(self.main_szr)
    232  #               self.Layout()
    233  #               self.Show(True)
    234
    235                  self.__register_events()
    236
    237          #----------------------------------------------
    238          # internal API
    239          #----------------------------------------------
    240 -        def __register_events(self):
    241  #               # because of
    242  #               #       https://www.wiki.wxpython.org/self.Bind%20vs.%20self.button.Bind
    243  #               # do self.Bind() rather than self.nb.Bind()
    244  #               # - notebook page is about to change
    245  #               #self.nb.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGING, self._on_notebook_page_changing)
    246                  self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGING, self._on_notebook_page_changing, self.nb)
    247  #               # - notebook page has been changed
    248  #               #self.nb.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self._on_notebook_page_changed)
    249                  self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self._on_notebook_page_changed, self.nb)
    250  #               # - popup menu on right click in notebook
    251  #               #wx.EVT_RIGHT_UP(self.nb, self._on_right_click)
    252
    253                  gmDispatcher.connect(self._on_post_patient_selection, 'post_patient_selection')
    254
    255          #----------------------------------------------
    256 -        def __load_plugins(self):
    257
    258                  wx.BeginBusyCursor()
    259
    260                  # get plugin list
    261                  plugins2load_by_name = gmPlugin.GetPluginLoadList (
    262                          option = 'horstspace.notebook.plugin_load_order',
    263                          plugin_dir = 'gui',
    264                          defaults = ['gmProviderInboxPlugin']
    265                  )
    266
    267                  _log.debug('plugin load order: %s', plugins2load_by_name)
    268
    269                  nr_plugins = len(plugins2load_by_name)
    270                  failed_plugins = []
    271
    272                  #  set up a progress bar
    273                  progress_bar = gmPlugin.cLoadProgressBar(nr_plugins)
    274
    275                  #  and load them
    276                  prev_plugin = ""
    277                  first_plugin = None
    278                  plugin = None
    279                  result = -1
    280                  for idx in range(nr_plugins):
    281                          curr_plugin = plugins2load_by_name[idx]
    282                          progress_bar.Update(result, curr_plugin)
    283                          try:
    284                                  plugin = gmPlugin.instantiate_plugin('gui', curr_plugin)
    285                                  if plugin:
    286                                          plugin.register()
    287                                          result = 1
    288                                  else:
    289                                          _log.error("plugin [%s] not loaded, see errors above", curr_plugin)
    290                                          failed_plugins.append(curr_plugin)
    291                                          result = 1
    292                          except Exception:
    293                                  _log.exception('failed to load plugin %s', curr_plugin)
    294                                  failed_plugins.append(curr_plugin)
    295                                  result = 0
    296
    297                          if first_plugin is None:
    298                                  first_plugin = plugin
    299                          prev_plugin = curr_plugin
    300
    301                  _log.debug('failed plugins: %s', failed_plugins)
    302                  progress_bar.DestroyLater()
    303                  wx.EndBusyCursor()
    304
    305                  # force-refresh first notebook page
    306                  page = self.nb.GetPage(0)
    307                  page.Refresh()
    308
    309                  return True
    310
    311          #----------------------------------------------
    312          # external callbacks
    313          #----------------------------------------------
    314 -        def _on_post_patient_selection(self, **kwargs):
    315                  db_cfg = gmCfg.cCfgSQL()
    316                  default_plugin = db_cfg.get2 (
    317                          option = 'patient_search.plugin_to_raise_after_search',
    318                          workplace = gmPraxis.gmCurrentPraxisBranch().active_workplace,
    319                          bias = 'user',
    320                          default = 'gmPatientOverviewPlugin'
    321                  )
    322                  gmDispatcher.send(signal = 'display_widget', name = default_plugin)
    323
    324          #----------------------------------------------
    325 -        def _on_notebook_page_changing(self, event):
    326                  """Called before notebook page change is processed."""
    327
    328                  _log.debug('just before switching notebook tabs')
    329
    330                  _log.debug('id: %s', event.Id)
    331                  _log.debug('event object (= source notebook): %s = %s', event.EventObject.Id, event.EventObject)
    332                  _log.debug('this notebook (= event receiver): %s = %s', self.nb.Id, self.nb)
    333                  if event.EventObject.Id != self.nb.Id:
    334                          _log.error('this event came from another notebook')
    335
    336                  self.__target_page_already_checked = False
    337
    338                  self.__id_nb_page_before_switch = self.nb.GetSelection()
    339                  self.__id_evt_page_before_switch = event.GetOldSelection()
    340                  __id_evt_page_after_switch = event.GetSelection()
    341
    342                  _log.debug('source/target page state in EVT_NOTEBOOK_PAGE_CHANGING:')
    343                  _log.debug(' #1 - notebook current page: %s (= notebook.GetSelection())', self.__id_nb_page_before_switch)
    344                  _log.debug(' #2 - event source page: %s (= page event says it is coming from, event.GetOldSelection())', self.__id_evt_page_before_switch)
    345                  _log.debug(' #3 - event target page: %s (= page event wants to go to, event.GetSelection())', __id_evt_page_after_switch)
    346                  if self.__id_evt_page_before_switch != self.__id_nb_page_before_switch:
    347                          _log.warning(' problem: #1 and #2 really should match but do not')
    348
    349                  # can we check the target page ?
    350                  if __id_evt_page_after_switch == self.__id_evt_page_before_switch:
    351                          # no, so complain
    352                          # (the docs say that on Windows GetSelection() returns the
    353                          #  old page ID, eg. the same value GetOldSelection() returns)
    354                          _log.debug('this system is: sys: [%s] wx: [%s]', sys.platform, wx.Platform)
    355                          _log.debug('it seems to be one of those platforms that have no clue which notebook page they are switching to')
    356                          _log.debug('(Windows is documented to return the old page from both evt.GetOldSelection() and evt.GetSelection())')
    357                          _log.debug('current notebook page : %s', self.__id_nb_page_before_switch)
    358                          _log.debug('source page from event: %s', self.__id_evt_page_before_switch)
    359                          _log.debug('target page from event: %s', __id_evt_page_after_switch)
    360                          _log.warning('cannot check whether notebook page change needs to be vetoed')
    361                          # but let's do a basic check anyways
    362                          pat = gmPerson.gmCurrentPatient()
    363                          if not pat.connected:
    364                                  gmDispatcher.send(signal = 'statustext', msg =_('Cannot change notebook tabs. No active patient.'))
    365                                  event.Veto()
    366                                  return
    367                          # that test passed, so let's hope things are fine
    368                          event.Allow()           # redundant ?
    369                          event.Skip()
    370                          return
    371
    372                  # check target page
    373                  target_page = self.__gb['horstspace.notebook.pages'][__id_evt_page_after_switch]
    374                  _log.debug('checking event target page for focussability: %s', target_page)
    375                  if not target_page.can_receive_focus():
    376                          _log.warning('veto()ing page change')
    377                          event.Veto()
    378                          return
    379
    380                  # everything seems fine so switch
    381                  _log.debug('event target page seems focussable')
    382                  self.__target_page_already_checked = True
    383                  event.Allow()           # redundant ?
    384                  event.Skip()
    385                  return
    386
    387          #----------------------------------------------
    388 -        def _on_notebook_page_changed(self, event):
    389                  """Called when notebook page changes."""
    390
    391                  _log.debug('just after switching notebook tabs')
    392
    393                  _log.debug('id: %s', event.Id)
    394                  _log.debug('event object (= source notebook): %s = %s', event.EventObject.Id, event.EventObject)
    395                  _log.debug('this notebook (= event receiver): %s = %s', self.nb.Id, self.nb)
    396                  if event.EventObject.Id != self.nb.Id:
    397                          _log.error('this event came from another notebook')
    398
    399                  event.Skip()
    400
    401                  id_nb_page_after_switch = self.nb.GetSelection()
    402                  id_evt_page_before_switch = event.GetOldSelection()
    403                  id_evt_page_after_switch = event.GetSelection()
    404
    405                  _log.debug('source/target page state in EVT_NOTEBOOK_PAGE_CHANGED:')
    406                  _log.debug(' #1 - current notebook page: %s (notebook.GetSelection())', id_nb_page_after_switch)
    407                  _log.debug(' #2 - event source page: %s (= page event says it is coming from, event.GetOldSelection())', id_evt_page_before_switch)
    408                  _log.debug(' #3 - event target page: %s (= page event wants to go to, event.GetSelection())', id_evt_page_after_switch)
    409
    410                  if self.__id_nb_page_before_switch != id_evt_page_before_switch:
    411                          _log.warning('those two really *should* match:')
    412                          _log.warning(' wx.Notebook.GetSelection(): %s (notebook current page before switch) ', self.__id_nb_page_before_switch)
    413                          _log.warning(' EVT_NOTEBOOK_PAGE_CHANGED.GetOldSelection(): %s (event source page)' % id_evt_page_before_switch)
    414
    415                  target_page = self.__gb['horstspace.notebook.pages'][id_evt_page_after_switch]
    416
    417                  # well-behaving wxPython port ?
    418                  if self.__target_page_already_checked:
    419                          _log.debug('target page (evt=%s, nb=%s) claims to have been checked for focussability already: %s', id_evt_page_after_switch, id_nb_page_after_switch, target_page)
    420                          target_page.receive_focus()
    421                          self.__target_page_already_checked = False
    422                          return
    423
    424                  # no, complain
    425                  _log.debug('target page not checked for focussability yet: %s', target_page)
    426                  _log.debug('EVT_NOTEBOOK_PAGE_CHANGED.GetOldSelection(): %s' % id_evt_page_before_switch)
    427                  _log.debug('EVT_NOTEBOOK_PAGE_CHANGED.GetSelection()   : %s' % id_evt_page_after_switch)
    428                  _log.debug('wx.Notebook.GetSelection() (after switch)  : %s' % id_nb_page_after_switch)
    429
    430                  # check the new page just for good measure
    431                  if target_page.can_receive_focus():
    432                          _log.debug('we are lucky: target page *can* receive focus anyway')
    433                          target_page.receive_focus()
    434                          return
    435
    436                  _log.error('target page cannot receive focus but too late for veto')
    437                  return
    438
    439  #       #----------------------------------------------
    440  #       def _on_right_click(self, evt):
    441  #               evt.Skip()
    442  #               return
    443  #
    444  #               load_menu = wx.Menu()
    445  #               any_loadable = 0
    446  #               plugins2load_by_name = gmPlugin.GetPluginLoadList('gui')
    447  #               plugin = None
    448  #               for plugin_name in plugins2load_by_name:
    449  #                       try:
    450  #                               plugin = gmPlugin.instantiate_plugin('gui', plugin_name)
    451  #                       except Exception:
    452  #                               continue
    453  #                       # not a plugin
    454  #                       if not isinstance(plugin, gmPlugin.cNotebookPlugin):
    455  #                               plugin = None
    456  #                               continue
    457  #                       # already loaded ?
    458  #                       if plugin.__class__.__name__ in self.guibroker['horstspace.notebook.gui'].keys():
    459  #                               plugin = None
    460  #                               continue
    461  #                       # add to load menu
    462  #                       item = load_menu.AppendItem(wx.MenuItem(load_menu, plugin.name()))
    463  #                       self.Bind(wx.EVT_MENU, plugin.on_load, load_menu_OR_item)
    464  #                       any_loadable = 1
    465  #               # make menus
    466  #               menu = wx.Menu()
    467  #               ID_LOAD = wx.NewId()
    468  #               ID_DROP = wx.NewId()
    469  #               if any_loadable:
    470  #                       menu.Append(ID_LOAD, _('add plugin ...'), load_menu)
    471  #               plugins = self.guibroker['horstspace.notebook.gui']
    472  #               raised_plugin = plugins[self.nb.GetSelection()].name()
    473  #               item = menu.AppendItem(wx.MenuItem(-1, "drop [%s]" % raised_plugin))
    474  #               self.Bind(wx.EVT_MENU, self._on_drop_plugin, item)
    475  #               self.PopupMenu(menu, evt.GetPosition())
    476  #               menu.DestroyLater()
    477  #               evt.Skip()
    478
    479          #----------------------------------------------
    480 -        def _on_drop_plugin(self, evt):
    481                  """Unload plugin and drop from load list."""
    482                  pages = self.guibroker['horstspace.notebook.pages']
    483                  page = pages[self.nb.GetSelection()]
    484                  page.unregister()
    485                  self.nb.AdvanceSelection()
    486                  # FIXME:"dropping" means talking to configurator so not reloaded
    487
    488          #----------------------------------------------
    489 -        def _on_hide_plugin (self, evt):
    490                  """Unload plugin but don't touch configuration."""
    491                  # this dictionary links notebook page numbers to plugin objects
    492                  pages = self.guibroker['horstspace.notebook.pages']
    493                  page = pages[self.nb.GetSelection()]
    494                  page.unregister()
    495
    496  #==============================================================================
    497  if __name__ == '__main__':
    498          wx.InitAllImageHandlers()
    499          pgbar = gmPluginLoadProgressBar(3)
    500