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
|