Little improvement for label preview (box), better handling of situations where rotation is not possible

git-svn-id: http://svn.osgeo.org/qgis/trunk@14877 c8812cc2-4d05-0410-92ff-de0c093fc19c
This commit is contained in:
mhugent 2010-12-09 16:07:27 +00:00
parent ad407f511b
commit a62efcd455
6 changed files with 164 additions and 82 deletions

View File

@ -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;
}

View File

@ -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;
};

View File

@ -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;
}

View File

@ -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;

View File

@ -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,6 +114,7 @@ void QgsMapToolRotateLabel::canvasMoveEvent( QMouseEvent * e )
if ( mRotationItem )
{
mRotationItem->setSymbolRotation( displayValue );
setRotationPreviewBox( displayValue - mStartRotation );
mRotationItem->update();
}
}
@ -117,9 +122,16 @@ void QgsMapToolRotateLabel::canvasMoveEvent( QMouseEvent * e )
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 );
}

View File

@ -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;