[FEATURE] Duplicate map layer(s)

- Action available in Layer menu and legend contextual menu
- Layer style copy/pasted to duplicate
- Memory and plugin layers skipped
- Add sip binding to action in app interface
This commit is contained in:
Larry Shaffer 2012-10-31 20:04:24 -06:00
parent 42104d7f3d
commit c11df1aa79
8 changed files with 102 additions and 0 deletions

View File

@ -364,6 +364,8 @@ class QgisInterface : QObject
virtual QAction *actionLayerSaveAs() = 0; virtual QAction *actionLayerSaveAs() = 0;
virtual QAction *actionLayerSelectionSaveAs() = 0; virtual QAction *actionLayerSelectionSaveAs() = 0;
virtual QAction *actionRemoveLayer() = 0; virtual QAction *actionRemoveLayer() = 0;
/** @note added in 2.0 */
virtual QAction *actionDuplicateLayer() = 0;
virtual QAction *actionLayerProperties() = 0; virtual QAction *actionLayerProperties() = 0;
virtual QAction *actionLayerSeparator2() = 0 /Deprecated/; virtual QAction *actionLayerSeparator2() = 0 /Deprecated/;
virtual QAction *actionAddToOverview() = 0; virtual QAction *actionAddToOverview() = 0;

View File

@ -430,6 +430,9 @@ void QgsLegendLayer::addToPopupMenu( QMenu& theMenu )
// remove from canvas // remove from canvas
theMenu.addAction( QgsApplication::getThemeIcon( "/mActionRemoveLayer.png" ), tr( "&Remove" ), QgisApp::instance(), SLOT( removeLayer() ) ); theMenu.addAction( QgsApplication::getThemeIcon( "/mActionRemoveLayer.png" ), tr( "&Remove" ), QgisApp::instance(), SLOT( removeLayer() ) );
// duplicate layer
theMenu.addAction( QgsApplication::getThemeIcon( "/mActionAddMap.png" ), tr( "&Duplicate" ), QgisApp::instance(), SLOT( duplicateLayers() ) );
// set layer crs // set layer crs
theMenu.addAction( QgsApplication::getThemeIcon( "/mActionSetCRS.png" ), tr( "&Set Layer CRS" ), QgisApp::instance(), SLOT( setLayerCRS() ) ); theMenu.addAction( QgsApplication::getThemeIcon( "/mActionSetCRS.png" ), tr( "&Set Layer CRS" ), QgisApp::instance(), SLOT( setLayerCRS() ) );

View File

@ -961,6 +961,7 @@ void QgisApp::createActions()
connect( mActionLayerSaveAs, SIGNAL( triggered() ), this, SLOT( saveAsFile() ) ); connect( mActionLayerSaveAs, SIGNAL( triggered() ), this, SLOT( saveAsFile() ) );
connect( mActionLayerSelectionSaveAs, SIGNAL( triggered() ), this, SLOT( saveSelectionAsVectorFile() ) ); connect( mActionLayerSelectionSaveAs, SIGNAL( triggered() ), this, SLOT( saveSelectionAsVectorFile() ) );
connect( mActionRemoveLayer, SIGNAL( triggered() ), this, SLOT( removeLayer() ) ); connect( mActionRemoveLayer, SIGNAL( triggered() ), this, SLOT( removeLayer() ) );
connect( mActionDuplicateLayer, SIGNAL( triggered() ), this, SLOT( duplicateLayers() ) );
connect( mActionSetLayerCRS, SIGNAL( triggered() ), this, SLOT( setLayerCRS() ) ); connect( mActionSetLayerCRS, SIGNAL( triggered() ), this, SLOT( setLayerCRS() ) );
connect( mActionSetProjectCRSFromLayer, SIGNAL( triggered() ), this, SLOT( setProjectCRSFromLayer() ) ); connect( mActionSetProjectCRSFromLayer, SIGNAL( triggered() ), this, SLOT( setProjectCRSFromLayer() ) );
connect( mActionLayerProperties, SIGNAL( triggered() ), this, SLOT( layerProperties() ) ); connect( mActionLayerProperties, SIGNAL( triggered() ), this, SLOT( layerProperties() ) );
@ -1630,6 +1631,7 @@ void QgisApp::setTheme( QString theThemeName )
mActionAddMssqlLayer->setIcon( QgsApplication::getThemeIcon( "/mActionAddMssqlLayer.png" ) ); mActionAddMssqlLayer->setIcon( QgsApplication::getThemeIcon( "/mActionAddMssqlLayer.png" ) );
#endif #endif
mActionRemoveLayer->setIcon( QgsApplication::getThemeIcon( "/mActionRemoveLayer.png" ) ); mActionRemoveLayer->setIcon( QgsApplication::getThemeIcon( "/mActionRemoveLayer.png" ) );
mActionDuplicateLayer->setIcon( QgsApplication::getThemeIcon( "/mActionAddMap.png" ) );
mActionSetLayerCRS->setIcon( QgsApplication::getThemeIcon( "/mActionSetLayerCRS.png" ) ); mActionSetLayerCRS->setIcon( QgsApplication::getThemeIcon( "/mActionSetLayerCRS.png" ) );
mActionSetProjectCRSFromLayer->setIcon( QgsApplication::getThemeIcon( "/mActionSetProjectCRSFromLayer.png" ) ); mActionSetProjectCRSFromLayer->setIcon( QgsApplication::getThemeIcon( "/mActionSetProjectCRSFromLayer.png" ) );
mActionNewVectorLayer->setIcon( QgsApplication::getThemeIcon( "/mActionNewVectorLayer.png" ) ); mActionNewVectorLayer->setIcon( QgsApplication::getThemeIcon( "/mActionNewVectorLayer.png" ) );
@ -5341,6 +5343,77 @@ void QgisApp::removeLayer()
mMapCanvas->refresh(); mMapCanvas->refresh();
} }
void QgisApp::duplicateLayers( QList<QgsMapLayer *> lyrList )
{
if ( mMapCanvas && mMapCanvas->isDrawing() )
{
return;
}
if ( !mMapLegend )
{
return;
}
QList<QgsMapLayer *> selectedLyrs = lyrList.empty() ? mMapLegend->selectedLayers() : lyrList;
if ( selectedLyrs.empty() )
{
return;
}
mMapCanvas->freeze();
QgsMapLayer *dupLayer;
foreach ( QgsMapLayer * selectedLyr, selectedLyrs )
{
dupLayer = 0;
QString layerDupName = selectedLyr->name() + " " + tr( "copy" );
// duplicate the layer's basic parameters
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer*>( selectedLyr );
// TODO: check for other layer types that won't duplicate correctly
// currently memory and plugin layers are skipped
if ( vlayer && vlayer->storageType() != "Memory storage" )
{
dupLayer = new QgsVectorLayer( vlayer->source(), layerDupName, vlayer->providerType() );
}
if ( !dupLayer )
{
QgsRasterLayer *rlayer = qobject_cast<QgsRasterLayer*>( selectedLyr );
if ( rlayer )
{
dupLayer = new QgsRasterLayer( rlayer->source(), layerDupName );
}
}
if ( dupLayer && !dupLayer->isValid() )
{
QgsDebugMsg( "Duplicated layer was invalid" );
continue;
}
if ( !dupLayer )
{
QMessageBox::information( this,
tr( "Unsupported Layer" ),
tr( "%1\n\nDuplication of layer type is unsupported." ).arg( selectedLyr->name() ) );
continue;
}
// add layer to project and layer registry
addMapLayer( dupLayer );
// duplicate the layer style
copyStyle( selectedLyr );
pasteStyle( dupLayer );
}
dupLayer = 0;
mMapCanvas->freeze( false );
mMapCanvas->refresh();
}
void QgisApp::setLayerCRS() void QgisApp::setLayerCRS()
{ {
if ( mMapCanvas && mMapCanvas->isDrawing() ) if ( mMapCanvas && mMapCanvas->isDrawing() )
@ -6833,6 +6906,7 @@ void QgisApp::selectionChanged( QgsMapLayer *layer )
void QgisApp::legendLayerSelectionChanged( void ) void QgisApp::legendLayerSelectionChanged( void )
{ {
mActionRemoveLayer->setEnabled( mMapLegend && mMapLegend->selectedLayers().size() > 0 ); mActionRemoveLayer->setEnabled( mMapLegend && mMapLegend->selectedLayers().size() > 0 );
mActionDuplicateLayer->setEnabled( mMapLegend && mMapLegend->selectedLayers().size() > 0 );
mActionSetLayerCRS->setEnabled( mMapLegend && mMapLegend->selectedLayers().size() > 0 ); mActionSetLayerCRS->setEnabled( mMapLegend && mMapLegend->selectedLayers().size() > 0 );
mActionSetProjectCRSFromLayer->setEnabled( mMapLegend && mMapLegend->selectedLayers().size() == 1 ); mActionSetProjectCRSFromLayer->setEnabled( mMapLegend && mMapLegend->selectedLayers().size() == 1 );
} }

View File

@ -290,6 +290,8 @@ class QgisApp : public QMainWindow, private Ui::MainWindow
QAction *actionLayerSaveAs() { return mActionLayerSaveAs; } QAction *actionLayerSaveAs() { return mActionLayerSaveAs; }
QAction *actionLayerSelectionSaveAs() { return mActionLayerSelectionSaveAs; } QAction *actionLayerSelectionSaveAs() { return mActionLayerSelectionSaveAs; }
QAction *actionRemoveLayer() { return mActionRemoveLayer; } QAction *actionRemoveLayer() { return mActionRemoveLayer; }
/** @note added in 2.0 */
QAction *actionDuplicateLayer() { return mActionDuplicateLayer; }
QAction *actionSetLayerCRS() { return mActionSetLayerCRS; } QAction *actionSetLayerCRS() { return mActionSetLayerCRS; }
QAction *actionSetProjectCRSFromLayer() { return mActionSetProjectCRSFromLayer; } QAction *actionSetProjectCRSFromLayer() { return mActionSetProjectCRSFromLayer; }
QAction *actionLayerProperties() { return mActionLayerProperties; } QAction *actionLayerProperties() { return mActionLayerProperties; }
@ -543,6 +545,9 @@ class QgisApp : public QMainWindow, private Ui::MainWindow
void userCenter(); void userCenter();
//! Remove a layer from the map and legend //! Remove a layer from the map and legend
void removeLayer(); void removeLayer();
/** Duplicate map layer(s) in legend
* @note added in 2.0 */
void duplicateLayers( const QList<QgsMapLayer *> lyrList = QList<QgsMapLayer *>() );
//! Set CRS of a layer //! Set CRS of a layer
void setLayerCRS(); void setLayerCRS();
//! Assign layer CRS to project //! Assign layer CRS to project

View File

@ -465,6 +465,7 @@ QAction *QgisAppInterface::actionToggleEditing() { return qgis->actionToggleEdit
QAction *QgisAppInterface::actionLayerSaveAs() { return qgis->actionLayerSaveAs(); } QAction *QgisAppInterface::actionLayerSaveAs() { return qgis->actionLayerSaveAs(); }
QAction *QgisAppInterface::actionLayerSelectionSaveAs() { return qgis->actionLayerSelectionSaveAs(); } QAction *QgisAppInterface::actionLayerSelectionSaveAs() { return qgis->actionLayerSelectionSaveAs(); }
QAction *QgisAppInterface::actionRemoveLayer() { return qgis->actionRemoveLayer(); } QAction *QgisAppInterface::actionRemoveLayer() { return qgis->actionRemoveLayer(); }
QAction *QgisAppInterface::actionDuplicateLayer() { return qgis->actionDuplicateLayer(); }
QAction *QgisAppInterface::actionLayerProperties() { return qgis->actionLayerProperties(); } QAction *QgisAppInterface::actionLayerProperties() { return qgis->actionLayerProperties(); }
QAction *QgisAppInterface::actionLayerSeparator2() { return 0; } QAction *QgisAppInterface::actionLayerSeparator2() { return 0; }
QAction *QgisAppInterface::actionAddToOverview() { return qgis->actionAddToOverview(); } QAction *QgisAppInterface::actionAddToOverview() { return qgis->actionAddToOverview(); }

View File

@ -313,6 +313,8 @@ class QgisAppInterface : public QgisInterface
virtual QAction *actionLayerSaveAs(); virtual QAction *actionLayerSaveAs();
virtual QAction *actionLayerSelectionSaveAs(); virtual QAction *actionLayerSelectionSaveAs();
virtual QAction *actionRemoveLayer(); virtual QAction *actionRemoveLayer();
/** @note added in 2.0 */
virtual QAction *actionDuplicateLayer();
virtual QAction *actionLayerProperties(); virtual QAction *actionLayerProperties();
virtual QAction *actionLayerSeparator2(); virtual QAction *actionLayerSeparator2();
virtual QAction *actionAddToOverview(); virtual QAction *actionAddToOverview();

View File

@ -466,6 +466,8 @@ class GUI_EXPORT QgisInterface : public QObject
virtual QAction *actionLayerSaveAs() = 0; virtual QAction *actionLayerSaveAs() = 0;
virtual QAction *actionLayerSelectionSaveAs() = 0; virtual QAction *actionLayerSelectionSaveAs() = 0;
virtual QAction *actionRemoveLayer() = 0; virtual QAction *actionRemoveLayer() = 0;
/** @note added in 2.0 */
virtual QAction *actionDuplicateLayer() = 0;
virtual QAction *actionLayerProperties() = 0; virtual QAction *actionLayerProperties() = 0;
#ifndef Q_MOC_RUN #ifndef Q_MOC_RUN
Q_DECL_DEPRECATED Q_DECL_DEPRECATED

View File

@ -168,6 +168,7 @@
<addaction name="mActionLayerSaveAs"/> <addaction name="mActionLayerSaveAs"/>
<addaction name="mActionLayerSelectionSaveAs"/> <addaction name="mActionLayerSelectionSaveAs"/>
<addaction name="mActionRemoveLayer"/> <addaction name="mActionRemoveLayer"/>
<addaction name="mActionDuplicateLayer"/>
<addaction name="mActionSetLayerCRS"/> <addaction name="mActionSetLayerCRS"/>
<addaction name="mActionSetProjectCRSFromLayer"/> <addaction name="mActionSetProjectCRSFromLayer"/>
<addaction name="mActionLayerProperties"/> <addaction name="mActionLayerProperties"/>
@ -1821,6 +1822,18 @@ Acts on currently active editable layer</string>
<string>Html Annotation</string> <string>Html Annotation</string>
</property> </property>
</action> </action>
<action name="mActionDuplicateLayer">
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/mActionAddMap.png</normaloff>:/images/themes/default/mActionAddMap.png</iconset>
</property>
<property name="text">
<string>Duplicate Layer(s)</string>
</property>
<property name="toolTip">
<string>Duplicate Layer(s)</string>
</property>
</action>
</widget> </widget>
<resources> <resources>
<include location="../../images/images.qrc"/> <include location="../../images/images.qrc"/>