Skip to content

Commit 5bc2183

Browse files
committed
Keep group and checked state when handling bad layers
Fixes #21387 - Unavailable layers because of a moved folder
1 parent 4e9c4b5 commit 5bc2183

File tree

1 file changed

+44
-12
lines changed

1 file changed

+44
-12
lines changed

src/app/qgshandlebadlayers.cpp

+44-12
Original file line numberDiff line numberDiff line change
@@ -361,14 +361,6 @@ void QgsHandleBadLayers::apply()
361361
{
362362
QgsProject::instance()->layerTreeRegistryBridge()->setEnabled( true );
363363
buttonBox->button( QDialogButtonBox::Ignore )->setEnabled( false );
364-
QList<QgsMapLayer *> toRemove;
365-
for ( const auto &l : QgsProject::instance()->mapLayers( ) )
366-
{
367-
if ( ! l->isValid() )
368-
toRemove << l;
369-
}
370-
371-
QgsProject::instance()->removeMapLayers( toRemove );
372364

373365
for ( int i = 0; i < mLayerList->rowCount(); i++ )
374366
{
@@ -378,20 +370,60 @@ void QgsHandleBadLayers::apply()
378370
QTableWidgetItem *item = mLayerList->item( i, 4 );
379371
QString datasource = item->text();
380372

381-
node.namedItem( QStringLiteral( "datasource" ) ).toElement().firstChild().toText().setData( datasource );
382-
if ( QgsProject::instance()->readLayer( node ) )
373+
bool dataSourceChanged { false };
374+
const QString layerId { node.namedItem( QStringLiteral( "id" ) ).toElement().text() };
375+
const QString provider { node.namedItem( QStringLiteral( "provider" ) ).toElement().text() };
376+
const QString name { mLayerList->item( i, 0 )->text() };
377+
378+
// Try first to change the datasource of the existing layers, this will
379+
// maintain the current status (checked/unchecked) and group
380+
if ( QgsProject::instance()->mapLayer( layerId ) )
381+
{
382+
QgsDataProvider::ProviderOptions options;
383+
QgsMapLayer *mapLayer = QgsProject::instance()->mapLayer( layerId );
384+
if ( mapLayer )
385+
{
386+
mapLayer->setDataSource( datasource, name, provider, options );
387+
dataSourceChanged = mapLayer->isValid();
388+
}
389+
}
390+
391+
// If the data source was changed successfully, remove the bad layer from the dialog
392+
// otherwise, try to set the new datasource in the XML node and reload the layer,
393+
// finally marks with red all remaining bad layers.
394+
if ( dataSourceChanged )
383395
{
384396
mLayerList->removeRow( i-- );
385397
}
386398
else
387399
{
388-
item->setForeground( QBrush( Qt::red ) );
400+
node.namedItem( QStringLiteral( "datasource" ) ).toElement().firstChild().toText().setData( datasource );
401+
if ( QgsProject::instance()->readLayer( node ) )
402+
{
403+
mLayerList->removeRow( i-- );
404+
}
405+
else
406+
{
407+
item->setForeground( QBrush( Qt::red ) );
408+
}
389409
}
390410
}
391-
QgsProject::instance()->layerTreeRegistryBridge()->setEnabled( false );
392411

412+
// Final cleanup: remove any bad layer (it should not be any btw)
393413
if ( mLayerList->rowCount() == 0 )
414+
{
415+
QList<QgsMapLayer *> toRemove;
416+
const auto mapLayers = QgsProject::instance()->mapLayers();
417+
for ( const auto &l : mapLayers )
418+
{
419+
if ( ! l->isValid() )
420+
toRemove << l;
421+
}
422+
QgsProject::instance()->removeMapLayers( toRemove );
394423
accept();
424+
}
425+
426+
QgsProject::instance()->layerTreeRegistryBridge()->setEnabled( false );
395427

396428
}
397429

0 commit comments

Comments
 (0)