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"