]> sigrok.org Git - pulseview.git/blob - pv/widgets/sweeptimingwidget.cpp
SweepTimingWidgets: Fix list mode to show the correct suffix
[pulseview.git] / pv / widgets / sweeptimingwidget.cpp
1 /*
2  * This file is part of the PulseView project.
3  *
4  * Copyright (C) 2013 Joel Holdsworth <joel@airwebreathe.org.uk>
5  *
6  * This program 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.
10  *
11  * This program 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.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
19  */
20
21 #include "sweeptimingwidget.h"
22
23 #include <vector>
24
25 #include <assert.h>
26
27 #include <extdef.h>
28
29 using std::vector;
30
31 namespace pv {
32 namespace widgets {
33
34 SweepTimingWidget::SweepTimingWidget(const char *suffix,
35         QWidget *parent) :
36         QWidget(parent),
37         _suffix(suffix),
38         _layout(this),
39         _value(this),
40         _list(this),
41         _value_type(None)
42 {
43         setContentsMargins(0, 0, 0, 0);
44
45         _value.setDecimals(0);
46         _value.setSuffix(QString::fromUtf8(suffix));
47
48         connect(&_list, SIGNAL(currentIndexChanged(int)),
49                 this, SIGNAL(value_changed()));
50         connect(&_value, SIGNAL(editingFinished()),
51                 this, SIGNAL(value_changed()));
52
53         setLayout(&_layout);
54         _layout.setMargin(0);
55         _layout.addWidget(&_list);
56         _layout.addWidget(&_value);
57
58         show_none();
59 }
60
61 void SweepTimingWidget::show_none()
62 {
63         _value_type = None;
64         _value.hide();
65         _list.hide();
66 }
67
68 void SweepTimingWidget::show_min_max_step(uint64_t min, uint64_t max,
69         uint64_t step)
70 {
71         assert(max > min);
72         assert(step > 0);
73
74         _value_type = MinMaxStep;
75
76         _value.setRange(min, max);
77         _value.setSingleStep(step);
78
79         _value.show();
80         _list.hide();
81 }
82
83 void SweepTimingWidget::show_list(const uint64_t *vals, size_t count)
84 {
85         _value_type = List;
86
87         _list.clear();
88         for (size_t i = 0; i < count; i++)
89         {
90                 char *const s = sr_si_string_u64(vals[i], _suffix);
91                 _list.addItem(QString::fromUtf8(s),
92                         qVariantFromValue(vals[i]));
93                 g_free(s);
94         }
95
96         _value.hide();
97         _list.show();
98 }
99
100 void SweepTimingWidget::show_125_list(uint64_t min, uint64_t max)
101 {
102         assert(max > min);
103
104         // Create a 1-2-5-10 list of entries.
105         const unsigned int FineScales[] = {1, 2, 5};
106         uint64_t value, decade;
107         unsigned int fine;
108         vector<uint64_t> values;
109
110         // Compute the starting decade
111         for (decade = 1; decade * 10 <= min; decade *= 10);
112
113         // Compute the first entry
114         for (fine = 0; fine < countof(FineScales); fine++)
115                 if (FineScales[fine] * decade >= min)
116                         break;
117
118         assert(fine < countof(FineScales));
119
120         // Add the minimum entry if it's not on the 1-2-5 progression
121         if (min != FineScales[fine] * decade)
122                 values.push_back(min);
123
124         while ((value = FineScales[fine] * decade) < max) {
125                 values.push_back(value);
126                 if (++fine >= countof(FineScales))
127                         fine = 0, decade *= 10;
128         }
129
130         // Add the max value
131         values.push_back(max);
132
133         // Make a C array, and give it to the sweep timing widget
134         uint64_t *const values_array = new uint64_t[values.size()];
135         copy(values.begin(), values.end(), values_array);
136         show_list(values_array, values.size());
137         delete[] values_array;
138 }
139
140 uint64_t SweepTimingWidget::value() const
141 {
142         switch(_value_type)
143         {
144         case None:
145                 return 0;
146
147         case MinMaxStep:
148                 return (uint64_t)_value.value();
149
150         case List:
151         {
152                 const int index = _list.currentIndex();
153                 return (index >= 0) ? _list.itemData(
154                         index).value<uint64_t>() : 0;
155         }
156
157         default:
158                 // Unexpected value type
159                 assert(0);
160                 return 0;
161         }
162 }
163
164 void SweepTimingWidget::set_value(uint64_t value)
165 {
166         _value.setValue(value);
167
168         for (int i = 0; i < _list.count(); i++)
169                 if (value == _list.itemData(i).value<uint64_t>())
170                         _list.setCurrentIndex(i);
171 }
172
173 } // widgets
174 } // pv