Wrong selection background in custom QItemDelegate



  • I try to create checkable checkbox item for QTableView. But default methods involve the use of QAbstractItemView::AllEditTriggers, but I'm use QAbstractItemView::NoEditTriggers, because table have to be uneditable for user, except of checkboxes.

    So I inherits QItemDelegate. And here is how it looks:
    !http://storage7.static.itmages.ru/i/12/0807/h_1344366097_7345772_5f64de37d4.png(example)!
    @void CheckBoxDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
    const QModelIndex &index) const
    {
    drawBackground(painter, option, index);
    drawFocus(painter, option, option.rect);
    QStyleOptionViewItemV4 opt(option);
    opt.rect = checkRect(option, option.rect);
    opt.state = opt.state & ~QStyle::State_HasFocus;
    opt.state |= (index.data().toInt() > 0 ? QStyle::State_On : QStyle::State_Off);
    qApp->style()->drawPrimitive(QStyle::PE_IndicatorViewItemCheck, &opt, painter);
    }@

    And here you can see a problem. On KDE (Linux) selection background are flat. But have to be volumed, like default (see "Total" column).

    How can I make it look normal?

    PS: I try to use QStyledItemDelegate, but selection simply disappear...
    @void CheckBoxDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
    const QModelIndex &index) const
    {
    QStyleOptionViewItemV4 opt(option);
    initStyleOption(&opt, index);

    QStyle *style = opt.widget ? opt.widget->style() : QApplication::style();
    opt.rect = checkRect(option, option.rect);
    opt.state = opt.state & ~QStyle::State_HasFocus;
    opt.state |= (index.data().toInt() > 0 ? QStyle::State_On : QStyle::State_Off);
    style->drawPrimitive(QStyle::PE_IndicatorViewItemCheck, &opt, painter);
    

    }@



  • Hi there,
    A checkbox is one of the widgets that you do not need a separate delegate for if using qstandardItem. The "checked state" in the QStandardModel is available for it.
    Otherwise keep searching for the proper option that does it.
    good luck



  • As I say, if I use:
    @this->model()->setData(model()->index(0, 0, Qt::Checked, Qt::CheckStateRole);@
    with QAbstractItemView::NoEditTriggers - I can't click on it.

    PS: also it looks wierd:
    !http://storage7.static.itmages.ru/i/12/0808/h_1344423289_5346095_17f286dad8.png(example)!



  • The 0 you can remove by returning an empty string in the model::data(). Don't have my project at hand, but you are able to center the checkbox in the model AFAIK. When you have the NoEditTriggers you can't trigger anything, so even when you use a delegate it shouldn't be called from the view when selected. Or does it?
    Good luck finding the solution.



  • I know, but my delegate is clickable with NoEditTriggers.

    Here is the source (finded somewhere in the internet):
    @
    #ifndef CHBOXDELEGATE_H
    #define CHBOXDELEGATE_H

    #include <QtGui/QItemDelegate>

    class CheckBoxDelegate : public QItemDelegate
    {
    Q_OBJECT

    public:
    explicit CheckBoxDelegate(bool eventEnabled, QObject* parent = 0);
    QRect checkRect(const QStyleOptionViewItem &option, const QRect &bounding) const;

    private:
    bool isEventEnabled;
    QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option,
    const QModelIndex& index ) const;
    void paint(QPainter* painter, const QStyleOptionViewItem& option,
    const QModelIndex& index) const;
    bool editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option,
    const QModelIndex& index);
    };

    #endif // CHBOXDELEGATE_H

    #include <QtGui/QApplication>
    #include <QtGui/QMouseEvent>
    #include <QtGui/QPainter>

    #include "chboxdelegate.h"

    CheckBoxDelegate::CheckBoxDelegate(bool eventEnabled, QObject *parent) :
    QItemDelegate(parent)
    {
    isEventEnabled = eventEnabled;
    }

    QWidget* CheckBoxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option,
    const QModelIndex &index) const
    {
    Q_UNUSED (parent)
    Q_UNUSED (option)
    Q_UNUSED (index)
    return NULL;
    }

    // FIXME: wrong background on KDE
    void CheckBoxDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
    const QModelIndex &index) const
    {
    drawBackground(painter, option, index);
    drawFocus(painter, option, option.rect);
    QStyleOptionViewItemV4 opt(option);
    opt.rect = checkRect(option, option.rect);
    opt.state = opt.state & ~QStyle::State_HasFocus;
    opt.state |= (index.data().toInt() > 0 ? QStyle::State_On : QStyle::State_Off);
    qApp->style()->drawPrimitive(QStyle::PE_IndicatorViewItemCheck, &opt, painter);

    }

    QRect CheckBoxDelegate::checkRect(const QStyleOptionViewItem &option, const QRect &bounding) const
    {
    QStyleOptionButton opt;
    opt.QStyleOption::operator=(option);
    opt.rect = bounding;
    QRect cr = qApp->style()->subElementRect(QStyle::SE_ViewItemCheckIndicator, &opt);
    int deltaX = (bounding.width()-cr.width())/2;
    int deltaY = (bounding.height()-cr.height())/2;
    return QRect(bounding.left() + deltaX, bounding.top() + deltaY, cr.width(), cr.height());
    }

    bool CheckBoxDelegate::editorEvent(QEvent *event, QAbstractItemModel *model,
    const QStyleOptionViewItem &option, const QModelIndex &index)
    {
    if (!isEventEnabled)
    return false;

    if(!event || !model)
        return false;
    
    Qt::ItemFlags flags = model->flags(index);
    if (!(option.state & QStyle::State_Enabled) || !(flags & Qt::ItemIsEnabled))
        return false;
    
    
    switch(event->type()) {
    case QEvent::MouseButtonRelease :
    case QEvent::MouseButtonDblClick : {
        QRect cr(checkRect(option, option.rect));
        QMouseEvent *me = static_cast<QMouseEvent*>(event);
        if (me->button() != Qt::LeftButton || !cr.contains(me->pos()))
            return false;
    
        // eat the double click events inside the check rect
        if(event->type() == QEvent::MouseButtonDblClick)
            return true;
        break;
    }
    case QEvent::KeyPress : {
        QKeyEvent *kev = static_cast<QKeyEvent*>(event);
        if(kev->key() != Qt::Key_Space && kev->key() != Qt::Key_Select)
            return false;
        break;
    }
    default: return false;
    }
    
    
    int value = (index.data().toInt() == 0 ? 2 : 0);
    return model->setData(index, value, Qt::EditRole);
    

    }
    @


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.