From d2fc849cc2a5a01775180e171c724316f732db34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Borna=20Rajkovi=C4=87?= Date: Sun, 19 Jun 2022 20:10:44 +0200 Subject: [PATCH] Added message source and arm example --- CMakeLists.txt | 2 +- comdel/display/component_display.cpp | 83 +- comdel/display/dialog/attribute_dialog.cpp | 5 +- comdel/display/dialog/error_dialog.cpp | 4 +- comdel/display/dialog/generic_dialog.cpp | 18 +- comdel/display/dialog/generic_dialog.h | 6 +- comdel/display/dialog/memory_dialog.cpp | 3 +- comdel/display/dialog/name_dialog.cpp | 5 +- comdel/display/dialog/success_dialog.cpp | 6 +- comdel/display/dialog/success_dialog.h | 2 +- comdel/display/dialog/warning_dialog.cpp | 2 +- comdel/display/library_display.cpp | 12 +- comdel/display/library_display.h | 3 + comdel/display/schema_display.cpp | 29 +- comdel/domain/comdel_generator.cpp | 96 +- comdel/domain/comdel_validator.cpp | 79 +- comdel/domain/comdel_validator.h | 9 +- comdel/domain/connection_instance.cpp | 19 + comdel/domain/connection_instance.h | 2 + comdel/domain/display.cpp | 16 + comdel/domain/display.h | 16 + comdel/domain/schema.cpp | 21 +- comdel/domain/schema_creator.cpp | 14 +- comdel/domain/value.cpp | 12 +- examples/arm/arm_library.csl | 1107 +++++++++++++++++ examples/arm/model.csch | 64 + examples/arm/model2.csch | 233 ++++ examples/arm/test.system | 75 ++ examples/arm/test2.system | 245 ++++ .../{schema.csl => schema.csch} | 0 .../{schema2.csl => schema2.csch} | 0 .../{schema3.csl => schema3.csch} | 0 .../{schema4.csl => schema4.csch} | 0 .../{schema5.csl => schema5.csch} | 0 mainwindow.cpp | 52 +- mainwindow.h | 7 + message_source.cpp | 145 +++ message_source.h | 43 + 38 files changed, 2261 insertions(+), 174 deletions(-) create mode 100644 examples/arm/arm_library.csl create mode 100644 examples/arm/model.csch create mode 100644 examples/arm/model2.csch create mode 100644 examples/arm/test.system create mode 100644 examples/arm/test2.system rename examples/simplified FRISC model/{schema.csl => schema.csch} (100%) rename examples/simplified FRISC model/{schema2.csl => schema2.csch} (100%) rename examples/simplified FRISC model/{schema3.csl => schema3.csch} (100%) rename examples/simplified FRISC model/{schema4.csl => schema4.csch} (100%) rename examples/simplified FRISC model/{schema5.csl => schema5.csch} (100%) create mode 100644 message_source.cpp create mode 100644 message_source.h diff --git a/CMakeLists.txt b/CMakeLists.txt index a0aaa8f..65ee788 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,5 +37,5 @@ add_executable(SchemeEditor comdel/parser/comdel_lexer.cpp main.cpp mainwindow.ui - comdel/domain/comdel_validator.cpp comdel/domain/comdel_validator.h comdel/display/dialog/attribute_dialog.cpp comdel/display/dialog/attribute_dialog.h comdel/display/dialog/name_dialog.cpp comdel/display/dialog/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/dialog/single_automatic_dialog.cpp comdel/display/dialog/single_automatic_dialog.h comdel/parser/color.h comdel/display/dialog/generic_dialog.cpp comdel/display/dialog/generic_dialog.h comdel/display/dialog/warning_dialog.cpp comdel/display/dialog/warning_dialog.h comdel/display/dialog/error_dialog.cpp comdel/display/dialog/error_dialog.h comdel/display/dialog/memory_dialog.cpp comdel/display/dialog/memory_dialog.h comdel/display/dialog/success_dialog.cpp comdel/display/dialog/success_dialog.h) + comdel/domain/comdel_validator.cpp comdel/domain/comdel_validator.h comdel/display/dialog/attribute_dialog.cpp comdel/display/dialog/attribute_dialog.h comdel/display/dialog/name_dialog.cpp comdel/display/dialog/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/dialog/single_automatic_dialog.cpp comdel/display/dialog/single_automatic_dialog.h comdel/parser/color.h comdel/display/dialog/generic_dialog.cpp comdel/display/dialog/generic_dialog.h comdel/display/dialog/warning_dialog.cpp comdel/display/dialog/warning_dialog.h comdel/display/dialog/error_dialog.cpp comdel/display/dialog/error_dialog.h comdel/display/dialog/memory_dialog.cpp comdel/display/dialog/memory_dialog.h comdel/display/dialog/success_dialog.cpp comdel/display/dialog/success_dialog.h message_source.cpp message_source.h) target_link_libraries(SchemeEditor Qt5::Core Qt5::Gui Qt5::Widgets) diff --git a/comdel/display/component_display.cpp b/comdel/display/component_display.cpp index a1063d0..913f4d9 100644 --- a/comdel/display/component_display.cpp +++ b/comdel/display/component_display.cpp @@ -5,6 +5,7 @@ #include "application.h" #include "comdel/display/dialog/single_automatic_dialog.h" #include "comdel/display/dialog/memory_dialog.h" +#include "message_source.h" #include #include @@ -25,7 +26,7 @@ namespace display { void Component::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { QMenu menu; - menu.addAction("Izmjeni ime", [this]() { + menu.addAction(QMESSAGE("msg_dialog_name_update"), [this]() { std::set names; for(const auto &component: Application::instance()->getSchema()->componentInstances) { names.insert(component->name); @@ -45,22 +46,29 @@ namespace display { bool enabled = attr->attribute.getPopup().has_value(); if(attr->value.getType() == domain::Value::MEMORY_REFERENCE) { - menu.addAction("Izmjeni memoriju", [attr]() { - auto dialog = new MemoryDialog("Izmjeni memoriju", "Izmjeni", attr, + menu.addAction(QMESSAGE("msg_dialog_memory_update"), [attr]() { + auto dialog = new MemoryDialog(MESSAGE("msg_dialog_memory_update"), + MESSAGE("msg_dialog_actions_update"), + attr, Application::instance()->getSchema()->componentInstances); dialog->exec(); }); } else { - auto action = menu.addAction(QString::fromStdString("Izmjeni '" + attr->attribute.getDisplayName() + "'"), - [attr]() { - auto dialog = new AttributeDialog("Izmjeni " + attr->attribute.getDisplayName(), "Izmjeni", attr); - dialog->exec(); - }); + std::map params = {{"attribute", attr->attribute.getDisplayName()}}; + auto action = menu.addAction(QMESSAGE_PARAM("msg_dialog_attribute_update", params), + [attr]() { + std::map params = {{"attribute", attr->attribute.getDisplayName()}}; + auto dialog = new AttributeDialog(MESSAGE_PARAM("msg_dialog_attribute_update", params), + "msg_dialog_actions_update", + attr); + dialog->exec(); + }); action->setEnabled(enabled); } } menu.addSeparator(); - menu.addAction(QString::fromStdString("Ukloni " + this->instance->name), [this]() { + std::map params = {{"name", instance->name}}; + menu.addAction(QMESSAGE_PARAM("msg_dialog_actions_remove_named", params), [this]() { Application::instance()->removeComponent(this->instance->name); auto view = dynamic_cast(this->scene()->views()[0]); view->refreshContent(); @@ -75,19 +83,28 @@ namespace display { auto pinConnections = Application::instance()->getSchema()->getConnections(componentInstance->name, pin.getName()); if(isSingleAutomatic(pinConnections)) { - auto *update = menu.addMenu("Izmjeni"); - auto *remove = menu.addMenu("Ukloni"); + auto *update = menu.addMenu(QMESSAGE("msg_pin_update")); + auto *remove = menu.addMenu(QMESSAGE("msg_pin_remove")); for (auto pinConnection: pinConnections) { // this always must be true as only directConnections can be connected multiple times if (auto directConnection = dynamic_cast(pinConnection)) { if (directConnection->bus->bus.getType() == domain::Bus::SINGLE_AUTOMATIC) { - auto connectionName = directConnection->attributes[0].value.stringify() + "-" + - directConnection->attributes[1].value.stringify(); - update->addAction(QString::fromStdString("Izmjeni " + connectionName), [directConnection]() { - auto dialog = new SingleAutomaticDialog("Izmjeni sabirnicu", "Izmjeni", directConnection->attributes); + auto params = MessageSource::instance()->map( + {{"wire1", directConnection->attributes[0].value}, + {"wire2", directConnection->attributes[1].value}} + ); + update->addAction(QMESSAGE_PARAM("msg_sa_pin_update_title", params), + [directConnection]() { + auto params = MessageSource::instance()->map( + {{"wire1", directConnection->attributes[0].value}, + {"wire2", directConnection->attributes[1].value}} + ); + auto dialog = new SingleAutomaticDialog(MESSAGE_PARAM("msg_sa_pin_update_title", params), + MESSAGE("msg_pin_update_action"), + directConnection->attributes); dialog->exec(); }); - remove->addAction(QString::fromStdString("Ukloni " + connectionName), + remove->addAction(QMESSAGE_PARAM("msg_sa_pin_remove_title", params), [this, directConnection]() { Application::instance()->removeConnection(directConnection); auto view = dynamic_cast(this->scene()->views()[0]); @@ -109,12 +126,15 @@ namespace display { } for (int i = 0; i < pinConnection->attributes.size(); i++) { auto *attr = &pinConnection->attributes[i]; - menu.addAction(QString::fromStdString("Izmjeni '" + attr->attribute.getDisplayName() + "'"),[attr]() { - auto dialog = new AttributeDialog("Izmjeni '" + attr->attribute.getDisplayName() + "'", "Izmjeni", attr); - dialog->exec(); + std::map params = {{"name", attr->attribute.getDisplayName()}}; + menu.addAction(QMESSAGE_PARAM("msg_dialog_actions_update_named", params), + [attr]() { + std::map params = {{"name", attr->attribute.getDisplayName()}}; + auto dialog = new AttributeDialog(MESSAGE_PARAM("msg_dialog_actions_update_named", params), "msg_pin_update_action", attr); + dialog->exec(); }); } - menu.addAction("Ukloni poveznicu", [this, pinConnection]() { + menu.addAction(QMESSAGE("msg_pin_remove_action"), [this, pinConnection]() { Application::instance()->removeConnection(pinConnection); auto view = dynamic_cast(this->scene()->views()[0]); view->refreshContent(); @@ -186,7 +206,7 @@ namespace display { void Bus::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { QMenu menu; - menu.addAction("Izmjeni ime", [this]() { + menu.addAction(QMESSAGE("msg_dialog_name_update"), [this]() { std::set names; for(const auto &component: Application::instance()->getSchema()->busInstances) { names.insert(component->name); @@ -201,7 +221,9 @@ namespace display { setToolTip(QString::fromStdString(busInstance->name + "::" + busInstance->bus.getDisplayName())); }); menu.addSeparator(); - menu.addAction(QString::fromStdString("Ukloni " + this->busInstance->name), [this]() { + + std::map params = {{"name", busInstance->name}}; + menu.addAction(QMESSAGE_PARAM("msg_dialog_actions_remove_named", params), [this]() { Application::instance()->removeBus(this->busInstance->name); auto view = dynamic_cast(this->scene()->views()[0]); view->refreshContent(); @@ -306,10 +328,19 @@ namespace display { } void DirectConnection::updateConnection() { - auto pin1 = connection->instance->component.getPin( - connection->connection.getComponent().pin).getDisplayPin(); - auto pin2 = connection->secondInstance->component.getPin( - connection->connection.getSecondComponent()->pin).getDisplayPin(); + domain::ui::Pin pin1, pin2; + if(connection->connection.getComponent().component == connection->instance->component.getName()) { + pin1 = connection->instance->component.getPin( + connection->connection.getComponent().pin).getDisplayPin(); + pin2 = connection->secondInstance->component.getPin( + connection->connection.getSecondComponent()->pin).getDisplayPin(); + + } else { + pin1 = connection->instance->component.getPin( + connection->connection.getSecondComponent()->pin).getDisplayPin(); + pin2 = connection->secondInstance->component.getPin( + connection->connection.getComponent().pin).getDisplayPin(); + } setLine(connection->instance->position.first + pin1.getConnectionX(), connection->instance->position.second + pin1.getConnectionY(), diff --git a/comdel/display/dialog/attribute_dialog.cpp b/comdel/display/dialog/attribute_dialog.cpp index 1236c9b..dea54ab 100644 --- a/comdel/display/dialog/attribute_dialog.cpp +++ b/comdel/display/dialog/attribute_dialog.cpp @@ -4,6 +4,7 @@ #include "application.h" #include "error_dialog.h" #include "warning_dialog.h" +#include "message_source.h" namespace display { @@ -140,11 +141,11 @@ namespace display { auto *radioLayout = new QHBoxLayout(group); group->setLayout(radioLayout); - auto isTrue = new QRadioButton("da", group); + auto isTrue = new QRadioButton(QMESSAGE("msg_boolean_true"), group); connect(isTrue, &QRadioButton::clicked, [this]() { this->value = domain::Value::fromBool(true); }); - auto isFalse = new QRadioButton("ne", group); + auto isFalse = new QRadioButton(QMESSAGE("msg_boolean_false"), group); connect(isFalse, &QRadioButton::clicked, [this]() { this->value = domain::Value::fromBool(false); }); diff --git a/comdel/display/dialog/error_dialog.cpp b/comdel/display/dialog/error_dialog.cpp index 736042e..ce5d4aa 100644 --- a/comdel/display/dialog/error_dialog.cpp +++ b/comdel/display/dialog/error_dialog.cpp @@ -6,7 +6,7 @@ namespace display { ErrorDialog::ErrorDialog(std::vector errors) - : GenericDialog("Greške", "") { + : GenericDialog("msg_dialog_error_title", std::nullopt, "msg_dialog_error_close") { auto contentLayout = new QVBoxLayout(); content->setLayout(contentLayout); @@ -17,7 +17,7 @@ namespace display { } ErrorDialog::ErrorDialog(std::ostringstream& errorStream) - : GenericDialog("Greške", "") { + : GenericDialog("msg_dialog_error_title", std::nullopt, "msg_dialog_error_close") { auto contentLayout = new QVBoxLayout(); content->setLayout(contentLayout); diff --git a/comdel/display/dialog/generic_dialog.cpp b/comdel/display/dialog/generic_dialog.cpp index c8a2ce4..7d5f1a4 100644 --- a/comdel/display/dialog/generic_dialog.cpp +++ b/comdel/display/dialog/generic_dialog.cpp @@ -1,9 +1,11 @@ #include #include "generic_dialog.h" -display::GenericDialog::GenericDialog(std::string title, std::string action) { +#include "message_source.h" + +display::GenericDialog::GenericDialog(std::string title, std::optional action, std::string cancel) { setAttribute(Qt::WA_DeleteOnClose); - setWindowTitle(QString::fromStdString(title)); + setWindowTitle(QMESSAGE(title)); setLayout(new QVBoxLayout()); content = new QWidget(this); @@ -14,12 +16,16 @@ display::GenericDialog::GenericDialog(std::string title, std::string action) { layout()->addWidget(actionWidget); // if action isn't defined only close button is offered - if(!action.empty()) { - okButton = new QPushButton(QString::fromStdString(action), this); - connect(okButton, &QPushButton::clicked, this, [this](){if(this->onUpdate()) this->accept();}); + if(action.has_value()) { + okButton = new QPushButton(QMESSAGE(*action), this); + connect(okButton, &QPushButton::clicked, this, [this](){ + if(this->onUpdate()) { + this->accept(); + } + }); actionBar->addWidget(okButton); } - cancelButton = new QPushButton("Odustani", this); + cancelButton = new QPushButton(QMESSAGE(cancel), this); connect(cancelButton, &QPushButton::clicked, [this]() { reject(); }); actionBar->addWidget(cancelButton); } diff --git a/comdel/display/dialog/generic_dialog.h b/comdel/display/dialog/generic_dialog.h index d2f2ee4..28c70ab 100644 --- a/comdel/display/dialog/generic_dialog.h +++ b/comdel/display/dialog/generic_dialog.h @@ -5,12 +5,16 @@ #include #include +#include + namespace display { class GenericDialog: public QDialog { public: - GenericDialog(std::string title, std::string action = "Ažuriraj"); + explicit GenericDialog(std::string title, + std::optional action = "msg_dialog_actions_update", + std::string cancel = "msg_dialog_actions_cancel"); protected: void setOkButtonDisabled(bool disabled); diff --git a/comdel/display/dialog/memory_dialog.cpp b/comdel/display/dialog/memory_dialog.cpp index 27e2ccd..2fcab2a 100644 --- a/comdel/display/dialog/memory_dialog.cpp +++ b/comdel/display/dialog/memory_dialog.cpp @@ -1,6 +1,7 @@ #include #include #include "memory_dialog.h" +#include "message_source.h" namespace display { @@ -35,7 +36,7 @@ namespace display { for (const auto& entry: memoryInstances) { combo->addItem(QString::fromStdString(entry)); } - combo->addItem("null"); + combo->addItem(QMESSAGE("msg_dialog_memory_default")); connect(combo, QOverload::of(&QComboBox::currentIndexChanged), [this](int index) { if(index == memoryInstances.size()) { diff --git a/comdel/display/dialog/name_dialog.cpp b/comdel/display/dialog/name_dialog.cpp index a77fbf7..44764b5 100644 --- a/comdel/display/dialog/name_dialog.cpp +++ b/comdel/display/dialog/name_dialog.cpp @@ -1,15 +1,16 @@ #include #include "name_dialog.h" +#include "message_source.h" namespace display { NameDialog::NameDialog(std::string currentName, std::set &names) - : GenericDialog("Izmjeni ime", "Izmjeni"), currentName(currentName), usedNames(names) { + : GenericDialog("msg_dialog_name_update"), currentName(currentName), usedNames(names) { usedNames.erase(currentName); auto *contentLayout = new QVBoxLayout(); - contentLayout->addWidget(new QLabel("Izmjeni ime", this)); + contentLayout->addWidget(new QLabel(QMESSAGE("msg_dialog_name_update"), this)); edit = new QLineEdit(this); edit->insert(currentName.c_str()); diff --git a/comdel/display/dialog/success_dialog.cpp b/comdel/display/dialog/success_dialog.cpp index bae5529..c1d6d8a 100644 --- a/comdel/display/dialog/success_dialog.cpp +++ b/comdel/display/dialog/success_dialog.cpp @@ -2,14 +2,16 @@ #include #include #include "success_dialog.h" +#include "message_source.h" namespace display { - SuccessDialog::SuccessDialog(std::string message, std::string action) { + SuccessDialog::SuccessDialog(std::string message) { setLayout(new QVBoxLayout()); + setWindowTitle(QMESSAGE("msg_dialog_success_title")); layout()->addWidget(new QLabel(QString::fromStdString(message))); - auto button = new QPushButton(QString::fromStdString(action)); + auto button = new QPushButton(QMESSAGE("msg_dialog_actions_ok")); connect(button, &QPushButton::clicked, [this]() {accept();}); layout()->addWidget(button); } diff --git a/comdel/display/dialog/success_dialog.h b/comdel/display/dialog/success_dialog.h index 0f12386..f2a81eb 100644 --- a/comdel/display/dialog/success_dialog.h +++ b/comdel/display/dialog/success_dialog.h @@ -11,7 +11,7 @@ namespace display { class SuccessDialog: public QDialog { public: - explicit SuccessDialog(std::string message, std::string action = "Ok"); + explicit SuccessDialog(std::string message); }; } // display diff --git a/comdel/display/dialog/warning_dialog.cpp b/comdel/display/dialog/warning_dialog.cpp index 4405d79..4ef9130 100644 --- a/comdel/display/dialog/warning_dialog.cpp +++ b/comdel/display/dialog/warning_dialog.cpp @@ -5,7 +5,7 @@ namespace display { WarningDialog::WarningDialog(domain::ValidationError error) - : GenericDialog("Upozorenje", "U redu") { + : GenericDialog("msg_dialog_warning_title", "msg_dialog_actions_ok") { auto contentLayout = new QVBoxLayout(); content->setLayout(contentLayout); diff --git a/comdel/display/library_display.cpp b/comdel/display/library_display.cpp index ffa4563..699cc12 100644 --- a/comdel/display/library_display.cpp +++ b/comdel/display/library_display.cpp @@ -1,4 +1,5 @@ #include "library_display.h" +#include "message_source.h" #include #include @@ -15,16 +16,23 @@ namespace display { busList = new LibraryList(this); layout->setContentsMargins(4, 4, 4, 4); - layout->addWidget(new QLabel("Komponente:")); + + componentsLabel = new QLabel(QMESSAGE("msg_sidebar_components")); + busLabel = new QLabel(QMESSAGE("msg_sidebar_busses")); + + layout->addWidget(componentsLabel); layout->addWidget(componentList, 1); layout->addSpacing(8); - layout->addWidget(new QLabel("Sabirnice:")); + layout->addWidget(busLabel); layout->addWidget(busList, 1); } void Library::refreshContent() { library = Application::instance()->getLibrary(); + componentsLabel->setText(QMESSAGE("msg_sidebar_components")); + busLabel->setText(QMESSAGE("msg_sidebar_busses")); + componentList->clear(); busList->clear(); diff --git a/comdel/display/library_display.h b/comdel/display/library_display.h index 5033935..a4c5b3d 100644 --- a/comdel/display/library_display.h +++ b/comdel/display/library_display.h @@ -5,6 +5,7 @@ #include #include +#include #include "library_list.h" namespace display { @@ -21,6 +22,8 @@ namespace display { LibraryList *componentList; LibraryList *busList; + QLabel *componentsLabel; + QLabel *busLabel; }; } // namespace display diff --git a/comdel/display/schema_display.cpp b/comdel/display/schema_display.cpp index 2c98709..6e61f8d 100644 --- a/comdel/display/schema_display.cpp +++ b/comdel/display/schema_display.cpp @@ -8,6 +8,8 @@ #include #include #include +#include "message_source.h" + namespace display { @@ -183,7 +185,7 @@ namespace display { if (rect.contains(endPoint)) { auto name = components[pinInstance.component]->getComponentInstance()->component.getName(); - auto con = library->getConnection({instance->component.getName(), connection.pin.value().getName()}, + auto con = library->getConnection({instance->component.getName(), context.pin->getPin().getName()}, {name, pinInstance.pin}); if (con.has_value()) { auto busInstance = Application::instance()->addBus(library->getBus(con->getBus()), 0, 0); @@ -199,12 +201,22 @@ namespace display { return; } - auto conInstance = std::make_shared(instance, - components[pinInstance.component]->getComponentInstance().get(), - attributes, busInstance.get(), - *con); + std::shared_ptr conInstance = nullptr; + if(con->getComponent() == domain::ConnectionComponent{instance->component.getName(), context.pin->getPin().getName()}) { + conInstance = std::make_shared(instance, + components[pinInstance.component]->getComponentInstance().get(), + attributes, busInstance.get(), + *con); + } else { + conInstance = std::make_shared(components[pinInstance.component]->getComponentInstance().get(), + instance, + attributes, busInstance.get(), + *con); + } + schema->connections.push_back(conInstance); + if (conInstance != nullptr) { auto c = new display::DirectConnection(conInstance.get(), components[conInstance->instance->name], @@ -276,13 +288,14 @@ namespace display { 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("Postavi memoriju", "Postavi", &attribute, schema->componentInstances); + auto dialog = new MemoryDialog("msg_dialog_memory_set", "msg_dialog_actions_set", &attribute, schema->componentInstances); if(dialog->exec() == QDialog::Rejected) { // if any dialog isn't set, whole creation is rejected return {}; } } else { - auto dialog = new AttributeDialog("Postavi " + attribute.attribute.getDisplayName(), "Postavi", &attribute); + std::map params = {{"attribute", attribute.attribute.getDisplayName()}}; + auto dialog = new AttributeDialog(MESSAGE_PARAM("msg_dialog_attribute_set", params), "msg_dialog_actions_set", &attribute); if(dialog->exec() == QDialog::Rejected) { // if any dialog isn't set, whole creation is rejected return {}; @@ -301,7 +314,7 @@ namespace display { instanceAttributes.emplace_back(attr.getName(), attr.getDefault(), attr); } - auto dialog = new display::SingleAutomaticDialog("Postavi sabirnicu", "Postavi", instanceAttributes); + auto dialog = new display::SingleAutomaticDialog("msg_dialog_sa_pin_set", "msg_dialog_actions_set", instanceAttributes); if(dialog->exec() == QDialog::Rejected) { // if dialog is rejected, whole creation is rejected return {}; diff --git a/comdel/domain/comdel_generator.cpp b/comdel/domain/comdel_generator.cpp index 1096058..ef9fc0e 100644 --- a/comdel/domain/comdel_generator.cpp +++ b/comdel/domain/comdel_generator.cpp @@ -3,6 +3,7 @@ // #include +#include #include "comdel_generator.h" namespace domain { @@ -148,12 +149,9 @@ namespace domain { for (auto &bus: schema->busInstances) { buffer << "\t//" << bus->name << std::endl; for (auto &wire: bus->bus.getWires()) { - std::string name = wire.getName(); - if (usedNames.count(wire.getName()) > 0) { - name = bus->name + "__" + wire.getName(); - } - if (wire.isHidden()) { - name = "--" + name; + auto name = (wire.isHidden() ? "--" : "") + wire.getName(); + if (usedNames.count(name) > 0) { + name = (wire.isHidden() ? "--" : "") + bus->name + "__" + wire.getName(); } usedNames.insert(name); usedMappings.insert(std::make_pair(bus->name + "." + wire.getName(), name)); @@ -203,6 +201,9 @@ namespace domain { map &wireNames, stringstream &buffer); + void generateSingleAutomaticPin(std::vector connections, ComponentInstance *instance, string pin, + map &wireNames, stringstream &buffer); + void generateComponent(Schema *schema, map &wires, ostream &buffer, shared_ptr &component); @@ -250,37 +251,42 @@ namespace domain { for (auto &pin: component->component.getPins()) { if (schema->hasConnection(component->name, pin.getName())) { - auto conn = schema->getConnection(component->name, pin.getName()); - auto busConn = dynamic_cast(conn); - if (busConn != nullptr) { - for (auto wire: busConn->connection.getWires()) { - if (wire.isType(Value::ATTRIBUTE_REFERENCE)) { - auto attribute = busConn->getAttribute(wire.asReference()); - if (wire.isType(Value::WIRE_REFERENCE)) { - tempOutput << wires[busConn->bus->name + "." + attribute.value.asReference()] << ", "; - } else if (wire.isType(Value::NIL)) { - tempOutput << "*, "; + auto connections = schema->getConnections(component->name, pin.getName()); + if(connections.size() == 1) { + auto conn = connections[0]; + auto busConn = dynamic_cast(conn); + if (busConn != nullptr) { + for (auto wire: busConn->connection.getWires()) { + if (wire.isType(Value::ATTRIBUTE_REFERENCE)) { + auto attribute = busConn->getAttribute(wire.asReference()); + if (wire.isType(Value::WIRE_REFERENCE)) { + tempOutput << wires[busConn->bus->name + "." + attribute.value.asReference()] << ", "; + } else if (wire.isType(Value::NIL)) { + tempOutput << "*, "; + } else { + tempOutput << attribute.value.stringify() << ", "; + } } else { - tempOutput << attribute.value.stringify() << ", "; - } - } else { - if (wire.isType(Value::WIRE_REFERENCE)) { - tempOutput << wires[busConn->bus->name + "." + wire.asReference()] << ", "; - } else if (wire.isType(Value::NIL)) { - tempOutput << "*, "; - } else { - tempOutput << wire.stringify() << ", "; + if (wire.isType(Value::WIRE_REFERENCE)) { + tempOutput << wires[busConn->bus->name + "." + wire.asReference()] << ", "; + } else if (wire.isType(Value::NIL)) { + tempOutput << "*, "; + } else { + tempOutput << wire.stringify() << ", "; + } } } } - } - auto dirConn = dynamic_cast(conn); - if (dirConn != nullptr) { - if (dirConn->bus->bus.getType() == Bus::AUTOMATIC) { - generateAutomaticPin(dirConn, component->name, pin.getName(), wires, tempOutput); - } else { - generateSingleAutomaticPin(dirConn, component->name, pin.getName(), wires, tempOutput); + auto dirConn = dynamic_cast(conn); + if (dirConn != nullptr) { + if (dirConn->bus->bus.getType() == Bus::AUTOMATIC) { + generateAutomaticPin(dirConn, component->name, pin.getName(), wires, tempOutput); + } else { + generateSingleAutomaticPin(dirConn, component->name, pin.getName(), wires, tempOutput); + } } + } else { + generateSingleAutomaticPin(connections, component.get(), pin.getName(), wires, tempOutput); } } else { // if no connection exists than defaults must exist @@ -341,8 +347,30 @@ namespace domain { } } - void - generateAutomaticPin(DirectConnectionInstance *connection, string name, string pin, map wireNames, + void generateSingleAutomaticPin(std::vector connections, ComponentInstance *instance, string pin, + map &wireNames, stringstream &buffer) { + std::map selectedValues; + for(auto conn: connections) { + auto dirConn = dynamic_cast(conn); + auto index = dirConn->getSelected(ConnectionComponent{instance->name, pin}); + selectedValues.insert(std::make_pair(index, dirConn->bus)); + } + + std::vector defaultWires = instance->component.getPin(pin).getWires().value(); + + for (int i=0; i 0) { + auto wireName = selectedValues[i]->name + "." + selectedValues[i]->bus.getWires()[0].getName(); + buffer << wireNames[wireName] << ", "; + } else if(defaultWires[i].isType(Value::NIL)) { + buffer << "*, "; + } else { + buffer << defaultWires[i].stringify() << ", "; + } + } + } + + void generateAutomaticPin(DirectConnectionInstance *connection, string name, string pin, map wireNames, stringstream &buffer) { std::vector wires; if (connection->instance->name == name && connection->connection.getComponent().pin == pin) { diff --git a/comdel/domain/comdel_validator.cpp b/comdel/domain/comdel_validator.cpp index 64dda6b..f4c05d3 100644 --- a/comdel/domain/comdel_validator.cpp +++ b/comdel/domain/comdel_validator.cpp @@ -1,6 +1,7 @@ #include #include "comdel_validator.h" #include "library.h" +#include "message_source.h" namespace domain { @@ -30,24 +31,20 @@ namespace domain { for (auto comp: library.getComponents()) { int count = instanceMap[comp.getName()]; - context.attributes["componentName"] = Value::fromString(comp.getName()); + context.attributes["componentName"] = Value::fromString(comp.getDisplayName()); context.attributes["min"] = Value::fromInt(comp.getCount().first); context.attributes["max"] = Value::fromInt(comp.getCount().second); context.attributes["count"] = Value::fromInt(count); if (count < comp.getCount().first) { - auto message = populateMessage( - "Nedovoljno instanci komponente '{componentName}' potrebno barem {min}, pronađeno {count}", - context); + auto message = MESSAGE_PARAM("msg_validators_component_min_count", context.map()); errors.emplace_back(Action::ERROR, message); } else if (count > comp.getCount().second) { - auto message = populateMessage( - "Previše insanci komponente '{componentName}' dozvoljeno najviše {max}, pronađeno {count}", context); + auto message = MESSAGE_PARAM("msg_validators_component_max_count", context.map()); errors.emplace_back(Action::ERROR, message); } } - // validate bus instance count std::map busInstanceMap; for (auto &inst: schema.busInstances) { @@ -57,18 +54,16 @@ namespace domain { for (auto bus: library.getBuses()) { int count = busInstanceMap[bus.getName()]; - context.attributes["busName"] = Value::fromString(bus.getName()); + context.attributes["busName"] = Value::fromString(bus.getDisplayName()); context.attributes["min"] = Value::fromInt(bus.getCount().first); context.attributes["max"] = Value::fromInt(bus.getCount().second); context.attributes["count"] = Value::fromInt(count); if (count < bus.getCount().first) { - auto message = populateMessage( - "Nedovoljno instanci sabirnice '{busName}' potrebna barem jedna {min}, pronađeno {count}", context); + auto message = MESSAGE_PARAM("msg_validators_bus_min_count", context.map()); errors.emplace_back(Action::ERROR, message); } else if (count > bus.getCount().second) { - auto message = populateMessage( - "Previše instanci sabirnice '{busName}' dozvoljeno najviše {max}, pronađeno {count}", context); + auto message = MESSAGE_PARAM("msg_validators_bus_max_count", context.map()); errors.emplace_back(Action::ERROR, message); } } @@ -85,9 +80,8 @@ namespace domain { if (pin.getConnection().has_value()) { if (!connectionExists(schema, inst, pin)) { context.instance = inst.get(); - context.attributes["instanceName"] = Value::fromString(inst->name); - auto message = populateMessage(pin.getConnection().value(), context); - errors.emplace_back(Action::ERROR, message); + auto message = MESSAGE_PARAM(pin.getConnection().value(), context.map()); + errors.emplace_back(context.instance, nullptr, Action::ERROR, message); } } } @@ -147,7 +141,7 @@ namespace domain { ruleContext.function = validators; auto action = rule.evaluate(ruleContext); if (action) { - std::string message = this->populateMessage(action->getMessage(), context); + auto message = MESSAGE_PARAM(action->getMessage(), context.map()); return ValidationError{context.instance, context.attribute, action->getType(), message}; } return nullopt; @@ -172,7 +166,7 @@ namespace domain { 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); + auto message = MESSAGE_PARAM("msg_validators_memory_not_found", context.map()); errors.emplace_back(component.get(), nullptr, Action::ERROR, message); } } @@ -191,9 +185,8 @@ namespace domain { for(auto& component: schema.componentInstances) { if(names.find(component->name) != names.end()) { - context.attributes["componentName"] = Value::fromString(component->name); - auto message = populateMessage( - "Pronađeno više instanci sa imenom '{componentName}'", context); + context.instance = component.get(); + auto message = MESSAGE_PARAM("msg_validators_duplicates_found", context.map()); errors.emplace_back(Action::ERROR, message); } names.insert(component->name); @@ -201,26 +194,6 @@ namespace domain { return errors; } - - std::string ComdelValidator::populateMessage(string source, ValidationContext context) { - for (auto &[key, value]: context.attributes) { - source = replacePlaceholder(source, key, value); - } - return source; - } - - string ComdelValidator::replacePlaceholder(string source, string key, Value value) { - key = "{" + key + "}"; - auto placeholderValue = value.string(); - - auto found = source.find(key); - while (found != string::npos) { - source.replace(found, key.length(), placeholderValue); - found = source.find(key); - } - return source; - } - bool ComdelValidator::connectionExists(Schema &schema, shared_ptr &component, Pin &pin) { for (auto conn: schema.connections) { auto busConnection = dynamic_cast(conn.get()); @@ -233,13 +206,9 @@ namespace domain { auto directConnection = dynamic_cast(conn.get()); if (directConnection != nullptr) { - if (directConnection->instance->name == component->name && - directConnection->connection.getComponent().pin == pin.getName()) { - return true; - } - if (directConnection->secondInstance->name == component->name && - directConnection->connection.getSecondComponent()->pin == pin.getName()) { - return true; + if ((directConnection->instance->name == component->name && directConnection->connection.getComponent().pin == pin.getName()) || + (directConnection->secondInstance->name == component->name) && directConnection->connection.getSecondComponent()->pin == pin.getName()) { + return directConnection->connection.isConnecting({component->component.getName(), pin.getName()}); } } } @@ -252,4 +221,20 @@ namespace domain { this->validators.insert(std::make_pair(validator->getName(), validator)); } } + + std::map ValidationContext::map() { + std::map parametars; + if(instance != nullptr) { + parametars["instanceName"] = instance->name; + parametars["componentName"] = instance->component.getDisplayName(); + } + if(attribute != nullptr) { + parametars["attributeName"] = attribute->name; + parametars["attribute"] = attribute->value.string(); + } + for(auto [key, value]: attributes) { + parametars[key] = value.string(); + } + return parametars; + } } \ No newline at end of file diff --git a/comdel/domain/comdel_validator.h b/comdel/domain/comdel_validator.h index 2b9cdb3..9e97f33 100644 --- a/comdel/domain/comdel_validator.h +++ b/comdel/domain/comdel_validator.h @@ -23,6 +23,8 @@ namespace domain { InstanceAttribute *attribute; std::map addressSpaces; std::map attributes; + + std::map map(); }; class ComdelValidator { @@ -41,18 +43,13 @@ namespace domain { std::vector validateInstanceCount(Schema &schema, Library &library, ValidationContext context); - std::vector - validatePinConnections(Schema &schema, Library &library, ValidationContext context); + std::vector validatePinConnections(Schema &schema, Library &library, ValidationContext context); ComdelValidator(std::vector validators); private: std::map validators; - std::string populateMessage(string message, ValidationContext context); - - string replacePlaceholder(string message, const string name, Value value); - bool connectionExists(Schema &schema, shared_ptr &component, Pin &pin); }; diff --git a/comdel/domain/connection_instance.cpp b/comdel/domain/connection_instance.cpp index 56dbced..e1bd1c1 100644 --- a/comdel/domain/connection_instance.cpp +++ b/comdel/domain/connection_instance.cpp @@ -26,4 +26,23 @@ namespace domain { Connection connection) : ConnectionInstance(instance, attributes, connection), secondInstance(secondInstance), bus(bus) {} + int DirectConnectionInstance::getSelected(ConnectionComponent conn) { + if(this->instance->name == conn.component) { + auto selected = attributes[0].value.asString(); + for(int i=0; isize(); i++) { + if(connection.getSecondWires().value()[i].isType(Value::STRING) && connection.getSecondWires().value()[i].asString() == selected) { + return i; + } + } + } + return -1; + } + } // namespace domain diff --git a/comdel/domain/connection_instance.h b/comdel/domain/connection_instance.h index e2f5e8d..3351051 100644 --- a/comdel/domain/connection_instance.h +++ b/comdel/domain/connection_instance.h @@ -41,6 +41,8 @@ namespace domain { DirectConnectionInstance(ComponentInstance *instance, ComponentInstance *secondsInstance, std::vector attributes, BusInstance *bus, Connection connection); + + int getSelected(ConnectionComponent connection); }; diff --git a/comdel/domain/display.cpp b/comdel/domain/display.cpp index 7b0327d..4470180 100644 --- a/comdel/domain/display.cpp +++ b/comdel/domain/display.cpp @@ -51,6 +51,21 @@ namespace domain { buffer << "\t\t}\n\n"; } + void ui::Ellipse::render(QGraphicsItemGroup *group) { + auto ellipse = new QGraphicsEllipseItem(x, y, w, h); + ellipse->setPen(QPen(config.lineColor)); + ellipse->setBrush(QBrush(config.fillColor)); + group->addToGroup(ellipse); + } + + void ui::Ellipse::comdel(std::ostream &buffer, int x, int y) { + buffer << "\t\tellipse {\n"; + buffer << "\t\t\tx: " << (this->x + x) << "; y: " << (this->y + y) << ";\n"; + buffer << "\t\t\tw: " << w << "; h: " << h << ";\n"; + buffer << "\t\t}\n\n"; + } + + void ui::Line::render(QGraphicsItemGroup *group) { auto line = new QGraphicsLineItem(x1, y1, x2, y2); line->setPen(QPen(config.lineColor)); @@ -205,6 +220,7 @@ namespace domain { if (pin) pin->render(group); if (bus) bus->render(group, size); if (text) text->render(group, context); + if (ellipse) ellipse->render(group); } void ui::Item::comdel(std::ostream &buffer, int x, int y, int size) { diff --git a/comdel/domain/display.h b/comdel/domain/display.h index 9d35269..4810c8d 100644 --- a/comdel/domain/display.h +++ b/comdel/domain/display.h @@ -58,6 +58,19 @@ namespace domain { }; + class Ellipse { + public: + int x, y, w, h; + DisplayConfig config; + + Ellipse(int x, int y, int w, int h, DisplayConfig config) : x(x), y(y), w(w), h(h), config(config) {} + + void render(QGraphicsItemGroup *group); + + void comdel(std::ostream &buffer, int x, int y); + + }; + class Line { public: int x1, y1, x2, y2; @@ -108,6 +121,8 @@ namespace domain { Pin(int x, int y, int w, int h, PinOrientation orientation, PinType pinType, DisplayConfig config) : x(x), y(y), w(w), h(h), orientation(orientation), pinType(pinType), config(config) {} + Pin(): config(DisplayConfig(Color(), Color())) {}; + public: void render(QGraphicsItemGroup *group); @@ -130,6 +145,7 @@ namespace domain { std::optional pin = std::nullopt; std::optional bus = std::nullopt; std::optional text = std::nullopt; + std::optional ellipse = std::nullopt; void render(QGraphicsItemGroup *group, ui::DisplayContext context, int size = 0); void comdel(std::ostream &buffer, int x, int y, int size = 0); diff --git a/comdel/domain/schema.cpp b/comdel/domain/schema.cpp index 365ecb4..e9f5e2b 100644 --- a/comdel/domain/schema.cpp +++ b/comdel/domain/schema.cpp @@ -57,12 +57,10 @@ namespace domain { 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); + entries.push_back({ConnectionEntry::BUS, bus.get(), nullopt, nullopt, conn}); } } } else { @@ -92,19 +90,16 @@ namespace domain { for(auto& conn: this->connections) { if(conn->connection == entry.connection) { if(bus.getType() == Bus::REGULAR) { - if(entry.busInstance.value()->bus.getName() == conn->connection.getBus()) { + auto busConnection = dynamic_cast(conn.get()); + if(busConnection->instance == instance && busConnection->bus == entry.busInstance.value()) { return true; } } else { - auto *directInstance = dynamic_cast(conn.get()); - ComponentInstance* secondInstance; - if(directInstance->instance == instance) { - secondInstance = directInstance->secondInstance; - } else { - secondInstance = directInstance->instance; + auto directConnection = dynamic_cast(conn.get()); + if(directConnection->instance == instance && directConnection->secondInstance == entry.componentInstance.value() || + directConnection->secondInstance == instance && directConnection->instance == entry.componentInstance.value()) { + return true; } - - return entry.componentInstance == secondInstance; } } } @@ -113,8 +108,8 @@ namespace domain { entries.end() ); } - return entries; + } } // namespace domain diff --git a/comdel/domain/schema_creator.cpp b/comdel/domain/schema_creator.cpp index 73b210a..c2881be 100644 --- a/comdel/domain/schema_creator.cpp +++ b/comdel/domain/schema_creator.cpp @@ -345,10 +345,12 @@ namespace domain { if (!node.second.has_value()) { errors.emplace_back(node.span, "missing second component"); + return nullopt; } ConnectionComponent second{node.second->component.value, node.second->pin.value}; + auto firstComponentInstance = getComponentPin(first.component, first.pin); if (!firstComponentInstance) { errors.emplace_back(node.span, "pin does not exist"); @@ -405,7 +407,10 @@ namespace domain { } } - + if(node.secondWires->empty()) { + errors.emplace_back(node.span, "missing second @wires definition"); + return nullopt; + } std::vector secondWires; for (auto &secondWire: *node.secondWires) { if (secondWire.is(ValueNode::NIL)) { @@ -654,6 +659,13 @@ namespace domain { h = readInt(errors, item, "h"); text = readString(errors, item, "text"); displayItem.text = ui::Text(x, y, w, h, text, color); + } else if (type == "ellipse") { + long long int x, y, w, h; + x = readInt(errors, item, "x"); + y = readInt(errors, item, "y"); + w = readInt(errors, item, "w"); + h = readInt(errors, item, "h"); + displayItem.ellipse = ui::Ellipse(x, y, w, h, {lineColor, fillColor}); } else if (type == "rect") { long long int x, y, w, h; x = readInt(errors, item, "x"); diff --git a/comdel/domain/value.cpp b/comdel/domain/value.cpp index ab18620..5e458d1 100644 --- a/comdel/domain/value.cpp +++ b/comdel/domain/value.cpp @@ -92,29 +92,33 @@ namespace domain { void Value::setInt(long long value) { if (isType(Value::INT)) { this->intValue = value; + } else { + throw std::exception(); } - throw std::exception(); } void Value::setString(std::string value) { if (isType(Value::STRING)) { this->stringValue = value; + } else { + throw std::exception(); } - throw std::exception(); } void Value::setBool(bool value) { if (isType(Value::BOOL)) { this->boolValue = value; + } else { + throw std::exception(); } - throw std::exception(); } void Value::setReference(std::string value) { if (isType(Value::WIRE_REFERENCE)) { this->reference = value; + } else { + throw std::exception(); } - throw std::exception(); } diff --git a/examples/arm/arm_library.csl b/examples/arm/arm_library.csl new file mode 100644 index 0000000..1e61f9a --- /dev/null +++ b/examples/arm/arm_library.csl @@ -0,0 +1,1107 @@ +@name "Jednostavni ARM" +@info "Primjer ARM biblioteke" +@directory "." +@header "set load_performs_init;" +@componentHeader " clock 100MHz;" + +// adresni prostori +@address adresniProstor(0,0xFFFFFFFF) + +/******************************************************************* + * KOMPONENTE * + ***************************************************************** */ + +@component Memory64KiB memory { + @displayName "Memorija" + @instanceName memorija + @tooltip "Memorija" + @count (1,1) + @source "memory.comdel" + + @display { + rect { + x:0; y:0; w: 80; h: 80; + fillColor: #ffffff; + } + text { + x:0; y:12; w: 80; h: 80; + text: "Memory 64 KB"; + } + } + + @pin ahbPin inOut { + @tooltip "Pin za spajanje na AHB" + @connection "COMDEL se ne može stvoriti. Memorija nije spojena na AHB" + @display { + pin { + x: 0; y: 0; w: 10; h: 10; + type: "in"; + orientation: "top"; + } + } + } +} + +@component DMAC_simple { + @instanceName dmac + @displayName "DMAC" + @count (0, 1) + @source "dmac.comdel" + @tooltip "DMAC" + + @display { + + // title and border + rect { x: 0; y: 20; w: 110; h: 85; fillColor: #ffffff; } + text { x: 0; y: 21; w: 110; h: 15; text: "DMAC"; } + + rect { x: 30; y: 0; w: 10; h: 19; fillColor: #aaaaaa; lineColor: #aaaaaa; } + text { x: 27; y: 4; w: 10; h: 19; text: "S"; } + rect { x: 70; y: 0; w: 10; h: 19; fillColor: #cccccc; lineColor: #cccccc; } + text { x: 67; y: 4; w: 10; h: 19; text: "M"; } + + // transfer size counter register + text { x: 10; y: 40; w: 24; h: 14; text: "CNT:";} + rect { x: 8; y: 56; w: 30; h: 14;} + text { x: 6; y: 53; w: 26; h: 14; text: "4096";} + + // hbusreq, hgrant and intr labels and pins + text {x: 50; y: 40; w: 45; h: 14; text: "HBUSREQ";} + text {x: 50; y: 57; w: 45; h: 14; text: "HGRANT";} + text {x: 50; y: 73; w: 35; h: 14; text: "INTR";} + } + + @pin ahbSlavePin in { + @tooltip "Slave pin za spajanje na AHB" + @connection "COMDEL se ne može stvoriti. DMAC S nije spojen na AHB" + @display { + pin { + x: 30; y: 0; w: 10; h: 10; + type: "in"; + orientation: "top"; + } + } + } + + @pin ahbMasterPin in { + @tooltip "Master pin za spajanje na AHB" + @connection "COMDEL se ne može stvoriti. DMAC M nije spojen na AHB" + @display { + pin { + x: 70; y: 0; w: 10; h: 10; + type: "in"; + orientation: "top"; + } + } + } + + @pin apbPin in { + @tooltip "Pin za spajanje na APB" + @connection "COMDEL se ne može stvoriti. DMAC nije spojen na APB" + @display { + pin { + x: 100; y: 20; w: 10; h: 10; + type: "in"; + orientation: "top"; + } + } + } + + @pin dev0 out { + @tooltip "Pin za spajanje uređaja 0" + @display { + pin { + x: 110; y: 30; w: 10; h: 10; + type: "out"; + orientation: "right"; + } + } + @wires {0, null} + } + @pin dev1 out { + @tooltip "Pin za spajanje uređaja 1" + @display { + pin { + x: 110; y: 45; w: 10; h: 10; + type: "out"; + orientation: "right"; + } + } + @wires {0, null} + } + @pin dev2 out { + @tooltip "Pin za spajanje uređaja 2" + @display { + pin { + x: 110; y: 60; w: 10; h: 10; + type: "out"; + orientation: "right"; + } + } + @wires {0, null} + } + @pin dev3 out { + @tooltip "Pin za spajanje uređaja 3" + @display { + pin { + x: 110; y: 75; w: 10; h: 10; + type: "out"; + orientation: "right"; + } + } + @wires {0, null} + } +} + +@component UI_UNIT { + @displayName "UI uređaj" + @instanceName ui_unit + @count (0, 4) + @source "ui_unit.comdel" + @tooltip "UI uređaj" + + @attribute type int default 0 { + @displayName "Vrsta veze" + @popup automatic { + @title "Vrsta veze" + @text "Izaberite vrstu veze" + @enumerated { + "Ulaz" = 1, + "Izlaz" = 0, + } + } + } + @attribute name string default "" { + @displayName "Ime uređaja" + @popup automatic { + @title "Ime uređaja" + @text "Izaberite ime uređaja" + } + } + @attribute width int default 8 { + @displayName "Širina sabirnice" + } + @attribute duration int default 40 { + @displayName "Trajanje" + } + + @display { + rect { x: 0; y: 0; w: 60; h:60; } + text { x: 15; y: 20; w: 45; h:40; text: "{name}";} + } + + @pin apbPin in { + @tooltip "Pin za spajanje na APB" + @connection "COMDEL se ne može stvoriti. UI_UNIT nije spojen na APB" + @display { + pin { + x: 25; y: 0; w: 10; h: 10; + type: "in"; + orientation: "top"; + } + } + } + @pin dmacPin out { + @tooltip "Pin za spajanje na DMAC" + @connection "COMDEL se ne može stvoriti. UI_UNIT nije spojen na DMAC" + @display { + pin { + x: 0; y: 25; w: 10; h: 10; + type: "in"; + orientation: "left"; + } + } + } +} + +@component interrupt_selector { + @instanceName interruptSelector + @count (0, 2) + @source "interrupt_selector.comdel" + @tooltip "Interrupt selector" + + @display { + rect { + x:0; y: 0; w:10; h:10; + lineColor: #000000; + fillColor: #0000ff; + } + } + + @pin apbPin in { + @tooltip "Pin za spajanje na APB" + @connection "COMDEL se ne može stvoriti. Selector nije spojena na APB" + @display { + pin { + x: 10; y: 0; w: 10; h: 10; + type: "in"; + orientation: "right"; + } + } + } + + @pin ahbPin in { + @tooltip "Pin za spajanje na AHB" + @connection "COMDEL se ne može stvoriti. Selector nije spojena na AHB" + @display { + pin { + x: -10; y: 0; w: 10; h: 10; + type: "in"; + orientation: "left"; + } + } + } + +} + +@component lcd8 { + @displayName "LCD ekran" + @instanceName lcd + @count (0, 4) + @source "lcd8.signal" + @tooltip "LCD ekran" + + @display { + rect { + x:0; y:0; w: 120; h:55; + } + text { + x:0; y:0; w:120; h:15; + text: "LCD"; + } + rect { + x: 10; y: 16; w: 100; h: 20; + fillColor: #CCCCCCFF; + } + // shiftable registers + rect { x: 12; y:40; w:12; h:12; } + rect { x: 24; y:40; w:12; h:12; } + rect { x: 36; y:40; w:12; h:12; } + rect { x: 48; y:40; w:12; h:12; } + rect { x: 60; y:40; w:12; h:12; } + rect { x: 72; y:40; w:12; h:12; } + rect { x: 84; y:40; w:12; h:12; } + rect { x: 96; y:40; w:12; h:12; } + } + + @pin gpioPin inOut { + @tooltip "Pin za spajanje na GPIO" + @connection "COMDEL se ne može stvoriti. LCD nije spojen na GPIO" + @display { + pin { + x: -10; y: 22; w: 10; h: 10; + type: "in"; + orientation: "left"; + } + } + } +} + +@component pushbutton { + @displayName "Push button" + @instanceName push_button + @count (0, 100) + @source "pushbutton.comdel" + @tooltip "Push button" + + @display { + line { x1: 0; y1: 0; x2: 8; y2: 10; } + + ellipse {x: 8; y: 8; w: 4; h: 4;} + ellipse {x: 22; y: 8; w: 4; h: 4; fillColor: #ffffff; } + + rect { + x: 0; y: 0; w: 34; h: 20; + fillColor: #00880055; + lineColor: #00000000; + } + } + + @pin gpioPin out { + @tooltip "Pin za spajanje na GPIO" + @connection "COMDEL se ne može stvariti. Button nije spojena na GPIO" + @display { + pin { + x: 12; y: -10; w: 10; h: 10; + type: "in"; + orientation: "top"; + } + } + @wires {null} + } +} + + +@component togglebutton { + @displayName "Toggle button" + @instanceName toggle_button + @count (0, 100) + @source "togglebutton.comdel" + @tooltip "Toggle button" + + @display { + line { x1: 0; y1: 0; x2: 8; y2: 10; } + + ellipse {x: 8; y: 8; w: 4; h: 4;} + ellipse {x: 22; y: 8; w: 4; h: 4; fillColor: #ffffff; } + + rect { + x: 0; y: 0; w: 34; h: 20; + fillColor: #00880055; + lineColor: #00000000; + } + } + + @pin gpioPin out { + @tooltip "Pin za spajanje na GPIO" + @connection "COMDEL se ne može stvariti. Button nije spojena na GPIO" + @display { + pin { + x: 12; y: -10; w: 10; h: 10; + type: "in"; + orientation: "top"; + } + } + @wires {null} + } +} + + +@component signal { + @instanceName signal + @count (1, 1) + @source "signal.comdel" + @tooltip "Signal" + + @display { + rect { + x:0; y:10; w:10; h:10; + lineColor: #000000; + fillColor: #0000ff; + } + } + + @pin apbPin in { + @tooltip "Pin za spajanje na APB" + @connection "COMDEL se ne može stvariti. Signal nije spojena na APB" + @display { + pin { + x: 0; y: 0; w: 10; h: 10; + type: "in"; + orientation: "top"; + } + } + } +} + +@component LED { + @instanceName led + @count(0, 1000) + @source "led.comdel" + @tooltip "LED žaruljica" + + @display { + rect { + x:0; y:10; w:10; h:10; + lineColor: #000000; + fillColor: #888888; + } + } + + @attribute onColor string default "green" { + @displayName "boja" + @popup automatic { + @title "Boja LED žaruljice" + @text "Odaberite boju LED žaruljice" + @enumerated { + "Zelena" = "green", + "Žuta" = "yellow", + "Crvena" = "red" + } + } + } + + @pin gpioPin in { + @tooltip "Pin za spajanje na GPIO" + @connection "COMDEL se ne može stvariti. LED nije spojena na GPIO" + @display { + pin { + x: 0; y: 0; w: 10; h: 10; + type: "in"; + orientation: "top"; + } + } + @wires {null} + } +} + +@component GPIO { + @instanceName gpio + @tooltip "GPIO" + @count (0, 2) + @source "gpio.comdel" + + @display { + rect { + x: 0; y: 0; w: 80; h: 100; + fillColor: #ffffff; + } + text { + x: 10; y: 36; w: 80; h: 100; + text: "{title}"; + } + // PORT A + rect { + x: 10; y: 14; w: 60; h: 14; + } + text { + x: 10; y: 11; w: 60; h: 14; + text: "0000 0000"; + } + + // PORT B + rect { + x: 10; y: 73; w: 60; h: 14; + } + text { + x: 10; y: 70; w: 60; h: 14; + text: "0000 0000"; + } + } + + @attribute title string default "GPIO 1" { + @displayName "GPIO ime" + @popup automatic { + @title "Izmjeni ime" + @text "Postavi novo ime" + } + } + + @pin apbPin inOut { + @tooltip "Pin za spajanje na APB" + @connection "COMDEL se ne može stvoriti. GPIO nije spojen na APB" + @display { + pin { + x: 0; y: 40; w: 10; h: 10; + type: "in"; + orientation: "left"; + fillColor: #3333ff; + } + } + } + + @pin portA out { + @tooltip "Port A" + @display { + pin { + x: 70; y: 16; w: 10; h: 10; + type: "in"; + orientation: "right"; + } + } + @wires {null, null, null, null, null, null, null, null} + } + + @pin portB in { + @tooltip "Port B" + @display { + pin { + x: 70; y: 75; w: 10; h: 10; + type: "in"; + orientation: "right"; + } + } + @wires {null, null, null, null, null, null, null, null} + } +} + +@component RTC_IO { + @displayName "RTC" + @instanceName rtc + @tooltip "RTC" + @count (0,1000) + @source "rtc.comdel" + + @display { + rect { + x: 0; y: 0; w: 40; h: 40; + fillColor: #ffffff; + } + text { + x: 0; y: 0; w: 40; h: 40; + text: "RTC"; + } + } + + @pin apbPin inOut { + @tooltip "Pin za spajanje na APB" + @connection "COMDEL se ne može stvoriti. Temperature nije spojen na APB" + @display { + pin { + x: 15; y: 30; w: 10; h: 10; + type: "in"; + orientation: "bottom"; + } + } + } +} + +@component Temperature { + @displayName "Termometar" + @instanceName temperature + @tooltip "Termometar" + @count (0,1000) + @source "temperature.comdel" + + @display { + rect { + x:0; y:0; w: 120; h: 30; + } + text { + x:0; y:0; w: 120; h: 30; + text: "Termometar"; + } + text { + x: 7; y: 13; w: 12; h: 15; + text: "--"; + } + text { + x: 100; y: 13; w: 12; h: 15; + text: "20"; + } + } + + @pin gpioPin inOut { + @tooltip "Pin za spajanje na GPIO" + @connection "COMDEL se ne može stvoriti. Termometar nije spojen na GPIO" + @display { + pin { + x: 15; y: 30; w: 10; h: 10; + type: "in"; + orientation: "bottom"; + } + } + } +} + +@component Decoder { + @displayName "Dekoder" + @instanceName decoder + @tooltip "Dekoder" + @count (1, 1) + @source "decoder.comdel" + + @display { + rect { + x: 0; y: 0; w: 50; h: 40; + } + text { + x: 0; y: 0; w: 50; h: 40; + text: "Dekoder"; + } + } + + @pin ahbPin in { + @tooltip "Pin za spajanje na AHB" + @connection "COMDEL se ne može stvoriti. Dekoder nije spojena na AHB" + @display { + pin { + x: 15; y: 30; w: 10; h: 10; + type: "in"; + orientation: "top"; + } + } + } +} + +@component Bridge { + @displayName "Bridge" + @instanceName bridge + @tooltip "Bridge" + @count (1, 1) + @source "bridge.comdel" + + @display { + rect { + x: 0; y: 0; w: 60; h: 40; + } + text { + x: 10; y: 10; w: 60; h: 40; + text: "Bridge"; + } + } + + @pin ahbPin in { + @tooltip "Pin za spajanje na AHB" + @connection "COMDEL se ne može stvoriti. Bridge nije spojena na AHB" + @display { + pin { + x: 0; y: 15; w: 10; h: 10; + type: "in"; + orientation: "left"; + } + } + } + + @pin apbPin in { + @tooltip "Pin za spajanje na APB" + @connection "COMDEL se ne može stvoriti. Bridge nije spojena na APB" + @display { + pin { + x: 50; y: 15; w: 10; h: 10; + type: "in"; + orientation: "right"; + } + } + } + + @pin connectionPin in { + @tooltip "Ulazni pin" + @display { + pin { + x: 25; y: 0; w: 10; h: 10; + type: "in"; + orientation: "top"; + } + } + @wires {1, 1, 1, 1, 1} + } +} + +@component ARM7tdmi processor { + @displayName "ARM" + @instanceName arm + @tooltip "ARM procesor" + @count (1, 1) + @source "arm7tdmi.comdel" + + @display { + rect { + x:0; y:0; w: 110; h: 110; + fillColor: #ffffff; + } + text { + x:0; y:0; w: 110; h: 110; + text: "ARM"; + } + rect { + x: 50; y: 111; w: 10; h: 19; + fillColor: #999999; + lineColor: #999999; + } + } + + @pin ahbPin inOut { + @tooltip "Pin za spajanje na AHB" + @connection "COMDEL se ne može stvoriti. Procesor nije spojen na AHB" + @display { + pin { + x: 50; y: 121; w: 10; h: 10; + type: "in"; + orientation: "bottom"; + } + } + } + + @pin dmacPin inOut { + @tooltip "Pin za spajanje na DMAC" + @display { + pin { + x: 100; y: 50; w: 10; h: 10; + type: "in"; + orientation: "right"; + } + } + @wires {null, null} + } +} + +/******************************************************************* + * SABIRNICE * + **************************************************************** */ +@bus AHB regular { + @instanceName ahb + @tooltip "Brza sabirnica" + @count (1,1) + @display { + bus { + x: 0; y: 0; + w: 249; h: 20; + orientation: "horizontal"; + fillColor: #999999; + lineColor: #999999; + } + } + @wires { + addr<32>, rdata<32>, wdata<32>, size<3>, write, ready wired_or, + // interupts and bus request + irq wired_or, fiq wired_or, nmreq wired_and, + // hsel_* + sel_mem hidden, sel_bridge, sel_dmac + // dmac + busreq, grant + } +} + +@bus APB regular { + @instanceName apb + @tooltip "Spora sabirnica" + @count (1,1) + @display { + bus { + x: 0; y: 0; + w: 329; h: 20; + orientation: "horizontal"; + fillColor: #999999; + lineColor: #999999; + } + } + @wires { + addr<32>, rdata<32>, wdata<32>, size<3> hidden, + enable, write, + sel_gpio_1, sel_gpio_2, sel_ui_in, sel_rtc, sel_ui_out, + rtc_int hidden, dmac_int hidden, impulse hidden + } +} + +// DMAC +@bus dmac_io automatic { + @instanceName arm_dmac + @count (0, 1000) + @wires {dmareq hidden, dmaack hidden} +} + +// gpio +@bus gpio_sa singleAutomatic { + @instanceName gpio_sa + @count (0, 1000) + @wires { + xp hidden + } +} + +@bus gpio_port automatic { + @instanceName gpio_port + @count (0, 1000) + @wires { + xp0 hidden, xp1 hidden, xp2 hidden, xp3 hidden, + xp4 hidden, xp5 hidden, xp6 hidden, xp7 hidden + } +} + + +/******************************************************************* + * PRAVILA POVEZIVANJA * + **************************************************************** */ + +@connection (Memory64KiB.ahbPin, AHB) { + @wires {addr, rdata, wdata, size, write, ready, sel_mem} +} + +@connection (interrupt_selector.apbPin, APB) { + @attribute interrupt wire default rtc_int { + @popup automatic { + @title "Interupt" + @text "Izaberite interupt" + @enumerated { + "DMAC" = dmac_int, + "RTC" = rtc_int + } + } + } + + @wires {interrupt} +} + +@connection (interrupt_selector.ahbPin, AHB) { + @wires {irq, fiq} +} + +@connection (ARM7tdmi.ahbPin, AHB) { + @wires {addr, rdata, wdata, size, write, ready, irq, fiq, nmreq, busreq, grant} +} + +@connection (Decoder.ahbPin, AHB) { + @wires {addr, nmreq, sel_mem, sel_bridge, sel_dmac, 1, 1} +} + +@connection (Bridge.ahbPin, AHB) { + @wires {addr, rdata, wdata, size, write, ready, sel_bridge} +} + +@connection (signal.apbPin, APB) { + @wires { impulse } +} + +@connection (Bridge.apbPin, APB) { + @wires { + addr, rdata, wdata, size, enable, write, + sel_gpio_1, sel_gpio_2, sel_rtc, sel_ui_in, sel_ui_out + } +} + +@connection (DMAC_simple.ahbSlavePin, AHB) { + @wires { + addr, rdata, wdata, size, write, ready, sel_dmac + } +} + +@connection (DMAC_simple.ahbMasterPin, AHB) { + @wires { + addr, rdata, wdata, size, write, ready, nmreq, busreq, grant + } +} + +@connection (DMAC_simple.apbPin, APB) { + @wires { + dmac_int + } +} + + +@connection (UI_UNIT.dmacPin, dmac_io, DMAC_simple.dev0) { + @wires { dmareq, dmaack } + @wires { dmareq, dmaack } +} +@connection (UI_UNIT.dmacPin, dmac_io, DMAC_simple.dev1) { + @wires { dmareq, dmaack } + @wires { dmareq, dmaack } +} +@connection (UI_UNIT.dmacPin, dmac_io, DMAC_simple.dev2) { + @wires { dmareq, dmaack } + @wires { dmareq, dmaack } +} +@connection (UI_UNIT.dmacPin, dmac_io, DMAC_simple.dev3) { + @wires { dmareq, dmaack } + @wires { dmareq, dmaack } +} + +@connection (UI_UNIT.apbPin, APB) { + @attribute intSelect wire default sel_ui_in { + @popup automatic { + @title "Interrupt" + @text "Izaberite interrupt" + @enumerated { + "INT 0" = sel_ui_in, + "INT 1" = sel_ui_out + } + } + } + @wires { + addr, rdata, wdata, size, enable, write, intSelect + } +} + +@connection (GPIO.apbPin, APB) { + @attribute gpioSelect wire default sel_gpio_1 { + @displayName "GPIO interupt" + @popup automatic { + @title "GPIO interupt" + @text "Izaberite GPIO interupt" + @enumerated { + "GPIO 1"= sel_gpio_1, + "GPIO 2"= sel_gpio_2 + } + } + } + + @wires {addr, rdata, wdata, enable, write, gpioSelect} +} + +@connection (GPIO.portA, gpio_sa, LED.gpioPin) { + @attribute gpioPortA string default "XP0" { + @popup automatic { + @title "Port A" + @text "Izaberite izlaz" + } + } + @attribute ledGpioPin string default "Ulaz" { + @popup automatic { + @title "LED žaruljica" + @text "Izaberite ulaz" + } + } + + @wires{"XP0", "XP1", "XP2", "XP3", "XP4", "XP5", "XP6", "XP7"} + @wires{"Ulaz"} +} +@connection (GPIO.portB, gpio_sa, LED.gpioPin) { + @attribute gpioPortB string default "XP0" { + @popup automatic { + @title "Port B" + @text "Izaberite izlaz" + } + } + @attribute ledGpioPin string default "Ulaz" { + @popup automatic { + @title "LED žaruljica" + @text "Izaberite ulaz" + } + } + + @wires{"XP0", "XP1", "XP2", "XP3", "XP4", "XP5", "XP6", "XP7"} + @wires{"Ulaz"} +} + + +@connection (GPIO.portA, gpio_sa, pushbutton.gpioPin) { + @attribute gpioPortA string default "XP0" { + @popup automatic { + @title "Port A" + @text "Izaberite ulaz" + } + } + @attribute buttonGpioPin string default "Izlaz" { + @popup automatic { + @title "Gumb" + @text "Izaberite izlaz" + } + } + + @wires{"XP0", "XP1", "XP2", "XP3", "XP4", "XP5", "XP6", "XP7"} + @wires{"Izlaz"} +} +@connection (GPIO.portB, gpio_sa, pushbutton.gpioPin) { + @attribute gpioPortB string default "XP0" { + @popup automatic { + @title "Port B" + @text "Izaberite ulaz" + } + } + @attribute buttonGpioPin string default "Izlaz" { + @popup automatic { + @title "Gumb" + @text "Izaberite izlaz" + } + } + + @wires{"XP0", "XP1", "XP2", "XP3", "XP4", "XP5", "XP6", "XP7"} + @wires{"Izlaz"} +} + + +@connection (GPIO.portA, gpio_sa, togglebutton.gpioPin) { + @attribute gpioPortA string default "XP0" { + @popup automatic { + @title "Port A" + @text "Izaberite ulaz" + } + } + @attribute buttonGpioPin string default "Izlaz" { + @popup automatic { + @title "Gumb" + @text "Izaberite izlaz" + } + } + + @wires{"XP0", "XP1", "XP2", "XP3", "XP4", "XP5", "XP6", "XP7"} + @wires{"Izlaz"} +} +@connection (GPIO.portB, gpio_sa, togglebutton.gpioPin) { + @attribute gpioPortB string default "XP0" { + @popup automatic { + @title "Port B" + @text "Izaberite ulaz" + } + } + @attribute buttonGpioPin string default "Izlaz" { + @popup automatic { + @title "Gumb" + @text "Izaberite izlaz" + } + } + + @wires{"XP0", "XP1", "XP2", "XP3", "XP4", "XP5", "XP6", "XP7"} + @wires{"Izlaz"} +} + + +@connection (GPIO.portA, gpio_port, Temperature.gpioPin) { + @wires {xp0, xp1, xp2, xp3, xp4, xp5, xp6, xp7} + @wires {xp0, xp1, xp2, xp3, xp4, xp5, xp6, xp7} +} +@connection (GPIO.portB, gpio_port, Temperature.gpioPin) { + @wires {xp0, xp1, xp2, xp3, xp4, xp5, xp6, xp7} + @wires {xp0, xp1, xp2, xp3, xp4, xp5, xp6, xp7} +} + + +@connection (GPIO.portA, gpio_port, lcd8.gpioPin) { + @wires {xp0, xp1, xp2, xp3, xp4, xp5, xp6, xp7} + @wires {xp0, xp1, xp2, xp3, xp4, xp5, xp6, xp7} +} +@connection (GPIO.portB, gpio_port, lcd8.gpioPin) { + @wires {xp0, xp1, xp2, xp3, xp4, xp5, xp6, xp7} + @wires {xp0, xp1, xp2, xp3, xp4, xp5, xp6, xp7} +} + + +@connection (RTC_IO.apbPin, APB) { + @wires { + addr, rdata, wdata, size, enable, write, sel_rtc, rtc_int, impulse + } +} + + +/******************************************************************* + * PRIJEVODI * + ***************************************************************** */ +@messages { + msg_toolbar_load_library: "Učitaj biblioteku"; + msg_toolbar_load_schema: "Učitaj schemu"; + msg_toolbar_save_schema: "Spremi schemu"; + msg_toolbar_generate_comdel: "Generiraj COMDEL"; + + msg_sidebar_components: "Komponente:"; + msg_sidebar_busses: "Sabirnice:"; + + msg_boolean_true: "Da"; + msg_boolean_false: "Ne"; + + msg_dialog_success_title: "Uspjeh"; + msg_dialog_success_validation: "Nema validacijskih greški"; + msg_dialog_success_comdel_generation: "Uspješno generiran COMDEL model"; + msg_dialog_success_save_schema: "Uspješno spremljena schema"; + + msg_dialog_actions_ok: "U redu"; + msg_dialog_actions_cancel: "Odustani"; + msg_dialog_actions_set: "Postavi"; + msg_dialog_actions_update: "Ažuriraj"; + msg_dialog_actions_update_named: "Ažuriraj '{name}'"; + msg_dialog_actions_remove_named: "Ukloni '{name}'"; + + msg_pin_update: "Ažuriraj"; + msg_pin_remove: "Ukloni"; + msg_sa_pin_update_title: "Ažuriraj {wire1} - {wire2}"; + msg_sa_pin_remove_title: "Ukloni {wire1} - {wire2}"; + msg_pin_update_action: "Ažuriraj poveznicu"; + msg_pin_remove_action: "Ukloni poveznicu"; + + msg_dialog_error_title: "Greška"; + msg_dialog_warning_title: "Upozorenje"; + msg_dialog_error_close: "Zatvori"; + + msg_dialog_attribute_update: "Ažuriraj '{attribute}'"; + msg_dialog_attribute_set: "Postavi '{attribute}'"; + msg_dialog_name_update: "Ažuriraj ime"; + msg_dialog_memory_update: "Ažuriraj memoriju"; + msg_dialog_memory_set: "Postavi memoriju"; + msg_dialog_memory_default: "Memorija nije izabrana"; + msg_dialog_sa_pin_set: "Postavi sabirnicu"; + + msg_validators_component_min_count: "Nedovoljno instanci komponente '{componentName}'. Potrebno barem {min}, pronađeno {count}!"; + msg_validators_component_max_count: "Previše instanci komponente '{componentName}'. Dozvoljeno najviše {max}, pronađeno {count}!"; + msg_validators_bus_min_count: "Nedovoljno instanci sabirnice '{busName}'. Potrebno barem {min}, pronađeno {count}!"; + msg_validators_bus_max_count: "Previše instanci sabirnice '{busName}'. Dozvoljeno najviše {max}, pronađeno {count}!"; + msg_validators_memory_not_found: "Ne postoji memorijska instanca {memoryReference}!"; + msg_validators_duplicates_found: "Pronađeno više instanci s imenom {instanceName}!"; + + msg_files_load_library: "Otvori biblioteku"; + msg_files_load_library_format: "COMDEL biblioteka (*.csl)"; + msg_files_load_schema: "Otvori schemu"; + msg_files_load_schema_format: "COMDEL schema (*.csch)"; + msg_files_store_schema: "Spremi schemu"; + msg_files_store_schema_format: "COMDEL schema (*.csch)"; + msg_files_store_comdel: "Spremi COMDEL model"; + msg_files_store_comdel_format: "COMDEL model (*.system)"; +} \ No newline at end of file diff --git a/examples/arm/model.csch b/examples/arm/model.csch new file mode 100644 index 0000000..b62236a --- /dev/null +++ b/examples/arm/model.csch @@ -0,0 +1,64 @@ +@source "/home/bbr/Documents/Personal/FER/schema_editor/examples/arm/arm_library.csl" + +@schema { + @instance bridge Bridge { + @position (-263, -97) + } + + @instance arm ARM7tdmi { + @position (-473, -283) + @attribute _memory memorija + } + + @instance memorija Memory64KiB { + @position (-433, 6) + } + + @instance decoder Decoder { + @position (-541, -212) + } + + @instance rtc RTC_IO { + @position (-63, -190) + } + + @instance gpio GPIO { + @position (-217, 13) + @attribute title "GPIO 1" + } + + @instance temperature Temperature { + @position (-47, -12) + } + + @instance ahb AHB { + @position (-514, -86) + @size 249 + } + + @instance apb APB { + @position (-201, -87) + @size 329 + } + + @instance gpio_port gpio_port { + @position (0, 0) + @size -1 + } + + @connection (bridge.ahbPin, ahb) { + } + @connection (bridge.apbPin, apb) { + } + @connection (memorija.ahbPin, ahb) { + } + @connection (arm.ahbPin, ahb) { + } + @connection (decoder.ahbPin, ahb) { + } + @connection (rtc.apbPin, apb) { + } + @connection (gpio.apbPin, apb) { + @attribute gpioSelect sel_gpio_1 + } +} diff --git a/examples/arm/model2.csch b/examples/arm/model2.csch new file mode 100644 index 0000000..267a28a --- /dev/null +++ b/examples/arm/model2.csch @@ -0,0 +1,233 @@ +@source "arm_library.csl" +// /home/bbr/Documents/Personal/FER/schema_editor/examples/arm/ +@schema { + @instance bridge Bridge { + @position (-263, -97) + } + + @instance arm ARM7tdmi { + @position (-473, -283) + @attribute _memory memorija + } + + @instance memorija Memory64KiB { + @position (-545, 37) + } + + @instance decoder Decoder { + @position (-541, -212) + } + + @instance rtc RTC_IO { + @position (-63, -190) + } + + @instance gpio GPIO { + @position (32, 11) + @attribute title "GPIO 1" + } + + @instance temperature Temperature { + @position (144, -25) + } + + @instance led LED { + @position (159, 138) + @attribute onColor "green" + } + + @instance led_000 LED { + @position (182, 139) + @attribute onColor "yellow" + } + + @instance led_001 LED { + @position (202, 140) + @attribute onColor "red" + } + + @instance interruptSelector interrupt_selector { + @position (-235, -134) + } + + @instance signal signal { + @position (63, -44) + } + + @instance interruptSelector_000 interrupt_selector { + @position (-238, -160) + } + + @instance lcd lcd8 { + @position (181, -199) + } + + @instance gpio_000 GPIO { + @position (53, -222) + @attribute title "GPIO 2" + } + + @instance push_button pushbutton { + @position (260, -98) + } + + @instance toggle_button togglebutton { + @position (205, -70) + } + + @instance dmac DMAC_simple { + @position (-445, 12) + } + + @instance ui_unit UI_UNIT { + @position (-189, 25) + @attribute type 0 + @attribute name "Izlaz" + @attribute width 8 + @attribute duration 40 + } + + @instance ui_unit_000 UI_UNIT { + @position (-118, 63) + @attribute type 1 + @attribute name "Ulaz" + @attribute width 8 + @attribute duration 40 + } + + @instance ahb AHB { + @position (-514, -86) + @size 249 + } + + @instance apb APB { + @position (-201, -87) + @size 329 + } + + @instance gpio_port gpio_port { + @position (0, 0) + @size -1 + } + + @instance gpio_port_000 gpio_port { + @position (0, 0) + @size -1 + } + + @instance gpio_sa gpio_sa { + @position (0, 0) + @size -1 + } + + @instance gpio_sa_000 gpio_sa { + @position (0, 0) + @size -1 + } + + @instance gpio_sa_001 gpio_sa { + @position (0, 0) + @size -1 + } + + @instance gpio_sa_002 gpio_sa { + @position (0, 0) + @size -1 + } + + @instance gpio_port_001 gpio_port { + @position (0, 0) + @size -1 + } + + @instance gpio_sa_003 gpio_sa { + @position (0, 0) + @size -1 + } + + @instance gpio_sa_004 gpio_sa { + @position (0, 0) + @size -1 + } + + @instance arm_dmac dmac_io { + @position (0, 0) + @size -1 + } + + @instance arm_dmac_000 dmac_io { + @position (0, 0) + @size -1 + } + + @connection (bridge.ahbPin, ahb) { + } + @connection (bridge.apbPin, apb) { + } + @connection (memorija.ahbPin, ahb) { + } + @connection (arm.ahbPin, ahb) { + } + @connection (decoder.ahbPin, ahb) { + } + @connection (rtc.apbPin, apb) { + } + @connection (gpio.apbPin, apb) { + @attribute gpioSelect sel_gpio_1 + } + @connection (gpio.portA, gpio_port_000, temperature.gpioPin) { + } + @connection (gpio.portB, gpio_sa, led.gpioPin) { + @attribute gpioPortB "XP0" + @attribute ledGpioPin "Ulaz" + } + @connection (gpio.portB, gpio_sa_000, led_000.gpioPin) { + @attribute gpioPortB "XP4" + @attribute ledGpioPin "Ulaz" + } + @connection (gpio.portB, gpio_sa_001, led_001.gpioPin) { + @attribute gpioPortB "XP6" + @attribute ledGpioPin "Ulaz" + } + @connection (interruptSelector.ahbPin, ahb) { + } + @connection (interruptSelector.apbPin, apb) { + @attribute interrupt rtc_int + } + @connection (signal.apbPin, apb) { + } + @connection (interruptSelector_000.ahbPin, ahb) { + } + @connection (interruptSelector_000.apbPin, apb) { + @attribute interrupt dmac_int + } + @connection (gpio_000.apbPin, apb) { + @attribute gpioSelect sel_gpio_2 + } + @connection (gpio_000.portA, gpio_port_001, lcd.gpioPin) { + } + @connection (gpio_000.portB, gpio_sa_003, push_button.gpioPin) { + @attribute gpioPortB "XP0" + @attribute buttonGpioPin "Izlaz" + } + @connection (gpio_000.portB, gpio_sa_004, toggle_button.gpioPin) { + @attribute gpioPortB "XP1" + @attribute buttonGpioPin "Izlaz" + } + @connection (dmac.apbPin, apb) { + } + @connection (dmac.ahbMasterPin, ahb) { + } + @connection (dmac.ahbSlavePin, ahb) { + } + @connection (ui_unit_000.dmacPin, arm_dmac, dmac.dev3) { + } + @connection (ui_unit.dmacPin, arm_dmac_000, dmac.dev2) { + } + @connection (ui_unit.apbPin, apb) { + @attribute intSelect sel_ui_in + } + @connection (ui_unit_000.apbPin, apb) { + @attribute intSelect sel_ui_out + } +} diff --git a/examples/arm/test.system b/examples/arm/test.system new file mode 100644 index 0000000..1a23585 --- /dev/null +++ b/examples/arm/test.system @@ -0,0 +1,75 @@ +set load_performs_init; +#include "\arm7tdmi.comdel" +#include "\bridge.comdel" +#include "\decoder.comdel" +#include "\memory.comdel" + + + +component System +{ + clock 100MHz; + //ahb + wire<32> addr; + wire<32> rdata; + wire<32> wdata; + wire<3> size; + wire write; + wired_or ready; + wired_or irq; + wired_or fiq; + wired_and nmreq; + wire --sel_mem; + wire sel_bridge; + wire sel_dmac; + + + //apb + wire<32> apb__addr; + wire<32> apb__rdata; + wire<32> apb__wdata; + wire<3> --apb__size; + wire enable; + wire apb__write; + wire sel_gpio_1; + wire sel_gpio_2; + wire sel_ui_in; + wire sel_rtc; + wire sel_ui_out; + + + // components -------------------------------------------- + subcomponent Memory64KiB memorija(addr, rdata, wdata, size, write, ready, --sel_mem); + subcomponent Bridge bridge(addr, rdata, wdata, size, write, ready, sel_bridge, apb__addr, apb__rdata, apb__wdata, --apb__size, enable, apb__write, sel_gpio_1, sel_gpio_2, sel_rtc, sel_ui_in, sel_ui_out, 1, 1, 1, 1, 1); + subcomponent ARM7tdmi arm(addr, rdata, wdata, size, write, ready, irq, fiq, nmreq, *, *) uses memorija; + subcomponent Decoder decoder(addr, nmreq, --sel_mem, sel_bridge, sel_dmac, 1, 1); + + display { + component { x: -222; y: -97; ref: "bridge"; } + component { x: -473; y: -283; ref: "arm"; } + component { x: -433; y: 6; ref: "memorija"; } + component { x: -323; y: -217; ref: "decoder"; } + + // ahb bus + + rectangle { + x: -514; y: -86; + w: 249; h: 20; + } + + + // apb bus + + rectangle { + x: -111; y: -81; + w: 329; h: 20; + } + + + line {x1:-222; y1:-77; x2:-389; y2:-75;} + line {x1:-162; y1:-77; x2:54; y2:-70;} + line {x1:-428; y1:6; x2:-389; y2:-75;} + line {x1:-418; y1:-152; x2:-389; y2:-75;} + line {x1:-303; y1:-187; x2:-389; y2:-75;} + } +} \ No newline at end of file diff --git a/examples/arm/test2.system b/examples/arm/test2.system new file mode 100644 index 0000000..640deb3 --- /dev/null +++ b/examples/arm/test2.system @@ -0,0 +1,245 @@ +set load_performs_init; +#include ".\arm7tdmi.comdel" +#include ".\bridge.comdel" +#include ".\decoder.comdel" +#include ".\dmac.comdel" +#include ".\gpio.comdel" +#include ".\interrupt_selector.comdel" +#include ".\lcd8.signal" +#include ".\led.comdel" +#include ".\memory.comdel" +#include ".\pushbutton.comdel" +#include ".\rtc.comdel" +#include ".\signal.comdel" +#include ".\temperature.comdel" +#include ".\togglebutton.comdel" +#include ".\ui_unit.comdel" + + + +component System +{ + clock 100MHz; + //ahb + wire<32> addr; + wire<32> rdata; + wire<32> wdata; + wire<3> size; + wire write; + wired_or ready; + wired_or irq; + wired_or fiq; + wired_and nmreq; + wire --sel_mem; + wire sel_bridge; + wire sel_dmac; + wire busreq; + wire grant; + + + //apb + wire<32> apb__addr; + wire<32> apb__rdata; + wire<32> apb__wdata; + wire<3> --size; + wire enable; + wire apb__write; + wire sel_gpio_1; + wire sel_gpio_2; + wire sel_ui_in; + wire sel_rtc; + wire sel_ui_out; + wire --rtc_int; + wire --dmac_int; + wire --impulse; + + + //gpio_port + wire --xp0; + wire --xp1; + wire --xp2; + wire --xp3; + wire --xp4; + wire --xp5; + wire --xp6; + wire --xp7; + + + //gpio_port_000 + wire --gpio_port_000__xp0; + wire --gpio_port_000__xp1; + wire --gpio_port_000__xp2; + wire --gpio_port_000__xp3; + wire --gpio_port_000__xp4; + wire --gpio_port_000__xp5; + wire --gpio_port_000__xp6; + wire --gpio_port_000__xp7; + + + //gpio_sa + wire --xp; + + + //gpio_sa_000 + wire --gpio_sa_000__xp; + + + //gpio_sa_001 + wire --gpio_sa_001__xp; + + + //gpio_sa_002 + wire --gpio_sa_002__xp; + + + //gpio_port_001 + wire --gpio_port_001__xp0; + wire --gpio_port_001__xp1; + wire --gpio_port_001__xp2; + wire --gpio_port_001__xp3; + wire --gpio_port_001__xp4; + wire --gpio_port_001__xp5; + wire --gpio_port_001__xp6; + wire --gpio_port_001__xp7; + + + //gpio_sa_003 + wire --gpio_sa_003__xp; + + + //gpio_sa_004 + wire --gpio_sa_004__xp; + + + //arm_dmac + wire --dmareq; + wire --dmaack; + + + //arm_dmac_000 + wire --arm_dmac_000__dmareq; + wire --arm_dmac_000__dmaack; + + + // components -------------------------------------------- + subcomponent Memory64KiB memorija(addr, rdata, wdata, size, write, ready, --sel_mem); + subcomponent Bridge bridge(addr, rdata, wdata, size, write, ready, sel_bridge, apb__addr, apb__rdata, apb__wdata, --size, enable, apb__write, sel_gpio_1, sel_gpio_2, sel_rtc, sel_ui_in, sel_ui_out, 1, 1, 1, 1, 1); + subcomponent ARM7tdmi arm(addr, rdata, wdata, size, write, ready, irq, fiq, nmreq, busreq, grant, *, *) uses memorija; + subcomponent Decoder decoder(addr, nmreq, --sel_mem, sel_bridge, sel_dmac, 1, 1); + subcomponent RTC_IO rtc(apb__addr, apb__rdata, apb__wdata, --size, enable, apb__write, sel_rtc, --rtc_int, --impulse); + subcomponent GPIO gpio<"GPIO 1">(apb__addr, apb__rdata, apb__wdata, enable, apb__write, sel_gpio_1, --gpio_port_000__xp0, --gpio_port_000__xp1, --gpio_port_000__xp2, --gpio_port_000__xp3, --gpio_port_000__xp4, --gpio_port_000__xp5, --gpio_port_000__xp6, --gpio_port_000__xp7, --xp, *, *, *, --gpio_sa_000__xp, *, --gpio_sa_001__xp, *); + subcomponent Temperature temperature(--gpio_port_000__xp0, --gpio_port_000__xp1, --gpio_port_000__xp2, --gpio_port_000__xp3, --gpio_port_000__xp4, --gpio_port_000__xp5, --gpio_port_000__xp6, --gpio_port_000__xp7); + subcomponent LED led<"green">(--xp); + subcomponent LED led_000<"yellow">(--gpio_sa_000__xp); + subcomponent LED led_001<"red">(--gpio_sa_001__xp); + subcomponent interrupt_selector interruptSelector(rtc_int, irq, fiq); + subcomponent signal signal(--impulse); + subcomponent interrupt_selector interruptSelector_000(dmac_int, irq, fiq); + subcomponent lcd8 lcd(--gpio_port_001__xp0, --gpio_port_001__xp1, --gpio_port_001__xp2, --gpio_port_001__xp3, --gpio_port_001__xp4, --gpio_port_001__xp5, --gpio_port_001__xp6, --gpio_port_001__xp7); + subcomponent GPIO gpio_000<"GPIO 2">(apb__addr, apb__rdata, apb__wdata, enable, apb__write, sel_gpio_2, --gpio_port_001__xp0, --gpio_port_001__xp1, --gpio_port_001__xp2, --gpio_port_001__xp3, --gpio_port_001__xp4, --gpio_port_001__xp5, --gpio_port_001__xp6, --gpio_port_001__xp7, --gpio_sa_003__xp, --gpio_sa_004__xp, *, *, *, *, *, *); + subcomponent pushbutton push_button(--gpio_sa_003__xp); + subcomponent togglebutton toggle_button(--gpio_sa_004__xp); + subcomponent DMAC_simple dmac(addr, rdata, wdata, size, write, ready, sel_dmac, addr, rdata, wdata, size, write, ready, nmreq, busreq, grant, --dmac_int, 0, *, 0, *, --arm_dmac_000__dmareq, --arm_dmac_000__dmaack, --dmareq, --dmaack); + subcomponent UI_UNIT ui_unit<0, "Izlaz", 8, 40>(apb__addr, apb__rdata, apb__wdata, --size, enable, apb__write, sel_ui_in, --arm_dmac_000__dmareq, --arm_dmac_000__dmaack); + subcomponent UI_UNIT ui_unit_000<1, "Ulaz", 8, 40>(apb__addr, apb__rdata, apb__wdata, --size, enable, apb__write, sel_ui_out, --dmareq, --dmaack); + + display { + component { x: -263; y: -97; ref: "bridge"; } + component { x: -473; y: -283; ref: "arm"; } + component { x: -545; y: 37; ref: "memorija"; } + component { x: -541; y: -212; ref: "decoder"; } + component { x: -63; y: -190; ref: "rtc"; } + component { x: 32; y: 11; ref: "gpio"; } + component { x: 144; y: -25; ref: "temperature"; } + component { x: 159; y: 138; ref: "led"; } + component { x: 182; y: 139; ref: "led_000"; } + component { x: 202; y: 140; ref: "led_001"; } + component { x: -235; y: -134; ref: "interruptSelector"; } + component { x: 63; y: -44; ref: "signal"; } + component { x: -238; y: -160; ref: "interruptSelector_000"; } + component { x: 181; y: -199; ref: "lcd"; } + component { x: 53; y: -222; ref: "gpio_000"; } + component { x: 260; y: -98; ref: "push_button"; } + component { x: 205; y: -70; ref: "toggle_button"; } + component { x: -445; y: 12; ref: "dmac"; } + component { x: -189; y: 25; ref: "ui_unit"; } + component { x: -118; y: 63; ref: "ui_unit_000"; } + + // ahb bus + + rectangle { + x: -514; y: -86; + w: 249; h: 20; + } + + + // apb bus + + rectangle { + x: -201; y: -87; + w: 329; h: 20; + } + + + // gpio_port bus + + + // gpio_port_000 bus + + + // gpio_sa bus + + + // gpio_sa_000 bus + + + // gpio_sa_001 bus + + + // gpio_sa_002 bus + + + // gpio_port_001 bus + + + // gpio_sa_003 bus + + + // gpio_sa_004 bus + + + // arm_dmac bus + + + // arm_dmac_000 bus + + + line {x1:-263; y1:-77; x2:-389; y2:-75;} + line {x1:-203; y1:-77; x2:-36; y2:-76;} + line {x1:-540; y1:37; x2:-389; y2:-75;} + line {x1:-418; y1:-152; x2:-389; y2:-75;} + line {x1:-521; y1:-182; x2:-389; y2:-75;} + line {x1:-43; y1:-150; x2:-36; y2:-76;} + line {x1:32; y1:56; x2:-36; y2:-76;} + line {x1:112; y1:32; x2:164; y2:15;} + line {x1:112; y1:91; x2:164; y2:138;} + line {x1:112; y1:91; x2:187; y2:139;} + line {x1:112; y1:91; x2:207; y2:140;} + line {x1:-245; y1:-129; x2:-389; y2:-75;} + line {x1:-215; y1:-129; x2:-36; y2:-76;} + line {x1:68; y1:-44; x2:-36; y2:-76;} + line {x1:-248; y1:-155; x2:-389; y2:-75;} + line {x1:-218; y1:-155; x2:-36; y2:-76;} + line {x1:53; y1:-177; x2:-36; y2:-76;} + line {x1:133; y1:-201; x2:171; y2:-172;} + line {x1:133; y1:-142; x2:277; y2:-108;} + line {x1:133; y1:-142; x2:222; y2:-80;} + line {x1:-340; y1:32; x2:-36; y2:-76;} + line {x1:-370; y1:12; x2:-389; y2:-75;} + line {x1:-410; y1:12; x2:-389; y2:-75;} + line {x1:-118; y1:93; x2:-325; y2:92;} + line {x1:-189; y1:55; x2:-325; y2:77;} + line {x1:-159; y1:25; x2:-36; y2:-76;} + line {x1:-88; y1:63; x2:-36; y2:-76;} + } +} \ No newline at end of file diff --git a/examples/simplified FRISC model/schema.csl b/examples/simplified FRISC model/schema.csch similarity index 100% rename from examples/simplified FRISC model/schema.csl rename to examples/simplified FRISC model/schema.csch diff --git a/examples/simplified FRISC model/schema2.csl b/examples/simplified FRISC model/schema2.csch similarity index 100% rename from examples/simplified FRISC model/schema2.csl rename to examples/simplified FRISC model/schema2.csch diff --git a/examples/simplified FRISC model/schema3.csl b/examples/simplified FRISC model/schema3.csch similarity index 100% rename from examples/simplified FRISC model/schema3.csl rename to examples/simplified FRISC model/schema3.csch diff --git a/examples/simplified FRISC model/schema4.csl b/examples/simplified FRISC model/schema4.csch similarity index 100% rename from examples/simplified FRISC model/schema4.csl rename to examples/simplified FRISC model/schema4.csch diff --git a/examples/simplified FRISC model/schema5.csl b/examples/simplified FRISC model/schema5.csch similarity index 100% rename from examples/simplified FRISC model/schema5.csl rename to examples/simplified FRISC model/schema5.csch diff --git a/mainwindow.cpp b/mainwindow.cpp index f6593c2..dbdbede 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -3,6 +3,7 @@ #include "application.h" #include "comdel/display/dialog/error_dialog.h" #include "comdel/display/dialog/success_dialog.h" +#include "message_source.h" #include #include @@ -30,10 +31,12 @@ void MainWindow::setupUi() ui->centralwidget->setLayout(layout); // setup toolbar - ui->toolBar->addAction("Učitaj bibiloteku", this, &MainWindow::onLoadLibrary); - ui->toolBar->addAction("Učitaj shemu", this, &MainWindow::onLoadSchema); - ui->toolBar->addAction("Spremi shemu", this, &MainWindow::onStoreScheme); - ui->toolBar->addAction("Generiraj comdel", this, &MainWindow::onGenerateComdel); + loadLibrary = ui->toolBar->addAction(QMESSAGE("msg_toolbar_load_library"), this, &MainWindow::onLoadLibrary); + loadSchema = ui->toolBar->addAction(QMESSAGE("msg_toolbar_load_schema"), this, &MainWindow::onLoadSchema); + saveSchema = ui->toolBar->addAction(QMESSAGE("msg_toolbar_save_schema"), this, &MainWindow::onStoreScheme); + generateComdel = ui->toolBar->addAction(QMESSAGE("msg_toolbar_generate_comdel"), this, &MainWindow::onGenerateComdel); + + updateTranslations(); connect(ui->actionSave_schema, &QAction::triggered, this, &MainWindow::onStoreScheme); connect(ui->actionExport_schema, &QAction::triggered, this, &MainWindow::onGenerateComdel); @@ -57,7 +60,9 @@ void MainWindow::setupUi() void MainWindow::onLoadLibrary() { auto filename = QFileDialog::getOpenFileName(this, - tr("Otvori biblioteku"), "", tr("Comdel biblioteka (*.csl)")); + QMESSAGE("msg_files_load_library"), + "", + QMESSAGE("msg_files_load_library_format")); if(!filename.isEmpty()) { std::ostringstream output; @@ -67,6 +72,9 @@ void MainWindow::onLoadLibrary() { if(!instance->loadLibrary(librarySource, output)) { auto dialog = new display::ErrorDialog(output); dialog->exec(); + } else { + MessageSource::instance()->load(Application::instance()->getLibrary()->getMessages()); + updateTranslations(); } libraryDisplay->refreshContent(); @@ -76,7 +84,9 @@ void MainWindow::onLoadLibrary() { void MainWindow::onLoadSchema() { auto filename = QFileDialog::getOpenFileName(this, - tr("Otvori shemu"), "", tr("Comdel shema (*.csl)")); + QMESSAGE("msg_files_load_schema"), + "", + QMESSAGE("msg_files_load_schema_format")); if(!filename.isEmpty()) { std::ostringstream output; @@ -88,6 +98,9 @@ void MainWindow::onLoadSchema() { formatErrors(result.second, output); auto dialog = new display::ErrorDialog(output); dialog->exec(); + } else { + MessageSource::instance()->load(Application::instance()->getLibrary()->getMessages()); + updateTranslations(); } libraryDisplay->refreshContent(); @@ -97,7 +110,9 @@ void MainWindow::onLoadSchema() { void MainWindow::onStoreScheme() { auto filename = QFileDialog::getSaveFileName(this, - tr("Spremi shemu"), "", tr("Comdel shema (*.csl)")); + QMESSAGE("msg_files_store_schema"), + "", + QMESSAGE("msg_files_store_schema_format")); if(!filename.isEmpty()) { std::ostringstream output; @@ -106,7 +121,7 @@ void MainWindow::onStoreScheme() { out<exec(); } else { auto dialog = new display::ErrorDialog(output); @@ -118,24 +133,26 @@ void MainWindow::onStoreScheme() { void MainWindow::onGenerateComdel() { auto filename = QFileDialog::getSaveFileName(this, - tr("Spremi shemu"), "", tr("Comdel sustav (*.system)")); + QMESSAGE("msg_files_store_comdel"), + "", + QMESSAGE("msg_files_store_comdel_format")); if(!filename.isEmpty()) { std::ostringstream output; auto validationErrors = Application::instance()->generateComdel(output); - std::ostringstream buff; - formatErrors(validationErrors, buff); + std::ostringstream errorOutput; + formatErrors(validationErrors, errorOutput); if(!Application::hasErrors(validationErrors)) { std::ofstream out(filename.toStdString(), std::ios::out | std::ios::binary); out<exec(); } else { - auto dialog = new display::ErrorDialog(output); + auto dialog = new display::ErrorDialog(errorOutput); dialog->exec(); } } @@ -152,7 +169,7 @@ void MainWindow::onValidateSchema(bool /*toggled*/) { auto dialog = new display::ErrorDialog(buff); dialog->exec(); } else { - auto dialog = new display::SuccessDialog("Nema validacijskih greški"); + auto dialog = new display::SuccessDialog(MESSAGE("msg_dialog_success_validation")); dialog->exec(); } } @@ -178,3 +195,10 @@ MainWindow::~MainWindow() { delete ui; } + +void MainWindow::updateTranslations() { + loadLibrary->setText(QMESSAGE("msg_toolbar_load_library")); + loadSchema->setText(QMESSAGE("msg_toolbar_load_schema")); + saveSchema->setText(QMESSAGE("msg_toolbar_save_schema")); + generateComdel->setText(QMESSAGE("msg_toolbar_generate_comdel")); +} diff --git a/mainwindow.h b/mainwindow.h index 1f4ec20..8117ca6 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -41,6 +41,13 @@ private: display::Schema *schemaDisplay; Ui::MainWindow *ui; + QAction* loadLibrary; + QAction* loadSchema; + QAction* saveSchema; + QAction* generateComdel; + static void formatErrors(std::vector& errors, std::ostream& output); + + void updateTranslations(); }; #endif // MAIN_WINDOW_H diff --git a/message_source.cpp b/message_source.cpp new file mode 100644 index 0000000..e4245c5 --- /dev/null +++ b/message_source.cpp @@ -0,0 +1,145 @@ +// +// Created by bbr on 14.06.22.. +// + +#include "message_source.h" + +#include + +// static instance of application +static MessageSource *messageSource = nullptr; + +MessageSource *MessageSource::instance() { + if (messageSource == nullptr) { + messageSource = new MessageSource(); + } + return messageSource; +} + +void MessageSource::loadDefaults() { + messages.clear(); + + // TOOLBAR + add("msg_toolbar_load_library", "Load library"); + add("msg_toolbar_load_schema", "Load schema"); + add("msg_toolbar_save_schema", "Save schema"); + add("msg_toolbar_generate_comdel", "Generate comdel"); + + // SIDEBAR + add("msg_sidebar_components", "Components:"); + add("msg_sidebar_busses", "Busses:"); + + // VALUES + add("msg_boolean_true", "True"); + add("msg_boolean_false", "False"); + + // SUCCESS MESSAGES + add("msg_dialog_success_title", "Success"); + add("msg_dialog_success_validation", "No validation errors found!"); + add("msg_dialog_success_comdel_generation", "Successfully generate COMDEL model!"); + add("msg_dialog_success_save_schema", "Successfully saved schema"); + + // DEFAULT ACTIONS + add("msg_dialog_actions_ok", "Ok"); + add("msg_dialog_actions_cancel", "Cancel"); + add("msg_dialog_actions_set", "Set"); + add("msg_dialog_actions_update", "Update"); + add("msg_dialog_actions_update_named", "Update {name}"); + add("msg_dialog_actions_remove_named", "Remove {name}"); + // PIN DIALOG + add("msg_pin_update", "Update"); + add("msg_pin_remove", "Remove"); + add("msg_sa_pin_update_title", "Update {wire1} - {wire2}"); + add("msg_sa_pin_remove_title", "Remove {wire1} - {wire2}"); + add("msg_pin_update_action", "Update connection"); + add("msg_pin_remove_action", "Remove connection"); + // ERROR DIALOG + add("msg_dialog_error_title", "Error"); + add("msg_dialog_error_close", "Close"); + // WARNING DIALOG + add("msg_dialog_warning_title", "Warning"); + // ATTRIBUTE DIALOG/ACTION + add("msg_dialog_attribute_update", "Update {attribute}"); + add("msg_dialog_attribute_set", "Set {attribute}"); + // NAME DIALOG + add("msg_dialog_name_update", "Update name"); + // MEMORY DIALOG/ACTION + add("msg_dialog_memory_update", "Update memory"); + add("msg_dialog_memory_set", "Set memory"); + add("msg_dialog_memory_default", "No memory selected"); + // CONNECTION + add("msg_dialog_sa_pin_set", "Set wire"); + // VALIDATORS + add("msg_validators_component_min_count", "Missing instances of component {componentName}. Required at least {min}, found {count}!"); + add("msg_validators_component_max_count", "Too many instances of component {componentname}. Expected at most {max}, found {count}!"); + add("msg_validators_bus_min_count", "Missing instances of bus {busName}. Required at least {min}, found {count}!"); + add("msg_validators_bus_max_count", "Too many instances of bus {busName}. Expected at most {max}, found {count}!"); + add("msg_validators_memory_not_found", "Cannot find memory instance {memoryReference}"); + add("msg_validators_duplicates_found", "Found multiple instances with name {instanceName}"); + + // LOADING/SAVING DIALOGS + add("msg_files_load_library", "Open library"); + add("msg_files_load_library_format", "COMDEL library (*.csl)"); + add("msg_files_load_schema", "Open schema"); + add("msg_files_load_schema_format", "COMDEL schema (*.csch)"); + add("msg_files_store_schema", "Store schema"); + add("msg_files_store_schema_format", "COMDEL schema (*.csch)"); + add("msg_files_store_comdel", "Store COMDEL system"); + add("msg_files_store_comdel_format", "COMDEL system (*.system)"); + +} + +void MessageSource::add(const std::string& key, std::string message) { + messages[key] = message; +} + +std::string MessageSource::get(const std::string& key, std::map parametars) { + std::string message; + if(messages.count(key) == 1) { + // if key not found in translations use key as message + message = messages[key]; + } else { + message = key; + } + + message = populateMessage(message, parametars); + + return message; +} + +std::string MessageSource::get(const std::string &key) { + return get(key, {}); +} + +std::string MessageSource::populateMessage(std::string message, std::map parametars) { + for (auto &[key, value]: parametars) { + message = replacePlaceholder(message, key, value); + } + return message; +} + +std::string MessageSource::replacePlaceholder(std::string message, const std::string key, std::string value) { + auto wholeKey = "{" + key + "}"; + + auto found = message.find(wholeKey); + while (found != std::string::npos) { + message.replace(found, wholeKey.length(), value); + found = message.find(key); + } + return message; +} + +void MessageSource::load(std::map _messages) { + loadDefaults(); + for (auto &[key, value]: _messages) { + messages[key] = value; + } +} + +std::map MessageSource::map(std::map values) { + std::map parametars; + for (auto &[key, value]: values) { + parametars[key] = value.string(); + } + return parametars; +} diff --git a/message_source.h b/message_source.h new file mode 100644 index 0000000..2da260c --- /dev/null +++ b/message_source.h @@ -0,0 +1,43 @@ +// +// Created by bbr on 14.06.22.. +// + +#ifndef SCHEMEEDITOR_MESSAGE_SOURCE_H +#define SCHEMEEDITOR_MESSAGE_SOURCE_H + + +#include +#include +#include "comdel/domain/value.h" + +class MessageSource { +private: + MessageSource() { + loadDefaults(); + } + + void add(const std::string& key, std::string message); + std::string populateMessage(std::string message, std::map parametars); + std::string replacePlaceholder(std::string message, std::string key, std::string value); + + std::map messages; + +public: + static MessageSource *instance(); + static std::map map(std::map values); + + std::string get(const std::string& key); + std::string get(const std::string& key, std::map parametars); + + void loadDefaults(); + void load(std::map messages); +}; + +#define MESSAGE_PARAM(key, params) MessageSource::instance()->get(key, params) +#define MESSAGE(key) MessageSource::instance()->get(key) +#define MESSAGE_MAP(value) MessageSource::instance()->map(value) + +#define QMESSAGE_PARAM(key, params) QString::fromStdString(MessageSource::instance()->get(key, params)) +#define QMESSAGE(key) QString::fromStdString(MessageSource::instance()->get(key)) + +#endif //SCHEMEEDITOR_MESSAGE_SOURCE_H