annotate widgets/IconLoader.cpp @ 1509:8145a9c4c253

The default key frame map is not working well at the moment, because its extents are not being properly updated as the models they depend on are loaded. Leave it empty for now.
author Chris Cannam
date Tue, 17 Sep 2019 12:50:34 +0100
parents 8b7f797bca86
children 705d1d979ae4
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@1452 24 #include <QSettings>
Chris@289 25
Chris@957 26 #include <vector>
Chris@957 27 #include <set>
Chris@957 28
Chris@957 29 #include "base/Debug.h"
Chris@957 30
Chris@957 31 using namespace std;
Chris@957 32
Chris@957 33 static set<QString> autoInvertExceptions {
Chris@289 34 // These are the icons that look OK in their default colours, even
Chris@289 35 // in a colour scheme with a black background. (They may also be
Chris@289 36 // icons that would look worse if we tried to auto-invert them.)
Chris@289 37 // If we have icons that look bad when auto-inverted but that are
Chris@289 38 // not suitable for use without being inverted, we'll need to
Chris@289 39 // supply inverted versions -- the loader will load xx_inverse.png
Chris@289 40 // in preference to xx.png if a dark background is found.)
Chris@289 41 "fileclose",
Chris@289 42 "filenew",
Chris@289 43 "fileopen",
Chris@289 44 "fileopenaudio",
Chris@289 45 "fileopensession",
Chris@289 46 "filesave",
Chris@289 47 "filesaveas",
Chris@957 48 "filesaveas-sv",
Chris@289 49 "help",
Chris@289 50 "editcut",
Chris@289 51 "editcopy",
Chris@289 52 "editpaste",
Chris@289 53 "editdelete",
Chris@289 54 "exit",
Chris@289 55 "zoom-fit",
Chris@289 56 "zoom-in",
Chris@289 57 "zoom-out",
Chris@289 58 "zoom"
Chris@289 59 };
Chris@289 60
Chris@957 61 static vector<int> sizes { 0, 16, 22, 24, 32, 48, 64, 128 };
Chris@957 62
Chris@289 63 QIcon
Chris@289 64 IconLoader::load(QString name)
Chris@289 65 {
Chris@957 66 QIcon icon;
Chris@957 67 for (int sz: sizes) {
Chris@957 68 QPixmap pmap(loadPixmap(name, sz));
Chris@957 69 if (!pmap.isNull()) icon.addPixmap(pmap);
Chris@957 70 }
Chris@957 71 return icon;
Chris@957 72 }
Chris@957 73
Chris@957 74 bool
Chris@957 75 IconLoader::shouldInvert() const
Chris@957 76 {
Chris@1452 77 QSettings settings;
Chris@1452 78 settings.beginGroup("IconLoader");
Chris@1452 79 if (!settings.value("invert-icons-on-dark-background", true).toBool()) {
Chris@1452 80 return false;
Chris@1452 81 }
Chris@957 82 QColor bg = QApplication::palette().window().color();
Chris@957 83 bool darkBackground = (bg.red() + bg.green() + bg.blue() <= 384);
Chris@957 84 return darkBackground;
Chris@957 85 }
Chris@957 86
Chris@957 87 bool
Chris@957 88 IconLoader::shouldAutoInvert(QString name) const
Chris@957 89 {
Chris@957 90 if (shouldInvert()) {
Chris@957 91 return (autoInvertExceptions.find(name) == autoInvertExceptions.end());
Chris@957 92 } else {
Chris@957 93 return false;
Chris@957 94 }
Chris@289 95 }
Chris@289 96
Chris@289 97 QPixmap
Chris@957 98 IconLoader::loadPixmap(QString name, int size)
Chris@289 99 {
Chris@957 100 bool invert = shouldInvert();
Chris@958 101
Chris@958 102 QString scalableName, nonScalableName;
Chris@958 103 QPixmap pmap;
Chris@958 104
Chris@1262 105 // attempt to load a pixmap with the right size and inversion
Chris@958 106 nonScalableName = makeNonScalableFilename(name, size, invert);
Chris@958 107 pmap = QPixmap(nonScalableName);
Chris@958 108
Chris@1262 109 if (pmap.isNull() && size > 0) {
Chris@1262 110 // if that failed, load a scalable vector with the right
Chris@1262 111 // inversion and scale it
Chris@958 112 scalableName = makeScalableFilename(name, invert);
Chris@958 113 pmap = loadScalable(scalableName, size);
Chris@958 114 }
Chris@958 115
Chris@1262 116 if (pmap.isNull() && invert) {
Chris@1262 117 // if that failed, and we were asking for an inverted pixmap,
Chris@1262 118 // that may mean we don't have an inverted version of it. We
Chris@1262 119 // could either auto-invert or use the uninverted version
Chris@957 120 nonScalableName = makeNonScalableFilename(name, size, false);
Chris@957 121 pmap = QPixmap(nonScalableName);
Chris@957 122
Chris@1262 123 if (pmap.isNull() && size > 0) {
Chris@958 124 scalableName = makeScalableFilename(name, false);
Chris@958 125 pmap = loadScalable(scalableName, size);
Chris@1262 126 }
Chris@1262 127
Chris@1262 128 if (!pmap.isNull() && shouldAutoInvert(name)) {
Chris@1262 129 pmap = invertPixmap(pmap);
Chris@958 130 }
Chris@957 131 }
Chris@958 132
Chris@1262 133 return pmap;
Chris@957 134 }
Chris@957 135
Chris@957 136 QPixmap
Chris@957 137 IconLoader::loadScalable(QString name, int size)
Chris@957 138 {
Chris@957 139 if (!QFile(name).exists()) {
Chris@1003 140 // cerr << "loadScalable: no such file as: \"" << name << "\"" << endl;
Chris@957 141 return QPixmap();
Chris@957 142 }
Chris@957 143 QPixmap pmap(size, size);
Chris@957 144 pmap.fill(Qt::transparent);
Chris@957 145 QSvgRenderer renderer(name);
Chris@958 146 QPainter painter;
Chris@958 147 painter.begin(&pmap);
Chris@1003 148 // cerr << "calling renderer for " << name << " at size " << size << "..." << endl;
Chris@957 149 renderer.render(&painter);
Chris@1003 150 // cerr << "renderer completed" << endl;
Chris@958 151 painter.end();
Chris@957 152 return pmap;
Chris@957 153 }
Chris@957 154
Chris@957 155 QString
Chris@957 156 IconLoader::makeNonScalableFilename(QString name, int size, bool invert)
Chris@957 157 {
Chris@957 158 if (invert) {
Chris@957 159 if (size == 0) {
Chris@957 160 return QString(":icons/%1_inverse.png").arg(name);
Chris@957 161 } else {
Chris@957 162 return QString(":icons/%1-%2_inverse.png").arg(name).arg(size);
Chris@289 163 }
Chris@957 164 } else {
Chris@957 165 if (size == 0) {
Chris@957 166 return QString(":icons/%1.png").arg(name);
Chris@957 167 } else {
Chris@957 168 return QString(":icons/%1-%2.png").arg(name).arg(size);
Chris@289 169 }
Chris@289 170 }
Chris@957 171 }
Chris@289 172
Chris@957 173 QString
Chris@957 174 IconLoader::makeScalableFilename(QString name, bool invert)
Chris@957 175 {
Chris@957 176 if (invert) {
Chris@957 177 return QString(":icons/scalable/%1_inverse.svg").arg(name);
Chris@957 178 } else {
Chris@957 179 return QString(":icons/scalable/%1.svg").arg(name);
Chris@289 180 }
Chris@957 181 }
Chris@289 182
Chris@957 183 QPixmap
Chris@957 184 IconLoader::invertPixmap(QPixmap pmap)
Chris@957 185 {
Chris@289 186 // No suitable inverted icon found for black background; try to
Chris@289 187 // auto-invert the default one
Chris@289 188
Chris@289 189 QImage img = pmap.toImage().convertToFormat(QImage::Format_ARGB32);
Chris@289 190
Chris@289 191 for (int y = 0; y < img.height(); ++y) {
Chris@289 192 for (int x = 0; x < img.width(); ++x) {
Chris@289 193
Chris@289 194 QRgb rgba = img.pixel(x, y);
Chris@289 195 QColor colour = QColor
Chris@289 196 (qRed(rgba), qGreen(rgba), qBlue(rgba), qAlpha(rgba));
Chris@289 197
Chris@289 198 int alpha = colour.alpha();
Chris@289 199 if (colour.saturation() < 5 && colour.alpha() > 10) {
Chris@289 200 colour.setHsv(colour.hue(),
Chris@289 201 colour.saturation(),
Chris@289 202 255 - colour.value());
Chris@289 203 colour.setAlpha(alpha);
Chris@289 204 img.setPixel(x, y, colour.rgba());
Chris@289 205 }
Chris@289 206 }
Chris@289 207 }
Chris@289 208
Chris@289 209 pmap = QPixmap::fromImage(img);
Chris@289 210 return pmap;
Chris@289 211 }
Chris@289 212