svcore  1.9
PropertyContainer.cpp
Go to the documentation of this file.
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
00002 
00003 /*
00004     Sonic Visualiser
00005     An audio file viewer and annotation editor.
00006     Centre for Digital Music, Queen Mary, University of London.
00007     This file copyright 2006 Chris Cannam and QMUL.
00008     
00009     This program is free software; you can redistribute it and/or
00010     modify it under the terms of the GNU General Public License as
00011     published by the Free Software Foundation; either version 2 of the
00012     License, or (at your option) any later version.  See the file
00013     COPYING included with this distribution for more information.
00014 */
00015 
00016 #include "PropertyContainer.h"
00017 #include "RangeMapper.h"
00018 #include "UnitDatabase.h"
00019 
00020 #include <iostream>
00021 
00022 PropertyContainer::PropertyList
00023 PropertyContainer::getProperties() const
00024 {
00025     return PropertyList();
00026 }
00027 
00028 PropertyContainer::PropertyType
00029 PropertyContainer::getPropertyType(const PropertyName &) const
00030 {
00031     return InvalidProperty;
00032 }
00033 
00034 QString
00035 PropertyContainer::getPropertyIconName(const PropertyName &) const
00036 {
00037     return QString();
00038 }
00039 
00040 QString
00041 PropertyContainer::getPropertyGroupName(const PropertyName &) const
00042 {
00043     return QString();
00044 }
00045 
00046 int
00047 PropertyContainer::getPropertyRangeAndValue(const PropertyName &,
00048                                             int *min, int *max, int *deflt) const
00049 {
00050     if (min) *min = 0;
00051     if (max) *max = 0;
00052     if (deflt) *deflt = 0;
00053     return 0;
00054 }
00055 
00056 QString
00057 PropertyContainer::getPropertyValueLabel(const PropertyName &, int) const
00058 {
00059     return QString();
00060 }
00061 
00062 RangeMapper *
00063 PropertyContainer::getNewPropertyRangeMapper(const PropertyName &) const
00064 {
00065     return 0;
00066 }
00067 
00068 void
00069 PropertyContainer::setProperty(const PropertyName &name, int) 
00070 {
00071     cerr << "WARNING: PropertyContainer[" << getPropertyContainerName() << "]::setProperty(" << name << "): no implementation in subclass!" << endl;
00072 }
00073 
00074 Command *
00075 PropertyContainer::getSetPropertyCommand(const PropertyName &name, int value)
00076 {
00077     int currentValue = getPropertyRangeAndValue(name, 0, 0, 0);
00078     if (value == currentValue) return 0;
00079     return new SetPropertyCommand(this, name, value);
00080 }
00081  
00082 void
00083 PropertyContainer::setPropertyFuzzy(QString nameString, QString valueString)
00084 {
00085     PropertyName name;
00086     int value;
00087     if (!convertPropertyStrings(nameString, valueString, name, value)) {
00088         cerr << "WARNING: PropertyContainer::setProperty(\""
00089                   << nameString << "\", \""
00090                   << valueString
00091                   << "\"): Name and value conversion failed" << endl;
00092         return;
00093     }
00094     setProperty(name, value);
00095 }
00096  
00097 Command *
00098 PropertyContainer::getSetPropertyCommand(QString nameString, QString valueString)
00099 {
00100     PropertyName name;
00101     int value;
00102     if (!convertPropertyStrings(nameString, valueString, name, value)) {
00103         cerr << "WARNING: PropertyContainer::getSetPropertyCommand(\""
00104                   << nameString << "\", \""
00105                   << valueString
00106                   << "\"): Name and value conversion failed" << endl;
00107         return 0;
00108     }
00109     return getSetPropertyCommand(name, value);
00110 }
00111 
00112 bool
00113 PropertyContainer::convertPropertyStrings(QString nameString, QString valueString,
00114                                           PropertyName &name, int &value)
00115 {
00116     PropertyList pl = getProperties();
00117 
00118     QString adjusted = nameString.trimmed();
00119     adjusted.replace('_', ' ');
00120     adjusted.replace('-', ' ');
00121     
00122     name = "";
00123 
00124     for (PropertyList::iterator pli = pl.begin(); pli != pl.end(); ++pli) {
00125 
00126         QString label = getPropertyLabel(*pli);
00127 
00128         if (label != "" && (nameString == label || adjusted == label)) {
00129             name = *pli;
00130             break;
00131         } else if (nameString == *pli) {
00132             name = *pli;
00133             break;
00134         }
00135     }
00136 
00137     if (name == "") {
00138         cerr << "PropertyContainer::convertPropertyStrings: Unable to match name string \"" << nameString << "\"" << endl;
00139         return false;
00140     }
00141 
00142     value = 0;
00143     bool success = false;
00144     
00145     bool isDouble = false;
00146     double dval = valueString.toDouble(&isDouble);
00147 
00148     switch (getPropertyType(name)) {
00149 
00150     case ToggleProperty:
00151         if (valueString == tr("yes") || 
00152             valueString == tr("on") ||
00153             valueString == tr("true")) {
00154             value = 1; success = true;
00155         } else if (valueString == tr("no") ||
00156                    valueString == tr("off") ||
00157                    valueString == tr("false")) {
00158             value = 0; success = true;
00159         }
00160         break;
00161 
00162     case RangeProperty:
00163         if (isDouble) {
00164             RangeMapper *mapper = getNewPropertyRangeMapper(name);
00165             if (mapper) {
00166                 value = mapper->getPositionForValue(dval);
00167                 delete mapper;
00168                 success = true;
00169             }
00170         }
00171         break;
00172 
00173     case ValueProperty:
00174     case ColourProperty:
00175     {
00176         int min, max;
00177         getPropertyRangeAndValue(name, &min, &max, 0);
00178         for (int i = min; i <= max; ++i) {
00179             if (valueString == getPropertyValueLabel(name, i)) {
00180                 value = i;
00181                 success = true;
00182                 break;
00183             }
00184         }
00185         break;
00186     }
00187         
00188     case UnitsProperty:
00189         value = UnitDatabase::getInstance()->getUnitId(valueString, false);
00190         if (value >= 0) success = true;
00191         else value = 0;
00192         break;
00193 
00194     case InvalidProperty:
00195         SVDEBUG << "PropertyContainer::convertPropertyStrings: Invalid property name \"" << name << "\"" << endl;
00196         return false;
00197     }
00198 
00199     if (success) return true;
00200 
00201     int min, max;
00202     getPropertyRangeAndValue(name, &min, &max, 0);
00203     
00204     bool ok = false;
00205     int i = valueString.toInt(&ok);
00206     if (!ok) {
00207         cerr << "PropertyContainer::convertPropertyStrings: Unable to parse value string \"" << valueString << "\"" << endl;
00208         return false;
00209     } else if (i < min || i > max) {
00210         SVDEBUG << "PropertyContainer::convertPropertyStrings: Property value \"" << i << "\" outside valid range " << min << " to " << max << endl;
00211         return false;
00212     }
00213 
00214     value = i;
00215     return true;
00216 }
00217 
00218 PropertyContainer::SetPropertyCommand::SetPropertyCommand(PropertyContainer *pc,
00219                                                           const PropertyName &pn,
00220                                                           int value) :
00221     m_pc(pc),
00222     m_pn(pn),
00223     m_value(value),
00224     m_oldValue(0)
00225 {
00226 }
00227 
00228 void
00229 PropertyContainer::SetPropertyCommand::execute()
00230 {
00231     m_oldValue = m_pc->getPropertyRangeAndValue(m_pn, 0, 0, 0);
00232     m_pc->setProperty(m_pn, m_value);
00233 }
00234 
00235 void
00236 PropertyContainer::SetPropertyCommand::unexecute() 
00237 {
00238     m_pc->setProperty(m_pn, m_oldValue);
00239 }
00240 
00241 QString
00242 PropertyContainer::SetPropertyCommand::getName() const
00243 {
00244     return tr("Set %1 Property").arg(m_pn);
00245 }
00246