changeset 964:9b4771ba2e3e osx-retina

Merge from branch scalable-icons
author Chris Cannam
date Thu, 14 May 2015 15:40:37 +0100
parents fa96108d552d (current diff) c91878670297 (diff)
children 0aac065f09f9
files svgui.pro
diffstat 4 files changed, 133 insertions(+), 34 deletions(-) [+]
line wrap: on
line diff
--- a/svgui.pro	Thu May 14 15:39:47 2015 +0100
+++ b/svgui.pro	Thu May 14 15:40:37 2015 +0100
@@ -26,7 +26,7 @@
 }
 
 CONFIG += staticlib qt thread warn_on stl rtti exceptions c++11
-QT += network xml gui widgets
+QT += network xml gui widgets svg
 
 TARGET = svgui
 
--- a/widgets/CommandHistory.cpp	Thu May 14 15:39:47 2015 +0100
+++ b/widgets/CommandHistory.cpp	Thu May 14 15:40:37 2015 +0100
@@ -26,6 +26,8 @@
 
 #include "base/Command.h"
 
+#include "IconLoader.h"
+
 #include <QRegExp>
 #include <QMenu>
 #include <QToolBar>
@@ -53,12 +55,16 @@
     m_bundleTimer(0),
     m_bundleTimeout(3000)
 {
-    m_undoAction = new QAction(QIcon(":/icons/undo.png"), tr("&Undo"), this);
+    IconLoader loader;
+    QIcon undoIcon(loader.load("undo"));
+    QIcon redoIcon(loader.load("redo"));
+    
+    m_undoAction = new QAction(undoIcon, ("&Undo"), this);
     m_undoAction->setShortcut(tr("Ctrl+Z"));
     m_undoAction->setStatusTip(tr("Undo the last editing operation"));
     connect(m_undoAction, SIGNAL(triggered()), this, SLOT(undo()));
     
-    m_undoMenuAction = new QAction(QIcon(":/icons/undo.png"), tr("&Undo"), this);
+    m_undoMenuAction = new QAction(undoIcon, tr("&Undo"), this);
     connect(m_undoMenuAction, SIGNAL(triggered()), this, SLOT(undo()));
     
     m_undoMenu = new QMenu(tr("&Undo"));
@@ -66,12 +72,12 @@
     connect(m_undoMenu, SIGNAL(triggered(QAction *)),
 	    this, SLOT(undoActivated(QAction*)));
 
-    m_redoAction = new QAction(QIcon(":/icons/redo.png"), tr("Re&do"), this);
+    m_redoAction = new QAction(redoIcon, tr("Re&do"), this);
     m_redoAction->setShortcut(tr("Ctrl+Shift+Z"));
     m_redoAction->setStatusTip(tr("Redo the last operation that was undone"));
     connect(m_redoAction, SIGNAL(triggered()), this, SLOT(redo()));
     
-    m_redoMenuAction = new QAction(QIcon(":/icons/redo.png"), tr("Re&do"), this);
+    m_redoMenuAction = new QAction(redoIcon, tr("Re&do"), this);
     connect(m_redoMenuAction, SIGNAL(triggered()), this, SLOT(redo()));
 
     m_redoMenu = new QMenu(tr("Re&do"));
--- a/widgets/IconLoader.cpp	Thu May 14 15:39:47 2015 +0100
+++ b/widgets/IconLoader.cpp	Thu May 14 15:40:37 2015 +0100
@@ -19,8 +19,17 @@
 #include <QApplication>
 #include <QPainter>
 #include <QPalette>
+#include <QFile>
+#include <QSvgRenderer>
 
-static const char *autoInvertExceptions[] = {
+#include <vector>
+#include <set>
+
+#include "base/Debug.h"
+
+using namespace std;
+
+static set<QString> autoInvertExceptions {
     // These are the icons that look OK in their default colours, even
     // in a colour scheme with a black background.  (They may also be
     // icons that would look worse if we tried to auto-invert them.)
@@ -29,16 +38,13 @@
     // supply inverted versions -- the loader will load xx_inverse.png
     // in preference to xx.png if a dark background is found.)
     "fileclose",
-    "filenew-22",
     "filenew",
-    "fileopen-22",
     "fileopen",
     "fileopenaudio",
     "fileopensession",
-    "filesave-22",
     "filesave",
-    "filesaveas-22",
     "filesaveas",
+    "filesaveas-sv",
     "help",
     "editcut",
     "editcopy",
@@ -51,42 +57,121 @@
     "zoom"
 };
 
+static vector<int> sizes { 0, 16, 22, 24, 32, 48, 64, 128 };
+
 QIcon
 IconLoader::load(QString name)
 {
-    QPixmap pmap(loadPixmap(name));
-    if (pmap.isNull()) return QIcon();
-    else return QIcon(pmap);
+    QIcon icon;
+    for (int sz: sizes) {
+        QPixmap pmap(loadPixmap(name, sz));
+        if (!pmap.isNull()) icon.addPixmap(pmap);
+    }
+    return icon;
+}
+
+bool
+IconLoader::shouldInvert() const
+{
+    QColor bg = QApplication::palette().window().color();
+    bool darkBackground = (bg.red() + bg.green() + bg.blue() <= 384);
+    return darkBackground;
+}
+
+bool
+IconLoader::shouldAutoInvert(QString name) const
+{
+    if (shouldInvert()) {
+        return (autoInvertExceptions.find(name) == autoInvertExceptions.end());
+    } else {
+        return false;
+    }
 }
 
 QPixmap
-IconLoader::loadPixmap(QString name)
+IconLoader::loadPixmap(QString name, int size)
 {
-    QColor bg = QApplication::palette().window().color();
-    if (bg.red() + bg.green() + bg.blue() > 384) { // light background
-        QPixmap pmap(QString(":icons/%1").arg(name));
-        if (pmap.isNull()) {
-            pmap = QPixmap(QString(":icons/%1.png").arg(name));
-        }
-        return pmap;
+    bool invert = shouldInvert();
+
+    QString scalableName, nonScalableName;
+    QPixmap pmap;
+
+    nonScalableName = makeNonScalableFilename(name, size, invert);
+    pmap = QPixmap(nonScalableName);
+    if (!pmap.isNull()) return pmap;
+
+    if (size > 0) {
+        scalableName = makeScalableFilename(name, invert);
+        pmap = loadScalable(scalableName, size);
+        if (!pmap.isNull()) return pmap;
     }
 
-    QPixmap pmap(QString(":icons/%1").arg(name));
-    if (pmap.isNull()) {
-        pmap = QPixmap(QString(":icons/%1_inverse.png").arg(name));
-        if (pmap.isNull()) {
-            pmap = QPixmap(QString(":icons/%1.png").arg(name));
-        }
-    }
-    if (pmap.isNull()) return pmap;
+    if (invert && shouldAutoInvert(name)) {
 
-    for (int i = 0; i < int(sizeof(autoInvertExceptions)/
-                            sizeof(autoInvertExceptions[0])); ++i) {
-        if (autoInvertExceptions[i] == name) {
-            return pmap;
+        nonScalableName = makeNonScalableFilename(name, size, false);
+        pmap = QPixmap(nonScalableName);
+        if (!pmap.isNull()) return invertPixmap(pmap);
+
+        if (size > 0) {
+            scalableName = makeScalableFilename(name, false);
+            pmap = loadScalable(scalableName, size);
+            if (!pmap.isNull()) return invertPixmap(pmap);
         }
     }
 
+    return QPixmap();
+}
+
+QPixmap
+IconLoader::loadScalable(QString name, int size)
+{
+    if (!QFile(name).exists()) {
+        cerr << "loadScalable: no such file as: \"" << name << "\"" << endl;
+        return QPixmap();
+    }
+    QPixmap pmap(size, size);
+    pmap.fill(Qt::transparent);
+    QSvgRenderer renderer(name);
+    QPainter painter;
+    painter.begin(&pmap);
+    cerr << "calling renderer for " << name << " at size " << size << "..." << endl;
+    renderer.render(&painter);
+    cerr << "renderer completed" << endl;
+    painter.end();
+    return pmap;
+}
+
+QString
+IconLoader::makeNonScalableFilename(QString name, int size, bool invert)
+{
+    if (invert) {
+        if (size == 0) {
+            return QString(":icons/%1_inverse.png").arg(name);
+        } else {
+            return QString(":icons/%1-%2_inverse.png").arg(name).arg(size);
+        }
+    } else {
+        if (size == 0) {
+            return QString(":icons/%1.png").arg(name);
+        } else {
+            return QString(":icons/%1-%2.png").arg(name).arg(size);
+        }
+    }
+}
+
+QString
+IconLoader::makeScalableFilename(QString name, bool invert)
+{
+    if (invert) {
+        return QString(":icons/scalable/%1_inverse.svg").arg(name);
+    } else {
+        return QString(":icons/scalable/%1.svg").arg(name);
+    }
+}
+
+QPixmap
+IconLoader::invertPixmap(QPixmap pmap)
+{
     // No suitable inverted icon found for black background; try to
     // auto-invert the default one
 
--- a/widgets/IconLoader.h	Thu May 14 15:39:47 2015 +0100
+++ b/widgets/IconLoader.h	Thu May 14 15:40:37 2015 +0100
@@ -25,7 +25,15 @@
     virtual ~IconLoader() { }
 
     QIcon load(QString name);
-    QPixmap loadPixmap(QString name);
+
+private:
+    bool shouldInvert() const;
+    bool shouldAutoInvert(QString) const;
+    QPixmap loadPixmap(QString, int);
+    QPixmap loadScalable(QString, int);
+    QPixmap invertPixmap(QPixmap);
+    QString makeScalableFilename(QString, bool);
+    QString makeNonScalableFilename(QString, int, bool);
 };
 
 #endif