File indexing completed on 2024-04-28 05:38:11
0001 /*************************************************************************** 0002 * Copyright (C) 2015 by Renaud Guezennec * 0003 * https://rolisteam.org/contact * 0004 * * 0005 * rolisteam is free software; you can redistribute it and/or modify * 0006 * it under the terms of the GNU General Public License as published by * 0007 * the Free Software Foundation; either version 2 of the License, or * 0008 * (at your option) any later version. * 0009 * * 0010 * This program is distributed in the hope that it will be useful, * 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0013 * GNU General Public License for more details. * 0014 * * 0015 * You should have received a copy of the GNU General Public License * 0016 * along with this program; if not, write to the * 0017 * Free Software Foundation, Inc., * 0018 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 0019 ***************************************************************************/ 0020 0021 #include "childpointitem.h" 0022 #include "visualitem.h" 0023 0024 #include "controller/item_controllers/visualitemcontroller.h" 0025 #include "controller/view_controller/vectorialmapcontroller.h" 0026 #include <QDebug> 0027 #include <QGraphicsScene> 0028 #include <QGraphicsSceneMouseEvent> 0029 #include <QPainter> 0030 0031 #include <cmath> 0032 #include <math.h> 0033 #define PI 3.14159265 0034 0035 #define SQUARE_SIZE 6 0036 0037 bool allowResizing(ChildPointItem::Change change) 0038 { 0039 return (change == ChildPointItem::None || change == ChildPointItem::Resizing); 0040 } 0041 0042 bool allowRotation(ChildPointItem::Change change) 0043 { 0044 return (change == ChildPointItem::None || change == ChildPointItem::Rotation); 0045 } 0046 0047 ChildPointItem::ChildPointItem(vmap::VisualItemController* ctrl, int point, VisualItem* parent, Control control) 0048 : QGraphicsObject(parent), m_ctrl(ctrl), m_pointId(point), m_parent(parent), m_control(control) 0049 { 0050 m_editable= true; 0051 // connect(m_ctrl, &vmap::VisualItemController::rotationChanged, this, [this]() { setRotation(-m_ctrl->rotation()); 0052 // }); 0053 // setFlag(QGraphicsItem::ItemIgnoresParentOpacity); 0054 // setAcceptHoverEvents(true); 0055 // setFlags(QGraphicsItem::ItemIsSelectable|QGraphicsItem::ItemSendsGeometryChanges|QGraphicsItem::ItemIsMovable|QGraphicsItem::ItemIsFocusable); 0056 // setFlags(QGraphicsItem::ItemIsSelectable|QGraphicsItem::ItemIsFocusable); 0057 } 0058 0059 ChildPointItem::~ChildPointItem() {} 0060 0061 QVariant ChildPointItem::itemChange(GraphicsItemChange change, const QVariant& value) 0062 { 0063 /* if(!m_editable) 0064 return QGraphicsItem::itemChange(change, value); 0065 0066 if(change == ItemPositionChange && isSelected() && m_currentMotion != NONE 0067 && m_currentMotion != MOUSE) 0068 { 0069 QPointF newPos= value.toPointF(); 0070 switch(m_currentMotion) 0071 { 0072 case X_AXIS: 0073 newPos.setY(pos().y()); 0074 break; 0075 case Y_AXIS: 0076 newPos.setX(pos().x()); 0077 0078 break; 0079 case MOVE: 0080 m_parent->setPos(mapToScene(newPos)); 0081 break; 0082 default: 0083 break; 0084 } 0085 if(newPos != value.toPointF()) 0086 { 0087 return newPos; 0088 } 0089 }*/ 0090 0091 return QGraphicsItem::itemChange(change, value); 0092 } 0093 QRectF ChildPointItem::boundingRect() const 0094 { 0095 return QRectF(m_startPoint.x(), m_startPoint.y(), 2 * SQUARE_SIZE, 2 * SQUARE_SIZE); 0096 } 0097 void ChildPointItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) 0098 { 0099 Q_UNUSED(option) 0100 Q_UNUSED(widget) 0101 painter->setPen(Qt::black); 0102 painter->fillRect(m_startPoint.x(), m_startPoint.y(), 2 * SQUARE_SIZE, 2 * SQUARE_SIZE, Qt::gray); 0103 painter->drawRect(m_startPoint.x(), m_startPoint.y(), 2 * SQUARE_SIZE, 2 * SQUARE_SIZE); 0104 } 0105 void ChildPointItem::setMotion(ChildPointItem::MOTIONS m) 0106 { 0107 m_motion= m; 0108 // if((MOUSE == m_currentMotion) || (NONE == m_currentMotion)) 0109 { 0110 setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsFocusable); 0111 } 0112 /* else 0113 { 0114 setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemSendsGeometryChanges 0115 | QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsFocusable); 0116 }*/ 0117 } 0118 void ChildPointItem::setPlacement(ChildPointItem::PLACEMENT p) 0119 { 0120 // MiddelLeft,MiddleRight,Center,ButtomLeft,ButtomRight,ButtomCenter}; 0121 m_placement= p; 0122 switch(m_placement) 0123 { 0124 case TopLeft: 0125 m_startPoint.setX(0); 0126 m_startPoint.setY(0); 0127 break; 0128 case TopRight: 0129 m_startPoint.setX(-(2 * SQUARE_SIZE)); 0130 m_startPoint.setY(0); 0131 break; 0132 case TopCenter: 0133 m_startPoint.setX(-(SQUARE_SIZE)); 0134 m_startPoint.setY(0); 0135 break; 0136 case MiddelLeft: 0137 m_startPoint.setX(0); 0138 m_startPoint.setY(-(SQUARE_SIZE)); 0139 break; 0140 case MiddleRight: 0141 m_startPoint.setX(-(2 * SQUARE_SIZE)); 0142 m_startPoint.setY(-(SQUARE_SIZE)); 0143 break; 0144 case Center: 0145 m_startPoint.setX(-(SQUARE_SIZE)); 0146 m_startPoint.setY(-(SQUARE_SIZE)); 0147 break; 0148 case ButtomLeft: 0149 m_startPoint.setX(0); 0150 m_startPoint.setY(-(2 * SQUARE_SIZE)); 0151 break; 0152 case ButtomRight: 0153 m_startPoint.setX(-(2 * SQUARE_SIZE)); 0154 m_startPoint.setY(-(2 * SQUARE_SIZE)); 0155 break; 0156 case ButtomCenter: 0157 m_startPoint.setX(-(SQUARE_SIZE)); 0158 m_startPoint.setY(-(2 * SQUARE_SIZE)); 0159 break; 0160 } 0161 } 0162 0163 ChildPointItem::PLACEMENT ChildPointItem::placement() const 0164 { 0165 return m_placement; 0166 } 0167 /*void ChildPointItem::mouseMoveEvent(QGraphicsSceneMouseEvent * event) 0168 { 0169 event->accept(); 0170 QPointF v = pos() + event->pos();//distance vector 0171 qreal rot = m_parent->rotation(); 0172 0173 0174 if(m_editable) 0175 { 0176 if(m_currentMotion == MOUSE) 0177 { 0178 if(!(event->modifiers() & Qt::ControlModifier)) 0179 { 0180 VisualItem::TransformType transformType = VisualItem::NoTransform; 0181 0182 qreal W = 0;//qMax(fabs(v.x()), 5.0); 0183 qreal H = 0;//qMax(fabs(v.y()), 4.0); 0184 qreal X = 0; 0185 qreal Y = 0; 0186 m_parent->setRotation(0); 0187 v = event->pos();//distance vector 0188 switch(m_placement) 0189 { 0190 case TopLeft://topleft 0191 // m_parent->setTransformOriginPoint(m_parent->boundingRect().bottomRight()); 0192 X = v.x(); 0193 Y = v.y(); 0194 W = m_parent->boundingRect().width() - X; 0195 H = m_parent->boundingRect().height() - Y; 0196 break; 0197 case TopRight://topright 0198 // m_parent->setTransformOriginPoint(m_parent->boundingRect().bottomLeft()); 0199 Y = v.y(); 0200 W = m_parent->boundingRect().width() + v.x(); 0201 H = m_parent->boundingRect().height() - Y; 0202 break; 0203 case ButtomRight:// bottom right 0204 // m_parent->setTransformOriginPoint(m_parent->boundingRect().topLeft()); 0205 W = m_parent->boundingRect().width() + v.x(); 0206 H = m_parent->boundingRect().height() + v.y(); 0207 break; 0208 case ButtomLeft://bottom left 0209 //m_parent->setTransformOriginPoint(m_parent->boundingRect().topRight()); 0210 X = v.x(); 0211 H = m_parent->boundingRect().height() + v.y(); 0212 W = m_parent->boundingRect().width() - X; 0213 break; 0214 } 0215 if((event->modifiers() & Qt::ShiftModifier)) 0216 { 0217 transformType = VisualItem::KeepRatio; 0218 } 0219 else if(event->modifiers() & Qt::AltModifier) 0220 { 0221 transformType = VisualItem::Sticky; 0222 int size = m_parent->getOption(VisualItem::GridSize).toInt(); 0223 W = std::round(W/size)*size; 0224 H = std::round(H/size)*size; 0225 } 0226 0227 { 0228 if(rot == 0) 0229 { 0230 m_parent->moveBy(X,Y); 0231 } 0232 m_parent->resizeContents(QRectF(0, 0, W, H),transformType); 0233 //m_parent->setTransformOriginPoint(m_parent->boundingRect().center()); 0234 m_parent->setRotation(rot); 0235 } 0236 } 0237 } 0238 if(((m_currentMotion == MOUSE)||(m_allowRotation))&&(event->modifiers() & Qt::ControlModifier)) 0239 { 0240 if (v.isNull()) 0241 return; 0242 0243 QPointF refPos = pos(); 0244 0245 // set item rotation (set rotation relative to current) 0246 qreal refAngle = atan2(refPos.y(), refPos.x()); 0247 qreal newAngle = atan2(v.y(), v.x()); 0248 double dZr = 57.29577951308232 * (newAngle - refAngle); // 180 * a / M_PI 0249 double zr = m_parent->rotation() + dZr; 0250 m_parent->setTransformOriginPoint(m_parent->boundingRect().center()); 0251 m_parent->setRotation(zr); 0252 } 0253 else 0254 { 0255 QGraphicsItem::mouseMoveEvent(event); 0256 } 0257 } 0258 else 0259 { 0260 QGraphicsItem::mouseMoveEvent(event); 0261 } 0262 }*/ 0263 0264 void ChildPointItem::mouseMoveEvent(QGraphicsSceneMouseEvent* event) 0265 { 0266 event->accept(); 0267 QPointF v= pos() + event->pos(); 0268 if(!m_editable) 0269 { 0270 QGraphicsItem::mouseMoveEvent(event); 0271 return; 0272 } 0273 bool hasCtrlModifier= (event->modifiers() & Qt::ControlModifier); 0274 bool hasShiftModifier= (event->modifiers() & Qt::ShiftModifier); 0275 0276 if(!hasCtrlModifier && (m_motion & ChildPointItem::Y_AXIS || m_motion & ChildPointItem::X_AXIS) 0277 && allowResizing(m_currentChange)) 0278 { 0279 m_currentChange= Resizing; 0280 auto move= event->pos() - event->lastPos(); 0281 m_motion& ChildPointItem::Y_AXIS ? move.setX(0) : move.setY(0); 0282 m_ctrl->setCorner(move, m_pointId); 0283 } 0284 0285 if(!hasCtrlModifier && (m_motion & MOVE) && allowResizing(m_currentChange)) 0286 { 0287 m_currentChange= Resizing; 0288 Core::TransformType transformType= Core::TransformType::NoTransform; 0289 0290 auto W= qMax(2 * std::fabs(v.x()), 5.0); 0291 auto H= qMax(2 * std::fabs(v.y()), 4.0); 0292 if(event->modifiers() & Qt::AltModifier) 0293 { 0294 transformType= Core::TransformType::Sticky; 0295 int size= m_ctrl->gridSize(); 0296 W= std::round(W / size) * size; 0297 H= std::round(H / size) * size; 0298 } 0299 else if(hasShiftModifier) 0300 { 0301 transformType= Core::TransformType::KeepRatio; 0302 } 0303 0304 auto move= event->pos() - event->lastPos(); 0305 m_ctrl->setCorner(move, m_pointId, transformType); // mapToScene(pos()) + 0306 } 0307 0308 if((m_motion & ROTATION) && hasCtrlModifier && allowRotation(m_currentChange)) 0309 { 0310 if(v.isNull()) 0311 return; 0312 m_currentChange= Rotation; 0313 0314 QPointF refPos= pos(); 0315 0316 // set item rotation (set rotation relative to current) 0317 qreal refAngle= atan2(refPos.y(), refPos.x()); 0318 qreal newAngle= atan2(v.y(), v.x()); 0319 double dZr= 57.29577951308232 * (newAngle - refAngle); // 180 * a / M_PI 0320 double zr= m_ctrl->rotation() + dZr; 0321 m_ctrl->setRotation(zr); 0322 } 0323 else 0324 { 0325 QGraphicsItem::mouseMoveEvent(event); 0326 } 0327 } 0328 void ChildPointItem::mouseReleaseEvent(QGraphicsSceneMouseEvent* event) 0329 { 0330 m_parent->endOfGeometryChange(m_currentChange); 0331 m_currentChange= None; 0332 0333 QGraphicsItem::mouseReleaseEvent(event); 0334 } 0335 0336 void ChildPointItem::setEditableItem(bool b) 0337 { 0338 m_editable= b; 0339 // if((m_editable) && (((MOUSE == m_motion) || (NONE == m_motion)))) 0340 { 0341 setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsFocusable); 0342 } 0343 } 0344 void ChildPointItem::setPointID(int a) 0345 { 0346 m_pointId= a; 0347 } 0348 int ChildPointItem::getPointID() const 0349 { 0350 return m_pointId; 0351 } 0352 0353 ChildPointItem::Control ChildPointItem::control() const 0354 { 0355 return m_control; 0356 }