Skip to content

Commit

Permalink
Add source widget for XYZ layers, allowing users to change properties
Browse files Browse the repository at this point in the history
like the min/max zoom levels and authentication settings for any
XYZ layer in a project on a layer-by-layer basis
  • Loading branch information
nyalldawson committed Dec 25, 2020
1 parent 639f63e commit e32c5cd
Show file tree
Hide file tree
Showing 11 changed files with 417 additions and 0 deletions.
10 changes: 10 additions & 0 deletions python/gui/auto_generated/qgsprovidersourcewidget.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,16 @@ Sets the source ``uri`` to show in the widget.
Returns the source URI as currently defined by the widget.

.. seealso:: :py:func:`setSourceUri`
%End

signals:

void validChanged( bool isValid );
%Docstring
Emitted whenever the validation status of the widget changes.

If ``isValid`` is ``False`` then the widget is not valid, and any dialog using the widget should be prevented from
being accepted.
%End

};
Expand Down
11 changes: 11 additions & 0 deletions src/gui/providers/gdal/qgsgdalfilesourcewidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,16 @@ QgsGdalFileSourceWidget::QgsGdalFileSourceWidget( QWidget *parent )
layout->addWidget( mFileWidget );

setLayout( layout );

connect( mFileWidget, &QgsFileWidget::fileChanged, this, &QgsGdalFileSourceWidget::validate );
}

void QgsGdalFileSourceWidget::setSourceUri( const QString &uri )
{
mSourceParts = QgsProviderRegistry::instance()->decodeUri( QStringLiteral( "gdal" ), uri );

mFileWidget->setFilePath( mSourceParts.value( QStringLiteral( "path" ) ).toString() );
mIsValid = true;
}

QString QgsGdalFileSourceWidget::sourceUri() const
Expand All @@ -53,5 +56,13 @@ QString QgsGdalFileSourceWidget::sourceUri() const
return QgsProviderRegistry::instance()->encodeUri( QStringLiteral( "gdal" ), parts );
}

void QgsGdalFileSourceWidget::validate()
{
const bool valid = !mFileWidget->filePath().isEmpty();
if ( valid != mIsValid )
emit validChanged( valid );
mIsValid = valid;
}


///@endcond
5 changes: 5 additions & 0 deletions src/gui/providers/gdal/qgsgdalfilesourcewidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,15 @@ class QgsGdalFileSourceWidget : public QgsProviderSourceWidget
void setSourceUri( const QString &uri ) override;
QString sourceUri() const override;

private slots:

void validate();

private:
QgsFileWidget *mFileWidget = nullptr;

QVariantMap mSourceParts;
bool mIsValid = false;
};

///@endcond
Expand Down
10 changes: 10 additions & 0 deletions src/gui/qgsprovidersourcewidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,15 @@ class GUI_EXPORT QgsProviderSourceWidget : public QWidget
*/
virtual QString sourceUri() const = 0;

signals:

/**
* Emitted whenever the validation status of the widget changes.
*
* If \a isValid is FALSE then the widget is not valid, and any dialog using the widget should be prevented from
* being accepted.
*/
void validChanged( bool isValid );

};
#endif //QGSPROVIDERSOURCEWIDGET_H
6 changes: 6 additions & 0 deletions src/gui/raster/qgsrasterlayerproperties.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -731,6 +731,12 @@ void QgsRasterLayerProperties::sync()
layout->addWidget( mSourceWidget );
mSourceGroupBox->setLayout( layout );
mSourceGroupBox->show();

connect( mSourceWidget, &QgsProviderSourceWidget::validChanged, this, [ = ]( bool isValid )
{
buttonBox->button( QDialogButtonBox::Apply )->setEnabled( isValid );
buttonBox->button( QDialogButtonBox::Ok )->setEnabled( isValid );
} );
}
}

Expand Down
1 change: 1 addition & 0 deletions src/providers/wms/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ if (WITH_GUI)
qgswmtsdimensions.cpp
qgsxyzconnectiondialog.cpp
qgsxyzsourceselect.cpp
qgsxyzsourcewidget.cpp
)
endif()

Expand Down
42 changes: 42 additions & 0 deletions src/providers/wms/qgswmsprovidergui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
#include "qgsproviderguimetadata.h"
#include "qgswmsdataitemguiproviders.h"
#include "qgswmsdataitems.h"
#include "qgsprovidersourcewidgetprovider.h"
#include "qgsxyzsourcewidget.h"

//! Provider for WMS layers source select
class QgsWmsSourceSelectProvider : public QgsSourceSelectProvider
Expand Down Expand Up @@ -52,6 +54,39 @@ class QgsXyzSourceSelectProvider : public QgsSourceSelectProvider
}
};

class QgsXyzSourceWidgetProvider : public QgsProviderSourceWidgetProvider
{
public:
QgsXyzSourceWidgetProvider() : QgsProviderSourceWidgetProvider() {}
QString providerKey() const override
{
return QStringLiteral( "xyz" );
}
bool canHandleLayer( QgsMapLayer *layer ) const override
{
if ( layer->providerType() != QLatin1String( "wms" ) )
return false;

const QVariantMap parts = QgsProviderRegistry::instance()->decodeUri( QStringLiteral( "wms" ), layer->source() );
if ( parts.value( QStringLiteral( "type" ) ).toString() != QLatin1String( "xyz" ) )
return false;

return true;
}
QgsProviderSourceWidget *createWidget( QgsMapLayer *layer, QWidget *parent = nullptr ) override
{
if ( layer->providerType() != QLatin1String( "wms" ) )
return nullptr;

const QVariantMap parts = QgsProviderRegistry::instance()->decodeUri( QStringLiteral( "wms" ), layer->source() );
if ( parts.value( QStringLiteral( "type" ) ).toString() != QLatin1String( "xyz" ) )
return nullptr;

return new QgsXyzSourceWidget( parent );
}
};


QgsWmsProviderGuiMetadata::QgsWmsProviderGuiMetadata()
: QgsProviderGuiMetadata( QgsWmsProvider::WMS_KEY )
{
Expand All @@ -71,6 +106,13 @@ QList<QgsDataItemGuiProvider *> QgsWmsProviderGuiMetadata::dataItemGuiProviders(
<< new QgsXyzDataItemGuiProvider;
}

QList<QgsProviderSourceWidgetProvider *> QgsWmsProviderGuiMetadata::sourceWidgetProviders()
{
QList<QgsProviderSourceWidgetProvider *> providers;
providers << new QgsXyzSourceWidgetProvider();
return providers;
}

void QgsWmsProviderGuiMetadata::registerGui( QMainWindow *widget )
{
QgsTileScaleWidget::showTileScale( widget );
Expand Down
1 change: 1 addition & 0 deletions src/providers/wms/qgswmsprovidergui.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class QgsWmsProviderGuiMetadata: public QgsProviderGuiMetadata
QList<QgsSourceSelectProvider *> sourceSelectProviders() override;

QList<QgsDataItemGuiProvider *> dataItemGuiProviders() override;
QList<QgsProviderSourceWidgetProvider *> sourceWidgetProviders() override;

void registerGui( QMainWindow *widget ) override;
};
Expand Down
108 changes: 108 additions & 0 deletions src/providers/wms/qgsxyzsourcewidget.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/***************************************************************************
qgsxyzsourcewidget.cpp
--------------------------------------
Date : December 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 "qgsxyzsourcewidget.h"

#include "qgsproviderregistry.h"


QgsXyzSourceWidget::QgsXyzSourceWidget( QWidget *parent )
: QgsProviderSourceWidget( parent )
{
setupUi( this );

// Behavior for min and max zoom checkbox
connect( mCheckBoxZMin, &QCheckBox::toggled, mSpinZMin, &QSpinBox::setEnabled );
connect( mCheckBoxZMax, &QCheckBox::toggled, mSpinZMax, &QSpinBox::setEnabled );
mSpinZMax->setClearValue( 18 );

connect( mEditUrl, &QLineEdit::textChanged, this, &QgsXyzSourceWidget::validate );
}

void QgsXyzSourceWidget::setSourceUri( const QString &uri )
{
mSourceParts = QgsProviderRegistry::instance()->decodeUri( QStringLiteral( "wms" ), uri );

mEditUrl->setText( mSourceParts.value( QStringLiteral( "url" ) ).toString() );
mCheckBoxZMin->setChecked( mSourceParts.value( QStringLiteral( "zmin" ) ).isValid() );
mSpinZMin->setValue( mCheckBoxZMin->isChecked() ? mSourceParts.value( QStringLiteral( "zmin" ) ).toInt() : 0 );
mCheckBoxZMax->setChecked( mSourceParts.value( QStringLiteral( "zmax" ) ).isValid() );
mSpinZMax->setValue( mCheckBoxZMax->isChecked() ? mSourceParts.value( QStringLiteral( "zmax" ) ).toInt() : 18 );
mAuthSettings->setUsername( mSourceParts.value( QStringLiteral( "username" ) ).toString() );
mAuthSettings->setPassword( mSourceParts.value( QStringLiteral( "password" ) ).toString() );
mEditReferer->setText( mSourceParts.value( QStringLiteral( "referer" ) ).toString() );

int index = 0; // default is "unknown"
if ( mSourceParts.value( QStringLiteral( "tilePixelRatio" ) ).toInt() == 2. )
index = 2; // high-res
else if ( mSourceParts.value( QStringLiteral( "tilePixelRatio" ) ).toInt() == 1. )
index = 1; // normal-res
mComboTileResolution->setCurrentIndex( index );

mAuthSettings->setConfigId( mSourceParts.value( QStringLiteral( "authcfg" ) ).toString() );

mIsValid = true;
}

QString QgsXyzSourceWidget::sourceUri() const
{
QVariantMap parts = mSourceParts;

parts.insert( QStringLiteral( "url" ), mEditUrl->text() );
if ( mCheckBoxZMin->isChecked() )
parts.insert( QStringLiteral( "zmin" ), mSpinZMin->value() );
else
parts.remove( QStringLiteral( "zmin" ) );
if ( mCheckBoxZMax->isChecked() )
parts.insert( QStringLiteral( "zmax" ), mSpinZMax->value() );
else
parts.remove( QStringLiteral( "zmax" ) );

if ( !mAuthSettings->username().isEmpty() )
parts.insert( QStringLiteral( "username" ), mAuthSettings->username() );
else
parts.remove( QStringLiteral( "username" ) );
if ( !mAuthSettings->password().isEmpty() )
parts.insert( QStringLiteral( "password" ), mAuthSettings->password() );
else
parts.remove( QStringLiteral( "password" ) );

if ( !mEditReferer->text().isEmpty() )
parts.insert( QStringLiteral( "referer" ), mEditReferer->text() );
else
parts.remove( QStringLiteral( "referer" ) );

if ( mComboTileResolution->currentIndex() > 0 )
parts.insert( QStringLiteral( "tilePixelRatio" ), mComboTileResolution->currentIndex() );
else
parts.remove( QStringLiteral( "tilePixelRatio" ) );

if ( !mAuthSettings->configId().isEmpty() )
parts.insert( QStringLiteral( "authcfg" ), mAuthSettings->configId() );
else
parts.remove( QStringLiteral( "authcfg" ) );

return QgsProviderRegistry::instance()->encodeUri( QStringLiteral( "wms" ), parts );
}

void QgsXyzSourceWidget::validate()
{
const bool valid = !mEditUrl->text().isEmpty();
if ( valid != mIsValid )
emit validChanged( valid );
mIsValid = valid;
}
44 changes: 44 additions & 0 deletions src/providers/wms/qgsxyzsourcewidget.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/***************************************************************************
qgsxyzsourcewidget.h
--------------------------------------
Date : December 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 QGGXYZSOURCEWIDGET_H
#define QGGXYZSOURCEWIDGET_H

#include "qgsprovidersourcewidget.h"
#include "ui_qgsxyzsourcewidgetbase.h"
#include <QVariantMap>

class QgsXyzSourceWidget : public QgsProviderSourceWidget, private Ui::QgsXyzSourceWidgetBase
{
Q_OBJECT

public:
QgsXyzSourceWidget( QWidget *parent = nullptr );

void setSourceUri( const QString &uri ) override;
QString sourceUri() const override;

private slots:

void validate();

private:

QVariantMap mSourceParts;
bool mIsValid = false;
};

#endif // QGGXYZSOURCEWIDGET_H
Loading

0 comments on commit e32c5cd

Please sign in to comment.