#include "ElaGraphicsScene.h" #include #include #include #include #include #include "ElaGraphicsItem.h" #include "ElaGraphicsLineItem.h" #include "private/ElaGraphicsScenePrivate.h" Q_PROPERTY_CREATE_Q_CPP(ElaGraphicsScene, bool, IsCheckLinkPort) Q_PROPERTY_CREATE_Q_CPP(ElaGraphicsScene, QString, SerializePath) ElaGraphicsScene::ElaGraphicsScene(QObject *parent) : QGraphicsScene(parent), d_ptr(new ElaGraphicsScenePrivate()) { Q_D(ElaGraphicsScene); d->q_ptr = this; setItemIndexMethod(QGraphicsScene::NoIndex); d->_pIsCheckLinkPort = false; d->_sceneMode = ElaGraphicsSceneType::SceneMode::Default; d->_pSerializePath = "./scene.bin"; } ElaGraphicsScene::~ElaGraphicsScene() {} void ElaGraphicsScene::addItem(ElaGraphicsItem *item) { Q_D(ElaGraphicsScene); if (!item) { return; } for (const auto &pair : d->_items.toStdMap()) { if (pair.second == item) { return; } } item->setParent(this); item->setZValue(d->_currentZ); if (item->getItemName().isEmpty()) { item->setItemName(QString("ElaItem%1").arg(d->_currentZ)); } item->setPos(sceneRect().width() / 2, sceneRect().height() / 2); QGraphicsScene::addItem(item); d->_currentZ++; d->_items.insert(item->getItemUID(), item); } void ElaGraphicsScene::removeItem(ElaGraphicsItem *item) { Q_D(ElaGraphicsScene); if (!item) { return; } d->_items.remove(d->_items.key(item)); removeItemLink(item); QGraphicsScene::removeItem(item); delete item; update(); } void ElaGraphicsScene::removeSelectedItems() { QList selectedItemList = getSelectedElaItems(); if (selectedItemList.count() == 0) { return; } for (auto item : selectedItemList) { removeItem(item); } } void ElaGraphicsScene::clear() { Q_D(ElaGraphicsScene); d->_itemsLink.clear(); for (const auto &pair : d->_items.toStdMap()) { delete pair.second; } d->_items.clear(); update(); } QList ElaGraphicsScene::createAndAddItem(int width, int height, int count) { if (count <= 0) { return QList(); } QList createItemList; for (int i = 0; i < count; i++) { ElaGraphicsItem *item = new ElaGraphicsItem(); item->setWidth(width); item->setHeight(height); createItemList.append(item); addItem(item); } return createItemList; } QList ElaGraphicsScene::getSelectedElaItems() const { QList selectedItemList = selectedItems(); QList selectedElaItemList; for (auto item : selectedItemList) { ElaGraphicsItem *itemCast = dynamic_cast(item); if (itemCast) { selectedElaItemList.append(itemCast); } } return selectedElaItemList; } QList ElaGraphicsScene::getElaItems() { Q_D(ElaGraphicsScene); return d->_items.values(); } QList ElaGraphicsScene::getElaItems(QPoint pos) { QList itemList = items(pos); QList elaItemList; for (auto item : itemList) { ElaGraphicsItem *elaItem = dynamic_cast(item); if (elaItem) { elaItemList.append(elaItem); } } return elaItemList; } QList ElaGraphicsScene::getElaItems(QPointF pos) { QList itemList = items(pos); QList elaItemList; for (auto item : itemList) { ElaGraphicsItem *elaItem = dynamic_cast(item); if (elaItem) { elaItemList.append(elaItem); } } return elaItemList; } QList ElaGraphicsScene::getElaItems(QRect rect) { QList itemList = items(rect); QList elaItemList; for (auto item : itemList) { ElaGraphicsItem *elaItem = dynamic_cast(item); if (elaItem) { elaItemList.append(elaItem); } } return elaItemList; } QList ElaGraphicsScene::getElaItems(QRectF rect) { QList itemList = items(rect); QList elaItemList; for (auto item : itemList) { ElaGraphicsItem *elaItem = dynamic_cast(item); if (elaItem) { elaItemList.append(elaItem); } } return elaItemList; } void ElaGraphicsScene::setSceneMode(ElaGraphicsSceneType::SceneMode mode) { Q_D(ElaGraphicsScene); d->_sceneMode = mode; if (mode == ElaGraphicsSceneType::SceneMode::DragMove) { views().at(0)->setDragMode(QGraphicsView::ScrollHandDrag); } else { views().at(0)->setDragMode(QGraphicsView::RubberBandDrag); } } ElaGraphicsSceneType::SceneMode ElaGraphicsScene::getSceneMode() const { return d_ptr->_sceneMode; } void ElaGraphicsScene::selectAllItems() { Q_D(ElaGraphicsScene); for (const auto &pair : d->_items.toStdMap()) { ElaGraphicsItem *item = pair.second; item->setSelected(true); } } QList ElaGraphicsScene::getItemLinkList() const { return d_ptr->_itemsLink; } bool ElaGraphicsScene::addItemLink(ElaGraphicsItem *item1, ElaGraphicsItem *item2, int port1, int port2) { Q_D(ElaGraphicsScene); if (!item1 || !item2 || (item1 == item2) || port1 < 0 || port2 < 0 || item1->getMaxLinkPortCount() <= port1 || item2->getMaxLinkPortCount() <= port2) { return false; } if (d->_pIsCheckLinkPort) { if (!item1->getLinkPortState(port1) && !item2->getLinkPortState(port2)) { item1->setLinkPortState(true, port1); item2->setLinkPortState(true, port2); } else { return false; } } QVariantMap linkObject; linkObject.insert(item1->getItemUID(), port1); linkObject.insert(item2->getItemUID(), port2); d->_itemsLink.append(linkObject); ElaGraphicsLineItem *lineItem = new ElaGraphicsLineItem(item1, item2, port1, port2); QGraphicsScene::addItem(lineItem); d->_lineItemsList.append(lineItem); update(); return true; } bool ElaGraphicsScene::removeItemLink(ElaGraphicsItem *item1) { Q_D(ElaGraphicsScene); if (!item1) { return false; } if (d->_pIsCheckLinkPort) { item1->setLinkPortState(false); } // 处理与该Item有关的连接 foreach (auto &link, d->_itemsLink) { if (link.contains(item1->getItemUID())) { if (d->_pIsCheckLinkPort) { // 解除otherItem端口占用 QStringList keys = link.keys(); keys.removeOne(item1->getItemUID()); ElaGraphicsItem *otherItem = d->_items.value(keys.at(0)); otherItem->setLinkPortState(false, link.value(keys.at(0)).toInt()); } d->_itemsLink.removeOne(link); } } // 处理连接图元 foreach (auto lineItem, d->_lineItemsList) { if (lineItem->isTargetLink(item1)) { d->_lineItemsList.removeOne(lineItem); QGraphicsScene::removeItem(lineItem); delete lineItem; } } update(); return true; } bool ElaGraphicsScene::removeItemLink(ElaGraphicsItem *item1, ElaGraphicsItem *item2, int port1, int port2) { Q_D(ElaGraphicsScene); if (!item1 || !item2) { return false; } bool isLinkExist = false; foreach (auto &link, d->_itemsLink) { QVariant portVariant1 = link.value(item1->getItemUID()); QVariant portVariant2 = link.value(item2->getItemUID()); if (portVariant1.isValid() && portVariant2.isValid() && portVariant1.toUInt() == port1 && portVariant2.toUInt() == port2) { d->_itemsLink.removeOne(link); // 这里处理连线图元 isLinkExist = true; break; } } foreach (auto lineItem, d->_lineItemsList) { if (lineItem->isTargetLink(item1, item2, port1, port2)) { d->_lineItemsList.removeOne(lineItem); QGraphicsScene::removeItem(lineItem); delete lineItem; break; } } if (isLinkExist) { if (d->_pIsCheckLinkPort) { item1->setLinkPortState(false, port1); item2->setLinkPortState(false, port2); } update(); return true; } else { return false; } } QVector ElaGraphicsScene::getItemsDataRoute() const { QVector dataRouteVector; for (const auto &pair : d_ptr->_items.toStdMap()) { ElaGraphicsItem *item = pair.second; dataRouteVector.append(item->getDataRoutes()); } return dataRouteVector; } void ElaGraphicsScene::serialize() { Q_D(ElaGraphicsScene); QFile file(d->_pSerializePath); if (!file.open(QIODevice::WriteOnly)) { qDebug() << "serialize Error"; return; } QDataStream serialStream(&file); serialStream << d; file.flush(); file.close(); } void ElaGraphicsScene::deserialize() { Q_D(ElaGraphicsScene); QFile file(d->_pSerializePath); if (!file.open(QIODevice::ReadOnly)) { qDebug() << "deserialize Error"; return; } QDataStream deserialStream(&file); deserialStream >> d; file.close(); update(); } void ElaGraphicsScene::focusOutEvent(QFocusEvent *event) { Q_D(ElaGraphicsScene); d->_sceneMode = ElaGraphicsSceneType::SceneMode::Default; d->_removeLinkLineItem(); QGraphicsScene::focusOutEvent(event); } void ElaGraphicsScene::keyPressEvent(QKeyEvent *event) { Q_D(ElaGraphicsScene); switch (event->key()) { case Qt::Key_Control: { d->_sceneMode = ElaGraphicsSceneType::SceneMode::MultiSelect; break; } case Qt::Key_Shift: { d->_sceneMode = ElaGraphicsSceneType::SceneMode::ItemLink; clearSelection(); break; } case Qt::Key_Delete: { removeSelectedItems(); break; } } QGraphicsScene::keyPressEvent(event); } void ElaGraphicsScene::keyReleaseEvent(QKeyEvent *event) { Q_D(ElaGraphicsScene); d->_sceneMode = ElaGraphicsSceneType::SceneMode::Default; d->_removeLinkLineItem(); QGraphicsScene::keyReleaseEvent(event); } void ElaGraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent *event) { Q_D(ElaGraphicsScene); if (event->button() == Qt::LeftButton) { if (d->_sceneMode == ElaGraphicsSceneType::SceneMode::Default) { d->_isLeftButtonPress = true; d->_lastPos = event->pos(); } } QList selectedItemList = selectedItems(); QGraphicsScene::mousePressEvent(event); if (d->_sceneMode == ElaGraphicsSceneType::SceneMode::ItemLink) { for (auto item : selectedItemList) { item->setSelected(true); } d->_lastPos = event->pos(); } } void ElaGraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { Q_D(ElaGraphicsScene); QList itemList = getElaItems(event->scenePos()); if (event->button() == Qt::LeftButton) { d->_isLeftButtonPress = false; switch (d->_sceneMode) { case ElaGraphicsSceneType::SceneMode::Default: { if (itemList.count() > 0) { Q_EMIT mouseLeftClickedItem(itemList[0]); } break; } case ElaGraphicsSceneType::SceneMode::ItemLink: { QList selectedItemList = getSelectedElaItems(); if (selectedItemList.count() == 1 && !d->_linkLineItem) { d->_linkLineItem = new ElaGraphicsLineItem(selectedItemList.at(0)->pos(), selectedItemList.at(0)->pos()); QGraphicsScene::addItem(d->_linkLineItem); } else if (selectedItemList.count() == 2) { if (d->_pIsCheckLinkPort) { Q_EMIT showItemLink(); } else { QVariantMap linkObject; for (auto item : selectedItemList) { linkObject.insert(item->getItemUID(), 0); } d->_itemsLink.append(linkObject); QGraphicsScene::mouseReleaseEvent(event); d->_removeLinkLineItem(); addItemLink(selectedItemList.at(0), selectedItemList.at(1)); clearSelection(); return; } } else { d->_removeLinkLineItem(); update(); } break; } default: { break; } } } else if (event->button() == Qt::RightButton) { if (itemList.count() > 0) { clearSelection(); itemList[0]->setSelected(true); Q_EMIT mouseRightClickedItem(itemList[0]); } } QGraphicsScene::mouseReleaseEvent(event); } void ElaGraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { Q_D(ElaGraphicsScene); if (d->_sceneMode == ElaGraphicsSceneType::SceneMode::ItemLink) { if (getSelectedElaItems().count() == 1) { if (d->_linkLineItem) { d->_linkLineItem->setEndPoint(event->scenePos()); d->_linkLineItem->update(); } } } else { if (d->_isLeftButtonPress) { for (auto lineItem : d->_lineItemsList) { lineItem->update(); } } } QGraphicsScene::mouseMoveEvent(event); } void ElaGraphicsScene::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) { QList itemList = getElaItems(event->scenePos()); if (itemList.count() > 0) { Q_EMIT mouseDoubleClickedItem(itemList[0]); } QGraphicsScene::mouseDoubleClickEvent(event); }