Compare commits
2 Commits
1100a9f0b9
...
cbff8ff5f2
Author | SHA1 | Date |
---|---|---|
Borna Rajković | cbff8ff5f2 | |
Borna Rajković | 0a658a4aba |
|
@ -38,5 +38,5 @@ add_executable(SchemeEditor
|
||||||
comdel/parser/comdellexer.cpp
|
comdel/parser/comdellexer.cpp
|
||||||
main.cpp
|
main.cpp
|
||||||
mainwindow.ui
|
mainwindow.ui
|
||||||
comdel/domain/comdelvalidator.cpp comdel/domain/comdelvalidator.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/domain/comdelvalidator.cpp comdel/domain/comdelvalidator.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)
|
||||||
target_link_libraries(SchemeEditor Qt5::Core Qt5::Gui Qt5::Widgets)
|
target_link_libraries(SchemeEditor Qt5::Core Qt5::Gui Qt5::Widgets)
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
#include <QGraphicsSceneContextMenuEvent>
|
#include <QGraphicsSceneContextMenuEvent>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
namespace display {
|
namespace display {
|
||||||
|
|
||||||
|
@ -35,8 +36,36 @@ void Component::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) {
|
||||||
menu.exec(event->screenPos());
|
menu.exec(event->screenPos());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Pin::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) {
|
||||||
|
QMenu menu;
|
||||||
|
menu.addAction("Connect pin", [&]() {});
|
||||||
|
menu.exec(event->screenPos());
|
||||||
|
}
|
||||||
|
|
||||||
void Bus::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) {
|
void Pin::mousePressEvent(QGraphicsSceneMouseEvent *event) {
|
||||||
|
if(event->button() == Qt::MouseButton::LeftButton) {
|
||||||
|
auto view = dynamic_cast<Schema*>(this->scene()->views()[0]);
|
||||||
|
view->state = Schema::CREATING_CONNECTION;
|
||||||
|
view->context.pin = this;
|
||||||
|
view->context.startingPoint = view->mapToScene(event->pos().toPoint());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Pin::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
|
||||||
|
auto view = dynamic_cast<Schema*>(this->scene()->views()[0]);
|
||||||
|
if(view->state == Schema::CREATING_CONNECTION) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Pin::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) {
|
||||||
|
if(event->button() == Qt::MouseButton::LeftButton) {
|
||||||
|
auto view = dynamic_cast<Schema*>(this->scene()->views()[0]);
|
||||||
|
view->state = Schema::DEFAULT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Bus::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) {
|
||||||
QMenu menu;
|
QMenu menu;
|
||||||
menu.addAction("Izmjeni ime", [this](){
|
menu.addAction("Izmjeni ime", [this](){
|
||||||
auto dialog = new NameDialog(this->busInstance.get());
|
auto dialog = new NameDialog(this->busInstance.get());
|
||||||
|
@ -107,4 +136,5 @@ void Bus::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) {
|
||||||
}
|
}
|
||||||
menu.exec(event->screenPos());
|
menu.exec(event->screenPos());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace display
|
} // namespace display
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
#include <comdel/domain/wireinstance.h>
|
#include <comdel/domain/wireinstance.h>
|
||||||
|
|
||||||
#include <QGraphicsItemGroup>
|
#include <QGraphicsItemGroup>
|
||||||
|
#include <QGraphicsSceneMouseEvent>
|
||||||
|
#include <QGraphicsSceneMouseEvent>
|
||||||
#include "comdel/domain/connectioninstance.h"
|
#include "comdel/domain/connectioninstance.h"
|
||||||
|
|
||||||
namespace display {
|
namespace display {
|
||||||
|
@ -17,6 +19,12 @@ public:
|
||||||
Pin(domain::Pin pin): pin(pin) {
|
Pin(domain::Pin pin): pin(pin) {
|
||||||
pin.getDisplayPin().render(this);
|
pin.getDisplayPin().render(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override;
|
||||||
|
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
|
||||||
|
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
|
||||||
|
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Component: public QGraphicsItemGroup
|
class Component: public QGraphicsItemGroup
|
||||||
|
|
|
@ -11,8 +11,8 @@ Library::Library()
|
||||||
auto layout = new QVBoxLayout();
|
auto layout = new QVBoxLayout();
|
||||||
this->setLayout(layout);
|
this->setLayout(layout);
|
||||||
|
|
||||||
componentList = new QListWidget();
|
componentList = new LibraryList(this);
|
||||||
busList = new QListWidget();
|
busList = new LibraryList(this);
|
||||||
|
|
||||||
layout->setMargin(4);
|
layout->setMargin(4);
|
||||||
layout->addWidget(new QLabel("Components:"));
|
layout->addWidget(new QLabel("Components:"));
|
||||||
|
@ -34,14 +34,14 @@ void Library::setLibrary(std::optional<domain::Library> library) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for(auto& component: library->getComponents()) {
|
for(auto& component: library->getComponents()) {
|
||||||
auto item = new QListWidgetItem{QString::fromStdString(component.getName())};
|
auto item = new LibraryListItem{component.getName(), "comdel/component", component.getName(), componentList};
|
||||||
item->setToolTip(QString::fromStdString(component.getTooltip()));
|
item->setToolTip(QString::fromStdString(component.getTooltip()));
|
||||||
componentList->addItem(item);
|
componentList->addItem(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
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 QListWidgetItem{QString::fromStdString(bus.getName())};
|
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,6 +5,7 @@
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
#include <comdel/domain/library.h>
|
#include <comdel/domain/library.h>
|
||||||
|
#include "library_list.h"
|
||||||
|
|
||||||
namespace display {
|
namespace display {
|
||||||
|
|
||||||
|
@ -18,8 +19,8 @@ public:
|
||||||
private:
|
private:
|
||||||
std::optional<domain::Library> library;
|
std::optional<domain::Library> library;
|
||||||
|
|
||||||
QListWidget *componentList;
|
LibraryList *componentList;
|
||||||
QListWidget *busList;
|
LibraryList *busList;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
//
|
||||||
|
// Created by bbr on 22.05.22..
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "library_list.h"
|
||||||
|
|
||||||
|
#include <QMouseEvent>
|
||||||
|
#include <QDrag>
|
||||||
|
#include <QMimeData>
|
||||||
|
|
||||||
|
namespace display {
|
||||||
|
|
||||||
|
LibraryList::LibraryList(QWidget *parent): QListWidget(parent) {
|
||||||
|
setDragDropMode(DragOnly);
|
||||||
|
}
|
||||||
|
|
||||||
|
QMimeData *LibraryList::mimeData(const QList<QListWidgetItem *> items) const {
|
||||||
|
for(auto qItem: items) {
|
||||||
|
// we only allow one item to be dragged at a time
|
||||||
|
auto item = dynamic_cast<LibraryListItem*>(qItem);
|
||||||
|
auto* md = new QMimeData();
|
||||||
|
md->setData(QString::fromStdString(item->mimeType), QByteArray::fromStdString(item->value));
|
||||||
|
return md;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
LibraryListItem::LibraryListItem(std::string title, std::string mimeType, std::string value, QListWidget *parent): QListWidgetItem(parent), mimeType(mimeType), value(value) {
|
||||||
|
setText(QString::fromStdString(title));
|
||||||
|
}
|
||||||
|
} // display
|
|
@ -0,0 +1,34 @@
|
||||||
|
//
|
||||||
|
// Created by bbr on 22.05.22..
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef SCHEMEEDITOR_LIBRARY_LIST_H
|
||||||
|
#define SCHEMEEDITOR_LIBRARY_LIST_H
|
||||||
|
|
||||||
|
#include <QListWidget>
|
||||||
|
#include <QList>
|
||||||
|
#include <QMimeData>
|
||||||
|
|
||||||
|
namespace display {
|
||||||
|
|
||||||
|
class LibraryList: public QListWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
LibraryList(QWidget *parent);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QMimeData *mimeData(const QList<QListWidgetItem*> items) const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class LibraryListItem: public QListWidgetItem {
|
||||||
|
|
||||||
|
public:
|
||||||
|
std::string mimeType;
|
||||||
|
std::string value;
|
||||||
|
|
||||||
|
LibraryListItem(std::string title, std::string mimeType, std::string value, QListWidget *parent);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // display
|
||||||
|
|
||||||
|
#endif //SCHEMEEDITOR_LIBRARY_LIST_H
|
|
@ -1,15 +1,22 @@
|
||||||
#include "component_display.h"
|
#include "component_display.h"
|
||||||
#include "schema_display.h"
|
#include "schema_display.h"
|
||||||
|
|
||||||
|
#include <QDrag>
|
||||||
|
#include <QDragEnterEvent>
|
||||||
|
#include <QDropEvent>
|
||||||
|
#include <QMimeData>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
namespace display {
|
namespace display {
|
||||||
|
|
||||||
Schema::Schema()
|
Schema::Schema()
|
||||||
{
|
{
|
||||||
this->setScene(&scene);
|
this->setScene(&scene);
|
||||||
|
this->setAcceptDrops(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Schema::setSchema(domain::Schema* _schema)
|
void Schema::setSchema(domain::Schema* _schema, domain::Library* _library)
|
||||||
{
|
{
|
||||||
std::map<std::string, display::ComponentGroup*> components;
|
std::map<std::string, display::ComponentGroup*> components;
|
||||||
std::map<std::string, display::BusGroup*> buses;
|
std::map<std::string, display::BusGroup*> buses;
|
||||||
|
@ -17,6 +24,7 @@ void Schema::setSchema(domain::Schema* _schema)
|
||||||
scene.clear();
|
scene.clear();
|
||||||
connections.clear();
|
connections.clear();
|
||||||
this->schema = _schema;
|
this->schema = _schema;
|
||||||
|
this->library = _library;
|
||||||
if(schema != nullptr) {
|
if(schema != nullptr) {
|
||||||
for(auto &instance: schema->componentInstances) {
|
for(auto &instance: schema->componentInstances) {
|
||||||
auto group = new display::ComponentGroup(instance);
|
auto group = new display::ComponentGroup(instance);
|
||||||
|
@ -49,4 +57,51 @@ void Schema::updateConnections() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Schema::dragEnterEvent(QDragEnterEvent *event) {
|
||||||
|
if(event->mimeData()->hasFormat("comdel/component") ||
|
||||||
|
event->mimeData()->hasFormat("comdel/bus")) {
|
||||||
|
event->acceptProposedAction();
|
||||||
|
} else {
|
||||||
|
std::cout<<"false"<< std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Schema::dropEvent(QDropEvent *event) {
|
||||||
|
if(event->mimeData()->hasFormat("comdel/component")) {
|
||||||
|
auto component = library->getComponent(event->mimeData()->data("comdel/component").toStdString());
|
||||||
|
|
||||||
|
auto attributes = std::vector<domain::InstanceAttribute>();
|
||||||
|
for(auto attr: component.getAttributes()) {
|
||||||
|
attributes.emplace_back(attr.getName(), attr.getDefault(), attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto currentPos = this->mapToScene(event->pos());
|
||||||
|
|
||||||
|
auto instance = std::make_shared<domain::ComponentInstance>(component.getInstanceName(), attributes, std::make_pair(currentPos.x(), currentPos.y()), component);
|
||||||
|
schema->componentInstances.push_back(instance);
|
||||||
|
|
||||||
|
auto group = new display::ComponentGroup(instance);
|
||||||
|
scene.addItem(group);
|
||||||
|
|
||||||
|
event->acceptProposedAction();
|
||||||
|
}
|
||||||
|
if(event->mimeData()->hasFormat("comdel/bus")) {
|
||||||
|
auto bus = library->getBus(event->mimeData()->data("comdel/bus").toStdString());
|
||||||
|
|
||||||
|
auto currentPos = this->mapToScene(event->pos());
|
||||||
|
|
||||||
|
auto instance = std::make_shared<domain::BusInstance>(bus.getName(), std::make_pair(currentPos.x(), currentPos.y()), bus, 50);
|
||||||
|
schema->busInstances.push_back(instance);
|
||||||
|
|
||||||
|
auto group = new display::BusGroup(instance);
|
||||||
|
scene.addItem(group);
|
||||||
|
|
||||||
|
event->acceptProposedAction();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Schema::dragMoveEvent(QDragMoveEvent *event) {
|
||||||
|
event->acceptProposedAction();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace display
|
} // namespace display
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
#include <comdel/domain/schema.h>
|
#include <comdel/domain/schema.h>
|
||||||
|
#include <comdel/domain/library.h>
|
||||||
|
|
||||||
namespace display {
|
namespace display {
|
||||||
|
|
||||||
|
@ -13,19 +14,42 @@ namespace display {
|
||||||
|
|
||||||
class Schema: public QGraphicsView
|
class Schema: public QGraphicsView
|
||||||
{
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
enum State {
|
||||||
|
DEFAULT,
|
||||||
|
CREATING_CONNECTION
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Context {
|
||||||
|
display::Pin *pin;
|
||||||
|
QPointF startingPoint;
|
||||||
|
};
|
||||||
|
|
||||||
|
State state = DEFAULT;
|
||||||
|
Context context;
|
||||||
|
|
||||||
Schema();
|
Schema();
|
||||||
|
|
||||||
std::vector<BusConnection*> connections;
|
std::vector<BusConnection*> connections;
|
||||||
|
|
||||||
void setSchema(domain::Schema* schema);
|
void setSchema(domain::Schema* schema, domain::Library* library);
|
||||||
|
|
||||||
void updateConnections();
|
void updateConnections();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
void dragEnterEvent(QDragEnterEvent *event) override;
|
||||||
|
void dropEvent(QDropEvent *event) override;
|
||||||
|
void dragMoveEvent(QDragMoveEvent *event) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QGraphicsScene scene;
|
QGraphicsScene scene;
|
||||||
|
|
||||||
domain::Schema* schema;
|
domain::Schema* schema;
|
||||||
|
domain::Library* library;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace display
|
} // namespace display
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "comdelvalidator.h"
|
#include "comdelvalidator.h"
|
||||||
|
#include "library.h"
|
||||||
|
|
||||||
namespace domain {
|
namespace domain {
|
||||||
|
|
||||||
|
@ -15,6 +16,78 @@ std::vector<ValidationError> ComdelValidator::validateSchema(Schema &schema, Val
|
||||||
return errors;
|
return errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<ValidationError> ComdelValidator::validateInstanceCount(Schema& schema, Library& library, ValidationContext context) {
|
||||||
|
std::vector<ValidationError> errors;
|
||||||
|
|
||||||
|
// validate instance count
|
||||||
|
std::map<std::string, int> instanceMap;
|
||||||
|
for(auto& inst: schema.componentInstances) {
|
||||||
|
instanceMap[inst->component.getName()]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto comp: library.getComponents()) {
|
||||||
|
int count = instanceMap[comp.getName()];
|
||||||
|
|
||||||
|
context.attributes["componentName"] = Value::fromString(comp.getName());
|
||||||
|
context.attributes["min"] = Value::fromInt(comp.getCount().first);
|
||||||
|
context.attributes["max"] = Value::fromInt(comp.getCount().second);
|
||||||
|
context.attributes["count"] = Value::fromInt(count);
|
||||||
|
|
||||||
|
if(count < comp.getCount().first) {
|
||||||
|
auto message = populateMessage("Not enough instances of component '{componentName}' required at least {min}, found {count}", context);
|
||||||
|
errors.push_back(ValidationError{nullptr, nullptr, Action::ERROR, message});
|
||||||
|
} else if(count > comp.getCount().second) {
|
||||||
|
auto message = populateMessage("To many instances of component '{componentName}' allow at most {max}, found {count}", context);
|
||||||
|
errors.push_back(ValidationError{nullptr, nullptr, Action::ERROR, message});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// validate bus instance count
|
||||||
|
std::map<std::string, int> busInstanceMap;
|
||||||
|
for(auto& inst: schema.busInstances) {
|
||||||
|
busInstanceMap[inst->bus.getName()]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto bus: library.getBuses()) {
|
||||||
|
int count = busInstanceMap[bus.getName()];
|
||||||
|
|
||||||
|
context.attributes["busName"] = Value::fromString(bus.getName());
|
||||||
|
context.attributes["min"] = Value::fromInt(bus.getCount().first);
|
||||||
|
context.attributes["max"] = Value::fromInt(bus.getCount().second);
|
||||||
|
context.attributes["count"] = Value::fromInt(count);
|
||||||
|
|
||||||
|
if(count < bus.getCount().first) {
|
||||||
|
auto message = populateMessage("Not enough instances of bus '{busName}' required at least {min}, found {count}", context);
|
||||||
|
errors.push_back(ValidationError{nullptr, nullptr, Action::ERROR, message});
|
||||||
|
} else if(count > bus.getCount().second) {
|
||||||
|
auto message = populateMessage("To many instances of bus '{busName}' allow at most {max}, found {count}", context);
|
||||||
|
errors.push_back(ValidationError{nullptr, nullptr, Action::ERROR, message});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<ValidationError> ComdelValidator::validatePinConnections(Schema &schema, Library &library, ValidationContext context) {
|
||||||
|
std::vector<ValidationError> errors;
|
||||||
|
|
||||||
|
for(auto& inst: schema.componentInstances) {
|
||||||
|
for(auto& pin: inst->component.getPins()) {
|
||||||
|
if(pin.getConnection().getType() == PinConnection::REQUIRED) {
|
||||||
|
if(!connectionExists(schema, inst, pin)) {
|
||||||
|
context.instance = inst.get();
|
||||||
|
context.attributes["instanceName"] = Value::fromString(inst->name);
|
||||||
|
auto message = populateMessage(pin.getConnection().getMessage(), context);
|
||||||
|
errors.push_back(ValidationError{nullptr, nullptr, Action::ERROR, message});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<ValidationError> ComdelValidator::validateComponent(ComponentInstance* instance, ValidationContext context) {
|
std::vector<ValidationError> ComdelValidator::validateComponent(ComponentInstance* instance, ValidationContext context) {
|
||||||
std::vector<ValidationError> errors;
|
std::vector<ValidationError> errors;
|
||||||
|
|
||||||
|
@ -89,4 +162,26 @@ string ComdelValidator::replacePlaceholder(string source, string key, Value valu
|
||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ComdelValidator::connectionExists(Schema &schema, shared_ptr<ComponentInstance> &component, Pin &pin) {
|
||||||
|
for(auto conn: schema.connections) {
|
||||||
|
auto busConnection = dynamic_cast<BusConnectionInstance*>(conn.get());
|
||||||
|
if(busConnection != nullptr) {
|
||||||
|
if(busConnection->instance->name == component->name && busConnection->connection.getComponent().pin == pin.getName()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto directConnection = dynamic_cast<DirectConnectionInstance*>(conn.get());
|
||||||
|
if(directConnection != nullptr) {
|
||||||
|
if(directConnection->instance->name == component->name && busConnection->connection.getComponent().pin == pin.getName()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if(directConnection->secondInstance->name == component->name && busConnection->connection.getSecondComponent()->pin == pin.getName()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "instance.h"
|
#include "instance.h"
|
||||||
#include "schema.h"
|
#include "schema.h"
|
||||||
|
#include "library.h"
|
||||||
|
|
||||||
namespace domain {
|
namespace domain {
|
||||||
|
|
||||||
|
@ -29,6 +30,9 @@ public:
|
||||||
std::vector<ValidationError> validateAttribute(InstanceAttribute *attribute, ValidationContext context);
|
std::vector<ValidationError> validateAttribute(InstanceAttribute *attribute, ValidationContext context);
|
||||||
std::optional<ValidationError> validateRule(Rule rule, ValidationContext context);
|
std::optional<ValidationError> validateRule(Rule rule, ValidationContext context);
|
||||||
|
|
||||||
|
std::vector<ValidationError> validateInstanceCount(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) {
|
||||||
for(auto* validator: validators) {
|
for(auto* validator: validators) {
|
||||||
validator->clear();
|
validator->clear();
|
||||||
|
@ -42,6 +46,8 @@ private:
|
||||||
std::string populateMessage(string message, ValidationContext context);
|
std::string populateMessage(string message, ValidationContext context);
|
||||||
|
|
||||||
string replacePlaceholder(string message, const string name, Value value);
|
string replacePlaceholder(string message, const string name, Value value);
|
||||||
|
|
||||||
|
bool connectionExists(Schema &schema, shared_ptr <ComponentInstance> &component, Pin &pin);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,22 +51,14 @@
|
||||||
x: 0; y:0; w:100; h:100;
|
x: 0; y:0; w:100; h:100;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@pin glavniPin inOut {
|
@pin glavniPin in {
|
||||||
@tooltip "pin za spajanje na glavnu sabirnicu"
|
@tooltip "pin za spajanje na glavnu sabirnicu"
|
||||||
@connection required("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 {
|
|
||||||
x: 100; y: 50;
|
|
||||||
fillColor: white;
|
|
||||||
lineColor: red;
|
|
||||||
fillColorConnected: white;
|
|
||||||
lineColorConnected: black;
|
|
||||||
side: left;
|
|
||||||
size: 20;
|
|
||||||
}*/
|
|
||||||
pin {
|
pin {
|
||||||
x: 42; y: 100; w: 16; h:16;
|
x: 42; y: 100; w: 16; h:16;
|
||||||
|
type: "in";
|
||||||
|
orientation: "bottom";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -183,7 +175,9 @@
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
pin {
|
pin {
|
||||||
x: 42; y: -16; w: 16; h: 16;
|
x: 42; y: -16; w: 16; h:16;
|
||||||
|
type: "out";
|
||||||
|
orientation: "top";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -192,7 +186,7 @@
|
||||||
@component DMA {
|
@component DMA {
|
||||||
@instanceName "dma"
|
@instanceName "dma"
|
||||||
@tooltip "DMA-kontroler"
|
@tooltip "DMA-kontroler"
|
||||||
@count (1,1000)
|
@count (0,1000)
|
||||||
@source "dma.cdl"
|
@source "dma.cdl"
|
||||||
|
|
||||||
@attribute pocetnaAdresa int default 0 {
|
@attribute pocetnaAdresa int default 0 {
|
||||||
|
@ -303,20 +297,13 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@bus PIOSabirnica automatic {
|
@bus PIOSabirnica automatic {
|
||||||
|
@count (0, 20)
|
||||||
@wires {
|
@wires {
|
||||||
PIO_DATA<8>,
|
PIO_DATA<8>,
|
||||||
READY,
|
READY,
|
||||||
STROBE
|
STROBE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@bus Test singleAutomatic {
|
|
||||||
@tooltip "sabirnica za spajanje FRISC a s memorijama i UI/jedinicama"
|
|
||||||
@count (1,1)
|
|
||||||
|
|
||||||
@wires {
|
|
||||||
CONNECTOR,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@connection (FRISC.glavniPin, glavnaSabirnica) {
|
@connection (FRISC.glavniPin, glavnaSabirnica) {
|
||||||
@wires{ADR, DATA, READ, WRITE, SIZE, WAIT, INT0, INT1, INT2, INT3, IACK, 1, null}
|
@wires{ADR, DATA, READ, WRITE, SIZE, WAIT, INT0, INT1, INT2, INT3, IACK, 1, null}
|
||||||
|
@ -345,22 +332,3 @@
|
||||||
@wires{PIO_DATA, READY, STROBE}
|
@wires{PIO_DATA, READY, STROBE}
|
||||||
@wires{PIO_DATA, READY, STROBE}
|
@wires{PIO_DATA, READY, STROBE}
|
||||||
}
|
}
|
||||||
|
|
||||||
@connection (FRISC.glavniPin, Test, Memorija.glavniPin) {
|
|
||||||
@wires{null, "READY", null}
|
|
||||||
@wires{"PIO_DATA", null, null}
|
|
||||||
|
|
||||||
@attribute dmaPoveznica string default "" {
|
|
||||||
@popup automatic {
|
|
||||||
@title "Spoji DMA kraj"
|
|
||||||
@text "Odaberite poveznicu za dma kraja"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@attribute mmaPoveznica string default "" {
|
|
||||||
@popup automatic {
|
|
||||||
@title "Spoji MMA kraj"
|
|
||||||
@text "Odaberite poveznicu za mma kraja"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,33 +1,27 @@
|
||||||
@source "frisc_library.csl"
|
@source "frisc_library.csl"
|
||||||
|
|
||||||
@schema {
|
@schema {
|
||||||
@instance proc FRISC {
|
@instance proc FRISC {
|
||||||
@position (0, 0)
|
@position (0, 0)
|
||||||
@attribute _memory null
|
@attribute _memory null
|
||||||
}
|
}
|
||||||
|
|
||||||
@instance mem Memorija {
|
@instance mem Memorija {
|
||||||
@position (0, 250)
|
@position (0, 250)
|
||||||
@attribute sinkroniziran false
|
@attribute sinkroniziran false
|
||||||
@attribute brzina 1
|
@attribute brzina 1
|
||||||
@attribute kapacitet 1024
|
@attribute kapacitet 1024
|
||||||
@attribute size 8
|
@attribute size 8
|
||||||
@attribute pocetnaAdresa 1023
|
@attribute pocetnaAdresa 1024
|
||||||
}
|
}
|
||||||
|
|
||||||
@instance bus glavnaSabirnica {
|
@instance bus glavnaSabirnica {
|
||||||
@position (0, 200)
|
@position (0, 200)
|
||||||
@size 100
|
@size 100
|
||||||
}
|
}
|
||||||
|
|
||||||
@instance testBus Test {}
|
@connection (proc.glavniPin, bus) {
|
||||||
|
}
|
||||||
@connection (proc.glavniPin, bus) {}
|
@connection (mem.glavniPin, bus) {
|
||||||
|
}
|
||||||
@connection (mem.glavniPin, bus) {}
|
|
||||||
|
|
||||||
@connection (proc.glavniPin, testBus, mem.glavniPin) {
|
|
||||||
@attribute dmaPoveznica "READY"
|
|
||||||
@attribute mmaPoveznica "PIO_DATA"
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -3,7 +3,7 @@
|
||||||
@schema {
|
@schema {
|
||||||
@instance proc FRISC {
|
@instance proc FRISC {
|
||||||
@position (0, 0)
|
@position (0, 0)
|
||||||
@attribute _memory mem
|
@attribute _memory null
|
||||||
}
|
}
|
||||||
|
|
||||||
@instance mem Memorija {
|
@instance mem Memorija {
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
@attribute brzina 1
|
@attribute brzina 1
|
||||||
@attribute kapacitet 1024
|
@attribute kapacitet 1024
|
||||||
@attribute size 8
|
@attribute size 8
|
||||||
@attribute pocetnaAdresa 1023
|
@attribute pocetnaAdresa 1024
|
||||||
}
|
}
|
||||||
|
|
||||||
@instance bus glavnaSabirnica {
|
@instance bus glavnaSabirnica {
|
||||||
|
@ -20,17 +20,6 @@
|
||||||
@size 100
|
@size 100
|
||||||
}
|
}
|
||||||
|
|
||||||
@instance testBus Test {
|
|
||||||
@position (0, 200)
|
|
||||||
@size 0
|
|
||||||
}
|
|
||||||
|
|
||||||
@connection (proc.glavniPin, bus) {
|
|
||||||
}
|
|
||||||
@connection (mem.glavniPin, bus) {
|
@connection (mem.glavniPin, bus) {
|
||||||
}
|
}
|
||||||
@connection (proc.glavniPin, testBus, mem.glavniPin) {
|
|
||||||
@attribute dmaPoveznica "READY"
|
|
||||||
@attribute mmaPoveznica "PIO_DATA"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,7 +96,7 @@ void MainWindow::onLoadLibrary() {
|
||||||
|
|
||||||
// on library load we create a new schema
|
// on library load we create a new schema
|
||||||
schema = new domain::Schema();
|
schema = new domain::Schema();
|
||||||
schemaDisplay->setSchema(schema);
|
schemaDisplay->setSchema(schema, &(*library));
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -145,7 +145,7 @@ void MainWindow::onLoadSchema() {
|
||||||
|
|
||||||
if(generator.getErrors().empty()) {
|
if(generator.getErrors().empty()) {
|
||||||
libraryDisplay->setLibrary(library);
|
libraryDisplay->setLibrary(library);
|
||||||
schemaDisplay->setSchema(schema);
|
schemaDisplay->setSchema(schema, &(*library));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -209,6 +209,12 @@ void MainWindow::onValidateSchema(bool /*toggled*/) {
|
||||||
}
|
}
|
||||||
auto errors = validator.validateSchema(*schema, context);
|
auto errors = validator.validateSchema(*schema, context);
|
||||||
|
|
||||||
|
auto countValidation = validator.validateInstanceCount(*schema, *library, context);
|
||||||
|
errors.insert(errors.end(), countValidation.begin(), countValidation.end());
|
||||||
|
|
||||||
|
auto pinValidation = validator.validatePinConnections(*schema, *library, context);
|
||||||
|
errors.insert(errors.end(), pinValidation.begin(), pinValidation.end());
|
||||||
|
|
||||||
errors.erase(std::remove_if(
|
errors.erase(std::remove_if(
|
||||||
errors.begin(), errors.end(), [](const domain::ValidationError& error) { return error.type == domain::Action::WARNING;}),
|
errors.begin(), errors.end(), [](const domain::ValidationError& error) { return error.type == domain::Action::WARNING;}),
|
||||||
errors.end());
|
errors.end());
|
||||||
|
@ -245,7 +251,7 @@ void MainWindow::clear() {
|
||||||
library = std::nullopt;
|
library = std::nullopt;
|
||||||
|
|
||||||
libraryDisplay->setLibrary(library);
|
libraryDisplay->setLibrary(library);
|
||||||
schemaDisplay->setSchema(schema);
|
schemaDisplay->setSchema(schema, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
MainWindow::~MainWindow()
|
MainWindow::~MainWindow()
|
||||||
|
|
Loading…
Reference in New Issue