Curved offset first attempt

This commit is contained in:
Alessandro Pasotti 2022-03-10 16:25:27 +01:00 committed by Nyall Dawson
parent 28bb05b0d5
commit 66322f4c7f
9 changed files with 441 additions and 193 deletions

View File

@ -219,6 +219,7 @@ Contains settings for how a map layer will be labeled.
PositionX, PositionX,
PositionY, PositionY,
PositionPoint, PositionPoint,
CurvedOffset,
Hali, Hali,
Vali, Vali,
Rotation, Rotation,

View File

@ -53,6 +53,7 @@ QgsMapToolLabel::~QgsMapToolLabel()
delete mCalloutOtherPointsRubberBand; delete mCalloutOtherPointsRubberBand;
delete mFeatureRubberBand; delete mFeatureRubberBand;
delete mFixPointRubberBand; delete mFixPointRubberBand;
delete mOffsetFromLineStartRubberBand;
} }
void QgsMapToolLabel::deactivate() void QgsMapToolLabel::deactivate()
@ -216,6 +217,7 @@ void QgsMapToolLabel::createRubberBands()
{ {
delete mLabelRubberBand; delete mLabelRubberBand;
delete mFeatureRubberBand; delete mFeatureRubberBand;
delete mOffsetFromLineStartRubberBand;
//label rubber band //label rubber band
mLabelRubberBand = new QgsRubberBand( mCanvas, QgsWkbTypes::LineGeometry ); mLabelRubberBand = new QgsRubberBand( mCanvas, QgsWkbTypes::LineGeometry );
@ -238,6 +240,12 @@ void QgsMapToolLabel::createRubberBands()
QgsGeometry geom = f.geometry(); QgsGeometry geom = f.geometry();
if ( !geom.isNull() ) if ( !geom.isNull() )
{ {
const int r = QgsSettingsRegistryCore::settingsDigitizingLineColorRed.value();
const int g = QgsSettingsRegistryCore::settingsDigitizingLineColorGreen.value();
const int b = QgsSettingsRegistryCore::settingsDigitizingLineColorBlue.value();
const int a = QgsSettingsRegistryCore::settingsDigitizingLineColorAlpha.value();
if ( geom.type() == QgsWkbTypes::PolygonGeometry ) if ( geom.type() == QgsWkbTypes::PolygonGeometry )
{ {
// for polygons, we don't want to fill the whole polygon itself with the rubber band // for polygons, we don't want to fill the whole polygon itself with the rubber band
@ -246,10 +254,13 @@ void QgsMapToolLabel::createRubberBands()
// instead, just use the boundary of the polygon for the rubber band // instead, just use the boundary of the polygon for the rubber band
geom = QgsGeometry( geom.constGet()->boundary() ); geom = QgsGeometry( geom.constGet()->boundary() );
} }
int r = QgsSettingsRegistryCore::settingsDigitizingLineColorRed.value(); else if ( geom.type() == QgsWkbTypes::LineGeometry )
int g = QgsSettingsRegistryCore::settingsDigitizingLineColorGreen.value(); {
int b = QgsSettingsRegistryCore::settingsDigitizingLineColorBlue.value(); mOffsetFromLineStartRubberBand = new QgsRubberBand( mCanvas, QgsWkbTypes::PointGeometry );
int a = QgsSettingsRegistryCore::settingsDigitizingLineColorAlpha.value(); mOffsetFromLineStartRubberBand->setColor( QColor( r, g, b, a ) );
mOffsetFromLineStartRubberBand->hide();
}
mFeatureRubberBand = new QgsRubberBand( mCanvas, geom.type() ); mFeatureRubberBand = new QgsRubberBand( mCanvas, geom.type() );
mFeatureRubberBand->setColor( QColor( r, g, b, a ) ); mFeatureRubberBand->setColor( QColor( r, g, b, a ) );
mFeatureRubberBand->setToGeometry( geom, vlayer ); mFeatureRubberBand->setToGeometry( geom, vlayer );
@ -284,6 +295,8 @@ void QgsMapToolLabel::deleteRubberBands()
mFeatureRubberBand = nullptr; mFeatureRubberBand = nullptr;
delete mFixPointRubberBand; delete mFixPointRubberBand;
mFixPointRubberBand = nullptr; mFixPointRubberBand = nullptr;
delete mOffsetFromLineStartRubberBand;
mOffsetFromLineStartRubberBand = nullptr;
cadDockWidget()->clear(); cadDockWidget()->clear();
cadDockWidget()->clearPoints(); cadDockWidget()->clearPoints();
} }
@ -845,6 +858,39 @@ bool QgsMapToolLabel::currentLabelDataDefinedPosition( double &x, bool &xSuccess
return true; return true;
} }
bool QgsMapToolLabel::currentLabelDataDefinedCurvedOffset( double &offset, bool &offsetSuccess, int &curvedOffsetCol ) const
{
offsetSuccess = false;
QgsVectorLayer *vlayer = mCurrentLabel.layer;
QgsFeatureId featureId = mCurrentLabel.pos.featureId;
if ( ! vlayer )
{
return false;
}
if ( !labelOffsettable( vlayer, mCurrentLabel.settings, curvedOffsetCol ) )
{
return false;
}
QgsFeature f;
if ( !vlayer->getFeatures( QgsFeatureRequest().setFilterFid( featureId ).setFlags( QgsFeatureRequest::NoGeometry ) ).nextFeature( f ) )
{
return false;
}
if ( mCurrentLabel.settings.dataDefinedProperties().isActive( QgsPalLayerSettings::CurvedOffset ) )
{
QgsAttributes attributes = f.attributes();
if ( !attributes.at( curvedOffsetCol ).isNull() )
offset = attributes.at( curvedOffsetCol ).toDouble( &offsetSuccess );
}
return true;
}
QgsMapToolLabel::PropertyStatus QgsMapToolLabel::labelRotatableStatus( QgsVectorLayer *layer, const QgsPalLayerSettings &settings, int &rotationCol ) const QgsMapToolLabel::PropertyStatus QgsMapToolLabel::labelRotatableStatus( QgsVectorLayer *layer, const QgsPalLayerSettings &settings, int &rotationCol ) const
{ {
PropertyStatus status = PropertyStatus::DoesNotExist; PropertyStatus status = PropertyStatus::DoesNotExist;
@ -921,6 +967,30 @@ bool QgsMapToolLabel::changeCurrentLabelDataDefinedPosition( const QVariant &x,
return true; return true;
} }
bool QgsMapToolLabel::changeCurrentLabelDataDefinedCurvedOffset( const QVariant &offset )
{
if ( mCurrentLabel.settings.dataDefinedProperties().isActive( QgsPalLayerSettings::CurvedOffset ) )
{
PropertyStatus status = PropertyStatus::DoesNotExist;
const QString curvedOffsetColName = dataDefinedColumnName( QgsPalLayerSettings::CurvedOffset, mCurrentLabel.settings, mCurrentLabel.layer, status );
const int curvedOffsetCol = mCurrentLabel.layer->fields().lookupField( curvedOffsetColName );
if ( !mCurrentLabel.layer->changeAttributeValue( mCurrentLabel.pos.featureId, curvedOffsetCol, offset ) )
return false;
}
else
{
PropertyStatus status = PropertyStatus::DoesNotExist;
const QString curvedOffsetColName = dataDefinedColumnName( QgsPalLayerSettings::PositionX, mCurrentLabel.settings, mCurrentLabel.layer, status );
const int curvedOffsetCol = mCurrentLabel.layer->fields().lookupField( curvedOffsetColName );
if ( !mCurrentLabel.layer->changeAttributeValue( mCurrentLabel.pos.featureId, curvedOffsetCol, offset ) )
return false;
}
return true;
}
bool QgsMapToolLabel::dataDefinedShowHide( QgsVectorLayer *vlayer, QgsFeatureId featureId, int &show, bool &showSuccess, int &showCol ) const bool QgsMapToolLabel::dataDefinedShowHide( QgsVectorLayer *vlayer, QgsFeatureId featureId, int &show, bool &showSuccess, int &showCol ) const
{ {
showSuccess = false; showSuccess = false;
@ -1017,7 +1087,7 @@ bool QgsMapToolLabel::isPinned()
double x, y; double x, y;
bool xSuccess, ySuccess; bool xSuccess, ySuccess;
if ( currentLabelDataDefinedPosition( x, xSuccess, y, ySuccess, xCol, yCol, pointCol ) && xSuccess && ySuccess ) if ( currentLabelDataDefinedPosition( x, xSuccess, y, ySuccess, xCol, yCol, pointCol ) )
rc = true; rc = true;
} }
@ -1054,6 +1124,20 @@ bool QgsMapToolLabel::labelMoveable( QgsVectorLayer *vlayer, const QgsPalLayerSe
return false; return false;
} }
bool QgsMapToolLabel::labelOffsettable( QgsVectorLayer *vlayer, const QgsPalLayerSettings &settings, int &curvedOffsetCol ) const
{
curvedOffsetCol = -1;
if ( settings.dataDefinedProperties().isActive( QgsPalLayerSettings::CurvedOffset ) )
{
PropertyStatus status = PropertyStatus::DoesNotExist;
QString pointColName = dataDefinedColumnName( QgsPalLayerSettings::CurvedOffset, settings, vlayer, status );
curvedOffsetCol = vlayer->fields().lookupField( pointColName );
if ( curvedOffsetCol >= 0 )
return true;
}
return false;
}
bool QgsMapToolLabel::diagramCanShowHide( QgsVectorLayer *vlayer, int &showCol ) const bool QgsMapToolLabel::diagramCanShowHide( QgsVectorLayer *vlayer, int &showCol ) const
{ {
showCol = -1; showCol = -1;

View File

@ -86,6 +86,7 @@ class APP_EXPORT QgsMapToolLabel: public QgsMapToolAdvancedDigitizing
QgsRubberBand *mFeatureRubberBand = nullptr; QgsRubberBand *mFeatureRubberBand = nullptr;
//! Shows label fixpoint (left/bottom by default) //! Shows label fixpoint (left/bottom by default)
QgsRubberBand *mFixPointRubberBand = nullptr; QgsRubberBand *mFixPointRubberBand = nullptr;
QgsRubberBand *mOffsetFromLineStartRubberBand = nullptr;
struct APP_EXPORT LabelDetails struct APP_EXPORT LabelDetails
{ {
@ -201,6 +202,16 @@ class APP_EXPORT QgsMapToolLabel: public QgsMapToolAdvancedDigitizing
*/ */
bool currentLabelDataDefinedPosition( double &x, bool &xSuccess, double &y, bool &ySuccess, int &xCol, int &yCol, int &pointCol ) const; bool currentLabelDataDefinedPosition( double &x, bool &xSuccess, double &y, bool &ySuccess, int &xCol, int &yCol, int &pointCol ) const;
/**
* Gets data defined curved offset of current label
* \param offset out: data defined curved offset
* \param offsetSuccess out: FALSE if attribute value is NULL
* \param curvedOffsetCol out: index of the curved offset column
* \returns FALSE if layer does not have data defined label curved offset enabled
* \since QGIS 3.26
*/
bool currentLabelDataDefinedCurvedOffset( double &offset, bool &offsetSuccess, int &curvedOffsetCol ) const;
/** /**
* Returns data defined rotation of current label * Returns data defined rotation of current label
* \param rotation out: rotation value * \param rotation out: rotation value
@ -220,6 +231,14 @@ class APP_EXPORT QgsMapToolLabel: public QgsMapToolAdvancedDigitizing
*/ */
bool changeCurrentLabelDataDefinedPosition( const QVariant &x, const QVariant &y ); bool changeCurrentLabelDataDefinedPosition( const QVariant &x, const QVariant &y );
/**
* Change the data defined curve offset current label
* \param curvedOffsetCol out: index of the curved offset
* \param x data defined offset
* \returns TRUE if data defined curved offset could be changed
*/
bool changeCurrentLabelDataDefinedCurvedOffset( const QVariant &offset );
/** /**
* Returns data defined show/hide of a feature. * Returns data defined show/hide of a feature.
* \param vlayer vector layer * \param vlayer vector layer
@ -239,6 +258,7 @@ class APP_EXPORT QgsMapToolLabel: public QgsMapToolAdvancedDigitizing
bool isPinned(); bool isPinned();
bool labelMoveable( QgsVectorLayer *vlayer, const QgsPalLayerSettings &settings, int &xCol, int &yCol, int &pointCol ) const; bool labelMoveable( QgsVectorLayer *vlayer, const QgsPalLayerSettings &settings, int &xCol, int &yCol, int &pointCol ) const;
bool labelOffsettable( QgsVectorLayer *vlayer, const QgsPalLayerSettings &settings, int &curvedOffsetCol ) const;
bool createAuxiliaryFields( QgsPalIndexes &palIndexes ); bool createAuxiliaryFields( QgsPalIndexes &palIndexes );
bool createAuxiliaryFields( LabelDetails &details, QgsPalIndexes &palIndexes ) const; bool createAuxiliaryFields( LabelDetails &details, QgsPalIndexes &palIndexes ) const;

View File

@ -34,6 +34,7 @@ QgsMapToolMoveLabel::QgsMapToolMoveLabel( QgsMapCanvas *canvas, QgsAdvancedDigit
mPalProperties << QgsPalLayerSettings::PositionX; mPalProperties << QgsPalLayerSettings::PositionX;
mPalProperties << QgsPalLayerSettings::PositionY; mPalProperties << QgsPalLayerSettings::PositionY;
mPalProperties << QgsPalLayerSettings::CurvedOffset;
mDiagramProperties << QgsDiagramLayerSettings::PositionX; mDiagramProperties << QgsDiagramLayerSettings::PositionX;
mDiagramProperties << QgsDiagramLayerSettings::PositionY; mDiagramProperties << QgsDiagramLayerSettings::PositionY;
@ -58,9 +59,41 @@ void QgsMapToolMoveLabel::deleteRubberBands()
void QgsMapToolMoveLabel::cadCanvasMoveEvent( QgsMapMouseEvent *e ) void QgsMapToolMoveLabel::cadCanvasMoveEvent( QgsMapMouseEvent *e )
{ {
if ( mLabelRubberBand ) if ( mLabelRubberBand )
{ {
const QgsPointXY pointMapCoords = e->mapPoint(); const QgsPointXY pointMapCoords = e->mapPoint();
bool isCurved { mCurrentLabel.settings.placement == QgsPalLayerSettings::Placement::Curved };
if ( isCurved )
{
// Determine the closest point on the feature
const QgsFeatureId featureId = mCurrentLabel.pos.featureId;
if ( mCurrentLabel.layer )
{
const QgsFeature feature { mCurrentLabel.layer->getFeature( featureId ) };
const QgsGeometry pointMapGeometry { QgsGeometry::fromPointXY( pointMapCoords ) };
if ( feature.geometry().distance( pointMapGeometry ) / mCanvas->mapUnitsPerPixel() > 100.0 )
{
mCurrentLabel.settings.placement = QgsPalLayerSettings::Placement::Horizontal;
isCurved = false;
mOffsetFromLineStartRubberBand->hide();
}
else
{
mOffsetFromLineStartRubberBand->setToGeometry( feature.geometry().nearestPoint( pointMapGeometry ) );
mOffsetFromLineStartRubberBand->show();
}
}
}
if ( isCurved )
{
mLabelRubberBand->hide();
mFixPointRubberBand->hide();
}
else
{
const double offsetX = pointMapCoords.x() - mStartPointMapCoords.x(); const double offsetX = pointMapCoords.x() - mStartPointMapCoords.x();
const double offsetY = pointMapCoords.y() - mStartPointMapCoords.y(); const double offsetY = pointMapCoords.y() - mStartPointMapCoords.y();
mLabelRubberBand->setTranslationOffset( offsetX, offsetY ); mLabelRubberBand->setTranslationOffset( offsetX, offsetY );
@ -69,6 +102,9 @@ void QgsMapToolMoveLabel::cadCanvasMoveEvent( QgsMapMouseEvent *e )
mFixPointRubberBand->setTranslationOffset( offsetX, offsetY ); mFixPointRubberBand->setTranslationOffset( offsetX, offsetY );
mFixPointRubberBand->updatePosition(); mFixPointRubberBand->updatePosition();
mFixPointRubberBand->update(); mFixPointRubberBand->update();
mLabelRubberBand->show();
mFixPointRubberBand->show();
}
} }
else if ( mCalloutMoveRubberBand ) else if ( mCalloutMoveRubberBand )
{ {
@ -92,7 +128,7 @@ void QgsMapToolMoveLabel::cadCanvasMoveEvent( QgsMapMouseEvent *e )
void QgsMapToolMoveLabel::cadCanvasPressEvent( QgsMapMouseEvent *e ) void QgsMapToolMoveLabel::cadCanvasPressEvent( QgsMapMouseEvent *e )
{ {
if ( !mLabelRubberBand && !mCalloutMoveRubberBand ) if ( !mLabelRubberBand && !mCalloutMoveRubberBand && !mOffsetFromLineStartRubberBand )
{ {
if ( e->button() != Qt::LeftButton ) if ( e->button() != Qt::LeftButton )
return; return;
@ -182,9 +218,30 @@ void QgsMapToolMoveLabel::cadCanvasPressEvent( QgsMapMouseEvent *e )
return; return;
} }
int xCol = -1, yCol = -1, pointCol = -1; int xCol = -1, yCol = -1, pointCol = -1, curvedOffsetCol = -1;
if ( !mCurrentLabel.pos.isDiagram && !labelMoveable( vlayer, mCurrentLabel.settings, xCol, yCol, pointCol ) ) const bool isCurved { mCurrentLabel.settings.placement == QgsPalLayerSettings::Placement::Curved };
if ( isCurved && !mCurrentLabel.pos.isDiagram && !labelOffsettable( vlayer, mCurrentLabel.settings, pointCol ) )
{
QgsPalIndexes indexes;
if ( createAuxiliaryFields( indexes ) )
return;
if ( !labelOffsettable( vlayer, mCurrentLabel.settings, pointCol ) )
{
PropertyStatus status = PropertyStatus::DoesNotExist;
QString offsetColName = dataDefinedColumnName( QgsPalLayerSettings::CurvedOffset, mCurrentLabel.settings, vlayer, status );
if ( pointCol < 0 )
QgisApp::instance()->messageBar()->pushWarning( tr( "Move Label" ), tr( "The label offset column “%1” does not exist in the layer" ).arg( offsetColName ) );
return;
}
curvedOffsetCol = indexes[ QgsPalLayerSettings::CurvedOffset ];
}
else if ( !mCurrentLabel.pos.isDiagram && !labelMoveable( vlayer, mCurrentLabel.settings, xCol, yCol, pointCol ) )
{ {
if ( mCurrentLabel.settings.dataDefinedProperties().isActive( QgsPalLayerSettings::PositionPoint ) ) if ( mCurrentLabel.settings.dataDefinedProperties().isActive( QgsPalLayerSettings::PositionPoint ) )
{ {
@ -228,10 +285,11 @@ void QgsMapToolMoveLabel::cadCanvasPressEvent( QgsMapMouseEvent *e )
yCol = indexes[ QgsDiagramLayerSettings::PositionY ]; yCol = indexes[ QgsDiagramLayerSettings::PositionY ];
} }
if ( xCol >= 0 && yCol >= 0 ) if ( ( isCurved && curvedOffsetCol >= 0 ) || ( xCol >= 0 && yCol >= 0 ) )
{ {
const bool usesAuxFields = vlayer->fields().fieldOrigin( xCol ) == QgsFields::OriginJoin const bool usesAuxFields =
&& vlayer->fields().fieldOrigin( yCol ) == QgsFields::OriginJoin; ( isCurved && curvedOffsetCol >= 0 && vlayer->fields().fieldOrigin( curvedOffsetCol ) == QgsFields::OriginJoin ) ||
( vlayer->fields().fieldOrigin( xCol ) == QgsFields::OriginJoin && vlayer->fields().fieldOrigin( yCol ) == QgsFields::OriginJoin );
if ( !usesAuxFields && !vlayer->isEditable() ) if ( !usesAuxFields && !vlayer->isEditable() )
{ {
if ( vlayer->startEditing() ) if ( vlayer->startEditing() )
@ -258,7 +316,7 @@ void QgsMapToolMoveLabel::cadCanvasPressEvent( QgsMapMouseEvent *e )
createRubberBands(); createRubberBands();
} }
} }
else else // Second click
{ {
switch ( e->button() ) switch ( e->button() )
{ {
@ -295,12 +353,21 @@ void QgsMapToolMoveLabel::cadCanvasPressEvent( QgsMapMouseEvent *e )
int xCol = -1; int xCol = -1;
int yCol = -1; int yCol = -1;
int pointCol = -1; int pointCol = -1;
int curvedOffsetCol = -1;
double xPosOrig = 0; double xPosOrig = 0;
double yPosOrig = 0; double yPosOrig = 0;
double curvedOffsetOrig = 0;
bool xSuccess = false; bool xSuccess = false;
bool ySuccess = false; bool ySuccess = false;
bool curvedOffsetSuccess = false;
if ( !isCalloutMove && !currentLabelDataDefinedPosition( xPosOrig, xSuccess, yPosOrig, ySuccess, xCol, yCol, pointCol ) ) const bool isCurved { mCurrentLabel.settings.placement == QgsPalLayerSettings::Placement::Curved };
if ( !isCalloutMove && isCurved && !currentLabelDataDefinedCurvedOffset( curvedOffsetOrig, curvedOffsetSuccess, curvedOffsetCol ) )
{
return;
}
else if ( !isCalloutMove && !currentLabelDataDefinedPosition( xPosOrig, xSuccess, yPosOrig, ySuccess, xCol, yCol, pointCol ) )
{ {
return; return;
} }
@ -309,6 +376,32 @@ void QgsMapToolMoveLabel::cadCanvasPressEvent( QgsMapMouseEvent *e )
return; return;
} }
// Handle curved offset
if ( isCurved )
{
const QgsFeature feature { mCurrentLabel.layer->getFeature( featureId ) };
const QgsGeometry pointMapGeometry { QgsGeometry::fromPointXY( releaseCoords ) };
const QgsGeometry anchorPoint { feature.geometry().nearestPoint( pointMapGeometry ) };
const double offset { feature.geometry().lineLocatePoint( anchorPoint ) };
vlayer->beginEditCommand( tr( "Moved curved label offset" ) + QStringLiteral( " '%1'" ).arg( currentLabelText( 24 ) ) );
bool success = false;
if ( mCurrentLabel.settings.dataDefinedProperties().isActive( QgsPalLayerSettings::CurvedOffset ) )
{
success = changeCurrentLabelDataDefinedCurvedOffset( offset );
}
if ( !success )
{
if ( !vlayer->isEditable() )
{
QgisApp::instance()->messageBar()->pushWarning( tr( "Move curved label offset" ), tr( "Layer “%1” must be editable in order to move labels from it" ).arg( vlayer->name() ) );
vlayer->endEditCommand();
}
}
}
else
{
double xPosNew = 0; double xPosNew = 0;
double yPosNew = 0; double yPosNew = 0;
@ -415,6 +508,7 @@ void QgsMapToolMoveLabel::cadCanvasPressEvent( QgsMapMouseEvent *e )
vlayer->triggerRepaint(); vlayer->triggerRepaint();
break; break;
} }
}
default: default:
break; break;
} }

View File

@ -248,6 +248,7 @@ void QgsPalLayerSettings::initPropertyDefinitions()
{ QgsPalLayerSettings::PositionX, QgsPropertyDefinition( "PositionX", QObject::tr( "Position (X)" ), QgsPropertyDefinition::Double, origin ) }, { QgsPalLayerSettings::PositionX, QgsPropertyDefinition( "PositionX", QObject::tr( "Position (X)" ), QgsPropertyDefinition::Double, origin ) },
{ QgsPalLayerSettings::PositionY, QgsPropertyDefinition( "PositionY", QObject::tr( "Position (Y)" ), QgsPropertyDefinition::Double, origin ) }, { QgsPalLayerSettings::PositionY, QgsPropertyDefinition( "PositionY", QObject::tr( "Position (Y)" ), QgsPropertyDefinition::Double, origin ) },
{ QgsPalLayerSettings::PositionPoint, QgsPropertyDefinition( "PositionPoint", QgsPropertyDefinition::DataTypeString, QObject::tr( "Position (point)" ), QObject::tr( "A point geometry" ), origin ) }, { QgsPalLayerSettings::PositionPoint, QgsPropertyDefinition( "PositionPoint", QgsPropertyDefinition::DataTypeString, QObject::tr( "Position (point)" ), QObject::tr( "A point geometry" ), origin ) },
{ QgsPalLayerSettings::CurvedOffset, QgsPropertyDefinition( "CurvedOffset", QgsPropertyDefinition::DataTypeString, QObject::tr( "Offset from the line start" ), QObject::tr( "double [0.0-line lenght]" ), origin ) },
{ QgsPalLayerSettings::Hali, QgsPropertyDefinition( "Hali", QgsPropertyDefinition::DataTypeString, QObject::tr( "Horizontal alignment" ), QObject::tr( "string " ) + "[<b>Left</b>|<b>Center</b>|<b>Right</b>]", origin ) }, { QgsPalLayerSettings::Hali, QgsPropertyDefinition( "Hali", QgsPropertyDefinition::DataTypeString, QObject::tr( "Horizontal alignment" ), QObject::tr( "string " ) + "[<b>Left</b>|<b>Center</b>|<b>Right</b>]", origin ) },
{ {
QgsPalLayerSettings::Vali, QgsPropertyDefinition( "Vali", QgsPropertyDefinition::DataTypeString, QObject::tr( "Vertical alignment" ), QObject::tr( "string " ) + QStringLiteral( "[<b>Bottom</b>|<b>Base</b>|<br>" QgsPalLayerSettings::Vali, QgsPropertyDefinition( "Vali", QgsPropertyDefinition::DataTypeString, QObject::tr( "Vertical alignment" ), QObject::tr( "string " ) + QStringLiteral( "[<b>Bottom</b>|<b>Base</b>|<br>"

View File

@ -322,6 +322,7 @@ class CORE_EXPORT QgsPalLayerSettings
PositionX = 9, //!< X-coordinate data defined label position PositionX = 9, //!< X-coordinate data defined label position
PositionY = 10, //!< Y-coordinate data defined label position PositionY = 10, //!< Y-coordinate data defined label position
PositionPoint = 114, //!< Point-coordinate data defined label position PositionPoint = 114, //!< Point-coordinate data defined label position
CurvedOffset = 116, //!< Offset from start for curved lines (since QGIS 3.26)
Hali = 11, //!< Horizontal alignment for data defined label position (Left, Center, Right) 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) Vali = 12, //!< Vertical alignment for data defined label position (Bottom, Base, Half, Cap, Top)
Rotation = 14, //!< Label rotation (deprecated, for old project compatibility only) Rotation = 14, //!< Label rotation (deprecated, for old project compatibility only)

View File

@ -92,6 +92,8 @@ void QgsTextFormatWidget::initWidget()
connect( mCoordYDDBtn, &QgsPropertyOverrideButton::activated, this, &QgsTextFormatWidget::mCoordYDDBtn_activated ); connect( mCoordYDDBtn, &QgsPropertyOverrideButton::activated, this, &QgsTextFormatWidget::mCoordYDDBtn_activated );
connect( mCoordPointDDBtn, &QgsPropertyOverrideButton::changed, this, &QgsTextFormatWidget::mCoordPointDDBtn_changed ); connect( mCoordPointDDBtn, &QgsPropertyOverrideButton::changed, this, &QgsTextFormatWidget::mCoordPointDDBtn_changed );
connect( mCoordPointDDBtn, &QgsPropertyOverrideButton::activated, this, &QgsTextFormatWidget::mCoordPointDDBtn_activated ); connect( mCoordPointDDBtn, &QgsPropertyOverrideButton::activated, this, &QgsTextFormatWidget::mCoordPointDDBtn_activated );
connect( mCurvedLineOffsetDDBtn, &QgsPropertyOverrideButton::changed, this, &QgsTextFormatWidget::mCurvedLineOffsetDDBtn_changed );
connect( mCurvedLineOffsetDDBtn, &QgsPropertyOverrideButton::activated, this, &QgsTextFormatWidget::mCurvedLineOffsetDDBtn_activated );
connect( mShapeTypeCmbBx, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsTextFormatWidget::mShapeTypeCmbBx_currentIndexChanged ); connect( mShapeTypeCmbBx, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsTextFormatWidget::mShapeTypeCmbBx_currentIndexChanged );
connect( mShapeRotationCmbBx, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsTextFormatWidget::mShapeRotationCmbBx_currentIndexChanged ); connect( mShapeRotationCmbBx, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsTextFormatWidget::mShapeRotationCmbBx_currentIndexChanged );
connect( mShapeSVGParamsBtn, &QPushButton::clicked, this, &QgsTextFormatWidget::mShapeSVGParamsBtn_clicked ); connect( mShapeSVGParamsBtn, &QPushButton::clicked, this, &QgsTextFormatWidget::mShapeSVGParamsBtn_clicked );
@ -809,6 +811,7 @@ void QgsTextFormatWidget::populateDataDefinedButtons()
registerDataDefinedButton( mCoordXDDBtn, QgsPalLayerSettings::PositionX ); registerDataDefinedButton( mCoordXDDBtn, QgsPalLayerSettings::PositionX );
registerDataDefinedButton( mCoordYDDBtn, QgsPalLayerSettings::PositionY ); registerDataDefinedButton( mCoordYDDBtn, QgsPalLayerSettings::PositionY );
registerDataDefinedButton( mCoordPointDDBtn, QgsPalLayerSettings::PositionPoint ); registerDataDefinedButton( mCoordPointDDBtn, QgsPalLayerSettings::PositionPoint );
registerDataDefinedButton( mCurvedLineOffsetDDBtn, QgsPalLayerSettings::CurvedOffset );
registerDataDefinedButton( mCoordAlignmentHDDBtn, QgsPalLayerSettings::Hali ); registerDataDefinedButton( mCoordAlignmentHDDBtn, QgsPalLayerSettings::Hali );
registerDataDefinedButton( mCoordAlignmentVDDBtn, QgsPalLayerSettings::Vali ); registerDataDefinedButton( mCoordAlignmentVDDBtn, QgsPalLayerSettings::Vali );
registerDataDefinedButton( mCoordRotationDDBtn, QgsPalLayerSettings::LabelRotation ); registerDataDefinedButton( mCoordRotationDDBtn, QgsPalLayerSettings::LabelRotation );
@ -1616,6 +1619,20 @@ void QgsTextFormatWidget::mCoordPointDDBtn_activated( bool isActive )
mCoordYDDBtn->setActive( false ); mCoordYDDBtn->setActive( false );
} }
void QgsTextFormatWidget::mCurvedLineOffsetDDBtn_changed()
{
// TODO: update something?
}
void QgsTextFormatWidget::mCurvedLineOffsetDDBtn_activated( bool isActive )
{
if ( !isActive )
return;
mCurvedLineOffsetDDBtn->setActive( false );
mCurvedLineOffsetDDBtn->setActive( false );
}
void QgsTextFormatWidget::mShapeTypeCmbBx_currentIndexChanged( int ) void QgsTextFormatWidget::mShapeTypeCmbBx_currentIndexChanged( int )
{ {
// shape background // shape background

View File

@ -290,6 +290,8 @@ class GUI_EXPORT QgsTextFormatWidget : public QWidget, public QgsExpressionConte
void mCoordYDDBtn_activated( bool isActive ); void mCoordYDDBtn_activated( bool isActive );
void mCoordPointDDBtn_changed(); void mCoordPointDDBtn_changed();
void mCoordPointDDBtn_activated( bool isActive ); void mCoordPointDDBtn_activated( bool isActive );
void mCurvedLineOffsetDDBtn_changed();
void mCurvedLineOffsetDDBtn_activated( bool isActive );
void mShapeTypeCmbBx_currentIndexChanged( int index ); void mShapeTypeCmbBx_currentIndexChanged( int index );
void mShapeRotationCmbBx_currentIndexChanged( int index ); void mShapeRotationCmbBx_currentIndexChanged( int index );
void mShapeSVGParamsBtn_clicked(); void mShapeSVGParamsBtn_clicked();

View File

@ -109,7 +109,7 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>499</width> <width>502</width>
<height>300</height> <height>300</height>
</rect> </rect>
</property> </property>
@ -625,7 +625,7 @@
<item> <item>
<widget class="QStackedWidget" name="mLabelStackedWidget"> <widget class="QStackedWidget" name="mLabelStackedWidget">
<property name="currentIndex"> <property name="currentIndex">
<number>0</number> <number>7</number>
</property> </property>
<widget class="QWidget" name="mLabelPage_Text"> <widget class="QWidget" name="mLabelPage_Text">
<layout class="QVBoxLayout" name="verticalLayout_6"> <layout class="QVBoxLayout" name="verticalLayout_6">
@ -654,8 +654,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>485</width> <width>486</width>
<height>429</height> <height>457</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="0,1"> <layout class="QVBoxLayout" name="verticalLayout_2" stretch="0,1">
@ -1217,8 +1217,8 @@ font-style: italic;</string>
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>471</width> <width>281</width>
<height>742</height> <height>597</height>
</rect> </rect>
</property> </property>
<layout class="QGridLayout" name="gridLayout_42"> <layout class="QGridLayout" name="gridLayout_42">
@ -2131,8 +2131,8 @@ font-style: italic;</string>
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>299</width> <width>223</width>
<height>308</height> <height>250</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_12"> <layout class="QVBoxLayout" name="verticalLayout_12">
@ -2477,8 +2477,8 @@ font-style: italic;</string>
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>296</width> <width>223</width>
<height>291</height> <height>219</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_121"> <layout class="QVBoxLayout" name="verticalLayout_121">
@ -2755,8 +2755,8 @@ font-style: italic;</string>
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>438</width> <width>357</width>
<height>753</height> <height>606</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_21"> <layout class="QVBoxLayout" name="verticalLayout_21">
@ -3506,8 +3506,8 @@ font-style: italic;</string>
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>324</width> <width>267</width>
<height>457</height> <height>372</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_22"> <layout class="QVBoxLayout" name="verticalLayout_22">
@ -3934,8 +3934,8 @@ font-style: italic;</string>
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>159</width> <width>119</width>
<height>211</height> <height>166</height>
</rect> </rect>
</property> </property>
<layout class="QGridLayout" name="gridLayout_46"> <layout class="QGridLayout" name="gridLayout_46">
@ -4083,9 +4083,9 @@ font-style: italic;</string>
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>-936</y>
<width>472</width> <width>475</width>
<height>1690</height> <height>1402</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_11"> <layout class="QVBoxLayout" name="verticalLayout_11">
@ -5418,42 +5418,13 @@ font-style: italic;</string>
<string notr="true">labelplacementgroup</string> <string notr="true">labelplacementgroup</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout_4"> <layout class="QGridLayout" name="gridLayout_4">
<property name="leftMargin"> <item row="0" column="0">
<number>8</number> <widget class="QLabel" name="mCoordLabel">
</property>
<property name="rightMargin">
<number>8</number>
</property>
<item row="3" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_25">
<item>
<widget class="QgsPropertyOverrideButton" name="mCoordRotationDDBtn">
<property name="text"> <property name="text">
<string>…</string> <string>Coordinate</string>
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QComboBox" name="mCoordRotationUnitComboBox"/>
</item>
<item>
<widget class="QCheckBox" name="chkPreserveRotation">
<property name="toolTip">
<string>Uncheck to write labeling engine derived rotation on pin and NULL on unpin</string>
</property>
<property name="styleSheet">
<string notr="true">margin-left: 12px; margin-top: 3px;</string>
</property>
<property name="text">
<string>Preserve data rotation values</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="1"> <item row="0" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_22"> <layout class="QHBoxLayout" name="horizontalLayout_22">
<item> <item>
@ -5511,14 +5482,76 @@ font-style: italic;</string>
</item> </item>
</layout> </layout>
</item> </item>
<item row="0" column="0"> <item row="1" column="0">
<widget class="QLabel" name="mCoordLabel"> <widget class="QLabel" name="label_44">
<property name="text"> <property name="text">
<string>Coordinate</string> <string>Point</string>
</property>
</widget>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_15">
<item>
<widget class="QgsPropertyOverrideButton" name="mCoordPointDDBtn">
<property name="text">
<string>…</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_22">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_47">
<property name="text">
<string>Offset</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="1"> <item row="2" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_18">
<item>
<widget class="QgsPropertyOverrideButton" name="mCurvedLineOffsetDDBtn">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_24">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="3" column="0">
<widget class="QLabel" name="mCoordAlignmentLabel">
<property name="text">
<string>Alignment</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QFrame" name="mCoordAlignmentFrame"> <widget class="QFrame" name="mCoordAlignmentFrame">
<layout class="QHBoxLayout" name="horizontalLayout_27"> <layout class="QHBoxLayout" name="horizontalLayout_27">
<property name="leftMargin"> <property name="leftMargin">
@ -5589,51 +5622,43 @@ font-style: italic;</string>
</layout> </layout>
</widget> </widget>
</item> </item>
<item row="3" column="0"> <item row="4" column="0">
<widget class="QLabel" name="mCoordRotationLabel"> <widget class="QLabel" name="mCoordRotationLabel">
<property name="text"> <property name="text">
<string>Rotation</string> <string>Rotation</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="1"> <item row="4" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_15"> <layout class="QHBoxLayout" name="horizontalLayout_25">
<item> <item>
<widget class="QgsPropertyOverrideButton" name="mCoordPointDDBtn"> <widget class="QgsPropertyOverrideButton" name="mCoordRotationDDBtn">
<property name="text"> <property name="text">
<string>…</string> <string>…</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<spacer name="horizontalSpacer_22"> <widget class="QComboBox" name="mCoordRotationUnitComboBox"/>
<property name="orientation"> </item>
<enum>Qt::Horizontal</enum> <item>
<widget class="QCheckBox" name="chkPreserveRotation">
<property name="toolTip">
<string>Uncheck to write labeling engine derived rotation on pin and NULL on unpin</string>
</property> </property>
<property name="sizeHint" stdset="0"> <property name="styleSheet">
<size> <string notr="true">margin-left: 12px; margin-top: 3px;</string>
<width>0</width>
<height>20</height>
</size>
</property> </property>
</spacer> <property name="text">
<string>Preserve data rotation values</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item> </item>
</layout> </layout>
</item> </item>
<item row="2" column="0">
<widget class="QLabel" name="mCoordAlignmentLabel">
<property name="text">
<string>Alignment</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_44">
<property name="text">
<string>Point</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>
@ -5818,8 +5843,8 @@ font-style: italic;</string>
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>430</width> <width>304</width>
<height>708</height> <height>571</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_8"> <layout class="QVBoxLayout" name="verticalLayout_8">
@ -6953,6 +6978,7 @@ font-style: italic;</string>
<tabstop>mCoordXDDBtn</tabstop> <tabstop>mCoordXDDBtn</tabstop>
<tabstop>mCoordYDDBtn</tabstop> <tabstop>mCoordYDDBtn</tabstop>
<tabstop>mCoordPointDDBtn</tabstop> <tabstop>mCoordPointDDBtn</tabstop>
<tabstop>mCurvedLineOffsetDDBtn</tabstop>
<tabstop>mCoordAlignmentHDDBtn</tabstop> <tabstop>mCoordAlignmentHDDBtn</tabstop>
<tabstop>mCoordAlignmentVDDBtn</tabstop> <tabstop>mCoordAlignmentVDDBtn</tabstop>
<tabstop>mCoordRotationDDBtn</tabstop> <tabstop>mCoordRotationDDBtn</tabstop>
@ -6994,6 +7020,8 @@ font-style: italic;</string>
</tabstops> </tabstops>
<resources> <resources>
<include location="../../images/images.qrc"/> <include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
</resources> </resources>
<connections> <connections>
<connection> <connection>