]> git.sesse.net Git - kdenlive/commitdiff
Add "drag value" widget: Numbers can be edited by dragging horizontal on the widget...
authorTill Theato <root@ttill.de>
Sat, 22 Jan 2011 15:36:51 +0000 (15:36 +0000)
committerTill Theato <root@ttill.de>
Sat, 22 Jan 2011 15:36:51 +0000 (15:36 +0000)
svn path=/trunk/kdenlive/; revision=5341

src/CMakeLists.txt
src/doubleparameterwidget.cpp
src/doubleparameterwidget.h
src/dragvalue.cpp [new file with mode: 0644]
src/dragvalue.h [new file with mode: 0644]

index 49b5c730dd50b0182cd551c70999c1748b0da7a9..11f3e5ff732a59a74f674953632eeacf9d658a9b 100644 (file)
@@ -266,6 +266,7 @@ set(kdenlive_SRCS
   beziercurve/beziersplinewidget.cpp
   beziercurve/bpoint.cpp
   beziercurve/cubicbezierspline.cpp
+  dragvalue.cpp
 )
 
 add_definitions(${KDE4_DEFINITIONS})
index f9e8f5e1edfbd64d0f6df050d84d3c4e3fc4a9c7..96a80c0d37ab168982c8b4436dd609d3a3de325b 100644 (file)
@@ -19,6 +19,7 @@
 
 
 #include "doubleparameterwidget.h"
+#include "dragvalue.h"
 
 #include <QGridLayout>
 #include <QLabel>
@@ -46,12 +47,18 @@ DoubleParameterWidget::DoubleParameterWidget(const QString &name, int value, int
     //m_slider->setPageStep((max - min) / 10);
     layout->addWidget(m_slider, 0, 1);
 
+    m_dragVal = new DragValue(this);
+    m_dragVal->setRange(min, max);
+    m_dragVal->setPrecision(0);
+    layout->addWidget(m_dragVal, 0, 2);
+
     m_spinBox = new QSpinBox(this);
     m_spinBox->setRange(min, max);
     m_spinBox->setKeyboardTracking(false);
     if (!suffix.isEmpty())
         m_spinBox->setSuffix(suffix);
-    layout->addWidget(m_spinBox, 0, 2);
+    //layout->addWidget(m_spinBox, 0, 2);
+    m_spinBox->setHidden(true);
 
     QToolButton *reset = new QToolButton(this);
     reset->setAutoRaise(true);
@@ -65,31 +72,41 @@ DoubleParameterWidget::DoubleParameterWidget(const QString &name, int value, int
     m_commentLabel->setAlignment(Qt::AlignLeft | Qt::AlignTop);
     m_commentLabel->setFrameShape(QFrame::StyledPanel);
     m_commentLabel->setFrameShadow(QFrame::Raised);
-    m_commentLabel->setBackgroundRole(QPalette::AlternateBase);
     m_commentLabel->setHidden(true);
     layout->addWidget(m_commentLabel, 1, 0, 1, -1);
 
     connect(m_slider,  SIGNAL(valueChanged(int)), this, SLOT(setValue(int)));
+    connect(m_dragVal, SIGNAL(valueChanged(qreal, bool)), this, SLOT(slotSetValue(qreal, bool)));
     connect(m_spinBox, SIGNAL(valueChanged(int)), this, SLOT(setValue(int)));
     connect(reset,     SIGNAL(clicked(bool)),     this, SLOT(slotReset()));
 
-    m_spinBox->setValue(value);
+    //m_spinBox->setValue(value);
+    m_dragVal->setValue(value);
 }
 
 void DoubleParameterWidget::setValue(int value)
 {
     m_slider->blockSignals(true);
     m_spinBox->blockSignals(true);
+    m_dragVal->blockSignals(true);
 
     m_slider->setValue(value);
     m_spinBox->setValue(value);
+    m_dragVal->setValue(value);
 
     m_slider->blockSignals(false);
     m_spinBox->blockSignals(false);
+    m_dragVal->blockSignals(false);
 
     emit valueChanged(value);
 }
 
+void DoubleParameterWidget::slotSetValue(qreal value, bool final)
+{
+    if (final)
+        setValue((int)value);
+}
+
 int DoubleParameterWidget::getValue()
 {
     return m_spinBox->value();
index e677ad01b37f85cb5aea47ba9a93d13885ffa242..f7d529b5743a71d793e2dadab8275bd2c9de7db8 100644 (file)
@@ -26,6 +26,7 @@
 class QLabel;
 class QSlider;
 class QSpinBox;
+class DragValue;
 
 /**
  * @class DoubleParameterWidget
@@ -67,11 +68,14 @@ private slots:
     /** @brief Shows/Hides the comment label. */
     void slotShowComment(bool show);
 
+    void slotSetValue(qreal value, bool final);
+
 private:
     int m_default;
     QLabel *m_name;
     QSlider *m_slider;
     QSpinBox *m_spinBox;
+    DragValue *m_dragVal;
     QLabel *m_commentLabel;
     
 signals:
diff --git a/src/dragvalue.cpp b/src/dragvalue.cpp
new file mode 100644 (file)
index 0000000..279cf02
--- /dev/null
@@ -0,0 +1,254 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Till Theato (root@ttill.de)                     *
+ *   This file is part of Kdenlive (www.kdenlive.org).                     *
+ *                                                                         *
+ *   Kdenlive is free software: you can redistribute it and/or modify      *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation, either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   Kdenlive is distributed in the hope that it will be useful,           *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with Kdenlive.  If not, see <http://www.gnu.org/licenses/>.     *
+ ***************************************************************************/
+
+#include "dragvalue.h"
+#include "kdenlivesettings.h"
+
+#include <math.h>
+
+#include <QHBoxLayout>
+#include <QToolButton>
+#include <QLineEdit>
+#include <QDoubleValidator>
+#include <QIntValidator>
+#include <QMouseEvent>
+#include <QFocusEvent>
+#include <QWheelEvent>
+#include <QApplication>
+
+#include <KColorScheme>
+#include <KIcon>
+
+DragValue::DragValue(QWidget* parent) :
+        QWidget(parent),
+        m_maximum(100),
+        m_minimum(0),
+        m_precision(2),
+        m_step(1),
+        m_dragMode(false),
+        m_finalValue(true)
+{
+    setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
+    setFocusPolicy(Qt::StrongFocus);
+
+    QHBoxLayout *l = new QHBoxLayout(this);
+    l->setSpacing(0);
+    l->setMargin(0);
+
+    /*m_buttonDec = new QToolButton(this);
+    m_buttonDec->setIcon(KIcon("arrow-left"));
+    m_buttonDec->setIconSize(QSize(12, 12));
+    m_buttonDec->setObjectName("ButtonDec");
+    l->addWidget(m_buttonDec);*/
+
+    m_edit = new QLineEdit(this);
+    m_edit->setValidator(new QDoubleValidator(m_minimum, m_maximum, m_precision, this));
+    m_edit->setAlignment(Qt::AlignCenter);
+    m_edit->setEnabled(false);
+    l->addWidget(m_edit);
+
+    /*m_buttonInc = new QToolButton(this);
+    m_buttonInc->setIcon(KIcon("arrow-right"));
+    m_buttonInc->setIconSize(QSize(12, 12));
+    m_buttonInc->setObjectName("ButtonInc");
+    l->addWidget(m_buttonInc);*/
+
+    QPalette p = palette();
+    KColorScheme scheme(p.currentColorGroup(), KColorScheme::View, KSharedConfig::openConfig(KdenliveSettings::colortheme()));
+    QColor bg = scheme.background(KColorScheme::LinkBackground).color();
+    QColor fg = scheme.foreground(KColorScheme::LinkText).color();
+    QColor editbg = scheme.background(KColorScheme::ActiveBackground).color();
+    QColor editfg = scheme.foreground(KColorScheme::ActiveText).color();
+    QString stylesheet(QString("QLineEdit { background-color: rgb(%1, %2, %3); border: 1px solid rgb(%1, %2, %3); border-radius: 5px; padding: 0px; color: rgb(%4, %5, %6); } QLineEdit::disabled { color: rgb(%4, %5, %6); }")
+                        .arg(bg.red()).arg(bg.green()).arg(bg.blue())
+                        .arg(fg.red()).arg(fg.green()).arg(fg.blue()));
+    stylesheet.append(QString("QLineEdit::focus, QLineEdit::enabled { background-color: rgb(%1, %2, %3); color: rgb(%4, %5, %6); }")
+                        .arg(editbg.red()).arg(editbg.green()).arg(editbg.blue())
+                        .arg(editfg.red()).arg(editfg.green()).arg(editfg.blue()));
+/*     QString stylesheet(QString("QLineEdit { background-color: rgb(%1, %2, %3); border: 1px solid rgb(%1, %2, %3); padding: 2px; padding-bottom: 0px; border-top-left-radius: 7px; border-top-right-radius: 7px; }")
+                         .arg(bg.red()).arg(bg.green()).arg(bg.blue()));
+     stylesheet.append(QString("QLineEdit::focus, QLineEdit::enabled { background-color: rgb(%1, %2, %3); color: rgb(%4, %5, %6); }")
+                         .arg(textbg.red()).arg(textbg.green()).arg(textbg.blue())
+                         .arg(textfg.red()).arg(textfg.green()).arg(textfg.blue()));
+    QString stylesheet(QString("* { background-color: rgb(%1, %2, %3); margin: 0px; }").arg(bg.red()).arg(bg.green()).arg(bg.blue()));
+    stylesheet.append(QString("QLineEdit { border: 0px; height: 100%; } QLineEdit::focus, QLineEdit::enabled { background-color: rgb(%1, %2, %3); color: rgb(%4, %5, %6); }")
+                         .arg(textbg.red()).arg(textbg.green()).arg(textbg.blue())
+                         .arg(textfg.red()).arg(textfg.green()).arg(textfg.blue()));
+    stylesheet.append(QString("QToolButton { border: 1px solid rgb(%1, %2, %3); }").arg(bg.red()).arg(bg.green()).arg(bg.blue()));
+    stylesheet.append(QString("QToolButton#ButtonDec { border-top-left-radius: 5px; border-bottom-left-radius: 5px; }"));
+    stylesheet.append(QString("QToolButton#ButtonInc { border-top-right-radius: 5px; border-bottom-right-radius: 5px; }"));*/
+    setStyleSheet(stylesheet);
+
+    updateMaxWidth();
+
+    /*connect(m_buttonDec, SIGNAL(clicked(bool)), this, SLOT(slotValueDec()));
+    connect(m_buttonInc, SIGNAL(clicked(bool)), this, SLOT(slotValueInc()));*/
+    connect(m_edit, SIGNAL(editingFinished()), this, SLOT(slotEditingFinished()));
+}
+
+DragValue::~DragValue()
+{
+    delete m_edit;
+    /*delete m_buttonInc;
+    delete m_buttonDec;*/
+}
+
+int DragValue::precision() const
+{
+    return m_precision;
+}
+
+qreal DragValue::maximum() const
+{
+    return m_maximum;
+}
+
+qreal DragValue::minimum() const
+{
+    return m_minimum;
+}
+
+qreal DragValue::value() const
+{
+    return m_edit->text().toDouble();
+}
+
+void DragValue::setMaximum(qreal max)
+{
+    m_maximum = max;
+    updateMaxWidth();
+}
+
+void DragValue::setMinimum(qreal min)
+{
+    m_minimum = min;
+    updateMaxWidth();
+}
+
+void DragValue::setRange(qreal min, qreal max)
+{
+    m_maximum = max;
+    m_minimum = min;
+    updateMaxWidth();
+}
+
+void DragValue::setPrecision(int precision)
+{
+    m_precision = precision;
+    if (precision == 0)
+        m_edit->setValidator(new QIntValidator(m_minimum, m_maximum, this));
+    else
+        m_edit->setValidator(new QDoubleValidator(m_minimum, m_maximum, precision, this));
+}
+
+void DragValue::setStep(qreal step)
+{
+    m_step = step;
+}
+
+void DragValue::setValue(qreal value, bool final)
+{
+    m_finalValue = final;
+    value = qBound(m_minimum, value, m_maximum);
+
+    m_edit->setText(QString::number(value, 'f', m_precision));
+
+    emit valueChanged(value, final);
+}
+
+void DragValue::mousePressEvent(QMouseEvent* e)
+{
+    if (e->button() == Qt::LeftButton) {
+        m_dragStartPosition = m_dragLastPosition = e->pos();
+        m_dragMode = true;
+        e->accept();
+    }
+}
+
+void DragValue::mouseMoveEvent(QMouseEvent* e)
+{
+    if (m_dragMode && (e->pos() - m_dragStartPosition).manhattanLength() >= QApplication::startDragDistance()) {
+        int diffDistance = e->x() - m_dragLastPosition.x();
+        int direction = diffDistance > 0 ? 1 : -1; // since pow loses this info
+        setValue(value() + direction * pow(e->x() - m_dragLastPosition.x(), 2) / m_step, false);
+        m_dragLastPosition = e->pos();
+        e->accept();
+    }
+}
+
+void DragValue::mouseReleaseEvent(QMouseEvent* e)
+{
+    m_dragMode = false;
+    if (m_finalValue) {
+        m_edit->setEnabled(true);
+        m_edit->setFocus(Qt::MouseFocusReason);
+    } else {
+        setValue(value(), true);
+        e->accept();
+    }
+}
+
+void DragValue::wheelEvent(QWheelEvent* e)
+{
+    if (e->delta() > 0)
+        slotValueInc();
+    else
+        slotValueDec();
+}
+
+void DragValue::focusInEvent(QFocusEvent* e)
+{
+    if (e->reason() == Qt::TabFocusReason || e->reason() == Qt::BacktabFocusReason) {
+        m_edit->setEnabled(true);
+        m_edit->setFocus(e->reason());
+    } else {
+        QWidget::focusInEvent(e);
+    }
+}
+
+void DragValue::slotValueInc()
+{
+    setValue(m_edit->text().toDouble() + m_step);
+}
+
+void DragValue::slotValueDec()
+{
+    setValue(m_edit->text().toDouble() - m_step);
+}
+
+void DragValue::slotEditingFinished()
+{
+    m_finalValue = true;
+    qreal value = m_edit->text().toDouble();
+    m_edit->setEnabled(false);
+    emit valueChanged(value, true);
+}
+
+void DragValue::updateMaxWidth()
+{
+    int val = (int)(log10(qAbs(m_maximum) > qAbs(m_minimum) ? qAbs(m_maximum) : qAbs(m_minimum)) + .5);
+    val += m_precision;
+    if (m_precision)
+        val += 1;
+    if (m_minimum < 0)
+        val += 1;
+    QFontMetrics fm = m_edit->fontMetrics();
+    m_edit->setMaximumWidth(fm.width(QString().rightJustified(val, '8')));
+}
+
+#include "dragvalue.moc"
diff --git a/src/dragvalue.h b/src/dragvalue.h
new file mode 100644 (file)
index 0000000..5c8b4f5
--- /dev/null
@@ -0,0 +1,106 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Till Theato (root@ttill.de)                     *
+ *   This file is part of Kdenlive (www.kdenlive.org).                     *
+ *                                                                         *
+ *   Kdenlive is free software: you can redistribute it and/or modify      *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation, either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   Kdenlive is distributed in the hope that it will be useful,           *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with Kdenlive.  If not, see <http://www.gnu.org/licenses/>.     *
+ ***************************************************************************/
+
+#ifndef DRAGVALUE_H_
+#define DRAGVALUE_H_
+
+#include <QWidget>
+
+class QValidator;
+class QToolButton;
+class QLineEdit;
+
+/**
+ * @brief A widget for modifing numbers by dragging, using the mouse wheel or entering them with the keyboard.
+ */
+
+class DragValue : public QWidget
+{
+    Q_OBJECT
+
+public:
+    DragValue(QWidget* parent = 0);
+    virtual ~DragValue();
+
+    /** @brief Returns the precision = number of decimals */
+    int precision() const;
+    /** @brief Returns the maximum value */
+    qreal minimum() const;
+    /** @brief Returns the minimum value */
+    qreal maximum() const;
+
+    /** @brief Sets the precision (number of decimals) to @param precision. */
+    void setPrecision(int precision);
+    /** @brief Sets the minimum value. */
+    void setMinimum(qreal min);
+    /** @brief Sets the maximum value. */
+    void setMaximum(qreal max);
+    /** @brief Sets minimum and maximum value. */
+    void setRange(qreal min, qreal max);
+    /** @brief Sets the size of a step (when dragging or using the mouse wheel). */
+    void setStep(qreal step);
+
+    /** @brief Returns the current value */
+    qreal value() const;
+    
+public slots:
+    /** @brief Sets the value (forced to be in the valid range) and emits valueChanged. */
+    void setValue(qreal value, bool final = true);
+
+signals:
+    void valueChanged(qreal value, bool final);
+
+
+
+
+    /*
+     * Private
+     */
+
+protected:
+    virtual void mousePressEvent(QMouseEvent *e);
+    virtual void mouseMoveEvent(QMouseEvent *e);
+    virtual void mouseReleaseEvent(QMouseEvent *e);
+    /** @brief Forwards tab focus to lineedit since it is disabled. */
+    virtual void focusInEvent(QFocusEvent *e);
+    //virtual void keyPressEvent(QKeyEvent *e);
+    virtual void wheelEvent(QWheelEvent *e);
+
+private slots:
+    void slotValueInc();
+    void slotValueDec();
+    void slotEditingFinished();
+
+private:
+    qreal m_maximum;
+    qreal m_minimum;
+    int m_precision;
+    qreal m_step;
+    QLineEdit *m_edit;
+    /*QToolButton *m_buttonInc;
+    QToolButton *m_buttonDec;*/
+    QPoint m_dragStartPosition;
+    QPoint m_dragLastPosition;
+    bool m_dragMode;
+    bool m_finalValue;
+
+    /** @brief Sets the maximum width of the widget so that there is enough space for the widest possible value. */
+    void updateMaxWidth();
+};
+
+#endif