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@587
|
135 SVDEBUG << "SingleColourLayer::setDefaultColourFor: m_colourExplicitlySet = " << m_colourExplicitlySet << ", m_defaultColourSet " << m_defaultColourSet << 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@682
|
164 cerr << "hint = " << hint << ", impose = " << impose << endl;
|
Chris@367
|
165 #endif
|
Chris@293
|
166 } else {
|
Chris@367
|
167 #ifdef DEBUG_COLOUR_SELECTION
|
Chris@682
|
168 cerr << "(from ctor)" << 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@682
|
191 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@682
|
198 cerr << " *";
|
Chris@367
|
199 #endif
|
Chris@293
|
200 }
|
Chris@293
|
201
|
Chris@367
|
202 #ifdef DEBUG_COLOUR_SELECTION
|
Chris@682
|
203 cerr << 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@587
|
315 SVDEBUG << "SingleColourLayer::setProperties: changing colour from " << m_colour << " to " << colour << 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
|