2020-12-19 18:10:55 +01:00
|
|
|
/************************************************************************
|
|
|
|
**
|
|
|
|
** @file vlayoutexporter.cpp
|
|
|
|
** @author Roman Telezhynskyi <dismine(at)gmail.com>
|
|
|
|
** @date 19 12, 2020
|
|
|
|
**
|
|
|
|
** @brief
|
|
|
|
** @copyright
|
|
|
|
** This source code is part of the Valentina project, a pattern making
|
|
|
|
** program, whose allow create and modeling patterns of clothing.
|
|
|
|
** Copyright (C) 2020 Valentina project
|
|
|
|
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
|
|
|
|
**
|
|
|
|
** Valentina is free software: you can redistribute it and/or modify
|
|
|
|
** it under the terms of the GNU General Public License as published by
|
|
|
|
** the Free Software Foundation, either version 3 of the License, or
|
|
|
|
** (at your option) any later version.
|
|
|
|
**
|
|
|
|
** Valentina is distributed in the hope that it will be useful,
|
|
|
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
** GNU General Public License for more details.
|
|
|
|
**
|
|
|
|
** You should have received a copy of the GNU General Public License
|
|
|
|
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
**
|
|
|
|
*************************************************************************/
|
|
|
|
#include "vlayoutexporter.h"
|
|
|
|
|
|
|
|
#include <QFileInfo>
|
|
|
|
#include <QGraphicsScene>
|
|
|
|
#include <QGuiApplication>
|
|
|
|
#include <QPainter>
|
|
|
|
#include <QPrinter>
|
|
|
|
#include <QProcess>
|
|
|
|
#include <QSvgGenerator>
|
|
|
|
#include <QTemporaryFile>
|
|
|
|
#include <QtDebug>
|
|
|
|
#include <QCursor>
|
|
|
|
#include <QGraphicsItem>
|
2021-01-23 17:47:41 +01:00
|
|
|
#include <QImageWriter>
|
2020-12-19 18:10:55 +01:00
|
|
|
|
2023-05-03 15:23:54 +02:00
|
|
|
#include "../ifc/exception/vexception.h"
|
|
|
|
#include "../vdxf/vdxfpaintdevice.h"
|
2020-12-19 18:10:55 +01:00
|
|
|
#include "../vmisc/def.h"
|
2023-05-03 15:23:54 +02:00
|
|
|
#include "../vmisc/defglobal.h"
|
|
|
|
#include "../vmisc/vabstractapplication.h"
|
2020-12-19 18:10:55 +01:00
|
|
|
#include "../vobj/vobjpaintdevice.h"
|
2023-04-10 11:20:18 +02:00
|
|
|
#include "vgraphicsfillitem.h"
|
2023-05-03 15:23:54 +02:00
|
|
|
#include "vprintlayout.h"
|
|
|
|
#include "vrawlayout.h"
|
2020-12-19 18:10:55 +01:00
|
|
|
|
|
|
|
namespace
|
|
|
|
{
|
|
|
|
#ifdef Q_OS_WIN
|
2022-08-12 17:50:13 +02:00
|
|
|
Q_GLOBAL_STATIC_WITH_ARGS(const QString, PDFTOPS, (QLatin1String("pdftops.exe"))) // NOLINT
|
2020-12-19 18:10:55 +01:00
|
|
|
#else
|
2022-08-12 17:50:13 +02:00
|
|
|
Q_GLOBAL_STATIC_WITH_ARGS(const QString, PDFTOPS, (QLatin1String("pdftops"))) // NOLINT
|
2020-12-19 18:10:55 +01:00
|
|
|
#endif
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
|
|
/**
|
|
|
|
* @brief PrepareTextForDXF prepare QGraphicsSimpleTextItem items for export to flat dxf.
|
|
|
|
*
|
|
|
|
* Because QPaintEngine::drawTextItem doesn't pass whole string per time we mark end of each string by adding special
|
|
|
|
* placholder. This method append it.
|
|
|
|
*
|
|
|
|
* @param placeholder placeholder that will be appended to each QGraphicsSimpleTextItem item's text string.
|
|
|
|
*/
|
2023-04-10 11:20:18 +02:00
|
|
|
void PrepareDetailsForDXF(const QString &placeholder, const QList<QGraphicsItem *> &paperItems)
|
2020-12-19 18:10:55 +01:00
|
|
|
{
|
2021-09-06 14:31:19 +02:00
|
|
|
for (auto *item : paperItems)
|
2020-12-19 18:10:55 +01:00
|
|
|
{
|
2021-09-06 14:31:19 +02:00
|
|
|
QList<QGraphicsItem *> pieceChildren = item->childItems();
|
|
|
|
for (auto *child : qAsConst(pieceChildren))
|
2020-12-19 18:10:55 +01:00
|
|
|
{
|
2021-09-06 14:31:19 +02:00
|
|
|
if (child->type() == QGraphicsSimpleTextItem::Type)
|
2020-12-19 18:10:55 +01:00
|
|
|
{
|
2021-09-06 14:31:19 +02:00
|
|
|
if(auto *textItem = qgraphicsitem_cast<QGraphicsSimpleTextItem *>(child))
|
2020-12-19 18:10:55 +01:00
|
|
|
{
|
2021-09-06 14:31:19 +02:00
|
|
|
textItem->setText(textItem->text() + placeholder);
|
2020-12-19 18:10:55 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
|
|
/**
|
|
|
|
* @brief RestoreTextAfterDXF restore QGraphicsSimpleTextItem items after export to flat dxf.
|
|
|
|
*
|
|
|
|
* Because QPaintEngine::drawTextItem doesn't pass whole string per time we mark end of each string by adding special
|
|
|
|
* placholder. This method remove it.
|
|
|
|
*
|
|
|
|
* @param placeholder placeholder that will be removed from each QGraphicsSimpleTextItem item's text string.
|
|
|
|
*/
|
2023-04-10 11:20:18 +02:00
|
|
|
void RestoreDetailsAfterDXF(const QString &placeholder, const QList<QGraphicsItem *> &paperItems)
|
2020-12-19 18:10:55 +01:00
|
|
|
{
|
2021-09-06 14:31:19 +02:00
|
|
|
for (auto *item : paperItems)
|
2020-12-19 18:10:55 +01:00
|
|
|
{
|
2021-09-06 14:31:19 +02:00
|
|
|
QList<QGraphicsItem *> pieceChildren = item->childItems();
|
|
|
|
for (auto *child : qAsConst(pieceChildren))
|
2020-12-19 18:10:55 +01:00
|
|
|
{
|
2021-09-06 14:31:19 +02:00
|
|
|
if (child->type() == QGraphicsSimpleTextItem::Type)
|
2020-12-19 18:10:55 +01:00
|
|
|
{
|
2021-09-06 14:31:19 +02:00
|
|
|
if(auto *textItem = qgraphicsitem_cast<QGraphicsSimpleTextItem *>(child))
|
2020-12-19 18:10:55 +01:00
|
|
|
{
|
2021-09-06 14:31:19 +02:00
|
|
|
QString text = textItem->text();
|
|
|
|
text.replace(placeholder, QString());
|
|
|
|
textItem->setText(text);
|
2020-12-19 18:10:55 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
2023-04-10 11:20:18 +02:00
|
|
|
auto VLayoutExporter::IsShowGrainline() const -> bool
|
2020-12-19 18:10:55 +01:00
|
|
|
{
|
2023-04-10 11:20:18 +02:00
|
|
|
return m_showGrainline;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
|
|
void VLayoutExporter::SetShowGrainline(bool show)
|
|
|
|
{
|
|
|
|
m_showGrainline = show;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
|
|
void VLayoutExporter::ExportToSVG(QGraphicsScene *scene, const QList<QGraphicsItem *> &details) const
|
|
|
|
{
|
|
|
|
PrepareGrainlineForExport(details, m_showGrainline);
|
|
|
|
|
2020-12-19 18:10:55 +01:00
|
|
|
QSvgGenerator generator;
|
|
|
|
generator.setFileName(m_fileName);
|
|
|
|
|
|
|
|
QSize drawingSize;
|
|
|
|
drawingSize.setWidth(qFloor(m_imageRect.width() * m_xScale + m_margins.left() + m_margins.right()));
|
|
|
|
drawingSize.setHeight(qFloor(m_imageRect.height() * m_yScale + m_margins.top() + m_margins.bottom()));
|
|
|
|
generator.setSize(drawingSize);
|
|
|
|
|
|
|
|
QRectF viewBoxRect;
|
|
|
|
viewBoxRect.setWidth(m_imageRect.width() * m_xScale + m_margins.left() + m_margins.right());
|
|
|
|
viewBoxRect.setHeight(m_imageRect.height() * m_yScale + m_margins.top() + m_margins.bottom());
|
|
|
|
generator.setViewBox(viewBoxRect);
|
|
|
|
|
|
|
|
generator.setTitle(m_title);
|
|
|
|
generator.setDescription(m_description);
|
|
|
|
generator.setResolution(static_cast<int>(PrintDPI));
|
|
|
|
|
|
|
|
QPainter painter;
|
|
|
|
painter.begin(&generator);
|
2021-06-28 19:05:19 +02:00
|
|
|
painter.translate(-m_offset.x(), -m_offset.y());
|
2020-12-19 18:10:55 +01:00
|
|
|
painter.translate(m_margins.left(), m_margins.top());
|
|
|
|
painter.setRenderHint(QPainter::Antialiasing, true);
|
|
|
|
painter.setPen(m_pen);
|
|
|
|
painter.setBrush(QBrush(Qt::NoBrush));
|
|
|
|
painter.scale(m_xScale, m_yScale);
|
|
|
|
scene->render(&painter, m_imageRect, m_imageRect, Qt::IgnoreAspectRatio);
|
|
|
|
painter.end();
|
2023-04-10 11:20:18 +02:00
|
|
|
|
|
|
|
RestoreGrainlineAfterExport(details);
|
2020-12-19 18:10:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
2023-04-10 11:20:18 +02:00
|
|
|
void VLayoutExporter::ExportToPNG(QGraphicsScene *scene, const QList<QGraphicsItem *> &details) const
|
2020-12-19 18:10:55 +01:00
|
|
|
{
|
2023-04-10 11:20:18 +02:00
|
|
|
PrepareGrainlineForExport(details, m_showGrainline);
|
|
|
|
|
2020-12-19 18:10:55 +01:00
|
|
|
// Create the image with the exact size of the shrunk scene
|
|
|
|
QSize drawingSize;
|
|
|
|
drawingSize.setWidth(qFloor(m_imageRect.width() * m_xScale + m_margins.left() + m_margins.right()));
|
|
|
|
drawingSize.setHeight(qFloor(m_imageRect.height() * m_yScale + m_margins.top() + m_margins.bottom()));
|
|
|
|
|
|
|
|
QImage image(drawingSize, QImage::Format_ARGB32);
|
|
|
|
image.fill(Qt::white);
|
|
|
|
|
|
|
|
QPainter painter(&image);
|
|
|
|
painter.translate(m_margins.left(), m_margins.top());
|
|
|
|
painter.setRenderHint(QPainter::Antialiasing, true);
|
|
|
|
painter.setPen(m_pen);
|
|
|
|
painter.setBrush(QBrush(Qt::NoBrush));
|
|
|
|
painter.scale(m_xScale, m_yScale);
|
|
|
|
|
|
|
|
scene->render(&painter, m_imageRect, m_imageRect, Qt::IgnoreAspectRatio);
|
|
|
|
image.save(m_fileName);
|
2023-04-10 11:20:18 +02:00
|
|
|
|
|
|
|
RestoreGrainlineAfterExport(details);
|
2020-12-19 18:10:55 +01:00
|
|
|
}
|
|
|
|
|
2021-01-23 17:47:41 +01:00
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
2023-04-10 11:20:18 +02:00
|
|
|
void VLayoutExporter::ExportToTIF(QGraphicsScene *scene, const QList<QGraphicsItem *> &details) const
|
2021-01-23 17:47:41 +01:00
|
|
|
{
|
2023-04-10 11:20:18 +02:00
|
|
|
PrepareGrainlineForExport(details, m_showGrainline);
|
|
|
|
|
2021-01-23 17:47:41 +01:00
|
|
|
// Create the image with the exact size of the shrunk scene
|
|
|
|
QSize drawingSize;
|
|
|
|
drawingSize.setWidth(qFloor(m_imageRect.width() * m_xScale + m_margins.left() + m_margins.right()));
|
|
|
|
drawingSize.setHeight(qFloor(m_imageRect.height() * m_yScale + m_margins.top() + m_margins.bottom()));
|
|
|
|
|
|
|
|
QImage image(drawingSize, QImage::Format_ARGB32);
|
|
|
|
image.fill(Qt::white);
|
|
|
|
|
|
|
|
QPainter painter(&image);
|
|
|
|
painter.translate(m_margins.left(), m_margins.top());
|
|
|
|
painter.setRenderHint(QPainter::Antialiasing, true);
|
|
|
|
painter.setPen(m_pen);
|
|
|
|
painter.setBrush(QBrush(Qt::NoBrush));
|
|
|
|
painter.scale(m_xScale, m_yScale);
|
|
|
|
|
|
|
|
scene->render(&painter, m_imageRect, m_imageRect, Qt::IgnoreAspectRatio);
|
|
|
|
|
|
|
|
QImageWriter writer;
|
|
|
|
writer.setFormat("TIF");
|
|
|
|
writer.setCompression(1); // LZW-compression
|
|
|
|
writer.setFileName(m_fileName);
|
|
|
|
|
|
|
|
if (not writer.write(image))
|
|
|
|
{ // failed to save file
|
|
|
|
qCritical() << qUtf8Printable(tr("Can't save file '%1'. Error: %2.").arg(m_fileName, writer.errorString()));
|
2023-04-10 11:20:18 +02:00
|
|
|
RestoreGrainlineAfterExport(details);
|
2021-01-23 17:47:41 +01:00
|
|
|
return;
|
|
|
|
}
|
2023-04-10 11:20:18 +02:00
|
|
|
|
|
|
|
RestoreGrainlineAfterExport(details);
|
2021-01-23 17:47:41 +01:00
|
|
|
}
|
|
|
|
|
2020-12-19 18:10:55 +01:00
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
2023-04-10 11:20:18 +02:00
|
|
|
void VLayoutExporter::ExportToPDF(QGraphicsScene *scene, const QList<QGraphicsItem *> &details) const
|
2020-12-19 18:10:55 +01:00
|
|
|
{
|
2023-04-10 11:20:18 +02:00
|
|
|
ExportToPDF(scene, details, m_fileName);
|
2020-12-19 18:10:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
|
|
void VLayoutExporter::ExportToOBJ(QGraphicsScene *scene) const
|
|
|
|
{
|
|
|
|
VObjPaintDevice generator;
|
|
|
|
generator.setFileName(m_fileName);
|
|
|
|
generator.setSize(m_imageRect.size().toSize());
|
|
|
|
generator.setResolution(static_cast<int>(PrintDPI));
|
|
|
|
|
|
|
|
QPainter painter;
|
|
|
|
painter.begin(&generator);
|
|
|
|
scene->render(&painter, m_imageRect, m_imageRect, Qt::IgnoreAspectRatio);
|
|
|
|
painter.end();
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
2023-04-10 11:20:18 +02:00
|
|
|
void VLayoutExporter::ExportToPS(QGraphicsScene *scene, const QList<QGraphicsItem *> &details) const
|
2020-12-19 18:10:55 +01:00
|
|
|
{
|
|
|
|
QTemporaryFile tmp;
|
|
|
|
if (tmp.open())
|
|
|
|
{
|
2021-09-06 14:31:19 +02:00
|
|
|
const QString fileName = m_fileName;
|
2023-04-10 11:20:18 +02:00
|
|
|
ExportToPDF(scene, details, tmp.fileName());
|
2021-09-06 14:31:19 +02:00
|
|
|
PdfToPs(QStringList{tmp.fileName(), fileName});
|
2020-12-19 18:10:55 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
2023-04-10 11:20:18 +02:00
|
|
|
void VLayoutExporter::ExportToEPS(QGraphicsScene *scene, const QList<QGraphicsItem *> &details) const
|
2020-12-19 18:10:55 +01:00
|
|
|
{
|
|
|
|
QTemporaryFile tmp;
|
|
|
|
if (tmp.open())
|
|
|
|
{
|
2021-09-06 14:31:19 +02:00
|
|
|
const QString fileName = m_fileName;
|
2023-04-10 11:20:18 +02:00
|
|
|
ExportToPDF(scene, details, tmp.fileName());
|
2021-09-06 14:31:19 +02:00
|
|
|
PdfToPs(QStringList{QStringLiteral("-eps"), tmp.fileName(), fileName});
|
2020-12-19 18:10:55 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
2021-09-06 14:31:19 +02:00
|
|
|
void VLayoutExporter::ExportToFlatDXF(QGraphicsScene *scene, const QList<QGraphicsItem *> &details) const
|
2020-12-19 18:10:55 +01:00
|
|
|
{
|
2023-04-10 11:20:18 +02:00
|
|
|
PrepareDetailsForDXF(endStringPlaceholder, details);
|
|
|
|
PrepareGrainlineForExport(details, m_showGrainline);
|
2020-12-19 18:10:55 +01:00
|
|
|
|
|
|
|
VDxfPaintDevice generator;
|
2022-10-07 15:04:07 +02:00
|
|
|
generator.SetFileName(m_fileName);
|
|
|
|
generator.SetSize(QSize(qFloor(m_imageRect.width() * m_xScale), qFloor(m_imageRect.height() * m_yScale)));
|
|
|
|
generator.SetResolution(PrintDPI);
|
2020-12-19 18:10:55 +01:00
|
|
|
generator.SetVersion(static_cast<DRW::Version>(m_dxfVersion));
|
|
|
|
generator.SetBinaryFormat(m_binaryDxfFormat);
|
2022-10-07 15:04:07 +02:00
|
|
|
generator.SetInsunits(VarInsunits::Millimeters);// Decided to always use mm. See issue #745
|
2020-12-19 18:10:55 +01:00
|
|
|
|
|
|
|
QPainter painter;
|
|
|
|
if (painter.begin(&generator))
|
|
|
|
{
|
|
|
|
painter.scale(m_xScale, m_yScale);
|
|
|
|
scene->render(&painter, m_imageRect, m_imageRect, Qt::IgnoreAspectRatio);
|
2021-04-28 19:06:24 +02:00
|
|
|
if (not painter.end())
|
|
|
|
{
|
2022-03-28 16:40:44 +02:00
|
|
|
qCritical() << tr("Can't create a flat dxf file.")
|
2021-04-28 19:06:24 +02:00
|
|
|
<< generator.ErrorString();
|
|
|
|
}
|
2020-12-19 18:10:55 +01:00
|
|
|
}
|
|
|
|
|
2023-04-10 11:20:18 +02:00
|
|
|
RestoreDetailsAfterDXF(endStringPlaceholder, details);
|
|
|
|
RestoreGrainlineAfterExport(details);
|
2020-12-19 18:10:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
|
|
void VLayoutExporter::ExportToAAMADXF(const QVector<VLayoutPiece> &details) const
|
|
|
|
{
|
|
|
|
VDxfPaintDevice generator;
|
2022-10-07 15:04:07 +02:00
|
|
|
generator.SetFileName(m_fileName);
|
|
|
|
generator.SetSize(QSize(qCeil(m_imageRect.width() * m_xScale), qCeil(m_imageRect.height() * m_yScale)));
|
|
|
|
generator.SetResolution(PrintDPI);
|
2020-12-19 18:10:55 +01:00
|
|
|
generator.SetVersion(static_cast<DRW::Version>(m_dxfVersion));
|
|
|
|
generator.SetBinaryFormat(m_binaryDxfFormat);
|
2022-10-07 15:04:07 +02:00
|
|
|
generator.SetInsunits(VarInsunits::Millimeters);// Decided to always use mm. See issue #745
|
2020-12-19 18:10:55 +01:00
|
|
|
generator.SetXScale(m_xScale);
|
|
|
|
generator.SetYScale(m_yScale);
|
2021-04-28 19:06:24 +02:00
|
|
|
if (not generator.ExportToAAMA(details))
|
|
|
|
{
|
|
|
|
qCritical() << tr("Can't create an AAMA dxf file.")
|
|
|
|
<< generator.ErrorString();
|
|
|
|
}
|
2020-12-19 18:10:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
|
|
void VLayoutExporter::ExportToASTMDXF(const QVector<VLayoutPiece> &details) const
|
|
|
|
{
|
|
|
|
VDxfPaintDevice generator;
|
2022-10-07 15:04:07 +02:00
|
|
|
generator.SetFileName(m_fileName);
|
|
|
|
generator.SetSize(QSize(qCeil(m_imageRect.width() * m_xScale), qCeil(m_imageRect.height() * m_yScale)));
|
|
|
|
generator.SetResolution(PrintDPI);
|
2020-12-19 18:10:55 +01:00
|
|
|
generator.SetVersion(static_cast<DRW::Version>(m_dxfVersion));
|
|
|
|
generator.SetBinaryFormat(m_binaryDxfFormat);
|
2022-10-07 15:04:07 +02:00
|
|
|
generator.SetInsunits(VarInsunits::Millimeters);// Decided to always use mm. See issue #745
|
2020-12-19 18:10:55 +01:00
|
|
|
generator.SetXScale(m_xScale);
|
|
|
|
generator.SetYScale(m_yScale);
|
2021-04-28 19:06:24 +02:00
|
|
|
if (not generator.ExportToASTM(details))
|
|
|
|
{
|
|
|
|
qCritical() << tr("Can't create an ASTM dxf file.")
|
|
|
|
<< generator.ErrorString();
|
|
|
|
}
|
2020-12-19 18:10:55 +01:00
|
|
|
}
|
|
|
|
|
2020-12-23 17:57:25 +01:00
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
|
|
void VLayoutExporter::ExportToRLD(const QVector<VLayoutPiece> &details) const
|
|
|
|
{
|
2021-09-08 11:57:12 +02:00
|
|
|
QVector<VLayoutPiece> scaledPieces;
|
|
|
|
scaledPieces.reserve(details.size());
|
|
|
|
|
2020-12-23 17:57:25 +01:00
|
|
|
for(auto detail : details)
|
|
|
|
{
|
|
|
|
detail.Scale(m_xScale, m_yScale);
|
2021-09-08 11:57:12 +02:00
|
|
|
scaledPieces.append(detail);
|
2020-12-23 17:57:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
VRawLayoutData layoutData;
|
2021-09-08 11:57:12 +02:00
|
|
|
layoutData.pieces = scaledPieces;
|
2020-12-23 17:57:25 +01:00
|
|
|
|
|
|
|
VRawLayout generator;
|
|
|
|
if (not generator.WriteFile(m_fileName, layoutData))
|
|
|
|
{
|
|
|
|
const QString errorMsg = tr("Export raw layout data failed. %1.").arg(generator.ErrorString());
|
2021-02-24 15:26:11 +01:00
|
|
|
VAbstractApplication::VApp()->IsPedantic() ? throw VException(errorMsg) : qCritical() << errorMsg;
|
2020-12-23 17:57:25 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-19 18:10:55 +01:00
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
|
|
auto VLayoutExporter::SupportPDFConversion() -> bool
|
|
|
|
{
|
|
|
|
bool res = false;
|
|
|
|
|
|
|
|
QProcess proc;
|
|
|
|
#if defined(Q_OS_WIN) || defined(Q_OS_OSX)
|
|
|
|
// Seek pdftops in app bundle or near valentina.exe
|
|
|
|
proc.start(qApp->applicationDirPath() + QLatin1String("/")+ *PDFTOPS, QStringList());
|
|
|
|
#else
|
|
|
|
proc.start(*PDFTOPS, QStringList()); // Seek pdftops in standard path
|
|
|
|
#endif
|
|
|
|
|
|
|
|
const int timeout = 15000;
|
|
|
|
if (proc.waitForStarted(timeout) && (proc.waitForFinished(timeout) || proc.state() == QProcess::NotRunning))
|
|
|
|
{
|
|
|
|
res = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
qDebug() << *PDFTOPS << "error" << proc.error() << proc.errorString();
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
2023-05-03 13:07:02 +02:00
|
|
|
auto VLayoutExporter::offset() const -> QPointF
|
2021-06-28 19:05:19 +02:00
|
|
|
{
|
|
|
|
return m_offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
2021-07-26 15:52:54 +02:00
|
|
|
void VLayoutExporter::SetOffset(const QPointF &newOffset)
|
2021-06-28 19:05:19 +02:00
|
|
|
{
|
|
|
|
m_offset = newOffset;
|
|
|
|
}
|
|
|
|
|
2020-12-19 18:10:55 +01:00
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
|
|
/**
|
|
|
|
* @brief PdfToPs use external tool "pdftops" for converting pdf too eps or ps format.
|
|
|
|
* @param params string with parameter for tool. Parameters have format: "-eps input_file out_file". Use -eps when
|
|
|
|
* need create eps file.
|
|
|
|
*/
|
|
|
|
void VLayoutExporter::PdfToPs(const QStringList ¶ms)
|
|
|
|
{
|
|
|
|
#ifndef QT_NO_CURSOR
|
|
|
|
QGuiApplication::setOverrideCursor(Qt::WaitCursor);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
QProcess proc;
|
|
|
|
#if defined(Q_OS_MAC)
|
|
|
|
// Fix issue #594. Broken export on Mac.
|
|
|
|
proc.setWorkingDirectory(qApp->applicationDirPath());
|
|
|
|
proc.start(QLatin1String("./") + *PDFTOPS, params);
|
|
|
|
#else
|
|
|
|
proc.start(*PDFTOPS, params);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
const int timeout = 15000;
|
|
|
|
if (proc.waitForStarted(timeout))
|
|
|
|
{
|
|
|
|
proc.waitForFinished(timeout);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef QT_NO_CURSOR
|
|
|
|
QGuiApplication::restoreOverrideCursor();
|
|
|
|
#endif
|
|
|
|
|
2022-01-29 09:59:02 +01:00
|
|
|
QFile f(ConstLast<QString>(params));
|
2020-12-19 18:10:55 +01:00
|
|
|
if (not f.exists())
|
|
|
|
{
|
2022-01-29 09:59:02 +01:00
|
|
|
qCritical() << qUtf8Printable(tr("Creating file '%1' failed! %2")
|
|
|
|
.arg(ConstLast<QString>(params), proc.errorString()));
|
2020-12-19 18:10:55 +01:00
|
|
|
}
|
|
|
|
}
|
2021-05-22 11:52:24 +02:00
|
|
|
|
2021-09-06 14:31:19 +02:00
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
2023-04-10 11:20:18 +02:00
|
|
|
void VLayoutExporter::ExportToPDF(QGraphicsScene *scene, const QList<QGraphicsItem *> &details,
|
|
|
|
const QString &filename) const
|
2021-09-06 14:31:19 +02:00
|
|
|
{
|
2023-04-10 11:20:18 +02:00
|
|
|
PrepareGrainlineForExport(details, m_showGrainline);
|
|
|
|
|
2021-09-06 14:31:19 +02:00
|
|
|
QPrinter printer;
|
|
|
|
printer.setCreator(QGuiApplication::applicationDisplayName() + QChar(QChar::Space) +
|
|
|
|
QCoreApplication::applicationVersion());
|
|
|
|
printer.setOutputFormat(QPrinter::PdfFormat);
|
|
|
|
printer.setOutputFileName(filename);
|
|
|
|
printer.setDocName(QFileInfo(filename).fileName());
|
|
|
|
printer.setResolution(static_cast<int>(PrintDPI));
|
|
|
|
printer.setFullPage(m_ignorePrinterMargins);
|
|
|
|
|
2021-09-07 11:31:52 +02:00
|
|
|
QPageLayout::Orientation imageOrientation = m_imageRect.height() >= m_imageRect.width() ? QPageLayout::Portrait
|
|
|
|
: QPageLayout::Landscape;
|
|
|
|
|
2021-09-06 14:31:19 +02:00
|
|
|
qreal width = FromPixel(m_imageRect.width() * m_xScale + m_margins.left() + m_margins.right(), Unit::Mm);
|
|
|
|
qreal height = FromPixel(m_imageRect.height() * m_yScale + m_margins.top() + m_margins.bottom(), Unit::Mm);
|
|
|
|
|
2021-09-07 11:31:52 +02:00
|
|
|
QSizeF pageSize = imageOrientation == QPageLayout::Portrait ? QSizeF(width, height) : QSizeF(height, width);
|
|
|
|
if (not printer.setPageSize(QPageSize(pageSize, QPageSize::Millimeter)))
|
2021-09-06 14:31:19 +02:00
|
|
|
{
|
|
|
|
qWarning() << tr("Cannot set printer page size");
|
|
|
|
}
|
|
|
|
|
2021-09-07 11:31:52 +02:00
|
|
|
printer.setPageOrientation(imageOrientation);
|
|
|
|
|
2021-09-06 14:31:19 +02:00
|
|
|
if (not m_ignorePrinterMargins)
|
|
|
|
{
|
|
|
|
const qreal left = FromPixel(m_margins.left(), Unit::Mm);
|
|
|
|
const qreal top = FromPixel(m_margins.top(), Unit::Mm);
|
|
|
|
const qreal right = FromPixel(m_margins.right(), Unit::Mm);
|
|
|
|
const qreal bottom = FromPixel(m_margins.bottom(), Unit::Mm);
|
|
|
|
|
|
|
|
if (not printer.setPageMargins(QMarginsF(left, top, right, bottom), QPageLayout::Millimeter))
|
|
|
|
{
|
|
|
|
qWarning() << tr("Cannot set printer margins");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
QPainter painter;
|
|
|
|
if (not painter.begin(&printer))
|
|
|
|
{ // failed to open file
|
|
|
|
qCritical() << qUtf8Printable(tr("Can't open file '%1'").arg(m_fileName));
|
2023-04-10 11:20:18 +02:00
|
|
|
RestoreGrainlineAfterExport(details);
|
2021-09-06 14:31:19 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
painter.setRenderHint(QPainter::Antialiasing, true);
|
|
|
|
painter.setPen(m_pen);
|
|
|
|
painter.setBrush(QBrush(Qt::NoBrush));
|
|
|
|
painter.scale(m_xScale, m_yScale);
|
|
|
|
scene->render(&painter, VPrintLayout::SceneTargetRect(&printer, m_imageRect), m_imageRect, Qt::IgnoreAspectRatio);
|
|
|
|
painter.end();
|
2023-04-10 11:20:18 +02:00
|
|
|
|
|
|
|
RestoreGrainlineAfterExport(details);
|
2021-09-06 14:31:19 +02:00
|
|
|
}
|
2021-05-22 11:52:24 +02:00
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
2023-05-03 13:07:02 +02:00
|
|
|
auto VLayoutExporter::ExportFormatDescription(LayoutExportFormats format) -> QString
|
2021-05-22 11:52:24 +02:00
|
|
|
{
|
|
|
|
const QString dxfSuffix = QStringLiteral("(*.dxf)");
|
|
|
|
const QString dxfFlatFilesStr = tr("(flat) files");
|
|
|
|
const QString filesStr = tr("files");
|
|
|
|
|
|
|
|
switch(format)
|
|
|
|
{
|
|
|
|
case LayoutExportFormats::SVG:
|
|
|
|
return QStringLiteral("Svg %1 (*.svg)").arg(filesStr);
|
|
|
|
case LayoutExportFormats::PDF:
|
|
|
|
return QStringLiteral("PDF %1 (*.pdf)").arg(filesStr);
|
|
|
|
case LayoutExportFormats::PNG:
|
|
|
|
return tr("Image files") + QStringLiteral(" (*.png)");
|
|
|
|
case LayoutExportFormats::OBJ:
|
|
|
|
return QStringLiteral("Wavefront OBJ (*.obj)");
|
|
|
|
case LayoutExportFormats::PS:
|
|
|
|
return QStringLiteral("PS %1 (*.ps)").arg(filesStr);
|
|
|
|
case LayoutExportFormats::EPS:
|
|
|
|
return QStringLiteral("EPS %1 (*.eps)").arg(filesStr);
|
|
|
|
case LayoutExportFormats::DXF_AC1006_Flat:
|
|
|
|
return QStringLiteral("AutoCAD DXF R10 %1 %2").arg(dxfFlatFilesStr, dxfSuffix);
|
|
|
|
case LayoutExportFormats::DXF_AC1009_Flat:
|
|
|
|
return QStringLiteral("AutoCAD DXF R11/12 %1 %2").arg(dxfFlatFilesStr, dxfSuffix);
|
|
|
|
case LayoutExportFormats::DXF_AC1012_Flat:
|
|
|
|
return QStringLiteral("AutoCAD DXF R13 %1 %2").arg(dxfFlatFilesStr, dxfSuffix);
|
|
|
|
case LayoutExportFormats::DXF_AC1014_Flat:
|
|
|
|
return QStringLiteral("AutoCAD DXF R14 %1 %2").arg(dxfFlatFilesStr, dxfSuffix);
|
|
|
|
case LayoutExportFormats::DXF_AC1015_Flat:
|
|
|
|
return QStringLiteral("AutoCAD DXF 2000 %1 %2").arg(dxfFlatFilesStr, dxfSuffix);
|
|
|
|
case LayoutExportFormats::DXF_AC1018_Flat:
|
|
|
|
return QStringLiteral("AutoCAD DXF 2004 %1 %2").arg(dxfFlatFilesStr, dxfSuffix);
|
|
|
|
case LayoutExportFormats::DXF_AC1021_Flat:
|
|
|
|
return QStringLiteral("AutoCAD DXF 2007 %1 %2").arg(dxfFlatFilesStr, dxfSuffix);
|
|
|
|
case LayoutExportFormats::DXF_AC1024_Flat:
|
|
|
|
return QStringLiteral("AutoCAD DXF 2010 %1 %2").arg(dxfFlatFilesStr, dxfSuffix);
|
|
|
|
case LayoutExportFormats::DXF_AC1027_Flat:
|
|
|
|
return QStringLiteral("AutoCAD DXF 2013 %1 %2").arg(dxfFlatFilesStr, dxfSuffix);
|
2023-05-03 15:23:54 +02:00
|
|
|
case LayoutExportFormats::DXF_AAMA:
|
|
|
|
return QStringLiteral("AutoCAD DXF AAMA %1 %2").arg(filesStr, dxfSuffix);
|
|
|
|
case LayoutExportFormats::DXF_ASTM:
|
|
|
|
return QStringLiteral("AutoCAD DXF ASTM %1 %2").arg(filesStr, dxfSuffix);
|
2021-05-22 11:52:24 +02:00
|
|
|
case LayoutExportFormats::PDFTiled:
|
|
|
|
return QStringLiteral("PDF %1 %2 (*.pdf)").arg(tr("tiled"), filesStr);
|
|
|
|
case LayoutExportFormats::NC:
|
|
|
|
return QStringLiteral("%1 %2 (*.nc)").arg(tr("Numerical control"), filesStr);
|
|
|
|
case LayoutExportFormats::RLD:
|
|
|
|
return QStringLiteral("%1 %2 (*.rld)").arg(tr("Raw Layout Data"), filesStr);
|
|
|
|
case LayoutExportFormats::TIF:
|
|
|
|
return QStringLiteral("TIFF %1 (*.tif)").arg(filesStr);
|
|
|
|
default:
|
2023-05-03 15:23:54 +02:00
|
|
|
return {};
|
2021-05-22 11:52:24 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
2023-05-03 13:07:02 +02:00
|
|
|
auto VLayoutExporter::ExportFormatSuffix(LayoutExportFormats format) -> QString
|
2021-05-22 11:52:24 +02:00
|
|
|
{
|
|
|
|
switch(format)
|
|
|
|
{
|
|
|
|
case LayoutExportFormats::SVG:
|
|
|
|
return QStringLiteral(".svg");
|
|
|
|
case LayoutExportFormats::PDF:
|
|
|
|
case LayoutExportFormats::PDFTiled:
|
|
|
|
return QStringLiteral(".pdf");
|
|
|
|
case LayoutExportFormats::PNG:
|
|
|
|
return QStringLiteral(".png");
|
|
|
|
case LayoutExportFormats::OBJ:
|
|
|
|
return QStringLiteral(".obj");
|
|
|
|
case LayoutExportFormats::PS:
|
|
|
|
return QStringLiteral(".ps");
|
|
|
|
case LayoutExportFormats::EPS:
|
|
|
|
return QStringLiteral(".eps");
|
|
|
|
case LayoutExportFormats::DXF_AC1006_Flat:
|
|
|
|
case LayoutExportFormats::DXF_AC1009_Flat:
|
|
|
|
case LayoutExportFormats::DXF_AC1012_Flat:
|
|
|
|
case LayoutExportFormats::DXF_AC1014_Flat:
|
|
|
|
case LayoutExportFormats::DXF_AC1015_Flat:
|
|
|
|
case LayoutExportFormats::DXF_AC1018_Flat:
|
|
|
|
case LayoutExportFormats::DXF_AC1021_Flat:
|
|
|
|
case LayoutExportFormats::DXF_AC1024_Flat:
|
|
|
|
case LayoutExportFormats::DXF_AC1027_Flat:
|
2023-05-03 15:23:54 +02:00
|
|
|
case LayoutExportFormats::DXF_AAMA:
|
|
|
|
case LayoutExportFormats::DXF_ASTM:
|
2021-05-22 11:52:24 +02:00
|
|
|
return QStringLiteral(".dxf");
|
|
|
|
case LayoutExportFormats::NC:
|
|
|
|
return QStringLiteral(".nc");
|
|
|
|
case LayoutExportFormats::RLD:
|
|
|
|
return QStringLiteral(".rld");
|
|
|
|
case LayoutExportFormats::TIF:
|
|
|
|
return QStringLiteral(".tif");
|
|
|
|
default:
|
2023-05-03 15:23:54 +02:00
|
|
|
return {};
|
2021-05-22 11:52:24 +02:00
|
|
|
}
|
|
|
|
}
|
2023-04-10 11:20:18 +02:00
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
|
|
void VLayoutExporter::PrepareGrainlineForExport(const QList<QGraphicsItem *> &items, bool showGrainline)
|
|
|
|
{
|
|
|
|
for (auto *item : items)
|
|
|
|
{
|
|
|
|
QList<QGraphicsItem *> pieceChildren = item->childItems();
|
|
|
|
for (auto *child : qAsConst(pieceChildren))
|
|
|
|
{
|
|
|
|
if (child->type() == VGraphicsFillItem::Type)
|
|
|
|
{
|
|
|
|
child->setVisible(showGrainline);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
|
|
void VLayoutExporter::RestoreGrainlineAfterExport(const QList<QGraphicsItem *> &items)
|
|
|
|
{
|
|
|
|
for (auto *item : items)
|
|
|
|
{
|
|
|
|
QList<QGraphicsItem *> pieceChildren = item->childItems();
|
|
|
|
for (auto *child : qAsConst(pieceChildren))
|
|
|
|
{
|
|
|
|
if (child->type() == VGraphicsFillItem::Type)
|
|
|
|
{
|
|
|
|
child->setVisible(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|