#include "component_display.h" #include "schema_display.h" #include #include #include namespace display { Schema::Schema() { this->selectedBrush.setColor(QColor::fromRgb(20,20,125)); this->selectedPen.setColor(QColor::fromRgb(20, 20, 125)); this->setScene(&scene); this->setAcceptDrops(true); } void Schema::setSchema(domain::Schema* _schema, domain::Library* _library) { 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)); scene.addItem(group); } 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); } } for(auto &connection: schema->connections) { auto busInstance = dynamic_cast(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(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); } } } } void Schema::updateConnections() { if(schema != nullptr) { for(auto conn: busConnections) { conn->updateConnection(); } for(auto conn: directConnections) { conn->updateConnection(); } } } void Schema::dragEnterEvent(QDragEnterEvent *event) { if(event->mimeData()->hasFormat("comdel/component") || event->mimeData()->hasFormat("comdel/bus")) { event->acceptProposedAction(); } } 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(); for(auto attr: component.getAttributes()) { attributes.emplace_back(attr.getName(), attr.getDefault(), attr); } auto currentPos = this->mapToScene(event->pos()); auto instance = std::make_shared(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); 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[instance->name] = 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(bus.getName(), std::make_pair(currentPos.x(), currentPos.y()), bus); schema->busInstances.push_back(instance); auto group = new display::BusGroup(instance); scene.addItem(group); buses[instance->name] = group; event->acceptProposedAction(); } } void Schema::dragMoveEvent(QDragMoveEvent *event) { event->acceptProposedAction(); } void Schema::removeConnectable(QPointF endPoint) { auto instance = context.pin->getComponentInstance(); auto& pin = context.pin->getPin(); auto busInstances = getAvailableConnectionBusses(instance, pin); for(auto &bus: busInstances) { auto rect = buses[bus->name]->boundingRect(); rect = QRectF(buses[bus->name]->x(), buses[bus->name]->y(), rect.width(), rect.height()); if(rect.contains(endPoint)) { auto con = library->getConnection({instance->component.getName(), pin.getName()}, bus->bus.getName()); if(con.has_value()) { std::vector attributes; for(auto attr: con->getAttributes()) { attributes.emplace_back(attr.getName(), attr.getDefault(), attr); } auto conInstance = std::make_shared(instance, attributes, bus, *con); schema->connections.push_back(conInstance); if (conInstance != nullptr) { auto c = new display::BusConnection(conInstance.get(), components[conInstance->instance->name], buses[conInstance->bus->name]); busConnections.push_back(c); scene.addItem(c); } break; } } } auto pinInstances = getAvailableConnectionPins(instance, pin); for(auto &pinInstance: pinInstances) { auto rect = pins[pinInstance]->boundingRect(); rect.setX(pins[pinInstance]->scenePos().x()); rect.setY(pins[pinInstance]->scenePos().y()); if(rect.contains(endPoint)) { auto name = components[pinInstance.component]->getComponentInstance()->component.getName(); auto con = library->getConnection({instance->component.getName(), pin.getName()}, {name, pinInstance.pin}); if(con.has_value()) { auto bus = library->getBus(con->getBus()); auto busInstance = std::make_shared(bus.getName(), bus); schema->busInstances.push_back(busInstance); std::vector attributes; for(auto attr: con->getAttributes()) { attributes.emplace_back(attr.getName(), attr.getDefault(), attr); } auto conInstance = std::make_shared(instance, components[pinInstance.component]->getComponentInstance().get(), attributes, busInstance.get(), *con); schema->connections.push_back(conInstance); if (conInstance != nullptr) { auto c = new display::DirectConnection(conInstance.get(), components[conInstance->instance->name], components[conInstance->secondInstance->name]); directConnections.push_back(c); scene.addItem(c); } break; } } } updateConnections(); for(auto& item: this->context.selectable) { this->scene.removeItem(item); delete item; } this->context.selectable.clear(); } void Schema::showConnectable(Pin *domainPin) { auto& pin = domainPin->getPin(); auto busInstances = getAvailableConnectionBusses(domainPin->getComponentInstance(), domainPin->getPin()); for(auto bus: busInstances) { auto& group = buses[bus->name]; 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); } std::vector pinInstances = getAvailableConnectionPins(domainPin->getComponentInstance(), domainPin->getPin()); for(auto& pinInstance: pinInstances) { auto& instance = pins[pinInstance]; 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); } } std::vector Schema::getAvailableConnectionBusses(domain::ComponentInstance *instance, domain::Pin &pin) { std::vector instances; for(const auto& bus: schema->busInstances) { if(library->hasConnection(domain::ConnectionComponent{instance->component.getName(), pin.getName()}, bus->bus.getName())) { instances.push_back(bus.get()); } } return instances; } std::vector Schema::getAvailableConnectionPins(domain::ComponentInstance *instance, domain::Pin &pin) { std::vector instances; domain::ConnectionComponent source{instance->component.getName(), pin.getName()}; for(const auto& entry: pins) { std::string name = components[entry.first.component]->getComponentInstance()->component.getName(); if(library->hasConnection(source, domain::ConnectionComponent{name, entry.first.pin})) { instances.push_back(entry.first); } } return instances; } } // namespace display