File indexing completed on 2024-04-21 04:43:15

0001 /*  This file is part of the KDE project
0002     Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org>
0003 
0004     This library is free software; you can redistribute it and/or
0005     modify it under the terms of the GNU Lesser General Public
0006     License as published by the Free Software Foundation; either
0007     version 2.1 of the License, or (at your option) version 3, or any
0008     later version accepted by the membership of KDE e.V. (or its
0009     successor approved by the membership of KDE e.V.), Nokia Corporation
0010     (or its successors, if any) and the KDE Free Qt Foundation, which shall
0011     act as a proxy defined in Section 6 of version 3 of the license.
0012 
0013     This library is distributed in the hope that it will be useful,
0014     but WITHOUT ANY WARRANTY; without even the implied warranty of
0015     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0016     Lesser General Public License for more details.
0017 
0018     You should have received a copy of the GNU Lesser General Public
0019     License along with this library.  If not, see <http://www.gnu.org/licenses/>.
0020 
0021 */
0022 
0023 #include "effectwidget.h"
0024 #include "effectwidget_p.h"
0025 
0026 #include <QtAlgorithms>
0027 #include <QList>
0028 
0029 #include "effect.h"
0030 #include "effectparameter.h"
0031 #include "phonondefs_p.h"
0032 #include <QBoxLayout>
0033 #include <QLabel>
0034 #include <QSpinBox>
0035 #include <QCheckBox>
0036 #include <QComboBox>
0037 #include <QSlider>
0038 #include <limits>
0039 
0040 #ifdef min
0041 #undef min
0042 #endif
0043 #ifdef max
0044 #undef max
0045 #endif
0046 static const qreal DEFAULT_MIN = std::numeric_limits<qreal>::min();
0047 static const qreal DEFAULT_MAX = std::numeric_limits<qreal>::max();
0048 static const int DEFAULT_MIN_INT = std::numeric_limits<int>::min();
0049 static const int DEFAULT_MAX_INT = std::numeric_limits<int>::max();
0050 static const int SLIDER_RANGE = 8;
0051 static const int TICKINTERVAL = 4;
0052 
0053 
0054 #ifndef QT_NO_PHONON_EFFECTWIDGET
0055 
0056 namespace Phonon
0057 {
0058 
0059 EffectWidget::EffectWidget(Effect *effect, QWidget *parent)
0060     : QWidget(parent),
0061     k_ptr(new EffectWidgetPrivate(effect))
0062 {
0063     P_D(EffectWidget);
0064     d->q_ptr = this;
0065     d->autogenerateUi();
0066 }
0067 
0068 EffectWidget::~EffectWidget()
0069 {
0070     delete k_ptr;
0071 }
0072 
0073 /*
0074 EffectWidget::EffectWidget(EffectWidgetPrivate &dd, QWidget *parent)
0075     : QWidget(parent)
0076     , k_ptr(&dd)
0077 {
0078     P_D(EffectWidget);
0079     d->q_ptr = this;
0080     d->autogenerateUi();
0081 }
0082 */
0083 
0084 EffectWidgetPrivate::EffectWidgetPrivate(Effect *e)
0085     : effect(e)
0086 {
0087     //TODO: look up whether there is a specialized widget for this effect. This
0088     //could be a DSO or a Designer ui file found via KTrader.
0089     //
0090     //if no specialized widget is available:
0091 }
0092 
0093 void EffectWidgetPrivate::autogenerateUi()
0094 {
0095     P_Q(EffectWidget);
0096     QVBoxLayout *mainLayout = new QVBoxLayout(q);
0097     mainLayout->setContentsMargins(QMargins());
0098     const QList<Phonon::EffectParameter> parameters = effect->parameters();
0099     for (int i = 0; i < parameters.count(); ++i) {
0100         const EffectParameter &para = parameters.at(i);
0101         QVariant value = effect->parameterValue(para);
0102         QHBoxLayout *pLayout = new QHBoxLayout;
0103         mainLayout->addLayout(pLayout);
0104 
0105         QLabel *label = new QLabel(q);
0106         pLayout->addWidget(label);
0107         label->setText(para.name());
0108 #ifndef QT_NO_TOOLTIP
0109         label->setToolTip(para.description());
0110 #endif
0111 
0112         QWidget *control = nullptr;
0113         switch (int(para.type())) {
0114         case QVariant::String:
0115             {
0116                 QComboBox *cb = new QComboBox(q);
0117                 control = cb;
0118                 if (value.type() == QVariant::Int) {
0119                     //value just defines the item index
0120                     for (int i = 0; i < para.possibleValues().count(); ++i) {
0121                         cb->addItem(para.possibleValues().at(i).toString());
0122                     }
0123                     cb->setCurrentIndex(value.toInt());
0124                     QObject::connect(cb, SIGNAL(currentIndexChanged(int)), q, SLOT(_k_setIntParameter(int)));
0125                 } else {
0126                     for (int i = 0; i < para.possibleValues().count(); ++i) {
0127                         const QVariant &item = para.possibleValues().at(i);
0128                         cb->addItem(item.toString());
0129                         if (item == value) {
0130                             cb->setCurrentIndex(cb->count() - 1);
0131                         }
0132                     }
0133                     QObject::connect(cb, SIGNAL(currentIndexChanged(QString)), q, SLOT(_k_setStringParameter(QString)));
0134                 }
0135             }
0136             break;
0137         case QVariant::Bool:
0138             {
0139                 QCheckBox *cb = new QCheckBox(q);
0140                 control = cb;
0141                 cb->setChecked(value.toBool());
0142                 QObject::connect(cb, SIGNAL(toggled(bool)), q, SLOT(_k_setToggleParameter(bool)));
0143             }
0144             break;
0145         case QVariant::Int:
0146             {
0147                 QSpinBox *sb = new QSpinBox(q);
0148                 control = sb;
0149                 bool minValueOk = false;
0150                 bool maxValueOk = false;
0151                 const int minValue = para.minimumValue().toInt(&minValueOk);
0152                 const int maxValue = para.maximumValue().toInt(&maxValueOk);
0153 
0154                 sb->setRange(minValueOk ? minValue : DEFAULT_MIN_INT, maxValueOk ? maxValue : DEFAULT_MAX_INT);
0155                 sb->setValue(value.toInt());
0156                 QObject::connect(sb, SIGNAL(valueChanged(int)), q, SLOT(_k_setIntParameter(int)));
0157             }
0158             break;
0159         case QMetaType::Float:
0160         case QVariant::Double:
0161             {
0162                 const qreal minValue = para.minimumValue().canConvert(QVariant::Double) ?
0163                     para.minimumValue().toReal() : DEFAULT_MIN;
0164                 const qreal maxValue = para.maximumValue().canConvert(QVariant::Double) ?
0165                     para.maximumValue().toReal() : DEFAULT_MAX;
0166 
0167                 if (minValue == -1. && maxValue == 1.) {
0168                     //Special case values between -1 and 1.0 to use a slider for improved usability
0169                     QSlider *slider = new QSlider(Qt::Horizontal, q);
0170                     control = slider;
0171                     slider->setRange(-SLIDER_RANGE, +SLIDER_RANGE);
0172                     slider->setValue(int(SLIDER_RANGE * value.toReal()));
0173                     slider->setTickPosition(QSlider::TicksBelow);
0174                     slider->setTickInterval(TICKINTERVAL);
0175                     QObject::connect(slider, SIGNAL(valueChanged(int)), q, SLOT(_k_setSliderParameter(int)));
0176                 } else {
0177                     double step = 0.1;
0178                     if (qAbs(maxValue - minValue) > 50)
0179                         step = 1.0;
0180                     QDoubleSpinBox *sb = new QDoubleSpinBox(q);
0181                     control = sb;
0182                     sb->setRange(minValue, maxValue);
0183                     sb->setValue(value.toDouble());
0184                     sb->setSingleStep(step);
0185                     QObject::connect(sb, SIGNAL(valueChanged(double)), q,
0186                         SLOT(_k_setDoubleParameter(double)));
0187                 }
0188             }
0189             break;
0190         default:
0191             break;
0192         }
0193 
0194         if (control) {
0195 #ifndef QT_NO_TOOLTIP
0196         control->setToolTip(para.description());
0197 #endif
0198 #ifndef QT_NO_SHORTCUT
0199             label->setBuddy(control);
0200 #endif
0201             pLayout->addWidget(control);
0202             parameterForObject.insert(control, para);
0203         }
0204     }
0205 }
0206 
0207 void EffectWidgetPrivate::_k_setToggleParameter(bool checked)
0208 {
0209     P_Q(EffectWidget);
0210     if (parameterForObject.contains(q->sender())) {
0211         effect->setParameterValue(parameterForObject[q->sender()], checked);
0212     }
0213 }
0214 
0215 void EffectWidgetPrivate::_k_setIntParameter(int value)
0216 {
0217     P_Q(EffectWidget);
0218     if (parameterForObject.contains(q->sender())) {
0219         effect->setParameterValue(parameterForObject[q->sender()], value);
0220     }
0221 }
0222 
0223 void EffectWidgetPrivate::_k_setDoubleParameter(double value)
0224 {
0225     P_Q(EffectWidget);
0226     if (parameterForObject.contains(q->sender())) {
0227         effect->setParameterValue(parameterForObject[q->sender()], value);
0228     }
0229 }
0230 
0231 void EffectWidgetPrivate::_k_setStringParameter(const QString &value)
0232 {
0233     P_Q(EffectWidget);
0234     if (parameterForObject.contains(q->sender())) {
0235         effect->setParameterValue(parameterForObject[q->sender()], value);
0236     }
0237 }
0238 
0239 void EffectWidgetPrivate::_k_setSliderParameter(int value)
0240 {
0241     P_Q(EffectWidget);
0242     if (parameterForObject.contains(q->sender())) {
0243         effect->setParameterValue(parameterForObject[q->sender()], double(value) / double(SLIDER_RANGE));
0244     }
0245 }
0246 
0247 
0248 } // namespace Phonon
0249 
0250 
0251 #endif // QT_NO_PHONON_EFFECTWIDGET
0252 
0253 #include "moc_effectwidget.cpp"
0254 
0255 // vim: sw=4 ts=4