Add GUI to edit tab stop distances

This commit is contained in:
Nyall Dawson 2024-10-29 12:45:01 +10:00
parent 7badf62596
commit 40d41ddee3
15 changed files with 853 additions and 266 deletions

View File

@ -0,0 +1,11 @@
# The following has been generated automatically from src/gui/labeling/qgstabpositionwidget.h
try:
QgsTabPositionWidget.__attribute_docs__ = {'positionsChanged': 'Emitted when positions are changed in the widget.\n'}
QgsTabPositionWidget.__signal_arguments__ = {'positionsChanged': ['positions: List[QgsTextFormat.Tab]']}
QgsTabPositionWidget.__group__ = ['labeling']
except NameError:
pass
try:
QgsTabPositionDialog.__group__ = ['labeling']
except NameError:
pass

View File

@ -0,0 +1,92 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/labeling/qgstabpositionwidget.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.py again *
************************************************************************/
class QgsTabPositionWidget: QgsPanelWidget
{
%Docstring(signature="appended")
A widget for configuring :py:class:`QgsTextFormat` tab positions.
.. versionadded:: 3.42
%End
%TypeHeaderCode
#include "qgstabpositionwidget.h"
%End
public:
QgsTabPositionWidget( QWidget *parent /TransferThis/ = 0 );
%Docstring
Constructor for QgsTabPositionWidget, with the specified ``parent`` widget
%End
void setPositions( const QList< QgsTextFormat::Tab > &positions );
%Docstring
Sets the tab ``positions`` to show in the widget.
.. seealso:: :py:func:`positions`
%End
QList< QgsTextFormat::Tab > positions() const;
%Docstring
Returns the tab positions defined in the widget.
.. seealso:: :py:func:`setPositions`
%End
signals:
void positionsChanged( const QList< QgsTextFormat::Tab > &positions );
%Docstring
Emitted when positions are changed in the widget.
%End
};
class QgsTabPositionDialog : QDialog
{
%Docstring(signature="appended")
A dialog to enter a custom dash space pattern for lines
%End
%TypeHeaderCode
#include "qgstabpositionwidget.h"
%End
public:
QgsTabPositionDialog( QWidget *parent /TransferThis/ = 0, Qt::WindowFlags f = Qt::WindowFlags() );
%Docstring
Constructor for QgsTabPositionDialog
%End
void setPositions( const QList< QgsTextFormat::Tab > &positions );
%Docstring
Sets the tab ``positions`` to show in the dialog.
.. seealso:: :py:func:`positions`
%End
QList< QgsTextFormat::Tab > positions() const;
%Docstring
Returns the tab positions defined in the dialog.
.. seealso:: :py:func:`setPositions`
%End
};
/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/labeling/qgstabpositionwidget.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.py again *
************************************************************************/

View File

@ -166,6 +166,7 @@ when registering labels for the labeling settings currently defined by the widge
protected slots:
void updateLinePlacementOptions();

View File

@ -364,6 +364,7 @@
%Include auto_generated/labeling/qgslabellineanchorwidget.sip
%Include auto_generated/labeling/qgslabelobstaclesettingswidget.sip
%Include auto_generated/labeling/qgslabelsettingswidgetbase.sip
%Include auto_generated/labeling/qgstabpositionwidget.sip
%Include auto_generated/layertree/qgscustomlayerorderwidget.sip
%Include auto_generated/layertree/qgslayertreeembeddedconfigwidget.sip
%Include auto_generated/layertree/qgslayertreeembeddedwidgetregistry.sip

View File

@ -0,0 +1,11 @@
# The following has been generated automatically from src/gui/labeling/qgstabpositionwidget.h
try:
QgsTabPositionWidget.__attribute_docs__ = {'positionsChanged': 'Emitted when positions are changed in the widget.\n'}
QgsTabPositionWidget.__signal_arguments__ = {'positionsChanged': ['positions: List[QgsTextFormat.Tab]']}
QgsTabPositionWidget.__group__ = ['labeling']
except NameError:
pass
try:
QgsTabPositionDialog.__group__ = ['labeling']
except NameError:
pass

View File

@ -0,0 +1,92 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/labeling/qgstabpositionwidget.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.py again *
************************************************************************/
class QgsTabPositionWidget: QgsPanelWidget
{
%Docstring(signature="appended")
A widget for configuring :py:class:`QgsTextFormat` tab positions.
.. versionadded:: 3.42
%End
%TypeHeaderCode
#include "qgstabpositionwidget.h"
%End
public:
QgsTabPositionWidget( QWidget *parent /TransferThis/ = 0 );
%Docstring
Constructor for QgsTabPositionWidget, with the specified ``parent`` widget
%End
void setPositions( const QList< QgsTextFormat::Tab > &positions );
%Docstring
Sets the tab ``positions`` to show in the widget.
.. seealso:: :py:func:`positions`
%End
QList< QgsTextFormat::Tab > positions() const;
%Docstring
Returns the tab positions defined in the widget.
.. seealso:: :py:func:`setPositions`
%End
signals:
void positionsChanged( const QList< QgsTextFormat::Tab > &positions );
%Docstring
Emitted when positions are changed in the widget.
%End
};
class QgsTabPositionDialog : QDialog
{
%Docstring(signature="appended")
A dialog to enter a custom dash space pattern for lines
%End
%TypeHeaderCode
#include "qgstabpositionwidget.h"
%End
public:
QgsTabPositionDialog( QWidget *parent /TransferThis/ = 0, Qt::WindowFlags f = Qt::WindowFlags() );
%Docstring
Constructor for QgsTabPositionDialog
%End
void setPositions( const QList< QgsTextFormat::Tab > &positions );
%Docstring
Sets the tab ``positions`` to show in the dialog.
.. seealso:: :py:func:`positions`
%End
QList< QgsTextFormat::Tab > positions() const;
%Docstring
Returns the tab positions defined in the dialog.
.. seealso:: :py:func:`setPositions`
%End
};
/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/labeling/qgstabpositionwidget.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.py again *
************************************************************************/

View File

@ -166,6 +166,7 @@ when registering labels for the labeling settings currently defined by the widge
protected slots:
void updateLinePlacementOptions();

View File

@ -364,6 +364,7 @@
%Include auto_generated/labeling/qgslabellineanchorwidget.sip
%Include auto_generated/labeling/qgslabelobstaclesettingswidget.sip
%Include auto_generated/labeling/qgslabelsettingswidgetbase.sip
%Include auto_generated/labeling/qgstabpositionwidget.sip
%Include auto_generated/layertree/qgscustomlayerorderwidget.sip
%Include auto_generated/layertree/qgslayertreeembeddedconfigwidget.sip
%Include auto_generated/layertree/qgslayertreeembeddedwidgetregistry.sip

View File

@ -267,6 +267,7 @@ set(QGIS_GUI_SRCS
labeling/qgslabelobstaclesettingswidget.cpp
labeling/qgslabelsettingswidgetbase.cpp
labeling/qgsrulebasedlabelingwidget.cpp
labeling/qgstabpositionwidget.cpp
layertree/qgscustomlayerorderwidget.cpp
layertree/qgslayertreeembeddedconfigwidget.cpp
@ -1245,6 +1246,7 @@ set(QGIS_GUI_HDRS
labeling/qgslabelobstaclesettingswidget.h
labeling/qgslabelsettingswidgetbase.h
labeling/qgsrulebasedlabelingwidget.h
labeling/qgstabpositionwidget.h
layertree/qgscustomlayerorderwidget.h
layertree/qgslayertreeembeddedconfigwidget.h

View File

@ -0,0 +1,123 @@
/***************************************************************************
qgstabpositionwidget.h
---------------------
begin : October 2024
copyright : (C) 2024 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 "qgstabpositionwidget.h"
#include "qgsapplication.h"
#include "qgsdoublevalidator.h"
#include <QDialogButtonBox>
QgsTabPositionWidget::QgsTabPositionWidget( QWidget *parent )
: QgsPanelWidget( parent )
{
setupUi( this );
mAddButton->setIcon( QgsApplication::getThemeIcon( "symbologyAdd.svg" ) );
mRemoveButton->setIcon( QgsApplication::getThemeIcon( "symbologyRemove.svg" ) );
connect( mAddButton, &QPushButton::clicked, this, &QgsTabPositionWidget::mAddButton_clicked );
connect( mRemoveButton, &QPushButton::clicked, this, &QgsTabPositionWidget::mRemoveButton_clicked );
connect( mTabPositionTreeWidget, &QTreeWidget::itemChanged, this, &QgsTabPositionWidget::emitPositionsChanged );
}
void QgsTabPositionWidget::setPositions( const QList<QgsTextFormat::Tab> &positions )
{
mTabPositionTreeWidget->clear();
for ( const QgsTextFormat::Tab &tab : positions )
{
QTreeWidgetItem *entry = new QTreeWidgetItem();
entry->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled );
entry->setText( 0, QLocale().toString( tab.position() ) );
entry->setData( 0, Qt::EditRole, tab.position() );
mTabPositionTreeWidget->addTopLevelItem( entry );
}
}
QList<QgsTextFormat::Tab> QgsTabPositionWidget::positions() const
{
QList<QgsTextFormat::Tab> result;
const int nTopLevelItems = mTabPositionTreeWidget->topLevelItemCount();
result.reserve( nTopLevelItems );
for ( int i = 0; i < nTopLevelItems; ++i )
{
if ( QTreeWidgetItem *currentItem = mTabPositionTreeWidget->topLevelItem( i ) )
{
result << QgsTextFormat::Tab( QgsDoubleValidator::toDouble( currentItem->text( 0 ) ) );
}
}
std::sort( result.begin(), result.end(), []( const QgsTextFormat::Tab & a, const QgsTextFormat::Tab & b )
{
return a.position() < b.position();
} );
return result;
}
void QgsTabPositionWidget::mAddButton_clicked()
{
const QList< QgsTextFormat::Tab > currentPositions = positions();
double newPosition = 6;
if ( !currentPositions.empty() )
{
newPosition = currentPositions.last().position() + 6;
}
QTreeWidgetItem *entry = new QTreeWidgetItem();
entry->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled );
entry->setText( 0, QLocale().toString( newPosition ) );
entry->setData( 0, Qt::EditRole, newPosition );
mTabPositionTreeWidget->addTopLevelItem( entry );
emitPositionsChanged();
}
void QgsTabPositionWidget::mRemoveButton_clicked()
{
if ( QTreeWidgetItem *currentItem = mTabPositionTreeWidget->currentItem() )
{
mTabPositionTreeWidget->takeTopLevelItem( mTabPositionTreeWidget->indexOfTopLevelItem( currentItem ) );
}
emitPositionsChanged();
}
void QgsTabPositionWidget::emitPositionsChanged()
{
emit positionsChanged( positions() );
}
QgsTabPositionDialog::QgsTabPositionDialog( QWidget *parent, Qt::WindowFlags f )
: QDialog( parent, f )
{
QVBoxLayout *vLayout = new QVBoxLayout();
mWidget = new QgsTabPositionWidget();
vLayout->addWidget( mWidget );
QDialogButtonBox *bbox = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal );
connect( bbox, &QDialogButtonBox::accepted, this, &QgsTabPositionDialog::accept );
connect( bbox, &QDialogButtonBox::rejected, this, &QgsTabPositionDialog::reject );
vLayout->addWidget( bbox );
setLayout( vLayout );
setWindowTitle( tr( "Tab Positions" ) );
}
void QgsTabPositionDialog::setPositions( const QList<QgsTextFormat::Tab> &positions )
{
mWidget->setPositions( positions );
}
QList<QgsTextFormat::Tab> QgsTabPositionDialog::positions() const
{
return mWidget->positions();
}

View File

@ -0,0 +1,102 @@
/***************************************************************************
qgstabpositionwidget.h
---------------------
begin : October 2024
copyright : (C) 2024 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. *
* *
***************************************************************************/
#ifndef QGSTABPOSITIONWIDGET_H
#define QGSTABPOSITIONWIDGET_H
#include "ui_qgstabpositionwidgetbase.h"
#include "qgis_gui.h"
#include "qgis_sip.h"
#include "qgspanelwidget.h"
#include "qgstextformat.h"
#include <QDialog>
/**
* \ingroup gui
* \brief A widget for configuring QgsTextFormat tab positions.
* \since QGIS 3.42
*/
class GUI_EXPORT QgsTabPositionWidget: public QgsPanelWidget, private Ui::QgsTabPositionWidgetBase
{
Q_OBJECT
public:
//! Constructor for QgsTabPositionWidget, with the specified \a parent widget
QgsTabPositionWidget( QWidget *parent SIP_TRANSFERTHIS = nullptr );
/**
* Sets the tab \a positions to show in the widget.
*
* \see positions()
*/
void setPositions( const QList< QgsTextFormat::Tab > &positions );
/**
* Returns the tab positions defined in the widget.
*
* \see setPositions()
*/
QList< QgsTextFormat::Tab > positions() const;
signals:
/**
* Emitted when positions are changed in the widget.
*/
void positionsChanged( const QList< QgsTextFormat::Tab > &positions );
private slots:
void mAddButton_clicked();
void mRemoveButton_clicked();
void emitPositionsChanged();
};
/**
* \ingroup gui
* \brief A dialog to enter a custom dash space pattern for lines
*/
class GUI_EXPORT QgsTabPositionDialog : public QDialog
{
Q_OBJECT
public:
//! Constructor for QgsTabPositionDialog
QgsTabPositionDialog( QWidget *parent SIP_TRANSFERTHIS = nullptr, Qt::WindowFlags f = Qt::WindowFlags() );
/**
* Sets the tab \a positions to show in the dialog.
*
* \see positions()
*/
void setPositions( const QList< QgsTextFormat::Tab > &positions );
/**
* Returns the tab positions defined in the dialog.
*
* \see setPositions()
*/
QList< QgsTextFormat::Tab > positions() const;
private:
QgsTabPositionWidget *mWidget = nullptr;
};
#endif // QGSTABPOSITIONWIDGET_H

View File

@ -45,6 +45,7 @@
#include "qgsconfig.h"
#include "qgsprojectstylesettings.h"
#include "qgsprojectviewsettings.h"
#include "qgstabpositionwidget.h"
#include <QButtonGroup>
#include <QMessageBox>
@ -110,6 +111,7 @@ void QgsTextFormatWidget::initWidget()
connect( mToolButtonConfigureSubstitutes, &QToolButton::clicked, this, &QgsTextFormatWidget::mToolButtonConfigureSubstitutes_clicked );
connect( mKerningCheckBox, &QCheckBox::toggled, this, &QgsTextFormatWidget::kerningToggled );
connect( mComboOverlapHandling, qOverload< int >( &QComboBox::currentIndexChanged ), this, &QgsTextFormatWidget::overlapModeChanged );
connect( mTabStopsButton, &QToolButton::clicked, this, &QgsTextFormatWidget::configureTabStops );
const int iconSize = QgsGuiUtils::scaleIconSize( 20 );
mOptionsTab->setIconSize( QSize( iconSize, iconSize ) );
@ -929,6 +931,9 @@ void QgsTextFormatWidget::updateWidgetForFormat( const QgsTextFormat &format )
mDataDefinedProperties = format.dataDefinedProperties();
}
mTabPositions = format.tabPositions();
mTabStopDistanceSpin->setEnabled( mTabPositions.empty() );
// buffer
mBufferDrawChkBx->setChecked( buffer.enabled() );
mBufferFrame->setEnabled( buffer.enabled() );
@ -1128,6 +1133,7 @@ QgsTextFormat QgsTextFormatWidget::format( bool includeDataDefinedProperties ) c
format.setTabStopDistance( mTabDistanceUnitWidget->unit() == Qgis::RenderUnit::Percentage ? ( mTabStopDistanceSpin->value() / 100 ) : mTabStopDistanceSpin->value() );
format.setTabStopDistanceUnit( mTabDistanceUnitWidget->unit() );
format.setTabStopDistanceMapUnitScale( mTabDistanceUnitWidget->getMapUnitScale() );
format.setTabPositions( mTabPositions );
// buffer
QgsTextBufferSettings buffer;
@ -2162,6 +2168,35 @@ void QgsTextFormatWidget::mToolButtonConfigureSubstitutes_clicked()
}
}
void QgsTextFormatWidget::configureTabStops()
{
QgsPanelWidget *panel = QgsPanelWidget::findParentPanel( this );
if ( panel && panel->dockMode() )
{
QgsTabPositionWidget *widget = new QgsTabPositionWidget( panel );
widget->setPanelTitle( tr( "Tab Positions" ) );
widget->setPositions( mTabPositions );
connect( widget, &QgsTabPositionWidget::positionsChanged, this, [ = ]( const QList< QgsTextFormat::Tab > &positions )
{
mTabPositions = positions;
mTabStopDistanceSpin->setEnabled( mTabPositions.empty() );
emit widgetChanged();
} );
panel->openPanel( widget );
}
else
{
QgsTabPositionDialog dlg( this );
dlg.setPositions( mTabPositions );
if ( dlg.exec() == QDialog::Accepted )
{
mTabPositions = dlg.positions();
mTabStopDistanceSpin->setEnabled( mTabPositions.empty() );
emit widgetChanged();
}
}
}
void QgsTextFormatWidget::showBackgroundRadius( bool show )
{
mShapeRadiusLabel->setVisible( show );

View File

@ -170,6 +170,9 @@ class GUI_EXPORT QgsTextFormatWidget : public QWidget, public QgsExpressionConte
//! Text substitution list
QgsStringReplacementCollection mSubstitutions;
//! Tab positions
QList< QgsTextFormat::Tab > mTabPositions;
//! Quadrant button group
QButtonGroup *mQuadrantBtnGrp = nullptr;
//! Symbol direction button group
@ -299,6 +302,7 @@ class GUI_EXPORT QgsTextFormatWidget : public QWidget, public QgsExpressionConte
void mDirectSymbRightToolBtn_clicked();
void chkLineOrientationDependent_toggled( bool active );
void mToolButtonConfigureSubstitutes_clicked();
void configureTabStops();
void collapseSample( bool collapse );
void changeTextColor( const QColor &color );
void changeBufferColor( const QColor &color );

View File

@ -0,0 +1,87 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QgsTabPositionWidgetBase</class>
<widget class="QgsPanelWidget" name="QgsTabPositionWidgetBase">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>194</width>
<height>277</height>
</rect>
</property>
<property name="windowTitle">
<string>Tab Positions</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="QTreeWidget" name="mTabPositionTreeWidget">
<property name="headerHidden">
<bool>true</bool>
</property>
<property name="columnCount">
<number>1</number>
</property>
<column>
<property name="text">
<string>Dash</string>
</property>
</column>
</widget>
</item>
<item row="0" column="1">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QPushButton" name="mAddButton">
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="mRemoveButton">
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>245</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QgsPanelWidget</class>
<extends>QWidget</extends>
<header>qgspanelwidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@ -625,7 +625,7 @@
<item>
<widget class="QStackedWidget" name="mLabelStackedWidget">
<property name="currentIndex">
<number>0</number>
<number>1</number>
</property>
<widget class="QWidget" name="mLabelPage_Text">
<layout class="QVBoxLayout" name="verticalLayout_6">
@ -654,8 +654,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>305</width>
<height>307</height>
<width>485</width>
<height>410</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="0,1">
@ -1217,8 +1217,8 @@ font-style: italic;</string>
<rect>
<x>0</x>
<y>0</y>
<width>347</width>
<height>720</height>
<width>471</width>
<height>755</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_42">
@ -1228,16 +1228,6 @@ font-style: italic;</string>
<property name="rightMargin">
<number>6</number>
</property>
<item row="7" column="0">
<widget class="QLabel" name="labelBlendMode">
<property name="text">
<string>Blend mode</string>
</property>
</widget>
</item>
<item row="6" column="1" colspan="2">
<widget class="QComboBox" name="mTextOrientationComboBox"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_10">
<property name="text">
@ -1245,17 +1235,34 @@ font-style: italic;</string>
</property>
</widget>
</item>
<item row="7" column="3">
<widget class="QgsPropertyOverrideButton" name="mFontBlendModeDDBtn">
<item row="2" column="3">
<widget class="QgsPropertyOverrideButton" name="mFontWordSpacingDDBtn">
<property name="text">
<string>…</string>
</property>
</widget>
</item>
<item row="2" column="1" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_30">
<item row="3" column="3">
<widget class="QgsPropertyOverrideButton" name="mFontStretchDDBtn">
<property name="text">
<string>…</string>
</property>
</widget>
</item>
<item row="9" column="0" colspan="3">
<widget class="QCheckBox" name="mCheckBoxSubstituteText">
<property name="toolTip">
<string>If enabled, the label text will automatically be modified using a preset list of substitutes</string>
</property>
<property name="text">
<string>Apply label text substitutes</string>
</property>
</widget>
</item>
<item row="1" column="1" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_29">
<item>
<widget class="QLabel" name="mFontWordSpacingLabel_3">
<widget class="QLabel" name="mFontLetterSpacingLabel_3">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
@ -1263,12 +1270,12 @@ font-style: italic;</string>
</sizepolicy>
</property>
<property name="text">
<string>word</string>
<string>letter</string>
</property>
</widget>
</item>
<item>
<widget class="QgsDoubleSpinBox" name="mFontWordSpacingSpinBox">
<widget class="QgsDoubleSpinBox" name="mFontLetterSpacingSpinBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
@ -1297,17 +1304,27 @@ font-style: italic;</string>
</item>
</layout>
</item>
<item row="8" column="0" colspan="3">
<widget class="QCheckBox" name="mCheckBoxSubstituteText">
<property name="toolTip">
<string>If enabled, the label text will automatically be modified using a preset list of substitutes</string>
</property>
<item row="0" column="3">
<widget class="QgsPropertyOverrideButton" name="mFontCaseDDBtn">
<property name="text">
<string>Apply label text substitutes</string>
<string>…</string>
</property>
</widget>
</item>
<item row="8" column="3">
<item row="0" column="0">
<widget class="QLabel" name="mFontCapitalsLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Type case</string>
</property>
</widget>
</item>
<item row="9" column="3">
<widget class="QToolButton" name="mToolButtonConfigureSubstitutes">
<property name="enabled">
<bool>false</bool>
@ -1320,159 +1337,17 @@ font-style: italic;</string>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="QgsPropertyOverrideButton" name="mFontWordSpacingDDBtn">
<item row="8" column="3">
<widget class="QgsPropertyOverrideButton" name="mFontBlendModeDDBtn">
<property name="text">
<string>…</string>
</property>
</widget>
</item>
<item row="6" column="3">
<widget class="QgsPropertyOverrideButton" name="mTextOrientationDDBtn">
<item row="6" column="0" colspan="3">
<widget class="QCheckBox" name="mKerningCheckBox">
<property name="text">
<string>…</string>
</property>
</widget>
</item>
<item row="11" column="0" colspan="4">
<layout class="QGridLayout" name="gridLayout_34">
<property name="verticalSpacing">
<number>6</number>
</property>
<item row="0" column="2">
<spacer name="horizontalSpacer_8">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="mFormatNumChkBx">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Formatted numbers</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QgsPropertyOverrideButton" name="mFormatNumDDBtn">
<property name="text">
<string>…</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="3">
<widget class="QFrame" name="mFormatNumFrame">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QGridLayout" name="gridLayout_31">
<property name="leftMargin">
<number>20</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="mFormatNumDecimalsLabel">
<property name="text">
<string>Decimal places </string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QgsSpinBox" name="mFormatNumDecimalsSpnBx">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximum">
<number>20</number>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QgsPropertyOverrideButton" name="mFormatNumDecimalsDDBtn">
<property name="text">
<string>…</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QCheckBox" name="mFormatNumPlusSignChkBx">
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<property name="text">
<string>Show plus sign</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QgsPropertyOverrideButton" name="mFormatNumPlusSignDDBtn">
<property name="text">
<string>…</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item row="3" column="3">
<widget class="QgsPropertyOverrideButton" name="mFontStretchDDBtn">
<property name="text">
<string>…</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QgsPropertyOverrideButton" name="mFontCaseDDBtn">
<property name="text">
<string>…</string>
</property>
</widget>
</item>
<item row="12" column="3">
<spacer name="verticalSpacer_6">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="3">
<widget class="QgsPropertyOverrideButton" name="mFontLetterSpacingDDBtn">
<property name="text">
<string>…</string>
<string>Enable kerning</string>
</property>
</widget>
</item>
@ -1498,7 +1373,30 @@ font-style: italic;</string>
</property>
</widget>
</item>
<item row="9" column="0" colspan="4">
<item row="8" column="1" colspan="2">
<widget class="QgsBlendModeComboBox" name="comboBlendMode"/>
</item>
<item row="1" column="3">
<widget class="QgsPropertyOverrideButton" name="mFontLetterSpacingDDBtn">
<property name="text">
<string>…</string>
</property>
</widget>
</item>
<item row="13" column="3">
<spacer name="verticalSpacer_6">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item row="10" column="0" colspan="4">
<layout class="QGridLayout" name="gridLayout_35">
<property name="verticalSpacing">
<number>6</number>
@ -1710,36 +1608,10 @@ font-style: italic;</string>
</item>
</layout>
</item>
<item row="7" column="1" colspan="2">
<widget class="QgsBlendModeComboBox" name="comboBlendMode"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="mLabelStretch">
<property name="text">
<string>Stretch</string>
</property>
</widget>
</item>
<item row="3" column="1" colspan="2">
<widget class="QgsSpinBox" name="mSpinStretch">
<property name="suffix">
<string> %</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>4000</number>
</property>
<property name="value">
<number>100</number>
</property>
</widget>
</item>
<item row="1" column="1" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_29">
<item row="2" column="1" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_30">
<item>
<widget class="QLabel" name="mFontLetterSpacingLabel_3">
<widget class="QLabel" name="mFontWordSpacingLabel_3">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
@ -1747,12 +1619,12 @@ font-style: italic;</string>
</sizepolicy>
</property>
<property name="text">
<string>letter</string>
<string>word</string>
</property>
</widget>
</item>
<item>
<widget class="QgsDoubleSpinBox" name="mFontLetterSpacingSpinBox">
<widget class="QgsDoubleSpinBox" name="mFontWordSpacingSpinBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
@ -1781,7 +1653,141 @@ font-style: italic;</string>
</item>
</layout>
</item>
<item row="10" column="0" colspan="4">
<item row="3" column="1" colspan="2">
<widget class="QgsSpinBox" name="mSpinStretch">
<property name="suffix">
<string> %</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>4000</number>
</property>
<property name="value">
<number>100</number>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="mLabelStretch">
<property name="text">
<string>Stretch</string>
</property>
</widget>
</item>
<item row="12" column="0" colspan="4">
<layout class="QGridLayout" name="gridLayout_34">
<property name="verticalSpacing">
<number>6</number>
</property>
<item row="0" column="2">
<spacer name="horizontalSpacer_8">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="mFormatNumChkBx">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Formatted numbers</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QgsPropertyOverrideButton" name="mFormatNumDDBtn">
<property name="text">
<string>…</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="3">
<widget class="QFrame" name="mFormatNumFrame">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QGridLayout" name="gridLayout_31">
<property name="leftMargin">
<number>20</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="mFormatNumDecimalsLabel">
<property name="text">
<string>Decimal places </string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QgsSpinBox" name="mFormatNumDecimalsSpnBx">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximum">
<number>20</number>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QgsPropertyOverrideButton" name="mFormatNumDecimalsDDBtn">
<property name="text">
<string>…</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QCheckBox" name="mFormatNumPlusSignChkBx">
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<property name="text">
<string>Show plus sign</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QgsPropertyOverrideButton" name="mFormatNumPlusSignDDBtn">
<property name="text">
<string>…</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item row="7" column="1" colspan="2">
<widget class="QComboBox" name="mTextOrientationComboBox"/>
</item>
<item row="11" column="0" colspan="4">
<widget class="QFrame" name="mDirectSymbolsFrame">
<layout class="QGridLayout" name="gridLayout_33">
<property name="leftMargin">
@ -2081,39 +2087,85 @@ font-style: italic;</string>
</layout>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="mFontCapitalsLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item row="7" column="3">
<widget class="QgsPropertyOverrideButton" name="mTextOrientationDDBtn">
<property name="text">
<string>Type case</string>
<string>…</string>
</property>
</widget>
</item>
<item row="5" column="0" colspan="3">
<widget class="QCheckBox" name="mKerningCheckBox">
<item row="8" column="0">
<widget class="QLabel" name="labelBlendMode">
<property name="text">
<string>Enable kerning</string>
<string>Blend mode</string>
</property>
</widget>
</item>
<item row="6" column="0">
<item row="7" column="0">
<widget class="QLabel" name="labelTextOrientation">
<property name="text">
<string>Text orientation</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="mLabelStretch_2">
<property name="text">
<string>Tab distance</string>
<item row="4" column="1" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_31">
<property name="bottomMargin">
<number>0</number>
</property>
</widget>
<item>
<widget class="QgsDoubleSpinBox" name="mTabStopDistanceSpin">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Space in pixels or map units, relative to size unit choice</string>
</property>
<property name="decimals">
<number>4</number>
</property>
<property name="minimum">
<double>-1000.000000000000000</double>
</property>
<property name="maximum">
<double>999999999.000000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
<property name="showClearButton" stdset="0">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QgsUnitSelectionWidget" name="mTabDistanceUnitWidget" native="true">
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="mTabStopsButton">
<property name="toolTip">
<string>Configure tab stops</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/mActionOptions.svg</normaloff>:/images/themes/default/mActionOptions.svg</iconset>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item row="4" column="3">
<widget class="QgsPropertyOverrideButton" name="mTabDistanceDDBtn">
@ -2122,38 +2174,10 @@ font-style: italic;</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QgsDoubleSpinBox" name="mTabStopDistanceSpin">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Space in pixels or map units, relative to size unit choice</string>
</property>
<property name="decimals">
<number>4</number>
</property>
<property name="minimum">
<double>-1000.000000000000000</double>
</property>
<property name="maximum">
<double>999999999.000000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
<property name="showClearButton" stdset="0">
<bool>true</bool>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="QgsUnitSelectionWidget" name="mTabDistanceUnitWidget" native="true">
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
<item row="4" column="0">
<widget class="QLabel" name="mLabelStretch_2">
<property name="text">
<string>Tab distance</string>
</property>
</widget>
</item>
@ -2190,8 +2214,8 @@ font-style: italic;</string>
<rect>
<x>0</x>
<y>0</y>
<width>325</width>
<height>346</height>
<width>273</width>
<height>299</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_12">
@ -4142,9 +4166,9 @@ font-style: italic;</string>
<property name="geometry">
<rect>
<x>0</x>
<y>-229</y>
<width>471</width>
<height>1786</height>
<y>0</y>
<width>435</width>
<height>1784</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_11">
@ -5513,8 +5537,7 @@ font-style: italic;</string>
</spacer>
</item>
<item row="1" column="1">
<widget class="QToolButton" name="mGeometryGeneratorExpressionButton">
</widget>
<widget class="QToolButton" name="mGeometryGeneratorExpressionButton"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="mGeometryGeneratorWarningLabel">
@ -6965,6 +6988,7 @@ This limit is inclusive, that means the label will be displayed on this scale.</
<tabstop>mFontStretchDDBtn</tabstop>
<tabstop>mTabStopDistanceSpin</tabstop>
<tabstop>mTabDistanceUnitWidget</tabstop>
<tabstop>mTabStopsButton</tabstop>
<tabstop>mTabDistanceDDBtn</tabstop>
<tabstop>mKerningCheckBox</tabstop>
<tabstop>mTextOrientationComboBox</tabstop>