Question

I'm using c++ Qt library and I want to do something which would do :

connect(actionB11, SIGNAL(triggered()), this, SLOT(SetSomething(1, 1)));
connect(actionB12, SIGNAL(triggered()), this, SLOT(SetSomething(1, 2)));
connect(actionB21, SIGNAL(triggered()), this, SLOT(SetSomething(2, 1)));
connect(actionB22, SIGNAL(triggered()), this, SLOT(SetSomething(2, 2)));

The code above doesnt work because SIGNAL function has to have same number and argument types as SLOT function.

Does exist a way how to do it? I dont want to have about 20 function as SetSomething11, SetSomething12 calling SetSomething(1, 1) etc.

Was it helpful?

Solution

In situations like this you have three simple options:

  1. connect each QAction to its own slot (not good)
  2. use a QSignalMapper
  3. add each QAction to a QActionGroup and use the QActionGroup::triggered(QAction*) signal, coupled with setting each QAction's data (see QAction::setData() and QAction::data())

When you set the data for a QAction, you can only store one QVariant (i.e., one value). So if you want two values, I would recommend just creating a simple mapping, like this:

void Window::onActionGroupTriggered(QAction *action);
{
    int i = action->data().toInt();
    int a, b;
    a = i / 10;
    b = i - 10;
    setSomething(a, b); // for example if i = 15, then a = 1 and b = 5
}

OTHER TIPS

You may modify QAction class.

class QMyAction : public QAction
{
    Q_OBJECT
    QMyAction ( QObject * parent ) : 
    QAction(parent), _x(0), _y(0)
    {
         connect(this, SIGNAL(triggered(bool)), this, SLOT(re_trigger(bool)));
    } 
    QMyAction ( const QString & text, QObject * parent ) : 
    QAction (text, parent), _x(0), _y(0)
    {
         connect(this, SIGNAL(triggered(bool)), this, SLOT(re_trigger(bool)));
    }
    QMyAction ( const QIcon & icon, const QString & text, QObject * parent ) : 
    QAction(icon, text, parent), _x(0), _y(0)
    {
         connect(this, SIGNAL(triggered(bool)), this, SLOT(re_trigger(bool)));
    }
    void setX(int x)
    {
        _x = x;
    }
    int getX()
    {
        return _x;
    }
    void setY(int y)
    {
        _y = y;
    }
    int getY()
    {
        return _y;
    }

public slots:
    void re_trigger(bool)
    {
        emit triggered(_x, _y);
    }

signals:
    void triggered(int,int);

private:
    int _x;
    int _y;
};

Now, you can connect triggered(int,int) to SetSomething(int,int). But, you have to set x and y. Unless, they will always be 0.

You cannot use constant in SLOT signature, you have to use types there. When connecting signal to slot the slot must have the same subset of parameters signal has, otherwise they cannot be connected and QObject::connect() will return false.

connect(actionB11, SIGNAL(triggered()),
        this, SLOT(SetSomething()));

This slot takes no parameters, but you can use QObject::sender() to get pointer to the object, which emitted the signal. Then this pointer can be used to discriminate the source of the signal:

void SetSomething() {
    switch(sender()) {
    case actionB11;
        // do something
        break;
    case actionB12;
        // do something
        break;
    case actionB21;
        // do something
        break;
    case actionB22;
        // do something
        break;
    default:
        // Exceptional situation
    }
}

Alternatively you can use QSignalMapper to append additional discriminating parameters to slots.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top