Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

[Solved] QObject::setProperty does not fire the appropriate signal



  • Hey guys,

    I've defined a property like this:

    @
    Q_PROPERTY(int keepAliveInterval READ keepAliveInterval WRITE setKeepAliveInterval NOTIFY keepAliveIntervalChanged)
    @

    And now I set the property using the QObject::setProperty -Method as described here http://qt-project.org/doc/qt-5.0/qtcore/qobject.html#setProperty

    But that does not seem to fire the keepAliveIntervalChanged signal as I'd expect.

    How can I fire that signal?

    Background:
    What I'm trying to achieve is this:
    Read a JSON-file with property settings, convert that to an QVariantMap, for each item:
    apply that value to the property and fire the signal.

    This works so far, but no signal is fired....
    @
    QVariantMap::const_iterator iter;
    for (iter = variants.constBegin(); iter != variants.constEnd(); ++iter) {
    int pIdx = metaobject->indexOfProperty( iter.key().toLatin1() );

    if ( pIdx < 0 ) {
    continue;
    }
    object->setProperty(iter.key().toLatin1(), iter.value());
    }
    @


  • Lifetime Qt Champion

    Hi,

    Qt can't know when to trigger the signal (it's your business logic).

    Your setter can be something like:

    @
    void MyClass::setKeepAliveInterval(int interval)
    {
    if (_interval != interval) {
    _interval = interval;
    // do the needed stuff
    emit keepAliveIntervalChanged(_interval)
    }
    }
    @


  • Moderators

    did you specify the signal in your class definition?
    what did the connect statement return?



  • Hi, you have mis-understanded the usage and function of Q_PROPERTY.

    It won't fire signal for you automatically, you must emit the signal (keepAliveIntervalChanged) manually in you set function (setKeepAliveInterval).



  • Oh yes I forgot about that. You are right 1+1=2 and SGaist
    Of course my setter fires the signal if it's called.
    But the setter does not seem to be called.

    and to raven-worx:
    Yes, the connection is OK, cause I used the compiler checked connection style

    @
    connect(systemConfig(), &SystemConfiguration::keepAliveIntervalChanged, NetworkService::instance(), &NetworkService::setKeepAliveInterval);
    @


  • Moderators

    please make sure that iter.key().toLatin1() returns "keepAliveInterval" and also that setProperty() returns true...meaning the right property is set.



  • I checked the property afterwards and it's updated.

    But anyway. I finally found a solution, by manually fire the signal.

    @
    void QObjectHelper::qvariant2qobject(const QVariantMap& variants, QObject* object)
    {
    const QMetaObject *metaobject = object->metaObject();

    QVariantMap::const_iterator iter;
    for (iter = variants.constBegin(); iter != variants.constEnd(); ++iter) {
        int pIdx = metaobject->indexOfProperty( iter.key().toLatin1() );
    
        if ( pIdx < 0 ) {
            continue;
        }
        QByteArray propertyName = iter.key().toLatin1();
        object->setProperty(propertyName, iter.value());
    
        QMetaProperty metaproperty = metaobject->property( pIdx );
        QVariant::Type type = metaproperty.type();
        QVariant v( iter.value() );
        if ( v.canConvert( type ) ) {
            v.convert( type );
            metaproperty.write( object, v );
            if (metaproperty.hasNotifySignal()) {
                QGenericArgument ga(v.typeName(),v.data());
                metaproperty.notifySignal().invoke(object, Qt::QueuedConnection, ga);
            }
        } else if (QString(QLatin1String("QVariant")).compare(QLatin1String(metaproperty.typeName())) == 0) {
            metaproperty.write( object, v );
        }
    
    }
    

    }
    @


  • Lifetime Qt Champion

    Did you do the checks suggested by raven-worx ?

    I am using setProperty and it all works well.

    Also, if your setter follows the pattern of my previous post, the signal won't be fired when setting the same value.



  • [quote author="SGaist" date="1372417858"]Did you do the checks suggested by raven-worx ?[/quote]
    Yes, the result is true und the iter.key().toLatin1() returns “keepAliveInterval”

    [quote author="SGaist" date="1372417858"]Also, if your setter follows the pattern of my previous post, the signal won't be fired when setting the same value.[/quote]
    Wow!! That was the hint...
    Sometimes the solution is just too easy.
    Embarrassing....


  • Lifetime Qt Champion

    No biggies, this can happen to anyone (was bitten by something like this because the initial value of a member was the same as the one saved in settings so nothing happened)


Log in to reply