1 /***************************************************************************
2 * Copyright (C) 2011 by Till Theato (root@ttill.de) *
3 * Copyright (C) 2011 by Jean-Baptiste Mardelle (jb@kdenlive.org) *
4 * This file is part of Kdenlive (www.kdenlive.org). *
6 * Kdenlive is free software: you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation, either version 2 of the License, or *
9 * (at your option) any later version. *
11 * Kdenlive is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
16 * You should have received a copy of the GNU General Public License *
17 * along with Kdenlive. If not, see <http://www.gnu.org/licenses/>. *
18 ***************************************************************************/
20 #include "dragvalue.h"
21 #include "kdenlivesettings.h"
25 #include <QHBoxLayout>
26 #include <QToolButton>
28 #include <QDoubleValidator>
29 #include <QIntValidator>
30 #include <QMouseEvent>
31 #include <QFocusEvent>
32 #include <QWheelEvent>
33 #include <QApplication>
41 #include <KLocalizedString>
42 #include <KGlobalSettings>
44 DragValue::DragValue(const QString &label, int defaultValue, int id, const QString suffix, bool showSlider, QWidget* parent) :
49 m_default(defaultValue),
52 if (showSlider) setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
53 else setSizePolicy(QSizePolicy::Maximum, QSizePolicy::MinimumExpanding);
54 setFocusPolicy(Qt::StrongFocus);
55 setContextMenuPolicy(Qt::CustomContextMenu);
57 QHBoxLayout *l = new QHBoxLayout;
59 l->setContentsMargins(0, 0, 0, 0);
60 m_label = new CustomLabel(label, showSlider, this);
61 m_label->setCursor(Qt::PointingHandCursor);
62 m_label->setRange(m_minimum, m_maximum);
63 l->addWidget(m_label);
64 m_edit = new KIntSpinBox(this);
65 m_edit->setObjectName("dragBox");
66 if (!suffix.isEmpty()) m_edit->setSuffix(suffix);
68 m_edit->setButtonSymbols(QAbstractSpinBox::NoButtons);
69 m_edit->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
70 m_edit->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
71 m_edit->setRange(m_minimum, m_maximum);
73 connect(m_edit, SIGNAL(valueChanged(int)), this, SLOT(slotSetValue(int)));
74 connect(m_label, SIGNAL(valueChanged(int,bool)), this, SLOT(setValue(int,bool)));
75 connect(m_label, SIGNAL(resetValue()), this, SLOT(slotReset()));
77 m_label->setMaximumHeight(m_edit->sizeHint().height());
79 m_menu = new QMenu(this);
81 m_scale = new KSelectAction(i18n("Scaling"), this);
82 m_scale->addAction(i18n("Normal scale"));
83 m_scale->addAction(i18n("Pixel scale"));
84 m_scale->addAction(i18n("Nonlinear scale"));
85 m_scale->setCurrentItem(KdenliveSettings::dragvalue_mode());
86 m_menu->addAction(m_scale);
88 m_directUpdate = new QAction(i18n("Direct update"), this);
89 m_directUpdate->setCheckable(true);
90 m_directUpdate->setChecked(KdenliveSettings::dragvalue_directupdate());
91 m_menu->addAction(m_directUpdate);
93 QAction *reset = new QAction(KIcon("edit-undo"), i18n("Reset value"), this);
94 connect(reset, SIGNAL(triggered()), this, SLOT(slotReset()));
95 m_menu->addAction(reset);
98 QAction *timeline = new QAction(KIcon("go-jump"), i18n("Show %1 in timeline", label), this);
99 connect(timeline, SIGNAL(triggered()), this, SLOT(slotSetInTimeline()));
100 connect(m_label, SIGNAL(setInTimeline()), this, SLOT(slotSetInTimeline()));
101 m_menu->addAction(timeline);
104 connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(slotShowContextMenu(const QPoint&)));
105 connect(m_scale, SIGNAL(triggered(int)), this, SLOT(slotSetScaleMode(int)));
106 connect(m_directUpdate, SIGNAL(triggered(bool)), this, SLOT(slotSetDirectUpdate(bool)));
108 connect(m_edit, SIGNAL(editingFinished()), this, SLOT(slotEditingFinished()));
111 DragValue::~DragValue()
116 delete m_directUpdate;
119 int DragValue::spinSize()
121 return m_edit->sizeHint().width();
124 void DragValue::setSpinSize(int width)
126 m_edit->setMinimumWidth(width);
129 void DragValue::slotSetInTimeline()
131 emit inTimeline(m_id);
134 int DragValue::precision() const
139 qreal DragValue::maximum() const
144 qreal DragValue::minimum() const
149 qreal DragValue::value() const
151 return m_edit->value();
154 void DragValue::setMaximum(qreal max)
157 m_label->setRange(m_minimum, m_maximum);
158 m_edit->setRange(m_minimum, m_maximum);
161 void DragValue::setMinimum(qreal min)
164 m_label->setRange(m_minimum, m_maximum);
165 m_edit->setRange(m_minimum, m_maximum);
168 void DragValue::setRange(qreal min, qreal max)
172 m_label->setRange(m_minimum, m_maximum);
173 m_edit->setRange(m_minimum, m_maximum);
176 void DragValue::setPrecision(int /*precision*/)
178 //TODO: Not implemented, in case we need double value, we should replace the KIntSpinBox with KDoubleNumInput...
179 /*m_precision = precision;
181 m_edit->setValidator(new QIntValidator(m_minimum, m_maximum, this));
183 m_edit->setValidator(new QDoubleValidator(m_minimum, m_maximum, precision, this));*/
186 void DragValue::setStep(qreal /*step*/)
191 void DragValue::slotReset()
193 m_edit->blockSignals(true);
194 m_edit->setValue(m_default);
195 m_label->setValue(m_default);
196 m_edit->blockSignals(false);
197 emit valueChanged(m_default, true);
200 void DragValue::slotSetValue(int value)
202 setValue(value, KdenliveSettings::dragvalue_directupdate());
205 void DragValue::setValue(int value, bool final)
207 value = qBound(m_minimum, value, m_maximum);
208 m_edit->blockSignals(true);
209 m_edit->setValue(value);
210 m_edit->blockSignals(false);
211 m_label->setValue(value);
212 emit valueChanged(value, final);
215 void DragValue::focusInEvent(QFocusEvent* e)
217 if (e->reason() == Qt::TabFocusReason || e->reason() == Qt::BacktabFocusReason) {
218 //m_edit->setEnabled(true);
219 m_edit->setFocus(e->reason());
221 QWidget::focusInEvent(e);
225 void DragValue::slotEditingFinished()
227 qreal value = m_edit->value();
228 m_edit->clearFocus();
229 emit valueChanged(value, true);
232 void DragValue::slotShowContextMenu(const QPoint& pos)
234 // values might have been changed by another object of this class
235 m_scale->setCurrentItem(KdenliveSettings::dragvalue_mode());
236 m_directUpdate->setChecked(KdenliveSettings::dragvalue_directupdate());
237 m_menu->exec(mapToGlobal(pos));
240 void DragValue::slotSetScaleMode(int mode)
242 KdenliveSettings::setDragvalue_mode(mode);
245 void DragValue::slotSetDirectUpdate(bool directUpdate)
247 KdenliveSettings::setDragvalue_directupdate(directUpdate);
250 void DragValue::setInTimelineProperty(bool intimeline)
252 if (m_label->property("inTimeline").toBool() == intimeline) return;
253 m_label->setProperty("inTimeline", intimeline);
254 m_edit->setProperty("inTimeline", intimeline);
255 style()->unpolish(m_label);
256 style()->polish(m_label);
258 style()->unpolish(m_edit);
259 style()->polish(m_edit);
263 CustomLabel::CustomLabel(const QString &label, bool showSlider, QWidget* parent) :
264 QProgressBar(parent),
267 m_showSlider(showSlider)
269 setFont(KGlobalSettings::toolBarFont());
270 setFormat(" " + label);
271 setFocusPolicy(Qt::ClickFocus);
272 setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Maximum);
275 const QFontMetrics &fm = fontMetrics();
276 sh.setWidth(fm.width(" " + label + " "));
277 setMaximumWidth(sh.width());
278 setObjectName("dragOnly");
283 void CustomLabel::mousePressEvent(QMouseEvent* e)
285 if (e->button() == Qt::LeftButton) {
286 m_dragStartPosition = m_dragLastPosition = e->pos();
289 else if (e->button() == Qt::MidButton) {
291 m_dragStartPosition = QPoint(-1, -1);
293 else QWidget::mousePressEvent(e);
296 void CustomLabel::mouseMoveEvent(QMouseEvent* e)
298 if (m_dragStartPosition != QPoint(-1, -1)) {
299 if (!m_dragMode && (e->pos() - m_dragStartPosition).manhattanLength() >= QApplication::startDragDistance()) {
301 m_dragLastPosition = e->pos();
306 if (KdenliveSettings::dragvalue_mode() > 0 || !m_showSlider) {
307 int diff = e->x() - m_dragLastPosition.x();
309 if (e->modifiers() == Qt::ControlModifier)
311 else if (e->modifiers() == Qt::ShiftModifier)
313 if (KdenliveSettings::dragvalue_mode() == 2)
314 diff = (diff > 0 ? 1 : -1) * pow(diff, 2);
316 int nv = value() + diff / m_step;
317 if (nv != value()) setNewValue(nv, KdenliveSettings::dragvalue_directupdate());
320 int nv = minimum() + ((double) maximum() - minimum()) / width() * e->pos().x();
321 if (nv != value()) setNewValue(nv, KdenliveSettings::dragvalue_directupdate());
323 m_dragLastPosition = e->pos();
327 else QWidget::mouseMoveEvent(e);
330 void CustomLabel::mouseReleaseEvent(QMouseEvent* e)
332 if (e->button() == Qt::MidButton) {
336 if (e->modifiers() == Qt::ControlModifier) {
337 emit setInTimeline();
342 setNewValue(value(), true);
343 m_dragLastPosition = m_dragStartPosition;
346 else if (m_showSlider) {
347 setNewValue((int) (minimum() + ((double)maximum() - minimum()) / width() * e->pos().x()), true);
348 m_dragLastPosition = m_dragStartPosition;
354 void CustomLabel::wheelEvent(QWheelEvent* e)
356 if (e->delta() > 0) {
357 if (e->modifiers() == Qt::ControlModifier) slotValueInc(10);
361 if (e->modifiers() == Qt::ControlModifier) slotValueDec(10);
367 void CustomLabel::slotValueInc(int factor)
369 setNewValue((int) (value() + m_step * factor), true);
372 void CustomLabel::slotValueDec(int factor)
374 setNewValue((int) (value() - m_step * factor), true);
377 void CustomLabel::setNewValue(int value, bool update)
380 emit valueChanged(value, update);
383 #include "dragvalue.moc"