annotate base/PropertyContainer.cpp @ 316:3a6725f285d6

* Make RemoteFile far more pervasive, and use it for local files as well so that we can handle both transparently. Make it shallow copy with reference counting, so it can be used by value without having to worry about the cache file lifetime. Use RemoteFile for MainWindow file-open functions, etc
author Chris Cannam
date Thu, 18 Oct 2007 15:31:20 +0000
parents 3b8008d09541
children 516819f2b97b
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@94 32 //QString
Chris@94 33 //PropertyContainer::getPropertyLabel(const PropertyName &) const
Chris@94 34 //{
Chris@94 35 // return "";
Chris@94 36 //}
Chris@94 37
Chris@0 38 PropertyContainer::PropertyType
Chris@0 39 PropertyContainer::getPropertyType(const PropertyName &) const
Chris@0 40 {
Chris@0 41 return InvalidProperty;
Chris@0 42 }
Chris@0 43
Chris@0 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