add item rotate property to propertyEditor

This commit is contained in:
baiYue 2026-02-04 20:44:59 +08:00
parent 6f3f266838
commit f1dcea6308
14 changed files with 575 additions and 114 deletions

View File

@ -62,7 +62,7 @@ protected:
DesignerScene* m_pGraphicsScene;
SelectorManager* m_pSelectorManager;
StatusBar* m_pStatusBar;
QPointer<FixedPortsModel> _pModel;
FixedPortsModel* _pModel;
DiagramMode _mode;
QString _name;
PowerEntity* _pEntity; //组态图拓扑对象

View File

@ -63,6 +63,7 @@ public:
QWidget* getTopWidget();
QPointF getTerminalPos(const QString& sTerminalId); //获取拓扑接线点在当前diagram中的位置
ElectricConnectLineItem* getLineItemById(const QString& terminalId);
void updateItemLinePort(QUuid,ModelFunctionType); //刷新连接item的线端点位置
void showModelDlg(const QString&,QUuid,GraphicsProjectModelItem*); //点击时显示指定模型的dlg、指定item的数据(模型名对象Uuid,触发事件的item)
void initialPropertyDlg(); //初始化属性设置dlg每个模型拥各自的dlg
@ -153,6 +154,7 @@ public Q_SLOTS:
void onSignal_generateDiagram(const QString&); //生成工程组态信号
void onSignal_openBayManager();
void onDataTimerOut();
void onSelectionChanged();
private:
void addPortsToItem_json(PortState,QJsonArray,GraphicsProjectModelItem*); //将json格式的port添加到item
void autoSetModelName(GraphicsBaseModelItem*); //如果此页的工程模已被设置将projectName更新到item

View File

@ -18,14 +18,26 @@ public:
QPainterPath getPoints(void) const { return m_points; }
void moveLine(QPointF); //鼠标点击拖动
void calculatePath();
void resetCurLine(){_curLine = QPoint();}
void calculatePath();
void generateAvoidancePath(const QPointF& start, const QPointF& end,const QList<QRectF>& obstacleShapes); // 使用形状进行避障
double calculatePathLength(const QList<QPointF>& path);
bool lineIntersectsRect(const QLineF& line, const QRectF& rect);
bool isSegmentSafe(const QPointF& p1, const QPointF& p2,const QList<QRectF>& components);
bool isPathSafe(const QList<QPointF>& path,const QList<QRectF>& components);
bool segmentPenetratesComponent(const QLineF& segment,const QRectF& component);
QRectF getTotalComponentsBounds(const QList<QRectF>& components);
void collectRectilinearPaths(const QPointF& start, const QPointF& end,const QList<QRectF>& components,QMultiMap<double, QList<QPointF>>& paths);
void addPathIfRectilinear(const QList<QPointF>& path,QMultiMap<double, QList<QPointF>>& paths);
void collectBypassPaths(const QPointF& start, const QPointF& end,const QList<QRectF>& components,QMultiMap<double, QList<QPointF>>& paths);
void generateForcedRectilinearBypass(const QPointF& start, const QPointF& end,const QList<QRectF>& components);
QRectF findFirstBlockingComponent(const QPointF& start, const QPointF& end,const QList<QRectF>& components);
protected:
virtual QPainterPath shape() const override;
virtual QRectF boundingRect() const override;
virtual void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*) override;
private:
protected:
void initial();
private:
QPainterPath m_points;

View File

@ -14,6 +14,8 @@
#include "propertyType/dataSourceType.h"
//#include "graphicsItem/itemPort.h"
class FixedPortsModel;
enum ShapeType
{
T_undefined,
@ -171,12 +173,35 @@ protected:
class GraphicsBaseItem :public QObject, public AbstractShapeType<QGraphicsItem>
{
Q_OBJECT
public:
public:
enum RotateAngle {
Angle_0 = 0,
Angle_90 = 90,
Angle_180 = 180,
Angle_270 = 270
};
Q_ENUM(RotateAngle);
Q_PROPERTY(QString Name READ getName WRITE setName)
Q_PROPERTY(QPointF Position READ getPosition WRITE setPosition)
Q_PROPERTY(QRectF Size READ getSize WRITE setSize)
Q_PROPERTY(RotateAngle Rotation READ getRotateAngle WRITE setRotateAngle)
public:
GraphicsBaseItem(QGraphicsItem *parent);
GraphicsBaseItem(const GraphicsBaseItem&);
virtual ~GraphicsBaseItem();
virtual GraphicsBaseItem* clone() const = 0;
signals:
void itemRotated(GraphicsBaseItem*);
public:
virtual QString getName() const;
virtual void setName(QString);
virtual QPointF getPosition() const;
virtual void setPosition(QPointF);
virtual QRectF getSize() const;
virtual void setSize(QRectF);
virtual RotateAngle getRotateAngle() const;
virtual void setRotateAngle(RotateAngle);
public:
int addPort(PortState typ,QPointF vec,QString id = "",HandleType hType = T_lineInOut,PortPos pos = P_top,double dXPercent = 0,double dYPercent = 0); //新建,返回-1失败
virtual void movePort(QString id,QPointF vec); //移动可动点
@ -206,6 +231,7 @@ public:
virtual bool hasDynamicText(const QString& tag);
virtual void setDynamicLayoutRadius(qreal radius);
virtual QMap<QString,HandleText*> getDynamicText() {return m_mapDynamicText;}
void setHandle(FixedPortsModel* p){_pHandle = p;}
int collidesWithHandle(const QPointF& point)
{
@ -489,7 +515,10 @@ public slots:
void onUpdateData(); //data发送的更新通知
protected:
void rearrangeDynamicText(); //重新设置动态数据的布局
QList<QRectF> getComponentCollisionRects() const; //获取图所有碰撞矩形
QList<QPainterPath> getObstacleShapes() const; //获取所有碰撞shape
protected:
FixedPortsModel* _pHandle;
ModelProperty* _property;
PowerEntity* _pEntity; //图元拓扑
bool _itemChanged; //图元变化标志,判断是否需要保存
@ -543,10 +572,8 @@ class GraphicsProjectModelItem : public GraphicsBaseItem //工程模item
{
Q_OBJECT
public:
Q_PROPERTY(QString Name READ getName WRITE setName)
Q_PROPERTY(QPointF Position READ getPosition WRITE setPosition)
Q_PROPERTY(QRectF Size READ getSize WRITE setSize)
Q_PROPERTY(DataSourceType DataSourceType READ getDataSourceType WRITE setDataSourceType)
public:
GraphicsProjectModelItem(QGraphicsItem *parent);
GraphicsProjectModelItem(const GraphicsProjectModelItem&);
@ -595,12 +622,6 @@ public:
}
}
public:
QString getName() const;
void setName(QString);
QPointF getPosition() const;
void setPosition(QPointF);
QRectF getSize() const;
void setSize(QRectF);
DataSourceType getDataSourceType() const;
void setDataSourceType(DataSourceType);
protected:

View File

@ -22,6 +22,7 @@ public:
QVariantMap properties() const { return m_properties; }
DataState state() {return m_state;}
void setState(DataState s) {m_state = s;}
void setId(QString sId){m_uuid = sId;}
void setProperty(const QString& key, const QVariant& value);

View File

@ -23,7 +23,7 @@ BaseDrawingPanel::BaseDrawingPanel(PowerEntity* pEntity,QWidget *parent,DiagramM
,_pPropertyProxy(nullptr)
{
_pEntity = pEntity;
_pModel = QPointer<FixedPortsModel>(new FixedPortsModel(pEntity));
_pModel = new FixedPortsModel(pEntity);
_pModel->setTopWidget(this);
m_pSelectorManager = new SelectorManager(_pModel,this);
m_pGraphicsScene = new DesignerScene(_pModel,this);
@ -36,20 +36,7 @@ BaseDrawingPanel::BaseDrawingPanel(PowerEntity* pEntity,QWidget *parent,DiagramM
m_pGraphicsView->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
m_pGraphicsScene->setView(m_pGraphicsView);
_pModel->setScene(m_pGraphicsScene);
connect(m_pGraphicsScene, &DesignerScene::selectionChanged, this, [&](){
QList<QGraphicsItem*> selectedItems = m_pGraphicsScene->selectedItems();
if(_pModel){
auto pCavas = _pModel->getCavas();
if(pCavas){
if(selectedItems.count() != 1) {
_pModel->getCavas()->onTargetSelected(_pPropertyProxy);
return;
}
GraphicsBaseItem *item = static_cast<GraphicsBaseItem*>(selectedItems.first());
_pModel->getCavas()->onTargetSelected(item);
}
}
});
connect(m_pGraphicsScene, &DesignerScene::selectionChanged, _pModel, &FixedPortsModel::onSelectionChanged);
m_pStatusBar = new StatusBar(this);
m_pStatusBar->setMaximumHeight(25);
@ -77,8 +64,8 @@ BaseDrawingPanel::BaseDrawingPanel(PowerEntity* pEntity,QWidget *parent,DiagramM
BaseDrawingPanel::~BaseDrawingPanel()
{
if(_pModel)
delete _pModel;
//if(_pModel)
// delete _pModel;
if(_pPropertyProxy)
delete _pPropertyProxy;
}

View File

@ -192,6 +192,7 @@ void DrawingPanel::loadNodes(QJsonObject obj)
PowerConnection* pCon = TopologyManager::instance().connection(srcPortId.toString(),destPortId.toString());
if(pCon)
{
pCon->setId(id.toString());
QString srcItemId = pCon->fromComponent();
QString destItemId = pCon->toComponent();
//todo:从拓扑结构中查找port的id

View File

@ -51,6 +51,7 @@
#include "instance/dataAccessor.h"
#include "graphicsItem/handleText.h"
#include "bayMeasureDlg.h"
#include "basePannelPropertyProxy.h"
#include "global.h"
bool FixedPortsModel::_dataInitialised = false;
@ -84,7 +85,7 @@ FixedPortsModel::FixedPortsModel(PowerEntity* pEntity)
FixedPortsModel::~FixedPortsModel()
{
_cavas.clear();
}
QMap<QUuid,itemPageInfo> FixedPortsModel::allNodePos() const
@ -143,8 +144,18 @@ bool FixedPortsModel::addNodeItem(QUuid uuid,GraphicsProjectModelItem* pItem)
return false;
else
{
pItem->setHandle(this);
_nodeItem.insert(uuid,pItem);
connect(pItem,&GraphicsProjectModelItem::ifExist,this,&FixedPortsModel::onSignal_ifExits);
connect(pItem,&GraphicsBaseItem::itemRotated,this,[this](GraphicsBaseItem* pBase){
if(pBase){
auto pPro = pBase->getProperty();
QUuid uid = pPro->uuid();
if(pPro->type() != 8){ //排除线
updateItemLinePort(uid,ModelFunctionType::ProjectModel);
}
}
});
return true;
}
}
@ -645,10 +656,18 @@ QString FixedPortsModel::addNodeItem(QUuid id,QPointF pos,double width,double he
item->addPoint(pos);
item->setProperty(pro); //绑定模型
item->updateByProperty(); //使用模型更新自身
//QString sModel = _projectModelName.value(id.toString());
//item->setModelName(sModel);
item->setHandle(this);
_nodeItem.insert(id,item);
connect(item,&GraphicsProjectModelItem::ifExist,this,&FixedPortsModel::onSignal_ifExits);
connect(item,&GraphicsBaseItem::itemRotated,this,[this](GraphicsBaseItem* pBase){
if(pBase){
auto pPro = pBase->getProperty();
QUuid uid = pPro->uuid();
if(pPro->type() != 8){ //排除线
updateItemLinePort(uid,ModelFunctionType::ProjectModel);
}
}
});
}
return pro->name();
}
@ -1610,6 +1629,19 @@ void FixedPortsModel::onDataTimerOut()
}
}
void FixedPortsModel::onSelectionChanged()
{
QList<QGraphicsItem*> selectedItems = _scene->selectedItems();
if(_cavas){
if(selectedItems.count() != 1) {
_cavas->onTargetSelected(_widget->getPropertyProxy());
return;
}
GraphicsBaseItem *item = static_cast<GraphicsBaseItem*>(selectedItems.first());
_cavas->onTargetSelected(item);
}
}
void FixedPortsModel::startHttpRequest()
{
if(_timer)
@ -1794,6 +1826,31 @@ ElectricConnectLineItem* FixedPortsModel::getLineItemById(const QString& termina
return nullptr;
}
void FixedPortsModel::updateItemLinePort(QUuid uid,ModelFunctionType type)
{
QList<PowerConnection*> lstCon = TopologyManager::instance().getConnectionsFor(uid.toString(),type); //获取item的所有连接
for(auto &pCon:lstCon){
QString baseFromComponentId = pCon->fromComponent();
QString baseToComponentId = pCon->toComponent();
QString baseFromTerId = pCon->fromTerminalId();
QString baseToTerId = pCon->toTerminalId();
auto pLine = static_cast<ElectricConnectLineItem*>(nodeItem(QUuid(pCon->id())));
if(pLine){
if(uid.toString() == baseFromComponentId){
QPointF posFrom = getTerminalPos(baseFromTerId);
pLine->setStartPoint(posFrom);
pLine->calculatePath();
}
else if(uid.toString() == baseToComponentId){
QPointF posTo = getTerminalPos(baseToTerId);
pLine->setEndPoint(posTo);
pLine->calculatePath();
}
}
}
}
void FixedPortsModel::showModelDlg(const QString& sName,QUuid uuid,GraphicsProjectModelItem* pItem)
{
modelStateInfo stateInfo = _modelStateInfo[sName];

View File

@ -352,47 +352,341 @@ void ElectricConnectLineItem::moveLine(QPointF pos)
void ElectricConnectLineItem::calculatePath()
{
int n = m_lstPoints.size();
/*for(int i = 0;i < n-1;++i)
{
if(m_lstPoints[i] == m_lstPoints[i+1])
{
if(i == 0) //头重复去除一个
{
m_lstPoints.removeAt(i+1);
}
else if((i+1 == n-1)) //尾重复去除一个
{
m_lstPoints.removeAt(i+1);
}
else
{
m_lstPoints.removeAt(i+1);
m_lstPoints.removeAt(i);
}
qDebug()<<"reset";
resetCurLine();
break;
}
}*/
prepareGeometryChange();
m_points.clear();
m_pointsBoundingRect.clear();
if (m_lstPoints.size() < 2) return;
if(m_lstPoints.size() == 2 && (m_lstPoints.first().x() != m_lstPoints.last().x()) && (m_lstPoints.first().y() != m_lstPoints.last().y()))
{
if(m_lstPoints.first().y() < m_lstPoints.last().y())
m_lstPoints.insert(1,QPointF(m_lstPoints.first().x(),m_lstPoints.last().y()));
else
m_lstPoints.insert(1,QPointF(m_lstPoints.last().x(),m_lstPoints.first().y()));
QPointF start = m_lstPoints.first();
QPointF end = m_lstPoints.last();
qDebug() << "\n=== calculatePath ===";
qDebug() << "Start:" << start << "End:" << end;
// 创建新路径
m_points = QPainterPath();
m_points.moveTo(start);
qDebug() << "Initialized path, current position:" << m_points.currentPosition();
// 获取元件
QList<QRectF> components = getComponentCollisionRects();
qDebug() << "Found" << components.size() << "components";
// 检查起点终点距离
qDebug() << "Distance:" << QLineF(start, end).length();
// 如果距离很近,直接连接
if (QLineF(start, end).length() < 10) {
qDebug() << "Points are very close, direct connection";
m_points.lineTo(end);
} else {
// 生成路径
generateAvoidancePath(start, end, components);
}
m_points.moveTo(m_lstPoints.first());
QPointF pLast = m_lstPoints.first();
for(int i = 1;i <m_lstPoints.size();++i)
{
m_points.lineTo(m_lstPoints[i]);
m_pointsBoundingRect.addRect(QRectF(QPointF(pLast.x()-1,pLast.y()-1),QPointF(m_lstPoints[i].x()+1,m_lstPoints[i].y()+1)));
pLast = m_lstPoints[i];
// 验证路径
qDebug() << "After generation - Path element count:" << m_points.elementCount();
qDebug() << "After generation - Current position:" << m_points.currentPosition();
if (m_points.elementCount() <= 1) {
qWarning() << "Path has only" << m_points.elementCount() << "elements! Adding direct line";
m_points.lineTo(end);
}
// 确保路径结束于终点
if (m_points.currentPosition() != end) {
qWarning() << "Path does not end at destination! Adding final segment";
qDebug() << "Expected end:" << end << "Actual end:" << m_points.currentPosition();
m_points.lineTo(end);
}
update();
m_boundingRect = m_points.boundingRect();
prepareGeometryChange();
qDebug() << "Final path bounds:" << m_boundingRect;
qDebug() << "=== calculatePath end ===\n";
}
// 使用形状进行避障
void ElectricConnectLineItem::generateAvoidancePath(const QPointF& start, const QPointF& end,
const QList<QRectF>& components)
{
qDebug() << "=== generateAvoidancePath (rectilinear) ===";
m_points = QPainterPath();
m_points.moveTo(start);
// 生成候选路径列表,按长度排序
QMultiMap<double, QList<QPointF>> candidatePaths;
// 1. 收集所有可能的直角路径
collectRectilinearPaths(start, end, components, candidatePaths);
// 2. 选择最短的安全路径
for (auto it = candidatePaths.begin(); it != candidatePaths.end(); ++it) {
const QList<QPointF>& path = it.value();
if (isPathSafe(path, components)) {
qDebug() << " Selected path with length" << it.key() << ":" << path;
// 绘制路径
for (int i = 1; i < path.size(); i++) {
m_points.lineTo(path[i]);
}
return;
}
}
// 3. 所有路径都失败,使用强制绕行
qDebug() << " All rectilinear paths failed, using forced bypass";
generateForcedRectilinearBypass(start, end, components);
}
// 计算路径长度
double ElectricConnectLineItem::calculatePathLength(const QList<QPointF>& path)
{
double length = 0;
for (int i = 0; i < path.size() - 1; i++) {
length += QLineF(path[i], path[i+1]).length();
}
return length;
}
// 单一线段与矩形相交检测
bool ElectricConnectLineItem::lineIntersectsRect(const QLineF& line, const QRectF& rect)
{
// 检查端点是否在矩形内
if (rect.contains(line.p1()) || rect.contains(line.p2())) {
return true;
}
// 检查是否与矩形的边相交
QLineF edges[4] = {
QLineF(rect.topLeft(), rect.topRight()),
QLineF(rect.topRight(), rect.bottomRight()),
QLineF(rect.bottomRight(), rect.bottomLeft()),
QLineF(rect.bottomLeft(), rect.topLeft())
};
QPointF intersection;
for (int i = 0; i < 4; i++) {
if (line.intersects(edges[i], &intersection) == QLineF::BoundedIntersection) {
return true;
}
}
return false;
}
// 辅助方法实现
bool ElectricConnectLineItem::isSegmentSafe(const QPointF& p1, const QPointF& p2,
const QList<QRectF>& components)
{
QLineF segment(p1, p2);
for (const QRectF& component : components) {
if (segmentPenetratesComponent(segment, component)) {
return false;
}
}
return true;
}
bool ElectricConnectLineItem::isPathSafe(const QList<QPointF>& path,
const QList<QRectF>& components)
{
for (int i = 0; i < path.size() - 1; i++) {
if (!isSegmentSafe(path[i], path[i+1], components)) {
return false;
}
}
return true;
}
// 检查线段是否穿透元件
bool ElectricConnectLineItem::segmentPenetratesComponent(const QLineF& segment,
const QRectF& component)
{
// 检查线段端点是否在元件内
bool p1Inside = component.contains(segment.p1());
bool p2Inside = component.contains(segment.p2());
if (p1Inside && p2Inside) {
// 线段完全在元件内
return true;
}
// 获取与元件的交点
int intersectionCount = 0;
QLineF edges[4] = {
QLineF(component.topLeft(), component.topRight()),
QLineF(component.topRight(), component.bottomRight()),
QLineF(component.bottomRight(), component.bottomLeft()),
QLineF(component.bottomLeft(), component.topLeft())
};
QPointF intersection;
for (int i = 0; i < 4; i++) {
if (segment.intersects(edges[i], &intersection) == QLineF::BoundedIntersection) {
intersectionCount++;
}
}
// 如果线段与元件有2个或更多交点说明穿透了元件
return intersectionCount >= 2;
}
// 获取所有元件的总边界
QRectF ElectricConnectLineItem::getTotalComponentsBounds(const QList<QRectF>& components)
{
if (components.isEmpty()) {
return QRectF();
}
QRectF total = components.first();
for (int i = 1; i < components.size(); i++) {
total = total.united(components[i]);
}
return total;
}
// 收集所有可能的直角路径
void ElectricConnectLineItem::collectRectilinearPaths(const QPointF& start, const QPointF& end,
const QList<QRectF>& components,
QMultiMap<double, QList<QPointF>>& paths)
{
// 2段路径
QPointF turn1(start.x(), end.y()); // 水平-垂直
QPointF turn2(end.x(), start.y()); // 垂直-水平
addPathIfRectilinear({start, turn1, end}, paths);
addPathIfRectilinear({start, turn2, end}, paths);
// 3段路径
double midX = (start.x() + end.x()) / 2;
double midY = (start.y() + end.y()) / 2;
// 水平-垂直-水平
addPathIfRectilinear({start,
QPointF(start.x(), midY),
QPointF(end.x(), midY),
end}, paths);
// 垂直-水平-垂直
addPathIfRectilinear({start,
QPointF(midX, start.y()),
QPointF(midX, end.y()),
end}, paths);
// 4段路径绕行
collectBypassPaths(start, end, components, paths);
}
// 添加路径(如果是直角)
void ElectricConnectLineItem::addPathIfRectilinear(const QList<QPointF>& path,
QMultiMap<double, QList<QPointF>>& paths)
{
// 检查是否所有线段都是水平或垂直
for (int i = 0; i < path.size() - 1; i++) {
if (path[i].x() != path[i+1].x() && path[i].y() != path[i+1].y()) {
return; // 不是直角
}
}
double length = calculatePathLength(path);
paths.insert(length, path);
}
// 收集绕行路径
void ElectricConnectLineItem::collectBypassPaths(const QPointF& start, const QPointF& end,
const QList<QRectF>& components,
QMultiMap<double, QList<QPointF>>& paths)
{
if (components.isEmpty()) return;
// 获取所有元件的总边界
QRectF totalBounds = getTotalComponentsBounds(components);
if (!totalBounds.isValid()) return;
const double clearance = 20.0;
QRectF expanded = totalBounds.adjusted(-clearance, -clearance, clearance, clearance);
// 从上方绕行
addPathIfRectilinear({start,
QPointF(start.x(), expanded.top()),
QPointF(end.x(), expanded.top()),
end}, paths);
// 从下方绕行
addPathIfRectilinear({start,
QPointF(start.x(), expanded.bottom()),
QPointF(end.x(), expanded.bottom()),
end}, paths);
// 从左方绕行
addPathIfRectilinear({start,
QPointF(expanded.left(), start.y()),
QPointF(expanded.left(), end.y()),
end}, paths);
// 从右方绕行
addPathIfRectilinear({start,
QPointF(expanded.right(), start.y()),
QPointF(expanded.right(), end.y()),
end}, paths);
}
// 强制直角绕行
void ElectricConnectLineItem::generateForcedRectilinearBypass(const QPointF& start, const QPointF& end,
const QList<QRectF>& components)
{
qDebug() << " In generateForcedRectilinearBypass";
// 找到阻挡的元件
QRectF blocking = findFirstBlockingComponent(start, end, components);
if (blocking.isValid()) {
qDebug() << " Blocking component:" << blocking;
// 从上方或下方绕过
const double clearance = 15.0;
double bypassY = (start.y() < blocking.center().y()) ?
blocking.top() - clearance : blocking.bottom() + clearance;
QList<QPointF> path = {start,
QPointF(start.x(), bypassY),
QPointF(end.x(), bypassY),
end};
qDebug() << " Forced bypass path:" << path;
for (int i = 1; i < path.size(); i++) {
m_points.lineTo(path[i]);
}
} else {
// 没有阻挡,使用简单的直角路径
qDebug() << " No blocking component, using simple orthogonal path";
QPointF turnPoint = (qAbs(start.x() - end.x()) < qAbs(start.y() - end.y())) ?
QPointF(end.x(), start.y()) : QPointF(start.x(), end.y());
m_points.lineTo(turnPoint);
m_points.lineTo(end);
}
}
// 找到第一个阻挡的元件
QRectF ElectricConnectLineItem::findFirstBlockingComponent(const QPointF& start, const QPointF& end,
const QList<QRectF>& components)
{
QLineF line(start, end);
for (const QRectF& rect : components) {
if (lineIntersectsRect(line, rect)) {
return rect;
}
}
return QRectF();
}

View File

@ -3,6 +3,7 @@
#include "graphicsItem/handleText.h"
#include "graphicsItem/itemPort.h"
#include "baseProperty.h"
#include "graphicsDataModel/fixedPortsModel.h"
#include "dataBase.h"
#include <QGraphicsScene>
#include <QJsonArray>
@ -13,6 +14,7 @@ GraphicsBaseItem::GraphicsBaseItem(QGraphicsItem *parent)
: AbstractShapeType<QGraphicsItem>(parent)
,_property(nullptr)
,_pEntity(nullptr)
,_pHandle(nullptr)
{
m_type = T_item;
_itemChanged = false;
@ -69,6 +71,69 @@ GraphicsBaseItem::~GraphicsBaseItem()
}
}
QString GraphicsBaseItem::getName() const
{
if(_property)
return _property->name();
return QString();
}
void GraphicsBaseItem::setName(QString str)
{
if(_property)
_property->setName(str);
}
QPointF GraphicsBaseItem::getPosition() const
{
return pos();
}
void GraphicsBaseItem::setPosition(QPointF pos)
{
setPos(pos);
}
QRectF GraphicsBaseItem::getSize() const
{
return m_boundingRect;
}
void GraphicsBaseItem::setSize(QRectF rec)
{
prepareGeometryChange();
m_boundingRect = rec;
update();
}
GraphicsBaseItem::RotateAngle GraphicsBaseItem::getRotateAngle() const
{
int nRotate = rotation();
// 标准化角度到 0-360 范围
nRotate = nRotate % 360;
if (nRotate < 0) nRotate += 360;
// 映射到最近的 90 度倍数
int normalized = ((nRotate + 45) / 90) * 90 % 360;
QMetaEnum metaEnum = QMetaEnum::fromType<RotateAngle>();
// 检查标准化后的角度是否是有效的枚举值
if (metaEnum.valueToKey(normalized) != nullptr) {
return static_cast<RotateAngle>(normalized);
}
return RotateAngle::Angle_0;
}
void GraphicsBaseItem::setRotateAngle(RotateAngle angle)
{
int nAngle = static_cast<int>(angle);
setRotation(nAngle);
emit itemRotated(this);
}
int GraphicsBaseItem::addPort(PortState typ,QPointF vec,QString id,HandleType hType,PortPos pos,double dXPercent,double dYPercent)
{
int ntagId = -1;
@ -321,6 +386,56 @@ void GraphicsBaseItem::rearrangeDynamicText()
++i;
}
}
QList<QRectF> GraphicsBaseItem::getComponentCollisionRects() const
{
QList<QRectF> lst;
if(_pHandle){
auto mapItems = _pHandle->allItems();
for(auto &pItem:mapItems){
if (pItem == this) continue;
ModelProperty* pPro = pItem->getProperty();
if(pPro){
if(pPro->type() == 8) continue; //排除线
}
QRectF bounds = pItem->boundingRect();
bounds = pItem->mapRectToScene(bounds);
lst.append(bounds);
}
}
return lst;
}
QList<QPainterPath> GraphicsBaseItem::getObstacleShapes() const
{
QList<QPainterPath> obstacles;
if (!scene()) {
return obstacles;
}
if(_pHandle){
auto mapItems = _pHandle->allItems();
for(auto &pItem:mapItems){
if (pItem == this) continue;
ModelProperty* pPro = pItem->getProperty();
if(pPro){
if(pPro->type() == 8) continue; //排除线
}
// 获取元件的形状(考虑旋转)
QPainterPath shape = pItem->mapToScene(pItem->shape());
// 如果需要,可以稍微扩大形状
QPainterPathStroker stroker;
stroker.setWidth(10); // 扩大10像素作为安全距离
QPainterPath expandedShape = stroker.createStroke(shape);
obstacles.append(expandedShape);
}
}
return obstacles;
}
/********************************基模****************************************/
GraphicsBaseModelItem::GraphicsBaseModelItem(QGraphicsItem *parent)
:GraphicsBaseItem(parent)
@ -580,41 +695,6 @@ void GraphicsProjectModelItem::syncRotationDataFromParent(const double& data)
m_dSyncRotationByParent += 360;
}
QString GraphicsProjectModelItem::getName() const
{
if(_property)
return _property->name();
return QString();
}
void GraphicsProjectModelItem::setName(QString str)
{
if(_property)
_property->setName(str);
}
QPointF GraphicsProjectModelItem::getPosition() const
{
return pos();
}
void GraphicsProjectModelItem::setPosition(QPointF pos)
{
setPos(pos);
}
QRectF GraphicsProjectModelItem::getSize() const
{
return m_boundingRect;
}
void GraphicsProjectModelItem::setSize(QRectF rec)
{
prepareGeometryChange();
m_boundingRect = rec;
update();
}
DataSourceType GraphicsProjectModelItem::getDataSourceType() const
{
return _sourceType;

View File

@ -229,6 +229,7 @@ void MonitorPanel::loadNodes(QJsonObject obj)
PowerConnection* pCon = TopologyManager::instance().connection(srcPortId.toString(),destPortId.toString());
if(pCon)
{
pCon->setId(id.toString());
QString srcItemId = pCon->fromComponent();
QString destItemId = pCon->toComponent();
//todo:从拓扑结构中查找port的id

View File

@ -40,8 +40,8 @@ void LinkMovingSelector::mouseMoveEvent(QGraphicsSceneMouseEvent* event, Designe
}
else
{
if(m_pMovingLine)
m_pMovingLine->moveLine(ms_ptMouseLast);
//if(m_pMovingLine)
//m_pMovingLine->moveLine(ms_ptMouseLast); //暂时屏蔽移动线 260204
}
}

View File

@ -57,6 +57,7 @@ private slots:
void onAction_createEditor();
void onAction_unloadEditor(const QString&);
void onCavasItemSelected(QObject*);
public:
GraphicElementsPanel* graphicsElementsPanel() const;

View File

@ -143,9 +143,7 @@ void CMainWindow::initializeDockUi()
m_pPropertiesEditorView->setObject(m_pDiagramCavas);
PropertyEditorDock->setAllowedAreas(Qt::LeftDockWidgetArea|Qt::RightDockWidgetArea);
this->addDockWidget(Qt::RightDockWidgetArea,PropertyEditorDock);
connect(m_pDiagramCavas,&DiagramCavas::selectTarget,this,[&](QObject* obj){
m_pPropertiesEditorView->setObject(obj);
});
connect(m_pDiagramCavas,&DiagramCavas::selectTarget,this,&CMainWindow::onCavasItemSelected);
}
void CMainWindow::initializeAction()
@ -356,6 +354,12 @@ void CMainWindow::onAction_unloadEditor(const QString& str)
m_pDiagramCavas->onSignal_unloadProject(str);
}
void CMainWindow::onCavasItemSelected(QObject* obj)
{
if(m_pPropertiesEditorView)
m_pPropertiesEditorView->setObject(obj);
}
GraphicElementsPanel* CMainWindow::graphicsElementsPanel() const
{
if(m_pGraphicElementsPanel)