Gnumed.wxpython.gmKeywordExpansionWidgets

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

# Source Code for Module Gnumed.wxpython.gmKeywordExpansionWidgets

      1  # -*- coding: utf8 -*-
      2  """GNUmed keyword 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  import os.path
     11
     12
     13  import wx
     14
     15
     16  if __name__ == '__main__':
     17          sys.path.insert(0, '../../')
     18  from Gnumed.pycommon import gmDispatcher
     19  from Gnumed.pycommon import gmPG2
     20  from Gnumed.pycommon import gmTools
     21  from Gnumed.business import gmKeywordExpansion
     22  from Gnumed.wxpython import gmEditArea
     23  from Gnumed.wxpython import gmListWidgets
     24
     25
     26  _log = logging.getLogger('gm.ui')
     27
     28  _text_expansion_fillin_regex = r'\$\[.*\]\$'
     29
     30  #============================================================
     31 -class cKeywordExpansion_TextCtrlMixin():
     32
     33 -        def __init__(self):
     34                  if not isinstance(self, wx.TextCtrl):
     35                          raise TypeError('[%s]: can only be applied to wx.TextCtrl, not [%s]' % (cKeywordExpansion_TextCtrlMixin, self.__class__.__name__))
     36          #--------------------------------------------------------
     37 -        def enable_keyword_expansions(self):
     38                  self.__keyword_separators = regex.compile("[!?'\".,:;)}\]\r\n\s\t]+")
     39                  self.Bind(wx.EVT_CHAR, self.__on_char_in_keyword_expansion_mixin)
     40          #--------------------------------------------------------
     41 -        def disable_keyword_expansions(self):
     42                  self.Unbind(wx.EVT_CHAR)
     43          #--------------------------------------------------------
     44          # event handling
     45          #--------------------------------------------------------
     46 -        def __on_char_in_keyword_expansion_mixin(self, evt):
     47                  evt.Skip()
     48
     49                  # empty ?
     50                  if self.LastPosition == 1:
     51                          return
     52
     53                  char = unichr(evt.GetUnicodeKey())
     54
     55                  explicit_expansion = False
     56                  if evt.GetModifiers() == (wx.MOD_CMD | wx.MOD_ALT): # portable CTRL-ALT-...
     57                          if evt.GetKeyCode() == wx.WXK_RETURN:           # CTRL-ALT-ENTER
     58                                  explicit_expansion = True
     59                          elif evt.GetKeyCode() == 20:                            # CTRL-ALT-T
     60                                  explicit_expansion = True
     61                          else:
     62                                  return
     63
     64                  if not explicit_expansion:
     65                          # user did not press CTRL-ALT-ENTER,
     66                          # however, did they last enter a
     67                          # "keyword sepearator", active character ?
     68                          if self.__keyword_separators.match(char) is None:
     69                                  return
     70
     71                  caret_pos, line_no = self.PositionToXY(self.InsertionPoint)
     72                  line = self.GetLineText(line_no)
     73                  keyword = self.__keyword_separators.split(line[:caret_pos])[-1]
     74
     75                  if (
     76                          (not explicit_expansion)
     77                                  and
     78                          (keyword != u'$$steffi')                        # Easter Egg ;-)
     79                                  and
     80                          (keyword not in [ r[0] for r in gmKeywordExpansion.get_textual_expansion_keywords() ])
     81                  ):
     82                          return
     83
     84                  start = self.InsertionPoint - len(keyword)
     85                  wx.CallAfter(self.__replace_keyword_with_expansion, keyword, start, explicit_expansion)
     86
     87                  return
     88          #--------------------------------------------------------
     89          # internal helpers
     90          #--------------------------------------------------------
     91 -        def __replace_keyword_with_expansion(self, keyword=None, position=None, show_list=False):
     92
     93                  expansion = expand_keyword(parent = self, keyword = keyword, show_list = show_list)
     94
     95                  if expansion is None:
     96                          return
     97
     98                  if expansion == u'':
     99                          return
    100
    101                  if not self.IsMultiLine():
    102                          expansion_lines = gmTools.strip_leading_empty_lines (
    103                                  lines = gmTools.strip_trailing_empty_lines (
    104                                          text = expansion,
    105                                          return_list = True
    106                                  ),
    107                                  return_list = True
    108                          )
    109                          if len(expansion_lines) == 0:
    110                                  return
    111                          if len(expansion_lines) == 1:
    112                                  expansion = expansion_lines[0]
    113                          else:
    114                                  msg = _(
    115                                          'The fragment <%s> expands to multiple lines !\n'
    116                                          '\n'
    117                                          'This text field can hold one line only, hwoever.\n'
    118                                          '\n'
    119                                          'Please select the line you want to insert:'
    120                                  ) % keyword
    121                                  expansion = gmListWidgets.get_choices_from_list (
    122                                          parent = self,
    123                                          msg = msg,
    124                                          caption = _('Adapting multi-line expansion to single-line text field'),
    125                                          choices = expansion_lines,
    126                                          selections = [0],
    127                                          columns = [_('Keyword expansion lines')],
    128                                          single_selection = True,
    129                                          can_return_empty = False
    130                                  )
    131                                  if expansion is None:
    132                                          return
    133
    134                  self.Replace (
    135                          position,
    136                          position + len(keyword),
    137                          expansion
    138                  )
    139
    140                  self.SetInsertionPoint(position + len(expansion) + 1)
    141                  self.ShowPosition(position + len(expansion) + 1)
    142
    143                  return
    144
    145  #============================================================
    146  from Gnumed.wxGladeWidgets import wxgTextExpansionEditAreaPnl
    147
    148 -class cTextExpansionEditAreaPnl(wxgTextExpansionEditAreaPnl.wxgTextExpansionEditAreaPnl, gmEditArea.cGenericEditAreaMixin):
    149
    150 -        def __init__(self, *args, **kwds):
    151
    152                  try:
    153                          data = kwds['expansion']
    154                          del kwds['expansion']
    155                  except KeyError:
    156                          data = None
    157
    158                  wxgTextExpansionEditAreaPnl.wxgTextExpansionEditAreaPnl.__init__(self, *args, **kwds)
    159                  gmEditArea.cGenericEditAreaMixin.__init__(self)
    160
    161                  self.mode = 'new'
    162                  self.data = data
    163                  if data is not None:
    164                          self.mode = 'edit'
    165
    166  #               self.__init_ui()
    167                  self.__register_interests()
    168
    169                  self.__data_filename = None
    170          #--------------------------------------------------------
    171  #       def __init_ui(self, expansion=None):
    172  #               self._BTN_select_data_file.Enable(False)
    173          #----------------------------------------------------------------
    174          # generic Edit Area mixin API
    175          #----------------------------------------------------------------
    176 -        def _valid_for_save(self):
    177                  validity = True
    178
    179                  has_expansion = (
    180                          (self._TCTRL_expansion.GetValue().strip() != u'')
    181                                  or
    182                          (self.__data_filename is not None)
    183                                  or
    184                          ((self.data is not None) and (self.data['is_textual'] is False))
    185                  )
    186
    187                  if has_expansion:
    188                          self.display_tctrl_as_valid(tctrl = self._TCTRL_expansion, valid = True)
    189                          self.display_tctrl_as_valid(tctrl = self._TCTRL_data_file, valid = True)
    190                  else:
    191                          validity = False
    192                          gmDispatcher.send(signal = 'statustext', msg = _('Cannot save keyword expansion without text or data expansion.'), beep = True)
    193                          self.display_tctrl_as_valid(tctrl = self._TCTRL_expansion, valid = False)
    194                          self.display_tctrl_as_valid(tctrl = self._TCTRL_data_file, valid = False)
    195                          if self.data is None:
    196                                  self._TCTRL_expansion.SetFocus()
    197                          else:
    198                                  if self.data['is_textual']:
    199                                          self._TCTRL_expansion.SetFocus()
    200                                  else:
    201                                          self._BTN_select_data_file.SetFocus()
    202
    203                  if self._TCTRL_keyword.GetValue().strip() == u'':
    204                          validity = False
    205                          self.display_tctrl_as_valid(tctrl = self._TCTRL_keyword, valid = False)
    206                          gmDispatcher.send(signal = 'statustext', msg = _('Cannot save keyword expansion without keyword.'), beep = True)
    207                          self._TCTRL_keyword.SetFocus()
    208                  else:
    209                          self.display_tctrl_as_valid(tctrl = self._TCTRL_keyword, valid = True)
    210
    211                  return validity
    212          #----------------------------------------------------------------
    213 -        def _save_as_new(self):
    214                  expansion = gmKeywordExpansion.create_keyword_expansion (
    215                          keyword = self._TCTRL_keyword.GetValue().strip(),
    216                          text = self._TCTRL_expansion.GetValue(),
    217                          data_file = self.__data_filename,
    218                          public = self._RBTN_public.GetValue()
    219                  )
    220
    221                  if expansion is None:
    222                          return False
    223
    224                  expansion['is_encrypted'] = self._CHBOX_is_encrypted.IsChecked()
    225                  expansion.save()
    226
    227                  self.data = expansion
    228                  return True
    229          #----------------------------------------------------------------
    230 -        def _save_as_update(self):
    231
    232                  self.data['expansion'] = self._TCTRL_expansion.GetValue().strip()
    233                  self.data['is_encrypted'] = self._CHBOX_is_encrypted.IsChecked()
    234                  self.data.save()
    235
    236                  if self.__data_filename is not None:
    237                          self.data.update_data_from_file(filename = self.__data_filename)
    238
    239                  return True
    240          #----------------------------------------------------------------
    241          #----------------------------------------------------------------
    242 -        def _refresh_as_new(self):
    243                  self.__data_filename = None
    244
    245                  self._TCTRL_keyword.SetValue(u'')
    246                  self._TCTRL_keyword.Enable(True)
    247
    248                  self._LBL_data.Enable(False)
    249                  self._BTN_select_data_file.Enable(False)
    250                  self._TCTRL_data_file.SetValue(u'')
    251                  self._CHBOX_is_encrypted.SetValue(False)
    252                  self._CHBOX_is_encrypted.Enable(False)
    253
    254                  self._LBL_text.Enable(False)
    255                  self._TCTRL_expansion.SetValue(u'')
    256                  self._TCTRL_expansion.Enable(False)
    257
    258                  self._RBTN_public.Enable(False)
    259                  self._RBTN_private.Enable(False)
    260                  self._RBTN_public.SetValue(1)
    261
    262                  self._TCTRL_keyword.SetFocus()
    263          #----------------------------------------------------------------
    264 -        def _refresh_as_new_from_existing(self):
    265                  self._refresh_from_existing()
    266
    267                  self._TCTRL_keyword.SetValue(u'%s%s' % (self.data, _(u'___copy')))
    268                  self._TCTRL_keyword.Enable(True)
    269
    270                  self._RBTN_public.Enable(True)
    271                  self._RBTN_private.Enable(True)
    272
    273                  self._TCTRL_keyword.SetFocus()
    274          #----------------------------------------------------------------
    275 -        def _refresh_from_existing(self):
    276                  self.__data_filename = None
    277
    278                  self._TCTRL_keyword.SetValue(self.data['keyword'])
    279                  self._TCTRL_keyword.Enable(False)
    280
    281                  if self.data['is_textual']:
    282                          self._LBL_text.Enable(True)
    283                          self._TCTRL_expansion.SetValue(gmTools.coalesce(self.data['expansion'], u''))
    284
    285                          self._LBL_data.Enable(False)
    286                          self._BTN_select_data_file.Enable(False)
    287                          self._TCTRL_data_file.SetValue(u'')
    288                          self._CHBOX_is_encrypted.SetValue(False)
    289                          self._CHBOX_is_encrypted.Enable(False)
    290                  else:
    291                          self._LBL_text.Enable(False)
    292                          self._TCTRL_expansion.SetValue(u'')
    293
    294                          self._LBL_data.Enable(True)
    295                          self._BTN_select_data_file.Enable(True)
    296                          self._TCTRL_data_file.SetValue(_('Size: %s') % gmTools.size2str(self.data['data_size']))
    297                          self._CHBOX_is_encrypted.SetValue(self.data['is_encrypted'])
    298                          self._CHBOX_is_encrypted.Enable(True)
    299
    300                  self._RBTN_public.Enable(False)
    301                  self._RBTN_private.Enable(False)
    302                  if self.data['public_expansion']:
    303                          self._RBTN_public.SetValue(1)
    304                  else:
    305                          self._RBTN_private.SetValue(1)
    306
    307                  if self.data['is_textual']:
    308                          self._TCTRL_expansion.SetFocus()
    309                  else:
    310                          self._BTN_select_data_file.SetFocus()
    311          #----------------------------------------------------------------
    312          # event handling
    313          #----------------------------------------------------------------
    314 -        def __register_interests(self):
    315                  self._TCTRL_keyword.Bind(wx.EVT_TEXT, self._on_keyword_modified)
    316                  self._TCTRL_expansion.Bind(wx.EVT_TEXT, self._on_expansion_modified)
    317          #----------------------------------------------------------------
    318 -        def _on_keyword_modified(self, evt):
    319                  if self._TCTRL_keyword.GetValue().strip() == u'':
    320                          self._LBL_text.Enable(False)
    321                          self._TCTRL_expansion.Enable(False)
    322                          self._LBL_data.Enable(False)
    323                          self._BTN_select_data_file.Enable(False)
    324                          self._CHBOX_is_encrypted.Enable(False)
    325                          self._RBTN_public.Enable(False)
    326                          self._RBTN_private.Enable(False)
    327                          return
    328
    329                  # keyword is not empty
    330                  # mode must be new(_from_existing) or else
    331                  # we cannot modify the keyword in the first place
    332                  self._LBL_text.Enable(True)
    333                  self._TCTRL_expansion.Enable(True)
    334                  self._LBL_data.Enable(True)
    335                  self._BTN_select_data_file.Enable(True)
    336                  self._RBTN_public.Enable(True)
    337                  self._RBTN_private.Enable(True)
    338          #----------------------------------------------------------------
    339 -        def _on_expansion_modified(self, evt):
    340                  if self._TCTRL_expansion.GetValue().strip() == u'':
    341                          self._LBL_data.Enable(True)
    342                          self._BTN_select_data_file.Enable(True)
    343                          return
    344
    345                  self.__data_filename = None
    346                  self._LBL_data.Enable(False)
    347                  self._BTN_select_data_file.Enable(False)
    348                  self._TCTRL_data_file.SetValue(u'')
    349                  self._CHBOX_is_encrypted.Enable(False)
    350          #----------------------------------------------------------------
    351 -        def _on_select_data_file_button_pressed(self, event):
    352                  wildcards = [
    353                          u"%s (*)|*" % _('all files'),
    354                          u"%s (*.*)|*.*" % _('all files (Windows)')
    355                  ]
    356
    357                  dlg = wx.FileDialog (
    358                          parent = self,
    359                          message = _('Choose the file containing the data snippet'),
    360                          wildcard = '|'.join(wildcards),
    361                          style = wx.OPEN | wx.HIDE_READONLY | wx.FILE_MUST_EXIST
    362                  )
    363                  result = dlg.ShowModal()
    364                  if result != wx.ID_CANCEL:
    365                          self.__data_filename = dlg.GetPath()
    366                          self._TCTRL_data_file.SetValue(self.__data_filename)
    367                          self._CHBOX_is_encrypted.SetValue(False)
    368                          self._CHBOX_is_encrypted.Enable(True)
    369
    370                  dlg.Destroy()
    371
    372  #============================================================
    373 -def configure_keyword_text_expansion(parent=None):
    374
    375          if parent is None:
    376                  parent = wx.GetApp().GetTopWindow()
    377
    378          #----------------------
    379          def delete(expansion=None):
    380                  gmKeywordExpansion.delete_keyword_expansion(pk = expansion['pk_expansion'])
    381                  return True
    382          #----------------------
    383          def edit(expansion=None):
    384                  ea = cTextExpansionEditAreaPnl(parent, -1, expansion = expansion)
    385                  dlg = gmEditArea.cGenericEditAreaDlg2(parent, -1, edit_area = ea)
    386                  if expansion is None:
    387                          title = _('Adding keyword expansion')
    388                  else:
    389                          title = _('Editing keyword expansion "%s"') % expansion['keyword']
    390                  dlg.SetTitle(title)
    391                  if dlg.ShowModal() == wx.ID_OK:
    392                          return True
    393
    394                  return False
    395          #----------------------
    396          def tooltip(expansion):
    397                  return expansion.format()
    398          #----------------------
    399          def refresh(lctrl=None):
    400                  expansions = gmKeywordExpansion.get_keyword_expansions(order_by = u'is_textual DESC, keyword, public_expansion', force_reload = True)
    401                  items = [[
    402                                  e['keyword'],
    403                                  gmTools.bool2subst(e['is_textual'], _('text'), _('data')),
    404                                  gmTools.bool2subst(e['public_expansion'], _('public'), _('private'))
    405                          ] for e in expansions
    406                  ]
    407                  lctrl.set_string_items(items)
    408                  lctrl.set_data(expansions)
    409          #----------------------
    410
    411          gmListWidgets.get_choices_from_list (
    412                  parent = parent,
    413                  msg = _('\nSelect the keyword you want to edit !\n'),
    414                  caption = _('Editing keyword-based expansions ...'),
    415                  columns = [_('Keyword'), _('Type'), _('Scope')],
    416                  single_selection = True,
    417                  edit_callback = edit,
    418                  new_callback = edit,
    419                  delete_callback = delete,
    420                  refresh_callback = refresh,
    421                  list_tooltip_callback = tooltip
    422          )
    423  #============================================================
    424  from Gnumed.wxGladeWidgets import wxgTextExpansionFillInDlg
    425
    426 -class cTextExpansionFillInDlg(wxgTextExpansionFillInDlg.wxgTextExpansionFillInDlg):
    427
    428 -        def __init__(self, *args, **kwds):
    429                  wxgTextExpansionFillInDlg.wxgTextExpansionFillInDlg.__init__(self, *args, **kwds)
    430
    431                  self.__expansion = None
    432                  self.__init_ui()
    433          #---------------------------------------------
    434 -        def __init_ui(self):
    435                  self._LBL_top_part.SetLabel(u'')
    436                  font = self._LBL_left_part.GetFont()
    437                  font.SetPointSize(pointSize = font.GetPointSize() + 1)
    438                  self._LBL_left_part.SetFont(font)
    439                  self._LBL_left_part.SetLabel(u'')
    440                  self._LBL_left_part.Hide()
    441                  font = self._TCTRL_fillin.GetFont()
    442                  font.SetPointSize(pointSize = font.GetPointSize() + 1)
    443                  self._TCTRL_fillin.SetFont(font)
    444                  self._TCTRL_fillin.SetValue(u'')
    445                  self._TCTRL_fillin.SetBackgroundColour('yellow')
    446                  self._TCTRL_fillin.Disable()
    447                  self._TCTRL_fillin.Hide()
    448                  font = self._LBL_right_part.GetFont()
    449                  font.SetPointSize(pointSize = font.GetPointSize() + 1)
    450                  self._LBL_right_part.SetFont(font)
    451                  self._LBL_right_part.SetLabel(u'')
    452                  self._LBL_right_part.Hide()
    453                  self._LBL_bottom_part.SetLabel(u'')
    454                  self._BTN_OK.Disable()
    455                  self._BTN_forward.Disable()
    456                  self._BTN_cancel.SetFocus()
    457                  self._LBL_hint.SetLabel(u'')
    458          #---------------------------------------------
    459 -        def __goto_next_fillin(self):
    460                  if self.__expansion is None:
    461                          return
    462
    463                  if self.__new_expansion:
    464                          self.__filled_in = self.__expansion
    465                          self.__new_expansion = False
    466                  else:
    467                          self.__filled_in = (
    468                                  self._LBL_top_part.GetLabel() +
    469                                  self.__left_splitter +
    470                                  self._LBL_left_part.GetLabel() +
    471                                  self._TCTRL_fillin.GetValue().strip() +
    472                                  self._LBL_right_part.GetLabel() +
    473                                  self.__right_splitter +
    474                                  self._LBL_bottom_part.GetLabel()
    475                          )
    476
    477                  # anything to fill in ?
    478                  if regex.search(_text_expansion_fillin_regex, self.__filled_in) is None:
    479                          # no
    480                          self._LBL_top_part.SetLabel(self.__filled_in)
    481                          self._LBL_left_part.SetLabel(u'')
    482                          self._LBL_left_part.Hide()
    483                          self._TCTRL_fillin.SetValue(u'')
    484                          self._TCTRL_fillin.Disable()
    485                          self._TCTRL_fillin.Hide()
    486                          self._LBL_right_part.SetLabel(u'')
    487                          self._LBL_right_part.Hide()
    488                          self._LBL_bottom_part.SetLabel(u'')
    489                          self._BTN_OK.Enable()
    490                          self._BTN_forward.Disable()
    491                          self._BTN_OK.SetDefault()
    492                          return
    493
    494                  # yes
    495                  top, fillin, bottom = regex.split(r'(' + _text_expansion_fillin_regex + r')', self.__filled_in, maxsplit = 1)
    496                  top_parts = top.rsplit(u'\n', 1)
    497                  top_part = top_parts[0]
    498                  if len(top_parts) == 1:
    499                          self.__left_splitter = u''
    500                          left_part = u''
    501                  else:
    502                          self.__left_splitter = u'\n'
    503                          left_part = top_parts[1]
    504                  bottom_parts = bottom.split(u'\n', 1)
    505                  if len(bottom_parts) == 1:
    506                          parts = bottom_parts[0].split(u' ', 1)
    507                          right_part = parts[0]
    508                          if len(parts) == 1:
    509                                  self.__right_splitter = u''
    510                                  bottom_part = u''
    511                          else:
    512                                  self.__right_splitter = u' '
    513                                  bottom_part = parts[1]
    514                  else:
    515                          self.__right_splitter = u'\n'
    516                          right_part = bottom_parts[0]
    517                          bottom_part =  bottom_parts[1]
    518                  hint = fillin.strip('$').strip('[').strip(']').strip()
    519                  self._LBL_top_part.SetLabel(top_part)
    520                  self._LBL_left_part.SetLabel(left_part)
    521                  self._LBL_left_part.Show()
    522                  self._TCTRL_fillin.Enable()
    523                  self._TCTRL_fillin.SetValue(u'')
    524                  self._TCTRL_fillin.Show()
    525                  self._LBL_right_part.SetLabel(right_part)
    526                  self._LBL_right_part.Show()
    527                  self._LBL_bottom_part.SetLabel(bottom_part)
    528                  self._BTN_OK.Disable()
    529                  self._BTN_forward.Enable()
    530                  self._BTN_forward.SetDefault()
    531                  self._LBL_hint.SetLabel(hint)
    532                  self._TCTRL_fillin.SetFocus()
    533
    534                  self.Layout()
    535                  self.Fit()
    536          #---------------------------------------------
    537          # properties
    538          #---------------------------------------------
    539 -        def _get_expansion(self):
    540                  return self.__expansion
    541
    542 -        def _set_expansion(self, expansion):
    543                  self.__expansion = expansion
    544                  self.__new_expansion = True
    545                  self.__goto_next_fillin()
    546                  return
    547
    548          expansion = property(_get_expansion, _set_expansion)
    549          #---------------------------------------------
    550 -        def _get_filled_in(self):
    551                  return self.__filled_in
    552
    553          filled_in_expansion = property(_get_filled_in, lambda x:x)
    554          #---------------------------------------------
    555 -        def _set_keyword(self, keyword):
    556                  self.SetTitle(_('Expanding <%s>') % keyword)
    557
    558          keyword = property(lambda x:x, _set_keyword)
    559          #---------------------------------------------
    560          # event handlers
    561          #---------------------------------------------
    562 -        def _on_forward_button_pressed(self, event):
    563                  self.__goto_next_fillin()
    564  #============================================================
    565 -def expand_keyword(parent=None, keyword=None, show_list=False):
    566          """Expand keyword and replace inside it.
    567
    568          Returns:
    569                  None: aborted or no expansion available
    570                  u'': empty expansion
    571                  u'<text>' the expansion
    572          """
    573          if keyword is None:
    574                  return None
    575
    576          if parent is None:
    577                  parent = wx.GetApp().GetTopWindow()
    578
    579          if show_list:
    580                  candidates = gmKeywordExpansion.get_matching_textual_keywords(fragment = keyword)
    581                  if len(candidates) == 0:
    582                          return None
    583                  if len(candidates) == 1:
    584                          keyword = candidates[0]
    585                  else:
    586                          keyword = gmListWidgets.get_choices_from_list (
    587                                  parent = parent,
    588                                  msg = _(
    589                                          'Several macro keywords match the fragment [%s].\n'
    590                                          '\n'
    591                                          'Please select the expansion you want to happen.'
    592                                  ) % keyword,
    593                                  caption = _('Selecting text macro'),
    594                                  choices = candidates,
    595                                  columns = [_('Keyword')],
    596                                  single_selection = True,
    597                                  can_return_empty = False
    598                          )
    599                          if keyword is None:
    600                                  return None
    601
    602          expansion = gmKeywordExpansion.expand_keyword(keyword = keyword)
    603
    604          # not found
    605          if expansion is None:
    606                  return None
    607
    608          # no replacement necessary:
    609          if expansion.strip() == u'':
    610                  return expansion
    611
    612          if regex.search(_text_expansion_fillin_regex, expansion) is not None:
    613                  dlg = cTextExpansionFillInDlg(None, -1)
    614                  dlg.keyword = keyword
    615                  dlg.expansion = expansion
    616                  button = dlg.ShowModal()
    617                  if button == wx.ID_OK:
    618                          expansion = dlg.filled_in_expansion
    619                  dlg.Destroy()
    620
    621          return expansion
    622
    623  #============================================================
    624  # main
    625  #------------------------------------------------------------
    626  if __name__ == '__main__':
    627
    628          if len(sys.argv) < 2:
    629                  sys.exit()
    630
    631          if sys.argv[1] != 'test':
    632                  sys.exit()
    633
    634          from Gnumed.pycommon import gmI18N
    635          gmI18N.activate_locale()
    636          gmI18N.install_domain(domain = 'gnumed')
    637
    638          #----------------------------------------
    639 -        def test_fillin():
    640                  expansion = u"""HEMORR²HAGES: Blutungsrisiko unter OAK
    641  --------------------------------------
    642  Am Heart J. 2006 Mar;151(3):713-9.
    643
    644  $[1 oder 0 eingeben]$ H epatische oder Nierenerkrankung
    645  $[1 oder 0 eingeben]$ E thanolabusus
    646  $[1 oder 0 eingeben]$ M alignom
    647  $[1 oder 0 eingeben]$ O ld patient (> 75 Jahre)
    648  $[1 oder 0 eingeben]$ R eduzierte Thrombozytenzahl/-funktion
    649  $[2 oder 0 eingeben]$ R²ekurrente (frühere) große Blutung
    650  $[1 oder 0 eingeben]$ H ypertonie (unkontrolliert)
    651  $[1 oder 0 eingeben]$ A nämie
    652  $[1 oder 0 eingeben]$ G enetische Faktoren
    653  $[1 oder 0 eingeben]$ E xzessives Sturzrisiko
    654  $[1 oder 0 eingeben]$ S Schlaganfall in der Anamnese
    655  --------------------------------------
    656  Summe   Rate großer Blutungen
    657          pro 100 Patientenjahre
    658   0          1.9
    659   1          2.5
    660   2          5.3
    661   3          8.4
    662   4         10.4
    663  >4         12.3
    664
    665  Bewertung: Summe = $[Summe ausrechnen und bewerten]$"""
    666
    667                  app = wx.PyWidgetTester(size = (600, 600))
    668                  dlg = cTextExpansionFillInDlg(None, -1)
    669                  dlg.expansion = expansion
    670                  dlg.ShowModal()
    671                  #app.MainLoop()
    672          #----------------------------------------
    673          test_fillin()
    674