Extracted schema and library management to Application
This commit is contained in:
parent
0c4afe87d9
commit
86b8861533
|
@ -37,5 +37,5 @@ add_executable(SchemeEditor
|
|||
comdel/parser/comdellexer.cpp
|
||||
main.cpp
|
||||
mainwindow.ui
|
||||
comdel/domain/comdel_validator.cpp comdel/domain/comdel_validator.h comdel/display/attribute_dialog.cpp comdel/display/attribute_dialog.h comdel/display/name_dialog.cpp comdel/display/name_dialog.h comdel/domain/comdel_generator.cpp comdel/domain/comdel_generator.h comdel/display/library_list.cpp comdel/display/library_list.h)
|
||||
comdel/domain/comdel_validator.cpp comdel/domain/comdel_validator.h comdel/display/attribute_dialog.cpp comdel/display/attribute_dialog.h comdel/display/name_dialog.cpp comdel/display/name_dialog.h comdel/domain/comdel_generator.cpp comdel/domain/comdel_generator.h comdel/display/library_list.cpp comdel/display/library_list.h application.cpp application.h)
|
||||
target_link_libraries(SchemeEditor Qt5::Core Qt5::Gui Qt5::Widgets)
|
||||
|
|
|
@ -0,0 +1,160 @@
|
|||
//
|
||||
// Created by bbr on 27.05.22..
|
||||
//
|
||||
|
||||
#include "application.h"
|
||||
#include "comdel/parser/parse_context.h"
|
||||
#include "comdel/parser/parser_util.h"
|
||||
#include "comdel/domain/schema_creator.h"
|
||||
#include "comdel/domain/comdel_generator.h"
|
||||
#include "comdel/domain/comdel_validator.h"
|
||||
|
||||
std::optional<domain::Library> Application::getLibrary() {
|
||||
return library;
|
||||
}
|
||||
|
||||
domain::Schema *Application::getSchema() {
|
||||
return schema;
|
||||
}
|
||||
|
||||
void Application::clear() {
|
||||
if(schema != nullptr) {
|
||||
delete schema;
|
||||
schema = nullptr;
|
||||
}
|
||||
library = std::nullopt;
|
||||
libraryPath = "";
|
||||
}
|
||||
|
||||
bool Application::loadLibrary(std::string& filename, std::ostream &errorOutput) {
|
||||
clear();
|
||||
|
||||
ParseContext parseContext;
|
||||
auto libraryNode = load_library_from_file(&parseContext, filename.c_str(), errorOutput);
|
||||
if(libraryNode) {
|
||||
domain::SchemaCreator generator(validators);
|
||||
library = generator.loadLibrary(*libraryNode);
|
||||
|
||||
for (auto& error : generator.getErrors()) {
|
||||
parseContext.formatError(error, errorOutput, "ERROR: ");
|
||||
}
|
||||
|
||||
if(library.has_value()) {
|
||||
libraryPath = filename;
|
||||
// on library load we create a new schema
|
||||
schema = new domain::Schema();
|
||||
} else {
|
||||
errorOutput<<"Failed creating library model"<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
} else {
|
||||
errorOutput<<"Failed parsing library"<<std::endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Application::loadSchema(std::string &filename, std::ostream &errorOutput) {
|
||||
clear();
|
||||
|
||||
ParseContext parseContext;
|
||||
auto schemaNode = load_schema_from_file(&parseContext, filename.c_str(), errorOutput);
|
||||
|
||||
if(schemaNode) {
|
||||
domain::SchemaCreator generator(validators);
|
||||
library = generator.loadLibrary(*schemaNode->library);
|
||||
|
||||
libraryPath = schemaNode->source->asString();
|
||||
|
||||
for (auto& error : generator.getErrors()) {
|
||||
parseContext.formatError(error, errorOutput, "ERROR: ");
|
||||
}
|
||||
|
||||
if(library) {
|
||||
schema = generator.loadSchema(*schemaNode, *library);
|
||||
|
||||
for (auto& error : generator.getErrors()) {
|
||||
parseContext.formatError(error, errorOutput, "ERROR: ");
|
||||
}
|
||||
|
||||
if(schema == nullptr) {
|
||||
clear();
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
} else {
|
||||
errorOutput<<"Failed parsing library"<<std::endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Application::generateSchema(std::ostringstream &output) {
|
||||
if(schema == nullptr) {
|
||||
return false;
|
||||
}
|
||||
domain::generate_schema(libraryPath, schema, output);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<domain::ValidationError> Application::validateSchema() {
|
||||
if(schema == nullptr) {
|
||||
return std::vector<domain::ValidationError>{domain::ValidationError(domain::Action::ERROR, "No schema loaded")};
|
||||
}
|
||||
|
||||
domain::ComdelValidator validator{validators};
|
||||
|
||||
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);
|
||||
|
||||
auto countValidation = validator.validateInstanceCount(*schema, *library, context);
|
||||
errors.insert(errors.end(), countValidation.begin(), countValidation.end());
|
||||
|
||||
auto nameValidation = validator.validateInstanceNames(*schema, *library, context);
|
||||
errors.insert(errors.end(), nameValidation.begin(), nameValidation.end());
|
||||
|
||||
auto pinValidation = validator.validatePinConnections(*schema, *library, context);
|
||||
errors.insert(errors.end(), pinValidation.begin(), pinValidation.end());
|
||||
return errors;
|
||||
}
|
||||
|
||||
std::vector<domain::ValidationError> Application::generateComdel(std::ostringstream &output) {
|
||||
|
||||
auto errors = validateSchema();
|
||||
if(Application::hasErrors(errors)) {
|
||||
// as long as all validation errors are warning we continue with build
|
||||
domain::generate_comdel(schema, library.value(), output);
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
|
||||
bool Application::hasErrors(std::vector<domain::ValidationError> errors) {
|
||||
for(auto& err: errors) {
|
||||
if(err.type == domain::Action::ERROR) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// static instance of application
|
||||
static Application *application = nullptr;
|
||||
|
||||
Application *Application::instance() {
|
||||
if(application == nullptr) {
|
||||
application = new Application();
|
||||
}
|
||||
return application;
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
//
|
||||
// Created by bbr on 27.05.22..
|
||||
//
|
||||
|
||||
#ifndef SCHEMEEDITOR_APPLICATION_H
|
||||
#define SCHEMEEDITOR_APPLICATION_H
|
||||
|
||||
|
||||
#include "comdel/domain/library.h"
|
||||
#include "comdel/domain/schema.h"
|
||||
#include "comdel/domain/comdel_validator.h"
|
||||
|
||||
|
||||
class Application {
|
||||
private:
|
||||
std::string libraryPath;
|
||||
std::optional<domain::Library> library = std::nullopt;
|
||||
domain::Schema* schema = nullptr;
|
||||
public:
|
||||
std::optional<domain::Library> getLibrary();
|
||||
domain::Schema* getSchema();
|
||||
std::vector<domain::FunctionValidator*> validators = domain::getSupportedValidators();
|
||||
|
||||
void clear();
|
||||
|
||||
bool loadLibrary(std::string& filename, std::ostream& errorOutput);
|
||||
bool loadSchema(std::string& filename, std::ostream& errorOutput);
|
||||
|
||||
static Application* instance();
|
||||
|
||||
bool generateSchema(std::ostringstream &output);
|
||||
std::vector<domain::ValidationError> validateSchema();
|
||||
std::vector<domain::ValidationError> generateComdel(std::ostringstream &output);
|
||||
|
||||
static bool hasErrors(std::vector<domain::ValidationError> empty);
|
||||
|
||||
~Application() = default;
|
||||
};
|
||||
|
||||
|
||||
#endif //SCHEMEEDITOR_APPLICATION_H
|
|
@ -5,6 +5,8 @@
|
|||
#include "attribute_dialog.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include "application.h"
|
||||
|
||||
namespace display {
|
||||
|
||||
void AttributeDialog::onUpdate() {
|
||||
|
@ -15,7 +17,7 @@ namespace display {
|
|||
|
||||
domain::ValidationContext context;
|
||||
|
||||
for (auto &addressSpace: MainWindow::getLibrary()->getAddressSpaces()) {
|
||||
for (auto &addressSpace: Application::instance()->getLibrary()->getAddressSpaces()) {
|
||||
context.addressSpaces.insert(std::make_pair(addressSpace.getName(), addressSpace));
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "attribute_dialog.h"
|
||||
#include "name_dialog.h"
|
||||
#include "mainwindow.h"
|
||||
#include "application.h"
|
||||
|
||||
#include <QMenu>
|
||||
#include <QLine>
|
||||
|
@ -24,7 +25,7 @@ namespace display {
|
|||
[attr]() {
|
||||
if (attr->value.getType() == domain::Value::MEMORY_REFERENCE) {
|
||||
auto dialog = new MemoryDialog(attr,
|
||||
MainWindow::getSchema()->componentInstances);
|
||||
Application::instance()->getSchema()->componentInstances);
|
||||
dialog->exec();
|
||||
} else {
|
||||
auto dialog = new AttributeDialog(attr);
|
||||
|
|
|
@ -10,13 +10,14 @@ namespace display {
|
|||
Schema::Schema() {
|
||||
this->selectedBrush.setColor(QColor::fromRgb(20, 20, 125));
|
||||
this->selectedPen.setColor(QColor::fromRgb(20, 20, 125));
|
||||
|
||||
schema = nullptr;
|
||||
library = std::nullopt;
|
||||
this->setScene(&scene);
|
||||
this->setAcceptDrops(true);
|
||||
}
|
||||
|
||||
|
||||
void Schema::setSchema(domain::Schema *_schema, domain::Library *_library) {
|
||||
void Schema::setSchema(domain::Schema *_schema, std::optional<domain::Library> _library) {
|
||||
components.clear();
|
||||
buses.clear();
|
||||
|
||||
|
@ -216,6 +217,9 @@ namespace display {
|
|||
|
||||
for (auto bus: busInstances) {
|
||||
auto &group = buses[bus->name];
|
||||
if(group == nullptr) {
|
||||
continue;
|
||||
}
|
||||
auto rect = new QGraphicsRectItem(group->boundingRect());
|
||||
rect->setPen(selectedPen);
|
||||
rect->setPos(group->scenePos());
|
||||
|
|
|
@ -46,7 +46,7 @@ namespace display {
|
|||
std::vector<BusConnection *> busConnections;
|
||||
std::vector<DirectConnection *> directConnections;
|
||||
|
||||
void setSchema(domain::Schema *schema, domain::Library *library);
|
||||
void setSchema(domain::Schema *schema, std::optional<domain::Library> library);
|
||||
|
||||
void updateConnections();
|
||||
|
||||
|
@ -65,8 +65,8 @@ namespace display {
|
|||
private:
|
||||
QGraphicsScene scene;
|
||||
|
||||
domain::Schema *schema;
|
||||
domain::Library *library;
|
||||
domain::Schema *schema{};
|
||||
std::optional<domain::Library> library;
|
||||
|
||||
std::vector<domain::BusInstance *>
|
||||
getAvailableConnectionBusses(domain::ComponentInstance *instance, domain::Pin &pin);
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#include <set>
|
||||
#include "comdel_validator.h"
|
||||
#include "library.h"
|
||||
|
||||
|
@ -38,11 +39,11 @@ namespace domain {
|
|||
auto message = populateMessage(
|
||||
"Not enough instances of component '{componentName}' required at least {min}, found {count}",
|
||||
context);
|
||||
errors.push_back(ValidationError{nullptr, nullptr, Action::ERROR, message});
|
||||
errors.emplace_back(Action::ERROR, message);
|
||||
} else if (count > comp.getCount().second) {
|
||||
auto message = populateMessage(
|
||||
"To many instances of component '{componentName}' allow at most {max}, found {count}", context);
|
||||
errors.push_back(ValidationError{nullptr, nullptr, Action::ERROR, message});
|
||||
errors.emplace_back(Action::ERROR, message);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,11 +65,11 @@ namespace domain {
|
|||
if (count < bus.getCount().first) {
|
||||
auto message = populateMessage(
|
||||
"Not enough instances of bus '{busName}' required at least {min}, found {count}", context);
|
||||
errors.push_back(ValidationError{nullptr, nullptr, Action::ERROR, message});
|
||||
errors.emplace_back(Action::ERROR, message);
|
||||
} else if (count > bus.getCount().second) {
|
||||
auto message = populateMessage(
|
||||
"To many instances of bus '{busName}' allow at most {max}, found {count}", context);
|
||||
errors.push_back(ValidationError{nullptr, nullptr, Action::ERROR, message});
|
||||
errors.emplace_back(Action::ERROR, message);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -86,7 +87,7 @@ namespace domain {
|
|||
context.instance = inst.get();
|
||||
context.attributes["instanceName"] = Value::fromString(inst->name);
|
||||
auto message = populateMessage(pin.getConnection().getMessage(), context);
|
||||
errors.push_back(ValidationError{nullptr, nullptr, Action::ERROR, message});
|
||||
errors.emplace_back(Action::ERROR, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -152,6 +153,24 @@ namespace domain {
|
|||
return nullopt;
|
||||
}
|
||||
|
||||
std::vector<ValidationError>
|
||||
ComdelValidator::validateInstanceNames(Schema &schema, Library &library, ValidationContext context) {
|
||||
std::set<std::string> names;
|
||||
std::vector<ValidationError> errors;
|
||||
|
||||
for(auto& component: schema.componentInstances) {
|
||||
if(names.find(component->name) != names.end()) {
|
||||
context.attributes["componentName"] = Value::fromString(component->name);
|
||||
auto message = populateMessage(
|
||||
"There are multiple component instances named '{componentName}'", context);
|
||||
errors.emplace_back(Action::ERROR, message);
|
||||
}
|
||||
names.insert(component->name);
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
|
||||
|
||||
std::string ComdelValidator::populateMessage(string source, ValidationContext context) {
|
||||
for (auto &[key, value]: context.attributes) {
|
||||
source = replacePlaceholder(source, key, value);
|
||||
|
@ -202,5 +221,4 @@ namespace domain {
|
|||
this->validators.insert(std::make_pair(validator->getName(), validator));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -12,6 +12,10 @@ namespace domain {
|
|||
InstanceAttribute *attribute;
|
||||
Action::ActionType type;
|
||||
std::string message;
|
||||
|
||||
ValidationError(Action::ActionType type, std::string message): instance(nullptr), attribute(nullptr), type(type), message(message) {}
|
||||
|
||||
ValidationError(ComponentInstance* instance, InstanceAttribute* attribute, Action::ActionType type, std::string message): instance(instance), attribute(attribute), type(type), message(message) {}
|
||||
};
|
||||
|
||||
struct ValidationContext {
|
||||
|
@ -31,6 +35,8 @@ namespace domain {
|
|||
|
||||
std::optional<ValidationError> validateRule(Rule rule, ValidationContext context);
|
||||
|
||||
std::vector<ValidationError> validateInstanceNames(Schema &schema, Library &library, ValidationContext context);
|
||||
|
||||
std::vector<ValidationError> validateInstanceCount(Schema &schema, Library &library, ValidationContext context);
|
||||
|
||||
std::vector<ValidationError>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
component System
|
||||
{
|
||||
clock 100MHz;
|
||||
//glavnaSabirnica
|
||||
//bus
|
||||
wire<32> ADR;
|
||||
wire<32> DATA;
|
||||
wire READ;
|
||||
|
@ -28,17 +28,21 @@ component System
|
|||
|
||||
|
||||
// components --------------------------------------------
|
||||
subcomponent Memorija memorija<false, 1, 65536, 8, 0>(ADR, DATA, READ, WRITE, SIZE, WAIT, INT);
|
||||
subcomponent FRISC procesor(ADR, DATA, READ, WRITE, SIZE, WAIT, INT0, INT1, INT2, INT3, --IACK, 1, *, INT) uses memorija;
|
||||
subcomponent Memorija mem<false, 1, 1024, 8, 1024>(ADR, DATA, READ, WRITE, SIZE, WAIT, INT);
|
||||
subcomponent FRISC proc(ADR, DATA, READ, WRITE, SIZE, WAIT, INT0, INT1, INT2, INT3, --IACK, 1, *, INT);
|
||||
subcomponent FRISC procesor(ADR, DATA, READ, WRITE, SIZE, WAIT, INT0, INT1, INT2, INT3, --IACK, 1, *, 93852075053817, 0, null, null);
|
||||
subcomponent FRISC procesor(ADR, DATA, READ, WRITE, SIZE, WAIT, INT0, INT1, INT2, INT3, --IACK, 1, *, 93852075053817, 0, null, null);
|
||||
|
||||
display {
|
||||
component { x: -582; y: -296; ref: "procesor"; }
|
||||
component { x: -446; y: -12; ref: "memorija"; }
|
||||
component { x: 0; y: 0; ref: "proc"; }
|
||||
component { x: 0; y: 250; ref: "mem"; }
|
||||
component { x: -185; y: 9; ref: "procesor"; }
|
||||
component { x: -181; y: 194; ref: "procesor"; }
|
||||
|
||||
// glavnaSabirnica bus
|
||||
// bus bus
|
||||
|
||||
rectangle {
|
||||
x: -581; y: -37;
|
||||
x: 0; y: 200;
|
||||
w: 100; h: 20;
|
||||
}
|
||||
|
||||
|
@ -46,8 +50,10 @@ component System
|
|||
// directRam bus
|
||||
|
||||
|
||||
line {x1:-532; y1:-180; x2:-530; y2:-26;}
|
||||
line {x1:-462; y1:16; x2:-466; y2:-246;}
|
||||
line {x1:-396; y1:-28; x2:-530; y2:-26;}
|
||||
line {x1:50; y1:116; x2:50; y2:210;}
|
||||
line {x1:50; y1:234; x2:50; y2:210;}
|
||||
line {x1:-16; y1:278; x2:116; y2:50;}
|
||||
line {x1:-135; y1:125; x2:50; y2:210;}
|
||||
line {x1:-131; y1:310; x2:50; y2:210;}
|
||||
}
|
||||
}
|
200
mainwindow.cpp
200
mainwindow.cpp
|
@ -1,5 +1,6 @@
|
|||
#include "mainwindow.h"
|
||||
#include "ui_mainwindow.h"
|
||||
#include "application.h"
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QHBoxLayout>
|
||||
|
@ -14,22 +15,13 @@
|
|||
#include <fstream>
|
||||
#include <comdel/domain/comdel_generator.h>
|
||||
|
||||
std::optional<domain::Library> MainWindow::library;
|
||||
domain::Schema* MainWindow::schema;
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent)
|
||||
: QMainWindow(parent)
|
||||
, ui(new Ui::MainWindow)
|
||||
{
|
||||
schema = nullptr;
|
||||
library = std::nullopt;
|
||||
|
||||
ui->setupUi(this);
|
||||
|
||||
setupUi();
|
||||
|
||||
// define allowed methods
|
||||
validators = domain::getSupportedValidators();
|
||||
}
|
||||
|
||||
void MainWindow::setupUi()
|
||||
|
@ -71,187 +63,123 @@ void MainWindow::setupUi()
|
|||
void MainWindow::onLoadLibrary() {
|
||||
auto filename = QFileDialog::getOpenFileName(this,
|
||||
tr("Open library"), "/home", tr("Comdel library (*.csl)"));
|
||||
|
||||
std::ostringstream buffer;
|
||||
|
||||
log->clear();
|
||||
|
||||
if(!filename.isEmpty()) {
|
||||
librarySource = filename.toStdString();
|
||||
|
||||
std::ostringstream output;
|
||||
clear();
|
||||
|
||||
ParseContext parseContext;
|
||||
auto libraryNode = load_library_from_file(&parseContext, filename.toStdString().c_str(), buffer);
|
||||
if(libraryNode) {
|
||||
domain::SchemaCreator generator(validators);
|
||||
library = generator.loadLibrary(*libraryNode);
|
||||
auto librarySource = filename.toStdString();
|
||||
|
||||
for (auto& error : generator.getErrors()) {
|
||||
parseContext.formatError(error, buffer, "ERROR: ");
|
||||
auto instance = Application::instance();
|
||||
if(!instance->loadLibrary(librarySource, output)) {
|
||||
log->appendPlainText(QString::fromStdString(output.str()));
|
||||
}
|
||||
|
||||
if(generator.getErrors().empty()) {
|
||||
libraryDisplay->setLibrary(library);
|
||||
|
||||
// on library load we create a new schema
|
||||
schema = new domain::Schema();
|
||||
schemaDisplay->setSchema(schema, &(*library));
|
||||
libraryDisplay->setLibrary(instance->getLibrary());
|
||||
schemaDisplay->setSchema(instance->getSchema(), instance->getLibrary());
|
||||
}
|
||||
|
||||
} else {
|
||||
buffer<<"Failed loading library"<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
log->appendPlainText(QString::fromStdString(buffer.str()));
|
||||
}
|
||||
|
||||
void MainWindow::onLoadSchema() {
|
||||
auto filename = QFileDialog::getOpenFileName(this,
|
||||
tr("Open schema"), "/home", tr("Comdel schema (*.csl)"));
|
||||
|
||||
std::ostringstream buffer;
|
||||
|
||||
log->clear();
|
||||
|
||||
if(!filename.isEmpty()) {
|
||||
std::ostringstream output;
|
||||
clear();
|
||||
|
||||
ParseContext parseContext;
|
||||
auto schemaNode = load_schema_from_file(&parseContext, filename.toStdString().c_str(), buffer);
|
||||
auto schemaSource = filename.toStdString();
|
||||
|
||||
if(schemaNode) {
|
||||
domain::SchemaCreator generator(validators);
|
||||
library = generator.loadLibrary(*schemaNode->library);
|
||||
|
||||
librarySource = schemaNode->source->asString();
|
||||
|
||||
for (auto& error : generator.getErrors()) {
|
||||
parseContext.formatError(error, buffer, "ERROR: ");
|
||||
auto instance = Application::instance();
|
||||
if(!instance->loadSchema(schemaSource, output)) {
|
||||
log->appendPlainText(QString::fromStdString(output.str()));
|
||||
}
|
||||
|
||||
if(library) {
|
||||
schema = generator.loadSchema(*schemaNode, *library);
|
||||
|
||||
for (auto& error : generator.getErrors()) {
|
||||
parseContext.formatError(error, buffer, "ERROR: ");
|
||||
delete schema;
|
||||
schema = nullptr;
|
||||
libraryDisplay->setLibrary(instance->getLibrary());
|
||||
schemaDisplay->setSchema(instance->getSchema(), instance->getLibrary());
|
||||
}
|
||||
} else {
|
||||
library = std::nullopt;
|
||||
}
|
||||
|
||||
if(generator.getErrors().empty()) {
|
||||
libraryDisplay->setLibrary(library);
|
||||
schemaDisplay->setSchema(schema, &(*library));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log->appendPlainText(QString::fromStdString(buffer.str()));
|
||||
}
|
||||
|
||||
void MainWindow::onStoreScheme() {
|
||||
if(schema == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto filename = QFileDialog::getSaveFileName(this,
|
||||
tr("Save schema"), "/home", tr("Comdel schema (*.csl)"));
|
||||
if(!filename.isEmpty()) {
|
||||
log->clear();
|
||||
|
||||
std::ostringstream buffer;
|
||||
|
||||
domain::generate_schema(librarySource, schema, buffer);
|
||||
std::ostringstream output;
|
||||
|
||||
if(Application::instance()->generateSchema(output)) {
|
||||
std::ofstream out(filename.toStdString(), std::ios::out | std::ios::binary);
|
||||
out<<buffer.str();
|
||||
out<<output.str();
|
||||
out.close();
|
||||
|
||||
log->appendPlainText("Successfully stored schema\n");
|
||||
} else {
|
||||
log->appendPlainText("Failed storing schema\n");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::onGenerateComdel() {
|
||||
if(schema == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto filename = QFileDialog::getSaveFileName(this,
|
||||
tr("Save schema"), "/home", tr("Comdel system (*.system)"));
|
||||
if(!filename.isEmpty()) {
|
||||
log->clear();
|
||||
|
||||
std::ostringstream buffer;
|
||||
std::ostringstream output;
|
||||
|
||||
domain::generate_comdel(schema, library.value(), buffer);
|
||||
auto validationErrors = Application::instance()->generateComdel(output);
|
||||
|
||||
std::ostringstream buff;
|
||||
formatErrors(validationErrors, buff);
|
||||
log->appendPlainText(QString::fromStdString(buff.str()));
|
||||
|
||||
if(Application::hasErrors(validationErrors)) {
|
||||
std::ofstream out(filename.toStdString(), std::ios::out | std::ios::binary);
|
||||
out<<buffer.str();
|
||||
out<<output.str();
|
||||
out.close();
|
||||
|
||||
log->appendPlainText("Successfully generated comdel\n");
|
||||
} else {
|
||||
log->appendPlainText("Failed generating comdel\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::onValidateSchema(bool /*toggled*/) {
|
||||
if(schema == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
log->clear();
|
||||
|
||||
this->validationErrors.clear();
|
||||
|
||||
domain::ComdelValidator validator{validators};
|
||||
|
||||
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);
|
||||
|
||||
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());
|
||||
|
||||
errors.erase(std::remove_if(
|
||||
errors.begin(), errors.end(), [](const domain::ValidationError& error) { return error.type == domain::Action::WARNING;}),
|
||||
errors.end());
|
||||
auto errors = Application::instance()->validateSchema();
|
||||
|
||||
std::ostringstream buff;
|
||||
|
||||
for(auto err: errors) {
|
||||
if(err.instance != nullptr) {
|
||||
buff << err.instance->name;
|
||||
}
|
||||
if(err.attribute != nullptr) {
|
||||
buff << "::" << err.attribute->name;
|
||||
}
|
||||
if(err.type == domain::Action::ERROR) {
|
||||
buff << " [ERROR] ";
|
||||
} else {
|
||||
buff << " [WARNING] ";
|
||||
}
|
||||
buff << err.message << std::endl;
|
||||
}
|
||||
formatErrors(errors, buff);
|
||||
|
||||
log->appendPlainText(QString::fromStdString(buff.str()));
|
||||
|
||||
validationErrors = errors;
|
||||
}
|
||||
|
||||
void MainWindow::formatErrors(std::vector<domain::ValidationError>& errors, std::ostream& output) {
|
||||
for(auto& err: errors) {
|
||||
if(err.instance != nullptr) {
|
||||
output << err.instance->name;
|
||||
}
|
||||
if(err.attribute != nullptr) {
|
||||
output << "::" << err.attribute->name;
|
||||
}
|
||||
if(err.type == domain::Action::ERROR) {
|
||||
output << " [ERROR] ";
|
||||
} else {
|
||||
output << " [WARNING] ";
|
||||
}
|
||||
output << err.message << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::clear() {
|
||||
validationErrors.clear();
|
||||
if(schema != nullptr) {
|
||||
delete schema;
|
||||
schema = nullptr;
|
||||
}
|
||||
library = std::nullopt;
|
||||
|
||||
libraryDisplay->setLibrary(library);
|
||||
schemaDisplay->setSchema(schema, nullptr);
|
||||
log->clear();
|
||||
this->schemaDisplay->setSchema(nullptr, std::nullopt);
|
||||
this->libraryDisplay->setLibrary(std::nullopt);
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
|
|
20
mainwindow.h
20
mainwindow.h
|
@ -24,26 +24,11 @@ public:
|
|||
MainWindow(QWidget *parent = nullptr);
|
||||
~MainWindow();
|
||||
|
||||
display::Library *libraryDisplay;
|
||||
display::Schema *schemaDisplay;
|
||||
|
||||
static std::optional<domain::Library> library;
|
||||
static domain::Schema* schema;
|
||||
|
||||
std::vector<domain::FunctionValidator*> validators;
|
||||
|
||||
void setupUi();
|
||||
void clear();
|
||||
|
||||
static domain::Schema* getSchema() {
|
||||
return schema;
|
||||
}
|
||||
|
||||
static std::optional<domain::Library> getLibrary() {
|
||||
return library;
|
||||
}
|
||||
|
||||
|
||||
private slots:
|
||||
void onLoadLibrary();
|
||||
void onLoadSchema();
|
||||
|
@ -52,10 +37,11 @@ private slots:
|
|||
void onGenerateComdel();
|
||||
|
||||
private:
|
||||
std::string librarySource;
|
||||
display::Library *libraryDisplay;
|
||||
display::Schema *schemaDisplay;
|
||||
Ui::MainWindow *ui;
|
||||
QPlainTextEdit *log;
|
||||
std::vector<domain::ValidationError> validationErrors;
|
||||
|
||||
static void formatErrors(std::vector<domain::ValidationError>& errors, std::ostream& output);
|
||||
};
|
||||
#endif // MAIN_WINDOW_H
|
||||
|
|
Loading…
Reference in New Issue