Skip to content

Commit

Permalink
Merge pull request #36421 from 3nids/basemap_path
Browse files Browse the repository at this point in the history
Registry for localized data paths
  • Loading branch information
3nids committed May 19, 2020
2 parents 8249dcc + 1befc32 commit cc19fa1
Show file tree
Hide file tree
Showing 14 changed files with 596 additions and 46 deletions.
11 changes: 11 additions & 0 deletions python/core/auto_generated/qgsapplication.sip.in
Expand Up @@ -857,6 +857,17 @@ Gets the registry of available scalebar renderers.
Returns registry of available project storage implementations.

.. versionadded:: 3.2
%End

static QgsLocalizedDataPathRegistry *localizedDataPathRegistry() /KeepReference/;
%Docstring
Returns the registry of data repositories
These are used as paths for basemaps, logos, etc. which can be referenced
differently across work stations.

.. seealso:: :py:class:`QgsLocalizedDataPathRegistry`

.. versionadded:: 3.14
%End

static QString nullRepresentation();
Expand Down
71 changes: 71 additions & 0 deletions python/core/auto_generated/qgslocalizeddatapathregistry.sip.in
@@ -0,0 +1,71 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/qgslocalizeddatapathregistry.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/






class QgsLocalizedDataPathRegistry
{
%Docstring
A registry class to hold localized data paths which can be used for basemaps, logos, etc.
Paths are meant to be absolute paths and are stored by order of preference.

If a layer from one of the paths is loaded, it will be saved as localized in the project file.
For instance, if you have C:\my_maps in your localized paths,
C:\my_maps\my_country\ortho.tif will be save in your project as localized:my_country\ortho.tif

The resolving of the file paths happens in QgsPathResolver.

.. versionadded:: 3.14
%End

%TypeHeaderCode
#include "qgslocalizeddatapathregistry.h"
%End
public:
QgsLocalizedDataPathRegistry();

QString globalPath( const QString &localizedPath ) const;
%Docstring
Returns the global path if the file has been found in one of the paths, an empty string otherwise
%End

QString localizedPath( const QString &globalPath ) const;
%Docstring
Returns the localized path if the file has been found in one of the path, an empty string otherwise
%End

QStringList paths() const;
%Docstring
Returns a list of registered localized paths
%End


void registerPath( const QString &path, int position = -1 );
%Docstring
Registers a localized path
If ``position`` is given, the path is inserted at the given position in the list
Since the paths are stored by order of preference, lower positions in the list take precedence.
%End

void unregisterPath( const QString &path );
%Docstring
Unregisters a localized path
%End

};

/************************************************************************
* This file has been generated automatically from *
* *
* src/core/qgslocalizeddatapathregistry.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
1 change: 1 addition & 0 deletions python/core/core_auto.sip
Expand Up @@ -99,6 +99,7 @@
%Include auto_generated/qgslegendsettings.sip
%Include auto_generated/qgslegendstyle.sip
%Include auto_generated/qgslocaldefaultsettings.sip
%Include auto_generated/qgslocalizeddatapathregistry.sip
%Include auto_generated/qgslogger.sip
%Include auto_generated/qgsmapdecoration.sip
%Include auto_generated/qgsmaphittest.sip
Expand Down
70 changes: 70 additions & 0 deletions src/app/qgsoptions.cpp
Expand Up @@ -40,6 +40,7 @@
#include "qgsnumericformatwidget.h"

#include "qgsattributetablefiltermodel.h"
#include "qgslocalizeddatapathregistry.h"
#include "qgsrasterformatsaveoptionswidget.h"
#include "qgsrasterpyramidsoptionswidget.h"
#include "qgsdatumtransformtablewidget.h"
Expand Down Expand Up @@ -308,6 +309,21 @@ QgsOptions::QgsOptions( QWidget *parent, Qt::WindowFlags fl, const QList<QgsOpti
connect( mBtnAddTemplatePath, &QAbstractButton::clicked, this, &QgsOptions::addTemplatePath );
connect( mBtnRemoveTemplatePath, &QAbstractButton::clicked, this, &QgsOptions::removeTemplatePath );

// localized data paths
connect( mLocalizedDataPathAddButton, &QAbstractButton::clicked, this, &QgsOptions::addLocalizedDataPath );
connect( mLocalizedDataPathRemoveButton, &QAbstractButton::clicked, this, &QgsOptions::removeLocalizedDataPath );
connect( mLocalizedDataPathUpButton, &QAbstractButton::clicked, this, &QgsOptions::moveLocalizedDataPathUp );
connect( mLocalizedDataPathDownButton, &QAbstractButton::clicked, this, &QgsOptions::moveLocalizedDataPathDown );

const QStringList localizedPaths = QgsApplication::localizedDataPathRegistry()->paths();
for ( const QString &path : localizedPaths )
{
QListWidgetItem *newItem = new QListWidgetItem( mLocalizedDataPathListWidget );
newItem->setText( path );
newItem->setFlags( Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable );
mLocalizedDataPathListWidget->addItem( newItem );
}

//paths hidden from browser
const QStringList hiddenPathList = mSettings->value( QStringLiteral( "/browser/hiddenPaths" ) ).toStringList();
for ( const QString &path : hiddenPathList )
Expand Down Expand Up @@ -1409,6 +1425,11 @@ void QgsOptions::saveOptions()
}
mSettings->setValue( QStringLiteral( "Layout/searchPathsForTemplates" ), pathsList, QgsSettings::Core );

pathsList.clear();
for ( int r = 0; r < mLocalizedDataPathListWidget->count(); r++ )
pathsList << mLocalizedDataPathListWidget->item( r )->text();
QgsApplication::localizedDataPathRegistry()->setPaths( pathsList );

pathsList.clear();
for ( int i = 0; i < mListHiddenBrowserPaths->count(); ++i )
{
Expand Down Expand Up @@ -2528,6 +2549,55 @@ void QgsOptions::addColor()
mTreeCustomColors->addColor( newColor, QgsSymbolLayerUtils::colorToName( newColor ) );
}

void QgsOptions::removeLocalizedDataPath()
{
qDeleteAll( mLocalizedDataPathListWidget->selectedItems() );
}

void QgsOptions::addLocalizedDataPath()
{
QString myDir = QFileDialog::getExistingDirectory(
this,
tr( "Choose a Directory" ),
QDir::homePath(),
QFileDialog::ShowDirsOnly
);

if ( ! myDir.isEmpty() )
{
QListWidgetItem *newItem = new QListWidgetItem( mLocalizedDataPathListWidget );
newItem->setText( myDir );
newItem->setFlags( Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable );
mLocalizedDataPathListWidget->addItem( newItem );
mLocalizedDataPathListWidget->setCurrentItem( newItem );
}
}

void QgsOptions::moveLocalizedDataPathUp()
{
QList<QListWidgetItem *> selectedItems = mLocalizedDataPathListWidget->selectedItems();
QList<QListWidgetItem *>::iterator itemIt = selectedItems.begin();
for ( ; itemIt != selectedItems.end(); ++itemIt )
{
int row = mLocalizedDataPathListWidget->row( *itemIt );
mLocalizedDataPathListWidget->takeItem( row );
mLocalizedDataPathListWidget->insertItem( row - 1, *itemIt );
}
}

void QgsOptions::moveLocalizedDataPathDown()
{
QList<QListWidgetItem *> selectedItems = mLocalizedDataPathListWidget->selectedItems();
QList<QListWidgetItem *>::iterator itemIt = selectedItems.begin();
for ( ; itemIt != selectedItems.end(); ++itemIt )
{
int row = mLocalizedDataPathListWidget->row( *itemIt );
mLocalizedDataPathListWidget->takeItem( row );
mLocalizedDataPathListWidget->insertItem( row + 1, *itemIt );
}
}


QListWidgetItem *QgsOptions::addScaleToScaleList( const QString &newScale )
{
QListWidgetItem *newItem = new QListWidgetItem( newScale );
Expand Down
6 changes: 6 additions & 0 deletions src/app/qgsoptions.h
Expand Up @@ -241,6 +241,12 @@ class APP_EXPORT QgsOptions : public QgsOptionsDialogBase, private Ui::QgsOption

void addColor();

private slots:
void removeLocalizedDataPath();
void addLocalizedDataPath();
void moveLocalizedDataPathUp();
void moveLocalizedDataPathDown();

private:
QgsSettings *mSettings = nullptr;
QStringList i18nList();
Expand Down
2 changes: 2 additions & 0 deletions src/core/CMakeLists.txt
Expand Up @@ -306,6 +306,7 @@ SET(QGIS_CORE_SRCS
qgslegendstyle.cpp
qgslocaldefaultsettings.cpp
qgslocalec.cpp
qgslocalizeddatapathregistry.cpp
qgslogger.cpp
qgsmapdecoration.cpp
qgsmaphittest.cpp
Expand Down Expand Up @@ -854,6 +855,7 @@ SET(QGIS_CORE_HDRS
qgslegendstyle.h
qgslocaldefaultsettings.h
qgslocalec.h
qgslocalizeddatapathregistry.h
qgslogger.h
qgsmapdecoration.h
qgsmaphittest.h
Expand Down
8 changes: 8 additions & 0 deletions src/core/qgsapplication.cpp
Expand Up @@ -15,6 +15,7 @@

#include "qgsapplication.h"
#include "qgsauthmanager.h"
#include "qgslocalizeddatapathregistry.h"
#include "qgsdataitemproviderregistry.h"
#include "qgsexception.h"
#include "qgsgeometry.h"
Expand Down Expand Up @@ -2235,10 +2236,16 @@ QgsProjectStorageRegistry *QgsApplication::projectStorageRegistry()
return members()->mProjectStorageRegistry;
}

QgsLocalizedDataPathRegistry *QgsApplication::localizedDataPathRegistry()
{
return members()->mLocalizedDataPathRegistry;
}

QgsApplication::ApplicationMembers::ApplicationMembers()
{
// don't use initializer lists or scoped pointers - as more objects are added here we
// will need to be careful with the order of creation/destruction
mLocalizedDataPathRegistry = new QgsLocalizedDataPathRegistry();
mMessageLog = new QgsMessageLog();
mProfiler = new QgsRuntimeProfiler();

Expand Down Expand Up @@ -2402,6 +2409,7 @@ QgsApplication::ApplicationMembers::~ApplicationMembers()
delete mNumericFormatRegistry;
delete mBookmarkManager;
delete mConnectionRegistry;
delete mLocalizedDataPathRegistry;
}

QgsApplication::ApplicationMembers *QgsApplication::members()
Expand Down
11 changes: 11 additions & 0 deletions src/core/qgsapplication.h
Expand Up @@ -32,6 +32,7 @@ class QgsFieldFormatterRegistry;
class QgsColorSchemeRegistry;
class QgsPaintEffectRegistry;
class QgsProjectStorageRegistry;
class QgsLocalizedDataPathRegistry;
class QgsRendererRegistry;
class QgsSvgCache;
class QgsImageCache;
Expand Down Expand Up @@ -789,6 +790,15 @@ class CORE_EXPORT QgsApplication : public QApplication
*/
static QgsProjectStorageRegistry *projectStorageRegistry() SIP_KEEPREFERENCE;

/**
* Returns the registry of data repositories
* These are used as paths for basemaps, logos, etc. which can be referenced
* differently across work stations.
* \see QgsLocalizedDataPathRegistry
* \since QGIS 3.14
*/
static QgsLocalizedDataPathRegistry *localizedDataPathRegistry() SIP_KEEPREFERENCE;

/**
* This string is used to represent the value `NULL` throughout QGIS.
*
Expand Down Expand Up @@ -913,6 +923,7 @@ class CORE_EXPORT QgsApplication : public QApplication
QgsActionScopeRegistry *mActionScopeRegistry = nullptr;
QgsAnnotationRegistry *mAnnotationRegistry = nullptr;
QgsColorSchemeRegistry *mColorSchemeRegistry = nullptr;
QgsLocalizedDataPathRegistry *mLocalizedDataPathRegistry = nullptr;
QgsNumericFormatRegistry *mNumericFormatRegistry = nullptr;
QgsFieldFormatterRegistry *mFieldFormatterRegistry = nullptr;
QgsGpsConnectionRegistry *mGpsConnectionRegistry = nullptr;
Expand Down
97 changes: 97 additions & 0 deletions src/core/qgslocalizeddatapathregistry.cpp
@@ -0,0 +1,97 @@
/***************************************************************************
qgslocalizeddatapathregistry.cpp
--------------------------------------
Date : May 2020
Copyright : (C) 2020 by Denis Rouzaud
Email : denis.rouzaud
***************************************************************************
* *
* 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 <QDir>

#include "qgslocalizeddatapathregistry.h"
#include "qgssettings.h"
#include "qgis.h"
#include "qgsreadwritelocker.h"


QgsLocalizedDataPathRegistry::QgsLocalizedDataPathRegistry()
{
readFromSettings();
}

QString QgsLocalizedDataPathRegistry::globalPath( const QString &relativePath ) const
{
for ( const QDir &basePath : qgis::as_const( mPaths ) )
if ( basePath.exists( relativePath ) )
return basePath.absoluteFilePath( relativePath );

return QString();
}

QString QgsLocalizedDataPathRegistry::localizedPath( const QString &fullPath ) const
{
for ( const QDir &basePath : qgis::as_const( mPaths ) )
if ( fullPath.startsWith( basePath.absolutePath() ) )
return basePath.relativeFilePath( fullPath );

return QString();

}

QStringList QgsLocalizedDataPathRegistry::paths() const
{
QStringList paths;
for ( const QDir &dir : mPaths )
paths << dir.absolutePath();
return paths;
}

void QgsLocalizedDataPathRegistry::setPaths( const QStringList &paths )
{
mPaths.clear();
for ( const QString &path : paths )
{
QDir dir( path );
if ( !mPaths.contains( dir ) )
mPaths << dir;
}

writeToSettings();
}

void QgsLocalizedDataPathRegistry::registerPath( const QString &path, int position )
{
QDir dir( path );
if ( mPaths.contains( dir ) )
return;

if ( position >= 0 && position < mPaths.count() )
mPaths.insert( position, dir );
else
mPaths.append( dir );

writeToSettings();
}

void QgsLocalizedDataPathRegistry::unregisterPath( const QString &path )
{
mPaths.removeAll( QDir( path ) );
writeToSettings();
}

void QgsLocalizedDataPathRegistry::readFromSettings()
{
setPaths( QgsSettings().value( QStringLiteral( "/qgis/localized_data_paths" ) ).toStringList() );
}

void QgsLocalizedDataPathRegistry::writeToSettings()
{
QgsSettings().setValue( QStringLiteral( "/qgis/localized_data_paths" ), paths() );
}

0 comments on commit cc19fa1

Please sign in to comment.