New class QgsProjectDisplaySettings

This class (attached to a QgsProject object) provides a place to
store and retrieve settings related to project display behavior,
e.g. the numeric formats used for bearings and coordinates
This commit is contained in:
Nyall Dawson 2020-01-08 16:42:01 +10:00
parent 0ba2bccf86
commit 410da5e358
10 changed files with 385 additions and 0 deletions

View File

@ -575,6 +575,15 @@ relating to how a QgsProject should be viewed and behave inside a map canvas
.. versionadded:: 3.10.1
%End
QgsProjectDisplaySettings *displaySettings();
%Docstring
Returns the project's display settings, which settings and properties relating
to how a QgsProject should display values such as map coordinates and bearings.
.. versionadded:: 3.12
%End
QgsLayerTree *layerTreeRoot() const;
%Docstring
Returns pointer to the root (invisible) node of the project's layer tree

View File

@ -0,0 +1,90 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/qgsprojectdisplaysettings.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
class QgsProjectDisplaySettings : QObject
{
%Docstring
Contains settings and properties relating to how a QgsProject should display
values such as map coordinates and bearings.
.. versionadded:: 3.12
%End
%TypeHeaderCode
#include "qgsprojectdisplaysettings.h"
%End
public:
QgsProjectDisplaySettings( QObject *parent = 0 );
%Docstring
Constructor for QgsProjectDisplaySettings with the specified ``parent`` object.
%End
~QgsProjectDisplaySettings();
void reset();
%Docstring
Resets the settings to a default state.
%End
void setBearingFormat( QgsBearingNumericFormat *format /Transfer/ );
%Docstring
Sets the project bearing ``format``, which controls how bearings associated with the project are displayed.
Ownership of ``format`` is transferred to the settings.
.. seealso:: :py:func:`bearingFormat`
.. seealso:: :py:func:`bearingFormatChanged`
%End
const QgsBearingNumericFormat *bearingFormat() const;
%Docstring
Returns the project bearing's format, which controls how bearings associated with the project are displayed.
.. seealso:: :py:func:`setBearingFormat`
.. seealso:: :py:func:`bearingFormatChanged`
%End
bool readXml( const QDomElement &element, const QgsReadWriteContext &context );
%Docstring
Reads the settings's state from a DOM element.
.. seealso:: :py:func:`writeXml`
%End
QDomElement writeXml( QDomDocument &doc, const QgsReadWriteContext &context ) const;
%Docstring
Returns a DOM element representing the settings.
.. seealso:: :py:func:`readXml`
%End
signals:
void bearingFormatChanged();
%Docstring
Emitted when the bearing format changes.
.. seealso:: :py:func:`setBearingFormat`
.. seealso:: :py:func:`bearingFormat`
%End
};
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/qgsprojectdisplaysettings.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/

View File

@ -144,6 +144,7 @@
%Include auto_generated/qgspostgresstringutils.sip
%Include auto_generated/qgsproject.sip
%Include auto_generated/qgsprojectbadlayerhandler.sip
%Include auto_generated/qgsprojectdisplaysettings.sip
%Include auto_generated/qgsprojectfiletransform.sip
%Include auto_generated/qgsprojectproperty.sip
%Include auto_generated/qgsprojectstorage.sip

View File

@ -332,6 +332,7 @@ SET(QGIS_CORE_SRCS
qgsprojectbadlayerhandler.cpp
qgsprojectfiletransform.cpp
qgssnappingconfig.cpp
qgsprojectdisplaysettings.cpp
qgsprojectproperty.cpp
qgsprojectstorage.cpp
qgsprojectstorageregistry.cpp
@ -832,6 +833,7 @@ SET(QGIS_CORE_HDRS
qgspostgresstringutils.h
qgsproject.h
qgsprojectbadlayerhandler.h
qgsprojectdisplaysettings.h
qgsprojectfiletransform.h
qgsprojectproperty.h
qgsprojectstorage.h

View File

@ -58,6 +58,7 @@
#include "qgsexpressioncontextutils.h"
#include "qgsstyleentityvisitor.h"
#include "qgsprojectviewsettings.h"
#include "qgsprojectdisplaysettings.h"
#include <algorithm>
#include <QApplication>
@ -363,6 +364,7 @@ QgsProject::QgsProject( QObject *parent )
, mLayoutManager( new QgsLayoutManager( this ) )
, mBookmarkManager( QgsBookmarkManager::createProjectBasedManager( this ) )
, mViewSettings( new QgsProjectViewSettings( this ) )
, mDisplaySettings( new QgsProjectDisplaySettings( this ) )
, mRootGroup( new QgsLayerTree )
, mLabelingEngineSettings( new QgsLabelingEngineSettings )
, mArchive( new QgsProjectArchive() )
@ -748,6 +750,7 @@ void QgsProject::clear()
mLayoutManager->clear();
mBookmarkManager->clear();
mViewSettings->reset();
mDisplaySettings->reset();
mSnappingConfig.reset();
emit snappingConfigChanged( mSnappingConfig );
emit topologicalEditingChanged();
@ -1504,6 +1507,10 @@ bool QgsProject::readProjectFile( const QString &filename, QgsProject::ReadFlags
if ( !viewSettingsElement.isNull() )
mViewSettings->readXml( viewSettingsElement, context );
QDomElement displaySettingsElement = doc->documentElement().firstChildElement( QStringLiteral( "ProjectDisplaySettings" ) );
if ( !displaySettingsElement.isNull() )
mDisplaySettings->readXml( displaySettingsElement, context );
emit customVariablesChanged();
emit crsChanged();
emit ellipsoidChanged( ellipsoid() );
@ -2104,6 +2111,9 @@ bool QgsProject::writeProjectFile( const QString &filename )
QDomElement viewSettingsElem = mViewSettings->writeXml( *doc, context );
qgisNode.appendChild( viewSettingsElem );
QDomElement displaySettingsElem = mDisplaySettings->writeXml( *doc, context );
qgisNode.appendChild( displaySettingsElem );
// now wrap it up and ship it to the project file
doc->normalize(); // XXX I'm not entirely sure what this does
@ -2809,6 +2819,16 @@ QgsProjectViewSettings *QgsProject::viewSettings()
return mViewSettings;
}
const QgsProjectDisplaySettings *QgsProject::displaySettings() const
{
return mDisplaySettings;
}
QgsProjectDisplaySettings *QgsProject::displaySettings()
{
return mDisplaySettings;
}
QgsLayerTree *QgsProject::layerTreeRoot() const
{
return mRootGroup;

View File

@ -73,6 +73,7 @@ class QgsAuxiliaryStorage;
class QgsMapLayer;
class QgsBookmarkManager;
class QgsProjectViewSettings;
class QgsProjectDisplaySettings;
/**
* \ingroup core
@ -580,6 +581,21 @@ class CORE_EXPORT QgsProject : public QObject, public QgsExpressionContextGenera
*/
QgsProjectViewSettings *viewSettings();
/**
* Returns the project's display settings, which settings and properties relating
* to how a QgsProject should display values such as map coordinates and bearings.
* \note not available in Python bindings
* \since QGIS 3.12
*/
const QgsProjectDisplaySettings *displaySettings() const SIP_SKIP;
/**
* Returns the project's display settings, which settings and properties relating
* to how a QgsProject should display values such as map coordinates and bearings.
* \since QGIS 3.12
*/
QgsProjectDisplaySettings *displaySettings();
/**
* Returns pointer to the root (invisible) node of the project's layer tree
* \since QGIS 2.4
@ -1744,6 +1760,8 @@ class CORE_EXPORT QgsProject : public QObject, public QgsExpressionContextGenera
QgsProjectViewSettings *mViewSettings = nullptr;
QgsProjectDisplaySettings *mDisplaySettings = nullptr;
QgsLayerTree *mRootGroup = nullptr;
QgsLayerTreeRegistryBridge *mLayerTreeRegistryBridge = nullptr;

View File

@ -0,0 +1,69 @@
/***************************************************************************
qgsprojectdisplaysettings.cpp
-----------------------------
begin : January 2020
copyright : (C) 2020 by Nyall Dawson
email : nyall dot dawson at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsprojectdisplaysettings.h"
#include "qgis.h"
#include "qgsbearingnumericformat.h"
#include "qgsnumericformatregistry.h"
#include "qgsapplication.h"
#include <QDomElement>
QgsProjectDisplaySettings::QgsProjectDisplaySettings( QObject *parent )
: QObject( parent )
, mBearingFormat( qgis::make_unique< QgsBearingNumericFormat >() )
{
}
QgsProjectDisplaySettings::~QgsProjectDisplaySettings() = default;
void QgsProjectDisplaySettings::reset()
{
mBearingFormat = qgis::make_unique< QgsBearingNumericFormat >();
emit bearingFormatChanged();
}
void QgsProjectDisplaySettings::setBearingFormat( QgsBearingNumericFormat *format )
{
mBearingFormat.reset( format );
emit bearingFormatChanged();
}
const QgsBearingNumericFormat *QgsProjectDisplaySettings::bearingFormat() const
{
return mBearingFormat.get();
}
bool QgsProjectDisplaySettings::readXml( const QDomElement &element, const QgsReadWriteContext &context )
{
QDomElement bearingElement = element.firstChildElement( QStringLiteral( "BearingFormat" ) );
mBearingFormat.reset( static_cast< QgsBearingNumericFormat * >( QgsApplication::numericFormatRegistry()->createFromXml( bearingElement, context ) ) );
emit bearingFormatChanged();
return true;
}
QDomElement QgsProjectDisplaySettings::writeXml( QDomDocument &doc, const QgsReadWriteContext &context ) const
{
QDomElement element = doc.createElement( QStringLiteral( "ProjectDisplaySettings" ) );
QDomElement bearingElement = doc.createElement( QStringLiteral( "BearingFormat" ) );
mBearingFormat->writeXml( bearingElement, doc, context );
element.appendChild( bearingElement );
return element;
}

View File

@ -0,0 +1,99 @@
/***************************************************************************
qgsprojectdisplaysettings.h
---------------------------
begin : January 2020
copyright : (C) 2020 by Nyall Dawson
email : nyall dot dawson at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSPROJECTDISPLAYSETTINGS_H
#define QGSPROJECTDISPLAYSETTINGS_H
#include "qgis_core.h"
#include "qgis_sip.h"
#include <QObject>
#include <QVector>
#include <memory>
class QDomElement;
class QgsReadWriteContext;
class QDomDocument;
class QgsBearingNumericFormat;
/**
* Contains settings and properties relating to how a QgsProject should display
* values such as map coordinates and bearings.
*
* \ingroup core
* \since QGIS 3.12
*/
class CORE_EXPORT QgsProjectDisplaySettings : public QObject
{
Q_OBJECT
public:
/**
* Constructor for QgsProjectDisplaySettings with the specified \a parent object.
*/
QgsProjectDisplaySettings( QObject *parent = nullptr );
~QgsProjectDisplaySettings() override;
/**
* Resets the settings to a default state.
*/
void reset();
/**
* Sets the project bearing \a format, which controls how bearings associated with the project are displayed.
*
* Ownership of \a format is transferred to the settings.
*
* \see bearingFormat()
* \see bearingFormatChanged()
*/
void setBearingFormat( QgsBearingNumericFormat *format SIP_TRANSFER );
/**
* Returns the project bearing's format, which controls how bearings associated with the project are displayed.
*
* \see setBearingFormat()
* \see bearingFormatChanged()
*/
const QgsBearingNumericFormat *bearingFormat() const;
/**
* Reads the settings's state from a DOM element.
* \see writeXml()
*/
bool readXml( const QDomElement &element, const QgsReadWriteContext &context );
/**
* Returns a DOM element representing the settings.
* \see readXml()
*/
QDomElement writeXml( QDomDocument &doc, const QgsReadWriteContext &context ) const;
signals:
/**
* Emitted when the bearing format changes.
*
* \see setBearingFormat()
* \see bearingFormat()
*/
void bearingFormatChanged();
private:
std::unique_ptr< QgsBearingNumericFormat > mBearingFormat;
};
#endif // QGSPROJECTDISPLAYSETTINGS_H

View File

@ -69,6 +69,7 @@ ADD_PYTHON_TEST(PyQgsFieldFormattersTest test_qgsfieldformatters.py)
ADD_PYTHON_TEST(PyQgsFillSymbolLayers test_qgsfillsymbollayers.py)
ADD_PYTHON_TEST(PyQgsProject test_qgsproject.py)
ADD_PYTHON_TEST(PyQgsProjectBadLayers test_qgsprojectbadlayers.py)
ADD_PYTHON_TEST(PyQgsProjectDisplaySettings test_qgsprojectdisplaysettings.py)
ADD_PYTHON_TEST(PyQgsProjectViewSettings test_qgsprojectviewsettings.py)
ADD_PYTHON_TEST(PyQgsFeatureIterator test_qgsfeatureiterator.py)
ADD_PYTHON_TEST(PyQgsFeedback test_qgsfeedback.py)

View File

@ -0,0 +1,76 @@
# -*- coding: utf-8 -*-
"""QGIS Unit tests for QgsProjectDisplaySettings.
.. note:: This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
"""
__author__ = 'Nyall Dawson'
__date__ = '09/01/2020'
__copyright__ = 'Copyright 2020, The QGIS Project'
import qgis # NOQA
from qgis.core import (QgsProject,
QgsProjectDisplaySettings,
QgsReadWriteContext,
QgsBearingNumericFormat)
from qgis.PyQt.QtCore import QTemporaryDir
from qgis.PyQt.QtTest import QSignalSpy
from qgis.PyQt.QtXml import QDomDocument, QDomElement
from qgis.testing import start_app, unittest
from utilities import (unitTestDataPath)
app = start_app()
TEST_DATA_DIR = unitTestDataPath()
class TestQgsProjectDisplaySettings(unittest.TestCase):
def testBearingFormat(self):
p = QgsProjectDisplaySettings()
format = QgsBearingNumericFormat()
format.setNumberDecimalPlaces(9)
format.setDirectionFormat(QgsBearingNumericFormat.UseRange0To360)
spy = QSignalSpy(p.bearingFormatChanged)
p.setBearingFormat(format)
self.assertEqual(len(spy), 1)
self.assertEqual(p.bearingFormat().numberDecimalPlaces(), 9)
format = QgsBearingNumericFormat()
format.setNumberDecimalPlaces(3)
format.setDirectionFormat(QgsBearingNumericFormat.UseRange0To360)
p.setBearingFormat(format)
self.assertEqual(len(spy), 2)
self.assertEqual(p.bearingFormat().numberDecimalPlaces(), 3)
p.reset()
self.assertEqual(len(spy), 3)
self.assertEqual(p.bearingFormat().numberDecimalPlaces(), 6)
def testReadWrite(self):
p = QgsProjectDisplaySettings()
format = QgsBearingNumericFormat()
format.setNumberDecimalPlaces(9)
format.setDirectionFormat(QgsBearingNumericFormat.UseRange0To360)
p.setBearingFormat(format)
doc = QDomDocument("testdoc")
elem = p.writeXml(doc, QgsReadWriteContext())
p2 = QgsProjectDisplaySettings()
spy = QSignalSpy(p2.bearingFormatChanged)
self.assertTrue(p2.readXml(elem, QgsReadWriteContext()))
self.assertEqual(len(spy), 1)
self.assertEqual(p2.bearingFormat().numberDecimalPlaces(), 9)
self.assertEqual(p2.bearingFormat().directionFormat(), QgsBearingNumericFormat.UseRange0To360)
if __name__ == '__main__':
unittest.main()