DUNE-DAQ
DUNE Trigger and Data Acquisition software
Loading...
Searching...
No Matches
SchemaMainWindow.cpp
Go to the documentation of this file.
1
9#include "dbe/SchemaStyle.hpp"
10#include "dbe/SchemaTab.hpp"
11
12#include "oks/kernel.hpp" // for CanNotSetActiveFile exception
13
15#include "ui_SchemaMainWindow.h"
17#include "QInputDialog"
18#include <QCloseEvent>
19#include <QFileDialog>
20#include <QGraphicsScene>
21#include <QHeaderView>
22#include <QMessageBox>
23#include <QPrintDialog>
24#include <QPrinter>
25#include <QPushButton>
26#include <QSettings>
27#include <QSvgGenerator>
28
29// #include <format>
30#include <sstream>
31
32using namespace dunedaq;
33using namespace dunedaq::oks;
34
35dbse::SchemaMainWindow::SchemaMainWindow(QString SchemaFile, QWidget* parent)
36 : QMainWindow(parent)
37 , ui(new Ui::SchemaMainWindow)
38 , FileModel(nullptr)
39 , TableModel(nullptr)
40 , m_proxyModel(new QSortFilterProxyModel())
41 , ContextMenuFileView(nullptr)
42 , ContextMenuTableView(nullptr)
43{
45 m_default_state = saveState();
46 m_default_geometry = saveGeometry();
47 m_default_size = QSize(1400, 880);
48 QCoreApplication::setOrganizationName("dunedaq");
49 QCoreApplication::setApplicationName("dbse");
52
53 InitialTab();
56 setFocusPolicy(Qt::StrongFocus);
57
58 OpenSchemaFile(SchemaFile);
59}
60
62
63void
65{
66 ui->setupUi(this);
67 setWindowTitle(m_title);
68 ui->UndoView->setStack(KernelWrapper::GetInstance().GetUndoStack());
69 ui->ClassTableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
70 ui->ClassTableView->setDragEnabled(true);
71 ui->ClassTableView->setContextMenuPolicy(Qt::ContextMenuPolicy::CustomContextMenu);
72 ui->FileView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
73 ui->FileView->setContextMenuPolicy(Qt::ContextMenuPolicy::CustomContextMenu);
74 ui->FileView->setSelectionBehavior(QAbstractItemView::SelectRows);
75 ui->TabWidget->setTabsClosable(true);
76 ui->ClassTableSearchLine->setProperty("placeholderText", QVariant(QString("Search for classes regex")));
77 ui->ClassTableSearchLine->setClearButtonEnabled(true);
78 m_proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
79
80 QString DUNEDAQ_DB_PATH = getenv("DUNEDAQ_DB_PATH");
81 auto path_list = DUNEDAQ_DB_PATH.split(QLatin1Char(':'), Qt::SkipEmptyParts);
82 for (QString& path : path_list) {
83 if (!path.endsWith("/")) {
84 path.append("/");
85 }
86 m_path_urls.append(QUrl::fromLocalFile(path));
87 }
88}
89
90void
92{
93 add_tab();
94 ui->TabWidget->removeTab(0);
95}
96
97void
99{
100 QPushButton* new_tab_button = new QPushButton("+");
101 new_tab_button->setToolTip("Open new schema view tab");
102 ui->TabWidget->setCornerWidget(new_tab_button, Qt::TopLeftCorner);
103 connect(new_tab_button, SIGNAL(clicked()), this, SLOT(add_tab()));
104}
105
106void
108{
109 connect(ui->OpenFileSchema, SIGNAL(triggered()), this, SLOT(OpenSchemaFile()));
110 connect(ui->CreateNewSchema, SIGNAL(triggered()), this, SLOT(CreateNewSchema()));
111 connect(ui->ShowSchema, SIGNAL(triggered()), this, SLOT(show_file_info_active_schema()));
112 connect(ui->SaveSchema, SIGNAL(triggered()), this, SLOT(SaveSchema()));
113 connect(ui->actionSave_layout, SIGNAL(triggered()), this, SLOT(save_layout()));
114 connect(ui->actionRestore_layout, SIGNAL(triggered()), this, SLOT(restore_layout()));
115 connect(ui->actionDefault_layout, SIGNAL(triggered()), this, SLOT(default_layout()));
116 connect(ui->SetRelationship, SIGNAL(triggered(bool)), this, SLOT(ChangeCursorRelationship(bool)));
117 connect(ui->SetInheritance, SIGNAL(triggered(bool)), this, SLOT(ChangeCursorInheritance(bool)));
118 connect(ui->AddClass, SIGNAL(triggered()), this, SLOT(AddNewClass()));
119 connect(ui->SaveView, SIGNAL(triggered()), this, SLOT(SaveView()));
120 connect(ui->SaveViewAs, SIGNAL(triggered()), this, SLOT(SaveViewAs()));
121 connect(ui->LoadView, SIGNAL(triggered()), this, SLOT(LoadView()));
122 connect(ui->NameView, SIGNAL(triggered()), this, SLOT(NameView()));
123 connect(ui->Exit, SIGNAL(triggered()), this, SLOT(close()));
124
125 connect(ui->actionSettings, SIGNAL(triggered()), this, SLOT(edit_settings()));
126
127 connect(ui->displayClasses, SIGNAL(triggered(bool)), ui->ClassWidget, SLOT(setVisible(bool)));
128 connect(ui->displayDiagrams, SIGNAL(triggered(bool)), ui->TabWidget, SLOT(setVisible(bool)));
129 connect(ui->displayInfo_tabs, SIGNAL(triggered(bool)), ui->DockWidget, SLOT(setVisible(bool)));
130 connect(ui->displayToolbar, SIGNAL(triggered(bool)), ui->MainToolBar, SLOT(setVisible(bool)));
131 connect(ui->displayStatus_bar, SIGNAL(triggered(bool)), ui->StatusBar, SLOT(setVisible(bool)));
132
133 connect(ui->ClassWidget, SIGNAL(visibilityChanged(bool)), ui->displayClasses, SLOT(setChecked(bool)));
134 connect(ui->DockWidget, SIGNAL(visibilityChanged(bool)), ui->displayInfo_tabs, SLOT(setChecked(bool)));
135 connect(ui->MainToolBar, SIGNAL(visibilityChanged(bool)), ui->displayToolbar, SLOT(setChecked(bool)));
136
137 connect(ui->ClassTableView, SIGNAL(activated(QModelIndex)), this, SLOT(LaunchClassEditor(QModelIndex)));
138 connect(ui->close_tab, SIGNAL(triggered()), this, SLOT(close_tab()));
139
140 connect(&KernelWrapper::GetInstance(), SIGNAL(ClassCreated(QString)), this, SLOT(update_models()));
141 connect(&KernelWrapper::GetInstance(), SIGNAL(ClassUpdated(QString)), this, SLOT(update_models()));
142 connect(&KernelWrapper::GetInstance(), SIGNAL(ClassRemoved(QString)), this, SLOT(update_models()));
143 connect(&KernelWrapper::GetInstance(), SIGNAL(active_updated()), this, SLOT(update_models()));
144 connect(ui->TabWidget, SIGNAL(tabCloseRequested(int)), this, SLOT(RemoveTab(int)));
145
146 connect(ui->FileView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(CustomContextMenuFileView(QPoint)));
147 connect(ui->FileView, SIGNAL(activated(QModelIndex)), this, SLOT(show_file_info(QModelIndex)));
148
149 connect(
150 ui->ClassTableView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(CustomContextMenuTableView(QPoint)));
151 connect(ui->PrintView, SIGNAL(triggered()), this, SLOT(PrintCurrentView()));
152 connect(ui->exportView, SIGNAL(triggered()), this, SLOT(export_current_view()));
153 connect(ui->ClassTableSearchLine, SIGNAL(textChanged(QString)), m_proxyModel, SLOT(setFilterRegExp(QString)));
154 connect(ui->case_sensitive, SIGNAL(stateChanged(int)), this, SLOT(toggle_case_sensitive(int)));
155}
156
157void
159{
160 show_file_info(QString::fromStdString(KernelWrapper::GetInstance().GetActiveSchema()));
161}
162
163void
165{
166 QModelIndex index = ui->FileView->currentIndex();
167 show_file_info(index);
168}
169void
171{
172 QStringList row = FileModel->getRowFromIndex(index);
173 show_file_info(row.at(0));
174}
175void
177{
178 bool widget_found = false;
179 for (QWidget* widget : QApplication::allWidgets()) {
180 auto sfi = dynamic_cast<SchemaFileInfo*>(widget);
181 if (sfi != nullptr) {
182 if ((sfi->objectName()).compare(fn) == 0) {
183 sfi->raise();
184 sfi->setVisible(true);
185 sfi->activateWindow();
186 widget_found = true;
187 break;
188 }
189 }
190 }
191 if (!widget_found) {
192 auto info = new SchemaFileInfo(fn.toStdString());
195 info->show();
196 }
197}
198void
203void
205{
206 QStringList Headers{ "File Name", "Access", "Status" };
207
208 if (FileModel != nullptr) {
209 delete FileModel;
210 }
211 FileModel = new CustomFileModel(Headers);
212
213 ui->FileView->setModel(FileModel);
214 ui->FileView->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
215 ui->FileView->horizontalHeader()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
216 ui->FileView->horizontalHeader()->setSectionResizeMode(2, QHeaderView::ResizeToContents);
217}
218
219void
221{
222 QStringList Headers{ "Class Name" };
223
224 if (TableModel != nullptr) {
225 delete TableModel;
226 }
227 TableModel = new CustomTableModel(Headers);
228
229 m_proxyModel->setSourceModel(TableModel);
230 ui->ClassTableView->setModel(m_proxyModel);
231}
232
233int
235{
236 QString modified_views;
237 for (int index = 0; index < ui->TabWidget->count(); ++index) {
238 auto tab = dynamic_cast<SchemaTab*>(ui->TabWidget->widget(index));
239 if (tab->GetScene()->IsModified()) {
240 auto label = ui->TabWidget->tabText(index);
241 label = label.remove('*');
242 modified_views.append(" " + label + "\n");
243 }
244 }
245 if (!modified_views.isEmpty()) {
246 QString message("There are unsaved changes in the schema views:\n");
247 message.append(modified_views);
248 message.append("Do you want to save the changes in the schema views?\n");
249 return QMessageBox::question(
250 0, tr("SchemaEditor"), message, QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Discard);
251 }
252
253 return QMessageBox::Discard;
254}
255
256int
258{
259 // if ( KernelWrapper::GetInstance().GetUndoStack()->isClean() )
261 if (modified.empty()) {
262 return QMessageBox::Discard;
263 }
264
265 std::string msg = "There are unsaved changes in the following files:\n\n" + modified +
266 "Do you want to save the changes in the schema?\n";
267 return QMessageBox::question(0,
268 tr("SchemaEditor"),
269 QString(msg.c_str()),
270 QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel,
271 QMessageBox::Save);
272}
273
274void
280
281void
283{
284 QModelIndex Index = ui->ClassTableView->currentIndex();
285 QModelIndex proxyIndex = m_proxyModel->mapToSource(Index);
286 QStringList Row = TableModel->getRowFromIndex(proxyIndex);
287 OksClass* SchemaClass = KernelWrapper::GetInstance().FindClass(Row.at(0).toStdString());
288
289 if (SchemaClass->all_sub_classes()->size() != 0) {
290 QMessageBox::warning(0, "Schema editor", QString("Cannot delete class because it has sub-classes."));
291 return;
292 } else if (KernelWrapper::GetInstance().AnyClassReferenceThis(SchemaClass)) {
293 QMessageBox::warning(0, "Schema editor", QString("Cannot delete class because some classes references it."));
294 return;
295 } else {
296 QString Name = QString::fromStdString(SchemaClass->get_name());
298 SchemaClass, SchemaClass->get_name(), SchemaClass->get_description(), SchemaClass->get_is_abstract());
300 }
301}
302
303void
305{
306 QModelIndex Index = ui->ClassTableView->currentIndex();
307 QModelIndex proxyIndex = m_proxyModel->mapToSource(Index);
308 QStringList Row = TableModel->getRowFromIndex(proxyIndex);
309
310 if (!Row.isEmpty()) {
311 bool widget_found = false;
312 QString class_name = Row.at(0);
313 OksClass* class_info = KernelWrapper::GetInstance().FindClass(class_name.toStdString());
314
315 for (QWidget* widget : QApplication::allWidgets()) {
316 auto editor = dynamic_cast<SchemaClassEditor*>(widget);
317 if (editor != nullptr) {
318 if ((editor->objectName()).compare(class_name) == 0) {
319 editor->raise();
320 editor->setVisible(true);
321 editor->activateWindow();
322 widget_found = true;
323 }
324 }
325 }
326 if (!widget_found) {
327 SchemaClassEditor* editor = new SchemaClassEditor(class_info);
328 editor->show();
329 }
330 }
331}
332
333void
335{
336 QModelIndex index = ui->FileView->currentIndex();
337 QString file = FileModel->getRowFromIndex(index).at(0);
338 try {
339 KernelWrapper::GetInstance().SetActiveSchema(file.toStdString());
340 } catch (oks::CanNotSetActiveFile& exc) {
341 QMessageBox::warning(0,
342 "Set Active Schema",
343 QString("Could not make schema active!\n\n").append(QString(exc.what())),
344 QMessageBox::Ok);
345 return;
346 }
348
349 // In case we are highlighting classes in the active file, redraw current
350 // view tab now we've changed active file
351 SchemaTab* current_tab = dynamic_cast<SchemaTab*>(ui->TabWidget->currentWidget());
352 SchemaGraphicsScene* scene = current_tab->GetScene();
353 scene->update();
354
356}
357
358bool
360{
361 std::string filename = qfilename.toStdString();
362 std::set<std::string> includes;
364
365 QString advice{ "<br><br>Use the File info window to fix the problem." };
366 for (auto cls : KernelWrapper::GetInstance().get_schema_classes(filename)) {
367 auto relationships = cls->direct_relationships();
368 if (relationships != nullptr) {
369 for (auto rel : *relationships) {
370 auto rel_class = rel->get_class_type();
371 if (rel_class == nullptr) {
372 QString warning = "<b>Warning</b> class <i>" + QString::fromStdString(cls->get_name()) +
373 "</i> has relationship " + QString::fromStdString(rel->get_name()) +
374 " referring to class <i>" + QString::fromStdString(rel->get_type()) +
375 "</i> which is not loaded<br>";
376 QMessageBox::warning(0, "Check Schema", warning + advice, QMessageBox::Ok);
377 show_file_info(qfilename);
378 return false;
379 }
380 auto file = rel_class->get_file()->get_full_file_name();
381 if (file != filename && !includes.contains(file)) {
382 QString warning = "<b>Warning</b> class <i>" + QString::fromStdString(cls->get_name()) +
383 "</i> has relationship " + QString::fromStdString(rel->get_name()) +
384 " referring to class <i>" + QString::fromStdString(rel->get_class_type()->get_name()) +
385 "</i> from " + QString::fromStdString(file) + " which is not included by " + qfilename;
386 QMessageBox::warning(0, "Check Schema", warning + advice, QMessageBox::Ok);
387 show_file_info(qfilename);
388 return false;
389 }
390 }
391 }
392
393 auto super_classes = cls->direct_super_classes();
394 if (super_classes != nullptr) {
395 for (auto sc : *super_classes) {
396 auto sclass = KernelWrapper::GetInstance().FindClass(*sc);
397 if (sclass == nullptr) {
398 QString warning = "<b>Warning</b> class <i>" + QString::fromStdString(cls->get_name()) +
399 "</i> refers to super class <i>" + QString::fromStdString(*sc) +
400 "</i> which is not known<br>";
401 QMessageBox::warning(0, "Check Schema", warning + advice, QMessageBox::Ok);
402 show_file_info(qfilename);
403 return false;
404 }
405 auto file = sclass->get_file()->get_full_file_name();
406 if (file != filename && !includes.contains(file)) {
407 QString warning = "<b>Warning</b> class <i>" + QString::fromStdString(cls->get_name()) +
408 "</i> refers to super class <i>" + QString::fromStdString(*sc) + "</i> from " +
409 QString::fromStdString(file) + " which is not included by" + qfilename;
410 QMessageBox::warning(0, "Check Schema", warning + advice, QMessageBox::Ok);
411 show_file_info(qfilename);
412 return false;
413 }
414 }
415 }
416 }
417 return true;
418}
419
420bool
422{
424 return false;
425 }
426 bool status;
427 QString message;
428 try {
430 message = QString("File %1 saved").arg(filename);
431 status = true;
432 } catch (const oks::exception& exc) {
433 message = QString("Failed to save file %1").arg(filename);
434 status = false;
435 }
436 ui->StatusBar->showMessage(message);
437 return status;
438}
439
440void
442{
443 QModelIndex index = ui->FileView->currentIndex();
444 const auto file = FileModel->getRowFromIndex(index).at(0);
445 save_schema_file(file);
447}
448
449void
451{
452 SchemaTab* CurrentTab = dynamic_cast<SchemaTab*>(ui->TabWidget->currentWidget());
453
454 if (m_printer == nullptr) {
455 m_printer = new QPrinter;
456 }
457
458 if (QPrintDialog(m_printer).exec() == QDialog::Accepted) {
459 QPainter painter(m_printer);
460 painter.setRenderHint(QPainter::Antialiasing);
461
462 SchemaGraphicsScene* Scene = CurrentTab->GetScene();
463 QGraphicsView* View = CurrentTab->GetView();
464 Scene->render(&painter, QRectF(), View->viewport()->rect());
465 }
466}
467void
469{
470 auto tab = dynamic_cast<SchemaTab*>(ui->TabWidget->currentWidget());
471
472 auto file =
473 QFileDialog::getSaveFileName(this, tr("Export to SVG"), m_export_path, tr("SVG files (*.svg);;All files (*)"));
474 if (file.isEmpty()) {
475 return;
476 }
477
478 auto spos = file.lastIndexOf('/');
479 if (spos != -1) {
480 m_export_path = file;
481 m_export_path.truncate(spos);
482 }
483
484 if (!file.endsWith(".svg")) {
485 file.append(".svg");
486 }
487 QSvgGenerator generator;
488 generator.setFileName(file);
489 auto view = tab->GetView();
490 auto vpr = view->viewport()->rect();
491 generator.setSize(QSize(vpr.width(), vpr.height()));
492 generator.setViewBox(vpr);
493
494 QPainter painter;
495 painter.begin(&generator);
496 auto scene = tab->GetScene();
497 scene->render(&painter, QRectF(), view->viewport()->rect());
498 painter.end();
499}
500
501void
503{
504 int UserChoice = ShouldSaveChanges();
505
506 if (UserChoice == QMessageBox::Save) {
507 if (!SaveModifiedSchema()) {
508 event->ignore();
509 return;
510 }
511 } else if (UserChoice == QMessageBox::Cancel) {
512 event->ignore();
513 return;
514 }
515
516 UserChoice = ShouldSaveViewChanges();
517 if (UserChoice == QMessageBox::Cancel) {
518 event->ignore();
519 return;
520 }
521
523
525 save_layout();
526 }
527
528 for (QWidget* Widget : QApplication::allWidgets()) {
529 Widget->close();
530 }
531
532 event->accept();
533}
534
535void
541
542void
544{
545 OksFile* file{ nullptr };
546 if (!SchemaFile.isEmpty()) {
547 try {
548 file = KernelWrapper::GetInstance().LoadSchema(SchemaFile.toStdString());
549
550 if (m_schema_directory == QString(".")) {
551 std::vector<std::string> fnames;
553 std::string dir = fnames[0].substr(0, fnames[0].find_last_of('/'));
554 m_schema_directory.setPath(QString::fromStdString(dir));
555 }
556
557#ifdef QT_DEBUG
559#endif
560 } catch (oks::exception& Ex) {
561 QMessageBox::warning(
562 0, "Load Schema", QString("Could not load schema!\n\n").append(QString(Ex.what())), QMessageBox::Ok);
563 }
564
565 if (KernelWrapper::GetInstance().GetActiveSchema().empty()) {
566 try {
567 KernelWrapper::GetInstance().SetActiveSchema(SchemaFile.toStdString());
568 } catch (oks::CanNotSetActiveFile& exc) {
569 QMessageBox::warning(
570 0, "Load Schema", QString("Could not make schema active!\n\n").append(QString(exc.what())), QMessageBox::Ok);
571 }
572 }
573
576
577 update_window_title(QFileInfo(SchemaFile).fileName());
578 // ui->CreateNewSchema->setDisabled (true );
579 // ui->OpenFileSchema->setDisabled (true );
580 if (file != nullptr) {
581 check_schema_file(QString::fromStdString(file->get_full_file_name()));
582 }
583 }
584}
585
586void
588{
589 m_title.remove(QRegularExpression(": --.*"));
590 m_title.append(QString(": -- ") + text);
591 setWindowTitle(m_title);
592}
593
594void
596{
597 QFileDialog FileDialog(this, tr("Open Schema File"), ".", tr("XML schema files (*.schema.xml);;All files (*)"));
598 FileDialog.setAcceptMode(QFileDialog::AcceptOpen);
599 FileDialog.setFileMode(QFileDialog::AnyFile);
600 FileDialog.setViewMode(QFileDialog::Detail);
601 FileDialog.setDirectory(m_schema_directory);
602 FileDialog.setSidebarUrls(m_path_urls);
603 QStringList FilesSelected;
604 QString SchemaPath;
605
606 if (FileDialog.exec()) {
607 FilesSelected = FileDialog.selectedFiles();
608 }
609
610 if (FilesSelected.size()) {
611 m_schema_directory = FileDialog.directory();
612 SchemaPath = FilesSelected.value(0);
613 }
614
615 OpenSchemaFile(SchemaPath);
616}
617
618bool
620{
621 bool result = true;
622 for (auto file : KernelWrapper::GetInstance().get_modified_schema_files()) {
623 if (!save_schema_file(QString::fromStdString(file))) {
624 result = false;
625 }
626 }
628 return result;
629}
630
631void
633{
635 if (modified.empty()) {
636 QMessageBox::information(0, "Schema editor", QString("No modified schema files need saving"));
637
638 } else {
640 }
642}
643
644void
646{
647 QFileDialog FileDialog(this, tr("Create New schema File"), ".", tr("XML schema files (*.schema.xml);;All files (*)"));
648 FileDialog.setAcceptMode(QFileDialog::AcceptSave);
649 FileDialog.setFileMode(QFileDialog::AnyFile);
650 FileDialog.setViewMode(QFileDialog::Detail);
651 FileDialog.setDirectory(m_schema_directory);
652 FileDialog.setSidebarUrls(m_path_urls);
653 FileDialog.setLabelText(QFileDialog::Accept, "Create");
654 if (!FileDialog.exec()) {
655 return;
656 }
657
658 QStringList FilesSelected = FileDialog.selectedFiles();
659 if (FilesSelected.isEmpty()) {
660 QMessageBox::warning(0, "Schema editor", QString("Please provide a name for the schema !"));
661 return;
662 }
663
664 QString FileName = FilesSelected.at(0);
665 if (!FileName.endsWith(".schema.xml")) {
666 FileName.append(".schema.xml");
667 }
668
669 QFile FileInfo(FileName);
670 std::string FileNameStd = FileInfo.fileName().toStdString();
671
672 try {
677 ui->CreateNewSchema->setDisabled(true);
678 ui->OpenFileSchema->setDisabled(true);
679 } catch (oks::exception& Ex) {
680 QMessageBox::warning(
681 0,
682 "Schema editor",
683 QString("Could not create file : %1.\n\n%2").arg(QString::fromStdString(FileNameStd)).arg(QString(Ex.what())));
684 }
685}
686
687void
689{
690 if (ui->SetInheritance->isChecked()) {
691 ui->SetInheritance->setChecked(false);
692 }
693
694 if (State) {
695 ui->TabWidget->setCursor(Qt::CrossCursor);
696 } else {
697 ui->TabWidget->setCursor(Qt::ArrowCursor);
698 }
699
701}
702
703void
705{
706 if (ui->SetRelationship->isChecked()) {
707 ui->SetRelationship->setChecked(false);
708 }
709
710 if (State) {
711 ui->TabWidget->setCursor(Qt::CrossCursor);
712 } else {
713 ui->TabWidget->setCursor(Qt::ArrowCursor);
714 }
715
717}
718
719void
721{
722 auto index = ui->TabWidget->addTab(new SchemaTab(), "unnamed Schema View");
723 ui->TabWidget->setCurrentIndex(index);
724 auto tab = dynamic_cast<SchemaTab*>(ui->TabWidget->currentWidget());
727}
728
729void
731{
732 auto index = ui->TabWidget->currentIndex();
733 auto label = ui->TabWidget->tabText(index);
734 if (modified && !label.endsWith("*")) {
735 label += "*";
736 }
737 if (!modified && label.endsWith("*")) {
738 label = label.remove('*');
739 }
740 ui->TabWidget->setTabText(index, label);
741}
742
743void
745{
746 auto index = ui->TabWidget->currentIndex();
747 bool ok;
748 QString text = QInputDialog::getText(
749 nullptr, "Schema editor: rename class view", "New view name:", QLineEdit::Normal, "New Class View", &ok);
750 if (ok && !text.isEmpty()) {
751 ui->TabWidget->setTabText(index, text);
752 SchemaTab* CurrentTab = dynamic_cast<SchemaTab*>(ui->TabWidget->currentWidget());
753 CurrentTab->setName(text);
754 }
755
756 auto newtext = ui->TabWidget->tabText(index);
757}
758
759void
761{
762 SchemaTab* tab = dynamic_cast<SchemaTab*>(ui->TabWidget->currentWidget());
763 if (tab->GetScene()->items().size() != 0) {
764 auto file_name = tab->getFileName();
765 if (file_name == "./") {
766 SaveViewAs();
767 return;
768 }
769 write_view_file(file_name, tab);
770 }
771}
772void
774{
775 SchemaTab* CurrentTab = dynamic_cast<SchemaTab*>(ui->TabWidget->currentWidget());
776 if (CurrentTab->GetScene()->items().size() != 0) {
777 auto defName = CurrentTab->getFileName();
778 if (defName == "./") {
779 defName = m_view_dir;
780 }
781 QString FileName =
782 QFileDialog::getSaveFileName(this, tr("Save View"), defName, tr("View files (*.view);;All files (*)"));
783
784 if (!FileName.isEmpty()) {
785 auto spos = FileName.lastIndexOf('/');
786 if (spos != -1) {
787 m_view_dir = FileName;
788 m_view_dir.truncate(spos);
789 }
790
791 if (!FileName.endsWith(".view")) {
792 FileName.append(".view");
793 }
794
795 CurrentTab->setFileName(FileName);
796 auto text = QFileInfo(FileName).baseName();
797 CurrentTab->setName(text);
798 auto index = ui->TabWidget->currentIndex();
799 ui->TabWidget->setTabText(index, text);
800
801 write_view_file(FileName, CurrentTab);
802 }
803 }
804}
805
806void
808{
809 QFile file(file_name);
810 file.open(QIODevice::WriteOnly);
811
812 for (QGraphicsItem* item : tab->GetScene()->items()) {
813 auto object = dynamic_cast<SchemaGraphicObject*>(item);
814 if (object != nullptr) {
815 QString description = object->GetClassName() + "," + QString::number(object->scenePos().x()) + "," +
816 QString::number(object->scenePos().y()) + "\n";
817 file.write(description.toUtf8());
818 } else {
819 auto note = dynamic_cast<SchemaGraphicNote*>(item);
820 if (note != nullptr && !note->text().isEmpty()) {
821 auto text = note->text().replace("\n", "<br>");
822 text = text.replace(",", "<comma>");
823 QString line = "#," + QString::number(note->scenePos().x()) + "," + QString::number(note->scenePos().y()) +
824 "," + text + "\n";
825 file.write(line.toUtf8());
826 }
827 }
828 }
829
830 file.close();
831 auto message = QString("Saved view to %1").arg(file_name);
832 ui->StatusBar->showMessage(message);
833 tab->GetScene()->ClearModified();
834}
835
836void
838{
839 QString ViewPath =
840 QFileDialog::getOpenFileName(this, tr("Open view file"), m_view_dir, tr("View files (*.view);;All files (*)"));
841
842 if (!ViewPath.isEmpty()) {
843 auto spos = ViewPath.lastIndexOf('/');
844 if (spos != -1) {
845 m_view_dir = ViewPath;
846 m_view_dir.truncate(spos);
847 }
848 QFile ViewFile(ViewPath);
849 ViewFile.open(QIODevice::ReadOnly);
850
851 auto text = QFileInfo(ViewPath).baseName();
852 auto tab = dynamic_cast<SchemaTab*>(ui->TabWidget->currentWidget());
853 if (!tab->getName().isEmpty() || tab->GetScene()->IsModified()) {
854 add_tab();
855 tab = dynamic_cast<SchemaTab*>(ui->TabWidget->currentWidget());
856 }
857 auto index = ui->TabWidget->currentIndex();
858 ui->TabWidget->setTabText(index, text);
859 tab->setName(text);
860 tab->setFileName(ViewPath);
861
862 QStringList ClassesNames;
863 QList<QPointF> Positions;
864 QList<QPointF> note_positions;
865 QStringList notes;
866 while (!ViewFile.atEnd()) {
867 QString Line(ViewFile.readLine());
868 if (!Line.isEmpty()) {
869 QStringList ObjectDescription = Line.split(",");
870 QPointF Position;
871 Position.setX(ObjectDescription.at(1).toInt());
872 Position.setY(ObjectDescription.at(2).toInt());
873 if (ObjectDescription.at(0) == "#") {
874 note_positions.append(Position);
875 auto note_text = ObjectDescription.at(3);
876 if (note_text.back() == '\n') {
877 note_text.chop(1);
878 }
879 note_text = note_text.replace("<br>", "\n");
880 note_text = note_text.replace("<comma>", ",");
881 notes.append(note_text);
882 } else {
883 ClassesNames.append(ObjectDescription.at(0));
884 Positions.append(Position);
885 }
886 }
887 }
888 ViewFile.close();
889
890 auto message = QString("Loaded view from %1").arg(ViewPath);
891 ui->StatusBar->showMessage(message);
892
893 auto scene = tab->GetScene();
894 scene->CleanItemMap();
895 auto missing = scene->AddItemsToScene(ClassesNames, Positions);
896 if (!missing.empty()) {
897 QString warning_text{ "The following classes in " };
898 warning_text.append(QFileInfo(ViewPath).fileName());
899 warning_text.append(" are not present in the loaded schema:\n ");
900 warning_text.append(missing.join(",\n "));
901 QMessageBox::warning(this, tr("Load View"), warning_text);
902 }
903 scene->ClearModified();
904
905 scene->add_notes(notes, note_positions);
906 }
907}
908
909void
911{
912 QModelIndex proxyIndex = m_proxyModel->mapToSource(Index);
913 QStringList Row = TableModel->getRowFromIndex(proxyIndex);
914
915 if (!Row.isEmpty()) {
916 SchemaClassEditor::launch(Row.at(0));
917 }
918}
919
920void
922{
923 RemoveTab(ui->TabWidget->currentIndex());
924}
925
926void
928{
929 if (index == -1) {
930 return;
931 }
932
933 auto tab = dynamic_cast<SchemaTab*>(ui->TabWidget->widget(index));
934 if (tab->GetScene()->IsModified()) {
935 auto choice = QMessageBox::question(0,
936 tr("SchemaEditor"),
937 QString("There are unsaved changes in the schema view:\n"
938 "Do you really want to delete this schema view?\n"),
939 QMessageBox::Discard | QMessageBox::Cancel,
940 QMessageBox::Cancel);
941 if (choice == QMessageBox::Cancel) {
942 return;
943 }
944 }
945 ui->TabWidget->removeTab(index);
946 delete tab;
947 if (ui->TabWidget->count() == 0) {
948 add_tab();
949 }
950}
951
952void
954{
955 if (ContextMenuFileView == nullptr) {
956 ContextMenuFileView = new QMenu(this);
957
958 QAction* Act = new QAction(tr("Set as Active Schema"), this);
959 connect(Act, SIGNAL(triggered()), this, SLOT(SetSchemaFileActive()));
960 QAction* Sav = new QAction(tr("Save Schema File"), this);
961 connect(Sav, SIGNAL(triggered()), this, SLOT(SaveSchemaFile()));
962 QAction* info = new QAction(tr("Show file info"), this);
963 connect(info, SIGNAL(triggered()), this, SLOT(show_file_info()));
964
965 ContextMenuFileView->addAction(info);
966 ContextMenuFileView->addAction(Act);
967 ContextMenuFileView->addAction(Sav);
968 }
969
970 QModelIndex index = ui->FileView->currentIndex();
971
972 if (index.isValid()) {
973 QStringList row = FileModel->getRowFromIndex(index);
974 if (row.at(1) == "RW") {
975 ContextMenuFileView->actions().at(2)->setVisible(true);
976 if (!row.at(2).contains("Active")) {
977 ContextMenuFileView->actions().at(1)->setVisible(true);
978 } else {
979 ContextMenuFileView->actions().at(1)->setVisible(false);
980 }
981 } else {
982 ContextMenuFileView->actions().at(2)->setVisible(false);
983 ContextMenuFileView->actions().at(1)->setVisible(false);
984 }
985 ContextMenuFileView->exec(ui->FileView->mapToGlobal(Pos));
986 }
987}
988
989void
991{
992 if (ContextMenuTableView == nullptr) {
993 ContextMenuTableView = new QMenu(this);
994
995 QAction* add = new QAction(tr("&Add New Class"), this);
996 connect(add, SIGNAL(triggered()), this, SLOT(AddNewClass()));
997
998 QAction* remove = new QAction(tr("&Remove Selected Class"), this);
999 connect(remove, SIGNAL(triggered()), this, SLOT(RemoveClass()));
1000
1001 QAction* edit = new QAction(tr("&Edit Selected Class"), this);
1002 connect(edit, SIGNAL(triggered()), this, SLOT(editClass()));
1003
1004 ContextMenuTableView->addAction(add);
1005 ContextMenuTableView->addAction(edit);
1006 ContextMenuTableView->addAction(remove);
1007 }
1008
1009 QModelIndex Index = ui->ClassTableView->currentIndex();
1010
1011 if (Index.isValid()) {
1012 ContextMenuTableView->exec(ui->ClassTableView->mapToGlobal(Pos));
1013 }
1014}
1015
1016void
1018{
1019 if (ui->case_sensitive->isChecked()) {
1020 m_proxyModel->setFilterCaseSensitivity(Qt::CaseSensitive);
1021 } else {
1022 m_proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
1023 }
1024}
1025void
1027{
1028 auto tab = dynamic_cast<SchemaTab*>(ui->TabWidget->currentWidget());
1029 tab->GetScene()->update();
1030
1033}
1034
1035void
1037{
1038 if (m_settings == nullptr) {
1039 m_settings = new SchemaSettings(this);
1040 connect(m_settings, SIGNAL(settings_updated()), this, SLOT(update_view()));
1041 }
1042 m_settings->show();
1043}
1044
1045void
1047{
1048 QSettings settings;
1049 settings.beginGroup("MainWindow-layout");
1050 settings.setValue("size", size());
1051 settings.setValue("pos", pos());
1052 settings.setValue("geometry", saveGeometry());
1053 settings.setValue("state", saveState());
1054 settings.setValue("diagrams-visible", ui->TabWidget->isVisible());
1055 settings.setValue("statusbar-visible", ui->StatusBar->isVisible());
1056 settings.endGroup();
1057}
1058
1059void
1061{
1062 QSettings settings;
1063 settings.beginGroup("MainWindow-layout");
1064 if (settings.contains("size")) {
1065 resize(settings.value("size").toSize());
1066 }
1067 if (settings.contains("pos")) {
1068 move(settings.value("pos").toPoint());
1069 }
1070 if (settings.contains("geometry")) {
1071 restoreGeometry(settings.value("geometry").toByteArray());
1072 }
1073 if (settings.contains("state")) {
1074 restoreState(settings.value("state").toByteArray());
1075 }
1076
1077 auto visible = settings.value("diagrams-visible", true).toBool();
1078 ui->displayDiagrams->setChecked(visible);
1079 ui->TabWidget->setVisible(visible);
1080
1081 visible = settings.value("statusbar-visible", true).toBool();
1082 ui->StatusBar->setVisible(visible);
1083 ui->displayStatus_bar->setChecked(visible);
1084
1085 ui->displayToolbar->setChecked(ui->MainToolBar->isVisible());
1086 settings.endGroup();
1087
1088 settings.beginGroup("MainWindow");
1089 m_save_layout_on_exit = settings.value("saveLayout", false).toBool();
1090 settings.endGroup();
1091}
1092
1093void
1095{
1096 restoreGeometry(m_default_geometry);
1097 restoreState(m_default_state);
1098 resize(m_default_size);
1099
1100 ui->displayDiagrams->setChecked(true);
1101 ui->TabWidget->setVisible(true);
1102 ui->StatusBar->setVisible(true);
1103 ui->displayStatus_bar->setChecked(true);
1104}
CustomFileModel(QStringList &Headers, QObject *parent=nullptr)
Including Schema Editor.
CustomTableModel(QStringList Headers, QObject *parent=nullptr)
static KernelWrapper & GetInstance()
dunedaq::oks::OksFile * LoadSchema(const std::string &SchemaName) const
void SetActiveSchema(const std::string &ActiveSchema)
dunedaq::oks::OksClass * FindClass(std::string ClassName) const
void SaveSchema(const std::string &file) const
std::string ModifiedSchemaFiles() const
void SetInheritanceMode(bool Mode)
Editor Functions.
void CreateNewSchema(const std::string &SchemaName) const
void PushRemoveClassCommand(dunedaq::oks::OksClass *Class, std::string ClassName, std::string ClassDescription, bool Abstract)
void get_all_includes(const std::string &FileName, std::set< std::string > &IncludedFiles)
void GetSchemaFiles(std::vector< std::string > &SchemaFiles)
SchemaClassEditor(dunedaq::oks::OksClass *ClassInfo, QWidget *parent=nullptr)
static void launch(QString class_name)
void new_window(SchemaFileInfo *win)
SchemaFileInfo(std::string filename, QWidget *parent=0)
SchemaMainWindow(QString SchemaFile, QWidget *parent=nullptr)
SchemaSettings * m_settings
void connect_file_info(SchemaFileInfo *win)
void LaunchClassEditor(QModelIndex Index)
void OpenSchemaFile(QString SchemaFile)
void CustomContextMenuTableView(QPoint Pos)
void ChangeCursorInheritance(bool State)
void write_view_file(const QString &fn, SchemaTab *tab)
void modifiedView(bool modified)
void CustomContextMenuFileView(QPoint Pos)
bool save_schema_file(QString file)
void update_window_title(QString text)
CustomFileModel * FileModel
QSortFilterProxyModel * m_proxyModel
void ChangeCursorRelationship(bool State)
CustomTableModel * TableModel
std::unique_ptr< dbse::Ui::SchemaMainWindow > ui
void closeEvent(QCloseEvent *event)
void show_file_info(QModelIndex)
bool check_schema_file(QString file)
SchemaSettings(QWidget *parent=0)
void setFileName(const QString &)
Definition SchemaTab.cpp:43
QString getFileName()
Definition SchemaTab.cpp:49
SchemaGraphicsScene * GetScene() const
Definition SchemaTab.cpp:25
void setName(const QString &)
Definition SchemaTab.cpp:37
QGraphicsView * GetView() const
Definition SchemaTab.cpp:31
SchemaTab(QWidget *parent=nullptr)
Including QT Headers.
Definition SchemaTab.cpp:11
Failed to set active file.
Definition kernel.hpp:268
The OKS class.
Definition class.hpp:223
bool get_is_abstract() const noexcept
Definition class.hpp:392
const FList * all_sub_classes() const noexcept
Definition class.hpp:463
const std::string & get_name() const noexcept
Definition class.hpp:374
const std::string & get_description() const noexcept
Definition class.hpp:378
Provides interface to the OKS XML schema and data files.
Definition file.hpp:355
virtual const char * what() const noexcept
The DUNE-DAQ namespace.
FELIX Initialization std::string initerror FELIX queue timed std::string queuename Unexpected chunk size
static void load()