1 /*
2 * Frequency controller widget (originally from CuteSDR)
3 *
4 * This file is part of gqrx sdr.
5 *
6 * Copyright 2010 Moe Wheatley AE4JY
7 * Copyright 2012-2017 Alexandru Csete OZ9AEC
8 * All rights reserved.
9 *
10 * This software is released under the "Simplified BSD License".
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 *
18 * 2. Redistributions in binary form must reproduce the above copyright notice,
19 * this list of conditions and the following disclaimer in the documentation
20 * and/or other materials provided with the distribution.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
26 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 */
34 #include <QDebug>
35 #include "freqctrl.h"
36
37 // Manual adjustment of Font size as percent of control height
38 #define DIGIT_SIZE_PERCENT 90
39 #define UNITS_SIZE_PERCENT 60
40
41 // adjustment for separation between digits
42 #define SEPRATIO_N 100 // separation rectangle size ratio numerator times 100
43 #define SEPRATIO_D 3 // separation rectangle size ratio denominator
44
45 #define STATUS_TIP \
46 "Scroll or left-click to increase/decrease digit. " \
47 "Right-click to clear digits."
48
CFreqCtrl(QWidget * parent)49 CFreqCtrl::CFreqCtrl(QWidget *parent) :
50 QFrame(parent)
51 {
52 setAutoFillBackground(false);
53 setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
54 setFocusPolicy(Qt::StrongFocus);
55 setMouseTracking(true);
56 m_BkColor = QColor(0x1F, 0x1D, 0x1D, 0xFF);
57 m_InactiveColor = QColor(0x43, 0x43, 0x43, 0xFF);
58 m_DigitColor = QColor(0xFF, 0xFF, 0xFF, 0xFF);
59 m_HighlightColor = QColor(0x5A, 0x5A, 0x5A, 0xFF);
60 m_UnitsColor = Qt::gray;
61 m_freq = 146123456;
62 setup(0, 1, 4000000000U, 1, FCTL_UNIT_NONE);
63 m_Oldfreq = 0;
64 m_LastLeadZeroPos = 0;
65 m_LRMouseFreqSel = false;
66 m_ActiveEditDigit = -1;
67 m_ResetLowerDigits = true;
68 m_InvertScrolling = false;
69 m_UnitsFont = QFont("Arial", 12, QFont::Normal);
70 m_DigitFont = QFont("Arial", 12, QFont::Normal);
71
72 setStatusTip(tr(STATUS_TIP));
73 }
74
~CFreqCtrl()75 CFreqCtrl::~CFreqCtrl()
76 {
77 }
78
minimumSizeHint() const79 QSize CFreqCtrl::minimumSizeHint() const
80 {
81 return QSize(100, 20);
82 }
83
sizeHint() const84 QSize CFreqCtrl::sizeHint() const
85 {
86 return QSize(100, 20);
87 }
88
inRect(QRect & rect,QPoint & point)89 bool CFreqCtrl::inRect(QRect &rect, QPoint &point)
90 {
91 if ((point.x() < rect.right()) && (point.x() > rect.x()) &&
92 (point.y() < rect.bottom()) && (point.y() > rect.y()))
93 return true;
94 else
95 return false;
96 }
97
fmax_to_numdigits(qint64 fmax)98 static int fmax_to_numdigits(qint64 fmax)
99 {
100 if (fmax < 10e6)
101 return 7;
102 else if (fmax < 100e6)
103 return 8;
104 else if (fmax < 1e9)
105 return 9;
106 else if (fmax < 10e9)
107 return 10;
108 else if (fmax < 100e9)
109 return 11;
110
111 return 12;
112 }
113
setup(int NumDigits,qint64 Minf,qint64 Maxf,int MinStep,FctlUnit unit)114 void CFreqCtrl::setup(int NumDigits, qint64 Minf, qint64 Maxf, int MinStep,
115 FctlUnit unit)
116 {
117 int i;
118 qint64 pwr = 1;
119 m_LastEditDigit = 0;
120 m_Oldfreq = -1;
121
122 m_NumDigits = NumDigits ? NumDigits : fmax_to_numdigits(Maxf);
123
124 if (m_NumDigits > FCTL_MAX_DIGITS)
125 m_NumDigits = FCTL_MAX_DIGITS;
126
127 if (m_NumDigits < FCTL_MIN_DIGITS)
128 m_NumDigits = FCTL_MIN_DIGITS;
129
130 m_UnitString = "";
131 m_MinStep = MinStep;
132
133 if (m_MinStep == 0)
134 m_MinStep = 1;
135
136 m_MinFreq = Minf;
137 m_MaxFreq = Maxf;
138
139 if (m_freq < m_MinFreq)
140 m_freq = m_MinFreq;
141
142 if (m_freq > m_MaxFreq)
143 m_freq = m_MaxFreq;
144
145 for (i = 0; i < m_NumDigits; i++)
146 {
147 m_DigitInfo[i].weight = pwr;
148 m_DigitInfo[i].incval = pwr;
149 m_DigitInfo[i].modified = true;
150 m_DigitInfo[i].editmode = false;
151 m_DigitInfo[i].val = 0;
152 pwr *= 10;
153 }
154
155 if (m_MaxFreq > pwr)
156 m_MaxFreq = pwr - 1;
157
158 m_MaxFreq = m_MaxFreq - m_MaxFreq % m_MinStep;
159
160 if (m_MinFreq > pwr)
161 m_MinFreq = 1;
162
163 m_MinFreq = m_MinFreq - m_MinFreq % m_MinStep;
164 m_DigStart = 0;
165
166 setUnit(unit);
167
168 for (i = m_NumDigits - 1; i >= 0; i--)
169 {
170 if (m_DigitInfo[i].weight <= m_MinStep)
171 {
172 if (m_DigStart == 0)
173 {
174 m_DigitInfo[i].incval = m_MinStep;
175 m_DigStart = i;
176 }
177 else
178 {
179 if ((m_MinStep % m_DigitInfo[i + 1].weight) != 0)
180 m_DigStart = i;
181 m_DigitInfo[i].incval = 0;
182 }
183 }
184 }
185
186 m_NumSeps = (m_NumDigits - 1) / 3 - m_DigStart / 3;
187 }
188
setFrequency(qint64 freq)189 void CFreqCtrl::setFrequency(qint64 freq)
190 {
191 int i;
192 qint64 acc = 0;
193 qint64 rem;
194 int val;
195
196 if (freq == m_Oldfreq)
197 return;
198
199 if (freq < m_MinFreq)
200 freq = m_MinFreq;
201
202 if (freq > m_MaxFreq)
203 freq = m_MaxFreq;
204
205 m_freq = freq - freq % m_MinStep;
206 rem = m_freq;
207 m_LeadZeroPos = m_NumDigits;
208
209 for (i = m_NumDigits - 1; i >= m_DigStart; i--)
210 {
211 val = (int)(rem / m_DigitInfo[i].weight);
212 if (m_DigitInfo[i].val != val)
213 {
214 m_DigitInfo[i].val = val;
215 m_DigitInfo[i].modified = true;
216 }
217 rem = rem - val * m_DigitInfo[i].weight;
218 acc += val;
219 if ((acc == 0) && (i > m_DecPos))
220 {
221 m_LeadZeroPos = i;
222 }
223 }
224
225 // If the sign changed and the frequency is less than 1 unit,
226 // redraw the leading zero to get the correct sign.
227 if ((m_Oldfreq ^ m_freq) < 0 && m_DigitInfo[m_LeadZeroPos - 1].val == 0)
228 m_DigitInfo[m_LeadZeroPos - 1].modified = true;
229
230 // When frequency is negative all non-zero digits that
231 // have changed will have a negative sign. This loop will
232 // change all digits back to positive, except the one at
233 // position m_leadZeroPos-1. If that position is zero,
234 // it will be checked in the drawing method, drawDigits().
235 /** TBC if this works for all configurations */
236 if (m_freq < 0)
237 {
238 if (m_DigitInfo[m_LeadZeroPos - 1].val > 0)
239 m_DigitInfo[m_LeadZeroPos -
240 1].val = -m_DigitInfo[m_LeadZeroPos - 1].val;
241
242 for (i = 0; i < (m_LeadZeroPos - 1); i++)
243 {
244 if (m_DigitInfo[i].val < 0)
245 m_DigitInfo[i].val = -m_DigitInfo[i].val;
246 }
247 }
248
249 // signal the new frequency to world
250 m_Oldfreq = m_freq;
251 emit newFrequency(m_freq);
252 updateCtrl(m_LastLeadZeroPos != m_LeadZeroPos);
253 m_LastLeadZeroPos = m_LeadZeroPos;
254 }
255
setDigitColor(QColor col)256 void CFreqCtrl::setDigitColor(QColor col)
257 {
258 m_UpdateAll = true;
259 m_DigitColor = col;
260 for (int i = m_DigStart; i < m_NumDigits; i++)
261 m_DigitInfo[i].modified = true;
262 updateCtrl(true);
263 }
264
setUnit(FctlUnit unit)265 void CFreqCtrl::setUnit(FctlUnit unit)
266 {
267 m_NumDigitsForUnit = 2;
268 switch (unit)
269 {
270 case FCTL_UNIT_NONE:
271 m_NumDigitsForUnit = 0;
272 m_DecPos = 0;
273 m_UnitString = QString();
274 break;
275 case FCTL_UNIT_HZ:
276 m_DecPos = 0;
277 m_UnitString = "Hz ";
278 break;
279 case FCTL_UNIT_KHZ:
280 m_DecPos = 3;
281 m_UnitString = "kHz";
282 break;
283 case FCTL_UNIT_MHZ:
284 m_DecPos = 6;
285 m_UnitString = "MHz";
286 break;
287 case FCTL_UNIT_GHZ:
288 m_DecPos = 9;
289 m_UnitString = "GHz";
290 break;
291 case FCTL_UNIT_SEC:
292 m_DecPos = 6;
293 m_UnitString = "Sec";
294 break;
295 case FCTL_UNIT_MSEC:
296 m_DecPos = 3;
297 m_UnitString = "mS ";
298 break;
299 case FCTL_UNIT_USEC:
300 m_DecPos = 0;
301 m_UnitString = "uS ";
302 break;
303 case FCTL_UNIT_NSEC:
304 m_DecPos = 0;
305 m_UnitString = "nS ";
306 break;
307 }
308 m_Unit = unit;
309 m_UpdateAll = true;
310 updateCtrl(true);
311 }
312
setBgColor(QColor col)313 void CFreqCtrl::setBgColor(QColor col)
314 {
315 m_UpdateAll = true;
316 m_BkColor = col;
317
318 for (int i = m_DigStart; i < m_NumDigits; i++)
319 m_DigitInfo[i].modified = true;
320
321 updateCtrl(true);
322 }
323
setUnitsColor(QColor col)324 void CFreqCtrl::setUnitsColor(QColor col)
325 {
326 m_UpdateAll = true;
327 m_UnitsColor = col;
328 updateCtrl(true);
329 }
330
setHighlightColor(QColor col)331 void CFreqCtrl::setHighlightColor(QColor col)
332 {
333 m_UpdateAll = true;
334 m_HighlightColor = col;
335 updateCtrl(true);
336 }
337
updateCtrl(bool all)338 void CFreqCtrl::updateCtrl(bool all)
339 {
340 if (all)
341 {
342 m_UpdateAll = true;
343 for (int i = m_DigStart; i < m_NumDigits; i++)
344 m_DigitInfo[i].modified = true;
345 }
346 update();
347 }
348
resizeEvent(QResizeEvent *)349 void CFreqCtrl::resizeEvent(QResizeEvent *)
350 {
351 // qDebug() <<rect.width() << rect.height();
352 int dpr = devicePixelRatio();
353 m_Pixmap = QPixmap(width() * dpr, height() * dpr); // resize pixmap to current control size
354 m_Pixmap.setDevicePixelRatio(dpr);
355 m_Pixmap.fill(m_BkColor);
356 m_UpdateAll = true;
357 updateCtrl(true);
358 }
359
leaveEvent(QEvent *)360 void CFreqCtrl::leaveEvent(QEvent *)
361 {
362 // called when mouse cursor leaves this control so deactivate any highlights
363 if (m_ActiveEditDigit >= 0)
364 {
365 if (m_DigitInfo[m_ActiveEditDigit].editmode)
366 {
367 m_DigitInfo[m_ActiveEditDigit].editmode = false;
368 m_DigitInfo[m_ActiveEditDigit].modified = true;
369 m_ActiveEditDigit = -1;
370 updateCtrl(false);
371 }
372 }
373 }
374
paintEvent(QPaintEvent *)375 void CFreqCtrl::paintEvent(QPaintEvent *)
376 {
377 QPainter painter(&m_Pixmap);
378
379 if (m_UpdateAll) // if need to redraw everything
380 {
381 drawBkGround(painter);
382 m_UpdateAll = false;
383 }
384 // draw any modified digits to the m_MemDC
385 drawDigits(painter);
386 // now draw pixmap onto screen
387 QPainter scrnpainter(this);
388 scrnpainter.drawPixmap(0, 0, m_Pixmap); // blt to the screen(flickers like a candle, why?)
389 }
390
mouseMoveEvent(QMouseEvent * event)391 void CFreqCtrl::mouseMoveEvent(QMouseEvent *event)
392 {
393 QPoint pt = event->pos();
394 // find which digit is to be edited
395 if (isActiveWindow())
396 {
397 if (!hasFocus())
398 setFocus(Qt::MouseFocusReason);
399
400 for (int i = m_DigStart; i < m_NumDigits; i++)
401 {
402 if (inRect(m_DigitInfo[i].dQRect, pt))
403 {
404 if (!m_DigitInfo[i].editmode)
405 {
406 m_DigitInfo[i].editmode = true;
407 m_ActiveEditDigit = i;
408 }
409 }
410 else
411 {
412 // un-highlight the previous digit if moved off it
413 if (m_DigitInfo[i].editmode)
414 {
415 m_DigitInfo[i].editmode = false;
416 m_DigitInfo[i].modified = true;
417 }
418 }
419 }
420
421 updateCtrl(false);
422 }
423 }
424
mousePressEvent(QMouseEvent * event)425 void CFreqCtrl::mousePressEvent(QMouseEvent *event)
426 {
427 QPoint pt = event->pos();
428 if (event->button() == Qt::LeftButton)
429 {
430 for (int i = m_DigStart; i < m_NumDigits; i++)
431 {
432 if (inRect(m_DigitInfo[i].dQRect, pt)) // if in i'th digit
433 {
434 if (m_LRMouseFreqSel)
435 {
436 incFreq();
437 }
438 else
439 {
440 if (pt.y() < m_DigitInfo[i].dQRect.bottom() / 2) // top half?
441 incFreq();
442 else
443 decFreq(); // bottom half
444 }
445 }
446 }
447 }
448 else if (event->button() == Qt::RightButton)
449 {
450 for (int i = m_DigStart; i < m_NumDigits; i++)
451 {
452 if (inRect(m_DigitInfo[i].dQRect, pt)) // if in i'th digit
453 {
454 if (m_LRMouseFreqSel)
455 {
456 decFreq();
457 }
458 else
459 {
460 clearFreq();
461 }
462 }
463 }
464 }
465 }
466
wheelEvent(QWheelEvent * event)467 void CFreqCtrl::wheelEvent(QWheelEvent *event)
468 {
469 QPoint pt = event->pos();
470 int delta = m_InvertScrolling ? -event->angleDelta().y() : event->angleDelta().y();
471 int numDegrees = delta / 8;
472 int numSteps = numDegrees / 15;
473
474 for (int i = m_DigStart; i < m_NumDigits; i++)
475 {
476 if (inRect(m_DigitInfo[i].dQRect, pt)) // if in i'th digit
477 {
478 if (numSteps > 0)
479 incFreq();
480 else if (numSteps < 0)
481 decFreq();
482 }
483 }
484 }
485
keyPressEvent(QKeyEvent * event)486 void CFreqCtrl::keyPressEvent(QKeyEvent *event)
487 {
488 // call base class if dont over ride key
489 bool fSkipMsg = false;
490 qint64 tmp;
491
492 // qDebug() <<event->key();
493
494 switch (event->key())
495 {
496 case Qt::Key_0:
497 case Qt::Key_1:
498 case Qt::Key_2:
499 case Qt::Key_3:
500 case Qt::Key_4:
501 case Qt::Key_5:
502 case Qt::Key_6:
503 case Qt::Key_7:
504 case Qt::Key_8:
505 case Qt::Key_9:
506 if (m_ActiveEditDigit >= 0)
507 {
508 if (m_DigitInfo[m_ActiveEditDigit].editmode)
509 {
510 tmp = (m_freq / m_DigitInfo[m_ActiveEditDigit].weight) % 10;
511 m_freq -= tmp * m_DigitInfo[m_ActiveEditDigit].weight;
512 m_freq = m_freq + (event->key() - '0') *
513 m_DigitInfo[m_ActiveEditDigit].weight;
514 setFrequency(m_freq);
515 }
516 }
517 moveCursorRight();
518 fSkipMsg = true;
519 break;
520 case Qt::Key_Backspace:
521 case Qt::Key_Left:
522 if (m_ActiveEditDigit != -1)
523 {
524 moveCursorLeft();
525 fSkipMsg = true;
526 }
527 break;
528 case Qt::Key_Up:
529 if (m_ActiveEditDigit != -1)
530 {
531 incFreq();
532 fSkipMsg = true;
533 }
534 break;
535 case Qt::Key_Down:
536 if (m_ActiveEditDigit != -1)
537 {
538 decFreq();
539 fSkipMsg = true;
540 }
541 break;
542 case Qt::Key_Right:
543 if (m_ActiveEditDigit != -1)
544 {
545 moveCursorRight();
546 fSkipMsg = true;
547 }
548 break;
549 case Qt::Key_Home:
550 cursorHome();
551 fSkipMsg = true;
552 break;
553 case Qt::Key_End:
554 cursorEnd();
555 fSkipMsg = true;
556 break;
557 default:
558 break;
559 }
560 if (!fSkipMsg)
561 QFrame::keyPressEvent(event);
562 }
563
drawBkGround(QPainter & Painter)564 void CFreqCtrl::drawBkGround(QPainter &Painter)
565 {
566 QRect rect(0, 0, width(), height());
567
568 // qDebug() <<rect;
569 int cellwidth = 100 * rect.width() /
570 (100 * (m_NumDigits + m_NumDigitsForUnit) +
571 (m_NumSeps * SEPRATIO_N) / SEPRATIO_D);
572 int sepwidth = (SEPRATIO_N * cellwidth) / (100 * SEPRATIO_D);
573 // qDebug() <<cellwidth <<sepwidth;
574
575 // draw unit text
576 if (m_Unit != FCTL_UNIT_NONE)
577 {
578 m_UnitsRect.setRect(rect.right() - 2 * cellwidth, rect.top(),
579 2 * cellwidth, rect.height());
580 Painter.fillRect(m_UnitsRect, m_BkColor); // FIXME: not necessary?
581 m_UnitsFont.setPixelSize((UNITS_SIZE_PERCENT * rect.height()) / 100);
582 m_UnitsFont.setFamily("Arial");
583 Painter.setFont(m_UnitsFont);
584 Painter.setPen(m_UnitsColor);
585 Painter.drawText(m_UnitsRect, Qt::AlignHCenter | Qt::AlignVCenter,
586 m_UnitString);
587 }
588
589 // draw digits
590 m_DigitFont.setPixelSize((DIGIT_SIZE_PERCENT * rect.height()) / 100);
591 m_DigitFont.setFamily("Arial");
592 Painter.setFont(m_DigitFont);
593 Painter.setPen(m_DigitColor);
594
595 char dgsep = ' '; // digit group separator
596 int digpos = rect.right() - m_NumDigitsForUnit * cellwidth - 1; // starting digit x position
597 for (int i = m_DigStart; i < m_NumDigits; i++)
598 {
599 if ((i > m_DigStart) && ((i % 3) == 0))
600 {
601 m_SepRect[i].setCoords(digpos - sepwidth,
602 rect.top(),
603 digpos,
604 rect.bottom());
605 Painter.fillRect(m_SepRect[i], m_BkColor);
606 digpos -= sepwidth;
607 if (m_Unit == FCTL_UNIT_NONE)
608 {
609 if (m_LeadZeroPos > i)
610 dgsep = '.';
611 else
612 dgsep = ' ';
613 }
614 else
615 {
616 if (i == m_DecPos)
617 dgsep = '.';
618 else
619 dgsep = ' ';
620 }
621 Painter.drawText(m_SepRect[i], Qt::AlignHCenter | Qt::AlignVCenter,
622 QChar(dgsep));
623 }
624 else
625 {
626 m_SepRect[i].setCoords(0, 0, 0, 0);
627 }
628 m_DigitInfo[i].dQRect.setCoords(digpos - cellwidth, rect.top(),
629 digpos, rect.bottom());
630 digpos -= cellwidth;
631 }
632 }
633
634 // Draws just the Digits that have been modified
drawDigits(QPainter & Painter)635 void CFreqCtrl::drawDigits(QPainter &Painter)
636 {
637 Painter.setFont(m_DigitFont);
638 m_FirstEditableDigit = m_DigStart;
639
640 for (int i = m_DigStart; i < m_NumDigits; i++)
641 {
642 if (m_DigitInfo[i].incval == 0)
643 m_FirstEditableDigit++;
644
645 if (m_DigitInfo[i].modified || m_DigitInfo[i].editmode)
646 {
647 if (m_DigitInfo[i].editmode && m_DigitInfo[i].incval != 0)
648 Painter.fillRect(m_DigitInfo[i].dQRect, m_HighlightColor);
649 else
650 Painter.fillRect(m_DigitInfo[i].dQRect, m_BkColor);
651
652 if (i >= m_LeadZeroPos)
653 Painter.setPen(m_InactiveColor);
654 else
655 Painter.setPen(m_DigitColor);
656
657 if (m_freq < 0 && i == m_LeadZeroPos - 1 && m_DigitInfo[i].val == 0)
658 Painter.drawText(m_DigitInfo[i].dQRect,
659 Qt::AlignHCenter | Qt::AlignVCenter,
660 QString("-0"));
661 else
662 Painter.drawText(m_DigitInfo[i].dQRect,
663 Qt::AlignHCenter | Qt::AlignVCenter,
664 QString().number(m_DigitInfo[i].val));
665 m_DigitInfo[i].modified = false;
666 }
667 }
668 }
669
670 // Increment just the digit active in edit mode
incDigit()671 void CFreqCtrl::incDigit()
672 {
673 /** FIXME: no longer used? */
674 int tmp;
675 qint64 tmpl;
676
677 if (m_ActiveEditDigit >= 0)
678 {
679 if (m_DigitInfo[m_ActiveEditDigit].editmode)
680 {
681 if (m_DigitInfo[m_ActiveEditDigit].weight ==
682 m_DigitInfo[m_ActiveEditDigit].incval)
683 {
684 // get the current digit value
685 tmp =
686 (int)((m_freq / m_DigitInfo[m_ActiveEditDigit].weight) %
687 10);
688 // set the current digit value to zero
689 m_freq -= tmp * m_DigitInfo[m_ActiveEditDigit].weight;
690 tmp++;
691 if (tmp > 9)
692 tmp = 0;
693 m_freq = m_freq + (qint64)tmp *
694 m_DigitInfo[m_ActiveEditDigit].weight;
695 }
696 else
697 {
698 tmp =
699 (int)((m_freq / m_DigitInfo[m_ActiveEditDigit + 1].weight) %
700 10);
701 tmpl = m_freq + m_DigitInfo[m_ActiveEditDigit].incval;
702 if (tmp !=
703 (int)((tmpl / m_DigitInfo[m_ActiveEditDigit + 1].weight) %
704 10))
705 {
706 tmpl -= m_DigitInfo[m_ActiveEditDigit + 1].weight;
707 }
708 m_freq = tmpl;
709 }
710 setFrequency(m_freq);
711 }
712 }
713 }
714
715 // Increment the frequency by this digit active in edit mode
incFreq()716 void CFreqCtrl::incFreq()
717 {
718 if (m_ActiveEditDigit >= 0)
719 {
720 if (m_DigitInfo[m_ActiveEditDigit].editmode)
721 {
722 m_freq += m_DigitInfo[m_ActiveEditDigit].incval;
723 if (m_ResetLowerDigits)
724 {
725 /* Set digits below the active one to 0 */
726 m_freq = m_freq - m_freq %
727 m_DigitInfo[m_ActiveEditDigit].weight;
728 }
729 setFrequency(m_freq);
730 m_LastEditDigit = m_ActiveEditDigit;
731 }
732 }
733 }
734
735 // Decrement the digit active in edit mode
decDigit()736 void CFreqCtrl::decDigit()
737 {
738 /** FIXME: no longer used? */
739 int tmp;
740 qint64 tmpl;
741
742 if (m_ActiveEditDigit >= 0)
743 {
744 if (m_DigitInfo[m_ActiveEditDigit].editmode)
745 {
746 if (m_DigitInfo[m_ActiveEditDigit].weight ==
747 m_DigitInfo[m_ActiveEditDigit].incval)
748 {
749 // get the current digit value
750 tmp =
751 (int)((m_freq / m_DigitInfo[m_ActiveEditDigit].weight) %
752 10);
753 // set the current digit value to zero
754 m_freq -= tmp * m_DigitInfo[m_ActiveEditDigit].weight;
755 tmp--;
756 if (tmp < 0)
757 tmp = 9;
758 m_freq = m_freq + (qint64)tmp *
759 m_DigitInfo[m_ActiveEditDigit].weight;
760 }
761 else
762 {
763 tmp =
764 (int)((m_freq / m_DigitInfo[m_ActiveEditDigit + 1].weight) %
765 10);
766 tmpl = m_freq - m_DigitInfo[m_ActiveEditDigit].incval;
767 if (tmp !=
768 (int)((tmpl / m_DigitInfo[m_ActiveEditDigit + 1].weight) %
769 10))
770 {
771 tmpl += m_DigitInfo[m_ActiveEditDigit + 1].weight;
772 }
773 m_freq = tmpl;
774 }
775 setFrequency(m_freq);
776 }
777 }
778 }
779
780 // Decrement the frequency by this digit active in edit mode
decFreq()781 void CFreqCtrl::decFreq()
782 {
783 if (m_ActiveEditDigit >= 0)
784 {
785 if (m_DigitInfo[m_ActiveEditDigit].editmode)
786 {
787 m_freq -= m_DigitInfo[m_ActiveEditDigit].incval;
788 if (m_ResetLowerDigits)
789 {
790 /* digits below the active one are reset to 0 */
791 m_freq = m_freq - m_freq %
792 m_DigitInfo[m_ActiveEditDigit].weight;
793 }
794
795 setFrequency(m_freq);
796 m_LastEditDigit = m_ActiveEditDigit;
797 }
798 }
799 }
800
801 // Clear the selected digit and the digits below (i.e. set them to 0)
clearFreq()802 void CFreqCtrl::clearFreq()
803 {
804 if (m_ActiveEditDigit >= 0)
805 {
806 if (m_DigitInfo[m_ActiveEditDigit].editmode)
807 {
808 m_freq -= m_DigitInfo[m_ActiveEditDigit].val *
809 m_DigitInfo[m_ActiveEditDigit].incval;
810
811 /* digits below the active one are reset to 0 */
812 m_freq -= m_freq % m_DigitInfo[m_ActiveEditDigit].weight;
813
814 setFrequency(m_freq);
815 m_LastEditDigit = m_ActiveEditDigit;
816 }
817 }
818 }
819
820 // Cursor move routines for arrow key editing
moveCursorLeft()821 void CFreqCtrl::moveCursorLeft()
822 {
823 if ((m_ActiveEditDigit >= 0) && (m_ActiveEditDigit < m_NumDigits - 1))
824 {
825 cursor().setPos(mapToGlobal(m_DigitInfo[++m_ActiveEditDigit].dQRect.
826 center()));
827 }
828 }
829
moveCursorRight()830 void CFreqCtrl::moveCursorRight()
831 {
832 if (m_ActiveEditDigit > m_FirstEditableDigit)
833 {
834 cursor().setPos(mapToGlobal(m_DigitInfo[--m_ActiveEditDigit].dQRect.
835 center()));
836 }
837 }
838
cursorHome()839 void CFreqCtrl::cursorHome()
840 {
841 if (m_ActiveEditDigit >= 0)
842 {
843 cursor().setPos(mapToGlobal(
844 m_DigitInfo[m_NumDigits - 1].dQRect.center()));
845 }
846 }
847
cursorEnd()848 void CFreqCtrl::cursorEnd()
849 {
850 if (m_ActiveEditDigit > 0)
851 {
852 cursor().setPos(mapToGlobal(m_DigitInfo[m_FirstEditableDigit].dQRect.
853 center()));
854 }
855 }
856
setFrequencyFocus()857 void CFreqCtrl::setFrequencyFocus()
858 {
859 uint8_t position = floor(log10(m_freq));
860 position = (uint8_t)fmax(position, 4); // restrict min to 100s of kHz
861
862 QMouseEvent mouseEvent(QEvent::MouseMove,
863 m_DigitInfo[position].dQRect.center(),
864 Qt::NoButton,
865 Qt::NoButton,
866 Qt::NoModifier);
867 mouseMoveEvent(&mouseEvent);
868 }
869