1 /************************************************************************
2 **
3 ** @file vtoolsinglepoint.cpp
4 ** @author Roman Telezhynskyi <dismine(at)gmail.com>
5 ** @date November 15, 2013
6 **
7 ** @brief
8 ** @copyright
9 ** This source code is part of the Valentina project, a pattern making
10 ** program, whose allow create and modeling patterns of clothing.
11 ** Copyright (C) 2013-2015 Valentina project
12 ** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
13 **
14 ** Valentina is free software: you can redistribute it and/or modify
15 ** it under the terms of the GNU General Public License as published by
16 ** the Free Software Foundation, either version 3 of the License, or
17 ** (at your option) any later version.
18 **
19 ** Valentina is distributed in the hope that it will be useful,
20 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
21 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 ** GNU General Public License for more details.
23 **
24 ** You should have received a copy of the GNU General Public License
25 ** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
26 **
27 *************************************************************************/
28
29 #include "vtoolbasepoint.h"
30
31 #include <QApplication>
32 #include <QEvent>
33 #include <QFlags>
34 #include <QGraphicsLineItem>
35 #include <QGraphicsScene>
36 #include <QGraphicsSceneMouseEvent>
37 #include <QGraphicsView>
38 #include <QList>
39 #include <QMessageBox>
40 #include <QPen>
41 #include <QPointF>
42 #include <QPolygonF>
43 #include <QRectF>
44 #include <QSharedPointer>
45 #include <QStaticStringData>
46 #include <QStringData>
47 #include <QStringDataPtr>
48 #include <QUndoStack>
49 #include <new>
50
51 #include "../../../../dialogs/tools/dialogtool.h"
52 #include "../../../../dialogs/tools/dialogsinglepoint.h"
53 #include "../../../../undocommands/addpatternpiece.h"
54 #include "../../../../undocommands/deletepatternpiece.h"
55 #include "../../../../undocommands/movespoint.h"
56 #include "../ifc/exception/vexception.h"
57 #include "../ifc/ifcdef.h"
58 #include "../vgeometry/vgobject.h"
59 #include "../vgeometry/vpointf.h"
60 #include "../vmisc/vabstractapplication.h"
61 #include "../vpatterndb/vcontainer.h"
62 #include "../vwidgets/vgraphicssimpletextitem.h"
63 #include "../vwidgets/vmaingraphicsscene.h"
64 #include "../vwidgets/vmaingraphicsview.h"
65 #include "../../../vabstracttool.h"
66 #include "../../../vdatatool.h"
67 #include "../../vdrawtool.h"
68 #include "vtoolsinglepoint.h"
69
70 const QString VToolBasePoint::ToolType = QStringLiteral("single");
71
72 //---------------------------------------------------------------------------------------------------------------------
73 /**
74 * @brief VToolBasePoint constructor.
75 * @param initData init data.
76 * @param parent parent object.
77 */
VToolBasePoint(const VToolBasePointInitData & initData,QGraphicsItem * parent)78 VToolBasePoint::VToolBasePoint (const VToolBasePointInitData &initData, QGraphicsItem * parent )
79 :VToolSinglePoint(initData.doc, initData.data, initData.id, initData.notes, parent),
80 namePP(initData.nameActivPP)
81 {
82 m_baseColor = Qt::red;
83 this->setFlag(QGraphicsItem::ItemIsMovable, true);
84 this->setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
85 m_namePoint->setBrush(Qt::black);
86 ToolCreation(initData.typeCreation);
87 }
88
89 //---------------------------------------------------------------------------------------------------------------------
90 /**
91 * @brief setDialog set dialog when user want change tool option.
92 */
setDialog()93 void VToolBasePoint::setDialog()
94 {
95 SCASSERT(not m_dialog.isNull())
96 const QPointer<DialogSinglePoint> dialogTool = qobject_cast<DialogSinglePoint *>(m_dialog);
97 SCASSERT(not dialogTool.isNull())
98 const QSharedPointer<VPointF> p = VAbstractTool::data.GeometricObject<VPointF>(m_id);
99 dialogTool->SetData(p->name(), static_cast<QPointF>(*p));
100 dialogTool->SetNotes(m_notes);
101 }
102
103 //---------------------------------------------------------------------------------------------------------------------
Create(VToolBasePointInitData initData)104 VToolBasePoint *VToolBasePoint::Create(VToolBasePointInitData initData)
105 {
106 VPointF *point = new VPointF(initData.x, initData.y, initData.name, initData.mx, initData.my);
107 point->SetShowLabel(initData.showLabel);
108
109 if (initData.typeCreation == Source::FromGui)
110 {
111 initData.id = initData.data->AddGObject(point);
112 }
113 else
114 {
115 initData.data->UpdateGObject(initData.id, point);
116 if (initData.parse != Document::FullParse)
117 {
118 initData.doc->UpdateToolData(initData.id, initData.data);
119 }
120 }
121
122 if (initData.parse == Document::FullParse)
123 {
124 VAbstractTool::AddRecord(initData.id, Tool::BasePoint, initData.doc);
125 VToolBasePoint *spoint = new VToolBasePoint(initData);
126 initData.scene->addItem(spoint);
127 InitToolConnections(initData.scene, spoint);
128 VAbstractPattern::AddTool(initData.id, spoint);
129 return spoint;
130 }
131 return nullptr;
132 }
133
134 //---------------------------------------------------------------------------------------------------------------------
ShowVisualization(bool show)135 void VToolBasePoint::ShowVisualization(bool show)
136 {
137 Q_UNUSED(show) //don't have any visualization for base point yet
138 }
139
140 //---------------------------------------------------------------------------------------------------------------------
141 /**
142 * @brief AddToFile add tag with informations about tool into file.
143 */
AddToFile()144 void VToolBasePoint::AddToFile()
145 {
146 Q_ASSERT_X(not namePP.isEmpty(), Q_FUNC_INFO, "name pattern piece is empty");
147
148 QDomElement sPoint = doc->createElement(getTagName());
149
150 // Create SPoint tag
151 QSharedPointer<VGObject> obj = VAbstractTool::data.GetGObject(m_id);
152 SaveOptions(sPoint, obj);
153
154 //Create pattern piece structure
155 QDomElement patternPiece = doc->createElement(VAbstractPattern::TagDraw);
156 doc->SetAttribute(patternPiece, AttrName, namePP);
157
158 QDomElement calcElement = doc->createElement(VAbstractPattern::TagCalculation);
159 calcElement.appendChild(sPoint);
160
161 patternPiece.appendChild(calcElement);
162 patternPiece.appendChild(doc->createElement(VAbstractPattern::TagModeling));
163 patternPiece.appendChild(doc->createElement(VAbstractPattern::TagDetails));
164
165 AddPatternPiece *addPP = new AddPatternPiece(patternPiece, doc, namePP);
166 connect(addPP, &AddPatternPiece::ClearScene, doc, &VAbstractPattern::ClearScene);
167 connect(addPP, &AddPatternPiece::NeedFullParsing, doc, &VAbstractPattern::NeedFullParsing);
168 VAbstractApplication::VApp()->getUndoStack()->push(addPP);
169 }
170
171 //---------------------------------------------------------------------------------------------------------------------
172 /**
173 * @brief itemChange handle tool change.
174 * @param change change.
175 * @param value value.
176 * @return value.
177 */
itemChange(QGraphicsItem::GraphicsItemChange change,const QVariant & value)178 QVariant VToolBasePoint::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value)
179 {
180 if (change == ItemPositionChange && scene())
181 {
182 // Each time we move something we call recalculation scene rect. In some cases this can cause moving
183 // objects positions. And this cause infinite redrawing. That's why we wait the finish of saving the last move.
184 static bool changeFinished = true;
185 if (changeFinished)
186 {
187 changeFinished = false;
188 // value - this is new position.
189 QPointF newPos = value.toPointF();
190
191 MoveSPoint *moveSP = new MoveSPoint(doc, newPos.x(), newPos.y(), m_id, this->scene());
192 connect(moveSP, &MoveSPoint::NeedLiteParsing, doc, &VAbstractPattern::LiteParseTree);
193 VAbstractApplication::VApp()->getUndoStack()->push(moveSP);
194 const QList<QGraphicsView *> viewList = scene()->views();
195 if (not viewList.isEmpty())
196 {
197 if (VMainGraphicsView *view = qobject_cast<VMainGraphicsView *>(viewList.at(0)))
198 {
199 view->EnsureItemVisibleWithDelay(this, VMainGraphicsView::scrollDelay);
200 }
201 }
202 changeFinished = true;
203 }
204 }
205 return VToolSinglePoint::itemChange(change, value);
206 }
207
208 //---------------------------------------------------------------------------------------------------------------------
GetBasePointPos() const209 QPointF VToolBasePoint::GetBasePointPos() const
210 {
211 const QSharedPointer<VPointF> p = VAbstractTool::data.GeometricObject<VPointF>(m_id);
212 QPointF pos(VAbstractValApplication::VApp()->fromPixel(p->x()), VAbstractValApplication::VApp()->fromPixel(p->y()));
213 return pos;
214 }
215
216 //---------------------------------------------------------------------------------------------------------------------
SetBasePointPos(const QPointF & pos)217 void VToolBasePoint::SetBasePointPos(const QPointF &pos)
218 {
219 QSharedPointer<VPointF> p = VAbstractTool::data.GeometricObject<VPointF>(m_id);
220 p->setX(VAbstractValApplication::VApp()->toPixel(pos.x()));
221 p->setY(VAbstractValApplication::VApp()->toPixel(pos.y()));
222
223 QSharedPointer<VGObject> obj = qSharedPointerCast<VGObject>(p);
224
225 SaveOption(obj);
226 }
227
228 //---------------------------------------------------------------------------------------------------------------------
DeleteToolWithConfirm(bool ask)229 void VToolBasePoint::DeleteToolWithConfirm(bool ask)
230 {
231 if (doc->CountPP() <= 1)
232 {
233 return;
234 }
235
236 qCDebug(vTool, "Deleting base point.");
237 emit VAbstractValApplication::VApp()->getSceneView()->itemClicked(nullptr);
238 if (ask)
239 {
240 qCDebug(vTool, "Asking.");
241 if (ConfirmDeletion() == QMessageBox::No)
242 {
243 qCDebug(vTool, "User said no.");
244 return;
245 }
246 }
247
248 qCDebug(vTool, "Begin deleting.");
249 DeletePatternPiece *deletePP = new DeletePatternPiece(doc, nameActivDraw);
250 connect(deletePP, &DeletePatternPiece::NeedFullParsing, doc, &VAbstractPattern::NeedFullParsing);
251 VAbstractApplication::VApp()->getUndoStack()->push(deletePP);
252
253 // Throw exception, this will help prevent case when we forget to immediately quit function.
254 VExceptionToolWasDeleted e("Tool was used after deleting.");
255 throw e;
256 }
257
258 //---------------------------------------------------------------------------------------------------------------------
259 /**
260 * @brief SaveDialog save options into file after change in dialog.
261 */
SaveDialog(QDomElement & domElement,QList<quint32> & oldDependencies,QList<quint32> & newDependencies)262 void VToolBasePoint::SaveDialog(QDomElement &domElement, QList<quint32> &oldDependencies,
263 QList<quint32> &newDependencies)
264 {
265 SCASSERT(not m_dialog.isNull())
266 const QPointer<DialogSinglePoint> dialogTool = qobject_cast<DialogSinglePoint *>(m_dialog);
267 SCASSERT(not dialogTool.isNull())
268
269 Q_UNUSED(oldDependencies)
270 Q_UNUSED(newDependencies)
271
272 const QPointF p = dialogTool->GetPoint();
273 const QString name = dialogTool->GetPointName();
274 doc->SetAttribute(domElement, AttrName, name);
275 doc->SetAttribute(domElement, AttrX, QString().setNum(VAbstractValApplication::VApp()->fromPixel(p.x())));
276 doc->SetAttribute(domElement, AttrY, QString().setNum(VAbstractValApplication::VApp()->fromPixel(p.y())));
277
278 const QString notes = dialogTool->GetNotes();
279 doc->SetAttributeOrRemoveIf(domElement, AttrNotes, notes, notes.isEmpty());
280 }
281
282 //---------------------------------------------------------------------------------------------------------------------
hoverEnterEvent(QGraphicsSceneHoverEvent * event)283 void VToolBasePoint::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
284 {
285 VToolSinglePoint::hoverEnterEvent(event);
286
287 if (flags() & QGraphicsItem::ItemIsMovable)
288 {
289 SetItemOverrideCursor(this, cursorArrowOpenHand, 1, 1);
290 }
291 }
292
293 //---------------------------------------------------------------------------------------------------------------------
mousePressEvent(QGraphicsSceneMouseEvent * event)294 void VToolBasePoint::mousePressEvent(QGraphicsSceneMouseEvent *event)
295 {
296 if (flags() & QGraphicsItem::ItemIsMovable)
297 {
298 if (event->button() == Qt::LeftButton && event->type() != QEvent::GraphicsSceneMouseDoubleClick)
299 {
300 SetItemOverrideCursor(this, cursorArrowCloseHand, 1, 1);
301 event->accept();
302 }
303 }
304 VToolSinglePoint::mousePressEvent(event);
305 }
306
307 //---------------------------------------------------------------------------------------------------------------------
mouseReleaseEvent(QGraphicsSceneMouseEvent * event)308 void VToolBasePoint::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
309 {
310 if (flags() & QGraphicsItem::ItemIsMovable)
311 {
312 if (event->button() == Qt::LeftButton && event->type() != QEvent::GraphicsSceneMouseDoubleClick)
313 {
314 SetItemOverrideCursor(this, cursorArrowOpenHand, 1, 1);
315 }
316 }
317 VToolSinglePoint::mouseReleaseEvent(event);
318 }
319
320 //---------------------------------------------------------------------------------------------------------------------
SaveOptions(QDomElement & tag,QSharedPointer<VGObject> & obj)321 void VToolBasePoint::SaveOptions(QDomElement &tag, QSharedPointer<VGObject> &obj)
322 {
323 VToolSinglePoint::SaveOptions(tag, obj);
324
325 QSharedPointer<VPointF> point = qSharedPointerDynamicCast<VPointF>(obj);
326 SCASSERT(point.isNull() == false)
327
328 doc->SetAttribute(tag, AttrType, ToolType);
329 doc->SetAttribute(tag, AttrX, VAbstractValApplication::VApp()->fromPixel(point->x()));
330 doc->SetAttribute(tag, AttrY, VAbstractValApplication::VApp()->fromPixel(point->y()));
331 }
332
333 //---------------------------------------------------------------------------------------------------------------------
MakeToolTip() const334 QString VToolBasePoint::MakeToolTip() const
335 {
336 const QSharedPointer<VPointF> point = VAbstractTool::data.GeometricObject<VPointF>(m_id);
337
338 const QString toolTip = QString("<table>"
339 "<tr> <td><b>%1:</b> %2</td> </tr>"
340 "</table>")
341 .arg(tr("Label"), point->name());
342 return toolTip;
343 }
344
345 //---------------------------------------------------------------------------------------------------------------------
ShowContextMenu(QGraphicsSceneContextMenuEvent * event,quint32 id)346 void VToolBasePoint::ShowContextMenu(QGraphicsSceneContextMenuEvent *event, quint32 id)
347 {
348 qCDebug(vTool, "Context menu base point");
349 #ifndef QT_NO_CURSOR
350 QGuiApplication::restoreOverrideCursor();
351 qCDebug(vTool, "Restored overriden cursor");
352 #endif
353
354 try
355 {
356 if (doc->CountPP() > 1)
357 {
358 qCDebug(vTool, "PP count > 1");
359 ContextMenu<DialogSinglePoint>(event, id, RemoveOption::Enable, Referens::Ignore);
360 }
361 else
362 {
363 qCDebug(vTool, "PP count = 1");
364 ContextMenu<DialogSinglePoint>(event, id, RemoveOption::Disable);
365 }
366 }
367 catch(const VExceptionToolWasDeleted &e)
368 {
369 qCDebug(vTool, "Tool was deleted. Immediately leave method.");
370 Q_UNUSED(e)
371 return;//Leave this method immediately!!!
372 }
373 qCDebug(vTool, "Context menu closed. Tool was not deleted.");
374 }
375
376 //---------------------------------------------------------------------------------------------------------------------
377 /**
378 * @brief FullUpdateFromFile update tool data form file.
379 */
FullUpdateFromFile()380 void VToolBasePoint::FullUpdateFromFile()
381 {
382 ReadAttributes();
383 RefreshPointGeometry(*VAbstractTool::data.GeometricObject<VPointF>(m_id));
384 }
385
386 //---------------------------------------------------------------------------------------------------------------------
EnableToolMove(bool move)387 void VToolBasePoint::EnableToolMove(bool move)
388 {
389 this->setFlag(QGraphicsItem::ItemIsMovable, move);
390 VToolSinglePoint::EnableToolMove(move);
391 }
392