Skip to content

Commit

Permalink
Allow label settings gui widget to work widget layers
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Jun 21, 2019
1 parent 0fd4984 commit aa658e5
Show file tree
Hide file tree
Showing 9 changed files with 310 additions and 21 deletions.
14 changes: 14 additions & 0 deletions python/core/auto_generated/qgspallabeling.sip.in
Expand Up @@ -444,6 +444,8 @@ Returns the QgsExpression for this label settings. May be ``None`` if isExpressi

bool geometryGeneratorEnabled;

QgsWkbTypes::GeometryType layerType;

void calculateLabelSize( const QFontMetricsF *fm, const QString &text, double &labelX, double &labelY, const QgsFeature *f = 0, QgsRenderContext *context = 0 );
%Docstring
Calculates the space required to render the provided ``text`` in map units.
Expand Down Expand Up @@ -517,6 +519,18 @@ Sets the label text formatting settings, e.g., font settings, buffer settings, e
.. seealso:: :py:func:`format`

.. versionadded:: 3.0
%End

static QPixmap labelSettingsPreviewPixmap( const QgsPalLayerSettings &settings, QSize size, const QString &previewText = QString(), int padding = 0 );
%Docstring
Returns a pixmap preview for label ``settings``.

:param settings: label settings
:param size: target pixmap size
:param previewText: text to render in preview, or empty for default text
:param padding: space between icon edge and color ramp

.. versionadded:: 3.10
%End

const QgsFeature *mCurFeat;
Expand Down
2 changes: 0 additions & 2 deletions src/app/CMakeLists.txt
Expand Up @@ -52,7 +52,6 @@ SET(QGIS_APP_SRCS
qgsfeatureaction.cpp
qgslabelpropertydialog.cpp
qgslabelengineconfigdialog.cpp
qgslabelinggui.cpp
qgslabelingwidget.cpp
qgslayercapabilitiesmodel.cpp
qgslayertreeviewindicatorprovider.cpp
Expand Down Expand Up @@ -291,7 +290,6 @@ SET (QGIS_APP_MOC_HDRS
qgshtmlannotationdialog.h
qgsidentifyresultsdialog.h
qgslabelengineconfigdialog.h
qgslabelinggui.h
qgslabelingwidget.h
qgslabelpropertydialog.h
qgslayercapabilitiesmodel.h
Expand Down
102 changes: 102 additions & 0 deletions src/core/qgspallabeling.cpp
Expand Up @@ -19,6 +19,7 @@
#include "qgstextlabelfeature.h"
#include "qgsunittypes.h"
#include "qgsexception.h"
#include "qgsapplication.h"

#include <list>

Expand All @@ -37,6 +38,7 @@
#include <QFontMetrics>
#include <QTime>
#include <QPainter>
#include <QDesktopWidget>

#include "diagram/qgsdiagram.h"
#include "qgsdiagramrenderer.h"
Expand Down Expand Up @@ -396,6 +398,7 @@ QgsPalLayerSettings &QgsPalLayerSettings::operator=( const QgsPalLayerSettings &
geometryGenerator = s.geometryGenerator;
geometryGeneratorEnabled = s.geometryGeneratorEnabled;
geometryGeneratorType = s.geometryGeneratorType;
layerType = s.layerType;

return *this;
}
Expand Down Expand Up @@ -1002,6 +1005,8 @@ void QgsPalLayerSettings::readXml( const QDomElement &elem, const QgsReadWriteCo
geometryGeneratorEnabled = placementElem.attribute( QStringLiteral( "geometryGeneratorEnabled" ) ).toInt();
geometryGeneratorType = qgsEnumKeyToValue( placementElem.attribute( QStringLiteral( "geometryGeneratorType" ) ), QgsWkbTypes::PointGeometry );

layerType = qgsEnumKeyToValue( placementElem.attribute( QStringLiteral( "layerType" ) ), QgsWkbTypes::UnknownGeometry );

// rendering
QDomElement renderingElem = elem.firstChildElement( QStringLiteral( "rendering" ) );

Expand Down Expand Up @@ -1140,6 +1145,8 @@ QDomElement QgsPalLayerSettings::writeXml( QDomDocument &doc, const QgsReadWrite
const QMetaEnum metaEnum( QMetaEnum::fromType<QgsWkbTypes::GeometryType>() );
placementElem.setAttribute( QStringLiteral( "geometryGeneratorType" ), metaEnum.valueToKey( geometryGeneratorType ) );

placementElem.setAttribute( QStringLiteral( "layerType" ), metaEnum.valueToKey( layerType ) );

// rendering
QDomElement renderingElem = doc.createElement( QStringLiteral( "rendering" ) );
renderingElem.setAttribute( QStringLiteral( "drawLabels" ), drawLabels );
Expand Down Expand Up @@ -1174,6 +1181,101 @@ QDomElement QgsPalLayerSettings::writeXml( QDomDocument &doc, const QgsReadWrite
return elem;
}

QPixmap QgsPalLayerSettings::labelSettingsPreviewPixmap( const QgsPalLayerSettings &settings, QSize size, const QString &previewText, int padding )
{
// for now, just use format
QgsTextFormat tempFormat = settings.format();
QPixmap pixmap( size );
pixmap.fill( Qt::transparent );
QPainter painter;
painter.begin( &pixmap );

painter.setRenderHint( QPainter::Antialiasing );

QRect rect( 0, 0, size.width(), size.height() );

// shameless eye candy - use a subtle gradient when drawing background
painter.setPen( Qt::NoPen );
QColor background1 = tempFormat.previewBackgroundColor();
if ( ( background1.lightnessF() < 0.7 ) )
{
background1 = background1.darker( 125 );
}
else
{
background1 = background1.lighter( 125 );
}
QColor background2 = tempFormat.previewBackgroundColor();
QLinearGradient linearGrad( QPointF( 0, 0 ), QPointF( 0, rect.height() ) );
linearGrad.setColorAt( 0, background1 );
linearGrad.setColorAt( 1, background2 );
painter.setBrush( QBrush( linearGrad ) );
if ( size.width() > 30 )
{
painter.drawRoundedRect( rect, 6, 6 );
}
else
{
// don't use rounded rect for small previews
painter.drawRect( rect );
}
painter.setBrush( Qt::NoBrush );
painter.setPen( Qt::NoPen );
padding += 1; // move text away from background border

QgsRenderContext context;
QgsMapToPixel newCoordXForm;
newCoordXForm.setParameters( 1, 0, 0, 0, 0, 0 );
context.setMapToPixel( newCoordXForm );

context.setScaleFactor( QgsApplication::desktop()->logicalDpiX() / 25.4 );
context.setUseAdvancedEffects( true );
context.setPainter( &painter );

// slightly inset text to account for buffer/background
double xtrans = 0;
if ( tempFormat.buffer().enabled() )
xtrans = context.convertToPainterUnits( tempFormat.buffer().size(), tempFormat.buffer().sizeUnit(), tempFormat.buffer().sizeMapUnitScale() );
if ( tempFormat.background().enabled() && tempFormat.background().sizeType() != QgsTextBackgroundSettings::SizeFixed )
xtrans = std::max( xtrans, context.convertToPainterUnits( tempFormat.background().size().width(), tempFormat.background().sizeUnit(), tempFormat.background().sizeMapUnitScale() ) );

double ytrans = 0.0;
if ( tempFormat.buffer().enabled() )
ytrans = std::max( ytrans, context.convertToPainterUnits( tempFormat.buffer().size(), tempFormat.buffer().sizeUnit(), tempFormat.buffer().sizeMapUnitScale() ) );
if ( tempFormat.background().enabled() )
ytrans = std::max( ytrans, context.convertToPainterUnits( tempFormat.background().size().height(), tempFormat.background().sizeUnit(), tempFormat.background().sizeMapUnitScale() ) );

const QStringList text = QStringList() << ( previewText.isEmpty() ? QObject::tr( "Aa" ) : previewText );
const double textHeight = QgsTextRenderer::textHeight( context, tempFormat, text, QgsTextRenderer::Rect );
QRectF textRect = rect;
textRect.setLeft( xtrans + padding );
textRect.setWidth( rect.width() - xtrans - 2 * padding );

if ( textRect.width() > 2000 )
textRect.setWidth( 2000 - 2 * padding );

const double bottom = textRect.height() / 2 + textHeight / 2;
textRect.setTop( bottom - textHeight );
textRect.setBottom( bottom );

QgsTextRenderer::drawText( textRect, 0, QgsTextRenderer::AlignCenter, text, context, tempFormat );

// draw border on top of text
painter.setBrush( Qt::NoBrush );
painter.setPen( QPen( tempFormat.previewBackgroundColor().darker( 150 ), 0 ) );
if ( size.width() > 30 )
{
painter.drawRoundedRect( rect, 6, 6 );
}
else
{
// don't use rounded rect for small previews
painter.drawRect( rect );
}
painter.end();
return pixmap;
}

bool QgsPalLayerSettings::checkMinimumSizeMM( const QgsRenderContext &ct, const QgsGeometry &geom, double minSize ) const
{
return QgsPalLabeling::checkMinimumSizeMM( ct, geom, minSize );
Expand Down
16 changes: 16 additions & 0 deletions src/core/qgspallabeling.h
Expand Up @@ -851,6 +851,12 @@ class CORE_EXPORT QgsPalLayerSettings
//! Defines if the geometry generator is enabled or not. If disabled, the standard geometry will be taken.
bool geometryGeneratorEnabled = false;

/**
* Geometry type of layers associated with these settings.
* \since QGIS 3.10
*/
QgsWkbTypes::GeometryType layerType = QgsWkbTypes::UnknownGeometry;

/**
* Calculates the space required to render the provided \a text in map units.
* Results will be written to \a labelX and \a labelY.
Expand Down Expand Up @@ -926,6 +932,16 @@ class CORE_EXPORT QgsPalLayerSettings
*/
void setFormat( const QgsTextFormat &format ) { mFormat = format; }

/**
* Returns a pixmap preview for label \a settings.
* \param settings label settings
* \param size target pixmap size
* \param previewText text to render in preview, or empty for default text
* \param padding space between icon edge and color ramp
* \since QGIS 3.10
*/
static QPixmap labelSettingsPreviewPixmap( const QgsPalLayerSettings &settings, QSize size, const QString &previewText = QString(), int padding = 0 );

// temporary stuff: set when layer gets prepared or labeled
const QgsFeature *mCurFeat = nullptr;
QgsFields mCurFields;
Expand Down
44 changes: 36 additions & 8 deletions src/core/symbology/qgsstylemodel.cpp
Expand Up @@ -93,7 +93,7 @@ QVariant QgsStyleModel::data( const QModelIndex &index, int role ) const
break;

case QgsStyle::LabelSettingsEntity:
name = mTextFormatNames.value( index.row() - mSymbolNames.size() - mRampNames.size() - mTextFormatNames.size() );
name = mLabelSettingsNames.value( index.row() - mSymbolNames.size() - mRampNames.size() - mTextFormatNames.size() );
break;

case QgsStyle::TagEntity:
Expand Down Expand Up @@ -150,8 +150,20 @@ QVariant QgsStyleModel::data( const QModelIndex &index, int role ) const
break;
}

case QgsStyle::ColorrampEntity:
case QgsStyle::LabelSettingsEntity:
{
int width = static_cast< int >( Qgis::UI_SCALE_FACTOR * QFontMetrics( data( index, Qt::FontRole ).value< QFont >() ).width( 'X' ) * 23 );
int height = static_cast< int >( width / 1.61803398875 ); // golden ratio
const QgsPalLayerSettings settings = mStyle->labelSettings( name );
QPixmap pm = QgsPalLayerSettings::labelSettingsPreviewPixmap( settings, QSize( width, height ), QString(), height / 20 );
QByteArray data;
QBuffer buffer( &data );
pm.save( &buffer, "PNG", 100 );
tooltip += QStringLiteral( "<p><img src='data:image/png;base64, %3'>" ).arg( QString( data.toBase64() ) );
break;
}

case QgsStyle::ColorrampEntity:
case QgsStyle::TagEntity:
case QgsStyle::SmartgroupEntity:
break;
Expand Down Expand Up @@ -244,7 +256,23 @@ QVariant QgsStyleModel::data( const QModelIndex &index, int role ) const
}

case QgsStyle::LabelSettingsEntity:
return QVariant();
{
// use cached icon if possible
QIcon icon = mLabelSettingsIconCache.value( name );
if ( !icon.isNull() )
return icon;

const QgsPalLayerSettings settings( mStyle->labelSettings( name ) );
if ( mAdditionalSizes.isEmpty() )
icon.addPixmap( QgsPalLayerSettings::labelSettingsPreviewPixmap( settings, QSize( 24, 24 ), QString(), 1 ) );
for ( const QVariant &size : mAdditionalSizes )
{
QSize s = size.toSize();
icon.addPixmap( QgsPalLayerSettings::labelSettingsPreviewPixmap( settings, s, QString(), static_cast< int >( s.width() * ICON_PADDING_FACTOR ) ) );
}
mLabelSettingsIconCache.insert( name, icon );
return icon;
}

case QgsStyle::TagEntity:
case QgsStyle::SmartgroupEntity:
Expand Down Expand Up @@ -309,7 +337,7 @@ bool QgsStyleModel::setData( const QModelIndex &index, const QVariant &value, in
break;

case QgsStyle::LabelSettingsEntity:
name = mTextFormatNames.value( index.row() - mSymbolNames.size() - mRampNames.size() - mTextFormatNames.size() );
name = mLabelSettingsNames.value( index.row() - mSymbolNames.size() - mRampNames.size() - mTextFormatNames.size() );
break;

case QgsStyle::TagEntity:
Expand Down Expand Up @@ -412,7 +440,7 @@ int QgsStyleModel::rowCount( const QModelIndex &parent ) const
{
if ( !parent.isValid() )
{
return mSymbolNames.count() + mRampNames.count() + mTextFormatNames.count();
return mSymbolNames.count() + mRampNames.count() + mTextFormatNames.count() + mLabelSettingsNames.count();
}
return 0;
}
Expand Down Expand Up @@ -645,7 +673,7 @@ void QgsStyleModel::onLabelSettingsAdded( const QString &name )
if ( newNameIndex < 0 )
return; // shouldn't happen

beginInsertRows( QModelIndex(), newNameIndex + mSymbolNames.count() + mRampNames.count(), newNameIndex + mSymbolNames.count() + mRampNames.count() + mTextFormatNames.count() );
beginInsertRows( QModelIndex(), newNameIndex + mSymbolNames.count() + mRampNames.count() + mTextFormatNames.count(), newNameIndex + mSymbolNames.count() + mRampNames.count() + mTextFormatNames.count() );
mLabelSettingsNames = newLabelSettingsNames;
endInsertRows();
}
Expand All @@ -661,7 +689,7 @@ void QgsStyleModel::onLabelSettingsRemoved( const QString &name )
if ( oldNameIndex < 0 )
return; // shouldn't happen

beginRemoveRows( QModelIndex(), oldNameIndex + mSymbolNames.count() + mRampNames.count(), oldNameIndex + mSymbolNames.count() + mRampNames.count() + mTextFormatNames.count() );
beginRemoveRows( QModelIndex(), oldNameIndex + mSymbolNames.count() + mRampNames.count() + mTextFormatNames.count(), oldNameIndex + mSymbolNames.count() + mRampNames.count() + mTextFormatNames.count() );
mLabelSettingsNames = newLabelSettingsNames;
endRemoveRows();
}
Expand Down Expand Up @@ -696,7 +724,7 @@ void QgsStyleModel::onLabelSettingsRename( const QString &oldName, const QString
return;
}

beginMoveRows( QModelIndex(), oldNameIndex + mSymbolNames.count() + mRampNames.count(), oldNameIndex + mSymbolNames.count() + mRampNames.count() + mTextFormatNames.count(),
beginMoveRows( QModelIndex(), oldNameIndex + mSymbolNames.count() + mRampNames.count() + mTextFormatNames.count(), oldNameIndex + mSymbolNames.count() + mRampNames.count() + mTextFormatNames.count(),
QModelIndex(), ( newNameIndex > oldNameIndex ? newNameIndex + 1 : newNameIndex ) + mSymbolNames.count() + mRampNames.count() + mTextFormatNames.count() );
mLabelSettingsNames = newLabelSettingsNames;
endMoveRows();
Expand Down
2 changes: 2 additions & 0 deletions src/gui/CMakeLists.txt
Expand Up @@ -295,6 +295,7 @@ SET(QGIS_GUI_SRCS
qgshelp.cpp
qgsidentifymenu.cpp
qgskeyvaluewidget.cpp
qgslabelinggui.cpp
qgslistwidget.cpp
qgslegendfilterbutton.cpp
qgslimitedrandomcolorrampdialog.cpp
Expand Down Expand Up @@ -476,6 +477,7 @@ SET(QGIS_GUI_MOC_HDRS
qgshighlight.h
qgsidentifymenu.h
qgskeyvaluewidget.h
qgslabelinggui.h
qgslistwidget.h
qgslegendfilterbutton.h
qgslimitedrandomcolorrampdialog.h
Expand Down

0 comments on commit aa658e5

Please sign in to comment.