Added component/bus deletion and rename
This commit is contained in:
parent
f93a2afa63
commit
3172d7e4cf
245
application.cpp
245
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();
|
||||||
|
} 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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -18,9 +18,13 @@ 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++) {
|
||||||
|
@ -40,6 +44,13 @@ namespace display {
|
||||||
});
|
});
|
||||||
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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,9 +114,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());
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QListWidget>
|
#include <QListWidget>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
|
#include <application.h>
|
||||||
|
|
||||||
namespace display {
|
namespace display {
|
||||||
|
|
||||||
|
@ -19,11 +20,10 @@ namespace display {
|
||||||
layout->addSpacing(8);
|
layout->addSpacing(8);
|
||||||
layout->addWidget(new QLabel("Buses:"));
|
layout->addWidget(new QLabel("Buses:"));
|
||||||
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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -19,14 +19,15 @@ 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();
|
||||||
busConnections.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);
|
||||||
|
|
|
@ -46,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;
|
||||||
|
|
|
@ -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("There isn't a memory instance '{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);
|
||||||
|
|
|
@ -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,13 @@
|
||||||
|
|
||||||
@schema {
|
@schema {
|
||||||
@instance procesor FRISC {
|
@instance procesor FRISC {
|
||||||
@position (-76, -97)
|
@position (-112, -89)
|
||||||
@attribute _memory memorija
|
@attribute _memory memorija2
|
||||||
}
|
}
|
||||||
|
|
||||||
@instance memorija Memorija {
|
@instance procesor FRISC {
|
||||||
@position (52, 119)
|
@position (112, -89)
|
||||||
@attribute sinkroniziran false
|
@attribute _memory null
|
||||||
@attribute brzina 1
|
|
||||||
@attribute kapacitet 65536
|
|
||||||
@attribute size 8
|
|
||||||
@attribute pocetnaAdresa 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@instance glavnaSabirnica glavnaSabirnica {
|
|
||||||
@position (-78, 88)
|
|
||||||
@size 100
|
|
||||||
}
|
|
||||||
|
|
||||||
@instance directRam directRam {
|
|
||||||
@position (0, 0)
|
|
||||||
@size 0
|
|
||||||
}
|
|
||||||
|
|
||||||
@connection (memorija.glavniPin, glavnaSabirnica) {
|
|
||||||
}
|
|
||||||
@connection (procesor.glavniPin, glavnaSabirnica) {
|
|
||||||
}
|
|
||||||
@connection (memorija.memDirect, directRam, procesor.memDirect) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,7 +65,7 @@ void MainWindow::onLoadLibrary() {
|
||||||
tr("Open library"), "/home", tr("Comdel library (*.csl)"));
|
tr("Open library"), "/home", tr("Comdel library (*.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,8 +74,8 @@ 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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,17 +84,19 @@ void MainWindow::onLoadSchema() {
|
||||||
tr("Open schema"), "/home", tr("Comdel schema (*.csl)"));
|
tr("Open schema"), "/home", tr("Comdel schema (*.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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,12 +178,6 @@ 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;
|
||||||
|
|
Loading…
Reference in New Issue