int columnCount ( const QModelIndex & parent = QModelIndex() ) const; QVariant data ( const QModelIndex & index, int role = Qt::DisplayRole ) const; QModelIndex index ( int row, int column, const QModelIndex & parent = QModelIndex() ) const; QModelIndex parent ( const QModelIndex & index ) const; int rowCount ( const QModelIndex & parent = QModelIndex() ) const; Qt::ItemFlags flags ( const QModelIndex & index ) const;
bool setData ( const QModelIndex & index, const QVariant & value, int role = Qt::EditRole );
For this implementation, I was pushed by the way the work with CheckBox was implemented by the QItemDelegate delegate. Therefore, in addition to reading the documentation, it is also useful to look into the source code, there are many useful solutions there.
void QvObjectDelegate::paint( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const { painter->save(); if(index.parent().isValid()) { if(needRestart(index)) { drawItemBackground(painter, option, index); paintObjectHeader(painter, option, index); } paintObject(painter, option, index); } else { paintHeader(painter, option, index); } painter->restore(); painter->save(); painter->setPen(QColor(0xD7, 0xD7, 0xD7)); painter->drawLine(option.rect.bottomLeft(), option.rect.bottomRight()); painter->restore(); }
void QvObjectDelegate::paintHeader( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const { QPainter &p = *painter; p.save(); p.setClipRect(option.rect); p.setPen(QColor(77, 77, 77)); // QRect tr; QString name = index.data(Qt::DisplayRole).toString(), desc = index.data(QvObjectModel::DetailRole).toString(); QFont f = option.font; f.setPointSize(12); f.setWeight(QFont::Bold); QFontMetrics fm(f); tr = fm.boundingRect(name); p.setFont(f); p.drawText(option.rect, Qt::AlignVCenter | Qt::AlignLeft, name); f = option.font; f.setWeight(QFont::DemiBold); p.setFont(f); p.drawText(option.rect, Qt::AlignVCenter | Qt::AlignRight, desc); p.restore(); }
void QvObjectDelegate::paintObject(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const { QRect tr; QString name = index.data(Qt::DisplayRole).toString(), description = index.data(QvObjectModel::DescriptionRole).toString(); QPainter &p = *painter; p.setClipRect(option.rect); p.setPen(QColor(210, 210, 210)); p.setBrush(QColor(240, 240, 240)); p.setPen(QColor(77, 77, 77)); p.translate(option.rect.topLeft()); p.translate(0, sizeHint(option, index).height() - ITEM_HEIGHT); p.translate(OFFSET_H, OFFSET_H); QImage img = index.data(Qt::DecorationRole).value<QImage>(); if(!img.isNull()) { p.drawImage(0,0, img); } else { p.drawImage(0,0, defaultIcon_); } p.translate(ICON_SIZE + OFFSET_H, 0); // 10px // QFont f = option.font; f.setPointSize(10); f.setWeight(QFont::Bold); QFontMetrics fm(f); tr = fm.boundingRect(name); p.setFont(f); p.drawText(0, tr.height()-5, name); // p.setFont(option.font); fm = QFontMetrics(option.font); QDate date_ = index.data(QvObjectModel::DateRole).toDate(); int version_ = index.data(QvObjectModel::VersionRole).toInt(); QString versionStr_; if(!date_.isNull()) { versionStr_ = date_.toString("dd MMMM yyyy"); } else if(version_ > 1000000000){ int ver_min = 0; int ver = version_ / 1000000000; ver_min = version_ % 1000000000; int major = ver_min / 10000000; ver_min = ver_min % 10000000; int minor = ver_min / 100000; ver_min = ver_min % 100000; versionStr_ = QCoreApplication::translate("list", "%1.%2.%3.%4", "Version in list") .arg(ver).arg(major, 2, 10, QLatin1Char('0') ) .arg(minor, 2, 10, QLatin1Char('0')).arg(ver_min); } if(!versionStr_.isEmpty()) { tr = fm.boundingRect(versionStr_); tr.moveTo(option.rect.width() - ICON_SIZE - 2*OFFSET_H - tr.width() - OFFSET_BUTTON, 0 ); painter->drawText(tr, Qt::TextSingleLine, versionStr_); } int maxWidth(option.rect.width() - widthButtonGroup(index) - ICON_SIZE - OFFSET_H - DETAIL_OFFSET ); if(!index.data(QvObjectModel::DetailRole).toString().isEmpty()) { maxWidth -= fm.boundingRect(QCoreApplication::translate("list", "Detail")).width(); } description = fm.elidedText(description, Qt::ElideRight, maxWidth); p.translate(0, ICON_SIZE / 2); tr = fm.boundingRect(description); p.drawText(0, tr.height(), description); if(!index.data(QvObjectModel::DetailRole).toString().isEmpty()) { paintDetail(painter, option, index); } if(index.flags().testFlag(Qt::ItemFlag(QvAbstractListItem::Downloading))) { paintObjectProgress(painter, option, index); } paintObjectBtn(painter, option, index); }
p.translate(option.rect.topLeft()); p.translate(0, sizeHint(option, index).height() - ITEM_HEIGHT); p.translate(OFFSET_H, OFFSET_H);
void QvObjectDelegate::paintObjectProgress( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const { QStyleOptionProgressBarV2 opt; initStyleProgressOption(&opt, index); QStyle *style = QApplication::style(); opt.rect.setLeft(option.rect.width() - (CHECK_WIDTH + OFFSET_H) * 2 - ICON_SIZE - OFFSET_BUTTON - buttonRect.width() - OFFSET_BUTTON ); opt.rect.setTop( 4 ); opt.rect.setWidth(CHECK_WIDTH * 2); opt.rect.setHeight(PROGRESS_HEIGHT); painter->setPen(QColor(77, 77, 77)); style->drawControl(QStyle::CE_ProgressBar, &opt, painter); } void QvObjectDelegate::initStyleProgressOption( QStyleOptionProgressBar *option, const QModelIndex & index ) const { int value = index.data(QvObjectModel::ProgressRole).toInt(); if (!option) return; option->rect = QRect(100, 100, 100, 100); option->state |= QStyle::State_Active; option->state |= QStyle::State_Enabled; option->state |= QStyle::State_Horizontal; option->minimum = 0; option->maximum = 100; //maximum?maximum:100; option->progress = value; option->textAlignment = Qt::AlignCenter; option->textVisible = true; option->text = QString("%1%").arg(value); if (QStyleOptionProgressBarV2 *optionV2 = qstyleoption_cast<QStyleOptionProgressBarV2 *>(option)) { optionV2->orientation = Qt::Horizontal ; // ### Qt 5: use State_Horizontal instead optionV2->invertedAppearance = false; optionV2->bottomToTop = true; } }
style->drawControl(QStyle::CE_ProgressBar, &opt, painter);
QVector<QvObjectDelegate::ButtonAction> QvObjectDelegate::getButtons( const QModelIndex &index ) const { QVector<ButtonAction> tags_; if(needRestart(index) ) { tags_ << baRestart << baCancel; } else if( index.flags() & Qt::ItemFlag(QvAbstractListItem::Downloading) ) { tags_ << baCancel; } else { bool installed = index.data(QvObjectModel::InstalledRole).toBool(), enabled = index.data(QvObjectModel::EnabledRole).toBool(), buildin = index.data(QvObjectModel::BuildInRole).toBool(); if (installed && (index.flags() & Qt::ItemFlag(QvAbstractListItem::hasUpdate))) { tags_ << baUpdate;} if (installed && index.flags() & Qt::ItemFlag(QvAbstractListItem::canBeToggled)) { tags_ << (enabled ? baDisable : baEnable);} if (installed && !buildin) { tags_ << baRemove;} if (!installed) { tags_ << baInstall; } } return tags_; }
void QvObjectDelegate::drawButton( QStyleOptionButton &o, const QPoint &p, QPainter * painter ) const { if(o.rect.contains(p)) o.state |= QStyle::State_Sunken; QStyle * style = QApplication::style(); if(style) style->drawControl(QStyle::CE_PushButton, &o, painter ); o.state &= ~QStyle::State_Sunken; o.rect.translate(buttonRect.width() + OFFSET_BUTTON, 0); }
bool editorEvent( QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index );
Q_ASSERT(event); Q_ASSERT(model); // make sure that we have the right event type if ((event->type() == QEvent::MouseButtonRelease) || (event->type() == QEvent::MouseMove) || (event->type() == QEvent::MouseButtonPress)) { return validateLabel(index, option, event) || validateButton(index, option, event); } else if (event->type() == QEvent::KeyPress) { if (static_cast<QKeyEvent*>(event)->key() != Qt::Key_Space && static_cast<QKeyEvent*>(event)->key() != Qt::Key_Select) return false; } else { return false; } return false;
Source: https://habr.com/ru/post/134802/
All Articles