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

Generated by: LCOV version 2.0-1