X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fdragvalue.cpp;h=64a8f2eec69f53b43f8ed4c0ffc14f31fc13aa5e;hb=56aee6aedeeed3efd10ada8fe3c229eddc01ef05;hp=279cf02519fd957c9a9f8fc40d4a625bb8483919;hpb=7e12c66a6ae6d7d8f57b3d3c74a0bf73b92dd854;p=kdenlive diff --git a/src/dragvalue.cpp b/src/dragvalue.cpp index 279cf025..64a8f2ee 100644 --- a/src/dragvalue.cpp +++ b/src/dragvalue.cpp @@ -1,5 +1,6 @@ /*************************************************************************** * Copyright (C) 2011 by Till Theato (root@ttill.de) * + * Copyright (C) 2011 by Jean-Baptiste Mardelle (jb@kdenlive.org) * * This file is part of Kdenlive (www.kdenlive.org). * * * * Kdenlive is free software: you can redistribute it and/or modify * @@ -30,87 +31,146 @@ #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) +#include +#include + + +DragValue::DragValue(const QString &label, double defaultValue, int decimals, double min, double max, int id, const QString &suffix, bool showSlider, QWidget* parent) : + QWidget(parent), + m_maximum(max), + m_minimum(min), + m_decimals(decimals), + m_default(defaultValue), + m_id(id), + m_intEdit(NULL), + m_doubleEdit(NULL) { - setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred); + if (showSlider) setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); + else setSizePolicy(QSizePolicy::Maximum, QSizePolicy::MinimumExpanding); setFocusPolicy(Qt::StrongFocus); - - QHBoxLayout *l = new QHBoxLayout(this); + setContextMenuPolicy(Qt::CustomContextMenu); + setFocusPolicy(Qt::StrongFocus); + + QHBoxLayout *l = new QHBoxLayout; 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())); + l->setContentsMargins(0, 0, 0, 0); + m_label = new CustomLabel(label, showSlider, m_maximum - m_minimum, this); + l->addWidget(m_label); + if (decimals == 0) { + m_label->setMaximum(max - min); + m_label->setStep(1); + m_intEdit = new QSpinBox(this); + m_intEdit->setObjectName("dragBox"); + m_intEdit->setFocusPolicy(Qt::StrongFocus); + if (!suffix.isEmpty()) m_intEdit->setSuffix(suffix); + m_intEdit->setKeyboardTracking(false); + m_intEdit->setButtonSymbols(QAbstractSpinBox::NoButtons); + m_intEdit->setAlignment(Qt::AlignRight | Qt::AlignVCenter); + m_intEdit->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); + m_intEdit->setRange((int) m_minimum, (int)m_maximum); + l->addWidget(m_intEdit); + connect(m_intEdit, SIGNAL(valueChanged(int)), this, SLOT(slotSetValue(int))); + connect(m_intEdit, SIGNAL(editingFinished()), this, SLOT(slotEditingFinished())); + } else { + m_doubleEdit = new QDoubleSpinBox(this); + m_doubleEdit->setDecimals(decimals); + m_doubleEdit->setFocusPolicy(Qt::StrongFocus); + m_doubleEdit->setObjectName("dragBox"); + if (!suffix.isEmpty()) m_doubleEdit->setSuffix(suffix); + m_doubleEdit->setKeyboardTracking(false); + m_doubleEdit->setButtonSymbols(QAbstractSpinBox::NoButtons); + m_doubleEdit->setAlignment(Qt::AlignRight | Qt::AlignVCenter); + m_doubleEdit->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); + m_doubleEdit->setRange(m_minimum, m_maximum); + double factor = 100; + if (m_maximum - m_minimum > 10000) factor = 1000; + m_label->setStep(1); + m_doubleEdit->setSingleStep((m_maximum - m_minimum) / factor); + l->addWidget(m_doubleEdit); + connect(m_doubleEdit, SIGNAL(valueChanged(double)), this, SLOT(slotSetValue(double))); + connect(m_doubleEdit, SIGNAL(editingFinished()), this, SLOT(slotEditingFinished())); + } + + connect(m_label, SIGNAL(valueChanged(double,bool)), this, SLOT(setValueFromProgress(double,bool))); + connect(m_label, SIGNAL(resetValue()), this, SLOT(slotReset())); + setLayout(l); + if (m_intEdit) + m_label->setMaximumHeight(m_intEdit->sizeHint().height()); + else + m_label->setMaximumHeight(m_doubleEdit->sizeHint().height()); + + m_menu = new QMenu(this); + + m_scale = new KSelectAction(i18n("Scaling"), this); + m_scale->addAction(i18n("Normal scale")); + m_scale->addAction(i18n("Pixel scale")); + m_scale->addAction(i18n("Nonlinear scale")); + m_scale->setCurrentItem(KdenliveSettings::dragvalue_mode()); + m_menu->addAction(m_scale); + + m_directUpdate = new QAction(i18n("Direct update"), this); + m_directUpdate->setCheckable(true); + m_directUpdate->setChecked(KdenliveSettings::dragvalue_directupdate()); + m_menu->addAction(m_directUpdate); + + QAction *reset = new QAction(KIcon("edit-undo"), i18n("Reset value"), this); + connect(reset, SIGNAL(triggered()), this, SLOT(slotReset())); + m_menu->addAction(reset); + + if (m_id > -1) { + QAction *timeline = new QAction(KIcon("go-jump"), i18n("Show %1 in timeline", label), this); + connect(timeline, SIGNAL(triggered()), this, SLOT(slotSetInTimeline())); + connect(m_label, SIGNAL(setInTimeline()), this, SLOT(slotSetInTimeline())); + m_menu->addAction(timeline); + } + + connect(this, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(slotShowContextMenu(QPoint))); + connect(m_scale, SIGNAL(triggered(int)), this, SLOT(slotSetScaleMode(int))); + connect(m_directUpdate, SIGNAL(triggered(bool)), this, SLOT(slotSetDirectUpdate(bool))); } + DragValue::~DragValue() { - delete m_edit; - /*delete m_buttonInc; - delete m_buttonDec;*/ + delete m_intEdit; + delete m_doubleEdit; + delete m_menu; + //delete m_scale; + //delete m_directUpdate; +} + +int DragValue::spinSize() +{ + if (m_intEdit) + return m_intEdit->sizeHint().width(); + else + return m_doubleEdit->sizeHint().width(); +} + +void DragValue::setSpinSize(int width) +{ + if (m_intEdit) + m_intEdit->setMinimumWidth(width); + else + m_doubleEdit->setMinimumWidth(width); +} + +void DragValue::slotSetInTimeline() +{ + emit inTimeline(m_id); } int DragValue::precision() const { - return m_precision; + return m_decimals; } qreal DragValue::maximum() const @@ -125,130 +185,338 @@ qreal DragValue::minimum() const qreal DragValue::value() const { - return m_edit->text().toDouble(); + if (m_intEdit) return m_intEdit->value(); + else return m_doubleEdit->value(); } void DragValue::setMaximum(qreal max) { - m_maximum = max; - updateMaxWidth(); + if (m_maximum != max) { + m_maximum = max; + if (m_intEdit) + m_intEdit->setRange(m_minimum, m_maximum); + else + m_doubleEdit->setRange(m_minimum, m_maximum); + } } void DragValue::setMinimum(qreal min) { - m_minimum = min; - updateMaxWidth(); + if (m_minimum != min) { + m_minimum = min; + if (m_intEdit) + m_intEdit->setRange(m_minimum, m_maximum); + else + m_doubleEdit->setRange(m_minimum, m_maximum); + } } void DragValue::setRange(qreal min, qreal max) { m_maximum = max; m_minimum = min; - updateMaxWidth(); + if (m_intEdit) + m_intEdit->setRange(m_minimum, m_maximum); + else + m_doubleEdit->setRange(m_minimum, m_maximum); } -void DragValue::setPrecision(int precision) +void DragValue::setPrecision(int /*precision*/) { - m_precision = precision; + //TODO: Not implemented, in case we need double value, we should replace the KIntSpinBox with KDoubleNumInput... + /*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)); + m_edit->setValidator(new QDoubleValidator(m_minimum, m_maximum, precision, this));*/ } void DragValue::setStep(qreal step) { - m_step = step; + if (m_intEdit) + m_intEdit->setSingleStep(step); + else + m_doubleEdit->setSingleStep(step); } -void DragValue::setValue(qreal value, bool final) +void DragValue::slotReset() +{ + if (m_intEdit) { + m_intEdit->blockSignals(true); + m_intEdit->setValue(m_default); + m_intEdit->blockSignals(false); + emit valueChanged((int) m_default, true); + } + else { + m_doubleEdit->blockSignals(true); + m_doubleEdit->setValue(m_default); + m_doubleEdit->blockSignals(false); + emit valueChanged(m_default, true); + } + m_label->setProgressValue((m_default - m_minimum) / (m_maximum - m_minimum) * m_label->maximum()); +} + +void DragValue::slotSetValue(int value) +{ + setValue(value, true); +} + +void DragValue::slotSetValue(double value) +{ + setValue(value, true); +} + +void DragValue::setValueFromProgress(double value, bool final) +{ + value = m_minimum + value * (m_maximum - m_minimum) / m_label->maximum(); + if (m_decimals == 0) + setValue(qRound(value), final); + else + setValue(value, final); +} + +void DragValue::setValue(double value, bool final) { - m_finalValue = final; value = qBound(m_minimum, value, m_maximum); + if (m_intEdit) { + m_intEdit->blockSignals(true); + m_intEdit->setValue((int) value); + m_intEdit->blockSignals(false); + emit valueChanged((int) value, final); + } + else { + m_doubleEdit->blockSignals(true); + m_doubleEdit->setValue(value); + m_doubleEdit->blockSignals(false); + emit valueChanged(value, final); + } - m_edit->setText(QString::number(value, 'f', m_precision)); + m_label->setProgressValue((value - m_minimum) / (m_maximum - m_minimum) * m_label->maximum()); +} - emit valueChanged(value, final); +void DragValue::focusOutEvent(QFocusEvent*) +{ + if (m_intEdit) m_intEdit->setFocusPolicy(Qt::StrongFocus); + else m_doubleEdit->setFocusPolicy(Qt::StrongFocus); } -void DragValue::mousePressEvent(QMouseEvent* e) +void DragValue::focusInEvent(QFocusEvent* e) +{ + if (m_intEdit) + m_intEdit->setFocusPolicy(Qt::WheelFocus); + else + m_doubleEdit->setFocusPolicy(Qt::WheelFocus); + + if (e->reason() == Qt::TabFocusReason || e->reason() == Qt::BacktabFocusReason) { + if (m_intEdit) m_intEdit->setFocus(e->reason()); + else m_doubleEdit->setFocus(e->reason()); + } else { + QWidget::focusInEvent(e); + } +} + +void DragValue::slotEditingFinished() +{ + if (m_intEdit) { + int value = m_intEdit->value(); + m_intEdit->blockSignals(true); + m_intEdit->clearFocus(); + m_intEdit->blockSignals(false); + if (!KdenliveSettings::dragvalue_directupdate()) emit valueChanged((double) value, true); + } + else { + double value = m_doubleEdit->value(); + m_doubleEdit->blockSignals(true); + m_doubleEdit->clearFocus(); + m_doubleEdit->blockSignals(false); + if (!KdenliveSettings::dragvalue_directupdate()) emit valueChanged(value, true); + } +} + +void DragValue::slotShowContextMenu(const QPoint& pos) +{ + // values might have been changed by another object of this class + m_scale->setCurrentItem(KdenliveSettings::dragvalue_mode()); + m_directUpdate->setChecked(KdenliveSettings::dragvalue_directupdate()); + m_menu->exec(mapToGlobal(pos)); +} + +void DragValue::slotSetScaleMode(int mode) +{ + KdenliveSettings::setDragvalue_mode(mode); +} + +void DragValue::slotSetDirectUpdate(bool directUpdate) +{ + KdenliveSettings::setDragvalue_directupdate(directUpdate); +} + +void DragValue::setInTimelineProperty(bool intimeline) +{ + if (m_label->property("inTimeline").toBool() == intimeline) return; + m_label->setProperty("inTimeline", intimeline); + style()->unpolish(m_label); + style()->polish(m_label); + m_label->update(); + if (m_intEdit) { + m_intEdit->setProperty("inTimeline", intimeline); + style()->unpolish(m_intEdit); + style()->polish(m_intEdit); + m_intEdit->update(); + } + else { + m_doubleEdit->setProperty("inTimeline", intimeline); + style()->unpolish(m_doubleEdit); + style()->polish(m_doubleEdit); + m_doubleEdit->update(); + } + +} + +CustomLabel::CustomLabel(const QString &label, bool showSlider, int range, QWidget* parent) : + QProgressBar(parent), + m_dragMode(false), + m_showSlider(showSlider), + m_step(10.0) + //m_precision(pow(10, precision)), +{ + setFont(KGlobalSettings::toolBarFont()); + setFormat(' ' + label); + setFocusPolicy(Qt::StrongFocus); + setCursor(Qt::PointingHandCursor); + setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Maximum); + if (showSlider) setRange(0, 1000); + else { + setRange(0, range); + QSize sh; + const QFontMetrics &fm = fontMetrics(); + sh.setWidth(fm.width(' ' + label + ' ')); + setMaximumWidth(sh.width()); + setObjectName("dragOnly"); + } + setValue(0); +} + +void CustomLabel::mousePressEvent(QMouseEvent* e) { if (e->button() == Qt::LeftButton) { m_dragStartPosition = m_dragLastPosition = e->pos(); - m_dragMode = true; e->accept(); } + else if (e->button() == Qt::MidButton) { + emit resetValue(); + m_dragStartPosition = QPoint(-1, -1); + } + else QWidget::mousePressEvent(e); } -void DragValue::mouseMoveEvent(QMouseEvent* e) +void CustomLabel::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(); + if (m_dragStartPosition != QPoint(-1, -1)) { + if (!m_dragMode && (e->pos() - m_dragStartPosition).manhattanLength() >= QApplication::startDragDistance()) { + m_dragMode = true; + m_dragLastPosition = e->pos(); + e->accept(); + return; + } + if (m_dragMode) { + if (KdenliveSettings::dragvalue_mode() > 0 || !m_showSlider) { + int diff = e->x() - m_dragLastPosition.x(); + + if (e->modifiers() == Qt::ControlModifier) + diff *= 2; + else if (e->modifiers() == Qt::ShiftModifier) + diff /= 2; + if (KdenliveSettings::dragvalue_mode() == 2) + diff = (diff > 0 ? 1 : -1) * pow(diff, 2); + + double nv = value() + diff * m_step; + if (nv != value()) setNewValue(nv, KdenliveSettings::dragvalue_directupdate()); + } + else { + double nv = minimum() + ((double) maximum() - minimum()) / width() * e->pos().x(); + if (nv != value()) setNewValue(nv, KdenliveSettings::dragvalue_directupdate()); + } + m_dragLastPosition = e->pos(); + e->accept(); + } } + else QWidget::mouseMoveEvent(e); } -void DragValue::mouseReleaseEvent(QMouseEvent* e) +void CustomLabel::mouseReleaseEvent(QMouseEvent* e) { - m_dragMode = false; - if (m_finalValue) { - m_edit->setEnabled(true); - m_edit->setFocus(Qt::MouseFocusReason); - } else { - setValue(value(), true); + if (e->button() == Qt::MidButton) { + e->accept(); + return; + } + if (e->modifiers() == Qt::ControlModifier) { + emit setInTimeline(); + e->accept(); + return; + } + if (m_dragMode) { + setNewValue(value(), true); + m_dragLastPosition = m_dragStartPosition; e->accept(); } + else if (m_showSlider) { + setNewValue((double) maximum() * e->pos().x() / width(), true); + m_dragLastPosition = m_dragStartPosition; + e->accept(); + } + m_dragMode = false; } -void DragValue::wheelEvent(QWheelEvent* e) +void CustomLabel::wheelEvent(QWheelEvent* e) { - if (e->delta() > 0) - slotValueInc(); - else - slotValueDec(); + if (e->delta() > 0) { + if (e->modifiers() == Qt::ControlModifier) slotValueInc(10); + else if (e->modifiers() == Qt::AltModifier) slotValueInc(0.1); + else slotValueInc(); + } + else { + if (e->modifiers() == Qt::ControlModifier) slotValueDec(10); + else if (e->modifiers() == Qt::AltModifier) slotValueDec(0.1); + else slotValueDec(); + } + e->accept(); } -void DragValue::focusInEvent(QFocusEvent* e) +void CustomLabel::slotValueInc(double factor) { - if (e->reason() == Qt::TabFocusReason || e->reason() == Qt::BacktabFocusReason) { - m_edit->setEnabled(true); - m_edit->setFocus(e->reason()); - } else { - QWidget::focusInEvent(e); - } + setNewValue(value() + m_step * factor, true); } -void DragValue::slotValueInc() +void CustomLabel::slotValueDec(double factor) { - setValue(m_edit->text().toDouble() + m_step); + setNewValue(value() - m_step * factor, true); } -void DragValue::slotValueDec() +void CustomLabel::setProgressValue(double value) { - setValue(m_edit->text().toDouble() - m_step); + setValue(qRound(value)); } -void DragValue::slotEditingFinished() +void CustomLabel::setNewValue(double value, bool update) { - m_finalValue = true; - qreal value = m_edit->text().toDouble(); - m_edit->setEnabled(false); - emit valueChanged(value, true); + setValue(qRound(value)); + emit valueChanged(qRound(value), update); } -void DragValue::updateMaxWidth() +void CustomLabel::setStep(double step) { - 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'))); + m_step = step; +} + +void CustomLabel::focusInEvent(QFocusEvent*) +{ + setFocusPolicy(Qt::WheelFocus); +} + +void CustomLabel::focusOutEvent(QFocusEvent*) +{ + setFocusPolicy(Qt::StrongFocus); } #include "dragvalue.moc"