/*! \overload Returns the size hint for objects drawn with the delgate with style options \a option for item at \a index. */ QSize TwoLevelDelegate::sizeHint(const QStyleOptionViewItem & option, const QModelIndex &index) const { QList< StringPair > subTexts = index.model()->data(index, SubLabelsRole).value<QList<StringPair> >(); QFontMetrics fm(option.font); int sublinesheight = 0; if (subTexts.count() > 0) { QFont fs = differentFont(option.font, -2); QFont bfs = fs; bfs.setWeight(QFont::Bold); QFontMetrics sbfm(bfs); QFontMetrics sfm(fs); int sublineheight = qMax(sfm.ascent(), sbfm.ascent()) + qMax(sfm.descent(), sbfm.descent()) + 1; sublinesheight = subTexts.count() * (sublineheight + 1); } return QSize(qApp->style()->pixelMetric(QStyle::PM_ListViewIconSize) + fm.width("M")*10, qMax(qApp->style()->pixelMetric(QStyle::PM_ListViewIconSize), fm.height() + sublinesheight)); }
/*! \internal Returns the font to use for painting the sub label text of the item. Due to the nature of rich text painting in Qt 4.0 attributes such as bold and italic will be ignored. These attributes can be set by the text returned for QAbstractItemModel::data() where role is QAppointmentModel::SubLabelRole. By default returns a font at least two point sizes smaller of the font of the style option \a o. */ QFont QAppointmentDelegate::secondaryFont(const QStyleOptionViewItem &o) const { return differentFont(o.font, -2); }
void TwoLevelDelegate::paint(QPainter *painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const { QString text = index.model()->data(index, Qt::DisplayRole).toString(); QList< StringPair > subTexts = index.model()->data(index, SubLabelsRole).value<QList<StringPair> >(); QIcon decoration = qvariant_cast<QIcon>(index.model()->data(index, Qt::DecorationRole)); QIcon secondaryDecoration = qvariant_cast<QIcon>(index.model()->data(index, SubIconRole)); bool rtl = QtopiaApplication::layoutDirection() == Qt::RightToLeft ; painter->save(); // fill rect based on row background // or assume can be left to list class bool selected = (option.state & (QStyle::State_Active | QStyle::State_Selected)) == (QStyle::State_Active | QStyle::State_Selected); QBrush baseBrush = selected ? option.palette.highlight() : option.palette.base(); QBrush textBrush = selected ? option.palette.highlightedText() : option.palette.text(); QPalette modpalette(option.palette); modpalette.setBrush(QPalette::Text, textBrush); // To avoid messing with the alternating row color, don't set this... // modpalette.setBrush(QPalette::Base, baseBrush); // painter->setBrush(baseBrush); painter->setPen(textBrush.color()); if (selected) painter->fillRect(option.rect, baseBrush); QFont fbold = option.font; QFont fsmall = differentFont(option.font, -2); QFont fsmallbold = fsmall; fbold.setWeight(QFont::Bold); fsmallbold.setWeight(QFont::Bold); QFontMetrics fboldM(fbold); QFontMetrics fsmallM(fsmall); QFontMetrics fsmallboldM(fsmallbold); int decorationSize = qApp->style()->pixelMetric(QStyle::PM_ListViewIconSize); int x = option.rect.x(); int y = option.rect.y(); int width = option.rect.width(); int height = option.rect.height()-1; if ( rtl ) painter->drawPixmap(width-decorationSize, y, decoration.pixmap(decorationSize) ); else painter->drawPixmap(x, y, decoration.pixmap(decorationSize)); x += decorationSize + 2; width -= decorationSize + 2; int bcardwidth = 0; int bcardbase = y; if (!secondaryDecoration.isNull()) { bcardwidth = decorationSize; bcardbase = y+decorationSize; if ( rtl ) painter->drawPixmap( option.rect.x(), y, secondaryDecoration.pixmap(decorationSize)); else painter->drawPixmap(x+width-bcardwidth, y,secondaryDecoration.pixmap(decorationSize)); } // draw label bold painter->setFont(fbold); // fit inside available width; QRect space; if ( rtl ) space = QRect(option.rect.x() + bcardwidth, y, width-bcardwidth, height); else space = QRect(x, y, width - bcardwidth, height); painter->drawText(space, Qt::AlignLeading, fboldM.elidedText(text, Qt::ElideRight, space.width())); y+=fboldM.height(); QString secText; StringPair subLine; int headerWidth = 0; /* First, calculate the width of all the header sections */ foreach(subLine, subTexts) { if (!subLine.first.isEmpty()) { int w = fsmallboldM.boundingRect(subLine.first).width(); if (w > headerWidth) headerWidth = w; } } headerWidth += 4; // a little padding int sublineheight = qMax(fsmallM.ascent(), fsmallboldM.ascent()) + qMax(fsmallM.descent(), fsmallboldM.descent()) + 1; // per font baseline adjustments, durnit. int headbase = 0; int valbase = 0; if (fsmallM.ascent() > fsmallboldM.ascent()) headbase = fsmallM.ascent() - fsmallboldM.ascent(); else valbase = fsmallboldM.ascent() - fsmallM.ascent(); /* Now draw! */ while (y + sublineheight <= option.rect.bottom() && !subTexts.isEmpty()) { if (y > bcardbase) { bcardwidth = 0; if ( rtl ) space = QRect(option.rect.x(), y, width, option.rect.bottom() - y + 1); else space = QRect(x, y, width, option.rect.bottom() - y + 1); } else space.setTop(y); subLine = subTexts.takeFirst(); if (!subLine.first.isNull()) { if (!subLine.second.isEmpty()) { QRect headerRect = space.adjusted(0,headbase,0,0); QRect valueRect = space.adjusted(0,valbase,0,0); if (rtl) { headerRect.setLeft(option.rect.x() - headerWidth - 1); valueRect.setRight(option.rect.x() - headerWidth - 1); } else { headerRect.setRight(x + headerWidth + 1); valueRect.setLeft(x + headerWidth + 1); } painter->setFont(fsmallbold); painter->drawText(headerRect, Qt::AlignLeading, subLine.first); painter->setFont(fsmall); painter->drawText(valueRect, Qt::AlignLeading, fsmallM.elidedText(subLine.second, Qt::ElideRight, valueRect.width())); } else { painter->setFont(fsmallbold); painter->drawText(space, Qt::AlignLeading, fsmallboldM.elidedText(subLine.first, Qt::ElideRight, space.width())); } } else { if (!subLine.second.isEmpty()) { painter->setFont(fsmall); painter->drawText(space, Qt::AlignLeading, fsmallM.elidedText(subLine.second, Qt::ElideRight, space.width())); } } y += sublineheight + 1; } painter->restore(); }