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

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

      1  #############################################################################
      2  #
      3  # gmDrugDisplay_RT  Feedback: anything which is incorrect or ambiguous please
      4  #                   mailto rterry@gnumed.net
      5  # ---------------------------------------------------------------------------
      6  #
      7  # @author: Dr. Richard Terry
      8  # @author: Dr. Herb Horst
      9  # @author: Hilmar Berger
     10  # @acknowledgments: Gui screen Design taken with permission from
     11  #                   DrsDesk MimsAnnual @ DrsDesk Software 1995-2002
     12  #                   and @ Dr.R Terry
     13  #                   Basic skeleton of this code written by Dr. H Horst
     14  #                   heavily commented for learning purposes by Dr. R Terry
     15  # @copyright: authors
     16  # @license: GPL v2 or later (details at http://www.gnu.org)
     17  #
     18  # @TODO:
     19  #        decision of text display wigit
     20  #        why won't opening frame size be recognised
     21  #        put in testing for null field in Display_PI
     22  #        so as not to display a null field heading
     23  #        Need config file with:
     24  #        HTML font options for heading, subheading, subsubheading etc
     25  ############################################################################
     26  # $Source: /home/ncq/Projekte/cvs2git/vcs-mirror/gnumed/gnumed/client/wxpython/gui/gmDrugDisplay.py,v $
     27  __version__ = "$Revision: 1.34 $"
     28  __author__ = "H.Herb, R.Terry, H.Berger"
     29
     30  import string
     31
     32
     33  import wx
     34
     35
     36  _log = logging.getLogger('gm.ui')
     37  if __name__ == "__main__":
     38          # FIXME: standalone means diagnostics for now,
     39          # later on, when AmisBrowser is one foot in the door
     40          # to German doctors we'll change this again
     41          _log.SetAllLogLevels(gmLog.lData)
     42          _ = lambda x:x  # fool epydoc
     43          from Gnumed.pycommon import gmI18N
     44
     45
     46  from Gnumed.pycommon import gmDrugView, gmCfg, gmExceptions
     47  from Gnumed.wxpython import gmGuiHelpers
     48  from Gnumed.business import gmSurgery
     49
     50  _cfg = gmCfg.gmDefCfgFile
     51  #============================================================
     52  # These constants are used when referring to menu items below
     53  #============================================================
     54  ID_ABOUT = wx.NewId()
     55  ID_CONTENTS = wx.NewId()
     56  ID_EXIT  =  wx.NewId()
     57  ID_OPEN= wx.NewId()
     58  ID_HELP =  wx.NewId()
     59  ID_TEXTCTRL =  wx.NewId()
     60  ID_TEXT = wx.NewId()
     61  ID_COMBO_PRODUCT = wx.NewId()
     62  ID_RADIOBUTTON_BYANY = wx.NewId()
     63  ID_RADIOBUTTON_BYBRAND = wx.NewId()
     64  ID_RADIOBUTTON_BYGENERIC = wx.NewId()
     65  ID_RADIOBUTTON_BYINDICATION = wx.NewId()
     66  ID_LISTBOX_JUMPTO = wx.NewId()
     67  ID_LISTCTRL_DRUGCHOICE = wx.NewId()
     68  ID_BUTTON_PRESCRIBE = wx.NewId()
     69  ID_BUTTON_DISPLAY = wx.NewId()
     70  ID_BUTTON_PRINT = wx.NewId()
     71  ID_BUTTON_BOOKMARK = wx.NewId()
     72
     73  MODE_BRAND = 0
     74  MODE_GENERIC = 1
     75  MODE_INDICATION = 2
     76  MODE_ANY = 3    # search for brand name and generic name
     77
     78  #============================================================
     79 -class DrugDisplay(wx.Panel):
     80          """displays drug information in a convenience widget"""
     81
     82          NoDrugFoundMessageHTML  = "<HTML><HEAD></HEAD><BODY BGCOLOR='#FFFFFF8'> <FONT SIZE=3>" +     _("No matching drug found.") + "</FONT></BODY></HTML>"
     83          WelcomeMessageHTML      = "<HTML><HEAD></HEAD><BODY BGCOLOR='#FFFFFF8'> <FONT SIZE=3>" +     _("Please enter at least three digits of the drug name.") + "</FONT></BODY></HTML>"
     84
     85 -        def __init__(self, parent, id, pos = wxDefaultPosition,
     86                                   size = wxDefaultSize, style = wx.TAB_TRAVERSAL):
     87
     88                  wx.Panel.__init__(self, parent, id, pos, size, style)
     89
     90                  # if we are not inside gnumed we won't get a definite answer on
     91                  # who and where we are. in this case try to get config source
     92                  # from main config file (see gmCfg on how the name of this file
     93                  # is determined
     94                  # this is necessary to enable stand alone use of the drug browser
     95                  currworkplace = gmSurgery.gmCurrentPractice().active_workplace
     96                  if currworkplace is None:
     97                          # assume we are outside gnumed
     98                          self.dbName = _cfg.get('DrugReferenceBrowser', 'drugDBname')
     99                  else:
    100                          self.dbName, match = gmCfg.getDBParam(
    101                                  currworkplace,
    102                                  option="DrugReferenceBrowser.drugDBName"
    103                          )
    104
    105                  if self.dbName is None:
    106                          if __name__ == '__main__':
    107                                  title = _('Starting drug data browser')
    108                                  msg = _('Cannot start the drug data browser.\n\n'
    109                                                  'There is no drug database specified in the configuration.')
    110                                  gmGuiHelpers.gm_show_error(msg, title)
    111                          _log.Log(gmLog.lErr, "No drug database specified. Aborting drug browser.")
    112                          # FIXME: we shouldn't directly call Close() on the parent
    113  #                       parent.Close()
    114                          raise gmExceptions.ConstructorError, "No drug database specified"
    115
    116                  # initialize interface to drug database.
    117                  # this will fail if backend or config files are not available
    118                  try:
    119                          self.mDrugView=gmDrugView.DrugView(self.dbName)
    120                  except:
    121                          _log.LogException("Unhandled exception during DrugView API init.", sys.exc_info(), verbose = 0)
    122                          raise gmExceptions.ConstructorError, "Couldn't initialize DrugView API"
    123  #                       return None
    124
    125                  self.mode = MODE_BRAND
    126                  self.previousMode = MODE_BRAND
    127                  self.printer = wx.HtmlEasyPrinting()            #printer object to print html page
    128                  self.mId = None
    129                  self.drugProductInfo = None
    130                  self.__mListCtrlItems = {}              # array holding data on every row in the list
    131
    132                  #-------------------------------------------------------------
    133                  # These things build the physical window that you see when
    134                  # the program boots. They each refer to a subroutine that
    135                  # is listed below by the same name eg def Menus_Create(self)
    136                  #-------------------------------------------------------------
    137                  self.GuiElements_Init()     # add main gui elements
    138                  self.inDisplay_PI = 0       # first we display a drug list, not product info
    139                  self.GetDrugIssue()         # ?
    140
    141                  #--------------------------------------------------------------
    142                  # handler declarations for DrugDisplay
    143                  # note handlers for menu in Menus_Create()
    144                  #--------------------------------------------------------------
    145                  wx.EVT_BUTTON(self, ID_BUTTON_PRINT, self.OnPrint)
    146                  wx.EVT_BUTTON(self, ID_BUTTON_DISPLAY, self.OnDisplay)
    147                  wx.EVT_BUTTON(self, ID_BUTTON_PRESCRIBE, self.OnPrescribe)
    148                  wx.EVT_LISTBOX_DCLICK(self, ID_LISTBOX_JUMPTO, self.OnJumpToDblClick)
    149                  wx.EVT_LISTBOX(self, ID_LISTBOX_JUMPTO, self.OnJumpToSelected)
    150                  wx.EVT_LIST_ITEM_ACTIVATED(self, ID_LISTCTRL_DRUGCHOICE, self.OnDrugChoiceDblClick)
    151                  wx.EVT_RADIOBUTTON(self, ID_RADIOBUTTON_BYINDICATION, self.OnSearchByIndication)
    152                  wx.EVT_RADIOBUTTON(self, ID_RADIOBUTTON_BYGENERIC, self.OnSearchByGeneric)
    153                  wx.EVT_RADIOBUTTON(self, ID_RADIOBUTTON_BYBRAND, self.OnSearchByBrand)
    154                  wx.EVT_RADIOBUTTON(self, ID_RADIOBUTTON_BYANY, self.OnSearchByAny)
    155                  wx.EVT_TEXT(self, ID_COMBO_PRODUCT, self.OnProductKeyPressed)
    156                  wx.EVT_COMBOBOX(self, ID_COMBO_PRODUCT, self.OnProductSelected)
    157                  wx.EVT_BUTTON(self, wxID_OK, self.OnOk)
    158                  wx.EVT_BUTTON(self, wxID_CANCEL, self.OnCancel)
    159                  wx.EVT_BUTTON(self,ID_BUTTON_BOOKMARK, self.OnBookmark)
    160  #-----------------------------------------------------------------------------------------------------------------------
    161
    162 -        def GuiElements_Init(self):
    163                  #--------------------------------------------------
    164                  # create the controls for left hand side of screen
    165                  # 1)create the label 'Find' and the combo box the
    166                  #   user will type the name of drug into
    167                  #--------------------------------------------------
    168                  finddrug = wxStaticText( self, -1, _("   Find   "), wxDefaultPosition, wxDefaultSize, 0 )
    169                  finddrug.SetFont( wxFont( 14, wxSWISS, wx.NORMAL, wx.NORMAL ) )
    170
    171                  self.comboProduct = wxComboBox(
    172                          self,
    173                          ID_COMBO_PRODUCT,
    174                          "",
    175                          wxDefaultPosition,
    176                          wxSize(130,-1),
    177                          [] ,
    178                          wxCB_DROPDOWN
    179                  )
    180                  self.comboProduct.SetToolTip( wx.ToolTip(_("Enter the name of the drug you are interested in")) )
    181                  self.btnBookmark = wx.Button(
    182                          self,
    183                          ID_BUTTON_BOOKMARK,
    184                          _("&Bookmark"),
    185                          wxDefaultPosition,
    186                          wxDefaultSize,
    187                          0
    188                  )
    189                  #-----------------------------------------------------------
    190                  # create a sizer at topleft of screen to hold these controls
    191                  # and add them to it
    192                  #-----------------------------------------------------------
    193                  self.sizertopleft = wx.BoxSizer(wx.HORIZONTAL)
    194                  self.sizertopleft.Add( finddrug, 0, wxALIGN_CENTER_VERTICAL, 5 )
    195                  self.sizertopleft.Add( self.comboProduct, 1, wxGROW|wxALIGN_CENTER_VERTICAL, 5 )
    196                  self.sizertopleft.Add( self.btnBookmark, 0, wxALIGN_CENTER_VERTICAL, 5 )
    197                  #---------------------------------------------------------------
    198                  # next create the left sizer which will hold the drug list box
    199                  # and the html viewer
    200                  #---------------------------------------------------------------
    201                  self.sizer_left = wx.BoxSizer( wx.VERTICAL )
    202                  self.sizer_left.AddSpacer( 30, 10, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 1 )
    203                  self.sizer_left.AddSizer( self.sizertopleft, 0, wxGROW|wxALIGN_CENTER_VERTICAL, 5)
    204                  self.sizer_left.AddSpacer( 1, 1, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 1 )
    205                  self.listctrl_drugchoice=None
    206                  self.html_viewer=None
    207                  self.whichWidget = "listctrl_drugchoice"
    208                  self.ToggleWidget()
    209                  self.html_viewer.SetPage(self.WelcomeMessageHTML)
    210
    211                  #------------------------------------------------------------------------
    212                  # the search by option buttons sit on a wxStaticBoxSizer with wx.Vertical
    213                  # 1) create a wxStaticBox = bordered box with title search by
    214                  # 2) add this to the sizerSearchBy sizer
    215                  # 3) Add four radio buttons to this sizer
    216                  #------------------------------------------------------------------------
    217                  sboxSearchBy = wxStaticBox( self, -1, _("Search by") )
    218                  self.sizerSearchBy = wxStaticBoxSizer( sboxSearchBy, wx.VERTICAL )
    219                  sboxSearchBy.SetFont( wxFont( 10, wxSWISS, wx.NORMAL, wx.NORMAL ) )
    220
    221                  self.rbtnSearchAny = wxRadioButton( self, ID_RADIOBUTTON_BYANY, _("Any"), wxDefaultPosition, wxDefaultSize, 0 )
    222                  self.sizerSearchBy.Add( self.rbtnSearchAny, 0, wxGROW|wxALIGN_CENTER_VERTICAL, 1 )
    223                  self.rbtnSearchBrand = wxRadioButton( self, ID_RADIOBUTTON_BYBRAND, _("Brand name"), wxDefaultPosition, wxDefaultSize, 0 )
    224                  self.sizerSearchBy.Add( self.rbtnSearchBrand, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wx.TOP, 1 )
    225                  self.rbtnSearchGeneric = wxRadioButton( self, ID_RADIOBUTTON_BYGENERIC, _("Generic name"), wxDefaultPosition, wxDefaultSize, 0 )
    226                  self.sizerSearchBy.Add( self.rbtnSearchGeneric, 0, wxGROW|wxALIGN_CENTER_VERTICAL, 1 )
    227                  self.rbtnSearchIndication = wxRadioButton( self, ID_RADIOBUTTON_BYINDICATION, _("Indication"), wxDefaultPosition, wxDefaultSize, 0 )
    228                  self.sizerSearchBy.Add( self.rbtnSearchIndication, 0, wxGROW|wxALIGN_CENTER_VERTICAL, 1 )
    229                  #-------------------------------------------------------------------------
    230                  # and the right hand side vertical side bar sizer
    231                  # 1) add a space at top to make the static text box even with the top
    232                  #    of the main drug data display box
    233                  # 2) add the searchby static box with the radio buttons which is stuck on
    234                  #    to its own sizer
    235                  # 3) add a spacer below this and above the list box underneath
    236                  #-------------------------------------------------------------------------
    237                  self.sizerVInteractionSidebar = wx.BoxSizer( wx.VERTICAL )
    238                  self.sizerVInteractionSidebar.AddSpacer( 30, 10, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 12 )
    239                  self.sizerVInteractionSidebar.AddSizer( self.sizerSearchBy, 0, wxGROW|wxALIGN_CENTER_VERTICAL, 5 )
    240                  self.sizerVInteractionSidebar.AddSpacer( 30, 10, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 1 )
    241                  #--------------------------------------------------------------------------
    242                  # 4) create a listbox that will be populated with labels to jump to within the
    243                  #    product info text and add to the vertical side bar
    244                  #--------------------------------------------------------------------------
    245                  self.listbox_jumpto = wx.ListBox( self, ID_LISTBOX_JUMPTO, wxDefaultPosition, wxSize(150,100),
    246                          [] , wx.LB_SINGLE )
    247                  self.sizerVInteractionSidebar.Add( self.listbox_jumpto, 1, wxGROW|wxALIGN_CENTER_VERTICAL, 10 )
    248                  #--------------------------------------------------------------------------
    249                  # 5) Add another spacer underneath this listbox
    250                  #--------------------------------------------------------------------------
    251                  self.sizerVInteractionSidebar.AddSpacer( 20, 10, 0, wxALIGN_CENTRE|wxALL, 1 )
    252                  self.btnPrescribe = wx.Button( self, ID_BUTTON_PRESCRIBE, _("&Prescribe"), wxDefaultPosition, wxDefaultSize, 0 )
    253                  self.sizerVInteractionSidebar.Add( self.btnPrescribe, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 1 )
    254                  self.btnDisplay = wx.Button( self, ID_BUTTON_DISPLAY, _("&Display"), wxDefaultPosition, wxDefaultSize, 0 )
    255                  self.sizerVInteractionSidebar.Add( self.btnDisplay, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 1 )
    256                  self.btnPrint = wx.Button( self, ID_BUTTON_PRINT, _("&Print"), wxDefaultPosition, wxDefaultSize, 0 )
    257                  self.sizerVInteractionSidebar.Add( self.btnPrint, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 1 )
    258                  #-----------------------------------------------
    259                  # finally create the main sizer to hold the rest
    260                  # and all the sizers to the main sizer
    261                  #---------------------------------------------
    262                  self.sizermain = wx.BoxSizer(wx.HORIZONTAL)
    263                  self.sizermain.AddSizer(self.sizer_left, 1, wxGROW|wxALIGN_CENTER_HORIZONTAL|wxALL, 7)
    264                  self.sizermain.AddSizer(self.sizerVInteractionSidebar, 0, wxGROW|wxALIGN_LEFT|wxALL, 8)
    265                  self.SetAutoLayout( True )
    266                  self.SetSizer( self.sizermain )
    267                  self.sizermain.Fit( self )
    268                  self.sizermain.SetSizeHints( self )
    269
    270  #----------------------------------------------------------------------------------------------------------------------
    271          #--------------------------------
    272          # methods for DrugDisplay
    273          #--------------------------------
    274
    275 -        def OnDrugChoiceDblClick(self,event):
    276                  """
    277                  handle double clicks in list of drugs / substances.
    278                  """
    279                  # get row of selected event
    280                  item = event.GetData()
    281                  # get drug id and query mode
    282                  mode, code = self.__mListCtrlItems[item]
    283  #               gmLog.gmDefLog.Log (gmLog.lData,  "mode %s ,text code: %s" % (mode,code) )
    284                  # show detailed info
    285                  if mode == MODE_BRAND:
    286                          self.ToggleWidget ()
    287                          self.Display_PI (code)
    288                  elif mode == MODE_GENERIC:
    289                          self.Display_Generic (code)
    290                  elif mode == MODE_INDICATION:
    291                          pass
    292                  return
    293
    294          #----------------------------------------------------------------------------------------------------------------------
    295 -        def GetDrugIssue(self):
    296                  # diplay some info on what database we are currently using
    297                  self.SetTitle(self.dbName)
    298  #               gmLog.gmDefLog.Log (gmLog.lData, "got the issue date")
    299                  return True
    300
    301
    302          #----------------------------------------------------------------------------------------------------------------------
    303 -        def OnBookmark(self,event):
    304                  pass
    305
    306          #-----------------------------------------------------------------------------------------------------------------------------
    307 -        def ToggleWidget(self):
    308                  """
    309                  Swaps listctrl to HTML viewer widget and vice versa.
    310                  """
    311                  if self.whichWidget == "listctrl_drugchoice":
    312                          if self.html_viewer is not None:
    313                                  return
    314                          if self.listctrl_drugchoice is not None:
    315                                  self.sizer_left.Remove(self.listctrl_drugchoice)
    316                                  self.listctrl_drugchoice = None
    317                          self.html_viewer = wx.HtmlWindow(self, -1, size=(400, 200))
    318                          self.sizer_left.Add( self.html_viewer, 1, wxGROW|wxALIGN_CENTER_HORIZONTAL, 5 )
    319                          self.sizer_left.Layout()
    320                          self.whichWidget="html_viewer"
    321                  else:
    322                          if self.listctrl_drugchoice is not None:
    323                                  return
    324                          if self.html_viewer is not None:
    325                                  self.sizer_left.Remove(self.html_viewer)
    326                                  self.html_viewer = None
    327                          self.listctrl_drugchoice = wx.ListCtrl(self, ID_LISTCTRL_DRUGCHOICE, wxDefaultPosition, wxSize(400,200), style=wx.LC_SINGLE_SEL | wx.LC_REPORT )
    328                          self.sizer_left.Add( self.listctrl_drugchoice, 1, wxGROW|wxALIGN_CENTER_HORIZONTAL, 5 )
    329                          self.sizer_left.Layout()
    330                          self.whichWidget="listctrl_drugchoice"
    331
    332          #-----------------------------------------------------------------------------------------------------------------------------
    333 -        def Drug_Find(self):
    334                  #--------------------------------------------------------
    335                  # using text in listctrl_drugchoice to find any similar drugs
    336                  #--------------------------------------------------------
    337                  self.mId = None
    338                  drugtofind = string.lower(self.comboProduct.GetValue())
    339                  # if we entered *, show all entries found in index (that might take time)
    340                  searchmode = 'exact'
    341                  if drugtofind == '***':
    342                          searchmode = 'complete'
    343
    344                  # tell the DrugView abstraction layer to do an index search
    345                  # on brand/generic/indication
    346                  # expect a dictionary containing at least name & ID
    347                  # qtype will be set by radiobuttons
    348                  # qtype and ID form (virtually) a unique ID that can be used to access other data in the db
    349
    350                  qtype = self.mode
    351                  result = self.mDrugView.SearchIndex(self.mode,drugtofind,searchmode)
    352
    353                  # no drug found for this name
    354                  if result is None or len(result['id']) < 1:
    355                          # tell everybody that we didn't find a match
    356                          self.mId = None
    357                          self.drugProductInfo = None
    358                          # display message
    359                          if self.whichWidget == 'listctrl_drugchoice':
    360                                  self.ToggleWidget ()
    361                          self.html_viewer.SetPage(self.NoDrugFoundMessageHTML)
    362                          return
    363
    364                  numOfRows = len(result['id'])
    365                  # found exactly one drug
    366                  if numOfRows == 1:
    367                          seld.mId = result['id']
    368                          # if we found a brand *product*, show the product info
    369                          if qtype == MODE_BRAND:
    370                                  if self.whichWidget == 'listctrl_drugchoice':
    371                                          self.ToggleWidget ()
    372                                          self.Display_PI (self.mId)
    373                                  elif self.mId <> self.mLastId: # don't change unless different drug
    374                                          self.Display_PI (self.mId)
    375                                          self.mLastId = self.mId
    376                          # if we found a generic substance name, show all brands
    377                          # containing this generic
    378                          elif qtype == MODE_GENERIC:
    379                                  self.Display_Generic (self.mId)
    380                          # if we are browsing indications, show all generics + brands
    381                          # that match. Display Indication
    382                          elif qtype == MODE_INDICATION:
    383                                  self.Display_Indication(self.mId)
    384
    385                  # we have more than one result
    386                  # -> display a list of all matching names
    387                  else:
    388                          if self.whichWidget == 'html_viewer':
    389                                  self.ToggleWidget ()
    390                          # show list
    391                          self.BuildListCtrl(result,qtype)
    392
    393          #---------------------------------------------------------------------------------------------------------------------------
    394 -        def Display_Generic (self, aId):
    395                  """
    396                  Find all brand products that contain a certain generic substance and
    397          display them
    398                  """
    399                  brandsList=self.mDrugView.getBrandsForGeneric(aId)
    400
    401                  if type(brandsList['name']) == type([]):
    402                          res_num=len (brandsList['name'])
    403                  else:
    404                          res_num = 1
    405
    406                  qtype = MODE_BRAND
    407                  # no brand - should be an error, but AMIS allows that :(
    408                  if brandsList is None or res_num == 0:
    409                          gmLog.gmDefLog.Log (gmLog.lWarn,  "No brand product available containing generic ID: %s" % str(aId) )
    410                          if self.whichWidget == 'listctrl_drugchoice':
    411                                  self.ToggleWidget ()
    412                          self.html_viewer.SetPage(self.NoDrugFoundMessageHTML)
    413                          return None
    414                  # one brand, so display product information
    415                  if res_num == 1:
    416                          if self.whichWidget == 'listctrl_drugchoice':
    417                                  self.ToggleWidget ()
    418                          self.Display_PI (brandsList['id'])
    419                  else:
    420                          # multiple brands, display list
    421                          if self.whichWidget == 'html_viewer':
    422                                  self.ToggleWidget ()
    423                          # show list
    424                          self.BuildListCtrl(brandsList,qtype)
    425
    426                          return True
    427
    428          #-----------------------------------------------------------------
    429 -        def BuildListCtrl(self, aDataDict=None, dtype=None):
    430                  """
    431                  Sets all the ListCtrl widget to display the items found in
    432                  a database search.
    433                  The DataDict must at least have the keys 'id' and 'name', all
    434                  additional columns will be displayed in alphabetical order.
    435                  Column names will be derived from key names.
    436                  """
    437                  # clear old data
    438                  self.listctrl_drugchoice.ClearAll ()
    439                  self.__mListCtrlItems = {}
    440
    441                  if aDataDict is None or not (aDataDict.has_key('id') & aDataDict.has_key('name')):
    442                          _log.Log(gmLog.lWarn, "No data to build list control.")
    443                          return None
    444                  #print "1:", aDataDict['id']
    445                  # get column names from aDataDict key names
    446                  # remove 'id' and display name at leftmost position
    447                  columns = aDataDict.keys()
    448                  columns.remove('id')
    449                  columns.remove('name')
    450                  columns.insert(0,'name')
    451
    452                  # number of rows (products, drugs, substances etc.) found
    453                  numOfRows = len(aDataDict['id'])
    454
    455                  # set column names
    456                  # add columns for each parameter fetched
    457                  col_no = 0
    458                  for col in columns:
    459                          self.listctrl_drugchoice.InsertColumn(col_no, col)
    460                          col_no += 1
    461                  # hide ListCtrl for performance reasons
    462                  self.listctrl_drugchoice.Hide()
    463                  # loop through all products (rows)
    464                  for row in range(0,numOfRows):
    465                          col_no = 0
    466                  # for each product, display all parameters available
    467                  # code taken from gmSQLListCtrl.py
    468                          for col in columns:
    469                                  # item text
    470                                  item_text = str(aDataDict[col][row])
    471
    472                                  # if first column, insert new column and
    473                                  # and store pointer to item data (type,id)
    474                                  if col_no == 0:
    475                                          item=self.listctrl_drugchoice.InsertStringItem (row,item_text)
    476                                          self.listctrl_drugchoice.SetItemData(item,item)
    477                                          id = aDataDict['id'][row]
    478                                  # set data as type and database ID
    479                                          self.__mListCtrlItems[item]=(dtype,id)
    480                                  else:
    481                                          self.listctrl_drugchoice.SetStringItem(row,col_no,item_text)
    482                                  col_no += 1
    483                  # finally set column widths to AUTOSIZE
    484                  for i in range(0,len(columns)):
    485                          self.listctrl_drugchoice.SetColumnWidth(i, wx.LIST_AUTOSIZE)
    486                  # set focus to first item
    487                  firstItemState=self.listctrl_drugchoice.GetItemState(0,wx.LIST_STATE_FOCUSED | wx.LIST_STATE_SELECTED)
    488                  self.listctrl_drugchoice.SetItemState(0,wx.LIST_STATE_FOCUSED | wx.LIST_STATE_SELECTED, wx.LIST_STATE_FOCUSED | wx.LIST_STATE_SELECTED)
    489                  # show the listctrl
    490                  self.listctrl_drugchoice.Show()
    491                  # save data for further use
    492                  self.LastDataDict = aDataDict
    493                  return
    494
    495          #-----------------------------------------------------------------------------------------------------------------------------
    496 -        def Display_PI(self, aId=None):
    497                  """
    498                  Shows product information on a drug specified by aID.
    499                  """
    500                  # this is to stop recursion!
    501                  self.inDisplay_PI = 1
    502                  # if no aId has been specified, return
    503                  if aId == None:
    504                          return None
    505                  # remember Id for further use (display refresh etc.)
    506                  self.mId = aId
    507                  # getProductInfo returns a HTML-formatted page
    508                  (self.drugProductInfo,self.drugPIHeaders)=self.mDrugView.getProductInfo(aId)
    509  #               self.comboProduct.SetValue(result[0]['product'])
    510                  self.inDisplay_PI = 0
    511                  # show info page
    512                  self.html_viewer.SetPage(self.drugProductInfo)
    513                  # set jumpbox items
    514                  self.listbox_jumpto.Clear()
    515                  self.listbox_jumpto.InsertItems(self.drugPIHeaders,0)
    516                  return True
    517
    518  #--------------------------------------------------------------------------------------------------------------------------------------------------
    519 -        def TransferDataToWindow(self):
    520                  gmLog.gmDefLog.Log (gmLog.lData,  "Transfer data to Window")
    521                  return True
    522
    523 -        def TransferDataFromWindow(self):
    524                  return True
    525
    526          # handler implementations for DrugDisplay
    527
    528 -        def OnPrint (self, event):
    529                  """
    530                  If product info is available, print it.
    531                  """
    532                  if not self.drugProductInfo is None:
    533                          self.printer.PrintText(self.drugProductInfo)
    534                  return True
    535
    536 -        def OnDisplay(self, event):
    537                  """
    538                  Redisplay product info.
    539                  """
    540                  if not self.mId is None:
    541                          self.Display_PI(self.mId)
    542                  pass
    543
    544 -        def OnPrescribe(self, event):
    545                  pass
    546
    547 -        def OnJumpToDblClick(self, event):
    548                  pass
    549
    550 -        def OnJumpToSelected(self, event):
    551                  """
    552                  Jump to product info section selected by double-clicking a line in jumpbox.
    553                  """
    554                  tagname = self.listbox_jumpto.GetString(self.listbox_jumpto.GetSelection())
    555                  self.html_viewer.LoadPage('#' + tagname)
    556
    557          #--------------- handler for query mode radiobuttons --------------------
    558 -        def OnSearchByIndication(self, event):
    559                  self.mode = MODE_INDICATION
    560                  self.ClearInfo()
    561
    562 -        def OnSearchByGeneric(self, event):
    563                  self.mode = MODE_GENERIC
    564                  self.ClearInfo()
    565
    566 -        def OnSearchByBrand(self, event):
    567                  self.mode = MODE_BRAND
    568                  self.ClearInfo()
    569
    570 -        def OnSearchByAny(self, event):
    571                  self.mode = MODE_ANY
    572                  self.ClearInfo()
    573
    574          # Rewrote this
    575 -        def OnProductKeyPressed(self, event):
    576                  # first, do not recur when setting the box ourselves!
    577                  if not self.inDisplay_PI:
    578                          entry_string = self.comboProduct.GetValue()
    579                          # wait until at least 3 letters has been entered
    580                  # to reduce result set
    581                          if len(entry_string) > 2:
    582                                  self.Drug_Find()
    583
    584
    585 -        def OnProductSelected(self, event):
    586                  #----------------------------------------------
    587                  # get product information for drug in the combo
    588                  #----------------------------------------------
    589                  #self.comboProduct.SetValue(self.comboProduct.GetString(1))
    590                  #self.Drug_Find()
    591                  pass
    592
    593 -        def OnOk(self, event):
    594                  event.Skip(True)
    595
    596 -        def OnCancel(self, event):
    597                  event.Skip(True)
    598
    599 -        def ClearInfo(self):
    600                  """clears the search result list and jumpbox when query mode changed."""
    601                  if self.mode == self.previousMode:
    602                          return
    603                  self.previousMode = self.mode
    604                  if self.listctrl_drugchoice is not None:
    605                          self.listctrl_drugchoice.ClearAll()
    606                  else:
    607                          self.ToggleWidget()
    608                  self.listbox_jumpto.Clear()
    609                  self.comboProduct.SetValue("")
    610                  # display welcome message
    611                  self.whichWidget = "listctrl_drugchoice"
    612                  self.ToggleWidget()
    613                  self.html_viewer.SetPage(self.WelcomeMessageHTML)
    614
    615  #==================================================
    616  # Shall we just test this module?
    617  if __name__ == "__main__":
    618          _ = lambda x:x
    619          app = wxPyWidgetTester(size = (640, 400))
    620          app.SetWidget(DrugDisplay, -1)
    621          app.MainLoop()
    622  else:
    623          #=================================================
    624          # make this into GNUMed plugin
    625
    626          from Gnumed.pycommon import gmI18N
    627          from Gnumed.wxpython import gmPlugin
    628
    629 -        class gmDrugDisplay (gmPlugin.cNotebookPlugin):
    630
    631 -                def name (self):
    632                          return _("DrugBrowser")
    633
    634 -                def MenuInfo (self):
    635                          return ("view", _("&DrugBrowser"))
    636
    637 -                def GetWidget (self, parent):
    638                          return DrugDisplay (parent, -1)
    639
    640  #==================================================
    641