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 <QtAlgorithms> |
27 | #include <QList> |
28 | |
29 | #include "effect.h" |
30 | #include "effectparameter.h" |
31 | #include "phonondefs_p.h" |
32 | #include <QBoxLayout> |
33 | #include <QLabel> |
34 | #include <QSpinBox> |
35 | #include <QCheckBox> |
36 | #include <QComboBox> |
37 | #include <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 | #ifndef QT_NO_PHONON_EFFECTWIDGET |
55 | |
56 | namespace Phonon |
57 | { |
58 | |
59 | EffectWidget::EffectWidget(Effect *effect, QWidget *parent) |
60 | : QWidget(parent), |
61 | k_ptr(new EffectWidgetPrivate(effect)) |
62 | { |
63 | P_D(EffectWidget); |
64 | d->q_ptr = this; |
65 | d->autogenerateUi(); |
66 | } |
67 | |
68 | EffectWidget::~EffectWidget() |
69 | { |
70 | delete k_ptr; |
71 | } |
72 | |
73 | /* |
74 | EffectWidget::EffectWidget(EffectWidgetPrivate &dd, QWidget *parent) |
75 | : QWidget(parent) |
76 | , k_ptr(&dd) |
77 | { |
78 | P_D(EffectWidget); |
79 | d->q_ptr = this; |
80 | d->autogenerateUi(); |
81 | } |
82 | */ |
83 | |
84 | EffectWidgetPrivate::EffectWidgetPrivate(Effect *e) |
85 | : effect(e) |
86 | { |
87 | //TODO: look up whether there is a specialized widget for this effect. This |
88 | //could be a DSO or a Designer ui file found via KTrader. |
89 | // |
90 | //if no specialized widget is available: |
91 | } |
92 | |
93 | void EffectWidgetPrivate::autogenerateUi() |
94 | { |
95 | P_Q(EffectWidget); |
96 | QVBoxLayout *mainLayout = new QVBoxLayout(q); |
97 | mainLayout->setContentsMargins(QMargins()); |
98 | const QList<Phonon::EffectParameter> parameters = effect->parameters(); |
99 | for (int i = 0; i < parameters.count(); ++i) { |
100 | const EffectParameter ¶ = parameters.at(i); |
101 | QVariant value = effect->parameterValue(para); |
102 | QHBoxLayout *pLayout = new QHBoxLayout; |
103 | mainLayout->addLayout(layout: pLayout); |
104 | |
105 | QLabel *label = new QLabel(q); |
106 | pLayout->addWidget(label); |
107 | label->setText(para.name()); |
108 | #ifndef QT_NO_TOOLTIP |
109 | label->setToolTip(para.description()); |
110 | #endif |
111 | |
112 | QWidget *control = nullptr; |
113 | switch (int(para.type())) { |
114 | case QVariant::String: |
115 | { |
116 | QComboBox *cb = new QComboBox(q); |
117 | control = cb; |
118 | if (value.type() == QVariant::Int) { |
119 | //value just defines the item index |
120 | for (int i = 0; i < para.possibleValues().count(); ++i) { |
121 | cb->addItem(atext: para.possibleValues().at(i).toString()); |
122 | } |
123 | cb->setCurrentIndex(value.toInt()); |
124 | QObject::connect(sender: cb, SIGNAL(currentIndexChanged(int)), receiver: q, SLOT(_k_setIntParameter(int))); |
125 | } else { |
126 | for (int i = 0; i < para.possibleValues().count(); ++i) { |
127 | const QVariant &item = para.possibleValues().at(i); |
128 | cb->addItem(atext: item.toString()); |
129 | if (item == value) { |
130 | cb->setCurrentIndex(cb->count() - 1); |
131 | } |
132 | } |
133 | QObject::connect(sender: cb, SIGNAL(currentIndexChanged(QString)), receiver: q, SLOT(_k_setStringParameter(QString))); |
134 | } |
135 | } |
136 | break; |
137 | case QVariant::Bool: |
138 | { |
139 | QCheckBox *cb = new QCheckBox(q); |
140 | control = cb; |
141 | cb->setChecked(value.toBool()); |
142 | QObject::connect(sender: cb, SIGNAL(toggled(bool)), receiver: q, SLOT(_k_setToggleParameter(bool))); |
143 | } |
144 | break; |
145 | case QVariant::Int: |
146 | { |
147 | QSpinBox *sb = new QSpinBox(q); |
148 | control = sb; |
149 | bool minValueOk = false; |
150 | bool maxValueOk = false; |
151 | const int minValue = para.minimumValue().toInt(ok: &minValueOk); |
152 | const int maxValue = para.maximumValue().toInt(ok: &maxValueOk); |
153 | |
154 | sb->setRange(min: minValueOk ? minValue : DEFAULT_MIN_INT, max: maxValueOk ? maxValue : DEFAULT_MAX_INT); |
155 | sb->setValue(value.toInt()); |
156 | QObject::connect(sender: sb, SIGNAL(valueChanged(int)), receiver: q, SLOT(_k_setIntParameter(int))); |
157 | } |
158 | break; |
159 | case QMetaType::Float: |
160 | case QVariant::Double: |
161 | { |
162 | const qreal minValue = para.minimumValue().canConvert(targetTypeId: QVariant::Double) ? |
163 | para.minimumValue().toReal() : DEFAULT_MIN; |
164 | const qreal maxValue = para.maximumValue().canConvert(targetTypeId: QVariant::Double) ? |
165 | para.maximumValue().toReal() : DEFAULT_MAX; |
166 | |
167 | if (minValue == -1. && maxValue == 1.) { |
168 | //Special case values between -1 and 1.0 to use a slider for improved usability |
169 | QSlider *slider = new QSlider(Qt::Horizontal, q); |
170 | control = slider; |
171 | slider->setRange(min: -SLIDER_RANGE, max: +SLIDER_RANGE); |
172 | slider->setValue(int(SLIDER_RANGE * value.toReal())); |
173 | slider->setTickPosition(QSlider::TicksBelow); |
174 | slider->setTickInterval(TICKINTERVAL); |
175 | QObject::connect(sender: slider, SIGNAL(valueChanged(int)), receiver: q, SLOT(_k_setSliderParameter(int))); |
176 | } else { |
177 | double step = 0.1; |
178 | if (qAbs(t: maxValue - minValue) > 50) |
179 | step = 1.0; |
180 | QDoubleSpinBox *sb = new QDoubleSpinBox(q); |
181 | control = sb; |
182 | sb->setRange(min: minValue, max: maxValue); |
183 | sb->setValue(value.toDouble()); |
184 | sb->setSingleStep(step); |
185 | QObject::connect(sender: sb, SIGNAL(valueChanged(double)), receiver: q, |
186 | SLOT(_k_setDoubleParameter(double))); |
187 | } |
188 | } |
189 | break; |
190 | default: |
191 | break; |
192 | } |
193 | |
194 | if (control) { |
195 | #ifndef QT_NO_TOOLTIP |
196 | control->setToolTip(para.description()); |
197 | #endif |
198 | #ifndef QT_NO_SHORTCUT |
199 | label->setBuddy(control); |
200 | #endif |
201 | pLayout->addWidget(control); |
202 | parameterForObject.insert(key: control, value: para); |
203 | } |
204 | } |
205 | } |
206 | |
207 | void EffectWidgetPrivate::_k_setToggleParameter(bool checked) |
208 | { |
209 | P_Q(EffectWidget); |
210 | if (parameterForObject.contains(key: q->sender())) { |
211 | effect->setParameterValue(parameterForObject[q->sender()], value: checked); |
212 | } |
213 | } |
214 | |
215 | void EffectWidgetPrivate::_k_setIntParameter(int value) |
216 | { |
217 | P_Q(EffectWidget); |
218 | if (parameterForObject.contains(key: q->sender())) { |
219 | effect->setParameterValue(parameterForObject[q->sender()], value); |
220 | } |
221 | } |
222 | |
223 | void EffectWidgetPrivate::_k_setDoubleParameter(double value) |
224 | { |
225 | P_Q(EffectWidget); |
226 | if (parameterForObject.contains(key: q->sender())) { |
227 | effect->setParameterValue(parameterForObject[q->sender()], value); |
228 | } |
229 | } |
230 | |
231 | void EffectWidgetPrivate::_k_setStringParameter(const QString &value) |
232 | { |
233 | P_Q(EffectWidget); |
234 | if (parameterForObject.contains(key: q->sender())) { |
235 | effect->setParameterValue(parameterForObject[q->sender()], value); |
236 | } |
237 | } |
238 | |
239 | void EffectWidgetPrivate::_k_setSliderParameter(int value) |
240 | { |
241 | P_Q(EffectWidget); |
242 | if (parameterForObject.contains(key: q->sender())) { |
243 | effect->setParameterValue(parameterForObject[q->sender()], value: double(value) / double(SLIDER_RANGE)); |
244 | } |
245 | } |
246 | |
247 | |
248 | } // namespace Phonon |
249 | |
250 | |
251 | #endif // QT_NO_PHONON_EFFECTWIDGET |
252 | |
253 | #include "moc_effectwidget.cpp" |
254 | |
255 | // vim: sw=4 ts=4 |
256 | |