Mini Milestone
This commit is contained in:
parent
faee07b720
commit
9db8cc6b19
193
blueprint_grid.py
Normal file
193
blueprint_grid.py
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import pkgutil
|
||||||
|
import importlib
|
||||||
|
import inspect
|
||||||
|
import types
|
||||||
|
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QWidget
|
||||||
|
from PyQt5.QtCore import Qt, QUrl, QTimer
|
||||||
|
from PyQt5.QtGui import QGuiApplication
|
||||||
|
from PyQt5.QtQuick import QQuickView
|
||||||
|
|
||||||
|
# OdenGraphQt Fix: Monkey-patch QUndoStack
|
||||||
|
import OdenGraphQt.base.graph as base_graph
|
||||||
|
from PyQt5 import QtWidgets
|
||||||
|
base_graph.QtGui.QUndoStack = QtWidgets.QUndoStack
|
||||||
|
|
||||||
|
import OdenGraphQt.base.commands as base_commands
|
||||||
|
_original_redo = base_commands.NodesRemovedCmd.redo
|
||||||
|
_original_undo = base_commands.NodesRemovedCmd.undo
|
||||||
|
|
||||||
|
def _patched_redo(self):
|
||||||
|
try:
|
||||||
|
_original_redo(self)
|
||||||
|
except TypeError as e:
|
||||||
|
if "unexpected type" in str(e) and hasattr(self, 'node'):
|
||||||
|
node_ids = []
|
||||||
|
if isinstance(self.node, list):
|
||||||
|
node_ids = [getattr(n, 'id', str(n)) for n in self.node]
|
||||||
|
else:
|
||||||
|
node_ids = [getattr(self.node, 'id', str(self.node))]
|
||||||
|
self.graph.nodes_deleted.emit(node_ids)
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
|
||||||
|
def _patched_undo(self):
|
||||||
|
try:
|
||||||
|
_original_undo(self)
|
||||||
|
except TypeError as e:
|
||||||
|
if "unexpected type" in str(e) and hasattr(self, 'node'):
|
||||||
|
node_ids = []
|
||||||
|
if isinstance(self.node, list):
|
||||||
|
node_ids = [getattr(n, 'id', str(n)) for n in self.node]
|
||||||
|
else:
|
||||||
|
node_ids = [getattr(self.node, 'id', str(self.node))]
|
||||||
|
self.graph.nodes_deleted.emit(node_ids)
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
|
||||||
|
base_commands.NodesRemovedCmd.redo = _patched_redo
|
||||||
|
base_commands.NodesRemovedCmd.undo = _patched_undo
|
||||||
|
|
||||||
|
# OdenGraphQt Transparent Viewer
|
||||||
|
from OdenGraphQt.widgets.viewer import NodeViewer
|
||||||
|
|
||||||
|
class TransparentViewer(NodeViewer):
|
||||||
|
"""A NodeViewer that does not paint anything in drawBackground() -> Fully transparent."""
|
||||||
|
def drawBackground(self, painter, rect):
|
||||||
|
pass # Do nothing, ensuring transparency.
|
||||||
|
|
||||||
|
# NodeGraph & Node Import Helpers
|
||||||
|
from OdenGraphQt import NodeGraph, BaseNode
|
||||||
|
|
||||||
|
def import_nodes_from_folder(package_name):
|
||||||
|
imported_nodes = []
|
||||||
|
package = importlib.import_module(package_name)
|
||||||
|
for loader, module_name, is_pkg in pkgutil.walk_packages(
|
||||||
|
package.__path__, package.__name__ + "."):
|
||||||
|
module = importlib.import_module(module_name)
|
||||||
|
for name, obj in inspect.getmembers(module, inspect.isclass):
|
||||||
|
if issubclass(obj, BaseNode) and obj.__module__ == module.__name__:
|
||||||
|
imported_nodes.append(obj)
|
||||||
|
return imported_nodes
|
||||||
|
|
||||||
|
def make_node_command(graph, node_type):
|
||||||
|
def command():
|
||||||
|
try:
|
||||||
|
graph.create_node(node_type)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error creating node of type {node_type}: {e}")
|
||||||
|
return command
|
||||||
|
|
||||||
|
# Edit Mode Button
|
||||||
|
class EditButton(QPushButton):
|
||||||
|
"""A small, frameless button to toggle edit mode."""
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
super().__init__("Toggle Edit Mode", parent)
|
||||||
|
self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)
|
||||||
|
# Dark gray background with white text.
|
||||||
|
self.setStyleSheet("background-color: #444444; border: 1px solid black; color: white;")
|
||||||
|
self.resize(140, 40)
|
||||||
|
|
||||||
|
# Main Overlay Window
|
||||||
|
class MainWindow(QMainWindow):
|
||||||
|
"""A frameless, transparent overlay with OdenGraphQt nodes & edit mode toggle."""
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
# Full-screen overlay
|
||||||
|
app = QApplication.instance()
|
||||||
|
screen_geo = app.primaryScreen().geometry()
|
||||||
|
self.setGeometry(screen_geo)
|
||||||
|
|
||||||
|
# Frameless, top-most, fully transparent
|
||||||
|
self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)
|
||||||
|
self.setAttribute(Qt.WA_TranslucentBackground, True)
|
||||||
|
|
||||||
|
# QML Background
|
||||||
|
self.qml_view = QQuickView()
|
||||||
|
self.qml_view.setSource(QUrl("qml/background_grid.qml"))
|
||||||
|
self.qml_view.setFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)
|
||||||
|
self.qml_view.setClearBeforeRendering(True)
|
||||||
|
self.qml_view.setColor(Qt.transparent)
|
||||||
|
self.qml_view.show()
|
||||||
|
|
||||||
|
# Save the QML root object for later property sync
|
||||||
|
self.qml_root = self.qml_view.rootObject()
|
||||||
|
|
||||||
|
# NodeGraph with TransparentViewer
|
||||||
|
self.graph = NodeGraph(viewer=TransparentViewer())
|
||||||
|
self.nodeGraphWidget = self.graph.widget
|
||||||
|
self.nodeGraphWidget.setStyleSheet("background: transparent; border: none;")
|
||||||
|
|
||||||
|
# Transparent central widget
|
||||||
|
central = QWidget(self)
|
||||||
|
central.setAttribute(Qt.WA_TranslucentBackground, True)
|
||||||
|
self.setCentralWidget(central)
|
||||||
|
|
||||||
|
self.nodeGraphWidget.setParent(central)
|
||||||
|
self.nodeGraphWidget.setGeometry(central.rect())
|
||||||
|
|
||||||
|
# Edit Mode Button (Python controlled)
|
||||||
|
self.editButton = EditButton(self)
|
||||||
|
self.editButton.move(10, 10)
|
||||||
|
self.editButton.clicked.connect(self.toggleEditMode)
|
||||||
|
self.isEditMode = True # Set edit mode enabled by default
|
||||||
|
|
||||||
|
# Ensure QML grid overlay is enabled at startup
|
||||||
|
if self.qml_root:
|
||||||
|
self.qml_root.setProperty("editMode", self.isEditMode)
|
||||||
|
|
||||||
|
# Import custom nodes
|
||||||
|
try:
|
||||||
|
custom_nodes = import_nodes_from_folder('Nodes')
|
||||||
|
for node_class in custom_nodes:
|
||||||
|
self.graph.register_node(node_class)
|
||||||
|
|
||||||
|
graph_menu = self.graph.get_context_menu('graph')
|
||||||
|
for node_class in custom_nodes:
|
||||||
|
node_type = f"{node_class.__identifier__}.{node_class.__name__}"
|
||||||
|
node_name = node_class.NODE_NAME
|
||||||
|
graph_menu.add_command(
|
||||||
|
f"Add {node_name}",
|
||||||
|
make_node_command(self.graph, node_type)
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error setting up custom nodes: {e}")
|
||||||
|
|
||||||
|
# Global update timer
|
||||||
|
self.timer = QTimer(self)
|
||||||
|
self.timer.timeout.connect(self.global_update)
|
||||||
|
self.timer.start(500)
|
||||||
|
|
||||||
|
# Timer to ensure the button stays on top (hacky, but effective)
|
||||||
|
self.raiseTimer = QTimer(self)
|
||||||
|
self.raiseTimer.timeout.connect(self.editButton.raise_)
|
||||||
|
self.raiseTimer.start(1000) # Raise the button every 1 second
|
||||||
|
|
||||||
|
self.show()
|
||||||
|
self.nodeGraphWidget.setAttribute(Qt.WA_TransparentForMouseEvents, not self.isEditMode)
|
||||||
|
|
||||||
|
def toggleEditMode(self):
|
||||||
|
"""Toggle edit mode (pass-through clicks vs interactive)."""
|
||||||
|
self.isEditMode = not self.isEditMode
|
||||||
|
self.nodeGraphWidget.setAttribute(Qt.WA_TransparentForMouseEvents, not self.isEditMode)
|
||||||
|
# Button text remains constant.
|
||||||
|
self.editButton.setText("Toggle Edit Mode")
|
||||||
|
if self.qml_root:
|
||||||
|
self.qml_root.setProperty("editMode", self.isEditMode)
|
||||||
|
|
||||||
|
def global_update(self):
|
||||||
|
"""Update all nodes periodically."""
|
||||||
|
for node in self.graph.all_nodes():
|
||||||
|
if hasattr(node, "process_input"):
|
||||||
|
node.process_input()
|
||||||
|
|
||||||
|
# Entry Point
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app = QApplication(sys.argv)
|
||||||
|
window = MainWindow()
|
||||||
|
window.show()
|
||||||
|
sys.exit(app.exec_())
|
@ -1,98 +1,73 @@
|
|||||||
#!/usr/bin/env python3
|
import sys
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import pkgutil
|
import pkgutil
|
||||||
import importlib
|
import importlib
|
||||||
import inspect
|
import inspect
|
||||||
import types
|
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout, QGraphicsView, QGraphicsScene, QGraphicsItem
|
||||||
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QWidget
|
from PyQt5.QtCore import Qt, QTimer, QRectF, QPointF
|
||||||
from PyQt5.QtCore import Qt, QUrl, QTimer
|
from PyQt5.QtGui import QColor, QPainter, QPen, QBrush, QGradient, QLinearGradient
|
||||||
from PyQt5.QtGui import QGuiApplication
|
from PyQt5 import QtWidgets, QtCore, QtGui
|
||||||
from PyQt5.QtQuick import QQuickView
|
|
||||||
|
|
||||||
# OdenGraphQt Fix: Monkey-patch QUndoStack
|
# --- Custom Graph Scene ---
|
||||||
import OdenGraphQt.base.graph as base_graph
|
class CustomGraphScene(QGraphicsScene):
|
||||||
from PyQt5 import QtWidgets
|
"""
|
||||||
base_graph.QtGui.QUndoStack = QtWidgets.QUndoStack
|
Custom scene that draws a blueprint-style transparent grid with gradient shading.
|
||||||
|
"""
|
||||||
import OdenGraphQt.base.commands as base_commands
|
|
||||||
_original_redo = base_commands.NodesRemovedCmd.redo
|
|
||||||
_original_undo = base_commands.NodesRemovedCmd.undo
|
|
||||||
|
|
||||||
def _patched_redo(self):
|
|
||||||
try:
|
|
||||||
_original_redo(self)
|
|
||||||
except TypeError as e:
|
|
||||||
if "unexpected type" in str(e) and hasattr(self, 'node'):
|
|
||||||
node_ids = []
|
|
||||||
if isinstance(self.node, list):
|
|
||||||
node_ids = [getattr(n, 'id', str(n)) for n in self.node]
|
|
||||||
else:
|
|
||||||
node_ids = [getattr(self.node, 'id', str(self.node))]
|
|
||||||
self.graph.nodes_deleted.emit(node_ids)
|
|
||||||
else:
|
|
||||||
raise
|
|
||||||
|
|
||||||
def _patched_undo(self):
|
|
||||||
try:
|
|
||||||
_original_undo(self)
|
|
||||||
except TypeError as e:
|
|
||||||
if "unexpected type" in str(e) and hasattr(self, 'node'):
|
|
||||||
node_ids = []
|
|
||||||
if isinstance(self.node, list):
|
|
||||||
node_ids = [getattr(n, 'id', str(n)) for n in self.node]
|
|
||||||
else:
|
|
||||||
node_ids = [getattr(self.node, 'id', str(self.node))]
|
|
||||||
self.graph.nodes_deleted.emit(node_ids)
|
|
||||||
else:
|
|
||||||
raise
|
|
||||||
|
|
||||||
base_commands.NodesRemovedCmd.redo = _patched_redo
|
|
||||||
base_commands.NodesRemovedCmd.undo = _patched_undo
|
|
||||||
|
|
||||||
# OdenGraphQt Transparent Viewer
|
|
||||||
from OdenGraphQt.widgets.viewer import NodeViewer
|
|
||||||
|
|
||||||
class TransparentViewer(NodeViewer):
|
|
||||||
"""A NodeViewer that does not paint anything in drawBackground() -> Fully transparent."""
|
|
||||||
def drawBackground(self, painter, rect):
|
|
||||||
pass # Do nothing, ensuring transparency.
|
|
||||||
|
|
||||||
# NodeGraph & Node Import Helpers
|
|
||||||
from OdenGraphQt import NodeGraph, BaseNode
|
|
||||||
|
|
||||||
def import_nodes_from_folder(package_name):
|
|
||||||
imported_nodes = []
|
|
||||||
package = importlib.import_module(package_name)
|
|
||||||
for loader, module_name, is_pkg in pkgutil.walk_packages(
|
|
||||||
package.__path__, package.__name__ + "."):
|
|
||||||
module = importlib.import_module(module_name)
|
|
||||||
for name, obj in inspect.getmembers(module, inspect.isclass):
|
|
||||||
if issubclass(obj, BaseNode) and obj.__module__ == module.__name__:
|
|
||||||
imported_nodes.append(obj)
|
|
||||||
return imported_nodes
|
|
||||||
|
|
||||||
def make_node_command(graph, node_type):
|
|
||||||
def command():
|
|
||||||
try:
|
|
||||||
graph.create_node(node_type)
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error creating node of type {node_type}: {e}")
|
|
||||||
return command
|
|
||||||
|
|
||||||
# Edit Mode Button
|
|
||||||
class EditButton(QPushButton):
|
|
||||||
"""A small, frameless button to toggle edit mode."""
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
super().__init__("Enter Edit Mode", parent)
|
super().__init__(parent)
|
||||||
self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)
|
self.setBackgroundBrush(QtCore.Qt.transparent)
|
||||||
self.setStyleSheet("background-color: rgba(255,255,255,200); border: 1px solid black;")
|
self.grid_color = QtGui.QColor(100, 160, 160, 160) # Blueprint grid color (10% more transparent)
|
||||||
self.resize(140, 40)
|
self.grid_size = 115
|
||||||
|
|
||||||
# Main Overlay Window
|
def drawBackground(self, painter, rect):
|
||||||
|
"""
|
||||||
|
Custom draw function to render a blueprint-style grid with gradient shading.
|
||||||
|
"""
|
||||||
|
painter.save()
|
||||||
|
painter.setRenderHint(QPainter.Antialiasing, False)
|
||||||
|
painter.setBrush(QtCore.Qt.NoBrush) # No background fill
|
||||||
|
pen = QPen(self.grid_color, 0.5)
|
||||||
|
|
||||||
|
left = int(rect.left()) - (int(rect.left()) % self.grid_size)
|
||||||
|
top = int(rect.top()) - (int(rect.top()) % self.grid_size)
|
||||||
|
|
||||||
|
# Draw vertical lines
|
||||||
|
lines = []
|
||||||
|
for x in range(left, int(rect.right()), self.grid_size):
|
||||||
|
lines.append(QtCore.QLineF(x, rect.top(), x, rect.bottom()))
|
||||||
|
|
||||||
|
# Draw horizontal lines
|
||||||
|
for y in range(top, int(rect.bottom()), self.grid_size):
|
||||||
|
lines.append(QtCore.QLineF(rect.left(), y, rect.right(), y))
|
||||||
|
|
||||||
|
painter.setPen(pen)
|
||||||
|
painter.drawLines(lines)
|
||||||
|
|
||||||
|
# Draw gradient shading (top and bottom)
|
||||||
|
gradient = QLinearGradient(QPointF(rect.left(), rect.top()), QPointF(rect.left(), rect.bottom()))
|
||||||
|
gradient.setColorAt(0.0, QColor(0, 40, 100, 220)) # Darker blue at the top
|
||||||
|
gradient.setColorAt(0.5, QColor(0, 0, 0, 0)) # Transparent in the middle
|
||||||
|
gradient.setColorAt(1.0, QColor(0, 40, 100, 220)) # Darker blue at the bottom
|
||||||
|
painter.fillRect(rect, QBrush(gradient))
|
||||||
|
|
||||||
|
painter.restore()
|
||||||
|
|
||||||
|
# --- Custom Graph View ---
|
||||||
|
class CustomGraphView(QGraphicsView):
|
||||||
|
"""
|
||||||
|
Custom view for the graph that applies full transparency.
|
||||||
|
"""
|
||||||
|
def __init__(self, scene, parent=None):
|
||||||
|
super().__init__(scene, parent)
|
||||||
|
self.setRenderHints(QtGui.QPainter.Antialiasing | QtGui.QPainter.SmoothPixmapTransform)
|
||||||
|
self.setViewportUpdateMode(QGraphicsView.FullViewportUpdate)
|
||||||
|
self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
|
||||||
|
self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
|
||||||
|
self.setStyleSheet("background: transparent; border: none;")
|
||||||
|
self.setAttribute(QtCore.Qt.WA_TranslucentBackground, True)
|
||||||
|
|
||||||
|
# --- Main Window ---
|
||||||
class MainWindow(QMainWindow):
|
class MainWindow(QMainWindow):
|
||||||
"""A frameless, transparent overlay with OdenGraphQt nodes & edit mode toggle."""
|
"""A frameless, transparent overlay with a custom graph."""
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
@ -105,81 +80,28 @@ class MainWindow(QMainWindow):
|
|||||||
self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)
|
self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)
|
||||||
self.setAttribute(Qt.WA_TranslucentBackground, True)
|
self.setAttribute(Qt.WA_TranslucentBackground, True)
|
||||||
|
|
||||||
# QML Background
|
|
||||||
self.qml_view = QQuickView()
|
|
||||||
self.qml_view.setSource(QUrl("qml/background_grid.qml"))
|
|
||||||
self.qml_view.setFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)
|
|
||||||
self.qml_view.setClearBeforeRendering(True)
|
|
||||||
self.qml_view.setColor(Qt.transparent)
|
|
||||||
self.qml_view.show()
|
|
||||||
|
|
||||||
# Save the QML root object for later property sync
|
|
||||||
self.qml_root = self.qml_view.rootObject()
|
|
||||||
|
|
||||||
# NodeGraph with TransparentViewer
|
|
||||||
self.graph = NodeGraph(viewer=TransparentViewer())
|
|
||||||
self.nodeGraphWidget = self.graph.widget
|
|
||||||
self.nodeGraphWidget.setStyleSheet("background: transparent; border: none;")
|
|
||||||
|
|
||||||
# Transparent central widget
|
# Transparent central widget
|
||||||
central = QWidget(self)
|
central = QWidget(self)
|
||||||
central.setAttribute(Qt.WA_TranslucentBackground, True)
|
central.setAttribute(Qt.WA_TranslucentBackground, True)
|
||||||
|
layout = QVBoxLayout(central)
|
||||||
|
layout.setContentsMargins(0, 0, 0, 0)
|
||||||
self.setCentralWidget(central)
|
self.setCentralWidget(central)
|
||||||
|
|
||||||
self.nodeGraphWidget.setParent(central)
|
# Initialize Custom Graph Scene & View
|
||||||
self.nodeGraphWidget.setGeometry(central.rect())
|
self.scene = CustomGraphScene()
|
||||||
|
self.view = CustomGraphView(self.scene)
|
||||||
# Edit Mode Button (Python controlled)
|
layout.addWidget(self.view)
|
||||||
self.editButton = EditButton(self)
|
|
||||||
self.editButton.move(10, 10)
|
|
||||||
self.editButton.clicked.connect(self.toggleEditMode)
|
|
||||||
self.isEditMode = True # Set edit mode enabled by default
|
|
||||||
self.editButton.setText("Exit Edit Mode") # Reflect that grid is active
|
|
||||||
|
|
||||||
# Ensure QML grid overlay is enabled at startup
|
|
||||||
if self.qml_root:
|
|
||||||
self.qml_root.setProperty("editMode", self.isEditMode)
|
|
||||||
|
|
||||||
# Import custom nodes
|
|
||||||
try:
|
|
||||||
custom_nodes = import_nodes_from_folder('Nodes')
|
|
||||||
for node_class in custom_nodes:
|
|
||||||
self.graph.register_node(node_class)
|
|
||||||
|
|
||||||
graph_menu = self.graph.get_context_menu('graph')
|
|
||||||
for node_class in custom_nodes:
|
|
||||||
node_type = f"{node_class.__identifier__}.{node_class.__name__}"
|
|
||||||
node_name = node_class.NODE_NAME
|
|
||||||
graph_menu.add_command(
|
|
||||||
f"Add {node_name}",
|
|
||||||
make_node_command(self.graph, node_type)
|
|
||||||
)
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error setting up custom nodes: {e}")
|
|
||||||
|
|
||||||
# Global update timer
|
# Global update timer
|
||||||
self.timer = QTimer(self)
|
self.timer = QTimer(self)
|
||||||
self.timer.timeout.connect(self.global_update)
|
self.timer.timeout.connect(self.global_update)
|
||||||
self.timer.start(500)
|
self.timer.start(500)
|
||||||
|
|
||||||
self.show()
|
|
||||||
self.nodeGraphWidget.setAttribute(Qt.WA_TransparentForMouseEvents, not self.isEditMode)
|
|
||||||
|
|
||||||
def toggleEditMode(self):
|
|
||||||
"""Toggle edit mode (pass-through clicks vs interactive)."""
|
|
||||||
self.isEditMode = not self.isEditMode
|
|
||||||
self.nodeGraphWidget.setAttribute(Qt.WA_TransparentForMouseEvents, not self.isEditMode)
|
|
||||||
self.editButton.setText("Exit Edit Mode" if self.isEditMode else "Enter Edit Mode")
|
|
||||||
if self.qml_root:
|
|
||||||
self.qml_root.setProperty("editMode", self.isEditMode)
|
|
||||||
|
|
||||||
def global_update(self):
|
def global_update(self):
|
||||||
"""Update all nodes periodically."""
|
"""Update all nodes periodically (to be implemented)."""
|
||||||
for node in self.graph.all_nodes():
|
pass
|
||||||
if hasattr(node, "process_input"):
|
|
||||||
node.process_input()
|
|
||||||
|
|
||||||
# Entry Point
|
# --- Entry Point ---
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
app = QApplication(sys.argv)
|
app = QApplication(sys.argv)
|
||||||
window = MainWindow()
|
window = MainWindow()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user