Export tiled PDF with watermark.

--HG--
branch : develop
This commit is contained in:
Roman Telezhynskyi 2019-12-13 10:51:29 +02:00
parent 41c3ddf5db
commit 1d7667df61
37 changed files with 3661 additions and 71 deletions

View File

@ -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.

View File

@ -14,7 +14,7 @@
<string>Pattern properties</string>
</property>
<property name="windowIcon">
<iconset resource="../../../libs/vmisc/share/resources/icon.qrc">
<iconset>
<normaloff>:/icon/64x64/icon64x64.png</normaloff>:/icon/64x64/icon64x64.png</iconset>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
@ -1220,13 +1220,26 @@
<string>Security</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_10">
<item alignment="Qt::AlignTop">
<item>
<widget class="QCheckBox" name="checkBoxPatternReadOnly">
<property name="text">
<string>Open only for read</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_4">
@ -1421,20 +1434,18 @@
</layout>
</widget>
<customwidgets>
<customwidget>
<class>VPlainTextEdit</class>
<extends>QPlainTextEdit</extends>
<header location="global">vplaintextedit.h</header>
</customwidget>
<customwidget>
<class>VLineEdit</class>
<extends>QLineEdit</extends>
<header>vlineedit.h</header>
</customwidget>
<customwidget>
<class>VPlainTextEdit</class>
<extends>QPlainTextEdit</extends>
<header>vplaintextedit.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="../../../libs/vmisc/share/resources/icon.qrc"/>
</resources>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>

View File

@ -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<QPointer<WatermarkWindow>> i(m_watermarkEditors);
while (i.hasNext())
{
QPointer<WatermarkWindow> 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<QPointer<WatermarkWindow>>::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);
}

View File

@ -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<QPointer<WatermarkWindow>> 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

View File

@ -1795,11 +1795,22 @@
<addaction name="actionDetails"/>
<addaction name="actionLayout"/>
</widget>
<widget class="QMenu" name="menuWatermark">
<property name="title">
<string>Watermark</string>
</property>
<addaction name="actionWatermarkEditor"/>
<addaction name="actionEditCurrentWatermark"/>
<addaction name="separator"/>
<addaction name="actionLoadWatermark"/>
<addaction name="actionRemoveWatermark"/>
</widget>
<addaction name="menuFile"/>
<addaction name="menuPatternPiece"/>
<addaction name="menuMode"/>
<addaction name="menuMeasurements"/>
<addaction name="menuHistory"/>
<addaction name="menuWatermark"/>
<addaction name="menuWindow"/>
<addaction name="menuHelp"/>
</widget>
@ -2980,6 +2991,50 @@
<string>Globally show pieces main path</string>
</property>
</action>
<action name="actionLoadWatermark">
<property name="enabled">
<bool>false</bool>
</property>
<property name="icon">
<iconset theme="document-open">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>Load</string>
</property>
</action>
<action name="actionRemoveWatermark">
<property name="enabled">
<bool>false</bool>
</property>
<property name="icon">
<iconset theme="edit-delete">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>Remove</string>
</property>
</action>
<action name="actionEditCurrentWatermark">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Edit current</string>
</property>
</action>
<action name="actionWatermarkEditor">
<property name="icon">
<iconset theme="document-new">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>Editor</string>
</property>
<property name="toolTip">
<string>Create or edit a watermark</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>

View File

@ -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 <QFileDialog>
#include <QFileInfo>
@ -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<QGraphicsItem *> 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<QGraphicsRectItem *>(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;
}
//---------------------------------------------------------------------------------------------------------------------

View File

@ -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;

View File

@ -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

View File

@ -0,0 +1,728 @@
/************************************************************************
**
** @file watermarkwindow.cpp
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @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
** <https://bitbucket.org/dismine/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#include "watermarkwindow.h"
#include "ui_watermarkwindow.h"
#include <QCloseEvent>
#include <QFileDialog>
#include <QFileInfo>
#include <QFontDialog>
#include <QFuture>
#include <QMessageBox>
#include <QtConcurrent>
#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<int>::of(&QSpinBox::valueChanged),this,
[this](){WatermarkChangesWereSaved(false);});
connect(ui->lineEditText, &QLineEdit::textChanged, this, [this]()
{
WatermarkChangesWereSaved(false);
});
connect(ui->spinBoxTextRotation, QOverload<int>::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<int>::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<VWatermarkConverter *> futureConverter = QtConcurrent::run([path]()
{
QScopedPointer<VWatermarkConverter> 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<VWatermarkConverter> 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<char> 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<QMessageBox> 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<QMessageBox::StandardButton>(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 &currentFormatVersion, 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);
}
}

View File

@ -0,0 +1,103 @@
/************************************************************************
**
** @file watermarkwindow.h
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @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
** <https://bitbucket.org/dismine/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#ifndef WATERMARKWINDOW_H
#define WATERMARKWINDOW_H
#include <QMainWindow>
#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<VLockGuard<char>> lock{};
bool MaybeSave();
void UpdateWindowTitle();
QString GetWatermarkFileName();
bool ContinueFormatRewrite(const QString &currentFormatVersion, 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

View File

@ -0,0 +1,363 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>WatermarkWindow</class>
<widget class="QMainWindow" name="WatermarkWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>532</width>
<height>468</height>
</rect>
</property>
<property name="windowTitle">
<string>Watermark</string>
</property>
<property name="windowIcon">
<iconset resource="../../libs/vmisc/share/resources/icon.qrc">
<normaloff>:/icon/64x64/icon64x64.png</normaloff>:/icon/64x64/icon64x64.png</iconset>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonTextUnderIcon</enum>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QScrollArea" name="scrollArea">
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>512</width>
<height>344</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Opacity:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="spinBoxOpacity">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="suffix">
<string notr="true">%</string>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="value">
<number>20</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Text</string>
</property>
<layout class="QFormLayout" name="formLayout_3">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Text:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="lineEditText">
<property name="inputMask">
<string/>
</property>
<property name="maxLength">
<number>32767</number>
</property>
<property name="placeholderText">
<string>watermark text</string>
</property>
<property name="clearButtonEnabled">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Rotation:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="spinBoxTextRotation">
<property name="suffix">
<string notr="true">°</string>
</property>
<property name="maximum">
<number>360</number>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Font:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLineEdit" name="lineEditFontSample">
<property name="text">
<string extracomment="Use native text to test a font options">The quick brown fox jumps over the lazy dog</string>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="toolButtonFont">
<property name="toolTip">
<string>Edit font</string>
</property>
<property name="text">
<string notr="true">...</string>
</property>
<property name="icon">
<iconset resource="../../libs/vmisc/share/resources/icon.qrc">
<normaloff>:/icon/24x24/font_preferences.png</normaloff>:/icon/24x24/font_preferences.png</iconset>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Image</string>
</property>
<layout class="QFormLayout" name="formLayout_2">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Path:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLineEdit" name="lineEditPath">
<property name="placeholderText">
<string>path to image</string>
</property>
<property name="clearButtonEnabled">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButtonBrowse">
<property name="text">
<string>Browse…</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Rotation:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="spinBoxImageRotation">
<property name="suffix">
<string notr="true">°</string>
</property>
<property name="maximum">
<number>100</number>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="checkBoxGrayColor">
<property name="text">
<string>Gray color</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>532</width>
<height>22</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
<property name="title">
<string>&amp;File</string>
</property>
<addaction name="actionNew"/>
<addaction name="actionOpen"/>
<addaction name="actionSave"/>
<addaction name="actionSaveAs"/>
<addaction name="separator"/>
<addaction name="actionExit"/>
</widget>
<addaction name="menuFile"/>
</widget>
<widget class="QStatusBar" name="statusbar"/>
<widget class="QToolBar" name="toolBar">
<property name="windowTitle">
<string>Operations</string>
</property>
<property name="movable">
<bool>false</bool>
</property>
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
<addaction name="actionNew"/>
<addaction name="actionOpen"/>
<addaction name="actionSave"/>
</widget>
<action name="actionSave">
<property name="icon">
<iconset theme="document-save">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>Save</string>
</property>
</action>
<action name="actionSaveAs">
<property name="icon">
<iconset theme="document-save-as">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>Save &amp;As…</string>
</property>
</action>
<action name="actionExit">
<property name="icon">
<iconset theme="application-exit">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>E&amp;xit</string>
</property>
</action>
<action name="actionOpen">
<property name="icon">
<iconset theme="document-open">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>Open</string>
</property>
</action>
<action name="actionNew">
<property name="icon">
<iconset theme="document-new">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>New</string>
</property>
</action>
</widget>
<resources>
<include location="../../libs/vmisc/share/resources/icon.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -35,6 +35,7 @@
# include <qt_windows.h>
#endif /*Q_OS_WIN*/
#include <QFont>
#include <QString>
#include <QStringList>
@ -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

View File

@ -57,6 +57,7 @@
<file>schema/pattern/v0.8.3.xsd</file>
<file>schema/pattern/v0.8.4.xsd</file>
<file>schema/pattern/v0.8.5.xsd</file>
<file>schema/pattern/v0.8.6.xsd</file>
<file>schema/standard_measurements/v0.3.0.xsd</file>
<file>schema/standard_measurements/v0.4.0.xsd</file>
<file>schema/standard_measurements/v0.4.1.xsd</file>
@ -71,5 +72,6 @@
<file>schema/individual_measurements/v0.4.0.xsd</file>
<file>schema/individual_measurements/v0.5.0.xsd</file>
<file>schema/label_template/v1.0.0.xsd</file>
<file>schema/watermark/v1.0.0.xsd</file>
</qresource>
</RCC>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,51 @@
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="watermark">
<xs:complexType>
<xs:sequence>
<xs:element type="formatVersion" name="version"/>
<xs:element name="text">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:string" name="text"/>
<xs:attribute type="rotationType" name="rotation"/>
<xs:attribute type="xs:string" name="font"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name="image">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:string" name="path"/>
<xs:attribute type="rotationType" name="rotation"/>
<xs:attribute type="xs:boolean" name="grayscale"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="opacityType" name="opacity"/>
</xs:complexType>
</xs:element>
<xs:simpleType name="formatVersion">
<xs:restriction base="xs:string">
<xs:pattern value="[0-9]{1,}\.[0-9]{1,}\.[0-9]{1,}"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="opacityType">
<xs:restriction base="xs:unsignedInt">
<xs:minInclusive value="0"/>
<xs:maxInclusive value="100"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="rotationType">
<xs:restriction base="xs:unsignedInt">
<xs:minInclusive value="0"/>
<xs:maxInclusive value="360"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>

View File

@ -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<VFormulaField> &expressions, const QDomElement &element, const QString &attribute)
@ -1525,6 +1529,48 @@ QVector<VLabelTemplateLine> 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<int, QString> &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)

View File

@ -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<VLabelTemplateLine> &lines);
QVector<VLabelTemplateLine> GetPatternLabelTemplate() const;
bool SetWatermarkPath(const QString &path);
QString GetWatermarkPath() const;
void SetPatternMaterials(const QMap<int, QString> &materials);
QMap<int, QString> 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;

View File

@ -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()
{

View File

@ -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();

View File

@ -0,0 +1,108 @@
/************************************************************************
**
** @file vwatermarkconverter.cpp
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @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
** <https://bitbucket.org/dismine/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#include "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();
}

View File

@ -0,0 +1,62 @@
/************************************************************************
**
** @file vwatermarkconverter.h
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @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
** <https://bitbucket.org/dismine/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#ifndef 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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,144 @@
/************************************************************************
**
** @file vwatermark.cpp
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @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
** <https://bitbucket.org/dismine/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#include "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);
}
}
}

View File

@ -0,0 +1,63 @@
/************************************************************************
**
** @file vwatermark.h
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @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
** <https://bitbucket.org/dismine/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#ifndef 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

View File

@ -29,7 +29,6 @@
#include "vposter.h"
#include <QGraphicsLineItem>
#include <QGraphicsPixmapItem>
#include <QGraphicsTextItem>
#include <QPen>
#include <QPixmap>
@ -41,10 +40,14 @@
#include <QDebug>
#include <QFont>
#include <QFontMetrics>
#include <QImageReader>
#include <QPixmapCache>
#include <QPainter>
#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<QRgb*>(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<PosterData> VPoster::Calc(const QRect &imageRect, int page, PageOrientat
return poster;
}
//---------------------------------------------------------------------------------------------------------------------
QVector<QGraphicsItem *> VPoster::Tile(QGraphicsItem *parent,
const PosterData &img,
int sheets,
const VWatermarkData &watermarkData, const QString &watermarkPath) const
{
QVector<QGraphicsItem *> 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<QGraphicsItem *> VPoster::Borders(QGraphicsItem *parent, const PosterData &img, int sheets) const
{
@ -176,6 +263,84 @@ QVector<QGraphicsItem *> VPoster::Borders(QGraphicsItem *parent, const PosterDat
return data;
}
//---------------------------------------------------------------------------------------------------------------------
QVector<QGraphicsItem *> VPoster::TextWatermark(QGraphicsItem *parent, const PosterData &img,
const VWatermarkData &watermarkData) const
{
SCASSERT(parent != nullptr)
QVector<QGraphicsItem *> 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<QGraphicsItem *> VPoster::ImageWatermark(QGraphicsItem *parent, const PosterData &img,
const VWatermarkData &watermarkData,
const QString &watermarkPath) const
{
SCASSERT(parent != nullptr)
QVector<QGraphicsItem *> 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
{

View File

@ -34,10 +34,12 @@
#include <QtGlobal>
#include "../vmisc/def.h"
#include "../vlayout/vtextmanager.h"
class QGraphicsItem;
class QPrinter;
template <class T> class QVector;
class VWatermarkData;
struct PosterData
{
@ -68,7 +70,9 @@ public:
QVector<PosterData> Calc(const QRect &imageRect, int page, PageOrientation orientation) const;
QVector<QGraphicsItem *> Borders(QGraphicsItem *parent, const PosterData &img, int sheets) const;
QVector<QGraphicsItem *> 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<QGraphicsItem *> &data, QGraphicsItem *parent, QRect rec) const;
QVector<QGraphicsItem *> Borders(QGraphicsItem *parent, const PosterData &img, int sheets) const;
QVector<QGraphicsItem *> TextWatermark(QGraphicsItem *parent, const PosterData &img,
const VWatermarkData &watermarkData) const;
QVector<QGraphicsItem *> ImageWatermark(QGraphicsItem *parent, const PosterData &img,
const VWatermarkData &watermarkData, const QString &watermarkPath) const;
};
#endif // VPOSTER_H

View File

@ -79,5 +79,11 @@
<file>icon/32x32/button@2x.png</file>
<file>icon/16x16/broom.png</file>
<file>icon/16x16/broom@2x.png</file>
<file>icon/16x16/font_preferences@2x.png</file>
<file>icon/16x16/font_preferences.png</file>
<file>icon/32x32/font_preferences@2x.png</file>
<file>icon/32x32/font_preferences.png</file>
<file>icon/24x24/font_preferences@2x.png</file>
<file>icon/24x24/font_preferences.png</file>
</qresource>
</RCC>

Binary file not shown.

After

Width:  |  Height:  |  Size: 890 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -0,0 +1,245 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
inkscape:export-ydpi="96"
inkscape:export-xdpi="96"
inkscape:export-filename="/home/dismine/CAD/Valentina_0.7.x/valentina/src/libs/vmisc/share/resources/icon/24x24/font_preferences@2x.png"
width="48px"
height="48px"
id="svg11300"
sodipodi:version="0.32"
inkscape:version="0.92.4 (unknown)"
sodipodi:docname="font_preferences.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
version="1.1">
<defs
id="defs3">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 24 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="48 : 24 : 1"
inkscape:persp3d-origin="24 : 16 : 1"
id="perspective34" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient5060"
id="radialGradient6719"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-2.774389,0,0,1.969706,112.7623,-872.8854)"
cx="605.71429"
cy="486.64789"
fx="605.71429"
fy="486.64789"
r="117.14286" />
<linearGradient
inkscape:collect="always"
id="linearGradient5060">
<stop
style="stop-color:black;stop-opacity:1;"
offset="0"
id="stop5062" />
<stop
style="stop-color:black;stop-opacity:0;"
offset="1"
id="stop5064" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient5060"
id="radialGradient6717"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(2.774389,0,0,1.969706,-1891.633,-872.8854)"
cx="605.71429"
cy="486.64789"
fx="605.71429"
fy="486.64789"
r="117.14286" />
<linearGradient
id="linearGradient5048">
<stop
style="stop-color:black;stop-opacity:0;"
offset="0"
id="stop5050" />
<stop
id="stop5056"
offset="0.5"
style="stop-color:black;stop-opacity:1;" />
<stop
style="stop-color:black;stop-opacity:0;"
offset="1"
id="stop5052" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5048"
id="linearGradient6715"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(2.774389,0,0,1.969706,-1892.179,-872.8854)"
x1="302.85715"
y1="366.64789"
x2="302.85715"
y2="609.50507" />
<linearGradient
id="linearGradient11520">
<stop
id="stop11522"
offset="0.0000000"
style="stop-color:#ffffff;stop-opacity:1.0000000;" />
<stop
id="stop11524"
offset="1.0000000"
style="stop-color:#dcdcdc;stop-opacity:1.0000000;" />
</linearGradient>
<linearGradient
id="linearGradient11508"
inkscape:collect="always">
<stop
id="stop11510"
offset="0"
style="stop-color:#000000;stop-opacity:1;" />
<stop
id="stop11512"
offset="1"
style="stop-color:#000000;stop-opacity:0;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient11508"
id="radialGradient1348"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.000000,0.000000,0.000000,0.338462,-1.435476e-15,29.48178)"
cx="30.203562"
cy="44.565483"
fx="30.203562"
fy="44.565483"
r="6.5659914" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient11520"
id="radialGradient1366"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.995058,-1.651527e-32,0.000000,1.995058,-24.32488,-35.70087)"
cx="24.445690"
cy="35.878170"
fx="24.445690"
fy="35.878170"
r="20.530962" />
</defs>
<sodipodi:namedview
stroke="#ef2929"
fill="#eeeeec"
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="0.25490196"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1"
inkscape:cx="-337.1819"
inkscape:cy="22.612601"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:showpageshadow="false"
inkscape:window-width="1853"
inkscape:window-height="1025"
inkscape:window-x="67"
inkscape:window-y="27"
inkscape:window-maximized="1" />
<metadata
id="metadata4">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:creator>
<cc:Agent>
<dc:title>Jakub Steiner</dc:title>
</cc:Agent>
</dc:creator>
<dc:source>http://jimmac.musichall.cz</dc:source>
<cc:license
rdf:resource="http://creativecommons.org/publicdomain/zero/1.0/" />
<dc:title>Wi-Fi network</dc:title>
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/publicdomain/zero/1.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
</cc:License>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<g
transform="matrix(2.33489e-2,0,0,2.564584e-2,45.48163,38.7308)"
id="g6707">
<rect
style="opacity:0.40206185;color:black;fill:url(#linearGradient6715);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
id="rect6709"
width="1339.6335"
height="478.35718"
x="-1559.2523"
y="-150.69685" />
<path
style="opacity:0.40206185;color:black;fill:url(#radialGradient6717);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
d="M -219.61876,-150.68038 C -219.61876,-150.68038 -219.61876,327.65041 -219.61876,327.65041 C -76.744594,328.55086 125.78146,220.48075 125.78138,88.454235 C 125.78138,-43.572302 -33.655436,-150.68036 -219.61876,-150.68038 z "
id="path6711"
sodipodi:nodetypes="cccc" />
<path
sodipodi:nodetypes="cccc"
id="path6713"
d="M -1559.2523,-150.68038 C -1559.2523,-150.68038 -1559.2523,327.65041 -1559.2523,327.65041 C -1702.1265,328.55086 -1904.6525,220.48075 -1904.6525,88.454235 C -1904.6525,-43.572302 -1745.2157,-150.68036 -1559.2523,-150.68038 z "
style="opacity:0.40206185;color:black;fill:url(#radialGradient6719);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
</g>
<rect
ry="5.4548240"
rx="5.4548240"
y="3.5233452"
x="4.4147282"
height="40.061924"
width="40.061924"
id="rect11518"
style="opacity:1.0000000;color:#000000;fill:url(#radialGradient1366);fill-opacity:1.0000000;fill-rule:evenodd;stroke:#9b9b9b;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:bevel;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10.000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible" />
<rect
style="opacity:1.0000000;color:#000000;fill:none;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.99999976;stroke-linecap:butt;stroke-linejoin:bevel;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10.000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible"
id="rect11528"
width="37.696587"
height="37.696587"
x="5.5973887"
y="4.7060070"
rx="4.2426391"
ry="4.2426391" />
<path
style="font-size:24px;font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:120.00000477%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
d="M 19.187523,7.5673065 L 16.902367,15.512619 L 16.644555,16.579025 C 16.621108,16.680589 16.60939,16.766527 16.609398,16.836838 C 16.60939,16.961839 16.648452,17.071214 16.726586,17.164963 C 16.789077,17.235276 16.867202,17.270432 16.960961,17.270432 C 17.062514,17.270432 17.195327,17.207932 17.359398,17.082932 C 17.664076,16.85637 18.070326,16.387621 18.578148,15.676682 L 18.976586,15.957932 C 18.437513,16.770433 17.882826,17.391526 17.312523,17.821213 C 16.742202,18.243088 16.214859,18.454025 15.730492,18.454025 C 15.394547,18.454025 15.140641,18.368088 14.968773,18.196213 C 14.804704,18.03215 14.722673,17.789963 14.72268,17.46965 C 14.722673,17.086839 14.80861,16.582933 14.980492,15.957932 L 15.226586,15.079025 C 14.203142,16.414965 13.261737,17.348557 12.402367,17.879807 C 11.785176,18.262619 11.179708,18.454025 10.585961,18.454025 C 10.015646,18.454025 9.5234593,18.21965 9.1093984,17.7509 C 8.6953351,17.274339 8.4883041,16.621996 8.4883046,15.793869 C 8.4883041,14.551685 8.8593974,13.243093 9.6015859,11.868088 C 10.351583,10.485283 11.300801,9.3798153 12.449242,8.5516815 C 13.347674,7.8954418 14.19533,7.5673171 14.992211,7.5673065 C 15.468766,7.5673171 15.863297,7.692317 16.175805,7.9423065 C 16.496109,8.1923165 16.738296,8.6063786 16.902367,9.184494 L 17.324242,7.8485565 L 19.187523,7.5673065 M 15.015648,8.1766815 C 14.515642,8.1766915 13.984392,8.4110663 13.421898,8.8798065 C 12.625019,9.5438776 11.914082,10.528252 11.289086,11.832932 C 10.671896,13.137624 10.363302,14.31731 10.363305,15.371994 C 10.363302,15.903246 10.496115,16.325121 10.761742,16.637619 C 11.027364,16.942308 11.332051,17.094651 11.675805,17.09465 C 12.527363,17.094651 13.453143,16.465746 14.453148,15.207932 C 15.789078,13.536061 16.457046,11.821219 16.457055,10.0634 C 16.457046,9.3993465 16.32814,8.9188783 16.070336,8.621994 C 15.812515,8.3251289 15.460953,8.1766915 15.015648,8.1766815"
id="text3423" />
<path
style="font-size:29.01771545px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:120.00000477%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial Rounded CE"
d="M 23.843165,20.148025 L 23.843165,26.056417 C 24.570491,25.300761 25.311991,24.724563 26.067668,24.327823 C 26.823329,23.921665 27.758469,23.718579 28.873091,23.718564 C 30.157718,23.718579 31.281775,24.02557 32.245267,24.639536 C 33.218177,25.244086 33.969123,26.127274 34.498107,27.289103 C 35.036505,28.44151 35.305712,29.81116 35.305729,31.398057 C 35.305712,32.569351 35.154579,33.64618 34.852328,34.628545 C 34.559489,35.601473 34.129703,36.446878 33.562966,37.164761 C 32.996199,37.882649 32.306651,38.439954 31.49432,38.83668 C 30.691409,39.223961 29.803498,39.417601 28.830585,39.417601 C 28.235485,39.417601 27.673456,39.346757 27.144497,39.205069 C 26.624966,39.063381 26.18101,38.879187 25.812629,38.652486 C 25.444233,38.41634 25.127797,38.17547 24.863319,37.929877 C 24.608274,37.684285 24.268223,37.315897 23.843165,36.82471 L 23.843165,37.207268 C 23.843159,37.934601 23.668411,38.487184 23.318919,38.865018 C 22.969417,39.233407 22.525462,39.417601 21.987051,39.417601 C 21.439188,39.417601 20.999955,39.233407 20.669352,38.865018 C 20.348191,38.487184 20.187611,37.934601 20.187613,37.207268 L 20.187613,20.31805 C 20.187611,19.534063 20.343468,18.943696 20.655184,18.54695 C 20.976341,18.140798 21.420296,17.937712 21.987051,17.937691 C 22.582137,17.937712 23.040261,18.131352 23.361426,18.518612 C 23.68258,18.896467 23.843159,19.439604 23.843165,20.148025 M 24.02736,31.638927 C 24.027354,33.178609 24.376851,34.364065 25.075851,35.195297 C 25.784284,36.017091 26.709978,36.427986 27.852937,36.427983 C 28.825851,36.427986 29.66181,36.007645 30.360816,35.166959 C 31.069244,34.316836 31.423463,33.103043 31.423476,31.525576 C 31.423463,30.505431 31.277052,29.626966 30.984243,28.890178 C 30.691409,28.153411 30.275791,27.58666 29.737388,27.189921 C 29.198963,26.783761 28.570813,26.580675 27.852937,26.580663 C 27.11615,26.580675 26.459663,26.783761 25.883473,27.189921 C 25.307268,27.58666 24.853867,28.16758 24.523268,28.932685 C 24.192656,29.688364 24.027354,30.590443 24.02736,31.638927"
id="text3427" />
<path
style="font-size:19.52186584px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:120.00000477%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Carbon Block"
d="M 39.201934,12.649522 C 39.201926,12.84475 39.188912,13.13107 39.16289,13.508484 C 39.149868,13.8729 39.143361,14.139699 39.143368,14.308881 L 36.410307,14.308881 L 36.410307,11.907691 C 36.410302,11.439177 36.150011,11.204915 35.629432,11.204904 C 35.108846,11.204915 34.848554,11.439177 34.848558,11.907691 L 34.848558,19.618828 C 34.848554,20.100369 35.108846,20.341139 35.629432,20.341137 C 36.150011,20.341139 36.410302,20.100369 36.410307,19.618828 L 36.410307,17.061464 L 39.143368,17.061464 L 39.143368,19.560263 C 39.143361,20.328124 38.726894,20.913779 37.893969,21.317231 C 37.23022,21.642595 36.475375,21.805277 35.629432,21.805277 C 34.770467,21.805277 34.015622,21.642595 33.364896,21.317231 C 32.531962,20.913779 32.115496,20.328124 32.115496,19.560263 L 32.115496,12.044344 C 32.115496,10.599737 33.286807,9.877429 35.629432,9.8774174 C 36.800739,9.877429 37.6597,10.053126 38.206319,10.404508 C 38.870055,10.833999 39.201926,11.582337 39.201934,12.649522"
id="text3431" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -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<typename T>
T VSettings::GetCachedValue(T &cache, const QString &setting, T defValue, T valueMin, T valueMax) const

View File

@ -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)