Use QAbstractProxyModel to add extra "virtual" columns in a table - qt

I have some data which are stored in a variable "myStorage" (a QVector).
I use a QAbstractTableModel to display these data in a QTableView : each entry in the QVector is a row in the table and each field in "myStruct" is a column.
Now I want to display more information, in a new column, without any modification to "myStruct" or to my model.
So I tried to make a new model class, derived from QAbstractProxyModel, which should add the new "virtual" column.
(For example, this column could be the average of 2 existing fields in "myStruct")
But I can't make it work : in the worst case, the program crash, in the best case, I have the right number of columns (one more than in the proxied model) and the right headers, but the data are shifted and the last column is empty.
Is there any minimal/simple example of a "add virtual column proxy model" working implementation ?
Should I use QIdentityProxyModel as a base class instead of QAbstractProxyModel ?
Thanks

Related

Vaadin 14 Grid Component Column containing checkbox does not sort

I am using Vaadin 14 grid. This grid contains a number of columns. A few of them need to represent boolean values, hence we use a checkbox component inside that column. This is done by using grid.addComponentColumn method. The text related columns a just added using grid.addColumn
Now we want to enable multisort on the grid. By default the sorting indicators (up/down arrow) in the header are shown for the text based columns but not for the boolean values .
After adding sorting to the boolean column /component column (addComponentColumn(...).setSortable(true) the sorting indicators in the headers are shown, but the sorting itself is not performed when changing the sort direction (none / asc / desc) using the arrows in the header.
How can I make this work?
Thanks in advance!
When you have custom logic for what's rendering in a column, then you also need to explicitly configure how sorting should be handled for that column.
If you're using in-memory data, then you do that using Column.setComparator. If you're using a backend data source, then you should instead use Column.setSortProperty and also ensure that the data provider actually considers the contents of Query.getSortOrders.
You can see an example of this in practice at https://cookbook.vaadin.com/sort-with-renderer.

Return one record from a form data source

I have a form with an existing data source. This data source has a one to many relationship to another table that is not an existing data source. Even though this second table contains multiple records (one to many), the field in the table that I want is duplicated across all records. Therefore I want to add this second table as a data source, but only return one record from it.
If I add the second table directly, than my form contains a line for each record instead of just one.
This problem was solved by creating a view to use as the new datasource. This view defined a calculated column that was based on a method that contained a query string that used TOP 1. The details in much more detail are at Martin Dráb's blog: https://community.dynamics.com/ax/b/goshoom/archive/2015/06/29/join-first-line-in-ax-2012.
Use the property LinkType=ExistJoin on the datasource for your second table.
See the TransactionLog form for example.

Qt display not all fields from Model

I'm displaying the query from an QSqlModel in a table view. e.G.
SELECT id, name FROM person;
I don't want to display id in the view, however I need the id when the user clicks on a row in that view.
Is there a model in Qt, which allows me to display only specified columns in views but also providing access to invisible ones?
I used to do it by hiding the columns e.g.:
ui->myview->setColumnHidden( 0, true );
But probably there is a better solution.
Since the OP amended the question to exclude using QTableView the only alternative that would seem to work is the creation of a new class derived from QSortFilterProxyModel. One can override the filterAcceptsColumn method
Documentation on the class QSortFilterProxyModel can be found here
QSortFilterProxyModel can be used for sorting items, filtering out items, or both. The model transforms the structure of a source model by mapping the model indexes it supplies to new indexes, corresponding to different locations, for views to use. This approach allows a given source model to be restructured as far as views are concerned without requiring any transformations on the underlying data, and without duplicating the data in memory.
You'd also have to override MapToSource and SourceToMap . There is a good example of usage in this StackOverflow's answer

Qt – How to add calculated column in QsqlRelationalTableModel?

I have an table view showed
part description, quantity, price
And I have a Model/View using this code
model = new QSqlRelationalTableModel(this);
model->setTable("parts");
model->setRelation(3,QSqlRelation("part_tbl","part_id","part_desc"));
model->select();
ui->tableView->setModel(model);
I need to add a new column that shows quantity * price in the table view. It's important to know I'm using QsqlRelationalTableModel
Help is appreciated, Thanks in advance
I think your best bet for handling this is to make either a model that inherits QSqlRelationalTableModel, or one that acts as a proxy (and contains a member for the model). Your new model will add the extra column, and when the data is requested for that column, use the data from the other columns to compute what is required.

Flex DataGridColumn with array of objects as data provider

I have a datagrid that uses an array of objects as the data provider. The objects are essentially key/value pairs:
{ foo:"something"}
{ bar:"hello"}
{ caca:"lorem"}
The datagrid has 2 columns. The first column is the key and the second column is the value. Right now my grid looks like:
My dataFormatter function makes sure that depending on the column (i.e. the dataField value) the correct key or value gets printed out. This works fine for displaying. However, as soon as I try and edit the value field it essentially adds a new value into the object with a key of '1'. For example, if I edit the {caca:"lorem"} object it will then contain the value {caca:"lorem",1:"new value"}.
Is there any possible way I can set the DataGridColumn so that when I edit a value it will update the value associated with the key rather than inserting a new value? I've tried using a custom item editor but it still does the insert. It seems like I need to be able to update the 'dataField' with the actual key value but I'm not sure how to do that.
Looks like you need to think about where your data is going to be stored. I would recommend listening for a CollectionEvent.COLLECTION_CHANGE event on your data model. That event object will contain info about what change occurred, and you can make any updates you need to make.

Resources