Added message source and arm example

This commit is contained in:
Borna Rajković committed 2022-06-19 20:10:52 +02:00
1 parent eaa115d115
commit d2fc849cc2
38 files changed
+2261 -174

No files matched your search

+57 -26
View File
@@ -5,6 +5,7 @@
#include "application.h"
#include "comdel/display/dialog/single_automatic_dialog.h"
#include "comdel/display/dialog/memory_dialog.h"
#include "message_source.h"
#include <QMenu>
#include <QLine>
@@ -25,7 +26,7 @@ namespace display {
void Component::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) {
QMenu menu;
menu.addAction("Izmjeni ime", [this]() {
menu.addAction(QMESSAGE("msg_dialog_name_update"), [this]() {
std::set<std::string> names;
for(const auto &component: Application::instance()->getSchema()->componentInstances) {
names.insert(component->name);
@@ -45,22 +46,29 @@ namespace display {
bool enabled = attr->attribute.getPopup().has_value();
if(attr->value.getType() == domain::Value::MEMORY_REFERENCE) {
menu.addAction("Izmjeni memoriju", [attr]() {
auto dialog = new MemoryDialog("Izmjeni memoriju", "Izmjeni", attr,
menu.addAction(QMESSAGE("msg_dialog_memory_update"), [attr]() {
auto dialog = new MemoryDialog(MESSAGE("msg_dialog_memory_update"),
MESSAGE("msg_dialog_actions_update"),
attr,
Application::instance()->getSchema()->componentInstances);
dialog->exec();
});
} else {
auto action = menu.addAction(QString::fromStdString("Izmjeni '" + attr->attribute.getDisplayName() + "'"),
[attr]() {
auto dialog = new AttributeDialog("Izmjeni " + attr->attribute.getDisplayName(), "Izmjeni", attr);
dialog->exec();
});
std::map<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();
@@ -75,19 +83,28 @@ namespace display {
auto pinConnections = Application::instance()->getSchema()->getConnections(componentInstance->name, pin.getName());
if(isSingleAutomatic(pinConnections)) {
auto *update = menu.addMenu("Izmjeni");
auto *remove = menu.addMenu("Ukloni");
auto *update = menu.addMenu(QMESSAGE("msg_pin_update"));
auto *remove = menu.addMenu(QMESSAGE("msg_pin_remove"));
for (auto pinConnection: pinConnections) {
// this always must be true as only directConnections can be connected multiple times
if (auto directConnection = dynamic_cast<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("Izmjeni sabirnicu", "Izmjeni", directConnection->attributes);
auto params = MessageSource::instance()->map(
{{"wire1", directConnection->attributes[0].value},
{"wire2", directConnection->attributes[1].value}}
);
update->addAction(QMESSAGE_PARAM("msg_sa_pin_update_title", params),
[directConnection]() {
auto params = MessageSource::instance()->map(
{{"wire1", directConnection->attributes[0].value},
{"wire2", directConnection->attributes[1].value}}
);
auto dialog = new SingleAutomaticDialog(MESSAGE_PARAM("msg_sa_pin_update_title", params),
MESSAGE("msg_pin_update_action"),
directConnection->attributes);
dialog->exec();
});
remove->addAction(QString::fromStdString("Ukloni " + connectionName),
remove->addAction(QMESSAGE_PARAM("msg_sa_pin_remove_title", params),
[this, directConnection]() {
Application::instance()->removeConnection(directConnection);
auto view = dynamic_cast<Schema *>(this->scene()->views()[0]);
@@ -109,12 +126,15 @@ namespace display {
}
for (int i = 0; i < pinConnection->attributes.size(); i++) {
auto *attr = &pinConnection->attributes[i];
menu.addAction(QString::fromStdString("Izmjeni '" + attr->attribute.getDisplayName() + "'"),[attr]() {
auto dialog = new AttributeDialog("Izmjeni '" + attr->attribute.getDisplayName() + "'", "Izmjeni", attr);
dialog->exec();
std::map<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();
@@ -186,7 +206,7 @@ namespace display {
void Bus::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) {
QMenu menu;
menu.addAction("Izmjeni ime", [this]() {
menu.addAction(QMESSAGE("msg_dialog_name_update"), [this]() {
std::set<std::string> names;
for(const auto &component: Application::instance()->getSchema()->busInstances) {
names.insert(component->name);
@@ -201,7 +221,9 @@ namespace display {
setToolTip(QString::fromStdString(busInstance->name + "::" + busInstance->bus.getDisplayName()));
});
menu.addSeparator();
menu.addAction(QString::fromStdString("Ukloni " + this->busInstance->name), [this]() {
std::map<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();
@@ -306,10 +328,19 @@ namespace display {
}
void DirectConnection::updateConnection() {
auto pin1 = connection->instance->component.getPin(
connection->connection.getComponent().pin).getDisplayPin();
auto pin2 = connection->secondInstance->component.getPin(
connection->connection.getSecondComponent()->pin).getDisplayPin();
domain::ui::Pin pin1, pin2;
if(connection->connection.getComponent().component == connection->instance->component.getName()) {
pin1 = connection->instance->component.getPin(
connection->connection.getComponent().pin).getDisplayPin();
pin2 = connection->secondInstance->component.getPin(
connection->connection.getSecondComponent()->pin).getDisplayPin();
} else {
pin1 = connection->instance->component.getPin(
connection->connection.getSecondComponent()->pin).getDisplayPin();
pin2 = connection->secondInstance->component.getPin(
connection->connection.getComponent().pin).getDisplayPin();
}
setLine(connection->instance->position.first + pin1.getConnectionX(),
connection->instance->position.second + pin1.getConnectionY(),
+3 -2
View File
@@ -4,6 +4,7 @@
#include "application.h"
#include "error_dialog.h"
#include "warning_dialog.h"
#include "message_source.h"
namespace display {
@@ -140,11 +141,11 @@ namespace display {
auto *radioLayout = new QHBoxLayout(group);
group->setLayout(radioLayout);
auto isTrue = new QRadioButton("da", group);
auto isTrue = new QRadioButton(QMESSAGE("msg_boolean_true"), group);
connect(isTrue, &QRadioButton::clicked, [this]() {
this->value = domain::Value::fromBool(true);
});
auto isFalse = new QRadioButton("ne", group);
auto isFalse = new QRadioButton(QMESSAGE("msg_boolean_false"), group);
connect(isFalse, &QRadioButton::clicked, [this]() {
this->value = domain::Value::fromBool(false);
});
+2 -2
View File
@@ -6,7 +6,7 @@
namespace display {
ErrorDialog::ErrorDialog(std::vector<domain::ValidationError> errors)
: GenericDialog("Greške", "") {
: GenericDialog("msg_dialog_error_title", std::nullopt, "msg_dialog_error_close") {
auto contentLayout = new QVBoxLayout();
content->setLayout(contentLayout);
@@ -17,7 +17,7 @@ namespace display {
}
ErrorDialog::ErrorDialog(std::ostringstream& errorStream)
: GenericDialog("Greške", "") {
: GenericDialog("msg_dialog_error_title", std::nullopt, "msg_dialog_error_close") {
auto contentLayout = new QVBoxLayout();
content->setLayout(contentLayout);
+12 -6
View File
@@ -1,9 +1,11 @@
#include <QVBoxLayout>
#include "generic_dialog.h"
display::GenericDialog::GenericDialog(std::string title, std::string action) {
#include "message_source.h"
display::GenericDialog::GenericDialog(std::string title, std::optional<std::string> action, std::string cancel) {
setAttribute(Qt::WA_DeleteOnClose);
setWindowTitle(QString::fromStdString(title));
setWindowTitle(QMESSAGE(title));
setLayout(new QVBoxLayout());
content = new QWidget(this);
@@ -14,12 +16,16 @@ display::GenericDialog::GenericDialog(std::string title, std::string action) {
layout()->addWidget(actionWidget);
// if action isn't defined only close button is offered
if(!action.empty()) {
okButton = new QPushButton(QString::fromStdString(action), this);
connect(okButton, &QPushButton::clicked, this, [this](){if(this->onUpdate()) this->accept();});
if(action.has_value()) {
okButton = new QPushButton(QMESSAGE(*action), this);
connect(okButton, &QPushButton::clicked, this, [this](){
if(this->onUpdate()) {
this->accept();
}
});
actionBar->addWidget(okButton);
}
cancelButton = new QPushButton("Odustani", this);
cancelButton = new QPushButton(QMESSAGE(cancel), this);
connect(cancelButton, &QPushButton::clicked, [this]() { reject(); });
actionBar->addWidget(cancelButton);
}
+5 -1
View File
@@ -5,12 +5,16 @@
#include <QWidget>
#include <QPushButton>
#include <optional>
namespace display {
class GenericDialog: public QDialog {
public:
GenericDialog(std::string title, std::string action = "Ažuriraj");
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);
+2 -1
View File
@@ -1,6 +1,7 @@
#include <QVBoxLayout>
#include <QLabel>
#include "memory_dialog.h"
#include "message_source.h"
namespace display {
@@ -35,7 +36,7 @@ namespace display {
for (const auto& entry: memoryInstances) {
combo->addItem(QString::fromStdString(entry));
}
combo->addItem("null");
combo->addItem(QMESSAGE("msg_dialog_memory_default"));
connect(combo, QOverload<int>::of(&QComboBox::currentIndexChanged), [this](int index) {
if(index == memoryInstances.size()) {
+3 -2
View File
@@ -1,15 +1,16 @@
#include <set>
#include "name_dialog.h"
#include "message_source.h"
namespace display {
NameDialog::NameDialog(std::string currentName, std::set<std::string> &names)
: GenericDialog("Izmjeni ime", "Izmjeni"), currentName(currentName), usedNames(names) {
: GenericDialog("msg_dialog_name_update"), currentName(currentName), usedNames(names) {
usedNames.erase(currentName);
auto *contentLayout = new QVBoxLayout();
contentLayout->addWidget(new QLabel("Izmjeni ime", this));
contentLayout->addWidget(new QLabel(QMESSAGE("msg_dialog_name_update"), this));
edit = new QLineEdit(this);
edit->insert(currentName.c_str());
+4 -2
View File
@@ -2,14 +2,16 @@
#include <QLabel>
#include <QPushButton>
#include "success_dialog.h"
#include "message_source.h"
namespace display {
SuccessDialog::SuccessDialog(std::string message, std::string action) {
SuccessDialog::SuccessDialog(std::string message) {
setLayout(new QVBoxLayout());
setWindowTitle(QMESSAGE("msg_dialog_success_title"));
layout()->addWidget(new QLabel(QString::fromStdString(message)));
auto button = new QPushButton(QString::fromStdString(action));
auto button = new QPushButton(QMESSAGE("msg_dialog_actions_ok"));
connect(button, &QPushButton::clicked, [this]() {accept();});
layout()->addWidget(button);
}
+1 -1
View File
@@ -11,7 +11,7 @@ namespace display {
class SuccessDialog: public QDialog {
public:
explicit SuccessDialog(std::string message, std::string action = "Ok");
explicit SuccessDialog(std::string message);
};
} // display
+1 -1
View File
@@ -5,7 +5,7 @@
namespace display {
WarningDialog::WarningDialog(domain::ValidationError error)
: GenericDialog("Upozorenje", "U redu") {
: GenericDialog("msg_dialog_warning_title", "msg_dialog_actions_ok") {
auto contentLayout = new QVBoxLayout();
content->setLayout(contentLayout);
+10 -2
View File
@@ -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();
+3
View File
@@ -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
+21 -8
View File
@@ -8,6 +8,8 @@
#include <QDrag>
#include <QDragEnterEvent>
#include <QMimeData>
#include "message_source.h"
namespace display {
@@ -183,7 +185,7 @@ namespace display {
if (rect.contains(endPoint)) {
auto name = components[pinInstance.component]->getComponentInstance()->component.getName();
auto con = library->getConnection({instance->component.getName(), connection.pin.value().getName()},
auto con = library->getConnection({instance->component.getName(), context.pin->getPin().getName()},
{name, pinInstance.pin});
if (con.has_value()) {
auto busInstance = Application::instance()->addBus(library->getBus(con->getBus()), 0, 0);
@@ -199,12 +201,22 @@ namespace display {
return;
}
auto conInstance = std::make_shared<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],
@@ -276,13 +288,14 @@ namespace display {
domain::InstanceAttribute attribute(attr.getName(), attr.getDefault(), attr);
if(attr.getPopup().has_value() && attr.getPopup()->getType() == domain::Popup::AUTOMATIC) {
if(attr.getDefault().isType(domain::Value::MEMORY_REFERENCE)) {
auto dialog = new MemoryDialog("Postavi memoriju", "Postavi", &attribute, schema->componentInstances);
auto dialog = new MemoryDialog("msg_dialog_memory_set", "msg_dialog_actions_set", &attribute, schema->componentInstances);
if(dialog->exec() == QDialog::Rejected) {
// if any dialog isn't set, whole creation is rejected
return {};
}
} else {
auto dialog = new AttributeDialog("Postavi " + attribute.attribute.getDisplayName(), "Postavi", &attribute);
std::map<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 {};
@@ -301,7 +314,7 @@ namespace display {
instanceAttributes.emplace_back(attr.getName(), attr.getDefault(), attr);
}
auto dialog = new display::SingleAutomaticDialog("Postavi sabirnicu", "Postavi", instanceAttributes);
auto dialog = new display::SingleAutomaticDialog("msg_dialog_sa_pin_set", "msg_dialog_actions_set", instanceAttributes);
if(dialog->exec() == QDialog::Rejected) {
// if dialog is rejected, whole creation is rejected
return {};
+62 -34
View File
@@ -3,6 +3,7 @@
//
#include <set>
#include <QLayout>
#include "comdel_generator.h"
namespace domain {
@@ -148,12 +149,9 @@ namespace domain {
for (auto &bus: schema->busInstances) {
buffer << "\t//" << bus->name << std::endl;
for (auto &wire: bus->bus.getWires()) {
std::string name = wire.getName();
if (usedNames.count(wire.getName()) > 0) {
name = bus->name + "__" + wire.getName();
}
if (wire.isHidden()) {
name = "--" + name;
auto name = (wire.isHidden() ? "--" : "") + wire.getName();
if (usedNames.count(name) > 0) {
name = (wire.isHidden() ? "--" : "") + bus->name + "__" + wire.getName();
}
usedNames.insert(name);
usedMappings.insert(std::make_pair(bus->name + "." + wire.getName(), name));
@@ -203,6 +201,9 @@ namespace domain {
map<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 +251,42 @@ namespace domain {
for (auto &pin: component->component.getPins()) {
if (schema->hasConnection(component->name, pin.getName())) {
auto conn = schema->getConnection(component->name, pin.getName());
auto busConn = dynamic_cast<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 +347,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) {
+32 -47
View File
@@ -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);
}
}
@@ -85,9 +80,8 @@ namespace domain {
if (pin.getConnection().has_value()) {
if (!connectionExists(schema, inst, pin)) {
context.instance = inst.get();
context.attributes["instanceName"] = Value::fromString(inst->name);
auto message = populateMessage(pin.getConnection().value(), context);
errors.emplace_back(Action::ERROR, message);
auto message = MESSAGE_PARAM(pin.getConnection().value(), context.map());
errors.emplace_back(context.instance, nullptr, Action::ERROR, message);
}
}
}
@@ -147,7 +141,7 @@ namespace domain {
ruleContext.function = validators;
auto action = rule.evaluate(ruleContext);
if (action) {
std::string message = this->populateMessage(action->getMessage(), context);
auto message = MESSAGE_PARAM(action->getMessage(), context.map());
return ValidationError{context.instance, context.attribute, action->getType(), message};
}
return nullopt;
@@ -172,7 +166,7 @@ namespace domain {
if(memoryReference != nullopt) {
if(memoryInstances.count(*memoryReference) == 0) {
context.attributes["memoryReference"] = domain::Value::fromString(memoryReference.value());
auto message = populateMessage("Ne postoji memorijska komponenta '{memoryReference}'", context);
auto message = MESSAGE_PARAM("msg_validators_memory_not_found", context.map());
errors.emplace_back(component.get(), nullptr, Action::ERROR, message);
}
}
@@ -191,9 +185,8 @@ namespace domain {
for(auto& component: schema.componentInstances) {
if(names.find(component->name) != names.end()) {
context.attributes["componentName"] = Value::fromString(component->name);
auto message = populateMessage(
"Pronađeno više instanci sa imenom '{componentName}'", context);
context.instance = component.get();
auto message = MESSAGE_PARAM("msg_validators_duplicates_found", context.map());
errors.emplace_back(Action::ERROR, message);
}
names.insert(component->name);
@@ -201,26 +194,6 @@ namespace domain {
return errors;
}
std::string ComdelValidator::populateMessage(string source, ValidationContext context) {
for (auto &[key, value]: context.attributes) {
source = replacePlaceholder(source, key, value);
}
return source;
}
string ComdelValidator::replacePlaceholder(string source, string key, Value value) {
key = "{" + key + "}";
auto placeholderValue = value.string();
auto found = source.find(key);
while (found != string::npos) {
source.replace(found, key.length(), placeholderValue);
found = source.find(key);
}
return source;
}
bool ComdelValidator::connectionExists(Schema &schema, shared_ptr<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;
}
}
+3 -6
View File
@@ -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);
};
+19
View File
@@ -26,4 +26,23 @@ namespace domain {
Connection connection)
: ConnectionInstance(instance, attributes, connection), secondInstance(secondInstance), bus(bus) {}
int DirectConnectionInstance::getSelected(ConnectionComponent conn) {
if(this->instance->name == conn.component) {
auto selected = attributes[0].value.asString();
for(int i=0; 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
+2
View File
@@ -41,6 +41,8 @@ namespace domain {
DirectConnectionInstance(ComponentInstance *instance, ComponentInstance *secondsInstance,
std::vector<InstanceAttribute> attributes, BusInstance *bus, Connection connection);
int getSelected(ConnectionComponent connection);
};
+16
View File
@@ -51,6 +51,21 @@ namespace domain {
buffer << "\t\t}\n\n";
}
void ui::Ellipse::render(QGraphicsItemGroup *group) {
auto ellipse = new QGraphicsEllipseItem(x, y, w, h);
ellipse->setPen(QPen(config.lineColor));
ellipse->setBrush(QBrush(config.fillColor));
group->addToGroup(ellipse);
}
void ui::Ellipse::comdel(std::ostream &buffer, int x, int y) {
buffer << "\t\tellipse {\n";
buffer << "\t\t\tx: " << (this->x + x) << "; y: " << (this->y + y) << ";\n";
buffer << "\t\t\tw: " << w << "; h: " << h << ";\n";
buffer << "\t\t}\n\n";
}
void ui::Line::render(QGraphicsItemGroup *group) {
auto line = new QGraphicsLineItem(x1, y1, x2, y2);
line->setPen(QPen(config.lineColor));
@@ -205,6 +220,7 @@ namespace domain {
if (pin) pin->render(group);
if (bus) bus->render(group, size);
if (text) text->render(group, context);
if (ellipse) ellipse->render(group);
}
void ui::Item::comdel(std::ostream &buffer, int x, int y, int size) {
+16
View File
@@ -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);
+8 -13
View File
@@ -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
+13 -1
View File
@@ -345,10 +345,12 @@ namespace domain {
if (!node.second.has_value()) {
errors.emplace_back(node.span, "missing second component");
return nullopt;
}
ConnectionComponent second{node.second->component.value, node.second->pin.value};
auto firstComponentInstance = getComponentPin(first.component, first.pin);
if (!firstComponentInstance) {
errors.emplace_back(node.span, "pin does not exist");
@@ -405,7 +407,10 @@ namespace domain {
}
}
if(node.secondWires->empty()) {
errors.emplace_back(node.span, "missing second @wires definition");
return nullopt;
}
std::vector<Value> secondWires;
for (auto &secondWire: *node.secondWires) {
if (secondWire.is(ValueNode::NIL)) {
@@ -654,6 +659,13 @@ namespace domain {
h = readInt(errors, item, "h");
text = readString(errors, item, "text");
displayItem.text = ui::Text(x, y, w, h, text, color);
} else if (type == "ellipse") {
long long int x, y, w, h;
x = readInt(errors, item, "x");
y = readInt(errors, item, "y");
w = readInt(errors, item, "w");
h = readInt(errors, item, "h");
displayItem.ellipse = ui::Ellipse(x, y, w, h, {lineColor, fillColor});
} else if (type == "rect") {
long long int x, y, w, h;
x = readInt(errors, item, "x");
+8 -4
View File
@@ -92,29 +92,33 @@ namespace domain {
void Value::setInt(long long value) {
if (isType(Value::INT)) {
this->intValue = value;
} else {
throw std::exception();
}
throw std::exception();
}
void Value::setString(std::string value) {
if (isType(Value::STRING)) {
this->stringValue = value;
} else {
throw std::exception();
}
throw std::exception();
}
void Value::setBool(bool value) {
if (isType(Value::BOOL)) {
this->boolValue = value;
} else {
throw std::exception();
}
throw std::exception();
}
void Value::setReference(std::string value) {
if (isType(Value::WIRE_REFERENCE)) {
this->reference = value;
} else {
throw std::exception();
}
throw std::exception();
}