Skip to content

Commit

Permalink
QgsSettings: add writeArray and more group and array tests
Browse files Browse the repository at this point in the history
  • Loading branch information
elpaso committed Apr 12, 2017
1 parent 29d228d commit 9c2f88c
Show file tree
Hide file tree
Showing 4 changed files with 153 additions and 17 deletions.
31 changes: 26 additions & 5 deletions python/core/qgssettings.sip
Expand Up @@ -33,8 +33,10 @@ class QgsSettings : QObject
- Gui
- Server
- Plugins
- Misc
- Auth
- App
- Providers
- Misc

.. versionadded:: 3
%End
Expand Down Expand Up @@ -169,17 +171,30 @@ Set the Global Settings QSettings storage file
Adds prefix to the current group and starts reading from an array. Returns the size of the array.
:rtype: int
%End

void beginWriteArray( const QString &prefix, int size = -1 );
%Docstring
Adds prefix to the current group and starts writing an array of size size.
If size is -1 (the default), it is automatically determined based on the indexes of the entries written.
.. note::

This will completely shadow any existing array with the same name in the global settings
%End
void endArray();
%Docstring
Closes the array that was started using beginReadArray() or beginWriteArray().
%End

void setArrayIndex( int i );
%Docstring
remove(), and contains() will operate on the array entry at that index.
Sets the current array index to i. Calls to functions such as setValue(), value(),
remove(), and contains() will operate on the array entry at that index.
%End

void setValue( const QString &key, const QVariant &value, const QgsSettings::Section section = QgsSettings::NoSection );
%Docstring
An optional Section argument can be used to set a value to a specific Section.
Sets the value of setting key to value. If the key already exists, the previous value is overwritten.
An optional Section argument can be used to set a value to a specific Section.
%End

SIP_PYOBJECT value( const QString &key, const QVariant &defaultValue = QVariant(),
Expand All @@ -205,19 +220,25 @@ An optional Section argument can be used to set a value to a specific Section.

sipIsErr = !sipRes;
%End

bool contains( const QString &key, const QgsSettings::Section section = QgsSettings::NoSection ) const;
%Docstring
If a group is set using beginGroup(), key is taken to be relative to that group.
Returns true if there exists a setting called key; returns false otherwise.
If a group is set using beginGroup(), key is taken to be relative to that group.
:rtype: bool
%End
QString fileName() const;
%Docstring
Returns the path where settings written using this QSettings object are stored.
:rtype: str
%End

void sync();
%Docstring
loop at regular intervals, so you normally don't need to call it yourself.
Writes any unsaved changes to permanent storage, and reloads any settings that have been
changed in the meantime by another application.
This function is called automatically from QSettings's destructor and by the event
loop at regular intervals, so you normally don't need to call it yourself.
%End
void remove( const QString &key );
%Docstring
Expand Down
6 changes: 6 additions & 0 deletions src/core/qgssettings.cpp
Expand Up @@ -234,6 +234,12 @@ int QgsSettings::beginReadArray( const QString &prefix )
return size;
}

void QgsSettings::beginWriteArray( const QString &prefix, int size )
{
mUsingGlobalArray = false;
mUserSettings->beginWriteArray( prefix, size );
}

void QgsSettings::endArray()
{
mUserSettings->endArray();
Expand Down
38 changes: 27 additions & 11 deletions src/core/qgssettings.h
Expand Up @@ -44,8 +44,10 @@
* - Gui
* - Server
* - Plugins
* - Misc
* - Auth
* - App
* - Providers
* - Misc
*
* \since QGIS 3
*/
Expand Down Expand Up @@ -154,13 +156,23 @@ class CORE_EXPORT QgsSettings : public QObject
static bool setGlobalSettingsPath( QString path );
//! Adds prefix to the current group and starts reading from an array. Returns the size of the array.
int beginReadArray( const QString &prefix );

/** Adds prefix to the current group and starts writing an array of size size.
* If size is -1 (the default), it is automatically determined based on the indexes of the entries written.
* @note This will completely shadow any existing array with the same name in the global settings
*/
void beginWriteArray( const QString &prefix, int size = -1 );
//! Closes the array that was started using beginReadArray() or beginWriteArray().
void endArray();
//! Sets the current array index to i. Calls to functions such as setValue(), value(),
//! remove(), and contains() will operate on the array entry at that index.

/** Sets the current array index to i. Calls to functions such as setValue(), value(),
* remove(), and contains() will operate on the array entry at that index.
*/
void setArrayIndex( int i );
//! Sets the value of setting key to value. If the key already exists, the previous value is overwritten.
//! An optional Section argument can be used to set a value to a specific Section.

/** Sets the value of setting key to value. If the key already exists, the previous value is overwritten.
* An optional Section argument can be used to set a value to a specific Section.
*/
void setValue( const QString &key, const QVariant &value, const QgsSettings::Section section = QgsSettings::NoSection );

/** Returns the value for setting key. If the setting doesn't exist, it will be
Expand Down Expand Up @@ -190,15 +202,19 @@ class CORE_EXPORT QgsSettings : public QObject
sipIsErr = !sipRes;
% End
#endif
//! Returns true if there exists a setting called key; returns false otherwise.
//! If a group is set using beginGroup(), key is taken to be relative to that group.

/** Returns true if there exists a setting called key; returns false otherwise.
* If a group is set using beginGroup(), key is taken to be relative to that group.
*/
bool contains( const QString &key, const QgsSettings::Section section = QgsSettings::NoSection ) const;
//! Returns the path where settings written using this QSettings object are stored.
QString fileName() const;
//! Writes any unsaved changes to permanent storage, and reloads any settings that have been
//! changed in the meantime by another application.
//! This function is called automatically from QSettings's destructor and by the event
//! loop at regular intervals, so you normally don't need to call it yourself.

/** Writes any unsaved changes to permanent storage, and reloads any settings that have been
* changed in the meantime by another application.
* This function is called automatically from QSettings's destructor and by the event
* loop at regular intervals, so you normally don't need to call it yourself.
*/
void sync();
//! Removes the setting key and any sub-settings of key.
void remove( const QString &key );
Expand Down
95 changes: 94 additions & 1 deletion tests/src/python/test_qgssettings.py
Expand Up @@ -68,6 +68,14 @@ def addArrayToDefaults(self, prefix, key, values):
self.globalsettings.endArray()
self.globalsettings.sync()

def addGroupToDefaults(self, prefix, kvp):
defaults = QSettings(self.settings.globalSettingsPath(), QSettings.IniFormat) # NOQA
self.globalsettings.beginGroup(prefix)
for k, v in kvp.items():
self.globalsettings.setValue(k, v)
self.globalsettings.endGroup()
self.globalsettings.sync()

def test_basic_functionality(self):
self.assertEqual(self.settings.value('testqgissettings/doesnotexists', 'notexist'), 'notexist')
self.settings.setValue('testqgissettings/name', 'qgisrocks')
Expand Down Expand Up @@ -95,13 +103,69 @@ def test_allkeys(self):
self.assertEqual(3, len(self.settings.allKeys()))
self.assertEqual(2, len(self.globalsettings.allKeys()))

def test_precedence(self):
def test_precedence_simple(self):
self.assertEqual(self.settings.allKeys(), [])
self.addToDefaults('testqgissettings/names/name1', 'qgisrocks1')
self.settings.setValue('testqgissettings/names/name1', 'qgisrocks-1')

self.assertEqual(self.settings.value('testqgissettings/names/name1'), 'qgisrocks-1')

def test_precedence_group(self):
"""Test if user can override a group value"""
self.assertEqual(self.settings.allKeys(), [])
self.addGroupToDefaults('connections-xyz', {
'OSM': 'http://a.tile.openstreetmap.org/{z}/{x}/{y}.png',
'OSM-b': 'http://b.tile.openstreetmap.org/{z}/{x}/{y}.png',
})
self.settings.beginGroup('connections-xyz')
self.assertEqual(self.settings.value('OSM'), 'http://a.tile.openstreetmap.org/{z}/{x}/{y}.png')
self.assertEqual(self.settings.value('OSM-b'), 'http://b.tile.openstreetmap.org/{z}/{x}/{y}.png')
self.settings.endGroup()

# Override edit
self.settings.beginGroup('connections-xyz')
self.settings.setValue('OSM', 'http://c.tile.openstreetmap.org/{z}/{x}/{y}.png')
self.settings.endGroup()

# Check it again!
self.settings.beginGroup('connections-xyz')
self.assertEqual(self.settings.value('OSM'), 'http://c.tile.openstreetmap.org/{z}/{x}/{y}.png')
self.assertEqual(self.settings.value('OSM-b'), 'http://b.tile.openstreetmap.org/{z}/{x}/{y}.png')
self.settings.endGroup()

# Override remove: the global value will be resumed!!!
self.settings.beginGroup('connections-xyz')
self.settings.remove('OSM')
self.settings.endGroup()

# Check it again!
self.settings.beginGroup('connections-xyz')
self.assertEqual(self.settings.value('OSM'), 'http://a.tile.openstreetmap.org/{z}/{x}/{y}.png')
self.assertEqual(self.settings.value('OSM-b'), 'http://b.tile.openstreetmap.org/{z}/{x}/{y}.png')
self.settings.endGroup()

# Override remove: store a blank!
self.settings.beginGroup('connections-xyz')
self.settings.setValue('OSM', '')
self.settings.endGroup()

# Check it again!
self.settings.beginGroup('connections-xyz')
self.assertEqual(self.settings.value('OSM'), '')
self.assertEqual(self.settings.value('OSM-b'), 'http://b.tile.openstreetmap.org/{z}/{x}/{y}.png')
self.settings.endGroup()

# Override remove: store a None: will resume the global setting!
self.settings.beginGroup('connections-xyz')
self.settings.setValue('OSM', None)
self.settings.endGroup()

# Check it again!
self.settings.beginGroup('connections-xyz')
self.assertEqual(self.settings.value('OSM'), 'http://a.tile.openstreetmap.org/{z}/{x}/{y}.png')
self.assertEqual(self.settings.value('OSM-b'), 'http://b.tile.openstreetmap.org/{z}/{x}/{y}.png')
self.settings.endGroup()

def test_uft8(self):
self.assertEqual(self.settings.allKeys(), [])
self.addToDefaults('testqgissettings/names/namèé↓1', 'qgisrocks↓1')
Expand Down Expand Up @@ -153,6 +217,35 @@ def test_array(self):

self.assertEqual(values, ['qgisrocks1', 'qgisrocks2', 'qgisrocks3'])

def test_array_overrides(self):
"""Test if an array completely shadows the global one"""
self.assertEqual(self.settings.allKeys(), [])
self.addArrayToDefaults('testqgissettings', 'key', ['qgisrocks1', 'qgisrocks2', 'qgisrocks3'])
self.assertEqual(self.settings.allKeys(), ['testqgissettings/1/key', 'testqgissettings/2/key', 'testqgissettings/3/key', 'testqgissettings/size'])
self.assertEqual(self.globalsettings.allKeys(), ['testqgissettings/1/key', 'testqgissettings/2/key', 'testqgissettings/3/key', 'testqgissettings/size'])

self.assertEqual(3, self.globalsettings.beginReadArray('testqgissettings'))
self.globalsettings.endArray()
self.assertEqual(3, self.settings.beginReadArray('testqgissettings'))

# Now override!
self.settings.beginWriteArray('testqgissettings')
self.settings.setArrayIndex(0)
self.settings.setValue('key', 'myqgisrocksmore1')
self.settings.setArrayIndex(1)
self.settings.setValue('key', 'myqgisrocksmore2')
self.settings.endArray()

# Check it!
self.assertEqual(2, self.settings.beginReadArray('testqgissettings'))

values = []
for i in range(2):
self.settings.setArrayIndex(i)
values.append(self.settings.value("key"))

self.assertEqual(values, ['myqgisrocksmore1', 'myqgisrocksmore2'])

def test_section_getters_setters(self):
self.assertEqual(self.settings.allKeys(), [])

Expand Down

0 comments on commit 9c2f88c

Please sign in to comment.