Qt – How to add calculated column in QsqlRelationalTableModel? - qt

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.

Related

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.

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

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

Qt - Mapping two tables on the widgets using QDataWidgetMapper

There are two tables in SQLite. For a simple example, person and address.
How to map data of the current man from both tables to form widgets? How should we synchronize the current index of the two tables, if we use two QDataWidgetMapper's?
Is there another approach to display related data on the form, including insertion?
I would be very grateful for your help and examples.
If I got you right, you want to join two SQL tables (say person and address). If this is the case, you would need a QSqlQueryModel.
Note that QDataWidgetMapper is used for sharing a single model among multiple widgets. However in this case, it seems you want to show data from two tables in one widget.
QSqlQueryModel *model = new QSqlQueryModel;
model->setQuery("SELECT name, city FROM person INNER JOIN address ON persion.id=address.id");
model->setHeaderData(0, Qt::Horizontal, tr("Name"));
model->setHeaderData(1, Qt::Horizontal, tr("City"));
Now, you can use this 2D model wherever you need. Also you can use a QDataWidgetMapper with this model in order to share its data with multiple widgets.

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

AdvancedDataGrid (grouping) quick jump to row

I have a problem with the AdvancedDataGrid widget. When the dataProvider is an ArrayCollection (of arrays), the nth array (within the collection) is also the nth row within the grid, and I can jump and display the i-th row by scripting
adg.selectedIndex = i;
adg.scrollToIndex(i);
now, when I add a Grouping, the dataProvider ends up being a GroupingCollection2, and now the index in the dataprovider's source does not correspond to the index in the adg anymore (which is understandable, because it's being grouped).
How can I select and display a row in grouped data efficiently? Currently, I have to traverse the adg and compare each found item with its data attributes in order to find the correct index of the row within the adg, and jump to it like above. This process is very slow. Any thoughts?
edited later:
We already used a caching object as Shaun suggests, but it still didn't compensate for the search times. In order to fully construct a sorting of a list of things (which this problem equates to, as the list is completely reordered by the grouping), you always have to know the entire set. In the end we didn't solve that problem. The project is over now. I will accept Shaun's answer if no one knows a better way in three days.
Depending on what values your comparing against you can store the objects in a dictionary with the lookup using the property/properties that would be searched for, this way you have a constant time look-up for the object (no need to look at every single item). Say for example your using a property called id on an object then you can create an AS object like
var idLookup:Object = {};
for(myObject in objects)
idLookup[myObject.id] = myObject;
//Say you want multiple properties
//idLookup[myObject.id]={};
//idLookup[myObject.id][myObject.otherProp] = myObject;
now say the user types in an id you go into the idLookup object at that id property and retrieve the object:
var myObject:Object = idLookup[userInput.text];
myAdg.expandItem(myObject, true);
now when you want to get an object by id you can just do
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/controls/AdvancedDataGrid.html#expandItem()
I haven't done any thorough testing of this directly, but use a similar concept for doing quick look-ups for advanced filtering. Let me know if this helps at all or is going in the wrong direction. Also if you could clarify a bit more in terms of what types/number of values you need to lookup and if there's the possibility for multiple matches etc. I may be able to provide a better answer.
Good luck,
Shaun

Resources