schema_editor/comdel/display/schema_display.cpp

297 lines
12 KiB
C++
Raw Normal View History

2022-04-07 22:21:23 +00:00
#include "component_display.h"
#include "schema_display.h"
#include "application.h"
#include "attribute_dialog.h"
2022-04-07 22:21:23 +00:00
#include <QDrag>
#include <QDragEnterEvent>
#include <QMimeData>
2022-04-07 22:21:23 +00:00
namespace display {
2022-05-27 06:18:17 +00:00
Schema::Schema() {
this->selectedBrush.setColor(QColor::fromRgb(20, 20, 125));
this->selectedPen.setColor(QColor::fromRgb(20, 20, 125));
schema = nullptr;
library = std::nullopt;
2022-05-27 06:18:17 +00:00
this->setScene(&scene);
this->setAcceptDrops(true);
}
void Schema::setSchema(domain::Schema *_schema, std::optional<domain::Library> _library) {
2022-05-27 06:18:17 +00:00
components.clear();
buses.clear();
scene.clear();
busConnections.clear();
this->schema = _schema;
this->library = _library;
if (schema != nullptr) {
for (auto &instance: schema->componentInstances) {
auto group = new display::ComponentGroup(instance);
for (auto pin: group->getPins()) {
display::Pin *p = pin;
domain::ConnectionComponent connection{instance->name, p->getPin().getName()};
pins.insert(std::make_pair(connection, p));
}
components.insert(std::make_pair(instance->name, group));
2022-05-17 22:14:33 +00:00
scene.addItem(group);
}
2022-05-27 06:18:17 +00:00
for (auto &instance: schema->busInstances) {
if (instance->bus.getDisplayBus().has_value()) {
auto group = new display::BusGroup(instance);
buses.insert(std::make_pair(instance->name, group));
scene.addItem(group);
}
2022-05-25 05:39:45 +00:00
}
2022-05-27 06:18:17 +00:00
for (auto &connection: schema->connections) {
auto busInstance = dynamic_cast<domain::BusConnectionInstance *>(connection.get());
if (busInstance != nullptr) {
auto con = new display::BusConnection(busInstance, components[busInstance->instance->name],
buses[busInstance->bus->name]);
busConnections.push_back(con);
scene.addItem(con);
}
auto directInstance = dynamic_cast<domain::DirectConnectionInstance *>(connection.get());
if (directInstance != nullptr) {
auto con = new display::DirectConnection(directInstance, components[directInstance->instance->name],
components[directInstance->secondInstance->name]);
directConnections.push_back(con);
scene.addItem(con);
}
}
2022-04-07 22:21:23 +00:00
}
}
2022-05-27 06:18:17 +00:00
void Schema::updateConnections() {
if (schema != nullptr) {
for (auto conn: busConnections) {
conn->updateConnection();
}
for (auto conn: directConnections) {
conn->updateConnection();
}
2022-05-17 22:14:33 +00:00
}
}
void Schema::dragEnterEvent(QDragEnterEvent *event) {
2022-05-27 06:18:17 +00:00
if (event->mimeData()->hasFormat("comdel/component") ||
event->mimeData()->hasFormat("comdel/bus")) {
event->acceptProposedAction();
}
}
void Schema::dropEvent(QDropEvent *event) {
2022-05-27 06:18:17 +00:00
if (event->mimeData()->hasFormat("comdel/component")) {
auto component = library->getComponent(event->mimeData()->data("comdel/component").toStdString());
auto attributes = std::vector<domain::InstanceAttribute>();
2022-05-27 06:18:17 +00:00
for (auto attr: component.getAttributes()) {
domain::InstanceAttribute attribute(attr.getName(), attr.getDefault(), attr);
if(attr.getPopup().has_value() && attr.getPopup()->getType() == domain::Popup::AUTOMATIC) {
if(attr.getDefault().isType(domain::Value::MEMORY_REFERENCE)) {
auto dialog = new MemoryDialog(&attribute, schema->componentInstances);
if(dialog->exec() == QDialog::Rejected) {
// if any dialog isn't set, whole creation is rejected
event->ignore();
return;
}
} else {
auto dialog = new AttributeDialog(&attribute);
if(dialog->exec() == QDialog::Rejected) {
// if any dialog isn't set, whole creation is rejected
event->ignore();
return;
}
}
}
attributes.push_back(attribute);
}
auto currentPos = this->mapToScene(event->pos()).toPoint();
auto instance = Application::instance()->addComponent(component, attributes, currentPos.x(), currentPos.y());
auto group = new display::ComponentGroup(instance);
scene.addItem(group);
2022-05-27 06:18:17 +00:00
for (auto pin: group->getPins()) {
display::Pin *p = pin;
2022-05-25 05:39:45 +00:00
domain::ConnectionComponent connection{instance->name, p->getPin().getName()};
pins.insert(std::make_pair(connection, p));
}
components[instance->name] = group;
event->acceptProposedAction();
}
2022-05-27 06:18:17 +00:00
if (event->mimeData()->hasFormat("comdel/bus")) {
auto bus = library->getBus(event->mimeData()->data("comdel/bus").toStdString());
auto currentPos = this->mapToScene(event->pos()).toPoint();
auto instance = Application::instance()->addBus(bus, currentPos.x(), currentPos.y());
auto group = new display::BusGroup(instance);
scene.addItem(group);
2022-05-25 05:39:45 +00:00
buses[instance->name] = group;
event->acceptProposedAction();
}
}
void Schema::dragMoveEvent(QDragMoveEvent *event) {
event->acceptProposedAction();
}
2022-05-25 05:39:45 +00:00
void Schema::removeConnectable(QPointF endPoint) {
auto instance = context.pin->getComponentInstance();
2022-05-27 06:18:17 +00:00
auto &pin = context.pin->getPin();
2022-05-25 05:39:45 +00:00
auto busInstances = getAvailableConnectionBusses(instance, pin);
2022-05-27 06:18:17 +00:00
for (auto &bus: busInstances) {
2022-05-25 05:39:45 +00:00
auto rect = buses[bus->name]->boundingRect();
rect = QRectF(buses[bus->name]->x(), buses[bus->name]->y(), rect.width(), rect.height());
2022-05-27 06:18:17 +00:00
if (rect.contains(endPoint)) {
2022-05-25 05:39:45 +00:00
auto con = library->getConnection({instance->component.getName(), pin.getName()}, bus->bus.getName());
2022-05-27 06:18:17 +00:00
if (con.has_value()) {
2022-05-25 05:39:45 +00:00
std::vector<domain::InstanceAttribute> attributes;
2022-05-27 06:18:17 +00:00
for (auto attr: con->getAttributes()) {
2022-05-25 05:39:45 +00:00
attributes.emplace_back(attr.getName(), attr.getDefault(), attr);
}
auto conInstance = std::make_shared<domain::BusConnectionInstance>(instance, attributes, bus, *con);
schema->connections.push_back(conInstance);
if (conInstance != nullptr) {
auto c = new display::BusConnection(conInstance.get(), components[conInstance->instance->name],
2022-05-27 06:18:17 +00:00
buses[conInstance->bus->name]);
2022-05-25 05:39:45 +00:00
busConnections.push_back(c);
scene.addItem(c);
}
break;
}
}
}
auto pinInstances = getAvailableConnectionPins(instance, pin);
2022-05-27 06:18:17 +00:00
for (auto &pinInstance: pinInstances) {
2022-05-25 05:39:45 +00:00
auto rect = pins[pinInstance]->boundingRect();
rect.setX(pins[pinInstance]->scenePos().x());
rect.setY(pins[pinInstance]->scenePos().y());
2022-05-27 06:18:17 +00:00
if (rect.contains(endPoint)) {
2022-05-25 05:39:45 +00:00
auto name = components[pinInstance.component]->getComponentInstance()->component.getName();
2022-05-27 06:18:17 +00:00
auto con = library->getConnection({instance->component.getName(), pin.getName()},
{name, pinInstance.pin});
if (con.has_value()) {
2022-05-25 05:39:45 +00:00
auto bus = library->getBus(con->getBus());
auto busInstance = std::make_shared<domain::BusInstance>(bus.getName(), bus);
schema->busInstances.push_back(busInstance);
std::vector<domain::InstanceAttribute> attributes;
2022-05-27 06:18:17 +00:00
for (auto attr: con->getAttributes()) {
2022-05-25 05:39:45 +00:00
attributes.emplace_back(attr.getName(), attr.getDefault(), attr);
}
2022-05-27 06:18:17 +00:00
auto conInstance = std::make_shared<domain::DirectConnectionInstance>(instance,
components[pinInstance.component]->getComponentInstance().get(),
attributes, busInstance.get(),
*con);
2022-05-25 05:39:45 +00:00
schema->connections.push_back(conInstance);
if (conInstance != nullptr) {
2022-05-27 06:18:17 +00:00
auto c = new display::DirectConnection(conInstance.get(),
components[conInstance->instance->name],
components[conInstance->secondInstance->name]);
2022-05-25 05:39:45 +00:00
directConnections.push_back(c);
scene.addItem(c);
}
break;
}
}
}
updateConnections();
2022-05-27 06:18:17 +00:00
for (auto &item: this->context.selectable) {
2022-05-25 05:39:45 +00:00
this->scene.removeItem(item);
delete item;
}
this->context.selectable.clear();
}
void Schema::showConnectable(Pin *domainPin) {
2022-05-27 06:18:17 +00:00
auto &pin = domainPin->getPin();
2022-05-25 05:39:45 +00:00
auto busInstances = getAvailableConnectionBusses(domainPin->getComponentInstance(), domainPin->getPin());
2022-05-27 06:18:17 +00:00
for (auto bus: busInstances) {
auto &group = buses[bus->name];
if(group == nullptr) {
continue;
}
2022-05-25 05:39:45 +00:00
auto rect = new QGraphicsRectItem(group->boundingRect());
rect->setPen(selectedPen);
rect->setPos(group->scenePos());
auto _rect = rect->rect();
_rect.setWidth(_rect.width() + 1);
_rect.setHeight(_rect.height() + 1);
rect->setRect(_rect);
context.selectable.push_back(rect);
scene.addItem(rect);
}
2022-05-27 06:18:17 +00:00
std::vector<domain::ConnectionComponent> pinInstances = getAvailableConnectionPins(
domainPin->getComponentInstance(), domainPin->getPin());
2022-05-25 05:39:45 +00:00
2022-05-27 06:18:17 +00:00
for (auto &pinInstance: pinInstances) {
auto &instance = pins[pinInstance];
2022-05-25 05:39:45 +00:00
auto rect = new QGraphicsRectItem(instance->boundingRect());
rect->setPen(selectedPen);
rect->setPos(instance->scenePos());
auto _rect = rect->rect();
_rect.setWidth(_rect.width() + 1);
_rect.setHeight(_rect.height() + 1);
rect->setRect(_rect);
context.selectable.push_back(rect);
scene.addItem(rect);
}
}
2022-05-27 06:18:17 +00:00
std::vector<domain::BusInstance *>
Schema::getAvailableConnectionBusses(domain::ComponentInstance *instance, domain::Pin &pin) {
std::vector<domain::BusInstance *> instances;
for (const auto &bus: schema->busInstances) {
if (library->hasConnection(domain::ConnectionComponent{instance->component.getName(), pin.getName()},
bus->bus.getName())) {
2022-05-25 05:39:45 +00:00
instances.push_back(bus.get());
}
}
return instances;
}
2022-05-27 06:18:17 +00:00
std::vector<domain::ConnectionComponent>
Schema::getAvailableConnectionPins(domain::ComponentInstance *instance, domain::Pin &pin) {
2022-05-25 05:39:45 +00:00
std::vector<domain::ConnectionComponent> instances;
domain::ConnectionComponent source{instance->component.getName(), pin.getName()};
2022-05-27 06:18:17 +00:00
for (const auto &entry: pins) {
2022-05-25 05:39:45 +00:00
std::string name = components[entry.first.component]->getComponentInstance()->component.getName();
2022-05-27 06:18:17 +00:00
if (library->hasConnection(source, domain::ConnectionComponent{name, entry.first.pin})) {
2022-05-25 05:39:45 +00:00
instances.push_back(entry.first);
}
}
return instances;
}
2022-04-07 22:21:23 +00:00
} // namespace display