Skip to content

Commit

Permalink
Unify label rotation with other rotation settings
Browse files Browse the repository at this point in the history
Label rotation is now specified in degrees clockwise, just like
symbol rotation, map rotation, etc.

Fix #4518
  • Loading branch information
nyalldawson committed May 30, 2017
1 parent d99d14b commit 21a4ac4
Show file tree
Hide file tree
Showing 14 changed files with 98 additions and 53 deletions.
1 change: 1 addition & 0 deletions doc/api_break.dox
Original file line number Diff line number Diff line change
Expand Up @@ -1732,6 +1732,7 @@ members were removed. Use the QgsProperty framework through dataDefinedPropertie
and setDataDefinedProperties() instead.
- readXml() and writeXml() now expect a reference to QgsReadWriteContext.
- fromLayer() has been reoved. Labeling is read/written in QgsAbstractVectorLayerLabeling and its subclasses.
- angleOffset is now in degrees clockwise. QGIS 2.x used degrees counterclockwise.


QgsPanelWidgetStack {#qgis_api_break_3_0_QgsPanelWidgetStack}
Expand Down
8 changes: 7 additions & 1 deletion python/core/qgspallabeling.sip
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ class QgsPalLayerSettings
Hali,
Vali,
Rotation,
LabelRotation,
RepeatDistance,
RepeatDistanceUnit,
Priority,
Expand Down Expand Up @@ -346,7 +347,12 @@ Offset type for layer (only applies in certain placement modes)
double yOffset; // offset from point in mm or map units
bool labelOffsetInMapUnits; //true if label offset is in map units (otherwise in mm)
QgsMapUnitScale labelOffsetMapUnitScale;
double angleOffset; // rotation applied to offset labels

double angleOffset;
%Docstring
Label rotation, in degrees clockwise
%End

bool preserveRotation; // preserve predefined rotation data during label pin/unpin operations

double maxCurvedCharAngleIn; // maximum angle between inside curved label characters (defaults to 20.0, range 20.0 to 60.0)
Expand Down
5 changes: 2 additions & 3 deletions python/core/qgstextrenderer.sip
Original file line number Diff line number Diff line change
Expand Up @@ -405,16 +405,15 @@ class QgsTextBackgroundSettings

double rotation() const;
%Docstring
Returns the rotation for the background shape.
Returns the rotation for the background shape, in degrees clockwise.
.. seealso:: rotationType()
.. seealso:: setRotation()
:rtype: float
%End

void setRotation( double rotation );
%Docstring
Sets the rotation for the background shape.
\param rotation angle in degrees to rotate
Sets the ``rotation`` for the background shape, in degrees clockwise.
.. seealso:: rotation()
.. seealso:: setRotationType()
%End
Expand Down
2 changes: 1 addition & 1 deletion src/app/dwg/qgsdwgimportdialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ void QgsDwgImportDialog::createGroup( QgsLayerTreeGroup *group, QString name, QS
" WHEN alignv=3 THEN 'Top'"
" END"
" END" ).arg( DRW::MTEXT ) ) );
pls.dataDefinedProperties().setProperty( QgsPalLayerSettings::Rotation, QgsProperty::fromExpression( QStringLiteral( "angle*180.0/pi()" ) ) );
pls.dataDefinedProperties().setProperty( QgsPalLayerSettings::LabelRotation, QgsProperty::fromExpression( QStringLiteral( "360-angle*180.0/pi()" ) ) );

pls.placement = QgsPalLayerSettings::OrderedPositionsAroundPoint;
l->setLabeling( new QgsVectorLayerSimpleLabeling( pls ) );
Expand Down
2 changes: 1 addition & 1 deletion src/app/qgslabelinggui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,7 @@ void QgsLabelingGui::populateDataDefinedButtons()
mCoordAlignmentHDDBtn->setUsageInfo( ddPlaceInfo );
registerDataDefinedButton( mCoordAlignmentVDDBtn, QgsPalLayerSettings::Vali );
mCoordAlignmentVDDBtn->setUsageInfo( ddPlaceInfo );
registerDataDefinedButton( mCoordRotationDDBtn, QgsPalLayerSettings::Rotation );
registerDataDefinedButton( mCoordRotationDDBtn, QgsPalLayerSettings::LabelRotation );
mCoordRotationDDBtn->setUsageInfo( ddPlaceInfo );

// rendering
Expand Down
7 changes: 4 additions & 3 deletions src/app/qgslabelpropertydialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ QgsLabelPropertyDialog::QgsLabelPropertyDialog( const QString &layerId, const QS
QDialog( parent, f ), mLabelFont( labelFont ), mCurLabelField( -1 )
{
setupUi( this );
mRotationSpinBox->setClearValue( 0 );
fillHaliComboBox();
fillValiComboBox();

Expand Down Expand Up @@ -314,7 +315,7 @@ void QgsLabelPropertyDialog::setDataDefinedValues( QgsVectorLayer *vlayer )
case QgsPalLayerSettings::Color:
mFontColorButton->setColor( QColor( result.toString() ) );
break;
case QgsPalLayerSettings::Rotation:
case QgsPalLayerSettings::LabelRotation:
{
double rot = result.toDouble( &ok );
if ( ok )
Expand Down Expand Up @@ -407,7 +408,7 @@ void QgsLabelPropertyDialog::enableDataDefinedWidgets( QgsVectorLayer *vlayer )
case QgsPalLayerSettings::Color:
mFontColorButton->setEnabled( true );
break;
case QgsPalLayerSettings::Rotation:
case QgsPalLayerSettings::LabelRotation:
mRotationSpinBox->setEnabled( true );
break;
//font related properties
Expand Down Expand Up @@ -618,7 +619,7 @@ void QgsLabelPropertyDialog::on_mRotationSpinBox_valueChanged( double d )
//null value so that size is reset to default
rotation.clear();
}
insertChangedValue( QgsPalLayerSettings::Rotation, rotation );
insertChangedValue( QgsPalLayerSettings::LabelRotation, rotation );
}

void QgsLabelPropertyDialog::on_mFontColorButton_colorChanged( const QColor &color )
Expand Down
2 changes: 1 addition & 1 deletion src/app/qgsmaptoollabel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,7 @@ bool QgsMapToolLabel::layerIsRotatable( QgsVectorLayer *vlayer, int &rotationCol

bool QgsMapToolLabel::labelIsRotatable( QgsVectorLayer *layer, const QgsPalLayerSettings &settings, int &rotationCol ) const
{
QString rColName = dataDefinedColumnName( QgsPalLayerSettings::Rotation, settings );
QString rColName = dataDefinedColumnName( QgsPalLayerSettings::LabelRotation, settings );
rotationCol = layer->fields().lookupField( rColName );
return rotationCol != -1;
}
Expand Down
48 changes: 40 additions & 8 deletions src/core/qgspallabeling.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,8 @@ void QgsPalLayerSettings::initPropertyDefinitions()
QgsPalLayerSettings::Vali, QgsPropertyDefinition( "Vali", QgsPropertyDefinition::DataTypeString, QObject::tr( "Vertical alignment" ), QObject::tr( "string " ) + QStringLiteral( "[<b>Bottom</b>|<b>Base</b>|<br>"
"<b>Half</b>|<b>Cap</b>|<b>Top</b>]" ) )
},
{ QgsPalLayerSettings::Rotation, QgsPropertyDefinition( "Rotation", QObject::tr( "Label rotation" ), QgsPropertyDefinition::Rotation ) },
{ QgsPalLayerSettings::Rotation, QgsPropertyDefinition( "Rotation", QObject::tr( "Label rotation (deprecated)" ), QgsPropertyDefinition::Rotation ) },
{ QgsPalLayerSettings::LabelRotation, QgsPropertyDefinition( "LabelRotation", QObject::tr( "Label rotation" ), QgsPropertyDefinition::Rotation ) },
{ QgsPalLayerSettings::ScaleVisibility, QgsPropertyDefinition( "ScaleVisibility", QObject::tr( "Scale based visibility" ), QgsPropertyDefinition::Boolean ) },
{ QgsPalLayerSettings::MinScale, QgsPropertyDefinition( "MinScale", QObject::tr( "Minimum scale (denominator)" ), QgsPropertyDefinition::Double ) },
{ QgsPalLayerSettings::MaxScale, QgsPropertyDefinition( "MaxScale", QObject::tr( "Maximum scale (denominator)" ), QgsPropertyDefinition::Double ) },
Expand Down Expand Up @@ -598,7 +599,18 @@ void QgsPalLayerSettings::readFromLayerCustomProperties( QgsVectorLayer *layer )
{
labelOffsetMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( layer->customProperty( QStringLiteral( "labeling/labelOffsetMapUnitScale" ) ).toString() );
}
angleOffset = layer->customProperty( QStringLiteral( "labeling/angleOffset" ), QVariant( 0.0 ) ).toDouble();

QVariant tempAngle = layer->customProperty( QStringLiteral( "labeling/angleOffset" ), QVariant() );
if ( tempAngle.isValid() )
{
double oldAngle = layer->customProperty( QStringLiteral( "labeling/angleOffset" ), QVariant( 0.0 ) ).toDouble();
angleOffset = fmod( 360 - oldAngle, 360.0 );
}
else
{
angleOffset = layer->customProperty( QStringLiteral( "labeling/rotationAngle" ), QVariant( 0.0 ) ).toDouble();
}

preserveRotation = layer->customProperty( QStringLiteral( "labeling/preserveRotation" ), QVariant( true ) ).toBool();
maxCurvedCharAngleIn = layer->customProperty( QStringLiteral( "labeling/maxCurvedCharAngleIn" ), QVariant( 25.0 ) ).toDouble();
maxCurvedCharAngleOut = layer->customProperty( QStringLiteral( "labeling/maxCurvedCharAngleOut" ), QVariant( -25.0 ) ).toDouble();
Expand Down Expand Up @@ -691,6 +703,11 @@ void QgsPalLayerSettings::readFromLayerCustomProperties( QgsVectorLayer *layer )
mDataDefinedProperties.setProperty( ShadowOpacity, QgsProperty::fromExpression( QStringLiteral( "100 - (%1)" ).arg( mDataDefinedProperties.property( ShadowTransparency ).asExpression() ) ) );
mDataDefinedProperties.setProperty( ShadowTransparency, QgsProperty() );
}
if ( mDataDefinedProperties.isActive( Rotation ) )
{
mDataDefinedProperties.setProperty( LabelRotation, QgsProperty::fromExpression( QStringLiteral( "360 - (%1)" ).arg( mDataDefinedProperties.property( Rotation ).asExpression() ) ) );
mDataDefinedProperties.setProperty( Rotation, QgsProperty() );
}
}

void QgsPalLayerSettings::readXml( QDomElement &elem, const QgsReadWriteContext &context )
Expand Down Expand Up @@ -755,7 +772,17 @@ void QgsPalLayerSettings::readXml( QDomElement &elem, const QgsReadWriteContext
{
labelOffsetMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( placementElem.attribute( QStringLiteral( "labelOffsetMapUnitScale" ) ) );
}
angleOffset = placementElem.attribute( QStringLiteral( "angleOffset" ), QStringLiteral( "0" ) ).toDouble();

if ( placementElem.hasAttribute( QStringLiteral( "angleOffset" ) ) )
{
double oldAngle = placementElem.attribute( QStringLiteral( "angleOffset" ), QStringLiteral( "0" ) ).toDouble();
angleOffset = fmod( 360 - oldAngle, 360.0 );
}
else
{
angleOffset = placementElem.attribute( QStringLiteral( "rotationAngle" ), QStringLiteral( "0" ) ).toDouble();
}

preserveRotation = placementElem.attribute( QStringLiteral( "preserveRotation" ), QStringLiteral( "1" ) ).toInt();
maxCurvedCharAngleIn = placementElem.attribute( QStringLiteral( "maxCurvedCharAngleIn" ), QStringLiteral( "25" ) ).toDouble();
maxCurvedCharAngleOut = placementElem.attribute( QStringLiteral( "maxCurvedCharAngleOut" ), QStringLiteral( "-25" ) ).toDouble();
Expand Down Expand Up @@ -831,6 +858,11 @@ void QgsPalLayerSettings::readXml( QDomElement &elem, const QgsReadWriteContext
mDataDefinedProperties.setProperty( ShadowOpacity, QgsProperty::fromExpression( QStringLiteral( "100 - (%1)" ).arg( mDataDefinedProperties.property( ShadowTransparency ).asExpression() ) ) );
mDataDefinedProperties.setProperty( ShadowTransparency, QgsProperty() );
}
if ( mDataDefinedProperties.isActive( Rotation ) )
{
mDataDefinedProperties.setProperty( LabelRotation, QgsProperty::fromExpression( QStringLiteral( "360 - (%1)" ).arg( mDataDefinedProperties.property( Rotation ).asExpression() ) ) );
mDataDefinedProperties.setProperty( Rotation, QgsProperty() );
}
}


Expand Down Expand Up @@ -878,7 +910,7 @@ QDomElement QgsPalLayerSettings::writeXml( QDomDocument &doc, const QgsReadWrite
placementElem.setAttribute( QStringLiteral( "yOffset" ), yOffset );
placementElem.setAttribute( QStringLiteral( "labelOffsetInMapUnits" ), labelOffsetInMapUnits );
placementElem.setAttribute( QStringLiteral( "labelOffsetMapUnitScale" ), QgsSymbolLayerUtils::encodeMapUnitScale( labelOffsetMapUnitScale ) );
placementElem.setAttribute( QStringLiteral( "angleOffset" ), angleOffset );
placementElem.setAttribute( QStringLiteral( "rotationAngle" ), angleOffset );
placementElem.setAttribute( QStringLiteral( "preserveRotation" ), preserveRotation );
placementElem.setAttribute( QStringLiteral( "maxCurvedCharAngleIn" ), maxCurvedCharAngleIn );
placementElem.setAttribute( QStringLiteral( "maxCurvedCharAngleOut" ), maxCurvedCharAngleOut );
Expand Down Expand Up @@ -1576,13 +1608,13 @@ void QgsPalLayerSettings::registerFeature( QgsFeature &f, QgsRenderContext &cont
if ( placement == QgsPalLayerSettings::OverPoint && !qgsDoubleNear( angleOffset, 0.0 ) )
{
layerDefinedRotation = true;
angle = angleOffset * M_PI / 180; // convert to radians
angle = ( 360 - angleOffset ) * M_PI / 180; // convert to radians counterclockwise
}

const QgsMapToPixel &m2p = context.mapToPixel();
//data defined rotation?
context.expressionContext().setOriginalValueVariable( angleOffset );
exprVal = mDataDefinedProperties.value( QgsPalLayerSettings::Rotation, context.expressionContext() );
exprVal = mDataDefinedProperties.value( QgsPalLayerSettings::LabelRotation, context.expressionContext() );
if ( exprVal.isValid() )
{
bool ok;
Expand All @@ -1593,8 +1625,8 @@ void QgsPalLayerSettings::registerFeature( QgsFeature &f, QgsRenderContext &cont
dataDefinedRotation = true;
// TODO: add setting to disable having data defined rotation follow
// map rotation ?
rotD -= m2p.mapRotation();
angle = rotD * M_PI / 180.0;
rotD += m2p.mapRotation();
angle = ( 360 - rotD ) * M_PI / 180.0;
}
}

Expand Down
8 changes: 6 additions & 2 deletions src/core/qgspallabeling.h
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,8 @@ class CORE_EXPORT QgsPalLayerSettings
PositionY = 10, //!< Y-coordinate data defined label position
Hali = 11, //!< Horizontal alignment for data defined label position (Left, Center, Right)
Vali = 12, //!< Vertical alignment for data defined label position (Bottom, Base, Half, Cap, Top)
Rotation = 14, //!< Label rotation
Rotation = 14, //!< Label rotation (deprecated, for old project compatibility only)
LabelRotation = 96, //!< Label rotation (deprecated, for old project compatibility only)
RepeatDistance = 84,
RepeatDistanceUnit = 86,
Priority = 87,
Expand Down Expand Up @@ -463,7 +464,10 @@ class CORE_EXPORT QgsPalLayerSettings
double yOffset; // offset from point in mm or map units
bool labelOffsetInMapUnits; //true if label offset is in map units (otherwise in mm)
QgsMapUnitScale labelOffsetMapUnitScale;
double angleOffset; // rotation applied to offset labels

//! Label rotation, in degrees clockwise
double angleOffset;

bool preserveRotation; // preserve predefined rotation data during label pin/unpin operations

double maxCurvedCharAngleIn; // maximum angle between inside curved label characters (defaults to 20.0, range 20.0 to 60.0)
Expand Down
7 changes: 4 additions & 3 deletions src/core/qgstextrenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -369,14 +369,15 @@ class CORE_EXPORT QgsTextBackgroundSettings
*/
void setRotationType( RotationType type );

/** Returns the rotation for the background shape.
/**
* Returns the rotation for the background shape, in degrees clockwise.
* \see rotationType()
* \see setRotation()
*/
double rotation() const;

/** Sets the rotation for the background shape.
* \param rotation angle in degrees to rotate
/**
* Sets the \a rotation for the background shape, in degrees clockwise.
* \see rotation()
* \see setRotationType()
*/
Expand Down
2 changes: 1 addition & 1 deletion src/core/qgsvectorlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3768,7 +3768,7 @@ void QgsVectorLayer::readSldLabeling( const QDomNode &node )
double rotation = rotationElem.text().toDouble( &ok );
if ( ok )
{
settings.angleOffset = rotation;
settings.angleOffset = 360 - rotation;
}
}
}
Expand Down
4 changes: 0 additions & 4 deletions src/gui/qgstextformatwidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -214,9 +214,6 @@ void QgsTextFormatWidget::initWidget()
mPlacePolygonBtnGrp->setExclusive( true );
connect( mPlacePolygonBtnGrp, static_cast<void ( QButtonGroup::* )( int )>( &QButtonGroup::buttonClicked ), this, &QgsTextFormatWidget::updatePlacementWidgets );

// TODO: is this necessary? maybe just use the data defined-only rotation?
mPointAngleDDBtn->setVisible( false );

// Global settings group for groupboxes' saved/restored collapsed state
// maintains state across different dialogs
Q_FOREACH ( QgsCollapsibleGroupBox *grpbox, findChildren<QgsCollapsibleGroupBox *>() )
Expand Down Expand Up @@ -359,7 +356,6 @@ void QgsTextFormatWidget::initWidget()
<< mObstacleTypeComboBox
<< mOffsetTypeComboBox
<< mPalShowAllLabelsForLayerChkBx
<< mPointAngleDDBtn
<< mPointAngleSpinBox
<< mPointOffsetDDBtn
<< mPointOffsetUnitsDDBtn
Expand Down
38 changes: 22 additions & 16 deletions src/ui/qgslabelpropertydialogbase.ui
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>431</width>
<height>622</height>
<y>-391</y>
<width>417</width>
<height>689</height>
</rect>
</property>
<layout class="QVBoxLayout" name="mLabelPropertiesLayout">
Expand Down Expand Up @@ -576,11 +576,17 @@
</item>
<item row="5" column="1">
<widget class="QgsDoubleSpinBox" name="mRotationSpinBox">
<property name="wrapping">
<bool>true</bool>
</property>
<property name="specialValueText">
<string>Default</string>
</property>
<property name="suffix">
<string>˚</string>
</property>
<property name="minimum">
<double>-1.000000000000000</double>
<double>-360.000000000000000</double>
</property>
<property name="maximum">
<double>360.000000000000000</double>
Expand Down Expand Up @@ -623,24 +629,12 @@
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QgsScrollArea</class>
<extends>QScrollArea</extends>
<header>qgsscrollarea.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>QgsColorButton</class>
<extends>QToolButton</extends>
<header>qgscolorbutton.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>QgsCollapsibleGroupBox</class>
<extends>QGroupBox</extends>
<header>qgscollapsiblegroupbox.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>QgsDoubleSpinBox</class>
<extends>QDoubleSpinBox</extends>
Expand All @@ -651,6 +645,18 @@
<extends>QSpinBox</extends>
<header>qgsspinbox.h</header>
</customwidget>
<customwidget>
<class>QgsCollapsibleGroupBox</class>
<extends>QGroupBox</extends>
<header>qgscollapsiblegroupbox.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>QgsScrollArea</class>
<extends>QScrollArea</extends>
<header>qgsscrollarea.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>mLabelTextLineEdit</tabstop>
Expand Down
Loading

0 comments on commit 21a4ac4

Please sign in to comment.