feat: 添加ElaWidgetTool库
This commit is contained in:
556
ElaWidgetTools/ElaGraphicsScene.cpp
Normal file
556
ElaWidgetTools/ElaGraphicsScene.cpp
Normal file
@@ -0,0 +1,556 @@
|
||||
#include "ElaGraphicsScene.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
#include <QGraphicsSceneMouseEvent>
|
||||
#include <QGraphicsView>
|
||||
#include <QKeyEvent>
|
||||
|
||||
#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<ElaGraphicsItem*> 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<ElaGraphicsItem*> ElaGraphicsScene::createAndAddItem(int width, int height, int count)
|
||||
{
|
||||
if (count <= 0)
|
||||
{
|
||||
return QList<ElaGraphicsItem*>();
|
||||
}
|
||||
QList<ElaGraphicsItem*> 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<ElaGraphicsItem*> ElaGraphicsScene::getSelectedElaItems() const
|
||||
{
|
||||
QList<QGraphicsItem*> selectedItemList = selectedItems();
|
||||
QList<ElaGraphicsItem*> selectedElaItemList;
|
||||
for (auto item : selectedItemList)
|
||||
{
|
||||
ElaGraphicsItem* itemCast = dynamic_cast<ElaGraphicsItem*>(item);
|
||||
if (itemCast)
|
||||
{
|
||||
selectedElaItemList.append(itemCast);
|
||||
}
|
||||
}
|
||||
return selectedElaItemList;
|
||||
}
|
||||
|
||||
QList<ElaGraphicsItem*> ElaGraphicsScene::getElaItems()
|
||||
{
|
||||
Q_D(ElaGraphicsScene);
|
||||
return d->_items.values();
|
||||
}
|
||||
|
||||
QList<ElaGraphicsItem*> ElaGraphicsScene::getElaItems(QPoint pos)
|
||||
{
|
||||
QList<QGraphicsItem*> itemList = items(pos);
|
||||
QList<ElaGraphicsItem*> elaItemList;
|
||||
for (auto item : itemList)
|
||||
{
|
||||
ElaGraphicsItem* elaItem = dynamic_cast<ElaGraphicsItem*>(item);
|
||||
if (elaItem)
|
||||
{
|
||||
elaItemList.append(elaItem);
|
||||
}
|
||||
}
|
||||
return elaItemList;
|
||||
}
|
||||
|
||||
QList<ElaGraphicsItem*> ElaGraphicsScene::getElaItems(QPointF pos)
|
||||
{
|
||||
QList<QGraphicsItem*> itemList = items(pos);
|
||||
QList<ElaGraphicsItem*> elaItemList;
|
||||
for (auto item : itemList)
|
||||
{
|
||||
ElaGraphicsItem* elaItem = dynamic_cast<ElaGraphicsItem*>(item);
|
||||
if (elaItem)
|
||||
{
|
||||
elaItemList.append(elaItem);
|
||||
}
|
||||
}
|
||||
return elaItemList;
|
||||
}
|
||||
|
||||
QList<ElaGraphicsItem*> ElaGraphicsScene::getElaItems(QRect rect)
|
||||
{
|
||||
QList<QGraphicsItem*> itemList = items(rect);
|
||||
QList<ElaGraphicsItem*> elaItemList;
|
||||
for (auto item : itemList)
|
||||
{
|
||||
ElaGraphicsItem* elaItem = dynamic_cast<ElaGraphicsItem*>(item);
|
||||
if (elaItem)
|
||||
{
|
||||
elaItemList.append(elaItem);
|
||||
}
|
||||
}
|
||||
return elaItemList;
|
||||
}
|
||||
|
||||
QList<ElaGraphicsItem*> ElaGraphicsScene::getElaItems(QRectF rect)
|
||||
{
|
||||
QList<QGraphicsItem*> itemList = items(rect);
|
||||
QList<ElaGraphicsItem*> elaItemList;
|
||||
for (auto item : itemList)
|
||||
{
|
||||
ElaGraphicsItem* elaItem = dynamic_cast<ElaGraphicsItem*>(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<QVariantMap> 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<QVariantMap> ElaGraphicsScene::getItemsDataRoute() const
|
||||
{
|
||||
QVector<QVariantMap> 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<QGraphicsItem*> 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<ElaGraphicsItem*> 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<ElaGraphicsItem*> 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<ElaGraphicsItem*> itemList = getElaItems(event->scenePos());
|
||||
if (itemList.count() > 0)
|
||||
{
|
||||
Q_EMIT mouseDoubleClickedItem(itemList[0]);
|
||||
}
|
||||
QGraphicsScene::mouseDoubleClickEvent(event);
|
||||
}
|
||||
Reference in New Issue
Block a user