Qt model for chat widget - qt

I need to create a chat widget for communication with toy satellite. The satellite can send a child text or a picture, while a child can send only text.
I am programming this app on Qt, but stuck with proper model creation. Sure it have to be a list model, but in my case I've got two types of messages (picture or text) and also some additional data, like date and location (last only in messages from satellite).
What class I better to subclass or use as is for my task? Is standard model?enough or I need to subclass list abstract model?
Also I red, that some customization can be done even inside a model, like font color and so on. I am just wondering, is it a right place for it, or I better set background color of messages in delegate?
Just to mention, this class will be then used in a qml.

I think the easiest way for you is to go with QTreeWidget()

Related

qt permanently display delegate in view

How do you use QStyledItemDelegate / QItemDelegate to permanently display a complex widget, i.e. to handle the Qt.DisplayRole, not just Qt.EditRole?
The documentation eludes to using paint()... but that's just way to complex! Let's take for example rendering a QTreeView or QTableVeiw inside of a QTableView cell.
There is QAbstractItemView.setIndexWidget(), but that is a bad idea as it only used to display static content (and whats the fun in static models?).
Note
I found part of the answer in another post, but it was only a small subset of the answer, so I thought it warranted a new post with proper question.
The key is to use QAbstractItemView.openPersistentEditor() to always keep the cell in edit mode.
Some additional key elements
The Qt.EditRole flag will need to be provided for the cells which use delegates.
QStyledItemDelegate.sizeHintChanged.emit(index) needs to be called anytime the size of the editor widget has changed.
Implementing QStyledItemDelegate.sizeHint() can be tricky and tedious (or you can do index.internalPointer().editor_widget.sizeHint() assuming you saved a reference of the editor to the internal pointer during QStyledItemDelegate.createEditor()
here is a good post on how to determine sizes: What are the mechanics of the default delegate for item views in Qt?
Caution
It should be mentioned that opening editors is costly, so if you have thousands of indexes and they are all loaded at once, it can take a while. There are many ways to mitigate this issue:
Load the model incrementally using a thread
Use Qt's fetchMore() mechanism
call openPersistentEditor incrementally (using a timer, or as they come into view for the first time)
call openPersistentEditor when the parent is expanded and closePersistentEditor when the parent is collapsed, and possibly restrict the use of expand-all on nodes with many children.

Best way to display dynamic element on a QListView (with Model/View)?

We can implement our own delegate to display rich text or images, but ListView can print static item only. You can't put "real" items into it, you can just paint them.
So, there isn't a way to show clickable hyperlink, ReTweet buttons, or load asynchronous images. Just think about a timeline-listview for Facebook or Twitter. That's what I'm working on.
Now, my solution is writing my listview in QML. Other widget are still native Qt widget. (I don't like a non-native pure QML user interface.)
QML is really flexible when doing that kind of work. Then export my model, finally put a viewer into my QMainWindow. But coding in two programming languages and trying to communicate with other native widget is really difficult.
So, what's the best way to display dynamic element?
The MVC framework is not very good for this kind of work.
To do it properly, you would need to provide a delegate for whatever dynamic types you need to display, and then provide an external mechanism that forces the model to emit dataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight) whenever these types need redrawing. It gets worse with interactive content because you would need to force an update on mouse overs in order to trigger the delegate painting.
For stuff like this you are better off using QGraphicsScene/View. Rather than rely on a model, each item can take of itself and you still get only essential repaints (via it's BSP structure), plus you have the option of hardware acceleration.

Custom QGestureRecognizer and QTouchEvents

I want to use a custom input device for multitouch input in a Qt application. I plan to create QTouchEvents based on my raw input data. I also want to generate custom gestures.
As far as I understand, I have to subclass QGestureRecognizer, create a QGesture for the widget I want to control and implement recognize() to filter my QTouchEvents and trigger the gesture when appropriate.
Now I have two questions:
Is this the correct way to do things?
How do I make sure that QTouchEvents still reach my widget (e.g. for dragging) when I already use them in my QGestureRecognizer? Or should all interaction with my widget be in form of gestures?
My progress on this matter so far, should anyone find themselves in a similar situation:
1.: It may be the right way but it doesn't work. Even after registering my recognizer with the application, it does not receive any QTouchEvents. I therefore installed my recognizer as an eventFilter for the target widget.
2.: At least when using an eventFilter, one can pass the event to the original receiver. See http://doc.qt.io/qt-5/qobject.html#eventFilter.

How to retrieve text from within QGraphicsView?

I'm attempting to retrieve certain text from a QT based window (on Windows). The text is contained in a QGraphicsView (actually, a class that inherits QGraphicsView).
I'm able to intercept it with a series of hooks due a specific call hierarchy in the application, though this is not a very desirable solution.
While the particular text item is likely to be custom, it would be of great help to just enumerate all the items in a QGraphicsView - if possible with class names.
Any pointers on how to go about this will be appreciated.
Note:
I've been having problems with the items() function of QGraphicsView, it seems to be impossible to iterate over either with QListIterator or with items().at().

How do I tell Qt to always show an editor in a QTableView?

I've got a QTableView for which I want to display the last column always in edit mode. (It's a QComboBox where the user should be able to always change the value.)
I think I've seen the solution in the Qt documentation, but I can't find it anymore. Is there a simple way of doing it?
I think I could archive this effect by using openPersistentEditor() for every cell, but I'm looking for a better way. (Like specifying it only one time for the whole column.)
One way to get the automatic editing behaviour is to call the view's setEditTriggers() function with the QAbstractItemView::AllEditTriggers value.
To display the contents of a given column in a certain way, take a look at QAbstractItemView::setItemDelegateForColumn(). This will let you specify a custom delegate just for those items that need it. However, it won't automatically create an editor widget for each of them (there could in principle be thousands of them), but you could use the delegate to render each item in a way that makes it look like an editor widget.
There are two possibilities:
Using setIndexWidget, but Trolltech writes:
This function should only be used to
display static content within the
visible area corresponding to an item
of data. If you want to display custom
dynamic content or implement a custom
editor widget, subclass QItemDelegate
instead.
(And it breaks the Model/View pattern…)
Or using a delegate's paint method. But here you have to implement everything like enabled/disabled elements yourself.
The QAbstractItemModel::flags virtual function is called to test if an item is editable (see Qt::ItemIsEditable). Take a look at Making the Model Editable in the Model/View Programming documentation.
I can't see an easy way to do this, but you might be able to manage by using a delegate. I honestly don't know exactly how it would work, but you should be able to get something working if you try hard enough. If you get a proper delegate, you should be able to set it on a whole view, one cell of a view, or just a column or row.

Resources