icons: Add hicolor fallback for Qt < 5.5
authorManuel Nickschas <sputnick@quassel-irc.org>
Wed, 13 Jun 2018 20:57:37 +0000 (22:57 +0200)
committerManuel Nickschas <sputnick@quassel-irc.org>
Fri, 15 Jun 2018 23:30:32 +0000 (01:30 +0200)
Turns out that Qt only added support for split icon themes in 5.5,
so with older Qt versions our icon theme support doesn't work
properly.

Install hicolor icons for Qt < 5.5, as we already do for Qt 4.
Add a hicolor icon resource, too, and make use of it in the system
tray implementations, which is arguably the most important place
to have proper icon support.

This adds around 130 KiB to the binary size, but should save a lot
of headaches.

icons/CMakeLists.txt
icons/hicolor_icons.qrc [new file with mode: 0644]
src/common/main.cpp
src/qtui/legacysystemtray.cpp
src/qtui/statusnotifieritem.cpp

index b989db4..fab63f6 100644 (file)
@@ -7,6 +7,9 @@ if (WANT_MONO OR WANT_QTCLIENT)
 
     set(BUNDLED_ICON_THEME_DIR ${CMAKE_SOURCE_DIR}/3rdparty/icons)
 
+    # Always embed a hicolor fallback containing the most important (e.g. tray) icons
+    list(APPEND ICON_RCS ${CMAKE_CURRENT_SOURCE_DIR}/hicolor_icons.qrc)
+
     if (EMBED_DATA)
         # Always embed quassel-specific icons
         message(STATUS "Embedding Quassel-specific icons")
@@ -55,7 +58,7 @@ if (WANT_MONO OR WANT_QTCLIENT)
         # hicolor contains the application icon in all relevant sizes
         install(DIRECTORY hicolor DESTINATION ${CMAKE_INSTALL_ICONDIR})
 
-        if (USE_QT4)
+        if (USE_QT4 OR (USE_QT5 AND Qt5Core_VERSION VERSION_LESS 5.5.0))
             # Qt 4 doesn't seem to correctly load icons from injected themes
             # Install Quassel-specific ones from Oxygen into hicolor as fallback
             install(DIRECTORY oxygen/ DESTINATION ${CMAKE_INSTALL_ICONDIR}/hicolor)
diff --git a/icons/hicolor_icons.qrc b/icons/hicolor_icons.qrc
new file mode 100644 (file)
index 0000000..a51c9fa
--- /dev/null
@@ -0,0 +1,27 @@
+<RCC>
+  <qresource prefix="/icons">
+    <file alias="hicolor/24x24/actions/connect-quassel.svg">breeze/actions/24/connect-quassel.svg</file>
+    <file alias="hicolor/32x32/actions/connect-quassel.svg">breeze/actions/32/connect-quassel.svg</file>
+    <file alias="hicolor/24x24/actions/disconnect-quassel.svg">breeze/actions/24/disconnect-quassel.svg</file>
+    <file alias="hicolor/32x32/actions/disconnect-quassel.svg">breeze/actions/32/disconnect-quassel.svg</file>
+    <file alias="hicolor/32x32/apps/quassel.svg">breeze/apps/32/quassel.svg</file>
+    <file alias="hicolor/48x48/apps/quassel.svg">breeze/apps/48/quassel.svg</file>
+    <file alias="hicolor/64x64/apps/quassel.svg">breeze/apps/64/quassel.svg</file>
+    <file alias="hicolor/24x24/status/active-quassel-tray.svg">breeze/status/24/active-quassel-tray.svg</file>
+    <file alias="hicolor/64x64/status/active-quassel-tray.svg">breeze/status/64/active-quassel-tray.svg</file>
+    <file alias="hicolor/24x24/status/active-quassel-tray-inverted.svg">breeze/status/24/active-quassel-tray-inverted.svg</file>
+    <file alias="hicolor/64x64/status/active-quassel-tray-inverted.svg">breeze/status/64/active-quassel-tray-inverted.svg</file>
+    <file alias="hicolor/24x24/status/inactive-quassel.svg">breeze/status/24/inactive-quassel.svg</file>
+    <file alias="hicolor/64x64/status/inactive-quassel.svg">breeze/status/64/inactive-quassel.svg</file>
+    <file alias="hicolor/24x24/status/inactive-quassel-tray.svg">breeze/status/24/inactive-quassel-tray.svg</file>
+    <file alias="hicolor/64x64/status/inactive-quassel-tray.svg">breeze/status/64/inactive-quassel-tray.svg</file>
+    <file alias="hicolor/24x24/status/inactive-quassel-tray-inverted.svg">breeze/status/24/inactive-quassel-tray-inverted.svg</file>
+    <file alias="hicolor/64x64/status/inactive-quassel-tray-inverted.svg">breeze/status/64/inactive-quassel-tray-inverted.svg</file>
+    <file alias="hicolor/24x24/status/message-quassel.svg">breeze/status/24/message-quassel.svg</file>
+    <file alias="hicolor/64x64/status/message-quassel.svg">breeze/status/64/message-quassel.svg</file>
+    <file alias="hicolor/24x24/status/message-quassel-tray.svg">breeze/status/24/message-quassel-tray.svg</file>
+    <file alias="hicolor/64x64/status/message-quassel-tray.svg">breeze/status/64/message-quassel-tray.svg</file>
+    <file alias="hicolor/24x24/status/message-quassel-tray-inverted.svg">breeze/status/24/message-quassel-tray-inverted.svg</file>
+    <file alias="hicolor/64x64/status/message-quassel-tray-inverted.svg">breeze/status/64/message-quassel-tray-inverted.svg</file>
+  </qresource>
+</RCC>
index 6a36e54..75b295c 100644 (file)
@@ -100,6 +100,7 @@ int main(int argc, char **argv)
 #endif
 #ifndef BUILD_CORE
     Q_INIT_RESOURCE(pics);
+    Q_INIT_RESOURCE(hicolor_icons);
 #endif
 
 #ifdef EMBED_DATA
index 9308798..da27d23 100644 (file)
@@ -143,12 +143,14 @@ void LegacySystemTray::setState(State state_)
 
 void LegacySystemTray::updateIcon()
 {
+    QString icon;
     if (state() == State::NeedsAttention && !_blinkState) {
-        _trayIcon->setIcon(QIcon::fromTheme(iconName(State::Active)));
+        icon = iconName(State::Active);
     }
     else {
-        _trayIcon->setIcon(QIcon::fromTheme(iconName(state())));
+        icon = iconName(state());
     }
+    _trayIcon->setIcon(QIcon::fromTheme(icon, QIcon{QString{":/icons/hicolor/24x24/status/%1.svg"}.arg(icon)}));
 }
 
 
index 0965eef..dc33b97 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <QApplication>
 #include <QDir>
+#include <QFile>
 #include <QMenu>
 #include <QMouseEvent>
 #include <QTextDocument>
@@ -184,16 +185,27 @@ void StatusNotifierItem::refreshIcons()
         QDir baseDir{_iconThemePath + "/hicolor"};
         baseDir.removeRecursively();
         for (auto &&trayState : { State::Active, State::Passive, State::NeedsAttention }) {
-            QIcon icon = QIcon::fromTheme(SystemTray::iconName(trayState));
-            if (!icon.name().isEmpty()) {
+            auto iconName = SystemTray::iconName(trayState);
+            QIcon icon = QIcon::fromTheme(iconName);
+            if (!icon.isNull()) {
                 for (auto &&size : icon.availableSizes()) {
                     auto pixDir = QString{"%1/%2x%3/status"}.arg(baseDir.absolutePath()).arg(size.width()).arg(size.height());
                     QDir{}.mkpath(pixDir);
-                    if (!icon.pixmap(size).save(pixDir + "/" + icon.name() + ".png")) {
-                        qWarning() << "Could not save tray icon" << icon.name() << "for size" << size;
+                    if (!icon.pixmap(size).save(pixDir + "/" + iconName + ".png")) {
+                        qWarning() << "Could not save tray icon" << iconName << "for size" << size;
                     }
                 }
             }
+            else {
+                // No theme icon found; use fallback from resources
+                auto iconDir = QString{"%1/24x24/status"}.arg(baseDir.absolutePath());
+                QDir{}.mkpath(iconDir);
+                if (!QFile::copy(QString{":/icons/hicolor/24x24/status/%1.svg"}.arg(iconName),
+                                 QString{"%1/%2.svg"}.arg(iconDir, iconName))) {
+                    qWarning() << "Could not access fallback tray icon" << iconName;
+                    continue;
+                }
+            }
         }
     }
 #endif