annotate layer/SingleColourLayer.cpp @ 561:aced8ec09bc8

* Complete the overhaul of CSV file import; now you can pick the purpose for each column in the file, and SV should do the rest. The most significant practical improvement here is that we can now handle files in which time and duration do not necessarily appear in known columns.
author Chris Cannam
date Mon, 19 Jul 2010 17:08:56 +0000
parents e1a9e478b7f2
children f4960f8ce798
rev   line source
Chris@287 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@287 2
Chris@287 3 /*
Chris@287 4 Sonic Visualiser
Chris@287 5 An audio file viewer and annotation editor.
Chris@287 6 Centre for Digital Music, Queen Mary, University of London.
Chris@287 7 This file copyright 2007 QMUL.
Chris@287 8
Chris@287 9 This program is free software; you can redistribute it and/or
Chris@287 10 modify it under the terms of the GNU General Public License as
Chris@287 11 published by the Free Software Foundation; either version 2 of the
Chris@287 12 License, or (at your option) any later version. See the file
Chris@287 13 COPYING included with this distribution for more information.
Chris@287 14 */
Chris@287 15
Chris@287 16 #include "SingleColourLayer.h"
Chris@376 17 #include "ColourDatabase.h"
Chris@287 18 #include "view/View.h"
Chris@287 19
Chris@287 20 #include <iostream>
Chris@287 21
Chris@316 22 #include <QTextStream>
Chris@287 23 #include <QApplication>
Chris@287 24
Chris@367 25 //#define DEBUG_COLOUR_SELECTION 1
Chris@367 26
Chris@293 27 SingleColourLayer::ColourRefCount
Chris@293 28 SingleColourLayer::m_colourRefCount;
Chris@287 29
Chris@287 30 SingleColourLayer::SingleColourLayer() :
Chris@294 31 m_colour(0),
Chris@366 32 m_colourExplicitlySet(false),
Chris@366 33 m_defaultColourSet(false)
Chris@287 34 {
Chris@287 35 setDefaultColourFor(0);
Chris@287 36 }
Chris@287 37
Chris@299 38 QPixmap
Chris@299 39 SingleColourLayer::getLayerPresentationPixmap(QSize size) const
Chris@299 40 {
Chris@299 41 return ColourDatabase::getInstance()->getExamplePixmap(m_colour, size);
Chris@299 42 }
Chris@299 43
Chris@287 44 bool
Chris@287 45 SingleColourLayer::hasLightBackground() const
Chris@287 46 {
Chris@287 47 bool dark = ColourDatabase::getInstance()->useDarkBackground(m_colour);
Chris@287 48 return !dark;
Chris@287 49 }
Chris@287 50
Chris@287 51 Layer::PropertyList
Chris@287 52 SingleColourLayer::getProperties() const
Chris@287 53 {
Chris@287 54 PropertyList list = Layer::getProperties();
Chris@287 55 list.push_back("Colour");
Chris@287 56 return list;
Chris@287 57 }
Chris@287 58
Chris@287 59 QString
Chris@287 60 SingleColourLayer::getPropertyLabel(const PropertyName &name) const
Chris@287 61 {
Chris@287 62 if (name == "Colour") return tr("Colour");
Chris@287 63 return "";
Chris@287 64 }
Chris@287 65
Chris@287 66 Layer::PropertyType
Chris@287 67 SingleColourLayer::getPropertyType(const PropertyName &name) const
Chris@287 68 {
Chris@287 69 if (name == "Colour") return ColourProperty;
Chris@287 70 return InvalidProperty;
Chris@287 71 }
Chris@287 72
Chris@287 73 QString
Chris@287 74 SingleColourLayer::getPropertyGroupName(const PropertyName &) const
Chris@287 75 {
Chris@287 76 return QString();
Chris@287 77 }
Chris@287 78
Chris@287 79 int
Chris@287 80 SingleColourLayer::getPropertyRangeAndValue(const PropertyName &name,
Chris@287 81 int *min, int *max, int *deflt) const
Chris@287 82 {
Chris@287 83 int val = 0;
Chris@287 84
Chris@287 85 int garbage0, garbage1, garbage2;
Chris@287 86 if (!min) min = &garbage0;
Chris@287 87 if (!max) max = &garbage1;
Chris@287 88 if (!deflt) deflt = &garbage2;
Chris@287 89
Chris@287 90 if (name == "Colour") {
Chris@287 91
Chris@287 92 ColourDatabase::getInstance()->getColourPropertyRange(min, max);
Chris@287 93 *deflt = 0; //!!!
Chris@287 94
Chris@287 95 val = m_colour;
Chris@287 96
Chris@287 97 } else {
Chris@287 98 val = Layer::getPropertyRangeAndValue(name, min, max, deflt);
Chris@287 99 }
Chris@287 100
Chris@287 101 return val;
Chris@287 102 }
Chris@287 103
Chris@287 104 QString
Chris@287 105 SingleColourLayer::getPropertyValueLabel(const PropertyName &name,
Chris@287 106 int value) const
Chris@287 107 {
Chris@287 108 if (name == "Colour") {
Chris@376 109 ColourDatabase *db = ColourDatabase::getInstance();
Chris@376 110 if (value >= 0 && size_t(value) < db->getColourCount()) {
Chris@376 111 return db->getColourName(value);
Chris@376 112 }
Chris@287 113 }
Chris@287 114 return tr("<unknown>");
Chris@287 115 }
Chris@287 116
Chris@287 117 RangeMapper *
Chris@287 118 SingleColourLayer::getNewPropertyRangeMapper(const PropertyName &) const
Chris@287 119 {
Chris@287 120 return 0;
Chris@287 121 }
Chris@287 122
Chris@287 123 void
Chris@287 124 SingleColourLayer::setProperty(const PropertyName &name, int value)
Chris@287 125 {
Chris@287 126 if (name == "Colour") {
Chris@287 127 setBaseColour(value);
Chris@287 128 }
Chris@287 129 }
Chris@287 130
Chris@287 131 void
Chris@287 132 SingleColourLayer::setDefaultColourFor(View *v)
Chris@287 133 {
Chris@367 134 #ifdef DEBUG_COLOUR_SELECTION
Chris@366 135 std::cerr << "SingleColourLayer::setDefaultColourFor: m_colourExplicitlySet = " << m_colourExplicitlySet << ", m_defaultColourSet " << m_defaultColourSet << std::endl;
Chris@367 136 #endif
Chris@366 137
Chris@366 138 if (m_colourExplicitlySet || m_defaultColourSet) return;
Chris@294 139
Chris@367 140 if (v) m_defaultColourSet = true; // v==0 case doesn't really count
Chris@367 141
Chris@287 142 bool dark = false;
Chris@287 143 if (v) {
Chris@287 144 dark = !v->hasLightBackground();
Chris@287 145 } else {
Chris@287 146 QColor bg = QApplication::palette().color(QPalette::Window);
Chris@287 147 if (bg.red() + bg.green() + bg.blue() < 384) dark = true;
Chris@287 148 }
Chris@287 149
Chris@287 150 ColourDatabase *cdb = ColourDatabase::getInstance();
Chris@287 151
Chris@287 152 int hint = -1;
Chris@287 153 bool impose = false;
Chris@287 154 if (v) {
Chris@293 155 if (m_colourRefCount.find(m_colour) != m_colourRefCount.end() &&
Chris@293 156 m_colourRefCount[m_colour] > 0) {
Chris@293 157 m_colourRefCount[m_colour]--;
Chris@293 158 }
Chris@287 159 // We don't want to call this if !v because that probably
Chris@287 160 // means we're being called from the constructor, and this is
Chris@287 161 // a virtual function
Chris@287 162 hint = getDefaultColourHint(dark, impose);
Chris@367 163 #ifdef DEBUG_COLOUR_SELECTION
Chris@367 164 std::cerr << "hint = " << hint << ", impose = " << impose << std::endl;
Chris@367 165 #endif
Chris@293 166 } else {
Chris@367 167 #ifdef DEBUG_COLOUR_SELECTION
Chris@367 168 std::cerr << "(from ctor)" << std::endl;
Chris@367 169 #endif
Chris@287 170 }
Chris@287 171
Chris@287 172 if (hint >= 0 && impose) {
Chris@293 173 setBaseColour(hint);
Chris@287 174 return;
Chris@287 175 }
Chris@287 176
Chris@293 177 int bestCount = 0, bestColour = -1;
Chris@293 178
Chris@287 179 for (int i = 0; i < cdb->getColourCount(); ++i) {
Chris@293 180
Chris@287 181 int index = i;
Chris@287 182 if (hint > 0) index = (index + hint) % cdb->getColourCount();
Chris@287 183 if (cdb->useDarkBackground(index) != dark) continue;
Chris@293 184
Chris@293 185 int count = 0;
Chris@293 186 if (m_colourRefCount.find(index) != m_colourRefCount.end()) {
Chris@293 187 count = m_colourRefCount[index];
Chris@287 188 }
Chris@293 189
Chris@367 190 #ifdef DEBUG_COLOUR_SELECTION
Chris@367 191 std::cerr << "index = " << index << ", count = " << count;
Chris@367 192 #endif
Chris@293 193
Chris@293 194 if (bestColour < 0 || count < bestCount) {
Chris@293 195 bestColour = index;
Chris@293 196 bestCount = count;
Chris@367 197 #ifdef DEBUG_COLOUR_SELECTION
Chris@367 198 std::cerr << " *";
Chris@367 199 #endif
Chris@293 200 }
Chris@293 201
Chris@367 202 #ifdef DEBUG_COLOUR_SELECTION
Chris@367 203 std::cerr << std::endl;
Chris@367 204 #endif
Chris@287 205 }
Chris@293 206
Chris@293 207 if (bestColour < 0) m_colour = 0;
Chris@293 208 else m_colour = bestColour;
Chris@287 209
Chris@293 210 if (m_colourRefCount.find(m_colour) == m_colourRefCount.end()) {
Chris@293 211 m_colourRefCount[m_colour] = 1;
Chris@293 212 } else {
Chris@293 213 m_colourRefCount[m_colour]++;
Chris@293 214 }
Chris@287 215 }
Chris@287 216
Chris@287 217 void
Chris@287 218 SingleColourLayer::setBaseColour(int colour)
Chris@287 219 {
Chris@294 220 m_colourExplicitlySet = true;
Chris@294 221
Chris@287 222 if (m_colour == colour) return;
Chris@293 223
Chris@293 224 if (m_colourRefCount.find(m_colour) != m_colourRefCount.end() &&
Chris@293 225 m_colourRefCount[m_colour] > 0) {
Chris@293 226 m_colourRefCount[m_colour]--;
Chris@293 227 }
Chris@293 228
Chris@287 229 m_colour = colour;
Chris@293 230
Chris@293 231 if (m_colourRefCount.find(m_colour) == m_colourRefCount.end()) {
Chris@293 232 m_colourRefCount[m_colour] = 1;
Chris@293 233 } else {
Chris@293 234 m_colourRefCount[m_colour]++;
Chris@293 235 }
Chris@293 236
Chris@287 237 flagBaseColourChanged();
Chris@287 238 emit layerParametersChanged();
Chris@287 239 }
Chris@287 240
Chris@287 241 int
Chris@287 242 SingleColourLayer::getBaseColour() const
Chris@287 243 {
Chris@287 244 return m_colour;
Chris@287 245 }
Chris@287 246
Chris@287 247 QColor
Chris@287 248 SingleColourLayer::getBaseQColor() const
Chris@287 249 {
Chris@287 250 return ColourDatabase::getInstance()->getColour(m_colour);
Chris@287 251 }
Chris@287 252
Chris@287 253 QColor
Chris@287 254 SingleColourLayer::getBackgroundQColor(View *v) const
Chris@287 255 {
Chris@287 256 return v->getBackground();
Chris@287 257 }
Chris@287 258
Chris@287 259 QColor
Chris@287 260 SingleColourLayer::getForegroundQColor(View *v) const
Chris@287 261 {
Chris@287 262 return v->getForeground();
Chris@287 263 }
Chris@287 264
Chris@287 265 std::vector<QColor>
Chris@287 266 SingleColourLayer::getPartialShades(View *v) const
Chris@287 267 {
Chris@287 268 std::vector<QColor> s;
Chris@287 269 QColor base = getBaseQColor();
Chris@287 270 QColor bg = getBackgroundQColor(v);
Chris@287 271 for (int i = 0; i < 3; ++i) {
Chris@287 272 int red = base.red() + ((bg.red() - base.red()) * (i + 1)) / 4;
Chris@287 273 int green = base.green() + ((bg.green() - base.green()) * (i + 1)) / 4;
Chris@287 274 int blue = base.blue() + ((bg.blue() - base.blue()) * (i + 1)) / 4;
Chris@287 275 s.push_back(QColor(red, green, blue));
Chris@287 276 }
Chris@287 277 return s;
Chris@287 278 }
Chris@287 279
Chris@316 280 void
Chris@316 281 SingleColourLayer::toXml(QTextStream &stream,
Chris@316 282 QString indent, QString extraAttributes) const
Chris@287 283 {
Chris@287 284 QString s;
Chris@287 285
Chris@287 286 QString colourName, colourSpec, darkbg;
Chris@287 287 ColourDatabase::getInstance()->getStringValues
Chris@287 288 (m_colour, colourName, colourSpec, darkbg);
Chris@287 289
Chris@287 290 s += QString("colourName=\"%1\" "
Chris@287 291 "colour=\"%2\" "
Chris@287 292 "darkBackground=\"%3\" ")
Chris@287 293 .arg(colourName)
Chris@287 294 .arg(colourSpec)
Chris@287 295 .arg(darkbg);
Chris@287 296
Chris@316 297 Layer::toXml(stream, indent, extraAttributes + " " + s);
Chris@287 298 }
Chris@287 299
Chris@287 300 void
Chris@287 301 SingleColourLayer::setProperties(const QXmlAttributes &attributes)
Chris@287 302 {
Chris@287 303 QString colourName = attributes.value("colourName");
Chris@287 304 QString colourSpec = attributes.value("colour");
Chris@287 305 QString darkbg = attributes.value("darkBackground");
Chris@296 306
Chris@296 307 int colour = ColourDatabase::getInstance()->putStringValues
Chris@287 308 (colourName, colourSpec, darkbg);
Chris@296 309
Chris@296 310 m_colourExplicitlySet = true;
Chris@296 311
Chris@296 312 if (m_colour != colour) {
Chris@296 313
Chris@367 314 #ifdef DEBUG_COLOUR_SELECTION
Chris@296 315 std::cerr << "SingleColourLayer::setProperties: changing colour from " << m_colour << " to " << colour << std::endl;
Chris@367 316 #endif
Chris@296 317
Chris@296 318 if (m_colourRefCount.find(m_colour) != m_colourRefCount.end() &&
Chris@296 319 m_colourRefCount[m_colour] > 0) {
Chris@296 320 m_colourRefCount[m_colour]--;
Chris@296 321 }
Chris@296 322
Chris@296 323 m_colour = colour;
Chris@296 324
Chris@296 325 if (m_colourRefCount.find(m_colour) == m_colourRefCount.end()) {
Chris@296 326 m_colourRefCount[m_colour] = 1;
Chris@296 327 } else {
Chris@296 328 m_colourRefCount[m_colour]++;
Chris@296 329 }
Chris@296 330
Chris@296 331 flagBaseColourChanged();
Chris@294 332 }
Chris@287 333 }
Chris@287 334