Add API to allow setting the default view extent for a new project

Allows a QgsProject created using QGIS api only (i.e., not via the desktop
application) to specify the default extent which should be visible when
that project is opened.

Straight from the dox:

Sets the default view extent, which should be used as the initial map extent
when this project is opened.

\warning When a project is opened in the QGIS desktop application and saved, individual
map canvases will store their own previous view extent as custom project properties. Reloading
this saved version of the project will trigger the canvases to restore their individual last view
extents. Accordingly, in the QGIS desktop application, this setting only forms a default, initial
view used when the project is opened for the very first time.
This commit is contained in:
Nyall Dawson 2019-10-30 17:45:05 +10:00
parent 65490ab13e
commit f602ed3751
4 changed files with 131 additions and 1 deletions

View File

@ -30,6 +30,38 @@ Constructor for QgsProjectViewSettings with the specified ``parent`` object.
void reset();
%Docstring
Resets the settings to a default state.
%End
QgsReferencedRectangle defaultViewExtent() const;
%Docstring
Returns the default view extent, which should be used as the initial map extent
when this project is opened.
.. warning::
When a project is opened in the QGIS desktop application and saved, individual
map canvases will store their own previous view extent as custom project properties. Reloading
this saved version of the project will trigger the canvases to restore their individual last view
extents. Accordingly, in the QGIS desktop application, this setting only forms a default, initial
view used when the project is opened for the very first time.
.. seealso:: :py:func:`setDefaultViewExtent`
%End
void setDefaultViewExtent( const QgsReferencedRectangle &extent );
%Docstring
Sets the default view ``extent``, which should be used as the initial map extent
when this project is opened.
.. warning::
When a project is opened in the QGIS desktop application and saved, individual
map canvases will store their own previous view extent as custom project properties. Reloading
this saved version of the project will trigger the canvases to restore their individual last view
extents. Accordingly, in the QGIS desktop application, this setting only forms a default, initial
view used when the project is opened for the very first time.
.. seealso:: :py:func:`defaultViewExtent`
%End
void setMapScales( const QVector<double> &scales );

View File

@ -25,6 +25,7 @@ QgsProjectViewSettings::QgsProjectViewSettings( QObject *parent )
void QgsProjectViewSettings::reset()
{
mDefaultViewExtent = QgsReferencedRectangle();
if ( mUseProjectScales || !mMapScales.empty() )
{
mUseProjectScales = false;
@ -33,6 +34,16 @@ void QgsProjectViewSettings::reset()
}
}
QgsReferencedRectangle QgsProjectViewSettings::defaultViewExtent() const
{
return mDefaultViewExtent;
}
void QgsProjectViewSettings::setDefaultViewExtent( const QgsReferencedRectangle &extent )
{
mDefaultViewExtent = extent;
}
void QgsProjectViewSettings::setMapScales( const QVector<double> &scales )
{
// sort scales in descending order
@ -89,6 +100,22 @@ bool QgsProjectViewSettings::readXml( const QDomElement &element, const QgsReadW
emit mapScalesChanged();
}
QDomElement defaultViewElement = element.firstChildElement( QStringLiteral( "DefaultViewExtent" ) );
if ( !defaultViewElement.isNull() )
{
double xMin = defaultViewElement.attribute( QStringLiteral( "xmin" ) ).toDouble();
double yMin = defaultViewElement.attribute( QStringLiteral( "ymin" ) ).toDouble();
double xMax = defaultViewElement.attribute( QStringLiteral( "xmax" ) ).toDouble();
double yMax = defaultViewElement.attribute( QStringLiteral( "ymax" ) ).toDouble();
QgsCoordinateReferenceSystem crs;
crs.readXml( defaultViewElement );
mDefaultViewExtent = QgsReferencedRectangle( QgsRectangle( xMin, yMin, xMax, yMax ), crs );
}
else
{
mDefaultViewExtent = QgsReferencedRectangle();
}
return true;
}
@ -105,5 +132,17 @@ QDomElement QgsProjectViewSettings::writeXml( QDomDocument &doc, const QgsReadWr
scales.appendChild( scaleElement );
}
element.appendChild( scales );
if ( !mDefaultViewExtent.isNull() )
{
QDomElement defaultViewElement = doc.createElement( QStringLiteral( "DefaultViewExtent" ) );
defaultViewElement.setAttribute( QStringLiteral( "xmin" ), qgsDoubleToString( mDefaultViewExtent.xMinimum() ) );
defaultViewElement.setAttribute( QStringLiteral( "ymin" ), qgsDoubleToString( mDefaultViewExtent.yMinimum() ) );
defaultViewElement.setAttribute( QStringLiteral( "xmax" ), qgsDoubleToString( mDefaultViewExtent.xMaximum() ) );
defaultViewElement.setAttribute( QStringLiteral( "ymax" ), qgsDoubleToString( mDefaultViewExtent.yMaximum() ) );
mDefaultViewExtent.crs().writeXml( defaultViewElement, doc );
element.appendChild( defaultViewElement );
}
return element;
}

View File

@ -16,6 +16,7 @@
#define QGSPROJECTVIEWSETTINGS_H
#include "qgis_core.h"
#include "qgsreferencedgeometry.h"
#include <QObject>
#include <QVector>
@ -46,6 +47,34 @@ class CORE_EXPORT QgsProjectViewSettings : public QObject
*/
void reset();
/**
* Returns the default view extent, which should be used as the initial map extent
* when this project is opened.
*
* \warning When a project is opened in the QGIS desktop application and saved, individual
* map canvases will store their own previous view extent as custom project properties. Reloading
* this saved version of the project will trigger the canvases to restore their individual last view
* extents. Accordingly, in the QGIS desktop application, this setting only forms a default, initial
* view used when the project is opened for the very first time.
*
* \see setDefaultViewExtent()
*/
QgsReferencedRectangle defaultViewExtent() const;
/**
* Sets the default view \a extent, which should be used as the initial map extent
* when this project is opened.
*
* \warning When a project is opened in the QGIS desktop application and saved, individual
* map canvases will store their own previous view extent as custom project properties. Reloading
* this saved version of the project will trigger the canvases to restore their individual last view
* extents. Accordingly, in the QGIS desktop application, this setting only forms a default, initial
* view used when the project is opened for the very first time.
*
* \see defaultViewExtent()
*/
void setDefaultViewExtent( const QgsReferencedRectangle &extent );
/**
* Sets the list of custom project map \a scales.
*
@ -110,6 +139,7 @@ class CORE_EXPORT QgsProjectViewSettings : public QObject
QVector<double> mMapScales;
bool mUseProjectScales = false;
QgsReferencedRectangle mDefaultViewExtent;
};
#endif // QGSPROJECTVIEWSETTINGS_H

View File

@ -13,7 +13,10 @@ __copyright__ = 'Copyright 2019, The QGIS Project'
import qgis # NOQA
from qgis.core import (QgsProjectViewSettings,
QgsReadWriteContext)
QgsReadWriteContext,
QgsReferencedRectangle,
QgsRectangle,
QgsCoordinateReferenceSystem)
from qgis.PyQt.QtTest import QSignalSpy
from qgis.PyQt.QtXml import QDomDocument, QDomElement
@ -55,6 +58,29 @@ class TestQgsProjectViewSettings(unittest.TestCase):
p.setUseProjectScales(False)
self.assertEqual(len(spy), 4)
p.setUseProjectScales(True)
p.setMapScales([5000, 6000, 3000, 4000])
self.assertEqual(len(spy), 6)
p.reset()
self.assertEqual(len(spy), 7)
self.assertFalse(p.mapScales())
self.assertFalse(p.useProjectScales())
def testDefaultViewExtent(self):
p = QgsProjectViewSettings()
self.assertTrue(p.defaultViewExtent().isNull())
p.setDefaultViewExtent(QgsReferencedRectangle(QgsRectangle(1, 2, 3, 4), QgsCoordinateReferenceSystem("EPSG:3857")))
self.assertEqual(p.defaultViewExtent(), QgsReferencedRectangle(QgsRectangle(1, 2, 3, 4), QgsCoordinateReferenceSystem("EPSG:3857")))
p.setDefaultViewExtent(QgsReferencedRectangle())
self.assertTrue(p.defaultViewExtent().isNull())
p.setDefaultViewExtent(QgsReferencedRectangle(QgsRectangle(1, 2, 3, 4), QgsCoordinateReferenceSystem("EPSG:3857")))
p.reset()
self.assertTrue(p.defaultViewExtent().isNull())
def testReadWrite(self):
p = QgsProjectViewSettings()
self.assertFalse(p.mapScales())
@ -68,9 +94,11 @@ class TestQgsProjectViewSettings(unittest.TestCase):
self.assertFalse(p2.mapScales())
self.assertFalse(p2.useProjectScales())
self.assertEqual(len(spy), 0)
self.assertTrue(p2.defaultViewExtent().isNull())
p.setUseProjectScales(True)
p.setMapScales([56, 78, 99])
p.setDefaultViewExtent(QgsReferencedRectangle(QgsRectangle(1, 2, 3, 4), QgsCoordinateReferenceSystem("EPSG:3857")))
elem = p.writeXml(doc, QgsReadWriteContext())
p2 = QgsProjectViewSettings()
@ -79,6 +107,7 @@ class TestQgsProjectViewSettings(unittest.TestCase):
self.assertEqual(p2.mapScales(), [99.0, 78.0, 56.0])
self.assertTrue(p2.useProjectScales())
self.assertEqual(len(spy), 1)
self.assertEqual(p2.defaultViewExtent(), QgsReferencedRectangle(QgsRectangle(1, 2, 3, 4), QgsCoordinateReferenceSystem("EPSG:3857")))
if __name__ == '__main__':