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