mirror of
https://github.com/qgis/QGIS.git
synced 2025-02-25 00:58:06 -05:00
Fix #10343 (legend crash with invalid layer)
Fixed the crash itself in the context menu, but also changed the behavior to remove any invalid layers from project as currently there is no mechanism for postponing handling of invalid layers after project load
This commit is contained in:
parent
35de393d8d
commit
f57d4063a8
@ -142,67 +142,7 @@ QMenu* QgsAppLayerTreeViewMenuProvider::createContextMenu()
|
||||
duplicateLayersAction->setEnabled( false );
|
||||
}
|
||||
|
||||
// add custom layer actions - should this go at end?
|
||||
QList< LegendLayerAction > lyrActions = legendLayerActions( layer->type() );
|
||||
|
||||
if ( ! lyrActions.isEmpty() )
|
||||
{
|
||||
menu->addSeparator();
|
||||
QList<QMenu*> theMenus;
|
||||
for ( int i = 0; i < lyrActions.count(); i++ )
|
||||
{
|
||||
if ( lyrActions[i].allLayers || lyrActions[i].layers.contains( layer ) )
|
||||
{
|
||||
if ( lyrActions[i].menu.isEmpty() )
|
||||
{
|
||||
menu->addAction( lyrActions[i].action );
|
||||
}
|
||||
else
|
||||
{
|
||||
// find or create menu for given menu name
|
||||
// adapted from QgisApp::getPluginMenu( QString menuName )
|
||||
QString menuName = lyrActions[i].menu;
|
||||
#ifdef Q_WS_MAC
|
||||
// Mac doesn't have '&' keyboard shortcuts.
|
||||
menuName.remove( QChar( '&' ) );
|
||||
#endif
|
||||
QAction* before = 0;
|
||||
QMenu* newMenu = 0;
|
||||
QString dst = menuName;
|
||||
dst.remove( QChar( '&' ) );
|
||||
foreach ( QMenu* menu, theMenus )
|
||||
{
|
||||
QString src = menu->title();
|
||||
src.remove( QChar( '&' ) );
|
||||
int comp = dst.localeAwareCompare( src );
|
||||
if ( comp < 0 )
|
||||
{
|
||||
// Add item before this one
|
||||
before = menu->menuAction();
|
||||
break;
|
||||
}
|
||||
else if ( comp == 0 )
|
||||
{
|
||||
// Plugin menu item already exists
|
||||
newMenu = menu;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( ! newMenu )
|
||||
{
|
||||
// It doesn't exist, so create
|
||||
newMenu = new QMenu( menuName );
|
||||
theMenus.append( newMenu );
|
||||
// Where to put it? - we worked that out above...
|
||||
menu->insertMenu( before, newMenu );
|
||||
}
|
||||
// QMenu* menu = getMenu( lyrActions[i].menu, &theBeforeSep, &theAfterSep, &theMenu );
|
||||
newMenu->addAction( lyrActions[i].action );
|
||||
}
|
||||
}
|
||||
}
|
||||
menu->addSeparator();
|
||||
}
|
||||
addCustomLayerActions( menu, layer );
|
||||
|
||||
if ( layer && QgsProject::instance()->layerIsEmbedded( layer->id() ).isEmpty() )
|
||||
menu->addAction( tr( "&Properties" ), QgisApp::instance(), SLOT( layerProperties() ) );
|
||||
@ -308,3 +248,71 @@ QList< LegendLayerAction > QgsAppLayerTreeViewMenuProvider::legendLayerActions(
|
||||
|
||||
return mLegendLayerActionMap.contains( type ) ? mLegendLayerActionMap.value( type ) : QList< LegendLayerAction >() ;
|
||||
}
|
||||
|
||||
void QgsAppLayerTreeViewMenuProvider::addCustomLayerActions( QMenu* menu, QgsMapLayer* layer )
|
||||
{
|
||||
if ( !layer )
|
||||
return;
|
||||
|
||||
// add custom layer actions - should this go at end?
|
||||
QList< LegendLayerAction > lyrActions = legendLayerActions( layer->type() );
|
||||
|
||||
if ( ! lyrActions.isEmpty() )
|
||||
{
|
||||
menu->addSeparator();
|
||||
QList<QMenu*> theMenus;
|
||||
for ( int i = 0; i < lyrActions.count(); i++ )
|
||||
{
|
||||
if ( lyrActions[i].allLayers || lyrActions[i].layers.contains( layer ) )
|
||||
{
|
||||
if ( lyrActions[i].menu.isEmpty() )
|
||||
{
|
||||
menu->addAction( lyrActions[i].action );
|
||||
}
|
||||
else
|
||||
{
|
||||
// find or create menu for given menu name
|
||||
// adapted from QgisApp::getPluginMenu( QString menuName )
|
||||
QString menuName = lyrActions[i].menu;
|
||||
#ifdef Q_WS_MAC
|
||||
// Mac doesn't have '&' keyboard shortcuts.
|
||||
menuName.remove( QChar( '&' ) );
|
||||
#endif
|
||||
QAction* before = 0;
|
||||
QMenu* newMenu = 0;
|
||||
QString dst = menuName;
|
||||
dst.remove( QChar( '&' ) );
|
||||
foreach ( QMenu* menu, theMenus )
|
||||
{
|
||||
QString src = menu->title();
|
||||
src.remove( QChar( '&' ) );
|
||||
int comp = dst.localeAwareCompare( src );
|
||||
if ( comp < 0 )
|
||||
{
|
||||
// Add item before this one
|
||||
before = menu->menuAction();
|
||||
break;
|
||||
}
|
||||
else if ( comp == 0 )
|
||||
{
|
||||
// Plugin menu item already exists
|
||||
newMenu = menu;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( ! newMenu )
|
||||
{
|
||||
// It doesn't exist, so create
|
||||
newMenu = new QMenu( menuName );
|
||||
theMenus.append( newMenu );
|
||||
// Where to put it? - we worked that out above...
|
||||
menu->insertMenu( before, newMenu );
|
||||
}
|
||||
// QMenu* menu = getMenu( lyrActions[i].menu, &theBeforeSep, &theAfterSep, &theMenu );
|
||||
newMenu->addAction( lyrActions[i].action );
|
||||
}
|
||||
}
|
||||
}
|
||||
menu->addSeparator();
|
||||
}
|
||||
}
|
||||
|
@ -37,6 +37,9 @@ class QgsAppLayerTreeViewMenuProvider : public QObject, public QgsLayerTreeViewM
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
void addCustomLayerActions( QMenu* menu, QgsMapLayer* layer );
|
||||
|
||||
QgsLayerTreeView* mView;
|
||||
QgsMapCanvas* mCanvas;
|
||||
|
||||
|
@ -205,3 +205,21 @@ bool QgsLayerTreeUtils::layersModified( const QList<QgsLayerTreeLayer*>& layerNo
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void QgsLayerTreeUtils::removeInvalidLayers( QgsLayerTreeGroup* group )
|
||||
{
|
||||
QList<QgsLayerTreeNode*> nodesToRemove;
|
||||
foreach ( QgsLayerTreeNode* node, group->children() )
|
||||
{
|
||||
if ( QgsLayerTree::isGroup( node ) )
|
||||
removeInvalidLayers( QgsLayerTree::toGroup( node ) );
|
||||
else if ( QgsLayerTree::isLayer( node ) )
|
||||
{
|
||||
if ( !QgsLayerTree::toLayer( node )->layer() )
|
||||
nodesToRemove << node;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ( QgsLayerTreeNode* node, nodesToRemove )
|
||||
group->removeChildNode( node );
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ class CORE_EXPORT QgsLayerTreeUtils
|
||||
static bool layersEditable( const QList<QgsLayerTreeLayer*>& layerNodes );
|
||||
static bool layersModified( const QList<QgsLayerTreeLayer*>& layerNodes );
|
||||
|
||||
static void removeInvalidLayers(QgsLayerTreeGroup* group );
|
||||
|
||||
protected:
|
||||
static void addLegendGroupToTreeWidget( const QDomElement& groupElem, QgsLayerTreeGroup* parent );
|
||||
|
@ -942,6 +942,9 @@ bool QgsProject::read()
|
||||
// load embedded groups and layers
|
||||
loadEmbeddedNodes( mRootGroup );
|
||||
|
||||
// make sure the are just valid layers
|
||||
QgsLayerTreeUtils::removeInvalidLayers( mRootGroup );
|
||||
|
||||
// read the project: used by map canvas and legend
|
||||
emit readProject( *doc );
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user