Results 1 to 20 of 21

Thread: inserting custom Widget to listview

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Join Date
    Jan 2006
    Location
    Frankfurt
    Posts
    500
    Thanks
    1
    Thanked 52 Times in 52 Posts
    Platforms
    MacOS X Unix/X11

    Default Re: inserting custom Widget to listview

    If you go with setIndexWidget, YES, if you use a delegate, it depends. You can only use your widget for the edit state. You have to fake drawing of that widget in delegate:aint. It depends on how clever you do that. For example, if you instantiate a widget, take a screenshot of it and blit it to the cell, it is not clever.
    It's nice to be important but it's more important to be nice.

  2. #2
    Join Date
    Jan 2008
    Location
    Poland
    Posts
    687
    Thanks
    4
    Thanked 140 Times in 132 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: inserting custom Widget to listview

    as I understand from the picture all you need from the widgets are 3 buttons, the rest are labels, so you can draw it all by yourself in delegate.
    int QAbstractItemDelegate::sizeHint() you should return required size hint, and in QAbstractItemDelegate::paint() you can draw all you want width painter. Drawing text is simple (see QPainter::drawText()) and drawing buttons is also simple: QStyle::drawControl()
    Here is a code snippet from my code painting a button in one cell at column number = ButtonColumn:

    Qt Code:
    1. void MyDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
    2. {
    3. QStyledItemDelegate::paint(painter, option, index);
    4. if (!index.isValid() || index.column() != ButtonColumn) {
    5. return;
    6. }
    7.  
    8. State s = (State)(index.data(Qt::UserRole).toInt());
    9. if (s == Hovered)
    10. opt.state |= QStyle::State_MouseOver;
    11. if (s == Pressed)
    12. opt.state |= QStyle::State_Sunken;
    13. opt.state |= QStyle::State_Enabled;
    14. opt.rect = option.rect.adjusted(1, 1, -1, -1);
    15. opt.text = trUtf8("Button text");
    16. QApplication::style()->drawControl(QStyle::CE_PushButton, &opt, painter, 0);
    17. }
    To copy to clipboard, switch view to plain text mode 
    As you see the state of the button is stored in model cause there is one button for each index (in this column ButtonColumn) so the best way to store the state is to store it in model :] (State is my own enum).

    but then you have do your own event handling for hover and push events. I geting quite compicated, because you have to implement it in QAbstractItemDelegate::editorEvent() and in event filter installed on view's viewport. And view's viewport has to have mouse tracking enabled. So for my button's in columns here is there relevant, example code:

    Qt Code:
    1. bool HistoryDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
    2. {
    3. if (event->type() == QEvent::MouseMove) {
    4. if (index != m_lastUnderMouse) {
    5. if (m_lastUnderMouse.isValid()) {
    6. model->setData(m_lastUnderMouse, (int)Normal, Qt::UserRole);
    7. emit needsUpdate(m_lastUnderMouse);
    8. }
    9. if (index.isValid() && index.column() == ButtonColumn) {
    10. model->setData(index, (int)Hovered, Qt::UserRole);
    11. emit needsUpdate(index);
    12. m_lastUnderMouse = index;
    13. } else {
    14. m_lastUnderMouse = QModelIndex();
    15. }
    16. }
    17. }
    18. if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonDblClick) {
    19. if (index != m_lastUnderMouse) {
    20. if (m_lastUnderMouse.isValid()) {
    21. model->setData(m_lastUnderMouse, (int)Normal, Qt::UserRole);
    22. emit needsUpdate(m_lastUnderMouse);
    23. }
    24. if (index.isValid() && index.column() == ButtonColumn) {
    25. model->setData(index, (int)Pressed, Qt::UserRole);
    26. emit needsUpdate(index);
    27. emit clicked(index);
    28. m_lastUnderMouse = index;
    29. } else {
    30. m_lastUnderMouse = QModelIndex();
    31. }
    32. } else {
    33. if (m_lastUnderMouse.isValid()) {
    34. model->setData(m_lastUnderMouse, (int)Pressed, Qt::UserRole);
    35. emit needsUpdate(m_lastUnderMouse);
    36. emit clicked(m_lastUnderMouse);
    37. }
    38. }
    39. }
    40. if (event->type() == QEvent::MouseButtonRelease) {
    41. if (index != m_lastUnderMouse) {
    42. if (m_lastUnderMouse.isValid()) {
    43. model->setData(m_lastUnderMouse, (int)Normal, Qt::UserRole);
    44. emit needsUpdate(m_lastUnderMouse);
    45. }
    46. if (index.isValid() && index.column() == ButtonColumn) {
    47. model->setData(index, (int)Hovered, Qt::UserRole);
    48. emit needsUpdate(index);
    49. m_lastUnderMouse = index;
    50. } else {
    51. m_lastUnderMouse = QModelIndex();
    52. }
    53. } else {
    54. if (m_lastUnderMouse.isValid()) {
    55. model->setData(m_lastUnderMouse, (int)Hovered, Qt::UserRole);
    56. emit needsUpdate(m_lastUnderMouse);
    57. }
    58. }
    59. }
    60. return QStyledItemDelegate::editorEvent(event, model, option, index);
    61. }
    To copy to clipboard, switch view to plain text mode 
    m_lastUnderMouse is QPersistentModelIndex storing which index was last under mouse to know that we have to for example remove the hover highlight because now we are highlightind another index.
    needsUpdate() is connected to view and call update(QModelIndex) to call MyDelegate:aint() which will paint new button state.
    Qt Code:
    1. bool MyWidgetContainingView::eventFilter(QObject *obj, QEvent *event)
    2. {
    3. if (obj != ui->treeView->viewport())
    4. return QWidget::eventFilter(obj, event);
    5. switch (event->type()) {
    6. case QEvent::Leave:
    7. m_delegate->notifyMouseLeave();
    8. break;
    9. case QEvent::MouseMove:
    10. QModelIndex index = ui->treeView->indexAt(static_cast<QMouseEvent *>(event)->pos());
    11. if (!index.isValid())
    12. m_delegate->notifyMouseLeave();
    13. break;
    14. }
    15. return QWidget::eventFilter(obj, event);
    16. }
    To copy to clipboard, switch view to plain text mode 
    notifyMouseLeave() is the delegate method to notify delegate that mouse left view's viewport so it has to for example remove the hover highlight from m_lastUnderMouse if it is valid index.

    Hope this helps :]


    Notice that this solution is very efficient because there is no single real button, they are just drawn by delegate :]
    Last edited by faldzip; 10th January 2010 at 16:54.
    I would like to be a "Guru"

    Useful hints (try them before asking):
    1. Use Qt Assistant
    2. Search the forum

    If you haven't found solution yet then create new topic with smart question.

  3. The following 3 users say thank you to faldzip for this useful post:

    Maquefel (24th February 2011), MarkoSan (10th January 2010), youssna (11th May 2011)

  4. #3
    Join Date
    Jan 2006
    Location
    Ljubljana
    Posts
    687
    Thanks
    111
    Thanked 4 Times in 4 Posts
    Qt products
    Qt5 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows Android

    Default Re: inserting custom Widget to listview

    So, these are two ways of implementing my task?
    Last edited by MarkoSan; 10th January 2010 at 21:53.
    Qt 5.3 Opensource & Creator 3.1.2

  5. #4
    Join Date
    Jan 2008
    Location
    Poland
    Posts
    687
    Thanks
    4
    Thanked 140 Times in 132 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: inserting custom Widget to listview

    My whole previous post is one solution, and the last sentence was about it's performance advantage compared to setIndexWidget()
    I would like to be a "Guru"

    Useful hints (try them before asking):
    1. Use Qt Assistant
    2. Search the forum

    If you haven't found solution yet then create new topic with smart question.

  6. #5
    Join Date
    Jan 2006
    Location
    Ljubljana
    Posts
    687
    Thanks
    111
    Thanked 4 Times in 4 Posts
    Qt products
    Qt5 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows Android

    Default Re: inserting custom Widget to listview

    Well, as seen from my attached pic, I must display several strings and a pic. How do send this data to model, using custom roles?
    Qt 5.3 Opensource & Creator 3.1.2

  7. #6
    Join Date
    Jan 2008
    Location
    Poland
    Posts
    687
    Thanks
    4
    Thanked 140 Times in 132 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: inserting custom Widget to listview

    Quote Originally Posted by MarkoSan View Post
    Well, as seen from my attached pic, I must display several strings and a pic. How do send this data to model, using custom roles?
    It depends on your model. If you use QStandardItemModel then every QStandardItem has setData() method which you can use like this:
    Qt Code:
    1. item->setData("Label 1 text", Qt::UserRole);
    2. item->setData("Label 2 text", Qt::UserRole+1);
    3. item->setData("Label 3 text", Qt::UserRole+2);
    4. item->setData(false, Qt::UserRole+3); // button 1 pressed?
    To copy to clipboard, switch view to plain text mode 
    and so on.

    If you have your own mode implementation then you need to return proper value in YourMode::data():
    Qt Code:
    1. QVariant YourModel::data(const QModelIndex &index, int role) const
    2. {
    3. // ...
    4. if (role == Qt::UserRole + 2) {
    5. QString s = "Label 3 text"; // should take proper text for given index from your underlaying data structure
    6. return s;
    7. }
    8. // ...
    9. }
    To copy to clipboard, switch view to plain text mode 
    and so on.
    I would like to be a "Guru"

    Useful hints (try them before asking):
    1. Use Qt Assistant
    2. Search the forum

    If you haven't found solution yet then create new topic with smart question.

  8. #7
    Join Date
    Feb 2010
    Posts
    3
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: inserting custom Widget to listview

    Hi faldżip,

    Just wanted to say thanks for such a great code example of a button delegate in a view. It has helped me a lot! Maybe it should be included in the Qt documentation, because their delegate examples do not cover all of this.

    Dan

  9. #8
    Join Date
    Aug 2010
    Posts
    20
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Windows

    Default Re: inserting custom Widget to listview

    Is too bad idea to create a widget with the QCreator an use it to render all I need? (To avoid doing it manually)
    Here is an example

    Qt Code:
    1. class CustomItemDelegate : public QStyledItemDelegate
    2. {
    3. WidgetItem * witem;
    4. public:
    5.  
    6. CustomItemDelegate()
    7. {
    8. witem = new WidgetItem ();
    9. }
    10.  
    11. ~CustomItemDelegate()
    12. {
    13. delete witem;
    14. }
    15.  
    16.  
    17. void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const
    18. {
    19. witem->resize(option.rect.size());
    20.  
    21. /*
    22.   Here update the witem with some method with the real item data
    23.   Update labels, icons, and so on
    24.   */
    25.  
    26. painter->save();
    27. painter->translate(option.rect.topLeft());
    28. witem->render(painter);
    29. painter->restore();
    30. }
    31. }
    To copy to clipboard, switch view to plain text mode 

    Note that the widget is create just once and then all its components updated

  10. #9
    Join Date
    Aug 2010
    Posts
    20
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Windows

    Default Re: inserting custom Widget to listview

    If I have two buttons in an item, how can I know which one was press?

Similar Threads

  1. How to use custom widget editor with QItemDelegate
    By wysman in forum Qt Programming
    Replies: 2
    Last Post: 20th May 2009, 18:20
  2. Custom Widget - First Steps
    By sekatsim in forum Qt Programming
    Replies: 8
    Last Post: 26th June 2008, 17:19
  3. Custom widget
    By zorro68 in forum Qt Programming
    Replies: 7
    Last Post: 28th January 2008, 14:06
  4. custom plug-in widget in another custom plug-in widget.
    By MrGarbage in forum Qt Programming
    Replies: 6
    Last Post: 27th August 2007, 15:38
  5. Custom tab widget question
    By PrimeCP in forum Qt Programming
    Replies: 2
    Last Post: 7th August 2007, 11:17

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.