Skip to content

Commit 0b88de2

Browse files
committedOct 24, 2016
New widget QgsTextPreview for previewing all formatting for QgsTextRenderer
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
1 parent e3517c6 commit 0b88de2

File tree

8 files changed

+576
-382
lines changed

8 files changed

+576
-382
lines changed
 

‎python/gui/gui.sip

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@
161161
%Include qgstabwidget.sip
162162
%Include qgstablewidgetitem.sip
163163
%Include qgstextannotationitem.sip
164+
%Include qgstextpreview.sip
164165
%Include qgstrackedvectorlayertools.sip
165166
%Include qgstreewidgetitem.sip
166167
%Include qgsunitselectionwidget.sip

‎python/gui/qgstextpreview.sip

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/** \class QgsTextPreview
2+
* \ingroup gui
3+
* A widget for previewing text formatting settings.
4+
*
5+
* QgsTextPreview provides a widget for previewing the appearance of text rendered
6+
* using QgsTextRenderer. The preview includes all settings contained within
7+
* a QgsTextFormat, including shadow, background and buffer.
8+
*
9+
* In order to preview the exact appearance of text which uses sizes in map units,
10+
* the scale and map units must be set by calling setScale() and setMapUnits().
11+
*
12+
* @note Added in QGIS 3.0
13+
*/
14+
15+
class QgsTextPreview : public QLabel
16+
{
17+
%TypeHeaderCode
18+
#include <qgstextpreview.h>
19+
%End
20+
public:
21+
22+
/** Constructor for QgsTextPreview
23+
* @param parent parent widget
24+
*/
25+
QgsTextPreview( QWidget* parent = nullptr );
26+
27+
void paintEvent( QPaintEvent* e );
28+
29+
/** Sets the text format for previewing in the widget.
30+
* @param format text format
31+
* @see format()
32+
*/
33+
void setFormat( const QgsTextFormat& format );
34+
35+
/** Returns the text format used for previewing text in the widget.
36+
* @see setFormat()
37+
*/
38+
QgsTextFormat format() const;
39+
40+
/** Sets the scale to use for previewing format sizes in map units.
41+
* @param scale preview map scale
42+
* @see scale()
43+
* @see setMapUnits()
44+
*/
45+
void setScale( double scale );
46+
47+
/** Returns the scale used for previewing format sizes in map units.
48+
* @see setScale()
49+
* @see mapUnits()
50+
*/
51+
double scale() const;
52+
53+
/** Sets the map unit type for previewing format sizes in map units.
54+
* @param unit map units
55+
* @see mapUnits()
56+
* @see setScale()
57+
*/
58+
void setMapUnits( QgsUnitTypes::DistanceUnit unit );
59+
60+
/** Returns the map unit type used for previewing format sizes in map units.
61+
* @see setMapUnits()
62+
* @see scale()
63+
*/
64+
QgsUnitTypes::DistanceUnit mapUnits() const;
65+
66+
};

‎src/app/qgslabelinggui.cpp

Lines changed: 31 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@ QgsLabelingGui::QgsLabelingGui( QgsVectorLayer* layer, QgsMapCanvas* mapCanvas,
7878
{
7979
setupUi( this );
8080

81+
mPreviewScaleComboBox->setMapCanvas( mMapCanvas );
82+
mPreviewScaleComboBox->setShowCurrentScaleButton( true );
83+
connect( mPreviewScaleComboBox, SIGNAL( scaleChanged( double ) ), this, SLOT( previewScaleChanged( double ) ) );
84+
8185
mFieldExpressionWidget->registerExpressionContextGenerator( this );
8286

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

486490
// set correct initial tab to match displayed setting page
487491
whileBlocking( mOptionsTab )->setCurrentIndex( mLabelStackedWidget->currentIndex() );
492+
493+
if ( mMapCanvas )
494+
{
495+
lblFontPreview->setMapUnits( mMapCanvas->mapSettings().mapUnits() );
496+
mPreviewScaleComboBox->setScale( 1.0 / mMapCanvas->mapSettings().scale() );
497+
}
488498
}
489499

490500
void QgsLabelingGui::setDockMode( bool enabled )
@@ -958,7 +968,10 @@ QgsPalLayerSettings QgsLabelingGui::layerSettings()
958968
lyr.distInMapUnits = ( mLineDistanceUnitWidget->unit() == QgsUnitTypes::RenderMapUnits );
959969
lyr.distMapUnitScale = mLineDistanceUnitWidget->getMapUnitScale();
960970
lyr.offsetType = static_cast< QgsPalLayerSettings::OffsetType >( mOffsetTypeComboBox->currentData().toInt() );
961-
lyr.quadOffset = ( QgsPalLayerSettings::QuadrantPosition )mQuadrantBtnGrp->checkedId();
971+
if ( mQuadrantBtnGrp )
972+
{
973+
lyr.quadOffset = ( QgsPalLayerSettings::QuadrantPosition )mQuadrantBtnGrp->checkedId();
974+
}
962975
lyr.xOffset = mPointOffsetXSpinBox->value();
963976
lyr.yOffset = mPointOffsetYSpinBox->value();
964977
lyr.labelOffsetInMapUnits = ( mPointOffsetUnitWidget->unit() == QgsUnitTypes::RenderMapUnits );
@@ -1036,6 +1049,7 @@ QgsPalLayerSettings QgsLabelingGui::layerSettings()
10361049
QgsTextFormat format;
10371050
format.setColor( btnTextColor->color() );
10381051
format.setFont( mRefFont );
1052+
format.setSize( mFontSizeSpinBox->value() );
10391053
format.setNamedStyle( mFontStyleComboBox->currentText() );
10401054
format.setOpacity( 1.0 - mFontTranspSpinBox->value() / 100.0 );
10411055
format.setBlendMode( comboBlendMode->blendMode() );
@@ -1115,9 +1129,14 @@ QgsPalLayerSettings QgsLabelingGui::layerSettings()
11151129
lyr.leftDirectionSymbol = mDirectSymbLeftLineEdit->text();
11161130
lyr.rightDirectionSymbol = mDirectSymbRightLineEdit->text();
11171131
lyr.reverseDirectionSymbol = mDirectSymbRevChkBx->isChecked();
1118-
lyr.placeDirectionSymbol = ( QgsPalLayerSettings::DirectionSymbols )mDirectSymbBtnGrp->checkedId();
1119-
1120-
lyr.upsidedownLabels = ( QgsPalLayerSettings::UpsideDownLabels )mUpsidedownBtnGrp->checkedId();
1132+
if ( mDirectSymbBtnGrp )
1133+
{
1134+
lyr.placeDirectionSymbol = ( QgsPalLayerSettings::DirectionSymbols )mDirectSymbBtnGrp->checkedId();
1135+
}
1136+
if ( mUpsidedownBtnGrp )
1137+
{
1138+
lyr.upsidedownLabels = ( QgsPalLayerSettings::UpsideDownLabels )mUpsidedownBtnGrp->checkedId();
1139+
}
11211140

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

1612+
QgsTextFormat format = layerSettings().format();
1613+
15931614
scrollPreview();
1594-
lblFontPreview->setFont( mRefFont );
1595-
QFont previewFont = lblFontPreview->font();
1596-
double fontSize = mFontSizeSpinBox->value();
1597-
double previewRatio = mPreviewSize / fontSize;
1598-
double bufferSize = 0.0;
1615+
lblFontPreview->setFormat( format );
15991616
QString grpboxtitle;
1600-
QString sampleTxt = tr( "Text/Buffer sample" );
1601-
1602-
if ( mFontSizeUnitWidget->getUnit() == 1 ) // map units
1603-
{
1604-
// TODO: maybe match current map zoom level instead?
1605-
previewFont.setPointSize( mPreviewSize );
1606-
mPreviewSizeSlider->setEnabled( true );
1607-
grpboxtitle = sampleTxt + tr( " @ %1 pts (using map units)" ).arg( mPreviewSize );
1608-
1609-
previewFont.setWordSpacing( previewRatio * mFontWordSpacingSpinBox->value() );
1610-
previewFont.setLetterSpacing( QFont::AbsoluteSpacing, previewRatio * mFontLetterSpacingSpinBox->value() );
1611-
1612-
if ( mBufferDrawChkBx->isChecked() )
1613-
{
1614-
if ( mBufferUnitWidget->unit() == QgsUnitTypes::RenderMapUnits )
1615-
{
1616-
bufferSize = previewRatio * spinBufferSize->value() / 3.527;
1617-
}
1618-
else // millimeters
1619-
{
1620-
grpboxtitle = sampleTxt + tr( " @ %1 pts (using map units, BUFFER IN MILLIMETERS)" ).arg( mPreviewSize );
1621-
bufferSize = spinBufferSize->value();
1622-
}
1623-
}
1624-
}
1625-
else // in points
1626-
{
1627-
if ( fontSize > 0 )
1628-
previewFont.setPointSize( fontSize );
1629-
mPreviewSizeSlider->setEnabled( false );
1630-
grpboxtitle = sampleTxt;
1631-
1632-
if ( mBufferDrawChkBx->isChecked() )
1633-
{
1634-
if ( mBufferUnitWidget->unit() == QgsUnitTypes::RenderMillimeters )
1635-
{
1636-
bufferSize = spinBufferSize->value();
1637-
}
1638-
else // map units
1639-
{
1640-
grpboxtitle = sampleTxt + tr( " (BUFFER NOT SHOWN, in map units)" );
1641-
}
1642-
}
1643-
}
1644-
1645-
lblFontPreview->setFont( previewFont );
16461617
groupBox_mPreview->setTitle( grpboxtitle );
1647-
1648-
QColor prevColor = btnTextColor->color();
1649-
prevColor.setAlphaF(( 100.0 - ( double )( mFontTranspSpinBox->value() ) ) / 100.0 );
1650-
lblFontPreview->setTextColor( prevColor );
1651-
1652-
bool bufferNoFill = false;
1653-
if ( mBufferDrawChkBx->isChecked() && bufferSize != 0.0 )
1654-
{
1655-
QColor buffColor = btnBufferColor->color();
1656-
buffColor.setAlphaF(( 100.0 - ( double )( mBufferTranspSpinBox->value() ) ) / 100.0 );
1657-
1658-
bufferNoFill = !mBufferTranspFillChbx->isChecked();
1659-
lblFontPreview->setBuffer( bufferSize, buffColor, mBufferJoinStyleComboBox->penJoinStyle(), bufferNoFill );
1660-
}
1661-
else
1662-
{
1663-
lblFontPreview->setBuffer( 0, Qt::white, Qt::BevelJoin, bufferNoFill );
1664-
}
16651618
}
16661619

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

1816-
void QgsLabelingGui::on_mPreviewSizeSlider_valueChanged( int i )
1817-
{
1818-
mPreviewSize = i;
1819-
updatePreview();
1820-
}
1821-
18221769
void QgsLabelingGui::on_mFontSizeSpinBox_valueChanged( double d )
18231770
{
18241771
mRefFont.setPointSizeF( d );
@@ -2013,6 +1960,11 @@ void QgsLabelingGui::onSubstitutionsChanged( const QgsStringReplacementCollectio
20131960
emit widgetChanged();
20141961
}
20151962

1963+
void QgsLabelingGui::previewScaleChanged( double scale )
1964+
{
1965+
lblFontPreview->setScale( scale );
1966+
}
1967+
20161968
void QgsLabelingGui::updateSvgWidgets( const QString& svgPath )
20171969
{
20181970
if ( mShapeSVGPathLineEdit->text() != svgPath )

‎src/app/qgslabelinggui.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <QFontDatabase>
2323
#include <ui_qgslabelingguibase.h>
2424
#include "qgsstringutils.h"
25+
#include "qgspallabeling.h"
2526

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

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

155156
#endif

‎src/gui/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,7 @@ SET(QGIS_GUI_SRCS
308308
qgstabwidget.cpp
309309
qgstablewidgetitem.cpp
310310
qgstextannotationitem.cpp
311+
qgstextpreview.cpp
311312
qgstrackedvectorlayertools.cpp
312313
qgstreewidgetitem.cpp
313314
qgsunitselectionwidget.cpp
@@ -461,6 +462,7 @@ SET(QGIS_GUI_MOC_HDRS
461462
qgssublayersdialog.h
462463
qgstablewidgetbase.h
463464
qgstabwidget.h
465+
qgstextpreview.h
464466
qgstreewidgetitem.h
465467
qgsunitselectionwidget.h
466468
qgsuserinputdockwidget.h

‎src/gui/qgstextpreview.cpp

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/***************************************************************************
2+
qgstextpreview.cpp
3+
------------------
4+
begin : October 2016
5+
copyright : (C) 2016 by Nyall Dawson
6+
email : nyall dot dawson at gmail dot com
7+
***************************************************************************
8+
* *
9+
* This program is free software; you can redistribute it and/or modify *
10+
* it under the terms of the GNU General Public License as published by *
11+
* the Free Software Foundation; either version 2 of the License, or *
12+
* (at your option) any later version. *
13+
* *
14+
***************************************************************************/
15+
16+
#include "qgstextpreview.h"
17+
#include <QDesktopWidget>
18+
#include <QPainter>
19+
20+
QgsTextPreview::QgsTextPreview( QWidget* parent )
21+
: QLabel( parent )
22+
, mScale( -1 )
23+
, mMapUnits( QgsUnitTypes::DistanceMeters )
24+
{
25+
// initially use a basic transform with no scale
26+
QgsMapToPixel newCoordXForm;
27+
newCoordXForm.setParameters( 1, 0, 0, 0, 0, 0 );
28+
mContext.setMapToPixel( newCoordXForm );
29+
30+
mContext.setScaleFactor( QgsApplication::desktop()->logicalDpiX() / 25.4 );
31+
mContext.setUseAdvancedEffects( true );
32+
}
33+
34+
35+
void QgsTextPreview::paintEvent( QPaintEvent *e )
36+
{
37+
Q_UNUSED( e );
38+
QPainter p( this );
39+
40+
p.setRenderHint( QPainter::Antialiasing );
41+
42+
// slightly inset text
43+
double xtrans = 0;
44+
if ( mFormat.buffer().enabled() )
45+
xtrans = QgsTextRenderer::scaleToPixelContext( mFormat.buffer().size(), mContext, mFormat.buffer().sizeUnit(), false, mFormat.buffer().sizeMapUnitScale() );
46+
if ( mFormat.background().enabled() && mFormat.background().sizeType() != QgsTextBackgroundSettings::SizeFixed )
47+
xtrans = qMax( xtrans, QgsTextRenderer::scaleToPixelContext( mFormat.background().size().width(), mContext, mFormat.background().sizeUnit(), false, mFormat.background().sizeMapUnitScale() ) );
48+
xtrans += 4;
49+
50+
double ytrans = 0.0;
51+
if ( mFormat.buffer().enabled() )
52+
ytrans = qMax( ytrans, QgsTextRenderer::scaleToPixelContext( mFormat.buffer().size(), mContext, mFormat.buffer().sizeUnit(), false, mFormat.buffer().sizeMapUnitScale() ) );
53+
if ( mFormat.background().enabled() )
54+
ytrans = qMax( ytrans, QgsTextRenderer::scaleToPixelContext( mFormat.background().size().height(), mContext, mFormat.background().sizeUnit(), false, mFormat.background().sizeMapUnitScale() ) );
55+
ytrans += 4;
56+
57+
QRectF textRect = rect();
58+
textRect.setLeft( xtrans );
59+
textRect.setWidth( textRect.width() - xtrans );
60+
textRect.setTop( ytrans );
61+
if ( textRect.height() > 300 )
62+
textRect.setHeight( 300 );
63+
if ( textRect.width() > 2000 )
64+
textRect.setWidth( 2000 );
65+
66+
mContext.setPainter( &p );
67+
QgsTextRenderer::drawText( textRect, 0 , QgsTextRenderer::AlignLeft, QStringList() << text(),
68+
mContext, mFormat );
69+
}
70+
71+
void QgsTextPreview::setFormat( const QgsTextFormat& format )
72+
{
73+
mFormat = format;
74+
update();
75+
}
76+
77+
void QgsTextPreview::updateContext()
78+
{
79+
if ( mScale >= 0 )
80+
{
81+
QgsMapToPixel newCoordXForm = QgsMapToPixel::fromScale( mScale, mMapUnits, QgsApplication::desktop()->logicalDpiX() );
82+
mContext.setMapToPixel( newCoordXForm );
83+
}
84+
update();
85+
}
86+
87+
void QgsTextPreview::setScale( double scale )
88+
{
89+
mScale = scale;
90+
updateContext();
91+
}
92+
93+
void QgsTextPreview::setMapUnits( QgsUnitTypes::DistanceUnit unit )
94+
{
95+
mMapUnits = unit;
96+
updateContext();
97+
}

‎src/gui/qgstextpreview.h

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/***************************************************************************
2+
qgstextpreview.h
3+
----------------
4+
begin : October 2016
5+
copyright : (C) 2016 by Nyall Dawson
6+
email : nyall dot dawson at gmail dot com
7+
***************************************************************************
8+
* *
9+
* This program is free software; you can redistribute it and/or modify *
10+
* it under the terms of the GNU General Public License as published by *
11+
* the Free Software Foundation; either version 2 of the License, or *
12+
* (at your option) any later version. *
13+
* *
14+
***************************************************************************/
15+
#ifndef QGSTEXTPREVIEW_H
16+
#define QGSTEXTPREVIEW_H
17+
18+
#include "qgstextrenderer.h"
19+
20+
#include <QLabel>
21+
22+
/** \class QgsTextPreview
23+
* \ingroup gui
24+
* A widget for previewing text formatting settings.
25+
*
26+
* QgsTextPreview provides a widget for previewing the appearance of text rendered
27+
* using QgsTextRenderer. The preview includes all settings contained within
28+
* a QgsTextFormat, including shadow, background and buffer.
29+
*
30+
* In order to preview the exact appearance of text which uses sizes in map units,
31+
* the scale and map units must be set by calling setScale() and setMapUnits().
32+
*
33+
* @note Added in QGIS 3.0
34+
*/
35+
36+
class GUI_EXPORT QgsTextPreview : public QLabel
37+
{
38+
Q_OBJECT
39+
40+
Q_PROPERTY( QgsTextFormat format READ format WRITE setFormat )
41+
Q_PROPERTY( double scale READ scale WRITE setScale )
42+
Q_PROPERTY( QgsUnitTypes::DistanceUnit mapUnits READ mapUnits WRITE setMapUnits )
43+
44+
public:
45+
46+
/** Constructor for QgsTextPreview
47+
* @param parent parent widget
48+
*/
49+
QgsTextPreview( QWidget* parent = nullptr );
50+
51+
void paintEvent( QPaintEvent* e ) override;
52+
53+
/** Sets the text format for previewing in the widget.
54+
* @param format text format
55+
* @see format()
56+
*/
57+
void setFormat( const QgsTextFormat& format );
58+
59+
/** Returns the text format used for previewing text in the widget.
60+
* @see setFormat()
61+
*/
62+
QgsTextFormat format() const { return mFormat; }
63+
64+
/** Sets the scale to use for previewing format sizes in map units.
65+
* @param scale preview map scale
66+
* @see scale()
67+
* @see setMapUnits()
68+
*/
69+
void setScale( double scale );
70+
71+
/** Returns the scale used for previewing format sizes in map units.
72+
* @see setScale()
73+
* @see mapUnits()
74+
*/
75+
double scale() const { return mScale; }
76+
77+
/** Sets the map unit type for previewing format sizes in map units.
78+
* @param unit map units
79+
* @see mapUnits()
80+
* @see setScale()
81+
*/
82+
void setMapUnits( QgsUnitTypes::DistanceUnit unit );
83+
84+
/** Returns the map unit type used for previewing format sizes in map units.
85+
* @see setMapUnits()
86+
* @see scale()
87+
*/
88+
QgsUnitTypes::DistanceUnit mapUnits() const { return mMapUnits; }
89+
90+
private:
91+
QgsTextFormat mFormat;
92+
QgsRenderContext mContext;
93+
double mScale;
94+
QgsUnitTypes::DistanceUnit mMapUnits;
95+
void updateContext();
96+
};
97+
98+
#endif // QGSTEXTPREVIEW_H

‎src/ui/qgslabelingguibase.ui

Lines changed: 279 additions & 302 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)
Please sign in to comment.