Skip to content
Permalink
Browse files

Show a highlight around the label which will be affected when hovering

over labels using one of the interactive labeling map tools

For busy labeling areas, this lets you see in advance exactly which
label the tool will move/hide/etc
  • Loading branch information
nyalldawson committed Feb 21, 2021
1 parent b306ae0 commit 03eaf9f296ef2675b82c67ffb5e5b785445ec45e
@@ -124,6 +124,11 @@ void QgsMapToolChangeLabelProperties::canvasReleaseEvent( QgsMapMouseEvent *e )
}
}

void QgsMapToolChangeLabelProperties::cadCanvasMoveEvent( QgsMapMouseEvent *e )
{
updateHoveredLabel( e );
}

void QgsMapToolChangeLabelProperties::applyChanges( const QgsAttributeMap &changes )
{
QgsVectorLayer *vlayer = mCurrentLabel.layer;
@@ -30,6 +30,7 @@ class APP_EXPORT QgsMapToolChangeLabelProperties: public QgsMapToolLabel

void canvasPressEvent( QgsMapMouseEvent *e ) override;
void canvasReleaseEvent( QgsMapMouseEvent *e ) override;
void cadCanvasMoveEvent( QgsMapMouseEvent *e ) override;

protected:

@@ -33,6 +33,7 @@
#include "qgisapp.h"
#include "qgsmapmouseevent.h"
#include "qgsadvanceddigitizingdockwidget.h"
#include "qgsstatusbar.h"

#include <QMouseEvent>

@@ -45,10 +46,17 @@ QgsMapToolLabel::QgsMapToolLabel( QgsMapCanvas *canvas, QgsAdvancedDigitizingDoc
QgsMapToolLabel::~QgsMapToolLabel()
{
delete mLabelRubberBand;
delete mHoverRubberBand;
delete mFeatureRubberBand;
delete mFixPointRubberBand;
}

void QgsMapToolLabel::deactivate()
{
clearHoveredLabel();
QgsMapToolAdvancedDigitizing::deactivate();
}

bool QgsMapToolLabel::labelAtPosition( QMouseEvent *e, QgsLabelPosition &p )
{
QgsPointXY pt = toMapCoordinates( e->pos() );
@@ -876,3 +884,60 @@ bool QgsMapToolLabel::createAuxiliaryFields( LabelDetails &details, QgsDiagramIn

return newAuxiliaryLayer;
}

void QgsMapToolLabel::updateHoveredLabel( QgsMapMouseEvent *e )
{
if ( !mHoverRubberBand )
{
mHoverRubberBand = new QgsRubberBand( mCanvas, QgsWkbTypes::LineGeometry );
mHoverRubberBand->setWidth( 2 );
mHoverRubberBand->setSecondaryStrokeColor( QColor( 255, 255, 255, 100 ) );
mHoverRubberBand->setColor( QColor( 200, 0, 120, 255 ) );
}
QgsLabelPosition labelPos;
if ( !labelAtPosition( e, labelPos ) )
{
mHoverRubberBand->hide();
mCurrentHoverLabel = LabelDetails();
return;
}

LabelDetails newHoverLabel( labelPos );

if ( mCurrentHoverLabel.valid &&
newHoverLabel.layer == mCurrentHoverLabel.layer &&
newHoverLabel.pos.featureId == mCurrentHoverLabel.pos.featureId &&
newHoverLabel.pos.providerID == mCurrentHoverLabel.pos.providerID
)
return;

if ( !canModifyLabel( newHoverLabel ) )
{
mHoverRubberBand->hide();
mCurrentHoverLabel = LabelDetails();
return;
}

mCurrentHoverLabel = newHoverLabel;

mHoverRubberBand->show();
mHoverRubberBand->reset( QgsWkbTypes::LineGeometry );
mHoverRubberBand->addPoint( labelPos.cornerPoints.at( 0 ) );
mHoverRubberBand->addPoint( labelPos.cornerPoints.at( 1 ) );
mHoverRubberBand->addPoint( labelPos.cornerPoints.at( 2 ) );
mHoverRubberBand->addPoint( labelPos.cornerPoints.at( 3 ) );
mHoverRubberBand->addPoint( labelPos.cornerPoints.at( 0 ) );
QgisApp::instance()->statusBarIface()->showMessage( tr( "Label “%1” in %2" ).arg( labelPos.labelText, mCurrentHoverLabel.layer->name() ), 2000 );
}

void QgsMapToolLabel::clearHoveredLabel()
{
if ( mHoverRubberBand )
mHoverRubberBand->hide();
mCurrentHoverLabel = LabelDetails();
}

bool QgsMapToolLabel::canModifyLabel( const QgsMapToolLabel::LabelDetails & )
{
return true;
}
@@ -38,6 +38,8 @@ class APP_EXPORT QgsMapToolLabel: public QgsMapToolAdvancedDigitizing
QgsMapToolLabel( QgsMapCanvas *canvas, QgsAdvancedDigitizingDockWidget *cadDock );
~QgsMapToolLabel() override;

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
@@ -84,6 +86,7 @@ class APP_EXPORT QgsMapToolLabel: public QgsMapToolAdvancedDigitizing
bool labelIsRotatable( QgsVectorLayer *layer, const QgsPalLayerSettings &settings, int &rotationCol ) const;

protected:
QgsRubberBand *mHoverRubberBand = nullptr;
QgsRubberBand *mLabelRubberBand = nullptr;
QgsRubberBand *mFeatureRubberBand = nullptr;
//! Shows label fixpoint (left/bottom by default)
@@ -102,6 +105,8 @@ class APP_EXPORT QgsMapToolLabel: public QgsMapToolAdvancedDigitizing
//! Currently dragged label position
LabelDetails mCurrentLabel;

//! Currently hovered label position
LabelDetails mCurrentHoverLabel;

/**
* Returns label position for mouse click location
@@ -203,6 +208,10 @@ class APP_EXPORT QgsMapToolLabel: public QgsMapToolAdvancedDigitizing
bool createAuxiliaryFields( QgsDiagramIndexes &diagIndexes, bool overwriteExpression = true );
bool createAuxiliaryFields( LabelDetails &details, QgsDiagramIndexes &diagIndexes, bool overwriteExpression = true );

void updateHoveredLabel( QgsMapMouseEvent *e );
void clearHoveredLabel();
virtual bool canModifyLabel( const LabelDetails &label );

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

@@ -24,6 +24,7 @@
#include "qgsmessagebar.h"
#include "qgsadvanceddigitizingdockwidget.h"


QgsMapToolMoveLabel::QgsMapToolMoveLabel( QgsMapCanvas *canvas, QgsAdvancedDigitizingDockWidget *cadDock )
: QgsMapToolLabel( canvas, cadDock )
{
@@ -50,6 +51,10 @@ void QgsMapToolMoveLabel::cadCanvasMoveEvent( QgsMapMouseEvent *e )
mFixPointRubberBand->updatePosition();
mFixPointRubberBand->update();
}
else
{
updateHoveredLabel( e );
}
}

void QgsMapToolMoveLabel::cadCanvasPressEvent( QgsMapMouseEvent *e )
@@ -69,6 +74,8 @@ void QgsMapToolMoveLabel::cadCanvasPressEvent( QgsMapMouseEvent *e )
return;
}

clearHoveredLabel();

mCurrentLabel = LabelDetails( labelPos );

QgsVectorLayer *vlayer = mCurrentLabel.layer;
@@ -80,6 +80,10 @@ void QgsMapToolRotateLabel::canvasMoveEvent( QgsMapMouseEvent *e )
mRotationItem->update();
}
}
else
{
updateHoveredLabel( e );
}
}

void QgsMapToolRotateLabel::canvasPressEvent( QgsMapMouseEvent *e )
@@ -91,6 +95,7 @@ void QgsMapToolRotateLabel::canvasPressEvent( QgsMapMouseEvent *e )

// first click starts rotation tool
deleteRubberBands();
clearHoveredLabel();

QgsLabelPosition labelPos;
if ( !labelAtPosition( e, labelPos ) )
@@ -288,6 +293,17 @@ void QgsMapToolRotateLabel::keyReleaseEvent( QKeyEvent *e )
}
}

bool QgsMapToolRotateLabel::canModifyLabel( const QgsMapToolLabel::LabelDetails &label )
{
// only rotate non-pinned OverPoint placements until other placements are supported in pal::Feature

if ( !label.pos.isPinned
&& label.settings.placement != QgsPalLayerSettings::OverPoint )
return false;

return true;
}

int QgsMapToolRotateLabel::roundTo15Degrees( double n )
{
int m = static_cast< int >( n / 15.0 + 0.5 );
@@ -36,6 +36,8 @@ class APP_EXPORT QgsMapToolRotateLabel: public QgsMapToolLabel

protected:

bool canModifyLabel( const LabelDetails &label ) override;

static int roundTo15Degrees( double n );
//! Converts azimuth value so that 0 is corresponds to East
static double convertAzimuth( double a );
@@ -48,6 +48,8 @@ void QgsMapToolShowHideLabels::canvasPressEvent( QgsMapMouseEvent *e )
{
Q_UNUSED( e )

clearHoveredLabel();

QgsMapLayer *layer = mCanvas->currentLayer();
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
if ( !vlayer )
@@ -74,8 +76,13 @@ void QgsMapToolShowHideLabels::canvasPressEvent( QgsMapMouseEvent *e )
void QgsMapToolShowHideLabels::canvasMoveEvent( QgsMapMouseEvent *e )
{
if ( e->buttons() != Qt::LeftButton )
{
if ( !mDragging )
updateHoveredLabel( e );
return;
}

clearHoveredLabel();
if ( !mDragging )
{
mDragging = true;

0 comments on commit 03eaf9f

Please sign in to comment.