diff --git a/CMakeLists.txt b/CMakeLists.txt index 5782569..ee73233 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,6 +44,7 @@ set(H_HEADER_FILES include/util/baseSelector.h include/util/creatingSelector.h include/util/movingSelector.h + include/util/rotationSelector.h include/util/scalingSelector.h include/util/editingSelector.h include/util/selectorManager.h @@ -65,6 +66,7 @@ set(CPP_SOURCE_FILES source/util/baseSelector.cpp source/util/creatingSelector.cpp source/util/movingSelector.cpp + source/util/rotationSelector.cpp source/util/scalingSelector.cpp source/util/editingSelector.cpp source/util/selectorManager.cpp diff --git a/include/graphicsItem/graphicsBaseItem.h b/include/graphicsItem/graphicsBaseItem.h index 9852d00..b6d10e6 100644 --- a/include/graphicsItem/graphicsBaseItem.h +++ b/include/graphicsItem/graphicsBaseItem.h @@ -19,7 +19,7 @@ public: m_pen = QPen(Qt::NoPen); m_brush = QBrush(QColor(rand() % 32 * 8, rand() % 32 * 8, rand() % 32 * 8)); m_dWidth = m_dHeight = 0; - m_pMovingCopy = nullptr; + m_pOperationCopy = nullptr; } virtual ~AbstractShapeType() @@ -71,10 +71,11 @@ public: return HandleTag::H_none; } - //移动副本相关 - virtual void createMovingCopy() {} - virtual void removeMovingCopy() {} - virtual void moveMovingCopy(const QPointF&) {} + //操作副本相关 + virtual void createOperationCopy() {} + virtual void removeOperationCopy() {} + virtual void moveOperationCopy(const QPointF&) {} + virtual void rotateOperationCopy(const double&) {} virtual void resize(int,double, double, const QPointF&) {} virtual void move(const QPointF&) {} @@ -84,6 +85,19 @@ public: //handle相关 virtual int handleCount() { return m_vecHanle.count(); } + virtual ItemControlHandle* getHandle(int nHandle) + { + ItemControlHandle* handle = nullptr; + for(auto it = m_vecHanle.begin(); it != m_vecHanle.end(); it++) + { + if((*it)->getTag() == nHandle) + { + handle = (*it); + return handle; + } + } + return handle; + } virtual void setHandleVisible(bool bVisible) { for(auto it = m_vecHanle.begin(); it != m_vecHanle.end(); it++) @@ -161,13 +175,68 @@ public: case H_left: (*it)->move(boundRect.x() - nMargin, boundRect.y() + boundRect.height() * 0.5); break; + case H_rotate_leftTop: + { + ItemControlHandle* handle = getHandle(H_leftTop); + if(handle) + { + int nSize = handle->getSize(); + QPointF pt = handle->pos(); + (*it)->move(pt.x() - nSize - 1, pt.y() - nSize - 1); + } + else + (*it)->setVisible(false); + + break; + } + case H_rotate_rightTop: + { + ItemControlHandle* handle = getHandle(H_rightTop); + if(handle) + { + int nSize = handle->getSize(); + QPointF pt = handle->pos(); + (*it)->move(pt.x() + nSize + 1, pt.y() - nSize - 1); + } + else + (*it)->setVisible(false); + + break; + } + case H_rotate_rightBottom: + { + ItemControlHandle* handle = getHandle(H_rightBottom); + if(handle) + { + int nSize = handle->getSize(); + QPointF pt = handle->pos(); + (*it)->move(pt.x() + nSize + 1, pt.y() + nSize + 1); + } + else + (*it)->setVisible(false); + + break; + } + case H_rotate_leftBottom: + { + ItemControlHandle* handle = getHandle(H_leftBottom); + if(handle) + { + int nSize = handle->getSize(); + QPointF pt = handle->pos(); + (*it)->move(pt.x() - nSize - 1, pt.y() + nSize + 1); + } + else + (*it)->setVisible(false); + + break; + } default: break; } } } -protected: virtual QRectF boundingRect() const { return m_boundingRect; } virtual QPainterPath shape() { @@ -182,7 +251,7 @@ protected: double m_dHeight; QRectF m_boundingRect; - QGraphicsPathItem* m_pMovingCopy; //图元移动时的副本 + QGraphicsPathItem* m_pOperationCopy; //图元移动和旋转时的操作副本 QPointF m_movingIniPos; //移动副本开始移动初始点 QVector m_vecHanle; @@ -196,9 +265,10 @@ public: GraphicsBaseItem(QGraphicsItem *parent); virtual ~GraphicsBaseItem(); - virtual void createMovingCopy(); - virtual void removeMovingCopy(); - virtual void moveMovingCopy(const QPointF&); + virtual void createOperationCopy(); + virtual void removeOperationCopy(); + virtual void moveOperationCopy(const QPointF&); + virtual void rotateOperationCopy(const double&); //多边形、线段等点选创建的对象需要的函数 virtual void addPoint(const QPointF&) {} virtual bool endDrawing() { return true; } diff --git a/include/graphicsItem/itemControlHandle.h b/include/graphicsItem/itemControlHandle.h index fa68fd5..d5e77f8 100644 --- a/include/graphicsItem/itemControlHandle.h +++ b/include/graphicsItem/itemControlHandle.h @@ -6,6 +6,7 @@ enum HandleType { T_resize, //调整大小 + T_rotate, //旋转 T_editShape //编辑形状 }; @@ -20,6 +21,10 @@ enum HandleTag H_bottom, H_leftBottom, H_left, //8 + H_rotate_leftTop, + H_rotate_rightTop, + H_rotate_rightBottom, + H_rotate_leftBottom, //12 H_edit }; @@ -39,6 +44,7 @@ public: void setTag(int ht) { m_tag = ht; } int getTag() { return m_tag; } + int getSize(); void move(double, double); protected: diff --git a/include/util/baseSelector.h b/include/util/baseSelector.h index 9caea68..2aa2094 100644 --- a/include/util/baseSelector.h +++ b/include/util/baseSelector.h @@ -19,7 +19,7 @@ enum SelectorType ST_moving, //移动 ST_editing, //顶点编辑 ST_scaling, //缩放 - ST_rotating, //旋转 + ST_rotation, //旋转 }; enum OperationMode @@ -56,10 +56,11 @@ signals: void setWorkingSelector(SelectorType); protected: - //静态变量,用于不同类型对象间的成员共享 + //静态变量,用于不同类型selector间的成员共享 static OperationMode ms_opMode; static QPointF ms_ptMouseDown; static QPointF ms_ptMouseLast; + static double ms_dAngleMouseDownToItem; //鼠标按下时其位置和item中心点形成的夹角 static int ms_nDragHandle; //当前抓取的控制点 SelectorType m_type; diff --git a/include/util/rotationSelector.h b/include/util/rotationSelector.h new file mode 100644 index 0000000..22c4610 --- /dev/null +++ b/include/util/rotationSelector.h @@ -0,0 +1,28 @@ +/** + *\file rotationSelector.h + * + *\brief 用来实现图元旋转的selector + * + *\author dsc + */ + +#ifndef ROTATIONSELECTOR_H +#define ROTATIONSELECTOR_H + +#include "baseSelector.h" + +class RotationSelector : public BaseSelector +{ + Q_OBJECT + +public: + explicit RotationSelector(QObject *parent = 0); + virtual ~RotationSelector(); + +public: + void mousePressEvent(QGraphicsSceneMouseEvent*, DesignerScene*); + void mouseMoveEvent(QGraphicsSceneMouseEvent*, DesignerScene*); + void mouseReleaseEvent(QGraphicsSceneMouseEvent*, DesignerScene*); +}; + +#endif diff --git a/resource/PowerDesigner.qrc b/resource/PowerDesigner.qrc index e5d47e6..8785285 100644 --- a/resource/PowerDesigner.qrc +++ b/resource/PowerDesigner.qrc @@ -1,5 +1,8 @@ images/checkerboard.png + images/icon_rotate.png + images/icon_rotate2.png + images/icon-rotate3.png diff --git a/resource/images/icon-rotate3.png b/resource/images/icon-rotate3.png new file mode 100644 index 0000000..39c110a Binary files /dev/null and b/resource/images/icon-rotate3.png differ diff --git a/resource/images/icon_rotate.png b/resource/images/icon_rotate.png new file mode 100644 index 0000000..3c91ea9 Binary files /dev/null and b/resource/images/icon_rotate.png differ diff --git a/resource/images/icon_rotate2.png b/resource/images/icon_rotate2.png new file mode 100644 index 0000000..9dfadbd Binary files /dev/null and b/resource/images/icon_rotate2.png differ diff --git a/source/graphicsItem/graphicsBaseItem.cpp b/source/graphicsItem/graphicsBaseItem.cpp index be6fbba..ecba3e5 100644 --- a/source/graphicsItem/graphicsBaseItem.cpp +++ b/source/graphicsItem/graphicsBaseItem.cpp @@ -13,6 +13,13 @@ GraphicsBaseItem::GraphicsBaseItem(QGraphicsItem *parent) pHandle->setTag(i); m_vecHanle.push_back(pHandle); } + for(int i = H_rotate_leftTop; i <= H_rotate_leftBottom; i++) + { + ItemControlHandle* pHandle = new ItemControlHandle(this); + pHandle->setType(T_rotate); + pHandle->setTag(i); + m_vecHanle.push_back(pHandle); + } setFlag(QGraphicsItem::ItemIsMovable, true); setFlag(QGraphicsItem::ItemIsSelectable, true); @@ -26,43 +33,52 @@ GraphicsBaseItem::~GraphicsBaseItem() } -void GraphicsBaseItem::createMovingCopy() +void GraphicsBaseItem::createOperationCopy() { - m_pMovingCopy = new QGraphicsPathItem(this->shape()); - m_pMovingCopy->setPen(Qt::DashLine); - m_pMovingCopy->setPos(this->pos()); - m_pMovingCopy->setTransformOriginPoint(this->transformOriginPoint()); - m_pMovingCopy->setTransform(this->transform()); - m_pMovingCopy->setRotation(this->rotation()); - m_pMovingCopy->setScale(this->scale()); - m_pMovingCopy->setZValue(this->zValue()); + m_pOperationCopy = new QGraphicsPathItem(this->shape()); + m_pOperationCopy->setPen(Qt::DashLine); + m_pOperationCopy->setPos(this->pos()); + m_pOperationCopy->setTransformOriginPoint(this->transformOriginPoint()); + m_pOperationCopy->setTransform(this->transform()); + m_pOperationCopy->setRotation(this->rotation()); + m_pOperationCopy->setScale(this->scale()); + m_pOperationCopy->setZValue(this->zValue()); QGraphicsScene* scene = this->scene(); - if(scene && m_pMovingCopy) + if(scene && m_pOperationCopy) { - scene->addItem(m_pMovingCopy); + scene->addItem(m_pOperationCopy); m_movingIniPos = this->pos(); } } -void GraphicsBaseItem::removeMovingCopy() +void GraphicsBaseItem::removeOperationCopy() { QGraphicsScene* scene = this->scene(); - if(scene && m_pMovingCopy) + if(scene && m_pOperationCopy) { - this->setPos(m_pMovingCopy->pos()); //本体先移动到副本的位置 - scene->removeItem(m_pMovingCopy); - delete m_pMovingCopy; - m_pMovingCopy = nullptr; + if(this->pos() != m_pOperationCopy->pos()) + this->setPos(m_pOperationCopy->pos()); //本体移动到副本的位置 + if(this->rotation() != m_pOperationCopy->rotation()) + this->setRotation(m_pOperationCopy->rotation()); //本体旋转至副本的角度 + + scene->removeItem(m_pOperationCopy); + delete m_pOperationCopy; + m_pOperationCopy = nullptr; } } -void GraphicsBaseItem::moveMovingCopy(const QPointF& distance) +void GraphicsBaseItem::moveOperationCopy(const QPointF& distance) { - if(m_pMovingCopy) - m_pMovingCopy->setPos(m_movingIniPos + distance); + if(m_pOperationCopy) + m_pOperationCopy->setPos(m_movingIniPos + distance); } +void GraphicsBaseItem::rotateOperationCopy(const double& dAngle) +{ + if(m_pOperationCopy) + m_pOperationCopy->setRotation(dAngle); +} QVariant GraphicsBaseItem::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant& value) { diff --git a/source/graphicsItem/graphicsPolygonItem.cpp b/source/graphicsItem/graphicsPolygonItem.cpp index 25dcea4..ef41539 100644 --- a/source/graphicsItem/graphicsPolygonItem.cpp +++ b/source/graphicsItem/graphicsPolygonItem.cpp @@ -105,7 +105,7 @@ void GraphicPolygonItem::move(const QPointF& point) void GraphicPolygonItem::editShape(int nHandle,const QPointF& ptMouse) { QPointF pt = mapFromScene(ptMouse); - m_points[nHandle - H_left - 1] = pt; + m_points[nHandle - H_rotate_leftBottom - 1] = pt; prepareGeometryChange(); m_boundingRect = m_points.boundingRect(); m_dWidth = m_boundingRect.width(); diff --git a/source/graphicsItem/itemControlHandle.cpp b/source/graphicsItem/itemControlHandle.cpp index 3f1081e..5313d2b 100644 --- a/source/graphicsItem/itemControlHandle.cpp +++ b/source/graphicsItem/itemControlHandle.cpp @@ -30,6 +30,12 @@ void ItemControlHandle::paint(QPainter* painter, const QStyleOptionGraphicsItem* painter->setBrush(Qt::white); painter->drawRect(rect()); } + else if(m_type==T_rotate) + { + painter->setPen(Qt::NoPen); + painter->setBrush(Qt::NoBrush); + painter->drawRect(rect()); + } else if(m_type==T_editShape) { painter->setBrush(Qt::green); @@ -47,6 +53,12 @@ void ItemControlHandle::hoverLeaveEvent(QGraphicsSceneHoverEvent* event) QGraphicsRectItem::hoverLeaveEvent(event); } +int ItemControlHandle::getSize() +{ + int nSize = HNDLE_SIZE; + return nSize; +} + void ItemControlHandle::move(double x, double y) { setPos(x, y); diff --git a/source/util/baseSelector.cpp b/source/util/baseSelector.cpp index a051ee2..078034a 100644 --- a/source/util/baseSelector.cpp +++ b/source/util/baseSelector.cpp @@ -6,6 +6,7 @@ QPointF BaseSelector::ms_ptMouseDown(0.0,0.0); QPointF BaseSelector::ms_ptMouseLast(0.0,0.0); +double BaseSelector::ms_dAngleMouseDownToItem = 0.0; int BaseSelector::ms_nDragHandle = 0; BaseSelector::BaseSelector(QObject *parent) @@ -46,7 +47,19 @@ void BaseSelector::mousePressEvent(QGraphicsSceneMouseEvent* event, DesignerScen m_opMode = OM_scale; emit setWorkingSelector(ST_scaling); } - else if(ms_nDragHandle > H_left) //编辑控制点上 + else if(ms_nDragHandle >= H_rotate_leftTop && ms_nDragHandle <= H_rotate_leftBottom) //在旋转控制点上 + { + m_opMode = OM_rotate; + //计算夹角 + QPointF originPoint = item->mapToScene(item->boundingRect().center()); + double dLengthY = ms_ptMouseLast.y() - originPoint.y(); + double dLengthX = ms_ptMouseLast.x() - originPoint.x(); + ms_dAngleMouseDownToItem = atan2(dLengthY, dLengthX) * 180 / M_PI; + //创建副本 + item->createOperationCopy(); + emit setWorkingSelector(ST_rotation); + } + else if(ms_nDragHandle > H_rotate_leftBottom) //编辑控制点上 { m_opMode = OM_edit; setCursor(scene, Qt::ClosedHandCursor); @@ -67,12 +80,13 @@ void BaseSelector::mousePressEvent(QGraphicsSceneMouseEvent* event, DesignerScen setCursor(scene, Qt::ClosedHandCursor); } - if(m_opMode == OM_move) + if(m_opMode == OM_move) //可以多个选中同时移动 { for(int n = 0; n < items.size(); n++) { + //创建副本 GraphicsBaseItem* item = qgraphicsitem_cast(items.at(n)); - item->createMovingCopy(); + item->createOperationCopy(); } } else if(m_opMode == OM_none) @@ -132,6 +146,15 @@ void BaseSelector::mouseMoveEvent(QGraphicsSceneMouseEvent* event, DesignerScene case H_left: setCursor(scene, Qt::SizeHorCursor); break; + case H_rotate_leftTop: + case H_rotate_rightTop: + case H_rotate_rightBottom: + case H_rotate_leftBottom: + { + int nSize = 24; + QCursor rotateCursor = QCursor(QPixmap(":/images/icon_rotate2.png").scaled(nSize, nSize, Qt::KeepAspectRatio, Qt::SmoothTransformation)); + setCursor(scene, rotateCursor); + } default: break; } diff --git a/source/util/movingSelector.cpp b/source/util/movingSelector.cpp index a54c388..e5dd413 100644 --- a/source/util/movingSelector.cpp +++ b/source/util/movingSelector.cpp @@ -27,7 +27,7 @@ void MovingSelector::mouseMoveEvent(QGraphicsSceneMouseEvent* event, DesignerSce { GraphicsBaseItem* item = qgraphicsitem_cast(items.at(n)); if(item) - item->moveMovingCopy(ms_ptMouseLast - ms_ptMouseDown); + item->moveOperationCopy(ms_ptMouseLast - ms_ptMouseDown); } } @@ -38,7 +38,7 @@ void MovingSelector::mouseReleaseEvent(QGraphicsSceneMouseEvent* event, Designer { GraphicsBaseItem* item = qgraphicsitem_cast(items.at(n)); if(item) - item->removeMovingCopy(); + item->removeOperationCopy(); } setCursor(scene, Qt::ArrowCursor); diff --git a/source/util/rotationSelector.cpp b/source/util/rotationSelector.cpp new file mode 100644 index 0000000..1eda543 --- /dev/null +++ b/source/util/rotationSelector.cpp @@ -0,0 +1,60 @@ +#include "util/rotationSelector.h" +#include +#include +#include + +RotationSelector::RotationSelector(QObject *parent) + : BaseSelector(parent) +{ + m_type = ST_rotation; +} +RotationSelector::~RotationSelector() +{ + +} + +void RotationSelector::mousePressEvent(QGraphicsSceneMouseEvent* event, DesignerScene* scene) +{ + +} + +void RotationSelector::mouseMoveEvent(QGraphicsSceneMouseEvent* event, DesignerScene* scene) +{ + ms_ptMouseLast = event->scenePos(); + QList items = scene->selectedItems(); + if (items.count() == 1) + { + GraphicsBaseItem* item = qgraphicsitem_cast(items.first()); + if(item) + { + //计算夹角 + QPointF originPoint = item->mapToScene(item->boundingRect().center()); + double dLengthY = ms_ptMouseLast.y() - originPoint.y(); + double dLengthX = ms_ptMouseLast.x() - originPoint.x(); + double dAngleMouseToItem = atan2(dLengthY, dLengthX) * 180 / M_PI; + + double rotationAngle = item->rotation() + (dAngleMouseToItem - ms_dAngleMouseDownToItem); + if (rotationAngle > 360) + rotationAngle -= 360; + if (rotationAngle < -360) + rotationAngle += 360; + + item->rotateOperationCopy(rotationAngle); + } + } +} + +void RotationSelector::mouseReleaseEvent(QGraphicsSceneMouseEvent* event, DesignerScene* scene) +{ + QList items = scene->selectedItems(); + for(int n = 0; n < items.size(); n++) + { + GraphicsBaseItem* item = qgraphicsitem_cast(items.at(n)); + if(item) + item->removeOperationCopy(); + } + + ms_nDragHandle = H_none; + setCursor(scene, Qt::ArrowCursor); + emit setWorkingSelector(ST_base); +} diff --git a/source/util/selectorManager.cpp b/source/util/selectorManager.cpp index fb629ed..182a480 100644 --- a/source/util/selectorManager.cpp +++ b/source/util/selectorManager.cpp @@ -1,6 +1,7 @@ #include "util/selectorManager.h" #include "util/creatingSelector.h" #include "util/movingSelector.h" +#include "util/rotationSelector.h" #include "util/scalingSelector.h" #include "util/editingSelector.h" @@ -21,6 +22,9 @@ SelectorManager::SelectorManager(QObject *parent) MovingSelector* movingSelector = new MovingSelector(this); connect(movingSelector, SIGNAL(setWorkingSelector(SelectorType)), this, SLOT(onSignal_setWorkingSelector(SelectorType))); m_vecSelectors.push_back(movingSelector); + RotationSelector* rotationSelector = new RotationSelector(this); + connect(rotationSelector, SIGNAL(setWorkingSelector(SelectorType)), this, SLOT(onSignal_setWorkingSelector(SelectorType))); + m_vecSelectors.push_back(rotationSelector); ScalingSelector* scalingSelector = new ScalingSelector(this); connect(scalingSelector, SIGNAL(setWorkingSelector(SelectorType)), this, SLOT(onSignal_setWorkingSelector(SelectorType))); m_vecSelectors.push_back(scalingSelector); diff --git a/ui/mainwindow.ui b/ui/mainwindow.ui index c2f107d..2b0c15e 100644 --- a/ui/mainwindow.ui +++ b/ui/mainwindow.ui @@ -6,8 +6,8 @@ 0 0 - 1612 - 1016 + 1696 + 1079 @@ -19,7 +19,7 @@ 0 0 - 1612 + 1696 33