Loading...
Searching...
No Matches
NumericValueWidget.hpp
1#pragma once
2#include "ValueWidget.hpp"
3
4#include <score/widgets/MarginLess.hpp>
5#include <score/widgets/SignalUtils.hpp>
6#include <score/widgets/SpinBoxes.hpp>
7#include <score/widgets/TextLabel.hpp>
8
9#include <ossia/network/domain/domain.hpp>
10
11#include <QCheckBox>
12#include <QDialog>
13#include <QDialogButtonBox>
14#include <QGridLayout>
15#include <QHBoxLayout>
16#include <QPushButton>
17#include <QVBoxLayout>
18
19namespace State
20{
21template <typename T>
22using MatchingSpinbox = typename score::TemplatedSpinBox<T>::spinbox_type;
23
24template <typename T>
25class NumericValueWidget final : public ValueWidget
26{
27public:
28 NumericValueWidget(T value, QWidget* parent = nullptr)
29 : ValueWidget{parent}
30 {
31 auto lay = new score::MarginLess<QGridLayout>{this};
32 m_valueSBox = new score::SpinBox<T>{this};
33 lay->addWidget(m_valueSBox);
34 m_valueSBox->setValue(value);
35 }
36
37 ossia::value value() const override { return ossia::value{m_valueSBox->value()}; }
38
39private:
40 score::SpinBox<T>* m_valueSBox{};
41};
42
43template <typename T>
44class NumericValueSetDialog final : public QDialog
45{
46public:
47 using set_type = std::vector<T>;
48 NumericValueSetDialog(QWidget* parent)
49 : QDialog{parent}
50 {
51 auto lay = new score::MarginLess<QVBoxLayout>{this};
52 this->setLayout(lay);
53 lay->addLayout(m_lay = new score::MarginLess<QVBoxLayout>);
54
55 auto addbutton = new QPushButton{tr("+"), this};
56 connect(addbutton, &QPushButton::pressed, this, [this] { addRow({}); });
57 lay->addWidget(addbutton);
58
59 auto buttonBox
60 = new QDialogButtonBox{QDialogButtonBox::Ok | QDialogButtonBox::Cancel};
61
62 lay->addWidget(buttonBox);
63
64 connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
65 connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
66 }
67
68 set_type values()
69 {
70 set_type t;
71 for(auto widg : m_widgs)
72 {
73 t.push_back(widg->value().template get<T>());
74 }
75 return t;
76 }
77
78 void setValues(const set_type& t)
79 {
80 // OPTIMIZEME by reusing
81 for(auto row : m_rows)
82 delete row;
83 m_rows.clear();
84 m_widgs.clear();
85
86 for(auto val : t)
87 {
88 addRow(val);
89 }
90 }
91
92private:
93 void addRow(T c)
94 {
95 auto sub_widg = new QWidget{this};
96 auto sub_lay = new score::MarginLess<QHBoxLayout>{sub_widg};
97
98 auto minus_b = new QPushButton{tr("-"), this};
99 sub_lay->addWidget(minus_b);
100
101 connect(minus_b, &QPushButton::clicked, this, [this, i = m_rows.size()] {
102 removeRow(i);
103 });
104
105 auto widg = new NumericValueWidget<T>{c, this};
106 sub_lay->addWidget(widg);
107
108 m_lay->addWidget(sub_widg);
109 m_rows.push_back(sub_widg);
110 m_widgs.push_back(widg);
111 }
112
113 void removeRow(std::size_t i)
114 {
115 if(i < m_rows.size())
116 {
117 delete m_rows[i];
118 m_rows.erase(m_rows.begin() + i);
119 m_widgs.erase(m_widgs.begin() + i);
120 }
121 }
122
123 QVBoxLayout* m_lay{};
124 std::vector<QWidget*> m_rows;
125 std::vector<NumericValueWidget<T>*> m_widgs;
126};
127
128template <typename T>
129class NumericDomainWidget final : public QWidget
130{
131public:
132 using domain_type = ossia::domain_base<T>;
133 using set_type = std::vector<T>;
134
135 NumericDomainWidget(QWidget* parent)
136 : QWidget{parent}
137 {
138 auto lay = new score::MarginLess<QHBoxLayout>{this};
139 this->setLayout(lay);
140
141 m_minCB = new QCheckBox{tr("Min"), this};
142 m_maxCB = new QCheckBox{tr("Max"), this};
143 m_min = new score::SpinBox<T>{this};
144 m_max = new score::SpinBox<T>{this};
145 lay->addWidget(m_minCB);
146 lay->addWidget(m_min);
147 lay->addWidget(m_maxCB);
148 lay->addWidget(m_max);
149
150 m_min->setEnabled(false);
151 m_max->setEnabled(false);
152
153 connect(m_minCB, SignalUtils::QCheckBox_checkStateChanged(), this, [this](int st) {
154 m_min->setEnabled(bool(st));
155 });
156 connect(m_maxCB, SignalUtils::QCheckBox_checkStateChanged(), this, [this](int st) {
157 m_max->setEnabled(bool(st));
158 });
159 auto pb = new QPushButton{tr("Values"), this};
160 lay->addWidget(pb);
161
162 connect(pb, &QPushButton::clicked, this, [this] {
163 NumericValueSetDialog<T> dial{this};
164 dial.setValues(m_values);
165
166 if(dial.exec())
167 {
168 m_values = dial.values();
169 }
170 });
171 }
172
173 domain_type domain() const
174 {
175 domain_type dom;
176
177 if(m_minCB->checkState())
178 dom.min = m_min->value();
179 else
180 dom.min = std::nullopt;
181
182 if(m_maxCB->checkState())
183 dom.max = m_max->value();
184 else
185 dom.max = std::nullopt;
186
187 dom.values = m_values;
188
189 return dom;
190 }
191
192 void set_domain(ossia::domain dom_base)
193 {
194 m_values.clear();
195 m_minCB->setCheckState(Qt::Unchecked);
196 m_maxCB->setCheckState(Qt::Unchecked);
197
198 if(auto dom_p = dom_base.v.target<domain_type>())
199 {
200 auto& dom = *dom_p;
201
202 if(dom.min)
203 {
204 m_minCB->setCheckState(Qt::Checked);
205 m_min->setValue(*dom.min);
206 }
207 if(dom.max)
208 {
209 m_maxCB->setCheckState(Qt::Checked);
210 m_max->setValue(*dom.max);
211 }
212
213 m_values = dom.values;
214 }
215 }
216
217private:
218 QCheckBox* m_minCB{};
219 QCheckBox* m_maxCB{};
220 score::SpinBox<T>* m_min{};
221 score::SpinBox<T>* m_max{};
222
223 set_type m_values;
224};
225}
Definition NumericValueWidget.hpp:130
Definition NumericValueWidget.hpp:45
Definition NumericValueWidget.hpp:26
The ValueWidget class.
Definition ValueWidget.hpp:25
The MarginLess class.
Definition MarginLess.hpp:14
The SpinBox class.
Definition SpinBoxes.hpp:68
Utilities for OSSIA data structures.
Definition DeviceInterface.hpp:33
The TemplatedSpinBox class.
Definition SpinBoxes.hpp:19