Incorporated Save / Load / Close Workflow functionality

This commit is contained in:
Nicole Rappe 2025-02-24 23:54:04 -07:00
parent ece52e783d
commit 377e525e37
3 changed files with 310 additions and 1 deletions

101
Workflows/test.json Normal file
View File

@ -0,0 +1,101 @@
{
"graph":{
"layout_direction":0,
"acyclic":true,
"pipe_collision":false,
"pipe_slicing":true,
"pipe_style":1,
"accept_connection_types":{},
"reject_connection_types":{}
},
"nodes":{
"0x25032ceeae0":{
"type_":"bunny-lab.io.data_node.DataNode",
"icon":null,
"name":"Data Node",
"color":[
13,
18,
23,
255
],
"border_color":[
74,
84,
85,
255
],
"text_color":[
255,
255,
255,
180
],
"disabled":false,
"selected":false,
"visible":true,
"width":269.0,
"height":74.2,
"pos":[
-140.9796961059538,
314.0813482866816
],
"layout_direction":0,
"port_deletion_allowed":false,
"subgraph_session":{},
"custom":{
"value":"56"
}
},
"0x250626018b0":{
"type_":"bunny-lab.io.data_node.DataNode",
"icon":null,
"name":"Data Node 1",
"color":[
13,
18,
23,
255
],
"border_color":[
74,
84,
85,
255
],
"text_color":[
255,
255,
255,
180
],
"disabled":false,
"selected":false,
"visible":true,
"width":269.0,
"height":74.2,
"pos":[
436.3232366823503,
297.12809369166183
],
"layout_direction":0,
"port_deletion_allowed":false,
"subgraph_session":{},
"custom":{
"value":"56"
}
}
},
"connections":[
{
"out":[
"0x25032ceeae0",
"Output"
],
"in":[
"0x250626018b0",
"Input"
]
}
]
}

139
Workflows/test2.json Normal file
View File

@ -0,0 +1,139 @@
{
"graph":{
"layout_direction":0,
"acyclic":true,
"pipe_collision":false,
"pipe_slicing":true,
"pipe_style":1,
"accept_connection_types":{},
"reject_connection_types":{}
},
"nodes":{
"0x25062603f80":{
"type_":"bunny-lab.io.data_node.DataNode",
"icon":null,
"name":"Data Node",
"color":[
13,
18,
23,
255
],
"border_color":[
74,
84,
85,
255
],
"text_color":[
255,
255,
255,
180
],
"disabled":false,
"selected":false,
"visible":true,
"width":269.0,
"height":74.2,
"pos":[
-183.12907239097774,
203.3685322819906
],
"layout_direction":0,
"port_deletion_allowed":false,
"subgraph_session":{},
"custom":{
"value":"25"
}
},
"0x250626141a0":{
"type_":"bunny-lab.io.data_node.DataNode",
"icon":null,
"name":"Data Node 1",
"color":[
13,
18,
23,
255
],
"border_color":[
74,
84,
85,
255
],
"text_color":[
255,
255,
255,
180
],
"disabled":false,
"selected":false,
"visible":true,
"width":269.0,
"height":74.2,
"pos":[
279.96246102035116,
512.9884977805091
],
"layout_direction":0,
"port_deletion_allowed":false,
"subgraph_session":{},
"custom":{
"value":"25"
}
},
"0x250626159d0":{
"type_":"bunny-lab.io.backdrop.BackdropNode",
"icon":null,
"name":"flask",
"color":[
5,
129,
138,
255
],
"border_color":[
74,
84,
85,
255
],
"text_color":[
255,
255,
255,
180
],
"disabled":false,
"selected":false,
"visible":true,
"width":804.65254462634,
"height":483.4329838785975,
"pos":[
-205.22360825550223,
146.33335545174936
],
"layout_direction":0,
"port_deletion_allowed":false,
"subgraph_session":{},
"custom":{
"backdrop_text":""
}
}
},
"connections":[
{
"out":[
"0x25062603f80",
"Output"
],
"in":[
"0x250626141a0",
"Input"
]
}
]
}

View File

@ -19,6 +19,17 @@ except ImportError:
print("WARNING: Could not monkey-patch QUndoStack. You may see an error if OdenGraphQt needs it.")
# ------------------------------------------------------------------
# ------------------------------------------------------------------
# MONKEY-PATCH to fix "'BackdropNodeItem' object has no attribute 'widgets'"
# by giving BackdropNodeItem a trivial widgets dictionary.
try:
from OdenGraphQt.nodes.backdrop_node import BackdropNodeItem
if not hasattr(BackdropNodeItem, "widgets"):
BackdropNodeItem.widgets = {}
except ImportError:
print("WARNING: Could not monkey-patch BackdropNodeItem to add `widgets`.")
# ------------------------------------------------------------------
# Import your data_manager so we can start the Flask server
from Modules import data_manager
@ -44,6 +55,7 @@ QtWidgets.QGraphicsScene.setSelectionArea = _patched_setSelectionArea
# --- END PATCH ---
from OdenGraphQt import NodeGraph, BaseNode
from OdenGraphQt.widgets.dialogs import FileDialog
def import_nodes_from_folder(package_name):
"""
@ -103,6 +115,57 @@ def make_node_command(graph, node_type_str):
return command
def ensure_workflows_folder():
"""
Ensures a 'Workflows' subfolder exists.
"""
if not os.path.exists("Workflows"):
os.makedirs("Workflows")
def close_workflow(graph: NodeGraph):
"""
Closes the current workflow (removes all nodes and connections).
"""
graph.clear_session()
def save_workflow(graph: NodeGraph):
"""
Saves the current workflow (including custom names, positions, wires, etc.) into a JSON file
in the 'Workflows' subfolder.
"""
ensure_workflows_folder()
file_filter = "JSON Files (*.json);;All Files (*.*)"
dlg = FileDialog.getSaveFileName(None, "Save Workflow", os.path.join("Workflows", ""), file_filter)
file_path = dlg[0]
if not file_path:
return # User canceled
if not file_path.lower().endswith(".json"):
file_path += ".json"
try:
graph.save_session(file_path)
print(f"Workflow saved to {file_path}")
except Exception as e:
QtWidgets.QMessageBox.critical(None, "Error Saving Workflow", str(e))
def load_workflow(graph: NodeGraph):
"""
Loads a workflow (including node values, connections, positions, etc.) from a specified JSON file.
"""
ensure_workflows_folder()
file_filter = "JSON Files (*.json);;All Files (*.*)"
dlg = FileDialog.getOpenFileName(None, "Load Workflow", os.path.join("Workflows", ""), file_filter)
file_path = dlg[0]
if not file_path:
return # User canceled
try:
graph.load_session(file_path)
print(f"Workflow loaded from {file_path}")
except Exception as e:
QtWidgets.QMessageBox.critical(None, "Error Loading Workflow", str(e))
if __name__ == "__main__":
app = QtWidgets.QApplication([])
@ -140,6 +203,12 @@ if __name__ == "__main__":
lambda: [graph.remove_node(node) for node in graph.selected_nodes()] if graph.selected_nodes() else None
)
# Add workflow menu commands
workflow_menu = graph_context_menu.add_menu("Workflow")
workflow_menu.add_command("Load Workflow", lambda: load_workflow(graph))
workflow_menu.add_command("Save Workflow", lambda: save_workflow(graph))
workflow_menu.add_command("Close Workflow", lambda: close_workflow(graph))
# Grid styling changes
graph.set_background_color(20, 20, 20) # Dark gray
graph.set_grid_color(60, 60, 60) # Gray grid lines