Skip to content
Permalink
Browse files

New widget QgsTextPreview for previewing all formatting for QgsTextRe…

…nderer

Switch the labeling gui to use this widget, which has the benefits:
- previews all label settings, including shadow and background
- previews at a specified scale, so that any sizes using map units
will be correct
  • Loading branch information
nyalldawson committed Oct 24, 2016
1 parent e3517c6 commit 0b88de2487ac6a5b141cdebca0ec5ff86ca6e48f
@@ -161,6 +161,7 @@
%Include qgstabwidget.sip
%Include qgstablewidgetitem.sip
%Include qgstextannotationitem.sip
%Include qgstextpreview.sip
%Include qgstrackedvectorlayertools.sip
%Include qgstreewidgetitem.sip
%Include qgsunitselectionwidget.sip
@@ -0,0 +1,66 @@
/** \class QgsTextPreview
* \ingroup gui
* A widget for previewing text formatting settings.
*
* QgsTextPreview provides a widget for previewing the appearance of text rendered
* using QgsTextRenderer. The preview includes all settings contained within
* a QgsTextFormat, including shadow, background and buffer.
*
* In order to preview the exact appearance of text which uses sizes in map units,
* the scale and map units must be set by calling setScale() and setMapUnits().
*
* @note Added in QGIS 3.0
*/

class QgsTextPreview : public QLabel
{
%TypeHeaderCode
#include <qgstextpreview.h>
%End
public:

/** Constructor for QgsTextPreview
* @param parent parent widget
*/
QgsTextPreview( QWidget* parent = nullptr );

void paintEvent( QPaintEvent* e );

/** Sets the text format for previewing in the widget.
* @param format text format
* @see format()
*/
void setFormat( const QgsTextFormat& format );

/** Returns the text format used for previewing text in the widget.
* @see setFormat()
*/
QgsTextFormat format() const;

/** Sets the scale to use for previewing format sizes in map units.
* @param scale preview map scale
* @see scale()
* @see setMapUnits()
*/
void setScale( double scale );

/** Returns the scale used for previewing format sizes in map units.
* @see setScale()
* @see mapUnits()
*/
double scale() const;

/** Sets the map unit type for previewing format sizes in map units.
* @param unit map units
* @see mapUnits()
* @see setScale()
*/
void setMapUnits( QgsUnitTypes::DistanceUnit unit );

/** Returns the map unit type used for previewing format sizes in map units.
* @see setMapUnits()
* @see scale()
*/
QgsUnitTypes::DistanceUnit mapUnits() const;

};
@@ -78,6 +78,10 @@ QgsLabelingGui::QgsLabelingGui( QgsVectorLayer* layer, QgsMapCanvas* mapCanvas,
{
setupUi( this );

mPreviewScaleComboBox->setMapCanvas( mMapCanvas );
mPreviewScaleComboBox->setShowCurrentScaleButton( true );
connect( mPreviewScaleComboBox, SIGNAL( scaleChanged( double ) ), this, SLOT( previewScaleChanged( double ) ) );

mFieldExpressionWidget->registerExpressionContextGenerator( this );

Q_FOREACH ( QgsUnitSelectionWidget* unitWidget, findChildren<QgsUnitSelectionWidget*>() )
@@ -485,6 +489,12 @@ QgsLabelingGui::QgsLabelingGui( QgsVectorLayer* layer, QgsMapCanvas* mapCanvas,

// set correct initial tab to match displayed setting page
whileBlocking( mOptionsTab )->setCurrentIndex( mLabelStackedWidget->currentIndex() );

if ( mMapCanvas )
{
lblFontPreview->setMapUnits( mMapCanvas->mapSettings().mapUnits() );
mPreviewScaleComboBox->setScale( 1.0 / mMapCanvas->mapSettings().scale() );
}
}

void QgsLabelingGui::setDockMode( bool enabled )
@@ -958,7 +968,10 @@ QgsPalLayerSettings QgsLabelingGui::layerSettings()
lyr.distInMapUnits = ( mLineDistanceUnitWidget->unit() == QgsUnitTypes::RenderMapUnits );
lyr.distMapUnitScale = mLineDistanceUnitWidget->getMapUnitScale();
lyr.offsetType = static_cast< QgsPalLayerSettings::OffsetType >( mOffsetTypeComboBox->currentData().toInt() );
lyr.quadOffset = ( QgsPalLayerSettings::QuadrantPosition )mQuadrantBtnGrp->checkedId();
if ( mQuadrantBtnGrp )
{
lyr.quadOffset = ( QgsPalLayerSettings::QuadrantPosition )mQuadrantBtnGrp->checkedId();
}
lyr.xOffset = mPointOffsetXSpinBox->value();
lyr.yOffset = mPointOffsetYSpinBox->value();
lyr.labelOffsetInMapUnits = ( mPointOffsetUnitWidget->unit() == QgsUnitTypes::RenderMapUnits );
@@ -1036,6 +1049,7 @@ QgsPalLayerSettings QgsLabelingGui::layerSettings()
QgsTextFormat format;
format.setColor( btnTextColor->color() );
format.setFont( mRefFont );
format.setSize( mFontSizeSpinBox->value() );
format.setNamedStyle( mFontStyleComboBox->currentText() );
format.setOpacity( 1.0 - mFontTranspSpinBox->value() / 100.0 );
format.setBlendMode( comboBlendMode->blendMode() );
@@ -1115,9 +1129,14 @@ QgsPalLayerSettings QgsLabelingGui::layerSettings()
lyr.leftDirectionSymbol = mDirectSymbLeftLineEdit->text();
lyr.rightDirectionSymbol = mDirectSymbRightLineEdit->text();
lyr.reverseDirectionSymbol = mDirectSymbRevChkBx->isChecked();
lyr.placeDirectionSymbol = ( QgsPalLayerSettings::DirectionSymbols )mDirectSymbBtnGrp->checkedId();

lyr.upsidedownLabels = ( QgsPalLayerSettings::UpsideDownLabels )mUpsidedownBtnGrp->checkedId();
if ( mDirectSymbBtnGrp )
{
lyr.placeDirectionSymbol = ( QgsPalLayerSettings::DirectionSymbols )mDirectSymbBtnGrp->checkedId();
}
if ( mUpsidedownBtnGrp )
{
lyr.upsidedownLabels = ( QgsPalLayerSettings::UpsideDownLabels )mUpsidedownBtnGrp->checkedId();
}

lyr.maxCurvedCharAngleIn = mMaxCharAngleInDSpinBox->value();
// lyr.maxCurvedCharAngleOut must be negative, but it is shown as positive spinbox in GUI
@@ -1590,78 +1609,12 @@ void QgsLabelingGui::updatePreview()
return;
}

QgsTextFormat format = layerSettings().format();

scrollPreview();
lblFontPreview->setFont( mRefFont );
QFont previewFont = lblFontPreview->font();
double fontSize = mFontSizeSpinBox->value();
double previewRatio = mPreviewSize / fontSize;
double bufferSize = 0.0;
lblFontPreview->setFormat( format );
QString grpboxtitle;
QString sampleTxt = tr( "Text/Buffer sample" );

if ( mFontSizeUnitWidget->getUnit() == 1 ) // map units
{
// TODO: maybe match current map zoom level instead?
previewFont.setPointSize( mPreviewSize );
mPreviewSizeSlider->setEnabled( true );
grpboxtitle = sampleTxt + tr( " @ %1 pts (using map units)" ).arg( mPreviewSize );

previewFont.setWordSpacing( previewRatio * mFontWordSpacingSpinBox->value() );
previewFont.setLetterSpacing( QFont::AbsoluteSpacing, previewRatio * mFontLetterSpacingSpinBox->value() );

if ( mBufferDrawChkBx->isChecked() )
{
if ( mBufferUnitWidget->unit() == QgsUnitTypes::RenderMapUnits )
{
bufferSize = previewRatio * spinBufferSize->value() / 3.527;
}
else // millimeters
{
grpboxtitle = sampleTxt + tr( " @ %1 pts (using map units, BUFFER IN MILLIMETERS)" ).arg( mPreviewSize );
bufferSize = spinBufferSize->value();
}
}
}
else // in points
{
if ( fontSize > 0 )
previewFont.setPointSize( fontSize );
mPreviewSizeSlider->setEnabled( false );
grpboxtitle = sampleTxt;

if ( mBufferDrawChkBx->isChecked() )
{
if ( mBufferUnitWidget->unit() == QgsUnitTypes::RenderMillimeters )
{
bufferSize = spinBufferSize->value();
}
else // map units
{
grpboxtitle = sampleTxt + tr( " (BUFFER NOT SHOWN, in map units)" );
}
}
}

lblFontPreview->setFont( previewFont );
groupBox_mPreview->setTitle( grpboxtitle );

QColor prevColor = btnTextColor->color();
prevColor.setAlphaF(( 100.0 - ( double )( mFontTranspSpinBox->value() ) ) / 100.0 );
lblFontPreview->setTextColor( prevColor );

bool bufferNoFill = false;
if ( mBufferDrawChkBx->isChecked() && bufferSize != 0.0 )
{
QColor buffColor = btnBufferColor->color();
buffColor.setAlphaF(( 100.0 - ( double )( mBufferTranspSpinBox->value() ) ) / 100.0 );

bufferNoFill = !mBufferTranspFillChbx->isChecked();
lblFontPreview->setBuffer( bufferSize, buffColor, mBufferJoinStyleComboBox->penJoinStyle(), bufferNoFill );
}
else
{
lblFontPreview->setBuffer( 0, Qt::white, Qt::BevelJoin, bufferNoFill );
}
}

void QgsLabelingGui::scrollPreview()
@@ -1813,12 +1766,6 @@ void QgsLabelingGui::populateFontStyleComboBox()
mFontStyleComboBox->setCurrentIndex( curIndx );
}

void QgsLabelingGui::on_mPreviewSizeSlider_valueChanged( int i )
{
mPreviewSize = i;
updatePreview();
}

void QgsLabelingGui::on_mFontSizeSpinBox_valueChanged( double d )
{
mRefFont.setPointSizeF( d );
@@ -2013,6 +1960,11 @@ void QgsLabelingGui::onSubstitutionsChanged( const QgsStringReplacementCollectio
emit widgetChanged();
}

void QgsLabelingGui::previewScaleChanged( double scale )
{
lblFontPreview->setScale( scale );
}

void QgsLabelingGui::updateSvgWidgets( const QString& svgPath )
{
if ( mShapeSVGPathLineEdit->text() != svgPath )
@@ -22,6 +22,7 @@
#include <QFontDatabase>
#include <ui_qgslabelingguibase.h>
#include "qgsstringutils.h"
#include "qgspallabeling.h"

class QgsVectorLayer;
class QgsMapCanvas;
@@ -67,7 +68,6 @@ class APP_EXPORT QgsLabelingGui : public QWidget, private Ui::QgsLabelingGuiBase
void updatePlacementWidgets();
void updateSvgWidgets( const QString& svgPath );

void on_mPreviewSizeSlider_valueChanged( int i );
void on_mFontSizeSpinBox_valueChanged( double d );
void on_mFontCapitalsComboBox_currentIndexChanged( int index );
void on_mFontFamilyCmbBx_currentFontChanged( const QFont& f );
@@ -150,6 +150,7 @@ class APP_EXPORT QgsLabelingGui : public QWidget, private Ui::QgsLabelingGuiBase
void on_mShapeSVGPathLineEdit_textChanged( const QString& text );
void updateLinePlacementOptions();
void onSubstitutionsChanged( const QgsStringReplacementCollection& substitutions );
void previewScaleChanged( double scale );
};

#endif
@@ -308,6 +308,7 @@ SET(QGIS_GUI_SRCS
qgstabwidget.cpp
qgstablewidgetitem.cpp
qgstextannotationitem.cpp
qgstextpreview.cpp
qgstrackedvectorlayertools.cpp
qgstreewidgetitem.cpp
qgsunitselectionwidget.cpp
@@ -461,6 +462,7 @@ SET(QGIS_GUI_MOC_HDRS
qgssublayersdialog.h
qgstablewidgetbase.h
qgstabwidget.h
qgstextpreview.h
qgstreewidgetitem.h
qgsunitselectionwidget.h
qgsuserinputdockwidget.h
@@ -0,0 +1,97 @@
/***************************************************************************
qgstextpreview.cpp
------------------
begin : October 2016
copyright : (C) 2016 by Nyall Dawson
email : nyall dot dawson at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#include "qgstextpreview.h"
#include <QDesktopWidget>
#include <QPainter>

QgsTextPreview::QgsTextPreview( QWidget* parent )
: QLabel( parent )
, mScale( -1 )
, mMapUnits( QgsUnitTypes::DistanceMeters )
{
// initially use a basic transform with no scale
QgsMapToPixel newCoordXForm;
newCoordXForm.setParameters( 1, 0, 0, 0, 0, 0 );
mContext.setMapToPixel( newCoordXForm );

mContext.setScaleFactor( QgsApplication::desktop()->logicalDpiX() / 25.4 );
mContext.setUseAdvancedEffects( true );
}


void QgsTextPreview::paintEvent( QPaintEvent *e )
{
Q_UNUSED( e );
QPainter p( this );

p.setRenderHint( QPainter::Antialiasing );

// slightly inset text
double xtrans = 0;
if ( mFormat.buffer().enabled() )
xtrans = QgsTextRenderer::scaleToPixelContext( mFormat.buffer().size(), mContext, mFormat.buffer().sizeUnit(), false, mFormat.buffer().sizeMapUnitScale() );
if ( mFormat.background().enabled() && mFormat.background().sizeType() != QgsTextBackgroundSettings::SizeFixed )
xtrans = qMax( xtrans, QgsTextRenderer::scaleToPixelContext( mFormat.background().size().width(), mContext, mFormat.background().sizeUnit(), false, mFormat.background().sizeMapUnitScale() ) );
xtrans += 4;

double ytrans = 0.0;
if ( mFormat.buffer().enabled() )
ytrans = qMax( ytrans, QgsTextRenderer::scaleToPixelContext( mFormat.buffer().size(), mContext, mFormat.buffer().sizeUnit(), false, mFormat.buffer().sizeMapUnitScale() ) );
if ( mFormat.background().enabled() )
ytrans = qMax( ytrans, QgsTextRenderer::scaleToPixelContext( mFormat.background().size().height(), mContext, mFormat.background().sizeUnit(), false, mFormat.background().sizeMapUnitScale() ) );
ytrans += 4;

QRectF textRect = rect();
textRect.setLeft( xtrans );
textRect.setWidth( textRect.width() - xtrans );
textRect.setTop( ytrans );
if ( textRect.height() > 300 )
textRect.setHeight( 300 );
if ( textRect.width() > 2000 )
textRect.setWidth( 2000 );

mContext.setPainter( &p );
QgsTextRenderer::drawText( textRect, 0 , QgsTextRenderer::AlignLeft, QStringList() << text(),
mContext, mFormat );
}

void QgsTextPreview::setFormat( const QgsTextFormat& format )
{
mFormat = format;
update();
}

void QgsTextPreview::updateContext()
{
if ( mScale >= 0 )
{
QgsMapToPixel newCoordXForm = QgsMapToPixel::fromScale( mScale, mMapUnits, QgsApplication::desktop()->logicalDpiX() );
mContext.setMapToPixel( newCoordXForm );
}
update();
}

void QgsTextPreview::setScale( double scale )
{
mScale = scale;
updateContext();
}

void QgsTextPreview::setMapUnits( QgsUnitTypes::DistanceUnit unit )
{
mMapUnits = unit;
updateContext();
}

0 comments on commit 0b88de2

Please sign in to comment.
You can’t perform that action at this time.