08-02-2012 06:36 AM
Hi,
I need custom headers (basically something like sections in QML native ListView component http://doc.qt.nokia.com/4.7-snapshot/qml-listview.
Any Ideas?
Thanks,
Jan
Solved! Go to Solution.
08-02-2012 08:45 AM
As far as I'm concerned I think that it isn't possible !
Same, you can't sort on key in ASC and on a second key in DESC.
Moreover the title of header section is the value used for sort data ![]()
So in waiting, I have add a prefix to my sort field and in the QML, I re-format the text.
In your case, I do "1-Today", "2-Yesterday","3-Last..." ; then I sort on this key ; and in QML I do value.substring(.....)
To remove my prefix.
Nicolas
08-02-2012 09:50 AM
Thanks, I had the same idea, but was looking for some better way.
Jan
08-07-2012 10:38 AM
You may just want your own data model to sort and feed the data you want displayed.
Stuart
08-08-2012 04:34 AM
attachedObjects: [
GroupDataModel {
id: groupDataModel
objectName: "groupDataModel"
sortingKeys: ["groupid", "name"]
grouping: ItemGrouping.ByFullValue
}
]
ListView {
id: myList
objectName: "myList"
dataModel: groupDataModel
listItemComponents: [
ListItemComponent {
type: "header"
Container {
Label {
text: {
ListItemData.groupname // Impossible !!! we have to write only "ListItemData" :(
}
}
}
},
ListItemComponent {
type: "item"
Container {
Label {
text: {
ListItemData.name // OK - Why is it different of Group item ???
}
}
}
}
]
function itemType(data, indexPath) {
if (indexPath.length == 1)
return "header";
else
return "item";
}
}
Above, what we should be able to write.
Then, in C++ we populate the datamodel :
{
// groupid, groupname, name
{ 1, "France", "Paris" },
{ 1, "France", "Lyon" },
{ 2, "Canada", "Vancouver" },
....
}
Use our own data model, it's quiet complex to do only this... So RIM should add this as a standard feature.
Note: in heaer item, we can't write "ListItemData.groupname" (only ListItemData). RIM should change it also. So as to be able to write in header field several labels :
ListItemComponent {
type: "header"
Container {
Label {
text: {
ListItemData.groupname
}
}
Label {
text: {
ListItemData.anotherfield
}
}
},
Nicolas
08-08-2012 02:52 PM - edited 08-08-2012 03:10 PM
GroupDataModel sorts the sort keys to present the headers. So I can't quite wrap my head around displaying some field that isn't derived from the sort key. It seems inherently dangerous to me.
I can see what you are trying to do, but it makes me uncomfortable for the data model to expect the data field to be marked correctly. A small error in the XML would not be easily detected, and you are repeating the sort order of the field in each line. This should be under the control of the data model.
So here are two other ideas:
As for writing your own data model: if you are comfortable with C++ then this should be straight-forward. The hardest part is dealing with QVariant. But if you find this daunting then it's probably not the right approach for you. OTOH, it gives you complete flexibility of how to organize your data for display.
Stuart
08-08-2012 02:57 PM - edited 08-08-2012 02:59 PM
As for the original question, I wouldn't hesitate much before writing my own data model to sort into the appropriate categories, as tomorrow my display will be different than today's display for the same data. It's the display that is changing, not the data.
But if a feature allowed me to provide my own sort into header buckets, I'd probably use that.
Stuart
08-08-2012 05:14 PM
I understand your point of view.
But, in the header container, we might to want to show several info. Today, we can only show one information.
Sample, if I want to do an UI for a mail client :
header1 == Today (3 messages unread)
item1_1 == subject 1
item1_2 == subject 2 (in bold)
item1_3 == subject 3 (in bold)
item1_4 == subject 4
item1_5 == subject 5 (in bold)
header2 == Yesterday (all messages read)
item2_1 == ...
item2_2 == ...
item2_3 == ...
item2_4 == ...
header3 == 7 days ago
....
header4 == 1 month ago
...
etc,
So need to sort on key and show an other field (and even several data) in the header container is usefull !
For the moment, I do in one field "key;value1;value2;value3" then, in javascript (embedded in qml) I split the string ![]()
Nicolas
08-09-2012 09:26 AM
If you have a great idea for a feature for GroupDataModel that leads to strong designs and is easy to explain and use, of course submit a feature request! A strong design would allow the same data to be displayed differently today than tomorrow (the original problem), and would allow the same data to be organized and displayed differently in different lists.
What you want is a way to specify:
- what header a record belongs to
- what that header text should be
- how to sort the headers
- how to sort the items within that header.
A frequently useful extension to GroupDataModel that would allow this without requiring the display information to be included in the data xml could make a good feature request.
However, consider your latest scenario.
You're now asking for the header text to depend not only on the sort keys but the number of children under the header, or the number of children under the header with a specific attributes set. Someone else is looking for a way to display only a subset of the data. Considering how easy it is to make your own data model to sort, create headers of whatever name you like, or filter the data, are you sure you don't just want the flexibility of your own data model?
Stuart
08-09-2012 03:29 PM
Here, an example :
import bb.cascades 1.0
// In my sample, I create a mail subject list grouping by date
// (usefull to write a mail client)
//
// list structs :
// + Today (3/4 unread mails)
// - *subject1
// - *subject2
// - *subject3
// - subject4
// + Yesterday (1/5 unread mail)
// - subject1
// - *subject2
// - subject3
// - subject4
// - subject5
// + One week ago (15 mails)
// - subject1
// - subject2
// - subject3
// - ...
// - subject15
// ....
//
// So I define 2 JSON/XML "data" model :
// + header model
// [ group=1 ; name=Today ; unread=3 ]
// [ group=2 ; name=Yesterday ; unread=1 ]
// [ group=3 ; name=One week ago ; unread=0 ]
// + data model
// [ group=1 ; name=subject1 ; read=false ; date=2012-08-09 11:25:00 ]
// [ group=1 ; name=subject2 ; read=false ; date=2012-08-09 10:12:00 ]
// [ group=1 ; name=subject3 ; read=false ; date=2012-08-09 09:00:00 ]
// [ group=1 ; name=subject4 ; read=true ; date=2012-08-09 08:00:00 ]
// [ group=2 ; name=subject1 ; read=true ; date=2012-08-08 21:00:00 ]
// [ group=2 ; name=subject2 ; read=false ; date=2012-08-08 20:00:00 ]
// [ group=2 ; name=subject3 ; read=true ; date=2012-08-08 19:00:00 ]
// [ group=2 ; name=subject4 ; read=true ; date=2012-08-08 17:00:00 ]
// [ group=2 ; name=subject5 ; read=true ; date=2012-08-08 15:00:00 ]
// [ group=3 ; name=subject1 ; read=true ; date=2012-08-03 14:00:00 ]
// [ group=3 ; name=subject2 ; read=true ; date=2012-08-02 13:00:00 ]
// [ group=3 ; name=subject3 ; read=true ; date=2012-08-01 12:00:00 ]
// [ ... ]
// [ date=3 ; name=subject15 ; read=true ; date=2012-07-25 01:00:00 ]
//
// /!\ : I have ordered the data only to be easy to read ; but of course, we can
// shuffle data
Container {
attachedObjects: [
// Define the header model
GroupHeaderModel {
id: groupHeaderModel
objectName: "groupHeaderModel"
// Set the field used to group the data
groupingKey: ["group"]
// Define an option "autohide" = true / false
// . true : if there isn't items, the group is hidden
// . false : if there isn't items, the group is shown
// Define option "stick" = true / false
// . true : the header is always shown while items during the scroll
// . false : the header scroll with the items
},
GroupDataModel {
id: groupDataModel
objectName: "groupDataModel"
// Set the field used to sort items (into a group)
sortingKeys: ["date", "name"]
}
]
ListView {
id: myList
objectName: "myList"
layout: StackListLayout {
}
layoutProperties: StackLayoutProperties {
}
headerModel: groupHeaderModel
dataModel: groupDataModel
listItemComponents: [
// First level - header
ListHeaderComponent {
type: "header"
Container {
Label {
// We can access to each element of JSON/XML stream
// ListItemsNumbers is built by system to return the items numbers
text: writeHeader(ListHeaderData.name, ListHeaderData.unread, ListItemsNumbers)
}
}
},
// Second level - item
ListItemComponent {
type: "item"
Container {
// Work as the current implementation :)
// Add built-in variables as to know (i ; j) coordinate in the list / gridlist.
// ListItemX : int = line index
// ListItemY : int = column index
// With these values, we can know if it's an odd or even lines to skin the background line :)
}
}
]
function writeHeader(name, unread, total) {
if (ListHeaderData.unread > 0)
info = ListHeaderData.unread + "/" + total + " unread";
else
info = total + " mails";
return title + info;
}
}
}