1 | /* This file is part of the KDE project |
2 | Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org> |
3 | |
4 | This library is free software; you can redistribute it and/or |
5 | modify it under the terms of the GNU Lesser General Public |
6 | License as published by the Free Software Foundation; either |
7 | version 2.1 of the License, or (at your option) version 3, or any |
8 | later version accepted by the membership of KDE e.V. (or its |
9 | successor approved by the membership of KDE e.V.), Nokia Corporation |
10 | (or its successors, if any) and the KDE Free Qt Foundation, which shall |
11 | act as a proxy defined in Section 6 of version 3 of the license. |
12 | |
13 | This library is distributed in the hope that it will be useful, |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
16 | Lesser General Public License for more details. |
17 | |
18 | You should have received a copy of the GNU Lesser General Public |
19 | License along with this library. If not, see <http://www.gnu.org/licenses/>. |
20 | |
21 | */ |
22 | |
23 | #include "effectwidget.h" |
24 | #include "effectwidget_p.h" |
25 | |
26 | #include <QtCore/QtAlgorithms> |
27 | #include <QtCore/QList> |
28 | |
29 | #include "effect.h" |
30 | #include "effectparameter.h" |
31 | #include "phonondefs_p.h" |
32 | #include <QtGui/QBoxLayout> |
33 | #include <QtGui/QLabel> |
34 | #include <QtGui/QSpinBox> |
35 | #include <QtGui/QCheckBox> |
36 | #include <QtGui/QComboBox> |
37 | #include <QtGui/QSlider> |
38 | #include <limits> |
39 | |
40 | #ifdef min |
41 | #undef min |
42 | #endif |
43 | #ifdef max |
44 | #undef max |
45 | #endif |
46 | static const qreal DEFAULT_MIN = std::numeric_limits<qreal>::min(); |
47 | static const qreal DEFAULT_MAX = std::numeric_limits<qreal>::max(); |
48 | static const int DEFAULT_MIN_INT = std::numeric_limits<int>::min(); |
49 | static const int DEFAULT_MAX_INT = std::numeric_limits<int>::max(); |
50 | static const int SLIDER_RANGE = 8; |
51 | static const int TICKINTERVAL = 4; |
52 | |
53 | |
54 | QT_BEGIN_NAMESPACE |
55 | |
56 | #ifndef QT_NO_PHONON_EFFECTWIDGET |
57 | |
58 | namespace Phonon |
59 | { |
60 | |
61 | EffectWidget::EffectWidget(Effect *effect, QWidget *parent) |
62 | : QWidget(parent), |
63 | k_ptr(new EffectWidgetPrivate(effect)) |
64 | { |
65 | K_D(EffectWidget); |
66 | d->q_ptr = this; |
67 | d->autogenerateUi(); |
68 | } |
69 | |
70 | EffectWidget::~EffectWidget() |
71 | { |
72 | delete k_ptr; |
73 | } |
74 | |
75 | /* |
76 | EffectWidget::EffectWidget(EffectWidgetPrivate &dd, QWidget *parent) |
77 | : QWidget(parent) |
78 | , k_ptr(&dd) |
79 | { |
80 | K_D(EffectWidget); |
81 | d->q_ptr = this; |
82 | d->autogenerateUi(); |
83 | } |
84 | */ |
85 | |
86 | EffectWidgetPrivate::EffectWidgetPrivate(Effect *e) |
87 | : effect(e) |
88 | { |
89 | //TODO: look up whether there is a specialized widget for this effect. This |
90 | //could be a DSO or a Designer ui file found via KTrader. |
91 | // |
92 | //if no specialized widget is available: |
93 | } |
94 | |
95 | void EffectWidgetPrivate::autogenerateUi() |
96 | { |
97 | Q_Q(EffectWidget); |
98 | QVBoxLayout *mainLayout = new QVBoxLayout(q); |
99 | mainLayout->setMargin(0); |
100 | const QList<Phonon::EffectParameter> parameters = effect->parameters(); |
101 | for (int i = 0; i < parameters.count(); ++i) { |
102 | const EffectParameter ¶ = parameters.at(i); |
103 | QVariant value = effect->parameterValue(para); |
104 | QHBoxLayout *pLayout = new QHBoxLayout; |
105 | mainLayout->addLayout(pLayout); |
106 | |
107 | QLabel *label = new QLabel(q); |
108 | pLayout->addWidget(label); |
109 | label->setText(para.name()); |
110 | #ifndef QT_NO_TOOLTIP |
111 | label->setToolTip(para.description()); |
112 | #endif |
113 | |
114 | QWidget *control = 0; |
115 | switch (int(para.type())) { |
116 | case QVariant::String: |
117 | { |
118 | QComboBox *cb = new QComboBox(q); |
119 | control = cb; |
120 | if (value.type() == QVariant::Int) { |
121 | //value just defines the item index |
122 | for (int i = 0; i < para.possibleValues().count(); ++i) { |
123 | cb->addItem(para.possibleValues().at(i).toString()); |
124 | } |
125 | cb->setCurrentIndex(value.toInt()); |
126 | QObject::connect(cb, SIGNAL(currentIndexChanged(int)), q, SLOT(_k_setIntParameter(int))); |
127 | } else { |
128 | for (int i = 0; i < para.possibleValues().count(); ++i) { |
129 | const QVariant &item = para.possibleValues().at(i); |
130 | cb->addItem(item.toString()); |
131 | if (item == value) { |
132 | cb->setCurrentIndex(cb->count() - 1); |
133 | } |
134 | } |
135 | QObject::connect(cb, SIGNAL(currentIndexChanged(QString)), q, SLOT(_k_setStringParameter(QString))); |
136 | } |
137 | } |
138 | break; |
139 | case QVariant::Bool: |
140 | { |
141 | QCheckBox *cb = new QCheckBox(q); |
142 | control = cb; |
143 | cb->setChecked(value.toBool()); |
144 | QObject::connect(cb, SIGNAL(toggled(bool)), q, SLOT(_k_setToggleParameter(bool))); |
145 | } |
146 | break; |
147 | case QVariant::Int: |
148 | { |
149 | QSpinBox *sb = new QSpinBox(q); |
150 | control = sb; |
151 | bool minValueOk = false; |
152 | bool maxValueOk = false; |
153 | const int minValue = para.minimumValue().toInt(&minValueOk); |
154 | const int maxValue = para.maximumValue().toInt(&maxValueOk); |
155 | |
156 | sb->setRange(minValueOk ? minValue : DEFAULT_MIN_INT, maxValueOk ? maxValue : DEFAULT_MAX_INT); |
157 | sb->setValue(value.toInt()); |
158 | QObject::connect(sb, SIGNAL(valueChanged(int)), q, SLOT(_k_setIntParameter(int))); |
159 | } |
160 | break; |
161 | case QMetaType::Float: |
162 | case QVariant::Double: |
163 | { |
164 | const qreal minValue = para.minimumValue().canConvert(QVariant::Double) ? |
165 | para.minimumValue().toReal() : DEFAULT_MIN; |
166 | const qreal maxValue = para.maximumValue().canConvert(QVariant::Double) ? |
167 | para.maximumValue().toReal() : DEFAULT_MAX; |
168 | |
169 | if (minValue == -1. && maxValue == 1.) { |
170 | //Special case values between -1 and 1.0 to use a slider for improved usability |
171 | QSlider *slider = new QSlider(Qt::Horizontal, q); |
172 | control = slider; |
173 | slider->setRange(-SLIDER_RANGE, +SLIDER_RANGE); |
174 | slider->setValue(int(SLIDER_RANGE * value.toReal())); |
175 | slider->setTickPosition(QSlider::TicksBelow); |
176 | slider->setTickInterval(TICKINTERVAL); |
177 | QObject::connect(slider, SIGNAL(valueChanged(int)), q, SLOT(_k_setSliderParameter(int))); |
178 | } else { |
179 | double step = 0.1; |
180 | if (qAbs(maxValue - minValue) > 50) |
181 | step = 1.0; |
182 | QDoubleSpinBox *sb = new QDoubleSpinBox(q); |
183 | control = sb; |
184 | sb->setRange(minValue, maxValue); |
185 | sb->setValue(value.toDouble()); |
186 | sb->setSingleStep(step); |
187 | QObject::connect(sb, SIGNAL(valueChanged(double)), q, |
188 | SLOT(_k_setDoubleParameter(double))); |
189 | } |
190 | } |
191 | break; |
192 | default: |
193 | break; |
194 | } |
195 | |
196 | if (control) { |
197 | #ifndef QT_NO_TOOLTIP |
198 | control->setToolTip(para.description()); |
199 | #endif |
200 | #ifndef QT_NO_SHORTCUT |
201 | label->setBuddy(control); |
202 | #endif |
203 | pLayout->addWidget(control); |
204 | parameterForObject.insert(control, para); |
205 | } |
206 | } |
207 | } |
208 | |
209 | void EffectWidgetPrivate::_k_setToggleParameter(bool checked) |
210 | { |
211 | Q_Q(EffectWidget); |
212 | if (parameterForObject.contains(q->sender())) { |
213 | effect->setParameterValue(parameterForObject[q->sender()], checked); |
214 | } |
215 | } |
216 | |
217 | void EffectWidgetPrivate::_k_setIntParameter(int value) |
218 | { |
219 | Q_Q(EffectWidget); |
220 | if (parameterForObject.contains(q->sender())) { |
221 | effect->setParameterValue(parameterForObject[q->sender()], value); |
222 | } |
223 | } |
224 | |
225 | void EffectWidgetPrivate::_k_setDoubleParameter(double value) |
226 | { |
227 | Q_Q(EffectWidget); |
228 | if (parameterForObject.contains(q->sender())) { |
229 | effect->setParameterValue(parameterForObject[q->sender()], value); |
230 | } |
231 | } |
232 | |
233 | void EffectWidgetPrivate::_k_setStringParameter(const QString &value) |
234 | { |
235 | Q_Q(EffectWidget); |
236 | if (parameterForObject.contains(q->sender())) { |
237 | effect->setParameterValue(parameterForObject[q->sender()], value); |
238 | } |
239 | } |
240 | |
241 | void EffectWidgetPrivate::_k_setSliderParameter(int value) |
242 | { |
243 | Q_Q(EffectWidget); |
244 | if (parameterForObject.contains(q->sender())) { |
245 | effect->setParameterValue(parameterForObject[q->sender()], double(value) / double(SLIDER_RANGE)); |
246 | } |
247 | } |
248 | |
249 | |
250 | } // namespace Phonon |
251 | |
252 | |
253 | #endif // QT_NO_PHONON_EFFECTWIDGET |
254 | |
255 | QT_END_NAMESPACE |
256 | |
257 | #include "moc_effectwidget.cpp" |
258 | |
259 | // vim: sw=4 ts=4 |
260 | |