Skip to content
Permalink
Browse files
Little improvement for label preview (box), better handling of situat…
…ions where rotation is not possible

git-svn-id: http://svn.osgeo.org/qgis/trunk/qgis@14877 c8812cc2-4d05-0410-92ff-de0c093fc19c
  • Loading branch information
mhugent committed Dec 9, 2010
1 parent 643608c commit 9ef391f
Show file tree
Hide file tree
Showing 6 changed files with 164 additions and 82 deletions.
@@ -345,3 +345,66 @@ bool QgsMapToolLabel::rotationPoint( QgsPoint& pos )
}
return true;
}

bool QgsMapToolLabel::dataDefinedPosition( QgsVectorLayer* vlayer, int featureId, double& x, bool& xSuccess, double& y, bool& ySuccess, int& xCol, int& yCol ) const
{
xSuccess = false;
ySuccess = false;

if ( !vlayer )
{
return false;
}

if ( !layerIsMoveable( vlayer, xCol, yCol ) )
{
return false;
}

QgsFeature f;
if ( !vlayer->featureAtId( featureId, f, false, true ) )
{
return false;
}

QgsAttributeMap attributes = f.attributeMap();
x = attributes[xCol].toDouble( &xSuccess );
y = attributes[yCol].toDouble( &ySuccess );

return true;
}

bool QgsMapToolLabel::layerIsMoveable( const QgsMapLayer* ml, int& xCol, int& yCol ) const
{
const QgsVectorLayer* vlayer = dynamic_cast<const QgsVectorLayer*>( ml );
if ( !vlayer || !vlayer->isEditable() )
{
return false;
}

bool xColOk, yColOk;

QVariant xColumn = ml->customProperty( "labeling/dataDefinedProperty9" );
if ( !xColumn.isValid() )
{
return false;
}
xCol = xColumn.toInt( &xColOk );
if ( !xColOk )
{
return false;
}

QVariant yColumn = ml->customProperty( "labeling/dataDefinedProperty10" );
if ( !yColumn.isValid() )
{
return false;
}
yCol = yColumn.toInt( &yColOk );
if ( !yColOk )
{
return false;
}

return true;
}
@@ -31,6 +31,12 @@ class QgsMapToolLabel: public QgsMapTool
QgsMapToolLabel( QgsMapCanvas* canvas );
~QgsMapToolLabel();

/**Returns true if layer 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
@return true if labels of layer can be moved*/
bool layerIsMoveable( const QgsMapLayer* ml, int& xCol, int& yCol ) const;

protected:
QgsRubberBand* mLabelRubberBand;
QgsRubberBand* mFeatureRubberBand;
@@ -73,6 +79,17 @@ class QgsMapToolLabel: public QgsMapTool
/**Returns the font for the current feature (considering default font and data defined properties*/
QFont labelFontCurrentFeature();

/**Get data defined position of a feature
@param layerId layer identification string
@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
@return false if layer does not have data defined label position enabled*/
bool dataDefinedPosition( QgsVectorLayer* vlayer, int featureId, double& x, bool& xSuccess, double& y, bool& ySuccess, int& xCol, int& yCol ) const;

private:
QgsPalLayerSettings mInvalidLabelSettings;
};
@@ -116,8 +116,6 @@ void QgsMapToolMoveLabel::canvasReleaseEvent( QMouseEvent * e )
{
xPosNew = releaseCoords.x() - mClickOffsetX;
yPosNew = releaseCoords.y() - mClickOffsetY;

//todo: consider hali/vali if there
}
else
{
@@ -133,68 +131,5 @@ void QgsMapToolMoveLabel::canvasReleaseEvent( QMouseEvent * e )
mCanvas->refresh();
}

bool QgsMapToolMoveLabel::dataDefinedPosition( QgsVectorLayer* vlayer, int featureId, double& x, bool& xSuccess, double& y, bool& ySuccess, int& xCol, int& yCol ) const
{
xSuccess = false;
ySuccess = false;

if ( !vlayer )
{
return false;
}

if ( !layerIsMoveable( vlayer, xCol, yCol ) )
{
return false;
}

QgsFeature f;
if ( !vlayer->featureAtId( featureId, f, false, true ) )
{
return false;
}

QgsAttributeMap attributes = f.attributeMap();
x = attributes[xCol].toDouble( &xSuccess );
y = attributes[yCol].toDouble( &ySuccess );

return true;
}

bool QgsMapToolMoveLabel::layerIsMoveable( const QgsMapLayer* ml, int& xCol, int& yCol ) const
{
const QgsVectorLayer* vlayer = dynamic_cast<const QgsVectorLayer*>( ml );
if ( !vlayer || !vlayer->isEditable() )
{
return false;
}

bool xColOk, yColOk;

QVariant xColumn = ml->customProperty( "labeling/dataDefinedProperty9" );
if ( !xColumn.isValid() )
{
return false;
}
xCol = xColumn.toInt( &xColOk );
if ( !xColOk )
{
return false;
}

QVariant yColumn = ml->customProperty( "labeling/dataDefinedProperty10" );
if ( !yColumn.isValid() )
{
return false;
}
yCol = yColumn.toInt( &yColOk );
if ( !yColOk )
{
return false;
}

return true;
}



@@ -35,23 +35,7 @@ class QgsMapToolMoveLabel: public QgsMapToolLabel

virtual void canvasReleaseEvent( QMouseEvent * e );

/**Returns true if layer 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
@return true if labels of layer can be moved*/
bool layerIsMoveable( const QgsMapLayer* ml, int& xCol, int& yCol ) const;

protected:
/**Get data defined position of a feature
@param layerId layer identification string
@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
@return false if layer does not have data defined label position enabled*/
bool dataDefinedPosition( QgsVectorLayer* vlayer, int featureId, double& x, bool& xSuccess, double& y, bool& ySuccess, int& xCol, int& yCol ) const;

/**Start point of the move in map coordinates*/
QgsPoint mStartPointMapCoords;
@@ -26,13 +26,14 @@

#include "qgisapp.h"

QgsMapToolRotateLabel::QgsMapToolRotateLabel( QgsMapCanvas* canvas ): QgsMapToolLabel( canvas ), mRotationItem( 0 )
QgsMapToolRotateLabel::QgsMapToolRotateLabel( QgsMapCanvas* canvas ): QgsMapToolLabel( canvas ), mRotationItem( 0 ), mRotationPreviewBox( 0 )
{
}

QgsMapToolRotateLabel::~QgsMapToolRotateLabel()
{
delete mRotationItem;
delete mRotationPreviewBox;
}

void QgsMapToolRotateLabel::canvasPressEvent( QMouseEvent * e )
@@ -68,8 +69,11 @@ void QgsMapToolRotateLabel::canvasPressEvent( QMouseEvent * e )
{
mCurrentRotation = 0;
}
mStartRotation = mCurrentRotation;
createRubberBands();

mRotationPreviewBox = createRotationPreviewBox();

mRotationItem = new QgsPointRotationItem( mCanvas );
mRotationItem->setOrientation( QgsPointRotationItem::Counterclockwise );
mRotationItem->setSymbol( QgisApp::instance()->getThemePixmap( "mActionRotatePointSymbols.png" ).toImage() );
@@ -110,16 +114,24 @@ void QgsMapToolRotateLabel::canvasMoveEvent( QMouseEvent * e )
if ( mRotationItem )
{
mRotationItem->setSymbolRotation( displayValue );
setRotationPreviewBox( displayValue - mStartRotation );
mRotationItem->update();
}
}
}

void QgsMapToolRotateLabel::canvasReleaseEvent( QMouseEvent * e )
{
if ( !mLabelRubberBand ) //no rubber band created (most likely because the current label cannot be rotated )
{
return;
}

deleteRubberBands();
delete mRotationItem;
mRotationItem = 0;
delete mRotationPreviewBox;
mRotationPreviewBox = 0;

QgsMapLayer* layer = QgsMapLayerRegistry::instance()->mapLayer( mCurrentLabelPos.layerID );
if ( !layer )
@@ -140,6 +152,10 @@ void QgsMapToolRotateLabel::canvasReleaseEvent( QMouseEvent * e )
}

double rotation = mCtrlPressed ? roundTo15Degrees( mCurrentRotation ) : mCurrentRotation;
if ( rotation == mStartRotation ) //mouse button pressed / released, but no rotation
{
return;
}

vlayer->beginEditCommand( tr( "Label rotated" ) );
vlayer->changeAttributeValue( mCurrentLabelPos.featureId, rotationCol, rotation, false );
@@ -191,6 +207,16 @@ bool QgsMapToolRotateLabel::dataDefinedRotation( QgsVectorLayer* vlayer, int fea
}

QgsAttributeMap attributes = f.attributeMap();

//test, if data defined x- and y- values are not null. Otherwise, the position is determined by PAL and the rotation cannot be fixed
int xCol, yCol;
double x, y;
bool xSuccess, ySuccess;
if ( !dataDefinedPosition( vlayer, featureId, x, xSuccess, y, ySuccess, xCol, yCol ) || !xSuccess || !ySuccess )
{
return false;
}

rotation = attributes[rotationCol].toDouble( &rotationSuccess );
return true;
}
@@ -205,3 +231,53 @@ double QgsMapToolRotateLabel::azimuthToCCW( double a )
{
return ( a > 0 ? 360 - a : -a );
}

QgsRubberBand* QgsMapToolRotateLabel::createRotationPreviewBox()
{
delete mRotationPreviewBox;
QVector< QgsPoint > boxPoints = mCurrentLabelPos.cornerPoints;
if ( boxPoints.size() < 1 )
{
return 0;
}

mRotationPreviewBox = new QgsRubberBand( mCanvas, false );
mRotationPreviewBox->setColor( Qt::blue );
mRotationPreviewBox->setWidth( 3 );
setRotationPreviewBox( mCurrentRotation - mStartRotation );
return mRotationPreviewBox;
}

void QgsMapToolRotateLabel::setRotationPreviewBox( double rotation )
{
if ( !mRotationPreviewBox )
{
return;
}

mRotationPreviewBox->reset();
QVector< QgsPoint > boxPoints = mCurrentLabelPos.cornerPoints;
if ( boxPoints.size() < 1 )
{
return;
}

for ( int i = 0; i < boxPoints.size(); ++i )
{
mRotationPreviewBox->addPoint( rotatePointCounterClockwise( boxPoints.at( i ), mRotationPoint, rotation ) );
}
mRotationPreviewBox->addPoint( rotatePointCounterClockwise( boxPoints.at( 0 ), mRotationPoint, rotation ) );
mRotationPreviewBox->show();
}

QgsPoint QgsMapToolRotateLabel::rotatePointCounterClockwise( const QgsPoint& input, const QgsPoint& centerPoint, double degrees )
{
double rad = degrees / 180 * M_PI;
double v1x = input.x() - centerPoint.x();
double v1y = input.y() - centerPoint.y();

double v2x = cos( rad ) * v1x - sin( rad ) * v1y;
double v2y = sin( rad ) * v1x + cos( rad ) * v1y;

return QgsPoint( centerPoint.x() + v2x, centerPoint.y() + v2y );
}
@@ -49,11 +49,18 @@ class QgsMapToolRotateLabel: public QgsMapToolLabel
/**Converts azimuth value to counterclockwise 0 - 360*/
static double azimuthToCCW( double a );

QgsRubberBand* createRotationPreviewBox();
void setRotationPreviewBox( double rotation );

/**Rotates input point counterclockwise around centerPoint*/
QgsPoint rotatePointCounterClockwise( const QgsPoint& input, const QgsPoint& centerPoint, double degrees );

double mStartRotation; //rotation value prior to start rotating
double mCurrentRotation;
double mCurrentMouseAzimuth;
QgsPoint mRotationPoint;
QgsPointRotationItem* mRotationItem;
QgsRubberBand* mRotationPreviewBox;

/**True if ctrl was pressed during the last mouse move event*/
bool mCtrlPressed;

0 comments on commit 9ef391f

Please sign in to comment.