QML GridView - report current selection to C++ code
-
I have a C++ QAbstracListModel subclass that I have set to a QML GridView.
What I want is to know the current selection of the GridView in C++, so that I could synchronize the selection from it with another C++-based view. Usually, if both views are C++-based, then the solution is to use a common QItemSelectionModel. Since I want to use this standard approach, I am currently trying to employ it to my hybrid views' case.
What I have currently done is to create a QItemSelectionModel, make it use my QAbstractListModel subclass and expose both to QML:
@
DataModel* const dataModel = new DataModel( this );
QItemSelectionModel* const dataSelectionModel = new QItemSelectionModel( dataModel );
QDeclarativeView* view = new QDeclarativeView;
view->rootContext()->setContextProperty( "dataModel", dataModel );
view->rootContext()->setContextProperty( "dataSelectionModel", dataSelectionModel );
@What I have done in the QML's GridView:
@
GridView {
id: gridView
model: dataModelonCurrentIndexChanged: { dataSelectionModel.setCurrentIndex( gridView.model.modelIndex( currentIndex ), 0x0002 | 0x0010 ) }
}
@The numbers: 0x0002 | 0x0010, are:
@
QItemSelectionModel::Select 0x0002 // All specified indexes will be selected.
QItemSelectionModel::Current 0x0010 // The current selection will be updated.
QItemSelectionModel::SelectCurrent Select | Current
@I exposed these to QML as well, but for the current test case I have given them as numbers.
What I want to achieve is to set the currently selected QModelIndex from the QML's GridView to the common QItemSelectionModel.
Currently, I receive an error for:
GridView.qml: TypeError: Result of expression 'gridView.model.modelIndex' [undefined] is not a function.Any suggestions how to achieve this?
-
[quote author="napajejenunedk0" date="1364800580"]
What I want to achieve is to set the currently selected QModelIndex from the QML's GridView to the common QItemSelectionModel.
Currently, I receive an error for:
GridView.qml: TypeError: Result of expression 'gridView.model.modelIndex' [undefined] is not a function.Any suggestions how to achieve this?
[/quote]Could you please share the source code of DataModel? I guess it inherits QAbstractItemModel but it seems that you have not declared a method with name modelIndex.
-
bq. I have a C++ QAbstractListModel subclass ...
The model is a derived QAbstractListModel. Yes there is no modelIndex method, but what is strange is that Googling about the way to get the QModelIndex, I found several places where function having this name was used.
I presume I should override the index() function in my derived class and mark it as invokable by QML, since the QAbstractListModel doesn't provide it as such:
@
Q_INVOKABLE virtual QModelIndex index ( int row, int column = 0, const QModelIndex & parent = QModelIndex() ) const;
@or:
@
public slots:
virtual QModelIndex index ( int row, int column = 0, const QModelIndex & parent = QModelIndex() ) const;
@since slots are automatically marked as invokable by QML. The second is meaningless, I think.
I have currently made another solution: I am using a helper class, that I have registered using qmlRegisterType ... and then I inform an instance of a QItemSelection model of the current selection.This is not a good solution, since if the GridView allows for sorting or reordering the data, I will get the wrong indices. So, probably the best question is if it is possible to set a QItemSelectionModel to a QML GridView?
-
[quote author="napajejenunedk0" date="1364823576"]bq. I have a C++ QAbstractListModel subclass ...
The model is a derived QAbstractListModel. Yes there is no modelIndex method, but what is strange is that Googling about the way to get the QModelIndex, I found several places where function having this name was used.
[/quote]OK, in this case the error is not surprising because your are calling a non-existing method. It is always better to rely on the "official Qt documentation of QAbstractListModel":http://qt-project.org/doc/qt-5.0/qtcore/qabstractlistmodel-members.html rather than just on examples.
I don't have much experience with QML and I don't fully understand your case. But in my opinion your approach seems a bit complicated and may be you should try to simplify it. Since you can get the current "index and item":http://qt-project.org/doc/qt-5.0/qtquick/qml-qtquick2-gridview.html#currentIndex-prop of the GridView hence you should be able to process it at a C++ and do what ever you what with the data and to update a QWidget. Btw "this thread":http://qt-project.org/forums/viewthread/20090 might give you some ideas for handling updates at the data of a GridView.
-
What I've found is that currently the easiest way to know whenever the
GridView's currently selected index has changed is to create a helper class
that has a Qt metasystem registered property:@
Q_PROPERTY( int selectedIndex READ selectedIndex WRITE setSelectedIndex
NOTIFY selectedIndexChanged )
@Then make your helper class accessible by QML:
@
qmlRegisterType< ItemSelectionModelQmlHelper >( "Models.Tools", 1, 0,
"ItemSelectionModelQmlHelper" );
@Then create an instantiate of this class and expose it to QML:
@
QDeclarativeView* const view = new QDeclarativeView;
ItemSelectionModelQmlHelper* const helper = new ItemSelectionModelQmlHelper(
this );
view->rootContex()->setContextProperty( "_itemSelectionModelQmlHelper",
helper );
@Then one can create the QItemSelectionModel and listen to the helper's
signal, so that to set the current index of the QItemSelectionModel.Of course as mentioned above, if you use a sorting or filtration of the data
being displayed in the GridView the currently selected GridView item's index
may not correspond to a row in your QAbstractItemModel derived class.
This won't be the case if you have done the filtration and/or sorting in C++
using the QSortFilterProxyModel. The problem with the non-coresponding index
will arise only if you do the sorting/filtration in QML.It would be best if GridView has the option to specify a selection model.