Skip to content
Permalink
Browse files

Merge pull request #39527 from signedav/offlineindicator

Indicator for offline layers
  • Loading branch information
signedav committed Nov 11, 2020
2 parents 928997d + ef0bd56 commit f360838fbd2515b94af6dcb9e3868918f7a4b7e9
@@ -858,6 +858,7 @@
<file>themes/default/mIconModelInput.svg</file>
<file>themes/default/mIndicatorTemporal.svg</file>
<file>themes/default/mIndicatorTimeFromProject.svg</file>
<file>themes/default/mIndicatorOffline.svg</file>
<file>themes/default/temporal_navigation/back.svg</file>
<file>themes/default/temporal_navigation/forward.svg</file>
<file>themes/default/temporal_navigation/next.svg</file>
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16" xmlns:v="https://vecta.io/nano"><path d="M2.207 1.203l-.707.705.484.486h.002l.693.7c-.255.317-.523.63-.682 1-.45 1.048-.4 2.174.314 2.88l.002.002L4.373 9l.703-.002 4.23-4.23-.002-.707-2.06-2.03c-.35-.348-.815-.548-1.313-.598s-1.027.044-1.553.27c-.37.158-.68.427-.996.682l-.693-.7V1.7zm3.63 1.22a1.12 1.12 0 0 1 .707.314l.004.002 1.7 1.678-3.525 3.527-1.707-1.686c-.342-.343-.44-1-.102-1.78a3.75 3.75 0 0 1 1.861-1.861c.393-.17.76-.225 1.06-.195zm3.317 3.564l-.705.705.354.352.707.707.338.34L8.43 9.506l-.338-.34-.707-.707-.354-.352-.705.705.354.352.707.707.338.34-.727.727.002.707 2.058 2.026c.35.35.816.552 1.314.602s1.027-.046 1.553-.27c.37-.158.68-.425.996-.68l.695.7v.002l.484.484.705-.703-.484-.486-.695-.695c.254-.317.523-.627.682-.996.45-1.048.4-2.174-.314-2.88l-.002-.004-2.06-2.033-.703.004-.678.678-.338-.34-.707-.707zm2.432 1.775l1.705 1.686c.34.344.44 1 .102 1.777a3.75 3.75 0 0 1-1.859 1.863c-.393.17-.76.223-1.06.193s-.534-.138-.7-.312l-.002-.004-1.7-1.68z" fill-opacity=".706" fill="#2c2c2c" fill-rule="evenodd"/><path d="M2.7 1.7v.002l.283.28zm3.145.732c-.3-.03-.667.026-1.06.195a3.75 3.75 0 0 0-1.861 1.861c-.338.788-.24 1.436.102 1.78l.283.28c-.34-.344-.437-1-.1-1.775S4.27 3.24 5.058 2.9c.393-.17.76-.225 1.06-.195s.534.14.7.314h.002l1.416 1.396.002-.002-1.704-1.68a1.12 1.12 0 0 0-.707-.314zm3.47 1.643l.002.703-4.23 4.23L4.373 9l.285.283.703-.002 4.23-4.23-.004-.707zM8.697 6.94l-.002.002.354.352.707.707.1.092.002-.002-.338-.34-.707-.707zm2.9.822L8.06 11.285l.25.246 3.52-3.52 1.473 1.455c-.005-.006-.008-.014-.014-.02zm2.432 1.006c.68.707.736 1.817.3 2.852-.158.37-.427.68-.682.996l.248.248c.254-.316.522-.626.68-.994.45-1.048.4-2.174-.314-2.88v-.004zm-7.44.293l-.002.002.354.352.707.707.1.092.002-.002-.338-.34-.707-.707zm.672 2.826v.008L9.31 13.92c.35.35.816.552 1.314.602s1.027-.046 1.553-.27c.37-.158.68-.425.996-.68l.695.7-.246-.248v-.002l-.695-.7c-.316.254-.627.52-.996.68-.525.226-1.056.32-1.553.27s-.965-.252-1.314-.602l.002.004zm6.615 2.377l.484.486.705-.703-.248-.248-.703.7z" fill-opacity=".424" fill-rule="evenodd" fill="gray"/></svg>
@@ -1598,6 +1598,12 @@ Emitted when the validity of this layer changed.
.. versionadded:: 3.16
%End

void customPropertyChanged( const QString &key );
%Docstring
Emitted when a custom property of the layer has been changed or removed.

.. versionadded:: 3.18
%End

protected:

@@ -52,6 +52,7 @@ SET(QGIS_APP_SRCS
qgslayertreeviewnonremovableindicator.cpp
qgslayertreeviewbadlayerindicator.cpp
qgslayertreeviewtemporalindicator.cpp
qgslayertreeviewofflineindicator.cpp
qgsmapcanvasdockwidget.cpp
qgsmapsavedialog.cpp
qgsprojectlistitemdelegate.cpp
@@ -249,6 +249,7 @@ Q_GUI_EXPORT extern int qt_defaultDpiX();
#include "qgslayertreeviewnonremovableindicator.h"
#include "qgslayertreeviewnocrsindicator.h"
#include "qgslayertreeviewtemporalindicator.h"
#include "qgslayertreeviewofflineindicator.h"
#include "qgslayout.h"
#include "qgslayoutatlas.h"
#include "qgslayoutcustomdrophandler.h"
@@ -4750,6 +4751,7 @@ void QgisApp::initLayerTreeView()
new QgsLayerTreeViewMemoryIndicatorProvider( mLayerTreeView ); // gets parented to the layer view
new QgsLayerTreeViewTemporalIndicatorProvider( mLayerTreeView ); // gets parented to the layer view
new QgsLayerTreeViewNoCrsIndicatorProvider( mLayerTreeView ); // gets parented to the layer view
new QgsLayerTreeViewOfflineIndicatorProvider( mLayerTreeView ); // gets parented to the layer view
QgsLayerTreeViewBadLayerIndicatorProvider *badLayerIndicatorProvider = new QgsLayerTreeViewBadLayerIndicatorProvider( mLayerTreeView ); // gets parented to the layer view
connect( badLayerIndicatorProvider, &QgsLayerTreeViewBadLayerIndicatorProvider::requestChangeDataSource, this, &QgisApp::changeDataSource );
new QgsLayerTreeViewNonRemovableIndicatorProvider( mLayerTreeView ); // gets parented to the layer view
@@ -0,0 +1,68 @@
/***************************************************************************
qgslayertreeviewofflineindicator.cpp
--------------------------------------
Date : October 2020
Copyright : (C) 2020 by David Signer
Email : david at opengis dot ch
***************************************************************************
* *
* 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 "qgslayertreeviewofflineindicator.h"
#include "qgslayertreeview.h"
#include "qgslayertree.h"
#include "qgslayertreemodel.h"
#include "qgisapp.h"

QgsLayerTreeViewOfflineIndicatorProvider::QgsLayerTreeViewOfflineIndicatorProvider( QgsLayerTreeView *view )
: QgsLayerTreeViewIndicatorProvider( view )
{

}

void QgsLayerTreeViewOfflineIndicatorProvider::connectSignals( QgsMapLayer *layer )
{
if ( !layer )
return;

connect( layer, &QgsMapLayer::customPropertyChanged, this, &QgsLayerTreeViewOfflineIndicatorProvider::onLayerChanged );
}

void QgsLayerTreeViewOfflineIndicatorProvider::disconnectSignals( QgsMapLayer *layer )
{
if ( !layer )
return;

disconnect( layer, &QgsMapLayer::customPropertyChanged, this, &QgsLayerTreeViewOfflineIndicatorProvider::onLayerChanged );
}

bool QgsLayerTreeViewOfflineIndicatorProvider::acceptLayer( QgsMapLayer *layer )
{
return layer->customProperty( QStringLiteral( "isOfflineEditable" ), false ).toBool();
}

QString QgsLayerTreeViewOfflineIndicatorProvider::iconName( QgsMapLayer *layer )
{
Q_UNUSED( layer )
return QStringLiteral( "/mIndicatorOffline.svg" );
}

QString QgsLayerTreeViewOfflineIndicatorProvider::tooltipText( QgsMapLayer *layer )
{
Q_UNUSED( layer )
return tr( "<b>Offline layer</b>" );
}

void QgsLayerTreeViewOfflineIndicatorProvider::onLayerChanged()
{
QgsMapLayer *layer = qobject_cast<QgsMapLayer *>( sender() );
if ( !layer )
return;

updateLayerIndicator( layer );
}
@@ -0,0 +1,47 @@
/***************************************************************************
qgslayertreeviewofflineindicator.h
--------------------------------------
Date : October 2020
Copyright : (C) 2020 by David Signer
Email : david at opengis dot ch
***************************************************************************
* *
* 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 QGSLAYERTREEVIEWOFFLINEINDICATOR_H
#define QGSLAYERTREEVIEWOFFLINEINDICATOR_H

#include "qgslayertreeviewindicatorprovider.h"

#include <QSet>
#include <memory>

class QgsLayerTreeNode;
class QgsLayerTreeView;

//! Adds indicators showing whether layers are offline.
class QgsLayerTreeViewOfflineIndicatorProvider : public QgsLayerTreeViewIndicatorProvider
{
Q_OBJECT
public:
explicit QgsLayerTreeViewOfflineIndicatorProvider( QgsLayerTreeView *view );

protected:
void connectSignals( QgsMapLayer *layer ) override;
void disconnectSignals( QgsMapLayer *layer ) override;

protected slots:
void onLayerChanged();

private:
bool acceptLayer( QgsMapLayer *layer ) override;
QString iconName( QgsMapLayer *layer ) override;
QString tooltipText( QgsMapLayer *layer ) override;
};

#endif // QGSLAYERTREEVIEWOFFLINEINDICATOR_H
@@ -1707,7 +1707,11 @@ QStringList QgsMapLayer::customPropertyKeys() const

void QgsMapLayer::setCustomProperty( const QString &key, const QVariant &value )
{
mCustomProperties.setValue( key, value );
if ( !mCustomProperties.contains( key ) || mCustomProperties.value( key ) != value )
{
mCustomProperties.setValue( key, value );
emit customPropertyChanged( key );
}
}

void QgsMapLayer::setCustomProperties( const QgsObjectCustomProperties &properties )
@@ -1727,7 +1731,12 @@ QVariant QgsMapLayer::customProperty( const QString &value, const QVariant &defa

void QgsMapLayer::removeCustomProperty( const QString &key )
{
mCustomProperties.remove( key );

if ( mCustomProperties.contains( key ) )
{
mCustomProperties.remove( key );
emit customPropertyChanged( key );
}
}

QgsError QgsMapLayer::error() const
@@ -1429,6 +1429,12 @@ class CORE_EXPORT QgsMapLayer : public QObject
*/
void isValidChanged();

/**
* Emitted when a custom property of the layer has been changed or removed.
*
* \since QGIS 3.18
*/
void customPropertyChanged( const QString &key );

private slots:

@@ -399,6 +399,46 @@ def testSetDataSourceInvalidToValid(self):
# should STILL have kept renderer!
self.assertEqual(layer.renderer(), r)

def testSetCustomProperty(self):
"""
Test setting a custom property of the layer
"""
layer = createLayerWithOnePoint()
layer.setCustomProperty('Key_0', 'Value_0')
layer.setCustomProperty('Key_1', 'Value_1')

spy = QSignalSpy(layer.customPropertyChanged)

# change nothing by setting the same value
layer.setCustomProperty('Key_0', 'Value_0')
layer.setCustomProperty('Key_1', 'Value_1')
self.assertEqual(len(spy), 0)

# change one
layer.setCustomProperty('Key_0', 'Value zero')
self.assertEqual(len(spy), 1)

# add one
layer.setCustomProperty('Key_2', 'Value two')
self.assertEqual(len(spy), 2)

# add a null one and an empty one
layer.setCustomProperty('Key_3', None)
layer.setCustomProperty('Key_4', '')
self.assertEqual(len(spy), 4)

# remove one
layer.removeCustomProperty('Key_0')
self.assertEqual(len(spy), 5)

self.assertEqual(layer.customProperty('Key_0', 'no value'), 'no value')
self.assertEqual(layer.customProperty('Key_1', 'no value'), 'Value_1')
self.assertEqual(layer.customProperty('Key_2', 'no value'), 'Value two')
self.assertEqual(layer.customProperty('Key_3', 'no value'), None)
self.assertEqual(layer.customProperty('Key_4', 'no value'), '')

self.assertEqual(len(spy), 5)

def testStoreWkbTypeInvalidLayers(self):
"""
Test that layer wkb types are restored for projects with invalid layer paths

0 comments on commit f360838

Please sign in to comment.
You can’t perform that action at this time.