From d5a02ac48caad798e44ff03b50c57c74fa5ea8ce Mon Sep 17 00:00:00 2001 From: Roman Telezhynskyi Date: Mon, 6 Sep 2021 15:31:19 +0300 Subject: [PATCH] Export layout. --- .../puzzle/dialogs/dialogsavemanuallayout.cpp | 713 +++++++++++++ .../puzzle/dialogs/dialogsavemanuallayout.h | 101 ++ .../puzzle/dialogs/dialogsavemanuallayout.ui | 408 ++++++++ src/app/puzzle/layout/vplayout.cpp | 32 +- src/app/puzzle/layout/vplayout.h | 10 +- src/app/puzzle/layout/vplayoutsettings.cpp | 6 + src/app/puzzle/layout/vplayoutsettings.h | 2 + src/app/puzzle/layout/vpsheet.cpp | 242 ++++- src/app/puzzle/layout/vpsheet.h | 79 ++ src/app/puzzle/puzzle.pri | 11 +- src/app/puzzle/puzzle.pro | 20 +- src/app/puzzle/scene/vpgraphicstilegrid.cpp | 48 +- src/app/puzzle/scene/vpgraphicstilegrid.h | 8 +- src/app/puzzle/scene/vpmaingraphicsview.cpp | 339 +++---- src/app/puzzle/scene/vpmaingraphicsview.h | 53 +- src/app/puzzle/vpexporter.cpp | 143 --- src/app/puzzle/vpexporter.h | 32 - src/app/puzzle/vpmainwindow.cpp | 949 +++++++++++++++--- src/app/puzzle/vpmainwindow.h | 45 +- src/app/puzzle/vpmainwindow.ui | 172 +++- src/app/puzzle/vpsettings.cpp | 13 + src/app/puzzle/vpsettings.h | 3 + src/app/puzzle/vptilefactory.cpp | 132 +-- src/app/puzzle/vptilefactory.h | 34 +- .../valentina/dialogs/dialogsavelayout.cpp | 3 +- src/app/valentina/mainwindowsnogui.cpp | 18 +- src/libs/vlayout/vlayoutexporter.cpp | 139 +-- src/libs/vlayout/vlayoutexporter.h | 5 +- src/libs/vlayout/vprintlayout.cpp | 59 +- src/libs/vlayout/vprintlayout.h | 1 + src/libs/vwidgets/vmaingraphicsview.cpp | 2 +- 31 files changed, 2999 insertions(+), 823 deletions(-) create mode 100644 src/app/puzzle/dialogs/dialogsavemanuallayout.cpp create mode 100644 src/app/puzzle/dialogs/dialogsavemanuallayout.h create mode 100644 src/app/puzzle/dialogs/dialogsavemanuallayout.ui delete mode 100644 src/app/puzzle/vpexporter.cpp delete mode 100644 src/app/puzzle/vpexporter.h diff --git a/src/app/puzzle/dialogs/dialogsavemanuallayout.cpp b/src/app/puzzle/dialogs/dialogsavemanuallayout.cpp new file mode 100644 index 000000000..53396e896 --- /dev/null +++ b/src/app/puzzle/dialogs/dialogsavemanuallayout.cpp @@ -0,0 +1,713 @@ +/************************************************************************ + ** + ** @file dialogsavemanuallayout.cpp + ** @author Roman Telezhynskyi + ** @date 3 9, 2021 + ** + ** @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) 2021 Valentina project + ** All Rights Reserved. + ** + ** Valentina is free software: you can redistribute it and/or modify + ** it under the terms of the GNU General Public License as published by + ** the Free Software Foundation, either version 3 of the License, or + ** (at your option) any later version. + ** + ** Valentina is distributed in the hope that it will be useful, + ** but WITHOUT ANY WARRANTY; without even the implied warranty of + ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ** GNU General Public License for more details. + ** + ** You should have received a copy of the GNU General Public License + ** along with Valentina. If not, see . + ** + *************************************************************************/ +#include "dialogsavemanuallayout.h" +#include "ui_dialogsavemanuallayout.h" +#include "../vpapplication.h" +#include "../ifc/exception/vexception.h" +#include "../vlayout/vlayoutexporter.h" + +#include +#include +#include + +#ifndef Q_OS_WIN + Q_GLOBAL_STATIC_WITH_ARGS(const QString, baseFilenameRegExp, (QLatin1String("^[^\\/]+$"))) +#else + Q_GLOBAL_STATIC_WITH_ARGS(const QString, baseFilenameRegExp, (QLatin1String("^[^\\:?\"*|\\/<>]+$"))) +#endif + +bool DialogSaveManualLayout::havePdf = false; +bool DialogSaveManualLayout::tested = false; + +//--------------------------------------------------------------------------------------------------------------------- +DialogSaveManualLayout::DialogSaveManualLayout(int count, bool consoleExport, const QString &fileName, QWidget *parent) + : VAbstractLayoutDialog(parent), + ui(new Ui::DialogSaveManualLayout), + m_count(count), + m_consoleExport(consoleExport) +{ + ui->setupUi(this); + +#if defined(Q_OS_MAC) + setWindowFlags(Qt::Window); +#endif + + VPApplication::VApp()->PuzzleSettings()->GetOsSeparator() ? setLocale(QLocale()) : setLocale(QLocale::c()); + + QPushButton *bOk = ui->buttonBox->button(QDialogButtonBox::Ok); + SCASSERT(bOk != nullptr) + bOk->setEnabled(false); + + ui->lineEditFileName->setValidator( new QRegularExpressionValidator(QRegularExpression(*baseFilenameRegExp), this)); + + const QString mask = m_count > 1 ? fileName + '_' : fileName; + if (not m_consoleExport) + { + ui->lineEditFileName->setText(mask); + } + else + { + if (QRegularExpression(*baseFilenameRegExp).match(mask).hasMatch()) + { + ui->lineEditFileName->setText(mask); + } + else + { + throw VException(tr("The base filename does not match a regular expression.")); + } + } + + for (auto &v : InitFormats()) + { + ui->comboBoxFormat->addItem(v.first, QVariant(static_cast(v.second))); + } +#ifdef V_NO_ASSERT // Temporarily unavailable + RemoveFormatFromList(LayoutExportFormats::OBJ); +#endif + +// RemoveFormatFromList(LayoutExportFormats::NC); // No support for now + + connect(bOk, &QPushButton::clicked, this, &DialogSaveManualLayout::Save); + connect(ui->lineEditFileName, &QLineEdit::textChanged, this, &DialogSaveManualLayout::ShowExample); + connect(ui->comboBoxFormat, QOverload::of(&QComboBox::currentIndexChanged), + this, &DialogSaveManualLayout::ShowExample); + + connect(ui->pushButtonBrowse, &QPushButton::clicked, this, [this]() + { + const QString dirPath = VPApplication::VApp()->PuzzleSettings()->GetPathManualLayouts(); + bool usedNotExistedDir = false; + QDir directory(dirPath); + if (not directory.exists()) + { + usedNotExistedDir = directory.mkpath(QChar('.')); + } + + const QString dir = QFileDialog::getExistingDirectory( + this, tr("Select folder"), dirPath, + VAbstractApplication::VApp()->NativeFileDialog(QFileDialog::ShowDirsOnly | + QFileDialog::DontResolveSymlinks)); + if (not dir.isEmpty()) + {// If paths equal the signal will not be called, we will do this manually + dir == ui->lineEditPath->text() ? PathChanged(dir) : ui->lineEditPath->setText(dir); + } + + if (usedNotExistedDir) + { + QDir directory(dirPath); + directory.rmpath(QChar('.')); + } + }); + connect(ui->lineEditPath, &QLineEdit::textChanged, this, &DialogSaveManualLayout::PathChanged); + + ui->lineEditPath->setText(VPApplication::VApp()->PuzzleSettings()->GetPathManualLayouts()); + + connect(ui->toolButtonScaleConnected, &QToolButton::clicked, this, &DialogSaveManualLayout::ToggleScaleConnection); + + connect(ui->doubleSpinBoxHorizontalScale, QOverload::of(&QDoubleSpinBox::valueChanged), + this, &DialogSaveManualLayout::HorizontalScaleChanged); + connect(ui->doubleSpinBoxVerticalScale, QOverload::of(&QDoubleSpinBox::valueChanged), + this, &DialogSaveManualLayout::VerticalScaleChanged); + + ReadSettings(); + + ShowExample();//Show example for current format. +} + +//--------------------------------------------------------------------------------------------------------------------- +DialogSaveManualLayout::~DialogSaveManualLayout() +{ + delete ui; +} + +//--------------------------------------------------------------------------------------------------------------------- +QString DialogSaveManualLayout::Path() const +{ + return ui->lineEditPath->text(); +} + +//--------------------------------------------------------------------------------------------------------------------- +QString DialogSaveManualLayout::FileName() const +{ + return ui->lineEditFileName->text(); +} + +//--------------------------------------------------------------------------------------------------------------------- +LayoutExportFormats DialogSaveManualLayout::Format() const +{ + return static_cast(ui->comboBoxFormat->currentData().toInt()); +} + +//--------------------------------------------------------------------------------------------------------------------- +void DialogSaveManualLayout::SelectFormat(LayoutExportFormats format) +{ + if (static_cast(format) < 0 || format >= LayoutExportFormats::COUNT) + { + throw VException(tr("Tried to use out of range format number.")); + } + + const int i = ui->comboBoxFormat->findData(static_cast(format)); + if (i < 0) + { + throw VException(tr("Selected not present format.")); + } + ui->comboBoxFormat->setCurrentIndex(i); +} + +//--------------------------------------------------------------------------------------------------------------------- +void DialogSaveManualLayout::SetBinaryDXFFormat(bool binary) +{ + switch(Format()) + { + 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: + case LayoutExportFormats::DXF_AC1006_AAMA: + case LayoutExportFormats::DXF_AC1009_AAMA: + case LayoutExportFormats::DXF_AC1012_AAMA: + case LayoutExportFormats::DXF_AC1014_AAMA: + case LayoutExportFormats::DXF_AC1015_AAMA: + case LayoutExportFormats::DXF_AC1018_AAMA: + case LayoutExportFormats::DXF_AC1021_AAMA: + case LayoutExportFormats::DXF_AC1024_AAMA: + case LayoutExportFormats::DXF_AC1027_AAMA: + case LayoutExportFormats::DXF_AC1006_ASTM: + case LayoutExportFormats::DXF_AC1009_ASTM: + case LayoutExportFormats::DXF_AC1012_ASTM: + case LayoutExportFormats::DXF_AC1014_ASTM: + case LayoutExportFormats::DXF_AC1015_ASTM: + case LayoutExportFormats::DXF_AC1018_ASTM: + case LayoutExportFormats::DXF_AC1021_ASTM: + case LayoutExportFormats::DXF_AC1024_ASTM: + case LayoutExportFormats::DXF_AC1027_ASTM: + ui->checkBoxBinaryDXF->setChecked(binary); + break; + case LayoutExportFormats::SVG: + case LayoutExportFormats::PDF: + case LayoutExportFormats::PDFTiled: + case LayoutExportFormats::PNG: + case LayoutExportFormats::OBJ: + case LayoutExportFormats::PS: + case LayoutExportFormats::EPS: + case LayoutExportFormats::NC: + case LayoutExportFormats::RLD: + case LayoutExportFormats::TIF: + default: + ui->checkBoxBinaryDXF->setChecked(false); + break; + } +} + +//--------------------------------------------------------------------------------------------------------------------- +bool DialogSaveManualLayout::IsBinaryDXFFormat() const +{ + switch(Format()) + { + 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: + case LayoutExportFormats::DXF_AC1006_AAMA: + case LayoutExportFormats::DXF_AC1009_AAMA: + case LayoutExportFormats::DXF_AC1012_AAMA: + case LayoutExportFormats::DXF_AC1014_AAMA: + case LayoutExportFormats::DXF_AC1015_AAMA: + case LayoutExportFormats::DXF_AC1018_AAMA: + case LayoutExportFormats::DXF_AC1021_AAMA: + case LayoutExportFormats::DXF_AC1024_AAMA: + case LayoutExportFormats::DXF_AC1027_AAMA: + case LayoutExportFormats::DXF_AC1006_ASTM: + case LayoutExportFormats::DXF_AC1009_ASTM: + case LayoutExportFormats::DXF_AC1012_ASTM: + case LayoutExportFormats::DXF_AC1014_ASTM: + case LayoutExportFormats::DXF_AC1015_ASTM: + case LayoutExportFormats::DXF_AC1018_ASTM: + case LayoutExportFormats::DXF_AC1021_ASTM: + case LayoutExportFormats::DXF_AC1024_ASTM: + case LayoutExportFormats::DXF_AC1027_ASTM: + return ui->checkBoxBinaryDXF->isChecked(); + case LayoutExportFormats::SVG: + case LayoutExportFormats::PDF: + case LayoutExportFormats::PDFTiled: + case LayoutExportFormats::PNG: + case LayoutExportFormats::OBJ: + case LayoutExportFormats::PS: + case LayoutExportFormats::EPS: + case LayoutExportFormats::NC: + case LayoutExportFormats::RLD: + case LayoutExportFormats::TIF: + default: + return false; + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void DialogSaveManualLayout::SetDestinationPath(const QString &cmdDestinationPath) +{ + QString path; + if (cmdDestinationPath.isEmpty()) + { + path = QDir::currentPath(); + } + else if (QDir(cmdDestinationPath).isAbsolute()) + { + path = cmdDestinationPath; + } + else + { + QDir dir; + if (not dir.cd(cmdDestinationPath)) + { + throw VException(tr("The destination directory doesn't exists or is not readable.")); + } + path = dir.absolutePath(); + } + + qDebug() << "Output full path: " << path << "\n"; + ui->lineEditPath->setText(path); +} + +//--------------------------------------------------------------------------------------------------------------------- +bool DialogSaveManualLayout::IsTextAsPaths() const +{ + return ui->checkBoxTextAsPaths->isChecked(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void DialogSaveManualLayout::SetTextAsPaths(bool textAsPaths) +{ + ui->checkBoxTextAsPaths->setChecked(textAsPaths); +} + +//--------------------------------------------------------------------------------------------------------------------- +void DialogSaveManualLayout::SetXScale(qreal scale) +{ + ui->doubleSpinBoxHorizontalScale->setValue(scale * 100.); +} + +//--------------------------------------------------------------------------------------------------------------------- +qreal DialogSaveManualLayout::GetXScale() const +{ + return ui->doubleSpinBoxHorizontalScale->value() / 100.; +} + +//--------------------------------------------------------------------------------------------------------------------- +void DialogSaveManualLayout::SetYScale(qreal scale) +{ + ui->doubleSpinBoxVerticalScale->setValue(scale * 100.); +} + +//--------------------------------------------------------------------------------------------------------------------- +qreal DialogSaveManualLayout::GetYScale() const +{ + return ui->doubleSpinBoxVerticalScale->value() / 100.; +} + +//--------------------------------------------------------------------------------------------------------------------- +void DialogSaveManualLayout::SetExportUnified(bool value) +{ + switch(Format()) + { + case LayoutExportFormats::PDF: + case LayoutExportFormats::PDFTiled: + case LayoutExportFormats::PS: + case LayoutExportFormats::EPS: + ui->checkBoxExportUnified->setChecked(value); + break; + 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: + case LayoutExportFormats::DXF_AC1006_AAMA: + case LayoutExportFormats::DXF_AC1009_AAMA: + case LayoutExportFormats::DXF_AC1012_AAMA: + case LayoutExportFormats::DXF_AC1014_AAMA: + case LayoutExportFormats::DXF_AC1015_AAMA: + case LayoutExportFormats::DXF_AC1018_AAMA: + case LayoutExportFormats::DXF_AC1021_AAMA: + case LayoutExportFormats::DXF_AC1024_AAMA: + case LayoutExportFormats::DXF_AC1027_AAMA: + case LayoutExportFormats::DXF_AC1006_ASTM: + case LayoutExportFormats::DXF_AC1009_ASTM: + case LayoutExportFormats::DXF_AC1012_ASTM: + case LayoutExportFormats::DXF_AC1014_ASTM: + case LayoutExportFormats::DXF_AC1015_ASTM: + case LayoutExportFormats::DXF_AC1018_ASTM: + case LayoutExportFormats::DXF_AC1021_ASTM: + case LayoutExportFormats::DXF_AC1024_ASTM: + case LayoutExportFormats::DXF_AC1027_ASTM: + case LayoutExportFormats::SVG: + case LayoutExportFormats::PNG: + case LayoutExportFormats::OBJ: + case LayoutExportFormats::NC: + case LayoutExportFormats::RLD: + case LayoutExportFormats::TIF: + default: + ui->checkBoxExportUnified->setChecked(false); + break; + } + +} + +//--------------------------------------------------------------------------------------------------------------------- +bool DialogSaveManualLayout::IsExportUnified() const +{ + switch(Format()) + { + case LayoutExportFormats::PDF: + case LayoutExportFormats::PDFTiled: + case LayoutExportFormats::PS: + case LayoutExportFormats::EPS: + return ui->checkBoxExportUnified->isChecked(); + 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: + case LayoutExportFormats::DXF_AC1006_AAMA: + case LayoutExportFormats::DXF_AC1009_AAMA: + case LayoutExportFormats::DXF_AC1012_AAMA: + case LayoutExportFormats::DXF_AC1014_AAMA: + case LayoutExportFormats::DXF_AC1015_AAMA: + case LayoutExportFormats::DXF_AC1018_AAMA: + case LayoutExportFormats::DXF_AC1021_AAMA: + case LayoutExportFormats::DXF_AC1024_AAMA: + case LayoutExportFormats::DXF_AC1027_AAMA: + case LayoutExportFormats::DXF_AC1006_ASTM: + case LayoutExportFormats::DXF_AC1009_ASTM: + case LayoutExportFormats::DXF_AC1012_ASTM: + case LayoutExportFormats::DXF_AC1014_ASTM: + case LayoutExportFormats::DXF_AC1015_ASTM: + case LayoutExportFormats::DXF_AC1018_ASTM: + case LayoutExportFormats::DXF_AC1021_ASTM: + case LayoutExportFormats::DXF_AC1024_ASTM: + case LayoutExportFormats::DXF_AC1027_ASTM: + case LayoutExportFormats::SVG: + case LayoutExportFormats::PNG: + case LayoutExportFormats::OBJ: + case LayoutExportFormats::NC: + case LayoutExportFormats::RLD: + case LayoutExportFormats::TIF: + default: + return false; + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void DialogSaveManualLayout::showEvent(QShowEvent *event) +{ + QDialog::showEvent( event ); + if ( event->spontaneous() ) + { + return; + } + + if (m_isInitialized) + { + return; + } + // do your init stuff here + + setFixedHeight(size().height()); + + m_isInitialized = true;//first show windows are held +} + +//--------------------------------------------------------------------------------------------------------------------- +void DialogSaveManualLayout::Save() +{ + WriteSettings(); + + for (int i=0; i < m_count; ++i) + { + QString name; + if (m_count > 1 && not IsExportUnified()) + { + name = Path() + '/' + FileName() + QString::number(i+1) + VLayoutExporter::ExportFormatSuffix(Format()); + } + else + { + name = Path() + '/' + FileName() + VLayoutExporter::ExportFormatSuffix(Format()); + } + + if (QFile::exists(name)) + { + QMessageBox::StandardButton res = QMessageBox::question(this, tr("Name conflict"), + tr("Folder already contain file with name %1. Rewrite all conflict file names?") + .arg(name), QMessageBox::Yes|QMessageBox::No, QMessageBox::Yes); + if (res == QMessageBox::No) + { + reject(); + return; + } + + break; + } + } + accept(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void DialogSaveManualLayout::PathChanged(const QString &text) +{ + QPushButton *bOk = ui->buttonBox->button(QDialogButtonBox::Ok); + SCASSERT(bOk != nullptr) + + QPalette palette = ui->lineEditPath->palette(); + + QDir dir(text); + dir.setPath(text); + if (not text.isEmpty() && dir.exists(text)) + { + bOk->setEnabled(true); + palette.setColor(ui->lineEditPath->foregroundRole(), Qt::black); + } + else + { + bOk->setEnabled(false); + palette.setColor(ui->lineEditPath->foregroundRole(), Qt::red); + } + + ui->lineEditPath->setPalette(palette); +} + +//--------------------------------------------------------------------------------------------------------------------- +void DialogSaveManualLayout::ShowExample() +{ + const LayoutExportFormats currentFormat = Format(); + + QString example; + if (m_count > 1) + { + example = tr("Example:") + FileName() + QLatin1Char('1') + VLayoutExporter::ExportFormatSuffix(currentFormat); + } + else + { + example = tr("Example:") + FileName() + VLayoutExporter::ExportFormatSuffix(currentFormat); + } + ui->labelExample->setText(example); + + ui->checkBoxBinaryDXF->setEnabled(false); + ui->checkBoxTextAsPaths->setEnabled(true); + ui->checkBoxExportUnified->setEnabled(false); + + switch(currentFormat) + { + 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: + case LayoutExportFormats::DXF_AC1006_AAMA: + case LayoutExportFormats::DXF_AC1009_AAMA: + case LayoutExportFormats::DXF_AC1012_AAMA: + case LayoutExportFormats::DXF_AC1014_AAMA: + case LayoutExportFormats::DXF_AC1015_AAMA: + case LayoutExportFormats::DXF_AC1018_AAMA: + case LayoutExportFormats::DXF_AC1021_AAMA: + case LayoutExportFormats::DXF_AC1024_AAMA: + case LayoutExportFormats::DXF_AC1027_AAMA: + case LayoutExportFormats::DXF_AC1006_ASTM: + case LayoutExportFormats::DXF_AC1009_ASTM: + case LayoutExportFormats::DXF_AC1012_ASTM: + case LayoutExportFormats::DXF_AC1014_ASTM: + case LayoutExportFormats::DXF_AC1015_ASTM: + case LayoutExportFormats::DXF_AC1018_ASTM: + case LayoutExportFormats::DXF_AC1021_ASTM: + case LayoutExportFormats::DXF_AC1024_ASTM: + case LayoutExportFormats::DXF_AC1027_ASTM: + ui->checkBoxBinaryDXF->setEnabled(true); + break; + case LayoutExportFormats::RLD: + ui->checkBoxTextAsPaths->setEnabled(false); + break; + case LayoutExportFormats::PDFTiled: + case LayoutExportFormats::PDF: + case LayoutExportFormats::PS: + case LayoutExportFormats::EPS: + ui->checkBoxExportUnified->setEnabled(true); + break; + case LayoutExportFormats::SVG: + case LayoutExportFormats::PNG: + case LayoutExportFormats::OBJ: + case LayoutExportFormats::NC: + case LayoutExportFormats::TIF: + default: + break; + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void DialogSaveManualLayout::ToggleScaleConnection() +{ + m_scaleConnected = not m_scaleConnected; + + QIcon icon; + icon.addFile(m_scaleConnected ? QStringLiteral(":/icon/32x32/link.png") + : QStringLiteral(":/icon/32x32/broken_link.png")); + ui->toolButtonScaleConnected->setIcon(icon); +} + +//--------------------------------------------------------------------------------------------------------------------- +void DialogSaveManualLayout::HorizontalScaleChanged(double d) +{ + if (m_scaleConnected) + { + ui->doubleSpinBoxVerticalScale->blockSignals(true); + ui->doubleSpinBoxVerticalScale->setValue(d); + ui->doubleSpinBoxVerticalScale->blockSignals(false); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void DialogSaveManualLayout::VerticalScaleChanged(double d) +{ + if (m_scaleConnected) + { + ui->doubleSpinBoxHorizontalScale->blockSignals(true); + ui->doubleSpinBoxHorizontalScale->setValue(d); + ui->doubleSpinBoxHorizontalScale->blockSignals(false); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +bool DialogSaveManualLayout::SupportPSTest() +{ + if (!tested) + { + havePdf = VLayoutExporter::SupportPDFConversion(); + tested = true; + } + return havePdf; +} + +//--------------------------------------------------------------------------------------------------------------------- +QVector > DialogSaveManualLayout::InitFormats() +{ + QVector> list; + + auto InitFormat = [&list](LayoutExportFormats format) + { + list.append(std::make_pair(VLayoutExporter::ExportFormatDescription(format), format)); + }; + + InitFormat(LayoutExportFormats::SVG); + InitFormat(LayoutExportFormats::PDF); + InitFormat(LayoutExportFormats::PNG); + InitFormat(LayoutExportFormats::OBJ); + if (SupportPSTest()) + { + InitFormat(LayoutExportFormats::PS); + InitFormat(LayoutExportFormats::EPS); + } + InitFormat(LayoutExportFormats::DXF_AC1006_Flat); + InitFormat(LayoutExportFormats::DXF_AC1009_Flat); + InitFormat(LayoutExportFormats::DXF_AC1012_Flat); + InitFormat(LayoutExportFormats::DXF_AC1014_Flat); + InitFormat(LayoutExportFormats::DXF_AC1015_Flat); + InitFormat(LayoutExportFormats::DXF_AC1018_Flat); + InitFormat(LayoutExportFormats::DXF_AC1021_Flat); + InitFormat(LayoutExportFormats::DXF_AC1024_Flat); + InitFormat(LayoutExportFormats::DXF_AC1027_Flat); + InitFormat(LayoutExportFormats::DXF_AC1006_AAMA); + InitFormat(LayoutExportFormats::DXF_AC1009_AAMA); + InitFormat(LayoutExportFormats::DXF_AC1012_AAMA); + InitFormat(LayoutExportFormats::DXF_AC1014_AAMA); + InitFormat(LayoutExportFormats::DXF_AC1015_AAMA); + InitFormat(LayoutExportFormats::DXF_AC1018_AAMA); + InitFormat(LayoutExportFormats::DXF_AC1021_AAMA); + InitFormat(LayoutExportFormats::DXF_AC1024_AAMA); + InitFormat(LayoutExportFormats::DXF_AC1027_AAMA); + InitFormat(LayoutExportFormats::DXF_AC1006_ASTM); + InitFormat(LayoutExportFormats::DXF_AC1009_ASTM); + InitFormat(LayoutExportFormats::DXF_AC1012_ASTM); + InitFormat(LayoutExportFormats::DXF_AC1014_ASTM); + InitFormat(LayoutExportFormats::DXF_AC1015_ASTM); + InitFormat(LayoutExportFormats::DXF_AC1018_ASTM); + InitFormat(LayoutExportFormats::DXF_AC1021_ASTM); + InitFormat(LayoutExportFormats::DXF_AC1024_ASTM); + InitFormat(LayoutExportFormats::DXF_AC1027_ASTM); + InitFormat(LayoutExportFormats::PDFTiled); +// InitFormat(LayoutExportFormats::NC); + InitFormat(LayoutExportFormats::RLD); + InitFormat(LayoutExportFormats::TIF); + + return list; +} + +//--------------------------------------------------------------------------------------------------------------------- +void DialogSaveManualLayout::RemoveFormatFromList(LayoutExportFormats format) +{ + const int index = ui->comboBoxFormat->findData(static_cast(format)); + if (index != -1) + { + ui->comboBoxFormat->removeItem(index); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void DialogSaveManualLayout::ReadSettings() +{ + VPSettings *settings = VPApplication::VApp()->PuzzleSettings(); + SelectFormat(static_cast(settings->GetLayoutExportFormat())); +} + +//--------------------------------------------------------------------------------------------------------------------- +void DialogSaveManualLayout::WriteSettings() const +{ + if (m_consoleExport) + { + return; + } + + VPSettings *settings = VPApplication::VApp()->PuzzleSettings(); + settings->SetLayoutExportFormat(static_cast(Format())); +} diff --git a/src/app/puzzle/dialogs/dialogsavemanuallayout.h b/src/app/puzzle/dialogs/dialogsavemanuallayout.h new file mode 100644 index 000000000..ce2484b31 --- /dev/null +++ b/src/app/puzzle/dialogs/dialogsavemanuallayout.h @@ -0,0 +1,101 @@ +/************************************************************************ + ** + ** @file dialogsavemanuallayout.h + ** @author Roman Telezhynskyi + ** @date 3 9, 2021 + ** + ** @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) 2021 Valentina project + ** All Rights Reserved. + ** + ** Valentina is free software: you can redistribute it and/or modify + ** it under the terms of the GNU General Public License as published by + ** the Free Software Foundation, either version 3 of the License, or + ** (at your option) any later version. + ** + ** Valentina is distributed in the hope that it will be useful, + ** but WITHOUT ANY WARRANTY; without even the implied warranty of + ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ** GNU General Public License for more details. + ** + ** You should have received a copy of the GNU General Public License + ** along with Valentina. If not, see . + ** + *************************************************************************/ +#ifndef DIALOGSAVEMANUALLAYOUT_H +#define DIALOGSAVEMANUALLAYOUT_H + +#include "../vlayout/dialogs/vabstractlayoutdialog.h" +#include "../vlayout/vlayoutdef.h" + +namespace Ui +{ +class DialogSaveManualLayout; +} + +class DialogSaveManualLayout : public VAbstractLayoutDialog +{ + Q_OBJECT + +public: + explicit DialogSaveManualLayout(int count, bool consoleExport, const QString &fileName = QString(), + QWidget *parent = nullptr); + virtual ~DialogSaveManualLayout(); + + auto Path() const -> QString; + auto FileName() const -> QString; + + auto Format() const -> LayoutExportFormats; + void SelectFormat(LayoutExportFormats format); + + void SetBinaryDXFFormat(bool binary); + bool IsBinaryDXFFormat() const; + + void SetDestinationPath(const QString& cmdDestinationPath); + + bool IsTextAsPaths() const; + void SetTextAsPaths(bool textAsPaths); + + void SetXScale(qreal scale); + qreal GetXScale() const; + + void SetYScale(qreal scale); + qreal GetYScale() const; + + void SetExportUnified(bool value); + bool IsExportUnified() const; + +protected: + virtual void showEvent(QShowEvent *event) override; + +private slots: + void Save(); + void PathChanged(const QString &text); + void ShowExample(); + void ToggleScaleConnection(); + void HorizontalScaleChanged(double d); + void VerticalScaleChanged(double d); + +private: + Q_DISABLE_COPY(DialogSaveManualLayout) + Ui::DialogSaveManualLayout *ui; + int m_count; + bool m_isInitialized{false}; + bool m_scaleConnected{true}; + bool m_consoleExport; + + static bool havePdf; + static bool tested; + static bool SupportPSTest(); + static QVector > InitFormats(); + + void RemoveFormatFromList(LayoutExportFormats format); + + void ReadSettings(); + void WriteSettings() const; +}; + +#endif // DIALOGSAVEMANUALLAYOUT_H diff --git a/src/app/puzzle/dialogs/dialogsavemanuallayout.ui b/src/app/puzzle/dialogs/dialogsavemanuallayout.ui new file mode 100644 index 000000000..b53197f6e --- /dev/null +++ b/src/app/puzzle/dialogs/dialogsavemanuallayout.ui @@ -0,0 +1,408 @@ + + + DialogSaveManualLayout + + + + 0 + 0 + 503 + 383 + + + + Dialog + + + + + + + + Path: + + + + + + + + 0 + 0 + + + + Destination folder + + + Path to destination folder + + + true + + + + + + + + 0 + 0 + + + + Select path to destination folder + + + Browse… + + + + + + + + + + + + 0 + 0 + + + + File format: + + + + + + + + 0 + 0 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Options + + + + + + false + + + Binary form + + + + + + + true + + + Text as paths + + + + + + + false + + + Export unified + + + true + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Scale + + + + + + + + Horizontal: + + + + + + + Vertical: + + + + + + + + + + + % + + + 1 + + + 1.000000000000000 + + + 300.000000000000000 + + + 0.100000000000000 + + + 100.000000000000000 + + + + + + + % + + + 1 + + + 1.000000000000000 + + + 300.000000000000000 + + + 0.100000000000000 + + + 100.000000000000000 + + + + + + + + + 1 + + + 0 + + + 0 + + + + + + 10 + + + + <html><head/><body><p><span style=" font-size:16pt;">┐</span></p></body></html> + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + ... + + + + :/icon/32x32/link.png:/icon/32x32/link.png + + + + 32 + 32 + + + + QToolButton::DelayedPopup + + + + + + + <html><head/><body><p><span style=" font-size:16pt; font-weight:600;">┘</span></p></body></html> + + + + + + + + + + + + + + QLayout::SetDefaultConstraint + + + + + + 0 + 0 + + + + File name: + + + + + + + + 0 + 0 + + + + File base name + + + File base name + + + true + + + + + + + + 0 + 0 + + + + + 130 + 0 + + + + TextLabel + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + + buttonBox + accepted() + DialogSaveManualLayout + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + DialogSaveManualLayout + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/app/puzzle/layout/vplayout.cpp b/src/app/puzzle/layout/vplayout.cpp index 97ffaedda..fca3921db 100644 --- a/src/app/puzzle/layout/vplayout.cpp +++ b/src/app/puzzle/layout/vplayout.cpp @@ -30,6 +30,7 @@ #include "vppiece.h" #include "vpsheet.h" #include "../vpapplication.h" +#include "../vptilefactory.h" #include #include @@ -78,6 +79,11 @@ auto VPLayout::CreateLayout(QUndoStack *undoStack) -> VPLayoutPtr layout->LayoutSettings().SetDescription(QString("Description of my Layout")); // -------------------------------------------------------- + // init the tile factory + auto *tileFactory = new VPTileFactory(layout, settings); + tileFactory->refreshTileInfos(); + layout->SetTileFactory(tileFactory); + return layout; } @@ -108,6 +114,30 @@ void VPLayout::AddPiece(const VPPiecePtr &piece) } } +//--------------------------------------------------------------------------------------------------------------------- +VPTileFactory *VPLayout::TileFactory() const +{ + return m_tileFactory; +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPLayout::SetTileFactory(VPTileFactory *newTileFactory) +{ + m_tileFactory = newTileFactory; +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPLayout::RefreshScenePieces() const +{ + for (const auto& sheet : GetSheets()) + { + if (not sheet.isNull()) + { + sheet->SceneData()->RefreshPieces(sheet); + } + } +} + //--------------------------------------------------------------------------------------------------------------------- auto VPLayout::GetPieces() const -> QList { @@ -159,7 +189,7 @@ auto VPLayout::AddSheet(const VPSheetPtr &sheet) -> VPSheetPtr } //--------------------------------------------------------------------------------------------------------------------- -auto VPLayout::GetSheets() -> QList +auto VPLayout::GetSheets() const -> QList { return m_sheets; } diff --git a/src/app/puzzle/layout/vplayout.h b/src/app/puzzle/layout/vplayout.h index c35b136cf..114448f64 100644 --- a/src/app/puzzle/layout/vplayout.h +++ b/src/app/puzzle/layout/vplayout.h @@ -38,6 +38,7 @@ class VPPiece; class VPSheet; class QUndoStack; +class VPTileFactory; class VPLayout : public QObject { @@ -54,7 +55,7 @@ public: auto GetTrashedPieces() const -> QList; auto AddSheet(const VPSheetPtr &sheet) -> VPSheetPtr; - auto GetSheets() -> QList; + auto GetSheets() const -> QList; auto GetSheet(const QUuid &uuid) -> VPSheetPtr; /** @@ -87,6 +88,11 @@ public: void CheckPiecesPositionValidity() const; + auto TileFactory() const -> VPTileFactory *; + void SetTileFactory(VPTileFactory *newTileFactory); + + void RefreshScenePieces() const; + signals: void PieceSheetChanged(const VPPiecePtr &piece); void ActiveSheetChanged(const VPSheetPtr &focusedSheet); @@ -115,6 +121,8 @@ private: VPLayoutSettings m_layoutSettings{}; QUndoStack *m_undoStack; + + VPTileFactory *m_tileFactory{nullptr}; }; Q_DECLARE_METATYPE(VPLayoutPtr) diff --git a/src/app/puzzle/layout/vplayoutsettings.cpp b/src/app/puzzle/layout/vplayoutsettings.cpp index b67cc79aa..77bedb417 100644 --- a/src/app/puzzle/layout/vplayoutsettings.cpp +++ b/src/app/puzzle/layout/vplayoutsettings.cpp @@ -119,6 +119,12 @@ void VPLayoutSettings::SetTilesSizeConverted(const QSizeF &size) ); } +//--------------------------------------------------------------------------------------------------------------------- +auto VPLayoutSettings::GetTilesOrientation() const -> QPageLayout::Orientation +{ + return m_tilesSize.height() >= m_tilesSize.width() ? QPageLayout::Portrait : QPageLayout::Landscape; +} + //--------------------------------------------------------------------------------------------------------------------- auto VPLayoutSettings::GetTilesSize() const -> QSizeF { diff --git a/src/app/puzzle/layout/vplayoutsettings.h b/src/app/puzzle/layout/vplayoutsettings.h index beb054378..6b877c658 100644 --- a/src/app/puzzle/layout/vplayoutsettings.h +++ b/src/app/puzzle/layout/vplayoutsettings.h @@ -153,6 +153,8 @@ public: */ void SetTilesSizeConverted(const QSizeF &size); + auto GetTilesOrientation() const -> QPageLayout::Orientation; + /** * @brief GetTilesSize Returns the size of the tiles in Unit::Px * @return tiles size in Unit::Px diff --git a/src/app/puzzle/layout/vpsheet.cpp b/src/app/puzzle/layout/vpsheet.cpp index 5bae67f3b..7959bc784 100644 --- a/src/app/puzzle/layout/vpsheet.cpp +++ b/src/app/puzzle/layout/vpsheet.cpp @@ -30,12 +30,221 @@ #include "vplayout.h" #include "vppiece.h" #include "../vpapplication.h" +#include "../vwidgets/vmaingraphicsscene.h" +#include "../scene/vpgraphicssheet.h" +#include "../scene/vpgraphicspiece.h" +#include "../scene/vpgraphicstilegrid.h" +#include "../scene/vpgraphicspiececontrols.h" +#include "../scene/vpgraphicstilegrid.h" + +// VPSheetSceneData +//--------------------------------------------------------------------------------------------------------------------- +VPSheetSceneData::VPSheetSceneData(const VPLayoutPtr &layout, const QUuid &sheetUuid) + : m_layout(layout), + m_scene(new VMainGraphicsScene()) +{ + SCASSERT(not layout.isNull()) + + m_graphicsSheet = new VPGraphicsSheet(layout); + m_graphicsSheet->setPos(0, 0); + m_scene->addItem(m_graphicsSheet); + + m_graphicsTileGrid = new VPGraphicsTileGrid(layout, sheetUuid); + m_scene->addItem(m_graphicsTileGrid); + + m_rotationControls = new VPGraphicsPieceControls(layout); + m_rotationControls->setVisible(false); + m_scene->addItem(m_rotationControls); + + m_rotationOrigin = new VPGraphicsTransformationOrigin(layout); + m_rotationOrigin->setVisible(false); + m_scene->addItem(m_rotationOrigin); + + QObject::connect(m_rotationControls, &VPGraphicsPieceControls::ShowOrigin, + m_rotationOrigin, &VPGraphicsTransformationOrigin::on_ShowOrigin); + QObject::connect(m_rotationControls, &VPGraphicsPieceControls::TransformationOriginChanged, + m_rotationOrigin, &VPGraphicsTransformationOrigin::SetTransformationOrigin); +} //--------------------------------------------------------------------------------------------------------------------- -VPSheet::VPSheet(const VPLayoutPtr &layout) : - m_layout(layout) +VPSheetSceneData::~VPSheetSceneData() { - SCASSERT(layout != nullptr) + delete m_scene; +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VPSheetSceneData::Scene() const -> VMainGraphicsScene * +{ + return m_scene; +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPSheetSceneData::RefreshLayout() +{ + m_graphicsSheet->update(); + + m_graphicsTileGrid->update(); + + m_scene->update(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPSheetSceneData::RefreshPieces(const VPSheetPtr &sheet) +{ + qDeleteAll(m_graphicsPieces); + m_graphicsPieces.clear(); + + if (not sheet.isNull()) + { + QList pieces = sheet->GetPieces(); + m_graphicsPieces.reserve(pieces.size()); + + for (const auto &piece : pieces) + { + if (not piece.isNull()) + { + auto *graphicsPiece = new VPGraphicsPiece(piece); + m_graphicsPieces.append(graphicsPiece); + m_scene->addItem(graphicsPiece); + ConnectPiece(graphicsPiece); + } + } + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPSheetSceneData::PrepareForExport() +{ + m_graphicsSheet->SetShowBorder(false); + m_graphicsSheet->SetShowMargin(false); + + VPLayoutPtr layout = m_layout.toStrongRef(); + if (not layout.isNull()) + { + m_showGridTmp = layout->LayoutSettings().GetShowGrid(); + layout->LayoutSettings().SetShowGrid(false); + + m_showTilesTmp = layout->LayoutSettings().GetShowTiles(); + layout->LayoutSettings().SetShowTiles(false); + } + + RefreshLayout(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPSheetSceneData::CleanAfterExport() +{ + m_graphicsSheet->SetShowBorder(true); + m_graphicsSheet->SetShowMargin(true); + + VPLayoutPtr layout = m_layout.toStrongRef(); + if (not layout.isNull()) + { + layout->LayoutSettings().SetShowGrid(m_showGridTmp); + layout->LayoutSettings().SetShowTiles(m_showTilesTmp); + } + + RefreshLayout(); +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VPSheetSceneData::GraphicsPieces() const -> const QList & +{ + return m_graphicsPieces; +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VPSheetSceneData::GraphicsPiecesAsItems() const -> QList +{ + QList items; + items.reserve(m_graphicsPieces.size()); + + for(auto *item : m_graphicsPieces) + { + items.append(item); + } + + return items; +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VPSheetSceneData::RotationControls() const -> VPGraphicsPieceControls * +{ + return m_rotationControls; +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VPSheetSceneData::ScenePiece(const VPPiecePtr &piece) const -> VPGraphicsPiece * +{ + VPGraphicsPiece *_graphicsPiece = nullptr; + for(auto *graphicPiece : m_graphicsPieces) + { + if(graphicPiece->GetPiece() == piece) + { + _graphicsPiece = graphicPiece; + } + } + + return _graphicsPiece; +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPSheetSceneData::RemovePiece(VPGraphicsPiece *piece) +{ + m_graphicsPieces.removeAll(piece); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPSheetSceneData::AddPiece(VPGraphicsPiece *piece) +{ + m_graphicsPieces.append(piece); + ConnectPiece(piece); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPSheetSceneData::SetTextAsPaths(bool textAsPaths) const +{ + for (auto *piece : m_graphicsPieces) + { + if (piece != nullptr) + { + piece->SetTextAsPaths(textAsPaths); + } + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPSheetSceneData::ConnectPiece(VPGraphicsPiece *piece) +{ + SCASSERT(piece != nullptr) + + VPLayoutPtr layout = m_layout.toStrongRef(); + if (layout.isNull()) + { + return; + } + + QObject::connect(layout.get(), &VPLayout::PieceTransformationChanged, piece, + &VPGraphicsPiece::on_RefreshPiece); + QObject::connect(layout.get(), &VPLayout::PieceSelectionChanged, + m_rotationControls, &VPGraphicsPieceControls::on_UpdateControls); + QObject::connect(layout.get(), &VPLayout::PiecePositionValidityChanged, + piece, &VPGraphicsPiece::on_RefreshPiece); + QObject::connect(piece, &VPGraphicsPiece::PieceTransformationChanged, + m_rotationControls, &VPGraphicsPieceControls::on_UpdateControls); + QObject::connect(piece, &VPGraphicsPiece::HideTransformationHandles, + m_rotationControls, &VPGraphicsPieceControls::on_HideHandles); + QObject::connect(piece, &VPGraphicsPiece::HideTransformationHandles, + m_rotationOrigin, &VPGraphicsTransformationOrigin::on_HideHandles); +} + +// VPSheet +//--------------------------------------------------------------------------------------------------------------------- +VPSheet::VPSheet(const VPLayoutPtr &layout) : + m_layout(layout), + m_sceneData(new VPSheetSceneData(layout, Uuid())) +{ + SCASSERT(not layout.isNull()) VPSettings *settings = VPApplication::VApp()->PuzzleSettings(); SetIgnoreMargins(settings->GetLayoutSheetIgnoreMargins()); @@ -86,6 +295,25 @@ auto VPSheet::GetSelectedPieces() const -> QList return {}; } +//--------------------------------------------------------------------------------------------------------------------- +auto VPSheet::GetAsLayoutPieces() const -> QVector +{ + QList pieces = GetPieces(); + + QVector details; + details.reserve(pieces.size()); + + for (auto piece : pieces) + { + if (not piece.isNull()) + { + details.append(*piece); + } + } + + return details; +} + //--------------------------------------------------------------------------------------------------------------------- auto VPSheet::GetName() const -> QString { @@ -362,7 +590,13 @@ void VPSheet::CheckPiecePositionValidity(const VPPiecePtr &piece) const } //--------------------------------------------------------------------------------------------------------------------- -Unit VPSheet::SheetUnits() const +auto VPSheet::SceneData() const -> VPSheetSceneData * +{ + return m_sceneData; +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VPSheet::SheetUnits() const -> Unit { VPLayoutPtr layout = GetLayout(); if (not layout.isNull()) diff --git a/src/app/puzzle/layout/vpsheet.h b/src/app/puzzle/layout/vpsheet.h index ea8246e9d..45f60e1ff 100644 --- a/src/app/puzzle/layout/vpsheet.h +++ b/src/app/puzzle/layout/vpsheet.h @@ -39,6 +39,79 @@ class VPLayout; class VPPiece; +class VMainGraphicsScene; +class VPGraphicsPieceControls; +class VPGraphicsTransformationOrigin; +class VPGraphicsPiece; +class VPGraphicsTileGrid; +class VPGraphicsSheet; +class VLayoutPiece; + +class VPSheetSceneData +{ +public: + explicit VPSheetSceneData(const VPLayoutPtr &layout, const QUuid &sheetUuid); + ~VPSheetSceneData(); + + VMainGraphicsScene *Scene() const; + + /** + * @brief RefreshLayout Refreshes the rectangles for the layout border and the margin + */ + void RefreshLayout(); + + void RefreshPieces(const VPSheetPtr &sheet); + + /** + * @brief PrepareForExport prepares the graphic for an export (i.e hide margin etc) + */ + void PrepareForExport(); + + /** + * @brief CleanAfterExport cleans the graphic for an export (i.e show margin etc) + */ + void CleanAfterExport(); + + auto GraphicsPieces() const -> const QList &; + auto GraphicsPiecesAsItems() const -> QList; + + auto RotationControls() const -> VPGraphicsPieceControls *; + + auto ScenePiece(const VPPiecePtr &piece) const -> VPGraphicsPiece *; + + void RemovePiece(VPGraphicsPiece *piece); + void AddPiece(VPGraphicsPiece *piece); + + void SetTextAsPaths(bool textAsPaths) const; + +private: + Q_DISABLE_COPY(VPSheetSceneData) + + VPLayoutWeakPtr m_layout{}; + + VMainGraphicsScene *m_scene; + + VPGraphicsSheet *m_graphicsSheet{nullptr}; + + VPGraphicsTileGrid *m_graphicsTileGrid{nullptr}; + + VPGraphicsPieceControls *m_rotationControls{nullptr}; + VPGraphicsTransformationOrigin *m_rotationOrigin{nullptr}; + + QList m_graphicsPieces{}; + + /** + * variable to hold temporarly hte value of the show tiles + */ + bool m_showTilesTmp{false}; + + /** + * variable to hold temporarly hte value of the show grid + */ + bool m_showGridTmp{false}; + + void ConnectPiece(VPGraphicsPiece *piece); +}; class VPSheet : public QObject { @@ -58,6 +131,8 @@ public: auto GetSelectedPieces() const -> QList; + auto GetAsLayoutPieces() const -> QVector; + /** * @brief GetName Returns the name of the sheet * @return the name @@ -178,6 +253,8 @@ public: auto IgnoreMargins() const -> bool; void SetIgnoreMargins(bool newIgnoreMargins); + VPSheetSceneData *SceneData() const; + public slots: void CheckPiecePositionValidity(const VPPiecePtr &piece) const; @@ -210,6 +287,8 @@ private: GrainlineType m_grainlineType{GrainlineType::NotFixed}; + VPSheetSceneData *m_sceneData{nullptr}; + auto SheetUnits() const -> Unit; }; diff --git a/src/app/puzzle/puzzle.pri b/src/app/puzzle/puzzle.pri index 33865dd6e..2129fab00 100644 --- a/src/app/puzzle/puzzle.pri +++ b/src/app/puzzle/puzzle.pri @@ -22,7 +22,6 @@ SOURCES += \ $$PWD/carousel/vpcarrouselpiecelist.cpp \ $$PWD/vpcommandline.cpp \ $$PWD/vpcommands.cpp \ - $$PWD/vpexporter.cpp \ $$PWD/scene/vpgraphicspiece.cpp \ $$PWD/scene/vpgraphicspiececontrols.cpp \ $$PWD/scene/vpgraphicssheet.cpp \ @@ -38,7 +37,8 @@ SOURCES += \ $$PWD/vptilefactory.cpp \ $$PWD/xml/vplayoutfilereader.cpp \ $$PWD/xml/vplayoutfilewriter.cpp \ - $$PWD/xml/vplayoutliterals.cpp + $$PWD/xml/vplayoutliterals.cpp \ + $$PWD/dialogs/dialogsavemanuallayout.cpp *msvc*:SOURCES += $$PWD/stable.cpp @@ -64,7 +64,6 @@ HEADERS += \ $$PWD/carousel/vpcarrouselpiecelist.h \ $$PWD/vpcommandline.h \ $$PWD/vpcommands.h \ - $$PWD/vpexporter.h \ $$PWD/scene/vpgraphicspiece.h \ $$PWD/scene/vpgraphicspiececontrols.h \ $$PWD/scene/vpgraphicssheet.h \ @@ -80,7 +79,8 @@ HEADERS += \ $$PWD/vptilefactory.h \ $$PWD/xml/vplayoutfilereader.h \ $$PWD/xml/vplayoutfilewriter.h \ - $$PWD/xml/vplayoutliterals.h + $$PWD/xml/vplayoutliterals.h \ + $$PWD/dialogs/dialogsavemanuallayout.h FORMS += \ $$PWD/dialogs/configpages/puzzlepreferencesconfigurationpage.ui \ @@ -89,4 +89,5 @@ FORMS += \ $$PWD/dialogs/dialogpuzzlepreferences.ui \ $$PWD/dialogs/vpdialogabout.ui \ $$PWD/carousel/vpcarrousel.ui \ - $$PWD/vpmainwindow.ui + $$PWD/vpmainwindow.ui \ + $$PWD/dialogs/dialogsavemanuallayout.ui diff --git a/src/app/puzzle/puzzle.pro b/src/app/puzzle/puzzle.pro index d416415e7..a2a9a1dce 100644 --- a/src/app/puzzle/puzzle.pro +++ b/src/app/puzzle/puzzle.pro @@ -198,16 +198,7 @@ DEPENDPATH += $$PWD/../../libs/vwidgets win32:!win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vwidgets/$${DESTDIR}/vwidgets.lib else:unix|win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vwidgets/$${DESTDIR}/libvwidgets.a -## VFormat static library (depend on VPatternDB, IFC) -#unix|win32: LIBS += -L$$OUT_PWD/../../libs/vformat/$${DESTDIR}/ -lvformat - -#INCLUDEPATH += $$PWD/../../libs/vformat -#DEPENDPATH += $$PWD/../../libs/vformat - -#win32:!win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vformat/$${DESTDIR}/vformat.lib -#else:unix|win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vformat/$${DESTDIR}/libvformat.a - -# VLayout static library (depend on VGeometry) +# VLayout static library (depend on VGeometry, VFormat) unix|win32: LIBS += -L$$OUT_PWD/../../libs/vlayout/$${DESTDIR}/ -lvlayout INCLUDEPATH += $$PWD/../../libs/vlayout @@ -216,6 +207,15 @@ DEPENDPATH += $$PWD/../../libs/vlayout win32:!win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vlayout/$${DESTDIR}/vlayout.lib else:unix|win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vlayout/$${DESTDIR}/libvlayout.a +# VFormat static library (depend on VPatternDB, IFC) +unix|win32: LIBS += -L$$OUT_PWD/../../libs/vformat/$${DESTDIR}/ -lvformat + +INCLUDEPATH += $$PWD/../../libs/vformat +DEPENDPATH += $$PWD/../../libs/vformat + +win32:!win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vformat/$${DESTDIR}/vformat.lib +else:unix|win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vformat/$${DESTDIR}/libvformat.a + #VPatternDB static library (depend on vgeometry, vmisc) unix|win32: LIBS += -L$$OUT_PWD/../../libs/vpatterndb/$${DESTDIR} -lvpatterndb diff --git a/src/app/puzzle/scene/vpgraphicstilegrid.cpp b/src/app/puzzle/scene/vpgraphicstilegrid.cpp index 3154d3323..eb2d05782 100644 --- a/src/app/puzzle/scene/vpgraphicstilegrid.cpp +++ b/src/app/puzzle/scene/vpgraphicstilegrid.cpp @@ -3,13 +3,17 @@ #include "../vptilefactory.h" #include "../layout/vplayout.h" -//--------------------------------------------------------------------------------------------------------------------- -VPGraphicsTileGrid::VPGraphicsTileGrid(const VPLayoutPtr &layout, VPTileFactory *tileFactory, QGraphicsItem *parent): - QGraphicsItem(parent), - m_tileFactory(tileFactory), - m_layout(layout) +namespace { +constexpr qreal penWidth = 1; +} +//--------------------------------------------------------------------------------------------------------------------- +VPGraphicsTileGrid::VPGraphicsTileGrid(const VPLayoutPtr &layout, const QUuid &sheetUuid, QGraphicsItem *parent): + QGraphicsItem(parent), + m_layout(layout), + m_sheetUuid(sheetUuid) +{ } //--------------------------------------------------------------------------------------------------------------------- @@ -18,11 +22,15 @@ auto VPGraphicsTileGrid::boundingRect() const -> QRectF VPLayoutPtr layout = m_layout.toStrongRef(); if(not layout.isNull() && layout->LayoutSettings().GetShowTiles()) { - return QRectF(0, - 0, - m_tileFactory->getColNb()* m_tileFactory->getDrawingAreaWidth(), - m_tileFactory->getRowNb()* m_tileFactory->getDrawingAreaHeight() - ); + VPSheetPtr sheet = layout->GetSheet(m_sheetUuid); + + QRectF rect(0, 0, + layout->TileFactory()->ColNb(sheet) * layout->TileFactory()->DrawingAreaWidth(), + layout->TileFactory()->RowNb(sheet) * layout->TileFactory()->DrawingAreaHeight() ); + + constexpr qreal halfPenWidth = penWidth/2.; + + return rect.adjusted(-halfPenWidth, -halfPenWidth, halfPenWidth, halfPenWidth); } return {}; @@ -37,34 +45,36 @@ void VPGraphicsTileGrid::paint(QPainter *painter, const QStyleOptionGraphicsItem VPLayoutPtr layout = m_layout.toStrongRef(); if(not layout.isNull() && layout->LayoutSettings().GetShowTiles()) { - QPen pen(QColor(255,0,0,127), 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin); + VPSheetPtr sheet = layout->GetSheet(m_sheetUuid); + + QPen pen(QColor(255,0,0,127), penWidth, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin); pen.setCosmetic(true); pen.setStyle(Qt::DashLine); QBrush noBrush(Qt::NoBrush); painter->setPen(pen); painter->setBrush(noBrush); - for(int i=0;i<=m_tileFactory->getColNb();i++) + for(int i=0;i<=layout->TileFactory()->ColNb(sheet);i++) { painter->drawLine(QPointF( - i*m_tileFactory->getDrawingAreaWidth(), + i*layout->TileFactory()->DrawingAreaWidth(), 0), QPointF( - i*m_tileFactory->getDrawingAreaWidth(), - m_tileFactory->getRowNb()*m_tileFactory->getDrawingAreaHeight() + i*layout->TileFactory()->DrawingAreaWidth(), + layout->TileFactory()->RowNb(sheet)*layout->TileFactory()->DrawingAreaHeight() ) ); } - for(int j=0;j<=m_tileFactory->getRowNb();j++) + for(int j=0;j<=layout->TileFactory()->RowNb(sheet);j++) { painter->drawLine(QPointF( 0, - j*m_tileFactory->getDrawingAreaHeight() + j*layout->TileFactory()->DrawingAreaHeight() ), QPointF( - m_tileFactory->getColNb()*m_tileFactory->getDrawingAreaWidth(), - j*m_tileFactory->getDrawingAreaHeight() + layout->TileFactory()->ColNb(sheet)*layout->TileFactory()->DrawingAreaWidth(), + j*layout->TileFactory()->DrawingAreaHeight() ) ); } diff --git a/src/app/puzzle/scene/vpgraphicstilegrid.h b/src/app/puzzle/scene/vpgraphicstilegrid.h index b30b70195..df3931da0 100644 --- a/src/app/puzzle/scene/vpgraphicstilegrid.h +++ b/src/app/puzzle/scene/vpgraphicstilegrid.h @@ -31,6 +31,7 @@ #include #include +#include #include "../vmisc/def.h" #include "../layout/layoutdef.h" @@ -41,18 +42,17 @@ class VPLayout; class VPGraphicsTileGrid : public QGraphicsItem { public: - explicit VPGraphicsTileGrid(const VPLayoutPtr &layout, VPTileFactory *tileFactory, QGraphicsItem *parent = nullptr); + explicit VPGraphicsTileGrid(const VPLayoutPtr &layout, const QUuid &sheetUuid, QGraphicsItem *parent = nullptr); ~VPGraphicsTileGrid()=default; QRectF boundingRect() const override; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; - private: Q_DISABLE_COPY(VPGraphicsTileGrid) - VPTileFactory * m_tileFactory{nullptr}; - VPLayoutWeakPtr m_layout{}; + VPLayoutWeakPtr m_layout; + QUuid m_sheetUuid; }; #endif // VPGRAPHICSTILEGRID_H diff --git a/src/app/puzzle/scene/vpmaingraphicsview.cpp b/src/app/puzzle/scene/vpmaingraphicsview.cpp index f42fcbca9..f5d1f8c90 100644 --- a/src/app/puzzle/scene/vpmaingraphicsview.cpp +++ b/src/app/puzzle/scene/vpmaingraphicsview.cpp @@ -34,17 +34,16 @@ #include #include -#include "../scene/vpgraphicssheet.h" -#include "../scene/vpgraphicspiece.h" #include "../vptilefactory.h" -#include "../scene/vpgraphicstilegrid.h" #include "../carousel/vpmimedatapiece.h" #include "../layout/vplayout.h" #include "../layout/vpsheet.h" #include "../layout/vppiece.h" #include "../vwidgets/vmaingraphicsscene.h" #include "vptilefactory.h" +#include "vpgraphicspiece.h" #include "vpgraphicspiececontrols.h" + #include "../undocommands/vpundopiecemove.h" #include "../undocommands/vpundopiecerotate.h" #include "../undocommands/vpundooriginmove.h" @@ -62,41 +61,19 @@ const QKeySequence restoreOriginShortcut = QKeySequence(Qt::ControlModifier + Qt //--------------------------------------------------------------------------------------------------------------------- -VPMainGraphicsView::VPMainGraphicsView(const VPLayoutPtr &layout, VPTileFactory *tileFactory, QWidget *parent) : +VPMainGraphicsView::VPMainGraphicsView(const VPLayoutPtr &layout, QWidget *parent) : VMainGraphicsView(parent), - m_scene(new VMainGraphicsScene(this)), m_layout(layout) { - SCASSERT(not m_layout.isNull()) - setScene(m_scene); + SCASSERT(not layout.isNull()) - connect(m_scene, &VMainGraphicsScene::ItemClicked, this, &VPMainGraphicsView::on_ItemClicked); - - m_graphicsSheet = new VPGraphicsSheet(m_layout); - m_graphicsSheet->setPos(0, 0); - m_scene->addItem(m_graphicsSheet); + SwitchScene(layout->GetFocusedSheet()); setAcceptDrops(true); - m_graphicsTileGrid = new VPGraphicsTileGrid(m_layout, tileFactory); - m_scene->addItem(m_graphicsTileGrid); - - m_rotationControls = new VPGraphicsPieceControls(m_layout); - m_rotationControls->setVisible(false); - m_scene->addItem(m_rotationControls); - - m_rotationOrigin = new VPGraphicsTransformationOrigin(m_layout); - m_rotationOrigin->setVisible(false); - m_scene->addItem(m_rotationOrigin); - - connect(m_rotationControls, &VPGraphicsPieceControls::ShowOrigin, - m_rotationOrigin, &VPGraphicsTransformationOrigin::on_ShowOrigin); - connect(m_rotationControls, &VPGraphicsPieceControls::TransformationOriginChanged, - m_rotationOrigin, &VPGraphicsTransformationOrigin::SetTransformationOrigin); - // add the connections connect(layout.get(), &VPLayout::PieceSheetChanged, this, &VPMainGraphicsView::on_PieceSheetChanged); - connect(layout.get(), &VPLayout::ActiveSheetChanged, this, &VPMainGraphicsView::RefreshPieces); + connect(layout.get(), &VPLayout::ActiveSheetChanged, this, &VPMainGraphicsView::on_ActiveSheetChanged); auto *restoreOrigin = new QAction(this); restoreOrigin->setShortcut(restoreOriginShortcut); @@ -107,84 +84,29 @@ VPMainGraphicsView::VPMainGraphicsView(const VPLayoutPtr &layout, VPTileFactory //--------------------------------------------------------------------------------------------------------------------- void VPMainGraphicsView::RefreshLayout() { - // FIXME: Is that the way to go? - - m_graphicsSheet->update(); - - m_graphicsTileGrid->update(); - - m_scene->update(); -} - -//--------------------------------------------------------------------------------------------------------------------- -void VPMainGraphicsView::RefreshPieces() -{ - qDeleteAll(m_graphicsPieces); - m_graphicsPieces.clear(); - VPLayoutPtr layout = m_layout.toStrongRef(); if (not layout.isNull()) { VPSheetPtr sheet = layout->GetFocusedSheet(); if (not sheet.isNull()) { - QList pieces = sheet->GetPieces(); - m_graphicsPieces.reserve(pieces.size()); - - for (const auto &piece : pieces) - { - if (not piece.isNull()) - { - auto *graphicsPiece = new VPGraphicsPiece(piece); - m_graphicsPieces.append(graphicsPiece); - scene()->addItem(graphicsPiece); - ConnectPiece(graphicsPiece); - } - } + sheet->SceneData()->RefreshLayout(); } } } //--------------------------------------------------------------------------------------------------------------------- -auto VPMainGraphicsView::GetScene() -> VMainGraphicsScene* +void VPMainGraphicsView::RefreshPieces() { - return m_scene; -} - -//--------------------------------------------------------------------------------------------------------------------- -void VPMainGraphicsView::PrepareForExport() -{ - m_graphicsSheet->SetShowBorder(false); - m_graphicsSheet->SetShowMargin(false); - VPLayoutPtr layout = m_layout.toStrongRef(); if (not layout.isNull()) { - m_showGridTmp = layout->GetFocusedSheet()->GetLayout()->LayoutSettings().GetShowGrid(); - layout->GetFocusedSheet()->GetLayout()->LayoutSettings().SetShowGrid(false); - - m_showTilesTmp = layout->LayoutSettings().GetShowTiles(); - layout->LayoutSettings().SetShowTiles(false); + VPSheetPtr sheet = layout->GetFocusedSheet(); + if (not sheet.isNull()) + { + sheet->SceneData()->RefreshPieces(sheet); + } } - - RefreshLayout(); -} - -//--------------------------------------------------------------------------------------------------------------------- -void VPMainGraphicsView::CleanAfterExport() -{ - m_graphicsSheet->SetShowBorder(true); - m_graphicsSheet->SetShowMargin(true); - - VPLayoutPtr layout = m_layout.toStrongRef(); - if (not layout.isNull()) - { - layout->GetFocusedSheet()->GetLayout()->LayoutSettings().SetShowGrid(m_showGridTmp); - - layout->LayoutSettings().SetShowTiles(m_showTilesTmp); - } - - RefreshLayout(); } //--------------------------------------------------------------------------------------------------------------------- @@ -253,7 +175,20 @@ void VPMainGraphicsView::keyPressEvent(QKeyEvent *event) { if(event->key() == Qt::Key_Backspace || event->key() == Qt::Key_Delete) { - for(auto *graphicsPiece : m_graphicsPieces) + VPLayoutPtr layout = m_layout.toStrongRef(); + if (layout.isNull()) + { + return; + } + + VPSheetPtr sheet = layout->GetFocusedSheet(); + if (sheet.isNull()) + { + return ; + } + + const QList &graphicsPieces = sheet->SceneData()->GraphicsPieces(); + for(auto *graphicsPiece : graphicsPieces) { VPPiecePtr piece = graphicsPiece->GetPiece(); @@ -360,43 +295,50 @@ void VPMainGraphicsView::keyReleaseEvent(QKeyEvent *event) { if (not event->isAutoRepeat()) { - if (m_hasStickyPosition && not m_graphicsPieces.isEmpty()) + VPLayoutPtr layout = m_layout.toStrongRef(); + if (layout.isNull()) { - VPPiecePtr piece = m_graphicsPieces.first()->GetPiece(); - if (not piece.isNull()) + return; + } + + VPSheetPtr sheet = layout->GetFocusedSheet(); + if (sheet.isNull()) + { + return; + } + + const QList &graphicsPieces = sheet->SceneData()->GraphicsPieces(); + if (m_hasStickyPosition && not graphicsPieces.isEmpty()) + { + if (layout->LayoutSettings().GetStickyEdges()) { - VPLayoutPtr layout = piece->Layout(); - if (not layout.isNull() && layout->LayoutSettings().GetStickyEdges()) + auto PreparePieces = [layout]() { - auto PreparePieces = [layout]() + QList pieces; + VPSheetPtr sheet = layout->GetFocusedSheet(); + if (not sheet.isNull()) { - QList pieces; - VPSheetPtr sheet = layout->GetFocusedSheet(); - if (not sheet.isNull()) - { - pieces = sheet->GetSelectedPieces(); - } + pieces = sheet->GetSelectedPieces(); + } - return pieces; - }; + return pieces; + }; - QList pieces = PreparePieces(); - if (pieces.size() == 1) + QList pieces = PreparePieces(); + if (pieces.size() == 1) + { + VPPiecePtr p = pieces.first(); + + auto *command = new VPUndoPieceMove(p, m_stickyTranslateX, m_stickyTranslateY, + m_allowChangeMerge); + layout->UndoStack()->push(command); + + VPGraphicsPiece * gPiece = sheet->SceneData()->ScenePiece(p); + if (gPiece != nullptr) { - VPPiecePtr p = pieces.first(); - - auto *command = new VPUndoPieceMove(p, m_stickyTranslateX, m_stickyTranslateY, - m_allowChangeMerge); - layout->UndoStack()->push(command); - - VPGraphicsPiece * gPiece = ScenePiece(p); - if (gPiece != nullptr) - { - gPiece->SetStickyPoints(QVector()); - } + gPiece->SetStickyPoints(QVector()); } } - } } @@ -409,9 +351,20 @@ void VPMainGraphicsView::keyReleaseEvent(QKeyEvent *event) { if (not event->isAutoRepeat()) { - m_rotationControls->SetIgnorePieceTransformation(false); - m_rotationControls->on_UpdateControls(); - m_rotationControls->on_HideHandles(false); + VPLayoutPtr layout = m_layout.toStrongRef(); + if (layout.isNull()) + { + return; + } + + VPSheetPtr sheet = layout->GetFocusedSheet(); + if (sheet.isNull()) + { + sheet->SceneData()->RotationControls()->SetIgnorePieceTransformation(false); + sheet->SceneData()->RotationControls()->on_UpdateControls(); + sheet->SceneData()->RotationControls()->on_HideHandles(false); + } + m_rotationSum = 0; } } @@ -546,32 +499,14 @@ void VPMainGraphicsView::on_ItemClicked(QGraphicsItem *item) } //--------------------------------------------------------------------------------------------------------------------- -void VPMainGraphicsView::ConnectPiece(VPGraphicsPiece *piece) +void VPMainGraphicsView::on_SceneMouseMove(const QPointF &scenePos) { - SCASSERT(piece != nullptr) - - VPLayoutPtr layout = m_layout.toStrongRef(); - - connect(layout.get(), &VPLayout::PieceTransformationChanged, piece, - &VPGraphicsPiece::on_RefreshPiece); - connect(layout.get(), &VPLayout::PieceSelectionChanged, - m_rotationControls, &VPGraphicsPieceControls::on_UpdateControls); - connect(layout.get(), &VPLayout::PiecePositionValidityChanged, - piece, &VPGraphicsPiece::on_RefreshPiece); - connect(piece, &VPGraphicsPiece::PieceTransformationChanged, - m_rotationControls, &VPGraphicsPieceControls::on_UpdateControls); - connect(piece, &VPGraphicsPiece::HideTransformationHandles, - m_rotationControls, &VPGraphicsPieceControls::on_HideHandles); - connect(piece, &VPGraphicsPiece::HideTransformationHandles, - m_rotationOrigin, &VPGraphicsTransformationOrigin::on_HideHandles); + emit mouseMove(scenePos); } //--------------------------------------------------------------------------------------------------------------------- void VPMainGraphicsView::RotatePiecesByAngle(qreal angle) { - m_rotationControls->on_HideHandles(true); - m_rotationControls->SetIgnorePieceTransformation(true); - VPLayoutPtr layout = m_layout.toStrongRef(); if (layout.isNull()) { @@ -584,6 +519,9 @@ void VPMainGraphicsView::RotatePiecesByAngle(qreal angle) return; } + sheet->SceneData()->RotationControls()->on_HideHandles(true); + sheet->SceneData()->RotationControls()->SetIgnorePieceTransformation(true); + VPTransformationOrigon origin = sheet->TransformationOrigin(); auto PreparePieces = [this]() @@ -637,23 +575,31 @@ void VPMainGraphicsView::RotatePiecesByAngle(qreal angle) //--------------------------------------------------------------------------------------------------------------------- void VPMainGraphicsView::TranslatePiecesOn(qreal dx, qreal dy) { - if (m_graphicsPieces.isEmpty()) - { - return; - } - - VPPiecePtr piece = m_graphicsPieces.first()->GetPiece(); - if (piece.isNull()) - { - return; - } - - VPLayoutPtr layout = piece->Layout(); + VPLayoutPtr layout = m_layout.toStrongRef(); if (layout.isNull()) { return; } + VPSheetPtr sheet = layout->GetFocusedSheet(); + if (sheet.isNull()) + { + return; + } + + const QList &graphicsPieces = sheet->SceneData()->GraphicsPieces(); + + if (graphicsPieces.isEmpty()) + { + return; + } + + VPPiecePtr piece = graphicsPieces.first()->GetPiece(); + if (piece.isNull()) + { + return; + } + auto PreparePieces = [this]() { QList pieces; @@ -693,7 +639,7 @@ void VPMainGraphicsView::TranslatePiecesOn(qreal dx, qreal dy) m_hasStickyPosition = false; } - VPGraphicsPiece *gPiece = ScenePiece(p); + VPGraphicsPiece *gPiece = sheet->SceneData()->ScenePiece(p); if (gPiece != nullptr) { gPiece->SetStickyPoints(path); @@ -710,38 +656,66 @@ void VPMainGraphicsView::TranslatePiecesOn(qreal dx, qreal dy) } //--------------------------------------------------------------------------------------------------------------------- -auto VPMainGraphicsView::ScenePiece(const VPPiecePtr &piece) const -> VPGraphicsPiece * +void VPMainGraphicsView::SwitchScene(const VPSheetPtr &sheet) { - VPGraphicsPiece *_graphicsPiece = nullptr; - for(auto *graphicPiece : m_graphicsPieces) + if (not sheet.isNull()) { - if(graphicPiece->GetPiece() == piece) - { - _graphicsPiece = graphicPiece; - } + VMainGraphicsScene *scene = sheet->SceneData()->Scene(); + setScene(scene); + connect(scene, &VMainGraphicsScene::ItemClicked, this, &VPMainGraphicsView::on_ItemClicked, + Qt::UniqueConnection); + connect(scene, &VMainGraphicsScene::mouseMove, this, &VPMainGraphicsView::on_SceneMouseMove, + Qt::UniqueConnection); } - - return _graphicsPiece; } //--------------------------------------------------------------------------------------------------------------------- -void VPMainGraphicsView::on_PieceSheetChanged(const VPPiecePtr &piece) +void VPMainGraphicsView::ClearSelection() { - VPGraphicsPiece *graphicsPiece = ScenePiece(piece); - - VPLayoutPtr layout = piece->Layout(); + VPLayoutPtr layout = m_layout.toStrongRef(); if (layout.isNull()) { return; } - if (piece->Sheet().isNull() || piece->Sheet() == layout->GetTrashSheet() || - piece->Sheet() != layout->GetFocusedSheet()) // remove + VPSheetPtr sheet = layout->GetFocusedSheet(); + if (sheet.isNull()) + { + return; + } + + QList pieces = sheet->GetSelectedPieces(); + for (const auto& piece : pieces) + { + piece->SetSelected(false); + emit layout->PieceSelectionChanged(piece); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPMainGraphicsView::on_PieceSheetChanged(const VPPiecePtr &piece) +{ + VPLayoutPtr layout = m_layout.toStrongRef(); + if (layout.isNull()) + { + return; + } + + VPSheetPtr sheet = layout->GetFocusedSheet(); + if (sheet.isNull()) + { + return; + } + + VPGraphicsPiece *graphicsPiece = sheet->SceneData()->ScenePiece(piece); + + if (piece != nullptr && (piece->Sheet().isNull() || piece->Sheet() == layout->GetTrashSheet() || + piece->Sheet() != layout->GetFocusedSheet())) // remove { if (graphicsPiece != nullptr) { - scene()->removeItem(graphicsPiece); - m_graphicsPieces.removeAll(graphicsPiece); + sheet->SceneData()->Scene()->removeItem(graphicsPiece); + sheet->SceneData()->RemovePiece(graphicsPiece); delete graphicsPiece; } } @@ -750,13 +724,24 @@ void VPMainGraphicsView::on_PieceSheetChanged(const VPPiecePtr &piece) if(graphicsPiece == nullptr) { graphicsPiece = new VPGraphicsPiece(piece); - m_graphicsPieces.append(graphicsPiece); - ConnectPiece(graphicsPiece); + sheet->SceneData()->AddPiece(graphicsPiece); } - scene()->addItem(graphicsPiece); + sheet->SceneData()->Scene()->addItem(graphicsPiece); } - m_rotationControls->on_UpdateControls(); + sheet->SceneData()->RotationControls()->on_UpdateControls(); VMainGraphicsView::NewSceneRect(scene(), this); } + +//--------------------------------------------------------------------------------------------------------------------- +void VPMainGraphicsView::on_ActiveSheetChanged(const VPSheetPtr &focusedSheet) +{ + if (not focusedSheet.isNull()) + { + ClearSelection(); + SwitchScene(focusedSheet); + RefreshLayout(); + RefreshPieces(); + } +} diff --git a/src/app/puzzle/scene/vpmaingraphicsview.h b/src/app/puzzle/scene/vpmaingraphicsview.h index 2515670a8..792cd5b39 100644 --- a/src/app/puzzle/scene/vpmaingraphicsview.h +++ b/src/app/puzzle/scene/vpmaingraphicsview.h @@ -46,7 +46,7 @@ class VPMainGraphicsView : public VMainGraphicsView { Q_OBJECT public: - VPMainGraphicsView(const VPLayoutPtr &layout, VPTileFactory *tileFactory, QWidget *parent); + VPMainGraphicsView(const VPLayoutPtr &layout, QWidget *parent); ~VPMainGraphicsView() = default; /** @@ -54,22 +54,6 @@ public: */ void RefreshLayout(); - /** - * @brief GetScene Returns the scene of the view - * @return scene of the view - */ - auto GetScene() -> VMainGraphicsScene*; - - /** - * @brief PrepareForExport prepares the graphic for an export (i.e hide margin etc) - */ - void PrepareForExport(); - - /** - * @brief CleanAfterExport cleans the graphic for an export (i.e show margin etc) - */ - void CleanAfterExport(); - public slots: /** * @brief on_PieceSheetChanged The slot is called when the given piece was moved from the given piece list to @@ -78,8 +62,17 @@ public slots: */ void on_PieceSheetChanged(const VPPiecePtr &piece); + void on_ActiveSheetChanged(const VPSheetPtr &focusedSheet); + void RefreshPieces(); +signals: + /** + * @brief mouseMove send new mouse position. + * @param scenePos new mouse position. + */ + void mouseMove(const QPointF &scenePos); + protected: void dragEnterEvent(QDragEnterEvent *event) override; void dragMoveEvent(QDragMoveEvent *event) override; @@ -96,32 +89,13 @@ protected: private slots: void RestoreOrigin() const; void on_ItemClicked(QGraphicsItem* item); + void on_SceneMouseMove(const QPointF &scenePos); private: Q_DISABLE_COPY(VPMainGraphicsView) - VMainGraphicsScene *m_scene; - - VPGraphicsSheet *m_graphicsSheet{nullptr}; - - VPGraphicsTileGrid *m_graphicsTileGrid{nullptr}; - - VPGraphicsPieceControls *m_rotationControls{nullptr}; - VPGraphicsTransformationOrigin *m_rotationOrigin{nullptr}; - VPLayoutWeakPtr m_layout; - QList m_graphicsPieces{}; - - /** - * variable to hold temporarly hte value of the show tiles - */ - bool m_showTilesTmp{false}; - - /** - * variable to hold temporarly hte value of the show grid - */ - bool m_showGridTmp{false}; bool m_allowChangeMerge{false}; qreal m_rotationSum{0}; @@ -130,12 +104,11 @@ private: qreal m_stickyTranslateX{0}; qreal m_stickyTranslateY{0}; - void ConnectPiece(VPGraphicsPiece *piece); - void RotatePiecesByAngle(qreal angle); void TranslatePiecesOn(qreal dx, qreal dy); - auto ScenePiece(const VPPiecePtr &piece) const -> VPGraphicsPiece *; + void SwitchScene(const VPSheetPtr &sheet); + void ClearSelection(); }; #endif // VPMAINGRAPHICSVIEW_H diff --git a/src/app/puzzle/vpexporter.cpp b/src/app/puzzle/vpexporter.cpp deleted file mode 100644 index f9d2b20ca..000000000 --- a/src/app/puzzle/vpexporter.cpp +++ /dev/null @@ -1,143 +0,0 @@ -#include "vpexporter.h" - -#include -#include - -#include "../vwidgets/vmaingraphicsscene.h" -#include "layout/vpsheet.h" -#include "scene/vpmaingraphicsview.h" -#include "../vobj/vobjpaintdevice.h" -#include "../vdxf/vdxfpaintdevice.h" - - -//--------------------------------------------------------------------------------------------------------------------- -VPExporter::VPExporter() -{ - -} - -//--------------------------------------------------------------------------------------------------------------------- -VPExporter::~VPExporter() -{ - -} - -//--------------------------------------------------------------------------------------------------------------------- -void VPExporter::Export(VPLayout* layout, LayoutExportFormats format, VPMainGraphicsView *mainGraphicsView) -{ - QString dir = QDir::homePath(); - QString filters(ExportFormatDescription(format)); - - // is it ok to have a null ptr hier as a parent? - QString fileName = QFileDialog::getSaveFileName(nullptr, tr("Save as"), - dir + QLatin1String("/") + layout->GetFocusedSheet()->GetName() + ExportFormatSuffix(format), - filters, nullptr -#ifdef Q_OS_LINUX - , QFileDialog::DontUseNativeDialog -#endif - ); - - if(not fileName.isEmpty()) - { - mainGraphicsView->PrepareForExport(); - - SetFileName(fileName); - - QSizeF size = QSizeF(layout->GetFocusedSheet()->GetSheetSize()); - const QRectF rect = QRectF(0, 0, size.width(), size.height()); - - SetImageRect(rect); - - switch(format) - { - case LayoutExportFormats::SVG: - ExportToSVG(mainGraphicsView->scene()); - break; - - case LayoutExportFormats::PDF: - ExportToPDF(mainGraphicsView->scene()); - break; - - case LayoutExportFormats::TIF: - ExportToTIF(mainGraphicsView->scene()); - break; - - case LayoutExportFormats::OBJ: - ExportToOBJ(mainGraphicsView->scene()); - break; - - case LayoutExportFormats::PS: - ExportToPS(mainGraphicsView->scene()); - break; - - case LayoutExportFormats::EPS: - ExportToEPS(mainGraphicsView->scene()); - break; - - default: - // just for test purpuses, to be removed: - QMessageBox msgBox; - msgBox.setText(QString("TODO VPExporter, Handling for format %1 is still missing.").arg(ExportFormatDescription(format))); - int ret = msgBox.exec(); - Q_UNUSED(ret); - break; - } - - mainGraphicsView->CleanAfterExport(); - } -} - -//--------------------------------------------------------------------------------------------------------------------- -QVector > VPExporter::InitFormats() -{ - QVector> list; - - auto InitFormat = [&list](LayoutExportFormats format) - { - list.append(std::make_pair(ExportFormatDescription(format), format)); - }; - - InitFormat(LayoutExportFormats::SVG); - InitFormat(LayoutExportFormats::PDF); -// InitFormat(LayoutExportFormats::PNG); - InitFormat(LayoutExportFormats::TIF); - - InitFormat(LayoutExportFormats::OBJ); - - InitFormat(LayoutExportFormats::PS); - InitFormat(LayoutExportFormats::EPS); - - InitFormat(LayoutExportFormats::DXF_AC1006_Flat); -/* InitFormat(LayoutExportFormats::DXF_AC1009_Flat); - InitFormat(LayoutExportFormats::DXF_AC1012_Flat); - InitFormat(LayoutExportFormats::DXF_AC1014_Flat); - InitFormat(LayoutExportFormats::DXF_AC1015_Flat); - InitFormat(LayoutExportFormats::DXF_AC1018_Flat); - InitFormat(LayoutExportFormats::DXF_AC1021_Flat); - InitFormat(LayoutExportFormats::DXF_AC1024_Flat); - InitFormat(LayoutExportFormats::DXF_AC1027_Flat); - InitFormat(LayoutExportFormats::DXF_AC1006_AAMA); - InitFormat(LayoutExportFormats::DXF_AC1009_AAMA); - InitFormat(LayoutExportFormats::DXF_AC1012_AAMA); - InitFormat(LayoutExportFormats::DXF_AC1014_AAMA); - InitFormat(LayoutExportFormats::DXF_AC1015_AAMA); - InitFormat(LayoutExportFormats::DXF_AC1018_AAMA); - InitFormat(LayoutExportFormats::DXF_AC1021_AAMA); - InitFormat(LayoutExportFormats::DXF_AC1024_AAMA); - InitFormat(LayoutExportFormats::DXF_AC1027_AAMA); - InitFormat(LayoutExportFormats::DXF_AC1006_ASTM); - InitFormat(LayoutExportFormats::DXF_AC1009_ASTM); - InitFormat(LayoutExportFormats::DXF_AC1012_ASTM); - InitFormat(LayoutExportFormats::DXF_AC1014_ASTM); - InitFormat(LayoutExportFormats::DXF_AC1015_ASTM); - InitFormat(LayoutExportFormats::DXF_AC1018_ASTM); - InitFormat(LayoutExportFormats::DXF_AC1021_ASTM); - InitFormat(LayoutExportFormats::DXF_AC1024_ASTM); - InitFormat(LayoutExportFormats::DXF_AC1027_ASTM);*/ - -// InitFormat(LayoutExportFormats::PDFTiled); -// InitFormat(LayoutExportFormats::NC); -// InitFormat(LayoutExportFormats::RLD); - - return list; -} diff --git a/src/app/puzzle/vpexporter.h b/src/app/puzzle/vpexporter.h deleted file mode 100644 index 66a2c81eb..000000000 --- a/src/app/puzzle/vpexporter.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef VPEXPORTER_H -#define VPEXPORTER_H - -#include - -#include "layout/vplayout.h" -#include "../vmisc/def.h" -#include "vcommonsettings.h" -#include "../vlayout/vlayoutdef.h" -#include "../vlayout/vlayoutexporter.h" - -//#include "../dialogs/dialogsavelayout.h" - -class VPMainGraphicsView; - -class VPExporter : VLayoutExporter -{ -public: - VPExporter(); - ~VPExporter(); - - void Export(VPLayout* layout, LayoutExportFormats format, VPMainGraphicsView *mainGraphicsView); - - /** - * @brief InitFormats - * @return returns the list of formats, that we can export in puzzle - */ - QVector > InitFormats(); - -}; - -#endif // VPEXPORTER_H diff --git a/src/app/puzzle/vpmainwindow.cpp b/src/app/puzzle/vpmainwindow.cpp index d35a72730..52b983740 100644 --- a/src/app/puzzle/vpmainwindow.cpp +++ b/src/app/puzzle/vpmainwindow.cpp @@ -41,6 +41,8 @@ #include "xml/vplayoutfilereader.h" #include "vpapplication.h" #include "../vlayout/vrawlayout.h" +#include "../vlayout/vlayoutexporter.h" +#include "../vlayout/vprintlayout.h" #include "../vmisc/vsysexits.h" #include "../vmisc/projectversion.h" #include "../ifc/xml/vlayoutconverter.h" @@ -51,6 +53,8 @@ #include "undocommands/vpundoaddsheet.h" #include "undocommands/vpundopiecerotate.h" #include "undocommands/vpundopiecemove.h" +#include "dialogs/dialogsavemanuallayout.h" +#include "../vdxf/libdxfrw/drw_base.h" #if QT_VERSION < QT_VERSION_CHECK(5, 12, 0) #include "../vmisc/backport/qscopeguard.h" @@ -70,6 +74,29 @@ QT_WARNING_POP namespace { +//--------------------------------------------------------------------------------------------------------------------- +auto CreateLayoutPath(const QString &path) -> bool +{ + bool usedNotExistedDir = true; + QDir dir(path); + dir.setPath(path); + if (not dir.exists(path)) + { + usedNotExistedDir = dir.mkpath(QChar('.')); + } + return usedNotExistedDir; +} + +//--------------------------------------------------------------------------------------------------------------------- +void RemoveLayoutPath(const QString &path, bool usedNotExistedDir) +{ + if (usedNotExistedDir) + { + QDir dir(path); + dir.rmpath(QChar('.')); + } +} + //--------------------------------------------------------------------------------------------------------------------- void SetDoubleSpinBoxValue(QDoubleSpinBox *spinBox, qreal value) { @@ -118,6 +145,19 @@ auto PiecesBoundingRect(const QList &selectedPieces) -> QRectF } } // namespace +struct VPExportData +{ + LayoutExportFormats format{LayoutExportFormats::SVG}; + QList sheets{}; + QString path{}; + QString fileName{}; + qreal xScale{1.}; + qreal yScale{1.}; + bool isBinaryDXF{false}; + bool textAsPaths{false}; + bool exportUnified{true}; +}; + //--------------------------------------------------------------------------------------------------------------------- VPMainWindow::VPMainWindow(const VPCommandLinePtr &cmd, QWidget *parent) : VAbstractMainWindow(parent), @@ -141,7 +181,7 @@ VPMainWindow::VPMainWindow(const VPCommandLinePtr &cmd, QWidget *parent) : }); connect(m_layout.get(), &VPLayout::ActiveSheetChanged, this, [this]() { - m_tileFactory->refreshTileInfos(); + m_layout->TileFactory()->refreshTileInfos(); m_graphicsView->RefreshLayout(); SetPropertyTabSheetData(); }); @@ -151,10 +191,6 @@ VPMainWindow::VPMainWindow(const VPCommandLinePtr &cmd, QWidget *parent) : LayoutWasSaved(clean); }); - // init the tile factory - m_tileFactory = new VPTileFactory(m_layout, VPApplication::VApp()->Settings()); - m_tileFactory->refreshTileInfos(); - // init status bar statusBar()->addPermanentWidget(m_statusLabel, 1); @@ -288,10 +324,10 @@ auto VPMainWindow::LoadFile(QString path) -> bool SetPropertiesData(); m_carrousel->Refresh(); - m_graphicsView->RefreshLayout(); - m_graphicsView->RefreshPieces(); - m_tileFactory->refreshTileInfos(); + m_graphicsView->on_ActiveSheetChanged(m_layout->GetFocusedSheet()); + m_layout->TileFactory()->refreshTileInfos(); m_layout->CheckPiecesPositionValidity(); + VMainGraphicsView::NewSceneRect(m_graphicsView->scene(), m_graphicsView); return true; @@ -428,40 +464,12 @@ void VPMainWindow::InitZoom() void VPMainWindow::SetupMenu() { // most of the actions are connected through name convention (auto-connection) - + // File // -------------------- connects the actions for the file menu ui->actionNew->setShortcuts(QKeySequence::New); ui->actionSave->setShortcuts(QKeySequence::Save); ui->actionSaveAs->setShortcuts(QKeySequence::SaveAs); - connect(ui->actionExit, &QAction::triggered, this, &VPMainWindow::close); - ui->actionExit->setShortcuts(QKeySequence::Quit); - - // -------------------- connects the actions for the windows menu - // TODO : initialise the entries for the different windows - - // Add dock properties action - QAction* actionDockWidgetToolOptions = ui->dockWidgetProperties->toggleViewAction(); - ui->menuEdit->addAction(actionDockWidgetToolOptions); - - auto *separatorAct = new QAction(this); - separatorAct->setSeparator(true); - ui->menuEdit->addAction(separatorAct); - - // Add Undo/Redo actions. - undoAction = m_layout->UndoStack()->createUndoAction(this, tr("&Undo")); - undoAction->setShortcuts(QKeySequence::Undo); - undoAction->setIcon(QIcon::fromTheme("edit-undo")); - ui->menuEdit->addAction(undoAction); - ui->toolBarUndoCommands->addAction(undoAction); - - redoAction = m_layout->UndoStack()->createRedoAction(this, tr("&Redo")); - redoAction->setShortcuts(QKeySequence::Redo); - redoAction->setIcon(QIcon::fromTheme("edit-redo")); - ui->menuEdit->addAction(redoAction); - ui->toolBarUndoCommands->addAction(redoAction); - - // File m_recentFileActs.fill(nullptr); for (auto & recentFileAct : m_recentFileActs) { @@ -490,6 +498,34 @@ void VPMainWindow::SetupMenu() // Actions for recent files loaded by a puzzle window application. UpdateRecentFileActions(); + connect(ui->actionExit, &QAction::triggered, this, &VPMainWindow::close); + ui->actionExit->setShortcuts(QKeySequence::Quit); + + // Layout + connect(ui->actionExportLayout, &QAction::triggered, this, &VPMainWindow::on_ExportLayout); + + // Sheet + connect(ui->actionExportSheet, &QAction::triggered, this, &VPMainWindow::on_ExportSheet); + + // Add dock properties action + ui->menuSheet->addSeparator(); + QAction* actionDockWidgetToolOptions = ui->dockWidgetProperties->toggleViewAction(); + ui->menuSheet->addAction(actionDockWidgetToolOptions); + ui->menuSheet->addSeparator(); + + // Add Undo/Redo actions. + undoAction = m_layout->UndoStack()->createUndoAction(this, tr("&Undo")); + undoAction->setShortcuts(QKeySequence::Undo); + undoAction->setIcon(QIcon::fromTheme("edit-undo")); + ui->menuSheet->addAction(undoAction); + ui->toolBarUndoCommands->addAction(undoAction); + + redoAction = m_layout->UndoStack()->createRedoAction(this, tr("&Redo")); + redoAction->setShortcuts(QKeySequence::Redo); + redoAction->setIcon(QIcon::fromTheme("edit-redo")); + ui->menuSheet->addAction(redoAction); + ui->toolBarUndoCommands->addAction(redoAction); + // Window connect(ui->menuWindow, &QMenu::aboutToShow, this, [this]() { @@ -726,7 +762,7 @@ void VPMainWindow::InitPropertyTabCurrentSheet() { sheet->RemoveUnusedLength(); LayoutWasSaved(false); - m_tileFactory->refreshTileInfos(); + m_layout->TileFactory()->refreshTileInfos(); m_graphicsView->RefreshLayout(); m_graphicsView->RefreshPieces(); SetPropertyTabSheetData(); @@ -763,7 +799,7 @@ void VPMainWindow::InitPropertyTabCurrentSheet() { sheet->SetIgnoreMargins(state != 0); LayoutWasSaved(false); - m_tileFactory->refreshTileInfos(); + m_layout->TileFactory()->refreshTileInfos(); m_graphicsView->RefreshLayout(); sheet->ValidatePiecesOutOfBound(); @@ -772,6 +808,8 @@ void VPMainWindow::InitPropertyTabCurrentSheet() }); ui->groupBoxSheetGrid->setVisible(false); // temporary hide + + connect(ui->pushButtonSheetExport, &QPushButton::clicked, this, &VPMainWindow::on_ExportSheet); } //--------------------------------------------------------------------------------------------------------------------- @@ -826,7 +864,7 @@ void VPMainWindow::InitPropertyTabTiles() m_layout->LayoutSettings().SetIgnoreTilesMargins(state != 0); LayoutWasSaved(false); - m_tileFactory->refreshTileInfos(); + m_layout->TileFactory()->refreshTileInfos(); m_graphicsView->RefreshLayout(); VMainGraphicsView::NewSceneRect(m_graphicsView->scene(), m_graphicsView); } @@ -941,13 +979,7 @@ void VPMainWindow::InitPropertyTabLayout() } }); - connect(ui->pushButtonLayoutExport, &QPushButton::clicked, this, [this]() - { - if (not m_layout.isNull()) - { - // TODO export layout - } - }); + connect(ui->pushButtonLayoutExport, &QPushButton::clicked, this, &VPMainWindow::on_ExportLayout); } //--------------------------------------------------------------------------------------------------------------------- @@ -1045,8 +1077,7 @@ void VPMainWindow::SetPropertyTabSheetData() if (not sheet.isNull()) { ui->groupBoxSheetInfos->setDisabled(false); - VPSheetPtr sheet = m_layout->GetFocusedSheet(); - SetLineEditValue(ui->lineEditSheetName, not sheet.isNull() ? sheet->GetName() : QString()); + SetLineEditValue(ui->lineEditSheetName, sheet->GetName()); ui->groupBoxPaperFormat->setDisabled(false); const qint32 indexUnit = ui->comboBoxLayoutUnit->findData(UnitsToStr(m_layout->LayoutSettings().GetUnit())); @@ -1196,8 +1227,6 @@ void VPMainWindow::SetPropertyTabTilesData() ui->groupBoxTilesControl->setDisabled(false); SetCheckBoxValue(ui->checkBoxTilesShowTiles, m_layout->LayoutSettings().GetShowTiles()); - - ui->groupBoxTilesExport->setDisabled(false); } else { @@ -1218,8 +1247,6 @@ void VPMainWindow::SetPropertyTabTilesData() ui->groupBoxTilesControl->setDisabled(true); SetCheckBoxValue(ui->checkBoxTilesShowTiles, false); - - ui->groupBoxTilesExport->setDisabled(true); } } @@ -1280,7 +1307,7 @@ void VPMainWindow::SetPropertyTabLayoutData() //--------------------------------------------------------------------------------------------------------------------- void VPMainWindow::InitMainGraphics() { - m_graphicsView = new VPMainGraphicsView(m_layout, m_tileFactory, this); + m_graphicsView = new VPMainGraphicsView(m_layout, this); m_graphicsView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn); m_graphicsView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); ui->centralWidget->layout()->addWidget(m_graphicsView); @@ -1288,7 +1315,7 @@ void VPMainWindow::InitMainGraphics() m_graphicsView->RefreshLayout(); connect(m_graphicsView, &VPMainGraphicsView::ScaleChanged, this, &VPMainWindow::on_ScaleChanged); - connect(m_graphicsView->GetScene(), &VMainGraphicsScene::mouseMove, this, &VPMainWindow::on_MouseMoved); + connect(m_graphicsView, &VPMainGraphicsView::mouseMove, this, &VPMainWindow::on_MouseMoved); connect(m_layout.get(), &VPLayout::PieceSheetChanged, m_carrousel, &VPCarrousel::Refresh); } @@ -1495,80 +1522,6 @@ auto VPMainWindow::MaybeSave() -> bool return true; } -//--------------------------------------------------------------------------------------------------------------------- -void VPMainWindow::generateTiledPdf(QString fileName) -{ -// if(not fileName.isEmpty()) -// { -// m_graphicsView->PrepareForExport(); -// m_tileFactory->refreshTileInfos(); - -// PageOrientation tilesOrientation = m_layout->LayoutSettings().GetTilesOrientation(); - -// // ------------- Set up the printer -// QScopedPointer printer(new QPrinter()); - -// printer->setCreator(QGuiApplication::applicationDisplayName()+QChar(QChar::Space)+ -// QCoreApplication::applicationVersion()); -// printer->setPageOrientation(QPageLayout::Portrait); // in the pdf file the pages should always be in portrait - -// // here we might need to so some rounding for the size. -// printer->setPageSize(QPageSize(m_layout->LayoutSettings().GetTilesSize(Unit::Mm), -// QPageSize::Millimeter)); -// printer->setFullPage(true); - -// #ifdef Q_OS_MAC -// printer->setOutputFormat(QPrinter::NativeFormat); -// #else -// printer->setOutputFormat(QPrinter::PdfFormat); -// #endif - -// printer->setOutputFileName(fileName); -// printer->setResolution(static_cast(PrintDPI)); -// printer->setDocName(m_layout->GetFocusedSheet()->GetName()); - -// // ------------- Set up the painter -// QPainter painter; -// if (not painter.begin(printer.data())) -// { // failed to open file -// qCritical() << tr("Failed to open file, is it writable?"); -// return; -// } -// painter.setFont( QFont( QStringLiteral("Arial"), 8, QFont::Normal ) ); -// painter.setRenderHint(QPainter::Antialiasing, true); -// painter.setBrush ( QBrush ( Qt::NoBrush ) ); - -// if(tilesOrientation == PageOrientation::Landscape) -// { -// // The landscape tiles have to be rotated, because the pages -// // stay portrait in the pdf -// painter.rotate(90); -// painter.translate(0, -ToPixel(printer->pageRect(QPrinter::Millimeter).width(), Unit::Mm)); -// } - -// for(int row=0;rowgetRowNb();row++) // for each row of the tiling grid -// { -// for(int col=0;colgetColNb();col++) // for each column of tiling grid -// { -// if(not (row == 0 && col == 0)) -// { -// if (not printer->newPage()) -// { -// qWarning("failed in flushing page to disk, disk full?"); -// return; -// } -// } - -// m_tileFactory->drawTile(&painter, m_graphicsView, row, col); -// } -// } - -// painter.end(); - -// m_graphicsView->CleanAfterExport(); -// } -} - //--------------------------------------------------------------------------------------------------------------------- void VPMainWindow::CreateWindowMenu(QMenu *menu) { @@ -1976,6 +1929,587 @@ void VPMainWindow::RotatePiecesToGrainline() } } +//--------------------------------------------------------------------------------------------------------------------- +void VPMainWindow::ExportData(const VPExportData &data) +{ + if (data.format == LayoutExportFormats::DXF_AC1006_AAMA || + data.format == LayoutExportFormats::DXF_AC1009_AAMA || + data.format == LayoutExportFormats::DXF_AC1012_AAMA || + data.format == LayoutExportFormats::DXF_AC1014_AAMA || + data.format == LayoutExportFormats::DXF_AC1015_AAMA || + data.format == LayoutExportFormats::DXF_AC1018_AAMA || + data.format == LayoutExportFormats::DXF_AC1021_AAMA || + data.format == LayoutExportFormats::DXF_AC1024_AAMA || + data.format == LayoutExportFormats::DXF_AC1027_AAMA || + data.format == LayoutExportFormats::DXF_AC1006_ASTM || + data.format == LayoutExportFormats::DXF_AC1009_ASTM || + data.format == LayoutExportFormats::DXF_AC1012_ASTM || + data.format == LayoutExportFormats::DXF_AC1014_ASTM || + data.format == LayoutExportFormats::DXF_AC1015_ASTM || + data.format == LayoutExportFormats::DXF_AC1018_ASTM || + data.format == LayoutExportFormats::DXF_AC1021_ASTM || + data.format == LayoutExportFormats::DXF_AC1024_ASTM || + data.format == LayoutExportFormats::DXF_AC1027_ASTM || + data.format == LayoutExportFormats::RLD) + { + for (int i = 0; i < data.sheets.size(); ++i) + { + QString name; + + if (data.sheets.size() > 1) + { + name = data.path + '/' + data.fileName + + QString::number(i+1) + VLayoutExporter::ExportFormatSuffix(data.format); + } + else + { + name = data.path + '/' + data.fileName + VLayoutExporter::ExportFormatSuffix(data.format); + } + + VPSheetPtr sheet = data.sheets.at(i); + ExportApparelLayout(data, sheet->GetAsLayoutPieces(), name, sheet->GetSheetSize().toSize()); + } + } + else + { + ExportFlatLayout(data); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPMainWindow::ExportApparelLayout(const VPExportData &data, const QVector &details, + const QString &name, const QSize &size) const +{ + const QString path = data.path; + bool usedNotExistedDir = CreateLayoutPath(path); + if (not usedNotExistedDir) + { + qCritical() << tr("Can't create a path"); + return; + } + + VPApplication::VApp()->PuzzleSettings()->SetPathManualLayouts(path); + + QT_WARNING_PUSH + QT_WARNING_DISABLE_GCC("-Wnoexcept") + + VLayoutExporter exporter; + + QT_WARNING_POP + + exporter.SetFileName(name); + exporter.SetImageRect(QRectF(0, 0, size.width(), size.height())); + exporter.SetXScale(data.xScale); + exporter.SetYScale(data.yScale); + exporter.SetBinaryDxfFormat(data.isBinaryDXF); + + switch (data.format) + { + case LayoutExportFormats::DXF_AC1006_ASTM: + exporter.SetDxfVersion(DRW::AC1006); + exporter.ExportToASTMDXF(details); + break; + case LayoutExportFormats::DXF_AC1009_ASTM: + exporter.SetDxfVersion(DRW::AC1009); + exporter.ExportToASTMDXF(details); + break; + case LayoutExportFormats::DXF_AC1012_ASTM: + exporter.SetDxfVersion(DRW::AC1012); + exporter.ExportToASTMDXF(details); + break; + case LayoutExportFormats::DXF_AC1014_ASTM: + exporter.SetDxfVersion(DRW::AC1014); + exporter.ExportToASTMDXF(details); + break; + case LayoutExportFormats::DXF_AC1015_ASTM: + exporter.SetDxfVersion(DRW::AC1015); + exporter.ExportToASTMDXF(details); + break; + case LayoutExportFormats::DXF_AC1018_ASTM: + exporter.SetDxfVersion(DRW::AC1018); + exporter.ExportToASTMDXF(details); + break; + case LayoutExportFormats::DXF_AC1021_ASTM: + exporter.SetDxfVersion(DRW::AC1021); + exporter.ExportToASTMDXF(details); + break; + case LayoutExportFormats::DXF_AC1024_ASTM: + exporter.SetDxfVersion(DRW::AC1024); + exporter.ExportToASTMDXF(details); + break; + case LayoutExportFormats::DXF_AC1027_ASTM: + exporter.SetDxfVersion(DRW::AC1027); + exporter.ExportToASTMDXF(details); + break; + case LayoutExportFormats::DXF_AC1006_AAMA: + exporter.SetDxfVersion(DRW::AC1006); + exporter.ExportToAAMADXF(details); + break; + case LayoutExportFormats::DXF_AC1009_AAMA: + exporter.SetDxfVersion(DRW::AC1009); + exporter.ExportToAAMADXF(details); + break; + case LayoutExportFormats::DXF_AC1012_AAMA: + exporter.SetDxfVersion(DRW::AC1012); + exporter.ExportToAAMADXF(details); + break; + case LayoutExportFormats::DXF_AC1014_AAMA: + exporter.SetDxfVersion(DRW::AC1014); + exporter.ExportToAAMADXF(details); + break; + case LayoutExportFormats::DXF_AC1015_AAMA: + exporter.SetDxfVersion(DRW::AC1015); + exporter.ExportToAAMADXF(details); + break; + case LayoutExportFormats::DXF_AC1018_AAMA: + exporter.SetDxfVersion(DRW::AC1018); + exporter.ExportToAAMADXF(details); + break; + case LayoutExportFormats::DXF_AC1021_AAMA: + exporter.SetDxfVersion(DRW::AC1021); + exporter.ExportToAAMADXF(details); + break; + case LayoutExportFormats::DXF_AC1024_AAMA: + exporter.SetDxfVersion(DRW::AC1024); + exporter.ExportToAAMADXF(details); + break; + case LayoutExportFormats::DXF_AC1027_AAMA: + exporter.SetDxfVersion(DRW::AC1027); + exporter.ExportToAAMADXF(details); + break; + case LayoutExportFormats::RLD: + exporter.ExportToRLD(details); + break; + default: + qDebug() << "Can't recognize file type." << Q_FUNC_INFO; + break; + } + + RemoveLayoutPath(path, usedNotExistedDir); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPMainWindow::ExportFlatLayout(const VPExportData &data) +{ + const QString path = data.path; + bool usedNotExistedDir = CreateLayoutPath(path); + if (not usedNotExistedDir) + { + qCritical() << tr("Can't create a path"); + return; + } + + m_layout->RefreshScenePieces(); + + VPApplication::VApp()->PuzzleSettings()->SetPathManualLayouts(path); + + if (data.format == LayoutExportFormats::PDFTiled) + { + ExportPdfTiledFile(data); + } + else if ((data.format == LayoutExportFormats::PDF || data.format == LayoutExportFormats::PS || + data.format == LayoutExportFormats::EPS) && data.exportUnified) + { + ExportUnifiedPdfFile(data); + } + else + { + ExportScene(data); + } + + RemoveLayoutPath(path, usedNotExistedDir); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPMainWindow::ExportScene(const VPExportData &data) +{ + QT_WARNING_PUSH + QT_WARNING_DISABLE_GCC("-Wnoexcept") + + VLayoutExporter exporter; + + QT_WARNING_POP + + exporter.SetXScale(data.xScale); + exporter.SetYScale(data.yScale); + exporter.SetDescription(m_layout->LayoutSettings().GetDescription()); + exporter.SetBinaryDxfFormat(data.isBinaryDXF); + + QList sheets = data.sheets; + + for (int i=0; i < sheets.size(); ++i) + { + VPSheetPtr sheet = sheets.at(i); + if (sheet.isNull()) + { + continue; + } + + sheet->SceneData()->PrepareForExport(); + sheet->SceneData()->SetTextAsPaths(data.textAsPaths); + + exporter.SetMargins(sheet->GetSheetMargins()); + exporter.SetTitle(sheet->GetName()); + exporter.SetIgnorePrinterMargins(sheet->IgnoreMargins()); + + QString name; + if (sheets.size() > 1) + { + name = data.path + '/' + data.fileName + QString::number(i+1) + + VLayoutExporter::ExportFormatSuffix(data.format); + } + else + { + name = data.path + '/' + data.fileName + VLayoutExporter::ExportFormatSuffix(data.format); + } + + exporter.SetFileName(name); + exporter.SetImageRect(sheet->GetMarginsRect()); + + switch (data.format) + { + case LayoutExportFormats::SVG: + exporter.SetPen(QPen(Qt::black, VAbstractApplication::VApp()->Settings()->WidthHairLine(), + Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); + exporter.ExportToSVG(sheet->SceneData()->Scene()); + break; + case LayoutExportFormats::PDF: + exporter.SetPen(QPen(Qt::black, VAbstractApplication::VApp()->Settings()->WidthHairLine(), + Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); + exporter.ExportToPDF(sheet->SceneData()->Scene()); + break; + case LayoutExportFormats::PNG: + exporter.SetPen(QPen(Qt::black, VAbstractApplication::VApp()->Settings()->WidthHairLine(), + Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); + exporter.ExportToPNG(sheet->SceneData()->Scene()); + break; + case LayoutExportFormats::OBJ: + exporter.ExportToOBJ(sheet->SceneData()->Scene()); + break; + case LayoutExportFormats::PS: + exporter.SetPen(QPen(Qt::black, VAbstractApplication::VApp()->Settings()->WidthHairLine(), + Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); + exporter.ExportToPS(sheet->SceneData()->Scene()); + break; + case LayoutExportFormats::EPS: + exporter.SetPen(QPen(Qt::black, VAbstractApplication::VApp()->Settings()->WidthHairLine(), + Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); + exporter.ExportToEPS(sheet->SceneData()->Scene()); + break; + case LayoutExportFormats::DXF_AC1006_Flat: + exporter.SetDxfVersion(DRW::AC1006); + exporter.ExportToFlatDXF(sheet->SceneData()->Scene(), sheet->SceneData()->GraphicsPiecesAsItems()); + break; + case LayoutExportFormats::DXF_AC1009_Flat: + exporter.SetDxfVersion(DRW::AC1009); + exporter.ExportToFlatDXF(sheet->SceneData()->Scene(), sheet->SceneData()->GraphicsPiecesAsItems()); + break; + case LayoutExportFormats::DXF_AC1012_Flat: + exporter.SetDxfVersion(DRW::AC1012); + exporter.ExportToFlatDXF(sheet->SceneData()->Scene(), sheet->SceneData()->GraphicsPiecesAsItems()); + break; + case LayoutExportFormats::DXF_AC1014_Flat: + exporter.SetDxfVersion(DRW::AC1014); + exporter.ExportToFlatDXF(sheet->SceneData()->Scene(), sheet->SceneData()->GraphicsPiecesAsItems()); + break; + case LayoutExportFormats::DXF_AC1015_Flat: + exporter.SetDxfVersion(DRW::AC1015); + exporter.ExportToFlatDXF(sheet->SceneData()->Scene(), sheet->SceneData()->GraphicsPiecesAsItems()); + break; + case LayoutExportFormats::DXF_AC1018_Flat: + exporter.SetDxfVersion(DRW::AC1018); + exporter.ExportToFlatDXF(sheet->SceneData()->Scene(), sheet->SceneData()->GraphicsPiecesAsItems()); + break; + case LayoutExportFormats::DXF_AC1021_Flat: + exporter.SetDxfVersion(DRW::AC1021); + exporter.ExportToFlatDXF(sheet->SceneData()->Scene(), sheet->SceneData()->GraphicsPiecesAsItems()); + break; + case LayoutExportFormats::DXF_AC1024_Flat: + exporter.SetDxfVersion(DRW::AC1024); + exporter.ExportToFlatDXF(sheet->SceneData()->Scene(), sheet->SceneData()->GraphicsPiecesAsItems()); + break; + case LayoutExportFormats::DXF_AC1027_Flat: + exporter.SetDxfVersion(DRW::AC1027); + exporter.ExportToFlatDXF(sheet->SceneData()->Scene(), sheet->SceneData()->GraphicsPiecesAsItems()); + break; + case LayoutExportFormats::TIF: + exporter.SetPen(QPen(Qt::black, VAbstractApplication::VApp()->Settings()->WidthHairLine(), + Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); + exporter.ExportToTIF(sheet->SceneData()->Scene()); + break; + default: + qDebug() << "Can't recognize file type." << Q_FUNC_INFO; + break; + } + + sheet->SceneData()->CleanAfterExport(); + sheet->SceneData()->SetTextAsPaths(false); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPMainWindow::ExportUnifiedPdfFile(const VPExportData &data) +{ + const QString name = data.path + '/' + data.fileName + VLayoutExporter::ExportFormatSuffix(data.format); + + if (data.format == LayoutExportFormats::PDF) + { + GenerateUnifiedPdfFile(data, name); + } + else if (data.format == LayoutExportFormats::PS) + { + QTemporaryFile tmp; + if (tmp.open()) + { + GenerateUnifiedPdfFile(data, tmp.fileName()); + VLayoutExporter::PdfToPs(QStringList{tmp.fileName(), name}); + } + } + else if (data.format == LayoutExportFormats::EPS) + { + QTemporaryFile tmp; + if (tmp.open()) + { + GenerateUnifiedPdfFile(data, tmp.fileName()); + VLayoutExporter::PdfToPs(QStringList{QStringLiteral("-eps"), tmp.fileName(), name}); + } + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPMainWindow::GenerateUnifiedPdfFile(const VPExportData &data, const QString &name) +{ + QPrinter printer; + printer.setCreator(QGuiApplication::applicationDisplayName() + QChar(QChar::Space) + + QCoreApplication::applicationVersion()); + printer.setOutputFormat(QPrinter::PdfFormat); + printer.setOutputFileName(name); + printer.setDocName(QFileInfo(name).fileName()); + printer.setResolution(static_cast(PrintDPI)); + printer.setPageOrientation(QPageLayout::Portrait); + + QPainter painter; + + bool firstPage = true; + + for (const auto& sheet : data.sheets) + { + QMarginsF margins; + if (not sheet->IgnoreMargins()) + { + margins = sheet->GetSheetMargins(); + } + + QRectF imageRect = sheet->GetMarginsRect(); + qreal width = FromPixel(imageRect.width() * data.xScale + margins.left() + margins.right(), Unit::Mm); + qreal height = FromPixel(imageRect.height() * data.yScale + margins.top() + margins.bottom(), Unit::Mm); + + if (firstPage) + { + if (not printer.setPageSize(QPageSize(QSizeF(width, height), QPageSize::Millimeter))) + { + qWarning() << tr("Cannot set printer page size"); + } + + if (not painter.begin(&printer)) + { // failed to open file + qCritical() << qUtf8Printable(tr("Can't open file '%1'").arg(name)); + return; + } + + painter.setRenderHint(QPainter::Antialiasing, true); + painter.setPen(QPen(Qt::black, VAbstractApplication::VApp()->Settings()->WidthHairLine(), + Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); + painter.setBrush(QBrush(Qt::NoBrush)); + painter.scale(data.xScale, data.yScale); + } + else + { + if (not printer.newPage()) + { + qCritical() << tr("Failed in flushing page to disk, disk full?"); + return; + } + + if (not printer.setPageSize(QPageSize(QSizeF(width, height), QPageSize::Millimeter))) + { + qWarning() << tr("Cannot set printer page size"); + } + } + + if (not sheet->IgnoreMargins()) + { + const qreal left = FromPixel(margins.left(), Unit::Mm); + const qreal top = FromPixel(margins.top(), Unit::Mm); + const qreal right = FromPixel(margins.right(), Unit::Mm); + const qreal bottom = FromPixel(margins.bottom(), Unit::Mm); + + if (not printer.setPageMargins(QMarginsF(left, top, right, bottom), QPageLayout::Millimeter)) + { + qWarning() << tr("Cannot set printer margins"); + } + } + else + { + printer.setFullPage(sheet->IgnoreMargins()); + } + + sheet->SceneData()->PrepareForExport(); + sheet->SceneData()->Scene()->render(&painter, VPrintLayout::SceneTargetRect(&printer, imageRect), imageRect, + Qt::IgnoreAspectRatio); + sheet->SceneData()->CleanAfterExport(); + + firstPage = false; + } + + painter.end(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPMainWindow::ExportPdfTiledFile(const VPExportData &data) +{ + QPrinter printer; +#ifdef Q_OS_MAC + printer.setOutputFormat(QPrinter::NativeFormat); +#else + printer.setOutputFormat(QPrinter::PdfFormat); +#endif + printer.setCreator(QGuiApplication::applicationDisplayName() + QChar(QChar::Space) + + QCoreApplication::applicationVersion()); + + QPageLayout::Orientation tiledPDFOrientation = m_layout->LayoutSettings().GetTilesOrientation(); + + printer.setPageOrientation(tiledPDFOrientation); + + if (not printer.setPageSize(QPageSize(m_layout->LayoutSettings().GetTilesSize(Unit::Mm), QPageSize::Millimeter))) + { + qWarning() << tr("Cannot set printer page size"); + } + + printer.setFullPage(m_layout->LayoutSettings().IgnoreTilesMargins()); + + if (not m_layout->LayoutSettings().IgnoreTilesMargins()) + { + QMarginsF tiledMargins = m_layout->LayoutSettings().GetTilesMargins(); + QMarginsF printerMargins; + if(tiledPDFOrientation == QPageLayout::Landscape) + { + // because when painting we have a -90rotation in landscape mode, + // see function PrintPages. + printerMargins = QMarginsF(tiledMargins.bottom(), tiledMargins.left(), tiledMargins.top(), + tiledMargins.right()); + } + else + { + printerMargins = tiledMargins; + } + + if (not printer.setPageMargins(UnitConvertor(printerMargins, Unit::Px, Unit::Mm), QPageLayout::Millimeter)) + { + qWarning() << tr("Cannot set printer margins"); + } + } + + printer.setResolution(static_cast(PrintDPI)); + + QPainter painter; + + // when tiled, the landscape tiles have to be rotated, because the pages + // stay portrait in the pdf + if(tiledPDFOrientation == QPageLayout::Landscape) + { + const int angle = -90; + painter.rotate(angle); + painter.translate(-ToPixel(printer.pageRect(QPrinter::Millimeter).height(), Unit::Mm), 0); + } + + if (data.exportUnified) + { + const QString name = data.path + '/' + data.fileName + VLayoutExporter::ExportFormatSuffix(data.format); + + printer.setOutputFileName(name); + printer.setDocName(QFileInfo(name).baseName()); + + if (not painter.begin(&printer)) + { // failed to open file + qCritical() << tr("Failed to open file, is it writable?"); + return; + } + + painter.setPen(QPen(Qt::black, VAbstractApplication::VApp()->Settings()->WidthMainLine(), Qt::SolidLine, + Qt::RoundCap, Qt::RoundJoin)); + painter.setBrush(QBrush(Qt::NoBrush)); + painter.setRenderHint(QPainter::Antialiasing, true); + + bool firstSheet = true; + for (const auto& sheet : data.sheets) + { + GeneratePdfTiledFile(sheet, &painter, &printer, firstSheet); + firstSheet = false; + } + + painter.end(); + } + else + { + for (int i = 0; i < data.sheets.size(); ++i) + { + const QString name = data.path + '/' + data.fileName + QString::number(i+1) + + VLayoutExporter::ExportFormatSuffix(data.format); + + printer.setOutputFileName(name); + printer.setDocName(QFileInfo(name).baseName()); + + if (not painter.begin(&printer)) + { // failed to open file + qCritical() << tr("Failed to open file, is it writable?"); + return; + } + + painter.setPen(QPen(Qt::black, VAbstractApplication::VApp()->Settings()->WidthMainLine(), Qt::SolidLine, + Qt::RoundCap, Qt::RoundJoin)); + painter.setBrush(QBrush(Qt::NoBrush)); + painter.setRenderHint(QPainter::Antialiasing, true); + + bool firstSheet = true; + GeneratePdfTiledFile(data.sheets.at(i), &painter, &printer, firstSheet); + + painter.end(); + } + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPMainWindow::GeneratePdfTiledFile(const VPSheetPtr &sheet, QPainter *painter, QPrinter *printer, bool firstSheet) +{ + SCASSERT(not sheet.isNull()) + SCASSERT(painter != nullptr) + SCASSERT(printer != nullptr) + + sheet->SceneData()->PrepareForExport(); + m_layout->TileFactory()->refreshTileInfos(); + sheet->SceneData()->SetTextAsPaths(false); + + for(int row=0; row < m_layout->TileFactory()->RowNb(sheet); row++) // for each row of the tiling grid + { + for(int col=0; col < m_layout->TileFactory()->ColNb(sheet); col++) // for each column of tiling grid + { + if(not (row == 0 && col == 0) || not firstSheet) + { + if (not printer->newPage()) + { + qWarning("failed in flushing page to disk, disk full?"); + return; + } + } + + m_layout->TileFactory()->drawTile(painter, printer, sheet, row, col); + } + } + + sheet->SceneData()->CleanAfterExport(); +} + //--------------------------------------------------------------------------------------------------------------------- void VPMainWindow::on_actionNew_triggered() { @@ -2257,7 +2791,7 @@ void VPMainWindow::on_SheetSizeChanged() CorrectMaxMargins(); LayoutWasSaved(false); - m_tileFactory->refreshTileInfos(); + m_layout->TileFactory()->refreshTileInfos(); m_graphicsView->RefreshLayout(); } } @@ -2282,7 +2816,7 @@ void VPMainWindow::on_SheetOrientationChanged(bool checked) SheetPaperSizeChanged(); CorrectMaxMargins(); LayoutWasSaved(false); - m_tileFactory->refreshTileInfos(); + m_layout->TileFactory()->refreshTileInfos(); m_graphicsView->RefreshLayout(); } } @@ -2343,7 +2877,7 @@ void VPMainWindow::on_TilesSizeChanged() CorrectMaxMargins(); LayoutWasSaved(false); - m_tileFactory->refreshTileInfos(); + m_layout->TileFactory()->refreshTileInfos(); m_graphicsView->RefreshLayout(); } } @@ -2364,7 +2898,7 @@ void VPMainWindow::on_TilesOrientationChanged(bool checked) TilePaperSizeChanged(); CorrectMaxMargins(); LayoutWasSaved(false); - m_tileFactory->refreshTileInfos(); + m_layout->TileFactory()->refreshTileInfos(); m_graphicsView->RefreshLayout(); } } @@ -2380,38 +2914,13 @@ void VPMainWindow::on_TilesMarginChanged() ui->doubleSpinBoxTileMarginRight->value(), ui->doubleSpinBoxTileMarginBottom->value()); LayoutWasSaved(false); - m_tileFactory->refreshTileInfos(); + m_layout->TileFactory()->refreshTileInfos(); m_graphicsView->RefreshLayout(); } VMainGraphicsView::NewSceneRect(m_graphicsView->scene(), m_graphicsView); } -//--------------------------------------------------------------------------------------------------------------------- -void VPMainWindow::on_pushButtonTilesExport_clicked() -{ - QString dir = QDir::homePath(); - QString filters(tr("PDF Files") + QLatin1String("(*.pdf)")); - QString fileName = QFileDialog::getSaveFileName(this, tr("Save as"), - dir + QLatin1String("/") + m_layout->GetFocusedSheet()->GetName() + QLatin1String(".pdf"), - filters, nullptr -#ifdef Q_OS_LINUX - , QFileDialog::DontUseNativeDialog -#endif - ); - - generateTiledPdf(fileName); -} - -//--------------------------------------------------------------------------------------------------------------------- -void VPMainWindow::on_pushButtonSheetExport_clicked() -{ -// LayoutExportFormats format = static_cast(ui->comboBoxSheetExportFormat->currentData().toInt()); - -// VPExporter exporter; -// exporter.Export(m_layout.get(), format, m_graphicsView); -} - //--------------------------------------------------------------------------------------------------------------------- void VPMainWindow::on_CarrouselLocationChanged(Qt::DockWidgetArea area) { @@ -2826,6 +3335,128 @@ void VPMainWindow::on_ConvertPaperSize() CorrectMaxMargins(); } +//--------------------------------------------------------------------------------------------------------------------- +void VPMainWindow::on_ExportLayout() +{ + if (m_layout.isNull()) + { + return; + } + + QList sheets = m_layout->GetSheets(); + if (sheets.isEmpty()) + { + return; + } + + DialogSaveManualLayout dialog(sheets.size(), false, m_layout->LayoutSettings().GetTitle(), this); + + if (dialog.exec() == QDialog::Rejected) + { + return; + } + + // TODO add checks for out of bound and pieces superpositions + + VPExportData data; + data.format = dialog.Format(); + data.path = dialog.Path(); + data.fileName = dialog.FileName(); + data.sheets = sheets; + data.xScale = dialog.GetXScale(); + data.yScale = dialog.GetYScale(); + data.isBinaryDXF = dialog.IsBinaryDXFFormat(); + data.textAsPaths = dialog.IsTextAsPaths(); + data.exportUnified = dialog.IsExportUnified(); + + ExportData(data); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPMainWindow::on_ExportSheet() +{ + if (m_layout.isNull()) + { + return; + } + + VPSheetPtr sheet = m_layout->GetFocusedSheet(); + if (sheet.isNull()) + { + return; + } + + DialogSaveManualLayout dialog(1, false, sheet->GetName(), this); + + if (dialog.exec() == QDialog::Rejected) + { + return; + } + + // TODO add checks for out of bound and pieces superpositions + + VPExportData data; + data.format = dialog.Format(); + data.path = dialog.Path(); + data.fileName = dialog.FileName(); + data.sheets = QList{sheet}; + data.xScale = dialog.GetXScale(); + data.yScale = dialog.GetYScale(); + data.isBinaryDXF = dialog.IsBinaryDXFFormat(); + data.textAsPaths = dialog.IsTextAsPaths(); + data.exportUnified = dialog.IsExportUnified(); + + ExportData(data); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPMainWindow::on_actionPrintLayout_triggered() +{ + +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPMainWindow::on_actionPrintPreviewLayout_triggered() +{ + +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPMainWindow::on_actionPrintTiledLayout_triggered() +{ + +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPMainWindow::on_actionPrintPreviewTiledLayout_triggered() +{ + +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPMainWindow::on_actionPrintSheet_triggered() +{ + +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPMainWindow::on_actionPrintPreviewSheet_triggered() +{ + +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPMainWindow::on_actionPrintTiledSheet_triggered() +{ + +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPMainWindow::on_actionPrintPreviewTiledSheet_triggered() +{ + +} + //--------------------------------------------------------------------------------------------------------------------- #if defined(Q_OS_MAC) void VPMainWindow::AboutToShowDockMenu() diff --git a/src/app/puzzle/vpmainwindow.h b/src/app/puzzle/vpmainwindow.h index 7340c8557..5ca5ce92e 100644 --- a/src/app/puzzle/vpmainwindow.h +++ b/src/app/puzzle/vpmainwindow.h @@ -40,7 +40,6 @@ #include "layout/vppiece.h" #include "../vlayout/vlayoutpiece.h" #include "vptilefactory.h" -#include "vpexporter.h" #include "vpcommandline.h" #include "../vlayout/vlayoutdef.h" #include "../vwidgets/vabstractmainwindow.h" @@ -55,6 +54,7 @@ namespace Ui class QFileSystemWatcher; template class QSharedPointer; class DialogPuzzlePreferences; +struct VPExportData; class VPMainWindow : public VAbstractMainWindow { @@ -221,18 +221,6 @@ private slots: */ void on_TilesMarginChanged(); - /** - * @brief on_pushButtonTilesExport_clicked When the export tiles button is clicked - */ - void on_pushButtonTilesExport_clicked(); - - /** - * @brief on_pushButtonLayoutExport_clicked When the button - * "Export layout" in the layout property is clicked. - * The slot is automatically connected through name convention. - */ - void on_pushButtonSheetExport_clicked(); - /** * @brief CarrouselLocationChanged When the piece carrousel's location * has been changed @@ -272,6 +260,19 @@ private slots: void on_ConvertPaperSize(); + void on_ExportLayout(); + void on_ExportSheet(); + + void on_actionPrintLayout_triggered(); + void on_actionPrintPreviewLayout_triggered(); + void on_actionPrintTiledLayout_triggered(); + void on_actionPrintPreviewTiledLayout_triggered(); + + void on_actionPrintSheet_triggered(); + void on_actionPrintPreviewSheet_triggered(); + void on_actionPrintTiledSheet_triggered(); + void on_actionPrintPreviewTiledSheet_triggered(); + #if defined(Q_OS_MAC) void AboutToShowDockMenu(); #endif //defined(Q_OS_MAC) @@ -289,8 +290,6 @@ private: VPLayoutPtr m_layout; - VPTileFactory *m_tileFactory{nullptr}; - /** * @brief spin box with the scale factor of the graphic view */ @@ -402,12 +401,6 @@ private: auto MaybeSave() -> bool; - /** - * @brief generateTiledPdf Generates the tiled Pdf in the given filename - * @param fileName output file name - */ - void generateTiledPdf(QString fileName); - void CreateWindowMenu(QMenu *menu); auto IsLayoutReadOnly() const -> bool; @@ -443,6 +436,16 @@ private: void CorrectMaxMargins(); void RotatePiecesToGrainline(); + + void ExportData(const VPExportData &data); + void ExportApparelLayout(const VPExportData &data, const QVector &details, const QString &name, + const QSize &size) const; + void ExportFlatLayout(const VPExportData &data); + void ExportScene(const VPExportData &data); + void ExportUnifiedPdfFile(const VPExportData &data); + void GenerateUnifiedPdfFile(const VPExportData &data, const QString &name); + void ExportPdfTiledFile(const VPExportData &data); + void GeneratePdfTiledFile(const VPSheetPtr &sheet, QPainter *painter, QPrinter *printer, bool firstSheet); }; #endif // VPMAINWINDOW_H diff --git a/src/app/puzzle/vpmainwindow.ui b/src/app/puzzle/vpmainwindow.ui index 790ed2f94..8fa9e2f22 100644 --- a/src/app/puzzle/vpmainwindow.ui +++ b/src/app/puzzle/vpmainwindow.ui @@ -57,12 +57,19 @@ - + - &Edit + &Sheet + + + + + + + @@ -77,8 +84,20 @@ + + + &Layout + + + + + + + + - + + @@ -1504,22 +1523,6 @@ - - - - Export - - - - - - Export Tiled Pdf - - - - - - @@ -1770,6 +1773,9 @@ Ctrl+O + + QAction::ApplicationSpecificRole + @@ -1785,6 +1791,9 @@ Ctrl+S + + QAction::ApplicationSpecificRole + @@ -1800,6 +1809,9 @@ Ctrl+Shift+S + + QAction::ApplicationSpecificRole + @@ -1838,6 +1850,9 @@ Ctrl+N + + QAction::ApplicationSpecificRole + @@ -1931,11 +1946,129 @@ Preferences + + QAction::PreferencesRole + Add Sheet + + QAction::ApplicationSpecificRole + + + + + + .. + + + Print + + + QAction::ApplicationSpecificRole + + + + + + .. + + + Print preview + + + QAction::ApplicationSpecificRole + + + + + + .. + + + Print tiled + + + QAction::ApplicationSpecificRole + + + + + + .. + + + Print preview tiled + + + QAction::ApplicationSpecificRole + + + + + Export + + + QAction::ApplicationSpecificRole + + + + + + .. + + + Print + + + QAction::ApplicationSpecificRole + + + + + + .. + + + Print preview + + + QAction::ApplicationSpecificRole + + + + + + .. + + + Print tiled + + + QAction::ApplicationSpecificRole + + + + + + .. + + + Print preview tiled + + + QAction::ApplicationSpecificRole + + + + + Export + + + QAction::ApplicationSpecificRole + @@ -1953,7 +2086,6 @@ lineEditSheetName pushButtonSheetExport checkBoxTilesShowTiles - pushButtonTilesExport lineEditLayoutName plainTextEditLayoutDescription checkBoxLayoutWarningPiecesSuperposition diff --git a/src/app/puzzle/vpsettings.cpp b/src/app/puzzle/vpsettings.cpp index b54d97648..af9f5787b 100644 --- a/src/app/puzzle/vpsettings.cpp +++ b/src/app/puzzle/vpsettings.cpp @@ -50,6 +50,7 @@ Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingLayoutWarningPiecesOutOfBound, (QLatin1String("layout/warningPiecesOutOfBound"))) Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingLayoutFollowGrainline, (QLatin1String("layout/followGrainline"))) Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingLayoutPieceGap, (QLatin1String("layout/pieceGap"))) +Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingLayoutExportFormat, (QLatin1String("layout/exportFormat"))) } // namespace Q_DECLARE_METATYPE(QMarginsF) @@ -290,3 +291,15 @@ auto VPSettings::GetLayoutPieceGap() const -> qreal { return ValueOrDef(*this, *settingLayoutPieceGap, UnitConvertor(5, Unit::Mm, Unit::Px)); } + +//--------------------------------------------------------------------------------------------------------------------- +qint8 VPSettings::GetLayoutExportFormat() const +{ + return qvariant_cast(value(*settingLayoutExportFormat, 0)); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPSettings::SetLayoutExportFormat(qint8 format) +{ + setValue(*settingLayoutExportFormat, format); +} diff --git a/src/app/puzzle/vpsettings.h b/src/app/puzzle/vpsettings.h index d4098db40..75f589b6d 100644 --- a/src/app/puzzle/vpsettings.h +++ b/src/app/puzzle/vpsettings.h @@ -94,6 +94,9 @@ public: void SetLayoutPieceGap(qreal value); auto GetLayoutPieceGap() const -> qreal; + auto GetLayoutExportFormat() const -> qint8; + void SetLayoutExportFormat(qint8 format); + private: Q_DISABLE_COPY(VPSettings) }; diff --git a/src/app/puzzle/vptilefactory.cpp b/src/app/puzzle/vptilefactory.cpp index c3323b3f7..934c836e5 100644 --- a/src/app/puzzle/vptilefactory.cpp +++ b/src/app/puzzle/vptilefactory.cpp @@ -7,13 +7,14 @@ #include "scene/vpmaingraphicsview.h" #include "../vmisc/def.h" #include "../vmisc/vcommonsettings.h" +#include "../vlayout/vprintlayout.h" //--------------------------------------------------------------------------------------------------------------------- VPTileFactory::VPTileFactory(const VPLayoutPtr &layout, VCommonSettings *commonSettings): m_layout(layout), - m_commonSettings(commonSettings) + m_commonSettings(commonSettings), + m_infoStripeWidth(UnitConvertor(1, Unit::Cm, Unit::Px)) { - m_infoStripeWidth = UnitConvertor(1, Unit::Cm, Unit::Px); } //--------------------------------------------------------------------------------------------------------------------- @@ -48,34 +49,53 @@ void VPTileFactory::refreshTileInfos() { m_drawingAreaWidth += m_infoStripeWidth; } - - QSizeF sheetSize; - VPSheetPtr sheet = layout->GetFocusedSheet(); - if (not sheet.isNull()) - { - sheetSize = sheet->GetSheetSize(); - } - m_nbCol = qCeil(sheetSize.width()/m_drawingAreaWidth); - m_nbRow = qCeil(sheetSize.height()/m_drawingAreaHeight); } } //--------------------------------------------------------------------------------------------------------------------- -void VPTileFactory::drawTile(QPainter *painter, VPMainGraphicsView *graphicsView, int row, int col) +void VPTileFactory::drawTile(QPainter *painter, QPrinter *printer, const VPSheetPtr &sheet, int row, int col) { + SCASSERT(painter != nullptr) + SCASSERT(printer != nullptr) + VPLayoutPtr layout = m_layout.toStrongRef(); if(layout.isNull()) { - return - ; + return; } + + if (sheet.isNull()) + { + return; + } + + const int nbCol = ColNb(sheet); + const int nbRow = RowNb(sheet); + + if (row < 0 || row > nbRow || col < 0 || col > nbCol) + { + return; + } + QMarginsF tilesMargins = layout->LayoutSettings().GetTilesMargins(); QPen penTileInfos = QPen(QColor(180,180,180), m_commonSettings->WidthHairLine(), Qt::DashLine, Qt::RoundCap, Qt::RoundJoin); QPen penTileDrawing = QPen(Qt::black, m_commonSettings->WidthMainLine(), Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin); - QSvgRenderer* svgRenderer = new QSvgRenderer(); + // paint the content of the page + QRectF source = QRectF(col*m_drawingAreaWidth, + row*m_drawingAreaHeight, + m_drawingAreaWidth + m_infoStripeWidth, + m_drawingAreaHeight + m_infoStripeWidth + ); + + painter->setPen(penTileDrawing); + + sheet->SceneData()->Scene()->render(painter, VPrintLayout::SceneTargetRect(printer, source), source, + Qt::IgnoreAspectRatio); + + QScopedPointer svgRenderer(new QSvgRenderer()); // ------------- prepare triangles for position marks QRectF rectBasic = QRectF(-UnitConvertor(0.5, Unit::Cm, Unit::Px), @@ -91,7 +111,6 @@ void VPTileFactory::drawTile(QPainter *painter, VPMainGraphicsView *graphicsView QBrush triangleBush = QBrush(QColor(200,200,200)); - // add the tiles decorations (cutting and gluing lines, scissors, infos etc.) painter->setPen(penTileInfos); @@ -107,19 +126,17 @@ void VPTileFactory::drawTile(QPainter *painter, VPMainGraphicsView *graphicsView // scissors along the top line svgRenderer->load(QStringLiteral("://puzzleicon/svg/icon_scissors_horizontal.svg")); svgRenderer->render(painter, QRectF(tilesMargins.left() + m_drawingAreaWidth, - tilesMargins.top(), - UnitConvertor(1, Unit::Cm, Unit::Px), - UnitConvertor(0.56, Unit::Cm, Unit::Px) - )); + tilesMargins.top(), + UnitConvertor(1, Unit::Cm, Unit::Px), + UnitConvertor(0.56, Unit::Cm, Unit::Px))); // dashed top line (for cutting) penTileInfos.setStyle(Qt::DashLine); painter->setPen(penTileInfos); painter->drawLine(QPointF(tilesMargins.left(), - tilesMargins.top()), - QPointF(tilesMargins.left() + m_drawingAreaWidth + m_infoStripeWidth, - tilesMargins.top()) - ); + tilesMargins.top()), + QPointF(tilesMargins.left() + m_drawingAreaWidth + m_infoStripeWidth, + tilesMargins.top())); } else { @@ -127,10 +144,9 @@ void VPTileFactory::drawTile(QPainter *painter, VPMainGraphicsView *graphicsView penTileInfos.setStyle(Qt::SolidLine); painter->setPen(penTileInfos); painter->drawLine(QPointF(tilesMargins.left(), - tilesMargins.top()), - QPointF(tilesMargins.left() + m_drawingAreaWidth + ((col < m_nbCol-1)? m_infoStripeWidth : 0), - tilesMargins.top()) - ); + tilesMargins.top()), + QPointF(tilesMargins.left() + m_drawingAreaWidth + ((col < nbCol-1)? m_infoStripeWidth : 0), + tilesMargins.top())); } if(col > 0) @@ -168,11 +184,11 @@ void VPTileFactory::drawTile(QPainter *painter, VPMainGraphicsView *graphicsView painter->drawLine(QPointF(tilesMargins.left(), tilesMargins.top()), QPointF(tilesMargins.left(), - tilesMargins.top() + m_drawingAreaHeight + ((row < m_nbRow-1)? m_infoStripeWidth : 0)) + tilesMargins.top() + m_drawingAreaHeight + ((row < nbRow-1)? m_infoStripeWidth : 0)) ); } - if(row < m_nbRow-1) + if(row < nbRow-1) { // add bottom triangle QPainterPath triangleBottom = @@ -191,19 +207,20 @@ void VPTileFactory::drawTile(QPainter *painter, VPMainGraphicsView *graphicsView QPointF(tilesMargins.left() + m_drawingAreaWidth + m_infoStripeWidth, tilesMargins.top() + m_drawingAreaHeight) ); - } else + } + else { // solid bottom line at the edge penTileInfos.setStyle(Qt::SolidLine); painter->setPen(penTileInfos); painter->drawLine(QPointF(tilesMargins.left(), tilesMargins.top() + m_drawingAreaHeight), - QPointF(tilesMargins.left() + m_drawingAreaWidth + ((col < m_nbCol-1)? m_infoStripeWidth : 0), + QPointF(tilesMargins.left() + m_drawingAreaWidth + ((col < nbCol-1)? m_infoStripeWidth : 0), tilesMargins.top() + m_drawingAreaHeight) ); } - if(col < m_nbCol-1) + if(col < nbCol-1) { // add right triangle QPainterPath triangleRight = @@ -230,25 +247,10 @@ void VPTileFactory::drawTile(QPainter *painter, VPMainGraphicsView *graphicsView painter->drawLine(QPointF(tilesMargins.left() + m_drawingAreaWidth, tilesMargins.top()), QPointF(tilesMargins.left() + m_drawingAreaWidth, - tilesMargins.top()+ m_drawingAreaHeight + ((row < m_nbRow-1) ? m_infoStripeWidth : 0)) + tilesMargins.top()+ m_drawingAreaHeight + ((row < nbRow-1) ? m_infoStripeWidth : 0)) ); } - // paint the content of the page - QRectF source = QRectF(col*m_drawingAreaWidth, - row*m_drawingAreaHeight, - m_drawingAreaWidth + m_infoStripeWidth, - m_drawingAreaHeight + m_infoStripeWidth - ); - QRectF target = QRectF(tilesMargins.left(), - tilesMargins.top(), - source.width(), - source.height() - ); - - painter->setPen(penTileDrawing); - graphicsView->GetScene()->render(painter, target, source, Qt::IgnoreAspectRatio); - // prepare the painting for the text information QTextDocument td; td.setPageSize(QSizeF( @@ -274,15 +276,20 @@ void VPTileFactory::drawTile(QPainter *painter, VPMainGraphicsView *graphicsView painter->restore(); // paint the page information - const QString page = tr("Page %1 of %2").arg(row*m_nbCol+col+1).arg(m_nbCol*m_nbRow); + const QString page = tr("Page %1 of %2").arg(row*nbCol+col+1).arg(nbCol*nbRow); td.setPageSize(QSizeF(m_drawingAreaHeight - UnitConvertor(2, Unit::Cm, Unit::Px), m_drawingAreaWidth)); + + QFontMetrics metrix = QFontMetrics(td.defaultFont()); + QString clippedSheetName = metrix.elidedText(sheet->GetName(), Qt::ElideMiddle, + metrix.width(QString().fill('z', 50))); + td.setHtml(QString("" "" "" "" "
%1 - %2
") - .arg(page).arg(layout->GetFocusedSheet()->GetName())); + .arg(page).arg(clippedSheetName)); painter->save(); painter->rotate(-90); painter->translate(QPointF(-(m_drawingAreaHeight+tilesMargins.top()) + UnitConvertor(1, Unit::Cm, Unit::Px), @@ -290,29 +297,38 @@ void VPTileFactory::drawTile(QPainter *painter, VPMainGraphicsView *graphicsView )); td.drawContents(painter); painter->restore(); - } //--------------------------------------------------------------------------------------------------------------------- -int VPTileFactory::getRowNb() +auto VPTileFactory::RowNb(const VPSheetPtr &sheet) const -> int { - return m_nbRow; + if (sheet.isNull()) + { + return 0; + } + QSizeF sheetSize = sheet->GetSheetSize(); + return qCeil(sheetSize.height() / m_drawingAreaHeight); } //--------------------------------------------------------------------------------------------------------------------- -int VPTileFactory::getColNb() +auto VPTileFactory::ColNb(const VPSheetPtr &sheet) const -> int { - return m_nbCol; + if (sheet.isNull()) + { + return 0; + } + QSizeF sheetSize = sheet->GetSheetSize(); + return qCeil(sheetSize.width() / m_drawingAreaWidth); } //--------------------------------------------------------------------------------------------------------------------- -qreal VPTileFactory::getDrawingAreaHeight() +auto VPTileFactory::DrawingAreaHeight() const -> qreal { return m_drawingAreaHeight; } //--------------------------------------------------------------------------------------------------------------------- -qreal VPTileFactory::getDrawingAreaWidth() +auto VPTileFactory::DrawingAreaWidth() const -> qreal { return m_drawingAreaWidth; } diff --git a/src/app/puzzle/vptilefactory.h b/src/app/puzzle/vptilefactory.h index 050eff123..7fb5e526b 100644 --- a/src/app/puzzle/vptilefactory.h +++ b/src/app/puzzle/vptilefactory.h @@ -34,7 +34,7 @@ #include "layout/vplayout.h" -class VPMainGraphicsView; +class QGraphicsScene; class VCommonSettings; class QPainter; @@ -54,36 +54,36 @@ public: * @param row current row * @param col current column */ - void drawTile(QPainter *painter, VPMainGraphicsView *graphicsView, int row, int col); + void drawTile(QPainter *painter, QPrinter *printer, const VPSheetPtr &sheet, int row, int col); /** - * @brief refreshTileInfos Resfreshes the tile infos (m_nbCol, m_nbRow, m_drawingAreaHeight, m_drawingAreaWidth) + * @brief refreshTileInfos Resfreshes the tile infos (m_drawingAreaHeight, m_drawingAreaWidth) */ void refreshTileInfos(); /** - * @brief getRowNb Returns the number of row pages + * @brief RowNb Returns the number of row pages * @return number of row pages */ - int getRowNb(); + auto RowNb(const VPSheetPtr &sheet) const -> int; /** - * @brief getColNb Returns the number of col pages + * @brief ColNb Returns the number of col pages * @return number of col pages */ - int getColNb(); + auto ColNb(const VPSheetPtr &sheet) const -> int; /** - * @brief getDrawingAreaHeight Returns the usable height of the tile in Px + * @brief DrawingAreaHeight Returns the usable height of the tile in Px * @return usable height of the tile in Px */ - qreal getDrawingAreaHeight(); + auto DrawingAreaHeight() const -> qreal; /** - * @brief getDrawingAreaWidth Returns the usable width of the tile in Px + * @brief DrawingAreaWidth Returns the usable width of the tile in Px * @return usable width of the tile in Px */ - qreal getDrawingAreaWidth(); + auto DrawingAreaWidth() const -> qreal; private: Q_DISABLE_COPY(VPTileFactory) @@ -91,16 +91,6 @@ private: VPLayoutWeakPtr m_layout; VCommonSettings *m_commonSettings{nullptr}; - /** - * @brief m_nbCol the number of column-pages for the current sheet of the layout - */ - int m_nbCol{0}; - - /** - * @brief m_nbRow the number of row-pages for the current sheet of the layout - */ - int m_nbRow{0}; - /** * @brief m_drawingAreaHeight the height of the drawing area */ @@ -114,7 +104,7 @@ private: /** * @brief m_infoStripeWidth the width of the info / glueing stripe in Px */ - qreal m_infoStripeWidth{0}; + qreal m_infoStripeWidth; }; diff --git a/src/app/valentina/dialogs/dialogsavelayout.cpp b/src/app/valentina/dialogs/dialogsavelayout.cpp index fb3bd0f3f..980ebcf9f 100644 --- a/src/app/valentina/dialogs/dialogsavelayout.cpp +++ b/src/app/valentina/dialogs/dialogsavelayout.cpp @@ -69,8 +69,7 @@ DialogSaveLayout::DialogSaveLayout(int count, Draw mode, const QString &fileName ui->lineEditPath->setClearButtonEnabled(true); ui->lineEditFileName->setClearButtonEnabled(true); - VAbstractValApplication::VApp()->ValentinaSettings()->GetOsSeparator() ? setLocale(QLocale()) - : setLocale(QLocale::c()); + VAbstractApplication::VApp()->Settings()->GetOsSeparator() ? setLocale(QLocale()) : setLocale(QLocale::c()); QPushButton *bOk = ui->buttonBox->button(QDialogButtonBox::Ok); SCASSERT(bOk != nullptr) diff --git a/src/app/valentina/mainwindowsnogui.cpp b/src/app/valentina/mainwindowsnogui.cpp index 48697ddfe..900111ec3 100644 --- a/src/app/valentina/mainwindowsnogui.cpp +++ b/src/app/valentina/mainwindowsnogui.cpp @@ -1172,55 +1172,55 @@ void MainWindowsNoGUI::ExportScene(const QList &scenes, case LayoutExportFormats::DXF_AC1006_Flat: paper->setVisible(false); exporter.SetDxfVersion(DRW::AC1006); - exporter.ExportToFlatDXF(scene, details); + exporter.ExportToFlatDXF(scene, details.at(i)); paper->setVisible(true); break; case LayoutExportFormats::DXF_AC1009_Flat: paper->setVisible(false); exporter.SetDxfVersion(DRW::AC1009); - exporter.ExportToFlatDXF(scene, details); + exporter.ExportToFlatDXF(scene, details.at(i)); paper->setVisible(true); break; case LayoutExportFormats::DXF_AC1012_Flat: paper->setVisible(false); exporter.SetDxfVersion(DRW::AC1012); - exporter.ExportToFlatDXF(scene, details); + exporter.ExportToFlatDXF(scene, details.at(i)); paper->setVisible(true); break; case LayoutExportFormats::DXF_AC1014_Flat: paper->setVisible(false); exporter.SetDxfVersion(DRW::AC1014); - exporter.ExportToFlatDXF(scene, details); + exporter.ExportToFlatDXF(scene, details.at(i)); paper->setVisible(true); break; case LayoutExportFormats::DXF_AC1015_Flat: paper->setVisible(false); exporter.SetDxfVersion(DRW::AC1015); - exporter.ExportToFlatDXF(scene, details); + exporter.ExportToFlatDXF(scene, details.at(i)); paper->setVisible(true); break; case LayoutExportFormats::DXF_AC1018_Flat: paper->setVisible(false); exporter.SetDxfVersion(DRW::AC1018); - exporter.ExportToFlatDXF(scene, details); + exporter.ExportToFlatDXF(scene, details.at(i)); paper->setVisible(true); break; case LayoutExportFormats::DXF_AC1021_Flat: paper->setVisible(false); exporter.SetDxfVersion(DRW::AC1021); - exporter.ExportToFlatDXF(scene, details); + exporter.ExportToFlatDXF(scene, details.at(i)); paper->setVisible(true); break; case LayoutExportFormats::DXF_AC1024_Flat: paper->setVisible(false); exporter.SetDxfVersion(DRW::AC1024); - exporter.ExportToFlatDXF(scene, details); + exporter.ExportToFlatDXF(scene, details.at(i)); paper->setVisible(true); break; case LayoutExportFormats::DXF_AC1027_Flat: paper->setVisible(false); exporter.SetDxfVersion(DRW::AC1027); - exporter.ExportToFlatDXF(scene, details); + exporter.ExportToFlatDXF(scene, details.at(i)); paper->setVisible(true); break; case LayoutExportFormats::TIF: diff --git a/src/libs/vlayout/vlayoutexporter.cpp b/src/libs/vlayout/vlayoutexporter.cpp index fa19a1cb8..659808b51 100644 --- a/src/libs/vlayout/vlayoutexporter.cpp +++ b/src/libs/vlayout/vlayoutexporter.cpp @@ -48,6 +48,7 @@ #include "vrawlayout.h" #include "../vmisc/vabstractvalapplication.h" #include "../ifc/exception/vexception.h" +#include "vprintlayout.h" namespace { @@ -66,21 +67,18 @@ Q_GLOBAL_STATIC_WITH_ARGS(const QString, PDFTOPS, (QLatin1String("pdftops"))) * * @param placeholder placeholder that will be appended to each QGraphicsSimpleTextItem item's text string. */ -void PrepareTextForDXF(const QString &placeholder, const QList > &details) +void PrepareTextForDXF(const QString &placeholder, const QList &paperItems) { - for (const auto &paperItems : details) + for (auto *item : paperItems) { - for (auto *item : paperItems) + QList pieceChildren = item->childItems(); + for (auto *child : qAsConst(pieceChildren)) { - QList pieceChildren = item->childItems(); - for (auto *child : qAsConst(pieceChildren)) + if (child->type() == QGraphicsSimpleTextItem::Type) { - if (child->type() == QGraphicsSimpleTextItem::Type) + if(auto *textItem = qgraphicsitem_cast(child)) { - if(auto *textItem = qgraphicsitem_cast(child)) - { - textItem->setText(textItem->text() + placeholder); - } + textItem->setText(textItem->text() + placeholder); } } } @@ -96,23 +94,20 @@ void PrepareTextForDXF(const QString &placeholder, const QList > &details) +void RestoreTextAfterDXF(const QString &placeholder, const QList &paperItems) { - for (const auto &paperItems : details) + for (auto *item : paperItems) { - for (auto *item : paperItems) + QList pieceChildren = item->childItems(); + for (auto *child : qAsConst(pieceChildren)) { - QList pieceChildren = item->childItems(); - for (auto *child : qAsConst(pieceChildren)) + if (child->type() == QGraphicsSimpleTextItem::Type) { - if (child->type() == QGraphicsSimpleTextItem::Type) + if(auto *textItem = qgraphicsitem_cast(child)) { - if(auto *textItem = qgraphicsitem_cast(child)) - { - QString text = textItem->text(); - text.replace(placeholder, QString()); - textItem->setText(text); - } + QString text = textItem->text(); + text.replace(placeholder, QString()); + textItem->setText(text); } } } @@ -209,46 +204,7 @@ void VLayoutExporter::ExportToTIF(QGraphicsScene *scene) const //--------------------------------------------------------------------------------------------------------------------- void VLayoutExporter::ExportToPDF(QGraphicsScene *scene) const { - QPrinter printer; - printer.setCreator(QGuiApplication::applicationDisplayName() + QChar(QChar::Space) + - QCoreApplication::applicationVersion()); - printer.setOutputFormat(QPrinter::PdfFormat); - printer.setOutputFileName(m_fileName); - printer.setDocName(QFileInfo(m_fileName).fileName()); - printer.setResolution(static_cast(PrintDPI)); - printer.setPageOrientation(QPageLayout::Portrait); - printer.setFullPage(m_ignorePrinterMargins); - - 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); - - if (not printer.setPageSize(QPageSize(QSizeF(width, height), QPageSize::Millimeter))) - { - qWarning() << tr("Cannot set printer page size"); - } - - 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)); - return; - } - 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(); + ExportToPDF(scene, m_fileName); } //--------------------------------------------------------------------------------------------------------------------- @@ -271,8 +227,9 @@ void VLayoutExporter::ExportToPS(QGraphicsScene *scene) const QTemporaryFile tmp; if (tmp.open()) { - ExportToPDF(scene); - PdfToPs(QStringList{tmp.fileName(), m_fileName}); + const QString fileName = m_fileName; + ExportToPDF(scene, tmp.fileName()); + PdfToPs(QStringList{tmp.fileName(), fileName}); } } @@ -282,13 +239,14 @@ void VLayoutExporter::ExportToEPS(QGraphicsScene *scene) const QTemporaryFile tmp; if (tmp.open()) { - ExportToPDF(scene); - PdfToPs(QStringList{QStringLiteral("-eps"), tmp.fileName(), m_fileName}); + const QString fileName = m_fileName; + ExportToPDF(scene, tmp.fileName()); + PdfToPs(QStringList{QStringLiteral("-eps"), tmp.fileName(), fileName}); } } //--------------------------------------------------------------------------------------------------------------------- -void VLayoutExporter::ExportToFlatDXF(QGraphicsScene *scene, const QList > &details) const +void VLayoutExporter::ExportToFlatDXF(QGraphicsScene *scene, const QList &details) const { PrepareTextForDXF(endStringPlaceholder, details); @@ -447,6 +405,53 @@ void VLayoutExporter::PdfToPs(const QStringList ¶ms) } } +//--------------------------------------------------------------------------------------------------------------------- +void VLayoutExporter::ExportToPDF(QGraphicsScene *scene, const QString &filename) const +{ + 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(PrintDPI)); + printer.setPageOrientation(QPageLayout::Portrait); + printer.setFullPage(m_ignorePrinterMargins); + + 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); + + if (not printer.setPageSize(QPageSize(QSizeF(width, height), QPageSize::Millimeter))) + { + qWarning() << tr("Cannot set printer page size"); + } + + 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)); + 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(); +} //--------------------------------------------------------------------------------------------------------------------- QString VLayoutExporter::ExportFormatDescription(LayoutExportFormats format) diff --git a/src/libs/vlayout/vlayoutexporter.h b/src/libs/vlayout/vlayoutexporter.h index 701b7bc4d..1966090f2 100644 --- a/src/libs/vlayout/vlayoutexporter.h +++ b/src/libs/vlayout/vlayoutexporter.h @@ -86,7 +86,7 @@ public: void ExportToOBJ(QGraphicsScene *scene) const; void ExportToPS(QGraphicsScene *scene) const; void ExportToEPS(QGraphicsScene *scene) const; - void ExportToFlatDXF(QGraphicsScene *scene, const QList > &details) const; + void ExportToFlatDXF(QGraphicsScene *scene, const QList &details) const; void ExportToAAMADXF(const QVector &details) const; void ExportToASTMDXF(const QVector &details) const; void ExportToRLD(const QVector &details) const; @@ -96,6 +96,7 @@ public: static QString ExportFormatDescription(LayoutExportFormats format); static QString ExportFormatSuffix(LayoutExportFormats format); + static void PdfToPs(const QStringList ¶ms); auto offset() const -> QPointF; void SetOffset(const QPointF &newOffset); @@ -114,7 +115,7 @@ private: int m_dxfVersion{0}; QPointF m_offset{}; - static void PdfToPs(const QStringList ¶ms); + void ExportToPDF(QGraphicsScene *scene, const QString &filename) const; }; //--------------------------------------------------------------------------------------------------------------------- diff --git a/src/libs/vlayout/vprintlayout.cpp b/src/libs/vlayout/vprintlayout.cpp index b1b09ba4b..e9c250a55 100644 --- a/src/libs/vlayout/vprintlayout.cpp +++ b/src/libs/vlayout/vprintlayout.cpp @@ -386,14 +386,6 @@ void VPrintLayout::PrintPages(QPrinter *printer) VWatermarkData data = WatermarkData(); - // Here we try understand difference between printer's dpi and our. - // Get printer rect acording to our dpi. - const QRectF printerPageRect(0, 0, ToPixel(printer->pageRect(QPrinter::Millimeter).width(), Unit::Mm), - ToPixel(printer->pageRect(QPrinter::Millimeter).height(), Unit::Mm)); - const QRect pageRect = printer->pageLayout().paintRectPixels(printer->resolution()); - const double xscale = pageRect.width() / printerPageRect.width(); - const double yscale = pageRect.height() / printerPageRect.height(); - for (int i = 0; i < copyCount; ++i) { for (int j = 0; j < numPages; ++j) @@ -437,24 +429,8 @@ void VPrintLayout::PrintPages(QPrinter *printer) QRectF source; m_isTiled ? source = poster->at(index).rect : source = paper->rect(); - qreal x; - qreal y; - if(printer->fullPage()) - { - QPageLayout layout = printer->pageLayout(); - layout.setUnits(QPageLayout::Millimeter); - QMarginsF printerMargins = layout.margins(); - x = qFloor(ToPixel(printerMargins.left(), Unit::Mm)); - y = qFloor(ToPixel(printerMargins.top(), Unit::Mm)); - } - else - { - x = 0; y = 0; - } - - QRectF target(x * xscale, y * yscale, source.width() * xscale, source.height() * yscale); - - m_layoutScenes.at(paperIndex)->render(&painter, target, source, Qt::IgnoreAspectRatio); + m_layoutScenes.at(paperIndex)->render(&painter, VPrintLayout::SceneTargetRect(printer, source), source, + Qt::IgnoreAspectRatio); if (m_isTiled) { @@ -762,3 +738,34 @@ auto VPrintLayout::ContinueIfLayoutStale(QWidget *parent) -> int return QMessageBox::Yes; } + +//--------------------------------------------------------------------------------------------------------------------- +QRectF VPrintLayout::SceneTargetRect(QPrinter *printer, const QRectF &source) +{ + SCASSERT(printer != nullptr) + + qreal x; + qreal y; + if(printer->fullPage()) + { + QPageLayout layout = printer->pageLayout(); + layout.setUnits(QPageLayout::Millimeter); + QMarginsF printerMargins = layout.margins(); + x = qFloor(ToPixel(printerMargins.left(), Unit::Mm)); + y = qFloor(ToPixel(printerMargins.top(), Unit::Mm)); + } + else + { + x = 0; y = 0; + } + + // Here we try understand difference between printer's dpi and our. + // Get printer rect acording to our dpi. + const QRectF printerPageRect(0, 0, ToPixel(printer->pageRect(QPrinter::Millimeter).width(), Unit::Mm), + ToPixel(printer->pageRect(QPrinter::Millimeter).height(), Unit::Mm)); + const QRect pageRect = printer->pageLayout().paintRectPixels(printer->resolution()); + const double xscale = pageRect.width() / printerPageRect.width(); + const double yscale = pageRect.height() / printerPageRect.height(); + + return QRectF(x * xscale, y * yscale, source.width() * xscale, source.height() * yscale); +} diff --git a/src/libs/vlayout/vprintlayout.h b/src/libs/vlayout/vprintlayout.h index f23e914ab..d3aafc2e2 100644 --- a/src/libs/vlayout/vprintlayout.h +++ b/src/libs/vlayout/vprintlayout.h @@ -121,6 +121,7 @@ public: void CleanLayout(); static auto ContinueIfLayoutStale(QWidget *parent) -> int; + static auto SceneTargetRect(QPrinter *printer, const QRectF &source) -> QRectF; private slots: void PrintPages (QPrinter *printer); diff --git a/src/libs/vwidgets/vmaingraphicsview.cpp b/src/libs/vwidgets/vmaingraphicsview.cpp index 84f42e350..d170bae74 100644 --- a/src/libs/vwidgets/vmaingraphicsview.cpp +++ b/src/libs/vwidgets/vmaingraphicsview.cpp @@ -793,7 +793,7 @@ void VMainGraphicsView::NewSceneRect(QGraphicsScene *sc, QGraphicsView *view, QG { QRectF rect = item->sceneBoundingRect(); const QList children = item->childItems(); - for (auto child : children) + for (auto *child : children) { if(child->isVisible()) {