Skip to content

Commit

Permalink
[needs-docs] Upgrade project level setting for Label as Outlines/text…
Browse files Browse the repository at this point in the history
… setting to use newer API

And replace labeling engine dialog "Draw text as outlines" checkbox with a combobox
presenting the choice of always rendering as outlines OR text.

(This will allow us to easily add additional methods in future, e.g. potentially
a "Render as text wherever possible" setting, for defaulting to text objects
whenever it doesn't impact the rendering quality to do so)
  • Loading branch information
nyalldawson committed Dec 11, 2018
1 parent 12b3e15 commit 7ed4218
Show file tree
Hide file tree
Showing 10 changed files with 196 additions and 35 deletions.
21 changes: 20 additions & 1 deletion python/core/auto_generated/qgslabelingenginesettings.sip.in
Expand Up @@ -8,7 +8,6 @@




class QgsLabelingEngineSettings
{
%Docstring
Expand All @@ -25,6 +24,7 @@ Stores global configuration for labeling engine
{
UseAllLabels,
UsePartialCandidates,
// TODO QGIS 4.0: remove
RenderOutlineLabels,
DrawLabelRectOnly,
DrawCandidates,
Expand Down Expand Up @@ -92,6 +92,25 @@ Read configuration of the labeling engine from a project
Write configuration of the labeling engine to a project
%End


QgsRenderContext::TextRenderFormat defaultTextRenderFormat() const;
%Docstring
Returns the default text rendering format for the labels.

.. seealso:: :py:func:`setDefaultTextRenderFormat`

.. versionadded:: 3.4.3
%End

void setDefaultTextRenderFormat( QgsRenderContext::TextRenderFormat format );
%Docstring
Sets the default text rendering ``format`` for the labels.

.. seealso:: :py:func:`defaultTextRenderFormat`

.. versionadded:: 3.4.3
%End

};

QFlags<QgsLabelingEngineSettings::Flag> operator|(QgsLabelingEngineSettings::Flag f1, QFlags<QgsLabelingEngineSettings::Flag> f2);
Expand Down
19 changes: 17 additions & 2 deletions python/core/auto_generated/qgsmapsettings.sip.in
Expand Up @@ -296,6 +296,11 @@ Returns the text render format, which dictates how text is rendered (e.g. as pat
%Docstring
Sets the text render ``format``, which dictates how text is rendered (e.g. as paths or real text objects).

.. warning::

Calling the setLabelingEngineSettings() method will reset the text render format to match the default
text render format from the label engine settings.

.. seealso:: :py:func:`textRenderFormat`

.. versionadded:: 3.4.3
Expand Down Expand Up @@ -504,14 +509,24 @@ Gets segmentation tolerance type (maximum angle or maximum difference between cu

void setLabelingEngineSettings( const QgsLabelingEngineSettings &settings );
%Docstring
Sets global configuration of the labeling engine
Sets the global configuration of the labeling engine.

.. note::

Calling this method will reset the textRenderFormat() to match the default
text render format from the label engine ``settings``.

.. seealso:: :py:func:`labelingEngineSettings`


.. versionadded:: 3.0
%End

const QgsLabelingEngineSettings &labelingEngineSettings() const;
%Docstring
Returns global configuration of the labeling engine
Returns the global configuration of the labeling engine.

.. seealso:: :py:func:`setLabelingEngineSettings`

.. versionadded:: 3.0
%End
Expand Down
12 changes: 8 additions & 4 deletions src/app/qgslabelengineconfigdialog.cpp
Expand Up @@ -36,6 +36,9 @@ QgsLabelEngineConfigDialog::QgsLabelEngineConfigDialog( QWidget *parent )
// search method
cboSearchMethod->setCurrentIndex( engineSettings.searchMethod() );

mTextRenderFormatComboBox->addItem( tr( "Always Render Labels as Paths (Recommended)" ), QgsRenderContext::TextFormatAlwaysOutlines );
mTextRenderFormatComboBox->addItem( tr( "Always Render Labels as Text" ), QgsRenderContext::TextFormatAlwaysText );

// candidate numbers
int candPoint, candLine, candPolygon;
engineSettings.numCandidatePositions( candPoint, candLine, candPolygon );
Expand All @@ -47,9 +50,9 @@ QgsLabelEngineConfigDialog::QgsLabelEngineConfigDialog( QWidget *parent )
chkShowAllLabels->setChecked( engineSettings.testFlag( QgsLabelingEngineSettings::UseAllLabels ) );

chkShowPartialsLabels->setChecked( engineSettings.testFlag( QgsLabelingEngineSettings::UsePartialCandidates ) );
mDrawOutlinesChkBox->setChecked( engineSettings.testFlag( QgsLabelingEngineSettings::RenderOutlineLabels ) );
}

mTextRenderFormatComboBox->setCurrentIndex( mTextRenderFormatComboBox->findData( engineSettings.defaultTextRenderFormat() ) );
}

void QgsLabelEngineConfigDialog::onOK()
{
Expand All @@ -63,7 +66,8 @@ void QgsLabelEngineConfigDialog::onOK()
engineSettings.setFlag( QgsLabelingEngineSettings::DrawCandidates, chkShowCandidates->isChecked() );
engineSettings.setFlag( QgsLabelingEngineSettings::UseAllLabels, chkShowAllLabels->isChecked() );
engineSettings.setFlag( QgsLabelingEngineSettings::UsePartialCandidates, chkShowPartialsLabels->isChecked() );
engineSettings.setFlag( QgsLabelingEngineSettings::RenderOutlineLabels, mDrawOutlinesChkBox->isChecked() );

engineSettings.setDefaultTextRenderFormat( static_cast< QgsRenderContext::TextRenderFormat >( mTextRenderFormatComboBox->currentData().toInt() ) );

QgsProject::instance()->setLabelingEngineSettings( engineSettings );

Expand All @@ -80,7 +84,7 @@ void QgsLabelEngineConfigDialog::setDefaults()
chkShowCandidates->setChecked( false );
chkShowAllLabels->setChecked( false );
chkShowPartialsLabels->setChecked( p.getShowPartial() );
mDrawOutlinesChkBox->setChecked( true );
mTextRenderFormatComboBox->setCurrentIndex( mTextRenderFormatComboBox->findData( QgsRenderContext::TextFormatAlwaysOutlines ) );
}

void QgsLabelEngineConfigDialog::showHelp()
Expand Down
1 change: 1 addition & 0 deletions src/core/layout/qgslayoutitemmap.cpp
Expand Up @@ -1118,6 +1118,7 @@ QgsMapSettings QgsLayoutItemMap::mapSettings( const QgsRectangle &extent, QSizeF
jobMapSettings.setPathResolver( mLayout->project()->pathResolver() );

jobMapSettings.setLabelingEngineSettings( mLayout->project()->labelingEngineSettings() );
// override the default text render format inherited from the labeling engine settings using the layout's render context setting
jobMapSettings.setTextRenderFormat( mLayout->renderContext().textRenderFormat() );

return jobMapSettings;
Expand Down
17 changes: 14 additions & 3 deletions src/core/qgslabelingenginesettings.cpp
Expand Up @@ -19,7 +19,7 @@


QgsLabelingEngineSettings::QgsLabelingEngineSettings()
: mFlags( RenderOutlineLabels | UsePartialCandidates )
: mFlags( UsePartialCandidates )
{
}

Expand All @@ -41,7 +41,15 @@ void QgsLabelingEngineSettings::readSettingsFromProject( QgsProject *prj )
if ( prj->readBoolEntry( QStringLiteral( "PAL" ), QStringLiteral( "/DrawRectOnly" ), false, &saved ) ) mFlags |= DrawLabelRectOnly;
if ( prj->readBoolEntry( QStringLiteral( "PAL" ), QStringLiteral( "/ShowingAllLabels" ), false, &saved ) ) mFlags |= UseAllLabels;
if ( prj->readBoolEntry( QStringLiteral( "PAL" ), QStringLiteral( "/ShowingPartialsLabels" ), true, &saved ) ) mFlags |= UsePartialCandidates;
if ( prj->readBoolEntry( QStringLiteral( "PAL" ), QStringLiteral( "/DrawOutlineLabels" ), true, &saved ) ) mFlags |= RenderOutlineLabels;

mDefaultTextRenderFormat = QgsRenderContext::TextFormatAlwaysOutlines;
// if users have disabled the older PAL "DrawOutlineLabels" setting, respect that
if ( !prj->readBoolEntry( QStringLiteral( "PAL" ), QStringLiteral( "/DrawOutlineLabels" ), true ) )
mDefaultTextRenderFormat = QgsRenderContext::TextFormatAlwaysText;
// otherwise, prefer the new setting
const int projectTextFormat = prj->readNumEntry( QStringLiteral( "PAL" ), QStringLiteral( "/TextFormat" ), -1 );
if ( projectTextFormat >= 0 )
mDefaultTextRenderFormat = static_cast< QgsRenderContext::TextRenderFormat >( projectTextFormat );
}

void QgsLabelingEngineSettings::writeSettingsToProject( QgsProject *project )
Expand All @@ -55,5 +63,8 @@ void QgsLabelingEngineSettings::writeSettingsToProject( QgsProject *project )
project->writeEntry( QStringLiteral( "PAL" ), QStringLiteral( "/DrawRectOnly" ), mFlags.testFlag( DrawLabelRectOnly ) );
project->writeEntry( QStringLiteral( "PAL" ), QStringLiteral( "/ShowingAllLabels" ), mFlags.testFlag( UseAllLabels ) );
project->writeEntry( QStringLiteral( "PAL" ), QStringLiteral( "/ShowingPartialsLabels" ), mFlags.testFlag( UsePartialCandidates ) );
project->writeEntry( QStringLiteral( "PAL" ), QStringLiteral( "/DrawOutlineLabels" ), mFlags.testFlag( RenderOutlineLabels ) );

project->writeEntry( QStringLiteral( "PAL" ), QStringLiteral( "/TextFormat" ), static_cast< int >( mDefaultTextRenderFormat ) );
}


33 changes: 31 additions & 2 deletions src/core/qgslabelingenginesettings.h
Expand Up @@ -16,7 +16,7 @@
#define QGSLABELINGENGINESETTINGS_H

#include "qgis_core.h"

#include "qgsrendercontext.h"
#include <QFlags>

class QgsProject;
Expand All @@ -34,7 +34,8 @@ class CORE_EXPORT QgsLabelingEngineSettings
{
UseAllLabels = 1 << 1, //!< Whether to draw all labels even if there would be collisions
UsePartialCandidates = 1 << 2, //!< Whether to use also label candidates that are partially outside of the map view
RenderOutlineLabels = 1 << 3, //!< Whether to render labels as text or outlines
// TODO QGIS 4.0: remove
RenderOutlineLabels = 1 << 3, //!< Whether to render labels as text or outlines. Deprecated and of QGIS 3.4.3 - use defaultTextRenderFormat() instead.
DrawLabelRectOnly = 1 << 4, //!< Whether to only draw the label rect and not the actual label text (used for unit tests)
DrawCandidates = 1 << 5, //!< Whether to draw rectangles of generated candidates (good for debugging)
};
Expand Down Expand Up @@ -82,6 +83,32 @@ class CORE_EXPORT QgsLabelingEngineSettings
//! Write configuration of the labeling engine to a project
void writeSettingsToProject( QgsProject *project );

// TODO QGIS 4.0: In reality the text render format settings don't only apply to labels, but also
// ANY text rendered using QgsTextRenderer (including some non-label text items in layouts).
// These methods should possibly be moved out of here and into the general QgsProject settings.

/**
* Returns the default text rendering format for the labels.
*
* \see setDefaultTextRenderFormat()
* \since QGIS 3.4.3
*/
QgsRenderContext::TextRenderFormat defaultTextRenderFormat() const
{
return mDefaultTextRenderFormat;
}

/**
* Sets the default text rendering \a format for the labels.
*
* \see defaultTextRenderFormat()
* \since QGIS 3.4.3
*/
void setDefaultTextRenderFormat( QgsRenderContext::TextRenderFormat format )
{
mDefaultTextRenderFormat = format;
}

private:
//! Flags
Flags mFlags;
Expand All @@ -90,6 +117,8 @@ class CORE_EXPORT QgsLabelingEngineSettings
//! Number of candedate positions that will be generated for features
int mCandPoint = 16, mCandLine = 50, mCandPolygon = 30;

QgsRenderContext::TextRenderFormat mDefaultTextRenderFormat = QgsRenderContext::TextFormatAlwaysOutlines;

};

Q_DECLARE_OPERATORS_FOR_FLAGS( QgsLabelingEngineSettings::Flags )
Expand Down
25 changes: 22 additions & 3 deletions src/core/qgsmapsettings.h
Expand Up @@ -267,12 +267,18 @@ class CORE_EXPORT QgsMapSettings
/**
* Sets the text render \a format, which dictates how text is rendered (e.g. as paths or real text objects).
*
* \warning Calling the setLabelingEngineSettings() method will reset the text render format to match the default
* text render format from the label engine settings.
*
* \see textRenderFormat()
* \since QGIS 3.4.3
*/
void setTextRenderFormat( QgsRenderContext::TextRenderFormat format )
{
mTextRenderFormat = format;
// ensure labeling engine setting is also kept in sync, just in case anyone accesses QgsMapSettings::labelingEngineSettings().defaultTextRenderFormat()
// instead of correctly calling QgsMapSettings::textRenderFormat(). It can't hurt to be consistent!
mLabelingEngineSettings.setDefaultTextRenderFormat( format );
}

//! sets format of internal QImage
Expand Down Expand Up @@ -433,13 +439,26 @@ class CORE_EXPORT QgsMapSettings
QgsAbstractGeometry::SegmentationToleranceType segmentationToleranceType() const { return mSegmentationToleranceType; }

/**
* Sets global configuration of the labeling engine
* Sets the global configuration of the labeling engine.
*
* \note Calling this method will reset the textRenderFormat() to match the default
* text render format from the label engine \a settings.
*
* \see labelingEngineSettings()
*
* \since QGIS 3.0
*/
void setLabelingEngineSettings( const QgsLabelingEngineSettings &settings ) { mLabelingEngineSettings = settings; }
void setLabelingEngineSettings( const QgsLabelingEngineSettings &settings )
{
mLabelingEngineSettings = settings;
mTextRenderFormat = settings.defaultTextRenderFormat();
}

/**
* Returns global configuration of the labeling engine
* Returns the global configuration of the labeling engine.
*
* \see setLabelingEngineSettings()
*
* \since QGIS 3.0
*/
const QgsLabelingEngineSettings &labelingEngineSettings() const { return mLabelingEngineSettings; }
Expand Down
39 changes: 19 additions & 20 deletions src/ui/qgslabelengineconfigdialog.ui
Expand Up @@ -205,18 +205,25 @@
</layout>
</item>
<item>
<layout class="QGridLayout" name="gridLayout_2">
<property name="verticalSpacing">
<number>6</number>
</property>
<item row="3" column="0">
<widget class="QCheckBox" name="chkShowCandidates">
<layout class="QGridLayout" name="gridLayout_2" columnstretch="0,1">
<item row="0" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Show candidates (for debugging)</string>
<string>Text rendering</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="mTextRenderFormatComboBox"/>
</item>
<item row="1" column="0" colspan="2">
<widget class="QCheckBox" name="chkShowPartialsLabels">
<property name="text">
<string>Allow truncated labels on edges of map</string>
</property>
</widget>
</item>
<item row="2" column="0">
<item row="2" column="0" colspan="2">
<widget class="QCheckBox" name="chkShowAllLabels">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
Expand All @@ -232,17 +239,10 @@
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="mDrawOutlinesChkBox">
<property name="text">
<string>Draw text as outlines (recommended)</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="chkShowPartialsLabels">
<item row="3" column="0" colspan="2">
<widget class="QCheckBox" name="chkShowCandidates">
<property name="text">
<string>Show partial labels</string>
<string>Show candidates (for debugging)</string>
</property>
</widget>
</item>
Expand Down Expand Up @@ -278,11 +278,10 @@
<tabstop>spinCandPoint</tabstop>
<tabstop>spinCandLine</tabstop>
<tabstop>spinCandPolygon</tabstop>
<tabstop>mDrawOutlinesChkBox</tabstop>
<tabstop>mTextRenderFormatComboBox</tabstop>
<tabstop>chkShowPartialsLabels</tabstop>
<tabstop>chkShowAllLabels</tabstop>
<tabstop>chkShowCandidates</tabstop>
<tabstop>buttonBox</tabstop>
</tabstops>
<resources/>
<connections>
Expand Down
37 changes: 37 additions & 0 deletions tests/src/core/testqgslabelingengine.cpp
Expand Up @@ -40,6 +40,7 @@ class TestQgsLabelingEngine : public QObject
void cleanupTestCase();
void init();// will be called before each testfunction is executed.
void cleanup();// will be called after every testfunction.
void testEngineSettings();
void testBasic();
void testDiagrams();
void testRuleBased();
Expand Down Expand Up @@ -99,6 +100,42 @@ void TestQgsLabelingEngine::cleanup()
vl = nullptr;
}

void TestQgsLabelingEngine::testEngineSettings()
{
// test labeling engine settings

// getters/setters
QgsLabelingEngineSettings settings;
settings.setDefaultTextRenderFormat( QgsRenderContext::TextFormatAlwaysText );
QCOMPARE( settings.defaultTextRenderFormat(), QgsRenderContext::TextFormatAlwaysText );
settings.setDefaultTextRenderFormat( QgsRenderContext::TextFormatAlwaysOutlines );
QCOMPARE( settings.defaultTextRenderFormat(), QgsRenderContext::TextFormatAlwaysOutlines );

// reading from project
QgsProject p;
settings.setDefaultTextRenderFormat( QgsRenderContext::TextFormatAlwaysText );
settings.writeSettingsToProject( &p );
QgsLabelingEngineSettings settings2;
settings2.readSettingsFromProject( &p );
QCOMPARE( settings2.defaultTextRenderFormat(), QgsRenderContext::TextFormatAlwaysText );

settings.setDefaultTextRenderFormat( QgsRenderContext::TextFormatAlwaysOutlines );
settings.writeSettingsToProject( &p );
settings2.readSettingsFromProject( &p );
QCOMPARE( settings2.defaultTextRenderFormat(), QgsRenderContext::TextFormatAlwaysOutlines );

// test that older setting is still respected as a fallback
QgsProject p2;
QgsLabelingEngineSettings settings3;
p2.writeEntry( QStringLiteral( "PAL" ), QStringLiteral( "/DrawOutlineLabels" ), false );
settings3.readSettingsFromProject( &p2 );
QCOMPARE( settings3.defaultTextRenderFormat(), QgsRenderContext::TextFormatAlwaysText );

p2.writeEntry( QStringLiteral( "PAL" ), QStringLiteral( "/DrawOutlineLabels" ), true );
settings3.readSettingsFromProject( &p2 );
QCOMPARE( settings3.defaultTextRenderFormat(), QgsRenderContext::TextFormatAlwaysOutlines );
}

void TestQgsLabelingEngine::setDefaultLabelParams( QgsPalLayerSettings &settings )
{
QgsTextFormat format;
Expand Down

0 comments on commit 7ed4218

Please sign in to comment.