Redesign of pattern image.
Preparations for support of background image. #43
This commit is contained in:
parent
2448ee4361
commit
141b33884d
|
@ -36,6 +36,11 @@
|
|||
#include <QMessageBox>
|
||||
#include <QRadioButton>
|
||||
#include <QCompleter>
|
||||
#include <QSet>
|
||||
#include <QImageReader>
|
||||
#include <QMimeType>
|
||||
#include <QDesktopServices>
|
||||
#include <QUrl>
|
||||
|
||||
#include "../xml/vpattern.h"
|
||||
#include "../vpatterndb/vcontainer.h"
|
||||
|
@ -44,6 +49,7 @@
|
|||
#include "dialogknownmaterials.h"
|
||||
#include "../vmisc/vvalentinasettings.h"
|
||||
#include "../qmuparser/qmudef.h"
|
||||
#include "../ifc/xml/vpatternimage.h"
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
DialogPatternProperties::DialogPatternProperties(VPattern *doc, VContainer *pattern, QWidget *parent)
|
||||
|
@ -250,21 +256,6 @@ void DialogPatternProperties::SaveReadOnlyState()
|
|||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
QImage DialogPatternProperties::GetImage()
|
||||
{
|
||||
// we set an image from file.val
|
||||
QImage image;
|
||||
QByteArray byteArray;
|
||||
byteArray.append(doc->GetImage().toUtf8());
|
||||
QByteArray ba = QByteArray::fromBase64(byteArray);
|
||||
QBuffer buffer(&ba);
|
||||
buffer.open(QIODevice::ReadOnly);
|
||||
QString extension = doc->GetImageExtension();
|
||||
image.load(&buffer, extension.toLatin1().data()); // writes image into ba in 'extension' format
|
||||
return image;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void DialogPatternProperties::ValidatePassmarkLength() const
|
||||
{
|
||||
|
@ -318,19 +309,12 @@ void DialogPatternProperties::InitImage()
|
|||
|
||||
connect(changeImageAction, &QAction::triggered, this, &DialogPatternProperties::ChangeImage);
|
||||
connect(saveImageAction, &QAction::triggered, this, &DialogPatternProperties::SaveImage);
|
||||
connect(showImageAction, &QAction::triggered, this, [this]()
|
||||
{
|
||||
QLabel *label = new QLabel(this, Qt::Window);
|
||||
const QImage image = GetImage();
|
||||
label->setPixmap(QPixmap::fromImage(image));
|
||||
label->setGeometry(QRect(QCursor::pos(), image.size()));
|
||||
label->show();
|
||||
});
|
||||
connect(showImageAction, &QAction::triggered, this, &DialogPatternProperties::ShowImage);
|
||||
|
||||
const QImage image = GetImage();
|
||||
if (not image.isNull())
|
||||
const VPatternImage image = doc->GetImage();
|
||||
if (image.IsValid())
|
||||
{
|
||||
ui->imageLabel->setPixmap(QPixmap::fromImage(image));
|
||||
ui->imageLabel->setPixmap(image.GetPixmap(ui->imageLabel->width(), ui->imageLabel->height()));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -343,35 +327,46 @@ void DialogPatternProperties::InitImage()
|
|||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void DialogPatternProperties::ChangeImage()
|
||||
{
|
||||
const QString filter = tr("Images") + QLatin1String(" (*.png *.jpg *.jpeg *.bmp)");
|
||||
const QString fileName = QFileDialog::getOpenFileName(this, tr("Image for pattern"), QString(), filter, nullptr,
|
||||
VAbstractApplication::VApp()->NativeFileDialog());
|
||||
auto PrepareFilter = []()
|
||||
{
|
||||
const QList<QByteArray> supportedFormats = QImageReader::supportedImageFormats();
|
||||
const QSet<QString> filterFormats{"bmp", "jpeg", "jpg", "png", "svg", "svgz", "tif", "tiff", "webp"};
|
||||
QStringList sufixes;
|
||||
for (const auto& format : supportedFormats)
|
||||
{
|
||||
if (filterFormats.contains(format))
|
||||
{
|
||||
sufixes.append(QStringLiteral("*.%1").arg(QString(format)));
|
||||
}
|
||||
}
|
||||
|
||||
QStringList filters;
|
||||
|
||||
if (not sufixes.isEmpty())
|
||||
{
|
||||
filters.append(tr("Images") + QStringLiteral(" (%1)").arg(sufixes.join(' ')));
|
||||
}
|
||||
|
||||
filters.append(tr("All files") + QStringLiteral(" (*.*)"));
|
||||
|
||||
return filters.join(QStringLiteral(";;"));
|
||||
};
|
||||
|
||||
const QString fileName = QFileDialog::getOpenFileName(this, tr("Image for pattern"), QString(), PrepareFilter(),
|
||||
nullptr, VAbstractApplication::VApp()->NativeFileDialog());
|
||||
if (not fileName.isEmpty())
|
||||
{
|
||||
QImage image;
|
||||
if (not image.load(fileName))
|
||||
VPatternImage image = VPatternImage::FromFile(fileName);
|
||||
|
||||
if (not image.IsValid())
|
||||
{
|
||||
qCritical() << tr("Invalid image. Error: %1").arg(image.ErrorString());
|
||||
return;
|
||||
}
|
||||
ui->imageLabel->setPixmap(QPixmap::fromImage(image));
|
||||
QFileInfo f(fileName);
|
||||
QString extension = f.suffix().toUpper();
|
||||
|
||||
if (extension == QLatin1String("JPEG"))
|
||||
{
|
||||
extension = "JPG";
|
||||
}
|
||||
if (extension == QLatin1String("PNG") || extension == QLatin1String("JPG") || extension == QLatin1String("BMP"))
|
||||
{
|
||||
QByteArray byteArray;
|
||||
QBuffer buffer(&byteArray);
|
||||
buffer.open(QIODevice::WriteOnly);
|
||||
image.save(&buffer, extension.toLatin1().data()); //writes the image in 'extension' format inside the buffer
|
||||
QString iconBase64 = QString::fromLatin1(byteArray.toBase64().data());
|
||||
doc->SetImage(image);
|
||||
ui->imageLabel->setPixmap(image.GetPixmap(ui->imageLabel->width(), ui->imageLabel->height()));
|
||||
|
||||
// save our image to file.val
|
||||
doc->SetImage(iconBase64, extension);
|
||||
}
|
||||
deleteAction->setEnabled(true);
|
||||
saveImageAction->setEnabled(true);
|
||||
showImageAction->setEnabled(true);
|
||||
|
@ -381,24 +376,70 @@ void DialogPatternProperties::ChangeImage()
|
|||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void DialogPatternProperties::SaveImage()
|
||||
{
|
||||
QByteArray byteArray;
|
||||
byteArray.append(doc->GetImage().toUtf8());
|
||||
QByteArray ba = QByteArray::fromBase64(byteArray);
|
||||
const QString extension = doc->GetImageExtension().prepend(QChar('.'));
|
||||
QString filter = tr("Images") + QStringLiteral(" (*") + extension + QChar(')');
|
||||
QString filename = QFileDialog::getSaveFileName(this, tr("Save File"), tr("untitled"), filter, &filter,
|
||||
const VPatternImage image = doc->GetImage();
|
||||
|
||||
if (not image.IsValid())
|
||||
{
|
||||
qCritical() << tr("Unable to save image. Error: %1").arg(image.ErrorString());
|
||||
return;
|
||||
}
|
||||
|
||||
QMimeType mime = image.MimeTypeFromData();
|
||||
QString path = QDir::homePath() + QDir::separator() + tr("untitled");
|
||||
|
||||
QStringList suffixes = mime.suffixes();
|
||||
if (not suffixes.isEmpty())
|
||||
{
|
||||
path += '.' + suffixes.at(0);
|
||||
}
|
||||
|
||||
QString filter = mime.filterString();
|
||||
QString filename = QFileDialog::getSaveFileName(this, tr("Save Image"), path, filter, nullptr,
|
||||
VAbstractApplication::VApp()->NativeFileDialog());
|
||||
if (not filename.isEmpty())
|
||||
{
|
||||
if (not filename.endsWith(extension.toUpper()))
|
||||
{
|
||||
filename.append(extension);
|
||||
}
|
||||
QFile file(filename);
|
||||
if (file.open(QIODevice::WriteOnly))
|
||||
{
|
||||
file.write(ba);
|
||||
file.close();
|
||||
file.write(QByteArray::fromBase64(image.ContentData()));
|
||||
}
|
||||
else
|
||||
{
|
||||
qCritical() << tr("Unable to save image. Error: %1").arg(file.errorString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void DialogPatternProperties::ShowImage()
|
||||
{
|
||||
const VPatternImage image = doc->GetImage();
|
||||
|
||||
if (not image.IsValid())
|
||||
{
|
||||
qCritical() << tr("Unable to show image. Error: %1").arg(image.ErrorString());
|
||||
return;
|
||||
}
|
||||
|
||||
QMimeType mime = image.MimeTypeFromData();
|
||||
QString name = QDir::tempPath() + QDir::separator() + QStringLiteral("image.XXXXXX");
|
||||
|
||||
QStringList suffixes = mime.suffixes();
|
||||
if (not suffixes.isEmpty())
|
||||
{
|
||||
name += '.' + suffixes.at(0);
|
||||
}
|
||||
|
||||
delete m_tmpImage;
|
||||
m_tmpImage = new QTemporaryFile(name, this);
|
||||
if (m_tmpImage->open())
|
||||
{
|
||||
m_tmpImage->write(QByteArray::fromBase64(image.ContentData()));
|
||||
m_tmpImage->flush();
|
||||
QDesktopServices::openUrl(QUrl::fromLocalFile(m_tmpImage->fileName()));
|
||||
}
|
||||
else
|
||||
{
|
||||
qCritical() << tr("Unable to open temp file");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
|
||||
#include <QDialog>
|
||||
#include <QMap>
|
||||
#include <QPointer>
|
||||
|
||||
#include "../vmisc/def.h"
|
||||
#include "../ifc/ifcdef.h"
|
||||
|
@ -39,6 +40,7 @@ class VPattern;
|
|||
class VContainer;
|
||||
class QCheckBox;
|
||||
class QCompleter;
|
||||
class QTemporaryFile;
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
|
@ -61,6 +63,7 @@ private slots:
|
|||
void DescEdited();
|
||||
void ChangeImage();
|
||||
void SaveImage();
|
||||
void ShowImage();
|
||||
private:
|
||||
Q_DISABLE_COPY(DialogPatternProperties)
|
||||
Ui::DialogPatternProperties *ui;
|
||||
|
@ -77,12 +80,12 @@ private:
|
|||
QCompleter *m_completer{nullptr};
|
||||
QStringList m_variables{};
|
||||
QString m_oldPassmarkLength{};
|
||||
QPointer<QTemporaryFile> m_tmpImage{};
|
||||
|
||||
void SaveDescription();
|
||||
void SaveReadOnlyState();
|
||||
|
||||
void InitImage();
|
||||
QImage GetImage();
|
||||
|
||||
void ValidatePassmarkLength() const;
|
||||
};
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
include(../../../common.pri)
|
||||
|
||||
# Library work with xml.
|
||||
QT += xml xmlpatterns printsupport concurrent
|
||||
QT += xml xmlpatterns printsupport concurrent svg
|
||||
|
||||
# We don't need gui library.
|
||||
QT -= gui
|
||||
|
|
|
@ -65,6 +65,7 @@
|
|||
<file>schema/pattern/v0.8.11.xsd</file>
|
||||
<file>schema/pattern/v0.8.12.xsd</file>
|
||||
<file>schema/pattern/v0.8.13.xsd</file>
|
||||
<file>schema/pattern/v0.9.0.xsd</file>
|
||||
<file>schema/multisize_measurements/v0.3.0.xsd</file>
|
||||
<file>schema/multisize_measurements/v0.4.0.xsd</file>
|
||||
<file>schema/multisize_measurements/v0.4.1.xsd</file>
|
||||
|
|
1132
src/libs/ifc/schema/pattern/v0.9.0.xsd
Normal file
1132
src/libs/ifc/schema/pattern/v0.9.0.xsd
Normal file
File diff suppressed because it is too large
Load Diff
|
@ -41,6 +41,7 @@
|
|||
#include <QtConcurrentMap>
|
||||
#include <QFuture>
|
||||
#include <QtConcurrentRun>
|
||||
#include <QMimeDatabase>
|
||||
|
||||
#include "../exception/vexceptionemptyparameter.h"
|
||||
#include "../exception/vexceptionobjecterror.h"
|
||||
|
@ -57,6 +58,7 @@
|
|||
#include "../vmisc/vabstractvalapplication.h"
|
||||
#include "../vmisc/compatibility.h"
|
||||
#include "../vlayout/vtextmanager.h"
|
||||
#include "vpatternimage.h"
|
||||
|
||||
class QDomElement;
|
||||
|
||||
|
@ -137,7 +139,7 @@ const QString VAbstractPattern::AttrPassmarkLength = QStringLiteral("passmark
|
|||
const QString VAbstractPattern::AttrOpacity = QStringLiteral("opacity");
|
||||
const QString VAbstractPattern::AttrTags = QStringLiteral("tags");
|
||||
|
||||
const QString VAbstractPattern::AttrExtension = QStringLiteral("extension");
|
||||
const QString VAbstractPattern::AttrContentType = QStringLiteral("contentType");
|
||||
|
||||
const QString VAbstractPattern::AttrFormula = QStringLiteral("formula");
|
||||
const QString VAbstractPattern::AttrDescription = QStringLiteral("description");
|
||||
|
@ -1228,44 +1230,32 @@ void VAbstractPattern::SetPassmarkLengthVariable(const QString &name)
|
|||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
QString VAbstractPattern::GetImage() const
|
||||
auto VAbstractPattern::GetImage() const -> VPatternImage
|
||||
{
|
||||
return UniqueTagText(TagImage);
|
||||
VPatternImage image;
|
||||
|
||||
const QDomNodeList list = elementsByTagName(TagImage);
|
||||
if (not list.isEmpty())
|
||||
{
|
||||
QDomElement imgTag = list.at(0).toElement();
|
||||
if (not imgTag.isNull())
|
||||
{
|
||||
image.SetContentData(imgTag.text().toLatin1(), imgTag.attribute(AttrContentType));
|
||||
}
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
QString VAbstractPattern::GetImageExtension() const
|
||||
{
|
||||
const QString defExt = QStringLiteral("PNG");
|
||||
const QDomNodeList nodeList = this->elementsByTagName(TagImage);
|
||||
if (nodeList.isEmpty())
|
||||
{
|
||||
return defExt;
|
||||
}
|
||||
else
|
||||
{
|
||||
const QDomNode domNode = nodeList.at(0);
|
||||
if (domNode.isNull() == false && domNode.isElement())
|
||||
{
|
||||
const QDomElement domElement = domNode.toElement();
|
||||
if (domElement.isNull() == false)
|
||||
{
|
||||
const QString ext = domElement.attribute(AttrExtension, defExt);
|
||||
return ext;
|
||||
}
|
||||
}
|
||||
}
|
||||
return defExt;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VAbstractPattern::SetImage(const QString &text, const QString &extension)
|
||||
auto VAbstractPattern::SetImage(const VPatternImage &image) -> bool
|
||||
{
|
||||
QDomElement imageElement = CheckTagExists(TagImage);
|
||||
setTagText(imageElement, text);
|
||||
CheckTagExists(TagImage).setAttribute(AttrExtension, extension);
|
||||
setTagText(imageElement, image.ContentData());
|
||||
imageElement.setAttribute(AttrContentType, image.ContentType());
|
||||
modified = true;
|
||||
emit patternChanged(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
class QDomElement;
|
||||
class VPiecePath;
|
||||
class VPieceNode;
|
||||
class VPatternImage;
|
||||
|
||||
enum class Document : qint8 { FullLiteParse, LiteParse, LitePPParse, FullParse };
|
||||
enum class LabelType : qint8 {NewPatternPiece, NewLabel};
|
||||
|
@ -200,9 +201,8 @@ public:
|
|||
QString GetPassmarkLengthVariable() const;
|
||||
void SetPassmarkLengthVariable(const QString &name);
|
||||
|
||||
QString GetImage() const;
|
||||
QString GetImageExtension() const;
|
||||
void SetImage(const QString &text, const QString &extension);
|
||||
VPatternImage GetImage() const;
|
||||
bool SetImage(const VPatternImage &image);
|
||||
void DeleteImage();
|
||||
|
||||
QString GetVersion() const;
|
||||
|
@ -319,7 +319,7 @@ public:
|
|||
static const QString AttrOpacity;
|
||||
static const QString AttrTags;
|
||||
|
||||
static const QString AttrExtension;
|
||||
static const QString AttrContentType;
|
||||
|
||||
static const QString AttrFormula;
|
||||
static const QString AttrDescription;
|
||||
|
|
|
@ -891,7 +891,7 @@ auto VDomDocument::GetFormatVersion(const QString &version) -> unsigned
|
|||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
bool VDomDocument::setTagText(const QString &tag, const QString &text)
|
||||
auto VDomDocument::setTagText(const QString &tag, const QString &text) -> bool
|
||||
{
|
||||
const QDomNodeList nodeList = this->elementsByTagName(tag);
|
||||
if (nodeList.isEmpty())
|
||||
|
@ -900,10 +900,10 @@ bool VDomDocument::setTagText(const QString &tag, const QString &text)
|
|||
}
|
||||
else
|
||||
{
|
||||
const QDomNode domNode = nodeList.at(0);
|
||||
if (domNode.isNull() == false && domNode.isElement())
|
||||
QDomNode domNode = nodeList.at(0);
|
||||
if (not domNode.isNull() && domNode.isElement())
|
||||
{
|
||||
const QDomElement domElement = domNode.toElement();
|
||||
QDomElement domElement = domNode.toElement();
|
||||
return setTagText(domElement, text);
|
||||
}
|
||||
}
|
||||
|
@ -911,17 +911,30 @@ bool VDomDocument::setTagText(const QString &tag, const QString &text)
|
|||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
bool VDomDocument::setTagText(const QDomElement &domElement, const QString &text)
|
||||
auto VDomDocument::setTagText(QDomElement &domElement, const QString &text) -> bool
|
||||
{
|
||||
if (domElement.isNull() == false)
|
||||
if (not domElement.isNull())
|
||||
{
|
||||
QDomElement parent = domElement.parentNode().toElement();
|
||||
QDomElement newTag = createElement(domElement.tagName());
|
||||
QDomNode oldText = domElement.firstChild();
|
||||
const QDomText newText = createTextNode(text);
|
||||
|
||||
const QDomText newTagText = createTextNode(text);
|
||||
newTag.appendChild(newTagText);
|
||||
if (oldText.isNull())
|
||||
{
|
||||
domElement.appendChild(newText);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (oldText.nodeType() == QDomNode::TextNode)
|
||||
{
|
||||
domElement.replaceChild(newText, oldText);
|
||||
}
|
||||
else
|
||||
{
|
||||
RemoveAllChildren(domElement);
|
||||
domElement.appendChild(newText);
|
||||
}
|
||||
}
|
||||
|
||||
parent.replaceChild(newTag, domElement);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -149,7 +149,7 @@ public:
|
|||
|
||||
protected:
|
||||
bool setTagText(const QString &tag, const QString &text);
|
||||
bool setTagText(const QDomElement &domElement, const QString &text);
|
||||
bool setTagText(QDomElement &domElement, const QString &text);
|
||||
QString UniqueTagText(const QString &tagName, const QString &defVal = QString()) const;
|
||||
void CollectId(const QDomElement &node, QVector<quint32> &vector)const;
|
||||
|
||||
|
|
|
@ -60,8 +60,8 @@ class QDomElement;
|
|||
*/
|
||||
|
||||
const QString VPatternConverter::PatternMinVerStr = QStringLiteral("0.1.4");
|
||||
const QString VPatternConverter::PatternMaxVerStr = QStringLiteral("0.8.13");
|
||||
const QString VPatternConverter::CurrentSchema = QStringLiteral("://schema/pattern/v0.8.13.xsd");
|
||||
const QString VPatternConverter::PatternMaxVerStr = QStringLiteral("0.9.0");
|
||||
const QString VPatternConverter::CurrentSchema = QStringLiteral("://schema/pattern/v0.9.0.xsd");
|
||||
|
||||
//VPatternConverter::PatternMinVer; // <== DON'T FORGET TO UPDATE TOO!!!!
|
||||
//VPatternConverter::PatternMaxVer; // <== DON'T FORGET TO UPDATE TOO!!!!
|
||||
|
@ -167,6 +167,8 @@ Q_GLOBAL_STATIC_WITH_ARGS(const QString, strUserDefined, (QLatin1String("userDef
|
|||
Q_GLOBAL_STATIC_WITH_ARGS(const QString, strPlacement, (QLatin1String("placement")))
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(const QString, strCutNumber, (QLatin1String("cutNumber")))
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(const QString, strQuantity, (QLatin1String("quantity")))
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(const QString, strExtension, (QLatin1String("extension")))
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(const QString, strContentType, (QLatin1String("contentType")))
|
||||
} // anonymous namespace
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -246,7 +248,8 @@ auto VPatternConverter::XSDSchema(unsigned ver) const -> QString
|
|||
std::make_pair(FormatVersion(0, 8, 10), QStringLiteral("://schema/pattern/v0.8.10.xsd")),
|
||||
std::make_pair(FormatVersion(0, 8, 11), QStringLiteral("://schema/pattern/v0.8.11.xsd")),
|
||||
std::make_pair(FormatVersion(0, 8, 12), QStringLiteral("://schema/pattern/v0.8.12.xsd")),
|
||||
std::make_pair(FormatVersion(0, 8, 13), CurrentSchema)
|
||||
std::make_pair(FormatVersion(0, 8, 13), QStringLiteral("://schema/pattern/v0.8.13.xsd")),
|
||||
std::make_pair(FormatVersion(0, 9, 0), CurrentSchema)
|
||||
};
|
||||
|
||||
if (schemas.contains(ver))
|
||||
|
@ -519,6 +522,10 @@ void VPatternConverter::ApplyPatches()
|
|||
ValidateXML(XSDSchema(FormatVersion(0, 8, 13)));
|
||||
Q_FALLTHROUGH();
|
||||
case (FormatVersion(0, 8, 13)):
|
||||
ToV0_9_0();
|
||||
ValidateXML(XSDSchema(FormatVersion(0, 9, 0)));
|
||||
Q_FALLTHROUGH();
|
||||
case (FormatVersion(0, 9, 0)):
|
||||
break;
|
||||
default:
|
||||
InvalidVersion(m_ver);
|
||||
|
@ -536,7 +543,7 @@ void VPatternConverter::DowngradeToCurrentMaxVersion()
|
|||
bool VPatternConverter::IsReadOnly() const
|
||||
{
|
||||
// Check if attribute readOnly was not changed in file format
|
||||
Q_STATIC_ASSERT_X(VPatternConverter::PatternMaxVer == FormatVersion(0, 8, 13),
|
||||
Q_STATIC_ASSERT_X(VPatternConverter::PatternMaxVer == FormatVersion(0, 9, 0),
|
||||
"Check attribute readOnly.");
|
||||
|
||||
// Possibly in future attribute readOnly will change position etc.
|
||||
|
@ -1238,6 +1245,19 @@ void VPatternConverter::ToV0_8_13()
|
|||
Save();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VPatternConverter::ToV0_9_0()
|
||||
{
|
||||
// TODO. Delete if minimal supported version is 0.9.0
|
||||
Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < FormatVersion(0, 9, 0),
|
||||
"Time to refactor the code.");
|
||||
|
||||
ConvertImageToV0_9_0();
|
||||
|
||||
SetVersion(QStringLiteral("0.9.0"));
|
||||
Save();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VPatternConverter::TagUnitToV0_2_0()
|
||||
{
|
||||
|
@ -2790,6 +2810,61 @@ void VPatternConverter::AddPieceUUIDV0_8_8()
|
|||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VPatternConverter::ConvertImageToV0_9_0()
|
||||
{
|
||||
// TODO. Delete if minimal supported version is 0.9.0
|
||||
Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < FormatVersion(0, 9, 0),
|
||||
"Time to refactor the code.");
|
||||
|
||||
const QDomNodeList list = elementsByTagName(*strImage);
|
||||
if (not list.isEmpty())
|
||||
{
|
||||
QDomElement img = list.at(0).toElement();
|
||||
if (not img.isNull())
|
||||
{
|
||||
QString extension = img.attribute(*strExtension);
|
||||
img.removeAttribute(*strExtension);
|
||||
|
||||
if (not extension.isEmpty())
|
||||
{
|
||||
QMap<QString, QString> mimeTypes{
|
||||
{"BMP", "image/bmp"},
|
||||
{"JPG", "image/jpeg"},
|
||||
{"PNG", "image/png"}
|
||||
};
|
||||
|
||||
if (mimeTypes.contains(extension))
|
||||
{
|
||||
img.setAttribute(*strContentType, mimeTypes.value(extension));
|
||||
}
|
||||
}
|
||||
|
||||
const QString content = img.text();
|
||||
if (not content.isEmpty())
|
||||
{
|
||||
auto SplitString = [content]()
|
||||
{
|
||||
const int n = 80;
|
||||
QStringList list;
|
||||
QString tmp(content);
|
||||
|
||||
while (not tmp.isEmpty())
|
||||
{
|
||||
list.append(tmp.left(n));
|
||||
tmp.remove(0, n);
|
||||
}
|
||||
|
||||
return list;
|
||||
};
|
||||
|
||||
QStringList data = SplitString();
|
||||
setTagText(img, data.join("\n"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VPatternConverter::TagUnionDetailsToV0_4_0()
|
||||
{
|
||||
|
|
|
@ -53,7 +53,7 @@ public:
|
|||
static const QString PatternMaxVerStr;
|
||||
static const QString CurrentSchema;
|
||||
static Q_DECL_CONSTEXPR const unsigned PatternMinVer = FormatVersion(0, 1, 4);
|
||||
static Q_DECL_CONSTEXPR const unsigned PatternMaxVer = FormatVersion(0, 8, 13);
|
||||
static Q_DECL_CONSTEXPR const unsigned PatternMaxVer = FormatVersion(0, 9, 0);
|
||||
|
||||
protected:
|
||||
virtual unsigned MinVer() const override;
|
||||
|
@ -136,6 +136,7 @@ private:
|
|||
void ToV0_8_11();
|
||||
void ToV0_8_12();
|
||||
void ToV0_8_13();
|
||||
void ToV0_9_0();
|
||||
|
||||
void TagUnitToV0_2_0();
|
||||
void TagIncrementToV0_2_0();
|
||||
|
@ -191,6 +192,8 @@ private:
|
|||
|
||||
void RemoveGradationV0_8_8();
|
||||
void AddPieceUUIDV0_8_8();
|
||||
|
||||
void ConvertImageToV0_9_0();
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
|
221
src/libs/ifc/xml/vpatternimage.cpp
Normal file
221
src/libs/ifc/xml/vpatternimage.cpp
Normal file
|
@ -0,0 +1,221 @@
|
|||
/************************************************************************
|
||||
**
|
||||
** @file vpatternimage.cpp
|
||||
** @author Roman Telezhynskyi <dismine(at)gmail.com>
|
||||
** @date 11 1, 2022
|
||||
**
|
||||
** @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) 2022 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 "vpatternimage.h"
|
||||
|
||||
#include <QImage>
|
||||
#include <QImageReader>
|
||||
#include <QMimeDatabase>
|
||||
#include <QPainter>
|
||||
#include <QPixmap>
|
||||
#include <QRegularExpressionMatch>
|
||||
#include <QSvgRenderer>
|
||||
#include <QDebug>
|
||||
#include <QBuffer>
|
||||
#include <QSize>
|
||||
#include <QFile>
|
||||
|
||||
namespace
|
||||
{
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto IsMimeTypeImage(const QMimeType &mime) -> bool
|
||||
{
|
||||
QStringList aliases = mime.aliases();
|
||||
aliases.prepend(mime.name());
|
||||
|
||||
QRegularExpression rx(QStringLiteral("^image\\/[-\\w]+(\\.[-\\w]+)*([+][-\\w]+)?$"));
|
||||
|
||||
return std::any_of(aliases.begin(), aliases.end(), [rx](const QString &name) { return rx.match(name).hasMatch(); });
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto SplitString(QString str) -> QStringList
|
||||
{
|
||||
QStringList list;
|
||||
|
||||
const int n = 80;
|
||||
while (not str.isEmpty())
|
||||
{
|
||||
list.append(str.left(n));
|
||||
str.remove(0, n);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VPatternImage::FromFile(const QString &fileName) -> VPatternImage
|
||||
{
|
||||
VPatternImage image;
|
||||
QMimeType mime = QMimeDatabase().mimeTypeForFile(fileName);
|
||||
|
||||
if (not IsMimeTypeImage(mime))
|
||||
{
|
||||
qCritical() << tr("Unexpected mime type: %1").arg(mime.name());
|
||||
return {};
|
||||
}
|
||||
|
||||
QFile file(fileName);
|
||||
if (not file.open(QIODevice::ReadOnly))
|
||||
{
|
||||
qCritical() << tr("Couldn't read the image. Error: %1").arg(file.errorString());
|
||||
return {};
|
||||
}
|
||||
|
||||
QString base64 = SplitString(QString::fromLatin1(file.readAll().toBase64().data())).join('\n');
|
||||
|
||||
image.SetContentData(base64.toLatin1(), mime.name());
|
||||
return image;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VPatternImage::ContentType() const -> const QString &
|
||||
{
|
||||
return m_contentType;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VPatternImage::ContentData() const -> const QByteArray &
|
||||
{
|
||||
return m_contentData;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VPatternImage::SetContentData(const QByteArray &newContentData, const QString &newContentType)
|
||||
{
|
||||
m_contentData = newContentData;
|
||||
m_contentType = not newContentType.isEmpty() ? newContentType : MimeTypeFromData().name();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VPatternImage::IsNull() const -> bool
|
||||
{
|
||||
return m_contentData.isEmpty();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VPatternImage::IsValid() const -> bool
|
||||
{
|
||||
m_errorString.clear();
|
||||
|
||||
if (IsNull())
|
||||
{
|
||||
m_errorString = tr("No data.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_contentType.isEmpty())
|
||||
{
|
||||
m_errorString = tr("Content type is empty.");
|
||||
return false;
|
||||
}
|
||||
|
||||
QMimeType mime = MimeTypeFromData();
|
||||
QSet<QString> aliases = mime.aliases().toSet();
|
||||
aliases.insert(mime.name());
|
||||
|
||||
QSet<QString> gzipMime {"application/gzip", "application/x-gzip"};
|
||||
|
||||
if (gzipMime.contains(aliases))
|
||||
{
|
||||
QSvgRenderer render(QByteArray::fromBase64(m_contentData));
|
||||
if (render.isValid())
|
||||
{
|
||||
mime = QMimeDatabase().mimeTypeForName(QStringLiteral("image/svg+xml-compressed"));
|
||||
aliases = mime.aliases().toSet();
|
||||
aliases.insert(mime.name());
|
||||
}
|
||||
}
|
||||
|
||||
if (not aliases.contains(m_contentType))
|
||||
{
|
||||
m_errorString = tr("Content type mistmatch.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (not IsMimeTypeImage(mime))
|
||||
{
|
||||
m_errorString = tr("Not image.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VPatternImage::GetPixmap(int width, int height) const -> QPixmap
|
||||
{
|
||||
if (not IsValid())
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
QByteArray array = QByteArray::fromBase64(m_contentData);
|
||||
QBuffer buffer(&array);
|
||||
buffer.open(QIODevice::ReadOnly);
|
||||
|
||||
QImageReader imageReader(&buffer);
|
||||
imageReader.setScaledSize(QSize(width, height));
|
||||
|
||||
QImage image = imageReader.read();
|
||||
if (image.isNull())
|
||||
{
|
||||
qCritical()<< tr("Couldn't read the image. Error: %1").arg(imageReader.errorString());
|
||||
return {};
|
||||
}
|
||||
|
||||
return QPixmap::fromImage(image);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VPatternImage::ErrorString() const -> const QString &
|
||||
{
|
||||
return m_errorString;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VPatternImage::MimeTypeFromData() const -> QMimeType
|
||||
{
|
||||
return QMimeDatabase().mimeTypeForData(QByteArray::fromBase64(m_contentData));
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VPatternImage::Size() const -> QSize
|
||||
{
|
||||
if (not IsValid())
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
QByteArray array = QByteArray::fromBase64(m_contentData);
|
||||
QBuffer buffer(&array);
|
||||
buffer.open(QIODevice::ReadOnly);
|
||||
|
||||
return QImageReader(&buffer).size();
|
||||
}
|
68
src/libs/ifc/xml/vpatternimage.h
Normal file
68
src/libs/ifc/xml/vpatternimage.h
Normal file
|
@ -0,0 +1,68 @@
|
|||
/************************************************************************
|
||||
**
|
||||
** @file vpatternimage.h
|
||||
** @author Roman Telezhynskyi <dismine(at)gmail.com>
|
||||
** @date 11 1, 2022
|
||||
**
|
||||
** @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) 2022 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 VPATTERNIMAGE_H
|
||||
#define VPATTERNIMAGE_H
|
||||
|
||||
#include <QString>
|
||||
#include <QCoreApplication>
|
||||
|
||||
|
||||
class QPixmap;
|
||||
class QMimeType;
|
||||
|
||||
class VPatternImage
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(VPatternImage)
|
||||
public:
|
||||
VPatternImage() = default;
|
||||
|
||||
static auto FromFile(const QString &fileName) -> VPatternImage;
|
||||
|
||||
auto ContentType() const -> const QString &;
|
||||
|
||||
auto ContentData() const -> const QByteArray &;
|
||||
void SetContentData(const QByteArray &newContentData, const QString & newContentType);
|
||||
|
||||
auto IsNull() const -> bool;
|
||||
auto IsValid() const -> bool;
|
||||
|
||||
auto GetPixmap(int width, int height) const -> QPixmap;
|
||||
|
||||
auto ErrorString() const -> const QString &;
|
||||
|
||||
auto MimeTypeFromData() const -> QMimeType;
|
||||
|
||||
auto Size() const -> QSize;
|
||||
|
||||
private:
|
||||
QString m_contentType{};
|
||||
QByteArray m_contentData{};
|
||||
mutable QString m_errorString{};
|
||||
};
|
||||
|
||||
#endif // VPATTERNIMAGE_H
|
|
@ -6,6 +6,7 @@ HEADERS += \
|
|||
$$PWD/vdomdocument.h \
|
||||
$$PWD/vlayoutconverter.h \
|
||||
$$PWD/vpatternconverter.h \
|
||||
$$PWD/vpatternimage.h \
|
||||
$$PWD/vtoolrecord.h \
|
||||
$$PWD/vabstractpattern.h \
|
||||
$$PWD/vvstconverter.h \
|
||||
|
@ -19,6 +20,7 @@ SOURCES += \
|
|||
$$PWD/vdomdocument.cpp \
|
||||
$$PWD/vlayoutconverter.cpp \
|
||||
$$PWD/vpatternconverter.cpp \
|
||||
$$PWD/vpatternimage.cpp \
|
||||
$$PWD/vtoolrecord.cpp \
|
||||
$$PWD/vabstractpattern.cpp \
|
||||
$$PWD/vvstconverter.cpp \
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#
|
||||
#-------------------------------------------------
|
||||
|
||||
QT += testlib widgets printsupport concurrent xml xmlpatterns
|
||||
QT += testlib widgets printsupport concurrent xml xmlpatterns svg
|
||||
|
||||
QT -= gui
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#
|
||||
#-------------------------------------------------
|
||||
|
||||
QT += testlib widgets xml printsupport concurrent xmlpatterns
|
||||
QT += testlib widgets xml printsupport concurrent xmlpatterns svg
|
||||
|
||||
QT -= gui
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#
|
||||
#-------------------------------------------------
|
||||
|
||||
QT += core testlib gui printsupport xml xmlpatterns concurrent
|
||||
QT += core testlib gui printsupport xml xmlpatterns concurrent svg
|
||||
|
||||
TARGET = ValentinaTests
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user