QGraphicsItem* GIFactory::createComponentGI( ComponentDescriptor* type) { qDebug() << "Generating Graphics item for" << type->text(); // collect all the information QString componentName = type->text(); QGraphicsItemGroup* parent = new QGraphicsItemGroup(); // create all the partial items and calculate sizes unsigned int inSection_minWidth = 0; unsigned int outSection_minWidth = 0; unsigned int portSection_lineHeight = 0; QList<PortEntry> inPorts = QList<PortEntry>(); QList<PortEntry> outPorts = QList<PortEntry>(); for (PortDescriptor * port : type->ports()) { PortEntry portEntry = PortEntry(port, parent); unsigned int width = portEntry.textGraphics()->boundingRect().width() + 2 * TEXT_PADDING; unsigned int height = portEntry.textGraphics()->boundingRect().height() + 2 * TEXT_PADDING; // adjust the line height, if needed if (height > portSection_lineHeight) { portSection_lineHeight = height; } switch (port->direction()) { case model::enums::PortDirection::IN : { inPorts.append(portEntry); if (width > inSection_minWidth) { inSection_minWidth = width; } } break; case model::enums::PortDirection::OUT : { outPorts.append(portEntry); if (width > outSection_minWidth) { outSection_minWidth = width; } } break; default: continue; // do not handle other types. } } std::sort(inPorts.begin(), inPorts.end()); std::sort(outPorts.begin(), outPorts.end()); unsigned int portSection_height = inPorts.count() > outPorts.count() ? inPorts.count() * portSection_lineHeight : outPorts.count() * portSection_lineHeight; QGraphicsTextItem* text_compName = new QGraphicsTextItem(componentName, parent); parent->addToGroup(text_compName); unsigned int nameSection_minWidth = text_compName->boundingRect().width() + 2 * TEXT_PADDING; unsigned int nameSection_height = text_compName->boundingRect().height() + 2 * TEXT_PADDING; // adjust the total width unsigned int totalWidth = 0; if (nameSection_minWidth > (inSection_minWidth + outSection_minWidth)) { totalWidth = nameSection_minWidth; if (inSection_minWidth > totalWidth / 2) { // extend outSection_minWidth outSection_minWidth = totalWidth - inSection_minWidth; } else if (outSection_minWidth > totalWidth / 2) { // extend inSection_minWidth inSection_minWidth = totalWidth - outSection_minWidth; } else { // stretch both to totalWidth / 2 inSection_minWidth = totalWidth / 2; outSection_minWidth = totalWidth / 2; } } else { // adjust nameSection_minWidth totalWidth = inSection_minWidth + outSection_minWidth; } // now actually place all the stuff QBrush nameSectionBrush = QBrush(Qt::lightGray, Qt::SolidPattern); QBrush portSectionBrush = QBrush(Qt::white, Qt::SolidPattern); QPen pen = QPen(Qt::black, Qt::SolidLine); QPoint currentPos = QPoint(0, 0); // draw the rectangles QGraphicsRectItem* nameSection = new QGraphicsRectItem( currentPos.x(), currentPos.y(), totalWidth, nameSection_height, parent); nameSection->setBrush(nameSectionBrush); nameSection->setPen(pen); nameSection->setZValue(-1); parent->addToGroup(nameSection); currentPos.ry() += nameSection_height; QGraphicsRectItem* inSection = new QGraphicsRectItem( currentPos.x(), currentPos.y(), inSection_minWidth, portSection_height, parent); inSection->setBrush(portSectionBrush); inSection->setPen(pen); inSection->setZValue(-1); parent->addToGroup(inSection); currentPos.rx() += inSection_minWidth; QGraphicsRectItem* outSection = new QGraphicsRectItem( currentPos.x(), currentPos.y(), outSection_minWidth, portSection_height, parent); outSection->setBrush(portSectionBrush); outSection->setPen(pen); outSection->setZValue(-1); parent->addToGroup(outSection); // place the texts and set the port positions in the port descriptor text_compName->setPos((totalWidth - text_compName->boundingRect().width()) / 2, /*0 + */ TEXT_PADDING); currentPos.setX(0); currentPos.setY(nameSection_height); for(PortEntry inIter : inPorts){ inIter.textGraphics()->setPos(currentPos.x() + TEXT_PADDING, currentPos.y() + TEXT_PADDING); currentPos.ry() += portSection_lineHeight / 2; QPoint portPos = QPoint(currentPos.x() - PORT_DIAMETER, currentPos.y()); inIter.descriptor()->setPosition(portPos); QGraphicsLineItem* lineToPort = new QGraphicsLineItem(QLineF(portPos, currentPos), parent); parent->addToGroup(lineToPort); currentPos.ry() += portSection_lineHeight / 2; } currentPos.setX(totalWidth); currentPos.setY(nameSection_height); for(PortEntry outIter : outPorts){ outIter.textGraphics()->setPos( currentPos.x() - TEXT_PADDING - outIter.textGraphics()->boundingRect().width(), currentPos.y() + TEXT_PADDING); currentPos.ry() += portSection_lineHeight / 2; QPoint portPos = QPoint(currentPos.x() + PORT_DIAMETER, currentPos.y()); outIter.descriptor()->setPosition(portPos); QGraphicsLineItem* lineToPort = new QGraphicsLineItem(QLineF(currentPos, portPos), parent); parent->addToGroup(lineToPort); currentPos.ry() += portSection_lineHeight / 2; } parent->setVisible(true); return parent; }
BoardScene::BoardScene(const SLFormat::Board* inBoard, QWidget* inParent) :QGraphicsScene(inParent), mBoard(inBoard) { this->setSceneRect(0, 0, mBoard->size().x, mBoard->size().y); // background const unsigned activeLayer = mBoard->activeLayer(); QBrush brush(gSettings().backgroundColor()); QPen pen(brush.color()); mBackground = this->addRect(this->sceneRect(), pen, brush); // ground planes (initially invisible) for (unsigned i = 0; i < SLFormat::Board::cNumberLayers; i++) { unsigned layer = gSettings().layerFromOrderNumber(i); if (mBoard->isGroundPlaneSupported(layer)) { QGraphicsItemGroup* plane = new QGraphicsItemGroup; mGroundPlanes[layer] = plane; addItem(plane); plane->setVisible(false); auto rect = new QGraphicsRectItem(this->sceneRect()); const QColor color = gSettings().groundPlaneLayerColor(layer); rect->setBrush(QBrush(color)); rect->setPen(QPen(color)); plane->addToGroup(rect); } else { mGroundPlanes[layer] = nullptr; } } // grid mGrid = new BoardGrid(mBoard); addItem(mGrid); // layers for (unsigned i = 0; i < SLFormat::Board::cNumberLayers; i++) { unsigned layer = gSettings().layerFromOrderNumber(i); mLayerGroups[layer] = new QGraphicsItemGroup; addItem(mLayerGroups[layer]); } mDrillHoles = new QGraphicsItemGroup; addItem(mDrillHoles); // components on layers for (auto comp : mBoard->components()) { ComponentItem* item = ComponentFactory::createItem(comp); if (item) { unsigned layer = comp->layer(); mLayerGroups[layer]->addToGroup(item->mainItem()); if (mBoard->isGroundPlaneSupported(layer)) { mGroundPlanes[layer]->addToGroup(item->groundPlaneItem()); } mDrillHoles->addToGroup(item->drillItem()); } } // show ground plane for active layer if (mBoard->isGroundPlaneEnabled(activeLayer)) { assert(mGroundPlanes[activeLayer]); mGroundPlanes[activeLayer]->setVisible(true); } }