Skip to content

Commit

Permalink
wip 2 - TscatRootModel works as before with paths
Browse files Browse the repository at this point in the history
  • Loading branch information
pboettch committed Jun 9, 2024
1 parent 07b9756 commit 0e5f5e7
Show file tree
Hide file tree
Showing 5 changed files with 149 additions and 123 deletions.
16 changes: 12 additions & 4 deletions tscat_gui/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

from tscat import _Catalogue, _Event
from .edit import EntityEditView
from .model_base.constants import UUIDDataRole
from .model_base.constants import UUIDDataRole, EntityRole
from .state import AppState
from .tscat_driver.actions import Action, AddEventsToCatalogueAction, CanonicalizeImportAction, CreateEntityAction, \
DeleteAttributeAction, MoveToTrashAction, SaveAction, SetAttributeAction
Expand Down Expand Up @@ -165,9 +165,17 @@ def __current_event_changed(self, _: QtCore.QModelIndex, __: QtCore.QModelIndex)

def __catalogue_selection_changed(self, _: QtCore.QItemSelection, __: QtCore.QItemSelection) -> None:
if not self.programmatic_select:
uuids = [index.data(UUIDDataRole) for index in self.catalogues_view.selectedIndexes()]
self.state.updated('active_select', _Catalogue, uuids)
self.catalogues_selected.emit(uuids)
catalogue_uuids = []
selected_indexes = self.catalogues_view.selectedIndexes()
for index in selected_indexes:
if index.data(EntityRole) is not None:
catalogue_uuids.append(index.data(UUIDDataRole))

if selected_indexes:
self.state.set_catalogue_path(self.catalogue_model.current_path(selected_indexes[-1]))
if catalogue_uuids:
self.state.updated('active_select', _Catalogue, catalogue_uuids)
self.catalogues_selected.emit(catalogue_uuids)

def __create_undo_redo_action_menu_on_toolbutton(self,
index_range: range,
Expand Down
10 changes: 9 additions & 1 deletion tscat_gui/state.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class SelectState:
selected: List[str]
type: Union[Type[tscat._Catalogue], Type[tscat._Event]]
selected_catalogues: List[str]
catalogue_path: List[str]


class AppState(QtCore.QObject):
Expand All @@ -24,7 +25,7 @@ class AppState(QtCore.QObject):

def __init__(self) -> None:
super().__init__()
self._select_state = SelectState([], tscat._Catalogue, [])
self._select_state = SelectState([], tscat._Catalogue, [], [])

self._undo_stack = QtGui.QUndoStack()
self._undo_stack.cleanChanged.connect(lambda x: self.undo_stack_clean_changed.emit(x)) # type: ignore
Expand Down Expand Up @@ -58,3 +59,10 @@ def updated(self, action: str, ty: Union[Type[tscat._Catalogue], Type[tscat._Eve

log.debug(f'app-state-updated action:{action}, type:{ty}, uuids:{uuids}')
self.state_changed.emit(action, ty, uuids)

def set_catalogue_path(self, path: List[str]) -> None:
print("setting path", path)
self._select_state.catalogue_path = path

def current_catalogue_path(self) -> List[str]:
return self._select_state.catalogue_path
3 changes: 0 additions & 3 deletions tscat_gui/tscat_driver/nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,3 @@ def uuid(self) -> str:
@property
def name(self) -> str:
return self._name

def flags(self):
return QtCore.Qt.ItemIsEnabled # super().flags() | QtCore.Qt.ItemIsDragEnabled | QtCore.Qt.ItemIsDropEnabled # type: ignore
235 changes: 121 additions & 114 deletions tscat_gui/tscat_driver/tscat_root_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import tempfile
from typing import Any, Dict, List, Sequence, Union, cast

import itertools
from PySide6.QtCore import QAbstractItemModel, QMimeData, QModelIndex, QPersistentModelIndex, QUrl, Qt, Signal

from tscat import _Catalogue
Expand Down Expand Up @@ -38,6 +37,45 @@ def __init__(self) -> None:
def _trash_index(self) -> QModelIndex:
return self.index(0, 0, QModelIndex())

def _node_from_catalogue_path(self, c: _Catalogue) -> Node:
root = self._root
if hasattr(c, 'Path') and isinstance(c.Path, list) and all(isinstance(x, str) for x in c.Path):
for folder in c.Path:
for child in root.children:
if isinstance(child, FolderNode) and child.name == folder:
root = child
break
else:
new_folder = FolderNode(folder)
root.append_child(new_folder)
root = new_folder

return root

def _node_from_uuid(self, uuid: str) -> CatalogNode:
stack = [self._root]

while stack:
node = stack.pop()
if isinstance(node, CatalogNode) and node.uuid == uuid:
return node

# we do not want to search in Catalogue's children, they are events
if not isinstance(node, CatalogNode):
stack.extend(node.children)

raise ValueError(f'Node with uuid {uuid} not found')

def _index_from_node(self, node: Node) -> QModelIndex:
if node.parent is None:
return QModelIndex()

return self.index(node.row, 0, self._index_from_node(node.parent))

def index_from_uuid(self, uuid: str) -> QModelIndex:
node = self._node_from_uuid(uuid)
return self._index_from_node(node)

def _driver_action_done(self, action: Action) -> None:
if isinstance(action, GetCataloguesAction):
if action.removed_items:
Expand All @@ -53,111 +91,75 @@ def _driver_action_done(self, action: Action) -> None:
self._root.set_children([self._trash])

for c in action.catalogues:
root = self._root
if hasattr(c, 'Path') and isinstance(c.Path, list) and all(isinstance(x, str) for x in c.Path):
for folder in c.Path:
for child in root.children:
if isinstance(child, FolderNode) and child.name == folder:
root = child
break
else:
new_folder = FolderNode(folder)
root.append_child(new_folder)
root = new_folder

root.append_child(CatalogNode(c))
parent_node = self._node_from_catalogue_path(c)
parent_node.append_child(CatalogNode(c))
self.endResetModel()

# elif isinstance(action, GetCatalogueAction):
# for row, child in enumerate(self._root.children):
# if child.uuid == action.uuid:
# index = self.index(row, 0, QModelIndex())
# self.dataChanged.emit(index, index) # type: ignore
# return

# for row, child in enumerate(self._trash.children):
# if child.uuid == action.uuid:
# index = self.index(row, 0, self._trash_index())
# self.dataChanged.emit(index, index) # type: ignore

# elif isinstance(action, CreateEntityAction):
# if isinstance(action.entity, _Catalogue):
# self.beginInsertRows(QModelIndex(), len(self._root.children), len(self._root.children))
# node = CatalogNode(action.entity)
# self._root.append_child(node)
# self.endInsertRows()

# elif isinstance(action, (RemoveEntitiesAction, DeletePermanentlyAction)):
# for row, c in reversed(list(enumerate(self._root.children))):
# if c.uuid in action.uuids:
# self.beginRemoveRows(QModelIndex(), row, row)
# self._root.remove_child(c)
# self.endRemoveRows()
# if c.uuid in self._catalogues:
# del self._catalogues[c.uuid]

# for row, c in reversed(list(enumerate(self._trash.children))):
# if c.uuid in action.uuids:
# self.beginRemoveRows(self._trash_index(), row, row)
# self._trash.remove_child(c)
# self.endRemoveRows()

# elif isinstance(action, MoveToTrashAction):
# for row, c in reversed(list(enumerate(self._root.children))):
# if c.uuid in action.uuids:
# self.beginRemoveRows(QModelIndex(), row, row)
# self._root.remove_child(c)
# self.endRemoveRows()

# self.beginInsertRows(self._trash_index(), len(self._trash.children), len(self._trash.children))
# self._trash.append_child(c)
# self.endInsertRows()

# elif isinstance(action, RestoreFromTrashAction):
# for row, c in reversed(list(enumerate(self._trash.children))):
# if c.uuid in action.uuids:
# self.beginRemoveRows(self._trash_index(), row, row)
# self._trash.remove_child(c)
# self.endRemoveRows()

# self.beginInsertRows(QModelIndex(), len(self._root.children), len(self._root.children))
# self._root.append_child(c)
# self.endInsertRows()

# elif isinstance(action, RestorePermanentlyDeletedAction):
# for e in action.deleted_entities:
# if isinstance(e.restored_entity, _Catalogue):
# node = CatalogNode(e.restored_entity)
# if e.restored_entity.is_removed():
# self.beginInsertRows(self._trash_index(), len(self._trash.children), len(self._trash.children))
# self._trash.append_child(node)
# self.endInsertRows()
# else:
# self.beginInsertRows(QModelIndex(), len(self._root.children), len(self._root.children))
# self._root.append_child(node)
# self.endInsertRows()

# elif isinstance(action, (SetAttributeAction, DeleteAttributeAction)):
# for c in filter(lambda x: isinstance(x, _Catalogue), action.entities):
# assert isinstance(c, _Catalogue)
# for row, child in enumerate(self._root.children):
# if isinstance(child, CatalogNode) and child.uuid == c.uuid:
# child.node = c
# index = self.index(row, 0, QModelIndex())
# self.dataChanged.emit(index, index) # type: ignore

# for row, child in enumerate(self._trash.children):
# if isinstance(child, CatalogNode) and child.uuid == c.uuid:
# child.node = c
# index = self.index(row, 0, self._trash_index())
# self.dataChanged.emit(index, index) # type: ignore

# elif isinstance(action, ImportCanonicalizedDictAction):
# self.beginInsertRows(QModelIndex(),
# len(self._root.children),
# len(self._root.children) + len(action.catalogues) - 1)
# self._root.append_children(list(map(CatalogNode, action.catalogues)))
# self.endInsertRows()
elif isinstance(action, GetCatalogueAction):
# also search in Trash
node = self._node_from_uuid(action.uuid)
index = self._index_from_node(node)
self.dataChanged.emit(index, index) # type: ignore

elif isinstance(action, CreateEntityAction):
if isinstance(action.entity, _Catalogue):
node = CatalogNode(action.entity)
self._insert_catalogue_node_at_node_path_or_trash(node)

elif isinstance(action, (RemoveEntitiesAction, DeletePermanentlyAction)):
for uuid in action.uuids:
node = self._node_from_uuid(uuid)
index = self._index_from_node(node)

self.beginRemoveRows(index.parent(), index.row(), index.row())
node.parent.remove_child(node)
self.endRemoveRows()

# in case a catalogueModel was created for this catalogue, remove it
if uuid in self._catalogues:
del self._catalogues[uuid]

elif isinstance(action, (MoveToTrashAction, RestoreFromTrashAction)): # Move to Trash exists only for Catalogs
for uuid, entity in zip(action.uuids, action.entities):
node = self._node_from_uuid(uuid)
index = self._index_from_node(node)

self.beginRemoveRows(index.parent(), index.row(), index.row())
node.parent.remove_child(node)
self.endRemoveRows()

node.node = entity # update the node's entity to the new one with the removed flag set

self._insert_catalogue_node_at_node_path_or_trash(node)

elif isinstance(action, RestorePermanentlyDeletedAction):
for e in action.deleted_entities:
if isinstance(e.restored_entity, _Catalogue):
node = CatalogNode(e.restored_entity)
self._insert_catalogue_node_at_node_path_or_trash(node)

elif isinstance(action, (SetAttributeAction, DeleteAttributeAction)):
for c in filter(lambda x: isinstance(x, _Catalogue), action.entities):
node = self._node_from_uuid(c.uuid)
node.node = c

index = self._index_from_node(node)
self.dataChanged.emit(index, index) # type: ignore

elif isinstance(action, ImportCanonicalizedDictAction):
for node in list(map(CatalogNode, action.catalogues)):
self._insert_catalogue_node_at_node_path_or_trash(node)

def _insert_catalogue_node_at_node_path_or_trash(self, node: CatalogNode) -> None:
if node.node.is_removed(): # undelete to Trash
parent_node = self._trash
else:
parent_node = self._node_from_catalogue_path(node.node)
parent_index = self._index_from_node(parent_node)

self.beginInsertRows(parent_index, len(parent_node.children), len(parent_node.children))
parent_node.append_child(node)
self.endInsertRows()

def catalog(self, uuid: str) -> CatalogModel:
if uuid not in self._catalogues:
Expand All @@ -177,16 +179,20 @@ def catalog(self, uuid: str) -> CatalogModel:

return self._catalogues[uuid]

def index_from_uuid(self, uuid: str, parent=QModelIndex()) -> QModelIndex:
for i in range(self.rowCount(parent)):
index = self.index(i, 0, parent)
if self.data(index, UUIDDataRole) == uuid:
return index
if self.rowCount(index) > 0:
result = self.index_from_uuid(uuid, index)
if result != QModelIndex():
return result
return QModelIndex()
def current_path(self, index: QModelIndex) -> List[str]:
if not index.isValid():
return []

# get the path starting with the parent if the index is a catalogue else starting with the index
if index.data(EntityRole) is not None:
index = index.parent()

path = []

while index.isValid():
path.append(index.data())
index = index.parent()
return path[::-1]

def index(self, row: int, column: int,
parent: Union[QModelIndex, QPersistentModelIndex] = QModelIndex()) -> QModelIndex:
Expand Down Expand Up @@ -241,6 +247,7 @@ def data(self, index: Union[QModelIndex, QPersistentModelIndex],
elif role == EntityRole:
if isinstance(item, CatalogNode):
return item.node
return None

def flags(self, index: Union[QModelIndex, QPersistentModelIndex]) -> Qt.ItemFlag:
if index.isValid():
Expand Down
8 changes: 7 additions & 1 deletion tscat_gui/undo.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ def _select(self, uuids: List[str],

if type == tscat._Event:
self.state.updated('passive_select', tscat._Catalogue, self._select_state.selected_catalogues)
self.state.set_catalogue_path(self._select_state.catalogue_path)
self.state.updated('active_select', type, uuids)
if type == tscat._Catalogue:
print("TODO update path in select_state")

def redo(self) -> None:
self._redo()
Expand Down Expand Up @@ -157,17 +160,20 @@ def __init__(self, state: AppState, parent=None) -> None:

def _redo(self) -> None:
def creation_callback(action: CreateEntityAction) -> None:
print("New Catalogue created", action.entity)
assert action.entity is not None
self.uuid = action.entity.uuid
assert self.uuid is not None
self._select([self.uuid], tscat._Catalogue)

print(self.state.current_catalogue_path())
from .tscat_driver.model import tscat_model
tscat_model.do(CreateEntityAction(creation_callback, tscat._Catalogue,
{
'name': "New Catalogue",
'author': os.getlogin(),
'uuid': self.uuid
'uuid': self.uuid,
'Path': self.state.current_catalogue_path()
}))

def _undo(self) -> None:
Expand Down

0 comments on commit 0e5f5e7

Please sign in to comment.