Chris@49: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@0: Chris@0: /* Chris@52: Sonic Visualiser Chris@52: An audio file viewer and annotation editor. Chris@52: Centre for Digital Music, Queen Mary, University of London. Chris@202: This file copyright 2006 Chris Cannam and QMUL. Chris@0: Chris@52: This program is free software; you can redistribute it and/or Chris@52: modify it under the terms of the GNU General Public License as Chris@52: published by the Free Software Foundation; either version 2 of the Chris@52: License, or (at your option) any later version. See the file Chris@52: COPYING included with this distribution for more information. Chris@0: */ Chris@0: Chris@0: #include "PropertyContainer.h" Chris@199: #include "RangeMapper.h" Chris@199: #include "UnitDatabase.h" Chris@46: Chris@46: #include Chris@0: Chris@0: PropertyContainer::PropertyList Chris@0: PropertyContainer::getProperties() const Chris@0: { Chris@0: return PropertyList(); Chris@0: } Chris@0: Chris@0: PropertyContainer::PropertyType Chris@0: PropertyContainer::getPropertyType(const PropertyName &) const Chris@0: { Chris@0: return InvalidProperty; Chris@0: } Chris@0: Chris@0: QString Chris@340: PropertyContainer::getPropertyIconName(const PropertyName &) const Chris@340: { Chris@340: return QString(); Chris@340: } Chris@340: Chris@340: QString Chris@0: PropertyContainer::getPropertyGroupName(const PropertyName &) const Chris@0: { Chris@0: return QString(); Chris@0: } Chris@0: Chris@0: int Chris@245: PropertyContainer::getPropertyRangeAndValue(const PropertyName &, Chris@245: int *min, int *max, int *deflt) const Chris@0: { Chris@0: if (min) *min = 0; Chris@0: if (max) *max = 0; Chris@245: if (deflt) *deflt = 0; Chris@0: return 0; Chris@0: } Chris@0: Chris@0: QString Chris@928: PropertyContainer::getPropertyValueLabel(const PropertyName &, int) const Chris@0: { Chris@0: return QString(); Chris@0: } Chris@0: Chris@984: QString Chris@984: PropertyContainer::getPropertyValueIconName(const PropertyName &, int) const Chris@984: { Chris@984: return QString(); Chris@984: } Chris@984: Chris@190: RangeMapper * Chris@190: PropertyContainer::getNewPropertyRangeMapper(const PropertyName &) const Chris@190: { Chris@1582: return nullptr; Chris@190: } Chris@190: Chris@0: void Chris@46: PropertyContainer::setProperty(const PropertyName &name, int) Chris@46: { Chris@843: cerr << "WARNING: PropertyContainer[" << getPropertyContainerName() << "]::setProperty(" << name << "): no implementation in subclass!" << endl; Chris@46: } Chris@46: Chris@387: Command * Chris@387: PropertyContainer::getSetPropertyCommand(const PropertyName &name, int value) Chris@46: { Chris@1582: int currentValue = getPropertyRangeAndValue(name, nullptr, nullptr, nullptr); Chris@1582: if (value == currentValue) return nullptr; Chris@387: return new SetPropertyCommand(this, name, value); Chris@46: } Chris@199: Chris@199: void Chris@528: PropertyContainer::setPropertyFuzzy(QString nameString, QString valueString) Chris@199: { Chris@199: PropertyName name; Chris@199: int value; Chris@199: if (!convertPropertyStrings(nameString, valueString, name, value)) { Chris@843: cerr << "WARNING: PropertyContainer::setProperty(\"" Chris@686: << nameString << "\", \"" Chris@844: << valueString Chris@843: << "\"): Name and value conversion failed" << endl; Chris@199: return; Chris@199: } Chris@199: setProperty(name, value); Chris@199: } Chris@199: Chris@387: Command * Chris@387: PropertyContainer::getSetPropertyCommand(QString nameString, QString valueString) Chris@199: { Chris@199: PropertyName name; Chris@199: int value; Chris@199: if (!convertPropertyStrings(nameString, valueString, name, value)) { Chris@843: cerr << "WARNING: PropertyContainer::getSetPropertyCommand(\"" Chris@686: << nameString << "\", \"" Chris@844: << valueString Chris@843: << "\"): Name and value conversion failed" << endl; Chris@1582: return nullptr; Chris@199: } Chris@387: return getSetPropertyCommand(name, value); Chris@199: } Chris@199: Chris@199: bool Chris@199: PropertyContainer::convertPropertyStrings(QString nameString, QString valueString, Chris@199: PropertyName &name, int &value) Chris@199: { Chris@199: PropertyList pl = getProperties(); Chris@199: Chris@199: QString adjusted = nameString.trimmed(); Chris@199: adjusted.replace('_', ' '); Chris@199: adjusted.replace('-', ' '); Chris@199: Chris@199: name = ""; Chris@199: Chris@199: for (PropertyList::iterator pli = pl.begin(); pli != pl.end(); ++pli) { Chris@199: Chris@199: QString label = getPropertyLabel(*pli); Chris@199: Chris@199: if (label != "" && (nameString == label || adjusted == label)) { Chris@199: name = *pli; Chris@199: break; Chris@199: } else if (nameString == *pli) { Chris@199: name = *pli; Chris@199: break; Chris@199: } Chris@199: } Chris@199: Chris@199: if (name == "") { Chris@843: cerr << "PropertyContainer::convertPropertyStrings: Unable to match name string \"" << nameString << "\"" << endl; Chris@199: return false; Chris@199: } Chris@199: Chris@199: value = 0; Chris@199: bool success = false; Chris@199: Chris@199: bool isDouble = false; Chris@199: double dval = valueString.toDouble(&isDouble); Chris@199: Chris@199: switch (getPropertyType(name)) { Chris@199: Chris@199: case ToggleProperty: Chris@199: if (valueString == tr("yes") || Chris@199: valueString == tr("on") || Chris@199: valueString == tr("true")) { Chris@199: value = 1; success = true; Chris@199: } else if (valueString == tr("no") || Chris@199: valueString == tr("off") || Chris@199: valueString == tr("false")) { Chris@199: value = 0; success = true; Chris@199: } Chris@199: break; Chris@199: Chris@199: case RangeProperty: Chris@199: if (isDouble) { Chris@199: RangeMapper *mapper = getNewPropertyRangeMapper(name); Chris@199: if (mapper) { Chris@199: value = mapper->getPositionForValue(dval); Chris@199: delete mapper; Chris@199: success = true; Chris@199: } Chris@199: } Chris@199: break; Chris@199: Chris@199: case ValueProperty: Chris@387: case ColourProperty: Chris@1331: case ColourMapProperty: Chris@199: { Chris@199: int min, max; Chris@1582: getPropertyRangeAndValue(name, &min, &max, nullptr); Chris@199: for (int i = min; i <= max; ++i) { Chris@199: if (valueString == getPropertyValueLabel(name, i)) { Chris@199: value = i; Chris@199: success = true; Chris@199: break; Chris@199: } Chris@199: } Chris@199: break; Chris@199: } Chris@199: Chris@199: case UnitsProperty: Chris@199: value = UnitDatabase::getInstance()->getUnitId(valueString, false); Chris@199: if (value >= 0) success = true; Chris@199: else value = 0; Chris@199: break; Chris@199: Chris@199: case InvalidProperty: Chris@690: SVDEBUG << "PropertyContainer::convertPropertyStrings: Invalid property name \"" << name << "\"" << endl; Chris@199: return false; Chris@199: } Chris@199: Chris@199: if (success) return true; Chris@199: Chris@199: int min, max; Chris@1582: getPropertyRangeAndValue(name, &min, &max, nullptr); Chris@199: Chris@199: bool ok = false; Chris@199: int i = valueString.toInt(&ok); Chris@199: if (!ok) { Chris@843: cerr << "PropertyContainer::convertPropertyStrings: Unable to parse value string \"" << valueString << "\"" << endl; Chris@199: return false; Chris@199: } else if (i < min || i > max) { Chris@690: SVDEBUG << "PropertyContainer::convertPropertyStrings: Property value \"" << i << "\" outside valid range " << min << " to " << max << endl; Chris@199: return false; Chris@199: } Chris@199: Chris@199: value = i; Chris@199: return true; Chris@199: } Chris@46: Chris@46: PropertyContainer::SetPropertyCommand::SetPropertyCommand(PropertyContainer *pc, Chris@1429: const PropertyName &pn, Chris@1429: int value) : Chris@46: m_pc(pc), Chris@46: m_pn(pn), Chris@46: m_value(value), Chris@46: m_oldValue(0) Chris@0: { Chris@0: } Chris@0: Chris@46: void Chris@46: PropertyContainer::SetPropertyCommand::execute() Chris@46: { Chris@1582: m_oldValue = m_pc->getPropertyRangeAndValue(m_pn, nullptr, nullptr, nullptr); Chris@46: m_pc->setProperty(m_pn, m_value); Chris@46: } Chris@46: Chris@46: void Chris@46: PropertyContainer::SetPropertyCommand::unexecute() Chris@46: { Chris@46: m_pc->setProperty(m_pn, m_oldValue); Chris@46: } Chris@46: Chris@46: QString Chris@46: PropertyContainer::SetPropertyCommand::getName() const Chris@46: { Chris@247: return tr("Set %1 Property").arg(m_pn); Chris@46: } Chris@46: