QGIS API Documentation 3.99.0-Master (2fe06baccd8)
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{
32
33}
34
36{
37 mDefaultViewExtent = QgsReferencedRectangle();
38
39 mDefaultRotation = 0;
40
41 const bool fullExtentChanged = !mPresetFullExtent.isNull();
42 mPresetFullExtent = QgsReferencedRectangle();
43 if ( fullExtentChanged )
45
46 if ( mUseProjectScales || !mMapScales.empty() )
47 {
48 mUseProjectScales = false;
49 mMapScales.clear();
50 emit mapScalesChanged();
51 }
52}
53
55{
56 return mDefaultViewExtent;
57}
58
60{
61 mDefaultViewExtent = extent;
62}
63
65{
66 return mPresetFullExtent;
67}
68
70{
71 if ( extent == mPresetFullExtent )
72 return;
73
74 mPresetFullExtent = extent;
76}
77
79{
80 mRestoreProjectExtentOnProjectLoad = projectExtentCheckboxState;
81}
82
84{
85 return mRestoreProjectExtentOnProjectLoad;
86}
87
88
90{
91 if ( !mProject )
92 return mPresetFullExtent;
93
94 if ( !mPresetFullExtent.isNull() )
95 {
96 QgsCoordinateTransform ct( mPresetFullExtent.crs(), mProject->crs(), mProject->transformContext() );
98 try
99 {
100 return QgsReferencedRectangle( ct.transformBoundingBox( mPresetFullExtent ), mProject->crs() );
101 }
102 catch ( QgsCsException &e )
103 {
104 QgsDebugError( QStringLiteral( "Transform error encountered while determining project extent: %1" ).arg( e.what() ) );
105 return QgsReferencedRectangle();
106 }
107 }
108 else
109 {
110 const QList< QgsMapLayer * > layers = mProject->mapLayers( true ).values();
111
112 QList< QgsMapLayer * > nonBaseMapLayers;
113 std::copy_if( layers.begin(), layers.end(),
114 std::back_inserter( nonBaseMapLayers ),
115 []( const QgsMapLayer * layer ) { return !( layer->properties() & Qgis::MapLayerProperty::IsBasemapLayer ) && !( layer->properties() & Qgis::MapLayerProperty::Is3DBasemapLayer ); } );
116
117 // unless ALL layers from the project are basemap layers, we exclude these by default as their extent won't be useful for the project.
118 if ( !nonBaseMapLayers.empty( ) )
119 return QgsReferencedRectangle( QgsMapLayerUtils::combinedExtent( nonBaseMapLayers, mProject->crs(), mProject->transformContext() ), mProject->crs() );
120 else
121 return QgsReferencedRectangle( QgsMapLayerUtils::combinedExtent( layers, mProject->crs(), mProject->transformContext() ), mProject->crs() );
122 }
123}
124
125void QgsProjectViewSettings::setMapScales( const QVector<double> &scales )
126{
127 // sort scales in descending order
128 QVector< double > sorted = scales;
129 std::sort( sorted.begin(), sorted.end(), std::greater<double>() );
130
131 if ( sorted == mapScales() )
132 return;
133
134 mMapScales = sorted;
135
136 emit mapScalesChanged();
137}
138
140{
141 return mMapScales;
142}
143
145{
146 if ( enabled == useProjectScales() )
147 return;
148
149 mUseProjectScales = enabled;
150 emit mapScalesChanged();
151}
152
154{
155 return mUseProjectScales;
156}
157
159{
160 return mDefaultRotation;
161}
162
164{
165 mDefaultRotation = rotation;
166}
167
168bool QgsProjectViewSettings::readXml( const QDomElement &element, const QgsReadWriteContext & )
169{
170 const bool useProjectScale = element.attribute( QStringLiteral( "UseProjectScales" ), QStringLiteral( "0" ) ).toInt();
171
172 QDomNodeList scalesNodes = element.elementsByTagName( QStringLiteral( "Scales" ) );
173 QVector< double > newScales;
174 if ( !scalesNodes.isEmpty() )
175 {
176 const QDomElement scalesElement = scalesNodes.at( 0 ).toElement();
177 scalesNodes = scalesElement.elementsByTagName( QStringLiteral( "Scale" ) );
178 for ( int i = 0; i < scalesNodes.count(); i++ )
179 {
180 const QDomElement scaleElement = scalesNodes.at( i ).toElement();
181 newScales.append( scaleElement.attribute( QStringLiteral( "Value" ) ).toDouble() );
182 }
183 }
184 if ( useProjectScale != mUseProjectScales || newScales != mMapScales )
185 {
186 mMapScales = newScales;
187 mUseProjectScales = useProjectScale;
188 emit mapScalesChanged();
189 }
190
191 const QDomElement defaultViewElement = element.firstChildElement( QStringLiteral( "DefaultViewExtent" ) );
192 if ( !defaultViewElement.isNull() )
193 {
194 const double xMin = defaultViewElement.attribute( QStringLiteral( "xmin" ) ).toDouble();
195 const double yMin = defaultViewElement.attribute( QStringLiteral( "ymin" ) ).toDouble();
196 const double xMax = defaultViewElement.attribute( QStringLiteral( "xmax" ) ).toDouble();
197 const double yMax = defaultViewElement.attribute( QStringLiteral( "ymax" ) ).toDouble();
199 crs.readXml( defaultViewElement );
200 mDefaultViewExtent = QgsReferencedRectangle( QgsRectangle( xMin, yMin, xMax, yMax ), crs );
201 }
202 else
203 {
204 mDefaultViewExtent = QgsReferencedRectangle();
205 }
206
207 const QDomElement presetViewElement = element.firstChildElement( QStringLiteral( "PresetFullExtent" ) );
208 if ( !presetViewElement.isNull() )
209 {
210 const double xMin = presetViewElement.attribute( QStringLiteral( "xmin" ) ).toDouble();
211 const double yMin = presetViewElement.attribute( QStringLiteral( "ymin" ) ).toDouble();
212 const double xMax = presetViewElement.attribute( QStringLiteral( "xmax" ) ).toDouble();
213 const double yMax = presetViewElement.attribute( QStringLiteral( "ymax" ) ).toDouble();
215 crs.readXml( presetViewElement );
216 setPresetFullExtent( QgsReferencedRectangle( QgsRectangle( xMin, yMin, xMax, yMax ), crs ) );
217 }
218 else
219 {
221 }
222
223 mDefaultRotation = element.attribute( QStringLiteral( "rotation" ), QStringLiteral( "0" ) ).toDouble();
224 mRestoreProjectExtentOnProjectLoad = element.attribute( QStringLiteral( "LoadProjectExtent" ), QStringLiteral( "0" ) ).toInt();
225
226 return true;
227}
228
229QDomElement QgsProjectViewSettings::writeXml( QDomDocument &doc, const QgsReadWriteContext & ) const
230{
231 QDomElement element = doc.createElement( QStringLiteral( "ProjectViewSettings" ) );
232 element.setAttribute( QStringLiteral( "UseProjectScales" ), mUseProjectScales ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
233
234 if ( mRestoreProjectExtentOnProjectLoad )
235 {
236 element.setAttribute( QStringLiteral( "LoadProjectExtent" ), QStringLiteral( "1" ) );
237 }
238
239 element.setAttribute( QStringLiteral( "rotation" ), qgsDoubleToString( mDefaultRotation ) );
240
241 QDomElement scales = doc.createElement( QStringLiteral( "Scales" ) );
242 for ( const double scale : mMapScales )
243 {
244 QDomElement scaleElement = doc.createElement( QStringLiteral( "Scale" ) );
245 scaleElement.setAttribute( QStringLiteral( "Value" ), qgsDoubleToString( scale ) );
246 scales.appendChild( scaleElement );
247 }
248 element.appendChild( scales );
249
250 if ( !mDefaultViewExtent.isNull() )
251 {
252 QDomElement defaultViewElement = doc.createElement( QStringLiteral( "DefaultViewExtent" ) );
253 defaultViewElement.setAttribute( QStringLiteral( "xmin" ), qgsDoubleToString( mDefaultViewExtent.xMinimum() ) );
254 defaultViewElement.setAttribute( QStringLiteral( "ymin" ), qgsDoubleToString( mDefaultViewExtent.yMinimum() ) );
255 defaultViewElement.setAttribute( QStringLiteral( "xmax" ), qgsDoubleToString( mDefaultViewExtent.xMaximum() ) );
256 defaultViewElement.setAttribute( QStringLiteral( "ymax" ), qgsDoubleToString( mDefaultViewExtent.yMaximum() ) );
257 mDefaultViewExtent.crs().writeXml( defaultViewElement, doc );
258 element.appendChild( defaultViewElement );
259 }
260
261 if ( !mPresetFullExtent.isNull() )
262 {
263 QDomElement presetViewElement = doc.createElement( QStringLiteral( "PresetFullExtent" ) );
264 presetViewElement.setAttribute( QStringLiteral( "xmin" ), qgsDoubleToString( mPresetFullExtent.xMinimum() ) );
265 presetViewElement.setAttribute( QStringLiteral( "ymin" ), qgsDoubleToString( mPresetFullExtent.yMinimum() ) );
266 presetViewElement.setAttribute( QStringLiteral( "xmax" ), qgsDoubleToString( mPresetFullExtent.xMaximum() ) );
267 presetViewElement.setAttribute( QStringLiteral( "ymax" ), qgsDoubleToString( mPresetFullExtent.yMaximum() ) );
268 mPresetFullExtent.crs().writeXml( presetViewElement, doc );
269 element.appendChild( presetViewElement );
270 }
271
272 return element;
273}
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