Seamly2D
Code documentation
vvitconverter.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * *
3  * Copyright (C) 2017 Seamly, LLC *
4  * *
5  * https://github.com/fashionfreedom/seamly2d *
6  * *
7  ***************************************************************************
8  **
9  ** Seamly2D is free software: you can redistribute it and/or modify
10  ** it under the terms of the GNU General Public License as published by
11  ** the Free Software Foundation, either version 3 of the License, or
12  ** (at your option) any later version.
13  **
14  ** Seamly2D is distributed in the hope that it will be useful,
15  ** but WITHOUT ANY WARRANTY; without even the implied warranty of
16  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  ** GNU General Public License for more details.
18  **
19  ** You should have received a copy of the GNU General Public License
20  ** along with Seamly2D. If not, see <http://www.gnu.org/licenses/>.
21  **
22  **************************************************************************
23 
24  ************************************************************************
25  **
26  ** @file vvitconverter.cpp
27  ** @author Roman Telezhynskyi <dismine(at)gmail.com>
28  ** @date 15 7, 2015
29  **
30  ** @brief
31  ** @copyright
32  ** This source code is part of the Valentine project, a pattern making
33  ** program, whose allow create and modeling patterns of clothing.
34  ** Copyright (C) 2015 Seamly2D project
35  ** <https://github.com/fashionfreedom/seamly2d> All Rights Reserved.
36  **
37  ** Seamly2D is free software: you can redistribute it and/or modify
38  ** it under the terms of the GNU General Public License as published by
39  ** the Free Software Foundation, either version 3 of the License, or
40  ** (at your option) any later version.
41  **
42  ** Seamly2D is distributed in the hope that it will be useful,
43  ** but WITHOUT ANY WARRANTY; without even the implied warranty of
44  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
45  ** GNU General Public License for more details.
46  **
47  ** You should have received a copy of the GNU General Public License
48  ** along with Seamly2D. If not, see <http://www.gnu.org/licenses/>.
49  **
50  *************************************************************************/
51 
52 #include "vvitconverter.h"
53 
54 #include <QDomNode>
55 #include <QDomNodeList>
56 #include <QDomText>
57 #include <QFile>
58 #include <QLatin1String>
59 #include <QList>
60 #include <QMap>
61 #include <QMultiMap>
62 #include <QStaticStringData>
63 #include <QStringData>
64 #include <QStringDataPtr>
65 
66 #include "../exception/vexception.h"
67 #include "../vmisc/def.h"
68 #include "vabstractmconverter.h"
69 
70 /*
71  * Version rules:
72  * 1. Version have three parts "major.minor.patch";
73  * 2. major part only for stable releases;
74  * 3. minor - 10 or more patch changes, or one big change;
75  * 4. patch - little change.
76  */
77 
78 const QString VVITConverter::MeasurementMinVerStr = QStringLiteral("0.2.0");
79 const QString VVITConverter::MeasurementMaxVerStr = QStringLiteral("0.3.3");
80 const QString VVITConverter::CurrentSchema = QStringLiteral("://schema/individual_measurements/v0.3.3.xsd");
81 
82 //VVITConverter::MeasurementMinVer; // <== DON'T FORGET TO UPDATE TOO!!!!
83 //VVITConverter::MeasurementMaxVer; // <== DON'T FORGET TO UPDATE TOO!!!!
84 
85 static const QString strTagRead_Only = QStringLiteral("read-only");
86 
87 //---------------------------------------------------------------------------------------------------------------------
88 VVITConverter::VVITConverter(const QString &fileName)
89  :VAbstractMConverter(fileName)
90 {
92 }
93 
94 //---------------------------------------------------------------------------------------------------------------------
95 QString VVITConverter::XSDSchema(int ver) const
96 {
97  switch (ver)
98  {
99  case (0x000200):
100  return QStringLiteral("://schema/individual_measurements/v0.2.0.xsd");
101  case (0x000300):
102  return QStringLiteral("://schema/individual_measurements/v0.3.0.xsd");
103  case (0x000301):
104  return QStringLiteral("://schema/individual_measurements/v0.3.1.xsd");
105  case (0x000302):
106  return QStringLiteral("://schema/individual_measurements/v0.3.2.xsd");
107  case (0x000303):
108  return CurrentSchema;
109  default:
110  InvalidVersion(ver);
111  break;
112  }
113  return QString();//unreachable code
114 }
115 
116 //---------------------------------------------------------------------------------------------------------------------
118 {
119  switch (m_ver)
120  {
121  case (0x000200):
122  ToV0_3_0();
125  case (0x000300):
126  ToV0_3_1();
129  case (0x000301):
130  ToV0_3_2();
133  case (0x000302):
134  ToV0_3_3();
137  case (0x000303):
138  break;
139  default:
141  break;
142  }
143 }
144 
145 //---------------------------------------------------------------------------------------------------------------------
147 {
149  Save();
150 }
151 
152 //---------------------------------------------------------------------------------------------------------------------
154 {
155  // Check if attribute read-only was not changed in file format
156  Q_STATIC_ASSERT_X(VVITConverter::MeasurementMaxVer == CONVERTER_VERSION_CHECK(0, 3, 3),
157  "Check attribute read-only.");
158 
159  // Possibly in future attribute read-only will change position etc.
160  // For now position is the same for all supported format versions.
161  // But don't forget to keep all versions of attribute until we support that format versions
162 
164 }
165 
166 //---------------------------------------------------------------------------------------------------------------------
168 {
169  // TODO. Delete if minimal supported version is 0.3.0
170  Q_STATIC_ASSERT_X(VVITConverter::MeasurementMinVer < CONVERTER_VERSION_CHECK(0, 3, 0),
171  "Time to refactor the code.");
172 
173  QDomElement rootElement = this->documentElement();
174  QDomNode refChild = rootElement.firstChildElement("version");
175 
176  QDomElement ro = createElement(QStringLiteral("read-only"));
177  const QDomText roNodeText = createTextNode("false");
178  ro.appendChild(roNodeText);
179  refChild = rootElement.insertAfter(ro, refChild);
180 
181  refChild = rootElement.insertAfter(createElement(QStringLiteral("notes")), refChild);
182 
183  QDomElement unit = createElement("unit");
184  unit.appendChild(createTextNode(MUnitV0_2_0()));
185  rootElement.insertAfter(unit, refChild);
186 }
187 
188 //---------------------------------------------------------------------------------------------------------------------
190 {
191  // TODO. Delete if minimal supported version is 0.3.0
192  Q_STATIC_ASSERT_X(VVITConverter::MeasurementMinVer < CONVERTER_VERSION_CHECK(0, 3, 0),
193  "Time to refactor the code.");
194 
195  return UniqueTagText(QStringLiteral("unit"), QStringLiteral("cm"));
196 }
197 
198 //---------------------------------------------------------------------------------------------------------------------
200 {
201  // TODO. Delete if minimal supported version is 0.3.0
202  Q_STATIC_ASSERT_X(VVITConverter::MeasurementMinVer < CONVERTER_VERSION_CHECK(0, 3, 0),
203  "Time to refactor the code.");
204 
205  const QString tagBM = QStringLiteral("body-measurements");
206 
207  QDomElement bm = createElement(tagBM);
208 
209  const QMultiMap<QString, QString> names = OldNamesToNewNames_InV0_3_0();
210  const QList<QString> keys = names.uniqueKeys();
211  for (int i = 0; i < keys.size(); ++i)
212  {
213  qreal resValue = 0;
214 
215  // This has the same effect as a .values(), just isn't as elegant
216  const QList<QString> list = names.values( keys.at(i) );
217  foreach(const QString &val, list )
218  {
219  const QDomNodeList nodeList = this->elementsByTagName(val);
220  if (nodeList.isEmpty())
221  {
222  continue;
223  }
224 
225  const qreal value = GetParametrDouble(nodeList.at(0).toElement(), QStringLiteral("value"), "0.0");
226 
227  if (not qFuzzyIsNull(value))
228  {
229  resValue = value;
230  }
231  }
232 
233  bm.appendChild(AddMV0_3_0(keys.at(i), resValue));
234  }
235 
236  QDomElement rootElement = this->documentElement();
237  const QDomNodeList listBM = elementsByTagName(tagBM);
238  rootElement.replaceChild(bm, listBM.at(0));
239 }
240 
241 //---------------------------------------------------------------------------------------------------------------------
242 QDomElement VVITConverter::AddMV0_3_0(const QString &name, qreal value)
243 {
244  // TODO. Delete if minimal supported version is 0.3.0
245  Q_STATIC_ASSERT_X(VVITConverter::MeasurementMinVer < CONVERTER_VERSION_CHECK(0, 3, 0),
246  "Time to refactor the code.");
247 
248  QDomElement element = createElement(QStringLiteral("m"));
249 
250  SetAttribute(element, QStringLiteral("name"), name);
251  SetAttribute(element, QStringLiteral("value"), QString().setNum(value));
252  SetAttribute(element, QStringLiteral("description"), QString(""));
253  SetAttribute(element, QStringLiteral("full_name"), QString(""));
254 
255  return element;
256 }
257 
258 //---------------------------------------------------------------------------------------------------------------------
260 {
261  // TODO. Delete if minimal supported version is 0.3.1
262  Q_STATIC_ASSERT_X(VVITConverter::MeasurementMinVer < CONVERTER_VERSION_CHECK(0, 3, 1),
263  "Time to refactor the code.");
264 
265  const QDomNodeList nodeList = this->elementsByTagName(QStringLiteral("sex"));
266  QDomElement sex = nodeList.at(0).toElement();
267 
268  QDomElement gender = createElement(QStringLiteral("gender"));
269  gender.appendChild(createTextNode(sex.text()));
270 
271  QDomElement parent = sex.parentNode().toElement();
272  parent.replaceChild(gender, sex);
273 }
274 
275 //---------------------------------------------------------------------------------------------------------------------
277 {
278  // TODO. Delete if minimal supported version is 0.3.2
279  Q_STATIC_ASSERT_X(VVITConverter::MeasurementMinVer < CONVERTER_VERSION_CHECK(0, 3, 2),
280  "Time to refactor the code.");
281 
282  QDomElement pm_system = createElement(QStringLiteral("pm_system"));
283  pm_system.appendChild(createTextNode(QStringLiteral("998")));
284 
285  const QDomNodeList nodeList = this->elementsByTagName(QStringLiteral("personal"));
286  QDomElement personal = nodeList.at(0).toElement();
287 
288  QDomElement parent = personal.parentNode().toElement();
289  parent.insertBefore(pm_system, personal);
290 }
291 
292 //---------------------------------------------------------------------------------------------------------------------
294 {
295  // TODO. Delete if minimal supported version is 0.3.3
296  Q_STATIC_ASSERT_X(VVITConverter::MeasurementMinVer < CONVERTER_VERSION_CHECK(0, 3, 3),
297  "Time to refactor the code.");
298 
300  auto i = names.constBegin();
301  while (i != names.constEnd())
302  {
303  const QDomNodeList nodeList = this->elementsByTagName(QStringLiteral("m"));
304  if (nodeList.isEmpty())
305  {
306  ++i;
307  continue;
308  }
309 
310  for (int ii = 0; ii < nodeList.size(); ++ii)
311  {
312  const QString attrName = QStringLiteral("name");
313  QDomElement element = nodeList.at(ii).toElement();
314  const QString name = GetParametrString(element, attrName);
315  if (name == i.value())
316  {
317  SetAttribute(element, attrName, i.key());
318  }
319  }
320 
321  ++i;
322  }
323 }
324 
325 //---------------------------------------------------------------------------------------------------------------------
327 {
328  // TODO. Delete if minimal supported version is 0.3.0
329  Q_STATIC_ASSERT_X(VVITConverter::MeasurementMinVer < CONVERTER_VERSION_CHECK(0, 3, 0),
330  "Time to refactor the code.");
331 
332  AddRootComment();
333  SetVersion(QStringLiteral("0.3.0"));
336  Save();
337 }
338 
339 //---------------------------------------------------------------------------------------------------------------------
341 {
342  // TODO. Delete if minimal supported version is 0.3.1
343  Q_STATIC_ASSERT_X(VVITConverter::MeasurementMinVer < CONVERTER_VERSION_CHECK(0, 3, 1),
344  "Time to refactor the code.");
345 
346  SetVersion(QStringLiteral("0.3.1"));
347  GenderV0_3_1();
348  Save();
349 }
350 
351 //---------------------------------------------------------------------------------------------------------------------
353 {
354  // TODO. Delete if minimal supported version is 0.3.2
355  Q_STATIC_ASSERT_X(VVITConverter::MeasurementMinVer < CONVERTER_VERSION_CHECK(0, 3, 2),
356  "Time to refactor the code.");
357 
358  SetVersion(QStringLiteral("0.3.2"));
359  PM_SystemV0_3_2();
360  Save();
361 }
362 
363 //---------------------------------------------------------------------------------------------------------------------
365 {
366  // TODO. Delete if minimal supported version is 0.3.3
367  Q_STATIC_ASSERT_X(VVITConverter::MeasurementMinVer < CONVERTER_VERSION_CHECK(0, 3, 3),
368  "Time to refactor the code.");
369 
370  SetVersion(QStringLiteral("0.3.3"));
372  Save();
373 }
void SetVersion(const QString &version)
Q_NORETURN void InvalidVersion(int ver) const
void ValidateInputFile(const QString &currentSchema) const
static QMap< QString, QString > OldNamesToNewNames_InV0_3_3()
static QMultiMap< QString, QString > OldNamesToNewNames_InV0_3_0()
static QString GetParametrString(const QDomElement &domElement, const QString &name, const QString &defValue=QString())
Returns the string value of the given attribute. RENAME: see above.
static void ValidateXML(const QString &schema, const QString &fileName)
ValidateXML validate xml file by xsd schema.
static qreal GetParametrDouble(const QDomElement &domElement, const QString &name, const QString &defValue)
Returns the double value of the given attribute.
QString UniqueTagText(const QString &tagName, const QString &defVal=QString()) const
void SetAttribute(QDomElement &domElement, const QString &name, const T &value) const
SetAttribute set attribute in pattern file. Replace "," by ".".
Definition: vdomdocument.h:185
virtual void DowngradeToCurrentMaxVersion() Q_DECL_OVERRIDE
static Q_DECL_CONSTEXPR const int MeasurementMinVer
Definition: vvitconverter.h:79
void ConvertMeasurementsToV0_3_3()
virtual void ApplyPatches() Q_DECL_OVERRIDE
void AddNewTagsForV0_3_0()
static const QString MeasurementMaxVerStr
Definition: vvitconverter.h:72
QString MUnitV0_2_0()
void PM_SystemV0_3_2()
void ConvertMeasurementsToV0_3_0()
QDomElement AddMV0_3_0(const QString &name, qreal value)
virtual QString XSDSchema(int ver) const Q_DECL_OVERRIDE
VVITConverter(const QString &fileName)
virtual bool IsReadOnly() const Q_DECL_OVERRIDE
static const QString CurrentSchema
Definition: vvitconverter.h:73
static Q_DECL_CONSTEXPR const int MeasurementMaxVer
Definition: vvitconverter.h:80
static const QString MeasurementMinVerStr
Definition: vvitconverter.h:97
const QString trueStr
Definition: def.cpp:197
const QString falseStr
Definition: def.cpp:198
#define V_FALLTHROUGH
Definition: def.h:351
#define CONVERTER_VERSION_CHECK(major, minor, patch)
static const QString strTagRead_Only