0
votes

First of all, sorry for my English.

Recentlly I'm working on a Qt project that supports plugins. In my program, I want to load plugins and create QAction instance for every plugin when the program starts. Then I met the problem: when the QAction instance is triggered, how can I know which one is triggered? (the trigger() signal of QAction has no parameters)

First I think about dynamic signal-slot connection using connect. But that requires dynamically declare slot function for every QAction instance. I don't know how to implement.

Then I have another idea. I try to implement a new Class MyAction which inherit QAction. And when it is triggered, I can emit my own signal with necessary parameters. Here's some code.

class MyAction: public QAction
{
public:
    int ID;
    MyAction();
    MyAction(const QIcon & icon, const QString & text, QObject * parent, int id)
    : QAction(icon, text, parent)
        {ID = id;}
    ~MyAction();

signals:
    void clicked(int id);

public slots:
    void trigger(){qDebug() << "triggered!"; emit clicked(ID);}
};

However, there's no "triggered!" in console.

I'll appreciate any suggestion!

2

2 Answers

3
votes

The QObject::sender() function will return the pointer to the object that has sent the corresponding signal. You can call it in your slot, like:

void onActionTrigger()
{
    QAction *action = qobject_cast<QAction *>(sender());
    [..]
}

I use qobject_cast here because sender() function returns a pointer to QObject.

1
votes

You can associate an integer, string or pointer to widget or object with a signal's sender using QSignalMapper. Here's an (untested) outline of how to use it:

// connect actions to map
auto mapper = new QSignalMapper(this);
connect(mapper, &QSignalMapper::mapped, this, &Myclass::trigger);

for (QAction *a: actions) {
     mapper.setMapping(a, a->text());
     connect(a, &QAction::triggered, mapper, &QSignalMapper::map);
}
// slot implementation
void Myclass::trigger(QString text)
{
    qDebug() << "triggered by action" << text;
}

I've left out the template arguments to connect() - you'll need to add them to select the correct overloads of the signals and slots, but I didn't want to clutter the above code.