Loading data in QTreeView async - c++

I have a really big tree structure and I cant load the complete tree into Ram on client side. I am using Qt's QTreeView.
I want to load the sub elements of an item dynamically when the user expands the element.
Is there some signal that triggers when the user opens an item in the tree?
I am using the tutorial Simple Tree Model Example. When I do changes to the model the view has also to be updated. And I dont want to loose the focus to avoid user confusion!
and after some time (request to the server)...

You need to implement a subclass of QAbstractItemModel that can process needed amount of data. When an item is expanded in the view, it calls QAbstractItemModel::rowCount to determine children count and then QAbstractItemModel::flags and QAbstractItemModel::data to get children data. If requested data is not available at the moment, you should return placeholder data (i.e. 1 row containing "Loading"), and start a request. When the data is received, emit rowsAboutToBeInserted and rowsInserted signals to notify the view about new data (you should also notify it about removing "Loading" row). The view will then call rowCount, data, and flags methods again, and your model should now provide loaded data. Use QCache to keep last accessed data in memory.

Related

Update QAbstractItemModel from external data source

I want to use QAbstractItemModel as many times before which will hold a tree structure from an external model. This model can send notifications before deleting a row and after finishing deleting a row. These notofications can happen at any time (within same GUI thread).
QAbstractItemModel has the beginRemoveRows and endRemoveRows which is then connected to the model signals. What I don't understand is how I get the QModelIndex. My underlying data model does not know anything about QAbstractItemModel which is per design because I wan to use that in other places where Qt is inacceptable.
What is the right way to get the QModelIndex when I know what is the index of the element inside the underlying data structure and have access to the parent?

QStandardItemModel - how to ignore data changed event by row moved but NOT by cell changes from user

I'm using QStandardItemModel with table view.
My table allows moving rows and for user to edit a cell.
I want to catch the cell changes from user edits.
Problem is, if a user drags a row, and/or edits cells the same signals are fired. How can I grab the cell changes and ignore the row changes?
Solution is to Subclass the QStandarItemModel. Don't waste time trying to track from the GUI by item selected, clicked, pressed. Once you subclass, you're now in control of how the model (which is your data) is going to work, we can do anything.
In particular, look at ::itemData, the ::dropMimeData and ::setData functions. Between those items you know which are from internal dnd or not. You can store to var's, emit by Qt's sig/slot mechanism to GUI, or whatever your class needs.
Another useful tool is to hook into the deleget closeEditor func:
#include <QAbstractItemDelegate>
QAbstractItemDelegate * d = tv->itemDelegate();
connect(d, &QAbstractItemDelegate::closeEditor, this, &MainWindow::endEditHint);
Hope this helps anyone who might have this arise.

Qt/QML: Delay window rendering until data is available

I am building an application using Qt/QML. The QML of my main window is very complex and depends on lots of data which must be loaded via HTTP and then be processed by a C++ backend before it is ready to be displayed.
The C++ backend provides a signal which is fired when the data is ready. Until then, I want the window to be empty except for a simple loading indicator being displayed. Of course, I could use a simple overlay which hides my actual interface until the data is available, but this would mean that the QML code of my actual user interface is already loaded and tries to access the not-yet-available data, which is causing a lot of errors, so I would need to add dozens of dummy values and NOTIFY signals for each single property which might not yet be available.
What is the best way to completely deactivate a portion of QML code and to enable it as soon as a signal is triggered?
My personal experience is to not give data to your view components, don't bind them. For example, set your text value to an empty string or don't set it, set your image component source to an empty string or don't set it at first. When your signal comes in with data ready, you assign the data to the views at that time.

Is it fine to change model data internally before displaying views?

Is it fine to change model data internally before displaying views? For example
struct MainWindow : QMainWindow
{
MainWindow()
{
mTreeView->setModel(mModel);
mModel->appendChild(...); // No beginInsertRows() and similars are called
}
};
Although the model is set to the view before changing the model data, the view is not displayed since it is done in the constructor of main window. If the view is updated when it is displayed, I think the code should be okay.
When the model is already connected to one or more views I totally recommend calling the corresponding begin... and end... methods before and after the model modification. Those functions emit the signals which connected views (or proxies) must handle before and after the data is modified. Otherwise, the views may end up in an invalid state.
When no views (or proxies) are connected it is safe to do so.
It is fine to do so - your program will not crash, at least. However when you add new items to the model in the way you show in your example, your view will not display the update, especially if you do not use beginInsertRows().
If you want the view properly show the actual data, try to set model after you insert items in it. Otherwise you will need to call beginInsertRows() and endInsertRows() in your model class.

Qt Model-View data and model in separate thread

Previously, I asked about running model and view in different threads and now, I understand how it poses a problem. To circumvent the problem, I was thinking of duplication of data. When data is modified by the worker thread, it simultaneously sends an update to GUI/Model thread to update the model with the same data (so there exist a exact copy of data with the GUI/model).
Does this sound like a plausible approach? Other method is to use direct widgets with default models like QTableWidget etc. but then I need to do a lot of things that are powered by QTableView by default.
Please suggest!
Link to other question: Design Pattern, Qt Model/View and multiple threads
There are 2 scenarios that are possible but in either case you will need at least 2 objects as follows:
Data Object
Contains all functions required for maintaining and manipulating data. Data is stored in Pointers to objects describing data. Data Structures for this I will leave up to you.
Model
Contains a vector of pointers to data that is currently being displayed
Scenario 1
Data in QTableView is display only in which case on a QTimer signal or a different signal the data storage is locked and vector for display model is cut and put into the model and reset() is called to have QTableView repainted with new data.
Scenario 2
You can manipulate data via custom ItemEditor in QTableView. In this case the top widget that has QTableView should have references to your data object and QTableView and a signal handler for the signal emitted by the ItemEditor when the edit is complete. This signal handler will then lock the data structure inside data object and update it, once done it may cut a new vector to display but more often then not it won't have to.
How you will set up the locking, searching, etc is entirely up to you.