Compare commits

..

No commits in common. "f66fc1db26af4bcc670a27011245090efc7e1686" and "f93a2afa639e1aa196b79fb9048ab55035c98cff" have entirely different histories.

41 changed files with 381 additions and 933 deletions

View File

@ -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/comdel_lexer.cpp comdel/parser/comdellexer.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/display/single_automatic_dialog.cpp comdel/display/single_automatic_dialog.h) comdel/domain/comdel_validator.cpp comdel/domain/comdel_validator.h comdel/display/attribute_dialog.cpp comdel/display/attribute_dialog.h comdel/display/name_dialog.cpp comdel/display/name_dialog.h comdel/domain/comdel_generator.cpp comdel/domain/comdel_generator.h comdel/display/library_list.cpp comdel/display/library_list.h application.cpp application.h)
target_link_libraries(SchemeEditor Qt5::Core Qt5::Gui Qt5::Widgets) target_link_libraries(SchemeEditor Qt5::Core Qt5::Gui Qt5::Widgets)

View File

@ -9,80 +9,77 @@ 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/display/single_automatic_dialog.cpp \ comdel/domain/addressspace.cpp \
comdel/domain/address_space.cpp \
comdel/domain/attribute.cpp \ comdel/domain/attribute.cpp \
comdel/domain/bus.cpp \ comdel/domain/bus.cpp \
comdel/domain/comdel_generator.cpp \ comdel/domain/schemacreator.cpp \
comdel/domain/comdel_validator.cpp \
comdel/domain/component.cpp \ comdel/domain/component.cpp \
comdel/domain/connection.cpp \ comdel/domain/connection.cpp \
comdel/domain/connection_instance.cpp \ comdel/domain/comdelvalidator.cpp \
comdel/domain/connectioninstance.cpp \
comdel/domain/display.cpp \ comdel/domain/display.cpp \
comdel/domain/function_signature.cpp \ comdel/domain/functionsignature.cpp \
comdel/domain/instance.cpp \ comdel/domain/instance.cpp \
comdel/domain/instance_attribute.cpp \ comdel/domain/instanceattribute.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/parser/ast_nodes.cpp \ comdel/domain/wireinstance.cpp \
comdel/parser/comdel_lexer.cpp \ comdel/parser/astnode.cpp \
comdel/parser/comdel_parser.cpp \ comdel/parser/comdellexer.cpp \
comdel/parser/parse_context.cpp \ comdel/parser/comdelparser.cpp \
comdel/parser/parser_util.cpp \ comdel/parser/parsecontext.cpp \
comdel/parser/source_error.cpp \ comdel/parser/parserutil.cpp \
comdel/parser/sourceerror.cpp \
comdel/parser/token.cpp \ comdel/parser/token.cpp \
comdel/parser/tokens_type.cpp \ comdel/parser/tokenstype.cpp \
application.cpp \ comdel/display/dialogmanager.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/display/single_automatic_dialog.h \ comdel/domain/addressspace.h \
comdel/domain/address_space.h \
comdel/domain/attribute.h \ comdel/domain/attribute.h \
comdel/domain/bus.h \ comdel/domain/bus.h \
comdel/domain/comdel_generator.h \ comdel/domain/schemacreator.h \
comdel/domain/comdel_validator.h \
comdel/domain/component.h \ comdel/domain/component.h \
comdel/domain/connection.h \ comdel/domain/connection.h \
comdel/domain/connection_instance.h \ comdel/domain/comdelvalidator.h \
comdel/domain/connectioninstance.h \
comdel/domain/display.h \ comdel/domain/display.h \
comdel/domain/function_signature.h \ comdel/domain/functionsignature.h \
comdel/domain/instance.h \ comdel/domain/instance.h \
comdel/domain/instance_attribute.h \ comdel/domain/instanceattribute.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/parser/ast_nodes.h \ comdel/domain/wireinstance.h \
comdel/parser/comdel_lexer.h \ comdel/parser/astnode.h \
comdel/parser/comdel_parser.h \ comdel/parser/comdellexer.h \
comdel/parser/comdelparser.h \
comdel/parser/expected.h \ comdel/parser/expected.h \
comdel/parser/parse_context.h \ comdel/parser/parsecontext.h \
comdel/parser/parser_util.h \ comdel/parser/parserutil.h \
comdel/parser/poly.h \ comdel/parser/poly.h \
comdel/parser/presult.h \ comdel/parser/presult.h \
comdel/parser/source_error.h \ comdel/parser/sourceerror.h \
comdel/parser/token.h \ comdel/parser/token.h \
comdel/parser/tokens_type.h \ comdel/parser/tokenstype.h \
comdel/display/dialogmanager.h \
comdel/display/attribute_dialog.h \
comdel/display/name_dialog.h \
mainwindow.h mainwindow.h
FORMS += \ FORMS += \

View File

@ -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,97 +26,76 @@ 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(library.value()); schema = new domain::Schema();
} 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;
} }
std::pair<bool, std::vector<domain::ValidationError>> Application::loadSchema(std::string &filename, std::ostream &errorOutput) { bool 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, errors}; return false;
} }
} else { } else {
clear(); clear();
return {false, errors}; return false;
} }
} else { } else {
errorOutput << "Failed parsing library" << std::endl; errorOutput<<"Failed parsing library"<<std::endl;
return {false, errors}; return false;
} }
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);
@ -124,7 +103,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")};
} }
@ -135,20 +114,17 @@ 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 memoryReferenceValidation = validator.validateMemoryReferences(*schema, *library, context); auto countValidation = validator.validateInstanceCount(*schema, *library, context);
errors.insert(errors.end(), memoryReferenceValidation.begin(), memoryReferenceValidation.end()); errors.insert(errors.end(), countValidation.begin(), countValidation.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;
@ -157,7 +133,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);
} }
@ -165,8 +141,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;
} }
} }
@ -177,29 +153,26 @@ 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> std::shared_ptr<domain::ComponentInstance> Application::addComponent(domain::Component component, std::vector<domain::InstanceAttribute> attributes, int x, int y) {
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( schema->componentInstances.push_back(std::make_shared<domain::ComponentInstance>(name, attributes, std::make_pair(x, y), component));
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());
@ -209,162 +182,18 @@ 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;
}
}

View File

@ -21,9 +21,6 @@ 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();
@ -31,7 +28,7 @@ public:
void clear(); void clear();
bool loadLibrary(std::string& filename, std::ostream& errorOutput); bool loadLibrary(std::string& filename, std::ostream& errorOutput);
std::pair<bool, std::vector<domain::ValidationError>> loadSchema(std::string& filename, std::ostream& errorOutput); bool loadSchema(std::string& filename, std::ostream& errorOutput);
static Application* instance(); static Application* instance();
@ -40,18 +37,11 @@ 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);
}; };

View File

@ -59,16 +59,14 @@ namespace display {
} }
AttributeDialog::AttributeDialog(domain::InstanceAttribute *attribute, bool updating) { AttributeDialog::AttributeDialog(domain::InstanceAttribute *attribute) {
setAttribute(Qt::WA_DeleteOnClose); setAttribute(Qt::WA_DeleteOnClose);
attributeValue = attribute; attributeValue = attribute;
auto actionType = updating ? "Izmjeni " : "Postavi "; this->setWindowTitle(QString::fromStdString("Izmjeni " + attribute->attribute.getName()));
this->setWindowTitle(QString::fromStdString(actionType + attribute->attribute.getName()));
auto layout = new QVBoxLayout(this); auto layout = new QVBoxLayout(this);
this->setLayout(layout); this->setLayout(layout);
@ -122,11 +120,11 @@ namespace display {
auto *radioLayout = new QHBoxLayout(group); auto *radioLayout = new QHBoxLayout(group);
group->setLayout(radioLayout); group->setLayout(radioLayout);
auto isTrue = new QRadioButton("da", group); auto isTrue = new QRadioButton("true", 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("ne", group); auto isFalse = new QRadioButton("false", group);
connect(isFalse, &QRadioButton::clicked, [this]() { connect(isFalse, &QRadioButton::clicked, [this]() {
this->value = domain::Value::fromBool(false); this->value = domain::Value::fromBool(false);
}); });
@ -142,7 +140,7 @@ namespace display {
layout->addWidget(group); layout->addWidget(group);
} }
auto button = new QPushButton(updating ? "Ažuriraj" : "Postavi"); auto button = new QPushButton("Ažuriraj");
connect(button, &QPushButton::clicked, this, &AttributeDialog::onUpdate); connect(button, &QPushButton::clicked, this, &AttributeDialog::onUpdate);
layout->addWidget(button); layout->addWidget(button);
@ -172,16 +170,14 @@ namespace display {
} }
MemoryDialog::MemoryDialog(domain::InstanceAttribute *attribute, MemoryDialog::MemoryDialog(domain::InstanceAttribute *attribute,
std::vector<std::shared_ptr<domain::ComponentInstance>> instances, bool updating) { std::vector<std::shared_ptr<domain::ComponentInstance>> instances) {
memoryInstances = std::vector<std::string>(); memoryInstances = std::vector<std::string>();
setAttribute(Qt::WA_DeleteOnClose); setAttribute(Qt::WA_DeleteOnClose);
attributeValue = attribute; attributeValue = attribute;
auto actionType = updating ? "Izmjeni memoriju" : "Postavi memoriju"; this->setWindowTitle(QString::fromStdString("Izmjeni " + attribute->attribute.getName()));
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) {
@ -216,7 +212,7 @@ namespace display {
} }
} }
auto button = new QPushButton(updating ? "Ažuriraj" : "Postavi"); auto button = new QPushButton("Ažuriraj");
connect(button, &QPushButton::clicked, this, &MemoryDialog::onUpdate); connect(button, &QPushButton::clicked, this, &MemoryDialog::onUpdate);
layout->addWidget(button); layout->addWidget(button);

View File

@ -42,7 +42,7 @@ namespace display {
domain::InstanceAttribute *attributeValue; domain::InstanceAttribute *attributeValue;
public: public:
AttributeDialog(domain::InstanceAttribute *attribute, bool updating = true); AttributeDialog(domain::InstanceAttribute *attribute);
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, bool updating = true); std::vector<std::shared_ptr<domain::ComponentInstance>> instances);
public slots: public slots:

View File

@ -3,19 +3,14 @@
#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]() {
@ -23,41 +18,28 @@ 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();
if(attr->value.getType() == domain::Value::MEMORY_REFERENCE) { auto action = menu.addAction(QString::fromStdString("Izmjeni " + attr->name),
menu.addAction("Izmjeni memoriju", [attr]() { [attr]() {
auto dialog = new MemoryDialog(attr, if (attr->value.getType() == domain::Value::MEMORY_REFERENCE) {
Application::instance()->getSchema()->componentInstances); auto dialog = new MemoryDialog(attr,
dialog->exec(); Application::instance()->getSchema()->componentInstances);
}); dialog->exec();
} else { } else {
auto action = menu.addAction(QString::fromStdString("Izmjeni '" + attr->name + "'"), auto dialog = new AttributeDialog(attr);
[attr]() { dialog->exec();
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());
} }
@ -68,7 +50,7 @@ namespace display {
void Pin::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { void Pin::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) {
QMenu menu; QMenu menu;
menu.addAction("Poveži pin", [&]() {}); menu.addAction("Connect pin", [&]() {});
menu.exec(event->screenPos()); menu.exec(event->screenPos());
} }
@ -81,8 +63,6 @@ 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);
@ -123,19 +103,9 @@ 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());
} }
@ -233,8 +203,7 @@ 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);
} }
@ -259,36 +228,23 @@ 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();
if(connection->bus->bus.getType() == domain::Bus::SINGLE_AUTOMATIC) { auto action = menu.addAction(QString::fromStdString("Izmjeni " + attr->name),
auto &attributes = this->connection->attributes; [attr]() {
menu.addAction(QString::fromStdString("Izmjeni poveznicu"), auto dialog = new AttributeDialog(attr);
[&attributes]() { dialog->exec();
auto dialog = new display::SingleAutomaticDialog(attributes); });
dialog->exec(); action->setEnabled(enabled);
});
} 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);
} }

View File

@ -3,7 +3,6 @@
#include <QLabel> #include <QLabel>
#include <QListWidget> #include <QListWidget>
#include <QVBoxLayout> #include <QVBoxLayout>
#include <application.h>
namespace display { namespace display {
@ -14,16 +13,17 @@ namespace display {
componentList = new LibraryList(this); componentList = new LibraryList(this);
busList = new LibraryList(this); busList = new LibraryList(this);
layout->setContentsMargins(4, 4, 4, 4); layout->setMargin(4);
layout->addWidget(new QLabel("Komponente:")); layout->addWidget(new QLabel("Components:"));
layout->addWidget(componentList, 1); layout->addWidget(componentList, 1);
layout->addSpacing(8); layout->addSpacing(8);
layout->addWidget(new QLabel("Sabirnice:")); layout->addWidget(new QLabel("Buses:"));
layout->addWidget(busList, 1); layout->addWidget(busList, 1);
setLibrary(library);
} }
void Library::refreshContent() { void Library::setLibrary(std::optional<domain::Library> library) {
library = Application::instance()->getLibrary();
componentList->clear(); componentList->clear();
busList->clear(); busList->clear();

View File

@ -13,7 +13,7 @@ namespace display {
public: public:
Library(); Library();
void refreshContent(); void setLibrary(std::optional<domain::Library> library);
private: private:
std::optional<domain::Library> library; std::optional<domain::Library> library;

View File

@ -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

View File

@ -5,21 +5,38 @@
#include <set> #include <set>
#include "name_dialog.h" #include "name_dialog.h"
display::NameDialog::NameDialog(std::string currentName, std::set<std::string> &names): currentName(currentName) { display::NameDialog::NameDialog(domain::ComponentInstance *instance, std::set<std::string>& names) : componentInstance(instance), usedNames(names) {
usedNames.erase(currentName); usedNames.erase(instance->name);
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(currentName.c_str()); edit->insert(instance->name.c_str());
connect(edit, &QLineEdit::textChanged, this, &NameDialog::onNameUpdate); connect(edit, &QLineEdit::textChanged, this, &NameDialog::onNameUpdate);
layout->addWidget(edit); layout->addWidget(edit);
setWindowTitle("Izmjeni ime"); this->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);
setLayout(layout); this->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) {
@ -31,10 +48,12 @@ void display::NameDialog::onNameUpdate(const QString &text) {
} }
void display::NameDialog::onNameChange() { void display::NameDialog::onNameChange() {
currentName = edit->text().toStdString();
close();
}
std::string display::NameDialog::getName() {
return currentName; if (componentInstance != nullptr) {
componentInstance->name = this->edit->text().toStdString();
} else if (busInstance != nullptr) {
busInstance->name = this->edit->text().toStdString();
}
this->close();
} }

View File

@ -17,13 +17,15 @@ namespace display {
std::set<std::string> usedNames; std::set<std::string> usedNames;
QLineEdit *edit = nullptr; QLineEdit *edit = nullptr;
std::string currentName; domain::ComponentInstance *componentInstance = nullptr;
domain::BusInstance *busInstance = nullptr;
QPushButton *button; QPushButton *button;
public: public:
NameDialog(std::string currentName, std::set<std::string>& names);
std::string getName(); NameDialog(domain::ComponentInstance *instance, std::set<std::string>& names);
NameDialog(domain::BusInstance *instance, std::set<std::string>& names);
public slots: public slots:
void onNameUpdate(const QString& text); void onNameUpdate(const QString& text);

View File

@ -2,7 +2,6 @@
#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>
@ -11,6 +10,8 @@
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);
@ -18,17 +19,14 @@ namespace display {
} }
void Schema::refreshContent() { void Schema::setSchema(domain::Schema *_schema, std::optional<domain::Library> _library) {
schema = Application::instance()->getSchema();
library = Application::instance()->getLibrary();
components.clear(); components.clear();
buses.clear(); buses.clear();
scene.clear();
pins.clear();
busConnections.clear();
directConnections.clear();
scene.clear();
busConnections.clear();
this->schema = _schema;
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);
@ -88,9 +86,27 @@ 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 = populateAttributes(component.getAttributes()); auto attributes = std::vector<domain::InstanceAttribute>();
if(attributes.size() != component.getAttributes().size()) { for (auto attr: component.getAttributes()) {
return; domain::InstanceAttribute attribute(attr.getName(), attr.getDefault(), attr);
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();
@ -132,26 +148,18 @@ namespace display {
auto instance = context.pin->getComponentInstance(); auto instance = context.pin->getComponentInstance();
auto &pin = context.pin->getPin(); auto &pin = context.pin->getPin();
auto availableConnections = schema->availableConnections(instance->name, pin.getName(), true); auto busInstances = getAvailableConnectionBusses(instance, pin);
for(auto &connection: availableConnections) { for (auto &bus: busInstances) {
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()) {
auto attributes = populateAttributes(con->getAttributes()); std::vector<domain::InstanceAttribute> attributes;
if(attributes.size() != con->getAttributes().size()) { for (auto attr: con->getAttributes()) {
clearSelectable(); attributes.emplace_back(attr.getName(), attr.getDefault(), attr);
return;
} }
auto conInstance = std::make_shared<domain::BusConnectionInstance>(instance, attributes, bus, *con); auto conInstance = std::make_shared<domain::BusConnectionInstance>(instance, attributes, bus, *con);
@ -168,11 +176,9 @@ namespace display {
} }
} }
for (auto &connection: availableConnections) { auto pinInstances = getAvailableConnectionPins(instance, pin);
if(connection.type != domain::ConnectionEntry::COMPONENT) {
continue; for (auto &pinInstance: pinInstances) {
}
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());
@ -182,17 +188,13 @@ 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 busInstance = Application::instance()->addBus(library->getBus(con->getBus()), 0, 0); auto bus = library->getBus(con->getBus());
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;
if(library->getBus(con->getBus()).getType() == domain::Bus::SINGLE_AUTOMATIC) { for (auto attr: con->getAttributes()) {
attributes = populateSingleAutomaticConnection(*con); attributes.emplace_back(attr.getName(), attr.getDefault(), attr);
} 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,
@ -213,25 +215,28 @@ namespace display {
} }
} }
clearSelectable(); updateConnections();
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 availableConnections = schema->availableConnections(domainPin->getComponentInstance()->name, pin.getName(), true); auto busInstances = getAvailableConnectionBusses(domainPin->getComponentInstance(), domainPin->getPin());
for(auto &connection: availableConnections) { for (auto bus: busInstances) {
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->setBrush(selectedBrush); rect->setPen(selectedPen);
rect->setPos(group->scenePos()); rect->setPos(group->scenePos());
auto _rect = rect->rect(); auto _rect = rect->rect();
@ -243,14 +248,12 @@ namespace display {
scene.addItem(rect); scene.addItem(rect);
} }
for (auto &connection: availableConnections) { std::vector<domain::ConnectionComponent> pinInstances = getAvailableConnectionPins(
if(connection.type != domain::ConnectionEntry::COMPONENT) { domainPin->getComponentInstance(), domainPin->getPin());
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());
@ -265,56 +268,29 @@ namespace display {
} }
std::vector<domain::InstanceAttribute> Schema::populateAttributes(std::vector<domain::Attribute>& attributes) { std::vector<domain::BusInstance *>
std::vector<domain::InstanceAttribute> instanceAttributes; Schema::getAvailableConnectionBusses(domain::ComponentInstance *instance, domain::Pin &pin) {
std::vector<domain::BusInstance *> instances;
for (auto attr: attributes) { for (const auto &bus: schema->busInstances) {
domain::InstanceAttribute attribute(attr.getName(), attr.getDefault(), attr); if (library->hasConnection(domain::ConnectionComponent{instance->component.getName(), pin.getName()},
if(attr.getPopup().has_value() && attr.getPopup()->getType() == domain::Popup::AUTOMATIC) { bus->bus.getName())) {
if(attr.getDefault().isType(domain::Value::MEMORY_REFERENCE)) { instances.push_back(bus.get());
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 instanceAttributes; return instances;
} }
std::vector<domain::InstanceAttribute> Schema::populateSingleAutomaticConnection(domain::Connection connection) { std::vector<domain::ConnectionComponent>
std::vector<domain::InstanceAttribute> instanceAttributes; Schema::getAvailableConnectionPins(domain::ComponentInstance *instance, domain::Pin &pin) {
std::vector<domain::ConnectionComponent> instances;
for (auto attr: connection.getAttributes()) { domain::ConnectionComponent source{instance->component.getName(), pin.getName()};
instanceAttributes.emplace_back(attr.getName(), attr.getDefault(), attr); for (const auto &entry: pins) {
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

View File

@ -4,7 +4,6 @@
#include <QGraphicsView> #include <QGraphicsView>
#include <QWidget> #include <QWidget>
#include <QColor>
#include <QGraphicsLineItem> #include <QGraphicsLineItem>
#include <comdel/domain/schema.h> #include <comdel/domain/schema.h>
@ -20,9 +19,8 @@ namespace display {
public: public:
QBrush selectedBrush = QBrush(QColor::fromRgb(50, 50, 150, 100), Qt::BrushStyle::SolidPattern); QBrush selectedBrush;
QPen selectedPen = QPen(QColor::fromRgb(50, 50, 150), 1, Qt::PenStyle::SolidLine); QPen selectedPen;
QPen activeLinePen = QPen(QColor::fromRgb(250, 100, 100));
enum State { enum State {
DEFAULT, DEFAULT,
@ -48,14 +46,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;
@ -70,11 +68,11 @@ namespace display {
domain::Schema *schema{}; domain::Schema *schema{};
std::optional<domain::Library> library; std::optional<domain::Library> library;
std::vector<domain::InstanceAttribute> populateAttributes(std::vector<domain::Attribute>& attributes); std::vector<domain::BusInstance *>
getAvailableConnectionBusses(domain::ComponentInstance *instance, domain::Pin &pin);
std::vector<domain::InstanceAttribute> populateSingleAutomaticConnection(domain::Connection connection); std::vector<domain::ConnectionComponent>
getAvailableConnectionPins(domain::ComponentInstance *instance, domain::Pin &pin);
void clearSelectable();
}; };
} // namespace display } // namespace display

View File

@ -1,75 +0,0 @@
//
// 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

View File

@ -1,35 +0,0 @@
//
// 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

View File

@ -59,8 +59,4 @@ namespace domain {
return popup; return popup;
} }
void Attribute::setPupup(std::optional<Popup> popup) {
this->popup = popup;
}
} // namespace domain } // namespace domain

View File

@ -54,7 +54,7 @@ namespace domain {
void setEnumeration(std::vector<Enumeration> enums) { void setEnumeration(std::vector<Enumeration> enums) {
enumerated = true; enumerated = true;
enumeration = enums; enumeration = std::move(enums);
} }
}; };
@ -71,7 +71,6 @@ namespace domain {
Value getDefault(); Value getDefault();
std::optional<Popup> getPopup(); std::optional<Popup> getPopup();
void setPupup(std::optional<Popup> popup);
}; };
} // namespace domain } // namespace domain

View File

@ -285,11 +285,7 @@ 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()) {
if(wire.isType(Value::NIL)) { tempOutput << wire.stringify() << ", ";
tempOutput << "*, ";
} else {
tempOutput << wire.stringify() << ", ";
}
} }
} }
} }
@ -315,26 +311,22 @@ 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.asString(); selected = connection->attributes[0].value.asReference();
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.asString(); selected = connection->attributes[1].value.asReference();
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) {
auto wireName = connection->bus->name + "." + connection->bus->bus.getWires()[0].getName(); buffer << wireNames[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() << ", ";
} }

View File

@ -153,37 +153,6 @@ 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;

View File

@ -35,8 +35,6 @@ 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);

View File

@ -62,7 +62,7 @@ namespace domain {
return false; return false;
} }
std::vector<Attribute>& Component::getAttributes() { std::vector<Attribute> Component::getAttributes() {
return attributes; return attributes;
} }

View File

@ -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);

View File

@ -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;
} }

View File

@ -53,17 +53,14 @@ 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();

View File

@ -1,13 +1,7 @@
#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) {
@ -45,16 +39,11 @@ 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) {
_w = size; group->addToGroup(new QGraphicsRectItem(x, y, size, h));
} else { } else {
_h = size; group->addToGroup(new QGraphicsRectItem(x, y, w, 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() {

View File

@ -39,72 +39,4 @@ 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

View File

@ -3,33 +3,14 @@
#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(Library library): library(std::move(library)) {} Schema() = default;
std::vector<shared_ptr<BusInstance>> busInstances; std::vector<shared_ptr<BusInstance>> busInstances;
std::vector<shared_ptr<ComponentInstance>> componentInstances; std::vector<shared_ptr<ComponentInstance>> componentInstances;
@ -40,8 +21,6 @@ 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

View File

@ -438,9 +438,7 @@ 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 {
domain::Popup popup = *attributes[0].getPopup(); attributes[0].getPopup()->setEnumeration(createWireEnumeration(firstWires));
popup.setEnumeration(createWireEnumeration(firstWires));
attributes[0].setPupup(popup);
} }
if (!attributes[1].getPopup().has_value()) { if (!attributes[1].getPopup().has_value()) {
@ -448,9 +446,7 @@ 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 {
domain::Popup popup = *attributes[1].getPopup(); attributes[1].getPopup()->setEnumeration(createWireEnumeration(secondWires));
popup.setEnumeration(createWireEnumeration(secondWires));
attributes[1].setPupup(popup);
} }
} }
@ -736,7 +732,7 @@ namespace domain {
std::optional<Popup> popup; std::optional<Popup> popup;
if (node.popup) { if (node.popup) {
popup = loadPopup(*node.popup, name, toType(node.type)); popup = loadPopup(*node.popup, name, value.getType());
} }
pop(); pop();
@ -866,7 +862,7 @@ namespace domain {
Schema *SchemaCreator::loadSchema(SchemaNode node, Library &library) { Schema *SchemaCreator::loadSchema(SchemaNode node, Library &library) {
auto *schema = new Schema(library); auto *schema = new Schema();
for (auto &instance: node.instances) { for (auto &instance: node.instances) {
if (library.hasComponent(instance.component.value)) { if (library.hasComponent(instance.component.value)) {
@ -939,26 +935,16 @@ 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().equals(value)) { if (en.getValue().asReference() == value.asReference()) {
valueFound = true; value = Value::fromReference(value.asReference(), Value::WIRE_REFERENCE);
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 (!valueFound) { if (value.isType(Value::UNDEFINED)) {
errors.emplace_back(attr.span, "invalid value"); errors.emplace_back(attr.span, "invalid value");
} }
attributes.emplace_back(attribute.getName(), value, attribute); attributes.emplace_back(attribute.getName(), toType(attr.value), attribute);
} else { } else {
errors.emplace_back(attr.name.span, "unknown attribute"); errors.emplace_back(attr.name.span, "unknown attribute");
} }

View File

@ -50,11 +50,12 @@ 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) {
++position;
} else {
ATLAS_ASSERT_FAIL("Internal parser error, called bump after EOF"); ATLAS_ASSERT_FAIL("Internal parser error, called bump after EOF");
} else {
tokens[++position];
} }
expectedTokens.clear(); expectedTokens.clear();
} }
@ -1347,7 +1348,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()->asString())); return spanner(ValueNode::ofString(parseString()->value));
} else if (check(TokenType::IDENTIFIER)) { } else if (check(TokenType::IDENTIFIER)) {
return spanner(ValueNode::ofIdentifier(parseIdentifier()->value)); return spanner(ValueNode::ofIdentifier(parseIdentifier()->value));
} else { } else {

View File

@ -1,4 +1,4 @@
#include "comdel_lexer.h" #include "comdellexer.h"
#include "token.h" #include "token.h"
#include "tokens_type.h" #include "tokens_type.h"

View File

@ -1,4 +1,4 @@
#include "comdel_lexer.h" #include "comdellexer.h"
#include "comdel_parser.h" #include "comdel_parser.h"
#include "parser_util.h" #include "parser_util.h"

View File

@ -7,7 +7,7 @@
component System component System
{ {
clock 100MHz; clock 100MHz;
//glavnaSabirnica //bus
wire<32> ADR; wire<32> ADR;
wire<32> DATA; wire<32> DATA;
wire READ; wire READ;
@ -23,31 +23,32 @@ component System
wire --BACK; wire --BACK;
//directRam
wire INT;
// components -------------------------------------------- // components --------------------------------------------
subcomponent Memorija memorija<false, 1, 65536, 8, 0>(ADR, DATA, READ, WRITE, SIZE, WAIT, *, *, *, INT); subcomponent Memorija mem<false, 1, 1024, 8, 1024>(ADR, DATA, READ, WRITE, SIZE, WAIT, 94534054858378, 0, null, null);
subcomponent FRISC procesor(ADR, DATA, READ, WRITE, SIZE, WAIT, INT0, INT1, INT2, INT3, --IACK, 1, *, INT, *, *, *); subcomponent FRISC procesor_002(ADR, DATA, READ, WRITE, SIZE, WAIT, INT0, INT1, INT2, INT3, --IACK, 1, *, 94534054858378, 0, null, null);
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: -377; y: -302; ref: "procesor"; } component { x: 0; y: 0; ref: "procesor_002"; }
component { x: -56; y: -80; ref: "memorija"; } component { x: 0; y: 250; ref: "mem"; }
component { x: -89; y: 74; ref: "procesor_001"; }
component { x: -175; y: 195; ref: "procesor_000"; }
component { x: -195; y: 63; ref: "procesor"; }
// glavnaSabirnica bus // bus bus
rectangle { rectangle {
x: -377; y: -106; x: 0; y: 200;
w: 100; h: 20; w: 100; h: 20;
} }
// directRam bus line {x1:50; y1:116; x2:50; y2:210;}
line {x1:50; y1:234; x2:50; y2:210;}
line {x1:-39; y1:190; x2:50; y2:210;}
line {x1:-6; y1:-96; x2:-326; y2:-95;} line {x1:-145; y1:179; x2:50; y2:210;}
line {x1:-327; y1:-186; x2:-326; y2:-95;} line {x1:-125; y1:311; x2:50; y2:210;}
line {x1:-72; y1:-52; x2:-261; y2:-252;}
} }
} }

View File

@ -8,12 +8,13 @@
@address pomocniAS(0xFFFF0000,0xFFFFFFFF) @address pomocniAS(0xFFFF0000,0xFFFFFFFF)
@messages { @messages {
ok: "OK"; Ok: "OK";
yes: "Da"; Yes: "Da";
no: "Ne"; No: "Ne";
cancel: "Odustani"; Cancel: "Otkaži";
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 {
@ -72,7 +73,6 @@
orientation: "right"; orientation: "right";
} }
} }
@wires{null, null, null, null}
} }
} }
@ -215,7 +215,6 @@
orientation: "left"; orientation: "left";
} }
} }
@wires{null, null, null, null}
} }
} }
@ -230,7 +229,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")
} }
} }
@ -240,7 +239,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)")
} }
} }
@ -282,7 +281,7 @@
} }
*/ */
pin { pin {
x: 100; y: 30; w: 16; h: 16; x: 100; y: 50; w: 16; h: 16;
} }
} }
} }
@ -292,7 +291,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: 100; y: 7; w: 16; h: 16; x: 0; y: 0; w: 0; h: 0;
} }
} }
@wires { 0, 0, null, null} @wires { 0, 0, null, null}
@ -345,7 +344,7 @@
} }
} }
@bus directRam singleAutomatic { @bus directRam automatic {
@instanceName directRam @instanceName directRam
@wires { @wires {
INT INT
@ -376,25 +375,12 @@
@wires{ADR, DATA, READ, WRITE, SIZE, WAIT, interupt, BREQ, BACK} @wires{ADR, DATA, READ, WRITE, SIZE, WAIT, interupt, BREQ, BACK}
} }
@connection (DMA.dodatnaPoveznica, PIOSabirnica, FRISC.glavniPin) { @connection (DMA.glavniPin, 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) {
@attribute procConn string default "INT" { @wires{INT}
@popup automatic { @wires{INT}
@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"}
} }

View File

@ -1,14 +1,42 @@
@source "/home/bbr/Documents/Personal/FER/schema_editor/examples/simplified FRISC model/frisc_library.csl" @source "frisc_library.csl"
@schema { @schema {
@instance procesor FRISC { @instance procesor_002 FRISC {
@position (-177, -122) @position (0, 0)
@attribute _memory memorija2
}
@instance procesor FRISC {
@position (49, -97)
@attribute _memory null @attribute _memory null
} }
@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 {
@position (-195, 63)
@attribute _memory null
}
@instance bus glavnaSabirnica {
@position (0, 200)
@size 100
}
@connection (procesor_002.glavniPin, bus) {
}
@connection (mem.glavniPin, bus) {
}
} }

View File

@ -2,28 +2,33 @@
@schema { @schema {
@instance procesor FRISC { @instance procesor FRISC {
@position (-464, -314) @position (-76, -97)
@attribute _memory null @attribute _memory memorija
} }
@instance dma DMA { @instance memorija Memorija {
@position (-269, 46) @position (52, 119)
@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 (-579, -160) @position (-78, 88)
@size 100 @size 100
} }
@instance PIOSabirnica PIOSabirnica { @instance directRam directRam {
@position (0, 0) @position (0, 0)
@size 0 @size 0
} }
@connection (dma.glavniPin, glavnaSabirnica) { @connection (memorija.glavniPin, glavnaSabirnica) {
@attribute interupt INT2
} }
@connection (dma.glavniPin, PIOSabirnica, procesor.glavniPin) { @connection (procesor.glavniPin, glavnaSabirnica) {
}
@connection (memorija.memDirect, directRam, procesor.memDirect) {
} }
} }

View File

@ -1,16 +0,0 @@
@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) {
}
}

View File

@ -1,49 +0,0 @@
@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"
}
}

View File

@ -32,13 +32,11 @@ void MainWindow::setupUi()
ui->centralwidget->setLayout(layout); ui->centralwidget->setLayout(layout);
// setup toolbar // setup toolbar
ui->toolBar->addAction("Učitaj bibiloteku", this, &MainWindow::onLoadLibrary); ui->toolBar->addAction("Load library", this, &MainWindow::onLoadLibrary);
ui->toolBar->addAction("Učitaj shemu", this, &MainWindow::onLoadSchema); ui->toolBar->addAction("Load schema", this, &MainWindow::onLoadSchema);
ui->toolBar->addAction("Spremi shemu", this, &MainWindow::onStoreScheme); ui->toolBar->addAction("Save schema", this, &MainWindow::onStoreScheme);
ui->toolBar->addAction("Generiraj comdel", this, &MainWindow::onGenerateComdel); ui->toolBar->addAction("Generate system", 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
@ -49,10 +47,10 @@ void MainWindow::setupUi()
schemaParent->setLayout(schemaLayout); schemaParent->setLayout(schemaLayout);
schemaDisplay = new display::Schema(); schemaDisplay = new display::Schema();
schemaLayout->setContentsMargins(0, 0, 0, 0); schemaLayout->setMargin(0);
schemaLayout->addWidget(schemaDisplay, 1); schemaLayout->addWidget(schemaDisplay, 1);
layout->setContentsMargins(0, 0, 0, 0); layout->setMargin(0);
layout->addWidget(libraryDisplay); layout->addWidget(libraryDisplay);
layout->addWidget(schemaParent, 1); layout->addWidget(schemaParent, 1);
@ -64,10 +62,10 @@ void MainWindow::setupUi()
void MainWindow::onLoadLibrary() { void MainWindow::onLoadLibrary() {
auto filename = QFileDialog::getOpenFileName(this, auto filename = QFileDialog::getOpenFileName(this,
tr("Otvori biblioteku"), "", tr("Comdel biblioteka (*.csl)")); tr("Open library"), "/home", tr("Comdel library (*.csl)"));
if(!filename.isEmpty()) { if(!filename.isEmpty()) {
std::ostringstream output; std::ostringstream output;
log->clear(); clear();
auto librarySource = filename.toStdString(); auto librarySource = filename.toStdString();
@ -76,35 +74,33 @@ void MainWindow::onLoadLibrary() {
log->appendPlainText(QString::fromStdString(output.str())); log->appendPlainText(QString::fromStdString(output.str()));
} }
libraryDisplay->refreshContent(); libraryDisplay->setLibrary(instance->getLibrary());
schemaDisplay->refreshContent(); schemaDisplay->setSchema(instance->getSchema(), instance->getLibrary());
} }
} }
void MainWindow::onLoadSchema() { void MainWindow::onLoadSchema() {
auto filename = QFileDialog::getOpenFileName(this, auto filename = QFileDialog::getOpenFileName(this,
tr("Otvori shemu"), "", tr("Comdel shema (*.csl)")); tr("Open schema"), "/home", tr("Comdel schema (*.csl)"));
if(!filename.isEmpty()) { if(!filename.isEmpty()) {
std::ostringstream output; std::ostringstream output;
log->clear(); clear();
auto schemaSource = filename.toStdString(); auto schemaSource = filename.toStdString();
auto instance = Application::instance(); auto instance = Application::instance();
auto result = instance->loadSchema(schemaSource, output); if(!instance->loadSchema(schemaSource, output)) {
if(!result.first){
formatErrors(result.second, output);
log->appendPlainText(QString::fromStdString(output.str())); log->appendPlainText(QString::fromStdString(output.str()));
} }
libraryDisplay->refreshContent(); libraryDisplay->setLibrary(instance->getLibrary());
schemaDisplay->refreshContent(); schemaDisplay->setSchema(instance->getSchema(), instance->getLibrary());
} }
} }
void MainWindow::onStoreScheme() { void MainWindow::onStoreScheme() {
auto filename = QFileDialog::getSaveFileName(this, auto filename = QFileDialog::getSaveFileName(this,
tr("Spremi shemu"), "", tr("Comdel shema (*.csl)")); tr("Save schema"), "/home", tr("Comdel schema (*.csl)"));
if(!filename.isEmpty()) { if(!filename.isEmpty()) {
log->clear(); log->clear();
@ -115,9 +111,9 @@ void MainWindow::onStoreScheme() {
out<<output.str(); out<<output.str();
out.close(); out.close();
log->appendPlainText("Uspješno spremljena shema\n"); log->appendPlainText("Successfully stored schema\n");
} else { } else {
log->appendPlainText("Greška tijekom spremanja sheme\n"); log->appendPlainText("Failed storing schema\n");
} }
} }
@ -125,7 +121,7 @@ void MainWindow::onStoreScheme() {
void MainWindow::onGenerateComdel() { void MainWindow::onGenerateComdel() {
auto filename = QFileDialog::getSaveFileName(this, auto filename = QFileDialog::getSaveFileName(this,
tr("Spremi shemu"), "", tr("Comdel sustav (*.system)")); tr("Save schema"), "/home", tr("Comdel system (*.system)"));
if(!filename.isEmpty()) { if(!filename.isEmpty()) {
log->clear(); log->clear();
@ -137,14 +133,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("Uspješno generiranje comdel modela\n"); log->appendPlainText("Successfully generated comdel\n");
} else { } else {
log->appendPlainText("Neuspješno generiranje comdel modela\n"); log->appendPlainText("Failed generating comdel\n");
} }
} }
} }
@ -180,7 +176,13 @@ 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;
} }

View File

@ -53,17 +53,17 @@
</widget> </widget>
<action name="actionSave_schema"> <action name="actionSave_schema">
<property name="text"> <property name="text">
<string>Spremi shemu</string> <string>Save schema</string>
</property> </property>
</action> </action>
<action name="actionExport_schema"> <action name="actionExport_schema">
<property name="text"> <property name="text">
<string>Generiraj comdel</string> <string>Export schema</string>
</property> </property>
</action> </action>
<action name="actionValidate"> <action name="actionValidate">
<property name="text"> <property name="text">
<string>Validairaj</string> <string>Validate</string>
</property> </property>
</action> </action>
</widget> </widget>