Skip to content

Commit

Permalink
Merge pull request #46356 from domi4484/labelPositioningPoint
Browse files Browse the repository at this point in the history
  • Loading branch information
m-kuhn committed Jan 10, 2022
2 parents ecdc190 + 52e2c25 commit ef40878
Show file tree
Hide file tree
Showing 17 changed files with 510 additions and 310 deletions.
1 change: 1 addition & 0 deletions python/core/auto_generated/labeling/qgspallabeling.sip.in
Expand Up @@ -218,6 +218,7 @@ Contains settings for how a map layer will be labeled.
// (data defined only)
PositionX,
PositionY,
PositionPoint,
Hali,
Vali,
Rotation,
Expand Down
7 changes: 4 additions & 3 deletions python/gui/auto_generated/qgstextformatwidget.sip.in
Expand Up @@ -145,11 +145,12 @@ Sets the background color for the text preview widget.
:param color: background color
%End

void enableDataDefinedAlignment( bool enable );
void enableDataDefinedAlignment( bool enable ) /Deprecated/;
%Docstring
Controls whether data defined alignment buttons are enabled.
Update the enabled state of the data defined alignment buttons.

:param enable: set to ``True`` to enable alignment controls
.. deprecated::
QGIS 3.24
%End

virtual QgsExpressionContext createExpressionContext() const;
Expand Down
139 changes: 89 additions & 50 deletions src/app/labeling/qgsmaptoollabel.cpp
Expand Up @@ -36,6 +36,7 @@
#include "qgsstatusbar.h"
#include "qgslabelingresults.h"
#include "qgsexpressionnodeimpl.h"
#include "qgsreferencedgeometry.h"

#include <QMouseEvent>

Expand Down Expand Up @@ -630,7 +631,7 @@ QVariant QgsMapToolLabel::evaluateDataDefinedProperty( QgsPalLayerSettings::Prop
return labelSettings.dataDefinedProperties().value( property, context, defaultValue );
}

bool QgsMapToolLabel::currentLabelDataDefinedPosition( double &x, bool &xSuccess, double &y, bool &ySuccess, int &xCol, int &yCol ) const
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;
Expand All @@ -650,7 +651,7 @@ bool QgsMapToolLabel::currentLabelDataDefinedPosition( double &x, bool &xSuccess
return false;
}
}
else if ( !labelMoveable( vlayer, mCurrentLabel.settings, xCol, yCol ) )
else if ( !labelMoveable( vlayer, mCurrentLabel.settings, xCol, yCol, pointCol ) )
{
return false;
}
Expand All @@ -661,18 +662,37 @@ bool QgsMapToolLabel::currentLabelDataDefinedPosition( double &x, bool &xSuccess
return false;
}

if ( mCurrentLabel.pos.isUnplaced )
{
xSuccess = false;
ySuccess = false;
}
else
if ( !mCurrentLabel.pos.isUnplaced )
{
QgsAttributes attributes = f.attributes();
if ( !attributes.at( xCol ).isNull() )
x = attributes.at( xCol ).toDouble( &xSuccess );
if ( !attributes.at( yCol ).isNull() )
y = attributes.at( yCol ).toDouble( &ySuccess );

if ( mCurrentLabel.settings.dataDefinedProperties().isActive( QgsPalLayerSettings::PositionPoint ) )
{
if ( pointCol >= 0
&& !attributes.at( pointCol ).isNull() )
{
QVariant pointAsVariant = attributes.at( pointCol );
if ( pointAsVariant.canConvert<QgsGeometry>() )
{
const QgsGeometry geometry = pointAsVariant.value<QgsGeometry>();
if ( const QgsPoint *point = ( geometry.constGet() ? qgsgeometry_cast<const QgsPoint *>( geometry.constGet()->simplifiedTypeRef() ) : nullptr ) )
{
x = point->x();
y = point->y();

xSuccess = true;
ySuccess = true;
}
}
}
}
else
{
if ( !attributes.at( xCol ).isNull() )
x = attributes.at( xCol ).toDouble( &xSuccess );
if ( !attributes.at( yCol ).isNull() )
y = attributes.at( yCol ).toDouble( &ySuccess );
}
}

return true;
Expand Down Expand Up @@ -710,10 +730,10 @@ bool QgsMapToolLabel::currentLabelDataDefinedRotation( double &rotation, bool &r
//test, if data defined x- and y- values are not null. Otherwise, the position is determined by PAL and the rotation cannot be fixed
if ( !ignoreXY )
{
int xCol, yCol;
int xCol, yCol, pointCol;
double x, y;
bool xSuccess, ySuccess;
if ( !currentLabelDataDefinedPosition( x, xSuccess, y, ySuccess, xCol, yCol ) || !xSuccess || !ySuccess )
if ( !currentLabelDataDefinedPosition( x, xSuccess, y, ySuccess, xCol, yCol, pointCol ) || !xSuccess || !ySuccess )
{
return false;
}
Expand All @@ -723,6 +743,31 @@ bool QgsMapToolLabel::currentLabelDataDefinedRotation( double &rotation, bool &r
return true;
}

bool QgsMapToolLabel::changeCurrentLabelDataDefinedPosition( const QVariant &x, const QVariant &y )
{
if ( mCurrentLabel.settings.dataDefinedProperties().isActive( QgsPalLayerSettings::PositionPoint ) )
{
QString pointColName = dataDefinedColumnName( QgsPalLayerSettings::PositionPoint, mCurrentLabel.settings, mCurrentLabel.layer );
int pointCol = mCurrentLabel.layer->fields().lookupField( pointColName );

if ( !mCurrentLabel.layer->changeAttributeValue( mCurrentLabel.pos.featureId, pointCol, QVariant::fromValue( QgsReferencedGeometry( QgsGeometry::fromPointXY( QgsPoint( x.toDouble(), y.toDouble() ) ), mCurrentLabel.layer->crs() ) ) ) )
return false;
}
else
{
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;
}

return true;
}

bool QgsMapToolLabel::dataDefinedShowHide( QgsVectorLayer *vlayer, QgsFeatureId featureId, int &show, bool &showSuccess, int &showCol ) const
{
showSuccess = false;
Expand Down Expand Up @@ -782,40 +827,6 @@ bool QgsMapToolLabel::diagramMoveable( QgsVectorLayer *vlayer, int &xCol, int &y
return false;
}

bool QgsMapToolLabel::labelMoveable( QgsVectorLayer *vlayer, int &xCol, int &yCol ) const
{
if ( !vlayer || !vlayer->isEditable() || !vlayer->labelsEnabled() )
{
return false;
}

const auto constSubProviders = vlayer->labeling()->subProviders();
for ( const QString &providerId : constSubProviders )
{
if ( labelMoveable( vlayer, vlayer->labeling()->settings( providerId ), xCol, yCol ) )
return true;
}

return false;
}

bool QgsMapToolLabel::labelMoveable( QgsVectorLayer *vlayer, const QgsPalLayerSettings &settings, int &xCol, int &yCol ) const
{
QString xColName = dataDefinedColumnName( QgsPalLayerSettings::PositionX, settings, vlayer );
QString yColName = dataDefinedColumnName( QgsPalLayerSettings::PositionY, settings, vlayer );
//return !xColName.isEmpty() && !yColName.isEmpty();
xCol = vlayer->fields().lookupField( xColName );
yCol = vlayer->fields().lookupField( yColName );
return ( xCol != -1 && yCol != -1 );
}

bool QgsMapToolLabel::layerCanPin( QgsVectorLayer *vlayer, int &xCol, int &yCol ) const
{
// currently same as QgsMapToolLabel::labelMoveable, but may change
bool canPin = labelMoveable( vlayer, xCol, yCol );
return canPin;
}

bool QgsMapToolLabel::labelCanShowHide( QgsVectorLayer *vlayer, int &showCol ) const
{
if ( !vlayer || !vlayer->isEditable() || !vlayer->labelsEnabled() )
Expand Down Expand Up @@ -848,17 +859,45 @@ bool QgsMapToolLabel::isPinned()
{
// for diagrams, the isPinned attribute is not set. So we check directly if
// there's data defined.
int xCol, yCol;
int xCol, yCol, pointCol;
double x, y;
bool xSuccess, ySuccess;

if ( currentLabelDataDefinedPosition( x, xSuccess, y, ySuccess, xCol, yCol ) && xSuccess && ySuccess )
if ( currentLabelDataDefinedPosition( x, xSuccess, y, ySuccess, xCol, yCol, pointCol ) && xSuccess && ySuccess )
rc = true;
}

return rc;
}

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

if ( settings.dataDefinedProperties().isActive( QgsPalLayerSettings::PositionPoint ) )
{
QString pointColName = dataDefinedColumnName( QgsPalLayerSettings::PositionPoint, settings, vlayer );
pointCol = vlayer->fields().lookupField( pointColName );
if ( pointCol >= 0 )
return true;
}

if ( settings.dataDefinedProperties().isActive( QgsPalLayerSettings::PositionX )
&& settings.dataDefinedProperties().isActive( QgsPalLayerSettings::PositionY ) )
{
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 true;
}

return false;
}

bool QgsMapToolLabel::diagramCanShowHide( QgsVectorLayer *vlayer, int &showCol ) const
{
showCol = -1;
Expand Down
31 changes: 13 additions & 18 deletions src/app/labeling/qgsmaptoollabel.h
Expand Up @@ -45,15 +45,6 @@ class APP_EXPORT QgsMapToolLabel: public QgsMapToolAdvancedDigitizing

void deactivate() override;

/**
* Returns TRUE if label move can be applied to a layer
* \param xCol out: index of the attribute for data defined x coordinate
* \param yCol out: index of the attribute for data defined y coordinate
* \returns TRUE if labels of layer can be moved
*/
bool labelMoveable( QgsVectorLayer *vlayer, int &xCol, int &yCol ) const;
bool labelMoveable( QgsVectorLayer *vlayer, const QgsPalLayerSettings &settings, int &xCol, int &yCol ) const;

/**
* Returns true if diagram move can be applied to a layer
* \param xCol out: index of the attribute for data defined x coordinate
Expand All @@ -62,14 +53,6 @@ class APP_EXPORT QgsMapToolLabel: public QgsMapToolAdvancedDigitizing
*/
bool diagramMoveable( QgsVectorLayer *vlayer, int &xCol, int &yCol ) const;

/**
* Returns TRUE if layer has attribute fields set up
* \param xCol out: index of the attribute for data defined x coordinate
* \param yCol out: index of the attribute for data defined y coordinate
* \returns TRUE if layer fields set up and exist
*/
bool layerCanPin( QgsVectorLayer *vlayer, int &xCol, int &yCol ) const;

/**
* Returns TRUE if layer has attribute field set up for diagrams
* \param showCol out: attribute column for data defined diagram showing
Expand Down Expand Up @@ -187,9 +170,10 @@ class APP_EXPORT QgsMapToolLabel: public QgsMapToolAdvancedDigitizing
* \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 ) const;
bool currentLabelDataDefinedPosition( double &x, bool &xSuccess, double &y, bool &ySuccess, int &xCol, int &yCol, int &pointCol ) const;

/**
* Returns data defined rotation of current label
Expand All @@ -201,6 +185,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 All @@ -219,6 +212,8 @@ class APP_EXPORT QgsMapToolLabel: public QgsMapToolAdvancedDigitizing
*/
bool isPinned();

bool labelMoveable( QgsVectorLayer *vlayer, const QgsPalLayerSettings &settings, int &xCol, int &yCol, int &pointCol ) const;

bool createAuxiliaryFields( QgsPalIndexes &palIndexes );
bool createAuxiliaryFields( LabelDetails &details, QgsPalIndexes &palIndexes ) const;
bool createAuxiliaryFields( QgsDiagramIndexes &diagIndexes );
Expand Down

0 comments on commit ef40878

Please sign in to comment.