QGIS API Documentation 3.99.0-Master (26c88405ac0)
Loading...
Searching...
No Matches
qgsprojectviewsettings.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsprojectviewsettings.cpp
3 -----------------------------
4 begin : October 2019
5 copyright : (C) 2019 by Nyall Dawson
6 email : nyall dot dawson at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
17
18#include "qgis.h"
20#include "qgsmaplayerutils.h"
21#include "qgsmessagelog.h"
22#include "qgsproject.h"
23
24#include <QDomElement>
25
26#include "moc_qgsprojectviewsettings.cpp"
27
29 : QObject( project )
30 , mProject( project )
31 , mRestoreProjectExtentOnProjectLoad( false )
32{
33
34}
35
37{
38 mDefaultViewExtent = QgsReferencedRectangle();
39
40 mDefaultRotation = 0;
41
42 const bool fullExtentChanged = !mPresetFullExtent.isNull();
43 mPresetFullExtent = QgsReferencedRectangle();
44 if ( fullExtentChanged )
46
47 if ( mUseProjectScales || !mMapScales.empty() )
48 {
49 mUseProjectScales = false;
50 mMapScales.clear();
51 emit mapScalesChanged();
52 }
53}
54
56{
57 return mDefaultViewExtent;
58}
59
61{
62 mDefaultViewExtent = extent;
63}
64
66{
67 return mPresetFullExtent;
68}
69
71{
72 if ( extent == mPresetFullExtent )
73 return;
74
75 mPresetFullExtent = extent;
77}
78
80{
81 mRestoreProjectExtentOnProjectLoad = projectExtentCheckboxState;
82}
83
85{
86 return mRestoreProjectExtentOnProjectLoad;
87}
88
89
91{
92 if ( !mProject )
93 return mPresetFullExtent;
94
95 if ( !mPresetFullExtent.isNull() )
96 {
97 QgsCoordinateTransform ct( mPresetFullExtent.crs(), mProject->crs(), mProject->transformContext() );
99 try
100 {
101 return QgsReferencedRectangle( ct.transformBoundingBox( mPresetFullExtent ), mProject->crs() );
102 }
103 catch ( QgsCsException &e )
104 {
105 QgsDebugError( QStringLiteral( "Transform error encountered while determining project extent: %1" ).arg( e.what() ) );
106 return QgsReferencedRectangle();
107 }
108 }
109 else
110 {
111 const QList< QgsMapLayer * > layers = mProject->mapLayers( true ).values();
112
113 QList< QgsMapLayer * > nonBaseMapLayers;
114 std::copy_if( layers.begin(), layers.end(),
115 std::back_inserter( nonBaseMapLayers ),
116 []( const QgsMapLayer * layer ) { return !( layer->properties() & Qgis::MapLayerProperty::IsBasemapLayer ) && !( layer->properties() & Qgis::MapLayerProperty::Is3DBasemapLayer ); } );
117
118 // unless ALL layers from the project are basemap layers, we exclude these by default as their extent won't be useful for the project.
119 if ( !nonBaseMapLayers.empty( ) )
120 return QgsReferencedRectangle( QgsMapLayerUtils::combinedExtent( nonBaseMapLayers, mProject->crs(), mProject->transformContext() ), mProject->crs() );
121 else
122 return QgsReferencedRectangle( QgsMapLayerUtils::combinedExtent( layers, mProject->crs(), mProject->transformContext() ), mProject->crs() );
123 }
124}
125
126void QgsProjectViewSettings::setMapScales( const QVector<double> &scales )
127{
128 // sort scales in descending order
129 QVector< double > sorted = scales;
130 std::sort( sorted.begin(), sorted.end(), std::greater<double>() );
131
132 if ( sorted == mapScales() )
133 return;
134
135 mMapScales = sorted;
136
137 emit mapScalesChanged();
138}
139
141{
142 return mMapScales;
143}
144
146{
147 if ( enabled == useProjectScales() )
148 return;
149
150 mUseProjectScales = enabled;
151 emit mapScalesChanged();
152}
153
155{
156 return mUseProjectScales;
157}
158
160{
161 return mDefaultRotation;
162}
163
165{
166 mDefaultRotation = rotation;
167}
168
169bool QgsProjectViewSettings::readXml( const QDomElement &element, const QgsReadWriteContext & )
170{
171 const bool useProjectScale = element.attribute( QStringLiteral( "UseProjectScales" ), QStringLiteral( "0" ) ).toInt();
172
173 QDomNodeList scalesNodes = element.elementsByTagName( QStringLiteral( "Scales" ) );
174 QVector< double > newScales;
175 if ( !scalesNodes.isEmpty() )
176 {
177 const QDomElement scalesElement = scalesNodes.at( 0 ).toElement();
178 scalesNodes = scalesElement.elementsByTagName( QStringLiteral( "Scale" ) );
179 for ( int i = 0; i < scalesNodes.count(); i++ )
180 {
181 const QDomElement scaleElement = scalesNodes.at( i ).toElement();
182 newScales.append( scaleElement.attribute( QStringLiteral( "Value" ) ).toDouble() );
183 }
184 }
185 if ( useProjectScale != mUseProjectScales || newScales != mMapScales )
186 {
187 mMapScales = newScales;
188 mUseProjectScales = useProjectScale;
189 emit mapScalesChanged();
190 }
191
192 const QDomElement defaultViewElement = element.firstChildElement( QStringLiteral( "DefaultViewExtent" ) );
193 if ( !defaultViewElement.isNull() )
194 {
195 const double xMin = defaultViewElement.attribute( QStringLiteral( "xmin" ) ).toDouble();
196 const double yMin = defaultViewElement.attribute( QStringLiteral( "ymin" ) ).toDouble();
197 const double xMax = defaultViewElement.attribute( QStringLiteral( "xmax" ) ).toDouble();
198 const double yMax = defaultViewElement.attribute( QStringLiteral( "ymax" ) ).toDouble();
200 crs.readXml( defaultViewElement );
201 mDefaultViewExtent = QgsReferencedRectangle( QgsRectangle( xMin, yMin, xMax, yMax ), crs );
202 }
203 else
204 {
205 mDefaultViewExtent = QgsReferencedRectangle();
206 }
207
208 const QDomElement presetViewElement = element.firstChildElement( QStringLiteral( "PresetFullExtent" ) );
209 if ( !presetViewElement.isNull() )
210 {
211 const double xMin = presetViewElement.attribute( QStringLiteral( "xmin" ) ).toDouble();
212 const double yMin = presetViewElement.attribute( QStringLiteral( "ymin" ) ).toDouble();
213 const double xMax = presetViewElement.attribute( QStringLiteral( "xmax" ) ).toDouble();
214 const double yMax = presetViewElement.attribute( QStringLiteral( "ymax" ) ).toDouble();
216 crs.readXml( presetViewElement );
217 setPresetFullExtent( QgsReferencedRectangle( QgsRectangle( xMin, yMin, xMax, yMax ), crs ) );
218 }
219 else
220 {
222 }
223
224 mDefaultRotation = element.attribute( QStringLiteral( "rotation" ), QStringLiteral( "0" ) ).toDouble();
225 mRestoreProjectExtentOnProjectLoad = element.attribute( QStringLiteral( "LoadProjectExtent" ), QStringLiteral( "0" ) ).toInt();
226
227 return true;
228}
229
230QDomElement QgsProjectViewSettings::writeXml( QDomDocument &doc, const QgsReadWriteContext & ) const
231{
232 QDomElement element = doc.createElement( QStringLiteral( "ProjectViewSettings" ) );
233 element.setAttribute( QStringLiteral( "UseProjectScales" ), mUseProjectScales ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
234
235 if ( mRestoreProjectExtentOnProjectLoad )
236 {
237 element.setAttribute( QStringLiteral( "LoadProjectExtent" ), QStringLiteral( "1" ) );
238 }
239
240 element.setAttribute( QStringLiteral( "rotation" ), qgsDoubleToString( mDefaultRotation ) );
241
242 QDomElement scales = doc.createElement( QStringLiteral( "Scales" ) );
243 for ( const double scale : mMapScales )
244 {
245 QDomElement scaleElement = doc.createElement( QStringLiteral( "Scale" ) );
246 scaleElement.setAttribute( QStringLiteral( "Value" ), qgsDoubleToString( scale ) );
247 scales.appendChild( scaleElement );
248 }
249 element.appendChild( scales );
250
251 if ( !mDefaultViewExtent.isNull() )
252 {
253 QDomElement defaultViewElement = doc.createElement( QStringLiteral( "DefaultViewExtent" ) );
254 defaultViewElement.setAttribute( QStringLiteral( "xmin" ), qgsDoubleToString( mDefaultViewExtent.xMinimum() ) );
255 defaultViewElement.setAttribute( QStringLiteral( "ymin" ), qgsDoubleToString( mDefaultViewExtent.yMinimum() ) );
256 defaultViewElement.setAttribute( QStringLiteral( "xmax" ), qgsDoubleToString( mDefaultViewExtent.xMaximum() ) );
257 defaultViewElement.setAttribute( QStringLiteral( "ymax" ), qgsDoubleToString( mDefaultViewExtent.yMaximum() ) );
258 mDefaultViewExtent.crs().writeXml( defaultViewElement, doc );
259 element.appendChild( defaultViewElement );
260 }
261
262 if ( !mPresetFullExtent.isNull() )
263 {
264 QDomElement presetViewElement = doc.createElement( QStringLiteral( "PresetFullExtent" ) );
265 presetViewElement.setAttribute( QStringLiteral( "xmin" ), qgsDoubleToString( mPresetFullExtent.xMinimum() ) );
266 presetViewElement.setAttribute( QStringLiteral( "ymin" ), qgsDoubleToString( mPresetFullExtent.yMinimum() ) );
267 presetViewElement.setAttribute( QStringLiteral( "xmax" ), qgsDoubleToString( mPresetFullExtent.xMaximum() ) );
268 presetViewElement.setAttribute( QStringLiteral( "ymax" ), qgsDoubleToString( mPresetFullExtent.yMaximum() ) );
269 mPresetFullExtent.crs().writeXml( presetViewElement, doc );
270 element.appendChild( presetViewElement );
271 }
272
273 return element;
274}
Represents a coordinate reference system (CRS).
bool readXml(const QDomNode &node)
Restores state from the given DOM node.
Handles coordinate transforms between two coordinate systems.
void setBallparkTransformsAreAppropriate(bool appropriate)
Sets whether approximate "ballpark" results are appropriate for this coordinate transform.
QgsRectangle transformBoundingBox(const QgsRectangle &rectangle, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool handle180Crossover=false) const
Transforms a rectangle from the source CRS to the destination CRS.
Custom exception class for Coordinate Reference System related exceptions.
QString what() const
static QgsRectangle combinedExtent(const QList< QgsMapLayer * > &layers, const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &transformContext)
Returns the combined extent of a list of layers.
Base class for all map layer types.
Definition qgsmaplayer.h:80
double defaultRotation() const
Returns the default map rotation (in clockwise degrees) for maps in the project.
QgsReferencedRectangle defaultViewExtent() const
Returns the default view extent, which should be used as the initial map extent when this project is ...
bool useProjectScales() const
Returns true if project mapScales() are enabled.
QgsReferencedRectangle presetFullExtent() const
Returns the project's preset full extent.
void setPresetFullExtent(const QgsReferencedRectangle &extent)
Sets the project's preset full extent.
void reset()
Resets the settings to a default state.
void presetFullExtentChanged()
Emitted whenever the presetFullExtent() is changed.
void setDefaultViewExtent(const QgsReferencedRectangle &extent)
Sets the default view extent, which should be used as the initial map extent when this project is ope...
bool restoreProjectExtentOnProjectLoad()
Returns whether the project's preset full extent should be restored when the project is loaded.
bool readXml(const QDomElement &element, const QgsReadWriteContext &context)
Reads the settings's state from a DOM element.
void setDefaultRotation(double rotation)
Set the default rotation of maps in the project, in clockwise degrees.
void setMapScales(const QVector< double > &scales)
Sets the list of custom project map scales.
void setUseProjectScales(bool enabled)
Sets whether project mapScales() are enabled.
QVector< double > mapScales() const
Returns the list of custom project map scales.
QgsProjectViewSettings(QgsProject *project=nullptr)
Constructor for QgsProjectViewSettings for the specified project.
void mapScalesChanged()
Emitted when the list of custom project map scales changes.
QgsReferencedRectangle fullExtent() const
Returns the full extent of the project, which represents the maximal limits of the project.
QDomElement writeXml(QDomDocument &doc, const QgsReadWriteContext &context) const
Returns a DOM element representing the settings.
void setRestoreProjectExtentOnProjectLoad(bool state)
Sets whether the project's preset full extent should be restored when the project is loaded.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition qgsproject.h:109
A container for the context for various read/write operations on objects.
A rectangle specified with double values.
A QgsRectangle with associated coordinate reference system.
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition qgis.h:6524
#define QgsDebugError(str)
Definition qgslogger.h:57