|
1 | 1 | from PySide6.QtWidgets import (
|
2 | 2 | QWidget, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit, QSpinBox,
|
3 |
| - QDoubleSpinBox, QComboBox, QCheckBox, QGroupBox, QPushButton, |
4 |
| - QApplication, QScrollArea, QTextEdit, QDateEdit, QTimeEdit, |
5 |
| - QDateTimeEdit, QTabWidget, QFrame, QSplitter, QTreeWidget, |
6 |
| - QTreeWidgetItem, QHeaderView, QFormLayout, QMessageBox, |
7 |
| - QStackedWidget, QSlider, QProgressBar, QDial, QLCDNumber, |
8 |
| - QListWidget, QListWidgetItem, QTableWidget, QTableWidgetItem |
| 3 | + QDoubleSpinBox, QComboBox, QCheckBox, QPushButton, QScrollArea, |
| 4 | + QTextEdit, QDateEdit, QTimeEdit, QDateTimeEdit, QFrame, QMessageBox, |
| 5 | + QStackedWidget |
9 | 6 | )
|
10 |
| -from PySide6.QtCore import Qt, QDate, QTime, QDateTime, QTimer, Signal, QObject, QUrl, QCoreApplication |
11 |
| -from PySide6.QtGui import QValidator, QRegularExpressionValidator, QFont, QPalette, QColor |
| 7 | +from PySide6.QtCore import Qt, QDate, QTime, QDateTime, Signal |
| 8 | +from PySide6.QtGui import QRegularExpressionValidator |
12 | 9 | import json
|
13 | 10 | import re
|
14 |
| -import uuid |
15 |
| -import base64 |
16 |
| -from datetime import datetime, date, time |
17 |
| -from typing import Any, Dict, List, Optional, Union, Callable, Set |
| 11 | +from typing import Any, Dict, List, Optional, Union, Callable |
18 | 12 | from urllib.parse import urlparse
|
19 | 13 | import ipaddress
|
20 | 14 | import email.utils
|
|
171 | 165 | }
|
172 | 166 | """
|
173 | 167 |
|
| 168 | + |
174 | 169 | class ValidationError:
|
175 | 170 | """Custom validation error class (not an Exception)"""
|
176 | 171 | def __init__(self, message: str, path: str = "", schema_path: str = ""):
|
@@ -648,6 +643,8 @@ def validate_value(self) -> List[ValidationError]:
|
648 | 643 | """Validate current value against schema"""
|
649 | 644 | try:
|
650 | 645 | value = self.get_value()
|
| 646 | + if value is None and self.schema.get("type") == "array": |
| 647 | + value = [] |
651 | 648 | return self.validator.validate(value, self.schema, self.path)
|
652 | 649 | except Exception as e:
|
653 | 650 | return [ValidationError(str(e), self.path)]
|
@@ -1043,7 +1040,32 @@ def update_controls(self):
|
1043 | 1040 |
|
1044 | 1041 | def get_value(self) -> List[Any]:
|
1045 | 1042 | """Get array values"""
|
1046 |
| - return [widget.get_value() for widget in self.item_widgets] |
| 1043 | + values = [] |
| 1044 | + for i in range(self.items_layout.count() - 1): |
| 1045 | + item_container = self.items_layout.itemAt(i).widget() |
| 1046 | + if not item_container: |
| 1047 | + continue |
| 1048 | + |
| 1049 | + container_layout = item_container.layout() |
| 1050 | + if not container_layout: |
| 1051 | + continue |
| 1052 | + |
| 1053 | + widget_item = container_layout.itemAt(1) |
| 1054 | + if not widget_item: |
| 1055 | + continue |
| 1056 | + |
| 1057 | + item_widget = widget_item.widget() |
| 1058 | + if not hasattr(item_widget, 'get_value'): |
| 1059 | + continue |
| 1060 | + |
| 1061 | + try: |
| 1062 | + value = item_widget.get_value() |
| 1063 | + if value is not None: |
| 1064 | + values.append(value) |
| 1065 | + except Exception as e: |
| 1066 | + print(f"Error getting array item value: {e}") |
| 1067 | + |
| 1068 | + return values |
1047 | 1069 |
|
1048 | 1070 | def set_value(self, value: List[Any]):
|
1049 | 1071 | """Set array values"""
|
@@ -1207,31 +1229,39 @@ def _validate_object(self, data: Dict, schema: Dict, path: str, errors: List[Val
|
1207 | 1229 | errors.append(ValidationError(f"Required property '{prop_name}' is missing", path))
|
1208 | 1230 |
|
1209 | 1231 | def get_value(self) -> Dict[str, Any]:
|
1210 |
| - result = {} |
1211 |
| - for prop_name, widget in self.property_widgets.items(): |
1212 |
| - try: |
1213 |
| - value = widget.get_value() |
1214 |
| - if value is not None: |
1215 |
| - # Filter keys that are actually in the current schema |
1216 |
| - if prop_name in self.schema.get("properties", {}): |
1217 |
| - prop_schema = self.schema["properties"][prop_name] |
1218 |
| - |
1219 |
| - # If this is a conditional schema, apply its 'if' to see if 'then' or 'else' is active |
1220 |
| - if "if" in prop_schema and isinstance(widget, ConditionalWidget): |
1221 |
| - try: |
1222 |
| - active_value = value |
1223 |
| - allowed_keys = set(widget._current_schema.get("properties", {}).keys()) if widget._current_schema else set() |
1224 |
| - if isinstance(active_value, dict): |
1225 |
| - active_value = {k: v for k, v in active_value.items() if k in allowed_keys} |
1226 |
| - result[prop_name] = active_value |
1227 |
| - except Exception as e: |
1228 |
| - print(f"Error filtering conditional value for {prop_name}: {e}") |
1229 |
| - else: |
1230 |
| - result[prop_name] = value |
1231 |
| - except Exception as e: |
1232 |
| - print(f"Error getting value for {prop_name}: {e}") |
1233 |
| - return result |
1234 |
| - |
| 1232 | + result = {} |
| 1233 | + for prop_name, widget in self.property_widgets.items(): |
| 1234 | + if widget is None or not hasattr(widget, 'get_value'): |
| 1235 | + continue |
| 1236 | + |
| 1237 | + try: |
| 1238 | + # Check if widget is properly initialized |
| 1239 | + if not widget.isVisible() and isinstance(widget, (OneOfWidget, AnyOfWidget)): |
| 1240 | + continue |
| 1241 | + |
| 1242 | + value = widget.get_value() |
| 1243 | + if value is not None: |
| 1244 | + # Filter keys that are actually in the current schema |
| 1245 | + if prop_name in self.schema.get("properties", {}): |
| 1246 | + prop_schema = self.schema["properties"][prop_name] |
| 1247 | + |
| 1248 | + # Handle conditional schemas |
| 1249 | + if "if" in prop_schema and isinstance(widget, ConditionalWidget): |
| 1250 | + try: |
| 1251 | + active_value = value |
| 1252 | + allowed_keys = set(widget._current_schema.get("properties", {}).keys()) if widget._current_schema else set() |
| 1253 | + if isinstance(active_value, dict): |
| 1254 | + active_value = {k: v for k, v in active_value.items() if k in allowed_keys} |
| 1255 | + result[prop_name] = active_value |
| 1256 | + except Exception: |
| 1257 | + pass |
| 1258 | + else: |
| 1259 | + result[prop_name] = value |
| 1260 | + except Exception: |
| 1261 | + pass |
| 1262 | + |
| 1263 | + return result |
| 1264 | + |
1235 | 1265 | def set_value(self, value: Dict[str, Any]):
|
1236 | 1266 | if not isinstance(value, dict):
|
1237 | 1267 | return
|
@@ -1352,6 +1382,23 @@ def _get_parent_context(self) -> Dict[str, Any]:
|
1352 | 1382 | except:
|
1353 | 1383 | return {}
|
1354 | 1384 |
|
| 1385 | + def get_value(self) -> Any: |
| 1386 | + current_index = self.selector.currentIndex() |
| 1387 | + if 0 <= current_index < len(self.option_widgets): |
| 1388 | + current_widget = self.option_widgets[current_index] |
| 1389 | + try: |
| 1390 | + value = current_widget.get_value() |
| 1391 | + if isinstance(value, dict): |
| 1392 | + schema_option = self.schema["oneOf"][current_index] |
| 1393 | + if "properties" in schema_option and "type" in schema_option["properties"]: |
| 1394 | + type_value = schema_option["properties"]["type"].get("const") |
| 1395 | + if type_value: |
| 1396 | + value["type"] = type_value |
| 1397 | + return value |
| 1398 | + except Exception as e: |
| 1399 | + print(f"Error getting oneOf value: {e}") |
| 1400 | + return None |
| 1401 | + |
1355 | 1402 | def set_value(self, value: Any):
|
1356 | 1403 | """Enhanced value setting with better matching"""
|
1357 | 1404 | best_match_index = 0
|
|
0 commit comments