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
46static const qreal DEFAULT_MIN = std::numeric_limits<qreal>::min();
47static const qreal DEFAULT_MAX = std::numeric_limits<qreal>::max();
48static const int DEFAULT_MIN_INT = std::numeric_limits<int>::min();
49static const int DEFAULT_MAX_INT = std::numeric_limits<int>::max();
50static const int SLIDER_RANGE = 8;
51static const int TICKINTERVAL = 4;
52
53
54QT_BEGIN_NAMESPACE
55
56#ifndef QT_NO_PHONON_EFFECTWIDGET
57
58namespace Phonon
59{
60
61EffectWidget::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
70EffectWidget::~EffectWidget()
71{
72 delete k_ptr;
73}
74
75/*
76EffectWidget::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
86EffectWidgetPrivate::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
95void 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 &para = 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
209void 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
217void 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
225void 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
233void 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
241void 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
255QT_END_NAMESPACE
256
257#include "moc_effectwidget.cpp"
258
259// vim: sw=4 ts=4
260