Package Gnumed :: Package wxpython :: Module gmMedicationWidgets
[frames] | no frames]

Source Code for Module Gnumed.wxpython.gmMedicationWidgets

   1  """GNUmed medication/substances handling widgets. 
   2  """ 
   3  #================================================================ 
   4  # $Source: /cvsroot/gnumed/gnumed/gnumed/client/wxpython/gmMedicationWidgets.py,v $ 
   5  # $Id: gmMedicationWidgets.py,v 1.32 2010/01/13 21:52:04 ncq Exp $ 
   6  __version__ = "$Revision: 1.32 $" 
   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  #============================================================ 
27 -def manage_substances_in_brands(parent=None):
28 29 if parent is None: 30 parent = wx.GetApp().GetTopWindow() 31 32 #------------------------------------------------------------ 33 def delete(component): 34 gmMedication.delete_component_from_branded_drug ( 35 brand = component['pk_brand'], 36 component = component['pk_substance_in_brand'] 37 ) 38 return True
39 #------------------------------------------------------------ 40 def refresh(lctrl): 41 substs = gmMedication.get_substances_in_brands() 42 items = [ [ 43 u'%s%s' % (s['brand'], gmTools.coalesce(s['atc_brand'], u'', u' (%s)')), 44 s['substance'], 45 gmTools.coalesce(s['atc_substance'], u''), 46 s['preparation'], 47 gmTools.coalesce(s['external_code_brand'], u''), 48 s['pk_substance_in_brand'] 49 ] for s in substs ] 50 lctrl.set_string_items(items) 51 lctrl.set_data(substs) 52 #------------------------------------------------------------ 53 msg = _('\nThese are the substances in the drug brands known to GNUmed.\n') 54 55 gmListWidgets.get_choices_from_list ( 56 parent = parent, 57 msg = msg, 58 caption = _('Showing drug brand components (substances).'), 59 columns = [_('Brand'), _('Substance'), u'ATC', _('Preparation'), _('Code'), u'#'], 60 single_selection = True, 61 #new_callback = new, 62 #edit_callback = edit, 63 delete_callback = delete, 64 refresh_callback = refresh 65 ) 66 #============================================================
67 -def manage_branded_drugs(parent=None):
68 69 if parent is None: 70 parent = wx.GetApp().GetTopWindow() 71 #------------------------------------------------------------ 72 def delete(brand): 73 gmMedication.delete_branded_drug(brand = brand['pk']) 74 return True
75 #------------------------------------------------------------ 76 def new(): 77 drug_db = get_drug_database(parent = parent) 78 79 if drug_db is None: 80 return False 81 82 drug_db.import_drugs() 83 84 return True 85 #------------------------------------------------------------ 86 def refresh(lctrl): 87 drugs = gmMedication.get_branded_drugs() 88 items = [ [ 89 d['description'], 90 d['preparation'], 91 gmTools.coalesce(d['atc_code'], u''), 92 gmTools.coalesce(d['external_code'], u''), 93 d['pk'] 94 ] for d in drugs ] 95 lctrl.set_string_items(items) 96 lctrl.set_data(drugs) 97 #------------------------------------------------------------ 98 msg = _('\nThese are the drug brands known to GNUmed.\n') 99 100 gmListWidgets.get_choices_from_list ( 101 parent = parent, 102 msg = msg, 103 caption = _('Showing branded drugs.'), 104 columns = [_('Name'), _('Preparation'), _('ATC'), _('Code'), u'#'], 105 single_selection = True, 106 refresh_callback = refresh, 107 new_callback = new, 108 #edit_callback = edit, 109 delete_callback = delete 110 ) 111 #============================================================
112 -def manage_substances_in_use(parent=None):
113 114 if parent is None: 115 parent = wx.GetApp().GetTopWindow() 116 #------------------------------------------------------------ 117 def delete(substance): 118 gmMedication.delete_used_substance(substance = substance['pk']) 119 return True
120 #------------------------------------------------------------ 121 def new(): 122 drug_db = get_drug_database(parent = parent) 123 124 if drug_db is None: 125 return False 126 127 drug_db.import_drugs() 128 129 return True 130 #------------------------------------------------------------ 131 def refresh(lctrl): 132 substs = gmMedication.get_substances_in_use() 133 items = [ [ 134 s['description'], 135 gmTools.coalesce(s['atc_code'], u''), 136 s['pk'] 137 ] for s in substs ] 138 lctrl.set_string_items(items) 139 lctrl.set_data(substs) 140 #------------------------------------------------------------ 141 msg = _('\nThese are the substances currently or previously\nconsumed across all patients.\n') 142 143 gmListWidgets.get_choices_from_list ( 144 parent = parent, 145 msg = msg, 146 caption = _('Showing consumed substances.'), 147 columns = [_('Name'), _('ATC'), u'#'], 148 single_selection = True, 149 refresh_callback = refresh, 150 new_callback = new, 151 #edit_callback = edit, 152 delete_callback = delete 153 ) 154 #============================================================ 155 # generic drug database access 156 #============================================================
157 -def configure_drug_data_source(parent=None):
158 gmCfgWidgets.configure_string_from_list_option ( 159 parent = parent, 160 message = _( 161 '\n' 162 'Please select the default drug data source from the list below.\n' 163 '\n' 164 'Note that to actually use it you need to have the database installed, too.' 165 ), 166 option = 'external.drug_data.default_source', 167 bias = 'user', 168 default_value = None, 169 choices = gmMedication.drug_data_source_interfaces.keys(), 170 columns = [_('Drug data source')], 171 data = gmMedication.drug_data_source_interfaces.keys(), 172 caption = _('Configuring default drug data source') 173 )
174 #============================================================
175 -def get_drug_database(parent = None):
176 dbcfg = gmCfg.cCfgSQL() 177 178 default_db = dbcfg.get2 ( 179 option = 'external.drug_data.default_source', 180 workplace = gmSurgery.gmCurrentPractice().active_workplace, 181 bias = 'workplace' 182 ) 183 184 if default_db is None: 185 gmDispatcher.send('statustext', msg = _('No default drug database configured.'), beep = True) 186 configure_drug_data_source(parent = parent) 187 default_db = dbcfg.get2 ( 188 option = 'external.drug_data.default_source', 189 workplace = gmSurgery.gmCurrentPractice().active_workplace, 190 bias = 'workplace' 191 ) 192 if default_db is None: 193 gmGuiHelpers.gm_show_error ( 194 aMessage = _('There is no default drug database configured.'), 195 aTitle = _('Jumping to drug database') 196 ) 197 return None 198 199 try: 200 return gmMedication.drug_data_source_interfaces[default_db]() 201 except KeyError: 202 _log.error('faulty default drug data source configuration: %s', default_db) 203 return None
204 #============================================================
205 -def jump_to_drug_database():
206 dbcfg = gmCfg.cCfgSQL() 207 drug_db = get_drug_database() 208 if drug_db is None: 209 return 210 drug_db.switch_to_frontend(blocking = False)
211 #============================================================
212 -def jump_to_ifap(import_drugs=False):
213 214 dbcfg = gmCfg.cCfgSQL() 215 216 ifap_cmd = dbcfg.get2 ( 217 option = 'external.ifap-win.shell_command', 218 workplace = gmSurgery.gmCurrentPractice().active_workplace, 219 bias = 'workplace', 220 default = 'wine "C:\Ifapwin\WIAMDB.EXE"' 221 ) 222 found, binary = gmShellAPI.detect_external_binary(ifap_cmd) 223 if not found: 224 gmDispatcher.send('statustext', msg = _('Cannot call IFAP via [%s].') % ifap_cmd) 225 return False 226 ifap_cmd = binary 227 228 if import_drugs: 229 transfer_file = os.path.expanduser(dbcfg.get2 ( 230 option = 'external.ifap-win.transfer_file', 231 workplace = gmSurgery.gmCurrentPractice().active_workplace, 232 bias = 'workplace', 233 default = '~/.wine/drive_c/Ifapwin/ifap2gnumed.csv' 234 )) 235 # file must exist for Ifap to write into it 236 try: 237 f = open(transfer_file, 'w+b').close() 238 except IOError: 239 _log.exception('Cannot create IFAP <-> GNUmed transfer file [%s]', transfer_file) 240 gmDispatcher.send('statustext', msg = _('Cannot create IFAP <-> GNUmed transfer file [%s].') % transfer_file) 241 return False 242 243 wx.BeginBusyCursor() 244 gmShellAPI.run_command_in_shell(command = ifap_cmd, blocking = import_drugs) 245 wx.EndBusyCursor() 246 247 if import_drugs: 248 # COMMENT: this file must exist PRIOR to invoking IFAP 249 # COMMENT: or else IFAP will not write data into it ... 250 try: 251 csv_file = open(transfer_file, 'rb') # FIXME: encoding 252 except: 253 _log.exception('cannot access [%s]', fname) 254 csv_file = None 255 256 if csv_file is not None: 257 import csv 258 csv_lines = csv.DictReader ( 259 csv_file, 260 fieldnames = u'PZN Handelsname Form Abpackungsmenge Einheit Preis1 Hersteller Preis2 rezeptpflichtig Festbetrag Packungszahl Packungsgr\xf6\xdfe'.split(), 261 delimiter = ';' 262 ) 263 pat = gmPerson.gmCurrentPatient() 264 emr = pat.get_emr() 265 # dummy episode for now 266 epi = emr.add_episode(episode_name = _('Current medication')) 267 for line in csv_lines: 268 narr = u'%sx %s %s %s (\u2258 %s %s) von %s (%s)' % ( 269 line['Packungszahl'].strip(), 270 line['Handelsname'].strip(), 271 line['Form'].strip(), 272 line[u'Packungsgr\xf6\xdfe'].strip(), 273 line['Abpackungsmenge'].strip(), 274 line['Einheit'].strip(), 275 line['Hersteller'].strip(), 276 line['PZN'].strip() 277 ) 278 emr.add_clin_narrative(note = narr, soap_cat = 's', episode = epi) 279 csv_file.close() 280 281 return True
282 #============================================================
283 -def update_atc_reference_data():
284 285 dlg = wx.FileDialog ( 286 parent = None, 287 message = _('Choose an ATC import config file'), 288 defaultDir = os.path.expanduser(os.path.join('~', 'gnumed')), 289 defaultFile = '', 290 wildcard = "%s (*.conf)|*.conf|%s (*)|*" % (_('config files'), _('all files')), 291 style = wx.OPEN | wx.HIDE_READONLY | wx.FILE_MUST_EXIST 292 ) 293 294 result = dlg.ShowModal() 295 if result == wx.ID_CANCEL: 296 return 297 298 cfg_file = dlg.GetPath() 299 dlg.Destroy() 300 301 conn = gmAuthWidgets.get_dbowner_connection(procedure = _('importing ATC reference data')) 302 if conn is None: 303 return False 304 305 wx.BeginBusyCursor() 306 307 if gmATC.atc_import(cfg_fname = cfg_file, conn = conn): 308 gmDispatcher.send(signal = 'statustext', msg = _('Successfully imported ATC reference data.')) 309 else: 310 gmDispatcher.send(signal = 'statustext', msg = _('Importing ATC reference data failed.'), beep = True) 311 312 wx.EndBusyCursor() 313 return True
314 315 #============================================================ 316 # current medication widgets 317 #============================================================
318 -class cSubstanceSchedulePhraseWheel(gmPhraseWheel.cPhraseWheel):
319
320 - def __init__(self, *args, **kwargs):
321 322 query = u""" 323 SELECT schedule as sched, schedule 324 FROM clin.substance_intake 325 where schedule %(fragment_condition)s 326 ORDER BY sched 327 LIMIT 50""" 328 329 mp = gmMatchProvider.cMatchProvider_SQL2(queries = query) 330 mp.setThresholds(1, 2, 4) 331 gmPhraseWheel.cPhraseWheel.__init__(self, *args, **kwargs) 332 self.SetToolTipString(_('The schedule for taking this substance.')) 333 self.matcher = mp 334 self.selection_only = False
335 #============================================================
336 -class cSubstancePreparationPhraseWheel(gmPhraseWheel.cPhraseWheel):
337
338 - def __init__(self, *args, **kwargs):
339 340 query = u""" 341 ( 342 SELECT preparation as prep, preparation 343 FROM ref.branded_drug 344 where preparation %(fragment_condition)s 345 ) union ( 346 SELECT preparation as prep, preparation 347 FROM clin.substance_intake 348 where preparation %(fragment_condition)s 349 ) 350 order by prep 351 limit 30""" 352 353 mp = gmMatchProvider.cMatchProvider_SQL2(queries = query) 354 mp.setThresholds(1, 2, 4) 355 gmPhraseWheel.cPhraseWheel.__init__(self, *args, **kwargs) 356 self.SetToolTipString(_('The preparation (form) of the substance the patient is taking.')) 357 self.matcher = mp 358 self.selection_only = False
359 #============================================================
360 -class cSubstancePhraseWheel(gmPhraseWheel.cPhraseWheel):
361
362 - def __init__(self, *args, **kwargs):
363 364 query = u""" 365 ( 366 SELECT pk, (coalesce(atc_code || ': ', '') || description) as subst 367 FROM clin.consumed_substance 368 WHERE description %(fragment_condition)s 369 ) union ( 370 SELECT NULL, (coalesce(atc_code || ': ', '') || description) as subst 371 FROM ref.substance_in_brand 372 WHERE description %(fragment_condition)s 373 ) 374 order by subst 375 limit 50""" 376 377 mp = gmMatchProvider.cMatchProvider_SQL2(queries = query) 378 mp.setThresholds(1, 2, 4) 379 gmPhraseWheel.cPhraseWheel.__init__(self, *args, **kwargs) 380 self.SetToolTipString(_('The INN / substance the patient is taking.')) 381 self.matcher = mp 382 self.selection_only = False
383 #============================================================
384 -class cBrandedDrugPhraseWheel(gmPhraseWheel.cPhraseWheel):
385
386 - def __init__(self, *args, **kwargs):
387 388 query = u""" 389 SELECT pk, (coalesce(atc_code || ': ', '') || description || ' (' || preparation || ')') as brand 390 FROM ref.branded_drug 391 WHERE description %(fragment_condition)s 392 ORDER BY brand 393 LIMIT 50""" 394 395 mp = gmMatchProvider.cMatchProvider_SQL2(queries = query) 396 mp.setThresholds(2, 3, 4) 397 gmPhraseWheel.cPhraseWheel.__init__(self, *args, **kwargs) 398 self.SetToolTipString(_('The brand name of the drug the patient is taking.')) 399 self.matcher = mp 400 self.selection_only = False
401 402 #============================================================ 403 from Gnumed.wxGladeWidgets import wxgCurrentMedicationEAPnl 404
405 -class cCurrentMedicationEAPnl(wxgCurrentMedicationEAPnl.wxgCurrentMedicationEAPnl, gmEditArea.cGenericEditAreaMixin):
406
407 - def __init__(self, *args, **kwargs):
408 409 try: 410 data = kwargs['substance'] 411 del kwargs['substance'] 412 except KeyError: 413 data = None 414 415 wxgCurrentMedicationEAPnl.wxgCurrentMedicationEAPnl.__init__(self, *args, **kwargs) 416 gmEditArea.cGenericEditAreaMixin.__init__(self) 417 self.mode = 'new' 418 self.data = data 419 if data is not None: 420 self.mode = 'edit' 421 422 self.__init_ui()
423 #----------------------------------------------------------------
424 - def __init_ui(self):
425 426 # adjust phrasewheels 427 428 self._PRW_brand.add_callback_on_lose_focus(callback = self._on_leave_brand)
429 430 #---------------------------------------------------------------- 431 # generic Edit Area mixin API 432 #----------------------------------------------------------------
433 - def _valid_for_save(self):
434 435 validity = True 436 437 if self._PRW_substance.GetValue().strip() == u'': 438 self._PRW_substance.display_as_valid(False) 439 validity = False 440 else: 441 self._PRW_substance.display_as_valid(True) 442 443 if self._PRW_preparation.GetValue().strip() == u'': 444 self._PRW_preparation.display_as_valid(False) 445 validity = False 446 else: 447 self._PRW_preparation.display_as_valid(True) 448 449 if self._CHBOX_approved.IsChecked(): 450 if self._PRW_episode.GetValue().strip() == u'': 451 self._PRW_episode.display_as_valid(False) 452 validity = False 453 else: 454 self._PRW_episode.display_as_valid(True) 455 456 if self._CHBOX_approved.IsChecked() is True: 457 self._PRW_duration.display_as_valid(True) 458 else: 459 if self._PRW_duration.GetValue().strip() in [u'', gmTools.u_infinity]: 460 self._PRW_duration.display_as_valid(True) 461 else: 462 if gmDateTime.str2interval(self._PRW_duration.GetValue()) is None: 463 self._PRW_duration.display_as_valid(False) 464 validity = False 465 else: 466 self._PRW_duration.display_as_valid(True) 467 468 if validity is False: 469 gmDispatcher.send(signal = 'statustext', msg = _('Cannot save substance intake. Invalid or missing essential input.')) 470 471 return validity
472 #----------------------------------------------------------------
473 - def _save_as_new(self):
474 475 emr = gmPerson.gmCurrentPatient().get_emr() 476 477 # 1) create substance intake entry 478 if self._PRW_substance.GetData() is None: 479 subst = self._PRW_substance.GetValue().strip() 480 else: 481 # normalize, do not simply re-use name from phrasewheel 482 subst = gmMedication.get_substance_by_pk(pk = self._PRW_substance.GetData())['description'] 483 484 intake = emr.add_substance_intake ( 485 substance = subst, 486 episode = self._PRW_episode.GetData(can_create = True), 487 preparation = self._PRW_preparation.GetValue() 488 ) 489 490 intake['strength'] = self._PRW_strength.GetValue() 491 intake['started'] = gmDateTime.wxDate2py_dt(wxDate = self._DP_started.GetValue()) 492 intake['schedule'] = self._PRW_schedule.GetValue() 493 intake['aim'] = self._PRW_aim.GetValue() 494 intake['notes'] = self._PRW_notes.GetValue() 495 intake['is_long_term'] = self._CHBOX_long_term.IsChecked() 496 intake['intake_is_approved_of'] = self._CHBOX_approved.IsChecked() 497 498 if self._PRW_duration.GetValue().strip() in [u'', gmTools.u_infinity]: 499 intake['duration'] = None 500 else: 501 intake['duration'] = gmDateTime.str2interval(self._PRW_duration.GetValue()) 502 503 # 2) create or retrieve brand 504 brand = None 505 pk_brand = self._PRW_brand.GetData() 506 507 # brand pre-selected ? 508 if pk_brand is None: 509 # no, so ... 510 desc = self._PRW_brand.GetValue().strip() 511 if desc != u'': 512 # ... create or get it 513 brand = gmMedication.create_branded_drug ( 514 brand_name = desc, 515 preparation = self._PRW_preparation.GetValue().strip(), 516 return_existing = True 517 ) 518 pk_brand = brand['pk'] 519 else: 520 # yes, so get it 521 brand = gmMedication.cBrandedDrug(aPK_obj = pk_brand) 522 523 # 3) link brand, if available 524 intake['pk_brand'] = pk_brand 525 intake.save() 526 527 # brand neither creatable nor pre-selected 528 if brand is None: 529 self.data = intake 530 return True 531 532 # 4) add substance to brand as component (because 533 # that's effectively what we are saying here) 534 # FIXME: we may want to ask the user here 535 # FIXME: or only do it if there are no components yet 536 if self._PRW_substance.GetData() is None: 537 brand.add_component(substance = self._PRW_substance.GetValue().strip()) 538 else: 539 # normalize substance name 540 subst = gmMedication.get_substance_by_pk(pk = self._PRW_substance.GetData()) 541 if subst is not None: 542 brand.add_component(substance = subst['description']) 543 544 self.data = intake 545 return True
546 #----------------------------------------------------------------
547 - def _save_as_update(self):
548 549 if self._PRW_substance.GetData() is None: 550 self.data['pk_substance'] = gmMedication.create_used_substance ( 551 substance = self._PRW_substance.GetValue().strip() 552 )['pk'] 553 else: 554 self.data['pk_substance'] = self._PRW_substance.GetData() 555 556 self.data['started'] = gmDateTime.wxDate2py_dt(wxDate = self._DP_started.GetValue()) 557 self.data['preparation'] = self._PRW_preparation.GetValue() 558 self.data['strength'] = self._PRW_strength.GetValue() 559 self.data['schedule'] = self._PRW_schedule.GetValue() 560 self.data['aim'] = self._PRW_aim.GetValue() 561 self.data['notes'] = self._PRW_notes.GetValue() 562 self.data['is_long_term'] = self._CHBOX_long_term.IsChecked() 563 self.data['intake_is_approved_of'] = self._CHBOX_approved.IsChecked() 564 self.data['pk_episode'] = self._PRW_episode.GetData(can_create = True) 565 566 if self._PRW_duration.GetValue().strip() in [u'', gmTools.u_infinity]: 567 self.data['duration'] = None 568 else: 569 self.data['duration'] = gmDateTime.str2interval(self._PRW_duration.GetValue()) 570 571 if self._PRW_brand.GetData() is None: 572 desc = self._PRW_brand.GetValue().strip() 573 if desc != u'': 574 # create or get brand 575 self.data['pk_brand'] = gmMedication.create_branded_drug ( 576 brand_name = desc, 577 preparation = self._PRW_preparation.GetValue().strip(), 578 return_existing = True 579 )['pk'] 580 else: 581 self.data['pk_brand'] = self._PRW_brand.GetData() 582 583 self.data.save() 584 return True
585 #----------------------------------------------------------------
586 - def _refresh_as_new(self):
587 self._PRW_substance.SetText(u'', None) 588 self._PRW_strength.SetText(u'', None) 589 self._PRW_preparation.SetText(u'', None) 590 self._PRW_schedule.SetText(u'', None) 591 self._PRW_duration.SetText(u'', None) 592 self._PRW_aim.SetText(u'', None) 593 self._PRW_notes.SetText(u'', None) 594 self._PRW_episode.SetData(None) 595 596 self._CHBOX_long_term.SetValue(False) 597 self._CHBOX_approved.SetValue(True) 598 599 self._DP_started.SetValue(dt = gmDateTime.py_dt2wxDate(py_dt = gmDateTime.pydt_now_here(), wx = wx)) 600 601 self._PRW_brand.SetText(u'', None) 602 self._TCTRL_brand_ingredients.SetValue(u'') 603 604 self._PRW_substance.SetFocus()
605 #----------------------------------------------------------------
606 - def _refresh_from_existing(self):
607 608 self._PRW_substance.SetText(self.data['substance'], self.data['pk_substance']) 609 self._PRW_strength.SetText(gmTools.coalesce(self.data['strength'], u''), self.data['strength']) 610 self._PRW_preparation.SetText(gmTools.coalesce(self.data['preparation'], u''), self.data['preparation']) 611 if self.data['is_long_term']: 612 self._CHBOX_long_term.SetValue(True) 613 self._PRW_duration.Enable(False) 614 self._PRW_duration.SetText(gmTools.u_infinity, None) 615 else: 616 self._CHBOX_long_term.SetValue(False) 617 self._PRW_duration.Enable(True) 618 if self.data['duration'] is None: 619 self._PRW_duration.SetText(u'', None) 620 else: 621 self._PRW_duration.SetText(gmDateTime.format_interval(self.data['duration'], gmDateTime.acc_days), self.data['duration']) 622 self._PRW_aim.SetText(gmTools.coalesce(self.data['aim'], u''), self.data['aim']) 623 self._PRW_notes.SetText(gmTools.coalesce(self.data['notes'], u''), self.data['notes']) 624 self._PRW_episode.SetData(self.data['pk_episode']) 625 self._PRW_schedule.SetText(gmTools.coalesce(self.data['schedule'], u''), self.data['schedule']) 626 627 self._CHBOX_approved.SetValue(self.data['intake_is_approved_of']) 628 629 self._DP_started.SetValue(gmDateTime.py_dt2wxDate(py_dt = self.data['started'], wx = wx)) 630 631 self._PRW_brand.SetText(u'', None) 632 self._TCTRL_brand_ingredients.SetValue(u'') 633 if self.data['pk_brand'] is not None: 634 brand = gmMedication.cBrandedDrug(aPK_obj = self.data['pk_brand']) 635 self._PRW_brand.SetText(brand['description'], self.data['pk_brand']) 636 comps = brand.components 637 if comps is not None: 638 comps = u' / '.join([ u'%s%s' % (c['description'], gmTools.coalesce(c['atc_code'], u'', u' (%s)')) for c in comps ]) 639 self._TCTRL_brand_ingredients.SetValue(comps) 640 641 self._PRW_substance.SetFocus()
642 #----------------------------------------------------------------
644 self._refresh_as_new() 645 646 self._PRW_substance.SetText(u'', None) 647 self._PRW_strength.SetText(u'', None) 648 self._PRW_notes.SetText(u'', None) 649 650 self._PRW_substance.SetFocus()
651 #---------------------------------------------------------------- 652 # event handlers 653 #----------------------------------------------------------------
654 - def _on_leave_brand(self):
655 self._TCTRL_brand_ingredients.SetValue(u'') 656 657 pk_brand = self._PRW_brand.GetData() 658 if pk_brand is None: 659 return 660 661 brand = gmMedication.cBrandedDrug(aPK_obj = pk_brand) 662 self._PRW_preparation.SetText(brand['preparation'], None) 663 664 comps = brand.components 665 if comps is None: 666 return 667 comps = u' / '.join([ u'%s%s' % (c['description'], gmTools.coalesce(c['atc_code'], u'', u' (%s)')) for c in comps ]) 668 self._TCTRL_brand_ingredients.SetValue(comps)
669 #----------------------------------------------------------------
670 - def _on_get_substance_button_pressed(self, event):
671 drug_db = get_drug_database() 672 if drug_db is None: 673 return 674 result = drug_db.import_drugs() 675 if result is None: 676 return 677 new_drugs, new_substances = result 678 if len(new_substances) == 0: 679 return 680 # FIXME: could usefully 681 # FIXME: a) ask which to post-process 682 # FIXME: b) remember the others for post-processing 683 first = new_substances[0] 684 self._PRW_substance.SetText(first['description'], first['pk'])
685 #----------------------------------------------------------------
686 - def _on_get_brand_button_pressed(self, event):
687 drug_db = get_drug_database() 688 if drug_db is None: 689 return 690 result = drug_db.import_drugs() 691 if result is None: 692 return 693 new_drugs, new_substances = result 694 if len(new_drugs) == 0: 695 return 696 # FIXME: could usefully 697 # FIXME: a) ask which to post-process 698 # FIXME: b) remember the others for post-processing 699 first = new_drugs[0] 700 self._PRW_brand.SetText(first['description'], first['pk'])
701 #----------------------------------------------------------------
702 - def _on_chbox_long_term_checked(self, event):
703 if self._CHBOX_long_term.IsChecked() is True: 704 self._PRW_duration.Enable(False) 705 else: 706 self._PRW_duration.Enable(True)
707 #============================================================
708 -def delete_substance_intake(parent=None, substance=None):
709 delete_it = gmGuiHelpers.gm_show_question ( 710 aMessage = _( 711 'Do you really want to remove this substance intake ?\n' 712 '\n' 713 'It may be prudent to edit the details first so as to\n' 714 'leave behind some indication of why it was deleted.\n' 715 ), 716 aTitle = _('Deleting medication / substance intake') 717 ) 718 if not delete_it: 719 return 720 721 gmMedication.delete_substance_intake(substance = substance)
722 #------------------------------------------------------------
723 -def edit_intake_of_substance(parent = None, substance=None):
724 ea = cCurrentMedicationEAPnl(parent = parent, id = -1, substance = substance) 725 dlg = gmEditArea.cGenericEditAreaDlg2(parent = parent, id = -1, edit_area = ea, single_entry = (substance is not None)) 726 dlg.SetTitle(gmTools.coalesce(substance, _('Adding substance intake'), _('Editing substance intake'))) 727 if dlg.ShowModal() == wx.ID_OK: 728 dlg.Destroy() 729 return True 730 dlg.Destroy() 731 return False
732 #============================================================ 733 # current substances grid 734 #------------------------------------------------------------
735 -def configure_medication_list_template(parent=None):
736 737 if parent is None: 738 parent = wx.GetApp().GetTopWindow() 739 740 template = gmFormWidgets.manage_form_templates(parent = parent) 741 option = u'form_templates.medication_list' 742 743 if template is None: 744 gmDispatcher.send(signal = 'statustext', msg = _('No medication list template configured.'), beep = True) 745 return None 746 747 dbcfg = gmCfg.cCfgSQL() 748 dbcfg.set ( 749 workplace = gmSurgery.gmCurrentPractice().active_workplace, 750 option = option, 751 value = u'%s - %s' % (template['name_long'], template['external_version']) 752 ) 753 754 return template
755 #------------------------------------------------------------ 828 #------------------------------------------------------------
829 -class cCurrentSubstancesGrid(wx.grid.Grid):
830 """A grid class for displaying current substance intake. 831 832 - does NOT listen to the currently active patient 833 - thereby it can display any patient at any time 834 """
835 - def __init__(self, *args, **kwargs):
836 837 wx.grid.Grid.__init__(self, *args, **kwargs) 838 839 self.__patient = None 840 self.__row_data = {} 841 self.__row_tooltips = {} 842 self.__prev_row = None 843 self.__prev_tooltip_row = None 844 self.__prev_cell_0 = None 845 self.__grouping_mode = u'episode' 846 self.__filter_show_unapproved = False 847 self.__filter_show_inactive = False 848 849 self.__grouping2col_labels = { 850 u'episode': [ 851 _('Episode'), 852 _('Substance'), 853 _('Dose'), 854 _('Schedule'), 855 _('Started'), 856 _('Duration'), 857 _('Brand') 858 ], 859 u'brand': [ 860 _('Brand'), 861 _('Schedule'), 862 _('Substance'), 863 _('Dose'), 864 _('Started'), 865 _('Duration'), 866 _('Episode') 867 ] 868 } 869 870 self.__grouping2order_by_clauses = { 871 u'episode': u'pk_health_issue nulls first, episode, substance, started', 872 u'brand': u'brand nulls last, substance, started' 873 } 874 875 self.__init_ui() 876 self.__register_events()
877 #------------------------------------------------------------ 878 # external API 879 #------------------------------------------------------------
880 - def get_selected_cells(self):
881 882 sel_block_top_left = self.GetSelectionBlockTopLeft() 883 sel_block_bottom_right = self.GetSelectionBlockBottomRight() 884 sel_cols = self.GetSelectedCols() 885 sel_rows = self.GetSelectedRows() 886 887 selected_cells = [] 888 889 # individually selected cells (ctrl-click) 890 selected_cells += self.GetSelectedCells() 891 892 # selected rows 893 selected_cells += list ( 894 (row, col) 895 for row in sel_rows 896 for col in xrange(self.GetNumberCols()) 897 ) 898 899 # selected columns 900 selected_cells += list ( 901 (row, col) 902 for row in xrange(self.GetNumberRows()) 903 for col in sel_cols 904 ) 905 906 # selection blocks 907 for top_left, bottom_right in zip(self.GetSelectionBlockTopLeft(), self.GetSelectionBlockBottomRight()): 908 selected_cells += [ 909 (row, col) 910 for row in xrange(top_left[0], bottom_right[0] + 1) 911 for col in xrange(top_left[1], bottom_right[1] + 1) 912 ] 913 914 return set(selected_cells)
915 #------------------------------------------------------------
916 - def get_selected_rows(self):
917 rows = {} 918 919 for row, col in self.get_selected_cells(): 920 rows[row] = True 921 922 return rows.keys()
923 #------------------------------------------------------------
924 - def get_selected_data(self):
925 return [ self.__row_data[row] for row in self.get_selected_rows() ]
926 #------------------------------------------------------------
927 - def repopulate_grid(self):
928 929 self.empty_grid() 930 931 if self.__patient is None: 932 return 933 934 emr = self.__patient.get_emr() 935 meds = emr.get_current_substance_intake ( 936 order_by = self.__grouping2order_by_clauses[self.__grouping_mode], 937 include_unapproved = self.__filter_show_unapproved, 938 include_inactive = self.__filter_show_inactive 939 ) 940 if not meds: 941 return 942 943 self.BeginBatch() 944 945 # columns 946 labels = self.__grouping2col_labels[self.__grouping_mode] 947 if self.__filter_show_unapproved: 948 self.AppendCols(numCols = len(labels) + 1) 949 else: 950 self.AppendCols(numCols = len(labels)) 951 for col_idx in range(len(labels)): 952 self.SetColLabelValue(col_idx, labels[col_idx]) 953 if self.__filter_show_unapproved: 954 self.SetColLabelValue(len(labels), u'OK?') 955 self.SetColSize(len(labels), 40) 956 957 self.AppendRows(numRows = len(meds)) 958 959 # loop over data 960 for row_idx in range(len(meds)): 961 med = meds[row_idx] 962 self.__row_data[row_idx] = med 963 964 if med['is_currently_active'] is not True: 965 attr = self.GetOrCreateCellAttr(row_idx, 0) 966 attr.SetTextColour('grey') 967 self.SetRowAttr(row_idx, attr) 968 969 if self.__grouping_mode == u'episode': 970 if med['pk_episode'] is None: 971 self.__prev_cell_0 = None 972 self.SetCellValue(row_idx, 0, gmTools.u_diameter) 973 else: 974 if self.__prev_cell_0 != med['episode']: 975 self.__prev_cell_0 = med['episode'] 976 self.SetCellValue(row_idx, 0, gmTools.coalesce(med['episode'], u'')) 977 978 self.SetCellValue(row_idx, 1, med['substance']) 979 self.SetCellValue(row_idx, 2, gmTools.coalesce(med['strength'], u'')) 980 self.SetCellValue(row_idx, 3, gmTools.coalesce(med['schedule'], u'')) 981 self.SetCellValue(row_idx, 4, med['started'].strftime('%Y-%m-%d')) 982 983 if med['is_long_term']: 984 self.SetCellValue(row_idx, 5, gmTools.u_infinity) 985 else: 986 if med['duration'] is None: 987 self.SetCellValue(row_idx, 5, u'') 988 else: 989 self.SetCellValue(row_idx, 5, gmDateTime.format_interval(med['duration'], gmDateTime.acc_days)) 990 991 if med['pk_brand'] is None: 992 self.SetCellValue(row_idx, 6, gmTools.coalesce(med['brand'], u'')) 993 else: 994 if med['fake_brand']: 995 self.SetCellValue(row_idx, 6, gmTools.coalesce(med['brand'], u'', _('%s (fake)'))) 996 else: 997 self.SetCellValue(row_idx, 6, gmTools.coalesce(med['brand'], u'')) 998 999 elif self.__grouping_mode == u'brand': 1000 1001 if med['pk_brand'] 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['brand']: 1006 self.__prev_cell_0 = med['brand'] 1007 if med['fake_brand']: 1008 self.SetCellValue(row_idx, 0, gmTools.coalesce(med['brand'], u'', _('%s (fake)'))) 1009 else: 1010 self.SetCellValue(row_idx, 0, gmTools.coalesce(med['brand'], u'')) 1011 1012 self.SetCellValue(row_idx, 1, gmTools.coalesce(med['schedule'], u'')) 1013 self.SetCellValue(row_idx, 2, med['substance']) 1014 self.SetCellValue(row_idx, 3, gmTools.coalesce(med['strength'], u'')) 1015 self.SetCellValue(row_idx, 4, med['started'].strftime('%Y-%m-%d')) 1016 1017 if med['is_long_term']: 1018 self.SetCellValue(row_idx, 5, gmTools.u_infinity) 1019 else: 1020 if med['duration'] is None: 1021 self.SetCellValue(row_idx, 5, u'') 1022 else: 1023 self.SetCellValue(row_idx, 5, gmDateTime.format_interval(med['duration'], gmDateTime.acc_days)) 1024 1025 if med['pk_episode'] is None: 1026 self.SetCellValue(row_idx, 6, u'') 1027 else: 1028 self.SetCellValue(row_idx, 6, gmTools.coalesce(med['episode'], u'')) 1029 1030 else: 1031 raise ValueError('unknown grouping mode [%s]' % self.__grouping_mode) 1032 1033 if self.__filter_show_unapproved: 1034 self.SetCellValue ( 1035 row_idx, 1036 len(labels), 1037 gmTools.bool2subst(med['intake_is_approved_of'], gmTools.u_checkmark_thin, u'', u'?') 1038 ) 1039 1040 #self.SetCellAlignment(row, col, horiz = wx.ALIGN_RIGHT, vert = wx.ALIGN_CENTRE) 1041 1042 self.EndBatch()
1043 #------------------------------------------------------------
1044 - def empty_grid(self):
1045 self.BeginBatch() 1046 self.ClearGrid() 1047 # Windows cannot do "nothing", it rather decides to assert() 1048 # on thinking it is supposed to do nothing 1049 if self.GetNumberRows() > 0: 1050 self.DeleteRows(pos = 0, numRows = self.GetNumberRows()) 1051 if self.GetNumberCols() > 0: 1052 self.DeleteCols(pos = 0, numCols = self.GetNumberCols()) 1053 self.EndBatch() 1054 self.__row_data = {} 1055 self.__prev_cell_0 = None
1056 #------------------------------------------------------------
1057 - def show_info_on_entry(self):
1058 1059 if len(self.__row_data) == 0: 1060 return 1061 1062 sel_rows = self.get_selected_rows() 1063 if len(sel_rows) != 1: 1064 return 1065 1066 drug_db = get_drug_database() 1067 if drug_db is None: 1068 return 1069 1070 drug_db.show_info_on_substance(substance = self.get_selected_data()[0])
1071 #------------------------------------------------------------
1072 - def check_interactions(self):
1073 1074 if len(self.__row_data) == 0: 1075 return 1076 1077 drug_db = get_drug_database() 1078 if drug_db is None: 1079 return 1080 1081 if len(self.get_selected_rows()) > 1: 1082 drug_db.check_drug_interactions(substances = self.get_selected_data()) 1083 else: 1084 drug_db.check_drug_interactions(substances = self.__row_data.values())
1085 #------------------------------------------------------------
1086 - def add_substance(self):
1087 edit_intake_of_substance(parent = self, substance = None)
1088 #------------------------------------------------------------
1089 - def edit_substance(self):
1090 1091 rows = self.get_selected_rows() 1092 1093 if len(rows) == 0: 1094 return 1095 1096 if len(rows) > 1: 1097 gmDispatcher.send(signal = 'statustext', msg = _('Cannot edit more than one substance at once.'), beep = True) 1098 return 1099 1100 subst = self.get_selected_data()[0] 1101 edit_intake_of_substance(parent = self, substance = subst)
1102 #------------------------------------------------------------
1103 - def delete_substance(self):
1104 1105 rows = self.get_selected_rows() 1106 1107 if len(rows) == 0: 1108 return 1109 1110 if len(rows) > 1: 1111 gmDispatcher.send(signal = 'statustext', msg = _('Cannot delete more than one substance at once.'), beep = True) 1112 return 1113 1114 subst = self.get_selected_data()[0] 1115 delete_substance_intake(parent = self, substance = subst['pk_substance_intake'])
1116 #------------------------------------------------------------
1117 - def print_medication_list(self):
1118 # there could be some filtering/user interaction going on here 1119 _cfg = gmCfg2.gmCfgData() 1120 print_medication_list(parent = self, cleanup = _cfg.get(option = 'debug'))
1121 #------------------------------------------------------------
1122 - def get_row_tooltip(self, row=None):
1123 1124 entry = self.__row_data[row] 1125 1126 tt = _('Substance intake entry (%s, %s) [#%s] \n') % ( 1127 gmTools.bool2subst(entry['is_currently_active'], _('active'), _('inactive')), 1128 gmTools.bool2subst(entry['intake_is_approved_of'], _('approved'), _('unapproved')), 1129 entry['pk_substance_intake'] 1130 ) 1131 1132 tt += u' ' + _('Substance name: %s [#%s]\n') % (entry['substance'], entry['pk_substance']) 1133 tt += u' ' + _('Preparation: %s\n') % entry['preparation'] 1134 tt += gmTools.coalesce(entry['strength'], u'', _(' Amount per dose: %s\n')) 1135 tt += gmTools.coalesce(entry['atc_substance'], u'', _(' ATC (substance): %s\n')) 1136 1137 tt += u'\n' 1138 1139 tt += gmTools.coalesce ( 1140 entry['brand'], 1141 u'', 1142 _(' Brand name: %%s [#%s]\n') % entry['pk_brand'] 1143 ) 1144 tt += gmTools.coalesce(entry['atc_brand'], u'', _(' ATC (brand): %s\n')) 1145 1146 tt += u'\n' 1147 1148 tt += gmTools.coalesce(entry['schedule'], u'', _(' Regimen: %s\n')) 1149 1150 if entry['is_long_term']: 1151 duration = u' %s %s' % (gmTools.u_right_arrow, gmTools.u_infinity) 1152 else: 1153 if entry['duration'] is None: 1154 duration = u'' 1155 else: 1156 duration = u' %s %s' % (gmTools.u_right_arrow, gmDateTime.format_interval(entry['duration'], gmDateTime.acc_days)) 1157 1158 tt += _(' Started %s%s%s\n') % ( 1159 entry['started'].strftime('%Y %B %d').decode(gmI18N.get_encoding()), 1160 duration, 1161 gmTools.bool2subst(entry['is_long_term'], _(' (long-term)'), _(' (short-term)'), u'') 1162 ) 1163 1164 tt += u'\n' 1165 1166 tt += gmTools.coalesce(entry['aim'], u'', _(' Aim: %s\n')) 1167 tt += gmTools.coalesce(entry['episode'], u'', _(' Episode: %s\n')) 1168 tt += gmTools.coalesce(entry['notes'], u'', _(' Advice: %s\n')) 1169 1170 tt += u'\n' 1171 1172 # tt += _(u'Revisions: %(row_ver)s, last %(mod_when)s by %(mod_by)s.') % ({ 1173 tt += _(u'Revisions: Last modified %(mod_when)s by %(mod_by)s.') % ({ 1174 #'row_ver': entry['row_version'], 1175 'mod_when': entry['modified_when'].strftime('%c').decode(gmI18N.get_encoding()), 1176 'mod_by': entry['modified_by'] 1177 }) 1178 1179 return tt
1180 #------------------------------------------------------------ 1181 # internal helpers 1182 #------------------------------------------------------------
1183 - def __init_ui(self):
1184 self.CreateGrid(0, 1) 1185 self.EnableEditing(0) 1186 self.EnableDragGridSize(1) 1187 self.SetSelectionMode(wx.grid.Grid.wxGridSelectRows) 1188 1189 self.SetColLabelAlignment(wx.ALIGN_LEFT, wx.ALIGN_CENTER) 1190 1191 self.SetRowLabelSize(0) 1192 self.SetRowLabelAlignment(horiz = wx.ALIGN_RIGHT, vert = wx.ALIGN_CENTRE)
1193 #------------------------------------------------------------ 1194 # properties 1195 #------------------------------------------------------------
1196 - def _get_patient(self):
1197 return self.__patient
1198
1199 - def _set_patient(self, patient):
1200 self.__patient = patient 1201 self.repopulate_grid()
1202 1203 patient = property(_get_patient, _set_patient) 1204 #------------------------------------------------------------
1205 - def _get_grouping_mode(self):
1206 return self.__grouping_mode
1207
1208 - def _set_grouping_mode(self, mode):
1209 self.__grouping_mode = mode 1210 self.repopulate_grid()
1211 1212 grouping_mode = property(_get_grouping_mode, _set_grouping_mode) 1213 #------------------------------------------------------------
1215 return self.__filter_show_unapproved
1216
1217 - def _set_filter_show_unapproved(self, val):
1218 self.__filter_show_unapproved = val 1219 self.repopulate_grid()
1220 1221 filter_show_unapproved = property(_get_filter_show_unapproved, _set_filter_show_unapproved) 1222 #------------------------------------------------------------
1223 - def _get_filter_show_inactive(self):
1224 return self.__filter_show_inactive
1225
1226 - def _set_filter_show_inactive(self, val):
1227 self.__filter_show_inactive = val 1228 self.repopulate_grid()
1229 1230 filter_show_inactive = property(_get_filter_show_inactive, _set_filter_show_inactive) 1231 #------------------------------------------------------------ 1232 # event handling 1233 #------------------------------------------------------------
1234 - def __register_events(self):
1235 # dynamic tooltips: GridWindow, GridRowLabelWindow, GridColLabelWindow, GridCornerLabelWindow 1236 self.GetGridWindow().Bind(wx.EVT_MOTION, self.__on_mouse_over_cells) 1237 #self.GetGridRowLabelWindow().Bind(wx.EVT_MOTION, self.__on_mouse_over_row_labels) 1238 #self.GetGridColLabelWindow().Bind(wx.EVT_MOTION, self.__on_mouse_over_col_labels) 1239 1240 # editing cells 1241 self.Bind(wx.grid.EVT_GRID_CELL_LEFT_DCLICK, self.__on_cell_left_dclicked)
1242 #------------------------------------------------------------
1243 - def __on_mouse_over_cells(self, evt):
1244 """Calculate where the mouse is and set the tooltip dynamically.""" 1245 1246 # Use CalcUnscrolledPosition() to get the mouse position within the 1247 # entire grid including what's offscreen 1248 x, y = self.CalcUnscrolledPosition(evt.GetX(), evt.GetY()) 1249 1250 # use this logic to prevent tooltips outside the actual cells 1251 # apply to GetRowSize, too 1252 # tot = 0 1253 # for col in xrange(self.NumberCols): 1254 # tot += self.GetColSize(col) 1255 # if xpos <= tot: 1256 # self.tool_tip.Tip = 'Tool tip for Column %s' % ( 1257 # self.GetColLabelValue(col)) 1258 # break 1259 # else: # mouse is in label area beyond the right-most column 1260 # self.tool_tip.Tip = '' 1261 1262 row, col = self.XYToCell(x, y) 1263 1264 if row == self.__prev_tooltip_row: 1265 return 1266 1267 self.__prev_tooltip_row = row 1268 1269 try: 1270 evt.GetEventObject().SetToolTipString(self.get_row_tooltip(row = row)) 1271 except KeyError: 1272 pass
1273 #------------------------------------------------------------
1274 - def __on_cell_left_dclicked(self, evt):
1275 row = evt.GetRow() 1276 data = self.__row_data[row] 1277 edit_intake_of_substance(parent = self, substance = data)
1278 #============================================================ 1279 from Gnumed.wxGladeWidgets import wxgCurrentSubstancesPnl 1280
1281 -class cCurrentSubstancesPnl(wxgCurrentSubstancesPnl.wxgCurrentSubstancesPnl, gmRegetMixin.cRegetOnPaintMixin):
1282 1283 """Panel holding a grid with current substances. Used as notebook page.""" 1284
1285 - def __init__(self, *args, **kwargs):
1286 1287 wxgCurrentSubstancesPnl.wxgCurrentSubstancesPnl.__init__(self, *args, **kwargs) 1288 gmRegetMixin.cRegetOnPaintMixin.__init__(self) 1289 1290 self.__register_interests()
1291 #----------------------------------------------------- 1292 # reget-on-paint mixin API 1293 #-----------------------------------------------------
1294 - def _populate_with_data(self):
1295 """Populate cells with data from model.""" 1296 pat = gmPerson.gmCurrentPatient() 1297 if pat.connected: 1298 self._grid_substances.patient = pat 1299 else: 1300 self._grid_substances.patient = None 1301 return True
1302 #-------------------------------------------------------- 1303 # event handling 1304 #--------------------------------------------------------
1305 - def __register_interests(self):
1306 gmDispatcher.connect(signal = u'pre_patient_selection', receiver = self._on_pre_patient_selection) 1307 gmDispatcher.connect(signal = u'post_patient_selection', receiver = self._schedule_data_reget) 1308 gmDispatcher.connect(signal = u'substance_intake_mod_db', receiver = self._schedule_data_reget)
1309 # active_substance_mod_db 1310 # substance_brand_mod_db 1311 #--------------------------------------------------------
1312 - def _on_pre_patient_selection(self):
1313 wx.CallAfter(self.__on_pre_patient_selection)
1314 #--------------------------------------------------------
1315 - def __on_pre_patient_selection(self):
1316 self._grid_substances.patient = None
1317 #--------------------------------------------------------
1318 - def _on_add_button_pressed(self, event):
1319 self._grid_substances.add_substance()
1320 #--------------------------------------------------------
1321 - def _on_edit_button_pressed(self, event):
1322 self._grid_substances.edit_substance()
1323 #--------------------------------------------------------
1324 - def _on_delete_button_pressed(self, event):
1325 self._grid_substances.delete_substance()
1326 #--------------------------------------------------------
1327 - def _on_info_button_pressed(self, event):
1328 self._grid_substances.show_info_on_entry()
1329 #--------------------------------------------------------
1330 - def _on_interactions_button_pressed(self, event):
1331 self._grid_substances.check_interactions()
1332 #--------------------------------------------------------
1333 - def _on_episode_grouping_selected(self, event):
1334 self._grid_substances.grouping_mode = 'episode'
1335 #--------------------------------------------------------
1336 - def _on_brand_grouping_selected(self, event):
1337 self._grid_substances.grouping_mode = 'brand'
1338 #--------------------------------------------------------
1339 - def _on_show_unapproved_checked(self, event):
1340 self._grid_substances.filter_show_unapproved = self._CHBOX_show_unapproved.GetValue()
1341 #--------------------------------------------------------
1342 - def _on_show_inactive_checked(self, event):
1343 self._grid_substances.filter_show_inactive = self._CHBOX_show_inactive.GetValue()
1344 #--------------------------------------------------------
1345 - def _on_print_button_pressed(self, event):
1346 self._grid_substances.print_medication_list()
1347 #============================================================ 1348 # main 1349 #------------------------------------------------------------ 1350 if __name__ == '__main__': 1351 1352 from Gnumed.pycommon import gmI18N 1353 1354 gmI18N.activate_locale() 1355 gmI18N.install_domain(domain = 'gnumed') 1356 1357 #---------------------------------------- 1358 #---------------------------------------- 1359 if (len(sys.argv) > 1) and (sys.argv[1] == 'test'): 1360 # test_*() 1361 pass 1362 1363 #============================================================ 1364 # $Log: gmMedicationWidgets.py,v $ 1365 # Revision 1.32 2010/01/13 21:52:04 ncq 1366 # - implement phrase wheel on schedule and preparation 1367 # 1368 # Revision 1.31 2010/01/09 20:15:06 ncq 1369 # - use Advice 1370 # 1371 # Revision 1.30 2010/01/08 12:21:04 ncq 1372 # - even better error detection on forms template loading 1373 # 1374 # Revision 1.29 2010/01/06 14:42:20 ncq 1375 # - medication list printing: 1376 # - tie cleanup to --debug 1377 # - better error detection 1378 # 1379 # Revision 1.28 2010/01/01 21:48:15 ncq 1380 # - remove confusing status message 1381 # 1382 # Revision 1.27 2009/12/26 19:08:38 ncq 1383 # - document printing of medication list in EMR 1384 # 1385 # Revision 1.26 2009/12/25 22:07:17 ncq 1386 # - cleanup 1387 # - configure-medication-list-template 1388 # - print-medication-list 1389 # - show-info-on-entry 1390 # - tooltips on substance entry rows 1391 # 1392 # Revision 1.25 2009/12/22 12:02:57 ncq 1393 # - cleanup 1394 # 1395 # Revision 1.24 2009/12/03 17:51:11 ncq 1396 # - explicit ATC col in brand component list 1397 # 1398 # Revision 1.23 2009/12/02 16:50:44 ncq 1399 # - enable brand component deletion 1400 # - normalize substance name before adding as component 1401 # 1402 # Revision 1.22 2009/12/01 21:55:24 ncq 1403 # - branded drug phrasewheel 1404 # - much improved substance intake EA implementation 1405 # 1406 # Revision 1.21 2009/11/30 13:15:20 ncq 1407 # - better meds grid column ordering as per list 1408 # 1409 # Revision 1.20 2009/11/29 20:01:46 ncq 1410 # - substance phrasewheel 1411 # 1412 # Revision 1.19 2009/11/29 16:05:41 ncq 1413 # - must set self.data *late* in _save-as-new or else ! 1414 # - properly enable/disable duration PRW 1415 # - grid business logic moved into grid so no need to access self._grid_substances anymore 1416 # 1417 # Revision 1.18 2009/11/28 18:31:30 ncq 1418 # - implement drug brand management 1419 # - implement drug brand component management 1420 # 1421 # Revision 1.17 2009/11/24 20:59:59 ncq 1422 # - use import-drugs rather than import-drugs-as-substances 1423 # - improved grid layout as per list 1424 # - fix get-selected-data 1425 # - make grid wrapper do less 1426 # 1427 # Revision 1.16 2009/11/19 14:44:25 ncq 1428 # - improved plugin 1429 # 1430 # Revision 1.15 2009/11/15 01:09:07 ncq 1431 # - implement grouping/filtering 1432 # - mark unapproved vs approved if showing all substances 1433 # 1434 # Revision 1.14 2009/11/08 20:49:20 ncq 1435 # - implement deletion 1436 # - start grouping/filtering/ row tooltips 1437 # 1438 # Revision 1.13 2009/11/06 15:19:25 ncq 1439 # - implement saving as new substance intake 1440 # 1441 # Revision 1.12 2009/10/29 17:23:24 ncq 1442 # - consolidate get-drug-database 1443 # - much improved substance intake EA 1444 # - better naming and adjust to such 1445 # 1446 # Revision 1.11 2009/10/28 21:48:55 ncq 1447 # - further improved substances grid 1448 # 1449 # Revision 1.10 2009/10/28 16:43:42 ncq 1450 # - start implementing substances edit area 1451 # - enhance grid to allow actual substances management 1452 # 1453 # Revision 1.9 2009/10/26 22:30:58 ncq 1454 # - implement deletion of INN 1455 # 1456 # Revision 1.8 2009/10/21 20:41:53 ncq 1457 # - access MMI from substance management via NEW button 1458 # 1459 # Revision 1.7 2009/10/21 09:21:13 ncq 1460 # - manage substances 1461 # - jump to drug database 1462 # 1463 # Revision 1.6 2009/10/20 10:27:35 ncq 1464 # - implement configuration of drug data source 1465 # 1466 # Revision 1.5 2009/09/01 22:36:08 ncq 1467 # - add jump-to-mmi 1468 # 1469 # Revision 1.4 2009/06/20 12:46:04 ncq 1470 # - move IFAP handling here 1471 # 1472 # Revision 1.3 2009/06/10 21:02:34 ncq 1473 # - update-atc-reference-data 1474 # 1475 # Revision 1.2 2009/05/13 12:20:59 ncq 1476 # - improve and streamline 1477 # 1478 # Revision 1.1 2009/05/12 12:04:01 ncq 1479 # - substance intake handling 1480 # 1481 # 1482