Is it possible to dynamically populate a ListView within a GridView ?
In our application, we need to display a GridView wich contains some elements of custom type OverviewEntry and in these elements, we have a QList of element of custom type ChannelEntry.
Some code is more usefull than a long description so, please found the related code (simplified, of course) :
Code:
//Main.cpp
...
m_viewer = new QQuickView();
...
QList<ChannelEntry *> channels;
for (int i=0; i<5; i++) {
for (int j=0; j<4; j++) {
channels.append(new ChannelEntry("foo"));
}
m_overviewList.append(new OverviewEntry("bar", channels));
}
...
QQmlContext *ctxt = m_viewer->rootContext();
ctxt
->setContextProperty
("overviewModel",
QVariant::fromValue(m_overviewList
));
...
Code:
//OverviewEntry.h
class OverviewEntry
: public QObject{
Q_OBJECT
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged
) ...
Q_PROPERTY(QList<ChannelEntry> channels READ channels WRITE setChannels NOTIFY channelsChanged)
...
QList<ChannelEntry *> m_channels;
};
Q_DECLARE_METATYPE(QList<ChannelEntry>)
Code:
//ChannelEntry.h
class ChannelEntry
: public QObject{
Q_OBJECT
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged
) ...
};
Code:
//Main.qml
...
GridView {
model: overviewModel
delegate : OverviewEntry {}
}
...
Code:
//OverviewEntry.qml
...
Text{
text: modelData.name
}
...
ListView {
model: modelData.channels
delegate : ChannelEntry {}
}
...
Code:
//ChannelEntry.qml
...
Text{
text: modelData.name
}
...
My GridView is well populated but my ListView remains empty... Even after 2-3 days of trying different approach...
So what am I missing ? Anyone has a clue, please ?
Re: Is it possible to dynamically populate a ListView within a GridView ?
Should this:
Code:
Q_PROPERTY(QList<ChannelEntry> channels READ channels WRITE setChannels NOTIFY channelsChanged)
be
Code:
Q_PROPERTY(QList<ChannelEntry *> channels READ channels WRITE setChannels NOTIFY channelsChanged)
?
[STRIKE]Also, I think all your properties need to point to the 'm_'<variableName>, where you've declared them as such[/STRIKE]
(no see below & also 'Property System' topic in doc.)
Re: Is it possible to dynamically populate a ListView within a GridView ?
Quote:
Originally Posted by
rickbsgu
Should this:
Q_PROPERTY(QList<ChannelEntry> channels READ channels WRITE setChannels NOTIFY channelsChanged)
be
Q_PROPERTY(QList<ChannelEntry *> m_channels READ channels WRITE setChannels NOTIFY channelsChanged)
?
Yes.
Quote:
Originally Posted by
rickbsgu
Also, I think all your properties need to point to the 'm_'<variableName>, where you've declared them as such.
No.
Quote:
Originally Posted by
andrioli.n
My GridView is well populated but my ListView remains empty... Even after 2-3 days of trying different approach...
So what am I missing ? Anyone has a clue, please ?
Aside from the error spotted by rickbsgu which probably happend when you simplied the code for pasting, and the ever growing channel list which probably has the same cause, this looks quite OK.
Normally you wouldn't depend on a certain type of model inside a delegate but that is OK as well.
Is your channels getter function being called?
Are ChannelEntry {} instance being created?
Cheers,
_
Re: Is it possible to dynamically populate a ListView within a GridView ?
First of all, thank you for your answers.
Quote:
Should this:
Q_PROPERTY(QList<ChannelEntry> channels READ channels WRITE setChannels NOTIFY channelsChanged)
be
Q_PROPERTY(QList<ChannelEntry *> m_channels READ channels WRITE setChannels NOTIFY channelsChanged)
?
Exact, but as anda_skoa said, it's due to simplification (it's a pointer in my real source code) but doesn't work anyway...
By the way, in the constructor of my OverviewEntry object :
Code:
m_overviewList.append(new OverviewEntry("bar", channels));
my variable channels (QList of ChannelEntry *) contains the right data. And the member m_channels is well filled by the same data.
All is functionnal until it reached the QML part.
Re: Is it possible to dynamically populate a ListView within a GridView ?
Quote:
Originally Posted by
andrioli.n
Exact, but as anda_skoa said, it's due to simplification (it's a pointer in my real source code) but doesn't work anyway...
Posting obviously wrong code has the problem of everyone finding the obvious problems.
Posting working code gives everyone a chance to spot the actual problem.
So it is a matter of whether you want help finding problems that don't exist or finding problems that you have as well.
Quote:
Originally Posted by
andrioli.n
All is functionnal until it reached the QML part.
Good! Then you can go ahead and try the suggested things to narrow the problem down.
Cheers,
_
Re: Is it possible to dynamically populate a ListView within a GridView ?
Quote:
Originally Posted by
anda_skoa
Posting obviously wrong code has the problem of everyone finding the obvious problems.
Posting working code gives everyone a chance to spot the actual problem.
So it is a matter of whether you want help finding problems that don't exist or finding problems that you have as well.
Thanks for the advice, the posted code wasn't wrong on purpose but due to a typo...
For trying the suggested things, I don't see any other leads. I checked your suggestions earlier but everything works good in this side of the code. I just can't access my embedded model in my QML. I'm stuck right there... :confused:
Re: Is it possible to dynamically populate a ListView within a GridView ?
Quote:
Originally Posted by
andrioli.n
For trying the suggested things, I don't see any other leads.
I suggested to things to look into in comment #3, but I don't see where you've posted your findings.
Maybe you can post the again?
Cheers,
_
Re: Is it possible to dynamically populate a ListView within a GridView ?
Quote:
Originally Posted by
anda_skoa
Normally you wouldn't depend on a certain type of model inside a delegate but that is OK as well.
Is your channels getter function being called?
Are ChannelEntry {} instance being created?
My apologies, I only talk about my OverviewEntry instance in my response but the ChannelEntry instances contained in variable m_channels are well instantiated.
Quote:
Originally Posted by
andrioli.n
By the way, in the constructor of my OverviewEntry object :
Code:
m_overviewList.append(new OverviewEntry("bar", channels));
my variable channels (QList of ChannelEntry *) contains the right data. And the member m_channels is well filled by the same data.
All is functionnal until it reached the QML part.
Any other suggestions ?
Thank you
Re: Is it possible to dynamically populate a ListView within a GridView ?
Quote:
Originally Posted by
andrioli.n
My apologies, I only talk about my OverviewEntry instance in my response but the ChannelEntry instances contained in variable m_channels are well instantiated.
Well, yes, you said that the C++ parts are working.
I mean the ChannelEntry QML elements. Are they being instantiated as often as they should.
Also, how did you determine that the property getter is being called?
Debug output? Breakpoint? Is it called on all the overview objects?
Cheers,
_
Re: Is it possible to dynamically populate a ListView within a GridView ?
Quote:
Originally Posted by
anda_skoa
I mean the ChannelEntry QML elements. Are they being instantiated as often as they should.
As I said in my first post, my GridView of OverviewEntry is well populated in QML but my ListView of ChannelEntry remains empty with a count of 0 element, even if the m_channels property contains my ChannelEntries.
So it doesn't seems to be a matter of how QML is interpreting my ChannelEntries objects but the list in itself, I believe.
Quote:
Originally Posted by
anda_skoa
Also, how did you determine that the property getter is being called?
Debug output? Breakpoint? Is it called on all the overview objects?
Well, I put some breakpoint in my OverviewEntry and ChannelEntry constructors and they are well instantiated. In terms of data, all is there. I guess I miss some specific QT declaration for making my QList<ChannelEntry *> usable in a model's member...
Re: Is it possible to dynamically populate a ListView within a GridView ?
Quote:
Originally Posted by
andrioli.n
Well, I put some breakpoint in my OverviewEntry and ChannelEntry constructors and they are well instantiated.
We could safe some time if you tell me how often I should repeat the question on whether the property getter is being called before you deem it worthy to be answered, then I can just do that in a single posting.
Unless of course you don't want to narrow down the problem?
Cheers,
_
Re: Is it possible to dynamically populate a ListView within a GridView ?
Quote:
Originally Posted by
anda_skoa
We could safe some time if you tell me how often I should repeat the question on whether the property getter is being called before you deem it worthy to be answered, then I can just do that in a single posting.
Unless of course you don't want to narrow down the problem?
Cheers,
_
I should read more carefully, my bad...
You're right, the getters of my OverviewEntry are well called but none of the ChannelEntry's one. (by the way, the ChannelEntry object is used elsewhere in the code and qml and worked well in a usual usage)
Re: Is it possible to dynamically populate a ListView within a GridView ?
Ok, so OverviewEntry::channel() is called for all instances of OverViewEntry?
And each call returned a non-empty list?
Cheers,
_
Re: Is it possible to dynamically populate a ListView within a GridView ?
Quote:
Originally Posted by
anda_skoa
Ok, so OverviewEntry::channel() is called for all instances of OverViewEntry?
And each call returned a non-empty list?
Cheers,
_
Exactly, that's why I suspect I misunderstood the way Qt is working behind the scene.
Re: Is it possible to dynamically populate a ListView within a GridView ?
Ok, so lets summarize:
- Your OverviewEntry QML instances are created
- They display the value of the name property
- They call the channels() getter when assigning to the ListView's model property
- The channels() getters return a correct, non-empty QList<ChannelEntry*>
- The ListView counts are 0
What kind of output do you get when you put this into the ListViews
Code:
onModelChanged: console.log("model for " + modelData.name + " is " + model);
Cheers,
_
Re: Is it possible to dynamically populate a ListView within a GridView ?
Quote:
Originally Posted by
anda_skoa
Ok, so lets summarize:
- Your OverviewEntry QML instances are created
- They display the value of the name property
- They call the channels() getter when assigning to the ListView's model property
- The channels() getters return a correct, non-empty QList<ChannelEntry*>
- The ListView counts are 0
What kind of output do you get when you put this into the ListViews
Code:
onModelChanged: console.log("model for " + modelData.name + " is " + model);
Cheers,
_
I just made the test and this is the output :
- qml: model for OverviewEntry 1 is QVariant(QList<ChannelEntry*>)
- qml: model for OverviewEntry 2 is QVariant(QList<ChannelEntry*>)
- qml: model for OverviewEntry 3 is QVariant(QList<ChannelEntry*>)
- qml: model for OverviewEntry 4 is QVariant(QList<ChannelEntry*>)
- qml: model for OverviewEntry 5 is QVariant(QList<ChannelEntry*>)
- qml: model for OverviewEntry 6 is QVariant(QList<ChannelEntry*>)
Re: Is it possible to dynamically populate a ListView within a GridView ?
Hmm.
You also have
Code:
Q_DECLARE_METATYPE(QList<ChannelEntry*>);
have you tried adding
Code:
Q_DECLARE_METATYPE(ChannelEntry*);
Cheers,
_
Re: Is it possible to dynamically populate a ListView within a GridView ?
Quote:
Originally Posted by
anda_skoa
Hmm.
You also have
Code:
Q_DECLARE_METATYPE(QList<ChannelEntry*>);
have you tried adding
Code:
Q_DECLARE_METATYPE(ChannelEntry*);
Cheers,
_
I tried but it doesn't change anything. Even with these two Q_DECLARE_METATYPE commented, it works same way.
But if I comment :
Code:
//Main.cpp
...
qmlRegisterType<ChannelEntry>("ChannelEntry", 1, 0, "ChannelEntry");
...
The app crashed...
Re: Is it possible to dynamically populate a ListView within a GridView ?
Probably because you are now using the same name for the registered type and the QML element type.
Change the second string argument here and maybe also use qmlRegisterUncreatableType()
Cheers,
_
Re: Is it possible to dynamically populate a ListView within a GridView ?
Quote:
Originally Posted by
anda_skoa
Probably because you are now using the same name for the registered type and the QML element type.
Change the second string argument here and maybe also use qmlRegisterUncreatableType()
Cheers,
_
I tried by refactoring my C++ type ChannelEntry into QChannelEntry and setting :
Code:
//Main.cpp
...
qmlRegisterType<QChannelEntry>("ChannelEntry", 1, 0, "QChannelEntry");
qmlRegisterUncreatableType<QChannelEntry>("ChannelEntry", 1, 0, "QChannelEntry","");
...
And the only change is the result of your debug output :
- qml: model for OverviewEntry 1 is QVariant(QList<QChannelEntry*>)
- qml: model for OverviewEntry 2 is QVariant(QList<QChannelEntry*>)
- qml: model for OverviewEntry 3 is QVariant(QList<QChannelEntry*>)
- qml: model for OverviewEntry 4 is QVariant(QList<QChannelEntry*>)
- qml: model for OverviewEntry 5 is QVariant(QList<QChannelEntry*>)
- qml: model for OverviewEntry 6 is QVariant(QList<QChannelEntry*>)
Remark : I also tried by commenting qmlRegisterType or qmlRegisterUncreatableType but with no success