######################################################################################################################
# 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 alternative and scenario items in a tree.
:authors: P. Vennström (VTT)
:date: 17.6.2020
"""
from PySide2.QtCore import Qt
from .tree_item_utility import LastGrayMixin, EditableMixin, RootItem, EmptyChildRootItem, LeafItem, NonLazyTreeItem
[docs]_ALTERNATIVE_ICON = "\uf277" # map-signs
[docs]_SCENARIO_ICON = "\uf008" # film
[docs]class AlternativeRootItem(EmptyChildRootItem):
"""An alternative root item."""
@property
[docs] def item_type(self):
return "alternative root"
@property
[docs] def display_data(self):
return "alternative"
@property
[docs] def icon_code(self):
return _ALTERNATIVE_ICON
[docs] def empty_child(self):
return AlternativeLeafItem()
[docs]class ScenarioRootItem(EmptyChildRootItem):
"""A scenario root item."""
@property
[docs] def item_type(self):
return "scenario root"
@property
[docs] def display_data(self):
return "scenario"
@property
[docs] def icon_code(self):
return _SCENARIO_ICON
[docs] def empty_child(self):
return ScenarioLeafItem()
[docs]class AlternativeLeafItem(LastGrayMixin, EditableMixin, LeafItem):
"""An alternative leaf item."""
@property
[docs] def item_type(self):
return "alternative"
@property
[docs] def add_item_to_db(self, db_item):
self.db_mngr.add_alternatives({self.db_map: [db_item]})
[docs] def update_item_in_db(self, db_item):
self.db_mngr.update_alternatives({self.db_map: [db_item]})
[docs] def flags(self, column):
return super().flags(column) | Qt.ItemIsDragEnabled
[docs]class ScenarioLeafItem(LastGrayMixin, EditableMixin, LeafItem):
"""A scenario leaf item."""
@property
[docs] def item_type(self):
return "scenario"
[docs] def add_item_to_db(self, db_item):
self.db_mngr.add_scenarios({self.db_map: [db_item]})
[docs] def update_item_in_db(self, db_item):
self.db_mngr.update_scenarios({self.db_map: [db_item]})
@property
[docs] def scenario_alternative_root_item(self):
return self.child(1)
[docs] def fetch_more(self):
if not self.id:
return
self.append_children(ScenarioActiveItem(), ScenarioAlternativeRootItem())
self._fetched = True
[docs] def handle_updated_in_db(self):
super().handle_updated_in_db()
self.scenario_alternative_root_item.update_alternative_id_list()
[docs]class ScenarioActiveItem(NonLazyTreeItem):
@property
[docs] def item_type(self):
return "scenario active"
[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):
active = "yes" if self.parent_item.item_data["active"] else "no"
return "active: " + active
return super().data(column, role)
[docs] def set_data(self, column, value, role=Qt.EditRole):
if role == Qt.EditRole and column == 0:
active = {"yes": True, "no": False}.get(value)
if active is None:
return False
db_item = {"id": self.parent_item.id, "active": active}
self.parent_item.update_item_in_db(db_item)
return True
return False
[docs]class ScenarioAlternativeRootItem(RootItem):
"""A scenario alternative root item."""
@property
[docs] def item_type(self):
return "scenario_alternative root"
@property
[docs] def display_data(self):
return "scenario_alternative"
@property
@property
[docs] def icon_code(self):
return _ALTERNATIVE_ICON
@property
[docs] def alternative_id_list(self):
return self.db_mngr.get_scenario_alternative_id_list(self.db_map, self.parent_item.id)
[docs] def flags(self, column):
return super().flags(column) | Qt.ItemIsDropEnabled
[docs] def fetch_more(self):
children = [ScenarioAlternativeLeafItem() for _ in self.alternative_id_list]
self.append_children(*children)
self._fetched = True
[docs] def update_alternative_id_list(self):
alt_count = len(self.alternative_id_list)
curr_alt_count = self.child_count()
if alt_count > curr_alt_count:
added_count = alt_count - curr_alt_count
children = [ScenarioAlternativeLeafItem() for _ in range(added_count)]
self.insert_children(curr_alt_count, *children)
elif curr_alt_count > alt_count:
removed_count = curr_alt_count - alt_count
self.remove_children(alt_count, removed_count)
[docs]class ScenarioAlternativeLeafItem(LeafItem):
"""A scenario alternative leaf item."""
@property
[docs] def item_type(self):
return "alternative"
@property
@property
[docs] def id(self):
try:
return self.parent_item.alternative_id_list[self.child_number()]
except IndexError:
return None
[docs] def add_item_to_db(self, db_item):
raise NotImplementedError()
[docs] def update_item_in_db(self, db_item):
raise NotImplementedError()
[docs] def flags(self, column):
return super().flags(column) | Qt.ItemIsDragEnabled