Results 1 to 2 of 2

Thread: QTableView, Model/View, QCheckBox

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Join Date
    Jan 2011
    Posts
    32
    Thanks
    6
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default QTableView, Model/View, QCheckBox

    I have subclassed QItemDelegate to display a column of QCheckBox items for boolean values. I am using a bit of manipulation, but things are working out the way that I want them. I get a column of checkboxes that are centered in the cells and when I click on one, the appearance changes ever so slightly and the check state changes immediately without having to click to bring up the editor then click again to change the state.

    Here is my code to accomplish this.

    CBItemDelegate.h:

    Qt Code:
    1. #ifndef CBITEMDELEGATE_H
    2. #define CBITEMDELEGATE_H
    3.  
    4. #include <QItemDelegate>
    5. #include "checkbox.h"
    6. #include <QTableView>
    7.  
    8. class CBItemDelegate : public QItemDelegate
    9. {
    10. Q_OBJECT
    11. public:
    12. explicit CBItemDelegate(QTableView *parent = 0);
    13. QWidget *createEditor(QWidget *parent,
    14. const QStyleOptionViewItem &option,
    15. const QModelIndex &index) const;
    16. void setEditorData(QWidget *editor,
    17. const QModelIndex &index) const;
    18. void setModelData(QWidget *editor,
    19. const QModelIndex &index) const;
    20. void updateEditorGeometry(QWidget *editor,
    21. const QStyleOptionViewItem &option,
    22. const QModelIndex &index) const;
    23. void paint(QPainter *painter,
    24. const QStyleOptionViewItem &option,
    25. const QModelIndex &index) const;
    26. virtual bool editorEvent(QEvent *event,
    27. const QStyleOptionViewItem &option,
    28. const QModelIndex &index);
    29.  
    30. private:
    31. QTableView *my_table;
    32.  
    33. private slots:
    34. void slot_clicked(int row, Qt::CheckState cs);
    35.  
    36. signals:
    37. void sig_clicked(int row, Qt::CheckState cs);
    38.  
    39. };
    40.  
    41. #endif //CBITEMDELEGATE_H
    To copy to clipboard, switch view to plain text mode 

    CBItemDelegate.cpp:

    Qt Code:
    1. #include "cbitemdelegate.h"
    2. #include <QApplication>
    3. #include <QAbstractItemView>
    4. #include <QtGui>
    5.  
    6. CBItemDelegate::CBItemDelegate(QTableView *parent)
    7. : QItemDelegate(parent)
    8. {
    9. my_table = parent;
    10. }
    11.  
    12. QWidget *CBItemDelegate::createEditor(QWidget *parent,
    13. const QModelIndex &index) const {
    14. CheckBox *editor = new CheckBox(index.row(), parent);
    15. editor->installEventFilter(const_cast<CBItemDelegate*>(this));
    16. editor->setFixedSize(24, 24);
    17. editor->setFocusPolicy(Qt::StrongFocus);
    18. editor->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    19. connect(editor, SIGNAL(pressed(int,Qt::CheckState)),
    20. this, SLOT(slot_clicked(int,Qt::CheckState)),
    21. Qt::DirectConnection);
    22. QRect rect = my_table->visualRect(index);
    23. QPoint draw_at(rect.left() + (rect.width() / 2) - (editor->width() / 2),
    24. rect.top() + (rect.height() / 2) - (editor->height() / 2));
    25. editor->move(draw_at);
    26. return editor;
    27. }
    28.  
    29. void CBItemDelegate::slot_clicked(int row, Qt::CheckState cs) {
    30. emit sig_clicked(row, cs);
    31. }
    32.  
    33. void CBItemDelegate::setEditorData(QWidget *editor,
    34. const QModelIndex &index) const {
    35. int value = index.model()->data(index, Qt::DisplayRole).toInt();
    36.  
    37. CheckBox *checkBox = static_cast<CheckBox*>(editor);
    38. if(value == 1)
    39. checkBox->setCheckState(Qt::Unchecked);
    40. else
    41. checkBox->setCheckState(Qt::Checked);
    42. }
    43.  
    44. void CBItemDelegate::setModelData(QWidget *editor,
    45. const QModelIndex &index) const {
    46. CheckBox *checkBox = static_cast<CheckBox*>(editor);
    47. int value;
    48. if(checkBox->checkState() == Qt::Checked)
    49. value = 1;
    50. else
    51. value = 0;
    52.  
    53. model->setData(index, value);
    54. }
    55.  
    56. void CBItemDelegate::updateEditorGeometry(QWidget *editor,
    57. const QStyleOptionViewItem &option,
    58. const QModelIndex &index) const {
    59. QRect r;
    60. r.setSize(QSize(24, 24));
    61. r.moveTo((option.rect.width() / 2) - (editor->width() / 2),
    62. (option.rect.height() / 2) - (editor->height() / 2));
    63. editor->setGeometry(r);
    64. QRect rect = my_table->visualRect(index);
    65. QPoint draw_at(rect.left() + (rect.width() / 2) - (editor->width() / 2),
    66. rect.top() + (rect.height() / 2) - (editor->height() / 2));
    67. editor->move(draw_at);
    68. }
    69.  
    70. void CBItemDelegate::paint(QPainter *painter,
    71. const QStyleOptionViewItem &option,
    72. const QModelIndex &index) const {
    73. bool data = index.model()->data(index, Qt::DisplayRole).toBool();
    74. QStyleOptionButton checkboxstyle;
    75. QRect checkbox_rect = QApplication::style()->subElementRect(QStyle::SE_CheckBoxIndicator, &checkboxstyle);
    76. checkboxstyle.rect = option.rect;
    77. checkboxstyle.rect.setLeft(option.rect.x() + option.rect.width()/2 - checkbox_rect.width()/2);
    78. if(data)
    79. checkboxstyle.state = QStyle::State_On|QStyle::State_Enabled;
    80. else
    81. checkboxstyle.state = QStyle::State_Off|QStyle::State_Enabled;
    82.  
    83. QApplication::style()->drawControl(QStyle::CE_CheckBox, &checkboxstyle, painter);
    84. }
    85.  
    86. bool CBItemDelegate::editorEvent(QEvent *event,
    87. const QStyleOptionViewItem &option,
    88. const QModelIndex &index) {
    89. Q_ASSERT(event);
    90. Q_ASSERT(model);
    91.  
    92. // make sure that the item is checkable
    93. Qt::ItemFlags flags = model->flags(index);
    94. if (!(flags & Qt::ItemIsUserCheckable) || !(flags & Qt::ItemIsEnabled))
    95. return false;
    96. // make sure that we have a check state
    97. QVariant value = index.data(Qt::CheckStateRole);
    98. if (!value.isValid())
    99. return false;
    100. // make sure that we have the right event type
    101. if (event->type() == QEvent::MouseButtonRelease) {
    102. const int textMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1;
    103. QRect checkRect = QStyle::alignedRect(option.direction, Qt::AlignCenter,
    104. check(option, option.rect, Qt::Checked).size(),
    105. QRect(option.rect.x() + textMargin, option.rect.y(),
    106. option.rect.width() - (2 * textMargin), option.rect.height()));
    107. if (!checkRect.contains(static_cast<QMouseEvent*>(event)->pos()))
    108. return false;
    109. } else if (event->type() == QEvent::KeyPress) {
    110. if (static_cast<QKeyEvent*>(event)->key() != Qt::Key_Space
    111. && static_cast<QKeyEvent*>(event)->key() != Qt::Key_Select)
    112. return false;
    113. } else {
    114. return false;
    115. }
    116. Qt::CheckState state = (static_cast<Qt::CheckState>(value.toInt()) == Qt::Checked
    117. ? Qt::Unchecked : Qt::Checked);
    118.  
    119. QMessageBox::information(0,
    120. QString((state == Qt::Checked) ? "Qt::Checked" : "Qt::Unchecked"),
    121. QString("[%1/%2]").arg(index.row()).arg(index.column()));
    122.  
    123. return model->setData(index, state, Qt::CheckStateRole);
    124. }
    To copy to clipboard, switch view to plain text mode 

    All of this works well. Now, however, I need to get a clicked() signal from the checkboxes in a column. Try as I might, I cannot seem to figure out where to go to lock in on this one.

    As you may note, I have also subclassed QCheckBox as well attempting to manipulate the signals/slots from there - no joy.

    You may also note in the createEditor method that I connect a signal from the created editor, from which I get one signal, and then nothing else. I am just blind guessing, but it seems that maybe the view makes a copy of the editor and then destroys the original thus breaking the signal/slot connection(?)

    I really don't know. Could someone help me figure out where to look to get some sort of clicked() signal from these checkbox delegates? It doesn't even matter to me what information is passed. When I get the clicked signal, I can go find the information I need. I just need a clicked() (or pressed() etc.) signal that works.

    Any ideas? Or am I attacking this in a basically incorrect fashion, perhaps?

  2. #2
    Join Date
    Jan 2011
    Posts
    32
    Thanks
    6
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: QTableView, Model/View, QCheckBox

    Okay, found a way.

    Note line 16 of CBItemDelegate.cpp

    I derived a custom event filter and installed it to catch the mouse events. From there I am able to draw the information out and do what I need.

Similar Threads

  1. QTableView, Model/View, QCheckBox
    By lxman in forum Qt Programming
    Replies: 5
    Last Post: 7th July 2011, 00:53
  2. Replies: 1
    Last Post: 24th February 2011, 05:54
  3. Replies: 3
    Last Post: 23rd February 2011, 09:27
  4. QTableView - model / view pattern - layout, edit
    By vlastagf in forum Qt Programming
    Replies: 4
    Last Post: 1st August 2009, 22:42
  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.