mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-13 00:03:09 -04:00
[FEATURE][composer] Data defined legend titles and column count
(fix #11913)
This commit is contained in:
parent
a67c84b9a9
commit
ec9ba9c2a2
@ -242,9 +242,13 @@ class QgsComposerLegend : QgsComposerItem
|
||||
//Overridden to show legend title
|
||||
virtual QString displayName() const;
|
||||
|
||||
const QgsLegendSettings& legendSettings() const;
|
||||
|
||||
public slots:
|
||||
/** Data changed*/
|
||||
void synchronizeWithModel();
|
||||
/** Sets mCompositionMap to 0 if the map is deleted*/
|
||||
void invalidateCurrentMap();
|
||||
virtual void refreshDataDefinedProperty( const QgsComposerObject::DataDefinedProperty property = QgsComposerObject::AllProperties, const QgsExpressionContext* context = nullptr );
|
||||
|
||||
};
|
||||
|
@ -51,6 +51,9 @@ class QgsComposerObject : QObject, QgsExpressionContextGenerator
|
||||
PictureSvgOutlineWidth, //!< SVG outline width
|
||||
//html item
|
||||
SourceUrl /*!< html source url */
|
||||
//legend item
|
||||
LegendTitle, //!< Legend title
|
||||
LegendColumnCount, //!< Legend column count
|
||||
};
|
||||
|
||||
/** Specifies whether the value returned by a function should be the original, user
|
||||
|
@ -100,6 +100,11 @@ QgsComposerLegendWidget::QgsComposerLegendWidget( QgsComposerLegend* legend )
|
||||
connect( &legend->composition()->atlasComposition(), SIGNAL( coverageLayerChanged( QgsVectorLayer* ) ), this, SLOT( updateFilterLegendByAtlasButton() ) );
|
||||
}
|
||||
|
||||
registerDataDefinedButton( mLegendTitleDDBtn, QgsComposerObject::LegendTitle,
|
||||
QgsDataDefinedButtonV2::AnyType, QgsDataDefinedButtonV2::anyStringDesc() );
|
||||
registerDataDefinedButton( mColumnsDDBtn, QgsComposerObject::LegendColumnCount,
|
||||
QgsDataDefinedButtonV2::AnyType, QgsDataDefinedButtonV2::intPosOneDesc() );
|
||||
|
||||
setGuiElements();
|
||||
|
||||
connect( mItemTreeView->selectionModel(), SIGNAL( currentChanged( const QModelIndex &, const QModelIndex & ) ),
|
||||
@ -160,6 +165,8 @@ void QgsComposerLegendWidget::setGuiElements()
|
||||
blockAllSignals( false );
|
||||
|
||||
on_mCheckBoxAutoUpdate_stateChanged( mLegend->autoUpdateModel() ? Qt::Checked : Qt::Unchecked );
|
||||
updateDataDefinedButton( mLegendTitleDDBtn );
|
||||
updateDataDefinedButton( mColumnsDDBtn );
|
||||
}
|
||||
|
||||
void QgsComposerLegendWidget::on_mWrapCharLineEdit_textChanged( const QString &text )
|
||||
|
@ -265,6 +265,7 @@ void QgsComposerLegend::setLegendFilterByMapEnabled( bool enabled )
|
||||
|
||||
void QgsComposerLegend::setTitle( const QString& t )
|
||||
{
|
||||
mTitle = t;
|
||||
mSettings.setTitle( t );
|
||||
|
||||
if ( mComposition && id().isEmpty() )
|
||||
@ -273,7 +274,7 @@ void QgsComposerLegend::setTitle( const QString& t )
|
||||
mComposition->itemsModel()->updateItemDisplayName( this );
|
||||
}
|
||||
}
|
||||
QString QgsComposerLegend::title() const { return mSettings.title(); }
|
||||
QString QgsComposerLegend::title() const { return mTitle; }
|
||||
|
||||
Qt::AlignmentFlag QgsComposerLegend::titleAlignment() const { return mSettings.titleAlignment(); }
|
||||
void QgsComposerLegend::setTitleAlignment( Qt::AlignmentFlag alignment ) { mSettings.setTitleAlignment( alignment ); }
|
||||
@ -315,8 +316,8 @@ void QgsComposerLegend::setWmsLegendHeight( double h ) { mSettings.setWmsLegendS
|
||||
void QgsComposerLegend::setWrapChar( const QString& t ) { mSettings.setWrapChar( t ); }
|
||||
QString QgsComposerLegend::wrapChar() const {return mSettings.wrapChar(); }
|
||||
|
||||
int QgsComposerLegend::columnCount() const { return mSettings.columnCount(); }
|
||||
void QgsComposerLegend::setColumnCount( int c ) { mSettings.setColumnCount( c ); }
|
||||
int QgsComposerLegend::columnCount() const { return mColumnCount; }
|
||||
void QgsComposerLegend::setColumnCount( int c ) { mColumnCount = c; mSettings.setColumnCount( c ); }
|
||||
|
||||
bool QgsComposerLegend::splitLayer() const { return mSettings.splitLayer(); }
|
||||
void QgsComposerLegend::setSplitLayer( bool s ) { mSettings.setSplitLayer( s ); }
|
||||
@ -362,9 +363,9 @@ bool QgsComposerLegend::writeXml( QDomElement& elem, QDomDocument & doc ) const
|
||||
elem.appendChild( composerLegendElem );
|
||||
|
||||
//write general properties
|
||||
composerLegendElem.setAttribute( QStringLiteral( "title" ), mSettings.title() );
|
||||
composerLegendElem.setAttribute( QStringLiteral( "title" ), mTitle );
|
||||
composerLegendElem.setAttribute( QStringLiteral( "titleAlignment" ), QString::number( static_cast< int >( mSettings.titleAlignment() ) ) );
|
||||
composerLegendElem.setAttribute( QStringLiteral( "columnCount" ), QString::number( mSettings.columnCount() ) );
|
||||
composerLegendElem.setAttribute( QStringLiteral( "columnCount" ), QString::number( mColumnCount ) );
|
||||
composerLegendElem.setAttribute( QStringLiteral( "splitLayer" ), QString::number( mSettings.splitLayer() ) );
|
||||
composerLegendElem.setAttribute( QStringLiteral( "equalColumnWidth" ), QString::number( mSettings.equalColumnWidth() ) );
|
||||
|
||||
@ -462,14 +463,16 @@ bool QgsComposerLegend::readXml( const QDomElement& itemElem, const QDomDocument
|
||||
}
|
||||
|
||||
//read general properties
|
||||
mSettings.setTitle( itemElem.attribute( QStringLiteral( "title" ) ) );
|
||||
mTitle = itemElem.attribute( QStringLiteral( "title" ) );
|
||||
mSettings.setTitle( mTitle );
|
||||
if ( !itemElem.attribute( QStringLiteral( "titleAlignment" ) ).isEmpty() )
|
||||
{
|
||||
mSettings.setTitleAlignment( static_cast< Qt::AlignmentFlag >( itemElem.attribute( QStringLiteral( "titleAlignment" ) ).toInt() ) );
|
||||
}
|
||||
int colCount = itemElem.attribute( QStringLiteral( "columnCount" ), QStringLiteral( "1" ) ).toInt();
|
||||
if ( colCount < 1 ) colCount = 1;
|
||||
mSettings.setColumnCount( colCount );
|
||||
mColumnCount = colCount;
|
||||
mSettings.setColumnCount( mColumnCount );
|
||||
mSettings.setSplitLayer( itemElem.attribute( QStringLiteral( "splitLayer" ), QStringLiteral( "0" ) ).toInt() == 1 );
|
||||
mSettings.setEqualColumnWidth( itemElem.attribute( QStringLiteral( "equalColumnWidth" ), QStringLiteral( "0" ) ).toInt() == 1 );
|
||||
|
||||
@ -642,6 +645,42 @@ void QgsComposerLegend::invalidateCurrentMap()
|
||||
setComposerMap( nullptr );
|
||||
}
|
||||
|
||||
void QgsComposerLegend::refreshDataDefinedProperty( const QgsComposerObject::DataDefinedProperty property, const QgsExpressionContext* context )
|
||||
{
|
||||
QgsExpressionContext scopedContext = createExpressionContext();
|
||||
const QgsExpressionContext* evalContext = context ? context : &scopedContext;
|
||||
|
||||
bool forceUpdate = false;
|
||||
//updates data defined properties and redraws item to match
|
||||
if ( property == QgsComposerObject::LegendTitle || property == QgsComposerObject::AllProperties )
|
||||
{
|
||||
bool ok = false;
|
||||
QString t = mProperties.valueAsString( QgsComposerObject::LegendTitle, *evalContext, mTitle, &ok );
|
||||
if ( ok )
|
||||
{
|
||||
mSettings.setTitle( t );
|
||||
forceUpdate = true;
|
||||
}
|
||||
}
|
||||
if ( property == QgsComposerObject::LegendColumnCount || property == QgsComposerObject::AllProperties )
|
||||
{
|
||||
bool ok = false;
|
||||
int cols = mProperties.valueAsInt( QgsComposerObject::LegendColumnCount, *evalContext, mColumnCount, &ok );
|
||||
if ( ok && cols >= 0 )
|
||||
{
|
||||
mSettings.setColumnCount( cols );
|
||||
forceUpdate = true;
|
||||
}
|
||||
}
|
||||
if ( forceUpdate )
|
||||
{
|
||||
adjustBoxSize();
|
||||
update();
|
||||
}
|
||||
|
||||
QgsComposerObject::refreshDataDefinedProperty( property, context );
|
||||
}
|
||||
|
||||
void QgsComposerLegend::mapLayerStyleOverridesChanged()
|
||||
{
|
||||
if ( !mComposerMap )
|
||||
|
@ -272,12 +272,21 @@ class CORE_EXPORT QgsComposerLegend : public QgsComposerItem
|
||||
//Overridden to show legend title
|
||||
virtual QString displayName() const override;
|
||||
|
||||
/**
|
||||
* Returns the legend's renderer settings object.
|
||||
* @note added in QGIS 3.0
|
||||
*/
|
||||
const QgsLegendSettings& legendSettings() const { return mSettings; }
|
||||
|
||||
public slots:
|
||||
//! Data changed
|
||||
void synchronizeWithModel();
|
||||
//! Sets mCompositionMap to 0 if the map is deleted
|
||||
void invalidateCurrentMap();
|
||||
|
||||
virtual void refreshDataDefinedProperty( const QgsComposerObject::DataDefinedProperty property = QgsComposerObject::AllProperties, const QgsExpressionContext* context = nullptr ) override;
|
||||
|
||||
|
||||
private slots:
|
||||
void updateFilterByMap( bool redraw = true );
|
||||
|
||||
@ -301,6 +310,9 @@ class CORE_EXPORT QgsComposerLegend : public QgsComposerItem
|
||||
|
||||
QgsLegendSettings mSettings;
|
||||
|
||||
QString mTitle;
|
||||
int mColumnCount = 1;
|
||||
|
||||
const QgsComposerMap* mComposerMap;
|
||||
|
||||
bool mLegendFilterByMap;
|
||||
|
@ -61,6 +61,8 @@ const QgsPropertyDefinition QgsComposerObject::sPropertyNameMap
|
||||
{ QgsComposerObject::PictureSvgBackgroundColor, "dataDefinedSvgBackgroundColor" },
|
||||
{ QgsComposerObject::PictureSvgOutlineColor, "dataDefinedSvgOutlineColor" },
|
||||
{ QgsComposerObject::PictureSvgOutlineWidth, "dataDefinedSvgOutlineWidth" },
|
||||
{ QgsComposerObject::LegendTitle, "dataDefinedLegendTitle" },
|
||||
{ QgsComposerObject::LegendColumnCount, "dataDefinedLegendColumns" },
|
||||
};
|
||||
|
||||
|
||||
|
@ -78,6 +78,9 @@ class CORE_EXPORT QgsComposerObject: public QObject, public QgsExpressionContext
|
||||
PictureSvgOutlineWidth, //!< SVG outline width
|
||||
//html item
|
||||
SourceUrl, //!< Html source url
|
||||
//legend item
|
||||
LegendTitle, //!< Legend title
|
||||
LegendColumnCount, //!< Legend column count
|
||||
};
|
||||
|
||||
static const QgsPropertyDefinition sPropertyNameMap;
|
||||
|
@ -83,13 +83,7 @@
|
||||
<property name="collapsed" stdset="0">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
||||
</property>
|
||||
<property name="labelAlignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="mTitleLabel">
|
||||
<property name="text">
|
||||
@ -100,8 +94,12 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="mTitleLineEdit"/>
|
||||
<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">
|
||||
@ -110,8 +108,12 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QgsComposerItemComboBox" name="mMapComboBox"/>
|
||||
<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">
|
||||
@ -120,21 +122,17 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="mWrapCharLineEdit">
|
||||
<property name="frame">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="mTitleLineEdit"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_15">
|
||||
<item row="0" column="2">
|
||||
<widget class="QgsDataDefinedButtonV2" name="mLegendTitleDDBtn">
|
||||
<property name="text">
|
||||
<string>Title alignment</string>
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<item row="1" column="1" colspan="2">
|
||||
<widget class="QComboBox" name="mTitleAlignCombo">
|
||||
<item>
|
||||
<property name="text">
|
||||
@ -153,10 +151,13 @@
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="mCheckboxResizeContents">
|
||||
<property name="text">
|
||||
<string>Resize to fit contents</string>
|
||||
<item row="2" column="1" colspan="2">
|
||||
<widget class="QgsComposerItemComboBox" name="mMapComboBox"/>
|
||||
</item>
|
||||
<item row="3" column="1" colspan="2">
|
||||
<widget class="QLineEdit" name="mWrapCharLineEdit">
|
||||
<property name="frame">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -550,21 +551,8 @@
|
||||
<property name="collapsed" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
||||
</property>
|
||||
<property name="labelAlignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Count</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="1">
|
||||
<widget class="QgsSpinBox" name="mColumnCountSpinBox">
|
||||
<property name="prefix">
|
||||
<string/>
|
||||
@ -577,14 +565,41 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Count</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QgsDataDefinedButtonV2" name="mColumnsDDBtn">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<spacer name="horizontalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="4">
|
||||
<widget class="QCheckBox" name="mEqualColumnWidthCheckBox">
|
||||
<property name="text">
|
||||
<string>Equal column widths</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="2">
|
||||
<item row="3" column="0" colspan="4">
|
||||
<widget class="QCheckBox" name="mSplitLayerCheckBox">
|
||||
<property name="toolTip">
|
||||
<string>Allow splitting layer items into multiple columns.</string>
|
||||
@ -1013,18 +1028,17 @@
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>QgsCollapsibleGroupBoxBasic</class>
|
||||
<extends>QGroupBox</extends>
|
||||
<header>qgscollapsiblegroupbox.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>QgsColorButton</class>
|
||||
<extends>QToolButton</extends>
|
||||
<header>qgscolorbutton.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>QgsDataDefinedButtonV2</class>
|
||||
<extends>QToolButton</extends>
|
||||
<header>qgsdatadefinedbuttonv2.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>QgsDoubleSpinBox</class>
|
||||
<extends>QDoubleSpinBox</extends>
|
||||
@ -1035,6 +1049,12 @@
|
||||
<extends>QSpinBox</extends>
|
||||
<header>qgsspinbox.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>QgsCollapsibleGroupBoxBasic</class>
|
||||
<extends>QGroupBox</extends>
|
||||
<header location="global">qgscollapsiblegroupbox.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>QgsComposerItemComboBox</class>
|
||||
<extends>QComboBox</extends>
|
||||
@ -1055,6 +1075,7 @@
|
||||
<tabstop>scrollArea</tabstop>
|
||||
<tabstop>mMainPropertiesColGroupBox</tabstop>
|
||||
<tabstop>mTitleLineEdit</tabstop>
|
||||
<tabstop>mLegendTitleDDBtn</tabstop>
|
||||
<tabstop>mTitleAlignCombo</tabstop>
|
||||
<tabstop>mMapComboBox</tabstop>
|
||||
<tabstop>mWrapCharLineEdit</tabstop>
|
||||
@ -1080,6 +1101,7 @@
|
||||
<tabstop>mItemFontButton</tabstop>
|
||||
<tabstop>mFontColorButton</tabstop>
|
||||
<tabstop>mColumnsColGroupBox</tabstop>
|
||||
<tabstop>mColumnsDDBtn</tabstop>
|
||||
<tabstop>mColumnCountSpinBox</tabstop>
|
||||
<tabstop>mEqualColumnWidthCheckBox</tabstop>
|
||||
<tabstop>mSplitLayerCheckBox</tabstop>
|
||||
@ -1100,6 +1122,7 @@
|
||||
<tabstop>mIconLabelSpaceSpinBox</tabstop>
|
||||
<tabstop>mBoxSpaceSpinBox</tabstop>
|
||||
<tabstop>mColumnSpaceSpinBox</tabstop>
|
||||
<tabstop>mLineSpacingSpinBox</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="../../../images/images.qrc"/>
|
||||
|
@ -24,7 +24,9 @@ from qgis.core import (QgsComposerLegend,
|
||||
QgsMarkerSymbol,
|
||||
QgsSingleSymbolRenderer,
|
||||
QgsRectangle,
|
||||
QgsProject
|
||||
QgsProject,
|
||||
QgsComposerObject,
|
||||
QgsExpressionBasedProperty
|
||||
)
|
||||
from qgis.testing import (start_app,
|
||||
unittest
|
||||
@ -200,5 +202,41 @@ class TestQgsComposerLegend(unittest.TestCase):
|
||||
|
||||
QgsProject.instance().removeMapLayers([point_layer.id()])
|
||||
|
||||
def testDataDefinedTitle(self):
|
||||
mapSettings = QgsMapSettings()
|
||||
|
||||
composition = QgsComposition(mapSettings, QgsProject.instance())
|
||||
composition.setPaperSize(297, 210)
|
||||
|
||||
legend = QgsComposerLegend(composition)
|
||||
composition.addComposerLegend(legend)
|
||||
|
||||
legend.setTitle('original')
|
||||
self.assertEqual(legend.title(), 'original')
|
||||
self.assertEqual(legend.legendSettings().title(), 'original')
|
||||
|
||||
legend.dataDefinedProperties().setProperty(QgsComposerObject.LegendTitle, QgsExpressionBasedProperty("'new'"))
|
||||
legend.refreshDataDefinedProperty()
|
||||
self.assertEqual(legend.title(), 'original')
|
||||
self.assertEqual(legend.legendSettings().title(), 'new')
|
||||
|
||||
def testDataDefinedColumnCount(self):
|
||||
mapSettings = QgsMapSettings()
|
||||
|
||||
composition = QgsComposition(mapSettings, QgsProject.instance())
|
||||
composition.setPaperSize(297, 210)
|
||||
|
||||
legend = QgsComposerLegend(composition)
|
||||
composition.addComposerLegend(legend)
|
||||
|
||||
legend.setColumnCount(2)
|
||||
self.assertEqual(legend.columnCount(), 2)
|
||||
self.assertEqual(legend.legendSettings().columnCount(), 2)
|
||||
|
||||
legend.dataDefinedProperties().setProperty(QgsComposerObject.LegendColumnCount, QgsExpressionBasedProperty("5"))
|
||||
legend.refreshDataDefinedProperty()
|
||||
self.assertEqual(legend.columnCount(), 2)
|
||||
self.assertEqual(legend.legendSettings().columnCount(), 5)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
Loading…
x
Reference in New Issue
Block a user