tags:

views:

934

answers:

2

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?

+3  A: 

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.)

Reed Hedges
Yup. The QT signals are pretty low-level (in the current version at least, there might be hope in the far future ;). Actually they're text-based (just look inside a moc_xx.cpp file or how the SLOT/SIGNAL macros are defined.)
Marcus Lindblom
+2  A: 

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.

Kaleb Pederson