File indexing completed on 2023-05-30 09:18:55
0001 /* 0002 * Abstract Contact Delegate - base class for other delegates 0003 * 0004 * Copyright (C) 2011 Martin Klapetek <martin.klapetek@gmail.com> 0005 * 0006 * This library is free software; you can redistribute it and/or 0007 * modify it under the terms of the GNU Lesser General Public 0008 * License as published by the Free Software Foundation; either 0009 * version 2.1 of the License, or (at your option) any later version. 0010 * 0011 * This library is distributed in the hope that it will be useful, 0012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 * Lesser General Public License for more details. 0015 * 0016 * You should have received a copy of the GNU Lesser General Public 0017 * License along with this library; if not, write to the Free Software 0018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 0019 */ 0020 0021 #include "abstract-contact-delegate.h" 0022 0023 #include <QApplication> 0024 #include <QStyle> 0025 #include <QPainter> 0026 #include <QToolTip> 0027 #include <QHelpEvent> 0028 #include <QFontDatabase> 0029 #include <QAbstractItemView> 0030 #include <QStyleOptionViewItem> 0031 0032 #include <KIconLoader> 0033 0034 #include <KTp/types.h> 0035 0036 const int SPACING = 2; 0037 const int ACCOUNT_ICON_SIZE = 22; 0038 const qreal GROUP_ICON_OPACITY = 0.6; 0039 0040 AbstractContactDelegate::AbstractContactDelegate(QObject *parent) 0041 : QStyledItemDelegate(parent) 0042 { 0043 } 0044 0045 AbstractContactDelegate::~AbstractContactDelegate() 0046 { 0047 } 0048 0049 void AbstractContactDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const 0050 { 0051 if (index.data(KTp::RowTypeRole).toInt() == KTp::ContactRowType || index.data(KTp::RowTypeRole).toInt() == KTp::PersonRowType) { 0052 paintContact(painter, option, index); 0053 } else { 0054 paintHeader(painter, option, index); 0055 } 0056 } 0057 0058 QSize AbstractContactDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const 0059 { 0060 if (index.data(KTp::RowTypeRole).toInt() == KTp::ContactRowType || index.data(KTp::RowTypeRole).toInt() == KTp::PersonRowType) { 0061 return sizeHintContact(option, index); 0062 } else { 0063 return sizeHintHeader(option, index); 0064 } 0065 } 0066 0067 void AbstractContactDelegate::paintHeader(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const 0068 { 0069 QStyleOptionViewItem opt = option; 0070 initStyleOption(&opt, index); 0071 0072 painter->save(); 0073 0074 painter->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform | QPainter::HighQualityAntialiasing); 0075 painter->setClipRect(opt.rect); 0076 0077 QStyle *style = QApplication::style(); 0078 style->drawPrimitive(QStyle::PE_PanelItemViewItem, &option, painter); 0079 0080 QRect groupRect = opt.rect; 0081 0082 //paint the background 0083 QBrush bgBrush(option.palette.color(QPalette::Active, QPalette::Button).lighter(105)); 0084 painter->fillRect(groupRect, bgBrush); 0085 0086 //paint very subtle line at the bottom 0087 QPen thinLinePen; 0088 thinLinePen.setWidth(0); 0089 thinLinePen.setColor(option.palette.color(QPalette::Active, QPalette::Button)); 0090 painter->setPen(thinLinePen); 0091 //to get nice sharp 1px line we need to turn AA off, otherwise it will be all blurry 0092 painter->setRenderHint(QPainter::Antialiasing, false); 0093 painter->drawLine(groupRect.bottomLeft(), groupRect.bottomRight()); 0094 painter->setRenderHint(QPainter::Antialiasing, true); 0095 0096 //remove spacing from the sides and one point to the bottom for the 1px line 0097 groupRect.adjust(SPACING, 0, -SPACING, -1); 0098 0099 //get the proper rect for the expand sign 0100 int iconSize = IconSize(KIconLoader::Toolbar); 0101 0102 QStyleOption expandSignOption = option; 0103 expandSignOption.rect = groupRect; 0104 //FIXME hardcoded magic...though corresponds with the list indentation 0105 expandSignOption.rect.setSize(QSize(14, iconSize)); 0106 expandSignOption.rect.moveLeft(groupRect.left()); 0107 expandSignOption.rect.moveTop(groupRect.top() + groupRect.height()/2 - expandSignOption.rect.height()/2); 0108 // simulates mouseover to highlight arrow when selected with keyboard 0109 if (option.state & QStyle::State_Selected) { 0110 expandSignOption.state |= QStyle::State_MouseOver; 0111 } 0112 0113 //paint the expand sign 0114 if (option.state & QStyle::State_Open) { 0115 style->drawPrimitive(QStyle::PE_IndicatorArrowDown, &expandSignOption, painter); 0116 } else { 0117 style->drawPrimitive(QStyle::PE_IndicatorArrowRight, &expandSignOption, painter); 0118 } 0119 0120 QFont groupFont = QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont); 0121 0122 //paint the group icon 0123 QRect groupIconRect; 0124 groupIconRect.setSize(QSize(ACCOUNT_ICON_SIZE, ACCOUNT_ICON_SIZE)); 0125 groupIconRect.moveRight(groupRect.right()); 0126 groupIconRect.moveTop(groupRect.top() + groupRect.height()/2 - groupIconRect.height()/2); 0127 0128 if (index.data(KTp::RowTypeRole).toInt() == KTp::AccountRowType) { 0129 //draw the icon with some opacity 0130 painter->setOpacity(GROUP_ICON_OPACITY); 0131 painter->drawPixmap(groupIconRect, index.data(Qt::DecorationRole).value<QIcon>().pixmap(ACCOUNT_ICON_SIZE)); 0132 painter->setOpacity(1.0); 0133 } else { 0134 groupIconRect.setWidth(0); 0135 } 0136 0137 //paint the header string 0138 QRect groupLabelRect = groupRect.adjusted(expandSignOption.rect.width() + SPACING * 2, 0, -groupIconRect.width() -SPACING, 0); 0139 QString countsString = QString("(%1/%2)").arg(index.data(KTp::HeaderOnlineUsersRole).toString(), 0140 index.data(KTp::HeaderTotalUsersRole).toString()); 0141 QString groupHeaderString = index.data(Qt::DisplayRole).toString(); 0142 QFontMetrics groupFontMetrics(groupFont); 0143 0144 painter->setFont(groupFont); 0145 if (index.data(KTp::HeaderTotalUsersRole).toInt() > 0) { 0146 painter->setPen(option.palette.color(QPalette::Disabled, QPalette::Text)); 0147 painter->drawText(groupLabelRect, Qt::AlignVCenter | Qt::AlignRight, countsString); 0148 } 0149 0150 painter->setPen(option.palette.color(QPalette::Active, QPalette::Text)); 0151 painter->drawText(groupLabelRect, Qt::AlignVCenter | Qt::AlignLeft, 0152 groupFontMetrics.elidedText(groupHeaderString, Qt::ElideRight, 0153 groupLabelRect.width() - groupFontMetrics.width(countsString) - SPACING)); 0154 0155 painter->restore(); 0156 } 0157 0158 QSize AbstractContactDelegate::sizeHintHeader(const QStyleOptionViewItem &option, const QModelIndex &index) const 0159 { 0160 Q_UNUSED(option) 0161 Q_UNUSED(index) 0162 0163 // Add one point to the bottom for the 1px line 0164 return QSize(0, qMax(ACCOUNT_ICON_SIZE, QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont).pixelSize()) + SPACING + 1); 0165 } 0166 0167 bool AbstractContactDelegate::helpEvent(QHelpEvent *event, QAbstractItemView *view, const QStyleOptionViewItem &option, const QModelIndex &index) 0168 { 0169 Q_UNUSED(event) 0170 Q_UNUSED(view) 0171 Q_UNUSED(option) 0172 Q_UNUSED(index) 0173 return false; 0174 } 0175 0176 void AbstractContactDelegate::avatarToGray(QPixmap &avatar) const 0177 { 0178 QImage image = avatar.toImage(); 0179 QImage alpha= image.alphaChannel(); 0180 for (int i = 0; i < image.width(); ++i) { 0181 for (int j = 0; j < image.height(); ++j) { 0182 int colour = qGray(image.pixel(i, j)); 0183 image.setPixel(i, j, qRgb(colour, colour, colour)); 0184 } 0185 } 0186 image.setAlphaChannel(alpha); 0187 avatar = QPixmap::fromImage(image); 0188 }