PDA

View Full Version : TableView/Proxy problem



poporacer
15th August 2011, 04:39
I have a program that uses several tables and I highlight certain cells in the tableView. I have a proxyModel to make this happen. I use almost identical code for several different tables but on one tableView it isn’t showing correctly. The first thing I notice is that the table is shown in reverse order. In other words, the table shows the last item from the database first. All the other tableViews I use, show the data in a first to last order. The other problem is that the correct data is not highlighted. If the table was in the correct order, the correct cell would be highlighted. I think my problem might be with a mapToSource issue but I don’t know what index to use?? (I am a Newbie to Qt and trying to learn) I do not know why the table is shown in reverse order? Also, what events trigger the setData() function?

Here is the code I have for the proxy model:

myproxymodel.h


#ifndef MYPROXYMODEL_H
#define MYPROXYMODEL_H

#include <QSortFilterProxyModel>

class MyProxyModel : public QSortFilterProxyModel
{
Q_OBJECT

public:
MyProxyModel(QObject* parent);
~MyProxyModel();
QVariant data ( const QModelIndex & index, int role )const;

private:
int m_lowScore;
int m_highScore;
int m_lowReactRow;
int m_fastReactRow;

MyProxyModel* proxy;

private slots:
void getRows (int, int, int, int);

};

#endif //MYPROXYMODEL_H
myproxymodel.cpp

#include "myproxymodel.h"

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

}
MyProxyModel::~MyProxyModel()
{

}

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

if (!sourceIndex.isValid())
return QVariant();
if (m_slowReactRow<0)
{
if ( sourceIndex.row() == m_highScore && sourceIndex.column()== 2 && role == Qt::BackgroundRole )
{
return QVariant( Qt::yellow );
}
else if ( sourceIndex.row() == m_lowScore && sourceIndex.column()== 2 && role == Qt::BackgroundRole )
{
return QVariant( Qt::red );
}

else
{
return QSortFilterProxyModel::data( index, role );
}

}
else
{
if ( sourceIndex.row() == m_highScore && sourceIndex.column()== 2 && role == Qt::BackgroundRole )
{
return QVariant( Qt::yellow );
}
else if ( sourceIndex.row() == m_lowScore && sourceIndex.column()== 2 && role == Qt::BackgroundRole )
{
return QVariant( Qt::red );
}
else if (sourceIndex.row()== m_fastReactRow && sourceIndex.column()==3 && role == Qt::BackgroundRole)
{
return QVariant( Qt::yellow );
}
else if ( sourceIndex.row() == m_slowReactRow && sourceIndex.column()== 3 && role == Qt::BackgroundRole )
{
return QVariant( Qt::red );
}
else
{
return QSortFilterProxyModel::data( index, role );
}
}
}
void MyProxyModel::getRows( int rowLow,int rowHigh, int rowSlowReact, int rowFastReact)
{
m_highScore=rowHigh;
m_lowScore=rowLow;
m_slowReactRow= rowSlowReact;
m_fastReactRow= rowFastReact;
}
This is the table creation code for one of the tableViews that show correctly:
testclass.cpp

void TestClass::createTimerTable() // this is called in the constructor of the form
{
testModel= new QSqlRelationalTableModel(this);
testModel->setEditStrategy(QSqlTableModel::OnRowChange);
testModel->setTable("testtable");
testModel->setRelation(2,QSqlRelation("student","id", "LName"));
testModel->setRelation(3,QSqlRelation("testNum", "id","Test"));
testModel->setHeaderData(1,Qt::Horizontal,"Section");
testModel->select();

proxy = new MyProxyModel (this);
proxy->setSourceModel(testModel);
ui->tableView->setModel(proxy);

connect(this,SIGNAL(sendRows(int, int, int, int)),
proxy, SLOT(getRows(int, int, int, int)));

//set up tableview
ui->tableView->setItemDelegate(new QSqlRelationalDelegate(this));
ui->tableView->setSelectionMode(QAbstractItemView::SingleSelectio n);
ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows );
ui->tableView->setColumnHidden(0,true); // id
ui->tableView->resizeColumnsToContents();
ui->tableView->horizontalHeader()->setStretchLastSection(true);
}
void TestClass::setTable(QString desc) //This is called in the constructor after createTimerTable
{
mTableString=desc;
testModel->setFilter(QString(desc));
testModel->select();
updateTimeStats();
}
void TestClass::updateTimeStats()
{
float totScore=0;
float totReactTime=0;
float lowScore=FLT_MAX;
int rowLowScore=0;
int rowHighScore =0;
int rowSlowReact =0;
int rowFastReact =0;
float slowReactTime =FLT_MIN;
float highScore=FLT_MIN;
float fastReactTime=FLT_MAX;
float currentScore=0;
float currentReactTime =0;
QString string;
int totRows=proxy->rowCount();
if (totRows >0)
{
for (int r=0; r<totRows; r++)
{
currentScore=proxy->index(r,2).data(Qt::DisplayRole).toFloat();
currentReactTime=proxy->index(r,3).data(Qt::DisplayRole).toFloat();

if (currentScore < lowScore)
{
lowScore=currentScore;
rowLowScore=r;
}

if (currentScore > highScore)
{
highScore=currentScore;
rowHighScore =r;
}

if (currentReactTime > slowReactTime)
{
slowReactTime=currentReactTime;
rowSlowReact =r;
}

if (currentReactTime<fastReactTime)
{
fastReactTime=currentReactTime;
rowFastReact =r;
}

totTime+=currentTime;
totReactTime+=currentReactTime;

}
startModel->select();
}
Here is the code for the tableView that is in reverse order and not highlighted correctly:
dlgprint.cpp

void DlgPrint::createReportTable(QStringList stringList) //strinLlist is used elsewhere
{

printModel= new QSqlRelationalTableModel (this);
printModel-> setEditStrategy(QSqlTableModel::OnManualSubmit);
printModel-> setTable (mTableName); //string identified through assessor function
printModel-> setRelation (2, QSqlRelation("student", "id", "LName"));
printModel-> setRelation (3, QSqlRelation("testNum", "id", "Test"));
printModel->setFilter(mFilterString);
printModel->select();

proxy = new MyProxyModel(this);
proxy->setSourceModel(printModel);
ui->printView->setModel(proxy);

connect(this,SIGNAL(sendRows(int, int, int, int)),
proxy, SLOT(getRows(int, int, int, int)));

ui->printView->setItemDelegate(new QSqlRelationalDelegate(this));
ui->printView->setSelectionMode(QAbstractItemView::SingleSelectio n);
ui->printView->setSelectionBehavior(QAbstractItemView::SelectRows );
ui->printView->setColumnHidden(0,true);//id
ui->printView->resizeColumnsToContents();
printModel->setHeaderData (2, Qt::Horizontal, "Score");
ui->printView->setSortingEnabled(true);
ui->printView->resizeColumnsToContents () ;
ui->printView->horizontalHeader()->setStretchLastSection(true);
highlightCells();
printModel->select();
}
void DlgPrint::highlightCells()
{
float highScore= FLT_MIN;
float lowScore= FLT_MAX;
float fastReactionTime=FLT_MAX;
float slowReactionTime=FLT_MIN;
int rowHigh=0;
int rowLow=0;
int rowFastReact=0;
int rowSlowReact=0;
float totalTime =0;
float totalReactTime=0;
float averageScore =0;
float averageReact=0;
int totalRows = 0;
float currentScore;
float currentReactTime;
QString string;


int numRows =proxy->rowCount();

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

currentscore = proxy->index(r,2).data(Qt::DisplayRole).toFloat();
currentReactTime = proxy->index(r,3).data(Qt::DisplayRole).toFloat();

//something here to mapToSource??

if (currentScore > highScore)
{
highScore = currentScore;
rowHigh = r;
}
if (currentScore < lowScore)
{
lowScore = currentScore;
rowLow = r;
}
totalRows++;
totalScore += currentScore;


if (currentReactTime < fastReactionTime)
{
fastReactionTime = currentReactTime;
rowFastReact = r;
}
if (currentReactTime > slowReactionTime)
{
slowReactionTime = currentReactTime;
rowSlowReact = r;
}
totalReactTime += currentReactTime;
}


}

if (totalRows !=0)
{
averageScore=totalScore/totalRows;
averageReact=totalReactTime/totalRows;
}

emit sendRows (rowSlow, rowFast,rowSlowReact, rowFastReact);
}
I tried to eliminate the code that was irrelevant to the table creation. Hopefully I didn’t forget something. What is wrong here?

majorwoody
15th August 2011, 07:48
void DlgPrint::createReportTable(QStringList stringList) //strinLlist is used elsewhere
{
printModel= new QSqlRelationalTableModel (this);
printModel-> setEditStrategy(QSqlTableModel::OnManualSubmit);
printModel-> setTable (mTableName); //string identified through assessor function
printModel-> setRelation (2, QSqlRelation("student", "id", "LName"));
printModel-> setRelation (3, QSqlRelation("testNum", "id", "Test"));
printModel->setFilter(mFilterString);
printModel->select();

proxy = new MyProxyModel(this);
proxy->setSourceModel(printModel);
ui->printView->setModel(proxy);

connect(this,SIGNAL(sendRows(int, int, int, int)),
proxy, SLOT(getRows(int, int, int, int)));

ui->printView->setItemDelegate(new QSqlRelationalDelegate(this));
ui->printView->setSelectionMode(QAbstractItemView::SingleSelectio n);
ui->printView->setSelectionBehavior(QAbstractItemView::SelectRows );
ui->printView->setColumnHidden(0,true);//id
ui->printView->resizeColumnsToContents();
printModel->setHeaderData (2, Qt::Horizontal, "Score");
ui->printView->setSortingEnabled(true);
ui->printView->resizeColumnsToContents () ;
ui->printView->horizontalHeader()->setStretchLastSection(true);
highlightCells();
printModel->select(); // Why is this?
}


Why do you select again?

poporacer
15th August 2011, 14:00
Sorry, that was a typo....but that would not have caused the problem. Any ideas?

norobro
16th August 2011, 00:17
From the docs:
Note:. Setting the property to true with setSortingEnabled() immediately triggers a call to sortByColumn() with the current sort section and order. You sort the proxyModel before you highlight the cells. Try the reverse:
highlightCells();
ui->printView->setSortingEnabled(true);
ui->printView->resizeColumnsToContents () ;
ui->printView->horizontalHeader()->setStretchLastSection(true);
//highlightCells();
HTH

poporacer
16th August 2011, 01:49
That worked great!!!....but why is the tableView in the reverse order? There is no field to sort on when the tableView is created. When the tableView is first created, I want the data to be in the order it is in the source and then let the user sort the data how he pleases.

norobro
16th August 2011, 02:25
The following will list the sort section(column) and the sort order for your view:
qDebug() << printView->horizontalHeader()->sortIndicatorSection();
qDebug() << printView->horizontalHeader()->QHeaderView::sortIndicatorOrder();
I tried it on a view and the default sort order seems to be Qt:: DescendingOrder (1). You can set the sort order and sort section before you calling setSortingEnabled() like so:
printView->horizontalHeader()->setSortIndicator(0, Qt::AscendingOrder);
printView->setSortingEnabled(true); Change the "0" if your db is ordered differently.

poporacer
16th August 2011, 03:08
Thanks.....That fixed it!!!! Now to my next issue....but I will post a new thread for that. I really appreciate the help!!!!