Skip to content

Commit

Permalink
Add possibility do data define label position by point instead of X/Y
Browse files Browse the repository at this point in the history
  • Loading branch information
domi4484 committed Jan 10, 2022
1 parent 6d2c424 commit ff04cbb
Show file tree
Hide file tree
Showing 15 changed files with 396 additions and 100 deletions.
26 changes: 25 additions & 1 deletion python/core/auto_generated/geometry/qgsreferencedgeometry.sip.in
Expand Up @@ -163,13 +163,37 @@ Construct a new QgsReferencedGeometry from referenced ``point``
Construct a new QgsReferencedGeometry from referenced ``rectangle``
%End

static QgsReferencedGeometry fromEwkt( const QString &ewkt );
%Docstring
Creates a new geometry from a EWKT string

.. note::

Assumes a string in the format SRID={EPSG Id};WKT

.. seealso:: :py:func:`asEwkt`

.. versionadded:: 3.22
%End

QString asEwkt( int precision = 17 ) const;
%Docstring
Exports the geometry to EWKT

:param precision: number of decimal places for coordinates

:return: the EWKT string in format SRID={EPSG Id};WKT

.. seealso:: :py:func:`fromEwkt`

.. versionadded:: 3.22
%End

SIP_PYOBJECT __repr__();
%MethodCode
QString str = QStringLiteral( "<QgsReferencedGeometry: %1 (%2)>" ).arg( sipCpp->asWkt(), sipCpp->crs().authid() );
sipRes = PyUnicode_FromString( str.toUtf8().constData() );
%End

};


Expand Down
Expand Up @@ -11,7 +11,7 @@



class QgsAbstractVectorLayerLabeling : QObject
class QgsAbstractVectorLayerLabeling
{
%Docstring(signature="appended")
Abstract base class - its implementations define different approaches to the labeling of a vector layer.
Expand All @@ -21,6 +21,14 @@ Abstract base class - its implementations define different approaches to the lab

%TypeHeaderCode
#include "qgsvectorlayerlabeling.h"
%End
%ConvertToSubClassCode
if ( sipCpp->type() == "simple" )
sipType = sipType_QgsVectorLayerSimpleLabeling;
else if ( sipCpp->type() == "rule-based" )
sipType = sipType_QgsRuleBasedLabeling;
else
sipType = 0;
%End
public:
QgsAbstractVectorLayerLabeling();
Expand Down Expand Up @@ -104,10 +112,6 @@ Returns the default layer settings to use for the specified vector ``layer``.
.. versionadded:: 3.20
%End

signals:

void labelingChanged();

protected:

virtual void writeTextSymbolizer( QDomNode &parent, QgsPalLayerSettings &settings, const QVariantMap &props ) const;
Expand Down
143 changes: 143 additions & 0 deletions src/app/labeling/qgsmaptoollabel.cpp
Expand Up @@ -678,6 +678,88 @@ bool QgsMapToolLabel::currentLabelDataDefinedPosition( double &x, bool &xSuccess
return true;
}

bool QgsMapToolLabel::currentLabelDataDefinedPosition( double &x, bool &xSuccess, double &y, bool &ySuccess, int &xCol, int &yCol, int &pointCol ) const
{
QgsVectorLayer *vlayer = mCurrentLabel.layer;
QgsFeatureId featureId = mCurrentLabel.pos.featureId;

xSuccess = false;
ySuccess = false;

if ( !vlayer )
{
return false;
}

if ( mCurrentLabel.pos.isDiagram )
{
if ( !diagramMoveable( vlayer, xCol, yCol ) )
{
return false;
}
}
else if ( !labelMoveable( vlayer, mCurrentLabel.settings, xCol, yCol, pointCol ) )
{
return false;
}

QgsFeature f;
if ( !vlayer->getFeatures( QgsFeatureRequest().setFilterFid( featureId ).setFlags( QgsFeatureRequest::NoGeometry ) ).nextFeature( f ) )
{
return false;
}

if ( !mCurrentLabel.pos.isUnplaced )
{
QgsAttributes attributes = f.attributes();
switch ( mCurrentLabel.settings.placementCoordinateType() )
{
case QgsLabeling::CoordinateType::XY:
{
if ( !attributes.at( xCol ).isNull() )
x = attributes.at( xCol ).toDouble( &xSuccess );
if ( !attributes.at( yCol ).isNull() )
y = attributes.at( yCol ).toDouble( &ySuccess );
}
break;
case QgsLabeling::CoordinateType::Point:
{
if ( !attributes.at( pointCol ).isNull() )
{
QVariant pointAsVariant = attributes.at( pointCol );
if ( pointAsVariant.canConvert<QgsGeometry>() )
{
QgsGeometry geometryPoint = pointAsVariant.value<QgsGeometry>();
const QgsPoint *point = qgsgeometry_cast<QgsPoint *>( geometryPoint.constGet() );

x = point->x();
y = point->y();

xSuccess = true;
ySuccess = true;
}
else if ( !pointAsVariant.toByteArray().isEmpty() )
{
QgsPoint point;
QgsConstWkbPtr wkbPtr( pointAsVariant.toByteArray() );
if ( point.fromWkb( wkbPtr ) )
{
x = point.x();
y = point.y();

xSuccess = true;
ySuccess = true;
}
}
}
}
break;
}
}

return true;
}

bool QgsMapToolLabel::labelIsRotatable( QgsVectorLayer *layer, const QgsPalLayerSettings &settings, int &rotationCol ) const
{
QString rColName = dataDefinedColumnName( QgsPalLayerSettings::LabelRotation, settings, layer );
Expand Down Expand Up @@ -723,6 +805,36 @@ bool QgsMapToolLabel::currentLabelDataDefinedRotation( double &rotation, bool &r
return true;
}

bool QgsMapToolLabel::changeCurrentLabelDataDefinedPosition( const QVariant &x, const QVariant &y )
{
switch ( mCurrentLabel.settings.placementCoordinateType() )
{
case QgsLabeling::CoordinateType::XY:
{
QString xColName = dataDefinedColumnName( QgsPalLayerSettings::PositionX, mCurrentLabel.settings, mCurrentLabel.layer );
QString yColName = dataDefinedColumnName( QgsPalLayerSettings::PositionY, mCurrentLabel.settings, mCurrentLabel.layer );
int xCol = mCurrentLabel.layer->fields().lookupField( xColName );
int yCol = mCurrentLabel.layer->fields().lookupField( yColName );

if ( !mCurrentLabel.layer->changeAttributeValue( mCurrentLabel.pos.featureId, xCol, x )
|| !mCurrentLabel.layer->changeAttributeValue( mCurrentLabel.pos.featureId, yCol, y ) )
return false;
}
break;
case QgsLabeling::CoordinateType::Point:
{
QString pointColName = dataDefinedColumnName( QgsPalLayerSettings::PositionPoint, mCurrentLabel.settings, mCurrentLabel.layer );
int pointCol = mCurrentLabel.layer->fields().lookupField( pointColName );

if ( !mCurrentLabel.layer->changeAttributeValue( mCurrentLabel.pos.featureId, pointCol, QgsPoint( x.toDouble(), y.toDouble() ).asWkt() ) )
return false;
}
break;
}

return true;
}

bool QgsMapToolLabel::dataDefinedShowHide( QgsVectorLayer *vlayer, QgsFeatureId featureId, int &show, bool &showSuccess, int &showCol ) const
{
showSuccess = false;
Expand Down Expand Up @@ -809,6 +921,37 @@ bool QgsMapToolLabel::labelMoveable( QgsVectorLayer *vlayer, const QgsPalLayerSe
return ( xCol != -1 && yCol != -1 );
}

bool QgsMapToolLabel::labelMoveable( QgsVectorLayer *vlayer, const QgsPalLayerSettings &settings, int &xCol, int &yCol, int &pointCol ) const
{
xCol = -1;
yCol = -1;
pointCol = -1;

switch ( mCurrentLabel.settings.placementCoordinateType() )
{
case QgsLabeling::CoordinateType::XY:
{
QString xColName = dataDefinedColumnName( QgsPalLayerSettings::PositionX, settings, vlayer );
QString yColName = dataDefinedColumnName( QgsPalLayerSettings::PositionY, settings, vlayer );
xCol = vlayer->fields().lookupField( xColName );
yCol = vlayer->fields().lookupField( yColName );
if ( xCol <= 0 && yCol <= 0 )
return false;
}
break;
case QgsLabeling::CoordinateType::Point:
{
QString pointColName = dataDefinedColumnName( QgsPalLayerSettings::PositionPoint, settings, vlayer );
pointCol = vlayer->fields().lookupField( pointColName );
if ( pointCol <= 0 )
return false;
}
break;
}

return true;
}

bool QgsMapToolLabel::layerCanPin( QgsVectorLayer *vlayer, int &xCol, int &yCol ) const
{
// currently same as QgsMapToolLabel::labelMoveable, but may change
Expand Down
23 changes: 23 additions & 0 deletions src/app/labeling/qgsmaptoollabel.h
Expand Up @@ -53,6 +53,7 @@ class APP_EXPORT QgsMapToolLabel: public QgsMapToolAdvancedDigitizing
*/
bool labelMoveable( QgsVectorLayer *vlayer, int &xCol, int &yCol ) const;
bool labelMoveable( QgsVectorLayer *vlayer, const QgsPalLayerSettings &settings, int &xCol, int &yCol ) const;
bool labelMoveable( QgsVectorLayer *vlayer, const QgsPalLayerSettings &settings, int &xCol, int &yCol, int &pointCol ) const;

/**
* Returns true if diagram move can be applied to a layer
Expand Down Expand Up @@ -191,6 +192,19 @@ class APP_EXPORT QgsMapToolLabel: public QgsMapToolAdvancedDigitizing
*/
bool currentLabelDataDefinedPosition( double &x, bool &xSuccess, double &y, bool &ySuccess, int &xCol, int &yCol ) const;

/**
* Gets data defined position of current label
* \param x out: data defined x-coordinate
* \param xSuccess out: FALSE if attribute value is NULL
* \param y out: data defined y-coordinate
* \param ySuccess out: FALSE if attribute value is NULL
* \param xCol out: index of the x position column
* \param yCol out: index of the y position column
* \param pointCol out: index of the point position column
* \returns FALSE if layer does not have data defined label position enabled
*/
bool currentLabelDataDefinedPosition( double &x, bool &xSuccess, double &y, bool &ySuccess, int &xCol, int &yCol, int &pointCol ) const;

/**
* Returns data defined rotation of current label
* \param rotation out: rotation value
Expand All @@ -201,6 +215,15 @@ class APP_EXPORT QgsMapToolLabel: public QgsMapToolAdvancedDigitizing
*/
bool currentLabelDataDefinedRotation( double &rotation, bool &rotationSuccess, int &rCol, bool ignoreXY = false ) const;

/**
* Change the data defined position of current label
* \param rCol out: index of the rotation column
* \param x data defined x-coordinate
* \param y data defined y-coordinate
* \returns TRUE if data defined position could be changed
*/
bool changeCurrentLabelDataDefinedPosition( const QVariant &x, const QVariant &y );

/**
* Returns data defined show/hide of a feature.
* \param vlayer vector layer
Expand Down

0 comments on commit ff04cbb

Please sign in to comment.