Line data Source code
1 : // DUNE DAQ modification notice:
2 : // This file has been modified from the original ATLAS dbe source for the DUNE DAQ project.
3 : // Fork baseline commit: dbe-02-12-17 (2022-05-12).
4 : // Renamed since fork: no.
5 :
6 : #include "dbe/ObjectEditor.hpp"
7 : #include "dbe/StyleUtility.hpp"
8 : #include "dbe/Sorting.hpp"
9 : #include "dbe/config_api_set.hpp"
10 : #include "dbe/config_api_get.hpp"
11 : #include "dbe/config_api_graph.hpp"
12 : #include "dbe/config_api_commands.hpp"
13 : #include "dbe/messenger.hpp"
14 : #include "ui_ObjectEditor.h"
15 : #include "dbe/MainWindow.hpp"
16 :
17 : #include <QFileInfo>
18 : #include <QCloseEvent>
19 : #include <QMessageBox>
20 :
21 : namespace dbegraph = dbe::config::api::graph;
22 :
23 : namespace {
24 : class NoScrollingTable : public QTableWidget {
25 : public:
26 0 : explicit NoScrollingTable(QWidget* parent = nullptr)
27 0 : : QTableWidget(parent) {}
28 :
29 0 : void scrollTo(const QModelIndex& /*index*/, ScrollHint /*hint*/) override {
30 : // NOTE: for the reason why this is an empty implementation, see ATLASDBE-202
31 0 : }
32 : };
33 : } // namespace
34 :
35 : //------------------------------------------------------------------------------------------
36 0 : dbe::ObjectEditor::~ObjectEditor() = default;
37 : //------------------------------------------------------------------------------------------
38 :
39 : //------------------------------------------------------------------------------------------
40 0 : dbe::ObjectEditor::ObjectEditor(QWidget * parent)
41 : :
42 : QWidget(parent),
43 0 : ui ( new Ui::ObjectEditor ),
44 0 : IsValid ( false ),
45 0 : this_editor_values_changed ( false ),
46 0 : CurrentRow ( 0 ),
47 0 : MainLayout ( new QHBoxLayout() ),
48 0 : WidgetTable ( new NoScrollingTable() ),
49 0 : RenameWidget ( nullptr ),
50 0 : LineEdit ( nullptr ),
51 0 : GoButton ( nullptr ),
52 0 : MoveWidget ( nullptr ),
53 0 : FileView ( nullptr ),
54 0 : IncludedFileModel ( nullptr ),
55 0 : MoveGoButton ( nullptr ),
56 0 : uuid ( QUuid::createUuid() )
57 : {
58 0 : ui->setupUi ( this );
59 0 : }
60 : //------------------------------------------------------------------------------------------
61 :
62 : //------------------------------------------------------------------------------------------
63 :
64 0 : dbe::ObjectEditor::ObjectEditor ( std::string const & cname, QWidget * parent )
65 0 : : ObjectEditor ( parent ) {
66 :
67 0 : classname = cname;
68 0 : m_object_to_edit = nullptr;
69 0 : this_is_in_copy_mode = true;
70 0 : this_editor_is_owned = true;
71 0 : this_is_in_creation_mode = true;
72 :
73 0 : ui->RenameButton->setDisabled ( true ); // Cannot rename an object that does not exist
74 0 : ui->ClassLabel->setText ( QString ( "New Object" ) );
75 :
76 0 : init();
77 0 : }
78 :
79 : //------------------------------------------------------------------------------------------
80 :
81 0 : dbe::ObjectEditor::ObjectEditor ( tref const & object, QWidget * parent, bool iscopy )
82 0 : : ObjectEditor ( parent ) {
83 :
84 0 : classname = object.class_name();
85 0 : m_object_to_edit.reset(new dref ( object ));
86 0 : this_is_in_copy_mode = iscopy;
87 0 : this_editor_is_owned = false;
88 0 : this_is_in_creation_mode = false;
89 :
90 0 : ui->ClassLabel->setText (
91 0 : QString ( "Full object name : %1@%2" ).arg ( Object().UID().c_str() ).arg (
92 0 : Object().class_name().c_str() ) );
93 :
94 0 : this->setWindowTitle (
95 0 : QString ( "Edit Object %1 of Class %2" ).arg ( Object().UID().c_str() ).arg (
96 0 : Object().class_name().c_str() ) );
97 :
98 0 : this->setObjectName (
99 0 : QString ( "%1@%2" ).arg ( Object().UID().c_str() ).arg ( Object().class_name().c_str() ) );
100 :
101 0 : init();
102 0 : }
103 :
104 : //------------------------------------------------------------------------------------------
105 0 : void dbe::ObjectEditor::init() {
106 0 : dunedaq::conffwk::class_t const & Class =
107 0 : dbe::config::api::info::onclass::definition ( classname, false );
108 0 : int NumberOfRows = Class.p_attributes.size() + Class.p_relationships.size();
109 0 : int NumberOfColumns = 1;
110 0 : WidgetTable->setRowCount ( NumberOfRows );
111 0 : WidgetTable->setColumnCount ( NumberOfColumns );
112 0 : setAttribute ( Qt::WA_DeleteOnClose, true );
113 :
114 0 : SetController();
115 0 : BuildWidgets();
116 0 : UpdateActions();
117 0 : BuildFileInfo();
118 :
119 0 : ui->DetailsGroupBox->setVisible ( false );
120 :
121 0 : WidgetTable->setSizePolicy ( QSizePolicy::Expanding, QSizePolicy::Expanding );
122 0 : WidgetTable->horizontalHeader()->setVisible ( false );
123 0 : WidgetTable->horizontalHeader()->setSectionResizeMode ( QHeaderView::ResizeToContents );
124 0 : WidgetTable->horizontalHeader()->setSectionResizeMode ( 0, QHeaderView::Stretch );
125 0 : WidgetTable->setVerticalHeaderLabels ( HorizontalHeaders );
126 0 : WidgetTable->setSelectionMode ( QAbstractItemView::NoSelection );
127 :
128 0 : if ( this_is_in_creation_mode )
129 : {
130 0 : ui->RenameButton->setDisabled ( true );
131 0 : ui->MoveButton->setDisabled ( true );
132 : }
133 : else {
134 0 : bool rw = confaccessor::check_file_rw (
135 0 : QString::fromStdString ( Object().contained_in() ));
136 0 : if (!rw) {
137 0 : WidgetTable->setDisabled(true);
138 0 : ui->RenameButton->setDisabled(true);
139 0 : ui->MoveButton->setDisabled(true);
140 : }
141 : }
142 0 : ui->TableLayout->addWidget ( WidgetTable );
143 :
144 0 : ui->ApplyButton->setEnabled ( false );
145 :
146 0 : ui->RenameButton->setToolTip ( "Rename object" );
147 :
148 :
149 0 : this->show();
150 0 : }
151 :
152 0 : void dbe::ObjectEditor::keyPressEvent(QKeyEvent* event) {
153 0 : if (event->key() == Qt::Key_Escape) {
154 0 : close();
155 : }
156 0 : QWidget::keyPressEvent(event);
157 0 : }
158 : //------------------------------------------------------------------------------------------
159 :
160 : //------------------------------------------------------------------------------------------
161 0 : void dbe::ObjectEditor::HideDetailWidget ( bool Hide )
162 : {
163 0 : if ( Hide )
164 : {
165 0 : ui->DetailWidget->hide();
166 0 : ui->DetailsGroupBox->hide();
167 : }
168 : else
169 : {
170 0 : ui->DetailWidget->show();
171 0 : ui->DetailsGroupBox->show();
172 : }
173 0 : }
174 :
175 : //------------------------------------------------------------------------------------------
176 :
177 : //------------------------------------------------------------------------------------------
178 0 : bool dbe::ObjectEditor::IsEditorValid() const
179 : {
180 0 : return IsValid;
181 : }
182 :
183 0 : bool dbe::ObjectEditor::WasObjectChanged() const
184 : {
185 0 : return this_editor_values_changed;
186 : }
187 :
188 : //------------------------------------------------------------------------------------------
189 :
190 : //------------------------------------------------------------------------------------------
191 0 : bool dbe::ObjectEditor::CanCloseWindow()
192 : {
193 0 : if ( this_editor_values_changed and
194 0 : ui->ApplyButton->isEnabled() )
195 : {
196 0 : int ret =
197 0 : QMessageBox::question (
198 : 0,
199 0 : tr ( "DBE - ObjectEditor" ),
200 0 : QString (
201 0 : "There are unsaved changes for object\n'%1.%2'\n\nDo you want to apply changes?\n" )
202 0 : .arg ( QString::fromStdString ( Object().full_name() ) ),
203 0 : QMessageBox::Apply | QMessageBox::Discard | QMessageBox::Cancel,
204 : QMessageBox::Apply );
205 :
206 0 : switch ( ret )
207 : {
208 :
209 0 : case QMessageBox::Discard:
210 0 : ResetObjectChanged();
211 0 : break;
212 :
213 0 : case QMessageBox::Apply:
214 0 : ParseToSave();
215 0 : break;
216 :
217 : case QMessageBox::Cancel:
218 : return false;
219 0 : break;
220 : }
221 :
222 0 : return true;
223 : }
224 : else
225 : {
226 0 : return true;
227 : }
228 : }
229 :
230 : //------------------------------------------------------------------------------------------
231 :
232 : //------------------------------------------------------------------------------------------
233 0 : void dbe::ObjectEditor::SetStatusBar()
234 : {
235 0 : StatusBar->setSizeGripEnabled ( false );
236 0 : StatusBar->setAutoFillBackground ( true );
237 0 : }
238 :
239 : //------------------------------------------------------------------------------------------
240 :
241 : //------------------------------------------------------------------------------------------
242 0 : void dbe::ObjectEditor::SetController()
243 : {
244 0 : connect ( ui->DetailButton, SIGNAL ( toggled ( bool ) ), ui->DetailsGroupBox,
245 : SLOT ( setVisible ( bool ) ), Qt::UniqueConnection );
246 0 : connect ( ui->CloseButton, SIGNAL ( clicked ( bool ) ), this, SLOT ( close() ),
247 : Qt::UniqueConnection );
248 0 : connect ( ui->ApplyButton, SIGNAL ( clicked() ), this, SLOT ( ParseToSave() ),
249 : Qt::UniqueConnection );
250 :
251 0 : connect ( ui->RenameButton, SIGNAL ( clicked() ), this, SLOT ( LaunchRenameObject() ) );
252 0 : connect ( ui->MoveButton, SIGNAL ( clicked() ), this, SLOT ( LaunchMoveObject() ) );
253 :
254 0 : connect ( &confaccessor::ref(), SIGNAL ( object_changed ( QString, dref ) ), this,
255 : SLOT ( UpdateObjectEditor ( QString, dref ) ) );
256 :
257 0 : connect ( &confaccessor::ref(), SIGNAL ( object_deleted ( QString, dref ) ), this,
258 : SLOT ( ShouldCloseThisWindow ( QString, dref ) ) );
259 :
260 0 : MainWindow * mainwin = MainWindow::findthis();
261 0 : if(mainwin != nullptr) {
262 0 : connect (mainwin, SIGNAL(signal_batch_change_stopped(const QList<QPair<QString, QString>>&)),
263 : this, SLOT(UpdateObjectEditor(const QList<QPair<QString, QString>>&)), Qt::UniqueConnection);
264 0 : connect (mainwin, SIGNAL(signal_externalchanges_processed()),
265 : this, SLOT(UpdateObjectEditor()), Qt::UniqueConnection);
266 : }
267 0 : }
268 :
269 0 : void dbe::ObjectEditor::UpdateObjectEditor(const QList<QPair<QString, QString>>& objs) {
270 0 : for(const auto& p : objs) {
271 0 : if((p.first.toStdString() == Object().class_name()) && (p.second.toStdString() == Object().UID())) {
272 0 : UpdateObjectEditor("", inner::dbcontroller::get({Object().UID(), Object().class_name()}));
273 0 : break;
274 : }
275 : }
276 0 : }
277 :
278 0 : void dbe::ObjectEditor::UpdateObjectEditor() {
279 0 : const auto& ref = inner::dbcontroller::get({Object().UID(), Object().class_name()});
280 0 : if(ref.is_null() == false) {
281 0 : UpdateObjectEditor("", inner::dbcontroller::get({Object().UID(), Object().class_name()}));
282 : } else {
283 : // The object has been deleted
284 0 : this->close();
285 : }
286 0 : }
287 :
288 : //------------------------------------------------------------------------------------------
289 :
290 : //------------------------------------------------------------------------------------------
291 0 : void dbe::ObjectEditor::UpdateObjectEditor ( QString const & src, dref updated_object )
292 : {
293 : // src is ignored even in the case of this being the source
294 : // changes must always be applied since it is developer responsibility
295 : // to emit signals as needed
296 0 : Q_UNUSED ( src );
297 :
298 0 : if ( not this_editor_is_owned and m_object_to_edit and Object().UID() == updated_object.UID()
299 0 : and Object().class_name() == updated_object.class_name() )
300 : {
301 :
302 0 : m_object_to_edit.reset ( new dref ( updated_object ) );
303 :
304 0 : dunedaq::conffwk::class_t const & classdef =
305 0 : dbe::config::api::info::onclass::definition ( classname, false );
306 0 : std::vector<dunedaq::conffwk::attribute_t> class_attributes = classdef.p_attributes;
307 0 : std::vector<dunedaq::conffwk::relationship_t> class_relations = classdef.p_relationships;
308 :
309 0 : for ( dunedaq::conffwk::attribute_t attr : class_attributes )
310 : {
311 0 : if ( widgets::editors::base * attreditor =
312 0 : this_widgets[QString::fromStdString ( attr.p_name )] )
313 : {
314 0 : set_attribute_widget ( attr, attreditor );
315 : }
316 0 : }
317 :
318 0 : for ( dunedaq::conffwk::relationship_t arelation : class_relations )
319 : {
320 0 : QStringList relvalues;
321 0 : QString relname = QString ( arelation.p_name.c_str() );
322 :
323 0 : if ( widgets::editors::relation * relwidget =
324 0 : dynamic_cast<widgets::editors::relation *> ( this_widgets[relname] ) )
325 : {
326 0 : if ( relwidget->ischanged() )
327 : {
328 0 : relvalues = relwidget->getdata();
329 : }
330 : else
331 : {
332 0 : std::vector<tref> connected;
333 :
334 0 : if ( config::api::info::relation::is_simple ( arelation ) )
335 : {
336 0 : try
337 : {
338 0 : connected.push_back (
339 0 : config::api::graph::linked::through::relation<tref> ( Object(), arelation ) );
340 : }
341 0 : catch ( daq::dbe::config_object_retrieval_result_is_null const & e )
342 : {
343 : // nothing needs be done to handle the case that a relation has no object set
344 0 : }
345 : }
346 : else
347 : {
348 0 : connected =
349 0 : dbegraph::linked::through::relation<std::vector<tref>> ( Object(), arelation );
350 : }
351 :
352 0 : std::transform ( connected.begin(), connected.end(), std::back_inserter ( relvalues ),
353 0 : [] ( decltype ( connected ) ::value_type const & x )
354 : {
355 0 : return QString::fromStdString ( x.UID() );
356 : }
357 :
358 : );
359 :
360 0 : }
361 :
362 0 : relwidget->setdata ( relvalues );
363 0 : relwidget->SetEditor();
364 : }
365 0 : }
366 0 : }
367 :
368 : // Trick to properly refresh the window (repaint and update does not seem to work)
369 0 : const auto& s = size();
370 0 : resize(s.width() + 1, s.height() +1);
371 0 : resize(s.width(), s.height());
372 0 : }
373 :
374 : //------------------------------------------------------------------------------------------
375 :
376 : //------------------------------------------------------------------------------------------
377 0 : void dbe::ObjectEditor::ShouldCloseThisWindow ( QString const src, dref const key )
378 : {
379 0 : Q_UNUSED ( src );
380 :
381 0 : std::string const & fullname = key.UID() + "@" + key.class_name();
382 :
383 0 : if ( ( m_object_to_edit and not m_object_to_edit->is_valid() )
384 0 : or ( this->objectName().toStdString() == fullname ) )
385 : {
386 0 : this->close();
387 : }
388 0 : }
389 :
390 : //------------------------------------------------------------------------------------------
391 :
392 : //------------------------------------------------------------------------------------------
393 0 : void dbe::ObjectEditor::BuildWidgets()
394 : {
395 0 : dunedaq::conffwk::class_t const & classdef =
396 0 : dbe::config::api::info::onclass::definition ( classname, false );
397 0 : std::vector<dunedaq::conffwk::attribute_t> attributes = classdef.p_attributes;
398 0 : std::vector<dunedaq::conffwk::relationship_t> relations = classdef.p_relationships;
399 :
400 0 : for ( dunedaq::conffwk::attribute_t const & attr : attributes ) // Build widgets for attributes
401 :
402 : {
403 0 : QString name = QString::fromStdString ( attr.p_name );
404 :
405 0 : if ( attr.p_is_multi_value )
406 : {
407 0 : widgets::editors::multiattr * widget = new widgets::editors::multiattr ( attr, this,
408 0 : true );
409 0 : set_attribute_widget ( attr, widget );
410 :
411 0 : set_tooltip ( attr, widget );
412 0 : register_attribute_widget ( name, widget );
413 0 : connect ( widget, SIGNAL ( signal_value_change() ), this, SLOT ( UpdateActions() ),
414 : Qt::UniqueConnection );
415 0 : connect ( widget, SIGNAL ( signal_value_change() ), this, SLOT ( ObjectChanged() ),
416 : Qt::UniqueConnection );
417 0 : emit LoadedInitials();
418 : }
419 : else
420 : {
421 0 : switch ( attr.p_type )
422 : {
423 :
424 0 : case dunedaq::conffwk::enum_type:
425 :
426 0 : case dunedaq::conffwk::bool_type:
427 0 : {
428 0 : widgets::editors::combo * Widget = new widgets::editors::combo ( attr, this, true );
429 0 : set_attribute_widget ( attr, Widget );
430 0 : set_tooltip ( attr, Widget );
431 0 : register_attribute_widget ( name, Widget );
432 0 : connect ( Widget->Combo, SIGNAL ( activated ( QString ) ), this, SLOT ( UpdateActions() ),
433 : Qt::UniqueConnection );
434 0 : connect ( Widget, SIGNAL ( signal_value_change() ), this, SLOT ( ObjectChanged() ),
435 : Qt::UniqueConnection );
436 0 : emit LoadedInitials();
437 : break;
438 : }
439 :
440 0 : case dunedaq::conffwk::double_type:
441 :
442 0 : case dunedaq::conffwk::float_type:
443 :
444 0 : case dunedaq::conffwk::s8_type:
445 :
446 0 : case dunedaq::conffwk::s16_type:
447 :
448 0 : case dunedaq::conffwk::s32_type:
449 :
450 0 : case dunedaq::conffwk::s64_type:
451 :
452 0 : case dunedaq::conffwk::u8_type:
453 :
454 0 : case dunedaq::conffwk::u16_type:
455 :
456 0 : case dunedaq::conffwk::u32_type:
457 :
458 0 : case dunedaq::conffwk::u64_type:
459 0 : {
460 0 : widgets::editors::numericattr * Widget = new widgets::editors::numericattr ( attr, this,
461 0 : true );
462 0 : set_attribute_widget ( attr, Widget );
463 0 : set_tooltip ( attr, Widget );
464 0 : register_attribute_widget ( name, Widget );
465 0 : connect ( Widget, SIGNAL ( signal_value_change() ), this, SLOT ( UpdateActions() ),
466 : Qt::UniqueConnection );
467 0 : connect ( Widget, SIGNAL ( signal_value_change() ), this, SLOT ( ObjectChanged() ),
468 : Qt::UniqueConnection );
469 0 : emit LoadedInitials();
470 : break;
471 : }
472 :
473 0 : case dunedaq::conffwk::string_type:
474 :
475 0 : case dunedaq::conffwk::date_type:
476 :
477 0 : case dunedaq::conffwk::time_type:
478 0 : {
479 0 : widgets::editors::stringattr * Widget = new widgets::editors::stringattr ( attr, this,
480 0 : true );
481 0 : set_attribute_widget ( attr, Widget );
482 0 : set_tooltip ( attr, Widget );
483 0 : register_attribute_widget ( name, Widget );
484 0 : connect ( Widget, SIGNAL ( signal_value_change() ), this, SLOT ( UpdateActions() ),
485 : Qt::UniqueConnection );
486 0 : connect ( Widget, SIGNAL ( signal_value_change() ), this, SLOT ( ObjectChanged() ),
487 : Qt::UniqueConnection );
488 0 : emit LoadedInitials();
489 : break;
490 : }
491 :
492 0 : case dunedaq::conffwk::class_type:
493 0 : {
494 0 : widgets::editors::combo * Widget = new widgets::editors::combo ( attr, this, true );
495 0 : set_attribute_widget ( attr, Widget );
496 0 : set_tooltip ( attr, Widget );
497 0 : register_attribute_widget ( name, Widget );
498 0 : connect ( Widget->Combo, SIGNAL ( activated ( QString ) ), this, SLOT ( UpdateActions() ),
499 : Qt::UniqueConnection );
500 0 : connect ( Widget, SIGNAL ( signal_value_change() ), this, SLOT ( ObjectChanged() ),
501 : Qt::UniqueConnection );
502 0 : emit LoadedInitials();
503 : break;
504 : }
505 : }
506 : }
507 0 : }
508 :
509 0 : for ( dunedaq::conffwk::relationship_t const & arelation :
510 0 : relations ) // Build widgets for relations ( relationships )
511 : {
512 0 : widgets::editors::relation * widget = new widgets::editors::relation ( arelation, this,
513 0 : true );
514 0 : QString name = QString::fromStdString ( arelation.p_name );
515 0 : QStringList Data;
516 :
517 0 : if ( m_object_to_edit and not Object().is_null() )
518 : {
519 0 : std::vector<tref> DataList;
520 :
521 0 : if ( config::api::info::relation::is_simple ( arelation ) )
522 : {
523 0 : try
524 : {
525 0 : DataList.push_back (
526 0 : dbegraph::linked::through::relation<tref> ( Object(), arelation ) );
527 : }
528 0 : catch ( daq::dbe::config_object_retrieval_result_is_null const & e )
529 : {
530 : // nothing needs be done to handle cases that a relation has not been set
531 0 : }
532 : }
533 : else
534 : {
535 0 : DataList = dbegraph::linked::through::relation<std::vector<tref>> ( Object(), arelation );
536 : }
537 :
538 0 : for ( tref const & i : DataList )
539 : {
540 0 : if ( not i.is_null() )
541 : {
542 0 : Data.push_back ( QString::fromStdString ( i.UID() ) );
543 : }
544 : }
545 0 : }
546 :
547 0 : widget->setdata ( Data );
548 0 : widget->SetEditor();
549 0 : set_tooltip ( arelation, widget );
550 0 : register_relation_widget ( name, widget );
551 0 : connect ( widget, SIGNAL ( signal_value_change() ), this, SLOT ( UpdateActions() ),
552 : Qt::UniqueConnection );
553 0 : connect ( widget, SIGNAL ( signal_value_change() ), this, SLOT ( ObjectChanged() ),
554 : Qt::UniqueConnection );
555 0 : connect ( widget, SIGNAL ( LoadedInitials() ), this, SLOT ( ResetObjectChanged() ),
556 : Qt::UniqueConnection );
557 0 : connect ( this, SIGNAL ( LoadedInitials() ), widget, SLOT ( slot_set_initial_loaded() ),
558 : Qt::UniqueConnection );
559 : /// Some connections are missing
560 0 : emit LoadedInitials();
561 0 : }
562 0 : }
563 :
564 : //------------------------------------------------------------------------------------------
565 :
566 : //------------------------------------------------------------------------------------------
567 0 : void dbe::ObjectEditor::set_tooltip ( dunedaq::conffwk::attribute_t const & Attribute,
568 : widgets::editors::base * Widget )
569 : {
570 0 : QString ToolTip;
571 0 : ToolTip.append ( QString ( "Attribute Name: %1 \n" ).arg (
572 : Attribute.p_name.c_str() ) );
573 0 : ToolTip.append (
574 0 : QString ( " Type: %1 \n" ).arg (
575 0 : dunedaq::conffwk::attribute_t::type2str ( Attribute.p_type ) ) );
576 0 : ToolTip.append ( QString ( " Range: %1 \n" ).arg (
577 : Attribute.p_range.c_str() ) );
578 0 : ToolTip.append (
579 0 : QString ( " Format: %1 \n" ).arg (
580 0 : dunedaq::conffwk::attribute_t::format2str ( Attribute.p_int_format ) ) );
581 0 : ToolTip.append ( QString ( " Not Null: %1 \n" ).arg (
582 0 : Attribute.p_is_not_null ) );
583 0 : ToolTip.append (
584 0 : QString ( " Is Multi Value: %1 \n" ).arg ( Attribute.p_is_multi_value ) );
585 0 : ToolTip.append (
586 0 : QString ( " Default Value: %1 \n" ).arg ( Attribute.p_default_value.c_str() ) );
587 0 : ToolTip.append (
588 0 : QString ( " Description: %1 \n" ).arg ( Attribute.p_description.c_str() ) );
589 0 : Widget->setToolTip ( ToolTip );
590 0 : }
591 :
592 : //------------------------------------------------------------------------------------------
593 :
594 : //------------------------------------------------------------------------------------------
595 0 : void dbe::ObjectEditor::set_tooltip ( dunedaq::conffwk::relationship_t const & relation,
596 : widgets::editors::base * widget )
597 : {
598 0 : QString ToolTip;
599 0 : ToolTip.append (
600 0 : QString ( "Relationship Name: %1 \n" ).arg ( relation.p_name.c_str() ) );
601 0 : ToolTip.append (
602 0 : QString ( " Type: %1 \n" ).arg ( relation.p_type.c_str() ) );
603 0 : ToolTip.append (
604 0 : QString ( " Cardinality %1 \n" ).arg (
605 0 : dunedaq::conffwk::relationship_t::card2str ( relation.p_cardinality ) ) );
606 0 : ToolTip.append (
607 0 : QString ( " Is Aggregation: %1 \n" ).arg ( relation.p_is_aggregation ) );
608 0 : ToolTip.append (
609 0 : QString ( " Description: %1 \n" ).arg ( relation.p_description.c_str() ) );
610 0 : widget->setToolTip ( ToolTip );
611 0 : }
612 :
613 : //------------------------------------------------------------------------------------------
614 :
615 : //------------------------------------------------------------------------------------------
616 0 : void dbe::ObjectEditor::set_attribute_widget ( dunedaq::conffwk::attribute_t const & Attribute,
617 : widgets::editors::base * Widget )
618 : {
619 0 : {
620 0 : QStringList values;
621 :
622 0 : if ( not Widget->ischanged() and m_object_to_edit and not Object().is_null() )
623 : {
624 0 : values = dbe::config::api::get::attribute::list<QStringList> ( Object(), Attribute );
625 : }
626 : else
627 : {
628 0 : values = Widget->getdata();
629 : }
630 :
631 0 : Widget->setdata ( values );
632 0 : }
633 :
634 0 : {
635 0 : QStringList defaults_values
636 0 : { dbe::config::api::get::defaults::attribute::value ( Attribute ) };
637 0 : Widget->setdefaults ( defaults_values.at ( 0 ) );
638 :
639 0 : if ( this_is_in_creation_mode) {
640 0 : Widget->setdata(defaults_values);
641 : }
642 0 : }
643 :
644 0 : Widget->SetEditor();
645 0 : }
646 :
647 : //------------------------------------------------------------------------------------------
648 :
649 : //------------------------------------------------------------------------------------------
650 0 : void dbe::ObjectEditor::register_attribute_widget ( QString const & name,
651 : widgets::editors::base * widget )
652 : {
653 0 : HorizontalHeaders.append(name);
654 0 : WidgetTable->setCellWidget(CurrentRow, 0, widget);
655 :
656 0 : if(dynamic_cast<widgets::editors::multiattr *>(widget)) {
657 0 : WidgetTable->setRowHeight(CurrentRow, 100);
658 0 : } else if(widgets::editors::stringattr * sa = dynamic_cast<widgets::editors::stringattr *>(widget)) {
659 0 : QTextEdit* le = sa->GetLineEdit();
660 0 : const auto& textSize = QFontMetrics(le->document()->defaultFont()).size(0, le->toPlainText());
661 0 : WidgetTable->setRowHeight(CurrentRow, std::min(150, textSize.height() + 15));
662 : } else {
663 0 : WidgetTable->verticalHeader()->setSectionResizeMode(CurrentRow, QHeaderView::Fixed);
664 : }
665 :
666 0 : CurrentRow++;
667 0 : this_widgets[name] = widget;
668 0 : }
669 :
670 : //------------------------------------------------------------------------------------------
671 :
672 : //------------------------------------------------------------------------------------------
673 0 : void dbe::ObjectEditor::register_relation_widget ( QString const & name,
674 : widgets::editors::base * widget )
675 : {
676 0 : HorizontalHeaders.append ( name );
677 0 : WidgetTable->setCellWidget ( CurrentRow, 0, widget );
678 :
679 0 : if(widgets::editors::relation * w = dynamic_cast<widgets::editors::relation *>(widget)) {
680 0 : if(w->GetIsMultiValue() == true) {
681 0 : WidgetTable->setRowHeight(CurrentRow, 100);
682 : } else {
683 0 : WidgetTable->verticalHeader()->setSectionResizeMode(CurrentRow, QHeaderView::Fixed);
684 : }
685 : }
686 :
687 0 : CurrentRow++;
688 0 : this_widgets[name] = widget;
689 0 : }
690 :
691 : //------------------------------------------------------------------------------------------
692 :
693 : //------------------------------------------------------------------------------------------
694 0 : void dbe::ObjectEditor::BuildFileInfo()
695 : {
696 0 : if ( m_object_to_edit and not Object().is_null() )
697 : {
698 0 : QString FileName = QString ( Object().contained_in().c_str() );
699 0 : QList<QStringList> FileCache = confaccessor::ref().GetIncludedFileCache();
700 0 : QFileInfo FileInfo = QFileInfo ( FileName );
701 :
702 0 : for ( QStringList File : FileCache )
703 : {
704 0 : if ( FileName.contains ( File.at ( 1 ) ) )
705 : {
706 0 : FilePermission = File.at ( 2 );
707 0 : break;
708 : }
709 0 : }
710 :
711 0 : ui->FileLabel->setText ( QString ( "File: %1" ).arg ( FileInfo.fileName() ) );
712 0 : ui->DirLabel->setText ( QString ( "Dir: %1" ).arg ( FileInfo.absolutePath() ) );
713 0 : ui->WriteLabel->setText ( QString ( "Permission: %1" ).arg ( FilePermission ) );
714 0 : }
715 0 : }
716 :
717 : //------------------------------------------------------------------------------------------
718 :
719 : //------------------------------------------------------------------------------------------
720 : // void dbe::ObjectEditor::closeEvent ( QCloseEvent * e )
721 : // {
722 : // if ( not this_editor_is_owned and CanCloseWindow() )
723 : // {
724 : // e->accept();
725 : // }
726 : // else if ( this_editor_is_owned )
727 : // {
728 : // e->accept();
729 : // }
730 : // else
731 : // {
732 : // e->ignore();
733 : // }
734 : // }
735 :
736 : //------------------------------------------------------------------------------------------
737 :
738 : //------------------------------------------------------------------------------------------
739 0 : void dbe::ObjectEditor::UpdateActions()
740 : {
741 0 : int NotNullCounter = 0;
742 0 : int NotValidCounter = 0;
743 :
744 0 : QStringList NotValidList;
745 :
746 0 : for ( auto & i : this_widgets )
747 : {
748 0 : std::shared_ptr<editor_data_state> Editor = i.second->dataeditor<editor_data_state>();
749 :
750 0 : if ( Editor != nullptr )
751 : {
752 0 : if ( not Editor->is_valid() )
753 : {
754 0 : NotValidCounter++;
755 0 : NotValidList.append ( i.first );
756 : }
757 :
758 0 : if ( Editor->must_not_be_null() )
759 : {
760 0 : NotNullCounter++;
761 : }
762 : }
763 0 : }
764 :
765 0 : QLabel * StatusLabel = new QLabel();
766 0 : StatusLabel->setWordWrap ( true );
767 0 : StatusLabel->setFrameStyle ( QFrame::NoFrame );
768 :
769 0 : if ( NotValidCounter == 0 )
770 : {
771 0 : StatusLabel->setText (
772 0 : QString ( "All minimal necessary attributes and relationships are set" ) );
773 :
774 0 : if ( this_is_in_copy_mode or this_is_in_creation_mode or
775 0 : confaccessor::check_file_rw ( QString::fromStdString ( Object().contained_in() ) ) )
776 : {
777 0 : ui->ApplyButton->setEnabled ( true );
778 : }
779 :
780 0 : IsValid = true;
781 : }
782 : else
783 : {
784 0 : QString MexHead = QString ( "From %1 NOT NULL attributes/relationships, %2 are not set: " )
785 0 : .arg ( NotNullCounter ).arg ( NotValidCounter );
786 0 : QString Mex = MexHead + NotValidList.join ( "," );
787 0 : StatusLabel->setText ( Mex );
788 :
789 0 : ui->ApplyButton->setEnabled ( false );
790 :
791 0 : IsValid = false;
792 0 : }
793 :
794 : /// This signal will be caught by object editor
795 0 : emit WidgetUpdated();
796 0 : }
797 :
798 : //------------------------------------------------------------------------------------------
799 :
800 : //------------------------------------------------------------------------------------------
801 0 : void dbe::ObjectEditor::ObjectChanged()
802 : {
803 0 : this_editor_values_changed = true;
804 :
805 0 : if ( IsValid and (this_is_in_creation_mode
806 0 : or confaccessor::check_file_rw ( QString::fromStdString ( Object().contained_in() ) ) ))
807 : {
808 0 : ui->ApplyButton->setEnabled ( true );
809 : }
810 0 : }
811 :
812 0 : void dbe::ObjectEditor::ResetObjectChanged()
813 : {
814 0 : this_editor_values_changed = false;
815 0 : ui->ApplyButton->setEnabled ( false );
816 0 : }
817 :
818 : //------------------------------------------------------------------------------------------
819 :
820 : //------------------------------------------------------------------------------------------
821 0 : void dbe::ObjectEditor::ParseToSave()
822 : {
823 0 : if ( FilePermission != "RO" )
824 : {
825 0 : if ( not IsValid )
826 : {
827 0 : ERROR ( "Changes cannot be applied for object", "Changes are invalid", "with UID:",
828 0 : Object().UID(), "of class:", Object().class_name() );
829 0 : return;
830 : }
831 :
832 0 : for ( auto const & i : this_widgets )
833 : {
834 0 : widgets::editors::base * ceditor = i.second;
835 0 : bool Changed = ceditor->ischanged();
836 :
837 0 : if ( Changed || this_is_in_copy_mode )
838 : {
839 0 : QStringList DataList = ceditor->getdata();
840 :
841 0 : if ( auto attreditor = ceditor->dataeditor<editor_data<dunedaq::conffwk::attribute_t>>() )
842 : {
843 0 : dunedaq::conffwk::attribute_t Attribute = attreditor->get();
844 :
845 0 : dbe::config::api::set::attribute ( Object(), Attribute, DataList );
846 0 : ceditor->setdata ( DataList );
847 0 : ceditor->setchanged ( false );
848 0 : }
849 0 : else if ( auto releditor =
850 0 : ceditor->dataeditor<editor_data<dunedaq::conffwk::relationship_t>>() )
851 : {
852 0 : dunedaq::conffwk::relationship_t Relationship = releditor->get();
853 0 : dbe::config::api::set::relation ( Object(), Relationship, DataList );
854 0 : ceditor->setdata ( DataList );
855 0 : ceditor->setchanged ( false );
856 0 : }
857 0 : }
858 : }
859 :
860 0 : MainWindow::findthis()->build_file_model();
861 :
862 0 : ui->ApplyButton->setDisabled ( true );
863 :
864 0 : this_editor_values_changed = false;
865 : }
866 : else
867 : {
868 0 : ERROR ( "Changes cannot be applied", "File access permission error" );
869 : }
870 : }
871 :
872 : //------------------------------------------------------------------------------------------
873 :
874 : //------------------------------------------------------------------------------------------
875 0 : void dbe::ObjectEditor::LaunchRenameObject()
876 : {
877 0 : if ( RenameWidget == nullptr )
878 : {
879 0 : RenameWidget = new QDialog ( this );
880 0 : RenameWidget->setSizePolicy ( QSizePolicy::Preferred, QSizePolicy::Preferred );
881 0 : RenameWidget->setToolTip ( "Type string to edit line and press Enter." );
882 0 : RenameWidget->setWindowTitle ( "Choose a new object id" );
883 :
884 0 : QHBoxLayout * Layout = new QHBoxLayout ( RenameWidget );
885 0 : QLabel * Label = new QLabel ( QString ( "Rename Object:" ), RenameWidget );
886 0 : GoButton = new QPushButton ( "Rename !" );
887 :
888 0 : LineEdit = new QLineEdit ( RenameWidget );
889 0 : LineEdit->setToolTip ( "Type string and press Enter" );
890 :
891 0 : Layout->addWidget ( Label );
892 0 : Layout->addWidget ( LineEdit );
893 0 : Layout->addWidget ( GoButton );
894 0 : RenameWidget->setLayout ( Layout );
895 :
896 0 : connect ( LineEdit, SIGNAL ( returnPressed() ), this, SLOT ( RenameObject() ) );
897 0 : connect ( GoButton, SIGNAL ( clicked() ), this, SLOT ( RenameObject() ) );
898 0 : connect ( &confaccessor::ref(), SIGNAL ( object_renamed ( QString, dref ) ), this,
899 : SLOT ( slot_external_rename_object ( QString, dref ) ) );
900 : }
901 :
902 0 : RenameWidget->show();
903 0 : }
904 :
905 0 : void dbe::ObjectEditor::LaunchMoveObject()
906 : {
907 0 : if ( MoveWidget == nullptr )
908 : {
909 0 : MoveWidget = new QDialog ( this );
910 0 : MoveWidget->setSizePolicy ( QSizePolicy::Preferred, QSizePolicy::Preferred );
911 0 : MoveWidget->setToolTip ( "Choose file and press Move." );
912 0 : MoveWidget->setWindowTitle ( "Choose new file for object" );
913 :
914 0 : QVBoxLayout * Layout = new QVBoxLayout ( MoveWidget );
915 0 : QLabel * Label = new QLabel ( QString ( "Choose new file" ), MoveWidget );
916 0 : MoveGoButton = new QPushButton ( "Move !" );
917 :
918 0 : if ( IncludedFileModel == nullptr )
919 : {
920 0 : QList<QStringList> List = confaccessor::ref().GetIncludedFileCache();
921 0 : IncludedFileModel = new FileModel ( List );
922 0 : }
923 :
924 0 : FileView = new CustomFileView ( MoveWidget );
925 0 : FileView->setModel ( IncludedFileModel );
926 0 : FileView->horizontalHeader()->setSectionResizeMode ( QHeaderView::Stretch );
927 :
928 0 : Layout->addWidget ( Label );
929 0 : Layout->addWidget ( FileView );
930 0 : Layout->addWidget ( MoveGoButton );
931 :
932 0 : MoveWidget->setLayout ( Layout );
933 0 : connect ( FileView, SIGNAL ( stateChanged ( const QString & ) ), this,
934 : SLOT ( ActiveFileChanged ( const QString & ) ), Qt::UniqueConnection );
935 0 : connect ( MoveGoButton, SIGNAL ( clicked() ), this, SLOT ( MoveObject() ) );
936 : }
937 :
938 0 : MoveWidget->show();
939 0 : }
940 :
941 : //------------------------------------------------------------------------------------------
942 :
943 0 : void dbe::ObjectEditor::save_and_close() {
944 0 : if (ui->ApplyButton->isEnabled() ) {
945 0 : ParseToSave();
946 : }
947 0 : close();
948 0 : }
949 :
950 : //------------------------------------------------------------------------------------------
951 0 : void dbe::ObjectEditor::RenameObject()
952 : {
953 0 : std::string newname = LineEdit->text().toStdString();
954 0 : dbe::config::api::commands::renobj ( Object(), newname, uuid );
955 0 : RenameWidget->close();
956 0 : }
957 :
958 0 : void dbe::ObjectEditor::slot_external_rename_object ( QString const & src,
959 : dref const & /* obj */)
960 : {
961 : // Rename can only occur by undoing a command issued from an ObjectEditor therefore
962 : // the uuid and src have to be equal. We also check the UID
963 :
964 0 : if ( src == uuid.toString() )
965 : {
966 0 : ui->ClassLabel->setText (
967 0 : QString ( "Object : %1@%2" ).arg ( Object().UID().c_str() ).arg (
968 0 : Object().class_name().c_str() ) );
969 0 : setWindowTitle (
970 0 : QString ( "Edit Object %1 of Class %2" ).arg ( Object().UID().c_str() ).arg (
971 0 : Object().class_name().c_str() ) );
972 0 : setObjectName (
973 0 : QString ( "%1@%2" ).arg ( Object().UID().c_str() ).arg ( Object().class_name().c_str() ) );
974 : }
975 0 : }
976 :
977 0 : void dbe::ObjectEditor::MoveObject()
978 : {
979 0 : if ( dbe::config::api::commands::movobj ( Object(), ActivateFile.toStdString(), uuid ) )
980 : {
981 0 : ui->FileLabel->setText ( QString ( "File: %1" ).arg ( Object().contained_in().c_str() ) );
982 : }
983 :
984 0 : MoveWidget->close();
985 0 : }
986 :
987 0 : void dbe::ObjectEditor::ActiveFileChanged ( const QString & File )
988 : {
989 0 : if ( File.isEmpty() )
990 : {
991 : return;
992 : }
993 :
994 0 : ActivateFile = File;
995 : }
996 :
997 : //------------------------------------------------------------------------------------------
998 :
999 : //------------------------------------------------------------------------------------------
1000 0 : bool dbe::ObjectEditor::ParseToCreate ( std::string const & objectname,
1001 : std::string const & filename )
1002 : {
1003 0 : if ( not config::api::info::has_obj ( classname, objectname ) )
1004 : {
1005 0 : try
1006 : {
1007 0 : dbe::t_config_object_preimage::type_attrmap object_attributes;
1008 0 : dbe::t_config_object_preimage::type_relmap object_relations;
1009 :
1010 : // Build [attribute , new values ] map and [ relation , new relations ] map
1011 : // by looping through all widgets contained in this objects
1012 :
1013 0 : for ( auto const & awidget : this_widgets )
1014 : {
1015 0 : widgets::editors::base * editor = awidget.second;
1016 :
1017 : // Retrieve data held by the editor
1018 0 : QStringList editordata = editor->getdata();
1019 :
1020 0 : if ( std::shared_ptr<editor_data<dunedaq::conffwk::attribute_t>> accessor =
1021 0 : editor->dataeditor<editor_data<dunedaq::conffwk::attribute_t>>() )
1022 : {
1023 0 : dunedaq::conffwk::attribute_t attribute = accessor->get();
1024 :
1025 : /*
1026 : * Convert to the preimage value type
1027 : */
1028 :
1029 0 : for ( auto const & element : editordata )
1030 : {
1031 0 : object_attributes[attribute.p_name].push_back ( element.toStdString() );
1032 : }
1033 0 : }
1034 0 : else if ( std::shared_ptr<editor_data<dunedaq::conffwk::relationship_t>> accessor =
1035 0 : editor->dataeditor<editor_data<dunedaq::conffwk::relationship_t>>() )
1036 : {
1037 0 : dunedaq::conffwk::relationship_t relation = accessor->get();
1038 :
1039 : /*
1040 : * Convert to the preimage value type
1041 : */
1042 :
1043 0 : for ( auto const & element : editordata )
1044 : {
1045 0 : object_relations[relation.p_name].push_back (
1046 0 : { element.toStdString(), relation.p_type } );
1047 : }
1048 0 : }
1049 :
1050 : // editor->SetValueList(editordata);
1051 0 : editor->setchanged ( false );
1052 0 : }
1053 :
1054 0 : dbe::config::api::commands::newobj (
1055 : filename, classname, objectname,
1056 0 : object_attributes, object_relations, uuid );
1057 :
1058 0 : }
1059 0 : catch ( daq::dbe::ObjectChangeWasNotSuccessful const & e )
1060 : {
1061 0 : ERROR ( "Object creation did not complete successfully", dbe::config::errors::parse ( e ) );
1062 0 : return false;
1063 0 : }
1064 0 : catch ( dunedaq::conffwk::Exception const & e )
1065 : {
1066 0 : ERROR ( "Object could not be created", dbe::config::errors::parse ( e ) );
1067 0 : return false;
1068 0 : }
1069 :
1070 0 : return true;
1071 : }
1072 : else
1073 : {
1074 0 : ERROR ( "Object cannot be created for", "Object already exists", "with name (UID):",
1075 0 : objectname, " in class ", classname );
1076 0 : return false;
1077 : }
1078 : }
1079 :
1080 0 : void dbe::ObjectEditor::SetUsedForCopy ( bool Used )
1081 : {
1082 0 : this_is_in_copy_mode = Used;
1083 0 : }
1084 :
1085 : //------------------------------------------------------------------------------------------
|