Skip to content

Commit 7e022f0

Browse files
committed
Disable remove action instead of message box + unit test
1 parent 42517f8 commit 7e022f0

File tree

4 files changed

+71
-8
lines changed

4 files changed

+71
-8
lines changed

src/app/qgisapp.cpp

+17-6
Original file line numberDiff line numberDiff line change
@@ -9320,16 +9320,14 @@ void QgisApp::removeLayer()
93209320
}
93219321
}
93229322

9323+
// extra check for required layers
9324+
// In theory it should not be needed because the remove action should be disabled
9325+
// if there are required layers in the selection...
93239326
const QSet<QgsMapLayer *> requiredLayers = QgsProject::instance()->requiredLayers();
93249327
for ( QgsMapLayer *layer : selectedLayers )
93259328
{
93269329
if ( requiredLayers.contains( layer ) )
9327-
{
9328-
QMessageBox::warning( this, tr( "Required layers" ),
9329-
tr( "The layer '%1' is marked as a required and therefore it cannot be removed from the project.\n\n"
9330-
"If you really need to remove the layer, unmark it as required in the Project Properties window > Data Sources tab." ).arg( layer->name() ) );
93319330
return;
9332-
}
93339331
}
93349332

93359333
if ( !activeTaskDescriptions.isEmpty() )
@@ -11587,7 +11585,7 @@ void QgisApp::selectionChanged( QgsMapLayer *layer )
1158711585

1158811586
void QgisApp::legendLayerSelectionChanged()
1158911587
{
11590-
QList<QgsLayerTreeLayer *> selectedLayers = mLayerTreeView ? mLayerTreeView->selectedLayerNodes() : QList<QgsLayerTreeLayer *>();
11588+
const QList<QgsLayerTreeLayer *> selectedLayers = mLayerTreeView ? mLayerTreeView->selectedLayerNodes() : QList<QgsLayerTreeLayer *>();
1159111589

1159211590
mActionDuplicateLayer->setEnabled( !selectedLayers.isEmpty() );
1159311591
mActionSetLayerScaleVisibility->setEnabled( !selectedLayers.isEmpty() );
@@ -11613,6 +11611,19 @@ void QgisApp::legendLayerSelectionChanged()
1161311611
mLegendExpressionFilterButton->setChecked( exprEnabled );
1161411612
}
1161511613
}
11614+
11615+
// remove action - check for required layers
11616+
bool removeEnabled = true;
11617+
const QSet<QgsMapLayer *> requiredLayers = QgsProject::instance()->requiredLayers();
11618+
for ( QgsLayerTreeLayer *nodeLayer : selectedLayers )
11619+
{
11620+
if ( requiredLayers.contains( nodeLayer->layer() ) )
11621+
{
11622+
removeEnabled = false;
11623+
break;
11624+
}
11625+
}
11626+
mActionRemoveLayer->setEnabled( removeEnabled );
1161611627
}
1161711628

1161811629
void QgisApp::layerEditStateChanged()

src/app/qgsapplayertreeviewmenuprovider.cpp

+16-2
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,8 @@ QMenu *QgsAppLayerTreeViewMenuProvider::createContextMenu()
8787

8888
menu->addSeparator();
8989
menu->addAction( actions->actionAddGroup( menu ) );
90-
menu->addAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionRemoveLayer.svg" ) ), tr( "&Remove Group…" ), QgisApp::instance(), SLOT( removeLayer() ) );
90+
QAction *removeAction = menu->addAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionRemoveLayer.svg" ) ), tr( "&Remove Group…" ), QgisApp::instance(), SLOT( removeLayer() ) );
91+
removeAction->setEnabled( removeActionEnabled() );
9192
menu->addSeparator();
9293

9394
menu->addAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionSetCRS.png" ) ),
@@ -171,7 +172,8 @@ QMenu *QgsAppLayerTreeViewMenuProvider::createContextMenu()
171172

172173
// duplicate layer
173174
QAction *duplicateLayersAction = menu->addAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionDuplicateLayer.svg" ) ), tr( "&Duplicate Layer" ), QgisApp::instance(), SLOT( duplicateLayers() ) );
174-
menu->addAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionRemoveLayer.svg" ) ), tr( "&Remove Layer…" ), QgisApp::instance(), SLOT( removeLayer() ) );
175+
QAction *removeAction = menu->addAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionRemoveLayer.svg" ) ), tr( "&Remove Layer…" ), QgisApp::instance(), SLOT( removeLayer() ) );
176+
removeAction->setEnabled( removeActionEnabled() );
175177

176178
menu->addSeparator();
177179

@@ -708,3 +710,15 @@ void QgsAppLayerTreeViewMenuProvider::setSymbolLegendNodeColor( const QColor &co
708710
layer->emitStyleChanged();
709711
}
710712
}
713+
714+
bool QgsAppLayerTreeViewMenuProvider::removeActionEnabled()
715+
{
716+
const QList<QgsLayerTreeLayer *> selectedLayers = mView->selectedLayerNodes();
717+
const QSet<QgsMapLayer *> requiredLayers = QgsProject::instance()->requiredLayers();
718+
for ( QgsLayerTreeLayer *nodeLayer : selectedLayers )
719+
{
720+
if ( requiredLayers.contains( nodeLayer->layer() ) )
721+
return false;
722+
}
723+
return true;
724+
}

src/app/qgsapplayertreeviewmenuprovider.h

+3
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ class QgsAppLayerTreeViewMenuProvider : public QObject, public QgsLayerTreeViewM
6767
void setVectorSymbolColor( const QColor &color );
6868
void editSymbolLegendNodeSymbol();
6969
void setSymbolLegendNodeColor( const QColor &color );
70+
71+
private:
72+
bool removeActionEnabled();
7073
};
7174

7275
#endif // QGSAPPLAYERTREEVIEWMENUPROVIDER_H

tests/src/core/testqgsproject.cpp

+35
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ class TestQgsProject : public QObject
4040
void testPathResolverSvg();
4141
void testProjectUnits();
4242
void variablesChanged();
43+
void testRequiredLayers();
4344
};
4445

4546
void TestQgsProject::init()
@@ -347,6 +348,40 @@ void TestQgsProject::variablesChanged()
347348
delete prj;
348349
}
349350

351+
void TestQgsProject::testRequiredLayers()
352+
{
353+
QString dataDir( TEST_DATA_DIR ); //defined in CmakeLists.txt
354+
QString layerPath = dataDir + "/points.shp";
355+
QgsVectorLayer *layer1 = new QgsVectorLayer( layerPath, QStringLiteral( "points 1" ), QStringLiteral( "ogr" ) );
356+
QgsVectorLayer *layer2 = new QgsVectorLayer( layerPath, QStringLiteral( "points 2" ), QStringLiteral( "ogr" ) );
357+
358+
QgsProject prj;
359+
prj.addMapLayer( layer1 );
360+
prj.addMapLayer( layer2 );
361+
362+
QSet<QgsMapLayer *> reqLayers;
363+
reqLayers << layer2;
364+
prj.setRequiredLayers( reqLayers );
365+
366+
QSet<QgsMapLayer *> reqLayersReturned = prj.requiredLayers();
367+
QCOMPARE( reqLayersReturned.count(), 1 );
368+
QCOMPARE( *reqLayersReturned.constBegin(), layer2 );
369+
370+
QTemporaryFile f;
371+
QVERIFY( f.open() );
372+
f.close();
373+
prj.setFileName( f.fileName() );
374+
prj.write();
375+
376+
// test reading required layers back
377+
QgsProject prj2;
378+
prj2.setFileName( f.fileName() );
379+
QVERIFY( prj2.read() );
380+
QSet<QgsMapLayer *> reqLayersReturned2 = prj2.requiredLayers();
381+
QCOMPARE( reqLayersReturned2.count(), 1 );
382+
QCOMPARE( ( *reqLayersReturned.constBegin() )->name(), QString( "points 2" ) );
383+
}
384+
350385

351386
QGSTEST_MAIN( TestQgsProject )
352387
#include "testqgsproject.moc"

0 commit comments

Comments
 (0)