Skip to content
Permalink
Browse files

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
  • Loading branch information
wonder-sk committed May 25, 2014
1 parent 35de393 commit f57d4063a83bf6e05813583884b522d88d954a4a
@@ -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 );

0 comments on commit f57d406

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