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

# Source Code for Module Gnumed.wxpython.gmAddressWidgets

       1  """GNUmed generic address related widgets."""
       2  #================================================================
       3  __author__ = 'karsten.hilbert@gmx.net'
       4  __license__ = 'GPL v2 or later (details at http://www.gnu.org)'
       5
       6  # stdlib
       7  import logging, sys
       8
       9
      10  # 3rd party
      11  import wx
      12
      13
      14  # GNUmed
      15  if __name__ == '__main__':
      16          sys.path.insert(0, '../../')
      17
      18  from Gnumed.pycommon import gmTools
      19  from Gnumed.pycommon import gmMatchProvider
      20  from Gnumed.business import gmDemographicRecord
      21
      22  from Gnumed.wxpython import gmCfgWidgets
      23  from Gnumed.wxpython import gmPhraseWheel
      24  from Gnumed.wxpython import gmListWidgets
      25  from Gnumed.wxpython import gmEditArea
      26  from Gnumed.wxpython import gmGuiHelpers
      27
      28
      29  _log = logging.getLogger('gm.ui')
      30  #============================================================
      31  # country related widgets / functions
      32  #============================================================
      33 -def configure_default_country(parent=None):
      34
      35          if parent is None:
      36                  parent = wx.GetApp().GetTopWindow()
      37
      38          countries = gmDemographicRecord.get_countries()
      39
      40          gmCfgWidgets.configure_string_from_list_option (
      41                  parent = parent,
      42                  message = _('Select the default country for new persons.\n'),
      43                  option = 'person.create.default_country',
      44                  bias = 'user',
      45                  choices = [ (c['l10n_country'], c['code']) for c in countries ],
      46                  columns = [_('Country'), _('Code')],
      47                  data = [ c['code'] for c in countries ]
      48          )
      49  #============================================================
      50 -class cCountryPhraseWheel(gmPhraseWheel.cPhraseWheel):
      51
      52 -        def __init__(self, *args, **kwargs):
      53
      54                  gmPhraseWheel.cPhraseWheel.__init__(self, *args, **kwargs)
      55
      56                  context = {
      57                          u'ctxt_zip': {
      58                                  u'where_part': u'and zip ilike %(zip)s',
      59                                  u'placeholder': u'zip'
      60                          }
      61                  }
      62                  query = u"""
      63  SELECT
      64          data,
      65          field_label,
      66          list_label
      67  FROM (
      68          SELECT DISTINCT ON (data)
      69                  data,
      70                  field_label,
      71                  list_label,
      72                  rank
      73          FROM (
      74
      75          -- localized to user
      76                          SELECT
      77                                  code_country AS data,
      78                                  l10n_country AS field_label,
      79                                  l10n_country || ' (' || code_country || '): ' || country AS list_label,
      80                                  1 AS rank
      81                          FROM dem.v_zip2data
      82                          WHERE
      83                                  l10n_country %(fragment_condition)s
      84                                  %(ctxt_zip)s
      85                  UNION ALL
      86                          SELECT
      87                                  code AS data,
      88                                  _(name) AS field_label,
      89                                  _(name) || ' (' || code || '): ' || name AS list_label,
      90                                  2 AS rank
      91                          FROM dem.country
      92                          WHERE
      93                                  _(name) %(fragment_condition)s
      94
      95                  UNION ALL
      96
      97          -- non-localized
      98                          SELECT
      99                                  code_country AS data,
     100                                  l10n_country AS field_label,
     101                                  country || ' (' || code_country || '): ' || l10n_country AS list_label,
     102                                  3 AS rank
     103                          FROM dem.v_zip2data
     104                          WHERE
     105                                  country %(fragment_condition)s
     106                                  %(ctxt_zip)s
     107                  UNION ALL
     108                          SELECT
     109                                  code AS data,
     110                                  _(name) AS field_label,
     111                                  name || ' (' || code || '): ' || _(name) AS list_label,
     112                                  4 AS rank
     113                          FROM dem.country
     114                          WHERE
     115                                  name %(fragment_condition)s
     116
     117                  UNION ALL
     118
     119          -- abbreviation
     120                          SELECT
     121                                  code AS data,
     122                                  _(name) AS field_label,
     123                                  code || ': ' || _(name) || ' (' || name || ')' AS list_label,
     124                                  5 AS rank
     125                          FROM dem.country
     126                          WHERE
     127                                  code %(fragment_condition)s
     128
     129          ) AS candidates
     130  ) AS distint_candidates
     131  ORDER BY rank, list_label
     132  LIMIT 25"""
     133                  mp = gmMatchProvider.cMatchProvider_SQL2(queries=query, context=context)
     134                  mp._SQL_data2match = u"""
     135                          SELECT
     136                                  code AS data,
     137                                  _(name) AS field_label,
     138                                  code || ': ' || _(name) || ' (' || name || ')' AS list_label,
     139                                  5 AS rank
     140                          FROM dem.country
     141                          WHERE
     142                                  code = %(pk)s
     143                  """
     144                  mp.setThresholds(2, 5, 9)
     145                  self.matcher = mp
     146
     147                  self.unset_context(context = u'zip')
     148                  self.SetToolTipString(_('Type or select a country.'))
     149                  self.capitalisation_mode = gmTools.CAPS_FIRST
     150                  self.selection_only = True
     151
     152  #============================================================
     153  # province/state related widgets / functions
     154  #============================================================
     155 -def configure_default_region(parent=None):
     156
     157          if parent is None:
     158                  parent = wx.GetApp().GetTopWindow()
     159
     160          provs = gmDemographicRecord.get_provinces()
     161
     162          gmCfgWidgets.configure_string_from_list_option (
     163                  parent = parent,
     164                  message = _('Select the default region/province/state/territory for new persons.\n'),
     165                  option = 'person.create.default_region',
     166                  bias = 'user',
     167                  choices = [ (p['l10n_country'], p['l10n_state'], p['code_state']) for p in provs ],
     168                  columns = [_('Country'), _('Region'), _('Code')],
     169                  data = [ p['state'] for p in provs ]
     170          )
     171  #============================================================
     172 -def edit_province(parent=None, province=None):
     173          ea = cProvinceEAPnl(parent = parent, id = -1, province = province)
     174          dlg = gmEditArea.cGenericEditAreaDlg2(parent = parent, id = -1, edit_area = ea, single_entry = (province is not None))
     175          dlg.SetTitle(gmTools.coalesce(province, _('Adding province'), _('Editing province')))
     176          result = dlg.ShowModal()
     177          dlg.Destroy()
     178          return (result == wx.ID_OK)
     179  #============================================================
     180 -def delete_province(parent=None, province=None):
     181
     182          msg = _(
     183                  'Are you sure you want to delete this province ?\n'
     184                  '\n'
     185                  'Deletion will only work if this province is not\n'
     186                  'yet in use in any patient addresses.'
     187          )
     188
     189          tt = _(
     190                  'Also delete any towns/cities/villages known\n'
     191                  'to be situated in this state as long as\n'
     192                  'no patients are recorded to live there.'
     193          )
     194
     195          dlg = gmGuiHelpers.c2ButtonQuestionDlg (
     196                  parent,
     197                  -1,
     198                  caption = _('Deleting province'),
     199                  question = msg,
     200                  show_checkbox = True,
     201                  checkbox_msg = _('delete related townships'),
     202                  checkbox_tooltip = tt,
     203                  button_defs = [
     204                          {'label': _('Yes, delete'), 'tooltip': _('Delete province and possibly related townships.'), 'default': False},
     205                          {'label': _('No'), 'tooltip': _('No, do NOT delete anything.'), 'default': True}
     206                  ]
     207          )
     208
     209          decision = dlg.ShowModal()
     210          if decision != wx.ID_YES:
     211                  dlg.Destroy()
     212                  return False
     213
     214          include_urbs = dlg.checkbox_is_checked()
     215          dlg.Destroy()
     216
     217          return gmDemographicRecord.delete_province(province = province, delete_urbs = include_urbs)
     218  #============================================================
     219 -def manage_provinces(parent=None):
     220
     221          if parent is None:
     222                  parent = wx.GetApp().GetTopWindow()
     223
     224          #------------------------------------------------------------
     225          def delete(province=None):
     226                  return delete_province(parent = parent, province = province['pk_state'])
     227          #------------------------------------------------------------
     228          def edit(province=None):
     229                  return edit_province(parent = parent, province = province)
     230          #------------------------------------------------------------
     231          def refresh(lctrl):
     232                  wx.BeginBusyCursor()
     233                  provinces = gmDemographicRecord.get_provinces()
     234                  lctrl.set_string_items([ (p['l10n_country'], p['l10n_state']) for p in provinces ])
     235                  lctrl.set_data(provinces)
     236                  wx.EndBusyCursor()
     237          #------------------------------------------------------------
     238          msg = _(
     239                  '\n'
     240                  'This list shows the provinces known to GNUmed.\n'
     241                  '\n'
     242                  'In your jurisdiction "province" may correspond to either of "state",\n'
     243                  '"county", "region", "territory", or some such term.\n'
     244                  '\n'
     245                  'Select the province you want to edit !\n'
     246          )
     247
     248          gmListWidgets.get_choices_from_list (
     249                  parent = parent,
     250                  msg = msg,
     251                  caption = _('Editing provinces ...'),
     252                  columns = [_('Country'), _('Province')],
     253                  single_selection = True,
     254                  new_callback = edit,
     255                  #edit_callback = edit,
     256                  delete_callback = delete,
     257                  refresh_callback = refresh
     258          )
     259  #============================================================
     260 -class cStateSelectionPhraseWheel(gmPhraseWheel.cPhraseWheel):
     261
     262 -        def __init__(self, *args, **kwargs):
     263
     264                  gmPhraseWheel.cPhraseWheel.__init__(self, *args, **kwargs)
     265
     266                  context = {
     267                          u'ctxt_country_name': {
     268                                  u'where_part': u'AND l10n_country ILIKE %(country_name)s OR country ILIKE %(country_name)s',
     269                                  u'placeholder': u'country_name'
     270                          },
     271                          u'ctxt_zip': {
     272                                  u'where_part': u'AND zip ilike %(zip)s',
     273                                  u'placeholder': u'zip'
     274                          },
     275                          u'ctxt_country_code': {
     276                                  u'where_part': u'AND country IN (SELECT code FROM dem.country WHERE _(name) ILIKE %(country_name)s OR name ILIKE %(country_name)s)',
     277                                  u'placeholder': u'country_name'
     278                          }
     279                  }
     280
     281                  query = u"""
     282  SELECT
     283          data,
     284          field_label,
     285          list_label
     286  FROM (
     287          SELECT DISTINCT ON (field_label)
     288                  data,
     289                  field_label,
     290                  list_label,
     291                  rank
     292          FROM (
     293                          -- 1: find states based on name, context: zip and country name
     294                          SELECT
     295                                  code_state AS data,
     296                                  state AS field_label,
     297                                  state || ' (' || code_state || '), ' || l10n_country || ' (' || code_country || ')' AS list_label,
     298                                  1 AS rank
     299                          FROM dem.v_zip2data
     300                          WHERE
     301                                  state %(fragment_condition)s
     302                                  %(ctxt_country_name)s
     303                                  %(ctxt_zip)s
     304
     305                  UNION ALL
     306
     307                          -- 2: find states based on code, context: zip and country name
     308                          SELECT
     309                                  code_state AS data,
     310                                  state AS field_label,
     311                                  code_state || ': ' || state || ' (' || l10n_country || ', ' || code_country || ')' AS list_label,
     312                                  2 AS rank
     313                          FROM dem.v_zip2data
     314                          WHERE
     315                                  code_state %(fragment_condition)s
     316                                  %(ctxt_country_name)s
     317                                  %(ctxt_zip)s
     318
     319                  UNION ALL
     320
     321                          -- 3: find states based on name, context: country
     322                          SELECT
     323                                  code AS data,
     324                                  name AS field_label,
     325                                  name || ' (' || code || '), ' || country AS list_label,
     326                                  3 AS rank
     327                          FROM dem.state
     328                          WHERE
     329                                  name %(fragment_condition)s
     330                                  %(ctxt_country_code)s
     331
     332                  UNION ALL
     333
     334                          -- 4: find states based on code, context: country
     335                          SELECT
     336                                  code AS data,
     337                                  name AS field_label,
     338                                  code || ': ' || name || ', ' || country AS list_label,
     339                                  3 AS rank
     340                          FROM dem.state
     341                          WHERE
     342                                  code %(fragment_condition)s
     343                                  %(ctxt_country_code)s
     344
     345          ) AS candidate_states
     346  ) AS distinct_matches
     347  ORDER BY rank, list_label
     348  LIMIT 50"""
     349
     350                  mp = gmMatchProvider.cMatchProvider_SQL2(queries=query, context=context)
     351                  mp.setThresholds(2, 5, 6)
     352                  mp.word_separators = u'[ \t]+'
     353                  self.matcher = mp
     354
     355                  self.unset_context(context = u'zip')
     356                  self.unset_context(context = u'country_name')
     357                  self.SetToolTipString(_('Type or select a state/region/province/territory.'))
     358                  self.capitalisation_mode = gmTools.CAPS_FIRST
     359                  self.selection_only = True
     360  #====================================================================
     361  from Gnumed.wxGladeWidgets import wxgProvinceEAPnl
     362
     363 -class cProvinceEAPnl(wxgProvinceEAPnl.wxgProvinceEAPnl, gmEditArea.cGenericEditAreaMixin):
     364
     365 -        def __init__(self, *args, **kwargs):
     366
     367                  try:
     368                          data = kwargs['province']
     369                          del kwargs['province']
     370                  except KeyError:
     371                          data = None
     372
     373                  wxgProvinceEAPnl.wxgProvinceEAPnl.__init__(self, *args, **kwargs)
     374                  gmEditArea.cGenericEditAreaMixin.__init__(self)
     375
     376                  self.mode = 'new'
     377                  self.data = data
     378                  if data is not None:
     379                          self.mode = 'edit'
     380
     381                  self.__init_ui()
     382          #----------------------------------------------------------------
     383 -        def __init_ui(self):
     384                  self._PRW_province.selection_only = False
     385          #----------------------------------------------------------------
     386          # generic Edit Area mixin API
     387          #----------------------------------------------------------------
     388 -        def _valid_for_save(self):
     389
     390                  validity = True
     391
     392                  if self._PRW_province.GetData() is None:
     393                          if self._PRW_province.GetValue().strip() == u'':
     394                                  validity = False
     395                                  self._PRW_province.display_as_valid(False)
     396                          else:
     397                                  self._PRW_province.display_as_valid(True)
     398                  else:
     399                          self._PRW_province.display_as_valid(True)
     400
     401                  if self._PRW_province.GetData() is None:
     402                          if self._TCTRL_code.GetValue().strip() == u'':
     403                                  validity = False
     404                                  self._TCTRL_code.SetBackgroundColour(gmPhraseWheel.color_prw_invalid)
     405                          else:
     406                                  self._TCTRL_code.SetBackgroundColour(gmPhraseWheel.color_prw_valid)
     407
     408                  if self._PRW_country.GetData() is None:
     409                          validity = False
     410                          self._PRW_country.display_as_valid(False)
     411                  else:
     412                          self._PRW_country.display_as_valid(True)
     413
     414                  return validity
     415          #----------------------------------------------------------------
     416 -        def _save_as_new(self):
     417                  gmDemographicRecord.create_province (
     418                          name = self._PRW_province.GetValue().strip(),
     419                          code = self._TCTRL_code.GetValue().strip(),
     420                          country = self._PRW_country.GetData()
     421                  )
     422
     423                  # EA is refreshed automatically after save, so need this ...
     424                  self.data = {
     425                          'l10n_state' : self._PRW_province.GetValue().strip(),
     426                          'code_state' : self._TCTRL_code.GetValue().strip(),
     427                          'l10n_country' : self._PRW_country.GetValue().strip(),
     428                          'code_country' : self._PRW_country.GetData().strip()
     429                  }
     430
     431                  return True
     432          #----------------------------------------------------------------
     433 -        def _save_as_update(self):
     434                  # update self.data and save the changes
     435                  #self.data[''] =
     436                  #self.data[''] =
     437                  #self.data[''] =
     438                  #self.data.save()
     439
     440                  # do nothing for now (IOW, don't support updates)
     441                  return True
     442          #----------------------------------------------------------------
     443 -        def _refresh_as_new(self):
     444                  self._PRW_province.SetText()
     445                  self._TCTRL_code.SetValue(u'')
     446                  self._PRW_country.SetText()
     447
     448                  self._PRW_province.SetFocus()
     449          #----------------------------------------------------------------
     450 -        def _refresh_from_existing(self):
     451                  self._PRW_province.SetText(self.data['l10n_state'], self.data['code_state'])
     452                  self._TCTRL_code.SetValue(self.data['code_state'])
     453                  self._PRW_country.SetText(self.data['l10n_country'], self.data['code_country'])
     454
     455                  self._PRW_province.SetFocus()
     456          #----------------------------------------------------------------
     457 -        def _refresh_as_new_from_existing(self):
     458                  self._PRW_province.SetText()
     459                  self._TCTRL_code.SetValue(u'')
     460                  self._PRW_country.SetText(self.data['l10n_country'], self.data['code_country'])
     461
     462                  self._PRW_province.SetFocus()
     463
     464  #============================================================
     465  # other address parts phrasewheels and widgets
     466  #============================================================
     467 -class cZipcodePhraseWheel(gmPhraseWheel.cPhraseWheel):
     468
     469 -        def __init__(self, *args, **kwargs):
     470                  # FIXME: add possible context
     471                  query = u"""(
     472                          SELECT DISTINCT ON (list_label)
     473                                  postcode AS data,
     474                                  postcode || ' (' || name || ')' AS list_label,
     475                                  postcode AS field_label
     476                          FROM dem.street
     477                          WHERE
     478                                  postcode %(fragment_condition)s
     479                          ORDER BY list_label
     480                          LIMIT 20
     481
     482                  ) UNION (
     483
     484                          SELECT DISTINCT ON (list_label)
     485                                  postcode AS data,
     486                                  postcode || ' (' || name || ')' AS list_label,
     487                                  postcode AS field_label
     488                          FROM dem.urb
     489                          WHERE
     490                                  postcode %(fragment_condition)s
     491                          ORDER BY list_label
     492                          LIMIT 20
     493                  )"""
     494                  mp = gmMatchProvider.cMatchProvider_SQL2(queries=query)
     495                  mp.setThresholds(2, 3, 15)
     496                  gmPhraseWheel.cPhraseWheel.__init__(self, *args, **kwargs)
     497                  self.SetToolTipString(_("Type or select a zip code (postcode).\n\nUse e.g. '?' if unknown."))
     498                  self.matcher = mp
     499  #============================================================
     500 -class cStreetPhraseWheel(gmPhraseWheel.cPhraseWheel):
     501
     502 -        def __init__(self, *args, **kwargs):
     503                  context = {
     504                          u'ctxt_zip': {
     505                                  u'where_part': u'AND zip ILIKE %(zip)s',
     506                                  u'placeholder': u'zip'
     507                          }
     508                  }
     509                  query = u"""
     510          SELECT
     511                  data,
     512                  field_label,
     513                  list_label
     514          FROM (
     515
     516                          SELECT DISTINCT ON (data)
     517                                  street AS data,
     518                                  street AS field_label,
     519                                  street || ' (' || zip || ', ' || urb || coalesce(', ' || suburb, '') || ', ' || l10n_country || ')' AS list_label,
     520                                  1 AS rank
     521                          FROM dem.v_zip2data
     522                          WHERE
     523                                  street %(fragment_condition)s
     524                                  %(ctxt_zip)s
     525
     526                  UNION ALL
     527
     528                          SELECT DISTINCT ON (data)
     529                                  name AS data,
     530                                  name AS field_label,
     531                                  name || ' (' || postcode || coalesce(', ' || suburb, '') || ')' AS list_label,
     532                                  2 AS rank
     533                          FROM dem.street
     534                          WHERE
     535                                  name %(fragment_condition)s
     536
     537          ) AS matching_streets
     538          ORDER BY rank, field_label
     539          LIMIT 50"""
     540                  mp = gmMatchProvider.cMatchProvider_SQL2(queries=query, context=context)
     541                  mp.setThresholds(3, 5, 8)
     542                  gmPhraseWheel.cPhraseWheel.__init__(self, *args, **kwargs)
     543                  self.unset_context(context = u'zip')
     544
     545                  self.SetToolTipString(_('Type or select a street.'))
     546                  self.capitalisation_mode = gmTools.CAPS_FIRST
     547                  self.matcher = mp
     548  #============================================================
     549 -class cSuburbPhraseWheel(gmPhraseWheel.cPhraseWheel):
     550
     551 -        def __init__(self, *args, **kwargs):
     552
     553                  query = """
     554  SELECT DISTINCT ON (suburb) suburb, suburb
     555  FROM dem.street
     556  WHERE suburb %(fragment_condition)s
     557  ORDER BY suburb
     558  LIMIT 50
     559  """
     560                  mp = gmMatchProvider.cMatchProvider_SQL2(queries=query)
     561                  mp.setThresholds(2, 3, 6)
     562                  gmPhraseWheel.cPhraseWheel.__init__ (
     563                          self,
     564                          *args,
     565                          **kwargs
     566                  )
     567
     568                  self.SetToolTipString(_('Type or select the suburb.'))
     569                  self.capitalisation_mode = gmTools.CAPS_FIRST
     570                  self.matcher = mp
     571  #============================================================
     572 -class cUrbPhraseWheel(gmPhraseWheel.cPhraseWheel):
     573
     574 -        def __init__(self, *args, **kwargs):
     575                  context = {
     576                          u'ctxt_zip': {
     577                                  u'where_part': u'and zip ilike %(zip)s',
     578                                  u'placeholder': u'zip'
     579                          }
     580                  }
     581                  query = u"""
     582          SELECT DISTINCT ON (rank, data)
     583                  data,
     584                  field_label,
     585                  list_label
     586          FROM (
     587
     588                          SELECT
     589                                  urb AS data,
     590                                  urb AS field_label,
     591                                  urb || ' (' || zip || ', ' || state || ', ' || l10n_country || ')' AS list_label,
     592                                  1 AS rank
     593                          FROM dem.v_zip2data
     594                          WHERE
     595                                  urb %(fragment_condition)s
     596                                  %(ctxt_zip)s
     597
     598                  UNION ALL
     599
     600                          SELECT
     601                                  name AS data,
     602                                  name AS field_label,
     603                                  name || ' (' || postcode ||')' AS list_label,
     604                                  2 AS rank
     605                          FROM dem.urb
     606                          WHERE
     607                                  name %(fragment_condition)s
     608
     609          ) AS matching_urbs
     610          ORDER BY rank, data
     611          LIMIT 50"""
     612                  mp = gmMatchProvider.cMatchProvider_SQL2(queries=query, context=context)
     613                  mp.setThresholds(3, 5, 7)
     614                  gmPhraseWheel.cPhraseWheel.__init__ (
     615                          self,
     616                          *args,
     617                          **kwargs
     618                  )
     619                  self.unset_context(context = u'zip')
     620
     621                  self.SetToolTipString(_('Type or select a city/town/village/dwelling.'))
     622                  self.capitalisation_mode = gmTools.CAPS_FIRST
     623                  self.matcher = mp
     624  #============================================================
     625  # address type related widgets
     626  #============================================================
     627 -class cAddressTypePhraseWheel(gmPhraseWheel.cPhraseWheel):
     628
     629 -        def __init__(self, *args, **kwargs):
     630
     631                  query = u"""
     632  SELECT id, type FROM ((
     633          SELECT id, _(name) AS type, 1 AS rank
     634          FROM dem.address_type
     635          WHERE _(name) %(fragment_condition)s
     636  ) UNION (
     637          SELECT id, name AS type, 2 AS rank
     638          FROM dem.address_type
     639          WHERE name %(fragment_condition)s
     640  )) AS ur
     641  order by
     642          ur.rank, ur.type
     643  """
     644                  mp = gmMatchProvider.cMatchProvider_SQL2(queries=query)
     645                  mp.setThresholds(1, 2, 4)
     646                  mp.word_separators = u'[ \t]+'
     647                  gmPhraseWheel.cPhraseWheel.__init__ (
     648                          self,
     649                          *args,
     650                          **kwargs
     651                  )
     652                  self.matcher = mp
     653                  self.SetToolTipString(_('Select the type of address.'))
     654  #               self.capitalisation_mode = gmTools.CAPS_FIRST
     655                  self.selection_only = True
     656          #--------------------------------------------------------
     657  #       def GetData(self, can_create=False):
     658  #               if self.data is None:
     659  #                       if can_create:
     660  #                               self.data = gmDocuments.create_document_type(self.GetValue().strip())['pk_doc_type']    # FIXME: error handling
     661  #               return self.data
     662
     663  #============================================================
     664  # address phrasewheels and widgets
     665  #============================================================
     666 -def manage_addresses(parent=None):
     667
     668          if parent is None:
     669                  parent = wx.GetApp().GetTopWindow()
     670
     671          #------------------------------------------------------------
     672          def calculate_tooltip(address):
     673                  return u'\n'.join(address.format())
     674          #------------------------------------------------------------
     675          def delete(address):
     676                  return gmDemographicRecord.delete_address(pk_address = address['pk_address'])
     677          #------------------------------------------------------------
     678          def refresh(lctrl):
     679                  adrs = gmDemographicRecord.get_addresses(order_by = u'l10n_country, urb, street, number, subunit')
     680                  items = [ [
     681                                  a['street'],
     682                                  gmTools.coalesce(a['notes_street'], u''),
     683                                  a['number'],
     684                                  gmTools.coalesce(a['subunit'], u''),
     685                                  a['postcode'],
     686                                  a['urb'],
     687                                  gmTools.coalesce(a['suburb'], u''),
     688                                  a['l10n_state'],
     689                                  a['l10n_country'],
     690                                  gmTools.coalesce(a['notes_subunit'], u'')
     691                          ] for a in adrs
     692                  ]
     693                  lctrl.set_string_items(items)
     694                  lctrl.set_data(adrs)
     695
     696          #------------------------------------------------------------
     697          cols = [
     698                  _('Street'),
     699                  _('Street info'),
     700                  _('Number'),
     701                  _('Subunit'),
     702                  _('Postal code'),
     703                  _('Community'),
     704                  _('Suburb'),
     705                  _('Region'),
     706                  _('Country'),
     707                  _('Comment')
     708          ]
     709          return gmListWidgets.get_choices_from_list (
     710                  parent = parent,
     711                  caption = _('Showing addresses registered in GNUmed.'),
     712                  columns = cols,
     713                  single_selection = True,
     714                  refresh_callback = refresh,
     715                  delete_callback = delete,
     716                  list_tooltip_callback = calculate_tooltip
     717          )
     718
     719  #============================================================
     720  from Gnumed.wxGladeWidgets import wxgGenericAddressEditAreaPnl
     721
     722 -class cAddressEAPnl(wxgGenericAddressEditAreaPnl.wxgGenericAddressEditAreaPnl, gmEditArea.cGenericEditAreaMixin):
     723
     724 -        def __init__(self, *args, **kwargs):
     725
     726                  try:
     727                          data = kwargs['address']
     728                          del kwargs['address']
     729                  except KeyError:
     730                          data = None
     731
     732                  self.address_holder = None
     733                  self.__type_is_editable = True
     734                  self.__address_is_searchable = False
     735
     736                  wxgGenericAddressEditAreaPnl.wxgGenericAddressEditAreaPnl.__init__(self, *args, **kwargs)
     737                  gmEditArea.cGenericEditAreaMixin.__init__(self)
     738
     739                  self.type_is_editable = True
     740                  self.address_is_searchable = False
     741
     742                  # Code using this mixin should set mode and data
     743                  # after instantiating the class:
     744                  self.mode = 'new'
     745                  self.data = data
     746                  if data is not None:
     747                          self.mode = 'edit'
     748
     749                  self.__init_ui()
     750          #----------------------------------------------------------------
     751 -        def __init_ui(self):
     752                  self._PRW_zip.add_callback_on_lose_focus(self._on_zip_set)
     753                  self._PRW_country.add_callback_on_lose_focus(self._on_country_set)
     754          #----------------------------------------------------------------
     755          # generic Edit Area mixin API
     756          #----------------------------------------------------------------
     757 -        def _valid_for_save(self):
     758
     759                  validity = True
     760
     761                  # if any field is filled, all must be filled, so track that
     762                  is_any_field_filled = False
     763
     764                  # check by string
     765                  required_fields = [
     766                          self._PRW_urb,
     767                          self._TCTRL_number,
     768                          self._PRW_street,
     769                          self._PRW_zip
     770                  ]
     771                  if self.__type_is_editable:
     772                          required_fields.insert(0, self._PRW_type)
     773                  for field in required_fields:
     774                          if len(field.GetValue().strip()) == 0:
     775                                  if is_any_field_filled:
     776                                          self.display_ctrl_as_valid(field, False)
     777                                          field.SetFocus()
     778                                          gmGuiHelpers.gm_show_error (
     779                                                  _('Address details must be filled in completely or not at all.'),
     780                                                  _('Saving contact data')
     781                                          )
     782                                          validity = False
     783                          else:
     784                                  is_any_field_filled = True
     785                                  self.display_ctrl_as_valid(field, True)
     786
     787                  # check by data
     788                  required_fields = (
     789                          self._PRW_country,
     790                          self._PRW_state
     791                  )
     792                  for field in required_fields:
     793                          if field.GetData() is None:
     794                                  if is_any_field_filled:
     795                                          self.display_ctrl_as_valid(field, False)
     796                                          field.SetFocus()
     797                                          gmGuiHelpers.gm_show_error (
     798                                                  _('Address details must be filled in completely or not at all.'),
     799                                                  _('Saving contact data')
     800                                          )
     801                                          validity = False
     802                          else:
     803                                  is_any_field_filled = True
     804                                  self.display_ctrl_as_valid(field, True)
     805
     806                  return validity
     807          #----------------------------------------------------------------
     808 -        def _save_as_new(self):
     809                  try:
     810                          # will create or return address
     811                          address = gmDemographicRecord.create_address (
     812                                  country = self._PRW_country.GetData(),
     813                                  state = self._PRW_state.GetData(),
     814                                  urb = self._PRW_urb.GetValue().strip(),
     815                                  suburb = gmTools.none_if(self._PRW_suburb.GetValue().strip(), u''),
     816                                  postcode = self._PRW_zip.GetValue().strip(),
     817                                  street = self._PRW_street.GetValue().strip(),
     818                                  number = self._TCTRL_number.GetValue().strip(),
     819                                  subunit = gmTools.none_if(self._TCTRL_subunit.GetValue().strip(), u'')
     820                          )
     821                  except:
     822                          _log.exception('cannot save address')
     823                          gmGuiHelpers.gm_show_error (
     824                                  _('Cannot save address.\n\n'
     825                                    'Does the state [%s]\n'
     826                                    'exist in country [%s] ?'
     827                                  ) % (
     828                                          self._PRW_state.GetValue().strip(),
     829                                          self._PRW_country.GetValue().strip()
     830                                  ),
     831                                  _('Saving address')
     832                          )
     833                          return False
     834
     835                  # link address to holder (there better be one)
     836                  linked_address = self.address_holder.link_address(id_type = self._PRW_type.GetData(), address = address)
     837                  if linked_address['pk_address'] != address['pk_address']:
     838                          raise ValueError('problem linking address to person or org')
     839
     840                  address['notes_street'] = gmTools.none_if(self._TCTRL_notes_street.GetValue().strip(), u'')
     841                  address['notes_subunit'] = gmTools.none_if(self._TCTRL_notes_subunit.GetValue().strip(), u'')
     842                  address.save()
     843
     844                  linked_address.refetch_payload()
     845                  self.data = linked_address
     846
     847                  return True
     848          #----------------------------------------------------------------
     849 -        def _save_as_update(self):
     850                  # do not update existing address, rather
     851                  # create new one or get corresponding
     852                  # address should it exist
     853                  try:
     854                          address = gmDemographicRecord.create_address (
     855                                  country = self._PRW_country.GetData(),
     856                                  state = self._PRW_state.GetData(),
     857                                  urb = self._PRW_urb.GetValue().strip(),
     858                                  suburb = gmTools.none_if(self._PRW_suburb.GetValue().strip(), u''),
     859                                  postcode = self._PRW_zip.GetValue().strip(),
     860                                  street = self._PRW_street.GetValue().strip(),
     861                                  number = self._TCTRL_number.GetValue().strip(),
     862                                  subunit = gmTools.none_if(self._TCTRL_subunit.GetValue().strip(), u'')
     863                          )
     864                  except:
     865                          _log.exception('cannot save address')
     866                          gmGuiHelpers.gm_show_error (
     867                                  _('Cannot save address.\n\n'
     868                                    'Does the state [%s]\n'
     869                                    'exist in country [%s] ?'
     870                                  ) % (
     871                                          self._PRW_state.GetValue().strip(),
     872                                          self._PRW_country.GetValue().strip()
     873                                  ),
     874                                  _('Saving address')
     875                          )
     876                          return False
     877
     878                  # link address to holder (there better be one)
     879                  linked_address = self.address_holder.link_address(id_type = self._PRW_type.GetData(), address = address)
     880                  if linked_address['pk_address'] != address['pk_address']:
     881                          raise ValueError('problem linking address to person or org')
     882
     883                  address['notes_street'] = gmTools.none_if(self._TCTRL_notes_street.GetValue().strip(), u'')
     884                  address['notes_subunit'] = gmTools.none_if(self._TCTRL_notes_subunit.GetValue().strip(), u'')
     885                  address.save()
     886
     887                  linked_address.refetch_payload()
     888                  self.data = linked_address
     889
     890                  return True
     891          #----------------------------------------------------------------
     892 -        def _refresh_as_new(self):
     893                  self._PRW_type.SetText(u'', None)
     894                  self._PRW_zip.SetText(u'', None)
     895                  self._PRW_street.SetText(u'', None)
     896                  self._TCTRL_notes_street.SetValue(u'')
     897                  self._TCTRL_number.SetValue(u'')
     898                  self._TCTRL_subunit.SetValue(u'')
     899                  self._PRW_suburb.SetText(u'', None)
     900                  self._PRW_urb.SetText(u'', None)
     901                  self._PRW_state.SetText(u'', None)
     902                  self._PRW_country.SetText(u'', None)
     903                  self._TCTRL_notes_subunit.SetValue(u'')
     904
     905                  if self.__type_is_editable:
     906                          self._PRW_type.SetFocus()
     907                  else:
     908                          self._PRW_zip.SetFocus()
     909          #----------------------------------------------------------------
     910 -        def _refresh_as_new_from_existing(self):
     911                  self._refresh_as_new()
     912
     913                  self._PRW_zip.SetText(self.data['postcode'])
     914                  self._PRW_street.SetText(self.data['street'], data = self.data['street'])
     915                  self._PRW_suburb.SetText(gmTools.coalesce(self.data['suburb'], ''))
     916                  self._PRW_urb.SetText(self.data['urb'], data = self.data['urb'])
     917                  self._PRW_state.SetText(self.data['l10n_state'], data = self.data['code_state'])
     918                  self._PRW_country.SetText(self.data['l10n_country'], data = self.data['code_country'])
     919
     920                  if self.__type_is_editable:
     921                          self._PRW_type.SetFocus()
     922                  else:
     923                          self._TCTRL_number.SetFocus()
     924          #----------------------------------------------------------------
     925 -        def _refresh_from_existing(self):
     926                  if self.__type_is_editable:
     927                          self._PRW_type.SetText(self.data['l10n_address_type'])
     928                  else:
     929                          self._PRW_type.SetText(u'', None)
     930                  self._PRW_zip.SetText(self.data['postcode'])
     931                  self._PRW_street.SetText(self.data['street'], data = self.data['street'])
     932                  self._TCTRL_notes_street.SetValue(gmTools.coalesce(self.data['notes_street'], ''))
     933                  self._TCTRL_number.SetValue(self.data['number'])
     934                  self._TCTRL_subunit.SetValue(gmTools.coalesce(self.data['subunit'], ''))
     935                  self._PRW_suburb.SetText(gmTools.coalesce(self.data['suburb'], ''))
     936                  self._PRW_urb.SetText(self.data['urb'], data = self.data['urb'])
     937                  self._PRW_state.SetText(self.data['l10n_state'], data = self.data['code_state'])
     938                  self._PRW_country.SetText(self.data['l10n_country'], data = self.data['code_country'])
     939                  self._TCTRL_notes_subunit.SetValue(gmTools.coalesce(self.data['notes_subunit'], ''))
     940
     941                  if self.__type_is_editable:
     942                          self._PRW_type.SetFocus()
     943                  else:
     944                          self._PRW_zip.SetFocus()
     945          #----------------------------------------------------------------
     946          # event handling
     947          #----------------------------------------------------------------
     948 -        def _on_zip_set(self):
     949                  """Set the street, town, state and country according to entered zip code."""
     950                  zip_code = self._PRW_zip.GetValue()
     951                  if zip_code.strip() == u'':
     952                          self._PRW_street.unset_context(context = u'zip')
     953                          self._PRW_urb.unset_context(context = u'zip')
     954                          self._PRW_state.unset_context(context = u'zip')
     955                          self._PRW_country.unset_context(context = u'zip')
     956                  else:
     957                          self._PRW_street.set_context(context = u'zip', val = zip_code)
     958                          self._PRW_urb.set_context(context = u'zip', val = zip_code)
     959                          self._PRW_state.set_context(context = u'zip', val = zip_code)
     960                          self._PRW_country.set_context(context = u'zip', val = zip_code)
     961          #----------------------------------------------------------------
     962 -        def _on_country_set(self):
     963                  """Set the states according to entered country."""
     964                  country = self._PRW_country.GetData()
     965                  if country is None:
     966                          self._PRW_state.unset_context(context = 'country')
     967                  else:
     968                          self._PRW_state.set_context(context = 'country', val = country)
     969          #----------------------------------------------------------------
     970          # properties
     971          #----------------------------------------------------------------
     972 -        def _get_type_is_editable(self):
     973                  return self.__type_is_editable
     974
     975 -        def _set_type_is_editable(self, type_is_editable):
     976                  self.__type_is_editable = type_is_editable
     977                  self._PRW_type.Enable(type_is_editable)
     978                  self._PRW_type.Show(type_is_editable)
     979                  self._LBL_type.Show(type_is_editable)
     980
     981          type_is_editable = property(_get_type_is_editable, _set_type_is_editable)
     982          #----------------------------------------------------------------
     983 -        def _get_address_is_searchable(self):
     984                  return self.__address_is_searchable
     985
     986 -        def _set_address_is_searchable(self, address_is_searchable):
     987                  # FIXME: always set to FALSE when self.mode == 'new' ?
     988                  self.__address_is_searchable = address_is_searchable
     989                  self._PRW_address_searcher.Enable(address_is_searchable)
     990                  self._PRW_address_searcher.Show(address_is_searchable)
     991                  self._LBL_search.Show(address_is_searchable)
     992
     993          address_is_searchable = property(_get_address_is_searchable, _set_address_is_searchable)
     994          #----------------------------------------------------------------
     995 -        def _get_address(self):
     996                  return self.data
     997
     998 -        def _set_address(self, address):
     999                  self.data = address
    1000
    1001          address = property(_get_address, _set_address)
    1002
    1003  #============================================================
    1004 -class cAddressMatchProvider(gmMatchProvider.cMatchProvider_SQL2):
    1005
    1006 -        def __init__(self):
    1007
    1008                  query = u"""
    1009  SELECT * FROM (
    1010          (SELECT
    1011                  pk_address AS data,
    1012                  (street || ' ' || number || coalesce(' (' || subunit || ')', '') || ', '
    1013                                  || urb || coalesce(' (' || suburb || ')', '') || ', '
    1014                                  || postcode || ', '
    1015                                  || code_country
    1016                  ) AS field_label,
    1017                  (street || ' ' || number || coalesce(' (' || subunit || ')', '') || ', '
    1018                                  || urb || coalesce(' (' || suburb || ')', '') || ', '
    1019                                  || postcode || ', '
    1020                                  || l10n_state || ', '
    1021                                  || l10n_country
    1022                                  || coalesce(', ' || notes_street, '')
    1023                                  || coalesce(', ' || notes_subunit, '')
    1024                  ) AS list_label
    1025          FROM
    1026                  dem.v_address
    1027          WHERE
    1028                  street %(fragment_condition)s
    1029
    1030          ) UNION (
    1031
    1032          SELECT
    1033                  pk_address AS data,
    1034                  (street || ' ' || number || coalesce(' (' || subunit || ')', '') || ', '
    1035                                  || urb || coalesce(' (' || suburb || ')', '') || ', '
    1036                                  || postcode || ', '
    1037                                  || code_country
    1038                  ) AS field_label,
    1039                  (street || ' ' || number || coalesce(' (' || subunit || ')', '') || ', '
    1040                                  || urb || coalesce(' (' || suburb || ')', '') || ', '
    1041                                  || postcode || ', '
    1042                                  || l10n_state || ', '
    1043                                  || l10n_country
    1044                                  || coalesce(', ' || notes_street, '')
    1045                                  || coalesce(', ' || notes_subunit, '')
    1046                  ) AS list_label
    1047          FROM
    1048                  dem.v_address
    1049          WHERE
    1050                  postcode_street %(fragment_condition)s
    1051
    1052          ) UNION (
    1053
    1054          SELECT
    1055                  pk_address AS data,
    1056                  (street || ' ' || number || coalesce(' (' || subunit || ')', '') || ', '
    1057                                  || urb || coalesce(' (' || suburb || ')', '') || ', '
    1058                                  || postcode || ', '
    1059                                  || code_country
    1060                  ) AS field_label,
    1061                  (street || ' ' || number || coalesce(' (' || subunit || ')', '') || ', '
    1062                                  || urb || coalesce(' (' || suburb || ')', '') || ', '
    1063                                  || postcode || ', '
    1064                                  || l10n_state || ', '
    1065                                  || l10n_country
    1066                                  || coalesce(', ' || notes_street, '')
    1067                                  || coalesce(', ' || notes_subunit, '')
    1068                  ) AS list_label
    1069          FROM
    1070                  dem.v_address
    1071          WHERE
    1072                  postcode_urb %(fragment_condition)s
    1073          )
    1074  ) AS matching_addresses
    1075  ORDER BY list_label
    1076  LIMIT 50"""
    1077
    1078                  gmMatchProvider.cMatchProvider_SQL2.__init__(self, queries = query)
    1079
    1080                  self.setThresholds(2, 4, 6)
    1081  #               self.word_separators = u'[ \t]+'
    1082
    1083                  self._SQL_data2match = u"""
    1084          SELECT
    1085                  pk_address AS data,
    1086                  (street || ' ' || number || coalesce(' (' || subunit || ')', '') || ', '
    1087                                  || urb || coalesce(' (' || suburb || ')', '') || ', '
    1088                                  || postcode || ', '
    1089                                  || code_country
    1090                  ) AS field_label,
    1091                  (street || ' ' || number || coalesce(' (' || subunit || ')', '') || ', '
    1092                                  || urb || coalesce(' (' || suburb || ')', '') || ', '
    1093                                  || postcode || ', '
    1094                                  || l10n_state || ', '
    1095                                  || l10n_country
    1096                                  || coalesce(', ' || notes_street, '')
    1097                                  || coalesce(', ' || notes_subunit, '')
    1098                  ) AS list_label
    1099          FROM
    1100                  dem.v_address
    1101          WHERE
    1102                  pk_address = %(pk)s
    1103          """
    1104
    1105  #============================================================
    1106 -class cAddressPhraseWheel(gmPhraseWheel.cPhraseWheel):
    1107
    1108 -        def __init__(self, *args, **kwargs):
    1109
    1110                  gmPhraseWheel.cPhraseWheel.__init__(self, *args, **kwargs)
    1111                  self.matcher = cAddressMatchProvider()
    1112                  self.SetToolTipString(_('Select an address by postcode or street name.'))
    1113                  self.selection_only = True
    1114                  self.__address = None
    1115                  self.__old_pk = None
    1116          #--------------------------------------------------------
    1117 -        def _get_data_tooltip(self):
    1118                  adr = self.address
    1119                  if adr is None:
    1120                          return None
    1121                  return u'\n'.join(adr.format())
    1122          #--------------------------------------------------------
    1123 -        def _data2instance(self):
    1124                  return gmDemographicRecord.cAddress(aPK_obj = self.GetData())
    1125          #--------------------------------------------------------
    1126          # properties
    1127          #--------------------------------------------------------
    1128 -        def __get_address(self):
    1129                  pk = self.GetData()
    1130                  if pk is None:
    1131                          self.__address = None
    1132                          return None
    1133                  if self.__address is None:
    1134                          self.__old_pk = pk
    1135                          self.__address = gmDemographicRecord.cAddress(aPK_obj = pk)
    1136                  else:
    1137                          if pk != self.__old_pk:
    1138                                  self.__old_pk = pk
    1139                                  self.__address = gmDemographicRecord.cAddress(aPK_obj = pk)
    1140                  return self.__address
    1141
    1142 -        def __set_address(self, address):
    1143                  if address is None:
    1144                          self.__old_pk = None
    1145                          self.__address = None
    1146                          self.SetText(u'', None)
    1147                          return
    1148                  if isinstance(address, gmDemographicRecord.cAddress):
    1149                          self.__old_pk = address['pk_address']
    1150                          self.__address = address
    1151                          pk = self.__old_pk
    1152                  else:
    1153                          self.__old_pk = None
    1154                          self.__address = None
    1155                          pk = address
    1156                  match = self.matcher.get_match_by_data(data = pk)
    1157                  if match is None:
    1158                          raise ValueError(u'[%s]: cannot match address [#%s]' % (self.__class__.__name__, pk))
    1159                  self.SetText(match['field_label'], pk)
    1160
    1161          address = property(__get_address, __set_address)
    1162          #--------------------------------------------------------
    1163 -        def __get_person_address(self):
    1164                  pk = self.GetData()
    1165                  if pk is None:
    1166                          self.__address = None
    1167                          return None
    1168                  if self.__address is None:
    1169                          self.__old_pk = pk
    1170                          self.__address = gmDemographicRecord.cPatientAddress(aPK_obj = pk)
    1171                  else:
    1172                          if pk != self.__old_pk:
    1173                                  self.__old_pk = pk
    1174                                  self.__address = gmDemographicRecord.cPatientAddress(aPK_obj = pk)
    1175                  return self.__address
    1176
    1177          person_address = property(__get_person_address, lambda x:x)
    1178  #================================================================
    1179  # main
    1180  #----------------------------------------------------------------
    1181  if __name__ == '__main__':
    1182
    1183          if len(sys.argv) < 2:
    1184                  sys.exit()
    1185
    1186          if sys.argv[1] != 'test':
    1187                  sys.exit()
    1188
    1189          from Gnumed.pycommon import gmI18N
    1190          gmI18N.activate_locale()
    1191          gmI18N.install_domain()
    1192          from Gnumed.business import gmPersonSearch
    1193
    1194          #--------------------------------------------------------
    1195 -        def test_country_prw():
    1196                  app = wx.PyWidgetTester(size = (200, 50))
    1197                  pw = cCountryPhraseWheel(app.frame, -1)
    1198                  app.frame.Show(True)
    1199                  app.MainLoop()
    1200          #--------------------------------------------------------
    1201 -        def test_state_prw():
    1202                  app = wx.PyWidgetTester(size = (200, 50))
    1203                  pw = cStateSelectionPhraseWheel(app.frame, -1)
    1204                  pw.set_context(context = u'zip', val = u'04318')
    1205                  pw.set_context(context = u'country', val = u'Deutschland')
    1206                  app.frame.Show(True)
    1207                  app.MainLoop()
    1208          #--------------------------------------------------------
    1209 -        def test_zipcode_prw():
    1210                  app = wx.PyWidgetTester(size = (200, 50))
    1211                  pw = cZipcodePhraseWheel(app.frame, -1)
    1212                  app.frame.Show(True)
    1213                  app.MainLoop()
    1214          #--------------------------------------------------------
    1215 -        def test_street_prw():
    1216                  app = wx.PyWidgetTester(size = (200, 50))
    1217                  pw = cStreetPhraseWheel(app.frame, -1)
    1218  #               pw.set_context(context = u'zip', val = u'04318')
    1219                  app.frame.Show(True)
    1220                  app.MainLoop()
    1221          #--------------------------------------------------------
    1222 -        def test_suburb_prw():
    1223                  app = wx.PyWidgetTester(size = (200, 50))
    1224                  pw = cSuburbPhraseWheel(app.frame, -1)
    1225                  app.frame.Show(True)
    1226                  app.MainLoop()
    1227          #--------------------------------------------------------
    1228 -        def test_urb_prw():
    1229                  app = wx.PyWidgetTester(size = (200, 50))
    1230                  pw = cUrbPhraseWheel(app.frame, -1)
    1231                  app.frame.Show(True)
    1232                  pw.set_context(context = u'zip', val = u'04317')
    1233                  app.MainLoop()
    1234          #--------------------------------------------------------
    1235 -        def test_address_type_prw():
    1236                  app = wx.PyWidgetTester(size = (200, 50))
    1237                  pw = cAddressTypePhraseWheel(app.frame, -1)
    1238                  app.frame.Show(True)
    1239                  app.MainLoop()
    1240          #--------------------------------------------------------
    1241 -        def test_address_prw():
    1242                  app = wx.PyWidgetTester(size = (200, 50))
    1243                  pw = cAddressPhraseWheel(app.frame, -1)
    1244                  app.frame.Show(True)
    1245                  app.MainLoop()
    1246          #--------------------------------------------------------
    1247 -        def test_address_ea_pnl():
    1248                  app = wx.PyWidgetTester(size = (600, 400))
    1249                  app.SetWidget(cAddressEditAreaPnl, address = gmDemographicRecord.cAddress(aPK_obj = 1))
    1250                  app.MainLoop()
    1251          #--------------------------------------------------------
    1252          #test_address_type_prw()
    1253          #test_zipcode_prw()
    1254          #test_state_prw()
    1255          #test_street_prw()
    1256          #test_suburb_prw()
    1257          #test_country_prw()
    1258          #test_urb_prw()
    1259          #test_address_ea_pnl()
    1260          test_address_prw()
    1261
    1262  #================================================================
    1263