|
53 | 53 | #include "qgsbusyindicatordialog.h"
|
54 | 54 | #include "qgslayoutundostack.h"
|
55 | 55 | #include "qgslayoutpagecollection.h"
|
| 56 | +#include "ui_qgssvgexportoptions.h" |
56 | 57 | #include <QShortcut>
|
57 | 58 | #include <QComboBox>
|
58 | 59 | #include <QLineEdit>
|
@@ -182,6 +183,7 @@ QgsLayoutDesignerDialog::QgsLayoutDesignerDialog( QWidget *parent, Qt::WindowFla
|
182 | 183 |
|
183 | 184 | connect( mActionExportAsImage, &QAction::triggered, this, &QgsLayoutDesignerDialog::exportToRaster );
|
184 | 185 | connect( mActionExportAsPDF, &QAction::triggered, this, &QgsLayoutDesignerDialog::exportToPdf );
|
| 186 | + connect( mActionExportAsSVG, &QAction::triggered, this, &QgsLayoutDesignerDialog::exportToSvg ); |
185 | 187 |
|
186 | 188 | connect( mActionShowGrid, &QAction::triggered, this, &QgsLayoutDesignerDialog::showGrid );
|
187 | 189 | connect( mActionSnapGrid, &QAction::triggered, this, &QgsLayoutDesignerDialog::snapToGrid );
|
@@ -1671,6 +1673,152 @@ void QgsLayoutDesignerDialog::exportToPdf()
|
1671 | 1673 | QApplication::restoreOverrideCursor();
|
1672 | 1674 | }
|
1673 | 1675 |
|
| 1676 | +void QgsLayoutDesignerDialog::exportToSvg() |
| 1677 | +{ |
| 1678 | + if ( containsWmsLayers() ) |
| 1679 | + { |
| 1680 | + showWmsPrintingWarning(); |
| 1681 | + } |
| 1682 | + |
| 1683 | + showSvgExportWarning(); |
| 1684 | + |
| 1685 | + QgsSettings settings; |
| 1686 | + QString lastUsedFile = settings.value( QStringLiteral( "UI/lastSaveAsSvgFile" ), QStringLiteral( "qgis.svg" ) ).toString(); |
| 1687 | + QFileInfo file( lastUsedFile ); |
| 1688 | + QString outputFileName; |
| 1689 | + |
| 1690 | +#if 0// TODO |
| 1691 | + if ( hasAnAtlas && !atlasOnASingleFile && |
| 1692 | + ( mode == QgsComposer::Atlas || mComposition->atlasMode() == QgsComposition::PreviewAtlas ) ) |
| 1693 | + { |
| 1694 | + outputFileName = QDir( file.path() ).filePath( atlasMap->currentFilename() ) + ".pdf"; |
| 1695 | + } |
| 1696 | + else |
| 1697 | + { |
| 1698 | +#endif |
| 1699 | + outputFileName = file.path(); |
| 1700 | +#if 0 //TODO |
| 1701 | + } |
| 1702 | +#endif |
| 1703 | + |
| 1704 | +#ifdef Q_OS_MAC |
| 1705 | + QgisApp::instance()->activateWindow(); |
| 1706 | + this->raise(); |
| 1707 | +#endif |
| 1708 | + outputFileName = QFileDialog::getSaveFileName( |
| 1709 | + this, |
| 1710 | + tr( "Export to SVG" ), |
| 1711 | + outputFileName, |
| 1712 | + tr( "SVG Format" ) + " (*.svg *.SVG)" ); |
| 1713 | + this->activateWindow(); |
| 1714 | + if ( outputFileName.isEmpty() ) |
| 1715 | + { |
| 1716 | + return; |
| 1717 | + } |
| 1718 | + |
| 1719 | + if ( !outputFileName.endsWith( QLatin1String( ".svg" ), Qt::CaseInsensitive ) ) |
| 1720 | + { |
| 1721 | + outputFileName += QLatin1String( ".svg" ); |
| 1722 | + } |
| 1723 | + |
| 1724 | + settings.setValue( QStringLiteral( "UI/lastSaveAsSvgFile" ), outputFileName ); |
| 1725 | + |
| 1726 | + bool groupLayers = false; |
| 1727 | + bool prevSettingLabelsAsOutlines = mLayout->project()->readBoolEntry( QStringLiteral( "PAL" ), QStringLiteral( "/DrawOutlineLabels" ), true ); |
| 1728 | + bool clipToContent = false; |
| 1729 | + double marginTop = 0.0; |
| 1730 | + double marginRight = 0.0; |
| 1731 | + double marginBottom = 0.0; |
| 1732 | + double marginLeft = 0.0; |
| 1733 | + bool previousForceVector = mLayout->customProperty( QStringLiteral( "forceVector" ), false ).toBool(); |
| 1734 | + |
| 1735 | + // open options dialog |
| 1736 | + QDialog dialog; |
| 1737 | + Ui::QgsSvgExportOptionsDialog options; |
| 1738 | + options.setupUi( &dialog ); |
| 1739 | + options.chkTextAsOutline->setChecked( prevSettingLabelsAsOutlines ); |
| 1740 | + options.chkMapLayersAsGroup->setChecked( mLayout->customProperty( QStringLiteral( "svgGroupLayers" ), false ).toBool() ); |
| 1741 | + options.mClipToContentGroupBox->setChecked( mLayout->customProperty( QStringLiteral( "svgCropToContents" ), false ).toBool() ); |
| 1742 | + options.mForceVectorCheckBox->setChecked( previousForceVector ); |
| 1743 | + options.mTopMarginSpinBox->setValue( mLayout->customProperty( QStringLiteral( "svgCropMarginTop" ), 0 ).toInt() ); |
| 1744 | + options.mRightMarginSpinBox->setValue( mLayout->customProperty( QStringLiteral( "svgCropMarginRight" ), 0 ).toInt() ); |
| 1745 | + options.mBottomMarginSpinBox->setValue( mLayout->customProperty( QStringLiteral( "svgCropMarginBottom" ), 0 ).toInt() ); |
| 1746 | + options.mLeftMarginSpinBox->setValue( mLayout->customProperty( QStringLiteral( "svgCropMarginLeft" ), 0 ).toInt() ); |
| 1747 | + |
| 1748 | + if ( dialog.exec() != QDialog::Accepted ) |
| 1749 | + return; |
| 1750 | + |
| 1751 | + groupLayers = options.chkMapLayersAsGroup->isChecked(); |
| 1752 | + clipToContent = options.mClipToContentGroupBox->isChecked(); |
| 1753 | + marginTop = options.mTopMarginSpinBox->value(); |
| 1754 | + marginRight = options.mRightMarginSpinBox->value(); |
| 1755 | + marginBottom = options.mBottomMarginSpinBox->value(); |
| 1756 | + marginLeft = options.mLeftMarginSpinBox->value(); |
| 1757 | + |
| 1758 | + //save dialog settings |
| 1759 | + mLayout->setCustomProperty( QStringLiteral( "svgGroupLayers" ), groupLayers ); |
| 1760 | + mLayout->setCustomProperty( QStringLiteral( "svgCropToContents" ), clipToContent ); |
| 1761 | + mLayout->setCustomProperty( QStringLiteral( "svgCropMarginTop" ), marginTop ); |
| 1762 | + mLayout->setCustomProperty( QStringLiteral( "svgCropMarginRight" ), marginRight ); |
| 1763 | + mLayout->setCustomProperty( QStringLiteral( "svgCropMarginBottom" ), marginBottom ); |
| 1764 | + mLayout->setCustomProperty( QStringLiteral( "svgCropMarginLeft" ), marginLeft ); |
| 1765 | + |
| 1766 | + //temporarily override label draw outlines setting |
| 1767 | + mLayout->project()->writeEntry( QStringLiteral( "PAL" ), QStringLiteral( "/DrawOutlineLabels" ), options.chkTextAsOutline->isChecked() ); |
| 1768 | + |
| 1769 | + mView->setPaintingEnabled( false ); |
| 1770 | + QApplication::setOverrideCursor( Qt::BusyCursor ); |
| 1771 | + |
| 1772 | + QgsLayoutExporter::SvgExportSettings svgSettings; |
| 1773 | + svgSettings.forceVectorOutput = mLayout->customProperty( QStringLiteral( "forceVector" ), false ).toBool(); |
| 1774 | + svgSettings.cropToContents = clipToContent; |
| 1775 | + svgSettings.cropMargins = QgsMargins( marginLeft, marginTop, marginRight, marginBottom ); |
| 1776 | + svgSettings.forceVectorOutput = options.mForceVectorCheckBox->isChecked(); |
| 1777 | + |
| 1778 | + // force a refresh, to e.g. update data defined properties, tables, etc |
| 1779 | + mLayout->refresh(); |
| 1780 | + |
| 1781 | + QFileInfo fi( outputFileName ); |
| 1782 | + QgsLayoutExporter exporter( mLayout ); |
| 1783 | + switch ( exporter.exportToSvg( outputFileName, svgSettings ) ) |
| 1784 | + { |
| 1785 | + case QgsLayoutExporter::Success: |
| 1786 | + { |
| 1787 | + mMessageBar->pushMessage( tr( "Export layout" ), |
| 1788 | + tr( "Successfully exported layout to <a href=\"%1\">%2</a>" ).arg( QUrl::fromLocalFile( fi.path() ).toString(), outputFileName ), |
| 1789 | + QgsMessageBar::INFO, 0 ); |
| 1790 | + break; |
| 1791 | + } |
| 1792 | + |
| 1793 | + case QgsLayoutExporter::FileError: |
| 1794 | + QMessageBox::warning( this, tr( "Export to SVG" ), |
| 1795 | + tr( "Cannot write to %1.\n\nThis file may be open in another application." ).arg( outputFileName ), |
| 1796 | + QMessageBox::Ok, |
| 1797 | + QMessageBox::Ok ); |
| 1798 | + break; |
| 1799 | + |
| 1800 | + case QgsLayoutExporter::PrintError: |
| 1801 | + QMessageBox::warning( this, tr( "Export to SVG" ), |
| 1802 | + tr( "Could not create print device." ), |
| 1803 | + QMessageBox::Ok, |
| 1804 | + QMessageBox::Ok ); |
| 1805 | + break; |
| 1806 | + |
| 1807 | + |
| 1808 | + case QgsLayoutExporter::MemoryError: |
| 1809 | + QMessageBox::warning( this, tr( "Memory Allocation Error" ), |
| 1810 | + tr( "Exporting the SVG " |
| 1811 | + "resulted in a memory overflow.\n\n" |
| 1812 | + "Please try a lower resolution or a smaller paper size." ), |
| 1813 | + QMessageBox::Ok, QMessageBox::Ok ); |
| 1814 | + break; |
| 1815 | + } |
| 1816 | + |
| 1817 | + mView->setPaintingEnabled( true ); |
| 1818 | + mLayout->project()->writeEntry( QStringLiteral( "PAL" ), QStringLiteral( "/DrawOutlineLabels" ), prevSettingLabelsAsOutlines ); |
| 1819 | + QApplication::restoreOverrideCursor(); |
| 1820 | +} |
| 1821 | + |
1674 | 1822 | void QgsLayoutDesignerDialog::paste()
|
1675 | 1823 | {
|
1676 | 1824 | QPointF pt = mView->mapFromGlobal( QCursor::pos() );
|
@@ -1816,6 +1964,34 @@ void QgsLayoutDesignerDialog::showWmsPrintingWarning()
|
1816 | 1964 | }
|
1817 | 1965 | }
|
1818 | 1966 |
|
| 1967 | +void QgsLayoutDesignerDialog::showSvgExportWarning() |
| 1968 | +{ |
| 1969 | + QgsSettings settings; |
| 1970 | + |
| 1971 | + bool displaySVGWarning = settings.value( QStringLiteral( "/UI/displaySVGWarning" ), true ).toBool(); |
| 1972 | + |
| 1973 | + if ( displaySVGWarning ) |
| 1974 | + { |
| 1975 | + QgsMessageViewer m( this ); |
| 1976 | + m.setWindowTitle( tr( "Export as SVG" ) ); |
| 1977 | + m.setCheckBoxText( tr( "Don't show this message again" ) ); |
| 1978 | + m.setCheckBoxState( Qt::Unchecked ); |
| 1979 | + m.setCheckBoxVisible( true ); |
| 1980 | + m.setCheckBoxQgsSettingsLabel( QStringLiteral( "/UI/displaySVGWarning" ) ); |
| 1981 | + m.setMessageAsHtml( tr( "<p>The SVG export function in QGIS has several " |
| 1982 | + "problems due to bugs and deficiencies in the " ) |
| 1983 | + + tr( "underlying Qt SVG library. In particular, there are problems " |
| 1984 | + "with layers not being clipped to the map " |
| 1985 | + "bounding box.</p>" ) |
| 1986 | + + tr( "If you require a vector-based output file from " |
| 1987 | + "QGIS it is suggested that you try exporting " |
| 1988 | + "to PDF if the SVG output is not " |
| 1989 | + "satisfactory." |
| 1990 | + "</p>" ) ); |
| 1991 | + m.exec(); |
| 1992 | + } |
| 1993 | +} |
| 1994 | + |
1819 | 1995 | bool QgsLayoutDesignerDialog::requiresRasterization() const
|
1820 | 1996 | {
|
1821 | 1997 | QList< QgsLayoutItem *> items;
|
|
0 commit comments