SingleColourLayer.cpp
Go to the documentation of this file.
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2 
3 /*
4  Sonic Visualiser
5  An audio file viewer and annotation editor.
6  Centre for Digital Music, Queen Mary, University of London.
7  This file copyright 2007 QMUL.
8 
9  This program is free software; you can redistribute it and/or
10  modify it under the terms of the GNU General Public License as
11  published by the Free Software Foundation; either version 2 of the
12  License, or (at your option) any later version. See the file
13  COPYING included with this distribution for more information.
14 */
15 
16 #include "SingleColourLayer.h"
17 #include "ColourDatabase.h"
18 #include "view/View.h"
19 
20 #include <iostream>
21 
22 #include <QTextStream>
23 #include <QApplication>
24 
25 //#define DEBUG_COLOUR_SELECTION 1
26 
29 
31  m_colour(0),
32  m_colourExplicitlySet(false),
33  m_defaultColourSet(false)
34 {
35  // Reference current colour because setDefaulColourFor
36  // will unreference it before (possibly) changing it.
37  refColor();
38  setDefaultColourFor(nullptr);
39 }
40 
42 {
43  unrefColor();
44 }
45 
46 QPixmap
48 {
50 }
51 
52 bool
54 {
56  return !dark;
57 }
58 
59 Layer::PropertyList
61 {
62  PropertyList list = Layer::getProperties();
63  list.push_back("Colour");
64  return list;
65 }
66 
67 QString
68 SingleColourLayer::getPropertyLabel(const PropertyName &name) const
69 {
70  if (name == "Colour") return tr("Colour");
71  return "";
72 }
73 
74 Layer::PropertyType
75 SingleColourLayer::getPropertyType(const PropertyName &name) const
76 {
77  if (name == "Colour") return ColourProperty;
78  return InvalidProperty;
79 }
80 
81 QString
82 SingleColourLayer::getPropertyGroupName(const PropertyName &) const
83 {
84  return QString();
85 }
86 
87 int
89  int *min, int *max, int *deflt) const
90 {
91  int val = 0;
92 
93  int garbage0, garbage1, garbage2;
94  if (!min) min = &garbage0;
95  if (!max) max = &garbage1;
96  if (!deflt) deflt = &garbage2;
97 
98  if (name == "Colour") {
99 
101  *deflt = 0;
102 
103  val = m_colour;
104 
105  } else {
106  val = Layer::getPropertyRangeAndValue(name, min, max, deflt);
107  }
108 
109  return val;
110 }
111 
112 QString
114  int value) const
115 {
116  if (name == "Colour") {
118  if (value >= 0 && value < db->getColourCount()) {
119  return db->getColourName(value);
120  }
121  }
122  return tr("<unknown>");
123 }
124 
125 RangeMapper *
127 {
128  return nullptr;
129 }
130 
131 void
132 SingleColourLayer::setProperty(const PropertyName &name, int value)
133 {
134  if (name == "Colour") {
135  setBaseColour(value);
136  }
137 }
138 
139 void
141 {
142 #ifdef DEBUG_COLOUR_SELECTION
143  SVDEBUG << "SingleColourLayer::setDefaultColourFor: m_colourExplicitlySet = " << m_colourExplicitlySet << ", m_defaultColourSet " << m_defaultColourSet << endl;
144 #endif
145 
147 
148  if (v) m_defaultColourSet = true; // v==0 case doesn't really count
149 
150  bool dark = false;
151  if (v) {
152  dark = !v->hasLightBackground();
153  } else {
154  QColor bg = QApplication::palette().color(QPalette::Window);
155  if (bg.red() + bg.green() + bg.blue() < 384) dark = true;
156  }
157 
159 
160  int hint = -1;
161  bool impose = false;
162  if (v) {
163  // We don't want to call this if !v because that probably
164  // means we're being called from the constructor, and this is
165  // a virtual function
166  hint = getDefaultColourHint(dark, impose);
167 #ifdef DEBUG_COLOUR_SELECTION
168  cerr << "hint = " << hint << ", impose = " << impose << endl;
169 #endif
170  } else {
171 #ifdef DEBUG_COLOUR_SELECTION
172  cerr << "(from ctor)" << endl;
173 #endif
174  }
175 
176  if (hint >= 0 && impose) {
177  setBaseColour(hint);
178  return;
179  }
180 
181  unrefColor();
182 
183  int bestCount = 0, bestColour = -1;
184 
185  for (int i = 0; i < cdb->getColourCount(); ++i) {
186 
187  int index = i;
188  if (hint > 0) index = (index + hint) % cdb->getColourCount();
189  if (cdb->useDarkBackground(index) != dark) continue;
190 
191  int count = 0;
192  if (m_colourRefCount.find(index) != m_colourRefCount.end()) {
193  count = m_colourRefCount[index];
194  }
195 
196 #ifdef DEBUG_COLOUR_SELECTION
197  cerr << "index = " << index << ", count = " << count;
198 #endif
199 
200  if (bestColour < 0 || count < bestCount) {
201  bestColour = index;
202  bestCount = count;
203 #ifdef DEBUG_COLOUR_SELECTION
204  cerr << " *";
205 #endif
206  }
207 
208 #ifdef DEBUG_COLOUR_SELECTION
209  cerr << endl;
210 #endif
211  }
212 
213  if (bestColour < 0) m_colour = 0;
214  else m_colour = bestColour;
215 
216  refColor();
217 }
218 
219 void
221 {
222  m_colourExplicitlySet = true;
223 
224  if (m_colour == colour) return;
225 
226  refColor();
227  m_colour = colour;
228  unrefColor();
229 
231  emit layerParametersChanged();
232 }
233 
234 int
236 {
237  return m_colour;
238 }
239 
240 QColor
242 {
244 }
245 
246 QColor
248 {
249  return v->getBackground();
250 }
251 
252 QColor
254 {
255  return v->getForeground();
256 }
257 
258 std::vector<QColor>
260 {
261  std::vector<QColor> s;
262  QColor base = getBaseQColor();
263  QColor bg = getBackgroundQColor(v);
264  for (int i = 0; i < 3; ++i) {
265  int red = base.red() + ((bg.red() - base.red()) * (i + 1)) / 4;
266  int green = base.green() + ((bg.green() - base.green()) * (i + 1)) / 4;
267  int blue = base.blue() + ((bg.blue() - base.blue()) * (i + 1)) / 4;
268  s.push_back(QColor(red, green, blue));
269  }
270  return s;
271 }
272 
273 void
274 SingleColourLayer::toXml(QTextStream &stream,
275  QString indent, QString extraAttributes) const
276 {
277  QString s;
278 
279  QString colourName, colourSpec, darkbg;
281  (m_colour, colourName, colourSpec, darkbg);
282 
283  s += QString("colourName=\"%1\" "
284  "colour=\"%2\" "
285  "darkBackground=\"%3\" ")
286  .arg(colourName)
287  .arg(colourSpec)
288  .arg(darkbg);
289 
290  Layer::toXml(stream, indent, extraAttributes + " " + s);
291 }
292 
293 void
294 SingleColourLayer::setProperties(const QXmlAttributes &attributes)
295 {
296  QString colourName = attributes.value("colourName");
297  QString colourSpec = attributes.value("colour");
298  QString darkbg = attributes.value("darkBackground");
299 
301  (colourName, colourSpec, darkbg);
302 
303  if (colour == -1)
304  return;
305 
306  m_colourExplicitlySet = true;
307 
308  if (m_colour != colour) {
309 
310 #ifdef DEBUG_COLOUR_SELECTION
311  SVDEBUG << "SingleColourLayer::setProperties: changing colour from " << m_colour << " to " << colour << endl;
312 #endif
313 
314  unrefColor();
315  m_colour = colour;
316  refColor();
317 
319  }
320 }
321 
323 {
324  if (m_colourRefCount.find(m_colour) == m_colourRefCount.end()) {
326  } else {
328  }
329 }
330 
332 {
333  if (m_colourRefCount.find(m_colour) != m_colourRefCount.end() &&
334  m_colourRefCount[m_colour] > 0) {
336  }
337 }
QString getColourName(int c) const
Return the name of the colour at index c.
virtual void flagBaseColourChanged()
virtual QColor getForeground() const =0
virtual QColor getBackground() const =0
PropertyList getProperties() const override
void toXml(QTextStream &stream, QString indent="", QString extraAttributes="") const override
Convert the layer&#39;s data (though not those of the model it refers to) into XML for file output...
Definition: Layer.cpp:653
QPixmap getLayerPresentationPixmap(QSize size) const override
QColor getColour(int c) const
Return the colour at index c.
virtual void setBaseColour(int)
Set the colour used to draw primary items in the layer.
bool useDarkBackground(int c) const
Return true if the colour at index c is marked as using a dark background.
virtual QColor getForegroundQColor(LayerGeometryProvider *v) const
void getColourPropertyRange(int *min, int *max) const
int putStringValues(QString colourName, QString colourSpec, QString darkbg)
std::vector< QColor > getPartialShades(LayerGeometryProvider *v) const
virtual QColor getBaseQColor() const
void toXml(QTextStream &stream, QString indent="", QString extraAttributes="") const override
virtual int getDefaultColourHint(bool, bool &)
Interface for classes that provide geometry information (such as size, start frame, and a large number of other properties) about the disposition of a layer.
int getColourCount() const
Return the number of colours in the database.
static ColourRefCount m_colourRefCount
QString getPropertyGroupName(const PropertyName &) const override
void layerParametersChanged()
void getStringValues(int index, QString &colourName, QString &colourSpec, QString &darkbg) const
int getPropertyRangeAndValue(const PropertyName &, int *min, int *max, int *deflt) const override
virtual void setDefaultColourFor(LayerGeometryProvider *v)
PropertyType getPropertyType(const PropertyName &) const override
void setProperties(const QXmlAttributes &attributes) override
Set the particular properties of a layer (those specific to the subclass) from a set of XML attribute...
QString getPropertyValueLabel(const PropertyName &, int value) const override
std::map< int, int > ColourRefCount
bool hasLightBackground() const override
Return true if the layer currently has a dark colour on a light background, false if it has a light c...
virtual QColor getBackgroundQColor(LayerGeometryProvider *v) const
virtual bool hasLightBackground() const =0
RangeMapper * getNewPropertyRangeMapper(const PropertyName &) const override
void setProperty(const PropertyName &, int value) override
QString getPropertyLabel(const PropertyName &) const override
virtual int getBaseColour() const
Retrieve the current primary drawing colour, as a ColourDatabase index value.
static ColourDatabase * getInstance()
QPixmap getExamplePixmap(int c, QSize size) const
Generate a swatch pixmap illustrating the colour at index c.