Skip to content
Permalink
Browse files

[feature] Allow auto-creation of callout auxiliary fields when

attempting to move a callout start or end point interactively

Makes the user experience for moving a callout follow the exact
same behavior as that of moving a label, where aux fields are
immediately created for users whenever required instead
of forcing them to create them themselves in advance.
  • Loading branch information
nyalldawson committed Mar 15, 2021
1 parent a1fa68d commit f557a19bf49195fa1d620c70beed5bb219bd4686
@@ -877,7 +877,6 @@ bool QgsMapToolLabel::createAuxiliaryFields( QgsDiagramIndexes &indexes, bool ov
return createAuxiliaryFields( mCurrentLabel, indexes, overwriteExpression );
}


bool QgsMapToolLabel::createAuxiliaryFields( LabelDetails &details, QgsDiagramIndexes &indexes, bool overwriteExpression )
{
bool newAuxiliaryLayer = false;
@@ -922,6 +921,56 @@ bool QgsMapToolLabel::createAuxiliaryFields( LabelDetails &details, QgsDiagramIn
return newAuxiliaryLayer;
}

bool QgsMapToolLabel::createAuxiliaryFields( QgsCalloutIndexes &calloutIndexes, bool overwriteExpression )
{
return createAuxiliaryFields( mCurrentCallout, calloutIndexes, overwriteExpression );
}

bool QgsMapToolLabel::createAuxiliaryFields( QgsCalloutPosition &details, QgsCalloutIndexes &calloutIndexes, bool overwriteExpression )
{
bool newAuxiliaryLayer = false;
QgsVectorLayer *vlayer = QgsProject::instance()->mapLayer<QgsVectorLayer *>( details.layerID );

if ( !vlayer )
return newAuxiliaryLayer;

if ( !vlayer->auxiliaryLayer() )
{
QgsNewAuxiliaryLayerDialog dlg( vlayer );
dlg.exec();
newAuxiliaryLayer = true;
}

if ( !vlayer->auxiliaryLayer() )
return false;

QgsTemporaryCursorOverride cursor( Qt::WaitCursor );
bool changed = false;
for ( const QgsCallout::Property &p : qgis::as_const( mCalloutProperties ) )
{
int index = -1;

// always use the default activated property
QgsProperty prop = vlayer->labeling() && vlayer->labeling()->settings( details.providerID ).callout() ? vlayer->labeling()->settings( details.providerID ).callout()->dataDefinedProperties().property( p ) :
QgsProperty();
if ( prop.propertyType() == QgsProperty::FieldBasedProperty && prop.isActive() )
{
index = vlayer->fields().lookupField( prop.field() );
}
else if ( prop.propertyType() != QgsProperty::ExpressionBasedProperty || overwriteExpression )
{
index = QgsAuxiliaryLayer::createProperty( p, vlayer );
changed = true;
}

calloutIndexes[p] = index;
}
if ( changed )
emit vlayer->styleChanged();

return newAuxiliaryLayer;
}

void QgsMapToolLabel::updateHoveredLabel( QgsMapMouseEvent *e )
{
if ( !mHoverRubberBand )
@@ -938,9 +987,7 @@ void QgsMapToolLabel::updateHoveredLabel( QgsMapMouseEvent *e )

QgsCalloutPosition calloutPosition;
bool isOrigin = false;
int xCol = 0;
int yCol = 0;
if ( calloutAtPosition( e, calloutPosition, isOrigin ) && canModifyCallout( calloutPosition, isOrigin, xCol, yCol ) )
if ( calloutAtPosition( e, calloutPosition, isOrigin ) )
{
if ( !mCalloutOtherPointsRubberBand )
{
@@ -23,12 +23,14 @@
#include "qgsnewauxiliarylayerdialog.h"
#include "qgsauxiliarystorage.h"
#include "qgscalloutposition.h"
#include "qgscallout.h"
#include "qgis_app.h"

class QgsRubberBand;

typedef QMap<QgsPalLayerSettings::Property, int> QgsPalIndexes;
typedef QMap<QgsDiagramLayerSettings::Property, int> QgsDiagramIndexes;
typedef QMap<QgsCallout::Property, int> QgsCalloutIndexes;

//! Base class for map tools that modify label properties
class APP_EXPORT QgsMapToolLabel: public QgsMapToolAdvancedDigitizing
@@ -112,6 +114,8 @@ class APP_EXPORT QgsMapToolLabel: public QgsMapToolAdvancedDigitizing
//! Currently hovered label position
LabelDetails mCurrentHoverLabel;

QgsCalloutPosition mCurrentCallout;

/**
* Returns label position for mouse click location
* \param e mouse event
@@ -220,6 +224,8 @@ class APP_EXPORT QgsMapToolLabel: public QgsMapToolAdvancedDigitizing
bool createAuxiliaryFields( LabelDetails &details, QgsPalIndexes &palIndexes, bool overwriteExpression = true ) const;
bool createAuxiliaryFields( QgsDiagramIndexes &diagIndexes, bool overwriteExpression = true );
bool createAuxiliaryFields( LabelDetails &details, QgsDiagramIndexes &diagIndexes, bool overwriteExpression = true );
bool createAuxiliaryFields( QgsCalloutIndexes &calloutIndexes, bool overwriteExpression = true );
bool createAuxiliaryFields( QgsCalloutPosition &details, QgsCalloutIndexes &calloutIndexes, bool overwriteExpression = true );

void updateHoveredLabel( QgsMapMouseEvent *e );
void clearHoveredLabel();
@@ -228,6 +234,7 @@ class APP_EXPORT QgsMapToolLabel: public QgsMapToolAdvancedDigitizing

QList<QgsPalLayerSettings::Property> mPalProperties;
QList<QgsDiagramLayerSettings::Property> mDiagramProperties;
QList<QgsCallout::Property> mCalloutProperties;

friend class TestQgsMapToolLabel;
};
@@ -37,6 +37,11 @@ QgsMapToolMoveLabel::QgsMapToolMoveLabel( QgsMapCanvas *canvas, QgsAdvancedDigit

mDiagramProperties << QgsDiagramLayerSettings::PositionX;
mDiagramProperties << QgsDiagramLayerSettings::PositionY;

mCalloutProperties << QgsCallout::OriginX;
mCalloutProperties << QgsCallout::OriginY;
mCalloutProperties << QgsCallout::DestinationX;
mCalloutProperties << QgsCallout::DestinationY;
}

QgsMapToolMoveLabel::~QgsMapToolMoveLabel()
@@ -100,8 +105,19 @@ void QgsMapToolMoveLabel::cadCanvasPressEvent( QgsMapMouseEvent *e )

int xCol = 0;
int yCol = 0;
if ( calloutAtPosition( e, calloutPosition, mCurrentCalloutMoveOrigin ) && canModifyCallout( calloutPosition, mCurrentCalloutMoveOrigin, xCol, yCol ) )
if ( calloutAtPosition( e, calloutPosition, mCurrentCalloutMoveOrigin ) )
{
if ( !canModifyCallout( calloutPosition, mCurrentCalloutMoveOrigin, xCol, yCol ) )
{
QgsCalloutIndexes indexes;

if ( createAuxiliaryFields( calloutPosition, indexes ) )
return;

if ( !canModifyCallout( calloutPosition, mCurrentCalloutMoveOrigin, xCol, yCol ) )
return;
}

// callouts are a smaller target, so they take precedence over labels
mCurrentLabel = LabelDetails();
mCurrentCallout = calloutPosition;
@@ -43,7 +43,6 @@ class APP_EXPORT QgsMapToolMoveLabel: public QgsMapToolLabel

bool canModifyCallout( const QgsCalloutPosition &position, bool isOrigin, int &xCol, int &yCol ) override;

QgsCalloutPosition mCurrentCallout;
bool mCurrentCalloutMoveOrigin = false;

QgsRubberBand *mCalloutMoveRubberBand = nullptr;

0 comments on commit f557a19

Please sign in to comment.