diff --git a/src/app/valentina/dialogs/dialogpatternproperties.cpp b/src/app/valentina/dialogs/dialogpatternproperties.cpp index 702e7eaf4..c85d1f9bc 100644 --- a/src/app/valentina/dialogs/dialogpatternproperties.cpp +++ b/src/app/valentina/dialogs/dialogpatternproperties.cpp @@ -28,7 +28,10 @@ #include "dialogpatternproperties.h" #include "ui_dialogpatternproperties.h" +#include #include +#include +#include #include "../xml/vpattern.h" #include "../vpatterndb/vcontainer.h" #include "../core/vapplication.h" @@ -41,7 +44,11 @@ DialogPatternProperties::DialogPatternProperties(VPattern *doc, VContainer *pat QDialog(parent), ui(new Ui::DialogPatternProperties), doc(doc), pattern(pattern), heightsChecked(MAX_HEIGHTS), sizesChecked(MAX_SIZES), heights (QMap()), sizes(QMap()), data(QMap()), descriptionChanged(false), gradationChanged(false), defaultChanged(false), - securityChanged(false), isInitialized(false) + securityChanged(false), isInitialized(false), + deleteAction(nullptr), + changeImageAction(nullptr), + saveImageAction(nullptr), + showImageAction(nullptr) { ui->setupUi(this); @@ -62,6 +69,8 @@ DialogPatternProperties::DialogPatternProperties(VPattern *doc, VContainer *pat ui->plainTextEditTechNotes->setPlainText(doc->GetNotes()); connect(ui->plainTextEditTechNotes, &QPlainTextEdit::textChanged, this, &DialogPatternProperties::DescEdited); + InitImage(); + connect(ui->buttonBox->button(QDialogButtonBox::Ok), &QPushButton::clicked, this, &DialogPatternProperties::Ok); connect(ui->buttonBox->button(QDialogButtonBox::Apply), &QPushButton::clicked, this, &DialogPatternProperties::Apply); @@ -603,3 +612,145 @@ void DialogPatternProperties::InitComboBox(QComboBox *box, const QMapGetImage().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::InitImage() +{ + ui->imageLabel->setContextMenuPolicy(Qt::CustomContextMenu); + ui->imageLabel->setScaledContents(true); + connect(ui->imageLabel, &QWidget::customContextMenuRequested, this, &DialogPatternProperties::ShowContextMenu); + + deleteAction = new QAction(tr("Delete image"), this); + changeImageAction = new QAction(tr("Change image"), this); + saveImageAction = new QAction(tr("Save image to file"), this); + showImageAction = new QAction(tr("Show image"), this); + + connect(deleteAction, &QAction::triggered, this, &DialogPatternProperties::DeleteImage); + connect(changeImageAction, &QAction::triggered, this, &DialogPatternProperties::ChangeImage); + connect(saveImageAction, &QAction::triggered, this, &DialogPatternProperties::SaveImage); + connect(showImageAction, &QAction::triggered, this, &DialogPatternProperties::ShowImage); + + const QImage image = GetImage(); + if (not image.isNull()) + { + ui->imageLabel->setPixmap(QPixmap::fromImage(image)); + } + else + { + deleteAction->setEnabled(false); + saveImageAction->setEnabled(false); + showImageAction->setEnabled(false); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void DialogPatternProperties::ChangeImage() +{ + const QString fileName = QFileDialog::getOpenFileName(this, tr("Image for pattern"), QString(), + tr("Images (*.png *.jpg *.jpeg *.bmp)")); + QImage image; + if (fileName.isEmpty()) + { + return; + } + else + { + if (not image.load(fileName)) + { + 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()); + + // save our image to file.val + doc->SetImage(iconBase64, extension); + } + deleteAction->setEnabled(true); + saveImageAction->setEnabled(true); + showImageAction->setEnabled(true); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void DialogPatternProperties::DeleteImage() +{ + doc->DeleteImage(); + ui->imageLabel->setText(tr("Change image")); + deleteAction->setEnabled(false); + saveImageAction->setEnabled(false); + showImageAction->setEnabled(false); +} + +//--------------------------------------------------------------------------------------------------------------------- +void DialogPatternProperties::SaveImage() +{ + QByteArray byteArray; + byteArray.append(doc->GetImage().toUtf8()); + QByteArray ba = QByteArray::fromBase64(byteArray); + const QString extension = QLatin1String(".") + doc->GetImageExtension(); + QString filter = tr("Images") + QLatin1String(" (*") + extension + QLatin1String(")"); + QString filename = QFileDialog::getSaveFileName(this, tr("Save File"), tr("untitled"), filter, &filter); + 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(); + } + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void DialogPatternProperties::ShowImage() +{ + 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(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void DialogPatternProperties::ShowContextMenu() +{ + QMenu menu(this); + menu.addAction(deleteAction); + menu.addAction(changeImageAction); + menu.addAction(saveImageAction); + menu.addAction(showImageAction); + menu.exec(QCursor::pos()); + menu.show(); +} diff --git a/src/app/valentina/dialogs/dialogpatternproperties.h b/src/app/valentina/dialogs/dialogpatternproperties.h index f97f0a50b..ce8f07291 100644 --- a/src/app/valentina/dialogs/dialogpatternproperties.h +++ b/src/app/valentina/dialogs/dialogpatternproperties.h @@ -57,12 +57,17 @@ public slots: void CheckStateHeight(int state); void CheckStateSize(int state); void DescEdited(); + void ChangeImage(); + void ShowContextMenu(); protected: virtual void showEvent(QShowEvent *event) Q_DECL_OVERRIDE; private slots: void ToggleComboBox(); void DefValueChanged(); void SecurityValueChanged(); + void DeleteImage(); + void SaveImage(); + void ShowImage(); private: Q_DISABLE_COPY(DialogPatternProperties) Ui::DialogPatternProperties *ui; @@ -78,6 +83,10 @@ private: bool defaultChanged; bool securityChanged; bool isInitialized; + QAction *deleteAction; + QAction *changeImageAction; + QAction *saveImageAction; + QAction *showImageAction; void SetHeightsChecked(bool enabled); void SetSizesChecked(bool enabled); @@ -99,6 +108,8 @@ private: void UpdateDefHeight(); void UpdateDefSize(); + void InitImage(); + QImage GetImage(); }; #endif // DIALOGPATTERNPROPERTIES_H diff --git a/src/app/valentina/dialogs/dialogpatternproperties.ui b/src/app/valentina/dialogs/dialogpatternproperties.ui index 97e241854..c71c33d56 100644 --- a/src/app/valentina/dialogs/dialogpatternproperties.ui +++ b/src/app/valentina/dialogs/dialogpatternproperties.ui @@ -43,20 +43,86 @@ - + + + 0 + + + QLayout::SetMaximumSize + + + 0 + + + 0 + + + 0 + - - - Pattern description - - + + + + + Pattern description + + + + + + + + + + + - - - + + + 6 - + + 0 + + + + + + 200 + 200 + + + + + 150 + 200 + + + + + 200 + 200 + + + + Call context menu for edit + + + No image + + + Qt::AutoText + + + Qt::AlignCenter + + + 1 + + + + diff --git a/src/app/valentina/xml/vpattern.cpp b/src/app/valentina/xml/vpattern.cpp index f0485fd95..31c89cbf0 100644 --- a/src/app/valentina/xml/vpattern.cpp +++ b/src/app/valentina/xml/vpattern.cpp @@ -129,7 +129,7 @@ void VPattern::Parse(const Document &parse) SCASSERT(sceneDraw != nullptr); SCASSERT(sceneDetail != nullptr); QStringList tags = QStringList() << TagDraw << TagIncrements << TagAuthor << TagDescription << TagNotes - << TagMeasurements << TagVersion << TagGradation << TagUnit; + << TagMeasurements << TagVersion << TagGradation << TagImage << TagUnit; PrepareForParse(parse); QDomNode domNode = documentElement().firstChild(); while (domNode.isNull() == false) @@ -183,7 +183,10 @@ void VPattern::Parse(const Document &parse) case 7: // TagGradation qCDebug(vXML, "Tag gradation."); break; - case 8: // TagUnit + case 8: // TagImage + qCDebug(vXML, "Tag image."); + break; + case 9: // TagUnit qCDebug(vXML, "Tag unit."); break; default: @@ -2899,7 +2902,7 @@ void VPattern::SetDefCustom(bool value) { CheckTagExists(TagGradation); QDomNodeList tags = elementsByTagName(TagGradation); - if (tags.size() == 0) + if (tags.isEmpty()) { qDebug()<<"Can't save attribute "< + + + + + + + + + @@ -342,6 +351,13 @@ + + + + + + + diff --git a/src/libs/ifc/xml/vabstractpattern.cpp b/src/libs/ifc/xml/vabstractpattern.cpp index 9b4758bf7..ca528a4ab 100644 --- a/src/libs/ifc/xml/vabstractpattern.cpp +++ b/src/libs/ifc/xml/vabstractpattern.cpp @@ -41,6 +41,7 @@ const QString VAbstractPattern::TagDetails = QStringLiteral("details"); const QString VAbstractPattern::TagAuthor = QStringLiteral("author"); const QString VAbstractPattern::TagDescription = QStringLiteral("description"); const QString VAbstractPattern::TagNotes = QStringLiteral("notes"); +const QString VAbstractPattern::TagImage = QStringLiteral("image"); const QString VAbstractPattern::TagMeasurements = QStringLiteral("measurements"); const QString VAbstractPattern::TagIncrements = QStringLiteral("increments"); const QString VAbstractPattern::TagIncrement = QStringLiteral("increment"); @@ -107,6 +108,7 @@ const QString VAbstractPattern::AttrS56 = QStringLiteral("s56"); const QString VAbstractPattern::AttrCustom = QStringLiteral("custom"); const QString VAbstractPattern::AttrDefHeight = QStringLiteral("defHeight"); const QString VAbstractPattern::AttrDefSize = QStringLiteral("defSize"); +const QString VAbstractPattern::AttrExtension = QStringLiteral("extension"); const QString VAbstractPattern::IncrementName = QStringLiteral("name"); const QString VAbstractPattern::IncrementFormula = QStringLiteral("formula"); @@ -701,7 +703,7 @@ void VAbstractPattern::SetGradationHeights(const QMap &options) { CheckTagExists(TagGradation); QDomNodeList tags = elementsByTagName(TagGradation); - if (tags.size() == 0) + if (tags.isEmpty()) { qDebug()<<"Can't save tag "< &options) { CheckTagExists(TagGradation); QDomNodeList tags = elementsByTagName(TagGradation); - if (tags.size() == 0) + if (tags.isEmpty()) { qDebug()<<"Can't save tag "<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) +{ + QDomElement imageElement = CheckTagExists(TagImage); + setTagText(imageElement, text); + CheckTagExists(TagImage).setAttribute(AttrExtension, extension); + modified = true; + emit patternChanged(false); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VAbstractPattern::DeleteImage() +{ + QDomElement pattern = documentElement(); + pattern.removeChild(CheckTagExists(TagImage)); + modified = true; + emit patternChanged(false); +} + //--------------------------------------------------------------------------------------------------------------------- QString VAbstractPattern::GetVersion() const { @@ -1041,78 +1093,81 @@ void VAbstractPattern::SetActivPP(const QString &name) } //--------------------------------------------------------------------------------------------------------------------- -void VAbstractPattern::CheckTagExists(const QString &tag) +QDomElement VAbstractPattern::CheckTagExists(const QString &tag) { - QDomNodeList list = elementsByTagName(tag); - if (list.size() == 0) + const QDomNodeList list = elementsByTagName(tag); + QDomElement element; + if (list.isEmpty()) { - QStringList tags = QStringList() << TagVersion << TagAuthor << TagDescription << TagNotes << TagGradation; - QDomElement pattern = documentElement(); + const QStringList tags = QStringList() << TagUnit << TagImage << TagAuthor << TagDescription << TagNotes + << TagGradation; switch (tags.indexOf(tag)) { - case 0: //TagVersion + case 0: //TagUnit + { + return QDomElement(); break;// Mandatory tag - case 1: //TagAuthor - pattern.insertAfter(createElement(TagAuthor), elementsByTagName(TagVersion).at(0)); - SetVersion(); - break; - case 2: //TagDescription + } + case 1: //TagImage { - for (int i = tags.indexOf(tag)-1; i >= 0; --i) - { - QDomNodeList list = elementsByTagName(tags.at(i)); - if (list.isEmpty()) - { - continue; - } - pattern.insertAfter(createElement(TagDescription), list.at(0)); - } - SetVersion(); + element = createElement(TagImage); break; } - case 3: //TagNotes + case 2: //TagAuthor { - for (int i = tags.indexOf(tag)-1; i >= 0; --i) - { - QDomNodeList list = elementsByTagName(tags.at(i)); - if (list.isEmpty()) - { - continue; - } - pattern.insertAfter(createElement(TagNotes), list.at(0)); - } - SetVersion(); + element = createElement(TagAuthor); break; } - case 4: //TagGradation + case 3: //TagDescription { - QDomElement gradation = createElement(TagGradation); + element = createElement(TagDescription); + break; + } + case 4: //TagNotes + { + element = createElement(TagNotes); + break; + } + case 5: //TagGradation + { + element = createElement(TagGradation); QDomElement heights = createElement(TagHeights); heights.setAttribute(AttrAll, QLatin1Literal("true")); - gradation.appendChild(heights); + element.appendChild(heights); QDomElement sizes = createElement(TagSizes); sizes.setAttribute(AttrAll, QLatin1Literal("true")); - gradation.appendChild(sizes); - - for (int i = tags.indexOf(tag)-1; i >= 0; --i) - { - QDomNodeList list = elementsByTagName(tags.at(i)); - if (list.isEmpty()) - { - continue; - } - pattern.insertAfter(gradation, list.at(0)); - break; - } - SetVersion(); + element.appendChild(sizes); break; } default: + { + return QDomElement(); break; + } } + InsertTag(tags, element); + return element; } + return list.at(0).toElement(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VAbstractPattern::InsertTag(const QStringList &tags, const QDomElement &element) +{ + QDomElement pattern = documentElement(); + for (int i = tags.indexOf(element.tagName())-1; i >= 0; --i) + { + const QDomNodeList list = elementsByTagName(tags.at(i)); + if (list.isEmpty()) + { + continue; + } + pattern.insertAfter(element, list.at(0)); + break; + } + SetVersion(); } //--------------------------------------------------------------------------------------------------------------------- diff --git a/src/libs/ifc/xml/vabstractpattern.h b/src/libs/ifc/xml/vabstractpattern.h index 0f5c77396..8524b4f9f 100644 --- a/src/libs/ifc/xml/vabstractpattern.h +++ b/src/libs/ifc/xml/vabstractpattern.h @@ -106,6 +106,11 @@ public: QString GetNotes() const; void SetNotes(const QString &text); + QString GetImage() const; + QString GetImageExtension() const; + void SetImage(const QString &text, const QString &extension); + void DeleteImage(); + QString GetVersion() const; void SetVersion(); @@ -129,6 +134,7 @@ public: static const QString TagDetails; static const QString TagAuthor; static const QString TagDescription; + static const QString TagImage; static const QString TagNotes; static const QString TagMeasurements; static const QString TagIncrements; @@ -196,6 +202,7 @@ public: static const QString AttrCustom; static const QString AttrDefHeight; static const QString AttrDefSize; + static const QString AttrExtension; static const QString IncrementName; static const QString IncrementFormula; @@ -272,7 +279,8 @@ protected: void SetActivPP(const QString& name); - void CheckTagExists(const QString &tag); + QDomElement CheckTagExists(const QString &tag); + void InsertTag(const QStringList &tags, const QDomElement &element); private: Q_DISABLE_COPY(VAbstractPattern) diff --git a/src/libs/ifc/xml/vdomdocument.cpp b/src/libs/ifc/xml/vdomdocument.cpp index f0d6bae55..0a44f9841 100644 --- a/src/libs/ifc/xml/vdomdocument.cpp +++ b/src/libs/ifc/xml/vdomdocument.cpp @@ -698,24 +698,29 @@ bool VDomDocument::setTagText(const QString &tag, const QString &text) if (domNode.isNull() == false && domNode.isElement()) { const QDomElement domElement = domNode.toElement(); - if (domElement.isNull() == false) - { - QDomElement parent = domElement.parentNode().toElement(); - QDomElement newTag = createElement(tag); - if (not text.isEmpty()) - { - const QDomText newTagText = createTextNode(text); - newTag.appendChild(newTagText); - } - - parent.replaceChild(newTag, domElement); - return true; - } + return setTagText(domElement, text); } } return false; } +//--------------------------------------------------------------------------------------------------------------------- +bool VDomDocument::setTagText(const QDomElement &domElement, const QString &text) +{ + if (domElement.isNull() == false) + { + QDomElement parent = domElement.parentNode().toElement(); + QDomElement newTag = createElement(domElement.tagName()); + + const QDomText newTagText = createTextNode(text); + newTag.appendChild(newTagText); + + parent.replaceChild(newTag, domElement); + return true; + } + return false; +} + //--------------------------------------------------------------------------------------------------------------------- /** * @brief RemoveAllChildren remove all children from file. diff --git a/src/libs/ifc/xml/vdomdocument.h b/src/libs/ifc/xml/vdomdocument.h index 538bdabcd..4972d7796 100644 --- a/src/libs/ifc/xml/vdomdocument.h +++ b/src/libs/ifc/xml/vdomdocument.h @@ -115,6 +115,7 @@ public: protected: bool setTagText(const QString &tag, const QString &text); + bool setTagText(const QDomElement &domElement, const QString &text); QString UniqueTagText(const QString &tagName, const QString &defVal = QString()) const; void TestUniqueId() const; diff --git a/src/libs/vtools/dialogs/tools/dialogtool.h b/src/libs/vtools/dialogs/tools/dialogtool.h index 86e752be2..2eeec1370 100644 --- a/src/libs/vtools/dialogs/tools/dialogtool.h +++ b/src/libs/vtools/dialogs/tools/dialogtool.h @@ -32,7 +32,7 @@ #include "../vmisc/vabstractapplication.h" #include "../vmisc/logging.h" #include "../vwidgets/vmaingraphicsscene.h" -#include "../../visualization/visualization.h" +#include "visualization/visualization.h" #include "../ifc/xml/vabstractpattern.h" #include