Results 1 to 4 of 4

Thread: How Do I Refresh a View if the Delegate Changes its Display Format?

  1. #1
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default How Do I Refresh a View if the Delegate Changes its Display Format?

    I have a series of table models displayed either in a QTableView or QDataWidgetMapper. Each display widget has an attached QStyledItemDelegate derivative. The delegate's paint method is responsible for displaying date and duration columns in a format that is dynamically changeable by the user, e.g. a duration column can be displayed in whole minutes, decimal hours, or HH:MM.

    I would like the related views to update when this format changes but haven't found the "correct" way to do this. I can have the delegates emit a signal when the format changes but there is nothing obvious to connect it to that would cause the view to refresh. For the QDataWidgetMapper, which displays a single row output in my application, I can force a refresh using toFirst(). I haven't found the equivalent for QTableView (other than reset() which loses selections etc.). The example code below shows the sort of thing I'm after. The table view only redraws when scrolled or resized.

    I've also considered pushing the determination of the display text back into the models. The Qt::DisplayRole could return the variably formatted date/duration and emit layoutChanged() to force refresh. This doesn't work with the mapper though.

    Any suggestions?

    Qt Code:
    1. #include <QtGui>
    2.  
    3. class TestDelegate: public QStyledItemDelegate {
    4. Q_OBJECT
    5. public:
    6. TestDelegate(QObject * parent = 0 )
    7. : QStyledItemDelegate(parent)
    8. {
    9. m_format = true;
    10. }
    11.  
    12. void paint(QPainter *painter,
    13. const QStyleOptionViewItem &option,
    14. const QModelIndex &index) const
    15. {
    16. Q_ASSERT(index.isValid());
    17. qDebug() << "Paint called for ("<< index.row() << "," << index.column() << ")";
    18.  
    19. // Default setup for this index
    20. QStyleOptionViewItemV4 opt = option;
    21. initStyleOption(&opt, index);
    22. const QWidget *widget = opt.widget;
    23. QStyle *style = widget ? widget->style() : QApplication::style();
    24.  
    25. // Change the display the columns
    26. int mins = index.data(Qt::EditRole).toInt();
    27. if (m_format) {
    28. // H:MM
    29. int hours = mins / 60;
    30. mins = mins % 60;
    31. opt.text = QString("%1:%2").arg(hours).arg(mins, 2, 10, QLatin1Char('0'));
    32. }
    33. else {
    34. // raw minutes
    35. opt.text = opt.locale.toString(mins);
    36. }
    37.  
    38. // Draw it
    39. style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, widget);
    40. }
    41.  
    42. public slots:
    43. void toggleFormat() {
    44. m_format = !m_format;
    45. qDebug() << "Toggled to : " << m_format;
    46. }
    47.  
    48. private:
    49. bool m_format;
    50.  
    51. };
    52.  
    53.  
    54.  
    55. class MainWindow: public QWidget {
    56. Q_OBJECT
    57. public:
    58. MainWindow(QWidget *parent=0):
    59. QWidget(parent)
    60. {
    61. m_button = new QPushButton(this);
    62. m_button->setText("Toggle format");
    63.  
    64. m_view = new QTableView(this);
    65. TestDelegate *del = new TestDelegate(this);
    66. m_view->setItemDelegate(del);
    67. connect(m_button, SIGNAL(clicked()), del, SLOT(toggleFormat()));
    68.  
    69. QVBoxLayout *layout= new QVBoxLayout(this);
    70. layout->addWidget(m_view);
    71. layout->addWidget(m_button);
    72. }
    73.  
    74. void setModel(QAbstractItemModel *model) {
    75. m_view->setModel(model);
    76. }
    77.  
    78. public slots:
    79.  
    80. private:
    81. QTableView *m_view;
    82. QPushButton *m_button;
    83. };
    84.  
    85.  
    86. int main(int argc, char *argv[])
    87. {
    88. QApplication a(argc, argv);
    89.  
    90. for (int row=0; row<10; row++) {
    91. for (int col=0; col<5; col++) {
    92. QStandardItem *newItem = new QStandardItem();
    93. newItem->setData(row*10+col, Qt::EditRole);
    94. model->setItem(row ,col, newItem);
    95. }
    96. }
    97.  
    98.  
    99. MainWindow main;
    100. main.setModel(model);
    101. main.show();
    102.  
    103. return a.exec();
    104. delete model;
    105. }
    106.  
    107. #include "main.moc"
    To copy to clipboard, switch view to plain text mode 
    Last edited by ChrisW67; 17th March 2010 at 22:58. Reason: Disabled smileys in text

  2. #2
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: How Do I Refresh a View if the Delegate Changes its Display Format?

    Thanks to the kind souls who read my plea.

    A eureka/d'oh! moment has lead me to a solution for the table view. I have the delegate emit a signal that I connect to the QTableView::viewPort() update() slot.

    I'm still working on the equivalent for the widget mapper. Connecting to the update() or repaint()slot of the widget containing all the mapped widgets does not do it.

  3. #3
    Join Date
    Oct 2006
    Location
    New Delhi, India
    Posts
    2,467
    Thanks
    8
    Thanked 334 Times in 317 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: How Do I Refresh a View if the Delegate Changes its Display Format?

    You could have also used something in MainWindow ctor like -
    Qt Code:
    1. connect(m_button, SIGNAL(clicked()), this, SLOT(toggleFormat()));
    2. // and in MainWindow::toggleFormat()
    3. MainWindow::toggleFormat()
    4. { del->toggleFormat();
    5. m_view->update();
    6. }
    To copy to clipboard, switch view to plain text mode 

    This would keep the work of delegate to only render. I dont think it was good that delegate tells view to update. I guess its the controller / creator's job.

  4. #4
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: How Do I Refresh a View if the Delegate Changes its Display Format?

    In the real application the signal to change date or duration format comes from outside of the affected view (I just put it there for the example). I could connect that signal to a view slot as you suggest and, yes, it probably is neater. Thanks for the thought.

Similar Threads

  1. Date format is not display
    By sosanjay in forum Qt Programming
    Replies: 2
    Last Post: 9th November 2009, 10:26
  2. Replies: 1
    Last Post: 15th April 2009, 09:00
  3. How to constantly refresh time on a view
    By salmanmanekia in forum Qt Programming
    Replies: 5
    Last Post: 23rd June 2008, 12:44
  4. [model/view] slow refresh on big table
    By lauranger in forum Qt Programming
    Replies: 4
    Last Post: 3rd March 2008, 21:40
  5. Replies: 9
    Last Post: 7th November 2006, 15:10

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
  •  
Qt is a trademark of The Qt Company.