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