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