Skip to content

Commit 6acd326

Browse files
authored
[FEATURE] Draw extent onto canvas in save as image/PDF dialog (#4878)
1 parent 71b9ce2 commit 6acd326

File tree

10 files changed

+411
-2
lines changed

10 files changed

+411
-2
lines changed

python/gui/gui_auto.sip

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@
137137
%Include qgsmaptoolcapture.sip
138138
%Include qgsmaptooledit.sip
139139
%Include qgsmaptoolemitpoint.sip
140+
%Include qgsmaptoolextent.sip
140141
%Include qgsmaptoolidentify.sip
141142
%Include qgsmaptoolidentifyfeature.sip
142143
%Include qgsmaptoolpan.sip

python/gui/qgsextentgroupbox.sip

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111

1212

13+
14+
1315
class QgsExtentGroupBox : QgsCollapsibleGroupBox
1416
{
1517
%Docstring
@@ -34,6 +36,7 @@ class QgsExtentGroupBox : QgsCollapsibleGroupBox
3436
CurrentExtent,
3537
UserExtent,
3638
ProjectLayerExtent,
39+
DrawOnCanvas,
3740
};
3841

3942
explicit QgsExtentGroupBox( QWidget *parent /TransferThis/ = 0 );
@@ -124,6 +127,13 @@ class QgsExtentGroupBox : QgsCollapsibleGroupBox
124127
:rtype: str
125128
%End
126129

130+
void setMapCanvas( QgsMapCanvas *canvas );
131+
%Docstring
132+
Sets the map canvas to enable dragging of extent on a canvas.
133+
\param canvas the map canvas
134+
.. versionadded:: 3.0
135+
%End
136+
127137
public slots:
128138

129139
void setOutputExtentFromOriginal();
@@ -145,6 +155,12 @@ class QgsExtentGroupBox : QgsCollapsibleGroupBox
145155
%Docstring
146156
Sets the output extent to match a ``layer``'s extent (may be transformed to output CRS).
147157
.. versionadded:: 3.0
158+
%End
159+
160+
void setOutputExtentFromDrawOnCanvas();
161+
%Docstring
162+
Sets the output extent by dragging on the canvas.
163+
.. versionadded:: 3.0
148164
%End
149165

150166
signals:

python/gui/qgsmaptoolextent.sip

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/************************************************************************
2+
* This file has been generated automatically from *
3+
* *
4+
* src/gui/qgsmaptoolextent.h *
5+
* *
6+
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
7+
************************************************************************/
8+
9+
10+
11+
12+
13+
14+
class QgsMapToolExtent : QgsMapTool
15+
{
16+
%Docstring
17+
A map tool that emits an extent from a rectangle drawn onto the map canvas.
18+
.. versionadded:: 3.0
19+
%End
20+
21+
%TypeHeaderCode
22+
#include "qgsmaptoolextent.h"
23+
%End
24+
public:
25+
26+
QgsMapToolExtent( QgsMapCanvas *canvas );
27+
%Docstring
28+
constructor
29+
%End
30+
31+
virtual Flags flags() const;
32+
virtual void canvasMoveEvent( QgsMapMouseEvent *e );
33+
virtual void canvasPressEvent( QgsMapMouseEvent *e );
34+
virtual void canvasReleaseEvent( QgsMapMouseEvent *e );
35+
virtual void activate();
36+
virtual void deactivate();
37+
38+
void setRatio( QSize ratio );
39+
%Docstring
40+
Sets a fixed aspect ratio to be used when dragging extent onto the canvas.
41+
To unset a fixed aspect ratio, set the width and height to zero.
42+
\param ratio aspect ratio's width and height
43+
*
44+
%End
45+
46+
QSize ratio() const;
47+
%Docstring
48+
Returns the current fixed aspect ratio to be used when dragging extent onto the canvas.
49+
If the aspect ratio isn't fixed, the width and height will be set to zero.
50+
*
51+
:rtype: QSize
52+
%End
53+
54+
QgsRectangle extent() const;
55+
%Docstring
56+
Returns the current extent drawn onto the canvas.
57+
:rtype: QgsRectangle
58+
%End
59+
60+
signals:
61+
62+
void extentChanged( const QgsRectangle &extent );
63+
%Docstring
64+
signal emitted on extent change
65+
%End
66+
67+
};
68+
69+
/************************************************************************
70+
* This file has been generated automatically from *
71+
* *
72+
* src/gui/qgsmaptoolextent.h *
73+
* *
74+
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
75+
************************************************************************/

src/app/qgsmapsavedialog.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ QgsMapSaveDialog::QgsMapSaveDialog( QWidget *parent, QgsMapCanvas *mapCanvas, QL
5959
mExtentGroupBox->setOutputCrs( ms.destinationCrs() );
6060
mExtentGroupBox->setCurrentExtent( mExtent, ms.destinationCrs() );
6161
mExtentGroupBox->setOutputExtentFromCurrent();
62+
mExtentGroupBox->setMapCanvas( mapCanvas );
6263

6364
mScaleWidget->setScale( ms.scale() );
6465
mScaleWidget->setMapCanvas( mMapCanvas );

src/gui/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,7 @@ SET(QGIS_GUI_SRCS
283283
qgsmaptoolcapture.cpp
284284
qgsmaptooledit.cpp
285285
qgsmaptoolemitpoint.cpp
286+
qgsmaptoolextent.cpp
286287
qgsmaptoolidentify.cpp
287288
qgsmaptoolidentifyfeature.cpp
288289
qgsmaptoolpan.cpp
@@ -437,6 +438,7 @@ SET(QGIS_GUI_MOC_HDRS
437438
qgsmaptoolcapture.h
438439
qgsmaptooledit.h
439440
qgsmaptoolemitpoint.h
441+
qgsmaptoolextent.h
440442
qgsmaptoolidentify.h
441443
qgsmaptoolidentifyfeature.h
442444
qgsmaptoolpan.h

src/gui/qgsextentgroupbox.cpp

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,17 @@
1212
* (at your option) any later version. *
1313
* *
1414
***************************************************************************/
15+
1516
#include "qgsextentgroupbox.h"
1617

18+
#include "qgslogger.h"
1719
#include "qgscoordinatetransform.h"
1820
#include "qgsrasterblock.h"
21+
#include "qgsmapcanvas.h"
1922
#include "qgsmaplayermodel.h"
2023
#include "qgsexception.h"
2124
#include "qgsproject.h"
25+
2226
#include <QMenu>
2327
#include <QAction>
2428

@@ -40,13 +44,15 @@ QgsExtentGroupBox::QgsExtentGroupBox( QWidget *parent )
4044
mYMaxLineEdit->setValidator( new QDoubleValidator( this ) );
4145

4246
mOriginalExtentButton->setVisible( false );
47+
mButtonDrawOnCanvas->setVisible( false );
4348

4449
connect( mCurrentExtentButton, &QAbstractButton::clicked, this, &QgsExtentGroupBox::setOutputExtentFromCurrent );
4550
connect( mOriginalExtentButton, &QAbstractButton::clicked, this, &QgsExtentGroupBox::setOutputExtentFromOriginal );
51+
connect( mButtonDrawOnCanvas, &QAbstractButton::clicked, this, &QgsExtentGroupBox::setOutputExtentFromDrawOnCanvas );
52+
4653
connect( this, &QGroupBox::clicked, this, &QgsExtentGroupBox::groupBoxClicked );
4754
}
4855

49-
5056
void QgsExtentGroupBox::setOriginalExtent( const QgsRectangle &originalExtent, const QgsCoordinateReferenceSystem &originalCrs )
5157
{
5258
mOriginalExtent = originalExtent;
@@ -83,6 +89,11 @@ void QgsExtentGroupBox::setOutputCrs( const QgsCoordinateReferenceSystem &output
8389
setOutputExtentFromLayer( mExtentLayer.data() );
8490
break;
8591

92+
case DrawOnCanvas:
93+
mOutputCrs = outputCrs;
94+
extentDrawn( outputExtent() );
95+
break;
96+
8697
case UserExtent:
8798
try
8899
{
@@ -167,6 +178,9 @@ void QgsExtentGroupBox::updateTitle()
167178
case ProjectLayerExtent:
168179
msg = mExtentLayerName;
169180
break;
181+
case DrawOnCanvas:
182+
msg = tr( "drawn on canvas" );
183+
break;
170184
}
171185
if ( isCheckable() && !isChecked() )
172186
msg = tr( "none" );
@@ -213,7 +227,17 @@ void QgsExtentGroupBox::setExtentToLayerExtent( const QString &layerId )
213227

214228
void QgsExtentGroupBox::setOutputExtentFromCurrent()
215229
{
216-
setOutputExtent( mCurrentExtent, mCurrentCrs, CurrentExtent );
230+
if ( mCanvas )
231+
{
232+
// Use unrotated visible extent to insure output size and scale matches canvas
233+
QgsMapSettings ms = mCanvas->mapSettings();
234+
ms.setRotation( 0 );
235+
setOutputExtent( ms.visibleExtent(), ms.destinationCrs(), CurrentExtent );
236+
}
237+
else
238+
{
239+
setOutputExtent( mCurrentExtent, mCurrentCrs, CurrentExtent );
240+
}
217241
}
218242

219243

@@ -238,6 +262,34 @@ void QgsExtentGroupBox::setOutputExtentFromLayer( const QgsMapLayer *layer )
238262
setOutputExtent( layer->extent(), layer->crs(), ProjectLayerExtent );
239263
}
240264

265+
void QgsExtentGroupBox::setOutputExtentFromDrawOnCanvas()
266+
{
267+
if ( mCanvas )
268+
{
269+
mMapToolPrevious = mCanvas->mapTool();
270+
if ( !mMapToolExtent )
271+
{
272+
mMapToolExtent.reset( new QgsMapToolExtent( mCanvas ) );
273+
connect( mMapToolExtent.get(), &QgsMapToolExtent::extentChanged, this, &QgsExtentGroupBox::extentDrawn );
274+
connect( mMapToolExtent.get(), &QgsMapTool::deactivated, this, [ = ]
275+
{
276+
window()->setVisible( true );
277+
mMapToolPrevious = nullptr;
278+
} );
279+
}
280+
mCanvas->setMapTool( mMapToolExtent.get() );
281+
window()->setVisible( false );
282+
}
283+
}
284+
285+
void QgsExtentGroupBox::extentDrawn( const QgsRectangle &extent )
286+
{
287+
setOutputExtent( extent, mCanvas->mapSettings().destinationCrs(), DrawOnCanvas );
288+
mCanvas->setMapTool( mMapToolPrevious );
289+
window()->setVisible( true );
290+
mMapToolPrevious = nullptr;
291+
}
292+
241293
void QgsExtentGroupBox::groupBoxClicked()
242294
{
243295
if ( !isCheckable() )
@@ -269,3 +321,16 @@ QString QgsExtentGroupBox::titleBase() const
269321
{
270322
return mTitleBase;
271323
}
324+
325+
void QgsExtentGroupBox::setMapCanvas( QgsMapCanvas *canvas )
326+
{
327+
if ( canvas )
328+
{
329+
mCanvas = canvas;
330+
mButtonDrawOnCanvas->setVisible( true );
331+
}
332+
else
333+
{
334+
mButtonDrawOnCanvas->setVisible( false );
335+
}
336+
}

src/gui/qgsextentgroupbox.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,13 @@
1212
* (at your option) any later version. *
1313
* *
1414
***************************************************************************/
15+
1516
#ifndef QGSEXTENTGROUPBOX_H
1617
#define QGSEXTENTGROUPBOX_H
1718

1819
#include "qgscollapsiblegroupbox.h"
20+
#include "qgsmaptool.h"
21+
#include "qgsmaptoolextent.h"
1922
#include "qgis.h"
2023

2124
#include "ui_qgsextentgroupboxwidget.h"
@@ -24,6 +27,8 @@
2427
#include "qgsrectangle.h"
2528
#include "qgis_gui.h"
2629

30+
#include <memory>
31+
2732
class QgsCoordinateReferenceSystem;
2833
class QgsMapLayerModel;
2934
class QgsMapLayer;
@@ -52,6 +57,7 @@ class GUI_EXPORT QgsExtentGroupBox : public QgsCollapsibleGroupBox, private Ui::
5257
CurrentExtent, //!< Map canvas extent
5358
UserExtent, //!< Extent manually entered/modified by the user
5459
ProjectLayerExtent, //!< Extent taken from a layer within the project
60+
DrawOnCanvas, //!< Extent taken from a rectangled drawn onto the map canvas
5561
};
5662

5763
/**
@@ -135,6 +141,13 @@ class GUI_EXPORT QgsExtentGroupBox : public QgsCollapsibleGroupBox, private Ui::
135141
*/
136142
QString titleBase() const;
137143

144+
/**
145+
* Sets the map canvas to enable dragging of extent on a canvas.
146+
* \param canvas the map canvas
147+
* \since QGIS 3.0
148+
*/
149+
void setMapCanvas( QgsMapCanvas *canvas );
150+
138151
public slots:
139152

140153
/**
@@ -158,6 +171,12 @@ class GUI_EXPORT QgsExtentGroupBox : public QgsCollapsibleGroupBox, private Ui::
158171
*/
159172
void setOutputExtentFromLayer( const QgsMapLayer *layer );
160173

174+
/**
175+
* Sets the output extent by dragging on the canvas.
176+
* \since QGIS 3.0
177+
*/
178+
void setOutputExtentFromDrawOnCanvas();
179+
161180
signals:
162181

163182
/**
@@ -175,6 +194,8 @@ class GUI_EXPORT QgsExtentGroupBox : public QgsCollapsibleGroupBox, private Ui::
175194
void groupBoxClicked();
176195
void layerMenuAboutToShow();
177196

197+
void extentDrawn( const QgsRectangle &extent );
198+
178199
private:
179200
void setOutputExtent( const QgsRectangle &r, const QgsCoordinateReferenceSystem &srcCrs, QgsExtentGroupBox::ExtentState state );
180201
void setOutputExtentFromLineEdit();
@@ -199,6 +220,10 @@ class GUI_EXPORT QgsExtentGroupBox : public QgsCollapsibleGroupBox, private Ui::
199220
QPointer< const QgsMapLayer > mExtentLayer;
200221
QString mExtentLayerName;
201222

223+
std::unique_ptr< QgsMapToolExtent > mMapToolExtent;
224+
QPointer< QgsMapTool > mMapToolPrevious = nullptr;
225+
QgsMapCanvas *mCanvas = nullptr;
226+
202227
void setExtentToLayerExtent( const QString &layerId );
203228

204229
};

0 commit comments

Comments
 (0)