annotate layer/SingleColourLayer.cpp @ 349:369a197737c7

* Various fixes to object lifetime management, particularly in the spectrum layer and for notification of main model deletion. The main purpose of this is to improve the behaviour of the spectrum, but I think it may also help with #1840922 Various crashes in Layer Summary window.
author Chris Cannam
date Wed, 23 Jan 2008 15:43:27 +0000
parents c0b9eec70639
children a55affd7ab6c 0895517bb2d1
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@287 17 #include "base/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@293 25 SingleColourLayer::ColourRefCount
Chris@293 26 SingleColourLayer::m_colourRefCount;
Chris@287 27
Chris@287 28 SingleColourLayer::SingleColourLayer() :
Chris@294 29 m_colour(0),
Chris@294 30 m_colourExplicitlySet(false)
Chris@287 31 {
Chris@287 32 setDefaultColourFor(0);
Chris@287 33 }
Chris@287 34
Chris@299 35 QPixmap
Chris@299 36 SingleColourLayer::getLayerPresentationPixmap(QSize size) const
Chris@299 37 {
Chris@299 38 return ColourDatabase::getInstance()->getExamplePixmap(m_colour, size);
Chris@299 39 }
Chris@299 40
Chris@287 41 bool
Chris@287 42 SingleColourLayer::hasLightBackground() const
Chris@287 43 {
Chris@287 44 bool dark = ColourDatabase::getInstance()->useDarkBackground(m_colour);
Chris@287 45 return !dark;
Chris@287 46 }
Chris@287 47
Chris@287 48 Layer::PropertyList
Chris@287 49 SingleColourLayer::getProperties() const
Chris@287 50 {
Chris@287 51 PropertyList list = Layer::getProperties();
Chris@287 52 list.push_back("Colour");
Chris@287 53 return list;
Chris@287 54 }
Chris@287 55
Chris@287 56 QString
Chris@287 57 SingleColourLayer::getPropertyLabel(const PropertyName &name) const
Chris@287 58 {
Chris@287 59 if (name == "Colour") return tr("Colour");
Chris@287 60 return "";
Chris@287 61 }
Chris@287 62
Chris@287 63 Layer::PropertyType
Chris@287 64 SingleColourLayer::getPropertyType(const PropertyName &name) const
Chris@287 65 {
Chris@287 66 if (name == "Colour") return ColourProperty;
Chris@287 67 return InvalidProperty;
Chris@287 68 }
Chris@287 69
Chris@287 70 QString
Chris@287 71 SingleColourLayer::getPropertyGroupName(const PropertyName &) const
Chris@287 72 {
Chris@287 73 return QString();
Chris@287 74 }
Chris@287 75
Chris@287 76 int
Chris@287 77 SingleColourLayer::getPropertyRangeAndValue(const PropertyName &name,
Chris@287 78 int *min, int *max, int *deflt) const
Chris@287 79 {
Chris@287 80 int val = 0;
Chris@287 81
Chris@287 82 int garbage0, garbage1, garbage2;
Chris@287 83 if (!min) min = &garbage0;
Chris@287 84 if (!max) max = &garbage1;
Chris@287 85 if (!deflt) deflt = &garbage2;
Chris@287 86
Chris@287 87 if (name == "Colour") {
Chris@287 88
Chris@287 89 ColourDatabase::getInstance()->getColourPropertyRange(min, max);
Chris@287 90 *deflt = 0; //!!!
Chris@287 91
Chris@287 92 val = m_colour;
Chris@287 93
Chris@287 94 } else {
Chris@287 95 val = Layer::getPropertyRangeAndValue(name, min, max, deflt);
Chris@287 96 }
Chris@287 97
Chris@287 98 return val;
Chris@287 99 }
Chris@287 100
Chris@287 101 QString
Chris@287 102 SingleColourLayer::getPropertyValueLabel(const PropertyName &name,
Chris@287 103 int value) const
Chris@287 104 {
Chris@287 105 if (name == "Colour") {
Chris@287 106 return Layer::getPropertyValueLabel(name, value);
Chris@287 107 }
Chris@287 108 return tr("<unknown>");
Chris@287 109 }
Chris@287 110
Chris@287 111 RangeMapper *
Chris@287 112 SingleColourLayer::getNewPropertyRangeMapper(const PropertyName &) const
Chris@287 113 {
Chris@287 114 return 0;
Chris@287 115 }
Chris@287 116
Chris@287 117 void
Chris@287 118 SingleColourLayer::setProperty(const PropertyName &name, int value)
Chris@287 119 {
Chris@287 120 if (name == "Colour") {
Chris@287 121 setBaseColour(value);
Chris@287 122 }
Chris@287 123 }
Chris@287 124
Chris@287 125 void
Chris@287 126 SingleColourLayer::setDefaultColourFor(View *v)
Chris@287 127 {
Chris@294 128 if (m_colourExplicitlySet) return;
Chris@294 129
Chris@287 130 bool dark = false;
Chris@287 131 if (v) {
Chris@287 132 dark = !v->hasLightBackground();
Chris@287 133 } else {
Chris@287 134 QColor bg = QApplication::palette().color(QPalette::Window);
Chris@287 135 if (bg.red() + bg.green() + bg.blue() < 384) dark = true;
Chris@287 136 }
Chris@287 137
Chris@287 138 ColourDatabase *cdb = ColourDatabase::getInstance();
Chris@287 139
Chris@287 140 int hint = -1;
Chris@287 141 bool impose = false;
Chris@287 142 if (v) {
Chris@293 143 if (m_colourRefCount.find(m_colour) != m_colourRefCount.end() &&
Chris@293 144 m_colourRefCount[m_colour] > 0) {
Chris@293 145 m_colourRefCount[m_colour]--;
Chris@293 146 }
Chris@287 147 // We don't want to call this if !v because that probably
Chris@287 148 // means we're being called from the constructor, and this is
Chris@287 149 // a virtual function
Chris@287 150 hint = getDefaultColourHint(dark, impose);
Chris@297 151 // std::cerr << "hint = " << hint << ", impose = " << impose << std::endl;
Chris@293 152 } else {
Chris@297 153 // std::cerr << "(from ctor)" << std::endl;
Chris@287 154 }
Chris@287 155
Chris@287 156 if (hint >= 0 && impose) {
Chris@293 157 setBaseColour(hint);
Chris@287 158 return;
Chris@287 159 }
Chris@287 160
Chris@293 161 int bestCount = 0, bestColour = -1;
Chris@293 162
Chris@287 163 for (int i = 0; i < cdb->getColourCount(); ++i) {
Chris@293 164
Chris@287 165 int index = i;
Chris@287 166 if (hint > 0) index = (index + hint) % cdb->getColourCount();
Chris@287 167 if (cdb->useDarkBackground(index) != dark) continue;
Chris@293 168
Chris@293 169 int count = 0;
Chris@293 170 if (m_colourRefCount.find(index) != m_colourRefCount.end()) {
Chris@293 171 count = m_colourRefCount[index];
Chris@287 172 }
Chris@293 173
Chris@297 174 // std::cerr << "index = " << index << ", count = " << count;
Chris@293 175
Chris@293 176 if (bestColour < 0 || count < bestCount) {
Chris@293 177 bestColour = index;
Chris@293 178 bestCount = count;
Chris@297 179 // std::cerr << " *";
Chris@293 180 }
Chris@293 181
Chris@297 182 // std::cerr << std::endl;
Chris@287 183 }
Chris@293 184
Chris@293 185 if (bestColour < 0) m_colour = 0;
Chris@293 186 else m_colour = bestColour;
Chris@287 187
Chris@293 188 if (m_colourRefCount.find(m_colour) == m_colourRefCount.end()) {
Chris@293 189 m_colourRefCount[m_colour] = 1;
Chris@293 190 } else {
Chris@293 191 m_colourRefCount[m_colour]++;
Chris@293 192 }
Chris@287 193 }
Chris@287 194
Chris@287 195 void
Chris@287 196 SingleColourLayer::setBaseColour(int colour)
Chris@287 197 {
Chris@294 198 m_colourExplicitlySet = true;
Chris@294 199
Chris@287 200 if (m_colour == colour) return;
Chris@293 201
Chris@293 202 if (m_colourRefCount.find(m_colour) != m_colourRefCount.end() &&
Chris@293 203 m_colourRefCount[m_colour] > 0) {
Chris@293 204 m_colourRefCount[m_colour]--;
Chris@293 205 }
Chris@293 206
Chris@287 207 m_colour = colour;
Chris@293 208
Chris@293 209 if (m_colourRefCount.find(m_colour) == m_colourRefCount.end()) {
Chris@293 210 m_colourRefCount[m_colour] = 1;
Chris@293 211 } else {
Chris@293 212 m_colourRefCount[m_colour]++;
Chris@293 213 }
Chris@293 214
Chris@287 215 flagBaseColourChanged();
Chris@287 216 emit layerParametersChanged();
Chris@287 217 }
Chris@287 218
Chris@287 219 int
Chris@287 220 SingleColourLayer::getBaseColour() const
Chris@287 221 {
Chris@287 222 return m_colour;
Chris@287 223 }
Chris@287 224
Chris@287 225 QColor
Chris@287 226 SingleColourLayer::getBaseQColor() const
Chris@287 227 {
Chris@287 228 return ColourDatabase::getInstance()->getColour(m_colour);
Chris@287 229 }
Chris@287 230
Chris@287 231 QColor
Chris@287 232 SingleColourLayer::getBackgroundQColor(View *v) const
Chris@287 233 {
Chris@287 234 return v->getBackground();
Chris@287 235 }
Chris@287 236
Chris@287 237 QColor
Chris@287 238 SingleColourLayer::getForegroundQColor(View *v) const
Chris@287 239 {
Chris@287 240 return v->getForeground();
Chris@287 241 }
Chris@287 242
Chris@287 243 std::vector<QColor>
Chris@287 244 SingleColourLayer::getPartialShades(View *v) const
Chris@287 245 {
Chris@287 246 std::vector<QColor> s;
Chris@287 247 QColor base = getBaseQColor();
Chris@287 248 QColor bg = getBackgroundQColor(v);
Chris@287 249 for (int i = 0; i < 3; ++i) {
Chris@287 250 int red = base.red() + ((bg.red() - base.red()) * (i + 1)) / 4;
Chris@287 251 int green = base.green() + ((bg.green() - base.green()) * (i + 1)) / 4;
Chris@287 252 int blue = base.blue() + ((bg.blue() - base.blue()) * (i + 1)) / 4;
Chris@287 253 s.push_back(QColor(red, green, blue));
Chris@287 254 }
Chris@287 255 return s;
Chris@287 256 }
Chris@287 257
Chris@316 258 void
Chris@316 259 SingleColourLayer::toXml(QTextStream &stream,
Chris@316 260 QString indent, QString extraAttributes) const
Chris@287 261 {
Chris@287 262 QString s;
Chris@287 263
Chris@287 264 QString colourName, colourSpec, darkbg;
Chris@287 265 ColourDatabase::getInstance()->getStringValues
Chris@287 266 (m_colour, colourName, colourSpec, darkbg);
Chris@287 267
Chris@287 268 s += QString("colourName=\"%1\" "
Chris@287 269 "colour=\"%2\" "
Chris@287 270 "darkBackground=\"%3\" ")
Chris@287 271 .arg(colourName)
Chris@287 272 .arg(colourSpec)
Chris@287 273 .arg(darkbg);
Chris@287 274
Chris@316 275 Layer::toXml(stream, indent, extraAttributes + " " + s);
Chris@287 276 }
Chris@287 277
Chris@287 278 void
Chris@287 279 SingleColourLayer::setProperties(const QXmlAttributes &attributes)
Chris@287 280 {
Chris@287 281 QString colourName = attributes.value("colourName");
Chris@287 282 QString colourSpec = attributes.value("colour");
Chris@287 283 QString darkbg = attributes.value("darkBackground");
Chris@296 284
Chris@296 285 int colour = ColourDatabase::getInstance()->putStringValues
Chris@287 286 (colourName, colourSpec, darkbg);
Chris@296 287
Chris@296 288 m_colourExplicitlySet = true;
Chris@296 289
Chris@296 290 if (m_colour != colour) {
Chris@296 291
Chris@296 292 std::cerr << "SingleColourLayer::setProperties: changing colour from " << m_colour << " to " << colour << std::endl;
Chris@296 293
Chris@296 294 if (m_colourRefCount.find(m_colour) != m_colourRefCount.end() &&
Chris@296 295 m_colourRefCount[m_colour] > 0) {
Chris@296 296 m_colourRefCount[m_colour]--;
Chris@296 297 }
Chris@296 298
Chris@296 299 m_colour = colour;
Chris@296 300
Chris@296 301 if (m_colourRefCount.find(m_colour) == m_colourRefCount.end()) {
Chris@296 302 m_colourRefCount[m_colour] = 1;
Chris@296 303 } else {
Chris@296 304 m_colourRefCount[m_colour]++;
Chris@296 305 }
Chris@296 306
Chris@296 307 flagBaseColourChanged();
Chris@294 308 }
Chris@287 309 }
Chris@287 310