[FEATURE][layouts] Expose choice of arrangement of legends (i.e.
symbols to the left OR symbols to the right of legend text), and alignment for group/subgroup/item text Allows creation of right-to-left locale friendly legends. Additionally, we default to this right-to-left style alignment when creating new legends under a RTL based locale.
@ -765,6 +765,8 @@
|
|||||||
<file>themes/default/mIconAlignJustify.svg</file>
|
<file>themes/default/mIconAlignJustify.svg</file>
|
||||||
<file>themes/default/mIconAlignLeft.svg</file>
|
<file>themes/default/mIconAlignLeft.svg</file>
|
||||||
<file>themes/default/mIconAlignRight.svg</file>
|
<file>themes/default/mIconAlignRight.svg</file>
|
||||||
|
<file>themes/default/mIconArrangeSymbolsLeft.svg</file>
|
||||||
|
<file>themes/default/mIconArrangeSymbolsRight.svg</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
<qresource prefix="/images/tips">
|
<qresource prefix="/images/tips">
|
||||||
<file alias="symbol_levels.png">qgis_tips/symbol_levels.png</file>
|
<file alias="symbol_levels.png">qgis_tips/symbol_levels.png</file>
|
||||||
|
|||||||
1
images/themes/default/mIconArrangeSymbolsLeft.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 6.35 6.35"><path style="marker:none" d="M2.646 2.646H5.82v.529H2.646zm0 1.852H4.55v.529H2.646zm0-3.44h2.54v.53h-2.54z" color="#555753" overflow="visible" fill="#555753" filter="url(#filter8750)"/><path fill="#848484" stroke="#5c5c5c" stroke-width=".224" d="M.641.641h1.364V1.74H.641zm0 1.852h1.364v1.099H.641zm0 1.852h1.364v1.099H.641z"/></svg>
|
||||||
|
After Width: | Height: | Size: 420 B |
1
images/themes/default/mIconArrangeSymbolsRight.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 6.35 6.35"><path style="marker:none" d="M.53 2.646h3.174v.529H.53zm0 1.852h1.904v.529H.53zm0-3.44h2.539v.53H.529z" color="#555753" overflow="visible" fill="#555753" filter="url(#filter8750)"/><path d="M4.345.641H5.71v1.1H4.345zm0 1.852H5.71v1.1H4.345zm0 1.852H5.71v1.1H4.345z" fill="#848484" stroke="#5c5c5c" stroke-width=".224"/></svg>
|
||||||
|
After Width: | Height: | Size: 412 B |
@ -76,10 +76,23 @@ Default implementation does nothing. *
|
|||||||
|
|
||||||
struct ItemContext
|
struct ItemContext
|
||||||
{
|
{
|
||||||
|
ItemContext();
|
||||||
|
|
||||||
QgsRenderContext *context;
|
QgsRenderContext *context;
|
||||||
QPainter *painter;
|
QPainter *painter;
|
||||||
|
|
||||||
QPointF point;
|
QPointF point;
|
||||||
|
|
||||||
double labelXOffset;
|
double labelXOffset;
|
||||||
|
|
||||||
|
double top;
|
||||||
|
|
||||||
|
double columnLeft;
|
||||||
|
|
||||||
|
double columnRight;
|
||||||
|
|
||||||
|
double maxSiblingSymbolWidth;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ItemMetrics
|
struct ItemMetrics
|
||||||
|
|||||||
@ -279,6 +279,28 @@ Returns the legend symbol width.
|
|||||||
Sets the legend symbol ``width``.
|
Sets the legend symbol ``width``.
|
||||||
|
|
||||||
.. seealso:: :py:func:`symbolWidth`
|
.. seealso:: :py:func:`symbolWidth`
|
||||||
|
%End
|
||||||
|
|
||||||
|
void setSymbolAlignment( Qt::AlignmentFlag alignment );
|
||||||
|
%Docstring
|
||||||
|
Sets the ``alignment`` for placement of legend symbols.
|
||||||
|
|
||||||
|
Only Qt.AlignLeft or Qt.AlignRight are supported values.
|
||||||
|
|
||||||
|
.. seealso:: :py:func:`symbolAlignment`
|
||||||
|
|
||||||
|
.. versionadded:: 3.10.0
|
||||||
|
%End
|
||||||
|
|
||||||
|
Qt::AlignmentFlag symbolAlignment() const;
|
||||||
|
%Docstring
|
||||||
|
Returns the alignment for placement of legend symbols.
|
||||||
|
|
||||||
|
Only Qt.AlignLeft or Qt.AlignRight are supported values.
|
||||||
|
|
||||||
|
.. seealso:: :py:func:`setSymbolAlignment`
|
||||||
|
|
||||||
|
.. versionadded:: 3.10.0
|
||||||
%End
|
%End
|
||||||
|
|
||||||
double symbolHeight() const;
|
double symbolHeight() const;
|
||||||
|
|||||||
@ -32,18 +32,14 @@ in QgsLegendModel class.
|
|||||||
|
|
||||||
Qt::AlignmentFlag titleAlignment() const;
|
Qt::AlignmentFlag titleAlignment() const;
|
||||||
%Docstring
|
%Docstring
|
||||||
Returns the alignment of the legend title
|
Returns the alignment of the legend title.
|
||||||
|
|
||||||
:return: Qt.AlignmentFlag for the legend title
|
|
||||||
|
|
||||||
.. seealso:: :py:func:`setTitleAlignment`
|
.. seealso:: :py:func:`setTitleAlignment`
|
||||||
%End
|
%End
|
||||||
|
|
||||||
void setTitleAlignment( Qt::AlignmentFlag alignment );
|
void setTitleAlignment( Qt::AlignmentFlag alignment );
|
||||||
%Docstring
|
%Docstring
|
||||||
Sets the alignment of the legend title
|
Sets the ``alignment`` of the legend title.
|
||||||
|
|
||||||
:param alignment: Text alignment for drawing the legend title
|
|
||||||
|
|
||||||
.. seealso:: :py:func:`titleAlignment`
|
.. seealso:: :py:func:`titleAlignment`
|
||||||
%End
|
%End
|
||||||
@ -102,6 +98,28 @@ Overrides fontColor()
|
|||||||
QSizeF symbolSize() const;
|
QSizeF symbolSize() const;
|
||||||
void setSymbolSize( QSizeF s );
|
void setSymbolSize( QSizeF s );
|
||||||
|
|
||||||
|
void setSymbolAlignment( Qt::AlignmentFlag alignment );
|
||||||
|
%Docstring
|
||||||
|
Sets the ``alignment`` for placement of legend symbols.
|
||||||
|
|
||||||
|
Only Qt.AlignLeft or Qt.AlignRight are supported values.
|
||||||
|
|
||||||
|
.. seealso:: :py:func:`symbolAlignment`
|
||||||
|
|
||||||
|
.. versionadded:: 3.10.0
|
||||||
|
%End
|
||||||
|
|
||||||
|
Qt::AlignmentFlag symbolAlignment() const;
|
||||||
|
%Docstring
|
||||||
|
Returns the alignment for placement of legend symbols.
|
||||||
|
|
||||||
|
Only Qt.AlignLeft or Qt.AlignRight are supported values.
|
||||||
|
|
||||||
|
.. seealso:: :py:func:`setSymbolAlignment`
|
||||||
|
|
||||||
|
.. versionadded:: 3.10.0
|
||||||
|
%End
|
||||||
|
|
||||||
bool drawRasterStroke() const;
|
bool drawRasterStroke() const;
|
||||||
%Docstring
|
%Docstring
|
||||||
Returns whether a stroke will be drawn around raster symbol items.
|
Returns whether a stroke will be drawn around raster symbol items.
|
||||||
|
|||||||
@ -58,6 +58,24 @@ The font for this style.
|
|||||||
void setMargin( double margin );
|
void setMargin( double margin );
|
||||||
%Docstring
|
%Docstring
|
||||||
Sets all margins
|
Sets all margins
|
||||||
|
%End
|
||||||
|
|
||||||
|
Qt::Alignment alignment() const;
|
||||||
|
%Docstring
|
||||||
|
Returns the alignment for the legend component.
|
||||||
|
|
||||||
|
.. seealso:: :py:func:`setAlignment`
|
||||||
|
|
||||||
|
.. versionadded:: 3.10
|
||||||
|
%End
|
||||||
|
|
||||||
|
void setAlignment( Qt::Alignment alignment );
|
||||||
|
%Docstring
|
||||||
|
Sets the alignment for the legend component.
|
||||||
|
|
||||||
|
.. seealso:: :py:func:`alignment`
|
||||||
|
|
||||||
|
.. versionadded:: 3.10
|
||||||
%End
|
%End
|
||||||
|
|
||||||
void writeXml( const QString &name, QDomElement &elem, QDomDocument &doc ) const;
|
void writeXml( const QString &name, QDomElement &elem, QDomDocument &doc ) const;
|
||||||
|
|||||||
@ -49,6 +49,18 @@ Sets the current ``alignment`` choice.
|
|||||||
.. seealso:: :py:func:`currentAlignment`
|
.. seealso:: :py:func:`currentAlignment`
|
||||||
%End
|
%End
|
||||||
|
|
||||||
|
void customiseAlignmentDisplay( Qt::Alignment alignment, const QString &text = QString(), const QIcon &icon = QIcon() );
|
||||||
|
%Docstring
|
||||||
|
Sets the ``text`` and ``icon`` to use for a particular ``alignment`` option,
|
||||||
|
replacing the default text or icon.
|
||||||
|
|
||||||
|
If ``text`` or ``icon`` is not specified, they will not be changed from the default.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
This must be called after first filtering the available alignment options via setAvailableAlignments().
|
||||||
|
%End
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
void changed();
|
void changed();
|
||||||
|
|||||||
@ -195,6 +195,16 @@ void QgsLayoutAppUtils::registerGuiForKnownItemTypes()
|
|||||||
// try to find a good map to link the legend with by default
|
// try to find a good map to link the legend with by default
|
||||||
legend->setLinkedMap( findSensibleDefaultLinkedMapItem( legend ) );
|
legend->setLinkedMap( findSensibleDefaultLinkedMapItem( legend ) );
|
||||||
|
|
||||||
|
if ( QApplication::isRightToLeft() )
|
||||||
|
{
|
||||||
|
// for right-to-left locales, use an appropriate default layout
|
||||||
|
legend->setSymbolAlignment( Qt::AlignRight );
|
||||||
|
legend->rstyle( QgsLegendStyle::Group ).setAlignment( Qt::AlignRight );
|
||||||
|
legend->rstyle( QgsLegendStyle::Subgroup ).setAlignment( Qt::AlignRight );
|
||||||
|
legend->rstyle( QgsLegendStyle::SymbolLabel ).setAlignment( Qt::AlignRight );
|
||||||
|
legend->setTitleAlignment( Qt::AlignRight );
|
||||||
|
}
|
||||||
|
|
||||||
legend->updateLegend();
|
legend->updateLegend();
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
|||||||
@ -70,7 +70,10 @@ QgsLayoutLegendWidget::QgsLayoutLegendWidget( QgsLayoutItemLegend *legend )
|
|||||||
setupUi( this );
|
setupUi( this );
|
||||||
connect( mWrapCharLineEdit, &QLineEdit::textChanged, this, &QgsLayoutLegendWidget::mWrapCharLineEdit_textChanged );
|
connect( mWrapCharLineEdit, &QLineEdit::textChanged, this, &QgsLayoutLegendWidget::mWrapCharLineEdit_textChanged );
|
||||||
connect( mTitleLineEdit, &QLineEdit::textChanged, this, &QgsLayoutLegendWidget::mTitleLineEdit_textChanged );
|
connect( mTitleLineEdit, &QLineEdit::textChanged, this, &QgsLayoutLegendWidget::mTitleLineEdit_textChanged );
|
||||||
connect( mTitleAlignCombo, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsLayoutLegendWidget::mTitleAlignCombo_currentIndexChanged );
|
connect( mTitleAlignCombo, &QgsAlignmentComboBox::changed, this, &QgsLayoutLegendWidget::titleAlignmentChanged );
|
||||||
|
connect( mGroupAlignCombo, &QgsAlignmentComboBox::changed, this, &QgsLayoutLegendWidget::groupAlignmentChanged );
|
||||||
|
connect( mSubgroupAlignCombo, &QgsAlignmentComboBox::changed, this, &QgsLayoutLegendWidget::subgroupAlignmentChanged );
|
||||||
|
connect( mItemAlignCombo, &QgsAlignmentComboBox::changed, this, &QgsLayoutLegendWidget::itemAlignmentChanged );
|
||||||
connect( mColumnCountSpinBox, static_cast < void ( QSpinBox::* )( int ) > ( &QSpinBox::valueChanged ), this, &QgsLayoutLegendWidget::mColumnCountSpinBox_valueChanged );
|
connect( mColumnCountSpinBox, static_cast < void ( QSpinBox::* )( int ) > ( &QSpinBox::valueChanged ), this, &QgsLayoutLegendWidget::mColumnCountSpinBox_valueChanged );
|
||||||
connect( mSplitLayerCheckBox, &QCheckBox::toggled, this, &QgsLayoutLegendWidget::mSplitLayerCheckBox_toggled );
|
connect( mSplitLayerCheckBox, &QCheckBox::toggled, this, &QgsLayoutLegendWidget::mSplitLayerCheckBox_toggled );
|
||||||
connect( mEqualColumnWidthCheckBox, &QCheckBox::toggled, this, &QgsLayoutLegendWidget::mEqualColumnWidthCheckBox_toggled );
|
connect( mEqualColumnWidthCheckBox, &QCheckBox::toggled, this, &QgsLayoutLegendWidget::mEqualColumnWidthCheckBox_toggled );
|
||||||
@ -111,6 +114,16 @@ QgsLayoutLegendWidget::QgsLayoutLegendWidget( QgsLayoutItemLegend *legend )
|
|||||||
mLayerFontButton->setMode( QgsFontButton::ModeQFont );
|
mLayerFontButton->setMode( QgsFontButton::ModeQFont );
|
||||||
mItemFontButton->setMode( QgsFontButton::ModeQFont );
|
mItemFontButton->setMode( QgsFontButton::ModeQFont );
|
||||||
|
|
||||||
|
mTitleAlignCombo->setAvailableAlignments( Qt::AlignLeft | Qt::AlignHCenter | Qt::AlignRight );
|
||||||
|
mGroupAlignCombo->setAvailableAlignments( Qt::AlignLeft | Qt::AlignHCenter | Qt::AlignRight );
|
||||||
|
mSubgroupAlignCombo->setAvailableAlignments( Qt::AlignLeft | Qt::AlignHCenter | Qt::AlignRight );
|
||||||
|
mItemAlignCombo->setAvailableAlignments( Qt::AlignLeft | Qt::AlignHCenter | Qt::AlignRight );
|
||||||
|
|
||||||
|
mArrangementCombo->setAvailableAlignments( Qt::AlignLeft | Qt::AlignRight );
|
||||||
|
connect( mArrangementCombo, &QgsAlignmentComboBox::changed, this, &QgsLayoutLegendWidget::arrangementChanged );
|
||||||
|
mArrangementCombo->customiseAlignmentDisplay( Qt::AlignLeft, tr( "Symbols on Left" ), QgsApplication::getThemeIcon( QStringLiteral( "/mIconArrangeSymbolsLeft.svg" ) ) );
|
||||||
|
mArrangementCombo->customiseAlignmentDisplay( Qt::AlignRight, tr( "Symbols on Right" ), QgsApplication::getThemeIcon( QStringLiteral( "/mIconArrangeSymbolsRight.svg" ) ) );
|
||||||
|
|
||||||
// setup icons
|
// setup icons
|
||||||
mAddToolButton->setIcon( QIcon( QgsApplication::iconPath( "symbologyAdd.svg" ) ) );
|
mAddToolButton->setIcon( QIcon( QgsApplication::iconPath( "symbologyAdd.svg" ) ) );
|
||||||
mEditPushButton->setIcon( QIcon( QgsApplication::iconPath( "symbologyEdit.svg" ) ) );
|
mEditPushButton->setIcon( QIcon( QgsApplication::iconPath( "symbologyEdit.svg" ) ) );
|
||||||
@ -168,11 +181,13 @@ void QgsLayoutLegendWidget::setGuiElements()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int alignment = mLegend->titleAlignment() == Qt::AlignLeft ? 0 : mLegend->titleAlignment() == Qt::AlignHCenter ? 1 : 2;
|
|
||||||
|
|
||||||
blockAllSignals( true );
|
blockAllSignals( true );
|
||||||
mTitleLineEdit->setText( mLegend->title() );
|
mTitleLineEdit->setText( mLegend->title() );
|
||||||
mTitleAlignCombo->setCurrentIndex( alignment );
|
whileBlocking( mTitleAlignCombo )->setCurrentAlignment( mLegend->titleAlignment() );
|
||||||
|
whileBlocking( mGroupAlignCombo )->setCurrentAlignment( mLegend->style( QgsLegendStyle::Group ).alignment() );
|
||||||
|
whileBlocking( mSubgroupAlignCombo )->setCurrentAlignment( mLegend->style( QgsLegendStyle::Subgroup ).alignment() );
|
||||||
|
whileBlocking( mItemAlignCombo )->setCurrentAlignment( mLegend->style( QgsLegendStyle::SymbolLabel ).alignment() );
|
||||||
|
whileBlocking( mArrangementCombo )->setCurrentAlignment( mLegend->symbolAlignment() );
|
||||||
mFilterByMapToolButton->setChecked( mLegend->legendFilterByMapEnabled() );
|
mFilterByMapToolButton->setChecked( mLegend->legendFilterByMapEnabled() );
|
||||||
mColumnCountSpinBox->setValue( mLegend->columnCount() );
|
mColumnCountSpinBox->setValue( mLegend->columnCount() );
|
||||||
mSplitLayerCheckBox->setChecked( mLegend->splitLayer() );
|
mSplitLayerCheckBox->setChecked( mLegend->splitLayer() );
|
||||||
@ -240,11 +255,11 @@ void QgsLayoutLegendWidget::mTitleLineEdit_textChanged( const QString &text )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsLayoutLegendWidget::mTitleAlignCombo_currentIndexChanged( int index )
|
void QgsLayoutLegendWidget::titleAlignmentChanged()
|
||||||
{
|
{
|
||||||
if ( mLegend )
|
if ( mLegend )
|
||||||
{
|
{
|
||||||
Qt::AlignmentFlag alignment = index == 0 ? Qt::AlignLeft : index == 1 ? Qt::AlignHCenter : Qt::AlignRight;
|
Qt::AlignmentFlag alignment = static_cast< Qt::AlignmentFlag >( static_cast< int >( mTitleAlignCombo->currentAlignment() & Qt::AlignHorizontal_Mask ) );
|
||||||
mLegend->beginCommand( tr( "Change Title Alignment" ) );
|
mLegend->beginCommand( tr( "Change Title Alignment" ) );
|
||||||
mLegend->setTitleAlignment( alignment );
|
mLegend->setTitleAlignment( alignment );
|
||||||
mLegend->update();
|
mLegend->update();
|
||||||
@ -252,6 +267,51 @@ void QgsLayoutLegendWidget::mTitleAlignCombo_currentIndexChanged( int index )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QgsLayoutLegendWidget::groupAlignmentChanged()
|
||||||
|
{
|
||||||
|
if ( mLegend )
|
||||||
|
{
|
||||||
|
mLegend->beginCommand( tr( "Change Group Alignment" ) );
|
||||||
|
mLegend->rstyle( QgsLegendStyle::Group ).setAlignment( mGroupAlignCombo->currentAlignment() );
|
||||||
|
mLegend->update();
|
||||||
|
mLegend->endCommand();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsLayoutLegendWidget::subgroupAlignmentChanged()
|
||||||
|
{
|
||||||
|
if ( mLegend )
|
||||||
|
{
|
||||||
|
mLegend->beginCommand( tr( "Change Subgroup Alignment" ) );
|
||||||
|
mLegend->rstyle( QgsLegendStyle::Subgroup ).setAlignment( mSubgroupAlignCombo->currentAlignment() );
|
||||||
|
mLegend->update();
|
||||||
|
mLegend->endCommand();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsLayoutLegendWidget::itemAlignmentChanged()
|
||||||
|
{
|
||||||
|
if ( mLegend )
|
||||||
|
{
|
||||||
|
mLegend->beginCommand( tr( "Change Item Alignment" ) );
|
||||||
|
mLegend->rstyle( QgsLegendStyle::SymbolLabel ).setAlignment( mItemAlignCombo->currentAlignment() );
|
||||||
|
mLegend->update();
|
||||||
|
mLegend->endCommand();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsLayoutLegendWidget::arrangementChanged()
|
||||||
|
{
|
||||||
|
if ( mLegend )
|
||||||
|
{
|
||||||
|
Qt::AlignmentFlag alignment = static_cast< Qt::AlignmentFlag >( static_cast< int >( mArrangementCombo->currentAlignment() & Qt::AlignHorizontal_Mask ) );
|
||||||
|
mLegend->beginCommand( tr( "Change Legend Arrangement" ) );
|
||||||
|
mLegend->setSymbolAlignment( alignment );
|
||||||
|
mLegend->update();
|
||||||
|
mLegend->endCommand();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void QgsLayoutLegendWidget::mColumnCountSpinBox_valueChanged( int c )
|
void QgsLayoutLegendWidget::mColumnCountSpinBox_valueChanged( int c )
|
||||||
{
|
{
|
||||||
if ( mLegend )
|
if ( mLegend )
|
||||||
@ -1053,7 +1113,7 @@ void QgsLayoutLegendWidget::setCurrentNodeStyleFromAction()
|
|||||||
if ( !a || !mItemTreeView->currentNode() )
|
if ( !a || !mItemTreeView->currentNode() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QgsLegendRenderer::setNodeLegendStyle( mItemTreeView->currentNode(), ( QgsLegendStyle::Style ) a->data().toInt() );
|
QgsLegendRenderer::setNodeLegendStyle( mItemTreeView->currentNode(), static_cast< QgsLegendStyle::Style >( a->data().toInt() ) );
|
||||||
mLegend->updateFilterByMap();
|
mLegend->updateFilterByMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1175,7 +1235,7 @@ QMenu *QgsLayoutLegendMenuProvider::createContextMenu()
|
|||||||
QAction *action = menu->addAction( QgsLegendStyle::styleLabel( style ), mWidget, &QgsLayoutLegendWidget::setCurrentNodeStyleFromAction );
|
QAction *action = menu->addAction( QgsLegendStyle::styleLabel( style ), mWidget, &QgsLayoutLegendWidget::setCurrentNodeStyleFromAction );
|
||||||
action->setCheckable( true );
|
action->setCheckable( true );
|
||||||
action->setChecked( currentStyle == style );
|
action->setChecked( currentStyle == style );
|
||||||
action->setData( ( int ) style );
|
action->setData( static_cast< int >( style ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
return menu;
|
return menu;
|
||||||
|
|||||||
@ -49,7 +49,6 @@ class QgsLayoutLegendWidget: public QgsLayoutItemBaseWidget, private Ui::QgsLayo
|
|||||||
|
|
||||||
void mWrapCharLineEdit_textChanged( const QString &text );
|
void mWrapCharLineEdit_textChanged( const QString &text );
|
||||||
void mTitleLineEdit_textChanged( const QString &text );
|
void mTitleLineEdit_textChanged( const QString &text );
|
||||||
void mTitleAlignCombo_currentIndexChanged( int index );
|
|
||||||
void mColumnCountSpinBox_valueChanged( int c );
|
void mColumnCountSpinBox_valueChanged( int c );
|
||||||
void mSplitLayerCheckBox_toggled( bool checked );
|
void mSplitLayerCheckBox_toggled( bool checked );
|
||||||
void mEqualColumnWidthCheckBox_toggled( bool checked );
|
void mEqualColumnWidthCheckBox_toggled( bool checked );
|
||||||
@ -108,6 +107,12 @@ class QgsLayoutLegendWidget: public QgsLayoutItemBaseWidget, private Ui::QgsLayo
|
|||||||
void layerFontChanged();
|
void layerFontChanged();
|
||||||
void itemFontChanged();
|
void itemFontChanged();
|
||||||
|
|
||||||
|
void titleAlignmentChanged();
|
||||||
|
void groupAlignmentChanged();
|
||||||
|
void subgroupAlignmentChanged();
|
||||||
|
void itemAlignmentChanged();
|
||||||
|
void arrangementChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QgsLayoutLegendWidget() = delete;
|
QgsLayoutLegendWidget() = delete;
|
||||||
void blockAllSignals( bool b );
|
void blockAllSignals( bool b );
|
||||||
|
|||||||
@ -84,8 +84,27 @@ QSizeF QgsLayerTreeModelLegendNode::drawSymbol( const QgsLegendSettings &setting
|
|||||||
return QSizeF();
|
return QSizeF();
|
||||||
|
|
||||||
if ( ctx && ctx->painter )
|
if ( ctx && ctx->painter )
|
||||||
symbolIcon.paint( ctx->painter, ctx->point.x(), ctx->point.y() + ( itemHeight - settings.symbolSize().height() ) / 2,
|
{
|
||||||
settings.symbolSize().width(), settings.symbolSize().height() );
|
switch ( settings.symbolAlignment() )
|
||||||
|
{
|
||||||
|
case Qt::AlignLeft:
|
||||||
|
default:
|
||||||
|
symbolIcon.paint( ctx->painter,
|
||||||
|
static_cast< int >( ctx->columnLeft ),
|
||||||
|
static_cast< int >( ctx->top + ( itemHeight - settings.symbolSize().height() ) / 2 ),
|
||||||
|
static_cast< int >( settings.symbolSize().width() ),
|
||||||
|
static_cast< int >( settings.symbolSize().height() ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Qt::AlignRight:
|
||||||
|
symbolIcon.paint( ctx->painter,
|
||||||
|
static_cast< int >( ctx->columnRight - settings.symbolSize().width() ),
|
||||||
|
static_cast< int >( ctx->top + ( itemHeight - settings.symbolSize().height() ) / 2 ),
|
||||||
|
static_cast< int >( settings.symbolSize().width() ),
|
||||||
|
static_cast< int >( settings.symbolSize().height() ) );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
return settings.symbolSize();
|
return settings.symbolSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,13 +136,34 @@ QSizeF QgsLayerTreeModelLegendNode::drawSymbolText( const QgsLegendSettings &set
|
|||||||
|
|
||||||
labelSize.rheight() = lines.count() * textHeight + ( lines.count() - 1 ) * ( settings.lineSpacing() + textDescent );
|
labelSize.rheight() = lines.count() * textHeight + ( lines.count() - 1 ) * ( settings.lineSpacing() + textDescent );
|
||||||
|
|
||||||
double labelX = 0.0, labelY = 0.0;
|
double labelXMin = 0.0;
|
||||||
|
double labelXMax = 0.0;
|
||||||
|
double labelY = 0.0;
|
||||||
if ( ctx && ctx->painter )
|
if ( ctx && ctx->painter )
|
||||||
{
|
{
|
||||||
ctx->painter->setPen( settings.fontColor() );
|
ctx->painter->setPen( settings.fontColor() );
|
||||||
|
switch ( settings.symbolAlignment() )
|
||||||
|
{
|
||||||
|
case Qt::AlignLeft:
|
||||||
|
default:
|
||||||
|
labelXMin = ctx->columnLeft + std::max( static_cast< double >( symbolSize.width() ), ctx->maxSiblingSymbolWidth )
|
||||||
|
+ settings.style( QgsLegendStyle::Symbol ).margin( QgsLegendStyle::Right )
|
||||||
|
+ settings.style( QgsLegendStyle::SymbolLabel ).margin( QgsLegendStyle::Left );
|
||||||
|
labelXMax = ctx->columnRight;
|
||||||
|
break;
|
||||||
|
|
||||||
labelX = ctx->point.x() + std::max( static_cast< double >( symbolSize.width() ), ctx->labelXOffset );
|
case Qt::AlignRight:
|
||||||
labelY = ctx->point.y();
|
labelXMin = ctx->columnLeft;
|
||||||
|
// NOTE -- while the below calculations use the flipped margins from the style, that's only done because
|
||||||
|
// those are the only margins we expose and use for now! (and we expose them as generic margins, not side-specific
|
||||||
|
// ones) TODO when/if we expose other margin settings, these should be reversed...
|
||||||
|
labelXMax = ctx->columnRight - std::max( static_cast< double >( symbolSize.width() ), ctx->maxSiblingSymbolWidth )
|
||||||
|
- settings.style( QgsLegendStyle::Symbol ).margin( QgsLegendStyle::Right )
|
||||||
|
- settings.style( QgsLegendStyle::SymbolLabel ).margin( QgsLegendStyle::Left );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
labelY = ctx->top;
|
||||||
|
|
||||||
// Vertical alignment of label with symbol
|
// Vertical alignment of label with symbol
|
||||||
if ( labelSize.height() < symbolSize.height() )
|
if ( labelSize.height() < symbolSize.height() )
|
||||||
@ -134,11 +174,27 @@ QSizeF QgsLayerTreeModelLegendNode::drawSymbolText( const QgsLegendSettings &set
|
|||||||
|
|
||||||
for ( QStringList::ConstIterator itemPart = lines.constBegin(); itemPart != lines.constEnd(); ++itemPart )
|
for ( QStringList::ConstIterator itemPart = lines.constBegin(); itemPart != lines.constEnd(); ++itemPart )
|
||||||
{
|
{
|
||||||
labelSize.rwidth() = std::max( settings.textWidthMillimeters( symbolLabelFont, *itemPart ), double( labelSize.width() ) );
|
const double lineWidth = settings.textWidthMillimeters( symbolLabelFont, *itemPart );
|
||||||
|
labelSize.rwidth() = std::max( lineWidth, double( labelSize.width() ) );
|
||||||
|
|
||||||
if ( ctx && ctx->painter )
|
if ( ctx && ctx->painter )
|
||||||
{
|
{
|
||||||
settings.drawText( ctx->painter, labelX, labelY, *itemPart, symbolLabelFont );
|
switch ( settings.style( QgsLegendStyle::SymbolLabel ).alignment() )
|
||||||
|
{
|
||||||
|
case Qt::AlignLeft:
|
||||||
|
default:
|
||||||
|
settings.drawText( ctx->painter, labelXMin, labelY, *itemPart, symbolLabelFont );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Qt::AlignRight:
|
||||||
|
settings.drawText( ctx->painter, labelXMax - lineWidth, labelY, *itemPart, symbolLabelFont );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Qt::AlignHCenter:
|
||||||
|
settings.drawText( ctx->painter, labelXMin + ( labelXMax - labelXMin - lineWidth ) / 2.0, labelY, *itemPart, symbolLabelFont );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if ( itemPart != ( lines.end() - 1 ) )
|
if ( itemPart != ( lines.end() - 1 ) )
|
||||||
labelY += textDescent + settings.lineSpacing() + textHeight;
|
labelY += textDescent + settings.lineSpacing() + textHeight;
|
||||||
}
|
}
|
||||||
@ -462,8 +518,7 @@ QSizeF QgsSymbolLegendNode::drawSymbol( const QgsLegendSettings &settings, ItemC
|
|||||||
|
|
||||||
if ( ctx && ctx->painter )
|
if ( ctx && ctx->painter )
|
||||||
{
|
{
|
||||||
double currentXPosition = ctx->point.x();
|
double currentYCoord = ctx->top + ( itemHeight - settings.symbolSize().height() ) / 2;
|
||||||
double currentYCoord = ctx->point.y() + ( itemHeight - settings.symbolSize().height() ) / 2;
|
|
||||||
QPainter *p = ctx->painter;
|
QPainter *p = ctx->painter;
|
||||||
|
|
||||||
//setup painter scaling to dots so that raster symbology is drawn to scale
|
//setup painter scaling to dots so that raster symbology is drawn to scale
|
||||||
@ -475,7 +530,18 @@ QSizeF QgsSymbolLegendNode::drawSymbol( const QgsLegendSettings &settings, ItemC
|
|||||||
|
|
||||||
p->save();
|
p->save();
|
||||||
p->setRenderHint( QPainter::Antialiasing );
|
p->setRenderHint( QPainter::Antialiasing );
|
||||||
p->translate( currentXPosition + widthOffset, currentYCoord + heightOffset );
|
|
||||||
|
switch ( settings.symbolAlignment() )
|
||||||
|
{
|
||||||
|
case Qt::AlignLeft:
|
||||||
|
default:
|
||||||
|
p->translate( ctx->columnLeft + widthOffset, currentYCoord + heightOffset );
|
||||||
|
break;
|
||||||
|
case Qt::AlignRight:
|
||||||
|
p->translate( ctx->columnRight - widthOffset - width, currentYCoord + heightOffset );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
p->scale( 1.0 / dotsPerMM, 1.0 / dotsPerMM );
|
p->scale( 1.0 / dotsPerMM, 1.0 / dotsPerMM );
|
||||||
if ( opacity != 255 && settings.useAdvancedEffects() )
|
if ( opacity != 255 && settings.useAdvancedEffects() )
|
||||||
{
|
{
|
||||||
@ -659,8 +725,19 @@ QSizeF QgsImageLegendNode::drawSymbol( const QgsLegendSettings &settings, ItemCo
|
|||||||
|
|
||||||
if ( ctx && ctx->painter )
|
if ( ctx && ctx->painter )
|
||||||
{
|
{
|
||||||
ctx->painter->drawImage( QRectF( ctx->point.x(), ctx->point.y(), settings.wmsLegendSize().width(), settings.wmsLegendSize().height() ),
|
switch ( settings.symbolAlignment() )
|
||||||
|
{
|
||||||
|
case Qt::AlignLeft:
|
||||||
|
default:
|
||||||
|
ctx->painter->drawImage( QRectF( ctx->columnLeft, ctx->top, settings.wmsLegendSize().width(), settings.wmsLegendSize().height() ),
|
||||||
mImage, QRectF( 0, 0, mImage.width(), mImage.height() ) );
|
mImage, QRectF( 0, 0, mImage.width(), mImage.height() ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Qt::AlignRight:
|
||||||
|
ctx->painter->drawImage( QRectF( ctx->columnRight - settings.wmsLegendSize().width(), ctx->top, settings.wmsLegendSize().width(), settings.wmsLegendSize().height() ),
|
||||||
|
mImage, QRectF( 0, 0, mImage.width(), mImage.height() ) );
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return settings.wmsLegendSize();
|
return settings.wmsLegendSize();
|
||||||
}
|
}
|
||||||
@ -724,8 +801,19 @@ QSizeF QgsRasterSymbolLegendNode::drawSymbol( const QgsLegendSettings &settings,
|
|||||||
ctx->painter->setPen( Qt::NoPen );
|
ctx->painter->setPen( Qt::NoPen );
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->painter->drawRect( QRectF( ctx->point.x(), ctx->point.y() + ( itemHeight - settings.symbolSize().height() ) / 2,
|
switch ( settings.symbolAlignment() )
|
||||||
|
{
|
||||||
|
case Qt::AlignLeft:
|
||||||
|
default:
|
||||||
|
ctx->painter->drawRect( QRectF( ctx->columnLeft, ctx->top + ( itemHeight - settings.symbolSize().height() ) / 2,
|
||||||
settings.symbolSize().width(), settings.symbolSize().height() ) );
|
settings.symbolSize().width(), settings.symbolSize().height() ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Qt::AlignRight:
|
||||||
|
ctx->painter->drawRect( QRectF( ctx->columnRight - settings.symbolSize().width(), ctx->top + ( itemHeight - settings.symbolSize().height() ) / 2,
|
||||||
|
settings.symbolSize().width(), settings.symbolSize().height() ) );
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return settings.symbolSize();
|
return settings.symbolSize();
|
||||||
}
|
}
|
||||||
@ -829,9 +917,27 @@ QSizeF QgsWmsLegendNode::drawSymbol( const QgsLegendSettings &settings, ItemCont
|
|||||||
|
|
||||||
if ( ctx && ctx->painter )
|
if ( ctx && ctx->painter )
|
||||||
{
|
{
|
||||||
ctx->painter->drawImage( QRectF( ctx->point, settings.wmsLegendSize() ),
|
switch ( settings.symbolAlignment() )
|
||||||
|
{
|
||||||
|
case Qt::AlignLeft:
|
||||||
|
default:
|
||||||
|
ctx->painter->drawImage( QRectF( ctx->columnLeft,
|
||||||
|
ctx->top,
|
||||||
|
settings.wmsLegendSize().width(),
|
||||||
|
settings.wmsLegendSize().height() ),
|
||||||
mImage,
|
mImage,
|
||||||
QRectF( QPointF( 0, 0 ), mImage.size() ) );
|
QRectF( QPointF( 0, 0 ), mImage.size() ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Qt::AlignRight:
|
||||||
|
ctx->painter->drawImage( QRectF( ctx->columnRight - settings.wmsLegendSize().width(),
|
||||||
|
ctx->top,
|
||||||
|
settings.wmsLegendSize().width(),
|
||||||
|
settings.wmsLegendSize().height() ),
|
||||||
|
mImage,
|
||||||
|
QRectF( QPointF( 0, 0 ), mImage.size() ) );
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return settings.wmsLegendSize();
|
return settings.wmsLegendSize();
|
||||||
}
|
}
|
||||||
@ -958,7 +1064,7 @@ QgsLayerTreeModelLegendNode::ItemMetrics QgsDataDefinedSizeLegendNode::draw( con
|
|||||||
context.setPainter( ctx->painter );
|
context.setPainter( ctx->painter );
|
||||||
ctx->painter->save();
|
ctx->painter->save();
|
||||||
ctx->painter->setRenderHint( QPainter::Antialiasing );
|
ctx->painter->setRenderHint( QPainter::Antialiasing );
|
||||||
ctx->painter->translate( ctx->point );
|
ctx->painter->translate( ctx->columnLeft, ctx->top );
|
||||||
ctx->painter->scale( 1 / context.scaleFactor(), 1 / context.scaleFactor() );
|
ctx->painter->scale( 1 / context.scaleFactor(), 1 / context.scaleFactor() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -86,14 +86,56 @@ class CORE_EXPORT QgsLayerTreeModelLegendNode : public QObject
|
|||||||
|
|
||||||
struct ItemContext
|
struct ItemContext
|
||||||
{
|
{
|
||||||
|
Q_NOWARN_DEPRECATED_PUSH //because of deprecated members
|
||||||
|
ItemContext() = default;
|
||||||
|
Q_NOWARN_DEPRECATED_POP
|
||||||
|
|
||||||
//! Render context, if available
|
//! Render context, if available
|
||||||
QgsRenderContext *context = nullptr;
|
QgsRenderContext *context = nullptr;
|
||||||
//! Painter
|
//! Painter
|
||||||
QPainter *painter = nullptr;
|
QPainter *painter = nullptr;
|
||||||
//! Top-left corner of the legend item
|
|
||||||
QPointF point;
|
/**
|
||||||
//! offset from the left side where label should start
|
* Top-left corner of the legend item.
|
||||||
double labelXOffset;
|
* \deprecated Use top, columnLeft, columnRight instead.
|
||||||
|
*/
|
||||||
|
Q_DECL_DEPRECATED QPointF point;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Offset from the left side where label should start.
|
||||||
|
* \deprecated use columnLeft, columnRight instead.
|
||||||
|
*/
|
||||||
|
Q_DECL_DEPRECATED double labelXOffset = 0.0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Top y-position of legend item.
|
||||||
|
* \since QGIS 3.10
|
||||||
|
*/
|
||||||
|
double top = 0.0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Left side of current legend column. This should be used when determining
|
||||||
|
* where to render legend item content, correctly respecting the symbol and text
|
||||||
|
* alignment from the legend settings.
|
||||||
|
* \since QGIS 3.10
|
||||||
|
*/
|
||||||
|
double columnLeft = 0.0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Right side of current legend column. This should be used when determining
|
||||||
|
* where to render legend item content, correctly respecting the symbol and text
|
||||||
|
* alignment from the legend settings.
|
||||||
|
* \since QGIS 3.10
|
||||||
|
*/
|
||||||
|
double columnRight = 0.0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Largest symbol width, considering all other sibling legend components associated with
|
||||||
|
* the current component.
|
||||||
|
* \since QGIS 3.10
|
||||||
|
*/
|
||||||
|
double maxSiblingSymbolWidth = 0.0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ItemMetrics
|
struct ItemMetrics
|
||||||
|
|||||||
@ -139,6 +139,7 @@ void QgsLayoutItemLegend::paint( QPainter *painter, const QStyleOptionGraphicsIt
|
|||||||
attemptResize( newSize );
|
attemptResize( newSize );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsLayoutItem::paint( painter, itemStyle, pWidget );
|
QgsLayoutItem::paint( painter, itemStyle, pWidget );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -366,6 +367,16 @@ void QgsLayoutItemLegend::setSymbolWidth( double w )
|
|||||||
mSettings.setSymbolSize( QSizeF( w, mSettings.symbolSize().height() ) );
|
mSettings.setSymbolSize( QSizeF( w, mSettings.symbolSize().height() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QgsLayoutItemLegend::setSymbolAlignment( Qt::AlignmentFlag alignment )
|
||||||
|
{
|
||||||
|
mSettings.setSymbolAlignment( alignment );
|
||||||
|
}
|
||||||
|
|
||||||
|
Qt::AlignmentFlag QgsLayoutItemLegend::symbolAlignment() const
|
||||||
|
{
|
||||||
|
return mSettings.symbolAlignment();
|
||||||
|
}
|
||||||
|
|
||||||
double QgsLayoutItemLegend::symbolHeight() const
|
double QgsLayoutItemLegend::symbolHeight() const
|
||||||
{
|
{
|
||||||
return mSettings.symbolSize().height();
|
return mSettings.symbolSize().height();
|
||||||
@ -488,6 +499,10 @@ bool QgsLayoutItemLegend::writePropertiesToElement( QDomElement &legendElem, QDo
|
|||||||
|
|
||||||
legendElem.setAttribute( QStringLiteral( "symbolWidth" ), QString::number( mSettings.symbolSize().width() ) );
|
legendElem.setAttribute( QStringLiteral( "symbolWidth" ), QString::number( mSettings.symbolSize().width() ) );
|
||||||
legendElem.setAttribute( QStringLiteral( "symbolHeight" ), QString::number( mSettings.symbolSize().height() ) );
|
legendElem.setAttribute( QStringLiteral( "symbolHeight" ), QString::number( mSettings.symbolSize().height() ) );
|
||||||
|
|
||||||
|
legendElem.setAttribute( QStringLiteral( "symbolAlignment" ), mSettings.symbolAlignment() );
|
||||||
|
|
||||||
|
legendElem.setAttribute( QStringLiteral( "symbolAlignment" ), mSettings.symbolAlignment() );
|
||||||
legendElem.setAttribute( QStringLiteral( "lineSpacing" ), QString::number( mSettings.lineSpacing() ) );
|
legendElem.setAttribute( QStringLiteral( "lineSpacing" ), QString::number( mSettings.lineSpacing() ) );
|
||||||
|
|
||||||
legendElem.setAttribute( QStringLiteral( "rasterBorder" ), mSettings.drawRasterStroke() );
|
legendElem.setAttribute( QStringLiteral( "rasterBorder" ), mSettings.drawRasterStroke() );
|
||||||
@ -577,6 +592,8 @@ bool QgsLayoutItemLegend::readPropertiesFromElement( const QDomElement &itemElem
|
|||||||
mSettings.setColumnSpace( itemElem.attribute( QStringLiteral( "columnSpace" ), QStringLiteral( "2.0" ) ).toDouble() );
|
mSettings.setColumnSpace( itemElem.attribute( QStringLiteral( "columnSpace" ), QStringLiteral( "2.0" ) ).toDouble() );
|
||||||
|
|
||||||
mSettings.setSymbolSize( QSizeF( itemElem.attribute( QStringLiteral( "symbolWidth" ), QStringLiteral( "7.0" ) ).toDouble(), itemElem.attribute( QStringLiteral( "symbolHeight" ), QStringLiteral( "14.0" ) ).toDouble() ) );
|
mSettings.setSymbolSize( QSizeF( itemElem.attribute( QStringLiteral( "symbolWidth" ), QStringLiteral( "7.0" ) ).toDouble(), itemElem.attribute( QStringLiteral( "symbolHeight" ), QStringLiteral( "14.0" ) ).toDouble() ) );
|
||||||
|
mSettings.setSymbolAlignment( static_cast< Qt::AlignmentFlag >( itemElem.attribute( QStringLiteral( "symbolAlignment" ), QString::number( Qt::AlignLeft ) ).toInt() ) );
|
||||||
|
|
||||||
mSettings.setWmsLegendSize( QSizeF( itemElem.attribute( QStringLiteral( "wmsLegendWidth" ), QStringLiteral( "50" ) ).toDouble(), itemElem.attribute( QStringLiteral( "wmsLegendHeight" ), QStringLiteral( "25" ) ).toDouble() ) );
|
mSettings.setWmsLegendSize( QSizeF( itemElem.attribute( QStringLiteral( "wmsLegendWidth" ), QStringLiteral( "50" ) ).toDouble(), itemElem.attribute( QStringLiteral( "wmsLegendHeight" ), QStringLiteral( "25" ) ).toDouble() ) );
|
||||||
mSettings.setLineSpacing( itemElem.attribute( QStringLiteral( "lineSpacing" ), QStringLiteral( "1.0" ) ).toDouble() );
|
mSettings.setLineSpacing( itemElem.attribute( QStringLiteral( "lineSpacing" ), QStringLiteral( "1.0" ) ).toDouble() );
|
||||||
|
|
||||||
@ -776,7 +793,7 @@ void QgsLayoutItemLegend::doUpdateFilterByMap()
|
|||||||
|
|
||||||
if ( mMap && ( mLegendFilterByMap || filterByExpression || mInAtlas ) )
|
if ( mMap && ( mLegendFilterByMap || filterByExpression || mInAtlas ) )
|
||||||
{
|
{
|
||||||
int dpi = mLayout->renderContext().dpi();
|
double dpi = mLayout->renderContext().dpi();
|
||||||
|
|
||||||
QgsRectangle requestRectangle = mMap->requestedExtent();
|
QgsRectangle requestRectangle = mMap->requestedExtent();
|
||||||
|
|
||||||
|
|||||||
@ -266,6 +266,26 @@ class CORE_EXPORT QgsLayoutItemLegend : public QgsLayoutItem
|
|||||||
*/
|
*/
|
||||||
void setSymbolWidth( double width );
|
void setSymbolWidth( double width );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the \a alignment for placement of legend symbols.
|
||||||
|
*
|
||||||
|
* Only Qt::AlignLeft or Qt::AlignRight are supported values.
|
||||||
|
*
|
||||||
|
* \see symbolAlignment()
|
||||||
|
* \since QGIS 3.10.0
|
||||||
|
*/
|
||||||
|
void setSymbolAlignment( Qt::AlignmentFlag alignment );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the alignment for placement of legend symbols.
|
||||||
|
*
|
||||||
|
* Only Qt::AlignLeft or Qt::AlignRight are supported values.
|
||||||
|
*
|
||||||
|
* \see setSymbolAlignment()
|
||||||
|
* \since QGIS 3.10.0
|
||||||
|
*/
|
||||||
|
Qt::AlignmentFlag symbolAlignment() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the legend symbol height.
|
* Returns the legend symbol height.
|
||||||
* \see setSymbolHeight()
|
* \see setSymbolHeight()
|
||||||
|
|||||||
@ -129,19 +129,38 @@ QSizeF QgsLegendRenderer::paintAndDetermineSizeInternal( QgsRenderContext *conte
|
|||||||
if ( !rootGroup )
|
if ( !rootGroup )
|
||||||
return size;
|
return size;
|
||||||
|
|
||||||
QList<Atom> atomList = createAtomList( rootGroup, mSettings.splitLayer() );
|
QList<LegendComponentGroup> atomList = createComponentGroupList( rootGroup, mSettings.splitLayer() );
|
||||||
|
|
||||||
setColumns( atomList );
|
setColumns( atomList );
|
||||||
|
|
||||||
qreal maxColumnWidth = 0;
|
// another iteration -- this one is required to calculate the maximum item width for each
|
||||||
|
// column. Unfortunately, we can't trust the atom widths at this stage, as they are minimal widths
|
||||||
|
// only. When actually rendering a symbol node, the text is aligned according to the WIDEST
|
||||||
|
// symbol in a column. So that means we can't possibly determine the exact size of legend components
|
||||||
|
// until now. BUUUUUUUUUUUUT. Because everything sucks, we can't even start the actual render of items
|
||||||
|
// at the same time we calculate this -- legend items REQUIRE the REAL width of the columns in order to
|
||||||
|
// correctly align right or center-aligned symbols/text. Bah -- A triple iteration it is!
|
||||||
|
QMap< int, double > maxColumnWidths;
|
||||||
|
qreal maxEqualColumnWidth = 0;
|
||||||
|
// temporarily remove painter from context -- we don't need to actually draw anything yet. But we DO need
|
||||||
|
// to send the full render context so that an expression context is available during the size calculation
|
||||||
|
QPainter *prevPainter = context ? context->painter() : nullptr;
|
||||||
|
if ( context )
|
||||||
|
context->setPainter( nullptr );
|
||||||
|
for ( const LegendComponentGroup &atom : qgis::as_const( atomList ) )
|
||||||
|
{
|
||||||
|
const QSizeF actualSize = drawGroup( atom, context, ColumnContext() );
|
||||||
if ( mSettings.equalColumnWidth() )
|
if ( mSettings.equalColumnWidth() )
|
||||||
{
|
{
|
||||||
const auto constAtomList = atomList;
|
maxEqualColumnWidth = std::max( actualSize.width(), maxEqualColumnWidth );
|
||||||
for ( const Atom &atom : constAtomList )
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
maxColumnWidth = std::max( atom.size.width(), maxColumnWidth );
|
maxColumnWidths[ atom.column ] = std::max( actualSize.width(), maxColumnWidths.value( atom.column, 0 ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ( context )
|
||||||
|
context->setPainter( prevPainter );
|
||||||
|
|
||||||
//calculate size of title
|
//calculate size of title
|
||||||
QSizeF titleSize = drawTitle();
|
QSizeF titleSize = drawTitle();
|
||||||
@ -149,48 +168,46 @@ QSizeF QgsLegendRenderer::paintAndDetermineSizeInternal( QgsRenderContext *conte
|
|||||||
titleSize.rwidth() += mSettings.boxSpace() * 2.0;
|
titleSize.rwidth() += mSettings.boxSpace() * 2.0;
|
||||||
double columnTop = mSettings.boxSpace() + titleSize.height() + mSettings.style( QgsLegendStyle::Title ).margin( QgsLegendStyle::Bottom );
|
double columnTop = mSettings.boxSpace() + titleSize.height() + mSettings.style( QgsLegendStyle::Title ).margin( QgsLegendStyle::Bottom );
|
||||||
|
|
||||||
QPointF point( mSettings.boxSpace(), columnTop );
|
|
||||||
bool firstInColumn = true;
|
bool firstInColumn = true;
|
||||||
double columnMaxHeight = 0;
|
double columnMaxHeight = 0;
|
||||||
qreal columnWidth = 0;
|
qreal columnWidth = 0;
|
||||||
int column = 0;
|
int column = -1;
|
||||||
const auto constAtomList = atomList;
|
ColumnContext columnContext;
|
||||||
for ( const Atom &atom : constAtomList )
|
columnContext.left = mSettings.boxSpace();
|
||||||
|
columnContext.right = mLegendSize.width() - mSettings.boxSpace();
|
||||||
|
double currentY = columnTop;
|
||||||
|
|
||||||
|
for ( const LegendComponentGroup &atom : qgis::as_const( atomList ) )
|
||||||
{
|
{
|
||||||
if ( atom.column > column )
|
if ( atom.column > column )
|
||||||
{
|
{
|
||||||
// Switch to next column
|
// Switch to next column
|
||||||
if ( mSettings.equalColumnWidth() )
|
columnContext.left = atom.column > 0 ? columnContext.right + mSettings.columnSpace() : mSettings.boxSpace();
|
||||||
{
|
columnWidth = mSettings.equalColumnWidth() ? maxEqualColumnWidth : maxColumnWidths.value( atom.column );
|
||||||
point.rx() += mSettings.columnSpace() + maxColumnWidth;
|
columnContext.right = columnContext.left + columnWidth;
|
||||||
}
|
currentY = columnTop;
|
||||||
else
|
|
||||||
{
|
|
||||||
point.rx() += mSettings.columnSpace() + columnWidth;
|
|
||||||
}
|
|
||||||
point.ry() = columnTop;
|
|
||||||
columnWidth = 0;
|
|
||||||
column++;
|
column++;
|
||||||
firstInColumn = true;
|
firstInColumn = true;
|
||||||
}
|
}
|
||||||
if ( !firstInColumn )
|
if ( !firstInColumn )
|
||||||
{
|
{
|
||||||
point.ry() += spaceAboveAtom( atom );
|
currentY += spaceAboveGroup( atom );
|
||||||
}
|
}
|
||||||
|
|
||||||
QSizeF atomSize = context ? drawAtom( atom, context, point )
|
if ( context )
|
||||||
: drawAtom( atom, painter, point );
|
drawGroup( atom, context, columnContext, currentY );
|
||||||
columnWidth = std::max( atomSize.width(), columnWidth );
|
else if ( painter )
|
||||||
|
drawGroup( atom, columnContext, painter, currentY );
|
||||||
|
|
||||||
point.ry() += atom.size.height();
|
currentY += atom.size.height();
|
||||||
columnMaxHeight = std::max( point.y() - columnTop, columnMaxHeight );
|
columnMaxHeight = std::max( currentY - columnTop, columnMaxHeight );
|
||||||
|
|
||||||
firstInColumn = false;
|
firstInColumn = false;
|
||||||
}
|
}
|
||||||
point.rx() += columnWidth + mSettings.boxSpace();
|
const double totalWidth = columnContext.right + mSettings.boxSpace();
|
||||||
|
|
||||||
size.rheight() = columnTop + columnMaxHeight + mSettings.boxSpace();
|
size.rheight() = columnTop + columnMaxHeight + mSettings.boxSpace();
|
||||||
size.rwidth() = point.x();
|
size.rwidth() = totalWidth;
|
||||||
if ( !mSettings.title().isEmpty() )
|
if ( !mSettings.title().isEmpty() )
|
||||||
{
|
{
|
||||||
size.rwidth() = std::max( titleSize.width(), size.width() );
|
size.rwidth() = std::max( titleSize.width(), size.width() );
|
||||||
@ -207,32 +224,38 @@ QSizeF QgsLegendRenderer::paintAndDetermineSizeInternal( QgsRenderContext *conte
|
|||||||
// Now we have set the correct total item width and can draw the title centered
|
// Now we have set the correct total item width and can draw the title centered
|
||||||
if ( !mSettings.title().isEmpty() )
|
if ( !mSettings.title().isEmpty() )
|
||||||
{
|
{
|
||||||
if ( mSettings.titleAlignment() == Qt::AlignLeft )
|
|
||||||
{
|
|
||||||
point.rx() = mSettings.boxSpace();
|
|
||||||
}
|
|
||||||
else if ( mSettings.titleAlignment() == Qt::AlignHCenter )
|
|
||||||
{
|
|
||||||
point.rx() = size.width() / 2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
point.rx() = size.width() - mSettings.boxSpace();
|
|
||||||
}
|
|
||||||
point.ry() = mSettings.boxSpace();
|
|
||||||
if ( context )
|
if ( context )
|
||||||
drawTitle( context, point, mSettings.titleAlignment(), size.width() );
|
drawTitle( context, mSettings.boxSpace(), mSettings.titleAlignment(), size.width() );
|
||||||
else
|
else
|
||||||
drawTitle( painter, point, mSettings.titleAlignment(), size.width() );
|
drawTitle( painter, mSettings.boxSpace(), mSettings.titleAlignment(), size.width() );
|
||||||
}
|
}
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QgsLegendRenderer::widthAndOffsetForTitleText( const Qt::AlignmentFlag halignment, const double legendWidth, double &textBoxWidth, double &textBoxLeft )
|
||||||
QList<QgsLegendRenderer::Atom> QgsLegendRenderer::createAtomList( QgsLayerTreeGroup *parentGroup, bool splitLayer )
|
|
||||||
{
|
{
|
||||||
QList<Atom> atoms;
|
switch ( halignment )
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
textBoxLeft = mSettings.boxSpace();
|
||||||
|
textBoxWidth = legendWidth - 2 * mSettings.boxSpace();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Qt::AlignHCenter:
|
||||||
|
{
|
||||||
|
// not sure on this logic, I just moved it -- don't blame me for it being totally obscure!
|
||||||
|
const double centerX = legendWidth / 2;
|
||||||
|
textBoxWidth = ( std::min( static_cast< double >( centerX ), legendWidth - centerX ) - mSettings.boxSpace() ) * 2.0;
|
||||||
|
textBoxLeft = centerX - textBoxWidth / 2.;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QgsLegendRenderer::LegendComponentGroup> QgsLegendRenderer::createComponentGroupList( QgsLayerTreeGroup *parentGroup, bool splitLayer )
|
||||||
|
{
|
||||||
|
QList<LegendComponentGroup> atoms;
|
||||||
|
|
||||||
if ( !parentGroup ) return atoms;
|
if ( !parentGroup ) return atoms;
|
||||||
|
|
||||||
@ -244,29 +267,29 @@ QList<QgsLegendRenderer::Atom> QgsLegendRenderer::createAtomList( QgsLayerTreeGr
|
|||||||
QgsLayerTreeGroup *nodeGroup = QgsLayerTree::toGroup( node );
|
QgsLayerTreeGroup *nodeGroup = QgsLayerTree::toGroup( node );
|
||||||
|
|
||||||
// Group subitems
|
// Group subitems
|
||||||
QList<Atom> groupAtoms = createAtomList( nodeGroup, splitLayer );
|
QList<LegendComponentGroup> groupAtoms = createComponentGroupList( nodeGroup, splitLayer );
|
||||||
bool hasSubItems = !groupAtoms.empty();
|
bool hasSubItems = !groupAtoms.empty();
|
||||||
|
|
||||||
if ( nodeLegendStyle( nodeGroup ) != QgsLegendStyle::Hidden )
|
if ( nodeLegendStyle( nodeGroup ) != QgsLegendStyle::Hidden )
|
||||||
{
|
{
|
||||||
Nucleon nucleon;
|
LegendComponent nucleon;
|
||||||
nucleon.item = node;
|
nucleon.item = node;
|
||||||
nucleon.size = drawGroupTitle( nodeGroup );
|
nucleon.size = drawGroupTitle( nodeGroup );
|
||||||
|
|
||||||
if ( !groupAtoms.isEmpty() )
|
if ( !groupAtoms.isEmpty() )
|
||||||
{
|
{
|
||||||
// Add internal space between this group title and the next nucleon
|
// Add internal space between this group title and the next nucleon
|
||||||
groupAtoms[0].size.rheight() += spaceAboveAtom( groupAtoms[0] );
|
groupAtoms[0].size.rheight() += spaceAboveGroup( groupAtoms[0] );
|
||||||
// Prepend this group title to the first atom
|
// Prepend this group title to the first atom
|
||||||
groupAtoms[0].nucleons.prepend( nucleon );
|
groupAtoms[0].components.prepend( nucleon );
|
||||||
groupAtoms[0].size.rheight() += nucleon.size.height();
|
groupAtoms[0].size.rheight() += nucleon.size.height();
|
||||||
groupAtoms[0].size.rwidth() = std::max( nucleon.size.width(), groupAtoms[0].size.width() );
|
groupAtoms[0].size.rwidth() = std::max( nucleon.size.width(), groupAtoms[0].size.width() );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// no subitems, append new atom
|
// no subitems, append new atom
|
||||||
Atom atom;
|
LegendComponentGroup atom;
|
||||||
atom.nucleons.append( nucleon );
|
atom.components.append( nucleon );
|
||||||
atom.size.rwidth() += nucleon.size.width();
|
atom.size.rwidth() += nucleon.size.width();
|
||||||
atom.size.rheight() += nucleon.size.height();
|
atom.size.rheight() += nucleon.size.height();
|
||||||
atom.size.rwidth() = std::max( nucleon.size.width(), atom.size.width() );
|
atom.size.rwidth() = std::max( nucleon.size.width(), atom.size.width() );
|
||||||
@ -284,14 +307,14 @@ QList<QgsLegendRenderer::Atom> QgsLegendRenderer::createAtomList( QgsLayerTreeGr
|
|||||||
{
|
{
|
||||||
QgsLayerTreeLayer *nodeLayer = QgsLayerTree::toLayer( node );
|
QgsLayerTreeLayer *nodeLayer = QgsLayerTree::toLayer( node );
|
||||||
|
|
||||||
Atom atom;
|
LegendComponentGroup atom;
|
||||||
|
|
||||||
if ( nodeLegendStyle( nodeLayer ) != QgsLegendStyle::Hidden )
|
if ( nodeLegendStyle( nodeLayer ) != QgsLegendStyle::Hidden )
|
||||||
{
|
{
|
||||||
Nucleon nucleon;
|
LegendComponent nucleon;
|
||||||
nucleon.item = node;
|
nucleon.item = node;
|
||||||
nucleon.size = drawLayerTitle( nodeLayer );
|
nucleon.size = drawLayerTitle( nodeLayer );
|
||||||
atom.nucleons.append( nucleon );
|
atom.components.append( nucleon );
|
||||||
atom.size.rwidth() = nucleon.size.width();
|
atom.size.rwidth() = nucleon.size.width();
|
||||||
atom.size.rheight() = nucleon.size.height();
|
atom.size.rheight() = nucleon.size.height();
|
||||||
}
|
}
|
||||||
@ -304,13 +327,13 @@ QList<QgsLegendRenderer::Atom> QgsLegendRenderer::createAtomList( QgsLayerTreeGr
|
|||||||
if ( legendNodes.isEmpty() && mLegendModel->legendFilterMapSettings() )
|
if ( legendNodes.isEmpty() && mLegendModel->legendFilterMapSettings() )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
QList<Atom> layerAtoms;
|
QList<LegendComponentGroup> layerAtoms;
|
||||||
|
|
||||||
for ( int j = 0; j < legendNodes.count(); j++ )
|
for ( int j = 0; j < legendNodes.count(); j++ )
|
||||||
{
|
{
|
||||||
QgsLayerTreeModelLegendNode *legendNode = legendNodes.at( j );
|
QgsLayerTreeModelLegendNode *legendNode = legendNodes.at( j );
|
||||||
|
|
||||||
Nucleon symbolNucleon = drawSymbolItem( legendNode );
|
LegendComponent symbolNucleon = drawSymbolItem( legendNode );
|
||||||
|
|
||||||
if ( !mSettings.splitLayer() || j == 0 )
|
if ( !mSettings.splitLayer() || j == 0 )
|
||||||
{
|
{
|
||||||
@ -318,18 +341,18 @@ QList<QgsLegendRenderer::Atom> QgsLegendRenderer::createAtomList( QgsLayerTreeGr
|
|||||||
// the width is not correct at this moment, we must align all symbol labels
|
// the width is not correct at this moment, we must align all symbol labels
|
||||||
atom.size.rwidth() = std::max( symbolNucleon.size.width(), atom.size.width() );
|
atom.size.rwidth() = std::max( symbolNucleon.size.width(), atom.size.width() );
|
||||||
// Add symbol space only if there is already title or another item above
|
// Add symbol space only if there is already title or another item above
|
||||||
if ( !atom.nucleons.isEmpty() )
|
if ( !atom.components.isEmpty() )
|
||||||
{
|
{
|
||||||
// TODO: for now we keep Symbol and SymbolLabel Top margin in sync
|
// TODO: for now we keep Symbol and SymbolLabel Top margin in sync
|
||||||
atom.size.rheight() += mSettings.style( QgsLegendStyle::Symbol ).margin( QgsLegendStyle::Top );
|
atom.size.rheight() += mSettings.style( QgsLegendStyle::Symbol ).margin( QgsLegendStyle::Top );
|
||||||
}
|
}
|
||||||
atom.size.rheight() += symbolNucleon.size.height();
|
atom.size.rheight() += symbolNucleon.size.height();
|
||||||
atom.nucleons.append( symbolNucleon );
|
atom.components.append( symbolNucleon );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Atom symbolAtom;
|
LegendComponentGroup symbolAtom;
|
||||||
symbolAtom.nucleons.append( symbolNucleon );
|
symbolAtom.components.append( symbolNucleon );
|
||||||
symbolAtom.size.rwidth() = symbolNucleon.size.width();
|
symbolAtom.size.rwidth() = symbolNucleon.size.width();
|
||||||
symbolAtom.size.rheight() = symbolNucleon.size.height();
|
symbolAtom.size.rheight() = symbolNucleon.size.height();
|
||||||
layerAtoms.append( symbolAtom );
|
layerAtoms.append( symbolAtom );
|
||||||
@ -344,7 +367,7 @@ QList<QgsLegendRenderer::Atom> QgsLegendRenderer::createAtomList( QgsLayerTreeGr
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void QgsLegendRenderer::setColumns( QList<Atom> &atomList )
|
void QgsLegendRenderer::setColumns( QList<LegendComponentGroup> &atomList )
|
||||||
{
|
{
|
||||||
if ( mSettings.columnCount() == 0 ) return;
|
if ( mSettings.columnCount() == 0 ) return;
|
||||||
|
|
||||||
@ -352,9 +375,9 @@ void QgsLegendRenderer::setColumns( QList<Atom> &atomList )
|
|||||||
double totalHeight = 0;
|
double totalHeight = 0;
|
||||||
qreal maxAtomHeight = 0;
|
qreal maxAtomHeight = 0;
|
||||||
const auto constAtomList = atomList;
|
const auto constAtomList = atomList;
|
||||||
for ( const Atom &atom : constAtomList )
|
for ( const LegendComponentGroup &atom : constAtomList )
|
||||||
{
|
{
|
||||||
totalHeight += spaceAboveAtom( atom );
|
totalHeight += spaceAboveGroup( atom );
|
||||||
totalHeight += atom.size.height();
|
totalHeight += atom.size.height();
|
||||||
maxAtomHeight = std::max( atom.size.height(), maxAtomHeight );
|
maxAtomHeight = std::max( atom.size.height(), maxAtomHeight );
|
||||||
}
|
}
|
||||||
@ -375,10 +398,10 @@ void QgsLegendRenderer::setColumns( QList<Atom> &atomList )
|
|||||||
// Recalc average height for remaining columns including current
|
// Recalc average height for remaining columns including current
|
||||||
double avgColumnHeight = ( totalHeight - closedColumnsHeight ) / ( mSettings.columnCount() - currentColumn );
|
double avgColumnHeight = ( totalHeight - closedColumnsHeight ) / ( mSettings.columnCount() - currentColumn );
|
||||||
|
|
||||||
Atom atom = atomList.at( i );
|
LegendComponentGroup atom = atomList.at( i );
|
||||||
double currentHeight = currentColumnHeight;
|
double currentHeight = currentColumnHeight;
|
||||||
if ( currentColumnAtomCount > 0 )
|
if ( currentColumnAtomCount > 0 )
|
||||||
currentHeight += spaceAboveAtom( atom );
|
currentHeight += spaceAboveGroup( atom );
|
||||||
currentHeight += atom.size.height();
|
currentHeight += atom.size.height();
|
||||||
|
|
||||||
bool canCreateNewColumn = ( currentColumnAtomCount > 0 ) // do not leave empty column
|
bool canCreateNewColumn = ( currentColumnAtomCount > 0 ) // do not leave empty column
|
||||||
@ -414,39 +437,40 @@ void QgsLegendRenderer::setColumns( QList<Atom> &atomList )
|
|||||||
QMap<QString, qreal> maxSymbolWidth;
|
QMap<QString, qreal> maxSymbolWidth;
|
||||||
for ( int i = 0; i < atomList.size(); i++ )
|
for ( int i = 0; i < atomList.size(); i++ )
|
||||||
{
|
{
|
||||||
Atom &atom = atomList[i];
|
LegendComponentGroup &atom = atomList[i];
|
||||||
for ( int j = 0; j < atom.nucleons.size(); j++ )
|
for ( int j = 0; j < atom.components.size(); j++ )
|
||||||
{
|
{
|
||||||
if ( QgsLayerTreeModelLegendNode *legendNode = qobject_cast<QgsLayerTreeModelLegendNode *>( atom.nucleons.at( j ).item ) )
|
if ( QgsLayerTreeModelLegendNode *legendNode = qobject_cast<QgsLayerTreeModelLegendNode *>( atom.components.at( j ).item ) )
|
||||||
{
|
{
|
||||||
QString key = QStringLiteral( "%1-%2" ).arg( reinterpret_cast< qulonglong >( legendNode->layerNode() ) ).arg( atom.column );
|
QString key = QStringLiteral( "%1-%2" ).arg( reinterpret_cast< qulonglong >( legendNode->layerNode() ) ).arg( atom.column );
|
||||||
maxSymbolWidth[key] = std::max( atom.nucleons.at( j ).symbolSize.width(), maxSymbolWidth[key] );
|
maxSymbolWidth[key] = std::max( atom.components.at( j ).symbolSize.width(), maxSymbolWidth[key] );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for ( int i = 0; i < atomList.size(); i++ )
|
for ( int i = 0; i < atomList.size(); i++ )
|
||||||
{
|
{
|
||||||
Atom &atom = atomList[i];
|
LegendComponentGroup &atom = atomList[i];
|
||||||
for ( int j = 0; j < atom.nucleons.size(); j++ )
|
for ( int j = 0; j < atom.components.size(); j++ )
|
||||||
{
|
{
|
||||||
if ( QgsLayerTreeModelLegendNode *legendNode = qobject_cast<QgsLayerTreeModelLegendNode *>( atom.nucleons.at( j ).item ) )
|
if ( QgsLayerTreeModelLegendNode *legendNode = qobject_cast<QgsLayerTreeModelLegendNode *>( atom.components.at( j ).item ) )
|
||||||
{
|
{
|
||||||
QString key = QStringLiteral( "%1-%2" ).arg( reinterpret_cast< qulonglong >( legendNode->layerNode() ) ).arg( atom.column );
|
QString key = QStringLiteral( "%1-%2" ).arg( reinterpret_cast< qulonglong >( legendNode->layerNode() ) ).arg( atom.column );
|
||||||
double space = mSettings.style( QgsLegendStyle::Symbol ).margin( QgsLegendStyle::Right ) +
|
double space = mSettings.style( QgsLegendStyle::Symbol ).margin( QgsLegendStyle::Right ) +
|
||||||
mSettings.style( QgsLegendStyle::SymbolLabel ).margin( QgsLegendStyle::Left );
|
mSettings.style( QgsLegendStyle::SymbolLabel ).margin( QgsLegendStyle::Left );
|
||||||
atom.nucleons[j].labelXOffset = maxSymbolWidth[key] + space;
|
atom.components[j].labelXOffset = maxSymbolWidth[key] + space;
|
||||||
atom.nucleons[j].size.rwidth() = maxSymbolWidth[key] + space + atom.nucleons.at( j ).labelSize.width();
|
atom.components[j].maxSiblingSymbolWidth = maxSymbolWidth[key];
|
||||||
|
atom.components[j].size.rwidth() = maxSymbolWidth[key] + space + atom.components.at( j ).labelSize.width();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QSizeF QgsLegendRenderer::drawTitle( QPainter *painter, QPointF point, Qt::AlignmentFlag halignment, double legendWidth )
|
QSizeF QgsLegendRenderer::drawTitle( QPainter *painter, double top, Qt::AlignmentFlag halignment, double legendWidth )
|
||||||
{
|
{
|
||||||
return drawTitleInternal( nullptr, painter, point, halignment, legendWidth );
|
return drawTitleInternal( nullptr, painter, top, halignment, legendWidth );
|
||||||
}
|
}
|
||||||
|
|
||||||
QSizeF QgsLegendRenderer::drawTitleInternal( QgsRenderContext *context, QPainter *painter, QPointF point, Qt::AlignmentFlag halignment, double legendWidth )
|
QSizeF QgsLegendRenderer::drawTitleInternal( QgsRenderContext *context, QPainter *painter, const double top, Qt::AlignmentFlag halignment, double legendWidth )
|
||||||
{
|
{
|
||||||
QSizeF size( 0, 0 );
|
QSizeF size( 0, 0 );
|
||||||
if ( mSettings.title().isEmpty() )
|
if ( mSettings.title().isEmpty() )
|
||||||
@ -455,7 +479,7 @@ QSizeF QgsLegendRenderer::drawTitleInternal( QgsRenderContext *context, QPainter
|
|||||||
}
|
}
|
||||||
|
|
||||||
QStringList lines = mSettings.splitStringForWrapping( mSettings.title() );
|
QStringList lines = mSettings.splitStringForWrapping( mSettings.title() );
|
||||||
double y = point.y();
|
double y = top;
|
||||||
|
|
||||||
if ( context && context->painter() )
|
if ( context && context->painter() )
|
||||||
{
|
{
|
||||||
@ -469,22 +493,7 @@ QSizeF QgsLegendRenderer::drawTitleInternal( QgsRenderContext *context, QPainter
|
|||||||
//calculate width and left pos of rectangle to draw text into
|
//calculate width and left pos of rectangle to draw text into
|
||||||
double textBoxWidth;
|
double textBoxWidth;
|
||||||
double textBoxLeft;
|
double textBoxLeft;
|
||||||
switch ( halignment )
|
widthAndOffsetForTitleText( halignment, legendWidth, textBoxWidth, textBoxLeft );
|
||||||
{
|
|
||||||
case Qt::AlignHCenter:
|
|
||||||
textBoxWidth = ( std::min( static_cast< double >( point.x() ), legendWidth - point.x() ) - mSettings.boxSpace() ) * 2.0;
|
|
||||||
textBoxLeft = point.x() - textBoxWidth / 2.;
|
|
||||||
break;
|
|
||||||
case Qt::AlignRight:
|
|
||||||
textBoxLeft = mSettings.boxSpace();
|
|
||||||
textBoxWidth = point.x() - mSettings.boxSpace();
|
|
||||||
break;
|
|
||||||
case Qt::AlignLeft:
|
|
||||||
default:
|
|
||||||
textBoxLeft = point.x();
|
|
||||||
textBoxWidth = legendWidth - point.x() - mSettings.boxSpace();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
QFont titleFont = mSettings.style( QgsLegendStyle::Title ).font();
|
QFont titleFont = mSettings.style( QgsLegendStyle::Title ).font();
|
||||||
|
|
||||||
@ -515,17 +524,17 @@ QSizeF QgsLegendRenderer::drawTitleInternal( QgsRenderContext *context, QPainter
|
|||||||
y += mSettings.lineSpacing();
|
y += mSettings.lineSpacing();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
size.rheight() = y - point.y();
|
size.rheight() = y - top;
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
double QgsLegendRenderer::spaceAboveAtom( const Atom &atom )
|
double QgsLegendRenderer::spaceAboveGroup( const LegendComponentGroup &atom )
|
||||||
{
|
{
|
||||||
if ( atom.nucleons.isEmpty() ) return 0;
|
if ( atom.components.isEmpty() ) return 0;
|
||||||
|
|
||||||
Nucleon nucleon = atom.nucleons.first();
|
LegendComponent nucleon = atom.components.first();
|
||||||
|
|
||||||
if ( QgsLayerTreeGroup *nodeGroup = qobject_cast<QgsLayerTreeGroup *>( nucleon.item ) )
|
if ( QgsLayerTreeGroup *nodeGroup = qobject_cast<QgsLayerTreeGroup *>( nucleon.item ) )
|
||||||
{
|
{
|
||||||
@ -546,16 +555,17 @@ double QgsLegendRenderer::spaceAboveAtom( const Atom &atom )
|
|||||||
|
|
||||||
|
|
||||||
// Draw atom and expand its size (using actual nucleons labelXOffset)
|
// Draw atom and expand its size (using actual nucleons labelXOffset)
|
||||||
QSizeF QgsLegendRenderer::drawAtom( const Atom &atom, QPainter *painter, QPointF point )
|
QSizeF QgsLegendRenderer::drawGroup( const LegendComponentGroup &atom, const ColumnContext &columnContext, QPainter *painter, double top )
|
||||||
{
|
{
|
||||||
return drawAtomInternal( atom, nullptr, painter, point );
|
return drawGroupInternal( atom, nullptr, columnContext, painter, top );
|
||||||
}
|
}
|
||||||
|
|
||||||
QSizeF QgsLegendRenderer::drawAtomInternal( const Atom &atom, QgsRenderContext *context, QPainter *painter, QPointF point )
|
QSizeF QgsLegendRenderer::drawGroupInternal( const LegendComponentGroup &atom, QgsRenderContext *context, const ColumnContext &columnContext, QPainter *painter, const double top )
|
||||||
{
|
{
|
||||||
bool first = true;
|
bool first = true;
|
||||||
QSizeF size = QSizeF( atom.size );
|
QSizeF size = QSizeF( atom.size );
|
||||||
for ( const Nucleon &nucleon : qgis::as_const( atom.nucleons ) )
|
double currentY = top;
|
||||||
|
for ( const LegendComponent &nucleon : qgis::as_const( atom.components ) )
|
||||||
{
|
{
|
||||||
if ( QgsLayerTreeGroup *groupItem = qobject_cast<QgsLayerTreeGroup *>( nucleon.item ) )
|
if ( QgsLayerTreeGroup *groupItem = qobject_cast<QgsLayerTreeGroup *>( nucleon.item ) )
|
||||||
{
|
{
|
||||||
@ -564,12 +574,12 @@ QSizeF QgsLegendRenderer::drawAtomInternal( const Atom &atom, QgsRenderContext *
|
|||||||
{
|
{
|
||||||
if ( !first )
|
if ( !first )
|
||||||
{
|
{
|
||||||
point.ry() += mSettings.style( s ).margin( QgsLegendStyle::Top );
|
currentY += mSettings.style( s ).margin( QgsLegendStyle::Top );
|
||||||
}
|
}
|
||||||
if ( context )
|
if ( context )
|
||||||
drawGroupTitle( groupItem, context, point );
|
drawGroupTitle( groupItem, context, columnContext, currentY );
|
||||||
else
|
else
|
||||||
drawGroupTitle( groupItem, painter, point );
|
drawGroupTitle( groupItem, columnContext, painter, currentY );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ( QgsLayerTreeLayer *layerItem = qobject_cast<QgsLayerTreeLayer *>( nucleon.item ) )
|
else if ( QgsLayerTreeLayer *layerItem = qobject_cast<QgsLayerTreeLayer *>( nucleon.item ) )
|
||||||
@ -579,38 +589,38 @@ QSizeF QgsLegendRenderer::drawAtomInternal( const Atom &atom, QgsRenderContext *
|
|||||||
{
|
{
|
||||||
if ( !first )
|
if ( !first )
|
||||||
{
|
{
|
||||||
point.ry() += mSettings.style( s ).margin( QgsLegendStyle::Top );
|
currentY += mSettings.style( s ).margin( QgsLegendStyle::Top );
|
||||||
}
|
}
|
||||||
if ( context )
|
if ( context )
|
||||||
drawLayerTitle( layerItem, context, point );
|
drawLayerTitle( layerItem, context, columnContext, currentY );
|
||||||
else
|
else
|
||||||
drawLayerTitle( layerItem, painter, point );
|
drawLayerTitle( layerItem, columnContext, painter, currentY );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ( QgsLayerTreeModelLegendNode *legendNode = qobject_cast<QgsLayerTreeModelLegendNode *>( nucleon.item ) )
|
else if ( QgsLayerTreeModelLegendNode *legendNode = qobject_cast<QgsLayerTreeModelLegendNode *>( nucleon.item ) )
|
||||||
{
|
{
|
||||||
if ( !first )
|
if ( !first )
|
||||||
{
|
{
|
||||||
point.ry() += mSettings.style( QgsLegendStyle::Symbol ).margin( QgsLegendStyle::Top );
|
currentY += mSettings.style( QgsLegendStyle::Symbol ).margin( QgsLegendStyle::Top );
|
||||||
}
|
}
|
||||||
|
|
||||||
Nucleon symbolNucleon = context ? drawSymbolItem( legendNode, context, point, nucleon.labelXOffset )
|
LegendComponent symbolNucleon = context ? drawSymbolItem( legendNode, context, columnContext, currentY, nucleon.maxSiblingSymbolWidth )
|
||||||
: drawSymbolItem( legendNode, painter, point, nucleon.labelXOffset );
|
: drawSymbolItem( legendNode, columnContext, painter, currentY, nucleon.maxSiblingSymbolWidth );
|
||||||
// expand width, it may be wider because of labelXOffset
|
// expand width, it may be wider because of labelXOffset
|
||||||
size.rwidth() = std::max( symbolNucleon.size.width(), size.width() );
|
size.rwidth() = std::max( symbolNucleon.size.width(), size.width() );
|
||||||
}
|
}
|
||||||
point.ry() += nucleon.size.height();
|
currentY += nucleon.size.height();
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsLegendRenderer::Nucleon QgsLegendRenderer::drawSymbolItem( QgsLayerTreeModelLegendNode *symbolItem, QPainter *painter, QPointF point, double labelXOffset )
|
QgsLegendRenderer::LegendComponent QgsLegendRenderer::drawSymbolItem( QgsLayerTreeModelLegendNode *symbolItem, const ColumnContext &columnContext, QPainter *painter, double top, double maxSiblingSymbolWidth )
|
||||||
{
|
{
|
||||||
return drawSymbolItemInternal( symbolItem, nullptr, painter, point, labelXOffset );
|
return drawSymbolItemInternal( symbolItem, columnContext, nullptr, painter, top, maxSiblingSymbolWidth );
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsLegendRenderer::Nucleon QgsLegendRenderer::drawSymbolItemInternal( QgsLayerTreeModelLegendNode *symbolItem, QgsRenderContext *context, QPainter *painter, QPointF point, double labelXOffset )
|
QgsLegendRenderer::LegendComponent QgsLegendRenderer::drawSymbolItemInternal( QgsLayerTreeModelLegendNode *symbolItem, const ColumnContext &columnContext, QgsRenderContext *context, QPainter *painter, double top, double maxSiblingSymbolWidth )
|
||||||
{
|
{
|
||||||
QgsLayerTreeModelLegendNode::ItemContext ctx;
|
QgsLayerTreeModelLegendNode::ItemContext ctx;
|
||||||
ctx.context = context;
|
ctx.context = context;
|
||||||
@ -624,8 +634,15 @@ QgsLegendRenderer::Nucleon QgsLegendRenderer::drawSymbolItemInternal( QgsLayerTr
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx.painter = context ? context->painter() : painter;
|
ctx.painter = context ? context->painter() : painter;
|
||||||
ctx.point = point;
|
Q_NOWARN_DEPRECATED_PUSH
|
||||||
ctx.labelXOffset = labelXOffset;
|
ctx.point = QPointF( columnContext.left, top );
|
||||||
|
ctx.labelXOffset = maxSiblingSymbolWidth;
|
||||||
|
Q_NOWARN_DEPRECATED_POP
|
||||||
|
|
||||||
|
ctx.top = top;
|
||||||
|
ctx.columnLeft = columnContext.left;
|
||||||
|
ctx.columnRight = columnContext.right;
|
||||||
|
ctx.maxSiblingSymbolWidth = maxSiblingSymbolWidth;
|
||||||
|
|
||||||
QgsLayerTreeModelLegendNode::ItemMetrics im = symbolItem->draw( mSettings, context ? &ctx
|
QgsLayerTreeModelLegendNode::ItemMetrics im = symbolItem->draw( mSettings, context ? &ctx
|
||||||
: ( painter ? &ctx : nullptr ) );
|
: ( painter ? &ctx : nullptr ) );
|
||||||
@ -633,23 +650,30 @@ QgsLegendRenderer::Nucleon QgsLegendRenderer::drawSymbolItemInternal( QgsLayerTr
|
|||||||
if ( layerScope )
|
if ( layerScope )
|
||||||
delete context->expressionContext().popScope();
|
delete context->expressionContext().popScope();
|
||||||
|
|
||||||
Nucleon nucleon;
|
LegendComponent nucleon;
|
||||||
nucleon.item = symbolItem;
|
nucleon.item = symbolItem;
|
||||||
nucleon.symbolSize = im.symbolSize;
|
nucleon.symbolSize = im.symbolSize;
|
||||||
nucleon.labelSize = im.labelSize;
|
nucleon.labelSize = im.labelSize;
|
||||||
//QgsDebugMsg( QStringLiteral( "symbol height = %1 label height = %2").arg( symbolSize.height()).arg( labelSize.height() ));
|
//QgsDebugMsg( QStringLiteral( "symbol height = %1 label height = %2").arg( symbolSize.height()).arg( labelSize.height() ));
|
||||||
double width = std::max( static_cast< double >( im.symbolSize.width() ), labelXOffset ) + im.labelSize.width();
|
// NOTE -- we hard code left/right margins below, because those are the only ones exposed for use currently.
|
||||||
|
// ideally we could (should?) expose all these margins as settings, and then adapt the below to respect the current symbol/text alignment
|
||||||
|
// and consider the correct margin sides...
|
||||||
|
double width = std::max( static_cast< double >( im.symbolSize.width() ), maxSiblingSymbolWidth )
|
||||||
|
+ mSettings.style( QgsLegendStyle::Symbol ).margin( QgsLegendStyle::Right )
|
||||||
|
+ mSettings.style( QgsLegendStyle::SymbolLabel ).margin( QgsLegendStyle::Left )
|
||||||
|
+ im.labelSize.width();
|
||||||
|
|
||||||
double height = std::max( im.symbolSize.height(), im.labelSize.height() );
|
double height = std::max( im.symbolSize.height(), im.labelSize.height() );
|
||||||
nucleon.size = QSizeF( width, height );
|
nucleon.size = QSizeF( width, height );
|
||||||
return nucleon;
|
return nucleon;
|
||||||
}
|
}
|
||||||
|
|
||||||
QSizeF QgsLegendRenderer::drawLayerTitle( QgsLayerTreeLayer *nodeLayer, QPainter *painter, QPointF point )
|
QSizeF QgsLegendRenderer::drawLayerTitle( QgsLayerTreeLayer *nodeLayer, const ColumnContext &columnContext, QPainter *painter, double top )
|
||||||
{
|
{
|
||||||
return drawLayerTitleInternal( nodeLayer, nullptr, painter, point );
|
return drawLayerTitleInternal( nodeLayer, columnContext, nullptr, painter, top );
|
||||||
}
|
}
|
||||||
|
|
||||||
QSizeF QgsLegendRenderer::drawLayerTitleInternal( QgsLayerTreeLayer *nodeLayer, QgsRenderContext *context, QPainter *painter, QPointF point )
|
QSizeF QgsLegendRenderer::drawLayerTitleInternal( QgsLayerTreeLayer *nodeLayer, const ColumnContext &columnContext, QgsRenderContext *context, QPainter *painter, const double top )
|
||||||
{
|
{
|
||||||
QSizeF size( 0, 0 );
|
QSizeF size( 0, 0 );
|
||||||
QModelIndex idx = mLegendModel->node2index( nodeLayer );
|
QModelIndex idx = mLegendModel->node2index( nodeLayer );
|
||||||
@ -658,7 +682,7 @@ QSizeF QgsLegendRenderer::drawLayerTitleInternal( QgsLayerTreeLayer *nodeLayer,
|
|||||||
if ( mLegendModel->data( idx, Qt::DisplayRole ).toString().isEmpty() )
|
if ( mLegendModel->data( idx, Qt::DisplayRole ).toString().isEmpty() )
|
||||||
return size;
|
return size;
|
||||||
|
|
||||||
double y = point.y();
|
double y = top;
|
||||||
|
|
||||||
if ( context && context->painter() )
|
if ( context && context->painter() )
|
||||||
context->painter()->setPen( mSettings.layerFontColor() );
|
context->painter()->setPen( mSettings.layerFontColor() );
|
||||||
@ -678,21 +702,32 @@ QSizeF QgsLegendRenderer::drawLayerTitleInternal( QgsLayerTreeLayer *nodeLayer,
|
|||||||
|
|
||||||
const QStringList lines = mSettings.evaluateItemText( mLegendModel->data( idx, Qt::DisplayRole ).toString(),
|
const QStringList lines = mSettings.evaluateItemText( mLegendModel->data( idx, Qt::DisplayRole ).toString(),
|
||||||
context ? context->expressionContext() : tempContext );
|
context ? context->expressionContext() : tempContext );
|
||||||
|
int i = 0;
|
||||||
for ( QStringList::ConstIterator layerItemPart = lines.constBegin(); layerItemPart != lines.constEnd(); ++layerItemPart )
|
for ( QStringList::ConstIterator layerItemPart = lines.constBegin(); layerItemPart != lines.constEnd(); ++layerItemPart )
|
||||||
{
|
{
|
||||||
y += mSettings.fontAscentMillimeters( layerFont );
|
y += mSettings.fontAscentMillimeters( layerFont );
|
||||||
if ( context && context->painter() )
|
if ( QPainter *destPainter = context && context->painter() ? context->painter() : painter )
|
||||||
mSettings.drawText( context->painter(), point.x(), y, *layerItemPart, layerFont );
|
{
|
||||||
if ( painter )
|
double x = columnContext.left;
|
||||||
mSettings.drawText( painter, point.x(), y, *layerItemPart, layerFont );
|
if ( mSettings.style( nodeLegendStyle( nodeLayer ) ).alignment() != Qt::AlignLeft )
|
||||||
|
{
|
||||||
|
const double labelWidth = mSettings.textWidthMillimeters( layerFont, *layerItemPart );
|
||||||
|
if ( mSettings.style( nodeLegendStyle( nodeLayer ) ).alignment() == Qt::AlignRight )
|
||||||
|
x = columnContext.right - labelWidth;
|
||||||
|
else if ( mSettings.style( nodeLegendStyle( nodeLayer ) ).alignment() == Qt::AlignHCenter )
|
||||||
|
x = columnContext.left + ( columnContext.right - columnContext.left - labelWidth ) / 2;
|
||||||
|
}
|
||||||
|
mSettings.drawText( destPainter, x, y, *layerItemPart, layerFont );
|
||||||
|
}
|
||||||
qreal width = mSettings.textWidthMillimeters( layerFont, *layerItemPart );
|
qreal width = mSettings.textWidthMillimeters( layerFont, *layerItemPart );
|
||||||
size.rwidth() = std::max( width, size.width() );
|
size.rwidth() = std::max( width, size.width() );
|
||||||
if ( layerItemPart != ( lines.end() - 1 ) )
|
if ( layerItemPart != ( lines.end() - 1 ) )
|
||||||
{
|
{
|
||||||
y += mSettings.lineSpacing();
|
y += mSettings.lineSpacing();
|
||||||
}
|
}
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
size.rheight() = y - point.y();
|
size.rheight() = y - top;
|
||||||
size.rheight() += mSettings.style( nodeLegendStyle( nodeLayer ) ).margin( QgsLegendStyle::Side::Bottom );
|
size.rheight() += mSettings.style( nodeLegendStyle( nodeLayer ) ).margin( QgsLegendStyle::Side::Bottom );
|
||||||
|
|
||||||
if ( layerScope )
|
if ( layerScope )
|
||||||
@ -701,17 +736,17 @@ QSizeF QgsLegendRenderer::drawLayerTitleInternal( QgsLayerTreeLayer *nodeLayer,
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
QSizeF QgsLegendRenderer::drawGroupTitle( QgsLayerTreeGroup *nodeGroup, QPainter *painter, QPointF point )
|
QSizeF QgsLegendRenderer::drawGroupTitle( QgsLayerTreeGroup *nodeGroup, const ColumnContext &columnContext, QPainter *painter, double top )
|
||||||
{
|
{
|
||||||
return drawGroupTitleInternal( nodeGroup, nullptr, painter, point );
|
return drawGroupTitleInternal( nodeGroup, columnContext, nullptr, painter, top );
|
||||||
}
|
}
|
||||||
|
|
||||||
QSizeF QgsLegendRenderer::drawGroupTitleInternal( QgsLayerTreeGroup *nodeGroup, QgsRenderContext *context, QPainter *painter, QPointF point )
|
QSizeF QgsLegendRenderer::drawGroupTitleInternal( QgsLayerTreeGroup *nodeGroup, const ColumnContext &columnContext, QgsRenderContext *context, QPainter *painter, const double top )
|
||||||
{
|
{
|
||||||
QSizeF size( 0, 0 );
|
QSizeF size( 0, 0 );
|
||||||
QModelIndex idx = mLegendModel->node2index( nodeGroup );
|
QModelIndex idx = mLegendModel->node2index( nodeGroup );
|
||||||
|
|
||||||
double y = point.y();
|
double y = top;
|
||||||
|
|
||||||
if ( context && context->painter() )
|
if ( context && context->painter() )
|
||||||
context->painter()->setPen( mSettings.fontColor() );
|
context->painter()->setPen( mSettings.fontColor() );
|
||||||
@ -727,10 +762,20 @@ QSizeF QgsLegendRenderer::drawGroupTitleInternal( QgsLayerTreeGroup *nodeGroup,
|
|||||||
for ( QStringList::ConstIterator groupPart = lines.constBegin(); groupPart != lines.constEnd(); ++groupPart )
|
for ( QStringList::ConstIterator groupPart = lines.constBegin(); groupPart != lines.constEnd(); ++groupPart )
|
||||||
{
|
{
|
||||||
y += mSettings.fontAscentMillimeters( groupFont );
|
y += mSettings.fontAscentMillimeters( groupFont );
|
||||||
if ( context && context->painter() )
|
|
||||||
mSettings.drawText( context->painter(), point.x(), y, *groupPart, groupFont );
|
if ( QPainter *destPainter = context && context->painter() ? context->painter() : painter )
|
||||||
else if ( painter )
|
{
|
||||||
mSettings.drawText( painter, point.x(), y, *groupPart, groupFont );
|
double x = columnContext.left;
|
||||||
|
if ( mSettings.style( nodeLegendStyle( nodeGroup ) ).alignment() != Qt::AlignLeft )
|
||||||
|
{
|
||||||
|
const double labelWidth = mSettings.textWidthMillimeters( groupFont, *groupPart );
|
||||||
|
if ( mSettings.style( nodeLegendStyle( nodeGroup ) ).alignment() == Qt::AlignRight )
|
||||||
|
x = columnContext.right - labelWidth;
|
||||||
|
else if ( mSettings.style( nodeLegendStyle( nodeGroup ) ).alignment() == Qt::AlignHCenter )
|
||||||
|
x = columnContext.left + ( columnContext.right - columnContext.left - labelWidth ) / 2;
|
||||||
|
}
|
||||||
|
mSettings.drawText( destPainter, x, y, *groupPart, groupFont );
|
||||||
|
}
|
||||||
qreal width = mSettings.textWidthMillimeters( groupFont, *groupPart );
|
qreal width = mSettings.textWidthMillimeters( groupFont, *groupPart );
|
||||||
size.rwidth() = std::max( width, size.width() );
|
size.rwidth() = std::max( width, size.width() );
|
||||||
if ( groupPart != ( lines.end() - 1 ) )
|
if ( groupPart != ( lines.end() - 1 ) )
|
||||||
@ -738,7 +783,7 @@ QSizeF QgsLegendRenderer::drawGroupTitleInternal( QgsLayerTreeGroup *nodeGroup,
|
|||||||
y += mSettings.lineSpacing();
|
y += mSettings.lineSpacing();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
size.rheight() = y - point.y();
|
size.rheight() = y - top;
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -794,29 +839,29 @@ void QgsLegendRenderer::setNodeLegendStyle( QgsLayerTreeNode *node, QgsLegendSty
|
|||||||
node->removeCustomProperty( QStringLiteral( "legend/title-style" ) );
|
node->removeCustomProperty( QStringLiteral( "legend/title-style" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
QSizeF QgsLegendRenderer::drawTitle( QgsRenderContext *rendercontext, QPointF point, Qt::AlignmentFlag halignment, double legendWidth )
|
QSizeF QgsLegendRenderer::drawTitle( QgsRenderContext *rendercontext, double top, Qt::AlignmentFlag halignment, double legendWidth )
|
||||||
{
|
{
|
||||||
return drawTitleInternal( rendercontext, nullptr, point, halignment, legendWidth );
|
return drawTitleInternal( rendercontext, nullptr, top, halignment, legendWidth );
|
||||||
}
|
}
|
||||||
|
|
||||||
QSizeF QgsLegendRenderer::drawAtom( const Atom &atom, QgsRenderContext *rendercontext, QPointF point )
|
QSizeF QgsLegendRenderer::drawGroup( const LegendComponentGroup &atom, QgsRenderContext *rendercontext, const ColumnContext &columnContext, double top )
|
||||||
{
|
{
|
||||||
return drawAtomInternal( atom, rendercontext, nullptr, point );
|
return drawGroupInternal( atom, rendercontext, columnContext, nullptr, top );
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsLegendRenderer::Nucleon QgsLegendRenderer::drawSymbolItem( QgsLayerTreeModelLegendNode *symbolItem, QgsRenderContext *rendercontext, QPointF point, double labelXOffset )
|
QgsLegendRenderer::LegendComponent QgsLegendRenderer::drawSymbolItem( QgsLayerTreeModelLegendNode *symbolItem, QgsRenderContext *rendercontext, const ColumnContext &columnContext, double top, double maxSiblingSymbolWidth )
|
||||||
{
|
{
|
||||||
return drawSymbolItemInternal( symbolItem, rendercontext, nullptr, point, labelXOffset );
|
return drawSymbolItemInternal( symbolItem, columnContext, rendercontext, nullptr, top, maxSiblingSymbolWidth );
|
||||||
}
|
}
|
||||||
|
|
||||||
QSizeF QgsLegendRenderer::drawLayerTitle( QgsLayerTreeLayer *nodeLayer, QgsRenderContext *rendercontext, QPointF point )
|
QSizeF QgsLegendRenderer::drawLayerTitle( QgsLayerTreeLayer *nodeLayer, QgsRenderContext *rendercontext, const ColumnContext &columnContext, double top )
|
||||||
{
|
{
|
||||||
return drawLayerTitleInternal( nodeLayer, rendercontext, nullptr, point );
|
return drawLayerTitleInternal( nodeLayer, columnContext, rendercontext, nullptr, top );
|
||||||
}
|
}
|
||||||
|
|
||||||
QSizeF QgsLegendRenderer::drawGroupTitle( QgsLayerTreeGroup *nodeGroup, QgsRenderContext *rendercontext, QPointF point )
|
QSizeF QgsLegendRenderer::drawGroupTitle( QgsLayerTreeGroup *nodeGroup, QgsRenderContext *rendercontext, const ColumnContext &columnContext, double top )
|
||||||
{
|
{
|
||||||
return drawGroupTitleInternal( nodeGroup, rendercontext, nullptr, point );
|
return drawGroupTitleInternal( nodeGroup, columnContext, rendercontext, nullptr, top );
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsLegendRenderer::drawLegend( QgsRenderContext &context )
|
void QgsLegendRenderer::drawLegend( QgsRenderContext &context )
|
||||||
|
|||||||
@ -119,17 +119,17 @@ class CORE_EXPORT QgsLegendRenderer
|
|||||||
#ifndef SIP_RUN
|
#ifndef SIP_RUN
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A legend Nucleon is either a group title, a layer title or a layer child item.
|
* A legend component is either a group title, a layer title or a layer child item.
|
||||||
*
|
*
|
||||||
* E.g. a layer title nucleon is just the layer's title, it does not
|
* E.g. a layer title component is just the layer's title, it does not
|
||||||
* include all of that layer's subitems. Similarly, a group's title nucleon is just
|
* include all of that layer's subitems. Similarly, a group's title component is just
|
||||||
* the group title, and does not include the actual content of that group.
|
* the group title, and does not include the actual content of that group.
|
||||||
*/
|
*/
|
||||||
class Nucleon
|
class LegendComponent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
//! Constructor for Nuclean
|
|
||||||
Nucleon() = default;
|
LegendComponent() = default;
|
||||||
|
|
||||||
QObject *item = nullptr;
|
QObject *item = nullptr;
|
||||||
|
|
||||||
@ -139,7 +139,7 @@ class CORE_EXPORT QgsLegendRenderer
|
|||||||
//! Label size, not including any preset padding space around the label
|
//! Label size, not including any preset padding space around the label
|
||||||
QSizeF labelSize;
|
QSizeF labelSize;
|
||||||
|
|
||||||
//! Nucleon size
|
//! Component size
|
||||||
QSizeF size;
|
QSizeF size;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -149,12 +149,18 @@ class CORE_EXPORT QgsLegendRenderer
|
|||||||
* within the same legend column.
|
* within the same legend column.
|
||||||
*/
|
*/
|
||||||
double labelXOffset = 0.0;
|
double labelXOffset = 0.0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Largest symbol width, considering all other sibling components associated with
|
||||||
|
* this component.
|
||||||
|
*/
|
||||||
|
double maxSiblingSymbolWidth = 0.0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An Atom is indivisible set of legend Nucleons (i.e. it is indivisible into more columns).
|
* An component group is an indivisible set of legend components (i.e. it is indivisible into more columns).
|
||||||
*
|
*
|
||||||
* An Atom may consist of one or more Nucleon(s), depending on the layer splitting mode:
|
* A group may consist of one or more component(s), depending on the layer splitting mode:
|
||||||
*
|
*
|
||||||
* 1) no layer split: [group_title ...] layer_title layer_item [layer_item ...]
|
* 1) no layer split: [group_title ...] layer_title layer_item [layer_item ...]
|
||||||
* 2) layer split: [group_title ...] layer_title layer_item
|
* 2) layer split: [group_title ...] layer_title layer_item
|
||||||
@ -165,20 +171,38 @@ class CORE_EXPORT QgsLegendRenderer
|
|||||||
* and it would not be logical to leave a group or layer title at the bottom of a column,
|
* and it would not be logical to leave a group or layer title at the bottom of a column,
|
||||||
* separated from the actual content of that group or layer.
|
* separated from the actual content of that group or layer.
|
||||||
*/
|
*/
|
||||||
class Atom
|
class LegendComponentGroup
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
//! List of child Nucleons belonging to this Atom.
|
//! List of child components belonging to this group.
|
||||||
QList<Nucleon> nucleons;
|
QList<LegendComponent> components;
|
||||||
|
|
||||||
//! Atom size, including internal spacing between Nucleons, but excluding any padding space around the Atom itself.
|
//! Group size, including internal spacing between components, but excluding any padding space around the group itself.
|
||||||
QSizeF size = QSizeF( 0, 0 );
|
QSizeF size = QSizeF( 0, 0 );
|
||||||
|
|
||||||
//! Corresponding column index
|
//! Corresponding column index
|
||||||
int column = 0;
|
int column = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains contextual information about the current column being rendered
|
||||||
|
*/
|
||||||
|
class ColumnContext
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
ColumnContext()
|
||||||
|
: left( 0 )
|
||||||
|
, right( 0 )
|
||||||
|
{}
|
||||||
|
|
||||||
|
//! Left edge of column
|
||||||
|
double left = 0;
|
||||||
|
//! Right edge of column
|
||||||
|
double right = 0;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws the legend and returns the actual size of the legend.
|
* Draws the legend and returns the actual size of the legend.
|
||||||
*
|
*
|
||||||
@ -188,15 +212,15 @@ class CORE_EXPORT QgsLegendRenderer
|
|||||||
QSizeF paintAndDetermineSize( QPainter *painter = nullptr );
|
QSizeF paintAndDetermineSize( QPainter *painter = nullptr );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a list of Atoms for the specified \a parentGroup, respecting the current layer's
|
* Returns a list of component groups for the specified \a parentGroup, respecting the current layer's
|
||||||
* splitting settings.
|
* splitting settings.
|
||||||
*/
|
*/
|
||||||
QList<Atom> createAtomList( QgsLayerTreeGroup *parentGroup, bool splitLayer );
|
QList<LegendComponentGroup> createComponentGroupList( QgsLayerTreeGroup *parentGroup, bool splitLayer );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Divides a list of Atoms into columns, and sets the column index for each atom in the list.
|
* Divides a list of component groups into columns, and sets the column index for each group in the list.
|
||||||
*/
|
*/
|
||||||
void setColumns( QList<Atom> &atomList );
|
void setColumns( QList<LegendComponentGroup> &groupList );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws a title in the legend using the title font and the specified alignment settings.
|
* Draws a title in the legend using the title font and the specified alignment settings.
|
||||||
@ -205,25 +229,25 @@ class CORE_EXPORT QgsLegendRenderer
|
|||||||
*
|
*
|
||||||
* If \a painter is NULLPTR, no painting will be attempted, but the required size will still be calculated and returned.
|
* If \a painter is NULLPTR, no painting will be attempted, but the required size will still be calculated and returned.
|
||||||
*/
|
*/
|
||||||
QSizeF drawTitle( QPainter *painter = nullptr, QPointF point = QPointF(), Qt::AlignmentFlag halignment = Qt::AlignLeft, double legendWidth = 0 );
|
QSizeF drawTitle( QPainter *painter = nullptr, double top = 0, Qt::AlignmentFlag halignment = Qt::AlignLeft, double legendWidth = 0 );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the calculated padding space required above the given \a atom.
|
* Returns the calculated padding space required above the given component \a group.
|
||||||
*/
|
*/
|
||||||
double spaceAboveAtom( const Atom &atom );
|
double spaceAboveGroup( const LegendComponentGroup &group );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws an \a atom and return its actual size.
|
* Draws a component \a group and return its actual size.
|
||||||
*
|
*
|
||||||
* The \a atom is drawn with the space above it, so that the first atoms in column are all
|
* The \a group is drawn with the space above it, so that the first groups in a column are all
|
||||||
* aligned to the same line regardless of their style top spacing.
|
* aligned to the same line regardless of their style top spacing.
|
||||||
*/
|
*/
|
||||||
QSizeF drawAtom( const Atom &atom, QPainter *painter = nullptr, QPointF point = QPointF() );
|
QSizeF drawGroup( const LegendComponentGroup &group, const ColumnContext &columnContext, QPainter *painter = nullptr, double top = 0 );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws the symbol of a given symbol QgsLayerTreeModelLegendNode.
|
* Draws the symbol of a given symbol QgsLayerTreeModelLegendNode.
|
||||||
*/
|
*/
|
||||||
Nucleon drawSymbolItem( QgsLayerTreeModelLegendNode *symbolItem, QPainter *painter = nullptr, QPointF point = QPointF(), double labelXOffset = 0 );
|
LegendComponent drawSymbolItem( QgsLayerTreeModelLegendNode *symbolItem, const ColumnContext &columnContext = ColumnContext(), QPainter *painter = nullptr, double top = 0, double maxSiblingSymbolWidth = 0 );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws the title of a layer, given a QgsLayerTreeLayer, and a destination \a painter.
|
* Draws the title of a layer, given a QgsLayerTreeLayer, and a destination \a painter.
|
||||||
@ -232,13 +256,13 @@ class CORE_EXPORT QgsLegendRenderer
|
|||||||
*
|
*
|
||||||
* The \a painter may be NULLPTR, in which case on the size is calculated and no painting is attempted.
|
* The \a painter may be NULLPTR, in which case on the size is calculated and no painting is attempted.
|
||||||
*/
|
*/
|
||||||
QSizeF drawLayerTitle( QgsLayerTreeLayer *nodeLayer, QPainter *painter = nullptr, QPointF point = QPointF() );
|
QSizeF drawLayerTitle( QgsLayerTreeLayer *nodeLayer, const ColumnContext &columnContext = ColumnContext(), QPainter *painter = nullptr, double top = 0 );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws a group item.
|
* Draws a group item.
|
||||||
* Returns the size of the title.
|
* Returns the size of the title.
|
||||||
*/
|
*/
|
||||||
QSizeF drawGroupTitle( QgsLayerTreeGroup *nodeGroup, QPainter *painter = nullptr, QPointF point = QPointF() );
|
QSizeF drawGroupTitle( QgsLayerTreeGroup *nodeGroup, const ColumnContext &columnContext = ColumnContext(), QPainter *painter = nullptr, double top = 0 );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders a group item in a \a json object.
|
* Renders a group item in a \a json object.
|
||||||
@ -262,22 +286,22 @@ class CORE_EXPORT QgsLegendRenderer
|
|||||||
*
|
*
|
||||||
* If \a context is NULLPTR, no painting will be attempted, but the required size will still be calculated and returned.
|
* If \a context is NULLPTR, no painting will be attempted, but the required size will still be calculated and returned.
|
||||||
*/
|
*/
|
||||||
QSizeF drawTitle( QgsRenderContext *context, QPointF point = QPointF(), Qt::AlignmentFlag halignment = Qt::AlignLeft, double legendWidth = 0 );
|
QSizeF drawTitle( QgsRenderContext *context, double top, Qt::AlignmentFlag halignment = Qt::AlignLeft, double legendWidth = 0 );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws an \a atom and return its actual size, using the specified render \a context.
|
* Draws an \a group and return its actual size, using the specified render \a context.
|
||||||
*
|
*
|
||||||
* The \a atom is drawn with the space above it, so that the first atoms in column are all
|
* The \a group is drawn with the space above it, so that the first groups in a column are all
|
||||||
* aligned to the same line regardless of their style top spacing.
|
* aligned to the same line regardless of their style top spacing.
|
||||||
*
|
*
|
||||||
* If \a context is NULLPTR, no painting will be attempted, but the required size will still be calculated and returned.
|
* If \a context is NULLPTR, no painting will be attempted, but the required size will still be calculated and returned.
|
||||||
*/
|
*/
|
||||||
QSizeF drawAtom( const Atom &atom, QgsRenderContext *rendercontext, QPointF point = QPointF() );
|
QSizeF drawGroup( const LegendComponentGroup &group, QgsRenderContext *rendercontext, const ColumnContext &columnContext, double top = 0 );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws the symbol of a given symbol QgsLayerTreeModelLegendNode, using the specified render \a context.
|
* Draws the symbol of a given symbol QgsLayerTreeModelLegendNode, using the specified render \a context.
|
||||||
*/
|
*/
|
||||||
Nucleon drawSymbolItem( QgsLayerTreeModelLegendNode *symbolItem, QgsRenderContext *context, QPointF point = QPointF(), double labelXOffset = 0 );
|
LegendComponent drawSymbolItem( QgsLayerTreeModelLegendNode *symbolItem, QgsRenderContext *context, const ColumnContext &columnContext, double top, double maxSiblingSymbolWidth = 0 );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws the title of a layer, given a QgsLayerTreeLayer, and a destination render \a context.
|
* Draws the title of a layer, given a QgsLayerTreeLayer, and a destination render \a context.
|
||||||
@ -286,21 +310,20 @@ class CORE_EXPORT QgsLegendRenderer
|
|||||||
*
|
*
|
||||||
* The \a context may be NULLPTR, in which case on the size is calculated and no painting is attempted.
|
* The \a context may be NULLPTR, in which case on the size is calculated and no painting is attempted.
|
||||||
*/
|
*/
|
||||||
QSizeF drawLayerTitle( QgsLayerTreeLayer *nodeLayer, QgsRenderContext *context, QPointF point = QPointF() );
|
QSizeF drawLayerTitle( QgsLayerTreeLayer *nodeLayer, QgsRenderContext *context, const ColumnContext &columnContext, double top = 0 );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws a group's title, using the specified render \a context.
|
* Draws a group's title, using the specified render \a context.
|
||||||
*
|
*
|
||||||
* Returns the size of the title.
|
* Returns the size of the title.
|
||||||
*/
|
*/
|
||||||
QSizeF drawGroupTitle( QgsLayerTreeGroup *nodeGroup, QgsRenderContext *context, QPointF point = QPointF() );
|
QSizeF drawGroupTitle( QgsLayerTreeGroup *nodeGroup, QgsRenderContext *context, const ColumnContext &columnContext = ColumnContext(), double top = 0 );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the style of the given \a node.
|
* Returns the style of the given \a node.
|
||||||
*/
|
*/
|
||||||
QgsLegendStyle::Style nodeLegendStyle( QgsLayerTreeNode *node );
|
QgsLegendStyle::Style nodeLegendStyle( QgsLayerTreeNode *node );
|
||||||
|
|
||||||
private:
|
|
||||||
QgsLayerTreeModel *mLegendModel = nullptr;
|
QgsLayerTreeModel *mLegendModel = nullptr;
|
||||||
|
|
||||||
QgsLegendSettings mSettings;
|
QgsLegendSettings mSettings;
|
||||||
@ -308,12 +331,14 @@ class CORE_EXPORT QgsLegendRenderer
|
|||||||
QSizeF mLegendSize;
|
QSizeF mLegendSize;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
QSizeF drawTitleInternal( QgsRenderContext *context, QPainter *painter, QPointF point, Qt::AlignmentFlag halignment, double legendWidth );
|
QSizeF drawTitleInternal( QgsRenderContext *context, QPainter *painter, double top, Qt::AlignmentFlag halignment, double legendWidth );
|
||||||
QSizeF drawAtomInternal( const Atom &atom, QgsRenderContext *context, QPainter *painter, QPointF point );
|
QSizeF drawGroupInternal( const LegendComponentGroup &group, QgsRenderContext *context, const ColumnContext &columnContext, QPainter *painter, double top );
|
||||||
QgsLegendRenderer::Nucleon drawSymbolItemInternal( QgsLayerTreeModelLegendNode *symbolItem, QgsRenderContext *context, QPainter *painter, QPointF point, double labelXOffset );
|
QgsLegendRenderer::LegendComponent drawSymbolItemInternal( QgsLayerTreeModelLegendNode *symbolItem, const ColumnContext &columnContext, QgsRenderContext *context, QPainter *painter, double top, double maxSiblingSymbolWidth );
|
||||||
QSizeF drawLayerTitleInternal( QgsLayerTreeLayer *nodeLayer, QgsRenderContext *context, QPainter *painter, QPointF point );
|
QSizeF drawLayerTitleInternal( QgsLayerTreeLayer *nodeLayer, const ColumnContext &columnContext, QgsRenderContext *context, QPainter *painter, double top );
|
||||||
QSizeF drawGroupTitleInternal( QgsLayerTreeGroup *nodeGroup, QgsRenderContext *context, QPainter *painter, QPointF point );
|
QSizeF drawGroupTitleInternal( QgsLayerTreeGroup *nodeGroup, const ColumnContext &columnContext, QgsRenderContext *context, QPainter *painter, double top );
|
||||||
QSizeF paintAndDetermineSizeInternal( QgsRenderContext *context, QPainter *painter );
|
QSizeF paintAndDetermineSizeInternal( QgsRenderContext *context, QPainter *painter );
|
||||||
|
|
||||||
|
void widthAndOffsetForTitleText( const Qt::AlignmentFlag halignment, double legendWidth, double &width, double &offset );
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // QGSLEGENDRENDERER_H
|
#endif // QGSLEGENDRENDERER_H
|
||||||
|
|||||||
@ -44,16 +44,14 @@ class CORE_EXPORT QgsLegendSettings
|
|||||||
QString title() const { return mTitle; }
|
QString title() const { return mTitle; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the alignment of the legend title
|
* Returns the alignment of the legend title.
|
||||||
* \returns Qt::AlignmentFlag for the legend title
|
* \see setTitleAlignment()
|
||||||
* \see setTitleAlignment
|
|
||||||
*/
|
*/
|
||||||
Qt::AlignmentFlag titleAlignment() const { return mTitleAlignment; }
|
Qt::AlignmentFlag titleAlignment() const { return mTitleAlignment; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the alignment of the legend title
|
* Sets the \a alignment of the legend title.
|
||||||
* \param alignment Text alignment for drawing the legend title
|
* \see titleAlignment()
|
||||||
* \see titleAlignment
|
|
||||||
*/
|
*/
|
||||||
void setTitleAlignment( Qt::AlignmentFlag alignment ) { mTitleAlignment = alignment; }
|
void setTitleAlignment( Qt::AlignmentFlag alignment ) { mTitleAlignment = alignment; }
|
||||||
|
|
||||||
@ -109,6 +107,26 @@ class CORE_EXPORT QgsLegendSettings
|
|||||||
QSizeF symbolSize() const {return mSymbolSize;}
|
QSizeF symbolSize() const {return mSymbolSize;}
|
||||||
void setSymbolSize( QSizeF s ) {mSymbolSize = s;}
|
void setSymbolSize( QSizeF s ) {mSymbolSize = s;}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the \a alignment for placement of legend symbols.
|
||||||
|
*
|
||||||
|
* Only Qt::AlignLeft or Qt::AlignRight are supported values.
|
||||||
|
*
|
||||||
|
* \see symbolAlignment()
|
||||||
|
* \since QGIS 3.10.0
|
||||||
|
*/
|
||||||
|
void setSymbolAlignment( Qt::AlignmentFlag alignment ) { mSymbolAlignment = alignment; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the alignment for placement of legend symbols.
|
||||||
|
*
|
||||||
|
* Only Qt::AlignLeft or Qt::AlignRight are supported values.
|
||||||
|
*
|
||||||
|
* \see setSymbolAlignment()
|
||||||
|
* \since QGIS 3.10.0
|
||||||
|
*/
|
||||||
|
Qt::AlignmentFlag symbolAlignment() const { return mSymbolAlignment; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether a stroke will be drawn around raster symbol items.
|
* Returns whether a stroke will be drawn around raster symbol items.
|
||||||
* \see setDrawRasterStroke()
|
* \see setDrawRasterStroke()
|
||||||
@ -327,6 +345,9 @@ class CORE_EXPORT QgsLegendSettings
|
|||||||
|
|
||||||
//! Font color for layers, overrides font color
|
//! Font color for layers, overrides font color
|
||||||
QColor mLayerFontColor;
|
QColor mLayerFontColor;
|
||||||
|
|
||||||
|
//! Symbol alignment
|
||||||
|
Qt::AlignmentFlag mSymbolAlignment = Qt::AlignLeft;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -48,16 +48,22 @@ void QgsLegendStyle::setMargin( double margin )
|
|||||||
|
|
||||||
void QgsLegendStyle::writeXml( const QString &name, QDomElement &elem, QDomDocument &doc ) const
|
void QgsLegendStyle::writeXml( const QString &name, QDomElement &elem, QDomDocument &doc ) const
|
||||||
{
|
{
|
||||||
if ( elem.isNull() ) return;
|
if ( elem.isNull() )
|
||||||
|
return;
|
||||||
|
|
||||||
QDomElement styleElem = doc.createElement( QStringLiteral( "style" ) );
|
QDomElement styleElem = doc.createElement( QStringLiteral( "style" ) );
|
||||||
|
|
||||||
styleElem.setAttribute( QStringLiteral( "name" ), name );
|
styleElem.setAttribute( QStringLiteral( "name" ), name );
|
||||||
|
styleElem.setAttribute( QStringLiteral( "alignment" ), QString::number( mAlignment ) );
|
||||||
|
|
||||||
if ( !qgsDoubleNear( mMarginMap[Top], 0.0 ) ) styleElem.setAttribute( QStringLiteral( "marginTop" ), QString::number( mMarginMap[Top] ) );
|
if ( !qgsDoubleNear( mMarginMap[Top], 0.0 ) )
|
||||||
if ( !qgsDoubleNear( mMarginMap[Bottom], 0.0 ) ) styleElem.setAttribute( QStringLiteral( "marginBottom" ), QString::number( mMarginMap[Bottom] ) );
|
styleElem.setAttribute( QStringLiteral( "marginTop" ), QString::number( mMarginMap[Top] ) );
|
||||||
if ( !qgsDoubleNear( mMarginMap[Left], 0.0 ) ) styleElem.setAttribute( QStringLiteral( "marginLeft" ), QString::number( mMarginMap[Left] ) );
|
if ( !qgsDoubleNear( mMarginMap[Bottom], 0.0 ) )
|
||||||
if ( !qgsDoubleNear( mMarginMap[Right], 0.0 ) ) styleElem.setAttribute( QStringLiteral( "marginRight" ), QString::number( mMarginMap[Right] ) );
|
styleElem.setAttribute( QStringLiteral( "marginBottom" ), QString::number( mMarginMap[Bottom] ) );
|
||||||
|
if ( !qgsDoubleNear( mMarginMap[Left], 0.0 ) )
|
||||||
|
styleElem.setAttribute( QStringLiteral( "marginLeft" ), QString::number( mMarginMap[Left] ) );
|
||||||
|
if ( !qgsDoubleNear( mMarginMap[Right], 0.0 ) )
|
||||||
|
styleElem.setAttribute( QStringLiteral( "marginRight" ), QString::number( mMarginMap[Right] ) );
|
||||||
|
|
||||||
styleElem.appendChild( QgsFontUtils::toXmlElement( mFont, doc, QStringLiteral( "styleFont" ) ) );
|
styleElem.appendChild( QgsFontUtils::toXmlElement( mFont, doc, QStringLiteral( "styleFont" ) ) );
|
||||||
|
|
||||||
@ -78,6 +84,8 @@ void QgsLegendStyle::readXml( const QDomElement &elem, const QDomDocument &doc )
|
|||||||
mMarginMap[Bottom] = elem.attribute( QStringLiteral( "marginBottom" ), QStringLiteral( "0" ) ).toDouble();
|
mMarginMap[Bottom] = elem.attribute( QStringLiteral( "marginBottom" ), QStringLiteral( "0" ) ).toDouble();
|
||||||
mMarginMap[Left] = elem.attribute( QStringLiteral( "marginLeft" ), QStringLiteral( "0" ) ).toDouble();
|
mMarginMap[Left] = elem.attribute( QStringLiteral( "marginLeft" ), QStringLiteral( "0" ) ).toDouble();
|
||||||
mMarginMap[Right] = elem.attribute( QStringLiteral( "marginRight" ), QStringLiteral( "0" ) ).toDouble();
|
mMarginMap[Right] = elem.attribute( QStringLiteral( "marginRight" ), QStringLiteral( "0" ) ).toDouble();
|
||||||
|
|
||||||
|
mAlignment = static_cast< Qt::Alignment >( elem.attribute( QStringLiteral( "alignment" ), QString::number( Qt::AlignLeft ) ).toInt() );
|
||||||
}
|
}
|
||||||
|
|
||||||
QString QgsLegendStyle::styleName( Style s )
|
QString QgsLegendStyle::styleName( Style s )
|
||||||
|
|||||||
@ -80,6 +80,22 @@ class CORE_EXPORT QgsLegendStyle
|
|||||||
//! Sets all margins
|
//! Sets all margins
|
||||||
void setMargin( double margin );
|
void setMargin( double margin );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the alignment for the legend component.
|
||||||
|
*
|
||||||
|
* \see setAlignment()
|
||||||
|
* \since QGIS 3.10
|
||||||
|
*/
|
||||||
|
Qt::Alignment alignment() const { return mAlignment; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the alignment for the legend component.
|
||||||
|
*
|
||||||
|
* \see alignment()
|
||||||
|
* \since QGIS 3.10
|
||||||
|
*/
|
||||||
|
void setAlignment( Qt::Alignment alignment ) { mAlignment = alignment; }
|
||||||
|
|
||||||
void writeXml( const QString &name, QDomElement &elem, QDomDocument &doc ) const;
|
void writeXml( const QString &name, QDomElement &elem, QDomDocument &doc ) const;
|
||||||
|
|
||||||
void readXml( const QDomElement &elem, const QDomDocument &doc );
|
void readXml( const QDomElement &elem, const QDomDocument &doc );
|
||||||
@ -97,6 +113,8 @@ class CORE_EXPORT QgsLegendStyle
|
|||||||
QFont mFont;
|
QFont mFont;
|
||||||
//! Space around element
|
//! Space around element
|
||||||
QMap<Side, double> mMarginMap;
|
QMap<Side, double> mMarginMap;
|
||||||
|
|
||||||
|
Qt::Alignment mAlignment = Qt::AlignLeft;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -48,6 +48,18 @@ void QgsAlignmentComboBox::setCurrentAlignment( Qt::Alignment alignment )
|
|||||||
setCurrentIndex( index );
|
setCurrentIndex( index );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QgsAlignmentComboBox::customiseAlignmentDisplay( Qt::Alignment alignment, const QString &text, const QIcon &icon )
|
||||||
|
{
|
||||||
|
const int index = findData( QVariant( alignment ) );
|
||||||
|
if ( index >= 0 )
|
||||||
|
{
|
||||||
|
if ( !text.isEmpty() )
|
||||||
|
setItemText( index, text );
|
||||||
|
if ( !icon.isNull() )
|
||||||
|
setItemIcon( index, icon );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void QgsAlignmentComboBox::populate()
|
void QgsAlignmentComboBox::populate()
|
||||||
{
|
{
|
||||||
Qt::Alignment prevAlign = currentAlignment();
|
Qt::Alignment prevAlign = currentAlignment();
|
||||||
|
|||||||
@ -61,6 +61,16 @@ class GUI_EXPORT QgsAlignmentComboBox : public QComboBox
|
|||||||
*/
|
*/
|
||||||
void setCurrentAlignment( Qt::Alignment alignment );
|
void setCurrentAlignment( Qt::Alignment alignment );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the \a text and \a icon to use for a particular \a alignment option,
|
||||||
|
* replacing the default text or icon.
|
||||||
|
*
|
||||||
|
* If \a text or \a icon is not specified, they will not be changed from the default.
|
||||||
|
*
|
||||||
|
* \note This must be called after first filtering the available alignment options via setAvailableAlignments().
|
||||||
|
*/
|
||||||
|
void customiseAlignmentDisplay( Qt::Alignment alignment, const QString &text = QString(), const QIcon &icon = QIcon() );
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -167,8 +167,6 @@ namespace QgsWms
|
|||||||
QgsLegendSettings settings = legendSettings();
|
QgsLegendSettings settings = legendSettings();
|
||||||
QgsLayerTreeModelLegendNode::ItemContext ctx;
|
QgsLayerTreeModelLegendNode::ItemContext ctx;
|
||||||
ctx.painter = painter.get();
|
ctx.painter = painter.get();
|
||||||
ctx.labelXOffset = 0;
|
|
||||||
ctx.point = QPointF();
|
|
||||||
nodeModel.drawSymbol( settings, &ctx, size.height() / dpmm );
|
nodeModel.drawSymbol( settings, &ctx, size.height() / dpmm );
|
||||||
painter->end();
|
painter->end();
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>393</width>
|
<width>323</width>
|
||||||
<height>995</height>
|
<height>995</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
@ -64,8 +64,8 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>377</width>
|
<width>312</width>
|
||||||
<height>1662</height>
|
<height>1459</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="mainLayout">
|
<layout class="QVBoxLayout" name="mainLayout">
|
||||||
@ -84,6 +84,44 @@
|
|||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout_2">
|
<layout class="QGridLayout" name="gridLayout_2">
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QLineEdit" name="mTitleLineEdit"/>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Wrap text on</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1" colspan="2">
|
||||||
|
<widget class="QLineEdit" name="mWrapCharLineEdit">
|
||||||
|
<property name="frame">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="2">
|
||||||
|
<widget class="QgsPropertyOverrideButton" name="mLegendTitleDDBtn">
|
||||||
|
<property name="text">
|
||||||
|
<string>…</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="0" colspan="2">
|
||||||
|
<widget class="QCheckBox" name="mCheckboxResizeContents">
|
||||||
|
<property name="text">
|
||||||
|
<string>Resize to fit contents</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="mMapLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Map</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QLabel" name="mTitleLabel">
|
<widget class="QLabel" name="mTitleLabel">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@ -94,70 +132,16 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLabel" name="label_15">
|
|
||||||
<property name="text">
|
|
||||||
<string>Title alignment</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QLabel" name="mMapLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>Map</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="5" column="0" colspan="2">
|
|
||||||
<widget class="QCheckBox" name="mCheckboxResizeContents">
|
|
||||||
<property name="text">
|
|
||||||
<string>Resize to fit contents</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="0">
|
|
||||||
<widget class="QLabel" name="label">
|
|
||||||
<property name="text">
|
|
||||||
<string>Wrap text on</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="QLineEdit" name="mTitleLineEdit"/>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="2">
|
|
||||||
<widget class="QgsPropertyOverrideButton" name="mLegendTitleDDBtn">
|
|
||||||
<property name="text">
|
|
||||||
<string>…</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1" colspan="2">
|
<item row="1" column="1" colspan="2">
|
||||||
<widget class="QComboBox" name="mTitleAlignCombo">
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>Left</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>Center</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>Right</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="1" colspan="2">
|
|
||||||
<widget class="QgsLayoutItemComboBox" name="mMapComboBox"/>
|
<widget class="QgsLayoutItemComboBox" name="mMapComboBox"/>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="1" colspan="2">
|
<item row="3" column="1" colspan="2">
|
||||||
<widget class="QLineEdit" name="mWrapCharLineEdit">
|
<widget class="QgsAlignmentComboBox" name="mArrangementCombo"/>
|
||||||
<property name="frame">
|
</item>
|
||||||
<bool>true</bool>
|
<item row="3" column="0">
|
||||||
|
<widget class="QLabel" name="label_15">
|
||||||
|
<property name="text">
|
||||||
|
<string>Arrangement</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -255,7 +239,7 @@
|
|||||||
<string/>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
<iconset resource="../../../images/images.qrc">
|
<iconset>
|
||||||
<normaloff>:/images/themes/default/mActionArrowDown.svg</normaloff>:/images/themes/default/mActionArrowDown.svg</iconset>
|
<normaloff>:/images/themes/default/mActionArrowDown.svg</normaloff>:/images/themes/default/mActionArrowDown.svg</iconset>
|
||||||
</property>
|
</property>
|
||||||
<property name="iconSize">
|
<property name="iconSize">
|
||||||
@ -272,7 +256,7 @@
|
|||||||
<string/>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
<iconset resource="../../../images/images.qrc">
|
<iconset>
|
||||||
<normaloff>:/images/themes/default/mActionArrowUp.svg</normaloff>:/images/themes/default/mActionArrowUp.svg</iconset>
|
<normaloff>:/images/themes/default/mActionArrowUp.svg</normaloff>:/images/themes/default/mActionArrowUp.svg</iconset>
|
||||||
</property>
|
</property>
|
||||||
<property name="iconSize">
|
<property name="iconSize">
|
||||||
@ -292,7 +276,7 @@
|
|||||||
<string>…</string>
|
<string>…</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
<iconset resource="../../../images/images.qrc">
|
<iconset>
|
||||||
<normaloff>:/images/themes/default/mActionAddGroup.svg</normaloff>:/images/themes/default/mActionAddGroup.svg</iconset>
|
<normaloff>:/images/themes/default/mActionAddGroup.svg</normaloff>:/images/themes/default/mActionAddGroup.svg</iconset>
|
||||||
</property>
|
</property>
|
||||||
<property name="iconSize">
|
<property name="iconSize">
|
||||||
@ -309,7 +293,7 @@
|
|||||||
<string/>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
<iconset resource="../../../images/images.qrc">
|
<iconset>
|
||||||
<normaloff>:/images/themes/default/symbologyAdd.svg</normaloff>:/images/themes/default/symbologyAdd.svg</iconset>
|
<normaloff>:/images/themes/default/symbologyAdd.svg</normaloff>:/images/themes/default/symbologyAdd.svg</iconset>
|
||||||
</property>
|
</property>
|
||||||
<property name="iconSize">
|
<property name="iconSize">
|
||||||
@ -326,7 +310,7 @@
|
|||||||
<string/>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
<iconset resource="../../../images/images.qrc">
|
<iconset>
|
||||||
<normaloff>:/images/themes/default/symbologyRemove.svg</normaloff>:/images/themes/default/symbologyRemove.svg</iconset>
|
<normaloff>:/images/themes/default/symbologyRemove.svg</normaloff>:/images/themes/default/symbologyRemove.svg</iconset>
|
||||||
</property>
|
</property>
|
||||||
<property name="iconSize">
|
<property name="iconSize">
|
||||||
@ -343,7 +327,7 @@
|
|||||||
<string/>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
<iconset resource="../../../images/images.qrc">
|
<iconset>
|
||||||
<normaloff>:/images/themes/default/symbologyEdit.svg</normaloff>:/images/themes/default/symbologyEdit.svg</iconset>
|
<normaloff>:/images/themes/default/symbologyEdit.svg</normaloff>:/images/themes/default/symbologyEdit.svg</iconset>
|
||||||
</property>
|
</property>
|
||||||
<property name="iconSize">
|
<property name="iconSize">
|
||||||
@ -366,7 +350,7 @@
|
|||||||
<string/>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
<iconset resource="../../../images/images.qrc">
|
<iconset>
|
||||||
<normaloff>:/images/themes/default/mActionSum.svg</normaloff>:/images/themes/default/mActionSum.svg</iconset>
|
<normaloff>:/images/themes/default/mActionSum.svg</normaloff>:/images/themes/default/mActionSum.svg</iconset>
|
||||||
</property>
|
</property>
|
||||||
<property name="iconSize">
|
<property name="iconSize">
|
||||||
@ -386,7 +370,7 @@
|
|||||||
<string>Filter Legend by Map Content</string>
|
<string>Filter Legend by Map Content</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
<iconset resource="../../../images/images.qrc">
|
<iconset>
|
||||||
<normaloff>:/images/themes/default/mActionFilter2.svg</normaloff>:/images/themes/default/mActionFilter2.svg</iconset>
|
<normaloff>:/images/themes/default/mActionFilter2.svg</normaloff>:/images/themes/default/mActionFilter2.svg</iconset>
|
||||||
</property>
|
</property>
|
||||||
<property name="iconSize">
|
<property name="iconSize">
|
||||||
@ -406,7 +390,7 @@
|
|||||||
<string/>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
<iconset resource="../../../images/images.qrc">
|
<iconset>
|
||||||
<normaloff>:/images/themes/default/mIconExpressionFilter.svg</normaloff>:/images/themes/default/mIconExpressionFilter.svg</iconset>
|
<normaloff>:/images/themes/default/mIconExpressionFilter.svg</normaloff>:/images/themes/default/mIconExpressionFilter.svg</iconset>
|
||||||
</property>
|
</property>
|
||||||
<property name="iconSize">
|
<property name="iconSize">
|
||||||
@ -451,7 +435,7 @@
|
|||||||
<enum>Qt::StrongFocus</enum>
|
<enum>Qt::StrongFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Fonts</string>
|
<string>Fonts and Text Formatting</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="syncGroup" stdset="0">
|
<property name="syncGroup" stdset="0">
|
||||||
<string notr="true">composeritem</string>
|
<string notr="true">composeritem</string>
|
||||||
@ -459,34 +443,32 @@
|
|||||||
<property name="collapsed" stdset="0">
|
<property name="collapsed" stdset="0">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
<layout class="QGridLayout" name="gridLayout_4" columnstretch="0,0,0">
|
||||||
<item>
|
<item row="3" column="0" colspan="3">
|
||||||
<widget class="QgsFontButton" name="mTitleFontButton">
|
<widget class="QLabel" name="label_21">
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Title font</string>
|
<string><b>Group Headings</b></string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item row="1" column="0">
|
||||||
<widget class="QgsFontButton" name="mGroupFontButton">
|
<widget class="QLabel" name="label_28">
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Group font</string>
|
<string>Font</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item row="11" column="1" colspan="2">
|
||||||
|
<widget class="QgsAlignmentComboBox" name="mItemAlignCombo"/>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="0" colspan="3">
|
||||||
|
<widget class="QLabel" name="label_23">
|
||||||
|
<property name="text">
|
||||||
|
<string><b>Subgroup Headings</b></string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="7" column="1" colspan="2">
|
||||||
<widget class="QgsFontButton" name="mLayerFontButton">
|
<widget class="QgsFontButton" name="mLayerFontButton">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
@ -499,7 +481,10 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item row="5" column="1" colspan="2">
|
||||||
|
<widget class="QgsAlignmentComboBox" name="mGroupAlignCombo"/>
|
||||||
|
</item>
|
||||||
|
<item row="10" column="1" colspan="2">
|
||||||
<widget class="QgsFontButton" name="mItemFontButton">
|
<widget class="QgsFontButton" name="mItemFontButton">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
@ -512,7 +497,41 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item row="9" column="0" colspan="3">
|
||||||
|
<widget class="QLabel" name="label_25">
|
||||||
|
<property name="text">
|
||||||
|
<string><b>Item Labels</b></string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="11" column="0">
|
||||||
|
<widget class="QLabel" name="label_20">
|
||||||
|
<property name="text">
|
||||||
|
<string>Alignment</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1" colspan="2">
|
||||||
|
<widget class="QgsFontButton" name="mTitleFontButton">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Title font</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="0">
|
||||||
|
<widget class="QLabel" name="label_18">
|
||||||
|
<property name="text">
|
||||||
|
<string>Alignment</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="12" column="0" colspan="3">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="label_16">
|
<widget class="QLabel" name="label_16">
|
||||||
@ -555,6 +574,67 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="4" column="0">
|
||||||
|
<widget class="QLabel" name="label_22">
|
||||||
|
<property name="text">
|
||||||
|
<string>Font</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="8" column="0">
|
||||||
|
<widget class="QLabel" name="label_19">
|
||||||
|
<property name="text">
|
||||||
|
<string>Alignment</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="10" column="0">
|
||||||
|
<widget class="QLabel" name="label_26">
|
||||||
|
<property name="text">
|
||||||
|
<string>Font</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="7" column="0">
|
||||||
|
<widget class="QLabel" name="label_24">
|
||||||
|
<property name="text">
|
||||||
|
<string>Font</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0" colspan="3">
|
||||||
|
<widget class="QLabel" name="label_27">
|
||||||
|
<property name="text">
|
||||||
|
<string><b>Legend Title</b></string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="8" column="1" colspan="2">
|
||||||
|
<widget class="QgsAlignmentComboBox" name="mSubgroupAlignCombo"/>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="1" colspan="2">
|
||||||
|
<widget class="QgsFontButton" name="mGroupFontButton">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Group font</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1" colspan="2">
|
||||||
|
<widget class="QgsAlignmentComboBox" name="mTitleAlignCombo"/>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="label_29">
|
||||||
|
<property name="text">
|
||||||
|
<string>Alignment</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -1102,15 +1182,20 @@
|
|||||||
<extends>QToolButton</extends>
|
<extends>QToolButton</extends>
|
||||||
<header location="global">qgslegendfilterbutton.h</header>
|
<header location="global">qgslegendfilterbutton.h</header>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>QgsAlignmentComboBox</class>
|
||||||
|
<extends>QComboBox</extends>
|
||||||
|
<header>qgsalignmentcombobox.h</header>
|
||||||
|
</customwidget>
|
||||||
</customwidgets>
|
</customwidgets>
|
||||||
<tabstops>
|
<tabstops>
|
||||||
<tabstop>scrollArea</tabstop>
|
<tabstop>scrollArea</tabstop>
|
||||||
<tabstop>mMainPropertiesColGroupBox</tabstop>
|
<tabstop>mMainPropertiesColGroupBox</tabstop>
|
||||||
<tabstop>mTitleLineEdit</tabstop>
|
<tabstop>mTitleLineEdit</tabstop>
|
||||||
<tabstop>mLegendTitleDDBtn</tabstop>
|
<tabstop>mLegendTitleDDBtn</tabstop>
|
||||||
<tabstop>mTitleAlignCombo</tabstop>
|
|
||||||
<tabstop>mMapComboBox</tabstop>
|
<tabstop>mMapComboBox</tabstop>
|
||||||
<tabstop>mWrapCharLineEdit</tabstop>
|
<tabstop>mWrapCharLineEdit</tabstop>
|
||||||
|
<tabstop>mArrangementCombo</tabstop>
|
||||||
<tabstop>mCheckboxResizeContents</tabstop>
|
<tabstop>mCheckboxResizeContents</tabstop>
|
||||||
<tabstop>mLegendItemColGroupBox</tabstop>
|
<tabstop>mLegendItemColGroupBox</tabstop>
|
||||||
<tabstop>mCheckBoxAutoUpdate</tabstop>
|
<tabstop>mCheckBoxAutoUpdate</tabstop>
|
||||||
@ -1128,13 +1213,17 @@
|
|||||||
<tabstop>mFilterLegendByAtlasCheckBox</tabstop>
|
<tabstop>mFilterLegendByAtlasCheckBox</tabstop>
|
||||||
<tabstop>mFontsColGroupBox</tabstop>
|
<tabstop>mFontsColGroupBox</tabstop>
|
||||||
<tabstop>mTitleFontButton</tabstop>
|
<tabstop>mTitleFontButton</tabstop>
|
||||||
|
<tabstop>mTitleAlignCombo</tabstop>
|
||||||
<tabstop>mGroupFontButton</tabstop>
|
<tabstop>mGroupFontButton</tabstop>
|
||||||
|
<tabstop>mGroupAlignCombo</tabstop>
|
||||||
<tabstop>mLayerFontButton</tabstop>
|
<tabstop>mLayerFontButton</tabstop>
|
||||||
|
<tabstop>mSubgroupAlignCombo</tabstop>
|
||||||
<tabstop>mItemFontButton</tabstop>
|
<tabstop>mItemFontButton</tabstop>
|
||||||
|
<tabstop>mItemAlignCombo</tabstop>
|
||||||
<tabstop>mFontColorButton</tabstop>
|
<tabstop>mFontColorButton</tabstop>
|
||||||
<tabstop>mColumnsColGroupBox</tabstop>
|
<tabstop>mColumnsColGroupBox</tabstop>
|
||||||
<tabstop>mColumnsDDBtn</tabstop>
|
|
||||||
<tabstop>mColumnCountSpinBox</tabstop>
|
<tabstop>mColumnCountSpinBox</tabstop>
|
||||||
|
<tabstop>mColumnsDDBtn</tabstop>
|
||||||
<tabstop>mEqualColumnWidthCheckBox</tabstop>
|
<tabstop>mEqualColumnWidthCheckBox</tabstop>
|
||||||
<tabstop>mSplitLayerCheckBox</tabstop>
|
<tabstop>mSplitLayerCheckBox</tabstop>
|
||||||
<tabstop>mSymbolsColGroupBox</tabstop>
|
<tabstop>mSymbolsColGroupBox</tabstop>
|
||||||
@ -1156,35 +1245,6 @@
|
|||||||
<tabstop>mColumnSpaceSpinBox</tabstop>
|
<tabstop>mColumnSpaceSpinBox</tabstop>
|
||||||
<tabstop>mLineSpacingSpinBox</tabstop>
|
<tabstop>mLineSpacingSpinBox</tabstop>
|
||||||
</tabstops>
|
</tabstops>
|
||||||
<resources>
|
<resources/>
|
||||||
<include location="../../../images/images.qrc"/>
|
|
||||||
<include location="../../../images/images.qrc"/>
|
|
||||||
<include location="../../../images/images.qrc"/>
|
|
||||||
<include location="../../../images/images.qrc"/>
|
|
||||||
<include location="../../../images/images.qrc"/>
|
|
||||||
<include location="../../../images/images.qrc"/>
|
|
||||||
<include location="../../../images/images.qrc"/>
|
|
||||||
<include location="../../../images/images.qrc"/>
|
|
||||||
<include location="../../../images/images.qrc"/>
|
|
||||||
<include location="../../../images/images.qrc"/>
|
|
||||||
<include location="../../../images/images.qrc"/>
|
|
||||||
<include location="../../../images/images.qrc"/>
|
|
||||||
<include location="../../../images/images.qrc"/>
|
|
||||||
<include location="../../../images/images.qrc"/>
|
|
||||||
<include location="../../../images/images.qrc"/>
|
|
||||||
<include location="../../../images/images.qrc"/>
|
|
||||||
<include location="../../../images/images.qrc"/>
|
|
||||||
<include location="../../../images/images.qrc"/>
|
|
||||||
<include location="../../../images/images.qrc"/>
|
|
||||||
<include location="../../../images/images.qrc"/>
|
|
||||||
<include location="../../../images/images.qrc"/>
|
|
||||||
<include location="../../../images/images.qrc"/>
|
|
||||||
<include location="../../../images/images.qrc"/>
|
|
||||||
<include location="../../../images/images.qrc"/>
|
|
||||||
<include location="../../../images/images.qrc"/>
|
|
||||||
<include location="../../../images/images.qrc"/>
|
|
||||||
<include location="../../../images/images.qrc"/>
|
|
||||||
<include location="../../../images/images.qrc"/>
|
|
||||||
</resources>
|
|
||||||
<connections/>
|
<connections/>
|
||||||
</ui>
|
</ui>
|
||||||
|
|||||||
@ -124,6 +124,13 @@ class TestQgsLegendRenderer : public QObject
|
|||||||
|
|
||||||
void testBasic();
|
void testBasic();
|
||||||
void testBigMarker();
|
void testBigMarker();
|
||||||
|
|
||||||
|
void testRightAlignText();
|
||||||
|
void testCenterAlignText();
|
||||||
|
void testLeftAlignTextRightAlignSymbol();
|
||||||
|
void testCenterAlignTextRightAlignSymbol();
|
||||||
|
void testRightAlignTextRightAlignSymbol();
|
||||||
|
|
||||||
void testMapUnits();
|
void testMapUnits();
|
||||||
void testTallSymbol();
|
void testTallSymbol();
|
||||||
void testLineSpacing();
|
void testLineSpacing();
|
||||||
@ -321,6 +328,124 @@ void TestQgsLegendRenderer::testBigMarker()
|
|||||||
QVERIFY( _verifyImage( testName, mReport ) );
|
QVERIFY( _verifyImage( testName, mReport ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TestQgsLegendRenderer::testCenterAlignText()
|
||||||
|
{
|
||||||
|
QgsMarkerSymbol *sym = new QgsMarkerSymbol();
|
||||||
|
sym->setColor( Qt::red );
|
||||||
|
sym->setSize( sym->size() * 6 );
|
||||||
|
QgsCategorizedSymbolRenderer *catRenderer = dynamic_cast<QgsCategorizedSymbolRenderer *>( mVL3->renderer() );
|
||||||
|
QVERIFY( catRenderer );
|
||||||
|
catRenderer->updateCategorySymbol( 0, sym );
|
||||||
|
|
||||||
|
QgsLayerTreeModel legendModel( mRoot );
|
||||||
|
QgsLegendSettings settings;
|
||||||
|
settings.rstyle( QgsLegendStyle::Group ).setAlignment( Qt::AlignHCenter );
|
||||||
|
settings.rstyle( QgsLegendStyle::Subgroup ).setAlignment( Qt::AlignHCenter );
|
||||||
|
settings.rstyle( QgsLegendStyle::SymbolLabel ).setAlignment( Qt::AlignHCenter );
|
||||||
|
_setStandardTestFont( settings );
|
||||||
|
_renderLegend( QStringLiteral( "legend_center_align_text" ), &legendModel, settings );
|
||||||
|
QVERIFY( _verifyImage( QStringLiteral( "legend_center_align_text" ), mReport ) );
|
||||||
|
|
||||||
|
settings.setColumnCount( 2 );
|
||||||
|
_renderLegend( QStringLiteral( "legend_two_cols_center_align_text" ), &legendModel, settings );
|
||||||
|
QVERIFY( _verifyImage( QStringLiteral( "legend_two_cols_center_align_text" ), mReport ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestQgsLegendRenderer::testLeftAlignTextRightAlignSymbol()
|
||||||
|
{
|
||||||
|
QgsMarkerSymbol *sym = new QgsMarkerSymbol();
|
||||||
|
sym->setColor( Qt::red );
|
||||||
|
sym->setSize( sym->size() * 6 );
|
||||||
|
QgsCategorizedSymbolRenderer *catRenderer = dynamic_cast<QgsCategorizedSymbolRenderer *>( mVL3->renderer() );
|
||||||
|
QVERIFY( catRenderer );
|
||||||
|
catRenderer->updateCategorySymbol( 0, sym );
|
||||||
|
|
||||||
|
QgsLayerTreeModel legendModel( mRoot );
|
||||||
|
QgsLegendSettings settings;
|
||||||
|
settings.rstyle( QgsLegendStyle::Group ).setAlignment( Qt::AlignLeft );
|
||||||
|
settings.rstyle( QgsLegendStyle::Subgroup ).setAlignment( Qt::AlignLeft );
|
||||||
|
settings.rstyle( QgsLegendStyle::SymbolLabel ).setAlignment( Qt::AlignLeft );
|
||||||
|
settings.setSymbolAlignment( Qt::AlignRight );
|
||||||
|
_setStandardTestFont( settings );
|
||||||
|
_renderLegend( QStringLiteral( "legend_right_symbol_left_align_text" ), &legendModel, settings );
|
||||||
|
QVERIFY( _verifyImage( QStringLiteral( "legend_right_symbol_left_align_text" ), mReport ) );
|
||||||
|
|
||||||
|
settings.setColumnCount( 2 );
|
||||||
|
_renderLegend( QStringLiteral( "legend_two_cols_right_align_symbol_left_align_text" ), &legendModel, settings );
|
||||||
|
QVERIFY( _verifyImage( QStringLiteral( "legend_two_cols_right_align_symbol_left_align_text" ), mReport ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestQgsLegendRenderer::testCenterAlignTextRightAlignSymbol()
|
||||||
|
{
|
||||||
|
QgsMarkerSymbol *sym = new QgsMarkerSymbol();
|
||||||
|
sym->setColor( Qt::red );
|
||||||
|
sym->setSize( sym->size() * 6 );
|
||||||
|
QgsCategorizedSymbolRenderer *catRenderer = dynamic_cast<QgsCategorizedSymbolRenderer *>( mVL3->renderer() );
|
||||||
|
QVERIFY( catRenderer );
|
||||||
|
catRenderer->updateCategorySymbol( 0, sym );
|
||||||
|
|
||||||
|
QgsLayerTreeModel legendModel( mRoot );
|
||||||
|
QgsLegendSettings settings;
|
||||||
|
settings.rstyle( QgsLegendStyle::Group ).setAlignment( Qt::AlignHCenter );
|
||||||
|
settings.rstyle( QgsLegendStyle::Subgroup ).setAlignment( Qt::AlignHCenter );
|
||||||
|
settings.rstyle( QgsLegendStyle::SymbolLabel ).setAlignment( Qt::AlignHCenter );
|
||||||
|
settings.setSymbolAlignment( Qt::AlignRight );
|
||||||
|
_setStandardTestFont( settings );
|
||||||
|
_renderLegend( QStringLiteral( "legend_right_symbol_center_align_text" ), &legendModel, settings );
|
||||||
|
QVERIFY( _verifyImage( QStringLiteral( "legend_right_symbol_center_align_text" ), mReport ) );
|
||||||
|
|
||||||
|
settings.setColumnCount( 2 );
|
||||||
|
_renderLegend( QStringLiteral( "legend_two_cols_right_align_symbol_center_align_text" ), &legendModel, settings );
|
||||||
|
QVERIFY( _verifyImage( QStringLiteral( "legend_two_cols_right_align_symbol_center_align_text" ), mReport ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestQgsLegendRenderer::testRightAlignTextRightAlignSymbol()
|
||||||
|
{
|
||||||
|
QgsMarkerSymbol *sym = new QgsMarkerSymbol();
|
||||||
|
sym->setColor( Qt::red );
|
||||||
|
sym->setSize( sym->size() * 6 );
|
||||||
|
QgsCategorizedSymbolRenderer *catRenderer = dynamic_cast<QgsCategorizedSymbolRenderer *>( mVL3->renderer() );
|
||||||
|
QVERIFY( catRenderer );
|
||||||
|
catRenderer->updateCategorySymbol( 0, sym );
|
||||||
|
|
||||||
|
QgsLayerTreeModel legendModel( mRoot );
|
||||||
|
QgsLegendSettings settings;
|
||||||
|
settings.rstyle( QgsLegendStyle::Group ).setAlignment( Qt::AlignRight );
|
||||||
|
settings.rstyle( QgsLegendStyle::Subgroup ).setAlignment( Qt::AlignRight );
|
||||||
|
settings.rstyle( QgsLegendStyle::SymbolLabel ).setAlignment( Qt::AlignRight );
|
||||||
|
settings.setSymbolAlignment( Qt::AlignRight );
|
||||||
|
_setStandardTestFont( settings );
|
||||||
|
_renderLegend( QStringLiteral( "legend_right_symbol_right_align_text" ), &legendModel, settings );
|
||||||
|
QVERIFY( _verifyImage( QStringLiteral( "legend_right_symbol_right_align_text" ), mReport ) );
|
||||||
|
|
||||||
|
settings.setColumnCount( 2 );
|
||||||
|
_renderLegend( QStringLiteral( "legend_two_cols_right_align_symbol_right_align_text" ), &legendModel, settings );
|
||||||
|
QVERIFY( _verifyImage( QStringLiteral( "legend_two_cols_right_align_symbol_right_align_text" ), mReport ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestQgsLegendRenderer::testRightAlignText()
|
||||||
|
{
|
||||||
|
QgsMarkerSymbol *sym = new QgsMarkerSymbol();
|
||||||
|
sym->setColor( Qt::red );
|
||||||
|
sym->setSize( sym->size() * 6 );
|
||||||
|
QgsCategorizedSymbolRenderer *catRenderer = dynamic_cast<QgsCategorizedSymbolRenderer *>( mVL3->renderer() );
|
||||||
|
QVERIFY( catRenderer );
|
||||||
|
catRenderer->updateCategorySymbol( 0, sym );
|
||||||
|
|
||||||
|
QgsLayerTreeModel legendModel( mRoot );
|
||||||
|
QgsLegendSettings settings;
|
||||||
|
settings.rstyle( QgsLegendStyle::Group ).setAlignment( Qt::AlignRight );
|
||||||
|
settings.rstyle( QgsLegendStyle::Subgroup ).setAlignment( Qt::AlignRight );
|
||||||
|
settings.rstyle( QgsLegendStyle::SymbolLabel ).setAlignment( Qt::AlignRight );
|
||||||
|
_setStandardTestFont( settings );
|
||||||
|
_renderLegend( QStringLiteral( "legend_right_align_text" ), &legendModel, settings );
|
||||||
|
QVERIFY( _verifyImage( QStringLiteral( "legend_right_align_text" ), mReport ) );
|
||||||
|
|
||||||
|
settings.setColumnCount( 2 );
|
||||||
|
_renderLegend( QStringLiteral( "legend_two_cols_right_align_text" ), &legendModel, settings );
|
||||||
|
QVERIFY( _verifyImage( QStringLiteral( "legend_two_cols_right_align_text" ), mReport ) );
|
||||||
|
}
|
||||||
|
|
||||||
void TestQgsLegendRenderer::testMapUnits()
|
void TestQgsLegendRenderer::testMapUnits()
|
||||||
{
|
{
|
||||||
QString testName = QStringLiteral( "legend_mapunits" );
|
QString testName = QStringLiteral( "legend_mapunits" );
|
||||||
|
|||||||
@ -10,7 +10,7 @@ __author__ = '(C) 2017 by Nyall Dawson'
|
|||||||
__date__ = '24/10/2017'
|
__date__ = '24/10/2017'
|
||||||
__copyright__ = 'Copyright 2017, The QGIS Project'
|
__copyright__ = 'Copyright 2017, The QGIS Project'
|
||||||
|
|
||||||
from qgis.PyQt.QtCore import QRectF
|
from qgis.PyQt.QtCore import QRectF, QDir
|
||||||
from qgis.PyQt.QtGui import QColor
|
from qgis.PyQt.QtGui import QColor
|
||||||
|
|
||||||
from qgis.core import (QgsPrintLayout,
|
from qgis.core import (QgsPrintLayout,
|
||||||
@ -52,8 +52,17 @@ class TestQgsLayoutItemLegend(unittest.TestCase, LayoutItemTestCase):
|
|||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
cls.item_class = QgsLayoutItemLegend
|
cls.item_class = QgsLayoutItemLegend
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.report = "<h1>Python QgsLayoutItemLegend Tests</h1>\n"
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
report_file_path = "%s/qgistest.html" % QDir.tempPath()
|
||||||
|
with open(report_file_path, 'a') as report_file:
|
||||||
|
report_file.write(self.report)
|
||||||
|
|
||||||
def testInitialSizeSymbolMapUnits(self):
|
def testInitialSizeSymbolMapUnits(self):
|
||||||
"""Test initial size of legend with a symbol size in map units"""
|
"""Test initial size of legend with a symbol size in map units"""
|
||||||
|
QgsProject.instance().removeAllMapLayers()
|
||||||
|
|
||||||
point_path = os.path.join(TEST_DATA_DIR, 'points.shp')
|
point_path = os.path.join(TEST_DATA_DIR, 'points.shp')
|
||||||
point_layer = QgsVectorLayer(point_path, 'points', 'ogr')
|
point_layer = QgsVectorLayer(point_path, 'points', 'ogr')
|
||||||
@ -89,6 +98,7 @@ class TestQgsLayoutItemLegend(unittest.TestCase, LayoutItemTestCase):
|
|||||||
'composer_legend_mapunits', layout)
|
'composer_legend_mapunits', layout)
|
||||||
checker.setControlPathPrefix("composer_legend")
|
checker.setControlPathPrefix("composer_legend")
|
||||||
result, message = checker.testLayout()
|
result, message = checker.testLayout()
|
||||||
|
self.report += checker.report()
|
||||||
self.assertTrue(result, message)
|
self.assertTrue(result, message)
|
||||||
|
|
||||||
# resize with non-top-left reference point
|
# resize with non-top-left reference point
|
||||||
@ -147,6 +157,7 @@ class TestQgsLayoutItemLegend(unittest.TestCase, LayoutItemTestCase):
|
|||||||
'composer_legend_size_content', layout)
|
'composer_legend_size_content', layout)
|
||||||
checker.setControlPathPrefix("composer_legend")
|
checker.setControlPathPrefix("composer_legend")
|
||||||
result, message = checker.testLayout()
|
result, message = checker.testLayout()
|
||||||
|
self.report += checker.report()
|
||||||
self.assertTrue(result, message)
|
self.assertTrue(result, message)
|
||||||
|
|
||||||
QgsProject.instance().removeMapLayers([point_layer.id()])
|
QgsProject.instance().removeMapLayers([point_layer.id()])
|
||||||
@ -191,6 +202,7 @@ class TestQgsLayoutItemLegend(unittest.TestCase, LayoutItemTestCase):
|
|||||||
'composer_legend_noresize', layout)
|
'composer_legend_noresize', layout)
|
||||||
checker.setControlPathPrefix("composer_legend")
|
checker.setControlPathPrefix("composer_legend")
|
||||||
result, message = checker.testLayout()
|
result, message = checker.testLayout()
|
||||||
|
self.report += checker.report()
|
||||||
self.assertTrue(result, message)
|
self.assertTrue(result, message)
|
||||||
|
|
||||||
QgsProject.instance().removeMapLayers([point_layer.id()])
|
QgsProject.instance().removeMapLayers([point_layer.id()])
|
||||||
@ -235,6 +247,7 @@ class TestQgsLayoutItemLegend(unittest.TestCase, LayoutItemTestCase):
|
|||||||
'composer_legend_noresize_crop', layout)
|
'composer_legend_noresize_crop', layout)
|
||||||
checker.setControlPathPrefix("composer_legend")
|
checker.setControlPathPrefix("composer_legend")
|
||||||
result, message = checker.testLayout()
|
result, message = checker.testLayout()
|
||||||
|
self.report += checker.report()
|
||||||
self.assertTrue(result, message)
|
self.assertTrue(result, message)
|
||||||
|
|
||||||
QgsProject.instance().removeMapLayers([point_layer.id()])
|
QgsProject.instance().removeMapLayers([point_layer.id()])
|
||||||
@ -360,6 +373,7 @@ class TestQgsLayoutItemLegend(unittest.TestCase, LayoutItemTestCase):
|
|||||||
'composer_legend_expressions', layout)
|
'composer_legend_expressions', layout)
|
||||||
checker.setControlPathPrefix("composer_legend")
|
checker.setControlPathPrefix("composer_legend")
|
||||||
result, message = checker.testLayout()
|
result, message = checker.testLayout()
|
||||||
|
self.report += checker.report()
|
||||||
self.assertTrue(result, message)
|
self.assertTrue(result, message)
|
||||||
|
|
||||||
QgsProject.instance().removeMapLayers([point_layer.id()])
|
QgsProject.instance().removeMapLayers([point_layer.id()])
|
||||||
|
|||||||
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 15 KiB |