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