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