CVB++ 15.1
Loading...
Searching...
No Matches
detail_custom_lineedit.hpp
1#pragma once
2
3#pragma warning(push)
4#pragma warning(disable : 4800)
5#pragma warning(disable : 4251)
6#pragma warning(disable : 4244)
7#include <QFrame>
8#include <QList>
9#include <QLineEdit>
10#include <QHBoxLayout>
11#include <QLabel>
12#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
13# include <QRegularExpressionValidator>
14#else
15# include <QRegExpValidator>
16#endif
17#include <QEvent>
18#include <QKeyEvent>
19#pragma warning(pop)
20
21#include "../../global.hpp"
22#include "../../utilities/system_info.hpp"
23
24namespace Cvb
25{
26
27 CVB_BEGIN_INLINE_NS
28
29 namespace UI
30 {
31 namespace Private
32 {
33
34#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
35 using RegExp = QRegularExpression;
36 using RegExpValidator = QRegularExpressionValidator;
37#else
38 using RegExp = QRegExp;
39 using RegExpValidator = QRegExpValidator;
40#endif
41
42 class CustomLineEdit : public QFrame
43 {
44
45 Q_OBJECT
46
47 public:
48 CustomLineEdit(RegExp rx, QString separator, int numLineEdits = 1, int maxDigits = 4, QWidget *parent = 0)
49 : QFrame(parent)
50 , numLineEdits_(numLineEdits)
51 , maxDigits_(maxDigits)
52 {
53 setFrameShape(QFrame::Panel);
54 setFrameShadow(QFrame::Sunken);
55
56 auto layout = new QHBoxLayout(this); // NOLINT(cppcoreguidelines-owning-memory)
57 layout->setContentsMargins(0, 0, 0, 0);
58 layout->setSpacing(0);
59
60 for (int i = 0; i != numLineEdits_; ++i)
61 {
62 if (i != 0)
63 {
64 auto sep = new QLabel(separator, this);
65 sep->setStyleSheet("background: white");
66 layout->addWidget(sep);
67 layout->setStretch(layout->count(), 0);
68 }
69
70 auto edit = new QLineEdit(this); // NOLINT(cppcoreguidelines-owning-memory)
71 edit->installEventFilter(this);
72
73 layout->addWidget(edit);
74 layout->setStretch(layout->count(), 1);
75
76 edit->setFrame(false);
77 edit->setAlignment(Qt::AlignCenter);
78
79 auto font = edit->font();
80 font.setStyleHint(QFont::Monospace);
81 font.setFixedPitch(true);
82 edit->setFont(font);
83
84 auto validator = new RegExpValidator(rx, edit); // NOLINT(cppcoreguidelines-owning-memory)
85 edit->setValidator(validator);
86
87 lineEdit_.append(edit);
88
89 QObject::connect(edit, &QLineEdit::editingFinished, [this]() {
90 for (int i = 0; i < numLineEdits_; i++)
91 {
92 if (lineEdit_[i]->hasFocus())
93 return;
94 }
95 TextChanged(Text()); // send signal
96 });
97 }
98
99 setMaximumWidth(30 * numLineEdits);
100 }
101
102 void SetReadOnly(bool readOnly)
103 {
104 for (int i = 0; i < numLineEdits_; i++)
105 {
106 lineEdit_[i]->setReadOnly(readOnly);
107 }
108 }
109
110 void SetEnabled(bool enabled)
111 {
112 for (int i = 0; i < numLineEdits_; i++)
113 {
114 lineEdit_[i]->setEnabled(enabled);
115 }
116 }
117
118 protected:
119 bool eventFilter(QObject *obj, QEvent *event) override
120 {
121 auto bRes = QFrame::eventFilter(obj, event);
122
123 if (event->type() == QEvent::KeyPress)
124 {
125 auto keyevent = dynamic_cast<QKeyEvent *>(event);
126 if (keyevent)
127 {
128 for (int i = 0; i < numLineEdits_; ++i)
129 {
130 auto lineEdit = lineEdit_[i];
131 if (lineEdit == obj)
132 {
133 switch (keyevent->key())
134 {
135 case Qt::Key_Left:
136 if (lineEdit->cursorPosition() == 0)
137 {
138 // user wants to move to previous item
139 MovePrevLineEdit(i);
140 }
141 break;
142
143 case Qt::Key_Right:
144 if (lineEdit->text().isEmpty() || (lineEdit->text().size() == lineEdit->cursorPosition()))
145 {
146 // user wants to move to next item
147 MoveNextLineEdit(i);
148 }
149 break;
150
151 case Qt::Key_0:
152 if (lineEdit->text().isEmpty() || lineEdit->text() == "0")
153 {
154 lineEdit->setText("0");
155 // user wants to move to next item
156 MoveNextLineEdit(i);
157 }
158 break;
159
160 case Qt::Key_Backspace:
161 if (lineEdit->text().isEmpty() || lineEdit->cursorPosition() == 0)
162 {
163 // user wants to move to previous item
164 MovePrevLineEdit(i);
165 }
166 break;
167
168 case Qt::Key_Comma:
169 case Qt::Key_Period:
170 MoveNextLineEdit(i);
171 break;
172
173 case Qt::Key_Tab:
174 break;
175
176 case Qt::Key_Return:
177 TextChanged(Text()); // send signal
178 break;
179 }
180 }
181 }
182 }
183 }
184
185 return bRes;
186 }
187
188 Q_SIGNALS:
189
190 void TextChanged(const QString &text);
191
192 private:
193 void MoveNextLineEdit(int i)
194 {
195 if (i + 1 != numLineEdits_)
196 {
197 lineEdit_[i + 1]->setFocus();
198 lineEdit_[i + 1]->setCursorPosition(0);
199 lineEdit_[i + 1]->selectAll();
200 }
201 }
202
203 void MovePrevLineEdit(int i)
204 {
205 if (i != 0)
206 {
207 lineEdit_[i - 1]->setFocus();
208 lineEdit_[i - 1]->setCursorPosition(static_cast<int>(lineEdit_[i - 1]->text().size()));
209 }
210 }
211
212 virtual QString Text() const = 0;
213 virtual void SetText(const QString &text) = 0;
214
215 protected:
216 int numLineEdits_; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
217 int maxDigits_; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
218 QList<QLineEdit *> lineEdit_; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
219
220 }; /* class CustomLineEdit */
221
222 class IpLineEdit : public CustomLineEdit
223 {
224
225 Q_OBJECT
226
227 public:
228 explicit IpLineEdit(QWidget *parent = 0)
229 : CustomLineEdit(RegExp("^(0|[1-9]|[1-9][0-9]|1[0-9][0-9]|2([0-4][0-9]|5[0-5]))$"), ".", 4, 3, parent)
230 {
231 }
232
233 QString Text() const override
234 {
235 auto value = QString("");
236 for (int i = 0; i < numLineEdits_; i++)
237 {
238 value.append(lineEdit_[i]->text());
239 if (i < (numLineEdits_ - 1))
240 value.append(".");
241 }
242
243 if (value.isEmpty())
244 {
245 for (int i = 0; i < numLineEdits_; ++i)
246 {
247 value.append("0");
248 if (i < (numLineEdits_ - 1))
249 value.append(".");
250 }
251 return value;
252 }
253 return value;
254 }
255
256 void SetText(const QString &text) override
257 {
258 auto ip = text.split(".");
259
260 if (ip.size() != numLineEdits_)
261 return;
262
263 for (int i = 0; i < numLineEdits_; i++)
264 {
265 lineEdit_[i]->setText(ip.at(i));
266 }
267 }
268
269 }; /* class IpLineEdit */
270
271 class MacLineEdit : public CustomLineEdit
272 {
273
274 Q_OBJECT
275
276 public:
277 explicit MacLineEdit(QWidget *parent = 0)
278 : CustomLineEdit(RegExp("[0-9A-Fa-f]{2}"), "-", 6, 2, parent)
279 {
280 }
281
282 QString Text() const override
283 {
284 auto value = QString("");
285 for (int i = 0; i < numLineEdits_; i++)
286 {
287 value.append(lineEdit_[i]->text());
288 if (i < (numLineEdits_ - 1))
289 value.append("-");
290 }
291
292 if (value.isEmpty())
293 return "00-00-00-00-00-00";
294 return value;
295 }
296
297 void SetText(const QString &text) override
298 {
299 auto mac = text.split("-");
300
301 if (mac.size() != numLineEdits_)
302 mac = text.split(":");
303
304 if (mac.size() != numLineEdits_)
305 return;
306
307 for (int i = 0; i < numLineEdits_; i++)
308 {
309 lineEdit_[i]->setText(mac.at(i));
310 }
311 }
312
313 }; /* class MacLineEdit */
314
315 } /* namespace Private */
316 } /* namespace UI */
317
318 CVB_END_INLINE_NS
319
320} /* namespace Cvb */
Namespace for user interface components.
Definition decl_image_scene.hpp:39
Root namespace for the Image Manager interface.
Definition version.hpp:11