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"