Skip to content

Commit

Permalink
create QgsMapLayer::LayerFlags for Searchable, Identifiable and Remov…
Browse files Browse the repository at this point in the history
…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 authored Sep 8, 2018
1 parent 48dcab7 commit 89830f6
Show file tree
Hide file tree
Showing 22 changed files with 310 additions and 215 deletions.
4 changes: 4 additions & 0 deletions python/core/auto_additions/qgsmaplayer.py
Original file line number Diff line number Diff line change
@@ -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
37 changes: 37 additions & 0 deletions python/core/auto_generated/qgsmaplayer.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 );
Expand Down Expand Up @@ -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);



/************************************************************************
Expand Down
24 changes: 18 additions & 6 deletions python/core/auto_generated/qgsproject.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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();
Expand Down
19 changes: 0 additions & 19 deletions python/core/auto_generated/qgsvectorlayer.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -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 );
Expand Down Expand Up @@ -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();
Expand Down
6 changes: 2 additions & 4 deletions src/app/qgisapp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
Expand Down
3 changes: 1 addition & 2 deletions src/app/qgsapplayertreeviewmenuprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
72 changes: 38 additions & 34 deletions src/app/qgslayercapabilitiesmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 ) );
}
}

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 )
{
Expand All @@ -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;
}
}
}
Expand All @@ -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;
}
}
}
}
Expand Down
10 changes: 6 additions & 4 deletions src/app/qgslayercapabilitiesmodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
};

Expand Down
27 changes: 22 additions & 5 deletions src/app/qgsprojectproperties.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 ) );
}
}

Expand Down
Loading

0 comments on commit 89830f6

Please sign in to comment.