]> git.sesse.net Git - kdenlive/blob - src/dragvalue.cpp
Add "drag value" widget: Numbers can be edited by dragging horizontal on the widget...
[kdenlive] / src / dragvalue.cpp
1 /***************************************************************************
2  *   Copyright (C) 2011 by Till Theato (root@ttill.de)                     *
3  *   This file is part of Kdenlive (www.kdenlive.org).                     *
4  *                                                                         *
5  *   Kdenlive is free software: you can redistribute it and/or modify      *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation, either version 2 of the License, or     *
8  *   (at your option) any later version.                                   *
9  *                                                                         *
10  *   Kdenlive is distributed in the hope that it will be useful,           *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with Kdenlive.  If not, see <http://www.gnu.org/licenses/>.     *
17  ***************************************************************************/
18
19 #include "dragvalue.h"
20 #include "kdenlivesettings.h"
21
22 #include <math.h>
23
24 #include <QHBoxLayout>
25 #include <QToolButton>
26 #include <QLineEdit>
27 #include <QDoubleValidator>
28 #include <QIntValidator>
29 #include <QMouseEvent>
30 #include <QFocusEvent>
31 #include <QWheelEvent>
32 #include <QApplication>
33
34 #include <KColorScheme>
35 #include <KIcon>
36
37 DragValue::DragValue(QWidget* parent) :
38         QWidget(parent),
39         m_maximum(100),
40         m_minimum(0),
41         m_precision(2),
42         m_step(1),
43         m_dragMode(false),
44         m_finalValue(true)
45 {
46     setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
47     setFocusPolicy(Qt::StrongFocus);
48
49     QHBoxLayout *l = new QHBoxLayout(this);
50     l->setSpacing(0);
51     l->setMargin(0);
52
53     /*m_buttonDec = new QToolButton(this);
54     m_buttonDec->setIcon(KIcon("arrow-left"));
55     m_buttonDec->setIconSize(QSize(12, 12));
56     m_buttonDec->setObjectName("ButtonDec");
57     l->addWidget(m_buttonDec);*/
58
59     m_edit = new QLineEdit(this);
60     m_edit->setValidator(new QDoubleValidator(m_minimum, m_maximum, m_precision, this));
61     m_edit->setAlignment(Qt::AlignCenter);
62     m_edit->setEnabled(false);
63     l->addWidget(m_edit);
64
65     /*m_buttonInc = new QToolButton(this);
66     m_buttonInc->setIcon(KIcon("arrow-right"));
67     m_buttonInc->setIconSize(QSize(12, 12));
68     m_buttonInc->setObjectName("ButtonInc");
69     l->addWidget(m_buttonInc);*/
70
71     QPalette p = palette();
72     KColorScheme scheme(p.currentColorGroup(), KColorScheme::View, KSharedConfig::openConfig(KdenliveSettings::colortheme()));
73     QColor bg = scheme.background(KColorScheme::LinkBackground).color();
74     QColor fg = scheme.foreground(KColorScheme::LinkText).color();
75     QColor editbg = scheme.background(KColorScheme::ActiveBackground).color();
76     QColor editfg = scheme.foreground(KColorScheme::ActiveText).color();
77     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); }")
78                         .arg(bg.red()).arg(bg.green()).arg(bg.blue())
79                         .arg(fg.red()).arg(fg.green()).arg(fg.blue()));
80     stylesheet.append(QString("QLineEdit::focus, QLineEdit::enabled { background-color: rgb(%1, %2, %3); color: rgb(%4, %5, %6); }")
81                         .arg(editbg.red()).arg(editbg.green()).arg(editbg.blue())
82                         .arg(editfg.red()).arg(editfg.green()).arg(editfg.blue()));
83 /*     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; }")
84                          .arg(bg.red()).arg(bg.green()).arg(bg.blue()));
85      stylesheet.append(QString("QLineEdit::focus, QLineEdit::enabled { background-color: rgb(%1, %2, %3); color: rgb(%4, %5, %6); }")
86                          .arg(textbg.red()).arg(textbg.green()).arg(textbg.blue())
87                          .arg(textfg.red()).arg(textfg.green()).arg(textfg.blue()));
88     QString stylesheet(QString("* { background-color: rgb(%1, %2, %3); margin: 0px; }").arg(bg.red()).arg(bg.green()).arg(bg.blue()));
89     stylesheet.append(QString("QLineEdit { border: 0px; height: 100%; } QLineEdit::focus, QLineEdit::enabled { background-color: rgb(%1, %2, %3); color: rgb(%4, %5, %6); }")
90                          .arg(textbg.red()).arg(textbg.green()).arg(textbg.blue())
91                          .arg(textfg.red()).arg(textfg.green()).arg(textfg.blue()));
92     stylesheet.append(QString("QToolButton { border: 1px solid rgb(%1, %2, %3); }").arg(bg.red()).arg(bg.green()).arg(bg.blue()));
93     stylesheet.append(QString("QToolButton#ButtonDec { border-top-left-radius: 5px; border-bottom-left-radius: 5px; }"));
94     stylesheet.append(QString("QToolButton#ButtonInc { border-top-right-radius: 5px; border-bottom-right-radius: 5px; }"));*/
95     setStyleSheet(stylesheet);
96
97     updateMaxWidth();
98
99     /*connect(m_buttonDec, SIGNAL(clicked(bool)), this, SLOT(slotValueDec()));
100     connect(m_buttonInc, SIGNAL(clicked(bool)), this, SLOT(slotValueInc()));*/
101     connect(m_edit, SIGNAL(editingFinished()), this, SLOT(slotEditingFinished()));
102 }
103
104 DragValue::~DragValue()
105 {
106     delete m_edit;
107     /*delete m_buttonInc;
108     delete m_buttonDec;*/
109 }
110
111 int DragValue::precision() const
112 {
113     return m_precision;
114 }
115
116 qreal DragValue::maximum() const
117 {
118     return m_maximum;
119 }
120
121 qreal DragValue::minimum() const
122 {
123     return m_minimum;
124 }
125
126 qreal DragValue::value() const
127 {
128     return m_edit->text().toDouble();
129 }
130
131 void DragValue::setMaximum(qreal max)
132 {
133     m_maximum = max;
134     updateMaxWidth();
135 }
136
137 void DragValue::setMinimum(qreal min)
138 {
139     m_minimum = min;
140     updateMaxWidth();
141 }
142
143 void DragValue::setRange(qreal min, qreal max)
144 {
145     m_maximum = max;
146     m_minimum = min;
147     updateMaxWidth();
148 }
149
150 void DragValue::setPrecision(int precision)
151 {
152     m_precision = precision;
153     if (precision == 0)
154         m_edit->setValidator(new QIntValidator(m_minimum, m_maximum, this));
155     else
156         m_edit->setValidator(new QDoubleValidator(m_minimum, m_maximum, precision, this));
157 }
158
159 void DragValue::setStep(qreal step)
160 {
161     m_step = step;
162 }
163
164 void DragValue::setValue(qreal value, bool final)
165 {
166     m_finalValue = final;
167     value = qBound(m_minimum, value, m_maximum);
168
169     m_edit->setText(QString::number(value, 'f', m_precision));
170
171     emit valueChanged(value, final);
172 }
173
174 void DragValue::mousePressEvent(QMouseEvent* e)
175 {
176     if (e->button() == Qt::LeftButton) {
177         m_dragStartPosition = m_dragLastPosition = e->pos();
178         m_dragMode = true;
179         e->accept();
180     }
181 }
182
183 void DragValue::mouseMoveEvent(QMouseEvent* e)
184 {
185     if (m_dragMode && (e->pos() - m_dragStartPosition).manhattanLength() >= QApplication::startDragDistance()) {
186         int diffDistance = e->x() - m_dragLastPosition.x();
187         int direction = diffDistance > 0 ? 1 : -1; // since pow loses this info
188         setValue(value() + direction * pow(e->x() - m_dragLastPosition.x(), 2) / m_step, false);
189         m_dragLastPosition = e->pos();
190         e->accept();
191     }
192 }
193
194 void DragValue::mouseReleaseEvent(QMouseEvent* e)
195 {
196     m_dragMode = false;
197     if (m_finalValue) {
198         m_edit->setEnabled(true);
199         m_edit->setFocus(Qt::MouseFocusReason);
200     } else {
201         setValue(value(), true);
202         e->accept();
203     }
204 }
205
206 void DragValue::wheelEvent(QWheelEvent* e)
207 {
208     if (e->delta() > 0)
209         slotValueInc();
210     else
211         slotValueDec();
212 }
213
214 void DragValue::focusInEvent(QFocusEvent* e)
215 {
216     if (e->reason() == Qt::TabFocusReason || e->reason() == Qt::BacktabFocusReason) {
217         m_edit->setEnabled(true);
218         m_edit->setFocus(e->reason());
219     } else {
220         QWidget::focusInEvent(e);
221     }
222 }
223
224 void DragValue::slotValueInc()
225 {
226     setValue(m_edit->text().toDouble() + m_step);
227 }
228
229 void DragValue::slotValueDec()
230 {
231     setValue(m_edit->text().toDouble() - m_step);
232 }
233
234 void DragValue::slotEditingFinished()
235 {
236     m_finalValue = true;
237     qreal value = m_edit->text().toDouble();
238     m_edit->setEnabled(false);
239     emit valueChanged(value, true);
240 }
241
242 void DragValue::updateMaxWidth()
243 {
244     int val = (int)(log10(qAbs(m_maximum) > qAbs(m_minimum) ? qAbs(m_maximum) : qAbs(m_minimum)) + .5);
245     val += m_precision;
246     if (m_precision)
247         val += 1;
248     if (m_minimum < 0)
249         val += 1;
250     QFontMetrics fm = m_edit->fontMetrics();
251     m_edit->setMaximumWidth(fm.width(QString().rightJustified(val, '8')));
252 }
253
254 #include "dragvalue.moc"