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