From 7e12c66a6ae6d7d8f57b3d3c74a0bf73b92dd854 Mon Sep 17 00:00:00 2001 From: Till Theato Date: Sat, 22 Jan 2011 15:36:51 +0000 Subject: [PATCH] Add "drag value" widget: Numbers can be edited by dragging horizontal on the widget, by using the mouse wheel or by using the keyboard. svn path=/trunk/kdenlive/; revision=5341 --- src/CMakeLists.txt | 1 + src/doubleparameterwidget.cpp | 23 ++- src/doubleparameterwidget.h | 4 + src/dragvalue.cpp | 254 ++++++++++++++++++++++++++++++++++ src/dragvalue.h | 106 ++++++++++++++ 5 files changed, 385 insertions(+), 3 deletions(-) create mode 100644 src/dragvalue.cpp create mode 100644 src/dragvalue.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 49b5c730..11f3e5ff 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -266,6 +266,7 @@ set(kdenlive_SRCS beziercurve/beziersplinewidget.cpp beziercurve/bpoint.cpp beziercurve/cubicbezierspline.cpp + dragvalue.cpp ) add_definitions(${KDE4_DEFINITIONS}) diff --git a/src/doubleparameterwidget.cpp b/src/doubleparameterwidget.cpp index f9e8f5e1..96a80c0d 100644 --- a/src/doubleparameterwidget.cpp +++ b/src/doubleparameterwidget.cpp @@ -19,6 +19,7 @@ #include "doubleparameterwidget.h" +#include "dragvalue.h" #include #include @@ -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(); diff --git a/src/doubleparameterwidget.h b/src/doubleparameterwidget.h index e677ad01..f7d529b5 100644 --- a/src/doubleparameterwidget.h +++ b/src/doubleparameterwidget.h @@ -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 index 00000000..279cf025 --- /dev/null +++ b/src/dragvalue.cpp @@ -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 . * + ***************************************************************************/ + +#include "dragvalue.h" +#include "kdenlivesettings.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +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 index 00000000..5c8b4f5a --- /dev/null +++ b/src/dragvalue.h @@ -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 . * + ***************************************************************************/ + +#ifndef DRAGVALUE_H_ +#define DRAGVALUE_H_ + +#include + +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 -- 2.39.2