┌   ┐
54
└   ┘

summaryrefslogtreecommitdiff
path: root/src/panels/information/pixmapviewer.cpp
blob: 4f3f9e82f2c2d49c9825d5159c8507c6e6a53a74 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/*
 * SPDX-FileCopyrightText: 2006 Peter Penz <[email protected]>
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 */

#include "pixmapviewer.h"

#include <KIconLoader>

#include <QImageReader>
#include <QMovie>
#include <QPainter>
#include <QStyle>

PixmapViewer::PixmapViewer(QWidget *parent)
    : QWidget(parent)
    , m_animatedImage(nullptr)
    , m_sizeHint()
    , m_hasAnimatedImage(false)
{
    setMinimumWidth(KIconLoader::SizeEnormous);
    setMinimumHeight(KIconLoader::SizeEnormous);
}

PixmapViewer::~PixmapViewer()
{
}

void PixmapViewer::setPixmap(const QPixmap &pixmap)
{
    if (pixmap.isNull()) {
        return;
    }

    m_pixmap = pixmap;

    // Avoid flicker with static pixmap if an animated image is running
    if (m_animatedImage && m_animatedImage->state() == QMovie::Running) {
        return;
    }

    update();

    if (m_hasAnimatedImage) {
        // If there is no transition animation but an animatedImage
        // and it is not already running, start animating now
        if (m_animatedImage->state() != QMovie::Running) {
            m_animatedImage->start();
        }
    }
}

void PixmapViewer::setSizeHint(const QSize &size)
{
    if (m_animatedImage && size != m_sizeHint) {
        m_animatedImage->setScaledSize(QSize());
        m_animatedImage->stop();
    }

    m_sizeHint = size;
    updateGeometry();
}

QSize PixmapViewer::sizeHint() const
{
    return m_sizeHint;
}

void PixmapViewer::setAnimatedImageFileName(const QString &fileName)
{
    if (!m_animatedImage) {
        m_animatedImage = new QMovie(this);
        connect(m_animatedImage, &QMovie::frameChanged, this, &PixmapViewer::updateAnimatedImageFrame);
    }

    if (m_animatedImage->fileName() != fileName) {
        m_animatedImage->setFileName(fileName);
    }

    m_hasAnimatedImage = m_animatedImage->isValid() && (m_animatedImage->frameCount() > 1);
}

QString PixmapViewer::animatedImageFileName() const
{
    if (!m_hasAnimatedImage) {
        return QString();
    }
    return m_animatedImage->fileName();
}

void PixmapViewer::paintEvent(QPaintEvent *event)
{
    QWidget::paintEvent(event);

    QPainter painter(this);

    if (!m_pixmap.isNull()) {
        style()->drawItemPixmap(&painter, rect(), Qt::AlignCenter, m_pixmap);
    }
}

void PixmapViewer::updateAnimatedImageFrame()
{
    Q_ASSERT(m_animatedImage);

    m_pixmap = m_animatedImage->currentPixmap();
    const auto physicalSize = m_sizeHint * devicePixelRatio();
    if (m_pixmap.width() > physicalSize.width() || m_pixmap.height() > physicalSize.height()) {
        m_pixmap = m_pixmap.scaled(physicalSize, Qt::KeepAspectRatio);
        m_animatedImage->setScaledSize(m_pixmap.size());
    }
    m_pixmap.setDevicePixelRatio(devicePixelRatio());
    update();
}

void PixmapViewer::stopAnimatedImage()
{
    if (m_hasAnimatedImage) {
        m_animatedImage->stop();
        m_hasAnimatedImage = false;
        delete m_animatedImage;
        m_animatedImage = nullptr;
    }
}

bool PixmapViewer::isAnimatedMimeType(const QString &mimeType)
{
    const QList<QByteArray> imageFormats = QImageReader::imageFormatsForMimeType(mimeType.toUtf8());
    return std::any_of(imageFormats.begin(), imageFormats.end(), [](const QByteArray &format) {
        return QMovie::supportedFormats().contains(format);
    });
}

#include "moc_pixmapviewer.cpp"