QGIS API Documentation  3.21.0-Master (5b68dc587e)
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  return QgsReferencedRectangle( QgsMapLayerUtils::combinedExtent( layers, mProject->crs(), mProject->transformContext() ), mProject->crs() );
87  }
88 }
89 
90 void QgsProjectViewSettings::setMapScales( const QVector<double> &scales )
91 {
92  // sort scales in descending order
93  QVector< double > sorted = scales;
94  std::sort( sorted.begin(), sorted.end(), std::greater<double>() );
95 
96  if ( sorted == mapScales() )
97  return;
98 
99  mMapScales = sorted;
100 
101  emit mapScalesChanged();
102 }
103 
104 QVector<double> QgsProjectViewSettings::mapScales() const
105 {
106  return mMapScales;
107 }
108 
110 {
111  if ( enabled == useProjectScales() )
112  return;
113 
114  mUseProjectScales = enabled;
115  emit mapScalesChanged();
116 }
117 
119 {
120  return mUseProjectScales;
121 }
122 
123 bool QgsProjectViewSettings::readXml( const QDomElement &element, const QgsReadWriteContext & )
124 {
125  const bool useProjectScale = element.attribute( QStringLiteral( "UseProjectScales" ), QStringLiteral( "0" ) ).toInt();
126 
127  QDomNodeList scalesNodes = element.elementsByTagName( QStringLiteral( "Scales" ) );
128  QVector< double > newScales;
129  if ( !scalesNodes.isEmpty() )
130  {
131  const QDomElement scalesElement = scalesNodes.at( 0 ).toElement();
132  scalesNodes = scalesElement.elementsByTagName( QStringLiteral( "Scale" ) );
133  for ( int i = 0; i < scalesNodes.count(); i++ )
134  {
135  const QDomElement scaleElement = scalesNodes.at( i ).toElement();
136  newScales.append( scaleElement.attribute( QStringLiteral( "Value" ) ).toDouble() );
137  }
138  }
139  if ( useProjectScale != mUseProjectScales || newScales != mMapScales )
140  {
141  mMapScales = newScales;
142  mUseProjectScales = useProjectScale;
143  emit mapScalesChanged();
144  }
145 
146  const QDomElement defaultViewElement = element.firstChildElement( QStringLiteral( "DefaultViewExtent" ) );
147  if ( !defaultViewElement.isNull() )
148  {
149  const double xMin = defaultViewElement.attribute( QStringLiteral( "xmin" ) ).toDouble();
150  const double yMin = defaultViewElement.attribute( QStringLiteral( "ymin" ) ).toDouble();
151  const double xMax = defaultViewElement.attribute( QStringLiteral( "xmax" ) ).toDouble();
152  const double yMax = defaultViewElement.attribute( QStringLiteral( "ymax" ) ).toDouble();
154  crs.readXml( defaultViewElement );
155  mDefaultViewExtent = QgsReferencedRectangle( QgsRectangle( xMin, yMin, xMax, yMax ), crs );
156  }
157  else
158  {
159  mDefaultViewExtent = QgsReferencedRectangle();
160  }
161 
162  const QDomElement presetViewElement = element.firstChildElement( QStringLiteral( "PresetFullExtent" ) );
163  if ( !presetViewElement.isNull() )
164  {
165  const double xMin = presetViewElement.attribute( QStringLiteral( "xmin" ) ).toDouble();
166  const double yMin = presetViewElement.attribute( QStringLiteral( "ymin" ) ).toDouble();
167  const double xMax = presetViewElement.attribute( QStringLiteral( "xmax" ) ).toDouble();
168  const double yMax = presetViewElement.attribute( QStringLiteral( "ymax" ) ).toDouble();
170  crs.readXml( presetViewElement );
171  setPresetFullExtent( QgsReferencedRectangle( QgsRectangle( xMin, yMin, xMax, yMax ), crs ) );
172  }
173  else
174  {
176  }
177 
178  return true;
179 }
180 
181 QDomElement QgsProjectViewSettings::writeXml( QDomDocument &doc, const QgsReadWriteContext & ) const
182 {
183  QDomElement element = doc.createElement( QStringLiteral( "ProjectViewSettings" ) );
184  element.setAttribute( QStringLiteral( "UseProjectScales" ), mUseProjectScales ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
185 
186  QDomElement scales = doc.createElement( QStringLiteral( "Scales" ) );
187  for ( const double scale : mMapScales )
188  {
189  QDomElement scaleElement = doc.createElement( QStringLiteral( "Scale" ) );
190  scaleElement.setAttribute( QStringLiteral( "Value" ), qgsDoubleToString( scale ) );
191  scales.appendChild( scaleElement );
192  }
193  element.appendChild( scales );
194 
195  if ( !mDefaultViewExtent.isNull() )
196  {
197  QDomElement defaultViewElement = doc.createElement( QStringLiteral( "DefaultViewExtent" ) );
198  defaultViewElement.setAttribute( QStringLiteral( "xmin" ), qgsDoubleToString( mDefaultViewExtent.xMinimum() ) );
199  defaultViewElement.setAttribute( QStringLiteral( "ymin" ), qgsDoubleToString( mDefaultViewExtent.yMinimum() ) );
200  defaultViewElement.setAttribute( QStringLiteral( "xmax" ), qgsDoubleToString( mDefaultViewExtent.xMaximum() ) );
201  defaultViewElement.setAttribute( QStringLiteral( "ymax" ), qgsDoubleToString( mDefaultViewExtent.yMaximum() ) );
202  mDefaultViewExtent.crs().writeXml( defaultViewElement, doc );
203  element.appendChild( defaultViewElement );
204  }
205 
206  if ( !mPresetFullExtent.isNull() )
207  {
208  QDomElement presetViewElement = doc.createElement( QStringLiteral( "PresetFullExtent" ) );
209  presetViewElement.setAttribute( QStringLiteral( "xmin" ), qgsDoubleToString( mPresetFullExtent.xMinimum() ) );
210  presetViewElement.setAttribute( QStringLiteral( "ymin" ), qgsDoubleToString( mPresetFullExtent.yMinimum() ) );
211  presetViewElement.setAttribute( QStringLiteral( "xmax" ), qgsDoubleToString( mPresetFullExtent.xMaximum() ) );
212  presetViewElement.setAttribute( QStringLiteral( "ymax" ), qgsDoubleToString( mPresetFullExtent.yMaximum() ) );
213  mPresetFullExtent.crs().writeXml( presetViewElement, doc );
214  element.appendChild( presetViewElement );
215  }
216 
217  return element;
218 }
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.
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:101
QgsCoordinateTransformContext transformContext
Definition: qgsproject.h:107
QgsCoordinateReferenceSystem crs
Definition: qgsproject.h:106
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:1186
const QgsCoordinateReferenceSystem & crs