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 &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
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