Skip to content

Commit a29c6a7

Browse files
slarosanirvn
authored andcommitted
[needs-docs] Reorganisation of contextual menu for group and layer (#6665)
1 parent f75c0a8 commit a29c6a7

File tree

3 files changed

+150
-124
lines changed

3 files changed

+150
-124
lines changed

src/app/qgisapp.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -831,6 +831,11 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
831831
//! pastes group or layer from the clipboard to layer tree
832832
void pasteLayer();
833833

834+
//! Set CRS of a layer
835+
void setLayerCrs();
836+
//! Assign layer CRS to project
837+
void setProjectCrsFromLayer();
838+
834839
//! copies features to internal clipboard
835840
void copyFeatures( QgsFeatureStore &featureStore );
836841
void loadGDALSublayers( const QString &uri, const QStringList &list );
@@ -1040,10 +1045,6 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
10401045
void setLayerScaleVisibility();
10411046
//! Zoom to nearest scale such that current layer is visible
10421047
void zoomToLayerScale();
1043-
//! Set CRS of a layer
1044-
void setLayerCrs();
1045-
//! Assign layer CRS to project
1046-
void setProjectCrsFromLayer();
10471048

10481049
/**
10491050
* Zooms so that the pixels of the raster layer occupies exactly one screen pixel.

src/app/qgsapplayertreeviewmenuprovider.cpp

Lines changed: 139 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -75,21 +75,35 @@ QMenu *QgsAppLayerTreeViewMenuProvider::createContextMenu()
7575
{
7676
menu->addAction( actions->actionZoomToGroup( mCanvas, menu ) );
7777

78-
menu->addAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionRemoveLayer.svg" ) ), tr( "&Remove" ), QgisApp::instance(), SLOT( removeLayer() ) );
79-
80-
menu->addAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionSetCRS.png" ) ),
81-
tr( "&Set Group CRS" ), QgisApp::instance(), SLOT( legendGroupSetCrs() ) );
78+
menu->addAction( tr( "Copy Group" ), QgisApp::instance(), SLOT( copyLayer() ) );
79+
if ( QgisApp::instance()->clipboard()->hasFormat( QGSCLIPBOARD_MAPLAYER_MIME ) )
80+
{
81+
QAction *actionPasteLayerOrGroup = new QAction( tr( "Paste Layer/Group" ), menu );
82+
connect( actionPasteLayerOrGroup, &QAction::triggered, QgisApp::instance(), &QgisApp::pasteLayer );
83+
menu->addAction( actionPasteLayerOrGroup );
84+
}
8285

8386
menu->addAction( actions->actionRenameGroupOrLayer( menu ) );
8487

85-
menu->addAction( tr( "&Set Group WMS data" ), QgisApp::instance(), SLOT( legendGroupSetWmsData() ) );
88+
menu->addSeparator();
89+
menu->addAction( actions->actionAddGroup( menu ) );
90+
menu->addAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionRemoveLayer.svg" ) ), tr( "&Remove…" ), QgisApp::instance(), SLOT( removeLayer() ) );
91+
menu->addSeparator();
92+
93+
menu->addAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionSetCRS.png" ) ),
94+
tr( "&Set Group CRS…" ), QgisApp::instance(), SLOT( legendGroupSetCrs() ) );
95+
menu->addAction( tr( "&Set Group WMS Data…" ), QgisApp::instance(), SLOT( legendGroupSetWmsData() ) );
96+
97+
menu->addSeparator();
8698

8799
menu->addAction( actions->actionMutuallyExclusiveGroup( menu ) );
88100

89101
menu->addAction( actions->actionCheckAndAllChildren( menu ) );
90102

91103
menu->addAction( actions->actionUncheckAndAllChildren( menu ) );
92104

105+
menu->addSeparator();
106+
93107
if ( mView->selectedNodes( true ).count() >= 2 )
94108
menu->addAction( actions->actionGroupSelected( menu ) );
95109

@@ -98,17 +112,13 @@ QMenu *QgsAppLayerTreeViewMenuProvider::createContextMenu()
98112
menu->addAction( tr( "Paste Style" ), QgisApp::instance(), SLOT( applyStyleToGroup() ) );
99113
}
100114

101-
menu->addAction( tr( "Copy Group" ), QgisApp::instance(), SLOT( copyLayer() ) );
102-
if ( QgisApp::instance()->clipboard()->hasFormat( QGSCLIPBOARD_MAPLAYER_MIME ) )
103-
{
104-
QAction *actionPasteLayerOrGroup = new QAction( tr( "Paste Layer/Group" ), menu );
105-
connect( actionPasteLayerOrGroup, &QAction::triggered, QgisApp::instance(), &QgisApp::pasteLayer );
106-
menu->addAction( actionPasteLayerOrGroup );
107-
}
108-
109-
menu->addAction( tr( "Save As Layer Definition File…" ), QgisApp::instance(), SLOT( saveAsLayerDefinition() ) );
115+
menu->addSeparator();
110116

111-
menu->addAction( actions->actionAddGroup( menu ) );
117+
QMenu *menuExportGroup = new QMenu( tr( "Export" ), menu );
118+
QAction *actionSaveAsDefinitionGroup = new QAction( tr( "Save as Layer Definition File…" ), menuExportGroup );
119+
connect( actionSaveAsDefinitionGroup, &QAction::triggered, QgisApp::instance(), &QgisApp::saveAsLayerDefinition );
120+
menuExportGroup->addAction( actionSaveAsDefinitionGroup );
121+
menu->addMenu( menuExportGroup );
112122
}
113123
else if ( QgsLayerTree::isLayer( node ) )
114124
{
@@ -122,6 +132,15 @@ QMenu *QgsAppLayerTreeViewMenuProvider::createContextMenu()
122132
menu->addAction( actions->actionShowInOverview( menu ) );
123133
}
124134

135+
if ( vlayer )
136+
menu->addAction( actions->actionShowFeatureCount( menu ) );
137+
138+
QAction *actionCopyLayer = new QAction( tr( "Copy Layer" ), menu );
139+
connect( actionCopyLayer, &QAction::triggered, QgisApp::instance(), &QgisApp::copyLayer );
140+
menu->addAction( actionCopyLayer );
141+
142+
menu->addAction( actions->actionRenameGroupOrLayer( menu ) );
143+
125144
if ( rlayer )
126145
{
127146
menu->addAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionZoomActual.svg" ) ), tr( "&Zoom to Native Resolution (100%)" ), QgisApp::instance(), SLOT( legendLayerZoomNative() ) );
@@ -130,100 +149,31 @@ QMenu *QgsAppLayerTreeViewMenuProvider::createContextMenu()
130149
menu->addAction( tr( "&Stretch Using Current Extent" ), QgisApp::instance(), SLOT( legendLayerStretchUsingCurrentExtent() ) );
131150
}
132151

133-
menu->addAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionRemoveLayer.svg" ) ), tr( "&Remove" ), QgisApp::instance(), SLOT( removeLayer() ) );
134-
135-
// duplicate layer
136-
QAction *duplicateLayersAction = menu->addAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionDuplicateLayer.svg" ) ), tr( "&Duplicate" ), QgisApp::instance(), SLOT( duplicateLayers() ) );
137-
138-
if ( layer && layer->isSpatial() )
152+
addCustomLayerActions( menu, layer );
153+
if ( layer && layer->type() == QgsMapLayer::VectorLayer && static_cast<QgsVectorLayer *>( layer )->providerType() == QLatin1String( "virtual" ) )
139154
{
140-
// set layer scale visibility
141-
menu->addAction( tr( "&Set Layer Scale Visibility" ), QgisApp::instance(), SLOT( setLayerScaleVisibility() ) );
142-
143-
if ( !layer->isInScaleRange( mCanvas->scale() ) )
144-
menu->addAction( tr( "Zoom to &Visible Scale" ), QgisApp::instance(), SLOT( zoomToLayerScale() ) );
145-
146-
QAction *checkAll = actions->actionCheckAndAllParents( menu );
147-
if ( checkAll )
148-
menu->addAction( checkAll );
149-
150-
// set layer crs
151-
menu->addAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionSetCRS.png" ) ), tr( "Set Layer CRS" ), QgisApp::instance(), SLOT( setLayerCrs() ) );
152-
153-
// assign layer crs to project
154-
menu->addAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionSetProjectCRS.png" ) ), tr( "Set &Project CRS from Layer" ), QgisApp::instance(), SLOT( setProjectCrsFromLayer() ) );
155+
menu->addAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionAddVirtualLayer.svg" ) ), tr( "Edit Virtual Layer…" ), QgisApp::instance(), SLOT( addVirtualLayer() ) );
155156
}
156157

157-
// style-related actions
158-
if ( layer && mView->selectedLayerNodes().count() == 1 )
159-
{
160-
QMenu *menuStyleManager = new QMenu( tr( "Styles" ), menu );
158+
menu->addSeparator();
161159

162-
QgisApp *app = QgisApp::instance();
163-
menuStyleManager->addAction( tr( "Copy Style" ), app, SLOT( copyStyle() ) );
164-
if ( app->clipboard()->hasFormat( QGSCLIPBOARD_STYLE_MIME ) )
165-
{
166-
menuStyleManager->addAction( tr( "Paste Style" ), app, SLOT( pasteStyle() ) );
167-
}
160+
// duplicate layer
161+
QAction *duplicateLayersAction = menu->addAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionDuplicateLayer.svg" ) ), tr( "&Duplicate" ), QgisApp::instance(), SLOT( duplicateLayers() ) );
162+
menu->addAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionRemoveLayer.svg" ) ), tr( "&Remove…" ), QgisApp::instance(), SLOT( removeLayer() ) );
168163

169-
menuStyleManager->addSeparator();
170-
QgsMapLayerStyleGuiUtils::instance()->addStyleManagerActions( menuStyleManager, layer );
164+
menu->addSeparator();
171165

172-
if ( vlayer )
173-
{
174-
const QgsSingleSymbolRenderer *singleRenderer = dynamic_cast< const QgsSingleSymbolRenderer * >( vlayer->renderer() );
175-
if ( !singleRenderer && vlayer->renderer() && vlayer->renderer()->embeddedRenderer() )
176-
{
177-
singleRenderer = dynamic_cast< const QgsSingleSymbolRenderer * >( vlayer->renderer()->embeddedRenderer() );
178-
}
179-
if ( singleRenderer && singleRenderer->symbol() )
180-
{
181-
//single symbol renderer, so add set color/edit symbol actions
182-
menuStyleManager->addSeparator();
183-
QgsColorWheel *colorWheel = new QgsColorWheel( menuStyleManager );
184-
colorWheel->setColor( singleRenderer->symbol()->color() );
185-
QgsColorWidgetAction *colorAction = new QgsColorWidgetAction( colorWheel, menuStyleManager, menuStyleManager );
186-
colorAction->setDismissOnColorSelection( false );
187-
connect( colorAction, &QgsColorWidgetAction::colorChanged, this, &QgsAppLayerTreeViewMenuProvider::setVectorSymbolColor );
188-
//store the layer id in action, so we can later retrieve the corresponding layer
189-
colorAction->setProperty( "layerId", vlayer->id() );
190-
menuStyleManager->addAction( colorAction );
166+
if ( node->parent() != mView->layerTreeModel()->rootGroup() )
167+
menu->addAction( actions->actionMakeTopLevel( menu ) );
191168

192-
//add recent colors action
193-
QList<QgsRecentColorScheme *> recentSchemes;
194-
QgsApplication::colorSchemeRegistry()->schemes( recentSchemes );
195-
if ( !recentSchemes.isEmpty() )
196-
{
197-
QgsColorSwatchGridAction *recentColorAction = new QgsColorSwatchGridAction( recentSchemes.at( 0 ), menuStyleManager, QStringLiteral( "symbology" ), menuStyleManager );
198-
recentColorAction->setProperty( "layerId", vlayer->id() );
199-
recentColorAction->setDismissOnColorSelection( false );
200-
menuStyleManager->addAction( recentColorAction );
201-
connect( recentColorAction, &QgsColorSwatchGridAction::colorChanged, this, &QgsAppLayerTreeViewMenuProvider::setVectorSymbolColor );
202-
}
169+
QAction *checkAll = actions->actionCheckAndAllParents( menu );
170+
if ( checkAll )
171+
menu->addAction( checkAll );
203172

204-
menuStyleManager->addSeparator();
205-
QAction *editSymbolAction = new QAction( tr( "Edit Symbol…" ), menuStyleManager );
206-
//store the layer id in action, so we can later retrieve the corresponding layer
207-
editSymbolAction->setProperty( "layerId", vlayer->id() );
208-
connect( editSymbolAction, &QAction::triggered, this, &QgsAppLayerTreeViewMenuProvider::editVectorSymbol );
209-
menuStyleManager->addAction( editSymbolAction );
210-
}
211-
}
212-
213-
menu->addMenu( menuStyleManager );
214-
}
215-
else
216-
{
217-
if ( QgisApp::instance()->clipboard()->hasFormat( QGSCLIPBOARD_STYLE_MIME ) )
218-
{
219-
menu->addAction( tr( "Paste Style" ), QgisApp::instance(), SLOT( applyStyleToGroup() ) );
220-
}
221-
}
173+
if ( mView->selectedNodes( true ).count() >= 2 )
174+
menu->addAction( actions->actionGroupSelected( menu ) );
222175

223176
menu->addSeparator();
224-
QAction *actionCopyLayer = new QAction( tr( "Copy Layer" ), menu );
225-
connect( actionCopyLayer, &QAction::triggered, QgisApp::instance(), &QgisApp::copyLayer );
226-
menu->addAction( actionCopyLayer );
227177

228178
if ( vlayer )
229179
{
@@ -263,11 +213,35 @@ QMenu *QgsAppLayerTreeViewMenuProvider::createContextMenu()
263213
QAction *action = menu->addAction( tr( "&Filter…" ), QgisApp::instance(), SLOT( layerSubsetString() ) );
264214
action->setEnabled( !vlayer->isEditable() );
265215
}
216+
}
266217

267-
menu->addAction( actions->actionShowFeatureCount( menu ) );
218+
menu->addSeparator();
268219

269-
menu->addSeparator();
220+
if ( layer && layer->isSpatial() )
221+
{
222+
// set layer scale visibility
223+
menu->addAction( tr( "&Set Layer Scale Visibility" ), QgisApp::instance(), SLOT( setLayerScaleVisibility() ) );
270224

225+
if ( !layer->isInScaleRange( mCanvas->scale() ) )
226+
menu->addAction( tr( "Zoom to &Visible Scale" ), QgisApp::instance(), SLOT( zoomToLayerScale() ) );
227+
228+
QMenu *menuSetCRS = new QMenu( tr( "Set CRS" ), menu );
229+
// set layer crs
230+
QAction *actionSetLayerCrs = new QAction( tr( "Set Layer CRS…" ), menuSetCRS );
231+
connect( actionSetLayerCrs, &QAction::triggered, QgisApp::instance(), &QgisApp::setLayerCrs );
232+
menuSetCRS->addAction( actionSetLayerCrs );
233+
// assign layer crs to project
234+
QAction *actionSetProjectCrs = new QAction( tr( "Set &Project CRS from Layer" ), menuSetCRS );
235+
connect( actionSetProjectCrs, &QAction::triggered, QgisApp::instance(), &QgisApp::setProjectCrsFromLayer );
236+
menuSetCRS->addAction( actionSetProjectCrs );
237+
238+
menu->addMenu( menuSetCRS );
239+
}
240+
241+
menu->addSeparator();
242+
243+
if ( vlayer )
244+
{
271245
// save as vector file
272246
QMenu *menuExportVector = new QMenu( tr( "Export" ), menu );
273247
QAction *actionSaveAs = new QAction( tr( "Save as…" ), menuExportVector );
@@ -297,34 +271,85 @@ QMenu *QgsAppLayerTreeViewMenuProvider::createContextMenu()
297271
connect( actionSaveStyle, &QAction::triggered, QgisApp::instance(), [ = ] { QgisApp::instance()->saveStyleFile(); } );
298272
menuExportRaster->addAction( actionSaveStyle );
299273
menu->addMenu( menuExportRaster );
300-
301-
menu->addSeparator();
302274
}
303275
else if ( layer && layer->type() == QgsMapLayer::PluginLayer && mView->selectedLayerNodes().count() == 1 )
304276
{
305277
// disable duplication of plugin layers
306278
duplicateLayersAction->setEnabled( false );
307279
}
308280

309-
addCustomLayerActions( menu, layer );
281+
menu->addSeparator();
310282

311-
if ( layer && QgsProject::instance()->layerIsEmbedded( layer->id() ).isEmpty() )
312-
menu->addAction( tr( "&Properties" ), QgisApp::instance(), SLOT( layerProperties() ) );
283+
// style-related actions
284+
if ( layer && mView->selectedLayerNodes().count() == 1 )
285+
{
286+
menu->addSeparator();
287+
QMenu *menuStyleManager = new QMenu( tr( "Styles" ), menu );
313288

314-
if ( node->parent() != mView->layerTreeModel()->rootGroup() )
315-
menu->addAction( actions->actionMakeTopLevel( menu ) );
289+
QgisApp *app = QgisApp::instance();
290+
menuStyleManager->addAction( tr( "Copy Style" ), app, SLOT( copyStyle() ) );
291+
if ( app->clipboard()->hasFormat( QGSCLIPBOARD_STYLE_MIME ) )
292+
{
293+
menuStyleManager->addAction( tr( "Paste Style" ), app, SLOT( pasteStyle() ) );
294+
}
316295

317-
menu->addAction( actions->actionRenameGroupOrLayer( menu ) );
296+
menuStyleManager->addSeparator();
297+
QgsMapLayerStyleGuiUtils::instance()->addStyleManagerActions( menuStyleManager, layer );
318298

319-
if ( mView->selectedNodes( true ).count() >= 2 )
320-
menu->addAction( actions->actionGroupSelected( menu ) );
299+
if ( vlayer )
300+
{
301+
const QgsSingleSymbolRenderer *singleRenderer = dynamic_cast< const QgsSingleSymbolRenderer * >( vlayer->renderer() );
302+
if ( !singleRenderer && vlayer->renderer() && vlayer->renderer()->embeddedRenderer() )
303+
{
304+
singleRenderer = dynamic_cast< const QgsSingleSymbolRenderer * >( vlayer->renderer()->embeddedRenderer() );
305+
}
306+
if ( singleRenderer && singleRenderer->symbol() )
307+
{
308+
//single symbol renderer, so add set color/edit symbol actions
309+
menuStyleManager->addSeparator();
310+
QgsColorWheel *colorWheel = new QgsColorWheel( menuStyleManager );
311+
colorWheel->setColor( singleRenderer->symbol()->color() );
312+
QgsColorWidgetAction *colorAction = new QgsColorWidgetAction( colorWheel, menuStyleManager, menuStyleManager );
313+
colorAction->setDismissOnColorSelection( false );
314+
connect( colorAction, &QgsColorWidgetAction::colorChanged, this, &QgsAppLayerTreeViewMenuProvider::setVectorSymbolColor );
315+
//store the layer id in action, so we can later retrieve the corresponding layer
316+
colorAction->setProperty( "layerId", vlayer->id() );
317+
menuStyleManager->addAction( colorAction );
321318

322-
if ( layer && layer->type() == QgsMapLayer::VectorLayer && static_cast<QgsVectorLayer *>( layer )->providerType() == QLatin1String( "virtual" ) )
319+
//add recent colors action
320+
QList<QgsRecentColorScheme *> recentSchemes;
321+
QgsApplication::colorSchemeRegistry()->schemes( recentSchemes );
322+
if ( !recentSchemes.isEmpty() )
323+
{
324+
QgsColorSwatchGridAction *recentColorAction = new QgsColorSwatchGridAction( recentSchemes.at( 0 ), menuStyleManager, QStringLiteral( "symbology" ), menuStyleManager );
325+
recentColorAction->setProperty( "layerId", vlayer->id() );
326+
recentColorAction->setDismissOnColorSelection( false );
327+
menuStyleManager->addAction( recentColorAction );
328+
connect( recentColorAction, &QgsColorSwatchGridAction::colorChanged, this, &QgsAppLayerTreeViewMenuProvider::setVectorSymbolColor );
329+
}
330+
331+
menuStyleManager->addSeparator();
332+
QAction *editSymbolAction = new QAction( tr( "Edit Symbol…" ), menuStyleManager );
333+
//store the layer id in action, so we can later retrieve the corresponding layer
334+
editSymbolAction->setProperty( "layerId", vlayer->id() );
335+
connect( editSymbolAction, &QAction::triggered, this, &QgsAppLayerTreeViewMenuProvider::editVectorSymbol );
336+
menuStyleManager->addAction( editSymbolAction );
337+
}
338+
}
339+
340+
menu->addMenu( menuStyleManager );
341+
}
342+
else
323343
{
324-
menu->addAction( tr( "Edit Virtual Layer…" ), QgisApp::instance(), SLOT( addVirtualLayer() ) );
344+
if ( QgisApp::instance()->clipboard()->hasFormat( QGSCLIPBOARD_STYLE_MIME ) )
345+
{
346+
menu->addAction( tr( "Paste Style" ), QgisApp::instance(), SLOT( applyStyleToGroup() ) );
347+
}
325348
}
326-
}
327349

350+
if ( layer && QgsProject::instance()->layerIsEmbedded( layer->id() ).isEmpty() )
351+
menu->addAction( tr( "&Properties…" ), QgisApp::instance(), SLOT( layerProperties() ) );
352+
}
328353
}
329354
else if ( QgsLayerTreeModelLegendNode *node = mView->layerTreeModel()->index2legendNode( idx ) )
330355
{

0 commit comments

Comments
 (0)