mirror of
https://github.com/bec-project/bec_widgets.git
synced 2025-07-14 03:31:50 +02:00
feat(safe_property): added decorator to handle errors in Property decorator from qt to not crash designer
This commit is contained in:
@ -2,10 +2,46 @@ import functools
|
|||||||
import sys
|
import sys
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
from qtpy.QtCore import QObject, Qt, Signal, Slot
|
from qtpy.QtCore import Property, QObject, Qt, Signal, Slot
|
||||||
from qtpy.QtWidgets import QApplication, QMessageBox, QPushButton, QVBoxLayout, QWidget
|
from qtpy.QtWidgets import QApplication, QMessageBox, QPushButton, QVBoxLayout, QWidget
|
||||||
|
|
||||||
|
|
||||||
|
def SafeProperty(prop_type, *prop_args, popup_error: bool = False, **prop_kwargs):
|
||||||
|
"""
|
||||||
|
Decorator to create a Qt Property with a safe setter that won't crash Designer on errors.
|
||||||
|
Behaves similarly to SafeSlot, but for properties.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
prop_type: The property type (e.g., str, bool, "QStringList", etc.)
|
||||||
|
popup_error (bool): If True, show popup on error, otherwise just handle it silently.
|
||||||
|
*prop_args, **prop_kwargs: Additional arguments and keyword arguments accepted by Property.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def decorator(getter):
|
||||||
|
class PropertyWrapper:
|
||||||
|
def __init__(self, getter_func):
|
||||||
|
self.getter_func = getter_func
|
||||||
|
|
||||||
|
def setter(self, setter_func):
|
||||||
|
@functools.wraps(setter_func)
|
||||||
|
def safe_setter(self_, value):
|
||||||
|
try:
|
||||||
|
return setter_func(self_, value)
|
||||||
|
except Exception:
|
||||||
|
if popup_error:
|
||||||
|
ErrorPopupUtility().custom_exception_hook(
|
||||||
|
*sys.exc_info(), popup_error=True
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
|
||||||
|
return Property(prop_type, self.getter_func, safe_setter, *prop_args, **prop_kwargs)
|
||||||
|
|
||||||
|
return PropertyWrapper(getter)
|
||||||
|
|
||||||
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
def SafeSlot(*slot_args, **slot_kwargs): # pylint: disable=invalid-name
|
def SafeSlot(*slot_args, **slot_kwargs): # pylint: disable=invalid-name
|
||||||
"""Function with args, acting like a decorator, applying "error_managed" decorator + Qt Slot
|
"""Function with args, acting like a decorator, applying "error_managed" decorator + Qt Slot
|
||||||
to the passed function, to display errors instead of potentially raising an exception
|
to the passed function, to display errors instead of potentially raising an exception
|
||||||
@ -91,6 +127,12 @@ class _ErrorPopupUtility(QObject):
|
|||||||
msg.setMinimumHeight(400)
|
msg.setMinimumHeight(400)
|
||||||
msg.exec_()
|
msg.exec_()
|
||||||
|
|
||||||
|
def show_property_error(self, title, message, widget):
|
||||||
|
"""
|
||||||
|
Show a property-specific error message.
|
||||||
|
"""
|
||||||
|
self.error_occurred.emit(title, message, widget)
|
||||||
|
|
||||||
def format_traceback(self, traceback_message: str) -> str:
|
def format_traceback(self, traceback_message: str) -> str:
|
||||||
"""
|
"""
|
||||||
Format the traceback message to be displayed in the error popup by adding indentation to each line.
|
Format the traceback message to be displayed in the error popup by adding indentation to each line.
|
||||||
|
Reference in New Issue
Block a user