Deserializes graph data, creating all nodes, connections, and groups.
(self, data, offset=QPointF(0, 0))
| 378 | } |
| 379 | |
| 380 | def deserialize(self, data, offset=QPointF(0, 0)): |
| 381 | """Deserializes graph data, creating all nodes, connections, and groups.""" |
| 382 | if not data: |
| 383 | return |
| 384 | if offset == QPointF(0, 0): |
| 385 | self.clear_graph() |
| 386 | # Load graph metadata only when loading a complete graph (not copying/pasting) |
| 387 | self.graph_title = data.get("graph_title", "Untitled Graph") |
| 388 | self.graph_description = data.get("graph_description", "") |
| 389 | |
| 390 | uuid_to_node_map = {} |
| 391 | nodes_to_update = [] |
| 392 | |
| 393 | # First, deserialize nodes |
| 394 | for node_data in data.get("nodes", []): |
| 395 | original_pos = QPointF(node_data["pos"][0], node_data["pos"][1]) |
| 396 | new_pos = original_pos + offset |
| 397 | is_reroute = node_data.get("is_reroute", False) |
| 398 | |
| 399 | # Determine UUID first |
| 400 | old_uuid = node_data["uuid"] |
| 401 | new_uuid = str(uuid.uuid4()) if offset != QPointF(0, 0) else old_uuid |
| 402 | |
| 403 | if is_reroute: |
| 404 | node = self.create_node("", pos=(new_pos.x(), new_pos.y()), is_reroute=True, use_command=False) |
| 405 | else: |
| 406 | node = self.create_node(node_data["title"], pos=(new_pos.x(), new_pos.y()), use_command=False) |
| 407 | |
| 408 | # Set UUID BEFORE doing any operations that might reference the node |
| 409 | node.uuid = new_uuid |
| 410 | |
| 411 | node.description = node_data.get("description", "") |
| 412 | node.set_code(node_data.get("code", "")) |
| 413 | node.set_gui_code(node_data.get("gui_code", "")) |
| 414 | node.set_gui_get_values_code(node_data.get("gui_get_values_code", "")) |
| 415 | if "size" in node_data: |
| 416 | # Apply size validation during loading |
| 417 | loaded_width, loaded_height = node_data["size"] |
| 418 | |
| 419 | # Calculate minimum size requirements |
| 420 | min_width, min_height = node.calculate_absolute_minimum_size() |
| 421 | |
| 422 | # Ensure loaded size meets minimum requirements |
| 423 | corrected_width = max(loaded_width, min_width) |
| 424 | corrected_height = max(loaded_height, min_height) |
| 425 | |
| 426 | # Debug logging for size corrections |
| 427 | from utils.debug_config import should_debug, DEBUG_FILE_LOADING |
| 428 | if should_debug(DEBUG_FILE_LOADING) and (corrected_width != loaded_width or corrected_height != loaded_height): |
| 429 | print(f"DEBUG: Node '{node_data['title']}' size corrected from " |
| 430 | f"{loaded_width}x{loaded_height} to {corrected_width}x{corrected_height}") |
| 431 | |
| 432 | node.width, node.height = corrected_width, corrected_height |
| 433 | colors = node_data.get("colors", {}) |
| 434 | if "title" in colors: |
| 435 | node.color_title_bar = QColor(colors["title"]) |
| 436 | if "body" in colors: |
| 437 | node.color_body = QColor(colors["body"]) |