create QgsMapLayer::LayerFlags for Searchable, Identifiable and Removable (#7815)

* create QgsMapLayer::LayerFlags for Searchable, Identifiable and Removable

this brings back the information previously saved in the project node back to the layer node
this will allow to embed this information in layer styles

* skip unexisting flag node to avoid setting wrong value for flag

* mark QgsProject::(set)requiredLayers as deprecated

* better API docs

* use new API in current code

* more docs and more old API fixes

* fix bad conversion

* more old API fix

* add missing SIP_OUT

* s/testFlags/testFlag

* fix var name

* adapt project test to test flags

* remove debug calls

* fixeS
This commit is contained in:
Denis Rouzaud 2018-09-08 07:54:21 -04:00 committed by GitHub
parent 48dcab75cb
commit 89830f614e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 311 additions and 216 deletions

View File

@ -0,0 +1,4 @@
# The following has been generated automatically from src/core/qgsmaplayer.h
QgsMapLayer.LayerFlag.baseClass = QgsMapLayer
QgsMapLayer.LayerFlags.baseClass = QgsMapLayer
LayerFlags = QgsMapLayer # dirty hack since SIP seems to introduce the flags in module

View File

@ -66,6 +66,15 @@ This is the base class for all map layer types (vector, raster).
Metadata,
};
enum LayerFlag
{
Identifiable,
Removable,
Searchable,
};
typedef QFlags<QgsMapLayer::LayerFlag> LayerFlags;
QgsMapLayer( QgsMapLayer::LayerType type = VectorLayer, const QString &name = QString(), const QString &source = QString() );
%Docstring
Constructor for QgsMapLayer
@ -91,6 +100,32 @@ is still unique.
QgsMapLayer::LayerType type() const;
%Docstring
Returns the type of the layer.
%End
QgsMapLayer::LayerFlags flags() const;
%Docstring
Returns the flags for this layer.
.. note::
Flags are options specified by the user used for the UI but are not preventing any API call.
For instance, even if the Removable flag is not set, the layer can still be removed with the API
but the action will not be listed in the legend menu.
.. versionadded:: 3.4
%End
void setFlags( QgsMapLayer::LayerFlags flags );
%Docstring
Returns the flags for this layer.
.. note::
Flags are options specified by the user used for the UI but are not preventing any API call.
For instance, even if the Removable flag is not set, the layer can still be removed with the API
but the action will not be listed in the legend menu.
.. versionadded:: 3.4
%End
static QString extensionPropertyType( PropertyType type );
@ -1473,6 +1508,8 @@ Checks whether a new set of dependencies will introduce a cycle
};
QFlags<QgsMapLayer::LayerFlag> operator|(QgsMapLayer::LayerFlag f1, QFlags<QgsMapLayer::LayerFlag> f2);
/************************************************************************

View File

@ -573,19 +573,25 @@ Returns pointer to the project's annotation manager.
%End
void setNonIdentifiableLayers( const QList<QgsMapLayer *> &layers );
void setNonIdentifiableLayers( const QList<QgsMapLayer *> &layers );
%Docstring
Set a list of layers which should not be taken into account on map identification
.. deprecated:: since QGIS 3.4 use QgsMapLayer.setFlags() instead
%End
void setNonIdentifiableLayers( const QStringList &layerIds );
void setNonIdentifiableLayers( const QStringList &layerIds );
%Docstring
Set a list of layers which should not be taken into account on map identification
.. deprecated:: since QGIS 3.4 use QgsMapLayer.setFlags() instead
%End
QStringList nonIdentifiableLayers() const;
QStringList nonIdentifiableLayers() const;
%Docstring
Gets the list of layers which currently should not be taken into account on map identification
.. deprecated:: since QGIS 3.4 use QgsMapLayer.setFlags() instead
%End
bool autoTransaction() const;
@ -973,23 +979,27 @@ Sets the project's ``metadata`` store.
.. versionadded:: 3.2
%End
QSet<QgsMapLayer *> requiredLayers() const;
QSet<QgsMapLayer *> requiredLayers() const;
%Docstring
Returns a set of map layers that are required in the project and therefore they should not get
removed from the project. The set of layers may be configured by users in project properties.
and it is mainly a hint for the user interface to protect users from removing layers that important
in the project. The removeMapLayer(), removeMapLayers() calls do not block removal of layers listed here.
.. deprecated:: since QGIS 3.4 use QgsMapLayer.flags() instead
.. versionadded:: 3.2
%End
void setRequiredLayers( const QSet<QgsMapLayer *> &layers );
void setRequiredLayers( const QSet<QgsMapLayer *> &layers );
%Docstring
Configures a set of map layers that are required in the project and therefore they should not get
removed from the project. The set of layers may be configured by users in project properties.
and it is mainly a hint for the user interface to protect users from removing layers that important
in the project. The removeMapLayer(), removeMapLayers() calls do not block removal of layers listed here.
.. deprecated:: since QGIS 3.4 use QgsMapLayer.setFlags() instead
.. versionadded:: 3.2
%End
@ -1095,9 +1105,11 @@ Emitted when loading layers has produced some messages
.. versionadded:: 3.2
%End
void nonIdentifiableLayersChanged( QStringList nonIdentifiableLayers );
void nonIdentifiableLayersChanged( QStringList nonIdentifiableLayers );
%Docstring
Emitted when the list of layer which are excluded from map identification changes
.. deprecated:: since QGIS 3.4
%End
void fileNameChanged();

View File

@ -1496,18 +1496,6 @@ If you need only the count of committed features call this method on this layer'
Make layer read-only (editing disabled) or not
:return: false if the layer is in editing yet
%End
bool searchable() const;
%Docstring
Returns true if the provider is in read-only mode
%End
void setSearchable( bool searchable );
%Docstring
Make layer searchable or not
.. versionadded:: 3.4
%End
bool changeGeometry( QgsFeatureId fid, QgsGeometry &geometry, bool skipDefaultValue = false );
@ -2592,13 +2580,6 @@ Emitted when the read only state of this layer is changed.
Only applies to manually set readonly state, not to the edit mode.
.. versionadded:: 3.0
%End
void searchableChanged();
%Docstring
Emitted when the search state of this layer is changed.
.. versionadded:: 3.4
%End
void symbolFeatureCountMapChanged();

View File

@ -9569,10 +9569,9 @@ void QgisApp::removeLayer()
// extra check for required layers
// In theory it should not be needed because the remove action should be disabled
// if there are required layers in the selection...
const QSet<QgsMapLayer *> requiredLayers = QgsProject::instance()->requiredLayers();
for ( QgsMapLayer *layer : selectedLayers )
{
if ( requiredLayers.contains( layer ) )
if ( !layer->flags().testFlag( QgsMapLayer::Removable ) )
return;
}
@ -12052,10 +12051,9 @@ void QgisApp::legendLayerSelectionChanged()
// remove action - check for required layers
bool removeEnabled = true;
const QSet<QgsMapLayer *> requiredLayers = QgsProject::instance()->requiredLayers();
for ( QgsLayerTreeLayer *nodeLayer : selectedLayers )
{
if ( requiredLayers.contains( nodeLayer->layer() ) )
if ( !nodeLayer->layer()->flags().testFlag( QgsMapLayer::Removable ) )
{
removeEnabled = false;
break;

View File

@ -720,10 +720,9 @@ void QgsAppLayerTreeViewMenuProvider::setSymbolLegendNodeColor( const QColor &co
bool QgsAppLayerTreeViewMenuProvider::removeActionEnabled()
{
const QList<QgsLayerTreeLayer *> selectedLayers = mView->selectedLayerNodes();
const QSet<QgsMapLayer *> requiredLayers = QgsProject::instance()->requiredLayers();
for ( QgsLayerTreeLayer *nodeLayer : selectedLayers )
{
if ( requiredLayers.contains( nodeLayer->layer() ) )
if ( !nodeLayer->layer()->flags().testFlag( QgsMapLayer::Removable ) )
return false;
}
return true;

View File

@ -24,15 +24,13 @@
QgsLayerCapabilitiesModel::QgsLayerCapabilitiesModel( QgsProject *project, QObject *parent )
: QSortFilterProxyModel( parent )
{
mNonIdentifiableLayers = project->nonIdentifiableLayers();
mRequiredLayers = project->requiredLayers();
const QMap<QString, QgsMapLayer *> &mapLayers = QgsProject::instance()->mapLayers();
const QMap<QString, QgsMapLayer *> &mapLayers = project->mapLayers();
for ( QMap<QString, QgsMapLayer *>::const_iterator it = mapLayers.constBegin(); it != mapLayers.constEnd(); ++it )
{
mReadOnlyLayers.insert( it.value(), it.value()->readOnly() );
QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( it.value() );
mSearchableLayers.insert( it.value(), vl && vl->searchable() );
mSearchableLayers.insert( it.value(), it.value()->type() == QgsMapLayer::VectorLayer && it.value()->flags().testFlag( QgsMapLayer::Searchable ) );
mIdentifiableLayers.insert( it.value(), it.value()->flags().testFlag( QgsMapLayer::Identifiable ) );
mRemovableLayers.insert( it.value(), it.value()->flags().testFlag( QgsMapLayer::Removable ) );
}
}
@ -67,14 +65,14 @@ void QgsLayerCapabilitiesModel::toggleSelectedItems( const QModelIndexList &chec
}
}
QStringList QgsLayerCapabilitiesModel::nonIdentifiableLayers() const
bool QgsLayerCapabilitiesModel::identifiable( QgsMapLayer *layer ) const
{
return mNonIdentifiableLayers;
return mIdentifiableLayers.value( layer, true );
}
QSet<QgsMapLayer *> QgsLayerCapabilitiesModel::requiredLayers() const
bool QgsLayerCapabilitiesModel::removable( QgsMapLayer *layer ) const
{
return mRequiredLayers;
return mRemovableLayers.value( layer, true );
}
bool QgsLayerCapabilitiesModel::readOnly( QgsMapLayer *layer ) const
@ -258,7 +256,7 @@ QVariant QgsLayerCapabilitiesModel::data( const QModelIndex &idx, int role ) con
if ( idx.column() == IdentifiableColumn )
{
if ( layer->isSpatial() )
return !mNonIdentifiableLayers.contains( layer->id() ) ? trueValue : falseValue;
return mIdentifiableLayers.value( layer, true ) ? trueValue : falseValue;
}
else if ( idx.column() == ReadOnlyColumn )
{
@ -272,7 +270,7 @@ QVariant QgsLayerCapabilitiesModel::data( const QModelIndex &idx, int role ) con
}
else if ( idx.column() == RequiredColumn )
{
return mRequiredLayers.contains( layer ) ? trueValue : falseValue;
return !mRemovableLayers.value( layer, true ) ? trueValue : falseValue;
}
}
}
@ -291,44 +289,50 @@ bool QgsLayerCapabilitiesModel::setData( const QModelIndex &index, const QVarian
{
if ( layer->isSpatial() )
{
bool nonIdentifiable = value == Qt::Unchecked;
bool containsLayer = mNonIdentifiableLayers.contains( layer->id() );
if ( containsLayer && !nonIdentifiable )
mNonIdentifiableLayers.removeAll( layer->id() );
if ( !containsLayer && nonIdentifiable )
mNonIdentifiableLayers.append( layer->id() );
emit dataChanged( index, index );
return true;
bool identifiable = value == Qt::Checked;
if ( identifiable != mIdentifiableLayers.value( layer, true ) )
{
mIdentifiableLayers.insert( layer, identifiable );
emit dataChanged( index, index );
return true;
}
}
}
else if ( index.column() == ReadOnlyColumn )
{
if ( layer->type() == QgsMapLayer::VectorLayer )
{
mReadOnlyLayers.insert( layer, value == Qt::Checked );
emit dataChanged( index, index );
return true;
bool readOnly = value == Qt::Checked;
if ( readOnly != mReadOnlyLayers.value( layer, true ) )
{
mReadOnlyLayers.insert( layer, readOnly );
emit dataChanged( index, index );
return true;
}
}
}
else if ( index.column() == SearchableColumn )
{
if ( layer->type() == QgsMapLayer::VectorLayer )
{
mSearchableLayers.insert( layer, value == Qt::Checked );
emit dataChanged( index, index );
return true;
bool searchable = value == Qt::Checked;
if ( searchable != mSearchableLayers.value( layer, true ) )
{
mSearchableLayers.insert( layer, searchable );
emit dataChanged( index, index );
return true;
}
}
}
else if ( index.column() == RequiredColumn )
{
bool required = value == Qt::Checked;
bool containsLayer = mRequiredLayers.contains( layer );
if ( containsLayer && !required )
mRequiredLayers.remove( layer );
if ( !containsLayer && required )
mRequiredLayers.insert( layer );
emit dataChanged( index, index );
return true;
bool removable = value == Qt::Unchecked;
if ( removable != mRemovableLayers.value( layer, true ) )
{
mRemovableLayers.insert( layer, removable );
emit dataChanged( index, index );
return true;
}
}
}
}

View File

@ -43,8 +43,8 @@ class APP_EXPORT QgsLayerCapabilitiesModel : public QSortFilterProxyModel
QgsLayerTreeModel *layerTreeModel() const;
void setLayerTreeModel( QgsLayerTreeModel *layerTreeModel );
QStringList nonIdentifiableLayers() const;
QSet<QgsMapLayer *> requiredLayers() const;
bool identifiable( QgsMapLayer *layer ) const;
bool removable( QgsMapLayer *layer ) const;
bool readOnly( QgsMapLayer *layer ) const;
bool searchable( QgsMapLayer *layer ) const;
QgsMapLayer *mapLayer( const QModelIndex &idx ) const;
@ -71,10 +71,12 @@ class APP_EXPORT QgsLayerCapabilitiesModel : public QSortFilterProxyModel
QString mFilterText;
bool mShowSpatialLayersOnly = false;
QStringList mNonIdentifiableLayers;
QSet<QgsMapLayer *> mRequiredLayers;
QHash<QgsMapLayer *, bool> mReadOnlyLayers;
QHash<QgsMapLayer *, bool> mSearchableLayers;
QHash<QgsMapLayer *, bool> mIdentifiableLayers;
QHash<QgsMapLayer *, bool> mRemovableLayers;
QgsLayerTreeModel *mLayerTreeModel = nullptr;
};

View File

@ -1036,17 +1036,34 @@ void QgsProjectProperties::apply()
emit scalesChanged();
}
QgsProject::instance()->setNonIdentifiableLayers( mLayerCapabilitiesModel->nonIdentifiableLayers() );
QgsProject::instance()->setRequiredLayers( mLayerCapabilitiesModel->requiredLayers() );
const QMap<QString, QgsMapLayer *> &mapLayers = QgsProject::instance()->mapLayers();
for ( QMap<QString, QgsMapLayer *>::const_iterator it = mapLayers.constBegin(); it != mapLayers.constEnd(); ++it )
{
QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( it.value() );
QgsMapLayer *layer = it.value();
QgsMapLayer::LayerFlags flags = layer->flags();
if ( mLayerCapabilitiesModel->identifiable( layer ) )
flags |= QgsMapLayer::Identifiable;
else
flags &= ~QgsMapLayer::Identifiable;
if ( mLayerCapabilitiesModel->removable( layer ) )
flags |= QgsMapLayer::Removable;
else
flags &= ~QgsMapLayer::Removable;
if ( mLayerCapabilitiesModel->searchable( layer ) )
flags |= QgsMapLayer::Searchable;
else
flags &= ~QgsMapLayer::Searchable;
layer->setFlags( flags );
QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layer );
if ( vl )
{
// read only and searchable are for vector layers only for now
// read only is for vector layers only for now
vl->setReadOnly( mLayerCapabilitiesModel->readOnly( vl ) );
vl->setSearchable( mLayerCapabilitiesModel->searchable( vl ) );
}
}

View File

@ -144,6 +144,16 @@ QgsMapLayer::LayerType QgsMapLayer::type() const
return mLayerType;
}
QgsMapLayer::LayerFlags QgsMapLayer::flags() const
{
return mFlags;
}
void QgsMapLayer::setFlags( QgsMapLayer::LayerFlags flags )
{
mFlags = flags;
}
QString QgsMapLayer::id() const
{
return mID;
@ -389,6 +399,23 @@ bool QgsMapLayer::readLayerXml( const QDomElement &layerElement, QgsReadWriteCo
QDomElement metadataElem = layerElement.firstChildElement( QStringLiteral( "resourceMetadata" ) );
mMetadata.readMetadataXml( metadataElem );
// flags
QDomElement flagsElem = layerElement.firstChildElement( QStringLiteral( "flags" ) );
QMetaEnum metaEnum = QMetaEnum::fromType<QgsMapLayer::LayerFlag>();
for ( int idx = 0; idx < metaEnum.keyCount(); ++idx )
{
const char *enumKey = metaEnum.key( idx );
QDomNode flagNode = flagsElem.namedItem( QString( enumKey ) );
if ( flagNode.isNull() )
continue;
bool flagValue = flagNode.toElement().text() == "1" ? true : false;
QgsMapLayer::LayerFlag enumValue = static_cast<QgsMapLayer::LayerFlag>( metaEnum.keyToValue( enumKey ) );
if ( mFlags.testFlag( enumValue ) && !flagValue )
mFlags &= ~enumValue;
else if ( !mFlags.testFlag( enumValue ) && flagValue )
mFlags |= enumValue;
}
return true;
} // bool QgsMapLayer::readLayerXML
@ -554,6 +581,21 @@ bool QgsMapLayer::writeLayerXml( QDomElement &layerElement, QDomDocument &docume
mMetadata.writeMetadataXml( myMetadataElem, document );
layerElement.appendChild( myMetadataElem );
// flags
// this code is saving automatically all the flags entries
QDomElement layerFlagsElem = document.createElement( QStringLiteral( "flags" ) );
QMetaEnum metaEnum = QMetaEnum::fromType<QgsMapLayer::LayerFlag>();
for ( int idx = 0; idx < metaEnum.keyCount(); ++idx )
{
const char *enumKey = metaEnum.key( idx );
QgsMapLayer::LayerFlag enumValue = static_cast<QgsMapLayer::LayerFlag>( metaEnum.keyToValue( enumKey ) );
bool flagValue = mFlags.testFlag( enumValue );
QDomElement flagElem = document.createElement( enumKey );
flagElem.appendChild( document.createTextNode( QString::number( flagValue ) ) );
layerFlagsElem.appendChild( flagElem );
}
layerElement.appendChild( layerFlagsElem );
// now append layer node to map layer node
writeCustomProperties( layerElement, document );

View File

@ -118,6 +118,21 @@ class CORE_EXPORT QgsMapLayer : public QObject
Metadata,
};
/**
* Flags for the map layer
* \note Flags are options specified by the user used for the UI but are not preventing any API call.
* \since QGIS 3.4
*/
enum LayerFlag
{
Identifiable = 1 << 0, //!< If the layer is identifiable using the identify map tool and as a WMS layer.
Removable = 1 << 1, //!< If the layer can be removed from the project. The layer will not be removable from the legend menu entry but can still be removed with an API call.
Searchable = 1 << 2, //!< Only for vector-layer, determines if the layer is used in the 'search all layers' locator.
};
Q_ENUM( LayerFlag )
Q_DECLARE_FLAGS( LayerFlags, LayerFlag )
Q_FLAG( LayerFlags )
/**
* Constructor for QgsMapLayer
* \param type layer type
@ -146,6 +161,24 @@ class CORE_EXPORT QgsMapLayer : public QObject
*/
QgsMapLayer::LayerType type() const;
/**
* Returns the flags for this layer.
* \note Flags are options specified by the user used for the UI but are not preventing any API call.
* For instance, even if the Removable flag is not set, the layer can still be removed with the API
* but the action will not be listed in the legend menu.
* \since QGIS 3.4
*/
QgsMapLayer::LayerFlags flags() const;
/**
* Returns the flags for this layer.
\note Flags are options specified by the user used for the UI but are not preventing any API call.
* For instance, even if the Removable flag is not set, the layer can still be removed with the API
* but the action will not be listed in the legend menu.
* \since QGIS 3.4
*/
void setFlags( QgsMapLayer::LayerFlags flags );
/**
* Returns the extension of a Property.
* \returns The extension
@ -1335,6 +1368,8 @@ class CORE_EXPORT QgsMapLayer : public QObject
//! Type of the layer (e.g., vector, raster)
QgsMapLayer::LayerType mLayerType;
LayerFlags mFlags = LayerFlags( Identifiable | Removable | Searchable );
//! Blend mode for the layer
QPainter::CompositionMode mBlendMode = QPainter::CompositionMode_SourceOver;
@ -1375,6 +1410,7 @@ class CORE_EXPORT QgsMapLayer : public QObject
};
Q_DECLARE_METATYPE( QgsMapLayer * )
Q_DECLARE_OPERATORS_FOR_FLAGS( QgsMapLayer::LayerFlags )
#ifndef SIP_RUN

View File

@ -1271,6 +1271,27 @@ bool QgsProject::readProjectFile( const QString &filename )
mRootGroup->readLayerOrderFromXml( layerTreeCanvasElem );
}
// Convert pre 3.4 to create layers flags
if ( QgsProjectVersion( 3, 4, 0 ) > fileVersion )
{
const QStringList requiredLayerIds = readListEntry( QStringLiteral( "RequiredLayers" ), QStringLiteral( "Layers" ) );
for ( const QString &layerId : requiredLayerIds )
{
if ( QgsMapLayer *layer = mapLayer( layerId ) )
{
layer->setFlags( layer->flags() & ~QgsMapLayer::Removable );
}
}
const QStringList disabledLayerIds = readListEntry( QStringLiteral( "Identify" ), QStringLiteral( "/disabledLayers" ) );
for ( const QString &layerId : disabledLayerIds )
{
if ( QgsMapLayer *layer = mapLayer( layerId ) )
{
layer->setFlags( layer->flags() & ~QgsMapLayer::Identifiable );
}
}
}
// make sure the are just valid layers
QgsLayerTreeUtils::removeInvalidLayers( mRootGroup );
@ -1323,7 +1344,9 @@ bool QgsProject::readProjectFile( const QString &filename )
if ( clean )
setDirty( false );
Q_NOWARN_DEPRECATED_PUSH
emit nonIdentifiableLayersChanged( nonIdentifiableLayers() );
Q_NOWARN_DEPRECATED_POP
if ( mTranslator )
{
@ -2224,18 +2247,6 @@ QgsLayerTreeGroup *QgsProject::createEmbeddedGroup( const QString &groupName, co
context.setPathResolver( pathResolver() );
context.setProjectTranslator( this );
// store identify disabled layers of the embedded project
QSet<QString> embeddedIdentifyDisabledLayers;
QDomElement disabledLayersElem = projectDocument.documentElement().firstChildElement( QStringLiteral( "properties" ) ).firstChildElement( QStringLiteral( "Identify" ) ).firstChildElement( QStringLiteral( "disabledLayers" ) );
if ( !disabledLayersElem.isNull() )
{
QDomNodeList valueList = disabledLayersElem.elementsByTagName( QStringLiteral( "value" ) );
for ( int i = 0; i < valueList.size(); ++i )
{
embeddedIdentifyDisabledLayers.insert( valueList.at( i ).toElement().text() );
}
}
QgsLayerTreeGroup *root = new QgsLayerTreeGroup;
QDomElement layerTreeElem = projectDocument.documentElement().firstChildElement( QStringLiteral( "layer-tree-group" ) );
@ -2269,16 +2280,9 @@ QgsLayerTreeGroup *QgsProject::createEmbeddedGroup( const QString &groupName, co
initializeEmbeddedSubtree( projectFilePath, newGroup );
mLayerTreeRegistryBridge->setEnabled( true );
QStringList thisProjectIdentifyDisabledLayers = nonIdentifiableLayers();
// consider the layers might be identify disabled in its project
Q_FOREACH ( const QString &layerId, newGroup->findLayerIds() )
{
if ( embeddedIdentifyDisabledLayers.contains( layerId ) )
{
thisProjectIdentifyDisabledLayers.append( layerId );
}
QgsLayerTreeLayer *layer = newGroup->findLayer( layerId );
if ( layer )
{
@ -2287,8 +2291,6 @@ QgsLayerTreeGroup *QgsProject::createEmbeddedGroup( const QString &groupName, co
}
}
setNonIdentifiableLayers( thisProjectIdentifyDisabledLayers );
return newGroup;
}
@ -2446,37 +2448,46 @@ const QgsAnnotationManager *QgsProject::annotationManager() const
void QgsProject::setNonIdentifiableLayers( const QList<QgsMapLayer *> &layers )
{
QStringList currentLayers = nonIdentifiableLayers();
QStringList newLayers;
Q_FOREACH ( QgsMapLayer *l, layers )
const QMap<QString, QgsMapLayer *> &projectLayers = mapLayers();
for ( QMap<QString, QgsMapLayer *>::const_iterator it = projectLayers.constBegin(); it != projectLayers.constEnd(); ++it )
{
newLayers << l->id();
if ( layers.contains( it.value() ) == !it.value()->flags().testFlag( QgsMapLayer::Identifiable ) )
continue;
if ( layers.contains( it.value() ) )
it.value()->setFlags( it.value()->flags() & ~QgsMapLayer::Identifiable );
else
it.value()->setFlags( it.value()->flags() | QgsMapLayer::Identifiable );
}
if ( newLayers == currentLayers )
return;
QStringList disabledLayerIds;
Q_FOREACH ( QgsMapLayer *l, layers )
{
disabledLayerIds << l->id();
}
setNonIdentifiableLayers( disabledLayerIds );
emit nonIdentifiableLayersChanged( nonIdentifiableLayers() );
}
void QgsProject::setNonIdentifiableLayers( const QStringList &layerIds )
{
writeEntry( QStringLiteral( "Identify" ), QStringLiteral( "/disabledLayers" ), layerIds );
emit nonIdentifiableLayersChanged( layerIds );
QList<QgsMapLayer *> nonIdentifiableLayers;
for ( const QString &layerId : layerIds )
{
QgsMapLayer *layer = mapLayer( layerId );
if ( layer )
nonIdentifiableLayers << layer;
}
setNonIdentifiableLayers( nonIdentifiableLayers );
}
QStringList QgsProject::nonIdentifiableLayers() const
{
return readListEntry( QStringLiteral( "Identify" ), QStringLiteral( "/disabledLayers" ) );
QStringList nonIdentifiableLayers;
const QMap<QString, QgsMapLayer *> &layers = mapLayers();
for ( QMap<QString, QgsMapLayer *>::const_iterator it = layers.constBegin(); it != layers.constEnd(); ++it )
{
if ( !it.value()->flags().testFlag( QgsMapLayer::Identifiable ) )
{
nonIdentifiableLayers.append( it.value()->id() );
}
}
return nonIdentifiableLayers;
}
bool QgsProject::autoTransaction() const
@ -2803,25 +2814,32 @@ void QgsProject::setMetadata( const QgsProjectMetadata &metadata )
QSet<QgsMapLayer *> QgsProject::requiredLayers() const
{
QSet<QgsMapLayer *> layers;
const QStringList lst = readListEntry( QStringLiteral( "RequiredLayers" ), QStringLiteral( "Layers" ) );
for ( const QString &layerId : lst )
QSet<QgsMapLayer *> requiredLayers;
const QMap<QString, QgsMapLayer *> &layers = mapLayers();
for ( QMap<QString, QgsMapLayer *>::const_iterator it = layers.constBegin(); it != layers.constEnd(); ++it )
{
if ( QgsMapLayer *layer = mapLayer( layerId ) )
layers.insert( layer );
if ( !it.value()->flags().testFlag( QgsMapLayer::Removable ) )
{
requiredLayers.insert( it.value() );
}
}
return layers;
return requiredLayers;
}
void QgsProject::setRequiredLayers( const QSet<QgsMapLayer *> &layers )
{
QStringList layerIds;
layerIds.reserve( layers.count() );
for ( QgsMapLayer *layer : layers )
const QMap<QString, QgsMapLayer *> &projectLayers = mapLayers();
for ( QMap<QString, QgsMapLayer *>::const_iterator it = projectLayers.constBegin(); it != projectLayers.constEnd(); ++it )
{
layerIds << layer->id();
if ( layers.contains( it.value() ) == !it.value()->flags().testFlag( QgsMapLayer::Removable ) )
continue;
if ( layers.contains( it.value() ) )
it.value()->setFlags( it.value()->flags() & ~QgsMapLayer::Removable );
else
it.value()->setFlags( it.value()->flags() | QgsMapLayer::Removable );
}
writeEntry( QStringLiteral( "RequiredLayers" ), QStringLiteral( "Layers" ), layerIds );
}
void QgsProject::generateTsFile( const QString &locale )

View File

@ -553,18 +553,21 @@ class CORE_EXPORT QgsProject : public QObject, public QgsExpressionContextGenera
/**
* Set a list of layers which should not be taken into account on map identification
* \deprecated since QGIS 3.4 use QgsMapLayer::setFlags() instead
*/
void setNonIdentifiableLayers( const QList<QgsMapLayer *> &layers );
Q_DECL_DEPRECATED void setNonIdentifiableLayers( const QList<QgsMapLayer *> &layers );
/**
* Set a list of layers which should not be taken into account on map identification
* \deprecated since QGIS 3.4 use QgsMapLayer::setFlags() instead
*/
void setNonIdentifiableLayers( const QStringList &layerIds );
Q_DECL_DEPRECATED void setNonIdentifiableLayers( const QStringList &layerIds );
/**
* Gets the list of layers which currently should not be taken into account on map identification
* \deprecated since QGIS 3.4 use QgsMapLayer::setFlags() instead
*/
QStringList nonIdentifiableLayers() const;
Q_DECL_DEPRECATED QStringList nonIdentifiableLayers() const;
/**
* Transactional editing means that on supported datasources (postgres databases) the edit state of
@ -953,18 +956,20 @@ class CORE_EXPORT QgsProject : public QObject, public QgsExpressionContextGenera
* removed from the project. The set of layers may be configured by users in project properties.
* and it is mainly a hint for the user interface to protect users from removing layers that important
* in the project. The removeMapLayer(), removeMapLayers() calls do not block removal of layers listed here.
* \deprecated since QGIS 3.4 use QgsMapLayer::flags() instead
* \since QGIS 3.2
*/
QSet<QgsMapLayer *> requiredLayers() const;
Q_DECL_DEPRECATED QSet<QgsMapLayer *> requiredLayers() const;
/**
* Configures a set of map layers that are required in the project and therefore they should not get
* removed from the project. The set of layers may be configured by users in project properties.
* and it is mainly a hint for the user interface to protect users from removing layers that important
* in the project. The removeMapLayer(), removeMapLayers() calls do not block removal of layers listed here.
* \deprecated since QGIS 3.4 use QgsMapLayer::setFlags() instead
* \since QGIS 3.2
*/
void setRequiredLayers( const QSet<QgsMapLayer *> &layers );
Q_DECL_DEPRECATED void setRequiredLayers( const QSet<QgsMapLayer *> &layers );
/**
* Triggers the collection strings of .qgs to be included in ts file and calls writeTsFile()
@ -1058,8 +1063,11 @@ class CORE_EXPORT QgsProject : public QObject, public QgsExpressionContextGenera
*/
void loadingLayerMessageReceived( const QString &layerName, const QList<QgsReadWriteContext::ReadWriteMessage> &messages );
//! Emitted when the list of layer which are excluded from map identification changes
void nonIdentifiableLayersChanged( QStringList nonIdentifiableLayers );
/**
* Emitted when the list of layer which are excluded from map identification changes
* \deprecated since QGIS 3.4
*/
Q_DECL_DEPRECATED void nonIdentifiableLayersChanged( QStringList nonIdentifiableLayers );
//! Emitted when the file name of the project changes
void fileNameChanged();

View File

@ -2070,8 +2070,6 @@ bool QgsVectorLayer::readSymbology( const QDomNode &layerNode, QString &errorMes
QDomElement mapLayerNode = layerNode.toElement();
if ( mapLayerNode.attribute( QStringLiteral( "readOnly" ), QStringLiteral( "0" ) ).toInt() == 1 )
mReadOnly = true;
if ( mapLayerNode.attribute( QStringLiteral( "searchable" ), QStringLiteral( "0" ) ).toInt() == 1 )
mSearchable = true;
updateFields();
@ -2378,9 +2376,6 @@ bool QgsVectorLayer::writeSymbology( QDomNode &node, QDomDocument &doc, QString
// save readonly state
node.toElement().setAttribute( QStringLiteral( "readOnly" ), mReadOnly );
// save searchable state
node.toElement().setAttribute( QStringLiteral( "searchable" ), mSearchable );
// save preview expression
QDomElement prevExpElem = doc.createElement( QStringLiteral( "previewExpression" ) );
QDomText prevExpText = doc.createTextNode( mDisplayExpression );
@ -3112,26 +3107,12 @@ bool QgsVectorLayer::setReadOnly( bool readonly )
return true;
}
bool QgsVectorLayer::searchable() const
{
return mSearchable;
}
void QgsVectorLayer::setSearchable( bool searchable )
{
if ( searchable == mSearchable )
return;
mSearchable = searchable;
emit searchableChanged();
}
bool QgsVectorLayer::isModified() const
{
emit beforeModifiedCheck();
return mEditBuffer && mEditBuffer->isModified();
}
bool QgsVectorLayer::isAuxiliaryField( int index, int &srcIndex ) const
{
bool auxiliaryField = false;

View File

@ -360,7 +360,6 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
Q_PROPERTY( QgsEditFormConfig editFormConfig READ editFormConfig WRITE setEditFormConfig NOTIFY editFormConfigChanged )
Q_PROPERTY( bool readOnly READ isReadOnly WRITE setReadOnly NOTIFY readOnlyChanged )
Q_PROPERTY( double opacity READ opacity WRITE setOpacity NOTIFY opacityChanged )
Q_PROPERTY( bool searchable READ searchable WRITE setSearchable NOTIFY searchableChanged )
public:
@ -1383,17 +1382,6 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
*/
bool setReadOnly( bool readonly = true );
/**
* Returns true if the provider is in read-only mode
*/
bool searchable() const;
/**
* Make layer searchable or not
* \since QGIS 3.4
*/
void setSearchable( bool searchable );
/**
* Changes a feature's \a geometry within the layer's edit buffer
* (but does not immediately commit the changes). The \a fid argument
@ -2320,12 +2308,6 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
*/
void readOnlyChanged();
/**
* Emitted when the search state of this layer is changed.
* \since QGIS 3.4
*/
void searchableChanged();
/**
* Emitted when the feature count for symbols on this layer has been recalculated.
*
@ -2392,9 +2374,6 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
//! Flag indicating whether the layer is in read-only mode (editing disabled) or not
bool mReadOnly = false;
//! Indicates whether the layer is searchable or not
bool mSearchable = true;
/**
* Set holding the feature IDs that are activated. Note that if a feature
subsequently gets deleted (i.e. by its addition to mDeletedFeatureIds),

View File

@ -141,8 +141,6 @@ QList<QgsMapToolIdentify::IdentifyResult> QgsMapToolIdentify::identify( const Qg
{
QApplication::setOverrideCursor( Qt::WaitCursor );
QStringList noIdentifyLayerIdList = QgsProject::instance()->readListEntry( QStringLiteral( "Identify" ), QStringLiteral( "/disabledLayers" ) );
int layerCount;
if ( layerList.isEmpty() )
layerCount = mCanvas->layerCount();
@ -162,7 +160,7 @@ QList<QgsMapToolIdentify::IdentifyResult> QgsMapToolIdentify::identify( const Qg
emit identifyProgress( i, mCanvas->layerCount() );
emit identifyMessage( tr( "Identifying on %1…" ).arg( layer->name() ) );
if ( noIdentifyLayerIdList.contains( layer->id() ) )
if ( !layer->flags().testFlag( QgsMapLayer::Identifiable ) )
continue;
if ( identifyLayer( &results, layer, mLastGeometry, mLastExtent, mLastMapUnitsPerPixel, layerType ) )

View File

@ -65,15 +65,9 @@ QgsQuickFeatureLayerPairs QgsQuickIdentifyKit::identify( const QPointF &point, Q
}
else
{
QStringList noIdentifyLayerIdList;
if ( mMapSettings->project() )
{
noIdentifyLayerIdList = mMapSettings->project()->nonIdentifiableLayers();
}
for ( QgsMapLayer *layer : mMapSettings->mapSettings().layers() )
{
if ( mMapSettings->project() && noIdentifyLayerIdList.contains( layer->id() ) )
if ( mMapSettings->project() && !layer->flags().testFlag( QgsMapLayer::Identifiable ) )
continue;
QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layer );
@ -91,7 +85,6 @@ QgsQuickFeatureLayerPairs QgsQuickIdentifyKit::identify( const QPointF &point, Q
QgsDebugMsg( QStringLiteral( "IdentifyKit identified %1 results with TopDownStopAtFirst mode." ).arg( results.count() ) );
return results;
}
}
QgsDebugMsg( QStringLiteral( "IdentifyKit identified %1 results" ).arg( results.count() ) );

View File

@ -771,7 +771,6 @@ namespace QgsWms
const QgsProject *project, const QString &version,
const QgsServerRequest &request, bool projectSettings )
{
QStringList nonIdentifiableLayers = project->nonIdentifiableLayers();
const QgsLayerTree *projectLayerTreeRoot = project->layerTreeRoot();
QDomElement layerParentElem = doc.createElement( QStringLiteral( "Layer" ) );
@ -936,7 +935,7 @@ namespace QgsWms
}
// queryable layer
if ( project->nonIdentifiableLayers().contains( l->id() ) )
if ( !l->flags().testFlag( QgsMapLayer::Identifiable ) )
{
layerElem.setAttribute( QStringLiteral( "queryable" ), QStringLiteral( "0" ) );
}

View File

@ -247,7 +247,7 @@ namespace QgsWms
QDomElement layerElem = doc.createElement( QStringLiteral( "Layer" ) );
// queryable layer
if ( project->nonIdentifiableLayers().contains( l->id() ) )
if ( !l->flags().testFlag( QgsMapLayer::Identifiable ) )
{
layerElem.setAttribute( QStringLiteral( "queryable" ), QStringLiteral( "false" ) );
}

View File

@ -1253,7 +1253,7 @@ namespace QgsWms
if ( queryLayer == layerNickname( *layer ) )
{
validLayer = true;
queryableLayer = !mProject->nonIdentifiableLayers().contains( layer->id() ) ;
queryableLayer = layer->flags().testFlag( QgsMapLayer::Identifiable );
if ( !queryableLayer )
{
break;
@ -2946,20 +2946,13 @@ namespace QgsWms
void QgsRenderer::removeNonIdentifiableLayers( QList<QgsMapLayer *> &layers ) const
{
QStringList nonIdentifiableLayers = mProject->nonIdentifiableLayers();
if ( !nonIdentifiableLayers.isEmpty() )
QList<QgsMapLayer *>::iterator it = layers.begin();
while ( it != layers.end() )
{
QList<QgsMapLayer *> wantedLayers;
for ( QgsMapLayer *layer : layers )
{
if ( nonIdentifiableLayers.contains( layer->id() ) )
continue;
wantedLayers.append( layer );
}
layers = wantedLayers;
if ( !( *it )->flags().testFlag( QgsMapLayer::Identifiable ) )
it = layers.erase( it );
else
++it;
}
}

View File

@ -249,8 +249,6 @@ namespace QgsWmts
#endif
QgsCoordinateReferenceSystem wgs84 = QgsCoordinateReferenceSystem::fromOgcWmsCrs( GEO_EPSG_CRS_AUTHID );
QStringList nonIdentifiableLayers = project->nonIdentifiableLayers();
// WMTS Project configuration
bool wmtsProject = project->readBoolEntry( QStringLiteral( "WMTSLayers" ), QStringLiteral( "Project" ) );
@ -349,7 +347,7 @@ namespace QgsWmts
{
wgs84BoundingRect.combineExtentWith( QgsRectangle( -180, -90, 180, 90 ) );
}
if ( !queryable && !nonIdentifiableLayers.contains( l->id() ) )
if ( !queryable && l->flags().testFlag( QgsMapLayer::Identifiable ) )
{
queryable = true;
}
@ -425,7 +423,7 @@ namespace QgsWmts
if ( wmtsJpegLayerIdList.contains( lId ) )
pLayer.formats << QStringLiteral( "image/jpeg" );
pLayer.queryable = ( !nonIdentifiableLayers.contains( l->id() ) );
pLayer.queryable = ( l->flags().testFlag( QgsMapLayer::Identifiable ) );
pLayer.maxScale = l->maximumScale();
pLayer.minScale = l->minimumScale();

View File

@ -40,7 +40,7 @@ class TestQgsProject : public QObject
void testPathResolverSvg();
void testProjectUnits();
void variablesChanged();
void testRequiredLayers();
void testLayerFlags();
};
void TestQgsProject::init()
@ -356,7 +356,7 @@ void TestQgsProject::variablesChanged()
delete prj;
}
void TestQgsProject::testRequiredLayers()
void TestQgsProject::testLayerFlags()
{
QString dataDir( TEST_DATA_DIR ); //defined in CmakeLists.txt
QString layerPath = dataDir + "/points.shp";
@ -367,13 +367,9 @@ void TestQgsProject::testRequiredLayers()
prj.addMapLayer( layer1 );
prj.addMapLayer( layer2 );
QSet<QgsMapLayer *> reqLayers;
reqLayers << layer2;
prj.setRequiredLayers( reqLayers );
layer2->setFlags( layer2->flags() & ~QgsMapLayer::Removable );
QSet<QgsMapLayer *> reqLayersReturned = prj.requiredLayers();
QCOMPARE( reqLayersReturned.count(), 1 );
QCOMPARE( *reqLayersReturned.constBegin(), layer2 );
QString layer2id = layer2->id();
QTemporaryFile f;
QVERIFY( f.open() );
@ -385,9 +381,9 @@ void TestQgsProject::testRequiredLayers()
QgsProject prj2;
prj2.setFileName( f.fileName() );
QVERIFY( prj2.read() );
QSet<QgsMapLayer *> reqLayersReturned2 = prj2.requiredLayers();
QCOMPARE( reqLayersReturned2.count(), 1 );
QCOMPARE( ( *reqLayersReturned.constBegin() )->name(), QString( "points 2" ) );
QgsMapLayer *layer = prj.mapLayer( layer2id );
QVERIFY( layer );
QVERIFY( !layer->flags().testFlag( QgsMapLayer::Removable ) );
}