File indexing completed on 2024-06-23 04:40:22
0001 /* 0002 SPDX-FileCopyrightText: 2023-2024 Laurent Montel <montel.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "emoticonitemdelegate.h" 0008 #include <QAbstractItemView> 0009 #include <QMovie> 0010 #include <QPainter> 0011 #include <TextEmoticonsCore/EmojiModel> 0012 using namespace TextEmoticonsWidgets; 0013 EmoticonItemDelegate::EmoticonItemDelegate(QObject *parent) 0014 : QStyledItemDelegate{parent} 0015 { 0016 } 0017 0018 EmoticonItemDelegate::~EmoticonItemDelegate() = default; 0019 0020 void EmoticonItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const 0021 { 0022 const bool imageAnimated = index.data(TextEmoticonsCore::EmojiModel::Animated).toBool(); 0023 if (imageAnimated) { 0024 const QString imageAnimatedFilename = index.data(TextEmoticonsCore::EmojiModel::AnimatedFileName).toString(); 0025 auto it = findRunningAnimatedImage(index); 0026 QPixmap scaledPixmap; 0027 if (it != mRunningAnimatedImages.end()) { 0028 scaledPixmap = (*it).movie->currentPixmap(); 0029 } else { 0030 mRunningAnimatedImages.emplace_back(index); 0031 auto &rai = mRunningAnimatedImages.back(); 0032 rai.movie->setFileName(imageAnimatedFilename); 0033 rai.movie->setScaledSize(option.decorationSize); 0034 auto view = qobject_cast<QAbstractItemView *>(const_cast<QWidget *>(option.widget)); 0035 const QPersistentModelIndex &idx = rai.index; 0036 QObject::connect( 0037 rai.movie, 0038 &QMovie::frameChanged, 0039 view, 0040 [view, idx, this]() { 0041 if (view->viewport()->rect().contains(view->visualRect(idx))) { 0042 view->update(idx); 0043 } else { 0044 removeRunningAnimatedImage(idx); 0045 } 0046 }, 0047 Qt::QueuedConnection); 0048 rai.movie->start(); 0049 scaledPixmap = rai.movie->currentPixmap(); 0050 } 0051 scaledPixmap.setDevicePixelRatio(option.widget->devicePixelRatioF()); 0052 painter->drawPixmap(QRect(option.rect.topLeft(), option.decorationSize), scaledPixmap); 0053 } else { 0054 QStyledItemDelegate::paint(painter, option, index); 0055 } 0056 } 0057 0058 std::vector<TextEmoticonsCore::RunningAnimatedImage>::iterator EmoticonItemDelegate::findRunningAnimatedImage(const QModelIndex &index) const 0059 { 0060 auto matchesIndex = [&](const TextEmoticonsCore::RunningAnimatedImage &rai) { 0061 return rai.index == index; 0062 }; 0063 return std::find_if(mRunningAnimatedImages.begin(), mRunningAnimatedImages.end(), matchesIndex); 0064 } 0065 0066 void EmoticonItemDelegate::removeRunningAnimatedImage(const QModelIndex &index) const 0067 { 0068 auto it = findRunningAnimatedImage(index); 0069 if (it != mRunningAnimatedImages.end()) { 0070 mRunningAnimatedImages.erase(it); 0071 } 0072 } 0073 0074 #include "moc_emoticonitemdelegate.cpp"