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