Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEATURE][needs-docs] Add XYZ connection to provide default OpenStreetMap tiles #5000

Merged
merged 11 commits into from Sep 8, 2017
5 changes: 5 additions & 0 deletions python/core/qgssettings.sip
Expand Up @@ -155,6 +155,11 @@ Returns a list of all top-level keys that can be read using the QSettings object
%Docstring
Returns a list of all key top-level groups that contain keys that can be read using the QSettings object.
:rtype: list of str
%End
QStringList globalChildGroups() const;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you mind adding a test case for globalChildGroups() to https://github.com/qgis/QGIS/blob/master/tests/src/python/test_qgssettings.py ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @elpaso. I discovered another minor issue writing the test. The test now covers the settings.globalChildGroups().

%Docstring
Returns a list of all key top-level groups (same as childGroups) but only for groups defined in global settings.
:rtype: list of str
%End
static QString globalSettingsPath();
%Docstring
Expand Down
2 changes: 2 additions & 0 deletions resources/CMakeLists.txt
@@ -1,4 +1,6 @@
INSTALL(FILES srs.db qgis.db symbology-style.xml spatialite.db customization.xml
DESTINATION ${QGIS_DATA_DIR}/resources)
INSTALL(FILES qgis_global_settings.ini
DESTINATION ${QGIS_DATA_DIR})
INSTALL(DIRECTORY cpt-city-qgis-min DESTINATION ${QGIS_DATA_DIR}/resources)
INSTALL(DIRECTORY themes DESTINATION ${QGIS_DATA_DIR}/resources)
8 changes: 8 additions & 0 deletions resources/qgis_global_settings.ini
@@ -0,0 +1,8 @@
[qgis]
connections-xyz\OpenStreetMap\authcfg=
connections-xyz\OpenStreetMap\password=
connections-xyz\OpenStreetMap\referer=
connections-xyz\OpenStreetMap\url=http://a.tile.openstreetmap.org/{z}/{x}/{y}.png
connections-xyz\OpenStreetMap\username=
connections-xyz\OpenStreetMap\zmax=19
connections-xyz\OpenStreetMap\zmin=0
57 changes: 28 additions & 29 deletions src/app/main.cpp
Expand Up @@ -785,35 +785,6 @@ int main( int argc, char *argv[] )
QCoreApplication::setApplicationName( QgsApplication::QGIS_APPLICATION_NAME );
QCoreApplication::setAttribute( Qt::AA_DontShowIconsInMenus, false );


// SetUp the QgsSettings Global Settings:
// - use the path specified with --globalsettingsfile path,
// - use the environment if not found
// - use a default location as a fallback
if ( globalsettingsfile.isEmpty() )
{
globalsettingsfile = getenv( "QGIS_GLOBAL_SETTINGS_FILE" );
}
if ( globalsettingsfile.isEmpty() )
{
QString default_globalsettingsfile = QgsApplication::pkgDataPath() + "/qgis_global_settings.ini";
if ( QFile::exists( default_globalsettingsfile ) )
{
globalsettingsfile = default_globalsettingsfile;
}
}
if ( !globalsettingsfile.isEmpty() )
{
if ( ! QgsSettings::setGlobalSettingsPath( globalsettingsfile ) )
{
QgsMessageLog::logMessage( QString( "Invalid globalsettingsfile path: %1" ).arg( globalsettingsfile ), QStringLiteral( "QGIS" ) );
}
else
{
QgsMessageLog::logMessage( QString( "Successfully loaded globalsettingsfile path: %1" ).arg( globalsettingsfile ), QStringLiteral( "QGIS" ) );
}
}

QgsSettings settings;
if ( configLocalStorageLocation.isEmpty() )
{
Expand Down Expand Up @@ -848,6 +819,34 @@ int main( int argc, char *argv[] )

QgsApplication myApp( argc, argv, myUseGuiFlag, profileFolder );

// SetUp the QgsSettings Global Settings:
// - use the path specified with --globalsettingsfile path,
// - use the environment if not found
// - use a default location as a fallback
if ( globalsettingsfile.isEmpty() )
{
globalsettingsfile = getenv( "QGIS_GLOBAL_SETTINGS_FILE" );
}
if ( globalsettingsfile.isEmpty() )
{
QString default_globalsettingsfile = QgsApplication::pkgDataPath() + "/qgis_global_settings.ini";
if ( QFile::exists( default_globalsettingsfile ) )
{
globalsettingsfile = default_globalsettingsfile;
}
}
if ( !globalsettingsfile.isEmpty() )
{
if ( ! QgsSettings::setGlobalSettingsPath( globalsettingsfile ) )
{
QgsMessageLog::logMessage( QString( "Invalid globalsettingsfile path: %1" ).arg( globalsettingsfile ), QStringLiteral( "QGIS" ) );
}
else
{
QgsMessageLog::logMessage( QString( "Successfully loaded globalsettingsfile path: %1" ).arg( globalsettingsfile ), QStringLiteral( "QGIS" ) );
}
}

#ifdef Q_OS_MAC
// Set hidpi icons; use SVG icons, as PNGs will be relatively too small
QCoreApplication::setAttribute( Qt::AA_UseHighDpiPixmaps );
Expand Down
9 changes: 9 additions & 0 deletions src/core/qgssettings.cpp
Expand Up @@ -149,6 +149,15 @@ QStringList QgsSettings::childGroups() const
}
return keys;
}
QStringList QgsSettings::globalChildGroups() const
{
QStringList keys;
if ( mGlobalSettings )
{
QStringList keys = mGlobalSettings->childGroups();
}
return keys;
}

QVariant QgsSettings::value( const QString &key, const QVariant &defaultValue, const QgsSettings::Section section ) const
{
Expand Down
2 changes: 2 additions & 0 deletions src/core/qgssettings.h
Expand Up @@ -150,6 +150,8 @@ class CORE_EXPORT QgsSettings : public QObject
QStringList childKeys() const;
//! Returns a list of all key top-level groups that contain keys that can be read using the QSettings object.
QStringList childGroups() const;
//! Returns a list of all key top-level groups (same as childGroups) but only for groups defined in global settings.
QStringList globalChildGroups() const;
//! Return the path to the Global Settings QSettings storage file
static QString globalSettingsPath() { return sGlobalSettingsPath; }
//! Set the Global Settings QSettings storage file
Expand Down
1 change: 0 additions & 1 deletion src/providers/wms/qgswmssourceselect.cpp
Expand Up @@ -20,7 +20,6 @@

#include "qgswmsprovider.h"
#include "qgis.h" // GEO_EPSG_CRS_ID
#include "qgscontexthelp.h"
#include "qgscoordinatereferencesystem.h"
#include "qgsdatasourceuri.h"
#include "qgsprojectionselectiondialog.h"
Expand Down
49 changes: 48 additions & 1 deletion src/providers/wms/qgsxyzconnection.cpp
Expand Up @@ -13,6 +13,7 @@
* *
***************************************************************************/

#include <qgslogger.h>
#include "qgsxyzconnection.h"

#include "qgsdatasourceuri.h"
Expand Down Expand Up @@ -41,8 +42,27 @@ QString QgsXyzConnection::encodedUri() const
QStringList QgsXyzConnectionUtils::connectionList()
{
QgsSettings settings;
QStringList connList;

settings.beginGroup( QStringLiteral( "qgis/connections-xyz" ) );
return settings.childGroups();
connList = settings.childGroups();

QStringList global = settings.globalChildGroups();
settings.endGroup();

for ( auto &s : global )
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To avoid a detach you might want to try the new qgsAsConst 029f741 recently added by @nyalldawson or use Q_FOREACH

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It also should be const auto &

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To avoid a detach you might want to try the new qgsAsConst 029f741 recently added by @nyalldawson or use Q_FOREACH

... or simply use const QStringList global

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer to avoid the Q_FOREACH.

I've used the suggested pattern:

  const QStringList global = settings.globalChildGroups();
  for ( const auto &s : global )

{
settings.beginGroup( "qgis/connections-xyz/" + s );
bool isHidden = settings.value( QStringLiteral( "hidden" ), false ).toBool();
QString url = settings.value( QStringLiteral( "url" ), "" ).toString();
settings.endGroup();
if ( isHidden )
{
connList.removeOne( s );
}
}

return connList;
}

QgsXyzConnection QgsXyzConnectionUtils::connection( const QString &name )
Expand All @@ -59,18 +79,40 @@ QgsXyzConnection QgsXyzConnectionUtils::connection( const QString &name )
conn.username = settings.value( QStringLiteral( "username" ) ).toString();
conn.password = settings.value( QStringLiteral( "password" ) ).toString();
conn.referer = settings.value( QStringLiteral( "referer" ) ).toString();
conn.hidden = settings.value( QStringLiteral( "hidden" ) ).toBool();
return conn;
}

void QgsXyzConnectionUtils::deleteConnection( const QString &name )
{
QgsSettings settings;
settings.remove( "qgis/connections-xyz/" + name );

settings.beginGroup( QStringLiteral( "qgis/connections-xyz" ) );
QStringList global = settings.globalChildGroups();

if ( global.contains( name ) )
{
QgsSettings settings;
settings.beginGroup( "qgis/connections-xyz/" + name );
settings.setValue( QStringLiteral( "hidden" ), true );
}

}

void QgsXyzConnectionUtils::addConnection( const QgsXyzConnection &conn )
{
QgsSettings settings;
bool addHiddenProperty = false;

settings.beginGroup( QStringLiteral( "qgis/connections-xyz" ) );
QStringList global = settings.globalChildGroups();
if ( global.contains( conn.name ) )
{
addHiddenProperty = true;
}
settings.endGroup();

settings.beginGroup( "qgis/connections-xyz/" + conn.name );
settings.setValue( QStringLiteral( "url" ), conn.url );
settings.setValue( QStringLiteral( "zmin" ), conn.zMin );
Expand All @@ -79,4 +121,9 @@ void QgsXyzConnectionUtils::addConnection( const QgsXyzConnection &conn )
settings.setValue( QStringLiteral( "username" ), conn.username );
settings.setValue( QStringLiteral( "password" ), conn.password );
settings.setValue( QStringLiteral( "referer" ), conn.referer );
if ( addHiddenProperty )
{
settings.setValue( QStringLiteral( "hidden" ), false );
}

}
5 changes: 3 additions & 2 deletions src/providers/wms/qgsxyzconnection.h
Expand Up @@ -32,6 +32,7 @@ struct QgsXyzConnection
QString password;
// Referer
QString referer;
bool hidden;

QString encodedUri() const;
};
Expand All @@ -40,7 +41,7 @@ struct QgsXyzConnection
class QgsXyzConnectionUtils
{
public:
//! Returns list of existing connections
//! Returns list of existing connections, unless the hidden ones
static QStringList connectionList();

//! Returns connection details
Expand All @@ -54,4 +55,4 @@ class QgsXyzConnectionUtils
};


#endif // QGSXYZCONNECTION_H
#endif // QGSXYZCONNECTION_H
1 change: 1 addition & 0 deletions tests/src/python/CMakeLists.txt
Expand Up @@ -172,6 +172,7 @@ ADD_PYTHON_TEST(PyQgsVersionCompare test_versioncompare.py)
ADD_PYTHON_TEST(PyQgsDBManagerGpkg test_db_manager_gpkg.py)
ADD_PYTHON_TEST(PyQgsFileDownloader test_qgsfiledownloader.py)
ADD_PYTHON_TEST(PyQgsSettings test_qgssettings.py)
ADD_PYTHON_TEST(PyQgsGlobalSettings test_qgis_global_settings.py)
ADD_PYTHON_TEST(PyQgsZipUtils test_qgsziputils.py)

IF (NOT WIN32)
Expand Down
56 changes: 56 additions & 0 deletions tests/src/python/test_qgis_global_settings.py
@@ -0,0 +1,56 @@
# -*- coding: utf-8 -*-
"""
***************************************************************************
test_qgis_global_settings.py
---------------------
Date : January 2017
Copyright : (C) 2017, Jorge Gustavo Rocha
Email : jgr at geomaster dot pt
***************************************************************************
* *
* 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__ = 'Jorge Gustavo Rocha'
__date__ = 'August 2017'
__copyright__ = '(C) 2017, Jorge Gustavo Rocha'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'

from qgis.testing import start_app, unittest
from qgis.PyQt.QtCore import qDebug
from qgis.core import QgsApplication, QgsRasterLayer, QgsSettings

start_app()


def createXYZLayerFromURL(url):
typeandurl = "type=xyz&url=" + url
osm = QgsRasterLayer(typeandurl, "OpenStreetMap", "wms")
return osm


class TestQgsGlobalSettings(unittest.TestCase):

def test_global_settings_exist(self):
qDebug('QgsApplication.pkgDataPath(): {0}'.format(QgsApplication.pkgDataPath()))
# Path after deployment
# QgsSettings.setGlobalSettingsPath(QgsApplication.pkgDataPath() + '/qgis_global_settings.ini')
# Path before deployment
QgsSettings.setGlobalSettingsPath(QgsApplication.pkgDataPath() + '/resources/qgis_global_settings.ini')
self.settings = QgsSettings('testqgissettings', 'testqgissettings')
settings = QgsSettings()
# qDebug('settings.allKeys(): {0}'.format(settings.allKeys()))
defaulturl = settings.value('qgis/connections-xyz/OpenStreetMap/url')
self.assertEqual(defaulturl, 'http://a.tile.openstreetmap.org/{z}/{x}/{y}.png')
layer = createXYZLayerFromURL(defaulturl)
self.assertEqual(layer.name(), 'OpenStreetMap')


if __name__ == '__main__':
unittest.main()