annotate widgets/IconLoader.cpp @ 1447:8afea53332f3 single-point

Add option to make pane sizes auto-resize-only (i.e. remove user control via a splitter); also place alignment views above panes instead of below, meaning the extra bit of space that we currently have for the pane without one at least goes to the primary pane
author Chris Cannam
date Tue, 30 Apr 2019 15:53:21 +0100
parents a9c2e791ab8d
children 8b7f797bca86
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@1262 99 // attempt to load a pixmap with the right size and inversion
Chris@958 100 nonScalableName = makeNonScalableFilename(name, size, invert);
Chris@958 101 pmap = QPixmap(nonScalableName);
Chris@958 102
Chris@1262 103 if (pmap.isNull() && size > 0) {
Chris@1262 104 // if that failed, load a scalable vector with the right
Chris@1262 105 // inversion and scale it
Chris@958 106 scalableName = makeScalableFilename(name, invert);
Chris@958 107 pmap = loadScalable(scalableName, size);
Chris@958 108 }
Chris@958 109
Chris@1262 110 if (pmap.isNull() && invert) {
Chris@1262 111 // if that failed, and we were asking for an inverted pixmap,
Chris@1262 112 // that may mean we don't have an inverted version of it. We
Chris@1262 113 // could either auto-invert or use the uninverted version
Chris@957 114 nonScalableName = makeNonScalableFilename(name, size, false);
Chris@957 115 pmap = QPixmap(nonScalableName);
Chris@957 116
Chris@1262 117 if (pmap.isNull() && size > 0) {
Chris@958 118 scalableName = makeScalableFilename(name, false);
Chris@958 119 pmap = loadScalable(scalableName, size);
Chris@1262 120 }
Chris@1262 121
Chris@1262 122 if (!pmap.isNull() && shouldAutoInvert(name)) {
Chris@1262 123 pmap = invertPixmap(pmap);
Chris@958 124 }
Chris@957 125 }
Chris@958 126
Chris@1262 127 return pmap;
Chris@957 128 }
Chris@957 129
Chris@957 130 QPixmap
Chris@957 131 IconLoader::loadScalable(QString name, int size)
Chris@957 132 {
Chris@957 133 if (!QFile(name).exists()) {
Chris@1003 134 // cerr << "loadScalable: no such file as: \"" << name << "\"" << endl;
Chris@957 135 return QPixmap();
Chris@957 136 }
Chris@957 137 QPixmap pmap(size, size);
Chris@957 138 pmap.fill(Qt::transparent);
Chris@957 139 QSvgRenderer renderer(name);
Chris@958 140 QPainter painter;
Chris@958 141 painter.begin(&pmap);
Chris@1003 142 // cerr << "calling renderer for " << name << " at size " << size << "..." << endl;
Chris@957 143 renderer.render(&painter);
Chris@1003 144 // cerr << "renderer completed" << endl;
Chris@958 145 painter.end();
Chris@957 146 return pmap;
Chris@957 147 }
Chris@957 148
Chris@957 149 QString
Chris@957 150 IconLoader::makeNonScalableFilename(QString name, int size, bool invert)
Chris@957 151 {
Chris@957 152 if (invert) {
Chris@957 153 if (size == 0) {
Chris@957 154 return QString(":icons/%1_inverse.png").arg(name);
Chris@957 155 } else {
Chris@957 156 return QString(":icons/%1-%2_inverse.png").arg(name).arg(size);
Chris@289 157 }
Chris@957 158 } else {
Chris@957 159 if (size == 0) {
Chris@957 160 return QString(":icons/%1.png").arg(name);
Chris@957 161 } else {
Chris@957 162 return QString(":icons/%1-%2.png").arg(name).arg(size);
Chris@289 163 }
Chris@289 164 }
Chris@957 165 }
Chris@289 166
Chris@957 167 QString
Chris@957 168 IconLoader::makeScalableFilename(QString name, bool invert)
Chris@957 169 {
Chris@957 170 if (invert) {
Chris@957 171 return QString(":icons/scalable/%1_inverse.svg").arg(name);
Chris@957 172 } else {
Chris@957 173 return QString(":icons/scalable/%1.svg").arg(name);
Chris@289 174 }
Chris@957 175 }
Chris@289 176
Chris@957 177 QPixmap
Chris@957 178 IconLoader::invertPixmap(QPixmap pmap)
Chris@957 179 {
Chris@289 180 // No suitable inverted icon found for black background; try to
Chris@289 181 // auto-invert the default one
Chris@289 182
Chris@289 183 QImage img = pmap.toImage().convertToFormat(QImage::Format_ARGB32);
Chris@289 184
Chris@289 185 for (int y = 0; y < img.height(); ++y) {
Chris@289 186 for (int x = 0; x < img.width(); ++x) {
Chris@289 187
Chris@289 188 QRgb rgba = img.pixel(x, y);
Chris@289 189 QColor colour = QColor
Chris@289 190 (qRed(rgba), qGreen(rgba), qBlue(rgba), qAlpha(rgba));
Chris@289 191
Chris@289 192 int alpha = colour.alpha();
Chris@289 193 if (colour.saturation() < 5 && colour.alpha() > 10) {
Chris@289 194 colour.setHsv(colour.hue(),
Chris@289 195 colour.saturation(),
Chris@289 196 255 - colour.value());
Chris@289 197 colour.setAlpha(alpha);
Chris@289 198 img.setPixel(x, y, colour.rgba());
Chris@289 199 }
Chris@289 200 }
Chris@289 201 }
Chris@289 202
Chris@289 203 pmap = QPixmap::fromImage(img);
Chris@289 204 return pmap;
Chris@289 205 }
Chris@289 206