Reputation: 2567
Is there any way to bind arguments to slots ala boost::bind?
Here's a for-instance. I have a window with a tree view, and I want to allow the user to hide a column from a context menu. I end up doing something like:
void MyWindow::contextMenuEvent (QContextMenuEvent* event) {
m_column = view->columnAt (event->x());
QMenu menu;
menu.addAction (tr ("Hide Column"), this, SLOT (hideColumn ()));
// .. run the menu, etc
}
I need to capture the index of the column over which the context menu was activated and store it in a member variable that is used by my window's hideColumn
slot:
void MyWindow::hideColumn () {
view->setColumnHidden (m_column, true);
}
What I'd really like is to be able to bind the column number to my slot when I create the menu so I don't need this member variable. Basically the Qt equivalent of:
menu.addAction (tr ("Hide Column"),
boost::bind (&MyWindow::hideColumn, this,
event->columnAt (event->x()));
Or even better yet adapting the QAction::triggered signal and attaching it to the QTreeView::hideColumn slot, which takes the column index as an argument:
menu.addAction (tr ("Hide Column"),
boost::bind (&QTreeView::hideColumn, view,
event->columnAt (event->x())));
Is any of this do-able?
Upvotes: 4
Views: 6478
Reputation: 2927
As mentioned in a comment above, this is much easier in Qt 5 as you can connect a signal directly to a functor such as the result of std::tr1::bind() or boost::bind(). For Qt 4, there are a number of adapter libraries. Kaleb mentioned LibQxt. I have one at https://github.com/robertknight/qt-signal-tools
Upvotes: 3
Reputation: 91
Can't you use the setData
function of the QAction
?
void MyWindow::contextMenuEvent (QContextMenuEvent* event)
{
m_column = view->columnAt (event->x());
QMenu menu;
QAction * action = menu.addAction (tr ("Hide Column"), this, SLOT (hideColumn ()));
action->setData(QVariant(hideColumn));
}
void hideColumn()
{
const QAction * action = qobject_cast<const QAction *>(this->sender());
assert(action);
int hide_column = action->data().value<int>();
this->view->setColumnHidden (m_column, true);
}
Upvotes: 6
Reputation: 46479
LibQxt makes this possible through QxtBoundFunction and QxtMetaObject (the former does not show up in their documentation for some reason). It's an Open Source project, so you can grab the source if you're interested in the implementation. It uses the following syntax:
connect(
button,
SIGNAL(clicked()),
QxtMetaObject::bind(
lineEdit,
SLOT(setText(QString)),
Q_ARG(QString, "Hello World!)
)
);
LibQxt has some other very useful features like the ability to emit signals over a QIODevice, such as network connection.
Upvotes: 6
Reputation: 1650
AFAIK the only way is to create a QSignalMapper object to do this. It's like an extra level of indirection that can be used to generate a new signal providing the column index. It's a little bit clumsy IME, you can end up with lots of QSignalMapper objects hanging around all the time, but seems to be the best way at this time. (Ideally, IMO, you would be able to just supply any value such as the column index to connect() which would get passed as an argument to the slot, but you can't.)
Upvotes: 4