Warning, file /network/ktp-contact-list/contact-delegate-compact.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /*
0002  * Contact Delegate - compact version
0003  *
0004  * Copyright (C) 2011 Martin Klapetek <martin.klapetek@gmail.com>
0005  * Copyright (C) 2012 Dominik Cermak <d.cermak@arcor.de>
0006  *
0007  * This library is free software; you can redistribute it and/or
0008  * modify it under the terms of the GNU Lesser General Public
0009  * License as published by the Free Software Foundation; either
0010  * version 2.1 of the License, or (at your option) any later version.
0011  *
0012  * This library is distributed in the hope that it will be useful,
0013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0015  * Lesser General Public License for more details.
0016  *
0017  * You should have received a copy of the GNU Lesser General Public
0018  * License along with this library; if not, write to the Free Software
0019  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
0020  */
0021 
0022 #include "contact-delegate-compact.h"
0023 
0024 #include <QPainter>
0025 #include <QPainterPath>
0026 #include <QToolTip>
0027 #include <QApplication>
0028 #include <QStyle>
0029 #include <QHelpEvent>
0030 #include <QFontDatabase>
0031 #include <QPixmapCache>
0032 #include <QCryptographicHash>
0033 #include <QStyleOptionViewItem>
0034 
0035 #include <KIconLoader>
0036 
0037 #include <KTp/types.h>
0038 
0039 ContactDelegateCompact::ContactDelegateCompact(ContactDelegateCompact::ListSize size, QObject *parent)
0040     : AbstractContactDelegate(parent)
0041 {
0042     setListMode(size);
0043     QPixmapCache::setCacheLimit(102400);
0044 }
0045 
0046 ContactDelegateCompact::~ContactDelegateCompact()
0047 {
0048 
0049 }
0050 
0051 void ContactDelegateCompact::paintContact(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
0052 {
0053     QStyleOptionViewItem opt = option;
0054     initStyleOption(&opt, index);
0055 
0056     bool isSubcontact = index.parent().isValid() && index.parent().data(KTp::RowTypeRole).toUInt() == KTp::PersonRowType;
0057 
0058     painter->save();
0059 
0060     painter->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform | QPainter::HighQualityAntialiasing);
0061     painter->setClipRect(opt.rect);
0062 
0063     QStyle *style = QApplication::style();
0064     style->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter);
0065 
0066     QRect iconRect = opt.rect;
0067     iconRect.setSize(QSize(m_avatarSize, m_avatarSize));
0068     iconRect.moveTo(QPoint(iconRect.x() + m_spacing, iconRect.y() + m_spacing));
0069 
0070     QPixmap avatar(qvariant_cast<QPixmap>(index.data(KTp::ContactAvatarPixmapRole)));
0071 
0072     if (index.data(KTp::ContactUnreadMessageCountRole).toInt() > 0) {
0073         avatar = SmallIcon("mail-unread-new", KIconLoader::SizeMedium);
0074     }
0075 
0076     //if the contact is offline, gray it out
0077     if (index.data(KTp::ContactPresenceTypeRole).toUInt() == Tp::ConnectionPresenceTypeOffline) {
0078         if (!QPixmapCache::find(index.data(KTp::IdRole).toString() + QStringLiteral("gray"), &avatar)) {
0079             avatarToGray(avatar);
0080             QPixmapCache::insert(index.data(KTp::IdRole).toString() + QStringLiteral("gray"), avatar);
0081         }
0082     }
0083 
0084     if (!avatar.isNull()) {
0085         style->drawItemPixmap(painter, iconRect, Qt::AlignCenter, avatar.scaled(iconRect.size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
0086     }
0087 
0088     // This value is used to set the correct width for the username and the presence message.
0089     int rightIconsWidth = m_presenceIconSize + m_spacing;
0090 
0091     QPixmap icon = QIcon::fromTheme(index.data(KTp::ContactPresenceIconRole).toString()).pixmap(KIconLoader::SizeSmallMedium);
0092 
0093     QRect statusIconRect = opt.rect;
0094 
0095     statusIconRect.setSize(QSize(m_presenceIconSize, m_presenceIconSize));
0096     statusIconRect.moveTo(QPoint(opt.rect.right() - (rightIconsWidth),
0097                                  opt.rect.top() + (opt.rect.height() - m_presenceIconSize) / 2));
0098 
0099     painter->drawPixmap(statusIconRect, icon);
0100 
0101     // Right now we only check for 'phone', as that's the most interesting type.
0102     if (index.data(KTp::ContactClientTypesRole).toStringList().contains(QLatin1String("phone"))) {
0103         // Additional space is needed for the icons, don't add too much spacing between the two icons
0104         rightIconsWidth += m_clientTypeIconSize + m_spacing;
0105 
0106         QPixmap phone = QIcon::fromTheme("phone").pixmap(m_clientTypeIconSize);
0107         QRect phoneIconRect = opt.rect;
0108         phoneIconRect.setSize(QSize(m_clientTypeIconSize, m_clientTypeIconSize));
0109         phoneIconRect.moveTo(QPoint(opt.rect.right() - rightIconsWidth,
0110                                     opt.rect.top() + (opt.rect.height() - m_clientTypeIconSize) / 2));
0111         painter->drawPixmap(phoneIconRect, phone);
0112     }
0113 
0114     const Tp::AccountPtr &account = index.data(KTp::AccountRole).value<Tp::AccountPtr>();
0115     if (account && isSubcontact) {
0116         rightIconsWidth += m_clientTypeIconSize + m_spacing;
0117 
0118         const QPixmap accountIcon = QIcon::fromTheme(account->iconName()).pixmap(m_clientTypeIconSize);
0119         QRect accountIconRect = opt.rect;
0120         accountIconRect.setSize(QSize(m_clientTypeIconSize, m_clientTypeIconSize));
0121         accountIconRect.moveTo(QPoint(opt.rect.right() - rightIconsWidth,
0122                                     opt.rect.top() + (opt.rect.height() - m_clientTypeIconSize) / 2));
0123         painter->drawPixmap(accountIconRect, accountIcon);
0124     }
0125 
0126     QFont nameFont;
0127 
0128     if (m_listSize == ContactDelegateCompact::Mini) {
0129         nameFont = QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont);
0130     } else {
0131         nameFont = QFontDatabase::systemFont(QFontDatabase::GeneralFont);
0132     }
0133 
0134     const QFontMetrics nameFontMetrics(nameFont);
0135 
0136     if (option.state & QStyle::State_Selected) {
0137         painter->setPen(option.palette.color(option.palette.currentColorGroup(), QPalette::HighlightedText));
0138     } else {
0139         painter->setPen(option.palette.color(option.palette.currentColorGroup(), QPalette::Text));
0140     }
0141 
0142     painter->setFont(nameFont);
0143 
0144     QRect userNameRect = opt.rect;
0145     userNameRect.setX(iconRect.x() + iconRect.width() + m_spacing * 2);
0146     userNameRect.setY(userNameRect.y() + (userNameRect.height()/2 - nameFontMetrics.height()/2));
0147     userNameRect.setWidth(userNameRect.width() - rightIconsWidth);
0148 
0149     QString nameText = index.data(Qt::DisplayRole).toString();
0150 
0151     painter->drawText(userNameRect,
0152                       nameFontMetrics.elidedText(nameText, Qt::ElideRight, userNameRect.width()));
0153 
0154     QRect presenceMessageRect = opt.rect;
0155     presenceMessageRect.setX(userNameRect.x() + nameFontMetrics.boundingRect(opt.text).width() + m_spacing * 2);
0156     presenceMessageRect.setWidth(opt.rect.width() - presenceMessageRect.x() - rightIconsWidth);
0157     presenceMessageRect.setY(presenceMessageRect.y() + (presenceMessageRect.height()/2 - nameFontMetrics.height()/2));
0158 
0159     if (option.state & QStyle::State_Selected) {
0160         painter->setPen(option.palette.color(QPalette::Disabled, QPalette::HighlightedText));
0161     } else {
0162         painter->setPen(option.palette.color(QPalette::Disabled, QPalette::Text));
0163     }
0164 
0165     painter->drawText(presenceMessageRect,
0166                       nameFontMetrics.elidedText(index.data(KTp::ContactPresenceMessageRole).toString().trimmed(),
0167                                                  Qt::ElideRight, presenceMessageRect.width()));
0168 
0169     painter->restore();
0170 }
0171 
0172 QSize ContactDelegateCompact::sizeHintContact(const QStyleOptionViewItem &option, const QModelIndex &index) const
0173 {
0174     Q_UNUSED(option);
0175     Q_UNUSED(index);
0176 
0177     return QSize(0, qMax(m_avatarSize + 2 * m_spacing, QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont).pixelSize() + m_spacing));
0178 }
0179 
0180 QSize ContactDelegateCompact::sizeHintHeader(const QStyleOptionViewItem& option, const QModelIndex& index) const
0181 {
0182     Q_UNUSED(option);
0183     Q_UNUSED(index);
0184 
0185     if (m_listSize == ContactDelegateCompact::Mini) {
0186         return QSize(0, qMax(m_avatarSize + 2 * m_spacing, QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont).pixelSize() + m_spacing));
0187     } else {
0188         return AbstractContactDelegate::sizeHintHeader(option, index);
0189     }
0190 }
0191 
0192 void ContactDelegateCompact::setListMode(ContactDelegateCompact::ListSize size)
0193 {
0194     if (size == ContactDelegateCompact::Mini) {
0195         m_spacing = 1;
0196         int iconSize = qMax(KIconLoader::global()->currentSize(KIconLoader::Small),
0197                             QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont).pixelSize() + m_spacing);
0198         m_avatarSize = iconSize;
0199         m_presenceIconSize = iconSize;
0200         m_clientTypeIconSize = iconSize;
0201     } else if (size == ContactDelegateCompact::Normal) {
0202         m_spacing = 4;
0203         m_avatarSize = IconSize(KIconLoader::Toolbar);
0204         m_presenceIconSize = IconSize(KIconLoader::Small);
0205         m_clientTypeIconSize = IconSize(KIconLoader::Small);
0206     }
0207 
0208     m_listSize = size;
0209 }