Skip to content

Scene

The scene owns the nodes and edges, and knows how to save and restore them.

nodeeditor.node_scene

A module containing the representation of the NodeEditor's Scene

InvalidFile

Bases: Exception

Raised when a file cannot be loaded as a Scene.

Scene

Bases: Serializable

Class representing NodeEditor's Scene

has_been_modified property writable

has_been_modified

Has this Scene been modified?

:getter: True if the Scene has been modified :setter: set new state. Triggers Has Been Modified event :type: bool

initUI

initUI()

Set up Graphics Scene Instance

getNodeByID

getNodeByID(node_id)

Find node in the scene according to provided node_id

:param node_id: ID of the node we are looking for :type node_id: int :return: Found Node or None

topological_order

topological_order()

The Nodes of this Scene in dependency order.

Every Node comes after the Nodes feeding it. Nodes that do not depend on each other keep their scene order, so the result is reproducible for a given graph.

:return: the Nodes in dependency order :rtype: list of :class:~nodeeditor.node_node.Node :raises :class:~nodeeditor.node_graph.GraphCycleError if the graph contains a cycle

descendants

descendants(node)

Every Node reachable downstream of node, excluding node.

Ordered breadth-first, so the nearest nodes come first. A node reachable through several paths appears once.

:param node: the Node to start from :type node: :class:~nodeeditor.node_node.Node :return: the downstream Nodes :rtype: list of :class:~nodeeditor.node_node.Node

ancestors

ancestors(node)

Every Node feeding node, excluding node itself.

Ordered breadth-first, so the nearest nodes come first.

:param node: the Node to start from :type node: :class:~nodeeditor.node_node.Node :return: the upstream Nodes :rtype: list of :class:~nodeeditor.node_node.Node

components

components()

The disconnected subgraphs of this Scene.

Two Nodes belong to the same component when a chain of Edges connects them, regardless of direction. A Node without any connection forms a component of its own. The components come in scene order.

:return: one list of Nodes per component :rtype: list of list of :class:~nodeeditor.node_node.Node

cycles

cycles()

The cycles of this Scene.

One representative cycle per cyclic region. Within a cycle, the Edges are listed in traversal order and the last one leads back to the node the first one started from.

:return: the cycles, each a list of Edges :rtype: list of list of :class:~nodeeditor.node_edge.Edge

paths

paths(source, target)

Every simple path from source to target.

A path is a list of (node, edge) steps, where the edge of a step is the Edge that led into its Node. The first step carries None as its edge.

:param source: the Node to start from :type source: :class:~nodeeditor.node_node.Node :param target: the Node to reach :type target: :class:~nodeeditor.node_node.Node :return: the paths found :rtype: list of list of (Node, Edge)

shortest_path

shortest_path(source, target)

The shortest path from source to target, counted in Edges.

:param source: the Node to start from :type source: :class:~nodeeditor.node_node.Node :param target: the Node to reach :type target: :class:~nodeeditor.node_node.Node :return: the shortest path, or None when target is unreachable :rtype: list of (Node, Edge) or None

setSilentSelectionEvents

setSilentSelectionEvents(value=True)

Calling this can suppress onItemSelected events to be triggered. This is useful when working with clipboard

onItemSelected

onItemSelected(silent=False)

Handle Item selection and trigger event Item Selected

:param silent: If True scene's onItemSelected won't be called and history stamp not stored :type silent: bool

onItemsDeselected

onItemsDeselected(silent=False)

Handle Items deselection and trigger event Items Deselected

:param silent: If True scene's onItemsDeselected won't be called and history stamp not stored :type silent: bool

isModified

isModified()

Is this Scene dirty aka has been modified ?

:return: True if Scene has been modified :rtype: bool

getSelectedItems

getSelectedItems()

Returns currently selected Graphics Items

:return: list of QGraphicsItems :rtype: list[QGraphicsItem]

getSelectedNodes

getSelectedNodes()

Returns currently selected Nodes

:return: list of Node :rtype: list[Node]

doDeselectItems

doDeselectItems(silent=False)

Deselects everything in scene

:param silent: If True scene's onItemsDeselected won't be called :type silent: bool

undo

undo()

Revert the most recent recorded change.

Routed through the scene rather than called on history directly so subclasses can layer an alternative undo backend underneath the default snapshot implementation.

redo

redo()

Reapply the most recently reverted change.

canUndo

canUndo()

Is there a recorded change which can be undone?

:return: True if the Scene history holds an undoable change :rtype: bool

canRedo

canRedo()

Is there a reverted change which can be redone?

:return: True if the Scene history holds a redoable change :rtype: bool

addHasBeenModifiedListener

addHasBeenModifiedListener(callback)

Register callback for Has Been Modified event

:param callback: callback function

addItemSelectedListener

addItemSelectedListener(callback)

Register callback for Item Selected event

:param callback: callback function

addItemsDeselectedListener

addItemsDeselectedListener(callback)

Register callback for Items Deselected event

:param callback: callback function

addDragEnterListener

addDragEnterListener(callback)

Register callback for Drag Enter event

:param callback: callback function

addDropListener

addDropListener(callback)

Register callback for Drop event

:param callback: callback function

resetLastSelectedStates

resetLastSelectedStates()

Resets internal selected flags in all Nodes and Edges in the Scene

getView

getView()

Shortcut for returning Scene QGraphicsView

:return: QGraphicsView attached to the Scene :rtype: QGraphicsView

getItemAt

getItemAt(pos)

Shortcut for retrieving item at provided Scene position

:param pos: scene position :type pos: QPointF :return: Qt Graphics Item at scene position :rtype: QGraphicsItem

getColorScheme

getColorScheme()

Get the global color scheme instance used by all scenes

:return: NodeEditorColorScheme instance

setEdgeColors

setEdgeColors(
    default=None, selected=None, hovered=None, dragging=None
)

Update edge colors and refresh the scene

:param default: Default edge color (hex string, QColor, or RGB tuple) :param selected: Selected edge color :param hovered: Hovered edge color :param dragging: Dragging edge color

Example::

scene.setEdgeColors(default="#FF0000", selected="#00FF00")

setSocketColors

setSocketColors(
    outline=None, highlight=None, type_colors=None
)

Update socket colors and refresh the scene

:param outline: Socket outline color (hex string, QColor, or RGB tuple) :param highlight: Socket highlight color :param type_colors: List of colors for socket types

Example::

scene.setSocketColors(
    outline="#000000",
    highlight="#00FF00",
    type_colors=["#FF0000", "#00FF00", "#0000FF"]
)

setHighlightColor

setHighlightColor(color)

Update the color used for highlighting edges and sockets

:param color: Highlight color (hex string, QColor, or RGB tuple)

Example::

scene.setHighlightColor("#00FF00")

setSocketTypeColor

setSocketTypeColor(socket_type, color)

Update the color for a specific socket type

:param socket_type: Socket type index :param color: Color to set (hex string, QColor, or RGB tuple)

Example::

scene.setSocketTypeColor(0, "#FF0000")  # Set type 0 to red

addNode

addNode(node)

Add :class:~nodeeditor.node_node.Node to this Scene

:param node: :class:~nodeeditor.node_node.Node to be added to this Scene :type node: :class:~nodeeditor.node_node.Node

addEdge

addEdge(edge)

Add :class:~nodeeditor.node_edge.Edge to this Scene

:param edge: :class:~nodeeditor.node_edge.Edge to be added to this Scene :return: :class:~nodeeditor.node_edge.Edge

removeNode

removeNode(node)

Remove :class:~nodeeditor.node_node.Node from this Scene

:param node: :class:~nodeeditor.node_node.Node to be removed from this Scene :type node: :class:~nodeeditor.node_node.Node

removeEdge

removeEdge(edge)

Remove :class:~nodeeditor.node_edge.Edge from this Scene

:param edge: :class:~nodeeditor.node_edge.Edge to be remove from this Scene :return: :class:~nodeeditor.node_edge.Edge

addGroup

addGroup(group)

Add Group to this Scene

:param group: Group to be added to this Scene

removeGroup

removeGroup(group)

Remove Group from this Scene

:param group: Group to be removed from this Scene

getGroupById

getGroupById(group_id)

Find the Group in this Scene according to the provided group_id

:param group_id: ID of the group we are looking for :type group_id: int :return: Found Group or None

findCollapsedGroupForNode

findCollapsedGroupForNode(node)

Return collapsed Group containing node, or None.

findGroupForDrop

findGroupForDrop(scenepos, exclude_nodes=None)

Topmost smallest group whose bounding rect contains scenepos.

Uses boundingRect (not header-only shape) so drops onto the body work. Returns None if no candidate. exclude_nodes skips groups that already contain all dragged nodes (avoids redundant history stamps).

dropNodesIntoGroup

dropNodesIntoGroup(nodes, scenepos)

Move nodes into group under scenepos. Returns True if changed.

clear

clear()

Remove all Nodes, Edges and Groups from this Scene

saveToFile

saveToFile(filename)

Save this Scene to the file on disk.

:param filename: where to save this scene :type filename: str

loadFromFile

loadFromFile(filename)

Load Scene from a file on disk

:param filename: from what file to load the Scene :type filename: str :raises: :class:~nodeeditor.node_scene.InvalidFile if there was an error decoding JSON file

getEdgeClass

getEdgeClass()

Return the class representing Edge. Override me if needed

setNodeClassSelector

setNodeClassSelector(class_selecting_function)

Set the function which decides what Node class to instantiate when deserializing Scene. If not set, we will always instantiate :class:~nodeeditor.node_node.Node for each Node in the Scene

:param class_selecting_function: function which returns Node class type (not instance) from Node serialized dict data :type class_selecting_function: function :return: Class Type of Node to be instantiated during deserialization :rtype: Node class type

getNodeClassFromData

getNodeClassFromData(data)

Takes Node serialized data and determines which Node Class to instantiate according the description in the serialized Node

:param data: serialized Node object data :type data: dict :return: Instance of Node class to be used in this Scene :rtype: Node class instance

serialize

serialize()

Serialize this Scene into an OrderedDict for storing in memory or on disk.

:return: data serialized in OrderedDict :rtype: OrderedDict

deserialize

deserialize(
    data, hashmap=None, restore_id=True, *args, **kwargs
)

Deserialize this Scene from a dict of serialized data.

Nodes, Edges and Groups already present in the Scene are reused, the ones missing from the data are created and the leftover ones are removed.

:param data: Dictionary containing serialized data :type data: dict :param hashmap: Helper dictionary containing references (by id == key) to existing objects :type hashmap: dict :param restore_id: True if we are creating new Sockets. False is useful when loading existing Sockets of which we want to keep the existing object's id. :type restore_id: bool :return: True if deserialization was successful, otherwise False :rtype: bool

nodeeditor.node_scene_clipboard

A module containing all code for working with Clipboard

SceneClipboard

Class contains all the code for serialization/deserialization from Clipboard

serializeSelected

serializeSelected(delete=False)

Serializes selected items in the Scene into OrderedDict

:param delete: True if you want to delete selected items after serialization. Useful for Cut operation :type delete: bool :return: Serialized data of current selection in NodeEditor :class:~nodeeditor.node_scene.Scene

deserializeFromClipboard

deserializeFromClipboard(data, *args, **kwargs)

Deserializes data from Clipboard.

:param data: dict data for deserialization to the :class:nodeeditor.node_scene.Scene. :type data: dict

nodeeditor.node_scene_history

A module containing all code for working with History (Undo/Redo)

SelectionDict

Bases: TypedDict

Define the TypedDict for selection objects

SceneHistory

Class contains all the code for undo/redo operations

Two guards control re-entrancy:

  • restore depth - incremented by :meth:restoring. Any history store attempted while the depth is non-zero is ignored, so restoring a stamp can never push a new entry onto the stack.
  • merge key - an optional grouping token supplied to :meth:storeHistory. Consecutive stores sharing a key are coalesced into a single entry, which is how bursts of keystrokes collapse into one undo step.

is_restoring_history property writable

is_restoring_history

True while a history stamp is being restored.

Retained as a property for backward compatibility: legacy callers assign to it directly instead of using :meth:restoring.

is_restoring property

is_restoring

Alias of :attr:is_restoring_history for new call sites.

clear

clear()

Reset the history stack

storeInitialHistoryStamp

storeInitialHistoryStamp()

Helper function usually used when new or open file requested

restoring

restoring(is_undo=False)

Context manager guarding a history restore.

Nestable: the depth counter only reaches zero when the outermost block exits, so an inner callback cannot re-enable history storage for the remainder of an outer restore.

:param is_undo: True when the restore is an undo, which is the flag legacy history_stamp_callback implementations read to decide which side of a diff to apply.

addHistoryModifiedListener

addHistoryModifiedListener(callback)

Register callback for HistoryModified event

:param callback: callback function

addHistoryStoredListener

addHistoryStoredListener(callback)

Register callback for HistoryStored event

:param callback: callback function

addHistoryRestoredListener

addHistoryRestoredListener(callback)

Register callback for HistoryRestored event

:param callback: callback function

removeHistoryModifiedListener

removeHistoryModifiedListener(callback)

Remove registered callback for HistoryModified event

:param callback: callback function

removeHistoryStoredListener

removeHistoryStoredListener(callback)

Remove registered callback for HistoryStored event

:param callback: callback function

removeHistoryRestoredListener

removeHistoryRestoredListener(callback)

Remove registered callback for HistoryRestored event

:param callback: callback function

canUndo

canUndo()

Return True if Undo is available for current History Stack

:rtype: bool

canRedo

canRedo()

Return True if Redo is available for current History Stack

:rtype: bool

currentText

currentText()

Description of the stamp the next undo would revert.

nextText

nextText()

Description of the stamp the next redo would reapply.

undo

undo()

Undo operation (restore previous snapshot).

redo

redo()

Redo operation

restoreHistory

restoreHistory()

Restore History Stamp from History stack.

Triggers:

  • History Modified event
  • History Restored event

storeHistory

storeHistory(
    desc,
    setModified=False,
    data=None,
    callback=None,
    merge_key=None,
    merge=None,
)

Store History Stamp into History Stack

:param desc: Description of current History Stamp :type desc: str :param setModified: if True marks :class:~nodeeditor.node_scene.Scene with has_been_modified :type setModified: bool :param data: Additional data to store with History Stamp :type data: dict :param callback: Callback function to call after storing the History Stamp :type callback: function :param merge_key: Grouping token. When it matches the key of the current top-of-stack stamp, that stamp is updated in place instead of a new one being appended, so a burst of related changes collapses into a single undo step. :type merge_key: str or None :param merge: Combines the existing payload with the incoming one when a merge happens. Receives (existing_data, new_data) and returns the payload to store. Defaults to replacing the payload outright, which is correct when the payload is a self-contained snapshot of the post-change state. Use it to preserve the original side of a diff so undo still returns to where the burst began. :type merge: callable or None :return: True if a new stamp was pushed, False if the store was skipped (restore in progress) or coalesced into the top stamp. :rtype: bool

Triggers:

  • HistoryModified
  • History Stored

captureCurrentSelection

captureCurrentSelection()

Create dictionary with a list of selected nodes and a list of selected edges :return: dict 'nodes' - list of selected nodes, 'edges' - list of selected edges :rtype: dict

createHistoryStamp

createHistoryStamp(desc, data=None, merge_key=None)

Create History Stamp. Internally serialize whole scene and the current selection

:param desc: Descriptive label for the History Stamp :param data: Optional side-channel payload replayed to the owning content :param merge_key: Optional grouping token recorded alongside the stamp :return: History stamp serializing state of Scene and current selection :rtype: dict

restoreHistoryStamp

restoreHistoryStamp(history_stamp)

Restore History Stamp to current Scene with selection of items included

:param history_stamp: History Stamp to restore :type history_stamp: dict