diff --git a/ChangeLog.txt b/ChangeLog.txt
index 1757f2ada..d45a7a8ae 100644
--- a/ChangeLog.txt
+++ b/ChangeLog.txt
@@ -35,6 +35,7 @@
- New feature Pattern Messages.
- [#984] Special variable "CurrentLength" for tools Cut Arc, Cut Spline and Cut Spline Path.
- Added a ruler at the bottom of a tiled PDF document.
+- Export tiled PDF with watermark.
# Version 0.6.2 (unreleased)
- [#903] Bug in tool Cut Spline path.
diff --git a/src/app/valentina/dialogs/dialogpatternproperties.ui b/src/app/valentina/dialogs/dialogpatternproperties.ui
index 90117708f..4f5631aa7 100644
--- a/src/app/valentina/dialogs/dialogpatternproperties.ui
+++ b/src/app/valentina/dialogs/dialogpatternproperties.ui
@@ -14,7 +14,7 @@
Pattern properties
-
+
:/icon/64x64/icon64x64.png:/icon/64x64/icon64x64.png
@@ -1220,13 +1220,26 @@
Security
- -
+
-
Open only for read
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
@@ -1421,20 +1434,18 @@
-
- VPlainTextEdit
- QPlainTextEdit
-
-
VLineEdit
QLineEdit
+
+ VPlainTextEdit
+ QPlainTextEdit
+
+
-
-
-
+
buttonBox
diff --git a/src/app/valentina/mainwindow.cpp b/src/app/valentina/mainwindow.cpp
index 0f5cf844f..f4e542ab8 100644
--- a/src/app/valentina/mainwindow.cpp
+++ b/src/app/valentina/mainwindow.cpp
@@ -64,6 +64,7 @@
#include "../qmuparser/qmuparsererror.h"
#include "../vtools/dialogs/support/dialogeditlabel.h"
#include "../vformat/vpatternrecipe.h"
+#include "watermarkwindow.h"
#if QT_VERSION < QT_VERSION_CHECK(5, 12, 0)
#include "../vmisc/backport/qscopeguard.h"
@@ -1933,6 +1934,69 @@ void MainWindow::SyncMeasurements()
}
}
+//---------------------------------------------------------------------------------------------------------------------
+void MainWindow::CreateWatermark()
+{
+ CleanWaterkmarkEditors();
+ OpenWatermark();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void MainWindow::EditCurrentWatermark()
+{
+ CleanWaterkmarkEditors();
+
+ QString watermarkFile = doc->GetWatermarkPath();
+ if (not watermarkFile.isEmpty())
+ {
+ OpenWatermark(watermarkFile);
+ }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void MainWindow::LoadWatermark()
+{
+ const QString filter(tr("Watermark files") + QLatin1String(" (*.vwm)"));
+ QString dir = QDir::homePath();
+ qDebug("Run QFileDialog::getOpenFileName: dir = %s.", qUtf8Printable(dir));
+ const QString filePath = QFileDialog::getOpenFileName(this, tr("Open file"), dir, filter, nullptr);
+ if (filePath.isEmpty())
+ {
+ return;
+ }
+
+ if (doc->SetWatermarkPath(filePath))
+ {
+ ui->actionRemoveWatermark->setEnabled(true);
+ ui->actionEditCurrentWatermark->setEnabled(true);
+ }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void MainWindow::RemoveWatermark()
+{
+ if (doc->SetWatermarkPath(QString()))
+ {
+ ui->actionRemoveWatermark->setEnabled(false);
+ ui->actionEditCurrentWatermark->setEnabled(false);
+ }
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------
+void MainWindow::CleanWaterkmarkEditors()
+{
+ QMutableListIterator> i(m_watermarkEditors);
+ while (i.hasNext())
+ {
+ QPointer watermarkEditor = i.next();
+ if (watermarkEditor.isNull())
+ {
+ i.remove();
+ }
+ }
+}
+
//---------------------------------------------------------------------------------------------------------------------
#if defined(Q_OS_MAC)
void MainWindow::OpenAt(QAction *where)
@@ -3153,6 +3217,9 @@ void MainWindow::Clear()
ui->actionOriginalLabelFont->setEnabled(false);
ui->actionHideLabels->setEnabled(false);
ui->plainTextEditPatternMessages->clear();
+ ui->actionLoadWatermark->setEnabled(false);
+ ui->actionRemoveWatermark->setEnabled(false);
+ ui->actionEditCurrentWatermark->setEnabled(false);
}
//---------------------------------------------------------------------------------------------------------------------
@@ -3513,6 +3580,10 @@ void MainWindow::SetEnableWidgets(bool enable)
ui->actionOriginalLabelFont->setEnabled(enable);
ui->actionHideLabels->setEnabled(enable);
+ ui->actionLoadWatermark->setEnabled(enable);
+ ui->actionRemoveWatermark->setEnabled(enable && not doc->GetWatermarkPath().isEmpty());
+ ui->actionEditCurrentWatermark->setEnabled(enable && not doc->GetWatermarkPath().isEmpty());
+
actionDockWidgetToolOptions->setEnabled(enable && designStage);
actionDockWidgetGroups->setEnabled(enable && designStage);
@@ -4630,6 +4701,11 @@ void MainWindow::CreateActions()
DialogEditLabel editor(doc);
editor.exec();
});
+
+ connect(ui->actionWatermarkEditor, &QAction::triggered, this, &MainWindow::CreateWatermark);
+ connect(ui->actionEditCurrentWatermark, &QAction::triggered, this, &MainWindow::EditCurrentWatermark);
+ connect(ui->actionLoadWatermark, &QAction::triggered, this, &MainWindow::LoadWatermark);
+ connect(ui->actionRemoveWatermark, &QAction::triggered, this, &MainWindow::RemoveWatermark);
}
//---------------------------------------------------------------------------------------------------------------------
@@ -6161,3 +6237,25 @@ void MainWindow::PrintPatternMessage(QEvent *event)
m_unreadPatternMessage->setText(DialogWarningIcon() + tr("Pattern messages"));
}
}
+
+//---------------------------------------------------------------------------------------------------------------------
+void MainWindow::OpenWatermark(const QString &path)
+{
+ QList>::const_iterator i;
+ for (i = m_watermarkEditors.begin(); i != m_watermarkEditors.end(); ++i)
+ {
+ if (not (*i).isNull() && not (*i)->CurrentFile().isEmpty()
+ && (*i)->CurrentFile() == AbsoluteMPath(qApp->GetPatternPath(), path))
+ {
+ (*i)->show();
+ return;
+ }
+ }
+
+ auto *watermark = new WatermarkWindow(qApp->GetPatternPath(), this);
+ connect(watermark, &WatermarkWindow::New, this, [this](){OpenWatermark();});
+ connect(watermark, &WatermarkWindow::OpenAnother, this, [this](const QString &path){OpenWatermark(path);});
+ m_watermarkEditors.append(watermark);
+ watermark->show();
+ watermark->Open(path);
+}
diff --git a/src/app/valentina/mainwindow.h b/src/app/valentina/mainwindow.h
index ea85cdd67..ae4db1910 100644
--- a/src/app/valentina/mainwindow.h
+++ b/src/app/valentina/mainwindow.h
@@ -53,6 +53,7 @@ class VWidgetDetails;
class QToolButton;
class QDoubleSpinBox;
class QProgressBar;
+class WatermarkWindow;
/**
* @brief The MainWindow class main windows.
@@ -197,6 +198,11 @@ private slots:
void ShowMeasurements();
void MeasurementsChanged(const QString &path);
void SyncMeasurements();
+
+ void CreateWatermark();
+ void EditCurrentWatermark();
+ void LoadWatermark();
+ void RemoveWatermark();
#if defined(Q_OS_MAC)
void OpenAt(QAction *where);
#endif //defined(Q_OS_MAC)
@@ -276,6 +282,8 @@ private:
QProgressBar *m_progressBar;
QLabel *m_statusLabel;
+ QList> m_watermarkEditors{};
+
void SetDefaultHeight();
void SetDefaultSize();
@@ -381,6 +389,9 @@ private:
void ToolSelectDetail();
void PrintPatternMessage(QEvent *event);
+
+ void OpenWatermark(const QString &path = QString());
+ void CleanWaterkmarkEditors();
};
#endif // MAINWINDOW_H
diff --git a/src/app/valentina/mainwindow.ui b/src/app/valentina/mainwindow.ui
index 3a6cd41c5..45663747b 100644
--- a/src/app/valentina/mainwindow.ui
+++ b/src/app/valentina/mainwindow.ui
@@ -1795,11 +1795,22 @@
+
+
@@ -2980,6 +2991,50 @@
Globally show pieces main path
+
+
+ false
+
+
+
+ ..
+
+
+ Load
+
+
+
+
+ false
+
+
+
+ ..
+
+
+ Remove
+
+
+
+
+ false
+
+
+ Edit current
+
+
+
+
+
+ ..
+
+
+ Editor
+
+
+ Create or edit a watermark
+
+
diff --git a/src/app/valentina/mainwindowsnogui.cpp b/src/app/valentina/mainwindowsnogui.cpp
index be9ac961c..281de0200 100644
--- a/src/app/valentina/mainwindowsnogui.cpp
+++ b/src/app/valentina/mainwindowsnogui.cpp
@@ -36,6 +36,7 @@
#include "../vmisc/dialogs/dialogexporttocsv.h"
#include "../vmisc/qxtcsvmodel.h"
#include "../vformat/vmeasurements.h"
+#include "../vformat/vwatermark.h"
#include "../vlayout/vlayoutgenerator.h"
#include "dialogs/dialoglayoutprogress.h"
#include "dialogs/dialogsavelayout.h"
@@ -49,6 +50,7 @@
#include "../vtools/tools/vtoolseamallowance.h"
#include "../ifc/xml/vvstconverter.h"
#include "../ifc/xml/vvitconverter.h"
+#include "../ifc/xml/vwatermarkconverter.h"
#include
#include
@@ -876,6 +878,31 @@ void MainWindowsNoGUI::PrintPages(QPrinter *printer)
copyCount = printer->copyCount();
}
+ VWatermarkData data;
+ const QString watermarkPath = AbsoluteMPath(qApp->GetPatternPath(), doc->GetWatermarkPath());
+ if (not watermarkPath.isEmpty())
+ {
+ try
+ {
+ VWatermarkConverter converter(watermarkPath);
+ VWatermark watermark;
+ watermark.setXMLContent(converter.Convert());
+ data = watermark.GetWatermark();
+
+ if (not data.path.isEmpty())
+ {
+ // Clean previous cache
+ QPixmapCache::remove(AbsoluteMPath(watermarkPath, data.path));
+ }
+ }
+ catch (VException &e)
+ {
+ const QString errorMsg = tr("File error.\n\n%1\n\n%2").arg(e.ErrorMessage(), e.DetailedInformation());
+ qApp->IsPedantic() ? throw VException(errorMsg) :
+ qWarning() << VAbstractApplication::patternMessageSignature + errorMsg;
+ }
+ }
+
for (int i = 0; i < copyCount; ++i)
{
for (int j = 0; j < numPages; ++j)
@@ -905,10 +932,11 @@ void MainWindowsNoGUI::PrintPages(QPrinter *printer)
if (paper)
{
QVector posterData;
+
if (isTiled)
{
- // Draw borders
- posterData = posterazor->Borders(paper, poster->at(index), scenes.size());
+ // Draw tile
+ posterData = posterazor->Tile(paper, poster->at(index), scenes.size(), data, watermarkPath);
}
PreparePaper(paperIndex);
@@ -1408,7 +1436,6 @@ void MainWindowsNoGUI::PreparePaper(int index) const
shadows.at(index)->setVisible(false);
paper->setPen(QPen(Qt::white, 0.1, Qt::NoPen));// border
}
-
}
//---------------------------------------------------------------------------------------------------------------------
@@ -1718,43 +1745,6 @@ void MainWindowsNoGUI::SetPrinterSettings(QPrinter *printer, const PrintType &pr
}
printer->setDocName(FileName());
-
- IsLayoutGrayscale() ? printer->setColorMode(QPrinter::GrayScale) : printer->setColorMode(QPrinter::Color);
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-bool MainWindowsNoGUI::IsLayoutGrayscale() const
-{
- const QRect target = QRect(0, 0, 100, 100);//Small image less memory need
-
- for (int i=0; i < scenes.size(); ++i)
- {
- if (auto *paper = qgraphicsitem_cast(papers.at(i)))
- {
- // Hide shadow and paper border
- PreparePaper(i);
-
- // Render png
- QImage image(target.size(), QImage::Format_RGB32);
- image.fill(Qt::white);
- QPainter painter(&image);
- painter.setPen(QPen(Qt::black, qApp->Settings()->WidthMainLine(), Qt::SolidLine, Qt::RoundCap,
- Qt::RoundJoin));
- painter.setBrush ( QBrush ( Qt::NoBrush ) );
- scenes.at(i)->render(&painter, target, paper->rect(), Qt::KeepAspectRatio);
- painter.end();
-
- // Restore
- RestorePaper(i);
-
- if (not image.isGrayscale())
- {
- return false;
- }
- }
- }
-
- return true;
}
//---------------------------------------------------------------------------------------------------------------------
diff --git a/src/app/valentina/mainwindowsnogui.h b/src/app/valentina/mainwindowsnogui.h
index 30e7a0479..0db57b567 100644
--- a/src/app/valentina/mainwindowsnogui.h
+++ b/src/app/valentina/mainwindowsnogui.h
@@ -39,6 +39,7 @@
#include "dialogs/dialogsavelayout.h"
#include "../vlayout/vlayoutgenerator.h"
#include "../vwidgets/vabstractmainwindow.h"
+#include "../vlayout/vtextmanager.h"
class QGraphicsScene;
struct PosterData;
@@ -194,7 +195,6 @@ private:
enum class PrintType : char {PrintPDF, PrintPreview, PrintNative};
void SetPrinterSettings(QPrinter *printer, const PrintType &printType);
- bool IsLayoutGrayscale() const;
QPageSize::PageSizeId FindPageSizeId(const QSizeF &size) const;
bool isPagesUniform() const;
diff --git a/src/app/valentina/valentina.pri b/src/app/valentina/valentina.pri
index 772b54f49..32fa0d9dd 100644
--- a/src/app/valentina/valentina.pri
+++ b/src/app/valentina/valentina.pri
@@ -10,7 +10,8 @@ include(core/core.pri)
SOURCES += \
$$PWD/main.cpp \
$$PWD/mainwindow.cpp \
- $$PWD/mainwindowsnogui.cpp
+ $$PWD/mainwindowsnogui.cpp \
+ $$PWD/watermarkwindow.cpp
*msvc*:SOURCES += $$PWD/stable.cpp
@@ -19,7 +20,10 @@ HEADERS += \
$$PWD/mainwindow.h \
$$PWD/stable.h \
$$PWD/version.h \
- $$PWD/mainwindowsnogui.h
+ $$PWD/mainwindowsnogui.h \
+ $$PWD/watermarkwindow.h
+
# Main forms
FORMS += \
- $$PWD/mainwindow.ui
+ $$PWD/mainwindow.ui \
+ $$PWD/watermarkwindow.ui
diff --git a/src/app/valentina/watermarkwindow.cpp b/src/app/valentina/watermarkwindow.cpp
new file mode 100644
index 000000000..f801ade79
--- /dev/null
+++ b/src/app/valentina/watermarkwindow.cpp
@@ -0,0 +1,728 @@
+/************************************************************************
+ **
+ ** @file watermarkwindow.cpp
+ ** @author Roman Telezhynskyi
+ ** @date 24 12, 2019
+ **
+ ** @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) 2019 Valentina project
+ ** 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 .
+ **
+ *************************************************************************/
+#include "watermarkwindow.h"
+#include "ui_watermarkwindow.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "../vmisc/def.h"
+#include "core/vapplication.h"
+#include "../vpropertyexplorer/checkablemessagebox.h"
+#include "../ifc/exception/vexception.h"
+#include "../ifc/xml/vwatermarkconverter.h"
+
+//---------------------------------------------------------------------------------------------------------------------
+WatermarkWindow::WatermarkWindow(const QString &patternPath, QWidget *parent) :
+ QMainWindow(parent),
+ ui(new Ui::WatermarkWindow),
+ m_patternPath(patternPath),
+ m_okPathColor()
+{
+ ui->setupUi(this);
+ m_okPathColor = ui->lineEditPath->palette().color(ui->lineEditPath->foregroundRole());
+
+ qApp->Settings()->GetOsSeparator() ? setLocale(QLocale()) : setLocale(QLocale::c());
+ UpdateWindowTitle();
+
+ m_curFileFormatVersion = VWatermarkConverter::WatermarkMaxVer;
+ m_curFileFormatVersionStr = VWatermarkConverter::WatermarkMaxVerStr;
+
+ ToolBarStyle(ui->toolBar);
+
+ connect(ui->spinBoxOpacity, QOverload::of(&QSpinBox::valueChanged),this,
+ [this](){WatermarkChangesWereSaved(false);});
+
+ connect(ui->lineEditText, &QLineEdit::textChanged, this, [this]()
+ {
+ WatermarkChangesWereSaved(false);
+ });
+
+ connect(ui->spinBoxTextRotation, QOverload::of(&QSpinBox::valueChanged),this,
+ [this](){WatermarkChangesWereSaved(false);});
+
+ connect(ui->toolButtonFont, &QToolButton::clicked, this, [this]()
+ {
+ bool ok;
+ QFont font = QFontDialog::getFont(&ok, m_data.font, this);
+ if (ok)
+ {
+ WatermarkChangesWereSaved(false);
+ m_data.font = font;
+ ui->lineEditFontSample->setFont(font);
+ }
+ });
+
+ connect(ui->lineEditPath, &QLineEdit::textChanged, this, [this]()
+ {
+ WatermarkChangesWereSaved(false);
+ ValidatePath();
+ });
+
+ connect(ui->pushButtonBrowse, &QPushButton::clicked, this, [this]()
+ {
+ const QString filter = tr("Images") + QLatin1String(" (*.png *.jpg *.jpeg *.bmp)");
+ const QString fileName = QFileDialog::getOpenFileName(this, tr("Watermark image"), QString(), filter,
+ nullptr);
+ if (not fileName.isEmpty())
+ {
+ ui->lineEditPath->setText(fileName);
+ }
+ });
+
+ connect(ui->spinBoxImageRotation, QOverload::of(&QSpinBox::valueChanged),this,
+ [this](){WatermarkChangesWereSaved(false);});
+
+ connect(ui->checkBoxGrayColor, &QCheckBox::stateChanged, this, [this](){WatermarkChangesWereSaved(false);});
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+WatermarkWindow::~WatermarkWindow()
+{
+ delete ui;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QString WatermarkWindow::CurrentFile() const
+{
+ return m_curFile;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+bool WatermarkWindow::Open(QString path)
+{
+ qDebug("Loading new watermark file %s.", qUtf8Printable(path));
+
+ if (path.isEmpty())
+ {
+ qDebug("Path is empty");
+ Clear();
+ return false;
+ }
+
+ // Convert to absolute path if need
+ path = AbsoluteMPath(m_patternPath, path);
+
+ QFuture futureConverter = QtConcurrent::run([path]()
+ {
+ QScopedPointer converter(new VWatermarkConverter(path));
+ return converter.take();
+ });
+
+ //We have unsaved changes or load more then one file per time
+ if (OpenNewEditor(path))
+ {
+ return false;
+ }
+
+ qDebug("Loking watermark file");
+ VlpCreateLock(lock, path);
+
+ if (lock->IsLocked())
+ {
+ qDebug("Watermark file %s was locked.", qUtf8Printable(path));
+ }
+ else
+ {
+ if (not IgnoreLocking(lock->GetLockError(), path))
+ {
+ return false;
+ }
+ }
+
+ VWatermark doc;
+
+ try
+ {
+ QScopedPointer converter(futureConverter.result());
+ m_curFileFormatVersion = converter->GetCurrentFormatVersion();
+ m_curFileFormatVersionStr = converter->GetFormatVersionStr();
+ doc.setXMLContent(converter->Convert());
+ }
+ catch (VException &e)
+ {
+ qCritical("%s\n\n%s\n\n%s", qUtf8Printable(tr("File error.")),
+ qUtf8Printable(e.ErrorMessage()), qUtf8Printable(e.DetailedInformation()));
+ Clear();
+ return false;
+ }
+
+ m_curFile = path;
+ UpdateWindowTitle();
+ m_data = doc.GetWatermark();
+ ShowWatermark();
+
+ return true;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void WatermarkWindow::closeEvent(QCloseEvent *event)
+{
+#if defined(Q_OS_MAC) && QT_VERSION < QT_VERSION_CHECK(5, 11, 1)
+ // Workaround for Qt bug https://bugreports.qt.io/browse/QTBUG-43344
+ static int numCalled = 0;
+ if (numCalled++ >= 1)
+ {
+ return;
+ }
+#endif
+
+ if (MaybeSave())
+ {
+ event->accept();
+ deleteLater();
+ }
+ else
+ {
+ event->ignore();
+ }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void WatermarkWindow::changeEvent(QEvent *event)
+{
+ if (event->type() == QEvent::LanguageChange)
+ {
+ // retranslate designer form (single inheritance approach)
+ ui->retranslateUi(this);
+
+ UpdateWindowTitle();
+ }
+ // remember to call base class implementation
+ QMainWindow::changeEvent(event);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void WatermarkWindow::showEvent(QShowEvent *event)
+{
+ QMainWindow::showEvent( event );
+ if ( event->spontaneous() )
+ {
+ return;
+ }
+
+ if (m_isInitialized)
+ {
+ return;
+ }
+ // do your init stuff here
+
+ QSize sz = qApp->ValentinaSettings()->GetWatermarkEditorSize();
+ if (sz.isEmpty() == false)
+ {
+ resize(sz);
+ }
+
+ m_isInitialized = true;//first show windows are held
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void WatermarkWindow::resizeEvent(QResizeEvent *event)
+{
+ // remember the size for the next time this window is opened, but only
+ // if the window was already initialized, which rules out the resize at
+ // window creating, which would
+ if (m_isInitialized)
+ {
+ qApp->ValentinaSettings()->SetWatermarkEditorSize(size());
+ }
+ QMainWindow::resizeEvent(event);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void WatermarkWindow::on_actionNew_triggered()
+{
+ emit New();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+bool WatermarkWindow::on_actionSaveAs_triggered()
+{
+ QString filters(tr("Watermark files") + QLatin1String("(*.vwm)"));
+ QString dir;
+ if (m_curFile.isEmpty())
+ {
+ dir = QDir::homePath();
+ }
+ else
+ {
+ dir = QFileInfo(m_curFile).absolutePath();
+ }
+
+ QString fileName = QFileDialog::getSaveFileName(this, tr("Save as"),
+ dir + QLatin1String("/") + tr("watermark") + QLatin1String(".vwm"),
+ filters, nullptr);
+
+ if (fileName.isEmpty())
+ {
+ return false;
+ }
+
+ QFileInfo f( fileName );
+ if (f.suffix().isEmpty() && f.suffix() != QLatin1String("vwm"))
+ {
+ fileName += QLatin1String(".vwm");
+ }
+
+ if (f.exists() && m_curFile != fileName)
+ {
+ // Temporary try to lock the file before saving
+ VLockGuard tmp(fileName);
+ if (not tmp.IsLocked())
+ {
+ qCritical("%s", qUtf8Printable(tr("Failed to lock. This file already opened in another window.")));
+ return false;
+ }
+ }
+
+ QString error;
+ const bool result = SaveWatermark(fileName, error);
+ if (not result)
+ {
+ QMessageBox messageBox(this);
+ messageBox.setIcon(QMessageBox::Warning);
+ messageBox.setInformativeText(tr("Could not save file"));
+ messageBox.setDefaultButton(QMessageBox::Ok);
+ messageBox.setDetailedText(error);
+ messageBox.setStandardButtons(QMessageBox::Ok);
+ messageBox.exec();
+
+ return result;
+ }
+
+ if (m_curFile == fileName && not lock.isNull())
+ {
+ lock->Unlock();
+ }
+ VlpCreateLock(lock, fileName);
+
+ if (lock->IsLocked())
+ {
+ qDebug("Watermark file %s was locked.", qUtf8Printable(fileName));
+ }
+ else
+ {
+ qDebug("Failed to lock %s", qUtf8Printable(fileName));
+ qDebug("Error type: %d", lock->GetLockError());
+ qCritical("%s", qUtf8Printable(tr("Failed to lock. This file already opened in another window. Expect "
+ "collissions when run 2 copies of the program.")));
+ }
+
+ return result;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+bool WatermarkWindow::on_actionSave_triggered()
+{
+ if (m_curFile.isEmpty())
+ {
+ return on_actionSaveAs_triggered();
+ }
+ else
+ {
+ if (m_curFileFormatVersion < VWatermarkConverter::WatermarkMaxVer
+ && not ContinueFormatRewrite(m_curFileFormatVersionStr, VWatermarkConverter::WatermarkMaxVerStr))
+ {
+ return false;
+ }
+#ifdef Q_OS_WIN32
+ qt_ntfs_permission_lookup++; // turn checking on
+#endif /*Q_OS_WIN32*/
+ const bool isFileWritable = QFileInfo(m_curFile).isWritable();
+#ifdef Q_OS_WIN32
+ qt_ntfs_permission_lookup--; // turn it off again
+#endif /*Q_OS_WIN32*/
+
+ if (not isFileWritable)
+ {
+ QMessageBox messageBox(this);
+ messageBox.setIcon(QMessageBox::Question);
+ messageBox.setText(tr("The document has no write permissions."));
+ messageBox.setInformativeText("Do you want to change the premissions?");
+ messageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel);
+ messageBox.setDefaultButton(QMessageBox::Yes);
+
+ if (messageBox.exec() == QMessageBox::Yes)
+ {
+#ifdef Q_OS_WIN32
+ qt_ntfs_permission_lookup++; // turn checking on
+#endif /*Q_OS_WIN32*/
+ bool changed = QFile::setPermissions(m_curFile,
+ QFileInfo(m_curFile).permissions() | QFileDevice::WriteUser);
+#ifdef Q_OS_WIN32
+ qt_ntfs_permission_lookup--; // turn it off again
+#endif /*Q_OS_WIN32*/
+
+ if (not changed)
+ {
+ QMessageBox messageBox(this);
+ messageBox.setIcon(QMessageBox::Warning);
+ messageBox.setText(tr("Cannot set permissions for %1 to writable.").arg(m_curFile));
+ messageBox.setInformativeText(tr("Could not save the file."));
+ messageBox.setDefaultButton(QMessageBox::Ok);
+ messageBox.setStandardButtons(QMessageBox::Ok);
+ messageBox.exec();
+ return false;
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ QString error;
+ bool result = SaveWatermark(m_curFile, error);
+ if (result)
+ {
+ m_curFileFormatVersion = VWatermarkConverter::WatermarkMaxVer;
+ m_curFileFormatVersionStr = VWatermarkConverter::WatermarkMaxVerStr;
+ }
+ else
+ {
+ QMessageBox messageBox(this);
+ messageBox.setIcon(QMessageBox::Warning);
+ messageBox.setText(tr("Could not save the file"));
+ messageBox.setDefaultButton(QMessageBox::Ok);
+ messageBox.setDetailedText(error);
+ messageBox.setStandardButtons(QMessageBox::Ok);
+ messageBox.exec();
+ }
+ return result;
+ }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void WatermarkWindow::on_actionOpen_triggered()
+{
+ qDebug("Openning new watermark file.");
+ const QString filter(tr("Watermark files") + QLatin1String(" (*.vwm)"));
+ QString dir = QDir::homePath();
+ qDebug("Run QFileDialog::getOpenFileName: dir = %s.", qUtf8Printable(dir));
+ const QString filePath = QFileDialog::getOpenFileName(this, tr("Open file"), dir, filter, nullptr);
+ if (filePath.isEmpty())
+ {
+ return;
+ }
+ Open(filePath);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void WatermarkWindow::on_actionExit_triggered()
+{
+ close();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void WatermarkWindow::WatermarkChangesWereSaved(bool saved)
+{
+ const bool state = /*doc->IsModified() ||*/ !saved;
+ setWindowModified(state);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+bool WatermarkWindow::MaybeSave()
+{
+ if (this->isWindowModified())
+ {
+ QScopedPointer messageBox(new QMessageBox(tr("Unsaved changes"),
+ tr("The watermark has been modified.\n"
+ "Do you want to save your changes?"),
+ QMessageBox::Warning, QMessageBox::Yes, QMessageBox::No,
+ QMessageBox::Cancel, this, Qt::Sheet));
+
+ messageBox->setDefaultButton(QMessageBox::Yes);
+ messageBox->setEscapeButton(QMessageBox::Cancel);
+
+ messageBox->setButtonText(QMessageBox::Yes, m_curFile.isEmpty() ? tr("Save") : tr("Save as"));
+ messageBox->setButtonText(QMessageBox::No, tr("Don't Save"));
+
+ messageBox->setWindowModality(Qt::ApplicationModal);
+ const auto ret = static_cast(messageBox->exec());
+
+ switch (ret)
+ {
+ case QMessageBox::Yes:
+ return m_curFile.isEmpty() ? on_actionSaveAs_triggered() : on_actionSave_triggered();
+ case QMessageBox::No:
+ return true;
+ case QMessageBox::Cancel:
+ return false;
+ default:
+ break;
+ }
+ }
+ return true;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void WatermarkWindow::UpdateWindowTitle()
+{
+ bool isFileWritable = true;
+ if (not m_curFile.isEmpty())
+ {
+#ifdef Q_OS_WIN32
+ qt_ntfs_permission_lookup++; // turn checking on
+#endif /*Q_OS_WIN32*/
+ isFileWritable = QFileInfo(m_curFile).isWritable();
+#ifdef Q_OS_WIN32
+ qt_ntfs_permission_lookup--; // turn it off again
+#endif /*Q_OS_WIN32*/
+ }
+
+ if (isFileWritable)
+ {
+ setWindowTitle(GetWatermarkFileName());
+ }
+ else
+ {
+ setWindowTitle(GetWatermarkFileName() + QLatin1String(" (") + tr("read only") + QLatin1String(")"));
+ }
+ setWindowFilePath(m_curFile);
+
+#if defined(Q_OS_MAC)
+ static QIcon fileIcon = QIcon(QCoreApplication::applicationDirPath() +
+ QLatin1String("/../Resources/Valentina.icns"));
+ QIcon icon;
+ if (not m_curFile.isEmpty())
+ {
+ if (not isWindowModified())
+ {
+ icon = fileIcon;
+ }
+ else
+ {
+ static QIcon darkIcon;
+
+ if (darkIcon.isNull())
+ {
+ darkIcon = QIcon(darkenPixmap(fileIcon.pixmap(16, 16)));
+ }
+ icon = darkIcon;
+ }
+ }
+ setWindowIcon(icon);
+#endif //defined(Q_OS_MAC)
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QString WatermarkWindow::GetWatermarkFileName()
+{
+ QString shownName = tr("untitled.vwm");
+ if(not m_curFile.isEmpty())
+ {
+ shownName = StrippedName(m_curFile);
+ }
+ shownName += QLatin1String("[*]");
+ return shownName;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+bool WatermarkWindow::ContinueFormatRewrite(const QString ¤tFormatVersion, const QString &maxFormatVersion)
+{
+ if (qApp->Settings()->GetConfirmFormatRewriting())
+ {
+ Utils::CheckableMessageBox msgBox(this);
+ msgBox.setWindowTitle(tr("Confirm format rewriting"));
+ msgBox.setText(tr("This file is using previous format version v%1. The current is v%2. "
+ "Saving the file with this app version will update the format version for this "
+ "file. This may prevent you from be able to open the file with older app versions. "
+ "Do you really want to continue?").arg(currentFormatVersion, maxFormatVersion));
+ msgBox.setStandardButtons(QDialogButtonBox::Yes | QDialogButtonBox::No);
+ msgBox.setDefaultButton(QDialogButtonBox::No);
+ msgBox.setIconPixmap(QApplication::style()->standardIcon(QStyle::SP_MessageBoxQuestion).pixmap(32, 32));
+
+ int dialogResult = msgBox.exec();
+
+ if (dialogResult == QDialog::Accepted)
+ {
+ qApp->Settings()->SetConfirmFormatRewriting(not msgBox.isChecked());
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+bool WatermarkWindow::SaveWatermark(const QString &fileName, QString &error)
+{
+ m_data.opacity = ui->spinBoxOpacity->value();
+ m_data.text = ui->lineEditText->text();
+ m_data.textRotation = ui->spinBoxTextRotation->value();
+ m_data.path = RelativeMPath(fileName, ui->lineEditPath->text());
+ m_data.imageRotation = ui->spinBoxImageRotation->value();
+ m_data.grayscale = ui->checkBoxGrayColor->isChecked();
+
+ VWatermark doc;
+ doc.CreateEmptyWatermark();
+ doc.SetWatermark(m_data);
+
+ const bool result = doc.SaveDocument(fileName, error);
+ if (result)
+ {
+ SetCurrentFile(fileName);
+ statusBar()->showMessage(tr("File saved"), 5000);
+ WatermarkChangesWereSaved(result);
+ }
+ return result;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void WatermarkWindow::SetCurrentFile(const QString &fileName)
+{
+ m_curFile = fileName;
+ UpdateWindowTitle();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+bool WatermarkWindow::OpenNewEditor(const QString &fileName) const
+{
+ if (this->isWindowModified() || not m_curFile.isEmpty())
+ {
+ emit OpenAnother(fileName);
+ return true;
+ }
+ return false;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void WatermarkWindow::Clear()
+{
+ m_curFile.clear();
+ UpdateWindowTitle();
+ setWindowModified(false);
+ m_data = VWatermarkData();
+ ShowWatermark();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+bool WatermarkWindow::IgnoreLocking(int error, const QString &path)
+{
+ QMessageBox::StandardButton answer = QMessageBox::Abort;
+ switch(error)
+ {
+ case QLockFile::LockFailedError:
+ answer = QMessageBox::warning(this, tr("Locking file"),
+ tr("This file already opened in another window. Ignore if you want "
+ "to continue (not recommended, can cause a data corruption)."),
+ QMessageBox::Abort|QMessageBox::Ignore, QMessageBox::Abort);
+ break;
+ case QLockFile::PermissionError:
+ answer = QMessageBox::question(this, tr("Locking file"),
+ tr("The lock file could not be created, for lack of permissions. "
+ "Ignore if you want to continue (not recommended, can cause "
+ "a data corruption)."),
+ QMessageBox::Abort|QMessageBox::Ignore, QMessageBox::Abort);
+ break;
+ case QLockFile::UnknownError:
+ answer = QMessageBox::question(this, tr("Locking file"),
+ tr("Unknown error happened, for instance a full partition prevented "
+ "writing out the lock file. Ignore if you want to continue (not "
+ "recommended, can cause a data corruption)."),
+ QMessageBox::Abort|QMessageBox::Ignore, QMessageBox::Abort);
+ break;
+ default:
+ answer = QMessageBox::Abort;
+ break;
+ }
+
+ if (answer == QMessageBox::Abort)
+ {
+ qDebug("Failed to lock %s", qUtf8Printable(path));
+ qDebug("Error type: %d", error);
+ Clear();
+ return false;
+ }
+ return true;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void WatermarkWindow::ShowWatermark()
+{
+ ui->spinBoxOpacity->blockSignals(true);
+ ui->spinBoxOpacity->setValue(m_data.opacity);
+ ui->spinBoxOpacity->blockSignals(false);
+
+ ui->lineEditText->blockSignals(true);
+ ui->lineEditText->setText(m_data.text);
+ ui->lineEditText->blockSignals(false);
+
+ ui->spinBoxTextRotation->blockSignals(true);
+ ui->spinBoxTextRotation->setValue(m_data.textRotation);
+ ui->spinBoxTextRotation->blockSignals(false);
+
+ ui->lineEditFontSample->blockSignals(true);
+ ui->lineEditFontSample->setFont(m_data.font);
+ ui->lineEditFontSample->blockSignals(false);
+
+ ui->lineEditPath->blockSignals(true);
+ ui->lineEditPath->setText(AbsoluteMPath(m_curFile, m_data.path));
+ ValidatePath();
+ ui->lineEditPath->blockSignals(false);
+
+ ui->spinBoxImageRotation->blockSignals(true);
+ ui->spinBoxImageRotation->setValue(m_data.imageRotation);
+ ui->spinBoxImageRotation->blockSignals(false);
+
+ ui->checkBoxGrayColor->blockSignals(true);
+ ui->checkBoxGrayColor->setChecked(m_data.grayscale);
+ ui->checkBoxGrayColor->blockSignals(false);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void WatermarkWindow::ValidatePath()
+{
+ QPalette palette = ui->lineEditPath->palette();
+ const QString path = ui->lineEditPath->text();
+ palette.setColor(ui->lineEditPath->foregroundRole(),
+ path.isEmpty() || QFileInfo::exists(path) ? m_okPathColor : Qt::red);
+ ui->lineEditPath->setPalette(palette);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void WatermarkWindow::ToolBarStyle(QToolBar *bar)
+{
+ SCASSERT(bar != nullptr)
+ if (qApp->Settings()->GetToolBarStyle())
+ {
+ bar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
+ }
+ else
+ {
+ bar->setToolButtonStyle(Qt::ToolButtonIconOnly);
+ }
+}
diff --git a/src/app/valentina/watermarkwindow.h b/src/app/valentina/watermarkwindow.h
new file mode 100644
index 000000000..d0be5f303
--- /dev/null
+++ b/src/app/valentina/watermarkwindow.h
@@ -0,0 +1,103 @@
+/************************************************************************
+ **
+ ** @file watermarkwindow.h
+ ** @author Roman Telezhynskyi
+ ** @date 24 12, 2019
+ **
+ ** @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) 2019 Valentina project
+ ** 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 .
+ **
+ *************************************************************************/
+#ifndef WATERMARKWINDOW_H
+#define WATERMARKWINDOW_H
+
+#include
+
+#include "../ifc/ifcdef.h"
+#include "../vformat/vwatermark.h"
+#include "../vmisc/vlockguard.h"
+
+namespace Ui
+{
+class WatermarkWindow;
+}
+
+class WatermarkWindow : public QMainWindow
+{
+ Q_OBJECT
+
+public:
+ explicit WatermarkWindow(const QString &patternPath, QWidget *parent = nullptr);
+ ~WatermarkWindow();
+
+ QString CurrentFile() const;
+
+ bool Open(QString path);
+
+signals:
+ void New();
+ void OpenAnother(const QString &fileName) const;
+
+protected:
+ virtual void closeEvent(QCloseEvent *event) override;
+ virtual void changeEvent(QEvent* event) override;
+ virtual void showEvent(QShowEvent *event) override;
+ virtual void resizeEvent(QResizeEvent *event) override;
+
+private slots:
+ void on_actionNew_triggered();
+ bool on_actionSaveAs_triggered();
+ bool on_actionSave_triggered();
+ void on_actionOpen_triggered();
+ void on_actionExit_triggered();
+
+ void WatermarkChangesWereSaved(bool saved);
+
+private:
+ Q_DISABLE_COPY(WatermarkWindow)
+ Ui::WatermarkWindow *ui;
+ QString m_patternPath;
+ QString m_curFile{};
+ VWatermarkData m_data{};
+ QColor m_okPathColor;
+ bool m_isInitialized{false};
+
+ int m_curFileFormatVersion{0x0};
+ QString m_curFileFormatVersionStr{QLatin1String("0.0.0")};
+
+ QSharedPointer> lock{};
+
+ bool MaybeSave();
+ void UpdateWindowTitle();
+
+ QString GetWatermarkFileName();
+
+ bool ContinueFormatRewrite(const QString ¤tFormatVersion, const QString &maxFormatVersion);
+ bool SaveWatermark(const QString &fileName, QString &error);
+ void SetCurrentFile(const QString &fileName);
+ bool OpenNewEditor(const QString &fileName = QString()) const;
+ void Clear();
+ bool IgnoreLocking(int error, const QString &path);
+ void ShowWatermark();
+ void ValidatePath();
+ void ToolBarStyle(QToolBar *bar);
+};
+
+#endif // WATERMARKWINDOW_H
diff --git a/src/app/valentina/watermarkwindow.ui b/src/app/valentina/watermarkwindow.ui
new file mode 100644
index 000000000..98504975b
--- /dev/null
+++ b/src/app/valentina/watermarkwindow.ui
@@ -0,0 +1,363 @@
+
+
+ WatermarkWindow
+
+
+
+ 0
+ 0
+ 532
+ 468
+
+
+
+ Watermark
+
+
+
+ :/icon/64x64/icon64x64.png:/icon/64x64/icon64x64.png
+
+
+ Qt::ToolButtonTextUnderIcon
+
+
+
+ -
+
+
+ true
+
+
+
+
+ 0
+ 0
+ 512
+ 344
+
+
+
+
-
+
+
+ QFormLayout::ExpandingFieldsGrow
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ Opacity:
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ %
+
+
+ 100
+
+
+ 20
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Text
+
+
+
+ QFormLayout::ExpandingFieldsGrow
+
+
-
+
+
+ Text:
+
+
+
+ -
+
+
+
+
+
+ 32767
+
+
+ watermark text
+
+
+ true
+
+
+
+ -
+
+
+ Rotation:
+
+
+
+ -
+
+
+ °
+
+
+ 360
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Font:
+
+
+
+ -
+
+
-
+
+
+ The quick brown fox jumps over the lazy dog
+
+
+ true
+
+
+
+ -
+
+
+ Edit font
+
+
+ ...
+
+
+
+ :/icon/24x24/font_preferences.png:/icon/24x24/font_preferences.png
+
+
+
+ 24
+ 24
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Image
+
+
+
+ QFormLayout::ExpandingFieldsGrow
+
+
-
+
+
+ Path:
+
+
+
+ -
+
+
-
+
+
+ path to image
+
+
+ true
+
+
+
+ -
+
+
+ Browse…
+
+
+
+
+
+ -
+
+
+ Rotation:
+
+
+
+ -
+
+
+ °
+
+
+ 100
+
+
+
+ -
+
+
+ Gray color
+
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Operations
+
+
+ false
+
+
+ TopToolBarArea
+
+
+ false
+
+
+
+
+
+
+
+
+ ..
+
+
+ Save
+
+
+
+
+
+ ..
+
+
+ Save &As…
+
+
+
+
+
+ ..
+
+
+ E&xit
+
+
+
+
+
+ ..
+
+
+ Open
+
+
+
+
+
+ ..
+
+
+ New
+
+
+
+
+
+
+
+
diff --git a/src/libs/ifc/ifcdef.h b/src/libs/ifc/ifcdef.h
index b4c7542ec..58fcb55d4 100644
--- a/src/libs/ifc/ifcdef.h
+++ b/src/libs/ifc/ifcdef.h
@@ -35,6 +35,7 @@
# include
#endif /*Q_OS_WIN*/
+#include
#include
#include
@@ -237,6 +238,17 @@ struct VLabelTemplateLine
int fontSizeIncrement;
};
+struct VWatermarkData
+{
+ int opacity{20};
+ QString text{};
+ int textRotation{0};
+ QFont font{};
+ QString path{};
+ int imageRotation{0};
+ bool grayscale{false};
+};
+
QT_WARNING_POP
#endif // IFCDEF_H
diff --git a/src/libs/ifc/schema.qrc b/src/libs/ifc/schema.qrc
index bef07eb83..bf0597e5d 100644
--- a/src/libs/ifc/schema.qrc
+++ b/src/libs/ifc/schema.qrc
@@ -57,6 +57,7 @@
schema/pattern/v0.8.3.xsd
schema/pattern/v0.8.4.xsd
schema/pattern/v0.8.5.xsd
+ schema/pattern/v0.8.6.xsd
schema/standard_measurements/v0.3.0.xsd
schema/standard_measurements/v0.4.0.xsd
schema/standard_measurements/v0.4.1.xsd
@@ -71,5 +72,6 @@
schema/individual_measurements/v0.4.0.xsd
schema/individual_measurements/v0.5.0.xsd
schema/label_template/v1.0.0.xsd
+ schema/watermark/v1.0.0.xsd
diff --git a/src/libs/ifc/schema/pattern/v0.8.6.xsd b/src/libs/ifc/schema/pattern/v0.8.6.xsd
new file mode 100644
index 000000000..7f860f2ac
--- /dev/null
+++ b/src/libs/ifc/schema/pattern/v0.8.6.xsd
@@ -0,0 +1,1252 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/libs/ifc/schema/watermark/v1.0.0.xsd b/src/libs/ifc/schema/watermark/v1.0.0.xsd
new file mode 100644
index 000000000..1b9c44e31
--- /dev/null
+++ b/src/libs/ifc/schema/watermark/v1.0.0.xsd
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/libs/ifc/xml/vabstractpattern.cpp b/src/libs/ifc/xml/vabstractpattern.cpp
index b89b5b041..297e9c6d0 100644
--- a/src/libs/ifc/xml/vabstractpattern.cpp
+++ b/src/libs/ifc/xml/vabstractpattern.cpp
@@ -55,6 +55,7 @@
#include "vdomdocument.h"
#include "vtoolrecord.h"
#include "../vmisc/vabstractapplication.h"
+#include "../vlayout/vtextmanager.h"
class QDomElement;
@@ -90,6 +91,7 @@ const QString VAbstractPattern::TagPatternNum = QStringLiteral("patternNum
const QString VAbstractPattern::TagCustomerName = QStringLiteral("customer");
const QString VAbstractPattern::TagCompanyName = QStringLiteral("company");
const QString VAbstractPattern::TagPatternLabel = QStringLiteral("patternLabel");
+const QString VAbstractPattern::TagWatermark = QStringLiteral("watermark");
const QString VAbstractPattern::TagPatternMaterials = QStringLiteral("patternMaterials");
const QString VAbstractPattern::TagFinalMeasurements= QStringLiteral("finalMeasurements");
const QString VAbstractPattern::TagMaterial = QStringLiteral("material");
@@ -132,6 +134,7 @@ const QString VAbstractPattern::AttrNumber = QStringLiteral("number")
const QString VAbstractPattern::AttrCheckUniqueness = QStringLiteral("checkUniqueness");
const QString VAbstractPattern::AttrManualPassmarkLength = QStringLiteral("manualPassmarkLength");
const QString VAbstractPattern::AttrPassmarkLength = QStringLiteral("passmarkLength");
+const QString VAbstractPattern::AttrOpacity = QStringLiteral("opacity");
const QString VAbstractPattern::AttrAll = QStringLiteral("all");
@@ -215,6 +218,7 @@ Q_GLOBAL_STATIC_WITH_ARGS(QString, patternNumberCached, (unknownCharacter))
Q_GLOBAL_STATIC_WITH_ARGS(QString, labelDateFormatCached, (unknownCharacter))
Q_GLOBAL_STATIC_WITH_ARGS(QString, patternNameCached, (unknownCharacter))
Q_GLOBAL_STATIC_WITH_ARGS(QString, MPathCached, (unknownCharacter))
+Q_GLOBAL_STATIC_WITH_ARGS(QString, WatermarkPathCached, (unknownCharacter))
Q_GLOBAL_STATIC_WITH_ARGS(QString, companyNameCached, (unknownCharacter))
void ReadExpressionAttribute(QVector &expressions, const QDomElement &element, const QString &attribute)
@@ -1525,6 +1529,48 @@ QVector VAbstractPattern::GetPatternLabelTemplate() const
return patternLabelLines;
}
+//---------------------------------------------------------------------------------------------------------------------
+bool VAbstractPattern::SetWatermarkPath(const QString &path)
+{
+ QDomElement tag = CheckTagExists(TagWatermark);
+
+ if (path.isEmpty())
+ {
+ QDomNode parent = tag.parentNode();
+ parent.removeChild(tag);
+
+ emit patternChanged(false);
+ patternLabelWasChanged = true;
+ *WatermarkPathCached = path;
+ return true;
+ }
+ else
+ {
+ if (setTagText(tag, path))
+ {
+ emit patternChanged(false);
+ patternLabelWasChanged = true;
+ *WatermarkPathCached = path;
+ return true;
+ }
+ else
+ {
+ qDebug() << "Can't save path to watermark" << Q_FUNC_INFO;
+ return false;
+ }
+ }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QString VAbstractPattern::GetWatermarkPath() const
+{
+ if (*WatermarkPathCached == unknownCharacter)
+ {
+ *WatermarkPathCached = UniqueTagText(TagWatermark);
+ }
+ return *WatermarkPathCached;
+}
+
//---------------------------------------------------------------------------------------------------------------------
void VAbstractPattern::SetPatternMaterials(const QMap &materials)
{
@@ -1728,10 +1774,23 @@ QDomElement VAbstractPattern::CheckTagExists(const QString &tag)
QDomElement element;
if (list.isEmpty())
{
- const QStringList tags = QStringList() << TagUnit << TagImage << TagDescription << TagNotes
- << TagGradation << TagPatternName << TagPatternNum << TagCompanyName
- << TagCustomerName << TagPatternLabel << TagPatternMaterials
- << TagFinalMeasurements;
+ const QStringList tags
+ {
+ TagUnit, // 0
+ TagImage, // 1
+ TagDescription, // 2
+ TagNotes, // 3
+ TagGradation, // 4
+ TagPatternName, // 5
+ TagPatternNum, // 6
+ TagCompanyName, // 7
+ TagCustomerName, // 8
+ TagPatternLabel, // 9
+ TagWatermark, // 10
+ TagPatternMaterials, // 11
+ TagFinalMeasurements // 12
+ };
+
switch (tags.indexOf(tag))
{
case 1: //TagImage
@@ -1771,10 +1830,13 @@ QDomElement VAbstractPattern::CheckTagExists(const QString &tag)
case 9: // TagPatternLabel
element = createElement(TagPatternLabel);
break;
- case 10: // TagPatternMaterials
+ case 10: // TagWatermark
+ element = createElement(TagWatermark);
+ break;
+ case 11: // TagPatternMaterials
element = createElement(TagPatternMaterials);
break;
- case 11: // TagFinalMeasurements
+ case 12: // TagFinalMeasurements
element = createElement(TagFinalMeasurements);
break;
case 0: //TagUnit (Mandatory tag)
diff --git a/src/libs/ifc/xml/vabstractpattern.h b/src/libs/ifc/xml/vabstractpattern.h
index baaf2fff1..1da118d76 100644
--- a/src/libs/ifc/xml/vabstractpattern.h
+++ b/src/libs/ifc/xml/vabstractpattern.h
@@ -43,6 +43,7 @@
#include "../vmisc/def.h"
#include "vdomdocument.h"
#include "vtoolrecord.h"
+#include "../vlayout/vtextmanager.h"
class QDomElement;
class VPiecePath;
@@ -172,6 +173,9 @@ public:
void SetPatternLabelTemplate(const QVector &lines);
QVector GetPatternLabelTemplate() const;
+ bool SetWatermarkPath(const QString &path);
+ QString GetWatermarkPath() const;
+
void SetPatternMaterials(const QMap &materials);
QMap GetPatternMaterials() const;
@@ -240,6 +244,7 @@ public:
static const QString TagCompanyName;
static const QString TagCustomerName;
static const QString TagPatternLabel;
+ static const QString TagWatermark;
static const QString TagPatternMaterials;
static const QString TagFinalMeasurements;
static const QString TagMaterial;
@@ -282,6 +287,7 @@ public:
static const QString AttrCheckUniqueness;
static const QString AttrManualPassmarkLength;
static const QString AttrPassmarkLength;
+ static const QString AttrOpacity;
static const QString AttrAll;
diff --git a/src/libs/ifc/xml/vpatternconverter.cpp b/src/libs/ifc/xml/vpatternconverter.cpp
index aba3b81be..abf862c57 100644
--- a/src/libs/ifc/xml/vpatternconverter.cpp
+++ b/src/libs/ifc/xml/vpatternconverter.cpp
@@ -59,8 +59,8 @@ class QDomElement;
*/
const QString VPatternConverter::PatternMinVerStr = QStringLiteral("0.1.4");
-const QString VPatternConverter::PatternMaxVerStr = QStringLiteral("0.8.5");
-const QString VPatternConverter::CurrentSchema = QStringLiteral("://schema/pattern/v0.8.5.xsd");
+const QString VPatternConverter::PatternMaxVerStr = QStringLiteral("0.8.6");
+const QString VPatternConverter::CurrentSchema = QStringLiteral("://schema/pattern/v0.8.6.xsd");
//VPatternConverter::PatternMinVer; // <== DON'T FORGET TO UPDATE TOO!!!!
//VPatternConverter::PatternMaxVer; // <== DON'T FORGET TO UPDATE TOO!!!!
@@ -235,7 +235,8 @@ QString VPatternConverter::XSDSchema(int ver) const
std::make_pair(FORMAT_VERSION(0, 8, 2), QStringLiteral("://schema/pattern/v0.8.2.xsd")),
std::make_pair(FORMAT_VERSION(0, 8, 3), QStringLiteral("://schema/pattern/v0.8.3.xsd")),
std::make_pair(FORMAT_VERSION(0, 8, 4), QStringLiteral("://schema/pattern/v0.8.4.xsd")),
- std::make_pair(FORMAT_VERSION(0, 8, 5), CurrentSchema)
+ std::make_pair(FORMAT_VERSION(0, 8, 5), QStringLiteral("://schema/pattern/v0.8.5.xsd")),
+ std::make_pair(FORMAT_VERSION(0, 8, 6), CurrentSchema)
};
if (schemas.contains(ver))
@@ -476,6 +477,10 @@ void VPatternConverter::ApplyPatches()
ValidateXML(XSDSchema(FORMAT_VERSION(0, 8, 5)), m_convertedFileName);
Q_FALLTHROUGH();
case (FORMAT_VERSION(0, 8, 5)):
+ ToV0_8_6();
+ ValidateXML(XSDSchema(FORMAT_VERSION(0, 8, 6)), m_convertedFileName);
+ Q_FALLTHROUGH();
+ case (FORMAT_VERSION(0, 8, 6)):
break;
default:
InvalidVersion(m_ver);
@@ -493,7 +498,7 @@ void VPatternConverter::DowngradeToCurrentMaxVersion()
bool VPatternConverter::IsReadOnly() const
{
// Check if attribute readOnly was not changed in file format
- Q_STATIC_ASSERT_X(VPatternConverter::PatternMaxVer == FORMAT_VERSION(0, 8, 5),
+ Q_STATIC_ASSERT_X(VPatternConverter::PatternMaxVer == FORMAT_VERSION(0, 8, 6),
"Check attribute readOnly.");
// Possibly in future attribute readOnly will change position etc.
@@ -1113,6 +1118,16 @@ void VPatternConverter::ToV0_8_5()
Save();
}
+//---------------------------------------------------------------------------------------------------------------------
+void VPatternConverter::ToV0_8_6()
+{
+ // TODO. Delete if minimal supported version is 0.8.6
+ Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < FORMAT_VERSION(0, 8, 6),
+ "Time to refactor the code.");
+ SetVersion(QStringLiteral("0.8.6"));
+ Save();
+}
+
//---------------------------------------------------------------------------------------------------------------------
void VPatternConverter::TagUnitToV0_2_0()
{
diff --git a/src/libs/ifc/xml/vpatternconverter.h b/src/libs/ifc/xml/vpatternconverter.h
index 553675d52..40c0595d7 100644
--- a/src/libs/ifc/xml/vpatternconverter.h
+++ b/src/libs/ifc/xml/vpatternconverter.h
@@ -53,7 +53,7 @@ public:
static const QString PatternMaxVerStr;
static const QString CurrentSchema;
static Q_DECL_CONSTEXPR const int PatternMinVer = FORMAT_VERSION(0, 1, 4);
- static Q_DECL_CONSTEXPR const int PatternMaxVer = FORMAT_VERSION(0, 8, 5);
+ static Q_DECL_CONSTEXPR const int PatternMaxVer = FORMAT_VERSION(0, 8, 6);
protected:
virtual int MinVer() const override;
@@ -128,6 +128,7 @@ private:
void ToV0_8_3();
void ToV0_8_4();
void ToV0_8_5();
+ void ToV0_8_6();
void TagUnitToV0_2_0();
void TagIncrementToV0_2_0();
diff --git a/src/libs/ifc/xml/vwatermarkconverter.cpp b/src/libs/ifc/xml/vwatermarkconverter.cpp
new file mode 100644
index 000000000..037f8a53a
--- /dev/null
+++ b/src/libs/ifc/xml/vwatermarkconverter.cpp
@@ -0,0 +1,108 @@
+/************************************************************************
+ **
+ ** @file vwatermarkconverter.cpp
+ ** @author Roman Telezhynskyi
+ ** @date 26 12, 2019
+ **
+ ** @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) 2019 Valentina project
+ ** 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 .
+ **
+ *************************************************************************/
+#include "vwatermarkconverter.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 VWatermarkConverter::WatermarkMinVerStr = QStringLiteral("1.0.0");
+const QString VWatermarkConverter::WatermarkMaxVerStr = QStringLiteral("1.0.0");
+const QString VWatermarkConverter::CurrentSchema = QStringLiteral("://schema/watermark/v1.0.0.xsd");
+
+//VWatermarkConverter::WatermarkMinVer; // <== DON'T FORGET TO UPDATE TOO!!!!
+//VWatermarkConverter::WatermarkMaxVer; // <== DON'T FORGET TO UPDATE TOO!!!!
+
+//---------------------------------------------------------------------------------------------------------------------
+VWatermarkConverter::VWatermarkConverter(const QString &fileName)
+ : VAbstractConverter(fileName)
+{
+ ValidateInputFile(CurrentSchema);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+int VWatermarkConverter::MinVer() const
+{
+ return WatermarkMinVer;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+int VWatermarkConverter::MaxVer() const
+{
+ return WatermarkMaxVer;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QString VWatermarkConverter::MinVerStr() const
+{
+ return WatermarkMinVerStr;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QString VWatermarkConverter::MaxVerStr() const
+{
+ return WatermarkMaxVerStr;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QString VWatermarkConverter::XSDSchema(int ver) const
+{
+ switch (ver)
+ {
+ case (0x010000):
+ return CurrentSchema;
+ default:
+ InvalidVersion(ver);
+ break;
+ }
+ return QString();//unreachable code
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VWatermarkConverter::ApplyPatches()
+{
+ switch (m_ver)
+ {
+ case (0x010000):
+ break;
+ default:
+ InvalidVersion(m_ver);
+ break;
+ }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VWatermarkConverter::DowngradeToCurrentMaxVersion()
+{
+ SetVersion(WatermarkMaxVerStr);
+ Save();
+}
diff --git a/src/libs/ifc/xml/vwatermarkconverter.h b/src/libs/ifc/xml/vwatermarkconverter.h
new file mode 100644
index 000000000..6f626f868
--- /dev/null
+++ b/src/libs/ifc/xml/vwatermarkconverter.h
@@ -0,0 +1,62 @@
+/************************************************************************
+ **
+ ** @file vwatermarkconverter.h
+ ** @author Roman Telezhynskyi
+ ** @date 26 12, 2019
+ **
+ ** @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) 2019 Valentina project
+ ** 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 .
+ **
+ *************************************************************************/
+#ifndef VWATERMARKCONVERTER_H
+#define VWATERMARKCONVERTER_H
+
+#include "vabstractconverter.h"
+
+class VWatermarkConverter : public VAbstractConverter
+{
+public:
+ explicit VWatermarkConverter(const QString &fileName);
+ virtual ~VWatermarkConverter() Q_DECL_EQ_DEFAULT;
+
+ static const QString WatermarkMaxVerStr;
+ static const QString CurrentSchema;
+ static Q_DECL_CONSTEXPR const int WatermarkMinVer = FORMAT_VERSION(1, 0, 0);
+ static Q_DECL_CONSTEXPR const int WatermarkMaxVer = FORMAT_VERSION(1, 0, 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 {return false;}
+
+private:
+ Q_DISABLE_COPY(VWatermarkConverter)
+ static const QString WatermarkMinVerStr;
+};
+
+#endif // VWATERMARKCONVERTER_H
diff --git a/src/libs/ifc/xml/xml.pri b/src/libs/ifc/xml/xml.pri
index d5d333e23..1c558ea04 100644
--- a/src/libs/ifc/xml/xml.pri
+++ b/src/libs/ifc/xml/xml.pri
@@ -10,7 +10,8 @@ HEADERS += \
$$PWD/vvstconverter.h \
$$PWD//vvitconverter.h \
$$PWD//vabstractmconverter.h \
- $$PWD/vlabeltemplateconverter.h
+ $$PWD/vlabeltemplateconverter.h \
+ $$PWD/vwatermarkconverter.h
SOURCES += \
$$PWD/vabstractconverter.cpp \
@@ -21,4 +22,5 @@ SOURCES += \
$$PWD/vvstconverter.cpp \
$$PWD//vvitconverter.cpp \
$$PWD//vabstractmconverter.cpp \
- $$PWD/vlabeltemplateconverter.cpp
+ $$PWD/vlabeltemplateconverter.cpp \
+ $$PWD/vwatermarkconverter.cpp
diff --git a/src/libs/vformat/vformat.pri b/src/libs/vformat/vformat.pri
index f3b883b34..77773b0b9 100644
--- a/src/libs/vformat/vformat.pri
+++ b/src/libs/vformat/vformat.pri
@@ -4,7 +4,8 @@
SOURCES += \
$$PWD/vmeasurements.cpp \
$$PWD/vlabeltemplate.cpp \
- $$PWD/vpatternrecipe.cpp
+ $$PWD/vpatternrecipe.cpp \
+ $$PWD/vwatermark.cpp
*msvc*:SOURCES += $$PWD/stable.cpp
@@ -12,4 +13,5 @@ HEADERS += \
$$PWD/vmeasurements.h \
$$PWD/stable.h \
$$PWD/vlabeltemplate.h \
- $$PWD/vpatternrecipe.h
+ $$PWD/vpatternrecipe.h \
+ $$PWD/vwatermark.h
diff --git a/src/libs/vformat/vwatermark.cpp b/src/libs/vformat/vwatermark.cpp
new file mode 100644
index 000000000..04cdd5bb3
--- /dev/null
+++ b/src/libs/vformat/vwatermark.cpp
@@ -0,0 +1,144 @@
+/************************************************************************
+ **
+ ** @file vwatermark.cpp
+ ** @author Roman Telezhynskyi
+ ** @date 25 12, 2019
+ **
+ ** @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) 2019 Valentina project
+ ** 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 .
+ **
+ *************************************************************************/
+#include "vwatermark.h"
+
+#include "../vmisc/projectversion.h"
+
+const QString VWatermark::TagWatermark = QStringLiteral("watermark");
+const QString VWatermark::TagText = QStringLiteral("text");
+const QString VWatermark::TagImage = QStringLiteral("image");
+
+const QString VWatermark::AttrOpacity = QStringLiteral("opacity");
+const QString VWatermark::AttrText = QStringLiteral("text");
+const QString VWatermark::AttrRotation = QStringLiteral("rotation");
+const QString VWatermark::AttrFont = QStringLiteral("font");
+const QString VWatermark::AttrPath = QStringLiteral("path");
+const QString VWatermark::AttrGrayscale = QStringLiteral("grayscale");
+
+namespace
+{
+//---------------------------------------------------------------------------------------------------------------------
+QString FileComment()
+{
+ return QString("Watermark created with Valentina v%1 (https://valentinaproject.bitbucket.io/).")
+ .arg(APP_VERSION_STR);
+}
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+VWatermark::VWatermark()
+{}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VWatermark::CreateEmptyWatermark()
+{
+ this->clear();
+ QDomElement wElement = this->createElement(TagWatermark);
+
+ wElement.appendChild(createComment(FileComment()));
+ wElement.appendChild(CreateElementWithText(TagVersion, "1.0.0" /*VWatermarkConverter::WatermarkMaxVerStr*/));
+ wElement.appendChild(createElement(TagText));
+ wElement.appendChild(createElement(TagImage));
+
+ appendChild(wElement);
+ insertBefore(createProcessingInstruction(QStringLiteral("xml"),
+ QStringLiteral("version=\"1.0\" encoding=\"UTF-8\"")), this->firstChild());
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+bool VWatermark::SaveDocument(const QString &fileName, QString &error)
+{
+ // Update comment with Valentina version
+ QDomNode commentNode = documentElement().firstChild();
+ if (commentNode.isComment())
+ {
+ QDomComment comment = commentNode.toComment();
+ comment.setData(FileComment());
+ }
+
+ return VDomDocument::SaveDocument(fileName, error);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+VWatermarkData VWatermark::GetWatermark() const
+{
+ VWatermarkData data;
+
+ QDomNode root = documentElement();
+ if (not root.isNull() && root.isElement())
+ {
+ const QDomElement rootElement = root.toElement();
+ data.opacity = GetParametrUInt(rootElement, AttrOpacity, QChar('2'));
+
+ QDomElement text = rootElement.firstChildElement(TagText);
+ if (not text.isNull())
+ {
+ data.text = GetParametrEmptyString(text, AttrText);
+ data.textRotation = GetParametrUInt(text, AttrRotation, QChar('0'));
+ data.font.fromString(GetParametrEmptyString(text, AttrFont));
+ }
+
+ QDomElement image = rootElement.firstChildElement(TagImage);
+ if (not image.isNull())
+ {
+ data.path = GetParametrEmptyString(image, AttrPath);
+ data.imageRotation = GetParametrUInt(image, AttrRotation, QChar('0'));
+ data.grayscale = GetParametrBool(image, AttrGrayscale, falseStr);
+ }
+ }
+
+ return data;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VWatermark::SetWatermark(const VWatermarkData &data)
+{
+ QDomNode root = documentElement();
+ if (not root.isNull() && root.isElement())
+ {
+ QDomElement rootElement = root.toElement();
+ SetAttribute(rootElement, AttrOpacity, data.opacity);
+
+ QDomElement text = rootElement.firstChildElement(TagText);
+ if (not text.isNull())
+ {
+ SetAttributeOrRemoveIf(text, AttrText, data.text, data.text.isEmpty());
+ SetAttributeOrRemoveIf(text, AttrRotation, data.textRotation, data.textRotation == 0);
+ const QString fontString = data.font.toString();
+ SetAttributeOrRemoveIf(text, AttrFont, fontString, fontString.isEmpty());
+ }
+
+ QDomElement image = rootElement.firstChildElement(TagImage);
+ if (not image.isNull())
+ {
+ SetAttributeOrRemoveIf(image, AttrPath, data.path, data.path.isEmpty());
+ SetAttributeOrRemoveIf(image, AttrRotation, data.imageRotation, data.imageRotation == 0);
+ SetAttributeOrRemoveIf(image, AttrGrayscale, data.grayscale, data.grayscale == false);
+ }
+ }
+}
diff --git a/src/libs/vformat/vwatermark.h b/src/libs/vformat/vwatermark.h
new file mode 100644
index 000000000..37cb48c7d
--- /dev/null
+++ b/src/libs/vformat/vwatermark.h
@@ -0,0 +1,63 @@
+/************************************************************************
+ **
+ ** @file vwatermark.h
+ ** @author Roman Telezhynskyi
+ ** @date 25 12, 2019
+ **
+ ** @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) 2019 Valentina project
+ ** 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 .
+ **
+ *************************************************************************/
+#ifndef VWATERMARK_H
+#define VWATERMARK_H
+
+#include "../ifc/xml/vdomdocument.h"
+
+
+class VWatermark : public VDomDocument
+{
+ Q_DECLARE_TR_FUNCTIONS(VWatermark)
+public:
+ VWatermark();
+ virtual ~VWatermark() Q_DECL_EQ_DEFAULT;
+
+ void CreateEmptyWatermark();
+
+ virtual bool SaveDocument(const QString &fileName, QString &error) override;
+
+ VWatermarkData GetWatermark() const;
+ void SetWatermark(const VWatermarkData &data);
+
+ static const QString TagWatermark;
+ static const QString TagText;
+ static const QString TagImage;
+
+ static const QString AttrOpacity;
+ static const QString AttrText;
+ static const QString AttrRotation;
+ static const QString AttrFont;
+ static const QString AttrPath;
+ static const QString AttrGrayscale;
+
+private:
+ Q_DISABLE_COPY(VWatermark)
+};
+
+#endif // VWATERMARK_H
diff --git a/src/libs/vlayout/vposter.cpp b/src/libs/vlayout/vposter.cpp
index 6a925ce56..7a640c0ef 100644
--- a/src/libs/vlayout/vposter.cpp
+++ b/src/libs/vlayout/vposter.cpp
@@ -29,7 +29,6 @@
#include "vposter.h"
#include
-#include
#include
#include
#include
@@ -41,10 +40,14 @@
#include
#include
#include
+#include
+#include
+#include
#include "../vmisc/vmath.h"
#include "../vmisc/def.h"
#include "../vmisc/vabstractapplication.h"
+#include "../ifc/exception/vexception.h"
namespace
{
@@ -53,6 +56,65 @@ qreal ToPixel(qreal val)
{
return val / 25.4 * PrintDPI; // Mm to pixels with current dpi.
}
+
+//---------------------------------------------------------------------------------------------------------------------
+QImage Grayscale(QImage image)
+{
+ for (int ii = 0; ii < image.height(); ii++)
+ {
+ uchar* scan = image.scanLine(ii);
+ int depth = 4;
+ for (int jj = 0; jj < image.width(); jj++)
+ {
+ QRgb* rgbpixel = reinterpret_cast(scan + jj * depth);
+ int gray = qGray(*rgbpixel);
+ *rgbpixel = QColor(gray, gray, gray, qAlpha(*rgbpixel)).rgba();
+ }
+ }
+
+ return image;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QPixmap WatermarkImageFromCache(const VWatermarkData &watermarkData, const QString &watermarkPath, QString &error)
+{
+ QPixmap pixmap;
+ QString imagePath = AbsoluteMPath(watermarkPath, watermarkData.path);
+
+ if (not QPixmapCache::find(imagePath, pixmap))
+ {
+ QImageReader imageReader(imagePath);
+ QImage watermark = imageReader.read();
+ if (watermark.isNull())
+ {
+ error = imageReader.errorString();
+ return pixmap;
+ }
+
+ if (watermarkData.grayscale)
+ {
+ watermark = Grayscale(watermark);
+ watermark.save("/home/dismine/grayscale.png", "PNG");
+ }
+
+ // Workaround for QGraphicsPixmapItem opacity problem.
+ // Opacity applied only if use a cached pixmap and only after first draw. First image always has opacity 1.
+ // Preparing an image manually allows to avoid the problem.
+ QImage tmp(watermark.width(), watermark.height(), watermark.format());
+ tmp = tmp.convertToFormat(QImage::Format_ARGB32);
+ tmp.fill(Qt::transparent);
+ QPainter p;
+ p.begin(&tmp);
+ p.setOpacity(watermarkData.opacity/100.);
+ p.drawImage(QPointF(), watermark);
+ p.end();
+
+ pixmap = QPixmap::fromImage(tmp);
+
+ QPixmapCache::insert(imagePath, pixmap);
+ }
+ return pixmap;
+}
}
//---------------------------------------------------------------------------------------------------------------------
@@ -89,6 +151,31 @@ QVector VPoster::Calc(const QRect &imageRect, int page, PageOrientat
return poster;
}
+//---------------------------------------------------------------------------------------------------------------------
+QVector VPoster::Tile(QGraphicsItem *parent,
+ const PosterData &img,
+ int sheets,
+ const VWatermarkData &watermarkData, const QString &watermarkPath) const
+{
+ QVector data;
+ data.append(Borders(parent, img, sheets));
+
+ if (watermarkData.opacity > 0)
+ {
+ if (not watermarkData.path.isEmpty())
+ {
+ data += ImageWatermark(parent, img, watermarkData, watermarkPath);
+ }
+
+ if (not watermarkData.text.isEmpty())
+ {
+ data += TextWatermark(parent, img, watermarkData);
+ }
+ }
+
+ return data;
+}
+
//---------------------------------------------------------------------------------------------------------------------
QVector VPoster::Borders(QGraphicsItem *parent, const PosterData &img, int sheets) const
{
@@ -176,6 +263,84 @@ QVector VPoster::Borders(QGraphicsItem *parent, const PosterDat
return data;
}
+//---------------------------------------------------------------------------------------------------------------------
+QVector VPoster::TextWatermark(QGraphicsItem *parent, const PosterData &img,
+ const VWatermarkData &watermarkData) const
+{
+ SCASSERT(parent != nullptr)
+
+ QVector data;
+
+ QGraphicsSimpleTextItem *text = new QGraphicsSimpleTextItem(watermarkData.text, parent);
+ text->setFont(watermarkData.font);
+ text->setOpacity(watermarkData.opacity/100.);
+ text->setTransformOriginPoint(text->boundingRect().center());
+ text->setRotation(-watermarkData.textRotation);
+
+ const QRect boundingRect = text->boundingRect().toRect();
+ int x = img.rect.x() + (img.rect.width() - boundingRect.width()) / 2;
+ int y = img.rect.y() + (img.rect.height() - boundingRect.height()) / 2;
+
+ text->setX(x);
+ text->setY(y);
+ text->setZValue(-1);
+
+ data.append(text);
+
+ return data;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+QVector VPoster::ImageWatermark(QGraphicsItem *parent, const PosterData &img,
+ const VWatermarkData &watermarkData,
+ const QString &watermarkPath) const
+{
+ SCASSERT(parent != nullptr)
+
+ QVector data;
+
+ QGraphicsItem *image = nullptr;
+
+ QFileInfo f(watermarkData.path);
+ if (f.suffix() == "png" || f.suffix() == "jpg" || f.suffix() == "jpeg" || f.suffix() == "bmp")
+ {
+ QString error;
+ QPixmap watermark = WatermarkImageFromCache(watermarkData, watermarkPath, error);
+
+ if (watermark.isNull())
+ {
+ const QString errorMsg = tr("Cannot open the watermark image. %1").arg(error);
+ qApp->IsPedantic() ? throw VException(errorMsg) :
+ qWarning() << VAbstractApplication::patternMessageSignature + errorMsg;
+ return data;
+ }
+
+ image = new QGraphicsPixmapItem(watermark, parent);
+ }
+ else
+ {
+ const QString errorMsg = tr("Not supported file suffix '%1'").arg(f.suffix());
+ qApp->IsPedantic() ? throw VException(errorMsg) :
+ qWarning() << VAbstractApplication::patternMessageSignature + errorMsg;
+ return data;
+ }
+
+ image->setZValue(-1);
+ image->setTransformOriginPoint(image->boundingRect().center());
+ image->setRotation(-watermarkData.imageRotation);
+
+ const QRect boundingRect = image->boundingRect().toRect();
+ int x = img.rect.x() + (img.rect.width() - boundingRect.width()) / 2;
+ int y = img.rect.y() + (img.rect.height() - boundingRect.height()) / 2;
+
+ image->setX(x);
+ image->setY(y);
+
+ data.append(image);
+
+ return data;
+}
+
//---------------------------------------------------------------------------------------------------------------------
int VPoster::CountRows(int height, PageOrientation orientation) const
{
diff --git a/src/libs/vlayout/vposter.h b/src/libs/vlayout/vposter.h
index 79b985a83..d242658b5 100644
--- a/src/libs/vlayout/vposter.h
+++ b/src/libs/vlayout/vposter.h
@@ -34,10 +34,12 @@
#include
#include "../vmisc/def.h"
+#include "../vlayout/vtextmanager.h"
class QGraphicsItem;
class QPrinter;
template class QVector;
+class VWatermarkData;
struct PosterData
{
@@ -68,7 +70,9 @@ public:
QVector Calc(const QRect &imageRect, int page, PageOrientation orientation) const;
- QVector Borders(QGraphicsItem *parent, const PosterData &img, int sheets) const;
+ QVector Tile(QGraphicsItem *parent, const PosterData &img, int sheets,
+ const VWatermarkData &watermarkData, const QString &watermarkPath) const;
+
private:
const QPrinter *printer;
/**
@@ -85,6 +89,13 @@ private:
QRect PageRect() const;
void Ruler(QVector &data, QGraphicsItem *parent, QRect rec) const;
+
+ QVector Borders(QGraphicsItem *parent, const PosterData &img, int sheets) const;
+
+ QVector TextWatermark(QGraphicsItem *parent, const PosterData &img,
+ const VWatermarkData &watermarkData) const;
+ QVector ImageWatermark(QGraphicsItem *parent, const PosterData &img,
+ const VWatermarkData &watermarkData, const QString &watermarkPath) const;
};
#endif // VPOSTER_H
diff --git a/src/libs/vmisc/share/resources/icon.qrc b/src/libs/vmisc/share/resources/icon.qrc
index 1e346727e..ebd7ae48f 100644
--- a/src/libs/vmisc/share/resources/icon.qrc
+++ b/src/libs/vmisc/share/resources/icon.qrc
@@ -79,5 +79,11 @@
icon/32x32/button@2x.png
icon/16x16/broom.png
icon/16x16/broom@2x.png
+ icon/16x16/font_preferences@2x.png
+ icon/16x16/font_preferences.png
+ icon/32x32/font_preferences@2x.png
+ icon/32x32/font_preferences.png
+ icon/24x24/font_preferences@2x.png
+ icon/24x24/font_preferences.png
diff --git a/src/libs/vmisc/share/resources/icon/16x16/font_preferences.png b/src/libs/vmisc/share/resources/icon/16x16/font_preferences.png
new file mode 100644
index 000000000..8fd032e65
Binary files /dev/null and b/src/libs/vmisc/share/resources/icon/16x16/font_preferences.png differ
diff --git a/src/libs/vmisc/share/resources/icon/16x16/font_preferences@2x.png b/src/libs/vmisc/share/resources/icon/16x16/font_preferences@2x.png
new file mode 100644
index 000000000..a6041a898
Binary files /dev/null and b/src/libs/vmisc/share/resources/icon/16x16/font_preferences@2x.png differ
diff --git a/src/libs/vmisc/share/resources/icon/24x24/font_preferences.png b/src/libs/vmisc/share/resources/icon/24x24/font_preferences.png
new file mode 100644
index 000000000..93d71b5ac
Binary files /dev/null and b/src/libs/vmisc/share/resources/icon/24x24/font_preferences.png differ
diff --git a/src/libs/vmisc/share/resources/icon/24x24/font_preferences@2x.png b/src/libs/vmisc/share/resources/icon/24x24/font_preferences@2x.png
new file mode 100644
index 000000000..2cb6e7fd8
Binary files /dev/null and b/src/libs/vmisc/share/resources/icon/24x24/font_preferences@2x.png differ
diff --git a/src/libs/vmisc/share/resources/icon/32x32/font_preferences.png b/src/libs/vmisc/share/resources/icon/32x32/font_preferences.png
new file mode 100644
index 000000000..a6041a898
Binary files /dev/null and b/src/libs/vmisc/share/resources/icon/32x32/font_preferences.png differ
diff --git a/src/libs/vmisc/share/resources/icon/32x32/font_preferences@2x.png b/src/libs/vmisc/share/resources/icon/32x32/font_preferences@2x.png
new file mode 100644
index 000000000..82c247c2d
Binary files /dev/null and b/src/libs/vmisc/share/resources/icon/32x32/font_preferences@2x.png differ
diff --git a/src/libs/vmisc/share/resources/icon/svg/font_preferences.svg b/src/libs/vmisc/share/resources/icon/svg/font_preferences.svg
new file mode 100644
index 000000000..8ea824632
--- /dev/null
+++ b/src/libs/vmisc/share/resources/icon/svg/font_preferences.svg
@@ -0,0 +1,245 @@
+
+
+
+
diff --git a/src/libs/vmisc/vsettings.cpp b/src/libs/vmisc/vsettings.cpp
index 12792f72a..548b69fc9 100644
--- a/src/libs/vmisc/vsettings.cpp
+++ b/src/libs/vmisc/vsettings.cpp
@@ -119,6 +119,8 @@ Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingDockWidgetPatternMessagesActive,
(QLatin1String("dockWidget/patternMessagesActive")))
Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingPatternMessagesFontSize, (QLatin1String("font/patternMessagesSize")))
+Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingWatermarkEditorSize, (QLatin1String("watermarkEditorSize")))
+
// Reading settings file is very expensive, cache values to speed up getting a value
int scrollingDurationCached = -1;
int scrollingUpdateIntervalCached = -1;
@@ -781,6 +783,18 @@ void VSettings::SetAutoRefreshPatternMessage(bool value)
setValue(*settingAutoRefreshPatternMessage, value);
}
+//---------------------------------------------------------------------------------------------------------------------
+QSize VSettings::GetWatermarkEditorSize() const
+{
+ return value(*settingWatermarkEditorSize, QSize(0, 0)).toSize();
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VSettings::SetWatermarkEditorSize(const QSize &sz)
+{
+ setValue(*settingWatermarkEditorSize, sz);
+}
+
//---------------------------------------------------------------------------------------------------------------------
template
T VSettings::GetCachedValue(T &cache, const QString &setting, T defValue, T valueMin, T valueMax) const
diff --git a/src/libs/vmisc/vsettings.h b/src/libs/vmisc/vsettings.h
index 96e39c151..21c13cb80 100644
--- a/src/libs/vmisc/vsettings.h
+++ b/src/libs/vmisc/vsettings.h
@@ -198,6 +198,9 @@ public:
bool GetAutoRefreshPatternMessage() const;
void SetAutoRefreshPatternMessage(bool value);
+ QSize GetWatermarkEditorSize() const;
+ void SetWatermarkEditorSize(const QSize& sz);
+
private:
Q_DISABLE_COPY(VSettings)