From 1464118b67a030d290eb14e7c6612202273e1366 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Mon, 7 Sep 2015 15:09:21 +0200 Subject: QIcon: add a hook in the engine so a non null QIconEngine can still be a null icon Implement it in the QIconLoader We have to change detach() because some code does: icon = QIcon::fromTheme("foobar"); if (icon.isNull()) icon.addPixmap(...); so addPixmap and addFile have to work on a null QIcon by resetting the iconEngine. Change-Id: I07719bef93930cf4692384a8c64e21a97dcce25c Reviewed-by: David Faure --- src/gui/image/qicon.cpp | 15 +++++++++------ src/gui/image/qiconengine.cpp | 17 +++++++++++++++++ src/gui/image/qiconengine.h | 3 ++- src/gui/image/qiconloader.cpp | 5 +++++ 4 files changed, 33 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp index 7a59adffb8..ef039f0678 100644 --- a/src/gui/image/qicon.cpp +++ b/src/gui/image/qicon.cpp @@ -918,7 +918,7 @@ void QIcon::paint(QPainter *painter, const QRect &rect, Qt::Alignment alignment, */ bool QIcon::isNull() const { - return !d; + return !d || d->engine->isNull(); } /*!\internal @@ -933,7 +933,12 @@ bool QIcon::isDetached() const void QIcon::detach() { if (d) { - if (d->ref.load() != 1) { + if (d->engine->isNull()) { + if (!d->ref.deref()) + delete d; + d = 0; + return; + } else if (d->ref.load() != 1) { QIconPrivate *x = new QIconPrivate; x->engine = d->engine->clone(); if (!d->ref.deref()) @@ -957,11 +962,10 @@ void QIcon::addPixmap(const QPixmap &pixmap, Mode mode, State state) { if (pixmap.isNull()) return; + detach(); if (!d) { d = new QIconPrivate; d->engine = new QPixmapIconEngine; - } else { - detach(); } d->engine->addPixmap(pixmap, mode, state); } @@ -1001,6 +1005,7 @@ void QIcon::addFile(const QString &fileName, const QSize &size, Mode mode, State { if (fileName.isEmpty()) return; + detach(); if (!d) { #ifndef QT_NO_LIBRARY QFileInfo info(fileName); @@ -1023,8 +1028,6 @@ void QIcon::addFile(const QString &fileName, const QSize &size, Mode mode, State d = new QIconPrivate; d->engine = new QPixmapIconEngine; } - } else { - detach(); } d->engine->addFile(fileName, size, mode, state); diff --git a/src/gui/image/qiconengine.cpp b/src/gui/image/qiconengine.cpp index a25b216432..49a3bead53 100644 --- a/src/gui/image/qiconengine.cpp +++ b/src/gui/image/qiconengine.cpp @@ -143,6 +143,11 @@ void QIconEngine::addFile(const QString &/*fileName*/, const QSize &/*size*/, QI icon, for example when instantiating an icon using QIcon::fromTheme(). + \value IsNullHook Allow to query if this engine represents a null + icon. The \a data argument of the virtual_hook() is a pointer to a + bool that can be set to true if the icon is null. This enum value + was added in Qt 5.7. + \sa virtual_hook() */ @@ -276,4 +281,16 @@ QString QIconEngine::iconName() const return name; } +/*! + \since 5.7 + + Returns true if this icon engine represent a null QIcon. + */ +bool QIconEngine::isNull() const +{ + bool isNull = false; + const_cast(this)->virtual_hook(QIconEngine::IsNullHook, &isNull); + return isNull; +} + QT_END_NAMESPACE diff --git a/src/gui/image/qiconengine.h b/src/gui/image/qiconengine.h index 735da863fd..f0ff143b36 100644 --- a/src/gui/image/qiconengine.h +++ b/src/gui/image/qiconengine.h @@ -57,7 +57,7 @@ public: virtual bool read(QDataStream &in); virtual bool write(QDataStream &out) const; - enum IconEngineHook { AvailableSizesHook = 1, IconNameHook }; + enum IconEngineHook { AvailableSizesHook = 1, IconNameHook, IsNullHook }; struct AvailableSizesArgument { @@ -70,6 +70,7 @@ public: QIcon::State state = QIcon::Off) const; virtual QString iconName() const; + bool isNull() const; // ### Qt6 make virtual virtual void virtual_hook(int id, void *data); }; diff --git a/src/gui/image/qiconloader.cpp b/src/gui/image/qiconloader.cpp index 3ead72dfbb..3fd1f57ac4 100644 --- a/src/gui/image/qiconloader.cpp +++ b/src/gui/image/qiconloader.cpp @@ -587,6 +587,11 @@ void QIconLoaderEngine::virtual_hook(int id, void *data) name = m_info.iconName; } break; + case QIconEngine::IsNullHook: + { + *reinterpret_cast(data) = m_info.entries.isEmpty(); + } + break; default: QIconEngine::virtual_hook(id, data); } -- cgit v1.2.3