Skip to content

Commit

Permalink
[layertree] Add python bindings - part one (core)
Browse files Browse the repository at this point in the history
  • Loading branch information
wonder-sk committed Jun 3, 2014
1 parent a50719b commit 73358c3
Show file tree
Hide file tree
Showing 11 changed files with 342 additions and 11 deletions.
1 change: 1 addition & 0 deletions python/CMakeLists.txt
Expand Up @@ -79,6 +79,7 @@ INCLUDE_DIRECTORIES(
../src/core/diagram
../src/core/dxf
../src/core/gps
../src/core/layertree
../src/core/raster
../src/core/symbology-ng

Expand Down
7 changes: 7 additions & 0 deletions python/core/core.sip
Expand Up @@ -153,6 +153,13 @@
%Include gps/qgsnmeaconnection.sip
%Include gps/qgsqtlocationconnection.sip

%Include layertree/qgslayertree.sip
%Include layertree/qgslayertreegroup.sip
%Include layertree/qgslayertreelayer.sip
%Include layertree/qgslayertreenode.sip
%Include layertree/qgslayertreeregistrybridge.sip
%Include layertree/qgslayertreeutils.sip

%Include raster/qgsraster.sip
%Include raster/qgscliptominmaxenhancement.sip
%Include raster/qgscolorrampshader.sip
Expand Down
29 changes: 29 additions & 0 deletions python/core/layertree/qgslayertree.sip
@@ -0,0 +1,29 @@
%ModuleHeaderCode
#include <qgslayertree.h>
%End

/**
* Namespace with helper functions for layer tree operations.
*
* Only generally useful routines should be here. Miscellaneous utility functions for work
* with the layer tree are in QgsLayerTreeUtils class.
*
* @note added in 2.4
*/
namespace QgsLayerTree
{
//! Check whether the node is a valid group node
bool isGroup( QgsLayerTreeNode* node );

//! Check whether the node is a valid layer node
bool isLayer( QgsLayerTreeNode* node );

//! Cast node to a group. No type checking is done - use isGroup() to find out whether this operation is legal.
// PYTHON: automatic cast
//inline QgsLayerTreeGroup* toGroup( QgsLayerTreeNode* node );

//! Cast node to a layer. No type checking is done - use isLayer() to find out whether this operation is legal.
// PYTHON: automatic cast
//inline QgsLayerTreeLayer* toLayer( QgsLayerTreeNode* node );

};
53 changes: 53 additions & 0 deletions python/core/layertree/qgslayertreegroup.sip
@@ -0,0 +1,53 @@
/**
* Layer tree group node serves as a container for layers and further groups.
*
* @note added in 2.4
*/
class QgsLayerTreeGroup : QgsLayerTreeNode
{
%TypeHeaderCode
#include <qgslayertreegroup.h>
%End

public:
QgsLayerTreeGroup( const QString& name = QString(), Qt::CheckState checked = Qt::Checked );

QString name() const;
void setName( const QString& n );

QgsLayerTreeGroup* addGroup( const QString& name ) /Factory/;
QgsLayerTreeLayer* insertLayer( int index, QgsMapLayer* layer ) /Factory/;
QgsLayerTreeLayer* addLayer( QgsMapLayer* layer ) /Factory/;

void insertChildNodes( int index, QList<QgsLayerTreeNode*> nodes /Transfer/ );
void insertChildNode( int index, QgsLayerTreeNode* node /Transfer/ );
void addChildNode( QgsLayerTreeNode* node /Transfer/ );

void removeChildNode( QgsLayerTreeNode* node );

void removeLayer( QgsMapLayer* layer );

void removeChildren( int from, int count );

void removeAllChildren();

QgsLayerTreeLayer* findLayer( const QString& layerId );
QList<QgsLayerTreeLayer*> findLayers() const;
QStringList findLayerIds() const;
QgsLayerTreeGroup* findGroup( const QString& name );

static QgsLayerTreeGroup* readXML( QDomElement& element ) /Factory/;
virtual void writeXML( QDomElement& parentElement );

void readChildrenFromXML( QDomElement& element );

virtual QString dump() const;

virtual QgsLayerTreeNode* clone() const /Factory/;

Qt::CheckState isVisible() const;
void setVisible( Qt::CheckState state );

private:
QgsLayerTreeGroup( const QgsLayerTreeGroup& other );
};
54 changes: 54 additions & 0 deletions python/core/layertree/qgslayertreelayer.sip
@@ -0,0 +1,54 @@
/**
* Layer tree node points to a map layer.
*
* When using with existing QgsMapLayer instance, it is expected that the layer
* has been registered in QgsMapLayerRegistry earlier.
*
* The node can exist also without a valid instance of a layer (just ID). That
* means the referenced layer does not need to be loaded in order to use it
* in layer tree. In such case, the node will start listening to map layer
* registry updates in expectation that the layer (identified by its ID) will
* be loaded later.
*
* A map layer is supposed to be present in one layer tree just once. It is
* however possible that temporarily a layer exists in one tree more than just
* once, e.g. while reordering items with drag and drop.
*
* @note added in 2.4
*/
class QgsLayerTreeLayer : QgsLayerTreeNode
{
%TypeHeaderCode
#include <qgslayertreelayer.h>
%End

public:
explicit QgsLayerTreeLayer( QgsMapLayer* layer );

explicit QgsLayerTreeLayer( QString layerId, QString name = QString() );

QString layerId() const;

QgsMapLayer* layer() const;

QString layerName() const;
void setLayerName( const QString& n );

Qt::CheckState isVisible() const;
void setVisible( Qt::CheckState visible );

static QgsLayerTreeLayer* readXML( QDomElement& element ) /Factory/;
virtual void writeXML( QDomElement& parentElement );

virtual QString dump() const;

virtual QgsLayerTreeNode* clone() const /Factory/;

signals:
//! emitted when a previously unavailable layer got loaded
void layerLoaded();

private:
QgsLayerTreeLayer( const QgsLayerTreeLayer& other );

};
123 changes: 123 additions & 0 deletions python/core/layertree/qgslayertreenode.sip
@@ -0,0 +1,123 @@
/**
* This class is a base class for nodes in a layer tree.
* Layer tree is a hierarchical structure consisting of group and layer nodes:
* - group nodes are containers and may contain children (layer and group nodes)
* - layer nodes point to map layers, they do not contain further children
*
* Layer trees may be used for organization of layers, typically a layer tree
* is exposed to the user using QgsLayerTreeView widget which shows the tree
* and allows manipulation with the tree.
*
* Ownership of nodes: every node is owned by its parent. Therefore once node
* is added to a layer tree, it is the responsibility of the parent to delete it
* when the node is not needed anymore. Deletion of root node of a tree will
* delete all nodes of the tree.
*
* Signals: signals are propagated from children to parent. That means it is
* sufficient to connect to root node in order to get signals about updates
* in the whole layer tree. When adding or removing a node that contains further
* children (i.e. a whole subtree), the addition/removal signals are emitted
* only for the root node of the subtree that is being added or removed.
*
* Custom properties: Every node may have some custom properties assigned to it.
* This mechanism allows third parties store additional data with the nodes.
* The properties are used within QGIS code (whether to show layer in overview,
* whether the node is embedded from another project etc), but may be also
* used by third party plugins. Custom properties are stored also in the project
* file. The storage is not efficient for large amount of data.
*
* Custom properties that have already been used within QGIS:
* - "overview" - whether to show a layer in overview
* - "showFeatureCount" - whether to show feature counts in layer tree (vector only)
* - "embedded" - whether the node comes from an external project
* - "embedded_project" - path to the external project (embedded root node only)
*
* @see also QgsLayerTree, QgsLayerTreeLayer, QgsLayerTreeGroup
* @note added in 2.4
*/
class QgsLayerTreeNode : QObject
{
%TypeHeaderCode
#include <qgslayertree.h>
%End

%ConvertToSubClassCode
if (sipCpp->inherits("QgsLayerTreeNode"))
{
sipType = sipType_QgsLayerTreeNode;
QgsLayerTreeNode* node = qobject_cast<QgsLayerTreeNode*>(sipCpp);
if (QgsLayerTree::isLayer(node))
sipType = sipType_QgsLayerTreeLayer;
else if (QgsLayerTree::isGroup(node))
sipType = sipType_QgsLayerTreeGroup;
}
else
sipType = 0;
%End

public:

//! Enumeration of possible tree node types
enum NodeType
{
NodeGroup, //!< container of other groups and layers
NodeLayer //!< leaf node pointing to a layer
};

~QgsLayerTreeNode();

//! Find out about type of the node. It is usually shorter to use convenience functions from QgsLayerTree namespace for that
NodeType nodeType();
//! Get pointer to the parent. If parent is a null pointer, the node is a root node
QgsLayerTreeNode* parent();
//! Get list of children of the node. Children are owned by the parent
QList<QgsLayerTreeNode*> children();

//! Read layer tree from XML. Returns new instance
static QgsLayerTreeNode* readXML( QDomElement& element );
//! Write layer tree to XML
virtual void writeXML( QDomElement& parentElement ) = 0;

//! Return string with layer tree structure. For debug purposes only
virtual QString dump() const = 0;

//! Create a copy of the node. Returns new instance
virtual QgsLayerTreeNode* clone() const = 0 /Factory/;

//! Return whether the node should be shown as expanded or collapsed in GUI
bool isExpanded() const;
//! Set whether the node should be shown as expanded or collapsed in GUI
void setExpanded( bool expanded );

/** Set a custom property for the node. Properties are stored in a map and saved in project file. */
void setCustomProperty( const QString& key, const QVariant& value );
/** Read a custom property from layer. Properties are stored in a map and saved in project file. */
QVariant customProperty( const QString& key, const QVariant& defaultValue = QVariant() ) const;
/** Remove a custom property from layer. Properties are stored in a map and saved in project file. */
void removeCustomProperty( const QString& key );
/** Return list of keys stored in custom properties */
QStringList customProperties() const;

signals:

//! Emitted when one or more nodes will be added to a node within the tree
void willAddChildren( QgsLayerTreeNode* node, int indexFrom, int indexTo );
//! Emitted when one or more nodes have been added to a node within the tree
void addedChildren( QgsLayerTreeNode* node, int indexFrom, int indexTo );
//! Emitted when one or more nodes will be removed from a node within the tree
void willRemoveChildren( QgsLayerTreeNode* node, int indexFrom, int indexTo );
//! Emitted when one or more nodes has been removed from a node within the tree
void removedChildren( QgsLayerTreeNode* node, int indexFrom, int indexTo );
//! Emitted when check state of a node within the tree has been changed
void visibilityChanged( QgsLayerTreeNode* node, Qt::CheckState state );
//! Emitted when a custom property of a node within the tree has been changed or removed
void customPropertyChanged( QgsLayerTreeNode* node, QString key );

protected:

QgsLayerTreeNode( NodeType t );

private:
QgsLayerTreeNode( const QgsLayerTreeNode& other );

};
29 changes: 29 additions & 0 deletions python/core/layertree/qgslayertreeregistrybridge.sip
@@ -0,0 +1,29 @@
/**
* Listens to the updates in map layer registry and does changes in layer tree.
*
* When connected to a layer tree, any layers added to the map layer registry
* will be also added to the layer tree. Similarly, map layers that are removed
* from registry will be removed from the layer tree.
*
* If a layer is completely removed from the layer tree, it will be also removed
* from the map layer registry.
*
* @note added in 2.4
*/
class QgsLayerTreeRegistryBridge : QObject
{
%TypeHeaderCode
#include <qgslayertreeregistrybridge.h>
%End

public:
explicit QgsLayerTreeRegistryBridge( QgsLayerTreeGroup* root, QObject *parent /TransferThis/ = 0 );

void setEnabled( bool enabled );
bool isEnabled() const;

//! Set where the new layers should be inserted - can be used to follow current selection.
//! By default it is root group with zero index.
void setLayerInsertionPoint( QgsLayerTreeGroup* parentGroup, int index );

};
37 changes: 37 additions & 0 deletions python/core/layertree/qgslayertreeutils.sip
@@ -0,0 +1,37 @@
/**
* Assorted functions for dealing with layer trees.
*
* @note added in 2.4
*/
class QgsLayerTreeUtils
{
%TypeHeaderCode
#include <qgslayertreeutils.h>
%End

public:

//! Try to load layer tree from <legend> tag from project files from QGIS 2.2 and below
static bool readOldLegend( QgsLayerTreeGroup* root, const QDomElement& legendElem );
//! Try to load custom layer order from <legend> tag from project files from QGIS 2.2 and below
static bool readOldLegendLayerOrder( const QDomElement& legendElem, bool& hasCustomOrder, QStringList& order );
//! Return <legend> tag used in QGIS 2.2 and below
static QDomElement writeOldLegend( QDomDocument& doc, QgsLayerTreeGroup* root, bool hasCustomOrder, const QStringList& order );

//! Convert Qt::CheckState to QString
static QString checkStateToXml( Qt::CheckState state );
//! Convert QString to Qt::CheckState
static Qt::CheckState checkStateFromXml( QString txt );

//! Return true if any of the layers is editable
static bool layersEditable( const QList<QgsLayerTreeLayer*>& layerNodes );
//! Return true if any of the layers is modified
static bool layersModified( const QList<QgsLayerTreeLayer*>& layerNodes );

//! Remove layer nodes that refer to invalid layers
static void removeInvalidLayers( QgsLayerTreeGroup* group );

//! Remove subtree of embedded groups. Useful when saving layer tree
static void removeChildrenOfEmbeddedGroups( QgsLayerTreeGroup* group );

};
4 changes: 4 additions & 0 deletions python/core/qgspallabeling.sip
Expand Up @@ -606,6 +606,10 @@ class QgsLabelComponent
*/
class QgsLabelingResults
{
%TypeHeaderCode
#include <qgspallabeling.h>
%End

public:
QgsLabelingResults();
~QgsLabelingResults();
Expand Down

0 comments on commit 73358c3

Please sign in to comment.