Added initial support for the manual layout format version converter.

This commit is contained in:
Roman Telezhynskyi 2020-04-23 18:05:00 +03:00
parent aeebd2a095
commit 82ce2aadfe
11 changed files with 432 additions and 50 deletions

View File

@ -36,6 +36,8 @@
#include "puzzleapplication.h" #include "puzzleapplication.h"
#include "../vlayout/vrawlayout.h" #include "../vlayout/vrawlayout.h"
#include "../vmisc/vsysexits.h" #include "../vmisc/vsysexits.h"
#include "../ifc/xml/vlayoutconverter.h"
#include "../ifc/exception/vexception.h"
#include <QLoggingCategory> #include <QLoggingCategory>
@ -79,12 +81,24 @@ PuzzleMainWindow::~PuzzleMainWindow()
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
bool PuzzleMainWindow::LoadFile(const QString &path) bool PuzzleMainWindow::LoadFile(QString path)
{ {
try
{
VLayoutConverter converter(path);
path = converter.Convert();
}
catch (VException &e)
{
qCCritical(pWindow, "%s\n\n%s\n\n%s", qUtf8Printable(tr("File error.")),
qUtf8Printable(e.ErrorMessage()), qUtf8Printable(e.DetailedInformation()));
return false;
}
QFile file(path); QFile file(path);
file.open(QIODevice::ReadOnly); file.open(QIODevice::ReadOnly);
VPuzzleLayoutFileReader *fileReader = new VPuzzleLayoutFileReader(); QScopedPointer<VPuzzleLayoutFileReader> fileReader(new VPuzzleLayoutFileReader());
if(m_layout == nullptr) if(m_layout == nullptr)
{ {

View File

@ -57,7 +57,7 @@ public:
* @param path * @param path
* @return * @return
*/ */
bool LoadFile(const QString &path); bool LoadFile(QString path);
/** /**
* @brief SaveFile Saves the current layout to the layout file of given path * @brief SaveFile Saves the current layout to the layout file of given path

View File

@ -53,31 +53,7 @@ bool VPuzzleLayoutFileReader::ReadFile(VPuzzleLayout *layout, QFile *file)
if (readNextStartElement()) if (readNextStartElement())
{ {
ReadLayout(layout);
// TODO extend the handling
// if it doesn't start with layout, error
// if it starts with version > than current version, error
if (name() == ML::TagLayout)
{
QString versionStr = ReadAttributeEmptyString(attributes(), ML::AttrVersion);
QStringList versionStrParts = versionStr.split('.');
m_layoutFormatVersion = FORMAT_VERSION(versionStrParts.at(0).toInt(),versionStrParts.at(1).toInt(),versionStrParts.at(2).toInt());
if(VPuzzleLayoutFileWriter::LayoutFileFormatVersion >= m_layoutFormatVersion)
{
ReadLayout(layout);
}
else
{
// TODO better error handling
raiseError(QObject::tr("You're trying to open a layout that was created with a newer version of puzzle"));
}
}
else
{
raiseError(QObject::tr("Wrong file structure"));
}
} }
return !error(); return !error();

View File

@ -46,10 +46,6 @@ public:
private: private:
Q_DISABLE_COPY(VPuzzleLayoutFileReader) Q_DISABLE_COPY(VPuzzleLayoutFileReader)
/**
* @brief m_layoutFormatVersion holds the version of the layout currently being read
*/
int m_layoutFormatVersion;
void ReadLayout(VPuzzleLayout *layout); void ReadLayout(VPuzzleLayout *layout);
void ReadProperties(VPuzzleLayout *layout); void ReadProperties(VPuzzleLayout *layout);

View File

@ -31,6 +31,7 @@
#include "vpuzzlelayer.h" #include "vpuzzlelayer.h"
#include "vpuzzlepiece.h" #include "vpuzzlepiece.h"
#include "layoutliterals.h" #include "layoutliterals.h"
#include "../ifc/xml/vlayoutconverter.h"
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
VPuzzleLayoutFileWriter::VPuzzleLayoutFileWriter() VPuzzleLayoutFileWriter::VPuzzleLayoutFileWriter()
@ -61,7 +62,7 @@ void VPuzzleLayoutFileWriter::WriteFile(VPuzzleLayout *layout, QFile *file)
void VPuzzleLayoutFileWriter::WriteLayout(VPuzzleLayout *layout) void VPuzzleLayoutFileWriter::WriteLayout(VPuzzleLayout *layout)
{ {
writeStartElement(ML::TagLayout); writeStartElement(ML::TagLayout);
SetAttribute(ML::AttrVersion, LayoutFileFormatVersionStr); SetAttribute(ML::AttrVersion, VLayoutConverter::LayoutMaxVerStr);
WriteProperties(layout); WriteProperties(layout);
WriteLayers(layout); WriteLayers(layout);
@ -180,7 +181,7 @@ void VPuzzleLayoutFileWriter::WritePiece(VPuzzlePiece *piece)
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void VPuzzleLayoutFileWriter::WriteMargins(QMarginsF margins) void VPuzzleLayoutFileWriter::WriteMargins(const QMarginsF &margins)
{ {
writeStartElement(ML::TagMargin); writeStartElement(ML::TagMargin);
SetAttribute(ML::AttrLeft, margins.left()); SetAttribute(ML::AttrLeft, margins.left());

View File

@ -29,12 +29,16 @@
#ifndef VPUZZLELAYOUTFILEWRITER_H #ifndef VPUZZLELAYOUTFILEWRITER_H
#define VPUZZLELAYOUTFILEWRITER_H #define VPUZZLELAYOUTFILEWRITER_H
#include <QLocale>
#include <QXmlStreamWriter> #include <QXmlStreamWriter>
#include "../ifc/xml/vabstractconverter.h"
#include "../vmisc/literals.h"
class VPuzzleLayout; class VPuzzleLayout;
class VPuzzleLayer; class VPuzzleLayer;
class VPuzzlePiece; class VPuzzlePiece;
class QFile;
class QMarginsF;
class VPuzzleLayoutFileWriter : public QXmlStreamWriter class VPuzzleLayoutFileWriter : public QXmlStreamWriter
{ {
@ -44,20 +48,6 @@ public:
void WriteFile(VPuzzleLayout *layout, QFile *file); void WriteFile(VPuzzleLayout *layout, QFile *file);
/*
* Version rules:
* 1. Version have three parts "major.minor.patch";
* 2. major part only for stable releases;
* 3. minor - 10 or more patch changes, or one big change;
* 4. patch - little change.
*/
/**
* @brief LayoutFileFormatVersion holds the version
*
*/
static Q_DECL_CONSTEXPR const int LayoutFileFormatVersion = FORMAT_VERSION(1, 0, 0);
const QString LayoutFileFormatVersionStr = QStringLiteral("1.0.0");
private: private:
void WriteLayout(VPuzzleLayout *layout); void WriteLayout(VPuzzleLayout *layout);
@ -68,7 +58,7 @@ private:
void WriteLayer(VPuzzleLayer *layer, const QString &tagName); void WriteLayer(VPuzzleLayer *layer, const QString &tagName);
void WritePiece(VPuzzlePiece *piece); void WritePiece(VPuzzlePiece *piece);
void WriteMargins(QMarginsF margins); void WriteMargins(const QMarginsF &margins);
void WriteSize(QSizeF size); void WriteSize(QSizeF size);
template <typename T> template <typename T>

View File

@ -75,5 +75,6 @@
<file>schema/individual_measurements/v0.5.0.xsd</file> <file>schema/individual_measurements/v0.5.0.xsd</file>
<file>schema/label_template/v1.0.0.xsd</file> <file>schema/label_template/v1.0.0.xsd</file>
<file>schema/watermark/v1.0.0.xsd</file> <file>schema/watermark/v1.0.0.xsd</file>
<file>schema/layout/v0.1.0.xsd</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@ -0,0 +1,221 @@
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="layout">
<xs:complexType>
<xs:sequence>
<xs:element name="properties">
<xs:complexType>
<xs:sequence>
<xs:element type="xs:string" name="unit"/>
<xs:element type="xs:string" name="description"/>
<xs:element name="size">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:float" name="width"/>
<xs:attribute type="xs:short" name="length"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name="margin">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:float" name="top"/>
<xs:attribute type="xs:float" name="right"/>
<xs:attribute type="xs:float" name="bottom"/>
<xs:attribute type="xs:float" name="left"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name="control">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:string" name="followGrainLine"/>
<xs:attribute type="xs:string" name="warningSuperposition"/>
<xs:attribute type="xs:string" name="warningOutOfBound"/>
<xs:attribute type="xs:string" name="stickyEdges"/>
<xs:attribute type="xs:float" name="piecesGap"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name="tiles">
<xs:complexType>
<xs:sequence>
<xs:element name="size">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:float" name="width"/>
<xs:attribute type="xs:float" name="length"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name="margin">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:float" name="top"/>
<xs:attribute type="xs:float" name="right"/>
<xs:attribute type="xs:float" name="bottom"/>
<xs:attribute type="xs:float" name="left"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="xs:string" name="visible"/>
<xs:attribute type="xs:string" name="matchingMarks"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="layers">
<xs:complexType>
<xs:sequence>
<xs:element name="unplacedPiecesLayer">
<xs:complexType>
<xs:sequence>
<xs:element name="pieces">
<xs:complexType>
<xs:sequence>
<xs:element name="piece" maxOccurs="unbounded" minOccurs="0">
<xs:complexType mixed="true">
<xs:sequence>
<xs:element name="cuttingLine" minOccurs="0">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:string" name="style"/>
<xs:attribute type="xs:string" name="color"/>
<xs:attribute type="xs:string" name="p"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name="seamLine" minOccurs="0">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:string" name="style"/>
<xs:attribute type="xs:string" name="color"/>
<xs:attribute type="xs:string" name="visible"/>
<xs:attribute type="xs:string" name="p"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name="grainline" minOccurs="0">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:float" name="angle"/>
<xs:attribute type="xs:string" name="p"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name="passMark" minOccurs="0">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:string" name="p"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name="internalPath" minOccurs="0">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:string" name="p"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name="placeLabel" minOccurs="0">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:string" name="p"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name="labels" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:element name="label">
<xs:complexType>
<xs:choice maxOccurs="unbounded" minOccurs="0">
<xs:element name="text">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:string" name="align" use="optional"/>
<xs:attribute type="xs:string" name="decoration" use="optional"/>
<xs:attribute type="xs:byte" name="fsize" use="optional"/>
<xs:attribute type="xs:byte" name="size" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:choice>
<xs:attribute type="xs:byte" name="width"/>
<xs:attribute type="xs:byte" name="height"/>
<xs:attribute type="xs:string" name="transform"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="xs:string" name="id" use="optional"/>
<xs:attribute type="xs:string" name="name" use="optional"/>
<xs:attribute type="xs:string" name="mirrored" use="optional"/>
<xs:attribute type="xs:string" name="transform" use="optional"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="layer">
<xs:complexType>
<xs:sequence>
<xs:element name="piece">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:string" name="id"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="xs:byte" name="id"/>
<xs:attribute type="xs:string" name="name"/>
<xs:attribute type="xs:string" name="selected"/>
<xs:attribute type="xs:string" name="visible"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="formatVersion" name="version"/>
</xs:complexType>
</xs:element>
<xs:simpleType name="formatVersion">
<xs:restriction base="xs:string">
<xs:pattern value="[0-9]{1,}\.[0-9]{1,}\.[0-9]{1,}"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>

View File

@ -0,0 +1,91 @@
/************************************************************************
**
** @file vlayoutconverter.cpp
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @date 23 4, 2020
**
** @brief
** @copyright
** This source code is part of the Valentina project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2020 Valentina project
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#include "vlayoutconverter.h"
/*
* Version rules:
* 1. Version have three parts "major.minor.patch";
* 2. major part only for stable releases;
* 3. minor - 10 or more patch changes, or one big change;
* 4. patch - little change.
*/
const QString VLayoutConverter::LayoutMinVerStr = QStringLiteral("0.1.0");
const QString VLayoutConverter::LayoutMaxVerStr = QStringLiteral("0.1.0");
const QString VLayoutConverter::CurrentSchema = QStringLiteral("://schema/layout/v0.1.0.xsd");
//VLayoutConverter::LayoutMinVer; // <== DON'T FORGET TO UPDATE TOO!!!!
//VLayoutConverter::LayoutMaxVer; // <== DON'T FORGET TO UPDATE TOO!!!!
//---------------------------------------------------------------------------------------------------------------------
VLayoutConverter::VLayoutConverter(const QString &fileName)
: VAbstractConverter(fileName)
{
ValidateInputFile(CurrentSchema);
}
//---------------------------------------------------------------------------------------------------------------------
QString VLayoutConverter::XSDSchema(int ver) const
{
QHash <int, QString> schemas =
{
std::make_pair(FORMAT_VERSION(0, 1, 0), CurrentSchema)
};
if (schemas.contains(ver))
{
return schemas.value(ver);
}
InvalidVersion(ver);
}
//---------------------------------------------------------------------------------------------------------------------
void VLayoutConverter::ApplyPatches()
{
switch (m_ver)
{
case (FORMAT_VERSION(0, 1, 0)):
break;
default:
InvalidVersion(m_ver);
}
}
//---------------------------------------------------------------------------------------------------------------------
void VLayoutConverter::DowngradeToCurrentMaxVersion()
{
SetVersion(LayoutMaxVerStr);
Save();
}
//---------------------------------------------------------------------------------------------------------------------
bool VLayoutConverter::IsReadOnly() const
{
return false;
}

View File

@ -0,0 +1,90 @@
/************************************************************************
**
** @file vlayoutconverter.h
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @date 23 4, 2020
**
** @brief
** @copyright
** This source code is part of the Valentina project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2020 Valentina project
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#ifndef VLAYOUTCONVERTER_H
#define VLAYOUTCONVERTER_H
#include "vabstractconverter.h"
class QDomElement;
class QString;
class VLayoutConverter : public VAbstractConverter
{
Q_DECLARE_TR_FUNCTIONS(VLayoutConverter)
public:
explicit VLayoutConverter(const QString &fileName);
virtual ~VLayoutConverter() Q_DECL_EQ_DEFAULT;
static const QString LayoutMaxVerStr;
static const QString CurrentSchema;
static Q_DECL_CONSTEXPR const int LayoutMinVer = FORMAT_VERSION(0, 1, 0);
static Q_DECL_CONSTEXPR const int LayoutMaxVer = FORMAT_VERSION(0, 1, 0);
protected:
virtual int MinVer() const override;
virtual int MaxVer() const override;
virtual QString MinVerStr() const override;
virtual QString MaxVerStr() const override;
virtual QString XSDSchema(int ver) const override;
virtual void ApplyPatches() override;
virtual void DowngradeToCurrentMaxVersion() override;
virtual bool IsReadOnly() const override;
private:
Q_DISABLE_COPY(VLayoutConverter)
static const QString LayoutMinVerStr;
};
//---------------------------------------------------------------------------------------------------------------------
inline int VLayoutConverter::MinVer() const
{
return LayoutMinVer;
}
//---------------------------------------------------------------------------------------------------------------------
inline int VLayoutConverter::MaxVer() const
{
return LayoutMaxVer;
}
//---------------------------------------------------------------------------------------------------------------------
inline QString VLayoutConverter::MinVerStr() const
{
return LayoutMinVerStr;
}
//---------------------------------------------------------------------------------------------------------------------
inline QString VLayoutConverter::MaxVerStr() const
{
return LayoutMaxVerStr;
}
#endif // VLAYOUTCONVERTER_H

View File

@ -4,6 +4,7 @@
HEADERS += \ HEADERS += \
$$PWD/vabstractconverter.h \ $$PWD/vabstractconverter.h \
$$PWD/vdomdocument.h \ $$PWD/vdomdocument.h \
$$PWD/vlayoutconverter.h \
$$PWD/vpatternconverter.h \ $$PWD/vpatternconverter.h \
$$PWD/vtoolrecord.h \ $$PWD/vtoolrecord.h \
$$PWD/vabstractpattern.h \ $$PWD/vabstractpattern.h \
@ -16,6 +17,7 @@ HEADERS += \
SOURCES += \ SOURCES += \
$$PWD/vabstractconverter.cpp \ $$PWD/vabstractconverter.cpp \
$$PWD/vdomdocument.cpp \ $$PWD/vdomdocument.cpp \
$$PWD/vlayoutconverter.cpp \
$$PWD/vpatternconverter.cpp \ $$PWD/vpatternconverter.cpp \
$$PWD/vtoolrecord.cpp \ $$PWD/vtoolrecord.cpp \
$$PWD/vabstractpattern.cpp \ $$PWD/vabstractpattern.cpp \