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