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