Set background color to a cell of a tableView
-
My guess is, that you are now trying to let your proxy model do both the highlighting and the sorting, right? While that is possible, it complicates things a bit. You are now probably highlighting based on the row number for the requested index your proxy's data method, right? Well, sorting obviously changes the order of the rows, so those row numbers are not going to be valid anymore. You might, instead of triggering your highlight based on the requested row number, trigger it based on the row number of the source model that the row in the proxy model represents. For instance.
However, what I would do, is just keep the proxy doing one thing. Simply don't use the sorting facilities of your proxy model (or better yet, disable them), and use a separate proxy for the sorting and the filtering. So you end up with:
[Source model] -> [Highlight proxy] -> [Sort/filter proxy] -> [View]
Downside is that a highlighted row might be filtered out this way. I guess if you want to filter too, you might even have to go for:
[Source model] -> [Filter proxy] -> [Highlight proxy] -> [Sort proxy] -> [View]
-
But the problem with this order is, that the view by default will change the sort property on the model that it is displaying. In this case, that would be the Highlight proxy, while you want it to be the sort proxy. If you are going to have the filter and the sort proxies consecutive, you might as well use a single proxy to do the filtering and the sorting.
If the base model of the highlight proxy changes, it needs to re-query for the correct rows to highlight anyway. It would be the same if the base SQL model would be refreshed, for instance.
-
Hello,
I want to color a cell on a SqlRelationalTableModel.
The condition is, if the value of the cell is 1, I want it blue otherwise it should be red.
After reading the whole topic, I'm very confused. Could someone please help me out?
For example, how to start etc.
Is it the same way like poporacer did? "Just" inherit from QSortFilterProxyModel ?Thanks in advice
-
[quote author="Andre" date="1302589505"]My guess is, that you are now trying to let your proxy model do both the highlighting and the sorting, right? While that is possible, it complicates things a bit. You are now probably highlighting based on the row number for the requested index your proxy's data method, right? [/quote]
I guess that is correct because I am using the proxy model. I don't implement anything else in the proxy except for the highlight part (data function)
[quote author="Andre" date="1302589505"]Well, sorting obviously changes the order of the rows, so those row numbers are not going to be valid anymore. You might, instead of triggering your highlight based on the requested row number, trigger it based on the row number of the source model that the row in the proxy model represents. [/quote]
This seems like a clean method that would probably work. How would I do that?
[quote author="Andre" date="1302589505"] Simply don't use the sorting facilities of your proxy model (or better yet, disable them), and use a separate proxy for the sorting and the filtering. [/quote]
Since I only implement the data function in my proxy, I am not sure how to disable the sorting function in one proxy and implement it in another.
[quote author="Andre" date="1302589505"] So you end up with: [Source model] -> [Highlight proxy] -> [Sort/filter proxy] -> [View] Downside is that a highlighted row might be filtered out this way. I guess if you want to filter too, you might even have to go for: [Source model] -> [Filter proxy] -> [Highlight proxy] -> [Sort proxy] -> [View] [/quote]
So to implement this it would be something like this?
@printModel= new QSqlRelationalTableModel (this);
printModel-> setTable (mTableName); //or should this be called from sortProxy?
printModel->setFilter(mFilterString);//or should this be called from sortProxy?filterproxy->setSourceModel(printModel);
proxy->setSourceModel(filterProxy);
sortProxy->setSourceModel(proxy);ui->printView->setModel(sortProxy);
@
If the highlighted row is part of the view, can you identify the row and highlight the correct row via a setData function in the view and then capture the sort routine and then re-iterate through the view and make the appropriate color change? It seems like this is more difficult than it should be just to highlight an identified row. but if that is the way to do it, then I want to learn and understand how.
-
How can I link the query result which is placed in another class, with the variable(which is neccessary for the evaluating), from derived proxymodel class?
-
Can you explain that a little more fully please or even post some code? I think I understand but I could be off the mark.
Are you saying that you need some result from your query to be known in your prxoy for comparison? If so just add a member variable and a slot that sets it to your proxy and emit a signal from your query object that emits the needed value. Then connect the signal to the slot. In your slot you should also be sure to invalidate() the proxy.
-
Well,
I have a SqlRelationalTableModel and one column which holds either 1 or 2, shown is the corresponding name. (From Sqlite Database)Like it's descripted in this thread, I have to inherit from QSortFilterProxyModel and override data().
How do I implement it, that the "real" value behind the cell is going to be evaluated and not the name? Which way could be the best?
It may sound confused, sorry for that. Can you understand my matter?
-
I think what you are after, is that you need to convert the model index that you have for the proxy model to the model index that you need for the source model. QSortFilterProxyModel has mapping methods for both ways. You need mapToSource. This allows you to get the model index for the source data model that corresponds to the item that data() is currently called for in your proxy model.
@
// in your data reimplementation
if (role == Qt::BackgroundRole ) {
sourceIndex = mapToSource(proxyIndex);
if (sourceIndex.data(Qt::EditRole).toInt() == 1) {
return QVariant(Qt::blue);
}
}
@Or something like that.
-
I guess proxyIndex is equal to QModelIndex &index?
-
I have been reading to see if I can figure out how to get the table to be highlighted correctly after it is sorted but I have not been able to figure it out. I drew a blank with having four models as suggested but I did find something else that might work....but it isn't. I think I should be able to capture the signal from when the user clicks on the header and emit a signal to reload the table. Here is what I tried but when I debug, the signal does not get called.
@QHeaderView *horizHeader;
QSqlRelationalTableModel printModel;
MyProxyModel proxy;printModel= new QSqlRelationalTableModel (this);
printModel-> setTable (mTableName);
printModel-> setRelation (2, QSqlRelation("name", "id", "LName"));printModel->select();
proxy = new MyProxyModel(this);
proxy->setSourceModel(printModel);
ui->printView->setModel(proxy);
horizHeader= ui->printView->horizontalHeader(); connect(horizHeader, SIGNAL(sortIndicatorChanged (int) ),
proxy,SIGNAL(dataChanged ( ) ));
@
I am pretty sure it is because of the wrong syntax for the dataChanged signal, but I am not sure how to make it work. Will this work? Or am I going down the wrong path? Is the model method better? If so, how do I make it work? I have no clue on how to start. -
Hello,
I implemented the data function, but my tableview stays empty. The Grid is shown, but without any data inside. Here is the code:data implementation
@QVariant proxymodel::data(const QModelIndex &index, int role) const
{
QModelIndex sourceIndex;
if (!index.isValid())
return QVariant();if (role == Qt::BackgroundRole ) {
sourceIndex = mapToSource(index);
if (sourceIndex.data(Qt::EditRole).toInt() == 1) {
return QVariant(Qt::blue);
}
}
return QVariant();
}@the filltable function
@
void Window::fillTable()
{
model = new QSqlRelationalTableModel( tableView );
model->setTable("Protokoll");
proxy = new proxymodel(tableView);model->setRelation(12,QSqlRelation("Status", "ID", "Status")); model->setEditStrategy(QSqlTableModel::OnFieldChange); tableView->setItemDelegate(new QSqlRelationalDelegate(tableView)); proxy->setSourceModel(model);
tableView->setModel(proxy);
model->select();
}
@
What is wrong? -
It looks to me as if you have not finished implementing the data() function in your proxy. You check for the role to see if it is the background role and correctly return blue if the data matches your criteria.
However, you have not handled the case where the data does not match your criteria. You have also not handled any of the cases where the role is not the background role.
I think it needs to look more like this:
@
QVariant proxymodel::data(const QModelIndex &index, int role) const
{
QModelIndex sourceIndex;
if (!index.isValid())
return QVariant();// We only wish to override the background role if (role == Qt::BackgroundRole ) { sourceIndex = mapToSource(index); if (sourceIndex.data(Qt::EditRole).toInt() == 1) { return QVariant(Qt::blue); } else { return QSortFilterProxyModel::data( index, role ); } } // Let the base class handle all other cases return QSortFilterProxyModel::data( index, role );
}
@ -
Indeed, which can be further simplified to:
@
QVariant proxymodel::data(const QModelIndex &index, int role) const
{
QModelIndex sourceIndex;
if (!index.isValid())
return QVariant();// We only wish to override the background role if (role == Qt::BackgroundRole ) { sourceIndex = mapToSource(index); if (sourceIndex.data(Qt::EditRole).toInt() == 1) { return QVariant(Qt::blue); } } // Let the base class handle all other cases return QSortFilterProxyModel::data( index, role );
}
@:-)
-
It works now! Thank you!!
-
Sorry for double post, but I have a few questions remaining. One point is that the ItemDelegate does not work anymore.
@tableView->setItemDelegate(new QSqlRelationalDelegate(this));@And last but not least I cant access every cell in my table - It's just not editable?!