[vlc-devel] [PATCH 8/8] qt, qml: provide RoundImage implementation from cpp
Prince Gupta
guptaprince8832 at gmail.com
Wed Apr 21 10:12:04 UTC 2021
previously RoundImage was implemented in QML using Opacitymask which was
slow, new implementation done in cpp using QQuickPaintedItem is around ~5x faster
---
modules/gui/qt/Makefile.am | 3 +-
modules/gui/qt/maininterface/mainui.cpp | 5 +
.../qt/medialibrary/qml/ArtistTopBanner.qml | 4 +-
.../qml/MusicAlbumsGridExpandDelegate.qml | 5 +-
.../medialibrary/qml/MusicArtistsAlbums.qml | 4 +-
.../medialibrary/qml/VideoInfoExpandPanel.qml | 5 +-
modules/gui/qt/vlc.qrc | 1 -
modules/gui/qt/widgets/native/roundimage.cpp | 324 ++++++++++++++++++
modules/gui/qt/widgets/native/roundimage.hpp | 139 ++++++++
modules/gui/qt/widgets/qml/GridItem.qml | 1 -
modules/gui/qt/widgets/qml/MediaCover.qml | 5 +-
modules/gui/qt/widgets/qml/RoundImage.qml | 56 ---
modules/gui/qt/widgets/qml/TableColumns.qml | 1 -
13 files changed, 483 insertions(+), 70 deletions(-)
create mode 100644 modules/gui/qt/widgets/native/roundimage.cpp
create mode 100644 modules/gui/qt/widgets/native/roundimage.hpp
delete mode 100644 modules/gui/qt/widgets/qml/RoundImage.qml
diff --git a/modules/gui/qt/Makefile.am b/modules/gui/qt/Makefile.am
index 49d3ae6aa8..1b9b513b38 100644
--- a/modules/gui/qt/Makefile.am
+++ b/modules/gui/qt/Makefile.am
@@ -254,6 +254,7 @@ libqt_plugin_la_SOURCES = \
gui/qt/widgets/native/interface_widgets.hpp \
gui/qt/widgets/native/qvlcframe.cpp \
gui/qt/widgets/native/qvlcframe.hpp \
+ gui/qt/widgets/native/roundimage.cpp gui/qt/widgets/native/roundimage.hpp \
gui/qt/widgets/native/searchlineedit.cpp gui/qt/widgets/native/searchlineedit.hpp
if HAVE_WIN32
libqt_plugin_la_SOURCES += \
@@ -392,6 +393,7 @@ nodist_libqt_plugin_la_SOURCES = \
gui/qt/widgets/native/animators.moc.cpp \
gui/qt/widgets/native/customwidgets.moc.cpp \
gui/qt/widgets/native/interface_widgets.moc.cpp \
+ gui/qt/widgets/native/roundimage.moc.cpp \
gui/qt/widgets/native/searchlineedit.moc.cpp
if HAVE_WIN32
@@ -787,7 +789,6 @@ libqt_plugin_la_QML = \
gui/qt/widgets/qml/NavigableRow.qml \
gui/qt/widgets/qml/PlayCover.qml \
gui/qt/widgets/qml/RoundButton.qml \
- gui/qt/widgets/qml/RoundImage.qml \
gui/qt/widgets/qml/ScanProgressBar.qml \
gui/qt/widgets/qml/ScrollingText.qml \
gui/qt/widgets/qml/SearchBox.qml \
diff --git a/modules/gui/qt/maininterface/mainui.cpp b/modules/gui/qt/maininterface/mainui.cpp
index 0d792d4e59..6aabf3ab90 100644
--- a/modules/gui/qt/maininterface/mainui.cpp
+++ b/modules/gui/qt/maininterface/mainui.cpp
@@ -50,6 +50,8 @@
#include "menus/qml_menu_wrapper.hpp"
+#include "widgets/native/roundimage.hpp"
+
#include "videosurface.hpp"
#include <QQuickWindow>
@@ -257,6 +259,9 @@ void MainUI::registerQMLTypes()
qmlRegisterType<PlaylistContextMenu>( "org.videolan.vlc", 0, 1, "PlaylistContextMenu" );
qmlRegisterType<SortFilterProxyModel>( "org.videolan.vlc", 0, 1, "SortFilterProxyModel" );
+ // Custom controls
+ qmlRegisterType<RoundImage>( "org.videolan.controls", 0, 1, "RoundImage" );
+
qRegisterMetaType<QList<QQmlError>>("QList<QQmlError>");
}
diff --git a/modules/gui/qt/medialibrary/qml/ArtistTopBanner.qml b/modules/gui/qt/medialibrary/qml/ArtistTopBanner.qml
index 367c8f2323..9e45675721 100644
--- a/modules/gui/qt/medialibrary/qml/ArtistTopBanner.qml
+++ b/modules/gui/qt/medialibrary/qml/ArtistTopBanner.qml
@@ -22,6 +22,7 @@ import QtQml.Models 2.11
import QtGraphicalEffects 1.0
import org.videolan.medialib 0.1
+import org.videolan.controls 0.1
import "qrc:///widgets/" as Widgets
import "qrc:///style/"
@@ -73,12 +74,11 @@ Widgets.NavigableFocusScope {
Layout.preferredHeight: VLCStyle.cover_normal
Layout.preferredWidth: VLCStyle.cover_normal
- Widgets.RoundImage {
+ RoundImage {
source: artist.cover || VLCStyle.noArtArtist
height: VLCStyle.cover_normal
width: VLCStyle.cover_normal
radius: VLCStyle.cover_normal
-
}
Rectangle {
diff --git a/modules/gui/qt/medialibrary/qml/MusicAlbumsGridExpandDelegate.qml b/modules/gui/qt/medialibrary/qml/MusicAlbumsGridExpandDelegate.qml
index f974b740f3..7fa67ab541 100644
--- a/modules/gui/qt/medialibrary/qml/MusicAlbumsGridExpandDelegate.qml
+++ b/modules/gui/qt/medialibrary/qml/MusicAlbumsGridExpandDelegate.qml
@@ -21,6 +21,7 @@ import QtQuick.Layouts 1.3
import QtQml.Models 2.11
import org.videolan.medialib 0.1
+import org.videolan.controls 0.1
import "qrc:///widgets/" as Widgets
import "qrc:///util/Helpers.js" as Helpers
@@ -89,9 +90,9 @@ Widgets.NavigableFocusScope {
height: VLCStyle.expandCover_music_height
width: VLCStyle.expandCover_music_width
- Widgets.RoundImage {
+ RoundImage {
id: expand_cover_id
- asynchronous: true
+
height: VLCStyle.expandCover_music_height
width: VLCStyle.expandCover_music_width
radius: VLCStyle.expandCover_music_radius
diff --git a/modules/gui/qt/medialibrary/qml/MusicArtistsAlbums.qml b/modules/gui/qt/medialibrary/qml/MusicArtistsAlbums.qml
index 33b3b141d4..a6237e04af 100644
--- a/modules/gui/qt/medialibrary/qml/MusicArtistsAlbums.qml
+++ b/modules/gui/qt/medialibrary/qml/MusicArtistsAlbums.qml
@@ -21,6 +21,7 @@ import QtQml.Models 2.2
import QtQuick.Layouts 1.3
import org.videolan.medialib 0.1
+import org.videolan.controls 0.1
import "qrc:///util/" as Util
import "qrc:///util/Helpers.js" as Helpers
@@ -161,12 +162,11 @@ Widgets.NavigableFocusScope {
bottomMargin: VLCStyle.margin_xsmall
}
- Widgets.RoundImage {
+ RoundImage {
source: model.cover || VLCStyle.noArtArtistSmall
height: VLCStyle.play_cover_small
width: VLCStyle.play_cover_small
radius: VLCStyle.play_cover_small
- mipmap: true
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
diff --git a/modules/gui/qt/medialibrary/qml/VideoInfoExpandPanel.qml b/modules/gui/qt/medialibrary/qml/VideoInfoExpandPanel.qml
index 59314c6b3a..c8afb409cc 100644
--- a/modules/gui/qt/medialibrary/qml/VideoInfoExpandPanel.qml
+++ b/modules/gui/qt/medialibrary/qml/VideoInfoExpandPanel.qml
@@ -21,6 +21,7 @@ import QtQml.Models 2.11
import QtQuick.Layouts 1.3
import org.videolan.medialib 0.1
+import org.videolan.controls 0.1
import "qrc:///widgets/" as Widgets
import "qrc:///util/KeyHelper.js" as KeyHelper
@@ -94,14 +95,12 @@ Widgets.NavigableFocusScope {
width: VLCStyle.gridCover_video_width
/* A bigger cover for the album */
- Widgets.RoundImage {
+ RoundImage {
id: expand_cover_id
anchors.fill: parent
- asynchronous: true
source: model.thumbnail || VLCStyle.noArtCover
sourceSize: Qt.size(width, height)
- fillMode: Image.PreserveAspectFit
radius: VLCStyle.gridCover_radius
}
diff --git a/modules/gui/qt/vlc.qrc b/modules/gui/qt/vlc.qrc
index 93f129a807..f86c76a8ba 100644
--- a/modules/gui/qt/vlc.qrc
+++ b/modules/gui/qt/vlc.qrc
@@ -223,7 +223,6 @@
<file alias="RoundButton.qml">widgets/qml/RoundButton.qml</file>
<file alias="LabelSeparator.qml">widgets/qml/LabelSeparator.qml</file>
<file alias="ContextButton.qml">widgets/qml/ContextButton.qml</file>
- <file alias="RoundImage.qml">widgets/qml/RoundImage.qml</file>
<file alias="VideoQualityLabels.qml">widgets/qml/VideoQualityLabels.qml</file>
<file alias="VideoProgressBar.qml">widgets/qml/VideoProgressBar.qml</file>
<file alias="NavigableCol.qml">widgets/qml/NavigableCol.qml</file>
diff --git a/modules/gui/qt/widgets/native/roundimage.cpp b/modules/gui/qt/widgets/native/roundimage.cpp
new file mode 100644
index 0000000000..49fa1946d2
--- /dev/null
+++ b/modules/gui/qt/widgets/native/roundimage.cpp
@@ -0,0 +1,324 @@
+/*****************************************************************************
+ * roundimage.cpp: Custom widgets
+ ****************************************************************************
+ * Copyright (C) 2021 the VideoLAN team
+ *
+ * Authors: Prince Gupta <guptaprince8832 at gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "roundimage.hpp"
+
+#include <QBrush>
+#include <QImage>
+#include <QPainterPath>
+#include <QPen>
+#include <QQuickWindow>
+#include <QSvgRenderer>
+#include <QGuiApplication>
+
+#ifdef QT_NETWORK_LIB
+#include <QNetworkAccessManager>
+#include <QNetworkReply>
+#include <QNetworkRequest>
+#endif
+
+namespace
+{
+ QString getPath(const QUrl &url)
+ {
+ QString path = url.isLocalFile() ? url.toLocalFile() : url.toString();
+ if (path.startsWith("qrc:///"))
+ path.replace(0, strlen("qrc:///"), ":/");
+ return path;
+ }
+
+ QByteArray readFile(const QUrl &url)
+ {
+#ifdef QT_NETWORK_LIB
+ if (url.scheme() == "http" || url.scheme() == "https")
+ {
+ QNetworkAccessManager networkMgr;
+ networkMgr.setRedirectPolicy(QNetworkRequest::NoLessSafeRedirectPolicy);
+ auto reply = networkMgr.get(QNetworkRequest(url));
+ QEventLoop loop;
+ QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
+ loop.exec();
+ return reply->readAll();
+ }
+#endif
+
+ QByteArray data;
+ QString path = getPath(url);
+ QFile file(path);
+ if (file.open(QIODevice::ReadOnly))
+ data = file.readAll();
+ return data;
+ }
+}
+
+RoundImage::RoundImage(QQuickItem *parent) : QQuickPaintedItem {parent}
+{
+ if (window() || qGuiApp)
+ setDPR(window() ? window()->devicePixelRatio() : qGuiApp->devicePixelRatio());
+
+ connect(this, &QQuickItem::heightChanged, this, &RoundImage::regenerateRoundImage);
+ connect(this, &QQuickItem::widthChanged, this, &RoundImage::regenerateRoundImage);
+}
+
+void RoundImage::paint(QPainter *painter)
+{
+ painter->drawImage(QPointF {0., 0.}, m_roundImage, m_roundImage.rect());
+}
+
+void RoundImage::classBegin()
+{
+ QQuickPaintedItem::classBegin();
+
+ m_isComponentComplete = false;
+}
+
+void RoundImage::componentComplete()
+{
+ QQuickPaintedItem::componentComplete();
+
+ Q_ASSERT(!m_isComponentComplete); // classBegin is not called?
+ m_isComponentComplete = true;
+ if (!m_source.isEmpty())
+ updateSource();
+}
+
+QUrl RoundImage::source() const
+{
+ return m_source;
+}
+
+qreal RoundImage::radius() const
+{
+ return m_radius;
+}
+
+QSizeF RoundImage::sourceSize() const
+{
+ return m_sourceSize;
+}
+
+void RoundImage::setSource(QUrl source)
+{
+ if (m_source == source)
+ return;
+
+ m_source = source;
+ emit sourceChanged(m_source);
+ updateSource();
+}
+
+void RoundImage::setRadius(qreal radius)
+{
+ if (m_radius == radius)
+ return;
+
+ m_radius = radius;
+ emit radiusChanged(m_radius);
+ regenerateRoundImage();
+}
+
+void RoundImage::setSourceSize(QSizeF sourceSize)
+{
+ if (m_sourceSize == sourceSize)
+ return;
+
+ m_sourceSize = sourceSize;
+ emit sourceSizeChanged(m_sourceSize);
+ updateSource();
+}
+
+void RoundImage::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &value)
+{
+ if (change == QQuickItem::ItemDevicePixelRatioHasChanged)
+ setDPR(value.realValue);
+
+ QQuickPaintedItem::itemChange(change, value);
+}
+
+void RoundImage::setDPR(const qreal value)
+{
+ if (m_dpr == value)
+ return;
+
+ m_dpr = value;
+ if (m_sourceSize.isValid())
+ updateSource(); // "effectiveSourceSize" is changed
+ else
+ regenerateRoundImage();
+}
+
+void RoundImage::updateSource()
+{
+ if (!m_isComponentComplete)
+ return;
+
+ const QSizeF effectiveSourceSize = m_sourceSize.isValid() ? m_sourceSize * m_dpr : QSize {};
+ m_loader.reset(new Loader({m_source, effectiveSourceSize}));
+ connect(m_loader.get(), &BaseAsyncTask::result, this, [this]()
+ {
+ m_sourceImage = m_loader->takeResult();
+ m_loader.reset();
+
+ regenerateRoundImage();
+ });
+
+ m_loader->start(*QThreadPool::globalInstance());
+}
+
+void RoundImage::regenerateRoundImage()
+{
+ if (!m_isComponentComplete
+ || m_enqueuedGeneration
+ || m_loader /* when loader ends it will call regenerateRoundImage */)
+ return;
+
+ // use Qt::QueuedConnection to delay generation, so that dependent properties
+ // subsequent updates can be merged, f.e when VLCStyle.scale changes
+ m_enqueuedGeneration = true;
+
+ QMetaObject::invokeMethod(this, [this] ()
+ {
+ m_enqueuedGeneration = false;
+
+ // Image is generated in size factor of `m_dpr` to avoid scaling artefacts when
+ // generated image is set with device pixel ratio
+ m_roundImageGenerator.reset(new RoundImageGenerator({width() * m_dpr, height() * m_dpr, radius() * m_dpr, m_sourceImage}));
+ connect(m_roundImageGenerator.get(), &BaseAsyncTask::result, this, [this]()
+ {
+ m_roundImage = m_roundImageGenerator->takeResult();
+ m_roundImage.setDevicePixelRatio(m_dpr);
+ m_roundImageGenerator.reset();
+
+ update();
+ });
+
+ m_roundImageGenerator->start(*QThreadPool::globalInstance());
+ }, Qt::QueuedConnection);
+}
+
+RoundImage::Loader::Loader(const Params ¶ms) : params {params} {}
+
+RoundImage::ImagePtr RoundImage::Loader::execute()
+{
+ return Image::getImage(params.source, params.sourceSize);
+}
+
+RoundImage::RoundImageGenerator::RoundImageGenerator(const RoundImage::RoundImageGenerator::Params ¶ms) : params {params} {}
+
+QImage RoundImage::RoundImageGenerator::execute()
+{
+ if (params.width <= 0 || params.height <= 0)
+ return {};
+
+ QImage target(params.width, params.height, QImage::Format_ARGB32);
+ if (target.isNull())
+ return target;
+
+ target.fill(Qt::transparent);
+ if (Q_UNLIKELY(!params.image))
+ return target;
+
+ QPainter painter;
+ painter.begin(&target);
+ painter.setRenderHint(QPainter::Antialiasing, true);
+ painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
+
+ QPainterPath path;
+ path.addRoundedRect(0, 0, params.width, params.height, params.radius, params.radius);
+ painter.setClipPath(path);
+
+ params.image->paint(&painter, {params.width, params.height});
+ painter.end();
+
+ return target;
+}
+
+std::shared_ptr<RoundImage::Image> RoundImage::Image::getImage(const QUrl &source, const QSizeF &sourceSize)
+{
+ class QtImage : public Image
+ {
+ public:
+ QtImage(const QByteArray &data, const QSizeF &sourceSize)
+ {
+ m_image.loadFromData(data);
+
+ if (sourceSize.isValid())
+ m_image = m_image.scaled(sourceSize.toSize(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
+ }
+
+ void paint(QPainter *painter, const QSizeF &size) override
+ {
+ if (m_image.isNull() || !painter || !size.isValid())
+ return;
+
+ auto image = m_image;
+
+ // do PreserveAspectCrop
+ const qreal ratio = std::max(qreal(size.width()) / image.width(), qreal(size.height()) / image.height());
+ if (ratio != 0.0)
+ image = image.scaled(qRound(image.width() * ratio), qRound(image.height() * ratio),
+ Qt::IgnoreAspectRatio, // aspect ratio handled manually by using `ratio`
+ Qt::SmoothTransformation);
+
+ const QPointF alignedCenteredTopLeft {(size.width() - image.width()) / 2, (size.height() - image.height()) / 2};
+ painter->drawImage(alignedCenteredTopLeft, image);
+ }
+
+ private:
+ QImage m_image;
+ };
+
+ class SVGImage : public Image
+ {
+ public:
+ SVGImage(const QByteArray &data)
+ {
+ m_svg.load(data);
+ }
+
+ void paint(QPainter *painter, const QSizeF &size) override
+ {
+ if (!m_svg.isValid() || !painter || !size.isValid())
+ return;
+
+ // do PreserveAspectCrop
+ const QSizeF defaultSize = m_svg.defaultSize();
+ const qreal ratio = std::max(size.width() / defaultSize.width(), size.height() / defaultSize.height());
+ const QSizeF targetSize = defaultSize * ratio;
+ const QPointF alignedCenteredTopLeft {(size.width() - targetSize.width()) / 2., (size.height() - targetSize.height()) / 2.};
+ m_svg.render(painter, QRectF {alignedCenteredTopLeft, targetSize});
+ }
+
+ private:
+ QSvgRenderer m_svg;
+ };
+
+ const QByteArray data = readFile(source);
+ if (source.toString().endsWith(".svg"))
+ return std::make_shared<SVGImage>(data);
+ return std::make_shared<QtImage>(data, sourceSize);
+}
diff --git a/modules/gui/qt/widgets/native/roundimage.hpp b/modules/gui/qt/widgets/native/roundimage.hpp
new file mode 100644
index 0000000000..db97dd4996
--- /dev/null
+++ b/modules/gui/qt/widgets/native/roundimage.hpp
@@ -0,0 +1,139 @@
+/*****************************************************************************
+ * roundimage.hpp: Custom widgets
+ ****************************************************************************
+ * Copyright (C) 2021 the VideoLAN team
+ *
+ * Authors: Prince Gupta <guptaprince8832 at gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifndef VLC_QT_ROUNDIMAGE_HPP
+#define VLC_QT_ROUNDIMAGE_HPP
+
+#include "qt.hpp"
+
+#include "util/asynctask.hpp"
+
+#include <QPixmap>
+#include <QPainter>
+#include <QQuickPaintedItem>
+#include <QUrl>
+
+class RoundImage : public QQuickPaintedItem
+{
+ Q_OBJECT
+
+ // url of the image
+ Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
+
+ // sets the maximum number of pixels stored for the loaded image so that large images do not use more memory than necessary
+ Q_PROPERTY(QSizeF sourceSize READ sourceSize WRITE setSourceSize NOTIFY sourceSizeChanged)
+
+ Q_PROPERTY(qreal radius READ radius WRITE setRadius NOTIFY radiusChanged)
+
+public:
+ RoundImage(QQuickItem *parent = nullptr);
+
+ void paint(QPainter *painter) override;
+
+ void classBegin() override;
+ void componentComplete() override;
+
+ QUrl source() const;
+ qreal radius() const;
+ QSizeF sourceSize() const;
+
+public slots:
+ void setSource(QUrl source);
+ void setRadius(qreal radius);
+ void setSourceSize(QSizeF sourceSize);
+
+signals:
+ void sourceChanged(QUrl source);
+ void radiusChanged(int radius);
+ void sourceSizeChanged(QSizeF sourceSize);
+
+protected:
+ void itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &value) override;
+
+private:
+ class Image
+ {
+ public:
+ static std::shared_ptr<Image> getImage(const QUrl &source, const QSizeF &sourceSize);
+ virtual ~Image() = default;
+
+ // must be reentrant
+ virtual void paint(QPainter *painter, const QSizeF &size) = 0;
+ };
+
+ using ImagePtr = std::shared_ptr<Image>;
+
+ class Loader : public AsyncTask<ImagePtr>
+ {
+ public:
+ struct Params
+ {
+ QUrl source;
+ QSizeF sourceSize;
+ };
+
+ Loader(const Params ¶ms);
+
+ ImagePtr execute();
+
+ private:
+ const Params params;
+ };
+
+ class RoundImageGenerator : public AsyncTask<QImage>
+ {
+ public:
+ struct Params
+ {
+ qreal width;
+ qreal height;
+ qreal radius;
+ ImagePtr image;
+ };
+
+ RoundImageGenerator(const Params ¶ms);
+
+ QImage execute();
+
+ private:
+ const Params params;
+ };
+
+ void setDPR(qreal value);
+ void updateSource();
+ void regenerateRoundImage();
+
+ QUrl m_source;
+ ImagePtr m_sourceImage;
+ qreal m_radius = 0.0;
+ QSizeF m_sourceSize;
+ qreal m_dpr = 1.0; // device pixel ratio
+ QImage m_roundImage;
+ TaskHandle<Loader> m_loader {};
+ TaskHandle<RoundImageGenerator> m_roundImageGenerator {};
+
+ bool m_enqueuedGeneration = false;
+ bool m_isComponentComplete = true;
+};
+
+#endif
+
diff --git a/modules/gui/qt/widgets/qml/GridItem.qml b/modules/gui/qt/widgets/qml/GridItem.qml
index ec8d3972d8..48d2f1a822 100644
--- a/modules/gui/qt/widgets/qml/GridItem.qml
+++ b/modules/gui/qt/widgets/qml/GridItem.qml
@@ -249,7 +249,6 @@ FocusScope {
height: pictureHeight
playCoverVisible: root.highlighted
onPlayIconClicked: root.playClicked()
- clip: true
radius: VLCStyle.gridCover_radius
}
diff --git a/modules/gui/qt/widgets/qml/MediaCover.qml b/modules/gui/qt/widgets/qml/MediaCover.qml
index 1a9d9517e3..7b92d900c5 100644
--- a/modules/gui/qt/widgets/qml/MediaCover.qml
+++ b/modules/gui/qt/widgets/qml/MediaCover.qml
@@ -22,7 +22,9 @@ import QtQuick.Controls 2.4
import "qrc:///widgets/" as Widgets
import "qrc:///style/"
-Widgets.RoundImage {
+import org.videolan.controls 0.1
+
+RoundImage {
id: root
property alias playCoverOpacity: playCoverLoader.opacity
@@ -35,6 +37,7 @@ Widgets.RoundImage {
height: VLCStyle.listAlbumCover_height
width: VLCStyle.listAlbumCover_width
+ sourceSize: Qt.size(width, height)
Loader {
id: overlay
diff --git a/modules/gui/qt/widgets/qml/RoundImage.qml b/modules/gui/qt/widgets/qml/RoundImage.qml
deleted file mode 100644
index 4d9567cfc3..0000000000
--- a/modules/gui/qt/widgets/qml/RoundImage.qml
+++ /dev/null
@@ -1,56 +0,0 @@
-/*****************************************************************************
- * Copyright (C) 2019 VLC authors and VideoLAN
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * ( at your option ) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
- *****************************************************************************/
-import QtQuick 2.11
-import QtQuick.Controls 2.4
-import QtGraphicalEffects 1.0
-
-import "qrc:///style/"
-
-Item {
- id: root
-
- property real radius: 3
- property alias asynchronous: cover.asynchronous
- property alias fillMode: cover.fillMode
- property alias mipmap: cover.mipmap
- property alias paintedHeight: cover.paintedHeight
- property alias paintedWidth: cover.paintedWidth
- property alias source: cover.source
- property alias sourceSize: cover.sourceSize
- property alias status: cover.status
- property alias horizontalAlignment: cover.horizontalAlignment
- property alias verticalAlignment: cover.verticalAlignment
-
- Image {
- id: cover
-
- anchors.fill: parent
- asynchronous: true
- fillMode: Image.PreserveAspectCrop
- sourceSize: Qt.size(width, height)
- layer.enabled: true
- layer.effect: OpacityMask {
- maskSource: Rectangle {
- radius: root.radius
- width: root.width
- height: root.height
- visible: false
- }
- }
- }
-}
diff --git a/modules/gui/qt/widgets/qml/TableColumns.qml b/modules/gui/qt/widgets/qml/TableColumns.qml
index cf08caa897..71d46b188e 100644
--- a/modules/gui/qt/widgets/qml/TableColumns.qml
+++ b/modules/gui/qt/widgets/qml/TableColumns.qml
@@ -59,7 +59,6 @@ Item {
anchors.fill: parent
source: (rowModel ? (root.showTitleText ? rowModel.cover : rowModel[model.criteria]) : VLCStyle.noArtCover) || VLCStyle.noArtCover
- mipmap: true // this widget can down scale the source a lot, so for better visuals we use mipmap
playCoverVisible: currentlyFocused || containsMouse
playIconSize: VLCStyle.play_cover_small
onPlayIconClicked: medialib.addAndPlay( rowModel.id )
--
2.27.0
More information about the vlc-devel
mailing list