1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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
39
40
41 _log.SetAllLogLevels(gmLog.lData)
42 _ = lambda x:x
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 gmPraxis
49
50 _cfg = gmCfg.gmDefCfgFile
51
52
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
77
78
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
91
92
93
94
95 currworkplace = gmPraxis.gmCurrentPraxisBranch().active_workplace
96 if currworkplace is None:
97
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
113
114 raise gmExceptions.ConstructorError, "No drug database specified"
115
116
117
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
124
125 self.mode = MODE_BRAND
126 self.previousMode = MODE_BRAND
127 self.printer = wx.HtmlEasyPrinting()
128 self.mId = None
129 self.drugProductInfo = None
130 self.__mListCtrlItems = {}
131
132
133
134
135
136
137 self.GuiElements_Init()
138 self.inDisplay_PI = 0
139 self.GetDrugIssue()
140
141
142
143
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
163
164
165
166
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
191
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
199
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
213
214
215
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
231
232
233
234
235
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
243
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
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
260
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
273
274
293
294
296
297 self.SetTitle(self.dbName)
298
299 return True
300
301
302
305
306
331
332
334
335
336
337 self.mId = None
338 drugtofind = string.lower(self.comboProduct.GetValue())
339
340 searchmode = 'exact'
341 if drugtofind == '***':
342 searchmode = 'complete'
343
344
345
346
347
348
349
350 qtype = self.mode
351 result = self.mDrugView.SearchIndex(self.mode,drugtofind,searchmode)
352
353
354 if result is None or len(result['id']) < 1:
355
356 self.mId = None
357 self.drugProductInfo = None
358
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
366 if numOfRows == 1:
367 seld.mId = result['id']
368
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:
374 self.Display_PI (self.mId)
375 self.mLastId = self.mId
376
377
378 elif qtype == MODE_GENERIC:
379 self.Display_Generic (self.mId)
380
381
382 elif qtype == MODE_INDICATION:
383 self.Display_Indication(self.mId)
384
385
386
387 else:
388 if self.whichWidget == 'html_viewer':
389 self.ToggleWidget ()
390
391 self.BuildListCtrl(result,qtype)
392
393
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
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
415 if res_num == 1:
416 if self.whichWidget == 'listctrl_drugchoice':
417 self.ToggleWidget ()
418 self.Display_PI (brandsList['id'])
419 else:
420
421 if self.whichWidget == 'html_viewer':
422 self.ToggleWidget ()
423
424 self.BuildListCtrl(brandsList,qtype)
425
426 return True
427
428
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
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
445
446
447 columns = aDataDict.keys()
448 columns.remove('id')
449 columns.remove('name')
450 columns.insert(0,'name')
451
452
453 numOfRows = len(aDataDict['id'])
454
455
456
457 col_no = 0
458 for col in columns:
459 self.listctrl_drugchoice.InsertColumn(col_no, col)
460 col_no += 1
461
462 self.listctrl_drugchoice.Hide()
463
464 for row in range(0,numOfRows):
465 col_no = 0
466
467
468 for col in columns:
469
470 item_text = str(aDataDict[col][row])
471
472
473
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
479 self.__mListCtrlItems[item]=(dtype,id)
480 else:
481 self.listctrl_drugchoice.SetStringItem(row,col_no,item_text)
482 col_no += 1
483
484 for i in range(0,len(columns)):
485 self.listctrl_drugchoice.SetColumnWidth(i, wx.LIST_AUTOSIZE)
486
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
490 self.listctrl_drugchoice.Show()
491
492 self.LastDataDict = aDataDict
493 return
494
495
497 """
498 Shows product information on a drug specified by aID.
499 """
500
501 self.inDisplay_PI = 1
502
503 if aId == None:
504 return None
505
506 self.mId = aId
507
508 (self.drugProductInfo,self.drugPIHeaders)=self.mDrugView.getProductInfo(aId)
509
510 self.inDisplay_PI = 0
511
512 self.html_viewer.SetPage(self.drugProductInfo)
513
514 self.listbox_jumpto.Clear()
515 self.listbox_jumpto.InsertItems(self.drugPIHeaders,0)
516 return True
517
518
520 gmLog.gmDefLog.Log (gmLog.lData, "Transfer data to Window")
521 return True
522
525
526
527
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
537 """
538 Redisplay product info.
539 """
540 if not self.mId is None:
541 self.Display_PI(self.mId)
542 pass
543
545 pass
546
549
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
561
565
569
573
574
576
577 if not self.inDisplay_PI:
578 entry_string = self.comboProduct.GetValue()
579
580
581 if len(entry_string) > 2:
582 self.Drug_Find()
583
584
586
587
588
589
590
591 pass
592
593 - def OnOk(self, event):
595
598
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
611 self.whichWidget = "listctrl_drugchoice"
612 self.ToggleWidget()
613 self.html_viewer.SetPage(self.WelcomeMessageHTML)
614
615
616
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
625
626 from Gnumed.pycommon import gmI18N
627 from Gnumed.wxpython import gmPlugin
628
630
632 return _("DrugBrowser")
633
635 return ("view", _("&DrugBrowser"))
636
639
640
641