1
2
3
4 __license__ = 'GPL'
5 __author__ = "R.Terry, K.Hilbert"
6
7
8 import sys
9 import logging
10 import datetime as pydt
11
12
13 import wx
14
15
16 if __name__ == '__main__':
17 sys.path.insert(0, '../../')
18 from Gnumed.pycommon import gmDispatcher
19
20
21 _log = logging.getLogger('gm.ui')
22
23 edit_area_modes = ['new', 'edit', 'new_from_existing']
24
26 """Mixin for edit area panels providing generic functionality.
27
28 **************** start of template ****************
29
30 #====================================================================
31 # Class definition:
32
33 from Gnumed.wxGladeWidgets import wxgXxxEAPnl
34
35 class cXxxEAPnl(wxgXxxEAPnl.wxgXxxEAPnl, gmEditArea.cGenericEditAreaMixin):
36
37 def __init__(self, *args, **kwargs):
38
39 try:
40 data = kwargs['xxx']
41 del kwargs['xxx']
42 except KeyError:
43 data = None
44
45 wxgXxxEAPnl.wxgXxxEAPnl.__init__(self, *args, **kwargs)
46 gmEditArea.cGenericEditAreaMixin.__init__(self)
47
48 # Code using this mixin should set mode and data
49 # after instantiating the class:
50 self.mode = 'new'
51 self.data = data
52 if data is not None:
53 self.mode = 'edit'
54
55 #self.__init_ui()
56
57 #----------------------------------------------------------------
58 # def __init_ui(self):
59 # # adjust phrasewheels etc
60
61 #----------------------------------------------------------------
62 # generic Edit Area mixin API
63 #----------------------------------------------------------------
64 def _valid_for_save(self):
65
66 # its best to validate bottom -> top such that the
67 # cursor ends up in the topmost failing field
68
69 # remove when implemented:
70 return False
71
72 validity = True
73
74 if self._TCTRL_xxx.GetValue().strip() == u'':
75 validity = False
76 self.display_tctrl_as_valid(tctrl = self._TCTRL_xxx, valid = False)
77 self.StatusText = _('No entry in field xxx.')
78 self._TCTRL_xxx.SetFocus()
79 else:
80 self.display_tctrl_as_valid(tctrl = self._TCTRL_xxx, valid = True)
81
82 if self._PRW_xxx.GetData() is None:
83 validity = False
84 self._PRW_xxx.display_as_valid(False)
85 self.StatusText = _('No entry in field xxx.')
86 self._PRW_xxx.SetFocus()
87 else:
88 self._PRW_xxx.display_as_valid(True)
89
90 return validity
91
92 #----------------------------------------------------------------
93 def _save_as_new(self):
94
95 # remove when implemented:
96 return False
97
98 # save the data as a new instance
99 data = gmXXXX.create_xxxx()
100
101 data[''] = self._
102 data[''] = self._
103
104 data.save()
105
106 # must be done very late or else the property access
107 # will refresh the display such that later field
108 # access will return empty values
109 self.data = data
110 return False
111 return True
112
113 #----------------------------------------------------------------
114 def _save_as_update(self):
115
116 # remove when implemented:
117 return False
118
119 # update self.data and save the changes
120 self.data[''] = self._TCTRL_xxx.GetValue().strip()
121 self.data[''] = self._PRW_xxx.GetData()
122 self.data[''] = self._CHBOX_xxx.GetValue()
123 self.data.save()
124 return True
125
126 #----------------------------------------------------------------
127 def _refresh_as_new(self):
128 pass
129
130 #----------------------------------------------------------------
131 def _refresh_as_new_from_existing(self):
132 self._refresh_as_new()
133
134 #----------------------------------------------------------------
135 def _refresh_from_existing(self):
136 pass
137
138 #----------------------------------------------------------------
139 def set_fields(self, fields):
140 # <fields> must be a dict compatible with the
141 # structure of the business object this edit
142 # area is for,
143 # thusly, the edit area knows how to set its
144 # controls from it,
145 # <fields> doesn't have to contain all keys, rather:
146 # - missing ones are skipped
147 # - unknown ones are ignored
148 # each key must hold a dict with at least a key 'value'
149 # and _can_ contain another key 'data',
150 # 'value' and 'data' must be compatible with the
151 # control they go into,
152 # controls which don't require 'data' (say, RadioButton)
153 # will ignore an existing 'data' key
154 pass
155
156 #----------------------------------------------------------------
157
158 **************** end of template ****************
159 """
161 self.__mode = 'new'
162 self.__data = None
163 self.successful_save_msg = None
164 self.__tctrl_validity_colors = {
165 True: wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW),
166 False: 'pink'
167 }
168 self._refresh_as_new()
169
170
171
172
175
177 if mode not in edit_area_modes:
178 raise ValueError('[%s] <mode> must be in %s' % (self.__class__.__name__, edit_area_modes))
179 if mode == 'edit':
180 if self.__data is None:
181 raise ValueError('[%s] <mode> "edit" needs data value' % self.__class__.__name__)
182
183 prev_mode = self.__mode
184 self.__mode = mode
185 if mode != prev_mode:
186 self.refresh()
187
188 mode = property(_get_mode, _set_mode)
189
190
193
195 if data is None:
196 if self.__mode == 'edit':
197 raise ValueError('[%s] <mode> "edit" needs data value' % self.__class__.__name__)
198 self.__data = data
199 self.refresh()
200
201 data = property(_get_data, _set_data)
202
203
204 - def _set_status_text(self, msg, beep=False):
205 gmDispatcher.send(signal = 'statustext_ea', msg = msg, beep = beep)
206
207 StatusText = property(lambda x:x, _set_status_text)
208
209
210
211
213 """Invoked from the generic edit area dialog.
214
215 Invokes
216 _valid_for_save,
217 _save_as_new,
218 _save_as_update
219 on the implementing edit area as needed.
220
221 _save_as_* must set self.__data and return True/False
222 """
223 if not self._valid_for_save():
224 return False
225
226
227 gmDispatcher.send(signal = 'statustext_ea', msg = '')
228
229 if self.__mode in ['new', 'new_from_existing']:
230 if self._save_as_new():
231 self.mode = 'edit'
232 return True
233 return False
234
235 elif self.__mode == 'edit':
236 return self._save_as_update()
237
238 else:
239 raise ValueError('[%s] <mode> must be in %s' % (self.__class__.__name__, edit_area_modes))
240
241
243 """Invoked from the generic edit area dialog.
244
245 Invokes
246 _refresh_as_new()
247 _refresh_from_existing()
248 _refresh_as_new_from_existing()
249 on the implementing edit area as needed.
250
251 Then calls _valid_for_save().
252 """
253 if self.__mode == 'new':
254 result = self._refresh_as_new()
255 self._valid_for_save()
256 return result
257 elif self.__mode == 'edit':
258 result = self._refresh_from_existing()
259 self._valid_for_save()
260 return result
261 elif self.__mode == 'new_from_existing':
262 result = self._refresh_as_new_from_existing()
263 self._valid_for_save()
264 return result
265 else:
266 raise ValueError('[%s] <mode> must be in %s' % (self.__class__.__name__, edit_area_modes))
267
268
271
272
276
277
278 from Gnumed.wxGladeWidgets import wxgGenericEditAreaDlg2
279
281 """Dialog for parenting edit area panels with save/clear/next/cancel"""
282
283 _lucky_day = 1
284 _lucky_month = 4
285 _today = pydt.date.today()
286
288
289 new_ea = kwargs['edit_area']
290 del kwargs['edit_area']
291
292 if not isinstance(new_ea, cGenericEditAreaMixin):
293 raise TypeError('[%s]: edit area instance must be child of cGenericEditAreaMixin')
294
295 try:
296 single_entry = kwargs['single_entry']
297 del kwargs['single_entry']
298 except KeyError:
299 single_entry = False
300
301 try:
302 title = kwargs['title']
303 except KeyError:
304 title = self.__class__.__name__
305 if not title.startswith('GMd: '):
306 title = 'GMd: %s' % title
307 kwargs['title'] = title
308
309 wxgGenericEditAreaDlg2.wxgGenericEditAreaDlg2.__init__(self, *args, **kwargs)
310
311 self.left_extra_button = None
312
313 if cGenericEditAreaDlg2._today.day != cGenericEditAreaDlg2._lucky_day:
314 self._BTN_lucky.Enable(False)
315 self._BTN_lucky.Hide()
316 else:
317 if cGenericEditAreaDlg2._today.month != cGenericEditAreaDlg2._lucky_month:
318 self._BTN_lucky.Enable(False)
319 self._BTN_lucky.Hide()
320
321
322 dummy_ea_pnl = self._PNL_ea
323 ea_pnl_szr = dummy_ea_pnl.GetContainingSizer()
324 ea_pnl_parent = dummy_ea_pnl.GetParent()
325
326 dummy_ea_pnl.DestroyLater()
327 del dummy_ea_pnl
328 new_ea_min_size = new_ea.GetMinSize()
329 new_ea.Reparent(ea_pnl_parent)
330 self._PNL_ea = new_ea
331 ea_pnl_szr.Add(self._PNL_ea, 1, wx.EXPAND, 0)
332 ea_pnl_szr.SetMinSize(new_ea_min_size)
333 ea_pnl_szr.Fit(new_ea)
334
335
336 if single_entry:
337 self._BTN_forward.Enable(False)
338 self._BTN_forward.Hide()
339
340 self._adjust_clear_revert_buttons()
341
342
343 self._TCTRL_status.SetValue('')
344 gmDispatcher.connect(signal = 'statustext_ea', receiver = self._on_set_statustext)
345
346
347 main_szr = self.GetSizer()
348 main_szr.Fit(self)
349 self.Layout()
350
351
352 self._PNL_ea.refresh()
353
354
355 - def _on_set_statustext(self, msg=None, loglevel=None, beep=False):
356 if msg is None:
357 msg = ''
358 self._TCTRL_status.SetValue(msg.strip())
359 if beep:
360 wx.Bell()
361
362
374
375
383
384
387
388
391
392
407
418
427
428
429
445
446 left_extra_button = property(lambda x:x, _set_left_extra_button)
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467 from Gnumed.pycommon import gmGuiBroker
468
469
470 _gb = gmGuiBroker.GuiBroker()
471
472 gmSECTION_SUMMARY = 1
473 gmSECTION_DEMOGRAPHICS = 2
474 gmSECTION_CLINICALNOTES = 3
475 gmSECTION_FAMILYHISTORY = 4
476 gmSECTION_PASTHISTORY = 5
477 gmSECTION_SCRIPT = 8
478 gmSECTION_REQUESTS = 9
479 gmSECTION_REFERRALS = 11
480 gmSECTION_RECALLS = 12
481
482 richards_blue = wx.Colour(0,0,131)
483 richards_aqua = wx.Colour(0,194,197)
484 richards_dark_gray = wx.Colour(131,129,131)
485 richards_light_gray = wx.Colour(255,255,255)
486 richards_coloured_gray = wx.Colour(131,129,131)
487
488
489 CONTROLS_WITHOUT_LABELS =['wxTextCtrl', 'cEditAreaField', 'wx.SpinCtrl', 'gmPhraseWheel', 'wx.ComboBox']
490
492 widget.SetForegroundColour(wx.Colour(255, 0, 0))
493 widget.SetFont(wx.Font(12, wx.SWISS, wx.NORMAL, wx.BOLD, False, ''))
494
507 if not isinstance(edit_area, cEditArea2):
508 raise TypeError('<edit_area> must be of type cEditArea2 but is <%s>' % type(edit_area))
509 wx.Dialog.__init__(self, parent, id, title, pos, size, style, name)
510 self.__wxID_BTN_SAVE = wx.NewId()
511 self.__wxID_BTN_RESET = wx.NewId()
512 self.__editarea = edit_area
513 self.__do_layout()
514 self.__register_events()
515
516
517
520
522 self.__editarea.Reparent(self)
523
524 self.__btn_SAVE = wx.Button(self, self.__wxID_BTN_SAVE, _("Save"))
525 self.__btn_SAVE.SetToolTip(_('save entry into medical record'))
526 self.__btn_RESET = wx.Button(self, self.__wxID_BTN_RESET, _("Reset"))
527 self.__btn_RESET.SetToolTip(_('reset entry'))
528 self.__btn_CANCEL = wx.Button(self, wx.ID_CANCEL, _("Cancel"))
529 self.__btn_CANCEL.SetToolTip(_('discard entry and cancel'))
530
531 szr_buttons = wx.BoxSizer(wx.HORIZONTAL)
532 szr_buttons.Add(self.__btn_SAVE, 1, wx.EXPAND | wx.ALL, 1)
533 szr_buttons.Add(self.__btn_RESET, 1, wx.EXPAND | wx.ALL, 1)
534 szr_buttons.Add(self.__btn_CANCEL, 1, wx.EXPAND | wx.ALL, 1)
535
536 szr_main = wx.BoxSizer(wx.VERTICAL)
537 szr_main.Add(self.__editarea, 1, wx.EXPAND)
538 szr_main.Add(szr_buttons, 0, wx.EXPAND)
539
540 self.SetSizerAndFit(szr_main)
541
542
543
545
546 wx.EVT_BUTTON(self.__btn_SAVE, self.__wxID_BTN_SAVE, self._on_SAVE_btn_pressed)
547 wx.EVT_BUTTON(self.__btn_RESET, self.__wxID_BTN_RESET, self._on_RESET_btn_pressed)
548 wx.EVT_BUTTON(self.__btn_CANCEL, wx.ID_CANCEL, self._on_CANCEL_btn_pressed)
549
550 wx.EVT_CLOSE(self, self._on_CANCEL_btn_pressed)
551
552
553
554
555
556
557 return 1
558
560 if self.__editarea.save_data():
561 self.__editarea.Close()
562 self.EndModal(wx.ID_OK)
563 return
564 short_err = self.__editarea.get_short_error()
565 long_err = self.__editarea.get_long_error()
566 if (short_err is None) and (long_err is None):
567 long_err = _(
568 'Unspecified error saving data in edit area.\n\n'
569 'Programmer forgot to specify proper error\n'
570 'message in [%s].'
571 ) % self.__editarea.__class__.__name__
572 if short_err is not None:
573 gmDispatcher.send(signal = 'statustext', msg = short_err)
574 if long_err is not None:
575 gmGuiHelpers.gm_show_error(long_err, _('saving clinical data'))
576
578 self.__editarea.Close()
579 self.EndModal(wx.ID_CANCEL)
580
583
585 - def __init__(self, parent, id, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.TAB_TRAVERSAL):
586
587 wx.Panel.__init__ (
588 self,
589 parent,
590 id,
591 pos = pos,
592 size = size,
593 style = style | wx.TAB_TRAVERSAL
594 )
595 self.SetBackgroundColour(wx.Colour(222,222,222))
596
597 self.data = None
598 self.fields = {}
599 self.prompts = {}
600 self._short_error = None
601 self._long_error = None
602 self._summary = None
603 self._patient = gmPerson.gmCurrentPatient()
604 self.__wxID_BTN_OK = wx.NewId()
605 self.__wxID_BTN_CLEAR = wx.NewId()
606 self.__do_layout()
607 self.__register_events()
608 self.Show()
609
610
611
613 """This needs to be overridden by child classes."""
614 self._long_error = _(
615 'Cannot save data from edit area.\n\n'
616 'Programmer forgot to override method:\n'
617 ' <%s.save_data>'
618 ) % self.__class__.__name__
619 return False
620
622 msg = _(
623 'Cannot reset fields in edit area.\n\n'
624 'Programmer forgot to override method:\n'
625 ' <%s.reset_ui>'
626 ) % self.__class__.__name__
627 gmGuiHelpers.gm_show_error(msg)
628
630 tmp = self._short_error
631 self._short_error = None
632 return tmp
633
635 tmp = self._long_error
636 self._long_error = None
637 return tmp
638
640 return _('<No embed string for [%s]>') % self.__class__.__name__
641
642
643
655
660
661
662
664 self.__deregister_events()
665 event.Skip()
666
668 """Only active if _make_standard_buttons was called in child class."""
669
670 try:
671 event.Skip()
672 if self.data is None:
673 self._save_new_entry()
674 self.reset_ui()
675 else:
676 self._save_modified_entry()
677 self.reset_ui()
678 except Exception as err:
679
680
681 gmGuiHelpers.gm_show_error (err, _("Invalid Input"))
682 except:
683 _log.exception( "save data problem in [%s]" % self.__class__.__name__)
684
686 """Only active if _make_standard_buttons was called in child class."""
687
688 self.reset_ui()
689 event.Skip()
690
692 self.__deregister_events()
693
694 if not self._patient.connected:
695 return True
696
697
698
699
700 return True
701 _log.error('[%s] lossage' % self.__class__.__name__)
702 return False
703
705 """Just before new patient becomes active."""
706
707 if not self._patient.connected:
708 return True
709
710
711
712
713 return True
714 _log.error('[%s] lossage' % self.__class__.__name__)
715 return False
716
718 """Just after new patient became active."""
719
720 self.reset_ui()
721
722
723
725
726
727 self._define_prompts()
728 self._define_fields(parent = self)
729 if len(self.fields) != len(self.prompts):
730 _log.error('[%s]: #fields != #prompts' % self.__class__.__name__)
731 return None
732
733
734 szr_main_fgrid = wx.FlexGridSizer(rows = len(self.prompts), cols=2)
735 color = richards_aqua
736 lines = self.prompts.keys()
737 lines.sort()
738 for line in lines:
739
740 label, color, weight = self.prompts[line]
741
742 prompt = wx.StaticText (
743 parent = self,
744 id = -1,
745 label = label,
746 style = wx.ALIGN_CENTRE
747 )
748
749 prompt.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.BOLD, False, ''))
750 prompt.SetForegroundColour(color)
751 prompt.SetBackgroundColour(richards_light_gray)
752 szr_main_fgrid.Add(prompt, flag=wx.EXPAND | wx.ALIGN_RIGHT)
753
754
755 szr_line = wx.BoxSizer(wx.HORIZONTAL)
756 positions = self.fields[line].keys()
757 positions.sort()
758 for pos in positions:
759 field, weight = self.fields[line][pos]
760
761 szr_line.Add(field, weight, wx.EXPAND)
762 szr_main_fgrid.Add(szr_line, flag=wx.GROW | wx.ALIGN_LEFT)
763
764
765 szr_main_fgrid.AddGrowableCol(1)
766
767
768
769
770
771
772
773 self.SetSizerAndFit(szr_main_fgrid)
774
775
776
777
779 """Child classes override this to define their prompts using _add_prompt()"""
780 _log.error('missing override in [%s]' % self.__class__.__name__)
781
783 """Add a new prompt line.
784
785 To be used from _define_fields in child classes.
786
787 - label, the label text
788 - color
789 - weight, the weight given in sizing the various rows. 0 means the row
790 always has minimum size
791 """
792 self.prompts[line] = (label, color, weight)
793
795 """Defines the fields.
796
797 - override in child classes
798 - mostly uses _add_field()
799 """
800 _log.error('missing override in [%s]' % self.__class__.__name__)
801
802 - def _add_field(self, line=None, pos=None, widget=None, weight=0):
803 if None in (line, pos, widget):
804 _log.error('argument error in [%s]: line=%s, pos=%s, widget=%s' % (self.__class__.__name__, line, pos, widget))
805 if line not in self.fields:
806 self.fields[line] = {}
807 self.fields[line][pos] = (widget, weight)
808
826
827
828
829
831 - def __init__ (self, parent, id = -1, pos = wx.DefaultPosition, size=wx.DefaultSize):
834
836 - def __init__(self, parent, id, pos, size, style):
837
838 print("class [%s] is deprecated, use cEditArea2 instead" % self.__class__.__name__)
839
840
841 wx.Panel.__init__(self, parent, id, pos=pos, size=size, style=wx.NO_BORDER | wx.TAB_TRAVERSAL)
842 self.SetBackgroundColour(wx.Colour(222,222,222))
843
844 self.data = None
845 self.fields = {}
846 self.prompts = {}
847
848 ID_BTN_OK = wx.NewId()
849 ID_BTN_CLEAR = wx.NewId()
850
851 self.__do_layout()
852
853
854
855
856
857
858 self._patient = gmPerson.gmCurrentPatient()
859 self.__register_events()
860 self.Show(True)
861
862
863
865
866 self._define_prompts()
867 self.fields_pnl = wx.Panel(self, -1, style = wx.RAISED_BORDER | wx.TAB_TRAVERSAL)
868 self._define_fields(parent = self.fields_pnl)
869
870 szr_prompts = self.__generate_prompts()
871 szr_fields = self.__generate_fields()
872
873
874 self.szr_main_panels = wx.BoxSizer(wx.HORIZONTAL)
875 self.szr_main_panels.Add(szr_prompts, 11, wx.EXPAND)
876 self.szr_main_panels.Add(5, 0, 0, wx.EXPAND)
877 self.szr_main_panels.Add(szr_fields, 90, wx.EXPAND)
878
879
880
881 self.szr_central_container = wx.BoxSizer(wx.HORIZONTAL)
882 self.szr_central_container.Add(self.szr_main_panels, 1, wx.EXPAND | wx.ALL, 5)
883
884
885 self.SetAutoLayout(True)
886 self.SetSizer(self.szr_central_container)
887 self.szr_central_container.Fit(self)
888
890 if len(self.fields) != len(self.prompts):
891 _log.error('[%s]: #fields != #prompts' % self.__class__.__name__)
892 return None
893
894 prompt_pnl = wx.Panel(self, -1, wx.DefaultPosition, wx.DefaultSize, wx.SIMPLE_BORDER)
895 prompt_pnl.SetBackgroundColour(richards_light_gray)
896
897 color = richards_aqua
898 lines = self.prompts.keys()
899 lines.sort()
900 self.prompt_widget = {}
901 for line in lines:
902 label, color, weight = self.prompts[line]
903 self.prompt_widget[line] = self.__make_prompt(prompt_pnl, "%s " % label, color)
904
905 shadow_below_prompts = wxWindow(self, -1, wx.DefaultPosition, wx.DefaultSize, 0)
906 shadow_below_prompts.SetBackgroundColour(richards_dark_gray)
907 szr_shadow_below_prompts = wx.BoxSizer (wx.HORIZONTAL)
908 szr_shadow_below_prompts.Add(5, 0, 0, wx.EXPAND)
909 szr_shadow_below_prompts.Add(shadow_below_prompts, 10, wx.EXPAND)
910
911
912 vszr_prompts = wx.BoxSizer(wx.VERTICAL)
913 vszr_prompts.Add(prompt_pnl, 97, wx.EXPAND)
914 vszr_prompts.Add(szr_shadow_below_prompts, 5, wx.EXPAND)
915
916
917 shadow_rightof_prompts = wxWindow(self, -1, wx.DefaultPosition, wx.DefaultSize, 0)
918 shadow_rightof_prompts.SetBackgroundColour(richards_dark_gray)
919 szr_shadow_rightof_prompts = wx.BoxSizer(wx.VERTICAL)
920 szr_shadow_rightof_prompts.Add(0,5,0,wx.EXPAND)
921 szr_shadow_rightof_prompts.Add(shadow_rightof_prompts, 1, wx.EXPAND)
922
923
924 hszr_prompts = wx.BoxSizer(wx.HORIZONTAL)
925 hszr_prompts.Add(vszr_prompts, 10, wx.EXPAND)
926 hszr_prompts.Add(szr_shadow_rightof_prompts, 1, wx.EXPAND)
927
928 return hszr_prompts
929
931 self.fields_pnl.SetBackgroundColour(wx.Colour(222,222,222))
932
933 vszr = wx.BoxSizer(wx.VERTICAL)
934 lines = self.fields.keys()
935 lines.sort()
936 self.field_line_szr = {}
937 for line in lines:
938 self.field_line_szr[line] = wx.BoxSizer(wx.HORIZONTAL)
939 positions = self.fields[line].keys()
940 positions.sort()
941 for pos in positions:
942 field, weight = self.fields[line][pos]
943 self.field_line_szr[line].Add(field, weight, wx.EXPAND)
944 try:
945 vszr.Add(self.field_line_szr[line], self.prompts[line][2], flag = wx.EXPAND)
946 except KeyError:
947 _log.error("Error with line=%s, self.field_line_szr has key:%s; self.prompts has key: %s" % (
948 line,
949 (line in self.field_line_szr),
950 (line in self.prompts)
951 ))
952
953 self.fields_pnl.SetSizer(vszr)
954 vszr.Fit(self.fields_pnl)
955
956
957 shadow_below_edit_fields = wxWindow(self, -1, wx.DefaultPosition, wx.DefaultSize, 0)
958 shadow_below_edit_fields.SetBackgroundColour(richards_coloured_gray)
959 szr_shadow_below_edit_fields = wx.BoxSizer(wx.HORIZONTAL)
960 szr_shadow_below_edit_fields.Add(5, 0, 0, wx.EXPAND)
961 szr_shadow_below_edit_fields.Add(shadow_below_edit_fields, 12, wx.EXPAND)
962
963
964 vszr_edit_fields = wx.BoxSizer(wx.VERTICAL)
965 vszr_edit_fields.Add(self.fields_pnl, 92, wx.EXPAND)
966 vszr_edit_fields.Add(szr_shadow_below_edit_fields, 5, wx.EXPAND)
967
968
969 shadow_rightof_edit_fields = wxWindow(self, -1, wx.DefaultPosition, wx.DefaultSize, 0)
970 shadow_rightof_edit_fields.SetBackgroundColour(richards_coloured_gray)
971 szr_shadow_rightof_edit_fields = wx.BoxSizer(wx.VERTICAL)
972 szr_shadow_rightof_edit_fields.Add(0, 5, 0, wx.EXPAND)
973 szr_shadow_rightof_edit_fields.Add(shadow_rightof_edit_fields, 1, wx.EXPAND)
974
975
976 hszr_edit_fields = wx.BoxSizer(wx.HORIZONTAL)
977 hszr_edit_fields.Add(vszr_edit_fields, 89, wx.EXPAND)
978 hszr_edit_fields.Add(szr_shadow_rightof_edit_fields, 1, wx.EXPAND)
979
980 return hszr_edit_fields
981
983
984 prompt = wx.StaticText(
985 parent,
986 -1,
987 aLabel,
988 style = wx.ALIGN_RIGHT
989 )
990 prompt.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.BOLD, False, ''))
991 prompt.SetForegroundColour(aColor)
992 return prompt
993
994
995
997 """Add a new prompt line.
998
999 To be used from _define_fields in child classes.
1000
1001 - label, the label text
1002 - color
1003 - weight, the weight given in sizing the various rows. 0 means the rwo
1004 always has minimum size
1005 """
1006 self.prompts[line] = (label, color, weight)
1007
1008 - def _add_field(self, line=None, pos=None, widget=None, weight=0):
1009 if None in (line, pos, widget):
1010 _log.error('argument error in [%s]: line=%s, pos=%s, widget=%s' % (self.__class__.__name__, line, pos, widget))
1011 if line not in self.fields:
1012 self.fields[line] = {}
1013 self.fields[line][pos] = (widget, weight)
1014
1016 """Defines the fields.
1017
1018 - override in child classes
1019 - mostly uses _add_field()
1020 """
1021 _log.error('missing override in [%s]' % self.__class__.__name__)
1022
1024 _log.error('missing override in [%s]' % self.__class__.__name__)
1025
1039
1042
1044 _log.error('[%s] programmer forgot to define _save_data()' % self.__class__.__name__)
1045 _log.info('child classes of cEditArea *must* override this function')
1046 return False
1047
1048
1049
1051
1052 wx.EVT_BUTTON(self.btn_OK, ID_BTN_OK, self._on_OK_btn_pressed)
1053 wx.EVT_BUTTON(self.btn_Clear, ID_BTN_CLEAR, self._on_clear_btn_pressed)
1054
1055 wx.EVT_SIZE (self.fields_pnl, self._on_resize_fields)
1056
1057
1058 gmDispatcher.connect(signal = 'pre_patient_unselection', receiver = self._on_pre_patient_unselection)
1059 gmDispatcher.connect(signal = 'application_closing', receiver = self._on_application_closing)
1060 gmDispatcher.connect(signal = 'post_patient_selection', receiver = self.on_post_patient_selection)
1061
1062 return 1
1063
1064
1065
1067
1068 try:
1069 event.Skip()
1070 if self.data is None:
1071 self._save_new_entry()
1072 self.set_data()
1073 else:
1074 self._save_modified_entry()
1075 self.set_data()
1076 except Exception as err:
1077
1078
1079 gmGuiHelpers.gm_show_error (err, _("Invalid Input"))
1080 except:
1081 _log.exception( "save data problem in [%s]" % self.__class__.__name__)
1082
1087
1088 - def on_post_patient_selection( self, **kwds):
1089
1090 self.set_data()
1091
1093
1094 if not self._patient.connected:
1095 return True
1096 if self._save_data():
1097 return True
1098 _log.error('[%s] lossage' % self.__class__.__name__)
1099 return False
1100
1102
1103 if not self._patient.connected:
1104 return True
1105 if self._save_data():
1106 return True
1107 _log.error('[%s] lossage' % self.__class__.__name__)
1108 return False
1109
1111 self.fields_pnl.Layout()
1112
1113 for i in self.field_line_szr.keys():
1114
1115 pos = self.field_line_szr[i].GetPosition()
1116
1117 self.prompt_widget[i].SetPosition((0, pos.y))
1118
1120 - def __init__(self, parent, id, aType = None):
1121
1122 print("class [%s] is deprecated, use cEditArea2 instead" % self.__class__.__name__)
1123
1124
1125 if aType not in _known_edit_area_types:
1126 _log.error('unknown edit area type: [%s]' % aType)
1127 raise gmExceptions.ConstructorError('unknown edit area type: [%s]' % aType)
1128 self._type = aType
1129
1130
1131 cEditArea.__init__(self, parent, id)
1132
1133 self.input_fields = {}
1134
1135 self._postInit()
1136 self.old_data = {}
1137
1138 self._patient = gmPerson.gmCurrentPatient()
1139 self.Show(True)
1140
1141
1142
1143
1144
1145
1147
1148 prompt_pnl = wx.Panel(self, -1, wx.DefaultPosition, wx.DefaultSize, wx.SIMPLE_BORDER)
1149 prompt_pnl.SetBackgroundColour(richards_light_gray)
1150
1151 gszr = wx.FlexGridSizer (len(prompt_labels)+1, 1, 2, 2)
1152 color = richards_aqua
1153 for prompt in prompt_labels:
1154 label = self.__make_prompt(prompt_pnl, "%s " % prompt, color)
1155 gszr.Add(label, 0, wx.EXPAND | wx.ALIGN_RIGHT)
1156 color = richards_blue
1157 gszr.RemoveGrowableRow (line-1)
1158
1159 prompt_pnl.SetSizer(gszr)
1160 gszr.Fit(prompt_pnl)
1161 prompt_pnl.SetAutoLayout(True)
1162
1163
1164 shadow_below_prompts = wxWindow(self, -1, wx.DefaultPosition, wx.DefaultSize, 0)
1165 shadow_below_prompts.SetBackgroundColour(richards_dark_gray)
1166 szr_shadow_below_prompts = wx.BoxSizer (wx.HORIZONTAL)
1167 szr_shadow_below_prompts.Add(5, 0, 0, wx.EXPAND)
1168 szr_shadow_below_prompts.Add(shadow_below_prompts, 10, wx.EXPAND)
1169
1170
1171 vszr_prompts = wx.BoxSizer(wx.VERTICAL)
1172 vszr_prompts.Add(prompt_pnl, 97, wx.EXPAND)
1173 vszr_prompts.Add(szr_shadow_below_prompts, 5, wx.EXPAND)
1174
1175
1176 shadow_rightof_prompts = wxWindow(self, -1, wx.DefaultPosition, wx.DefaultSize, 0)
1177 shadow_rightof_prompts.SetBackgroundColour(richards_dark_gray)
1178 szr_shadow_rightof_prompts = wx.BoxSizer(wx.VERTICAL)
1179 szr_shadow_rightof_prompts.Add(0,5,0,wx.EXPAND)
1180 szr_shadow_rightof_prompts.Add(shadow_rightof_prompts,1,wx.EXPAND)
1181
1182
1183 hszr_prompts = wx.BoxSizer(wx.HORIZONTAL)
1184 hszr_prompts.Add(vszr_prompts, 10, wx.EXPAND)
1185 hszr_prompts.Add(szr_shadow_rightof_prompts, 1, wx.EXPAND)
1186
1187 return hszr_prompts
1188
1190 _log.error('programmer forgot to define edit area lines for [%s]' % self._type)
1191 _log.info('child classes of gmEditArea *must* override this function')
1192 return []
1193
1195
1196 fields_pnl = wx.Panel(self, -1, wx.DefaultPosition, wx.DefaultSize, style = wx.RAISED_BORDER | wx.TAB_TRAVERSAL)
1197 fields_pnl.SetBackgroundColour(wx.Colour(222,222,222))
1198
1199 gszr = wx.GridSizer(len(_prompt_defs[self._type]), 1, 2, 2)
1200
1201
1202 lines = self._make_edit_lines(parent = fields_pnl)
1203
1204 self.lines = lines
1205 if len(lines) != len(_prompt_defs[self._type]):
1206 _log.error('#(edit lines) not equal #(prompts) for [%s], something is fishy' % self._type)
1207 for line in lines:
1208 gszr.Add(line, 0, wx.EXPAND | wx.ALIGN_LEFT)
1209
1210 fields_pnl.SetSizer(gszr)
1211 gszr.Fit(fields_pnl)
1212 fields_pnl.SetAutoLayout(True)
1213
1214
1215 shadow_below_edit_fields = wxWindow(self, -1, wx.DefaultPosition, wx.DefaultSize, 0)
1216 shadow_below_edit_fields.SetBackgroundColour(richards_coloured_gray)
1217 szr_shadow_below_edit_fields = wx.BoxSizer(wx.HORIZONTAL)
1218 szr_shadow_below_edit_fields.Add(5, 0, 0, wx.EXPAND)
1219 szr_shadow_below_edit_fields.Add(shadow_below_edit_fields, 12, wx.EXPAND)
1220
1221
1222 vszr_edit_fields = wx.BoxSizer(wx.VERTICAL)
1223 vszr_edit_fields.Add(fields_pnl, 92, wx.EXPAND)
1224 vszr_edit_fields.Add(szr_shadow_below_edit_fields, 5, wx.EXPAND)
1225
1226
1227 shadow_rightof_edit_fields = wxWindow(self, -1, wx.DefaultPosition, wx.DefaultSize, 0)
1228 shadow_rightof_edit_fields.SetBackgroundColour(richards_coloured_gray)
1229 szr_shadow_rightof_edit_fields = wx.BoxSizer(wx.VERTICAL)
1230 szr_shadow_rightof_edit_fields.Add(0, 5, 0, wx.EXPAND)
1231 szr_shadow_rightof_edit_fields.Add(shadow_rightof_edit_fields, 1, wx.EXPAND)
1232
1233
1234 hszr_edit_fields = wx.BoxSizer(wx.HORIZONTAL)
1235 hszr_edit_fields.Add(vszr_edit_fields, 89, wx.EXPAND)
1236 hszr_edit_fields.Add(szr_shadow_rightof_edit_fields, 1, wx.EXPAND)
1237
1238 return hszr_edit_fields
1239
1242
1247
1249 map = {}
1250 for k in self.input_fields.keys():
1251 map[k] = ''
1252 return map
1253
1254
1256 self._default_init_fields()
1257
1258
1259
1260
1261
1263 _log.warning("you may want to override _updateUI for [%s]" % self.__class__.__name__)
1264
1265
1266 - def _postInit(self):
1267 """override for further control setup"""
1268 pass
1269
1270
1272 szr = wx.BoxSizer(wx.HORIZONTAL)
1273 szr.Add( widget, weight, wx.EXPAND)
1274 szr.Add( 0,0, spacerWeight, wx.EXPAND)
1275 return szr
1276
1278
1279 cb = wx.CheckBox( parent, -1, _(title))
1280 cb.SetForegroundColour( richards_blue)
1281 return cb
1282
1283
1284
1286 """this is a utlity method to add extra columns"""
1287
1288 if "extraColumns" in self.__class__.__dict__:
1289 for x in self.__class__.extraColumns:
1290 lines = self._addColumn(parent, lines, x, weightMap)
1291 return lines
1292
1293
1294 - def _addColumn(self, parent, lines, extra, weightMap = {}, existingWeight = 5 , extraWeight = 2):
1295 """
1296 # add ia extra column in the edit area.
1297 # preconditions:
1298 # parent is fields_pnl (weak);
1299 # self.input_fields exists (required);
1300 # ; extra is a list of tuples of format -
1301 # ( key for input_fields, widget label , widget class to instantiate )
1302 """
1303 newlines = []
1304 i = 0
1305 for x in lines:
1306
1307 if x in weightMap:
1308 (existingWeight, extraWeight) = weightMap[x]
1309
1310 szr = wx.BoxSizer(wx.HORIZONTAL)
1311 szr.Add( x, existingWeight, wx.EXPAND)
1312 if i < len(extra) and extra[i] is not None:
1313 (inputKey, widgetLabel, aclass) = extra[i]
1314 if aclass.__name__ in CONTROLS_WITHOUT_LABELS:
1315 szr.Add( self._make_prompt(parent, widgetLabel, richards_blue) )
1316 widgetLabel = ""
1317
1318 w = aclass( parent, -1, widgetLabel)
1319 if not aclass.__name__ in CONTROLS_WITHOUT_LABELS:
1320 w.SetForegroundColour(richards_blue)
1321
1322 szr.Add(w, extraWeight , wx.EXPAND)
1323
1324
1325 self.input_fields[inputKey] = w
1326
1327 newlines.append(szr)
1328 i += 1
1329 return newlines
1330
1350
1353
1356
1362
1373
1374 -class gmPastHistoryEditArea(gmEditArea):
1375
1376 - def __init__(self, parent, id):
1377 gmEditArea.__init__(self, parent, id, aType = 'past history')
1378
1379 - def _define_prompts(self):
1380 self._add_prompt(line = 1, label = _("When Noted"))
1381 self._add_prompt(line = 2, label = _("Laterality"))
1382 self._add_prompt(line = 3, label = _("Condition"))
1383 self._add_prompt(line = 4, label = _("Notes"))
1384 self._add_prompt(line = 6, label = _("Status"))
1385 self._add_prompt(line = 7, label = _("Progress Note"))
1386 self._add_prompt(line = 8, label = '')
1387
1388 - def _define_fields(self, parent):
1389
1390 self.fld_date_noted = gmDateTimeInput.gmDateInput(
1391 parent = parent,
1392 id = -1,
1393 style = wx.SIMPLE_BORDER
1394 )
1395 self._add_field(
1396 line = 1,
1397 pos = 1,
1398 widget = self.fld_date_noted,
1399 weight = 2
1400 )
1401 self._add_field(
1402 line = 1,
1403 pos = 2,
1404 widget = cPrompt_edit_area(parent,-1, _("Age")),
1405 weight = 0)
1406
1407 self.fld_age_noted = cEditAreaField(parent)
1408 self._add_field(
1409 line = 1,
1410 pos = 3,
1411 widget = self.fld_age_noted,
1412 weight = 2
1413 )
1414
1415
1416 self.fld_laterality_none= wx.RadioButton(parent, -1, _("N/A"))
1417 self.fld_laterality_left= wx.RadioButton(parent, -1, _("L"))
1418 self.fld_laterality_right= wx.RadioButton(parent, -1, _("R"))
1419 self.fld_laterality_both= wx.RadioButton(parent, -1, _("both"))
1420 self._add_field(
1421 line = 2,
1422 pos = 1,
1423 widget = self.fld_laterality_none,
1424 weight = 0
1425 )
1426 self._add_field(
1427 line = 2,
1428 pos = 2,
1429 widget = self.fld_laterality_left,
1430 weight = 0
1431 )
1432 self._add_field(
1433 line = 2,
1434 pos = 3,
1435 widget = self.fld_laterality_right,
1436 weight = 1
1437 )
1438 self._add_field(
1439 line = 2,
1440 pos = 4,
1441 widget = self.fld_laterality_both,
1442 weight = 1
1443 )
1444
1445 self.fld_condition= cEditAreaField(parent)
1446 self._add_field(
1447 line = 3,
1448 pos = 1,
1449 widget = self.fld_condition,
1450 weight = 6
1451 )
1452
1453 self.fld_notes= cEditAreaField(parent)
1454 self._add_field(
1455 line = 4,
1456 pos = 1,
1457 widget = self.fld_notes,
1458 weight = 6
1459 )
1460
1461 self.fld_significant= wx.CheckBox(
1462 parent,
1463 -1,
1464 _("significant"),
1465 style = wx.NO_BORDER
1466 )
1467 self.fld_active= wx.CheckBox(
1468 parent,
1469 -1,
1470 _("active"),
1471 style = wx.NO_BORDER
1472 )
1473
1474 self._add_field(
1475 line = 5,
1476 pos = 1,
1477 widget = self.fld_significant,
1478 weight = 0
1479 )
1480 self._add_field(
1481 line = 5,
1482 pos = 2,
1483 widget = self.fld_active,
1484 weight = 0
1485 )
1486
1487 self.fld_progress= cEditAreaField(parent)
1488 self._add_field(
1489 line = 6,
1490 pos = 1,
1491 widget = self.fld_progress,
1492 weight = 6
1493 )
1494
1495
1496 self._add_field(
1497 line = 7,
1498 pos = 4,
1499 widget = self._make_standard_buttons(parent),
1500 weight = 2
1501 )
1502
1503 - def _postInit(self):
1504 return
1505
1506 wx.EVT_KILL_FOCUS( self.fld_age_noted, self._ageKillFocus)
1507 wx.EVT_KILL_FOCUS( self.fld_date_noted, self._yearKillFocus)
1508
1509 - def _ageKillFocus( self, event):
1510
1511 event.Skip()
1512 try :
1513 year = self._getBirthYear() + int(self.fld_age_noted.GetValue().strip() )
1514 self.fld_date_noted.SetValue( str (year) )
1515 except:
1516 pass
1517
1518 - def _getBirthYear(self):
1519 try:
1520 birthyear = int(str(self._patient['dob']).split('-')[0])
1521 except:
1522
1523 birthyear = 1
1524
1525 return birthyear
1526
1527 - def _yearKillFocus( self, event):
1528 event.Skip()
1529 try:
1530 age = int(self.fld_date_noted.GetValue().strip() ) - self._getBirthYear()
1531 self.fld_age_noted.SetValue( str (age) )
1532 except:
1533 pass
1534
1535 __init_values = {
1536 "condition": "",
1537 "notes1": "",
1538 "notes2": "",
1539 "age": "",
1540
1541 "progress": "",
1542 "active": 1,
1543 "operation": 0,
1544 "confidential": 0,
1545 "significant": 1,
1546 "both": 0,
1547 "left": 0,
1548 "right": 0,
1549 "none" : 1
1550 }
1551
1552 - def _getDefaultAge(self):
1553 try:
1554
1555 return 1
1556 except:
1557 return 0
1558
1559 - def _get_init_values(self):
1560 values = gmPastHistoryEditArea.__init_values
1561 values["age"] = str( self._getDefaultAge())
1562 return values
1563
1564 - def _save_data(self):
1565 clinical = self._patient.emr.get_past_history()
1566 if self.getDataId() is None:
1567 id = clinical.create_history( self.get_fields_formatting_values() )
1568 self.setDataId(id)
1569 return
1570
1571 clinical.update_history( self.get_fields_formatting_values(), self.getDataId() )
1572
1573
1583
1585 self._add_prompt (line = 1, label = _ ("Specialty"))
1586 self._add_prompt (line = 2, label = _ ("Name"))
1587 self._add_prompt (line = 3, label = _ ("Address"))
1588 self._add_prompt (line = 4, label = _ ("Options"))
1589 self._add_prompt (line = 5, label = _("Text"), weight =6)
1590 self._add_prompt (line = 6, label = "")
1591
1593 self.fld_specialty = gmPhraseWheel.cPhraseWheel (
1594 parent = parent,
1595 id = -1,
1596 style = wx.SIMPLE_BORDER
1597 )
1598
1599 self._add_field (
1600 line = 1,
1601 pos = 1,
1602 widget = self.fld_specialty,
1603 weight = 1
1604 )
1605 self.fld_name = gmPhraseWheel.cPhraseWheel (
1606 parent = parent,
1607 id = -1,
1608 style = wx.SIMPLE_BORDER
1609 )
1610
1611 self._add_field (
1612 line = 2,
1613 pos = 1,
1614 widget = self.fld_name,
1615 weight = 1
1616 )
1617 self.fld_address = wx.ComboBox (parent, -1, style = wx.CB_READONLY)
1618
1619 self._add_field (
1620 line = 3,
1621 pos = 1,
1622 widget = self.fld_address,
1623 weight = 1
1624 )
1625
1626
1627 self.fld_name.add_callback_on_selection(self.setAddresses)
1628
1629 self.fld_med = wx.CheckBox (parent, -1, _("Meds"), style=wx.NO_BORDER)
1630 self._add_field (
1631 line = 4,
1632 pos = 1,
1633 widget = self.fld_med,
1634 weight = 1
1635 )
1636 self.fld_past = wx.CheckBox (parent, -1, _("Past Hx"), style=wx.NO_BORDER)
1637 self._add_field (
1638 line = 4,
1639 pos = 4,
1640 widget = self.fld_past,
1641 weight = 1
1642 )
1643 self.fld_text = wx.TextCtrl (parent, -1, style= wx.TE_MULTILINE)
1644 self._add_field (
1645 line = 5,
1646 pos = 1,
1647 widget = self.fld_text,
1648 weight = 1)
1649
1650 self._add_field(
1651 line = 6,
1652 pos = 1,
1653 widget = self._make_standard_buttons(parent),
1654 weight = 1
1655 )
1656 return 1
1657
1659 """
1660 Doesn't accept any value as this doesn't make sense for this edit area
1661 """
1662 self.fld_specialty.SetValue ('')
1663 self.fld_name.SetValue ('')
1664 self.fld_address.Clear ()
1665 self.fld_address.SetValue ('')
1666 self.fld_med.SetValue (0)
1667 self.fld_past.SetValue (0)
1668 self.fld_text.SetValue ('')
1669 self.recipient = None
1670
1672 """
1673 Set the available addresses for the selected identity
1674 """
1675 if id is None:
1676 self.recipient = None
1677 self.fld_address.Clear ()
1678 self.fld_address.SetValue ('')
1679 else:
1680 self.recipient = gmDemographicRecord.cDemographicRecord_SQL (id)
1681 self.fld_address.Clear ()
1682 self.addr = self.recipient.getAddresses ('work')
1683 for i in self.addr:
1684 self.fld_address.Append (_("%(number)s %(street)s, %(urb)s %(postcode)s") % i, ('post', i))
1685 fax = self.recipient.getCommChannel (gmDemographicRecord.FAX)
1686 email = self.recipient.getCommChannel (gmDemographicRecord.EMAIL)
1687 if fax:
1688 self.fld_address.Append ("%s: %s" % (_("FAX"), fax), ('fax', fax))
1689 if email:
1690 self.fld_address.Append ("%s: %s" % (_("E-MAIL"), email), ('email', email))
1691
1692 - def _save_new_entry(self):
1693 """
1694 We are always saving a "new entry" here because data_ID is always None
1695 """
1696 if not self.recipient:
1697 raise UserWarning(_('must have a recipient'))
1698 if self.fld_address.GetSelection() == -1:
1699 raise UserWarning(_('must select address'))
1700 channel, addr = self.fld_address.GetClientData (self.fld_address.GetSelection())
1701 text = self.fld_text.GetValue()
1702 flags = {}
1703 flags['meds'] = self.fld_med.GetValue()
1704 flags['pasthx'] = self.fld_past.GetValue()
1705 if not gmReferral.create_referral (self._patient, self.recipient, channel, addr, text, flags):
1706 raise UserWarning('error sending form')
1707
1708
1709
1710
1711
1719
1720
1721
1723 _log.debug("making prescription lines")
1724 lines = []
1725 self.txt_problem = cEditAreaField(parent)
1726 self.txt_class = cEditAreaField(parent)
1727 self.txt_generic = cEditAreaField(parent)
1728 self.txt_drug_product = cEditAreaField(parent)
1729 self.txt_strength= cEditAreaField(parent)
1730 self.txt_directions= cEditAreaField(parent)
1731 self.txt_for = cEditAreaField(parent)
1732 self.txt_progress = cEditAreaField(parent)
1733
1734 lines.append(self.txt_problem)
1735 lines.append(self.txt_class)
1736 lines.append(self.txt_generic)
1737 lines.append(self.txt_drug_product)
1738 lines.append(self.txt_strength)
1739 lines.append(self.txt_directions)
1740 lines.append(self.txt_for)
1741 lines.append(self.txt_progress)
1742 lines.append(self._make_standard_buttons(parent))
1743 self.input_fields = {
1744 "problem": self.txt_problem,
1745 "class" : self.txt_class,
1746 "generic" : self.txt_generic,
1747 "prod" : self.txt_drug_product,
1748 "strength": self.txt_strength,
1749 "directions": self.txt_directions,
1750 "for" : self.txt_for,
1751 "progress": self.txt_progress
1752
1753 }
1754
1755 return self._makeExtraColumns( parent, lines)
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1774
1775
1776
1777
1778
1779
1782 wx.StaticText.__init__(self, parent, id, prompt, wx.DefaultPosition, wx.DefaultSize, wx.ALIGN_LEFT)
1783 self.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.BOLD, False, ''))
1784 self.SetForegroundColour(aColor)
1785
1786
1787
1788
1789
1791 - def __init__(self, parent, id, prompt_labels):
1792 wx.Panel.__init__(self, parent, id, wx.DefaultPosition, wx.DefaultSize, wx.SIMPLE_BORDER)
1793 self.SetBackgroundColour(richards_light_gray)
1794 gszr = wx.GridSizer (len(prompt_labels)+1, 1, 2, 2)
1795 color = richards_aqua
1796 for prompt_key in prompt_labels.keys():
1797 label = cPrompt_edit_area(self, -1, " %s" % prompt_labels[prompt_key], aColor = color)
1798 gszr.Add(label, 0, wx.EXPAND | wx.ALIGN_RIGHT)
1799 color = richards_blue
1800 self.SetSizer(gszr)
1801 gszr.Fit(self)
1802 self.SetAutoLayout(True)
1803
1804
1805
1806
1807
1808
1809
1810 -class EditTextBoxes(wx.Panel):
1811 - def __init__(self, parent, id, editareaprompts, section):
1812 wx.Panel.__init__(self, parent, id, wx.DefaultPosition, wx.DefaultSize,style = wx.RAISED_BORDER | wx.TAB_TRAVERSAL)
1813 self.SetBackgroundColour(wx.Colour(222,222,222))
1814 self.parent = parent
1815
1816 self.gszr = wx.GridSizer(len(editareaprompts), 1, 2, 2)
1817
1818 if section == gmSECTION_SUMMARY:
1819 pass
1820 elif section == gmSECTION_DEMOGRAPHICS:
1821 pass
1822 elif section == gmSECTION_CLINICALNOTES:
1823 pass
1824 elif section == gmSECTION_FAMILYHISTORY:
1825 pass
1826 elif section == gmSECTION_PASTHISTORY:
1827 pass
1828
1829
1830 self.txt_condition = cEditAreaField(self,PHX_CONDITION,wx.DefaultPosition,wx.DefaultSize)
1831 self.rb_sideleft = wxRadioButton(self,PHX_LEFT, _(" (L) "), wx.DefaultPosition,wx.DefaultSize)
1832 self.rb_sideright = wxRadioButton(self, PHX_RIGHT, _("(R)"), wx.DefaultPosition,wx.DefaultSize,wx.SUNKEN_BORDER)
1833 self.rb_sideboth = wxRadioButton(self, PHX_BOTH, _("Both"), wx.DefaultPosition,wx.DefaultSize)
1834 rbsizer = wx.BoxSizer(wx.HORIZONTAL)
1835 rbsizer.Add(self.rb_sideleft,1,wx.EXPAND)
1836 rbsizer.Add(self.rb_sideright,1,wx.EXPAND)
1837 rbsizer.Add(self.rb_sideboth,1,wx.EXPAND)
1838 szr1 = wx.BoxSizer(wx.HORIZONTAL)
1839 szr1.Add(self.txt_condition, 4, wx.EXPAND)
1840 szr1.Add(rbsizer, 3, wx.EXPAND)
1841
1842
1843
1844
1845 self.txt_notes1 = cEditAreaField(self,PHX_NOTES,wx.DefaultPosition,wx.DefaultSize)
1846
1847 self.txt_notes2= cEditAreaField(self,PHX_NOTES2,wx.DefaultPosition,wx.DefaultSize)
1848
1849 self.txt_agenoted = cEditAreaField(self, PHX_AGE, wx.DefaultPosition, wx.DefaultSize)
1850 szr4 = wx.BoxSizer(wx.HORIZONTAL)
1851 szr4.Add(self.txt_agenoted, 1, wx.EXPAND)
1852 szr4.Add(5, 0, 5)
1853
1854 self.txt_yearnoted = cEditAreaField(self,PHX_YEAR,wx.DefaultPosition,wx.DefaultSize)
1855 szr5 = wx.BoxSizer(wx.HORIZONTAL)
1856 szr5.Add(self.txt_yearnoted, 1, wx.EXPAND)
1857 szr5.Add(5, 0, 5)
1858
1859 self.parent.cb_active = wx.CheckBox(self, PHX_ACTIVE, _("Active"), wx.DefaultPosition,wx.DefaultSize, wx.NO_BORDER)
1860 self.parent.cb_operation = wx.CheckBox(self, PHX_OPERATION, _("Operation"), wx.DefaultPosition,wx.DefaultSize, wx.NO_BORDER)
1861 self.parent.cb_confidential = wx.CheckBox(self, PHX_CONFIDENTIAL , _("Confidential"), wx.DefaultPosition,wx.DefaultSize, wx.NO_BORDER)
1862 self.parent.cb_significant = wx.CheckBox(self, PHX_SIGNIFICANT, _("Significant"), wx.DefaultPosition,wx.DefaultSize, wx.NO_BORDER)
1863 szr6 = wx.BoxSizer(wx.HORIZONTAL)
1864 szr6.Add(self.parent.cb_active, 1, wx.EXPAND)
1865 szr6.Add(self.parent.cb_operation, 1, wx.EXPAND)
1866 szr6.Add(self.parent.cb_confidential, 1, wx.EXPAND)
1867 szr6.Add(self.parent.cb_significant, 1, wx.EXPAND)
1868
1869 self.txt_progressnotes = cEditAreaField(self,PHX_PROGRESSNOTES ,wx.DefaultPosition,wx.DefaultSize)
1870
1871 szr8 = wx.BoxSizer(wx.HORIZONTAL)
1872 szr8.Add(5, 0, 6)
1873 szr8.Add(self._make_standard_buttons(), 0, wx.EXPAND)
1874
1875 self.gszr.Add(szr1,0,wx.EXPAND)
1876 self.gszr.Add(self.txt_notes1,0,wx.EXPAND)
1877 self.gszr.Add(self.txt_notes2,0,wx.EXPAND)
1878 self.gszr.Add(szr4,0,wx.EXPAND)
1879 self.gszr.Add(szr5,0,wx.EXPAND)
1880 self.gszr.Add(szr6,0,wx.EXPAND)
1881 self.gszr.Add(self.txt_progressnotes,0,wx.EXPAND)
1882 self.gszr.Add(szr8,0,wx.EXPAND)
1883
1884
1885 elif section == gmSECTION_SCRIPT:
1886 pass
1887 elif section == gmSECTION_REQUESTS:
1888 pass
1889 elif section == gmSECTION_RECALLS:
1890 pass
1891 else:
1892 pass
1893
1894 self.SetSizer(self.gszr)
1895 self.gszr.Fit(self)
1896
1897 self.SetAutoLayout(True)
1898 self.Show(True)
1899
1901 self.btn_OK = wx.Button(self, -1, _("Ok"))
1902 self.btn_Clear = wx.Button(self, -1, _("Clear"))
1903 szr_buttons = wx.BoxSizer(wx.HORIZONTAL)
1904 szr_buttons.Add(self.btn_OK, 1, wx.EXPAND, wx.ALL, 1)
1905 szr_buttons.Add(5, 0, 0)
1906 szr_buttons.Add(self.btn_Clear, 1, wx.EXPAND, wx.ALL, 1)
1907 return szr_buttons
1908
1910 - def __init__(self, parent, id, line_labels, section):
1911 _log.warning('***** old style EditArea instantiated, please convert *****')
1912
1913 wx.Panel.__init__(self, parent, id, wx.DefaultPosition, wx.DefaultSize, style = wx.NO_BORDER)
1914 self.SetBackgroundColour(wx.Colour(222,222,222))
1915
1916
1917 prompts = gmPnlEditAreaPrompts(self, -1, line_labels)
1918
1919 shadow_below_prompts = wxWindow(self, -1, wx.DefaultPosition, wx.DefaultSize, 0)
1920
1921 shadow_below_prompts.SetBackgroundColour(richards_dark_gray)
1922 szr_shadow_below_prompts = wx.BoxSizer (wx.HORIZONTAL)
1923 szr_shadow_below_prompts.Add(5,0,0,wx.EXPAND)
1924 szr_shadow_below_prompts.Add(shadow_below_prompts, 10, wx.EXPAND)
1925
1926 szr_prompts = wx.BoxSizer(wx.VERTICAL)
1927 szr_prompts.Add(prompts, 97, wx.EXPAND)
1928 szr_prompts.Add(szr_shadow_below_prompts, 5, wx.EXPAND)
1929
1930
1931 edit_fields = EditTextBoxes(self, -1, line_labels, section)
1932
1933 shadow_below_editarea = wxWindow(self, -1, wx.DefaultPosition, wx.DefaultSize, 0)
1934
1935 shadow_below_editarea.SetBackgroundColour(richards_coloured_gray)
1936 szr_shadow_below_editarea = wx.BoxSizer(wx.HORIZONTAL)
1937 szr_shadow_below_editarea.Add(5,0,0,wx.EXPAND)
1938 szr_shadow_below_editarea.Add(shadow_below_editarea, 12, wx.EXPAND)
1939
1940 szr_editarea = wx.BoxSizer(wx.VERTICAL)
1941 szr_editarea.Add(edit_fields, 92, wx.EXPAND)
1942 szr_editarea.Add(szr_shadow_below_editarea, 5, wx.EXPAND)
1943
1944
1945
1946 shadow_rightof_prompts = wxWindow(self, -1, wx.DefaultPosition, wx.DefaultSize, 0)
1947 shadow_rightof_prompts.SetBackgroundColour(richards_dark_gray)
1948 szr_shadow_rightof_prompts = wx.BoxSizer(wx.VERTICAL)
1949 szr_shadow_rightof_prompts.Add(0,5,0,wx.EXPAND)
1950 szr_shadow_rightof_prompts.Add(shadow_rightof_prompts,1,wx.EXPAND)
1951
1952 shadow_rightof_editarea = wxWindow(self, -1, wx.DefaultPosition, wx.DefaultSize, 0)
1953 shadow_rightof_editarea.SetBackgroundColour(richards_coloured_gray)
1954 szr_shadow_rightof_editarea = wx.BoxSizer(wx.VERTICAL)
1955 szr_shadow_rightof_editarea.Add(0, 5, 0, wx.EXPAND)
1956 szr_shadow_rightof_editarea.Add(shadow_rightof_editarea, 1, wx.EXPAND)
1957
1958
1959 self.szr_main_panels = wx.BoxSizer(wx.HORIZONTAL)
1960 self.szr_main_panels.Add(szr_prompts, 10, wx.EXPAND)
1961 self.szr_main_panels.Add(szr_shadow_rightof_prompts, 1, wx.EXPAND)
1962 self.szr_main_panels.Add(5, 0, 0, wx.EXPAND)
1963 self.szr_main_panels.Add(szr_editarea, 89, wx.EXPAND)
1964 self.szr_main_panels.Add(szr_shadow_rightof_editarea, 1, wx.EXPAND)
1965
1966
1967
1968 self.szr_central_container = wx.BoxSizer(wx.HORIZONTAL)
1969 self.szr_central_container.Add(self.szr_main_panels, 1, wx.EXPAND | wx.ALL, 5)
1970 self.SetSizer(self.szr_central_container)
1971 self.szr_central_container.Fit(self)
1972 self.SetAutoLayout(True)
1973 self.Show(True)
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250 if __name__ == "__main__":
2251
2252
2257 self._add_prompt(line=1, label='line 1')
2258 self._add_prompt(line=2, label='buttons')
2260
2261 self.fld_substance = cEditAreaField(parent)
2262 self._add_field(
2263 line = 1,
2264 pos = 1,
2265 widget = self.fld_substance,
2266 weight = 1
2267 )
2268
2269 self._add_field(
2270 line = 2,
2271 pos = 1,
2272 widget = self._make_standard_buttons(parent),
2273 weight = 1
2274 )
2275
2276 app = wxPyWidgetTester(size = (400, 200))
2277 app.SetWidget(cTestEditArea)
2278 app.MainLoop()
2279
2280
2281
2282
2283
2284
2285
2286