annotate base/PropertyContainer.cpp @ 458:f60360209e5c

* Fix race condition in FFTFileCache when reading from the same FFT model from multiple threads (e.g. when applying more than one plugin at once)
author Chris Cannam
date Wed, 15 Oct 2008 12:08:02 +0000
parents 7aa1de571880
children 57857a57a03a
rev   line source
Chris@49 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@0 2
Chris@0 3 /*
Chris@52 4 Sonic Visualiser
Chris@52 5 An audio file viewer and annotation editor.
Chris@52 6 Centre for Digital Music, Queen Mary, University of London.
Chris@202 7 This file copyright 2006 Chris Cannam and QMUL.
Chris@0 8
Chris@52 9 This program is free software; you can redistribute it and/or
Chris@52 10 modify it under the terms of the GNU General Public License as
Chris@52 11 published by the Free Software Foundation; either version 2 of the
Chris@52 12 License, or (at your option) any later version. See the file
Chris@52 13 COPYING included with this distribution for more information.
Chris@0 14 */
Chris@0 15
Chris@0 16 #include "PropertyContainer.h"
Chris@199 17 #include "RangeMapper.h"
Chris@199 18 #include "UnitDatabase.h"
Chris@46 19
Chris@46 20 #include <iostream>
Chris@0 21
Chris@0 22 PropertyContainer::PropertyList
Chris@0 23 PropertyContainer::getProperties() const
Chris@0 24 {
Chris@0 25 return PropertyList();
Chris@0 26 }
Chris@0 27
Chris@0 28 PropertyContainer::PropertyType
Chris@0 29 PropertyContainer::getPropertyType(const PropertyName &) const
Chris@0 30 {
Chris@0 31 return InvalidProperty;
Chris@0 32 }
Chris@0 33
Chris@0 34 QString
Chris@340 35 PropertyContainer::getPropertyIconName(const PropertyName &) const
Chris@340 36 {
Chris@340 37 return QString();
Chris@340 38 }
Chris@340 39
Chris@340 40 QString
Chris@0 41 PropertyContainer::getPropertyGroupName(const PropertyName &) const
Chris@0 42 {
Chris@0 43 return QString();
Chris@0 44 }
Chris@0 45
Chris@0 46 int
Chris@245 47 PropertyContainer::getPropertyRangeAndValue(const PropertyName &,
Chris@245 48 int *min, int *max, int *deflt) const
Chris@0 49 {
Chris@0 50 if (min) *min = 0;
Chris@0 51 if (max) *max = 0;
Chris@245 52 if (deflt) *deflt = 0;
Chris@0 53 return 0;
Chris@0 54 }
Chris@0 55
Chris@0 56 QString
Chris@277 57 PropertyContainer::getPropertyValueLabel(const PropertyName &name, int value) const
Chris@0 58 {
Chris@0 59 return QString();
Chris@0 60 }
Chris@0 61
Chris@190 62 RangeMapper *
Chris@190 63 PropertyContainer::getNewPropertyRangeMapper(const PropertyName &) const
Chris@190 64 {
Chris@190 65 return 0;
Chris@190 66 }
Chris@190 67
Chris@0 68 void
Chris@46 69 PropertyContainer::setProperty(const PropertyName &name, int)
Chris@46 70 {
Chris@46 71 std::cerr << "WARNING: PropertyContainer[" << getPropertyContainerName().toStdString() << "]::setProperty(" << name.toStdString() << "): no implementation in subclass!" << std::endl;
Chris@46 72 }
Chris@46 73
Chris@387 74 Command *
Chris@387 75 PropertyContainer::getSetPropertyCommand(const PropertyName &name, int value)
Chris@46 76 {
Chris@245 77 int currentValue = getPropertyRangeAndValue(name, 0, 0, 0);
Chris@387 78 if (value == currentValue) return 0;
Chris@387 79 return new SetPropertyCommand(this, name, value);
Chris@46 80 }
Chris@199 81
Chris@199 82 void
Chris@199 83 PropertyContainer::setProperty(QString nameString, QString valueString)
Chris@199 84 {
Chris@199 85 PropertyName name;
Chris@199 86 int value;
Chris@199 87 if (!convertPropertyStrings(nameString, valueString, name, value)) {
Chris@199 88 std::cerr << "WARNING: PropertyContainer::setProperty(\""
Chris@199 89 << nameString.toStdString() << "\", \""
Chris@199 90 << valueString.toStdString()
Chris@199 91 << "\"): Name and value conversion failed" << std::endl;
Chris@199 92 return;
Chris@199 93 }
Chris@199 94 setProperty(name, value);
Chris@199 95 }
Chris@199 96
Chris@387 97 Command *
Chris@387 98 PropertyContainer::getSetPropertyCommand(QString nameString, QString valueString)
Chris@199 99 {
Chris@199 100 PropertyName name;
Chris@199 101 int value;
Chris@199 102 if (!convertPropertyStrings(nameString, valueString, name, value)) {
Chris@387 103 std::cerr << "WARNING: PropertyContainer::getSetPropertyCommand(\""
Chris@199 104 << nameString.toStdString() << "\", \""
Chris@199 105 << valueString.toStdString()
Chris@199 106 << "\"): Name and value conversion failed" << std::endl;
Chris@387 107 return 0;
Chris@199 108 }
Chris@387 109 return getSetPropertyCommand(name, value);
Chris@199 110 }
Chris@199 111
Chris@199 112 bool
Chris@199 113 PropertyContainer::convertPropertyStrings(QString nameString, QString valueString,
Chris@199 114 PropertyName &name, int &value)
Chris@199 115 {
Chris@199 116 PropertyList pl = getProperties();
Chris@199 117
Chris@199 118 QString adjusted = nameString.trimmed();
Chris@199 119 adjusted.replace('_', ' ');
Chris@199 120 adjusted.replace('-', ' ');
Chris@199 121
Chris@199 122 name = "";
Chris@199 123
Chris@199 124 for (PropertyList::iterator pli = pl.begin(); pli != pl.end(); ++pli) {
Chris@199 125
Chris@199 126 QString label = getPropertyLabel(*pli);
Chris@199 127
Chris@199 128 if (label != "" && (nameString == label || adjusted == label)) {
Chris@199 129 name = *pli;
Chris@199 130 break;
Chris@199 131 } else if (nameString == *pli) {
Chris@199 132 name = *pli;
Chris@199 133 break;
Chris@199 134 }
Chris@199 135 }
Chris@199 136
Chris@199 137 if (name == "") {
Chris@199 138 std::cerr << "PropertyContainer::convertPropertyStrings: Unable to match name string \"" << nameString.toStdString() << "\"" << std::endl;
Chris@199 139 return false;
Chris@199 140 }
Chris@199 141
Chris@199 142 value = 0;
Chris@199 143 bool success = false;
Chris@199 144
Chris@199 145 bool isDouble = false;
Chris@199 146 double dval = valueString.toDouble(&isDouble);
Chris@199 147
Chris@199 148 switch (getPropertyType(name)) {
Chris@199 149
Chris@199 150 case ToggleProperty:
Chris@199 151 if (valueString == tr("yes") ||
Chris@199 152 valueString == tr("on") ||
Chris@199 153 valueString == tr("true")) {
Chris@199 154 value = 1; success = true;
Chris@199 155 } else if (valueString == tr("no") ||
Chris@199 156 valueString == tr("off") ||
Chris@199 157 valueString == tr("false")) {
Chris@199 158 value = 0; success = true;
Chris@199 159 }
Chris@199 160 break;
Chris@199 161
Chris@199 162 case RangeProperty:
Chris@199 163 if (isDouble) {
Chris@199 164 RangeMapper *mapper = getNewPropertyRangeMapper(name);
Chris@199 165 if (mapper) {
Chris@199 166 value = mapper->getPositionForValue(dval);
Chris@199 167 delete mapper;
Chris@199 168 success = true;
Chris@199 169 }
Chris@199 170 }
Chris@199 171 break;
Chris@199 172
Chris@199 173 case ValueProperty:
Chris@387 174 case ColourProperty:
Chris@199 175 {
Chris@199 176 int min, max;
Chris@245 177 getPropertyRangeAndValue(name, &min, &max, 0);
Chris@199 178 for (int i = min; i <= max; ++i) {
Chris@199 179 if (valueString == getPropertyValueLabel(name, i)) {
Chris@199 180 value = i;
Chris@199 181 success = true;
Chris@199 182 break;
Chris@199 183 }
Chris@199 184 }
Chris@199 185 break;
Chris@199 186 }
Chris@199 187
Chris@199 188 case UnitsProperty:
Chris@199 189 value = UnitDatabase::getInstance()->getUnitId(valueString, false);
Chris@199 190 if (value >= 0) success = true;
Chris@199 191 else value = 0;
Chris@199 192 break;
Chris@199 193
Chris@199 194 case InvalidProperty:
Chris@199 195 std::cerr << "PropertyContainer::convertPropertyStrings: Invalid property name \"" << name.toStdString() << "\"" << std::endl;
Chris@199 196 return false;
Chris@199 197 }
Chris@199 198
Chris@199 199 if (success) return true;
Chris@199 200
Chris@199 201 int min, max;
Chris@245 202 getPropertyRangeAndValue(name, &min, &max, 0);
Chris@199 203
Chris@199 204 bool ok = false;
Chris@199 205 int i = valueString.toInt(&ok);
Chris@199 206 if (!ok) {
Chris@199 207 std::cerr << "PropertyContainer::convertPropertyStrings: Unable to parse value string \"" << valueString.toStdString() << "\"" << std::endl;
Chris@199 208 return false;
Chris@199 209 } else if (i < min || i > max) {
Chris@199 210 std::cerr << "PropertyContainer::convertPropertyStrings: Property value \"" << i << "\" outside valid range " << min << " to " << max << std::endl;
Chris@199 211 return false;
Chris@199 212 }
Chris@199 213
Chris@199 214 value = i;
Chris@199 215 return true;
Chris@199 216 }
Chris@46 217
Chris@46 218 PropertyContainer::SetPropertyCommand::SetPropertyCommand(PropertyContainer *pc,
Chris@46 219 const PropertyName &pn,
Chris@46 220 int value) :
Chris@46 221 m_pc(pc),
Chris@46 222 m_pn(pn),
Chris@46 223 m_value(value),
Chris@46 224 m_oldValue(0)
Chris@0 225 {
Chris@0 226 }
Chris@0 227
Chris@46 228 void
Chris@46 229 PropertyContainer::SetPropertyCommand::execute()
Chris@46 230 {
Chris@245 231 m_oldValue = m_pc->getPropertyRangeAndValue(m_pn, 0, 0, 0);
Chris@46 232 m_pc->setProperty(m_pn, m_value);
Chris@46 233 }
Chris@46 234
Chris@46 235 void
Chris@46 236 PropertyContainer::SetPropertyCommand::unexecute()
Chris@46 237 {
Chris@46 238 m_pc->setProperty(m_pn, m_oldValue);
Chris@46 239 }
Chris@46 240
Chris@46 241 QString
Chris@46 242 PropertyContainer::SetPropertyCommand::getName() const
Chris@46 243 {
Chris@247 244 return tr("Set %1 Property").arg(m_pn);
Chris@46 245 }
Chris@46 246