2
votes

I have two QML items with the same interface (signals emitted and handled) and different objectName property values:

Text {
    id: the_first_item
    objectName: "the_first_item"

    signal ping();

    onPing: {
        text = "pong! (variant 1)"
    }
}

Text {
    id: the_second_item
    objectName: "the_second_item"

    signal ping();

    onPing: {
        text = "pong! (variant 2)"
    }
}

I want to emit the ping signal in context of one of these items. In QML i would do it this way:

Item {
    onSomething: the_first_item.ping()
}

The problem is that I want to do it from C++ code. I have a pointer to instance of the QQuickItem class retrieved using findChild method and value of objectName property.

The only solution for handling signals triggered from the C++ code I have found was to define its own QObject derivative, declare a signal method in its body and then simply invoke it in context of an instance of this class:

class SomeLogic : public QObject
{
public signals:
    void ping();

public:
    void doSth() { ping(); }
};

Then, put a pointer to instance of this class in the engine's root context and connect a handler to this signal in QML in a following way:

Text {
    id: the_first_item
    //objectName: "the_first_item"

    Connections {
        target: the_instance_of_some_logic_property_name
        onPing: {
            text = "pong!"
        }
    }
}

But it's not good if I understand things correctly, because if the_second_item is defined in the same way, both of them will handle the ping signal emitted by the_instance_of_some_logic_property_name and I would like to trigger only one of them.

Now, while I am writing it, I think that maybe providing an utility function in each of items and then emit the ping signal in its own context, like that:

Text {
    id: the_first_item
    objectName: "the_first_item"

    signal ping();

    onPing: {
        text = "pong!"
    }

    function emitPing() {
        ping()
    }
}

In a simplier case, the emitPing would be enough (I wouldn't have to define the signal nor handler - I will just set the text in the emitPing function) but if I understand things correctly, the difference between function and signal is that the function invocation is synchronous while the signal is asynchronous and for some reasons (transistions between GUI states initiated from QML but handled in C++) I would like it to be asynchronous. I would also want to avoid necessity to write the no-brainer emitPing function everywhere.

Question: Is there a way to emit the ping signal, from the C++ code, in context of the_first_item only?

1

1 Answers

4
votes

Since it helped as a comment, now as an answere:

You can emit signals of any QObject using Qts MetaObject System. In this case, to emit the ping signal of the_first_item, just call QMetaObject::invokeMethod(the_first_item, "ping");

More informations about the whole meta object mechanisms can be found here: The Meta-Object System.