Fix async crashes like getting display name from Ui.

This commit is contained in:
Julien Wadel 2025-01-20 10:36:27 +01:00
parent 5e3a2d07aa
commit 05b7251797
3 changed files with 34 additions and 17 deletions

View file

@ -36,6 +36,7 @@ public:
QVariant getValue() const; QVariant getValue() const;
void onSetValue(QVariant value); void onSetValue(QVariant value);
void setDefaultValue(QVariant value); // Don't send signal void setDefaultValue(QVariant value); // Don't send signal
bool mDeleted = false;
signals: signals:
void requestValue(); void requestValue();
void setValue(QVariant value); void setValue(QVariant value);

View file

@ -40,24 +40,35 @@ VariantObject::VariantObject(QString name, QVariant defaultValue, QObject *paren
mConnection = QSharedPointer<SafeConnection<SafeObject, SafeObject>>( mConnection = QSharedPointer<SafeConnection<SafeObject, SafeObject>>(
new SafeConnection<SafeObject, SafeObject>(mCoreObject, mModelObject), &QObject::deleteLater); new SafeConnection<SafeObject, SafeObject>(mCoreObject, mModelObject), &QObject::deleteLater);
mConnection->makeConnectToCore(&SafeObject::setValue, [this, d = mName](QVariant value) { // Note: do not use member because 'this' is managed by GUI and can be deleted. Objects scope should have the same
mConnection->invokeToModel([this, value, d]() { // as connections so it should be fine to use the object directly.
if (mModelObject) mModelObject->onSetValue(value); mConnection->makeConnectToCore(&SafeObject::setValue,
}); [this, d = mName, modelObject = mModelObject.get()](QVariant value) {
}); if (modelObject && !modelObject->mDeleted)
mConnection->makeConnectToModel(&SafeObject::setValue, [this, d = mName, coreObject = mCoreObject](QVariant value) { mConnection->invokeToModel([this, value, d, modelObject]() {
// Note: do not use member because 'this' is managed by GUI and can be deleted. if (modelObject && !modelObject->mDeleted)
mConnection->invokeToCore([this, d, coreObject, value]() { modelObject->onSetValue(value);
if (coreObject) coreObject->onSetValue(value); });
}); });
}); mConnection->makeConnectToModel(&SafeObject::setValue,
mConnection->makeConnectToModel(&SafeObject::valueChanged, [this](QVariant value) { [this, d = mName, coreObject = mCoreObject.get()](QVariant value) {
mConnection->invokeToCore([this, value]() { mCoreObject->valueChanged(value); }); if (coreObject && !coreObject->mDeleted)
mConnection->invokeToCore([this, d, coreObject, value]() {
if (coreObject && !coreObject->mDeleted) coreObject->onSetValue(value);
});
});
mConnection->makeConnectToModel(&SafeObject::valueChanged, [this, coreObject = mCoreObject.get()](QVariant value) {
if (coreObject && !coreObject->mDeleted)
mConnection->invokeToCore([this, value, coreObject]() {
if (coreObject && !coreObject->mDeleted) coreObject->valueChanged(value);
});
}); });
connect(mCoreObject.get(), &SafeObject::valueChanged, this, &VariantObject::valueChanged); connect(mCoreObject.get(), &SafeObject::valueChanged, this, &VariantObject::valueChanged);
} }
VariantObject::~VariantObject() { VariantObject::~VariantObject() {
mCoreObject->mDeleted = true;
mModelObject->mDeleted = true;
} }
QVariant VariantObject::getValue() const { QVariant VariantObject::getValue() const {

View file

@ -38,13 +38,18 @@ class VariantObject : public QObject, public AbstractObject {
public: public:
VariantObject(QString name, QObject *parent = nullptr); VariantObject(QString name, QObject *parent = nullptr);
VariantObject(QString name, QVariant defaultValue, QObject *parent = nullptr); VariantObject(QString name, QVariant defaultValue, QObject *parent = nullptr);
~VariantObject(); virtual ~VariantObject();
// Note: do not use member because 'this' is managed by GUI and can be deleted. Objects scope should have the same
// as connections so it should be fine to use the object directly.
template <typename Func, typename... Args> template <typename Func, typename... Args>
void makeRequest(Func &&callable, Args &&...args) { void makeRequest(Func &&callable, Args &&...args) {
mConnection->makeConnectToCore(&SafeObject::requestValue, [this, callable, args...]() { mConnection->makeConnectToCore(&SafeObject::requestValue,
mConnection->invokeToModel([this, callable, args...]() { mModelObject->setValue(callable(args...)); }); [this, modelObject = mModelObject.get(), callable, args...]() {
}); mConnection->invokeToModel([this, modelObject, callable, args...]() {
modelObject->setValue(callable(args...));
});
});
} }
template <typename Sender, typename SenderClass> template <typename Sender, typename SenderClass>
void makeUpdate(Sender sender, SenderClass signal) { void makeUpdate(Sender sender, SenderClass signal) {