Compare commits
	
		
			No commits in common. "master" and "feature/component_display_configuration" have entirely different histories.
		
	
	
		
			master
			...
			feature/co
		
	
		
| @ -37,5 +37,5 @@ add_executable(SchemeEditor | |||||||
|         comdel/parser/comdel_lexer.cpp |         comdel/parser/comdel_lexer.cpp | ||||||
|   main.cpp |   main.cpp | ||||||
|   mainwindow.ui |   mainwindow.ui | ||||||
|         comdel/domain/comdel_validator.cpp comdel/domain/comdel_validator.h comdel/display/dialog/attribute_dialog.cpp comdel/display/dialog/attribute_dialog.h comdel/display/dialog/name_dialog.cpp comdel/display/dialog/name_dialog.h comdel/domain/comdel_generator.cpp comdel/domain/comdel_generator.h comdel/display/library_list.cpp comdel/display/library_list.h application.cpp application.h comdel/display/dialog/single_automatic_dialog.cpp comdel/display/dialog/single_automatic_dialog.h comdel/parser/color.h comdel/display/dialog/generic_dialog.cpp comdel/display/dialog/generic_dialog.h comdel/display/dialog/warning_dialog.cpp comdel/display/dialog/warning_dialog.h comdel/display/dialog/error_dialog.cpp comdel/display/dialog/error_dialog.h comdel/display/dialog/memory_dialog.cpp comdel/display/dialog/memory_dialog.h comdel/display/dialog/success_dialog.cpp comdel/display/dialog/success_dialog.h message_source.cpp message_source.h) |         comdel/domain/comdel_validator.cpp comdel/domain/comdel_validator.h comdel/display/attribute_dialog.cpp comdel/display/attribute_dialog.h comdel/display/name_dialog.cpp comdel/display/name_dialog.h comdel/domain/comdel_generator.cpp comdel/domain/comdel_generator.h comdel/display/library_list.cpp comdel/display/library_list.h application.cpp application.h comdel/display/single_automatic_dialog.cpp comdel/display/single_automatic_dialog.h comdel/parser/color.cpp comdel/parser/color.h) | ||||||
| target_link_libraries(SchemeEditor Qt5::Core Qt5::Gui Qt5::Widgets) | target_link_libraries(SchemeEditor Qt5::Core Qt5::Gui Qt5::Widgets) | ||||||
|  | |||||||
| @ -9,18 +9,13 @@ CONFIG += c++17 | |||||||
| #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0 | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0 | ||||||
| 
 | 
 | ||||||
| SOURCES += \ | SOURCES += \ | ||||||
|     comdel/display/dialog/attribute_dialog.cpp \ |     comdel/display/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/component_display.cpp \ | ||||||
|     comdel/display/library_display.cpp \ |     comdel/display/library_display.cpp \ | ||||||
|     comdel/display/library_list.cpp \ |     comdel/display/library_list.cpp \ | ||||||
|  |     comdel/display/name_dialog.cpp \ | ||||||
|     comdel/display/schema_display.cpp \ |     comdel/display/schema_display.cpp \ | ||||||
|  |     comdel/display/single_automatic_dialog.cpp \ | ||||||
|     comdel/domain/address_space.cpp \ |     comdel/domain/address_space.cpp \ | ||||||
|     comdel/domain/attribute.cpp \ |     comdel/domain/attribute.cpp \ | ||||||
|     comdel/domain/bus.cpp \ |     comdel/domain/bus.cpp \ | ||||||
| @ -49,22 +44,16 @@ SOURCES += \ | |||||||
|     comdel/parser/tokens_type.cpp \ |     comdel/parser/tokens_type.cpp \ | ||||||
|     application.cpp \ |     application.cpp \ | ||||||
|     main.cpp \ |     main.cpp \ | ||||||
|     message_source.cpp \ |  | ||||||
|     mainwindow.cpp |     mainwindow.cpp | ||||||
| 
 | 
 | ||||||
| HEADERS += \ | HEADERS += \ | ||||||
|     comdel/display/dialog/attribute_dialog.h \ |     comdel/display/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/component_display.h \ | ||||||
|     comdel/display/library_display.h \ |     comdel/display/library_display.h \ | ||||||
|     comdel/display/library_list.h \ |     comdel/display/library_list.h \ | ||||||
|  |     comdel/display/name_dialog.h \ | ||||||
|     comdel/display/schema_display.h \ |     comdel/display/schema_display.h \ | ||||||
|  |     comdel/display/single_automatic_dialog.h \ | ||||||
|     comdel/domain/address_space.h \ |     comdel/domain/address_space.h \ | ||||||
|     comdel/domain/attribute.h \ |     comdel/domain/attribute.h \ | ||||||
|     comdel/domain/bus.h \ |     comdel/domain/bus.h \ | ||||||
| @ -94,7 +83,6 @@ HEADERS += \ | |||||||
|     comdel/parser/source_error.h \ |     comdel/parser/source_error.h \ | ||||||
|     comdel/parser/token.h \ |     comdel/parser/token.h \ | ||||||
|     comdel/parser/tokens_type.h \ |     comdel/parser/tokens_type.h \ | ||||||
|     message_source.h \ |  | ||||||
|     mainwindow.h |     mainwindow.h | ||||||
| 
 | 
 | ||||||
| FORMS += \ | FORMS += \ | ||||||
|  | |||||||
| @ -90,7 +90,7 @@ std::pair<bool, std::vector<domain::ValidationError>> Application::loadSchema(st | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|     } else { |     } else { | ||||||
|         errorOutput << "Failed schema library" << std::endl; |         errorOutput << "Failed parsing library" << std::endl; | ||||||
|         return {false, errors}; |         return {false, errors}; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										283
									
								
								comdel/display/attribute_dialog.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										283
									
								
								comdel/display/attribute_dialog.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,283 @@ | |||||||
|  | //
 | ||||||
|  | // 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); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										89
									
								
								comdel/display/attribute_dialog.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								comdel/display/attribute_dialog.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,89 @@ | |||||||
|  | #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,11 +1,9 @@ | |||||||
| #include "component_display.h" | #include "component_display.h" | ||||||
| #include "comdel/display/dialog/attribute_dialog.h" | #include "attribute_dialog.h" | ||||||
| #include "comdel/display/dialog/name_dialog.h" | #include "name_dialog.h" | ||||||
| #include "mainwindow.h" | #include "mainwindow.h" | ||||||
| #include "application.h" | #include "application.h" | ||||||
| #include "comdel/display/dialog/single_automatic_dialog.h" | #include "single_automatic_dialog.h" | ||||||
| #include "comdel/display/dialog/memory_dialog.h" |  | ||||||
| #include "message_source.h" |  | ||||||
| 
 | 
 | ||||||
| #include <QMenu> | #include <QMenu> | ||||||
| #include <QLine> | #include <QLine> | ||||||
| @ -20,13 +18,13 @@ namespace display { | |||||||
| 
 | 
 | ||||||
|     Component::Component(const std::shared_ptr<domain::ComponentInstance> &instance): instance(instance) { |     Component::Component(const std::shared_ptr<domain::ComponentInstance> &instance): instance(instance) { | ||||||
|         setFlag(ItemSendsGeometryChanges, true); |         setFlag(ItemSendsGeometryChanges, true); | ||||||
|         setToolTip(QString::fromStdString(instance->name + "::" + instance->component.getDisplayName())); |         setToolTip(QString::fromStdString(instance->name + "::" + instance->component.getName())); | ||||||
|         instance->component.getDisplay().render(this, domain::ui::DisplayContext(instance.get())); |         instance->component.getDisplay().render(this, domain::ui::DisplayContext(instance.get())); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void Component::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { |     void Component::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { | ||||||
|         QMenu menu; |         QMenu menu; | ||||||
|         menu.addAction(QMESSAGE("msg_dialog_name_update"), [this]() { |         menu.addAction("Izmjeni ime", [this]() { | ||||||
|             std::set<std::string> names; |             std::set<std::string> names; | ||||||
|             for(const auto &component: Application::instance()->getSchema()->componentInstances) { |             for(const auto &component: Application::instance()->getSchema()->componentInstances) { | ||||||
|                 names.insert(component->name); |                 names.insert(component->name); | ||||||
| @ -38,7 +36,7 @@ namespace display { | |||||||
|             auto newName = dialog->getName(); |             auto newName = dialog->getName(); | ||||||
| 
 | 
 | ||||||
|             Application::instance()->renameComponent(currentName, newName); |             Application::instance()->renameComponent(currentName, newName); | ||||||
|             setToolTip(QString::fromStdString(instance->name + "::" + instance->component.getDisplayName())); |             setToolTip(QString::fromStdString(instance->name + "::" + instance->component.getName())); | ||||||
|         }); |         }); | ||||||
|         menu.addSeparator(); |         menu.addSeparator(); | ||||||
|         for (int i = 0; i < this->instance->attributes.size(); i++) { |         for (int i = 0; i < this->instance->attributes.size(); i++) { | ||||||
| @ -46,29 +44,22 @@ namespace display { | |||||||
|             bool enabled = attr->attribute.getPopup().has_value(); |             bool enabled = attr->attribute.getPopup().has_value(); | ||||||
| 
 | 
 | ||||||
|             if(attr->value.getType() == domain::Value::MEMORY_REFERENCE) { |             if(attr->value.getType() == domain::Value::MEMORY_REFERENCE) { | ||||||
|                 menu.addAction(QMESSAGE("msg_dialog_memory_update"), [attr]() { |                 menu.addAction("Izmjeni memoriju", [attr]() { | ||||||
|                     auto dialog = new MemoryDialog(MESSAGE("msg_dialog_memory_update"), |                     auto dialog = new MemoryDialog(attr, | ||||||
|                                                    MESSAGE("msg_dialog_actions_update"), |  | ||||||
|                                                    attr, |  | ||||||
|                                                    Application::instance()->getSchema()->componentInstances); |                                                    Application::instance()->getSchema()->componentInstances); | ||||||
|                     dialog->exec(); |                     dialog->exec(); | ||||||
|                 }); |                 }); | ||||||
|             } else { |             } else { | ||||||
|                 std::map<std::string, std::string> params = {{"attribute", attr->attribute.getDisplayName()}}; |                 auto action = menu.addAction(QString::fromStdString("Izmjeni '" + attr->name + "'"), | ||||||
|                 auto action = menu.addAction(QMESSAGE_PARAM("msg_dialog_attribute_update", params), |                                              [attr]() { | ||||||
|                     [attr]() { |                                                 auto dialog = new AttributeDialog(attr); | ||||||
|                         std::map<std::string, std::string> params = {{"attribute", attr->attribute.getDisplayName()}}; |                                                 dialog->exec(); | ||||||
|                         auto dialog = new AttributeDialog(MESSAGE_PARAM("msg_dialog_attribute_update", params), |                                              }); | ||||||
|                                                           "msg_dialog_actions_update", |  | ||||||
|                                                           attr); |  | ||||||
|                         dialog->exec(); |  | ||||||
|                 }); |  | ||||||
|                 action->setEnabled(enabled); |                 action->setEnabled(enabled); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         menu.addSeparator(); |         menu.addSeparator(); | ||||||
|         std::map<std::string, std::string> params = {{"name", instance->name}}; |         menu.addAction(QString::fromStdString("Ukloni " + this->instance->name), [this]() { | ||||||
|         menu.addAction(QMESSAGE_PARAM("msg_dialog_actions_remove_named", params), [this]() { |  | ||||||
|             Application::instance()->removeComponent(this->instance->name); |             Application::instance()->removeComponent(this->instance->name); | ||||||
|             auto view = dynamic_cast<Schema *>(this->scene()->views()[0]); |             auto view = dynamic_cast<Schema *>(this->scene()->views()[0]); | ||||||
|             view->refreshContent(); |             view->refreshContent(); | ||||||
| @ -83,28 +74,19 @@ namespace display { | |||||||
|         auto pinConnections = Application::instance()->getSchema()->getConnections(componentInstance->name, pin.getName()); |         auto pinConnections = Application::instance()->getSchema()->getConnections(componentInstance->name, pin.getName()); | ||||||
| 
 | 
 | ||||||
|         if(isSingleAutomatic(pinConnections)) { |         if(isSingleAutomatic(pinConnections)) { | ||||||
|             auto *update = menu.addMenu(QMESSAGE("msg_pin_update")); |             auto *update = menu.addMenu("Izmjeni"); | ||||||
|             auto *remove = menu.addMenu(QMESSAGE("msg_pin_remove")); |             auto *remove = menu.addMenu("Ukloni"); | ||||||
|             for (auto pinConnection: pinConnections) { |             for (auto pinConnection: pinConnections) { | ||||||
|                 // this always must be true as only directConnections can be connected multiple times
 |                 // this always must be true as only directConnections can be connected multiple times
 | ||||||
|                 if (auto directConnection = dynamic_cast<domain::DirectConnectionInstance *>(pinConnection)) { |                 if (auto directConnection = dynamic_cast<domain::DirectConnectionInstance *>(pinConnection)) { | ||||||
|                     if (directConnection->bus->bus.getType() == domain::Bus::SINGLE_AUTOMATIC) { |                     if (directConnection->bus->bus.getType() == domain::Bus::SINGLE_AUTOMATIC) { | ||||||
|                         auto params = MessageSource::instance()->map( |                         auto connectionName = directConnection->attributes[0].value.stringify() + "-" + | ||||||
|                                 {{"wire1", directConnection->attributes[0].value}, |                                               directConnection->attributes[1].value.stringify(); | ||||||
|                                  {"wire2", directConnection->attributes[1].value}} |                         update->addAction(QString::fromStdString("Izmjeni " + connectionName), [directConnection]() { | ||||||
|                         ); |                             auto dialog = new SingleAutomaticDialog(directConnection->attributes); | ||||||
|                         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(); |                             dialog->exec(); | ||||||
|                         }); |                         }); | ||||||
|                         remove->addAction(QMESSAGE_PARAM("msg_sa_pin_remove_title", params), |                         remove->addAction(QString::fromStdString("Ukloni " + connectionName), | ||||||
|                                           [this, directConnection]() { |                                           [this, directConnection]() { | ||||||
|                                               Application::instance()->removeConnection(directConnection); |                                               Application::instance()->removeConnection(directConnection); | ||||||
|                                               auto view = dynamic_cast<Schema *>(this->scene()->views()[0]); |                                               auto view = dynamic_cast<Schema *>(this->scene()->views()[0]); | ||||||
| @ -126,15 +108,12 @@ namespace display { | |||||||
|             } |             } | ||||||
|             for (int i = 0; i < pinConnection->attributes.size(); i++) { |             for (int i = 0; i < pinConnection->attributes.size(); i++) { | ||||||
|                 auto *attr = &pinConnection->attributes[i]; |                 auto *attr = &pinConnection->attributes[i]; | ||||||
|                 std::map<std::string, std::string> params = {{"name", attr->attribute.getDisplayName()}}; |                 menu.addAction(QString::fromStdString("Izmjeni '" + attr->name + "'"),[attr]() { | ||||||
|                 menu.addAction(QMESSAGE_PARAM("msg_dialog_actions_update_named", params), |                     auto dialog = new AttributeDialog(attr); | ||||||
|                                [attr]() { |                     dialog->exec(); | ||||||
|                                    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(QMESSAGE("msg_pin_remove_action"), [this, pinConnection]() { |             menu.addAction("Ukloni poveznicu", [this, pinConnection]() { | ||||||
|                 Application::instance()->removeConnection(pinConnection); |                 Application::instance()->removeConnection(pinConnection); | ||||||
|                 auto view = dynamic_cast<Schema *>(this->scene()->views()[0]); |                 auto view = dynamic_cast<Schema *>(this->scene()->views()[0]); | ||||||
|                 view->refreshContent(); |                 view->refreshContent(); | ||||||
| @ -206,7 +185,7 @@ namespace display { | |||||||
| 
 | 
 | ||||||
|     void Bus::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { |     void Bus::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { | ||||||
|         QMenu menu; |         QMenu menu; | ||||||
|         menu.addAction(QMESSAGE("msg_dialog_name_update"), [this]() { |         menu.addAction("Izmjeni ime", [this]() { | ||||||
|             std::set<std::string> names; |             std::set<std::string> names; | ||||||
|             for(const auto &component: Application::instance()->getSchema()->busInstances) { |             for(const auto &component: Application::instance()->getSchema()->busInstances) { | ||||||
|                 names.insert(component->name); |                 names.insert(component->name); | ||||||
| @ -218,12 +197,10 @@ namespace display { | |||||||
|             auto newName = dialog->getName(); |             auto newName = dialog->getName(); | ||||||
| 
 | 
 | ||||||
|             Application::instance()->renameBus(currentName, newName); |             Application::instance()->renameBus(currentName, newName); | ||||||
|             setToolTip(QString::fromStdString(busInstance->name + "::" + busInstance->bus.getDisplayName())); |             setToolTip(QString::fromStdString(busInstance->name + "::" + busInstance->bus.getName())); | ||||||
|         }); |         }); | ||||||
|         menu.addSeparator(); |         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); |             Application::instance()->removeBus(this->busInstance->name); | ||||||
|             auto view = dynamic_cast<Schema *>(this->scene()->views()[0]); |             auto view = dynamic_cast<Schema *>(this->scene()->views()[0]); | ||||||
|             view->refreshContent(); |             view->refreshContent(); | ||||||
| @ -328,19 +305,10 @@ namespace display { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void DirectConnection::updateConnection() { |     void DirectConnection::updateConnection() { | ||||||
|         domain::ui::Pin pin1, pin2; |         auto pin1 = connection->instance->component.getPin( | ||||||
|         if(connection->connection.getComponent().component == connection->instance->component.getName()) { |                 connection->connection.getComponent().pin).getDisplayPin(); | ||||||
|             pin1 = connection->instance->component.getPin( |         auto pin2 = connection->secondInstance->component.getPin( | ||||||
|                     connection->connection.getComponent().pin).getDisplayPin(); |                 connection->connection.getSecondComponent()->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(), |         setLine(connection->instance->position.first + pin1.getConnectionX(), | ||||||
|                 connection->instance->position.second + pin1.getConnectionY(), |                 connection->instance->position.second + pin1.getConnectionY(), | ||||||
|  | |||||||
| @ -1,182 +0,0 @@ | |||||||
| #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; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -1,47 +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" |  | ||||||
| #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
 |  | ||||||
| @ -1,34 +0,0 @@ | |||||||
| #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
 |  | ||||||
| @ -1,22 +0,0 @@ | |||||||
| #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
 |  | ||||||
| @ -1,35 +0,0 @@ | |||||||
| #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); |  | ||||||
| } |  | ||||||
| @ -1,33 +0,0 @@ | |||||||
| #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
 |  | ||||||
| @ -1,60 +0,0 @@ | |||||||
| #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
 |  | ||||||
| @ -1,33 +0,0 @@ | |||||||
| #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
 |  | ||||||
| @ -1,40 +0,0 @@ | |||||||
| #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; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -1,19 +0,0 @@ | |||||||
| #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
 |  | ||||||
| @ -1,19 +0,0 @@ | |||||||
| //
 |  | ||||||
| // 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
 |  | ||||||
| @ -1,16 +0,0 @@ | |||||||
| #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
 |  | ||||||
| @ -1,20 +0,0 @@ | |||||||
| #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,5 +1,4 @@ | |||||||
| #include "library_display.h" | #include "library_display.h" | ||||||
| #include "message_source.h" |  | ||||||
| 
 | 
 | ||||||
| #include <QLabel> | #include <QLabel> | ||||||
| #include <QListWidget> | #include <QListWidget> | ||||||
| @ -16,23 +15,16 @@ namespace display { | |||||||
|         busList = new LibraryList(this); |         busList = new LibraryList(this); | ||||||
| 
 | 
 | ||||||
|         layout->setContentsMargins(4, 4, 4, 4); |         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->addWidget(componentList, 1); | ||||||
|         layout->addSpacing(8); |         layout->addSpacing(8); | ||||||
|         layout->addWidget(busLabel); |         layout->addWidget(new QLabel("Sabirnice:")); | ||||||
|         layout->addWidget(busList, 1); |         layout->addWidget(busList, 1); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void Library::refreshContent() { |     void Library::refreshContent() { | ||||||
|         library = Application::instance()->getLibrary(); |         library = Application::instance()->getLibrary(); | ||||||
| 
 | 
 | ||||||
|         componentsLabel->setText(QMESSAGE("msg_sidebar_components")); |  | ||||||
|         busLabel->setText(QMESSAGE("msg_sidebar_busses")); |  | ||||||
| 
 |  | ||||||
|         componentList->clear(); |         componentList->clear(); | ||||||
|         busList->clear(); |         busList->clear(); | ||||||
| 
 | 
 | ||||||
| @ -41,7 +33,7 @@ namespace display { | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         for (auto &component: library->getComponents()) { |         for (auto &component: library->getComponents()) { | ||||||
|             auto item = new LibraryListItem{component.getDisplayName(), "comdel/component", component.getName(), |             auto item = new LibraryListItem{component.getName(), "comdel/component", component.getName(), | ||||||
|                                             componentList}; |                                             componentList}; | ||||||
|             item->setToolTip(QString::fromStdString(component.getTooltip())); |             item->setToolTip(QString::fromStdString(component.getTooltip())); | ||||||
|             componentList->addItem(item); |             componentList->addItem(item); | ||||||
| @ -49,7 +41,7 @@ namespace display { | |||||||
| 
 | 
 | ||||||
|         for (auto &bus: library->getBuses()) { |         for (auto &bus: library->getBuses()) { | ||||||
|             if (bus.getType() == domain::Bus::REGULAR) { |             if (bus.getType() == domain::Bus::REGULAR) { | ||||||
|                 auto item = new LibraryListItem{bus.getDisplayName(), "comdel/bus", bus.getName(), busList}; |                 auto item = new LibraryListItem{bus.getName(), "comdel/bus", bus.getName(), busList}; | ||||||
|                 item->setToolTip(QString::fromStdString(bus.getTooltip())); |                 item->setToolTip(QString::fromStdString(bus.getTooltip())); | ||||||
|                 busList->addItem(item); |                 busList->addItem(item); | ||||||
|             } |             } | ||||||
|  | |||||||
| @ -5,7 +5,6 @@ | |||||||
| #include <QWidget> | #include <QWidget> | ||||||
| 
 | 
 | ||||||
| #include <comdel/domain/library.h> | #include <comdel/domain/library.h> | ||||||
| #include <QLabel> |  | ||||||
| #include "library_list.h" | #include "library_list.h" | ||||||
| 
 | 
 | ||||||
| namespace display { | namespace display { | ||||||
| @ -22,8 +21,6 @@ namespace display { | |||||||
|         LibraryList *componentList; |         LibraryList *componentList; | ||||||
|         LibraryList *busList; |         LibraryList *busList; | ||||||
| 
 | 
 | ||||||
|         QLabel *componentsLabel; |  | ||||||
|         QLabel *busLabel; |  | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
| } // namespace display
 | } // namespace display
 | ||||||
|  | |||||||
							
								
								
									
										50
									
								
								comdel/display/name_dialog.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								comdel/display/name_dialog.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,50 @@ | |||||||
|  | //
 | ||||||
|  | // 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; | ||||||
|  | } | ||||||
| @ -9,29 +9,25 @@ | |||||||
| 
 | 
 | ||||||
| #include <set> | #include <set> | ||||||
| 
 | 
 | ||||||
| #include "comdel/domain/instance.h" | #include <comdel/domain/instance.h> | ||||||
| #include "generic_dialog.h" |  | ||||||
| 
 | 
 | ||||||
| namespace display { | namespace display { | ||||||
| 
 | 
 | ||||||
|     class NameDialog : public GenericDialog { |     class NameDialog : public QDialog { | ||||||
|  | 
 | ||||||
|  |         std::set<std::string> usedNames; | ||||||
|  |         QLineEdit *edit = nullptr; | ||||||
|  |         std::string currentName; | ||||||
|  |         QPushButton *button; | ||||||
| 
 | 
 | ||||||
|     public: |     public: | ||||||
|         NameDialog(std::string currentName, std::set<std::string>& names); |         NameDialog(std::string currentName, std::set<std::string>& names); | ||||||
| 
 | 
 | ||||||
|         std::string getName(); |         std::string getName(); | ||||||
| 
 | 
 | ||||||
|     protected: |  | ||||||
|         bool onUpdate() override; |  | ||||||
| 
 |  | ||||||
|     public slots: |     public slots: | ||||||
|         void onNameUpdate(const QString& text); |         void onNameUpdate(const QString& text); | ||||||
| 
 |         void onNameChange(); | ||||||
|     private: |  | ||||||
|         std::set<std::string> usedNames; |  | ||||||
|         QLineEdit *edit = nullptr; |  | ||||||
|         std::string currentName; |  | ||||||
| 
 |  | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
| @ -1,15 +1,12 @@ | |||||||
| #include "component_display.h" | #include "component_display.h" | ||||||
| #include "schema_display.h" | #include "schema_display.h" | ||||||
| #include "application.h" | #include "application.h" | ||||||
| #include "comdel/display/dialog/attribute_dialog.h" | #include "attribute_dialog.h" | ||||||
| #include "comdel/display/dialog/single_automatic_dialog.h" | #include "single_automatic_dialog.h" | ||||||
| #include "comdel/display/dialog/memory_dialog.h" |  | ||||||
| 
 | 
 | ||||||
| #include <QDrag> | #include <QDrag> | ||||||
| #include <QDragEnterEvent> | #include <QDragEnterEvent> | ||||||
| #include <QMimeData> | #include <QMimeData> | ||||||
| #include "message_source.h" |  | ||||||
| 
 |  | ||||||
| 
 | 
 | ||||||
| namespace display { | namespace display { | ||||||
| 
 | 
 | ||||||
| @ -185,7 +182,7 @@ namespace display { | |||||||
| 
 | 
 | ||||||
|             if (rect.contains(endPoint)) { |             if (rect.contains(endPoint)) { | ||||||
|                 auto name = components[pinInstance.component]->getComponentInstance()->component.getName(); |                 auto name = components[pinInstance.component]->getComponentInstance()->component.getName(); | ||||||
|                 auto con = library->getConnection({instance->component.getName(), context.pin->getPin().getName()}, |                 auto con = library->getConnection({instance->component.getName(), connection.pin.value().getName()}, | ||||||
|                                                   {name, pinInstance.pin}); |                                                   {name, pinInstance.pin}); | ||||||
|                 if (con.has_value()) { |                 if (con.has_value()) { | ||||||
|                     auto busInstance = Application::instance()->addBus(library->getBus(con->getBus()), 0, 0); |                     auto busInstance = Application::instance()->addBus(library->getBus(con->getBus()), 0, 0); | ||||||
| @ -201,22 +198,12 @@ namespace display { | |||||||
|                         return; |                         return; | ||||||
|                     } |                     } | ||||||
| 
 | 
 | ||||||
|                     std::shared_ptr<domain::DirectConnectionInstance> conInstance = nullptr; |                     auto conInstance = std::make_shared<domain::DirectConnectionInstance>(instance, | ||||||
|                     if(con->getComponent() == domain::ConnectionComponent{instance->component.getName(), context.pin->getPin().getName()}) { |                                                                                           components[pinInstance.component]->getComponentInstance().get(), | ||||||
|                         conInstance = std::make_shared<domain::DirectConnectionInstance>(instance, |                                                                                           attributes, busInstance.get(), | ||||||
|                                                                            components[pinInstance.component]->getComponentInstance().get(), |                                                                                           *con); | ||||||
|                                                                            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); |                     schema->connections.push_back(conInstance); | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|                     if (conInstance != nullptr) { |                     if (conInstance != nullptr) { | ||||||
|                         auto c = new display::DirectConnection(conInstance.get(), |                         auto c = new display::DirectConnection(conInstance.get(), | ||||||
|                                                                components[conInstance->instance->name], |                                                                components[conInstance->instance->name], | ||||||
| @ -288,14 +275,13 @@ namespace display { | |||||||
|             domain::InstanceAttribute attribute(attr.getName(), attr.getDefault(), attr); |             domain::InstanceAttribute attribute(attr.getName(), attr.getDefault(), attr); | ||||||
|             if(attr.getPopup().has_value() && attr.getPopup()->getType() == domain::Popup::AUTOMATIC) { |             if(attr.getPopup().has_value() && attr.getPopup()->getType() == domain::Popup::AUTOMATIC) { | ||||||
|                 if(attr.getDefault().isType(domain::Value::MEMORY_REFERENCE)) { |                 if(attr.getDefault().isType(domain::Value::MEMORY_REFERENCE)) { | ||||||
|                     auto dialog = new MemoryDialog("msg_dialog_memory_set", "msg_dialog_actions_set", &attribute, schema->componentInstances); |                     auto dialog = new MemoryDialog(&attribute, schema->componentInstances, false); | ||||||
|                     if(dialog->exec() == QDialog::Rejected) { |                     if(dialog->exec() == QDialog::Rejected) { | ||||||
|                         // if any dialog isn't set, whole creation is rejected
 |                         // if any dialog isn't set, whole creation is rejected
 | ||||||
|                         return {}; |                         return {}; | ||||||
|                     } |                     } | ||||||
|                 } else { |                 } else { | ||||||
|                     std::map<std::string, std::string> params = {{"attribute", attribute.attribute.getDisplayName()}}; |                     auto dialog = new AttributeDialog(&attribute, false); | ||||||
|                     auto dialog = new AttributeDialog(MESSAGE_PARAM("msg_dialog_attribute_set", params), "msg_dialog_actions_set", &attribute); |  | ||||||
|                     if(dialog->exec() == QDialog::Rejected) { |                     if(dialog->exec() == QDialog::Rejected) { | ||||||
|                         // if any dialog isn't set, whole creation is rejected
 |                         // if any dialog isn't set, whole creation is rejected
 | ||||||
|                         return {}; |                         return {}; | ||||||
| @ -314,7 +300,7 @@ namespace display { | |||||||
|             instanceAttributes.emplace_back(attr.getName(), attr.getDefault(), attr); |             instanceAttributes.emplace_back(attr.getName(), attr.getDefault(), attr); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         auto dialog = new display::SingleAutomaticDialog("msg_dialog_sa_pin_set", "msg_dialog_actions_set", instanceAttributes); |         auto dialog = new display::SingleAutomaticDialog(instanceAttributes, false); | ||||||
|         if(dialog->exec() == QDialog::Rejected) { |         if(dialog->exec() == QDialog::Rejected) { | ||||||
|             // if dialog is rejected, whole creation is rejected
 |             // if dialog is rejected, whole creation is rejected
 | ||||||
|             return {}; |             return {}; | ||||||
|  | |||||||
| @ -1,3 +1,7 @@ | |||||||
|  | //
 | ||||||
|  | // Created by bbr on 05.06.22..
 | ||||||
|  | //
 | ||||||
|  | 
 | ||||||
| #include "single_automatic_dialog.h" | #include "single_automatic_dialog.h" | ||||||
| #include <QVBoxLayout> | #include <QVBoxLayout> | ||||||
| #include <QLabel> | #include <QLabel> | ||||||
| @ -5,23 +9,38 @@ | |||||||
| #include <QPushButton> | #include <QPushButton> | ||||||
| 
 | 
 | ||||||
| namespace display { | 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; |         firstValue = values[0].value; | ||||||
|         secondValue = values[1].value; |         secondValue = values[1].value; | ||||||
| 
 | 
 | ||||||
|         auto *contentLayout = new QHBoxLayout(); |         auto *parentLayout = new QVBoxLayout(this); | ||||||
|         auto *firstLayout = new QVBoxLayout(); |         auto *contentLayout = new QHBoxLayout(this); | ||||||
|         auto *secondLayout = new QVBoxLayout(); |         auto *firstLayout = new QVBoxLayout(this); | ||||||
|  |         auto *secondLayout = new QVBoxLayout(this); | ||||||
| 
 | 
 | ||||||
|         content->setLayout(contentLayout); |         parentLayout->addLayout(contentLayout); | ||||||
|         contentLayout->addLayout(firstLayout); |         contentLayout->addLayout(firstLayout); | ||||||
|         contentLayout->addLayout(secondLayout); |         contentLayout->addLayout(secondLayout); | ||||||
|  |         this->setLayout(parentLayout); | ||||||
| 
 | 
 | ||||||
|         setupValues(firstLayout, values[0], &SingleAutomaticDialog::onFirstEnumerationChanged); |         setupValues(firstLayout, values[0], &SingleAutomaticDialog::onFirstEnumerationChanged); | ||||||
|         setupValues(secondLayout, values[1], &SingleAutomaticDialog::onSecondEnumerationChanged); |         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)) { |     void SingleAutomaticDialog::setupValues(QVBoxLayout *layout, domain::InstanceAttribute &attribute, void (display::SingleAutomaticDialog::* handler)(int)) { | ||||||
| @ -56,10 +75,10 @@ namespace display { | |||||||
|         secondValue = attributes[1].attribute.getPopup()->getEnumeration()[index].getValue(); |         secondValue = attributes[1].attribute.getPopup()->getEnumeration()[index].getValue(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     bool SingleAutomaticDialog::onUpdate() { |     void SingleAutomaticDialog::onUpdate() { | ||||||
|         attributes[0].value = firstValue; |         attributes[0].value = firstValue; | ||||||
|         attributes[1].value = secondValue; |         attributes[1].value = secondValue; | ||||||
|         return true; |         accept(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| } // display
 | } // display
 | ||||||
| @ -1,3 +1,7 @@ | |||||||
|  | //
 | ||||||
|  | // Created by bbr on 05.06.22..
 | ||||||
|  | //
 | ||||||
|  | 
 | ||||||
| #ifndef SCHEMEEDITOR_SINGLE_AUTOMATIC_DIALOG_H | #ifndef SCHEMEEDITOR_SINGLE_AUTOMATIC_DIALOG_H | ||||||
| #define SCHEMEEDITOR_SINGLE_AUTOMATIC_DIALOG_H | #define SCHEMEEDITOR_SINGLE_AUTOMATIC_DIALOG_H | ||||||
| 
 | 
 | ||||||
| @ -6,29 +10,24 @@ | |||||||
| #include <QVBoxLayout> | #include <QVBoxLayout> | ||||||
| #include "comdel/domain/value.h" | #include "comdel/domain/value.h" | ||||||
| #include "comdel/domain/instance_attribute.h" | #include "comdel/domain/instance_attribute.h" | ||||||
| #include "generic_dialog.h" |  | ||||||
| 
 | 
 | ||||||
| namespace display { | namespace display { | ||||||
| 
 | 
 | ||||||
|     class SingleAutomaticDialog: public GenericDialog { |     class SingleAutomaticDialog: public QDialog { | ||||||
|         domain::Value firstValue; |         domain::Value firstValue; | ||||||
|         domain::Value secondValue; |         domain::Value secondValue; | ||||||
|         std::vector<domain::InstanceAttribute> &attributes; |         std::vector<domain::InstanceAttribute> &attributes; | ||||||
| 
 | 
 | ||||||
|     public: |     public: | ||||||
|         explicit SingleAutomaticDialog( |         explicit SingleAutomaticDialog(std::vector<domain::InstanceAttribute>& values, bool updating = true); | ||||||
|                 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)); |         void setupValues(QVBoxLayout *layout, domain::InstanceAttribute &attribute, void (display::SingleAutomaticDialog::* handler)(int)); | ||||||
| 
 | 
 | ||||||
|     public slots: |     public slots: | ||||||
| 
 | 
 | ||||||
|         void onFirstEnumerationChanged(int index); |         void onFirstEnumerationChanged(int index); | ||||||
|         void onSecondEnumerationChanged(int index); |         void onSecondEnumerationChanged(int index); | ||||||
|  |         void onUpdate(); | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
| } // display
 | } // display
 | ||||||
| @ -44,15 +44,8 @@ namespace domain { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|     Attribute::Attribute(std::string name, std::optional<std::string> displayName, Value defaultValue, std::optional<Popup> popup) |     Attribute::Attribute(std::string name, Value defaultValue, std::optional<Popup> popup) | ||||||
|             : name(name), displayName(displayName), defaultValue(defaultValue), popup(popup) {} |             : name(name), defaultValue(defaultValue), popup(popup) {} | ||||||
| 
 |  | ||||||
|     std::string Attribute::getDisplayName() { |  | ||||||
|         if(displayName.has_value()) { |  | ||||||
|             return *displayName; |  | ||||||
|         } |  | ||||||
|         return name; |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     std::string Attribute::getName() { |     std::string Attribute::getName() { | ||||||
|         return name; |         return name; | ||||||
|  | |||||||
| @ -61,16 +61,13 @@ namespace domain { | |||||||
| 
 | 
 | ||||||
|     class Attribute { |     class Attribute { | ||||||
|         std::string name; |         std::string name; | ||||||
|         std::optional<std::string> displayName; |  | ||||||
|         Value defaultValue; |         Value defaultValue; | ||||||
|         std::optional<Popup> popup; |         std::optional<Popup> popup; | ||||||
|     public: |     public: | ||||||
|         Attribute(std::string name, std::optional<std::string> displayName, Value defaultValue, std::optional<Popup> popup = std::nullopt); |         Attribute(std::string name, Value defaultValue, std::optional<Popup> popup = std::nullopt); | ||||||
| 
 | 
 | ||||||
|         std::string getName(); |         std::string getName(); | ||||||
| 
 | 
 | ||||||
|         std::string getDisplayName(); |  | ||||||
| 
 |  | ||||||
|         Value getDefault(); |         Value getDefault(); | ||||||
| 
 | 
 | ||||||
|         std::optional<Popup> getPopup(); |         std::optional<Popup> getPopup(); | ||||||
|  | |||||||
| @ -35,21 +35,14 @@ namespace domain { | |||||||
|         return type; |         return type; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     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, |     Bus::Bus(std::string name, std::string instanceName, std::string tooltip, BusType type, std::pair<int, int> count, std::vector<Wire> wires, | ||||||
|              std::optional<ui::Bus> displayBus) |              std::optional<ui::Bus> displayBus) | ||||||
|             : name(name), displayName(displayName), instanceName(instanceName), tooltip(tooltip), type(type), count(count), wires(wires), displayBus(displayBus) {} |             : name(name), instanceName(instanceName), tooltip(tooltip), type(type), count(count), wires(wires), displayBus(displayBus) {} | ||||||
| 
 | 
 | ||||||
|     std::string Bus::getName() { |     std::string Bus::getName() { | ||||||
|         return name; |         return name; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     std::string Bus::getDisplayName() { |  | ||||||
|         if(displayName.has_value()) { |  | ||||||
|             return *displayName; |  | ||||||
|         } |  | ||||||
|         return name; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     std::string Bus::getTooltip() { |     std::string Bus::getTooltip() { | ||||||
|         return tooltip; |         return tooltip; | ||||||
|     } |     } | ||||||
| @ -69,5 +62,4 @@ namespace domain { | |||||||
|     std::optional<ui::Bus> Bus::getDisplayBus() { |     std::optional<ui::Bus> Bus::getDisplayBus() { | ||||||
|         return displayBus; |         return displayBus; | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
| } // namespace domain
 | } // namespace domain
 | ||||||
|  | |||||||
| @ -25,8 +25,8 @@ namespace domain { | |||||||
|         std::string name; |         std::string name; | ||||||
|         WireType type; |         WireType type; | ||||||
|         int width; |         int width; | ||||||
|         bool hidden = false; |         bool hidden; | ||||||
|         bool hasTerminate = false; |         bool hasTerminate; | ||||||
|         Value terminateWith; |         Value terminateWith; | ||||||
| 
 | 
 | ||||||
|     public: |     public: | ||||||
| @ -54,7 +54,6 @@ namespace domain { | |||||||
|         }; |         }; | ||||||
|     private: |     private: | ||||||
|         std::string name; |         std::string name; | ||||||
|         std::optional<std::string> displayName; |  | ||||||
|         std::string instanceName; |         std::string instanceName; | ||||||
|         std::string tooltip; |         std::string tooltip; | ||||||
|         BusType type; |         BusType type; | ||||||
| @ -64,13 +63,11 @@ namespace domain { | |||||||
|         std::vector<Wire> wires; |         std::vector<Wire> wires; | ||||||
| 
 | 
 | ||||||
|     public: |     public: | ||||||
|         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, |         Bus(std::string name, 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::optional<ui::Bus> display = std::nullopt); | ||||||
| 
 | 
 | ||||||
|         std::string getName(); |         std::string getName(); | ||||||
| 
 | 
 | ||||||
|         std::string getDisplayName(); |  | ||||||
| 
 |  | ||||||
|         std::string getInstanceName(); |         std::string getInstanceName(); | ||||||
| 
 | 
 | ||||||
|         std::string getTooltip(); |         std::string getTooltip(); | ||||||
|  | |||||||
| @ -3,7 +3,6 @@ | |||||||
| //
 | //
 | ||||||
| 
 | 
 | ||||||
| #include <set> | #include <set> | ||||||
| #include <QLayout> |  | ||||||
| #include "comdel_generator.h" | #include "comdel_generator.h" | ||||||
| 
 | 
 | ||||||
| namespace domain { | namespace domain { | ||||||
| @ -128,18 +127,8 @@ namespace domain { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void generateConnection(ConnectionInstance *connection, ostream &buffer) { |     void generateConnection(ConnectionInstance *connection, ostream &buffer) { | ||||||
| 
 |         buffer << "\t\tline {x1:" << connection->start.first << "; y1:" << connection->start.second << "; " << | ||||||
|         auto x1 = connection->start.first; |                "x2:" << connection->end.first << "; y2:" << connection->end.second << ";}" << "\n"; | ||||||
|         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) { |     void generateBus(BusInstance *bus, ostream &buffer) { | ||||||
| @ -159,10 +148,13 @@ namespace domain { | |||||||
|         for (auto &bus: schema->busInstances) { |         for (auto &bus: schema->busInstances) { | ||||||
|             buffer << "\t//" << bus->name << std::endl; |             buffer << "\t//" << bus->name << std::endl; | ||||||
|             for (auto &wire: bus->bus.getWires()) { |             for (auto &wire: bus->bus.getWires()) { | ||||||
|                 auto name = wire.getName(); |                 std::string name = wire.getName(); | ||||||
|                 if (usedNames.count(name) > 0) { |                 if (usedNames.count(wire.getName()) > 0) { | ||||||
|                     name = bus->name + "__" + wire.getName(); |                     name = bus->name + "__" + wire.getName(); | ||||||
|                 } |                 } | ||||||
|  |                 if (wire.isHidden()) { | ||||||
|  |                     name = "--" + name; | ||||||
|  |                 } | ||||||
|                 usedNames.insert(name); |                 usedNames.insert(name); | ||||||
|                 usedMappings.insert(std::make_pair(bus->name + "." + wire.getName(), name)); |                 usedMappings.insert(std::make_pair(bus->name + "." + wire.getName(), name)); | ||||||
| 
 | 
 | ||||||
| @ -192,11 +184,7 @@ namespace domain { | |||||||
|         if (wire.getWidth() != 1) { |         if (wire.getWidth() != 1) { | ||||||
|             buffer << "<" << wire.getWidth() << ">"; |             buffer << "<" << wire.getWidth() << ">"; | ||||||
|         } |         } | ||||||
|         buffer << " " << (wire.isHidden() ? "--" : "") << name; |         buffer << " " << name << ";" << std::endl; | ||||||
|         if(wire.hasTerminateWith()) { |  | ||||||
|             buffer << " = " << wire.getTerminateWith().asInt(); |  | ||||||
|         } |  | ||||||
|         buffer << ";" << std::endl; |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     std::set<std::string> createImports(Schema *schema) { |     std::set<std::string> createImports(Schema *schema) { | ||||||
| @ -215,9 +203,6 @@ namespace domain { | |||||||
|                                     map<string, string> &wireNames, |                                     map<string, string> &wireNames, | ||||||
|                                     stringstream &buffer); |                                     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, |     void generateComponent(Schema *schema, map<string, string> &wires, ostream &buffer, | ||||||
|                            shared_ptr<ComponentInstance> &component); |                            shared_ptr<ComponentInstance> &component); | ||||||
| 
 | 
 | ||||||
| @ -265,42 +250,37 @@ namespace domain { | |||||||
| 
 | 
 | ||||||
|         for (auto &pin: component->component.getPins()) { |         for (auto &pin: component->component.getPins()) { | ||||||
|             if (schema->hasConnection(component->name, pin.getName())) { |             if (schema->hasConnection(component->name, pin.getName())) { | ||||||
|                 auto connections = schema->getConnections(component->name, pin.getName()); |                 auto conn = schema->getConnection(component->name, pin.getName()); | ||||||
|                 if(connections.size() == 1) { |                 auto busConn = dynamic_cast<BusConnectionInstance *>(conn); | ||||||
|                     auto conn = connections[0]; |                 if (busConn != nullptr) { | ||||||
|                     auto busConn = dynamic_cast<BusConnectionInstance *>(conn); |                     for (auto wire: busConn->connection.getWires()) { | ||||||
|                     if (busConn != nullptr) { |                         if (wire.isType(Value::ATTRIBUTE_REFERENCE)) { | ||||||
|                         for (auto wire: busConn->connection.getWires()) { |                             auto attribute = busConn->getAttribute(wire.asReference()); | ||||||
|                             if (wire.isType(Value::ATTRIBUTE_REFERENCE)) { |                             if (wire.isType(Value::WIRE_REFERENCE)) { | ||||||
|                                 auto attribute = busConn->getAttribute(wire.asReference()); |                                 tempOutput << wires[busConn->bus->name + "." + attribute.value.asReference()] << ", "; | ||||||
|                                 if (wire.isType(Value::WIRE_REFERENCE)) { |                             } else if (wire.isType(Value::NIL)) { | ||||||
|                                     tempOutput << wires[busConn->bus->name + "." + attribute.value.asReference()] << ", "; |                                 tempOutput << "*, "; | ||||||
|                                 } else if (wire.isType(Value::NIL)) { |  | ||||||
|                                     tempOutput << "*, "; |  | ||||||
|                                 } else { |  | ||||||
|                                     tempOutput << attribute.value.stringify() << ", "; |  | ||||||
|                                 } |  | ||||||
|                             } else { |                             } else { | ||||||
|                                 if (wire.isType(Value::WIRE_REFERENCE)) { |                                 tempOutput << attribute.value.stringify() << ", "; | ||||||
|                                     tempOutput << wires[busConn->bus->name + "." + wire.asReference()] << ", "; |                             } | ||||||
|                                 } else if (wire.isType(Value::NIL)) { |                         } else { | ||||||
|                                     tempOutput << "*, "; |                             if (wire.isType(Value::WIRE_REFERENCE)) { | ||||||
|                                 } else { |                                 tempOutput << wires[busConn->bus->name + "." + wire.asReference()] << ", "; | ||||||
|                                     tempOutput << wire.stringify() << ", "; |                             } else if (wire.isType(Value::NIL)) { | ||||||
|                                 } |                                 tempOutput << "*, "; | ||||||
|  |                             } else { | ||||||
|  |                                 tempOutput << wire.stringify() << ", "; | ||||||
|                             } |                             } | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                     auto dirConn = dynamic_cast<DirectConnectionInstance *>(conn); |                 } | ||||||
|                     if (dirConn != nullptr) { |                 auto dirConn = dynamic_cast<DirectConnectionInstance *>(conn); | ||||||
|                         if (dirConn->bus->bus.getType() == Bus::AUTOMATIC) { |                 if (dirConn != nullptr) { | ||||||
|                             generateAutomaticPin(dirConn, component->name, pin.getName(), wires, tempOutput); |                     if (dirConn->bus->bus.getType() == Bus::AUTOMATIC) { | ||||||
|                         } else { |                         generateAutomaticPin(dirConn, component->name, pin.getName(), wires, tempOutput); | ||||||
|                             generateSingleAutomaticPin(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 { |             } else { | ||||||
|                 // if no connection exists than defaults must exist
 |                 // if no connection exists than defaults must exist
 | ||||||
| @ -361,30 +341,8 @@ namespace domain { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void generateSingleAutomaticPin(std::vector<ConnectionInstance*> connections, ComponentInstance *instance, string pin, |     void | ||||||
|                                     map<string, string> &wireNames, stringstream &buffer) { |     generateAutomaticPin(DirectConnectionInstance *connection, string name, string pin, map<string, string> wireNames, | ||||||
|         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) { |                          stringstream &buffer) { | ||||||
|         std::vector<Value> wires; |         std::vector<Value> wires; | ||||||
|         if (connection->instance->name == name && connection->connection.getComponent().pin == pin) { |         if (connection->instance->name == name && connection->connection.getComponent().pin == pin) { | ||||||
|  | |||||||
| @ -1,7 +1,6 @@ | |||||||
| #include <set> | #include <set> | ||||||
| #include "comdel_validator.h" | #include "comdel_validator.h" | ||||||
| #include "library.h" | #include "library.h" | ||||||
| #include "message_source.h" |  | ||||||
| 
 | 
 | ||||||
| namespace domain { | namespace domain { | ||||||
| 
 | 
 | ||||||
| @ -31,20 +30,24 @@ namespace domain { | |||||||
|         for (auto comp: library.getComponents()) { |         for (auto comp: library.getComponents()) { | ||||||
|             int count = instanceMap[comp.getName()]; |             int count = instanceMap[comp.getName()]; | ||||||
| 
 | 
 | ||||||
|             context.attributes["componentName"] = Value::fromString(comp.getDisplayName()); |             context.attributes["componentName"] = Value::fromString(comp.getName()); | ||||||
|             context.attributes["min"] = Value::fromInt(comp.getCount().first); |             context.attributes["min"] = Value::fromInt(comp.getCount().first); | ||||||
|             context.attributes["max"] = Value::fromInt(comp.getCount().second); |             context.attributes["max"] = Value::fromInt(comp.getCount().second); | ||||||
|             context.attributes["count"] = Value::fromInt(count); |             context.attributes["count"] = Value::fromInt(count); | ||||||
| 
 | 
 | ||||||
|             if (count < comp.getCount().first) { |             if (count < comp.getCount().first) { | ||||||
|                 auto message = MESSAGE_PARAM("msg_validators_component_min_count", context.map()); |                 auto message = populateMessage( | ||||||
|  |                         "Nedovoljno instanci komponente '{componentName}' potrebno barem {min}, pronađeno {count}", | ||||||
|  |                         context); | ||||||
|                 errors.emplace_back(Action::ERROR, message); |                 errors.emplace_back(Action::ERROR, message); | ||||||
|             } else if (count > comp.getCount().second) { |             } else if (count > comp.getCount().second) { | ||||||
|                 auto message = MESSAGE_PARAM("msg_validators_component_max_count", context.map()); |                 auto message = populateMessage( | ||||||
|  |                         "Previše insanci komponente '{componentName}' dozvoljeno najviše {max}, pronađeno {count}", context); | ||||||
|                 errors.emplace_back(Action::ERROR, message); |                 errors.emplace_back(Action::ERROR, message); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|         // validate bus instance count
 |         // validate bus instance count
 | ||||||
|         std::map<std::string, int> busInstanceMap; |         std::map<std::string, int> busInstanceMap; | ||||||
|         for (auto &inst: schema.busInstances) { |         for (auto &inst: schema.busInstances) { | ||||||
| @ -54,16 +57,18 @@ namespace domain { | |||||||
|         for (auto bus: library.getBuses()) { |         for (auto bus: library.getBuses()) { | ||||||
|             int count = busInstanceMap[bus.getName()]; |             int count = busInstanceMap[bus.getName()]; | ||||||
| 
 | 
 | ||||||
|             context.attributes["busName"] = Value::fromString(bus.getDisplayName()); |             context.attributes["busName"] = Value::fromString(bus.getName()); | ||||||
|             context.attributes["min"] = Value::fromInt(bus.getCount().first); |             context.attributes["min"] = Value::fromInt(bus.getCount().first); | ||||||
|             context.attributes["max"] = Value::fromInt(bus.getCount().second); |             context.attributes["max"] = Value::fromInt(bus.getCount().second); | ||||||
|             context.attributes["count"] = Value::fromInt(count); |             context.attributes["count"] = Value::fromInt(count); | ||||||
| 
 | 
 | ||||||
|             if (count < bus.getCount().first) { |             if (count < bus.getCount().first) { | ||||||
|                 auto message = MESSAGE_PARAM("msg_validators_bus_min_count", context.map()); |                 auto message = populateMessage( | ||||||
|  |                         "Nedovoljno instanci sabirnice '{busName}' potrebna barem jedna {min}, pronađeno {count}", context); | ||||||
|                 errors.emplace_back(Action::ERROR, message); |                 errors.emplace_back(Action::ERROR, message); | ||||||
|             } else if (count > bus.getCount().second) { |             } else if (count > bus.getCount().second) { | ||||||
|                 auto message = MESSAGE_PARAM("msg_validators_bus_max_count", context.map()); |                 auto message = populateMessage( | ||||||
|  |                         "Previše instanci sabirnice '{busName}' dozvoljeno najviše {max}, pronašeno {count}", context); | ||||||
|                 errors.emplace_back(Action::ERROR, message); |                 errors.emplace_back(Action::ERROR, message); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| @ -77,11 +82,12 @@ namespace domain { | |||||||
| 
 | 
 | ||||||
|         for (auto &inst: schema.componentInstances) { |         for (auto &inst: schema.componentInstances) { | ||||||
|             for (auto &pin: inst->component.getPins()) { |             for (auto &pin: inst->component.getPins()) { | ||||||
|                 if (pin.getConnection().has_value()) { |                 if (pin.getConnection().getType() == PinConnection::REQUIRED) { | ||||||
|                     if (!connectionExists(schema, inst, pin)) { |                     if (!connectionExists(schema, inst, pin)) { | ||||||
|                         context.instance = inst.get(); |                         context.instance = inst.get(); | ||||||
|                         auto message = MESSAGE_PARAM(pin.getConnection().value(), context.map()); |                         context.attributes["instanceName"] = Value::fromString(inst->name); | ||||||
|                         errors.emplace_back(context.instance, nullptr, Action::ERROR, message); |                         auto message = populateMessage(pin.getConnection().getMessage(), context); | ||||||
|  |                         errors.emplace_back(Action::ERROR, message); | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| @ -141,7 +147,7 @@ namespace domain { | |||||||
|         ruleContext.function = validators; |         ruleContext.function = validators; | ||||||
|         auto action = rule.evaluate(ruleContext); |         auto action = rule.evaluate(ruleContext); | ||||||
|         if (action) { |         if (action) { | ||||||
|             auto message = MESSAGE_PARAM(action->getMessage(), context.map()); |             std::string message = this->populateMessage(action->getMessage(), context); | ||||||
|             return ValidationError{context.instance, context.attribute, action->getType(), message}; |             return ValidationError{context.instance, context.attribute, action->getType(), message}; | ||||||
|         } |         } | ||||||
|         return nullopt; |         return nullopt; | ||||||
| @ -166,7 +172,7 @@ namespace domain { | |||||||
|                         if(memoryReference != nullopt) { |                         if(memoryReference != nullopt) { | ||||||
|                             if(memoryInstances.count(*memoryReference) == 0) { |                             if(memoryInstances.count(*memoryReference) == 0) { | ||||||
|                                 context.attributes["memoryReference"] = domain::Value::fromString(memoryReference.value()); |                                 context.attributes["memoryReference"] = domain::Value::fromString(memoryReference.value()); | ||||||
|                                 auto message = MESSAGE_PARAM("msg_validators_memory_not_found", context.map()); |                                 auto message = populateMessage("Ne postoji memorijska komponenta '{memoryReference}'", context); | ||||||
|                                 errors.emplace_back(component.get(), nullptr, Action::ERROR, message); |                                 errors.emplace_back(component.get(), nullptr, Action::ERROR, message); | ||||||
|                             } |                             } | ||||||
|                         } |                         } | ||||||
| @ -185,8 +191,9 @@ namespace domain { | |||||||
| 
 | 
 | ||||||
|         for(auto& component: schema.componentInstances) { |         for(auto& component: schema.componentInstances) { | ||||||
|             if(names.find(component->name) != names.end()) { |             if(names.find(component->name) != names.end()) { | ||||||
|                 context.instance = component.get(); |                 context.attributes["componentName"] = Value::fromString(component->name); | ||||||
|                 auto message = MESSAGE_PARAM("msg_validators_duplicates_found", context.map()); |                 auto message = populateMessage( | ||||||
|  |                         "Pronađeno više instanci sa imenom '{componentName}'", context); | ||||||
|                 errors.emplace_back(Action::ERROR, message); |                 errors.emplace_back(Action::ERROR, message); | ||||||
|             } |             } | ||||||
|             names.insert(component->name); |             names.insert(component->name); | ||||||
| @ -194,6 +201,26 @@ namespace domain { | |||||||
|         return errors; |         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) { |     bool ComdelValidator::connectionExists(Schema &schema, shared_ptr<ComponentInstance> &component, Pin &pin) { | ||||||
|         for (auto conn: schema.connections) { |         for (auto conn: schema.connections) { | ||||||
|             auto busConnection = dynamic_cast<BusConnectionInstance *>(conn.get()); |             auto busConnection = dynamic_cast<BusConnectionInstance *>(conn.get()); | ||||||
| @ -206,9 +233,13 @@ namespace domain { | |||||||
| 
 | 
 | ||||||
|             auto directConnection = dynamic_cast<DirectConnectionInstance *>(conn.get()); |             auto directConnection = dynamic_cast<DirectConnectionInstance *>(conn.get()); | ||||||
|             if (directConnection != nullptr) { |             if (directConnection != nullptr) { | ||||||
|                 if ((directConnection->instance->name == component->name && directConnection->connection.getComponent().pin == pin.getName()) || |                 if (directConnection->instance->name == component->name && | ||||||
|                     (directConnection->secondInstance->name == component->name) && directConnection->connection.getSecondComponent()->pin == pin.getName()) { |                     directConnection->connection.getComponent().pin == pin.getName()) { | ||||||
|                     return directConnection->connection.isConnecting({component->component.getName(), pin.getName()}); |                     return true; | ||||||
|  |                 } | ||||||
|  |                 if (directConnection->secondInstance->name == component->name && | ||||||
|  |                     directConnection->connection.getSecondComponent()->pin == pin.getName()) { | ||||||
|  |                     return true; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| @ -221,20 +252,4 @@ namespace domain { | |||||||
|             this->validators.insert(std::make_pair(validator->getName(), validator)); |             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,8 +23,6 @@ namespace domain { | |||||||
|         InstanceAttribute *attribute; |         InstanceAttribute *attribute; | ||||||
|         std::map<std::string, AddressSpace> addressSpaces; |         std::map<std::string, AddressSpace> addressSpaces; | ||||||
|         std::map<std::string, Value> attributes; |         std::map<std::string, Value> attributes; | ||||||
| 
 |  | ||||||
|         std::map<std::string, std::string> map(); |  | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     class ComdelValidator { |     class ComdelValidator { | ||||||
| @ -43,13 +41,18 @@ namespace domain { | |||||||
| 
 | 
 | ||||||
|         std::vector<ValidationError> validateInstanceCount(Schema &schema, Library &library, ValidationContext context); |         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); |         ComdelValidator(std::vector<FunctionValidator *> validators); | ||||||
| 
 | 
 | ||||||
|     private: |     private: | ||||||
|         std::map<std::string, FunctionValidator *> validators; |         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); |         bool connectionExists(Schema &schema, shared_ptr<ComponentInstance> &component, Pin &pin); | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,25 +1,17 @@ | |||||||
| #include "component.h" | #include "component.h" | ||||||
| #include <stdexcept> |  | ||||||
| 
 | 
 | ||||||
| namespace domain { | namespace domain { | ||||||
| 
 | 
 | ||||||
|     Component::Component(string name, optional<string> displayName, string tooltip, string source, ComponentType type, |     Component::Component(string name, string tooltip, string source, ComponentType type, | ||||||
|                          vector<Rule> rules, string instanceName, pair<int, int> count, Display display, |                          vector<Rule> rules, string instanceName, pair<int, int> count, Display display, | ||||||
|                          vector<Pin> pins, vector<Attribute> attributes) |                          vector<Pin> pins, vector<Attribute> attributes) | ||||||
|             : name(name), displayName(displayName), tooltip(tooltip), source(source), type(type), rules(rules), instanceName(instanceName), |             : name(name), tooltip(tooltip), source(source), type(type), rules(rules), instanceName(instanceName), | ||||||
|               count(count), display(display), pins(pins), attributes(attributes) {} |               count(count), display(display), pins(pins), attributes(attributes) {} | ||||||
| 
 | 
 | ||||||
|     std::string Component::getName() { |     std::string Component::getName() { | ||||||
|         return name; |         return name; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     std::string Component::getDisplayName() { |  | ||||||
|         if(displayName.has_value()) { |  | ||||||
|             return displayName.value(); |  | ||||||
|         } |  | ||||||
|         return name; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     std::string Component::getTooltip() { |     std::string Component::getTooltip() { | ||||||
|         return tooltip; |         return tooltip; | ||||||
|     } |     } | ||||||
| @ -58,7 +50,7 @@ namespace domain { | |||||||
|                 return p; |                 return p; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         throw std::runtime_error("no pin with name '" + pin + "'"); |         throw std::exception(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     bool Component::hasPin(std::string name) { |     bool Component::hasPin(std::string name) { | ||||||
| @ -80,7 +72,7 @@ namespace domain { | |||||||
|                 return attr; |                 return attr; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         throw std::runtime_error("no attribute with name '" + attribute + "'"); |         throw std::exception(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     bool Component::hasAttribute(std::string name, Value::ValueType type) { |     bool Component::hasAttribute(std::string name, Value::ValueType type) { | ||||||
| @ -102,4 +94,5 @@ namespace domain { | |||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| } // namespace domain
 | } // namespace domain
 | ||||||
|  | |||||||
| @ -23,7 +23,6 @@ namespace domain { | |||||||
| 
 | 
 | ||||||
|     private: |     private: | ||||||
|         std::string name; |         std::string name; | ||||||
|         std::optional<std::string> displayName; |  | ||||||
|         std::string tooltip; |         std::string tooltip; | ||||||
|         std::string source; |         std::string source; | ||||||
|         ComponentType type; |         ComponentType type; | ||||||
| @ -37,14 +36,12 @@ namespace domain { | |||||||
| 
 | 
 | ||||||
|     public: |     public: | ||||||
| 
 | 
 | ||||||
|         Component(string name, optional<string> displayName, string tooltip, string source, ComponentType type, |         Component(string name, string tooltip, string source, ComponentType type, | ||||||
|                   vector<Rule> rules, string instanceName, pair<int, int> count, Display display, |                   vector<Rule> rules, string instanceName, pair<int, int> count, Display display, | ||||||
|                   vector<Pin> pins, vector<Attribute> attributes); |                   vector<Pin> pins, vector<Attribute> attributes); | ||||||
| 
 | 
 | ||||||
|         std::string getName(); |         std::string getName(); | ||||||
| 
 | 
 | ||||||
|         std::string getDisplayName(); |  | ||||||
| 
 |  | ||||||
|         std::string getTooltip(); |         std::string getTooltip(); | ||||||
| 
 | 
 | ||||||
|         std::string getSource(); |         std::string getSource(); | ||||||
|  | |||||||
| @ -1,5 +1,4 @@ | |||||||
| #include "connection.h" | #include "connection.h" | ||||||
| #include <stdexcept> |  | ||||||
| 
 | 
 | ||||||
| namespace domain { | namespace domain { | ||||||
| 
 | 
 | ||||||
| @ -39,7 +38,7 @@ namespace domain { | |||||||
|                 return attributes[i]; |                 return attributes[i]; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         throw std::runtime_error("no attribute with name '" + name + "'"); |         throw std::exception(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     bool Connection::hasAttribute(std::string name) { |     bool Connection::hasAttribute(std::string name) { | ||||||
|  | |||||||
| @ -1,5 +1,4 @@ | |||||||
| #include "connection_instance.h" | #include "connection_instance.h" | ||||||
| #include <stdexcept> |  | ||||||
| 
 | 
 | ||||||
| namespace domain { | namespace domain { | ||||||
| 
 | 
 | ||||||
| @ -14,7 +13,7 @@ namespace domain { | |||||||
|                 return attr; |                 return attr; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         throw std::runtime_error("no attribute with name '" + attribute + "'"); |         throw std::exception(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -27,23 +26,4 @@ namespace domain { | |||||||
|                                                        Connection connection) |                                                        Connection connection) | ||||||
|             : ConnectionInstance(instance, attributes, connection), secondInstance(secondInstance), bus(bus) {} |             : 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
 | } // namespace domain
 | ||||||
|  | |||||||
| @ -41,8 +41,6 @@ namespace domain { | |||||||
| 
 | 
 | ||||||
|         DirectConnectionInstance(ComponentInstance *instance, ComponentInstance *secondsInstance, |         DirectConnectionInstance(ComponentInstance *instance, ComponentInstance *secondsInstance, | ||||||
|                                  std::vector<InstanceAttribute> attributes, BusInstance *bus, Connection connection); |                                  std::vector<InstanceAttribute> attributes, BusInstance *bus, Connection connection); | ||||||
| 
 |  | ||||||
|         int getSelected(ConnectionComponent connection); |  | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -47,27 +47,10 @@ namespace domain { | |||||||
|     void ui::Rect::comdel(std::ostream &buffer, int x, int y) { |     void ui::Rect::comdel(std::ostream &buffer, int x, int y) { | ||||||
|         buffer << "\t\trectangle {\n"; |         buffer << "\t\trectangle {\n"; | ||||||
|         buffer << "\t\t\tx: " << (this->x + x) << "; y: " << (this->y + y) << ";\n"; |         buffer << "\t\t\tx: " << (this->x + x) << "; y: " << (this->y + y) << ";\n"; | ||||||
|         buffer << "\t\t\twidth: " << w << "; height: " << h << ";\n"; |         buffer << "\t\t\tw: " << w << "; h: " << 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"; |         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) { |     void ui::Line::render(QGraphicsItemGroup *group) { | ||||||
|         auto line = new QGraphicsLineItem(x1, y1, x2, y2); |         auto line = new QGraphicsLineItem(x1, y1, x2, y2); | ||||||
|         line->setPen(QPen(config.lineColor)); |         line->setPen(QPen(config.lineColor)); | ||||||
| @ -75,12 +58,10 @@ namespace domain { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void ui::Line::comdel(std::ostream &buffer, int x, int y) { |     void ui::Line::comdel(std::ostream &buffer, int x, int y) { | ||||||
|         buffer << "\t\tpath {\n"; |         buffer << "\t\tline {\n"; | ||||||
|         buffer << "\t\t\tx:0; y:0;\n"; |         buffer << "\t\t\tx1: " << (x1 + x) << "; y1: " << (y1 + y) << ";\n"; | ||||||
|         buffer << "\t\t\tpoints: ("; |         buffer << "\t\t\tx2: " << (x2 + x) << "; y2: " << (y2 + y) << ";\n"; | ||||||
|         buffer << "(" << (x1 + x) << ", " << (y1 + y) << "),"; |         buffer << "\t\t}\n\n"; | ||||||
|         buffer << "(" << (x2 - x1) << "," << (y2 - y1) << "));\n"; |  | ||||||
|         buffer << "\t\t}" << std::endl; |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void ui::Bus::render(QGraphicsItemGroup *group, int size) { |     void ui::Bus::render(QGraphicsItemGroup *group, int size) { | ||||||
| @ -108,12 +89,10 @@ namespace domain { | |||||||
|         buffer << "\t\trectangle {\n"; |         buffer << "\t\trectangle {\n"; | ||||||
|         buffer << "\t\t\tx: " << (this->x + x) << "; y: " << (this->y + y) << ";\n"; |         buffer << "\t\t\tx: " << (this->x + x) << "; y: " << (this->y + y) << ";\n"; | ||||||
|         if (orientation == HORIZONTAL) { |         if (orientation == HORIZONTAL) { | ||||||
|             buffer << "\t\t\twidth: " << size << "; height: " << h << ";\n"; |             buffer << "\t\t\tw: " << size << "; h: " << h << ";\n"; | ||||||
|         } else { |         } else { | ||||||
|             buffer << "\t\t\twidth: " << w << "; height: " << size << ";\n"; |             buffer << "\t\t\tw: " << w << "; h: " << 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"; |         buffer << "\t\t}\n\n"; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -226,7 +205,6 @@ namespace domain { | |||||||
|         if (pin) pin->render(group); |         if (pin) pin->render(group); | ||||||
|         if (bus) bus->render(group, size); |         if (bus) bus->render(group, size); | ||||||
|         if (text) text->render(group, context); |         if (text) text->render(group, context); | ||||||
|         if (ellipse) ellipse->render(group); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void ui::Item::comdel(std::ostream &buffer, int x, int y, int size) { |     void ui::Item::comdel(std::ostream &buffer, int x, int y, int size) { | ||||||
|  | |||||||
| @ -58,19 +58,6 @@ 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 { |         class Line { | ||||||
|         public: |         public: | ||||||
|             int x1, y1, x2, y2; |             int x1, y1, x2, y2; | ||||||
| @ -121,8 +108,6 @@ namespace domain { | |||||||
|             Pin(int x, int y, int w, int h, PinOrientation orientation, PinType pinType, DisplayConfig config) |             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) {} |                 : x(x), y(y), w(w), h(h), orientation(orientation), pinType(pinType), config(config) {} | ||||||
| 
 | 
 | ||||||
|             Pin(): config(DisplayConfig(Color(), Color())) {}; |  | ||||||
| 
 |  | ||||||
|         public: |         public: | ||||||
|             void render(QGraphicsItemGroup *group); |             void render(QGraphicsItemGroup *group); | ||||||
| 
 | 
 | ||||||
| @ -145,7 +130,6 @@ namespace domain { | |||||||
|             std::optional<Pin> pin = std::nullopt; |             std::optional<Pin> pin = std::nullopt; | ||||||
|             std::optional<Bus> bus = std::nullopt; |             std::optional<Bus> bus = std::nullopt; | ||||||
|             std::optional<Text> text = 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 render(QGraphicsItemGroup *group, ui::DisplayContext context, int size = 0); | ||||||
|             void comdel(std::ostream &buffer, int x, int y, int size = 0); |             void comdel(std::ostream &buffer, int x, int y, int size = 0); | ||||||
|  | |||||||
| @ -1,5 +1,4 @@ | |||||||
| #include "library.h" | #include "library.h" | ||||||
| #include <stdexcept> |  | ||||||
| 
 | 
 | ||||||
| namespace domain { | namespace domain { | ||||||
| 
 | 
 | ||||||
| @ -52,7 +51,7 @@ namespace domain { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     bool Library::hasComponent(std::string name) { |     bool Library::hasComponent(std::string name) { | ||||||
|         for (unsigned int i = 0; i < components.size(); i++) { |         for (uint i = 0; i < components.size(); i++) { | ||||||
|             if (components[i].getName() == name) { |             if (components[i].getName() == name) { | ||||||
|                 return true; |                 return true; | ||||||
|             } |             } | ||||||
| @ -61,7 +60,7 @@ namespace domain { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     bool Library::hasBus(std::string name) { |     bool Library::hasBus(std::string name) { | ||||||
|         for (unsigned int i = 0; i < buses.size(); i++) { |         for (uint i = 0; i < buses.size(); i++) { | ||||||
|             if (buses[i].getName() == name) { |             if (buses[i].getName() == name) { | ||||||
|                 return true; |                 return true; | ||||||
|             } |             } | ||||||
| @ -71,30 +70,30 @@ namespace domain { | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|     AddressSpace &Library::getAddressSpace(std::string addressSpace) { |     AddressSpace &Library::getAddressSpace(std::string addressSpace) { | ||||||
|         for (unsigned int i = 0; i < addressSpaces.size(); i++) { |         for (uint i = 0; i < addressSpaces.size(); i++) { | ||||||
|             if (addressSpaces[i].getName() == addressSpace) { |             if (addressSpaces[i].getName() == addressSpace) { | ||||||
|                 return addressSpaces[i]; |                 return addressSpaces[i]; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         throw std::runtime_error("no address space with name '" + addressSpace + "'"); |         throw std::exception(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     Component &Library::getComponent(std::string component) { |     Component &Library::getComponent(std::string component) { | ||||||
|         for (unsigned int i = 0; i < components.size(); i++) { |         for (uint i = 0; i < components.size(); i++) { | ||||||
|             if (components[i].getName() == component) { |             if (components[i].getName() == component) { | ||||||
|                 return components[i]; |                 return components[i]; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         throw std::runtime_error("no component with name '" + component + "'"); |         throw std::exception(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     Bus &Library::getBus(std::string bus) { |     Bus &Library::getBus(std::string bus) { | ||||||
|         for (unsigned int i = 0; i < buses.size(); i++) { |         for (uint i = 0; i < buses.size(); i++) { | ||||||
|             if (buses[i].getName() == bus) { |             if (buses[i].getName() == bus) { | ||||||
|                 return buses[i]; |                 return buses[i]; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         throw std::runtime_error("no bus with name '" + bus + "'"); |         throw std::exception(); | ||||||
| 
 | 
 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -103,7 +102,7 @@ namespace domain { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     std::optional<Connection> Library::getConnection(ConnectionComponent component, std::string bus) { |     std::optional<Connection> Library::getConnection(ConnectionComponent component, std::string bus) { | ||||||
|         for (unsigned int i = 0; i < connections.size(); i++) { |         for (uint i = 0; i < connections.size(); i++) { | ||||||
|             if (connections[i].isConnecting(component, bus)) { |             if (connections[i].isConnecting(component, bus)) { | ||||||
|                 return connections[i]; |                 return connections[i]; | ||||||
|             } |             } | ||||||
| @ -117,7 +116,7 @@ namespace domain { | |||||||
| 
 | 
 | ||||||
|     std::optional<Connection> |     std::optional<Connection> | ||||||
|     Library::getConnection(ConnectionComponent component, std::string bus, ConnectionComponent secondComponent) { |     Library::getConnection(ConnectionComponent component, std::string bus, ConnectionComponent secondComponent) { | ||||||
|         for (unsigned int i = 0; i < connections.size(); i++) { |         for (uint i = 0; i < connections.size(); i++) { | ||||||
|             if (connections[i].isConnecting(component, bus, secondComponent)) { |             if (connections[i].isConnecting(component, bus, secondComponent)) { | ||||||
|                 return connections[i]; |                 return connections[i]; | ||||||
|             } |             } | ||||||
|  | |||||||
| @ -2,7 +2,19 @@ | |||||||
| 
 | 
 | ||||||
| namespace domain { | namespace domain { | ||||||
| 
 | 
 | ||||||
|     Pin::Pin(std::string name, PinType type, std::string tooltip, std::optional<std::string> connection, domain::ui::Pin pin, |     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, | ||||||
|              std::optional<std::vector<Value>> wires) |              std::optional<std::vector<Value>> wires) | ||||||
|             : name(name), type(type), tooltip(tooltip), connection(connection), displayPin(pin), wires(wires) {} |             : name(name), type(type), tooltip(tooltip), connection(connection), displayPin(pin), wires(wires) {} | ||||||
| 
 | 
 | ||||||
| @ -22,7 +34,7 @@ namespace domain { | |||||||
|         return displayPin; |         return displayPin; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     std::optional<std::string> Pin::getConnection() { |     PinConnection &Pin::getConnection() { | ||||||
|         return connection; |         return connection; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -9,6 +9,25 @@ | |||||||
| 
 | 
 | ||||||
| namespace domain { | 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 { |     class Pin { | ||||||
|     public: |     public: | ||||||
|         enum PinType { |         enum PinType { | ||||||
| @ -21,13 +40,13 @@ namespace domain { | |||||||
|         std::string name; |         std::string name; | ||||||
|         PinType type; |         PinType type; | ||||||
|         std::string tooltip; |         std::string tooltip; | ||||||
|         std::optional<std::string> connection; |         PinConnection connection; | ||||||
|         domain::ui::Pin displayPin; |         domain::ui::Pin displayPin; | ||||||
| 
 | 
 | ||||||
|         std::optional<std::vector<Value>> wires; |         std::optional<std::vector<Value>> wires; | ||||||
| 
 | 
 | ||||||
|     public: |     public: | ||||||
|         Pin(std::string name, PinType type, std::string tooltip, std::optional<std::string> connection, domain::ui::Pin pin, |         Pin(std::string name, PinType type, std::string tooltip, PinConnection connection, domain::ui::Pin pin, | ||||||
|             std::optional<std::vector<Value>> wires); |             std::optional<std::vector<Value>> wires); | ||||||
| 
 | 
 | ||||||
|         std::string &getName(); |         std::string &getName(); | ||||||
| @ -38,7 +57,7 @@ namespace domain { | |||||||
| 
 | 
 | ||||||
|         ui::Pin &getDisplayPin(); |         ui::Pin &getDisplayPin(); | ||||||
| 
 | 
 | ||||||
|         std::optional<std::string> getConnection(); |         PinConnection &getConnection(); | ||||||
| 
 | 
 | ||||||
|         std::optional<std::vector<Value>> &getWires(); |         std::optional<std::vector<Value>> &getWires(); | ||||||
|     }; |     }; | ||||||
|  | |||||||
| @ -57,10 +57,12 @@ namespace domain { | |||||||
|         ConnectionComponent connectionComponent{instance->component.getName(), pinName}; |         ConnectionComponent connectionComponent{instance->component.getName(), pinName}; | ||||||
|         for(auto &conn: library.getConnections()) { |         for(auto &conn: library.getConnections()) { | ||||||
|             if(conn.isConnecting(connectionComponent)) { |             if(conn.isConnecting(connectionComponent)) { | ||||||
|  |                 // if bus connection
 | ||||||
|                 if(library.getBus(conn.getBus()).getType() == Bus::REGULAR) { |                 if(library.getBus(conn.getBus()).getType() == Bus::REGULAR) { | ||||||
|                     for(auto& bus: busInstances) { |                     for(auto& bus: busInstances) { | ||||||
|                         if(bus->bus.getName() == conn.getBus()) { |                         if(bus->bus.getName() == conn.getBus()) { | ||||||
|                             entries.push_back({ConnectionEntry::BUS, bus.get(), nullopt, nullopt, conn}); |                             ConnectionEntry entry{ConnectionEntry::BUS, bus.get(), nullopt, nullopt, conn}; | ||||||
|  |                             entries.emplace_back(entry); | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                 } else { |                 } else { | ||||||
| @ -90,16 +92,19 @@ namespace domain { | |||||||
|                                 for(auto& conn: this->connections) { |                                 for(auto& conn: this->connections) { | ||||||
|                                     if(conn->connection == entry.connection) { |                                     if(conn->connection == entry.connection) { | ||||||
|                                         if(bus.getType() == Bus::REGULAR) { |                                         if(bus.getType() == Bus::REGULAR) { | ||||||
|                                             auto busConnection = dynamic_cast<BusConnectionInstance*>(conn.get()); |                                             if(entry.busInstance.value()->bus.getName() == conn->connection.getBus()) { | ||||||
|                                             if(busConnection->instance == instance && busConnection->bus == entry.busInstance.value()) { |  | ||||||
|                                                 return true; |                                                 return true; | ||||||
|                                             } |                                             } | ||||||
|                                         } else { |                                         } else { | ||||||
|                                             auto directConnection = dynamic_cast<DirectConnectionInstance*>(conn.get()); |                                             auto *directInstance = dynamic_cast<DirectConnectionInstance*>(conn.get()); | ||||||
|                                             if(directConnection->instance == instance && directConnection->secondInstance == entry.componentInstance.value() || |                                             ComponentInstance* secondInstance; | ||||||
|                                                directConnection->secondInstance == instance && directConnection->instance == entry.componentInstance.value()) { |                                             if(directInstance->instance == instance) { | ||||||
|                                                 return true; |                                                 secondInstance = directInstance->secondInstance; | ||||||
|  |                                             } else { | ||||||
|  |                                                 secondInstance = directInstance->instance; | ||||||
|                                             } |                                             } | ||||||
|  | 
 | ||||||
|  |                                             return entry.componentInstance == secondInstance; | ||||||
|                                         } |                                         } | ||||||
|                                     } |                                     } | ||||||
|                                 } |                                 } | ||||||
| @ -108,8 +113,8 @@ namespace domain { | |||||||
|                     entries.end() |                     entries.end() | ||||||
|             ); |             ); | ||||||
|         } |         } | ||||||
|         return entries; |  | ||||||
| 
 | 
 | ||||||
|  |         return entries; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| } // namespace domain
 | } // namespace domain
 | ||||||
|  | |||||||
| @ -5,8 +5,9 @@ | |||||||
| 
 | 
 | ||||||
| namespace domain { | namespace domain { | ||||||
| 
 | 
 | ||||||
|     ComdelContext::ComdelContext(std::string name, bool inComponent, bool inConnection, bool inSingleAutomaticConnection) | 
 | ||||||
|         : name(std::move(name)), inComponent(inComponent), inConnection(inConnection), inSingleAutomaticConnection(inSingleAutomaticConnection) {} |     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) {} | ||||||
| 
 | 
 | ||||||
|     bool ComdelContext::doesAttributeExists(std::string name, Value::ValueType type) { |     bool ComdelContext::doesAttributeExists(std::string name, Value::ValueType type) { | ||||||
|         for (auto &attribute: attributes) { |         for (auto &attribute: attributes) { | ||||||
| @ -26,9 +27,7 @@ namespace domain { | |||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /***********************************************************************
 | 
 | ||||||
|      *                      ENUM CONVERSIONS                               * |  | ||||||
|      ***********************************************************************/ |  | ||||||
|     Component::ComponentType toType(ComponentNode::ComponentType type) { |     Component::ComponentType toType(ComponentNode::ComponentType type) { | ||||||
|         if (type == ComponentNode::MEMORY) { |         if (type == ComponentNode::MEMORY) { | ||||||
|             return Component::MEMORY; |             return Component::MEMORY; | ||||||
| @ -79,26 +78,29 @@ namespace domain { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|     Value toType(ValueNode node, Value::ValueType type = Value::ValueType::UNDEFINED) { |     Value toType(ValueNode node, Value::ValueType type = Value::ValueType::UNDEFINED) { | ||||||
|         if (type == Value::MEMORY_REFERENCE) { |         if (type == Value::MEMORY_REFERENCE) { | ||||||
|             if (node.is(ValueNode::NIL)) { |             if (node.getType() == ValueNode::NIL) { | ||||||
|                 return Value::fromMemoryReference(nullopt); |                 return Value::fromMemoryReference(nullopt); | ||||||
|             } else { |             } else { | ||||||
|                 return Value::fromMemoryReference(node.asIdentifier()); |                 return Value::fromMemoryReference(node.asIdentifier()); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         if (node.is(ValueNode::BOOL)) { | 
 | ||||||
|  |         if (node.getType() == ValueNode::BOOL) { | ||||||
|             return Value::fromBool(node.asBool()); |             return Value::fromBool(node.asBool()); | ||||||
|         } else if (node.is(ValueNode::INT)) { |         } else if (node.getType() == ValueNode::INT) { | ||||||
|             return Value::fromInt(node.asInt()); |             return Value::fromInt(node.asInt()); | ||||||
|         } else if (node.is(ValueNode::STRING)) { |         } else if (node.getType() == ValueNode::STRING) { | ||||||
|             return Value::fromString(node.asString()); |             return Value::fromString(node.asString()); | ||||||
|         } else if (node.is(ValueNode::NIL)) { |         } else if (node.getType() == ValueNode::NIL) { | ||||||
|             return Value::fromNull(); |             return Value::fromNull(); | ||||||
|         } |         } | ||||||
|         return Value::fromReference(node.asIdentifier(), Value::UNDEFINED); |         return Value::fromReference(node.asIdentifier(), Value::UNDEFINED); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|     Bus::BusType toType(BusNode::BusType type) { |     Bus::BusType toType(BusNode::BusType type) { | ||||||
|         if (type == BusNode::AUTOMATIC) { |         if (type == BusNode::AUTOMATIC) { | ||||||
|             return Bus::AUTOMATIC; |             return Bus::AUTOMATIC; | ||||||
| @ -108,6 +110,7 @@ namespace domain { | |||||||
|         return Bus::REGULAR; |         return Bus::REGULAR; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|     Pin::PinType toType(PinNode::PinType type) { |     Pin::PinType toType(PinNode::PinType type) { | ||||||
|         if (type == PinNode::IN) { |         if (type == PinNode::IN) { | ||||||
|             return Pin::IN; |             return Pin::IN; | ||||||
| @ -117,6 +120,14 @@ namespace domain { | |||||||
|         return Pin::IN_OUT; |         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) { |     Popup::PopupType toType(PopupNode::PopupType type) { | ||||||
|         if (type == PopupNode::AUTOMATIC) { |         if (type == PopupNode::AUTOMATIC) { | ||||||
|             return Popup::AUTOMATIC; |             return Popup::AUTOMATIC; | ||||||
| @ -124,11 +135,6 @@ namespace domain { | |||||||
|         return Popup::ON_DEMAND; |         return Popup::ON_DEMAND; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     /***********************************************************************
 |  | ||||||
|      *                       SCHEMA CREATOR                                * |  | ||||||
|      ***********************************************************************/ |  | ||||||
| 
 |  | ||||||
|     SchemaCreator::SchemaCreator(std::vector<FunctionValidator *> validators) |     SchemaCreator::SchemaCreator(std::vector<FunctionValidator *> validators) | ||||||
|             : validators(std::move(validators)) {} |             : validators(std::move(validators)) {} | ||||||
| 
 | 
 | ||||||
| @ -153,6 +159,7 @@ namespace domain { | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         header = node.header ? node.header->asString() : ""; |         header = node.header ? node.header->asString() : ""; | ||||||
|  | 
 | ||||||
|         libraryInfo = node.libraryInfo ? node.libraryInfo->asString() : ""; |         libraryInfo = node.libraryInfo ? node.libraryInfo->asString() : ""; | ||||||
| 
 | 
 | ||||||
|         for (auto &as: node.addressSpaces) { |         for (auto &as: node.addressSpaces) { | ||||||
| @ -194,16 +201,12 @@ namespace domain { | |||||||
|         } else { |         } else { | ||||||
|             return nullopt; |             return nullopt; | ||||||
|         } |         } | ||||||
|  | 
 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     std::optional<Bus> SchemaCreator::loadBus(BusNode node) { |     std::optional<Bus> SchemaCreator::loadBus(BusNode node) { | ||||||
|         std::string busName = node.name.value; |         std::string busName = node.name.value; | ||||||
| 
 | 
 | ||||||
|         std::optional<std::string> displayName = nullopt; |  | ||||||
|         if(node.displayName.has_value()) { |  | ||||||
|             displayName = node.displayName->asString(); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         if (!node.instanceName) { |         if (!node.instanceName) { | ||||||
|             errors.emplace_back(node.span, "missing @instanceName"); |             errors.emplace_back(node.span, "missing @instanceName"); | ||||||
|             return nullopt; |             return nullopt; | ||||||
| @ -266,15 +269,16 @@ namespace domain { | |||||||
|             return nullopt; |             return nullopt; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         return Bus(busName, displayName, instanceName, tooltip, type, count, wires, displayBus); |         return Bus(busName, instanceName, tooltip, type, count, wires, displayBus); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|     std::optional<AddressSpace> SchemaCreator::loadAddressSpace(AddressSpaceNode node) { |     std::optional<AddressSpace> SchemaCreator::loadAddressSpace(AddressSpaceNode node) { | ||||||
|         return AddressSpace(node.name.value, node.range.first.value, node.range.second.value); |         return AddressSpace(node.name.value, node.start.value, node.end.value); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     std::optional<Connection> SchemaCreator::loadConnection(ConnectionNode node) { |     std::optional<Connection> SchemaCreator::loadConnection(ConnectionNode node) { | ||||||
|         push(ComdelContext("connection", false, true, false)); |         push(ComdelContext("connection", false, true, false, false)); | ||||||
| 
 | 
 | ||||||
|         std::string bus = node.bus.value; |         std::string bus = node.bus.value; | ||||||
|         auto busInstance = getBus(bus); |         auto busInstance = getBus(bus); | ||||||
| @ -345,12 +349,10 @@ namespace domain { | |||||||
| 
 | 
 | ||||||
|             if (!node.second.has_value()) { |             if (!node.second.has_value()) { | ||||||
|                 errors.emplace_back(node.span, "missing second component"); |                 errors.emplace_back(node.span, "missing second component"); | ||||||
|                 return nullopt; |  | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             ConnectionComponent second{node.second->component.value, node.second->pin.value}; |             ConnectionComponent second{node.second->component.value, node.second->pin.value}; | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|             auto firstComponentInstance = getComponentPin(first.component, first.pin); |             auto firstComponentInstance = getComponentPin(first.component, first.pin); | ||||||
|             if (!firstComponentInstance) { |             if (!firstComponentInstance) { | ||||||
|                 errors.emplace_back(node.span, "pin does not exist"); |                 errors.emplace_back(node.span, "pin does not exist"); | ||||||
| @ -407,10 +409,7 @@ namespace domain { | |||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if(node.secondWires->empty()) { | 
 | ||||||
|                 errors.emplace_back(node.span, "missing second @wires definition"); |  | ||||||
|                 return nullopt; |  | ||||||
|             } |  | ||||||
|             std::vector<Value> secondWires; |             std::vector<Value> secondWires; | ||||||
|             for (auto &secondWire: *node.secondWires) { |             for (auto &secondWire: *node.secondWires) { | ||||||
|                 if (secondWire.is(ValueNode::NIL)) { |                 if (secondWire.is(ValueNode::NIL)) { | ||||||
| @ -454,6 +453,7 @@ namespace domain { | |||||||
|                     attributes[1].setPupup(popup); |                     attributes[1].setPupup(popup); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  | 
 | ||||||
|             pop(); |             pop(); | ||||||
| 
 | 
 | ||||||
|             return Connection(first, second, bus, attributes, firstWires, secondWires); |             return Connection(first, second, bus, attributes, firstWires, secondWires); | ||||||
| @ -465,15 +465,10 @@ namespace domain { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     std::optional<Component> SchemaCreator::loadComponent(ComponentNode node) { |     std::optional<Component> SchemaCreator::loadComponent(ComponentNode node) { | ||||||
|         push(ComdelContext(node.name.value, true, false, false)); |         push(ComdelContext(node.name.value, true, false, false, false)); | ||||||
| 
 | 
 | ||||||
|         std::string componentName = node.name.value; |         std::string componentName = node.name.value; | ||||||
| 
 | 
 | ||||||
|         std::optional<std::string> displayName = nullopt; |  | ||||||
|         if (node.displayName.has_value()) { |  | ||||||
|             displayName = node.displayName->asString(); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         if (!node.tooltip) { |         if (!node.tooltip) { | ||||||
|             errors.emplace_back(node.span, "missing @tooltip"); |             errors.emplace_back(node.span, "missing @tooltip"); | ||||||
|             pop(); |             pop(); | ||||||
| @ -550,7 +545,7 @@ namespace domain { | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         pop(); |         pop(); | ||||||
|         return Component(componentName, displayName, tooltip, source, type, rules, instanceName, count, *display, pins, attributes); |         return Component(componentName, tooltip, source, type, rules, instanceName, count, *display, pins, attributes); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     std::optional<Wire> SchemaCreator::loadWire(WireNode node) { |     std::optional<Wire> SchemaCreator::loadWire(WireNode node) { | ||||||
| @ -589,10 +584,12 @@ namespace domain { | |||||||
|         } |         } | ||||||
|         ui::Pin displayPin = *display->getItems()[0].pin; |         ui::Pin displayPin = *display->getItems()[0].pin; | ||||||
| 
 | 
 | ||||||
|         std::optional<std::string> connection = std::nullopt; | 
 | ||||||
|         if (node.connection) { |         if (!node.connection) { | ||||||
|             connection = node.connection->asString(); |             errors.emplace_back(node.span, "missing @connection"); | ||||||
|  |             return nullopt; | ||||||
|         } |         } | ||||||
|  |         auto connection = loadPinConnection(*node.connection); | ||||||
| 
 | 
 | ||||||
|         std::optional<std::vector<Value>> wiresOpt = std::nullopt; |         std::optional<std::vector<Value>> wiresOpt = std::nullopt; | ||||||
|         if (node.wires.has_value()) { |         if (node.wires.has_value()) { | ||||||
| @ -613,81 +610,47 @@ namespace domain { | |||||||
|         return Pin(pinName, type, tooltip, connection, displayPin, wiresOpt); |         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::optional<Display> SchemaCreator::loadDisplay(DisplayNode node) { | ||||||
|         std::vector<ui::Item> items; |         std::vector<ui::Item> items; | ||||||
|         for (auto &item: node.items) { |         for (auto &item: node.items) { | ||||||
|             ui::Item displayItem; |             ui::Item displayItem; | ||||||
|             std::string type = item.type.value; |             std::string type = item.type.value; | ||||||
| 
 | 
 | ||||||
|             auto fillColor = readColor(errors, item, "fillColor", Color(255, 255, 255, 255)); |             auto fillColor = item.asColor(&errors, "fillColor", Color(255, 255, 255, 255)); | ||||||
|             auto lineColor = readColor(errors, item, "lineColor", Color(0, 0, 0, 255)); |             auto lineColor = item.asColor(&errors, "lineColor", Color(0, 0, 0, 255)); | ||||||
| 
 | 
 | ||||||
|             if (type == "text") { |             if (type == "text") { | ||||||
|                 long long int x, y, w, h; |                 long long int x, y, w, h; | ||||||
|                 std::string text; |                 std::string text; | ||||||
|                 auto color = readColor(errors, item, "color", Color(0, 0, 0, 255)); |                 auto color = item.asColor(&errors, "color", Color(0, 0, 0, 255)); | ||||||
|                 x = readInt(errors, item, "x"); |                 x = item.asInt(&errors, "x"); | ||||||
|                 y = readInt(errors, item, "y"); |                 y = item.asInt(&errors, "y"); | ||||||
|                 w = readInt(errors, item, "w"); |                 w = item.asInt(&errors, "w"); | ||||||
|                 h = readInt(errors, item, "h"); |                 h = item.asInt(&errors, "h"); | ||||||
|                 text = readString(errors, item, "text"); |                 text = item.asString(&errors, "text"); | ||||||
|                 displayItem.text = ui::Text(x, y, w, h, text, color); |                 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") { |             } else if (type == "rect") { | ||||||
|                 long long int x, y, w, h; |                 long long int x, y, w, h; | ||||||
|                 x = readInt(errors, item, "x"); |                 x = item.asInt(&errors, "x"); | ||||||
|                 y = readInt(errors, item, "y"); |                 y = item.asInt(&errors, "y"); | ||||||
|                 w = readInt(errors, item, "w"); |                 w = item.asInt(&errors, "w"); | ||||||
|                 h = readInt(errors, item, "h"); |                 h = item.asInt(&errors, "h"); | ||||||
|                 displayItem.rect = ui::Rect(x, y, w, h, {lineColor, fillColor}); |                 displayItem.rect = ui::Rect(x, y, w, h, {lineColor, fillColor}); | ||||||
|             } else if (type == "line") { |             } else if (type == "line") { | ||||||
|                 long long int x1, y1, x2, y2; |                 long long int x1, y1, x2, y2; | ||||||
|                 x1 = readInt(errors, item, "x1"); |                 x1 = item.asInt(&errors, "x1"); | ||||||
|                 y1 = readInt(errors, item, "y1"); |                 y1 = item.asInt(&errors, "y1"); | ||||||
|                 x2 = readInt(errors, item, "x2"); |                 x2 = item.asInt(&errors, "x2"); | ||||||
|                 y2 = readInt(errors, item, "y2"); |                 y2 = item.asInt(&errors, "y2"); | ||||||
|                 displayItem.line = ui::Line(x1, y1, x2, y2, {lineColor, fillColor}); |                 displayItem.line = ui::Line(x1, y1, x2, y2, {lineColor, fillColor}); | ||||||
|             } else if (type == "pin") { |             } else if (type == "pin") { | ||||||
|                 long long int x, y, w, h; |                 long long int x, y, w, h; | ||||||
|                 x = readInt(errors, item, "x"); |                 x = item.asInt(&errors, "x"); | ||||||
|                 y = readInt(errors, item, "y"); |                 y = item.asInt(&errors, "y"); | ||||||
|                 w = readInt(errors, item, "w"); |                 w = item.asInt(&errors, "w"); | ||||||
|                 h = readInt(errors, item, "h"); |                 h = item.asInt(&errors, "h"); | ||||||
|                 std::string _orientation = readString(errors, item, "orientation", "bottom"); |                 std::string _orientation = item.asString(&errors, "orientation", "bottom"); | ||||||
|                 std::string _pinType = readString(errors, item, "type", "out"); |                 std::string _pinType = item.asString(&errors, "type", "out"); | ||||||
| 
 | 
 | ||||||
|                 ui::PinOrientation orientation; |                 ui::PinOrientation orientation; | ||||||
|                 if (_orientation == "left") { |                 if (_orientation == "left") { | ||||||
| @ -716,11 +679,11 @@ namespace domain { | |||||||
|                 displayItem.pin = ui::Pin(x, y, w, h, orientation, pinType, {lineColor, fillColor}); |                 displayItem.pin = ui::Pin(x, y, w, h, orientation, pinType, {lineColor, fillColor}); | ||||||
|             } else if (type == "bus") { |             } else if (type == "bus") { | ||||||
|                 long long int x, y, w, h; |                 long long int x, y, w, h; | ||||||
|                 x = readInt(errors, item, "x"); |                 x = item.asInt(&errors, "x"); | ||||||
|                 y = readInt(errors, item, "y"); |                 y = item.asInt(&errors, "y"); | ||||||
|                 w = readInt(errors, item, "w"); |                 w = item.asInt(&errors, "w"); | ||||||
|                 h = readInt(errors, item, "h"); |                 h = item.asInt(&errors, "h"); | ||||||
|                 std::string _orientation = readString(errors, item, "orientation", "bottom"); |                 std::string _orientation = item.asString(&errors, "orientation", "bottom"); | ||||||
| 
 | 
 | ||||||
|                 ui::BusOrientation orientation; |                 ui::BusOrientation orientation; | ||||||
|                 if (_orientation == "horizontal") { |                 if (_orientation == "horizontal") { | ||||||
| @ -740,15 +703,16 @@ namespace domain { | |||||||
|         return Display(items); |         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::optional<Attribute> SchemaCreator::loadAttribute(AttributeNode node) { | ||||||
|         std::string name = node.name.value; |         std::string name = node.name.value; | ||||||
|         pushAdditional(name); |         pushAdditional(name); | ||||||
| 
 |  | ||||||
|         std::optional<std::string> displayName = nullopt; |  | ||||||
|         if (node.displayName.has_value()) { |  | ||||||
|             displayName = node.displayName->asString(); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         Value value; |         Value value; | ||||||
| 
 | 
 | ||||||
|         if (current().inComponent) { |         if (current().inComponent) { | ||||||
| @ -782,7 +746,7 @@ namespace domain { | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         current().attributes.emplace_back(name, nullopt, value); |         current().attributes.emplace_back(name, value); | ||||||
| 
 | 
 | ||||||
|         std::optional<Popup> popup; |         std::optional<Popup> popup; | ||||||
|         if (node.popup) { |         if (node.popup) { | ||||||
| @ -790,7 +754,7 @@ namespace domain { | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         pop(); |         pop(); | ||||||
|         return Attribute(name, displayName, value, popup); |         return Attribute(name, value, popup); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     std::optional<Popup> SchemaCreator::loadPopup(PopupNode node, std::string name, Value::ValueType type) { |     std::optional<Popup> SchemaCreator::loadPopup(PopupNode node, std::string name, Value::ValueType type) { | ||||||
| @ -799,7 +763,7 @@ namespace domain { | |||||||
|         pushAdditional(name); |         pushAdditional(name); | ||||||
| 
 | 
 | ||||||
|         current().attributes.clear(); |         current().attributes.clear(); | ||||||
|         current().attributes.emplace_back(name, nullopt, Value::ofType(type)); |         current().attributes.emplace_back(name, Value::ofType(type)); | ||||||
| 
 | 
 | ||||||
|         if (!node.title) { |         if (!node.title) { | ||||||
|             errors.emplace_back(node.span, "missing @title"); |             errors.emplace_back(node.span, "missing @title"); | ||||||
| @ -882,7 +846,7 @@ namespace domain { | |||||||
|             if (validator->getName() == function) { |             if (validator->getName() == function) { | ||||||
|                 if (validator->getSignature().size() == node.params.size()) { |                 if (validator->getSignature().size() == node.params.size()) { | ||||||
|                     std::vector<Value> params; |                     std::vector<Value> params; | ||||||
|                     for (unsigned int j = 0; j < validator->getSignature().size(); j++) { |                     for (uint j = 0; j < validator->getSignature().size(); j++) { | ||||||
|                         bool exists = false; |                         bool exists = false; | ||||||
|                         auto type = toType(node.params[j]); |                         auto type = toType(node.params[j]); | ||||||
|                         if (type.getType() == Value::UNDEFINED) { |                         if (type.getType() == Value::UNDEFINED) { | ||||||
| @ -1034,6 +998,7 @@ namespace domain { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     shared_ptr<ComponentInstance> SchemaCreator::loadComponentInstance(InstanceNode instance, Library &library) { |     shared_ptr<ComponentInstance> SchemaCreator::loadComponentInstance(InstanceNode instance, Library &library) { | ||||||
|  | 
 | ||||||
|         auto componentInstanceName = instance.name.value; |         auto componentInstanceName = instance.name.value; | ||||||
|         auto position = std::make_pair(instance.position->first.value, instance.position->second.value); |         auto position = std::make_pair(instance.position->first.value, instance.position->second.value); | ||||||
| 
 | 
 | ||||||
| @ -1056,7 +1021,7 @@ namespace domain { | |||||||
|                 if (std::count_if(attributes.begin(), attributes.end(), |                 if (std::count_if(attributes.begin(), attributes.end(), | ||||||
|                                   [&attr](InstanceAttribute &attribute) { return attr.getName() == attribute.name; }) == |                                   [&attr](InstanceAttribute &attribute) { return attr.getName() == attribute.name; }) == | ||||||
|                     0) { |                     0) { | ||||||
|                     errors.emplace_back(SourceError(instance.span, "missing attribute '" + attr.getDisplayName() + "'")); |                     errors.emplace_back(SourceError(instance.span, "missing attribute '" + attr.getName() + "'")); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| @ -1090,7 +1055,7 @@ namespace domain { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     std::optional<Attribute> SchemaCreator::createMemoryAttribute() { |     std::optional<Attribute> SchemaCreator::createMemoryAttribute() { | ||||||
|         return Attribute("_memory", nullopt, Value::fromMemoryReference(std::nullopt), createMemoryPopup()); |         return Attribute("_memory", Value::fromMemoryReference(std::nullopt), createMemoryPopup()); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     std::optional<Popup> SchemaCreator::createMemoryPopup() { |     std::optional<Popup> SchemaCreator::createMemoryPopup() { | ||||||
| @ -1138,7 +1103,7 @@ namespace domain { | |||||||
|             this->context.push_back(current()); |             this->context.push_back(current()); | ||||||
|             current().name = name; |             current().name = name; | ||||||
|         } else { |         } else { | ||||||
|             ComdelContext con(name, false, false, false); |             ComdelContext con(name, false, false, false, false); | ||||||
|             push(con); |             push(con); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -13,7 +13,6 @@ | |||||||
| 
 | 
 | ||||||
| namespace domain { | namespace domain { | ||||||
| 
 | 
 | ||||||
|     /** Context used for loading model */ |  | ||||||
|     struct ComdelContext { |     struct ComdelContext { | ||||||
|         std::vector<Attribute> attributes; |         std::vector<Attribute> attributes; | ||||||
|         std::vector<std::string> wires; |         std::vector<std::string> wires; | ||||||
| @ -21,8 +20,9 @@ namespace domain { | |||||||
|         bool inComponent; |         bool inComponent; | ||||||
|         bool inConnection; |         bool inConnection; | ||||||
|         bool inSingleAutomaticConnection; |         bool inSingleAutomaticConnection; | ||||||
|  |         bool inBus; | ||||||
| 
 | 
 | ||||||
|         ComdelContext(std::string name, bool inComponent, bool inConnection, bool inSingleAutomaticConnection); |         ComdelContext(std::string name, bool inComponent, bool inConnection, bool inSingleAutomaticConnection, bool inBus); | ||||||
| 
 | 
 | ||||||
|         bool doesAttributeExists(std::string name, Value::ValueType type); |         bool doesAttributeExists(std::string name, Value::ValueType type); | ||||||
|         bool doesWireExists(std::string name); |         bool doesWireExists(std::string name); | ||||||
| @ -30,16 +30,6 @@ namespace domain { | |||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     class SchemaCreator { |     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::vector<ComdelContext> context; | ||||||
| 
 | 
 | ||||||
|         std::string name; |         std::string name; | ||||||
| @ -53,6 +43,7 @@ namespace domain { | |||||||
|         std::vector<Connection> connections; |         std::vector<Connection> connections; | ||||||
|         std::map<std::string, std::string> messages; |         std::map<std::string, std::string> messages; | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|         std::vector<SourceError> errors; |         std::vector<SourceError> errors; | ||||||
|         std::vector<FunctionValidator *> validators; |         std::vector<FunctionValidator *> validators; | ||||||
| 
 | 
 | ||||||
| @ -66,25 +57,35 @@ namespace domain { | |||||||
|         std::optional<Display> loadDisplay(DisplayNode node); |         std::optional<Display> loadDisplay(DisplayNode node); | ||||||
|         std::optional<Wire> loadWire(WireNode node); |         std::optional<Wire> loadWire(WireNode node); | ||||||
|         std::optional<Pin> loadPin(PinNode pins); |         std::optional<Pin> loadPin(PinNode pins); | ||||||
|  | 
 | ||||||
|  |         PinConnection loadPinConnection(PinConnectionNode node); | ||||||
|  | 
 | ||||||
|         std::optional<Connection> loadConnection(ConnectionNode node); |         std::optional<Connection> loadConnection(ConnectionNode node); | ||||||
|         std::optional<Bus> loadBus(BusNode node); |         std::optional<Bus> loadBus(BusNode node); | ||||||
|  | 
 | ||||||
|         std::shared_ptr<ComponentInstance> loadComponentInstance(InstanceNode instance, Library &library); |         std::shared_ptr<ComponentInstance> loadComponentInstance(InstanceNode instance, Library &library); | ||||||
|         std::shared_ptr<BusInstance> loadBusInstance(InstanceNode instance, Library &library); |         std::shared_ptr<BusInstance> loadBusInstance(InstanceNode instance, Library &library); | ||||||
| 
 | 
 | ||||||
|         /** Utility classes */ |  | ||||||
|         std::optional<Bus> getBus(std::string name); |         std::optional<Bus> getBus(std::string name); | ||||||
|         std::optional<Pin> getComponentPin(std::string name, std::string pin); |         std::optional<Pin> getComponentPin(std::string name, std::string pin); | ||||||
|         bool hasAddressSpace(std::string name); |         bool hasAddressSpace(std::string name); | ||||||
| 
 | 
 | ||||||
|  |         void push(ComdelContext context); | ||||||
|  |         void pushAdditional(std::string name); | ||||||
|  |         ComdelContext ¤t(); | ||||||
|  |         void pop(); | ||||||
|  | 
 | ||||||
|         std::optional<Attribute> createMemoryAttribute(); |         std::optional<Attribute> createMemoryAttribute(); | ||||||
|         vector<Enumeration> createWireEnumeration(vector<Value> enumeration); |         vector<Enumeration> createWireEnumeration(vector<Value> enumeration); | ||||||
|         std::optional<Popup> createMemoryPopup(); |         std::optional<Popup> createMemoryPopup(); | ||||||
| 
 | 
 | ||||||
|         /** Context stack operations */ |     public: | ||||||
|         void push(ComdelContext context); |         explicit SchemaCreator(std::vector<FunctionValidator *> validators); | ||||||
|         void pushAdditional(std::string name); | 
 | ||||||
|         ComdelContext ¤t(); |         std::vector<SourceError> getErrors(); | ||||||
|         void pop(); | 
 | ||||||
|  |         std::optional<Library> loadLibrary(LibraryNode node); | ||||||
|  |         Schema *loadSchema(SchemaNode node, Library &library); | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
| } // namespace domain
 | } // namespace domain
 | ||||||
|  | |||||||
| @ -1,7 +1,6 @@ | |||||||
| #include "value.h" | #include "value.h" | ||||||
| 
 | 
 | ||||||
| #include <string> | #include <string> | ||||||
| #include <stdexcept> |  | ||||||
| 
 | 
 | ||||||
| namespace domain { | namespace domain { | ||||||
| 
 | 
 | ||||||
| @ -45,58 +44,32 @@ namespace domain { | |||||||
|         return type == _type; |         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() { |     long long Value::asInt() { | ||||||
|         if (isType(Value::INT)) { |         if (isType(Value::INT)) { | ||||||
|             return intValue; |             return intValue; | ||||||
|         } |         } | ||||||
|         throw std::runtime_error("expected 'int' but value contains '" + getTypename() + "'"); |         throw std::exception(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     std::string Value::asString() { |     std::string Value::asString() { | ||||||
|         if (isType(Value::STRING)) { |         if (isType(Value::STRING)) { | ||||||
|             return stringValue; |             return stringValue; | ||||||
|         } |         } | ||||||
|         throw std::runtime_error("expected 'string' but value contains '" + getTypename() + "'"); |         throw std::exception(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     bool Value::asBool() { |     bool Value::asBool() { | ||||||
|         if (isType(Value::BOOL)) { |         if (isType(Value::BOOL)) { | ||||||
|             return boolValue; |             return boolValue; | ||||||
|         } |         } | ||||||
|         throw std::runtime_error("expected 'bool' but value contains '" + getTypename() + "'"); |         throw std::exception(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     AddressSpace Value::asAddressSpace() { |     AddressSpace Value::asAddressSpace() { | ||||||
|         if (isType(Value::ADDRESS_SPACE)) { |         if (isType(Value::ADDRESS_SPACE)) { | ||||||
|             return *addressSpace; |             return *addressSpace; | ||||||
|         } |         } | ||||||
|         throw std::runtime_error("expected 'address space' but value contains '" + getTypename() + "'"); |         throw std::exception(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     std::string Value::asReference() { |     std::string Value::asReference() { | ||||||
| @ -104,7 +77,7 @@ namespace domain { | |||||||
|             isType(Value::ATTRIBUTE_REFERENCE) || isType(Value::UNDEFINED)) { |             isType(Value::ATTRIBUTE_REFERENCE) || isType(Value::UNDEFINED)) { | ||||||
|             return reference; |             return reference; | ||||||
|         } |         } | ||||||
|         throw std::runtime_error("expected 'reference' but value contains '" + getTypename() + "'"); |         throw std::exception(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     std::optional<std::string> Value::asMemoryReference() { |     std::optional<std::string> Value::asMemoryReference() { | ||||||
| @ -119,33 +92,29 @@ namespace domain { | |||||||
|     void Value::setInt(long long value) { |     void Value::setInt(long long value) { | ||||||
|         if (isType(Value::INT)) { |         if (isType(Value::INT)) { | ||||||
|             this->intValue = value; |             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) { |     void Value::setString(std::string value) { | ||||||
|         if (isType(Value::STRING)) { |         if (isType(Value::STRING)) { | ||||||
|             this->stringValue = value; |             this->stringValue = value; | ||||||
|         } else { |  | ||||||
|             throw std::runtime_error("expected to set 'string' but value contains '" + getTypename() + "'"); |  | ||||||
|         } |         } | ||||||
|  |         throw std::exception(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void Value::setBool(bool value) { |     void Value::setBool(bool value) { | ||||||
|         if (isType(Value::BOOL)) { |         if (isType(Value::BOOL)) { | ||||||
|             this->boolValue = value; |             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) { |     void Value::setReference(std::string value) { | ||||||
|         if (isType(Value::WIRE_REFERENCE)) { |         if (isType(Value::WIRE_REFERENCE)) { | ||||||
|             this->reference = value; |             this->reference = value; | ||||||
|         } else { |  | ||||||
|             throw std::runtime_error("expected to set 'wire' but value contains '" + getTypename() + "'"); |  | ||||||
|         } |         } | ||||||
|  |         throw std::exception(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -218,7 +187,7 @@ namespace domain { | |||||||
|                     return "null"; |                     return "null"; | ||||||
|                 } |                 } | ||||||
|             default: |             default: | ||||||
|                 throw std::runtime_error("unknown type couldn't stringify '" + getTypename() + "'"); |                 throw std::exception(); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -228,31 +197,4 @@ namespace domain { | |||||||
|         return val; |         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
 | } // namespace domain
 | ||||||
|  | |||||||
| @ -43,10 +43,34 @@ namespace domain { | |||||||
| 
 | 
 | ||||||
|         Value() = default; |         Value() = default; | ||||||
| 
 | 
 | ||||||
|         bool equals(Value value); |         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; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         std::string string(); |         std::string string(); | ||||||
|         std::string getTypename(); |  | ||||||
| 
 | 
 | ||||||
|         ValueType getType(); |         ValueType getType(); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,5 +1,9 @@ | |||||||
| #include "ast_nodes.h" | #include "ast_nodes.h" | ||||||
| 
 | 
 | ||||||
|  | /*************************** AST NODE ********************************/ | ||||||
|  | 
 | ||||||
|  | AstNode::~AstNode() = default; | ||||||
|  | 
 | ||||||
| /*************************** NUMBER NODE ********************************/ | /*************************** NUMBER NODE ********************************/ | ||||||
| 
 | 
 | ||||||
| NumberNode::NumberNode(const std::string &expression) { | NumberNode::NumberNode(const std::string &expression) { | ||||||
| @ -37,11 +41,7 @@ std::string StringNode::asString() { | |||||||
| 
 | 
 | ||||||
| /*************************** VALUE NODE ********************************/ | /*************************** VALUE NODE ********************************/ | ||||||
| 
 | 
 | ||||||
| ValueNode::ValueType ValueNode::getType() const { | long long ValueNode::asInt() { | ||||||
|     return type.value; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| long long int ValueNode::asInt() { |  | ||||||
|     if (is(INT)) { |     if (is(INT)) { | ||||||
|         return intValue.value(); |         return intValue.value(); | ||||||
|     } |     } | ||||||
| @ -135,38 +135,3 @@ ValueNode ValueNode::ofMemory(std::optional<std::string> _value) { | |||||||
|     value.identifierValue = _value; |     value.identifierValue = _value; | ||||||
|     return 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,30 +8,28 @@ | |||||||
| #include <utility> | #include <utility> | ||||||
| #include <vector> | #include <vector> | ||||||
| 
 | 
 | ||||||
| /*****************************************************************************
 |  | ||||||
|  *                            BASE TYPES                                     * |  | ||||||
|  *****************************************************************************/ |  | ||||||
| 
 |  | ||||||
| /**
 | /**
 | ||||||
|  * AST base class, all AST node classes extend this class. Class contains basic |  * AST base class, all AST node classes extend this class. Class contains basic | ||||||
|  * information about nodes location in file. |  * information about nodes location in file. | ||||||
|  */ |  */ | ||||||
| class AstNode { | class AstNode { | ||||||
| public: | public: | ||||||
|     /** Contains information about where in source file given node is located */ | 
 | ||||||
|     Span span; |     Span span; | ||||||
| 
 | 
 | ||||||
|     AstNode() = default; |     AstNode() = default; | ||||||
|  | 
 | ||||||
|  |     virtual ~AstNode(); | ||||||
|  | 
 | ||||||
|     AstNode(AstNode &&) = default; |     AstNode(AstNode &&) = default; | ||||||
|  | 
 | ||||||
|     AstNode &operator=(AstNode &&) = default; |     AstNode &operator=(AstNode &&) = default; | ||||||
|  | 
 | ||||||
|     AstNode(const AstNode &) = default; |     AstNode(const AstNode &) = default; | ||||||
|  | 
 | ||||||
|     AstNode &operator=(const AstNode &) = default; |     AstNode &operator=(const AstNode &) = default; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /**
 |  | ||||||
|  * AST base enum class, |  | ||||||
|  * Used to represent AST enums |  | ||||||
|  * */ |  | ||||||
| template<typename T> | template<typename T> | ||||||
| struct EnumNode : public AstNode { | struct EnumNode : public AstNode { | ||||||
|     EnumNode() = default; |     EnumNode() = default; | ||||||
| @ -41,423 +39,284 @@ struct EnumNode : public AstNode { | |||||||
|     T value; |     T value; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /** Represents string
 |  | ||||||
|  * value contains quote-marks ("" or '' depending on string type) |  | ||||||
|  * */ |  | ||||||
| struct StringNode : public AstNode { | struct StringNode : public AstNode { | ||||||
|     /** String including quote-marks*/ |  | ||||||
|     std::string value; |     std::string value; | ||||||
| 
 | 
 | ||||||
|     /** Returns string without quote-marks */ |  | ||||||
|     std::string asString(); |     std::string asString(); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /** Represents identifiers */ |  | ||||||
| struct IdentifierNode : public AstNode { | struct IdentifierNode : public AstNode { | ||||||
|     std::string value; |     std::string value; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /** Represents all numbers used
 |  | ||||||
|  * All numbers must fit into long long int |  | ||||||
|  * */ |  | ||||||
| struct NumberNode : public AstNode { | struct NumberNode : public AstNode { | ||||||
|     long long int value = 0; |     long long int value; | ||||||
| 
 | 
 | ||||||
|     explicit NumberNode(const std::string &expression); |     explicit NumberNode(const std::string &expression); | ||||||
| 
 | 
 | ||||||
|     NumberNode() = default; |     NumberNode() : value(0) {} | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /** Represents color
 |  | ||||||
|  * color comes in two formats #RRGGBB or #RRGGBBAA (AA representing opacity) |  | ||||||
|  * */ |  | ||||||
| struct ColorNode : public AstNode { | struct ColorNode : public AstNode { | ||||||
|     Color color; |     Color color; | ||||||
| 
 | 
 | ||||||
|     explicit ColorNode(const std::string &expression); |     explicit ColorNode(const std::string &expression); | ||||||
| 
 | 
 | ||||||
|     ColorNode() = default; |     ColorNode() {} | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /** Represents ordered number pair */ | 
 | ||||||
| struct NumberPairNode : public AstNode { | struct CountNode : public AstNode { | ||||||
|     NumberNode first; |     NumberNode first; | ||||||
|     NumberNode second; |     NumberNode second; | ||||||
| 
 | 
 | ||||||
|     NumberPairNode(NumberNode first, NumberNode second) : first(first), second(second) {} |     CountNode(NumberNode first, NumberNode second) : first(std::move(first)), second(std::move(second)) {} | ||||||
| 
 | 
 | ||||||
|     NumberPairNode() = default; |     CountNode() = default; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | struct AddressSpaceNode : public AstNode { | ||||||
|  |     IdentifierNode name; | ||||||
|  |     NumberNode start; | ||||||
|  |     NumberNode end; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /** 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 { | class ValueNode : public AstNode { | ||||||
| public: | public: | ||||||
|     enum ValueType { |     enum ValueType { | ||||||
|         /** Stores same content as NumberNode */ |  | ||||||
|         INT, |         INT, | ||||||
|         /** Stores same content as StringNode */ |  | ||||||
|         STRING, |         STRING, | ||||||
|         /** Stores true or false */ |  | ||||||
|         BOOL, |         BOOL, | ||||||
|         /** Stores wire nam or null */ |  | ||||||
|         WIRE, |         WIRE, | ||||||
|         /** Default type assigned when node value is of type IdentifierNode and more correct type is assigned later */ |  | ||||||
|         IDENTIFIER, |         IDENTIFIER, | ||||||
|         /** Stores memory name or null */ |  | ||||||
|         MEMORY, |         MEMORY, | ||||||
|         /** Stores null */ |  | ||||||
|         NIL, |         NIL, | ||||||
|         /** Store same content as ColorNode */ |  | ||||||
|         COLOR, |         COLOR, | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     /** Type determines what is stored inside ValueNode */ |     EnumNode<ValueType> type; | ||||||
|     EnumNode<ValueType> type = EnumNode(NIL); |     std::optional<long long> intValue; | ||||||
|     /** All possible values for ValueNode are stored inside optionals */ |     std::optional<std::string> stringValue; | ||||||
|     std::optional<long long> intValue = std::nullopt; |     std::optional<bool> boolValue; | ||||||
|     std::optional<std::string> stringValue = std::nullopt; |     std::optional<std::string> identifierValue; | ||||||
|     std::optional<bool> boolValue = std::nullopt; |     std::optional<Color> colorValue; | ||||||
|     std::optional<std::string> identifierValue = std::nullopt; |  | ||||||
|     std::optional<Color> colorValue = std::nullopt; |  | ||||||
| 
 | 
 | ||||||
| public: | public: | ||||||
|     ValueNode() = default; |     ValueNode() = default; | ||||||
| 
 | 
 | ||||||
|     ValueType getType() const; |     ValueType getType() const { | ||||||
|  |         return type.value; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     long long asInt(); | ||||||
| 
 | 
 | ||||||
|     /** 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 asString(); | ||||||
|  | 
 | ||||||
|     std::string asIdentifier(); |     std::string asIdentifier(); | ||||||
|  | 
 | ||||||
|     Color asColor(); |     Color asColor(); | ||||||
|  | 
 | ||||||
|     bool asBool(); |     bool asBool(); | ||||||
| 
 | 
 | ||||||
|     /** Returns true if ValueNode is of given valueType */ |  | ||||||
|     bool is(ValueType valueType); |     bool is(ValueType valueType); | ||||||
| 
 | 
 | ||||||
|     /** Static methods used to generate ValueNodes of requested type */ |  | ||||||
|     static ValueNode ofBool(bool _value); |     static ValueNode ofBool(bool _value); | ||||||
|  | 
 | ||||||
|     static ValueNode ofInt(long long _value); |     static ValueNode ofInt(long long _value); | ||||||
|  | 
 | ||||||
|     static ValueNode ofString(std::string _value); |     static ValueNode ofString(std::string _value); | ||||||
|  | 
 | ||||||
|     static ValueNode ofIdentifier(std::string _value); |     static ValueNode ofIdentifier(std::string _value); | ||||||
|  | 
 | ||||||
|     static ValueNode ofMemory(std::optional<std::string> _value); |     static ValueNode ofMemory(std::optional<std::string> _value); | ||||||
|  | 
 | ||||||
|     static ValueNode ofNull(); |     static ValueNode ofNull(); | ||||||
|  | 
 | ||||||
|     static ValueNode ofColor(Color color); |     static ValueNode ofColor(Color color); | ||||||
|  | 
 | ||||||
|     static ValueNode ofWire(std::optional<std::string> _value); |     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 { | struct ConditionNode { | ||||||
|     bool negated; |     bool negated; | ||||||
|     IdentifierNode functionName; |     IdentifierNode functionName; | ||||||
|     std::vector<ValueNode> params; |     std::vector<ValueNode> params; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /** Represents action executed inside if statement
 | class ActionNode : public AstNode { | ||||||
|  * */ | public: | ||||||
| struct ActionNode : public AstNode { |  | ||||||
|     /** There are two types of action determined by action type */ |  | ||||||
|     enum ActionType { |     enum ActionType { | ||||||
|         /** Error actions represent invalid state and cause validation to fail */ |  | ||||||
|         ERROR, |         ERROR, | ||||||
|         /** Warning actions represent states that can cause issue when simulating
 |  | ||||||
|          * model but models created with it are still valid |  | ||||||
|          * */ |  | ||||||
|         WARNING |         WARNING | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     EnumNode<ActionType> type; |     EnumNode<ActionType> type; | ||||||
|     /** Message used if condition is fulfilled */ |  | ||||||
|     StringNode message; |     StringNode message; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /** If statements represents one validation check inside rule */ | 
 | ||||||
| struct IfStatementNode : public AstNode { | struct IfStatementNode : public AstNode { | ||||||
|     ConditionNode condition; |     ConditionNode condition; | ||||||
|     ActionNode action; |     ActionNode action; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | struct RuleNode : public AstNode { | ||||||
|  |     std::vector<IfStatementNode> statements; | ||||||
|  | }; | ||||||
| 
 | 
 | ||||||
| /*****************************************************************************
 | struct EnumerationNode : public AstNode { | ||||||
|  *                            ATTRIBUTE TYPES                                * |     StringNode key; | ||||||
|  *****************************************************************************/ |     ValueNode value; | ||||||
|  | }; | ||||||
| 
 | 
 | ||||||
| /** Represents popup dialog used to modified attribute inside which it is defined
 |  | ||||||
|  * */ |  | ||||||
| struct PopupNode : public AstNode { | struct PopupNode : public AstNode { | ||||||
|     /** Determines type of popup*/ |  | ||||||
|     enum PopupType { |     enum PopupType { | ||||||
|         /** Automatic popup is opened when component or connection containing it is defined */ |  | ||||||
|         AUTOMATIC, |         AUTOMATIC, | ||||||
|         /** On demand popups are opened on user request usually from context menus*/ |  | ||||||
|         ON_DEMAND |         ON_DEMAND | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     std::optional<EnumNode<PopupType>> type; |     std::optional<EnumNode<PopupType>> type; | ||||||
|     /** Title of popup */ |  | ||||||
|     std::optional<StringNode> title; |     std::optional<StringNode> title; | ||||||
|     /** Text of popup */ |  | ||||||
|     std::optional<StringNode> text; |     std::optional<StringNode> text; | ||||||
| 
 | 
 | ||||||
|     /** If popup contains an enumeration*/ |  | ||||||
|     bool enumerated; |     bool enumerated; | ||||||
|     std::vector<StringPropertyNode> enumeration; |     std::vector<EnumerationNode> enumeration; | ||||||
| 
 | 
 | ||||||
|     /** Validation rules for given popup */ |  | ||||||
|     std::vector<RuleNode> rules; |     std::vector<RuleNode> rules; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /** Represents component or connection attribute
 | struct PropertyNode : public AstNode { | ||||||
|  * Attributes are values that can programmatically be changed |     IdentifierNode key; | ||||||
|  * if popup is defined |     ValueNode value; | ||||||
|  * */ |  | ||||||
| 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 { | ||||||
|  *                            DISPLAY TYPES                                  * |     IdentifierNode type; | ||||||
|  *****************************************************************************/ |     std::vector<PropertyNode> values; | ||||||
| 
 | 
 | ||||||
| struct DisplayItemNode; |     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; | ||||||
|  |     } | ||||||
|  | }; | ||||||
| 
 | 
 | ||||||
| /** Represents how a component or bus is rendered
 |  | ||||||
|  * Display is made from an list of display items |  | ||||||
|  * */ |  | ||||||
| struct DisplayNode : public AstNode { | struct DisplayNode : public AstNode { | ||||||
|     std::vector<DisplayItemNode> items; |     std::vector<DisplayItemNode> items; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /** DisplayItem represents one rendered item
 | struct PinConnectionNode : public AstNode { | ||||||
|  * in source code items are defined similar to json objects |     enum ConnectionType { | ||||||
|  * eg. |         REQUIRED, | ||||||
|  * @code rect { |         OPTIONAL | ||||||
|  *  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; |  | ||||||
| 
 | 
 | ||||||
|     /** Returns value of requested property
 |     StringNode message; | ||||||
|      * If requested property doesn't exists default value is returned (eg. asInt is called but PropertyNode contains string) |     EnumNode<ConnectionType> type; | ||||||
|      * 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 { | struct PinNode : public AstNode { | ||||||
|     /** Determines pin type, pin types currently only affect how pins are rendered */ |  | ||||||
|     enum PinType { |     enum PinType { | ||||||
|         IN_OUT, |         IN_OUT, | ||||||
|         IN, |         IN, | ||||||
|         OUT |         OUT | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     /** Name of pin */ |  | ||||||
|     IdentifierNode name; |     IdentifierNode name; | ||||||
|     /** Type of pin */ |  | ||||||
|     EnumNode<PinType> type; |     EnumNode<PinType> type; | ||||||
|     /** Tooltip content displayed on hover over pin */ |  | ||||||
|     std::optional<StringNode> tooltip; |     std::optional<StringNode> tooltip; | ||||||
|     /** If present this means pin must be connected to another component or bus to create connection
 |     std::optional<PinConnectionNode> connection; | ||||||
|      * Connection contains error message shown |  | ||||||
|      * */ |  | ||||||
|     std::optional<StringNode> connection; |  | ||||||
|     /** Determines how the pin is displayed */ |  | ||||||
|     std::optional<DisplayNode> display; |     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; |     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 { | struct WireNode : public AstNode { | ||||||
|     /** Determines type of wires */ |  | ||||||
|     enum WireType { |     enum WireType { | ||||||
|         /** Generic wire */ |  | ||||||
|         WIRE, |         WIRE, | ||||||
|         /** wired_and can have multiple sources, that are ANDed together */ |  | ||||||
|         WIRED_AND, |         WIRED_AND, | ||||||
|         /** wired_and can have multiple sources, that are ORed together */ |  | ||||||
|         WIRED_OR, |         WIRED_OR, | ||||||
|         /** r_wire can remain unconnected */ |  | ||||||
|         R_WIRE |         R_WIRE | ||||||
|     }; |     }; | ||||||
|     EnumNode<WireType> type; |     EnumNode<WireType> type; | ||||||
|     /** Name of wire */ |  | ||||||
|     IdentifierNode name; |     IdentifierNode name; | ||||||
|     /** Number of bits inside of a wire */ |  | ||||||
|     NumberNode size; |     NumberNode size; | ||||||
| 
 | 
 | ||||||
|     /** If wire is visible or hidden, this determines how wires are generated in COMDEL */ |  | ||||||
|     bool hidden = false; |     bool hidden = false; | ||||||
| 
 | 
 | ||||||
|     /** If wire isn't connected to anything it is replaced with terminate with terminateWith value */ |     bool hasTerminateWith; | ||||||
|     bool hasTerminateWith = false; |  | ||||||
|     ValueNode terminateWith; |     ValueNode terminateWith; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /** Buses dont exist in COMDEL but they are useful
 | struct AttributeNode : public AstNode { | ||||||
|  * as they allow us to connect multiple COMDEL wires together |     ValueNode::ValueType type; | ||||||
|  * */ |  | ||||||
| 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; |     IdentifierNode name; | ||||||
|     /** Display name */ |     std::optional<ValueNode> defaultValue; | ||||||
|     std::optional<StringNode> displayName; |     std::optional<PopupNode> popup; | ||||||
|     /** 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 { | struct ConnectionComponentNode : public AstNode { | ||||||
|     IdentifierNode component; |     IdentifierNode component; | ||||||
|     IdentifierNode pin; |     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 { | struct ConnectionNode : public AstNode { | ||||||
|     ConnectionComponentNode first; |     ConnectionComponentNode first; | ||||||
|     std::optional<ConnectionComponentNode> second; |     std::optional<ConnectionComponentNode> second; | ||||||
| @ -465,22 +324,51 @@ struct ConnectionNode : public AstNode { | |||||||
|     IdentifierNode bus; |     IdentifierNode bus; | ||||||
|     std::vector<AttributeNode> attributes; |     std::vector<AttributeNode> attributes; | ||||||
| 
 | 
 | ||||||
|     /** If connection is of type component-component it contains two pairs of wires */ |  | ||||||
|     std::vector<ValueNode> firstWires; |     std::vector<ValueNode> firstWires; | ||||||
|     std::optional<std::vector<ValueNode>> secondWires; |     std::optional<std::vector<ValueNode>> secondWires; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /** LibraryNode represent library instance */ | 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; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct LibraryNode : public AstNode { | struct LibraryNode : public AstNode { | ||||||
|     /** Name of library */ |  | ||||||
|     std::optional<StringNode> name; |     std::optional<StringNode> name; | ||||||
|     /** Library info contains generic information about library */ |  | ||||||
|     std::optional<StringNode> libraryInfo; |     std::optional<StringNode> libraryInfo; | ||||||
|     /** Contains text that is added to top of COMDEL file */ |  | ||||||
|     std::optional<StringNode> header; |     std::optional<StringNode> header; | ||||||
|     /** Contains path to component directory */ |  | ||||||
|     std::optional<StringNode> componentDirectory; |     std::optional<StringNode> componentDirectory; | ||||||
|     /** Contains text that is added to top of System component in COMDEL file */ |  | ||||||
|     std::optional<StringNode> componentHeader; |     std::optional<StringNode> componentHeader; | ||||||
| 
 | 
 | ||||||
|     std::vector<AddressSpaceNode> addressSpaces; |     std::vector<AddressSpaceNode> addressSpaces; | ||||||
| @ -489,64 +377,46 @@ struct LibraryNode : public AstNode { | |||||||
|     std::vector<BusNode> buses; |     std::vector<BusNode> buses; | ||||||
|     std::vector<ConnectionNode> connections; |     std::vector<ConnectionNode> connections; | ||||||
| 
 | 
 | ||||||
|     /** Contains properties used to translate dialog and error messages */ |  | ||||||
|     std::vector<PropertyNode> messages; |     std::vector<PropertyNode> messages; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /*****************************************************************************
 | // SCHEMA models
 | ||||||
|  *                            LIBRARY TYPES                                  * |  | ||||||
|  *****************************************************************************/ |  | ||||||
| 
 |  | ||||||
| /** Represents instance of attribute in component or connection instance */ |  | ||||||
| struct InstanceAttributeNode : public AstNode { | struct InstanceAttributeNode : public AstNode { | ||||||
|     IdentifierNode name; |     IdentifierNode name; | ||||||
|     ValueNode value; |     ValueNode value; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /** Represents instance of a component or a bus */ |  | ||||||
| struct InstanceNode : public AstNode { | struct InstanceNode : public AstNode { | ||||||
|     /** Contains instance name */ |  | ||||||
|     IdentifierNode name; |     IdentifierNode name; | ||||||
|     /** Contains component name */ |  | ||||||
|     IdentifierNode component; |     IdentifierNode component; | ||||||
| 
 | 
 | ||||||
|     /** Contains position of component instance */ |     std::optional<CountNode> position; | ||||||
|     std::optional<NumberPairNode> position; |  | ||||||
|     std::vector<InstanceAttributeNode> attributes; |     std::vector<InstanceAttributeNode> attributes; | ||||||
| 
 | 
 | ||||||
|     /** Contains size of bus instances */ |  | ||||||
|     std::optional<NumberNode> size; |     std::optional<NumberNode> size; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /** Represents ComponentConnection of a selected instance */ | struct ConnectionComponentInstance : public AstNode { | ||||||
| struct ConnectionComponentInstanceNode : public AstNode { |  | ||||||
|     /** Name of component instance */ |  | ||||||
|     IdentifierNode instance; |     IdentifierNode instance; | ||||||
|     /** Name of pin */ |  | ||||||
|     IdentifierNode pin; |     IdentifierNode pin; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /** Represents Connection instance */ |  | ||||||
| struct ConnectionInstanceNode : public AstNode { | struct ConnectionInstanceNode : public AstNode { | ||||||
|     ConnectionComponentInstanceNode first; |     ConnectionComponentInstance first; | ||||||
|     std::optional<ConnectionComponentInstanceNode> second; |     std::optional<ConnectionComponentInstance> second; | ||||||
| 
 | 
 | ||||||
|     IdentifierNode bus; |     IdentifierNode bus; | ||||||
| 
 | 
 | ||||||
|     std::vector<InstanceAttributeNode> attributes; |     std::vector<InstanceAttributeNode> attributes; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /** Represent schema instance */ | 
 | ||||||
| struct SchemaNode : public AstNode { | struct SchemaNode : public AstNode { | ||||||
|     /** Contains path to library source */ |  | ||||||
|     std::optional<StringNode> source; |     std::optional<StringNode> source; | ||||||
| 
 | 
 | ||||||
|     /** Contains list of instances */ |  | ||||||
|     std::vector<InstanceNode> instances; |     std::vector<InstanceNode> instances; | ||||||
|     /** Contains list of connection */ |  | ||||||
|     std::vector<ConnectionInstanceNode> connections; |     std::vector<ConnectionInstanceNode> connections; | ||||||
| 
 | 
 | ||||||
|     /** Contains library */ |  | ||||||
|     std::optional<LibraryNode> library; |     std::optional<LibraryNode> library; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										5
									
								
								comdel/parser/color.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								comdel/parser/color.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | |||||||
|  | //
 | ||||||
|  | // Created by bbr on 12.06.22..
 | ||||||
|  | //
 | ||||||
|  | 
 | ||||||
|  | #include "color.h" | ||||||
| @ -7,12 +7,12 @@ | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| struct Color { | struct Color { | ||||||
|     unsigned char r = 0; |     unsigned char r; | ||||||
|     unsigned char g = 0; |     unsigned char g; | ||||||
|     unsigned char b = 0; |     unsigned char b; | ||||||
|     unsigned char a = 255; |     unsigned char a; | ||||||
| 
 | 
 | ||||||
|     Color() = default; |     Color(): r(0), g(0), b(0), a(0) {} | ||||||
| 
 | 
 | ||||||
|     Color(unsigned char r, unsigned char g, unsigned char b, unsigned char a = 0): r(r), g(g), b(b), a(a) {} |     Color(unsigned char r, unsigned char g, unsigned char b, unsigned char a = 0): r(r), g(g), b(b), a(a) {} | ||||||
| }; | }; | ||||||
|  | |||||||
| @ -11,14 +11,11 @@ | |||||||
| #include <string> | #include <string> | ||||||
| #include <vector> | #include <vector> | ||||||
| 
 | 
 | ||||||
| /** Contains results of tokenizing,
 |  | ||||||
|  * if errors isn't empty tokenizing has failed */ |  | ||||||
| struct LexerResult { | struct LexerResult { | ||||||
|     std::vector<Token> tokens; |     std::vector<Token> tokens; | ||||||
|     std::vector<SourceError> errors; |     std::vector<SourceError> errors; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /** Used to tokenize input string */ |  | ||||||
| class ComdelLexer { | class ComdelLexer { | ||||||
| 
 | 
 | ||||||
|     enum Radix { |     enum Radix { | ||||||
| @ -27,11 +24,9 @@ class ComdelLexer { | |||||||
|         HEX_NUMBER = 16 |         HEX_NUMBER = 16 | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     /** Source file */ |  | ||||||
|     std::string source; |     std::string source; | ||||||
|     std::vector<Token> tokens; |     std::vector<Token> tokens; | ||||||
|     std::vector<SourceError> errors; |     std::vector<SourceError> errors; | ||||||
|     /** Source file */ |  | ||||||
|     ParseContext *parseContext; |     ParseContext *parseContext; | ||||||
|     unsigned fileId; |     unsigned fileId; | ||||||
| 
 | 
 | ||||||
| @ -41,32 +36,34 @@ public: | |||||||
|     LexerResult tokenize(); |     LexerResult tokenize(); | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     /** Current parsing info */ |     void skipWhitespace(); | ||||||
|  | 
 | ||||||
|  |     unsigned takeNumberInRadix(Radix radix); | ||||||
|  | 
 | ||||||
|  |     unsigned takeHexColor(); | ||||||
|  | 
 | ||||||
|  |     bool digitIsValid(char ch, Radix radix); | ||||||
|  | 
 | ||||||
|  |     Radix takeRadix(); | ||||||
|  | 
 | ||||||
|  |     PResult<TokenType> nextTokenType(); | ||||||
|  | 
 | ||||||
|     Position tokenBegin; |     Position tokenBegin; | ||||||
|     Position position; |     Position position; | ||||||
|     char ch; |     char ch; | ||||||
| 
 | 
 | ||||||
|     /** Methods used to skip unused content */ |  | ||||||
|     void skipWhitespace(); |  | ||||||
|     void skipComment(); |     void skipComment(); | ||||||
|  | 
 | ||||||
|     bool skipMultilineComment(); |     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> takeString(); | ||||||
|  | 
 | ||||||
|     PResult<TokenType> takeRawString(); |     PResult<TokenType> takeRawString(); | ||||||
| 
 | 
 | ||||||
|  |     void bump(unsigned count = 1); | ||||||
|  | 
 | ||||||
|     char peek(); |     char peek(); | ||||||
| 
 | 
 | ||||||
|     /** Checks if we reached end of file */ |  | ||||||
|     bool eof(); |     bool eof(); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -42,20 +42,16 @@ private: | |||||||
| 
 | 
 | ||||||
|     Span &getPreviousSpan(); |     Span &getPreviousSpan(); | ||||||
| 
 | 
 | ||||||
|     /** Skips current token */ |  | ||||||
|     void bump(); |     void bump(); | ||||||
|     /** Checks if next token is of given type and if it is consumes it */ | 
 | ||||||
|     bool consume(TokenType tokenType); |     bool consume(TokenType tokenType); | ||||||
|     /** Checks if next token is of given type */ | 
 | ||||||
|     bool check(TokenType tokenType); |     bool check(TokenType tokenType); | ||||||
|     /** Skips until next keyword on same level
 | 
 | ||||||
|      * Used to continue parsing on error |  | ||||||
|      * */ |  | ||||||
|     void skipUntilNextKeyword(); |     void skipUntilNextKeyword(); | ||||||
|     /** Retuns current token */ | 
 | ||||||
|     Token ¤t(); |     Token ¤t(); | ||||||
| 
 | 
 | ||||||
|     /** Throws error of unexpected types */ |  | ||||||
|     [[nodiscard]] PError unexpected(); |     [[nodiscard]] PError unexpected(); | ||||||
| 
 | 
 | ||||||
|     template<typename T> |     template<typename T> | ||||||
| @ -67,45 +63,73 @@ private: | |||||||
| 
 | 
 | ||||||
|     Spanner getSpanner(); |     Spanner getSpanner(); | ||||||
| 
 | 
 | ||||||
|     /** Base types */ |     // used to parse library and schema
 | ||||||
|     PResult<StringNode> parseString(); |     PResult<StringNode> parseString(); | ||||||
|  | 
 | ||||||
|     PResult<ColorNode> parseColor(); |     PResult<ColorNode> parseColor(); | ||||||
|  | 
 | ||||||
|     PResult<IdentifierNode> parseIdentifier(); |     PResult<IdentifierNode> parseIdentifier(); | ||||||
|  | 
 | ||||||
|     PResult<NumberNode> parseNumber(); |     PResult<NumberNode> parseNumber(); | ||||||
|     PResult<NumberPairNode> parseNumberPair(); | 
 | ||||||
|  |     PResult<CountNode> parseCount(); | ||||||
|  | 
 | ||||||
|     PResult<PropertyNode> parseProperty(std::optional<TokenType> valueType); |     PResult<PropertyNode> parseProperty(std::optional<TokenType> valueType); | ||||||
|     PResult<StringPropertyNode> parseStringProperty(); | 
 | ||||||
|  |     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<ValueNode> parseValue(); |     PResult<ValueNode> parseValue(); | ||||||
| 
 | 
 | ||||||
|     /** Library types */ |     // used to parse schema
 | ||||||
|     PResult<ValueNode> parseConnectionWire(); |     PResult<CountNode> parsePosition(); | ||||||
|     PResult<ComponentNode> parseComponent(); | 
 | ||||||
|  |     PResult<InstanceNode> parseInstance(); | ||||||
|  | 
 | ||||||
|  |     PResult<InstanceAttributeNode> parseInstanceAttribute(); | ||||||
|  | 
 | ||||||
|  |     PResult<ConnectionInstanceNode> parseConnectionInstance(); | ||||||
|  | 
 | ||||||
|     PResult<EnumNode<ComponentNode::ComponentType>> parseComponentType(); |     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<BusNode::BusType>> parseBusType(); | ||||||
| 
 | 
 | ||||||
|     /** Schema types */ |     PResult<EnumNode<PinConnectionNode::ConnectionType>> parseConnectionType(); | ||||||
|     PResult<InstanceNode> parseInstance(); |  | ||||||
|     PResult<InstanceAttributeNode> parseInstanceAttribute(); |  | ||||||
|     PResult<ConnectionInstanceNode> parseConnectionInstance(); |  | ||||||
|     PResult<ConnectionComponentInstanceNode> parseConnectionComponentInstance(); |  | ||||||
| 
 | 
 | ||||||
| public: | public: | ||||||
|     explicit ComdelParser(std::vector<Token> tokens); |     explicit ComdelParser(std::vector<Token> tokens); | ||||||
| 
 | 
 | ||||||
|     std::optional<SchemaNode> parseSchema(); |     std::optional<SchemaNode> parseSchema(); | ||||||
|  | 
 | ||||||
|     std::optional<LibraryNode> parseLibrary(); |     std::optional<LibraryNode> parseLibrary(); | ||||||
|  | 
 | ||||||
|     const std::vector<SourceError> &getErrors(); |     const std::vector<SourceError> &getErrors(); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -7,7 +7,6 @@ | |||||||
| #include <string> | #include <string> | ||||||
| #include <vector> | #include <vector> | ||||||
| 
 | 
 | ||||||
| /*** Represent source file */ |  | ||||||
| class SourceFile { | class SourceFile { | ||||||
|     std::string fileName; |     std::string fileName; | ||||||
|     std::string source; |     std::string source; | ||||||
| @ -23,7 +22,7 @@ public: | |||||||
|     void addLineOffset(unsigned offset); |     void addLineOffset(unsigned offset); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /*** Represent parsing context */ | 
 | ||||||
| class ParseContext { | class ParseContext { | ||||||
|     std::string applicationDir; |     std::string applicationDir; | ||||||
|     std::vector<SourceFile> fileMap; |     std::vector<SourceFile> fileMap; | ||||||
|  | |||||||
| @ -101,7 +101,7 @@ enum class TokenType { | |||||||
|     KW_SCHEMA, |     KW_SCHEMA, | ||||||
|     KW_POSITION, |     KW_POSITION, | ||||||
|     KW_SIZE, |     KW_SIZE, | ||||||
|     KW_DISPLAY_NAME, |     KW_UNKNOWN, | ||||||
| 
 | 
 | ||||||
|     // TYPES
 |     // TYPES
 | ||||||
|     INT_TYPE, |     INT_TYPE, | ||||||
|  | |||||||
| @ -106,7 +106,6 @@ TokenTables::TokenTables() { | |||||||
|     add(TokenType::KW_SCHEMA, "@schema", TOKENIZABLE | KEYWORD_NAME); |     add(TokenType::KW_SCHEMA, "@schema", TOKENIZABLE | KEYWORD_NAME); | ||||||
|     add(TokenType::KW_POSITION, "@position", TOKENIZABLE | KEYWORD_NAME); |     add(TokenType::KW_POSITION, "@position", TOKENIZABLE | KEYWORD_NAME); | ||||||
|     add(TokenType::KW_SIZE, "@size", TOKENIZABLE | KEYWORD_NAME); |     add(TokenType::KW_SIZE, "@size", TOKENIZABLE | KEYWORD_NAME); | ||||||
|     add(TokenType::KW_DISPLAY_NAME, "@displayName", TOKENIZABLE | KEYWORD_NAME); |  | ||||||
| 
 | 
 | ||||||
|     // All types
 |     // All types
 | ||||||
|     add(TokenType::INT_TYPE, "int", TOKENIZABLE); |     add(TokenType::INT_TYPE, "int", TOKENIZABLE); | ||||||
|  | |||||||
										
											Binary file not shown.
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -1,233 +0,0 @@ | |||||||
| @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 |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| @ -1,248 +0,0 @@ | |||||||
| 
 |  | ||||||
| \\ 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;} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| @ -1,28 +0,0 @@ | |||||||
| @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) { |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| @ -1,67 +0,0 @@ | |||||||
| 
 |  | ||||||
| // 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,6 +1,5 @@ | |||||||
| // Version 0.0.1 | // Version 0.0.1 | ||||||
| #include "libraries\frisc\vjezba1\FRISC.cdl" | #include "libraries\frisc\vjezba1\FRISC.cdl" | ||||||
| #include "libraries\frisc\vjezba1\dma.cdl" |  | ||||||
| #include "libraries\frisc\vjezba1\memory.cdl" | #include "libraries\frisc\vjezba1\memory.cdl" | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -24,43 +23,31 @@ component System | |||||||
| 	wire --BACK; | 	wire --BACK; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 	//PIOSabirnica |  | ||||||
| 	wire<8> PIO_DATA; |  | ||||||
| 	wire READY; |  | ||||||
| 	wire STROBE; |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 	//directRam | 	//directRam | ||||||
| 	wire INT; | 	wire INT; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 	// components -------------------------------------------- | 	// components -------------------------------------------- | ||||||
| 	subcomponent Memorija memorija<false, 1, 1024, 8, 0>(ADR, DATA, READ, WRITE, SIZE, WAIT, INT, *, *, *); | 	subcomponent Memorija memorija<false, 1, 65536, 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 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 { | 	display { | ||||||
| 		component { x: -104; y: -102; ref: "procesor"; } | 		component { x: -377; y: -302; ref: "procesor"; } | ||||||
| 		component { x: 39; y: 199; ref: "memorija"; } | 		component { x: -56; y: -80; ref: "memorija"; } | ||||||
| 		component { x: -352; y: 13; ref: "dma"; } |  | ||||||
| 
 | 
 | ||||||
| 		// glavnaSabirnica bus | 		// glavnaSabirnica bus | ||||||
| 
 | 
 | ||||||
| 		rectangle { | 		rectangle { | ||||||
| 			x: -106; y: 80; | 			x: -377; y: -106; | ||||||
| 			w: 100; h: 20; | 			w: 100; h: 20; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 		// PIOSabirnica bus |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 		// directRam bus | 		// directRam bus | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 		line {x1:-54; y1:14; x2:-55; y2:90;} | 		line {x1:-6; y1:-96; x2:-326; y2:-95;} | ||||||
| 		line {x1:89; y1:183; x2:-55; y2:90;} | 		line {x1:-327; y1:-186; x2:-326; y2:-95;} | ||||||
| 		line {x1:-236; y1:51; x2:-55; y2:90;} | 		line {x1:-72; y1:-52; x2:-261; y2:-252;} | ||||||
| 		line {x1:23; y1:227; x2:12; y2:-52;} |  | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| @ -17,7 +17,6 @@ | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @component FRISC processor { | @component FRISC processor { | ||||||
|     @displayName "Frisc procesor" |  | ||||||
|     @instanceName procesor |     @instanceName procesor | ||||||
|     @tooltip "Procesor FRISC, mora postojati jedan" |     @tooltip "Procesor FRISC, mora postojati jedan" | ||||||
|     @count (1, 1) |     @count (1, 1) | ||||||
| @ -61,7 +60,7 @@ | |||||||
|     } |     } | ||||||
|     @pin glavniPin in { |     @pin glavniPin in { | ||||||
|         @tooltip "pin za spajanje na glavnu sabirnicu" |         @tooltip "pin za spajanje na glavnu sabirnicu" | ||||||
|         @connection "COMDEL se ne može stvoriti. FRISC nije spojen na sabirnicu" |         @connection required("COMDEL se ne može stvoriti. FRISC nije spojen na sabirnicu") | ||||||
|         @display { |         @display { | ||||||
|             pin { |             pin { | ||||||
|                 x: 42; y: 100; w: 16; h:16; |                 x: 42; y: 100; w: 16; h:16; | ||||||
| @ -73,6 +72,7 @@ | |||||||
| 
 | 
 | ||||||
|     @pin memDirect inOut { |     @pin memDirect inOut { | ||||||
|             @tooltip "pin za izravno spajanje na RAM" |             @tooltip "pin za izravno spajanje na RAM" | ||||||
|  |             @connection optional("COMDEL se ne može stvoriti. FRISC nije spojen na sabirnicu") | ||||||
|             @display { |             @display { | ||||||
|                 pin { |                 pin { | ||||||
|                     x: 100; y: 42; w: 16; h:16; |                     x: 100; y: 42; w: 16; h:16; | ||||||
| @ -132,7 +132,6 @@ | |||||||
|     } |     } | ||||||
|     @attribute size int default 8 |     @attribute size int default 8 | ||||||
|     @attribute pocetnaAdresa int default 0 { |     @attribute pocetnaAdresa int default 0 { | ||||||
|         @displayName "Početna adresa" |  | ||||||
|         @popup automatic { |         @popup automatic { | ||||||
|             @title "Početna adresa memorije" |             @title "Početna adresa memorije" | ||||||
|             @text "Zadajte početnu adresu memorije" |             @text "Zadajte početnu adresu memorije" | ||||||
| @ -182,7 +181,7 @@ | |||||||
| 
 | 
 | ||||||
|     @pin glavniPin inOut { |     @pin glavniPin inOut { | ||||||
|         @tooltip "pin za spajanje na glavnu sabirnicu" |         @tooltip "pin za spajanje na glavnu sabirnicu" | ||||||
|         @connection "COMDEL se ne može stvoriti. Memorija nije spojena na sabirnicu" |         @connection required("COMDEL se ne može stvoriti. Memorija nije spojena na sabirnicu") | ||||||
|         @display { |         @display { | ||||||
|             /* |             /* | ||||||
|             pin { |             pin { | ||||||
| @ -205,6 +204,7 @@ | |||||||
| 
 | 
 | ||||||
|     @pin memDirect inOut { |     @pin memDirect inOut { | ||||||
|             @tooltip "pin za spajanje na procesor" |             @tooltip "pin za spajanje na procesor" | ||||||
|  |             @connection optional("COMDEL se ne može stvoriti. Memorija nije spojena na sabirnicu") | ||||||
|             @display { |             @display { | ||||||
|                 /* |                 /* | ||||||
|                 pin { |                 pin { | ||||||
| @ -228,14 +228,12 @@ | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @component DMA { | @component DMA { | ||||||
|     @displayName "DMA kontroler" |  | ||||||
|     @instanceName dma |     @instanceName dma | ||||||
|     @tooltip "DMA-kontroler" |     @tooltip "DMA-kontroler" | ||||||
|     @count (0,1000) |     @count (0,1000) | ||||||
|     @source "dma.cdl" |     @source "dma.cdl" | ||||||
| 
 | 
 | ||||||
|     @attribute pocetnaAdresa int default 0 { |     @attribute pocetnaAdresa int default 0 { | ||||||
|         @displayName "Početna adresa" |  | ||||||
|         @popup automatic { |         @popup automatic { | ||||||
|             @title "Početna adresa DMA-kontrolera" |             @title "Početna adresa DMA-kontrolera" | ||||||
|             @text "Zadajte početnu adresu DMA-kontrolera" |             @text "Zadajte početnu adresu DMA-kontrolera" | ||||||
| @ -278,7 +276,7 @@ | |||||||
| 
 | 
 | ||||||
|     @pin glavniPin in { |     @pin glavniPin in { | ||||||
|         @tooltip "pin za spajanje na glavnu sabirnicu" |         @tooltip "pin za spajanje na glavnu sabirnicu" | ||||||
|         @connection "COMDEL se ne može stvoriti. DMA nije spojena na sabirnicu" |         @connection required("COMDEL se ne može stvoriti. DMA nije spojena na sabirnicu") | ||||||
|         @display { |         @display { | ||||||
|             /* |             /* | ||||||
|             pin { |             pin { | ||||||
| @ -300,6 +298,7 @@ | |||||||
| 
 | 
 | ||||||
|     @pin dodatnaPoveznica in { |     @pin dodatnaPoveznica in { | ||||||
|         @tooltip "pin za spajanje na pomocnu sabirnicu" |         @tooltip "pin za spajanje na pomocnu sabirnicu" | ||||||
|  |         @connection optional("COMDEL se ne može stvoriti. DMA nije spojen na nesto!") | ||||||
|         @display { |         @display { | ||||||
|             pin { |             pin { | ||||||
|                 x: 100; y: 7; w: 16; h: 16; |                 x: 100; y: 7; w: 16; h: 16; | ||||||
| @ -311,7 +310,6 @@ | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @bus glavnaSabirnica regular { | @bus glavnaSabirnica regular { | ||||||
|     @displayName "Glavna sabirnica" |  | ||||||
|     @instanceName glavnaSabirnica |     @instanceName glavnaSabirnica | ||||||
|     @tooltip "sabirnica za spajanje FRISC a s memorijama i UI/jedinicama" |     @tooltip "sabirnica za spajanje FRISC a s memorijama i UI/jedinicama" | ||||||
|     @count (1,1) |     @count (1,1) | ||||||
|  | |||||||
							
								
								
									
										14
									
								
								examples/simplified FRISC model/schema2.csl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								examples/simplified FRISC model/schema2.csl
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | |||||||
|  | @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 | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | } | ||||||
							
								
								
									
										29
									
								
								examples/simplified FRISC model/schema3.csl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								examples/simplified FRISC model/schema3.csl
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,29 @@ | |||||||
|  | @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) { | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										16
									
								
								examples/simplified FRISC model/schema4.csl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								examples/simplified FRISC model/schema4.csl
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,16 @@ | |||||||
|  | @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 "frisc_library.csl" | @source "/home/bbr/Documents/Personal/FER/schema_editor/examples/simplified FRISC model/frisc_library.csl" | ||||||
| 
 | 
 | ||||||
| @schema { | @schema { | ||||||
| 	@instance procesor FRISC { | 	@instance procesor FRISC { | ||||||
| @ -1,18 +1,19 @@ | |||||||
| #include "mainwindow.h" | #include "mainwindow.h" | ||||||
| #include "ui_mainwindow.h" | #include "ui_mainwindow.h" | ||||||
| #include "application.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 <QFileDialog> | ||||||
| #include <QHBoxLayout> | #include <QHBoxLayout> | ||||||
| 
 | 
 | ||||||
| #include <comdel/parser/parse_context.h> | #include <comdel/parser/parse_context.h> | ||||||
| #include <comdel/domain/comdel_validator.h> | #include <comdel/parser/parser_util.h> | ||||||
|  | #include <comdel/domain/schema_creator.h> | ||||||
| 
 | 
 | ||||||
| #include <iostream> | #include <iostream> | ||||||
|  | #include <QPlainTextEdit> | ||||||
|  | #include <comdel/domain/comdel_validator.h> | ||||||
| #include <fstream> | #include <fstream> | ||||||
|  | #include <comdel/domain/comdel_generator.h> | ||||||
| 
 | 
 | ||||||
| MainWindow::MainWindow(QWidget *parent) | MainWindow::MainWindow(QWidget *parent) | ||||||
|     : QMainWindow(parent) |     : QMainWindow(parent) | ||||||
| @ -31,12 +32,10 @@ void MainWindow::setupUi() | |||||||
|     ui->centralwidget->setLayout(layout); |     ui->centralwidget->setLayout(layout); | ||||||
| 
 | 
 | ||||||
|     // setup toolbar
 |     // setup toolbar
 | ||||||
|     loadLibrary = ui->toolBar->addAction(QMESSAGE("msg_toolbar_load_library"), this, &MainWindow::onLoadLibrary); |     ui->toolBar->addAction("Učitaj bibiloteku", this, &MainWindow::onLoadLibrary); | ||||||
|     loadSchema = ui->toolBar->addAction(QMESSAGE("msg_toolbar_load_schema"), this, &MainWindow::onLoadSchema); |     ui->toolBar->addAction("Učitaj shemu", this, &MainWindow::onLoadSchema); | ||||||
|     saveSchema = ui->toolBar->addAction(QMESSAGE("msg_toolbar_save_schema"), this, &MainWindow::onStoreScheme); |     ui->toolBar->addAction("Spremi shemu", this, &MainWindow::onStoreScheme); | ||||||
|     generateComdel = ui->toolBar->addAction(QMESSAGE("msg_toolbar_generate_comdel"), this, &MainWindow::onGenerateComdel); |     ui->toolBar->addAction("Generiraj comdel", this, &MainWindow::onGenerateComdel); | ||||||
| 
 |  | ||||||
|     updateTranslations(); |  | ||||||
| 
 | 
 | ||||||
|     connect(ui->actionSave_schema, &QAction::triggered, this, &MainWindow::onStoreScheme); |     connect(ui->actionSave_schema, &QAction::triggered, this, &MainWindow::onStoreScheme); | ||||||
|     connect(ui->actionExport_schema, &QAction::triggered, this, &MainWindow::onGenerateComdel); |     connect(ui->actionExport_schema, &QAction::triggered, this, &MainWindow::onGenerateComdel); | ||||||
| @ -56,25 +55,25 @@ void MainWindow::setupUi() | |||||||
|     layout->setContentsMargins(0, 0, 0, 0); |     layout->setContentsMargins(0, 0, 0, 0); | ||||||
|     layout->addWidget(libraryDisplay); |     layout->addWidget(libraryDisplay); | ||||||
|     layout->addWidget(schemaParent, 1); |     layout->addWidget(schemaParent, 1); | ||||||
|  | 
 | ||||||
|  |     log = new QPlainTextEdit(); | ||||||
|  |     log->setFont(QFont("Courier")); | ||||||
|  |     log->setReadOnly(false); | ||||||
|  |     schemaLayout->addWidget(log); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void MainWindow::onLoadLibrary() { | void MainWindow::onLoadLibrary() { | ||||||
|     auto filename = QFileDialog::getOpenFileName(this, |     auto filename = QFileDialog::getOpenFileName(this, | ||||||
|                                                  QMESSAGE("msg_files_load_library"), |              tr("Otvori biblioteku"), "", tr("Comdel biblioteka (*.csl)")); | ||||||
|                                                  "", |  | ||||||
|                                                  QMESSAGE("msg_files_load_library_format")); |  | ||||||
|     if(!filename.isEmpty()) { |     if(!filename.isEmpty()) { | ||||||
|         std::ostringstream output; |         std::ostringstream output; | ||||||
|  |         log->clear(); | ||||||
| 
 | 
 | ||||||
|         auto librarySource = filename.toStdString(); |         auto librarySource = filename.toStdString(); | ||||||
| 
 | 
 | ||||||
|         auto instance = Application::instance(); |         auto instance = Application::instance(); | ||||||
|         if(!instance->loadLibrary(librarySource, output)) { |         if(!instance->loadLibrary(librarySource, output)) { | ||||||
|             auto dialog = new display::ErrorDialog(output); |             log->appendPlainText(QString::fromStdString(output.str())); | ||||||
|             dialog->exec(); |  | ||||||
|         } else { |  | ||||||
|             MessageSource::instance()->load(Application::instance()->getLibrary()->getMessages()); |  | ||||||
|             updateTranslations(); |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         libraryDisplay->refreshContent(); |         libraryDisplay->refreshContent(); | ||||||
| @ -84,11 +83,10 @@ void MainWindow::onLoadLibrary() { | |||||||
| 
 | 
 | ||||||
| void MainWindow::onLoadSchema() { | void MainWindow::onLoadSchema() { | ||||||
|     auto filename = QFileDialog::getOpenFileName(this, |     auto filename = QFileDialog::getOpenFileName(this, | ||||||
|                                                  QMESSAGE("msg_files_load_schema"), |              tr("Otvori shemu"), "", tr("Comdel shema (*.csl)")); | ||||||
|                                                  "", |  | ||||||
|                                                  QMESSAGE("msg_files_load_schema_format")); |  | ||||||
|     if(!filename.isEmpty()) { |     if(!filename.isEmpty()) { | ||||||
|         std::ostringstream output; |         std::ostringstream output; | ||||||
|  |         log->clear(); | ||||||
| 
 | 
 | ||||||
|         auto schemaSource = filename.toStdString(); |         auto schemaSource = filename.toStdString(); | ||||||
| 
 | 
 | ||||||
| @ -96,11 +94,7 @@ void MainWindow::onLoadSchema() { | |||||||
|         auto result = instance->loadSchema(schemaSource, output); |         auto result = instance->loadSchema(schemaSource, output); | ||||||
|         if(!result.first){ |         if(!result.first){ | ||||||
|             formatErrors(result.second, output); |             formatErrors(result.second, output); | ||||||
|             auto dialog = new display::ErrorDialog(output); |             log->appendPlainText(QString::fromStdString(output.str())); | ||||||
|             dialog->exec(); |  | ||||||
|         } else { |  | ||||||
|             MessageSource::instance()->load(Application::instance()->getLibrary()->getMessages()); |  | ||||||
|             updateTranslations(); |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         libraryDisplay->refreshContent(); |         libraryDisplay->refreshContent(); | ||||||
| @ -110,10 +104,10 @@ void MainWindow::onLoadSchema() { | |||||||
| 
 | 
 | ||||||
| void MainWindow::onStoreScheme() { | void MainWindow::onStoreScheme() { | ||||||
|     auto filename = QFileDialog::getSaveFileName(this, |     auto filename = QFileDialog::getSaveFileName(this, | ||||||
|                                                  QMESSAGE("msg_files_store_schema"), |                                                  tr("Spremi shemu"), "", tr("Comdel shema (*.csl)")); | ||||||
|                                                  "", |  | ||||||
|                                                  QMESSAGE("msg_files_store_schema_format")); |  | ||||||
|     if(!filename.isEmpty()) { |     if(!filename.isEmpty()) { | ||||||
|  |         log->clear(); | ||||||
|  | 
 | ||||||
|         std::ostringstream output; |         std::ostringstream output; | ||||||
| 
 | 
 | ||||||
|         if(Application::instance()->generateSchema(output)) { |         if(Application::instance()->generateSchema(output)) { | ||||||
| @ -121,11 +115,9 @@ void MainWindow::onStoreScheme() { | |||||||
|             out<<output.str(); |             out<<output.str(); | ||||||
|             out.close(); |             out.close(); | ||||||
| 
 | 
 | ||||||
|             auto dialog = new display::SuccessDialog(MESSAGE("msg_dialog_success_save_schema")); |             log->appendPlainText("Uspješno spremljena shema\n"); | ||||||
|             dialog->exec(); |  | ||||||
|         } else { |         } else { | ||||||
|             auto dialog = new display::ErrorDialog(output); |             log->appendPlainText("Greška tijekom spremanja sheme\n"); | ||||||
|             dialog->exec(); |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -133,27 +125,26 @@ void MainWindow::onStoreScheme() { | |||||||
| 
 | 
 | ||||||
| void MainWindow::onGenerateComdel() { | void MainWindow::onGenerateComdel() { | ||||||
|     auto filename = QFileDialog::getSaveFileName(this, |     auto filename = QFileDialog::getSaveFileName(this, | ||||||
|                                                  QMESSAGE("msg_files_store_comdel"), |                                                  tr("Spremi shemu"), "", tr("Comdel sustav (*.system)")); | ||||||
|                                                  "", |  | ||||||
|                                                  QMESSAGE("msg_files_store_comdel_format")); |  | ||||||
|     if(!filename.isEmpty()) { |     if(!filename.isEmpty()) { | ||||||
|  |         log->clear(); | ||||||
|  | 
 | ||||||
|         std::ostringstream output; |         std::ostringstream output; | ||||||
| 
 | 
 | ||||||
|         auto validationErrors = Application::instance()->generateComdel(output); |         auto validationErrors = Application::instance()->generateComdel(output); | ||||||
| 
 | 
 | ||||||
|         std::ostringstream errorOutput; |         std::ostringstream buff; | ||||||
|         formatErrors(validationErrors, errorOutput); |         formatErrors(validationErrors, buff); | ||||||
|  |         log->appendPlainText(QString::fromStdString(buff.str())); | ||||||
| 
 | 
 | ||||||
|         if(!Application::hasErrors(validationErrors)) { |         if(!Application::hasErrors(validationErrors)) { | ||||||
|             std::ofstream out(filename.toStdString(), std::ios::out | std::ios::binary); |             std::ofstream out(filename.toStdString(), std::ios::out | std::ios::binary); | ||||||
|             out<<output.str(); |             out<<output.str(); | ||||||
|             out.close(); |             out.close(); | ||||||
| 
 | 
 | ||||||
|             auto dialog = new display::SuccessDialog(MESSAGE("msg_dialog_success_comdel_generation")); |             log->appendPlainText("Uspješno generiranje comdel modela\n"); | ||||||
|             dialog->exec(); |  | ||||||
|         } else { |         } else { | ||||||
|             auto dialog = new display::ErrorDialog(errorOutput); |             log->appendPlainText("Neuspješno generiranje comdel modela\n"); | ||||||
|             dialog->exec(); |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @ -161,17 +152,15 @@ void MainWindow::onGenerateComdel() { | |||||||
| 
 | 
 | ||||||
| void MainWindow::onValidateSchema(bool /*toggled*/) { | void MainWindow::onValidateSchema(bool /*toggled*/) { | ||||||
| 
 | 
 | ||||||
|  |     log->clear(); | ||||||
|  | 
 | ||||||
|     auto errors = Application::instance()->validateSchema(); |     auto errors = Application::instance()->validateSchema(); | ||||||
| 
 | 
 | ||||||
|     if(Application::hasErrors(errors)) { |     std::ostringstream buff; | ||||||
|         std::ostringstream buff; |     formatErrors(errors, buff); | ||||||
|         formatErrors(errors, buff); | 
 | ||||||
|         auto dialog = new display::ErrorDialog(buff); |     log->appendPlainText(QString::fromStdString(buff.str())); | ||||||
|         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) { | void MainWindow::formatErrors(std::vector<domain::ValidationError>& errors, std::ostream& output) { | ||||||
| @ -195,10 +184,3 @@ MainWindow::~MainWindow() | |||||||
| { | { | ||||||
|     delete ui; |     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,14 +40,8 @@ private: | |||||||
|     display::Library *libraryDisplay; |     display::Library *libraryDisplay; | ||||||
|     display::Schema *schemaDisplay; |     display::Schema *schemaDisplay; | ||||||
|     Ui::MainWindow *ui; |     Ui::MainWindow *ui; | ||||||
| 
 |     QPlainTextEdit *log; | ||||||
|     QAction* loadLibrary; |  | ||||||
|     QAction* loadSchema; |  | ||||||
|     QAction* saveSchema; |  | ||||||
|     QAction* generateComdel; |  | ||||||
| 
 | 
 | ||||||
|     static void formatErrors(std::vector<domain::ValidationError>& errors, std::ostream& output); |     static void formatErrors(std::vector<domain::ValidationError>& errors, std::ostream& output); | ||||||
| 
 |  | ||||||
|     void updateTranslations(); |  | ||||||
| }; | }; | ||||||
| #endif // MAIN_WINDOW_H
 | #endif // MAIN_WINDOW_H
 | ||||||
|  | |||||||
| @ -1,145 +0,0 @@ | |||||||
| //
 |  | ||||||
| // 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; |  | ||||||
| } |  | ||||||
| @ -1,43 +0,0 @@ | |||||||
| //
 |  | ||||||
| // 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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user