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
28 __version__ = "$Revision: 1.34 $"
29 __author__ = "H.Herb, R.Terry, H.Berger"
30
31 import string
32
33
34 import wx
35
36
37 _log = logging.getLogger('gm.ui')
38 if __name__ == "__main__":
39
40
41
42 _log.SetAllLogLevels(gmLog.lData)
43 _ = lambda x:x
44 from Gnumed.pycommon import gmI18N
45
46
47 from Gnumed.pycommon import gmDrugView, gmCfg, gmExceptions
48 from Gnumed.wxpython import gmGuiHelpers
49 from Gnumed.business import gmPraxis
50
51 _cfg = gmCfg.gmDefCfgFile
52
53
54
55 ID_ABOUT = wx.NewId()
56 ID_CONTENTS = wx.NewId()
57 ID_EXIT = wx.NewId()
58 ID_OPEN= wx.NewId()
59 ID_HELP = wx.NewId()
60 ID_TEXTCTRL = wx.NewId()
61 ID_TEXT = wx.NewId()
62 ID_COMBO_PRODUCT = wx.NewId()
63 ID_RADIOBUTTON_BYANY = wx.NewId()
64 ID_RADIOBUTTON_BYPRODUCT = wx.NewId()
65 ID_RADIOBUTTON_BYGENERIC = wx.NewId()
66 ID_RADIOBUTTON_BYINDICATION = wx.NewId()
67 ID_LISTBOX_JUMPTO = wx.NewId()
68 ID_LISTCTRL_DRUGCHOICE = wx.NewId()
69 ID_BUTTON_PRESCRIBE = wx.NewId()
70 ID_BUTTON_DISPLAY = wx.NewId()
71 ID_BUTTON_PRINT = wx.NewId()
72 ID_BUTTON_BOOKMARK = wx.NewId()
73
74 MODE_PRODUCT = 0
75 MODE_GENERIC = 1
76 MODE_INDICATION = 2
77 MODE_ANY = 3
78
79
81 """displays drug information in a convenience widget"""
82
83 NoDrugFoundMessageHTML = "<HTML><HEAD></HEAD><BODY BGCOLOR='#FFFFFF8'> <FONT SIZE=3>" + _("No matching drug found.") + "</FONT></BODY></HTML>"
84 WelcomeMessageHTML = "<HTML><HEAD></HEAD><BODY BGCOLOR='#FFFFFF8'> <FONT SIZE=3>" + _("Please enter at least three digits of the drug name.") + "</FONT></BODY></HTML>"
85
86 - def __init__(self, parent, id, pos = wxDefaultPosition,
87 size = wxDefaultSize, style = wx.TAB_TRAVERSAL):
88
89 wx.Panel.__init__(self, parent, id, pos, size, style)
90
91
92
93
94
95
96 currworkplace = gmPraxis.gmCurrentPraxisBranch().active_workplace
97 if currworkplace is None:
98
99 self.dbName = _cfg.get('DrugReferenceBrowser', 'drugDBname')
100 else:
101 self.dbName, match = gmCfg.getDBParam(
102 currworkplace,
103 option="DrugReferenceBrowser.drugDBName"
104 )
105
106 if self.dbName is None:
107 if __name__ == '__main__':
108 title = _('Starting drug data browser')
109 msg = _('Cannot start the drug data browser.\n\n'
110 'There is no drug database specified in the configuration.')
111 gmGuiHelpers.gm_show_error(msg, title)
112 _log.Log(gmLog.lErr, "No drug database specified. Aborting drug browser.")
113
114
115 raise gmExceptions.ConstructorError, "No drug database specified"
116
117
118
119 try:
120 self.mDrugView=gmDrugView.DrugView(self.dbName)
121 except:
122 _log.LogException("Unhandled exception during DrugView API init.", sys.exc_info(), verbose = 0)
123 raise gmExceptions.ConstructorError, "Couldn't initialize DrugView API"
124
125
126 self.mode = MODE_PRODUCT
127 self.previousMode = MODE_PRODUCT
128 self.printer = wx.HtmlEasyPrinting()
129 self.mId = None
130 self.drugProductInfo = None
131 self.__mListCtrlItems = {}
132
133
134
135
136
137
138 self.GuiElements_Init()
139 self.inDisplay_PI = 0
140 self.GetDrugIssue()
141
142
143
144
145
146 wx.EVT_BUTTON(self, ID_BUTTON_PRINT, self.OnPrint)
147 wx.EVT_BUTTON(self, ID_BUTTON_DISPLAY, self.OnDisplay)
148 wx.EVT_BUTTON(self, ID_BUTTON_PRESCRIBE, self.OnPrescribe)
149 wx.EVT_LISTBOX_DCLICK(self, ID_LISTBOX_JUMPTO, self.OnJumpToDblClick)
150 wx.EVT_LISTBOX(self, ID_LISTBOX_JUMPTO, self.OnJumpToSelected)
151 wx.EVT_LIST_ITEM_ACTIVATED(self, ID_LISTCTRL_DRUGCHOICE, self.OnDrugChoiceDblClick)
152 wx.EVT_RADIOBUTTON(self, ID_RADIOBUTTON_BYINDICATION, self.OnSearchByIndication)
153 wx.EVT_RADIOBUTTON(self, ID_RADIOBUTTON_BYGENERIC, self.OnSearchByGeneric)
154 wx.EVT_RADIOBUTTON(self, ID_RADIOBUTTON_BYPRODUCT, self.OnSearchByProduct)
155 wx.EVT_RADIOBUTTON(self, ID_RADIOBUTTON_BYANY, self.OnSearchByAny)
156 wx.EVT_TEXT(self, ID_COMBO_PRODUCT, self.OnProductKeyPressed)
157 wx.EVT_COMBOBOX(self, ID_COMBO_PRODUCT, self.OnProductSelected)
158 wx.EVT_BUTTON(self, wxID_OK, self.OnOk)
159 wx.EVT_BUTTON(self, wxID_CANCEL, self.OnCancel)
160 wx.EVT_BUTTON(self,ID_BUTTON_BOOKMARK, self.OnBookmark)
161
162
164
165
166
167
168
169 finddrug = wxStaticText( self, -1, _(" Find "), wxDefaultPosition, wxDefaultSize, 0 )
170 finddrug.SetFont( wxFont( 14, wxSWISS, wx.NORMAL, wx.NORMAL ) )
171
172 self.comboProduct = wxComboBox(
173 self,
174 ID_COMBO_PRODUCT,
175 "",
176 wxDefaultPosition,
177 wxSize(130,-1),
178 [] ,
179 wxCB_DROPDOWN
180 )
181 self.comboProduct.SetToolTip( wx.ToolTip(_("Enter the name of the drug you are interested in")) )
182 self.btnBookmark = wx.Button(
183 self,
184 ID_BUTTON_BOOKMARK,
185 _("&Bookmark"),
186 wxDefaultPosition,
187 wxDefaultSize,
188 0
189 )
190
191
192
193
194 self.sizertopleft = wx.BoxSizer(wx.HORIZONTAL)
195 self.sizertopleft.Add( finddrug, 0, wxALIGN_CENTER_VERTICAL, 5 )
196 self.sizertopleft.Add( self.comboProduct, 1, wxGROW|wxALIGN_CENTER_VERTICAL, 5 )
197 self.sizertopleft.Add( self.btnBookmark, 0, wxALIGN_CENTER_VERTICAL, 5 )
198
199
200
201
202 self.sizer_left = wx.BoxSizer( wx.VERTICAL )
203 self.sizer_left.AddSpacer( 30, 10, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 1 )
204 self.sizer_left.AddSizer( self.sizertopleft, 0, wxGROW|wxALIGN_CENTER_VERTICAL, 5)
205 self.sizer_left.AddSpacer( 1, 1, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 1 )
206 self.listctrl_drugchoice=None
207 self.html_viewer=None
208 self.whichWidget = "listctrl_drugchoice"
209 self.ToggleWidget()
210 self.html_viewer.SetPage(self.WelcomeMessageHTML)
211
212
213
214
215
216
217
218 sboxSearchBy = wxStaticBox( self, -1, _("Search by") )
219 self.sizerSearchBy = wxStaticBoxSizer( sboxSearchBy, wx.VERTICAL )
220 sboxSearchBy.SetFont( wxFont( 10, wxSWISS, wx.NORMAL, wx.NORMAL ) )
221
222 self.rbtnSearchAny = wxRadioButton( self, ID_RADIOBUTTON_BYANY, _("Any"), wxDefaultPosition, wxDefaultSize, 0 )
223 self.sizerSearchBy.Add( self.rbtnSearchAny, 0, wxGROW|wxALIGN_CENTER_VERTICAL, 1 )
224 self.rbtnSearchProduct = wxRadioButton( self, ID_RADIOBUTTON_BYPRODUCT, _("Product name"), wxDefaultPosition, wxDefaultSize, 0 )
225 self.sizerSearchBy.Add( self.rbtnSearchProduct, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wx.TOP, 1 )
226 self.rbtnSearchGeneric = wxRadioButton( self, ID_RADIOBUTTON_BYGENERIC, _("Generic name"), wxDefaultPosition, wxDefaultSize, 0 )
227 self.sizerSearchBy.Add( self.rbtnSearchGeneric, 0, wxGROW|wxALIGN_CENTER_VERTICAL, 1 )
228 self.rbtnSearchIndication = wxRadioButton( self, ID_RADIOBUTTON_BYINDICATION, _("Indication"), wxDefaultPosition, wxDefaultSize, 0 )
229 self.sizerSearchBy.Add( self.rbtnSearchIndication, 0, wxGROW|wxALIGN_CENTER_VERTICAL, 1 )
230
231
232
233
234
235
236
237
238 self.sizerVInteractionSidebar = wx.BoxSizer( wx.VERTICAL )
239 self.sizerVInteractionSidebar.AddSpacer( 30, 10, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 12 )
240 self.sizerVInteractionSidebar.AddSizer( self.sizerSearchBy, 0, wxGROW|wxALIGN_CENTER_VERTICAL, 5 )
241 self.sizerVInteractionSidebar.AddSpacer( 30, 10, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 1 )
242
243
244
245
246 self.listbox_jumpto = wx.ListBox( self, ID_LISTBOX_JUMPTO, wxDefaultPosition, wxSize(150,100),
247 [] , wx.LB_SINGLE )
248 self.sizerVInteractionSidebar.Add( self.listbox_jumpto, 1, wxGROW|wxALIGN_CENTER_VERTICAL, 10 )
249
250
251
252 self.sizerVInteractionSidebar.AddSpacer( 20, 10, 0, wxALIGN_CENTRE|wxALL, 1 )
253 self.btnPrescribe = wx.Button( self, ID_BUTTON_PRESCRIBE, _("&Prescribe"), wxDefaultPosition, wxDefaultSize, 0 )
254 self.sizerVInteractionSidebar.Add( self.btnPrescribe, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 1 )
255 self.btnDisplay = wx.Button( self, ID_BUTTON_DISPLAY, _("&Display"), wxDefaultPosition, wxDefaultSize, 0 )
256 self.sizerVInteractionSidebar.Add( self.btnDisplay, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 1 )
257 self.btnPrint = wx.Button( self, ID_BUTTON_PRINT, _("&Print"), wxDefaultPosition, wxDefaultSize, 0 )
258 self.sizerVInteractionSidebar.Add( self.btnPrint, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 1 )
259
260
261
262
263 self.sizermain = wx.BoxSizer(wx.HORIZONTAL)
264 self.sizermain.AddSizer(self.sizer_left, 1, wxGROW|wxALIGN_CENTER_HORIZONTAL|wxALL, 7)
265 self.sizermain.AddSizer(self.sizerVInteractionSidebar, 0, wxGROW|wxALIGN_LEFT|wxALL, 8)
266 self.SetAutoLayout( True )
267 self.SetSizer( self.sizermain )
268 self.sizermain.Fit( self )
269 self.sizermain.SetSizeHints( self )
270
271
272
273
274
275
294
295
297
298 self.SetTitle(self.dbName)
299
300 return True
301
302
303
306
307
332
333
335
336
337
338 self.mId = None
339 drugtofind = string.lower(self.comboProduct.GetValue())
340
341 searchmode = 'exact'
342 if drugtofind == '***':
343 searchmode = 'complete'
344
345
346
347
348
349
350
351 qtype = self.mode
352 result = self.mDrugView.SearchIndex(self.mode,drugtofind,searchmode)
353
354
355 if result is None or len(result['id']) < 1:
356
357 self.mId = None
358 self.drugProductInfo = None
359
360 if self.whichWidget == 'listctrl_drugchoice':
361 self.ToggleWidget ()
362 self.html_viewer.SetPage(self.NoDrugFoundMessageHTML)
363 return
364
365 numOfRows = len(result['id'])
366
367 if numOfRows == 1:
368 seld.mId = result['id']
369
370 if qtype == MODE_PRODUCT:
371 if self.whichWidget == 'listctrl_drugchoice':
372 self.ToggleWidget ()
373 self.Display_PI (self.mId)
374 elif self.mId != self.mLastId:
375 self.Display_PI (self.mId)
376 self.mLastId = self.mId
377
378
379 elif qtype == MODE_GENERIC:
380 self.Display_Generic (self.mId)
381
382
383 elif qtype == MODE_INDICATION:
384 self.Display_Indication(self.mId)
385
386
387
388 else:
389 if self.whichWidget == 'html_viewer':
390 self.ToggleWidget ()
391
392 self.BuildListCtrl(result,qtype)
393
394
396 """
397 Find all drug products that contain a certain generic substance and
398 display them
399 """
400 productsList=self.mDrugView.getProductsForGeneric(aId)
401
402 if type(productsList['name']) == type([]):
403 res_num=len (productsList['name'])
404 else:
405 res_num = 1
406
407 qtype = MODE_PRODUCT
408
409 if productsList is None or res_num == 0:
410 gmLog.gmDefLog.Log (gmLog.lWarn, "No drug product available containing generic ID: %s" % str(aId) )
411 if self.whichWidget == 'listctrl_drugchoice':
412 self.ToggleWidget ()
413 self.html_viewer.SetPage(self.NoDrugFoundMessageHTML)
414 return None
415
416 if res_num == 1:
417 if self.whichWidget == 'listctrl_drugchoice':
418 self.ToggleWidget ()
419 self.Display_PI (productsList['id'])
420 else:
421
422 if self.whichWidget == 'html_viewer':
423 self.ToggleWidget ()
424
425 self.BuildListCtrl(productsList,qtype)
426
427 return True
428
429
431 """
432 Sets all the ListCtrl widget to display the items found in
433 a database search.
434 The DataDict must at least have the keys 'id' and 'name', all
435 additional columns will be displayed in alphabetical order.
436 Column names will be derived from key names.
437 """
438
439 self.listctrl_drugchoice.ClearAll ()
440 self.__mListCtrlItems = {}
441
442 if aDataDict is None or not ('id' in aDataDict & 'name' in aDataDict):
443 _log.Log(gmLog.lWarn, "No data to build list control.")
444 return None
445
446
447
448 columns = aDataDict.keys()
449 columns.remove('id')
450 columns.remove('name')
451 columns.insert(0,'name')
452
453
454 numOfRows = len(aDataDict['id'])
455
456
457
458 col_no = 0
459 for col in columns:
460 self.listctrl_drugchoice.InsertColumn(col_no, col)
461 col_no += 1
462
463 self.listctrl_drugchoice.Hide()
464
465 for row in range(0,numOfRows):
466 col_no = 0
467
468
469 for col in columns:
470
471 item_text = str(aDataDict[col][row])
472
473
474
475 if col_no == 0:
476 item=self.listctrl_drugchoice.InsertItem (row,item_text)
477 self.listctrl_drugchoice.SetItemData(item,item)
478 id = aDataDict['id'][row]
479
480 self.__mListCtrlItems[item]=(dtype,id)
481 else:
482 self.listctrl_drugchoice.SetItem(row,col_no,item_text)
483 col_no += 1
484
485 for i in range(0,len(columns)):
486 self.listctrl_drugchoice.SetColumnWidth(i, wx.LIST_AUTOSIZE)
487
488 firstItemState=self.listctrl_drugchoice.GetItemState(0,wx.LIST_STATE_FOCUSED | wx.LIST_STATE_SELECTED)
489 self.listctrl_drugchoice.SetItemState(0,wx.LIST_STATE_FOCUSED | wx.LIST_STATE_SELECTED, wx.LIST_STATE_FOCUSED | wx.LIST_STATE_SELECTED)
490
491 self.listctrl_drugchoice.Show()
492
493 self.LastDataDict = aDataDict
494 return
495
496
498 """
499 Shows product information on a drug specified by aID.
500 """
501
502 self.inDisplay_PI = 1
503
504 if aId == None:
505 return None
506
507 self.mId = aId
508
509 (self.drugProductInfo,self.drugPIHeaders)=self.mDrugView.getProductInfo(aId)
510
511 self.inDisplay_PI = 0
512
513 self.html_viewer.SetPage(self.drugProductInfo)
514
515 self.listbox_jumpto.Clear()
516 self.listbox_jumpto.InsertItems(self.drugPIHeaders,0)
517 return True
518
519
521 gmLog.gmDefLog.Log (gmLog.lData, "Transfer data to Window")
522 return True
523
526
527
528
530 """
531 If product info is available, print it.
532 """
533 if not self.drugProductInfo is None:
534 self.printer.PrintText(self.drugProductInfo)
535 return True
536
538 """
539 Redisplay product info.
540 """
541 if not self.mId is None:
542 self.Display_PI(self.mId)
543 pass
544
546 pass
547
550
552 """
553 Jump to product info section selected by double-clicking a line in jumpbox.
554 """
555 tagname = self.listbox_jumpto.GetString(self.listbox_jumpto.GetSelection())
556 self.html_viewer.LoadPage('#' + tagname)
557
558
562
566
570
574
575
577
578 if not self.inDisplay_PI:
579 entry_string = self.comboProduct.GetValue()
580
581
582 if len(entry_string) > 2:
583 self.Drug_Find()
584
585
587
588
589
590
591
592 pass
593
594 - def OnOk(self, event):
596
599
601 """clears the search result list and jumpbox when query mode changed."""
602 if self.mode == self.previousMode:
603 return
604 self.previousMode = self.mode
605 if self.listctrl_drugchoice is not None:
606 self.listctrl_drugchoice.ClearAll()
607 else:
608 self.ToggleWidget()
609 self.listbox_jumpto.Clear()
610 self.comboProduct.SetValue("")
611
612 self.whichWidget = "listctrl_drugchoice"
613 self.ToggleWidget()
614 self.html_viewer.SetPage(self.WelcomeMessageHTML)
615
616
617
618 if __name__ == "__main__":
619 _ = lambda x:x
620 app = wxPyWidgetTester(size = (640, 400))
621 app.SetWidget(DrugDisplay, -1)
622 app.MainLoop()
623 else:
624
625
626
627 from Gnumed.pycommon import gmI18N
628 from Gnumed.wxpython import gmPlugin
629
631
633 return _("DrugBrowser")
634
636 return ("view", _("&DrugBrowser"))
637
640
641
642