DUNE-DAQ
DUNE Trigger and Data Acquisition software
Loading...
Searching...
No Matches
SchemaFileInfo.cpp
Go to the documentation of this file.
1
5#include "dbe/SchemaStyle.hpp"
6#include "oks/class.hpp"
7#include "oks/kernel.hpp" // for CanNotSetActiveFile exception
8#include "ui_SchemaFileInfo.h"
9
10#include <QBrush>
11#include <QColor>
12#include <QDialogButtonBox>
13#include <QFileDialog>
14#include <QMessageBox>
15#include <QPushButton>
16#include <QString>
17
18namespace dbse {
19
20SchemaFileInfo::SchemaFileInfo(std::string filename, QWidget* /*parent*/)
21 : m_ui(new Ui::SchemaFileInfo)
23 , m_include_menu(nullptr)
24 , m_class_menu(nullptr)
25{
26
27 QWidget::setAttribute(Qt::WA_DeleteOnClose);
28
29 m_ui->setupUi(this);
30 // m_ui->buttonBox->setStandardButtons(QDialogButtonBox::Ok);
31 m_ui->missing_button->hide();
32 // m_ui->class_list->setDragEnabled ( true );
33 // m_ui->class_list->setAcceptDrops ( true );
34 setObjectName(QString::fromStdString(filename));
35 auto sp = filename.find_last_of('/');
36 if (sp == std::string::npos) {
37 sp = 0;
38 } else {
39 sp++;
40 }
41 setWindowTitle(QString("Schema File: %1").arg(QString::fromStdString(filename.substr(sp))));
42
43 m_ui->label->setText(QString::fromStdString(filename));
44 if (!KernelWrapper::GetInstance().IsFileWritable(m_filename)) {
45 QPalette pal;
46 pal.setColor(QPalette::Active, QPalette::WindowText, SchemaStyle::get_color("foreground", "readonly"));
47 m_ui->label->setPalette(pal);
48 // m_ui->label->setStyleSheet("color:rgb(128,0,0);");
49 }
51
52 QString DUNEDAQ_DB_PATH = getenv("DUNEDAQ_DB_PATH");
53 m_path_list = DUNEDAQ_DB_PATH.split(QLatin1Char(':'), Qt::SkipEmptyParts);
54 for (QString& path : m_path_list) {
55 if (!path.endsWith("/")) {
56 path.append("/");
57 }
58 m_path_urls.append(QUrl::fromLocalFile(path));
59 }
60
62
63 m_ui->textBrowser->hide();
64
66
67 m_ui->include_list->setContextMenuPolicy(Qt::ContextMenuPolicy::CustomContextMenu);
68 m_ui->class_list->setContextMenuPolicy(Qt::ContextMenuPolicy::CustomContextMenu);
69 connect(m_ui->include_list, SIGNAL(itemActivated(QListWidgetItem*)), this, SLOT(show_file_info(QListWidgetItem*)));
70 connect(
71 m_ui->include_list, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(activate_include_context_menu(QPoint)));
72
73 if (KernelWrapper::GetInstance().IsFileWritable(m_filename)) {
74 connect(m_ui->active_button, SIGNAL(pressed()), this, SLOT(set_active()));
75 connect(m_ui->add_button, SIGNAL(pressed()), this, SLOT(add_include()));
76 connect(m_ui->missing_button, SIGNAL(pressed()), this, SLOT(add_missing_includes()));
77 connect(&KernelWrapper::GetInstance(), SIGNAL(ClassUpdated(QString)), this, SLOT(class_updated(QString)));
78 connect(
79 m_ui->class_list, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(activate_class_context_menu(QPoint)));
80 } else {
81 m_ui->add_button->setEnabled(false);
82 m_ui->active_button->setEnabled(false);
83 m_ui->save_button->setEnabled(false);
84 }
85 connect(m_ui->save_button, SIGNAL(pressed()), this, SLOT(save_schema()));
86 connect(m_ui->close_button, SIGNAL(pressed()), this, SLOT(close()));
87 connect(&KernelWrapper::GetInstance(), SIGNAL(active_updated()), this, SLOT(show_status()));
88
89 connect(m_ui->class_list, SIGNAL(itemActivated(QListWidgetItem*)), this, SLOT(launch_class_editor(QListWidgetItem*)));
90}
91
92void
94{
95 m_ui->include_list->clear();
96 m_all_includes.clear();
98
99 std::set<std::string> direct_includes;
101
102 for (auto inc : m_all_includes) {
103 auto file = prune_path(inc);
104 auto item = new QListWidgetItem(QString::fromStdString(file));
105 item->setToolTip(QString::fromStdString(inc));
106 m_ui->include_list->addItem(item);
107 if (!direct_includes.contains(file)) {
108 item->setForeground(QBrush(SchemaStyle::get_color("foreground", "inherited")));
109 } else if (!KernelWrapper::GetInstance().IsFileWritable(inc)) {
110 item->setForeground(QBrush(SchemaStyle::get_color("foreground", "readonly")));
111 item->setBackground(QBrush(SchemaStyle::get_color("background", "readonly")));
112 } else {
113 item->setForeground(QBrush(SchemaStyle::get_color("foreground", "default")));
114 item->setBackground(QBrush(SchemaStyle::get_color("background", "default")));
115 }
116 }
117 m_ui->include_list->update();
118}
119
120bool
122{
123 bool ok = true;
124 auto relationships = cls->direct_relationships();
125 if (relationships != nullptr) {
126 for (auto rel : *relationships) {
127 auto rel_class = rel->get_class_type();
128 if (rel_class == nullptr) {
129 QString warning = "<b>Warning</b> class <i>" + QString::fromStdString(cls->get_name()) +
130 "</i> has relationship " + QString::fromStdString(rel->get_name()) +
131 " referring to class <i>" + QString::fromStdString(rel->get_type()) +
132 "</i> which is not loaded<br>";
133 m_ui->textBrowser->insertHtml(warning);
134 m_ui->textBrowser->show();
135 ok = false;
136 continue;
137 }
138 auto file = rel_class->get_file()->get_full_file_name();
139 if (file != m_filename && !m_all_includes.contains(file)) {
140 m_missing_includes.insert(file);
141 QString warning = "<b>Warning</b> class <i>" + QString::fromStdString(cls->get_name()) +
142 "</i> has relationship " + QString::fromStdString(rel->get_name()) +
143 " referring to class <i>" + QString::fromStdString(rel->get_class_type()->get_name()) +
144 "</i> from " + QString::fromStdString(file) + " which is not included<br>";
145 m_ui->textBrowser->insertHtml(warning);
146 m_ui->textBrowser->show();
147 ok = false;
148 }
149 }
150 }
151 return ok;
152}
153
154bool
156{
157 bool ok = true;
158 auto super_classes = cls->direct_super_classes();
159 if (super_classes != nullptr) {
160 for (auto sc : *super_classes) {
161 auto sclass = KernelWrapper::GetInstance().FindClass(*sc);
162 if (sclass == nullptr) {
163 QString warning = "<b>Warning</b> class <i>" + QString::fromStdString(cls->get_name()) +
164 "</i> refers to super class <i>" + QString::fromStdString(*sc) +
165 "</i> which is not known<br>";
166 m_ui->textBrowser->insertHtml(warning);
167 m_ui->textBrowser->show();
168 ok = false;
169 continue;
170 }
171 auto file = sclass->get_file()->get_full_file_name();
172 if (file != m_filename && !m_all_includes.contains(file)) {
173 m_missing_includes.insert(file);
174 QString warning = "<b>Warning</b> class <i>" + QString::fromStdString(cls->get_name()) +
175 "</i> refers to super class <i>" + QString::fromStdString(*sc) + "</i> from " +
176 QString::fromStdString(file) + " which is not included<br>";
177 m_ui->textBrowser->insertHtml(warning);
178 m_ui->textBrowser->show();
179 ok = false;
180 }
181 }
182 }
183 return ok;
184}
185
186void
188{
189 std::cout << "Removing include file " << filename << "\n";
190
191 auto temp_files = m_all_includes;
192 temp_files.erase(filename);
193 temp_files.insert(m_filename);
194
196 for (auto cls : classes) {
197 // Ignore classes in file we're removing
198 if (cls->get_file()->get_full_file_name() != filename) {
199 auto relationships = cls->direct_relationships();
200 if (relationships != nullptr) {
201 for (auto rel : *relationships) {
202 auto file = rel->get_class_type()->get_file()->get_full_file_name();
203 if (!temp_files.contains(file)) {
204 auto message = QString("Cannot remove %1 as class %2 has relationship to its %3 class")
205 .arg(QString::fromStdString(filename))
206 .arg(QString::fromStdString(cls->get_name()))
207 .arg(QString::fromStdString(rel->get_class_type()->get_name()));
208 QMessageBox::warning(0, "Schema editor", message);
209 return;
210 }
211 }
212 }
213 auto super_classes = cls->direct_super_classes();
214 if (super_classes != nullptr) {
215 for (auto sc : *super_classes) {
216 auto sclass = KernelWrapper::GetInstance().FindClass(*sc);
217 auto file = sclass->get_file()->get_full_file_name();
218 if (!temp_files.contains(file)) {
219 auto message = QString("Cannot remove %1 as class %2 has superclass %3 in %1")
220 .arg(QString::fromStdString(filename))
221 .arg(QString::fromStdString(cls->get_name()))
222 .arg(QString::fromStdString(*sc));
223 QMessageBox::warning(0, "Schema editor", message);
224 return;
225 }
226 }
227 }
228 }
229 }
230 try {
233 } catch (dunedaq::oks::FailedRemoveInclude& exc) {
234 QMessageBox::warning(0, "Schema editor", QString::fromStdString(exc.what()));
235 }
236
237 get_includes();
239 show_status();
240}
241
242void
244{
245 auto item = m_ui->include_list->currentItem();
246 std::string fn = item->text().toStdString();
247 remove_include(fn);
248}
249
250void
252{
253 close();
254}
255
256void
258{
259 close();
260}
261
262void
264{
265 if (event->key() == Qt::Key_Escape) {
266 close();
267 }
268 QWidget::keyPressEvent(event);
269}
270
271void
273{
274 SchemaClassEditor::launch(item->text());
275}
276
277void
279{
280 m_ui->class_list->clear();
281 m_ui->textBrowser->clear();
283 for (auto cls : classes) {
284 auto item = new QListWidgetItem(QString::fromStdString(cls->get_name()));
285
286 if (!KernelWrapper::GetInstance().IsFileWritable(m_filename)) {
287 item->setForeground(QBrush(SchemaStyle::get_color("foreground", "readonly")));
288 item->setBackground(QBrush(SchemaStyle::get_color("background", "readonly")));
289 }
290 if (!check_relationships(cls)) {
291 item->setForeground(QBrush(SchemaStyle::get_color("foreground", "error")));
292 item->setBackground(QBrush(SchemaStyle::get_color("background", "error")));
293 }
294 if (!check_superclasses(cls)) {
295 item->setForeground(QBrush(SchemaStyle::get_color("foreground", "error")));
296 item->setBackground(QBrush(SchemaStyle::get_color("background", "error")));
297 }
298
299 m_ui->class_list->addItem(item);
300 }
301 m_ui->class_summary->setText(QString("Total of %1 classes").arg(classes.size()));
302
303 // if (!m_missing_includes.empty() && m_missing_button == nullptr) {
304 // m_missing_button = m_ui->buttonBox->addButton("Add missing includes", QDialogButtonBox::ApplyRole);
305 // if (m_missing_button != nullptr) {
306 // connect ( m_missing_button, SIGNAL (pressed()), this, SLOT(add_missing_includes()));
307 // }
308 // else {
309 // std::cout << "Failed to add button\n";
310 // }
311 // }
312 if (m_missing_includes.empty()) {
313 m_ui->missing_button->setEnabled(false);
314 m_ui->missing_button->hide();
315 } else {
316 m_ui->missing_button->setEnabled(true);
317 m_ui->missing_button->show();
318 }
319}
320
321void
322SchemaFileInfo::class_updated(QString /*class_name*/)
323{
324 // auto cls = KernelWrapper::GetInstance().FindClass(class_name.toStdString());
325 // auto file = cls->get_file()->get_full_file_name();
326 // if (file == m_filename) {
327 show_status();
329 // }
330}
331
332void
334{
335 try {
337 } catch (const dunedaq::oks::exception& exc) {
338 QMessageBox::warning(0,
339 "Save Schema",
340 QString("Failed to save file %1").arg(m_filename.c_str()).append(QString(exc.what())),
341 QMessageBox::Ok);
342 }
343 show_status();
344 emit files_updated();
345}
346
347void
349{
350 QString status;
351 if (KernelWrapper::GetInstance().IsFileWritable(m_filename)) {
352 status.append("Read/Write");
353 } else {
354 status.append("Read only");
355 }
356 if (KernelWrapper::GetInstance().is_file_modified(m_filename)) {
357 status.append(" Modified");
358 if (m_missing_includes.empty()) {
359 m_ui->save_button->setEnabled(true);
360 } else {
361 m_ui->save_button->setEnabled(false);
362 }
363 } else {
364 m_ui->save_button->setEnabled(false);
365 }
366
367 if (m_filename == KernelWrapper::GetInstance().GetActiveSchema()) {
368 status.append(" Active");
369 m_ui->active_button->setEnabled(false);
370 } else if (KernelWrapper::GetInstance().IsFileWritable(m_filename)) {
371 m_ui->active_button->setEnabled(true);
372 }
373 m_ui->status->setText(status);
374}
375
376void
378{
379 auto fd = new QFileDialog(this, tr("Open File"), ".", tr("XML schema files (*.schema.xml)"));
380 fd->setFileMode(QFileDialog::ExistingFiles);
381 fd->setViewMode(QFileDialog::Detail);
382 fd->setAcceptMode(QFileDialog::AcceptOpen);
383 fd->setSidebarUrls(m_path_urls);
384 fd->exec();
385 auto files = fd->selectedFiles();
386 for (auto file : files) {
387 add_file(file.toStdString());
388 }
389 get_includes();
391 show_status();
392}
393
394void
396{
397 std::cout << "\nAdding missing include files:\n";
398
399 for (auto file : m_missing_includes) {
400 add_file(file);
401 }
402 m_missing_includes.clear();
403
404 get_includes();
405 m_ui->textBrowser->clear();
406 m_ui->textBrowser->hide();
407
408 get_includes();
410 show_status();
411}
412
413std::string
415{
416 for (QString& element : m_path_list) {
417 if (file.starts_with(element.toStdString())) {
418 file = file.substr(element.size());
419 break;
420 }
421 }
422 return file;
423}
424void
426{
427 std::cout << " " << file << "\n";
428 try {
430 emit files_updated();
431 } catch (std::exception& exc) {
432 QString message =
433 QString("Failed to add %1 to included files, %2").arg(QString::fromStdString(file)).arg(exc.what());
434 QMessageBox::warning(0, "Schema editor", message);
435 }
436}
437
438void
440{
441 if (m_include_menu == nullptr) {
442 m_include_menu = new QMenu(this);
443
444 if (KernelWrapper::GetInstance().IsFileWritable(m_filename)) {
445 QAction* add = new QAction(tr("Add New Include File"), this);
446 connect(add, SIGNAL(triggered()), this, SLOT(add_include()));
447 QAction* remove = new QAction(tr("Remove Selected Include File"), this);
448 connect(remove, SIGNAL(triggered()), this, SLOT(remove_include()));
449 m_include_menu->addAction(add);
450 m_include_menu->addAction(remove);
451 }
452 QAction* info = new QAction(tr("Show file info"), this);
453 connect(info, SIGNAL(triggered()), this, SLOT(show_file_info()));
454
455 m_include_menu->addAction(info);
456 }
457
458 if (m_ui->include_list->currentIndex().isValid()) {
459 m_include_menu->exec(m_ui->include_list->mapToGlobal(pos));
460 }
461}
462
463void
465{
466 if (m_class_menu == nullptr) {
467 m_class_menu = new QMenu(this);
468
469 QAction* add = new QAction(tr("&Add New Class"), this);
470 connect(add, SIGNAL(triggered()), this, SLOT(add_new_class()));
471
472 QAction* remove = new QAction(tr("&Remove Selected Class"), this);
473 connect(remove, SIGNAL(triggered()), this, SLOT(remove_class()));
474
475 QAction* edit = new QAction(tr("&Edit Selected Class"), this);
476 connect(edit, SIGNAL(triggered()), this, SLOT(edit_class()));
477
478 QAction* move = new QAction(tr("&Move Selected Class"), this);
479 connect(move, SIGNAL(triggered()), this, SLOT(move_class()));
480
481 m_class_menu->addAction(add);
482 m_class_menu->addAction(edit);
483 m_class_menu->addAction(move);
484 m_class_menu->addAction(remove);
485 }
486
487 if (m_ui->class_list->currentIndex().isValid()) {
488 m_class_menu->exec(m_ui->class_list->mapToGlobal(pos));
489 }
490}
491
492void
494{
495 SchemaClassEditor::launch(m_ui->class_list->currentItem()->text());
496}
497void
499{
500 auto oks_class = KernelWrapper::GetInstance().FindClass(m_ui->class_list->currentItem()->text().toStdString());
501 SchemaClassEditor::move_class(oks_class, this);
502}
503void
505{
506 auto item = m_ui->class_list->currentItem();
507 QString cn = item->text();
508 dunedaq::oks::OksClass* schema_class = KernelWrapper::GetInstance().FindClass(cn.toStdString());
509 if (schema_class->all_sub_classes()->size() != 0) {
510 QMessageBox::warning(0, "Schema editor", QString("Cannot delete class because it has sub-classes."));
511 return;
512 } else if (KernelWrapper::GetInstance().AnyClassReferenceThis(schema_class)) {
513 QMessageBox::warning(0, "Schema editor", QString("Cannot delete class because some other classes references it."));
514 return;
515 }
516
518 schema_class, schema_class->get_name(), schema_class->get_description(), schema_class->get_is_abstract());
519 delete item;
520 m_ui->class_list->update();
521}
522
523bool
525{
526 try {
528 } catch (dunedaq::oks::CanNotSetActiveFile& exc) {
529 auto qfn = QString::fromStdString(m_filename);
530 auto text = QString("Could not make schema file %1 active!\n\n").arg(qfn);
531 QMessageBox::warning(0, "Set Active Schema", text.append(QString(exc.what())), QMessageBox::Ok);
532 return false;
533 }
534 show_status();
535 return true;
536}
537
538void
540{
541 auto item = m_ui->include_list->currentItem();
542 std::string fn = item->text().toStdString();
543 set_active(fn);
544 show_status();
545}
546
547void
553
554void
556{
557 if (set_active(m_filename)) {
559 if (!nc.isEmpty()) {
560 auto item = new QListWidgetItem(nc);
561 m_ui->class_list->addItem(item);
562 m_ui->class_list->sortItems();
563 m_ui->class_list->setCurrentItem(item);
564 m_ui->class_list->update();
565 }
566 }
567}
568
569void
571{
572 show_file_info(m_ui->include_list->currentItem());
573}
574void
576{
577 show_file_info(item->text());
578}
579void
581{
582 bool widget_found = false;
583 for (QWidget* widget : QApplication::allWidgets()) {
584 auto sfi = dynamic_cast<SchemaFileInfo*>(widget);
585 if (sfi != nullptr) {
586 if ((sfi->objectName()).compare(fn) == 0) {
587 sfi->raise();
588 sfi->setVisible(true);
589 sfi->activateWindow();
590 widget_found = true;
591 break;
592 }
593 }
594 }
595 if (!widget_found) {
596 auto info = new SchemaFileInfo(fn.toStdString());
597 // connect (info, &SchemaFileInfo::files_updated,
598 // this, &SchemaMainWindow::update_models);
599 emit new_window(this);
600 info->show();
601 }
602}
603} // namespace dbse
static KernelWrapper & GetInstance()
void SetActiveSchema(const std::string &ActiveSchema)
dunedaq::oks::OksClass * FindClass(std::string ClassName) const
void RemoveInclude(std::string schemaFile, std::string IncludeFile) const
void SaveSchema(const std::string &file) const
void PushRemoveClassCommand(dunedaq::oks::OksClass *Class, std::string ClassName, std::string ClassDescription, bool Abstract)
void AddInclude(std::string schemaFile, std::string IncludeFile) const
void get_all_includes(const std::string &FileName, std::set< std::string > &IncludedFiles)
std::vector< dunedaq::oks::OksClass * > get_schema_classes(std::string &filename)
void get_direct_includes(const std::string &FileName, std::set< std::string > &IncludedFiles)
static void launch(QString class_name)
void new_window(SchemaFileInfo *win)
std::string prune_path(std::string file)
bool check_relationships(dunedaq::oks::OksClass *cls)
void launch_class_editor(QListWidgetItem *)
bool check_superclasses(dunedaq::oks::OksClass *cls)
std::set< std::string > m_missing_includes
QList< QUrl > m_path_urls
SchemaFileInfo(std::string filename, QWidget *parent=0)
void class_updated(QString class_name)
void show_file_info(QString fn)
void keyPressEvent(QKeyEvent *event) override
void add_file(std::string file)
void activate_include_context_menu(QPoint point)
std::set< std::string > m_all_includes
Ui::SchemaFileInfo * m_ui
void activate_class_context_menu(QPoint point)
Failed to set active file.
Definition kernel.hpp:268
Cannot remove include file. Such exception is thrown when OKS cannot remove include file.
Definition file.hpp:150
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::list< OksRelationship * > * direct_relationships() const noexcept
Definition class.hpp:572
const std::string & get_description() const noexcept
Definition class.hpp:378
const std::list< std::string * > * direct_super_classes() const noexcept
Definition class.hpp:417
virtual const char * what() const noexcept
Including QT Headers.
static QColor get_color(const QString &item, const QString &group)