1
2 """GNUmed text expansion widgets."""
3
4 __author__ = "Karsten Hilbert <Karsten.Hilbert@gmx.net>"
5 __license__ = "GPL v2 or later"
6
7 import logging
8 import sys
9 import re as regex
10
11
12 import wx
13
14
15 if __name__ == '__main__':
16 sys.path.insert(0, '../../')
17 from Gnumed.pycommon import gmDispatcher
18 from Gnumed.pycommon import gmPG2
19 from Gnumed.pycommon import gmTools
20 from Gnumed.wxpython import gmEditArea
21 from Gnumed.wxpython import gmListWidgets
22
23
24 _log = logging.getLogger('gm.ui')
25
26 _text_expansion_fillin_regex = r'\$<.*>\$'
27
28
29 from Gnumed.wxGladeWidgets import wxgTextExpansionEditAreaPnl
30
31 -class cTextExpansionEditAreaPnl(wxgTextExpansionEditAreaPnl.wxgTextExpansionEditAreaPnl, gmEditArea.cGenericEditAreaMixin):
32
33 - def __init__(self, *args, **kwds):
34
35 try:
36 data = kwds['keyword']
37 del kwds['keyword']
38 except KeyError:
39 data = None
40
41 wxgTextExpansionEditAreaPnl.wxgTextExpansionEditAreaPnl.__init__(self, *args, **kwds)
42 gmEditArea.cGenericEditAreaMixin.__init__(self)
43
44 self.mode = 'new'
45 self.data = data
46 if data is not None:
47 self.mode = 'edit'
48
49
50 self.__register_interests()
51
52 - def __init_ui(self, keyword=None):
53
54 if keyword is not None:
55 self.data = keyword
56
57
58
60 validity = True
61
62 if self._TCTRL_keyword.GetValue().strip() == u'':
63 validity = False
64 self.display_tctrl_as_valid(tctrl = self._TCTRL_keyword, valid = False)
65 gmDispatcher.send(signal = 'statustext', msg = _('Cannot save text expansion without keyword.'), beep = True)
66 else:
67 self.display_tctrl_as_valid(tctrl = self._TCTRL_keyword, valid = True)
68
69 if self._TCTRL_expansion.GetValue().strip() == u'':
70 validity = False
71 self.display_tctrl_as_valid(tctrl = self._TCTRL_expansion, valid = False)
72 gmDispatcher.send(signal = 'statustext', msg = _('Cannot save text expansion without expansion text.'), beep = True)
73 else:
74 self.display_tctrl_as_valid(tctrl = self._TCTRL_expansion, valid = True)
75
76 return validity
77
78 - def _save_as_new(self):
79 kwd = self._TCTRL_keyword.GetValue().strip()
80 saved = gmPG2.add_text_expansion (
81 keyword = kwd,
82 expansion = self._TCTRL_expansion.GetValue(),
83 public = self._RBTN_public.GetValue()
84 )
85 if not saved:
86 return False
87
88 self.data = kwd
89 return True
90
92 kwd = self._TCTRL_keyword.GetValue().strip()
93 gmPG2.edit_text_expansion (
94 keyword = kwd,
95 expansion = self._TCTRL_expansion.GetValue()
96 )
97 self.data = kwd
98 return True
99
100 - def _refresh_as_new(self):
101 self._TCTRL_keyword.SetValue(u'')
102 self._TCTRL_keyword.Enable(True)
103 self._TCTRL_expansion.SetValue(u'')
104 self._TCTRL_expansion.Enable(False)
105 self._RBTN_public.Enable(True)
106 self._RBTN_private.Enable(True)
107 self._RBTN_public.SetValue(1)
108
109 self._TCTRL_keyword.SetFocus()
110
112 self._TCTRL_keyword.SetValue(u'%s%s' % (self.data, _(u'___copy')))
113 self._TCTRL_keyword.Enable(True)
114 expansion = gmPG2.expand_keyword(keyword = self.data)
115 self._TCTRL_expansion.SetValue(gmTools.coalesce(expansion, u''))
116 self._TCTRL_expansion.Enable(True)
117 self._RBTN_public.Enable(True)
118 self._RBTN_private.Enable(True)
119 self._RBTN_public.SetValue(1)
120
121 self._TCTRL_keyword.SetFocus()
122
124 self._TCTRL_keyword.SetValue(self.data)
125 self._TCTRL_keyword.Enable(False)
126 expansion = gmPG2.expand_keyword(keyword = self.data)
127 self._TCTRL_expansion.SetValue(gmTools.coalesce(expansion, u''))
128 self._TCTRL_expansion.Enable(True)
129 self._RBTN_public.Enable(False)
130 self._RBTN_private.Enable(False)
131
132 self._TCTRL_expansion.SetFocus()
133
134
135
137 self._TCTRL_keyword.Bind(wx.EVT_TEXT, self._on_keyword_modified)
138
139 - def _on_keyword_modified(self, evt):
140 if self._TCTRL_keyword.GetValue().strip() == u'':
141 self._TCTRL_expansion.Enable(False)
142 else:
143 self._TCTRL_expansion.Enable(True)
144
146
147 if parent is None:
148 parent = wx.GetApp().GetTopWindow()
149
150
151 def delete(keyword=None):
152 gmPG2.delete_text_expansion(keyword = keyword)
153 return True
154
155 def edit(keyword=None):
156 ea = cTextExpansionEditAreaPnl(parent, -1, keyword = keyword)
157 dlg = gmEditArea.cGenericEditAreaDlg2(parent, -1, edit_area = ea)
158 dlg.SetTitle (
159 gmTools.coalesce(keyword, _('Adding text expansion'), _('Editing text expansion "%s"'))
160 )
161 if dlg.ShowModal() == wx.ID_OK:
162 return True
163
164 return False
165
166 def refresh(lctrl=None):
167 kwds = [ [
168 r[0],
169 gmTools.bool2subst(r[1], gmTools.u_checkmark_thick, u''),
170 gmTools.bool2subst(r[2], gmTools.u_checkmark_thick, u''),
171 r[3]
172 ] for r in gmPG2.get_text_expansion_keywords()
173 ]
174 data = [ r[0] for r in gmPG2.get_text_expansion_keywords() ]
175 lctrl.set_string_items(kwds)
176 lctrl.set_data(data)
177
178
179 gmListWidgets.get_choices_from_list (
180 parent = parent,
181 msg = _('\nSelect the keyword you want to edit !\n'),
182 caption = _('Editing keyword-based text expansions ...'),
183 columns = [_('Keyword'), _('Public'), _('Private'), _('Owner')],
184 single_selection = True,
185 edit_callback = edit,
186 new_callback = edit,
187 delete_callback = delete,
188 refresh_callback = refresh
189 )
190
191 from Gnumed.wxGladeWidgets import wxgTextExpansionFillInDlg
192
193 -class cTextExpansionFillInDlg(wxgTextExpansionFillInDlg.wxgTextExpansionFillInDlg):
194
195 - def __init__(self, *args, **kwds):
196 wxgTextExpansionFillInDlg.wxgTextExpansionFillInDlg.__init__(self, *args, **kwds)
197
198 self.__expansion = None
199 self.__init_ui()
200
201 - def __init_ui(self):
202 self._LBL_top_part.SetLabel(u'')
203 self._LBL_left_part.SetLabel(u'')
204 self._LBL_left_part.Hide()
205 self._TCTRL_fillin.SetValue(u'')
206 self._TCTRL_fillin.Disable()
207 self._TCTRL_fillin.Hide()
208 self._LBL_right_part.SetLabel(u'')
209 self._LBL_right_part.Hide()
210 self._LBL_bottom_part.SetLabel(u'')
211 self._BTN_OK.Disable()
212 self._BTN_forward.Disable()
213 self._BTN_cancel.SetFocus()
214 self._LBL_hint.SetLabel(u'')
215
217 if self.__expansion is None:
218 return
219
220 if self.__new_expansion:
221 self.__filled_in = self.__expansion
222 self.__new_expansion = False
223 else:
224 self.__filled_in = (
225 self._LBL_top_part.GetLabel() +
226 self.__left_splitter +
227 self._LBL_left_part.GetLabel() +
228 self._TCTRL_fillin.GetValue().strip() +
229 self._LBL_right_part.GetLabel() +
230 self.__right_splitter +
231 self._LBL_bottom_part.GetLabel()
232 )
233
234
235 if regex.search(_text_expansion_fillin_regex, self.__filled_in) is None:
236
237 self._LBL_top_part.SetLabel(self.__filled_in)
238 self._LBL_left_part.SetLabel(u'')
239 self._LBL_left_part.Hide()
240 self._TCTRL_fillin.SetValue(u'')
241 self._TCTRL_fillin.Disable()
242 self._TCTRL_fillin.Hide()
243 self._LBL_right_part.SetLabel(u'')
244 self._LBL_right_part.Hide()
245 self._LBL_bottom_part.SetLabel(u'')
246 self._BTN_OK.Enable()
247 self._BTN_forward.Disable()
248 self._BTN_OK.SetDefault()
249 return
250
251
252 top, fillin, bottom = regex.split(r'(' + _text_expansion_fillin_regex + r')', self.__filled_in, maxsplit = 1)
253 top_parts = top.rsplit(u'\n', 1)
254 top_part = top_parts[0]
255 if len(top_parts) == 1:
256 self.__left_splitter = u''
257 left_part = u''
258 else:
259 self.__left_splitter = u'\n'
260 left_part = top_parts[1]
261 bottom_parts = bottom.split(u'\n', 1)
262 if len(bottom_parts) == 1:
263 parts = bottom_parts[0].split(u' ', 1)
264 right_part = parts[0]
265 if len(parts) == 1:
266 self.__right_splitter = u''
267 bottom_part = u''
268 else:
269 self.__right_splitter = u' '
270 bottom_part = parts[1]
271 else:
272 self.__right_splitter = u'\n'
273 right_part = bottom_parts[0]
274 bottom_part = bottom_parts[1]
275 hint = fillin.strip('$').strip('<').strip('>').strip()
276 self._LBL_top_part.SetLabel(top_part)
277 self._LBL_left_part.SetLabel(left_part)
278 self._LBL_left_part.Show()
279 self._TCTRL_fillin.Enable()
280 self._TCTRL_fillin.SetValue(u'')
281 self._TCTRL_fillin.Show()
282 self._LBL_right_part.SetLabel(right_part)
283 self._LBL_right_part.Show()
284 self._LBL_bottom_part.SetLabel(bottom_part)
285 self._BTN_OK.Disable()
286 self._BTN_forward.Enable()
287 self._BTN_forward.SetDefault()
288 self._LBL_hint.SetLabel(hint)
289 self._TCTRL_fillin.SetFocus()
290
291 self.Layout()
292 self.Fit()
293
294
295
296 - def _get_expansion(self):
297 return self.__expansion
298
299 - def _set_expansion(self, expansion):
300 self.__expansion = expansion
301 self.__new_expansion = True
302 self.__goto_next_fillin()
303 return
304
305 expansion = property(_get_expansion, _set_expansion)
306
307 - def _get_filled_in(self):
308 return self.__filled_in
309
310 filled_in_expansion = property(_get_filled_in, lambda x:x)
311
313 self.__goto_next_fillin()
314
316 """Expand keyword and replace inside it.
317
318 Returns:
319 None: aborted or no expansion available
320 u'': empty expansion
321 u'<text>' the expansion
322 """
323 if keyword is None:
324 return None
325
326 if parent is None:
327 parent = wx.GetApp().GetTopWindow()
328
329 if show_list:
330 candidates = gmPG2.get_keyword_expansion_candidates(keyword = keyword)
331 if len(candidates) == 0:
332 return None
333 if len(candidates) == 1:
334 keyword = candidates[0]
335 else:
336 keyword = gmListWidgets.get_choices_from_list (
337 parent = parent,
338 msg = _(
339 'Several macros match the keyword [%s].\n'
340 '\n'
341 'Please select the expansion you want to happen.'
342 ) % keyword,
343 caption = _('Selecting text macro'),
344 choices = candidates,
345 columns = [_('Keyword')],
346 single_selection = True,
347 can_return_empty = False
348 )
349 if keyword is None:
350 return None
351
352 expansion = gmPG2.expand_keyword(keyword = keyword)
353
354
355 if expansion is None:
356 return None
357
358
359 if expansion.strip() == u'':
360 return expansion
361
362 if regex.search(_text_expansion_fillin_regex, expansion) is not None:
363 dlg = cTextExpansionFillInDlg(None, -1)
364 dlg.expansion = expansion
365 button = dlg.ShowModal()
366 if button == wx.ID_OK:
367 expansion = dlg.filled_in_expansion
368 dlg.Destroy()
369
370 return expansion
371
372
373
374
375 if __name__ == '__main__':
376
377 if len(sys.argv) < 2:
378 sys.exit()
379
380 if sys.argv[1] != 'test':
381 sys.exit()
382
383 from Gnumed.pycommon import gmI18N
384 gmI18N.activate_locale()
385 gmI18N.install_domain(domain = 'gnumed')
386
387
389 expansion = u"""HEMORR²HAGES: Blutungsrisiko unter OAK
390 --------------------------------------
391 Am Heart J. 2006 Mar;151(3):713-9.
392
393 $<1 oder 0 eingeben>$ H epatische oder Nierenerkrankung
394 $<1 oder 0 eingeben>$ E thanolabusus
395 $<1 oder 0 eingeben>$ M alignom
396 $<1 oder 0 eingeben>$ O ld patient (> 75 Jahre)
397 $<1 oder 0 eingeben>$ R eduzierte Thrombozytenzahl/-funktion
398 $<2 oder 0 eingeben>$ R²ekurrente (frühere) große Blutung
399 $<1 oder 0 eingeben>$ H ypertonie (unkontrolliert)
400 $<1 oder 0 eingeben>$ A nämie
401 $<1 oder 0 eingeben>$ G enetische Faktoren
402 $<1 oder 0 eingeben>$ E xzessives Sturzrisiko
403 $<1 oder 0 eingeben>$ S Schlaganfall in der Anamnese
404 --------------------------------------
405 Summe Rate großer Blutungen
406 pro 100 Patientenjahre
407 0 1.9
408 1 2.5
409 2 5.3
410 3 8.4
411 4 10.4
412 >4 12.3
413
414 Bewertung: Summe = $<Summe ausrechnen und bewerten>$"""
415
416 app = wx.PyWidgetTester(size = (600, 600))
417 dlg = cTextExpansionFillInDlg(None, -1)
418 dlg.expansion = expansion
419 dlg.ShowModal()
420
421
422 test_fillin()
423