Trying to build an application with a UI in QML and accessing data from a Sqlite database.
The QML view has a TableView to display information in a data grid with a model in C++.
The model is a class inheriting from QSqlQueryModel with a query to the database: setQuery("SELECT * FROM Samples", GetDataBase())
I am adding a new row in the database table every second in another thread.
When I navigate to the view where the TableView is placed, the grid is populated with the information in the table. All good. But then, every time I add a new row I call setQuery again but the table is not updated. If I go back and forth to the view again it is populated with all the new rows.
I thought the view was "automatically" notified whenever the model changed but I suppose I am missing any kind of notification to let the view know that there is new rows or something??
Also...this is just a testing application but I foresee that in my real app the information to be displayed in the grid will change very fast and the table can have several rows of information (order hundred thousand rows) so I wonder if QSqlQueryModel is the right model for this kind data.
Related
I have a complex software that has several tables and forms.
I need to join some tables in a QSqlQueryModel and show the result into a QTableView
I use a QSortFilterProxyModel to have the ability to search in the QTableView that contain the result
When I create the QTableView and set the models, everything is OK, but when in another part of the software the database changes I can't see the data changes in the QTableView.
This is a snippet code:
void form1::setModels()
{
queryModel = new QSqlQueryModel();
queryModel->setQuery("SELECT * FROM table1");
proxyModel = new QSortFilterProxyModel(queryModel);
proxyModel->setSourceModel(queryModel);
ui->tableView->setModel(proxyModel);
}
This method is called when I create form1 and it's placed below the database connection and open() call
Before I call form1 with exec I try to do a: (form1 contains the QTableView mentioned)
queryModel->query().exec()
In order to update the query but nothing happens until I close the program and run again.
Is like something in the middle of the model doesn't update properly
If I call setModels() before the form exec method (not only in the constructor of the form), the QTableView show the change correctly but I think that is not the correct way to do an update, I already have the models, and the tableview, I think that I only need to update the query and refresh the QTableView and the QSortFilterProxyModel, but I don't find the way to do that.
but when in another part of the software the database changes I can't see the data changes in the QTableView.
You need to update the model, then the view will be notified of any changes done. When you change the table table1, you do a reset on this model(reset the model, then query the database).
I have a SAP UI5 V2 odata model with a two way binding to a table and to a form.
The table is displaying all records, and when clicking on a record, I am using setBindingContext to bind the selected table record to the form for editing. When typing in the form, the values dynamically update in the table (because of the two way binding). model.submitChanges() writes the change back to the server.
So displaying the list, and editing records in the list are working just fine.
Now for the problem How to create records with the same form?
I also want to use the same form for adding new records, but I cannot figure out how to unbind the form from a previously selected record, or otherwise create a new blank entry in the data model to be sent to the server.
All of the tutorials I have been able to find on doing UI5 Odata CRUD operations don't really address this problem.
I discovered this example in the documentation which pointed me in the correct direction.
In summary, you use the oModel.createEntry method to create a new entry in the oData Model. You then have to bind this new entry to your form with setBindingContext - this is the part I was missing.
I have a Page with a Table for which its datasource is a relation and needs to be sorted based on fields from another model:
Page
Datasource = Indicators
Table
Datasource = Indicators [one] : MetadataText [many] (relation)
The Table needs to be sorted based on a field from another Model called MetadataField, which has a one to many relation with MetadataText.
I have the datasource of MetadataField sorted. But the content in the Table appears in random order. When I first access the application, the Table is sorted by the order that the records were loaded. After view some records, the sorting of the records changes and keeps changing.
I am using Google Drive tables.
You can easily sort related records by one of the fields that belong to the related record itself, but only once (you'll received those records sorted from server).
But it seems, that you want to sort related records by their related record. App Maker will not be your friend in this case... but javascript will be! Since App Maker loads all related records you can safely sort them on client using javascript:
indicatorsDatasource.load(function() {
indicatorsDatasource.items.forEach(function(indicator) {
indicator.MetadataTexts.sort(function(a, b) {
return /* here goes your sorting logic */;
});
});
});
It will work in O(n * m * log(m)) in case you have n Indicators on the page and every indicator has m associated MetadataTexts. If you want to let users to sort related records by clicking table's header, you'll need to implement that logic on your own. So... all this hassle leads us to alternative solution! What if we decouple related records and introduce separated datasource for them? Having that you'll be able to use full power of App Maker's tables (sorting/paging) with almost no effort. You can take a look at implementation sample in Project Tracker template ViewProject page.
My team is evaluating JavaFX as a platform for a database application which will make intense use of TableViews. We are under impression that in order to display data in tables we will have to sub-class TableView and write our own ValueFactory classes for each column data type and presentation mode we are going to need.
For example if we wanted to display bit fields as Yes/No text and on/off checkboxes, we would need 2 ValueFactories or one ValueFactory and two CellFactories for bit data type.
Q1: Is our understanding correct?
Q2: Do any 3d party libraries exist that would allow us to simply set a data binding property of their version of TableView to a ResultSet for example and automatically display data with minor tweaking of display mode?
As evaluation goes on there are more questions arising.
Q3: Willl we have to create a data row class for every SQL query and ObservableList for every class, which would mean that every time we changed returned columns, we would have to re-write data row class? Would we have to implement paging by keeping resultsets in memory and re-populating the ObservableLists on scrolling too?
Q1 - For each column you should specify valueFactory - very easy. If you don't want to show value as default you can specify cellfactory - not so easy. I think best practice is create own class which will extends TableView and you will specify everything you need. You can also create your own TableCell classes etc. I think this work is not so hard in developing javafx app.
Q2 - I don't know but i would create own classes.
Q3 - Observablelist should contain your entity class. Each query should return list of entity objects. Value factory is link with some entity object property.
I need to show a custom made list of nodes from a database table that is frequently updated from external sources.
When changes are made to the database, the list needs to be updated on the screen accordingly.
For this I have implemented an ObservableList with an onChanged method that should check for changes and rebuild the custom list.
I my case the onChanged method will never fire when new data is added in the database, only when changes are made on the fly to the already defined ObservableList.
How can i let the ObservableList know when new data exists in the database ?
Thanks in advance!
Given your answer to jkaufmann it seems you need to change your logic.
Instead of rebuilding ObservableList each time you need to calculate the difference with new data and update ObservableList with new/removed data.