mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-10 00:05:25 -04:00
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:
parent
ad407f511b
commit
a62efcd455
@ -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,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 );
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user