LCOV - code coverage report
Current view: top level - dbe/src/internal - MainWindow.cpp (source / functions) Coverage Total Hit
Test: code.result Lines: 0.0 % 894 0
Test Date: 2026-03-29 15:29:34 Functions: 0.0 % 74 0

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

Generated by: LCOV version 2.0-1