28 changes: 28 additions & 0 deletions python/gui/qgslegendinterface.sip
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,34 @@ class QgsLegendInterface : QObject
//! @note added in 1.5
virtual bool isLayerVisible( QgsMapLayer * ml ) = 0;

/** Add action for layers in the legend
* @note added in 2.0
*/
virtual void addLegendLayerAction( QAction* action, QString menu, QString id,
QgsMapLayer::LayerType type, bool allLayers ) = 0;

/** Add action for a specific layers in the legend.
* Use this in combination with addLegendLayerAction( allLayers = False )
* @note added in 2.0
*/
virtual void addLegendLayerActionForLayer( QAction* action, QgsMapLayer* layer ) = 0;

/** Remove action for layers in the legend
* @note added in 2.0
*/
virtual bool removeLegendLayerAction( QAction* action ) = 0;

//! Returns the current layer if the current item is a QgsLegendLayer.
//! If the current item is a QgsLegendLayer, its first maplayer is returned.
//! Else, 0 is returned.
//! @note Added in 2.0
virtual QgsMapLayer* currentLayer() = 0;

//! set the current layer
//! returns true if the layer exists, false otherwise
//! @note Added in 2.0
virtual bool setCurrentLayer( QgsMapLayer *layer ) = 0;

signals:

//! emitted when a group index has changed
Expand Down
27 changes: 27 additions & 0 deletions src/app/legend/qgsapplegendinterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ QgsAppLegendInterface::QgsAppLegendInterface( QgsLegend * legend )
connect( legend, SIGNAL( itemMovedGroup( QgsLegendItem *, int ) ), this, SIGNAL( groupRelationsChanged() ) );
// connect( legend, SIGNAL( itemChanged( QTreeWidgetItem*, int ) ), this, SIGNAL( groupRelationsChanged() ) );
connect( legend, SIGNAL( itemRemoved() ), this, SIGNAL( itemRemoved() ) );
connect( legend, SIGNAL( currentLayerChanged( QgsMapLayer * ) ), this, SIGNAL( currentLayerChanged( QgsMapLayer * ) ) );
}

QgsAppLegendInterface::~QgsAppLegendInterface()
Expand Down Expand Up @@ -191,3 +192,29 @@ void QgsAppLegendInterface::refreshLayerSymbology( QgsMapLayer *ml )
{
mLegend->refreshLayerSymbology( ml->id() );
}

void QgsAppLegendInterface::addLegendLayerAction( QAction* action,
QString menu, QString id, QgsMapLayer::LayerType type, bool allLayers )
{
mLegend->addLegendLayerAction( action, menu, id, type, allLayers );
}

void QgsAppLegendInterface::addLegendLayerActionForLayer( QAction* action, QgsMapLayer* layer )
{
mLegend->addLegendLayerActionForLayer( action, layer );
}

bool QgsAppLegendInterface::removeLegendLayerAction( QAction* action )
{
return mLegend->removeLegendLayerAction( action );
}

QgsMapLayer* QgsAppLegendInterface::currentLayer()
{
return mLegend->currentLayer();
}

bool QgsAppLegendInterface::setCurrentLayer( QgsMapLayer *layer )
{
return mLegend->setCurrentLayer( layer );
}
8 changes: 8 additions & 0 deletions src/app/legend/qgsapplegendinterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,14 @@ class QgsAppLegendInterface : public QgsLegendInterface
//! Check if a layer is visible
bool isLayerVisible( QgsMapLayer * ml );

void addLegendLayerAction( QAction* action, QString menu, QString id,
QgsMapLayer::LayerType type, bool allLayers );
void addLegendLayerActionForLayer( QAction* action, QgsMapLayer* layer );
bool removeLegendLayerAction( QAction* action );

QgsMapLayer* currentLayer();
bool setCurrentLayer( QgsMapLayer *layer );

public slots:

//! Add a new group
Expand Down
127 changes: 126 additions & 1 deletion src/app/legend/qgslegend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,7 @@ void QgsLegend::removeLayers( QStringList theLayers )
{
invLayerRemoved = true;
}
removeLegendLayerActionsForLayer( ll->layer() );
removeItem( ll );
delete ll;
break;
Expand Down Expand Up @@ -761,7 +762,73 @@ void QgsLegend::handleRightClickEvent( QTreeWidgetItem* item, const QPoint& posi
{
if ( li->type() == QgsLegendItem::LEGEND_LAYER )
{
qobject_cast<QgsLegendLayer*>( li )->addToPopupMenu( theMenu );
QgsLegendLayer* lyr = qobject_cast<QgsLegendLayer*>( li );
lyr->addToPopupMenu( theMenu );

// add custom layer actions
QList< LegendLayerAction > actions = legendLayerActions( lyr->layer()->type() );
if ( ! actions.isEmpty() )
{
theMenu.addSeparator();
QList<QMenu*> theMenus;
for ( int i = 0; i < actions.count(); i++ )
{
if ( actions[i].allLayers || actions[i].layers.contains( lyr->layer() ) )
{
if ( actions[i].menu.isEmpty() )
{
theMenu.addAction( actions[i].action );
}
else
{
// find or create menu for given menu name
// adapted from QgisApp::getPluginMenu( QString menuName )
QString menuName = actions[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, this );
theMenus.append( newMenu );
// Where to put it? - we worked that out above...
theMenu.insertMenu( before, newMenu );
}
// QMenu* menu = getMenu( actions[i].menu, &theBeforeSep, &theAfterSep, &theMenu );
newMenu->addAction( actions[i].action );
}
}
}
theMenu.addSeparator();
}

// properties goes on bottom of menu for consistency with normal ui standards
// e.g. kde stuff
theMenu.addAction( tr( "&Properties" ), QgisApp::instance(), SLOT( layerProperties() ) );

if ( li->parent() && !parentGroupEmbedded( li ) )
{
Expand Down Expand Up @@ -2969,3 +3036,61 @@ void QgsLegend::groupSelectedLayers()
}
}

void QgsLegend::addLegendLayerAction( QAction* action, QString menu, QString id,
QgsMapLayer::LayerType type, bool allLayers )
{
mLegendLayerActionMap[type].append( LegendLayerAction( action, menu, id, allLayers ) );
}

bool QgsLegend::removeLegendLayerAction( QAction* action )
{
QMap< QgsMapLayer::LayerType, QList< LegendLayerAction > >::iterator it;
for ( it = mLegendLayerActionMap.begin();
it != mLegendLayerActionMap.end(); ++it )
{
for ( int i = 0; i < it->count(); i++ )
{
if (( *it )[i].action == action )
{
( *it ).removeAt( i );
return true;
}
}
}
return false;
}

void QgsLegend::addLegendLayerActionForLayer( QAction* action, QgsMapLayer* layer )
{
QMap< QgsMapLayer::LayerType, QList< LegendLayerAction > >::iterator it;
for ( it = mLegendLayerActionMap.begin();
it != mLegendLayerActionMap.end(); ++it )
{
for ( int i = 0; i < it->count(); i++ )
{
if (( *it )[i].action == action )
{
( *it )[i].layers.append( layer );
return;
}
}
}
}

void QgsLegend::removeLegendLayerActionsForLayer( QgsMapLayer* layer )
{
QMap< QgsMapLayer::LayerType, QList< LegendLayerAction > >::iterator it;
for ( it = mLegendLayerActionMap.begin();
it != mLegendLayerActionMap.end(); ++it )
{
for ( int i = 0; i < it->count(); i++ )
{
( *it )[i].layers.removeAll( layer );
}
}
}

QList< LegendLayerAction > QgsLegend::legendLayerActions( QgsMapLayer::LayerType type ) const
{
return mLegendLayerActionMap.contains( type ) ? mLegendLayerActionMap.value( type ) : QList< LegendLayerAction >() ;
}
24 changes: 23 additions & 1 deletion src/app/legend/qgslegend.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ class QTreeWidgetItem;
class QgsCoordinateReferenceSystem;
class QgsMapCanvasLayer;

#include "qgsmaplayer.h"

//Information about relationship between groups and layers
//key: group name (or null strings for single layers without groups)
//value: containter with layer ids contained in the group
Expand All @@ -50,10 +52,21 @@ struct DrawingOrderInfo
bool embeddedGroup;
};

struct LegendLayerAction
{
LegendLayerAction( QAction* a, QString m, QString i, bool all )
: action( a ), menu( m ), id( i ), allLayers( all ) {}
QAction* action;
QString menu;
QString id;
bool allLayers;
QList<QgsMapLayer*> layers;
};

/**
\class QgsLegend
\brief A Legend treeview for QGIS
Map legend is a specialised QListView designed to show grooups of map layers,
Map legend is a specialised QListView designed to show groups of map layers,
map layers, and the map layer members, properties and symbols for each layer.
The legend supports simple operations such as displaying an ordered list of
Expand Down Expand Up @@ -362,6 +375,13 @@ class QgsLegend : public QTreeWidget
/** Create a new group for the selected items **/
void groupSelectedLayers();

void addLegendLayerAction( QAction* action, QString menu, QString id,
QgsMapLayer::LayerType type, bool allLayers );
bool removeLegendLayerAction( QAction* action );
void addLegendLayerActionForLayer( QAction* action, QgsMapLayer* layer );
void removeLegendLayerActionsForLayer( QgsMapLayer* layer );
QList< LegendLayerAction > legendLayerActions( QgsMapLayer::LayerType type ) const;

protected:

/*!Event handler for mouse movements.
Expand Down Expand Up @@ -549,6 +569,8 @@ class QgsLegend : public QTreeWidget
//! Widget that holds the indicator line //
QWidget *mInsertionLine;

QMap< QgsMapLayer::LayerType, QList< LegendLayerAction > > mLegendLayerActionMap;

#ifdef QGISDEBUG
void showItem( QString msg, QTreeWidgetItem *item );
#endif
Expand Down
4 changes: 0 additions & 4 deletions src/app/legend/qgslegendlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -520,10 +520,6 @@ void QgsLegendLayer::addToPopupMenu( QMenu& theMenu )
// disable duplication of plugin layers
duplicateLayersAction->setEnabled( false );
}

// properties goes on bottom of menu for consistency with normal ui standards
// e.g. kde stuff
theMenu.addAction( tr( "&Properties" ), QgisApp::instance(), SLOT( layerProperties() ) );
}

//////////
Expand Down
2 changes: 1 addition & 1 deletion src/app/qgisapp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7117,7 +7117,7 @@ void QgisApp::layersWereAdded( QList<QgsMapLayer *> theLayers )
QgsVectorDataProvider* vProvider = vlayer->dataProvider();
if ( vProvider && vProvider->capabilities() & QgsVectorDataProvider::EditingCapabilities )
{
connect( vlayer, SIGNAL( layerModified( bool ) ), this, SLOT( updateLayerModifiedActions() ) );
connect( vlayer, SIGNAL( layerModified() ), this, SLOT( updateLayerModifiedActions() ) );
connect( vlayer, SIGNAL( editingStarted() ), this, SLOT( layerEditStateChanged() ) );
connect( vlayer, SIGNAL( editingStopped() ), this, SLOT( layerEditStateChanged() ) );
}
Expand Down
36 changes: 36 additions & 0 deletions src/gui/qgslegendinterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@

class QgsMapLayer;
class QTreeWidgetItem;
class QAction;

#include "qgsmaplayer.h"

//Information about relationship between groups and layers
//key: group name (or null strings for single layers without groups)
Expand Down Expand Up @@ -83,6 +86,34 @@ class GUI_EXPORT QgsLegendInterface : public QObject
//! @note added in 1.5
virtual bool isLayerVisible( QgsMapLayer * ml ) = 0;

/** Add action for layers in the legend
* @note added in 2.0
*/
virtual void addLegendLayerAction( QAction* action, QString menu, QString id,
QgsMapLayer::LayerType type, bool allLayers ) = 0;

/** Add action for a specific layers in the legend.
* Use this in combination with addLegendLayerAction( allLayers = False )
* @note added in 2.0
*/
virtual void addLegendLayerActionForLayer( QAction* action, QgsMapLayer* layer ) = 0;

/** Remove action for layers in the legend
* @note added in 2.0
*/
virtual bool removeLegendLayerAction( QAction* action ) = 0;

//! Returns the current layer if the current item is a QgsLegendLayer.
//! If the current item is a QgsLegendLayer, its first maplayer is returned.
//! Else, 0 is returned.
//! @note Added in 2.0
virtual QgsMapLayer* currentLayer() = 0;

//! set the current layer
//! returns true if the layer exists, false otherwise
//! @note Added in 2.0
virtual bool setCurrentLayer( QgsMapLayer *layer ) = 0;

signals:

//! emitted when a group index has changed
Expand All @@ -97,6 +128,11 @@ class GUI_EXPORT QgsLegendInterface : public QObject
/* //! emitted when an item (group/layer) is removed */
void itemRemoved( );

//! Emitted whenever current (selected) layer changes
// the pointer to layer can be null if no layer is selected
//! @note Added in 2.0
void currentLayerChanged( QgsMapLayer * layer );

public slots:

//! Add a new group
Expand Down