Skip to content

Commit f7a3af3

Browse files
committedAug 2, 2012
Fix and update to Freeze/Thaw, Move, and Rotate Label tools
Updates - Move tool now preserves calculated x, y offset for upside-down labels, when initially moved and data-defined fields have no previous data. - Move tool now stores the label's PAL solution for rotation on initial move, if rotation is data-defined with no previous data. - Freeze/Thaw and Move tools now support all variations of previously data-defined halign and valign options on initial freeze. - Freeze/Thaw tool has updated key modifiers that should work across major platforms. - Tests for whether layer labels support data-defined rotation moved to base QgsMapToolLabel class. Fixes - Fix bug where labels defined in map units causing font to show as pointsize of same integer at small map scales. - Half of a fix for rotation point of labels with data-defined size of map units actually being based off of point size. (still references the layer-defined font size somewhere in the rotation point calculation) - Valign settings of Base and Half now more accurately key off of inverse of font ascent (instead of descent). No discernible shift occurs now on initial freeze.
1 parent b4b1c49 commit f7a3af3

8 files changed

+134
-86
lines changed
 

‎src/app/qgsmaptoolfreezelabels.cpp

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -257,8 +257,8 @@ void QgsMapToolFreezeLabels::freezeThawLabels( const QgsRectangle& ext, QMouseEv
257257
{
258258

259259
bool doThaw = e->modifiers() & Qt::ShiftModifier ? true : false;
260-
bool toggleThawOrFreeze = e->modifiers() & Qt::AltModifier ? true : false;
261-
bool doHide = e->modifiers() & Qt::ControlModifier ? true : false;
260+
bool toggleThawOrFreeze = e->modifiers() & Qt::ControlModifier ? true : false;
261+
bool doHide = ( doThaw && toggleThawOrFreeze );
262262

263263
// get list of all drawn labels from all layers within, or touching, chosen extent
264264
bool labelChanged = false;
@@ -432,16 +432,23 @@ bool QgsMapToolFreezeLabels::freezeThawLabel( QgsVectorLayer* vlayer,
432432
if ( freeze )
433433
{
434434

435-
QgsPoint labelpoint = labelpos.cornerPoints.at( 0 );
435+
// QgsPoint labelpoint = labelpos.cornerPoints.at( 0 );
436436

437-
double labelX = labelpoint.x();
438-
double labelY = labelpoint.y();
437+
QgsPoint referencePoint;
438+
if ( !rotationPoint( referencePoint, true ) )
439+
{
440+
referencePoint.setX( mCurrentLabelPos.labelRect.xMinimum() );
441+
referencePoint.setY( mCurrentLabelPos.labelRect.yMinimum() );
442+
}
443+
444+
double labelX = referencePoint.x();
445+
double labelY = referencePoint.y();
439446
double labelR = labelpos.rotation * 180 / M_PI;
440447

441448
// transform back to layer crs, if on-fly on
442449
if ( mRender->hasCrsTransformEnabled() )
443450
{
444-
QgsPoint transformedPoint = mRender->mapToLayerCoordinates( vlayer, labelpoint );
451+
QgsPoint transformedPoint = mRender->mapToLayerCoordinates( vlayer, referencePoint );
445452
labelX = transformedPoint.x();
446453
labelY = transformedPoint.y();
447454
}

‎src/app/qgsmaptoollabel.cpp

Lines changed: 71 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,14 @@ QFont QgsMapToolLabel::labelFontCurrentFeature()
230230
QMap< QgsPalLayerSettings::DataDefinedProperties, int >::const_iterator sizeIt = ddProperties.find( QgsPalLayerSettings::Size );
231231
if ( sizeIt != ddProperties.constEnd() )
232232
{
233-
font.setPointSizeF( attributes[*sizeIt].toDouble() );
233+
if ( layerSettings.fontSizeInMapUnits )
234+
{
235+
font.setPixelSize( layerSettings.sizeToPixel( attributes[*sizeIt].toDouble(), QgsRenderContext() ) );
236+
}
237+
else
238+
{
239+
font.setPointSizeF( attributes[*sizeIt].toDouble() );
240+
}
234241
}
235242

236243
//family
@@ -273,15 +280,15 @@ QFont QgsMapToolLabel::labelFontCurrentFeature()
273280
return font;
274281
}
275282

276-
bool QgsMapToolLabel::rotationPoint( QgsPoint& pos )
283+
bool QgsMapToolLabel::rotationPoint( QgsPoint& pos, bool ignoreUpsideDown )
277284
{
278285
QVector<QgsPoint> cornerPoints = mCurrentLabelPos.cornerPoints;
279286
if ( cornerPoints.size() < 4 )
280287
{
281288
return false;
282289
}
283290

284-
if ( mCurrentLabelPos.upsideDown )
291+
if ( mCurrentLabelPos.upsideDown && !ignoreUpsideDown )
285292
{
286293
pos = mCurrentLabelPos.cornerPoints.at( 2 );
287294
}
@@ -336,7 +343,7 @@ bool QgsMapToolLabel::rotationPoint( QgsPoint& pos )
336343
}
337344
else
338345
{
339-
double descentRatio = labelFontMetrics.descent() / labelFontMetrics.height();
346+
double descentRatio = 1 / labelFontMetrics.ascent() / labelFontMetrics.height();
340347
if ( valiString.compare( "Base", Qt::CaseInsensitive ) == 0 )
341348
{
342349
ydiff = labelSizeY * descentRatio;
@@ -351,7 +358,7 @@ bool QgsMapToolLabel::rotationPoint( QgsPoint& pos )
351358
double angle = mCurrentLabelPos.rotation;
352359
double xd = xdiff * cos( angle ) - ydiff * sin( angle );
353360
double yd = xdiff * sin( angle ) + ydiff * cos( angle );
354-
if ( mCurrentLabelPos.upsideDown )
361+
if ( mCurrentLabelPos.upsideDown && !ignoreUpsideDown )
355362
{
356363
pos.setX( pos.x() - xd );
357364
pos.setY( pos.y() - yd );
@@ -399,7 +406,65 @@ bool QgsMapToolLabel::dataDefinedPosition( QgsVectorLayer* vlayer, int featureId
399406
return true;
400407
}
401408

402-
bool QgsMapToolLabel:: diagramMoveable( const QgsMapLayer* ml, int& xCol, int& yCol ) const
409+
bool QgsMapToolLabel::layerIsRotatable( const QgsMapLayer* layer, int& rotationCol ) const
410+
{
411+
const QgsVectorLayer* vlayer = dynamic_cast<const QgsVectorLayer*>( layer );
412+
if ( !vlayer || !vlayer->isEditable() )
413+
{
414+
return false;
415+
}
416+
417+
QVariant rotation = layer->customProperty( "labeling/dataDefinedProperty14" );
418+
if ( !rotation.isValid() )
419+
{
420+
return false;
421+
}
422+
423+
bool rotationOk;
424+
rotationCol = rotation.toInt( &rotationOk );
425+
if ( !rotationOk )
426+
{
427+
return false;
428+
}
429+
return true;
430+
}
431+
432+
bool QgsMapToolLabel::dataDefinedRotation( QgsVectorLayer* vlayer, int featureId, double& rotation, bool& rotationSuccess )
433+
{
434+
rotationSuccess = false;
435+
if ( !vlayer )
436+
{
437+
return false;
438+
}
439+
440+
int rotationCol;
441+
if ( !layerIsRotatable( vlayer, rotationCol ) )
442+
{
443+
return false;
444+
}
445+
446+
QgsFeature f;
447+
if ( !vlayer->featureAtId( featureId, f, false, true ) )
448+
{
449+
return false;
450+
}
451+
452+
QgsAttributeMap attributes = f.attributeMap();
453+
454+
//test, if data defined x- and y- values are not null. Otherwise, the position is determined by PAL and the rotation cannot be fixed
455+
int xCol, yCol;
456+
double x, y;
457+
bool xSuccess, ySuccess;
458+
if ( !dataDefinedPosition( vlayer, featureId, x, xSuccess, y, ySuccess, xCol, yCol ) || !xSuccess || !ySuccess )
459+
{
460+
return false;
461+
}
462+
463+
rotation = attributes[rotationCol].toDouble( &rotationSuccess );
464+
return true;
465+
}
466+
467+
bool QgsMapToolLabel::diagramMoveable( const QgsMapLayer* ml, int& xCol, int& yCol ) const
403468
{
404469
const QgsVectorLayer* vlayer = dynamic_cast<const QgsVectorLayer*>( ml );
405470
if ( vlayer && vlayer->diagramRenderer() )

‎src/app/qgsmaptoollabel.h

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ class QgsMapToolLabel: public QgsMapTool
4646
@param yCol out: index of the attribute for data defined y coordinate
4747
@return true if layer fields set up and exist*/
4848
bool layerCanFreeze( const QgsMapLayer* ml, int& xCol, int& yCol ) const;
49+
/**Checks if labels in a layer can be rotated
50+
@param rotationCol out: attribute column for data defined label rotation*/
51+
bool layerIsRotatable( const QgsMapLayer* layer, int& rotationCol ) const;
4952

5053
protected:
5154
QgsRubberBand* mLabelRubberBand;
@@ -63,8 +66,9 @@ class QgsMapToolLabel: public QgsMapTool
6366
bool labelAtPosition( QMouseEvent* e, QgsLabelPosition& p );
6467

6568
/**Finds out rotation point of current label position
69+
@param ignoreUpsideDown treat label as right-side-up
6670
@return true in case of success*/
67-
bool rotationPoint( QgsPoint& pos );
71+
bool rotationPoint( QgsPoint& pos, bool ignoreUpsideDown = false );
6872

6973
/**Creates label / feature / fixpoint rubber bands for the current label position*/
7074
void createRubberBands();
@@ -90,7 +94,8 @@ class QgsMapToolLabel: public QgsMapTool
9094
QFont labelFontCurrentFeature();
9195

9296
/**Get data defined position of a feature
93-
@param layerId layer identification string
97+
@param vlayer vector layer
98+
@param featureId feature identification integer
9499
@param x out: data defined x-coordinate
95100
@param xSuccess out: false if attribute value is NULL
96101
@param y out: data defined y-coordinate
@@ -100,6 +105,15 @@ class QgsMapToolLabel: public QgsMapTool
100105
@return false if layer does not have data defined label position enabled*/
101106
bool dataDefinedPosition( QgsVectorLayer* vlayer, int featureId, double& x, bool& xSuccess, double& y, bool& ySuccess, int& xCol, int& yCol ) const;
102107

108+
/**Returns data defined rotation of a feature.
109+
@param vlayer vector layer
110+
@param featureId feature identification integer
111+
@param rotation out: rotation value
112+
@param rotationSuccess out: false if rotation value is NULL
113+
@return true if data defined rotation is enabled on the layer
114+
*/
115+
bool dataDefinedRotation( QgsVectorLayer* vlayer, int featureId, double& rotation, bool& rotationSuccess );
116+
103117
private:
104118
QgsPalLayerSettings mInvalidLabelSettings;
105119
};

‎src/app/qgsmaptoolmovelabel.cpp

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ void QgsMapToolMoveLabel::canvasPressEvent( QMouseEvent * e )
5050
{
5151
mStartPointMapCoords = toMapCoordinates( e->pos() );
5252
QgsPoint referencePoint;
53-
if ( !rotationPoint( referencePoint ) )
53+
if ( !rotationPoint( referencePoint, true ) )
5454
{
5555
referencePoint.setX( mCurrentLabelPos.labelRect.xMinimum() );
5656
referencePoint.setY( mCurrentLabelPos.labelRect.yMinimum() );
@@ -152,6 +152,26 @@ void QgsMapToolMoveLabel::canvasReleaseEvent( QMouseEvent * e )
152152
vlayer->beginEditCommand( tr( "Label moved" ) );
153153
vlayer->changeAttributeValue( mCurrentLabelPos.featureId, xCol, xPosNew, false );
154154
vlayer->changeAttributeValue( mCurrentLabelPos.featureId, yCol, yPosNew, false );
155+
156+
// set rotation to that of label, if data-defined and no rotation set yet
157+
// handle case of initially set rotation column fields of 0 instead of NULL
158+
// must come after setting x and y positions
159+
int rCol;
160+
if ( !mCurrentLabelPos.isDiagram && !mCurrentLabelPos.isFrozen
161+
&& layerIsRotatable( vlayer, rCol ) )
162+
{
163+
double labelRot = 0;
164+
double defRot;
165+
bool rSuccess;
166+
if ( dataDefinedRotation( vlayer, mCurrentLabelPos.featureId, defRot, rSuccess ) )
167+
{
168+
labelRot = mCurrentLabelPos.rotation * 180 / M_PI;
169+
if ( !rSuccess || ( rSuccess && defRot != labelRot ) )
170+
{
171+
vlayer->changeAttributeValue( mCurrentLabelPos.featureId, rCol, labelRot, false );
172+
}
173+
}
174+
}
155175
vlayer->endEditCommand();
156176

157177
mCanvas->refresh();

‎src/app/qgsmaptoolrotatelabel.cpp

Lines changed: 0 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -166,64 +166,6 @@ void QgsMapToolRotateLabel::canvasReleaseEvent( QMouseEvent *e )
166166
mCanvas->refresh();
167167
}
168168

169-
bool QgsMapToolRotateLabel::layerIsRotatable( const QgsMapLayer* layer, int& rotationCol ) const
170-
{
171-
const QgsVectorLayer* vlayer = dynamic_cast<const QgsVectorLayer*>( layer );
172-
if ( !vlayer || !vlayer->isEditable() )
173-
{
174-
return false;
175-
}
176-
177-
QVariant rotation = layer->customProperty( "labeling/dataDefinedProperty14" );
178-
if ( !rotation.isValid() )
179-
{
180-
return false;
181-
}
182-
183-
bool rotationOk;
184-
rotationCol = rotation.toInt( &rotationOk );
185-
if ( !rotationOk )
186-
{
187-
return false;
188-
}
189-
return true;
190-
}
191-
192-
bool QgsMapToolRotateLabel::dataDefinedRotation( QgsVectorLayer* vlayer, int featureId, double& rotation, bool& rotationSuccess )
193-
{
194-
rotationSuccess = false;
195-
if ( !vlayer )
196-
{
197-
return false;
198-
}
199-
200-
int rotationCol;
201-
if ( !layerIsRotatable( vlayer, rotationCol ) )
202-
{
203-
return false;
204-
}
205-
206-
QgsFeature f;
207-
if ( !vlayer->featureAtId( featureId, f, false, true ) )
208-
{
209-
return false;
210-
}
211-
212-
QgsAttributeMap attributes = f.attributeMap();
213-
214-
//test, if data defined x- and y- values are not null. Otherwise, the position is determined by PAL and the rotation cannot be fixed
215-
int xCol, yCol;
216-
double x, y;
217-
bool xSuccess, ySuccess;
218-
if ( !dataDefinedPosition( vlayer, featureId, x, xSuccess, y, ySuccess, xCol, yCol ) || !xSuccess || !ySuccess )
219-
{
220-
return false;
221-
}
222-
223-
rotation = attributes[rotationCol].toDouble( &rotationSuccess );
224-
return true;
225-
}
226-
227169
int QgsMapToolRotateLabel::roundTo15Degrees( double n )
228170
{
229171
int m = ( int )( n / 15.0 + 0.5 );

‎src/app/qgsmaptoolrotatelabel.h

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,7 @@ class QgsMapToolRotateLabel: public QgsMapToolLabel
3333
virtual void canvasMoveEvent( QMouseEvent * e );
3434
virtual void canvasReleaseEvent( QMouseEvent * e );
3535

36-
/**Checks if labels in a layer can be rotated
37-
@param rotationCol out: attribute column for data defined label rotation*/
38-
bool layerIsRotatable( const QgsMapLayer* layer, int& rotationCol ) const;
39-
4036
protected:
41-
/**Returns data defined rotation of a feature.
42-
@param rotation out: rotation value
43-
@param rotationSuccess out: false if rotation value is NULL
44-
@return true if data defined rotation is enabled on the layer
45-
*/
46-
bool dataDefinedRotation( QgsVectorLayer* vlayer, int featureId, double& rotation, bool& rotationSuccess );
4737

4838
static int roundTo15Degrees( double n );
4939
/**Converts azimuth value to counterclockwise 0 - 360*/

‎src/core/qgspallabeling.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,7 @@ void QgsPalLayerSettings::registerFeature( QgsVectorLayer* layer, QgsFeature& f
513513
if ( size.isValid() )
514514
{
515515
double sizeDouble = size.toDouble();
516-
if ( sizeDouble <= 0 )
516+
if ( sizeDouble <= 0 || sizeToPixel( sizeDouble, context ) < 1 )
517517
{
518518
return;
519519
}
@@ -859,8 +859,18 @@ int QgsPalLabeling::prepareLayer( QgsVectorLayer* layer, QSet<int>& attrIndices,
859859
// set whether adjacent lines should be merged
860860
l->setMergeConnectedLines( lyr.mergeLines );
861861

862-
lyr.textFont.setPixelSize( lyr.sizeToPixel( lyr.textFont.pointSizeF(), ctx ) );
862+
// fix for font size in map units causing font to show pointsize at small map scales
863+
int pixelFontSize = lyr.sizeToPixel( lyr.textFont.pointSizeF(), ctx );
863864

865+
if ( pixelFontSize < 1 )
866+
{
867+
lyr.textFont.setPixelSize( 1 );
868+
lyr.textFont.setPointSize( 1 );
869+
}
870+
else
871+
{
872+
lyr.textFont.setPixelSize( pixelFontSize );
873+
}
864874
//raster and vector scale factors
865875
lyr.vectorScaleFactor = ctx.scaleFactor();
866876
lyr.rasterCompressFactor = ctx.rasterScaleFactor();

‎src/ui/qgisapp.ui

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1720,7 +1720,7 @@
17201720
</property>
17211721
<property name="toolTip">
17221722
<string>Freeze or Thaw Labels
1723-
Shift thaws, Alt toggles, Ctl (Cmd) hides</string>
1723+
Shift thaws, Ctl (Cmd) toggles, Shift+Ctl (Cmd) hides</string>
17241724
</property>
17251725
</action>
17261726
<action name="mActionShowFrozenLabels">

0 commit comments

Comments
 (0)
Please sign in to comment.