I have a ListView
with model
, number 6 and horizontal scrolling .Inside ListView
there is a GridView
with model
a ListModel
.The ListElement
's of the ListModel
in GridView
are about 200.Right now I have managed to display the first 35 items in GridView
scrolling horizontally the ListView
.What i want to do is to display in each "page" of ListView
, groups of 35 ListElements
untill all of them displayed.Which means, in first "page" of ListView
display the first 35 items of GridView
, after that , in second "page" the other 35 items etc. while scrolling horizontally.I tryied with the below code to make groups of DelegateModel
and filter it conditionally in two pages at first, following the answer in this question Working with delegate model and delegate model group dynamically QML? :
DelegateModel {
id: visualModel
delegate: myButton
model:appsModel
property var visualIndex: pageList.currentIndex
groups: [
DelegateModelGroup {
id:firstpage
includeByDefault: true
name: "firstpage"
},
DelegateModelGroup {
id:secondpage
includeByDefault: true
name: "secondpage"
}
]
onVisualIndexChanged:{
if(visualIndex===0){
filterOnGroup: "firstpage";page="first"
}else if(visualIndex===1){
filterOnGroup: "secondpage";page="second"
}else{}
console.log(visualIndex, page);
}
Component.onCompleted:{
for( var i = 0;i < items.count;i++ ) {
var element = items.get(i).model;
if(element.appId > 35) {
items.removeGroups(i, 1, "firstpage");
}else if(element.appId <= 35 && element.appId > 70) {
items.removeGroups(i, 1, "secondpage");
}else{}
}
}
}
but it does not work.pageList
is the ListView
.
Any suggestion will be appreciated.
Thank you.
Your DelegateModel is problematic, because, for 6 pages, you would need to create 6 DelegateModelGroups, and, to generalize for n pages, you would need to generalize further.
I highly recommend you engineer a reusable DelegateModelGroup
that has a from
and to
that will help choose different elements from the underlying model to be visible, e.g.
ListView {
model: colorModel.count / 35
delegate: GridView {
model: DelegateModel {
property from: index * 35
property to: from + 35
model: colorModel
filterOnGroup: "visible"
// ... heavy lifting needed here
}
}
}
That way, for 200 items, it would assign 6 items to the parent ListView, and, for the inner GridView the visual model will choose 35 records from the underlying model to be visible.
Here's a complete working example:
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
Page {
id: page
ListView {
width: 640
height: 480
anchors.centerIn: parent
model: Math.floor((colorModel.count + 34) / 35)
orientation: ListView.Horizontal
clip: true
snapMode: ListView.SnapOneItem
delegate: GridView {
width: ListView.view.width
height: ListView.view.height
cellWidth: 70
cellHeight: 70
header: Label {
width: GridView.view.width
text: `page ${index + 1}`
horizontalAlignment: Qt.AlignHCenter
}
model: MyDelegateModel {
from: index * 35
to: Math.min(from + 35, colorModel.count)
model: colorModel
delegate: MyDelegate { }
}
}
}
ColorModel {
id: colorModel
}
}
// MyDelegateModel.qml
import QtQuick
import QtQuick.Controls
DelegateModel {
property int from: 0
property int to: 10
groups: [
DelegateModelGroup {
id: newItems
name: "new"
includeByDefault: true
onCountChanged: {
newItems.setGroups(from, to - from, ["new","visible"]);
}
},
DelegateModelGroup { name: "visible" }
]
filterOnGroup: "visible"
}
// MyDelegate.qml
import QtQuick
import QtQuick.Controls
Label {
width: 70
height: 70
text: txt
verticalAlignment: Qt.AlignVCenter
horizontalAlignment: Qt.AlignHCenter
color: Qt.color(col).hslLightness > 0.5 ? "black" : "white"
wrapMode: Text.Wrap
background: Rectangle { color: col }
}
// ColorModel.qml
import QtQuick
import QtQuick.Controls
ListModel {
Component.onCompleted: {
for (let i = 0; i < 200; i++) {
let txt = i;
let col = Qt.rgba(Math.random(),Math.random(),Math.random()).toString();
append({txt,col});
}
}
}
You can Try it Online!