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