Seamly2D
Code documentation
vcontrolpointspline.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * *
3  * Copyright (C) 2017 Seamly, LLC *
4  * *
5  * https://github.com/fashionfreedom/seamly2d *
6  * *
7  ***************************************************************************
8  **
9  ** Seamly2D is free software: you can redistribute it and/or modify
10  ** it under the terms of the GNU General Public License as published by
11  ** the Free Software Foundation, either version 3 of the License, or
12  ** (at your option) any later version.
13  **
14  ** Seamly2D is distributed in the hope that it will be useful,
15  ** but WITHOUT ANY WARRANTY; without even the implied warranty of
16  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  ** GNU General Public License for more details.
18  **
19  ** You should have received a copy of the GNU General Public License
20  ** along with Seamly2D. If not, see <http://www.gnu.org/licenses/>.
21  **
22  **************************************************************************
23 
24  ************************************************************************
25  **
26  ** @file vcontrolpointspline.cpp
27  ** @author Roman Telezhynskyi <dismine(at)gmail.com>
28  ** @date November 15, 2013
29  **
30  ** @brief
31  ** @copyright
32  ** This source code is part of the Valentine project, a pattern making
33  ** program, whose allow create and modeling patterns of clothing.
34  ** Copyright (C) 2013-2015 Seamly2D project
35  ** <https://github.com/fashionfreedom/seamly2d> All Rights Reserved.
36  **
37  ** Seamly2D is free software: you can redistribute it and/or modify
38  ** it under the terms of the GNU General Public License as published by
39  ** the Free Software Foundation, either version 3 of the License, or
40  ** (at your option) any later version.
41  **
42  ** Seamly2D is distributed in the hope that it will be useful,
43  ** but WITHOUT ANY WARRANTY; without even the implied warranty of
44  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
45  ** GNU General Public License for more details.
46  **
47  ** You should have received a copy of the GNU General Public License
48  ** along with Seamly2D. If not, see <http://www.gnu.org/licenses/>.
49  **
50  *************************************************************************/
51 
52 #include "vcontrolpointspline.h"
53 
54 #include <QBrush>
55 #include <QEvent>
56 #include <QGraphicsLineItem>
57 #include <QGraphicsScene>
58 #include <QGraphicsSceneMouseEvent>
59 #include <QGraphicsView>
60 #include <QLineF>
61 #include <QList>
62 #include <QMessageLogger>
63 #include <QPen>
64 #include <QPoint>
65 #include <QPolygonF>
66 #include <QRectF>
67 #include <Qt>
68 
69 #include "../vwidgets/global.h"
70 #include "../vmisc/vabstractapplication.h"
71 #include "../vgeometry/vgobject.h"
72 #include "vmaingraphicsscene.h"
73 #include "vmaingraphicsview.h"
75 #include "scalesceneitems.h"
76 
77 //---------------------------------------------------------------------------------------------------------------------
78 VControlPointSpline::VControlPointSpline(const qint32 &indexSpline, SplinePointPosition position, QGraphicsItem *parent)
79  : SceneRect(QColor(Qt::red), parent)
80  , controlLine(nullptr)
81  , indexSpline(indexSpline)
82  , position(position)
83  , freeAngle(true)
84  , freeLength(true)
85 {
86  init();
87 }
88 
89 //---------------------------------------------------------------------------------------------------------------------
90 /**
91  * @brief VControlPointSpline constructor.
92  * @param indexSpline index spline in list.
93  * @param position position point in spline.
94  * @param controlPoint control point.
95  * @param splinePoint spline point.
96  * @param parent parent object.
97  */
99  const QPointF &controlPoint, const QPointF &splinePoint, bool freeAngle,
100  bool freeLength, QGraphicsItem *parent)
101  : SceneRect(QColor(Qt::red), parent)
102  , controlLine(nullptr)
103  , indexSpline(indexSpline)
104  , position(position)
105  , freeAngle(freeAngle)
106  , freeLength(freeLength)
107 {
108  init();
109 
110  this->setFlag(QGraphicsItem::ItemIsMovable, true);
111  this->setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
112  this->setAcceptHoverEvents(true);
113  this->setPos(controlPoint);
114 
115  setCtrlLine(controlPoint, splinePoint);
116 }
117 
118 //---------------------------------------------------------------------------------------------------------------------
119 void VControlPointSpline::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
120 {
121  QPen lPen = controlLine->pen();
122  lPen.setColor(correctColor(controlLine, Qt::black));
123  controlLine->setPen(lPen);
124 
125  SceneRect::paint(painter, option, widget);
126 }
127 
128 //---------------------------------------------------------------------------------------------------------------------
129 /**
130  * @brief hoverEnterEvent handle hover enter events.
131  * @param event hover move event.
132  */
133 void VControlPointSpline::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
134 {
135  if (freeAngle || freeLength)
136  {
138  }
140 }
141 
142 //---------------------------------------------------------------------------------------------------------------------
143 void VControlPointSpline::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
144 {
145  if (freeAngle || freeLength)
146  {
147  setCursor(QCursor());
148  }
150 }
151 
152 //---------------------------------------------------------------------------------------------------------------------
153 /**
154  * @brief itemChange handle item change.
155  * @param change change.
156  * @param value value.
157  * @return value.
158  */
159 QVariant VControlPointSpline::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value)
160 {
161  switch (change)
162  {
163  case ItemPositionChange:
164  {
165  if (not freeAngle || not freeLength)
166  {
167  const QPointF splPoint = controlLine->line().p1() + pos();
168 
169  QLineF newLine(splPoint, value.toPointF());// value - new position.
170  QLineF oldLine(splPoint, pos());// pos() - old position.
171 
172  if (not freeAngle)
173  {
174  newLine.setAngle(oldLine.angle());
175  }
176 
177  if (not freeLength)
178  {
179  newLine.setLength(oldLine.length());
180  }
181 
182  return newLine.p2();
183  }
184 
185  break;
186  }
187  case ItemPositionHasChanged:
188  {
189  // Each time we move something we call recalculation scene rect. In some cases this can cause moving
190  // objects positions. And this cause infinite redrawing. That's why we wait the finish of saving the last
191  // move.
192  static bool changeFinished = true;
193  if (changeFinished)
194  {
195  changeFinished = false;
196  // value - new position.
197  emit ControlPointChangePosition(indexSpline, position, value.toPointF());
198  if (scene())
199  {
200  const QList<QGraphicsView *> viewList = scene()->views();
201  if (not viewList.isEmpty())
202  {
203  if (QGraphicsView *view = viewList.at(0))
204  {
205  const int xmargin = 50;
206  const int ymargin = 50;
207 
208  const QRectF viewRect = VMainGraphicsView::SceneVisibleArea(view);
209  const QRectF itemRect = mapToScene(boundingRect()).boundingRect();
210 
211  // If item's rect is bigger than view's rect ensureVisible works very unstable.
212  if (itemRect.height() + 2*ymargin < viewRect.height() &&
213  itemRect.width() + 2*xmargin < viewRect.width())
214  {
215  view->ensureVisible(itemRect, xmargin, ymargin);
216  }
217  else
218  {
219  // Ensure visible only small rect around a cursor
220  VMainGraphicsScene *currentScene = qobject_cast<VMainGraphicsScene *>(scene());
221  SCASSERT(currentScene)
222  const QPointF cursorPosition = currentScene->getScenePos();
223  view->ensureVisible(QRectF(cursorPosition.x()-5, cursorPosition.y()-5, 10, 10));
224  }
225  }
226  }
227  }
228  changeFinished = true;
229  }
230  break;
231  }
232  default:
233  break;
234  }
235  return SceneRect::itemChange(change, value);
236 }
237 
238 //---------------------------------------------------------------------------------------------------------------------
239 void VControlPointSpline::mousePressEvent(QGraphicsSceneMouseEvent *event)
240 {
241  if (event->button() == Qt::LeftButton && event->type() != QEvent::GraphicsSceneMouseDoubleClick)
242  {
243  if (freeAngle || freeLength)
244  {
246  }
247  }
248  SceneRect::mousePressEvent(event);
249 }
250 
251 //---------------------------------------------------------------------------------------------------------------------
252 void VControlPointSpline::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
253 {
254  if (event->button() == Qt::LeftButton && event->type() != QEvent::GraphicsSceneMouseDoubleClick)
255  {
256  if (freeAngle || freeLength)
257  {
259  }
260  }
261  SceneRect::mouseReleaseEvent(event);
262 }
263 
264 //---------------------------------------------------------------------------------------------------------------------
265 void VControlPointSpline::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
266 {
267  emit showContextMenu(event);
268 }
269 
270 //---------------------------------------------------------------------------------------------------------------------
272 {
273  setOnlyPoint(true);
274  this->setBrush(QBrush(Qt::NoBrush));
275  this->setZValue(100);
276 
277  controlLine = new VScaledLine(this);
279  controlLine->setFlag(QGraphicsItem::ItemStacksBehindParent, true);
280 }
281 
282 //---------------------------------------------------------------------------------------------------------------------
283 void VControlPointSpline::setCtrlLine(const QPointF &controlPoint, const QPointF &splinePoint)
284 {
285  QPointF p1, p2;
287  QLineF( QPointF(), splinePoint-controlPoint), p1, p2);
288  controlLine->setLine(QLineF(splinePoint-controlPoint, p1));
289 }
290 
291 //---------------------------------------------------------------------------------------------------------------------
292 /**
293  * @brief refreshCtrlPoint refresh the control point.
294  * @param indexSpline index spline in list.
295  * @param pos position point in spline.
296  * @param controlPoint control point.
297  * @param splinePoint spline point.
298  */
299 void VControlPointSpline::refreshCtrlPoint(const qint32 &indexSpline, SplinePointPosition pos,
300  const QPointF &controlPoint, const QPointF &splinePoint, bool freeAngle,
301  bool freeLength)
302 {
303  if (this->indexSpline == indexSpline && this->position == pos)
304  {
305  this->freeAngle = freeAngle;
306  this->freeLength = freeLength;
307  this->setPos(controlPoint);
308  setCtrlLine(controlPoint, splinePoint);
309  }
310 }
311 
312 //---------------------------------------------------------------------------------------------------------------------
313 /**
314  * @brief setEnabledPoint disable or enable control point.
315  * @param enable true - enable.
316  */
318 {
319  setEnabled(enable);
320  controlLine->setEnabled(enable);
321 
322  setFlag(QGraphicsItem::ItemIsSelectable, enable);
323  setFlag(QGraphicsItem::ItemIsMovable, enable);
324  setAcceptHoverEvents(enable);
325 }
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget=nullptr) Q_DECL_OVERRIDE
Definition: scene_rect.cpp:54
void setOnlyPoint(bool value)
Definition: scene_rect.cpp:73
virtual void hoverEnterEvent(QGraphicsSceneHoverEvent *event) Q_DECL_OVERRIDE
Definition: scene_rect.cpp:90
virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) Q_DECL_OVERRIDE
Definition: scene_rect.cpp:97
qint32 indexSpline
indexSpline index spline in list..
QVariant itemChange(GraphicsItemChange change, const QVariant &value) Q_DECL_OVERRIDE
itemChange handle item change.
virtual void mousePressEvent(QGraphicsSceneMouseEvent *event) Q_DECL_OVERRIDE
virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) Q_DECL_OVERRIDE
void showContextMenu(QGraphicsSceneContextMenuEvent *event)
showContextMenu emit when need show tool's context menu.
void ControlPointChangePosition(const qint32 &indexSpline, SplinePointPosition position, const QPointF &pos)
ControlPointChangePosition emit when control point change position.
SplinePointPosition position
position position point in spline.
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) Q_DECL_OVERRIDE
virtual void hoverEnterEvent(QGraphicsSceneHoverEvent *event) Q_DECL_OVERRIDE
hoverEnterEvent handle hover enter events.
void setCtrlLine(const QPointF &controlPoint, const QPointF &splinePoint)
void setEnabledPoint(bool enable)
setEnabledPoint disable or enable control point.
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget=nullptr) Q_DECL_OVERRIDE
VScaledLine * controlLine
controlLine pointer to line control point.
VControlPointSpline(const qint32 &indexSpline, SplinePointPosition position, QGraphicsItem *parent=nullptr)
virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) Q_DECL_OVERRIDE
void refreshCtrlPoint(const qint32 &indexSpline, SplinePointPosition pos, const QPointF &controlPoint, const QPointF &splinePoint, bool freeAngle=true, bool freeLength=true)
refreshCtrlPoint refresh the control point.
static qint32 LineIntersectCircle(const QPointF &center, qreal radius, const QLineF &line, QPointF &p1, QPointF &p2)
LineIntersectCircle find point intersection line and circle.
Definition: vgobject.cpp:391
The VMainGraphicsScene class main scene.
QPointF getScenePos() const
static QRectF SceneVisibleArea(QGraphicsView *view)
void setBasicWidth(const qreal &value)
const QString cursorArrowOpenHand
Definition: def.cpp:191
void SetItemOverrideCursor(QGraphicsItem *item, const QString &pixmapPath, int hotX, int hotY)
Definition: def.cpp:206
const QString cursorArrowCloseHand
Definition: def.cpp:192
#define SCASSERT(cond)
Definition: def.h:317
qreal sceneScale(QGraphicsScene *scene)
Definition: global.cpp:63
qreal scaledRadius(qreal scale)
Definition: global.cpp:103
QColor correctColor(const QGraphicsItem *item, const QColor &color)
Definition: global.cpp:80
const qreal widthHairLine
Definition: global.cpp:61
SplinePointPosition
Definition: vgeometrydef.h:58