1 //=============================================================================
2 // Awl
3 // Audio Widget Library
4 // $Id:$
5 //
6 // Copyright (C) 1999-2011 by Werner Schweer and others
7 //
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License
10 // as published by the Free Software Foundation; version 2 of
11 // the License, or (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 //=============================================================================
22
23 #include "floatentry.h"
24 #include "fastlog.h"
25 #include "gconfig.h"
26
27 #include <QLineEdit>
28 #include <QMouseEvent>
29 #include <QContextMenuEvent>
30 #include <QTimer>
31
32 #include "muse_math.h"
33
34 #define TIMER1 400
35 #define TIMER2 200
36 #define TIMEC 7
37 #define TIMER3 100
38 #define TIMEC2 20
39 #define TIMER4 50
40
41 namespace Awl {
42
43 //---------------------------------------------------------
44 // FloatEntry
45 //---------------------------------------------------------
46
FloatEntry(QWidget * parent,bool leftMouseButtonCanDecrease)47 FloatEntry::FloatEntry(QWidget* parent, bool leftMouseButtonCanDecrease)
48 : QLineEdit(parent), _leftMouseButtonCanDecrease(leftMouseButtonCanDecrease)
49 {
50 _id = 0;
51 _minValue = 0.0;
52 _maxValue = 1.0;
53 _log = false;
54 evx = 1.0;
55 _precision = 3;
56 timer = new QTimer(this);
57 connect(timer, SIGNAL(timeout()), SLOT(repeat()));
58 _value = 0.0f;
59 //connect(this, SIGNAL(returnPressed()), SLOT(endEdit()));
60 connect(this, SIGNAL(editingFinished()), SLOT(endEdit()));
61 setCursor(QCursor(Qt::ArrowCursor));
62 updateValue();
63 }
64
65 //---------------------------------------------------------
66 // calcIncrement()
67 //---------------------------------------------------------
68
calcIncrement() const69 double FloatEntry::calcIncrement() const
70 {
71 double dif;
72 if(_maxValue - _minValue > 0)
73 dif = _maxValue - _minValue;
74 else
75 dif = _minValue - _maxValue;
76
77 if(dif <= 10.0)
78 return 0.1;
79 else
80 if(dif <= 100.0)
81 return 1.0;
82 else
83 return 10.0;
84 }
85
86 //---------------------------------------------------------
87 // contextMenuEvent
88 //---------------------------------------------------------
89
contextMenuEvent(QContextMenuEvent * e)90 void FloatEntry::contextMenuEvent(QContextMenuEvent * e)
91 {
92 e->accept();
93 }
94
95 //---------------------------------------------------------
96 // setString
97 //---------------------------------------------------------
98
setString(double v)99 bool FloatEntry::setString(double v)
100 {
101 QString s;
102 // if (v < _minValue || v > _maxValue) {
103 if (v < _minValue) {
104 if (!_specialText.isEmpty())
105 setText(_specialText);
106 return true;
107 }
108 s.setNum(v, 'f', _precision);
109 if (!_suffix.isEmpty()) {
110 // s += " ";
111 s += _suffix;
112 }
113 setText(s);
114 return false;
115 }
116
117 //---------------------------------------------------------
118 // setSValue
119 //---------------------------------------------------------
120
setSValue(const QString & s)121 void FloatEntry::setSValue(const QString& s)
122 {
123 bool ok;
124 double v = s.toFloat(&ok);
125 if (ok && (v != _value)) {
126 if (v < _minValue)
127 v = _minValue;
128 if (v > _maxValue)
129 v = _maxValue;
130 _value = v;
131 updateValue();
132 valueChange();
133 }
134 }
135
136 //---------------------------------------------------------
137 // valueChange
138 //---------------------------------------------------------
139
valueChange()140 void FloatEntry::valueChange()
141 {
142 emit valueChanged(value(), _id);
143 }
144
145 //---------------------------------------------------------
146 // incValue
147 //---------------------------------------------------------
148
incValue(double)149 void FloatEntry::incValue(double)
150 {
151 if(_value >= _maxValue)
152 return;
153 double inc = calcIncrement();
154 if(_value + inc >= _maxValue)
155 //setValue(_maxValue);
156 _value = _maxValue;
157 else
158 //setValue(_value + inc);
159 _value += inc;
160 valueChange();
161 }
162
163 //---------------------------------------------------------
164 // decValue
165 //---------------------------------------------------------
166
decValue(double)167 void FloatEntry::decValue(double)
168 {
169 if(_value <= _minValue)
170 return;
171 double inc = calcIncrement();
172 if(_value - inc <= _minValue)
173 //setValue(_minValue);
174 _value = _minValue;
175 else
176 //setValue(_value - inc);
177 _value -= inc;
178 valueChange();
179 }
180
181 //---------------------------------------------------------
182 // setPrecision
183 //---------------------------------------------------------
184
setPrecision(int v)185 void FloatEntry::setPrecision(int v)
186 {
187 _precision = v;
188 setString(_value);
189 }
190
191 //---------------------------------------------------------
192 // sizeHint
193 //---------------------------------------------------------
194
sizeHint() const195 QSize FloatEntry::sizeHint() const
196 {
197 QFontMetrics fm = fontMetrics();
198 int h = fm.height() + 4;
199 int n = _precision + 3;
200 // Width() is obsolete. Qt >= 5.11 use horizontalAdvance().
201 #if QT_VERSION >= 0x050b00
202 int w = fm.horizontalAdvance(QString("-0.")) + fm.horizontalAdvance('0') * n + 6;
203 #else
204 int w = fm.width(QString("-0.")) + fm.width('0') * n + 6;
205 #endif
206 return QSize(w, h);
207 }
208
209 //---------------------------------------------------------
210 // endEdit
211 //---------------------------------------------------------
212
endEdit()213 void FloatEntry::endEdit()
214 {
215 if (QLineEdit::isModified())
216 setSValue(text());
217 clearFocus();
218 }
219
220 //---------------------------------------------------------
221 // mousePressEvent
222 //---------------------------------------------------------
223
mousePressEvent(QMouseEvent * event)224 void FloatEntry::mousePressEvent(QMouseEvent* event)
225 {
226 button = event->button();
227 starty = event->y();
228 evx = double(event->x());
229 timecount = 0;
230 repeat();
231 timer->start(TIMER1);
232 }
233
234 //---------------------------------------------------------
235 // wheelEvent
236 //---------------------------------------------------------
237
wheelEvent(QWheelEvent * event)238 void FloatEntry::wheelEvent(QWheelEvent* event)
239 {
240 event->accept();
241
242 const QPoint pixelDelta = event->pixelDelta();
243 const QPoint angleDegrees = event->angleDelta() / 8;
244 int delta = 0;
245 if(!pixelDelta.isNull())
246 delta = pixelDelta.y();
247 else if(!angleDegrees.isNull())
248 delta = angleDegrees.y() / 15;
249 else
250 return;
251
252 if (delta < 0)
253 decValue(-1.0);
254 else if (delta > 0)
255 incValue(1.0);
256 }
257
258 //---------------------------------------------------------
259 // repeat
260 //---------------------------------------------------------
261
repeat()262 void FloatEntry::repeat()
263 {
264 if (timecount == 1) {
265 ++timecount;
266 timer->stop();
267 timer->start(TIMER2);
268 return;
269 }
270 ++timecount;
271 if (timecount == TIMEC) {
272 timer->stop();
273 timer->start(TIMER3);
274 }
275 if (timecount == TIMEC2) {
276 timer->stop();
277 timer->start(TIMER4);
278 }
279
280 switch (button) {
281 case Qt::LeftButton:
282 if (!_leftMouseButtonCanDecrease)
283 return;
284 // else fall through
285 case Qt::MidButton:
286 decValue(evx);
287 break;
288 case Qt::RightButton:
289 incValue(evx);
290 break;
291 default:
292 break;
293 }
294 }
295
296 //---------------------------------------------------------
297 // mouseReleaseEvent
298 //---------------------------------------------------------
299
mouseReleaseEvent(QMouseEvent *)300 void FloatEntry::mouseReleaseEvent(QMouseEvent*)
301 {
302 button = Qt::NoButton;
303 timer->stop();
304 }
305
306 //---------------------------------------------------------
307 // mouseMoveEvent
308 //---------------------------------------------------------
309
mouseMoveEvent(QMouseEvent *)310 void FloatEntry::mouseMoveEvent(QMouseEvent*)
311 {
312 switch (button) {
313 case Qt::LeftButton:
314 break;
315 case Qt::MidButton:
316 break;
317 case Qt::RightButton:
318 break;
319 default:
320 break;
321 }
322 }
323
324 //---------------------------------------------------------
325 // mouseDoubleClickEvent
326 //---------------------------------------------------------
327
mouseDoubleClickEvent(QMouseEvent * event)328 void FloatEntry::mouseDoubleClickEvent(QMouseEvent* event)
329 {
330 if (event->button() != Qt::LeftButton) {
331 mousePressEvent(event);
332 return;
333 }
334 setFocus();
335 QLineEdit::setFrame(true);
336 update();
337 }
338
339 //---------------------------------------------------------
340 // setValue
341 //---------------------------------------------------------
342
setValue(double val)343 void FloatEntry::setValue(double val)
344 {
345 if (_log) {
346 if (val == 0.0f)
347 _value = _minValue;
348 else
349 _value = fast_log10(val) * 20.0f;
350 }
351 else
352 _value = val;
353 updateValue();
354 }
355
356 //---------------------------------------------------------
357 // updateValue
358 //---------------------------------------------------------
359
updateValue()360 void FloatEntry::updateValue()
361 {
362 if (setString(_value)) {
363 // value is out of range:
364 if (_value > _maxValue)
365 _value = _maxValue;
366 else if (_value < _minValue)
367 _value = _minValue;
368 }
369 }
370
371 //---------------------------------------------------------
372 // value
373 //---------------------------------------------------------
374
value() const375 double FloatEntry::value() const
376 {
377 double rv;
378 if (_log)
379 rv = muse_db2val(_value);
380 else
381 rv = _value;
382 return rv;
383 }
384
385 //---------------------------------------------------------
386 // minLogValue
387 //---------------------------------------------------------
388
389 //double FloatEntry::minValue() const {
390 // return _log ? pow(10.0, _minValue*0.05f) : _minValue;
391 //}
392
393 //---------------------------------------------------------
394 // setMinLogValue
395 //---------------------------------------------------------
396
setMinLogValue(double val)397 void FloatEntry::setMinLogValue(double val) {
398 if (_log) {
399 if (val == 0.0f) _minValue = -100;
400 else _minValue = fast_log10(val) * 20.0f;
401 }
402 else _minValue = val;
403 }
404
405 //---------------------------------------------------------
406 // maxLogValue
407 //---------------------------------------------------------
408
409 //double FloatEntry::maxValue() const {
410 // return _log ? pow(10.0, _maxValue*0.05f) : _maxValue;
411 //}
412
413 //---------------------------------------------------------
414 // setMaxLogValue
415 //---------------------------------------------------------
416
setMaxLogValue(double val)417 void FloatEntry::setMaxLogValue(double val) {
418 if (_log) {
419 _maxValue = fast_log10(val) * 20.0f;
420 }
421 else _maxValue = val;
422 }
423
424 }
425
426