File indexing completed on 2024-05-12 16:27:03

0001 /*
0002    SPDX-FileCopyrightText: 2020 David Faure <faure@kde.org>
0003 
0004    SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "channellistdelegate.h"
0008 #include "colorsandmessageviewstyle.h"
0009 #include "common/delegatepaintutil.h"
0010 #include "config-ruqola.h"
0011 #include "misc/avatarcachemanager.h"
0012 #include "model/roommodel.h"
0013 #include "rocketchataccount.h"
0014 
0015 #include <KColorScheme>
0016 #include <QPainter>
0017 
0018 namespace
0019 {
0020 constexpr uint padding = 2;
0021 }
0022 
0023 ChannelListDelegate::ChannelListDelegate(QObject *parent)
0024     : QItemDelegate(parent)
0025     , mAvatarCacheManager(new AvatarCacheManager(Utils::AvatarType::Room, this))
0026 {
0027 }
0028 
0029 ChannelListDelegate::~ChannelListDelegate() = default;
0030 
0031 void ChannelListDelegate::setCurrentRocketChatAccount(RocketChatAccount *currentRocketChatAccount)
0032 {
0033     mAvatarCacheManager->setCurrentRocketChatAccount(currentRocketChatAccount);
0034     mRocketChatAccount = currentRocketChatAccount;
0035 }
0036 
0037 void ChannelListDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
0038 {
0039     // [M] <avatar> [M] <icon> [M] <name>       <(nr_unread)> [M]    ([M] = margin)
0040     const auto isHeader = !index.parent().isValid();
0041     const int iconSize = isHeader ? 0 : option.widget->style()->pixelMetric(QStyle::PM_ButtonIconSize);
0042     const int margin = DelegatePaintUtil::margin();
0043     int offsetAvatarRoom = 0;
0044     const bool showRoomAvatar = mRocketChatAccount ? mRocketChatAccount->ownUserPreferences().showRoomAvatar() : false;
0045     if (!isHeader && showRoomAvatar) {
0046         offsetAvatarRoom = margin + option.rect.height() - 2 * padding; // Icon will be draw with option.rect.height() - 2 * padding as size.
0047     }
0048     const QRect decorationRect(option.rect.x() + margin + offsetAvatarRoom, option.rect.y() + padding, iconSize, option.rect.height() - 2 * padding);
0049     const QString text = index.data(Qt::DisplayRole).toString();
0050     // const QSize textSize = option.fontMetrics.size(Qt::TextSingleLine, text);
0051     const QString unreadText = isHeader ? QString() : makeUnreadText(index);
0052     const QSize unreadSize = !unreadText.isEmpty() ? option.fontMetrics.size(Qt::TextSingleLine, unreadText) : QSize(0, 0);
0053     const int xText = offsetAvatarRoom + option.rect.x() + iconSize + (isHeader ? 1 : 2) * margin;
0054     const QRect displayRect(xText, option.rect.y() + padding, option.rect.width() - xText - unreadSize.width() - margin, option.rect.height() - 2 * padding);
0055     const QRect unreadRect(option.rect.width() - unreadSize.width() - margin,
0056                            option.rect.y() + padding,
0057                            unreadSize.width(),
0058                            option.rect.height() - 2 * padding);
0059 
0060     QStyleOptionViewItem optionCopy = option;
0061     optionCopy.showDecorationSelected = true;
0062     drawBackground(painter, optionCopy, index);
0063 
0064     if (!isHeader) {
0065         const auto icon = index.data(Qt::DecorationRole).value<QIcon>();
0066         icon.paint(painter, decorationRect, Qt::AlignCenter);
0067         if (showRoomAvatar) {
0068             const auto avatarInfo = index.data(RoomModel::RoomAvatarInfo).value<Utils::AvatarInfo>();
0069             if (avatarInfo.isValid()) {
0070                 const QPixmap pix = mAvatarCacheManager->makeAvatarPixmap(option.widget, avatarInfo, option.rect.height() - 2 * padding);
0071 #if USE_ROUNDED_RECT_PIXMAP
0072                 const QPointF pos(margin, option.rect.top() + padding);
0073                 DelegatePaintUtil::createClipRoundedRectangle(painter, QRectF(pos, pix.size()), pos, pix);
0074 #else
0075                 painter->drawPixmap(margin, option.rect.top() + padding, pix);
0076 #endif
0077             }
0078         }
0079     }
0080 
0081     if (!(unreadText.isEmpty() && !index.data(RoomModel::RoomAlert).toBool())) {
0082         if (!index.data(RoomModel::HideBadgeForMention).toBool()) {
0083             optionCopy.palette.setBrush(QPalette::Text, optionCopy.palette.brush(QPalette::Link));
0084             if (option.state & QStyle::State_Selected) {
0085                 optionCopy.palette.setBrush(QPalette::Text, optionCopy.palette.brush(QPalette::HighlightedText));
0086             }
0087         }
0088     } else {
0089         if (option.state & QStyle::State_Selected) {
0090             optionCopy.palette.setBrush(QPalette::Text, optionCopy.palette.brush(QPalette::LinkVisited));
0091         }
0092         if (index.data(RoomModel::UserOffline).toBool()) {
0093             optionCopy.palette.setBrush(QPalette::Text, ColorsAndMessageViewStyle::self().schemeView().foreground(KColorScheme::InactiveText).color());
0094         }
0095     }
0096     drawDisplay(painter, optionCopy, displayRect, text); // this takes care of eliding if the text is too long
0097     if (!isHeader) {
0098         painter->setPen(ColorsAndMessageViewStyle::self().schemeView().foreground(KColorScheme::NegativeText).color());
0099         painter->drawText(unreadRect, unreadText);
0100     }
0101 }
0102 
0103 QString ChannelListDelegate::makeUnreadText(const QModelIndex &index) const
0104 {
0105     const bool hideBadgeForMention = index.data(RoomModel::HideBadgeForMention).toBool();
0106     if (hideBadgeForMention) {
0107         return QString();
0108     }
0109     const int unreadCount = index.data(RoomModel::RoomUnread).toInt();
0110     const QString unreadText = unreadCount > 0 ? QStringLiteral("(%1)").arg(unreadCount) : QString();
0111     const int userMentionsCount = index.data(RoomModel::RoomUserMentions).toInt();
0112     return (userMentionsCount > 0) ? QLatin1Char('@') + unreadText : unreadText;
0113 }
0114 
0115 QSize ChannelListDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
0116 {
0117     return QItemDelegate::sizeHint(option, index) + QSize(0, 2 * padding);
0118 }
0119 
0120 #include "moc_channellistdelegate.cpp"