Compare commits
5 Commits
f93a2afa63
...
f66fc1db26
Author | SHA1 | Date |
---|---|---|
Borna Rajković | f66fc1db26 | |
Borna Rajković | 1759adf25a | |
Borna Rajković | 1ec8b10ef5 | |
Borna Rajković | 9b7ede933a | |
Borna Rajković | 3172d7e4cf |
|
@ -34,8 +34,8 @@ add_executable(SchemeEditor
|
||||||
comdel/parser/tokens_type.cpp
|
comdel/parser/tokens_type.cpp
|
||||||
comdel/parser/ast_nodes.cpp
|
comdel/parser/ast_nodes.cpp
|
||||||
comdel/parser/parser_util.cpp
|
comdel/parser/parser_util.cpp
|
||||||
comdel/parser/comdellexer.cpp
|
comdel/parser/comdel_lexer.cpp
|
||||||
main.cpp
|
main.cpp
|
||||||
mainwindow.ui
|
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 application.cpp application.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 comdel/display/single_automatic_dialog.cpp comdel/display/single_automatic_dialog.h)
|
||||||
target_link_libraries(SchemeEditor Qt5::Core Qt5::Gui Qt5::Widgets)
|
target_link_libraries(SchemeEditor Qt5::Core Qt5::Gui Qt5::Widgets)
|
||||||
|
|
|
@ -9,77 +9,80 @@ CONFIG += c++17
|
||||||
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
|
comdel/display/attribute_dialog.cpp \
|
||||||
comdel/display/component_display.cpp \
|
comdel/display/component_display.cpp \
|
||||||
comdel/display/library_display.cpp \
|
comdel/display/library_display.cpp \
|
||||||
|
comdel/display/library_list.cpp \
|
||||||
|
comdel/display/name_dialog.cpp \
|
||||||
comdel/display/schema_display.cpp \
|
comdel/display/schema_display.cpp \
|
||||||
comdel/domain/addressspace.cpp \
|
comdel/display/single_automatic_dialog.cpp \
|
||||||
|
comdel/domain/address_space.cpp \
|
||||||
comdel/domain/attribute.cpp \
|
comdel/domain/attribute.cpp \
|
||||||
comdel/domain/bus.cpp \
|
comdel/domain/bus.cpp \
|
||||||
comdel/domain/schemacreator.cpp \
|
comdel/domain/comdel_generator.cpp \
|
||||||
|
comdel/domain/comdel_validator.cpp \
|
||||||
comdel/domain/component.cpp \
|
comdel/domain/component.cpp \
|
||||||
comdel/domain/connection.cpp \
|
comdel/domain/connection.cpp \
|
||||||
comdel/domain/comdelvalidator.cpp \
|
comdel/domain/connection_instance.cpp \
|
||||||
comdel/domain/connectioninstance.cpp \
|
|
||||||
comdel/domain/display.cpp \
|
comdel/domain/display.cpp \
|
||||||
comdel/domain/functionsignature.cpp \
|
comdel/domain/function_signature.cpp \
|
||||||
comdel/domain/instance.cpp \
|
comdel/domain/instance.cpp \
|
||||||
comdel/domain/instanceattribute.cpp \
|
comdel/domain/instance_attribute.cpp \
|
||||||
comdel/domain/library.cpp \
|
comdel/domain/library.cpp \
|
||||||
comdel/domain/pin.cpp \
|
comdel/domain/pin.cpp \
|
||||||
comdel/domain/rule.cpp \
|
comdel/domain/rule.cpp \
|
||||||
comdel/domain/schema.cpp \
|
comdel/domain/schema.cpp \
|
||||||
|
comdel/domain/schema_creator.cpp \
|
||||||
comdel/domain/value.cpp \
|
comdel/domain/value.cpp \
|
||||||
comdel/domain/wireinstance.cpp \
|
comdel/parser/ast_nodes.cpp \
|
||||||
comdel/parser/astnode.cpp \
|
comdel/parser/comdel_lexer.cpp \
|
||||||
comdel/parser/comdellexer.cpp \
|
comdel/parser/comdel_parser.cpp \
|
||||||
comdel/parser/comdelparser.cpp \
|
comdel/parser/parse_context.cpp \
|
||||||
comdel/parser/parsecontext.cpp \
|
comdel/parser/parser_util.cpp \
|
||||||
comdel/parser/parserutil.cpp \
|
comdel/parser/source_error.cpp \
|
||||||
comdel/parser/sourceerror.cpp \
|
|
||||||
comdel/parser/token.cpp \
|
comdel/parser/token.cpp \
|
||||||
comdel/parser/tokenstype.cpp \
|
comdel/parser/tokens_type.cpp \
|
||||||
comdel/display/dialogmanager.cpp \
|
application.cpp \
|
||||||
comdel/display/attribute_dialog.cpp \
|
|
||||||
comdel/display/name_dialog.cpp \
|
|
||||||
main.cpp \
|
main.cpp \
|
||||||
mainwindow.cpp
|
mainwindow.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
|
comdel/display/attribute_dialog.h \
|
||||||
comdel/display/component_display.h \
|
comdel/display/component_display.h \
|
||||||
comdel/display/library_display.h \
|
comdel/display/library_display.h \
|
||||||
|
comdel/display/library_list.h \
|
||||||
|
comdel/display/name_dialog.h \
|
||||||
comdel/display/schema_display.h \
|
comdel/display/schema_display.h \
|
||||||
comdel/domain/addressspace.h \
|
comdel/display/single_automatic_dialog.h \
|
||||||
|
comdel/domain/address_space.h \
|
||||||
comdel/domain/attribute.h \
|
comdel/domain/attribute.h \
|
||||||
comdel/domain/bus.h \
|
comdel/domain/bus.h \
|
||||||
comdel/domain/schemacreator.h \
|
comdel/domain/comdel_generator.h \
|
||||||
|
comdel/domain/comdel_validator.h \
|
||||||
comdel/domain/component.h \
|
comdel/domain/component.h \
|
||||||
comdel/domain/connection.h \
|
comdel/domain/connection.h \
|
||||||
comdel/domain/comdelvalidator.h \
|
comdel/domain/connection_instance.h \
|
||||||
comdel/domain/connectioninstance.h \
|
|
||||||
comdel/domain/display.h \
|
comdel/domain/display.h \
|
||||||
comdel/domain/functionsignature.h \
|
comdel/domain/function_signature.h \
|
||||||
comdel/domain/instance.h \
|
comdel/domain/instance.h \
|
||||||
comdel/domain/instanceattribute.h \
|
comdel/domain/instance_attribute.h \
|
||||||
comdel/domain/library.h \
|
comdel/domain/library.h \
|
||||||
comdel/domain/pin.h \
|
comdel/domain/pin.h \
|
||||||
comdel/domain/rule.h \
|
comdel/domain/rule.h \
|
||||||
comdel/domain/schema.h \
|
comdel/domain/schema.h \
|
||||||
|
comdel/domain/schema_creator.h \
|
||||||
comdel/domain/value.h \
|
comdel/domain/value.h \
|
||||||
comdel/domain/wireinstance.h \
|
comdel/parser/ast_nodes.h \
|
||||||
comdel/parser/astnode.h \
|
comdel/parser/comdel_lexer.h \
|
||||||
comdel/parser/comdellexer.h \
|
comdel/parser/comdel_parser.h \
|
||||||
comdel/parser/comdelparser.h \
|
|
||||||
comdel/parser/expected.h \
|
comdel/parser/expected.h \
|
||||||
comdel/parser/parsecontext.h \
|
comdel/parser/parse_context.h \
|
||||||
comdel/parser/parserutil.h \
|
comdel/parser/parser_util.h \
|
||||||
comdel/parser/poly.h \
|
comdel/parser/poly.h \
|
||||||
comdel/parser/presult.h \
|
comdel/parser/presult.h \
|
||||||
comdel/parser/sourceerror.h \
|
comdel/parser/source_error.h \
|
||||||
comdel/parser/token.h \
|
comdel/parser/token.h \
|
||||||
comdel/parser/tokenstype.h \
|
comdel/parser/tokens_type.h \
|
||||||
comdel/display/dialogmanager.h \
|
|
||||||
comdel/display/attribute_dialog.h \
|
|
||||||
comdel/display/name_dialog.h \
|
|
||||||
mainwindow.h
|
mainwindow.h
|
||||||
|
|
||||||
FORMS += \
|
FORMS += \
|
||||||
|
|
249
application.cpp
249
application.cpp
|
@ -18,7 +18,7 @@ domain::Schema *Application::getSchema() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::clear() {
|
void Application::clear() {
|
||||||
if(schema != nullptr) {
|
if (schema != nullptr) {
|
||||||
delete schema;
|
delete schema;
|
||||||
schema = nullptr;
|
schema = nullptr;
|
||||||
}
|
}
|
||||||
|
@ -26,76 +26,97 @@ void Application::clear() {
|
||||||
libraryPath = "";
|
libraryPath = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Application::loadLibrary(std::string& filename, std::ostream &errorOutput) {
|
bool Application::loadLibrary(std::string &filename, std::ostream &errorOutput) {
|
||||||
clear();
|
clear();
|
||||||
|
|
||||||
ParseContext parseContext;
|
ParseContext parseContext;
|
||||||
auto libraryNode = load_library_from_file(&parseContext, filename.c_str(), errorOutput);
|
auto libraryNode = load_library_from_file(&parseContext, filename.c_str(), errorOutput);
|
||||||
if(libraryNode) {
|
if (libraryNode) {
|
||||||
domain::SchemaCreator generator(validators);
|
domain::SchemaCreator generator(validators);
|
||||||
library = generator.loadLibrary(*libraryNode);
|
library = generator.loadLibrary(*libraryNode);
|
||||||
|
|
||||||
for (auto& error : generator.getErrors()) {
|
for (auto &error: generator.getErrors()) {
|
||||||
parseContext.formatError(error, errorOutput, "ERROR: ");
|
parseContext.formatError(error, errorOutput, "ERROR: ");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(library.has_value()) {
|
if (library.has_value()) {
|
||||||
errorOutput<<"Failed creating library model"<<std::endl;
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
libraryPath = filename;
|
libraryPath = filename;
|
||||||
// on library load we create a new schema
|
// on library load we create a new schema
|
||||||
schema = new domain::Schema();
|
schema = new domain::Schema(library.value());
|
||||||
|
} else {
|
||||||
|
errorOutput << "Failed creating library model" << std::endl;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
errorOutput<<"Failed parsing library"<<std::endl;
|
errorOutput << "Failed parsing library" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Application::loadSchema(std::string &filename, std::ostream &errorOutput) {
|
std::pair<bool, std::vector<domain::ValidationError>> Application::loadSchema(std::string &filename, std::ostream &errorOutput) {
|
||||||
clear();
|
clear();
|
||||||
|
|
||||||
|
std::vector<domain::ValidationError> errors;
|
||||||
|
|
||||||
ParseContext parseContext;
|
ParseContext parseContext;
|
||||||
auto schemaNode = load_schema_from_file(&parseContext, filename.c_str(), errorOutput);
|
auto schemaNode = load_schema_from_file(&parseContext, filename.c_str(), errorOutput);
|
||||||
|
|
||||||
if(schemaNode) {
|
if (schemaNode) {
|
||||||
domain::SchemaCreator generator(validators);
|
domain::SchemaCreator generator(validators);
|
||||||
library = generator.loadLibrary(*schemaNode->library);
|
library = generator.loadLibrary(*schemaNode->library);
|
||||||
|
|
||||||
libraryPath = schemaNode->source->asString();
|
libraryPath = schemaNode->source->asString();
|
||||||
|
|
||||||
for (auto& error : generator.getErrors()) {
|
for (auto &error: generator.getErrors()) {
|
||||||
parseContext.formatError(error, errorOutput, "ERROR: ");
|
parseContext.formatError(error, errorOutput, "ERROR: ");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(library) {
|
if (library) {
|
||||||
schema = generator.loadSchema(*schemaNode, *library);
|
schema = generator.loadSchema(*schemaNode, *library);
|
||||||
|
|
||||||
for (auto& error : generator.getErrors()) {
|
for (auto &error: generator.getErrors()) {
|
||||||
parseContext.formatError(error, errorOutput, "ERROR: ");
|
parseContext.formatError(error, errorOutput, "ERROR: ");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(schema == nullptr) {
|
if (schema == nullptr) {
|
||||||
clear();
|
clear();
|
||||||
return false;
|
return {false, errors};
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
clear();
|
clear();
|
||||||
return false;
|
return {false, errors};
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
errorOutput<<"Failed parsing library"<<std::endl;
|
errorOutput << "Failed parsing library" << std::endl;
|
||||||
return false;
|
return {false, errors};
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
|
domain::ComdelValidator validator{validators};
|
||||||
|
|
||||||
|
domain::ValidationContext context;
|
||||||
|
context.instance = nullptr;
|
||||||
|
context.attribute = nullptr;
|
||||||
|
context.addressSpaces = {};
|
||||||
|
|
||||||
|
auto memoryReferenceValidation = validator.validateMemoryReferences(*schema, *library, context);
|
||||||
|
errors.insert(errors.end(), memoryReferenceValidation.begin(), memoryReferenceValidation.end());
|
||||||
|
|
||||||
|
auto nameValidation = validator.validateInstanceNames(*schema, *library, context);
|
||||||
|
errors.insert(errors.end(), nameValidation.begin(), nameValidation.end());
|
||||||
|
|
||||||
|
if(!errors.empty()) {
|
||||||
|
clear();
|
||||||
|
return {false, errors};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {true, errors};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Application::generateSchema(std::ostringstream &output) {
|
bool Application::generateSchema(std::ostringstream &output) {
|
||||||
if(schema == nullptr) {
|
if (schema == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
domain::generate_schema(libraryPath, schema, output);
|
domain::generate_schema(libraryPath, schema, output);
|
||||||
|
@ -103,7 +124,7 @@ bool Application::generateSchema(std::ostringstream &output) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<domain::ValidationError> Application::validateSchema() {
|
std::vector<domain::ValidationError> Application::validateSchema() {
|
||||||
if(schema == nullptr) {
|
if (schema == nullptr) {
|
||||||
return std::vector<domain::ValidationError>{domain::ValidationError(domain::Action::ERROR, "No schema loaded")};
|
return std::vector<domain::ValidationError>{domain::ValidationError(domain::Action::ERROR, "No schema loaded")};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,17 +135,20 @@ std::vector<domain::ValidationError> Application::validateSchema() {
|
||||||
context.attribute = nullptr;
|
context.attribute = nullptr;
|
||||||
context.addressSpaces = {};
|
context.addressSpaces = {};
|
||||||
|
|
||||||
for(auto &lib: library->getAddressSpaces()) {
|
for (auto &lib: library->getAddressSpaces()) {
|
||||||
context.addressSpaces.insert(std::make_pair(lib.getName(), lib));
|
context.addressSpaces.insert(std::make_pair(lib.getName(), lib));
|
||||||
}
|
}
|
||||||
auto errors = validator.validateSchema(*schema, context);
|
auto errors = validator.validateSchema(*schema, context);
|
||||||
|
|
||||||
auto countValidation = validator.validateInstanceCount(*schema, *library, context);
|
auto memoryReferenceValidation = validator.validateMemoryReferences(*schema, *library, context);
|
||||||
errors.insert(errors.end(), countValidation.begin(), countValidation.end());
|
errors.insert(errors.end(), memoryReferenceValidation.begin(), memoryReferenceValidation.end());
|
||||||
|
|
||||||
auto nameValidation = validator.validateInstanceNames(*schema, *library, context);
|
auto nameValidation = validator.validateInstanceNames(*schema, *library, context);
|
||||||
errors.insert(errors.end(), nameValidation.begin(), nameValidation.end());
|
errors.insert(errors.end(), nameValidation.begin(), nameValidation.end());
|
||||||
|
|
||||||
|
auto countValidation = validator.validateInstanceCount(*schema, *library, context);
|
||||||
|
errors.insert(errors.end(), countValidation.begin(), countValidation.end());
|
||||||
|
|
||||||
auto pinValidation = validator.validatePinConnections(*schema, *library, context);
|
auto pinValidation = validator.validatePinConnections(*schema, *library, context);
|
||||||
errors.insert(errors.end(), pinValidation.begin(), pinValidation.end());
|
errors.insert(errors.end(), pinValidation.begin(), pinValidation.end());
|
||||||
return errors;
|
return errors;
|
||||||
|
@ -133,7 +157,7 @@ std::vector<domain::ValidationError> Application::validateSchema() {
|
||||||
std::vector<domain::ValidationError> Application::generateComdel(std::ostringstream &output) {
|
std::vector<domain::ValidationError> Application::generateComdel(std::ostringstream &output) {
|
||||||
|
|
||||||
auto errors = validateSchema();
|
auto errors = validateSchema();
|
||||||
if(Application::hasErrors(errors)) {
|
if (!Application::hasErrors(errors)) {
|
||||||
// as long as all validation errors are warning we continue with build
|
// as long as all validation errors are warning we continue with build
|
||||||
domain::generate_comdel(schema, library.value(), output);
|
domain::generate_comdel(schema, library.value(), output);
|
||||||
}
|
}
|
||||||
|
@ -141,8 +165,8 @@ std::vector<domain::ValidationError> Application::generateComdel(std::ostringstr
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Application::hasErrors(std::vector<domain::ValidationError> errors) {
|
bool Application::hasErrors(std::vector<domain::ValidationError> errors) {
|
||||||
for(auto& err: errors) {
|
for (auto &err: errors) {
|
||||||
if(err.type == domain::Action::ERROR) {
|
if (err.type == domain::Action::ERROR) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -153,26 +177,29 @@ bool Application::hasErrors(std::vector<domain::ValidationError> errors) {
|
||||||
static Application *application = nullptr;
|
static Application *application = nullptr;
|
||||||
|
|
||||||
Application *Application::instance() {
|
Application *Application::instance() {
|
||||||
if(application == nullptr) {
|
if (application == nullptr) {
|
||||||
application = new Application();
|
application = new Application();
|
||||||
}
|
}
|
||||||
return application;
|
return application;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<domain::ComponentInstance> Application::addComponent(domain::Component component, std::vector<domain::InstanceAttribute> attributes, int x, int y) {
|
std::shared_ptr<domain::ComponentInstance>
|
||||||
|
Application::addComponent(domain::Component component, std::vector<domain::InstanceAttribute> attributes, int x,
|
||||||
|
int y) {
|
||||||
std::set<std::string> names;
|
std::set<std::string> names;
|
||||||
for(const auto& c: schema->componentInstances) {
|
for (const auto &c: schema->componentInstances) {
|
||||||
names.insert(c->name);
|
names.insert(c->name);
|
||||||
}
|
}
|
||||||
std::string name = generateName(names, component.getInstanceName());
|
std::string name = generateName(names, component.getInstanceName());
|
||||||
|
|
||||||
schema->componentInstances.push_back(std::make_shared<domain::ComponentInstance>(name, attributes, std::make_pair(x, y), component));
|
schema->componentInstances.push_back(
|
||||||
|
std::make_shared<domain::ComponentInstance>(name, attributes, std::make_pair(x, y), component));
|
||||||
return schema->componentInstances.back();
|
return schema->componentInstances.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<domain::BusInstance> Application::addBus(domain::Bus bus, int x, int y) {
|
std::shared_ptr<domain::BusInstance> Application::addBus(domain::Bus bus, int x, int y) {
|
||||||
std::set<std::string> names;
|
std::set<std::string> names;
|
||||||
for(const auto& b: schema->busInstances) {
|
for (const auto &b: schema->busInstances) {
|
||||||
names.insert(b->name);
|
names.insert(b->name);
|
||||||
}
|
}
|
||||||
std::string name = generateName(names, bus.getInstanceName());
|
std::string name = generateName(names, bus.getInstanceName());
|
||||||
|
@ -182,18 +209,162 @@ std::shared_ptr<domain::BusInstance> Application::addBus(domain::Bus bus, int x,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string Application::generateName(std::set<std::string>& names, std::string instanceName) {
|
std::string Application::generateName(std::set<std::string> &names, std::string instanceName) {
|
||||||
if(names.find(instanceName) == names.end()) {
|
if (names.find(instanceName) == names.end()) {
|
||||||
return instanceName;
|
return instanceName;
|
||||||
}
|
}
|
||||||
char buffer[4];
|
char buffer[4];
|
||||||
for(int i=0; i<1000; i++) {
|
for (int i = 0; i < 1000; i++) {
|
||||||
sprintf(buffer, "%03d", i);
|
sprintf(buffer, "%03d", i);
|
||||||
auto name = instanceName + "_" + buffer;
|
auto name = instanceName + "_" + buffer;
|
||||||
if(names.find(name) == names.end()) {
|
if (names.find(name) == names.end()) {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// return default value as this should never happen
|
// return default value as this should never happen
|
||||||
return instanceName;
|
return instanceName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Application::removeComponent(std::string componentName) {
|
||||||
|
auto component = findComponentByName(componentName);
|
||||||
|
if (component == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::set<domain::BusInstance*> automaticBusses;
|
||||||
|
|
||||||
|
schema->connections.erase(
|
||||||
|
std::remove_if(
|
||||||
|
schema->connections.begin(),
|
||||||
|
schema->connections.end(),
|
||||||
|
[component, &automaticBusses](const std::shared_ptr<domain::ConnectionInstance> &conn) {
|
||||||
|
auto busConnection = dynamic_cast<domain::BusConnectionInstance *>(conn.get());
|
||||||
|
if (busConnection) {
|
||||||
|
if (busConnection->instance == component) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto directConnection = dynamic_cast<domain::DirectConnectionInstance *>(conn.get());
|
||||||
|
if (directConnection) {
|
||||||
|
if (directConnection->instance == component || directConnection->secondInstance == component) {
|
||||||
|
automaticBusses.insert(directConnection->bus);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}),
|
||||||
|
schema->connections.end()
|
||||||
|
);
|
||||||
|
|
||||||
|
schema->busInstances.erase(
|
||||||
|
std::remove_if(
|
||||||
|
schema->busInstances.begin(),
|
||||||
|
schema->busInstances.end(),
|
||||||
|
[&automaticBusses](const std::shared_ptr<domain::BusInstance> &bus) {
|
||||||
|
return automaticBusses.count(bus.get());
|
||||||
|
}),
|
||||||
|
schema->busInstances.end()
|
||||||
|
);
|
||||||
|
|
||||||
|
if(component->component.getType() == domain::Component::MEMORY) {
|
||||||
|
for(auto& comp: schema->componentInstances) {
|
||||||
|
if(comp->component.getType() == domain::Component::PROCESSOR) {
|
||||||
|
for(auto& attribute: comp->attributes) {
|
||||||
|
if(attribute.value.isType(domain::Value::MEMORY_REFERENCE) && attribute.value.asMemoryReference() == component->name) {
|
||||||
|
attribute.value = domain::Value::fromMemoryReference(std::nullopt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto iter = schema->componentInstances.begin(); iter != schema->componentInstances.end(); ++iter) {
|
||||||
|
if(iter->get() == component) {
|
||||||
|
schema->componentInstances.erase(iter);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Application::removeBus(std::string busName) {
|
||||||
|
auto bus = findBusByName(busName);
|
||||||
|
if (bus == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
schema->connections.erase(
|
||||||
|
std::remove_if(
|
||||||
|
schema->connections.begin(),
|
||||||
|
schema->connections.end(),
|
||||||
|
[bus](const std::shared_ptr<domain::ConnectionInstance> &conn) {
|
||||||
|
auto busConnection = dynamic_cast<domain::BusConnectionInstance *>(conn.get());
|
||||||
|
if (busConnection) {
|
||||||
|
if (busConnection->bus == bus) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}),
|
||||||
|
schema->connections.end()
|
||||||
|
);
|
||||||
|
|
||||||
|
for(auto iter = schema->busInstances.begin(); iter != schema->busInstances.end(); ++iter) {
|
||||||
|
if(iter->get() == bus) {
|
||||||
|
schema->busInstances.erase(iter);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
domain::ComponentInstance *Application::findComponentByName(std::string componentName) {
|
||||||
|
for (auto &comp: schema->componentInstances) {
|
||||||
|
if (comp->name == componentName) {
|
||||||
|
return comp.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
domain::BusInstance *Application::findBusByName(std::string busName) {
|
||||||
|
for (auto &bus: schema->busInstances) {
|
||||||
|
if (bus->name == busName) {
|
||||||
|
return bus.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::renameComponent(std::string currentName, std::string newName) {
|
||||||
|
if(currentName == newName) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto component = findComponentByName(currentName);
|
||||||
|
if(component) {
|
||||||
|
component->name = newName;
|
||||||
|
if(component->component.getType() == domain::Component::MEMORY) {
|
||||||
|
for(auto& comp: schema->componentInstances) {
|
||||||
|
if(comp.get()->component.getType() == domain::Component::PROCESSOR) {
|
||||||
|
for(auto& attribute: comp.get()->attributes) {
|
||||||
|
if(attribute.value.isType(domain::Value::MEMORY_REFERENCE) && attribute.value.asMemoryReference() == currentName) {
|
||||||
|
attribute.value = domain::Value::fromMemoryReference(newName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::renameBus(std::string currentName, std::string newName) {
|
||||||
|
if(currentName == newName) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto bus = findBusByName(currentName);
|
||||||
|
if(bus) {
|
||||||
|
bus->name = newName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -21,6 +21,9 @@ private:
|
||||||
|
|
||||||
std::string generateName(std::set<std::string>& names, std::string instanceName);
|
std::string generateName(std::set<std::string>& names, std::string instanceName);
|
||||||
|
|
||||||
|
domain::ComponentInstance *findComponentByName(std::string componentName);
|
||||||
|
domain::BusInstance *findBusByName(std::string busName);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::optional<domain::Library> getLibrary();
|
std::optional<domain::Library> getLibrary();
|
||||||
domain::Schema* getSchema();
|
domain::Schema* getSchema();
|
||||||
|
@ -28,7 +31,7 @@ public:
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
bool loadLibrary(std::string& filename, std::ostream& errorOutput);
|
bool loadLibrary(std::string& filename, std::ostream& errorOutput);
|
||||||
bool loadSchema(std::string& filename, std::ostream& errorOutput);
|
std::pair<bool, std::vector<domain::ValidationError>> loadSchema(std::string& filename, std::ostream& errorOutput);
|
||||||
|
|
||||||
static Application* instance();
|
static Application* instance();
|
||||||
|
|
||||||
|
@ -37,11 +40,18 @@ public:
|
||||||
std::vector<domain::ValidationError> generateComdel(std::ostringstream &output);
|
std::vector<domain::ValidationError> generateComdel(std::ostringstream &output);
|
||||||
|
|
||||||
std::shared_ptr<domain::ComponentInstance> addComponent(domain::Component component, std::vector<domain::InstanceAttribute> attributes, int x, int y);
|
std::shared_ptr<domain::ComponentInstance> addComponent(domain::Component component, std::vector<domain::InstanceAttribute> attributes, int x, int y);
|
||||||
|
bool removeComponent(std::string component);
|
||||||
|
|
||||||
std::shared_ptr<domain::BusInstance> addBus(domain::Bus bus, int x, int y);
|
std::shared_ptr<domain::BusInstance> addBus(domain::Bus bus, int x, int y);
|
||||||
|
bool removeBus(std::string bus);
|
||||||
|
|
||||||
static bool hasErrors(std::vector<domain::ValidationError> empty);
|
static bool hasErrors(std::vector<domain::ValidationError> empty);
|
||||||
|
|
||||||
~Application() = default;
|
~Application() = default;
|
||||||
|
|
||||||
|
void renameComponent(std::string currentName, std::string newName);
|
||||||
|
|
||||||
|
void renameBus(std::string currentName, std::string newName);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -59,14 +59,16 @@ namespace display {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AttributeDialog::AttributeDialog(domain::InstanceAttribute *attribute) {
|
AttributeDialog::AttributeDialog(domain::InstanceAttribute *attribute, bool updating) {
|
||||||
|
|
||||||
|
|
||||||
setAttribute(Qt::WA_DeleteOnClose);
|
setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
|
||||||
attributeValue = attribute;
|
attributeValue = attribute;
|
||||||
|
|
||||||
this->setWindowTitle(QString::fromStdString("Izmjeni " + attribute->attribute.getName()));
|
auto actionType = updating ? "Izmjeni " : "Postavi ";
|
||||||
|
|
||||||
|
this->setWindowTitle(QString::fromStdString(actionType + attribute->attribute.getName()));
|
||||||
|
|
||||||
auto layout = new QVBoxLayout(this);
|
auto layout = new QVBoxLayout(this);
|
||||||
this->setLayout(layout);
|
this->setLayout(layout);
|
||||||
|
@ -120,11 +122,11 @@ namespace display {
|
||||||
auto *radioLayout = new QHBoxLayout(group);
|
auto *radioLayout = new QHBoxLayout(group);
|
||||||
group->setLayout(radioLayout);
|
group->setLayout(radioLayout);
|
||||||
|
|
||||||
auto isTrue = new QRadioButton("true", group);
|
auto isTrue = new QRadioButton("da", group);
|
||||||
connect(isTrue, &QRadioButton::clicked, [this]() {
|
connect(isTrue, &QRadioButton::clicked, [this]() {
|
||||||
this->value = domain::Value::fromBool(true);
|
this->value = domain::Value::fromBool(true);
|
||||||
});
|
});
|
||||||
auto isFalse = new QRadioButton("false", group);
|
auto isFalse = new QRadioButton("ne", group);
|
||||||
connect(isFalse, &QRadioButton::clicked, [this]() {
|
connect(isFalse, &QRadioButton::clicked, [this]() {
|
||||||
this->value = domain::Value::fromBool(false);
|
this->value = domain::Value::fromBool(false);
|
||||||
});
|
});
|
||||||
|
@ -140,7 +142,7 @@ namespace display {
|
||||||
layout->addWidget(group);
|
layout->addWidget(group);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto button = new QPushButton("Ažuriraj");
|
auto button = new QPushButton(updating ? "Ažuriraj" : "Postavi");
|
||||||
connect(button, &QPushButton::clicked, this, &AttributeDialog::onUpdate);
|
connect(button, &QPushButton::clicked, this, &AttributeDialog::onUpdate);
|
||||||
|
|
||||||
layout->addWidget(button);
|
layout->addWidget(button);
|
||||||
|
@ -170,14 +172,16 @@ namespace display {
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryDialog::MemoryDialog(domain::InstanceAttribute *attribute,
|
MemoryDialog::MemoryDialog(domain::InstanceAttribute *attribute,
|
||||||
std::vector<std::shared_ptr<domain::ComponentInstance>> instances) {
|
std::vector<std::shared_ptr<domain::ComponentInstance>> instances, bool updating) {
|
||||||
memoryInstances = std::vector<std::string>();
|
memoryInstances = std::vector<std::string>();
|
||||||
|
|
||||||
setAttribute(Qt::WA_DeleteOnClose);
|
setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
|
||||||
attributeValue = attribute;
|
attributeValue = attribute;
|
||||||
|
|
||||||
this->setWindowTitle(QString::fromStdString("Izmjeni " + attribute->attribute.getName()));
|
auto actionType = updating ? "Izmjeni memoriju" : "Postavi memoriju";
|
||||||
|
|
||||||
|
this->setWindowTitle(QString::fromStdString(actionType));
|
||||||
|
|
||||||
for (auto &instance: instances) {
|
for (auto &instance: instances) {
|
||||||
if (instance->component.getType() == domain::Component::MEMORY) {
|
if (instance->component.getType() == domain::Component::MEMORY) {
|
||||||
|
@ -212,7 +216,7 @@ namespace display {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto button = new QPushButton("Ažuriraj");
|
auto button = new QPushButton(updating ? "Ažuriraj" : "Postavi");
|
||||||
connect(button, &QPushButton::clicked, this, &MemoryDialog::onUpdate);
|
connect(button, &QPushButton::clicked, this, &MemoryDialog::onUpdate);
|
||||||
|
|
||||||
layout->addWidget(button);
|
layout->addWidget(button);
|
||||||
|
|
|
@ -42,7 +42,7 @@ namespace display {
|
||||||
domain::InstanceAttribute *attributeValue;
|
domain::InstanceAttribute *attributeValue;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AttributeDialog(domain::InstanceAttribute *attribute);
|
AttributeDialog(domain::InstanceAttribute *attribute, bool updating = true);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ namespace display {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MemoryDialog(domain::InstanceAttribute *attribute,
|
MemoryDialog(domain::InstanceAttribute *attribute,
|
||||||
std::vector<std::shared_ptr<domain::ComponentInstance>> instances);
|
std::vector<std::shared_ptr<domain::ComponentInstance>> instances, bool updating = true);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
|
|
|
@ -3,14 +3,19 @@
|
||||||
#include "name_dialog.h"
|
#include "name_dialog.h"
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include "application.h"
|
#include "application.h"
|
||||||
|
#include "single_automatic_dialog.h"
|
||||||
|
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
#include <QLine>
|
#include <QLine>
|
||||||
|
#include <QPen>
|
||||||
#include <QGraphicsSceneContextMenuEvent>
|
#include <QGraphicsSceneContextMenuEvent>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
|
|
||||||
namespace display {
|
namespace display {
|
||||||
|
|
||||||
|
QPen connectionPen(QColor::fromRgb(150, 150, 250));
|
||||||
|
|
||||||
void Component::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) {
|
void Component::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) {
|
||||||
QMenu menu;
|
QMenu menu;
|
||||||
menu.addAction("Izmjeni ime", [this]() {
|
menu.addAction("Izmjeni ime", [this]() {
|
||||||
|
@ -18,28 +23,41 @@ namespace display {
|
||||||
for(const auto &component: Application::instance()->getSchema()->componentInstances) {
|
for(const auto &component: Application::instance()->getSchema()->componentInstances) {
|
||||||
names.insert(component->name);
|
names.insert(component->name);
|
||||||
}
|
}
|
||||||
|
auto dialog = new NameDialog(this->instance->name, names);
|
||||||
auto dialog = new NameDialog(this->instance.get(), names);
|
|
||||||
dialog->exec();
|
dialog->exec();
|
||||||
|
|
||||||
|
auto currentName = this->instance->name;
|
||||||
|
auto newName = dialog->getName();
|
||||||
|
|
||||||
|
Application::instance()->renameComponent(currentName, newName);
|
||||||
});
|
});
|
||||||
menu.addSeparator();
|
menu.addSeparator();
|
||||||
for (int i = 0; i < this->instance->attributes.size(); i++) {
|
for (int i = 0; i < this->instance->attributes.size(); i++) {
|
||||||
auto *attr = &this->instance->attributes[i];
|
auto *attr = &this->instance->attributes[i];
|
||||||
bool enabled = attr->attribute.getPopup().has_value();
|
bool enabled = attr->attribute.getPopup().has_value();
|
||||||
|
|
||||||
auto action = menu.addAction(QString::fromStdString("Izmjeni " + attr->name),
|
if(attr->value.getType() == domain::Value::MEMORY_REFERENCE) {
|
||||||
[attr]() {
|
menu.addAction("Izmjeni memoriju", [attr]() {
|
||||||
if (attr->value.getType() == domain::Value::MEMORY_REFERENCE) {
|
auto dialog = new MemoryDialog(attr,
|
||||||
auto dialog = new MemoryDialog(attr,
|
Application::instance()->getSchema()->componentInstances);
|
||||||
Application::instance()->getSchema()->componentInstances);
|
dialog->exec();
|
||||||
dialog->exec();
|
});
|
||||||
} else {
|
} else {
|
||||||
auto dialog = new AttributeDialog(attr);
|
auto action = menu.addAction(QString::fromStdString("Izmjeni '" + attr->name + "'"),
|
||||||
dialog->exec();
|
[attr]() {
|
||||||
}
|
auto dialog = new AttributeDialog(attr);
|
||||||
});
|
dialog->exec();
|
||||||
action->setEnabled(enabled);
|
});
|
||||||
|
action->setEnabled(enabled);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
menu.addSeparator();
|
||||||
|
menu.addAction(QString::fromStdString("Ukloni " + this->instance->name), [this]() {
|
||||||
|
Application::instance()->removeComponent(this->instance->name);
|
||||||
|
auto view = dynamic_cast<Schema *>(this->scene()->views()[0]);
|
||||||
|
view->refreshContent();
|
||||||
|
});
|
||||||
|
|
||||||
menu.exec(event->screenPos());
|
menu.exec(event->screenPos());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,7 +68,7 @@ namespace display {
|
||||||
|
|
||||||
void Pin::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) {
|
void Pin::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) {
|
||||||
QMenu menu;
|
QMenu menu;
|
||||||
menu.addAction("Connect pin", [&]() {});
|
menu.addAction("Poveži pin", [&]() {});
|
||||||
menu.exec(event->screenPos());
|
menu.exec(event->screenPos());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,6 +81,8 @@ namespace display {
|
||||||
QPointF(pin.getDisplayPin().getConnectionX(),
|
QPointF(pin.getDisplayPin().getConnectionX(),
|
||||||
pin.getDisplayPin().getConnectionY());
|
pin.getDisplayPin().getConnectionY());
|
||||||
view->context.line = new QGraphicsLineItem(QLineF(view->context.startingPoint, event->scenePos()));
|
view->context.line = new QGraphicsLineItem(QLineF(view->context.startingPoint, event->scenePos()));
|
||||||
|
view->context.line->setPen(QPen(QColor::fromRgb(100, 100, 250), 1, Qt::PenStyle::DashLine));
|
||||||
|
view->context.line->setZValue(1000);
|
||||||
this->scene()->addItem(view->context.line);
|
this->scene()->addItem(view->context.line);
|
||||||
|
|
||||||
view->showConnectable(this);
|
view->showConnectable(this);
|
||||||
|
@ -103,9 +123,19 @@ namespace display {
|
||||||
for(const auto &component: Application::instance()->getSchema()->busInstances) {
|
for(const auto &component: Application::instance()->getSchema()->busInstances) {
|
||||||
names.insert(component->name);
|
names.insert(component->name);
|
||||||
}
|
}
|
||||||
|
auto dialog = new NameDialog(this->busInstance->name, names);
|
||||||
auto dialog = new NameDialog(this->busInstance.get(), names);
|
|
||||||
dialog->exec();
|
dialog->exec();
|
||||||
|
|
||||||
|
auto currentName = this->busInstance->name;
|
||||||
|
auto newName = dialog->getName();
|
||||||
|
|
||||||
|
Application::instance()->renameBus(currentName, newName);
|
||||||
|
});
|
||||||
|
menu.addSeparator();
|
||||||
|
menu.addAction(QString::fromStdString("Ukloni " + this->busInstance->name), [this]() {
|
||||||
|
Application::instance()->removeBus(this->busInstance->name);
|
||||||
|
auto view = dynamic_cast<Schema *>(this->scene()->views()[0]);
|
||||||
|
view->refreshContent();
|
||||||
});
|
});
|
||||||
menu.exec(event->screenPos());
|
menu.exec(event->screenPos());
|
||||||
}
|
}
|
||||||
|
@ -203,7 +233,8 @@ namespace display {
|
||||||
BusConnection::BusConnection(domain::BusConnectionInstance *connection, ComponentGroup *component, BusGroup *bus): connection(
|
BusConnection::BusConnection(domain::BusConnectionInstance *connection, ComponentGroup *component, BusGroup *bus): connection(
|
||||||
connection), component(component), bus(bus) {
|
connection), component(component), bus(bus) {
|
||||||
updateConnection();
|
updateConnection();
|
||||||
|
setPen(connectionPen);
|
||||||
|
setZValue(-1);
|
||||||
setHandlesChildEvents(false);
|
setHandlesChildEvents(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,23 +259,36 @@ namespace display {
|
||||||
QMenu menu;
|
QMenu menu;
|
||||||
menu.addAction("Ukloni poveznicu", [this]() {});
|
menu.addAction("Ukloni poveznicu", [this]() {});
|
||||||
menu.addSeparator();
|
menu.addSeparator();
|
||||||
for (int i = 0; i < this->connection->attributes.size(); i++) {
|
|
||||||
auto *attr = &this->connection->attributes[i];
|
|
||||||
bool enabled = attr->attribute.getPopup().has_value();
|
|
||||||
|
|
||||||
auto action = menu.addAction(QString::fromStdString("Izmjeni " + attr->name),
|
if(connection->bus->bus.getType() == domain::Bus::SINGLE_AUTOMATIC) {
|
||||||
[attr]() {
|
auto &attributes = this->connection->attributes;
|
||||||
auto dialog = new AttributeDialog(attr);
|
menu.addAction(QString::fromStdString("Izmjeni poveznicu"),
|
||||||
dialog->exec();
|
[&attributes]() {
|
||||||
});
|
auto dialog = new display::SingleAutomaticDialog(attributes);
|
||||||
action->setEnabled(enabled);
|
dialog->exec();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < this->connection->attributes.size(); i++) {
|
||||||
|
auto *attr = &this->connection->attributes[i];
|
||||||
|
bool enabled = attr->attribute.getPopup().has_value();
|
||||||
|
|
||||||
|
auto action = menu.addAction(QString::fromStdString("Izmjeni " + attr->name),
|
||||||
|
[attr]() {
|
||||||
|
auto dialog = new AttributeDialog(attr);
|
||||||
|
dialog->exec();
|
||||||
|
});
|
||||||
|
action->setEnabled(enabled);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
menu.exec(event->screenPos());
|
menu.exec(event->screenPos());
|
||||||
}
|
}
|
||||||
|
|
||||||
DirectConnection::DirectConnection(domain::DirectConnectionInstance *connection, ComponentGroup *first,
|
DirectConnection::DirectConnection(domain::DirectConnectionInstance *connection, ComponentGroup *first,
|
||||||
ComponentGroup *second): connection(connection), first(first), second(second) {
|
ComponentGroup *second): connection(connection), first(first), second(second) {
|
||||||
updateConnection();
|
updateConnection();
|
||||||
|
setPen(connectionPen);
|
||||||
|
setZValue(-1);
|
||||||
setHandlesChildEvents(false);
|
setHandlesChildEvents(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QListWidget>
|
#include <QListWidget>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
|
#include <application.h>
|
||||||
|
|
||||||
namespace display {
|
namespace display {
|
||||||
|
|
||||||
|
@ -13,17 +14,16 @@ namespace display {
|
||||||
componentList = new LibraryList(this);
|
componentList = new LibraryList(this);
|
||||||
busList = new LibraryList(this);
|
busList = new LibraryList(this);
|
||||||
|
|
||||||
layout->setMargin(4);
|
layout->setContentsMargins(4, 4, 4, 4);
|
||||||
layout->addWidget(new QLabel("Components:"));
|
layout->addWidget(new QLabel("Komponente:"));
|
||||||
layout->addWidget(componentList, 1);
|
layout->addWidget(componentList, 1);
|
||||||
layout->addSpacing(8);
|
layout->addSpacing(8);
|
||||||
layout->addWidget(new QLabel("Buses:"));
|
layout->addWidget(new QLabel("Sabirnice:"));
|
||||||
layout->addWidget(busList, 1);
|
layout->addWidget(busList, 1);
|
||||||
|
|
||||||
setLibrary(library);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Library::setLibrary(std::optional<domain::Library> library) {
|
void Library::refreshContent() {
|
||||||
|
library = Application::instance()->getLibrary();
|
||||||
|
|
||||||
componentList->clear();
|
componentList->clear();
|
||||||
busList->clear();
|
busList->clear();
|
||||||
|
|
|
@ -13,7 +13,7 @@ namespace display {
|
||||||
public:
|
public:
|
||||||
Library();
|
Library();
|
||||||
|
|
||||||
void setLibrary(std::optional<domain::Library> library);
|
void refreshContent();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::optional<domain::Library> library;
|
std::optional<domain::Library> library;
|
||||||
|
|
|
@ -29,4 +29,4 @@ namespace display {
|
||||||
: QListWidgetItem(parent), mimeType(mimeType), value(value) {
|
: QListWidgetItem(parent), mimeType(mimeType), value(value) {
|
||||||
setText(QString::fromStdString(title));
|
setText(QString::fromStdString(title));
|
||||||
}
|
}
|
||||||
} // display
|
} // display
|
||||||
|
|
|
@ -5,38 +5,21 @@
|
||||||
#include <set>
|
#include <set>
|
||||||
#include "name_dialog.h"
|
#include "name_dialog.h"
|
||||||
|
|
||||||
display::NameDialog::NameDialog(domain::ComponentInstance *instance, std::set<std::string>& names) : componentInstance(instance), usedNames(names) {
|
display::NameDialog::NameDialog(std::string currentName, std::set<std::string> &names): currentName(currentName) {
|
||||||
usedNames.erase(instance->name);
|
usedNames.erase(currentName);
|
||||||
|
|
||||||
auto *layout = new QVBoxLayout(this);
|
auto *layout = new QVBoxLayout(this);
|
||||||
layout->addWidget(new QLabel("Izmjeni ime", this));
|
layout->addWidget(new QLabel("Izmjeni ime", this));
|
||||||
|
|
||||||
edit = new QLineEdit(this);
|
edit = new QLineEdit(this);
|
||||||
edit->insert(instance->name.c_str());
|
edit->insert(currentName.c_str());
|
||||||
connect(edit, &QLineEdit::textChanged, this, &NameDialog::onNameUpdate);
|
connect(edit, &QLineEdit::textChanged, this, &NameDialog::onNameUpdate);
|
||||||
layout->addWidget(edit);
|
layout->addWidget(edit);
|
||||||
this->setWindowTitle("Izmjeni ime");
|
setWindowTitle("Izmjeni ime");
|
||||||
button = new QPushButton("Ažuriraj", this);
|
button = new QPushButton("Ažuriraj", this);
|
||||||
connect(button, &QPushButton::clicked, this, &NameDialog::onNameChange);
|
connect(button, &QPushButton::clicked, this, &NameDialog::onNameChange);
|
||||||
layout->addWidget(button);
|
layout->addWidget(button);
|
||||||
this->setLayout(layout);
|
setLayout(layout);
|
||||||
}
|
|
||||||
|
|
||||||
display::NameDialog::NameDialog(domain::BusInstance *instance, std::set<std::string>& names): busInstance(instance), usedNames(names) {
|
|
||||||
usedNames.erase(instance->name);
|
|
||||||
|
|
||||||
auto *layout = new QVBoxLayout(this);
|
|
||||||
layout->addWidget(new QLabel("Izmjeni ime", this));
|
|
||||||
|
|
||||||
edit = new QLineEdit(this);
|
|
||||||
edit->insert(instance->name.c_str());
|
|
||||||
connect(edit, &QLineEdit::textChanged, this, &NameDialog::onNameUpdate);
|
|
||||||
layout->addWidget(edit);
|
|
||||||
this->setWindowTitle("Izmjeni ime");
|
|
||||||
button = new QPushButton("Ažuriraj", this);
|
|
||||||
connect(button, &QPushButton::clicked, this, &NameDialog::onNameChange);
|
|
||||||
layout->addWidget(button);
|
|
||||||
this->setLayout(layout);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void display::NameDialog::onNameUpdate(const QString &text) {
|
void display::NameDialog::onNameUpdate(const QString &text) {
|
||||||
|
@ -48,12 +31,10 @@ void display::NameDialog::onNameUpdate(const QString &text) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void display::NameDialog::onNameChange() {
|
void display::NameDialog::onNameChange() {
|
||||||
|
currentName = edit->text().toStdString();
|
||||||
|
close();
|
||||||
if (componentInstance != nullptr) {
|
}
|
||||||
componentInstance->name = this->edit->text().toStdString();
|
|
||||||
} else if (busInstance != nullptr) {
|
std::string display::NameDialog::getName() {
|
||||||
busInstance->name = this->edit->text().toStdString();
|
return currentName;
|
||||||
}
|
|
||||||
this->close();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,15 +17,13 @@ namespace display {
|
||||||
|
|
||||||
std::set<std::string> usedNames;
|
std::set<std::string> usedNames;
|
||||||
QLineEdit *edit = nullptr;
|
QLineEdit *edit = nullptr;
|
||||||
domain::ComponentInstance *componentInstance = nullptr;
|
std::string currentName;
|
||||||
domain::BusInstance *busInstance = nullptr;
|
|
||||||
QPushButton *button;
|
QPushButton *button;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
NameDialog(std::string currentName, std::set<std::string>& names);
|
||||||
|
|
||||||
NameDialog(domain::ComponentInstance *instance, std::set<std::string>& names);
|
std::string getName();
|
||||||
|
|
||||||
NameDialog(domain::BusInstance *instance, std::set<std::string>& names);
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void onNameUpdate(const QString& text);
|
void onNameUpdate(const QString& text);
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include "schema_display.h"
|
#include "schema_display.h"
|
||||||
#include "application.h"
|
#include "application.h"
|
||||||
#include "attribute_dialog.h"
|
#include "attribute_dialog.h"
|
||||||
|
#include "single_automatic_dialog.h"
|
||||||
|
|
||||||
#include <QDrag>
|
#include <QDrag>
|
||||||
#include <QDragEnterEvent>
|
#include <QDragEnterEvent>
|
||||||
|
@ -10,8 +11,6 @@
|
||||||
namespace display {
|
namespace display {
|
||||||
|
|
||||||
Schema::Schema() {
|
Schema::Schema() {
|
||||||
this->selectedBrush.setColor(QColor::fromRgb(20, 20, 125));
|
|
||||||
this->selectedPen.setColor(QColor::fromRgb(20, 20, 125));
|
|
||||||
schema = nullptr;
|
schema = nullptr;
|
||||||
library = std::nullopt;
|
library = std::nullopt;
|
||||||
this->setScene(&scene);
|
this->setScene(&scene);
|
||||||
|
@ -19,14 +18,17 @@ namespace display {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Schema::setSchema(domain::Schema *_schema, std::optional<domain::Library> _library) {
|
void Schema::refreshContent() {
|
||||||
|
schema = Application::instance()->getSchema();
|
||||||
|
library = Application::instance()->getLibrary();
|
||||||
|
|
||||||
components.clear();
|
components.clear();
|
||||||
buses.clear();
|
buses.clear();
|
||||||
|
|
||||||
scene.clear();
|
scene.clear();
|
||||||
|
pins.clear();
|
||||||
busConnections.clear();
|
busConnections.clear();
|
||||||
this->schema = _schema;
|
directConnections.clear();
|
||||||
this->library = _library;
|
|
||||||
if (schema != nullptr) {
|
if (schema != nullptr) {
|
||||||
for (auto &instance: schema->componentInstances) {
|
for (auto &instance: schema->componentInstances) {
|
||||||
auto group = new display::ComponentGroup(instance);
|
auto group = new display::ComponentGroup(instance);
|
||||||
|
@ -86,27 +88,9 @@ namespace display {
|
||||||
if (event->mimeData()->hasFormat("comdel/component")) {
|
if (event->mimeData()->hasFormat("comdel/component")) {
|
||||||
auto component = library->getComponent(event->mimeData()->data("comdel/component").toStdString());
|
auto component = library->getComponent(event->mimeData()->data("comdel/component").toStdString());
|
||||||
|
|
||||||
auto attributes = std::vector<domain::InstanceAttribute>();
|
auto attributes = populateAttributes(component.getAttributes());
|
||||||
for (auto attr: component.getAttributes()) {
|
if(attributes.size() != component.getAttributes().size()) {
|
||||||
domain::InstanceAttribute attribute(attr.getName(), attr.getDefault(), attr);
|
return;
|
||||||
if(attr.getPopup().has_value() && attr.getPopup()->getType() == domain::Popup::AUTOMATIC) {
|
|
||||||
if(attr.getDefault().isType(domain::Value::MEMORY_REFERENCE)) {
|
|
||||||
auto dialog = new MemoryDialog(&attribute, schema->componentInstances);
|
|
||||||
if(dialog->exec() == QDialog::Rejected) {
|
|
||||||
// if any dialog isn't set, whole creation is rejected
|
|
||||||
event->ignore();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
auto dialog = new AttributeDialog(&attribute);
|
|
||||||
if(dialog->exec() == QDialog::Rejected) {
|
|
||||||
// if any dialog isn't set, whole creation is rejected
|
|
||||||
event->ignore();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
attributes.push_back(attribute);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto currentPos = this->mapToScene(event->pos()).toPoint();
|
auto currentPos = this->mapToScene(event->pos()).toPoint();
|
||||||
|
@ -148,18 +132,26 @@ namespace display {
|
||||||
auto instance = context.pin->getComponentInstance();
|
auto instance = context.pin->getComponentInstance();
|
||||||
auto &pin = context.pin->getPin();
|
auto &pin = context.pin->getPin();
|
||||||
|
|
||||||
auto busInstances = getAvailableConnectionBusses(instance, pin);
|
auto availableConnections = schema->availableConnections(instance->name, pin.getName(), true);
|
||||||
|
|
||||||
for (auto &bus: busInstances) {
|
for(auto &connection: availableConnections) {
|
||||||
|
if(connection.type != domain::ConnectionEntry::BUS) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto bus = connection.busInstance.value();
|
||||||
|
if(buses[bus->name] == nullptr) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
auto rect = buses[bus->name]->boundingRect();
|
auto rect = buses[bus->name]->boundingRect();
|
||||||
rect = QRectF(buses[bus->name]->x(), buses[bus->name]->y(), rect.width(), rect.height());
|
rect = QRectF(buses[bus->name]->x(), buses[bus->name]->y(), rect.width(), rect.height());
|
||||||
|
|
||||||
if (rect.contains(endPoint)) {
|
if (rect.contains(endPoint)) {
|
||||||
auto con = library->getConnection({instance->component.getName(), pin.getName()}, bus->bus.getName());
|
auto con = library->getConnection({instance->component.getName(), pin.getName()}, bus->bus.getName());
|
||||||
if (con.has_value()) {
|
if (con.has_value()) {
|
||||||
std::vector<domain::InstanceAttribute> attributes;
|
auto attributes = populateAttributes(con->getAttributes());
|
||||||
for (auto attr: con->getAttributes()) {
|
if(attributes.size() != con->getAttributes().size()) {
|
||||||
attributes.emplace_back(attr.getName(), attr.getDefault(), attr);
|
clearSelectable();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto conInstance = std::make_shared<domain::BusConnectionInstance>(instance, attributes, bus, *con);
|
auto conInstance = std::make_shared<domain::BusConnectionInstance>(instance, attributes, bus, *con);
|
||||||
|
@ -176,9 +168,11 @@ namespace display {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pinInstances = getAvailableConnectionPins(instance, pin);
|
for (auto &connection: availableConnections) {
|
||||||
|
if(connection.type != domain::ConnectionEntry::COMPONENT) {
|
||||||
for (auto &pinInstance: pinInstances) {
|
continue;
|
||||||
|
}
|
||||||
|
auto pinInstance = domain::ConnectionComponent{connection.componentInstance.value()->name, connection.pin.value().getName()};
|
||||||
auto rect = pins[pinInstance]->boundingRect();
|
auto rect = pins[pinInstance]->boundingRect();
|
||||||
rect.setX(pins[pinInstance]->scenePos().x());
|
rect.setX(pins[pinInstance]->scenePos().x());
|
||||||
rect.setY(pins[pinInstance]->scenePos().y());
|
rect.setY(pins[pinInstance]->scenePos().y());
|
||||||
|
@ -188,13 +182,17 @@ namespace display {
|
||||||
auto con = library->getConnection({instance->component.getName(), pin.getName()},
|
auto con = library->getConnection({instance->component.getName(), pin.getName()},
|
||||||
{name, pinInstance.pin});
|
{name, pinInstance.pin});
|
||||||
if (con.has_value()) {
|
if (con.has_value()) {
|
||||||
auto bus = library->getBus(con->getBus());
|
auto busInstance = Application::instance()->addBus(library->getBus(con->getBus()), 0, 0);
|
||||||
auto busInstance = std::make_shared<domain::BusInstance>(bus.getName(), bus);
|
|
||||||
schema->busInstances.push_back(busInstance);
|
|
||||||
|
|
||||||
std::vector<domain::InstanceAttribute> attributes;
|
std::vector<domain::InstanceAttribute> attributes;
|
||||||
for (auto attr: con->getAttributes()) {
|
if(library->getBus(con->getBus()).getType() == domain::Bus::SINGLE_AUTOMATIC) {
|
||||||
attributes.emplace_back(attr.getName(), attr.getDefault(), attr);
|
attributes = populateSingleAutomaticConnection(*con);
|
||||||
|
} else {
|
||||||
|
attributes = populateAttributes(con->getAttributes());
|
||||||
|
}
|
||||||
|
if(attributes.size() != con->getAttributes().size()) {
|
||||||
|
clearSelectable();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto conInstance = std::make_shared<domain::DirectConnectionInstance>(instance,
|
auto conInstance = std::make_shared<domain::DirectConnectionInstance>(instance,
|
||||||
|
@ -215,28 +213,25 @@ namespace display {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateConnections();
|
clearSelectable();
|
||||||
|
|
||||||
|
|
||||||
for (auto &item: this->context.selectable) {
|
|
||||||
this->scene.removeItem(item);
|
|
||||||
delete item;
|
|
||||||
}
|
|
||||||
this->context.selectable.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Schema::showConnectable(Pin *domainPin) {
|
void Schema::showConnectable(Pin *domainPin) {
|
||||||
auto &pin = domainPin->getPin();
|
auto &pin = domainPin->getPin();
|
||||||
|
|
||||||
auto busInstances = getAvailableConnectionBusses(domainPin->getComponentInstance(), domainPin->getPin());
|
auto availableConnections = schema->availableConnections(domainPin->getComponentInstance()->name, pin.getName(), true);
|
||||||
|
|
||||||
for (auto bus: busInstances) {
|
for(auto &connection: availableConnections) {
|
||||||
|
if(connection.type != domain::ConnectionEntry::BUS) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto bus = connection.busInstance.value();
|
||||||
auto &group = buses[bus->name];
|
auto &group = buses[bus->name];
|
||||||
if(group == nullptr) {
|
if(group == nullptr) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
auto rect = new QGraphicsRectItem(group->boundingRect());
|
auto rect = new QGraphicsRectItem(group->boundingRect());
|
||||||
rect->setPen(selectedPen);
|
rect->setBrush(selectedBrush);
|
||||||
rect->setPos(group->scenePos());
|
rect->setPos(group->scenePos());
|
||||||
|
|
||||||
auto _rect = rect->rect();
|
auto _rect = rect->rect();
|
||||||
|
@ -248,12 +243,14 @@ namespace display {
|
||||||
scene.addItem(rect);
|
scene.addItem(rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<domain::ConnectionComponent> pinInstances = getAvailableConnectionPins(
|
for (auto &connection: availableConnections) {
|
||||||
domainPin->getComponentInstance(), domainPin->getPin());
|
if(connection.type != domain::ConnectionEntry::COMPONENT) {
|
||||||
|
continue;
|
||||||
for (auto &pinInstance: pinInstances) {
|
}
|
||||||
|
auto pinInstance = domain::ConnectionComponent{connection.componentInstance.value()->name, connection.pin.value().getName()};
|
||||||
auto &instance = pins[pinInstance];
|
auto &instance = pins[pinInstance];
|
||||||
auto rect = new QGraphicsRectItem(instance->boundingRect());
|
auto rect = new QGraphicsRectItem(instance->boundingRect());
|
||||||
|
rect->setBrush(selectedBrush);
|
||||||
rect->setPen(selectedPen);
|
rect->setPen(selectedPen);
|
||||||
rect->setPos(instance->scenePos());
|
rect->setPos(instance->scenePos());
|
||||||
|
|
||||||
|
@ -268,29 +265,56 @@ namespace display {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<domain::BusInstance *>
|
std::vector<domain::InstanceAttribute> Schema::populateAttributes(std::vector<domain::Attribute>& attributes) {
|
||||||
Schema::getAvailableConnectionBusses(domain::ComponentInstance *instance, domain::Pin &pin) {
|
std::vector<domain::InstanceAttribute> instanceAttributes;
|
||||||
std::vector<domain::BusInstance *> instances;
|
|
||||||
for (const auto &bus: schema->busInstances) {
|
for (auto attr: attributes) {
|
||||||
if (library->hasConnection(domain::ConnectionComponent{instance->component.getName(), pin.getName()},
|
domain::InstanceAttribute attribute(attr.getName(), attr.getDefault(), attr);
|
||||||
bus->bus.getName())) {
|
if(attr.getPopup().has_value() && attr.getPopup()->getType() == domain::Popup::AUTOMATIC) {
|
||||||
instances.push_back(bus.get());
|
if(attr.getDefault().isType(domain::Value::MEMORY_REFERENCE)) {
|
||||||
|
auto dialog = new MemoryDialog(&attribute, schema->componentInstances, false);
|
||||||
|
if(dialog->exec() == QDialog::Rejected) {
|
||||||
|
// if any dialog isn't set, whole creation is rejected
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
auto dialog = new AttributeDialog(&attribute, false);
|
||||||
|
if(dialog->exec() == QDialog::Rejected) {
|
||||||
|
// if any dialog isn't set, whole creation is rejected
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
instanceAttributes.push_back(attribute);
|
||||||
}
|
}
|
||||||
return instances;
|
return instanceAttributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<domain::ConnectionComponent>
|
std::vector<domain::InstanceAttribute> Schema::populateSingleAutomaticConnection(domain::Connection connection) {
|
||||||
Schema::getAvailableConnectionPins(domain::ComponentInstance *instance, domain::Pin &pin) {
|
std::vector<domain::InstanceAttribute> instanceAttributes;
|
||||||
std::vector<domain::ConnectionComponent> instances;
|
|
||||||
domain::ConnectionComponent source{instance->component.getName(), pin.getName()};
|
for (auto attr: connection.getAttributes()) {
|
||||||
for (const auto &entry: pins) {
|
instanceAttributes.emplace_back(attr.getName(), attr.getDefault(), attr);
|
||||||
std::string name = components[entry.first.component]->getComponentInstance()->component.getName();
|
|
||||||
if (library->hasConnection(source, domain::ConnectionComponent{name, entry.first.pin})) {
|
|
||||||
instances.push_back(entry.first);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return instances;
|
|
||||||
|
auto dialog = new display::SingleAutomaticDialog(instanceAttributes, false);
|
||||||
|
if(dialog->exec() == QDialog::Rejected) {
|
||||||
|
// if dialog is rejected, whole creation is rejected
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return instanceAttributes;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Schema::clearSelectable() {
|
||||||
|
updateConnections();
|
||||||
|
|
||||||
|
for (auto &item: this->context.selectable) {
|
||||||
|
this->scene.removeItem(item);
|
||||||
|
delete item;
|
||||||
|
}
|
||||||
|
this->context.selectable.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace display
|
} // namespace display
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#include <QGraphicsView>
|
#include <QGraphicsView>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
#include <QColor>
|
||||||
#include <QGraphicsLineItem>
|
#include <QGraphicsLineItem>
|
||||||
|
|
||||||
#include <comdel/domain/schema.h>
|
#include <comdel/domain/schema.h>
|
||||||
|
@ -19,8 +20,9 @@ namespace display {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
QBrush selectedBrush;
|
QBrush selectedBrush = QBrush(QColor::fromRgb(50, 50, 150, 100), Qt::BrushStyle::SolidPattern);
|
||||||
QPen selectedPen;
|
QPen selectedPen = QPen(QColor::fromRgb(50, 50, 150), 1, Qt::PenStyle::SolidLine);
|
||||||
|
QPen activeLinePen = QPen(QColor::fromRgb(250, 100, 100));
|
||||||
|
|
||||||
enum State {
|
enum State {
|
||||||
DEFAULT,
|
DEFAULT,
|
||||||
|
@ -46,14 +48,14 @@ namespace display {
|
||||||
std::vector<BusConnection *> busConnections;
|
std::vector<BusConnection *> busConnections;
|
||||||
std::vector<DirectConnection *> directConnections;
|
std::vector<DirectConnection *> directConnections;
|
||||||
|
|
||||||
void setSchema(domain::Schema *schema, std::optional<domain::Library> library);
|
|
||||||
|
|
||||||
void updateConnections();
|
void updateConnections();
|
||||||
|
|
||||||
void removeConnectable(QPointF f);
|
void removeConnectable(QPointF f);
|
||||||
|
|
||||||
void showConnectable(Pin *pin);
|
void showConnectable(Pin *pin);
|
||||||
|
|
||||||
|
void refreshContent();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
void dragEnterEvent(QDragEnterEvent *event) override;
|
void dragEnterEvent(QDragEnterEvent *event) override;
|
||||||
|
@ -68,11 +70,11 @@ namespace display {
|
||||||
domain::Schema *schema{};
|
domain::Schema *schema{};
|
||||||
std::optional<domain::Library> library;
|
std::optional<domain::Library> library;
|
||||||
|
|
||||||
std::vector<domain::BusInstance *>
|
std::vector<domain::InstanceAttribute> populateAttributes(std::vector<domain::Attribute>& attributes);
|
||||||
getAvailableConnectionBusses(domain::ComponentInstance *instance, domain::Pin &pin);
|
|
||||||
|
|
||||||
std::vector<domain::ConnectionComponent>
|
std::vector<domain::InstanceAttribute> populateSingleAutomaticConnection(domain::Connection connection);
|
||||||
getAvailableConnectionPins(domain::ComponentInstance *instance, domain::Pin &pin);
|
|
||||||
|
void clearSelectable();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace display
|
} // namespace display
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
//
|
||||||
|
// Created by bbr on 05.06.22..
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "single_automatic_dialog.h"
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QComboBox>
|
||||||
|
#include <QPushButton>
|
||||||
|
|
||||||
|
namespace display {
|
||||||
|
SingleAutomaticDialog::SingleAutomaticDialog(std::vector<domain::InstanceAttribute> &values, bool updating): attributes(values) {
|
||||||
|
setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
setWindowTitle(QString::fromStdString(updating ? "Ažuriraj poveznicu" : "Postavi poveznicu"));
|
||||||
|
|
||||||
|
firstValue = values[0].value;
|
||||||
|
secondValue = values[1].value;
|
||||||
|
|
||||||
|
auto *parentLayout = new QVBoxLayout(this);
|
||||||
|
auto *contentLayout = new QHBoxLayout(this);
|
||||||
|
auto *firstLayout = new QVBoxLayout(this);
|
||||||
|
auto *secondLayout = new QVBoxLayout(this);
|
||||||
|
|
||||||
|
parentLayout->addLayout(contentLayout);
|
||||||
|
contentLayout->addLayout(firstLayout);
|
||||||
|
contentLayout->addLayout(secondLayout);
|
||||||
|
this->setLayout(parentLayout);
|
||||||
|
|
||||||
|
setupValues(firstLayout, values[0], &SingleAutomaticDialog::onFirstEnumerationChanged);
|
||||||
|
setupValues(secondLayout, values[1], &SingleAutomaticDialog::onSecondEnumerationChanged);
|
||||||
|
|
||||||
|
auto button = new QPushButton(updating ? "Ažuriraj" : "Postavi");
|
||||||
|
connect(button, &QPushButton::clicked, this, &SingleAutomaticDialog::onUpdate);
|
||||||
|
parentLayout->addWidget(button);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SingleAutomaticDialog::setupValues(QVBoxLayout *layout, domain::InstanceAttribute &attribute, void (display::SingleAutomaticDialog::* handler)(int)) {
|
||||||
|
|
||||||
|
auto popup = *attribute.attribute.getPopup();
|
||||||
|
|
||||||
|
layout->addWidget(new QLabel(popup.getTitle().c_str()));
|
||||||
|
layout->addWidget(new QLabel(popup.getText().c_str()));
|
||||||
|
|
||||||
|
auto *combo = new QComboBox(this);
|
||||||
|
auto enumeration = attribute.attribute.getPopup()->getEnumeration();
|
||||||
|
for (auto entry: enumeration) {
|
||||||
|
combo->addItem(QString::fromStdString(entry.getName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
connect(combo, QOverload<int>::of(&QComboBox::currentIndexChanged), this,handler);
|
||||||
|
layout->addWidget(combo);
|
||||||
|
|
||||||
|
for (int i = 0; i < enumeration.size(); i++) {
|
||||||
|
if (attribute.value.equals(enumeration[i].getValue())) {
|
||||||
|
combo->setCurrentIndex(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SingleAutomaticDialog::onFirstEnumerationChanged(int index) {
|
||||||
|
firstValue = attributes[0].attribute.getPopup()->getEnumeration()[index].getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SingleAutomaticDialog::onSecondEnumerationChanged(int index) {
|
||||||
|
secondValue = attributes[1].attribute.getPopup()->getEnumeration()[index].getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SingleAutomaticDialog::onUpdate() {
|
||||||
|
attributes[0].value = firstValue;
|
||||||
|
attributes[1].value = secondValue;
|
||||||
|
accept();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // display
|
|
@ -0,0 +1,35 @@
|
||||||
|
//
|
||||||
|
// Created by bbr on 05.06.22..
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef SCHEMEEDITOR_SINGLE_AUTOMATIC_DIALOG_H
|
||||||
|
#define SCHEMEEDITOR_SINGLE_AUTOMATIC_DIALOG_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <QDialog>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include "comdel/domain/value.h"
|
||||||
|
#include "comdel/domain/instance_attribute.h"
|
||||||
|
|
||||||
|
namespace display {
|
||||||
|
|
||||||
|
class SingleAutomaticDialog: public QDialog {
|
||||||
|
domain::Value firstValue;
|
||||||
|
domain::Value secondValue;
|
||||||
|
std::vector<domain::InstanceAttribute> &attributes;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit SingleAutomaticDialog(std::vector<domain::InstanceAttribute>& values, bool updating = true);
|
||||||
|
|
||||||
|
void setupValues(QVBoxLayout *layout, domain::InstanceAttribute &attribute, void (display::SingleAutomaticDialog::* handler)(int));
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
|
||||||
|
void onFirstEnumerationChanged(int index);
|
||||||
|
void onSecondEnumerationChanged(int index);
|
||||||
|
void onUpdate();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // display
|
||||||
|
|
||||||
|
#endif //SCHEMEEDITOR_SINGLE_AUTOMATIC_DIALOG_H
|
|
@ -59,4 +59,8 @@ namespace domain {
|
||||||
return popup;
|
return popup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Attribute::setPupup(std::optional<Popup> popup) {
|
||||||
|
this->popup = popup;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace domain
|
} // namespace domain
|
||||||
|
|
|
@ -54,7 +54,7 @@ namespace domain {
|
||||||
|
|
||||||
void setEnumeration(std::vector<Enumeration> enums) {
|
void setEnumeration(std::vector<Enumeration> enums) {
|
||||||
enumerated = true;
|
enumerated = true;
|
||||||
enumeration = std::move(enums);
|
enumeration = enums;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -71,6 +71,7 @@ namespace domain {
|
||||||
Value getDefault();
|
Value getDefault();
|
||||||
|
|
||||||
std::optional<Popup> getPopup();
|
std::optional<Popup> getPopup();
|
||||||
|
void setPupup(std::optional<Popup> popup);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace domain
|
} // namespace domain
|
||||||
|
|
|
@ -285,7 +285,11 @@ namespace domain {
|
||||||
} else {
|
} else {
|
||||||
// if no connection exists than defaults must exist
|
// if no connection exists than defaults must exist
|
||||||
for (auto &wire: *pin.getWires()) {
|
for (auto &wire: *pin.getWires()) {
|
||||||
tempOutput << wire.stringify() << ", ";
|
if(wire.isType(Value::NIL)) {
|
||||||
|
tempOutput << "*, ";
|
||||||
|
} else {
|
||||||
|
tempOutput << wire.stringify() << ", ";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -311,22 +315,26 @@ namespace domain {
|
||||||
std::vector<Value> defaults;
|
std::vector<Value> defaults;
|
||||||
if (connection->instance->name == name && connection->connection.getComponent().pin == pin) {
|
if (connection->instance->name == name && connection->connection.getComponent().pin == pin) {
|
||||||
wires = connection->connection.getWires();
|
wires = connection->connection.getWires();
|
||||||
selected = connection->attributes[0].value.asReference();
|
selected = connection->attributes[0].value.asString();
|
||||||
defaults = *connection->instance->component.getPin(pin).getWires();
|
defaults = *connection->instance->component.getPin(pin).getWires();
|
||||||
} else {
|
} else {
|
||||||
wires = *connection->connection.getSecondWires();
|
wires = *connection->connection.getSecondWires();
|
||||||
selected = connection->attributes[1].value.asReference();
|
selected = connection->attributes[1].value.asString();
|
||||||
defaults = *connection->secondInstance->component.getPin(pin).getWires();
|
defaults = *connection->secondInstance->component.getPin(pin).getWires();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < wires.size(); i++) {
|
for (int i = 0; i < wires.size(); i++) {
|
||||||
if (wires[i].isType(Value::STRING)) {
|
if (wires[i].isType(Value::STRING)) {
|
||||||
if (wires[i].asString() == selected) {
|
if (wires[i].asString() == selected) {
|
||||||
buffer << wireNames[connection->bus->name + "." + connection->bus->bus.getWires()[0].getName()]
|
auto wireName = connection->bus->name + "." + connection->bus->bus.getWires()[0].getName();
|
||||||
<< ", ";
|
buffer << wireNames[wireName] << ", ";
|
||||||
|
} else if(defaults[i].isType(Value::NIL)) {
|
||||||
|
buffer << "*, ";
|
||||||
} else {
|
} else {
|
||||||
buffer << defaults[i].stringify();
|
buffer << defaults[i].stringify() << ", ";
|
||||||
}
|
}
|
||||||
|
} else if(defaults[i].isType(Value::NIL)) {
|
||||||
|
buffer << "*, ";
|
||||||
} else {
|
} else {
|
||||||
buffer << wires[i].stringify() << ", ";
|
buffer << wires[i].stringify() << ", ";
|
||||||
}
|
}
|
||||||
|
|
|
@ -153,6 +153,37 @@ namespace domain {
|
||||||
return nullopt;
|
return nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<ValidationError>
|
||||||
|
ComdelValidator::validateMemoryReferences(Schema &schema, Library &library, ValidationContext context) {
|
||||||
|
std::set<std::string> memoryInstances;
|
||||||
|
for(auto& component: schema.componentInstances) {
|
||||||
|
if(component->component.getType() == Component::MEMORY) {
|
||||||
|
memoryInstances.insert(component->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<ValidationError> errors;
|
||||||
|
for(auto& component: schema.componentInstances) {
|
||||||
|
if(component->component.getType() == Component::PROCESSOR) {
|
||||||
|
for(auto& attribute: component->attributes) {
|
||||||
|
if(attribute.value.isType(Value::MEMORY_REFERENCE)) {
|
||||||
|
auto memoryReference = attribute.value.asMemoryReference();
|
||||||
|
if(memoryReference != nullopt) {
|
||||||
|
if(memoryInstances.count(*memoryReference) == 0) {
|
||||||
|
context.attributes["memoryReference"] = domain::Value::fromString(memoryReference.value());
|
||||||
|
auto message = populateMessage("Ne postoji memorijska komponenta '{memoryReference}'", context);
|
||||||
|
errors.emplace_back(component.get(), nullptr, Action::ERROR, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<ValidationError>
|
std::vector<ValidationError>
|
||||||
ComdelValidator::validateInstanceNames(Schema &schema, Library &library, ValidationContext context) {
|
ComdelValidator::validateInstanceNames(Schema &schema, Library &library, ValidationContext context) {
|
||||||
std::set<std::string> names;
|
std::set<std::string> names;
|
||||||
|
|
|
@ -35,6 +35,8 @@ namespace domain {
|
||||||
|
|
||||||
std::optional<ValidationError> validateRule(Rule rule, ValidationContext context);
|
std::optional<ValidationError> validateRule(Rule rule, ValidationContext context);
|
||||||
|
|
||||||
|
std::vector<ValidationError> validateMemoryReferences(Schema &schema, Library &library, ValidationContext context);
|
||||||
|
|
||||||
std::vector<ValidationError> validateInstanceNames(Schema &schema, Library &library, 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> validateInstanceCount(Schema &schema, Library &library, ValidationContext context);
|
||||||
|
|
|
@ -62,7 +62,7 @@ namespace domain {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Attribute> Component::getAttributes() {
|
std::vector<Attribute>& Component::getAttributes() {
|
||||||
return attributes;
|
return attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,7 @@ namespace domain {
|
||||||
|
|
||||||
Pin getPin(std::string pin);
|
Pin getPin(std::string pin);
|
||||||
|
|
||||||
std::vector<Attribute> getAttributes();
|
std::vector<Attribute>& getAttributes();
|
||||||
|
|
||||||
Attribute getAttribute(std::string attribute);
|
Attribute getAttribute(std::string attribute);
|
||||||
|
|
||||||
|
|
|
@ -16,11 +16,11 @@ namespace domain {
|
||||||
return second;
|
return second;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Connection::getBus() {
|
std::string &Connection::getBus() {
|
||||||
return bus;
|
return bus;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Attribute> Connection::getAttributes() {
|
std::vector<Attribute>& Connection::getAttributes() {
|
||||||
return attributes;
|
return attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,14 +53,17 @@ namespace domain {
|
||||||
|
|
||||||
bool isConnecting(ConnectionComponent first, ConnectionComponent second);
|
bool isConnecting(ConnectionComponent first, ConnectionComponent second);
|
||||||
|
|
||||||
|
bool operator==(const Connection& connection) {
|
||||||
|
return (first == connection.first && bus == connection.bus && second == connection.second);
|
||||||
|
}
|
||||||
|
|
||||||
ConnectionComponent getComponent();
|
ConnectionComponent getComponent();
|
||||||
|
|
||||||
std::optional<ConnectionComponent> getSecondComponent();
|
std::optional<ConnectionComponent> getSecondComponent();
|
||||||
|
|
||||||
std::string getBus();
|
std::string &getBus();
|
||||||
|
|
||||||
std::vector<Attribute> getAttributes();
|
std::vector<Attribute>& getAttributes();
|
||||||
|
|
||||||
std::vector<Value> getWires();
|
std::vector<Value> getWires();
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,13 @@
|
||||||
#include "display.h"
|
#include "display.h"
|
||||||
|
|
||||||
|
#include <QBrush>
|
||||||
|
#include <QPen>
|
||||||
|
|
||||||
namespace domain {
|
namespace domain {
|
||||||
|
|
||||||
|
QBrush busBrush(QColor::fromRgb(200, 200, 200));
|
||||||
|
QPen busPen(QColor::fromRgb(200, 200, 200));
|
||||||
|
|
||||||
Display::Display(std::vector<ui::Item> items) : items(items) {}
|
Display::Display(std::vector<ui::Item> items) : items(items) {}
|
||||||
|
|
||||||
void Display::render(QGraphicsItemGroup *group) {
|
void Display::render(QGraphicsItemGroup *group) {
|
||||||
|
@ -39,11 +45,16 @@ namespace domain {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ui::Bus::render(QGraphicsItemGroup *group, int size) {
|
void ui::Bus::render(QGraphicsItemGroup *group, int size) {
|
||||||
|
int _w = w, _h = h;
|
||||||
if (orientation == HORIZONTAL) {
|
if (orientation == HORIZONTAL) {
|
||||||
group->addToGroup(new QGraphicsRectItem(x, y, size, h));
|
_w = size;
|
||||||
} else {
|
} else {
|
||||||
group->addToGroup(new QGraphicsRectItem(x, y, w, size));
|
_h = size;
|
||||||
}
|
}
|
||||||
|
auto rect = new QGraphicsRectItem(x, y, _w, _h);
|
||||||
|
rect->setBrush(busBrush);
|
||||||
|
rect->setPen(busPen);
|
||||||
|
group->addToGroup(rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ui::Bus::getDefaultSize() {
|
int ui::Bus::getDefaultSize() {
|
||||||
|
|
|
@ -39,4 +39,72 @@ namespace domain {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<ConnectionEntry> Schema::availableConnections(std::string instanceName, std::string pinName, bool onlyConnectable) {
|
||||||
|
std::vector<ConnectionEntry> entries;
|
||||||
|
|
||||||
|
auto instance = getComponentInstance(instanceName);
|
||||||
|
|
||||||
|
ConnectionComponent connectionComponent{instance->component.getName(), pinName};
|
||||||
|
for(auto &conn: library.getConnections()) {
|
||||||
|
if(conn.isConnecting(connectionComponent)) {
|
||||||
|
// if bus connection
|
||||||
|
if(library.getBus(conn.getBus()).getType() == Bus::REGULAR) {
|
||||||
|
for(auto& bus: busInstances) {
|
||||||
|
if(bus->bus.getName() == conn.getBus()) {
|
||||||
|
ConnectionEntry entry{ConnectionEntry::BUS, bus.get(), nullopt, nullopt, conn};
|
||||||
|
entries.emplace_back(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for(auto& component: componentInstances) {
|
||||||
|
for(auto& pin: component->component.getPins()) {
|
||||||
|
if(conn.isConnecting(connectionComponent, {component->component.getName(), pin.getName()})) {
|
||||||
|
ConnectionEntry entry{ConnectionEntry::COMPONENT, nullopt, component.get(), pin, conn};
|
||||||
|
entries.emplace_back(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(onlyConnectable) {
|
||||||
|
entries.erase(
|
||||||
|
std::remove_if(
|
||||||
|
entries.begin(),
|
||||||
|
entries.end(),
|
||||||
|
[this, instance](ConnectionEntry &entry) {
|
||||||
|
auto& bus = this->library.getBus(entry.connection.getBus());
|
||||||
|
// we allow duplicates of single automatic connections
|
||||||
|
if(bus.getType() == Bus::SINGLE_AUTOMATIC) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for(auto& conn: this->connections) {
|
||||||
|
if(conn->connection == entry.connection) {
|
||||||
|
if(bus.getType() == Bus::REGULAR) {
|
||||||
|
if(entry.busInstance.value()->bus.getName() == conn->connection.getBus()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
auto *directInstance = dynamic_cast<DirectConnectionInstance*>(conn.get());
|
||||||
|
ComponentInstance* secondInstance;
|
||||||
|
if(directInstance->instance == instance) {
|
||||||
|
secondInstance = directInstance->secondInstance;
|
||||||
|
} else {
|
||||||
|
secondInstance = directInstance->instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
return entry.componentInstance == secondInstance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}),
|
||||||
|
entries.end()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return entries;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace domain
|
} // namespace domain
|
||||||
|
|
|
@ -3,14 +3,33 @@
|
||||||
|
|
||||||
#include "connection_instance.h"
|
#include "connection_instance.h"
|
||||||
#include "instance.h"
|
#include "instance.h"
|
||||||
|
#include "library.h"
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace domain {
|
namespace domain {
|
||||||
|
|
||||||
|
struct ConnectionEntry {
|
||||||
|
enum Type {
|
||||||
|
BUS,
|
||||||
|
COMPONENT
|
||||||
|
};
|
||||||
|
|
||||||
|
Type type;
|
||||||
|
|
||||||
|
std::optional<BusInstance*> busInstance;
|
||||||
|
std::optional<ComponentInstance*> componentInstance;
|
||||||
|
std::optional<Pin> pin;
|
||||||
|
|
||||||
|
Connection connection;
|
||||||
|
};
|
||||||
|
|
||||||
class Schema {
|
class Schema {
|
||||||
|
private:
|
||||||
|
Library library;
|
||||||
public:
|
public:
|
||||||
Schema() = default;
|
Schema(Library library): library(std::move(library)) {}
|
||||||
|
|
||||||
std::vector<shared_ptr<BusInstance>> busInstances;
|
std::vector<shared_ptr<BusInstance>> busInstances;
|
||||||
std::vector<shared_ptr<ComponentInstance>> componentInstances;
|
std::vector<shared_ptr<ComponentInstance>> componentInstances;
|
||||||
|
@ -21,6 +40,8 @@ namespace domain {
|
||||||
ComponentInstance *getComponentInstance(std::string &name);
|
ComponentInstance *getComponentInstance(std::string &name);
|
||||||
bool hasConnection(string &component, string &pin);
|
bool hasConnection(string &component, string &pin);
|
||||||
ConnectionInstance *getConnection(string &component, string &pin);
|
ConnectionInstance *getConnection(string &component, string &pin);
|
||||||
|
|
||||||
|
std::vector<ConnectionEntry> availableConnections(std::string instance, std::string pin, bool onlyConnectable);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace domain
|
} // namespace domain
|
||||||
|
|
|
@ -438,7 +438,9 @@ namespace domain {
|
||||||
} else if (attributes[0].getDefault().getType() != Value::STRING) {
|
} else if (attributes[0].getDefault().getType() != Value::STRING) {
|
||||||
errors.emplace_back(node.attributes[0].span, "@attribute must be of type string");
|
errors.emplace_back(node.attributes[0].span, "@attribute must be of type string");
|
||||||
} else {
|
} else {
|
||||||
attributes[0].getPopup()->setEnumeration(createWireEnumeration(firstWires));
|
domain::Popup popup = *attributes[0].getPopup();
|
||||||
|
popup.setEnumeration(createWireEnumeration(firstWires));
|
||||||
|
attributes[0].setPupup(popup);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!attributes[1].getPopup().has_value()) {
|
if (!attributes[1].getPopup().has_value()) {
|
||||||
|
@ -446,7 +448,9 @@ namespace domain {
|
||||||
} else if (attributes[1].getDefault().getType() != Value::STRING) {
|
} else if (attributes[1].getDefault().getType() != Value::STRING) {
|
||||||
errors.emplace_back(node.attributes[1].span, "@attribute must be of type string");
|
errors.emplace_back(node.attributes[1].span, "@attribute must be of type string");
|
||||||
} else {
|
} else {
|
||||||
attributes[1].getPopup()->setEnumeration(createWireEnumeration(secondWires));
|
domain::Popup popup = *attributes[1].getPopup();
|
||||||
|
popup.setEnumeration(createWireEnumeration(secondWires));
|
||||||
|
attributes[1].setPupup(popup);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -732,7 +736,7 @@ namespace domain {
|
||||||
|
|
||||||
std::optional<Popup> popup;
|
std::optional<Popup> popup;
|
||||||
if (node.popup) {
|
if (node.popup) {
|
||||||
popup = loadPopup(*node.popup, name, value.getType());
|
popup = loadPopup(*node.popup, name, toType(node.type));
|
||||||
}
|
}
|
||||||
|
|
||||||
pop();
|
pop();
|
||||||
|
@ -862,7 +866,7 @@ namespace domain {
|
||||||
|
|
||||||
|
|
||||||
Schema *SchemaCreator::loadSchema(SchemaNode node, Library &library) {
|
Schema *SchemaCreator::loadSchema(SchemaNode node, Library &library) {
|
||||||
auto *schema = new Schema();
|
auto *schema = new Schema(library);
|
||||||
|
|
||||||
for (auto &instance: node.instances) {
|
for (auto &instance: node.instances) {
|
||||||
if (library.hasComponent(instance.component.value)) {
|
if (library.hasComponent(instance.component.value)) {
|
||||||
|
@ -935,16 +939,26 @@ namespace domain {
|
||||||
auto attribute = connection->getAttribute(attr.name.value);
|
auto attribute = connection->getAttribute(attr.name.value);
|
||||||
auto value = toType(attr.value);
|
auto value = toType(attr.value);
|
||||||
|
|
||||||
|
bool valueFound = false;
|
||||||
|
|
||||||
|
// all connection attributes must be of type enumeration
|
||||||
for (auto &en: attribute.getPopup()->getEnumeration()) {
|
for (auto &en: attribute.getPopup()->getEnumeration()) {
|
||||||
if (en.getValue().asReference() == value.asReference()) {
|
if (en.getValue().equals(value)) {
|
||||||
value = Value::fromReference(value.asReference(), Value::WIRE_REFERENCE);
|
valueFound = true;
|
||||||
|
break;
|
||||||
|
} else if(value.isType(Value::UNDEFINED)) {
|
||||||
|
if(en.getValue().isType(Value::WIRE_REFERENCE) && en.getValue().asReference() == value.asReference()) {
|
||||||
|
value = Value::fromReference(value.asReference(), Value::WIRE_REFERENCE);
|
||||||
|
valueFound = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (value.isType(Value::UNDEFINED)) {
|
if (!valueFound) {
|
||||||
errors.emplace_back(attr.span, "invalid value");
|
errors.emplace_back(attr.span, "invalid value");
|
||||||
}
|
}
|
||||||
|
|
||||||
attributes.emplace_back(attribute.getName(), toType(attr.value), attribute);
|
attributes.emplace_back(attribute.getName(), value, attribute);
|
||||||
} else {
|
} else {
|
||||||
errors.emplace_back(attr.name.span, "unknown attribute");
|
errors.emplace_back(attr.name.span, "unknown attribute");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include "comdellexer.h"
|
#include "comdel_lexer.h"
|
||||||
#include "token.h"
|
#include "token.h"
|
||||||
#include "tokens_type.h"
|
#include "tokens_type.h"
|
||||||
|
|
|
@ -50,12 +50,11 @@ bool ComdelParser::consume(TokenType tokenType) {
|
||||||
do{}while(0)
|
do{}while(0)
|
||||||
|
|
||||||
void ComdelParser::bump() {
|
void ComdelParser::bump() {
|
||||||
if (tokens[position].type == TokenType::END_OF_FILE) {
|
if (tokens[position].type != TokenType::END_OF_FILE) {
|
||||||
ATLAS_ASSERT_FAIL("Internal parser error, called bump after EOF");
|
++position;
|
||||||
} else {
|
} else {
|
||||||
tokens[++position];
|
ATLAS_ASSERT_FAIL("Internal parser error, called bump after EOF");
|
||||||
}
|
}
|
||||||
|
|
||||||
expectedTokens.clear();
|
expectedTokens.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1348,7 +1347,7 @@ PResult<ValueNode> ComdelParser::parseConnectionWire() {
|
||||||
bump();
|
bump();
|
||||||
return spanner(ValueNode::ofNull());
|
return spanner(ValueNode::ofNull());
|
||||||
} else if (check(TokenType::STRING)) {
|
} else if (check(TokenType::STRING)) {
|
||||||
return spanner(ValueNode::ofString(parseString()->value));
|
return spanner(ValueNode::ofString(parseString()->asString()));
|
||||||
} else if (check(TokenType::IDENTIFIER)) {
|
} else if (check(TokenType::IDENTIFIER)) {
|
||||||
return spanner(ValueNode::ofIdentifier(parseIdentifier()->value));
|
return spanner(ValueNode::ofIdentifier(parseIdentifier()->value));
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include "comdellexer.h"
|
#include "comdel_lexer.h"
|
||||||
#include "comdel_parser.h"
|
#include "comdel_parser.h"
|
||||||
#include "parser_util.h"
|
#include "parser_util.h"
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
component System
|
component System
|
||||||
{
|
{
|
||||||
clock 100MHz;
|
clock 100MHz;
|
||||||
//bus
|
//glavnaSabirnica
|
||||||
wire<32> ADR;
|
wire<32> ADR;
|
||||||
wire<32> DATA;
|
wire<32> DATA;
|
||||||
wire READ;
|
wire READ;
|
||||||
|
@ -23,32 +23,31 @@ component System
|
||||||
wire --BACK;
|
wire --BACK;
|
||||||
|
|
||||||
|
|
||||||
|
//directRam
|
||||||
|
wire INT;
|
||||||
|
|
||||||
|
|
||||||
// components --------------------------------------------
|
// components --------------------------------------------
|
||||||
subcomponent Memorija mem<false, 1, 1024, 8, 1024>(ADR, DATA, READ, WRITE, SIZE, WAIT, 94534054858378, 0, null, null);
|
subcomponent Memorija memorija<false, 1, 65536, 8, 0>(ADR, DATA, READ, WRITE, SIZE, WAIT, *, *, *, INT);
|
||||||
subcomponent FRISC procesor_002(ADR, DATA, READ, WRITE, SIZE, WAIT, INT0, INT1, INT2, INT3, --IACK, 1, *, 94534054858378, 0, null, null);
|
subcomponent FRISC procesor(ADR, DATA, READ, WRITE, SIZE, WAIT, INT0, INT1, INT2, INT3, --IACK, 1, *, INT, *, *, *);
|
||||||
subcomponent FRISC procesor_001(ADR, DATA, READ, WRITE, SIZE, WAIT, INT0, INT1, INT2, INT3, --IACK, 1, *, 94534054858378, 0, null, null);
|
|
||||||
subcomponent FRISC procesor_000(ADR, DATA, READ, WRITE, SIZE, WAIT, INT0, INT1, INT2, INT3, --IACK, 1, *, 94534054858378, 0, null, null);
|
|
||||||
subcomponent FRISC procesor(ADR, DATA, READ, WRITE, SIZE, WAIT, INT0, INT1, INT2, INT3, --IACK, 1, *, 94534054858378, 0, null, null);
|
|
||||||
|
|
||||||
display {
|
display {
|
||||||
component { x: 0; y: 0; ref: "procesor_002"; }
|
component { x: -377; y: -302; ref: "procesor"; }
|
||||||
component { x: 0; y: 250; ref: "mem"; }
|
component { x: -56; y: -80; ref: "memorija"; }
|
||||||
component { x: -89; y: 74; ref: "procesor_001"; }
|
|
||||||
component { x: -175; y: 195; ref: "procesor_000"; }
|
|
||||||
component { x: -195; y: 63; ref: "procesor"; }
|
|
||||||
|
|
||||||
// bus bus
|
// glavnaSabirnica bus
|
||||||
|
|
||||||
rectangle {
|
rectangle {
|
||||||
x: 0; y: 200;
|
x: -377; y: -106;
|
||||||
w: 100; h: 20;
|
w: 100; h: 20;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
line {x1:50; y1:116; x2:50; y2:210;}
|
// directRam bus
|
||||||
line {x1:50; y1:234; x2:50; y2:210;}
|
|
||||||
line {x1:-39; y1:190; x2:50; y2:210;}
|
|
||||||
line {x1:-145; y1:179; x2:50; y2:210;}
|
line {x1:-6; y1:-96; x2:-326; y2:-95;}
|
||||||
line {x1:-125; y1:311; x2:50; y2:210;}
|
line {x1:-327; y1:-186; x2:-326; y2:-95;}
|
||||||
|
line {x1:-72; y1:-52; x2:-261; y2:-252;}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -8,13 +8,12 @@
|
||||||
@address pomocniAS(0xFFFF0000,0xFFFFFFFF)
|
@address pomocniAS(0xFFFF0000,0xFFFFFFFF)
|
||||||
|
|
||||||
@messages {
|
@messages {
|
||||||
Ok: "OK";
|
ok: "OK";
|
||||||
Yes: "Da";
|
yes: "Da";
|
||||||
No: "Ne";
|
no: "Ne";
|
||||||
Cancel: "Otkaži";
|
cancel: "Odustani";
|
||||||
noneBusLine: "nespojen";
|
noneBusLine: "nespojen";
|
||||||
noneValue: "nema vrijednosti";
|
noneValue: "nema vrijednosti";
|
||||||
generalPinNotConnected: "Opći pin nije spojen niti na jednu sabirnicu";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@component FRISC processor {
|
@component FRISC processor {
|
||||||
|
@ -73,6 +72,7 @@
|
||||||
orientation: "right";
|
orientation: "right";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@wires{null, null, null, null}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,6 +215,7 @@
|
||||||
orientation: "left";
|
orientation: "left";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@wires{null, null, null, null}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,7 +230,7 @@
|
||||||
@title "Početna adresa DMA-kontrolera"
|
@title "Početna adresa DMA-kontrolera"
|
||||||
@text "Zadajte početnu adresu DMA-kontrolera"
|
@text "Zadajte početnu adresu DMA-kontrolera"
|
||||||
@rule {
|
@rule {
|
||||||
if(contains_address(glavniAS, pocetnaAdresa)) {
|
if(!contains_address(glavniAS, pocetnaAdresa)) {
|
||||||
error("Početna adresa memorije je izvan 32 bitnog adresnog prostora")
|
error("Početna adresa memorije je izvan 32 bitnog adresnog prostora")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -239,7 +240,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@rule {
|
@rule {
|
||||||
if(unique(glavniAS, pocetnaAdresa, 32)) {
|
if(!unique(glavniAS, pocetnaAdresa, 32)) {
|
||||||
error("Adrese memorije nisu jedinstvene u adresnom prostoru (preklapaju se s nekom drugom komponentom)")
|
error("Adrese memorije nisu jedinstvene u adresnom prostoru (preklapaju se s nekom drugom komponentom)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -281,7 +282,7 @@
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
pin {
|
pin {
|
||||||
x: 100; y: 50; w: 16; h: 16;
|
x: 100; y: 30; w: 16; h: 16;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -291,7 +292,7 @@
|
||||||
@connection optional("COMDEL se ne može stvoriti. DMA nije spojen na nesto!")
|
@connection optional("COMDEL se ne može stvoriti. DMA nije spojen na nesto!")
|
||||||
@display {
|
@display {
|
||||||
pin {
|
pin {
|
||||||
x: 0; y: 0; w: 0; h: 0;
|
x: 100; y: 7; w: 16; h: 16;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@wires { 0, 0, null, null}
|
@wires { 0, 0, null, null}
|
||||||
|
@ -344,7 +345,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@bus directRam automatic {
|
@bus directRam singleAutomatic {
|
||||||
@instanceName directRam
|
@instanceName directRam
|
||||||
@wires {
|
@wires {
|
||||||
INT
|
INT
|
||||||
|
@ -375,12 +376,25 @@
|
||||||
@wires{ADR, DATA, READ, WRITE, SIZE, WAIT, interupt, BREQ, BACK}
|
@wires{ADR, DATA, READ, WRITE, SIZE, WAIT, interupt, BREQ, BACK}
|
||||||
}
|
}
|
||||||
|
|
||||||
@connection (DMA.glavniPin, PIOSabirnica, FRISC.glavniPin) {
|
@connection (DMA.dodatnaPoveznica, PIOSabirnica, FRISC.glavniPin) {
|
||||||
@wires{PIO_DATA, READY, STROBE}
|
@wires{PIO_DATA, READY, STROBE}
|
||||||
@wires{PIO_DATA, READY, STROBE}
|
@wires{PIO_DATA, READY, STROBE}
|
||||||
}
|
}
|
||||||
|
|
||||||
@connection (FRISC.memDirect, directRam, Memorija.memDirect) {
|
@connection (FRISC.memDirect, directRam, Memorija.memDirect) {
|
||||||
@wires{INT}
|
@attribute procConn string default "INT" {
|
||||||
@wires{INT}
|
@popup automatic {
|
||||||
|
@title "Frisc INT"
|
||||||
|
@text "Processor interupt 1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@attribute memConn string default "INT" {
|
||||||
|
@popup automatic {
|
||||||
|
@title "Mem INT"
|
||||||
|
@text "Memory interupt 1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@wires{"INT", null, 1, "INT2"}
|
||||||
|
@wires{"INT", null, 1, "INT2"}
|
||||||
}
|
}
|
|
@ -1,42 +1,14 @@
|
||||||
@source "frisc_library.csl"
|
@source "/home/bbr/Documents/Personal/FER/schema_editor/examples/simplified FRISC model/frisc_library.csl"
|
||||||
|
|
||||||
@schema {
|
@schema {
|
||||||
@instance procesor_002 FRISC {
|
@instance procesor FRISC {
|
||||||
@position (0, 0)
|
@position (-177, -122)
|
||||||
@attribute _memory null
|
@attribute _memory memorija2
|
||||||
}
|
|
||||||
|
|
||||||
@instance mem Memorija {
|
|
||||||
@position (0, 250)
|
|
||||||
@attribute sinkroniziran false
|
|
||||||
@attribute brzina 1
|
|
||||||
@attribute kapacitet 1024
|
|
||||||
@attribute size 8
|
|
||||||
@attribute pocetnaAdresa 1024
|
|
||||||
}
|
|
||||||
|
|
||||||
@instance procesor_001 FRISC {
|
|
||||||
@position (-89, 74)
|
|
||||||
@attribute _memory null
|
|
||||||
}
|
|
||||||
|
|
||||||
@instance procesor_000 FRISC {
|
|
||||||
@position (-175, 195)
|
|
||||||
@attribute _memory null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@instance procesor FRISC {
|
@instance procesor FRISC {
|
||||||
@position (-195, 63)
|
@position (49, -97)
|
||||||
@attribute _memory null
|
@attribute _memory null
|
||||||
}
|
}
|
||||||
|
|
||||||
@instance bus glavnaSabirnica {
|
|
||||||
@position (0, 200)
|
|
||||||
@size 100
|
|
||||||
}
|
|
||||||
|
|
||||||
@connection (procesor_002.glavniPin, bus) {
|
|
||||||
}
|
|
||||||
@connection (mem.glavniPin, bus) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,33 +2,28 @@
|
||||||
|
|
||||||
@schema {
|
@schema {
|
||||||
@instance procesor FRISC {
|
@instance procesor FRISC {
|
||||||
@position (-76, -97)
|
@position (-464, -314)
|
||||||
@attribute _memory memorija
|
@attribute _memory null
|
||||||
}
|
}
|
||||||
|
|
||||||
@instance memorija Memorija {
|
@instance dma DMA {
|
||||||
@position (52, 119)
|
@position (-269, 46)
|
||||||
@attribute sinkroniziran false
|
|
||||||
@attribute brzina 1
|
|
||||||
@attribute kapacitet 65536
|
|
||||||
@attribute size 8
|
|
||||||
@attribute pocetnaAdresa 0
|
@attribute pocetnaAdresa 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@instance glavnaSabirnica glavnaSabirnica {
|
@instance glavnaSabirnica glavnaSabirnica {
|
||||||
@position (-78, 88)
|
@position (-579, -160)
|
||||||
@size 100
|
@size 100
|
||||||
}
|
}
|
||||||
|
|
||||||
@instance directRam directRam {
|
@instance PIOSabirnica PIOSabirnica {
|
||||||
@position (0, 0)
|
@position (0, 0)
|
||||||
@size 0
|
@size 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@connection (memorija.glavniPin, glavnaSabirnica) {
|
@connection (dma.glavniPin, glavnaSabirnica) {
|
||||||
|
@attribute interupt INT2
|
||||||
}
|
}
|
||||||
@connection (procesor.glavniPin, glavnaSabirnica) {
|
@connection (dma.glavniPin, PIOSabirnica, procesor.glavniPin) {
|
||||||
}
|
|
||||||
@connection (memorija.memDirect, directRam, procesor.memDirect) {
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
@source "/home/bbr/Documents/Personal/FER/schema_editor/examples/simplified FRISC model/frisc_library.csl"
|
||||||
|
|
||||||
|
@schema {
|
||||||
|
@instance procesor FRISC {
|
||||||
|
@position (-543, -304)
|
||||||
|
@attribute _memory null
|
||||||
|
}
|
||||||
|
|
||||||
|
@instance glavnaSabirnica glavnaSabirnica {
|
||||||
|
@position (-544, -91)
|
||||||
|
@size 100
|
||||||
|
}
|
||||||
|
|
||||||
|
@connection (procesor.glavniPin, glavnaSabirnica) {
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
@source "/home/bbr/Documents/Personal/FER/schema_editor/examples/simplified FRISC model/frisc_library.csl"
|
||||||
|
|
||||||
|
@schema {
|
||||||
|
@instance procesor FRISC {
|
||||||
|
@position (-104, -102)
|
||||||
|
@attribute _memory null
|
||||||
|
}
|
||||||
|
|
||||||
|
@instance memorija Memorija {
|
||||||
|
@position (39, 199)
|
||||||
|
@attribute sinkroniziran false
|
||||||
|
@attribute brzina 1
|
||||||
|
@attribute kapacitet 1024
|
||||||
|
@attribute size 8
|
||||||
|
@attribute pocetnaAdresa 0
|
||||||
|
}
|
||||||
|
|
||||||
|
@instance dma DMA {
|
||||||
|
@position (-352, 13)
|
||||||
|
@attribute pocetnaAdresa 1024
|
||||||
|
}
|
||||||
|
|
||||||
|
@instance glavnaSabirnica glavnaSabirnica {
|
||||||
|
@position (-106, 80)
|
||||||
|
@size 100
|
||||||
|
}
|
||||||
|
|
||||||
|
@instance PIOSabirnica PIOSabirnica {
|
||||||
|
@position (0, 0)
|
||||||
|
@size -1
|
||||||
|
}
|
||||||
|
|
||||||
|
@instance directRam directRam {
|
||||||
|
@position (0, 0)
|
||||||
|
@size -1
|
||||||
|
}
|
||||||
|
|
||||||
|
@connection (procesor.glavniPin, glavnaSabirnica) {
|
||||||
|
}
|
||||||
|
@connection (memorija.glavniPin, glavnaSabirnica) {
|
||||||
|
}
|
||||||
|
@connection (dma.glavniPin, glavnaSabirnica) {
|
||||||
|
@attribute interupt INT0
|
||||||
|
}
|
||||||
|
@connection (memorija.memDirect, directRam, procesor.memDirect) {
|
||||||
|
@attribute procConn "INT"
|
||||||
|
@attribute memConn "INT"
|
||||||
|
}
|
||||||
|
}
|
|
@ -32,11 +32,13 @@ void MainWindow::setupUi()
|
||||||
ui->centralwidget->setLayout(layout);
|
ui->centralwidget->setLayout(layout);
|
||||||
|
|
||||||
// setup toolbar
|
// setup toolbar
|
||||||
ui->toolBar->addAction("Load library", this, &MainWindow::onLoadLibrary);
|
ui->toolBar->addAction("Učitaj bibiloteku", this, &MainWindow::onLoadLibrary);
|
||||||
ui->toolBar->addAction("Load schema", this, &MainWindow::onLoadSchema);
|
ui->toolBar->addAction("Učitaj shemu", this, &MainWindow::onLoadSchema);
|
||||||
ui->toolBar->addAction("Save schema", this, &MainWindow::onStoreScheme);
|
ui->toolBar->addAction("Spremi shemu", this, &MainWindow::onStoreScheme);
|
||||||
ui->toolBar->addAction("Generate system", this, &MainWindow::onGenerateComdel);
|
ui->toolBar->addAction("Generiraj comdel", this, &MainWindow::onGenerateComdel);
|
||||||
|
|
||||||
|
connect(ui->actionSave_schema, &QAction::triggered, this, &MainWindow::onStoreScheme);
|
||||||
|
connect(ui->actionExport_schema, &QAction::triggered, this, &MainWindow::onGenerateComdel);
|
||||||
connect(ui->actionValidate, &QAction::triggered, this, &MainWindow::onValidateSchema);
|
connect(ui->actionValidate, &QAction::triggered, this, &MainWindow::onValidateSchema);
|
||||||
|
|
||||||
// setup central content
|
// setup central content
|
||||||
|
@ -47,10 +49,10 @@ void MainWindow::setupUi()
|
||||||
schemaParent->setLayout(schemaLayout);
|
schemaParent->setLayout(schemaLayout);
|
||||||
|
|
||||||
schemaDisplay = new display::Schema();
|
schemaDisplay = new display::Schema();
|
||||||
schemaLayout->setMargin(0);
|
schemaLayout->setContentsMargins(0, 0, 0, 0);
|
||||||
schemaLayout->addWidget(schemaDisplay, 1);
|
schemaLayout->addWidget(schemaDisplay, 1);
|
||||||
|
|
||||||
layout->setMargin(0);
|
layout->setContentsMargins(0, 0, 0, 0);
|
||||||
layout->addWidget(libraryDisplay);
|
layout->addWidget(libraryDisplay);
|
||||||
layout->addWidget(schemaParent, 1);
|
layout->addWidget(schemaParent, 1);
|
||||||
|
|
||||||
|
@ -62,10 +64,10 @@ void MainWindow::setupUi()
|
||||||
|
|
||||||
void MainWindow::onLoadLibrary() {
|
void MainWindow::onLoadLibrary() {
|
||||||
auto filename = QFileDialog::getOpenFileName(this,
|
auto filename = QFileDialog::getOpenFileName(this,
|
||||||
tr("Open library"), "/home", tr("Comdel library (*.csl)"));
|
tr("Otvori biblioteku"), "", tr("Comdel biblioteka (*.csl)"));
|
||||||
if(!filename.isEmpty()) {
|
if(!filename.isEmpty()) {
|
||||||
std::ostringstream output;
|
std::ostringstream output;
|
||||||
clear();
|
log->clear();
|
||||||
|
|
||||||
auto librarySource = filename.toStdString();
|
auto librarySource = filename.toStdString();
|
||||||
|
|
||||||
|
@ -74,33 +76,35 @@ void MainWindow::onLoadLibrary() {
|
||||||
log->appendPlainText(QString::fromStdString(output.str()));
|
log->appendPlainText(QString::fromStdString(output.str()));
|
||||||
}
|
}
|
||||||
|
|
||||||
libraryDisplay->setLibrary(instance->getLibrary());
|
libraryDisplay->refreshContent();
|
||||||
schemaDisplay->setSchema(instance->getSchema(), instance->getLibrary());
|
schemaDisplay->refreshContent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::onLoadSchema() {
|
void MainWindow::onLoadSchema() {
|
||||||
auto filename = QFileDialog::getOpenFileName(this,
|
auto filename = QFileDialog::getOpenFileName(this,
|
||||||
tr("Open schema"), "/home", tr("Comdel schema (*.csl)"));
|
tr("Otvori shemu"), "", tr("Comdel shema (*.csl)"));
|
||||||
if(!filename.isEmpty()) {
|
if(!filename.isEmpty()) {
|
||||||
std::ostringstream output;
|
std::ostringstream output;
|
||||||
clear();
|
log->clear();
|
||||||
|
|
||||||
auto schemaSource = filename.toStdString();
|
auto schemaSource = filename.toStdString();
|
||||||
|
|
||||||
auto instance = Application::instance();
|
auto instance = Application::instance();
|
||||||
if(!instance->loadSchema(schemaSource, output)) {
|
auto result = instance->loadSchema(schemaSource, output);
|
||||||
|
if(!result.first){
|
||||||
|
formatErrors(result.second, output);
|
||||||
log->appendPlainText(QString::fromStdString(output.str()));
|
log->appendPlainText(QString::fromStdString(output.str()));
|
||||||
}
|
}
|
||||||
|
|
||||||
libraryDisplay->setLibrary(instance->getLibrary());
|
libraryDisplay->refreshContent();
|
||||||
schemaDisplay->setSchema(instance->getSchema(), instance->getLibrary());
|
schemaDisplay->refreshContent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::onStoreScheme() {
|
void MainWindow::onStoreScheme() {
|
||||||
auto filename = QFileDialog::getSaveFileName(this,
|
auto filename = QFileDialog::getSaveFileName(this,
|
||||||
tr("Save schema"), "/home", tr("Comdel schema (*.csl)"));
|
tr("Spremi shemu"), "", tr("Comdel shema (*.csl)"));
|
||||||
if(!filename.isEmpty()) {
|
if(!filename.isEmpty()) {
|
||||||
log->clear();
|
log->clear();
|
||||||
|
|
||||||
|
@ -111,9 +115,9 @@ void MainWindow::onStoreScheme() {
|
||||||
out<<output.str();
|
out<<output.str();
|
||||||
out.close();
|
out.close();
|
||||||
|
|
||||||
log->appendPlainText("Successfully stored schema\n");
|
log->appendPlainText("Uspješno spremljena shema\n");
|
||||||
} else {
|
} else {
|
||||||
log->appendPlainText("Failed storing schema\n");
|
log->appendPlainText("Greška tijekom spremanja sheme\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,7 +125,7 @@ void MainWindow::onStoreScheme() {
|
||||||
|
|
||||||
void MainWindow::onGenerateComdel() {
|
void MainWindow::onGenerateComdel() {
|
||||||
auto filename = QFileDialog::getSaveFileName(this,
|
auto filename = QFileDialog::getSaveFileName(this,
|
||||||
tr("Save schema"), "/home", tr("Comdel system (*.system)"));
|
tr("Spremi shemu"), "", tr("Comdel sustav (*.system)"));
|
||||||
if(!filename.isEmpty()) {
|
if(!filename.isEmpty()) {
|
||||||
log->clear();
|
log->clear();
|
||||||
|
|
||||||
|
@ -133,14 +137,14 @@ void MainWindow::onGenerateComdel() {
|
||||||
formatErrors(validationErrors, buff);
|
formatErrors(validationErrors, buff);
|
||||||
log->appendPlainText(QString::fromStdString(buff.str()));
|
log->appendPlainText(QString::fromStdString(buff.str()));
|
||||||
|
|
||||||
if(Application::hasErrors(validationErrors)) {
|
if(!Application::hasErrors(validationErrors)) {
|
||||||
std::ofstream out(filename.toStdString(), std::ios::out | std::ios::binary);
|
std::ofstream out(filename.toStdString(), std::ios::out | std::ios::binary);
|
||||||
out<<output.str();
|
out<<output.str();
|
||||||
out.close();
|
out.close();
|
||||||
|
|
||||||
log->appendPlainText("Successfully generated comdel\n");
|
log->appendPlainText("Uspješno generiranje comdel modela\n");
|
||||||
} else {
|
} else {
|
||||||
log->appendPlainText("Failed generating comdel\n");
|
log->appendPlainText("Neuspješno generiranje comdel modela\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -176,13 +180,7 @@ void MainWindow::formatErrors(std::vector<domain::ValidationError>& errors, std:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::clear() {
|
|
||||||
log->clear();
|
|
||||||
this->schemaDisplay->setSchema(nullptr, std::nullopt);
|
|
||||||
this->libraryDisplay->setLibrary(std::nullopt);
|
|
||||||
}
|
|
||||||
|
|
||||||
MainWindow::~MainWindow()
|
MainWindow::~MainWindow()
|
||||||
{
|
{
|
||||||
delete ui;
|
delete ui;
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,17 +53,17 @@
|
||||||
</widget>
|
</widget>
|
||||||
<action name="actionSave_schema">
|
<action name="actionSave_schema">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Save schema</string>
|
<string>Spremi shemu</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="actionExport_schema">
|
<action name="actionExport_schema">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Export schema</string>
|
<string>Generiraj comdel</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="actionValidate">
|
<action name="actionValidate">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Validate</string>
|
<string>Validairaj</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
|
|
Loading…
Reference in New Issue