Results 1 to 7 of 7

Thread: call data() function after QHeaderview Sort

  1. #1
    Join Date
    Aug 2010
    Posts
    107
    Thanks
    5
    Qt products
    Qt4
    Platforms
    Windows

    Angry call data() function after QHeaderview Sort

    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

    Qt Code:
    1. #include <QSqlRelationalTableModel>
    2. #include<QSortFilterProxyModel>
    3. #include "myproxymodel.h"
    4.  
    5. MyProxyModel* proxy;
    6. QHeaderView *horizHeader;
    7. class MyProxyModel;
    To copy to clipboard, switch view to plain text mode 
    MainClass.cpp

    Qt Code:
    1. void MainClass::createReportTable(QStringList stringList)
    2. {
    3. mReportOptions=stringList;
    4.  
    5. printModel= new QSqlRelationalTableModel (this);
    6. printModel-> setEditStrategy(QSqlTableModel::OnRowChange);
    7. printModel-> setTable (mTableName);
    8. printModel-> setRelation (2, QSqlRelation("LName", "id", "Last Name"));
    9. printModel->select();
    10. proxy = new MyProxyModel(this);
    11. proxy->setSourceModel(printModel);
    12. ui->printView->setModel(proxy);
    13. horizHeader= ui->printView->horizontalHeader();
    14.  
    15.  
    16. connect(this,SIGNAL(sendRows(int, int)), // to send the selected rows to the proxy
    17. proxy, SLOT(getRows(int, int)));
    18. connect(horizHeader, SIGNAL(sortIndicatorChanged (int) ), //This dooesn't seem to work
    19. proxy,SIGNAL(dataChanged ( ) )); //this was to capture the click on the header and repopulate the table
    20.  
    21. ui->printView->setSelectionMode(QAbstractItemView::SingleSelection);
    22. ui->printView->setSelectionBehavior(QAbstractItemView::SelectRows);
    23.  
    24. printModel->setFilter(mFilterString);
    25. printModel->select();
    26. highlightCells();
    27.  
    28. void MainClass::highlightCells()
    29. {
    30. float lowSale=FLT_MAX;
    31. float highSale=FLT_MIN;
    32. float currentSales;
    33. int rowHigh=0;
    34. int rowLow=0;
    35. int numRows =proxy->rowCount();
    36.  
    37. for (int r=0; r<numRows; r++ )
    38. {
    39. if (ui->printView->isRowHidden(r))
    40. continue;
    41. currentSales = proxy->index(r,5).data(Qt::DisplayRole).toFloat();
    42. if (currentSales < lowSale)
    43. {
    44. lowSale = currentSale;
    45. rowLow = r;
    46. }
    47. if (currentSale > highSale)
    48. {
    49. highSale = currentSale;
    50. rowHigh = r;
    51. }
    52. }
    53.  
    54. emit sendRows (rowSlow, rowFast);
    55. }
    To copy to clipboard, switch view to plain text mode 
    myproxymodel.cpp

    Qt Code:
    1. #include "myproxymodel.h"
    2.  
    3. MyProxyModel::MyProxyModel (QObject *parent) :
    4. {
    5.  
    6. }
    7. MyProxyModel::~MyProxyModel()
    8. {
    9.  
    10. }
    11.  
    12. QVariant MyProxyModel::data ( const QModelIndex & index, int role ) const
    13. {
    14.  
    15. if (!index.isValid())
    16. return QVariant();
    17. if ( index.row() == m_lowRow && index.column()== 5 && role == Qt::BackgroundRole )
    18. {
    19.  
    20. return QVariant( Qt::yellow );
    21. }
    22. else if ( index.row() == m_highRow && index.column()== 5 && role == Qt::BackgroundRole )
    23. {
    24. return QVariant( Qt::red );
    25. }
    26. else
    27. {
    28. return QSortFilterProxyModel::data( index, role );
    29. }
    30.  
    31.  
    32. }
    33. void MyProxyModel::getRows( int rowHigh,int rowLow)
    34. {
    35. m_highRow=rowHigh;
    36. m_lowRow=rowLow;
    37. }
    To copy to clipboard, switch view to plain text mode 

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

  2. #2
    Join Date
    Feb 2008
    Posts
    491
    Thanks
    12
    Thanked 142 Times in 135 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11

    Default Re: call data() function after QHeaderview Sort

    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:
    Qt Code:
    1. QModelIndex QSortFilterProxyModel::mapToSource ( const QModelIndex & proxyIndex ) const
    To copy to clipboard, switch view to plain text mode 

  3. #3
    Join Date
    Aug 2010
    Posts
    107
    Thanks
    5
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: call data() function after QHeaderview Sort

    Thanks for your help. I don't totally understand. Here is what I have so far:
    Qt Code:
    1. QModelIndex testIndexSlow;
    2. QModelIndex testIndexFast;
    3.  
    4. //get fastest and slowest times and save row
    5.  
    6. int numRows =proxy->rowCount();
    7.  
    8. for (int r=0; r<numRows; r++ )
    9. {
    10.  
    11. if (ui->printView->isRowHidden(r))
    12. continue;
    13. //currentRunTime=proxy->mapToSource(index);
    14. currentRunTime = proxy->index(r,32).data(Qt::DisplayRole).toFloat();
    15. if (currentRunTime < fastRunTime)
    16. {
    17. fastRunTime = currentRunTime;
    18. rowFast = r;
    19. }
    20. if (currentRunTime > slowRunTime)
    21. {
    22. slowRunTime = currentRunTime;
    23. rowSlow = r;
    24. }
    25. totalRows++;
    26. totalTime += currentRunTime;
    27. }
    28. testIndexSlow =proxy->index(rowSlow,32,QModelIndex());
    29. testIndexFast =proxy->index(rowFast,32,QModelIndex());
    30. emit sendRows (testIndexSlow, testIndexFast);
    To copy to clipboard, switch view to plain text mode 
    I think that is what you suggested for the first part.

    But in the MyProxyModel::data() I put in the function declaration:
    Qt Code:
    1. QModelIndex QSortFilterProxyModel::mapToSource ( const QModelIndex & proxyIndex ) const;
    To copy to clipboard, switch view to plain text mode 
    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?

  4. #4
    Join Date
    Feb 2008
    Posts
    491
    Thanks
    12
    Thanked 142 Times in 135 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11

    Default Re: call data() function after QHeaderview Sort

    I believe the statement in data() should look like this:
    Qt Code:
    1. QModelIndex sourceIndex = mapToSource(index);
    To copy to clipboard, switch view to plain text mode 
    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.
    Last edited by norobro; 23rd April 2011 at 17:18.

  5. #5
    Join Date
    Aug 2010
    Posts
    107
    Thanks
    5
    Qt products
    Qt4
    Platforms
    Windows

    Question Re: call data() function after QHeaderview Sort

    Well, I still don't quite have it, but we are close! I added the
    Qt Code:
    1. QModelIndex sourceIndex = mapToSource(index);
    To copy to clipboard, switch view to plain text mode 
    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:
    Qt Code:
    1. QVariant MyProxyModel::data ( const QModelIndex & index, int role ) const
    2. {
    3. QModelIndex sourceIndex = mapToSource(index);
    4.  
    5. if (!sourceIndex.isValid())
    6. return QVariant();
    7. if ( sourceIndex.row() == m_fastRow && sourceIndex.column()== 32 && role == Qt::BackgroundRole )
    8. {
    9.  
    10. return QVariant( Qt::yellow );
    11. }
    12. else if ( sourceIndex.row() == m_slowRow && sourceIndex.column()== 32 && role == Qt::BackgroundRole )
    13. {
    14. return QVariant( Qt::red );
    15. }
    16. else
    17. {
    18. return QSortFilterProxyModel::data( index, role );
    19. }
    20. }
    To copy to clipboard, switch view to plain text mode 
    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.
    Qt Code:
    1. printModel= new QSqlRelationalTableModel (this);
    2. printModel-> setEditStrategy(QSqlTableModel::OnRowChange);
    3. printModel-> setTable (mTableName);
    4. printModel-> setRelation (2, QSqlRelation("rider", "id", "LName"));
    5. printModel->select();
    6. proxy = new MyProxyModel(this);
    7. proxy->setSourceModel(printModel);
    8. ui->printView->setModel(proxy);
    9. ui->printView->setSelectionMode(QAbstractItemView::SingleSelection);
    10. ui->printView->setSelectionBehavior(QAbstractItemView::SelectRows);
    11. printModel->setFilter(mFilterString);
    12. printModel->select();
    13.  
    14. int numRows =proxy->rowCount();
    15.  
    16. for (int r=0; r<numRows; r++ )
    17. {
    18.  
    19. currentRunTime = proxy->index(r,32).data(Qt::DisplayRole).toFloat();
    20.  
    21. if (currentRunTime < fastRunTime)
    22. {
    23. fastRunTime = currentRunTime;
    24. rowFast = r;
    25. }
    26. if (currentRunTime > slowRunTime)
    27. {
    28. slowRunTime = currentRunTime;
    29. rowSlow = r;
    30. }
    31. }
    32. emit sendRows (rowSlow, rowFast);
    To copy to clipboard, switch view to plain text mode 
    Any ideas?

  6. #6
    Join Date
    Feb 2008
    Posts
    491
    Thanks
    12
    Thanked 142 Times in 135 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11

    Default Re: call data() function after QHeaderview Sort

    I tried your code on a small db (no relation, no filter) and it works fine.

    Try moving your setFilter() statement like so:
    Qt Code:
    1. printModel-> setRelation (2, QSqlRelation("rider", "id", "LName"));
    2. printModel->setFilter(mFilterString); // move to here
    3. printModel->select();
    4. proxy = new MyProxyModel(this);
    5. proxy->setSourceModel(printModel);
    6. ui->printView->setModel(proxy);
    7. ui->printView->setSelectionMode(QAbstractItemView::SingleSelection);
    8. ui->printView->setSelectionBehavior(QAbstractItemView::SelectRows);
    9. // printModel->setFilter(mFilterString);
    10. // printModel->select();
    To copy to clipboard, switch view to plain text mode 

  7. #7
    Join Date
    Aug 2010
    Posts
    107
    Thanks
    5
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: call data() function after QHeaderview Sort

    That worked! Thanks a bunch!

Similar Threads

  1. Sort huge data use QSortFilterProxyModel
    By jiaorenjie in forum Qt Programming
    Replies: 0
    Last Post: 16th March 2011, 02:56
  2. QHeaderView Sort Indicator sizing
    By vycke in forum Qt Programming
    Replies: 3
    Last Post: 1st October 2009, 14:53
  3. can't get right data after sort
    By wirasto in forum Qt Programming
    Replies: 5
    Last Post: 28th June 2009, 18:19
  4. Replies: 4
    Last Post: 9th April 2009, 22:49
  5. function call
    By Walsi in forum Qt Programming
    Replies: 3
    Last Post: 12th June 2007, 09:13

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.