QGIS API Documentation 3.37.0-Master (49cede7946b)
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#include "qgis.h"
18#include "qgsproject.h"
19#include "qgsmaplayerutils.h"
21#include <QDomElement>
22
24 : QObject( project )
25 , mProject( project )
26{
27
28}
29
31{
32 mDefaultViewExtent = QgsReferencedRectangle();
33
34 mDefaultRotation = 0;
35
36 const bool fullExtentChanged = !mPresetFullExtent.isNull();
37 mPresetFullExtent = QgsReferencedRectangle();
38 if ( fullExtentChanged )
40
41 if ( mUseProjectScales || !mMapScales.empty() )
42 {
43 mUseProjectScales = false;
44 mMapScales.clear();
45 emit mapScalesChanged();
46 }
47}
48
50{
51 return mDefaultViewExtent;
52}
53
55{
56 mDefaultViewExtent = extent;
57}
58
60{
61 return mPresetFullExtent;
62}
63
65{
66 if ( extent == mPresetFullExtent )
67 return;
68
69 mPresetFullExtent = extent;
71}
72
74{
75 if ( !mProject )
76 return mPresetFullExtent;
77
78 if ( !mPresetFullExtent.isNull() )
79 {
80 QgsCoordinateTransform ct( mPresetFullExtent.crs(), mProject->crs(), mProject->transformContext() );
82 return QgsReferencedRectangle( ct.transformBoundingBox( mPresetFullExtent ), mProject->crs() );
83 }
84 else
85 {
86 const QList< QgsMapLayer * > layers = mProject->mapLayers( true ).values();
87
88 QList< QgsMapLayer * > nonBaseMapLayers;
89 std::copy_if( layers.begin(), layers.end(),
90 std::back_inserter( nonBaseMapLayers ),
91 []( const QgsMapLayer * layer ) { return !( layer->properties() & Qgis::MapLayerProperty::IsBasemapLayer ); } );
92
93 // unless ALL layers from the project are basemap layers, we exclude these by default as their extent won't be useful for the project.
94 if ( !nonBaseMapLayers.empty( ) )
95 return QgsReferencedRectangle( QgsMapLayerUtils::combinedExtent( nonBaseMapLayers, mProject->crs(), mProject->transformContext() ), mProject->crs() );
96 else
97 return QgsReferencedRectangle( QgsMapLayerUtils::combinedExtent( layers, mProject->crs(), mProject->transformContext() ), mProject->crs() );
98 }
99}
100
101void QgsProjectViewSettings::setMapScales( const QVector<double> &scales )
102{
103 // sort scales in descending order
104 QVector< double > sorted = scales;
105 std::sort( sorted.begin(), sorted.end(), std::greater<double>() );
106
107 if ( sorted == mapScales() )
108 return;
109
110 mMapScales = sorted;
111
112 emit mapScalesChanged();
113}
114
116{
117 return mMapScales;
118}
119
121{
122 if ( enabled == useProjectScales() )
123 return;
124
125 mUseProjectScales = enabled;
126 emit mapScalesChanged();
127}
128
130{
131 return mUseProjectScales;
132}
133
135{
136 return mDefaultRotation;
137}
138
140{
141 mDefaultRotation = rotation;
142}
143
144bool QgsProjectViewSettings::readXml( const QDomElement &element, const QgsReadWriteContext & )
145{
146 const bool useProjectScale = element.attribute( QStringLiteral( "UseProjectScales" ), QStringLiteral( "0" ) ).toInt();
147
148 QDomNodeList scalesNodes = element.elementsByTagName( QStringLiteral( "Scales" ) );
149 QVector< double > newScales;
150 if ( !scalesNodes.isEmpty() )
151 {
152 const QDomElement scalesElement = scalesNodes.at( 0 ).toElement();
153 scalesNodes = scalesElement.elementsByTagName( QStringLiteral( "Scale" ) );
154 for ( int i = 0; i < scalesNodes.count(); i++ )
155 {
156 const QDomElement scaleElement = scalesNodes.at( i ).toElement();
157 newScales.append( scaleElement.attribute( QStringLiteral( "Value" ) ).toDouble() );
158 }
159 }
160 if ( useProjectScale != mUseProjectScales || newScales != mMapScales )
161 {
162 mMapScales = newScales;
163 mUseProjectScales = useProjectScale;
164 emit mapScalesChanged();
165 }
166
167 const QDomElement defaultViewElement = element.firstChildElement( QStringLiteral( "DefaultViewExtent" ) );
168 if ( !defaultViewElement.isNull() )
169 {
170 const double xMin = defaultViewElement.attribute( QStringLiteral( "xmin" ) ).toDouble();
171 const double yMin = defaultViewElement.attribute( QStringLiteral( "ymin" ) ).toDouble();
172 const double xMax = defaultViewElement.attribute( QStringLiteral( "xmax" ) ).toDouble();
173 const double yMax = defaultViewElement.attribute( QStringLiteral( "ymax" ) ).toDouble();
175 crs.readXml( defaultViewElement );
176 mDefaultViewExtent = QgsReferencedRectangle( QgsRectangle( xMin, yMin, xMax, yMax ), crs );
177 }
178 else
179 {
180 mDefaultViewExtent = QgsReferencedRectangle();
181 }
182
183 const QDomElement presetViewElement = element.firstChildElement( QStringLiteral( "PresetFullExtent" ) );
184 if ( !presetViewElement.isNull() )
185 {
186 const double xMin = presetViewElement.attribute( QStringLiteral( "xmin" ) ).toDouble();
187 const double yMin = presetViewElement.attribute( QStringLiteral( "ymin" ) ).toDouble();
188 const double xMax = presetViewElement.attribute( QStringLiteral( "xmax" ) ).toDouble();
189 const double yMax = presetViewElement.attribute( QStringLiteral( "ymax" ) ).toDouble();
191 crs.readXml( presetViewElement );
192 setPresetFullExtent( QgsReferencedRectangle( QgsRectangle( xMin, yMin, xMax, yMax ), crs ) );
193 }
194 else
195 {
197 }
198
199 mDefaultRotation = element.attribute( QStringLiteral( "rotation" ), QStringLiteral( "0" ) ).toDouble();
200
201 return true;
202}
203
204QDomElement QgsProjectViewSettings::writeXml( QDomDocument &doc, const QgsReadWriteContext & ) const
205{
206 QDomElement element = doc.createElement( QStringLiteral( "ProjectViewSettings" ) );
207 element.setAttribute( QStringLiteral( "UseProjectScales" ), mUseProjectScales ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
208
209 element.setAttribute( QStringLiteral( "rotation" ), qgsDoubleToString( mDefaultRotation ) );
210
211 QDomElement scales = doc.createElement( QStringLiteral( "Scales" ) );
212 for ( const double scale : mMapScales )
213 {
214 QDomElement scaleElement = doc.createElement( QStringLiteral( "Scale" ) );
215 scaleElement.setAttribute( QStringLiteral( "Value" ), qgsDoubleToString( scale ) );
216 scales.appendChild( scaleElement );
217 }
218 element.appendChild( scales );
219
220 if ( !mDefaultViewExtent.isNull() )
221 {
222 QDomElement defaultViewElement = doc.createElement( QStringLiteral( "DefaultViewExtent" ) );
223 defaultViewElement.setAttribute( QStringLiteral( "xmin" ), qgsDoubleToString( mDefaultViewExtent.xMinimum() ) );
224 defaultViewElement.setAttribute( QStringLiteral( "ymin" ), qgsDoubleToString( mDefaultViewExtent.yMinimum() ) );
225 defaultViewElement.setAttribute( QStringLiteral( "xmax" ), qgsDoubleToString( mDefaultViewExtent.xMaximum() ) );
226 defaultViewElement.setAttribute( QStringLiteral( "ymax" ), qgsDoubleToString( mDefaultViewExtent.yMaximum() ) );
227 mDefaultViewExtent.crs().writeXml( defaultViewElement, doc );
228 element.appendChild( defaultViewElement );
229 }
230
231 if ( !mPresetFullExtent.isNull() )
232 {
233 QDomElement presetViewElement = doc.createElement( QStringLiteral( "PresetFullExtent" ) );
234 presetViewElement.setAttribute( QStringLiteral( "xmin" ), qgsDoubleToString( mPresetFullExtent.xMinimum() ) );
235 presetViewElement.setAttribute( QStringLiteral( "ymin" ), qgsDoubleToString( mPresetFullExtent.yMinimum() ) );
236 presetViewElement.setAttribute( QStringLiteral( "xmax" ), qgsDoubleToString( mPresetFullExtent.xMaximum() ) );
237 presetViewElement.setAttribute( QStringLiteral( "ymax" ), qgsDoubleToString( mPresetFullExtent.yMaximum() ) );
238 mPresetFullExtent.crs().writeXml( presetViewElement, doc );
239 element.appendChild( presetViewElement );
240 }
241
242 return element;
243}
This class represents a coordinate reference system (CRS).
bool readXml(const QDomNode &node)
Restores state from the given DOM node.
bool writeXml(QDomNode &node, QDomDocument &doc) const
Stores state to the given Dom node in the given document.
Class for doing transforms between two map 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.
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:75
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 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.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition qgsproject.h:107
QgsCoordinateTransformContext transformContext
Definition qgsproject.h:113
QgsCoordinateReferenceSystem crs
Definition qgsproject.h:112
QMap< QString, QgsMapLayer * > mapLayers(const bool validOnly=false) const
Returns a map of all registered layers by layer ID.
The class is used as a container of context for various read/write operations on other objects.
A rectangle specified with double values.
double xMinimum() const
Returns the x minimum value (left side of rectangle).
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
double xMaximum() const
Returns the x maximum value (right side of rectangle).
bool isNull() const
Test if the rectangle is null (holding no spatial information).
double yMaximum() const
Returns the y maximum value (top side of rectangle).
QgsCoordinateReferenceSystem crs() const
Returns the associated coordinate reference system, or an invalid CRS if no reference system is set.
A QgsRectangle with associated coordinate reference system.
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition qgis.h:5362
const QgsCoordinateReferenceSystem & crs