2022-03-29 19:31:45 +00:00
|
|
|
#include "mainwindow.h"
|
|
|
|
#include "ui_mainwindow.h"
|
|
|
|
|
2022-04-07 22:21:23 +00:00
|
|
|
#include <QFileDialog>
|
|
|
|
#include <QHBoxLayout>
|
|
|
|
|
2022-05-27 06:18:17 +00:00
|
|
|
#include <comdel/parser/parse_context.h>
|
|
|
|
#include <comdel/parser/parser_util.h>
|
|
|
|
#include <comdel/domain/schema_creator.h>
|
2022-04-07 22:21:23 +00:00
|
|
|
|
|
|
|
#include <iostream>
|
2022-04-09 19:11:17 +00:00
|
|
|
#include <QPlainTextEdit>
|
2022-05-27 06:18:17 +00:00
|
|
|
#include <comdel/domain/comdel_validator.h>
|
2022-04-24 20:21:45 +00:00
|
|
|
#include <fstream>
|
2022-05-08 22:51:47 +00:00
|
|
|
#include <comdel/domain/comdel_generator.h>
|
2022-04-07 22:21:23 +00:00
|
|
|
|
2022-05-15 16:38:17 +00:00
|
|
|
std::optional<domain::Library> MainWindow::library;
|
|
|
|
domain::Schema* MainWindow::schema;
|
|
|
|
|
2022-03-29 19:31:45 +00:00
|
|
|
MainWindow::MainWindow(QWidget *parent)
|
|
|
|
: QMainWindow(parent)
|
|
|
|
, ui(new Ui::MainWindow)
|
|
|
|
{
|
2022-05-15 16:38:17 +00:00
|
|
|
schema = nullptr;
|
|
|
|
library = std::nullopt;
|
|
|
|
|
2022-03-29 19:31:45 +00:00
|
|
|
ui->setupUi(this);
|
2022-04-07 22:21:23 +00:00
|
|
|
|
|
|
|
setupUi();
|
|
|
|
|
|
|
|
// define allowed methods
|
2022-05-15 09:17:05 +00:00
|
|
|
validators = domain::getSupportedValidators();
|
2022-04-07 22:21:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::setupUi()
|
|
|
|
{
|
2022-04-12 21:37:05 +00:00
|
|
|
setWindowTitle("COMDEL schema editor");
|
|
|
|
|
2022-04-07 22:21:23 +00:00
|
|
|
auto layout = new QHBoxLayout();
|
|
|
|
ui->centralwidget->setLayout(layout);
|
|
|
|
|
|
|
|
// setup toolbar
|
|
|
|
ui->toolBar->addAction("Load library", this, &MainWindow::onLoadLibrary);
|
|
|
|
ui->toolBar->addAction("Load schema", this, &MainWindow::onLoadSchema);
|
2022-04-24 20:21:45 +00:00
|
|
|
ui->toolBar->addAction("Save schema", this, &MainWindow::onStoreScheme);
|
2022-05-08 22:51:47 +00:00
|
|
|
ui->toolBar->addAction("Generate system", this, &MainWindow::onGenerateComdel);
|
2022-04-07 22:21:23 +00:00
|
|
|
|
2022-04-10 12:23:18 +00:00
|
|
|
connect(ui->actionValidate, &QAction::triggered, this, &MainWindow::onValidateSchema);
|
|
|
|
|
2022-04-07 22:21:23 +00:00
|
|
|
// setup central content
|
|
|
|
libraryDisplay = new display::Library();
|
2022-04-09 19:11:17 +00:00
|
|
|
|
|
|
|
auto schemaParent = new QWidget();
|
|
|
|
auto schemaLayout = new QVBoxLayout();
|
|
|
|
schemaParent->setLayout(schemaLayout);
|
|
|
|
|
2022-04-07 22:21:23 +00:00
|
|
|
schemaDisplay = new display::Schema();
|
2022-04-09 19:11:17 +00:00
|
|
|
schemaLayout->setMargin(0);
|
|
|
|
schemaLayout->addWidget(schemaDisplay, 1);
|
2022-04-07 22:21:23 +00:00
|
|
|
|
|
|
|
layout->setMargin(0);
|
|
|
|
layout->addWidget(libraryDisplay);
|
2022-04-09 19:11:17 +00:00
|
|
|
layout->addWidget(schemaParent, 1);
|
2022-04-07 22:21:23 +00:00
|
|
|
|
2022-04-09 19:11:17 +00:00
|
|
|
log = new QPlainTextEdit();
|
|
|
|
log->setFont(QFont("Courier"));
|
2022-04-12 21:37:05 +00:00
|
|
|
log->setReadOnly(false);
|
2022-04-09 19:11:17 +00:00
|
|
|
schemaLayout->addWidget(log);
|
2022-04-07 22:21:23 +00:00
|
|
|
}
|
|
|
|
|
2022-04-12 21:37:05 +00:00
|
|
|
void MainWindow::onLoadLibrary() {
|
|
|
|
auto filename = QFileDialog::getOpenFileName(this,
|
|
|
|
tr("Open library"), "/home", tr("Comdel library (*.csl)"));
|
2022-04-07 22:21:23 +00:00
|
|
|
|
2022-04-09 19:11:17 +00:00
|
|
|
std::ostringstream buffer;
|
|
|
|
|
2022-04-12 21:37:05 +00:00
|
|
|
log->clear();
|
|
|
|
|
2022-04-07 22:21:23 +00:00
|
|
|
if(!filename.isEmpty()) {
|
2022-04-24 20:21:45 +00:00
|
|
|
librarySource = filename.toStdString();
|
|
|
|
|
2022-04-07 22:21:23 +00:00
|
|
|
clear();
|
|
|
|
|
|
|
|
ParseContext parseContext;
|
2022-05-27 06:18:17 +00:00
|
|
|
auto libraryNode = load_library_from_file(&parseContext, filename.toStdString().c_str(), buffer);
|
2022-04-12 21:37:05 +00:00
|
|
|
if(libraryNode) {
|
2022-05-15 09:17:05 +00:00
|
|
|
domain::SchemaCreator generator(validators);
|
2022-04-12 21:37:05 +00:00
|
|
|
library = generator.loadLibrary(*libraryNode);
|
2022-04-07 22:21:23 +00:00
|
|
|
|
2022-04-09 19:11:17 +00:00
|
|
|
for (auto& error : generator.getErrors()) {
|
2022-04-24 20:21:45 +00:00
|
|
|
parseContext.formatError(error, buffer, "ERROR: ");
|
2022-04-09 19:11:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(generator.getErrors().empty()) {
|
|
|
|
libraryDisplay->setLibrary(library);
|
2022-04-12 21:37:05 +00:00
|
|
|
|
|
|
|
// on library load we create a new schema
|
2022-04-18 09:41:02 +00:00
|
|
|
schema = new domain::Schema();
|
2022-05-23 06:48:13 +00:00
|
|
|
schemaDisplay->setSchema(schema, &(*library));
|
2022-04-07 22:21:23 +00:00
|
|
|
}
|
|
|
|
|
2022-04-12 21:37:05 +00:00
|
|
|
} else {
|
2022-05-01 16:13:01 +00:00
|
|
|
buffer<<"Failed loading library"<<std::endl;
|
2022-04-07 22:21:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-09 19:11:17 +00:00
|
|
|
log->appendPlainText(QString::fromStdString(buffer.str()));
|
2022-04-07 22:21:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::onLoadSchema() {
|
|
|
|
auto filename = QFileDialog::getOpenFileName(this,
|
|
|
|
tr("Open schema"), "/home", tr("Comdel schema (*.csl)"));
|
|
|
|
|
2022-04-12 21:37:05 +00:00
|
|
|
std::ostringstream buffer;
|
|
|
|
|
|
|
|
log->clear();
|
|
|
|
|
2022-04-07 22:21:23 +00:00
|
|
|
if(!filename.isEmpty()) {
|
|
|
|
clear();
|
|
|
|
|
|
|
|
ParseContext parseContext;
|
2022-05-27 06:18:17 +00:00
|
|
|
auto schemaNode = load_schema_from_file(&parseContext, filename.toStdString().c_str(), buffer);
|
2022-04-07 22:21:23 +00:00
|
|
|
|
|
|
|
if(schemaNode) {
|
2022-05-15 09:17:05 +00:00
|
|
|
domain::SchemaCreator generator(validators);
|
2022-04-07 22:21:23 +00:00
|
|
|
library = generator.loadLibrary(*schemaNode->library);
|
|
|
|
|
2022-05-27 06:18:17 +00:00
|
|
|
librarySource = schemaNode->source->asString();
|
2022-04-24 20:21:45 +00:00
|
|
|
|
2022-04-07 22:21:23 +00:00
|
|
|
for (auto& error : generator.getErrors()) {
|
2022-04-24 20:21:45 +00:00
|
|
|
parseContext.formatError(error, buffer, "ERROR: ");
|
2022-04-07 22:21:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(library) {
|
|
|
|
schema = generator.loadSchema(*schemaNode, *library);
|
|
|
|
|
|
|
|
for (auto& error : generator.getErrors()) {
|
2022-04-24 20:21:45 +00:00
|
|
|
parseContext.formatError(error, buffer, "ERROR: ");
|
2022-05-08 13:47:47 +00:00
|
|
|
delete schema;
|
|
|
|
schema = nullptr;
|
2022-04-07 22:21:23 +00:00
|
|
|
}
|
2022-05-08 13:47:47 +00:00
|
|
|
} else {
|
|
|
|
library = std::nullopt;
|
2022-04-07 22:21:23 +00:00
|
|
|
}
|
|
|
|
|
2022-04-12 21:37:05 +00:00
|
|
|
if(generator.getErrors().empty()) {
|
|
|
|
libraryDisplay->setLibrary(library);
|
2022-05-23 06:48:13 +00:00
|
|
|
schemaDisplay->setSchema(schema, &(*library));
|
2022-04-12 21:37:05 +00:00
|
|
|
}
|
2022-04-07 22:21:23 +00:00
|
|
|
}
|
|
|
|
}
|
2022-04-12 21:37:05 +00:00
|
|
|
|
|
|
|
log->appendPlainText(QString::fromStdString(buffer.str()));
|
2022-04-10 12:23:18 +00:00
|
|
|
}
|
|
|
|
|
2022-04-24 20:21:45 +00:00
|
|
|
void MainWindow::onStoreScheme() {
|
|
|
|
if(schema == nullptr) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto filename = QFileDialog::getSaveFileName(this,
|
|
|
|
tr("Save schema"), "/home", tr("Comdel schema (*.csl)"));
|
|
|
|
|
|
|
|
std::ostringstream buffer;
|
|
|
|
|
2022-05-27 06:18:17 +00:00
|
|
|
domain::generate_schema(librarySource, schema, buffer);
|
2022-04-24 20:21:45 +00:00
|
|
|
|
2022-05-08 22:51:47 +00:00
|
|
|
std::ofstream out(filename.toStdString(), std::ios::out | std::ios::binary);
|
|
|
|
out<<buffer.str();
|
|
|
|
out.close();
|
|
|
|
}
|
2022-04-24 20:21:45 +00:00
|
|
|
|
2022-05-08 22:51:47 +00:00
|
|
|
void MainWindow::onGenerateComdel() {
|
|
|
|
if(schema == nullptr) {
|
|
|
|
return;
|
2022-04-24 20:21:45 +00:00
|
|
|
}
|
|
|
|
|
2022-05-08 22:51:47 +00:00
|
|
|
auto filename = QFileDialog::getSaveFileName(this,
|
|
|
|
tr("Save schema"), "/home", tr("Comdel system (*.system)"));
|
2022-04-24 20:21:45 +00:00
|
|
|
|
2022-05-08 22:51:47 +00:00
|
|
|
std::ostringstream buffer;
|
2022-04-24 20:21:45 +00:00
|
|
|
|
2022-05-27 06:18:17 +00:00
|
|
|
domain::generate_comdel(schema, library.value(), buffer);
|
2022-04-24 20:21:45 +00:00
|
|
|
|
|
|
|
std::ofstream out(filename.toStdString(), std::ios::out | std::ios::binary);
|
|
|
|
out<<buffer.str();
|
|
|
|
out.close();
|
|
|
|
}
|
|
|
|
|
2022-05-08 22:51:47 +00:00
|
|
|
|
2022-04-10 12:23:18 +00:00
|
|
|
void MainWindow::onValidateSchema(bool /*toggled*/) {
|
2022-04-18 09:41:02 +00:00
|
|
|
if(schema == nullptr) {
|
2022-04-12 21:37:05 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-05-19 19:08:00 +00:00
|
|
|
log->clear();
|
|
|
|
|
2022-04-10 12:23:18 +00:00
|
|
|
this->validationErrors.clear();
|
|
|
|
|
2022-05-15 09:17:05 +00:00
|
|
|
domain::ComdelValidator validator{validators};
|
2022-04-10 12:23:18 +00:00
|
|
|
|
|
|
|
domain::ValidationContext context;
|
|
|
|
context.instance = nullptr;
|
|
|
|
context.attribute = nullptr;
|
|
|
|
context.addressSpaces = {};
|
|
|
|
|
|
|
|
for(auto &lib: library->getAddressSpaces()) {
|
|
|
|
context.addressSpaces.insert(std::make_pair(lib.getName(), lib));
|
|
|
|
}
|
|
|
|
auto errors = validator.validateSchema(*schema, context);
|
|
|
|
|
2022-05-19 22:44:40 +00:00
|
|
|
auto countValidation = validator.validateInstanceCount(*schema, *library, context);
|
|
|
|
errors.insert(errors.end(), countValidation.begin(), countValidation.end());
|
|
|
|
|
|
|
|
auto pinValidation = validator.validatePinConnections(*schema, *library, context);
|
|
|
|
errors.insert(errors.end(), pinValidation.begin(), pinValidation.end());
|
|
|
|
|
2022-04-10 12:23:18 +00:00
|
|
|
errors.erase(std::remove_if(
|
|
|
|
errors.begin(), errors.end(), [](const domain::ValidationError& error) { return error.type == domain::Action::WARNING;}),
|
|
|
|
errors.end());
|
|
|
|
|
|
|
|
std::ostringstream buff;
|
|
|
|
|
|
|
|
for(auto err: errors) {
|
2022-05-01 16:13:01 +00:00
|
|
|
if(err.instance != nullptr) {
|
2022-04-10 12:23:18 +00:00
|
|
|
buff << err.instance->name;
|
|
|
|
}
|
2022-05-01 16:13:01 +00:00
|
|
|
if(err.attribute != nullptr) {
|
2022-04-10 12:23:18 +00:00
|
|
|
buff << "::" << err.attribute->name;
|
|
|
|
}
|
|
|
|
if(err.type == domain::Action::ERROR) {
|
|
|
|
buff << " [ERROR] ";
|
|
|
|
} else {
|
|
|
|
buff << " [WARNING] ";
|
|
|
|
}
|
|
|
|
buff << err.message << std::endl;
|
|
|
|
}
|
2022-04-07 22:21:23 +00:00
|
|
|
|
2022-04-10 12:23:18 +00:00
|
|
|
log->appendPlainText(QString::fromStdString(buff.str()));
|
|
|
|
|
|
|
|
validationErrors = errors;
|
2022-04-07 22:21:23 +00:00
|
|
|
}
|
|
|
|
|
2022-04-10 12:23:18 +00:00
|
|
|
|
2022-04-07 22:21:23 +00:00
|
|
|
void MainWindow::clear() {
|
2022-04-10 12:23:18 +00:00
|
|
|
validationErrors.clear();
|
2022-05-08 13:47:47 +00:00
|
|
|
if(schema != nullptr) {
|
|
|
|
delete schema;
|
|
|
|
schema = nullptr;
|
|
|
|
}
|
2022-04-07 22:21:23 +00:00
|
|
|
library = std::nullopt;
|
|
|
|
|
|
|
|
libraryDisplay->setLibrary(library);
|
2022-05-23 06:48:13 +00:00
|
|
|
schemaDisplay->setSchema(schema, nullptr);
|
2022-03-29 19:31:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
MainWindow::~MainWindow()
|
|
|
|
{
|
|
|
|
delete ui;
|
2022-04-24 20:21:45 +00:00
|
|
|
}
|