Skip to content

Commit

Permalink
Node tree widget: switch from a list widget to a tree widget.
Browse files Browse the repository at this point in the history
  • Loading branch information
don4get committed Nov 11, 2020
1 parent 709c005 commit 9f573ae
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 36 deletions.
2 changes: 0 additions & 2 deletions nodedge/blocks/block_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
import os
from typing import Dict

NODELISTWIDGET_MIMETYPE = "application/x-item"

OP_NODE_INPUT = 1
OP_NODE_OUTPUT = 2
OP_NODE_ADD = 3
Expand Down
1 change: 1 addition & 0 deletions nodedge/blocks/custom/input_block.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class InputBlock(Block):
operationTitle = "Input"
contentLabel = "In"
contentLabelObjectName = "InputBlockContent"
library = "input/output"

def __init__(self, scene, inputSocketTypes=(2, 2), outputSocketTypes=(1,)):
super().__init__(scene, inputSocketTypes=[], outputSocketTypes=(1,))
Expand Down
1 change: 1 addition & 0 deletions nodedge/blocks/custom/output_block.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class OutputBlock(Block):
operationTitle = "Output"
contentLabel = "Out"
contentLabelObjectName = "OutputBlockContent"
library = "input/output"

def __init__(self, scene, inputSocketTypes=(2, 2), outputSocketTypes=(1,)):
super().__init__(scene, inputSocketTypes=(1,), outputSocketTypes=[])
Expand Down
13 changes: 5 additions & 8 deletions nodedge/mdi_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,13 @@
from PySide2.QtWidgets import QAction, QGraphicsProxyWidget, QMenu

from nodedge.blocks.block import Block
from nodedge.blocks.block_config import (
BLOCKS,
NODELISTWIDGET_MIMETYPE,
getClassFromOperationCode,
)
from nodedge.blocks.block_config import BLOCKS, getClassFromOperationCode
from nodedge.connector import Socket
from nodedge.edge import EdgeType
from nodedge.editor_widget import EditorWidget
from nodedge.graphics_view import EdgeDraggingMode
from nodedge.node import Node
from nodedge.node_tree_widget import NODETREEWIDGET_MIMETYPE
from nodedge.utils import dumpException


Expand Down Expand Up @@ -148,7 +145,7 @@ def onNodeDragEnter(self, event: QDragEnterEvent):
being dragged
:return: QDragEnterEvent
"""
if not event.mimeData().hasFormat(NODELISTWIDGET_MIMETYPE):
if not event.mimeData().hasFormat(NODETREEWIDGET_MIMETYPE):
self.__logger.warning(
f"Dragging denied: Wrong Mime format ({event.mimeData().formats()})"
)
Expand All @@ -168,14 +165,14 @@ def onNodeDrop(self, event: QDropEvent):
dropped.
:type event: QDropEvent.py
"""
if not event.mimeData().hasFormat(NODELISTWIDGET_MIMETYPE):
if not event.mimeData().hasFormat(NODETREEWIDGET_MIMETYPE):
event.ignore()
self.__logger.warning(
f"Dropping denied: Wrong Mime format ({event.mimeData().formats()})"
)
return

eventData = event.mimeData().data(NODELISTWIDGET_MIMETYPE)
eventData = event.mimeData().data(NODETREEWIDGET_MIMETYPE)
dataStream = QDataStream(eventData, QIODevice.ReadOnly)
pixmap: QPixmap = QPixmap()

Expand Down
8 changes: 4 additions & 4 deletions nodedge/mdi_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
from nodedge.history_list_widget import HistoryListWidget
from nodedge.mdi_area import MdiArea
from nodedge.mdi_widget import MdiWidget
from nodedge.node_list_widget import NodeListWidget
from nodedge.node_tree_widget import NodeTreeWidget
from nodedge.scene_items_table_widget import SceneItemsTableWidget
from nodedge.utils import loadStyleSheets

Expand Down Expand Up @@ -436,13 +436,13 @@ def createNodesDock(self) -> None:
"""
Create Nodes dock.
"""
self.nodesListWidget = NodeListWidget()
self.nodesListWidget.itemsPressed.connect( # type: ignore
self.nodesTreeWidget = NodeTreeWidget()
self.nodesTreeWidget.itemsPressed.connect( # type: ignore
self.showItemsInStatusBar
)

self.nodesDock = QDockWidget("Nodes")
self.nodesDock.setWidget(self.nodesListWidget)
self.nodesDock.setWidget(self.nodesTreeWidget)
self.nodesDock.setFloating(False)

self.addDockWidget(Qt.RightDockWidgetArea, self.nodesDock)
Expand Down
80 changes: 58 additions & 22 deletions nodedge/node_list_widget.py → nodedge/node_tree_widget.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
"""Node list widget module containing
:class:`~nodedge.node_list_widget.NodeListWidget` class. """
"""Node tree widget module containing
:class:`~nodedge.node_tree_widget.NodeTreeWidget` class. """

import logging
from typing import Optional
Expand All @@ -16,18 +16,24 @@
Signal,
)
from PySide2.QtGui import QDrag, QIcon, QMouseEvent, QPixmap
from PySide2.QtWidgets import QAbstractItemView, QListWidget, QListWidgetItem, QWidget
from PySide2.QtWidgets import QAbstractItemView, QTreeWidget, QTreeWidgetItem, QWidget

from nodedge import DEBUG_ITEMS_PRESSED
from nodedge.blocks.block_config import *
from nodedge.utils import dumpException, widgetsAt

NODETREEWIDGET_MIMETYPE = "application/x-item"

class NodeListWidget(QListWidget):
COLUMNS = {
"Name": 0,
}


class NodeTreeWidget(QTreeWidget):
"""
Node list widget class.
Node tree widget class.
The list widget contains the declaration of all the available nodes.
The tree widget contains the declaration of all the available nodes.
"""

itemsPressed = Signal(list)
Expand All @@ -44,11 +50,13 @@ def __init__(self, parent: Optional[QWidget] = None):
self.__logger.setLevel(logging.INFO)

self.initUI()
self.setSortingEnabled(True)
self.setHeaderLabels(list(COLUMNS.keys()))

# noinspection PyAttributeOutsideInit
def initUI(self) -> None:
"""
Set up this :class:`~nodedge.node_list_widget.NodeListWidget` with its icon
Set up this :class:`~nodedge.node_tree_widget.NodeTreeWidget` with its icon
and :class:`~nodedge.node.Node`.
"""

Expand All @@ -62,7 +70,7 @@ def initUI(self) -> None:

def addNodes(self) -> None:
"""
Add available :class:`~nodedge.node.Node` s in the list widget.
Add available :class:`~nodedge.node.Node` s in the tree widget.
"""
# associateOperationCodeWithBlock(operationCode, blockClass)

Expand All @@ -71,45 +79,68 @@ def addNodes(self) -> None:

for key in keys:
node = getClassFromOperationCode(key)
self.addNode(node.operationTitle, node.icon, node.operationCode)
self.addNode(
node.operationTitle, node.icon, node.operationCode, node.library
)

def addNode(self, name, iconPath: Optional[str] = None, operationCode: int = 0):
def addNode(
self,
name: str,
iconPath: Optional[str] = None,
operationCode: int = 0,
libraryName: str = "",
):
"""
Add a :class:`~nodedge.node.Node` in the list widget.
Add a :class:`~nodedge.node.Node` in the tree widget.
"""
item = QListWidgetItem(name, self)

item = QTreeWidgetItem()
item.setText(0, name)
pixmap = QPixmap(iconPath) if iconPath else "."
# TODO: Investigate QIcon constructor
item.setIcon(QIcon(pixmap)) # type: ignore
item.setSizeHint(self.iconsSize)
item.setIcon(0, QIcon(pixmap)) # type: ignore
item.setSizeHint(0, self.iconsSize)

item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsDragEnabled)

item.setData(Qt.UserRole, pixmap)
item.setData(Qt.UserRole + 1, operationCode)
item.setData(0, Qt.UserRole, pixmap)
item.setData(0, Qt.UserRole + 1, operationCode)

libraryName = libraryName.capitalize()
if libraryName == "":
self.addTopLevelItem(item)
else:
items = self.findItems(libraryName, Qt.MatchExactly)
if not items:
libraryItem = QTreeWidgetItem()
libraryItem.setText(0, libraryName)
self.addTopLevelItem(libraryItem)
libraryItem.addChild(item)
else:
items[0].addChild(item)

def startDrag(self, *args, **kwargs) -> None:
"""
Serialize data when a user start dragging a node from the list, to be able to
Serialize data when a user start dragging a node from the tree, to be able to
instantiate it later.
"""
try:
item = self.currentItem()
operationCode = item.data(Qt.UserRole + 1)
operationCode = item.data(0, Qt.UserRole + 1)
self.__logger.debug(
f"Dragging text ({item.text()}) and code ({operationCode})"
f"Dragging text ({item.text(0)}) and code ({operationCode})"
)
pixmap = QPixmap(item.data(Qt.UserRole))
pixmap = QPixmap(item.data(0, Qt.UserRole))

itemData = QByteArray()
dataStream = QDataStream(itemData, QIODevice.WriteOnly)
# left operand works fine with QDataStream
dataStream << pixmap
dataStream.writeInt32(operationCode)
dataStream.writeQString(item.text())
dataStream.writeQString(item.text(0))

mimeData = QMimeData()
mimeData.setData(NODELISTWIDGET_MIMETYPE, itemData)
mimeData.setData(NODETREEWIDGET_MIMETYPE, itemData)

drag = QDrag(self)
drag.setMimeData(mimeData)
Expand All @@ -122,6 +153,11 @@ def startDrag(self, *args, **kwargs) -> None:
dumpException(e)

def mousePressEvent(self, e: QMouseEvent) -> None:
"""
Handle Qt's mouse press event.
:param e: `QMouseEvent`
:return: ``None``
"""
if DEBUG_ITEMS_PRESSED:
pos = e.globalPos()
itemsPressed = [w.__class__.__name__ for w in widgetsAt(pos)]
Expand Down

0 comments on commit 9f573ae

Please sign in to comment.