Compare commits
11 Commits
ae2a3c64ef
...
master
Author | SHA1 | Date |
---|---|---|
Borna Rajković | 947f6e464b | |
Borna Rajković | 9c332ac3e7 | |
Borna Rajković | edfd7fdf37 | |
Borna Rajković | 6ed60a2c26 | |
Borna Rajković | 9129a4bf43 | |
Borna Rajković | 350aa95da5 | |
Borna Rajković | d2fc849cc2 | |
Borna Rajković | eaa115d115 | |
Borna Rajković | 7be3a1b5bc | |
Borna Rajković | fe4a39803c | |
Borna Rajković | 1ec0433cfe |
|
@ -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/attribute_dialog.cpp comdel/display/attribute_dialog.h comdel/display/name_dialog.cpp comdel/display/name_dialog.h comdel/domain/comdel_generator.cpp comdel/domain/comdel_generator.h comdel/display/library_list.cpp comdel/display/library_list.h application.cpp application.h comdel/display/single_automatic_dialog.cpp comdel/display/single_automatic_dialog.h comdel/parser/color.cpp comdel/parser/color.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)
|
||||
|
|
|
@ -9,13 +9,18 @@ CONFIG += c++17
|
|||
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
||||
|
||||
SOURCES += \
|
||||
comdel/display/attribute_dialog.cpp \
|
||||
comdel/display/dialog/attribute_dialog.cpp \
|
||||
comdel/display/dialog/error_dialog.cpp \
|
||||
comdel/display/dialog/generic_dialog.cpp \
|
||||
comdel/display/dialog/memory_dialog.cpp \
|
||||
comdel/display/dialog/name_dialog.cpp \
|
||||
comdel/display/dialog/single_automatic_dialog.cpp \
|
||||
comdel/display/dialog/success_dialog.cpp \
|
||||
comdel/display/dialog/warning_dialog.cpp \
|
||||
comdel/display/component_display.cpp \
|
||||
comdel/display/library_display.cpp \
|
||||
comdel/display/library_list.cpp \
|
||||
comdel/display/name_dialog.cpp \
|
||||
comdel/display/schema_display.cpp \
|
||||
comdel/display/single_automatic_dialog.cpp \
|
||||
comdel/domain/address_space.cpp \
|
||||
comdel/domain/attribute.cpp \
|
||||
comdel/domain/bus.cpp \
|
||||
|
@ -44,16 +49,22 @@ SOURCES += \
|
|||
comdel/parser/tokens_type.cpp \
|
||||
application.cpp \
|
||||
main.cpp \
|
||||
message_source.cpp \
|
||||
mainwindow.cpp
|
||||
|
||||
HEADERS += \
|
||||
comdel/display/attribute_dialog.h \
|
||||
comdel/display/dialog/attribute_dialog.h \
|
||||
comdel/display/dialog/error_dialog.h \
|
||||
comdel/display/dialog/generic_dialog.h \
|
||||
comdel/display/dialog/memory_dialog.h \
|
||||
comdel/display/dialog/name_dialog.h \
|
||||
comdel/display/dialog/single_automatic_dialog.h \
|
||||
comdel/display/dialog/success_dialog.h \
|
||||
comdel/display/dialog/warning_dialog.h \
|
||||
comdel/display/component_display.h \
|
||||
comdel/display/library_display.h \
|
||||
comdel/display/library_list.h \
|
||||
comdel/display/name_dialog.h \
|
||||
comdel/display/schema_display.h \
|
||||
comdel/display/single_automatic_dialog.h \
|
||||
comdel/domain/address_space.h \
|
||||
comdel/domain/attribute.h \
|
||||
comdel/domain/bus.h \
|
||||
|
@ -83,6 +94,7 @@ HEADERS += \
|
|||
comdel/parser/source_error.h \
|
||||
comdel/parser/token.h \
|
||||
comdel/parser/tokens_type.h \
|
||||
message_source.h \
|
||||
mainwindow.h
|
||||
|
||||
FORMS += \
|
||||
|
|
|
@ -90,7 +90,7 @@ std::pair<bool, std::vector<domain::ValidationError>> Application::loadSchema(st
|
|||
}
|
||||
|
||||
} else {
|
||||
errorOutput << "Failed parsing library" << std::endl;
|
||||
errorOutput << "Failed schema library" << std::endl;
|
||||
return {false, errors};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,283 +0,0 @@
|
|||
//
|
||||
// Created by bbr on 18. 04. 2022..
|
||||
//
|
||||
|
||||
#include "attribute_dialog.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include "application.h"
|
||||
|
||||
namespace display {
|
||||
|
||||
AttributeDialog::AttributeDialog(domain::InstanceAttribute *attribute, bool updating) {
|
||||
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
attributeValue = attribute;
|
||||
|
||||
auto actionType = updating ? "Izmjeni " : "Postavi ";
|
||||
|
||||
this->setWindowTitle(QString::fromStdString(actionType + attribute->attribute.getName()));
|
||||
|
||||
auto layout = new QVBoxLayout(this);
|
||||
this->setLayout(layout);
|
||||
auto popup = *attribute->attribute.getPopup();
|
||||
|
||||
layout->addWidget(new QLabel(popup.getTitle().c_str()));
|
||||
layout->addWidget(new QLabel(popup.getText().c_str()));
|
||||
|
||||
auto type = attribute->attribute.getDefault().getType();
|
||||
value = attribute->value;
|
||||
|
||||
if (attribute->attribute.getPopup()->isEnumerated()) {
|
||||
auto *combo = new QComboBox(this);
|
||||
auto enumeration = attribute->attribute.getPopup()->getEnumeration();
|
||||
for (auto entry: enumeration) {
|
||||
combo->addItem(QString::fromStdString(entry.getName()));
|
||||
}
|
||||
|
||||
connect(combo, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
|
||||
&AttributeDialog::onEnumerationChanged);
|
||||
layout->addWidget(combo);
|
||||
|
||||
for (int i = 0; i < enumeration.size(); i++) {
|
||||
if (attributeValue->value.equals(enumeration[i].getValue())) {
|
||||
combo->setCurrentIndex(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} else if (!(type == domain::Value::ValueType::WIRE_REFERENCE || type == domain::Value::ValueType::BOOL)) {
|
||||
|
||||
auto edit = new QLineEdit(this);
|
||||
connect(edit, &QLineEdit::textChanged, this, &AttributeDialog::onTextChanged);
|
||||
layout->addWidget(edit);
|
||||
|
||||
switch (attribute->attribute.getDefault().getType()) {
|
||||
case domain::Value::ValueType::INT:
|
||||
edit->setValidator(new QIntValidator(-10000000, 10000000, edit));
|
||||
edit->insert(std::to_string(attribute->value.asInt()).c_str());
|
||||
break;
|
||||
case domain::Value::ValueType::STRING:
|
||||
edit->insert(attribute->value.asString().c_str());
|
||||
break;
|
||||
default:
|
||||
throw std::exception();
|
||||
}
|
||||
|
||||
} else if (type == domain::Value::ValueType::BOOL) {
|
||||
auto *group = new QGroupBox(this);
|
||||
|
||||
auto *radioLayout = new QHBoxLayout(group);
|
||||
group->setLayout(radioLayout);
|
||||
|
||||
auto isTrue = new QRadioButton("da", group);
|
||||
connect(isTrue, &QRadioButton::clicked, [this]() {
|
||||
this->value = domain::Value::fromBool(true);
|
||||
});
|
||||
auto isFalse = new QRadioButton("ne", group);
|
||||
connect(isFalse, &QRadioButton::clicked, [this]() {
|
||||
this->value = domain::Value::fromBool(false);
|
||||
});
|
||||
|
||||
if (attribute->value.asBool()) {
|
||||
isTrue->setChecked(true);
|
||||
} else {
|
||||
isFalse->setChecked(true);
|
||||
}
|
||||
|
||||
radioLayout->addWidget(isTrue);
|
||||
radioLayout->addWidget(isFalse);
|
||||
layout->addWidget(group);
|
||||
}
|
||||
|
||||
|
||||
auto buttonLayout = new QHBoxLayout(this);
|
||||
|
||||
auto okButton = new QPushButton(updating ? "Ažuriraj" : "Postavi", this);
|
||||
auto cancelButton = new QPushButton("Odustani", this);
|
||||
|
||||
connect(okButton, &QPushButton::clicked, this, &AttributeDialog::onUpdate);
|
||||
connect(cancelButton, &QPushButton::clicked, [this]() { reject(); });
|
||||
|
||||
buttonLayout->addWidget(okButton);
|
||||
buttonLayout->addWidget(cancelButton);
|
||||
|
||||
layout->addLayout(buttonLayout);
|
||||
}
|
||||
|
||||
void AttributeDialog::onUpdate() {
|
||||
auto oldValue = attributeValue->value;
|
||||
|
||||
attributeValue->value = value;
|
||||
domain::ComdelValidator validator(domain::getSupportedValidators());
|
||||
|
||||
domain::ValidationContext context;
|
||||
|
||||
for (auto &addressSpace: Application::instance()->getLibrary()->getAddressSpaces()) {
|
||||
context.addressSpaces.insert(std::make_pair(addressSpace.getName(), addressSpace));
|
||||
}
|
||||
|
||||
auto validationErrors = validator.validateAttribute(attributeValue, context);
|
||||
if (validationErrors.empty()) {
|
||||
accept();
|
||||
} else {
|
||||
bool canAccept = true;
|
||||
|
||||
std::vector<domain::ValidationError> errors;
|
||||
std::vector<domain::ValidationError> warnings;
|
||||
for (auto &err: validationErrors) {
|
||||
if (err.type == domain::Action::ERROR) {
|
||||
errors.push_back(err);
|
||||
} else {
|
||||
warnings.push_back(err);
|
||||
}
|
||||
}
|
||||
if (!errors.empty()) {
|
||||
canAccept = false;
|
||||
auto errorDialog = new ErrorDialog(errors);
|
||||
errorDialog->exec();
|
||||
}
|
||||
|
||||
for (auto &warning: warnings) {
|
||||
auto warningDialog = new WarningDialog(warning);
|
||||
int response = warningDialog->exec();
|
||||
if (response == QDialog::Rejected) {
|
||||
canAccept = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (canAccept) {
|
||||
accept();
|
||||
} else {
|
||||
attributeValue->value = oldValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AttributeDialog::onTextChanged(const QString &string) {
|
||||
switch (value.getType()) {
|
||||
case domain::Value::STRING:
|
||||
value.setString(string.toStdString());
|
||||
break;
|
||||
case domain::Value::INT:
|
||||
value = domain::Value::fromInt(parseInt(string.toStdString()));
|
||||
break;
|
||||
default:
|
||||
throw std::exception();
|
||||
}
|
||||
}
|
||||
|
||||
void AttributeDialog::onEnumerationChanged(int index) {
|
||||
value = attributeValue->attribute.getPopup()->getEnumeration()[index].getValue();
|
||||
}
|
||||
|
||||
MemoryDialog::MemoryDialog(domain::InstanceAttribute *attribute,
|
||||
std::vector<std::shared_ptr<domain::ComponentInstance>> instances, bool updating) {
|
||||
memoryInstances = std::vector<std::string>();
|
||||
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
attributeValue = attribute;
|
||||
|
||||
auto actionType = updating ? "Izmjeni memoriju" : "Postavi memoriju";
|
||||
|
||||
this->setWindowTitle(QString::fromStdString(actionType));
|
||||
|
||||
for (auto &instance: instances) {
|
||||
if (instance->component.getType() == domain::Component::MEMORY) {
|
||||
memoryInstances.push_back(instance->name);
|
||||
}
|
||||
}
|
||||
|
||||
auto layout = new QVBoxLayout(this);
|
||||
this->setLayout(layout);
|
||||
auto popup = *attribute->attribute.getPopup();
|
||||
|
||||
layout->addWidget(new QLabel(popup.getTitle().c_str()));
|
||||
layout->addWidget(new QLabel(popup.getText().c_str()));
|
||||
|
||||
value = attribute->value;
|
||||
|
||||
auto *combo = new QComboBox(this);
|
||||
for (auto &entry: memoryInstances) {
|
||||
combo->addItem(QString::fromStdString(entry));
|
||||
}
|
||||
combo->addItem("null");
|
||||
|
||||
connect(combo, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &MemoryDialog::onMemoryChanged);
|
||||
layout->addWidget(combo);
|
||||
|
||||
combo->setCurrentIndex(memoryInstances.size());
|
||||
for (int i = 0; i < memoryInstances.size(); i++) {
|
||||
if (attributeValue->value.asMemoryReference().has_value() &&
|
||||
attributeValue->value.asMemoryReference() == memoryInstances[i]) {
|
||||
combo->setCurrentIndex(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
auto buttonLayout = new QHBoxLayout(this);
|
||||
|
||||
auto okButton = new QPushButton(updating ? "Ažuriraj" : "Postavi");
|
||||
auto cancelButton = new QPushButton("Odustani", this);
|
||||
|
||||
connect(okButton, &QPushButton::clicked, this, &MemoryDialog::onUpdate);
|
||||
connect(cancelButton, &QPushButton::clicked, [this]() { reject(); });
|
||||
|
||||
buttonLayout->addWidget(okButton);
|
||||
buttonLayout->addWidget(cancelButton);
|
||||
|
||||
layout->addLayout(buttonLayout);
|
||||
}
|
||||
|
||||
void MemoryDialog::onUpdate() {
|
||||
attributeValue->value = value;
|
||||
accept();
|
||||
}
|
||||
|
||||
void MemoryDialog::onMemoryChanged(int index) {
|
||||
if (index == memoryInstances.size()) {
|
||||
value = domain::Value::fromMemoryReference(std::nullopt);
|
||||
} else {
|
||||
value = domain::Value::fromMemoryReference(memoryInstances[index]);
|
||||
}
|
||||
}
|
||||
|
||||
ErrorDialog::ErrorDialog(std::vector<domain::ValidationError> errors) {
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
this->setWindowTitle("Greške");
|
||||
|
||||
auto layout = new QVBoxLayout(this);
|
||||
this->setLayout(layout);
|
||||
|
||||
for (auto &err: errors) {
|
||||
layout->addWidget(new QLabel(QString::fromStdString(err.message), this));
|
||||
}
|
||||
}
|
||||
|
||||
WarningDialog::WarningDialog(domain::ValidationError error) {
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
this->setWindowTitle("Upozorenje");
|
||||
|
||||
auto layout = new QVBoxLayout(this);
|
||||
this->setLayout(layout);
|
||||
|
||||
layout->addWidget(new QLabel(QString::fromStdString(error.message), this));
|
||||
|
||||
auto buttonLayout = new QHBoxLayout(this);
|
||||
|
||||
auto okButton = new QPushButton("U redu", this);
|
||||
auto cancelButton = new QPushButton("Odustani", this);
|
||||
|
||||
connect(okButton, &QPushButton::clicked, [this]() { accept(); });
|
||||
connect(cancelButton, &QPushButton::clicked, [this]() { reject(); });
|
||||
|
||||
buttonLayout->addWidget(okButton);
|
||||
buttonLayout->addWidget(cancelButton);
|
||||
|
||||
layout->addLayout(buttonLayout);
|
||||
}
|
||||
}
|
|
@ -1,89 +0,0 @@
|
|||
#ifndef ATTRIBUTE_DIALOG_H
|
||||
#define ATTRIBUTE_DIALOG_H
|
||||
|
||||
#include <QIntValidator>
|
||||
#include <QPushButton>
|
||||
#include <QComboBox>
|
||||
#include <QGroupBox>
|
||||
#include <QRadioButton>
|
||||
#include <QDialog>
|
||||
#include <QLineEdit>
|
||||
#include <QLabel>
|
||||
#include <QVBoxLayout>
|
||||
#include <utility>
|
||||
#include <comdel/domain/instance_attribute.h>
|
||||
|
||||
#include <comdel/domain/value.h>
|
||||
#include "comdel/domain/comdel_validator.h"
|
||||
|
||||
namespace display {
|
||||
|
||||
class AttributeDialog : public QDialog {
|
||||
domain::Value value;
|
||||
|
||||
long long int parseInt(std::string expression) {
|
||||
try {
|
||||
if (expression.size() > 2) {
|
||||
if (expression.substr(0, 2) == "0x") {
|
||||
return std::stoll(expression, nullptr, 16);
|
||||
} else if (expression.substr(0, 2) == "0b") {
|
||||
return std::stoll(expression, nullptr, 2);
|
||||
} else {
|
||||
return std::stoll(expression, nullptr, 10);
|
||||
}
|
||||
} else {
|
||||
return std::stoll(expression, nullptr, 10);
|
||||
}
|
||||
} catch (std::exception &e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
domain::InstanceAttribute *attributeValue;
|
||||
|
||||
public:
|
||||
AttributeDialog(domain::InstanceAttribute *attribute, bool updating = true);
|
||||
|
||||
public slots:
|
||||
|
||||
void onTextChanged(const QString &string);
|
||||
|
||||
void onEnumerationChanged(int index);
|
||||
|
||||
void onUpdate();
|
||||
|
||||
};
|
||||
|
||||
|
||||
class MemoryDialog : public QDialog {
|
||||
domain::Value value;
|
||||
|
||||
domain::InstanceAttribute *attributeValue;
|
||||
std::vector<std::string> memoryInstances;
|
||||
|
||||
public:
|
||||
MemoryDialog(domain::InstanceAttribute *attribute,
|
||||
std::vector<std::shared_ptr<domain::ComponentInstance>> instances, bool updating = true);
|
||||
|
||||
public slots:
|
||||
|
||||
void onMemoryChanged(int index);
|
||||
|
||||
void onUpdate();
|
||||
|
||||
};
|
||||
|
||||
|
||||
class ErrorDialog : public QDialog {
|
||||
public:
|
||||
ErrorDialog(std::vector<domain::ValidationError> errors);
|
||||
};
|
||||
|
||||
class WarningDialog : public QDialog {
|
||||
public:
|
||||
WarningDialog(domain::ValidationError error);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //ATTRIBUTE_DIALOG_H
|
|
@ -1,9 +1,11 @@
|
|||
#include "component_display.h"
|
||||
#include "attribute_dialog.h"
|
||||
#include "name_dialog.h"
|
||||
#include "comdel/display/dialog/attribute_dialog.h"
|
||||
#include "comdel/display/dialog/name_dialog.h"
|
||||
#include "mainwindow.h"
|
||||
#include "application.h"
|
||||
#include "single_automatic_dialog.h"
|
||||
#include "comdel/display/dialog/single_automatic_dialog.h"
|
||||
#include "comdel/display/dialog/memory_dialog.h"
|
||||
#include "message_source.h"
|
||||
|
||||
#include <QMenu>
|
||||
#include <QLine>
|
||||
|
@ -18,13 +20,13 @@ namespace display {
|
|||
|
||||
Component::Component(const std::shared_ptr<domain::ComponentInstance> &instance): instance(instance) {
|
||||
setFlag(ItemSendsGeometryChanges, true);
|
||||
setToolTip(QString::fromStdString(instance->name + "::" + instance->component.getName()));
|
||||
setToolTip(QString::fromStdString(instance->name + "::" + instance->component.getDisplayName()));
|
||||
instance->component.getDisplay().render(this, domain::ui::DisplayContext(instance.get()));
|
||||
}
|
||||
|
||||
void Component::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) {
|
||||
QMenu menu;
|
||||
menu.addAction("Izmjeni ime", [this]() {
|
||||
menu.addAction(QMESSAGE("msg_dialog_name_update"), [this]() {
|
||||
std::set<std::string> names;
|
||||
for(const auto &component: Application::instance()->getSchema()->componentInstances) {
|
||||
names.insert(component->name);
|
||||
|
@ -36,7 +38,7 @@ namespace display {
|
|||
auto newName = dialog->getName();
|
||||
|
||||
Application::instance()->renameComponent(currentName, newName);
|
||||
setToolTip(QString::fromStdString(instance->name + "::" + instance->component.getName()));
|
||||
setToolTip(QString::fromStdString(instance->name + "::" + instance->component.getDisplayName()));
|
||||
});
|
||||
menu.addSeparator();
|
||||
for (int i = 0; i < this->instance->attributes.size(); i++) {
|
||||
|
@ -44,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(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->name + "'"),
|
||||
[attr]() {
|
||||
auto dialog = new AttributeDialog(attr);
|
||||
dialog->exec();
|
||||
});
|
||||
std::map<std::string, std::string> params = {{"attribute", attr->attribute.getDisplayName()}};
|
||||
auto action = menu.addAction(QMESSAGE_PARAM("msg_dialog_attribute_update", params),
|
||||
[attr]() {
|
||||
std::map<std::string, std::string> 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<std::string, std::string> 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<Schema *>(this->scene()->views()[0]);
|
||||
view->refreshContent();
|
||||
|
@ -74,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<domain::DirectConnectionInstance *>(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(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<Schema *>(this->scene()->views()[0]);
|
||||
|
@ -108,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->name + "'"),[attr]() {
|
||||
auto dialog = new AttributeDialog(attr);
|
||||
dialog->exec();
|
||||
std::map<std::string, std::string> params = {{"name", attr->attribute.getDisplayName()}};
|
||||
menu.addAction(QMESSAGE_PARAM("msg_dialog_actions_update_named", params),
|
||||
[attr]() {
|
||||
std::map<std::string, std::string> 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<Schema *>(this->scene()->views()[0]);
|
||||
view->refreshContent();
|
||||
|
@ -185,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<std::string> names;
|
||||
for(const auto &component: Application::instance()->getSchema()->busInstances) {
|
||||
names.insert(component->name);
|
||||
|
@ -197,10 +218,12 @@ namespace display {
|
|||
auto newName = dialog->getName();
|
||||
|
||||
Application::instance()->renameBus(currentName, newName);
|
||||
setToolTip(QString::fromStdString(busInstance->name + "::" + busInstance->bus.getName()));
|
||||
setToolTip(QString::fromStdString(busInstance->name + "::" + busInstance->bus.getDisplayName()));
|
||||
});
|
||||
menu.addSeparator();
|
||||
menu.addAction(QString::fromStdString("Ukloni " + this->busInstance->name), [this]() {
|
||||
|
||||
std::map<std::string, std::string> 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<Schema *>(this->scene()->views()[0]);
|
||||
view->refreshContent();
|
||||
|
@ -305,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(),
|
||||
|
|
|
@ -0,0 +1,182 @@
|
|||
#include "attribute_dialog.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include "application.h"
|
||||
#include "error_dialog.h"
|
||||
#include "warning_dialog.h"
|
||||
#include "message_source.h"
|
||||
#include <stdexcept>
|
||||
|
||||
namespace display {
|
||||
|
||||
long long int parseInt(std::string expression) {
|
||||
try {
|
||||
if (expression.size() > 2) {
|
||||
if (expression.substr(0, 2) == "0x") {
|
||||
return std::stoll(expression, nullptr, 16);
|
||||
} else if (expression.substr(0, 2) == "0b") {
|
||||
return std::stoll(expression, nullptr, 2);
|
||||
} else {
|
||||
return std::stoll(expression, nullptr, 10);
|
||||
}
|
||||
} else {
|
||||
return std::stoll(expression, nullptr, 10);
|
||||
}
|
||||
} catch (std::exception &e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
AttributeDialog::AttributeDialog(std::string title, std::string action, domain::InstanceAttribute *attribute):
|
||||
GenericDialog(title, action), attributeValue(attribute), value(attribute->value), popup(*attribute->attribute.getPopup()) {
|
||||
|
||||
auto *contentLayout = new QVBoxLayout();
|
||||
content->setLayout(contentLayout);
|
||||
|
||||
contentLayout->addWidget(new QLabel(popup.getTitle().c_str()));
|
||||
contentLayout->addWidget(new QLabel(popup.getText().c_str()));
|
||||
|
||||
auto type = attribute->value.getType();
|
||||
|
||||
if(popup.isEnumerated()) {
|
||||
contentLayout->addWidget(setupEnumeration());
|
||||
} else if(type == domain::Value::INT || type == domain::Value::STRING) {
|
||||
contentLayout->addWidget(setupLineEdit(type));
|
||||
} else if(type == domain::Value::BOOL) {
|
||||
contentLayout->addWidget(setupBool());
|
||||
}
|
||||
}
|
||||
|
||||
bool AttributeDialog::onUpdate() {
|
||||
auto validationErrors = validate();
|
||||
if (validationErrors.empty()) {
|
||||
attributeValue->value = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<domain::ValidationError> errors, warnings;
|
||||
for (auto &err: validationErrors) {
|
||||
if (err.type == domain::Action::ERROR) {
|
||||
errors.push_back(err);
|
||||
} else {
|
||||
warnings.push_back(err);
|
||||
}
|
||||
}
|
||||
|
||||
if (!errors.empty()) {
|
||||
auto errorDialog = new ErrorDialog(errors);
|
||||
errorDialog->exec();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool canAccept = true;
|
||||
for (auto &warning: warnings) {
|
||||
auto warningDialog = new WarningDialog(warning);
|
||||
int response = warningDialog->exec();
|
||||
if (response == QDialog::Rejected) {
|
||||
canAccept = false;
|
||||
}
|
||||
}
|
||||
if(canAccept) {
|
||||
attributeValue->value = value;
|
||||
}
|
||||
return canAccept;
|
||||
}
|
||||
|
||||
void AttributeDialog::onTextChanged(const QString &string) {
|
||||
switch (value.getType()) {
|
||||
case domain::Value::STRING:
|
||||
value.setString(string.toStdString());
|
||||
break;
|
||||
case domain::Value::INT:
|
||||
value = domain::Value::fromInt(parseInt(string.toStdString()));
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("invalid value type in text change");
|
||||
}
|
||||
}
|
||||
|
||||
void AttributeDialog::onEnumerationChanged(int index) {
|
||||
value = attributeValue->attribute.getPopup()->getEnumeration()[index].getValue();
|
||||
}
|
||||
|
||||
QComboBox *AttributeDialog::setupEnumeration() {
|
||||
auto *combo = new QComboBox(this);
|
||||
|
||||
auto enumeration = popup.getEnumeration();
|
||||
for (auto entry: enumeration) {
|
||||
combo->addItem(QString::fromStdString(entry.getName()));
|
||||
}
|
||||
connect(combo, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
|
||||
&AttributeDialog::onEnumerationChanged);
|
||||
|
||||
for (int i = 0; i < enumeration.size(); i++) {
|
||||
if (attributeValue->value.equals(enumeration[i].getValue())) {
|
||||
combo->setCurrentIndex(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return combo;
|
||||
}
|
||||
|
||||
QLineEdit *AttributeDialog::setupLineEdit(domain::Value::ValueType type) {
|
||||
auto edit = new QLineEdit(this);
|
||||
connect(edit, &QLineEdit::textChanged, this, &AttributeDialog::onTextChanged);
|
||||
|
||||
switch (type) {
|
||||
case domain::Value::ValueType::INT:
|
||||
edit->setValidator(new QIntValidator(-10000000, 10000000, edit));
|
||||
edit->insert(std::to_string(value.asInt()).c_str());
|
||||
break;
|
||||
case domain::Value::ValueType::STRING:
|
||||
edit->insert(value.asString().c_str());
|
||||
break;
|
||||
}
|
||||
return edit;
|
||||
}
|
||||
|
||||
QGroupBox *AttributeDialog::setupBool() {
|
||||
auto *group = new QGroupBox(this);
|
||||
|
||||
auto *radioLayout = new QHBoxLayout(group);
|
||||
group->setLayout(radioLayout);
|
||||
|
||||
auto isTrue = new QRadioButton(QMESSAGE("msg_boolean_true"), group);
|
||||
connect(isTrue, &QRadioButton::clicked, [this]() {
|
||||
this->value = domain::Value::fromBool(true);
|
||||
});
|
||||
auto isFalse = new QRadioButton(QMESSAGE("msg_boolean_false"), group);
|
||||
connect(isFalse, &QRadioButton::clicked, [this]() {
|
||||
this->value = domain::Value::fromBool(false);
|
||||
});
|
||||
|
||||
if (value.asBool()) {
|
||||
isTrue->setChecked(true);
|
||||
} else {
|
||||
isFalse->setChecked(true);
|
||||
}
|
||||
|
||||
radioLayout->addWidget(isTrue);
|
||||
radioLayout->addWidget(isFalse);
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
std::vector<domain::ValidationError> AttributeDialog::validate() {
|
||||
domain::ComdelValidator validator(domain::getSupportedValidators());
|
||||
|
||||
auto currentValue = attributeValue->value;
|
||||
attributeValue->value = value;
|
||||
domain::ValidationContext context;
|
||||
|
||||
for (auto &addressSpace: Application::instance()->getLibrary()->getAddressSpaces()) {
|
||||
context.addressSpaces.insert(std::make_pair(addressSpace.getName(), addressSpace));
|
||||
}
|
||||
|
||||
auto errors = validator.validateAttribute(attributeValue, context);
|
||||
attributeValue->value = currentValue;
|
||||
return errors;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
#ifndef ATTRIBUTE_DIALOG_H
|
||||
#define ATTRIBUTE_DIALOG_H
|
||||
|
||||
#include <QIntValidator>
|
||||
#include <QPushButton>
|
||||
#include <QComboBox>
|
||||
#include <QGroupBox>
|
||||
#include <QRadioButton>
|
||||
#include <QDialog>
|
||||
#include <QLineEdit>
|
||||
#include <QLabel>
|
||||
#include <QVBoxLayout>
|
||||
#include <utility>
|
||||
#include "comdel/domain/instance_attribute.h"
|
||||
|
||||
#include "comdel/domain/value.h"
|
||||
#include "comdel/domain/comdel_validator.h"
|
||||
#include "generic_dialog.h"
|
||||
|
||||
namespace display {
|
||||
|
||||
class AttributeDialog : public GenericDialog {
|
||||
public:
|
||||
AttributeDialog(std::string title, std::string action, domain::InstanceAttribute *attribute);
|
||||
|
||||
public slots:
|
||||
void onTextChanged(const QString &string);
|
||||
void onEnumerationChanged(int index);
|
||||
|
||||
protected:
|
||||
bool onUpdate() override;
|
||||
|
||||
private:
|
||||
QComboBox *setupEnumeration();
|
||||
QLineEdit *setupLineEdit(domain::Value::ValueType type);
|
||||
QGroupBox *setupBool();
|
||||
|
||||
std::vector<domain::ValidationError> validate();
|
||||
|
||||
domain::Value value;
|
||||
domain::InstanceAttribute *attributeValue;
|
||||
domain::Popup popup;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //ATTRIBUTE_DIALOG_H
|
|
@ -0,0 +1,34 @@
|
|||
#include <QVBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QPlainTextEdit>
|
||||
#include "error_dialog.h"
|
||||
|
||||
namespace display {
|
||||
|
||||
ErrorDialog::ErrorDialog(std::vector<domain::ValidationError> errors)
|
||||
: GenericDialog("msg_dialog_error_title", std::nullopt, "msg_dialog_error_close") {
|
||||
|
||||
auto contentLayout = new QVBoxLayout();
|
||||
content->setLayout(contentLayout);
|
||||
|
||||
for (auto &err: errors) {
|
||||
contentLayout->addWidget(new QLabel(QString::fromStdString(err.message), this));
|
||||
}
|
||||
}
|
||||
|
||||
ErrorDialog::ErrorDialog(std::ostringstream& errorStream)
|
||||
: GenericDialog("msg_dialog_error_title", std::nullopt, "msg_dialog_error_close") {
|
||||
|
||||
auto contentLayout = new QVBoxLayout();
|
||||
content->setLayout(contentLayout);
|
||||
|
||||
setMinimumWidth(1000);
|
||||
|
||||
auto log = new QPlainTextEdit();
|
||||
log->setFont(QFont("Courier"));
|
||||
log->appendPlainText(QString::fromStdString(errorStream.str()));
|
||||
log->setReadOnly(true);
|
||||
contentLayout->addWidget(log);
|
||||
}
|
||||
|
||||
} // display
|
|
@ -0,0 +1,22 @@
|
|||
#ifndef SCHEMEEDITOR_ERROR_DIALOG_H
|
||||
#define SCHEMEEDITOR_ERROR_DIALOG_H
|
||||
|
||||
#include "generic_dialog.h"
|
||||
#include "comdel/domain/comdel_validator.h"
|
||||
#include <sstream>
|
||||
|
||||
|
||||
namespace display {
|
||||
|
||||
class ErrorDialog : public GenericDialog {
|
||||
public:
|
||||
ErrorDialog(std::vector<domain::ValidationError> errors);
|
||||
ErrorDialog(std::ostringstream& errorStream);
|
||||
|
||||
protected:
|
||||
bool onUpdate() override { return true; }
|
||||
};
|
||||
|
||||
} // display
|
||||
|
||||
#endif //SCHEMEEDITOR_ERROR_DIALOG_H
|
|
@ -0,0 +1,35 @@
|
|||
#include <QVBoxLayout>
|
||||
#include "generic_dialog.h"
|
||||
|
||||
#include "message_source.h"
|
||||
|
||||
display::GenericDialog::GenericDialog(std::string title, std::optional<std::string> action, std::string cancel) {
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
setWindowTitle(QMESSAGE(title));
|
||||
|
||||
setLayout(new QVBoxLayout());
|
||||
content = new QWidget(this);
|
||||
layout()->addWidget(content);
|
||||
|
||||
auto actionWidget = new QWidget(this);
|
||||
auto actionBar = new QHBoxLayout(actionWidget);
|
||||
layout()->addWidget(actionWidget);
|
||||
|
||||
// if action isn't defined only close button is offered
|
||||
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(QMESSAGE(cancel), this);
|
||||
connect(cancelButton, &QPushButton::clicked, [this]() { reject(); });
|
||||
actionBar->addWidget(cancelButton);
|
||||
}
|
||||
|
||||
void display::GenericDialog::setOkButtonDisabled(bool disabled) {
|
||||
okButton->setDisabled(disabled);
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
#ifndef SCHEMEEDITOR_GENERIC_DIALOG_H
|
||||
#define SCHEMEEDITOR_GENERIC_DIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QWidget>
|
||||
#include <QPushButton>
|
||||
|
||||
#include <optional>
|
||||
|
||||
namespace display {
|
||||
|
||||
class GenericDialog: public QDialog {
|
||||
public:
|
||||
|
||||
explicit GenericDialog(std::string title,
|
||||
std::optional<std::string> action = "msg_dialog_actions_update",
|
||||
std::string cancel = "msg_dialog_actions_cancel");
|
||||
|
||||
protected:
|
||||
void setOkButtonDisabled(bool disabled);
|
||||
virtual bool onUpdate() = 0;
|
||||
|
||||
private:
|
||||
QPushButton *okButton;
|
||||
QPushButton *cancelButton;
|
||||
|
||||
protected:
|
||||
QWidget *content;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //SCHEMEEDITOR_GENERIC_DIALOG_H
|
|
@ -0,0 +1,60 @@
|
|||
#include <QVBoxLayout>
|
||||
#include <QLabel>
|
||||
#include "memory_dialog.h"
|
||||
#include "message_source.h"
|
||||
|
||||
namespace display {
|
||||
|
||||
|
||||
MemoryDialog::MemoryDialog(std::string title, std::string action, domain::InstanceAttribute *attribute,
|
||||
std::vector<std::shared_ptr<domain::ComponentInstance>> instances)
|
||||
: GenericDialog(title, action), value(attribute->value), attributeValue(attribute), popup(*attribute->attribute.getPopup()) {
|
||||
|
||||
for (auto &instance: instances) {
|
||||
if (instance->component.getType() == domain::Component::MEMORY) {
|
||||
memoryInstances.push_back(instance->name);
|
||||
}
|
||||
}
|
||||
|
||||
auto contentLayout = new QVBoxLayout(content);
|
||||
content->setLayout(contentLayout);
|
||||
|
||||
contentLayout->addWidget(new QLabel(popup.getTitle().c_str()));
|
||||
contentLayout->addWidget(new QLabel(popup.getText().c_str()));
|
||||
|
||||
contentLayout->addWidget(setupEnumeration());
|
||||
}
|
||||
|
||||
bool MemoryDialog::onUpdate() {
|
||||
attributeValue->value = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
QComboBox *MemoryDialog::setupEnumeration() {
|
||||
auto *combo = new QComboBox(this);
|
||||
|
||||
for (const auto& entry: memoryInstances) {
|
||||
combo->addItem(QString::fromStdString(entry));
|
||||
}
|
||||
combo->addItem(QMESSAGE("msg_dialog_memory_default"));
|
||||
|
||||
connect(combo, QOverload<int>::of(&QComboBox::currentIndexChanged), [this](int index) {
|
||||
if(index == memoryInstances.size()) {
|
||||
value = domain::Value::fromMemoryReference(std::nullopt);
|
||||
} else {
|
||||
value = domain::Value::fromMemoryReference(this->memoryInstances[index]);
|
||||
}
|
||||
});
|
||||
|
||||
combo->setCurrentIndex(memoryInstances.size());
|
||||
for (int i = 0; i < memoryInstances.size(); i++) {
|
||||
if (attributeValue->value.equals(domain::Value::fromMemoryReference(memoryInstances[i]))) {
|
||||
combo->setCurrentIndex(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return combo;
|
||||
}
|
||||
|
||||
} // display
|
|
@ -0,0 +1,33 @@
|
|||
#ifndef SCHEMEEDITOR_MEMORY_DIALOG_H
|
||||
#define SCHEMEEDITOR_MEMORY_DIALOG_H
|
||||
|
||||
#include <QComboBox>
|
||||
#include "generic_dialog.h"
|
||||
#include "comdel/domain/instance_attribute.h"
|
||||
#include "comdel/domain/instance.h"
|
||||
|
||||
|
||||
namespace display {
|
||||
|
||||
class MemoryDialog : public GenericDialog {
|
||||
public:
|
||||
MemoryDialog(std::string title, std::string action, domain::InstanceAttribute *attribute,
|
||||
std::vector<std::shared_ptr<domain::ComponentInstance>> instances);
|
||||
|
||||
protected:
|
||||
bool onUpdate() override;
|
||||
|
||||
private:
|
||||
QComboBox *setupEnumeration();
|
||||
|
||||
domain::Value value;
|
||||
domain::InstanceAttribute *attributeValue;
|
||||
std::vector<std::string> memoryInstances;
|
||||
|
||||
domain::Popup popup;
|
||||
};
|
||||
|
||||
|
||||
} // display
|
||||
|
||||
#endif //SCHEMEEDITOR_MEMORY_DIALOG_H
|
|
@ -0,0 +1,40 @@
|
|||
#include <set>
|
||||
#include "name_dialog.h"
|
||||
#include "message_source.h"
|
||||
|
||||
namespace display {
|
||||
|
||||
NameDialog::NameDialog(std::string currentName, std::set<std::string> &names)
|
||||
: GenericDialog("msg_dialog_name_update"), currentName(currentName), usedNames(names) {
|
||||
|
||||
usedNames.erase(currentName);
|
||||
|
||||
auto *contentLayout = new QVBoxLayout();
|
||||
contentLayout->addWidget(new QLabel(QMESSAGE("msg_dialog_name_update"), this));
|
||||
|
||||
edit = new QLineEdit(this);
|
||||
edit->insert(currentName.c_str());
|
||||
connect(edit, &QLineEdit::textChanged, this, &NameDialog::onNameUpdate);
|
||||
contentLayout->addWidget(edit);
|
||||
|
||||
content->setLayout(contentLayout);
|
||||
}
|
||||
|
||||
void NameDialog::onNameUpdate(const QString &text) {
|
||||
if(usedNames.find(text.toStdString()) == usedNames.end()) {
|
||||
setOkButtonDisabled(false);
|
||||
} else {
|
||||
setOkButtonDisabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
std::string NameDialog::getName() {
|
||||
return currentName;
|
||||
}
|
||||
|
||||
bool NameDialog::onUpdate() {
|
||||
currentName = edit->text().toStdString();
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -9,25 +9,29 @@
|
|||
|
||||
#include <set>
|
||||
|
||||
#include <comdel/domain/instance.h>
|
||||
#include "comdel/domain/instance.h"
|
||||
#include "generic_dialog.h"
|
||||
|
||||
namespace display {
|
||||
|
||||
class NameDialog : public QDialog {
|
||||
|
||||
std::set<std::string> usedNames;
|
||||
QLineEdit *edit = nullptr;
|
||||
std::string currentName;
|
||||
QPushButton *button;
|
||||
class NameDialog : public GenericDialog {
|
||||
|
||||
public:
|
||||
NameDialog(std::string currentName, std::set<std::string>& names);
|
||||
|
||||
std::string getName();
|
||||
|
||||
protected:
|
||||
bool onUpdate() override;
|
||||
|
||||
public slots:
|
||||
void onNameUpdate(const QString& text);
|
||||
void onNameChange();
|
||||
|
||||
private:
|
||||
std::set<std::string> usedNames;
|
||||
QLineEdit *edit = nullptr;
|
||||
std::string currentName;
|
||||
|
||||
};
|
||||
|
||||
}
|
|
@ -1,7 +1,3 @@
|
|||
//
|
||||
// Created by bbr on 05.06.22..
|
||||
//
|
||||
|
||||
#include "single_automatic_dialog.h"
|
||||
#include <QVBoxLayout>
|
||||
#include <QLabel>
|
||||
|
@ -9,38 +5,23 @@
|
|||
#include <QPushButton>
|
||||
|
||||
namespace display {
|
||||
SingleAutomaticDialog::SingleAutomaticDialog(std::vector<domain::InstanceAttribute> &values, bool updating): attributes(values) {
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
setWindowTitle(QString::fromStdString(updating ? "Ažuriraj poveznicu" : "Postavi poveznicu"));
|
||||
|
||||
SingleAutomaticDialog::SingleAutomaticDialog(std::string title, std::string action,
|
||||
std::vector<domain::InstanceAttribute> &values)
|
||||
: GenericDialog(title, action), attributes(values) {
|
||||
firstValue = values[0].value;
|
||||
secondValue = values[1].value;
|
||||
|
||||
auto *parentLayout = new QVBoxLayout(this);
|
||||
auto *contentLayout = new QHBoxLayout(this);
|
||||
auto *firstLayout = new QVBoxLayout(this);
|
||||
auto *secondLayout = new QVBoxLayout(this);
|
||||
auto *contentLayout = new QHBoxLayout();
|
||||
auto *firstLayout = new QVBoxLayout();
|
||||
auto *secondLayout = new QVBoxLayout();
|
||||
|
||||
parentLayout->addLayout(contentLayout);
|
||||
content->setLayout(contentLayout);
|
||||
contentLayout->addLayout(firstLayout);
|
||||
contentLayout->addLayout(secondLayout);
|
||||
this->setLayout(parentLayout);
|
||||
|
||||
setupValues(firstLayout, values[0], &SingleAutomaticDialog::onFirstEnumerationChanged);
|
||||
setupValues(secondLayout, values[1], &SingleAutomaticDialog::onSecondEnumerationChanged);
|
||||
|
||||
auto buttonLayout = new QHBoxLayout(this);
|
||||
|
||||
auto okButton = new QPushButton("U redu", this);
|
||||
auto cancelButton = new QPushButton("Odustani", this);
|
||||
|
||||
connect(okButton, &QPushButton::clicked, [this]() { accept(); });
|
||||
connect(cancelButton, &QPushButton::clicked, [this]() { reject(); });
|
||||
|
||||
buttonLayout->addWidget(okButton);
|
||||
buttonLayout->addWidget(cancelButton);
|
||||
|
||||
parentLayout->addLayout(buttonLayout);
|
||||
}
|
||||
|
||||
void SingleAutomaticDialog::setupValues(QVBoxLayout *layout, domain::InstanceAttribute &attribute, void (display::SingleAutomaticDialog::* handler)(int)) {
|
||||
|
@ -75,10 +56,10 @@ namespace display {
|
|||
secondValue = attributes[1].attribute.getPopup()->getEnumeration()[index].getValue();
|
||||
}
|
||||
|
||||
void SingleAutomaticDialog::onUpdate() {
|
||||
bool SingleAutomaticDialog::onUpdate() {
|
||||
attributes[0].value = firstValue;
|
||||
attributes[1].value = secondValue;
|
||||
accept();
|
||||
return true;
|
||||
}
|
||||
|
||||
} // display
|
|
@ -1,7 +1,3 @@
|
|||
//
|
||||
// Created by bbr on 05.06.22..
|
||||
//
|
||||
|
||||
#ifndef SCHEMEEDITOR_SINGLE_AUTOMATIC_DIALOG_H
|
||||
#define SCHEMEEDITOR_SINGLE_AUTOMATIC_DIALOG_H
|
||||
|
||||
|
@ -10,24 +6,29 @@
|
|||
#include <QVBoxLayout>
|
||||
#include "comdel/domain/value.h"
|
||||
#include "comdel/domain/instance_attribute.h"
|
||||
#include "generic_dialog.h"
|
||||
|
||||
namespace display {
|
||||
|
||||
class SingleAutomaticDialog: public QDialog {
|
||||
class SingleAutomaticDialog: public GenericDialog {
|
||||
domain::Value firstValue;
|
||||
domain::Value secondValue;
|
||||
std::vector<domain::InstanceAttribute> &attributes;
|
||||
|
||||
public:
|
||||
explicit SingleAutomaticDialog(std::vector<domain::InstanceAttribute>& values, bool updating = true);
|
||||
explicit SingleAutomaticDialog(
|
||||
std::string title,
|
||||
std::string action,
|
||||
std::vector<domain::InstanceAttribute>& values);
|
||||
|
||||
protected:
|
||||
bool onUpdate() override;
|
||||
void setupValues(QVBoxLayout *layout, domain::InstanceAttribute &attribute, void (display::SingleAutomaticDialog::* handler)(int));
|
||||
|
||||
public slots:
|
||||
|
||||
void onFirstEnumerationChanged(int index);
|
||||
void onSecondEnumerationChanged(int index);
|
||||
void onUpdate();
|
||||
};
|
||||
|
||||
} // display
|
|
@ -0,0 +1,19 @@
|
|||
#include <QVBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include "success_dialog.h"
|
||||
#include "message_source.h"
|
||||
|
||||
namespace display {
|
||||
|
||||
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(QMESSAGE("msg_dialog_actions_ok"));
|
||||
connect(button, &QPushButton::clicked, [this]() {accept();});
|
||||
layout()->addWidget(button);
|
||||
}
|
||||
|
||||
} // display
|
|
@ -0,0 +1,19 @@
|
|||
//
|
||||
// Created by bbr on 14.06.22..
|
||||
//
|
||||
|
||||
#ifndef SCHEMEEDITOR_SUCCESS_DIALOG_H
|
||||
#define SCHEMEEDITOR_SUCCESS_DIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
namespace display {
|
||||
|
||||
class SuccessDialog: public QDialog {
|
||||
public:
|
||||
explicit SuccessDialog(std::string message);
|
||||
};
|
||||
|
||||
} // display
|
||||
|
||||
#endif //SCHEMEEDITOR_SUCCESS_DIALOG_H
|
|
@ -0,0 +1,16 @@
|
|||
#include <QVBoxLayout>
|
||||
#include <QLabel>
|
||||
#include "warning_dialog.h"
|
||||
|
||||
namespace display {
|
||||
|
||||
WarningDialog::WarningDialog(domain::ValidationError error)
|
||||
: GenericDialog("msg_dialog_warning_title", "msg_dialog_actions_ok") {
|
||||
|
||||
auto contentLayout = new QVBoxLayout();
|
||||
content->setLayout(contentLayout);
|
||||
|
||||
contentLayout->addWidget(new QLabel(QString::fromStdString(error.message), this));
|
||||
}
|
||||
|
||||
} // display
|
|
@ -0,0 +1,20 @@
|
|||
#ifndef SCHEMEEDITOR_WARNING_DIALOG_H
|
||||
#define SCHEMEEDITOR_WARNING_DIALOG_H
|
||||
|
||||
#include "generic_dialog.h"
|
||||
#include "comdel/domain/comdel_validator.h"
|
||||
|
||||
namespace display {
|
||||
|
||||
class WarningDialog : public GenericDialog {
|
||||
public:
|
||||
WarningDialog(domain::ValidationError error);
|
||||
|
||||
protected:
|
||||
bool onUpdate() override { return true; };
|
||||
};
|
||||
|
||||
|
||||
} // display
|
||||
|
||||
#endif //SCHEMEEDITOR_WARNING_DIALOG_H
|
|
@ -1,4 +1,5 @@
|
|||
#include "library_display.h"
|
||||
#include "message_source.h"
|
||||
|
||||
#include <QLabel>
|
||||
#include <QListWidget>
|
||||
|
@ -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();
|
||||
|
||||
|
@ -33,7 +41,7 @@ namespace display {
|
|||
}
|
||||
|
||||
for (auto &component: library->getComponents()) {
|
||||
auto item = new LibraryListItem{component.getName(), "comdel/component", component.getName(),
|
||||
auto item = new LibraryListItem{component.getDisplayName(), "comdel/component", component.getName(),
|
||||
componentList};
|
||||
item->setToolTip(QString::fromStdString(component.getTooltip()));
|
||||
componentList->addItem(item);
|
||||
|
@ -41,7 +49,7 @@ namespace display {
|
|||
|
||||
for (auto &bus: library->getBuses()) {
|
||||
if (bus.getType() == domain::Bus::REGULAR) {
|
||||
auto item = new LibraryListItem{bus.getName(), "comdel/bus", bus.getName(), busList};
|
||||
auto item = new LibraryListItem{bus.getDisplayName(), "comdel/bus", bus.getName(), busList};
|
||||
item->setToolTip(QString::fromStdString(bus.getTooltip()));
|
||||
busList->addItem(item);
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <QWidget>
|
||||
|
||||
#include <comdel/domain/library.h>
|
||||
#include <QLabel>
|
||||
#include "library_list.h"
|
||||
|
||||
namespace display {
|
||||
|
@ -21,6 +22,8 @@ namespace display {
|
|||
LibraryList *componentList;
|
||||
LibraryList *busList;
|
||||
|
||||
QLabel *componentsLabel;
|
||||
QLabel *busLabel;
|
||||
};
|
||||
|
||||
} // namespace display
|
||||
|
|
|
@ -1,50 +0,0 @@
|
|||
//
|
||||
// Created by bbr on 18. 04. 2022..
|
||||
//
|
||||
|
||||
#include <set>
|
||||
#include "name_dialog.h"
|
||||
|
||||
display::NameDialog::NameDialog(std::string currentName, std::set<std::string> &names): currentName(currentName) {
|
||||
usedNames.erase(currentName);
|
||||
|
||||
auto *layout = new QVBoxLayout(this);
|
||||
layout->addWidget(new QLabel("Izmjeni ime", this));
|
||||
|
||||
edit = new QLineEdit(this);
|
||||
edit->insert(currentName.c_str());
|
||||
connect(edit, &QLineEdit::textChanged, this, &NameDialog::onNameUpdate);
|
||||
layout->addWidget(edit);
|
||||
setWindowTitle("Izmjeni ime");
|
||||
setLayout(layout);
|
||||
|
||||
auto buttonLayout = new QHBoxLayout(this);
|
||||
|
||||
button = new QPushButton("Ažuriraj");
|
||||
auto cancelButton = new QPushButton("Odustani", this);
|
||||
|
||||
connect(button, &QPushButton::clicked, this, &NameDialog::onNameChange);
|
||||
connect(cancelButton, &QPushButton::clicked, [this]() { reject(); });
|
||||
|
||||
buttonLayout->addWidget(button);
|
||||
buttonLayout->addWidget(cancelButton);
|
||||
|
||||
layout->addLayout(buttonLayout);
|
||||
}
|
||||
|
||||
void display::NameDialog::onNameUpdate(const QString &text) {
|
||||
if(usedNames.find(text.toStdString()) == usedNames.end()) {
|
||||
button->setDisabled(false);
|
||||
} else {
|
||||
button->setDisabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
void display::NameDialog::onNameChange() {
|
||||
currentName = edit->text().toStdString();
|
||||
close();
|
||||
}
|
||||
|
||||
std::string display::NameDialog::getName() {
|
||||
return currentName;
|
||||
}
|
|
@ -1,12 +1,15 @@
|
|||
#include "component_display.h"
|
||||
#include "schema_display.h"
|
||||
#include "application.h"
|
||||
#include "attribute_dialog.h"
|
||||
#include "single_automatic_dialog.h"
|
||||
#include "comdel/display/dialog/attribute_dialog.h"
|
||||
#include "comdel/display/dialog/single_automatic_dialog.h"
|
||||
#include "comdel/display/dialog/memory_dialog.h"
|
||||
|
||||
#include <QDrag>
|
||||
#include <QDragEnterEvent>
|
||||
#include <QMimeData>
|
||||
#include "message_source.h"
|
||||
|
||||
|
||||
namespace display {
|
||||
|
||||
|
@ -182,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);
|
||||
|
@ -198,12 +201,22 @@ namespace display {
|
|||
return;
|
||||
}
|
||||
|
||||
auto conInstance = std::make_shared<domain::DirectConnectionInstance>(instance,
|
||||
components[pinInstance.component]->getComponentInstance().get(),
|
||||
attributes, busInstance.get(),
|
||||
*con);
|
||||
std::shared_ptr<domain::DirectConnectionInstance> conInstance = nullptr;
|
||||
if(con->getComponent() == domain::ConnectionComponent{instance->component.getName(), context.pin->getPin().getName()}) {
|
||||
conInstance = std::make_shared<domain::DirectConnectionInstance>(instance,
|
||||
components[pinInstance.component]->getComponentInstance().get(),
|
||||
attributes, busInstance.get(),
|
||||
*con);
|
||||
} else {
|
||||
conInstance = std::make_shared<domain::DirectConnectionInstance>(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],
|
||||
|
@ -275,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(&attribute, schema->componentInstances, false);
|
||||
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(&attribute, false);
|
||||
std::map<std::string, std::string> 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 {};
|
||||
|
@ -300,7 +314,7 @@ namespace display {
|
|||
instanceAttributes.emplace_back(attr.getName(), attr.getDefault(), attr);
|
||||
}
|
||||
|
||||
auto dialog = new display::SingleAutomaticDialog(instanceAttributes, false);
|
||||
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 {};
|
||||
|
|
|
@ -44,8 +44,15 @@ namespace domain {
|
|||
}
|
||||
|
||||
|
||||
Attribute::Attribute(std::string name, Value defaultValue, std::optional<Popup> popup)
|
||||
: name(name), defaultValue(defaultValue), popup(popup) {}
|
||||
Attribute::Attribute(std::string name, std::optional<std::string> displayName, Value defaultValue, std::optional<Popup> popup)
|
||||
: name(name), displayName(displayName), defaultValue(defaultValue), popup(popup) {}
|
||||
|
||||
std::string Attribute::getDisplayName() {
|
||||
if(displayName.has_value()) {
|
||||
return *displayName;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
std::string Attribute::getName() {
|
||||
return name;
|
||||
|
|
|
@ -61,13 +61,16 @@ namespace domain {
|
|||
|
||||
class Attribute {
|
||||
std::string name;
|
||||
std::optional<std::string> displayName;
|
||||
Value defaultValue;
|
||||
std::optional<Popup> popup;
|
||||
public:
|
||||
Attribute(std::string name, Value defaultValue, std::optional<Popup> popup = std::nullopt);
|
||||
Attribute(std::string name, std::optional<std::string> displayName, Value defaultValue, std::optional<Popup> popup = std::nullopt);
|
||||
|
||||
std::string getName();
|
||||
|
||||
std::string getDisplayName();
|
||||
|
||||
Value getDefault();
|
||||
|
||||
std::optional<Popup> getPopup();
|
||||
|
|
|
@ -35,14 +35,21 @@ namespace domain {
|
|||
return type;
|
||||
}
|
||||
|
||||
Bus::Bus(std::string name, std::string instanceName, std::string tooltip, BusType type, std::pair<int, int> count, std::vector<Wire> wires,
|
||||
Bus::Bus(std::string name, std::optional<std::string> displayName, std::string instanceName, std::string tooltip, BusType type, std::pair<int, int> count, std::vector<Wire> wires,
|
||||
std::optional<ui::Bus> displayBus)
|
||||
: name(name), instanceName(instanceName), tooltip(tooltip), type(type), count(count), wires(wires), displayBus(displayBus) {}
|
||||
: name(name), displayName(displayName), instanceName(instanceName), tooltip(tooltip), type(type), count(count), wires(wires), displayBus(displayBus) {}
|
||||
|
||||
std::string Bus::getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
std::string Bus::getDisplayName() {
|
||||
if(displayName.has_value()) {
|
||||
return *displayName;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
std::string Bus::getTooltip() {
|
||||
return tooltip;
|
||||
}
|
||||
|
@ -62,4 +69,5 @@ namespace domain {
|
|||
std::optional<ui::Bus> Bus::getDisplayBus() {
|
||||
return displayBus;
|
||||
}
|
||||
|
||||
} // namespace domain
|
||||
|
|
|
@ -25,8 +25,8 @@ namespace domain {
|
|||
std::string name;
|
||||
WireType type;
|
||||
int width;
|
||||
bool hidden;
|
||||
bool hasTerminate;
|
||||
bool hidden = false;
|
||||
bool hasTerminate = false;
|
||||
Value terminateWith;
|
||||
|
||||
public:
|
||||
|
@ -54,6 +54,7 @@ namespace domain {
|
|||
};
|
||||
private:
|
||||
std::string name;
|
||||
std::optional<std::string> displayName;
|
||||
std::string instanceName;
|
||||
std::string tooltip;
|
||||
BusType type;
|
||||
|
@ -63,11 +64,13 @@ namespace domain {
|
|||
std::vector<Wire> wires;
|
||||
|
||||
public:
|
||||
Bus(std::string name, std::string instanceName, std::string tooltip, BusType type, std::pair<int, int> count, std::vector<Wire> wires,
|
||||
Bus(std::string name, std::optional<std::string> displayName, std::string instanceName, std::string tooltip, BusType type, std::pair<int, int> count, std::vector<Wire> wires,
|
||||
std::optional<ui::Bus> display = std::nullopt);
|
||||
|
||||
std::string getName();
|
||||
|
||||
std::string getDisplayName();
|
||||
|
||||
std::string getInstanceName();
|
||||
|
||||
std::string getTooltip();
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
//
|
||||
|
||||
#include <set>
|
||||
#include <QLayout>
|
||||
#include "comdel_generator.h"
|
||||
|
||||
namespace domain {
|
||||
|
@ -127,8 +128,18 @@ namespace domain {
|
|||
}
|
||||
|
||||
void generateConnection(ConnectionInstance *connection, ostream &buffer) {
|
||||
buffer << "\t\tline {x1:" << connection->start.first << "; y1:" << connection->start.second << "; " <<
|
||||
"x2:" << connection->end.first << "; y2:" << connection->end.second << ";}" << "\n";
|
||||
|
||||
auto x1 = connection->start.first;
|
||||
auto y1 = connection->start.second;
|
||||
auto x2 = connection->end.first;
|
||||
auto y2 = connection->end.second;
|
||||
|
||||
buffer << "\t\tpath {\n";
|
||||
buffer << "\t\t\tx:0; y:0;\n";
|
||||
buffer << "\t\t\tpoints: (";
|
||||
buffer << "(" << x1 << ", " << y1 << "),";
|
||||
buffer << "(" << (x2 - x1) << "," << (y2 - y1) << "));\n";
|
||||
buffer << "\t\t}" << std::endl;
|
||||
}
|
||||
|
||||
void generateBus(BusInstance *bus, ostream &buffer) {
|
||||
|
@ -148,13 +159,10 @@ 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) {
|
||||
auto name = wire.getName();
|
||||
if (usedNames.count(name) > 0) {
|
||||
name = bus->name + "__" + wire.getName();
|
||||
}
|
||||
if (wire.isHidden()) {
|
||||
name = "--" + name;
|
||||
}
|
||||
usedNames.insert(name);
|
||||
usedMappings.insert(std::make_pair(bus->name + "." + wire.getName(), name));
|
||||
|
||||
|
@ -184,7 +192,11 @@ namespace domain {
|
|||
if (wire.getWidth() != 1) {
|
||||
buffer << "<" << wire.getWidth() << ">";
|
||||
}
|
||||
buffer << " " << name << ";" << std::endl;
|
||||
buffer << " " << (wire.isHidden() ? "--" : "") << name;
|
||||
if(wire.hasTerminateWith()) {
|
||||
buffer << " = " << wire.getTerminateWith().asInt();
|
||||
}
|
||||
buffer << ";" << std::endl;
|
||||
}
|
||||
|
||||
std::set<std::string> createImports(Schema *schema) {
|
||||
|
@ -203,6 +215,9 @@ namespace domain {
|
|||
map<string, string> &wireNames,
|
||||
stringstream &buffer);
|
||||
|
||||
void generateSingleAutomaticPin(std::vector<ConnectionInstance*> connections, ComponentInstance *instance, string pin,
|
||||
map<string, string> &wireNames, stringstream &buffer);
|
||||
|
||||
void generateComponent(Schema *schema, map<string, string> &wires, ostream &buffer,
|
||||
shared_ptr<ComponentInstance> &component);
|
||||
|
||||
|
@ -250,37 +265,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<BusConnectionInstance *>(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<BusConnectionInstance *>(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<DirectConnectionInstance *>(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<DirectConnectionInstance *>(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 +361,30 @@ namespace domain {
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
generateAutomaticPin(DirectConnectionInstance *connection, string name, string pin, map<string, string> wireNames,
|
||||
void generateSingleAutomaticPin(std::vector<ConnectionInstance*> connections, ComponentInstance *instance, string pin,
|
||||
map<string, string> &wireNames, stringstream &buffer) {
|
||||
std::map<int, BusInstance*> selectedValues;
|
||||
for(auto conn: connections) {
|
||||
auto dirConn = dynamic_cast<DirectConnectionInstance*>(conn);
|
||||
auto index = dirConn->getSelected(ConnectionComponent{instance->name, pin});
|
||||
selectedValues.insert(std::make_pair(index, dirConn->bus));
|
||||
}
|
||||
|
||||
std::vector<Value> defaultWires = instance->component.getPin(pin).getWires().value();
|
||||
|
||||
for (int i=0; i<defaultWires.size(); i++) {
|
||||
if(selectedValues.count(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<string, string> wireNames,
|
||||
stringstream &buffer) {
|
||||
std::vector<Value> wires;
|
||||
if (connection->instance->name == name && connection->connection.getComponent().pin == pin) {
|
||||
|
@ -372,4 +414,4 @@ namespace domain {
|
|||
}
|
||||
}
|
||||
|
||||
} // domain
|
||||
} // domain
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include <set>
|
||||
#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<std::string, int> 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);
|
||||
}
|
||||
}
|
||||
|
@ -82,12 +77,11 @@ namespace domain {
|
|||
|
||||
for (auto &inst: schema.componentInstances) {
|
||||
for (auto &pin: inst->component.getPins()) {
|
||||
if (pin.getConnection().getType() == PinConnection::REQUIRED) {
|
||||
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().getMessage(), 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<ComponentInstance> &component, Pin &pin) {
|
||||
for (auto conn: schema.connections) {
|
||||
auto busConnection = dynamic_cast<BusConnectionInstance *>(conn.get());
|
||||
|
@ -233,13 +206,9 @@ namespace domain {
|
|||
|
||||
auto directConnection = dynamic_cast<DirectConnectionInstance *>(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<std::string, std::string> ValidationContext::map() {
|
||||
std::map<std::string, std::string> 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;
|
||||
}
|
||||
}
|
|
@ -23,6 +23,8 @@ namespace domain {
|
|||
InstanceAttribute *attribute;
|
||||
std::map<std::string, AddressSpace> addressSpaces;
|
||||
std::map<std::string, Value> attributes;
|
||||
|
||||
std::map<std::string, std::string> map();
|
||||
};
|
||||
|
||||
class ComdelValidator {
|
||||
|
@ -41,18 +43,13 @@ namespace domain {
|
|||
|
||||
std::vector<ValidationError> validateInstanceCount(Schema &schema, Library &library, ValidationContext context);
|
||||
|
||||
std::vector<ValidationError>
|
||||
validatePinConnections(Schema &schema, Library &library, ValidationContext context);
|
||||
std::vector<ValidationError> validatePinConnections(Schema &schema, Library &library, ValidationContext context);
|
||||
|
||||
ComdelValidator(std::vector<FunctionValidator *> validators);
|
||||
|
||||
private:
|
||||
std::map<std::string, FunctionValidator *> validators;
|
||||
|
||||
std::string populateMessage(string message, ValidationContext context);
|
||||
|
||||
string replacePlaceholder(string message, const string name, Value value);
|
||||
|
||||
bool connectionExists(Schema &schema, shared_ptr<ComponentInstance> &component, Pin &pin);
|
||||
};
|
||||
|
||||
|
|
|
@ -1,17 +1,25 @@
|
|||
#include "component.h"
|
||||
#include <stdexcept>
|
||||
|
||||
namespace domain {
|
||||
|
||||
Component::Component(string name, string tooltip, string source, ComponentType type,
|
||||
Component::Component(string name, optional<string> displayName, string tooltip, string source, ComponentType type,
|
||||
vector<Rule> rules, string instanceName, pair<int, int> count, Display display,
|
||||
vector<Pin> pins, vector<Attribute> attributes)
|
||||
: name(name), tooltip(tooltip), source(source), type(type), rules(rules), instanceName(instanceName),
|
||||
: name(name), displayName(displayName), tooltip(tooltip), source(source), type(type), rules(rules), instanceName(instanceName),
|
||||
count(count), display(display), pins(pins), attributes(attributes) {}
|
||||
|
||||
std::string Component::getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
std::string Component::getDisplayName() {
|
||||
if(displayName.has_value()) {
|
||||
return displayName.value();
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
std::string Component::getTooltip() {
|
||||
return tooltip;
|
||||
}
|
||||
|
@ -50,7 +58,7 @@ namespace domain {
|
|||
return p;
|
||||
}
|
||||
}
|
||||
throw std::exception();
|
||||
throw std::runtime_error("no pin with name '" + pin + "'");
|
||||
}
|
||||
|
||||
bool Component::hasPin(std::string name) {
|
||||
|
@ -72,7 +80,7 @@ namespace domain {
|
|||
return attr;
|
||||
}
|
||||
}
|
||||
throw std::exception();
|
||||
throw std::runtime_error("no attribute with name '" + attribute + "'");
|
||||
}
|
||||
|
||||
bool Component::hasAttribute(std::string name, Value::ValueType type) {
|
||||
|
@ -94,5 +102,4 @@ namespace domain {
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
} // namespace domain
|
||||
|
|
|
@ -23,6 +23,7 @@ namespace domain {
|
|||
|
||||
private:
|
||||
std::string name;
|
||||
std::optional<std::string> displayName;
|
||||
std::string tooltip;
|
||||
std::string source;
|
||||
ComponentType type;
|
||||
|
@ -36,12 +37,14 @@ namespace domain {
|
|||
|
||||
public:
|
||||
|
||||
Component(string name, string tooltip, string source, ComponentType type,
|
||||
Component(string name, optional<string> displayName, string tooltip, string source, ComponentType type,
|
||||
vector<Rule> rules, string instanceName, pair<int, int> count, Display display,
|
||||
vector<Pin> pins, vector<Attribute> attributes);
|
||||
|
||||
std::string getName();
|
||||
|
||||
std::string getDisplayName();
|
||||
|
||||
std::string getTooltip();
|
||||
|
||||
std::string getSource();
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "connection.h"
|
||||
#include <stdexcept>
|
||||
|
||||
namespace domain {
|
||||
|
||||
|
@ -38,7 +39,7 @@ namespace domain {
|
|||
return attributes[i];
|
||||
}
|
||||
}
|
||||
throw std::exception();
|
||||
throw std::runtime_error("no attribute with name '" + name + "'");
|
||||
}
|
||||
|
||||
bool Connection::hasAttribute(std::string name) {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "connection_instance.h"
|
||||
#include <stdexcept>
|
||||
|
||||
namespace domain {
|
||||
|
||||
|
@ -13,7 +14,7 @@ namespace domain {
|
|||
return attr;
|
||||
}
|
||||
}
|
||||
throw std::exception();
|
||||
throw std::runtime_error("no attribute with name '" + attribute + "'");
|
||||
}
|
||||
|
||||
|
||||
|
@ -26,4 +27,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; i<connection.getWires().size(); i++) {
|
||||
if(connection.getWires()[i].isType(Value::STRING) && connection.getWires()[i].asString() == selected) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
auto selected = attributes[1].value.asString();
|
||||
for(int i=0; i<connection.getSecondWires()->size(); i++) {
|
||||
if(connection.getSecondWires().value()[i].isType(Value::STRING) && connection.getSecondWires().value()[i].asString() == selected) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
} // namespace domain
|
||||
|
|
|
@ -41,6 +41,8 @@ namespace domain {
|
|||
|
||||
DirectConnectionInstance(ComponentInstance *instance, ComponentInstance *secondsInstance,
|
||||
std::vector<InstanceAttribute> attributes, BusInstance *bus, Connection connection);
|
||||
|
||||
int getSelected(ConnectionComponent connection);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -47,10 +47,27 @@ namespace domain {
|
|||
void ui::Rect::comdel(std::ostream &buffer, int x, int y) {
|
||||
buffer << "\t\trectangle {\n";
|
||||
buffer << "\t\t\tx: " << (this->x + x) << "; y: " << (this->y + y) << ";\n";
|
||||
buffer << "\t\t\tw: " << w << "; h: " << h << ";\n";
|
||||
buffer << "\t\t\twidth: " << w << "; height: " << h << ";\n";
|
||||
buffer << "\t\t\tfill_color: " << this->config.fillColor.name().toStdString() << ";\n";
|
||||
buffer << "\t\t\tline_color: " << this->config.lineColor.name().toStdString() << ";\n";
|
||||
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\twidth: " << w << "; height: " << 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));
|
||||
|
@ -58,10 +75,12 @@ namespace domain {
|
|||
}
|
||||
|
||||
void ui::Line::comdel(std::ostream &buffer, int x, int y) {
|
||||
buffer << "\t\tline {\n";
|
||||
buffer << "\t\t\tx1: " << (x1 + x) << "; y1: " << (y1 + y) << ";\n";
|
||||
buffer << "\t\t\tx2: " << (x2 + x) << "; y2: " << (y2 + y) << ";\n";
|
||||
buffer << "\t\t}\n\n";
|
||||
buffer << "\t\tpath {\n";
|
||||
buffer << "\t\t\tx:0; y:0;\n";
|
||||
buffer << "\t\t\tpoints: (";
|
||||
buffer << "(" << (x1 + x) << ", " << (y1 + y) << "),";
|
||||
buffer << "(" << (x2 - x1) << "," << (y2 - y1) << "));\n";
|
||||
buffer << "\t\t}" << std::endl;
|
||||
}
|
||||
|
||||
void ui::Bus::render(QGraphicsItemGroup *group, int size) {
|
||||
|
@ -89,10 +108,12 @@ namespace domain {
|
|||
buffer << "\t\trectangle {\n";
|
||||
buffer << "\t\t\tx: " << (this->x + x) << "; y: " << (this->y + y) << ";\n";
|
||||
if (orientation == HORIZONTAL) {
|
||||
buffer << "\t\t\tw: " << size << "; h: " << h << ";\n";
|
||||
buffer << "\t\t\twidth: " << size << "; height: " << h << ";\n";
|
||||
} else {
|
||||
buffer << "\t\t\tw: " << w << "; h: " << size << ";\n";
|
||||
buffer << "\t\t\twidth: " << w << "; height: " << size << ";\n";
|
||||
}
|
||||
buffer << "\t\t\tfill_color: " << this->config.fillColor.name().toStdString() << ";\n";
|
||||
buffer << "\t\t\tline_color: " << this->config.lineColor.name().toStdString() << ";\n";
|
||||
buffer << "\t\t}\n\n";
|
||||
}
|
||||
|
||||
|
@ -205,6 +226,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) {
|
||||
|
|
|
@ -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> pin = std::nullopt;
|
||||
std::optional<Bus> bus = std::nullopt;
|
||||
std::optional<Text> text = std::nullopt;
|
||||
std::optional<Ellipse> 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);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "library.h"
|
||||
#include <stdexcept>
|
||||
|
||||
namespace domain {
|
||||
|
||||
|
@ -51,7 +52,7 @@ namespace domain {
|
|||
}
|
||||
|
||||
bool Library::hasComponent(std::string name) {
|
||||
for (uint i = 0; i < components.size(); i++) {
|
||||
for (unsigned int i = 0; i < components.size(); i++) {
|
||||
if (components[i].getName() == name) {
|
||||
return true;
|
||||
}
|
||||
|
@ -60,7 +61,7 @@ namespace domain {
|
|||
}
|
||||
|
||||
bool Library::hasBus(std::string name) {
|
||||
for (uint i = 0; i < buses.size(); i++) {
|
||||
for (unsigned int i = 0; i < buses.size(); i++) {
|
||||
if (buses[i].getName() == name) {
|
||||
return true;
|
||||
}
|
||||
|
@ -70,30 +71,30 @@ namespace domain {
|
|||
|
||||
|
||||
AddressSpace &Library::getAddressSpace(std::string addressSpace) {
|
||||
for (uint i = 0; i < addressSpaces.size(); i++) {
|
||||
for (unsigned int i = 0; i < addressSpaces.size(); i++) {
|
||||
if (addressSpaces[i].getName() == addressSpace) {
|
||||
return addressSpaces[i];
|
||||
}
|
||||
}
|
||||
throw std::exception();
|
||||
throw std::runtime_error("no address space with name '" + addressSpace + "'");
|
||||
}
|
||||
|
||||
Component &Library::getComponent(std::string component) {
|
||||
for (uint i = 0; i < components.size(); i++) {
|
||||
for (unsigned int i = 0; i < components.size(); i++) {
|
||||
if (components[i].getName() == component) {
|
||||
return components[i];
|
||||
}
|
||||
}
|
||||
throw std::exception();
|
||||
throw std::runtime_error("no component with name '" + component + "'");
|
||||
}
|
||||
|
||||
Bus &Library::getBus(std::string bus) {
|
||||
for (uint i = 0; i < buses.size(); i++) {
|
||||
for (unsigned int i = 0; i < buses.size(); i++) {
|
||||
if (buses[i].getName() == bus) {
|
||||
return buses[i];
|
||||
}
|
||||
}
|
||||
throw std::exception();
|
||||
throw std::runtime_error("no bus with name '" + bus + "'");
|
||||
|
||||
}
|
||||
|
||||
|
@ -102,7 +103,7 @@ namespace domain {
|
|||
}
|
||||
|
||||
std::optional<Connection> Library::getConnection(ConnectionComponent component, std::string bus) {
|
||||
for (uint i = 0; i < connections.size(); i++) {
|
||||
for (unsigned int i = 0; i < connections.size(); i++) {
|
||||
if (connections[i].isConnecting(component, bus)) {
|
||||
return connections[i];
|
||||
}
|
||||
|
@ -116,7 +117,7 @@ namespace domain {
|
|||
|
||||
std::optional<Connection>
|
||||
Library::getConnection(ConnectionComponent component, std::string bus, ConnectionComponent secondComponent) {
|
||||
for (uint i = 0; i < connections.size(); i++) {
|
||||
for (unsigned int i = 0; i < connections.size(); i++) {
|
||||
if (connections[i].isConnecting(component, bus, secondComponent)) {
|
||||
return connections[i];
|
||||
}
|
||||
|
|
|
@ -2,19 +2,7 @@
|
|||
|
||||
namespace domain {
|
||||
|
||||
PinConnection::PinConnection(std::string message, ConnectionType type)
|
||||
: message(message), type(type) {}
|
||||
|
||||
PinConnection::ConnectionType PinConnection::getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
std::string PinConnection::getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
|
||||
Pin::Pin(std::string name, PinType type, std::string tooltip, PinConnection connection, domain::ui::Pin pin,
|
||||
Pin::Pin(std::string name, PinType type, std::string tooltip, std::optional<std::string> connection, domain::ui::Pin pin,
|
||||
std::optional<std::vector<Value>> wires)
|
||||
: name(name), type(type), tooltip(tooltip), connection(connection), displayPin(pin), wires(wires) {}
|
||||
|
||||
|
@ -34,7 +22,7 @@ namespace domain {
|
|||
return displayPin;
|
||||
}
|
||||
|
||||
PinConnection &Pin::getConnection() {
|
||||
std::optional<std::string> Pin::getConnection() {
|
||||
return connection;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,25 +9,6 @@
|
|||
|
||||
namespace domain {
|
||||
|
||||
class PinConnection {
|
||||
public:
|
||||
enum ConnectionType {
|
||||
REQUIRED,
|
||||
OPTIONAL
|
||||
};
|
||||
|
||||
private:
|
||||
std::string message;
|
||||
ConnectionType type;
|
||||
|
||||
public:
|
||||
PinConnection(std::string message, ConnectionType type);
|
||||
|
||||
ConnectionType getType();
|
||||
|
||||
std::string getMessage();
|
||||
};
|
||||
|
||||
class Pin {
|
||||
public:
|
||||
enum PinType {
|
||||
|
@ -40,13 +21,13 @@ namespace domain {
|
|||
std::string name;
|
||||
PinType type;
|
||||
std::string tooltip;
|
||||
PinConnection connection;
|
||||
std::optional<std::string> connection;
|
||||
domain::ui::Pin displayPin;
|
||||
|
||||
std::optional<std::vector<Value>> wires;
|
||||
|
||||
public:
|
||||
Pin(std::string name, PinType type, std::string tooltip, PinConnection connection, domain::ui::Pin pin,
|
||||
Pin(std::string name, PinType type, std::string tooltip, std::optional<std::string> connection, domain::ui::Pin pin,
|
||||
std::optional<std::vector<Value>> wires);
|
||||
|
||||
std::string &getName();
|
||||
|
@ -57,7 +38,7 @@ namespace domain {
|
|||
|
||||
ui::Pin &getDisplayPin();
|
||||
|
||||
PinConnection &getConnection();
|
||||
std::optional<std::string> getConnection();
|
||||
|
||||
std::optional<std::vector<Value>> &getWires();
|
||||
};
|
||||
|
|
|
@ -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<BusConnectionInstance*>(conn.get());
|
||||
if(busConnection->instance == instance && busConnection->bus == entry.busInstance.value()) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
auto *directInstance = dynamic_cast<DirectConnectionInstance*>(conn.get());
|
||||
ComponentInstance* secondInstance;
|
||||
if(directInstance->instance == instance) {
|
||||
secondInstance = directInstance->secondInstance;
|
||||
} else {
|
||||
secondInstance = directInstance->instance;
|
||||
auto directConnection = dynamic_cast<DirectConnectionInstance*>(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
|
||||
|
|
|
@ -5,9 +5,8 @@
|
|||
|
||||
namespace domain {
|
||||
|
||||
|
||||
ComdelContext::ComdelContext(std::string name, bool inComponent, bool inConnection, bool inSingleAutomaticConnection, bool inBus)
|
||||
: name(std::move(name)), inComponent(inComponent), inConnection(inConnection), inSingleAutomaticConnection(inSingleAutomaticConnection), inBus(inBus) {}
|
||||
ComdelContext::ComdelContext(std::string name, bool inComponent, bool inConnection, bool inSingleAutomaticConnection)
|
||||
: name(std::move(name)), inComponent(inComponent), inConnection(inConnection), inSingleAutomaticConnection(inSingleAutomaticConnection) {}
|
||||
|
||||
bool ComdelContext::doesAttributeExists(std::string name, Value::ValueType type) {
|
||||
for (auto &attribute: attributes) {
|
||||
|
@ -27,7 +26,9 @@ namespace domain {
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* ENUM CONVERSIONS *
|
||||
***********************************************************************/
|
||||
Component::ComponentType toType(ComponentNode::ComponentType type) {
|
||||
if (type == ComponentNode::MEMORY) {
|
||||
return Component::MEMORY;
|
||||
|
@ -78,29 +79,26 @@ namespace domain {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
Value toType(ValueNode node, Value::ValueType type = Value::ValueType::UNDEFINED) {
|
||||
if (type == Value::MEMORY_REFERENCE) {
|
||||
if (node.getType() == ValueNode::NIL) {
|
||||
if (node.is(ValueNode::NIL)) {
|
||||
return Value::fromMemoryReference(nullopt);
|
||||
} else {
|
||||
return Value::fromMemoryReference(node.asIdentifier());
|
||||
}
|
||||
}
|
||||
|
||||
if (node.getType() == ValueNode::BOOL) {
|
||||
if (node.is(ValueNode::BOOL)) {
|
||||
return Value::fromBool(node.asBool());
|
||||
} else if (node.getType() == ValueNode::INT) {
|
||||
} else if (node.is(ValueNode::INT)) {
|
||||
return Value::fromInt(node.asInt());
|
||||
} else if (node.getType() == ValueNode::STRING) {
|
||||
} else if (node.is(ValueNode::STRING)) {
|
||||
return Value::fromString(node.asString());
|
||||
} else if (node.getType() == ValueNode::NIL) {
|
||||
} else if (node.is(ValueNode::NIL)) {
|
||||
return Value::fromNull();
|
||||
}
|
||||
return Value::fromReference(node.asIdentifier(), Value::UNDEFINED);
|
||||
}
|
||||
|
||||
|
||||
Bus::BusType toType(BusNode::BusType type) {
|
||||
if (type == BusNode::AUTOMATIC) {
|
||||
return Bus::AUTOMATIC;
|
||||
|
@ -110,7 +108,6 @@ namespace domain {
|
|||
return Bus::REGULAR;
|
||||
}
|
||||
|
||||
|
||||
Pin::PinType toType(PinNode::PinType type) {
|
||||
if (type == PinNode::IN) {
|
||||
return Pin::IN;
|
||||
|
@ -120,14 +117,6 @@ namespace domain {
|
|||
return Pin::IN_OUT;
|
||||
}
|
||||
|
||||
PinConnection::ConnectionType toType(PinConnectionNode::ConnectionType type) {
|
||||
if (type == PinConnectionNode::OPTIONAL) {
|
||||
return PinConnection::OPTIONAL;
|
||||
}
|
||||
return PinConnection::REQUIRED;
|
||||
}
|
||||
|
||||
|
||||
Popup::PopupType toType(PopupNode::PopupType type) {
|
||||
if (type == PopupNode::AUTOMATIC) {
|
||||
return Popup::AUTOMATIC;
|
||||
|
@ -135,6 +124,11 @@ namespace domain {
|
|||
return Popup::ON_DEMAND;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* SCHEMA CREATOR *
|
||||
***********************************************************************/
|
||||
|
||||
SchemaCreator::SchemaCreator(std::vector<FunctionValidator *> validators)
|
||||
: validators(std::move(validators)) {}
|
||||
|
||||
|
@ -159,7 +153,6 @@ namespace domain {
|
|||
}
|
||||
|
||||
header = node.header ? node.header->asString() : "";
|
||||
|
||||
libraryInfo = node.libraryInfo ? node.libraryInfo->asString() : "";
|
||||
|
||||
for (auto &as: node.addressSpaces) {
|
||||
|
@ -201,12 +194,16 @@ namespace domain {
|
|||
} else {
|
||||
return nullopt;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::optional<Bus> SchemaCreator::loadBus(BusNode node) {
|
||||
std::string busName = node.name.value;
|
||||
|
||||
std::optional<std::string> displayName = nullopt;
|
||||
if(node.displayName.has_value()) {
|
||||
displayName = node.displayName->asString();
|
||||
}
|
||||
|
||||
if (!node.instanceName) {
|
||||
errors.emplace_back(node.span, "missing @instanceName");
|
||||
return nullopt;
|
||||
|
@ -269,16 +266,15 @@ namespace domain {
|
|||
return nullopt;
|
||||
}
|
||||
|
||||
return Bus(busName, instanceName, tooltip, type, count, wires, displayBus);
|
||||
return Bus(busName, displayName, instanceName, tooltip, type, count, wires, displayBus);
|
||||
}
|
||||
|
||||
|
||||
std::optional<AddressSpace> SchemaCreator::loadAddressSpace(AddressSpaceNode node) {
|
||||
return AddressSpace(node.name.value, node.start.value, node.end.value);
|
||||
return AddressSpace(node.name.value, node.range.first.value, node.range.second.value);
|
||||
}
|
||||
|
||||
std::optional<Connection> SchemaCreator::loadConnection(ConnectionNode node) {
|
||||
push(ComdelContext("connection", false, true, false, false));
|
||||
push(ComdelContext("connection", false, true, false));
|
||||
|
||||
std::string bus = node.bus.value;
|
||||
auto busInstance = getBus(bus);
|
||||
|
@ -349,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");
|
||||
|
@ -409,7 +407,10 @@ namespace domain {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
if(node.secondWires->empty()) {
|
||||
errors.emplace_back(node.span, "missing second @wires definition");
|
||||
return nullopt;
|
||||
}
|
||||
std::vector<Value> secondWires;
|
||||
for (auto &secondWire: *node.secondWires) {
|
||||
if (secondWire.is(ValueNode::NIL)) {
|
||||
|
@ -453,7 +454,6 @@ namespace domain {
|
|||
attributes[1].setPupup(popup);
|
||||
}
|
||||
}
|
||||
|
||||
pop();
|
||||
|
||||
return Connection(first, second, bus, attributes, firstWires, secondWires);
|
||||
|
@ -465,10 +465,15 @@ namespace domain {
|
|||
}
|
||||
|
||||
std::optional<Component> SchemaCreator::loadComponent(ComponentNode node) {
|
||||
push(ComdelContext(node.name.value, true, false, false, false));
|
||||
push(ComdelContext(node.name.value, true, false, false));
|
||||
|
||||
std::string componentName = node.name.value;
|
||||
|
||||
std::optional<std::string> displayName = nullopt;
|
||||
if (node.displayName.has_value()) {
|
||||
displayName = node.displayName->asString();
|
||||
}
|
||||
|
||||
if (!node.tooltip) {
|
||||
errors.emplace_back(node.span, "missing @tooltip");
|
||||
pop();
|
||||
|
@ -545,7 +550,7 @@ namespace domain {
|
|||
}
|
||||
|
||||
pop();
|
||||
return Component(componentName, tooltip, source, type, rules, instanceName, count, *display, pins, attributes);
|
||||
return Component(componentName, displayName, tooltip, source, type, rules, instanceName, count, *display, pins, attributes);
|
||||
}
|
||||
|
||||
std::optional<Wire> SchemaCreator::loadWire(WireNode node) {
|
||||
|
@ -584,12 +589,10 @@ namespace domain {
|
|||
}
|
||||
ui::Pin displayPin = *display->getItems()[0].pin;
|
||||
|
||||
|
||||
if (!node.connection) {
|
||||
errors.emplace_back(node.span, "missing @connection");
|
||||
return nullopt;
|
||||
std::optional<std::string> connection = std::nullopt;
|
||||
if (node.connection) {
|
||||
connection = node.connection->asString();
|
||||
}
|
||||
auto connection = loadPinConnection(*node.connection);
|
||||
|
||||
std::optional<std::vector<Value>> wiresOpt = std::nullopt;
|
||||
if (node.wires.has_value()) {
|
||||
|
@ -610,47 +613,81 @@ namespace domain {
|
|||
return Pin(pinName, type, tooltip, connection, displayPin, wiresOpt);
|
||||
}
|
||||
|
||||
Color readColor(std::vector<SourceError>& errors, DisplayItemNode& item, std::string property, Color _default) {
|
||||
auto color = item.asColor(property, _default);
|
||||
if(!color.has_value()) {
|
||||
errors.emplace_back(item.span, "expected color");
|
||||
return _default;
|
||||
}
|
||||
return *color;
|
||||
}
|
||||
|
||||
std::string readString(std::vector<SourceError>& errors, DisplayItemNode& item, std::string property, std::string _default = "") {
|
||||
auto value = item.asString(property, _default);
|
||||
if(!value.has_value()) {
|
||||
errors.emplace_back(item.span, "expected string");
|
||||
return _default;
|
||||
}
|
||||
return *value;
|
||||
}
|
||||
|
||||
long long int readInt(std::vector<SourceError>& errors, DisplayItemNode& item, std::string property, long long int _default = 0) {
|
||||
auto value = item.asInt(property, _default);
|
||||
if(!value.has_value()) {
|
||||
errors.emplace_back(item.span, "expected int");
|
||||
return _default;
|
||||
}
|
||||
return *value;
|
||||
}
|
||||
|
||||
std::optional<Display> SchemaCreator::loadDisplay(DisplayNode node) {
|
||||
std::vector<ui::Item> items;
|
||||
for (auto &item: node.items) {
|
||||
ui::Item displayItem;
|
||||
std::string type = item.type.value;
|
||||
|
||||
auto fillColor = item.asColor(&errors, "fillColor", Color(255, 255, 255, 255));
|
||||
auto lineColor = item.asColor(&errors, "lineColor", Color(0, 0, 0, 255));
|
||||
auto fillColor = readColor(errors, item, "fillColor", Color(255, 255, 255, 255));
|
||||
auto lineColor = readColor(errors, item, "lineColor", Color(0, 0, 0, 255));
|
||||
|
||||
if (type == "text") {
|
||||
long long int x, y, w, h;
|
||||
std::string text;
|
||||
auto color = item.asColor(&errors, "color", Color(0, 0, 0, 255));
|
||||
x = item.asInt(&errors, "x");
|
||||
y = item.asInt(&errors, "y");
|
||||
w = item.asInt(&errors, "w");
|
||||
h = item.asInt(&errors, "h");
|
||||
text = item.asString(&errors, "text");
|
||||
auto color = readColor(errors, item, "color", Color(0, 0, 0, 255));
|
||||
x = readInt(errors, item, "x");
|
||||
y = readInt(errors, item, "y");
|
||||
w = readInt(errors, item, "w");
|
||||
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 = item.asInt(&errors, "x");
|
||||
y = item.asInt(&errors, "y");
|
||||
w = item.asInt(&errors, "w");
|
||||
h = item.asInt(&errors, "h");
|
||||
x = readInt(errors, item, "x");
|
||||
y = readInt(errors, item, "y");
|
||||
w = readInt(errors, item, "w");
|
||||
h = readInt(errors, item, "h");
|
||||
displayItem.rect = ui::Rect(x, y, w, h, {lineColor, fillColor});
|
||||
} else if (type == "line") {
|
||||
long long int x1, y1, x2, y2;
|
||||
x1 = item.asInt(&errors, "x1");
|
||||
y1 = item.asInt(&errors, "y1");
|
||||
x2 = item.asInt(&errors, "x2");
|
||||
y2 = item.asInt(&errors, "y2");
|
||||
x1 = readInt(errors, item, "x1");
|
||||
y1 = readInt(errors, item, "y1");
|
||||
x2 = readInt(errors, item, "x2");
|
||||
y2 = readInt(errors, item, "y2");
|
||||
displayItem.line = ui::Line(x1, y1, x2, y2, {lineColor, fillColor});
|
||||
} else if (type == "pin") {
|
||||
long long int x, y, w, h;
|
||||
x = item.asInt(&errors, "x");
|
||||
y = item.asInt(&errors, "y");
|
||||
w = item.asInt(&errors, "w");
|
||||
h = item.asInt(&errors, "h");
|
||||
std::string _orientation = item.asString(&errors, "orientation", "bottom");
|
||||
std::string _pinType = item.asString(&errors, "type", "out");
|
||||
x = readInt(errors, item, "x");
|
||||
y = readInt(errors, item, "y");
|
||||
w = readInt(errors, item, "w");
|
||||
h = readInt(errors, item, "h");
|
||||
std::string _orientation = readString(errors, item, "orientation", "bottom");
|
||||
std::string _pinType = readString(errors, item, "type", "out");
|
||||
|
||||
ui::PinOrientation orientation;
|
||||
if (_orientation == "left") {
|
||||
|
@ -679,11 +716,11 @@ namespace domain {
|
|||
displayItem.pin = ui::Pin(x, y, w, h, orientation, pinType, {lineColor, fillColor});
|
||||
} else if (type == "bus") {
|
||||
long long int x, y, w, h;
|
||||
x = item.asInt(&errors, "x");
|
||||
y = item.asInt(&errors, "y");
|
||||
w = item.asInt(&errors, "w");
|
||||
h = item.asInt(&errors, "h");
|
||||
std::string _orientation = item.asString(&errors, "orientation", "bottom");
|
||||
x = readInt(errors, item, "x");
|
||||
y = readInt(errors, item, "y");
|
||||
w = readInt(errors, item, "w");
|
||||
h = readInt(errors, item, "h");
|
||||
std::string _orientation = readString(errors, item, "orientation", "bottom");
|
||||
|
||||
ui::BusOrientation orientation;
|
||||
if (_orientation == "horizontal") {
|
||||
|
@ -703,16 +740,15 @@ namespace domain {
|
|||
return Display(items);
|
||||
}
|
||||
|
||||
|
||||
PinConnection SchemaCreator::loadPinConnection(PinConnectionNode node) {
|
||||
std::string message = node.message.asString();
|
||||
PinConnection::ConnectionType type = toType(node.type.value);
|
||||
return {message, type};
|
||||
}
|
||||
|
||||
std::optional<Attribute> SchemaCreator::loadAttribute(AttributeNode node) {
|
||||
std::string name = node.name.value;
|
||||
pushAdditional(name);
|
||||
|
||||
std::optional<std::string> displayName = nullopt;
|
||||
if (node.displayName.has_value()) {
|
||||
displayName = node.displayName->asString();
|
||||
}
|
||||
|
||||
Value value;
|
||||
|
||||
if (current().inComponent) {
|
||||
|
@ -746,7 +782,7 @@ namespace domain {
|
|||
}
|
||||
}
|
||||
|
||||
current().attributes.emplace_back(name, value);
|
||||
current().attributes.emplace_back(name, nullopt, value);
|
||||
|
||||
std::optional<Popup> popup;
|
||||
if (node.popup) {
|
||||
|
@ -754,7 +790,7 @@ namespace domain {
|
|||
}
|
||||
|
||||
pop();
|
||||
return Attribute(name, value, popup);
|
||||
return Attribute(name, displayName, value, popup);
|
||||
}
|
||||
|
||||
std::optional<Popup> SchemaCreator::loadPopup(PopupNode node, std::string name, Value::ValueType type) {
|
||||
|
@ -763,7 +799,7 @@ namespace domain {
|
|||
pushAdditional(name);
|
||||
|
||||
current().attributes.clear();
|
||||
current().attributes.emplace_back(name, Value::ofType(type));
|
||||
current().attributes.emplace_back(name, nullopt, Value::ofType(type));
|
||||
|
||||
if (!node.title) {
|
||||
errors.emplace_back(node.span, "missing @title");
|
||||
|
@ -846,7 +882,7 @@ namespace domain {
|
|||
if (validator->getName() == function) {
|
||||
if (validator->getSignature().size() == node.params.size()) {
|
||||
std::vector<Value> params;
|
||||
for (uint j = 0; j < validator->getSignature().size(); j++) {
|
||||
for (unsigned int j = 0; j < validator->getSignature().size(); j++) {
|
||||
bool exists = false;
|
||||
auto type = toType(node.params[j]);
|
||||
if (type.getType() == Value::UNDEFINED) {
|
||||
|
@ -998,7 +1034,6 @@ namespace domain {
|
|||
}
|
||||
|
||||
shared_ptr<ComponentInstance> SchemaCreator::loadComponentInstance(InstanceNode instance, Library &library) {
|
||||
|
||||
auto componentInstanceName = instance.name.value;
|
||||
auto position = std::make_pair(instance.position->first.value, instance.position->second.value);
|
||||
|
||||
|
@ -1021,7 +1056,7 @@ namespace domain {
|
|||
if (std::count_if(attributes.begin(), attributes.end(),
|
||||
[&attr](InstanceAttribute &attribute) { return attr.getName() == attribute.name; }) ==
|
||||
0) {
|
||||
errors.emplace_back(SourceError(instance.span, "missing attribute '" + attr.getName() + "'"));
|
||||
errors.emplace_back(SourceError(instance.span, "missing attribute '" + attr.getDisplayName() + "'"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1055,7 +1090,7 @@ namespace domain {
|
|||
}
|
||||
|
||||
std::optional<Attribute> SchemaCreator::createMemoryAttribute() {
|
||||
return Attribute("_memory", Value::fromMemoryReference(std::nullopt), createMemoryPopup());
|
||||
return Attribute("_memory", nullopt, Value::fromMemoryReference(std::nullopt), createMemoryPopup());
|
||||
}
|
||||
|
||||
std::optional<Popup> SchemaCreator::createMemoryPopup() {
|
||||
|
@ -1103,7 +1138,7 @@ namespace domain {
|
|||
this->context.push_back(current());
|
||||
current().name = name;
|
||||
} else {
|
||||
ComdelContext con(name, false, false, false, false);
|
||||
ComdelContext con(name, false, false, false);
|
||||
push(con);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
namespace domain {
|
||||
|
||||
/** Context used for loading model */
|
||||
struct ComdelContext {
|
||||
std::vector<Attribute> attributes;
|
||||
std::vector<std::string> wires;
|
||||
|
@ -20,9 +21,8 @@ namespace domain {
|
|||
bool inComponent;
|
||||
bool inConnection;
|
||||
bool inSingleAutomaticConnection;
|
||||
bool inBus;
|
||||
|
||||
ComdelContext(std::string name, bool inComponent, bool inConnection, bool inSingleAutomaticConnection, bool inBus);
|
||||
ComdelContext(std::string name, bool inComponent, bool inConnection, bool inSingleAutomaticConnection);
|
||||
|
||||
bool doesAttributeExists(std::string name, Value::ValueType type);
|
||||
bool doesWireExists(std::string name);
|
||||
|
@ -30,6 +30,16 @@ namespace domain {
|
|||
};
|
||||
|
||||
class SchemaCreator {
|
||||
|
||||
public:
|
||||
explicit SchemaCreator(std::vector<FunctionValidator *> validators);
|
||||
|
||||
std::vector<SourceError> getErrors();
|
||||
|
||||
std::optional<Library> loadLibrary(LibraryNode node);
|
||||
Schema *loadSchema(SchemaNode node, Library &library);
|
||||
|
||||
private:
|
||||
std::vector<ComdelContext> context;
|
||||
|
||||
std::string name;
|
||||
|
@ -43,7 +53,6 @@ namespace domain {
|
|||
std::vector<Connection> connections;
|
||||
std::map<std::string, std::string> messages;
|
||||
|
||||
|
||||
std::vector<SourceError> errors;
|
||||
std::vector<FunctionValidator *> validators;
|
||||
|
||||
|
@ -57,35 +66,25 @@ namespace domain {
|
|||
std::optional<Display> loadDisplay(DisplayNode node);
|
||||
std::optional<Wire> loadWire(WireNode node);
|
||||
std::optional<Pin> loadPin(PinNode pins);
|
||||
|
||||
PinConnection loadPinConnection(PinConnectionNode node);
|
||||
|
||||
std::optional<Connection> loadConnection(ConnectionNode node);
|
||||
std::optional<Bus> loadBus(BusNode node);
|
||||
|
||||
std::shared_ptr<ComponentInstance> loadComponentInstance(InstanceNode instance, Library &library);
|
||||
std::shared_ptr<BusInstance> loadBusInstance(InstanceNode instance, Library &library);
|
||||
|
||||
/** Utility classes */
|
||||
std::optional<Bus> getBus(std::string name);
|
||||
std::optional<Pin> getComponentPin(std::string name, std::string pin);
|
||||
bool hasAddressSpace(std::string name);
|
||||
|
||||
void push(ComdelContext context);
|
||||
void pushAdditional(std::string name);
|
||||
ComdelContext ¤t();
|
||||
void pop();
|
||||
|
||||
std::optional<Attribute> createMemoryAttribute();
|
||||
vector<Enumeration> createWireEnumeration(vector<Value> enumeration);
|
||||
std::optional<Popup> createMemoryPopup();
|
||||
|
||||
public:
|
||||
explicit SchemaCreator(std::vector<FunctionValidator *> validators);
|
||||
|
||||
std::vector<SourceError> getErrors();
|
||||
|
||||
std::optional<Library> loadLibrary(LibraryNode node);
|
||||
Schema *loadSchema(SchemaNode node, Library &library);
|
||||
/** Context stack operations */
|
||||
void push(ComdelContext context);
|
||||
void pushAdditional(std::string name);
|
||||
ComdelContext ¤t();
|
||||
void pop();
|
||||
};
|
||||
|
||||
} // namespace domain
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "value.h"
|
||||
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace domain {
|
||||
|
||||
|
@ -44,32 +45,58 @@ namespace domain {
|
|||
return type == _type;
|
||||
}
|
||||
|
||||
std::string Value::getTypename() {
|
||||
switch (type) {
|
||||
case Value::BOOL:
|
||||
return "bool";
|
||||
case Value::INT:
|
||||
return "int";
|
||||
case Value::STRING:
|
||||
return "string";
|
||||
case Value::ADDRESS_SPACE:
|
||||
case Value::ADDRESS_SPACE_REFERENCE:
|
||||
return "address space";
|
||||
case Value::WIRE_REFERENCE:
|
||||
return "wire reference";
|
||||
case Value::ATTRIBUTE_REFERENCE:
|
||||
return "attribute";
|
||||
case Value::NIL:
|
||||
return "null";
|
||||
case Value::MEMORY:
|
||||
case Value::MEMORY_REFERENCE:
|
||||
return "memory";
|
||||
case Value::UNDEFINED:
|
||||
return "undefined";
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
long long Value::asInt() {
|
||||
if (isType(Value::INT)) {
|
||||
return intValue;
|
||||
}
|
||||
throw std::exception();
|
||||
throw std::runtime_error("expected 'int' but value contains '" + getTypename() + "'");
|
||||
}
|
||||
|
||||
std::string Value::asString() {
|
||||
if (isType(Value::STRING)) {
|
||||
return stringValue;
|
||||
}
|
||||
throw std::exception();
|
||||
throw std::runtime_error("expected 'string' but value contains '" + getTypename() + "'");
|
||||
}
|
||||
|
||||
bool Value::asBool() {
|
||||
if (isType(Value::BOOL)) {
|
||||
return boolValue;
|
||||
}
|
||||
throw std::exception();
|
||||
throw std::runtime_error("expected 'bool' but value contains '" + getTypename() + "'");
|
||||
}
|
||||
|
||||
AddressSpace Value::asAddressSpace() {
|
||||
if (isType(Value::ADDRESS_SPACE)) {
|
||||
return *addressSpace;
|
||||
}
|
||||
throw std::exception();
|
||||
throw std::runtime_error("expected 'address space' but value contains '" + getTypename() + "'");
|
||||
}
|
||||
|
||||
std::string Value::asReference() {
|
||||
|
@ -77,7 +104,7 @@ namespace domain {
|
|||
isType(Value::ATTRIBUTE_REFERENCE) || isType(Value::UNDEFINED)) {
|
||||
return reference;
|
||||
}
|
||||
throw std::exception();
|
||||
throw std::runtime_error("expected 'reference' but value contains '" + getTypename() + "'");
|
||||
}
|
||||
|
||||
std::optional<std::string> Value::asMemoryReference() {
|
||||
|
@ -92,29 +119,33 @@ namespace domain {
|
|||
void Value::setInt(long long value) {
|
||||
if (isType(Value::INT)) {
|
||||
this->intValue = value;
|
||||
} else {
|
||||
throw std::runtime_error("expected to set 'int' but value contains '" + getTypename() + "'");
|
||||
}
|
||||
throw std::exception();
|
||||
}
|
||||
|
||||
void Value::setString(std::string value) {
|
||||
if (isType(Value::STRING)) {
|
||||
this->stringValue = value;
|
||||
} else {
|
||||
throw std::runtime_error("expected to set 'string' but value contains '" + getTypename() + "'");
|
||||
}
|
||||
throw std::exception();
|
||||
}
|
||||
|
||||
void Value::setBool(bool value) {
|
||||
if (isType(Value::BOOL)) {
|
||||
this->boolValue = value;
|
||||
} else {
|
||||
throw std::runtime_error("expected to set 'bool' but value contains '" + getTypename() + "'");
|
||||
}
|
||||
throw std::exception();
|
||||
}
|
||||
|
||||
void Value::setReference(std::string value) {
|
||||
if (isType(Value::WIRE_REFERENCE)) {
|
||||
this->reference = value;
|
||||
} else {
|
||||
throw std::runtime_error("expected to set 'wire' but value contains '" + getTypename() + "'");
|
||||
}
|
||||
throw std::exception();
|
||||
}
|
||||
|
||||
|
||||
|
@ -187,7 +218,7 @@ namespace domain {
|
|||
return "null";
|
||||
}
|
||||
default:
|
||||
throw std::exception();
|
||||
throw std::runtime_error("unknown type couldn't stringify '" + getTypename() + "'");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -197,4 +228,31 @@ namespace domain {
|
|||
return val;
|
||||
}
|
||||
|
||||
bool Value::equals(Value value) {
|
||||
if (value.getType() == type) {
|
||||
switch (type) {
|
||||
case INT:
|
||||
return value.asInt() == intValue;
|
||||
case STRING:
|
||||
return value.asString() == stringValue;
|
||||
case NIL:
|
||||
case UNDEFINED:
|
||||
return true;
|
||||
case WIRE_REFERENCE:
|
||||
case ATTRIBUTE_REFERENCE:
|
||||
case ADDRESS_SPACE_REFERENCE:
|
||||
return value.asReference() == reference;
|
||||
case MEMORY_REFERENCE:
|
||||
return value.asMemoryReference() == memoryReference;
|
||||
case MEMORY:
|
||||
return value.asMemory() == memory;
|
||||
case BOOL:
|
||||
return value.asBool() == boolValue;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace domain
|
||||
|
|
|
@ -43,34 +43,10 @@ namespace domain {
|
|||
|
||||
Value() = default;
|
||||
|
||||
bool equals(Value value) {
|
||||
if (value.getType() == type) {
|
||||
switch (type) {
|
||||
case INT:
|
||||
return value.asInt() == intValue;
|
||||
case STRING:
|
||||
return value.asString() == stringValue;
|
||||
case NIL:
|
||||
case UNDEFINED:
|
||||
return true;
|
||||
case WIRE_REFERENCE:
|
||||
case ATTRIBUTE_REFERENCE:
|
||||
case ADDRESS_SPACE_REFERENCE:
|
||||
return value.asReference() == reference;
|
||||
case MEMORY_REFERENCE:
|
||||
return value.asMemoryReference() == memoryReference;
|
||||
case MEMORY:
|
||||
return value.asMemory() == memory;
|
||||
case BOOL:
|
||||
return value.asBool() == boolValue;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool equals(Value value);
|
||||
|
||||
std::string string();
|
||||
std::string getTypename();
|
||||
|
||||
ValueType getType();
|
||||
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
#include "ast_nodes.h"
|
||||
|
||||
/*************************** AST NODE ********************************/
|
||||
|
||||
AstNode::~AstNode() = default;
|
||||
|
||||
/*************************** NUMBER NODE ********************************/
|
||||
|
||||
NumberNode::NumberNode(const std::string &expression) {
|
||||
|
@ -41,7 +37,11 @@ std::string StringNode::asString() {
|
|||
|
||||
/*************************** VALUE NODE ********************************/
|
||||
|
||||
long long ValueNode::asInt() {
|
||||
ValueNode::ValueType ValueNode::getType() const {
|
||||
return type.value;
|
||||
}
|
||||
|
||||
long long int ValueNode::asInt() {
|
||||
if (is(INT)) {
|
||||
return intValue.value();
|
||||
}
|
||||
|
@ -134,4 +134,39 @@ ValueNode ValueNode::ofMemory(std::optional<std::string> _value) {
|
|||
value.type = EnumNode(MEMORY);
|
||||
value.identifierValue = _value;
|
||||
return value;
|
||||
}
|
||||
|
||||
/*************************** DisplayItem NODE ********************************/
|
||||
|
||||
std::optional<long long int> DisplayItemNode::asInt(const std::string &property, long long int _default) {
|
||||
auto prop = getProperty(property);
|
||||
if(prop.has_value()) {
|
||||
return prop->value.is(ValueNode::INT) ? std::optional(prop->value.asInt()) : std::nullopt;
|
||||
}
|
||||
return _default;
|
||||
}
|
||||
|
||||
std::optional<Color> DisplayItemNode::asColor(const std::string &property, Color _default) {
|
||||
auto prop = getProperty(property);
|
||||
if(prop.has_value()) {
|
||||
return prop->value.is(ValueNode::COLOR) ? std::optional(prop->value.asColor()) : std::nullopt;
|
||||
}
|
||||
return _default;
|
||||
}
|
||||
|
||||
std::optional<std::string> DisplayItemNode::asString(const std::string &property, std::string _default) {
|
||||
auto prop = getProperty(property);
|
||||
if(prop.has_value()) {
|
||||
return prop->value.is(ValueNode::STRING) ? std::optional(prop->value.asString()) : std::nullopt;
|
||||
}
|
||||
return _default;
|
||||
}
|
||||
|
||||
std::optional<PropertyNode> DisplayItemNode::getProperty(const std::string &property) {
|
||||
for(auto &prop: values) {
|
||||
if(prop.key.value == property) {
|
||||
return prop;
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
|
@ -8,28 +8,30 @@
|
|||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
/*****************************************************************************
|
||||
* BASE TYPES *
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* AST base class, all AST node classes extend this class. Class contains basic
|
||||
* information about nodes location in file.
|
||||
*/
|
||||
class AstNode {
|
||||
public:
|
||||
|
||||
/** Contains information about where in source file given node is located */
|
||||
Span span;
|
||||
|
||||
AstNode() = default;
|
||||
|
||||
virtual ~AstNode();
|
||||
|
||||
AstNode(AstNode &&) = default;
|
||||
|
||||
AstNode &operator=(AstNode &&) = default;
|
||||
|
||||
AstNode(const AstNode &) = default;
|
||||
|
||||
AstNode &operator=(const AstNode &) = default;
|
||||
};
|
||||
|
||||
/**
|
||||
* AST base enum class,
|
||||
* Used to represent AST enums
|
||||
* */
|
||||
template<typename T>
|
||||
struct EnumNode : public AstNode {
|
||||
EnumNode() = default;
|
||||
|
@ -39,284 +41,423 @@ struct EnumNode : public AstNode {
|
|||
T value;
|
||||
};
|
||||
|
||||
/** Represents string
|
||||
* value contains quote-marks ("" or '' depending on string type)
|
||||
* */
|
||||
struct StringNode : public AstNode {
|
||||
/** String including quote-marks*/
|
||||
std::string value;
|
||||
|
||||
/** Returns string without quote-marks */
|
||||
std::string asString();
|
||||
};
|
||||
|
||||
/** Represents identifiers */
|
||||
struct IdentifierNode : public AstNode {
|
||||
std::string value;
|
||||
};
|
||||
|
||||
/** Represents all numbers used
|
||||
* All numbers must fit into long long int
|
||||
* */
|
||||
struct NumberNode : public AstNode {
|
||||
long long int value;
|
||||
long long int value = 0;
|
||||
|
||||
explicit NumberNode(const std::string &expression);
|
||||
|
||||
NumberNode() : value(0) {}
|
||||
NumberNode() = default;
|
||||
};
|
||||
|
||||
/** Represents color
|
||||
* color comes in two formats #RRGGBB or #RRGGBBAA (AA representing opacity)
|
||||
* */
|
||||
struct ColorNode : public AstNode {
|
||||
Color color;
|
||||
|
||||
explicit ColorNode(const std::string &expression);
|
||||
|
||||
ColorNode() {}
|
||||
ColorNode() = default;
|
||||
};
|
||||
|
||||
|
||||
struct CountNode : public AstNode {
|
||||
/** Represents ordered number pair */
|
||||
struct NumberPairNode : public AstNode {
|
||||
NumberNode first;
|
||||
NumberNode second;
|
||||
|
||||
CountNode(NumberNode first, NumberNode second) : first(std::move(first)), second(std::move(second)) {}
|
||||
NumberPairNode(NumberNode first, NumberNode second) : first(first), second(second) {}
|
||||
|
||||
CountNode() = default;
|
||||
};
|
||||
|
||||
|
||||
struct AddressSpaceNode : public AstNode {
|
||||
IdentifierNode name;
|
||||
NumberNode start;
|
||||
NumberNode end;
|
||||
NumberPairNode() = default;
|
||||
};
|
||||
|
||||
/** Represents generic value
|
||||
* Because attributes can contain different value types,
|
||||
* this allows us to use one generic type for all attributes
|
||||
* */
|
||||
class ValueNode : public AstNode {
|
||||
public:
|
||||
enum ValueType {
|
||||
/** Stores same content as NumberNode */
|
||||
INT,
|
||||
/** Stores same content as StringNode */
|
||||
STRING,
|
||||
/** Stores true or false */
|
||||
BOOL,
|
||||
/** Stores wire nam or null */
|
||||
WIRE,
|
||||
/** Default type assigned when node value is of type IdentifierNode and more correct type is assigned later */
|
||||
IDENTIFIER,
|
||||
/** Stores memory name or null */
|
||||
MEMORY,
|
||||
/** Stores null */
|
||||
NIL,
|
||||
/** Store same content as ColorNode */
|
||||
COLOR,
|
||||
};
|
||||
|
||||
private:
|
||||
EnumNode<ValueType> type;
|
||||
std::optional<long long> intValue;
|
||||
std::optional<std::string> stringValue;
|
||||
std::optional<bool> boolValue;
|
||||
std::optional<std::string> identifierValue;
|
||||
std::optional<Color> colorValue;
|
||||
/** Type determines what is stored inside ValueNode */
|
||||
EnumNode<ValueType> type = EnumNode(NIL);
|
||||
/** All possible values for ValueNode are stored inside optionals */
|
||||
std::optional<long long> intValue = std::nullopt;
|
||||
std::optional<std::string> stringValue = std::nullopt;
|
||||
std::optional<bool> boolValue = std::nullopt;
|
||||
std::optional<std::string> identifierValue = std::nullopt;
|
||||
std::optional<Color> colorValue = std::nullopt;
|
||||
|
||||
public:
|
||||
ValueNode() = default;
|
||||
|
||||
ValueType getType() const {
|
||||
return type.value;
|
||||
}
|
||||
|
||||
long long asInt();
|
||||
ValueType getType() const;
|
||||
|
||||
/** Checks ValueNode is of requested type and returns it or returns default value for given type*/
|
||||
long long int asInt();
|
||||
std::string asString();
|
||||
|
||||
std::string asIdentifier();
|
||||
|
||||
Color asColor();
|
||||
|
||||
bool asBool();
|
||||
|
||||
/** Returns true if ValueNode is of given valueType */
|
||||
bool is(ValueType valueType);
|
||||
|
||||
/** Static methods used to generate ValueNodes of requested type */
|
||||
static ValueNode ofBool(bool _value);
|
||||
|
||||
static ValueNode ofInt(long long _value);
|
||||
|
||||
static ValueNode ofString(std::string _value);
|
||||
|
||||
static ValueNode ofIdentifier(std::string _value);
|
||||
|
||||
static ValueNode ofMemory(std::optional<std::string> _value);
|
||||
|
||||
static ValueNode ofNull();
|
||||
|
||||
static ValueNode ofColor(Color color);
|
||||
|
||||
static ValueNode ofWire(std::optional<std::string> _value);
|
||||
|
||||
};
|
||||
|
||||
/** Represents an identifier-value pair*/
|
||||
struct PropertyNode : public AstNode {
|
||||
IdentifierNode key;
|
||||
ValueNode value;
|
||||
|
||||
PropertyNode() = default;
|
||||
PropertyNode(IdentifierNode key, ValueNode value): key(key), value(value) {}
|
||||
};
|
||||
|
||||
/** Represents a string-value pair */
|
||||
struct StringPropertyNode : public AstNode {
|
||||
StringNode key;
|
||||
ValueNode value;
|
||||
|
||||
StringPropertyNode() = default;
|
||||
StringPropertyNode(StringNode key, ValueNode value): key(key), value(value) {}
|
||||
};
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* RULE TYPES *
|
||||
*****************************************************************************/
|
||||
|
||||
struct IfStatementNode;
|
||||
|
||||
/** Represents validation rule
|
||||
* Rules are made from a list of
|
||||
* if - else if statements
|
||||
* */
|
||||
struct RuleNode : public AstNode {
|
||||
std::vector<IfStatementNode> statements;
|
||||
};
|
||||
|
||||
/** Represents condition inside if statement
|
||||
* Every condition is made from optional negation operator !
|
||||
* Function called and list of function parameters
|
||||
* */
|
||||
struct ConditionNode {
|
||||
bool negated;
|
||||
IdentifierNode functionName;
|
||||
std::vector<ValueNode> params;
|
||||
};
|
||||
|
||||
class ActionNode : public AstNode {
|
||||
public:
|
||||
/** Represents action executed inside if statement
|
||||
* */
|
||||
struct ActionNode : public AstNode {
|
||||
/** There are two types of action determined by action type */
|
||||
enum ActionType {
|
||||
/** Error actions represent invalid state and cause validation to fail */
|
||||
ERROR,
|
||||
/** Warning actions represent states that can cause issue when simulating
|
||||
* model but models created with it are still valid
|
||||
* */
|
||||
WARNING
|
||||
};
|
||||
|
||||
EnumNode<ActionType> type;
|
||||
/** Message used if condition is fulfilled */
|
||||
StringNode message;
|
||||
};
|
||||
|
||||
|
||||
/** If statements represents one validation check inside rule */
|
||||
struct IfStatementNode : public AstNode {
|
||||
ConditionNode condition;
|
||||
ActionNode action;
|
||||
};
|
||||
|
||||
struct RuleNode : public AstNode {
|
||||
std::vector<IfStatementNode> statements;
|
||||
};
|
||||
|
||||
struct EnumerationNode : public AstNode {
|
||||
StringNode key;
|
||||
ValueNode value;
|
||||
};
|
||||
/*****************************************************************************
|
||||
* ATTRIBUTE TYPES *
|
||||
*****************************************************************************/
|
||||
|
||||
/** Represents popup dialog used to modified attribute inside which it is defined
|
||||
* */
|
||||
struct PopupNode : public AstNode {
|
||||
/** Determines type of popup*/
|
||||
enum PopupType {
|
||||
/** Automatic popup is opened when component or connection containing it is defined */
|
||||
AUTOMATIC,
|
||||
/** On demand popups are opened on user request usually from context menus*/
|
||||
ON_DEMAND
|
||||
};
|
||||
|
||||
std::optional<EnumNode<PopupType>> type;
|
||||
/** Title of popup */
|
||||
std::optional<StringNode> title;
|
||||
/** Text of popup */
|
||||
std::optional<StringNode> text;
|
||||
|
||||
/** If popup contains an enumeration*/
|
||||
bool enumerated;
|
||||
std::vector<EnumerationNode> enumeration;
|
||||
std::vector<StringPropertyNode> enumeration;
|
||||
|
||||
/** Validation rules for given popup */
|
||||
std::vector<RuleNode> rules;
|
||||
};
|
||||
|
||||
struct PropertyNode : public AstNode {
|
||||
IdentifierNode key;
|
||||
ValueNode value;
|
||||
/** Represents component or connection attribute
|
||||
* Attributes are values that can programmatically be changed
|
||||
* if popup is defined
|
||||
* */
|
||||
struct AttributeNode : public AstNode {
|
||||
/** Type of attribute */
|
||||
ValueNode::ValueType type;
|
||||
/** Name of attribute */
|
||||
IdentifierNode name;
|
||||
/** Display name */
|
||||
std::optional<StringNode> displayName;
|
||||
/** Default type of attribute */
|
||||
std::optional<ValueNode> defaultValue;
|
||||
/** Popup used to change attribute value */
|
||||
std::optional<PopupNode> popup;
|
||||
};
|
||||
|
||||
struct DisplayItemNode : public AstNode {
|
||||
IdentifierNode type;
|
||||
std::vector<PropertyNode> values;
|
||||
/*****************************************************************************
|
||||
* DISPLAY TYPES *
|
||||
*****************************************************************************/
|
||||
|
||||
long long int asInt(std::vector<SourceError> *errors, const std::string &property, long long int _default = 0) {
|
||||
for (auto &prop: values) {
|
||||
if (prop.key.value == property) {
|
||||
if (prop.value.is(ValueNode::INT)) {
|
||||
return prop.value.asInt();
|
||||
} else {
|
||||
if (errors != nullptr) {
|
||||
errors->emplace_back(prop.value.span, "expected number");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return _default;
|
||||
}
|
||||
|
||||
Color asColor(std::vector<SourceError> *errors, const std::string &property, Color _default = Color(0, 0, 0)) {
|
||||
for (auto &prop: values) {
|
||||
if (prop.key.value == property) {
|
||||
if (prop.value.is(ValueNode::COLOR)) {
|
||||
return prop.value.asColor();
|
||||
} else {
|
||||
if (errors != nullptr) {
|
||||
errors->emplace_back(prop.value.span, "expected number");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return _default;
|
||||
}
|
||||
|
||||
std::string asIdentifier(std::vector<SourceError> *errors, const std::string &property, std::string _default = "") {
|
||||
for (auto &prop: values) {
|
||||
if (prop.key.value == property) {
|
||||
if (prop.value.is(ValueNode::IDENTIFIER)) {
|
||||
return prop.value.asIdentifier();
|
||||
} else {
|
||||
if (errors != nullptr) {
|
||||
errors->emplace_back(prop.value.span, "expected identifier");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return _default;
|
||||
}
|
||||
|
||||
|
||||
std::string asString(std::vector<SourceError> *errors, const std::string &property, std::string _default = "") {
|
||||
for (auto &prop: values) {
|
||||
if (prop.key.value == property) {
|
||||
if (prop.value.is(ValueNode::STRING)) {
|
||||
return prop.value.asString();
|
||||
} else {
|
||||
if (errors != nullptr) {
|
||||
errors->emplace_back(prop.value.span, "expected string");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return _default;
|
||||
}
|
||||
};
|
||||
struct DisplayItemNode;
|
||||
|
||||
/** Represents how a component or bus is rendered
|
||||
* Display is made from an list of display items
|
||||
* */
|
||||
struct DisplayNode : public AstNode {
|
||||
std::vector<DisplayItemNode> items;
|
||||
};
|
||||
|
||||
struct PinConnectionNode : public AstNode {
|
||||
enum ConnectionType {
|
||||
REQUIRED,
|
||||
OPTIONAL
|
||||
};
|
||||
/** DisplayItem represents one rendered item
|
||||
* in source code items are defined similar to json objects
|
||||
* eg.
|
||||
* @code rect {
|
||||
* x: 100;
|
||||
* y: 100;
|
||||
* w: 100;
|
||||
* h: 100;
|
||||
* fillColor: #123456
|
||||
* }
|
||||
* */
|
||||
struct DisplayItemNode : public AstNode {
|
||||
/** Contains type of display item */
|
||||
IdentifierNode type;
|
||||
/** Contains all property nodes */
|
||||
std::vector<PropertyNode> values;
|
||||
|
||||
StringNode message;
|
||||
EnumNode<ConnectionType> type;
|
||||
/** Returns value of requested property
|
||||
* If requested property doesn't exists default value is returned (eg. asInt is called but PropertyNode contains string)
|
||||
* If value of requested property is different than expected nullopt is retured
|
||||
* */
|
||||
std::optional<long long int> asInt(const std::string &property, long long int _default = 0);
|
||||
std::optional<Color> asColor(const std::string &property, Color _default = Color(0, 0, 0));
|
||||
std::optional<std::string> asString(const std::string &property, std::string _default = "");
|
||||
|
||||
private:
|
||||
std::optional<PropertyNode> getProperty(const std::string &property);
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
* LIBRARY TYPES *
|
||||
*****************************************************************************/
|
||||
|
||||
/** Represents AddressSpaces
|
||||
* Address spaces are defined with their name and address range
|
||||
* */
|
||||
struct AddressSpaceNode : public AstNode {
|
||||
IdentifierNode name;
|
||||
/** Range represent which addresses are available for components that use memory space [first, second> */
|
||||
NumberPairNode range;
|
||||
};
|
||||
|
||||
/** Pins are used to create component-component or component-bus connections */
|
||||
struct PinNode : public AstNode {
|
||||
/** Determines pin type, pin types currently only affect how pins are rendered */
|
||||
enum PinType {
|
||||
IN_OUT,
|
||||
IN,
|
||||
OUT
|
||||
};
|
||||
|
||||
/** Name of pin */
|
||||
IdentifierNode name;
|
||||
/** Type of pin */
|
||||
EnumNode<PinType> type;
|
||||
/** Tooltip content displayed on hover over pin */
|
||||
std::optional<StringNode> tooltip;
|
||||
std::optional<PinConnectionNode> connection;
|
||||
/** If present this means pin must be connected to another component or bus to create connection
|
||||
* Connection contains error message shown
|
||||
* */
|
||||
std::optional<StringNode> connection;
|
||||
/** Determines how the pin is displayed */
|
||||
std::optional<DisplayNode> display;
|
||||
/** If pin connection is optional it requires list of wires used to populate comdel model */
|
||||
std::optional<std::vector<ValueNode>> wires;
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents COMDEL component
|
||||
* */
|
||||
struct ComponentNode : public AstNode {
|
||||
/** Determines type of component */
|
||||
enum ComponentType {
|
||||
/** Generic component */
|
||||
OTHER,
|
||||
/** Represents processor, all processors have implicit attribute _memory if type memory
|
||||
* used when generating COMDEL model to connect memories and processors
|
||||
*/
|
||||
PROCESSOR,
|
||||
/** Represents memory, all components of type memory can be selected in _memory attribute of processor */
|
||||
MEMORY
|
||||
};
|
||||
|
||||
/** Component name */
|
||||
IdentifierNode name;
|
||||
/** Component name */
|
||||
std::optional<StringNode> displayName;
|
||||
/** Tooltip displayed on hover */
|
||||
std::optional<StringNode> tooltip;
|
||||
/** Contains path to COMDEL source containing current component */
|
||||
std::optional<StringNode> source;
|
||||
/** Type of component */
|
||||
EnumNode<ComponentType> type;
|
||||
/** List of component level rules */
|
||||
std::vector<RuleNode> rules;
|
||||
/** Default used to name instances */
|
||||
std::optional<IdentifierNode> instanceName;
|
||||
/** Count determines number of instances allowed in a schema */
|
||||
std::optional<NumberPairNode> count;
|
||||
/** Display determines how component is rendered */
|
||||
std::optional<DisplayNode> display;
|
||||
/** List of all pins */
|
||||
std::vector<PinNode> pins;
|
||||
/** List of all attributes */
|
||||
std::vector<AttributeNode> attributes;
|
||||
};
|
||||
|
||||
/** WireNode represents COMDEL wire
|
||||
* */
|
||||
struct WireNode : public AstNode {
|
||||
/** Determines type of wires */
|
||||
enum WireType {
|
||||
/** Generic wire */
|
||||
WIRE,
|
||||
/** wired_and can have multiple sources, that are ANDed together */
|
||||
WIRED_AND,
|
||||
/** wired_and can have multiple sources, that are ORed together */
|
||||
WIRED_OR,
|
||||
/** r_wire can remain unconnected */
|
||||
R_WIRE
|
||||
};
|
||||
EnumNode<WireType> type;
|
||||
/** Name of wire */
|
||||
IdentifierNode name;
|
||||
/** Number of bits inside of a wire */
|
||||
NumberNode size;
|
||||
|
||||
/** If wire is visible or hidden, this determines how wires are generated in COMDEL */
|
||||
bool hidden = false;
|
||||
|
||||
bool hasTerminateWith;
|
||||
/** If wire isn't connected to anything it is replaced with terminate with terminateWith value */
|
||||
bool hasTerminateWith = false;
|
||||
ValueNode terminateWith;
|
||||
};
|
||||
|
||||
struct AttributeNode : public AstNode {
|
||||
ValueNode::ValueType type;
|
||||
/** Buses dont exist in COMDEL but they are useful
|
||||
* as they allow us to connect multiple COMDEL wires together
|
||||
* */
|
||||
struct BusNode : public AstNode {
|
||||
enum BusType {
|
||||
/** This busses connect two components */
|
||||
AUTOMATIC,
|
||||
/**
|
||||
* This busses allow us to connect multiple component together using one bus
|
||||
* */
|
||||
REGULAR,
|
||||
/** This busses connect two components,
|
||||
* they differ from automatic as they allow us to connect same pins multiple times */
|
||||
SINGLE_AUTOMATIC
|
||||
};
|
||||
|
||||
EnumNode<BusType> type;
|
||||
/** Bus name */
|
||||
IdentifierNode name;
|
||||
std::optional<ValueNode> defaultValue;
|
||||
std::optional<PopupNode> popup;
|
||||
/** Display name */
|
||||
std::optional<StringNode> displayName;
|
||||
/** Default used to name instances */
|
||||
std::optional<IdentifierNode> instanceName;
|
||||
/** Tooltip displayed on hover */
|
||||
std::optional<StringNode> tooltip;
|
||||
/** Count determines number of instances allowed in a schema */
|
||||
std::optional<NumberPairNode> count;
|
||||
/** Display determines how component is rendered */
|
||||
std::optional<DisplayNode> display;
|
||||
|
||||
/** List of all COMDEL wires contained in bus */
|
||||
std::vector<WireNode> wires;
|
||||
};
|
||||
|
||||
/** Represents ComponentConnection key in Connection node
|
||||
* (eg. componentName.pinName)
|
||||
* */
|
||||
struct ConnectionComponentNode : public AstNode {
|
||||
IdentifierNode component;
|
||||
IdentifierNode pin;
|
||||
};
|
||||
|
||||
/** Represents Connection node
|
||||
* Connection can be between component and bus in which second is null,
|
||||
* or between two components
|
||||
* */
|
||||
struct ConnectionNode : public AstNode {
|
||||
ConnectionComponentNode first;
|
||||
std::optional<ConnectionComponentNode> second;
|
||||
|
@ -324,51 +465,22 @@ struct ConnectionNode : public AstNode {
|
|||
IdentifierNode bus;
|
||||
std::vector<AttributeNode> attributes;
|
||||
|
||||
/** If connection is of type component-component it contains two pairs of wires */
|
||||
std::vector<ValueNode> firstWires;
|
||||
std::optional<std::vector<ValueNode>> secondWires;
|
||||
};
|
||||
|
||||
struct ComponentNode : public AstNode {
|
||||
enum ComponentType {
|
||||
OTHER,
|
||||
PROCESSOR,
|
||||
MEMORY
|
||||
};
|
||||
|
||||
IdentifierNode name;
|
||||
std::optional<StringNode> tooltip;
|
||||
std::optional<StringNode> source;
|
||||
EnumNode<ComponentType> type;
|
||||
std::vector<RuleNode> rules;
|
||||
std::optional<IdentifierNode> instanceName;
|
||||
std::optional<CountNode> count;
|
||||
std::optional<DisplayNode> display;
|
||||
std::vector<PinNode> pins;
|
||||
std::vector<AttributeNode> attributes;
|
||||
};
|
||||
|
||||
struct BusNode : public AstNode {
|
||||
enum BusType {
|
||||
AUTOMATIC,
|
||||
REGULAR,
|
||||
SINGLE_AUTOMATIC
|
||||
};
|
||||
|
||||
EnumNode<BusType> type;
|
||||
IdentifierNode name;
|
||||
std::optional<IdentifierNode> instanceName;
|
||||
std::optional<StringNode> tooltip;
|
||||
std::optional<CountNode> count;
|
||||
std::optional<DisplayNode> display;
|
||||
|
||||
std::vector<WireNode> wires;
|
||||
};
|
||||
|
||||
/** LibraryNode represent library instance */
|
||||
struct LibraryNode : public AstNode {
|
||||
/** Name of library */
|
||||
std::optional<StringNode> name;
|
||||
/** Library info contains generic information about library */
|
||||
std::optional<StringNode> libraryInfo;
|
||||
/** Contains text that is added to top of COMDEL file */
|
||||
std::optional<StringNode> header;
|
||||
/** Contains path to component directory */
|
||||
std::optional<StringNode> componentDirectory;
|
||||
/** Contains text that is added to top of System component in COMDEL file */
|
||||
std::optional<StringNode> componentHeader;
|
||||
|
||||
std::vector<AddressSpaceNode> addressSpaces;
|
||||
|
@ -377,46 +489,64 @@ struct LibraryNode : public AstNode {
|
|||
std::vector<BusNode> buses;
|
||||
std::vector<ConnectionNode> connections;
|
||||
|
||||
/** Contains properties used to translate dialog and error messages */
|
||||
std::vector<PropertyNode> messages;
|
||||
};
|
||||
|
||||
// SCHEMA models
|
||||
/*****************************************************************************
|
||||
* LIBRARY TYPES *
|
||||
*****************************************************************************/
|
||||
|
||||
/** Represents instance of attribute in component or connection instance */
|
||||
struct InstanceAttributeNode : public AstNode {
|
||||
IdentifierNode name;
|
||||
ValueNode value;
|
||||
};
|
||||
|
||||
/** Represents instance of a component or a bus */
|
||||
struct InstanceNode : public AstNode {
|
||||
/** Contains instance name */
|
||||
IdentifierNode name;
|
||||
/** Contains component name */
|
||||
IdentifierNode component;
|
||||
|
||||
std::optional<CountNode> position;
|
||||
/** Contains position of component instance */
|
||||
std::optional<NumberPairNode> position;
|
||||
std::vector<InstanceAttributeNode> attributes;
|
||||
|
||||
/** Contains size of bus instances */
|
||||
std::optional<NumberNode> size;
|
||||
};
|
||||
|
||||
struct ConnectionComponentInstance : public AstNode {
|
||||
/** Represents ComponentConnection of a selected instance */
|
||||
struct ConnectionComponentInstanceNode : public AstNode {
|
||||
/** Name of component instance */
|
||||
IdentifierNode instance;
|
||||
/** Name of pin */
|
||||
IdentifierNode pin;
|
||||
};
|
||||
|
||||
/** Represents Connection instance */
|
||||
struct ConnectionInstanceNode : public AstNode {
|
||||
ConnectionComponentInstance first;
|
||||
std::optional<ConnectionComponentInstance> second;
|
||||
ConnectionComponentInstanceNode first;
|
||||
std::optional<ConnectionComponentInstanceNode> second;
|
||||
|
||||
IdentifierNode bus;
|
||||
|
||||
std::vector<InstanceAttributeNode> attributes;
|
||||
};
|
||||
|
||||
|
||||
/** Represent schema instance */
|
||||
struct SchemaNode : public AstNode {
|
||||
/** Contains path to library source */
|
||||
std::optional<StringNode> source;
|
||||
|
||||
/** Contains list of instances */
|
||||
std::vector<InstanceNode> instances;
|
||||
/** Contains list of connection */
|
||||
std::vector<ConnectionInstanceNode> connections;
|
||||
|
||||
/** Contains library */
|
||||
std::optional<LibraryNode> library;
|
||||
};
|
||||
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
//
|
||||
// Created by bbr on 12.06.22..
|
||||
//
|
||||
|
||||
#include "color.h"
|
|
@ -7,12 +7,12 @@
|
|||
|
||||
|
||||
struct Color {
|
||||
unsigned char r;
|
||||
unsigned char g;
|
||||
unsigned char b;
|
||||
unsigned char a;
|
||||
unsigned char r = 0;
|
||||
unsigned char g = 0;
|
||||
unsigned char b = 0;
|
||||
unsigned char a = 255;
|
||||
|
||||
Color(): r(0), g(0), b(0), a(0) {}
|
||||
Color() = default;
|
||||
|
||||
Color(unsigned char r, unsigned char g, unsigned char b, unsigned char a = 0): r(r), g(g), b(b), a(a) {}
|
||||
};
|
||||
|
|
|
@ -11,11 +11,14 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
/** Contains results of tokenizing,
|
||||
* if errors isn't empty tokenizing has failed */
|
||||
struct LexerResult {
|
||||
std::vector<Token> tokens;
|
||||
std::vector<SourceError> errors;
|
||||
};
|
||||
|
||||
/** Used to tokenize input string */
|
||||
class ComdelLexer {
|
||||
|
||||
enum Radix {
|
||||
|
@ -24,9 +27,11 @@ class ComdelLexer {
|
|||
HEX_NUMBER = 16
|
||||
};
|
||||
|
||||
/** Source file */
|
||||
std::string source;
|
||||
std::vector<Token> tokens;
|
||||
std::vector<SourceError> errors;
|
||||
/** Source file */
|
||||
ParseContext *parseContext;
|
||||
unsigned fileId;
|
||||
|
||||
|
@ -36,34 +41,32 @@ public:
|
|||
LexerResult tokenize();
|
||||
|
||||
private:
|
||||
void skipWhitespace();
|
||||
|
||||
unsigned takeNumberInRadix(Radix radix);
|
||||
|
||||
unsigned takeHexColor();
|
||||
|
||||
bool digitIsValid(char ch, Radix radix);
|
||||
|
||||
Radix takeRadix();
|
||||
|
||||
PResult<TokenType> nextTokenType();
|
||||
|
||||
/** Current parsing info */
|
||||
Position tokenBegin;
|
||||
Position position;
|
||||
char ch;
|
||||
|
||||
/** Methods used to skip unused content */
|
||||
void skipWhitespace();
|
||||
void skipComment();
|
||||
|
||||
bool skipMultilineComment();
|
||||
void bump(unsigned count = 1);
|
||||
|
||||
/** Metods used for number parsing */
|
||||
unsigned takeNumberInRadix(Radix radix);
|
||||
bool digitIsValid(char ch, Radix radix);
|
||||
Radix takeRadix();
|
||||
|
||||
unsigned takeHexColor();
|
||||
|
||||
PResult<TokenType> nextTokenType();
|
||||
|
||||
PResult<TokenType> takeString();
|
||||
|
||||
PResult<TokenType> takeRawString();
|
||||
|
||||
void bump(unsigned count = 1);
|
||||
|
||||
char peek();
|
||||
|
||||
/** Checks if we reached end of file */
|
||||
bool eof();
|
||||
};
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -42,16 +42,20 @@ private:
|
|||
|
||||
Span &getPreviousSpan();
|
||||
|
||||
/** Skips current token */
|
||||
void bump();
|
||||
|
||||
/** Checks if next token is of given type and if it is consumes it */
|
||||
bool consume(TokenType tokenType);
|
||||
|
||||
/** Checks if next token is of given type */
|
||||
bool check(TokenType tokenType);
|
||||
|
||||
/** Skips until next keyword on same level
|
||||
* Used to continue parsing on error
|
||||
* */
|
||||
void skipUntilNextKeyword();
|
||||
|
||||
/** Retuns current token */
|
||||
Token ¤t();
|
||||
|
||||
/** Throws error of unexpected types */
|
||||
[[nodiscard]] PError unexpected();
|
||||
|
||||
template<typename T>
|
||||
|
@ -63,73 +67,45 @@ private:
|
|||
|
||||
Spanner getSpanner();
|
||||
|
||||
// used to parse library and schema
|
||||
/** Base types */
|
||||
PResult<StringNode> parseString();
|
||||
|
||||
PResult<ColorNode> parseColor();
|
||||
|
||||
PResult<IdentifierNode> parseIdentifier();
|
||||
|
||||
PResult<NumberNode> parseNumber();
|
||||
|
||||
PResult<CountNode> parseCount();
|
||||
|
||||
PResult<NumberPairNode> parseNumberPair();
|
||||
PResult<PropertyNode> parseProperty(std::optional<TokenType> valueType);
|
||||
|
||||
PResult<EnumerationNode> parseEnumeration();
|
||||
|
||||
PResult<ValueNode> parseConnectionWire();
|
||||
|
||||
PResult<ComponentNode> parseComponent();
|
||||
|
||||
PResult<AddressSpaceNode> parseAddress();
|
||||
|
||||
PResult<PinNode> parsePin();
|
||||
|
||||
PResult<DisplayNode> parseDisplay();
|
||||
|
||||
PResult<PinConnectionNode> parsePinConnection();
|
||||
|
||||
PResult<AttributeNode> parseAttribute();
|
||||
|
||||
PResult<PopupNode> parsePopup();
|
||||
|
||||
PResult<RuleNode> parseRule();
|
||||
|
||||
PResult<BusNode> parseBus();
|
||||
|
||||
PResult<WireNode> parseWire();
|
||||
|
||||
PResult<ConnectionNode> parseConnection();
|
||||
|
||||
PResult<DisplayItemNode> parseDisplayItem();
|
||||
|
||||
PResult<IfStatementNode> parseIfStatement();
|
||||
|
||||
PResult<StringPropertyNode> parseStringProperty();
|
||||
PResult<ValueNode> parseValue();
|
||||
|
||||
// used to parse schema
|
||||
PResult<CountNode> parsePosition();
|
||||
|
||||
PResult<InstanceNode> parseInstance();
|
||||
|
||||
PResult<InstanceAttributeNode> parseInstanceAttribute();
|
||||
|
||||
PResult<ConnectionInstanceNode> parseConnectionInstance();
|
||||
|
||||
/** Library types */
|
||||
PResult<ValueNode> parseConnectionWire();
|
||||
PResult<ComponentNode> parseComponent();
|
||||
PResult<EnumNode<ComponentNode::ComponentType>> parseComponentType();
|
||||
|
||||
PResult<AddressSpaceNode> parseAddress();
|
||||
PResult<PinNode> parsePin();
|
||||
PResult<DisplayNode> parseDisplay();
|
||||
PResult<AttributeNode> parseAttribute();
|
||||
PResult<PopupNode> parsePopup();
|
||||
PResult<RuleNode> parseRule();
|
||||
PResult<BusNode> parseBus();
|
||||
PResult<WireNode> parseWire();
|
||||
PResult<ConnectionNode> parseConnection();
|
||||
PResult<ConnectionComponentNode> parseConnectionComponent();
|
||||
PResult<DisplayItemNode> parseDisplayItem();
|
||||
PResult<IfStatementNode> parseIfStatement();
|
||||
PResult<EnumNode<BusNode::BusType>> parseBusType();
|
||||
|
||||
PResult<EnumNode<PinConnectionNode::ConnectionType>> parseConnectionType();
|
||||
/** Schema types */
|
||||
PResult<InstanceNode> parseInstance();
|
||||
PResult<InstanceAttributeNode> parseInstanceAttribute();
|
||||
PResult<ConnectionInstanceNode> parseConnectionInstance();
|
||||
PResult<ConnectionComponentInstanceNode> parseConnectionComponentInstance();
|
||||
|
||||
public:
|
||||
explicit ComdelParser(std::vector<Token> tokens);
|
||||
|
||||
std::optional<SchemaNode> parseSchema();
|
||||
|
||||
std::optional<LibraryNode> parseLibrary();
|
||||
|
||||
const std::vector<SourceError> &getErrors();
|
||||
};
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
/*** Represent source file */
|
||||
class SourceFile {
|
||||
std::string fileName;
|
||||
std::string source;
|
||||
|
@ -22,7 +23,7 @@ public:
|
|||
void addLineOffset(unsigned offset);
|
||||
};
|
||||
|
||||
|
||||
/*** Represent parsing context */
|
||||
class ParseContext {
|
||||
std::string applicationDir;
|
||||
std::vector<SourceFile> fileMap;
|
||||
|
|
|
@ -101,7 +101,7 @@ enum class TokenType {
|
|||
KW_SCHEMA,
|
||||
KW_POSITION,
|
||||
KW_SIZE,
|
||||
KW_UNKNOWN,
|
||||
KW_DISPLAY_NAME,
|
||||
|
||||
// TYPES
|
||||
INT_TYPE,
|
||||
|
|
|
@ -106,6 +106,7 @@ TokenTables::TokenTables() {
|
|||
add(TokenType::KW_SCHEMA, "@schema", TOKENIZABLE | KEYWORD_NAME);
|
||||
add(TokenType::KW_POSITION, "@position", TOKENIZABLE | KEYWORD_NAME);
|
||||
add(TokenType::KW_SIZE, "@size", TOKENIZABLE | KEYWORD_NAME);
|
||||
add(TokenType::KW_DISPLAY_NAME, "@displayName", TOKENIZABLE | KEYWORD_NAME);
|
||||
|
||||
// All types
|
||||
add(TokenType::INT_TYPE, "int", TOKENIZABLE);
|
||||
|
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,233 @@
|
|||
@source "arm_library.csl"
|
||||
|
||||
@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 (-200, 24)
|
||||
@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
|
||||
}
|
||||
}
|
|
@ -0,0 +1,248 @@
|
|||
|
||||
\\ Version 0.0.1
|
||||
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.comdel"
|
||||
#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;}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
@source "arm_library.csl"
|
||||
|
||||
@schema {
|
||||
@instance arm ARM7tdmi {
|
||||
@position (1179, 326)
|
||||
@attribute _memory memorija
|
||||
}
|
||||
|
||||
@instance memorija Memory64KiB {
|
||||
@position (1148, 521)
|
||||
}
|
||||
|
||||
@instance decoder Decoder {
|
||||
@position (1070, 381)
|
||||
}
|
||||
|
||||
@instance ahb AHB {
|
||||
@position (1027, 465)
|
||||
@size 249
|
||||
}
|
||||
|
||||
@connection (memorija.ahbPin, ahb) {
|
||||
}
|
||||
@connection (arm.ahbPin, ahb) {
|
||||
}
|
||||
@connection (decoder.ahbPin, ahb) {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
|
||||
// Version 0.0.1
|
||||
set load_performs_init;
|
||||
|
||||
#include ".\arm7tdmi.comdel"
|
||||
#include ".\decoder.comdel"
|
||||
#include ".\memory.comdel"
|
||||
|
||||
|
||||
|
||||
component System
|
||||
{
|
||||
clock 100 MHz;
|
||||
//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 --ahb__sel_mem;
|
||||
wire ahb__sel_bridge;
|
||||
wire ahb__sel_dmac;
|
||||
wire busreq = 0;
|
||||
wire grant;
|
||||
|
||||
|
||||
// components --------------------------------------------
|
||||
subcomponent Memory64KiB memorija(addr, rdata, wdata, size, write, ready, sel_mem);
|
||||
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);
|
||||
|
||||
display {
|
||||
component { x: 1179; y: 326; ref: "arm"; }
|
||||
component { x: 1148; y: 521; ref: "memorija"; }
|
||||
component { x: 1070; y: 381; ref: "decoder"; }
|
||||
|
||||
// ahb bus
|
||||
|
||||
rectangle {
|
||||
x: 1027; y: 465;
|
||||
width: 249; height: 20;
|
||||
fill_color: #999999;
|
||||
line_color: #999999;
|
||||
}
|
||||
|
||||
|
||||
path {
|
||||
x:0; y:0;
|
||||
points: ((1153, 521),(-1,-46));
|
||||
}
|
||||
path {
|
||||
x:0; y:0;
|
||||
points: ((1234, 457),(-82,18));
|
||||
}
|
||||
path {
|
||||
x:0; y:0;
|
||||
points: ((1090, 421),(62,54));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
// Version 0.0.1
|
||||
#include "libraries\frisc\vjezba1\FRISC.cdl"
|
||||
#include "libraries\frisc\vjezba1\dma.cdl"
|
||||
#include "libraries\frisc\vjezba1\memory.cdl"
|
||||
|
||||
|
||||
|
@ -23,31 +24,43 @@ component System
|
|||
wire --BACK;
|
||||
|
||||
|
||||
//PIOSabirnica
|
||||
wire<8> PIO_DATA;
|
||||
wire READY;
|
||||
wire STROBE;
|
||||
|
||||
|
||||
//directRam
|
||||
wire INT;
|
||||
|
||||
|
||||
// components --------------------------------------------
|
||||
subcomponent Memorija memorija<false, 1, 65536, 8, 0>(ADR, DATA, READ, WRITE, SIZE, WAIT, *, *, *, INT);
|
||||
subcomponent Memorija memorija<false, 1, 1024, 8, 0>(ADR, DATA, READ, WRITE, SIZE, WAIT, INT, *, *, *);
|
||||
subcomponent FRISC procesor(ADR, DATA, READ, WRITE, SIZE, WAIT, INT0, INT1, INT2, INT3, --IACK, 1, *, INT, *, *, *);
|
||||
subcomponent DMA dma<1024>(ADR, DATA, READ, WRITE, SIZE, WAIT, INT0, --BREQ, --BACK, 0, 0, *, *);
|
||||
|
||||
display {
|
||||
component { x: -377; y: -302; ref: "procesor"; }
|
||||
component { x: -56; y: -80; ref: "memorija"; }
|
||||
component { x: -104; y: -102; ref: "procesor"; }
|
||||
component { x: 39; y: 199; ref: "memorija"; }
|
||||
component { x: -352; y: 13; ref: "dma"; }
|
||||
|
||||
// glavnaSabirnica bus
|
||||
|
||||
rectangle {
|
||||
x: -377; y: -106;
|
||||
x: -106; y: 80;
|
||||
w: 100; h: 20;
|
||||
}
|
||||
|
||||
|
||||
// PIOSabirnica bus
|
||||
|
||||
|
||||
// directRam bus
|
||||
|
||||
|
||||
line {x1:-6; y1:-96; x2:-326; y2:-95;}
|
||||
line {x1:-327; y1:-186; x2:-326; y2:-95;}
|
||||
line {x1:-72; y1:-52; x2:-261; y2:-252;}
|
||||
line {x1:-54; y1:14; x2:-55; y2:90;}
|
||||
line {x1:89; y1:183; x2:-55; y2:90;}
|
||||
line {x1:-236; y1:51; x2:-55; y2:90;}
|
||||
line {x1:23; y1:227; x2:12; y2:-52;}
|
||||
}
|
||||
}
|
|
@ -17,6 +17,7 @@
|
|||
}
|
||||
|
||||
@component FRISC processor {
|
||||
@displayName "Frisc procesor"
|
||||
@instanceName procesor
|
||||
@tooltip "Procesor FRISC, mora postojati jedan"
|
||||
@count (1, 1)
|
||||
|
@ -60,7 +61,7 @@
|
|||
}
|
||||
@pin glavniPin in {
|
||||
@tooltip "pin za spajanje na glavnu sabirnicu"
|
||||
@connection required("COMDEL se ne može stvoriti. FRISC nije spojen na sabirnicu")
|
||||
@connection "COMDEL se ne može stvoriti. FRISC nije spojen na sabirnicu"
|
||||
@display {
|
||||
pin {
|
||||
x: 42; y: 100; w: 16; h:16;
|
||||
|
@ -72,7 +73,6 @@
|
|||
|
||||
@pin memDirect inOut {
|
||||
@tooltip "pin za izravno spajanje na RAM"
|
||||
@connection optional("COMDEL se ne može stvoriti. FRISC nije spojen na sabirnicu")
|
||||
@display {
|
||||
pin {
|
||||
x: 100; y: 42; w: 16; h:16;
|
||||
|
@ -132,6 +132,7 @@
|
|||
}
|
||||
@attribute size int default 8
|
||||
@attribute pocetnaAdresa int default 0 {
|
||||
@displayName "Početna adresa"
|
||||
@popup automatic {
|
||||
@title "Početna adresa memorije"
|
||||
@text "Zadajte početnu adresu memorije"
|
||||
|
@ -181,7 +182,7 @@
|
|||
|
||||
@pin glavniPin inOut {
|
||||
@tooltip "pin za spajanje na glavnu sabirnicu"
|
||||
@connection required("COMDEL se ne može stvoriti. Memorija nije spojena na sabirnicu")
|
||||
@connection "COMDEL se ne može stvoriti. Memorija nije spojena na sabirnicu"
|
||||
@display {
|
||||
/*
|
||||
pin {
|
||||
|
@ -204,7 +205,6 @@
|
|||
|
||||
@pin memDirect inOut {
|
||||
@tooltip "pin za spajanje na procesor"
|
||||
@connection optional("COMDEL se ne može stvoriti. Memorija nije spojena na sabirnicu")
|
||||
@display {
|
||||
/*
|
||||
pin {
|
||||
|
@ -228,12 +228,14 @@
|
|||
}
|
||||
|
||||
@component DMA {
|
||||
@displayName "DMA kontroler"
|
||||
@instanceName dma
|
||||
@tooltip "DMA-kontroler"
|
||||
@count (0,1000)
|
||||
@source "dma.cdl"
|
||||
|
||||
@attribute pocetnaAdresa int default 0 {
|
||||
@displayName "Početna adresa"
|
||||
@popup automatic {
|
||||
@title "Početna adresa DMA-kontrolera"
|
||||
@text "Zadajte početnu adresu DMA-kontrolera"
|
||||
|
@ -276,7 +278,7 @@
|
|||
|
||||
@pin glavniPin in {
|
||||
@tooltip "pin za spajanje na glavnu sabirnicu"
|
||||
@connection required("COMDEL se ne može stvoriti. DMA nije spojena na sabirnicu")
|
||||
@connection "COMDEL se ne može stvoriti. DMA nije spojena na sabirnicu"
|
||||
@display {
|
||||
/*
|
||||
pin {
|
||||
|
@ -298,7 +300,6 @@
|
|||
|
||||
@pin dodatnaPoveznica in {
|
||||
@tooltip "pin za spajanje na pomocnu sabirnicu"
|
||||
@connection optional("COMDEL se ne može stvoriti. DMA nije spojen na nesto!")
|
||||
@display {
|
||||
pin {
|
||||
x: 100; y: 7; w: 16; h: 16;
|
||||
|
@ -310,6 +311,7 @@
|
|||
}
|
||||
|
||||
@bus glavnaSabirnica regular {
|
||||
@displayName "Glavna sabirnica"
|
||||
@instanceName glavnaSabirnica
|
||||
@tooltip "sabirnica za spajanje FRISC a s memorijama i UI/jedinicama"
|
||||
@count (1,1)
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
@source "/home/bbr/Documents/Personal/FER/schema_editor/examples/simplified FRISC model/frisc_library.csl"
|
||||
|
||||
@schema {
|
||||
@instance procesor FRISC {
|
||||
@position (-177, -122)
|
||||
@attribute _memory memorija2
|
||||
}
|
||||
|
||||
@instance procesor FRISC {
|
||||
@position (49, -97)
|
||||
@attribute _memory null
|
||||
}
|
||||
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
@source "/home/bbr/Documents/Personal/FER/schema_editor/examples/simplified FRISC model/frisc_library.csl"
|
||||
|
||||
@schema {
|
||||
@instance procesor FRISC {
|
||||
@position (-464, -314)
|
||||
@attribute _memory null
|
||||
}
|
||||
|
||||
@instance dma DMA {
|
||||
@position (-269, 46)
|
||||
@attribute pocetnaAdresa 0
|
||||
}
|
||||
|
||||
@instance glavnaSabirnica glavnaSabirnica {
|
||||
@position (-579, -160)
|
||||
@size 100
|
||||
}
|
||||
|
||||
@instance PIOSabirnica PIOSabirnica {
|
||||
@position (0, 0)
|
||||
@size 0
|
||||
}
|
||||
|
||||
@connection (dma.glavniPin, glavnaSabirnica) {
|
||||
@attribute interupt INT2
|
||||
}
|
||||
@connection (dma.glavniPin, PIOSabirnica, procesor.glavniPin) {
|
||||
}
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
@source "/home/bbr/Documents/Personal/FER/schema_editor/examples/simplified FRISC model/frisc_library.csl"
|
||||
|
||||
@schema {
|
||||
@instance procesor FRISC {
|
||||
@position (-543, -304)
|
||||
@attribute _memory null
|
||||
}
|
||||
|
||||
@instance glavnaSabirnica glavnaSabirnica {
|
||||
@position (-544, -91)
|
||||
@size 100
|
||||
}
|
||||
|
||||
@connection (procesor.glavniPin, glavnaSabirnica) {
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
@source "/home/bbr/Documents/Personal/FER/schema_editor/examples/simplified FRISC model/frisc_library.csl"
|
||||
@source "frisc_library.csl"
|
||||
|
||||
@schema {
|
||||
@instance procesor FRISC {
|
|
@ -1,19 +1,18 @@
|
|||
#include "mainwindow.h"
|
||||
#include "ui_mainwindow.h"
|
||||
#include "application.h"
|
||||
#include "comdel/display/dialog/error_dialog.h"
|
||||
#include "comdel/display/dialog/success_dialog.h"
|
||||
#include "message_source.h"
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QHBoxLayout>
|
||||
|
||||
#include <comdel/parser/parse_context.h>
|
||||
#include <comdel/parser/parser_util.h>
|
||||
#include <comdel/domain/schema_creator.h>
|
||||
#include <comdel/domain/comdel_validator.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <QPlainTextEdit>
|
||||
#include <comdel/domain/comdel_validator.h>
|
||||
#include <fstream>
|
||||
#include <comdel/domain/comdel_generator.h>
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent)
|
||||
: QMainWindow(parent)
|
||||
|
@ -32,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);
|
||||
|
@ -55,25 +56,25 @@ void MainWindow::setupUi()
|
|||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
layout->addWidget(libraryDisplay);
|
||||
layout->addWidget(schemaParent, 1);
|
||||
|
||||
log = new QPlainTextEdit();
|
||||
log->setFont(QFont("Courier"));
|
||||
log->setReadOnly(false);
|
||||
schemaLayout->addWidget(log);
|
||||
}
|
||||
|
||||
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;
|
||||
log->clear();
|
||||
|
||||
auto librarySource = filename.toStdString();
|
||||
|
||||
auto instance = Application::instance();
|
||||
if(!instance->loadLibrary(librarySource, output)) {
|
||||
log->appendPlainText(QString::fromStdString(output.str()));
|
||||
auto dialog = new display::ErrorDialog(output);
|
||||
dialog->exec();
|
||||
} else {
|
||||
MessageSource::instance()->load(Application::instance()->getLibrary()->getMessages());
|
||||
updateTranslations();
|
||||
}
|
||||
|
||||
libraryDisplay->refreshContent();
|
||||
|
@ -83,10 +84,11 @@ 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;
|
||||
log->clear();
|
||||
|
||||
auto schemaSource = filename.toStdString();
|
||||
|
||||
|
@ -94,7 +96,11 @@ void MainWindow::onLoadSchema() {
|
|||
auto result = instance->loadSchema(schemaSource, output);
|
||||
if(!result.first){
|
||||
formatErrors(result.second, output);
|
||||
log->appendPlainText(QString::fromStdString(output.str()));
|
||||
auto dialog = new display::ErrorDialog(output);
|
||||
dialog->exec();
|
||||
} else {
|
||||
MessageSource::instance()->load(Application::instance()->getLibrary()->getMessages());
|
||||
updateTranslations();
|
||||
}
|
||||
|
||||
libraryDisplay->refreshContent();
|
||||
|
@ -104,10 +110,10 @@ 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()) {
|
||||
log->clear();
|
||||
|
||||
std::ostringstream output;
|
||||
|
||||
if(Application::instance()->generateSchema(output)) {
|
||||
|
@ -115,9 +121,11 @@ void MainWindow::onStoreScheme() {
|
|||
out<<output.str();
|
||||
out.close();
|
||||
|
||||
log->appendPlainText("Uspješno spremljena shema\n");
|
||||
auto dialog = new display::SuccessDialog(MESSAGE("msg_dialog_success_save_schema"));
|
||||
dialog->exec();
|
||||
} else {
|
||||
log->appendPlainText("Greška tijekom spremanja sheme\n");
|
||||
auto dialog = new display::ErrorDialog(output);
|
||||
dialog->exec();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -125,26 +133,27 @@ 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()) {
|
||||
log->clear();
|
||||
|
||||
std::ostringstream output;
|
||||
|
||||
auto validationErrors = Application::instance()->generateComdel(output);
|
||||
|
||||
std::ostringstream buff;
|
||||
formatErrors(validationErrors, buff);
|
||||
log->appendPlainText(QString::fromStdString(buff.str()));
|
||||
std::ostringstream errorOutput;
|
||||
formatErrors(validationErrors, errorOutput);
|
||||
|
||||
if(!Application::hasErrors(validationErrors)) {
|
||||
std::ofstream out(filename.toStdString(), std::ios::out | std::ios::binary);
|
||||
out<<output.str();
|
||||
out.close();
|
||||
|
||||
log->appendPlainText("Uspješno generiranje comdel modela\n");
|
||||
auto dialog = new display::SuccessDialog(MESSAGE("msg_dialog_success_comdel_generation"));
|
||||
dialog->exec();
|
||||
} else {
|
||||
log->appendPlainText("Neuspješno generiranje comdel modela\n");
|
||||
auto dialog = new display::ErrorDialog(errorOutput);
|
||||
dialog->exec();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -152,15 +161,17 @@ void MainWindow::onGenerateComdel() {
|
|||
|
||||
void MainWindow::onValidateSchema(bool /*toggled*/) {
|
||||
|
||||
log->clear();
|
||||
|
||||
auto errors = Application::instance()->validateSchema();
|
||||
|
||||
std::ostringstream buff;
|
||||
formatErrors(errors, buff);
|
||||
|
||||
log->appendPlainText(QString::fromStdString(buff.str()));
|
||||
|
||||
if(Application::hasErrors(errors)) {
|
||||
std::ostringstream buff;
|
||||
formatErrors(errors, buff);
|
||||
auto dialog = new display::ErrorDialog(buff);
|
||||
dialog->exec();
|
||||
} else {
|
||||
auto dialog = new display::SuccessDialog(MESSAGE("msg_dialog_success_validation"));
|
||||
dialog->exec();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::formatErrors(std::vector<domain::ValidationError>& errors, std::ostream& output) {
|
||||
|
@ -184,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"));
|
||||
}
|
||||
|
|
|
@ -40,8 +40,14 @@ private:
|
|||
display::Library *libraryDisplay;
|
||||
display::Schema *schemaDisplay;
|
||||
Ui::MainWindow *ui;
|
||||
QPlainTextEdit *log;
|
||||
|
||||
QAction* loadLibrary;
|
||||
QAction* loadSchema;
|
||||
QAction* saveSchema;
|
||||
QAction* generateComdel;
|
||||
|
||||
static void formatErrors(std::vector<domain::ValidationError>& errors, std::ostream& output);
|
||||
|
||||
void updateTranslations();
|
||||
};
|
||||
#endif // MAIN_WINDOW_H
|
||||
|
|
|
@ -0,0 +1,145 @@
|
|||
//
|
||||
// Created by bbr on 14.06.22..
|
||||
//
|
||||
|
||||
#include "message_source.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
// 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<std::string, std::string> 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<std::string, std::string> 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<std::string, std::string> _messages) {
|
||||
loadDefaults();
|
||||
for (auto &[key, value]: _messages) {
|
||||
messages[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> MessageSource::map(std::map<std::string, domain::Value> values) {
|
||||
std::map<std::string, std::string> parametars;
|
||||
for (auto &[key, value]: values) {
|
||||
parametars[key] = value.string();
|
||||
}
|
||||
return parametars;
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
//
|
||||
// Created by bbr on 14.06.22..
|
||||
//
|
||||
|
||||
#ifndef SCHEMEEDITOR_MESSAGE_SOURCE_H
|
||||
#define SCHEMEEDITOR_MESSAGE_SOURCE_H
|
||||
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#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<std::string, std::string> parametars);
|
||||
std::string replacePlaceholder(std::string message, std::string key, std::string value);
|
||||
|
||||
std::map<std::string, std::string> messages;
|
||||
|
||||
public:
|
||||
static MessageSource *instance();
|
||||
static std::map<std::string, std::string> map(std::map<std::string, domain::Value> values);
|
||||
|
||||
std::string get(const std::string& key);
|
||||
std::string get(const std::string& key, std::map<std::string, std::string> parametars);
|
||||
|
||||
void loadDefaults();
|
||||
void load(std::map<std::string, std::string> 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
|
Loading…
Reference in New Issue