QGIS API Documentation  3.27.0-Master (e113457133)
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 "qgslogger.h"
20 #include "qgsmaplayerutils.h"
21 #include "qgscoordinatetransform.h"
22 #include <QDomElement>
23 
25  : QObject( project )
26  , mProject( project )
27 {
28 
29 }
30 
32 {
33  mDefaultViewExtent = QgsReferencedRectangle();
34 
35  const bool fullExtentChanged = !mPresetFullExtent.isNull();
36  mPresetFullExtent = QgsReferencedRectangle();
37  if ( fullExtentChanged )
39 
40  if ( mUseProjectScales || !mMapScales.empty() )
41  {
42  mUseProjectScales = false;
43  mMapScales.clear();
44  emit mapScalesChanged();
45  }
46 }
47 
49 {
50  return mDefaultViewExtent;
51 }
52 
54 {
55  mDefaultViewExtent = extent;
56 }
57 
59 {
60  return mPresetFullExtent;
61 }
62 
64 {
65  if ( extent == mPresetFullExtent )
66  return;
67 
68  mPresetFullExtent = extent;
70 }
71 
73 {
74  if ( !mProject )
75  return mPresetFullExtent;
76 
77  if ( !mPresetFullExtent.isNull() )
78  {
79  QgsCoordinateTransform ct( mPresetFullExtent.crs(), mProject->crs(), mProject->transformContext() );
81  return QgsReferencedRectangle( ct.transformBoundingBox( mPresetFullExtent ), mProject->crs() );
82  }
83  else
84  {
85  const QList< QgsMapLayer * > layers = mProject->mapLayers( true ).values();
86 
87  QList< QgsMapLayer * > nonBaseMapLayers;
88  std::copy_if( layers.begin(), layers.end(),
89  std::back_inserter( nonBaseMapLayers ),
90  []( const QgsMapLayer * layer ) { return !( layer->properties() & Qgis::MapLayerProperty::IsBasemapLayer ); } );
91 
92  // unless ALL layers from the project are basemap layers, we exclude these by default as their extent won't be useful for the project.
93  if ( !nonBaseMapLayers.empty( ) )
94  return QgsReferencedRectangle( QgsMapLayerUtils::combinedExtent( nonBaseMapLayers, mProject->crs(), mProject->transformContext() ), mProject->crs() );
95  else
96  return QgsReferencedRectangle( QgsMapLayerUtils::combinedExtent( layers, mProject->crs(), mProject->transformContext() ), mProject->crs() );
97  }
98 }
99 
100 void QgsProjectViewSettings::setMapScales( const QVector<double> &scales )
101 {
102  // sort scales in descending order
103  QVector< double > sorted = scales;
104  std::sort( sorted.begin(), sorted.end(), std::greater<double>() );
105 
106  if ( sorted == mapScales() )
107  return;
108 
109  mMapScales = sorted;
110 
111  emit mapScalesChanged();
112 }
113 
114 QVector<double> QgsProjectViewSettings::mapScales() const
115 {
116  return mMapScales;
117 }
118 
120 {
121  if ( enabled == useProjectScales() )
122  return;
123 
124  mUseProjectScales = enabled;
125  emit mapScalesChanged();
126 }
127 
129 {
130  return mUseProjectScales;
131 }
132 
133 bool QgsProjectViewSettings::readXml( const QDomElement &element, const QgsReadWriteContext & )
134 {
135  const bool useProjectScale = element.attribute( QStringLiteral( "UseProjectScales" ), QStringLiteral( "0" ) ).toInt();
136 
137  QDomNodeList scalesNodes = element.elementsByTagName( QStringLiteral( "Scales" ) );
138  QVector< double > newScales;
139  if ( !scalesNodes.isEmpty() )
140  {
141  const QDomElement scalesElement = scalesNodes.at( 0 ).toElement();
142  scalesNodes = scalesElement.elementsByTagName( QStringLiteral( "Scale" ) );
143  for ( int i = 0; i < scalesNodes.count(); i++ )
144  {
145  const QDomElement scaleElement = scalesNodes.at( i ).toElement();
146  newScales.append( scaleElement.attribute( QStringLiteral( "Value" ) ).toDouble() );
147  }
148  }
149  if ( useProjectScale != mUseProjectScales || newScales != mMapScales )
150  {
151  mMapScales = newScales;
152  mUseProjectScales = useProjectScale;
153  emit mapScalesChanged();
154  }
155 
156  const QDomElement defaultViewElement = element.firstChildElement( QStringLiteral( "DefaultViewExtent" ) );
157  if ( !defaultViewElement.isNull() )
158  {
159  const double xMin = defaultViewElement.attribute( QStringLiteral( "xmin" ) ).toDouble();
160  const double yMin = defaultViewElement.attribute( QStringLiteral( "ymin" ) ).toDouble();
161  const double xMax = defaultViewElement.attribute( QStringLiteral( "xmax" ) ).toDouble();
162  const double yMax = defaultViewElement.attribute( QStringLiteral( "ymax" ) ).toDouble();
164  crs.readXml( defaultViewElement );
165  mDefaultViewExtent = QgsReferencedRectangle( QgsRectangle( xMin, yMin, xMax, yMax ), crs );
166  }
167  else
168  {
169  mDefaultViewExtent = QgsReferencedRectangle();
170  }
171 
172  const QDomElement presetViewElement = element.firstChildElement( QStringLiteral( "PresetFullExtent" ) );
173  if ( !presetViewElement.isNull() )
174  {
175  const double xMin = presetViewElement.attribute( QStringLiteral( "xmin" ) ).toDouble();
176  const double yMin = presetViewElement.attribute( QStringLiteral( "ymin" ) ).toDouble();
177  const double xMax = presetViewElement.attribute( QStringLiteral( "xmax" ) ).toDouble();
178  const double yMax = presetViewElement.attribute( QStringLiteral( "ymax" ) ).toDouble();
180  crs.readXml( presetViewElement );
181  setPresetFullExtent( QgsReferencedRectangle( QgsRectangle( xMin, yMin, xMax, yMax ), crs ) );
182  }
183  else
184  {
186  }
187 
188  return true;
189 }
190 
191 QDomElement QgsProjectViewSettings::writeXml( QDomDocument &doc, const QgsReadWriteContext & ) const
192 {
193  QDomElement element = doc.createElement( QStringLiteral( "ProjectViewSettings" ) );
194  element.setAttribute( QStringLiteral( "UseProjectScales" ), mUseProjectScales ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
195 
196  QDomElement scales = doc.createElement( QStringLiteral( "Scales" ) );
197  for ( const double scale : mMapScales )
198  {
199  QDomElement scaleElement = doc.createElement( QStringLiteral( "Scale" ) );
200  scaleElement.setAttribute( QStringLiteral( "Value" ), qgsDoubleToString( scale ) );
201  scales.appendChild( scaleElement );
202  }
203  element.appendChild( scales );
204 
205  if ( !mDefaultViewExtent.isNull() )
206  {
207  QDomElement defaultViewElement = doc.createElement( QStringLiteral( "DefaultViewExtent" ) );
208  defaultViewElement.setAttribute( QStringLiteral( "xmin" ), qgsDoubleToString( mDefaultViewExtent.xMinimum() ) );
209  defaultViewElement.setAttribute( QStringLiteral( "ymin" ), qgsDoubleToString( mDefaultViewExtent.yMinimum() ) );
210  defaultViewElement.setAttribute( QStringLiteral( "xmax" ), qgsDoubleToString( mDefaultViewExtent.xMaximum() ) );
211  defaultViewElement.setAttribute( QStringLiteral( "ymax" ), qgsDoubleToString( mDefaultViewExtent.yMaximum() ) );
212  mDefaultViewExtent.crs().writeXml( defaultViewElement, doc );
213  element.appendChild( defaultViewElement );
214  }
215 
216  if ( !mPresetFullExtent.isNull() )
217  {
218  QDomElement presetViewElement = doc.createElement( QStringLiteral( "PresetFullExtent" ) );
219  presetViewElement.setAttribute( QStringLiteral( "xmin" ), qgsDoubleToString( mPresetFullExtent.xMinimum() ) );
220  presetViewElement.setAttribute( QStringLiteral( "ymin" ), qgsDoubleToString( mPresetFullExtent.yMinimum() ) );
221  presetViewElement.setAttribute( QStringLiteral( "xmax" ), qgsDoubleToString( mPresetFullExtent.xMaximum() ) );
222  presetViewElement.setAttribute( QStringLiteral( "ymax" ), qgsDoubleToString( mPresetFullExtent.yMaximum() ) );
223  mPresetFullExtent.crs().writeXml( presetViewElement, doc );
224  element.appendChild( presetViewElement );
225  }
226 
227  return element;
228 }
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 SIP_THROW(QgsCsException)
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:73
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 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:104
QgsCoordinateTransformContext transformContext
Definition: qgsproject.h:110
QgsCoordinateReferenceSystem crs
Definition: qgsproject.h:109
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.
Definition: qgsrectangle.h:42
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:193
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:183
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:188
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:198
bool isNull() const
Test if the rectangle is null (all coordinates zero or after call to setMinimal()).
Definition: qgsrectangle.h:479
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:2199
const QgsCoordinateReferenceSystem & crs