PDA

View Full Version : call data() function after QHeaderview Sort



poporacer
22nd April 2011, 21:22
I posted this in the Newbie section and haven't gotten a response. I thought that maybe this was more than a newbie question. Sorry if I shouldn't have double posted. I have a QTableView that is based on a SQLRelational model. I subclassed QSortFilterProxyModel to be able to use the data() function to color certain cells based on a previous determination of the row. I was able to sucessfully do that, however if the user sorts the table by clicking on the header, the table sorts properly but the cells (not the correct data) that were previously highlighted are still highlighted. How do I get the tableview to have the properly highlighted rows after the sort? I thought that it might work if I get the data() function to get called after the sort is completed, but can't figure out how to do that. I tried to emit a dataChanged signal, but it doesn't seem to work. Is this the proper way of doing this or is there a better way?

MainClass.h


#include <QSqlRelationalTableModel>
#include<QSortFilterProxyModel>
#include "myproxymodel.h"

QSqlRelationalTableModel *printModel;
MyProxyModel* proxy;
QHeaderView *horizHeader;
class MyProxyModel;
MainClass.cpp


void MainClass::createReportTable(QStringList stringList)
{
mReportOptions=stringList;

printModel= new QSqlRelationalTableModel (this);
printModel-> setEditStrategy(QSqlTableModel::OnRowChange);
printModel-> setTable (mTableName);
printModel-> setRelation (2, QSqlRelation("LName", "id", "Last Name"));
printModel->select();
proxy = new MyProxyModel(this);
proxy->setSourceModel(printModel);
ui->printView->setModel(proxy);
horizHeader= ui->printView->horizontalHeader();


connect(this,SIGNAL(sendRows(int, int)), // to send the selected rows to the proxy
proxy, SLOT(getRows(int, int)));
connect(horizHeader, SIGNAL(sortIndicatorChanged (int) ), //This dooesn't seem to work
proxy,SIGNAL(dataChanged ( ) )); //this was to capture the click on the header and repopulate the table

ui->printView->setSelectionMode(QAbstractItemView::SingleSelectio n);
ui->printView->setSelectionBehavior(QAbstractItemView::SelectRows );

printModel->setFilter(mFilterString);
printModel->select();
highlightCells();

void MainClass::highlightCells()
{
float lowSale=FLT_MAX;
float highSale=FLT_MIN;
float currentSales;
int rowHigh=0;
int rowLow=0;
int numRows =proxy->rowCount();

for (int r=0; r<numRows; r++ )
{
if (ui->printView->isRowHidden(r))
continue;
currentSales = proxy->index(r,5).data(Qt::DisplayRole).toFloat();
if (currentSales < lowSale)
{
lowSale = currentSale;
rowLow = r;
}
if (currentSale > highSale)
{
highSale = currentSale;
rowHigh = r;
}
}

emit sendRows (rowSlow, rowFast);
}
myproxymodel.cpp


#include "myproxymodel.h"

MyProxyModel::MyProxyModel (QObject *parent) :
QSortFilterProxyModel(parent)
{

}
MyProxyModel::~MyProxyModel()
{

}

QVariant MyProxyModel::data ( const QModelIndex & index, int role ) const
{

if (!index.isValid())
return QVariant();
if ( index.row() == m_lowRow && index.column()== 5 && role == Qt::BackgroundRole )
{

return QVariant( Qt::yellow );
}
else if ( index.row() == m_highRow && index.column()== 5 && role == Qt::BackgroundRole )
{
return QVariant( Qt::red );
}
else
{
return QSortFilterProxyModel::data( index, role );
}


}
void MyProxyModel::getRows( int rowHigh,int rowLow)
{
m_highRow=rowHigh;
m_lowRow=rowLow;
}

So how do I get the proper data to be highlighted after the table is sorted?

norobro
22nd April 2011, 23:59
Try passing the QModelIndex of the cells that you want to highlight instead of the row numbers and then in MyProxyModel::data() map the index to your source model with:
QModelIndex QSortFilterProxyModel::mapToSource ( const QModelIndex & proxyIndex ) const

poporacer
23rd April 2011, 06:34
Thanks for your help. I don't totally understand. Here is what I have so far:

QModelIndex testIndexSlow;
QModelIndex testIndexFast;

//get fastest and slowest times and save row

int numRows =proxy->rowCount();

for (int r=0; r<numRows; r++ )
{

if (ui->printView->isRowHidden(r))
continue;
//currentRunTime=proxy->mapToSource(index);
currentRunTime = proxy->index(r,32).data(Qt::DisplayRole).toFloat();
if (currentRunTime < fastRunTime)
{
fastRunTime = currentRunTime;
rowFast = r;
}
if (currentRunTime > slowRunTime)
{
slowRunTime = currentRunTime;
rowSlow = r;
}
totalRows++;
totalTime += currentRunTime;
}
testIndexSlow =proxy->index(rowSlow,32,QModelIndex());
testIndexFast =proxy->index(rowFast,32,QModelIndex());
emit sendRows (testIndexSlow, testIndexFast);
I think that is what you suggested for the first part.

But in the MyProxyModel::data() I put in the function declaration:

QModelIndex QSortFilterProxyModel::mapToSource ( const QModelIndex & proxyIndex ) const;
and I get the error
invalid use of qualified-name 'QSortFilterProxyModel::mapToSource
I tried to make a QModelIndex variable but it didn't work.
What am I missing?

norobro
23rd April 2011, 14:09
I believe the statement in data() should look like this:
QModelIndex sourceIndex = mapToSource(index);Then compare sourceIndex with testIndexSlow and testIndexFast.

EDIT: After further review ;) it looks like your original code passing the row numbers should work. You only needed to add the mapToSource() statement above and compare.

poporacer
25th April 2011, 04:58
Well, I still don't quite have it, but we are close! I added the
QModelIndex sourceIndex = mapToSource(index); to the data() function and the correct cell is highlighted. But when the sort is conducted the highlight is on the same cell and not on the correct data. I figured that the sourceIndex needed to be used for the data() and when I used the following code the highlight now is linked to the data. BUT the wrong data is highlighted. Here is the code:

QVariant MyProxyModel::data ( const QModelIndex & index, int role ) const
{
QModelIndex sourceIndex = mapToSource(index);

if (!sourceIndex.isValid())
return QVariant();
if ( sourceIndex.row() == m_fastRow && sourceIndex.column()== 32 && role == Qt::BackgroundRole )
{

return QVariant( Qt::yellow );
}
else if ( sourceIndex.row() == m_slowRow && sourceIndex.column()== 32 && role == Qt::BackgroundRole )
{
return QVariant( Qt::red );
}
else
{
return QSortFilterProxyModel::data( index, role );
}
}
I think that somehow I need to mapToSource or mapFromSource in my code that figures out the correct row. In debugging the code it appears that one model is the reverse order of the other. Here is the code I use for getting the row.

printModel= new QSqlRelationalTableModel (this);
printModel-> setEditStrategy(QSqlTableModel::OnRowChange);
printModel-> setTable (mTableName);
printModel-> setRelation (2, QSqlRelation("rider", "id", "LName"));
printModel->select();
proxy = new MyProxyModel(this);
proxy->setSourceModel(printModel);
ui->printView->setModel(proxy);
ui->printView->setSelectionMode(QAbstractItemView::SingleSelectio n);
ui->printView->setSelectionBehavior(QAbstractItemView::SelectRows );
printModel->setFilter(mFilterString);
printModel->select();

int numRows =proxy->rowCount();

for (int r=0; r<numRows; r++ )
{

currentRunTime = proxy->index(r,32).data(Qt::DisplayRole).toFloat();

if (currentRunTime < fastRunTime)
{
fastRunTime = currentRunTime;
rowFast = r;
}
if (currentRunTime > slowRunTime)
{
slowRunTime = currentRunTime;
rowSlow = r;
}
}
emit sendRows (rowSlow, rowFast);

Any ideas?

norobro
25th April 2011, 17:39
I tried your code on a small db (no relation, no filter) and it works fine.

Try moving your setFilter() statement like so:
printModel-> setRelation (2, QSqlRelation("rider", "id", "LName"));
printModel->setFilter(mFilterString); // move to here
printModel->select();
proxy = new MyProxyModel(this);
proxy->setSourceModel(printModel);
ui->printView->setModel(proxy);
ui->printView->setSelectionMode(QAbstractItemView::SingleSelectio n);
ui->printView->setSelectionBehavior(QAbstractItemView::SelectRows );
// printModel->setFilter(mFilterString);
// printModel->select();

poporacer
28th April 2011, 01:39
That worked! Thanks a bunch!