1 /************************************************************************
2 **
3 ** @file vabstractpattern.cpp
4 ** @author Roman Telezhynskyi <dismine(at)gmail.com>
5 ** @date 15 6, 2015
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) 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 "vabstractpattern.h"
30
31 #include <QDomNode>
32 #include <QDomNodeList>
33 #include <QLatin1String>
34 #include <QList>
35 #include <QMessageLogger>
36 #include <QSet>
37 #include <QStaticStringData>
38 #include <QStringData>
39 #include <QStringDataPtr>
40 #include <QtDebug>
41 #include <QtConcurrentMap>
42 #include <QFuture>
43 #include <QtConcurrentRun>
44
45 #include "../exception/vexceptionemptyparameter.h"
46 #include "../exception/vexceptionobjecterror.h"
47 #include "../exception/vexceptionconversionerror.h"
48 #include "../qmuparser/qmutokenparser.h"
49 #include "../ifc/exception/vexceptionbadid.h"
50 #include "../ifc/ifcdef.h"
51 #include "../vpatterndb/vcontainer.h"
52 #include "../vpatterndb/vpiecenode.h"
53 #include "../vtools/tools/vdatatool.h"
54 #include "vpatternconverter.h"
55 #include "vdomdocument.h"
56 #include "vtoolrecord.h"
57 #include "../vmisc/vabstractvalapplication.h"
58 #include "../vmisc/compatibility.h"
59 #include "../vlayout/vtextmanager.h"
60
61 class QDomElement;
62
63 const QString VAbstractPattern::TagPattern = QStringLiteral("pattern");
64 const QString VAbstractPattern::TagCalculation = QStringLiteral("calculation");
65 const QString VAbstractPattern::TagModeling = QStringLiteral("modeling");
66 const QString VAbstractPattern::TagDetails = QStringLiteral("details");
67 const QString VAbstractPattern::TagDetail = QStringLiteral("detail");
68 const QString VAbstractPattern::TagDescription = QStringLiteral("description");
69 const QString VAbstractPattern::TagNotes = QStringLiteral("notes");
70 const QString VAbstractPattern::TagImage = QStringLiteral("image");
71 const QString VAbstractPattern::TagMeasurements = QStringLiteral("measurements");
72 const QString VAbstractPattern::TagIncrements = QStringLiteral("increments");
73 const QString VAbstractPattern::TagPreviewCalculations = QStringLiteral("previewCalculations");
74 const QString VAbstractPattern::TagIncrement = QStringLiteral("increment");
75 const QString VAbstractPattern::TagDraw = QStringLiteral("draw");
76 const QString VAbstractPattern::TagGroups = QStringLiteral("groups");
77 const QString VAbstractPattern::TagGroup = QStringLiteral("group");
78 const QString VAbstractPattern::TagGroupItem = QStringLiteral("item");
79 const QString VAbstractPattern::TagPoint = QStringLiteral("point");
80 const QString VAbstractPattern::TagSpline = QStringLiteral("spline");
81 const QString VAbstractPattern::TagArc = QStringLiteral("arc");
82 const QString VAbstractPattern::TagElArc = QStringLiteral("elArc");
83 const QString VAbstractPattern::TagTools = QStringLiteral("tools");
84 const QString VAbstractPattern::TagOperation = QStringLiteral("operation");
85 const QString VAbstractPattern::TagData = QStringLiteral("data");
86 const QString VAbstractPattern::TagPatternInfo = QStringLiteral("patternInfo");
87 const QString VAbstractPattern::TagPatternName = QStringLiteral("patternName");
88 const QString VAbstractPattern::TagPatternNum = QStringLiteral("patternNumber");
89 const QString VAbstractPattern::TagCustomerName = QStringLiteral("customer");
90 const QString VAbstractPattern::TagCustomerBirthDate = QStringLiteral("birthDate");
91 const QString VAbstractPattern::TagCustomerEmail = QStringLiteral("email");
92 const QString VAbstractPattern::TagCompanyName = QStringLiteral("company");
93 const QString VAbstractPattern::TagPatternLabel = QStringLiteral("patternLabel");
94 const QString VAbstractPattern::TagWatermark = QStringLiteral("watermark");
95 const QString VAbstractPattern::TagPatternMaterials = QStringLiteral("patternMaterials");
96 const QString VAbstractPattern::TagFinalMeasurements= QStringLiteral("finalMeasurements");
97 const QString VAbstractPattern::TagMaterial = QStringLiteral("material");
98 const QString VAbstractPattern::TagFMeasurement = QStringLiteral("finalMeasurment");
99 const QString VAbstractPattern::TagGrainline = QStringLiteral("grainline");
100 const QString VAbstractPattern::TagPath = QStringLiteral("path");
101 const QString VAbstractPattern::TagNodes = QStringLiteral("nodes");
102 const QString VAbstractPattern::TagNode = QStringLiteral("node");
103
104 const QString VAbstractPattern::AttrName = QStringLiteral("name");
105 const QString VAbstractPattern::AttrVisible = QStringLiteral("visible");
106 const QString VAbstractPattern::AttrObject = QStringLiteral("object");
107 const QString VAbstractPattern::AttrTool = QStringLiteral("tool");
108 const QString VAbstractPattern::AttrType = QStringLiteral("type");
109 const QString VAbstractPattern::AttrLetter = QStringLiteral("letter");
110 const QString VAbstractPattern::AttrAnnotation = QStringLiteral("annotation");
111 const QString VAbstractPattern::AttrOrientation = QStringLiteral("orientation");
112 const QString VAbstractPattern::AttrRotationWay = QStringLiteral("rotationWay");
113 const QString VAbstractPattern::AttrTilt = QStringLiteral("tilt");
114 const QString VAbstractPattern::AttrFoldPosition = QStringLiteral("foldPosition");
115 const QString VAbstractPattern::AttrQuantity = QStringLiteral("quantity");
116 const QString VAbstractPattern::AttrOnFold = QStringLiteral("onFold");
117 const QString VAbstractPattern::AttrDateFormat = QStringLiteral("dateFormat");
118 const QString VAbstractPattern::AttrTimeFormat = QStringLiteral("timeFormat");
119 const QString VAbstractPattern::AttrArrows = QStringLiteral("arrows");
120 const QString VAbstractPattern::AttrNodeReverse = QStringLiteral("reverse");
121 const QString VAbstractPattern::AttrNodeExcluded = QStringLiteral("excluded");
122 const QString VAbstractPattern::AttrNodePassmark = QStringLiteral("passmark");
123 const QString VAbstractPattern::AttrNodePassmarkLine = QStringLiteral("passmarkLine");
124 const QString VAbstractPattern::AttrNodePassmarkAngle = QStringLiteral("passmarkAngle");
125 const QString VAbstractPattern::AttrNodeShowSecondPassmark = QStringLiteral("showSecondPassmark");
126 const QString VAbstractPattern::AttrSABefore = QStringLiteral("before");
127 const QString VAbstractPattern::AttrSAAfter = QStringLiteral("after");
128 const QString VAbstractPattern::AttrStart = QStringLiteral("start");
129 const QString VAbstractPattern::AttrPath = QStringLiteral("path");
130 const QString VAbstractPattern::AttrEnd = QStringLiteral("end");
131 const QString VAbstractPattern::AttrIncludeAs = QStringLiteral("includeAs");
132 const QString VAbstractPattern::AttrRotation = QStringLiteral("rotation");
133 const QString VAbstractPattern::AttrNumber = QStringLiteral("number");
134 const QString VAbstractPattern::AttrCheckUniqueness = QStringLiteral("checkUniqueness");
135 const QString VAbstractPattern::AttrManualPassmarkLength = QStringLiteral("manualPassmarkLength");
136 const QString VAbstractPattern::AttrPassmarkLength = QStringLiteral("passmarkLength");
137 const QString VAbstractPattern::AttrOpacity = QStringLiteral("opacity");
138 const QString VAbstractPattern::AttrTags = QStringLiteral("tags");
139
140 const QString VAbstractPattern::AttrExtension = QStringLiteral("extension");
141
142 const QString VAbstractPattern::AttrFormula = QStringLiteral("formula");
143 const QString VAbstractPattern::AttrDescription = QStringLiteral("description");
144
145 const QString VAbstractPattern::NodeArc = QStringLiteral("NodeArc");
146 const QString VAbstractPattern::NodeElArc = QStringLiteral("NodeElArc");
147 const QString VAbstractPattern::NodePoint = QStringLiteral("NodePoint");
148 const QString VAbstractPattern::NodeSpline = QStringLiteral("NodeSpline");
149 const QString VAbstractPattern::NodeSplinePath = QStringLiteral("NodeSplinePath");
150
151 QHash<quint32, VDataTool*> VAbstractPattern::tools = QHash<quint32, VDataTool*>();
152 QVector<VLabelTemplateLine> VAbstractPattern::patternLabelLines = QVector<VLabelTemplateLine>();
153 QMap<int, QString> VAbstractPattern::patternMaterials = QMap<int, QString>();
154 bool VAbstractPattern::patternLabelWasChanged = false;
155
156 namespace
157 {
ReadExpressionAttribute(QVector<VFormulaField> & expressions,const QDomElement & element,const QString & attribute)158 void ReadExpressionAttribute(QVector<VFormulaField> &expressions, const QDomElement &element, const QString &attribute)
159 {
160 VFormulaField formula;
161 formula.expression = VDomDocument::GetParametrEmptyString(element, attribute);
162
163 if (formula.expression.isEmpty())
164 {
165 return;
166 }
167
168 formula.element = element;
169 formula.attribute = attribute;
170
171 expressions.append(formula);
172 }
173
174 //---------------------------------------------------------------------------------------------------------------------
GetTokens(const VFormulaField & formula)175 QList<QString> GetTokens(const VFormulaField &formula)
176 {
177 try
178 {
179 QScopedPointer<qmu::QmuTokenParser> cal(new qmu::QmuTokenParser(formula.expression, false, false));
180 return cal->GetTokens().values();
181 }
182 catch (const qmu::QmuParserError &e)
183 {
184 qWarning() << QObject::tr("Cannot get tokens from formula '%1'. Parser error: %2.")
185 .arg(formula.expression, e.GetMsg());
186 return QList<QString>();
187 }
188 catch (const qmu::QmuParserWarning &e)
189 {
190 qWarning() << QObject::tr("Cannot get tokens from formula '%1'. Formula error: %2.")
191 .arg(formula.expression, e.GetMsg());
192 return QList<QString>();
193 }
194 }
195
196 //---------------------------------------------------------------------------------------------------------------------
GatherTokens(QSet<QString> & tokens,const QList<QString> & tokenList)197 void GatherTokens(QSet<QString> &tokens, const QList<QString> &tokenList)
198 {
199 tokens = tokens.unite(ConvertToSet(tokenList));
200 }
201
202 //---------------------------------------------------------------------------------------------------------------------
203 /**
204 * @brief AdjustMaterials help function that combine user materials from pattern and cli.
205 * @param materials materials from pattern
206 * @return combined list
207 */
AdjustMaterials(QMap<int,QString> materials)208 QMap<int, QString> AdjustMaterials(QMap<int, QString> materials)
209 {
210 const QMap<int, QString> cliMaterials = VAbstractValApplication::VApp()->GetUserMaterials();
211 QMap<int, QString>::const_iterator i = cliMaterials.constBegin();
212 while (i != cliMaterials.constEnd())
213 {
214 if (not materials.contains(i.key()))
215 {
216 qWarning() << QObject::tr("User material number %1 was not defined in this pattern.").arg(i.key());
217 }
218
219 materials.insert(i.key(), i.value());
220 ++i;
221 }
222
223 return materials;
224 }
225
226 //---------------------------------------------------------------------------------------------------------------------
PrepareGroupTags(QStringList tags)227 QString PrepareGroupTags(QStringList tags)
228 {
229 for (auto &tag : tags)
230 {
231 tag = tag.simplified();
232 }
233
234 return ConvertToList(ConvertToSet<QString>(tags)).join(',');
235 }
236 }
237
238 //---------------------------------------------------------------------------------------------------------------------
VAbstractPattern(QObject * parent)239 VAbstractPattern::VAbstractPattern(QObject *parent)
240 : VDomDocument(parent),
241 nameActivPP(),
242 cursor(0),
243 toolsOnRemove(QVector<VDataTool*>()),
244 history(QVector<VToolRecord>()),
245 patternPieces(),
246 modified(false)
247 {}
248
249 //---------------------------------------------------------------------------------------------------------------------
~VAbstractPattern()250 VAbstractPattern::~VAbstractPattern()
251 {
252 qDeleteAll(toolsOnRemove);
253 toolsOnRemove.clear();
254 }
255
256 //---------------------------------------------------------------------------------------------------------------------
RequiresMeasurements() const257 bool VAbstractPattern::RequiresMeasurements() const
258 {
259 return not ListMeasurements().isEmpty();
260 }
261
262 //---------------------------------------------------------------------------------------------------------------------
ListMeasurements() const263 QStringList VAbstractPattern::ListMeasurements() const
264 {
265 const QFuture<QStringList> futureIncrements = QtConcurrent::run(this, &VAbstractPattern::ListIncrements);
266 const QList<QString> tokens = ConvertToList(QtConcurrent::blockingMappedReduced(ListExpressions(), GetTokens,
267 GatherTokens));
268
269 QSet<QString> measurements;
270 QSet<QString> others = ConvertToSet<QString>(futureIncrements.result());
271
272 for (const auto &token : tokens)
273 {
274 if (token == QChar('-') || measurements.contains(token) || others.contains(token))
275 {
276 continue;
277 }
278
279 IsVariable(token) || IsFunction(token) ? others.insert(token) : measurements.insert(token);
280 }
281
282 return QStringList(measurements.values());
283 }
284
285 //---------------------------------------------------------------------------------------------------------------------
286 /**
287 * @brief ChangeActivPP set new active pattern piece name.
288 * @param name new name.
289 * @param parse parser file mode.
290 */
ChangeActivPP(const QString & name,const Document & parse)291 void VAbstractPattern::ChangeActivPP(const QString &name, const Document &parse)
292 {
293 Q_ASSERT_X(not name.isEmpty(), Q_FUNC_INFO, "name pattern piece is empty");
294 if (CheckExistNamePP(name))
295 {
296 this->nameActivPP = name;
297 if (parse == Document::FullParse)
298 {
299 emit ChangedActivPP(name);
300 }
301 }
302 }
303
304 //---------------------------------------------------------------------------------------------------------------------
305 /**
306 * @brief GetActivDrawElement return draw tag for current pattern peace.
307 * @param element draw tag.
308 * @return true if found.
309 */
GetActivDrawElement(QDomElement & element) const310 bool VAbstractPattern::GetActivDrawElement(QDomElement &element) const
311 {
312 if (nameActivPP.isEmpty() == false)
313 {
314 const QDomNodeList elements = this->documentElement().elementsByTagName( TagDraw );
315 if (elements.size() == 0)
316 {
317 return false;
318 }
319 for ( qint32 i = 0; i < elements.count(); i++ )
320 {
321 element = elements.at( i ).toElement();
322 if (element.isNull() == false)
323 {
324 const QString fieldName = element.attribute( AttrName );
325 if ( fieldName == nameActivPP )
326 {
327 return true;
328 }
329 }
330 }
331 element = QDomElement();
332 }
333 return false;
334 }
335
336 //---------------------------------------------------------------------------------------------------------------------
getLocalHistory(const QString & draw) const337 QVector<VToolRecord> VAbstractPattern::getLocalHistory(const QString &draw) const
338 {
339 QVector<VToolRecord> historyPP;
340 for (qint32 i = 0; i< history.size(); ++i)
341 {
342 const VToolRecord &tool = history.at(i);
343 if (tool.getNameDraw() == draw)
344 {
345 historyPP.append(tool);
346 }
347 }
348 return historyPP;
349 }
350
351 //---------------------------------------------------------------------------------------------------------------------
352 /**
353 * @brief CheckNameDraw check if exist pattern peace with this name.
354 * @param name pattern peace name.
355 * @return true if exist.
356 */
CheckExistNamePP(const QString & name) const357 bool VAbstractPattern::CheckExistNamePP(const QString &name) const
358 {
359 Q_ASSERT_X(not name.isEmpty(), Q_FUNC_INFO, "name draw is empty");
360 const QDomNodeList elements = this->documentElement().elementsByTagName( TagDraw );
361 if (elements.size() == 0)
362 {
363 return false;
364 }
365 for ( qint32 i = 0; i < elements.count(); i++ )
366 {
367 const QDomElement elem = elements.at( i ).toElement();
368 if (elem.isNull() == false)
369 {
370 if ( GetParametrString(elem, AttrName) == name )
371 {
372 return true;
373 }
374 }
375 }
376 return false;
377 }
378
379 //---------------------------------------------------------------------------------------------------------------------
380 /**
381 * @brief GetActivNodeElement find element in current pattern piece by name.
382 * @param name name tag.
383 * @param element element.
384 * @return true if found.
385 */
GetActivNodeElement(const QString & name,QDomElement & element) const386 bool VAbstractPattern::GetActivNodeElement(const QString &name, QDomElement &element) const
387 {
388 Q_ASSERT_X(not name.isEmpty(), Q_FUNC_INFO, "name draw is empty");
389 QDomElement drawElement;
390 if (GetActivDrawElement(drawElement))
391 {
392 const QDomNodeList listElement = drawElement.elementsByTagName(name);
393 if (listElement.size() != 1)
394 {
395 return false;
396 }
397 element = listElement.at( 0 ).toElement();
398 if (element.isNull() == false)
399 {
400 return true;
401 }
402 else
403 {
404 return false;
405 }
406 }
407 return false;
408 }
409
410 //---------------------------------------------------------------------------------------------------------------------
ParseGroups(const QDomElement & domElement)411 void VAbstractPattern::ParseGroups(const QDomElement &domElement)
412 {
413 Q_ASSERT_X(not domElement.isNull(), Q_FUNC_INFO, "domElement is null");
414
415 QMap<quint32, quint32> itemTool;
416 QMap<quint32, bool> itemVisibility;
417
418 QDomNode domNode = domElement.firstChild();
419 while (domNode.isNull() == false)
420 {
421 if (domNode.isElement())
422 {
423 const QDomElement domElement = domNode.toElement();
424 if (domElement.isNull() == false)
425 {
426 if (domElement.tagName() == TagGroup)
427 {
428 VContainer::UpdateId(GetParametrUInt(domElement, AttrId, NULL_ID_STR), valentinaNamespace);
429
430 const QPair<bool, QMap<quint32, quint32> > groupData = ParseItemElement(domElement);
431 const QMap<quint32, quint32> group = groupData.second;
432 auto i = group.constBegin();
433 while (i != group.constEnd())
434 {
435 if (not itemTool.contains(i.key()))
436 {
437 itemTool.insert(i.key(), i.value());
438 }
439
440 const bool previous = itemVisibility.value(i.key(), false);
441 itemVisibility.insert(i.key(), previous || groupData.first);
442 ++i;
443 }
444 }
445 }
446 }
447 domNode = domNode.nextSibling();
448 }
449
450 auto i = itemTool.constBegin();
451 while (i != itemTool.constEnd())
452 {
453 if (tools.contains(i.value()))
454 {
455 VDataTool* tool = tools.value(i.value());
456 tool->GroupVisibility(i.key(), itemVisibility.value(i.key(), true));
457 }
458 ++i;
459 }
460 }
461
462 //---------------------------------------------------------------------------------------------------------------------
CountPP() const463 int VAbstractPattern::CountPP() const
464 {
465 const QDomElement rootElement = this->documentElement();
466 if (rootElement.isNull())
467 {
468 return 0;
469 }
470
471 return rootElement.elementsByTagName( TagDraw ).count();
472 }
473
474 //---------------------------------------------------------------------------------------------------------------------
GetPPElement(const QString & name)475 QDomElement VAbstractPattern::GetPPElement(const QString &name)
476 {
477 if (name.isEmpty() == false)
478 {
479 const QDomNodeList elements = this->documentElement().elementsByTagName( TagDraw );
480 if (elements.size() == 0)
481 {
482 return QDomElement();
483 }
484 for ( qint32 i = 0; i < elements.count(); i++ )
485 {
486 QDomElement element = elements.at( i ).toElement();
487 if (element.isNull() == false)
488 {
489 if ( element.attribute( AttrName ) == name )
490 {
491 return element;
492 }
493 }
494 }
495 }
496 return QDomElement();
497 }
498
499 //---------------------------------------------------------------------------------------------------------------------
500 /**
501 * @brief ChangeNamePP change pattern piece name.
502 * @param oldName old pattern piece name.
503 * @param newName new pattern piece name.
504 * @return true if success.
505 */
ChangeNamePP(const QString & oldName,const QString & newName)506 bool VAbstractPattern::ChangeNamePP(const QString &oldName, const QString &newName)
507 {
508 Q_ASSERT_X(not newName.isEmpty(), Q_FUNC_INFO, "new name pattern piece is empty");
509 Q_ASSERT_X(not oldName.isEmpty(), Q_FUNC_INFO, "old name pattern piece is empty");
510
511 if (CheckExistNamePP(oldName) == false)
512 {
513 qDebug()<<"Do not exist pattern piece with name"<<oldName;
514 return false;
515 }
516
517 if (CheckExistNamePP(newName))
518 {
519 qDebug()<<"Already exist pattern piece with name"<<newName;
520 return false;
521 }
522
523 QDomElement ppElement = GetPPElement(oldName);
524 if (ppElement.isElement())
525 {
526 if (nameActivPP == oldName)
527 {
528 nameActivPP = newName;
529 }
530 ppElement.setAttribute(AttrName, newName);
531 emit patternChanged(false);//For situation when we change name directly, without undocommands.
532 emit ChangedNameDraw(oldName, newName);
533 return true;
534 }
535 else
536 {
537 qDebug()<<"Can't find pattern piece node with name"<<oldName<<Q_FUNC_INFO;
538 return false;
539 }
540 }
541
542 //---------------------------------------------------------------------------------------------------------------------
543 /**
544 * @brief appendPP add new pattern piece.
545 *
546 * Method check if not exist pattern piece with the same name and change name active pattern piece name, send signal
547 * about change pattern piece. Doen't add pattern piece to file structure. This task make SPoint tool.
548 * @param name pattern peace name.
549 * @return true if success.
550 */
appendPP(const QString & name)551 bool VAbstractPattern::appendPP(const QString &name)
552 {
553 Q_ASSERT_X(not name.isEmpty(), Q_FUNC_INFO, "name pattern piece is empty");
554 if (name.isEmpty())
555 {
556 return false;
557 }
558 if (CheckExistNamePP(name) == false)
559 {
560 SetActivPP(name);
561 return true;
562 }
563 return false;
564 }
565
566 //---------------------------------------------------------------------------------------------------------------------
getCursor() const567 quint32 VAbstractPattern::getCursor() const
568 {
569 return cursor;
570 }
571
572 //---------------------------------------------------------------------------------------------------------------------
setCursor(const quint32 & value)573 void VAbstractPattern::setCursor(const quint32 &value)
574 {
575 if (cursor != value)
576 {
577 cursor = value;
578 emit ChangedCursor(cursor);
579 }
580 }
581
582 //---------------------------------------------------------------------------------------------------------------------
setXMLContent(const QString & fileName)583 void VAbstractPattern::setXMLContent(const QString &fileName)
584 {
585 Clear();
586 VDomDocument::setXMLContent(fileName);
587 m_patternNumber = ReadPatternNumber();
588 m_labelDateFormat = ReadLabelDateFormat();
589 m_patternName = ReadPatternName();
590 m_MPath = ReadMPath();
591 m_watermarkPath = ReadWatermarkPath();
592 m_companyName = ReadCompanyName();
593 m_units = ReadUnits();
594 }
595
596 //---------------------------------------------------------------------------------------------------------------------
Clear()597 void VAbstractPattern::Clear()
598 {
599 clear();
600 m_patternNumber.clear();
601 m_labelDateFormat.clear();
602 m_patternName.clear();
603 m_MPath.clear();
604 m_watermarkPath.clear();
605 m_companyName.clear();
606 m_units = Unit::LAST_UNIT_DO_NOT_USE;
607 modified = false;
608 }
609
610 //---------------------------------------------------------------------------------------------------------------------
611 /**
612 * @brief getTool return tool from tool list.
613 * @param id tool id.
614 * @return tool.
615 */
getTool(quint32 id)616 VDataTool *VAbstractPattern::getTool(quint32 id)
617 {
618 ToolExists(id);
619 return tools.value(id);
620 }
621
622 //---------------------------------------------------------------------------------------------------------------------
623 /**
624 * @brief AddTool add tool to list tools.
625 * @param id tool id.
626 * @param tool tool.
627 */
AddTool(quint32 id,VDataTool * tool)628 void VAbstractPattern::AddTool(quint32 id, VDataTool *tool)
629 {
630 Q_ASSERT_X(id != 0, Q_FUNC_INFO, "id == 0");
631 SCASSERT(tool != nullptr)
632 tools.insert(id, tool);
633 }
634
635 //---------------------------------------------------------------------------------------------------------------------
RemoveTool(quint32 id)636 void VAbstractPattern::RemoveTool(quint32 id)
637 {
638 tools.remove(id);
639 }
640
641 //---------------------------------------------------------------------------------------------------------------------
ParsePieceNodes(const QDomElement & domElement)642 VPiecePath VAbstractPattern::ParsePieceNodes(const QDomElement &domElement)
643 {
644 VPiecePath path;
645 const QDomNodeList nodeList = domElement.childNodes();
646 for (qint32 i = 0; i < nodeList.size(); ++i)
647 {
648 const QDomElement element = nodeList.at(i).toElement();
649 if (not element.isNull())
650 {
651 path.Append(ParseSANode(element));
652 }
653 }
654 return path;
655 }
656
657 //---------------------------------------------------------------------------------------------------------------------
ParsePieceCSARecords(const QDomElement & domElement)658 QVector<CustomSARecord> VAbstractPattern::ParsePieceCSARecords(const QDomElement &domElement)
659 {
660 QVector<CustomSARecord> records;
661 const QDomNodeList nodeList = domElement.childNodes();
662 for (qint32 i = 0; i < nodeList.size(); ++i)
663 {
664 const QDomElement element = nodeList.at(i).toElement();
665 if (not element.isNull())
666 {
667 CustomSARecord record;
668 record.startPoint = GetParametrUInt(element, VAbstractPattern::AttrStart, NULL_ID_STR);
669 record.path = GetParametrUInt(element, VAbstractPattern::AttrPath, NULL_ID_STR);
670 record.endPoint = GetParametrUInt(element, VAbstractPattern::AttrEnd, NULL_ID_STR);
671 record.reverse = GetParametrBool(element, VAbstractPattern::AttrNodeReverse, falseStr);
672 record.includeType = static_cast<PiecePathIncludeType>(GetParametrUInt(element,
673 VAbstractPattern::AttrIncludeAs,
674 QChar('1')));
675 records.append(record);
676 }
677 }
678 return records;
679 }
680
681 //---------------------------------------------------------------------------------------------------------------------
ParsePieceInternalPaths(const QDomElement & domElement)682 QVector<quint32> VAbstractPattern::ParsePieceInternalPaths(const QDomElement &domElement)
683 {
684 QVector<quint32> records;
685 const QDomNodeList nodeList = domElement.childNodes();
686 for (qint32 i = 0; i < nodeList.size(); ++i)
687 {
688 const QDomElement element = nodeList.at(i).toElement();
689 if (not element.isNull())
690 {
691 const quint32 path = GetParametrUInt(element, VAbstractPattern::AttrPath, NULL_ID_STR);
692 if (path > NULL_ID)
693 {
694 records.append(path);
695 }
696 }
697 }
698 return records;
699 }
700
701 //---------------------------------------------------------------------------------------------------------------------
ParsePiecePointRecords(const QDomElement & domElement)702 QVector<quint32> VAbstractPattern::ParsePiecePointRecords(const QDomElement &domElement)
703 {
704 QVector<quint32> records;
705 const QDomNodeList nodeList = domElement.childNodes();
706 for (qint32 i = 0; i < nodeList.size(); ++i)
707 {
708 const QDomElement element = nodeList.at(i).toElement();
709 if (not element.isNull())
710 {
711 const quint32 path = element.text().toUInt();
712 if (path > NULL_ID)
713 {
714 records.append(path);
715 }
716 }
717 }
718 return records;
719 }
720
721 //---------------------------------------------------------------------------------------------------------------------
ParseSANode(const QDomElement & domElement)722 VPieceNode VAbstractPattern::ParseSANode(const QDomElement &domElement)
723 {
724 const quint32 id = VDomDocument::GetParametrUInt(domElement, AttrIdObject, NULL_ID_STR);
725 const bool reverse = VDomDocument::GetParametrUInt(domElement, VAbstractPattern::AttrNodeReverse, QChar('0'));
726 const bool excluded = VDomDocument::GetParametrBool(domElement, VAbstractPattern::AttrNodeExcluded, falseStr);
727 const bool uniqeness = VDomDocument::GetParametrBool(domElement, VAbstractPattern::AttrCheckUniqueness, trueStr);
728 const QString saBefore = VDomDocument::GetParametrString(domElement, VAbstractPattern::AttrSABefore,
729 currentSeamAllowance);
730 const QString saAfter = VDomDocument::GetParametrString(domElement, VAbstractPattern::AttrSAAfter,
731 currentSeamAllowance);
732 const PieceNodeAngle angle = static_cast<PieceNodeAngle>(VDomDocument::GetParametrUInt(domElement, AttrAngle,
733 QChar('0')));
734
735 const bool passmark = VDomDocument::GetParametrBool(domElement, VAbstractPattern::AttrNodePassmark, falseStr);
736 const PassmarkLineType passmarkLine = StringToPassmarkLineType(VDomDocument::GetParametrString(domElement,
737 VAbstractPattern::AttrNodePassmarkLine,
738 strOne));
739 const PassmarkAngleType passmarkAngle = StringToPassmarkAngleType(VDomDocument::GetParametrString(domElement,
740 VAbstractPattern::AttrNodePassmarkAngle,
741 strStraightforward));
742
743 const bool showSecond = VDomDocument::GetParametrBool(domElement, VAbstractPattern::AttrNodeShowSecondPassmark,
744 trueStr);
745 const bool manualPassmarkLength =
746 VDomDocument::GetParametrBool(domElement, VAbstractPattern::AttrManualPassmarkLength, falseStr);
747 const QString passmarkLength =
748 VDomDocument::GetParametrEmptyString(domElement, VAbstractPattern::AttrPassmarkLength);
749
750 const QString t = VDomDocument::GetParametrString(domElement, AttrType, VAbstractPattern::NodePoint);
751 Tool tool;
752
753 const QStringList types
754 {
755 VAbstractPattern::NodePoint,
756 VAbstractPattern::NodeArc,
757 VAbstractPattern::NodeSpline,
758 VAbstractPattern::NodeSplinePath,
759 VAbstractPattern::NodeElArc
760 };
761
762 switch (types.indexOf(t))
763 {
764 case 0: // VAbstractPattern::NodePoint
765 tool = Tool::NodePoint;
766 break;
767 case 1: // VAbstractPattern::NodeArc
768 tool = Tool::NodeArc;
769 break;
770 case 2: // VAbstractPattern::NodeSpline
771 tool = Tool::NodeSpline;
772 break;
773 case 3: // VAbstractPattern::NodeSplinePath
774 tool = Tool::NodeSplinePath;
775 break;
776 case 4: // NodeElArc
777 tool = Tool::NodeElArc;
778 break;
779 default:
780 VException e(QObject::tr("Wrong tag name '%1'.").arg(t));
781 throw e;
782 }
783 VPieceNode node(id, tool, reverse);
784 node.SetFormulaSABefore(saBefore);
785 node.SetFormulaSAAfter(saAfter);
786 node.SetAngleType(angle);
787 node.SetExcluded(excluded);
788 node.SetCheckUniqueness(uniqeness);
789 node.SetShowSecondPassmark(showSecond);
790 node.SetPassmark(passmark);
791 node.SetPassmarkLineType(passmarkLine);
792 node.SetPassmarkAngleType(passmarkAngle);
793 node.SetManualPassmarkLength(manualPassmarkLength);
794 node.SetFormulaPassmarkLength(passmarkLength);
795
796 return node;
797 }
798
799 //---------------------------------------------------------------------------------------------------------------------
AddToolOnRemove(VDataTool * tool)800 void VAbstractPattern::AddToolOnRemove(VDataTool *tool)
801 {
802 SCASSERT(tool != nullptr)
803 toolsOnRemove.append(tool);
804 }
805
806 //---------------------------------------------------------------------------------------------------------------------
807 /**
808 * @brief getHistory return list with list of history records.
809 * @return list of history records.
810 */
getHistory()811 QVector<VToolRecord> *VAbstractPattern::getHistory()
812 {
813 return &history;
814 }
815
816 //---------------------------------------------------------------------------------------------------------------------
getLocalHistory() const817 QVector<VToolRecord> VAbstractPattern::getLocalHistory() const
818 {
819 return getLocalHistory(GetNameActivPP());
820 }
821
822 //---------------------------------------------------------------------------------------------------------------------
MPath() const823 QString VAbstractPattern::MPath() const
824 {
825 return m_MPath;
826 }
827
828 //---------------------------------------------------------------------------------------------------------------------
SetMPath(const QString & path)829 void VAbstractPattern::SetMPath(const QString &path)
830 {
831 if (setTagText(TagMeasurements, path))
832 {
833 m_MPath = path;
834 patternLabelWasChanged = true;
835 modified = true;
836 emit patternChanged(false);
837 }
838 else
839 {
840 qDebug()<<"Can't save path to measurements"<<Q_FUNC_INFO;
841 }
842 }
843
844 //---------------------------------------------------------------------------------------------------------------------
SiblingNodeId(const quint32 & nodeId) const845 quint32 VAbstractPattern::SiblingNodeId(const quint32 &nodeId) const
846 {
847 // This check helps to find missed tools in the switch
848 Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 55, "Check if need to ignore modeling tools.");
849
850 quint32 siblingId = NULL_ID;
851
852 const QVector<VToolRecord> history = getLocalHistory();
853 for (qint32 i = 0; i < history.size(); ++i)
854 {
855 const VToolRecord tool = history.at(i);
856 if (nodeId == tool.getId())
857 {
858 if (i == 0)
859 {
860 siblingId = NULL_ID;
861 }
862 else
863 {
864 for (qint32 j = i; j > 0; --j)
865 {
866 const VToolRecord tool = history.at(j-1);
867 switch ( tool.getTypeTool() )
868 {
869 case Tool::Arrow:
870 case Tool::Piece:
871 case Tool::UnionDetails:
872 case Tool::NodeArc:
873 case Tool::NodeElArc:
874 case Tool::NodePoint:
875 case Tool::NodeSpline:
876 case Tool::NodeSplinePath:
877 case Tool::PlaceLabel:
878 case Tool::Pin:
879 case Tool::PiecePath:
880 case Tool::InsertNode:
881 case Tool::DuplicateDetail:
882 continue;
883 default:
884 siblingId = tool.getId();
885 j = 0;// break loop
886 break;
887 }
888 }
889 }
890 }
891 }
892 return siblingId;
893 }
894
895 //---------------------------------------------------------------------------------------------------------------------
getPatternPieces() const896 QStringList VAbstractPattern::getPatternPieces() const
897 {
898 return patternPieces;
899 }
900
901 //---------------------------------------------------------------------------------------------------------------------
GetDescription() const902 QString VAbstractPattern::GetDescription() const
903 {
904 return UniqueTagText(TagDescription);
905 }
906
907 //---------------------------------------------------------------------------------------------------------------------
SetDescription(const QString & text)908 void VAbstractPattern::SetDescription(const QString &text)
909 {
910 CheckTagExists(TagDescription);
911 setTagText(TagDescription, text);
912 modified = true;
913 emit patternChanged(false);
914 }
915
916 //---------------------------------------------------------------------------------------------------------------------
GetNotes() const917 QString VAbstractPattern::GetNotes() const
918 {
919 return UniqueTagText(TagNotes);
920 }
921
922 //---------------------------------------------------------------------------------------------------------------------
SetNotes(const QString & text)923 void VAbstractPattern::SetNotes(const QString &text)
924 {
925 CheckTagExists(TagNotes);
926 setTagText(TagNotes, text);
927 modified = true;
928 emit patternChanged(false);
929 }
930
931 //---------------------------------------------------------------------------------------------------------------------
GetPatternName() const932 QString VAbstractPattern::GetPatternName() const
933 {
934 return m_patternName;
935 }
936
937 //---------------------------------------------------------------------------------------------------------------------
SetPatternName(const QString & qsName)938 void VAbstractPattern::SetPatternName(const QString &qsName)
939 {
940 m_patternName = qsName;
941 CheckTagExists(TagPatternName);
942 setTagText(TagPatternName, m_patternName);
943 patternLabelWasChanged = true;
944 modified = true;
945 emit patternChanged(false);
946 }
947
948 //---------------------------------------------------------------------------------------------------------------------
GetCompanyName() const949 QString VAbstractPattern::GetCompanyName() const
950 {
951 return m_companyName;
952 }
953
954 //---------------------------------------------------------------------------------------------------------------------
SetCompanyName(const QString & qsName)955 void VAbstractPattern::SetCompanyName(const QString& qsName)
956 {
957 m_companyName = qsName;
958 CheckTagExists(TagCompanyName);
959 setTagText(TagCompanyName, m_companyName);
960 patternLabelWasChanged = true;
961 modified = true;
962 emit patternChanged(false);
963 }
964
965 //---------------------------------------------------------------------------------------------------------------------
GetPatternNumber() const966 QString VAbstractPattern::GetPatternNumber() const
967 {
968 return m_patternNumber;
969 }
970
971 //---------------------------------------------------------------------------------------------------------------------
SetPatternNumber(const QString & qsNum)972 void VAbstractPattern::SetPatternNumber(const QString& qsNum)
973 {
974 m_patternNumber = qsNum;
975 CheckTagExists(TagPatternNum);
976 setTagText(TagPatternNum, m_patternNumber);
977 patternLabelWasChanged = true;
978 modified = true;
979 emit patternChanged(false);
980 }
981
982 //---------------------------------------------------------------------------------------------------------------------
GetCustomerName() const983 QString VAbstractPattern::GetCustomerName() const
984 {
985 return UniqueTagText(TagCustomerName);
986 }
987
988 //---------------------------------------------------------------------------------------------------------------------
SetCustomerName(const QString & qsName)989 void VAbstractPattern::SetCustomerName(const QString& qsName)
990 {
991 CheckTagExists(TagCustomerName);
992 setTagText(TagCustomerName, qsName);
993 patternLabelWasChanged = true;
994 modified = true;
995 emit patternChanged(false);
996 }
997
998 //---------------------------------------------------------------------------------------------------------------------
GetCustomerBirthDate() const999 QDate VAbstractPattern::GetCustomerBirthDate() const
1000 {
1001 return QDate::fromString(UniqueTagText(TagCustomerBirthDate), "yyyy-MM-dd");
1002 }
1003
1004 //---------------------------------------------------------------------------------------------------------------------
SetCustomerBirthDate(const QDate & date)1005 void VAbstractPattern::SetCustomerBirthDate(const QDate &date)
1006 {
1007 CheckTagExists(TagCustomerBirthDate);
1008 setTagText(TagCustomerBirthDate, date.toString("yyyy-MM-dd"));
1009 patternLabelWasChanged = true;
1010 modified = true;
1011 emit patternChanged(false);
1012 }
1013
1014 //---------------------------------------------------------------------------------------------------------------------
GetCustomerEmail() const1015 QString VAbstractPattern::GetCustomerEmail() const
1016 {
1017 return UniqueTagText(TagCustomerEmail);
1018 }
1019
1020 //---------------------------------------------------------------------------------------------------------------------
SetCustomerEmail(const QString & email)1021 void VAbstractPattern::SetCustomerEmail(const QString &email)
1022 {
1023 CheckTagExists(TagCustomerEmail);
1024 setTagText(TagCustomerEmail, email);
1025 patternLabelWasChanged = true;
1026 modified = true;
1027 emit patternChanged(false);
1028 }
1029
1030 //---------------------------------------------------------------------------------------------------------------------
GetLabelDateFormat() const1031 QString VAbstractPattern::GetLabelDateFormat() const
1032 {
1033 return m_labelDateFormat;
1034 }
1035
1036 //---------------------------------------------------------------------------------------------------------------------
SetLabelDateFormat(const QString & format)1037 void VAbstractPattern::SetLabelDateFormat(const QString &format)
1038 {
1039 m_labelDateFormat = format;
1040 QDomElement tag = CheckTagExists(TagPatternLabel);
1041 SetAttribute(tag, AttrDateFormat, m_labelDateFormat);
1042 patternLabelWasChanged = true;
1043 modified = true;
1044 emit patternChanged(false);
1045 }
1046
1047 //---------------------------------------------------------------------------------------------------------------------
GetLabelTimeFormat() const1048 QString VAbstractPattern::GetLabelTimeFormat() const
1049 {
1050 QString globalLabelTimeFormat = VAbstractApplication::VApp()->Settings()->GetLabelTimeFormat();
1051
1052 const QDomNodeList list = elementsByTagName(TagPatternLabel);
1053 if (list.isEmpty())
1054 {
1055 return globalLabelTimeFormat;
1056 }
1057
1058 QDomElement tag = list.at(0).toElement();
1059 return GetParametrString(tag, AttrTimeFormat, globalLabelTimeFormat);
1060 }
1061
1062 //---------------------------------------------------------------------------------------------------------------------
SetLabelTimeFormat(const QString & format)1063 void VAbstractPattern::SetLabelTimeFormat(const QString &format)
1064 {
1065 QDomElement tag = CheckTagExists(TagPatternLabel);
1066 SetAttribute(tag, AttrTimeFormat, format);
1067 patternLabelWasChanged = true;
1068 modified = true;
1069 emit patternChanged(false);
1070 }
1071
1072 //---------------------------------------------------------------------------------------------------------------------
SetPatternLabelTemplate(const QVector<VLabelTemplateLine> & lines)1073 void VAbstractPattern::SetPatternLabelTemplate(const QVector<VLabelTemplateLine> &lines)
1074 {
1075 QDomElement tag = CheckTagExists(TagPatternLabel);
1076 RemoveAllChildren(tag);
1077 SetLabelTemplate(tag, lines);
1078 patternLabelLines = lines;
1079 patternLabelWasChanged = true;
1080 modified = true;
1081 emit patternChanged(false);
1082 }
1083
1084 //---------------------------------------------------------------------------------------------------------------------
GetPatternLabelTemplate() const1085 QVector<VLabelTemplateLine> VAbstractPattern::GetPatternLabelTemplate() const
1086 {
1087 if (patternLabelLines.isEmpty())
1088 {
1089 const QDomNodeList list = elementsByTagName(TagPatternLabel);
1090 if (list.isEmpty() || list.at(0).childNodes().count() == 0)
1091 {
1092 return QVector<VLabelTemplateLine>();
1093 }
1094
1095 patternLabelLines = GetLabelTemplate(list.at(0).toElement());
1096 }
1097
1098 return patternLabelLines;
1099 }
1100
1101 //---------------------------------------------------------------------------------------------------------------------
SetWatermarkPath(const QString & path)1102 bool VAbstractPattern::SetWatermarkPath(const QString &path)
1103 {
1104 QDomElement tag = CheckTagExists(TagWatermark);
1105
1106 if (path.isEmpty())
1107 {
1108 QDomNode parent = tag.parentNode();
1109 parent.removeChild(tag);
1110
1111 emit patternChanged(false);
1112 patternLabelWasChanged = true;
1113 m_watermarkPath = path;
1114 modified = true;
1115 return true;
1116 }
1117 else
1118 {
1119 if (setTagText(tag, path))
1120 {
1121 emit patternChanged(false);
1122 patternLabelWasChanged = true;
1123 m_watermarkPath = path;
1124 modified = true;
1125 return true;
1126 }
1127 else
1128 {
1129 qDebug() << "Can't save path to watermark" << Q_FUNC_INFO;
1130 return false;
1131 }
1132 }
1133 }
1134
1135 //---------------------------------------------------------------------------------------------------------------------
GetWatermarkPath() const1136 QString VAbstractPattern::GetWatermarkPath() const
1137 {
1138 return m_watermarkPath;
1139 }
1140
1141 //---------------------------------------------------------------------------------------------------------------------
SetPatternMaterials(const QMap<int,QString> & materials)1142 void VAbstractPattern::SetPatternMaterials(const QMap<int, QString> &materials)
1143 {
1144 QDomElement tag = CheckTagExists(TagPatternMaterials);
1145 RemoveAllChildren(tag);
1146 SetMaterials(tag, materials);
1147 patternMaterials = materials;
1148 patternLabelWasChanged = true;
1149 modified = true;
1150 emit patternChanged(false);
1151 }
1152
1153 //---------------------------------------------------------------------------------------------------------------------
GetPatternMaterials() const1154 QMap<int, QString> VAbstractPattern::GetPatternMaterials() const
1155 {
1156 if (patternMaterials.isEmpty())
1157 {
1158 const QDomNodeList list = elementsByTagName(TagPatternMaterials);
1159 if (list.isEmpty() || list.at(0).childNodes().count() == 0)
1160 {
1161 return QMap<int, QString>();
1162 }
1163
1164 patternMaterials = GetMaterials(list.at(0).toElement());
1165 }
1166
1167 return AdjustMaterials(patternMaterials);
1168 }
1169
1170 //---------------------------------------------------------------------------------------------------------------------
GetFinalMeasurements() const1171 QVector<VFinalMeasurement> VAbstractPattern::GetFinalMeasurements() const
1172 {
1173 const QDomNodeList list = elementsByTagName(TagFinalMeasurements);
1174 if (list.isEmpty() || list.at(0).childNodes().count() == 0)
1175 {
1176 return QVector<VFinalMeasurement>();
1177 }
1178
1179 return GetFMeasurements(list.at(0).toElement());
1180 }
1181
1182 //---------------------------------------------------------------------------------------------------------------------
SetFinalMeasurements(const QVector<VFinalMeasurement> & measurements)1183 void VAbstractPattern::SetFinalMeasurements(const QVector<VFinalMeasurement> &measurements)
1184 {
1185 QDomElement tag = CheckTagExists(TagFinalMeasurements);
1186 RemoveAllChildren(tag);
1187 SetFMeasurements(tag, measurements);
1188 modified = true;
1189 emit patternChanged(false);
1190 }
1191
1192 //---------------------------------------------------------------------------------------------------------------------
SetPatternWasChanged(bool changed)1193 void VAbstractPattern::SetPatternWasChanged(bool changed)
1194 {
1195 patternLabelWasChanged = changed;
1196 }
1197
1198 //---------------------------------------------------------------------------------------------------------------------
GetPatternWasChanged() const1199 bool VAbstractPattern::GetPatternWasChanged() const
1200 {
1201 return patternLabelWasChanged;
1202 }
1203
1204 //---------------------------------------------------------------------------------------------------------------------
GetPassmarkLengthVariable() const1205 QString VAbstractPattern::GetPassmarkLengthVariable() const
1206 {
1207 const QDomElement pattern = documentElement();
1208
1209 if (pattern.isNull())
1210 {
1211 return {};
1212 }
1213
1214 return GetParametrEmptyString(pattern, AttrPassmarkLength);
1215 }
1216
1217 //---------------------------------------------------------------------------------------------------------------------
SetPassmarkLengthVariable(const QString & name)1218 void VAbstractPattern::SetPassmarkLengthVariable(const QString &name)
1219 {
1220 QDomElement pattern = documentElement();
1221
1222 if (not pattern.isNull())
1223 {
1224 SetAttribute(pattern, AttrPassmarkLength, name);
1225 modified = true;
1226 }
1227 }
1228
1229 //---------------------------------------------------------------------------------------------------------------------
GetImage() const1230 QString VAbstractPattern::GetImage() const
1231 {
1232 return UniqueTagText(TagImage);
1233 }
1234
1235 //---------------------------------------------------------------------------------------------------------------------
GetImageExtension() const1236 QString VAbstractPattern::GetImageExtension() const
1237 {
1238 const QString defExt = QStringLiteral("PNG");
1239 const QDomNodeList nodeList = this->elementsByTagName(TagImage);
1240 if (nodeList.isEmpty())
1241 {
1242 return defExt;
1243 }
1244 else
1245 {
1246 const QDomNode domNode = nodeList.at(0);
1247 if (domNode.isNull() == false && domNode.isElement())
1248 {
1249 const QDomElement domElement = domNode.toElement();
1250 if (domElement.isNull() == false)
1251 {
1252 const QString ext = domElement.attribute(AttrExtension, defExt);
1253 return ext;
1254 }
1255 }
1256 }
1257 return defExt;
1258 }
1259
1260 //---------------------------------------------------------------------------------------------------------------------
SetImage(const QString & text,const QString & extension)1261 void VAbstractPattern::SetImage(const QString &text, const QString &extension)
1262 {
1263 QDomElement imageElement = CheckTagExists(TagImage);
1264 setTagText(imageElement, text);
1265 CheckTagExists(TagImage).setAttribute(AttrExtension, extension);
1266 modified = true;
1267 emit patternChanged(false);
1268 }
1269
1270 //---------------------------------------------------------------------------------------------------------------------
DeleteImage()1271 void VAbstractPattern::DeleteImage()
1272 {
1273 QDomElement pattern = documentElement();
1274 pattern.removeChild(CheckTagExists(TagImage));
1275 modified = true;
1276 emit patternChanged(false);
1277 }
1278
1279 //---------------------------------------------------------------------------------------------------------------------
GetVersion() const1280 QString VAbstractPattern::GetVersion() const
1281 {
1282 return UniqueTagText(TagVersion, VPatternConverter::PatternMaxVerStr);
1283 }
1284
1285 //---------------------------------------------------------------------------------------------------------------------
SetVersion()1286 void VAbstractPattern::SetVersion()
1287 {
1288 setTagText(TagVersion, VPatternConverter::PatternMaxVerStr);
1289 emit patternChanged(false);
1290 }
1291
1292 //---------------------------------------------------------------------------------------------------------------------
1293 /**
1294 * @brief haveLiteChange we have unsaved change.
1295 */
haveLiteChange()1296 void VAbstractPattern::haveLiteChange()
1297 {
1298 emit patternChanged(false);
1299 }
1300
1301 //---------------------------------------------------------------------------------------------------------------------
NeedFullParsing()1302 void VAbstractPattern::NeedFullParsing()
1303 {
1304 emit UndoCommand();
1305 }
1306
1307 //---------------------------------------------------------------------------------------------------------------------
ClearScene()1308 void VAbstractPattern::ClearScene()
1309 {
1310 emit ClearMainWindow();
1311 }
1312
1313 //---------------------------------------------------------------------------------------------------------------------
CheckInLayoutList()1314 void VAbstractPattern::CheckInLayoutList()
1315 {
1316 emit UpdateInLayoutList();
1317 }
1318
1319 //---------------------------------------------------------------------------------------------------------------------
SelectedDetail(quint32 id)1320 void VAbstractPattern::SelectedDetail(quint32 id)
1321 {
1322 emit ShowDetail(id);
1323 }
1324
1325 //---------------------------------------------------------------------------------------------------------------------
UpdateVisiblityGroups()1326 void VAbstractPattern::UpdateVisiblityGroups()
1327 {
1328 emit UpdateGroups();
1329 }
1330
1331 //---------------------------------------------------------------------------------------------------------------------
ToolExists(const quint32 & id)1332 void VAbstractPattern::ToolExists(const quint32 &id)
1333 {
1334 if (tools.contains(id) == false)
1335 {
1336 throw VExceptionBadId(tr("Can't find tool in table."), id);
1337 }
1338 }
1339
1340 //---------------------------------------------------------------------------------------------------------------------
ParsePathNodes(const QDomElement & domElement)1341 VPiecePath VAbstractPattern::ParsePathNodes(const QDomElement &domElement)
1342 {
1343 VPiecePath path;
1344 const QDomNodeList nodeList = domElement.childNodes();
1345 for (qint32 i = 0; i < nodeList.size(); ++i)
1346 {
1347 const QDomElement element = nodeList.at(i).toElement();
1348 if (not element.isNull() && element.tagName() == VAbstractPattern::TagNode)
1349 {
1350 path.Append(ParseSANode(element));
1351 }
1352 }
1353 return path;
1354 }
1355
1356 //---------------------------------------------------------------------------------------------------------------------
1357 /**
1358 * @brief SetActivPP set current pattern piece.
1359 * @param name pattern peace name.
1360 */
SetActivPP(const QString & name)1361 void VAbstractPattern::SetActivPP(const QString &name)
1362 {
1363 Q_ASSERT_X(not name.isEmpty(), Q_FUNC_INFO, "name pattern piece is empty");
1364 this->nameActivPP = name;
1365 emit ChangedActivPP(name);
1366 }
1367
1368 //---------------------------------------------------------------------------------------------------------------------
CheckTagExists(const QString & tag)1369 QDomElement VAbstractPattern::CheckTagExists(const QString &tag)
1370 {
1371 const QDomNodeList list = elementsByTagName(tag);
1372 QDomElement element;
1373 if (list.isEmpty())
1374 {
1375 const QStringList tags
1376 {
1377 TagUnit, // 0
1378 TagImage, // 1
1379 TagDescription, // 2
1380 TagNotes, // 3
1381 TagPatternName, // 4
1382 TagPatternNum, // 5
1383 TagCompanyName, // 6
1384 TagCustomerName, // 7
1385 TagCustomerBirthDate, // 8
1386 TagCustomerEmail, // 9
1387 TagPatternLabel, // 10
1388 TagWatermark, // 11
1389 TagPatternMaterials, // 12
1390 TagFinalMeasurements // 13
1391 };
1392
1393 switch (tags.indexOf(tag))
1394 {
1395 case 1: //TagImage
1396 element = createElement(TagImage);
1397 break;
1398 case 2: //TagDescription
1399 element = createElement(TagDescription);
1400 break;
1401 case 3: //TagNotes
1402 element = createElement(TagNotes);
1403 break;
1404 case 4: // TagPatternName
1405 element = createElement(TagPatternName);
1406 break;
1407 case 5: // TagPatternNum
1408 element = createElement(TagPatternNum);
1409 break;
1410 case 6: // TagCompanyName
1411 element = createElement(TagCompanyName);
1412 break;
1413 case 7: // TagCustomerName
1414 element = createElement(TagCustomerName);
1415 break;
1416 case 8: // TagCustomerBirthDate
1417 element = createElement(TagCustomerBirthDate);
1418 break;
1419 case 9: // TagCustomerEmail
1420 element = createElement(TagCustomerEmail);
1421 break;
1422 case 10: // TagPatternLabel
1423 element = createElement(TagPatternLabel);
1424 break;
1425 case 11: // TagWatermark
1426 element = createElement(TagWatermark);
1427 break;
1428 case 12: // TagPatternMaterials
1429 element = createElement(TagPatternMaterials);
1430 break;
1431 case 13: // TagFinalMeasurements
1432 element = createElement(TagFinalMeasurements);
1433 break;
1434 case 0: //TagUnit (Mandatory tag)
1435 default:
1436 return QDomElement();
1437 }
1438 InsertTag(tags, element);
1439 return element;
1440 }
1441 return list.at(0).toElement();
1442 }
1443
1444 //---------------------------------------------------------------------------------------------------------------------
InsertTag(const QStringList & tags,const QDomElement & element)1445 void VAbstractPattern::InsertTag(const QStringList &tags, const QDomElement &element)
1446 {
1447 QDomElement pattern = documentElement();
1448 for (int i = tags.indexOf(element.tagName())-1; i >= 0; --i)
1449 {
1450 const QDomNodeList list = elementsByTagName(tags.at(i));
1451 if (not list.isEmpty())
1452 {
1453 pattern.insertAfter(element, list.at(0));
1454 break;
1455 }
1456 }
1457 SetVersion();
1458 }
1459
1460 //---------------------------------------------------------------------------------------------------------------------
GetIndexActivPP() const1461 int VAbstractPattern::GetIndexActivPP() const
1462 {
1463 const QDomNodeList drawList = elementsByTagName(TagDraw);
1464
1465 int index = 0;
1466 if (not drawList.isEmpty())
1467 {
1468 for (int i = 0; i < drawList.size(); ++i)
1469 {
1470 QDomElement node = drawList.at(i).toElement();
1471 if (node.attribute(AttrName) == nameActivPP)
1472 {
1473 index = i;
1474 break;
1475 }
1476 }
1477 }
1478
1479 return index;
1480 }
1481
1482 //---------------------------------------------------------------------------------------------------------------------
ListIncrements() const1483 QStringList VAbstractPattern::ListIncrements() const
1484 {
1485 QStringList increments;
1486
1487 auto GetExpressions = [&increments, this](const QString &type)
1488 {
1489 const QDomNodeList list = elementsByTagName(type);
1490 for (int i=0; i < list.size(); ++i)
1491 {
1492 const QString name = GetParametrEmptyString(list.at(i).toElement(), AttrName);
1493 if (not name.isEmpty())
1494 {
1495 increments.append(name);
1496 }
1497 }
1498 };
1499
1500 GetExpressions(TagIncrement);
1501 GetExpressions(TagPreviewCalculations);
1502
1503 return increments;
1504 }
1505
1506 //---------------------------------------------------------------------------------------------------------------------
ListExpressions() const1507 QVector<VFormulaField> VAbstractPattern::ListExpressions() const
1508 {
1509 // If new tool bring absolutely new type and has formula(s) create new method to cover it.
1510 // Note. Tool Union Details also contains formulas, but we don't use them for union and keep only to simplifying
1511 // working with nodes. Same code for saving reading.
1512 auto futurePointExpressions = QtConcurrent::run(this, &VAbstractPattern::ListPointExpressions);
1513 auto futureArcExpressions = QtConcurrent::run(this, &VAbstractPattern::ListArcExpressions);
1514 auto futureElArcExpressions = QtConcurrent::run(this, &VAbstractPattern::ListElArcExpressions);
1515 auto futureSplineExpressions = QtConcurrent::run(this, &VAbstractPattern::ListSplineExpressions);
1516 auto futureIncrementExpressions = QtConcurrent::run(this, &VAbstractPattern::ListIncrementExpressions);
1517 auto futureOperationExpressions = QtConcurrent::run(this, &VAbstractPattern::ListOperationExpressions);
1518 auto futurePathExpressions = QtConcurrent::run(this, &VAbstractPattern::ListPathExpressions);
1519 auto futurePieceExpressions = QtConcurrent::run(this, &VAbstractPattern::ListPieceExpressions);
1520 auto futureFinalMeasurementsExpressions = QtConcurrent::run(this,
1521 &VAbstractPattern::ListFinalMeasurementsExpressions);
1522
1523 QVector<VFormulaField> list;
1524 list << futurePointExpressions.result();
1525 list << futureArcExpressions.result();
1526 list << futureElArcExpressions.result();
1527 list << futureSplineExpressions.result();
1528 list << futureIncrementExpressions.result();
1529 list << futureOperationExpressions.result();
1530 list << futurePathExpressions.result();
1531 list << futurePieceExpressions.result();
1532 list << futureFinalMeasurementsExpressions.result();
1533
1534 return list;
1535 }
1536
1537 //---------------------------------------------------------------------------------------------------------------------
ListPointExpressions() const1538 QVector<VFormulaField> VAbstractPattern::ListPointExpressions() const
1539 {
1540 // Check if new tool doesn't bring new attribute with a formula.
1541 // If no just increment a number.
1542 // If new tool bring absolutely new type and has formula(s) create new method to cover it.
1543 Q_STATIC_ASSERT(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 55);
1544
1545 QVector<VFormulaField> expressions;
1546 const QDomNodeList list = elementsByTagName(TagPoint);
1547 for (int i=0; i < list.size(); ++i)
1548 {
1549 const QDomElement dom = list.at(i).toElement();
1550
1551 // Each tag can contains several attributes.
1552 ReadExpressionAttribute(expressions, dom, AttrLength);
1553 ReadExpressionAttribute(expressions, dom, AttrAngle);
1554 ReadExpressionAttribute(expressions, dom, AttrC1Radius);
1555 ReadExpressionAttribute(expressions, dom, AttrC2Radius);
1556 ReadExpressionAttribute(expressions, dom, AttrCRadius);
1557 ReadExpressionAttribute(expressions, dom, AttrRadius);
1558 ReadExpressionAttribute(expressions, dom, AttrWidth);
1559 ReadExpressionAttribute(expressions, dom, AttrHeight);
1560 }
1561
1562 return expressions;
1563 }
1564
1565 //---------------------------------------------------------------------------------------------------------------------
ListArcExpressions() const1566 QVector<VFormulaField> VAbstractPattern::ListArcExpressions() const
1567 {
1568 // Check if new tool doesn't bring new attribute with a formula.
1569 // If no just increment number.
1570 // If new tool bring absolutely new type and has formula(s) create new method to cover it.
1571 Q_STATIC_ASSERT(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 55);
1572
1573 QVector<VFormulaField> expressions;
1574 const QDomNodeList list = elementsByTagName(TagArc);
1575 for (int i=0; i < list.size(); ++i)
1576 {
1577 const QDomElement dom = list.at(i).toElement();
1578
1579 // Each tag can contains several attributes.
1580 ReadExpressionAttribute(expressions, dom, AttrAngle1);
1581 ReadExpressionAttribute(expressions, dom, AttrAngle2);
1582 ReadExpressionAttribute(expressions, dom, AttrRadius);
1583 ReadExpressionAttribute(expressions, dom, AttrLength);
1584 }
1585
1586 return expressions;
1587 }
1588
1589 //---------------------------------------------------------------------------------------------------------------------
ListElArcExpressions() const1590 QVector<VFormulaField> VAbstractPattern::ListElArcExpressions() const
1591 {
1592 // Check if new tool doesn't bring new attribute with a formula.
1593 // If no just increment number.
1594 // If new tool bring absolutely new type and has formula(s) create new method to cover it.
1595 Q_STATIC_ASSERT(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 55);
1596
1597 QVector<VFormulaField> expressions;
1598 const QDomNodeList list = elementsByTagName(TagElArc);
1599 for (int i=0; i < list.size(); ++i)
1600 {
1601 const QDomElement dom = list.at(i).toElement();
1602
1603 // Each tag can contains several attributes.
1604 ReadExpressionAttribute(expressions, dom, AttrRadius1);
1605 ReadExpressionAttribute(expressions, dom, AttrRadius2);
1606 ReadExpressionAttribute(expressions, dom, AttrAngle1);
1607 ReadExpressionAttribute(expressions, dom, AttrAngle2);
1608 ReadExpressionAttribute(expressions, dom, AttrRotationAngle);
1609 }
1610
1611 return expressions;
1612 }
1613
1614 //---------------------------------------------------------------------------------------------------------------------
ListSplineExpressions() const1615 QVector<VFormulaField> VAbstractPattern::ListSplineExpressions() const
1616 {
1617 QVector<VFormulaField> expressions;
1618 expressions << ListPathPointExpressions();
1619 return expressions;
1620 }
1621
1622 //---------------------------------------------------------------------------------------------------------------------
ListPathPointExpressions() const1623 QVector<VFormulaField> VAbstractPattern::ListPathPointExpressions() const
1624 {
1625 // Check if new tool doesn't bring new attribute with a formula.
1626 // If no just increment number.
1627 // If new tool bring absolutely new type and has formula(s) create new method to cover it.
1628 Q_STATIC_ASSERT(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 55);
1629
1630 QVector<VFormulaField> expressions;
1631 const QDomNodeList list = elementsByTagName(AttrPathPoint);
1632 for (int i=0; i < list.size(); ++i)
1633 {
1634 const QDomElement dom = list.at(i).toElement();
1635
1636 // Each tag can contains several attributes.
1637 ReadExpressionAttribute(expressions, dom, AttrKAsm1);
1638 ReadExpressionAttribute(expressions, dom, AttrKAsm2);
1639 ReadExpressionAttribute(expressions, dom, AttrAngle);
1640 }
1641
1642 return expressions;
1643 }
1644
1645 //---------------------------------------------------------------------------------------------------------------------
ListIncrementExpressions() const1646 QVector<VFormulaField> VAbstractPattern::ListIncrementExpressions() const
1647 {
1648 QVector<VFormulaField> expressions;
1649 const QDomNodeList list = elementsByTagName(TagIncrement);
1650 for (int i=0; i < list.size(); ++i)
1651 {
1652 const QDomElement dom = list.at(i).toElement();
1653
1654 ReadExpressionAttribute(expressions, dom, AttrFormula);
1655 }
1656
1657 return expressions;
1658 }
1659
1660 //---------------------------------------------------------------------------------------------------------------------
ListOperationExpressions() const1661 QVector<VFormulaField> VAbstractPattern::ListOperationExpressions() const
1662 {
1663 // Check if new tool doesn't bring new attribute with a formula.
1664 // If no just increment number.
1665 // If new tool bring absolutely new type and has formula(s) create new method to cover it.
1666 Q_STATIC_ASSERT(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 55);
1667
1668 QVector<VFormulaField> expressions;
1669 const QDomNodeList list = elementsByTagName(TagOperation);
1670 for (int i=0; i < list.size(); ++i)
1671 {
1672 const QDomElement dom = list.at(i).toElement();
1673
1674 // Each tag can contains several attributes.
1675 ReadExpressionAttribute(expressions, dom, AttrAngle);
1676 ReadExpressionAttribute(expressions, dom, AttrLength);
1677 }
1678
1679 return expressions;
1680 }
1681
1682 //---------------------------------------------------------------------------------------------------------------------
ListNodesExpressions(const QDomElement & nodes) const1683 QVector<VFormulaField> VAbstractPattern::ListNodesExpressions(const QDomElement &nodes) const
1684 {
1685 // Check if new tool doesn't bring new attribute with a formula.
1686 // If no just increment number.
1687 // If new tool bring absolutely new type and has formula(s) create new method to cover it.
1688 Q_STATIC_ASSERT(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 55);
1689
1690 QVector<VFormulaField> expressions;
1691
1692 const QDomNodeList nodeList = nodes.childNodes();
1693 for (qint32 i = 0; i < nodeList.size(); ++i)
1694 {
1695 const QDomElement element = nodeList.at(i).toElement();
1696 if (not element.isNull() && element.tagName() == VAbstractPattern::TagNode)
1697 {
1698 ReadExpressionAttribute(expressions, element, VAbstractPattern::AttrSABefore);
1699 ReadExpressionAttribute(expressions, element, VAbstractPattern::AttrSAAfter);
1700 ReadExpressionAttribute(expressions, element, VAbstractPattern::AttrPassmarkLength);
1701 }
1702 }
1703 return expressions;
1704 }
1705
1706 //---------------------------------------------------------------------------------------------------------------------
ListPathExpressions() const1707 QVector<VFormulaField> VAbstractPattern::ListPathExpressions() const
1708 {
1709 // Check if new tool doesn't bring new attribute with a formula.
1710 // If no just increment number.
1711 // If new tool bring absolutely new type and has formula(s) create new method to cover it.
1712 Q_STATIC_ASSERT(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 55);
1713
1714 QVector<VFormulaField> expressions;
1715 const QDomNodeList list = elementsByTagName(TagPath);
1716 for (int i=0; i < list.size(); ++i)
1717 {
1718 const QDomElement dom = list.at(i).toElement();
1719 if (dom.isNull())
1720 {
1721 continue;
1722 }
1723
1724 expressions << ListNodesExpressions(dom.firstChildElement(TagNodes));
1725 }
1726
1727 return expressions;
1728 }
1729
1730 //---------------------------------------------------------------------------------------------------------------------
ListGrainlineExpressions(const QDomElement & element) const1731 QVector<VFormulaField> VAbstractPattern::ListGrainlineExpressions(const QDomElement &element) const
1732 {
1733 QVector<VFormulaField> expressions;
1734 if (not element.isNull())
1735 {
1736 // Each tag can contains several attributes.
1737 ReadExpressionAttribute(expressions, element, AttrRotation);
1738 ReadExpressionAttribute(expressions, element, AttrLength);
1739 }
1740
1741 return expressions;
1742 }
1743
1744 //---------------------------------------------------------------------------------------------------------------------
ListPieceExpressions() const1745 QVector<VFormulaField> VAbstractPattern::ListPieceExpressions() const
1746 {
1747 // Check if new tool doesn't bring new attribute with a formula.
1748 // If no just increment number.
1749 // If new tool bring absolutely new type and has formula(s) create new method to cover it.
1750 Q_STATIC_ASSERT(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 55);
1751
1752 QVector<VFormulaField> expressions;
1753 const QDomNodeList list = elementsByTagName(TagDetail);
1754 for (int i=0; i < list.size(); ++i)
1755 {
1756 const QDomElement dom = list.at(i).toElement();
1757 if (dom.isNull())
1758 {
1759 continue;
1760 }
1761
1762 // Each tag can contains several attributes.
1763 ReadExpressionAttribute(expressions, dom, AttrWidth);
1764
1765 expressions << ListNodesExpressions(dom.firstChildElement(TagNodes));
1766 expressions << ListGrainlineExpressions(dom.firstChildElement(TagGrainline));
1767 }
1768
1769 return expressions;
1770 }
1771
1772 //---------------------------------------------------------------------------------------------------------------------
ListFinalMeasurementsExpressions() const1773 QVector<VFormulaField> VAbstractPattern::ListFinalMeasurementsExpressions() const
1774 {
1775 QVector<VFormulaField> expressions;
1776 const QDomNodeList list = elementsByTagName(TagFMeasurement);
1777 for (int i=0; i < list.size(); ++i)
1778 {
1779 const QDomElement dom = list.at(i).toElement();
1780 if (dom.isNull())
1781 {
1782 continue;
1783 }
1784
1785 // Each tag can contains several attributes.
1786 ReadExpressionAttribute(expressions, dom, AttrFormula);
1787 }
1788
1789 return expressions;
1790 }
1791
1792 //---------------------------------------------------------------------------------------------------------------------
IsVariable(const QString & token) const1793 bool VAbstractPattern::IsVariable(const QString &token) const
1794 {
1795 for (auto &var : builInVariables)
1796 {
1797 if (token.indexOf( var ) == 0)
1798 {
1799 if (var == currentLength || var == currentSeamAllowance)
1800 {
1801 return token == var;
1802 }
1803 else
1804 {
1805 return true;
1806 }
1807 }
1808 }
1809
1810 if (token.startsWith('#'))
1811 {
1812 return true;
1813 }
1814
1815 return false;
1816 }
1817
1818 //---------------------------------------------------------------------------------------------------------------------
IsFunction(const QString & token) const1819 bool VAbstractPattern::IsFunction(const QString &token) const
1820 {
1821 for (auto &fn : builInFunctions)
1822 {
1823 if (token.indexOf(fn) == 0)
1824 {
1825 return true;
1826 }
1827 }
1828
1829 return false;
1830 }
1831
1832 //---------------------------------------------------------------------------------------------------------------------
ParseItemElement(const QDomElement & domElement)1833 QPair<bool, QMap<quint32, quint32> > VAbstractPattern::ParseItemElement(const QDomElement &domElement)
1834 {
1835 Q_ASSERT_X(not domElement.isNull(), Q_FUNC_INFO, "domElement is null");
1836
1837 try
1838 {
1839 const bool visible = GetParametrBool(domElement, AttrVisible, trueStr);
1840
1841 QMap<quint32, quint32> items;
1842
1843 const QDomNodeList nodeList = domElement.childNodes();
1844 const qint32 num = nodeList.size();
1845 for (qint32 i = 0; i < num; ++i)
1846 {
1847 const QDomElement element = nodeList.at(i).toElement();
1848 if (not element.isNull() && element.tagName() == TagGroupItem)
1849 {
1850 const quint32 object = GetParametrUInt(element, AttrObject, NULL_ID_STR);
1851 const quint32 tool = GetParametrUInt(element, AttrTool, NULL_ID_STR);
1852 items.insert(object, tool);
1853 }
1854 }
1855
1856 QPair<bool, QMap<quint32, quint32> > group;
1857 group.first = visible;
1858 group.second = items;
1859
1860 return group;
1861 }
1862 catch (const VExceptionBadId &e)
1863 {
1864 VExceptionObjectError excep(tr("Error creating or updating group"), domElement);
1865 excep.AddMoreInformation(e.ErrorMessage());
1866 throw excep;
1867 }
1868 }
1869
1870 //---------------------------------------------------------------------------------------------------------------------
GetMaterials(const QDomElement & element) const1871 QMap<int, QString> VAbstractPattern::GetMaterials(const QDomElement &element) const
1872 {
1873 QMap<int, QString> materials;
1874
1875 if (not element.isNull())
1876 {
1877 QDomElement tagMaterial = element.firstChildElement();
1878 while (tagMaterial.isNull() == false)
1879 {
1880 if (tagMaterial.tagName() == TagMaterial)
1881 {
1882 const int number = static_cast<int>(GetParametrUInt(tagMaterial, AttrNumber, QChar('0')));
1883 const QString name = GetParametrEmptyString(tagMaterial, AttrName);
1884
1885 if (number > 0 && number <= userMaterialPlaceholdersQuantity)
1886 {
1887 materials.insert(number, name);
1888 }
1889 }
1890 tagMaterial = tagMaterial.nextSiblingElement(TagMaterial);
1891 }
1892 }
1893
1894 return materials;
1895 }
1896
1897 //---------------------------------------------------------------------------------------------------------------------
SetMaterials(QDomElement & element,const QMap<int,QString> & materials)1898 void VAbstractPattern::SetMaterials(QDomElement &element, const QMap<int, QString> &materials)
1899 {
1900 if (not element.isNull())
1901 {
1902 QMap<int, QString>::const_iterator i = materials.constBegin();
1903 while (i != materials.constEnd())
1904 {
1905 QDomElement tagMaterial = createElement(TagMaterial);
1906
1907 SetAttribute(tagMaterial, AttrNumber, i.key());
1908 SetAttribute(tagMaterial, AttrName, i.value());
1909
1910 element.appendChild(tagMaterial);
1911 ++i;
1912 }
1913 }
1914 }
1915
1916 //---------------------------------------------------------------------------------------------------------------------
GetFMeasurements(const QDomElement & element) const1917 QVector<VFinalMeasurement> VAbstractPattern::GetFMeasurements(const QDomElement &element) const
1918 {
1919 QVector<VFinalMeasurement> measurements;
1920
1921 if (not element.isNull())
1922 {
1923 QDomElement tagFMeasurement = element.firstChildElement();
1924 while (not tagFMeasurement.isNull())
1925 {
1926 if (tagFMeasurement.tagName() == TagFMeasurement)
1927 {
1928 VFinalMeasurement m;
1929
1930 m.name = GetParametrString(tagFMeasurement, AttrName, tr("measurement"));
1931 m.formula = GetParametrString(tagFMeasurement, AttrFormula, QChar('0'));
1932 m.description = GetParametrEmptyString(tagFMeasurement, AttrDescription);
1933
1934 measurements.append(m);
1935 }
1936 tagFMeasurement = tagFMeasurement.nextSiblingElement(TagFMeasurement);
1937 }
1938 }
1939
1940 return measurements;
1941 }
1942
1943 //---------------------------------------------------------------------------------------------------------------------
SetFMeasurements(QDomElement & element,const QVector<VFinalMeasurement> & measurements)1944 void VAbstractPattern::SetFMeasurements(QDomElement &element, const QVector<VFinalMeasurement> &measurements)
1945 {
1946 if (not element.isNull())
1947 {
1948 for (auto &m : measurements)
1949 {
1950 QDomElement tagFMeasurement = createElement(TagFMeasurement);
1951
1952 SetAttribute(tagFMeasurement, AttrName, m.name);
1953 SetAttribute(tagFMeasurement, AttrFormula, m.formula);
1954 SetAttributeOrRemoveIf(tagFMeasurement, AttrDescription, m.description, m.description.isEmpty());
1955
1956 element.appendChild(tagFMeasurement);
1957 }
1958 }
1959 }
1960
1961 //---------------------------------------------------------------------------------------------------------------------
1962 /**
1963 * @brief IsModified state of the document for cases that do not cover QUndoStack.
1964 * @return true if the document was modified without using QUndoStack.
1965 */
IsModified() const1966 bool VAbstractPattern::IsModified() const
1967 {
1968 return modified;
1969 }
1970
1971 //---------------------------------------------------------------------------------------------------------------------
SetModified(bool modified)1972 void VAbstractPattern::SetModified(bool modified)
1973 {
1974 this->modified = modified;
1975 }
1976
1977 //---------------------------------------------------------------------------------------------------------------------
GetDraw(const QString & name) const1978 QDomElement VAbstractPattern::GetDraw(const QString &name) const
1979 {
1980 const QDomNodeList draws = documentElement().elementsByTagName(TagDraw);
1981 for (int i=0; i < draws.size(); ++i)
1982 {
1983 QDomElement draw = draws.at(i).toElement();
1984 if (draw.isNull())
1985 {
1986 continue;
1987 }
1988
1989 if (draw.attribute(AttrName) == name)
1990 {
1991 return draw;
1992 }
1993 }
1994 return QDomElement();
1995 }
1996
1997 //---------------------------------------------------------------------------------------------------------------------
CreateGroups()1998 QDomElement VAbstractPattern::CreateGroups()
1999 {
2000 QDomElement draw;
2001 if (GetActivDrawElement(draw))
2002 {
2003 QDomElement groups = draw.firstChildElement(TagGroups);
2004
2005 if (groups.isNull())
2006 {
2007 groups = createElement(TagGroups);
2008 draw.appendChild(groups);
2009 }
2010
2011 return groups;
2012 }
2013 return QDomElement();
2014 }
2015
2016 //---------------------------------------------------------------------------------------------------------------------
CreateGroup(quint32 id,const QString & name,const QStringList & tags,const QMap<quint32,quint32> & groupData,vidtype tool)2017 QDomElement VAbstractPattern::CreateGroup(quint32 id, const QString &name, const QStringList &tags,
2018 const QMap<quint32, quint32> &groupData, vidtype tool)
2019 {
2020 if (id == NULL_ID || groupData.isEmpty())
2021 {
2022 return QDomElement();
2023 }
2024
2025 const QString preparedTags = PrepareGroupTags(tags);
2026
2027 QDomElement group = createElement(TagGroup);
2028 SetAttribute(group, AttrId, id);
2029 SetAttribute(group, AttrName, name);
2030 SetAttribute(group, AttrVisible, true);
2031 SetAttributeOrRemoveIf(group, AttrTool, tool, tool == null_id);
2032 SetAttributeOrRemoveIf(group, AttrTags, preparedTags, preparedTags.isEmpty());
2033
2034 auto i = groupData.constBegin();
2035 while (i != groupData.constEnd())
2036 {
2037 QDomElement item = createElement(TagGroupItem);
2038 item.setAttribute(AttrObject, i.key());
2039 item.setAttribute(AttrTool, i.value());
2040 group.appendChild(item);
2041 ++i;
2042 }
2043
2044 return group;
2045 }
2046 //---------------------------------------------------------------------------------------------------------------------
GroupLinkedToTool(vidtype toolId) const2047 vidtype VAbstractPattern::GroupLinkedToTool(vidtype toolId) const
2048 {
2049 const QDomNodeList groups = elementsByTagName(TagGroup);
2050 for (int i=0; i < groups.size(); ++i)
2051 {
2052 const QDomElement group = groups.at(i).toElement();
2053 if (not group.isNull() && group.hasAttribute(AttrTool))
2054 {
2055 const quint32 id = GetParametrUInt(group, AttrTool, NULL_ID_STR);
2056
2057 if (toolId == id)
2058 {
2059 return GetParametrUInt(group, AttrId, NULL_ID_STR);
2060 }
2061 }
2062 }
2063
2064 return null_id;
2065 }
2066
2067 //---------------------------------------------------------------------------------------------------------------------
GetGroupName(quint32 id)2068 QString VAbstractPattern::GetGroupName(quint32 id)
2069 {
2070 QString name = tr("New group");
2071 QDomElement group = elementById(id, TagGroup);
2072 if (group.isElement())
2073 {
2074 name = GetParametrString(group, AttrName, name);
2075
2076 }
2077
2078 return name;
2079 }
2080
2081 //---------------------------------------------------------------------------------------------------------------------
SetGroupName(quint32 id,const QString & name)2082 void VAbstractPattern::SetGroupName(quint32 id, const QString &name)
2083 {
2084 QDomElement group = elementById(id, TagGroup);
2085 if (group.isElement())
2086 {
2087 group.setAttribute(AttrName, name);
2088 modified = true;
2089 emit patternChanged(false);
2090 }
2091 }
2092
2093 //---------------------------------------------------------------------------------------------------------------------
GetGroupTags(vidtype id)2094 QStringList VAbstractPattern::GetGroupTags(vidtype id)
2095 {
2096 QStringList tags;
2097 QDomElement group = elementById(id, TagGroup);
2098 if (group.isElement())
2099 {
2100 tags = FilterGroupTags(GetParametrEmptyString(group, AttrTags));
2101 }
2102
2103 return tags;
2104 }
2105
2106 //---------------------------------------------------------------------------------------------------------------------
SetGroupTags(quint32 id,const QStringList & tags)2107 void VAbstractPattern::SetGroupTags(quint32 id, const QStringList &tags)
2108 {
2109 QDomElement group = elementById(id, TagGroup);
2110 if (group.isElement())
2111 {
2112 const QString rawTags = tags.join(',');
2113 SetAttributeOrRemoveIf(group, AttrTags, rawTags, rawTags.isEmpty());
2114 modified = true;
2115 emit patternChanged(false);
2116 }
2117 }
2118
2119 //---------------------------------------------------------------------------------------------------------------------
GetGroupCategories() const2120 QStringList VAbstractPattern::GetGroupCategories() const
2121 {
2122 QSet<QString> categories;
2123
2124 const QDomNodeList groups = elementsByTagName(TagGroup);
2125 for (int i=0; i < groups.size(); ++i)
2126 {
2127 const QDomElement group = groups.at(i).toElement();
2128 if (not group.isNull() && group.hasAttribute(AttrTags))
2129 {
2130 QStringList groupTags = VAbstractPattern::FilterGroupTags(GetParametrEmptyString(group, AttrTags));
2131 categories.unite(ConvertToSet<QString>(groupTags));
2132 }
2133 }
2134
2135 return ConvertToList(categories);
2136 }
2137
2138 //---------------------------------------------------------------------------------------------------------------------
GetGroups()2139 QMap<quint32, VGroupData> VAbstractPattern::GetGroups()
2140 {
2141 QMap<quint32, VGroupData> data;
2142
2143 try
2144 {
2145 QDomElement groups = CreateGroups();
2146 if (not groups.isNull())
2147 {
2148 QDomNode domNode = groups.firstChild();
2149 while (domNode.isNull() == false)
2150 {
2151 if (domNode.isElement())
2152 {
2153 const QDomElement group = domNode.toElement();
2154 if (group.isNull() == false)
2155 {
2156 if (group.tagName() == TagGroup)
2157 {
2158 VGroupData groupData;
2159 const quint32 id = GetParametrUInt(group, AttrId, QChar('0'));
2160 groupData.visible = GetParametrBool(group, AttrVisible, trueStr);
2161 groupData.name = GetParametrString(group, AttrName, tr("New group"));
2162 groupData.tags = FilterGroupTags(GetParametrEmptyString(group, AttrTags));
2163
2164 data.insert(id, groupData);
2165 }
2166 }
2167 }
2168 domNode = domNode.nextSibling();
2169 }
2170 }
2171 else
2172 {
2173 qDebug("Can't get tag Groups.");
2174 }
2175 }
2176 catch (const VExceptionConversionError &)
2177 {
2178 return QMap<quint32, VGroupData>();
2179 }
2180
2181 return data;
2182 }
2183
2184 //---------------------------------------------------------------------------------------------------------------------
2185 /**
2186 * @brief Returns the groups that contain or do not contain the item identified by the toolid and the objectid
2187 * @param toolId tool id
2188 * @param objectId object id
2189 * @param containItem |true if the groups have to contain the given item, false if they musn't contain the item
2190 * @return groups that contain or do not contain the item identified by the toolid and the objectid
2191 */
GetGroupsContainingItem(quint32 toolId,quint32 objectId,bool containItem)2192 QMap<quint32, QString> VAbstractPattern::GetGroupsContainingItem(quint32 toolId, quint32 objectId, bool containItem)
2193 {
2194 QMap<quint32, QString> data;
2195
2196 if(objectId == 0)
2197 {
2198 objectId = toolId;
2199 }
2200
2201 // TODO : order in alphabetical order
2202
2203 QDomElement groups = CreateGroups();
2204 if (not groups.isNull())
2205 {
2206 QDomNode domNode = groups.firstChild();
2207 while (domNode.isNull() == false) // iterate through the groups
2208 {
2209 if (domNode.isElement())
2210 {
2211 const QDomElement group = domNode.toElement();
2212 if (group.isNull() == false)
2213 {
2214 if (group.tagName() == TagGroup)
2215 {
2216 bool groupHasItem = GroupHasItem(group, toolId, objectId);
2217 if((containItem && groupHasItem) || (not containItem && not groupHasItem))
2218 {
2219 const quint32 groupId = GetParametrUInt(group, AttrId, QChar('0'));
2220 const QString name = GetParametrString(group, AttrName, tr("New group"));
2221 data.insert(groupId, name);
2222 }
2223 }
2224 }
2225 }
2226 domNode = domNode.nextSibling();
2227 }
2228 }
2229 else
2230 {
2231 qDebug("Can't get tag Groups.");
2232 }
2233
2234 return data;
2235 }
2236 //---------------------------------------------------------------------------------------------------------------------
2237 /**
2238 * @brief Checks if the given group has the item with the given toolId and objectId
2239 * @param groupDomElement group dom element
2240 * @param toolId tool id
2241 * @param objectId object id
2242 * @return true if the given group has the item with the given toolId and objectId
2243 */
GroupHasItem(const QDomElement & groupDomElement,quint32 toolId,quint32 objectId)2244 bool VAbstractPattern::GroupHasItem(const QDomElement &groupDomElement, quint32 toolId, quint32 objectId)
2245 {
2246 bool result = false;
2247
2248 QDomNode itemNode = groupDomElement.firstChild();
2249 while (itemNode.isNull() == false) // iterate through the items of the group
2250 {
2251 if (itemNode.isElement())
2252 {
2253 const QDomElement item = itemNode.toElement();
2254 if (item.isNull() == false)
2255 {
2256 quint32 toolIdIterate= GetParametrUInt(item, AttrTool, QChar('0'));
2257 quint32 objectIdIterate= GetParametrUInt(item, AttrObject, QChar('0'));
2258
2259 if(toolIdIterate == toolId && objectIdIterate == objectId)
2260 {
2261 result = true;
2262 break;
2263 }
2264 }
2265 }
2266 itemNode = itemNode.nextSibling();
2267 }
2268 return result;
2269 }
2270
2271 //---------------------------------------------------------------------------------------------------------------------
ReadUnits() const2272 auto VAbstractPattern::ReadUnits() const -> Unit
2273 {
2274 Unit units = StrToUnits(UniqueTagText(TagUnit, unitCM));
2275
2276 if (units == Unit::Px)
2277 {
2278 units = Unit::Cm;
2279 }
2280
2281 return units;
2282 }
2283
2284 //---------------------------------------------------------------------------------------------------------------------
ReadPatternNumber() const2285 QString VAbstractPattern::ReadPatternNumber() const
2286 {
2287 return UniqueTagText(TagPatternNum);
2288 }
2289
2290 //---------------------------------------------------------------------------------------------------------------------
ReadLabelDateFormat() const2291 QString VAbstractPattern::ReadLabelDateFormat() const
2292 {
2293 const QString globalLabelDateFormat = VAbstractApplication::VApp()->Settings()->GetLabelDateFormat();
2294
2295 const QDomNodeList list = elementsByTagName(TagPatternLabel);
2296 if (list.isEmpty())
2297 {
2298 return globalLabelDateFormat;
2299 }
2300
2301 QString labelDateFormat;
2302
2303 try
2304 {
2305 labelDateFormat = GetParametrString(list.at(0).toElement(), AttrDateFormat);
2306 }
2307 catch (const VExceptionEmptyParameter &)
2308 {
2309 return globalLabelDateFormat;
2310 }
2311 return labelDateFormat;
2312 }
2313
2314 //---------------------------------------------------------------------------------------------------------------------
ReadPatternName() const2315 QString VAbstractPattern::ReadPatternName() const
2316 {
2317 return UniqueTagText(TagPatternName);
2318 }
2319
2320 //---------------------------------------------------------------------------------------------------------------------
ReadMPath() const2321 QString VAbstractPattern::ReadMPath() const
2322 {
2323 return UniqueTagText(TagMeasurements);
2324 }
2325
2326 //---------------------------------------------------------------------------------------------------------------------
ReadWatermarkPath() const2327 QString VAbstractPattern::ReadWatermarkPath() const
2328 {
2329 return UniqueTagText(TagWatermark);
2330 }
2331
2332 //---------------------------------------------------------------------------------------------------------------------
ReadCompanyName() const2333 QString VAbstractPattern::ReadCompanyName() const
2334 {
2335 return UniqueTagText(TagCompanyName);
2336 }
2337
2338 //---------------------------------------------------------------------------------------------------------------------
2339 /**
2340 * @brief Adds an item to the given group with the given toolId and objectId
2341 * @param toolId tool id
2342 * @param objectId object id
2343 * @param groupId group id
2344 * @return group element
2345 */
AddItemToGroup(quint32 toolId,quint32 objectId,quint32 groupId)2346 QDomElement VAbstractPattern::AddItemToGroup(quint32 toolId, quint32 objectId, quint32 groupId)
2347 {
2348 QDomElement group = elementById(groupId, TagGroup);
2349
2350 if (group.isNull() == false)
2351 {
2352 if(objectId == 0)
2353 {
2354 objectId = toolId;
2355 }
2356
2357 QDomElement item = createElement(TagGroupItem);
2358 item.setAttribute(AttrTool, toolId);
2359 item.setAttribute(AttrObject, objectId);
2360 group.appendChild(item);
2361
2362 // to signalised that the pattern was changed and need to be saved
2363 modified = true;
2364 emit patternChanged(false);
2365
2366 // to update the group table of the gui
2367 emit UpdateGroups();
2368
2369 // parse the groups to update the drawing, in case the item was added to an invisible group
2370 QDomElement groups = CreateGroups();
2371 if (not groups.isNull())
2372 {
2373 ParseGroups(groups);
2374 }
2375
2376 return item;
2377 }
2378 else
2379 {
2380 qDebug() << "The group of id " << groupId << " doesn't exist";
2381 }
2382
2383 return QDomElement();
2384 }
2385
2386 //---------------------------------------------------------------------------------------------------------------------
2387 /**
2388 * @brief Removes the item of given toolId and objectId from the group of given groupId
2389 * @param toolId tool id
2390 * @param objectId object id
2391 * @param groupId group id
2392 * @return item element or null element is none
2393 */
RemoveItemFromGroup(quint32 toolId,quint32 objectId,quint32 groupId)2394 QDomElement VAbstractPattern::RemoveItemFromGroup(quint32 toolId, quint32 objectId, quint32 groupId)
2395 {
2396 QDomElement group = elementById(groupId, TagGroup);
2397
2398 if (group.isNull() == false)
2399 {
2400 if(objectId == 0)
2401 {
2402 objectId = toolId;
2403 }
2404
2405 QDomNode itemNode = group.firstChild();
2406 while (itemNode.isNull() == false) // iterate through the items of the group
2407 {
2408 if (itemNode.isElement())
2409 {
2410 const QDomElement item = itemNode.toElement();
2411 if (item.isNull() == false)
2412 {
2413 quint32 toolIdIterate= GetParametrUInt(item, AttrTool, QChar('0'));
2414 quint32 objectIdIterate= GetParametrUInt(item, AttrObject, QChar('0'));
2415
2416 if(toolIdIterate == toolId && objectIdIterate == objectId)
2417 {
2418 group.removeChild(itemNode);
2419
2420 // to signalised that the pattern was changed and need to be saved
2421 modified = true;
2422 emit patternChanged(false);
2423
2424 // to update the group table of the gui
2425 emit UpdateGroups();
2426
2427 // parse the groups to update the drawing, in case the item was removed from an invisible group
2428 QDomElement groups = CreateGroups();
2429 if (not groups.isNull())
2430 {
2431 ParseGroups(groups);
2432 }
2433
2434 return item;
2435 }
2436 }
2437 }
2438 itemNode = itemNode.nextSibling();
2439 }
2440 }
2441 else
2442 {
2443 qDebug() << "The group of id " << groupId << " doesn't exist";
2444 }
2445
2446 return QDomElement();
2447 }
2448
2449 //---------------------------------------------------------------------------------------------------------------------
2450 /**
2451 * @brief Returns true if the given group is empty
2452 * @param id group id
2453 * @return true if the given group is empty
2454 */
GroupIsEmpty(quint32 id)2455 bool VAbstractPattern::GroupIsEmpty(quint32 id)
2456 {
2457 QDomElement group = elementById(id, TagGroup);
2458
2459 if (group.isNull() == false)
2460 {
2461 return not group.hasChildNodes();
2462 }
2463 else
2464 {
2465 qDebug() << "The group of id " << id << " doesn't exist";
2466 return true;
2467 }
2468 }
2469
2470 //---------------------------------------------------------------------------------------------------------------------
GetGroupVisibility(quint32 id)2471 bool VAbstractPattern::GetGroupVisibility(quint32 id)
2472 {
2473 QDomElement group = elementById(id, TagGroup);
2474 if (group.isElement())
2475 {
2476 return GetParametrBool(group, AttrVisible, trueStr);
2477 }
2478 else
2479 {
2480 qDebug("Can't get group by id = %u.", id);
2481 return true;
2482 }
2483 }
2484
2485 //---------------------------------------------------------------------------------------------------------------------
PieceDrawName(quint32 id)2486 QString VAbstractPattern::PieceDrawName(quint32 id)
2487 {
2488 const QDomElement detail = elementById(id, VAbstractPattern::TagDetail);
2489 if (detail.isNull())
2490 {
2491 return QString();
2492 }
2493
2494 const QDomElement draw = detail.parentNode().parentNode().toElement();
2495 if (draw.isNull() || not draw.hasAttribute(VAbstractPattern::AttrName))
2496 {
2497 return QString();
2498 }
2499
2500 return draw.attribute(VAbstractPattern::AttrName);
2501 }
2502
2503 //---------------------------------------------------------------------------------------------------------------------
GetCompleteData() const2504 VContainer VAbstractPattern::GetCompleteData() const
2505 {
2506 return VContainer(nullptr, nullptr, VContainer::UniqueNamespace());
2507 }
2508
2509 //---------------------------------------------------------------------------------------------------------------------
GetCompletePPData(const QString & name) const2510 VContainer VAbstractPattern::GetCompletePPData(const QString &name) const
2511 {
2512 Q_UNUSED(name)
2513 return VContainer(nullptr, nullptr, VContainer::UniqueNamespace());
2514 }
2515
2516 //---------------------------------------------------------------------------------------------------------------------
Units() const2517 Unit VAbstractPattern::Units() const
2518 {
2519 return m_units;
2520 }
2521
2522 //---------------------------------------------------------------------------------------------------------------------
FilterGroupTags(const QString & tags)2523 QStringList VAbstractPattern::FilterGroupTags(const QString &tags)
2524 {
2525 if (tags.isEmpty())
2526 {
2527 return QStringList();
2528 }
2529
2530 QStringList list = tags.split(',');
2531 for (auto &tag : list)
2532 {
2533 tag = tag.simplified();
2534 }
2535
2536 list.removeAll("");
2537
2538 return ConvertToList(ConvertToSet<QString>(list));
2539 }
2540