diff options
author | Christian Ehrlicher <[email protected]> | 2024-09-19 20:38:40 +0200 |
---|---|---|
committer | Christian Ehrlicher <[email protected]> | 2024-10-11 10:54:42 +0200 |
commit | ff9818135db28e287e7818defd9c1a9acdebacdc (patch) | |
tree | d504ef8fce41ccea3642e330e6b17b499ad83ca0 | |
parent | 618b1faf37ddda4cdeff6934f5af7e699c9aad63 (diff) |
Widgets/Style: add QCachedPainter
Add a helper class QCachedPainter to simplify the usage of QPixmapCache.
Task-number: QTBUG-129680
Change-Id: Id6835ec05af2fff3fc43c36b5fedaec598cb580b
Reviewed-by: Axel Spoerl <[email protected]>
-rw-r--r-- | src/widgets/styles/qcommonstyle.cpp | 1 | ||||
-rw-r--r-- | src/widgets/styles/qstyle.cpp | 49 | ||||
-rw-r--r-- | src/widgets/styles/qstyle_p.h | 38 |
3 files changed, 88 insertions, 0 deletions
diff --git a/src/widgets/styles/qcommonstyle.cpp b/src/widgets/styles/qcommonstyle.cpp index 701dc2c45da..24968128da3 100644 --- a/src/widgets/styles/qcommonstyle.cpp +++ b/src/widgets/styles/qcommonstyle.cpp @@ -6233,6 +6233,7 @@ int QCommonStyle::layoutSpacing(QSizePolicy::ControlType /* control1 */, QSizePo void QCommonStyle::polish(QPalette &pal) { QStyle::polish(pal); + QCachedPainter::cleanupPixmapCache(); } /*! diff --git a/src/widgets/styles/qstyle.cpp b/src/widgets/styles/qstyle.cpp index 32a994f1114..183b0cbe0c9 100644 --- a/src/widgets/styles/qstyle.cpp +++ b/src/widgets/styles/qstyle.cpp @@ -7,8 +7,10 @@ #include "qwidget.h" #include "qbitmap.h" #include "qpixmapcache.h" +#include "qset.h" #include "qstyleoption.h" #include "private/qstyle_p.h" +#include "private/qstylehelper_p.h" #include "private/qguiapplication_p.h" #include <qpa/qplatformtheme.h> #ifndef QT_NO_DEBUG @@ -2422,6 +2424,53 @@ bool QStylePrivate::useFullScreenForPopup() return theme && theme->themeHint(QPlatformTheme::UseFullScreenForPopupMenu).toBool(); } +// +// QCachedPainter +QSet<QString> QCachedPainter::s_pixmapCacheKeys; +QCachedPainter::QCachedPainter(QPainter *painter, const QString &cachePrefix, + const QStyleOption *option, QSize size, QRect paintRect) + : m_painter(painter) + , m_option(option) + , m_paintRect(paintRect) +{ + const auto sz = size.isNull() ? option->rect.size() : size; + const qreal dpr = QStyleHelper::getDpr(painter); + m_pixmapName = QStyleHelper::uniqueName(cachePrefix, option, sz, dpr); + m_alreadyCached = QPixmapCache::find(m_pixmapName, &m_pixmap); + if (!m_alreadyCached) { + m_pixmap = styleCachePixmap(sz, dpr); + m_pixmapPainter = std::make_unique<QPainter>(&m_pixmap); + m_pixmapPainter->setRenderHint(QPainter::Antialiasing); + s_pixmapCacheKeys += m_pixmapName; + } +} + +QCachedPainter::~QCachedPainter() +{ + finish(); + if (!m_alreadyCached) + QPixmapCache::insert(m_pixmapName, m_pixmap); +} + +void QCachedPainter::finish() +{ + m_pixmapPainter.reset(); + if (!m_pixmapDrawn) { + m_pixmapDrawn = true; + if (m_paintRect.isNull()) + m_painter->drawPixmap(m_option->rect.topLeft(), m_pixmap); + else + m_painter->drawPixmap(m_paintRect, m_pixmap); + } +} + +void QCachedPainter::cleanupPixmapCache() +{ + for (const auto &key : s_pixmapCacheKeys) + QPixmapCache::remove(key); + s_pixmapCacheKeys.clear(); +} + QT_END_NAMESPACE #include "moc_qstyle.cpp" diff --git a/src/widgets/styles/qstyle_p.h b/src/widgets/styles/qstyle_p.h index d04dd491520..0412aca209b 100644 --- a/src/widgets/styles/qstyle_p.h +++ b/src/widgets/styles/qstyle_p.h @@ -72,6 +72,44 @@ inline QPixmap styleCachePixmap(const QSize &size, qreal pixelRatio) } \ } +// small helper to read out the pixmap to paint from QPixmapCache or re-draw +// it and put it into the QPixmapCache for later usage +class Q_WIDGETS_EXPORT QCachedPainter +{ +public: + QCachedPainter(QPainter *painter, const QString &cachePrefix, + const QStyleOption *option, QSize size = {}, QRect paintRect = {}); + ~QCachedPainter(); + void finish(); + bool needsPainting() const + { + return !m_alreadyCached; + } + QPainter *operator->() + { + return painter(); + } + QPainter *painter() + { + Q_ASSERT_X(m_pixmapPainter, "painter()", "Must only be called when painting on a pixmap to cache"); + return m_pixmapPainter.get(); + } + + // clean pixmap cache from all cached pixmaps (e.g. due to palette change) + // to make sure the widgets are painted correctly afterwards + static void cleanupPixmapCache(); +private: + QPainter *m_painter = nullptr; + const QStyleOption *m_option = nullptr; + std::unique_ptr<QPainter> m_pixmapPainter; + QString m_pixmapName; + QPixmap m_pixmap; + QRect m_paintRect; + bool m_alreadyCached; + bool m_pixmapDrawn = false; + static QSet<QString> s_pixmapCacheKeys; +}; + QT_END_NAMESPACE #endif //QSTYLE_P_H |