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