Skip to content

Commit

Permalink
Merge pull request #46725 from nirvn/label_alg_extra
Browse files Browse the repository at this point in the history
A couple of additional details and an important fix to the extract labels alg.
  • Loading branch information
nirvn committed Jan 7, 2022
2 parents 612f5dc + 93c89a5 commit f3c5b6e
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 27 deletions.
3 changes: 2 additions & 1 deletion python/core/auto_generated/qgsmaplayerproxymodel.sip.in
Expand Up @@ -37,7 +37,8 @@ The :py:class:`QgsMapLayerProxyModel` class provides an easy to use model to dis
VectorTileLayer,
PointCloudLayer,
AnnotationLayer,
All
All,
SpatialLayer
};
typedef QFlags<QgsMapLayerProxyModel::Filter> Filters;

Expand Down
116 changes: 94 additions & 22 deletions src/analysis/processing/qgsalgorithmextractlabels.cpp
Expand Up @@ -14,6 +14,7 @@
***************************************************************************/

#include "qgsalgorithmextractlabels.h"
#include "qgsexpressioncontextutils.h"
#include "qgsprocessingparameters.h"
#include "qgsmapthemecollection.h"
#include "qgsmaprenderercustompainterjob.h"
Expand Down Expand Up @@ -129,15 +130,15 @@ class ExtractLabelSink : public QgsLabelSink

void drawLabel( const QString &layerId, QgsRenderContext &context, pal::LabelPosition *label, const QgsPalLayerSettings &settings ) override
{
processLabel( layerId, context, label, settings );
processLabel( layerId, context, label, settings, false );
}

void drawUnplacedLabel( const QString &layerId, QgsRenderContext &context, pal::LabelPosition *label, const QgsPalLayerSettings &settings ) override
{
processLabel( layerId, context, label, settings );
processLabel( layerId, context, label, settings, true );
}

void processLabel( const QString &layerId, QgsRenderContext &context, pal::LabelPosition *label, const QgsPalLayerSettings &settings )
void processLabel( const QString &layerId, QgsRenderContext &context, pal::LabelPosition *label, const QgsPalLayerSettings &settings, bool unplacedLabel )
{
if ( mFeedback->isCanceled() )
{
Expand Down Expand Up @@ -231,24 +232,70 @@ class ExtractLabelSink : public QgsLabelSink
const double fontSize = static_cast<double>( font.pixelSize() ) * 72 / context.painter()->device()->logicalDpiX();
const bool fontItalic = font.italic();
const bool fontBold = font.bold();
const bool fontUnderline = font.underline();
const double fontLetterSpacing = font.letterSpacing();
const double fontWordSpacing = font.wordSpacing();

QgsTextFormat format = labelSettings.format();
if ( dataDefinedValues.contains( QgsPalLayerSettings::Size ) )
{
format.setSize( dataDefinedValues.value( QgsPalLayerSettings::Size ).toDouble() );
}
if ( dataDefinedValues.contains( QgsPalLayerSettings::Color ) )
{
format.setColor( dataDefinedValues.value( QgsPalLayerSettings::Color ).value<QColor>() );
}
if ( dataDefinedValues.contains( QgsPalLayerSettings::FontOpacity ) )
{
format.setOpacity( dataDefinedValues.value( QgsPalLayerSettings::FontOpacity ).toDouble() / 100.0 );
}
if ( dataDefinedValues.contains( QgsPalLayerSettings::MultiLineHeight ) )
{
QgsTextFormat format = labelSettings.format();
format.setLineHeight( dataDefinedValues.value( QgsPalLayerSettings::MultiLineHeight ).toDouble() );
labelSettings.setFormat( format );
}

QgsTextFormat format = labelSettings.format();
double formatLineHeight = format.lineHeight();
const QString formatColor = format.color().name();
const double formatOpacity = format.opacity() * 100;
const double formatLineHeight = format.lineHeight();

QgsTextBufferSettings buffer = format.buffer();
if ( dataDefinedValues.contains( QgsPalLayerSettings::BufferDraw ) )
{
buffer.setEnabled( dataDefinedValues.value( QgsPalLayerSettings::BufferDraw ).toBool() );
}
const bool bufferDraw = buffer.enabled();
double bufferSize = 0.0;
QString bufferColor;
double bufferOpacity = 0.0;
if ( bufferDraw )
{
if ( dataDefinedValues.contains( QgsPalLayerSettings::BufferSize ) )
{
buffer.setSize( dataDefinedValues.value( QgsPalLayerSettings::BufferSize ).toDouble() );
}
if ( dataDefinedValues.contains( QgsPalLayerSettings::BufferColor ) )
{
buffer.setColor( dataDefinedValues.value( QgsPalLayerSettings::BufferColor ).value<QColor>() );
}
if ( dataDefinedValues.contains( QgsPalLayerSettings::BufferOpacity ) )
{
buffer.setOpacity( dataDefinedValues.value( QgsPalLayerSettings::BufferOpacity ).toDouble() / 100.0 );
}

bufferSize = buffer.sizeUnit() == QgsUnitTypes::RenderPercentage
? context.convertToPainterUnits( format.size(), format.sizeUnit(), format.sizeMapUnitScale() ) * buffer.size() / 100
: context.convertToPainterUnits( buffer.size(), buffer.sizeUnit(), buffer.sizeMapUnitScale() );
bufferSize = bufferSize * 72 / context.painter()->device()->logicalDpiX();
bufferColor = buffer.color().name();
bufferOpacity = buffer.opacity() * 100;
}

QgsAttributes attributes;
attributes << mMapLayerNames.value( layerId ) << fid
<< labelText << label->getWidth() << label->getHeight() << labelRotation << label->conflictsWithObstacle()
<< fontFamily << fontSize << fontItalic << fontBold << fontStyle << fontLetterSpacing << fontWordSpacing
<< labelAlignment << formatLineHeight;
<< labelText << label->getWidth() << label->getHeight() << labelRotation << unplacedLabel
<< fontFamily << fontSize << fontItalic << fontBold << fontUnderline << fontStyle << fontLetterSpacing << fontWordSpacing
<< labelAlignment << formatLineHeight << formatColor << formatOpacity
<< bufferDraw << bufferSize << bufferColor << bufferOpacity;

double x = label->getX();
double y = label->getY();
Expand Down Expand Up @@ -293,19 +340,26 @@ QVariantMap QgsExtractLabelsAlgorithm::processAlgorithm( const QVariantMap &para
fields.append( QgsField( QStringLiteral( "Layer" ), QVariant::String, QString(), 0, 0 ) );
fields.append( QgsField( QStringLiteral( "FeatureID" ), QVariant::LongLong, QString(), 20 ) );
fields.append( QgsField( QStringLiteral( "LabelText" ), QVariant::String, QString(), 0, 0 ) );
fields.append( QgsField( QStringLiteral( "LabelWidth" ), QVariant::String, QString(), 20, 8 ) );
fields.append( QgsField( QStringLiteral( "LabelHeight" ), QVariant::String, QString(), 20, 8 ) );
fields.append( QgsField( QStringLiteral( "LabelWidth" ), QVariant::Double, QString(), 20, 8 ) );
fields.append( QgsField( QStringLiteral( "LabelHeight" ), QVariant::Double, QString(), 20, 8 ) );
fields.append( QgsField( QStringLiteral( "LabelRotation" ), QVariant::Double, QString(), 20, 2 ) );
fields.append( QgsField( QStringLiteral( "LabelUnplaced" ), QVariant::Bool, QString(), 1, 0 ) );
fields.append( QgsField( QStringLiteral( "Family" ), QVariant::String, QString(), 0, 0 ) );
fields.append( QgsField( QStringLiteral( "Size" ), QVariant::Double, QString(), 20, 4 ) );
fields.append( QgsField( QStringLiteral( "Italic" ), QVariant::Bool, QString(), 1, 0 ) );
fields.append( QgsField( QStringLiteral( "Bold" ), QVariant::Bool, QString(), 1, 0 ) );
fields.append( QgsField( QStringLiteral( "Underline" ), QVariant::Bool, QString(), 1, 0 ) );
fields.append( QgsField( QStringLiteral( "FontStyle" ), QVariant::String, QString(), 0, 0 ) );
fields.append( QgsField( QStringLiteral( "FontLetterSpacing" ), QVariant::Double, QString(), 20, 4 ) );
fields.append( QgsField( QStringLiteral( "FontWordSpacing" ), QVariant::Double, QString(), 20, 4 ) );
fields.append( QgsField( QStringLiteral( "MultiLineAlignment" ), QVariant::String, QString(), 0, 0 ) );
fields.append( QgsField( QStringLiteral( "MultiLineHeight" ), QVariant::Double, QString(), 20, 2 ) );
fields.append( QgsField( QStringLiteral( "Color" ), QVariant::String, QString(), 7, 0 ) );
fields.append( QgsField( QStringLiteral( "FontOpacity" ), QVariant::Double, QString(), 20, 1 ) );
fields.append( QgsField( QStringLiteral( "BufferDraw" ), QVariant::Bool, QString(), 1, 0 ) );
fields.append( QgsField( QStringLiteral( "BufferSize" ), QVariant::Double, QString(), 20, 4 ) );
fields.append( QgsField( QStringLiteral( "BufferColor" ), QVariant::String, QString(), 7, 0 ) );
fields.append( QgsField( QStringLiteral( "BufferOpacity" ), QVariant::Double, QString(), 20, 1 ) );

QString dest;
std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, fields, QgsWkbTypes::Point, mCrs, QgsFeatureSink::RegeneratePrimaryKey ) );
Expand All @@ -324,6 +378,13 @@ QVariantMap QgsExtractLabelsAlgorithm::processAlgorithm( const QVariantMap &para
mapSettings.setLayerStyleOverrides( mMapThemeStyleOverrides );
mapSettings.setLabelingEngineSettings( mLabelSettings );

//build the expression context
QgsExpressionContext expressionContext;
expressionContext << QgsExpressionContextUtils::globalScope()
<< QgsExpressionContextUtils::projectScope( context.project() )
<< QgsExpressionContextUtils::mapSettingsScope( mapSettings );
mapSettings.setExpressionContext( expressionContext );

QgsNullPaintDevice nullPaintDevice;
nullPaintDevice.setOutputSize( imageSize );
nullPaintDevice.setOutputDpi( dpi );
Expand Down Expand Up @@ -375,18 +436,29 @@ QVariantMap QgsExtractLabelsAlgorithm::processAlgorithm( const QVariantMap &para
textFormat.setSize( 9 );
textFormat.setSizeUnit( QgsUnitTypes::RenderPoints );
textFormat.setColor( QColor( 0, 0, 0 ) );

QgsTextBufferSettings buffer = textFormat.buffer();
buffer.setSizeUnit( QgsUnitTypes::RenderPoints );

textFormat.setBuffer( buffer );
settings.setFormat( textFormat );

settingsProperties.setProperty( QgsPalLayerSettings::Color, QgsProperty::fromExpression( QStringLiteral( "if(\"LabelUnplaced\",'255,0,0','0,0,0')" ) ) );
settingsProperties.setProperty( QgsPalLayerSettings::Family, QgsProperty::fromExpression( QStringLiteral( "\"Family\"" ) ) );
settingsProperties.setProperty( QgsPalLayerSettings::Italic, QgsProperty::fromExpression( QStringLiteral( "\"Italic\"" ) ) );
settingsProperties.setProperty( QgsPalLayerSettings::Bold, QgsProperty::fromExpression( QStringLiteral( "\"Bold\"" ) ) );
settingsProperties.setProperty( QgsPalLayerSettings::Size, QgsProperty::fromExpression( QStringLiteral( "\"Size\"" ) ) );
settingsProperties.setProperty( QgsPalLayerSettings::FontLetterSpacing, QgsProperty::fromExpression( QStringLiteral( "\"FontLetterSpacing\"" ) ) );
settingsProperties.setProperty( QgsPalLayerSettings::FontWordSpacing, QgsProperty::fromExpression( QStringLiteral( "\"FontWordSpacing\"" ) ) );
settingsProperties.setProperty( QgsPalLayerSettings::MultiLineAlignment, QgsProperty::fromExpression( QStringLiteral( "\"MultiLineAlignment\"" ) ) );
settingsProperties.setProperty( QgsPalLayerSettings::MultiLineHeight, QgsProperty::fromExpression( QStringLiteral( "\"MultiLineHeight\"" ) ) );
settingsProperties.setProperty( QgsPalLayerSettings::LabelRotation, QgsProperty::fromExpression( QStringLiteral( "\"LabelRotation\"" ) ) );
settingsProperties.setProperty( QgsPalLayerSettings::Color, QgsProperty::fromExpression( QStringLiteral( "if(\"LabelUnplaced\",'255,0,0',\"Color\")" ) ) );
settingsProperties.setProperty( QgsPalLayerSettings::FontOpacity, QgsProperty::fromField( QStringLiteral( "FontOpacity" ) ) );
settingsProperties.setProperty( QgsPalLayerSettings::Family, QgsProperty::fromField( QStringLiteral( "Family" ) ) );
settingsProperties.setProperty( QgsPalLayerSettings::Italic, QgsProperty::fromField( QStringLiteral( "Italic" ) ) );
settingsProperties.setProperty( QgsPalLayerSettings::Bold, QgsProperty::fromField( QStringLiteral( "Bold" ) ) );
settingsProperties.setProperty( QgsPalLayerSettings::Underline, QgsProperty::fromField( QStringLiteral( "Underline" ) ) );
settingsProperties.setProperty( QgsPalLayerSettings::Size, QgsProperty::fromField( QStringLiteral( "Size" ) ) );
settingsProperties.setProperty( QgsPalLayerSettings::FontLetterSpacing, QgsProperty::fromField( QStringLiteral( "FontLetterSpacing" ) ) );
settingsProperties.setProperty( QgsPalLayerSettings::FontWordSpacing, QgsProperty::fromField( QStringLiteral( "FontWordSpacing" ) ) );
settingsProperties.setProperty( QgsPalLayerSettings::MultiLineAlignment, QgsProperty::fromField( QStringLiteral( "MultiLineAlignment" ) ) );
settingsProperties.setProperty( QgsPalLayerSettings::MultiLineHeight, QgsProperty::fromField( QStringLiteral( "MultiLineHeight" ) ) );
settingsProperties.setProperty( QgsPalLayerSettings::LabelRotation, QgsProperty::fromField( QStringLiteral( "LabelRotation" ) ) );
settingsProperties.setProperty( QgsPalLayerSettings::BufferDraw, QgsProperty::fromField( QStringLiteral( "BufferDraw" ) ) );
settingsProperties.setProperty( QgsPalLayerSettings::BufferSize, QgsProperty::fromField( QStringLiteral( "BufferSize" ) ) );
settingsProperties.setProperty( QgsPalLayerSettings::BufferColor, QgsProperty::fromField( QStringLiteral( "BufferColor" ) ) );
settingsProperties.setProperty( QgsPalLayerSettings::BufferOpacity, QgsProperty::fromField( QStringLiteral( "BufferOpacity" ) ) );
settingsProperties.setProperty( QgsPalLayerSettings::Show, QgsProperty::fromExpression( QStringLiteral( "\"LabelUnplaced\"=false" ) ) );
settings.setDataDefinedProperties( settingsProperties );

Expand Down
3 changes: 2 additions & 1 deletion src/core/qgsmaplayerproxymodel.h
Expand Up @@ -55,7 +55,8 @@ class CORE_EXPORT QgsMapLayerProxyModel : public QSortFilterProxyModel
VectorTileLayer = 256, //!< QgsVectorTileLayer \since QGIS 3.14
PointCloudLayer = 512, //!< QgsPointCloudLayer \since QGIS 3.18
AnnotationLayer = 1024, //!< QgsAnnotationLayer \since QGIS 3.22
All = RasterLayer | VectorLayer | PluginLayer | MeshLayer | VectorTileLayer | PointCloudLayer | AnnotationLayer
All = RasterLayer | VectorLayer | PluginLayer | MeshLayer | VectorTileLayer | PointCloudLayer | AnnotationLayer,
SpatialLayer = RasterLayer | HasGeometry | PluginLayer | MeshLayer | VectorTileLayer | PointCloudLayer | AnnotationLayer //!< \since QGIS 3.24
};
Q_DECLARE_FLAGS( Filters, Filter )
Q_FLAG( Filters )
Expand Down
4 changes: 3 additions & 1 deletion src/gui/qgsextentwidget.cpp
Expand Up @@ -19,6 +19,7 @@
#include "qgslogger.h"
#include "qgscoordinatetransform.h"
#include "qgsmapcanvas.h"
#include "qgsmaplayerproxymodel.h"
#include "qgsmaplayermodel.h"
#include "qgsexception.h"
#include "qgsproject.h"
Expand Down Expand Up @@ -51,7 +52,8 @@ QgsExtentWidget::QgsExtentWidget( QWidget *parent, WidgetStyle style )
mLayerMenu = new QMenu( tr( "Calculate from Layer" ), this );
mButtonCalcFromLayer->setMenu( mLayerMenu );
connect( mLayerMenu, &QMenu::aboutToShow, this, &QgsExtentWidget::layerMenuAboutToShow );
mMapLayerModel = new QgsMapLayerModel( this );
mMapLayerModel = new QgsMapLayerProxyModel( this );
mMapLayerModel->setFilters( QgsMapLayerProxyModel::Filter::SpatialLayer );

mLayoutMenu = new QMenu( tr( "Calculate from Layout Map" ), this );
mButtonCalcFromLayout->setMenu( mLayoutMenu );
Expand Down
4 changes: 2 additions & 2 deletions src/gui/qgsextentwidget.h
Expand Up @@ -32,7 +32,7 @@

class QgsBookmarkManagerProxyModel;
class QgsCoordinateReferenceSystem;
class QgsMapLayerModel;
class QgsMapLayerProxyModel;
class QgsMapLayer;

/**
Expand Down Expand Up @@ -272,7 +272,7 @@ class GUI_EXPORT QgsExtentWidget : public QWidget, private Ui::QgsExtentGroupBox
QMenu *mLayoutMenu = nullptr;
QMenu *mBookmarkMenu = nullptr;

QgsMapLayerModel *mMapLayerModel = nullptr;
QgsMapLayerProxyModel *mMapLayerModel = nullptr;
QgsBookmarkManagerProxyModel *mBookmarkModel = nullptr;

QList< QAction * > mLayerMenuActions;
Expand Down

0 comments on commit f3c5b6e

Please sign in to comment.