DUNE-DAQ
DUNE Trigger and Data Acquisition software
Loading...
Searching...
No Matches
MainWindow.cpp
Go to the documentation of this file.
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/MainWindow.hpp"
11#include "dbe/CommitDialog.hpp"
12#include "dbe/StyleUtility.hpp"
14#include "dbe/Command.hpp"
15#include "dbe/FileInfo.hpp"
16#include "dbe/messenger.hpp"
18#include "dbe/config_api.hpp"
20#include "dbe/subtreeproxy.hpp"
21#include "dbe/treenode.hpp"
22#include "dbe/version.hpp"
23#include "dbe/MyApplication.hpp"
24
25#include "logging/Logging.hpp"
26
27#include <QFileDialog>
28#include <QMessageBox>
29#include <QProgressDialog>
30#include <QTime>
31#include <QUndoStack>
32#include <QSettings>
33#include <QCloseEvent>
34#include <QWhatsThis>
35#include <QDesktopServices>
36#include <QUrl>
37#include <QApplication>
38#include <QItemDelegate>
39
40#include <future>
41#include <thread>
42
43#include <boost/scope_exit.hpp>
44
45
46namespace {
47 // This allows to select data in the cells but to not modify them
48 class DummyEditorDelegate : public QItemDelegate {
49 public:
50 void setModelData(QWidget * /* editor */, QAbstractItemModel * /* model */, const QModelIndex & /* index */) const override {}
51 };
52}
53
54dbe::MainWindow::MainWindow ( QMap<QString, QString> const & cmdargs, QWidget * parent )
55 : QMainWindow ( parent ),
57 this_files ( nullptr ),
58 this_filesort ( new QSortFilterProxyModel ( this ) ),
59 this_classes ( nullptr ),
60 this_treefilter ( nullptr ),
61 isArchivedConf ( false )
62{
63 //qRegisterMetaType<RDBMap>("RDBMap");
64
66 setupUi ( this );
67
69 init();
70 init_tabs();
71 //init_rdb_menu();
72
74 attach();
75
77 load_settings ( false );
78 argsparse ( cmdargs );
79
80 if (isArchivedConf == true) {
81 OpenDB->setEnabled(false);
82 //OpenOracleDB->setEnabled(false);
83 //ConnectToRdb->setEnabled(false);
84 CreateDatabase->setEnabled(false);
85 Commit->setEnabled(false);
86
87 QMessageBox::information(this,
88 "DBE",
89 QString("The configuration is opened in archival/detached mode.")
90 .append("\nYou can browse or modify objects, but changes cannot be saved or commited."));
91 }
92
93 UndoView->show();
94
95}
96
98{
99 tableholder->addTab ( new TableTab ( tableholder ), "Table View" );
100 tableholder->removeTab ( 0 );
101
102 QPushButton * addtab_button = new QPushButton ( "+" );
103 tableholder->setCornerWidget ( addtab_button, Qt::TopLeftCorner );
104 connect ( addtab_button, SIGNAL ( clicked() ), this, SLOT ( slot_add_tab() ) );
105
106 tableholder->setTabsClosable ( true );
107 connect ( tableholder, SIGNAL ( tabCloseRequested ( int ) ), this,
108 SLOT ( slot_remove_tab ( int ) ) );
109}
110
112{
113 tableholder->addTab ( new TableTab ( tableholder ), "Table View" );
114 tableholder->setCurrentIndex ( tableholder->count()-1 );
115 tableholder->show();
116}
117
119{
120 if ( i == -1 || ( ( tableholder->count() == 1 ) && i == 0 ) )
121 {
122 return;
123 }
124
125 QWidget * Widget = tableholder->widget ( i );
126
127 tableholder->removeTab ( i );
128
129 delete Widget;
130
131 Widget = nullptr;
132}
133
134
136{
138 setWindowTitle ( "DUNE DAQ Configuration Database Editor (DBE)" );
140 UndoView->setStack ( confaccessor::get_commands().get() );
141 SearchLineTable->hide();
142 SearchLineTable->setClearButtonEnabled(true);
143 SearchTreeLine->setClearButtonEnabled(true);
144 CaseSensitiveCheckBoxTable->hide();
145 tableholder->removeTab ( 1 );
146
148 HelpMenu->setEnabled ( false ); // Until help is updated to be useful!!!
149
151 Commit->setEnabled ( false );
152 UndoAction->setEnabled ( true );
153 RedoAction->setEnabled ( true );
154
156 SearchBox->setFocusPolicy ( Qt::ClickFocus );
157
159 TreeView->setWhatsThis ( "This view shows the classes and objects of the database" );
160 FileView->setWhatsThis ( "This view shows the file structure of the database" );
161 UndoView->setWhatsThis ( "This view shows the commands in the Undo Command stack" );
162
163 CommittedTable->setHorizontalHeaderLabels(QStringList() << "File" << "Comment" << "Date");
164 CommittedTable->setAlternatingRowColors(true);
165 CommittedTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive);
166 CommittedTable->horizontalHeader()->setDefaultSectionSize(250);
167 CommittedTable->setWordWrap(true);
168 CommittedTable->setTextElideMode(Qt::ElideRight);
169 CommittedTable->setItemDelegate(new DummyEditorDelegate());
170
171 // Make Files the current tab
172 InfoWidget->setCurrentIndex (0);
173
174
177}
178
180{
181 connect ( OpenDB, SIGNAL ( triggered() ), this, SLOT ( slot_open_database_from_file() ) );
182 connect ( Commit, SIGNAL ( triggered() ), this, SLOT ( slot_commit_database() ) );
183 connect ( Exit, SIGNAL ( triggered() ), this, SLOT ( close() ) );
184 connect ( UndoAction, SIGNAL ( triggered() ), UndoView->stack(), SLOT ( undo() ) );
185 connect ( RedoAction, SIGNAL ( triggered() ), UndoView->stack(), SLOT ( redo() ) );
186 connect ( UndoAll, SIGNAL ( triggered() ), this, SLOT ( slot_undo_allchanges() ) );
187 connect ( BatchChange, SIGNAL ( triggered() ), this, SLOT ( slot_launch_batchchange() ) );
188 connect ( BatchChangeTable, SIGNAL ( triggered() ), this,
190
191 connect ( DisplayClassView, SIGNAL ( triggered ( bool ) ), TreeDockWidget,
192 SLOT ( setVisible ( bool ) ) );
193 connect ( DisplayTableView, SIGNAL ( triggered ( bool ) ), TableGroupBox,
194 SLOT ( setVisible ( bool ) ) );
195 connect ( DisplayMessages, SIGNAL ( triggered ( bool ) ), InfoDockWidget,
196 SLOT ( setVisible ( bool ) ) );
197 connect ( DisplayToolbar, SIGNAL ( triggered ( bool ) ), MainToolBar,
198 SLOT ( setVisible ( bool ) ) );
199
200 connect ( TreeDockWidget, SIGNAL ( visibilityChanged ( bool ) ), DisplayTableView,
201 SLOT ( setChecked ( bool ) ) );
202 connect ( InfoDockWidget , SIGNAL ( visibilityChanged ( bool ) ), DisplayMessages,
203 SLOT ( setChecked ( bool ) ) );
204 connect ( MainToolBar , SIGNAL ( visibilityChanged ( bool ) ), DisplayToolbar,
205 SLOT ( setChecked ( bool ) ) );
206
207
208 connect ( LoadDefaultSettings, SIGNAL ( triggered() ), this,
209 SLOT ( LoadDefaultSetting() ) );
210 connect ( CreateDatabase, SIGNAL ( triggered() ), this, SLOT ( slot_create_newdb() ) );
211 //connect ( OpenOracleDB, SIGNAL ( triggered() ), this, SLOT ( slot_oracle_prepare() ) );
212
213 connect ( WhatThisAction, SIGNAL ( triggered() ), this, SLOT ( slot_whatisthis() ) );
214 connect ( UserGuide, SIGNAL ( triggered() ), this, SLOT ( slot_show_userguide() ) );
215 connect ( UserChanges, SIGNAL ( triggered() ), this, SLOT ( slot_show_userchanges() ) );
216
217 connect ( TreeView, SIGNAL ( activated ( QModelIndex ) ), this,
218 SLOT ( slot_edit_object_from_class_view ( QModelIndex ) ) );
219
220 connect( &confaccessor::ref(), SIGNAL(db_committed(const std::list<std::string>&, const std::string&)), this,
221 SLOT(slot_update_committed_files(const std::list<std::string>&, const std::string&)));
222
223 connect ( confaccessor::gethandler().get(), SIGNAL ( FetchMoreData ( const treenode * ) ),
224 this,
225 SLOT ( slot_fetch_data ( const treenode * ) ) );
226
227 connect( &confaccessor::ref(), SIGNAL(object_created(QString, dref)), this,
229 connect( &confaccessor::ref(), SIGNAL(object_renamed(QString, dref)), this,
231 connect( &confaccessor::ref(), SIGNAL(object_changed(QString, dref)), this,
233 connect( &confaccessor::ref(), SIGNAL(object_deleted(QString, dref)), this,
235 connect( &confaccessor::ref(), SIGNAL(db_committed(const std::list<std::string>&, const std::string&)), this,
237 connect( &confaccessor::ref(), SIGNAL(IncludeFileDone()), this,
239 connect( &confaccessor::ref(), SIGNAL(RemoveFileDone()), this,
241 connect( &confaccessor::ref(), SIGNAL(ExternalChangesDetected()), this,
243 connect( &confaccessor::ref(), SIGNAL(ExternalChangesAccepted()), this,
245 connect( this, SIGNAL(signal_batch_change_stopped(const QList<QPair<QString, QString>>&)), this,
247
248 connect ( &confaccessor::ref(), SIGNAL ( IncludeFileDone() ), this,
249 SLOT ( slot_model_rebuild() ) );
250 connect ( &confaccessor::ref(), SIGNAL ( RemoveFileDone() ), this,
251 SLOT ( slot_model_rebuild() ) );
252 connect ( &confaccessor::ref(), SIGNAL ( ExternalChangesAccepted() ), this,
253 SLOT ( slot_process_externalchanges() ) );
254
255
256 connect ( SearchBox, SIGNAL ( currentIndexChanged(int) ), this,
257 SLOT ( slot_filter_query() ) );
258 connect ( SearchTreeLine, SIGNAL ( textChanged ( const QString & ) ), this,
259 SLOT ( slot_filter_textchange ( const QString & ) ) );
260 connect ( SearchTreeLine, SIGNAL ( textEdited ( const QString & ) ), this,
261 SLOT ( slot_filter_query() ) );
262 connect ( SearchTreeLine, SIGNAL ( returnPressed() ), this, SLOT ( slot_filter_query() ) );
263 connect ( SearchLineTable, SIGNAL ( textChanged ( const QString & ) ), this,
264 SLOT ( slot_filter_table_textchange ( const QString & ) ) );
265 connect ( CaseSensitiveCheckBoxTree, SIGNAL ( clicked ( bool ) ), this,
266 SLOT ( slot_toggle_casesensitive_for_treeview ( bool ) ) );
267 //connect ( ConnectToRdb, SIGNAL ( triggered ( QAction * ) ), this,
268 // SLOT ( slot_rdb_selected ( QAction * ) ) );
269
270 connect ( information_about_dbe, SIGNAL ( triggered() ), this,
272
273 // Connect to signals from the messenger system
274
276 SIGNAL ( signal_debug ( QString const, QString const ) ), this,
277 SLOT ( slot_debuginfo_message ( QString , QString ) ), Qt::QueuedConnection );
278
280 SIGNAL ( signal_info ( QString const, QString const ) ), this,
281 SLOT ( slot_information_message ( QString , QString ) ), Qt::QueuedConnection );
282
284 SIGNAL ( signal_note ( QString const, QString const ) ), this,
285 SLOT ( slot_notice_message ( QString , QString ) ), Qt::QueuedConnection );
286
288 SIGNAL ( signal_warn ( QString const, QString const ) ), this,
289 SLOT ( slot_warning_message ( QString , QString ) ), Qt::QueuedConnection );
290
292 SIGNAL ( signal_error ( QString const, QString const ) ), this,
293 SLOT ( slot_error_message ( QString, QString ) ), Qt::QueuedConnection );
294
296 SIGNAL ( signal_fail ( QString const, QString const ) ), this,
297 SLOT ( slot_failure_message ( QString , QString ) ), Qt::QueuedConnection );
298
299 // connect ( this, SIGNAL ( signal_rdb_found(const QString&, const RDBMap& ) ),
300 // this, SLOT ( slot_rdb_found(const QString&, const RDBMap&) ), Qt::AutoConnection );
301}
302
304{
305 QStringList Headers
306 { "Class Name", "# Objects" };
307
308 if ( this_classes != nullptr )
309 {
310 delete this_classes;
311 delete this_treefilter;
312 }
314 this_classes = new dbe::models::tree ( Headers );
317 this_treefilter->setFilterRegExp ( "" );
318
319 connect ( this_classes, SIGNAL ( ObjectFile ( QString ) ),
320 this, SLOT ( slot_loaded_db_file ( QString ) ) );
321
322 this_treefilter->setDynamicSortFilter ( true );
323 this_treefilter->setSourceModel ( this_classes );
325 TreeView->setModel ( this_treefilter );
326 TreeView->setSortingEnabled ( true );
327 TreeView->resizeColumnToContents ( 0 );
328 TreeView->resizeColumnToContents ( 1 );
329
330 connect ( HideCheckBox, SIGNAL ( toggled ( bool ) ), this_treefilter,
331 SLOT ( ToggleEmptyClasses ( bool ) ) );
332
333 connect ( ShowDerivedObjects, SIGNAL ( toggled ( bool ) ), this_classes,
334 SLOT ( ToggleAbstractClassesSelectable ( bool ) ) );
335
337}
338
340{
342 SearchLineTable->clear();
343 SearchLineTable->show();
344 SearchLineTable->setProperty ( "placeholderText", QVariant ( QString ( "Table Filter" ) ) );
345 CaseSensitiveCheckBoxTable->show();
346}
347
348void dbe::MainWindow::edit_object_at ( const QModelIndex & Index )
349{
350 treenode * tree_node = this_classes->getnode ( Index );
351
352 /*
353 * If an object node is linked to this index then launch the object editor
354 * else build a table for the class , showing all objects
355 */
356
357 if ( dynamic_cast<ObjectNode *> ( tree_node ) )
358 {
359 ObjectNode * NodeObject = dynamic_cast<ObjectNode *> ( tree_node );
360 tref ObjectToBeEdited = NodeObject->GetObject();
361 slot_launch_object_editor ( ObjectToBeEdited );
362 }
363 else
364 {
365 // Class node
366 QString const cname = tree_node->GetData ( 0 ).toString();
368 cname.toStdString(),
369 false );
370
371 if ( not cinfo.p_abstract or ShowDerivedObjects->isChecked() )
372 {
373 if ( TableTab * CurrentTab = dynamic_cast<TableTab *> ( tableholder->currentWidget() ) )
374 {
375 CurrentTab->CreateModels();
376 dbe::models::table * CurrentTabModel = CurrentTab->GetTableModel();
377 CustomDelegate * CurrentDelegate = CurrentTab->GetTableDelegate();
378 CustomTableView * CurrentView = CurrentTab->GetTableView();
379
380 connect ( CurrentView, SIGNAL ( OpenEditor ( tref ) ), this,
381 SLOT ( slot_launch_object_editor ( tref ) ), Qt::UniqueConnection );
382 connect ( CurrentDelegate, SIGNAL ( CreateObjectEditorSignal ( tref ) ), this,
383 SLOT ( slot_launch_object_editor ( tref ) ), Qt::UniqueConnection );
384
385 if ( dynamic_cast<ClassNode *> ( tree_node ) )
386 {
387 BOOST_SCOPE_EXIT(CurrentTabModel)
388 {
389 emit CurrentTabModel->layoutChanged();
390 }
391 BOOST_SCOPE_EXIT_END
392
393 emit CurrentTabModel->layoutAboutToBeChanged();
394
395 CurrentTabModel->BuildTableFromClass ( cname, ShowDerivedObjects->isChecked() );
397 tableholder->setTabText ( tableholder->currentIndex(), cname );
398 CurrentTab->ResetTableView();
399 }
400
401 CurrentTab->ResizeHeaders();
402 }
403 }
404 }
405}
406
407
409{
411
412 if ( !confaccessor::db_implementation_name().contains ( "roksconflibs" ) )
413 {
414 if ( this_files != nullptr ) {
415 delete this_files;
416 }
417 this_files = new FileModel();
418
419 this_filesort.setSourceModel ( this_files );
420 FileView->setModel ( &this_filesort );
421
422 FileView->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
423 FileView->horizontalHeader()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
424 FileView->horizontalHeader()->setSectionResizeMode(2, QHeaderView::ResizeToContents);
425 FileView->horizontalHeader()->setSectionResizeMode(3, QHeaderView::ResizeToContents);
426
428 }
429}
430
431
433{
434 if ( this_classes->canFetchMore ( this_classes->index ( ClassNode->GetRow(), 0,
435 QModelIndex() ) ) )
436 {
437 this_classes->fetchMore ( this_classes->index ( ClassNode->GetRow(), 0, QModelIndex() ) );
438 }
439}
440
442{
443 CommitDialog * SaveDialog = new CommitDialog();
444 int DialogResult = SaveDialog->exec();
445
446 if ( DialogResult )
447 {
449 for (auto file : dbe::confaccessor::uncommitted_files()) {
450 auto message = FileInfo::check_file_includes(QString::fromStdString(file));
451 if (!message.isEmpty()) {
452 QMessageBox::warning ( 0, "Save database", message );
453 FileInfo::show_file_info(QString::fromStdString(file));
454 return false;
455 }
456 }
457
458 QString CommitMessage = SaveDialog->GetCommitMessage();
459
460 try
461 {
462 std::list<std::string> const & modified = confaccessor::save ( CommitMessage );
464
466
467 if ( not modified.empty() )
468 {
469 std::string msg;
470
471 for ( std::string const & f : modified )
472 {
473 msg += "\n" + f;
474 }
475
476 INFO ( "List of modified files committed to the database ", "Program execution success",
477 msg );
478 }
479 else
480 {
481 WARN ( "Changes where committed successfully but list of modified files could not be retrieved",
482 "Unexpected program execution" );
483 }
484
485 }
486 catch ( dunedaq::conffwk::Exception const & e )
487 {
488 WARN ( "The changes could not be committed", dbe::config::errors::parse ( e ).c_str() )
489 ers::error ( e );
490 return false;
491 }
492 // Gaahhh confaccessor catches dunedaq::conffwk::Exception and
493 // rethrows it as daq::dbe::CouldNotCommitChanges!!
494 catch (daq::dbe::CouldNotCommitChanges const& exc)
495 {
496 std::string reason{exc.what()};
497 auto cause = exc.cause();
498 while (cause != nullptr) {
499 reason = cause->what();
500 cause = cause->cause();
501 }
502 WARN ("The changes could not be committed",
503 // dbe::config::errors::parse(exc).c_str(),
504 reason,
505 "\n\nTry fixing includes from File Info window")
506 ers::error (exc);
507 return false;
508 }
509 }
510 else
511 {
512 if ( Exit )
513 {
515 }
516 }
517 return true;
518}
519
521{
522 try
523 {
525 {
528 }
529 }
530 catch ( dunedaq::conffwk::Exception const & e )
531 {
532 ERROR ( "Database changes aborted", dbe::config::errors::parse ( e ).c_str() );
533 ers::error ( e );
534 }
535}
536
538{
539 try
540 {
542 {
544 }
545 }
546 catch ( dunedaq::conffwk::Exception const & e )
547 {
548 ERROR ( "External changes aborted", dbe::config::errors::parse ( e ).c_str() );
549 ers::error ( e );
550 }
551}
552
554{
555 bool WidgetFound = false;
556 QString ObjectEditorName = QString ( "%1@%2" ).arg ( Object.UID().c_str() ).arg (
557 Object.class_name().c_str() );
558
559 for ( QWidget * Editor : QApplication::allWidgets() )
560 {
561 ObjectEditor * Widget = dynamic_cast<ObjectEditor *> ( Editor );
562
563 if ( Widget != nullptr )
564 {
565 if ( ( Widget->objectName() ).compare ( ObjectEditorName ) == 0 )
566 {
567 Widget->raise();
568 Widget->setVisible ( true );
569 WidgetFound = true;
570 }
571 }
572 }
573
574 if ( !WidgetFound )
575 {
576 ( new ObjectEditor ( Object ) )->show();
577 }
578}
579
581{
583 {
584 BatchChangeWidget * Batch = new BatchChangeWidget ( nullptr );
585 Batch->setWindowModality ( Qt::WindowModal );
586 Batch->show();
587 }
588 else
589 {
590 ERROR ( "Database must have been loaded", "No database loaded" );
591 }
592}
593
595{
597 {
598 ERROR ( "Database must have been loaded", "No database loaded" );
599 return;
600 }
601
602 dbe::models::table * CurrentTableModel = nullptr;
603 TableTab * CurrentTab = dynamic_cast<TableTab *> ( tableholder->currentWidget() );
604 if ( CurrentTab ) {
605 CurrentTableModel = CurrentTab->GetTableModel();
606 }
607
608 std::vector<dref> TableObject;
609
610 if ( !CurrentTab || !CurrentTableModel )
611 {
612 ERROR ( "Table cannot be processed", "Table is empty" );
613 return;
614 }
615
616 if ( ( *CurrentTableModel->GetTableObjects() ).isEmpty() )
617 {
618 ERROR ( "Table cannot be processed", "Table is empty" );
619 return;
620 }
621
622 QString Filter = SearchLineTable->text();
623
624 for ( dref Object : *CurrentTableModel->GetTableObjects() )
625 {
626 if ( Filter.isEmpty() )
627 {
628 TableObject.push_back ( Object );
629 }
630 else
631 {
632 QString ObjectString = QString::fromStdString ( Object.UID() );
633
634 if ( ObjectString.contains ( Filter, Qt::CaseInsensitive ) )
635 {
636 TableObject.push_back ( Object );
637 }
638 }
639 }
640
642 true,
643 CurrentTableModel->get_class_name(),
644 TableObject, nullptr );
645 Batch->setWindowModality ( Qt::WindowModal );
646 Batch->show();
647}
648
653
655{
656 if (confaccessor::dbfullname().isEmpty()) {
657 return "";
658 }
659
661 for(QString f : allFiles) {
662 for(const QString& j : incs) {
663 if(f.endsWith(j)) {
664 return f.remove(j);
665 }
666 }
667 }
668
669 return "";
670}
671
673{
674
675 CreateDatabaseWidget * CreateDatabaseW = new CreateDatabaseWidget(nullptr, false, find_db_repository_dir());
676 CreateDatabaseW->show();
677 connect ( CreateDatabaseW, SIGNAL ( CanLoadDatabase ( const QString & ) ), this,
678 SLOT ( slot_load_db_from_create_widget ( const QString & ) ) );
679}
680
681void dbe::MainWindow::slot_load_db_from_create_widget ( const QString & DatabaseName )
682{
683 if ( !DatabaseName.isEmpty() )
684 {
685 QFileInfo DatabaseFile = QFileInfo ( DatabaseName );
686
687 if ( DatabaseFile.exists() )
688 {
689 QString Path = QString ( DatabaseFile.absoluteFilePath() );
690
691 if ( dbreload() )
692 {
694
695 if ( dbload() )
696 {
697 setinternals();
699 // // build_partition_tree_model();
700 // build_resource_tree_model();
702 }
703 }
704 }
705 else
706 {
707 WARN ( "File not found during database load", "File does not exist", "\n\n Filename:",
708 DatabaseFile.fileName().toStdString() );
709 }
710 }
711 else
712 {
713 ERROR ( "Database load error", "File was not selected" );
714 }
715}
716
718{
720 {
721 QMessageBox MessageBox;
722 MessageBox.setText (
723 "Do you really wish to abandon the current database and load a new one ?" );
724 MessageBox.setStandardButtons ( QMessageBox::Yes | QMessageBox::Cancel );
725 MessageBox.setDefaultButton ( QMessageBox::Cancel );
726 int UserOption = MessageBox.exec();
727
728 switch ( UserOption )
729 {
730
731 case QMessageBox::Yes:
732 return true;
733
734 case QMessageBox::Cancel:
735 return false;
736
737 default:
738 return false;
739 }
740 }
741 else
742 {
743 return true;
744 }
745}
746
748{
749 // For issues related to loading the configuration in a separate thread, see ATLASDBE-229
750
751 const bool alreadyLoaded = confaccessor::is_database_loaded();
752
753 // The QueuedConnection is mandatory to let the loop receive the signal even if
754 // it is emitted before "exec" is called
755 QEventLoop loop;
756 connect(this, SIGNAL(signal_db_loaded()), &loop, SLOT(quit()), Qt::QueuedConnection);
757
758 // Make life of the progress dialog longer
759 // Show only the first time, when the configuration is not loaded
760 // In other cases, just show a busy cursor
761 std::unique_ptr<QProgressDialog> progress_bar;
762 if(!alreadyLoaded) {
763 progress_bar.reset(new QProgressDialog( "Loading Configuration...", QString(), 0, 0, this ));
764 progress_bar->setWindowModality ( Qt::WindowModal );
765 progress_bar->show();
766 }
767
768 BOOST_SCOPE_EXIT(void)
769 {
770 QApplication::restoreOverrideCursor();
771 }
772 BOOST_SCOPE_EXIT_END
773
774 QApplication::setOverrideCursor ( QCursor ( Qt::WaitCursor ) );
775
776 // Close widgets
777 for ( QWidget * widget : QApplication::allWidgets() )
778 {
779 if ( dynamic_cast<ObjectEditor *> ( widget ) )
780 {
781 widget->close();
782 }
783 else if ( dynamic_cast<widgets::editors::base *> ( widget ) )
784 {
785 widget->close();
786 }
787 }
788
789 // Asynchronous execution only the first time the configuration is loaded
790 std::future<bool> waiter = std::async ( alreadyLoaded ? std::launch::deferred : std::launch::async, [this]
791 {
792 const bool result = confaccessor::load(!isArchivedConf);
793 emit signal_db_loaded(); // "loop.exec()" will return now
794 return result;
795 } );
796
797
798 // Do not call "exec" if the previous call is not asynchronous
799 if(!alreadyLoaded) {
800 loop.exec(QEventLoop::ExcludeUserInputEvents);
801 }
802
803 // If "deferred", the async call is executed now and here
804 return waiter.get();
805}
806
808{
810 confaccessor::gethandler()->ResetData();
812
814
815 for ( int i = 0; i < tableholder->count(); i++ )
816 {
817 TableTab * CurrentTab = dynamic_cast<TableTab *> ( tableholder->widget ( i ) );
818 if ( CurrentTab ) {
819 CurrentTab->DisconnectView();
820 }
821 }
822
823 FileView->setModel ( NULL );
824}
825
826void dbe::MainWindow::load_settings ( bool LoadSettings )
827{
829 QSettings * Settings;
830 QString userPath = QDir::homePath() + "/.conffwk/ATLAS_TDAQ_DBE";
831 QString userFile = "DBE_User_Settings.conf";
832
833 if ( !LoadSettings )
834 {
835 if ( QDir ( userPath ).exists ( userFile ) )
836 Settings = new QSettings ( "ATLAS_TDAQ_DBE",
837 "DBE_User_Settings" );
838 else
839 Settings = new QSettings ( ":theme/DBE_Default_User_Settings.conf",
840 QSettings::NativeFormat );
841 }
842 else
843 {
844 Settings = new QSettings ( ":theme/DBE_Default_User_Settings.conf",
845 QSettings::NativeFormat );
846 }
847
848 Settings->beginGroup ( "MainWindow-layout" );
849 resize ( Settings->value ( "size" ).toSize() );
850 move ( Settings->value ( "pos" ).toPoint() );
851 DisplayTableView->setChecked ( Settings->value ( "TableView" ).toBool() );
852 DisplayClassView->setChecked ( Settings->value ( "ClassView" ).toBool() );
853
854 DisplayMessages->setChecked ( Settings->value ( "Messages" ).toBool() );
855 restoreGeometry ( Settings->value ( "geometry" ).toByteArray() );
856 restoreState ( Settings->value ( "state" ).toByteArray() );
857 Settings->endGroup();
858
859 Settings->beginGroup ( "MainWindow-checkboxes" );
860 CaseSensitiveCheckBoxTree->setChecked (
861 Settings->value ( "tree-case-sensitive" ).toBool() );
862 CaseSensitiveCheckBoxTable->setChecked (
863 Settings->value ( "table-case-sensitive" ).toBool() );
864 Settings->endGroup();
865}
866
868{
869 QSettings Settings ( "ATLAS_TDAQ_DBE", "DBE_User_Settings" );
870 Settings.beginGroup ( "MainWindow-layout" );
871 Settings.setValue ( "size", size() );
872 Settings.setValue ( "pos", pos() );
873 Settings.setValue ( "TableView", DisplayTableView->isChecked() );
874 Settings.setValue ( "ClassView", DisplayClassView->isChecked() );
875
876 Settings.setValue ( "Messages", DisplayMessages->isChecked() );
877 Settings.setValue ( "geometry", saveGeometry() );
878 Settings.setValue ( "state", saveState() );
879 Settings.endGroup();
880
881 Settings.beginGroup ( "MainWindow-checkboxes" );
882 Settings.setValue ( "tree-case-sensitive", CaseSensitiveCheckBoxTree->isChecked() );
883 Settings.setValue ( "table-case-sensitive", CaseSensitiveCheckBoxTable->isChecked() );
884 Settings.endGroup();
885}
886
887void dbe::MainWindow::argsparse ( QMap<QString, QString> const & opts )
888{
889 if ( !opts.isEmpty() )
890 {
891 dbinfo LoadConfig;
892 QString FileToLoad;
893
894 QString FileName = opts.value ( "f" );
895 QString RdbFileName = opts.value ( "r" );
896 QString RoksFileName = opts.value ( "o" );
897 QString HashVersion = opts.value ( "v" );
898
899 if ( !FileName.isEmpty() )
900 {
901 FileToLoad = FileName;
902 LoadConfig = dbinfo::oks;
903
904 if ( !HashVersion.isEmpty() )
905 {
906 ::setenv("TDAQ_DB_VERSION", QString("hash:").append(HashVersion).toStdString().c_str(), 1);
907 ::setenv("OKS_GIT_PROTOCOL", "http", 1);
908 isArchivedConf = true;
909 }
910 }
911 else if ( !RdbFileName.isEmpty() )
912 {
913 FileToLoad = RdbFileName;
914 LoadConfig = dbinfo::rdb;
915 }
916 else if ( !RoksFileName.isEmpty() )
917 {
918 FileToLoad = RoksFileName;
919 LoadConfig = dbinfo::roks;
920 }
921
922 if ( not FileToLoad.isEmpty() )
923 {
924 dbopen ( FileToLoad, LoadConfig );
925 }
926 }
927}
928
929// /**
930// * Create Rdb menu based on the available Rdb information
931// */
932// void dbe::MainWindow::init_rdb_menu()
933// {
934// ConnectToRdb->clear();
935
936// std::list<IPCPartition> pl;
937// IPCPartition::getPartitions(pl);
938// TLOG_DEBUG(1) << "Found " << pl.size() << " partitions" ;
939
940// pl.push_front(IPCPartition("initial"));
941
942// auto f = [pl, this] () {
943// for ( auto it = pl.begin(); it != pl.end(); ++it )
944// {
945// lookForRDBServers ( *it );
946// }
947// };
948
949// std::thread t(f);
950// t.detach();
951// }
952
953// void dbe::MainWindow::slot_rdb_found(const QString& p, const RDBMap& rdbs) {
954// QMenu * part_menu = new QMenu(p);
955
956// for(auto it = rdbs.begin(); it != rdbs.end(); ++it) {
957// QAction * newAct = new QAction ( it.key(), part_menu );
958
959// QFont actFont = newAct->font();
960// if(it.value() == true) {
961// newAct->setToolTip ( QString ( "This is a Read-Only instance of the DB" ) );
962// actFont.setItalic ( true );
963// } else {
964// newAct->setToolTip ( QString ( "This is a Read/Write instance of the DB" ) );
965// actFont.setBold ( true );
966// }
967
968// newAct->setFont ( actFont );
969
970// part_menu->addAction ( newAct );
971// }
972
973// ConnectToRdb->addMenu ( part_menu );
974// }
975
976// /**
977// * Add rdb servers for each partition
978// *
979// * @param p is the partition source for which to populate with server information
980// */
981// void dbe::MainWindow::lookForRDBServers ( const IPCPartition & p )
982// {
983// TLOG_DEBUG(2) << "dbe::MainWindow::addRDBServers()" ;
984
985// if ( p.isValid() )
986// {
987// TLOG_DEBUG(2) << "Inserting partition = " << p.name() ;
988
989// RDBMap rdbs;
990
991// try
992// {
993// {
994// std::map<std::string, rdb::cursor_var> objects;
995// p.getObjects<rdb::cursor, ::ipc::use_cache, ::ipc::unchecked_narrow> ( objects );
996// std::map<std::string, rdb::cursor_var>::iterator rdb_it = objects.begin();
997
998// while ( rdb_it != objects.end() )
999// {
1000// TLOG_DEBUG(2) << "Found server : " << rdb_it->first ;
1001
1002// rdbs.insert(QString::fromStdString(rdb_it->first), true);
1003
1004// ++rdb_it;
1005// }
1006// }
1007
1008// {
1009// std::map<std::string, rdb::writer_var> objects;
1010// p.getObjects<rdb::writer, ::ipc::use_cache, ::ipc::unchecked_narrow> ( objects );
1011// std::map<std::string, rdb::writer_var>::iterator rdb_it = objects.begin();
1012
1013// while ( rdb_it != objects.end() )
1014// {
1015// TLOG_DEBUG(2) << "Found server : " << rdb_it->first ;
1016
1017// rdbs.insert(QString::fromStdString(rdb_it->first), false);
1018
1019// ++rdb_it;
1020// }
1021// }
1022// }
1023// catch ( daq::ipc::InvalidPartition& e )
1024// {
1025// ers::error ( e );
1026// }
1027
1028// if(rdbs.isEmpty() == false) {
1029// emit signal_rdb_found (QString::fromStdString(p.name()), rdbs);
1030// }
1031// }
1032// }
1033
1034// void dbe::MainWindow::slot_rdb_selected ( QAction * action )
1035// {
1036// QMenu * parentMenu = qobject_cast<QMenu *> ( action->parent() );
1037
1038// if ( parentMenu )
1039// {
1040// if ( dbreload() )
1041// {
1042// BOOST_SCOPE_EXIT(void)
1043// {
1044// QApplication::restoreOverrideCursor();
1045// }
1046// BOOST_SCOPE_EXIT_END
1047
1048// QApplication::setOverrideCursor(Qt::WaitCursor);
1049
1050// confaccessor::setdbinfo ( action->text() + "@" + parentMenu->title(), dbinfo::rdb );
1051
1052// if ( dbload() )
1053// {
1054// setinternals();
1055// build_class_tree_model();
1056// build_partition_tree_model();
1057// build_resource_tree_model();
1058// build_file_model();
1059// }
1060// }
1061// }
1062// }
1063
1064// void dbe::MainWindow::slot_oracle_prepare()
1065// {
1066// if ( this_oraclewidget == nullptr )
1067// {
1068// this_oraclewidget = new OracleWidget();
1069// connect ( this_oraclewidget, SIGNAL ( OpenOracleConfig ( const QString & ) ), this,
1070// SLOT ( slot_load_oracle ( const QString & ) ) );
1071// }
1072
1073// this_oraclewidget->raise();
1074// this_oraclewidget->show();
1075// }
1076
1077// void dbe::MainWindow::slot_load_oracle ( const QString & OracleDatabase )
1078// {
1079// if ( dbreload() )
1080// {
1081// confaccessor::setdblocation ( OracleDatabase );
1082
1083// if ( dbload() )
1084// {
1085// setinternals();
1086// build_class_tree_model();
1087// build_partition_tree_model();
1088// build_resource_tree_model();
1089// build_file_model();
1090// }
1091// }
1092
1093// if ( this_oraclewidget != nullptr )
1094// {
1095// this_oraclewidget->close();
1096// }
1097// }
1098
1100{
1101 QWhatsThis::enterWhatsThisMode();
1102}
1103
1105{
1106 static QString const title ( "About DBE" );
1107 static QString const msg = QString().
1108 append ( "DBE is an editor to work with OKS and RDB backends that manages most of the hard work for you in editing the configuration database\n" ).
1109 append ( "\n\nMaintained :\t\tC&C Working group \n\t\t\t(atlas-tdaq-cc-wg@cern.ch)" ).
1110 append ( "\nProgram version:\t\t" ).append ( dbe_compiled_version ).
1111 append ( "\nLibraries version:\t" ).
1112 append ( "\n\t\t\tdbecore(" ).append ( dbe_lib_core_version ).
1113 append ( "),\n\t\t\tdbe_config_api(" ).append ( dbe_lib_config_api_version ).
1114 append ( "),\n\t\t\tdbe_structure(" ).append ( dbe_lib_structure_version ).
1115 append ( "),\n\t\t\tdbe_internal(" ).append ( dbe_lib_internal_version ).append ( ')' ).
1116 append ( "\nRepo commit hash:\t" ).append ( dbe_compiled_commit );
1117
1118 QMessageBox::about ( this, title, msg );
1119}
1120
1122{
1123 QDesktopServices::openUrl ( QUrl ( "https://atlasdaq.cern.ch/dbe/" ) );
1124}
1125
1127{
1128 InfoWidget->setCurrentIndex ( InfoWidget->indexOf ( CommitedTab ) );
1129}
1130
1132{
1133 UndoView->stack()->setIndex ( 0 );
1134}
1135
1137{
1138 if ( CaseSensitiveCheckBoxTree->isChecked() )
1139 this_treefilter->setFilterCaseSensitivity (
1140 Qt::CaseSensitive );
1141 else
1142 {
1143 this_treefilter->setFilterCaseSensitivity ( Qt::CaseInsensitive );
1144 }
1146}
1147
1149{
1151 confaccessor::gethandler()->ResetData();
1154
1155 for ( int i = 0; i < tableholder->count(); i++ )
1156 {
1157 TableTab * CurrentTab = dynamic_cast<TableTab *> ( tableholder->widget ( i ) );
1158 if( CurrentTab ) {
1159 CurrentTab->DisconnectView();
1160 }
1161 }
1162
1163 FileView->setModel ( NULL );
1164
1167}
1168
1169void dbe::MainWindow::slot_filter_textchange ( const QString & FilterText )
1170{
1171 if ( this_treefilter != nullptr and SearchBox->currentIndex() != 1 )
1172 {
1174
1175 if ( SearchBox->currentIndex() == 2 )
1176 {
1177 this_treefilter->SetFilterRestrictionLevel ( 1000 );
1178 }
1179 else
1180 {
1181 this_treefilter->SetFilterRestrictionLevel ( 1 );
1182 }
1183
1184 this_treefilter->setFilterRegExp ( FilterText );
1185 }
1186
1188}
1189
1191{
1192 if ( this_treefilter == nullptr )
1193 {
1194 return;
1195 }
1196
1197 QString Tmp = SearchTreeLine->text();
1198 if ( SearchBox->currentIndex() == 1 )
1199 {
1201 std::vector<dbe::tref> Objects = ProcessQuery ( Tmp );
1202
1203 this_treefilter->SetQueryObjects ( Objects );
1204 this_treefilter->setFilterRegExp ( Tmp );
1206 }
1207 else {
1208 this_treefilter->ResetQueryObjects ( );
1210 }
1211}
1212
1213void dbe::MainWindow::slot_filter_table_textchange ( const QString & FilterText )
1214{
1215 TableTab * CurrentTab = dynamic_cast<TableTab *> ( tableholder->currentWidget() );
1216
1217 if ( CurrentTab )
1218 {
1219 dbe::models::tableselection * TableFilter = CurrentTab->GetTableFilter();
1220
1221 if ( TableFilter == nullptr )
1222 {
1223 return;
1224 }
1225
1227
1228 if ( CaseSensitiveCheckBoxTable->isChecked() )
1229 TableFilter->setFilterCaseSensitivity (
1230 Qt::CaseSensitive );
1231 else
1232 {
1233 TableFilter->setFilterCaseSensitivity ( Qt::CaseInsensitive );
1234 }
1235
1236 TableFilter->setFilterRegExp ( FilterText );
1237 }
1238}
1239
1241{
1242 // Keep track of the selected tab
1243 int IndexOfCurrentTab = tableholder->currentIndex();
1244
1245 // Here are the all the open tabs
1246 std::vector<QModelIndex> idxs;
1247
1248 for(int i = 0; i < tableholder->count(); ++i) {
1249 TableTab * CurrentTab = dynamic_cast<TableTab *>(tableholder->widget(i));
1250 if(CurrentTab) {
1251 if(CurrentTab->GetTableModel()) {
1252 const QString& TableClassName = CurrentTab->GetTableModel()->get_class_name();
1253 if(!TableClassName.isEmpty()) {
1254 treenode * NodeClass = confaccessor::gethandler()->getnode(TableClassName);
1255 if(NodeClass != nullptr) {
1256 idxs.push_back(this_classes->getindex(NodeClass));
1257 }
1258 }
1259 }
1260 }
1261 }
1262
1263 // Remove all the tabs
1264 while(tableholder->count() != 0) {
1265 tableholder->widget(0)->deleteLater();
1266 tableholder->removeTab(0);
1267 }
1268
1269 // Disconnecting models from views
1271
1272 // Re-create all the tabs
1273 for(const auto& idx : idxs) {
1274 slot_add_tab();
1275 edit_object_at(idx);
1276 }
1277
1278 // Set the current tab
1279 tableholder->setCurrentIndex ( IndexOfCurrentTab );
1280}
1281
1283{
1284 int total=0;
1285 for (int item=0; item<this_treefilter->rowCount(); item++) {
1286 auto index = this_treefilter->index(item, 1);
1287 auto data = this_treefilter->data(index);
1288 total += data.toInt();
1289 }
1290 TotalObjectsLabel->setText (
1291 QString ( "Total Objects: %1" ).arg ( total ) );
1292}
1293
1294void dbe::MainWindow::closeEvent ( QCloseEvent * event )
1295{
1296 if ( isArchivedConf || check_close() )
1297 {
1298 WriteSettings();
1299
1300 foreach ( QWidget * widget, QApplication::allWidgets() ) widget->close();
1301
1302 event->accept();
1303 }
1304 else
1305 {
1306 event->ignore();
1307 }
1308}
1309
1310std::vector<dbe::tref> dbe::MainWindow::ProcessQuery ( QString const & Tmp )
1311{
1312 if ( not Tmp.isEmpty() )
1313 {
1314 QString const Query = QString ( "(this (object-id \".*%1.*\" ~=))" ).arg ( Tmp );
1315
1316 try
1317 {
1318 std::vector<dbe::tref> result;
1319
1320 for ( std::string const & cname : dbe::config::api::info::onclass::allnames <
1321 std::vector<std::string >> () )
1322 {
1323 std::vector<dbe::tref> class_matching_objects = inner::dbcontroller::gets (
1324 cname, Query.toStdString() );
1325
1326 result.insert ( result.end(), class_matching_objects.begin(),
1327 class_matching_objects.end() );
1328 }
1329
1330 return result;
1331 }
1332 catch ( dunedaq::conffwk::Exception const & ex )
1333 {
1334 ers::error ( ex );
1335 ERROR ( "Query process error", dbe::config::errors::parse ( ex ).c_str() );
1336 }
1337 }
1338
1339 return
1340 {};
1341}
1342
1343bool dbe::MainWindow::eventFilter ( QObject * Target, QEvent * Event )
1344{
1345 if ( Target == SearchBox->lineEdit() && Event->type() == QEvent::MouseButtonRelease )
1346 {
1347 if ( !SearchBox->lineEdit()->hasSelectedText() )
1348 {
1349 SearchBox->lineEdit()->selectAll();
1350 return true;
1351 }
1352 }
1353
1354 return false;
1355}
1356
1358{
1359 bool OK = true;
1360
1361 foreach ( QWidget * widget, QApplication::allWidgets() )
1362 {
1363 ObjectCreator * ObjectCreatorInstance = dynamic_cast<ObjectCreator *> ( widget );
1364 ObjectEditor * ObjectEditorInstance = dynamic_cast<ObjectEditor *> ( widget );
1365
1366 if ( ObjectEditorInstance )
1367 {
1368 OK = ObjectEditorInstance->CanCloseWindow();
1369 }
1370
1371 if ( !OK )
1372 {
1373 return false;
1374 }
1375
1376 if ( ObjectCreatorInstance )
1377 {
1378 OK = ObjectCreatorInstance->CanClose();
1379 }
1380
1381 if ( !OK )
1382 {
1383 return false;
1384 }
1385 }
1386
1387 {
1389
1390 if ( undo_stack->isClean() )
1391 {
1392 if ( undo_stack->count() == 0 )
1393 {
1394 return true;
1395 }
1396 else
1397 {
1399 return true;
1400 }
1401 }
1402 else
1403 {
1404 int ret =
1405 QMessageBox::question (
1406 0,
1407 tr ( "DBE" ),
1408 QString (
1409 "There are unsaved changes.\n\nDo you want to save and commit them to the DB?\n" ),
1410 QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel,
1411 QMessageBox::Save );
1412
1413 if ( ret == QMessageBox::Discard )
1414 {
1416 return true;
1417 }
1418 else if ( ret == QMessageBox::Save )
1419 {
1420 return slot_commit_database ( true );
1421 }
1422 else if ( ret == QMessageBox::Cancel )
1423 {
1424 return false;
1425 }
1426 else
1427 {
1428 return true;
1429 }
1430 }
1431 }
1432}
1433
1434void dbe::MainWindow::slot_edit_object_from_class_view ( QModelIndex const & ProxyIndex )
1435{
1436 edit_object_at ( this_treefilter->mapToSource ( ProxyIndex ) );
1437}
1438
1444bool dbe::MainWindow::dbopen ( QString const & dbpath, dbinfo const & loadtype )
1445{
1446 if ( dbreload() )
1447 {
1448 confaccessor::setdbinfo ( dbpath, loadtype );
1449
1450 BOOST_SCOPE_EXIT(void)
1451 {
1452 QApplication::restoreOverrideCursor();
1453 }
1454 BOOST_SCOPE_EXIT_END
1455
1456 QApplication::setOverrideCursor(Qt::WaitCursor);
1457
1458 if ( dbload() )
1459 {
1460 setinternals();
1462 // build_partition_tree_model();
1463 // build_resource_tree_model();
1465 }
1466 }
1467
1468 return true;
1469}
1470
1472{
1473 QFileDialog FileDialog ( this, tr ( "Open File" ), ".", tr ( "XML files (*.xml)" ) );
1474 FileDialog.setAcceptMode ( QFileDialog::AcceptOpen );
1475 FileDialog.setFileMode ( QFileDialog::ExistingFile );
1476 FileDialog.setViewMode ( QFileDialog::Detail );
1477
1478 if ( FileDialog.exec() )
1479 {
1480 QStringList FilesSelected = FileDialog.selectedFiles();
1481
1482 if ( FilesSelected.size() )
1483 {
1484 QString DatabasePath = FilesSelected.value ( 0 );
1485 dbopen ( DatabasePath, dbinfo::oks );
1486 }
1487 }
1488}
1489
1490
1502{
1503 auto user_confirmation = [] ( QString const & msg )
1504 {
1505 QMessageBox ExternalMessageBox;
1506 ExternalMessageBox.setText ( msg );
1507 ExternalMessageBox.setStandardButtons ( QMessageBox::Yes | QMessageBox::No );
1508 ExternalMessageBox.setDefaultButton ( QMessageBox::Yes );
1509 return ExternalMessageBox.exec() == QMessageBox::Yes;
1510 };
1511
1513
1514 auto rewind_stack = [&undo_stack] ()
1515 {
1516 std::vector<bool > commands_original_undo_state;
1517
1518 // Loop over the commands and set their undo-state to false such that when the undostack
1519 // index is rewind to zero they will not be undone. The purpose is to replay them on top of
1520 // current changes.
1521
1522 for ( int i = 0; i < undo_stack->count(); ++i )
1523 {
1524 if ( dbe::actions::onobject const * Command =
1525 dynamic_cast<dbe::actions::onobject const *> ( undo_stack->command ( i ) )
1526 )
1527 {
1528 commands_original_undo_state.push_back ( Command->undoable() );
1529 Command->setundoable ( false );
1530 }
1531 }
1532
1533 // Rewind the command stack by setting the index to zero
1534 // Commands will not be replayed since we have set their state to false
1535 undo_stack->setIndex ( 0 );
1536
1537 // Reset the state of all commands one by one
1538 {
1539 auto cmdstate = commands_original_undo_state.begin();
1540
1541 for ( int i = 0; i != undo_stack->count(); ++i )
1542 {
1543 if ( dbe::actions::onobject const * Command =
1544 dynamic_cast<dbe::actions::onobject const *> ( undo_stack->command ( i ) )
1545 )
1546 {
1547 Command->setundoable ( *cmdstate++ );
1548 }
1549 }
1550 }
1551 };
1552
1553 // Close active editor widgets before replaying changes
1554 for ( QWidget * widget : QApplication::allWidgets() )
1555 {
1556 if ( dynamic_cast<widgets::editors::relation *> ( widget ) )
1557 {
1558 widget->close();
1559 }
1560 }
1561
1562
1563 if ( undo_stack->count() != 0 )
1564 {
1565 const QString msg = QString("External changes to the database have been applied. Do you want to replay your changes on top? ")
1566 + QString(" Otherwise any local change will be lost.\n");
1567 if ( user_confirmation ( msg ) )
1568 {
1569 rewind_stack();
1570
1571 // Empty the internal stack and place the changes in a reverse order in a local stack
1572 confaccessor::t_internal_changes_stack internal_changes_reverse_copy;
1573 auto internal_changes = confaccessor::get_internal_change_stack();
1574
1575 while ( not internal_changes->empty() )
1576 {
1577 internal_changes_reverse_copy.push ( internal_changes->top() );
1578 internal_changes->pop();
1579 }
1580
1581 // Replay the commands one by one
1582 for ( int i = 0; i < undo_stack->count(); ++i )
1583 {
1584 config_internal_change Change = internal_changes_reverse_copy.top();
1585 internal_changes_reverse_copy.pop();
1586 internal_changes->push ( Change );
1587
1588 try
1589 {
1590
1591 dbe::actions::onobject const * Command =
1592 dynamic_cast<dbe::actions::onobject const *> ( undo_stack->command ( i ) );
1593
1594 if ( not Command->redoable() )
1595 {
1596 undo_stack->redo();
1597 }
1598 else
1599 {
1600 // If the object we are trying to make the changes to does not exist it means it was deleted
1601
1602 if ( ( dbe::config::api::info::has_obj ( Change.classname, Change.uid ) and Change
1603 .request
1607 {
1608 // If in virtue of external modification the object still exists and our action was not a creation
1609 Command->reload();
1610 undo_stack->redo();
1611 }
1612 else if ( not dbe::config::api::info::has_obj ( Change.classname, Change.uid ) and Change
1613 .request
1615 {
1616 // If the external changes have removed the object and we have created it
1617 undo_stack->redo();
1618 Command->reload();
1619 }
1620 else
1621 {
1623 Command->setredoable ( false );
1624 Command->setundoable ( false );
1625
1626 // Advance the stack by redoing an non-redoable (i.e. the redo action has no effect) command
1627 undo_stack->redo();
1628 }
1629 }
1630
1631 }
1632 catch ( dunedaq::conffwk::Exception const & e )
1633 {
1634 WARN ( "Object reference could not be changed",
1635 dbe::config::errors::parse ( e ).c_str(), "for object with UID:", Change.uid,
1636 "of class", Change.classname );
1637 }
1638 catch ( ... )
1639 {
1640 WARN ( "Unknown exception during object modification", "s",
1641 "\n\nFor object with UID:", Change.uid.c_str(), "of class:",
1642 Change.classname.c_str() );
1643 }
1644 }
1645 } else {
1647 }
1648 }
1649 else
1650 {
1651 INFO ( "Database reloaded due external changes", "Database consistency enforcement" );
1653 }
1654
1657
1658 // Emit the signal for connected listeners (e.g., the object editors)
1660}
1661
1668{
1669 QWidgetList allwidgets = QApplication::topLevelWidgets();
1670
1671 QWidgetList::iterator it = allwidgets.begin();
1672 MainWindow * main_win = qobject_cast<MainWindow *> ( *it );
1673
1674 for ( ; it != allwidgets.end() and main_win == nullptr; ++it )
1675 {
1676 main_win = qobject_cast<MainWindow *> ( *it );
1677 }
1678
1679 return main_win;
1680}
1681
1682//-----------------------------------------------------------------------------------------------------------------------------
1683
1684//-----------------------------------------------------------------------------------------------------------------------------
1692namespace {
1693 const int MAX_MESSAGE_LENGTH = 500;
1694}
1695
1696void dbe::MainWindow::slot_failure_message ( QString const title, QString const msg )
1697{
1698 QMessageBox mb(this);
1699 mb.setIcon(QMessageBox::Icon::Critical);
1700 mb.setWindowTitle(title);
1701 mb.setStandardButtons(QMessageBox::Ok);
1702 if(msg.length() > MAX_MESSAGE_LENGTH) {
1703 QString&& m = msg.left(MAX_MESSAGE_LENGTH);
1704 m.append("...");
1705 mb.setText("<b>The message has been truncated because too long, look at the details for the full message</b>");
1706 mb.setInformativeText(m);
1707 mb.setDetailedText(msg);
1708 } else {
1709 mb.setText(msg);
1710 }
1711
1712 mb.exec();
1713}
1714
1722void dbe::MainWindow::slot_information_message ( QString const title, QString const msg )
1723{
1724 QMessageBox mb(this);
1725 mb.setIcon(QMessageBox::Icon::Information);
1726 mb.setWindowTitle(title);
1727 mb.setStandardButtons(QMessageBox::Ok);
1728 if(msg.length() > MAX_MESSAGE_LENGTH) {
1729 QString&& m = msg.left(MAX_MESSAGE_LENGTH);
1730 m.append("...");
1731 mb.setText("<b>The message has been truncated because too long, look at the details for the full message</b>");
1732 mb.setInformativeText(m);
1733 mb.setDetailedText(msg);
1734 } else {
1735 mb.setText(msg);
1736 }
1737
1738 mb.exec();
1739}
1740
1748void dbe::MainWindow::slot_debuginfo_message ( QString const title, QString const msg )
1749{
1750 QMessageBox mb(this);
1751 mb.setIcon(QMessageBox::Icon::Information);
1752 mb.setWindowTitle(title);
1753 mb.setStandardButtons(QMessageBox::Ok);
1754 if(msg.length() > MAX_MESSAGE_LENGTH) {
1755 QString&& m = msg.left(MAX_MESSAGE_LENGTH);
1756 m.append("...");
1757 mb.setText("<b>The message has been truncated because too long, look at the details for the full message</b>");
1758 mb.setInformativeText(m);
1759 mb.setDetailedText(msg);
1760 } else {
1761 mb.setText(msg);
1762 }
1763
1764 mb.exec();
1765}
1766
1774void dbe::MainWindow::slot_notice_message ( QString const title, QString const msg )
1775{
1776 QMessageBox mb(this);
1777 mb.setIcon(QMessageBox::Icon::Information);
1778 mb.setWindowTitle(title);
1779 mb.setStandardButtons(QMessageBox::Ok);
1780 if(msg.length() > MAX_MESSAGE_LENGTH) {
1781 QString&& m = msg.left(MAX_MESSAGE_LENGTH);
1782 m.append("...");
1783 mb.setText("<b>The message has been truncated because too long, look at the details for the full message</b>");
1784 mb.setInformativeText(m);
1785 mb.setDetailedText(msg);
1786 } else {
1787 mb.setText(msg);
1788 }
1789
1790 mb.exec();
1791}
1792
1800void dbe::MainWindow::slot_error_message ( QString const title, QString const msg )
1801{
1802 QMessageBox mb(this);
1803 mb.setIcon(QMessageBox::Icon::Critical);
1804 mb.setWindowTitle(title);
1805 mb.setStandardButtons(QMessageBox::Ok);
1806 if(msg.length() > MAX_MESSAGE_LENGTH) {
1807 QString&& m = msg.left(MAX_MESSAGE_LENGTH);
1808 m.append("...");
1809 mb.setText("<b>The message has been truncated because too long, look at the details for the full message</b>");
1810 mb.setInformativeText(m);
1811 mb.setDetailedText(msg);
1812 } else {
1813 mb.setText(msg);
1814 }
1815
1816 mb.exec();
1817}
1818
1826void dbe::MainWindow::slot_warning_message ( QString const title, QString const msg )
1827{
1828 QMessageBox mb(this);
1829 mb.setIcon(QMessageBox::Icon::Warning);
1830 mb.setWindowTitle(title);
1831 mb.setStandardButtons(QMessageBox::Ok);
1832 if(msg.length() > MAX_MESSAGE_LENGTH) {
1833 QString&& m = msg.left(MAX_MESSAGE_LENGTH);
1834 m.append("...");
1835 mb.setText("<b>The message has been truncated because too long, look at the details for the full message</b>");
1836 mb.setInformativeText(m);
1837 mb.setDetailedText(msg);
1838 } else {
1839 mb.setText(msg);
1840 }
1841
1842 mb.exec();
1843}
1844
1845//-----------------------------------------------------------------------------------------------------------------------------
1846
1851
1856
1857void dbe::MainWindow::slot_batch_change_stop(const QList<QPair<QString, QString>>& objs)
1858{
1859 std::vector<dbe::dref> objects;
1860 for(const auto& o : objs) {
1861 objects.push_back(inner::dbcontroller::get({o.second.toStdString(), o.first.toStdString()}));
1862 }
1863
1864 // This allows to not reset the main tree
1865 this_classes->objectsUpdated(objects);
1866
1867 // In this case the corresponding trees are reset
1868 // In order to apply the same policy as in the class tree
1869 // the subtree_proxy class needs to be completed with proper
1870 // implementation of slots when objects are modified
1871
1872 // Proper "refresh" of table tabs
1873 for ( int i = 0; i < tableholder->count(); i++ )
1874 {
1875 TableTab * CurrentTab = dynamic_cast<TableTab *> ( tableholder->widget ( i ) );
1876 if ( CurrentTab ) {
1877 dbe::models::table* m = CurrentTab->GetTableModel();
1878 if ( m ) {
1879 m->objectsUpdated(objects);
1880 }
1881 }
1882 }
1883
1884 emit signal_batch_change_stopped(objs);
1885
1887}
1888
1890{
1891 if(isArchivedConf == false) {
1892 const auto& uncommittedFiles = confaccessor::uncommitted_files();
1893
1894 if(uncommittedFiles.empty() == true) {
1895 Commit->setEnabled(false);
1896 Commit->setToolTip("There is nothing to commit");
1897 } else {
1898 Commit->setEnabled(true);
1899
1900 std::string l;
1901 for(const std::string& f : uncommittedFiles) {
1902 l += " " + f + "\n";
1903 }
1904
1905 Commit->setToolTip(QString::fromStdString("Commit changes.\nHere are the uncommitted files:\n" + l));
1906 }
1907
1909
1910 } else {
1911 Commit->setEnabled(false);
1912 }
1913}
1914
1915void dbe::MainWindow::slot_update_committed_files(const std::list<std::string>& files, const std::string& msg) {
1916 for(const std::string& f : files) {
1917 CommittedTable->insertRow(0);
1918 CommittedTable->setItem(0, 0, new QTableWidgetItem(QString::fromStdString(f)));
1919 CommittedTable->setItem(0, 1, new QTableWidgetItem(QString::fromStdString(msg)));
1920 CommittedTable->setItem(0, 2, new QTableWidgetItem(QDate::currentDate().toString() + " " + QTime::currentTime().toString()));
1921 }
1922
1923 CommittedTable->resizeColumnsToContents();
1924}
1925
1927{
1928 return not m_batch_change_in_progress;
1929}
1930
1932{
1933 allFiles.insert(file);
1934}
char const *const dbe_lib_core_version
Including DBE.
Definition cptr.hpp:55
QString GetCommitMessage() const
static void parse_all_objects()
Definition FileInfo.cpp:104
static QString check_file_includes(const QString &file)
Definition FileInfo.cpp:121
static void show_file_info(const QString &filename)
Definition FileInfo.cpp:454
void slot_fetch_data(treenode const *)
void slot_information_message(QString const, QString const)
void edit_object_at(const QModelIndex &Index)
bool dbopen(QString const &, dbinfo const &)
void slot_show_userchanges()
void slot_update_committed_files(const std::list< std::string > &, const std::string &)
void slot_warning_message(QString const, QString const)
std::atomic< bool > isArchivedConf
void slot_batch_change_start()
void LoadDefaultSetting()
void slot_loaded_db_file(QString)
void slot_batch_change_stop(const QList< QPair< QString, QString > > &)
void slot_remove_tab(int i)
dbe::models::tree * this_classes
void slot_launch_object_editor(tref)
void slot_abort_changes()
void slot_process_externalchanges()
void slot_toggle_casesensitive_for_treeview(bool)
void load_settings(bool LoadSettings=false)
void slot_launch_batchchange_on_table()
void build_class_tree_model()
QSet< QString > allFiles
void slot_toggle_commit_button()
void closeEvent(QCloseEvent *event)
void slot_load_db_from_create_widget(const QString &)
void build_file_model()
bool slot_commit_database(bool Exit=false)
void argsparse(QMap< QString, QString > const &)
void slot_launch_batchchange()
cptr< dbe::CustomTreeView > get_view() const
models::treeselection * this_treefilter
void slot_debuginfo_message(QString const, QString const)
void slot_error_message(QString const, QString const)
bool eventFilter(QObject *Target, QEvent *Event)
void slot_open_database_from_file()
void slot_abort_external_changes()
void signal_new_file_model()
QString find_db_repository_dir()
void build_table_model()
FileModel * this_files
void slot_create_newdb()
void slot_show_userguide()
static MainWindow * findthis()
void slot_undo_allchanges()
void slot_failure_message(QString const, QString const)
void slot_model_rebuild()
bool m_batch_change_in_progress
void slot_edit_object_from_class_view(QModelIndex const &)
void slot_filter_table_textchange(const QString &)
void signal_db_loaded()
void slot_filter_textchange(const QString &)
void signal_externalchanges_processed()
std::vector< dbe::tref > ProcessQuery(QString const &)
void signal_batch_change_stopped(const QList< QPair< QString, QString > > &)
void update_total_objects()
bool check_ready() const
MainWindow(QMap< QString, QString > const &CommandLine, QWidget *parent=nullptr)
void slot_notice_message(QString const, QString const)
QSortFilterProxyModel this_filesort
void slot_show_information_about_dbe()
tref GetObject() const
Definition treenode.cpp:279
static void InitColorManagement()
void DisconnectView()
Definition TableTab.cpp:87
dbe::models::table * GetTableModel() const
Definition TableTab.cpp:178
dbe::models::tableselection * GetTableFilter() const
Definition TableTab.cpp:183
void setundoable(bool s=true) const
Definition Command.cpp:553
void reload() const
Definition Command.cpp:588
void setredoable(bool s=true) const
Definition Command.cpp:558
bool redoable() const
Definition Command.cpp:568
static cptr< datahandler > gethandler()
static t_undo_stack_cptr get_commands()
static bool is_database_loaded()
cptr< t_undo_stack > t_undo_stack_cptr
static std::list< std::string > uncommitted_files()
std::stack< t_internal_change, std::vector< t_internal_change > > t_internal_changes_stack
static void abort()
static void set_total_objects(int const i)
static void clear_commands()
static QString dbfullname()
static t_internal_changes_stack_cptr get_internal_change_stack()
static bool load(bool subscribeToChanges=true)
static std::list< std::string > save(QString const &)
static void setdbinfo(QString const &location, dbinfo const itype=dbinfo::oks)
static confaccessor & ref()
static QString db_implementation_name()
static QStringList inclusions(QStringList const &candidates, QStringList files={ })
static dunedaq::conffwk::class_t definition(std::string const &cn, bool direct_only)
static std::vector< configobject::tref > gets(std::string const &cname, std::string const &query="")
static configobject::tref get(dbe::cokey const &desc)
static messenger_proxy & ref()
QList< dbe::dref > * GetTableObjects()
Definition table.cpp:476
QString get_class_name() const
Definition table.cpp:466
bool BuildTableFromClass(const QString &ClassName, bool BuildSubClasses=false)
Definition table.cpp:268
void SetFilterType(FilterType Filter)
virtual QVariant GetData(const int Column, int role=Qt::DisplayRole) const
Definition treenode.cpp:64
int GetRow() const
Definition treenode.cpp:86
char const *const dbe_lib_internal_version
char const *const dbe_lib_config_api_version
#define ERROR(...)
Definition messenger.hpp:93
#define WARN(...)
Definition messenger.hpp:85
#define INFO(...)
bool has_obj(std::string const &classname, std::string const &object_uid)
std::string const parse(ers::Issue const &)
inner::configobject::tref tref
Definition tref.hpp:35
dbinfo
Definition dbinfo.hpp:20
config_object_description dref
void error(const Issue &issue)
Definition ers.hpp:92
modification request
Type of modification.
std::string uid
Object Identification.
char const *const dbe_lib_structure_version
Including QT Headers.
Definition tree.cpp:16
#define dbe_compiled_version
Definition version.hpp:22
#define dbe_compiled_commit
Definition version.hpp:28