annotate base/PropertyContainer.cpp @ 212:fb8ddd00f440

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