Seamly2D
Code documentation
vvstconverter.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 VVSTConverter.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 "vvstconverter.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 VVSTConverter::MeasurementMinVerStr = QStringLiteral("0.3.0");
79 const QString VVSTConverter::MeasurementMaxVerStr = QStringLiteral("0.4.4");
80 const QString VVSTConverter::CurrentSchema = QStringLiteral("://schema/standard_measurements/v0.4.4.xsd");
81 
82 //VVSTConverter::MeasurementMinVer; // <== DON'T FORGET TO UPDATE TOO!!!!
83 //VVSTConverter::MeasurementMaxVer; // <== DON'T FORGET TO UPDATE TOO!!!!
84 
85 static const QString strTagRead_Only = QStringLiteral("read-only");
86 
87 //---------------------------------------------------------------------------------------------------------------------
88 VVSTConverter::VVSTConverter(const QString &fileName)
89  :VAbstractMConverter(fileName)
90 {
92 }
93 
94 //---------------------------------------------------------------------------------------------------------------------
95 QString VVSTConverter::XSDSchema(int ver) const
96 {
97  switch (ver)
98  {
99  case (0x000300):
100  return QStringLiteral("://schema/standard_measurements/v0.3.0.xsd");
101  case (0x000400):
102  return QStringLiteral("://schema/standard_measurements/v0.4.0.xsd");
103  case (0x000401):
104  return QStringLiteral("://schema/standard_measurements/v0.4.1.xsd");
105  case (0x000402):
106  return QStringLiteral("://schema/standard_measurements/v0.4.2.xsd");
107  case (0x000403):
108  return QStringLiteral("://schema/standard_measurements/v0.4.3.xsd");
109  case (0x000404):
110  return CurrentSchema;
111  default:
112  InvalidVersion(ver);
113  break;
114  }
115  return QString();//unreachable code
116 }
117 
118 //---------------------------------------------------------------------------------------------------------------------
120 {
121  switch (m_ver)
122  {
123  case (0x000300):
124  ToV0_4_0();
127  case (0x000400):
128  ToV0_4_1();
131  case (0x000401):
132  ToV0_4_2();
135  case (0x000402):
136  ToV0_4_3();
139  case (0x000403):
140  ToV0_4_4();
143  case (0x000404):
144  break;
145  default:
147  break;
148  }
149 }
150 
151 //---------------------------------------------------------------------------------------------------------------------
153 {
155  Save();
156 }
157 
158 //---------------------------------------------------------------------------------------------------------------------
160 {
161  // Check if attribute read-only was not changed in file format
162  Q_STATIC_ASSERT_X(VVSTConverter::MeasurementMaxVer == CONVERTER_VERSION_CHECK(0, 4, 4),
163  "Check attribute read-only.");
164 
165  // Possibly in future attribute read-only will change position etc.
166  // For now position is the same for all supported format versions.
167  // But don't forget to keep all versions of attribute until we support that format versions
168 
170 }
171 
172 //---------------------------------------------------------------------------------------------------------------------
174 {
175  // TODO. Delete if minimal supported version is 0.4.0
176  Q_STATIC_ASSERT_X(VVSTConverter::MeasurementMinVer < CONVERTER_VERSION_CHECK(0, 4, 0),
177  "Time to refactor the code.");
178 
179  QDomElement rootElement = this->documentElement();
180  QDomNode refChild = rootElement.firstChildElement("version");
181 
182  {
183  QDomElement ro = createElement(QStringLiteral("read-only"));
184  const QDomText roNodeText = createTextNode("false");
185  ro.appendChild(roNodeText);
186  refChild = rootElement.insertAfter(ro, refChild);
187  }
188 
189  {
190  QDomElement notes = createElement(QStringLiteral("notes"));
191  const QDomText nodeText = createTextNode(UniqueTagText(QStringLiteral("description")));
192  notes.appendChild(nodeText);
193  rootElement.insertAfter(notes, refChild);
194  }
195 }
196 
197 //---------------------------------------------------------------------------------------------------------------------
199 {
200  // TODO. Delete if minimal supported version is 0.4.0
201  Q_STATIC_ASSERT_X(VVSTConverter::MeasurementMinVer < CONVERTER_VERSION_CHECK(0, 4, 0),
202  "Time to refactor the code.");
203 
204  QDomElement rootElement = this->documentElement();
205 
206  {
207  const QDomNodeList nodeList = this->elementsByTagName(QStringLiteral("description"));
208  if (not nodeList.isEmpty())
209  {
210  rootElement.removeChild(nodeList.at(0));
211  }
212  }
213 
214  {
215  const QDomNodeList nodeList = this->elementsByTagName(QStringLiteral("id"));
216  if (not nodeList.isEmpty())
217  {
218  rootElement.removeChild(nodeList.at(0));
219  }
220  }
221 }
222 
223 //---------------------------------------------------------------------------------------------------------------------
225 {
226  // TODO. Delete if minimal supported version is 0.4.0
227  Q_STATIC_ASSERT_X(VVSTConverter::MeasurementMinVer < CONVERTER_VERSION_CHECK(0, 4, 0),
228  "Time to refactor the code.");
229 
230  const QString tagBM = QStringLiteral("body-measurements");
231 
232  QDomElement bm = createElement(tagBM);
233 
234  const QMultiMap<QString, QString> names = OldNamesToNewNames_InV0_3_0();
235  const QList<QString> keys = names.uniqueKeys();
236  for (int i = 0; i < keys.size(); ++i)
237  {
238  qreal resValue = 0;
239  qreal resSizeIncrease = 0;
240  qreal resHeightIncrease = 0;
241 
242  // This has the same effect as a .values(), just isn't as elegant
243  const QList<QString> list = names.values( keys.at(i) );
244  foreach(const QString &val, list )
245  {
246  const QDomNodeList nodeList = this->elementsByTagName(val);
247  if (nodeList.isEmpty())
248  {
249  continue;
250  }
251 
252  QDomElement m = nodeList.at(0).toElement();
253  const qreal value = GetParametrDouble(m, QStringLiteral("value"), "0.0");
254  const qreal size_increase = GetParametrDouble(m, QStringLiteral("size_increase"), "0.0");
255  const qreal height_increase = GetParametrDouble(m, QStringLiteral("height_increase"), "0.0");
256 
257  if (not qFuzzyIsNull(value))
258  {
259  resValue = value;
260  resSizeIncrease = size_increase;
261  resHeightIncrease = height_increase;
262  }
263  }
264 
265  bm.appendChild(AddMV0_4_0(keys.at(i), resValue, resSizeIncrease, resHeightIncrease));
266  }
267 
268  QDomElement rootElement = this->documentElement();
269  const QDomNodeList listBM = elementsByTagName(tagBM);
270  rootElement.replaceChild(bm, listBM.at(0));
271 }
272 
273 //---------------------------------------------------------------------------------------------------------------------
274 QDomElement VVSTConverter::AddMV0_4_0(const QString &name, qreal value, qreal sizeIncrease, qreal heightIncrease)
275 {
276  // TODO. Delete if minimal supported version is 0.4.0
277  Q_STATIC_ASSERT_X(VVSTConverter::MeasurementMinVer < CONVERTER_VERSION_CHECK(0, 4, 0),
278  "Time to refactor the code.");
279 
280  QDomElement element = createElement(QStringLiteral("m"));
281 
282  SetAttribute(element, QStringLiteral("name"), name);
283  SetAttribute(element, QStringLiteral("base"), QString().setNum(value));
284  SetAttribute(element, QStringLiteral("size_increase"), QString().setNum(sizeIncrease));
285  SetAttribute(element, QStringLiteral("height_increase"), QString().setNum(heightIncrease));
286  SetAttribute(element, QStringLiteral("description"), QString(""));
287  SetAttribute(element, QStringLiteral("full_name"), QString(""));
288 
289  return element;
290 }
291 
292 //---------------------------------------------------------------------------------------------------------------------
294 {
295  // TODO. Delete if minimal supported version is 0.4.1
296  Q_STATIC_ASSERT_X(VVSTConverter::MeasurementMinVer < CONVERTER_VERSION_CHECK(0, 4, 1),
297  "Time to refactor the code.");
298 
299  QDomElement pm_system = createElement(QStringLiteral("pm_system"));
300  pm_system.appendChild(createTextNode(QStringLiteral("998")));
301 
302  const QDomNodeList nodeList = this->elementsByTagName(QStringLiteral("size"));
303  QDomElement personal = nodeList.at(0).toElement();
304 
305  QDomElement parent = personal.parentNode().toElement();
306  parent.insertBefore(pm_system, personal);
307 }
308 
309 //---------------------------------------------------------------------------------------------------------------------
311 {
312  // TODO. Delete if minimal supported version is 0.4.2
313  Q_STATIC_ASSERT_X(VVSTConverter::MeasurementMinVer < CONVERTER_VERSION_CHECK(0, 4, 2),
314  "Time to refactor the code.");
315 
317  auto i = names.constBegin();
318  while (i != names.constEnd())
319  {
320  const QDomNodeList nodeList = this->elementsByTagName(QStringLiteral("m"));
321  if (nodeList.isEmpty())
322  {
323  ++i;
324  continue;
325  }
326 
327  for (int ii = 0; ii < nodeList.size(); ++ii)
328  {
329  const QString attrName = QStringLiteral("name");
330  QDomElement element = nodeList.at(ii).toElement();
331  const QString name = GetParametrString(element, attrName);
332  if (name == i.value())
333  {
334  SetAttribute(element, attrName, i.key());
335  }
336  }
337 
338  ++i;
339  }
340 }
341 
342 //---------------------------------------------------------------------------------------------------------------------
344 {
345  // TODO. Delete if minimal supported version is 0.4.0
346  Q_STATIC_ASSERT_X(VVSTConverter::MeasurementMinVer < CONVERTER_VERSION_CHECK(0, 4, 0),
347  "Time to refactor the code.");
348 
349  AddRootComment();
350  SetVersion(QStringLiteral("0.4.0"));
354  Save();
355 }
356 
357 //---------------------------------------------------------------------------------------------------------------------
359 {
360  // TODO. Delete if minimal supported version is 0.4.1
361  Q_STATIC_ASSERT_X(VVSTConverter::MeasurementMinVer < CONVERTER_VERSION_CHECK(0, 4, 1),
362  "Time to refactor the code.");
363 
364  SetVersion(QStringLiteral("0.4.1"));
365  PM_SystemV0_4_1();
366  Save();
367 }
368 
369 //---------------------------------------------------------------------------------------------------------------------
371 {
372  // TODO. Delete if minimal supported version is 0.4.2
373  Q_STATIC_ASSERT_X(VVSTConverter::MeasurementMinVer < CONVERTER_VERSION_CHECK(0, 4, 2),
374  "Time to refactor the code.");
375 
376  SetVersion(QStringLiteral("0.4.2"));
378  Save();
379 }
380 
381 //---------------------------------------------------------------------------------------------------------------------
383 {
384  // TODO. Delete if minimal supported version is 0.4.3
385  Q_STATIC_ASSERT_X(VVSTConverter::MeasurementMinVer < CONVERTER_VERSION_CHECK(0, 4, 3),
386  "Time to refactor the code.");
387 
388  SetVersion(QStringLiteral("0.4.3"));
389  Save();
390 }
391 
392 //---------------------------------------------------------------------------------------------------------------------
394 {
395  // TODO. Delete if minimal supported version is 0.4.4
396  Q_STATIC_ASSERT_X(VVSTConverter::MeasurementMinVer < CONVERTER_VERSION_CHECK(0, 4, 4),
397  "Time to refactor the code.");
398 
399  SetVersion(QStringLiteral("0.4.4"));
400  Save();
401 }
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
static const QString MeasurementMaxVerStr
Definition: vvstconverter.h:72
static Q_DECL_CONSTEXPR const int MeasurementMaxVer
Definition: vvstconverter.h:80
virtual void DowngradeToCurrentMaxVersion() Q_DECL_OVERRIDE
static Q_DECL_CONSTEXPR const int MeasurementMinVer
Definition: vvstconverter.h:79
virtual bool IsReadOnly() const Q_DECL_OVERRIDE
void PM_SystemV0_4_1()
static const QString CurrentSchema
Definition: vvstconverter.h:73
QDomElement AddMV0_4_0(const QString &name, qreal value, qreal sizeIncrease, qreal heightIncrease)
VVSTConverter(const QString &fileName)
void ConvertMeasurementsToV0_4_0()
void RemoveTagsForV0_4_0()
void AddNewTagsForV0_4_0()
void ConvertMeasurementsToV0_4_2()
virtual void ApplyPatches() Q_DECL_OVERRIDE
static const QString MeasurementMinVerStr
Definition: vvstconverter.h:97
virtual QString XSDSchema(int ver) const Q_DECL_OVERRIDE
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