QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
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 
16 #include "qgsprojectviewsettings.h"
17 #include "qgis.h"
18 #include "qgsproject.h"
19 #include "qgsmaplayerutils.h"
20 #include "qgscoordinatetransform.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 
101 void 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 
115 QVector<double> QgsProjectViewSettings::mapScales() const
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 
144 bool 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 
204 QDomElement 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 }
QgsProjectViewSettings::writeXml
QDomElement writeXml(QDomDocument &doc, const QgsReadWriteContext &context) const
Returns a DOM element representing the settings.
Definition: qgsprojectviewsettings.cpp:204
QgsProjectViewSettings::mapScalesChanged
void mapScalesChanged()
Emitted when the list of custom project map scales changes.
QgsReadWriteContext
The class is used as a container of context for various read/write operations on other objects.
Definition: qgsreadwritecontext.h:34
QgsProjectViewSettings::presetFullExtentChanged
void presetFullExtentChanged()
Emitted whenever the presetFullExtent() is changed.
QgsReferencedRectangle
A QgsRectangle with associated coordinate reference system.
Definition: qgsreferencedgeometry.h:73
QgsProject::mapLayers
QMap< QString, QgsMapLayer * > mapLayers(const bool validOnly=false) const
Returns a map of all registered layers by layer ID.
Definition: qgsproject.cpp:3955
crs
const QgsCoordinateReferenceSystem & crs
Definition: qgswfsgetfeature.cpp:105
QgsRectangle::yMinimum
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:198
QgsCoordinateTransform::transformBoundingBox
QgsRectangle transformBoundingBox(const QgsRectangle &rectangle, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool handle180Crossover=false) const SIP_THROW(QgsCsException)
Transforms a rectangle from the source CRS to the destination CRS.
Definition: qgscoordinatetransform.cpp:560
QgsProject::transformContext
QgsCoordinateTransformContext transformContext
Definition: qgsproject.h:110
qgis.h
QgsProjectViewSettings::setDefaultViewExtent
void setDefaultViewExtent(const QgsReferencedRectangle &extent)
Sets the default view extent, which should be used as the initial map extent when this project is ope...
Definition: qgsprojectviewsettings.cpp:54
QgsProjectViewSettings::setUseProjectScales
void setUseProjectScales(bool enabled)
Sets whether project mapScales() are enabled.
Definition: qgsprojectviewsettings.cpp:120
QgsCoordinateReferenceSystem::readXml
bool readXml(const QDomNode &node)
Restores state from the given DOM node.
Definition: qgscoordinatereferencesystem.cpp:1860
QgsRectangle
A rectangle specified with double values.
Definition: qgsrectangle.h:41
qgsDoubleToString
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition: qgis.h:2204
QgsProject
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition: qgsproject.h:103
QgsRectangle::xMaximum
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:183
QgsProjectViewSettings::defaultViewExtent
QgsReferencedRectangle defaultViewExtent() const
Returns the default view extent, which should be used as the initial map extent when this project is ...
Definition: qgsprojectviewsettings.cpp:49
QgsProjectViewSettings::setPresetFullExtent
void setPresetFullExtent(const QgsReferencedRectangle &extent)
Sets the project's preset full extent.
Definition: qgsprojectviewsettings.cpp:64
QgsCoordinateTransform::setBallparkTransformsAreAppropriate
void setBallparkTransformsAreAppropriate(bool appropriate)
Sets whether approximate "ballpark" results are appropriate for this coordinate transform.
Definition: qgscoordinatetransform.cpp:939
QgsCoordinateReferenceSystem::writeXml
bool writeXml(QDomNode &node, QDomDocument &doc) const
Stores state to the given Dom node in the given document.
Definition: qgscoordinatereferencesystem.cpp:1980
QgsProjectViewSettings::fullExtent
QgsReferencedRectangle fullExtent() const
Returns the full extent of the project, which represents the maximal limits of the project.
Definition: qgsprojectviewsettings.cpp:73
qgsmaplayerutils.h
QgsProjectViewSettings::QgsProjectViewSettings
QgsProjectViewSettings(QgsProject *project=nullptr)
Constructor for QgsProjectViewSettings for the specified project.
Definition: qgsprojectviewsettings.cpp:23
qgscoordinatetransform.h
QgsRectangle::xMinimum
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:188
QgsMapLayerUtils::combinedExtent
static QgsRectangle combinedExtent(const QList< QgsMapLayer * > &layers, const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &transformContext)
Returns the combined extent of a list of layers.
Definition: qgsmaplayerutils.cpp:30
QgsCoordinateReferenceSystem
This class represents a coordinate reference system (CRS).
Definition: qgscoordinatereferencesystem.h:211
QgsProjectViewSettings::reset
void reset()
Resets the settings to a default state.
Definition: qgsprojectviewsettings.cpp:30
QgsReferencedGeometryBase::crs
QgsCoordinateReferenceSystem crs() const
Returns the associated coordinate reference system, or an invalid CRS if no reference system is set.
Definition: qgsreferencedgeometry.h:53
qgsprojectviewsettings.h
QgsRectangle::yMaximum
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:193
QgsProjectViewSettings::mapScales
QVector< double > mapScales() const
Returns the list of custom project map scales.
Definition: qgsprojectviewsettings.cpp:115
QgsMapLayer
Base class for all map layer types. This is the base class for all map layer types (vector,...
Definition: qgsmaplayer.h:72
QgsProjectViewSettings::setMapScales
void setMapScales(const QVector< double > &scales)
Sets the list of custom project map scales.
Definition: qgsprojectviewsettings.cpp:101
QgsProjectViewSettings::defaultRotation
double defaultRotation() const
Returns the default map rotation (in clockwise degrees) for maps in the project.
Definition: qgsprojectviewsettings.cpp:134
QgsProjectViewSettings::readXml
bool readXml(const QDomElement &element, const QgsReadWriteContext &context)
Reads the settings's state from a DOM element.
Definition: qgsprojectviewsettings.cpp:144
QgsCoordinateTransform
Class for doing transforms between two map coordinate systems.
Definition: qgscoordinatetransform.h:57
QgsProjectViewSettings::setDefaultRotation
void setDefaultRotation(double rotation)
Set the default rotation of maps in the project, in clockwise degrees.
Definition: qgsprojectviewsettings.cpp:139
QgsProject::crs
QgsCoordinateReferenceSystem crs
Definition: qgsproject.h:109
QgsRectangle::isNull
bool isNull() const
Test if the rectangle is null (all coordinates zero or after call to setMinimal()).
Definition: qgsrectangle.h:479
qgsproject.h
QgsProjectViewSettings::presetFullExtent
QgsReferencedRectangle presetFullExtent() const
Returns the project's preset full extent.
Definition: qgsprojectviewsettings.cpp:59
QgsProjectViewSettings::useProjectScales
bool useProjectScales() const
Returns true if project mapScales() are enabled.
Definition: qgsprojectviewsettings.cpp:129