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