LCOV - code coverage report
Current view: top level - dbe/src/internal - MainWindow.cpp (source / functions) Coverage Total Hit
Test: code.result Lines: 0.0 % 832 0
Test Date: 2026-10-11 15:05:20 Functions: 0.0 % 74 0

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

Generated by: LCOV version 2.0-1