annotate widgets/IconLoader.cpp @ 1024:3bce4c45b681 spectrogram-minor-refactor

Rearrange cache update calculations so as to use the actual painted width returned by paint functions (though they only ever return the same width as requested, at this point)
author Chris Cannam
date Mon, 25 Jan 2016 15:52:26 +0000
parents 5fdf5cd032ac
children a9c2e791ab8d
rev   line source
Chris@289 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@289 2
Chris@289 3 /*
Chris@289 4 Sonic Visualiser
Chris@289 5 An audio file viewer and annotation editor.
Chris@289 6 Centre for Digital Music, Queen Mary, University of London.
Chris@289 7 This file copyright 2007 QMUL.
Chris@289 8
Chris@289 9 This program is free software; you can redistribute it and/or
Chris@289 10 modify it under the terms of the GNU General Public License as
Chris@289 11 published by the Free Software Foundation; either version 2 of the
Chris@289 12 License, or (at your option) any later version. See the file
Chris@289 13 COPYING included with this distribution for more information.
Chris@289 14 */
Chris@289 15
Chris@289 16 #include "IconLoader.h"
Chris@289 17
Chris@289 18 #include <QPixmap>
Chris@289 19 #include <QApplication>
Chris@289 20 #include <QPainter>
Chris@289 21 #include <QPalette>
Chris@957 22 #include <QFile>
Chris@957 23 #include <QSvgRenderer>
Chris@289 24
Chris@957 25 #include <vector>
Chris@957 26 #include <set>
Chris@957 27
Chris@957 28 #include "base/Debug.h"
Chris@957 29
Chris@957 30 using namespace std;
Chris@957 31
Chris@957 32 static set<QString> autoInvertExceptions {
Chris@289 33 // These are the icons that look OK in their default colours, even
Chris@289 34 // in a colour scheme with a black background. (They may also be
Chris@289 35 // icons that would look worse if we tried to auto-invert them.)
Chris@289 36 // If we have icons that look bad when auto-inverted but that are
Chris@289 37 // not suitable for use without being inverted, we'll need to
Chris@289 38 // supply inverted versions -- the loader will load xx_inverse.png
Chris@289 39 // in preference to xx.png if a dark background is found.)
Chris@289 40 "fileclose",
Chris@289 41 "filenew",
Chris@289 42 "fileopen",
Chris@289 43 "fileopenaudio",
Chris@289 44 "fileopensession",
Chris@289 45 "filesave",
Chris@289 46 "filesaveas",
Chris@957 47 "filesaveas-sv",
Chris@289 48 "help",
Chris@289 49 "editcut",
Chris@289 50 "editcopy",
Chris@289 51 "editpaste",
Chris@289 52 "editdelete",
Chris@289 53 "exit",
Chris@289 54 "zoom-fit",
Chris@289 55 "zoom-in",
Chris@289 56 "zoom-out",
Chris@289 57 "zoom"
Chris@289 58 };
Chris@289 59
Chris@957 60 static vector<int> sizes { 0, 16, 22, 24, 32, 48, 64, 128 };
Chris@957 61
Chris@289 62 QIcon
Chris@289 63 IconLoader::load(QString name)
Chris@289 64 {
Chris@957 65 QIcon icon;
Chris@957 66 for (int sz: sizes) {
Chris@957 67 QPixmap pmap(loadPixmap(name, sz));
Chris@957 68 if (!pmap.isNull()) icon.addPixmap(pmap);
Chris@957 69 }
Chris@957 70 return icon;
Chris@957 71 }
Chris@957 72
Chris@957 73 bool
Chris@957 74 IconLoader::shouldInvert() const
Chris@957 75 {
Chris@957 76 QColor bg = QApplication::palette().window().color();
Chris@957 77 bool darkBackground = (bg.red() + bg.green() + bg.blue() <= 384);
Chris@957 78 return darkBackground;
Chris@957 79 }
Chris@957 80
Chris@957 81 bool
Chris@957 82 IconLoader::shouldAutoInvert(QString name) const
Chris@957 83 {
Chris@957 84 if (shouldInvert()) {
Chris@957 85 return (autoInvertExceptions.find(name) == autoInvertExceptions.end());
Chris@957 86 } else {
Chris@957 87 return false;
Chris@957 88 }
Chris@289 89 }
Chris@289 90
Chris@289 91 QPixmap
Chris@957 92 IconLoader::loadPixmap(QString name, int size)
Chris@289 93 {
Chris@957 94 bool invert = shouldInvert();
Chris@958 95
Chris@958 96 QString scalableName, nonScalableName;
Chris@958 97 QPixmap pmap;
Chris@958 98
Chris@958 99 nonScalableName = makeNonScalableFilename(name, size, invert);
Chris@958 100 pmap = QPixmap(nonScalableName);
Chris@957 101 if (!pmap.isNull()) return pmap;
Chris@958 102
Chris@958 103 if (size > 0) {
Chris@958 104 scalableName = makeScalableFilename(name, invert);
Chris@958 105 pmap = loadScalable(scalableName, size);
Chris@958 106 if (!pmap.isNull()) return pmap;
Chris@958 107 }
Chris@958 108
Chris@957 109 if (invert && shouldAutoInvert(name)) {
Chris@957 110
Chris@957 111 nonScalableName = makeNonScalableFilename(name, size, false);
Chris@957 112 pmap = QPixmap(nonScalableName);
Chris@957 113 if (!pmap.isNull()) return invertPixmap(pmap);
Chris@957 114
Chris@958 115 if (size > 0) {
Chris@958 116 scalableName = makeScalableFilename(name, false);
Chris@958 117 pmap = loadScalable(scalableName, size);
Chris@958 118 if (!pmap.isNull()) return invertPixmap(pmap);
Chris@958 119 }
Chris@957 120 }
Chris@958 121
Chris@957 122 return QPixmap();
Chris@957 123 }
Chris@957 124
Chris@957 125 QPixmap
Chris@957 126 IconLoader::loadScalable(QString name, int size)
Chris@957 127 {
Chris@957 128 if (!QFile(name).exists()) {
Chris@1003 129 // cerr << "loadScalable: no such file as: \"" << name << "\"" << endl;
Chris@957 130 return QPixmap();
Chris@957 131 }
Chris@957 132 QPixmap pmap(size, size);
Chris@957 133 pmap.fill(Qt::transparent);
Chris@957 134 QSvgRenderer renderer(name);
Chris@958 135 QPainter painter;
Chris@958 136 painter.begin(&pmap);
Chris@1003 137 // cerr << "calling renderer for " << name << " at size " << size << "..." << endl;
Chris@957 138 renderer.render(&painter);
Chris@1003 139 // cerr << "renderer completed" << endl;
Chris@958 140 painter.end();
Chris@957 141 return pmap;
Chris@957 142 }
Chris@957 143
Chris@957 144 QString
Chris@957 145 IconLoader::makeNonScalableFilename(QString name, int size, bool invert)
Chris@957 146 {
Chris@957 147 if (invert) {
Chris@957 148 if (size == 0) {
Chris@957 149 return QString(":icons/%1_inverse.png").arg(name);
Chris@957 150 } else {
Chris@957 151 return QString(":icons/%1-%2_inverse.png").arg(name).arg(size);
Chris@289 152 }
Chris@957 153 } else {
Chris@957 154 if (size == 0) {
Chris@957 155 return QString(":icons/%1.png").arg(name);
Chris@957 156 } else {
Chris@957 157 return QString(":icons/%1-%2.png").arg(name).arg(size);
Chris@289 158 }
Chris@289 159 }
Chris@957 160 }
Chris@289 161
Chris@957 162 QString
Chris@957 163 IconLoader::makeScalableFilename(QString name, bool invert)
Chris@957 164 {
Chris@957 165 if (invert) {
Chris@957 166 return QString(":icons/scalable/%1_inverse.svg").arg(name);
Chris@957 167 } else {
Chris@957 168 return QString(":icons/scalable/%1.svg").arg(name);
Chris@289 169 }
Chris@957 170 }
Chris@289 171
Chris@957 172 QPixmap
Chris@957 173 IconLoader::invertPixmap(QPixmap pmap)
Chris@957 174 {
Chris@289 175 // No suitable inverted icon found for black background; try to
Chris@289 176 // auto-invert the default one
Chris@289 177
Chris@289 178 QImage img = pmap.toImage().convertToFormat(QImage::Format_ARGB32);
Chris@289 179
Chris@289 180 for (int y = 0; y < img.height(); ++y) {
Chris@289 181 for (int x = 0; x < img.width(); ++x) {
Chris@289 182
Chris@289 183 QRgb rgba = img.pixel(x, y);
Chris@289 184 QColor colour = QColor
Chris@289 185 (qRed(rgba), qGreen(rgba), qBlue(rgba), qAlpha(rgba));
Chris@289 186
Chris@289 187 int alpha = colour.alpha();
Chris@289 188 if (colour.saturation() < 5 && colour.alpha() > 10) {
Chris@289 189 colour.setHsv(colour.hue(),
Chris@289 190 colour.saturation(),
Chris@289 191 255 - colour.value());
Chris@289 192 colour.setAlpha(alpha);
Chris@289 193 img.setPixel(x, y, colour.rgba());
Chris@289 194 }
Chris@289 195 }
Chris@289 196 }
Chris@289 197
Chris@289 198 pmap = QPixmap::fromImage(img);
Chris@289 199 return pmap;
Chris@289 200 }
Chris@289 201