02-06-2013 04:50 PM
I have a problem with calling a C++ function from a Javascript in QML.
I created a QVariantListDataModel subclass in C++ called MovieListModel. And in this class I have a function declared as
Q_INVOKABLE void reload(const QString& a);
This class is exported in c++ in the application constructor as
qmlRegisterType<movie::MovieListModel>("me.movie", 1, 0, "MovieListModel");
And in my QML file I can create a new component with MovieListMode {}.
So this all follows the example of Exposing C++ objects to QML in the C++ and QML integration sample and the MovieListModel seems to work well.
Except for an issue I'm having with calling the reload function in MovieListModel in the QML javascript.
Does anyone know what I'm missing?
Solved! Go to Solution.
02-06-2013 05:00 PM
02-06-2013 05:15 PM
yes. you need to provide some qml's
and why UI (QML/JS) needs to reload model ?
02-06-2013 05:38 PM - edited 02-06-2013 05:39 PM
Below is the QML I'm using it on. This QML is called from another QML as a component, which isn't really relevant to the issue. The Javascript reload function here calls the reload method in the C++ created MovieListModel class.
The reason why the MovieListModel has a reload function is because the source for the data list model comes from a remote JSON source and needs to be updated when the user presses the refresh button.
import bb.cascades 1.0
import me.movie 1.0
import com.labsquare 1.0
import "jslibs/homepagehandlers.js" as Handlers
Container {
id: homePageList
property string listTitle
property string listType
signal loadingDone()
Label {
text: listTitle
textStyle.base: textStyleBoldTitle.style
}
ListView {
id: movieListView
dataModel: movieListModel
listItemComponents: [
ListItemComponent {
type: "item"
Container {
id: movieItem
rightMargin: 20
WebImageView {
id: itemImage
scalingMethod: ScalingMethod.AspectFit
preferredWidth: 160
url: (function (){
if (ListItemData.poster_path) {
return "http://someImageurl/w342" + ListItemData.poster_path;
} else {
return "asset:///images/star.png";
}
})()
}
}
}
]
// Item type-mapping
function itemType (data, indexPath) {
console.log('Indexpath: ' + indexPath.length);
return 'item';
}
attachedObjects: [
MovieListModel {
id: movieListModel
//listType: listType
onModelLoaded: {
loadingDone();
}
}
]
layout: StackListLayout {
orientation: LayoutOrientation.LeftToRight
headerMode: ListHeaderMode.Overlay
}
onTriggered: {
Handlers.handleTrigger(dataModel, indexPath);
}
}
onCreationCompleted: {
movieListModel.listType = listType
}
attachedObjects: [
TextStyleDefinition {
id: textStyleBoldTitle
base: SystemDefaults.TextStyles.TitleText
fontWeight: FontWeight.Bold
color: Color.Black
}
]
function reload() {
movieListModel.reload('boo');
}
}
02-06-2013 05:46 PM
02-06-2013 05:54 PM
If my guess is correct you should do following
1. move reload function to ListView
function reload() {
movieListModel.reload('boo');
}
2. when you call reload from ListItemComponent do following
onClicked: {
movieItem.ListItem.view.reload();
}
02-06-2013 05:55 PM
The reload function is called from the parent QML. When I set a breakpoint in the QML's reload(), it correctly hits the movieListModel.reload() line. But the c++ code is never hit.
Here is the parent QML. HomePageList is the QML component from my previous reply.
import bb.cascades 1.0
import me.kahwah 1.0
import com.labsquare 1.0
import "jslibs/homepagehandlers.js" as Handlers
NavigationPane {
id: homePagePane
Page {
id: homeTab
Container {
layout: DockLayout {
}
Container {
HomePageList {
id: popularList
listTitle: 'Popular Movies'
listType: 'Popular'
}
HomePageList {
listTitle: 'Now Playing'
listType: 'NowPlaying'
}
HomePageList {
listTitle: 'Upcoming Movies'
listType: 'Upcoming'
}
}
}
actions: [
ActionItem {
id: refresh
title: "Refresh"
onTriggered: {
popularList.reload();
}
}
]
}
}
02-06-2013 06:05 PM
02-06-2013 06:05 PM - edited 02-06-2013 06:06 PM
Please check that you are calling qmlRegisterType before loading the qml file in main.cpp.
Doing this in constructor may be too late.
Have you checked the device logs? There should be an error message there.
02-06-2013 06:10 PM
OK. Now I see the issue
You should move you data model from UI to some cpp class and expose data model as property.
Q_PROPERTY(bb::cascades::GroupDataModel *getDataModel READ getDataModel CONSTANT);
in c++ setContextProperty to your class that manage data model.
qml->setContextProperty("_myClass",this);
ListView{
dataModel: _myClass.getDataModel
}
Create Q_INVOKABLE reload (QString) method in MyClass.
ActionItem {
id: refresh
title: "Refresh"
onTriggered: {
_myClass.reload("boo");
}
}
above should work fine. I did that many times already.