I’m new to developing apps for SailfishOS, but I have developed an app in Qt/QML for desktop before.
I cannot figure out how to connect QML signals with C++ slots.
On desktop Qt, I had this code (for example) to achieve that:
However, when I try something similar for Sailfish, I get a compilation error:
Can anyone explain to me please, what’s the correct way of doing this on Sailfish?
The Sailfish Code I tried
int main(int argc, char *argv[])
{
QScopedPointer<QGuiApplication> app(SailfishApp::application(argc, argv));
QScopedPointer<QQuickView> v(SailfishApp::createView());
// If you wish to publish your app on the Jolla harbour, it is recommended
// that you prefix your internal namespaces with "harbour.".
//
// For details see:
// https://harbour.jolla.com/faq#1.5.0
qmlRegisterType<TaskListModel>("harbour.at.nis", 1, 0, "TaskListModel");
// qmlRegisterType<TasksManager>("harbour.at.nis", 1, 0, "TasksManager");
QQmlApplicationEngine engine;
TasksManager manager;
QQmlContext* context = engine.rootContext();
context->setContextProperty("tasksManager", &manager);
QObject* item = engine.rootObjects().value(0);
QObject::connect(item, SIGNAL(setActiveTaskList(QString)), &manager, SLOT(setActiveTaskList(QString)));
// Start the application.
v->setSource(SailfishApp::pathTo("qml/harbour-silicatasks.qml"));
v->show();
return app->exec();
}
Your code should work. Check if you need to use qmlRegisterType<TaskManager>(…., it’s commented out in your example? If TaskManager inherits from QObject? Did you use ancient Qt on desktop as well? Maybe something was changed after 5.6, the version used by Sailfish?
@x2s no, the compiler does not complain about object live time. And it’s ok here to pass a pointer to a local variable as nothing will live longer than main
The compiler complains about missing type information in QVariant, a class that can store anything but needs to know a bit about what it stores
To understand the compiler error message you have to think like the compiler
QQmlContext::setContextProperty() can take either pointer to QObject or a reference to QVariant. Maybe you were trying to give it the former, but perhaps TasksManager does not inherit QObject? The compiler thought that perhaps you were aiming for the second option, and tries to convert TasksManager pointer to QVariant by first converting it to void pointer and then giving it to QVariant(void *) constructor - which has been deleted. Deleted in this context has nothing to do with memory management, it really means that you are not supposed to call that constructor.
All in all, this rather misleading error message is trying to tell you that you TasksManager should inherit QObject which it does not.
Thank you all for your help!In my hurry, I must have forgotten to derive from QObject With that being fixed, I still cannot get it to work. I still have the code from above (now with TasksManager derived from QObject) and in QML I have this:
Page
{
id: mainPage
signal setActiveTaskList(string listName)
/*
some other stuff
*/
MainPageButton
{
text: name
onClicked: {
tasksManager.setActiveTaskList(name)
var listPage = pageStack.animatorPush(Qt.resolvedUrl("ListPage.qml"), {name: name})
}
}
}
Now I can compile, but when running the app, I get an error in the console
[W] unknown:0 - QObject::connect: Cannot connect (null)::setActiveTaskList(QString) to QObject::setActiveTaskList(QString)
This is now exactly like I did it on my desktop app, so I’m really confused, what’s wrong here
Is your project available somewhere, e.g. github? It’s quite difficult to try to guess the source of the issue when you have only posted small pieces of the code.