annotate base/PropertyContainer.cpp @ 267:fa612dc181af

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