[med-svn] [Git][med-team/gnumed-client][upstream] New upstream version 1.8.16+dfsg

Andreas Tille (@tille) gitlab at salsa.debian.org
Tue Nov 28 08:42:40 GMT 2023



Andreas Tille pushed to branch upstream at Debian Med / gnumed-client


Commits:
11e8dec4 by Andreas Tille at 2023-11-28T08:44:20+01:00
New upstream version 1.8.16+dfsg
- - - - -


14 changed files:

- client/CHANGELOG
- client/business/gmDataMining.py
- client/doc/api/gmPersonSearch.html
- client/doc/schema/gnumed-entire_schema-no_audit.dot
- client/doc/schema/gnumed-entire_schema.html
- client/gnumed.py
- client/wxGladeWidgets/wxgCurrentSubstancesPnl.py
- − client/wxGladeWidgets/wxgIncomingPluginPnl.py
- client/wxGladeWidgets/wxgMeasurementsAsTablePnl.py
- client/wxGladeWidgets/wxgMeasurementsByBatteryPnl.py
- client/wxGladeWidgets/wxgMeasurementsPnl.py
- client/wxGladeWidgets/wxgPACSPluginPnl.py
- client/wxpython/gmGuiMain.py
- client/wxpython/gmMedicationWidgets.py


Changes:

=====================================
client/CHANGELOG
=====================================
@@ -6,6 +6,14 @@
 # rel-1-8-patches
 ------------------------------------------------
 
+	1.8.16
+
+FIX: SQL plugin: exception on faulty query
+FIX: meds plugin: grid selection constant names
+FIX: gtk: do not abort on sizer flags inconsistencies in production code
+
+IMPROVED: plugin PACS: layout
+
 	1.8.15
 
 IMPROVED: person search: query speed


=====================================
client/business/gmDataMining.py
=====================================
@@ -105,7 +105,7 @@ def run_report_query(query=None, limit=None, pk_identity=None):
 			[''],
 			[str(t)]
 		]
-		for line in str(v).decode(gmI18N.get_encoding()).split('\n'):
+		for line in str(v).split('\n'):
 			rows.append([line])
 		rows.append([''])
 		for line in query.split('\n'):


=====================================
client/doc/api/gmPersonSearch.html
=====================================
@@ -60,6 +60,10 @@ ext ID:
 '…moY'
 '…Nar'
 '…Ear'</p>
+<p>find patient by several name parts:
+'leon nim'
+'spo zal'
+'leon nim zald'</p>
 <p>find patient by GNUmed ID:
 '12345678' (also searches by DOB)
 '#12345678' (also searches by external ID)</p>
@@ -121,6 +125,11 @@ ext ID:
                 '...Nar'
                 '...Ear'
 
+        find patient by several name parts:
+                'leon nim'
+                'spo zal'
+                'leon nim zald'
+
         find patient by GNUmed ID:
                 '12345678' (also searches by DOB)
                 '#12345678' (also searches by external ID)
@@ -323,52 +332,52 @@ class cPatientSearcher_SQL:
         #--------------------------------------------------------
         def __queries_for_firstname_with_comma(self, raw):
                 """Generate search queries for [ , <alpha> ] search terms."""
-                if regex.match(",\s*\w+$", raw.strip()) is None:
+                if not raw.startswith(','):
+                        return []
+
+                raw = raw.lstrip(' ,')
+                if not raw.isalpha():
                         return []
+
                 _log.debug("[%s]: a firstname" % raw)
-                tmp = self._normalize_soundalikes(raw.strip(' ,'))
-                cmd = """
+                normalized = self._normalize_soundalikes(raw)
+                cmd = """-- find patients by ",firstname"
                         SELECT DISTINCT ON (pk_identity) * FROM (
-                                SELECT *, %(match)s AS match_type FROM ((
-                                        SELECT d_vap.*
-                                        FROM dem.names, dem.v_active_persons d_vap
-                                        WHERE dem.names.firstnames ~ %(first)s and d_vap.pk_identity = dem.names.id_identity
-                                ) union all (
-                                        SELECT d_vap.*
-                                        FROM dem.names, dem.v_active_persons d_vap
-                                        WHERE dem.names.firstnames ~ %(first_w_caps)s and d_vap.pk_identity = dem.names.id_identity
-                                ) union all (
+                                SELECT *, %(match)s AS match_type FROM (
                                         SELECT d_vap.*
                                         FROM dem.names, dem.v_active_persons d_vap
-                                        WHERE lower(dem.names.firstnames) ~ lower(%(first)s) and d_vap.pk_identity = dem.names.id_identity
-                                )) AS super_list ORDER BY lastnames, firstnames, dob
+                                        WHERE dem.names.firstnames ~* %(first)s and d_vap.pk_identity = dem.names.id_identity
+                                ) AS super_list ORDER BY lastnames, firstnames, dob
                         ) AS sorted_list"""
                 args = {
                         'match': _('first name'),
-                        'first': '\m' + tmp,
-                        'first_w_caps': '\m' + gmTools.capitalize(tmp, mode = gmTools.CAPS_NAMES)
+                        'first': '\m' + normalized
                 }
                 return [{'cmd': cmd, 'args': args}]
 
         #--------------------------------------------------------
         def __queries_for_lastname_with_comma(self, raw):
                 """Generate search queries for [ <alpha> , ] search terms."""
-                if regex.match("\w+\s*,$", raw) is None:
+                if not raw.endswith(','):
+                        return []
+
+                raw = raw.rstrip(' ,')
+                if not raw.isalpha():
                         return []
+
                 _log.debug("[%s]: a lastname" % raw)
-                normalized = self._normalize_soundalikes(raw.strip(' ,'))
+                normalized = self._normalize_soundalikes(raw)
                 cmd = """-- find patients by "lastname,":
                         SELECT DISTINCT ON (pk_identity) * FROM (
                                 SELECT *, %(match)s AS match_type FROM ((
                                         SELECT d_vap.*
                                         FROM dem.names, dem.v_active_persons d_vap
-                                        WHERE lower(dem.names.lastnames) ~ lower(%(last)s) and d_vap.pk_identity = dem.names.id_identity
+                                        WHERE dem.names.lastnames ~* %(last)s and d_vap.pk_identity = dem.names.id_identity
                                 )) AS super_list ORDER BY lastnames, firstnames, dob
                         ) AS sorted_list"""
                 args = {
                         'match': _('last name'),
-                        'last': '\m%s' % normalized,
-#                       'last_w_caps': '^' + gmTools.capitalize(tmp, mode=gmTools.CAPS_NAMES)
+                        'last': '\m%s' % normalized
                 }
                 return [{'cmd': cmd, 'args': args}]
 
@@ -379,7 +388,6 @@ class cPatientSearcher_SQL:
                         return []
 
                 if raw != raw.upper():
-                        # not all UPPERCASE
                         return []
 
                 _log.debug("[%s]: a lastname" % raw)
@@ -400,6 +408,9 @@ class cPatientSearcher_SQL:
 
         #--------------------------------------------------------
         def __queries_for_name_fragment(self, raw):
+                if not raw.startswith('...'):
+                        return []
+
                 raw = raw.lstrip('.')
                 if not raw.isalpha():
                         return []
@@ -452,6 +463,9 @@ class cPatientSearcher_SQL:
                 if not raw.isalpha():
                         return []
 
+                if len(raw) < 3:
+                        return []
+
                 _log.debug("[%s]: a singular name part" % raw)
                 name = self._normalize_soundalikes(raw)
                 SQL = """-- find patients by name part even inside multi-part names:
@@ -469,28 +483,82 @@ class cPatientSearcher_SQL:
                 }
                 return [{'cmd': SQL, 'args': args}]
 
+        #--------------------------------------------------------
+        def __queries_for_several_name_parts(self, raw):
+                parts = regex.split('[,\.\-\s]+', raw)
+                print(parts)
+                for p in parts:
+                        if not p.isalpha():
+                                return []
+
+                parts = [ p for p in parts if len(p) > 1 ]
+                if len(parts) < 2:
+                        return []
+
+                _log.debug("[%s]: several name parts" % parts)
+                parts = [ '\m' + self._normalize_soundalikes(p) for p in parts ]
+                SQL = """-- find patients by name parts even inside multi-part names:
+                        SELECT DISTINCT ON (pk_identity) * FROM (
+                                SELECT *, %(match)s AS match_type FROM (
+                                        SELECT d_vap.*
+                                        FROM dem.names JOIN dem.v_active_persons d_vap ON (d_vap.pk_identity = dem.names.id_identity)
+                                        WHERE dem.names.lastnames ~* ANY(%(parts)s) AND dem.names.firstnames ~* ANY(%(parts)s)
+                                        -- AND dem.names.preferred ~* ANY(%(parts)s)
+                                ) AS super_list
+                                ORDER BY lastnames, firstnames, dob
+                        ) AS sorted_list"""
+                args = {
+                        'match': _('name parts'),
+                        'parts': parts
+                }
+                return [{'cmd': SQL, 'args': args}]
+
         #--------------------------------------------------------
         def __queries_for_LAST_and_first(self, raw):
                 """Generate search queries for [ <ALPHA> <alpha> ] or [ <alpha> <ALPHA> ] search terms."""
-                if regex.match("\w+\s+\w+$", raw) is None:
+#               if regex.match('^\w+\s+\w+$', raw) is None:
+#                       return []
+#               if raw == raw.upper():
+#                       # ALL caps
+#                       return []
+#               if raw == raw.lower():
+#                       # ALL lowercase
+#                       return []
+#               parts = [ p for p in regex.split('\s+', raw) ]
+                parts = raw.split()
+                if len(parts) != 2:
                         return []
-                if raw == raw.upper():
-                        # ALL caps
+
+                for p in parts:
+                        if not p.isalpha():
+                                return []
+
+                p1_upcase = parts[0] == parts[0].upper()
+                p2_upcase = parts[1] == parts[1].upper()
+                if p1_upcase and p2_upcase:
                         return []
-                if raw == raw.casefold():
-                        # ALL lowercase
+
+                if True not in [p1_upcase, p2_upcase]:
                         return []
-                parts = [ p for p in regex.split('\s+', raw) ]
-                last = None
-                if parts[0] == parts[0].upper():
+
+                if p1_upcase:
                         last = parts[0]
                         first = parts[1]
-                if parts[1] == parts[1].upper():
+                else:
                         last = parts[1]
                         first = parts[0]
+
+#               last = None
+#               if parts[0] == parts[0].upper():
+#                       last = parts[0]
+#                       first = parts[1]
+#               if parts[1] == parts[1].upper():
+#                       last = parts[1]
+#                       first = parts[0]
                 # found no UPPERCASE
-                if last is None:
-                        return []
+#               if last is None:
+#                       return []
+
                 _log.debug("[%s]: <LASTNAME firstname> or firstname LASTNAME" % raw)
                 last = self._normalize_soundalikes(last)
                 first = self._normalize_soundalikes(first)
@@ -674,6 +742,11 @@ class cPatientSearcher_SQL:
                 if queries:
                         return queries
 
+                # "<alpha> <alpha> <alpha> ..." - first OR last name OR nick
+                queries = self.__queries_for_several_name_parts(raw)
+                if queries:
+                        return queries
+
                 return []
 
         #--------------------------------------------------------
@@ -1268,6 +1341,7 @@ if __name__ == '__main__':
                 print("testing generate_simple_query()")
                 print("----------------------------")
                 data = [
+                        'jam tib, kir',
                         '...tiber',
                         '...iber',
                         'kirk',
@@ -1304,9 +1378,9 @@ if __name__ == '__main__':
         #--------------------------------------------------------
         gmPG2.request_login_params(setup_pool = True)
 
-        test_generate_simple_query()
+        #test_generate_simple_query()
         #test_patient_search_queries()
-        #test_ask_for_patient()
+        test_ask_for_patient()
         #test_search_by_dto()
 
 #============================================================</code></pre>
@@ -1536,52 +1610,52 @@ if __name__ == '__main__':
         #--------------------------------------------------------
         def __queries_for_firstname_with_comma(self, raw):
                 """Generate search queries for [ , <alpha> ] search terms."""
-                if regex.match(",\s*\w+$", raw.strip()) is None:
+                if not raw.startswith(','):
+                        return []
+
+                raw = raw.lstrip(' ,')
+                if not raw.isalpha():
                         return []
+
                 _log.debug("[%s]: a firstname" % raw)
-                tmp = self._normalize_soundalikes(raw.strip(' ,'))
-                cmd = """
+                normalized = self._normalize_soundalikes(raw)
+                cmd = """-- find patients by ",firstname"
                         SELECT DISTINCT ON (pk_identity) * FROM (
-                                SELECT *, %(match)s AS match_type FROM ((
-                                        SELECT d_vap.*
-                                        FROM dem.names, dem.v_active_persons d_vap
-                                        WHERE dem.names.firstnames ~ %(first)s and d_vap.pk_identity = dem.names.id_identity
-                                ) union all (
-                                        SELECT d_vap.*
-                                        FROM dem.names, dem.v_active_persons d_vap
-                                        WHERE dem.names.firstnames ~ %(first_w_caps)s and d_vap.pk_identity = dem.names.id_identity
-                                ) union all (
+                                SELECT *, %(match)s AS match_type FROM (
                                         SELECT d_vap.*
                                         FROM dem.names, dem.v_active_persons d_vap
-                                        WHERE lower(dem.names.firstnames) ~ lower(%(first)s) and d_vap.pk_identity = dem.names.id_identity
-                                )) AS super_list ORDER BY lastnames, firstnames, dob
+                                        WHERE dem.names.firstnames ~* %(first)s and d_vap.pk_identity = dem.names.id_identity
+                                ) AS super_list ORDER BY lastnames, firstnames, dob
                         ) AS sorted_list"""
                 args = {
                         'match': _('first name'),
-                        'first': '\m' + tmp,
-                        'first_w_caps': '\m' + gmTools.capitalize(tmp, mode = gmTools.CAPS_NAMES)
+                        'first': '\m' + normalized
                 }
                 return [{'cmd': cmd, 'args': args}]
 
         #--------------------------------------------------------
         def __queries_for_lastname_with_comma(self, raw):
                 """Generate search queries for [ <alpha> , ] search terms."""
-                if regex.match("\w+\s*,$", raw) is None:
+                if not raw.endswith(','):
                         return []
+
+                raw = raw.rstrip(' ,')
+                if not raw.isalpha():
+                        return []
+
                 _log.debug("[%s]: a lastname" % raw)
-                normalized = self._normalize_soundalikes(raw.strip(' ,'))
+                normalized = self._normalize_soundalikes(raw)
                 cmd = """-- find patients by "lastname,":
                         SELECT DISTINCT ON (pk_identity) * FROM (
                                 SELECT *, %(match)s AS match_type FROM ((
                                         SELECT d_vap.*
                                         FROM dem.names, dem.v_active_persons d_vap
-                                        WHERE lower(dem.names.lastnames) ~ lower(%(last)s) and d_vap.pk_identity = dem.names.id_identity
+                                        WHERE dem.names.lastnames ~* %(last)s and d_vap.pk_identity = dem.names.id_identity
                                 )) AS super_list ORDER BY lastnames, firstnames, dob
                         ) AS sorted_list"""
                 args = {
                         'match': _('last name'),
-                        'last': '\m%s' % normalized,
-#                       'last_w_caps': '^' + gmTools.capitalize(tmp, mode=gmTools.CAPS_NAMES)
+                        'last': '\m%s' % normalized
                 }
                 return [{'cmd': cmd, 'args': args}]
 
@@ -1592,7 +1666,6 @@ if __name__ == '__main__':
                         return []
 
                 if raw != raw.upper():
-                        # not all UPPERCASE
                         return []
 
                 _log.debug("[%s]: a lastname" % raw)
@@ -1613,6 +1686,9 @@ if __name__ == '__main__':
 
         #--------------------------------------------------------
         def __queries_for_name_fragment(self, raw):
+                if not raw.startswith('...'):
+                        return []
+
                 raw = raw.lstrip('.')
                 if not raw.isalpha():
                         return []
@@ -1665,6 +1741,9 @@ if __name__ == '__main__':
                 if not raw.isalpha():
                         return []
 
+                if len(raw) < 3:
+                        return []
+
                 _log.debug("[%s]: a singular name part" % raw)
                 name = self._normalize_soundalikes(raw)
                 SQL = """-- find patients by name part even inside multi-part names:
@@ -1682,28 +1761,82 @@ if __name__ == '__main__':
                 }
                 return [{'cmd': SQL, 'args': args}]
 
+        #--------------------------------------------------------
+        def __queries_for_several_name_parts(self, raw):
+                parts = regex.split('[,\.\-\s]+', raw)
+                print(parts)
+                for p in parts:
+                        if not p.isalpha():
+                                return []
+
+                parts = [ p for p in parts if len(p) > 1 ]
+                if len(parts) < 2:
+                        return []
+
+                _log.debug("[%s]: several name parts" % parts)
+                parts = [ '\m' + self._normalize_soundalikes(p) for p in parts ]
+                SQL = """-- find patients by name parts even inside multi-part names:
+                        SELECT DISTINCT ON (pk_identity) * FROM (
+                                SELECT *, %(match)s AS match_type FROM (
+                                        SELECT d_vap.*
+                                        FROM dem.names JOIN dem.v_active_persons d_vap ON (d_vap.pk_identity = dem.names.id_identity)
+                                        WHERE dem.names.lastnames ~* ANY(%(parts)s) AND dem.names.firstnames ~* ANY(%(parts)s)
+                                        -- AND dem.names.preferred ~* ANY(%(parts)s)
+                                ) AS super_list
+                                ORDER BY lastnames, firstnames, dob
+                        ) AS sorted_list"""
+                args = {
+                        'match': _('name parts'),
+                        'parts': parts
+                }
+                return [{'cmd': SQL, 'args': args}]
+
         #--------------------------------------------------------
         def __queries_for_LAST_and_first(self, raw):
                 """Generate search queries for [ <ALPHA> <alpha> ] or [ <alpha> <ALPHA> ] search terms."""
-                if regex.match("\w+\s+\w+$", raw) is None:
+#               if regex.match('^\w+\s+\w+$', raw) is None:
+#                       return []
+#               if raw == raw.upper():
+#                       # ALL caps
+#                       return []
+#               if raw == raw.lower():
+#                       # ALL lowercase
+#                       return []
+#               parts = [ p for p in regex.split('\s+', raw) ]
+                parts = raw.split()
+                if len(parts) != 2:
                         return []
-                if raw == raw.upper():
-                        # ALL caps
+
+                for p in parts:
+                        if not p.isalpha():
+                                return []
+
+                p1_upcase = parts[0] == parts[0].upper()
+                p2_upcase = parts[1] == parts[1].upper()
+                if p1_upcase and p2_upcase:
                         return []
-                if raw == raw.casefold():
-                        # ALL lowercase
+
+                if True not in [p1_upcase, p2_upcase]:
                         return []
-                parts = [ p for p in regex.split('\s+', raw) ]
-                last = None
-                if parts[0] == parts[0].upper():
+
+                if p1_upcase:
                         last = parts[0]
                         first = parts[1]
-                if parts[1] == parts[1].upper():
+                else:
                         last = parts[1]
                         first = parts[0]
+
+#               last = None
+#               if parts[0] == parts[0].upper():
+#                       last = parts[0]
+#                       first = parts[1]
+#               if parts[1] == parts[1].upper():
+#                       last = parts[1]
+#                       first = parts[0]
                 # found no UPPERCASE
-                if last is None:
-                        return []
+#               if last is None:
+#                       return []
+
                 _log.debug("[%s]: <LASTNAME firstname> or firstname LASTNAME" % raw)
                 last = self._normalize_soundalikes(last)
                 first = self._normalize_soundalikes(first)
@@ -1887,6 +2020,11 @@ if __name__ == '__main__':
                 if queries:
                         return queries
 
+                # "<alpha> <alpha> <alpha> ..." - first OR last name OR nick
+                queries = self.__queries_for_several_name_parts(raw)
+                if queries:
+                        return queries
+
                 return []
 
         #--------------------------------------------------------
@@ -2417,6 +2555,11 @@ SELECT DISTINCT ON (pk_identity) * FROM (
         if queries:
                 return queries
 
+        # "<alpha> <alpha> <alpha> ..." - first OR last name OR nick
+        queries = self.__queries_for_several_name_parts(raw)
+        if queries:
+                return queries
+
         return []</code></pre>
 </details>
 </dd>


=====================================
client/doc/schema/gnumed-entire_schema-no_audit.dot
=====================================
The diff for this file was not included because it is too large.

=====================================
client/doc/schema/gnumed-entire_schema.html
=====================================
The diff for this file was not included because it is too large.

=====================================
client/gnumed.py
=====================================
@@ -97,7 +97,7 @@ against. Please run GNUmed as a non-root user.
 	sys.exit(1)
 
 #----------------------------------------------------------
-current_client_version = '1.8.15'
+current_client_version = '1.8.16'
 current_client_branch = '1.8'
 
 _log = None


=====================================
client/wxGladeWidgets/wxgCurrentSubstancesPnl.py
=====================================
@@ -4,10 +4,10 @@
 #
 
 import wx
-import wx.grid
 
 # begin wxGlade: dependencies
 import gettext
+import wx.grid
 # end wxGlade
 
 # begin wxGlade: extracode
@@ -20,112 +20,136 @@ class wxgCurrentSubstancesPnl(wx.ScrolledWindow):
 		# begin wxGlade: wxgCurrentSubstancesPnl.__init__
 		kwds["style"] = kwds.get("style", 0) | wx.BORDER_NONE | wx.TAB_TRAVERSAL
 		wx.ScrolledWindow.__init__(self, *args, **kwds)
-		self._HLINE_lab = wx.StaticLine(self, wx.ID_ANY)
-		self._CHCE_grouping = wx.Choice(self, wx.ID_ANY, choices=[_("einlangerstring einlangerstring")])
-		self._CHBOX_show_inactive = wx.CheckBox(self, wx.ID_ANY, _("Inactive"))
-		self._CHBOX_show_unapproved = wx.CheckBox(self, wx.ID_ANY, _("Unapproved"))
-		self._grid_substances = cCurrentSubstancesGrid(self, wx.ID_ANY, size=(1, 1))
-		self._BTN_add = wx.Button(self, wx.ID_ADD, "", style=wx.BU_EXACTFIT)
-		self._BTN_edit = wx.Button(self, wx.ID_ANY, _("&Edit"), style=wx.BU_EXACTFIT)
-		self._BTN_delete = wx.Button(self, wx.ID_DELETE, "", style=wx.BU_EXACTFIT)
-		self._BTN_allergy = wx.Button(self, wx.ID_ANY, _("Allergy"), style=wx.BU_EXACTFIT)
-		self._BTN_info = wx.Button(self, wx.ID_ANY, _("Info"), style=wx.BU_EXACTFIT)
-		self._BTN_heart = wx.Button(self, wx.ID_ANY, _(u"\u2665"), style=wx.BU_EXACTFIT)
-		self._BTN_kidneys = wx.Button(self, wx.ID_ANY, _("Kidney"), style=wx.BU_EXACTFIT)
-		self._LBL_gfr = wx.StaticText(self, wx.ID_ANY, _("GFR: ?"))
-		self._BTN_interactions = wx.Button(self, wx.ID_ANY, _("&Interactions?"), style=wx.BU_EXACTFIT)
-		self._BTN_rx = wx.Button(self, wx.ID_ANY, _(u"\u211e"), style=wx.BU_EXACTFIT)
-		self._BTN_adr = wx.Button(self, wx.ID_ANY, _("ADR"), style=wx.BU_EXACTFIT)
-		self._BTN_print = wx.Button(self, wx.ID_PRINT, "", style=wx.BU_EXACTFIT)
-
-		self.__set_properties()
-		self.__do_layout()
-
-		self.Bind(wx.EVT_CHOICE, self._on_grouping_selected, self._CHCE_grouping)
-		self.Bind(wx.EVT_CHECKBOX, self._on_show_inactive_checked, self._CHBOX_show_inactive)
-		self.Bind(wx.EVT_CHECKBOX, self._on_show_unapproved_checked, self._CHBOX_show_unapproved)
-		self.Bind(wx.EVT_BUTTON, self._on_add_button_pressed, self._BTN_add)
-		self.Bind(wx.EVT_BUTTON, self._on_edit_button_pressed, self._BTN_edit)
-		self.Bind(wx.EVT_BUTTON, self._on_delete_button_pressed, self._BTN_delete)
-		self.Bind(wx.EVT_BUTTON, self._on_allergy_button_pressed, self._BTN_allergy)
-		self.Bind(wx.EVT_BUTTON, self._on_info_button_pressed, self._BTN_info)
-		self.Bind(wx.EVT_BUTTON, self._on_button_heart_pressed, self._BTN_heart)
-		self.Bind(wx.EVT_BUTTON, self._on_button_kidneys_pressed, self._BTN_kidneys)
-		self.Bind(wx.EVT_BUTTON, self._on_interactions_button_pressed, self._BTN_interactions)
-		self.Bind(wx.EVT_BUTTON, self._on_rx_button_pressed, self._BTN_rx)
-		self.Bind(wx.EVT_BUTTON, self._on_adr_button_pressed, self._BTN_adr)
-		self.Bind(wx.EVT_BUTTON, self._on_print_button_pressed, self._BTN_print)
-		# end wxGlade
-
-	def __set_properties(self):
-		# begin wxGlade: wxgCurrentSubstancesPnl.__set_properties
 		self.SetScrollRate(10, 10)
-		self._HLINE_lab.Hide()
-		self._CHCE_grouping.SetSelection(0)
-		self._CHBOX_show_inactive.SetToolTip(_("Whether to show inactive substances, too, or only those which are assumed to currently be active."))
-		self._CHBOX_show_inactive.SetValue(1)
-		self._CHBOX_show_unapproved.SetToolTip(_("Whether to show all substances or only those the intake of which is approved of."))
-		self._CHBOX_show_unapproved.SetValue(1)
-		self._BTN_add.SetToolTip(_("Add a substance."))
-		self._BTN_edit.SetToolTip(_("Edit the selected substance intake entry."))
-		self._BTN_delete.SetToolTip(_("Remove a substance from the list."))
-		self._BTN_allergy.SetToolTip(_("Discontinue selected entry due to an allergy or intolerance."))
-		self._BTN_info.SetToolTip(_("Show in-depth information on the selected substance if available."))
-		self._BTN_heart.SetFont(wx.Font(13, wx.DEFAULT, wx.NORMAL, wx.NORMAL, 0, ""))
-		self._BTN_heart.SetToolTip(_("Information on handling drugs in the presence of long Qt syndrome (%s)."))
-		self._BTN_kidneys.SetToolTip(_("Information on handling of drugs / the selected drug in the presence of renal insufficiency (%s)."))
-		self._BTN_interactions.SetToolTip(_("Check for interactions between selected drugs.\n\nIncludes all drugs if none selected."))
-		self._BTN_rx.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL, wx.NORMAL, 0, ""))
-		self._BTN_rx.SetToolTip(_("Write a prescription based on either of\n\n- the selected lines\n- a copy of the most recent prescription"))
-		self._BTN_adr.SetToolTip(_("Report an Adverse Drug Reaction."))
-		self._BTN_print.SetToolTip(_("Print the medication list."))
-		# end wxGlade
 
-	def __do_layout(self):
-		# begin wxGlade: wxgCurrentSubstancesPnl.__do_layout
 		__szr_main = wx.BoxSizer(wx.VERTICAL)
-		__szr_buttons = wx.BoxSizer(wx.HORIZONTAL)
-		__szr_grid = wx.BoxSizer(wx.HORIZONTAL)
-		__szr_grouping = wx.BoxSizer(wx.HORIZONTAL)
+
 		self._GSZR_lab = wx.GridSizer(0, 5, 2, 3)
+		__szr_main.Add(self._GSZR_lab, 0, wx.EXPAND, 3)
+
 		self._GSZR_lab.Add((0, 0), 0, 0, 0)
+
 		self._GSZR_lab.Add((0, 0), 0, 0, 0)
+
 		self._GSZR_lab.Add((0, 0), 0, 0, 0)
-		__szr_main.Add(self._GSZR_lab, 0, wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, 3)
-		__szr_main.Add(self._HLINE_lab, 0, wx.ALIGN_CENTER_VERTICAL | wx.BOTTOM | wx.EXPAND | wx.TOP, 2)
+
+		self._HLINE_lab = wx.StaticLine(self, wx.ID_ANY)
+		self._HLINE_lab.Hide()
+		__szr_main.Add(self._HLINE_lab, 0, wx.BOTTOM | wx.EXPAND | wx.TOP, 2)
+
+		__szr_grouping = wx.BoxSizer(wx.HORIZONTAL)
+		__szr_main.Add(__szr_grouping, 0, wx.EXPAND, 0)
+
 		__lbl_group = wx.StaticText(self, wx.ID_ANY, _("Sort by:"))
 		__szr_grouping.Add(__lbl_group, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 5)
-		__szr_grouping.Add(self._CHCE_grouping, 0, wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, 0)
+
+		self._CHCE_grouping = wx.Choice(self, wx.ID_ANY, choices=[_("einlangerstring einlangerstring")])
+		self._CHCE_grouping.SetSelection(0)
+		__szr_grouping.Add(self._CHCE_grouping, 0, wx.EXPAND, 0)
+
 		__SLINE_grouping = wx.StaticLine(self, wx.ID_ANY, style=wx.LI_VERTICAL)
 		__szr_grouping.Add(__SLINE_grouping, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 10)
+
 		__lbl_filter = wx.StaticText(self, wx.ID_ANY, _("Include:"))
 		__szr_grouping.Add(__lbl_filter, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 5)
-		__szr_grouping.Add(self._CHBOX_show_inactive, 0, wx.ALIGN_CENTER_VERTICAL | wx.EXPAND | wx.RIGHT, 5)
-		__szr_grouping.Add(self._CHBOX_show_unapproved, 0, wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, 5)
+
+		self._CHBOX_show_inactive = wx.CheckBox(self, wx.ID_ANY, _("Inactive"))
+		self._CHBOX_show_inactive.SetToolTip(_("Whether to show inactive substances, too, or only those which are assumed to currently be active."))
+		self._CHBOX_show_inactive.SetValue(1)
+		__szr_grouping.Add(self._CHBOX_show_inactive, 0, wx.EXPAND | wx.RIGHT, 5)
+
+		self._CHBOX_show_unapproved = wx.CheckBox(self, wx.ID_ANY, _("Unapproved"))
+		self._CHBOX_show_unapproved.SetToolTip(_("Whether to show all substances or only those the intake of which is approved of."))
+		self._CHBOX_show_unapproved.SetValue(1)
+		__szr_grouping.Add(self._CHBOX_show_unapproved, 0, wx.EXPAND, 5)
+
 		__szr_grouping.Add((20, 20), 1, wx.EXPAND, 0)
-		__szr_main.Add(__szr_grouping, 0, wx.EXPAND, 0)
-		__szr_grid.Add(self._grid_substances, 1, wx.EXPAND | wx.TOP, 5)
+
+		__szr_grid = wx.BoxSizer(wx.HORIZONTAL)
 		__szr_main.Add(__szr_grid, 1, wx.EXPAND, 0)
-		__szr_buttons.Add((20, 20), 1, wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, 0)
+
+		self._grid_substances = cCurrentSubstancesGrid(self, wx.ID_ANY, size=(1, 1))
+		__szr_grid.Add(self._grid_substances, 1, wx.EXPAND | wx.TOP, 5)
+
+		__szr_buttons = wx.BoxSizer(wx.HORIZONTAL)
+		__szr_main.Add(__szr_buttons, 0, wx.EXPAND | wx.TOP, 5)
+
+		__szr_buttons.Add((20, 20), 1, wx.EXPAND, 0)
+
+		self._BTN_add = wx.Button(self, wx.ID_ADD, "", style=wx.BU_EXACTFIT)
+		self._BTN_add.SetToolTip(_("Add a substance."))
 		__szr_buttons.Add(self._BTN_add, 0, wx.EXPAND | wx.RIGHT, 5)
+
+		self._BTN_edit = wx.Button(self, wx.ID_ANY, _("&Edit"), style=wx.BU_EXACTFIT)
+		self._BTN_edit.SetToolTip(_("Edit the selected substance intake entry."))
 		__szr_buttons.Add(self._BTN_edit, 0, wx.EXPAND | wx.RIGHT, 5)
+
+		self._BTN_delete = wx.Button(self, wx.ID_DELETE, "", style=wx.BU_EXACTFIT)
+		self._BTN_delete.SetToolTip(_("Remove a substance from the list."))
 		__szr_buttons.Add(self._BTN_delete, 0, wx.EXPAND | wx.RIGHT, 5)
+
+		self._BTN_allergy = wx.Button(self, wx.ID_ANY, _("Allergy"), style=wx.BU_EXACTFIT)
+		self._BTN_allergy.SetToolTip(_("Discontinue selected entry due to an allergy or intolerance."))
 		__szr_buttons.Add(self._BTN_allergy, 0, wx.EXPAND | wx.RIGHT, 5)
+
+		self._BTN_info = wx.Button(self, wx.ID_ANY, _("Info"), style=wx.BU_EXACTFIT)
+		self._BTN_info.SetToolTip(_("Show in-depth information on the selected substance if available."))
 		__szr_buttons.Add(self._BTN_info, 0, wx.EXPAND, 5)
+
 		__szr_buttons.Add((20, 20), 1, wx.EXPAND, 0)
+
+		self._BTN_heart = wx.Button(self, wx.ID_ANY, _(u"♥"), style=wx.BU_EXACTFIT)
+		self._BTN_heart.SetFont(wx.Font(13, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, 0, ""))
+		self._BTN_heart.SetToolTip(_("Information on handling drugs in the presence of long Qt syndrome (%s)."))
 		__szr_buttons.Add(self._BTN_heart, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 5)
+
+		self._BTN_kidneys = wx.Button(self, wx.ID_ANY, _("Kidney"), style=wx.BU_EXACTFIT)
+		self._BTN_kidneys.SetToolTip(_("Information on handling of drugs / the selected drug in the presence of renal insufficiency (%s)."))
 		__szr_buttons.Add(self._BTN_kidneys, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 5)
+
+		self._LBL_gfr = wx.StaticText(self, wx.ID_ANY, _("GFR: ?"))
 		__szr_buttons.Add(self._LBL_gfr, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 5)
+
+		self._BTN_interactions = wx.Button(self, wx.ID_ANY, _("&Interactions?"), style=wx.BU_EXACTFIT)
+		self._BTN_interactions.SetToolTip(_("Check for interactions between selected drugs.\n\nIncludes all drugs if none selected."))
 		__szr_buttons.Add(self._BTN_interactions, 0, wx.ALIGN_CENTER_VERTICAL, 5)
+
 		__szr_buttons.Add((20, 20), 1, wx.EXPAND, 0)
+
+		self._BTN_rx = wx.Button(self, wx.ID_ANY, _(u"℞"), style=wx.BU_EXACTFIT)
+		self._BTN_rx.SetFont(wx.Font(12, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, 0, ""))
+		self._BTN_rx.SetToolTip(_("Write a prescription based on either of\n\n- the selected lines\n- a copy of the most recent prescription"))
 		__szr_buttons.Add(self._BTN_rx, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 5)
+
+		self._BTN_adr = wx.Button(self, wx.ID_ANY, _("ADR"), style=wx.BU_EXACTFIT)
+		self._BTN_adr.SetToolTip(_("Report an Adverse Drug Reaction."))
 		__szr_buttons.Add(self._BTN_adr, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 5)
+
+		self._BTN_print = wx.Button(self, wx.ID_PRINT, "", style=wx.BU_EXACTFIT)
+		self._BTN_print.SetToolTip(_("Print the medication list."))
 		__szr_buttons.Add(self._BTN_print, 0, wx.ALIGN_CENTER_VERTICAL, 0)
-		__szr_buttons.Add((20, 20), 1, wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, 0)
-		__szr_main.Add(__szr_buttons, 0, wx.EXPAND | wx.TOP, 5)
+
+		__szr_buttons.Add((20, 20), 1, wx.EXPAND, 0)
+
 		self.SetSizer(__szr_main)
 		__szr_main.Fit(self)
+
 		self.Layout()
+
+		self.Bind(wx.EVT_CHOICE, self._on_grouping_selected, self._CHCE_grouping)
+		self.Bind(wx.EVT_CHECKBOX, self._on_show_inactive_checked, self._CHBOX_show_inactive)
+		self.Bind(wx.EVT_CHECKBOX, self._on_show_unapproved_checked, self._CHBOX_show_unapproved)
+		self.Bind(wx.EVT_BUTTON, self._on_add_button_pressed, self._BTN_add)
+		self.Bind(wx.EVT_BUTTON, self._on_edit_button_pressed, self._BTN_edit)
+		self.Bind(wx.EVT_BUTTON, self._on_delete_button_pressed, self._BTN_delete)
+		self.Bind(wx.EVT_BUTTON, self._on_allergy_button_pressed, self._BTN_allergy)
+		self.Bind(wx.EVT_BUTTON, self._on_info_button_pressed, self._BTN_info)
+		self.Bind(wx.EVT_BUTTON, self._on_button_heart_pressed, self._BTN_heart)
+		self.Bind(wx.EVT_BUTTON, self._on_button_kidneys_pressed, self._BTN_kidneys)
+		self.Bind(wx.EVT_BUTTON, self._on_interactions_button_pressed, self._BTN_interactions)
+		self.Bind(wx.EVT_BUTTON, self._on_rx_button_pressed, self._BTN_rx)
+		self.Bind(wx.EVT_BUTTON, self._on_adr_button_pressed, self._BTN_adr)
+		self.Bind(wx.EVT_BUTTON, self._on_print_button_pressed, self._BTN_print)
 		# end wxGlade
 
 	def _on_grouping_selected(self, event):  # wxGlade: wxgCurrentSubstancesPnl.<event_handler>


=====================================
client/wxGladeWidgets/wxgIncomingPluginPnl.py deleted
=====================================
@@ -1,55 +0,0 @@
-# -*- coding: UTF-8 -*-
-#
-# generated by wxGlade
-#
-
-import wx
-
-# begin wxGlade: dependencies
-import gettext
-# end wxGlade
-
-# begin wxGlade: extracode
-# end wxGlade
-
-
-class wxgIncomingPluginPnl(wx.Panel):
-	def __init__(self, *args, **kwds):
-		# begin wxGlade: wxgIncomingPluginPnl.__init__
-		kwds["style"] = kwds.get("style", 0) | wx.BORDER_NONE | wx.TAB_TRAVERSAL
-		wx.Panel.__init__(self, *args, **kwds)
-
-		__szr_main = wx.BoxSizer(wx.VERTICAL)
-
-		self._BTN_load_file = wx.Button(self, wx.ID_ANY, _("Load from &file"))
-		self._BTN_load_file.SetToolTip(_("Load a &file"))
-		__szr_main.Add(self._BTN_load_file, 0, wx.ALIGN_CENTER_HORIZONTAL, 0)
-
-		self._BTN_load_from_clipboard = wx.Button(self, wx.ID_ANY, _("Load from &clipboard"))
-		self._BTN_load_from_clipboard.SetToolTip(_("Load from clipboard"))
-		__szr_main.Add(self._BTN_load_from_clipboard, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.TOP, 3)
-
-		self._LBL_drop_target = wx.StaticText(self, wx.ID_ANY, _("Drag anything into this field."))
-		self._LBL_drop_target.SetFont(wx.Font(10, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_ITALIC, wx.FONTWEIGHT_NORMAL, 0, ""))
-		__szr_main.Add(self._LBL_drop_target, 1, wx.BOTTOM | wx.EXPAND | wx.TOP, 3)
-
-		__szr_main.Add((0, 0), 0, 0, 0)
-
-		self.SetSizer(__szr_main)
-		__szr_main.Fit(self)
-
-		self.Layout()
-
-		self.Bind(wx.EVT_BUTTON, self._on_load_file, self._BTN_load_file)
-		self.Bind(wx.EVT_BUTTON, self._on_load_from_clipboard, self._BTN_load_from_clipboard)
-		# end wxGlade
-
-	def _on_load_file(self, event):  # wxGlade: wxgIncomingPluginPnl.<event_handler>
-		print("Event handler '_on_load_file' not implemented!")
-		event.Skip()
-
-	def _on_load_from_clipboard(self, event):  # wxGlade: wxgIncomingPluginPnl.<event_handler>
-		print("Event handler '_on_load_from_clipboard' not implemented!")
-		event.Skip()
-
-# end of class wxgIncomingPluginPnl


=====================================
client/wxGladeWidgets/wxgMeasurementsAsTablePnl.py
=====================================
@@ -4,10 +4,10 @@
 #
 
 import wx
-import wx.grid
 
 # begin wxGlade: dependencies
 import gettext
+import wx.grid
 # end wxGlade
 
 # begin wxGlade: extracode
@@ -19,58 +19,64 @@ class wxgMeasurementsAsTablePnl(wx.Panel):
 		# begin wxGlade: wxgMeasurementsAsTablePnl.__init__
 		kwds["style"] = kwds.get("style", 0) | wx.BORDER_NONE | wx.TAB_TRAVERSAL
 		wx.Panel.__init__(self, *args, **kwds)
+
+		__szr_main = wx.BoxSizer(wx.VERTICAL)
+
 		from Gnumed.wxpython.gmMeasurementWidgets import cMeasurementsGrid
 		self._GRID_results_all = cMeasurementsGrid(self, wx.ID_ANY, size=(1, 1))
-		self._BTN_manage_types = wx.Button(self, wx.ID_ANY, _("Manage types"), style=wx.BU_EXACTFIT)
-		self._BTN_add = wx.Button(self, wx.ID_ADD, "", style=wx.BU_EXACTFIT)
-		self._BTN_select = wx.Button(self, wx.ID_ANY, _("&Select:"), style=wx.BU_EXACTFIT)
-		self._RBTN_my_unsigned = wx.RadioButton(self, wx.ID_ANY, _("your unsigned (&Y)"))
-		self._RBTN_all_unsigned = wx.RadioButton(self, wx.ID_ANY, _("all unsigned (&A)"))
-		self._BTN_review = wx.Button(self, wx.ID_ANY, _("&Actions ... "), style=wx.BU_EXACTFIT)
+		__szr_main.Add(self._GRID_results_all, 1, wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, 5)
 
-		self.__set_properties()
-		self.__do_layout()
+		__hline_buttons = wx.StaticLine(self, wx.ID_ANY)
+		__szr_main.Add(__hline_buttons, 0, wx.ALL | wx.EXPAND, 5)
 
-		self.Bind(wx.EVT_BUTTON, self._on_manage_types_button_pressed, self._BTN_manage_types)
-		self.Bind(wx.EVT_BUTTON, self._on_add_button_pressed, self._BTN_add)
-		self.Bind(wx.EVT_BUTTON, self._on_select_button_pressed, self._BTN_select)
-		self.Bind(wx.EVT_BUTTON, self._on_review_button_pressed, self._BTN_review)
-		# end wxGlade
+		__szr_bottom = wx.BoxSizer(wx.HORIZONTAL)
+		__szr_main.Add(__szr_bottom, 0, wx.BOTTOM | wx.EXPAND | wx.LEFT | wx.RIGHT, 5)
 
-	def __set_properties(self):
-		# begin wxGlade: wxgMeasurementsAsTablePnl.__set_properties
+		self._BTN_manage_types = wx.Button(self, wx.ID_ANY, _("Manage types"), style=wx.BU_EXACTFIT)
 		self._BTN_manage_types.SetToolTip(_("Manage test types."))
-		self._BTN_add.SetToolTip(_("Add measurments."))
-		self._BTN_select.SetToolTip(_("Select results according to your choice on the right.\n\nThis will override any previous selection.\n\nNote that you can also select cells, rows, or columns manually within the table."))
-		self._RBTN_my_unsigned.SetToolTip(_("Apply selection to those unsigned results for which you are to take responsibility."))
-		self._RBTN_all_unsigned.SetToolTip(_("Apply selection to all unsigned results."))
-		self._BTN_review.SetToolTip(_("Invoke actions on the selected measurements."))
-		# end wxGlade
-
-	def __do_layout(self):
-		# begin wxGlade: wxgMeasurementsAsTablePnl.__do_layout
-		__szr_main = wx.BoxSizer(wx.VERTICAL)
-		__szr_bottom = wx.BoxSizer(wx.HORIZONTAL)
-		__szr_main.Add(self._GRID_results_all, 1, wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, 5)
-		__hline_buttons = wx.StaticLine(self, wx.ID_ANY)
-		__szr_main.Add(__hline_buttons, 0, wx.ALL | wx.EXPAND, 5)
 		__szr_bottom.Add(self._BTN_manage_types, 0, wx.ALIGN_CENTER_VERTICAL, 0)
+
 		__szr_bottom.Add((20, 20), 2, wx.ALIGN_CENTER_VERTICAL, 0)
+
 		__vline_buttons = wx.StaticLine(self, wx.ID_ANY, style=wx.LI_VERTICAL)
 		__szr_bottom.Add(__vline_buttons, 0, wx.EXPAND | wx.RIGHT, 3)
+
 		__lbl_results = wx.StaticText(self, wx.ID_ANY, _("Results:"))
 		__szr_bottom.Add(__lbl_results, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 3)
+
+		self._BTN_add = wx.Button(self, wx.ID_ADD, "", style=wx.BU_EXACTFIT)
+		self._BTN_add.SetToolTip(_("Add measurments."))
 		__szr_bottom.Add(self._BTN_add, 0, wx.ALIGN_CENTER_VERTICAL, 3)
+
 		__szr_bottom.Add((20, 20), 1, wx.ALIGN_CENTER_VERTICAL, 0)
+
+		self._BTN_select = wx.Button(self, wx.ID_ANY, _("&Select:"), style=wx.BU_EXACTFIT)
+		self._BTN_select.SetToolTip(_("Select results according to your choice on the right.\n\nThis will override any previous selection.\n\nNote that you can also select cells, rows, or columns manually within the table."))
 		__szr_bottom.Add(self._BTN_select, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 5)
+
+		self._RBTN_my_unsigned = wx.RadioButton(self, wx.ID_ANY, _("your unsigned (&Y)"))
+		self._RBTN_my_unsigned.SetToolTip(_("Apply selection to those unsigned results for which you are to take responsibility."))
 		__szr_bottom.Add(self._RBTN_my_unsigned, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 3)
+
+		self._RBTN_all_unsigned = wx.RadioButton(self, wx.ID_ANY, _("all unsigned (&A)"))
+		self._RBTN_all_unsigned.SetToolTip(_("Apply selection to all unsigned results."))
 		__szr_bottom.Add(self._RBTN_all_unsigned, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 3)
+
+		self._BTN_review = wx.Button(self, wx.ID_ANY, _("&Actions ... "), style=wx.BU_EXACTFIT)
+		self._BTN_review.SetToolTip(_("Invoke actions on the selected measurements."))
 		__szr_bottom.Add(self._BTN_review, 0, wx.ALIGN_CENTER_VERTICAL, 0)
+
 		__szr_bottom.Add((20, 20), 1, wx.ALIGN_CENTER_VERTICAL, 0)
-		__szr_main.Add(__szr_bottom, 0, wx.BOTTOM | wx.EXPAND | wx.LEFT | wx.RIGHT, 5)
+
 		self.SetSizer(__szr_main)
 		__szr_main.Fit(self)
+
 		self.Layout()
+
+		self.Bind(wx.EVT_BUTTON, self._on_manage_types_button_pressed, self._BTN_manage_types)
+		self.Bind(wx.EVT_BUTTON, self._on_add_button_pressed, self._BTN_add)
+		self.Bind(wx.EVT_BUTTON, self._on_select_button_pressed, self._BTN_select)
+		self.Bind(wx.EVT_BUTTON, self._on_review_button_pressed, self._BTN_review)
 		# end wxGlade
 
 	def _on_manage_types_button_pressed(self, event):  # wxGlade: wxgMeasurementsAsTablePnl.<event_handler>


=====================================
client/wxGladeWidgets/wxgMeasurementsByBatteryPnl.py
=====================================
@@ -4,10 +4,10 @@
 #
 
 import wx
-import wx.grid
 
 # begin wxGlade: dependencies
 import gettext
+import wx.grid
 # end wxGlade
 
 # begin wxGlade: extracode
@@ -19,40 +19,37 @@ class wxgMeasurementsByBatteryPnl(wx.Panel):
 		# begin wxGlade: wxgMeasurementsByBatteryPnl.__init__
 		kwds["style"] = kwds.get("style", 0) | wx.BORDER_NONE | wx.TAB_TRAVERSAL
 		wx.Panel.__init__(self, *args, **kwds)
-		from Gnumed.wxpython.gmMeasurementWidgets import cTestPanelPRW
-		self._PRW_panel = cTestPanelPRW(self, wx.ID_ANY, "")
-		self._TCTRL_panel_comment = wx.TextCtrl(self, wx.ID_ANY, "")
-		self._BTN_manage_panels = wx.Button(self, wx.ID_ANY, _("Manage"), style=wx.BU_EXACTFIT)
-		from Gnumed.wxpython.gmMeasurementWidgets import cMeasurementsGrid
-		self._GRID_results_battery = cMeasurementsGrid(self, wx.ID_ANY, size=(1, 1))
-
-		self.__set_properties()
-		self.__do_layout()
 
-		self.Bind(wx.EVT_BUTTON, self._on_manage_panels_button_pressed, self._BTN_manage_panels)
-		# end wxGlade
-
-	def __set_properties(self):
-		# begin wxGlade: wxgMeasurementsByBatteryPnl.__set_properties
-		self._TCTRL_panel_comment.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BACKGROUND))
-		self._TCTRL_panel_comment.Enable(False)
-		self._BTN_manage_panels.SetToolTip(_("Manage test panels."))
-		# end wxGlade
-
-	def __do_layout(self):
-		# begin wxGlade: wxgMeasurementsByBatteryPnl.__do_layout
 		__szr_main = wx.BoxSizer(wx.VERTICAL)
+
 		__szr_panel_options = wx.BoxSizer(wx.HORIZONTAL)
+		__szr_main.Add(__szr_panel_options, 0, wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, 5)
+
 		__lbl_display = wx.StaticText(self, wx.ID_ANY, _("&Panel:"))
 		__szr_panel_options.Add(__lbl_display, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 5)
+
+		from Gnumed.wxpython.gmMeasurementWidgets import cTestPanelPRW
+		self._PRW_panel = cTestPanelPRW(self, wx.ID_ANY, "")
 		__szr_panel_options.Add(self._PRW_panel, 2, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 10)
+
+		self._TCTRL_panel_comment = wx.TextCtrl(self, wx.ID_ANY, "")
+		self._TCTRL_panel_comment.Enable(False)
 		__szr_panel_options.Add(self._TCTRL_panel_comment, 3, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 5)
+
+		self._BTN_manage_panels = wx.Button(self, wx.ID_ANY, _("Manage"), style=wx.BU_EXACTFIT)
+		self._BTN_manage_panels.SetToolTip(_("Manage test panels."))
 		__szr_panel_options.Add(self._BTN_manage_panels, 0, wx.ALIGN_CENTER_VERTICAL, 5)
-		__szr_main.Add(__szr_panel_options, 0, wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, 5)
+
+		from Gnumed.wxpython.gmMeasurementWidgets import cMeasurementsGrid
+		self._GRID_results_battery = cMeasurementsGrid(self, wx.ID_ANY, size=(1, 1))
 		__szr_main.Add(self._GRID_results_battery, 1, wx.EXPAND, 5)
+
 		self.SetSizer(__szr_main)
 		__szr_main.Fit(self)
+
 		self.Layout()
+
+		self.Bind(wx.EVT_BUTTON, self._on_manage_panels_button_pressed, self._BTN_manage_panels)
 		# end wxGlade
 
 	def _on_manage_panels_button_pressed(self, event):  # wxGlade: wxgMeasurementsByBatteryPnl.<event_handler>


=====================================
client/wxGladeWidgets/wxgMeasurementsPnl.py
=====================================
@@ -4,10 +4,10 @@
 #
 
 import wx
-import wx.grid
 
 # begin wxGlade: dependencies
 import gettext
+import wx.grid
 # end wxGlade
 
 # begin wxGlade: extracode
@@ -19,97 +19,119 @@ class wxgMeasurementsPnl(wx.Panel):
 		# begin wxGlade: wxgMeasurementsPnl.__init__
 		kwds["style"] = kwds.get("style", 0) | wx.BORDER_NONE | wx.TAB_TRAVERSAL
 		wx.Panel.__init__(self, *args, **kwds)
+
+		__szr_main = wx.BoxSizer(wx.VERTICAL)
+
+		__szr_panel_options = wx.BoxSizer(wx.HORIZONTAL)
+		__szr_main.Add(__szr_panel_options, 0, wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, 5)
+
+		__lbl_display = wx.StaticText(self, wx.ID_ANY, _("Spotlight &Panel:"))
+		__szr_panel_options.Add(__lbl_display, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 5)
+
 		from Gnumed.wxpython.gmMeasurementWidgets import cTestPanelPRW
 		self._PRW_panel = cTestPanelPRW(self, wx.ID_ANY, "")
+		__szr_panel_options.Add(self._PRW_panel, 2, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 10)
+
 		self._TCTRL_panel_comment = wx.TextCtrl(self, wx.ID_ANY, "")
+		self._TCTRL_panel_comment.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BACKGROUND))
+		self._TCTRL_panel_comment.Enable(False)
+		__szr_panel_options.Add(self._TCTRL_panel_comment, 3, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 5)
+
 		self._BTN_manage_panels = wx.Button(self, wx.ID_ANY, _("Manage panels"), style=wx.BU_EXACTFIT)
+		self._BTN_manage_panels.SetToolTip(_("Manage test panels."))
+		__szr_panel_options.Add(self._BTN_manage_panels, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 5)
+
 		self._BTN_display_mode = wx.Button(self, wx.ID_ANY, _("All: by day"), style=wx.BU_EXACTFIT)
+		self._BTN_display_mode.SetToolTip(_("Switch between modes of the full results display."))
+		__szr_panel_options.Add(self._BTN_display_mode, 0, wx.ALIGN_CENTER_VERTICAL, 0)
+
+		__szr_result_displays = wx.BoxSizer(wx.VERTICAL)
+		__szr_main.Add(__szr_result_displays, 1, wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, 5)
+
 		self._PNL_results_battery_grid = wx.Panel(self, wx.ID_ANY, style=wx.BORDER_NONE)
+		__szr_result_displays.Add(self._PNL_results_battery_grid, 1, wx.EXPAND, 0)
+
+		__szr_results_battery_grid = wx.BoxSizer(wx.HORIZONTAL)
+
 		from Gnumed.wxpython.gmMeasurementWidgets import cMeasurementsGrid
 		self._GRID_results_battery = cMeasurementsGrid(self._PNL_results_battery_grid, wx.ID_ANY, size=(1, 1))
+		__szr_results_battery_grid.Add(self._GRID_results_battery, 1, wx.EXPAND, 5)
+
 		self._PNL_results_all_grid = wx.Panel(self, wx.ID_ANY, style=wx.BORDER_NONE)
-		self._GRID_results_all = cMeasurementsGrid(self._PNL_results_all_grid, wx.ID_ANY, size=(1, 1))
-		from Gnumed.wxpython.gmMeasurementWidgets import cMeasurementsByDayPnl
-		self._PNL_results_all_listed = cMeasurementsByDayPnl(self, wx.ID_ANY, style=wx.BORDER_NONE | wx.TAB_TRAVERSAL)
-		self._BTN_manage_types = wx.Button(self, wx.ID_ANY, _("Manage types"), style=wx.BU_EXACTFIT)
-		self._BTN_add = wx.Button(self, wx.ID_ADD, "")
-		self._BTN_list = wx.Button(self, wx.ID_ANY, _("&List"))
-		self._BTN_select = wx.Button(self, wx.ID_ANY, _("&Select:"), style=wx.BU_EXACTFIT)
-		self._RBTN_my_unsigned = wx.RadioButton(self, wx.ID_ANY, _("your unsigned (&Y)"))
-		self._RBTN_all_unsigned = wx.RadioButton(self, wx.ID_ANY, _("all unsigned (&A)"))
-		self._BTN_review = wx.Button(self, wx.ID_ANY, _("&Actions ... "), style=wx.BU_EXACTFIT)
+		__szr_result_displays.Add(self._PNL_results_all_grid, 3, wx.EXPAND, 0)
 
-		self.__set_properties()
-		self.__do_layout()
+		__szr_results_all_grid = wx.BoxSizer(wx.HORIZONTAL)
 
-		self.Bind(wx.EVT_BUTTON, self._on_manage_panels_button_pressed, self._BTN_manage_panels)
-		self.Bind(wx.EVT_BUTTON, self._on_display_mode_button_pressed, self._BTN_display_mode)
-		self.Bind(wx.EVT_BUTTON, self._on_manage_types_button_pressed, self._BTN_manage_types)
-		self.Bind(wx.EVT_BUTTON, self._on_add_button_pressed, self._BTN_add)
-		self.Bind(wx.EVT_BUTTON, self._on_list_button_pressed, self._BTN_list)
-		self.Bind(wx.EVT_BUTTON, self._on_select_button_pressed, self._BTN_select)
-		self.Bind(wx.EVT_BUTTON, self._on_review_button_pressed, self._BTN_review)
-		# end wxGlade
+		self._GRID_results_all = cMeasurementsGrid(self._PNL_results_all_grid, wx.ID_ANY, size=(1, 1))
+		__szr_results_all_grid.Add(self._GRID_results_all, 1, wx.EXPAND, 5)
 
-	def __set_properties(self):
-		# begin wxGlade: wxgMeasurementsPnl.__set_properties
-		self._TCTRL_panel_comment.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BACKGROUND))
-		self._TCTRL_panel_comment.Enable(False)
-		self._BTN_manage_panels.SetToolTip(_("Manage test panels."))
-		self._BTN_display_mode.SetToolTip(_("Switch between modes of the full results display."))
+		from Gnumed.wxpython.gmMeasurementWidgets import cMeasurementsByDayPnl
+		self._PNL_results_all_listed = cMeasurementsByDayPnl(self, wx.ID_ANY, style=wx.BORDER_NONE | wx.TAB_TRAVERSAL)
 		self._PNL_results_all_listed.Hide()
-		self._BTN_manage_types.SetToolTip(_("Manage test types."))
-		self._BTN_add.SetToolTip(_("Add measurments."))
-		self._BTN_list.SetToolTip(_("Show all measurements in a chronological list."))
-		self._BTN_select.SetToolTip(_("Select results according to your choice on the right.\n\nThis will override any previous selection.\n\nNote that you can also select cells, rows, or columns manually within the table."))
-		self._RBTN_my_unsigned.SetToolTip(_("Apply selection to those unsigned results for which you are to take responsibility."))
-		self._RBTN_all_unsigned.SetToolTip(_("Apply selection to all unsigned results."))
-		self._BTN_review.SetToolTip(_("Invoke actions on the selected measurements."))
-		# end wxGlade
-
-	def __do_layout(self):
-		# begin wxGlade: wxgMeasurementsPnl.__do_layout
-		__szr_main = wx.BoxSizer(wx.VERTICAL)
-		__szr_bottom = wx.BoxSizer(wx.HORIZONTAL)
-		__szr_result_displays = wx.BoxSizer(wx.VERTICAL)
-		__szr_results_all_grid = wx.BoxSizer(wx.HORIZONTAL)
-		__szr_results_battery_grid = wx.BoxSizer(wx.HORIZONTAL)
-		__szr_panel_options = wx.BoxSizer(wx.HORIZONTAL)
-		__lbl_display = wx.StaticText(self, wx.ID_ANY, _("Spotlight &Panel:"))
-		__szr_panel_options.Add(__lbl_display, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 5)
-		__szr_panel_options.Add(self._PRW_panel, 2, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 10)
-		__szr_panel_options.Add(self._TCTRL_panel_comment, 3, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 5)
-		__szr_panel_options.Add(self._BTN_manage_panels, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 5)
-		__szr_panel_options.Add(self._BTN_display_mode, 0, wx.ALIGN_CENTER_VERTICAL, 0)
-		__szr_main.Add(__szr_panel_options, 0, wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, 5)
-		__szr_results_battery_grid.Add(self._GRID_results_battery, 1, wx.EXPAND, 5)
-		self._PNL_results_battery_grid.SetSizer(__szr_results_battery_grid)
-		__szr_result_displays.Add(self._PNL_results_battery_grid, 1, wx.EXPAND, 0)
-		__szr_results_all_grid.Add(self._GRID_results_all, 1, wx.EXPAND, 5)
-		self._PNL_results_all_grid.SetSizer(__szr_results_all_grid)
-		__szr_result_displays.Add(self._PNL_results_all_grid, 3, wx.EXPAND, 0)
 		__szr_result_displays.Add(self._PNL_results_all_listed, 3, wx.EXPAND, 0)
-		__szr_main.Add(__szr_result_displays, 1, wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, 5)
+
 		__hline_buttons = wx.StaticLine(self, wx.ID_ANY)
 		__szr_main.Add(__hline_buttons, 0, wx.ALL | wx.EXPAND, 5)
+
+		__szr_bottom = wx.BoxSizer(wx.HORIZONTAL)
+		__szr_main.Add(__szr_bottom, 0, wx.BOTTOM | wx.EXPAND | wx.LEFT | wx.RIGHT, 5)
+
+		self._BTN_manage_types = wx.Button(self, wx.ID_ANY, _("Manage types"), style=wx.BU_EXACTFIT)
+		self._BTN_manage_types.SetToolTip(_("Manage test types."))
 		__szr_bottom.Add(self._BTN_manage_types, 0, wx.ALIGN_CENTER_VERTICAL, 0)
+
 		__szr_bottom.Add((20, 20), 2, wx.ALIGN_CENTER_VERTICAL, 0)
+
 		__vline_buttons = wx.StaticLine(self, wx.ID_ANY, style=wx.LI_VERTICAL)
 		__szr_bottom.Add(__vline_buttons, 0, wx.EXPAND | wx.RIGHT, 3)
+
 		__lbl_results = wx.StaticText(self, wx.ID_ANY, _("Results:"))
 		__szr_bottom.Add(__lbl_results, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 3)
+
+		self._BTN_add = wx.Button(self, wx.ID_ADD, "")
+		self._BTN_add.SetToolTip(_("Add measurments."))
 		__szr_bottom.Add(self._BTN_add, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 3)
+
+		self._BTN_list = wx.Button(self, wx.ID_ANY, _("&List"))
+		self._BTN_list.SetToolTip(_("Show all measurements in a chronological list."))
 		__szr_bottom.Add(self._BTN_list, 0, wx.ALIGN_CENTER_VERTICAL, 0)
+
 		__szr_bottom.Add((20, 20), 1, wx.ALIGN_CENTER_VERTICAL, 0)
+
+		self._BTN_select = wx.Button(self, wx.ID_ANY, _("&Select:"), style=wx.BU_EXACTFIT)
+		self._BTN_select.SetToolTip(_("Select results according to your choice on the right.\n\nThis will override any previous selection.\n\nNote that you can also select cells, rows, or columns manually within the table."))
 		__szr_bottom.Add(self._BTN_select, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 5)
+
+		self._RBTN_my_unsigned = wx.RadioButton(self, wx.ID_ANY, _("your unsigned (&Y)"))
+		self._RBTN_my_unsigned.SetToolTip(_("Apply selection to those unsigned results for which you are to take responsibility."))
 		__szr_bottom.Add(self._RBTN_my_unsigned, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 3)
+
+		self._RBTN_all_unsigned = wx.RadioButton(self, wx.ID_ANY, _("all unsigned (&A)"))
+		self._RBTN_all_unsigned.SetToolTip(_("Apply selection to all unsigned results."))
 		__szr_bottom.Add(self._RBTN_all_unsigned, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 3)
+
+		self._BTN_review = wx.Button(self, wx.ID_ANY, _("&Actions ... "), style=wx.BU_EXACTFIT)
+		self._BTN_review.SetToolTip(_("Invoke actions on the selected measurements."))
 		__szr_bottom.Add(self._BTN_review, 0, wx.ALIGN_CENTER_VERTICAL, 0)
+
 		__szr_bottom.Add((20, 20), 1, wx.ALIGN_CENTER_VERTICAL, 0)
-		__szr_main.Add(__szr_bottom, 0, wx.BOTTOM | wx.EXPAND | wx.LEFT | wx.RIGHT, 5)
+
+		self._PNL_results_all_grid.SetSizer(__szr_results_all_grid)
+
+		self._PNL_results_battery_grid.SetSizer(__szr_results_battery_grid)
+
 		self.SetSizer(__szr_main)
 		__szr_main.Fit(self)
+
 		self.Layout()
+
+		self.Bind(wx.EVT_BUTTON, self._on_manage_panels_button_pressed, self._BTN_manage_panels)
+		self.Bind(wx.EVT_BUTTON, self._on_display_mode_button_pressed, self._BTN_display_mode)
+		self.Bind(wx.EVT_BUTTON, self._on_manage_types_button_pressed, self._BTN_manage_types)
+		self.Bind(wx.EVT_BUTTON, self._on_add_button_pressed, self._BTN_add)
+		self.Bind(wx.EVT_BUTTON, self._on_list_button_pressed, self._BTN_list)
+		self.Bind(wx.EVT_BUTTON, self._on_select_button_pressed, self._BTN_select)
+		self.Bind(wx.EVT_BUTTON, self._on_review_button_pressed, self._BTN_review)
 		# end wxGlade
 
 	def _on_manage_panels_button_pressed(self, event):  # wxGlade: wxgMeasurementsPnl.<event_handler>


=====================================
client/wxGladeWidgets/wxgPACSPluginPnl.py
=====================================
@@ -151,6 +151,8 @@ class wxgPACSPluginPnl(wx.Panel):
 		self._BTN_verify_patient_data.Enable(False)
 		__szr_patient_buttons.Add(self._BTN_verify_patient_data, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.TOP, 3)
 
+		__szr_image_and_buttons.Add((20, 20), 1, wx.EXPAND, 0)
+
 		__szr_pacs_buttons = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, _("PACS")), wx.VERTICAL)
 		__szr_image_and_buttons.Add(__szr_pacs_buttons, 0, wx.EXPAND | wx.LEFT, 2)
 


=====================================
client/wxpython/gmGuiMain.py
=====================================
@@ -3996,6 +3996,11 @@ def main():
 		gmDispatcher.connect(receiver = _signal_debugging_monitor)
 		_log.debug('gmDispatcher signal monitor activated')
 
+	try:
+		wx.SizerFlags.DisableConsistencyChecks()
+	except AttributeError:
+		pass
+
 	setup_safe_wxEndBusyCursor()
 
 	setup_callbacks()


=====================================
client/wxpython/gmMedicationWidgets.py
=====================================
@@ -1825,7 +1825,7 @@ class cCurrentSubstancesGrid(wx.grid.Grid):
 		self.CreateGrid(0, 1)
 		self.EnableEditing(0)
 		self.EnableDragGridSize(1)
-		self.SetSelectionMode(wx.grid.Grid.wxGridSelectRows)
+		self.SetSelectionMode(wx.grid.Grid.GridSelectRows)
 
 		self.SetColLabelAlignment(wx.ALIGN_LEFT, wx.ALIGN_CENTER)
 



View it on GitLab: https://salsa.debian.org/med-team/gnumed-client/-/commit/11e8dec4d467812965efcfa7c50061dff6f2e37b

-- 
View it on GitLab: https://salsa.debian.org/med-team/gnumed-client/-/commit/11e8dec4d467812965efcfa7c50061dff6f2e37b
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/debian-med-commit/attachments/20231128/c5b26708/attachment-0001.htm>


More information about the debian-med-commit mailing list