def layerTreeInsertionPoint(tree_view: QgsLayerTreeView) -> tuple: """ Direct copy of the code QgisApp::layerTreeInsertionPoint for QGIS < 3.10 """ insert_group = tree_view.layerTreeModel().rootGroup() current = tree_view.currentIndex() index = 0 if current.isValid(): index = current.row() current_node = tree_view.currentNode() if current_node: # if the insertion point is actually a group, insert new layers into the group if QgsLayerTree.isGroup(current_node): # if the group is embedded go to the first non-embedded group, at worst the top level item insert_group = firstGroupWithoutCustomProperty( current_node, "embedded") return InsertionPoint(insert_group, 0) # otherwise just set the insertion point in front of the current node parent_node = current_node.parent() if QgsLayerTree.isGroup(parent_node): # if the group is embedded go to the first non-embedded group, at worst the top level item insert_group = firstGroupWithoutCustomProperty( parent_node, "embedded") if parent_node != insert_group: index = 0 return InsertionPoint(insert_group, index)
def parseTreeRec(self, treeLeaf): for el in treeLeaf.children(): if QgsLayerTree.isLayer(el): l = el.layer() self.sortInto(l, self.layerDict, self.hierarchyDefinition) elif QgsLayerTree.isGroup(el): self.parseTreeRec(el)
def createContextMenu(self): menu = QMenu() actions: QgsLayerTreeViewDefaultActions = self.layerTreeView.defaultActions() if not self.layerTreeView.currentIndex().isValid(): # 不在图层上右键 self.actionAddGroup = actions.actionAddGroup(menu) menu.addAction(self.actionAddGroup) menu.addAction('Expand All', self.layerTreeView.expandAll) menu.addAction('Collapse All', self.layerTreeView.collapseAll) return menu node: QgsLayerTreeNode = self.layerTreeView.currentNode() if QgsLayerTree.isGroup(node): # 图组操作 print('group') pass elif QgsLayerTree.isLayer(node): print('layer') self.actionZoomToLayer = actions.actionZoomToLayer(self.mapCanvas, menu) menu.addAction(self.actionZoomToLayer) # 图层操作 layer = self.layerTreeView.currentLayer() if layer.type() == QgsMapLayerType.VectorLayer: # 矢量图层 actionOpenAttributeDialog = QAction('open Attribute Table', menu) actionOpenAttributeDialog.triggered.connect(lambda: self.openAttributeDialog(layer)) menu.addAction(actionOpenAttributeDialog) else: # 栅格图层 pass else: print('node type is none') return menu
def _getPosOfPrevGroup(self, groupName): topLevelGroups = [ child.name() for child in self.tocRoot.children() if QgsLayerTree.isGroup(child) ] if groupName in topLevelGroups: return topLevelGroups.index(groupName) else: return None
def nodeOrder(self, group): nodeorder = [] layerTree = QgsLayerTree() for node in group: if QgsLayerTree.isGroup(node): groupname = node.name() nodeorder.append(groupname) for child in self.nodeOrder(node.children()): nodeorder.append(groupname + '-' + child) elif QgsLayerTree.isLayer(node): nodeorder.append(node.layer().name()) return nodeorder
def nodeOrder(self, group): nodeorder = [] layerTree = QgsLayerTree() for node in group: if QgsLayerTree.isGroup(node): groupname = node.name() nodeorder.append(groupname) for child in self.nodeOrder(node.children()): nodeorder.append(groupname + '-' + child) elif QgsLayerTree.isLayer(node): nodeorder.append(node.layer().name()) return nodeorder
def insertInto(self, origin, destination, reset_initial_visibility): for el in origin.children(): if QgsLayerTree.isLayer(el): node = destination.addLayer(el.layer()) node.setItemVisibilityChecked( self.treeRoot.findLayer(el.layer()).isVisible() ) elif QgsLayerTree.isGroup(el): node = destination.addGroup(el.name()) self.insertInto(el, node, reset_initial_visibility) if reset_initial_visibility: # overwrite visibility with previously saved visibility node.setItemVisibilityChecked(el.itemVisibilityChecked())
def get_layers_and_visibility_from_node( root: QgsLayerTree, node: QgsLayerTreeNode) -> List[Tuple[QgsMapLayer, bool]]: layers = [] child: QgsLayerTreeNode for child in node.children(): if root.isGroup(child): # noinspection PyTypeChecker layers += LayerHandler.get_layers_and_visibility_from_node( root, child) else: layer = child.layer() visibility = child.itemVisibilityChecked( ) and node.itemVisibilityChecked() if layer: layers.append((layer, visibility)) return layers
def firstGroupWithoutCustomProperty(group: QgsLayerTreeGroup, _property: str) -> QgsLayerTreeGroup: """ Taken from QgsLayerTreeUtils::firstGroupWithoutCustomProperty :param group: :param _property: :return: """ # if the group is embedded go to the first non-embedded group, at worst the top level item while group.customProperty(_property): if not group.parent(): break if QgsLayerTree.isGroup(group.parent()): group = group.parent() else: dbg_info(group) assert False return group
def groupSelected(self): nodes = self.mView.selectedNodes(True) if len(nodes) < 2 or not QgsLayerTree.isGroup(nodes[0].parent()): return parentGroup = nodes[0].parent() insertIdx = parentGroup.children().index(nodes[0]) newGroup = QgsLayerTreeGroup(self.uniqueGroupName(parentGroup)) for node in nodes: newGroup.addChildNode(node.clone()) parentGroup.insertChildNode(insertIdx, newGroup) for node in nodes: group = node.parent() if group != None: group.removeChildNode(node) self.mView.setCurrentIndex( self.mView.layerTreeModel().node2index(newGroup))
def isPluginLayerTreeNode(self, node: QgsLayerTree) -> bool: # for some reason even the normal nodes are behaving like groups... if QgsLayerTree.isGroup(node): # unfortunately this does not work in Python, it's cpp only... # group = QgsLayerTree.toGroup(node) # All my other attempts also failed miserably # group = self.layerTree.findGroup(self.groupName) # return group is get_group() pass else: layer = self.project.mapLayer(node.layerId()) if layer in (self.simplifiedSegmentsLayer, self.verticesLayer, self.candidatesLayer, self.finalLayer): return True if self.wasBaseRasterLayerInitiallyInLegend and layer is self.baseRasterLayer: return True if self.wasSegmentsLayerInitiallyInLegend and layer is self.segmentsLayer: return True return False
def createContextMenu(self): menu = QMenu() actionAddGroup = QgisHelper.createAction(menu, "&Add GroupLayer", self.addGroup) actionAddVectorLayer = QgisHelper.createAction(menu, "&Add VectorLayer", self.addVectorLayer) actionZoomToGroup = QgisHelper.createAction(menu, "&Zoom To Group", self.zoomToGroup) actionRenameGroupOrLayer = QgisHelper.createAction( menu, "&Rename", self.rename) actionRemoveLayer = QgisHelper.createAction(menu, "&Remove", self.removeLayer) actionGroupSelected = QgisHelper.createAction(menu, "&Group Selected", self.groupSelected) actionZoomToLayer = QgisHelper.createAction(menu, "&Zoom To Layer", self.zoomToLayer) actionOpenAttributetable = QgisHelper.createAction( menu, "&Open Attribute Table", self.openAttriTable) actionSaveAs = QgisHelper.createAction(menu, "&Save as...", self.saveAs) actionLayerProperty = QgisHelper.createAction(menu, "&Property", self.layerProperty) self.actionShowOverview = QgisHelper.createAction( menu, "&Show in overview...", self.showOverview, None, None, None, True) idx = self.mView.currentIndex() node = self.mView.layerTreeModel().index2node(idx) if not idx.isValid(): #global menu menu.addAction(actionAddGroup) menu.addAction(actionAddVectorLayer) # menu.addAction( QgsApplication.getThemeIcon( "/mActionExpandTree.png" ), "&Expand All" , self.mView, "expandAll()" ) # menu.addAction( QgsApplication.getThemeIcon( "/mActionCollapseTree.png" ), "&Collapse All" , self.mView, "collapseAll()" ) elif (node != None): if (QgsLayerTree.isGroup(node)): menu.addAction(actionZoomToGroup) menu.addAction(actionRemoveLayer) # menu.addAction( QgsApplication.getThemeIcon( "/mActionSetCRS.png" ), # tr( "&Set Group CRS" ), QgisApp.instance(), SLOT( legendGroupSetCRS() ) ); menu.addAction(actionRenameGroupOrLayer) if (str(self.mView.selectedNodes(True)) >= 2): menu.addAction(actionGroupSelected) menu.addAction(actionAddGroup) menu.addAction(actionAddVectorLayer) elif (QgsLayerTree.isLayer(node)): menu.addAction(actionZoomToLayer) menu.addAction(actionRemoveLayer) menu.addAction(self.actionShowOverview) if self.mView.currentLayer().type() == QgsMapLayer.VectorLayer: menu.addAction(actionOpenAttributetable) menu.addAction(actionLayerProperty) menu.addAction(actionSaveAs) # menu.addAction( actions.actionShowInOverview( menu ) ) # if layer.type() == QgsMapLayer.RasterLayer : # menu.addAction( "&Zoom to Best Scale (100%)" , QgisApp.instance(), " legendLayerZoomNative() " ) # rasterLayer = qobject_cast<QgsRasterLayer *>( layer ); # if ( rasterLayer && rasterLayer.rastertype() != QgsRasterLayer.Palette ) # menu.addAction( tr( "&Stretch Using Current Extent" ), QgisApp.instance(), SLOT( legendLayerStretchUsingCurrentExtent() ) ); # } # menu.addAction( QgsApplication.getThemeIcon( "/mActionRemoveLayer.svg" ), tr( "&Remove" ), QgisApp.instance(), " removeLayer() "); # // 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" && self.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 && self.mView.selectedLayerNodes().count() == 1 ) # { # // disable duplication of plugin layers # duplicateLayersAction.setEnabled( false ); # } # addCustomLayerActions( menu, layer ); # # if ( layer && QgsProject.instance().layerIsEmbedded( layer.id() ).isEmpty() ) # menu.addAction( tr( "&Properties" ), QgisApp.instance(), SLOT( layerProperties() ) ); # if ( node.parent() != self.mView.layerTreeModel().rootGroup() ): # menu.addAction( actions.actionMakeTopLevel( menu ) ) menu.addAction(actionRenameGroupOrLayer) if (len(self.mView.selectedNodes(True)) >= 2): menu.addAction(actionGroupSelected) # if ( self.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() ) ); # } # } return menu
def data(self, index, role=Qt.DisplayRole): if not index.isValid(): return node = self.index2node(index) legend_node = self.index2legendNode(index) if legend_node and role == Qt.DecorationRole: pixmap = pixmapForLegendNode(legend_node) if pixmap: return pixmap if not node: return super().data(index, role) if role == Qt.FontRole: f = iface.layerTreeView().font() if node.customProperty("plugins/customTreeIcon/font"): f.fromString(node.customProperty("plugins/customTreeIcon/font")) elif QgsLayerTree.isLayer(node): f = self.layerTreeNodeFont(QgsLayerTree.NodeLayer) elif QgsLayerTree.isGroup(node): f = self.layerTreeNodeFont(QgsLayerTree.NodeGroup) if index == self.currentIndex(): f.setUnderline(not f.underline()) if QgsLayerTree.isLayer(node): _, _, scale = self.legendMapViewData() layer = node.layer() if (not node.isVisible() and (not layer or layer.isSpatial())) or ( layer and not layer.isInScaleRange(scale) ): f.setItalic(not f.italic()) return f if role == Qt.ForegroundRole: color = None if node.customProperty("plugins/customTreeIcon/textColor"): color = QColor(node.customProperty("plugins/customTreeIcon/textColor")) elif QgsLayerTree.isGroup(node): if self.settings.value("group_text_color"): color = QColor(self.settings.value("group_text_color")) else: if self.settings.value("layer_text_color"): color = QColor(self.settings.value("layer_text_color")) if color: if QgsLayerTree.isLayer(node): _, _, scale = self.legendMapViewData() layer = node.layer() if (not node.isVisible() and (not layer or layer.isSpatial())) or ( layer and not layer.isInScaleRange(scale) ): color.setAlpha(128) return color if role == Qt.BackgroundRole: if node.customProperty("plugins/customTreeIcon/backgroundColor"): return QColor( node.customProperty("plugins/customTreeIcon/backgroundColor") ) elif QgsLayerTree.isGroup(node): if self.settings.value("group_background_color"): return QColor(self.settings.value("group_background_color")) else: if self.settings.value("layer_background_color"): return QColor(self.settings.value("layer_background_color")) # Override data for DecorationRole (Icon) if role == Qt.DecorationRole and index.column() == 0: icon = None pixmap = None # If a custom icon was set for this node if node.customProperty("plugins/customTreeIcon/icon"): icon = QIcon(node.customProperty("plugins/customTreeIcon/icon")) # If an icon was set for the node type elif QgsLayerTree.isGroup(node): if self.settings.value("defaulticons/group", ""): icon = QIcon(self.settings.value("defaulticons/group")) else: icon = QIcon(":/images/themes/default/mActionFolder.svg") elif QgsLayerTree.isLayer(node): layer = node.layer() if not layer: return super().data(index, role) if layer.type() == QgsMapLayer.RasterLayer: if self.settings.value("defaulticons/raster", ""): icon = QIcon(self.settings.value("defaulticons/raster")) else: icon = QIcon(":/images/themes/default/mIconRaster.svg") if layer.type() == QgsMapLayer.VectorLayer: if self.testFlag( QgsLayerTreeModel.ShowLegend ) and self.legendEmbeddedInParent(node): size = iface.layerTreeView().iconSize() legend_node = self.legendNodeEmbeddedInParent(node) pixmap = pixmapForLegendNode(legend_node) else: if layer.geometryType() == QgsWkbTypes.PointGeometry: if self.settings.value("defaulticons/point", ""): icon = QIcon(self.settings.value("defaulticons/point")) else: icon = QIcon( ":/images/themes/default/mIconPointLayer.svg" ) elif layer.geometryType() == QgsWkbTypes.LineGeometry: if self.settings.value("defaulticons/line", ""): icon = QIcon(self.settings.value("defaulticons/line")) else: icon = QIcon( ":/images/themes/default/mIconLineLayer.svg" ) elif layer.geometryType() == QgsWkbTypes.PolygonGeometry: if self.settings.value("defaulticons/polygon", ""): icon = QIcon( self.settings.value("defaulticons/polygon") ) else: icon = QIcon( ":/images/themes/default/mIconPolygonLayer.svg" ) elif layer.geometryType() == QgsWkbTypes.NullGeometry: if self.settings.value("defaulticons/nogeometry", ""): icon = QIcon( self.settings.value("defaulticons/nogeometry") ) else: icon = QIcon( ":/images/themes/default/mIconTableLayer.svg" ) try: if layer.type() == QgsMapLayer.MeshLayer: if self.settings.value("defaulticons/mesh", ""): icon = QIcon(self.settings.value("defaulticons/mesh")) else: icon = QIcon(":/images/themes/default/mIconMeshLayer.svg") except AttributeError: pass # Special case: In-edition vector layer. Draw an editing icon over # the custom icon. Adapted from QGIS source code (qgslayertreemodel.cpp) if (pixmap or icon) and QgsLayerTree.isLayer(node): layer = node.layer() if layer and isinstance(layer, QgsVectorLayer) and layer.isEditable(): icon_size = iface.layerTreeView().iconSize().width() if icon_size == -1: icon_size = 16 if not pixmap and icon: pixmap = QPixmap(icon.pixmap(icon_size, icon_size)) painter = QPainter(pixmap) painter.drawPixmap( 0, 0, icon_size, icon_size, QgsApplication.getThemeIcon( ("/mIconEditableEdits.svg") if layer.isModified() else ("/mActionToggleEditing.svg") ).pixmap(icon_size, icon_size), ) painter.end() del painter if pixmap: return pixmap if icon: return icon # call QgsLayerTreeModel implementation return super().data(index, role)
def _getPosOfPrevGroup(self, groupName): topLevelGroups = [child.name() for child in self.tocRoot.children() if QgsLayerTree.isGroup(child)] if groupName in topLevelGroups: return topLevelGroups.index(groupName) else: return None