1 """GNUmed medication/substances handling widgets.
2 """
3
4
5
6 __version__ = "$Revision: 1.33 $"
7 __author__ = "Karsten Hilbert <Karsten.Hilbert@gmx.net>"
8
9 import logging, sys, os.path
10
11
12 import wx, wx.grid
13
14
15 if __name__ == '__main__':
16 sys.path.insert(0, '../../')
17 from Gnumed.pycommon import gmDispatcher, gmCfg, gmShellAPI, gmTools, gmDateTime
18 from Gnumed.pycommon import gmMatchProvider, gmI18N, gmPrinting, gmCfg2
19 from Gnumed.business import gmPerson, gmATC, gmSurgery, gmMedication, gmForms
20 from Gnumed.wxpython import gmGuiHelpers, gmRegetMixin, gmAuthWidgets, gmEditArea, gmMacro
21 from Gnumed.wxpython import gmCfgWidgets, gmListWidgets, gmPhraseWheel, gmFormWidgets
22
23
24 _log = logging.getLogger('gm.ui')
25 _log.info(__version__)
26
28
29 if parent is None:
30 parent = wx.GetApp().GetTopWindow()
31
32 def refresh(lctrl):
33 atcs = gmATC.get_reference_atcs()
34
35 items = [ [
36 a['atc'],
37 a['term'],
38 u'%s' % gmTools.coalesce(a['ddd'], u''),
39 gmTools.coalesce(a['unit'], u''),
40 gmTools.coalesce(a['administrative_route'], u''),
41 gmTools.coalesce(a['comment'], u''),
42 a['version'],
43 a['lang']
44 ] for a in atcs ]
45 lctrl.set_string_items(items)
46 lctrl.set_data(atcs)
47
48 gmListWidgets.get_choices_from_list (
49 parent = parent,
50 msg = _('\nThe ATC codes as known to GNUmed.\n'),
51 caption = _('Showing ATC codes.'),
52 columns = [ u'ATC', _('Term'), u'DDD', _('Unit'), _(u'Route'), _('Comment'), _('Version'), _('Language') ],
53 single_selection = True,
54 refresh_callback = refresh
55 )
56
57
59
60 if parent is None:
61 parent = wx.GetApp().GetTopWindow()
62
63
64 def delete(component):
65 gmMedication.delete_component_from_branded_drug (
66 brand = component['pk_brand'],
67 component = component['pk_substance_in_brand']
68 )
69 return True
70
71 def refresh(lctrl):
72 substs = gmMedication.get_substances_in_brands()
73 items = [ [
74 u'%s%s' % (s['brand'], gmTools.coalesce(s['atc_brand'], u'', u' (%s)')),
75 s['substance'],
76 gmTools.coalesce(s['atc_substance'], u''),
77 s['preparation'],
78 gmTools.coalesce(s['external_code_brand'], u''),
79 s['pk_substance_in_brand']
80 ] for s in substs ]
81 lctrl.set_string_items(items)
82 lctrl.set_data(substs)
83
84 msg = _('\nThese are the substances in the drug brands known to GNUmed.\n')
85
86 gmListWidgets.get_choices_from_list (
87 parent = parent,
88 msg = msg,
89 caption = _('Showing drug brand components (substances).'),
90 columns = [_('Brand'), _('Substance'), u'ATC', _('Preparation'), _('Code'), u'#'],
91 single_selection = True,
92
93
94 delete_callback = delete,
95 refresh_callback = refresh
96 )
97
99
100 if parent is None:
101 parent = wx.GetApp().GetTopWindow()
102
103 def delete(brand):
104 gmMedication.delete_branded_drug(brand = brand['pk'])
105 return True
106
107 def new():
108 drug_db = get_drug_database(parent = parent)
109
110 if drug_db is None:
111 return False
112
113 drug_db.import_drugs()
114
115 return True
116
117 def refresh(lctrl):
118 drugs = gmMedication.get_branded_drugs()
119 items = [ [
120 d['description'],
121 d['preparation'],
122 gmTools.coalesce(d['atc_code'], u''),
123 gmTools.coalesce(d['external_code'], u''),
124 d['pk']
125 ] for d in drugs ]
126 lctrl.set_string_items(items)
127 lctrl.set_data(drugs)
128
129 msg = _('\nThese are the drug brands known to GNUmed.\n')
130
131 gmListWidgets.get_choices_from_list (
132 parent = parent,
133 msg = msg,
134 caption = _('Showing branded drugs.'),
135 columns = [_('Name'), _('Preparation'), _('ATC'), _('Code'), u'#'],
136 single_selection = True,
137 refresh_callback = refresh,
138 new_callback = new,
139
140 delete_callback = delete
141 )
142
144
145 if parent is None:
146 parent = wx.GetApp().GetTopWindow()
147
148 def delete(substance):
149 gmMedication.delete_used_substance(substance = substance['pk'])
150 return True
151
152 def new():
153 drug_db = get_drug_database(parent = parent)
154
155 if drug_db is None:
156 return False
157
158 drug_db.import_drugs()
159
160 return True
161
162 def refresh(lctrl):
163 substs = gmMedication.get_substances_in_use()
164 items = [ [
165 s['description'],
166 gmTools.coalesce(s['atc_code'], u''),
167 s['pk']
168 ] for s in substs ]
169 lctrl.set_string_items(items)
170 lctrl.set_data(substs)
171
172 msg = _('\nThese are the substances currently or previously\nconsumed across all patients.\n')
173
174 gmListWidgets.get_choices_from_list (
175 parent = parent,
176 msg = msg,
177 caption = _('Showing consumed substances.'),
178 columns = [_('Name'), _('ATC'), u'#'],
179 single_selection = True,
180 refresh_callback = refresh,
181 new_callback = new,
182
183 delete_callback = delete
184 )
185
186
187
205
235
242
244
245 dbcfg = gmCfg.cCfgSQL()
246
247 ifap_cmd = dbcfg.get2 (
248 option = 'external.ifap-win.shell_command',
249 workplace = gmSurgery.gmCurrentPractice().active_workplace,
250 bias = 'workplace',
251 default = 'wine "C:\Ifapwin\WIAMDB.EXE"'
252 )
253 found, binary = gmShellAPI.detect_external_binary(ifap_cmd)
254 if not found:
255 gmDispatcher.send('statustext', msg = _('Cannot call IFAP via [%s].') % ifap_cmd)
256 return False
257 ifap_cmd = binary
258
259 if import_drugs:
260 transfer_file = os.path.expanduser(dbcfg.get2 (
261 option = 'external.ifap-win.transfer_file',
262 workplace = gmSurgery.gmCurrentPractice().active_workplace,
263 bias = 'workplace',
264 default = '~/.wine/drive_c/Ifapwin/ifap2gnumed.csv'
265 ))
266
267 try:
268 f = open(transfer_file, 'w+b').close()
269 except IOError:
270 _log.exception('Cannot create IFAP <-> GNUmed transfer file [%s]', transfer_file)
271 gmDispatcher.send('statustext', msg = _('Cannot create IFAP <-> GNUmed transfer file [%s].') % transfer_file)
272 return False
273
274 wx.BeginBusyCursor()
275 gmShellAPI.run_command_in_shell(command = ifap_cmd, blocking = import_drugs)
276 wx.EndBusyCursor()
277
278 if import_drugs:
279
280
281 try:
282 csv_file = open(transfer_file, 'rb')
283 except:
284 _log.exception('cannot access [%s]', fname)
285 csv_file = None
286
287 if csv_file is not None:
288 import csv
289 csv_lines = csv.DictReader (
290 csv_file,
291 fieldnames = u'PZN Handelsname Form Abpackungsmenge Einheit Preis1 Hersteller Preis2 rezeptpflichtig Festbetrag Packungszahl Packungsgr\xf6\xdfe'.split(),
292 delimiter = ';'
293 )
294 pat = gmPerson.gmCurrentPatient()
295 emr = pat.get_emr()
296
297 epi = emr.add_episode(episode_name = _('Current medication'))
298 for line in csv_lines:
299 narr = u'%sx %s %s %s (\u2258 %s %s) von %s (%s)' % (
300 line['Packungszahl'].strip(),
301 line['Handelsname'].strip(),
302 line['Form'].strip(),
303 line[u'Packungsgr\xf6\xdfe'].strip(),
304 line['Abpackungsmenge'].strip(),
305 line['Einheit'].strip(),
306 line['Hersteller'].strip(),
307 line['PZN'].strip()
308 )
309 emr.add_clin_narrative(note = narr, soap_cat = 's', episode = epi)
310 csv_file.close()
311
312 return True
313
315
316 dlg = wx.FileDialog (
317 parent = None,
318 message = _('Choose an ATC import config file'),
319 defaultDir = os.path.expanduser(os.path.join('~', 'gnumed')),
320 defaultFile = '',
321 wildcard = "%s (*.conf)|*.conf|%s (*)|*" % (_('config files'), _('all files')),
322 style = wx.OPEN | wx.HIDE_READONLY | wx.FILE_MUST_EXIST
323 )
324
325 result = dlg.ShowModal()
326 if result == wx.ID_CANCEL:
327 return
328
329 cfg_file = dlg.GetPath()
330 dlg.Destroy()
331
332 conn = gmAuthWidgets.get_dbowner_connection(procedure = _('importing ATC reference data'))
333 if conn is None:
334 return False
335
336 wx.BeginBusyCursor()
337
338 if gmATC.atc_import(cfg_fname = cfg_file, conn = conn):
339 gmDispatcher.send(signal = 'statustext', msg = _('Successfully imported ATC reference data.'))
340 else:
341 gmDispatcher.send(signal = 'statustext', msg = _('Importing ATC reference data failed.'), beep = True)
342
343 wx.EndBusyCursor()
344 return True
345
346
347
348
350
352
353 query = u"""
354 SELECT schedule as sched, schedule
355 FROM clin.substance_intake
356 where schedule %(fragment_condition)s
357 ORDER BY sched
358 LIMIT 50"""
359
360 mp = gmMatchProvider.cMatchProvider_SQL2(queries = query)
361 mp.setThresholds(1, 2, 4)
362 gmPhraseWheel.cPhraseWheel.__init__(self, *args, **kwargs)
363 self.SetToolTipString(_('The schedule for taking this substance.'))
364 self.matcher = mp
365 self.selection_only = False
366
368
370
371 query = u"""
372 (
373 SELECT preparation as prep, preparation
374 FROM ref.branded_drug
375 where preparation %(fragment_condition)s
376 ) union (
377 SELECT preparation as prep, preparation
378 FROM clin.substance_intake
379 where preparation %(fragment_condition)s
380 )
381 order by prep
382 limit 30"""
383
384 mp = gmMatchProvider.cMatchProvider_SQL2(queries = query)
385 mp.setThresholds(1, 2, 4)
386 gmPhraseWheel.cPhraseWheel.__init__(self, *args, **kwargs)
387 self.SetToolTipString(_('The preparation (form) of the substance the patient is taking.'))
388 self.matcher = mp
389 self.selection_only = False
390
392
394
395 query = u"""
396 (
397 SELECT pk, (coalesce(atc_code || ': ', '') || description) as subst
398 FROM clin.consumed_substance
399 WHERE description %(fragment_condition)s
400 ) union (
401 SELECT NULL, (coalesce(atc_code || ': ', '') || description) as subst
402 FROM ref.substance_in_brand
403 WHERE description %(fragment_condition)s
404 )
405 order by subst
406 limit 50"""
407
408 mp = gmMatchProvider.cMatchProvider_SQL2(queries = query)
409 mp.setThresholds(1, 2, 4)
410 gmPhraseWheel.cPhraseWheel.__init__(self, *args, **kwargs)
411 self.SetToolTipString(_('The INN / substance the patient is taking.'))
412 self.matcher = mp
413 self.selection_only = False
414
416
418
419 query = u"""
420 SELECT pk, (coalesce(atc_code || ': ', '') || description || ' (' || preparation || ')') as brand
421 FROM ref.branded_drug
422 WHERE description %(fragment_condition)s
423 ORDER BY brand
424 LIMIT 50"""
425
426 mp = gmMatchProvider.cMatchProvider_SQL2(queries = query)
427 mp.setThresholds(2, 3, 4)
428 gmPhraseWheel.cPhraseWheel.__init__(self, *args, **kwargs)
429 self.SetToolTipString(_('The brand name of the drug the patient is taking.'))
430 self.matcher = mp
431 self.selection_only = False
432
433
434 from Gnumed.wxGladeWidgets import wxgCurrentMedicationEAPnl
435
436 -class cCurrentMedicationEAPnl(wxgCurrentMedicationEAPnl.wxgCurrentMedicationEAPnl, gmEditArea.cGenericEditAreaMixin):
437
454
460
461
462
463
503
577
616
636
638
639 self._PRW_substance.SetText(self.data['substance'], self.data['pk_substance'])
640 self._PRW_strength.SetText(gmTools.coalesce(self.data['strength'], u''), self.data['strength'])
641 self._PRW_preparation.SetText(gmTools.coalesce(self.data['preparation'], u''), self.data['preparation'])
642 if self.data['is_long_term']:
643 self._CHBOX_long_term.SetValue(True)
644 self._PRW_duration.Enable(False)
645 self._PRW_duration.SetText(gmTools.u_infinity, None)
646 else:
647 self._CHBOX_long_term.SetValue(False)
648 self._PRW_duration.Enable(True)
649 if self.data['duration'] is None:
650 self._PRW_duration.SetText(u'', None)
651 else:
652 self._PRW_duration.SetText(gmDateTime.format_interval(self.data['duration'], gmDateTime.acc_days), self.data['duration'])
653 self._PRW_aim.SetText(gmTools.coalesce(self.data['aim'], u''), self.data['aim'])
654 self._PRW_notes.SetText(gmTools.coalesce(self.data['notes'], u''), self.data['notes'])
655 self._PRW_episode.SetData(self.data['pk_episode'])
656 self._PRW_schedule.SetText(gmTools.coalesce(self.data['schedule'], u''), self.data['schedule'])
657
658 self._CHBOX_approved.SetValue(self.data['intake_is_approved_of'])
659
660 self._DP_started.SetValue(gmDateTime.py_dt2wxDate(py_dt = self.data['started'], wx = wx))
661
662 self._PRW_brand.SetText(u'', None)
663 self._TCTRL_brand_ingredients.SetValue(u'')
664 if self.data['pk_brand'] is not None:
665 brand = gmMedication.cBrandedDrug(aPK_obj = self.data['pk_brand'])
666 self._PRW_brand.SetText(brand['description'], self.data['pk_brand'])
667 comps = brand.components
668 if comps is not None:
669 comps = u' / '.join([ u'%s%s' % (c['description'], gmTools.coalesce(c['atc_code'], u'', u' (%s)')) for c in comps ])
670 self._TCTRL_brand_ingredients.SetValue(comps)
671
672 self._PRW_substance.SetFocus()
673
675 self._refresh_as_new()
676
677 self._PRW_substance.SetText(u'', None)
678 self._PRW_strength.SetText(u'', None)
679 self._PRW_notes.SetText(u'', None)
680
681 self._PRW_substance.SetFocus()
682
683
684
686 self._TCTRL_brand_ingredients.SetValue(u'')
687
688 pk_brand = self._PRW_brand.GetData()
689 if pk_brand is None:
690 return
691
692 brand = gmMedication.cBrandedDrug(aPK_obj = pk_brand)
693 self._PRW_preparation.SetText(brand['preparation'], None)
694
695 comps = brand.components
696 if comps is None:
697 return
698 comps = u' / '.join([ u'%s%s' % (c['description'], gmTools.coalesce(c['atc_code'], u'', u' (%s)')) for c in comps ])
699 self._TCTRL_brand_ingredients.SetValue(comps)
700
716
732
734 if self._CHBOX_long_term.IsChecked() is True:
735 self._PRW_duration.Enable(False)
736 else:
737 self._PRW_duration.Enable(True)
738
740 delete_it = gmGuiHelpers.gm_show_question (
741 aMessage = _(
742 'Do you really want to remove this substance intake ?\n'
743 '\n'
744 'It may be prudent to edit the details first so as to\n'
745 'leave behind some indication of why it was deleted.\n'
746 ),
747 aTitle = _('Deleting medication / substance intake')
748 )
749 if not delete_it:
750 return
751
752 gmMedication.delete_substance_intake(substance = substance)
753
763
764
765
786
788
789 if parent is None:
790 parent = wx.GetApp().GetTopWindow()
791
792
793 dbcfg = gmCfg.cCfgSQL()
794 option = u'form_templates.medication_list'
795
796 template = dbcfg.get2 (
797 option = option,
798 workplace = gmSurgery.gmCurrentPractice().active_workplace,
799 bias = 'user'
800 )
801
802 if template is None:
803 template = configure_medication_list_template(parent = parent)
804 if template is None:
805 gmGuiHelpers.gm_show_error (
806 aMessage = _('There is no medication list template configured.'),
807 aTitle = _('Printing medication list')
808 )
809 return False
810 else:
811 try:
812 name, ver = template.split(u' - ')
813 except:
814 _log.exception('problem splitting medication list template name [%s]', template)
815 gmDispatcher.send(signal = 'statustext', msg = _('Problem loading medication list template.'), beep = True)
816 return False
817 template = gmForms.get_form_template(name_long = name, external_version = ver)
818 if template is None:
819 gmGuiHelpers.gm_show_error (
820 aMessage = _('Cannot load medication list template [%s - %s]') % (name, ver),
821 aTitle = _('Printing medication list')
822 )
823 return False
824
825
826 meds_list = template.instantiate()
827 ph = gmMacro.gmPlaceholderHandler()
828
829 meds_list.substitute_placeholders(data_source = ph)
830 pdf_name = meds_list.generate_output(cleanup = cleanup)
831 if cleanup:
832 meds_list.cleanup()
833 if pdf_name is None:
834 gmGuiHelpers.gm_show_error (
835 aMessage = _('Error generating the medication list.'),
836 aTitle = _('Printing medication list')
837 )
838 return False
839
840
841 printed = gmPrinting.print_file_by_shellscript(filename = pdf_name, jobtype = 'medication_list')
842 if not printed:
843 gmGuiHelpers.gm_show_error (
844 aMessage = _('Error printing the medication list.'),
845 aTitle = _('Printing medication list')
846 )
847 return False
848
849 pat = gmPerson.gmCurrentPatient()
850 emr = pat.get_emr()
851 epi = emr.add_episode(episode_name = 'administration', is_open = False)
852 emr.add_clin_narrative (
853 soap_cat = None,
854 note = _('medication list printed from template [%s - %s]') % (template['name_long'], template['external_version']),
855 episode = epi
856 )
857
858 return True
859
861 """A grid class for displaying current substance intake.
862
863 - does NOT listen to the currently active patient
864 - thereby it can display any patient at any time
865 """
867
868 wx.grid.Grid.__init__(self, *args, **kwargs)
869
870 self.__patient = None
871 self.__row_data = {}
872 self.__row_tooltips = {}
873 self.__prev_row = None
874 self.__prev_tooltip_row = None
875 self.__prev_cell_0 = None
876 self.__grouping_mode = u'episode'
877 self.__filter_show_unapproved = False
878 self.__filter_show_inactive = False
879
880 self.__grouping2col_labels = {
881 u'episode': [
882 _('Episode'),
883 _('Substance'),
884 _('Dose'),
885 _('Schedule'),
886 _('Started'),
887 _('Duration'),
888 _('Brand')
889 ],
890 u'brand': [
891 _('Brand'),
892 _('Schedule'),
893 _('Substance'),
894 _('Dose'),
895 _('Started'),
896 _('Duration'),
897 _('Episode')
898 ]
899 }
900
901 self.__grouping2order_by_clauses = {
902 u'episode': u'pk_health_issue nulls first, episode, substance, started',
903 u'brand': u'brand nulls last, substance, started'
904 }
905
906 self.__init_ui()
907 self.__register_events()
908
909
910
912
913 sel_block_top_left = self.GetSelectionBlockTopLeft()
914 sel_block_bottom_right = self.GetSelectionBlockBottomRight()
915 sel_cols = self.GetSelectedCols()
916 sel_rows = self.GetSelectedRows()
917
918 selected_cells = []
919
920
921 selected_cells += self.GetSelectedCells()
922
923
924 selected_cells += list (
925 (row, col)
926 for row in sel_rows
927 for col in xrange(self.GetNumberCols())
928 )
929
930
931 selected_cells += list (
932 (row, col)
933 for row in xrange(self.GetNumberRows())
934 for col in sel_cols
935 )
936
937
938 for top_left, bottom_right in zip(self.GetSelectionBlockTopLeft(), self.GetSelectionBlockBottomRight()):
939 selected_cells += [
940 (row, col)
941 for row in xrange(top_left[0], bottom_right[0] + 1)
942 for col in xrange(top_left[1], bottom_right[1] + 1)
943 ]
944
945 return set(selected_cells)
946
948 rows = {}
949
950 for row, col in self.get_selected_cells():
951 rows[row] = True
952
953 return rows.keys()
954
957
959
960 self.empty_grid()
961
962 if self.__patient is None:
963 return
964
965 emr = self.__patient.get_emr()
966 meds = emr.get_current_substance_intake (
967 order_by = self.__grouping2order_by_clauses[self.__grouping_mode],
968 include_unapproved = self.__filter_show_unapproved,
969 include_inactive = self.__filter_show_inactive
970 )
971 if not meds:
972 return
973
974 self.BeginBatch()
975
976
977 labels = self.__grouping2col_labels[self.__grouping_mode]
978 if self.__filter_show_unapproved:
979 self.AppendCols(numCols = len(labels) + 1)
980 else:
981 self.AppendCols(numCols = len(labels))
982 for col_idx in range(len(labels)):
983 self.SetColLabelValue(col_idx, labels[col_idx])
984 if self.__filter_show_unapproved:
985 self.SetColLabelValue(len(labels), u'OK?')
986 self.SetColSize(len(labels), 40)
987
988 self.AppendRows(numRows = len(meds))
989
990
991 for row_idx in range(len(meds)):
992 med = meds[row_idx]
993 self.__row_data[row_idx] = med
994
995 if med['is_currently_active'] is not True:
996 attr = self.GetOrCreateCellAttr(row_idx, 0)
997 attr.SetTextColour('grey')
998 self.SetRowAttr(row_idx, attr)
999
1000 if self.__grouping_mode == u'episode':
1001 if med['pk_episode'] is None:
1002 self.__prev_cell_0 = None
1003 self.SetCellValue(row_idx, 0, gmTools.u_diameter)
1004 else:
1005 if self.__prev_cell_0 != med['episode']:
1006 self.__prev_cell_0 = med['episode']
1007 self.SetCellValue(row_idx, 0, gmTools.coalesce(med['episode'], u''))
1008
1009 self.SetCellValue(row_idx, 1, med['substance'])
1010 self.SetCellValue(row_idx, 2, gmTools.coalesce(med['strength'], u''))
1011 self.SetCellValue(row_idx, 3, gmTools.coalesce(med['schedule'], u''))
1012 self.SetCellValue(row_idx, 4, med['started'].strftime('%Y-%m-%d'))
1013
1014 if med['is_long_term']:
1015 self.SetCellValue(row_idx, 5, gmTools.u_infinity)
1016 else:
1017 if med['duration'] is None:
1018 self.SetCellValue(row_idx, 5, u'')
1019 else:
1020 self.SetCellValue(row_idx, 5, gmDateTime.format_interval(med['duration'], gmDateTime.acc_days))
1021
1022 if med['pk_brand'] is None:
1023 self.SetCellValue(row_idx, 6, gmTools.coalesce(med['brand'], u''))
1024 else:
1025 if med['fake_brand']:
1026 self.SetCellValue(row_idx, 6, gmTools.coalesce(med['brand'], u'', _('%s (fake)')))
1027 else:
1028 self.SetCellValue(row_idx, 6, gmTools.coalesce(med['brand'], u''))
1029
1030 elif self.__grouping_mode == u'brand':
1031
1032 if med['pk_brand'] is None:
1033 self.__prev_cell_0 = None
1034 self.SetCellValue(row_idx, 0, gmTools.u_diameter)
1035 else:
1036 if self.__prev_cell_0 != med['brand']:
1037 self.__prev_cell_0 = med['brand']
1038 if med['fake_brand']:
1039 self.SetCellValue(row_idx, 0, gmTools.coalesce(med['brand'], u'', _('%s (fake)')))
1040 else:
1041 self.SetCellValue(row_idx, 0, gmTools.coalesce(med['brand'], u''))
1042
1043 self.SetCellValue(row_idx, 1, gmTools.coalesce(med['schedule'], u''))
1044 self.SetCellValue(row_idx, 2, med['substance'])
1045 self.SetCellValue(row_idx, 3, gmTools.coalesce(med['strength'], u''))
1046 self.SetCellValue(row_idx, 4, med['started'].strftime('%Y-%m-%d'))
1047
1048 if med['is_long_term']:
1049 self.SetCellValue(row_idx, 5, gmTools.u_infinity)
1050 else:
1051 if med['duration'] is None:
1052 self.SetCellValue(row_idx, 5, u'')
1053 else:
1054 self.SetCellValue(row_idx, 5, gmDateTime.format_interval(med['duration'], gmDateTime.acc_days))
1055
1056 if med['pk_episode'] is None:
1057 self.SetCellValue(row_idx, 6, u'')
1058 else:
1059 self.SetCellValue(row_idx, 6, gmTools.coalesce(med['episode'], u''))
1060
1061 else:
1062 raise ValueError('unknown grouping mode [%s]' % self.__grouping_mode)
1063
1064 if self.__filter_show_unapproved:
1065 self.SetCellValue (
1066 row_idx,
1067 len(labels),
1068 gmTools.bool2subst(med['intake_is_approved_of'], gmTools.u_checkmark_thin, u'', u'?')
1069 )
1070
1071
1072
1073 self.EndBatch()
1074
1076 self.BeginBatch()
1077 self.ClearGrid()
1078
1079
1080 if self.GetNumberRows() > 0:
1081 self.DeleteRows(pos = 0, numRows = self.GetNumberRows())
1082 if self.GetNumberCols() > 0:
1083 self.DeleteCols(pos = 0, numCols = self.GetNumberCols())
1084 self.EndBatch()
1085 self.__row_data = {}
1086 self.__prev_cell_0 = None
1087
1089
1090 if len(self.__row_data) == 0:
1091 return
1092
1093 sel_rows = self.get_selected_rows()
1094 if len(sel_rows) != 1:
1095 return
1096
1097 drug_db = get_drug_database()
1098 if drug_db is None:
1099 return
1100
1101 drug_db.show_info_on_substance(substance = self.get_selected_data()[0])
1102
1116
1119
1133
1135
1136 rows = self.get_selected_rows()
1137
1138 if len(rows) == 0:
1139 return
1140
1141 if len(rows) > 1:
1142 gmDispatcher.send(signal = 'statustext', msg = _('Cannot delete more than one substance at once.'), beep = True)
1143 return
1144
1145 subst = self.get_selected_data()[0]
1146 delete_substance_intake(parent = self, substance = subst['pk_substance_intake'])
1147
1152
1219
1220
1221
1223 self.CreateGrid(0, 1)
1224 self.EnableEditing(0)
1225 self.EnableDragGridSize(1)
1226 self.SetSelectionMode(wx.grid.Grid.wxGridSelectRows)
1227
1228 self.SetColLabelAlignment(wx.ALIGN_LEFT, wx.ALIGN_CENTER)
1229
1230 self.SetRowLabelSize(0)
1231 self.SetRowLabelAlignment(horiz = wx.ALIGN_RIGHT, vert = wx.ALIGN_CENTRE)
1232
1233
1234
1236 return self.__patient
1237
1241
1242 patient = property(_get_patient, _set_patient)
1243
1245 return self.__grouping_mode
1246
1250
1251 grouping_mode = property(_get_grouping_mode, _set_grouping_mode)
1252
1254 return self.__filter_show_unapproved
1255
1259
1260 filter_show_unapproved = property(_get_filter_show_unapproved, _set_filter_show_unapproved)
1261
1263 return self.__filter_show_inactive
1264
1268
1269 filter_show_inactive = property(_get_filter_show_inactive, _set_filter_show_inactive)
1270
1271
1272
1274
1275 self.GetGridWindow().Bind(wx.EVT_MOTION, self.__on_mouse_over_cells)
1276
1277
1278
1279
1280 self.Bind(wx.grid.EVT_GRID_CELL_LEFT_DCLICK, self.__on_cell_left_dclicked)
1281
1283 """Calculate where the mouse is and set the tooltip dynamically."""
1284
1285
1286
1287 x, y = self.CalcUnscrolledPosition(evt.GetX(), evt.GetY())
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301 row, col = self.XYToCell(x, y)
1302
1303 if row == self.__prev_tooltip_row:
1304 return
1305
1306 self.__prev_tooltip_row = row
1307
1308 try:
1309 evt.GetEventObject().SetToolTipString(self.get_row_tooltip(row = row))
1310 except KeyError:
1311 pass
1312
1317
1318 from Gnumed.wxGladeWidgets import wxgCurrentSubstancesPnl
1319
1320 -class cCurrentSubstancesPnl(wxgCurrentSubstancesPnl.wxgCurrentSubstancesPnl, gmRegetMixin.cRegetOnPaintMixin):
1321
1322 """Panel holding a grid with current substances. Used as notebook page."""
1323
1330
1331
1332
1341
1342
1343
1345 gmDispatcher.connect(signal = u'pre_patient_selection', receiver = self._on_pre_patient_selection)
1346 gmDispatcher.connect(signal = u'post_patient_selection', receiver = self._schedule_data_reget)
1347 gmDispatcher.connect(signal = u'substance_intake_mod_db', receiver = self._schedule_data_reget)
1348
1349
1350
1352 wx.CallAfter(self.__on_pre_patient_selection)
1353
1355 self._grid_substances.patient = None
1356
1359
1362
1365
1368
1371
1374
1377
1380
1383
1386
1387
1388
1389 if __name__ == '__main__':
1390
1391 from Gnumed.pycommon import gmI18N
1392
1393 gmI18N.activate_locale()
1394 gmI18N.install_domain(domain = 'gnumed')
1395
1396
1397
1398 if (len(sys.argv) > 1) and (sys.argv[1] == 'test'):
1399
1400 pass
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525