2

Inside a slot I check the QObject::sender() but now I want to call this slot directly like a function.

Can I know how this slot was called inside of the slot? Either by signal-slot mechanism or simply by calling the slot like a function?

Resurrection
  • 3,916
  • 2
  • 34
  • 56
kakush
  • 3,334
  • 14
  • 47
  • 68
  • 1
    Put the code into another function which has a `bool fromSignal`, and call this other function from your slot with `true`, and call it directly with `false` elsewhere. – Johannes Schaub - litb Sep 04 '16 at 10:16
  • 1
    @JohannesSchaub-litb That'd make a fine answer, I think, better than the current ones. – hyde Sep 04 '16 at 20:46

3 Answers3

3

You can check the sender() in both cases. In case of the slot being called via a signal/slot mechanism the sender will return a pointer while when called as a method it will return null pointer.

Simple example:

class Test : public QObject
{
    Q_OBJECT
signals:
    void signal();

public slots:
    void slot() { qDebug() << sender(); }
};

And the use:

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    Test test;
    Test test2;

    QObject::connect(&test, &Test::signal, &test2, &Test::slot);

    test.signal(); //slot is caled by signal
    test2.slot(); //slot is called as method directly

    return a.exec();
}

And the output:

Test(0xa8e8aff5b0)

QObject(0x0)

Community
  • 1
  • 1
Resurrection
  • 3,916
  • 2
  • 34
  • 56
  • sender is not null when it is called as a method – kakush Sep 04 '16 at 07:51
  • It is even stated in the documentation: "Returns a pointer to the object that sent the signal, if called in a slot activated by a signal; otherwise it returns 0. The pointer is valid only during the execution of the slot that calls this function from this object's thread context." http://doc.qt.io/qt-5/qobject.html#sender – Resurrection Sep 04 '16 at 08:07
  • 2
    The "if called in a slot" here presumably means "if called during the activation of a slot". Which means if he calls the slot directly "as a function" but from another slot invoked by a signal, the directly called slot will observe a non-null return value. But that is not what he was looking for. And it renders your solution flawed if not invalid. – Johannes Schaub - litb Sep 04 '16 at 10:11
3
  1. Add a default parameter to your slot:

    public slots:
        void slot(bool calledBySignal = true);
    
  2. Set the parameter to false when calling the slot directly:

    void MyClass::method()
    {
        [...]
        slot(false);
        [...]
    }
    
  3. Leave the connect() calls as they are; don't add a bool parameter to the signals, nor change SLOT(slot()) to SLOT(slot(bool)).

Disadvantage: It's easy to forget setting the parameter.

If your slot doesn't need to be public, because connect()ing to it is handled from inside the class only, you should make it private and add a wrapper method that's to be called instead, but still you'll need some discipline when calling it from inside the class. Johannes' suggestion would solve these issues.

Murphy
  • 3,827
  • 4
  • 21
  • 35
0

Another idea to distinguish between direct function call vs. Signal/Slot-invocation:

Use the method int QObject::senderSignalIndex() const and check for -1

if(QObject::senderSignalIndex() == -1){
    //called directly as a function
} else {
    // invoked via Signal/SLot mechanism
}

Returns the meta-method index of the signal that called the currently executing slot, which is a member of the class returned by sender(). If called outside of a slot activated by a signal, -1 is returned.

see Qt 4.8 documentation

This looks like a clean way to distinguish and there is no chance of getting into trouble with a null-pointer in contrast to using QObject * QObject::sender() const.

Regards, Felix

Community
  • 1
  • 1
opt12
  • 320
  • 3
  • 11