Bug report #18591

"Duplicate layers" action does not work with memory layer

Added by Harrissou Santanna over 1 year ago. Updated 10 months ago.

Status:Open
Priority:Normal
Assignee:-
Category:Map Legend
Affected QGIS version:3.4.4 Regression?:No
Operating System: Easy fix?:No
Pull Request or Patch supplied:No Resolution:
Crashes QGIS or corrupts data:No Copied to github as #:26479

Description

create a temporary layer (i used centroids alg on a layer)
right-click on the layer: the "Duplicate layer" action is grayed.
Click on Layer menu, the "Duplicate Layer(s)" action is NOT grayed. (Btw, it could be nice to have the same label). Click on that menu action, nothing happens. That tool however works if you use a not memory layer.

Also, you can however use the Copy and Paste layer actions in the Layer menu to duplicate the memory layer.

History

#1 Updated by Andrea Giudiceandrea 10 months ago

  • Affected QGIS version changed from 3.1(master) to 3.4.4

Confirmed in 3.4.4 and master (3.5 407adc761e).

It seems that QgisApp::duplicateLayers cannot duplicate memory layers (and plugin layers):

https://github.com/qgis/QGIS/blob/master/src/app/qgisapp.cpp#L10059

void QgisApp::duplicateLayers( const QList<QgsMapLayer *> &lyrList )
[...]
// currently memory and plugin layers are skipped

So it's correct that the "Duplicate layer" action is greyed out in the contextual menu of a memory layer. while it's incorrect that is not greyed out in the "Layer" menu.

This inconsistent behaviour seems to lay in different logic applied in createContextMenu() and legendLayerSelectionChanged().

In the the first case, the "Duplicate layer" action is disabled if the layer is of memory or plugin type
https://github.com/qgis/QGIS/blob/master/src/app/qgsapplayertreeviewmenuprovider.cpp#L234-L235

        if ( vlayer->storageType() == QLatin1String( "Memory storage" ) && mView->selectedLayerNodes().count() == 1 )
          duplicateLayersAction->setEnabled( false );

https://github.com/qgis/QGIS/blob/master/src/app/qgsapplayertreeviewmenuprovider.cpp#L331-L335
      else if ( layer && layer->type() == QgsMapLayer::PluginLayer && mView->selectedLayerNodes().count() == 1 )
      {
        // disable duplication of plugin layers
        duplicateLayersAction->setEnabled( false );
      }

in the latter case, the menu item is disabled only if the there are no layers selected
https://github.com/qgis/QGIS/blob/master/src/app/qgsapplayertreeviewmenuprovider.cpp#L331-L335

  mActionDuplicateLayer->setEnabled( !selectedLayers.isEmpty() );

In order to make the behaviour consistent, I think it should be sufficient to change the line this way (not tested):
  mActionDuplicateLayer->setEnabled( selectedLayers.count() == 1 && selectedLayers.front().type() != QgsMapLayer::PluginLayer && selectedLayers.front().providerType() != QLatin1String( "memory" ) || !selectedLayers.isEmpty() );

or

if ( selectedLayers.count() == 1 )
  mActionDuplicateLayer->setEnabled( selectedLayers.front().type() != QgsMapLayer::PluginLayer && selectedLayers.front().providerType() != QLatin1String( "Memory storage" ) )
else
  mActionDuplicateLayer->setEnabled( !selectedLayers.isEmpty() )

Also available in: Atom PDF