Skip to content

Commit 953d2c4

Browse files
committedDec 17, 2017
[layouts] Resurrect action for exporting to raster images
...this time, without all the useful code locked away in app!
1 parent 113664f commit 953d2c4

8 files changed

+804
-0
lines changed
 

‎src/app/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ SET(QGIS_APP_SRCS
185185
layout/qgslayoutdesignerdialog.cpp
186186
layout/qgslayoutguidewidget.cpp
187187
layout/qgslayouthtmlwidget.cpp
188+
layout/qgslayoutimageexportoptionsdialog.cpp
188189
layout/qgslayoutitemslistview.cpp
189190
layout/qgslayoutappmenuprovider.cpp
190191
layout/qgslayoutlabelwidget.cpp
@@ -403,6 +404,7 @@ SET (QGIS_APP_MOC_HDRS
403404
layout/qgslayoutdesignerdialog.h
404405
layout/qgslayoutguidewidget.h
405406
layout/qgslayouthtmlwidget.h
407+
layout/qgslayoutimageexportoptionsdialog.h
406408
layout/qgslayoutitemslistview.h
407409
layout/qgslayoutlabelwidget.h
408410
layout/qgslayoutlegendwidget.h

‎src/app/layout/qgslayoutdesignerdialog.cpp

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@
3333
#include "qgslayoutviewtoolselect.h"
3434
#include "qgslayoutviewtooleditnodes.h"
3535
#include "qgslayoutitemwidget.h"
36+
#include "qgslayoutimageexportoptionsdialog.h"
37+
#include "qgslayoutitemmap.h"
38+
#include "qgsmessageviewer.h"
3639
#include "qgsgui.h"
3740
#include "qgslayoutitemguiregistry.h"
3841
#include "qgslayoutpropertieswidget.h"
@@ -168,6 +171,8 @@ QgsLayoutDesignerDialog::QgsLayoutDesignerDialog( QWidget *parent, Qt::WindowFla
168171
connect( mActionLayoutManager, &QAction::triggered, this, &QgsLayoutDesignerDialog::showManager );
169172
connect( mActionRemoveLayout, &QAction::triggered, this, &QgsLayoutDesignerDialog::deleteLayout );
170173

174+
connect( mActionExportAsImage, &QAction::triggered, this, &QgsLayoutDesignerDialog::exportToRaster );
175+
171176
connect( mActionShowGrid, &QAction::triggered, this, &QgsLayoutDesignerDialog::showGrid );
172177
connect( mActionSnapGrid, &QAction::triggered, this, &QgsLayoutDesignerDialog::snapToGrid );
173178

@@ -1410,6 +1415,123 @@ void QgsLayoutDesignerDialog::deleteLayout()
14101415
close();
14111416
}
14121417

1418+
void QgsLayoutDesignerDialog::exportToRaster()
1419+
{
1420+
if ( containsWmsLayers() )
1421+
showWmsPrintingWarning();
1422+
1423+
// Image size
1424+
double oneInchInLayoutUnits = mLayout->convertToLayoutUnits( QgsLayoutMeasurement( 1, QgsUnitTypes::LayoutInches ) );
1425+
QSizeF maxPageSize = mLayout->pageCollection()->maximumPageSize();
1426+
bool hasUniformPageSizes = mLayout->pageCollection()->hasUniformPageSizes();
1427+
int width = ( int )( mLayout->context().dpi() * maxPageSize.width() / oneInchInLayoutUnits );
1428+
int height = ( int )( mLayout->context().dpi() * maxPageSize.height() / oneInchInLayoutUnits );
1429+
double dpi = mLayout->context().dpi();
1430+
1431+
int memuse = width * height * 3 / 1000000; // pixmap + image
1432+
QgsDebugMsg( QString( "Image %1x%2" ).arg( width ).arg( height ) );
1433+
QgsDebugMsg( QString( "memuse = %1" ).arg( memuse ) );
1434+
1435+
if ( memuse > 400 ) // about 4500x4500
1436+
{
1437+
int answer = QMessageBox::warning( nullptr, tr( "Export layout" ),
1438+
tr( "To create an image of %1x%2 requires about %3 MB of memory. Proceed?" )
1439+
.arg( width ).arg( height ).arg( memuse ),
1440+
QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok );
1441+
1442+
raise();
1443+
if ( answer == QMessageBox::Cancel )
1444+
return;
1445+
}
1446+
1447+
//get some defaults from the composition
1448+
bool cropToContents = mLayout->customProperty( QStringLiteral( "imageCropToContents" ), false ).toBool();
1449+
int marginTop = mLayout->customProperty( QStringLiteral( "imageCropMarginTop" ), 0 ).toInt();
1450+
int marginRight = mLayout->customProperty( QStringLiteral( "imageCropMarginRight" ), 0 ).toInt();
1451+
int marginBottom = mLayout->customProperty( QStringLiteral( "imageCropMarginBottom" ), 0 ).toInt();
1452+
int marginLeft = mLayout->customProperty( QStringLiteral( "imageCropMarginLeft" ), 0 ).toInt();
1453+
1454+
QgsLayoutImageExportOptionsDialog imageDlg( this );
1455+
imageDlg.setImageSize( maxPageSize );
1456+
imageDlg.setResolution( dpi );
1457+
imageDlg.setCropToContents( cropToContents );
1458+
imageDlg.setCropMargins( marginTop, marginRight, marginBottom, marginLeft );
1459+
1460+
#if 0 //TODO
1461+
QgsAtlasComposition *atlasMap = &mComposition->atlasComposition();
1462+
#endif
1463+
1464+
QString outputFileName;
1465+
#if 0 //TODO
1466+
if ( atlasMap->enabled() && mComposition->atlasMode() == QgsComposition::PreviewAtlas )
1467+
{
1468+
QString lastUsedDir = settings.value( QStringLiteral( "UI/lastSaveAsImageDir" ), QDir::homePath() ).toString();
1469+
outputFileName = QDir( lastUsedDir ).filePath( atlasMap->currentFilename() );
1470+
}
1471+
#endif
1472+
1473+
#ifdef Q_OS_MAC
1474+
mQgis->activateWindow();
1475+
this->raise();
1476+
#endif
1477+
QPair<QString, QString> fileNExt = QgsGuiUtils::getSaveAsImageName( this, tr( "Save layout as" ), outputFileName );
1478+
this->activateWindow();
1479+
1480+
if ( fileNExt.first.isEmpty() )
1481+
{
1482+
return;
1483+
}
1484+
1485+
if ( !imageDlg.exec() )
1486+
return;
1487+
1488+
cropToContents = imageDlg.cropToContents();
1489+
imageDlg.getCropMargins( marginTop, marginRight, marginBottom, marginLeft );
1490+
mLayout->setCustomProperty( QStringLiteral( "imageCropToContents" ), cropToContents );
1491+
mLayout->setCustomProperty( QStringLiteral( "imageCropMarginTop" ), marginTop );
1492+
mLayout->setCustomProperty( QStringLiteral( "imageCropMarginRight" ), marginRight );
1493+
mLayout->setCustomProperty( QStringLiteral( "imageCropMarginBottom" ), marginBottom );
1494+
mLayout->setCustomProperty( QStringLiteral( "imageCropMarginLeft" ), marginLeft );
1495+
1496+
mView->setPaintingEnabled( false );
1497+
1498+
QgsLayoutExporter exporter( mLayout );
1499+
1500+
QgsLayoutExporter::ImageExportSettings settings;
1501+
settings.cropToContents = cropToContents;
1502+
settings.cropMargins = QgsMargins( marginLeft, marginTop, marginRight, marginBottom );
1503+
settings.dpi = imageDlg.resolution();
1504+
if ( hasUniformPageSizes )
1505+
{
1506+
settings.imageSize = QSize( imageDlg.imageWidth(), imageDlg.imageHeight() );
1507+
}
1508+
settings.generateWorldFile = mLayout->customProperty( QStringLiteral( "exportWorldFile" ), false ).toBool();
1509+
1510+
switch ( exporter.exportToImage( fileNExt.first, settings ) )
1511+
{
1512+
case QgsLayoutExporter::Success:
1513+
break;
1514+
1515+
case QgsLayoutExporter::FileError:
1516+
QMessageBox::warning( this, tr( "Image Export Error" ),
1517+
QString( tr( "Cannot write to %1.\n\nThis file may be open in another application." ) ).arg( exporter.errorFile() ),
1518+
QMessageBox::Ok,
1519+
QMessageBox::Ok );
1520+
break;
1521+
1522+
case QgsLayoutExporter::MemoryError:
1523+
QMessageBox::warning( nullptr, tr( "Memory Allocation Error" ),
1524+
tr( "Trying to create image %1 (%2×%3 @ %4dpi ) "
1525+
"resulted in a memory overflow.\n\n"
1526+
"Please try a lower resolution or a smaller paper size." )
1527+
.arg( exporter.errorFile() ).arg( imageDlg.imageWidth() ).arg( imageDlg.imageHeight() ).arg( settings.dpi ),
1528+
QMessageBox::Ok, QMessageBox::Ok );
1529+
break;
1530+
1531+
}
1532+
mView->setPaintingEnabled( true );
1533+
}
1534+
14131535
void QgsLayoutDesignerDialog::paste()
14141536
{
14151537
QPointF pt = mView->mapFromGlobal( QCursor::pos() );
@@ -1525,6 +1647,36 @@ void QgsLayoutDesignerDialog::initializeRegistry()
15251647

15261648
}
15271649

1650+
bool QgsLayoutDesignerDialog::containsWmsLayers() const
1651+
{
1652+
QList< QgsLayoutItemMap *> maps;
1653+
mLayout->layoutItems( maps );
1654+
1655+
for ( QgsLayoutItemMap *map : qgis::as_const( maps ) )
1656+
{
1657+
if ( map->containsWmsLayer() )
1658+
return true;
1659+
}
1660+
return false;
1661+
}
1662+
1663+
void QgsLayoutDesignerDialog::showWmsPrintingWarning()
1664+
{
1665+
QgsSettings settings;
1666+
bool displayWMSWarning = settings.value( QStringLiteral( "/UI/displayComposerWMSWarning" ), true ).toBool();
1667+
if ( displayWMSWarning )
1668+
{
1669+
QgsMessageViewer *m = new QgsMessageViewer( this );
1670+
m->setWindowTitle( tr( "Project Contains WMS Layers" ) );
1671+
m->setMessage( tr( "Some WMS servers (e.g. UMN mapserver) have a limit for the WIDTH and HEIGHT parameter. Printing layers from such servers may exceed this limit. If this is the case, the WMS layer will not be printed" ), QgsMessageOutput::MessageText );
1672+
m->setCheckBoxText( tr( "Don't show this message again" ) );
1673+
m->setCheckBoxState( Qt::Unchecked );
1674+
m->setCheckBoxVisible( true );
1675+
m->setCheckBoxQgsSettingsLabel( QStringLiteral( "/UI/displayComposerWMSWarning" ) );
1676+
m->exec(); //deleted on close
1677+
}
1678+
}
1679+
15281680
void QgsLayoutDesignerDialog::selectItems( const QList<QgsLayoutItem *> items )
15291681
{
15301682
for ( QGraphicsItem *item : items )

‎src/app/layout/qgslayoutdesignerdialog.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,7 @@ class QgsLayoutDesignerDialog: public QMainWindow, private Ui::QgsLayoutDesigner
274274
void showManager();
275275
void renameLayout();
276276
void deleteLayout();
277+
void exportToRaster();
277278

278279
private:
279280

@@ -360,6 +361,10 @@ class QgsLayoutDesignerDialog: public QMainWindow, private Ui::QgsLayoutDesigner
360361

361362
void initializeRegistry();
362363

364+
bool containsWmsLayers() const;
365+
366+
//! Displays a warning because of possible min/max size in WMS
367+
void showWmsPrintingWarning();
363368
};
364369

365370
#endif // QGSLAYOUTDESIGNERDIALOG_H
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
/***************************************************************************
2+
qgslayoutimageexportoptionsdialog.cpp
3+
-------------------------------------
4+
begin : December 2017
5+
copyright : (C) 2017 by Nyall Dawson
6+
email : nyall dot dawson at gmail dot com
7+
***************************************************************************/
8+
9+
/***************************************************************************
10+
* *
11+
* This program is free software; you can redistribute it and/or modify *
12+
* it under the terms of the GNU General Public License as published by *
13+
* the Free Software Foundation; either version 2 of the License, or *
14+
* (at your option) any later version. *
15+
* *
16+
***************************************************************************/
17+
18+
#include "qgslayoutimageexportoptionsdialog.h"
19+
#include "qgis.h"
20+
#include "qgssettings.h"
21+
#include "qgsgui.h"
22+
23+
#include <QCheckBox>
24+
#include <QPushButton>
25+
26+
QgsLayoutImageExportOptionsDialog::QgsLayoutImageExportOptionsDialog( QWidget *parent, Qt::WindowFlags flags )
27+
: QDialog( parent, flags )
28+
{
29+
setupUi( this );
30+
connect( mWidthSpinBox, static_cast < void ( QSpinBox::* )( int ) > ( &QSpinBox::valueChanged ), this, &QgsLayoutImageExportOptionsDialog::mWidthSpinBox_valueChanged );
31+
connect( mHeightSpinBox, static_cast < void ( QSpinBox::* )( int ) > ( &QSpinBox::valueChanged ), this, &QgsLayoutImageExportOptionsDialog::mHeightSpinBox_valueChanged );
32+
connect( mResolutionSpinBox, static_cast < void ( QSpinBox::* )( int ) > ( &QSpinBox::valueChanged ), this, &QgsLayoutImageExportOptionsDialog::mResolutionSpinBox_valueChanged );
33+
34+
connect( mClipToContentGroupBox, &QGroupBox::toggled, this, &QgsLayoutImageExportOptionsDialog::clipToContentsToggled );
35+
36+
QgsGui::instance()->enableAutoGeometryRestore( this );
37+
}
38+
39+
void QgsLayoutImageExportOptionsDialog::setResolution( double resolution )
40+
{
41+
mResolutionSpinBox->setValue( resolution );
42+
43+
if ( mImageSize.isValid() )
44+
{
45+
mWidthSpinBox->blockSignals( true );
46+
mHeightSpinBox->blockSignals( true );
47+
if ( mClipToContentGroupBox->isChecked() )
48+
{
49+
mWidthSpinBox->setValue( 0 );
50+
mHeightSpinBox->setValue( 0 );
51+
}
52+
else
53+
{
54+
mWidthSpinBox->setValue( mImageSize.width() * resolution / 25.4 );
55+
mHeightSpinBox->setValue( mImageSize.height() * resolution / 25.4 );
56+
}
57+
mWidthSpinBox->blockSignals( false );
58+
mHeightSpinBox->blockSignals( false );
59+
}
60+
}
61+
62+
double QgsLayoutImageExportOptionsDialog::resolution() const
63+
{
64+
return mResolutionSpinBox->value();
65+
}
66+
67+
void QgsLayoutImageExportOptionsDialog::setImageSize( QSizeF size )
68+
{
69+
mImageSize = size;
70+
mWidthSpinBox->blockSignals( true );
71+
mHeightSpinBox->blockSignals( true );
72+
mWidthSpinBox->setValue( size.width() * mResolutionSpinBox->value() / 25.4 );
73+
mHeightSpinBox->setValue( size.height() * mResolutionSpinBox->value() / 25.4 );
74+
mWidthSpinBox->blockSignals( false );
75+
mHeightSpinBox->blockSignals( false );
76+
}
77+
78+
int QgsLayoutImageExportOptionsDialog::imageWidth() const
79+
{
80+
return mWidthSpinBox->value();
81+
}
82+
83+
int QgsLayoutImageExportOptionsDialog::imageHeight() const
84+
{
85+
return mHeightSpinBox->value();
86+
}
87+
88+
void QgsLayoutImageExportOptionsDialog::setCropToContents( bool crop )
89+
{
90+
mClipToContentGroupBox->setChecked( crop );
91+
}
92+
93+
bool QgsLayoutImageExportOptionsDialog::cropToContents() const
94+
{
95+
return mClipToContentGroupBox->isChecked();
96+
}
97+
98+
void QgsLayoutImageExportOptionsDialog::getCropMargins( int &topMargin, int &rightMargin, int &bottomMargin, int &leftMargin ) const
99+
{
100+
topMargin = mTopMarginSpinBox->value();
101+
rightMargin = mRightMarginSpinBox->value();
102+
bottomMargin = mBottomMarginSpinBox->value();
103+
leftMargin = mLeftMarginSpinBox->value();
104+
}
105+
106+
void QgsLayoutImageExportOptionsDialog::setCropMargins( int topMargin, int rightMargin, int bottomMargin, int leftMargin )
107+
{
108+
mTopMarginSpinBox->setValue( topMargin );
109+
mRightMarginSpinBox->setValue( rightMargin );
110+
mBottomMarginSpinBox->setValue( bottomMargin );
111+
mLeftMarginSpinBox->setValue( leftMargin );
112+
}
113+
114+
void QgsLayoutImageExportOptionsDialog::mWidthSpinBox_valueChanged( int value )
115+
{
116+
mHeightSpinBox->blockSignals( true );
117+
mResolutionSpinBox->blockSignals( true );
118+
mHeightSpinBox->setValue( mImageSize.height() * value / mImageSize.width() );
119+
mResolutionSpinBox->setValue( value * 25.4 / mImageSize.width() );
120+
mHeightSpinBox->blockSignals( false );
121+
mResolutionSpinBox->blockSignals( false );
122+
}
123+
124+
void QgsLayoutImageExportOptionsDialog::mHeightSpinBox_valueChanged( int value )
125+
{
126+
mWidthSpinBox->blockSignals( true );
127+
mResolutionSpinBox->blockSignals( true );
128+
mWidthSpinBox->setValue( mImageSize.width() * value / mImageSize.height() );
129+
mResolutionSpinBox->setValue( value * 25.4 / mImageSize.height() );
130+
mWidthSpinBox->blockSignals( false );
131+
mResolutionSpinBox->blockSignals( false );
132+
}
133+
134+
void QgsLayoutImageExportOptionsDialog::mResolutionSpinBox_valueChanged( int value )
135+
{
136+
mWidthSpinBox->blockSignals( true );
137+
mHeightSpinBox->blockSignals( true );
138+
if ( mClipToContentGroupBox->isChecked() )
139+
{
140+
mWidthSpinBox->setValue( 0 );
141+
mHeightSpinBox->setValue( 0 );
142+
}
143+
else
144+
{
145+
mWidthSpinBox->setValue( mImageSize.width() * value / 25.4 );
146+
mHeightSpinBox->setValue( mImageSize.height() * value / 25.4 );
147+
}
148+
mWidthSpinBox->blockSignals( false );
149+
mHeightSpinBox->blockSignals( false );
150+
}
151+
152+
void QgsLayoutImageExportOptionsDialog::clipToContentsToggled( bool state )
153+
{
154+
mWidthSpinBox->setEnabled( !state );
155+
mHeightSpinBox->setEnabled( !state );
156+
157+
if ( state )
158+
{
159+
whileBlocking( mWidthSpinBox )->setValue( 0 );
160+
whileBlocking( mHeightSpinBox )->setValue( 0 );
161+
}
162+
else
163+
{
164+
whileBlocking( mWidthSpinBox )->setValue( mImageSize.width() * mResolutionSpinBox->value() / 25.4 );
165+
whileBlocking( mHeightSpinBox )->setValue( mImageSize.height() * mResolutionSpinBox->value() / 25.4 );
166+
}
167+
}
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
/***************************************************************************
2+
qgslayoutimageexportoptionsdialog.h
3+
-------------------------------------
4+
begin : December 2017
5+
copyright : (C) 2017 by Nyall Dawson
6+
email : nyall dot dawson at gmail dot com
7+
***************************************************************************/
8+
9+
/***************************************************************************
10+
* *
11+
* This program is free software; you can redistribute it and/or modify *
12+
* it under the terms of the GNU General Public License as published by *
13+
* the Free Software Foundation; either version 2 of the License, or *
14+
* (at your option) any later version. *
15+
* *
16+
***************************************************************************/
17+
18+
#ifndef QGSLAYOUTIMAGEEXPORTOPTIONSDIALOG_H
19+
#define QGSLAYOUTIMAGEEXPORTOPTIONSDIALOG_H
20+
21+
#include <QDialog>
22+
#include "ui_qgslayoutimageexportoptions.h"
23+
24+
25+
/**
26+
* A dialog for customising the properties of an exported image file.
27+
*/
28+
class QgsLayoutImageExportOptionsDialog: public QDialog, private Ui::QgsLayoutImageExportOptionsDialog
29+
{
30+
Q_OBJECT
31+
32+
public:
33+
34+
/**
35+
* Constructor for QgsLayoutImageExportOptionsDialog
36+
* \param parent parent widget
37+
* \param flags window flags
38+
*/
39+
QgsLayoutImageExportOptionsDialog( QWidget *parent = nullptr, Qt::WindowFlags flags = 0 );
40+
41+
/**
42+
* Sets the initial resolution displayed in the dialog.
43+
* \param resolution default resolution in DPI
44+
* \see resolution()
45+
*/
46+
void setResolution( double resolution );
47+
48+
/**
49+
* Returns the selected resolution from the dialog.
50+
* \returns image resolution in DPI
51+
* \see setResolution()
52+
*/
53+
double resolution() const;
54+
55+
/**
56+
* Sets the target image size. This is used to calculate the default size in pixels
57+
* and also for determining the image's width to height ratio.
58+
* \param size image size
59+
*/
60+
void setImageSize( QSizeF size );
61+
62+
/**
63+
* Returns the user-set image width in pixels.
64+
* \see imageHeight
65+
*/
66+
int imageWidth() const;
67+
68+
/**
69+
* Returns the user-set image height in pixels.
70+
* \see imageWidth
71+
*/
72+
int imageHeight() const;
73+
74+
/**
75+
* Sets whether the crop to contents option should be checked in the dialog
76+
* \param crop set to true to check crop to contents
77+
* \see cropToContents()
78+
*/
79+
void setCropToContents( bool crop );
80+
81+
/**
82+
* Returns whether the crop to contents option is checked in the dialog.
83+
* \see setCropToContents()
84+
*/
85+
bool cropToContents() const;
86+
87+
/**
88+
* Fetches the current crop to contents margin values, in pixels.
89+
* \param topMargin destination for top margin
90+
* \param rightMargin destination for right margin
91+
* \param bottomMargin destination for bottom margin
92+
* \param leftMargin destination for left margin
93+
*/
94+
void getCropMargins( int &topMargin, int &rightMargin, int &bottomMargin, int &leftMargin ) const;
95+
96+
/**
97+
* Sets the current crop to contents margin values, in pixels.
98+
* \param topMargin top margin
99+
* \param rightMargin right margin
100+
* \param bottomMargin bottom margin
101+
* \param leftMargin left margin
102+
*/
103+
void setCropMargins( int topMargin, int rightMargin, int bottomMargin, int leftMargin );
104+
105+
private slots:
106+
107+
void mWidthSpinBox_valueChanged( int value );
108+
void mHeightSpinBox_valueChanged( int value );
109+
void mResolutionSpinBox_valueChanged( int value );
110+
void clipToContentsToggled( bool state );
111+
112+
private:
113+
114+
QSizeF mImageSize;
115+
116+
117+
};
118+
119+
#endif // QGSLAYOUTIMAGEEXPORTOPTIONSDIALOG_H

‎src/app/layout/qgslayoutpropertieswidget.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ QgsLayoutPropertiesWidget::QgsLayoutPropertiesWidget( QWidget *parent, QgsLayout
5656

5757
bool exportWorldFile = mLayout->customProperty( QStringLiteral( "exportWorldFile" ), false ).toBool();
5858
mGenerateWorldFileCheckBox->setChecked( exportWorldFile );
59+
connect( mGenerateWorldFileCheckBox, &QCheckBox::toggled, this, &QgsLayoutPropertiesWidget::worldFileToggled );
5960

6061
mTopMarginSpinBox->setValue( topMargin );
6162
mMarginUnitsComboBox->linkToWidget( mTopMarginSpinBox );

‎src/ui/layout/qgslayoutdesignerbase.ui

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@
6969
<addaction name="mActionLayoutManager"/>
7070
<addaction name="mActionLoadFromTemplate"/>
7171
<addaction name="mActionSaveAsTemplate"/>
72+
<addaction name="separator"/>
73+
<addaction name="mActionExportAsImage"/>
74+
<addaction name="mActionExportAsSVG"/>
75+
<addaction name="mActionExportAsPDF"/>
7276
</widget>
7377
<widget class="QToolBar" name="mToolsToolbar">
7478
<property name="windowTitle">
@@ -113,6 +117,10 @@
113117
<addaction name="mActionLoadFromTemplate"/>
114118
<addaction name="mActionSaveAsTemplate"/>
115119
<addaction name="separator"/>
120+
<addaction name="mActionExportAsImage"/>
121+
<addaction name="mActionExportAsSVG"/>
122+
<addaction name="mActionExportAsPDF"/>
123+
<addaction name="separator"/>
116124
<addaction name="mActionClose"/>
117125
</widget>
118126
<widget class="QMenu" name="mItemMenu">
@@ -1173,6 +1181,36 @@
11731181
<string>Delete layout</string>
11741182
</property>
11751183
</action>
1184+
<action name="mActionExportAsImage">
1185+
<property name="icon">
1186+
<iconset resource="../../../images/images.qrc">
1187+
<normaloff>:/images/themes/default/mActionSaveMapAsImage.svg</normaloff>:/images/themes/default/mActionSaveMapAsImage.svg</iconset>
1188+
</property>
1189+
<property name="text">
1190+
<string>Export as &amp;Image…</string>
1191+
</property>
1192+
<property name="toolTip">
1193+
<string>Export as image</string>
1194+
</property>
1195+
</action>
1196+
<action name="mActionExportAsPDF">
1197+
<property name="icon">
1198+
<iconset resource="../../../images/images.qrc">
1199+
<normaloff>:/images/themes/default/mActionSaveAsPDF.svg</normaloff>:/images/themes/default/mActionSaveAsPDF.svg</iconset>
1200+
</property>
1201+
<property name="text">
1202+
<string>&amp;Export as PDF…</string>
1203+
</property>
1204+
</action>
1205+
<action name="mActionExportAsSVG">
1206+
<property name="icon">
1207+
<iconset resource="../../../images/images.qrc">
1208+
<normaloff>:/images/themes/default/mActionSaveAsSVG.svg</normaloff>:/images/themes/default/mActionSaveAsSVG.svg</iconset>
1209+
</property>
1210+
<property name="text">
1211+
<string>Export as S&amp;VG…</string>
1212+
</property>
1213+
</action>
11761214
</widget>
11771215
<resources>
11781216
<include location="../../../images/images.qrc"/>
Lines changed: 320 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,320 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<ui version="4.0">
3+
<class>QgsLayoutImageExportOptionsDialog</class>
4+
<widget class="QDialog" name="QgsLayoutImageExportOptionsDialog">
5+
<property name="geometry">
6+
<rect>
7+
<x>0</x>
8+
<y>0</y>
9+
<width>533</width>
10+
<height>651</height>
11+
</rect>
12+
</property>
13+
<property name="windowTitle">
14+
<string>Image Export Options</string>
15+
</property>
16+
<layout class="QVBoxLayout" name="verticalLayout">
17+
<item>
18+
<widget class="QGroupBox" name="groupBox">
19+
<property name="title">
20+
<string>Export options</string>
21+
</property>
22+
<layout class="QGridLayout" name="gridLayout">
23+
<item row="0" column="0" colspan="2">
24+
<widget class="QLabel" name="label_9">
25+
<property name="text">
26+
<string>Export resolution</string>
27+
</property>
28+
</widget>
29+
</item>
30+
<item row="2" column="0" colspan="2">
31+
<widget class="QLabel" name="label_13">
32+
<property name="text">
33+
<string>Page height</string>
34+
</property>
35+
</widget>
36+
</item>
37+
<item row="0" column="2" colspan="2">
38+
<widget class="QgsSpinBox" name="mResolutionSpinBox">
39+
<property name="suffix">
40+
<string> dpi</string>
41+
</property>
42+
<property name="prefix">
43+
<string/>
44+
</property>
45+
<property name="maximum">
46+
<number>3000</number>
47+
</property>
48+
<property name="showClearButton" stdset="0">
49+
<bool>false</bool>
50+
</property>
51+
</widget>
52+
</item>
53+
<item row="1" column="2" colspan="2">
54+
<widget class="QgsSpinBox" name="mWidthSpinBox">
55+
<property name="specialValueText">
56+
<string>Auto</string>
57+
</property>
58+
<property name="suffix">
59+
<string> px</string>
60+
</property>
61+
<property name="prefix">
62+
<string/>
63+
</property>
64+
<property name="minimum">
65+
<number>0</number>
66+
</property>
67+
<property name="maximum">
68+
<number>99999999</number>
69+
</property>
70+
<property name="showClearButton" stdset="0">
71+
<bool>false</bool>
72+
</property>
73+
</widget>
74+
</item>
75+
<item row="1" column="0">
76+
<widget class="QLabel" name="label_10">
77+
<property name="text">
78+
<string>Page width</string>
79+
</property>
80+
</widget>
81+
</item>
82+
<item row="2" column="2" colspan="2">
83+
<widget class="QgsSpinBox" name="mHeightSpinBox">
84+
<property name="specialValueText">
85+
<string>Auto</string>
86+
</property>
87+
<property name="suffix">
88+
<string> px</string>
89+
</property>
90+
<property name="prefix">
91+
<string/>
92+
</property>
93+
<property name="minimum">
94+
<number>0</number>
95+
</property>
96+
<property name="maximum">
97+
<number>99999999</number>
98+
</property>
99+
<property name="showClearButton" stdset="0">
100+
<bool>false</bool>
101+
</property>
102+
</widget>
103+
</item>
104+
<item row="1" column="4">
105+
<spacer name="horizontalSpacer_3">
106+
<property name="orientation">
107+
<enum>Qt::Horizontal</enum>
108+
</property>
109+
<property name="sizeHint" stdset="0">
110+
<size>
111+
<width>40</width>
112+
<height>20</height>
113+
</size>
114+
</property>
115+
</spacer>
116+
</item>
117+
</layout>
118+
</widget>
119+
</item>
120+
<item>
121+
<widget class="QgsCollapsibleGroupBoxBasic" name="mClipToContentGroupBox">
122+
<property name="title">
123+
<string>Crop to content</string>
124+
</property>
125+
<property name="checkable">
126+
<bool>true</bool>
127+
</property>
128+
<property name="checked">
129+
<bool>false</bool>
130+
</property>
131+
<layout class="QVBoxLayout" name="verticalLayout_5">
132+
<item>
133+
<layout class="QGridLayout" name="gridLayout_5">
134+
<item row="1" column="0" colspan="4">
135+
<layout class="QHBoxLayout" name="horizontalLayout_7">
136+
<item>
137+
<widget class="QLabel" name="label_5">
138+
<property name="text">
139+
<string>Left</string>
140+
</property>
141+
</widget>
142+
</item>
143+
<item>
144+
<widget class="QgsSpinBox" name="mLeftMarginSpinBox">
145+
<property name="suffix">
146+
<string> px</string>
147+
</property>
148+
<property name="maximum">
149+
<number>1000</number>
150+
</property>
151+
</widget>
152+
</item>
153+
<item>
154+
<widget class="QLabel" name="label_11">
155+
<property name="text">
156+
<string>Right</string>
157+
</property>
158+
</widget>
159+
</item>
160+
<item>
161+
<widget class="QgsSpinBox" name="mRightMarginSpinBox">
162+
<property name="suffix">
163+
<string> px</string>
164+
</property>
165+
<property name="maximum">
166+
<number>1000</number>
167+
</property>
168+
</widget>
169+
</item>
170+
</layout>
171+
</item>
172+
<item row="2" column="1">
173+
<widget class="QLabel" name="label_12">
174+
<property name="text">
175+
<string>Bottom</string>
176+
</property>
177+
</widget>
178+
</item>
179+
<item row="0" column="1">
180+
<widget class="QLabel" name="label_4">
181+
<property name="text">
182+
<string>Top margin</string>
183+
</property>
184+
</widget>
185+
</item>
186+
<item row="0" column="3">
187+
<spacer name="horizontalSpacer_2">
188+
<property name="orientation">
189+
<enum>Qt::Horizontal</enum>
190+
</property>
191+
<property name="sizeHint" stdset="0">
192+
<size>
193+
<width>40</width>
194+
<height>20</height>
195+
</size>
196+
</property>
197+
</spacer>
198+
</item>
199+
<item row="0" column="0">
200+
<spacer name="horizontalSpacer">
201+
<property name="orientation">
202+
<enum>Qt::Horizontal</enum>
203+
</property>
204+
<property name="sizeHint" stdset="0">
205+
<size>
206+
<width>40</width>
207+
<height>20</height>
208+
</size>
209+
</property>
210+
</spacer>
211+
</item>
212+
<item row="0" column="2">
213+
<widget class="QgsSpinBox" name="mTopMarginSpinBox">
214+
<property name="suffix">
215+
<string> px</string>
216+
</property>
217+
<property name="maximum">
218+
<number>1000</number>
219+
</property>
220+
</widget>
221+
</item>
222+
<item row="2" column="2">
223+
<widget class="QgsSpinBox" name="mBottomMarginSpinBox">
224+
<property name="suffix">
225+
<string> px</string>
226+
</property>
227+
<property name="maximum">
228+
<number>1000</number>
229+
</property>
230+
</widget>
231+
</item>
232+
</layout>
233+
</item>
234+
</layout>
235+
</widget>
236+
</item>
237+
<item>
238+
<spacer name="verticalSpacer">
239+
<property name="orientation">
240+
<enum>Qt::Vertical</enum>
241+
</property>
242+
<property name="sizeHint" stdset="0">
243+
<size>
244+
<width>20</width>
245+
<height>40</height>
246+
</size>
247+
</property>
248+
</spacer>
249+
</item>
250+
<item>
251+
<widget class="QDialogButtonBox" name="buttonBox">
252+
<property name="orientation">
253+
<enum>Qt::Horizontal</enum>
254+
</property>
255+
<property name="standardButtons">
256+
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Save</set>
257+
</property>
258+
</widget>
259+
</item>
260+
</layout>
261+
</widget>
262+
<customwidgets>
263+
<customwidget>
264+
<class>QgsCollapsibleGroupBoxBasic</class>
265+
<extends>QGroupBox</extends>
266+
<header>qgscollapsiblegroupbox.h</header>
267+
<container>1</container>
268+
</customwidget>
269+
<customwidget>
270+
<class>QgsSpinBox</class>
271+
<extends>QSpinBox</extends>
272+
<header>qgsspinbox.h</header>
273+
</customwidget>
274+
</customwidgets>
275+
<tabstops>
276+
<tabstop>mResolutionSpinBox</tabstop>
277+
<tabstop>mWidthSpinBox</tabstop>
278+
<tabstop>mHeightSpinBox</tabstop>
279+
<tabstop>mClipToContentGroupBox</tabstop>
280+
<tabstop>mTopMarginSpinBox</tabstop>
281+
<tabstop>mLeftMarginSpinBox</tabstop>
282+
<tabstop>mRightMarginSpinBox</tabstop>
283+
<tabstop>mBottomMarginSpinBox</tabstop>
284+
</tabstops>
285+
<resources/>
286+
<connections>
287+
<connection>
288+
<sender>buttonBox</sender>
289+
<signal>accepted()</signal>
290+
<receiver>QgsLayoutImageExportOptionsDialog</receiver>
291+
<slot>accept()</slot>
292+
<hints>
293+
<hint type="sourcelabel">
294+
<x>248</x>
295+
<y>254</y>
296+
</hint>
297+
<hint type="destinationlabel">
298+
<x>157</x>
299+
<y>274</y>
300+
</hint>
301+
</hints>
302+
</connection>
303+
<connection>
304+
<sender>buttonBox</sender>
305+
<signal>rejected()</signal>
306+
<receiver>QgsLayoutImageExportOptionsDialog</receiver>
307+
<slot>reject()</slot>
308+
<hints>
309+
<hint type="sourcelabel">
310+
<x>316</x>
311+
<y>260</y>
312+
</hint>
313+
<hint type="destinationlabel">
314+
<x>286</x>
315+
<y>274</y>
316+
</hint>
317+
</hints>
318+
</connection>
319+
</connections>
320+
</ui>

0 commit comments

Comments
 (0)
Please sign in to comment.