I am working on chat system, i have a conversation page with a list view inside it, the list view delegates are text conversations. I want to add seen/unseen or read/unread to conversation delegates, the list view sourced by a custom model and i need something like delegates attached property which changes when the delegate is actually being viewed. is there any attached property which tell me the visibility status of each delegate items?
-
1Well, there is the `visible`-property which tells you whether it is visible or hidden. Otherwise, you may need to define a custom property and set it on your own. – DuKes0mE Mar 15 '17 at 15:28
-
I checked visibility, but the visibility became true when delegate isn't fully visible, could please make it more clear about custom property ? – e.jahandar Mar 15 '17 at 16:05
-
Take a look at [QML Properties](http://doc.qt.io/qt-5/qtqml-syntax-objectattributes.html#property-attributes). Basically, you can define your own properties outside from the usual ones. For instance, you could define `property bool isRead` for your use-case. In order to set that property, you need to define your own signal handlers which adjust your QML objects accordingly. One way to do this: use the `indexAt()`-method of Listview to detect whether your delegate is currently visible. Or track the delegates position with the bounding box of ListView. – DuKes0mE Mar 15 '17 at 16:39
1 Answers
You have two problems to solve:
- How to store the information that the message has been viewd
- When to set it as read.
So one after another...
The custom property within the delegate
is no good idea, as the information stored in it will be lost once the delegate
will leave the viewport of the ListView
and is destroyed.
The best solution would be, to store it in the ListView
's model. This way it is also possible, if the model
is somewhat persistend, that the information survives a restart of the app.
Maybe you might achive something with the next options I will present, in combination with Settings
but I would consider this hackish.
If that is not possible, and the information does not need to survive an app's restart, you need to think about a way of storing it outside the ListView
. For example you could have a array
or object/dictionary
to store it (beware: No change notifications). You might also use a second ListView
that you keep in sync (which might prove not so easy!).
Finally you might put your ListView
as a model in an Instantiator
, which instantiates simple QtObjects
with one property: read.
The latter would be the easiest way to store it outside the delegates and the model, so I will show you how it works:
Instantiator {
id: additionalInfo
model: customModel
delegate: QtObject {
property bool read // <--- This is a custom defined property
}
}
ListView {
model: customModel
delegate: MyDelegate {
onRead: additionalInfo.objectAt(index).read = true
Text {
text: additionalInfo.objectAt(index).read ? 'read' : 'unread'
}
}
}
And now for the second part: When is it acutally read
The problem with the visibility you already discovered. Item
s become visible even outside the listView
when they are created for the buffer
. So you can't use this information. But you have the following information:
- The position of the
listModel.contentItem
(x and y) - The position of the
delegate
in relation to thelistModel.contentItem
- The width and height of your
delegate
So you can say: The delegate
is fully visible iff:
listModel.contentItem.x + delegate.x >= 0
listModel.contentItem.y + delegate.y >= 0
listModel.contentItem.y + delegate.y + delegate.height <= listModel.height
listModel.contentItem.x + delegate.x + delegate.width <= listModel.width
An example, on how a Item
might check if it is visible in a Flickable
(remember: a ListView
IS a Flickable
) can be found here
This is: If it is possible to have the whole delegate with the view. If it is larger - well you need to define some criterias when the delegate is considered read.
But again: If there is any posibility to have it as a role in your model
, put it there!

- 1
- 1

- 13,081
- 4
- 49
- 89
-
-
-
i used the conditions you mentioned in onYchanged of delegates but it didn't work as expected, The delegate's are are created even they aren't in view, so we need some conditions for checking delegates are currently in view or not and also an event to check for that, so what event i should use which properly triggers the list view flick in delegate component? – e.jahandar Apr 17 '17 at 10:37
-
I added a link to a recent example, where *dtech* explains how to determine an `Item`s visiblity inside a `Flickable`. It only considers the *y*-coordinate of the `Item` and the `height` is neglected, but it should be easy to expand this example into a solution. – derM - not here for BOT dreams Apr 19 '17 at 20:23