summary refs log tree commit diff
path: root/src/ui
diff options
context:
space:
mode:
authorNicolas Werner <nicolas.werner@hotmail.de>2022-09-30 03:27:05 +0200
committerNicolas Werner <nicolas.werner@hotmail.de>2022-09-30 03:27:05 +0200
commit88cbac1695292e1dade325ee26ba5c52467d4b75 (patch)
tree275ef197ca81de7d08291f937cf4eca0451e4fcf /src/ui
parentMake clazy happy (diff)
downloadnheko-88cbac1695292e1dade325ee26ba5c52467d4b75.tar.xz
Basic threading support
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/MxcAnimatedImage.cpp47
-rw-r--r--src/ui/MxcAnimatedImage.h31
2 files changed, 47 insertions, 31 deletions
diff --git a/src/ui/MxcAnimatedImage.cpp b/src/ui/MxcAnimatedImage.cpp

index 8ecea7d9..90066fa0 100644 --- a/src/ui/MxcAnimatedImage.cpp +++ b/src/ui/MxcAnimatedImage.cpp
@@ -8,6 +8,7 @@ #include <QDir> #include <QFileInfo> #include <QMimeDatabase> +#include <QMovie> #include <QQuickWindow> #include <QSGImageNode> #include <QStandardPaths> @@ -34,8 +35,12 @@ MxcAnimatedImage::startDownload() QByteArray mimeType = QString::fromStdString(mtx::accessors::mimetype(*event)).toUtf8(); - static const auto formats = QMovie::supportedFormats(); - animatable_ = formats.contains(mimeType.split('/').back()); + static const auto movieFormats = QMovie::supportedFormats(); + QByteArray imageFormat; + const auto imageFormats = QImageReader::imageFormatsForMimeType(mimeType); + if (!imageFormats.isEmpty()) + imageFormat = imageFormats.front(); + animatable_ = movieFormats.contains(imageFormat); animatableChanged(); if (!animatable_) @@ -66,14 +71,14 @@ MxcAnimatedImage::startDownload() QPointer<MxcAnimatedImage> self = this; - auto processBuffer = [this, mimeType, encryptionInfo, self](QIODevice &device) { + auto processBuffer = [this, imageFormat, encryptionInfo, self](QIODevice &device) { if (!self) return; try { if (buffer.isOpen()) { - movie.stop(); - movie.setDevice(nullptr); + frameTimer.stop(); + movie->setDevice(nullptr); buffer.close(); } @@ -92,21 +97,22 @@ MxcAnimatedImage::startDownload() nhlog::net()->error("Failed to setup animated image buffer: {}", e.what()); } - QTimer::singleShot(0, this, [this, mimeType] { + QTimer::singleShot(0, this, [this, imageFormat] { nhlog::ui()->info( "Playing movie with size: {}, {}", buffer.bytesAvailable(), buffer.isOpen()); - movie.setFormat(mimeType); - movie.setDevice(&buffer); + movie->setFormat(imageFormat); + movie->setDevice(&buffer); if (height() != 0 && width() != 0) - movie.setScaledSize(this->size().toSize()); - if (buffer.bytesAvailable() < - 4LL * 1024 * 1024 * 1024) // cache images smaller than 4MB in RAM - movie.setCacheMode(QMovie::CacheAll); + movie->setScaledSize(this->size().toSize()); + + if (movie->supportsAnimation()) + frameTimer.setInterval(movie->nextImageDelay()); + if (play_) - movie.start(); + frameTimer.start(); else - movie.jumpToFrame(0); + movie->jumpToImage(0); emit loadedChanged(); update(); }); @@ -159,9 +165,9 @@ MxcAnimatedImage::geometryChanged(const QRectF &newGeometry, const QRectF &oldGe if (newGeometry.size() != oldGeometry.size()) { if (height() != 0 && width() != 0) { - QSizeF r = movie.scaledSize(); + QSizeF r = movie->scaledSize(); r.scale(newGeometry.size(), Qt::KeepAspectRatio); - movie.setScaledSize(r.toSize()); + movie->setScaledSize(r.toSize()); imageDirty = true; update(); } @@ -184,16 +190,15 @@ MxcAnimatedImage::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeD n->setFlags(QSGNode::OwnedByParent); } - auto img = movie.currentImage(); - n->setSourceRect(img.rect()); - if (!img.isNull()) - n->setTexture(window()->createTextureFromImage(std::move(img))); + n->setSourceRect(currentFrame.rect()); + if (!currentFrame.isNull()) + n->setTexture(window()->createTextureFromImage(currentFrame)); else { delete n; return nullptr; } - QSizeF r = img.size(); + QSizeF r = currentFrame.size(); r.scale(size(), Qt::KeepAspectRatio); n->setRect((width() - r.width()) / 2, (height() - r.height()) / 2, r.width(), r.height()); diff --git a/src/ui/MxcAnimatedImage.h b/src/ui/MxcAnimatedImage.h
index 8891e57e..2b067166 100644 --- a/src/ui/MxcAnimatedImage.h +++ b/src/ui/MxcAnimatedImage.h
@@ -6,7 +6,7 @@ #pragma once #include <QBuffer> -#include <QMovie> +#include <QImageReader> #include <QObject> #include <QQuickItem> @@ -24,10 +24,11 @@ class MxcAnimatedImage : public QQuickItem public: MxcAnimatedImage(QQuickItem *parent = nullptr) : QQuickItem(parent) + , movie(new QImageReader()) { connect(this, &MxcAnimatedImage::eventIdChanged, &MxcAnimatedImage::startDownload); connect(this, &MxcAnimatedImage::roomChanged, &MxcAnimatedImage::startDownload); - connect(&movie, &QMovie::frameChanged, this, &MxcAnimatedImage::newFrame); + connect(&frameTimer, &QTimer::timeout, this, &MxcAnimatedImage::newFrame); setFlag(QQuickItem::ItemHasContents); // setAcceptHoverEvents(true); } @@ -55,7 +56,10 @@ public: { if (play_ != newPlay) { play_ = newPlay; - movie.setPaused(!play_); + if (play_) + frameTimer.start(); + else + frameTimer.stop(); emit playChanged(); } } @@ -73,10 +77,16 @@ signals: private slots: void startDownload(); - void newFrame(int frame) + void newFrame() { - currentFrame = frame; - imageDirty = true; + if (movie->currentImageNumber() > 0 && !movie->canRead() && movie->imageCount() > 1) { + buffer.seek(0); + movie.reset(new QImageReader(movie->device(), movie->format())); + if (height() != 0 && width() != 0) + movie->setScaledSize(this->size().toSize()); + } + movie->read(&currentFrame); + imageDirty = true; update(); } @@ -86,8 +96,9 @@ private: QString filename_; bool animatable_ = false; QBuffer buffer; - QMovie movie; - int currentFrame = 0; - bool imageDirty = true; - bool play_ = true; + std::unique_ptr<QImageReader> movie; + bool imageDirty = true; + bool play_ = true; + QTimer frameTimer; + QImage currentFrame; };