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.33 2010/02/06 21:39:10 ncq Exp $ 
   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  #============================================================ 
27 -def browse_atc_reference(parent=None):
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 #============================================================
58 -def manage_substances_in_brands(parent=None):
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 #new_callback = new, 93 #edit_callback = edit, 94 delete_callback = delete, 95 refresh_callback = refresh 96 ) 97 #============================================================
98 -def manage_branded_drugs(parent=None):
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 #edit_callback = edit, 140 delete_callback = delete 141 ) 142 #============================================================
143 -def manage_substances_in_use(parent=None):
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 #edit_callback = edit, 183 delete_callback = delete 184 ) 185 #============================================================ 186 # generic drug database access 187 #============================================================
188 -def configure_drug_data_source(parent=None):
189 gmCfgWidgets.configure_string_from_list_option ( 190 parent = parent, 191 message = _( 192 '\n' 193 'Please select the default drug data source from the list below.\n' 194 '\n' 195 'Note that to actually use it you need to have the database installed, too.' 196 ), 197 option = 'external.drug_data.default_source', 198 bias = 'user', 199 default_value = None, 200 choices = gmMedication.drug_data_source_interfaces.keys(), 201 columns = [_('Drug data source')], 202 data = gmMedication.drug_data_source_interfaces.keys(), 203 caption = _('Configuring default drug data source') 204 )
205 #============================================================
206 -def get_drug_database(parent = None):
207 dbcfg = gmCfg.cCfgSQL() 208 209 default_db = dbcfg.get2 ( 210 option = 'external.drug_data.default_source', 211 workplace = gmSurgery.gmCurrentPractice().active_workplace, 212 bias = 'workplace' 213 ) 214 215 if default_db is None: 216 gmDispatcher.send('statustext', msg = _('No default drug database configured.'), beep = True) 217 configure_drug_data_source(parent = parent) 218 default_db = dbcfg.get2 ( 219 option = 'external.drug_data.default_source', 220 workplace = gmSurgery.gmCurrentPractice().active_workplace, 221 bias = 'workplace' 222 ) 223 if default_db is None: 224 gmGuiHelpers.gm_show_error ( 225 aMessage = _('There is no default drug database configured.'), 226 aTitle = _('Jumping to drug database') 227 ) 228 return None 229 230 try: 231 return gmMedication.drug_data_source_interfaces[default_db]() 232 except KeyError: 233 _log.error('faulty default drug data source configuration: %s', default_db) 234 return None
235 #============================================================
236 -def jump_to_drug_database():
237 dbcfg = gmCfg.cCfgSQL() 238 drug_db = get_drug_database() 239 if drug_db is None: 240 return 241 drug_db.switch_to_frontend(blocking = False)
242 #============================================================
243 -def jump_to_ifap(import_drugs=False):
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 # file must exist for Ifap to write into it 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 # COMMENT: this file must exist PRIOR to invoking IFAP 280 # COMMENT: or else IFAP will not write data into it ... 281 try: 282 csv_file = open(transfer_file, 'rb') # FIXME: encoding 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 # dummy episode for now 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 #============================================================
314 -def update_atc_reference_data():
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 # current medication widgets 348 #============================================================
349 -class cSubstanceSchedulePhraseWheel(gmPhraseWheel.cPhraseWheel):
350
351 - def __init__(self, *args, **kwargs):
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 #============================================================
367 -class cSubstancePreparationPhraseWheel(gmPhraseWheel.cPhraseWheel):
368
369 - def __init__(self, *args, **kwargs):
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 #============================================================
391 -class cSubstancePhraseWheel(gmPhraseWheel.cPhraseWheel):
392
393 - def __init__(self, *args, **kwargs):
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 #============================================================
415 -class cBrandedDrugPhraseWheel(gmPhraseWheel.cPhraseWheel):
416
417 - def __init__(self, *args, **kwargs):
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
438 - def __init__(self, *args, **kwargs):
439 440 try: 441 data = kwargs['substance'] 442 del kwargs['substance'] 443 except KeyError: 444 data = None 445 446 wxgCurrentMedicationEAPnl.wxgCurrentMedicationEAPnl.__init__(self, *args, **kwargs) 447 gmEditArea.cGenericEditAreaMixin.__init__(self) 448 self.mode = 'new' 449 self.data = data 450 if data is not None: 451 self.mode = 'edit' 452 453 self.__init_ui()
454 #----------------------------------------------------------------
455 - def __init_ui(self):
456 457 # adjust phrasewheels 458 459 self._PRW_brand.add_callback_on_lose_focus(callback = self._on_leave_brand)
460 461 #---------------------------------------------------------------- 462 # generic Edit Area mixin API 463 #----------------------------------------------------------------
464 - def _valid_for_save(self):
465 466 validity = True 467 468 if self._PRW_substance.GetValue().strip() == u'': 469 self._PRW_substance.display_as_valid(False) 470 validity = False 471 else: 472 self._PRW_substance.display_as_valid(True) 473 474 if self._PRW_preparation.GetValue().strip() == u'': 475 self._PRW_preparation.display_as_valid(False) 476 validity = False 477 else: 478 self._PRW_preparation.display_as_valid(True) 479 480 if self._CHBOX_approved.IsChecked(): 481 if self._PRW_episode.GetValue().strip() == u'': 482 self._PRW_episode.display_as_valid(False) 483 validity = False 484 else: 485 self._PRW_episode.display_as_valid(True) 486 487 if self._CHBOX_approved.IsChecked() is True: 488 self._PRW_duration.display_as_valid(True) 489 else: 490 if self._PRW_duration.GetValue().strip() in [u'', gmTools.u_infinity]: 491 self._PRW_duration.display_as_valid(True) 492 else: 493 if gmDateTime.str2interval(self._PRW_duration.GetValue()) is None: 494 self._PRW_duration.display_as_valid(False) 495 validity = False 496 else: 497 self._PRW_duration.display_as_valid(True) 498 499 if validity is False: 500 gmDispatcher.send(signal = 'statustext', msg = _('Cannot save substance intake. Invalid or missing essential input.')) 501 502 return validity
503 #----------------------------------------------------------------
504 - def _save_as_new(self):
505 506 emr = gmPerson.gmCurrentPatient().get_emr() 507 508 # 1) create substance intake entry 509 if self._PRW_substance.GetData() is None: 510 subst = self._PRW_substance.GetValue().strip() 511 else: 512 # normalize, do not simply re-use name from phrasewheel 513 subst = gmMedication.get_substance_by_pk(pk = self._PRW_substance.GetData())['description'] 514 515 intake = emr.add_substance_intake ( 516 substance = subst, 517 episode = self._PRW_episode.GetData(can_create = True), 518 preparation = self._PRW_preparation.GetValue() 519 ) 520 521 intake['strength'] = self._PRW_strength.GetValue() 522 intake['started'] = gmDateTime.wxDate2py_dt(wxDate = self._DP_started.GetValue()) 523 intake['schedule'] = self._PRW_schedule.GetValue() 524 intake['aim'] = self._PRW_aim.GetValue() 525 intake['notes'] = self._PRW_notes.GetValue() 526 intake['is_long_term'] = self._CHBOX_long_term.IsChecked() 527 intake['intake_is_approved_of'] = self._CHBOX_approved.IsChecked() 528 529 if self._PRW_duration.GetValue().strip() in [u'', gmTools.u_infinity]: 530 intake['duration'] = None 531 else: 532 intake['duration'] = gmDateTime.str2interval(self._PRW_duration.GetValue()) 533 534 # 2) create or retrieve brand 535 brand = None 536 pk_brand = self._PRW_brand.GetData() 537 538 # brand pre-selected ? 539 if pk_brand is None: 540 # no, so ... 541 desc = self._PRW_brand.GetValue().strip() 542 if desc != u'': 543 # ... create or get it 544 brand = gmMedication.create_branded_drug ( 545 brand_name = desc, 546 preparation = self._PRW_preparation.GetValue().strip(), 547 return_existing = True 548 ) 549 pk_brand = brand['pk'] 550 else: 551 # yes, so get it 552 brand = gmMedication.cBrandedDrug(aPK_obj = pk_brand) 553 554 # 3) link brand, if available 555 intake['pk_brand'] = pk_brand 556 intake.save() 557 558 # brand neither creatable nor pre-selected 559 if brand is None: 560 self.data = intake 561 return True 562 563 # 4) add substance to brand as component (because 564 # that's effectively what we are saying here) 565 # FIXME: we may want to ask the user here 566 # FIXME: or only do it if there are no components yet 567 if self._PRW_substance.GetData() is None: 568 brand.add_component(substance = self._PRW_substance.GetValue().strip()) 569 else: 570 # normalize substance name 571 subst = gmMedication.get_substance_by_pk(pk = self._PRW_substance.GetData()) 572 if subst is not None: 573 brand.add_component(substance = subst['description']) 574 575 self.data = intake 576 return True
577 #----------------------------------------------------------------
578 - def _save_as_update(self):
579 580 if self._PRW_substance.GetData() is None: 581 self.data['pk_substance'] = gmMedication.create_used_substance ( 582 substance = self._PRW_substance.GetValue().strip() 583 )['pk'] 584 else: 585 self.data['pk_substance'] = self._PRW_substance.GetData() 586 587 self.data['started'] = gmDateTime.wxDate2py_dt(wxDate = self._DP_started.GetValue()) 588 self.data['preparation'] = self._PRW_preparation.GetValue() 589 self.data['strength'] = self._PRW_strength.GetValue() 590 self.data['schedule'] = self._PRW_schedule.GetValue() 591 self.data['aim'] = self._PRW_aim.GetValue() 592 self.data['notes'] = self._PRW_notes.GetValue() 593 self.data['is_long_term'] = self._CHBOX_long_term.IsChecked() 594 self.data['intake_is_approved_of'] = self._CHBOX_approved.IsChecked() 595 self.data['pk_episode'] = self._PRW_episode.GetData(can_create = True) 596 597 if self._PRW_duration.GetValue().strip() in [u'', gmTools.u_infinity]: 598 self.data['duration'] = None 599 else: 600 self.data['duration'] = gmDateTime.str2interval(self._PRW_duration.GetValue()) 601 602 if self._PRW_brand.GetData() is None: 603 desc = self._PRW_brand.GetValue().strip() 604 if desc != u'': 605 # create or get brand 606 self.data['pk_brand'] = gmMedication.create_branded_drug ( 607 brand_name = desc, 608 preparation = self._PRW_preparation.GetValue().strip(), 609 return_existing = True 610 )['pk'] 611 else: 612 self.data['pk_brand'] = self._PRW_brand.GetData() 613 614 self.data.save() 615 return True
616 #----------------------------------------------------------------
617 - def _refresh_as_new(self):
618 self._PRW_substance.SetText(u'', None) 619 self._PRW_strength.SetText(u'', None) 620 self._PRW_preparation.SetText(u'', None) 621 self._PRW_schedule.SetText(u'', None) 622 self._PRW_duration.SetText(u'', None) 623 self._PRW_aim.SetText(u'', None) 624 self._PRW_notes.SetText(u'', None) 625 self._PRW_episode.SetData(None) 626 627 self._CHBOX_long_term.SetValue(False) 628 self._CHBOX_approved.SetValue(True) 629 630 self._DP_started.SetValue(dt = gmDateTime.py_dt2wxDate(py_dt = gmDateTime.pydt_now_here(), wx = wx)) 631 632 self._PRW_brand.SetText(u'', None) 633 self._TCTRL_brand_ingredients.SetValue(u'') 634 635 self._PRW_substance.SetFocus()
636 #----------------------------------------------------------------
637 - def _refresh_from_existing(self):
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 # event handlers 684 #----------------------------------------------------------------
685 - def _on_leave_brand(self):
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 #----------------------------------------------------------------
701 - def _on_get_substance_button_pressed(self, event):
702 drug_db = get_drug_database() 703 if drug_db is None: 704 return 705 result = drug_db.import_drugs() 706 if result is None: 707 return 708 new_drugs, new_substances = result 709 if len(new_substances) == 0: 710 return 711 # FIXME: could usefully 712 # FIXME: a) ask which to post-process 713 # FIXME: b) remember the others for post-processing 714 first = new_substances[0] 715 self._PRW_substance.SetText(first['description'], first['pk'])
716 #----------------------------------------------------------------
717 - def _on_get_brand_button_pressed(self, event):
718 drug_db = get_drug_database() 719 if drug_db is None: 720 return 721 result = drug_db.import_drugs() 722 if result is None: 723 return 724 new_drugs, new_substances = result 725 if len(new_drugs) == 0: 726 return 727 # FIXME: could usefully 728 # FIXME: a) ask which to post-process 729 # FIXME: b) remember the others for post-processing 730 first = new_drugs[0] 731 self._PRW_brand.SetText(first['description'], first['pk'])
732 #----------------------------------------------------------------
733 - def _on_chbox_long_term_checked(self, event):
734 if self._CHBOX_long_term.IsChecked() is True: 735 self._PRW_duration.Enable(False) 736 else: 737 self._PRW_duration.Enable(True)
738 #============================================================
739 -def delete_substance_intake(parent=None, substance=None):
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 #------------------------------------------------------------
754 -def edit_intake_of_substance(parent = None, substance=None):
755 ea = cCurrentMedicationEAPnl(parent = parent, id = -1, substance = substance) 756 dlg = gmEditArea.cGenericEditAreaDlg2(parent = parent, id = -1, edit_area = ea, single_entry = (substance is not None)) 757 dlg.SetTitle(gmTools.coalesce(substance, _('Adding substance intake'), _('Editing substance intake'))) 758 if dlg.ShowModal() == wx.ID_OK: 759 dlg.Destroy() 760 return True 761 dlg.Destroy() 762 return False
763 #============================================================ 764 # current substances grid 765 #------------------------------------------------------------
766 -def configure_medication_list_template(parent=None):
767 768 if parent is None: 769 parent = wx.GetApp().GetTopWindow() 770 771 template = gmFormWidgets.manage_form_templates(parent = parent) 772 option = u'form_templates.medication_list' 773 774 if template is None: 775 gmDispatcher.send(signal = 'statustext', msg = _('No medication list template configured.'), beep = True) 776 return None 777 778 dbcfg = gmCfg.cCfgSQL() 779 dbcfg.set ( 780 workplace = gmSurgery.gmCurrentPractice().active_workplace, 781 option = option, 782 value = u'%s - %s' % (template['name_long'], template['external_version']) 783 ) 784 785 return template
786 #------------------------------------------------------------ 859 #------------------------------------------------------------
860 -class cCurrentSubstancesGrid(wx.grid.Grid):
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 """
866 - def __init__(self, *args, **kwargs):
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 # external API 910 #------------------------------------------------------------
911 - def get_selected_cells(self):
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 # individually selected cells (ctrl-click) 921 selected_cells += self.GetSelectedCells() 922 923 # selected rows 924 selected_cells += list ( 925 (row, col) 926 for row in sel_rows 927 for col in xrange(self.GetNumberCols()) 928 ) 929 930 # selected columns 931 selected_cells += list ( 932 (row, col) 933 for row in xrange(self.GetNumberRows()) 934 for col in sel_cols 935 ) 936 937 # selection blocks 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 #------------------------------------------------------------
947 - def get_selected_rows(self):
948 rows = {} 949 950 for row, col in self.get_selected_cells(): 951 rows[row] = True 952 953 return rows.keys()
954 #------------------------------------------------------------
955 - def get_selected_data(self):
956 return [ self.__row_data[row] for row in self.get_selected_rows() ]
957 #------------------------------------------------------------
958 - def repopulate_grid(self):
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 # columns 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 # loop over data 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 #self.SetCellAlignment(row, col, horiz = wx.ALIGN_RIGHT, vert = wx.ALIGN_CENTRE) 1072 1073 self.EndBatch()
1074 #------------------------------------------------------------
1075 - def empty_grid(self):
1076 self.BeginBatch() 1077 self.ClearGrid() 1078 # Windows cannot do "nothing", it rather decides to assert() 1079 # on thinking it is supposed to do nothing 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 #------------------------------------------------------------
1088 - def show_info_on_entry(self):
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 #------------------------------------------------------------
1103 - def check_interactions(self):
1104 1105 if len(self.__row_data) == 0: 1106 return 1107 1108 drug_db = get_drug_database() 1109 if drug_db is None: 1110 return 1111 1112 if len(self.get_selected_rows()) > 1: 1113 drug_db.check_drug_interactions(substances = self.get_selected_data()) 1114 else: 1115 drug_db.check_drug_interactions(substances = self.__row_data.values())
1116 #------------------------------------------------------------
1117 - def add_substance(self):
1118 edit_intake_of_substance(parent = self, substance = None)
1119 #------------------------------------------------------------
1120 - def edit_substance(self):
1121 1122 rows = self.get_selected_rows() 1123 1124 if len(rows) == 0: 1125 return 1126 1127 if len(rows) > 1: 1128 gmDispatcher.send(signal = 'statustext', msg = _('Cannot edit more than one substance at once.'), beep = True) 1129 return 1130 1131 subst = self.get_selected_data()[0] 1132 edit_intake_of_substance(parent = self, substance = subst)
1133 #------------------------------------------------------------
1134 - def delete_substance(self):
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 #------------------------------------------------------------
1148 - def print_medication_list(self):
1149 # there could be some filtering/user interaction going on here 1150 _cfg = gmCfg2.gmCfgData() 1151 print_medication_list(parent = self, cleanup = _cfg.get(option = 'debug'))
1152 #------------------------------------------------------------
1153 - def get_row_tooltip(self, row=None):
1154 1155 entry = self.__row_data[row] 1156 1157 tt = _('Substance intake entry (%s, %s) [#%s] \n') % ( 1158 gmTools.bool2subst(entry['is_currently_active'], _('active'), _('inactive')), 1159 gmTools.bool2subst(entry['intake_is_approved_of'], _('approved'), _('unapproved')), 1160 entry['pk_substance_intake'] 1161 ) 1162 1163 tt += u' ' + _('Substance name: %s [#%s]\n') % (entry['substance'], entry['pk_substance']) 1164 tt += u' ' + _('Preparation: %s\n') % entry['preparation'] 1165 if entry['strength'] is not None: 1166 tt += u' ' + _('Amount per dose: %s') % entry['strength'] 1167 if entry.ddd is not None: 1168 tt += u' (DDD: %s %s)' % (entry.ddd['ddd'], entry.ddd['unit']) 1169 tt += u'\n' 1170 else: 1171 if entry.ddd is not None: 1172 tt += u' DDD: %s %s' % (entry.ddd['ddd'], entry.ddd['unit']) 1173 tt += u'\n' 1174 tt += gmTools.coalesce(entry['atc_substance'], u'', _(' ATC (substance): %s\n')) 1175 1176 tt += u'\n' 1177 1178 tt += gmTools.coalesce ( 1179 entry['brand'], 1180 u'', 1181 _(' Brand name: %%s [#%s]\n') % entry['pk_brand'] 1182 ) 1183 tt += gmTools.coalesce(entry['atc_brand'], u'', _(' ATC (brand): %s\n')) 1184 1185 tt += u'\n' 1186 1187 tt += gmTools.coalesce(entry['schedule'], u'', _(' Regimen: %s\n')) 1188 1189 if entry['is_long_term']: 1190 duration = u' %s %s' % (gmTools.u_right_arrow, gmTools.u_infinity) 1191 else: 1192 if entry['duration'] is None: 1193 duration = u'' 1194 else: 1195 duration = u' %s %s' % (gmTools.u_right_arrow, gmDateTime.format_interval(entry['duration'], gmDateTime.acc_days)) 1196 1197 tt += _(' Started %s%s%s\n') % ( 1198 entry['started'].strftime('%Y %B %d').decode(gmI18N.get_encoding()), 1199 duration, 1200 gmTools.bool2subst(entry['is_long_term'], _(' (long-term)'), _(' (short-term)'), u'') 1201 ) 1202 1203 tt += u'\n' 1204 1205 tt += gmTools.coalesce(entry['aim'], u'', _(' Aim: %s\n')) 1206 tt += gmTools.coalesce(entry['episode'], u'', _(' Episode: %s\n')) 1207 tt += gmTools.coalesce(entry['notes'], u'', _(' Advice: %s\n')) 1208 1209 tt += u'\n' 1210 1211 # tt += _(u'Revisions: %(row_ver)s, last %(mod_when)s by %(mod_by)s.') % ({ 1212 tt += _(u'Revisions: Last modified %(mod_when)s by %(mod_by)s.') % ({ 1213 #'row_ver': entry['row_version'], 1214 'mod_when': entry['modified_when'].strftime('%c').decode(gmI18N.get_encoding()), 1215 'mod_by': entry['modified_by'] 1216 }) 1217 1218 return tt
1219 #------------------------------------------------------------ 1220 # internal helpers 1221 #------------------------------------------------------------
1222 - def __init_ui(self):
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 # properties 1234 #------------------------------------------------------------
1235 - def _get_patient(self):
1236 return self.__patient
1237
1238 - def _set_patient(self, patient):
1239 self.__patient = patient 1240 self.repopulate_grid()
1241 1242 patient = property(_get_patient, _set_patient) 1243 #------------------------------------------------------------
1244 - def _get_grouping_mode(self):
1245 return self.__grouping_mode
1246
1247 - def _set_grouping_mode(self, mode):
1248 self.__grouping_mode = mode 1249 self.repopulate_grid()
1250 1251 grouping_mode = property(_get_grouping_mode, _set_grouping_mode) 1252 #------------------------------------------------------------
1254 return self.__filter_show_unapproved
1255
1256 - def _set_filter_show_unapproved(self, val):
1257 self.__filter_show_unapproved = val 1258 self.repopulate_grid()
1259 1260 filter_show_unapproved = property(_get_filter_show_unapproved, _set_filter_show_unapproved) 1261 #------------------------------------------------------------
1262 - def _get_filter_show_inactive(self):
1263 return self.__filter_show_inactive
1264
1265 - def _set_filter_show_inactive(self, val):
1266 self.__filter_show_inactive = val 1267 self.repopulate_grid()
1268 1269 filter_show_inactive = property(_get_filter_show_inactive, _set_filter_show_inactive) 1270 #------------------------------------------------------------ 1271 # event handling 1272 #------------------------------------------------------------
1273 - def __register_events(self):
1274 # dynamic tooltips: GridWindow, GridRowLabelWindow, GridColLabelWindow, GridCornerLabelWindow 1275 self.GetGridWindow().Bind(wx.EVT_MOTION, self.__on_mouse_over_cells) 1276 #self.GetGridRowLabelWindow().Bind(wx.EVT_MOTION, self.__on_mouse_over_row_labels) 1277 #self.GetGridColLabelWindow().Bind(wx.EVT_MOTION, self.__on_mouse_over_col_labels) 1278 1279 # editing cells 1280 self.Bind(wx.grid.EVT_GRID_CELL_LEFT_DCLICK, self.__on_cell_left_dclicked)
1281 #------------------------------------------------------------
1282 - def __on_mouse_over_cells(self, evt):
1283 """Calculate where the mouse is and set the tooltip dynamically.""" 1284 1285 # Use CalcUnscrolledPosition() to get the mouse position within the 1286 # entire grid including what's offscreen 1287 x, y = self.CalcUnscrolledPosition(evt.GetX(), evt.GetY()) 1288 1289 # use this logic to prevent tooltips outside the actual cells 1290 # apply to GetRowSize, too 1291 # tot = 0 1292 # for col in xrange(self.NumberCols): 1293 # tot += self.GetColSize(col) 1294 # if xpos <= tot: 1295 # self.tool_tip.Tip = 'Tool tip for Column %s' % ( 1296 # self.GetColLabelValue(col)) 1297 # break 1298 # else: # mouse is in label area beyond the right-most column 1299 # self.tool_tip.Tip = '' 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 #------------------------------------------------------------
1313 - def __on_cell_left_dclicked(self, evt):
1314 row = evt.GetRow() 1315 data = self.__row_data[row] 1316 edit_intake_of_substance(parent = self, substance = data)
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
1324 - def __init__(self, *args, **kwargs):
1325 1326 wxgCurrentSubstancesPnl.wxgCurrentSubstancesPnl.__init__(self, *args, **kwargs) 1327 gmRegetMixin.cRegetOnPaintMixin.__init__(self) 1328 1329 self.__register_interests()
1330 #----------------------------------------------------- 1331 # reget-on-paint mixin API 1332 #-----------------------------------------------------
1333 - def _populate_with_data(self):
1334 """Populate cells with data from model.""" 1335 pat = gmPerson.gmCurrentPatient() 1336 if pat.connected: 1337 self._grid_substances.patient = pat 1338 else: 1339 self._grid_substances.patient = None 1340 return True
1341 #-------------------------------------------------------- 1342 # event handling 1343 #--------------------------------------------------------
1344 - def __register_interests(self):
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 # active_substance_mod_db 1349 # substance_brand_mod_db 1350 #--------------------------------------------------------
1351 - def _on_pre_patient_selection(self):
1352 wx.CallAfter(self.__on_pre_patient_selection)
1353 #--------------------------------------------------------
1354 - def __on_pre_patient_selection(self):
1355 self._grid_substances.patient = None
1356 #--------------------------------------------------------
1357 - def _on_add_button_pressed(self, event):
1358 self._grid_substances.add_substance()
1359 #--------------------------------------------------------
1360 - def _on_edit_button_pressed(self, event):
1361 self._grid_substances.edit_substance()
1362 #--------------------------------------------------------
1363 - def _on_delete_button_pressed(self, event):
1364 self._grid_substances.delete_substance()
1365 #--------------------------------------------------------
1366 - def _on_info_button_pressed(self, event):
1367 self._grid_substances.show_info_on_entry()
1368 #--------------------------------------------------------
1369 - def _on_interactions_button_pressed(self, event):
1370 self._grid_substances.check_interactions()
1371 #--------------------------------------------------------
1372 - def _on_episode_grouping_selected(self, event):
1373 self._grid_substances.grouping_mode = 'episode'
1374 #--------------------------------------------------------
1375 - def _on_brand_grouping_selected(self, event):
1376 self._grid_substances.grouping_mode = 'brand'
1377 #--------------------------------------------------------
1378 - def _on_show_unapproved_checked(self, event):
1379 self._grid_substances.filter_show_unapproved = self._CHBOX_show_unapproved.GetValue()
1380 #--------------------------------------------------------
1381 - def _on_show_inactive_checked(self, event):
1382 self._grid_substances.filter_show_inactive = self._CHBOX_show_inactive.GetValue()
1383 #--------------------------------------------------------
1384 - def _on_print_button_pressed(self, event):
1385 self._grid_substances.print_medication_list()
1386 #============================================================ 1387 # main 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 # test_*() 1400 pass 1401 1402 #============================================================ 1403 # $Log: gmMedicationWidgets.py,v $ 1404 # Revision 1.33 2010/02/06 21:39:10 ncq 1405 # - browse-atc-reference 1406 # - include DDD in substance intake tooltip 1407 # 1408 # Revision 1.32 2010/01/13 21:52:04 ncq 1409 # - implement phrase wheel on schedule and preparation 1410 # 1411 # Revision 1.31 2010/01/09 20:15:06 ncq 1412 # - use Advice 1413 # 1414 # Revision 1.30 2010/01/08 12:21:04 ncq 1415 # - even better error detection on forms template loading 1416 # 1417 # Revision 1.29 2010/01/06 14:42:20 ncq 1418 # - medication list printing: 1419 # - tie cleanup to --debug 1420 # - better error detection 1421 # 1422 # Revision 1.28 2010/01/01 21:48:15 ncq 1423 # - remove confusing status message 1424 # 1425 # Revision 1.27 2009/12/26 19:08:38 ncq 1426 # - document printing of medication list in EMR 1427 # 1428 # Revision 1.26 2009/12/25 22:07:17 ncq 1429 # - cleanup 1430 # - configure-medication-list-template 1431 # - print-medication-list 1432 # - show-info-on-entry 1433 # - tooltips on substance entry rows 1434 # 1435 # Revision 1.25 2009/12/22 12:02:57 ncq 1436 # - cleanup 1437 # 1438 # Revision 1.24 2009/12/03 17:51:11 ncq 1439 # - explicit ATC col in brand component list 1440 # 1441 # Revision 1.23 2009/12/02 16:50:44 ncq 1442 # - enable brand component deletion 1443 # - normalize substance name before adding as component 1444 # 1445 # Revision 1.22 2009/12/01 21:55:24 ncq 1446 # - branded drug phrasewheel 1447 # - much improved substance intake EA implementation 1448 # 1449 # Revision 1.21 2009/11/30 13:15:20 ncq 1450 # - better meds grid column ordering as per list 1451 # 1452 # Revision 1.20 2009/11/29 20:01:46 ncq 1453 # - substance phrasewheel 1454 # 1455 # Revision 1.19 2009/11/29 16:05:41 ncq 1456 # - must set self.data *late* in _save-as-new or else ! 1457 # - properly enable/disable duration PRW 1458 # - grid business logic moved into grid so no need to access self._grid_substances anymore 1459 # 1460 # Revision 1.18 2009/11/28 18:31:30 ncq 1461 # - implement drug brand management 1462 # - implement drug brand component management 1463 # 1464 # Revision 1.17 2009/11/24 20:59:59 ncq 1465 # - use import-drugs rather than import-drugs-as-substances 1466 # - improved grid layout as per list 1467 # - fix get-selected-data 1468 # - make grid wrapper do less 1469 # 1470 # Revision 1.16 2009/11/19 14:44:25 ncq 1471 # - improved plugin 1472 # 1473 # Revision 1.15 2009/11/15 01:09:07 ncq 1474 # - implement grouping/filtering 1475 # - mark unapproved vs approved if showing all substances 1476 # 1477 # Revision 1.14 2009/11/08 20:49:20 ncq 1478 # - implement deletion 1479 # - start grouping/filtering/ row tooltips 1480 # 1481 # Revision 1.13 2009/11/06 15:19:25 ncq 1482 # - implement saving as new substance intake 1483 # 1484 # Revision 1.12 2009/10/29 17:23:24 ncq 1485 # - consolidate get-drug-database 1486 # - much improved substance intake EA 1487 # - better naming and adjust to such 1488 # 1489 # Revision 1.11 2009/10/28 21:48:55 ncq 1490 # - further improved substances grid 1491 # 1492 # Revision 1.10 2009/10/28 16:43:42 ncq 1493 # - start implementing substances edit area 1494 # - enhance grid to allow actual substances management 1495 # 1496 # Revision 1.9 2009/10/26 22:30:58 ncq 1497 # - implement deletion of INN 1498 # 1499 # Revision 1.8 2009/10/21 20:41:53 ncq 1500 # - access MMI from substance management via NEW button 1501 # 1502 # Revision 1.7 2009/10/21 09:21:13 ncq 1503 # - manage substances 1504 # - jump to drug database 1505 # 1506 # Revision 1.6 2009/10/20 10:27:35 ncq 1507 # - implement configuration of drug data source 1508 # 1509 # Revision 1.5 2009/09/01 22:36:08 ncq 1510 # - add jump-to-mmi 1511 # 1512 # Revision 1.4 2009/06/20 12:46:04 ncq 1513 # - move IFAP handling here 1514 # 1515 # Revision 1.3 2009/06/10 21:02:34 ncq 1516 # - update-atc-reference-data 1517 # 1518 # Revision 1.2 2009/05/13 12:20:59 ncq 1519 # - improve and streamline 1520 # 1521 # Revision 1.1 2009/05/12 12:04:01 ncq 1522 # - substance intake handling 1523 # 1524 # 1525