1 /************************************************************************
2  **
3  **  @file   vnodepoint.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 "vnodepoint.h"
30 
31 #include <QBrush>
32 #include <QDomElement>
33 #include <QFlags>
34 #include <QGraphicsLineItem>
35 #include <QGraphicsScene>
36 #include <QGraphicsSceneMouseEvent>
37 #include <QIcon>
38 #include <QMenu>
39 #include <QPen>
40 #include <QPoint>
41 #include <QRectF>
42 #include <QSharedPointer>
43 #include <QStaticStringData>
44 #include <QStringData>
45 #include <QStringDataPtr>
46 #include <Qt>
47 #include <new>
48 
49 #include "../../../vgeometry/vpointf.h"
50 #include "../../../vwidgets/vgraphicssimpletextitem.h"
51 #include "../ifc/xml/vdomdocument.h"
52 #include "../ifc/ifcdef.h"
53 #include "../vmisc/vabstractapplication.h"
54 #include "../vpatterndb/vcontainer.h"
55 #include "../vpatterndb/vpiecenode.h"
56 #include "../vwidgets/vmaingraphicsscene.h"
57 #include "../vwidgets/vmaingraphicsview.h"
58 #include "../vabstracttool.h"
59 #include "../vdatatool.h"
60 #include "vabstractnode.h"
61 #include "../../undocommands/label/movelabel.h"
62 #include "../../undocommands/label/showlabel.h"
63 #include "../vtoolseamallowance.h"
64 
65 const QString VNodePoint::ToolType = QStringLiteral("modeling");
66 
67 namespace
68 {
69 enum class ContextMenuOption : int
70 {
71     NoSelection,
72     ShowLabel,
73     Passmark,
74     Exclude,
75     ByLength,
76     ByPointsIntersection,
77     ByFirstEdgeSymmetry,
78     BySecondEdgeSymmetry,
79     ByFirstEdgeRightAngle,
80     BySecondEdgeRightAngle,
81     Straightforward,
82     Bisector,
83     Intersection,
84     IntersectionOnlyLeft,
85     IntersectionOnlyRight,
86     Intersection2,
87     Intersection2OnlyLeft,
88     Intersection2OnlyRight,
89     OneLine,
90     TwoLines,
91     ThreeLines,
92     TMark,
93     VMark,
94     VMark2,
95     UMark,
96     BoxMark,
97     Option,
98     InLayout,
99     ForbidFlipping,
100     ForceFlipping,
101     Remove,
102     LAST_ONE_DO_NOT_USE
103 };
104 }
105 
106 //---------------------------------------------------------------------------------------------------------------------
107 /**
108  * @brief VNodePoint constructor.
109  * @param initData init data.
110  * @param parent parent object.
111  */
VNodePoint(const VAbstractNodeInitData & initData,QObject * qoParent,QGraphicsItem * parent)112 VNodePoint::VNodePoint(const VAbstractNodeInitData &initData, QObject *qoParent, QGraphicsItem *parent)
113     : VAbstractNode(initData.doc, initData.data, initData.id, initData.idObject, initData.drawName, initData.idTool,
114                     qoParent),
115       VScenePoint(parent)
116 {
117     m_namePoint->SetShowParentTooltip(false);
118     connect(m_namePoint, &VGraphicsSimpleTextItem::PointChoosed, this, &VNodePoint::PointChoosed);
119     connect(m_namePoint, &VGraphicsSimpleTextItem::NameChangePosition, this, &VNodePoint::NameChangePosition);
120     connect(m_namePoint, &VGraphicsSimpleTextItem::ShowContextMenu,
121             this, [this](QGraphicsSceneContextMenuEvent *event)
122     {
123         contextMenuEvent(event);
124     });
125     RefreshPointGeometry(*VAbstractTool::data.GeometricObject<VPointF>(initData.id));
126     ToolCreation(initData.typeCreation);
127     setCursor(Qt::ArrowCursor);
128 }
129 
130 //---------------------------------------------------------------------------------------------------------------------
131 /**
132  * @brief Create help create tool.
133  * @param initData init data.
134  */
Create(const VAbstractNodeInitData & initData)135 void VNodePoint::Create(const VAbstractNodeInitData &initData)
136 {
137     if (initData.parse == Document::FullParse)
138     {
139         VAbstractTool::AddRecord(initData.id, Tool::NodePoint, initData.doc);
140         //TODO Need create garbage collector and remove all nodes, what we don't use.
141         //Better check garbage before each saving file. Check only modeling tags.
142         VNodePoint *point = new VNodePoint(initData);
143 
144         connect(initData.scene, &VMainGraphicsScene::EnableToolMove, point, &VNodePoint::EnableToolMove);
145         connect(initData.scene, &VMainGraphicsScene::EnablePointItemHover, point, &VNodePoint::AllowHover);
146         connect(initData.scene, &VMainGraphicsScene::EnablePointItemSelection, point, &VNodePoint::AllowSelecting);
147         connect(initData.scene, &VMainGraphicsScene::EnableLabelItemHover, point, &VNodePoint::AllowLabelHover);
148         connect(initData.scene, &VMainGraphicsScene::EnableLabelItemSelection, point, &VNodePoint::AllowLabelSelecting);
149         VAbstractPattern::AddTool(initData.id, point);
150         if (initData.idTool != NULL_ID)
151         {
152             //Some nodes we don't show on scene. Tool that create this nodes must free memory.
153             VDataTool *tool = VAbstractPattern::getTool(initData.idTool);
154             SCASSERT(tool != nullptr)
155             point->setParent(tool);// Adopted by a tool
156         }
157         else
158         {
159             // Try to prevent memory leak
160             initData.scene->addItem(point);// First adopted by scene
161             point->hide();// If no one will use node, it will stay hidden
162             point->SetParentType(ParentType::Scene);
163         }
164     }
165     else
166     {
167         initData.doc->UpdateToolData(initData.id, initData.data);
168     }
169 }
170 
171 //---------------------------------------------------------------------------------------------------------------------
getTagName() const172 QString VNodePoint::getTagName() const
173 {
174     return VAbstractPattern::TagPoint;
175 }
176 
177 //---------------------------------------------------------------------------------------------------------------------
ChangeLabelPosition(quint32 id,const QPointF & pos)178 void VNodePoint::ChangeLabelPosition(quint32 id, const QPointF &pos)
179 {
180     if (id == m_id)
181     {
182         QSharedPointer<VPointF> point = VAbstractTool::data.GeometricObject<VPointF>(id);
183         point->setMx(pos.x());
184         point->setMy(pos.y());
185         m_namePoint->SetRealPos(pos);
186         RefreshLine();
187         if (QGraphicsScene *sc = scene())
188         {
189             VMainGraphicsView::NewSceneRect(sc, VAbstractValApplication::VApp()->getSceneView(), this);
190         }
191     }
192 }
193 
194 //---------------------------------------------------------------------------------------------------------------------
SetLabelVisible(quint32 id,bool visible)195 void VNodePoint::SetLabelVisible(quint32 id, bool visible)
196 {
197     if (m_id == id)
198     {
199         const QSharedPointer<VPointF> point = VAbstractTool::data.GeometricObject<VPointF>(id);
200         point->SetShowLabel(visible);
201         RefreshPointGeometry(*point);
202         if (QGraphicsScene *sc = scene())
203         {
204             VMainGraphicsView::NewSceneRect(sc, VAbstractValApplication::VApp()->getSceneView(), this);
205         }
206     }
207 }
208 
209 //---------------------------------------------------------------------------------------------------------------------
PointChoosed()210 void VNodePoint::PointChoosed()
211 {
212     emit ChoosedTool(m_id, SceneObject::Point);
213 }
214 
215 //---------------------------------------------------------------------------------------------------------------------
216 /**
217  * @brief FullUpdateFromFile update tool data form file.
218  */
FullUpdateFromFile()219 void VNodePoint::FullUpdateFromFile()
220 {
221     try
222     {
223         RefreshPointGeometry(*VAbstractTool::data.GeometricObject<VPointF>(m_id));
224     }
225     catch (const VExceptionBadId &)
226     {
227         // ignore
228     }
229 }
230 
231 //---------------------------------------------------------------------------------------------------------------------
232 /**
233  * @brief AddToFile add tag with informations about tool into file.
234  */
AddToFile()235 void VNodePoint::AddToFile()
236 {
237     const QSharedPointer<VPointF> point = VAbstractTool::data.GeometricObject<VPointF>(m_id);
238     QDomElement domElement = doc->createElement(getTagName());
239 
240     doc->SetAttribute(domElement, VDomDocument::AttrId, m_id);
241     doc->SetAttribute(domElement, AttrType, ToolType);
242     doc->SetAttribute(domElement, AttrIdObject, idNode);
243     doc->SetAttribute(domElement, AttrMx, VAbstractValApplication::VApp()->fromPixel(point->mx()));
244     doc->SetAttribute(domElement, AttrMy, VAbstractValApplication::VApp()->fromPixel(point->my()));
245     doc->SetAttribute<bool>(domElement, AttrShowLabel, point->IsShowLabel());
246     if (idTool != NULL_ID)
247     {
248         doc->SetAttribute(domElement, AttrIdTool, idTool);
249     }
250 
251     AddToModeling(domElement);
252 }
253 
254 //---------------------------------------------------------------------------------------------------------------------
mousePressEvent(QGraphicsSceneMouseEvent * event)255 void VNodePoint::mousePressEvent(QGraphicsSceneMouseEvent *event)
256 {
257     // Special for not selectable item first need to call standard mousePressEvent then accept event
258     VScenePoint::mousePressEvent(event);
259 
260     // Somehow clicking on notselectable object do not clean previous selections.
261     if (not (flags() & ItemIsSelectable) && scene())
262     {
263         scene()->clearSelection();
264     }
265 
266     event->accept();// Special for not selectable item first need to call standard mousePressEvent then accept event
267 }
268 
269 //---------------------------------------------------------------------------------------------------------------------
270 /**
271  * @brief mouseReleaseEvent handle mouse release events.
272  * @param event mouse release event.
273  */
mouseReleaseEvent(QGraphicsSceneMouseEvent * event)274 void VNodePoint::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
275 {
276     if (IsSelectedByReleaseEvent(this, event))
277     {
278         emit ChoosedTool(m_id, SceneObject::Point);
279     }
280     VScenePoint::mouseReleaseEvent(event);
281 }
282 
283 //---------------------------------------------------------------------------------------------------------------------
284 /**
285  * @brief NameChangePosition label change position.
286  * @param pos new position.
287  */
NameChangePosition(const QPointF & pos)288 void VNodePoint::NameChangePosition(const QPointF &pos)
289 {
290     VAbstractApplication::VApp()->getUndoStack()->push(new MoveLabel(doc, pos - this->pos(), m_id));
291 }
292 
293 //---------------------------------------------------------------------------------------------------------------------
ShowNode()294 void VNodePoint::ShowNode()
295 {
296     if (parentType != ParentType::Scene && not m_exluded)
297     {
298         show();
299     }
300 }
301 
302 //---------------------------------------------------------------------------------------------------------------------
HideNode()303 void VNodePoint::HideNode()
304 {
305     hide();
306 }
307 
308 //---------------------------------------------------------------------------------------------------------------------
InitContextMenu(QMenu * menu,vidtype pieceId,quint32 referens)309 QHash<int, QAction *> VNodePoint::InitContextMenu(QMenu *menu, vidtype pieceId, quint32 referens)
310 {
311     SCASSERT(menu != nullptr)
312 
313     QHash<int, QAction *> contextMenu;
314 
315     QAction *actionShowLabel = menu->addAction(tr("Show label"));
316     actionShowLabel->setCheckable(true);
317     actionShowLabel->setChecked(VAbstractTool::data.GeometricObject<VPointF>(m_id)->IsShowLabel());
318     contextMenu.insert(static_cast<int>(ContextMenuOption::ShowLabel), actionShowLabel);
319 
320     InitPassmarkMenu(menu, pieceId, contextMenu);
321 
322     contextMenu.insert(static_cast<int>(ContextMenuOption::Exclude), menu->addAction(tr("Exclude")));
323 
324     InitAngleTypeMenu(menu, pieceId, contextMenu);
325     InitPassmarkAngleTypeMenu(menu, pieceId, contextMenu);
326     InitPassmarkLineTypeMenu(menu, pieceId, contextMenu);
327 
328     QAction *separatorAct = new QAction(this);
329     separatorAct->setSeparator(true);
330     menu->addAction(separatorAct);
331 
332     contextMenu.insert(static_cast<int>(ContextMenuOption::Option),
333                        menu->addAction(QIcon::fromTheme(QStringLiteral("preferences-other")), tr("Options")));
334 
335     const VPiece detail = VAbstractTool::data.GetPiece(pieceId);
336 
337     QAction *inLayoutOption = menu->addAction(tr("In layout"));
338     inLayoutOption->setCheckable(true);
339     inLayoutOption->setChecked(detail.IsInLayout());
340     contextMenu.insert(static_cast<int>(ContextMenuOption::InLayout), inLayoutOption);
341 
342     QAction *forbidFlippingOption = menu->addAction(tr("Forbid flipping"));
343     forbidFlippingOption->setCheckable(true);
344     forbidFlippingOption->setChecked(detail.IsForbidFlipping());
345     contextMenu.insert(static_cast<int>(ContextMenuOption::ForbidFlipping), forbidFlippingOption);
346 
347     QAction *forceFlippingOption = menu->addAction(tr("Force flipping"));
348     forceFlippingOption->setCheckable(true);
349     forceFlippingOption->setChecked(detail.IsForceFlipping());
350     contextMenu.insert(static_cast<int>(ContextMenuOption::ForceFlipping), forceFlippingOption);
351 
352     QAction *actionRemove = menu->addAction(QIcon::fromTheme(QStringLiteral("edit-delete")), tr("Delete"));
353     referens > 1 ? actionRemove->setEnabled(false) : actionRemove->setEnabled(true);
354     contextMenu.insert(static_cast<int>(ContextMenuOption::Remove), actionRemove);
355 
356     return contextMenu;
357 }
358 
359 //---------------------------------------------------------------------------------------------------------------------
InitPassmarkMenu(QMenu * menu,vidtype pieceId,QHash<int,QAction * > & contextMenu)360 void VNodePoint::InitPassmarkMenu(QMenu *menu, vidtype pieceId, QHash<int, QAction *> &contextMenu)
361 {
362     SCASSERT(menu != nullptr)
363 
364     const VPiece detail = VAbstractTool::data.GetPiece(pieceId);
365     const int nodeIndex = detail.GetPath().indexOfNode(m_id);
366     if (nodeIndex != -1)
367     {
368         QAction *actionPassmark = menu->addAction(tr("Passmark"));
369         actionPassmark->setCheckable(true);
370         actionPassmark->setChecked(detail.GetPath().at(nodeIndex).IsPassmark());
371 
372         contextMenu.insert(static_cast<int>(ContextMenuOption::Passmark), actionPassmark);
373     }
374 }
375 
376 //---------------------------------------------------------------------------------------------------------------------
InitAngleTypeMenu(QMenu * menu,vidtype pieceId,QHash<int,QAction * > & contextMenu)377 void VNodePoint::InitAngleTypeMenu(QMenu *menu, vidtype pieceId, QHash<int, QAction *> &contextMenu)
378 {
379     QMenu *angleTypeMenu = menu->addMenu(tr("Seam allowance angle"));
380     PieceNodeAngle curType = PieceNodeAngle::ByLength;
381 
382     const VPiece detail = VAbstractTool::data.GetPiece(pieceId);
383     const int nodeIndex = detail.GetPath().indexOfNode(m_id);
384     if (nodeIndex != -1)
385     {
386         const VPieceNode &node = detail.GetPath().at(nodeIndex);
387         curType = node.GetAngleType();
388 
389         angleTypeMenu->setEnabled(detail.IsSeamAllowance() && not detail.IsSeamAllowanceBuiltIn());
390     }
391     else
392     {
393         angleTypeMenu->setVisible(false);
394     }
395 
396     auto InitAngleAction = [angleTypeMenu, curType](const QString &name, PieceNodeAngle checkType)
397     {
398         QAction *action = angleTypeMenu->addAction(name);
399         action->setCheckable(true);
400         action->setChecked(curType == checkType);
401         return action;
402     };
403 
404     Q_STATIC_ASSERT_X(static_cast<int>(PieceNodeAngle::LAST_ONE_DO_NOT_USE) == 7, "Not all types were handled.");
405     contextMenu.insert(static_cast<int>(ContextMenuOption::ByLength),
406                        InitAngleAction(tr("by length"), PieceNodeAngle::ByLength));
407     contextMenu.insert(static_cast<int>(ContextMenuOption::ByPointsIntersection),
408                        InitAngleAction(tr("by points intersetions"), PieceNodeAngle::ByPointsIntersection));
409     contextMenu.insert(static_cast<int>(ContextMenuOption::ByFirstEdgeSymmetry),
410                        InitAngleAction(tr("by first edge symmetry"), PieceNodeAngle::ByFirstEdgeSymmetry));
411     contextMenu.insert(static_cast<int>(ContextMenuOption::BySecondEdgeSymmetry),
412                        InitAngleAction(tr("by second edge symmetry"), PieceNodeAngle::BySecondEdgeSymmetry));
413     contextMenu.insert(static_cast<int>(ContextMenuOption::ByFirstEdgeRightAngle),
414                        InitAngleAction(tr("by first edge right angle"), PieceNodeAngle::ByFirstEdgeRightAngle));
415     contextMenu.insert(static_cast<int>(ContextMenuOption::BySecondEdgeRightAngle),
416                        InitAngleAction(tr("by second edge right angle"), PieceNodeAngle::BySecondEdgeRightAngle));
417 }
418 
419 //---------------------------------------------------------------------------------------------------------------------
InitPassmarkAngleTypeMenu(QMenu * menu,vidtype pieceId,QHash<int,QAction * > & contextMenu)420 void VNodePoint::InitPassmarkAngleTypeMenu(QMenu *menu, vidtype pieceId, QHash<int, QAction *> &contextMenu)
421 {
422     QMenu *passmarkAngleMenu = menu->addMenu(tr("Passmark angle"));
423     PassmarkAngleType passmarkAngleCurType = PassmarkAngleType::Straightforward;
424 
425     const VPiece detail = VAbstractTool::data.GetPiece(pieceId);
426     const int nodeIndex = detail.GetPath().indexOfNode(m_id);
427     if (nodeIndex != -1)
428     {
429         const VPieceNode &node = detail.GetPath().at(nodeIndex);
430         passmarkAngleMenu->setEnabled(node.IsPassmark());
431         passmarkAngleCurType = node.GetPassmarkAngleType();
432     }
433     else
434     {
435         passmarkAngleMenu->setVisible(false);
436     }
437 
438     auto InitPassmarkAngleAction = [passmarkAngleMenu, passmarkAngleCurType](const QString &name,
439             PassmarkAngleType checkType)
440     {
441         QAction *action = passmarkAngleMenu->addAction(name);
442         action->setCheckable(true);
443         action->setChecked(passmarkAngleCurType == checkType);
444         return action;
445     };
446 
447     Q_STATIC_ASSERT_X(static_cast<int>(PassmarkAngleType::LAST_ONE_DO_NOT_USE) == 8, "Not all types were handled.");
448     contextMenu.insert(static_cast<int>(ContextMenuOption::Straightforward),
449                        InitPassmarkAngleAction(tr("Straightforward"), PassmarkAngleType::Straightforward));
450     contextMenu.insert(static_cast<int>(ContextMenuOption::Bisector),
451                        InitPassmarkAngleAction(tr("Bisector"), PassmarkAngleType::Bisector));
452     contextMenu.insert(static_cast<int>(ContextMenuOption::Intersection),
453                        InitPassmarkAngleAction(tr("Intersection"), PassmarkAngleType::Intersection));
454     contextMenu.insert(static_cast<int>(ContextMenuOption::IntersectionOnlyLeft),
455                        InitPassmarkAngleAction(tr("Intersection (only left)"),
456                                                PassmarkAngleType::IntersectionOnlyLeft));
457     contextMenu.insert(static_cast<int>(ContextMenuOption::IntersectionOnlyRight),
458                        InitPassmarkAngleAction(tr("Intersection (only right)"),
459                                                PassmarkAngleType::IntersectionOnlyRight));
460     contextMenu.insert(static_cast<int>(ContextMenuOption::Intersection2),
461                        InitPassmarkAngleAction(tr("Intersection 2"), PassmarkAngleType::Intersection2));
462     contextMenu.insert(static_cast<int>(ContextMenuOption::Intersection2OnlyLeft),
463                        InitPassmarkAngleAction(tr("Intersection 2 (only left)"),
464                                                PassmarkAngleType::Intersection2OnlyLeft));
465     contextMenu.insert(static_cast<int>(ContextMenuOption::Intersection2OnlyRight),
466                        InitPassmarkAngleAction(tr("Intersection 2 (only right)"),
467                                                PassmarkAngleType::Intersection2OnlyRight));
468 }
469 
470 //---------------------------------------------------------------------------------------------------------------------
InitPassmarkLineTypeMenu(QMenu * menu,vidtype pieceId,QHash<int,QAction * > & contextMenu)471 void VNodePoint::InitPassmarkLineTypeMenu(QMenu *menu, vidtype pieceId, QHash<int, QAction *> &contextMenu)
472 {
473     QMenu *passmarkLineTypeMenu = menu->addMenu(tr("Passmark mark"));
474     PassmarkLineType passmarkLineCurType = PassmarkLineType::OneLine;
475 
476     const VPiece detail = VAbstractTool::data.GetPiece(pieceId);
477     const int nodeIndex = detail.GetPath().indexOfNode(m_id);
478     if (nodeIndex != -1)
479     {
480         const VPieceNode &node = detail.GetPath().at(nodeIndex);
481         passmarkLineTypeMenu->setEnabled(node.IsPassmark());
482         passmarkLineCurType = node.GetPassmarkLineType();
483     }
484     else
485     {
486         passmarkLineTypeMenu->setVisible(false);
487     }
488 
489     auto InitPassmarkLineTypeAction = [passmarkLineTypeMenu, passmarkLineCurType](const QString &name,
490             PassmarkLineType checkType)
491     {
492         QAction *action = passmarkLineTypeMenu->addAction(name);
493         action->setCheckable(true);
494         action->setChecked(passmarkLineCurType == checkType);
495         return action;
496     };
497 
498     Q_STATIC_ASSERT_X(static_cast<int>(PassmarkLineType::LAST_ONE_DO_NOT_USE) == 8, "Not all types were handled.");
499     contextMenu.insert(static_cast<int>(ContextMenuOption::OneLine),
500                        InitPassmarkLineTypeAction(tr("One line"), PassmarkLineType::OneLine));
501     contextMenu.insert(static_cast<int>(ContextMenuOption::TwoLines),
502                        InitPassmarkLineTypeAction(tr("Two lines"), PassmarkLineType::TwoLines));
503     contextMenu.insert(static_cast<int>(ContextMenuOption::ThreeLines),
504                        InitPassmarkLineTypeAction(tr("Three lines"), PassmarkLineType::ThreeLines));
505     contextMenu.insert(static_cast<int>(ContextMenuOption::TMark),
506                        InitPassmarkLineTypeAction(tr("T mark"), PassmarkLineType::TMark));
507     contextMenu.insert(static_cast<int>(ContextMenuOption::VMark),
508                        InitPassmarkLineTypeAction(tr("V mark"), PassmarkLineType::VMark));
509     contextMenu.insert(static_cast<int>(ContextMenuOption::VMark2),
510                        InitPassmarkLineTypeAction(tr("V mark 2"), PassmarkLineType::VMark2));
511     contextMenu.insert(static_cast<int>(ContextMenuOption::UMark),
512                        InitPassmarkLineTypeAction(tr("U mark"), PassmarkLineType::UMark));
513     contextMenu.insert(static_cast<int>(ContextMenuOption::BoxMark),
514                        InitPassmarkLineTypeAction(tr("Box mark"), PassmarkLineType::BoxMark));
515 
516 }
517 
518 //---------------------------------------------------------------------------------------------------------------------
contextMenuEvent(QGraphicsSceneContextMenuEvent * event)519 void VNodePoint::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
520 {
521     if (m_suppressContextMenu)
522     {
523         return;
524     }
525 
526     if (VToolSeamAllowance *piece = qgraphicsitem_cast<VToolSeamAllowance *>(parentItem()))
527     {
528         QMenu menu;
529         QHash<int, QAction *> contextMenu = InitContextMenu(&menu, piece->getId(), piece->referens());
530 
531         PieceNodeAngle angleCurType = PieceNodeAngle::ByLength;
532         PassmarkAngleType passmarkAngleCurType = PassmarkAngleType::Straightforward;
533         PassmarkLineType passmarkLineCurType = PassmarkLineType::OneLine;
534         bool isPassmark = false;
535 
536         const VPiece detail = VAbstractTool::data.GetPiece(piece->getId());
537         const int nodeIndex = detail.GetPath().indexOfNode(m_id);
538         if (nodeIndex != -1)
539         {
540             const VPieceNode &node = detail.GetPath().at(nodeIndex);
541             angleCurType = node.GetAngleType();
542             passmarkAngleCurType = node.GetPassmarkAngleType();
543             passmarkLineCurType = node.GetPassmarkLineType();
544             isPassmark = node.IsPassmark();
545         }
546 
547         auto SelectSeamAllowanceAngle = [angleCurType, this](PieceNodeAngle type)
548         {
549             if (angleCurType != type)
550             {
551                 emit ToggleSeamAllowanceAngleType(m_id, type);
552             }
553         };
554 
555         auto SelectPassmarkAngle = [passmarkAngleCurType, this](PassmarkAngleType type)
556         {
557             if (passmarkAngleCurType != type)
558             {
559                 emit TogglePassmarkAngleType(m_id, type);
560             }
561         };
562 
563         auto SelectPassmarkLine = [passmarkLineCurType, this](PassmarkLineType type)
564         {
565             if (passmarkLineCurType != type)
566             {
567                 emit TogglePassmarkLineType(m_id, type);
568             }
569         };
570 
571         QAction *selectedAction = menu.exec(event->screenPos());
572         ContextMenuOption selectedOption = static_cast<ContextMenuOption>(
573                     contextMenu.key(selectedAction, static_cast<int>(ContextMenuOption::NoSelection)));
574 
575         Q_STATIC_ASSERT_X(static_cast<int>(ContextMenuOption::LAST_ONE_DO_NOT_USE) == 31,
576                           "Not all options were handled.");
577 
578 QT_WARNING_PUSH
579 QT_WARNING_DISABLE_GCC("-Wswitch-default")
580         switch(selectedOption)
581         {
582             case ContextMenuOption::LAST_ONE_DO_NOT_USE:
583                 Q_UNREACHABLE();
584             case ContextMenuOption::NoSelection:
585                 return;
586             case ContextMenuOption::Option:
587                 emit ShowOptions();
588                 break;
589             case ContextMenuOption::InLayout:
590                 emit ToggleInLayout(selectedAction->isChecked());
591                 break;
592             case ContextMenuOption::ForbidFlipping:
593                 emit ToggleForbidFlipping(selectedAction->isChecked());
594                 break;
595             case ContextMenuOption::ForceFlipping:
596                 emit ToggleForceFlipping(selectedAction->isChecked());
597                 break;
598             case ContextMenuOption::Remove:
599                 try
600                 {
601                     emit Delete();
602                 }
603                 catch(const VExceptionToolWasDeleted &e)
604                 {
605                     Q_UNUSED(e);
606                     return;//Leave this method immediately!!!
607                 }
608                 return;//Leave this method immediately after call!!!
609             case ContextMenuOption::ShowLabel:
610                 VAbstractApplication::VApp()->getUndoStack()->push(
611                             new ShowLabel(doc, m_id, selectedAction->isChecked()));
612                 break;
613             case ContextMenuOption::Exclude:
614                 emit ToggleExcludeState(m_id);
615                 break;
616             case ContextMenuOption::ByLength:
617                 SelectSeamAllowanceAngle(PieceNodeAngle::ByLength);
618                 break;
619             case ContextMenuOption::ByPointsIntersection:
620                 SelectSeamAllowanceAngle(PieceNodeAngle::ByPointsIntersection);
621                 break;
622             case ContextMenuOption::ByFirstEdgeSymmetry:
623                 SelectSeamAllowanceAngle(PieceNodeAngle::ByFirstEdgeSymmetry);
624                 break;
625             case ContextMenuOption::BySecondEdgeSymmetry:
626                 SelectSeamAllowanceAngle(PieceNodeAngle::BySecondEdgeSymmetry);
627                 break;
628             case ContextMenuOption::ByFirstEdgeRightAngle:
629                 SelectSeamAllowanceAngle(PieceNodeAngle::ByFirstEdgeRightAngle);
630                 break;
631             case ContextMenuOption::BySecondEdgeRightAngle:
632                 SelectSeamAllowanceAngle(PieceNodeAngle::BySecondEdgeRightAngle);
633                 break;
634             case ContextMenuOption::Passmark:
635                 emit TogglePassmark(m_id, not isPassmark);
636                 break;
637             case ContextMenuOption::Straightforward:
638                 SelectPassmarkAngle(PassmarkAngleType::Straightforward);
639                 break;
640             case ContextMenuOption::Bisector:
641                 SelectPassmarkAngle(PassmarkAngleType::Bisector);
642                 break;
643             case ContextMenuOption::Intersection:
644                 SelectPassmarkAngle(PassmarkAngleType::Intersection);
645                 break;
646             case ContextMenuOption::IntersectionOnlyLeft:
647                 SelectPassmarkAngle(PassmarkAngleType::IntersectionOnlyLeft);
648                 break;
649             case ContextMenuOption::IntersectionOnlyRight:
650                 SelectPassmarkAngle(PassmarkAngleType::IntersectionOnlyRight);
651                 break;
652             case ContextMenuOption::Intersection2:
653                 SelectPassmarkAngle(PassmarkAngleType::Intersection2);
654                 break;
655             case ContextMenuOption::Intersection2OnlyLeft:
656                 SelectPassmarkAngle(PassmarkAngleType::Intersection2OnlyLeft);
657                 break;
658             case ContextMenuOption::Intersection2OnlyRight:
659                 SelectPassmarkAngle(PassmarkAngleType::Intersection2OnlyRight);
660                 break;
661             case ContextMenuOption::OneLine:
662                 SelectPassmarkLine(PassmarkLineType::OneLine);
663                 break;
664             case ContextMenuOption::TwoLines:
665                 SelectPassmarkLine(PassmarkLineType::TwoLines);
666                 break;
667             case ContextMenuOption::ThreeLines:
668                 SelectPassmarkLine(PassmarkLineType::ThreeLines);
669                 break;
670             case ContextMenuOption::TMark:
671                 SelectPassmarkLine(PassmarkLineType::TMark);
672                 break;
673             case ContextMenuOption::VMark:
674                 SelectPassmarkLine(PassmarkLineType::VMark);
675                 break;
676             case ContextMenuOption::VMark2:
677                 SelectPassmarkLine(PassmarkLineType::VMark2);
678                 break;
679             case ContextMenuOption::UMark:
680                 SelectPassmarkLine(PassmarkLineType::UMark);
681                 break;
682             case ContextMenuOption::BoxMark:
683                 SelectPassmarkLine(PassmarkLineType::BoxMark);
684                 break;
685         };
686 QT_WARNING_POP
687     }
688 }
689 
690 //---------------------------------------------------------------------------------------------------------------------
hoverEnterEvent(QGraphicsSceneHoverEvent * event)691 void VNodePoint::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
692 {
693     setToolTip(VAbstractTool::data.GetGObject(m_id)->name());
694     VScenePoint::hoverEnterEvent(event);
695 }
696 
697 //---------------------------------------------------------------------------------------------------------------------
EnableToolMove(bool move)698 void VNodePoint::EnableToolMove(bool move)
699 {
700     m_namePoint->setFlag(QGraphicsItem::ItemIsMovable, move);
701 }
702 
703 //---------------------------------------------------------------------------------------------------------------------
AllowHover(bool enabled)704 void VNodePoint::AllowHover(bool enabled)
705 {
706     setAcceptHoverEvents(enabled);
707 }
708 
709 //---------------------------------------------------------------------------------------------------------------------
AllowSelecting(bool enabled)710 void VNodePoint::AllowSelecting(bool enabled)
711 {
712     setFlag(QGraphicsItem::ItemIsSelectable, enabled);
713 }
714 
715 //---------------------------------------------------------------------------------------------------------------------
AllowLabelHover(bool enabled)716 void VNodePoint::AllowLabelHover(bool enabled)
717 {
718     m_namePoint->setAcceptHoverEvents(enabled);
719 }
720 
721 //---------------------------------------------------------------------------------------------------------------------
AllowLabelSelecting(bool enabled)722 void VNodePoint::AllowLabelSelecting(bool enabled)
723 {
724     m_namePoint->setFlag(QGraphicsItem::ItemIsSelectable, enabled);
725 }
726