1 /************************************************************************
2 **
3 ** @file vpatternrecipe.cpp
4 ** @author Roman Telezhynskyi <dismine(at)gmail.com>
5 ** @date 8 7, 2019
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) 2019 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 "vpatternrecipe.h"
30 #include "../vmisc/projectversion.h"
31 #include "../vmisc/vabstractapplication.h"
32 #include "../ifc/xml/vabstractpattern.h"
33 #include "../ifc/exception/vexceptioninvalidhistory.h"
34 #include "../vpatterndb/vcontainer.h"
35 #include "../vgeometry/vpointf.h"
36 #include "../vgeometry/vcubicbezier.h"
37 #include "../vgeometry/vsplinepath.h"
38 #include "../vgeometry/vcubicbezierpath.h"
39 #include "../vtools/tools/drawTools/drawtools.h"
40 #include "../vpatterndb/calculator.h"
41
42 namespace
43 {
44 #define TagStep QStringLiteral("step")
45
46 #define AttrLabel QStringLiteral("label")
47 #define AttrLengthValue QStringLiteral("lengthValue")
48 #define AttrAngleValue QStringLiteral("angleValue")
49 #define AttrAngle1Value QStringLiteral("angle1Value")
50 #define AttrAngle2Value QStringLiteral("angle2Value")
51 #define AttrLength1Value QStringLiteral("length1Value")
52 #define AttrLength2Value QStringLiteral("length2Value")
53 #define AttrRadiusValue QStringLiteral("radiusValue")
54 #define AttrC1RadiusValue QStringLiteral("c1RadiusValue")
55 #define AttrC2RadiusValue QStringLiteral("c2RadiusValue")
56 #define AttrCRadiusValue QStringLiteral("cRadiusValue")
57 #define AttrRadius1Value QStringLiteral("radius1Value")
58 #define AttrRadius2Value QStringLiteral("radius2Value")
59 #define AttrRotationAngleValue QStringLiteral("rotationAngleValue")
60
61 //---------------------------------------------------------------------------------------------------------------------
FileComment()62 inline QString FileComment()
63 {
64 return QStringLiteral("Recipe created with Valentina v%1 (https://smart-pattern.com.ua/).")
65 .arg(APP_VERSION_STR);
66 }
67
68 //---------------------------------------------------------------------------------------------------------------------
69 template <typename T>
GetPatternTool(quint32 id)70 T *GetPatternTool(quint32 id)
71 {
72 T* tool = qobject_cast<T*>(VAbstractPattern::getTool(id));
73 if (not tool)
74 {
75 throw VExceptionInvalidHistory(QObject::tr("Cannot cast tool with id '%1'.").arg(id));
76 }
77 return tool;
78 }
79 } // namespace
80
81 //---------------------------------------------------------------------------------------------------------------------
VPatternRecipe(VAbstractPattern * pattern,QObject * parent)82 VPatternRecipe::VPatternRecipe(VAbstractPattern *pattern, QObject *parent)
83 : VDomDocument(parent),
84 m_pattern(pattern)
85 {
86 SCASSERT(pattern != nullptr)
87
88 QDomElement recipeElement = createElement(QStringLiteral("recipe"));
89 recipeElement.appendChild(createComment(FileComment()));
90 SetAttribute(recipeElement, QStringLiteral("version"), QStringLiteral("1.3.0"));
91
92 recipeElement.appendChild(Prerequisite());
93 recipeElement.appendChild(Content());
94
95 appendChild(recipeElement);
96 insertBefore(createProcessingInstruction(QStringLiteral("xml"),
97 QStringLiteral("version=\"1.0\" encoding=\"UTF-8\"")), firstChild());
98 }
99
100 //---------------------------------------------------------------------------------------------------------------------
Prerequisite()101 QDomElement VPatternRecipe::Prerequisite()
102 {
103 /*
104 <prerequisite>
105 <measurements>
106 <m description="" full_name="Обхват талии" name="@От" value="65"/>
107 </measurements>
108 <increments>
109 <increment description="" formula="height/2-15" name="#L_C"/>
110 </increments>
111 <previewCalculations>
112 <increment description="" formula="height/2-15" name="#L_C"/>
113 </previewCalculations>
114 </prerequisite>
115 */
116 QDomElement prerequisiteElement = createElement(QStringLiteral("prerequisite"));
117
118 prerequisiteElement.appendChild(CreateElementWithText(QStringLiteral("valentina"), APP_VERSION_STR));
119 prerequisiteElement.appendChild(CreateElementWithText(QStringLiteral("unit"),
120 UnitsToStr(VAbstractValApplication::VApp()->patternUnits())));
121 prerequisiteElement.appendChild(CreateElementWithText(QStringLiteral("author"), m_pattern->GetCompanyName()));
122 prerequisiteElement.appendChild(CreateElementWithText(QStringLiteral("pattenName"), m_pattern->GetPatternName()));
123 prerequisiteElement.appendChild(CreateElementWithText(QStringLiteral("description"), m_pattern->GetDescription()));
124 prerequisiteElement.appendChild(CreateElementWithText(QStringLiteral("notes"), m_pattern->GetNotes()));
125 prerequisiteElement.appendChild(Measurements());
126 prerequisiteElement.appendChild(Increments());
127 prerequisiteElement.appendChild(PreviewCalculations());
128
129 return prerequisiteElement;
130 }
131
132 //---------------------------------------------------------------------------------------------------------------------
Measurements()133 QDomElement VPatternRecipe::Measurements()
134 {
135 QDomElement measurements = createElement(QStringLiteral("measurements"));
136
137 VContainer data = m_pattern->GetCompleteData();
138 QList<QSharedPointer<VMeasurement>> patternMeasurements = data.DataMeasurements().values();
139
140 // Resore order
141 std::sort(patternMeasurements.begin(), patternMeasurements.end(),
142 [](const QSharedPointer<VMeasurement> &a, const QSharedPointer<VMeasurement> &b)
143 {return a->Index() < b->Index();});
144
145 for(auto &m : patternMeasurements)
146 {
147 measurements.appendChild(Measurement(m));
148 }
149
150 return measurements;
151 }
152
153 //---------------------------------------------------------------------------------------------------------------------
Measurement(const QSharedPointer<VMeasurement> & m)154 QDomElement VPatternRecipe::Measurement(const QSharedPointer<VMeasurement> &m)
155 {
156 /*
157 * <measurements>
158 * <m description="" full_name="Обхват талии" name="@От" value="65"/>
159 * </measurements>
160 */
161 QDomElement measurement = createElement(QStringLiteral("measurement"));
162
163 SetAttribute(measurement, QStringLiteral("description"), m->GetDescription());
164 SetAttribute(measurement, QStringLiteral("fullName"), m->GetGuiText());
165 SetAttribute(measurement, QStringLiteral("name"), m->GetName());
166 SetAttribute(measurement, QStringLiteral("formula"), m->GetFormula()); // TODO: localize
167 SetAttribute(measurement, QStringLiteral("value"), *m->GetValue());
168
169 return measurement;
170 }
171
172 //---------------------------------------------------------------------------------------------------------------------
Increments()173 QDomElement VPatternRecipe::Increments()
174 {
175 QDomElement increments = createElement(QStringLiteral("increments"));
176
177 VContainer data = m_pattern->GetCompleteData();
178 QList<QSharedPointer<VIncrement>> patternIncrements = data.DataIncrementsWithSeparators().values();
179
180 // Resore order
181 std::sort(patternIncrements.begin(), patternIncrements.end(),
182 [](const QSharedPointer<VIncrement> &a, const QSharedPointer<VIncrement> &b)
183 {return a->GetIndex() < b->GetIndex();});
184
185 for(auto &incr : patternIncrements)
186 {
187 if (not incr->IsPreviewCalculation())
188 {
189 increments.appendChild(Increment(incr));
190 }
191 }
192
193 return increments;
194 }
195
196 //---------------------------------------------------------------------------------------------------------------------
PreviewCalculations()197 QDomElement VPatternRecipe::PreviewCalculations()
198 {
199 QDomElement previewCalculations = createElement(QStringLiteral("previewCalculations"));
200
201 VContainer data = m_pattern->GetCompleteData();
202 QList<QSharedPointer<VIncrement>> patternIncrements = data.DataIncrementsWithSeparators().values();
203
204 // Resore order
205 std::sort(patternIncrements.begin(), patternIncrements.end(),
206 [](const QSharedPointer<VIncrement> &a, const QSharedPointer<VIncrement> &b)
207 {return a->GetIndex() < b->GetIndex();});
208
209 for(auto &incr : patternIncrements)
210 {
211 if (incr->IsPreviewCalculation())
212 {
213 previewCalculations.appendChild(Increment(incr));
214 }
215 }
216
217 return previewCalculations;
218 }
219
220 //---------------------------------------------------------------------------------------------------------------------
Increment(const QSharedPointer<VIncrement> & incr)221 QDomElement VPatternRecipe::Increment(const QSharedPointer<VIncrement> &incr)
222 {
223 QDomElement measurement = createElement(QStringLiteral("increment"));
224
225 SetAttribute(measurement, QStringLiteral("description"), incr->GetDescription());
226 SetAttribute(measurement, QStringLiteral("name"), incr->GetName());
227
228 if (incr->GetType() != VarType::IncrementSeparator)
229 {
230 SetAttribute(measurement, QStringLiteral("formula"), incr->GetFormula()); // TODO: localize
231 SetAttribute(measurement, QStringLiteral("value"), *incr->GetValue());
232 }
233 else
234 {
235 SetAttribute(measurement, QStringLiteral("separator"), true);
236 }
237
238 return measurement;
239 }
240
241 //---------------------------------------------------------------------------------------------------------------------
Content()242 QDomElement VPatternRecipe::Content()
243 {
244 QDomElement content = createElement(QStringLiteral("content"));
245
246 const QDomNodeList draws = m_pattern->documentElement().elementsByTagName(VAbstractPattern::TagDraw);
247 for (int i=0; i < draws.size(); ++i)
248 {
249 QDomElement draw = draws.at(i).toElement();
250 if (draw.isNull())
251 {
252 throw VExceptionInvalidHistory(tr("Invalid tag %1").arg(VAbstractPattern::TagDraw));
253 }
254
255 content.appendChild(Draft(draw));
256 }
257
258 content.appendChild(FinalMeasurements());
259
260 return content;
261 }
262
263 //---------------------------------------------------------------------------------------------------------------------
Draft(const QDomElement & draft)264 QDomElement VPatternRecipe::Draft(const QDomElement &draft)
265 {
266 QDomElement recipeDraft = createElement(QStringLiteral("draft"));
267
268 const QString draftName = draft.attribute(QStringLiteral("name"));
269 SetAttribute(recipeDraft, QStringLiteral("name"), draftName);
270
271 VContainer data = m_pattern->GetCompletePPData(draftName);
272
273 QVector<VToolRecord> *history = m_pattern->getHistory();
274 for (auto &record : *history)
275 {
276 if (record.getNameDraw() == draftName)
277 {
278 QDomElement step = Step(record, data);
279 if (not step.isNull())
280 {
281 recipeDraft.appendChild(step);
282 }
283 }
284 }
285
286 return recipeDraft;
287 }
288
289 //---------------------------------------------------------------------------------------------------------------------
Step(const VToolRecord & tool,const VContainer & data)290 QDomElement VPatternRecipe::Step(const VToolRecord &tool, const VContainer &data)
291 {
292 // This check helps to find missed tools in the switch
293 Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 55, "Not all tools were used in history.");
294
295 const QDomElement domElem = m_pattern->elementById(tool.getId());
296 if (not domElem.isElement() && tool.IsMandatory())
297 {
298 throw VExceptionInvalidHistory(tr("Can't find element by id '%1'").arg(tool.getId()));
299 }
300 try
301 {
302 QT_WARNING_PUSH
303 QT_WARNING_DISABLE_GCC("-Wswitch-default")
304 switch (tool.getTypeTool())
305 {
306 case Tool::Arrow:
307 case Tool::SinglePoint:
308 case Tool::DoublePoint:
309 case Tool::LinePoint:
310 case Tool::AbstractSpline:
311 case Tool::Cut:
312 case Tool::Midpoint:// Same as Tool::AlongLine, but tool will never has such type
313 case Tool::ArcIntersectAxis:// Same as Tool::CurveIntersectAxis, but tool will never has such type
314 case Tool::LAST_ONE_DO_NOT_USE:
315 Q_UNREACHABLE(); //-V501
316 break;
317 case Tool::BasePoint:
318 return BasePoint(tool);
319 case Tool::EndLine:
320 return EndLine(tool);
321 case Tool::Line:
322 return Line(tool);
323 case Tool::AlongLine:
324 return AlongLine(tool);
325 case Tool::ShoulderPoint:
326 return ShoulderPoint(tool);
327 case Tool::Normal:
328 return Normal(tool);
329 case Tool::Bisector:
330 return Bisector(tool);
331 case Tool::LineIntersect:
332 return LineIntersect(tool);
333 case Tool::Spline:
334 return Spline(tool);
335 case Tool::CubicBezier:
336 return CubicBezier(tool);
337 case Tool::Arc:
338 return Arc(tool);
339 case Tool::ArcWithLength:
340 return ArcWithLength(tool);
341 case Tool::SplinePath:
342 return SplinePath(tool);
343 case Tool::CubicBezierPath:
344 return CubicBezierPath(tool);
345 case Tool::PointOfContact:
346 return PointOfContact(tool);
347 case Tool::Height:
348 return Height(tool);
349 case Tool::Triangle:
350 return Triangle(tool);
351 case Tool::PointOfIntersection:
352 return PointOfIntersection(tool);
353 case Tool::CutArc:
354 return CutArc(tool);
355 case Tool::CutSpline:
356 return CutSpline(tool);
357 case Tool::CutSplinePath:
358 return CutSplinePath(tool);
359 case Tool::LineIntersectAxis:
360 return LineIntersectAxis(tool);
361 case Tool::CurveIntersectAxis:
362 return CurveIntersectAxis(tool);
363 case Tool::PointOfIntersectionArcs:
364 return PointOfIntersectionArcs(tool);
365 case Tool::PointOfIntersectionCircles:
366 return PointOfIntersectionCircles(tool);
367 case Tool::PointOfIntersectionCurves:
368 return PointOfIntersectionCurves(tool);
369 case Tool::PointFromCircleAndTangent:
370 return PointFromCircleAndTangent(tool);
371 case Tool::PointFromArcAndTangent:
372 return PointFromArcAndTangent(tool);
373 case Tool::TrueDarts:
374 return TrueDarts(tool);
375 case Tool::EllipticalArc:
376 return EllipticalArc(tool);
377 case Tool::Rotation:
378 return Rotation(tool, data);
379 case Tool::FlippingByLine:
380 return FlippingByLine(tool, data);
381 case Tool::FlippingByAxis:
382 return FlippingByAxis(tool, data);
383 case Tool::Move:
384 return Move(tool, data);
385 //Because "history" not only show history of pattern, but help restore current data for each pattern's
386 //piece, we need add record about details and nodes, but don't show them.
387 case Tool::Piece:
388 case Tool::UnionDetails:
389 case Tool::NodeArc:
390 case Tool::NodeElArc:
391 case Tool::NodePoint:
392 case Tool::NodeSpline:
393 case Tool::NodeSplinePath:
394 case Tool::Group:
395 case Tool::PiecePath:
396 case Tool::Pin:
397 case Tool::PlaceLabel:
398 case Tool::InsertNode:
399 case Tool::DuplicateDetail:
400 return QDomElement();
401 }
402 QT_WARNING_POP
403 }
404 catch (const VExceptionBadId &e)
405 {
406 throw VExceptionInvalidHistory(e.ErrorMessage());
407 }
408
409 throw VExceptionInvalidHistory(tr("Can't create history record for the tool."));
410 }
411
412 //---------------------------------------------------------------------------------------------------------------------
FinalMeasurements()413 QDomElement VPatternRecipe::FinalMeasurements()
414 {
415 QDomElement recipeFinalMeasurements = createElement(QStringLiteral("finalMeasurements"));
416
417 const QVector<VFinalMeasurement> measurements = m_pattern->GetFinalMeasurements();
418 VContainer data = m_pattern->GetCompleteData();
419
420 for (auto &m : measurements)
421 {
422 recipeFinalMeasurements.appendChild(FinalMeasurement(m, data));
423 }
424
425 return recipeFinalMeasurements;
426 }
427
428 //---------------------------------------------------------------------------------------------------------------------
FinalMeasurement(const VFinalMeasurement & fm,const VContainer & data)429 QDomElement VPatternRecipe::FinalMeasurement(const VFinalMeasurement &fm, const VContainer &data)
430 {
431 QDomElement recipeFinalMeasurement = createElement(QStringLiteral("finalMeasurement"));
432
433 SetAttribute(recipeFinalMeasurement, QStringLiteral("description"), fm.description);
434 SetAttribute(recipeFinalMeasurement, QStringLiteral("name"), fm.name);
435 SetAttribute(recipeFinalMeasurement, QStringLiteral("formula"), fm.formula); // TODO: localize
436
437 QScopedPointer<Calculator> cal(new Calculator());
438 try
439 {
440 const qreal result = cal->EvalFormula(data.DataVariables(), fm.formula);
441 if (qIsInf(result) || qIsNaN(result))
442 {
443 const QString errorMsg = QString("%1\n\n%1").arg(tr("Reading final measurements error."),
444 tr("Value for final measurtement '%1' is infinite or NaN. "
445 "Please, check your calculations.").arg(fm.name));
446 VAbstractApplication::VApp()->IsPedantic() ? throw VException(errorMsg)
447 : qWarning()
448 << VAbstractValApplication::warningMessageSignature + errorMsg;
449 }
450
451 SetAttribute(recipeFinalMeasurement, QStringLiteral("value"), result);
452 }
453 catch (const qmu::QmuParserError &e)
454 {
455 throw VExceptionInvalidHistory(tr("Unable to create record for final measurement '%1'. Error: %2")
456 .arg(fm.name).arg(e.GetMsg()));
457 }
458
459 return recipeFinalMeasurement;
460 }
461
462 //---------------------------------------------------------------------------------------------------------------------
BasePoint(const VToolRecord & record)463 QDomElement VPatternRecipe::BasePoint(const VToolRecord &record)
464 {
465 auto *tool = GetPatternTool<VToolBasePoint>(record.getId());
466
467 QDomElement step = createElement(TagStep);
468 ToolAttributes(step, tool);
469 return step;
470 }
471
472 //---------------------------------------------------------------------------------------------------------------------
EndLine(const VToolRecord & record)473 QDomElement VPatternRecipe::EndLine(const VToolRecord &record)
474 {
475 auto *tool = GetPatternTool<VToolEndLine>(record.getId());
476
477 QDomElement step = createElement(TagStep);
478
479 ToolAttributes(step, tool);
480 SetAttribute(step, AttrBasePoint, tool->BasePointName());
481 Formula(step, tool->GetFormulaLength(), AttrLength, AttrLengthValue);
482 Formula(step, tool->GetFormulaAngle(), AttrAngle, AttrAngleValue);
483 LineAttributes(step, tool);
484
485 return step;
486 }
487
488 //---------------------------------------------------------------------------------------------------------------------
Line(const VToolRecord & record)489 QDomElement VPatternRecipe::Line(const VToolRecord &record)
490 {
491 auto *tool = GetPatternTool<VToolLine>(record.getId());
492
493 QDomElement step = createElement(TagStep);
494
495 SetAttribute(step, AttrType, QStringLiteral("segment"));
496 SetAttribute(step, AttrFirstPoint, tool->FirstPointName());
497 SetAttribute(step, AttrSecondPoint, tool->SecondPointName());
498 LineAttributes(step, tool);
499
500 return step;
501 }
502
503 //---------------------------------------------------------------------------------------------------------------------
AlongLine(const VToolRecord & record)504 QDomElement VPatternRecipe::AlongLine(const VToolRecord &record)
505 {
506 auto *tool = GetPatternTool<VToolAlongLine>(record.getId());
507
508 QDomElement step = createElement(TagStep);
509
510 ToolAttributes(step, tool);
511 SetAttribute(step, AttrBasePoint, tool->BasePointName());
512 SetAttribute(step, AttrSecondPoint, tool->SecondPointName());
513 Formula(step, tool->GetFormulaLength(), AttrLength, AttrLengthValue);
514 LineAttributes(step, tool);
515
516 return step;
517 }
518
519 //---------------------------------------------------------------------------------------------------------------------
ShoulderPoint(const VToolRecord & record)520 QDomElement VPatternRecipe::ShoulderPoint(const VToolRecord &record)
521 {
522 auto *tool = GetPatternTool<VToolShoulderPoint>(record.getId());
523
524 QDomElement step = createElement(TagStep);
525
526 ToolAttributes(step, tool);
527 SetAttribute(step, AttrP1Line, tool->BasePointName());
528 SetAttribute(step, AttrP2Line, tool->SecondPointName());
529 SetAttribute(step, AttrPShoulder, tool->ShoulderPointName());
530 Formula(step, tool->GetFormulaLength(), AttrLength, AttrLengthValue);
531 LineAttributes(step, tool);
532
533 return step;
534 }
535
536 //---------------------------------------------------------------------------------------------------------------------
Normal(const VToolRecord & record)537 QDomElement VPatternRecipe::Normal(const VToolRecord &record)
538 {
539 auto *tool = GetPatternTool<VToolNormal>(record.getId());
540
541 QDomElement step = createElement(TagStep);
542
543 ToolAttributes(step, tool);
544 SetAttribute(step, AttrFirstPoint, tool->BasePointName());
545 SetAttribute(step, AttrSecondPoint, tool->SecondPointName());
546 Formula(step, tool->GetFormulaLength(), AttrLength, AttrLengthValue);
547 SetAttribute(step, AttrAngle, tool->GetAngle());
548 LineAttributes(step, tool);
549
550 return step;
551 }
552
553 //---------------------------------------------------------------------------------------------------------------------
Bisector(const VToolRecord & record)554 QDomElement VPatternRecipe::Bisector(const VToolRecord &record)
555 {
556 auto *tool = GetPatternTool<VToolBisector>(record.getId());
557
558 QDomElement step = createElement(TagStep);
559
560 ToolAttributes(step, tool);
561 SetAttribute(step, AttrFirstPoint, tool->FirstPointName());
562 SetAttribute(step, AttrSecondPoint, tool->BasePointName());
563 SetAttribute(step, AttrThirdPoint, tool->ThirdPointName());
564 Formula(step, tool->GetFormulaLength(), AttrLength, AttrLengthValue);
565 LineAttributes(step, tool);
566
567 return step;
568 }
569
570 //---------------------------------------------------------------------------------------------------------------------
LineIntersect(const VToolRecord & record)571 QDomElement VPatternRecipe::LineIntersect(const VToolRecord &record)
572 {
573 auto *tool = GetPatternTool<VToolLineIntersect>(record.getId());
574
575 QDomElement step = createElement(TagStep);
576
577 ToolAttributes(step, tool);
578
579 SetAttribute(step, AttrP1Line1, tool->Line1P1Name());
580 SetAttribute(step, AttrP2Line1, tool->Line1P2Name());
581 SetAttribute(step, AttrP1Line2, tool->Line2P1Name());
582 SetAttribute(step, AttrP2Line2, tool->Line2P2Name());
583
584 return step;
585 }
586
587 //---------------------------------------------------------------------------------------------------------------------
Spline(const VToolRecord & record)588 QDomElement VPatternRecipe::Spline(const VToolRecord &record)
589 {
590 auto *tool = GetPatternTool<VToolSpline>(record.getId());
591 VSpline spl = tool->getSpline();
592
593 QDomElement step = createElement(TagStep);
594
595 SetAttribute(step, AttrType, QStringLiteral("spline"));
596 SetAttribute(step, AttrLabel, tool->name());
597
598 SetAttribute(step, AttrPoint1, spl.GetP1().name());
599 SetAttribute(step, AttrPoint4, spl.GetP4().name());
600
601 SetAttribute(step, AttrAngle1, spl.GetStartAngleFormula());
602 SetAttribute(step, AttrAngle1Value, spl.GetStartAngle());
603
604 SetAttribute(step, AttrAngle2, spl.GetEndAngleFormula());
605 SetAttribute(step, AttrAngle2Value, spl.GetEndAngle());
606
607 SetAttribute(step, AttrLength1, spl.GetC1LengthFormula());
608 SetAttribute(step, AttrLength1Value, VAbstractValApplication::VApp()->fromPixel(spl.GetC1Length()));
609
610 SetAttribute(step, AttrLength2, spl.GetC2LengthFormula());
611 SetAttribute(step, AttrLength2Value, VAbstractValApplication::VApp()->fromPixel(spl.GetC2Length()));
612
613 CurveAttributes(step, tool);
614
615 return step;
616 }
617
618 //---------------------------------------------------------------------------------------------------------------------
CubicBezier(const VToolRecord & record)619 QDomElement VPatternRecipe::CubicBezier(const VToolRecord &record)
620 {
621 auto *tool = GetPatternTool<VToolCubicBezier>(record.getId());
622 VCubicBezier spl = tool->getSpline();
623
624 QDomElement step = createElement(TagStep);
625
626 ToolAttributes(step, tool);
627 SetAttribute(step, AttrPoint1, spl.GetP1().name());
628 SetAttribute(step, AttrPoint2, spl.GetP2().name());
629 SetAttribute(step, AttrPoint3, spl.GetP3().name());
630 SetAttribute(step, AttrPoint4, spl.GetP4().name());
631
632 CurveAttributes(step, tool);
633
634 return step;
635 }
636
637 //---------------------------------------------------------------------------------------------------------------------
Arc(const VToolRecord & record)638 QDomElement VPatternRecipe::Arc(const VToolRecord &record)
639 {
640 auto *tool = GetPatternTool<VToolArc>(record.getId());
641
642 QDomElement step = createElement(TagStep);
643
644 SetAttribute(step, AttrType, QStringLiteral("arc"));
645 SetAttribute(step, AttrLabel, tool->name());
646 SetAttribute(step, AttrCenter, tool->CenterPointName());
647 Formula(step, tool->GetFormulaRadius(), AttrRadius, AttrRadiusValue);
648 Formula(step, tool->GetFormulaF1(), AttrAngle1, AttrAngle1Value);
649 Formula(step, tool->GetFormulaF2(), AttrAngle2, AttrAngle2Value);
650
651 CurveAttributes(step, tool);
652
653 return step;
654 }
655
656 //---------------------------------------------------------------------------------------------------------------------
ArcWithLength(const VToolRecord & record)657 QDomElement VPatternRecipe::ArcWithLength(const VToolRecord &record)
658 {
659 auto *tool = GetPatternTool<VToolArcWithLength>(record.getId());
660
661 QDomElement step = createElement(TagStep);
662
663 ToolAttributes(step, tool);
664 SetAttribute(step, AttrCenter, tool->CenterPointName());
665 Formula(step, tool->GetFormulaRadius(), AttrRadius, AttrRadiusValue);
666 Formula(step, tool->GetFormulaF1(), AttrAngle1, AttrAngle1Value);
667 Formula(step, tool->GetFormulaLength(), AttrLength, AttrLengthValue);
668
669 CurveAttributes(step, tool);
670
671 return step;
672 }
673
674 //---------------------------------------------------------------------------------------------------------------------
SplinePath(const VToolRecord & record)675 QDomElement VPatternRecipe::SplinePath(const VToolRecord &record)
676 {
677 auto *tool = GetPatternTool<VToolSplinePath>(record.getId());
678 VSplinePath spl = tool->getSplinePath();
679
680 QDomElement step = createElement(TagStep);
681
682 SetAttribute(step, AttrType, QStringLiteral("splinePath"));
683 SetAttribute(step, AttrLabel, tool->name());
684
685 QDomElement nodes = createElement(QStringLiteral("nodes"));
686 QVector<VSplinePoint> path = spl.GetSplinePath();
687
688 if (path.isEmpty())
689 {
690 throw VExceptionInvalidHistory(QObject::tr("Empty list of nodes for tool with id '%1'.").arg(record.getId()));
691 }
692
693 for (auto &pathNode : path)
694 {
695 QDomElement node = createElement(QStringLiteral("node"));
696
697 SetAttribute(node, AttrPSpline, pathNode.P().name());
698
699 SetAttribute(node, AttrAngle1, pathNode.Angle1Formula());
700 SetAttribute(node, AttrAngle1Value, pathNode.Angle1());
701
702 SetAttribute(node, AttrAngle2, pathNode.Angle2Formula());
703 SetAttribute(node, AttrAngle2Value, pathNode.Angle2());
704
705 SetAttribute(node, AttrLength1, pathNode.Length1Formula());
706 SetAttribute(node, AttrLength1Value, VAbstractValApplication::VApp()->fromPixel(pathNode.Length1()));
707
708 SetAttribute(node, AttrLength2, pathNode.Length2Formula());
709 SetAttribute(node, AttrLength2Value, VAbstractValApplication::VApp()->fromPixel(pathNode.Length2()));
710
711 nodes.appendChild(node);
712 }
713
714 step.appendChild(nodes);
715
716 CurveAttributes(step, tool);
717
718 return step;
719 }
720
721 //---------------------------------------------------------------------------------------------------------------------
CubicBezierPath(const VToolRecord & record)722 QDomElement VPatternRecipe::CubicBezierPath(const VToolRecord &record)
723 {
724 auto *tool = GetPatternTool<VToolCubicBezierPath>(record.getId());
725 VCubicBezierPath spl = tool->getSplinePath();
726
727 QDomElement step = createElement(TagStep);
728
729 ToolAttributes(step, tool);
730
731 QDomElement nodes = createElement(QStringLiteral("nodes"));
732 QVector<VSplinePoint> path = spl.GetSplinePath();
733
734 if (path.isEmpty())
735 {
736 throw VExceptionInvalidHistory(QObject::tr("Empty list of nodes for tool with id '%1'.").arg(record.getId()));
737 }
738
739 for (auto &pathNode : path)
740 {
741 QDomElement node = createElement(QStringLiteral("node"));
742
743 SetAttribute(node, AttrPSpline, pathNode.P().name());
744
745 nodes.appendChild(node);
746 }
747
748 step.appendChild(nodes);
749
750 CurveAttributes(step, tool);
751
752 return step;
753 }
754
755 //---------------------------------------------------------------------------------------------------------------------
PointOfContact(const VToolRecord & record)756 QDomElement VPatternRecipe::PointOfContact(const VToolRecord &record)
757 {
758 auto *tool = GetPatternTool<VToolPointOfContact>(record.getId());
759
760 QDomElement step = createElement(TagStep);
761
762 ToolAttributes(step, tool);
763 SetAttribute(step, AttrCenter, tool->ArcCenterPointName());
764 SetAttribute(step, AttrFirstPoint, tool->FirstPointName());
765 SetAttribute(step, AttrSecondPoint, tool->SecondPointName());
766 Formula(step, tool->getArcRadius(), AttrRadius, AttrRadiusValue);
767
768 return step;
769 }
770
771 //---------------------------------------------------------------------------------------------------------------------
Height(const VToolRecord & record)772 QDomElement VPatternRecipe::Height(const VToolRecord &record)
773 {
774 auto *tool = GetPatternTool<VToolHeight>(record.getId());
775
776 QDomElement step = createElement(TagStep);
777
778 ToolAttributes(step, tool);
779 SetAttribute(step, AttrBasePoint, tool->BasePointName());
780 SetAttribute(step, AttrP1Line, tool->FirstLinePointName());
781 SetAttribute(step, AttrP2Line, tool->SecondLinePointName());
782 LineAttributes(step, tool);
783
784 return step;
785 }
786
787 //---------------------------------------------------------------------------------------------------------------------
Triangle(const VToolRecord & record)788 QDomElement VPatternRecipe::Triangle(const VToolRecord &record)
789 {
790 auto *tool = GetPatternTool<VToolTriangle>(record.getId());
791
792 QDomElement step = createElement(TagStep);
793
794 ToolAttributes(step, tool);
795 SetAttribute(step, AttrAxisP1, tool->AxisP1Name());
796 SetAttribute(step, AttrAxisP2, tool->AxisP2Name());
797 SetAttribute(step, AttrFirstPoint, tool->FirstPointName());
798 SetAttribute(step, AttrSecondPoint, tool->SecondPointName());
799
800 return step;
801 }
802
803 //---------------------------------------------------------------------------------------------------------------------
PointOfIntersection(const VToolRecord & record)804 QDomElement VPatternRecipe::PointOfIntersection(const VToolRecord &record)
805 {
806 auto *tool = GetPatternTool<VToolPointOfIntersection>(record.getId());
807
808 QDomElement step = createElement(TagStep);
809
810 ToolAttributes(step, tool);
811 SetAttribute(step, AttrFirstPoint, tool->FirstPointName());
812 SetAttribute(step, AttrSecondPoint, tool->SecondPointName());
813
814 return step;
815 }
816
817 //---------------------------------------------------------------------------------------------------------------------
CutArc(const VToolRecord & record)818 QDomElement VPatternRecipe::CutArc(const VToolRecord &record)
819 {
820 auto *tool = GetPatternTool<VToolCutArc>(record.getId());
821
822 QDomElement step = createElement(TagStep);
823
824 ToolAttributes(step, tool);
825 Formula(step, tool->GetFormulaLength(), AttrLength, AttrLengthValue);
826 SetAttribute(step, AttrArc, tool->CurveName());
827
828 CutCurveAttributes(step, tool);
829
830 return step;
831 }
832
833 //---------------------------------------------------------------------------------------------------------------------
CutSpline(const VToolRecord & record)834 QDomElement VPatternRecipe::CutSpline(const VToolRecord &record)
835 {
836 auto *tool = GetPatternTool<VToolCutSpline>(record.getId());
837
838 QDomElement step = createElement(TagStep);
839
840 ToolAttributes(step, tool);
841 Formula(step, tool->GetFormulaLength(), AttrLength, AttrLengthValue);
842 SetAttribute(step, VToolCutSpline::AttrSpline, tool->CurveName());
843
844 CutCurveAttributes(step, tool);
845
846 return step;
847 }
848
849 //---------------------------------------------------------------------------------------------------------------------
CutSplinePath(const VToolRecord & record)850 QDomElement VPatternRecipe::CutSplinePath(const VToolRecord &record)
851 {
852 auto *tool = GetPatternTool<VToolCutSplinePath>(record.getId());
853
854 QDomElement step = createElement(TagStep);
855
856 ToolAttributes(step, tool);
857 Formula(step, tool->GetFormulaLength(), AttrLength, AttrLengthValue);
858 SetAttribute(step, VToolCutSplinePath::AttrSplinePath, tool->CurveName());
859
860 CutCurveAttributes(step, tool);
861
862 return step;
863 }
864
865 //---------------------------------------------------------------------------------------------------------------------
LineIntersectAxis(const VToolRecord & record)866 QDomElement VPatternRecipe::LineIntersectAxis(const VToolRecord &record)
867 {
868 auto *tool = GetPatternTool<VToolLineIntersectAxis>(record.getId());
869
870 QDomElement step = createElement(TagStep);
871
872 ToolAttributes(step, tool);
873 SetAttribute(step, AttrBasePoint, tool->BasePointName());
874 SetAttribute(step, AttrP1Line, tool->FirstLinePoint());
875 SetAttribute(step, AttrP2Line, tool->SecondLinePoint());
876 Formula(step, tool->GetFormulaAngle(), AttrAngle, AttrAngleValue);
877 LineAttributes(step, tool);
878
879 return step;
880 }
881
882 //---------------------------------------------------------------------------------------------------------------------
CurveIntersectAxis(const VToolRecord & record)883 QDomElement VPatternRecipe::CurveIntersectAxis(const VToolRecord &record)
884 {
885 auto *tool = GetPatternTool<VToolCurveIntersectAxis>(record.getId());
886
887 QDomElement step = createElement(TagStep);
888
889 ToolAttributes(step, tool);
890 SetAttribute(step, AttrBasePoint, tool->BasePointName());
891 SetAttribute(step, AttrCurve, tool->CurveName());
892 Formula(step, tool->GetFormulaAngle(), AttrAngle, AttrAngleValue);
893 LineAttributes(step, tool);
894
895 return step;
896 }
897
898 //---------------------------------------------------------------------------------------------------------------------
PointOfIntersectionArcs(const VToolRecord & record)899 QDomElement VPatternRecipe::PointOfIntersectionArcs(const VToolRecord &record)
900 {
901 auto *tool = GetPatternTool<VToolPointOfIntersectionArcs>(record.getId());
902
903 QDomElement step = createElement(TagStep);
904
905 ToolAttributes(step, tool);
906 SetAttribute(step, AttrFirstArc, tool->FirstArcName());
907 SetAttribute(step, AttrSecondArc, tool->SecondArcName());
908 SetAttribute(step, AttrCrossPoint, static_cast<int>(tool->GetCrossCirclesPoint()));
909
910 return step;
911 }
912
913 //---------------------------------------------------------------------------------------------------------------------
PointOfIntersectionCircles(const VToolRecord & record)914 QDomElement VPatternRecipe::PointOfIntersectionCircles(const VToolRecord &record)
915 {
916 auto *tool = GetPatternTool<VToolPointOfIntersectionCircles>(record.getId());
917
918 QDomElement step = createElement(TagStep);
919
920 ToolAttributes(step, tool);
921 SetAttribute(step, AttrC1Center, tool->FirstCircleCenterPointName());
922 SetAttribute(step, AttrC2Center, tool->SecondCircleCenterPointName());
923 Formula(step, tool->GetFirstCircleRadius(), AttrC1Radius, AttrC1RadiusValue);
924 Formula(step, tool->GetSecondCircleRadius(), AttrC2Radius, AttrC2RadiusValue);
925 SetAttribute(step, AttrCrossPoint, static_cast<int>(tool->GetCrossCirclesPoint()));
926
927 return step;
928 }
929
930 //---------------------------------------------------------------------------------------------------------------------
PointOfIntersectionCurves(const VToolRecord & record)931 QDomElement VPatternRecipe::PointOfIntersectionCurves(const VToolRecord &record)
932 {
933 auto *tool = GetPatternTool<VToolPointOfIntersectionCurves>(record.getId());
934
935 QDomElement step = createElement(TagStep);
936
937 ToolAttributes(step, tool);
938 SetAttribute(step, AttrCurve1, tool->FirstCurveName());
939 SetAttribute(step, AttrCurve2, tool->SecondCurveName());
940 SetAttribute(step, AttrVCrossPoint, static_cast<int>(tool->GetVCrossPoint()));
941 SetAttribute(step, AttrHCrossPoint, static_cast<int>(tool->GetHCrossPoint()));
942
943 return step;
944 }
945
946 //---------------------------------------------------------------------------------------------------------------------
PointFromCircleAndTangent(const VToolRecord & record)947 QDomElement VPatternRecipe::PointFromCircleAndTangent(const VToolRecord &record)
948 {
949 auto *tool = GetPatternTool<VToolPointFromCircleAndTangent>(record.getId());
950
951 QDomElement step = createElement(TagStep);
952
953 ToolAttributes(step, tool);
954 SetAttribute(step, AttrCCenter, tool->CircleCenterPointName());
955 SetAttribute(step, AttrTangent, tool->TangentPointName());
956 Formula(step, tool->GetCircleRadius(), AttrCRadius, AttrCRadiusValue);
957 SetAttribute(step, AttrCrossPoint, static_cast<int>(tool->GetCrossCirclesPoint()));
958
959 return step;
960 }
961
962 //---------------------------------------------------------------------------------------------------------------------
PointFromArcAndTangent(const VToolRecord & record)963 QDomElement VPatternRecipe::PointFromArcAndTangent(const VToolRecord &record)
964 {
965 auto *tool = GetPatternTool<VToolPointFromArcAndTangent>(record.getId());
966
967 QDomElement step = createElement(TagStep);
968
969 ToolAttributes(step, tool);
970 SetAttribute(step, AttrArc, tool->ArcName());
971 SetAttribute(step, AttrTangent, tool->TangentPointName());
972 SetAttribute(step, AttrCrossPoint, static_cast<int>(tool->GetCrossCirclesPoint()));
973
974 return step;
975 }
976
977 //---------------------------------------------------------------------------------------------------------------------
TrueDarts(const VToolRecord & record)978 QDomElement VPatternRecipe::TrueDarts(const VToolRecord &record)
979 {
980 auto *tool = GetPatternTool<VToolTrueDarts>(record.getId());
981
982 QDomElement step = createElement(TagStep);
983
984 SetAttribute(step, AttrType, VToolTrueDarts::ToolType);
985 SetAttribute(step, AttrPoint1, tool->nameP1());
986 SetAttribute(step, AttrPoint2, tool->nameP2());
987 SetAttribute(step, AttrBaseLineP1, tool->BaseLineP1Name());
988 SetAttribute(step, AttrBaseLineP2, tool->BaseLineP2Name());
989 SetAttribute(step, AttrDartP1, tool->DartP1Name());
990 SetAttribute(step, AttrDartP2, tool->DartP2Name());
991 SetAttribute(step, AttrDartP3, tool->DartP3Name());
992
993 return step;
994 }
995
996 //---------------------------------------------------------------------------------------------------------------------
EllipticalArc(const VToolRecord & record)997 QDomElement VPatternRecipe::EllipticalArc(const VToolRecord &record)
998 {
999 auto *tool = GetPatternTool<VToolEllipticalArc>(record.getId());
1000
1001 QDomElement step = createElement(TagStep);
1002
1003 SetAttribute(step, AttrType, QStringLiteral("ellipticalArc"));
1004 SetAttribute(step, AttrLabel, tool->name());
1005
1006 SetAttribute(step, AttrCenter, tool->CenterPointName());
1007 Formula(step, tool->GetFormulaRadius1(), AttrRadius1, AttrRadius1Value);
1008 Formula(step, tool->GetFormulaRadius2(), AttrRadius2, AttrRadius2Value);
1009 Formula(step, tool->GetFormulaF1(), AttrAngle1, AttrAngle1Value);
1010 Formula(step, tool->GetFormulaF2(), AttrAngle2, AttrAngle2Value);
1011 Formula(step, tool->GetFormulaRotationAngle(), AttrRotationAngle, AttrRotationAngleValue);
1012
1013 CurveAttributes(step, tool);
1014
1015 return step;
1016 }
1017
1018 //---------------------------------------------------------------------------------------------------------------------
Rotation(const VToolRecord & record,const VContainer & data)1019 QDomElement VPatternRecipe::Rotation(const VToolRecord &record, const VContainer &data)
1020 {
1021 auto *tool = GetPatternTool<VToolRotation>(record.getId());
1022
1023 QDomElement step = createElement(TagStep);
1024
1025 SetAttribute(step, AttrType, VToolRotation::ToolType);
1026 SetAttribute(step, AttrCenter, tool->OriginPointName());
1027 Formula(step, tool->GetFormulaAngle(), AttrAngle, AttrAngleValue);
1028 SetAttribute(step, AttrSuffix, tool->Suffix());
1029
1030 step.appendChild(GroupOperationSource(tool, record.getId(), data));
1031
1032 return step;
1033 }
1034
1035 //---------------------------------------------------------------------------------------------------------------------
FlippingByLine(const VToolRecord & record,const VContainer & data)1036 QDomElement VPatternRecipe::FlippingByLine(const VToolRecord &record, const VContainer &data)
1037 {
1038 auto *tool = GetPatternTool<VToolFlippingByLine>(record.getId());
1039
1040 QDomElement step = createElement(TagStep);
1041
1042 SetAttribute(step, AttrType, VToolFlippingByLine::ToolType);
1043 SetAttribute(step, AttrP1Line, tool->FirstLinePointName());
1044 SetAttribute(step, AttrP2Line, tool->SecondLinePointName());
1045 SetAttribute(step, AttrSuffix, tool->Suffix());
1046
1047 step.appendChild(GroupOperationSource(tool, record.getId(), data));
1048
1049 return step;
1050 }
1051
1052 //---------------------------------------------------------------------------------------------------------------------
FlippingByAxis(const VToolRecord & record,const VContainer & data)1053 QDomElement VPatternRecipe::FlippingByAxis(const VToolRecord &record, const VContainer &data)
1054 {
1055 auto *tool = GetPatternTool<VToolFlippingByAxis>(record.getId());
1056
1057 QDomElement step = createElement(TagStep);
1058
1059 SetAttribute(step, AttrType, VToolFlippingByAxis::ToolType);
1060 SetAttribute(step, AttrCenter, tool->OriginPointName());
1061 SetAttribute(step, AttrAxisType, static_cast<int>(tool->GetAxisType()));
1062 SetAttribute(step, AttrSuffix, tool->Suffix());
1063
1064 step.appendChild(GroupOperationSource(tool, record.getId(), data));
1065
1066 return step;
1067 }
1068
1069 //---------------------------------------------------------------------------------------------------------------------
Move(const VToolRecord & record,const VContainer & data)1070 QDomElement VPatternRecipe::Move(const VToolRecord &record, const VContainer &data)
1071 {
1072 auto *tool = GetPatternTool<VToolMove>(record.getId());
1073
1074 QDomElement step = createElement(TagStep);
1075
1076 SetAttribute(step, AttrType, VToolMove::ToolType);
1077 Formula(step, tool->GetFormulaAngle(), AttrAngle, AttrAngleValue);
1078 Formula(step, tool->GetFormulaRotationAngle(), AttrRotationAngle, AttrRotationAngleValue);
1079 Formula(step, tool->GetFormulaLength(), AttrLength, AttrLengthValue);
1080 SetAttribute(step, AttrCenter, tool->OriginPointName());
1081 SetAttribute(step, AttrSuffix, tool->Suffix());
1082
1083 step.appendChild(GroupOperationSource(tool, record.getId(), data));
1084
1085 return step;
1086 }
1087
1088 //---------------------------------------------------------------------------------------------------------------------
Formula(QDomElement & step,const VFormula & formula,const QString & formulaStr,const QString & formulaValue)1089 inline void VPatternRecipe::Formula(QDomElement &step, const VFormula &formula, const QString &formulaStr,
1090 const QString &formulaValue)
1091 {
1092 if (formula.error())
1093 {
1094 throw VExceptionInvalidHistory(QObject::tr("Invalid formula '%1' for tool with id '%2'. %3.")
1095 .arg(formula.GetFormula(FormulaType::ToSystem))
1096 .arg(formula.getToolId())
1097 .arg(formula.Reason()));
1098 }
1099
1100 SetAttribute(step, formulaStr, formula.GetFormula(FormulaType::ToSystem));
1101 SetAttribute(step, formulaValue, formula.getDoubleValue());
1102 }
1103
1104 //---------------------------------------------------------------------------------------------------------------------
1105 template<typename T>
LineAttributes(QDomElement & step,T * tool)1106 inline void VPatternRecipe::LineAttributes(QDomElement &step, T *tool)
1107 {
1108 SetAttribute(step, AttrLineColor, tool->GetLineColor());
1109 SetAttribute(step, AttrTypeLine, tool->getLineType());
1110 }
1111
1112 //---------------------------------------------------------------------------------------------------------------------
1113 template<typename T>
CurveAttributes(QDomElement & step,T * tool)1114 void VPatternRecipe::CurveAttributes(QDomElement &step, T *tool)
1115 {
1116 SetAttribute(step, AttrLineColor, tool->GetLineColor());
1117 SetAttribute(step, AttrPenStyle, tool->GetPenStyle());
1118 SetAttribute(step, AttrAScale, tool->GetApproximationScale());
1119 SetAttribute(step, AttrDuplicate, tool->GetDuplicate());
1120 SetAttributeOrRemoveIf(step, AttrAlias, tool->GetAliasSuffix(), tool->GetAliasSuffix().isEmpty());
1121 }
1122
1123
1124 //---------------------------------------------------------------------------------------------------------------------
1125 template<typename T>
CutCurveAttributes(QDomElement & step,T * tool)1126 void VPatternRecipe::CutCurveAttributes(QDomElement &step, T *tool)
1127 {
1128 SetAttributeOrRemoveIf(step, AttrAlias1, tool->GetAliasSuffix1(), tool->GetAliasSuffix1().isEmpty());
1129 SetAttributeOrRemoveIf(step, AttrAlias2, tool->GetAliasSuffix2(), tool->GetAliasSuffix2().isEmpty());
1130 }
1131
1132 //---------------------------------------------------------------------------------------------------------------------
1133 template<typename T>
ToolAttributes(QDomElement & step,T * tool)1134 inline void VPatternRecipe::ToolAttributes(QDomElement &step, T *tool)
1135 {
1136 SetAttribute(step, AttrType, T::ToolType);
1137 SetAttribute(step, AttrLabel, tool->name());
1138 SetAttribute(step, AttrNotes, tool->GetNotes());
1139 }
1140
1141 //---------------------------------------------------------------------------------------------------------------------
GroupOperationSource(VAbstractOperation * tool,quint32 id,const VContainer & data)1142 QDomElement VPatternRecipe::GroupOperationSource(VAbstractOperation *tool, quint32 id, const VContainer &data)
1143 {
1144 SCASSERT(tool)
1145
1146 QDomElement nodes = createElement(QStringLiteral("nodes"));
1147 QVector<SourceItem> items = tool->SourceItems();
1148
1149 if (items.isEmpty())
1150 {
1151 throw VExceptionInvalidHistory(QObject::tr("Empty list of nodes for tool with id '%1'.").arg(id));
1152 }
1153
1154 for (auto &item : items)
1155 {
1156 QDomElement node = createElement(QStringLiteral("node"));
1157
1158 QSharedPointer<VGObject> obj;
1159
1160 try
1161 {
1162 obj = data.GetGObject(item.id);
1163 }
1164 catch (const VExceptionBadId &e)
1165 {
1166 qCritical() << e.ErrorMessage()<<Q_FUNC_INFO;
1167 continue;
1168 }
1169
1170 SetAttribute(node, AttrItem, obj->ObjectName());
1171 SetAttributeOrRemoveIf(node, AttrAlias, item.alias, item.alias.isEmpty());
1172
1173 if (obj->getType() != GOType::Point)
1174 {
1175 if (item.penStyle != TypeLineDefault)
1176 {
1177 SetAttribute(node, AttrPenStyle, item.penStyle);
1178 }
1179
1180 if (item.color != ColorDefault)
1181 {
1182 SetAttribute(node, AttrColor, item.color);
1183 }
1184 }
1185
1186 QT_WARNING_PUSH
1187 QT_WARNING_DISABLE_GCC("-Wswitch-default")
1188 switch(static_cast<GOType>(obj->getType()))
1189 {
1190 case GOType::Point:
1191 SetAttribute(node, AttrType, QStringLiteral("point"));
1192 break;
1193 case GOType::Arc:
1194 SetAttribute(node, AttrType, QStringLiteral("arc"));
1195 break;
1196 case GOType::EllipticalArc:
1197 SetAttribute(node, AttrType, QStringLiteral("elArc"));
1198 break;
1199 case GOType::Spline:
1200 case GOType::CubicBezier:
1201 SetAttribute(node, AttrType, QStringLiteral("spline"));
1202 break;
1203 case GOType::SplinePath:
1204 case GOType::CubicBezierPath:
1205 SetAttribute(node, AttrType, QStringLiteral("splinePath"));
1206 break;
1207 case GOType::Unknown:
1208 case GOType::PlaceLabel:
1209 Q_UNREACHABLE();
1210 break;
1211 }
1212 QT_WARNING_POP
1213
1214 nodes.appendChild(node);
1215 }
1216
1217 return nodes;
1218 }
1219