Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/treeform #197

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Unreleased

### Added
* Added dynamic import to enable access from expended `TreeForm`.

### Changed

Expand Down
17 changes: 16 additions & 1 deletion src/compas_viewer/components/sceneform.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
from PySide6.QtWidgets import QTreeWidget
from PySide6.QtWidgets import QTreeWidgetItem

from compas_viewer.components.treeform import Treeform


class Sceneform(QTreeWidget):
"""
Expand Down Expand Up @@ -37,12 +39,14 @@ class Sceneform(QTreeWidget):
def __init__(
self,
columns: list[dict],
show_selected_tree: Optional[bool] = True,
column_editable: Optional[list[bool]] = None,
show_headers: bool = True,
show_headers: Optional[bool] = True,
callback: Optional[Callable] = None,
):
super().__init__()
self.columns = columns
self.show_selected_tree = show_selected_tree
self.checkbox_columns: dict[int, str] = {}
self.column_editable = (column_editable or [False]) + [False] * (len(columns) - len(column_editable or [False]))
self.setColumnCount(len(columns))
Expand Down Expand Up @@ -75,6 +79,8 @@ def update(self):
if node.is_selected:
self.expand(node.parent)
self.scrollToItem(widget)
if self.show_selected_tree:
self.update_selected(node)

else:
self._sceneobjects = list(self.scene.objects)
Expand Down Expand Up @@ -109,6 +115,8 @@ def update(self):
widget.setSelected(node.is_selected)
if node.is_selected:
self.expand(node.parent)
if self.show_selected_tree:
self.update_selected(node)

widget.setFlags(widget.flags() | Qt.ItemIsUserCheckable | Qt.ItemIsSelectable | Qt.ItemIsEnabled)

Expand All @@ -119,6 +127,13 @@ def update(self):

self.adjust_column_widths()

def update_selected(self, node):
if not hasattr(self, "treeform"):
self.treeform = Treeform()
self.viewer.ui.sidebar.widget.addWidget(self.treeform)

self.treeform.update_from_dict({"objtype": node.__class__, "item": node.item, "settings": node.settings})

def expand(self, node):
if node.attributes.get("widget"):
node.attributes["widget"].setExpanded(True)
Expand Down
43 changes: 37 additions & 6 deletions src/compas_viewer/components/treeform.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,15 @@
from PySide6.QtWidgets import QTreeWidget
from PySide6.QtWidgets import QTreeWidgetItem

import compas.datastructures as ds
import compas.geometry as geom
from compas.datastructures import Tree
from compas.datastructures import TreeNode

# Collect all classes from compas.geometry dynamically
geometry_types = tuple(getattr(geom, attr) for attr in dir(geom) if isinstance(getattr(geom, attr), type))
datastructures_types = tuple(getattr(ds, attr) for attr in dir(ds) if isinstance(getattr(ds, attr), type))


class Treeform(QTreeWidget):
"""
Expand All @@ -16,10 +22,10 @@ class Treeform(QTreeWidget):

Parameters
----------
tree : :class:`compas.datastructures.Tree`
tree : :class:`compas.datastructures.Tree`, optional
The tree to be displayed. An typical example is the scene
object tree: :attr:`compas_viewer.viewer.Viewer._tree`.
columns : dict[str, callable]
columns : dict[str, callable], optional
A dictionary of column names and their corresponding attributes.
Example: ``{"Name": (lambda o: o.name), "Object": (lambda o: o)}``
show_headers : bool, optional
Expand Down Expand Up @@ -67,10 +73,10 @@ class Treeform(QTreeWidget):

def __init__(
self,
tree: Tree = None,
columns: dict[str, Callable] = None,
show_headers: bool = True,
stretch: int = 2,
tree: Optional[Tree] = None,
columns: Optional[dict[str, Callable]] = None,
show_headers: Optional[bool] = True,
stretch: Optional[int] = 2,
backgrounds: Optional[dict[str, Callable]] = None,
callback: Optional[Callable] = None,
):
Expand Down Expand Up @@ -115,13 +121,38 @@ def tree_from_dict(self, data):

def add_children(key, data, parent):
if isinstance(data, dict):
# TODO: bug - if key == 0, TreeNode name show Treenode instead of 0
node = TreeNode(name=key)
for child_key, child_data in data.items():
add_children(child_key, child_data, node)
elif isinstance(data, (list, tuple)):
node = TreeNode(name=key)
for child_index, child_data in enumerate(data):
add_children(child_index, child_data, node)
elif isinstance(data, geometry_types):
node = TreeNode(name=key)
for i, attr_name in enumerate(data.__data__):
if isinstance(attr_name, str):
if hasattr(data, attr_name):
attr_value = getattr(data, attr_name)
add_children(attr_name, attr_value, node)
elif isinstance(attr_name, float) and len(data.__data__) == 3:
attr_value = attr_name
if i == 0:
attr_name = "x"
elif i == 1:
attr_name = "y"
elif i == 2:
attr_name = "z"
add_children(attr_name, attr_value, node)
elif isinstance(data, datastructures_types):
node = TreeNode(name=key)
for attr_name in data.__data__:
if isinstance(attr_name, str):
if hasattr(data, attr_name):
attr_value = getattr(data, attr_name)
print(f"Attribute: {attr_name}, Value: {attr_value}")
add_children(attr_name, attr_value, node)
else:
node = TreeNode(name=key, value=data)

Expand Down
2 changes: 1 addition & 1 deletion src/compas_viewer/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ class StatusbarConfig(ConfigBase):
class SidebarConfig(ConfigBase):
show: bool = True
show_widgets: bool = True
sceneform: bool = True
show_selected_tree: bool = True
items: list[dict] = field(
default_factory=lambda: [
{
Expand Down
2 changes: 1 addition & 1 deletion src/compas_viewer/ui/sidebar.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def add_items(self) -> None:
columns = item.get("columns", None)
if columns is None:
raise ValueError("Please setup config for Sceneform")
self.sceneform = Sceneform(columns=columns)
self.sceneform = Sceneform(columns=columns, show_selected_tree=self.ui.viewer.config.ui.sidebar.show_selected_tree)
self.widget.addWidget(self.sceneform)

elif itemtype == "ObjectSetting":
Expand Down
Loading