void QgsLegendLayer::updateIcon() { QPixmap newIcon( getOriginalPixmap() ); QgsMapLayer* theLayer = layer(); //overview // FIXME: overview icon is missing /* if ( theFile->isInOverview() ) { // Overlay the overview icon on the default icon QPixmap myPixmap = QgsApplication::getThemePixmap( "/mIconOverview.png" ); QPainter p( &newIcon ); p.drawPixmap( 0, 0, myPixmap ); p.end(); }*/ //editable if ( theLayer->isEditable() ) { QPixmap myPixmap; QgsVectorLayer* vlayer = qobject_cast<QgsVectorLayer *>( theLayer ); if ( vlayer->isModified() ) { myPixmap = QgsApplication::getThemePixmap( "/mIconEditableEdits.png" ); } else { myPixmap = QgsApplication::getThemePixmap( "/mIconEditable.png" ); } // use editable icon instead of the layer's type icon newIcon = myPixmap; // Overlay the editable icon on the default icon /*QPainter p( &newIcon ); p.drawPixmap( 0, 0, myPixmap ); p.end();*/ } // TODO: projection error icon? QIcon theIcon( newIcon ); QgsLegend* l = legend(); if ( l ) { l->blockSignals( true ); //prevent unnecessary canvas redraw } setIcon( 0, theIcon ); if ( l ) { l->blockSignals( false ); } }
bool QgsLayerTreeUtils::layersModified( const QList<QgsLayerTreeLayer *> &layerNodes ) { const auto constLayerNodes = layerNodes; for ( QgsLayerTreeLayer *layerNode : constLayerNodes ) { QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layerNode->layer() ); if ( !vl ) continue; if ( vl->isEditable() && vl->isModified() ) return true; } return false; }
void QgsLegendLayer::addToPopupMenu( QMenu& theMenu ) { QgsMapLayer *lyr = layer(); QAction *toggleEditingAction = QgisApp::instance()->actionToggleEditing(); QAction *saveLayerEditsAction = QgisApp::instance()->actionSaveActiveLayerEdits(); QAction *allEditsAction = QgisApp::instance()->actionAllEdits(); // zoom to layer extent theMenu.addAction( QgsApplication::getThemeIcon( "/mActionZoomToLayer.svg" ), tr( "&Zoom to Layer Extent" ), legend(), SLOT( legendLayerZoom() ) ); if ( lyr->type() == QgsMapLayer::RasterLayer ) { theMenu.addAction( tr( "&Zoom to Best Scale (100%)" ), legend(), SLOT( legendLayerZoomNative() ) ); QgsRasterLayer *rasterLayer = qobject_cast<QgsRasterLayer *>( lyr ); if ( rasterLayer && rasterLayer->rasterType() != QgsRasterLayer::Palette ) { theMenu.addAction( tr( "&Stretch Using Current Extent" ), legend(), SLOT( legendLayerStretchUsingCurrentExtent() ) ); } } // show in overview QAction* showInOverviewAction = theMenu.addAction( tr( "&Show in Overview" ), this, SLOT( showInOverview() ) ); showInOverviewAction->setCheckable( true ); showInOverviewAction->blockSignals( true ); showInOverviewAction->setChecked( mLyr.isInOverview() ); showInOverviewAction->blockSignals( false ); // remove from canvas theMenu.addAction( QgsApplication::getThemeIcon( "/mActionRemoveLayer.svg" ), tr( "&Remove" ), QgisApp::instance(), SLOT( removeLayer() ) ); // duplicate layer QAction* duplicateLayersAction = theMenu.addAction( QgsApplication::getThemeIcon( "/mActionDuplicateLayer.svg" ), tr( "&Duplicate" ), QgisApp::instance(), SLOT( duplicateLayers() ) ); // set layer crs theMenu.addAction( QgsApplication::getThemeIcon( "/mActionSetCRS.png" ), tr( "&Set Layer CRS" ), QgisApp::instance(), SLOT( setLayerCRS() ) ); // assign layer crs to project theMenu.addAction( QgsApplication::getThemeIcon( "/mActionSetProjectCRS.png" ), tr( "Set &Project CRS from Layer" ), QgisApp::instance(), SLOT( setProjectCRSFromLayer() ) ); theMenu.addSeparator(); if ( lyr->type() == QgsMapLayer::VectorLayer ) { QgsVectorLayer* vlayer = qobject_cast<QgsVectorLayer *>( lyr ); // attribute table theMenu.addAction( QgsApplication::getThemeIcon( "/mActionOpenTable.png" ), tr( "&Open Attribute Table" ), QgisApp::instance(), SLOT( attributeTable() ) ); // allow editing int cap = vlayer->dataProvider()->capabilities(); if ( cap & QgsVectorDataProvider::EditingCapabilities ) { if ( toggleEditingAction ) { theMenu.addAction( toggleEditingAction ); toggleEditingAction->setChecked( vlayer->isEditable() ); } if ( saveLayerEditsAction && vlayer->isModified() ) { theMenu.addAction( saveLayerEditsAction ); } } if ( allEditsAction->isEnabled() ) { theMenu.addAction( allEditsAction ); } // disable duplication of memory layers if ( vlayer->storageType() == "Memory storage" && legend()->selectedLayers().count() == 1 ) { duplicateLayersAction->setEnabled( false ); } // save as vector file theMenu.addAction( tr( "Save As..." ), QgisApp::instance(), SLOT( saveAsFile() ) ); // save selection as vector file QAction* saveSelectionAsAction = theMenu.addAction( tr( "Save Selection As..." ), QgisApp::instance(), SLOT( saveSelectionAsVectorFile() ) ); if ( vlayer->selectedFeatureCount() == 0 ) { saveSelectionAsAction->setEnabled( false ); } if ( !vlayer->isEditable() && vlayer->dataProvider()->supportsSubsetString() && vlayer->vectorJoins().isEmpty() ) theMenu.addAction( tr( "&Filter..." ), QgisApp::instance(), SLOT( layerSubsetString() ) ); //show number of features in legend if requested QAction* showNFeaturesAction = new QAction( tr( "Show Feature Count" ), &theMenu ); showNFeaturesAction->setCheckable( true ); showNFeaturesAction->setChecked( mShowFeatureCount ); QObject::connect( showNFeaturesAction, SIGNAL( toggled( bool ) ), this, SLOT( setShowFeatureCount( bool ) ) ); theMenu.addAction( showNFeaturesAction ); theMenu.addSeparator(); }
QVariant QgsLayerTreeModel::data( const QModelIndex &index, int role ) const { if ( !index.isValid() ) return QVariant(); if ( QgsLayerTreeModelLegendNode* sym = index2symnode( index ) ) { if ( role == Qt::CheckStateRole && !testFlag( AllowSymbologyChangeState ) ) return QVariant(); return sym->data( role ); } QgsLayerTreeNode* node = index2node( index ); if ( role == Qt::DisplayRole || role == Qt::EditRole ) { if ( QgsLayerTree::isGroup( node ) ) return QgsLayerTree::toGroup( node )->name(); else if ( QgsLayerTree::isLayer( node ) ) { QgsLayerTreeLayer* nodeLayer = QgsLayerTree::toLayer( node ); QString name = nodeLayer->layerName(); if ( nodeLayer->customProperty( "showFeatureCount", 0 ).toInt() && role == Qt::DisplayRole ) { QgsVectorLayer* vlayer = qobject_cast<QgsVectorLayer*>( nodeLayer->layer() ); if ( vlayer && vlayer->pendingFeatureCount() >= 0 ) name += QString( " [%1]" ).arg( vlayer->pendingFeatureCount() ); } return name; } } else if ( role == Qt::DecorationRole && index.column() == 0 ) { if ( QgsLayerTree::isGroup( node ) ) return iconGroup(); else if ( QgsLayerTree::isLayer( node ) ) { QgsLayerTreeLayer* nodeLayer = QgsLayerTree::toLayer( node ); // if there's just on legend entry that should be embedded in layer - do that! if ( testFlag( ShowSymbology ) && mSymbologyNodes[nodeLayer].count() == 1 && mSymbologyNodes[nodeLayer][0]->isEmbeddedInParent() ) return mSymbologyNodes[nodeLayer][0]->data( Qt::DecorationRole ); QgsMapLayer* layer = QgsLayerTree::toLayer( node )->layer(); if ( !layer ) return QVariant(); if ( layer->type() == QgsMapLayer::RasterLayer ) { if ( testFlag( ShowRasterPreviewIcon ) ) { QgsRasterLayer* rlayer = qobject_cast<QgsRasterLayer *>( layer ); return QIcon( rlayer->previewAsPixmap( QSize( 32, 32 ) ) ); } else return QgsLayerItem::iconRaster(); } else if ( layer->type() == QgsMapLayer::VectorLayer ) { QgsVectorLayer* vlayer = static_cast<QgsVectorLayer*>( layer ); if ( vlayer->isEditable() ) { if ( vlayer->isModified() ) return QIcon( QgsApplication::getThemePixmap( "/mIconEditableEdits.png" ) ); else return QIcon( QgsApplication::getThemePixmap( "/mIconEditable.png" ) ); } if ( vlayer->geometryType() == QGis::Point ) return QgsLayerItem::iconPoint(); else if ( vlayer->geometryType() == QGis::Line ) return QgsLayerItem::iconLine(); else if ( vlayer->geometryType() == QGis::Polygon ) return QgsLayerItem::iconPolygon(); else if ( vlayer->geometryType() == QGis::NoGeometry ) return QgsLayerItem::iconTable(); } return QgsLayerItem::iconDefault(); } } else if ( role == Qt::CheckStateRole ) { if ( !testFlag( AllowNodeChangeVisibility ) ) return QVariant(); if ( QgsLayerTree::isLayer( node ) ) { QgsLayerTreeLayer* nodeLayer = QgsLayerTree::toLayer( node ); if ( nodeLayer->layer() && nodeLayer->layer()->type() == QgsMapLayer::VectorLayer ) { if ( qobject_cast<QgsVectorLayer*>( nodeLayer->layer() )->geometryType() == QGis::NoGeometry ) return QVariant(); // do not show checkbox for non-spatial tables } return nodeLayer->isVisible(); } else if ( QgsLayerTree::isGroup( node ) ) { QgsLayerTreeGroup* nodeGroup = QgsLayerTree::toGroup( node ); return nodeGroup->isVisible(); } } else if ( role == Qt::FontRole ) { QFont f( QgsLayerTree::isLayer( node ) ? mFontLayer : ( QgsLayerTree::isGroup( node ) ? mFontGroup : QFont() ) ); if ( node->customProperty( "embedded" ).toInt() ) f.setItalic( true ); if ( index == mCurrentIndex ) f.setUnderline( true ); return f; } else if ( role == Qt::ToolTipRole ) { if ( QgsLayerTree::isLayer( node ) ) { if ( QgsMapLayer* layer = QgsLayerTree::toLayer( node )->layer() ) return layer->publicSource(); } } return QVariant(); }
QVariant QgsLayerTreeModel::data( const QModelIndex &index, int role ) const { if ( !index.isValid() || index.column() > 1 ) return QVariant(); if ( QgsLayerTreeModelLegendNode* sym = index2legendNode( index ) ) return legendNodeData( sym, role ); QgsLayerTreeNode* node = index2node( index ); if ( role == Qt::DisplayRole || role == Qt::EditRole ) { if ( QgsLayerTree::isGroup( node ) ) return QgsLayerTree::toGroup( node )->name(); if ( QgsLayerTree::isLayer( node ) ) { QgsLayerTreeLayer* nodeLayer = QgsLayerTree::toLayer( node ); QString name = nodeLayer->layerName(); if ( nodeLayer->customProperty( "showFeatureCount", 0 ).toInt() && role == Qt::DisplayRole ) { QgsVectorLayer* vlayer = qobject_cast<QgsVectorLayer*>( nodeLayer->layer() ); if ( vlayer && vlayer->featureCount() >= 0 ) name += QString( " [%1]" ).arg( vlayer->featureCount() ); } return name; } } else if ( role == Qt::DecorationRole && index.column() == 0 ) { if ( QgsLayerTree::isGroup( node ) ) return iconGroup(); if ( QgsLayerTree::isLayer( node ) ) { QgsLayerTreeLayer *nodeLayer = QgsLayerTree::toLayer( node ); QgsMapLayer *layer = nodeLayer->layer(); if ( !layer ) return QVariant(); // icons possibly overriding default icon if ( layer->type() == QgsMapLayer::RasterLayer ) { if ( testFlag( ShowRasterPreviewIcon ) ) { QgsRasterLayer* rlayer = qobject_cast<QgsRasterLayer *>( layer ); return QIcon( QPixmap::fromImage( rlayer->previewAsImage( QSize( 32, 32 ) ) ) ); } else { return QgsLayerItem::iconRaster(); } } QgsVectorLayer *vlayer = dynamic_cast<QgsVectorLayer*>( layer ); QIcon icon; // if there's just on legend entry that should be embedded in layer - do that! if ( testFlag( ShowLegend ) && legendEmbeddedInParent( nodeLayer ) ) { icon = legendIconEmbeddedInParent( nodeLayer ); } else if ( vlayer && layer->type() == QgsMapLayer::VectorLayer ) { if ( vlayer->geometryType() == QGis::Point ) icon = QgsLayerItem::iconPoint(); else if ( vlayer->geometryType() == QGis::Line ) icon = QgsLayerItem::iconLine(); else if ( vlayer->geometryType() == QGis::Polygon ) icon = QgsLayerItem::iconPolygon(); else if ( vlayer->geometryType() == QGis::NoGeometry ) icon = QgsLayerItem::iconTable(); else icon = QgsLayerItem::iconDefault(); } if ( vlayer && vlayer->isEditable() ) { QPixmap pixmap( icon.pixmap( 16, 16 ) ); QPainter painter( &pixmap ); painter.drawPixmap( 0, 0, 16, 16, QgsApplication::getThemePixmap( vlayer->isModified() ? "/mIconEditableEdits.png" : "/mIconEditable.png" ) ); painter.end(); icon = QIcon( pixmap ); } return icon; } } else if ( role == Qt::CheckStateRole ) { if ( !testFlag( AllowNodeChangeVisibility ) ) return QVariant(); if ( QgsLayerTree::isLayer( node ) ) { QgsLayerTreeLayer* nodeLayer = QgsLayerTree::toLayer( node ); if ( nodeLayer->layer() && nodeLayer->layer()->type() == QgsMapLayer::VectorLayer ) { if ( qobject_cast<QgsVectorLayer*>( nodeLayer->layer() )->geometryType() == QGis::NoGeometry ) return QVariant(); // do not show checkbox for non-spatial tables } return nodeLayer->isVisible(); } else if ( QgsLayerTree::isGroup( node ) ) { QgsLayerTreeGroup* nodeGroup = QgsLayerTree::toGroup( node ); return nodeGroup->isVisible(); } } else if ( role == Qt::FontRole ) { QFont f( QgsLayerTree::isLayer( node ) ? mFontLayer : ( QgsLayerTree::isGroup( node ) ? mFontGroup : QFont() ) ); if ( node->customProperty( "embedded" ).toInt() ) f.setItalic( true ); if ( index == mCurrentIndex ) f.setUnderline( true ); return f; } else if ( role == Qt::ToolTipRole ) { if ( QgsLayerTree::isLayer( node ) ) { if ( QgsMapLayer* layer = QgsLayerTree::toLayer( node )->layer() ) return layer->publicSource(); } } return QVariant(); }
QMenu* QgsAppLayerTreeViewMenuProvider::createContextMenu() { QMenu* menu = new QMenu; QgsLayerTreeViewDefaultActions* actions = mView->defaultActions(); QModelIndex idx = mView->currentIndex(); if ( !idx.isValid() ) { // global menu menu->addAction( actions->actionAddGroup( menu ) ); // TODO: expand all, collapse all // TODO: update drawing order } else if ( QgsLayerTreeNode* node = mView->layerTreeModel()->index2node( idx ) ) { // layer or group selected if ( QgsLayerTree::isGroup( node ) ) { menu->addAction( actions->actionZoomToGroup( mCanvas, menu ) ); menu->addAction( actions->actionRemoveGroupOrLayer( menu ) ); menu->addAction( QgsApplication::getThemeIcon( "/mActionSetCRS.png" ), tr( "&Set Group CRS" ), QgisApp::instance(), SLOT( legendGroupSetCRS() ) ); menu->addAction( actions->actionRenameGroupOrLayer( menu ) ); if ( mView->selectedNodes( true ).count() >= 2 ) menu->addAction( actions->actionGroupSelected( menu ) ); menu->addAction( actions->actionAddGroup( menu ) ); } else if ( QgsLayerTree::isLayer( node ) ) { QgsMapLayer* layer = QgsLayerTree::toLayer( node )->layer(); menu->addAction( actions->actionZoomToLayer( mCanvas, menu ) ); menu->addAction( actions->actionShowInOverview( menu ) ); if ( layer && layer->type() == QgsMapLayer::RasterLayer ) { menu->addAction( tr( "&Zoom to Best Scale (100%)" ), QgisApp::instance(), SLOT( legendLayerZoomNative() ) ); QgsRasterLayer* rasterLayer = qobject_cast<QgsRasterLayer *>( layer ); if ( rasterLayer && rasterLayer->rasterType() != QgsRasterLayer::Palette ) menu->addAction( tr( "&Stretch Using Current Extent" ), QgisApp::instance(), SLOT( legendLayerStretchUsingCurrentExtent() ) ); } menu->addAction( actions->actionRemoveGroupOrLayer( menu ) ); // duplicate layer QAction* duplicateLayersAction = menu->addAction( QgsApplication::getThemeIcon( "/mActionDuplicateLayer.svg" ), tr( "&Duplicate" ), QgisApp::instance(), SLOT( duplicateLayers() ) ); // set layer scale visibility menu->addAction( tr( "&Set Layer Scale Visibility" ), QgisApp::instance(), SLOT( setLayerScaleVisibility() ) ); // set layer crs menu->addAction( QgsApplication::getThemeIcon( "/mActionSetCRS.png" ), tr( "&Set Layer CRS" ), QgisApp::instance(), SLOT( setLayerCRS() ) ); // assign layer crs to project menu->addAction( QgsApplication::getThemeIcon( "/mActionSetProjectCRS.png" ), tr( "Set &Project CRS from Layer" ), QgisApp::instance(), SLOT( setProjectCRSFromLayer() ) ); menu->addSeparator(); if ( layer && layer->type() == QgsMapLayer::VectorLayer ) { QgsVectorLayer* vlayer = qobject_cast<QgsVectorLayer *>( layer ); QAction *toggleEditingAction = QgisApp::instance()->actionToggleEditing(); QAction *saveLayerEditsAction = QgisApp::instance()->actionSaveActiveLayerEdits(); QAction *allEditsAction = QgisApp::instance()->actionAllEdits(); // attribute table menu->addAction( QgsApplication::getThemeIcon( "/mActionOpenTable.png" ), tr( "&Open Attribute Table" ), QgisApp::instance(), SLOT( attributeTable() ) ); // allow editing int cap = vlayer->dataProvider()->capabilities(); if ( cap & QgsVectorDataProvider::EditingCapabilities ) { if ( toggleEditingAction ) { menu->addAction( toggleEditingAction ); toggleEditingAction->setChecked( vlayer->isEditable() ); } if ( saveLayerEditsAction && vlayer->isModified() ) { menu->addAction( saveLayerEditsAction ); } } if ( allEditsAction->isEnabled() ) menu->addAction( allEditsAction ); // disable duplication of memory layers if ( vlayer->storageType() == "Memory storage" && mView->selectedLayerNodes().count() == 1 ) duplicateLayersAction->setEnabled( false ); // save as vector file menu->addAction( tr( "Save As..." ), QgisApp::instance(), SLOT( saveAsFile() ) ); menu->addAction( tr( "Save As Layer Definition File..." ), QgisApp::instance(), SLOT( saveAsLayerDefinition() ) ); if ( !vlayer->isEditable() && vlayer->dataProvider()->supportsSubsetString() && vlayer->vectorJoins().isEmpty() ) menu->addAction( tr( "&Filter..." ), QgisApp::instance(), SLOT( layerSubsetString() ) ); menu->addAction( actions->actionShowFeatureCount( menu ) ); menu->addSeparator(); } else if ( layer && layer->type() == QgsMapLayer::RasterLayer ) { menu->addAction( tr( "Save As..." ), QgisApp::instance(), SLOT( saveAsRasterFile() ) ); menu->addAction( tr( "Save As Layer Definition File..." ), QgisApp::instance(), SLOT( saveAsLayerDefinition() ) ); } else if ( layer && layer->type() == QgsMapLayer::PluginLayer && mView->selectedLayerNodes().count() == 1 ) { // disable duplication of plugin layers duplicateLayersAction->setEnabled( false ); } // TODO: custom actions if ( layer && QgsProject::instance()->layerIsEmbedded( layer->id() ).isEmpty() ) menu->addAction( tr( "&Properties" ), QgisApp::instance(), SLOT( layerProperties() ) ); if ( node->parent() != mView->layerTreeModel()->rootGroup() ) menu->addAction( actions->actionMakeTopLevel( menu ) ); menu->addAction( actions->actionRenameGroupOrLayer( menu ) ); if ( mView->selectedNodes( true ).count() >= 2 ) menu->addAction( actions->actionGroupSelected( menu ) ); if ( mView->selectedLayerNodes().count() == 1 ) { QgisApp* app = QgisApp::instance(); menu->addAction( tr( "Copy Style" ), app, SLOT( copyStyle() ) ); if ( app->clipboard()->hasFormat( QGSCLIPBOARD_STYLE_MIME ) ) { menu->addAction( tr( "Paste Style" ), app, SLOT( pasteStyle() ) ); } } } } else { // symbology item? } return menu; }
QMenu *QgsAppLayerTreeViewMenuProvider::createContextMenu() { QMenu *menu = new QMenu; QgsLayerTreeViewDefaultActions *actions = mView->defaultActions(); QModelIndex idx = mView->currentIndex(); if ( !idx.isValid() ) { // global menu menu->addAction( actions->actionAddGroup( menu ) ); menu->addAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionExpandTree.svg" ) ), tr( "&Expand All" ), mView, SLOT( expandAll() ) ); menu->addAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionCollapseTree.svg" ) ), tr( "&Collapse All" ), mView, SLOT( collapseAll() ) ); menu->addSeparator(); if ( QgisApp::instance()->clipboard()->hasFormat( QGSCLIPBOARD_MAPLAYER_MIME ) ) { QAction *actionPasteLayerOrGroup = new QAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionEditPaste.svg" ) ), tr( "Paste Layer/Group" ), menu ); connect( actionPasteLayerOrGroup, &QAction::triggered, QgisApp::instance(), &QgisApp::pasteLayer ); menu->addAction( actionPasteLayerOrGroup ); } // TODO: update drawing order } else if ( QgsLayerTreeNode *node = mView->layerTreeModel()->index2node( idx ) ) { // layer or group selected if ( QgsLayerTree::isGroup( node ) ) { menu->addAction( actions->actionZoomToGroup( mCanvas, menu ) ); menu->addAction( tr( "Copy Group" ), QgisApp::instance(), SLOT( copyLayer() ) ); if ( QgisApp::instance()->clipboard()->hasFormat( QGSCLIPBOARD_MAPLAYER_MIME ) ) { QAction *actionPasteLayerOrGroup = new QAction( tr( "Paste Layer/Group" ), menu ); connect( actionPasteLayerOrGroup, &QAction::triggered, QgisApp::instance(), &QgisApp::pasteLayer ); menu->addAction( actionPasteLayerOrGroup ); } menu->addAction( actions->actionRenameGroupOrLayer( menu ) ); menu->addSeparator(); menu->addAction( actions->actionAddGroup( menu ) ); QAction *removeAction = menu->addAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionRemoveLayer.svg" ) ), tr( "&Remove Group…" ), QgisApp::instance(), SLOT( removeLayer() ) ); removeAction->setEnabled( removeActionEnabled() ); menu->addSeparator(); menu->addAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionSetCRS.png" ) ), tr( "&Set Group CRS…" ), QgisApp::instance(), SLOT( legendGroupSetCrs() ) ); menu->addAction( tr( "&Set Group WMS Data…" ), QgisApp::instance(), SLOT( legendGroupSetWmsData() ) ); menu->addSeparator(); menu->addAction( actions->actionMutuallyExclusiveGroup( menu ) ); menu->addAction( actions->actionCheckAndAllChildren( menu ) ); menu->addAction( actions->actionUncheckAndAllChildren( menu ) ); if ( !( mView->selectedNodes( true ).count() == 1 && idx.row() == 0 ) ) { menu->addAction( actions->actionMoveToTop( menu ) ); } menu->addSeparator(); if ( mView->selectedNodes( true ).count() >= 2 ) menu->addAction( actions->actionGroupSelected( menu ) ); if ( QgisApp::instance()->clipboard()->hasFormat( QGSCLIPBOARD_STYLE_MIME ) ) { menu->addAction( tr( "Paste Style" ), QgisApp::instance(), SLOT( applyStyleToGroup() ) ); } menu->addSeparator(); QMenu *menuExportGroup = new QMenu( tr( "Export" ), menu ); QAction *actionSaveAsDefinitionGroup = new QAction( tr( "Save as Layer Definition File…" ), menuExportGroup ); connect( actionSaveAsDefinitionGroup, &QAction::triggered, QgisApp::instance(), &QgisApp::saveAsLayerDefinition ); menuExportGroup->addAction( actionSaveAsDefinitionGroup ); menu->addMenu( menuExportGroup ); } else if ( QgsLayerTree::isLayer( node ) ) { QgsMapLayer *layer = QgsLayerTree::toLayer( node )->layer(); QgsRasterLayer *rlayer = qobject_cast<QgsRasterLayer *>( layer ); QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer ); if ( layer && layer->isSpatial() ) { menu->addAction( actions->actionZoomToLayer( mCanvas, menu ) ); if ( vlayer ) { QAction *actionZoomSelected = actions->actionZoomToSelection( mCanvas, menu ); actionZoomSelected->setEnabled( !vlayer->selectedFeatures().isEmpty() ); menu->addAction( actionZoomSelected ); } menu->addAction( actions->actionShowInOverview( menu ) ); } if ( vlayer ) menu->addAction( actions->actionShowFeatureCount( menu ) ); QAction *actionCopyLayer = new QAction( tr( "Copy Layer" ), menu ); connect( actionCopyLayer, &QAction::triggered, QgisApp::instance(), &QgisApp::copyLayer ); menu->addAction( actionCopyLayer ); menu->addAction( actions->actionRenameGroupOrLayer( menu ) ); if ( rlayer ) { menu->addAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionZoomActual.svg" ) ), tr( "&Zoom to Native Resolution (100%)" ), QgisApp::instance(), SLOT( legendLayerZoomNative() ) ); if ( rlayer->rasterType() != QgsRasterLayer::Palette ) menu->addAction( tr( "&Stretch Using Current Extent" ), QgisApp::instance(), SLOT( legendLayerStretchUsingCurrentExtent() ) ); } addCustomLayerActions( menu, layer ); if ( layer && layer->type() == QgsMapLayer::VectorLayer && static_cast<QgsVectorLayer *>( layer )->providerType() == QLatin1String( "virtual" ) ) { menu->addAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionAddVirtualLayer.svg" ) ), tr( "Edit Virtual Layer…" ), QgisApp::instance(), SLOT( addVirtualLayer() ) ); } menu->addSeparator(); // duplicate layer QAction *duplicateLayersAction = menu->addAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionDuplicateLayer.svg" ) ), tr( "&Duplicate Layer" ), QgisApp::instance(), SLOT( duplicateLayers() ) ); QAction *removeAction = menu->addAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionRemoveLayer.svg" ) ), tr( "&Remove Layer…" ), QgisApp::instance(), SLOT( removeLayer() ) ); removeAction->setEnabled( removeActionEnabled() ); menu->addSeparator(); if ( node->parent() != mView->layerTreeModel()->rootGroup() ) menu->addAction( actions->actionMoveOutOfGroup( menu ) ); if ( !( mView->selectedNodes( true ).count() == 1 && idx.row() == 0 ) ) { menu->addAction( actions->actionMoveToTop( menu ) ); } QAction *checkAll = actions->actionCheckAndAllParents( menu ); if ( checkAll ) menu->addAction( checkAll ); if ( mView->selectedNodes( true ).count() >= 2 ) menu->addAction( actions->actionGroupSelected( menu ) ); menu->addSeparator(); if ( vlayer ) { QAction *toggleEditingAction = QgisApp::instance()->actionToggleEditing(); QAction *saveLayerEditsAction = QgisApp::instance()->actionSaveActiveLayerEdits(); QAction *allEditsAction = QgisApp::instance()->actionAllEdits(); // attribute table menu->addAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionOpenTable.svg" ) ), tr( "&Open Attribute Table" ), QgisApp::instance(), SLOT( attributeTable() ) ); // allow editing int cap = vlayer->dataProvider()->capabilities(); if ( cap & QgsVectorDataProvider::EditingCapabilities ) { if ( toggleEditingAction ) { menu->addAction( toggleEditingAction ); toggleEditingAction->setChecked( vlayer->isEditable() ); toggleEditingAction->setEnabled( true ); } if ( saveLayerEditsAction && vlayer->isModified() ) { menu->addAction( saveLayerEditsAction ); } } if ( allEditsAction->isEnabled() ) menu->addAction( allEditsAction ); // disable duplication of memory layers if ( vlayer->storageType() == QLatin1String( "Memory storage" ) && mView->selectedLayerNodes().count() == 1 ) duplicateLayersAction->setEnabled( false ); if ( vlayer->dataProvider()->supportsSubsetString() ) { QAction *action = menu->addAction( tr( "&Filter…" ), QgisApp::instance(), SLOT( layerSubsetString() ) ); action->setEnabled( !vlayer->isEditable() ); } } menu->addSeparator(); if ( layer && layer->isSpatial() ) { // set layer scale visibility menu->addAction( tr( "&Set Layer Scale Visibility…" ), QgisApp::instance(), SLOT( setLayerScaleVisibility() ) ); if ( !layer->isInScaleRange( mCanvas->scale() ) ) menu->addAction( tr( "Zoom to &Visible Scale" ), QgisApp::instance(), SLOT( zoomToLayerScale() ) ); QMenu *menuSetCRS = new QMenu( tr( "Set CRS" ), menu ); // set layer crs QAction *actionSetLayerCrs = new QAction( tr( "Set Layer CRS…" ), menuSetCRS ); connect( actionSetLayerCrs, &QAction::triggered, QgisApp::instance(), &QgisApp::setLayerCrs ); menuSetCRS->addAction( actionSetLayerCrs ); // assign layer crs to project QAction *actionSetProjectCrs = new QAction( tr( "Set &Project CRS from Layer" ), menuSetCRS ); connect( actionSetProjectCrs, &QAction::triggered, QgisApp::instance(), &QgisApp::setProjectCrsFromLayer ); menuSetCRS->addAction( actionSetProjectCrs ); menu->addMenu( menuSetCRS ); } menu->addSeparator(); if ( vlayer ) { // save as vector file QMenu *menuExportVector = new QMenu( tr( "Export" ), menu ); QAction *actionSaveAs = new QAction( tr( "Save Features As…" ), menuExportVector ); connect( actionSaveAs, &QAction::triggered, QgisApp::instance(), [ = ] { QgisApp::instance()->saveAsFile(); } ); menuExportVector->addAction( actionSaveAs ); QAction *actionSaveSelectedFeaturesAs = new QAction( tr( "Save Selected Features As…" ), menuExportVector ); connect( actionSaveSelectedFeaturesAs, &QAction::triggered, QgisApp::instance(), [ = ] { QgisApp::instance()->saveAsFile( nullptr, true ); } ); actionSaveSelectedFeaturesAs->setEnabled( vlayer->selectedFeatureCount() > 0 ); menuExportVector->addAction( actionSaveSelectedFeaturesAs ); QAction *actionSaveAsDefinitionLayer = new QAction( tr( "Save as Layer Definition File…" ), menuExportVector ); connect( actionSaveAsDefinitionLayer, &QAction::triggered, QgisApp::instance(), &QgisApp::saveAsLayerDefinition ); menuExportVector->addAction( actionSaveAsDefinitionLayer ); if ( vlayer->isSpatial() ) { QAction *actionSaveStyle = new QAction( tr( "Save as QGIS Layer Style File…" ), menuExportVector ); connect( actionSaveStyle, &QAction::triggered, QgisApp::instance(), [ = ] { QgisApp::instance()->saveStyleFile(); } ); menuExportVector->addAction( actionSaveStyle ); } menu->addMenu( menuExportVector ); } else if ( rlayer ) { QMenu *menuExportRaster = new QMenu( tr( "Export" ), menu ); QAction *actionSaveAs = new QAction( tr( "Save As…" ), menuExportRaster ); QAction *actionSaveAsDefinitionLayer = new QAction( tr( "Save as Layer Definition File…" ), menuExportRaster ); QAction *actionSaveStyle = new QAction( tr( "Save as QGIS Layer Style File…" ), menuExportRaster ); connect( actionSaveAs, &QAction::triggered, QgisApp::instance(), [ = ] { QgisApp::instance()->saveAsFile(); } ); menuExportRaster->addAction( actionSaveAs ); connect( actionSaveAsDefinitionLayer, &QAction::triggered, QgisApp::instance(), &QgisApp::saveAsLayerDefinition ); menuExportRaster->addAction( actionSaveAsDefinitionLayer ); connect( actionSaveStyle, &QAction::triggered, QgisApp::instance(), [ = ] { QgisApp::instance()->saveStyleFile(); } ); menuExportRaster->addAction( actionSaveStyle ); menu->addMenu( menuExportRaster ); } else if ( layer && layer->type() == QgsMapLayer::PluginLayer && mView->selectedLayerNodes().count() == 1 ) { // disable duplication of plugin layers duplicateLayersAction->setEnabled( false ); } menu->addSeparator(); // style-related actions if ( layer && mView->selectedLayerNodes().count() == 1 ) { menu->addSeparator(); QMenu *menuStyleManager = new QMenu( tr( "Styles" ), menu ); QgisApp *app = QgisApp::instance(); menuStyleManager->addAction( tr( "Copy Style" ), app, SLOT( copyStyle() ) ); if ( app->clipboard()->hasFormat( QGSCLIPBOARD_STYLE_MIME ) ) { menuStyleManager->addAction( tr( "Paste Style" ), app, SLOT( pasteStyle() ) ); } menuStyleManager->addSeparator(); QgsMapLayerStyleGuiUtils::instance()->addStyleManagerActions( menuStyleManager, layer ); if ( vlayer ) { const QgsSingleSymbolRenderer *singleRenderer = dynamic_cast< const QgsSingleSymbolRenderer * >( vlayer->renderer() ); if ( !singleRenderer && vlayer->renderer() && vlayer->renderer()->embeddedRenderer() ) { singleRenderer = dynamic_cast< const QgsSingleSymbolRenderer * >( vlayer->renderer()->embeddedRenderer() ); } if ( singleRenderer && singleRenderer->symbol() ) { //single symbol renderer, so add set color/edit symbol actions menuStyleManager->addSeparator(); QgsColorWheel *colorWheel = new QgsColorWheel( menuStyleManager ); colorWheel->setColor( singleRenderer->symbol()->color() ); QgsColorWidgetAction *colorAction = new QgsColorWidgetAction( colorWheel, menuStyleManager, menuStyleManager ); colorAction->setDismissOnColorSelection( false ); connect( colorAction, &QgsColorWidgetAction::colorChanged, this, &QgsAppLayerTreeViewMenuProvider::setVectorSymbolColor ); //store the layer id in action, so we can later retrieve the corresponding layer colorAction->setProperty( "layerId", vlayer->id() ); menuStyleManager->addAction( colorAction ); //add recent colors action QList<QgsRecentColorScheme *> recentSchemes; QgsApplication::colorSchemeRegistry()->schemes( recentSchemes ); if ( !recentSchemes.isEmpty() ) { QgsColorSwatchGridAction *recentColorAction = new QgsColorSwatchGridAction( recentSchemes.at( 0 ), menuStyleManager, QStringLiteral( "symbology" ), menuStyleManager ); recentColorAction->setProperty( "layerId", vlayer->id() ); recentColorAction->setDismissOnColorSelection( false ); menuStyleManager->addAction( recentColorAction ); connect( recentColorAction, &QgsColorSwatchGridAction::colorChanged, this, &QgsAppLayerTreeViewMenuProvider::setVectorSymbolColor ); } menuStyleManager->addSeparator(); QAction *editSymbolAction = new QAction( tr( "Edit Symbol…" ), menuStyleManager ); //store the layer id in action, so we can later retrieve the corresponding layer editSymbolAction->setProperty( "layerId", vlayer->id() ); connect( editSymbolAction, &QAction::triggered, this, &QgsAppLayerTreeViewMenuProvider::editVectorSymbol ); menuStyleManager->addAction( editSymbolAction ); } } menu->addMenu( menuStyleManager ); } else { if ( QgisApp::instance()->clipboard()->hasFormat( QGSCLIPBOARD_STYLE_MIME ) ) { menu->addAction( tr( "Paste Style" ), QgisApp::instance(), SLOT( applyStyleToGroup() ) ); } } if ( layer && QgsProject::instance()->layerIsEmbedded( layer->id() ).isEmpty() ) menu->addAction( tr( "&Properties…" ), QgisApp::instance(), SLOT( layerProperties() ) ); } } else if ( QgsLayerTreeModelLegendNode *node = mView->layerTreeModel()->index2legendNode( idx ) ) { if ( QgsSymbolLegendNode *symbolNode = dynamic_cast< QgsSymbolLegendNode * >( node ) ) { // symbology item if ( symbolNode->flags() & Qt::ItemIsUserCheckable ) { menu->addAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionShowAllLayers.svg" ) ), tr( "&Show All Items" ), symbolNode, SLOT( checkAllItems() ) ); menu->addAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionHideAllLayers.svg" ) ), tr( "&Hide All Items" ), symbolNode, SLOT( uncheckAllItems() ) ); menu->addSeparator(); } if ( symbolNode->symbol() ) { QgsColorWheel *colorWheel = new QgsColorWheel( menu ); colorWheel->setColor( symbolNode->symbol()->color() ); QgsColorWidgetAction *colorAction = new QgsColorWidgetAction( colorWheel, menu, menu ); colorAction->setDismissOnColorSelection( false ); connect( colorAction, &QgsColorWidgetAction::colorChanged, this, &QgsAppLayerTreeViewMenuProvider::setSymbolLegendNodeColor ); //store the layer id and rule key in action, so we can later retrieve the corresponding //legend node, if it still exists colorAction->setProperty( "layerId", symbolNode->layerNode()->layerId() ); colorAction->setProperty( "ruleKey", symbolNode->data( QgsLayerTreeModelLegendNode::RuleKeyRole ).toString() ); menu->addAction( colorAction ); //add recent colors action QList<QgsRecentColorScheme *> recentSchemes; QgsApplication::colorSchemeRegistry()->schemes( recentSchemes ); if ( !recentSchemes.isEmpty() ) { QgsColorSwatchGridAction *recentColorAction = new QgsColorSwatchGridAction( recentSchemes.at( 0 ), menu, QStringLiteral( "symbology" ), menu ); recentColorAction->setProperty( "layerId", symbolNode->layerNode()->layerId() ); recentColorAction->setProperty( "ruleKey", symbolNode->data( QgsLayerTreeModelLegendNode::RuleKeyRole ).toString() ); recentColorAction->setDismissOnColorSelection( false ); menu->addAction( recentColorAction ); connect( recentColorAction, &QgsColorSwatchGridAction::colorChanged, this, &QgsAppLayerTreeViewMenuProvider::setSymbolLegendNodeColor ); } menu->addSeparator(); } QAction *editSymbolAction = new QAction( tr( "Edit Symbol…" ), menu ); //store the layer id and rule key in action, so we can later retrieve the corresponding //legend node, if it still exists editSymbolAction->setProperty( "layerId", symbolNode->layerNode()->layerId() ); editSymbolAction->setProperty( "ruleKey", symbolNode->data( QgsLayerTreeModelLegendNode::RuleKeyRole ).toString() ); connect( editSymbolAction, &QAction::triggered, this, &QgsAppLayerTreeViewMenuProvider::editSymbolLegendNodeSymbol ); menu->addAction( editSymbolAction ); } } return menu; }