Line data Source code
1 : // DUNE DAQ modification notice:
2 : // This file has been modified from the original ATLAS dbe source for the DUNE DAQ project.
3 : // Fork baseline commit: dbe-02-12-17 (2022-05-12).
4 : // Renamed since fork: no.
5 :
6 : #include "dbe/BuildingBlockEditors.hpp"
7 : #include "dbe/CustomDelegate.hpp"
8 : #include "dbe/ObjectEditor.hpp"
9 : #include "dbe/StyleUtility.hpp"
10 : #include "dbe/Validator.hpp"
11 : #include "dbe/confaccessor.hpp"
12 : #include "dbe/config_api.hpp"
13 :
14 : #include <QByteArray>
15 : #include <QCompleter>
16 : #include <QDataStream>
17 : #include <QEvent>
18 : #include <QLineEdit>
19 : #include <QListWidget>
20 : #include <QMessageBox>
21 : #include <QMimeData>
22 : #include <QPair>
23 : #include <QStringListModel>
24 : #include <QWidget>
25 :
26 : #include <boost/scope_exit.hpp>
27 :
28 : #include <functional>
29 : #include <memory>
30 :
31 : namespace dbe {
32 0 : editor_data_state::~editor_data_state() = default;
33 :
34 : template<>
35 0 : editor_data<dunedaq::conffwk::relationship_t>::editor_data(dunedaq::conffwk::relationship_t const& virtue)
36 : : editor_data_state(true, false, true)
37 0 : , this_virtue(virtue)
38 : {
39 0 : }
40 :
41 : template<typename T>
42 0 : editor_data<T>::~editor_data() = default;
43 :
44 : namespace widgets {
45 :
46 : namespace editors {
47 : //------------------------------------------------------------------------------------------------
48 0 : base::base(std::shared_ptr<editor_data_state> editordata, QWidget* parent, bool owned)
49 : : QWidget(parent)
50 0 : , p_data_editor(editordata)
51 0 : , this_is_owned(owned)
52 0 : , this_value_changed(false)
53 0 : , this_initial_load(false)
54 : {
55 0 : }
56 :
57 : template<>
58 : std::shared_ptr<editor_data_state>
59 0 : base::dataeditor<editor_data_state>()
60 : {
61 0 : return p_data_editor;
62 : }
63 :
64 : QStringList
65 0 : base::getdata()
66 : {
67 0 : return this_data;
68 : }
69 :
70 : void
71 0 : base::setdata(QStringList const& ValueList)
72 : {
73 0 : this_data = ValueList;
74 0 : }
75 :
76 : void
77 0 : base::setdefaults(QString const& ValueDefault)
78 : {
79 0 : this_defaults = ValueDefault;
80 0 : }
81 :
82 : void
83 0 : base::setchanged(bool const val)
84 : {
85 0 : this_value_changed = val;
86 0 : }
87 :
88 : bool
89 0 : base::ischanged() const
90 : {
91 0 : return this_value_changed;
92 : }
93 :
94 : void
95 0 : base::slot_set_initial_loaded()
96 : {
97 0 : this_initial_load = true;
98 0 : }
99 :
100 : void
101 0 : base::closeEvent(QCloseEvent* Event)
102 : {
103 0 : Q_UNUSED(Event)
104 0 : }
105 :
106 : //------------------------------------------------------------------------------------------------
107 :
108 : //------------------------------------------------------------------------------------------------
109 0 : relation::relation(t_virtue const& relation, QWidget* parent, bool owned, bool readonly)
110 0 : : base(std::make_shared<t_build_block_editor>(relation), parent, owned)
111 0 : , p_base_data_editor(std::static_pointer_cast<t_build_block_editor>(p_data_editor))
112 0 : , IsMultiValue(false)
113 0 : , m_readonly(readonly)
114 0 : , StatusBar(nullptr)
115 0 : , ContextMenu(nullptr)
116 0 : , RemoveAction(nullptr)
117 0 : , MoveTop(nullptr)
118 0 : , MoveBottom(nullptr)
119 0 : , MoveUp(nullptr)
120 0 : , MoveDown(nullptr)
121 0 : , EditAction(nullptr)
122 0 : , CurrentItem(nullptr)
123 : {
124 0 : setupUi(this);
125 :
126 0 : t_virtue const& Virtue = p_base_data_editor->get();
127 :
128 0 : setWindowTitle(QString("Edit Relationship: %1").arg(Virtue.p_name.c_str()));
129 0 : ListWidget->setContextMenuPolicy(Qt::CustomContextMenu);
130 0 : ComboBox->setHidden(true);
131 :
132 : // if it is X_ and many then set multivalue
133 :
134 0 : if ((Virtue.p_cardinality == dunedaq::conffwk::zero_or_many) ||
135 : (Virtue.p_cardinality == dunedaq::conffwk::one_or_many)) {
136 0 : IsMultiValue = true;
137 : }
138 :
139 : // Check if this relation can be left unset
140 0 : if ((Virtue.p_cardinality == dunedaq::conffwk::one_or_many) || (Virtue.p_cardinality == dunedaq::conffwk::only_one)) {
141 0 : p_base_data_editor->set_not_null(true);
142 0 : p_base_data_editor->set_valid(false);
143 : }
144 :
145 : /// Setting Controller
146 0 : SetController();
147 :
148 0 : if (this_is_owned) {
149 0 : SaveButton->setHidden(true);
150 0 : RemoveButton->setHidden(true);
151 : }
152 :
153 0 : buildtooltip();
154 0 : }
155 :
156 : bool
157 0 : relation::eventFilter(QObject* Target, QEvent* Event)
158 : {
159 0 : if (dynamic_cast<QListWidget*>(Target)) {
160 0 : auto decode = [this](const QMimeData* const data) -> QPair<bool, QStringList> {
161 0 : bool allGood = true;
162 0 : QStringList newItems;
163 :
164 0 : if (data->hasFormat("application/vnd.text.list") == true) {
165 0 : QByteArray encodedData = data->data("application/vnd.text.list");
166 0 : QDataStream stream(&encodedData, QIODevice::ReadOnly);
167 :
168 0 : const std::string& referenceClass = p_base_data_editor->get().p_type;
169 :
170 0 : while (!stream.atEnd()) {
171 0 : QStringList text;
172 0 : stream >> text;
173 :
174 0 : const QString& obj_id = text.at(0);
175 0 : const QString& obj_class = text.at(1);
176 :
177 0 : if ((obj_class.toStdString() == referenceClass) ||
178 0 : (dbe::config::api::info::onclass::derived(referenceClass, obj_class.toStdString()) == true)) {
179 0 : newItems.append(obj_id);
180 : } else {
181 0 : allGood = false;
182 : }
183 0 : }
184 0 : } else {
185 0 : allGood = false;
186 : }
187 :
188 0 : return qMakePair(allGood, newItems);
189 0 : };
190 :
191 0 : if (Event->type() == QEvent::DragEnter) {
192 0 : QDragEnterEvent* tDragEvent = static_cast<QDragEnterEvent*>(Event);
193 :
194 0 : const QMimeData* const data = tDragEvent->mimeData();
195 0 : const auto& decodedData = decode(data);
196 0 : if ((decodedData.first == true) && (decodedData.second.size() > 0)) {
197 0 : tDragEvent->acceptProposedAction();
198 : }
199 :
200 0 : return true;
201 0 : }
202 :
203 0 : if (Event->type() == QEvent::Drop) {
204 0 : QDropEvent* tDropEvent = static_cast<QDropEvent*>(Event);
205 0 : if (!m_readonly) {
206 0 : const QMimeData* const data = tDropEvent->mimeData();
207 0 : for (const QString& o : decode(data).second) {
208 : // TODO: this is not very efficient for large lists
209 0 : AddToDataList(o);
210 0 : }
211 : }
212 :
213 0 : tDropEvent->acceptProposedAction();
214 :
215 0 : return true;
216 : }
217 0 : } else if (QComboBox* Box = dynamic_cast<QComboBox*>(Target)) {
218 0 : if (Event->type() == QEvent::Wheel) {
219 : return true;
220 : }
221 :
222 0 : if (Event->type() == QEvent::KeyPress) {
223 0 : QKeyEvent* KeyEvent = dynamic_cast<QKeyEvent*>(Event);
224 :
225 0 : if (KeyEvent->key() == Qt::Key_Up || KeyEvent->key() == Qt::Key_Down) {
226 : return true;
227 : } else {
228 : return false;
229 : }
230 : }
231 :
232 0 : if (Event->type() == QEvent::FocusOut) {
233 0 : QWidget* popup = Box->findChild<QFrame*>();
234 0 : QWidget* popup1 = Box->lineEdit()->findChild<QFrame*>();
235 :
236 0 : if (popup != popup1 and not popup->isHidden()) {
237 : return true;
238 : }
239 :
240 0 : if (FirstItem != nullptr && FirstItem->listWidget() == ListWidget && ListWidget->itemWidget(FirstItem) != 0) {
241 0 : ListWidget->takeItem(ListWidget->row(FirstItem));
242 0 : ListWidget->setItemWidget(FirstItem, nullptr);
243 0 : delete FirstItem;
244 0 : SetFirstItem();
245 : } else {
246 0 : std::cout << "Do we ever get here? FirstItem is not null but other conditions not met!\n";
247 : }
248 0 : return false;
249 : }
250 0 : } else if (QLineEdit* le = dynamic_cast<QLineEdit*>(Target)) {
251 0 : if (Event->type() == QEvent::MouseButtonDblClick) {
252 0 : const QString& value = le->text();
253 :
254 : // This string checking is very very bad...
255 0 : if ((value.isEmpty() == false) && (value != c_input_placeholder) && (value != c_no_object_placeholder)) {
256 0 : CreateObjectEditor(le->text().toStdString());
257 0 : return false;
258 : }
259 0 : }
260 : }
261 :
262 : return false;
263 : }
264 :
265 : void
266 0 : relation::SetEditor()
267 : {
268 0 : ListWidget->clear();
269 :
270 0 : if (IsMultiValue) {
271 0 : ListWidget->addItems(this_data);
272 :
273 : // Enable drops only for multi-value
274 : // This allows to drop several objects in a relationship (e.g., several computers in a rack)
275 : // Not really needed for single-value relationship (the item can be selected from the list)
276 0 : if (!m_readonly) {
277 0 : ListWidget->setAcceptDrops(true);
278 0 : ListWidget->installEventFilter(this);
279 : }
280 : }
281 :
282 0 : SetFirstItem();
283 :
284 0 : ListWidget->setSelectionMode(QAbstractItemView::ExtendedSelection);
285 0 : ListWidget->setEditTriggers(QAbstractItemView::DoubleClicked);
286 0 : ListWidget->setDragDropMode(QAbstractItemView::InternalMove);
287 :
288 0 : CurrentDataList = this_data;
289 :
290 : /// Cleaning and Fetching Data
291 0 : ComboBox->clear();
292 :
293 0 : FetchData();
294 0 : }
295 :
296 : void
297 0 : relation::FetchData()
298 : {
299 0 : QStringList result;
300 0 : t_virtue const& Virtue = p_base_data_editor->get();
301 :
302 0 : std::vector<tref> const& related{ dbe::config::api::info::onclass::objects<true>(Virtue.p_type) };
303 :
304 0 : for (tref const& o : related) {
305 0 : result.append(QString::fromStdString(o.full_name()));
306 : }
307 :
308 0 : emit FetchDataDone(result);
309 0 : }
310 :
311 : bool
312 0 : relation::GetIsMultiValue() const
313 : {
314 0 : return IsMultiValue;
315 : }
316 :
317 : void
318 0 : relation::DataWasFetched(QStringList ListOfObjects)
319 : {
320 0 : ComboBox->clear();
321 0 : if (!m_readonly) {
322 0 : ComboBox->addItems(ListOfObjects);
323 : }
324 0 : emit signal_internal_value_change();
325 :
326 0 : if (this_initial_load) {
327 0 : emit LoadedInitials();
328 : }
329 0 : }
330 :
331 : void
332 0 : relation::SetController()
333 : {
334 0 : connect(SaveButton, SIGNAL(clicked()), this, SLOT(EndSignal()));
335 0 : connect(RemoveButton, SIGNAL(clicked()), this, SLOT(RemoveFromDataList()));
336 0 : connect(this, SIGNAL(signal_internal_value_change()), this, SLOT(UpdateActions()));
337 0 : connect(this, SIGNAL(FetchDataDone(QStringList)), this, SLOT(DataWasFetched(QStringList)));
338 : /// Connect an action to edit objects from the list view
339 0 : connect(ListWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(CustomContextMenuRequested(QPoint)));
340 0 : connect(ListWidget,
341 : SIGNAL(itemDoubleClicked(QListWidgetItem*)),
342 : this,
343 : SLOT(CreateObjectEditor(QListWidgetItem*)),
344 : Qt::UniqueConnection);
345 0 : connect(ListWidget->model(), SIGNAL(layoutChanged()), this, SLOT(DummyMovement()));
346 0 : connect(ListWidget, SIGNAL(itemPressed(QListWidgetItem*)), this, SLOT(EditItemEntered(QListWidgetItem*)));
347 0 : connect(&confaccessor::ref(), SIGNAL(object_created(QString, dref)), this, SLOT(FetchData()));
348 0 : connect(&confaccessor::ref(), SIGNAL(object_deleted(QString, dref)), this, SLOT(FetchData()));
349 0 : }
350 :
351 : void
352 0 : relation::SetFirstItem()
353 : {
354 0 : if (IsMultiValue) {
355 0 : if (m_readonly) {
356 0 : if (this_data.isEmpty()) {
357 0 : FirstItem = new QListWidgetItem(c_no_object_placeholder);
358 0 : ListWidget->addItem(FirstItem);
359 : } else {
360 0 : FirstItem = new QListWidgetItem(this_data.at(0));
361 : }
362 : } else {
363 0 : FirstItem = new QListWidgetItem(c_input_placeholder);
364 0 : FirstItem->setBackground(Qt::GlobalColor::lightGray);
365 0 : FirstItem->setForeground(QColor(0, 0, 0, 127));
366 0 : ListWidget->addItem(FirstItem);
367 : }
368 : } else {
369 0 : if (this_data.isEmpty()) {
370 0 : FirstItem = new QListWidgetItem(c_no_object_placeholder);
371 : } else {
372 0 : FirstItem = new QListWidgetItem(this_data.at(0));
373 : }
374 0 : ListWidget->addItem(FirstItem);
375 : }
376 :
377 0 : FirstItem->setSizeHint(FirstItem->sizeHint() + QSize(0, 25));
378 0 : }
379 :
380 : void
381 0 : relation::buildtooltip()
382 : {
383 0 : t_virtue const& Virtue = p_base_data_editor->get();
384 0 : setToolTip(QString("Relationship Name: %1 \n").arg(Virtue.p_name.c_str()) +
385 0 : QString(" Type: %1 \n").arg(Virtue.p_type.c_str()) +
386 0 : QString(" Cardinality: %1 \n")
387 0 : .arg(dunedaq::conffwk::relationship_t::card2str(Virtue.p_cardinality)) +
388 0 : QString(" Is Aggregation: %1 \n").arg(Virtue.p_is_aggregation) +
389 0 : QString(" Description: %1 \n").arg(Virtue.p_description.c_str()));
390 0 : }
391 : void
392 0 : relation::CreateObjectEditor(const std::string& objectID)
393 : {
394 0 : t_virtue const& virt = p_base_data_editor->get();
395 0 : tref const& obj = inner::dbcontroller::get({ objectID, virt.p_type });
396 :
397 0 : QString oname = QString::fromStdString(obj.full_name());
398 :
399 0 : for (QWidget* editor : QApplication::allWidgets()) {
400 0 : if (ObjectEditor* w = dynamic_cast<ObjectEditor*>(editor)) {
401 0 : if ((w->objectName()).compare(oname) == 0) {
402 0 : w->raise();
403 0 : w->setVisible(true);
404 0 : return;
405 : }
406 : }
407 0 : }
408 :
409 0 : (new ObjectEditor(obj))->show();
410 0 : }
411 :
412 : void
413 0 : relation::CreateObjectEditor(QListWidgetItem* Item)
414 : {
415 0 : if (Item == FirstItem) {
416 0 : EditItemEntered(FirstItem);
417 0 : return;
418 : }
419 :
420 0 : std::string const& ouid = Item->data(Qt::DisplayRole).toString().toStdString();
421 0 : CreateObjectEditor(ouid);
422 0 : }
423 :
424 : void
425 0 : relation::CustomContextMenuRequested(const QPoint& pos)
426 : {
427 0 : if (ContextMenu == nullptr) {
428 0 : ContextMenu = new QMenu(ListWidget);
429 :
430 0 : MoveTop = new QAction(tr("Move Top"), this);
431 0 : MoveTop->setShortcutContext(Qt::WidgetShortcut);
432 0 : connect(MoveTop, SIGNAL(triggered()), this, SLOT(MoveTopSlot()));
433 0 : ContextMenu->addAction(MoveTop);
434 :
435 0 : MoveBottom = new QAction(tr("Move Bottom"), this);
436 0 : MoveBottom->setShortcutContext(Qt::WidgetShortcut);
437 0 : connect(MoveBottom, SIGNAL(triggered()), this, SLOT(MoveBottomSlot()));
438 0 : ContextMenu->addAction(MoveBottom);
439 :
440 0 : MoveUp = new QAction(tr("Move Up"), this);
441 0 : MoveUp->setShortcutContext(Qt::WidgetShortcut);
442 0 : connect(MoveUp, SIGNAL(triggered()), this, SLOT(MoveUpSlot()));
443 0 : ContextMenu->addAction(MoveUp);
444 :
445 0 : MoveDown = new QAction(tr("Move Down"), this);
446 0 : MoveDown->setShortcutContext(Qt::WidgetShortcut);
447 0 : connect(MoveDown, SIGNAL(triggered()), this, SLOT(MoveDownSlot()));
448 0 : ContextMenu->addAction(MoveDown);
449 :
450 0 : ContextMenu->addSeparator();
451 :
452 0 : EditAction = new QAction(tr("Edit"), this);
453 0 : EditAction->setShortcutContext(Qt::WidgetShortcut);
454 0 : connect(EditAction, SIGNAL(triggered()), this, SLOT(EditSlot()));
455 0 : ContextMenu->addAction(EditAction);
456 :
457 0 : RemoveAction = new QAction(tr("Remove"), this);
458 0 : RemoveAction->setShortcutContext(Qt::WidgetShortcut);
459 0 : connect(RemoveAction, SIGNAL(triggered()), this, SLOT(RemoveSlot()));
460 0 : ContextMenu->addAction(RemoveAction);
461 : }
462 :
463 0 : if (!m_readonly && (CurrentItem = ListWidget->itemAt(pos))) {
464 0 : if (CurrentItem != FirstItem) {
465 0 : (ContextMenu->actions()).at(0)->setVisible(true);
466 0 : (ContextMenu->actions()).at(1)->setVisible(true);
467 0 : (ContextMenu->actions()).at(2)->setVisible(true);
468 0 : (ContextMenu->actions()).at(3)->setVisible(true);
469 0 : (ContextMenu->actions()).at(4)->setVisible(true);
470 0 : (ContextMenu->actions()).at(5)->setVisible(false);
471 0 : (ContextMenu->actions()).at(6)->setVisible(true);
472 :
473 0 : ContextMenu->exec(ListWidget->mapToGlobal(pos));
474 : }
475 :
476 0 : else if (CurrentItem == FirstItem and not IsMultiValue) {
477 0 : (ContextMenu->actions()).at(0)->setVisible(false);
478 0 : (ContextMenu->actions()).at(1)->setVisible(false);
479 0 : (ContextMenu->actions()).at(2)->setVisible(false);
480 0 : (ContextMenu->actions()).at(3)->setVisible(false);
481 0 : (ContextMenu->actions()).at(4)->setVisible(true);
482 0 : (ContextMenu->actions()).at(5)->setVisible(true);
483 0 : (ContextMenu->actions()).at(6)->setVisible(true);
484 :
485 0 : ContextMenu->exec(ListWidget->mapToGlobal(pos));
486 : }
487 : }
488 0 : }
489 :
490 : void
491 0 : relation::RemoveSlot()
492 : {
493 0 : RemoveFromDataList();
494 0 : }
495 :
496 : void
497 0 : relation::MoveTopSlot()
498 : {
499 0 : int ItemPosition = ListWidget->row(CurrentItem);
500 0 : QString Item = this_data.at(ItemPosition);
501 :
502 0 : this_data.removeAt(ItemPosition);
503 0 : this_data.push_front(Item);
504 :
505 0 : FirstItem = ListWidget->takeItem(this_data.size());
506 0 : ListWidget->clear();
507 0 : ListWidget->addItems(this_data);
508 0 : ListWidget->addItem(FirstItem);
509 :
510 0 : int index = this_data.indexOf(Item);
511 0 : ListWidget->scrollTo(ListWidget->model()->index(index, 0));
512 0 : ListWidget->setCurrentRow(index);
513 :
514 0 : emit signal_internal_value_change();
515 0 : }
516 :
517 : void
518 0 : relation::MoveBottomSlot()
519 : {
520 0 : int ItemPosition = ListWidget->row(CurrentItem);
521 0 : QString Item = this_data.at(ItemPosition);
522 :
523 0 : this_data.removeAt(ItemPosition);
524 0 : this_data.push_back(Item);
525 :
526 0 : FirstItem = ListWidget->takeItem(this_data.size());
527 0 : ListWidget->clear();
528 0 : ListWidget->addItems(this_data);
529 0 : ListWidget->addItem(FirstItem);
530 :
531 0 : int index = this_data.indexOf(Item);
532 0 : ListWidget->scrollTo(ListWidget->model()->index(index, 0));
533 0 : ListWidget->setCurrentRow(index);
534 :
535 0 : emit signal_internal_value_change();
536 0 : }
537 :
538 : void
539 0 : relation::MoveUpSlot()
540 : {
541 0 : int ItemPosition = ListWidget->row(CurrentItem);
542 0 : QString Item = this_data.at(ItemPosition);
543 :
544 0 : if (ItemPosition != 0) {
545 0 : this_data.swapItemsAt(ItemPosition, ItemPosition - 1);
546 :
547 0 : FirstItem = ListWidget->takeItem(this_data.size());
548 0 : ListWidget->clear();
549 0 : ListWidget->addItems(this_data);
550 0 : ListWidget->addItem(FirstItem);
551 :
552 0 : int index = this_data.indexOf(Item);
553 0 : ListWidget->scrollTo(ListWidget->model()->index(index, 0));
554 0 : ListWidget->setCurrentRow(index);
555 :
556 0 : emit signal_internal_value_change();
557 : }
558 0 : }
559 :
560 : void
561 0 : relation::MoveDownSlot()
562 : {
563 0 : int ItemPosition = ListWidget->row(CurrentItem);
564 0 : QString Item = this_data.at(ItemPosition);
565 :
566 0 : if (ItemPosition != (this_data.size() - 1)) {
567 0 : this_data.swapItemsAt(ItemPosition, ItemPosition + 1);
568 :
569 0 : FirstItem = ListWidget->takeItem(this_data.size());
570 0 : ListWidget->clear();
571 0 : ListWidget->addItems(this_data);
572 0 : ListWidget->addItem(FirstItem);
573 :
574 0 : int index = this_data.indexOf(Item);
575 0 : ListWidget->scrollTo(ListWidget->model()->index(index, 0));
576 0 : ListWidget->setCurrentRow(index);
577 :
578 0 : emit signal_internal_value_change();
579 : }
580 0 : }
581 :
582 : void
583 0 : relation::EditSlot()
584 : {
585 0 : if (QComboBox* ComboBox = dynamic_cast<QComboBox*>(ListWidget->itemWidget(FirstItem))) {
586 0 : ComboBox->lineEdit()->setFocus();
587 : }
588 :
589 0 : t_virtue const& virt = p_base_data_editor->get();
590 0 : tref const& obj = inner::dbcontroller::get({ FirstItem->text().toStdString(), virt.p_type }
591 :
592 0 : );
593 0 : QString const& editorname = QString::fromStdString(obj.full_name());
594 :
595 0 : for (QWidget* editor : QApplication::allWidgets()) {
596 0 : if (ObjectEditor* w = dynamic_cast<ObjectEditor*>(editor)) {
597 0 : if ((w->objectName()).compare(editorname) == 0) {
598 0 : w->raise();
599 0 : w->setVisible(true);
600 0 : return;
601 : }
602 : }
603 0 : }
604 :
605 0 : (new ObjectEditor(obj))->show();
606 0 : }
607 :
608 : void
609 0 : relation::DummyMovement()
610 : {
611 0 : if (this_is_owned) {
612 0 : emit signal_internal_value_change();
613 : }
614 0 : }
615 :
616 : void
617 0 : relation::EditItemEntered(QListWidgetItem* Item)
618 : {
619 0 : if (Item != FirstItem) {
620 0 : return;
621 : }
622 :
623 0 : QStringList ListOfObjects;
624 :
625 0 : for (int i = 0; i < ComboBox->count(); ++i) {
626 0 : ListOfObjects.append(ComboBox->itemText(i));
627 : }
628 :
629 0 : QComboBox* NewComboBox = new QComboBox(this);
630 :
631 0 : NewComboBox->setLineEdit(new QLineEdit());
632 :
633 0 : NewComboBox->addItems(ListOfObjects);
634 :
635 0 : QCompleter* Completer = new QCompleter(ListOfObjects);
636 0 : Completer->setCaseSensitivity(Qt::CaseInsensitive);
637 0 : Completer->setFilterMode(Qt::MatchContains);
638 :
639 0 : NewComboBox->lineEdit()->setCompleter(Completer);
640 :
641 0 : NewComboBox->setEditable(true);
642 :
643 0 : NewComboBox->setEditText(Item->text());
644 :
645 0 : if (ListOfObjects.size() > 0) {
646 0 : NewComboBox->lineEdit()->selectAll();
647 : }
648 :
649 : else {
650 0 : NewComboBox->setEnabled(false);
651 : }
652 :
653 0 : QVariant VariantFromList(ListOfObjects);
654 0 : ValidatorAcceptMatch* MyCustomValidator = new ValidatorAcceptMatch(VariantFromList);
655 0 : NewComboBox->setValidator(MyCustomValidator);
656 0 : NewComboBox->installEventFilter(this);
657 :
658 0 : connect(NewComboBox, SIGNAL(activated(const QString&)), this, SLOT(AddToDataList(const QString&)));
659 :
660 0 : NewComboBox->lineEdit()->installEventFilter(this);
661 :
662 0 : ListWidget->setItemWidget(FirstItem, NewComboBox);
663 0 : }
664 :
665 : void
666 0 : relation::EndSignal()
667 : {
668 0 : if (IsMultiValue and ListWidget->item(0)->text() == c_input_placeholder and not this_value_changed) {
669 : return;
670 : }
671 :
672 0 : if (not this_data.isEmpty()) {
673 0 : this_data.clear();
674 : }
675 :
676 0 : for (int i = 0; i != ListWidget->count(); ++i) {
677 0 : QListWidgetItem* Item = ListWidget->item(i);
678 0 : QString const& val = Item->text();
679 :
680 0 : if (val != c_input_placeholder and val != c_no_object_placeholder) {
681 0 : this_data.append(val);
682 : }
683 0 : }
684 :
685 0 : if (not this_is_owned) {
686 0 : p_base_data_editor->set_valid(true);
687 0 : emit signal_edit_end();
688 : } else {
689 0 : emit signal_value_change(); /// This signal is caught by Object editor
690 : }
691 : }
692 :
693 : void
694 0 : relation::AddToDataList(const QString& DataValue)
695 : {
696 0 : if (IsMultiValue) {
697 0 : this_data.append(DataValue);
698 : } else {
699 0 : this_data = QStringList(DataValue);
700 : }
701 :
702 0 : ListWidget->clear();
703 :
704 0 : if (IsMultiValue) {
705 0 : ListWidget->addItems(this_data);
706 : }
707 :
708 0 : int index = this_data.indexOf(DataValue);
709 0 : ListWidget->scrollTo(ListWidget->model()->index(index, 0));
710 0 : ListWidget->setCurrentRow(index);
711 :
712 0 : if (IsMultiValue) {
713 0 : FirstItem = new QListWidgetItem(c_input_placeholder);
714 : } else {
715 0 : FirstItem = new QListWidgetItem(DataValue.toStdString().c_str());
716 : }
717 :
718 0 : ListWidget->addItem(FirstItem);
719 :
720 0 : if (IsMultiValue) {
721 0 : FirstItem->setBackground(Qt::GlobalColor::lightGray);
722 0 : FirstItem->setForeground(QColor(0, 0, 0, 127));
723 : }
724 :
725 0 : FirstItem->setSizeHint(FirstItem->sizeHint() + QSize(0, 25));
726 :
727 0 : if (this_is_owned) {
728 0 : emit signal_internal_value_change();
729 : }
730 0 : }
731 :
732 : void
733 0 : relation::RemoveFromDataList()
734 : {
735 0 : QList<QListWidgetItem*> items;
736 :
737 0 : if (IsMultiValue) {
738 0 : items = ListWidget->selectedItems();
739 : }
740 :
741 : else {
742 0 : items.append(FirstItem);
743 : }
744 :
745 0 : if (items.size() > 0) {
746 :
747 0 : for (QListWidgetItem* item : items) {
748 0 : QString text = item->text();
749 :
750 0 : if (text != c_input_placeholder) {
751 0 : if (IsMultiValue) {
752 0 : if (QListWidgetItem* toremove = ListWidget->takeItem(ListWidget->row(item))) {
753 0 : delete toremove;
754 : }
755 : } else {
756 :
757 0 : if (QComboBox* editbox = dynamic_cast<QComboBox*>(ListWidget->itemWidget(FirstItem))) {
758 0 : editbox->lineEdit()->clear();
759 0 : editbox->lineEdit()->clearFocus();
760 0 : FirstItem->setText(c_no_object_placeholder);
761 : }
762 : }
763 :
764 0 : this_data.removeOne(text);
765 : }
766 0 : }
767 :
768 0 : emit signal_internal_value_change();
769 : }
770 0 : }
771 :
772 : void
773 0 : relation::UpdateActions()
774 : {
775 0 : QStringList values;
776 :
777 0 : for (int i = 0; i < ListWidget->count(); ++i) {
778 0 : QString const& value = ListWidget->item(i)->text();
779 :
780 0 : if (value != c_no_object_placeholder and value != c_input_placeholder) {
781 0 : values.append(value);
782 : }
783 0 : }
784 :
785 0 : if (p_base_data_editor->must_not_be_null()) {
786 0 : if (values.size() > 0) {
787 0 : p_base_data_editor->set_valid(true);
788 0 : ListWidget->setPalette(QApplication::palette(this));
789 : } else {
790 0 : p_base_data_editor->set_valid(false);
791 0 : ListWidget->setPalette(StyleUtility::WarningStatusBarPallete);
792 : }
793 : } else {
794 0 : p_base_data_editor->set_valid(true);
795 : }
796 :
797 0 : if (values != CurrentDataList) {
798 0 : this_value_changed = true;
799 : }
800 :
801 0 : if (this_is_owned) {
802 0 : EndSignal();
803 : }
804 0 : }
805 :
806 : void
807 0 : relation::closeEvent(QCloseEvent* Event)
808 : {
809 0 : Q_UNUSED(Event)
810 0 : emit signal_force_close();
811 0 : }
812 :
813 : //------------------------------------------------------------------------------------------------
814 :
815 : //------------------------------------------------------------------------------------------------
816 0 : stringattr::stringattr(t_virtue const& attr, QWidget* parent, bool owned, bool readonly)
817 0 : : base(std::make_shared<t_build_block_editor>(attr), parent, owned)
818 0 : , m_base_data_editor(std::static_pointer_cast<t_build_block_editor>(p_data_editor))
819 0 : , m_readonly(readonly)
820 0 : , DefaultValue("")
821 0 : , PopUpButton(nullptr)
822 0 : , Dialog(nullptr)
823 0 : , OkButtonDialog(nullptr)
824 0 : , TextEditDialog(nullptr)
825 : {
826 0 : setupUi(this);
827 0 : t_virtue const& virtue = m_base_data_editor->get();
828 :
829 0 : if (m_readonly) {
830 0 : StringLineEdit->setReadOnly(true);
831 : } else {
832 0 : StringLineEdit->installEventFilter(this);
833 : }
834 0 : StringLineEdit->setTabChangesFocus(true);
835 :
836 0 : setWindowTitle(QString("Edit Attr : %1").arg(virtue.p_name.c_str()));
837 0 : AttributeNameLabel->setText(QString(virtue.p_name.c_str()) + " : ");
838 : /// LAYOUT CHANGE
839 0 : AttributeNameLabel->setHidden(true);
840 :
841 0 : UpdateActions();
842 :
843 0 : if (m_base_data_editor->must_not_be_null()) {
844 0 : m_base_data_editor->set_valid(true);
845 0 : StringLineEdit->setPalette(StyleUtility::WarningStatusBarPallete);
846 0 : OkButton->setDisabled(true);
847 0 : SetNullCheck(true);
848 : } else {
849 0 : SetNullCheck(false);
850 : }
851 :
852 0 : if (virtue.p_is_multi_value) {
853 0 : StringLineEdit->setPalette(QApplication::palette(this));
854 : }
855 :
856 0 : OkButton->setHidden(true);
857 :
858 0 : if (this_is_owned) {
859 0 : connect(StringLineEdit, SIGNAL(StringValidated()), this, SLOT(AddToDataList()), Qt::UniqueConnection);
860 0 : OkButton->setHidden(true);
861 : }
862 :
863 0 : SetController();
864 :
865 0 : buildtooltip();
866 0 : UpdateActions();
867 :
868 0 : AttributeNameLabel->setFocus();
869 0 : }
870 :
871 0 : stringattr::~stringattr()
872 : {
873 0 : delete Dialog;
874 0 : delete PopUpButton;
875 0 : }
876 :
877 : void
878 0 : stringattr::SetEditor()
879 : {
880 0 : if (this_data.isEmpty()) {
881 : return;
882 : }
883 :
884 0 : StringLineEdit->setText(this_data.value(0));
885 :
886 0 : slot_set_initial_loaded();
887 : }
888 :
889 : QTextEdit*
890 0 : stringattr::GetLineEdit() const
891 : {
892 0 : return StringLineEdit;
893 : }
894 :
895 : void
896 0 : stringattr::SetNullCheck(bool Check)
897 : {
898 0 : StringLineEdit->SetNullCheck(Check);
899 0 : }
900 :
901 : void
902 0 : stringattr::SetMultiCheck(bool Multi)
903 : {
904 0 : StringLineEdit->SetMultiCheck(Multi);
905 0 : }
906 :
907 : void
908 0 : stringattr::SetCheckDefaults(bool Default)
909 : {
910 0 : StringLineEdit->SetCheckDefault(Default);
911 0 : }
912 :
913 : void
914 0 : stringattr::SetFocusOnLine()
915 : {
916 0 : StringLineEdit->selectAll();
917 0 : }
918 :
919 : bool
920 0 : stringattr::eventFilter(QObject* target, QEvent* evt)
921 : {
922 0 : if (target == StringLineEdit) {
923 0 : if (evt->type() == QEvent::FocusIn) {
924 0 : ShowPopupButton();
925 0 : } else if (evt->type() == QEvent::KeyPress) {
926 0 : QKeyEvent* kevt = static_cast<QKeyEvent*>(evt);
927 0 : switch (kevt->key()) {
928 0 : case Qt::Key_Enter:
929 0 : case Qt::Key_Return:
930 :
931 0 : if (kevt->modifiers() == Qt::AltModifier) {
932 0 : kevt->setModifiers(Qt::NoModifier);
933 0 : return false;
934 : } else {
935 0 : StringLineEdit->parentWidget()->setFocus(Qt::FocusReason::TabFocusReason);
936 0 : emit signal_data_input_complete();
937 0 : return true;
938 : }
939 :
940 : break;
941 : default:
942 : break;
943 : }
944 : }
945 : }
946 : return false;
947 : }
948 :
949 : void
950 0 : stringattr::ClearText()
951 : {
952 0 : GetLineEdit()->clear();
953 0 : }
954 :
955 : void
956 0 : stringattr::buildtooltip()
957 : {
958 0 : t_virtue const& Virtue = m_base_data_editor->get();
959 :
960 0 : setToolTip(
961 0 : QString("Attribute Name: %1 \n").arg(Virtue.p_name.c_str()) +
962 0 : QString(" Type: %1 \n").arg(dunedaq::conffwk::attribute_t::type2str(Virtue.p_type)) +
963 0 : QString(" Range: %1 \n").arg(Virtue.p_range.c_str()) +
964 0 : QString(" Format: %1 \n").arg(dunedaq::conffwk::attribute_t::format2str(Virtue.p_int_format)) +
965 0 : QString(" Not Null: %1 \n").arg(Virtue.p_is_not_null) +
966 0 : QString(" Is Multi Value: %1 \n").arg(Virtue.p_is_multi_value) +
967 0 : QString(" Default Value: %1 \n").arg(Virtue.p_default_value.c_str()) +
968 0 : QString(" Description: %1 \n").arg(Virtue.p_description.c_str()));
969 0 : }
970 :
971 : void
972 0 : stringattr::closeEvent(QCloseEvent* Event)
973 : {
974 0 : Q_UNUSED(Event)
975 0 : emit signal_force_close();
976 0 : }
977 :
978 : void
979 0 : stringattr::SetController()
980 : {
981 0 : if (!m_readonly) {
982 0 : connect(StringLineEdit, SIGNAL(textChanged()), this, SLOT(UpdateActions()), Qt::UniqueConnection);
983 0 : connect(this, SIGNAL(signal_data_input_complete()), this, SLOT(AddToDataList()));
984 0 : connect(OkButton, SIGNAL(clicked()), this, SLOT(AddToDataList()), Qt::UniqueConnection);
985 : }
986 0 : }
987 :
988 : void
989 0 : stringattr::setdefaults(const QString& ValueDefault)
990 : {
991 0 : this_defaults = ValueDefault;
992 0 : StringLineEdit->SetDefaultValue(ValueDefault);
993 0 : }
994 :
995 : void
996 0 : stringattr::ShowPopupButton()
997 : {
998 0 : if (PopUpButton == nullptr) {
999 0 : PopUpButton = new QPushButton("...");
1000 0 : PopUpButton->setMaximumWidth(PopUpButton->fontMetrics().boundingRect("...").width() + 15);
1001 0 : connect(PopUpButton, SIGNAL(clicked()), this, SLOT(ShowDialog()), Qt::UniqueConnection);
1002 0 : horizontalLayout->addWidget(PopUpButton);
1003 : }
1004 :
1005 0 : PopUpButton->show();
1006 0 : }
1007 :
1008 : void
1009 0 : stringattr::HidePopupButton()
1010 : {
1011 0 : if (PopUpButton != nullptr) {
1012 0 : PopUpButton->hide();
1013 : }
1014 0 : }
1015 :
1016 : void
1017 0 : stringattr::UpdateActions()
1018 : {
1019 0 : t_virtue const& Virtue = m_base_data_editor->get();
1020 :
1021 0 : if (Virtue.p_is_not_null && (this_data.size() == 0)) {
1022 0 : OkButton->setEnabled(true);
1023 0 : m_base_data_editor->set_valid(false);
1024 : }
1025 :
1026 : else {
1027 0 : OkButton->setEnabled(true);
1028 0 : m_base_data_editor->set_valid(true);
1029 : }
1030 0 : }
1031 :
1032 : void
1033 0 : stringattr::AddToDataList()
1034 : {
1035 0 : QString NewValue = StringLineEdit->toPlainText();
1036 :
1037 0 : if (!this_data.contains(NewValue)) {
1038 0 : StringLineEdit->setToolTip(QString("The set value is : %1").arg(NewValue));
1039 0 : this_data.clear();
1040 0 : this_data.append(NewValue);
1041 :
1042 0 : UpdateActions();
1043 0 : this_value_changed = true;
1044 :
1045 0 : if (!this_is_owned) {
1046 0 : emit signal_value_change();
1047 0 : emit signal_edit_end();
1048 : } else {
1049 0 : emit signal_value_change();
1050 : }
1051 : }
1052 0 : }
1053 :
1054 : void
1055 0 : stringattr::ShowDialog()
1056 : {
1057 :
1058 0 : if (Dialog == nullptr) {
1059 0 : QVBoxLayout* Layout = new QVBoxLayout();
1060 0 : Dialog = new QDialog();
1061 0 : t_virtue const& Virtue = m_base_data_editor->get();
1062 0 : Dialog->setWindowTitle(QString("Edit Attr : %1").arg(Virtue.p_name.c_str()));
1063 0 : TextEditDialog = new QPlainTextEdit(Dialog);
1064 0 : OkButtonDialog = new QPushButton("OK", Dialog);
1065 0 : Layout->addWidget(TextEditDialog);
1066 0 : Layout->addWidget(OkButtonDialog);
1067 0 : Dialog->setLayout(Layout);
1068 0 : Dialog->setModal(true);
1069 :
1070 0 : connect(TextEditDialog, SIGNAL(textChanged()), this, SLOT(ToogleTextEditOkButton()), Qt::UniqueConnection);
1071 0 : connect(OkButtonDialog, SIGNAL(clicked()), this, SLOT(UpdateFromTextEdit()), Qt::UniqueConnection);
1072 : }
1073 :
1074 0 : TextEditDialog->clear();
1075 0 : TextEditDialog->insertPlainText(StringLineEdit->toPlainText());
1076 0 : Dialog->show();
1077 0 : }
1078 :
1079 : void
1080 0 : stringattr::UpdateFromTextEdit()
1081 : {
1082 0 : StringLineEdit->clear();
1083 0 : StringLineEdit->setText(TextEditDialog->toPlainText());
1084 0 : AddToDataList();
1085 0 : Dialog->close();
1086 0 : }
1087 :
1088 : void
1089 0 : stringattr::ToogleTextEditOkButton()
1090 : {
1091 0 : t_virtue const& Virtue = m_base_data_editor->get();
1092 :
1093 0 : if (TextEditDialog->toPlainText().isEmpty() && Virtue.p_is_not_null)
1094 0 : OkButtonDialog->setEnabled(false);
1095 : else {
1096 0 : OkButtonDialog->setEnabled(true);
1097 : }
1098 0 : }
1099 :
1100 : //------------------------------------------------------------------------------------------------
1101 :
1102 : //------------------------------------------------------------------------------------------------
1103 0 : numericattr::numericattr(t_virtue const& attr, QWidget* parent, bool owned, bool readonly)
1104 0 : : base(std::make_shared<t_build_block_editor>(attr), parent, owned)
1105 0 : , this_base_data_editor(std::static_pointer_cast<t_build_block_editor>(p_data_editor))
1106 0 : , m_readonly(readonly)
1107 0 : , this_native_base(-1)
1108 : {
1109 0 : setupUi(this);
1110 0 : t_virtue const& Virtue = this_base_data_editor->get();
1111 :
1112 0 : setWindowTitle(QString("Edit Attribute: %1").arg(Virtue.p_name.c_str()));
1113 0 : if (m_readonly) {
1114 0 : LineEdit->setReadOnly(true);
1115 : } else {
1116 0 : LineEdit->SetPopupMenu();
1117 : }
1118 0 : if (Virtue.p_is_not_null) {
1119 0 : this_base_data_editor->set_valid(false);
1120 0 : LineEdit->setPalette(StyleUtility::WarningStatusBarPallete);
1121 : } else {
1122 0 : LineEdit->SetNullCheck(false);
1123 : }
1124 :
1125 0 : if (!(Virtue.p_type == dunedaq::conffwk::float_type || Virtue.p_type == dunedaq::conffwk::double_type)) {
1126 0 : if (Virtue.p_int_format == dunedaq::conffwk::oct_int_format) {
1127 0 : FormatBox->setCurrentIndex(2);
1128 0 : this_base = 8;
1129 0 : this_native_base = 8;
1130 0 : } else if (Virtue.p_int_format == dunedaq::conffwk::dec_int_format) {
1131 0 : FormatBox->setCurrentIndex(0);
1132 0 : this_base = 10;
1133 0 : this_native_base = 10;
1134 0 : } else if (Virtue.p_int_format == dunedaq::conffwk::hex_int_format) {
1135 0 : FormatBox->setCurrentIndex(1);
1136 0 : this_base = 16;
1137 0 : this_native_base = 16;
1138 : }
1139 :
1140 0 : FormatBox->hide();
1141 : } else {
1142 0 : FormatBox->hide();
1143 : }
1144 :
1145 0 : SetController();
1146 :
1147 0 : AttributeName->setText(QString(Virtue.p_name.c_str()) + " : ");
1148 0 : AttributeName->setHidden(true);
1149 0 : buildtooltip();
1150 :
1151 0 : QString Dummy("Dummy");
1152 0 : UpdateActions(Dummy);
1153 0 : }
1154 :
1155 : void
1156 0 : numericattr::setdefaults(const QString& ValueDefault)
1157 : {
1158 0 : this_defaults = ValueDefault;
1159 0 : LineEdit->SetDefaultValue(this_defaults);
1160 0 : }
1161 :
1162 : QLineEdit*
1163 0 : numericattr::GetLineEdit() const
1164 : {
1165 0 : return LineEdit;
1166 : }
1167 :
1168 : void
1169 0 : numericattr::SetEditor()
1170 : {
1171 0 : if (this_data.isEmpty()) {
1172 : return;
1173 : }
1174 :
1175 0 : LineEdit->clear();
1176 :
1177 : /// change here
1178 0 : if (this_base == 16) {
1179 0 : if (not this_data.value(0).startsWith("0x")) {
1180 0 : LineEdit->setText("0x" + this_data.value(0));
1181 : } else {
1182 0 : LineEdit->setText(this_data.value(0));
1183 : }
1184 0 : } else if (this_base == 8) {
1185 0 : if (not this_data.value(0).startsWith("0") and this_data.value(0) != 0) {
1186 0 : LineEdit->setText("0" + this_data.value(0));
1187 : } else {
1188 0 : LineEdit->setText(this_data.value(0));
1189 : }
1190 : } else {
1191 0 : LineEdit->setText(this_data.value(0));
1192 : }
1193 : }
1194 :
1195 : void
1196 0 : numericattr::buildtooltip()
1197 : {
1198 0 : t_virtue const& Virtue = this_base_data_editor->get();
1199 :
1200 0 : setToolTip(
1201 0 : QString("Attribute Name: %1 \n").arg(Virtue.p_name.c_str()) +
1202 0 : QString(" Type: %1 \n").arg(dunedaq::conffwk::attribute_t::type2str(Virtue.p_type)) +
1203 0 : QString(" Range: %1 \n").arg(Virtue.p_range.c_str()) +
1204 0 : QString(" Format: %1 \n").arg(dunedaq::conffwk::attribute_t::format2str(Virtue.p_int_format)) +
1205 0 : QString(" Not Null: %1 \n").arg(Virtue.p_is_not_null) +
1206 0 : QString(" Is Multi Value: %1 \n").arg(Virtue.p_is_multi_value) +
1207 0 : QString(" Default Value: %1 \n").arg(Virtue.p_default_value.c_str()) +
1208 0 : QString(" Description: %1 \n").arg(Virtue.p_description.c_str()));
1209 0 : }
1210 :
1211 : void
1212 0 : numericattr::closeEvent(QCloseEvent* Event)
1213 : {
1214 0 : Q_UNUSED(Event)
1215 0 : emit signal_force_close();
1216 0 : }
1217 :
1218 : void
1219 0 : numericattr::SetController()
1220 : {
1221 0 : connect(LineEdit, SIGNAL(DecChange()), this, SLOT(ChangeFormatDec()));
1222 0 : connect(LineEdit, SIGNAL(OctChange()), this, SLOT(ChangeFormatOct()));
1223 0 : connect(LineEdit, SIGNAL(HexChange()), this, SLOT(ChangeFormatHex()));
1224 :
1225 0 : connect(FormatBox, SIGNAL(currentIndexChanged(int)), this, SLOT(ChangeFormat(int)), Qt::UniqueConnection);
1226 :
1227 0 : connect(LineEdit, SIGNAL(editingFinished()), this, SLOT(AddToList()), Qt::UniqueConnection);
1228 0 : connect(LineEdit, SIGNAL(textChanged(QString)), this, SLOT(UpdateActions(QString)), Qt::UniqueConnection);
1229 0 : connect(LineEdit, SIGNAL(returnPressed()), this, SLOT(checkIfDuplicated()), Qt::UniqueConnection);
1230 0 : }
1231 :
1232 : void
1233 0 : numericattr::ShowWarning(QString Format, QString Range)
1234 : {
1235 0 : LineEdit->setPalette(StyleUtility::AlertStatusBarPallete);
1236 :
1237 0 : t_virtue const& Virtue = this_base_data_editor->get();
1238 :
1239 0 : QString Message = QString("The value for attribute %1 is in the wrong format").arg(Virtue.p_name.c_str());
1240 :
1241 0 : if (Range != "") {
1242 0 : QString RangeMex = QString(" - The value should be in the range : %1").arg(Range);
1243 0 : Message.append("\n\n" + RangeMex);
1244 0 : }
1245 :
1246 0 : if (Format != "") {
1247 0 : Message.append(QString("\n\n - The value should be formatted as a %1.").arg(Format));
1248 : }
1249 :
1250 0 : QMessageBox::warning(this, tr("Wrong value"), Message);
1251 0 : return;
1252 0 : }
1253 :
1254 : bool
1255 0 : numericattr::ValidateIntegerValue(QString const& text)
1256 : {
1257 0 : auto checkInteger = [this, text]() {
1258 0 : t_virtue const& input = this_base_data_editor->get();
1259 :
1260 0 : bool convert_to_defined_base;
1261 :
1262 0 : qlonglong NewLongLong{ 0 };
1263 0 : qulonglong NewULongLong{ 0 };
1264 :
1265 0 : auto check_convert = [this, &convert_to_defined_base]() {
1266 : // If input cannot be converted to any base then show a warning and invalidate
1267 :
1268 0 : if (not convert_to_defined_base) {
1269 0 : if (this_native_base == 10) {
1270 0 : ShowWarning("DECIMAL");
1271 0 : } else if (this_native_base == 16) {
1272 0 : ShowWarning("HEX-DECIMAL");
1273 0 : } else if (this_native_base == 8) {
1274 0 : ShowWarning("OCT-DECIMAL");
1275 : }
1276 :
1277 0 : return false;
1278 : }
1279 :
1280 : return true;
1281 0 : };
1282 :
1283 0 : if (input.p_type == dunedaq::conffwk::u8_type or input.p_type == dunedaq::conffwk::u16_type or
1284 : input.p_type == dunedaq::conffwk::u32_type or input.p_type == dunedaq::conffwk::u64_type) {
1285 0 : NewULongLong = text.toULongLong(&convert_to_defined_base, this_base);
1286 :
1287 0 : if (not check_convert()) {
1288 : return false;
1289 : }
1290 :
1291 0 : qulonglong min_u;
1292 0 : qulonglong max_u;
1293 :
1294 0 : if (input.p_type == dunedaq::conffwk::u8_type) {
1295 : min_u = 0;
1296 : max_u = UCHAR_MAX;
1297 0 : } else if (input.p_type == dunedaq::conffwk::u16_type) {
1298 : min_u = 0;
1299 : max_u = USHRT_MAX;
1300 : } else if (input.p_type == dunedaq::conffwk::u32_type) {
1301 : min_u = 0;
1302 : max_u = ULONG_MAX;
1303 : } else if (input.p_type == dunedaq::conffwk::u64_type) {
1304 : min_u = 0;
1305 : max_u = ULONG_LONG_MAX;
1306 : } else {
1307 : return true;
1308 : }
1309 :
1310 0 : if (min_u <= NewULongLong and NewULongLong <= max_u) {
1311 : return true;
1312 : }
1313 :
1314 0 : ShowWarning("", QString("[%1 - %2]").arg(min_u).arg(max_u));
1315 0 : } else {
1316 0 : NewLongLong = text.toLongLong(&convert_to_defined_base, this_base);
1317 :
1318 0 : if (not check_convert()) {
1319 : return false;
1320 : }
1321 :
1322 0 : qlonglong min_s;
1323 0 : qlonglong max_s;
1324 :
1325 0 : if (input.p_type == dunedaq::conffwk::s8_type) {
1326 : min_s = SCHAR_MIN;
1327 : max_s = SCHAR_MAX;
1328 : } else if (input.p_type == dunedaq::conffwk::s16_type) {
1329 : min_s = SHRT_MIN;
1330 : max_s = SHRT_MAX;
1331 : } else if (input.p_type == dunedaq::conffwk::s32_type) {
1332 : min_s = LONG_MIN;
1333 : max_s = LONG_MAX;
1334 : } else if (input.p_type == dunedaq::conffwk::s64_type) {
1335 : min_s = -(LONG_LONG_MAX)-1;
1336 : max_s = LONG_LONG_MAX;
1337 : } else {
1338 : return true;
1339 : }
1340 :
1341 0 : if (min_s <= NewLongLong and NewLongLong <= max_s) {
1342 : return true;
1343 : }
1344 :
1345 0 : ShowWarning("", QString("[%1 - %2]").arg(min_s).arg(max_s));
1346 : }
1347 :
1348 : return false;
1349 0 : };
1350 :
1351 0 : return (checkInteger() && checkRange(text));
1352 0 : }
1353 :
1354 : bool
1355 0 : numericattr::checkRange(QString const& Value)
1356 : {
1357 0 : t_virtue const& Virtue = this_base_data_editor->get();
1358 :
1359 0 : QString Range = QString::fromStdString(Virtue.p_range);
1360 :
1361 0 : if (Range.isEmpty()) {
1362 : return true;
1363 : }
1364 :
1365 0 : QStringList ValueList = Range.split(",");
1366 :
1367 0 : QList<QPair<QString, QString>> RangeList;
1368 :
1369 0 : for (QString& RangeValue : ValueList) {
1370 0 : if (RangeValue.contains("..")) {
1371 0 : QStringList Ranges = RangeValue.split("..");
1372 0 : RangeList.append(QPair<QString, QString>(Ranges.at(0), Ranges.at(1)));
1373 0 : ValueList.removeOne(RangeValue);
1374 0 : }
1375 : }
1376 :
1377 0 : if (ValueList.contains(Value)) {
1378 : return true;
1379 : }
1380 :
1381 0 : for (QPair<QString, QString>& ValuePair : RangeList) {
1382 0 : if (ValuePair.first == "*") {
1383 0 : if (Value.toDouble() <= ValuePair.second.toDouble()) {
1384 0 : return true;
1385 : }
1386 :
1387 0 : ShowWarning("", Range);
1388 :
1389 0 : return false;
1390 : }
1391 :
1392 0 : else if (ValuePair.second == "*") {
1393 0 : if (Value.toDouble() >= ValuePair.first.toDouble()) {
1394 : return true;
1395 : }
1396 :
1397 0 : ShowWarning("", Range);
1398 :
1399 0 : return false;
1400 : }
1401 :
1402 : else {
1403 0 : if ((Value.toDouble() >= ValuePair.first.toDouble()) && (Value.toDouble() <= ValuePair.second.toDouble())) {
1404 : return true;
1405 : }
1406 :
1407 0 : ShowWarning("", Range);
1408 :
1409 0 : return false;
1410 : }
1411 : }
1412 :
1413 0 : ShowWarning("", Range);
1414 :
1415 0 : return false;
1416 0 : }
1417 :
1418 : bool
1419 0 : numericattr::ValidateFloatValue(QString const& Value)
1420 : {
1421 0 : bool validValue = true;
1422 :
1423 0 : t_virtue const& Virtue = this_base_data_editor->get();
1424 :
1425 0 : if (Virtue.p_type == dunedaq::conffwk::float_type) {
1426 0 : bool ok;
1427 0 : Value.toFloat(&ok);
1428 :
1429 0 : if (ok == false) {
1430 0 : ShowWarning("FLOAT");
1431 0 : validValue = false;
1432 : }
1433 : } else {
1434 0 : bool ok;
1435 0 : Value.toDouble(&ok);
1436 :
1437 0 : if (ok == false) {
1438 0 : ShowWarning("DOUBLE");
1439 0 : validValue = false;
1440 : }
1441 : }
1442 :
1443 0 : return (validValue && checkRange(Value));
1444 : }
1445 :
1446 : void
1447 0 : numericattr::checkIfDuplicated()
1448 : {
1449 : // Emit a special signal when the Enter/Return key is pressed
1450 : // and the data have not been changed
1451 : // That is useful, for instance, for the multi-attribute
1452 : // widget in order to add multiple times the same attribute
1453 : // (you do not want to add the same value multiple times just
1454 : // when the focus is lost)
1455 0 : if (this_data.contains(LineEdit->text())) {
1456 0 : emit signal_value_duplicated();
1457 : }
1458 0 : }
1459 :
1460 : void
1461 0 : numericattr::AddToList()
1462 : {
1463 : // No change in data, do nothing
1464 : // It avoids some unwanted loops when focus is acquired/lost
1465 0 : if (this_data.contains(LineEdit->text())) {
1466 0 : return;
1467 : }
1468 :
1469 0 : auto convert_to_proper_base = [this](const QString& value) -> QString {
1470 0 : if ((value.isEmpty() == false) && (this_native_base != -1) && (this_native_base != this_base)) {
1471 0 : QString cnvrtd;
1472 :
1473 0 : t_virtue const& virtue = this_base_data_editor->get();
1474 0 : bool Unsigned = (virtue.p_type == dunedaq::conffwk::u8_type || virtue.p_type == dunedaq::conffwk::u16_type ||
1475 : virtue.p_type == dunedaq::conffwk::u32_type || virtue.p_type == dunedaq::conffwk::u64_type);
1476 :
1477 0 : if (Unsigned == true) {
1478 0 : cnvrtd.setNum(LineEdit->text().toULongLong(0, this_base), this_native_base);
1479 : } else {
1480 0 : cnvrtd.setNum(LineEdit->text().toLongLong(0, this_base), this_native_base);
1481 : }
1482 :
1483 : // Be careful to set the contextaul menu properly
1484 0 : if (this_native_base == 8) {
1485 0 : if (cnvrtd.startsWith("0") == false) {
1486 0 : cnvrtd.insert(0, "0");
1487 : }
1488 0 : LineEdit->EmitOctSlot();
1489 0 : } else if (this_native_base == 10) {
1490 0 : LineEdit->EmitDecSlot();
1491 0 : } else if (this_native_base == 16) {
1492 0 : if (cnvrtd.startsWith("0x", Qt::CaseInsensitive) == false) {
1493 0 : cnvrtd.insert(0, "0x");
1494 : }
1495 0 : LineEdit->EmitHexSlot();
1496 : }
1497 :
1498 : // The current and native bases are now the same
1499 0 : this_base = this_native_base;
1500 :
1501 0 : return cnvrtd;
1502 0 : }
1503 :
1504 0 : return value;
1505 0 : };
1506 :
1507 0 : LineEdit->blockSignals(true);
1508 :
1509 0 : BOOST_SCOPE_EXIT(this_)
1510 : {
1511 0 : this_->LineEdit->blockSignals(false);
1512 0 : }
1513 0 : BOOST_SCOPE_EXIT_END
1514 :
1515 0 : bool isValid = true;
1516 :
1517 0 : QString input = LineEdit->text();
1518 :
1519 0 : t_virtue const& virtue = this_base_data_editor->get();
1520 0 : if ((virtue.p_type == dunedaq::conffwk::float_type or virtue.p_type == dunedaq::conffwk::double_type)) {
1521 0 : if (not ValidateFloatValue(input)) {
1522 0 : isValid = false;
1523 : }
1524 0 : } else if (not ValidateIntegerValue(input)) {
1525 0 : isValid = false;
1526 : }
1527 :
1528 : // ShowWarning("FLOAT", QString::fromStdString(virtue.p_name));
1529 :
1530 0 : this_data.clear();
1531 :
1532 : // We better save data in the proper format, in order to avoid issues
1533 : // with conversions (and having data saved in a bad format)
1534 0 : this_data.append(convert_to_proper_base(input));
1535 :
1536 0 : this_value_changed = true;
1537 :
1538 0 : if (isValid == true) {
1539 0 : QString Dummy("Dummy");
1540 0 : UpdateActions(Dummy);
1541 0 : } else {
1542 0 : this_base_data_editor->set_valid(false);
1543 : }
1544 :
1545 0 : if (not this_is_owned) {
1546 : // Not owned: multiattr (connected to signal_value_change) and
1547 : // CustomDelegate (connected to signal_edit_end and signal_force_close)
1548 0 : if (isValid == true) {
1549 : // Do not emit the signal in this case
1550 : // The table will try t write data and get back an exception
1551 0 : emit signal_edit_end();
1552 : }
1553 :
1554 0 : emit signal_value_change();
1555 : } else {
1556 : // Owned: ObjectEditor (connected to signal_value_change)
1557 0 : emit signal_value_change();
1558 : }
1559 0 : }
1560 :
1561 : void
1562 0 : numericattr::ChangeFormat(int i)
1563 : {
1564 0 : QString CurrentString = LineEdit->text();
1565 :
1566 0 : if (CurrentString.isEmpty()) {
1567 : // if(DecButton->isChecked())
1568 :
1569 0 : if (i == 0) {
1570 0 : this_base = 10;
1571 : }
1572 :
1573 : // else if(OctButton->isChecked())
1574 0 : else if (i == 2) {
1575 0 : this_base = 8;
1576 : }
1577 :
1578 : // else if(HexButton->isChecked())
1579 0 : else if (i == 1) {
1580 0 : this_base = 16;
1581 : }
1582 :
1583 0 : return;
1584 : }
1585 :
1586 0 : QString ConvertedString;
1587 0 : t_virtue const& Virtue = this_base_data_editor->get();
1588 :
1589 0 : bool Unsigned = (Virtue.p_type == dunedaq::conffwk::u8_type || Virtue.p_type == dunedaq::conffwk::u16_type ||
1590 : Virtue.p_type == dunedaq::conffwk::u32_type || Virtue.p_type == dunedaq::conffwk::u64_type);
1591 0 : bool OkConversion = false;
1592 :
1593 : // if(DecButton->isChecked())
1594 :
1595 0 : if (i == 0) {
1596 0 : if (Unsigned) {
1597 0 : ConvertedString.setNum(CurrentString.toULongLong(&OkConversion, 0), 10);
1598 : } else {
1599 0 : ConvertedString.setNum(CurrentString.toLongLong(&OkConversion, 0), 10);
1600 : }
1601 :
1602 0 : this_base = 10;
1603 : }
1604 :
1605 : // else if(OctButton->isChecked())
1606 0 : else if (i == 2) {
1607 0 : if (Unsigned) {
1608 0 : ConvertedString.setNum(CurrentString.toULongLong(&OkConversion, 0), 8);
1609 : } else {
1610 0 : ConvertedString.setNum(CurrentString.toLongLong(&OkConversion, 0), 8);
1611 : }
1612 :
1613 0 : ConvertedString.insert(0, "0");
1614 0 : this_base = 8;
1615 : }
1616 :
1617 : // else if(HexButton->isChecked())
1618 0 : else if (i == 1) {
1619 0 : if (Unsigned) {
1620 0 : ConvertedString.setNum(CurrentString.toULongLong(&OkConversion, 0), 16);
1621 : } else {
1622 0 : ConvertedString.setNum(CurrentString.toLongLong(&OkConversion, 0), 16);
1623 : }
1624 :
1625 0 : ConvertedString.insert(0, "0x");
1626 0 : this_base = 16;
1627 : }
1628 :
1629 0 : if (!OkConversion) {
1630 0 : QString Format;
1631 :
1632 0 : if (this_native_base == 10) {
1633 0 : Format = "DECIMAL";
1634 0 : } else if (this_native_base == 16) {
1635 0 : Format = "HEX-DECIMAL";
1636 0 : } else if (this_native_base == 8) {
1637 0 : Format = "OCT-DECIMAL";
1638 : }
1639 :
1640 0 : ShowWarning(Format);
1641 :
1642 0 : return;
1643 0 : }
1644 :
1645 0 : if (!ConvertedString.isEmpty()) {
1646 0 : LineEdit->clear();
1647 0 : LineEdit->setText(ConvertedString);
1648 : }
1649 0 : }
1650 :
1651 : void
1652 0 : numericattr::UpdateActions(QString Dummy)
1653 : {
1654 0 : Q_UNUSED(Dummy)
1655 :
1656 0 : if (this_base_data_editor->must_not_be_null() and (LineEdit->text().isEmpty())) {
1657 0 : this_base_data_editor->set_valid(false);
1658 0 : } else if (this_base_data_editor->must_not_be_null() and (this_data.size() == 0)) {
1659 0 : this_base_data_editor->set_valid(false);
1660 : } else {
1661 0 : this_base_data_editor->set_valid(true);
1662 : }
1663 0 : }
1664 :
1665 : void
1666 0 : numericattr::ChangeFormatDec()
1667 : {
1668 0 : ChangeFormat(0);
1669 0 : }
1670 :
1671 : void
1672 0 : numericattr::ChangeFormatHex()
1673 : {
1674 0 : ChangeFormat(1);
1675 0 : }
1676 :
1677 : void
1678 0 : numericattr::ChangeFormatOct()
1679 : {
1680 0 : ChangeFormat(2);
1681 0 : }
1682 :
1683 : //------------------------------------------------------------------------------------------------
1684 :
1685 : //------------------------------------------------------------------------------------------------
1686 0 : combo::combo(t_virtue const& attr, QWidget* parent, bool owned, bool readonly)
1687 0 : : base(std::make_shared<t_build_block_editor>(attr), parent, owned)
1688 0 : , m_base_data_editor(std::static_pointer_cast<t_build_block_editor>(p_data_editor))
1689 0 : , m_readonly(readonly)
1690 : {
1691 0 : setupUi(this);
1692 0 : SetController();
1693 : /// Configuration of combo box
1694 0 : Combo->setFocusPolicy(Qt::ClickFocus);
1695 0 : if (m_readonly) {
1696 0 : Combo->setEditable(false);
1697 0 : if (Combo->lineEdit() != nullptr) {
1698 0 : Combo->lineEdit()->setReadOnly(true);
1699 0 : Combo->lineEdit()->hide();
1700 : }
1701 : } else {
1702 0 : Combo->installEventFilter(this);
1703 0 : if (Combo->lineEdit() != nullptr) {
1704 0 : Combo->lineEdit()->installEventFilter(this);
1705 : }
1706 :
1707 0 : t_virtue const& Virtue = m_base_data_editor->get();
1708 0 : if (Virtue.p_type == dunedaq::conffwk::class_type) {
1709 0 : Combo->setEditable(true);
1710 : }
1711 : }
1712 0 : }
1713 :
1714 : void
1715 0 : combo::SetData(QStringList const& Data)
1716 : {
1717 0 : if (Data.isEmpty()) {
1718 : return;
1719 : }
1720 :
1721 0 : int Index = Combo->findText(Data.value(0));
1722 :
1723 0 : if (Index != -1) {
1724 0 : Combo->setCurrentIndex(Index);
1725 0 : Combo->setEditText(Data.value(0));
1726 : }
1727 : }
1728 :
1729 : void
1730 0 : combo::SetValidatorData(QStringList const& Data, bool AcceptNoMatch)
1731 : {
1732 0 : Combo->clear();
1733 0 : Combo->addItems(Data);
1734 :
1735 0 : if (Combo->isEditable()) {
1736 0 : QCompleter* Completer = new QCompleter(Combo->model(), Combo);
1737 0 : Completer->setCaseSensitivity(Qt::CaseInsensitive);
1738 0 : Completer->setCompletionMode(QCompleter::PopupCompletion);
1739 0 : Completer->setFilterMode(Qt::MatchContains);
1740 0 : Combo->setCompleter(Completer);
1741 : }
1742 0 : m_base_data_editor->set_obligatory(false);
1743 :
1744 0 : QVariant VarFromList(Data);
1745 :
1746 0 : if (AcceptNoMatch) {
1747 0 : ValidatorAcceptNoMatch* TmpValidator = new ValidatorAcceptNoMatch(VarFromList, this);
1748 0 : Combo->setValidator(TmpValidator);
1749 : } else {
1750 0 : ValidatorAcceptMatch* TmpValidator = new ValidatorAcceptMatch(VarFromList, this);
1751 0 : Combo->setValidator(TmpValidator);
1752 : }
1753 0 : }
1754 :
1755 : QStringList
1756 0 : combo::getdata()
1757 : {
1758 0 : this_data.clear();
1759 0 : this_data << Combo->currentText();
1760 0 : return this_data;
1761 : }
1762 :
1763 : void
1764 0 : combo::SetEditor()
1765 : {
1766 0 : t_virtue const& virt = m_base_data_editor->get();
1767 :
1768 0 : if (virt.p_type == dunedaq::conffwk::bool_type) {
1769 0 : QStringList tmp{ "true", "false" };
1770 0 : SetValidatorData(tmp);
1771 0 : } else if (virt.p_type == dunedaq::conffwk::enum_type) {
1772 0 : QString rangename = virt.p_range.c_str();
1773 0 : QStringList range = rangename.split(",");
1774 0 : range.sort();
1775 0 : SetValidatorData(range);
1776 0 : } else if (virt.p_type == dunedaq::conffwk::class_type) {
1777 0 : QStringList classes(dbe::config::api::info::onclass::allnames<QStringList>());
1778 0 : classes.sort();
1779 0 : SetValidatorData(classes);
1780 0 : Combo->lineEdit()->setText(c_input_placeholder);
1781 0 : }
1782 :
1783 0 : SetData(this_data);
1784 0 : }
1785 :
1786 : void
1787 0 : combo::setdata(QStringList const& v)
1788 : {
1789 0 : this_data = v;
1790 0 : }
1791 :
1792 : bool
1793 0 : combo::eventFilter(QObject* Target, QEvent* Event)
1794 : {
1795 0 : if (dynamic_cast<QLineEdit*>(Target) != nullptr) {
1796 0 : std::cout << "cast to QLineEdit\n";
1797 : }
1798 0 : if (Target == Combo && Combo->lineEdit() != nullptr) {
1799 0 : if (Event->type() < 100) {
1800 : }
1801 0 : if (Event->type() == QEvent::FocusOut) {
1802 0 : if (Combo->lineEdit()->text().isEmpty()) {
1803 0 : Combo->lineEdit()->setText(c_input_placeholder);
1804 : }
1805 0 : return true;
1806 : }
1807 0 : if (Event->type() == QEvent::FocusIn) {
1808 0 : if (!Combo->lineEdit()->hasSelectedText()) {
1809 0 : Combo->lineEdit()->selectAll();
1810 : }
1811 0 : return true;
1812 : }
1813 0 : if (Event->type() == QEvent::KeyPress) {
1814 0 : QKeyEvent* KeyEvent = dynamic_cast<QKeyEvent*>(Event);
1815 0 : if (KeyEvent->key() == Qt::Key_Up || KeyEvent->key() == Qt::Key_Down) {
1816 : return true;
1817 : } else {
1818 : return false;
1819 : }
1820 : }
1821 : }
1822 :
1823 0 : if (Event->type() == QEvent::Wheel) {
1824 : return true;
1825 : }
1826 :
1827 : return false;
1828 : }
1829 :
1830 : void
1831 0 : combo::wheelEvent(QWheelEvent* Event)
1832 : {
1833 0 : Q_UNUSED(Event)
1834 0 : return;
1835 : }
1836 :
1837 : void
1838 0 : combo::SetController()
1839 : {
1840 0 : connect(
1841 0 : Combo, SIGNAL(editTextChanged(const QString&)), this, SLOT(TryValidate(const QString&)), Qt::UniqueConnection);
1842 0 : connect(Combo, SIGNAL(activated(const QString&)), this, SLOT(ChangeDetected(const QString&)), Qt::UniqueConnection);
1843 0 : }
1844 :
1845 : void
1846 0 : combo::TryValidate(QString tmp)
1847 : {
1848 0 : if (tmp == c_input_placeholder) {
1849 0 : Combo->lineEdit()->setPalette(QApplication::palette(this));
1850 0 : return;
1851 : }
1852 0 : int index = 0;
1853 0 : if (Combo->validator() != nullptr) {
1854 0 : if (Combo->validator()->validate(tmp, index) == QValidator::Acceptable) {
1855 0 : m_base_data_editor->set_valid(true);
1856 :
1857 0 : if (CompareDefaults()) {
1858 0 : Combo->lineEdit()->setPalette(StyleUtility::LoadedDefault);
1859 : }
1860 :
1861 : else {
1862 0 : Combo->lineEdit()->setPalette(QApplication::palette(this));
1863 : }
1864 : }
1865 :
1866 0 : else if (Combo->validator()->validate(tmp, index) == QValidator::Intermediate) {
1867 0 : m_base_data_editor->set_not_null(false);
1868 0 : Combo->lineEdit()->setPalette(StyleUtility::WarningStatusBarPallete);
1869 : }
1870 : }
1871 :
1872 : else {
1873 0 : if (CompareDefaults()) {
1874 0 : Combo->setPalette(StyleUtility::LoadedDefault);
1875 : } else {
1876 0 : Combo->setPalette(QApplication::palette(this));
1877 : }
1878 : }
1879 : }
1880 :
1881 : void
1882 0 : combo::ChangeDetected(const QString& StringChange)
1883 : {
1884 0 : Q_UNUSED(StringChange)
1885 0 : this_value_changed = true;
1886 0 : emit signal_value_change();
1887 0 : }
1888 :
1889 : void
1890 0 : combo::CheckDefaults(int DefaultIndex)
1891 : {
1892 0 : Q_UNUSED(DefaultIndex)
1893 :
1894 0 : if (!this_defaults.isEmpty()) {
1895 0 : TryValidate(Combo->currentText());
1896 : }
1897 0 : }
1898 :
1899 : bool
1900 0 : combo::CompareDefaults()
1901 : {
1902 0 : if (this_defaults.isEmpty()) {
1903 : return false;
1904 : }
1905 :
1906 0 : if (this_defaults == Combo->currentText()) {
1907 : return true;
1908 : }
1909 :
1910 : return false;
1911 : }
1912 :
1913 : void
1914 0 : combo::buildtooltip()
1915 : {
1916 0 : }
1917 :
1918 : //------------------------------------------------------------------------------------------------
1919 :
1920 : //------------------------------------------------------------------------------------------------
1921 0 : multiattr::multiattr(t_virtue const& attr, QWidget* parent, bool owned, bool readonly)
1922 0 : : base(std::make_shared<t_build_block_editor>(attr), parent, owned)
1923 0 : , m_base_data_editor(std::static_pointer_cast<t_build_block_editor>(p_data_editor))
1924 0 : , m_readonly(readonly)
1925 0 : , StatusBar(nullptr)
1926 0 : , OkButton(nullptr)
1927 0 : , RemoveButton(nullptr)
1928 0 : , ListWidget(nullptr)
1929 0 : , ContextMenu(nullptr)
1930 0 : , RemoveAction(nullptr)
1931 : {
1932 0 : t_virtue const& Virtue = m_base_data_editor->get();
1933 :
1934 0 : setWindowTitle(QString("Edit Attribute : %1").arg(Virtue.p_name.c_str()));
1935 0 : QVBoxLayout* MainLayout = new QVBoxLayout(this);
1936 0 : MainLayout->setSpacing(0);
1937 0 : MainLayout->setMargin(0);
1938 0 : MainLayout->setContentsMargins(0, 0, 0, 0);
1939 0 : QHBoxLayout* ButtonLayout = new QHBoxLayout();
1940 0 : ListWidget = new QListWidget(this);
1941 0 : ListWidget->setContextMenuPolicy(Qt::CustomContextMenu);
1942 0 : MainLayout->addWidget(ListWidget);
1943 :
1944 0 : switch (Virtue.p_type) {
1945 : // Bool and enums have the same widget
1946 :
1947 0 : case dunedaq::conffwk::bool_type:
1948 0 : case dunedaq::conffwk::class_type:
1949 0 : case dunedaq::conffwk::enum_type: {
1950 0 : combo* Combo = new combo(attr, this);
1951 0 : MainLayout->addWidget(Combo);
1952 0 : connect(Combo->Combo,
1953 : SIGNAL(activated(const QString&)),
1954 : this,
1955 : SLOT(AddToDataList(const QString&)),
1956 : Qt::UniqueConnection);
1957 0 : BaseWidget = Combo;
1958 0 : Combo->setStyleSheet("QLineEdit { background: #c0c0c0;} "
1959 : "QLineEdit:focus {background: white;}");
1960 0 : break;
1961 : }
1962 :
1963 : // All numeric types are treated as uint64
1964 :
1965 0 : case dunedaq::conffwk::double_type:
1966 0 : case dunedaq::conffwk::float_type:
1967 0 : case dunedaq::conffwk::s8_type:
1968 0 : case dunedaq::conffwk::s16_type:
1969 0 : case dunedaq::conffwk::s32_type:
1970 0 : case dunedaq::conffwk::s64_type:
1971 0 : case dunedaq::conffwk::u8_type:
1972 0 : case dunedaq::conffwk::u16_type:
1973 0 : case dunedaq::conffwk::u32_type:
1974 0 : case dunedaq::conffwk::u64_type: {
1975 0 : numericattr* Numeric = new numericattr(Virtue, this);
1976 0 : MainLayout->addWidget(Numeric);
1977 0 : connect(Numeric, SIGNAL(signal_value_change()), this, SLOT(LineValueChanged()), Qt::UniqueConnection);
1978 0 : connect(Numeric, SIGNAL(signal_value_duplicated()), this, SLOT(LineValueChanged()), Qt::UniqueConnection);
1979 0 : BaseWidget = Numeric;
1980 : /// Frame
1981 0 : Numeric->GetLineEdit()->setFrame(false);
1982 0 : Numeric->GetLineEdit()->setReadOnly(m_readonly);
1983 0 : Numeric->GetLineEdit()->setPlaceholderText(c_input_placeholder);
1984 0 : Numeric->setStyleSheet("QLineEdit { background: #c0c0c0;} QLineEdit:focus {background: white;}");
1985 0 : Numeric->GetLineEdit()->setFixedHeight(24);
1986 0 : ListWidget->setFrameStyle(QFrame::NoFrame);
1987 : break;
1988 : }
1989 :
1990 : // Types below are all treated as string types
1991 0 : case dunedaq::conffwk::date_type:
1992 0 : case dunedaq::conffwk::time_type:
1993 0 : case dunedaq::conffwk::string_type: {
1994 0 : stringattr* String = new stringattr(Virtue, this);
1995 0 : String->SetMultiCheck(true);
1996 0 : MainLayout->addWidget(String);
1997 0 : connect(String, SIGNAL(signal_value_change()), this, SLOT(LineValueChanged()), Qt::UniqueConnection);
1998 0 : BaseWidget = String;
1999 : /// Frame
2000 0 : String->GetLineEdit()->setReadOnly(m_readonly);
2001 0 : String->GetLineEdit()->setFrameStyle(QFrame::NoFrame);
2002 0 : String->GetLineEdit()->setPlaceholderText(c_input_placeholder);
2003 0 : String->setStyleSheet("QLineEdit { background: #c0c0c0;} "
2004 : "QLineEdit:focus {background: white;}");
2005 : // String->GetLineEdit()->setFixedHeight ( 24 );
2006 :
2007 0 : ListWidget->setFrameStyle(QFrame::NoFrame);
2008 : break;
2009 : }
2010 :
2011 : default:
2012 : break;
2013 : }
2014 :
2015 0 : OkButton = new QPushButton(tr("Apply"));
2016 : // RemoveButton = new QPushButton(tr("Remove"));
2017 0 : ButtonLayout->addWidget(OkButton);
2018 : // ButtonLayout->addWidget(RemoveButton);
2019 0 : connect(OkButton, SIGNAL(clicked()), this, SLOT(EndSignal()));
2020 : // connect(RemoveButton,SIGNAL(clicked()),this,SLOT(RemoveFromDataList()));
2021 0 : connect(this, SIGNAL(signal_internal_value_change()), this, SLOT(UpdateActions()));
2022 0 : connect(ListWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(CustomContextMenuRequested(QPoint)));
2023 :
2024 0 : MainLayout->addLayout(ButtonLayout);
2025 0 : SetStatusBar();
2026 0 : MainLayout->addWidget(StatusBar);
2027 :
2028 0 : setLayout(MainLayout);
2029 :
2030 0 : if (Virtue.p_is_not_null) {
2031 0 : m_base_data_editor->set_valid(false);
2032 0 : OkButton->setDisabled(true);
2033 : }
2034 :
2035 0 : if (this_is_owned) {
2036 0 : OkButton->setHidden(true);
2037 : }
2038 :
2039 : else {
2040 0 : QFont Font;
2041 0 : QFontMetrics FontMetrics(Font);
2042 0 : setMinimumWidth(2 * FontMetrics.horizontalAdvance(QString("Edit Relationship: %1").arg(Virtue.p_name.c_str())) -
2043 : 15);
2044 0 : setMinimumHeight(100);
2045 0 : }
2046 :
2047 0 : buildtooltip();
2048 0 : UpdateActions();
2049 0 : }
2050 :
2051 : void
2052 0 : multiattr::SetEditor()
2053 : {
2054 0 : BaseWidget->SetEditor();
2055 :
2056 0 : ListWidget->clear();
2057 0 : ListWidget->addItems(this_data);
2058 0 : ListWidget->setSelectionMode(QAbstractItemView::ExtendedSelection);
2059 0 : ListWidget->setDragEnabled(true);
2060 0 : ListWidget->setAcceptDrops(true);
2061 0 : ListWidget->setEditTriggers(QAbstractItemView::DoubleClicked);
2062 0 : ListWidget->setDragDropMode(QAbstractItemView::InternalMove);
2063 :
2064 0 : for (int i = 0; i < ListWidget->count(); ++i) {
2065 0 : QListWidgetItem* widget = ListWidget->item(i);
2066 0 : widget->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled |
2067 : Qt::ItemIsEnabled);
2068 : }
2069 :
2070 0 : connect(ListWidget, SIGNAL(itemChanged(QListWidgetItem*)), this, SLOT(LineValueChanged(QListWidgetItem*)));
2071 0 : emit signal_internal_value_change();
2072 0 : }
2073 :
2074 : void
2075 0 : multiattr::buildtooltip()
2076 : {
2077 0 : t_virtue const& Virtue = m_base_data_editor->get();
2078 :
2079 0 : setToolTip(
2080 0 : QString("Attribute Name: %1 \n").arg(Virtue.p_name.c_str()) +
2081 0 : QString(" Type: %1 \n").arg(dunedaq::conffwk::attribute_t::type2str(Virtue.p_type)) +
2082 0 : QString(" Range: %1 \n").arg(Virtue.p_range.c_str()) +
2083 0 : QString(" Format: %1 \n").arg(dunedaq::conffwk::attribute_t::format2str(Virtue.p_int_format)) +
2084 0 : QString(" Not Null: %1 \n").arg(Virtue.p_is_not_null) +
2085 0 : QString(" Is Multi Value: %1 \n").arg(Virtue.p_is_multi_value) +
2086 0 : QString(" Default Value: %1 \n").arg(Virtue.p_default_value.c_str()) +
2087 0 : QString(" Description: %1 \n").arg(Virtue.p_description.c_str()));
2088 0 : }
2089 :
2090 : void
2091 0 : multiattr::closeEvent(QCloseEvent* Event)
2092 : {
2093 0 : Q_UNUSED(Event)
2094 0 : emit signal_force_close();
2095 0 : }
2096 :
2097 : void
2098 0 : multiattr::SetStatusBar()
2099 : {
2100 0 : StatusBar = new QStatusBar(this);
2101 0 : StatusBar->setSizeGripEnabled(false);
2102 : /// Color Management needs to be done
2103 0 : StatusBar->setAutoFillBackground(true);
2104 : /// Uncomment if you want a status bar
2105 0 : StatusBar->setHidden(true);
2106 0 : }
2107 :
2108 : bool
2109 0 : multiattr::eventFilter(QObject* Target, QEvent* Event)
2110 : {
2111 0 : (void)Target;
2112 0 : (void)Event;
2113 0 : return false;
2114 : }
2115 :
2116 : void
2117 0 : multiattr::AddToDataList(const QString& Data)
2118 : {
2119 0 : if (Data.isEmpty()) {
2120 : return;
2121 : }
2122 :
2123 0 : this_data.append(Data);
2124 :
2125 0 : ListWidget->clear();
2126 0 : ListWidget->addItems(this_data);
2127 0 : StatusBar->showMessage(QString("Item %1 was added.").arg(Data));
2128 :
2129 0 : this_value_changed = true;
2130 0 : emit signal_internal_value_change();
2131 : }
2132 :
2133 : void
2134 0 : multiattr::RemoveFromDataList()
2135 : {
2136 0 : QList<QListWidgetItem*> widgets = ListWidget->selectedItems();
2137 0 : this_value_changed = true;
2138 :
2139 0 : for (QListWidgetItem* widget : widgets) {
2140 0 : int index = this_data.indexOf(widget->text());
2141 :
2142 0 : if (index != -1) {
2143 0 : this_data.takeAt(index);
2144 : }
2145 :
2146 0 : int r = ListWidget->row(widget);
2147 :
2148 0 : if (QListWidgetItem* w = ListWidget->takeItem(r)) {
2149 0 : delete w;
2150 : }
2151 : }
2152 :
2153 0 : if (this_is_owned) {
2154 0 : StatusBar->showMessage("The selected items were removed.");
2155 : }
2156 :
2157 0 : if (dynamic_cast<stringattr*>(BaseWidget)) {
2158 : /// Color management needs to be done
2159 0 : stringattr* StringWidget = dynamic_cast<stringattr*>(BaseWidget);
2160 0 : StringWidget->GetLineEdit()->selectAll();
2161 0 : StringWidget->GetLineEdit()->clear();
2162 0 : StringWidget->SetCheckDefaults(false);
2163 0 : StringWidget->SetNullCheck(true);
2164 : }
2165 :
2166 0 : emit signal_internal_value_change();
2167 0 : emit signal_value_change();
2168 0 : }
2169 :
2170 : void
2171 0 : multiattr::UpdateActions()
2172 : {
2173 0 : t_virtue const& Virtue = m_base_data_editor->get();
2174 :
2175 0 : if (Virtue.p_is_not_null and this_data.size() == 0) {
2176 0 : OkButton->setDisabled(true);
2177 0 : StatusBar->showMessage("Attribute can not be null.");
2178 0 : m_base_data_editor->set_valid(false);
2179 0 : ListWidget->setPalette(StyleUtility::WarningStatusBarPallete);
2180 : /// EditString validator string
2181 : }
2182 :
2183 0 : else if (Virtue.p_is_not_null and this_data.size() > 0) {
2184 : /// Null Check validator string
2185 :
2186 0 : StatusBar->showMessage("Attribute is set.");
2187 0 : ListWidget->setPalette(QApplication::palette(this));
2188 0 : OkButton->setEnabled(true);
2189 0 : m_base_data_editor->set_valid(true);
2190 :
2191 0 : if (this_is_owned) {
2192 0 : EndSignal();
2193 : }
2194 0 : } else if (not Virtue.p_is_not_null and this_is_owned) {
2195 0 : m_base_data_editor->set_valid(true);
2196 0 : EndSignal();
2197 : }
2198 0 : }
2199 :
2200 : void
2201 0 : multiattr::LineValueChanged()
2202 : {
2203 0 : QStringList Data = BaseWidget->getdata();
2204 :
2205 0 : if ((!Data.isEmpty()) && BaseWidget->dataeditor()->is_valid()) {
2206 0 : AddToDataList(Data.at(0));
2207 : }
2208 0 : }
2209 :
2210 : void
2211 0 : multiattr::LineValueChanged(QListWidgetItem* changed)
2212 : {
2213 0 : int r = ListWidget->row(changed);
2214 0 : QString newtext = changed->text();
2215 0 : QString oldtext = this_data.at(r);
2216 0 : this_data.replace(r, newtext);
2217 0 : this_value_changed = true;
2218 :
2219 0 : StatusBar->showMessage(QString("Item %1 was modified.").arg(oldtext));
2220 :
2221 0 : emit signal_internal_value_change();
2222 0 : }
2223 :
2224 : void
2225 0 : multiattr::ListOrderChange(const QModelIndexList& IndexList)
2226 : {
2227 0 : Q_UNUSED(IndexList)
2228 :
2229 0 : this_data.clear();
2230 :
2231 0 : for (int i = 0; i < ListWidget->count(); ++i) {
2232 0 : this_data.append(ListWidget->item(i)->text());
2233 : }
2234 0 : }
2235 :
2236 : void
2237 0 : multiattr::EndSignal()
2238 : {
2239 0 : this_data.clear();
2240 :
2241 0 : for (int i = 0; i < ListWidget->count(); ++i) {
2242 0 : this_data.append(ListWidget->item(i)->text());
2243 : }
2244 :
2245 0 : if (!this_is_owned) {
2246 0 : m_base_data_editor->set_valid(true);
2247 0 : emit signal_edit_end();
2248 : }
2249 :
2250 : else {
2251 0 : emit signal_value_change();
2252 : }
2253 0 : }
2254 :
2255 : void
2256 0 : multiattr::CustomContextMenuRequested(const QPoint& pos)
2257 : {
2258 0 : if (ContextMenu == nullptr) {
2259 0 : ContextMenu = new QMenu(ListWidget);
2260 :
2261 0 : RemoveAction = new QAction(tr("Remove"), this);
2262 0 : RemoveAction->setShortcutContext(Qt::WidgetShortcut);
2263 0 : connect(RemoveAction, SIGNAL(triggered()), this, SLOT(RemoveSlot()), Qt::UniqueConnection);
2264 0 : ContextMenu->addAction(RemoveAction);
2265 : }
2266 :
2267 0 : ContextMenu->exec(ListWidget->mapToGlobal(pos));
2268 0 : }
2269 :
2270 : void
2271 0 : multiattr::RemoveSlot()
2272 : {
2273 0 : RemoveFromDataList();
2274 0 : }
2275 :
2276 : //------------------------------------------------------------------------------------------------
2277 :
2278 : } // end namespace editors
2279 : } // end namespace widgets
2280 : } // end namespace dbe
2281 :
2282 : //------------------------------------------------------------------------------------------------
|