File indexing completed on 2024-12-08 04:34:09

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     constexpr int extraMargins = 2 * padding;
0041     const auto isHeader = !index.parent().isValid();
0042     const int iconSize = isHeader ? 0 : option.widget->style()->pixelMetric(QStyle::PM_ButtonIconSize);
0043     const int margin = DelegatePaintUtil::margin();
0044     int offsetAvatarRoom = 0;
0045     const bool showRoomAvatar = mRocketChatAccount ? mRocketChatAccount->ownUserPreferences().showRoomAvatar() : false;
0046     if (!isHeader && showRoomAvatar) {
0047         offsetAvatarRoom = margin + option.rect.height() - extraMargins; // Icon will be draw with option.rect.height() - 2 * padding as size.
0048     }
0049     const QRect decorationRect(option.rect.x() + margin + offsetAvatarRoom, option.rect.y() + padding, iconSize, option.rect.height() - extraMargins);
0050     const QString text = index.data(Qt::DisplayRole).toString();
0051     // const QSize textSize = option.fontMetrics.size(Qt::TextSingleLine, text);
0052     const QString unreadText = isHeader ? QString() : makeUnreadText(index);
0053     const QSize unreadSize = !unreadText.isEmpty() ? option.fontMetrics.size(Qt::TextSingleLine, unreadText) : QSize(0, 0);
0054     const int xText = offsetAvatarRoom + option.rect.x() + iconSize + (isHeader ? 1 : 2) * margin;
0055     const QRect displayRect(xText, option.rect.y() + padding, option.rect.width() - xText - unreadSize.width() - margin, option.rect.height() - extraMargins);
0056     const QRect unreadRect(option.rect.width() - unreadSize.width() - margin,
0057                            option.rect.y() + padding,
0058                            unreadSize.width(),
0059                            option.rect.height() - extraMargins);
0060 
0061     QStyleOptionViewItem optionCopy = option;
0062     optionCopy.showDecorationSelected = true;
0063     drawBackground(painter, optionCopy, index);
0064 
0065     if (!isHeader) {
0066         const auto icon = index.data(Qt::DecorationRole).value<QIcon>();
0067         icon.paint(painter, decorationRect, Qt::AlignCenter);
0068         if (showRoomAvatar) {
0069             const auto avatarInfo = index.data(RoomModel::RoomAvatarInfo).value<Utils::AvatarInfo>();
0070             if (avatarInfo.isValid()) {
0071                 const QPixmap pix = mAvatarCacheManager->makeAvatarPixmap(option.widget, avatarInfo, option.rect.height() - extraMargins);
0072 #if USE_ROUNDED_RECT_PIXMAP
0073                 const QPointF pos(margin, option.rect.top() + padding);
0074                 DelegatePaintUtil::createClipRoundedRectangle(painter, QRectF(pos, pix.size()), pos, pix);
0075 #else
0076                 painter->drawPixmap(margin, option.rect.top() + padding, pix);
0077 #endif
0078             }
0079         }
0080     }
0081 
0082     if (!(unreadText.isEmpty() && !index.data(RoomModel::RoomAlert).toBool())) {
0083         if (!index.data(RoomModel::HideBadgeForMention).toBool()) {
0084             optionCopy.palette.setBrush(QPalette::Text, optionCopy.palette.brush(QPalette::Link));
0085             if (option.state & QStyle::State_Selected) {
0086                 optionCopy.palette.setBrush(QPalette::Text, optionCopy.palette.brush(QPalette::HighlightedText));
0087             }
0088         }
0089     } else {
0090         if (option.state & QStyle::State_Selected) {
0091             optionCopy.palette.setBrush(QPalette::Text, optionCopy.palette.brush(QPalette::LinkVisited));
0092         }
0093         if (index.data(RoomModel::UserOffline).toBool()) {
0094             optionCopy.palette.setBrush(QPalette::Text, ColorsAndMessageViewStyle::self().schemeView().foreground(KColorScheme::InactiveText).color());
0095         }
0096     }
0097     drawDisplay(painter, optionCopy, displayRect, text); // this takes care of eliding if the text is too long
0098     if (!isHeader) {
0099         painter->setPen(ColorsAndMessageViewStyle::self().schemeView().foreground(KColorScheme::NegativeText).color());
0100         painter->drawText(unreadRect, unreadText);
0101     }
0102 }
0103 
0104 QString ChannelListDelegate::makeUnreadText(const QModelIndex &index) const
0105 {
0106     const bool hideBadgeForMention = index.data(RoomModel::HideBadgeForMention).toBool();
0107     if (hideBadgeForMention) {
0108         return QString();
0109     }
0110     const int unreadCount = index.data(RoomModel::RoomUnread).toInt();
0111     const QString unreadText = unreadCount > 0 ? QStringLiteral("(%1)").arg(unreadCount) : QString();
0112     const int userMentionsCount = index.data(RoomModel::RoomUserMentions).toInt();
0113     return (userMentionsCount > 0) ? QLatin1Char('@') + unreadText : unreadText;
0114 }
0115 
0116 QSize ChannelListDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
0117 {
0118     constexpr int extraMargins = 2 * padding;
0119     return QItemDelegate::sizeHint(option, index) + QSize(0, extraMargins);
0120 }
0121 
0122 #include "moc_channellistdelegate.cpp"