Chris@287: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@287: Chris@287: /* Chris@287: Sonic Visualiser Chris@287: An audio file viewer and annotation editor. Chris@287: Centre for Digital Music, Queen Mary, University of London. Chris@287: This file copyright 2007 QMUL. Chris@287: Chris@287: This program is free software; you can redistribute it and/or Chris@287: modify it under the terms of the GNU General Public License as Chris@287: published by the Free Software Foundation; either version 2 of the Chris@287: License, or (at your option) any later version. See the file Chris@287: COPYING included with this distribution for more information. Chris@287: */ Chris@287: Chris@287: #include "SingleColourLayer.h" Chris@376: #include "ColourDatabase.h" Chris@287: #include "view/View.h" Chris@287: Chris@287: #include Chris@287: Chris@316: #include Chris@287: #include Chris@287: Chris@367: //#define DEBUG_COLOUR_SELECTION 1 Chris@367: Chris@293: SingleColourLayer::ColourRefCount Chris@293: SingleColourLayer::m_colourRefCount; Chris@287: Chris@287: SingleColourLayer::SingleColourLayer() : Chris@294: m_colour(0), Chris@366: m_colourExplicitlySet(false), Chris@366: m_defaultColourSet(false) Chris@287: { jakob@768: // Reference current colour because setDefaulColourFor jakob@768: // will unreference it before (possibly) changing it. jakob@768: refColor(); Chris@1408: setDefaultColourFor(nullptr); Chris@287: } Chris@287: jakob@768: SingleColourLayer::~SingleColourLayer() jakob@768: { jakob@768: unrefColor(); jakob@768: } jakob@768: Chris@299: QPixmap Chris@299: SingleColourLayer::getLayerPresentationPixmap(QSize size) const Chris@299: { Chris@299: return ColourDatabase::getInstance()->getExamplePixmap(m_colour, size); Chris@299: } Chris@299: Chris@287: bool Chris@287: SingleColourLayer::hasLightBackground() const Chris@287: { Chris@287: bool dark = ColourDatabase::getInstance()->useDarkBackground(m_colour); Chris@287: return !dark; Chris@287: } Chris@287: Chris@287: Layer::PropertyList Chris@287: SingleColourLayer::getProperties() const Chris@287: { Chris@287: PropertyList list = Layer::getProperties(); Chris@287: list.push_back("Colour"); Chris@287: return list; Chris@287: } Chris@287: Chris@287: QString Chris@287: SingleColourLayer::getPropertyLabel(const PropertyName &name) const Chris@287: { Chris@287: if (name == "Colour") return tr("Colour"); Chris@287: return ""; Chris@287: } Chris@287: Chris@287: Layer::PropertyType Chris@287: SingleColourLayer::getPropertyType(const PropertyName &name) const Chris@287: { Chris@287: if (name == "Colour") return ColourProperty; Chris@287: return InvalidProperty; Chris@287: } Chris@287: Chris@287: QString Chris@287: SingleColourLayer::getPropertyGroupName(const PropertyName &) const Chris@287: { Chris@287: return QString(); Chris@287: } Chris@287: Chris@287: int Chris@287: SingleColourLayer::getPropertyRangeAndValue(const PropertyName &name, Chris@287: int *min, int *max, int *deflt) const Chris@287: { Chris@287: int val = 0; Chris@287: Chris@287: int garbage0, garbage1, garbage2; Chris@287: if (!min) min = &garbage0; Chris@287: if (!max) max = &garbage1; Chris@287: if (!deflt) deflt = &garbage2; Chris@287: Chris@287: if (name == "Colour") { Chris@287: Chris@287: ColourDatabase::getInstance()->getColourPropertyRange(min, max); Chris@287: *deflt = 0; //!!! Chris@287: Chris@287: val = m_colour; Chris@287: Chris@287: } else { Chris@1266: val = Layer::getPropertyRangeAndValue(name, min, max, deflt); Chris@287: } Chris@287: Chris@287: return val; Chris@287: } Chris@287: Chris@287: QString Chris@287: SingleColourLayer::getPropertyValueLabel(const PropertyName &name, Chris@1266: int value) const Chris@287: { Chris@287: if (name == "Colour") { Chris@376: ColourDatabase *db = ColourDatabase::getInstance(); Chris@805: if (value >= 0 && value < db->getColourCount()) { Chris@376: return db->getColourName(value); Chris@376: } Chris@287: } Chris@287: return tr(""); Chris@287: } Chris@287: Chris@287: RangeMapper * Chris@287: SingleColourLayer::getNewPropertyRangeMapper(const PropertyName &) const Chris@287: { Chris@1408: return nullptr; Chris@287: } Chris@287: Chris@287: void Chris@287: SingleColourLayer::setProperty(const PropertyName &name, int value) Chris@287: { Chris@287: if (name == "Colour") { Chris@287: setBaseColour(value); Chris@287: } Chris@287: } Chris@287: Chris@287: void Chris@919: SingleColourLayer::setDefaultColourFor(LayerGeometryProvider *v) Chris@287: { Chris@367: #ifdef DEBUG_COLOUR_SELECTION Chris@587: SVDEBUG << "SingleColourLayer::setDefaultColourFor: m_colourExplicitlySet = " << m_colourExplicitlySet << ", m_defaultColourSet " << m_defaultColourSet << endl; Chris@367: #endif Chris@366: Chris@366: if (m_colourExplicitlySet || m_defaultColourSet) return; Chris@294: Chris@367: if (v) m_defaultColourSet = true; // v==0 case doesn't really count Chris@367: Chris@287: bool dark = false; Chris@287: if (v) { Chris@287: dark = !v->hasLightBackground(); Chris@287: } else { Chris@287: QColor bg = QApplication::palette().color(QPalette::Window); Chris@287: if (bg.red() + bg.green() + bg.blue() < 384) dark = true; Chris@287: } Chris@287: Chris@287: ColourDatabase *cdb = ColourDatabase::getInstance(); Chris@287: Chris@287: int hint = -1; Chris@287: bool impose = false; Chris@287: if (v) { Chris@287: // We don't want to call this if !v because that probably Chris@287: // means we're being called from the constructor, and this is Chris@287: // a virtual function Chris@287: hint = getDefaultColourHint(dark, impose); Chris@367: #ifdef DEBUG_COLOUR_SELECTION Chris@682: cerr << "hint = " << hint << ", impose = " << impose << endl; Chris@367: #endif Chris@293: } else { Chris@367: #ifdef DEBUG_COLOUR_SELECTION Chris@682: cerr << "(from ctor)" << endl; Chris@367: #endif Chris@287: } Chris@287: Chris@287: if (hint >= 0 && impose) { Chris@293: setBaseColour(hint); Chris@287: return; Chris@287: } Chris@287: jakob@768: unrefColor(); jakob@768: Chris@293: int bestCount = 0, bestColour = -1; Chris@293: Chris@287: for (int i = 0; i < cdb->getColourCount(); ++i) { Chris@293: Chris@287: int index = i; Chris@287: if (hint > 0) index = (index + hint) % cdb->getColourCount(); Chris@287: if (cdb->useDarkBackground(index) != dark) continue; Chris@293: Chris@293: int count = 0; Chris@293: if (m_colourRefCount.find(index) != m_colourRefCount.end()) { Chris@293: count = m_colourRefCount[index]; Chris@287: } Chris@293: Chris@367: #ifdef DEBUG_COLOUR_SELECTION Chris@682: cerr << "index = " << index << ", count = " << count; Chris@367: #endif Chris@293: Chris@293: if (bestColour < 0 || count < bestCount) { Chris@293: bestColour = index; Chris@293: bestCount = count; Chris@367: #ifdef DEBUG_COLOUR_SELECTION Chris@682: cerr << " *"; Chris@367: #endif Chris@293: } Chris@293: Chris@367: #ifdef DEBUG_COLOUR_SELECTION Chris@682: cerr << endl; Chris@367: #endif Chris@287: } jakob@768: Chris@293: if (bestColour < 0) m_colour = 0; Chris@293: else m_colour = bestColour; Chris@287: jakob@768: refColor(); Chris@287: } Chris@287: Chris@287: void Chris@287: SingleColourLayer::setBaseColour(int colour) Chris@287: { Chris@294: m_colourExplicitlySet = true; Chris@294: Chris@287: if (m_colour == colour) return; Chris@293: jakob@768: refColor(); Chris@287: m_colour = colour; jakob@768: unrefColor(); Chris@293: Chris@287: flagBaseColourChanged(); Chris@287: emit layerParametersChanged(); Chris@287: } Chris@287: Chris@287: int Chris@287: SingleColourLayer::getBaseColour() const Chris@287: { Chris@287: return m_colour; Chris@287: } Chris@287: Chris@287: QColor Chris@287: SingleColourLayer::getBaseQColor() const Chris@287: { Chris@287: return ColourDatabase::getInstance()->getColour(m_colour); Chris@287: } Chris@287: Chris@287: QColor Chris@919: SingleColourLayer::getBackgroundQColor(LayerGeometryProvider *v) const Chris@287: { Chris@287: return v->getBackground(); Chris@287: } Chris@287: Chris@287: QColor Chris@919: SingleColourLayer::getForegroundQColor(LayerGeometryProvider *v) const Chris@287: { Chris@287: return v->getForeground(); Chris@287: } Chris@287: Chris@287: std::vector Chris@919: SingleColourLayer::getPartialShades(LayerGeometryProvider *v) const Chris@287: { Chris@287: std::vector s; Chris@287: QColor base = getBaseQColor(); Chris@287: QColor bg = getBackgroundQColor(v); Chris@287: for (int i = 0; i < 3; ++i) { Chris@287: int red = base.red() + ((bg.red() - base.red()) * (i + 1)) / 4; Chris@287: int green = base.green() + ((bg.green() - base.green()) * (i + 1)) / 4; Chris@287: int blue = base.blue() + ((bg.blue() - base.blue()) * (i + 1)) / 4; Chris@287: s.push_back(QColor(red, green, blue)); Chris@287: } Chris@287: return s; Chris@287: } Chris@287: Chris@316: void Chris@316: SingleColourLayer::toXml(QTextStream &stream, Chris@316: QString indent, QString extraAttributes) const Chris@287: { Chris@287: QString s; Chris@287: Chris@287: QString colourName, colourSpec, darkbg; Chris@287: ColourDatabase::getInstance()->getStringValues Chris@287: (m_colour, colourName, colourSpec, darkbg); Chris@287: Chris@287: s += QString("colourName=\"%1\" " Chris@287: "colour=\"%2\" " Chris@287: "darkBackground=\"%3\" ") Chris@1266: .arg(colourName) Chris@287: .arg(colourSpec) Chris@287: .arg(darkbg); Chris@287: Chris@316: Layer::toXml(stream, indent, extraAttributes + " " + s); Chris@287: } Chris@287: Chris@287: void Chris@287: SingleColourLayer::setProperties(const QXmlAttributes &attributes) Chris@287: { Chris@287: QString colourName = attributes.value("colourName"); Chris@287: QString colourSpec = attributes.value("colour"); Chris@287: QString darkbg = attributes.value("darkBackground"); Chris@296: Chris@296: int colour = ColourDatabase::getInstance()->putStringValues Chris@287: (colourName, colourSpec, darkbg); Chris@296: jakob@767: if (colour == -1) jakob@767: return; jakob@767: Chris@296: m_colourExplicitlySet = true; Chris@296: Chris@296: if (m_colour != colour) { Chris@296: Chris@367: #ifdef DEBUG_COLOUR_SELECTION Chris@587: SVDEBUG << "SingleColourLayer::setProperties: changing colour from " << m_colour << " to " << colour << endl; Chris@367: #endif Chris@296: jakob@768: unrefColor(); Chris@296: m_colour = colour; jakob@768: refColor(); Chris@296: Chris@296: flagBaseColourChanged(); Chris@294: } Chris@287: } Chris@287: jakob@768: void SingleColourLayer::refColor() jakob@768: { jakob@768: if (m_colourRefCount.find(m_colour) == m_colourRefCount.end()) { jakob@768: m_colourRefCount[m_colour] = 1; jakob@768: } else { jakob@768: m_colourRefCount[m_colour]++; jakob@768: } jakob@768: } jakob@768: jakob@768: void SingleColourLayer::unrefColor() jakob@768: { jakob@768: if (m_colourRefCount.find(m_colour) != m_colourRefCount.end() && jakob@768: m_colourRefCount[m_colour] > 0) { jakob@768: m_colourRefCount[m_colour]--; jakob@768: } jakob@768: }