Package Gnumed :: Package wxpython :: Package gui :: Module gmXdtViewer |
[frames] | no frames]

# Source Code for Module Gnumed.wxpython.gui.gmXdtViewer

      1  """GNUmed xDT viewer.
      2
      3  TODO:
      4
      5  - popup menu on right-click
      6    - import this line
      7    - import all lines like this
      8    - search
      9    - print
     10    - ...
     11  """
     12  #=============================================================================
     13  __version__ = "$Revision: 1.39 $"
     14  __author__ = "S.Hilbert, K.Hilbert"
     15
     16  import sys, os, os.path, codecs, logging
     17
     18
     19  import wx
     20
     21
     22  from Gnumed.wxpython import gmGuiHelpers, gmPlugin
     23  from Gnumed.pycommon import gmI18N, gmDispatcher
     24  from Gnumed.business import gmXdtMappings, gmXdtObjects
     25  from Gnumed.wxGladeWidgets import wxgXdtListPnl
     26  from Gnumed.wxpython import gmAccessPermissionWidgets
     27
     28
     29  _log = logging.getLogger('gm.ui')
     30  _log.info(__version__)
     31
     32  #=============================================================================
     33  # FIXME: this belongs elsewhere under wxpython/
     34 -class cXdtListPnl(wxgXdtListPnl.wxgXdtListPnl):
     35 -        def __init__(self, *args, **kwargs):
     36                  wxgXdtListPnl.wxgXdtListPnl.__init__(self, *args, **kwargs)
     37
     38                  self.filename = None
     39
     40                  self.__cols = [
     41                          _('Field name'),
     42                          _('Interpreted content'),
     43                          _('xDT field ID'),
     44                          _('Raw content')
     45                  ]
     46                  self.__init_ui()
     47          #--------------------------------------------------------------
     48 -        def __init_ui(self):
     49                  for col in range(len(self.__cols)):
     50                          self._LCTRL_xdt.InsertColumn(col, self.__cols[col])
     51          #--------------------------------------------------------------
     52          # external API
     53          #--------------------------------------------------------------
     54 -        def select_file(self, path=None):
     55                  if path is None:
     56                          root_dir = os.path.expanduser(os.path.join('~', 'gnumed'))
     57                  else:
     58                          root_dir = path
     59                  # get file name
     60                  # - via file select dialog
     61                  dlg = wx.FileDialog (
     62                          parent = self,
     63                          message = _("Choose an xDT file"),
     64                          defaultDir = root_dir,
     65                          defaultFile = '',
     66                          wildcard = '%s (*.xDT)|*.?DT;*.?dt|%s (*)|*|%s (*.*)|*.*' % (_('xDT files'), _('all files'), _('all files (Win)')),
     67                          style = wx.OPEN | wx.FILE_MUST_EXIST
     68                  )
     69                  choice = dlg.ShowModal()
     70                  fname = None
     71                  if choice == wx.ID_OK:
     72                          fname =  dlg.GetPath()
     73                  dlg.Destroy()
     74                  return fname
     75          #--------------------------------------------------------------
     76 -        def load_file(self, filename=None):
     77                  if filename is None:
     78                          filename = self.select_file()
     79                  if filename is None:
     80                          return True
     81
     82                  self.filename = None
     83
     84                  try:
     85                          f = file(filename, 'r')
     86                  except IOError:
     87                          gmGuiHelpers.gm_show_error (
     88                                  _('Cannot access xDT file\n\n'
     89                                    ' [%s]'),
     90                                  _('loading xDT file')
     91                          )
     92                          return False
     93                  f.close()
     94
     95                  encoding = gmXdtObjects.determine_xdt_encoding(filename = filename)
     96                  if encoding is None:
     97                          encoding = 'utf8'
     98                          gmDispatcher.send(signal = 'statustext', msg = _('Encoding missing in xDT file. Assuming [%s].') % encoding)
     99                          _log.warning('xDT file [%s] does not define an encoding, assuming [%s]' % (filename, encoding))
    100
    101                  try:
    102                          xdt_file = codecs.open(filename=filename, mode='rU', encoding=encoding, errors='replace')
    103                  except IOError:
    104                          gmGuiHelpers.gm_show_error (
    105                                  _('Cannot access xDT file\n\n'
    106                                    ' [%s]'),
    107                                  _('loading xDT file')
    108                          )
    109                          return False
    110
    111                  # parse and display file
    112                  self._LCTRL_xdt.DeleteAllItems()
    113
    114                  self._LCTRL_xdt.InsertStringItem(index=0, label=_('name of xDT file'))
    115                  self._LCTRL_xdt.SetStringItem(index=0, col=1, label=filename)
    116
    117                  idx = 1
    118                  for line in xdt_file:
    119                          line = line.replace('\015','')
    120                          line = line.replace('\012','')
    121                          length, field, content = line[:3], line[3:7], line[7:]
    122
    123                          try:
    124                                  left = gmXdtMappings.xdt_id_map[field]
    125                          except KeyError:
    126                                  left = field
    127
    128                          try:
    129                                  right = gmXdtMappings.xdt_map_of_content_maps[field][content]
    130                          except KeyError:
    131                                  right = content
    132
    133                          self._LCTRL_xdt.InsertStringItem(index=idx, label=left)
    134                          self._LCTRL_xdt.SetStringItem(index=idx, col=1, label=right)
    135                          self._LCTRL_xdt.SetStringItem(index=idx, col=2, label=field)
    136                          self._LCTRL_xdt.SetStringItem(index=idx, col=3, label=content)
    137                          idx += 1
    138
    139                  xdt_file.close()
    140
    141                  self._LCTRL_xdt.SetColumnWidth(0, wx.LIST_AUTOSIZE)
    142                  self._LCTRL_xdt.SetColumnWidth(1, wx.LIST_AUTOSIZE)
    143
    144                  self._LCTRL_xdt.SetFocus()
    145                  self._LCTRL_xdt.SetItemState (
    146                          item = 0,
    147                          state = wx.LIST_STATE_SELECTED | wx.LIST_STATE_FOCUSED,
    148                          stateMask = wx.LIST_STATE_SELECTED | wx.LIST_STATE_FOCUSED
    149                  )
    150
    151                  self.filename = filename
    152          #--------------------------------------------------------------
    153          # event handlers
    154          #--------------------------------------------------------------
    155 -        def _on_load_button_pressed(self, evt):
    156                  self.load_file()
    157          #--------------------------------------------------------------
    158          # plugin API
    159          #--------------------------------------------------------------
    160 -        def repopulate_ui(self):
    161  #               if self.filename is None:
    162  #                       self.load_file()
    163                  return
    164  #=============================================================================
    165 -class gmXdtViewerPanel(wx.Panel):
    166 -        def __init__(self, parent, aFileName = None):
    167                  wx.Panel.__init__(self, parent, -1, style=wx.WANTS_CHARS)
    168
    169                  # our actual list
    170                  tID = wx.NewId()
    171                  self.list = gmXdtListCtrl(
    172                          self,
    173                          tID,
    174                          style=wx.LC_REPORT | wx.SUNKEN_BORDER | wx.LC_VRULES
    175                  )#|wx.LC_HRULES)
    176
    177                  self.list.InsertColumn(0, _("XDT field"))
    178                  self.list.InsertColumn(1, _("XDT field content"))
    179
    180                  self.filename = aFileName
    181
    182                  # set up events
    183                  wx.EVT_SIZE(self, self.OnSize)
    184
    185                  wx.EVT_LIST_ITEM_SELECTED(self, tID, self.OnItemSelected)
    186                  wx.EVT_LIST_ITEM_DESELECTED(self, tID, self.OnItemDeselected)
    187                  wx.EVT_LIST_ITEM_ACTIVATED(self, tID, self.OnItemActivated)
    188                  wx.EVT_LIST_DELETE_ITEM(self, tID, self.OnItemDelete)
    189
    190                  wx.EVT_LIST_COL_CLICK(self, tID, self.OnColClick)
    191                  wx.EVT_LIST_COL_RIGHT_CLICK(self, tID, self.OnColRightClick)
    192  #               wx.EVT_LIST_COL_BEGIN_DRAG(self, tID, self.OnColBeginDrag)
    193  #               wx.EVT_LIST_COL_DRAGGING(self, tID, self.OnColDragging)
    194  #               wx.EVT_LIST_COL_END_DRAG(self, tID, self.OnColEndDrag)
    195
    196                  wx.EVT_LEFT_DCLICK(self.list, self.OnDoubleClick)
    197                  wx.EVT_RIGHT_DOWN(self.list, self.OnRightDown)
    198
    199                  if wx.Platform == '__WXMSW__':
    200                          wx.EVT_COMMAND_RIGHT_CLICK(self.list, tID, self.OnRightClick)
    201                  elif wx.Platform == '__WXGTK__':
    202                          wx.EVT_RIGHT_UP(self.list, self.OnRightClick)
    203
    204          #-------------------------------------------------------------------------
    205 -        def Populate(self):
    206
    207                  # populate list
    208                  items = self.__decode_xdt()
    209                  for item_idx in range(len(items),0,-1):
    210                          data = items[item_idx]
    211                          idx = self.list.InsertItem(info=wx.ListItem())
    212                          self.list.SetStringItem(index=idx, col=0, label=data[0])
    213                          self.list.SetStringItem(index=idx, col=1, label=data[1])
    214                          #self.list.SetItemData(item_idx, item_idx)
    215
    216                  # reaspect
    217                  self.list.SetColumnWidth(0, wx.LIST_AUTOSIZE)
    218                  self.list.SetColumnWidth(1, wx.LIST_AUTOSIZE)
    219
    220                  # show how to select an item
    221                  #self.list.SetItemState(5, wx.LIST_STATE_SELECTED, wx.LIST_STATE_SELECTED)
    222
    223                  # show how to change the colour of a couple items
    224                  #item = self.list.GetItem(1)
    225                  #item.SetTextColour(wx.BLUE)
    226                  #self.list.SetItem(item)
    227                  #item = self.list.GetItem(4)
    228                  #item.SetTextColour(wxRED)
    229                  #self.list.SetItem(item)
    230
    231                  self.currentItem = 0
    232          #-------------------------------------------------------------------------
    233 -        def __decode_xdt(self):
    234                  if self.filename is None:
    235                          _log.error("Need name of file to parse !")
    236                          return None
    237
    238                  xDTFile = fileinput.input(self.filename)
    239                  items = {}
    240                  i = 1
    241                  for line in xDTFile:
    242                          # remove trailing CR and/or LF
    243                          line = string.replace(line,'\015','')
    244                          line = string.replace(line,'\012','')
    245                          length ,ID, content = line[:3], line[3:7], line[7:]
    246
    247                          try:
    248                                  left = xdt_id_map[ID]
    249                          except KeyError:
    250                                  left = ID
    251
    252                          try:
    253                                  right = xdt_map_of_content_maps[ID][content]
    254                          except KeyError:
    255                                  right = content
    256
    257                          items[i] = (left, right)
    258                          i = i + 1
    259
    260                  fileinput.close()
    261                  return items
    262          #-------------------------------------------------------------------------
    263 -        def OnRightDown(self, event):
    264                  self.x = event.GetX()
    265                  self.y = event.GetY()
    266                  item, flags = self.list.HitTest((self.x, self.y))
    267                  if flags & wx.LIST_HITTEST_ONITEM:
    268                          self.list.Select(item)
    269                  event.Skip()
    270          #-------------------------------------------------------------------------
    271 -        def getColumnText(self, index, col):
    272                  item = self.list.GetItem(index, col)
    273                  return item.GetText()
    274          #-------------------------------------------------------------------------
    275 -        def OnItemSelected(self, event):
    276                  self.currentItem = event.m_itemIndex
    277          #-------------------------------------------------------------------------
    278 -        def OnItemDeselected(self, evt):
    279                  item = evt.GetItem()
    280
    281                  # Show how to reselect something we don't want deselected
    282  #               if evt.m_itemIndex == 11:
    283  #                       wxCallAfter(self.list.SetItemState, 11, wx.LIST_STATE_SELECTED, wx.LIST_STATE_SELECTED)
    284          #-------------------------------------------------------------------------
    285 -        def OnItemActivated(self, event):
    286                  self.currentItem = event.m_itemIndex
    287          #-------------------------------------------------------------------------
    288 -        def OnItemDelete(self, event):
    289                  pass
    290          #-------------------------------------------------------------------------
    291 -        def OnColClick(self, event):
    292                  pass
    293          #-------------------------------------------------------------------------
    294 -        def OnColRightClick(self, event):
    295                  item = self.list.GetColumn(event.GetColumn())
    296          #-------------------------------------------------------------------------
    297  #       def OnColBeginDrag(self, event):
    298  #               pass
    299          #-------------------------------------------------------------------------
    300  #       def OnColDragging(self, event):
    301  #               pass
    302          #-------------------------------------------------------------------------
    303  #       def OnColEndDrag(self, event):
    304  #               pass
    305          #-------------------------------------------------------------------------
    306 -        def OnDoubleClick(self, event):
    307                  event.Skip()
    308          #-------------------------------------------------------------------------
    309 -        def OnRightClick(self, event):
    310                  return
    311                  menu = wx.Menu()
    312                  tPopupID1 = 0
    313                  tPopupID2 = 1
    314                  tPopupID3 = 2
    315                  tPopupID4 = 3
    316                  tPopupID5 = 5
    317
    318                  # Show how to put an icon in the menu
    319                  item = wx.MenuItem(menu, tPopupID1,"One")
    320                  item.SetBitmap(images.getSmilesBitmap())
    321
    322                  menu.AppendItem(item)
    323                  menu.Append(tPopupID2, "Two")
    324                  menu.Append(tPopupID3, "ClearAll and repopulate")
    325                  menu.Append(tPopupID4, "DeleteAllItems")
    326                  menu.Append(tPopupID5, "GetItem")
    327                  wx.EVT_MENU(self, tPopupID1, self.OnPopupOne)
    328                  wx.EVT_MENU(self, tPopupID2, self.OnPopupTwo)
    329                  wx.EVT_MENU(self, tPopupID3, self.OnPopupThree)
    330                  wx.EVT_MENU(self, tPopupID4, self.OnPopupFour)
    331                  wx.EVT_MENU(self, tPopupID5, self.OnPopupFive)
    332                  self.PopupMenu(menu, wxPoint(self.x, self.y))
    333                  menu.Destroy()
    334                  event.Skip()
    335          #-------------------------------------------------------------------------
    336 -        def OnPopupOne(self, event):
    337                  print "FindItem:", self.list.FindItem(-1, "Roxette")
    338                  print "FindItemData:", self.list.FindItemData(-1, 11)
    339          #-------------------------------------------------------------------------
    340 -        def OnPopupTwo(self, event):
    341                  pass
    342          #-------------------------------------------------------------------------
    343 -        def OnPopupThree(self, event):
    344                  self.list.ClearAll()
    345                  wx.CallAfter(self.PopulateList)
    346                  #wxYield()
    347                  #self.PopulateList()
    348          #-------------------------------------------------------------------------
    349 -        def OnPopupFour(self, event):
    350                  self.list.DeleteAllItems()
    351          #-------------------------------------------------------------------------
    352 -        def OnPopupFive(self, event):
    353                  item = self.list.GetItem(self.currentItem)
    354                  print item.m_text, item.m_itemId, self.list.GetItemData(self.currentItem)
    355          #-------------------------------------------------------------------------
    356 -        def OnSize(self, event):
    357                  w,h = self.GetClientSizeTuple()
    358                  self.list.SetDimensions(0, 0, w, h)
    359  #======================================================
    360 -class gmXdtViewer(gmPlugin.cNotebookPlugin):
    361          """Plugin to encapsulate xDT list-in-panel viewer"""
    362
    363          tab_name = _('xDT viewer')
    364          required_minimum_role = 'staff'
    365
    366          @gmAccessPermissionWidgets.verify_minimum_required_role (
    367                  required_minimum_role,
    368                  activity = _('loading plugin <%s>') % tab_name,
    369                  return_value_on_failure = False,
    370                  fail_silently = False
    371          )
    372 -        def register(self):
    373                  gmPlugin.cNotebookPlugin.register(self)
    374          #-------------------------------------------------
    375
    376 -        def name(self):
    377                  return gmXdtViewer.tab_name
    378
    379 -        def GetWidget(self, parent):
    380                  self._widget = cXdtListPnl(parent, -1)
    381                  return self._widget
    382
    383 -        def MenuInfo(self):
    384                  return ('tools', _('&xDT viewer'))
    385
    386 -        def can_receive_focus(self):
    387                  return True
    388  #======================================================
    389  # main
    390  #------------------------------------------------------
    391  if __name__ == '__main__':
    392          from Gnumed.pycommon import gmCfg2
    393
    394          cfg = gmCfg2.gmCfgData()
    395          cfg.add_cli(long_options=['xdt-file='])
    396          #---------------------
    397          # set up dummy app
    398 -        class TestApp (wx.App):
    399 -                def OnInit (self):
    400
    401                          fname = ""
    402                          # has the user manually supplied a config file on the command line ?
    403                          fname = cfg.get(option = '--xdt-file', source_order = [('cli', 'return')])
    404                          if fname is not None:
    405                                  _log.debug('XDT file is [%s]' % fname)
    406                                  # file valid ?
    407                                  if not os.access(fname, os.R_OK):
    408                                          title = _('Opening xDT file')
    409                                          msg = _('Cannot open xDT file.\n'
    410                                                          '[%s]') % fname
    411                                          gmGuiHelpers.gm_show_error(msg, title)
    412                                          return False
    413                          else:
    414                                  title = _('Opening xDT file')
    415                                  msg = _('You must provide an xDT file on the command line.\n'
    416                                                  'Format: --xdt-file=<file>')
    417                                  gmGuiHelpers.gm_show_error(msg, title)
    418                                  return False
    419
    420                          frame = wx.Frame(
    421                                  parent = None,
    422                                  id = -1,
    423                                  title = _("XDT Viewer"),
    424                                  size = wx.Size(800,600)
    425                          )
    426                          pnl = gmXdtViewerPanel(frame, fname)
    427                          pnl.Populate()
    428                          frame.Show(1)
    429                          return True
    430          #---------------------
    431          try:
    432                  app = TestApp ()
    433                  app.MainLoop ()
    434          except StandardError:
    435                  _log.exception('Unhandled exception.')
    436                  raise
    437
    438  #=============================================================================
    439