Source code for spinetoolbox.spine_db_editor.mvcmodels.tool_feature_item

######################################################################################################################
# Copyright (C) 2017-2021 Spine project consortium
# This file is part of Spine Toolbox.
# Spine Toolbox is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General
# Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option)
# any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
# Public License for more details. You should have received a copy of the GNU Lesser General Public License along with
# this program. If not, see <http://www.gnu.org/licenses/>.
######################################################################################################################

"""
Classes to represent tool and feature items in a tree.

:authors: M. Marin (KTH)
:date:    1.9.2020
"""
from PySide2.QtCore import Qt
from .tree_item_utility import LastGrayMixin, EditableMixin, RootItem, EmptyChildRootItem, LeafItem, NonLazyTreeItem

[docs]_FEATURE_ICON = "\uf5bc" # splotch
[docs]_TOOL_ICON = "\uf6e3" # hammer
[docs]_METHOD_ICON = "\uf1de" # sliders-h
[docs]class FeatureRootItem(EmptyChildRootItem): """A feature root item.""" @property
[docs] def item_type(self): return "feature root"
@property
[docs] def display_data(self): return "feature"
@property
[docs] def icon_code(self): return _FEATURE_ICON
[docs] def empty_child(self): return FeatureLeafItem()
[docs]class ToolRootItem(EmptyChildRootItem): """A tool root item.""" @property
[docs] def item_type(self): return "tool root"
@property
[docs] def display_data(self): return "tool"
@property
[docs] def icon_code(self): return _TOOL_ICON
[docs] def empty_child(self): return ToolLeafItem()
[docs]class FeatureLeafItem(LastGrayMixin, EditableMixin, LeafItem): """A feature leaf item.""" @property
[docs] def item_type(self): return "feature"
[docs] def _make_item_data(self): return {"name": "Enter new feature here...", "description": ""}
@property
[docs] def item_data(self): if not self.id: return self._item_data item_data = self.db_mngr.get_item(self.db_map, self.item_type, self.id) if not item_data: return {} name = self.model.make_feature_name(item_data["entity_class_name"], item_data["parameter_definition_name"]) return dict(name=name, **item_data)
@property
[docs] def tool_tip(self): return "<p>Drag this item and drop it onto a <b>tool feature</b> item below to create a tool feature</p>"
[docs] def add_item_to_db(self, db_item): if db_item is None: return self.db_mngr.add_features({self.db_map: [db_item]})
[docs] def update_item_in_db(self, db_item): if db_item is None: return self.db_mngr.update_features({self.db_map: [db_item]})
[docs] def flags(self, column): return super().flags(column) | Qt.ItemIsDragEnabled
[docs] def _make_item_to_add(self, value): ids = self._get_ids_from_feat_name(value) if not ids: return None parameter_definition_id, parameter_value_list_id = ids return dict( parameter_definition_id=parameter_definition_id, parameter_value_list_id=parameter_value_list_id, description=self._item_data["description"],
)
[docs] def _make_item_to_update(self, column, value): if column != 0: return super()._make_item_to_update(column, value) ids = self._get_ids_from_feat_name(value) if not ids: return None parameter_definition_id, parameter_value_list_id = ids return dict( id=self.id, parameter_definition_id=parameter_definition_id, parameter_value_list_id=parameter_value_list_id
)
[docs] def _get_ids_from_feat_name(self, feature_name): ids = self.model.get_feature_data(self.db_map, feature_name) if ids is None: self.model._parent.msg_error.emit( f"<p>Invalid feature '{feature_name}'. </p>" "<p>Please enter a valid combination of entity class/parameter definition.</p>" ) return None return ids
[docs]class ToolLeafItem(LastGrayMixin, EditableMixin, LeafItem): """A tool leaf item.""" @property
[docs] def item_type(self): return "tool"
[docs] def add_item_to_db(self, db_item): self.db_mngr.add_tools({self.db_map: [db_item]})
[docs] def update_item_in_db(self, db_item): self.db_mngr.update_tools({self.db_map: [db_item]})
[docs] def fetch_more(self): if not self.id: return self.append_children(ToolFeatureRootItem()) self._fetched = True
[docs]class ToolFeatureRootItem(RootItem): """A tool_feature root item.""" @property
[docs] def item_type(self): return "tool_feature root"
@property
[docs] def display_data(self): return "tool_feature"
@property
[docs] def tool_tip(self): return "<p>Drag a <b>feature</b> item from above and drop it here to create a tool feature</p>"
@property
[docs] def icon_code(self): return _FEATURE_ICON
@property
[docs] def feature_id_list(self): return [child.id for child in self.children]
[docs] def flags(self, column): return super().flags(column) | Qt.ItemIsDropEnabled
[docs]class ToolFeatureLeafItem(LeafItem): """A tool feature leaf item.""" @property
[docs] def item_type(self): return "tool_feature"
@property
[docs] def item_data(self): item_data = self.db_mngr.get_item(self.db_map, self.item_type, self.id) if not item_data: return {} feature_data = self.db_mngr.get_item(self.db_map, "feature", item_data["feature_id"]) name = self.model.make_feature_name( feature_data["entity_class_name"], feature_data["parameter_definition_name"] ) return dict(name=name, **item_data)
[docs] def fetch_more(self): self.append_children(ToolFeatureRequiredItem(), ToolFeatureMethodRootItem()) self._fetched = True
[docs] def add_item_to_db(self, db_item): raise NotImplementedError()
[docs] def update_item_in_db(self, db_item): self.db_mngr.update_tool_features({self.db_map: [db_item]})
[docs]class ToolFeatureRequiredItem(NonLazyTreeItem): """A tool feature required item.""" @property
[docs] def item_type(self): return "tool_feature required"
[docs] def flags(self, column): flags = super().flags(column) if column == 0: flags |= Qt.ItemIsEditable return flags
[docs] def data(self, column, role=Qt.DisplayRole): if column == 0 and role in (Qt.DisplayRole, Qt.EditRole): if not self.parent_item.item_data: return None required = "yes" if self.parent_item.item_data["required"] else "no" return "required: " + required return super().data(column, role)
[docs] def set_data(self, column, value, role=Qt.EditRole): if role == Qt.EditRole and column == 0: required = {"yes": True, "no": False}.get(value) if required is None: return False db_item = {"id": self.parent_item.id, "required": required} self.parent_item.update_item_in_db(db_item) return True return False
[docs]class ToolFeatureMethodRootItem(EmptyChildRootItem): """A tool_feature_method root item.""" @property
[docs] def item_type(self): return "tool_feature_method root"
@property
[docs] def display_data(self): return "tool_feature_method"
@property
[docs] def icon_code(self): return _METHOD_ICON
[docs] def empty_child(self): return ToolFeatureMethodLeafItem()
[docs]class ToolFeatureMethodLeafItem(LastGrayMixin, LeafItem): """A tool_feature_method leaf item.""" @property
[docs] def item_type(self): return "tool_feature_method"
@property
[docs] def tool_feature_item(self): return self.parent_item.parent_item
@property
[docs] def item_data(self): if not self.id: return self._item_data item_data = self.db_mngr.get_item(self.db_map, self.item_type, self.id) if not item_data: return {} name = self.db_mngr.get_value_list_item( self.db_map, item_data["parameter_value_list_id"], item_data["method_index"] ) return dict(name=name, **item_data)
[docs] def _make_item_data(self): return {"name": "Enter new method here...", "description": ""}
[docs] def flags(self, column): flags = super().flags(column) if column == 0: flags |= Qt.ItemIsEditable return flags
[docs] def _make_item_to_add(self, value): tool_feat_item = self.tool_feature_item tool_feature_id = tool_feat_item.id parameter_value_list_id = tool_feat_item.item_data["parameter_value_list_id"] method_index = self._get_method_index(parameter_value_list_id, value) if method_index is None: return None return dict( tool_feature_id=tool_feature_id, parameter_value_list_id=parameter_value_list_id, method_index=method_index
)
[docs] def _make_item_to_update(self, column, value): if column != 0: return super()._make_item_to_update(column, value) tool_feat_item = self.tool_feature_item parameter_value_list_id = tool_feat_item.item_data["parameter_value_list_id"] method_index = self._get_method_index(parameter_value_list_id, value) if method_index is None: return None return dict(id=self.id, method_index=method_index)
[docs] def _get_method_index(self, parameter_value_list_id, method): method_index = self.model.get_method_index(self.tool_feature_item.db_map, parameter_value_list_id, method) if method_index is None: self.model._parent.msg_error.emit( f"<p>Invalid method '{method}'. </p>" f"<p>Please enter a valid method for feature '{self.tool_feature_item.name}'.</p>" ) return None return method_index
[docs] def add_item_to_db(self, db_item): self.db_mngr.add_tool_feature_methods({self.db_map: [db_item]})
[docs] def update_item_in_db(self, db_item): self.db_mngr.update_tool_feature_methods({self.db_map: [db_item]})