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 item = new QListWidgetItem(QString::fromStdString(inc));
108 m_ui->include_list->addItem(item);
109 if (!direct_includes.contains(prune_path(inc))) {
110 item->setForeground(QBrush(SchemaStyle::get_color("foreground", "inherited")));
111 }
112 else if (!KernelWrapper::GetInstance().IsFileWritable (inc)) {
113 item->setForeground(QBrush(SchemaStyle::get_color("foreground", "readonly")));
114 item->setBackground(QBrush(SchemaStyle::get_color("background", "readonly")));
115 }
116 else {
117 item->setForeground(QBrush(SchemaStyle::get_color("foreground", "default")));
118 item->setBackground(QBrush(SchemaStyle::get_color("background", "default")));
119 }
120 }
121 m_ui->include_list->update();
122}
123
125 bool ok = true;
126 auto relationships = cls->direct_relationships();
127 if (relationships != nullptr) {
128 for (auto rel: *relationships) {
129 auto rel_class = rel->get_class_type();
130 if (rel_class == nullptr) {
131 QString warning = "<b>Warning</b> class <i>"
132 + QString::fromStdString(cls->get_name())
133 + "</i> has relationship "
134 + QString::fromStdString(rel->get_name())
135 + " referring to class <i>"
136 + QString::fromStdString(rel->get_type())
137 + "</i> which is not loaded<br>";
138 m_ui->textBrowser->insertHtml(warning);
139 m_ui->textBrowser->show();
140 ok = false;
141 continue;
142 }
143 auto file = rel_class->get_file()->get_full_file_name();
144 if (file != m_filename && !m_all_includes.contains(file)) {
145 m_missing_includes.insert(file);
146 QString warning = "<b>Warning</b> class <i>"
147 + QString::fromStdString(cls->get_name())
148 + "</i> has relationship "
149 + QString::fromStdString(rel->get_name())
150 + " referring to class <i>"
151 + QString::fromStdString(rel->get_class_type()->get_name())
152 + "</i> from " + QString::fromStdString(file)
153 + " which is not included<br>";
154 m_ui->textBrowser->insertHtml(warning);
155 m_ui->textBrowser->show();
156 ok = false;
157 }
158 }
159 }
160 return ok;
161}
162
164 bool ok = true;
165 auto super_classes = cls->direct_super_classes();
166 if (super_classes != nullptr) {
167 for (auto sc: *super_classes) {
168 auto sclass = KernelWrapper::GetInstance().FindClass(*sc);
169 if (sclass == nullptr) {
170 QString warning = "<b>Warning</b> class <i>"
171 + QString::fromStdString(cls->get_name())
172 + "</i> refers to super class <i>" + QString::fromStdString(*sc)
173 + "</i> which is not known<br>";
174 m_ui->textBrowser->insertHtml(warning);
175 m_ui->textBrowser->show();
176 ok = false;
177 continue;
178 }
179 auto file = sclass->get_file()->get_full_file_name();
180 if (file != m_filename && !m_all_includes.contains(file)) {
181 m_missing_includes.insert(file);
182 QString warning = "<b>Warning</b> class <i>"
183 + QString::fromStdString(cls->get_name())
184 + "</i> refers to super class <i>" + QString::fromStdString(*sc)
185 + "</i> from " + QString::fromStdString(file)
186 + " which is not included<br>";
187 m_ui->textBrowser->insertHtml(warning);
188 m_ui->textBrowser->show();
189 ok = false;
190 }
191 }
192 }
193 return ok;
194}
195
197 std::cout << "Removing include file " << filename << "\n";
198
199 auto temp_files = m_all_includes;
200 temp_files.erase(filename);
201 temp_files.insert(m_filename);
202
204 for (auto cls: classes) {
205 // Ignore classes in file we're removing
206 if (cls->get_file()->get_full_file_name() != filename) {
207 auto relationships = cls->direct_relationships();
208 if (relationships != nullptr) {
209 for (auto rel: *relationships) {
210 auto file = rel->get_class_type()->get_file()->get_full_file_name();
211 if (!temp_files.contains(file)) {
212 auto message = QString(
213 "Cannot remove %1 as class %2 has relationship to its %3 class").arg(
214 QString::fromStdString(filename)).arg(
215 QString::fromStdString(cls->get_name())).arg(
216 QString::fromStdString(rel->get_class_type()->get_name()));
217 QMessageBox::warning ( 0, "Schema editor", message );
218 return;
219 }
220 }
221 }
222 auto super_classes = cls->direct_super_classes();
223 if (super_classes != nullptr) {
224 for (auto sc: *super_classes) {
225 auto sclass = KernelWrapper::GetInstance().FindClass(*sc);
226 auto file = sclass->get_file()->get_full_file_name();
227 if (!temp_files.contains(file)) {
228 auto message = QString(
229 "Cannot remove %1 as class %2 has superclass %3 in %1").arg(
230 QString::fromStdString(filename)).arg(
231 QString::fromStdString(cls->get_name())).arg(
232 QString::fromStdString(*sc));
233 QMessageBox::warning ( 0, "Schema editor", message );
234 return;
235 }
236 }
237 }
238 }
239 }
240 try {
244 }
246 QMessageBox::warning (0, "Schema editor", QString::fromStdString(exc.what()));
247 }
248
249 get_includes();
251 show_status();
252}
253
255 auto item = m_ui->include_list->currentItem();
256 std::string fn = item->text().toStdString();
257 remove_include (fn);
258}
259
260
262 close();
263}
264
266 close();
267}
268
270 if (event->key() == Qt::Key_Escape) {
271 close();
272 }
273 QWidget::keyPressEvent(event);
274}
275
276void SchemaFileInfo::launch_class_editor(QListWidgetItem* item) {
277 SchemaClassEditor::launch(item->text());
278}
279
281 m_ui->class_list->clear();
282 m_ui->textBrowser->clear();
284 for (auto cls: classes) {
285 auto item = new QListWidgetItem(QString::fromStdString(cls->get_name()));
286
287 if (!KernelWrapper::GetInstance().IsFileWritable ( m_filename )) {
288 item->setForeground(QBrush(SchemaStyle::get_color("foreground", "readonly")));
289 item->setBackground(QBrush(SchemaStyle::get_color("background", "readonly")));
290 }
291 if (!check_relationships(cls)) {
292 item->setForeground(QBrush(SchemaStyle::get_color("foreground", "error")));
293 item->setBackground(QBrush(SchemaStyle::get_color("background", "error")));
294 }
295 if (!check_superclasses(cls)) {
296 item->setForeground(QBrush(SchemaStyle::get_color("foreground", "error")));
297 item->setBackground(QBrush(SchemaStyle::get_color("background", "error")));
298 }
299
300 m_ui->class_list->addItem(item);
301 }
302 m_ui->class_summary->setText (
303 QString("Total of %1 classes").arg(classes.size()));
304
305 // if (!m_missing_includes.empty() && m_missing_button == nullptr) {
306 // m_missing_button = m_ui->buttonBox->addButton("Add missing includes", QDialogButtonBox::ApplyRole);
307 // if (m_missing_button != nullptr) {
308 // connect ( m_missing_button, SIGNAL (pressed()), this, SLOT(add_missing_includes()));
309 // }
310 // else {
311 // std::cout << "Failed to add button\n";
312 // }
313 // }
314 if (m_missing_includes.empty()) {
315 m_ui->missing_button->setEnabled(false);
316 m_ui->missing_button->hide();
317 }
318 else {
319 m_ui->missing_button->setEnabled(true);
320 m_ui->missing_button->show();
321 }
322}
323
324void SchemaFileInfo::class_updated(QString /*class_name*/) {
325 // auto cls = KernelWrapper::GetInstance().FindClass(class_name.toStdString());
326 // auto file = cls->get_file()->get_full_file_name();
327 // if (file == m_filename) {
328 show_status();
330 // }
331}
332
334 try {
336 }
337 catch (const dunedaq::oks::exception& exc) {
338 QMessageBox::warning(0,
339 "Save Schema",
340 QString("Failed to save file %1" )
341 .arg (m_filename.c_str())
342 .append(QString(exc.what())),
343 QMessageBox::Ok);
344 }
345 show_status();
346 emit files_updated();
347}
348
350 QString status;
351 if (KernelWrapper::GetInstance().IsFileWritable ( m_filename )) {
352 status.append("Read/Write");
353 }
354 else {
355 status.append("Read only");
356 }
357 if (KernelWrapper::GetInstance().is_file_modified ( m_filename )) {
358 status.append(" Modified");
359 m_ui->save_button->setEnabled(true);
360 }
361 else {
362 m_ui->save_button->setEnabled(false);
363 }
364
365 if (m_filename == KernelWrapper::GetInstance().GetActiveSchema()) {
366 status.append(" Active");
367 m_ui->active_button->setEnabled(false);
368 }
369 else if (KernelWrapper::GetInstance().IsFileWritable (m_filename)) {
370 m_ui->active_button->setEnabled(true);
371 }
372 m_ui->status->setText(status);
373}
374
376 auto fd = new QFileDialog ( this, tr ( "Open File" ), ".",
377 tr ( "XML schema files (*.schema.xml)" ) );
378 fd->setFileMode ( QFileDialog::ExistingFiles );
379 fd->setViewMode ( QFileDialog::Detail );
380 fd->setAcceptMode ( QFileDialog::AcceptOpen );
381 fd->setSidebarUrls(m_path_urls);
382 fd->exec();
383 auto files = fd->selectedFiles();
384 for (auto file: files) {
385 add_file(file.toStdString());
386 }
387 get_includes();
389 show_status();
390}
391
393 std::cout << "\nAdding missing include files:\n";
394
395 for (auto file: m_missing_includes) {
396 add_file(file);
397 }
398 m_missing_includes.clear();
399
400 get_includes();
401 m_ui->textBrowser->clear();
402 m_ui->textBrowser->hide();
403
404 get_includes();
406 show_status();
407}
408
409std::string SchemaFileInfo::prune_path(std::string file) {
410 for ( QString & element : m_path_list ) {
411 if (file.starts_with(element.toStdString())) {
412 file = file.substr (element.size());
413 break;
414 }
415 }
416 return file;
417}
418 void dbse::SchemaFileInfo::add_file(std::string file) {
419 std::cout << " " << file << "\n";
420 try {
421 KernelWrapper::GetInstance().AddInclude(m_filename, prune_path(file));
422 emit files_updated();
423 }
424 catch (std::exception& exc) {
425 QString message = QString(
426 "Failed to add %1 to included files, %2" ).arg(
427 QString::fromStdString(file)).arg(exc.what());
428 QMessageBox::warning ( 0, "Schema editor", message );
429 }
430}
431
433{
434 if (m_include_menu == nullptr) {
435 m_include_menu = new QMenu (this);
436
437 if (KernelWrapper::GetInstance().IsFileWritable ( m_filename )) {
438 QAction* add = new QAction ( tr ( "Add New Include File" ), this );
439 connect (add, SIGNAL ( triggered() ), this, SLOT ( add_include() ) );
440 QAction* remove = new QAction ( tr ( "Remove Selected Include File" ), this );
441 connect (remove, SIGNAL ( triggered() ), this, SLOT ( remove_include() ) );
442 m_include_menu->addAction ( add );
443 m_include_menu->addAction ( remove );
444 }
445 QAction* info = new QAction ( tr ( "Show file info" ), this );
446 connect (info, SIGNAL ( triggered() ), this, SLOT ( show_file_info() ) );
447
448 m_include_menu->addAction ( info );
449 }
450
451 if (m_ui->include_list->currentIndex().isValid()) {
452 m_include_menu->exec (m_ui->include_list->mapToGlobal(pos));
453 }
454}
455
457{
458 if (m_class_menu == nullptr) {
459 m_class_menu = new QMenu (this);
460
461 QAction * add = new QAction (tr("&Add New Class"), this );
462 connect (add, SIGNAL (triggered()), this, SLOT (add_new_class()));
463
464 QAction* remove = new QAction(tr("&Remove Selected Class"), this );
465 connect (remove, SIGNAL(triggered()), this, SLOT(remove_class()));
466
467 QAction* edit = new QAction(tr( "&Edit Selected Class"), this );
468 connect (edit, SIGNAL (triggered()), this, SLOT (edit_class()));
469
470 QAction* move = new QAction(tr( "&Move Selected Class"), this );
471 connect (move, SIGNAL (triggered()), this, SLOT (move_class()));
472
473 m_class_menu->addAction (add);
474 m_class_menu->addAction (edit);
475 m_class_menu->addAction (move);
476 m_class_menu->addAction (remove);
477 }
478
479 if (m_ui->class_list->currentIndex().isValid()) {
480 m_class_menu->exec (m_ui->class_list->mapToGlobal(pos));
481 }
482}
483
485{
486 SchemaClassEditor::launch(m_ui->class_list->currentItem()->text());
487}
489{
490 auto oks_class = KernelWrapper::GetInstance().FindClass(
491 m_ui->class_list->currentItem()->text().toStdString());
492 SchemaClassEditor::move_class(oks_class, this);
493}
495{
496 auto item = m_ui->class_list->currentItem();
497 QString cn = item->text();
498 dunedaq::oks::OksClass* schema_class =
499 KernelWrapper::GetInstance().FindClass(cn.toStdString());
500 if (schema_class->all_sub_classes()->size() != 0) {
501 QMessageBox::warning ( 0, "Schema editor",
502 QString ( "Cannot delete class because it has sub-classes." ) );
503 return;
504 }
505 else if (KernelWrapper::GetInstance().AnyClassReferenceThis(schema_class)) {
506 QMessageBox::warning (0, "Schema editor",
507 QString ( "Cannot delete class because some other classes references it."));
508 return;
509 }
510
512 schema_class->get_name(),
513 schema_class->get_description(),
514 schema_class->get_is_abstract() );
515 delete item;
516 m_ui->class_list->update();
517}
518
520 try {
522 }
524 auto qfn = QString::fromStdString(m_filename);
525 auto text = QString("Could not make schema file %1 active!\n\n").arg(qfn);
526 QMessageBox::warning(0,
527 "Set Active Schema",
528 text.append(QString(exc.what())),
529 QMessageBox::Ok);
530 return false;
531 }
532 show_status();
533 return true;
534}
535
536
538 auto item = m_ui->include_list->currentItem();
539 std::string fn = item->text().toStdString();
540 set_active (fn);
541 show_status();
542}
543
545 set_active (m_filename);
546 show_status();
547}
548
549
551{
552 if (set_active (m_filename)) {
554 if (!nc.isEmpty()) {
555 auto item = new QListWidgetItem(nc);
556 m_ui->class_list->addItem(item);
557 m_ui->class_list->sortItems();
558 m_ui->class_list->setCurrentItem(item);
559 m_ui->class_list->update();
560 }
561 }
562}
563
564
565
567 show_file_info(m_ui->include_list->currentItem());
568}
569void dbse::SchemaFileInfo::show_file_info(QListWidgetItem* item) {
570 show_file_info(item->text());
571}
573 bool widget_found = false;
574 for ( QWidget * widget : QApplication::allWidgets() ) {
575 auto sfi = dynamic_cast<SchemaFileInfo *> ( widget );
576 if ( sfi != nullptr ) {
577 if ( (sfi->objectName() ).compare ( fn ) == 0 ) {
578 sfi->raise();
579 sfi->setVisible ( true );
580 sfi->activateWindow();
581 widget_found = true;
582 break;
583 }
584 }
585 }
586 if ( !widget_found ) {
587 auto info = new SchemaFileInfo(fn.toStdString());
588 // connect (info, &SchemaFileInfo::files_updated,
589 // this, &SchemaMainWindow::update_models);
590 emit new_window(this);
591 info->show();
592 }
593}
594} //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)