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"