annotate base/PropertyContainer.cpp @ 362:cc4eb32efc6c

* Further model lifecycle fixes
author Chris Cannam
date Thu, 24 Jan 2008 11:03:59 +0000
parents 516819f2b97b
children 7aa1de571880
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@46 17 #include "CommandHistory.h"
Chris@199 18 #include "RangeMapper.h"
Chris@199 19 #include "UnitDatabase.h"
Chris@277 20 #include "ColourDatabase.h"
Chris@199 21
Chris@199 22 #include <QColor>
Chris@46 23
Chris@46 24 #include <iostream>
Chris@0 25
Chris@0 26 PropertyContainer::PropertyList
Chris@0 27 PropertyContainer::getProperties() const
Chris@0 28 {
Chris@0 29 return PropertyList();
Chris@0 30 }
Chris@0 31
Chris@0 32 PropertyContainer::PropertyType
Chris@0 33 PropertyContainer::getPropertyType(const PropertyName &) const
Chris@0 34 {
Chris@0 35 return InvalidProperty;
Chris@0 36 }
Chris@0 37
Chris@0 38 QString
Chris@340 39 PropertyContainer::getPropertyIconName(const PropertyName &) const
Chris@340 40 {
Chris@340 41 return QString();
Chris@340 42 }
Chris@340 43
Chris@340 44 QString
Chris@0 45 PropertyContainer::getPropertyGroupName(const PropertyName &) const
Chris@0 46 {
Chris@0 47 return QString();
Chris@0 48 }
Chris@0 49
Chris@0 50 int
Chris@245 51 PropertyContainer::getPropertyRangeAndValue(const PropertyName &,
Chris@245 52 int *min, int *max, int *deflt) const
Chris@0 53 {
Chris@0 54 if (min) *min = 0;
Chris@0 55 if (max) *max = 0;
Chris@245 56 if (deflt) *deflt = 0;
Chris@0 57 return 0;
Chris@0 58 }
Chris@0 59
Chris@0 60 QString
Chris@277 61 PropertyContainer::getPropertyValueLabel(const PropertyName &name, int value) const
Chris@0 62 {
Chris@277 63 if (getPropertyType(name) == ColourProperty) {
Chris@277 64 ColourDatabase *db = ColourDatabase::getInstance();
Chris@277 65 if (value >= 0 && size_t(value) < db->getColourCount()) {
Chris@277 66 return db->getColourName(value);
Chris@277 67 }
Chris@277 68 }
Chris@277 69
Chris@0 70 return QString();
Chris@0 71 }
Chris@0 72
Chris@190 73 RangeMapper *
Chris@190 74 PropertyContainer::getNewPropertyRangeMapper(const PropertyName &) const
Chris@190 75 {
Chris@190 76 return 0;
Chris@190 77 }
Chris@190 78
Chris@0 79 void
Chris@46 80 PropertyContainer::setProperty(const PropertyName &name, int)
Chris@46 81 {
Chris@46 82 std::cerr << "WARNING: PropertyContainer[" << getPropertyContainerName().toStdString() << "]::setProperty(" << name.toStdString() << "): no implementation in subclass!" << std::endl;
Chris@46 83 }
Chris@46 84
Chris@46 85 void
Chris@46 86 PropertyContainer::setPropertyWithCommand(const PropertyName &name, int value)
Chris@46 87 {
Chris@245 88 int currentValue = getPropertyRangeAndValue(name, 0, 0, 0);
Chris@46 89 if (value == currentValue) return;
Chris@46 90
Chris@46 91 CommandHistory::getInstance()->addCommand
Chris@47 92 (new SetPropertyCommand(this, name, value), true, true); // bundled
Chris@46 93 }
Chris@199 94
Chris@199 95 void
Chris@199 96 PropertyContainer::setProperty(QString nameString, QString valueString)
Chris@199 97 {
Chris@199 98 PropertyName name;
Chris@199 99 int value;
Chris@199 100 if (!convertPropertyStrings(nameString, valueString, name, value)) {
Chris@199 101 std::cerr << "WARNING: PropertyContainer::setProperty(\""
Chris@199 102 << nameString.toStdString() << "\", \""
Chris@199 103 << valueString.toStdString()
Chris@199 104 << "\"): Name and value conversion failed" << std::endl;
Chris@199 105 return;
Chris@199 106 }
Chris@199 107 setProperty(name, value);
Chris@199 108 }
Chris@199 109
Chris@199 110 void
Chris@199 111 PropertyContainer::setPropertyWithCommand(QString nameString, QString valueString)
Chris@199 112 {
Chris@199 113 PropertyName name;
Chris@199 114 int value;
Chris@199 115 if (!convertPropertyStrings(nameString, valueString, name, value)) {
Chris@199 116 std::cerr << "WARNING: PropertyContainer::setPropertyWithCommand(\""
Chris@199 117 << nameString.toStdString() << "\", \""
Chris@199 118 << valueString.toStdString()
Chris@199 119 << "\"): Name and value conversion failed" << std::endl;
Chris@199 120 return;
Chris@199 121 }
Chris@199 122 setPropertyWithCommand(name, value);
Chris@199 123 }
Chris@199 124
Chris@199 125 bool
Chris@199 126 PropertyContainer::convertPropertyStrings(QString nameString, QString valueString,
Chris@199 127 PropertyName &name, int &value)
Chris@199 128 {
Chris@199 129 PropertyList pl = getProperties();
Chris@199 130
Chris@199 131 QString adjusted = nameString.trimmed();
Chris@199 132 adjusted.replace('_', ' ');
Chris@199 133 adjusted.replace('-', ' ');
Chris@199 134
Chris@199 135 name = "";
Chris@199 136
Chris@199 137 for (PropertyList::iterator pli = pl.begin(); pli != pl.end(); ++pli) {
Chris@199 138
Chris@199 139 QString label = getPropertyLabel(*pli);
Chris@199 140
Chris@199 141 if (label != "" && (nameString == label || adjusted == label)) {
Chris@199 142 name = *pli;
Chris@199 143 break;
Chris@199 144 } else if (nameString == *pli) {
Chris@199 145 name = *pli;
Chris@199 146 break;
Chris@199 147 }
Chris@199 148 }
Chris@199 149
Chris@199 150 if (name == "") {
Chris@199 151 std::cerr << "PropertyContainer::convertPropertyStrings: Unable to match name string \"" << nameString.toStdString() << "\"" << std::endl;
Chris@199 152 return false;
Chris@199 153 }
Chris@199 154
Chris@199 155 value = 0;
Chris@199 156 bool success = false;
Chris@199 157
Chris@199 158 bool isDouble = false;
Chris@199 159 double dval = valueString.toDouble(&isDouble);
Chris@199 160
Chris@199 161 switch (getPropertyType(name)) {
Chris@199 162
Chris@199 163 case ToggleProperty:
Chris@199 164 if (valueString == tr("yes") ||
Chris@199 165 valueString == tr("on") ||
Chris@199 166 valueString == tr("true")) {
Chris@199 167 value = 1; success = true;
Chris@199 168 } else if (valueString == tr("no") ||
Chris@199 169 valueString == tr("off") ||
Chris@199 170 valueString == tr("false")) {
Chris@199 171 value = 0; success = true;
Chris@199 172 }
Chris@199 173 break;
Chris@199 174
Chris@199 175 case RangeProperty:
Chris@199 176 if (isDouble) {
Chris@199 177 RangeMapper *mapper = getNewPropertyRangeMapper(name);
Chris@199 178 if (mapper) {
Chris@199 179 value = mapper->getPositionForValue(dval);
Chris@199 180 delete mapper;
Chris@199 181 success = true;
Chris@199 182 }
Chris@199 183 }
Chris@199 184 break;
Chris@199 185
Chris@199 186 case ValueProperty:
Chris@199 187 {
Chris@199 188 int min, max;
Chris@245 189 getPropertyRangeAndValue(name, &min, &max, 0);
Chris@199 190 for (int i = min; i <= max; ++i) {
Chris@199 191 if (valueString == getPropertyValueLabel(name, i)) {
Chris@199 192 value = i;
Chris@199 193 success = true;
Chris@199 194 break;
Chris@199 195 }
Chris@199 196 }
Chris@199 197 break;
Chris@199 198 }
Chris@199 199
Chris@199 200 case ColourProperty:
Chris@277 201 value = ColourDatabase::getInstance()->getColourIndex(valueString);
Chris@277 202 if (value >= 0) success = true;
Chris@277 203 else value = 0;
Chris@199 204 break;
Chris@199 205
Chris@199 206 case UnitsProperty:
Chris@199 207 value = UnitDatabase::getInstance()->getUnitId(valueString, false);
Chris@199 208 if (value >= 0) success = true;
Chris@199 209 else value = 0;
Chris@199 210 break;
Chris@199 211
Chris@199 212 case InvalidProperty:
Chris@199 213 std::cerr << "PropertyContainer::convertPropertyStrings: Invalid property name \"" << name.toStdString() << "\"" << std::endl;
Chris@199 214 return false;
Chris@199 215 }
Chris@199 216
Chris@199 217 if (success) return true;
Chris@199 218
Chris@199 219 int min, max;
Chris@245 220 getPropertyRangeAndValue(name, &min, &max, 0);
Chris@199 221
Chris@199 222 bool ok = false;
Chris@199 223 int i = valueString.toInt(&ok);
Chris@199 224 if (!ok) {
Chris@199 225 std::cerr << "PropertyContainer::convertPropertyStrings: Unable to parse value string \"" << valueString.toStdString() << "\"" << std::endl;
Chris@199 226 return false;
Chris@199 227 } else if (i < min || i > max) {
Chris@199 228 std::cerr << "PropertyContainer::convertPropertyStrings: Property value \"" << i << "\" outside valid range " << min << " to " << max << std::endl;
Chris@199 229 return false;
Chris@199 230 }
Chris@199 231
Chris@199 232 value = i;
Chris@199 233 return true;
Chris@199 234 }
Chris@46 235
Chris@46 236 PropertyContainer::SetPropertyCommand::SetPropertyCommand(PropertyContainer *pc,
Chris@46 237 const PropertyName &pn,
Chris@46 238 int value) :
Chris@46 239 m_pc(pc),
Chris@46 240 m_pn(pn),
Chris@46 241 m_value(value),
Chris@46 242 m_oldValue(0)
Chris@0 243 {
Chris@0 244 }
Chris@0 245
Chris@46 246 void
Chris@46 247 PropertyContainer::SetPropertyCommand::execute()
Chris@46 248 {
Chris@245 249 m_oldValue = m_pc->getPropertyRangeAndValue(m_pn, 0, 0, 0);
Chris@46 250 m_pc->setProperty(m_pn, m_value);
Chris@46 251 }
Chris@46 252
Chris@46 253 void
Chris@46 254 PropertyContainer::SetPropertyCommand::unexecute()
Chris@46 255 {
Chris@46 256 m_pc->setProperty(m_pn, m_oldValue);
Chris@46 257 }
Chris@46 258
Chris@46 259 QString
Chris@46 260 PropertyContainer::SetPropertyCommand::getName() const
Chris@46 261 {
Chris@247 262 return tr("Set %1 Property").arg(m_pn);
Chris@46 263 }
Chris@46 264