From 68ba5005ce02d251c40a6ad941bb17f064eab878 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Sun, 17 Nov 2024 14:38:29 -0800 Subject: [PATCH] core/icon: ability to specify a fallback or check if an icon exists --- src/core/iconimageprovider.cpp | 21 +++++++++++++++++++-- src/core/iconimageprovider.hpp | 7 ++++++- src/core/qmlglobal.cpp | 12 +++++++++++- src/core/qmlglobal.hpp | 6 ++++++ 4 files changed, 42 insertions(+), 4 deletions(-) diff --git a/src/core/iconimageprovider.cpp b/src/core/iconimageprovider.cpp index f4710fb8..cf24d37d 100644 --- a/src/core/iconimageprovider.cpp +++ b/src/core/iconimageprovider.cpp @@ -11,7 +11,9 @@ QPixmap IconImageProvider::requestPixmap(const QString& id, QSize* size, const QSize& requestedSize) { QString iconName; + QString fallbackName; QString path; + auto splitIdx = id.indexOf("?path="); if (splitIdx != -1) { iconName = id.sliced(0, splitIdx); @@ -19,10 +21,17 @@ IconImageProvider::requestPixmap(const QString& id, QSize* size, const QSize& re qWarning() << "Searching custom icon paths is not yet supported. Icon path will be ignored for" << id; } else { - iconName = id; + splitIdx = id.indexOf("?fallback="); + if (splitIdx != -1) { + iconName = id.sliced(0, splitIdx); + fallbackName = id.sliced(splitIdx + 10); + } else { + iconName = id; + } } auto icon = QIcon::fromTheme(iconName); + if (icon.isNull()) icon = QIcon::fromTheme(fallbackName); auto targetSize = requestedSize.isValid() ? requestedSize : QSize(100, 100); if (targetSize.width() == 0 || targetSize.height() == 0) targetSize = QSize(2, 2); @@ -55,12 +64,20 @@ QPixmap IconImageProvider::missingPixmap(const QSize& size) { return pixmap; } -QString IconImageProvider::requestString(const QString& icon, const QString& path) { +QString IconImageProvider::requestString( + const QString& icon, + const QString& path, + const QString& fallback +) { auto req = "image://icon/" + icon; if (!path.isEmpty()) { req += "?path=" + path; } + if (!fallback.isEmpty()) { + req += "?fallback=" + fallback; + } + return req; } diff --git a/src/core/iconimageprovider.hpp b/src/core/iconimageprovider.hpp index 167d93bd..57e26049 100644 --- a/src/core/iconimageprovider.hpp +++ b/src/core/iconimageprovider.hpp @@ -10,5 +10,10 @@ public: QPixmap requestPixmap(const QString& id, QSize* size, const QSize& requestedSize) override; static QPixmap missingPixmap(const QSize& size); - static QString requestString(const QString& icon, const QString& path); + + static QString requestString( + const QString& icon, + const QString& path = QString(), + const QString& fallback = QString() + ); }; diff --git a/src/core/qmlglobal.cpp b/src/core/qmlglobal.cpp index 9328d90a..23f238da 100644 --- a/src/core/qmlglobal.cpp +++ b/src/core/qmlglobal.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -196,7 +197,16 @@ QVariant QuickshellGlobal::env(const QString& variable) { // NOLINT } QString QuickshellGlobal::iconPath(const QString& icon) { - return IconImageProvider::requestString(icon, ""); + return IconImageProvider::requestString(icon); +} + +QString QuickshellGlobal::iconPath(const QString& icon, bool check) { + if (check && QIcon::fromTheme(icon).isNull()) return ""; + return IconImageProvider::requestString(icon); +} + +QString QuickshellGlobal::iconPath(const QString& icon, const QString& fallback) { + return IconImageProvider::requestString(icon, "", fallback); } QuickshellGlobal* QuickshellGlobal::create(QQmlEngine* engine, QJSEngine* /*unused*/) { diff --git a/src/core/qmlglobal.hpp b/src/core/qmlglobal.hpp index 7efdb413..4f46d238 100644 --- a/src/core/qmlglobal.hpp +++ b/src/core/qmlglobal.hpp @@ -137,6 +137,12 @@ public: /// > at the top of your root config file or set the `QS_ICON_THEME` variable to the name /// > of your icon theme. Q_INVOKABLE static QString iconPath(const QString& icon); + /// Setting the `check` parameter of `iconPath` to true will return an empty string + /// if the icon does not exist, instead of an image showing a missing texture. + Q_INVOKABLE static QString iconPath(const QString& icon, bool check); + /// Setting the `fallback` parameter of `iconPath` will attempt to load the fallback + /// icon if the requested one could not be loaded. + Q_INVOKABLE static QString iconPath(const QString& icon, const QString& fallback); [[nodiscard]] QString shellRoot() const;