OK. As said the traditional way is to use Qt's SIGNAL() and SLOT() macros which returns a const char*. This const char* can be used as a function argument.
An example where this is used is here:
https://github.com/FreeCAD/FreeCAD/blob ... m.cpp#L696
Code: Select all
QWidget* PropertyStringItem::createEditor(QWidget* parent, const QObject* receiver, const char* method) const
{
ExpLineEdit *le = new ExpLineEdit(parent);
le->setFrame(false);
le->setReadOnly(isReadOnly());
QObject::connect(le, SIGNAL(textChanged(const QString&)), receiver, method);
if(isBound()) {
le->bind(getPath());
le->setAutoApply(autoApply());
}
return le;
}
See that "method" is directly passed to the connect() function. The function createEditor() then is called within:
https://github.com/FreeCAD/FreeCAD/blob ... e.cpp#L142
Code: Select all
editor = childItem->createEditor(parent, this, SLOT(valueChanged()));
This approach is fine but has one big drawback: you can pass any (invalid) string and the compiler cannot tell you if it's wrong. You have to test it at run-time and then Qt will print a warning if such a slot function doesn't exist.
The more modern C++ approach is to pass a function pointer. Then the compiler will tell you if the method exists.
createDeleteAction(ui->listWidgetReferences, onRefDeleted())
What you do is to call onRefDeleted() inside createDeleteAction() and its return value "void" cannot be bound to the std::function.
std::function expects a function pointer and if the passed function is a static class function or global function it will look like this:
Code: Select all
createDeleteAction(ui->listWidgetReferences, &globalRefDeleted) // see the & and the lack of ()
createDeleteAction(ui->listWidgetReferences, &MyClass::staticRefDeleted)
Now if you have a non-static function you cannot pass it the same way because it's bound to an instance of the class. So, you do it this way:
Code: Select all
createDeleteAction(ui->listWidgetReferences, std::bind(&MyClass::onRefDeleted, this))
This is a rather new feature and was added in C++11 I think. The boost library has this for many, many years and the syntax is quite similar:
Code: Select all
boost::bind(&MyClass::section, this, _1)
The boost::bind also works very well with Qt's concurrent framework (it's about multi-threading) as you can see here:
https://github.com/FreeCAD/FreeCAD/blob ... s.cpp#L276
But I am not sure if it works with Qt's connect function (I haven't tested it).
Now back to std::function. The implementation of createDeleteAction will look like this:
Code: Select all
void TaskDressUpParameters::createDeleteAction(QWidget* w, std::function<void()> delFunc)
{
// See https://doc.qt.io/qt-5/qobject.html#connect-3
deleteAction = new QAction(tr("Remove"), this);
deleteAction->setShortcut(QKeySequence::Delete);
#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
// display shortcut behind the context menu entry
deleteAction->setShortcutVisibleInContextMenu(true);
#endif
w->addAction(deleteAction);
w->setContextMenuPolicy(Qt::ActionsContextMenu);
connect(deleteAction, &QAction::triggered, this, delFunc);
}
And you call it like this:
Code: Select all
createDeleteAction(ui->listWidgetReferences, std::bind(&TaskFemConstraintBearing::onReferenceDeleted, this));