From d9ecbc8ca663b71d53739cdbea5025b7a2affee3 Mon Sep 17 00:00:00 2001 From: zreszela Date: Fri, 23 Jul 2021 18:09:33 +0200 Subject: [PATCH 1/4] fix: restore of memorized conf when channel is undefined Since 6ac7aa67 measurement groups does not accept configurations with undefined channels - an exception is raised. This collides with restoring configuration memorized values when a channel was undefined while still present, but disabled, in measurement groups configurations. Raise the said exception only if the channel is enabled in the measurement group. --- src/sardana/pool/poolmeasurementgroup.py | 44 ++++++++++-------------- 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/src/sardana/pool/poolmeasurementgroup.py b/src/sardana/pool/poolmeasurementgroup.py index c335b16f7..ccd7cb3c0 100644 --- a/src/sardana/pool/poolmeasurementgroup.py +++ b/src/sardana/pool/poolmeasurementgroup.py @@ -793,37 +793,31 @@ def set_configuration_from_user(self, cfg): if 'channels' in ctrl_data: user_config_ctrl['channels'] = user_config_channel = {} for ch_name, ch_data in list(ctrl_data['channels'].items()): - if external: - validator = TangoAttributeNameValidator() - full_name = ch_data.get('full_name', ch_name) - params = validator.getUriGroups(full_name) - params['pool'] = pool - channel = PoolExternalObject(**params) - else: - try: - channel = pool.get_element_by_full_name(ch_name) - except KeyError: - raise ValueError( - '{} is not defined'.format(ch_data['name'])) - - ch_data = self._fill_channel_data(channel, ch_data) - user_config_channel[ch_name] = ch_data - ch_item = ChannelConfiguration(channel, ch_data) - ch_item.controller = ctrl_item - ctrl_item.add_channel(ch_item) - if ch_item.enabled: + if ch_data.get('enabled', True): if external: + validator = TangoAttributeNameValidator() + full_name = ch_data.get('full_name', ch_name) + params = validator.getUriGroups(full_name) + params['pool'] = pool + channel = PoolExternalObject(**params) id_ = channel.full_name else: + try: + channel = pool.get_element_by_full_name(ch_name) + except KeyError: + raise ValueError( + '{} is not defined'.format(ch_data['name'])) id_ = channel.id + ch_data = self._fill_channel_data(channel, ch_data) + ch_item = ChannelConfiguration(channel, ch_data) + ch_item.controller = ctrl_item + ctrl_item.add_channel(ch_item) user_elem_ids[ch_item.index] = id_ - - if ch_item.enabled: ctrl_enabled = True - - if acq_synch is not None: - channel_acq_synch[channel] = acq_synch - + if acq_synch is not None: + channel_acq_synch[channel] = acq_synch + user_config_channel[ch_name] = ch_data + if not external and ctrl.is_timerable(): ctrl_item.update_timer() ctrl_item.update_monitor() From 3d146b6603576a350ddd68190b3102b83bebc97c Mon Sep 17 00:00:00 2001 From: zreszela Date: Fri, 23 Jul 2021 18:14:44 +0200 Subject: [PATCH 2/4] fix: expconf with undefined channels #1615 introduced bugs in expconf when a channel is undefined but still present in the measurement groups configurations. Fix it by disabling all cells of a disabled channels. --- .../qtgui/extra_sardana/measurementgroup.py | 47 +++++++++++-------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/src/sardana/taurus/qt/qtgui/extra_sardana/measurementgroup.py b/src/sardana/taurus/qt/qtgui/extra_sardana/measurementgroup.py index 3d6171800..bd1eb9f7b 100644 --- a/src/sardana/taurus/qt/qtgui/extra_sardana/measurementgroup.py +++ b/src/sardana/taurus/qt/qtgui/extra_sardana/measurementgroup.py @@ -465,20 +465,23 @@ def flags(self, index): taurus_role = self.role(index.column()) if taurus_role == ChannelView.Channel: # channel column is not editable return flags - elif taurus_role in (ChannelView.Timer, - ChannelView.Monitor, - ChannelView.Synchronizer, - ChannelView.Synchronization): - ch_name, ch_data = index.internalPointer().itemData() - if not ch_data['_controller_name'].startswith("__"): - ch_info = self.getAvailableChannels()[ch_name] - # only timerable channels accept these configurations - if ch_info['type'] in ('CTExpChannel', - 'OneDExpChannel', - 'TwoDExpChannel'): - flags |= Qt.Qt.ItemIsEditable - else: - flags |= Qt.Qt.ItemIsEditable + ch_name, ch_data = index.internalPointer().itemData() + external = ch_data['_controller_name'].startswith("__") + if not external: + ch_info = self.getAvailableChannels().get(ch_name) + defined = ch_info is not None + if not defined: + return flags + timerable = ch_info['type'] in ('CTExpChannel', + 'OneDExpChannel', + 'TwoDExpChannel') + if taurus_role in (ChannelView.Timer, + ChannelView.Monitor, + ChannelView.Synchronizer, + ChannelView.Synchronization): + if external or not timerable: + return flags + flags |= Qt.Qt.ItemIsEditable return flags def data(self, index, role=Qt.Qt.DisplayRole): @@ -498,10 +501,11 @@ def data(self, index, role=Qt.Qt.DisplayRole): ctrlname = ch_data['_controller_name'] if ctrlname.startswith("__"): return None - ch_info = self.getAvailableChannels()[ch_name] - if ch_info['type'] not in ('CTExpChannel', - 'OneDExpChannel', - 'TwoDExpChannel'): + ch_info = self.getAvailableChannels().get(ch_name) + if (ch_info is not None + and ch_info['type'] not in ('CTExpChannel', + 'OneDExpChannel', + 'TwoDExpChannel')): return None unitdict = self.getPyData(ctrlname=ctrlname) key = self.data_keys_map[taurus_role] @@ -512,8 +516,11 @@ def data(self, index, role=Qt.Qt.DisplayRole): ctrlname = ch_data['_controller_name'] if ctrlname.startswith("__"): return None - ch_info = self.getAvailableChannels()[ch_name] - if ch_info['type'] in ('CTExpChannel', 'OneDExpChannel', 'TwoDExpChannel'): + ch_info = self.getAvailableChannels().get(ch_name) + if (ch_info is not None + and ch_info['type'] in ('CTExpChannel', + 'OneDExpChannel', + 'TwoDExpChannel')): unitdict = self.getPyData(ctrlname=ctrlname) key = self.data_keys_map[taurus_role] master_full_name = unitdict.get(key, None) From 528dc79f97df3876772b96d35fdb0aef8dbfd921 Mon Sep 17 00:00:00 2001 From: zreszela Date: Mon, 26 Jul 2021 10:39:51 +0200 Subject: [PATCH 3/4] Revert "fix: restore of memorized conf when channel is undefined" This reverts commit d9ecbc8ca663b71d53739cdbea5025b7a2affee3. --- src/sardana/pool/poolmeasurementgroup.py | 44 ++++++++++++++---------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/src/sardana/pool/poolmeasurementgroup.py b/src/sardana/pool/poolmeasurementgroup.py index ccd7cb3c0..c335b16f7 100644 --- a/src/sardana/pool/poolmeasurementgroup.py +++ b/src/sardana/pool/poolmeasurementgroup.py @@ -793,31 +793,37 @@ def set_configuration_from_user(self, cfg): if 'channels' in ctrl_data: user_config_ctrl['channels'] = user_config_channel = {} for ch_name, ch_data in list(ctrl_data['channels'].items()): - if ch_data.get('enabled', True): + if external: + validator = TangoAttributeNameValidator() + full_name = ch_data.get('full_name', ch_name) + params = validator.getUriGroups(full_name) + params['pool'] = pool + channel = PoolExternalObject(**params) + else: + try: + channel = pool.get_element_by_full_name(ch_name) + except KeyError: + raise ValueError( + '{} is not defined'.format(ch_data['name'])) + + ch_data = self._fill_channel_data(channel, ch_data) + user_config_channel[ch_name] = ch_data + ch_item = ChannelConfiguration(channel, ch_data) + ch_item.controller = ctrl_item + ctrl_item.add_channel(ch_item) + if ch_item.enabled: if external: - validator = TangoAttributeNameValidator() - full_name = ch_data.get('full_name', ch_name) - params = validator.getUriGroups(full_name) - params['pool'] = pool - channel = PoolExternalObject(**params) id_ = channel.full_name else: - try: - channel = pool.get_element_by_full_name(ch_name) - except KeyError: - raise ValueError( - '{} is not defined'.format(ch_data['name'])) id_ = channel.id - ch_data = self._fill_channel_data(channel, ch_data) - ch_item = ChannelConfiguration(channel, ch_data) - ch_item.controller = ctrl_item - ctrl_item.add_channel(ch_item) user_elem_ids[ch_item.index] = id_ + + if ch_item.enabled: ctrl_enabled = True - if acq_synch is not None: - channel_acq_synch[channel] = acq_synch - user_config_channel[ch_name] = ch_data - + + if acq_synch is not None: + channel_acq_synch[channel] = acq_synch + if not external and ctrl.is_timerable(): ctrl_item.update_timer() ctrl_item.update_monitor() From 244b5f252c56792cab06cab10a6bbf4ab7b05174 Mon Sep 17 00:00:00 2001 From: zreszela Date: Mon, 26 Jul 2021 10:51:52 +0200 Subject: [PATCH 4/4] fix: restore of memorized conf when channel is undefined (2nd attempt) Since 6ac7aa67 measurement groups does not accept configurations with undefined channels - an exception is raised. This collides with restoring configuration memorized values when a channel was undefined while still present, but disabled, in measurement groups configurations. Raise the said exception only if the channel is enabled in the measurement group. Previously d9ecbc8ca also tried to fix this issue but it introduced a regression when disabling all channels in the measurement group. --- src/sardana/pool/poolmeasurementgroup.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/sardana/pool/poolmeasurementgroup.py b/src/sardana/pool/poolmeasurementgroup.py index c335b16f7..5758599f7 100644 --- a/src/sardana/pool/poolmeasurementgroup.py +++ b/src/sardana/pool/poolmeasurementgroup.py @@ -803,6 +803,9 @@ def set_configuration_from_user(self, cfg): try: channel = pool.get_element_by_full_name(ch_name) except KeyError: + if not ch_data['enabled']: + user_config_channel[ch_name] = ch_data + continue raise ValueError( '{} is not defined'.format(ch_data['name']))