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  # $Source: /cvsroot/gnumed/gnumed/gnumed/client/wxpython/gui/gmXdtViewer.py,v $ 
 14  # $Id: gmXdtViewer.py,v 1.39 2009/06/29 15:12:49 ncq Exp $ 
 15  __version__ = "$Revision: 1.39 $" 
 16  __author__ = "S.Hilbert, K.Hilbert" 
 17   
 18  import sys, os, os.path, codecs, logging 
 19   
 20   
 21  import wx 
 22   
 23   
 24  from Gnumed.wxpython import gmGuiHelpers, gmPlugin 
 25  from Gnumed.pycommon import gmI18N, gmDispatcher 
 26  from Gnumed.business import gmXdtMappings, gmXdtObjects 
 27  from Gnumed.wxGladeWidgets import wxgXdtListPnl 
 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', 'xDT')) 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
365 - def name(self):
366 return gmXdtViewer.tab_name
367
368 - def GetWidget(self, parent):
369 self._widget = cXdtListPnl(parent, -1) 370 return self._widget
371
372 - def MenuInfo(self):
373 return ('tools', _('&xDT viewer'))
374
375 - def can_receive_focus(self):
376 return True
377 #====================================================== 378 # main 379 #------------------------------------------------------ 380 if __name__ == '__main__': 381 from Gnumed.pycommon import gmCfg2 382 383 cfg = gmCfg2.gmCfgData() 384 cfg.add_cli(long_options=['xdt-file=']) 385 #--------------------- 386 # set up dummy app
387 - class TestApp (wx.App):
388 - def OnInit (self):
389 390 fname = "" 391 # has the user manually supplied a config file on the command line ? 392 fname = cfg.get(option = '--xdt-file', source_order = [('cli', 'return')]) 393 if fname is not None: 394 _log.debug('XDT file is [%s]' % fname) 395 # file valid ? 396 if not os.access(fname, os.R_OK): 397 title = _('Opening xDT file') 398 msg = _('Cannot open xDT file.\n' 399 '[%s]') % fname 400 gmGuiHelpers.gm_show_error(msg, title) 401 return False 402 else: 403 title = _('Opening xDT file') 404 msg = _('You must provide an xDT file on the command line.\n' 405 'Format: --xdt-file=<file>') 406 gmGuiHelpers.gm_show_error(msg, title) 407 return False 408 409 frame = wx.Frame( 410 parent = None, 411 id = -1, 412 title = _("XDT Viewer"), 413 size = wx.Size(800,600) 414 ) 415 pnl = gmXdtViewerPanel(frame, fname) 416 pnl.Populate() 417 frame.Show(1) 418 return True
419 #--------------------- 420 try: 421 app = TestApp () 422 app.MainLoop () 423 except StandardError: 424 _log.exception('Unhandled exception.') 425 raise 426 427 #============================================================================= 428 # $Log: gmXdtViewer.py,v $ 429 # Revision 1.39 2009/06/29 15:12:49 ncq 430 # - do not force loading of an xDT file on tab-in anymore 431 # 432 # Revision 1.38 2009/01/15 11:41:18 ncq 433 # - improved list layout 434 # 435 # Revision 1.37 2008/03/06 18:32:31 ncq 436 # - standard lib logging only 437 # 438 # Revision 1.36 2008/01/30 14:03:42 ncq 439 # - use signal names directly 440 # - switch to std lib logging 441 # 442 # Revision 1.35 2008/01/28 16:15:50 ncq 443 # - fix typo 444 # 445 # Revision 1.34 2008/01/22 12:26:24 ncq 446 # - better tab names 447 # 448 # Revision 1.33 2008/01/05 16:42:02 ncq 449 # - no more logging in gm_show_*() 450 # 451 # Revision 1.32 2007/12/26 20:19:34 ncq 452 # - add = to long options 453 # 454 # Revision 1.31 2007/12/26 14:35:51 ncq 455 # - move to gmLog2/gmCfg2 456 # 457 # Revision 1.30 2007/12/11 12:49:26 ncq 458 # - explicit signal handling 459 # 460 # Revision 1.29 2007/08/29 14:43:43 ncq 461 # - show xDT field ID in third column to enable more comfortable debugging 462 # 463 # Revision 1.28 2007/08/12 00:12:41 ncq 464 # - no more gmSignals.py 465 # 466 # Revision 1.27 2007/05/21 13:06:39 ncq 467 # - proper chatch-all wildcard * rather than *.* 468 # 469 # Revision 1.26 2007/05/14 13:11:25 ncq 470 # - use statustext() signal 471 # 472 # Revision 1.25 2007/01/21 12:22:44 ncq 473 # - use determine_xdt_encoding() 474 # 475 # Revision 1.24 2006/11/24 10:01:31 ncq 476 # - gm_beep_statustext() -> gm_statustext() 477 # 478 # Revision 1.23 2006/10/31 16:05:40 ncq 479 # - exit first scan as soon as encoding was found 480 # - assume iso8859-1 if not found 481 # - display LDT file name in first line of list control 482 # 483 # Revision 1.22 2006/10/30 16:48:13 ncq 484 # - bring back in line with the plugin framework 485 # 486 # Revision 1.21 2006/07/19 20:32:11 ncq 487 # - cleanup 488 # 489 # Revision 1.20 2005/12/06 16:44:16 ncq 490 # - make it work standalone again 491 # 492 # Revision 1.19 2005/09/28 21:27:30 ncq 493 # - a lot of wx2.6-ification 494 # 495 # Revision 1.18 2005/09/26 18:01:52 ncq 496 # - use proper way to import wx26 vs wx2.4 497 # - note: THIS WILL BREAK RUNNING THE CLIENT IN SOME PLACES 498 # - time for fixup 499 # 500 # Revision 1.17 2004/08/04 17:16:02 ncq 501 # - wx.NotebookPlugin -> cNotebookPlugin 502 # - derive cNotebookPluginOld from cNotebookPlugin 503 # - make cNotebookPluginOld warn on use and implement old 504 # explicit "main.notebook.raised_plugin"/ReceiveFocus behaviour 505 # - ReceiveFocus() -> receive_focus() 506 # 507 # Revision 1.16 2004/06/25 12:37:21 ncq 508 # - eventually fix the import gmI18N issue 509 # 510 # Revision 1.15 2004/06/13 22:31:49 ncq 511 # - gb['main.toolbar'] -> gb['main.top_panel'] 512 # - self.internal_name() -> self.__class__.__name__ 513 # - remove set_widget_reference() 514 # - cleanup 515 # - fix lazy load in _on_patient_selected() 516 # - fix lazy load in ReceiveFocus() 517 # - use self._widget in self.GetWidget() 518 # - override populate_with_data() 519 # - use gb['main.notebook.raised_plugin'] 520 # 521 # Revision 1.14 2004/03/19 20:43:32 shilbert 522 # - fixed import 523 # 524 # Revision 1.13 2004/03/19 10:22:12 ncq 525 # - even better help 526 # 527 # Revision 1.12 2004/03/19 10:20:29 ncq 528 # - in standalone, display nice message upon xdt file load errors 529 # 530 # Revision 1.11 2004/03/19 08:27:50 ncq 531 # - fix imports, return BOOL from OnInit 532 # 533 # Revision 1.10 2004/03/18 09:43:02 ncq 534 # - import gmI18N if standalone 535 # 536 # Revision 1.9 2003/11/17 10:56:41 sjtan 537 # 538 # synced and commiting. 539 # 540 # Revision 1.1 2003/10/23 06:02:40 sjtan 541 # 542 # manual edit areas modelled after r.terry's specs. 543 # 544 # Revision 1.8 2003/06/26 21:41:51 ncq 545 # - fatal->verbose 546 # 547 # Revision 1.7 2003/04/28 12:12:18 ncq 548 # - refactor name(), better CANCEL handling on file select dialog 549 # 550 # Revision 1.6 2003/04/25 13:04:39 ncq 551 # - reorder variable use so fname is defined when logging 552 # 553 # Revision 1.5 2003/02/19 15:56:33 ncq 554 # - don't fail on malformed lines 555 # 556 # Revision 1.4 2003/02/19 12:42:38 ncq 557 # - further dict()ified __decode_xdt() 558 # 559 # Revision 1.3 2003/02/16 13:54:47 ncq 560 # - renamed command line option to --xdt-file= 561 # 562 # Revision 1.2 2003/02/15 15:33:58 ncq 563 # - typo 564 # 565 # Revision 1.1 2003/02/15 14:21:49 ncq 566 # - on demand loading of Manual 567 # - further pluginization of showmeddocs 568 # 569 # Revision 1.5 2003/02/15 13:52:08 ncq 570 # - hey, works as a plugin too, now :-)) 571 # 572 # Revision 1.4 2003/02/15 12:17:28 ncq 573 # - much better suited for plugin use 574 # 575 # Revision 1.3 2003/02/15 10:53:10 ncq 576 # - works standalone 577 # 578 # Revision 1.2 2003/02/13 15:51:09 ncq 579 # - added TODO 580 # 581 # Revision 1.1 2003/02/13 15:25:15 ncq 582 # - first version, works standalone only 583 # 584