Skip to content
Permalink
Browse files

create QgsMapLayer::LayerFlags for Searchable, Identifiable and Remov…

…able (#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
  • Loading branch information
3nids committed Sep 8, 2018
1 parent 48dcab7 commit 89830f614eac2f4aec17ba4bc07db885ab7c4ca7
@@ -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
@@ -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);



/************************************************************************
@@ -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();
@@ -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();
@@ -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;
@@ -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;
@@ -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;
}
}
}
}
@@ -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;
};

@@ -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 ) );
}
}

0 comments on commit 89830f6

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