mirror of
https://github.com/qgis/QGIS.git
synced 2025-12-05 00:04:40 -05:00
Port legend item
This commit is contained in:
parent
585a8b70ba
commit
d3430e4d42
@ -11,31 +11,6 @@
|
||||
|
||||
|
||||
|
||||
class QgsLegendModel : QgsLayerTreeModel
|
||||
{
|
||||
%Docstring
|
||||
Item model implementation based on layer tree model for composer legend.
|
||||
Overrides some functionality of QgsLayerTreeModel to better fit the needs of composer legend.
|
||||
|
||||
.. versionadded:: 2.6
|
||||
%End
|
||||
|
||||
%TypeHeaderCode
|
||||
#include "qgscomposerlegend.h"
|
||||
%End
|
||||
public:
|
||||
QgsLegendModel( QgsLayerTree *rootNode, QObject *parent /TransferThis/ = 0 );
|
||||
%Docstring
|
||||
Construct the model based on the given layer tree
|
||||
%End
|
||||
|
||||
virtual QVariant data( const QModelIndex &index, int role ) const;
|
||||
|
||||
|
||||
virtual Qt::ItemFlags flags( const QModelIndex &index ) const;
|
||||
|
||||
};
|
||||
|
||||
|
||||
class QgsComposerLegend : QgsComposerItem
|
||||
{
|
||||
@ -48,6 +23,7 @@ class QgsComposerLegend : QgsComposerItem
|
||||
%End
|
||||
public:
|
||||
QgsComposerLegend( QgsComposition *composition /TransferThis/ );
|
||||
~QgsComposerLegend();
|
||||
|
||||
virtual int type() const;
|
||||
%Docstring
|
||||
|
||||
@ -408,6 +408,7 @@
|
||||
%Include layout/qgslayoutitem.sip
|
||||
%Include layout/qgslayoutitemgroup.sip
|
||||
%Include layout/qgslayoutitemlabel.sip
|
||||
%Include layout/qgslayoutitemlegend.sip
|
||||
%Include layout/qgslayoutitemmap.sip
|
||||
%Include layout/qgslayoutitemmapgrid.sip
|
||||
%Include layout/qgslayoutitemmapitem.sip
|
||||
|
||||
@ -84,6 +84,23 @@ class QgsLayoutItem : QgsLayoutObject, QGraphicsRectItem, QgsLayoutUndoObjectInt
|
||||
UndoLabelFont,
|
||||
UndoLabelMargin,
|
||||
UndoLabelFontColor,
|
||||
UndoLegendText,
|
||||
UndoLegendColumnCount,
|
||||
UndoLegendSymbolWidth,
|
||||
UndoLegendSymbolHeight,
|
||||
UndoLegendWmsLegendWidth,
|
||||
UndoLegendWmsLegendHeight,
|
||||
UndoLegendTitleSpaceBottom,
|
||||
UndoLegendGroupSpace,
|
||||
UndoLegendLayerSpace,
|
||||
UndoLegendSymbolSpace,
|
||||
UndoLegendIconSymbolSpace,
|
||||
UndoLegendFontColor,
|
||||
UndoLegendBoxSpace,
|
||||
UndoLegendColumnSpace,
|
||||
UndoLegendLineSpacing,
|
||||
UndoLegendRasterStrokeWidth,
|
||||
UndoLegendRasterStrokeColor,
|
||||
UndoCustomCommand,
|
||||
};
|
||||
|
||||
|
||||
474
python/core/layout/qgslayoutitemlegend.sip
Normal file
474
python/core/layout/qgslayoutitemlegend.sip
Normal file
@ -0,0 +1,474 @@
|
||||
/************************************************************************
|
||||
* This file has been generated automatically from *
|
||||
* *
|
||||
* src/core/layout/qgslayoutitemlegend.h *
|
||||
* *
|
||||
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||
************************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class QgsLegendModel : QgsLayerTreeModel
|
||||
{
|
||||
%Docstring
|
||||
Item model implementation based on layer tree model for layout legend.
|
||||
|
||||
Overrides some functionality of QgsLayerTreeModel to better fit the needs of layout legends.
|
||||
|
||||
.. versionadded:: 2.6
|
||||
%End
|
||||
|
||||
%TypeHeaderCode
|
||||
#include "qgslayoutitemlegend.h"
|
||||
%End
|
||||
public:
|
||||
QgsLegendModel( QgsLayerTree *rootNode, QObject *parent /TransferThis/ = 0 );
|
||||
%Docstring
|
||||
Construct the model based on the given layer tree
|
||||
%End
|
||||
|
||||
virtual QVariant data( const QModelIndex &index, int role ) const;
|
||||
|
||||
|
||||
virtual Qt::ItemFlags flags( const QModelIndex &index ) const;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
class QgsLayoutItemLegend : QgsLayoutItem
|
||||
{
|
||||
%Docstring
|
||||
A layout item subclass for map legends.
|
||||
.. versionadded:: 3.0
|
||||
%End
|
||||
|
||||
%TypeHeaderCode
|
||||
#include "qgslayoutitemlegend.h"
|
||||
%End
|
||||
public:
|
||||
|
||||
QgsLayoutItemLegend( QgsLayout *layout );
|
||||
%Docstring
|
||||
Constructor for QgsLayoutItemLegend, with the specified parent ``layout``.
|
||||
%End
|
||||
|
||||
static QgsLayoutItemLegend *create( QgsLayout *layout ) /Factory/;
|
||||
%Docstring
|
||||
Returns a new legend item for the specified ``layout``.
|
||||
|
||||
The caller takes responsibility for deleting the returned object.
|
||||
:rtype: QgsLayoutItemLegend
|
||||
%End
|
||||
|
||||
virtual int type() const;
|
||||
|
||||
virtual QString stringType() const;
|
||||
|
||||
virtual QString displayName() const;
|
||||
|
||||
|
||||
void adjustBoxSize();
|
||||
%Docstring
|
||||
Sets the legend's item bounds to fit the whole legend content.
|
||||
%End
|
||||
|
||||
void setResizeToContents( bool enabled );
|
||||
%Docstring
|
||||
Sets whether the legend should automatically resize to fit its contents.
|
||||
\param enabled set to false to disable automatic resizing. The legend frame will not
|
||||
be expanded to fit legend items, and items may be cropped from display.
|
||||
.. seealso:: resizeToContents()
|
||||
%End
|
||||
|
||||
bool resizeToContents() const;
|
||||
%Docstring
|
||||
Returns whether the legend should automatically resize to fit its contents.
|
||||
.. seealso:: setResizeToContents()
|
||||
:rtype: bool
|
||||
%End
|
||||
|
||||
QgsLegendModel *model();
|
||||
%Docstring
|
||||
Returns the legend model.
|
||||
:rtype: QgsLegendModel
|
||||
%End
|
||||
|
||||
void setAutoUpdateModel( bool autoUpdate );
|
||||
%Docstring
|
||||
Sets whether the legend content should auto update to reflect changes in the project's
|
||||
layer tree.
|
||||
.. seealso:: autoUpdateModel()
|
||||
%End
|
||||
|
||||
bool autoUpdateModel() const;
|
||||
%Docstring
|
||||
Returns whether the legend content should auto update to reflect changes in the project's
|
||||
layer tree.
|
||||
.. seealso:: setAutoUpdateModel()
|
||||
:rtype: bool
|
||||
%End
|
||||
|
||||
void setLegendFilterByMapEnabled( bool enabled );
|
||||
%Docstring
|
||||
Set whether legend items should be filtered to show just the ones visible in the associated map.
|
||||
.. seealso:: legendFilterByMapEnabled()
|
||||
%End
|
||||
|
||||
bool legendFilterByMapEnabled() const;
|
||||
%Docstring
|
||||
Find out whether legend items are filtered to show just the ones visible in the associated map
|
||||
.. seealso:: setLegendFilterByMapEnabled()
|
||||
:rtype: bool
|
||||
%End
|
||||
|
||||
|
||||
void setLegendFilterOutAtlas( bool doFilter );
|
||||
%Docstring
|
||||
When set to true, during an atlas rendering, it will filter out legend elements
|
||||
where features are outside the current atlas feature.
|
||||
.. seealso:: legendFilterOutAtlas()
|
||||
%End
|
||||
|
||||
bool legendFilterOutAtlas() const;
|
||||
%Docstring
|
||||
Returns whether to filter out legend elements outside of the current atlas feature.
|
||||
.. seealso:: setLegendFilterOutAtlas()
|
||||
:rtype: bool
|
||||
%End
|
||||
|
||||
void setTitle( const QString &title );
|
||||
%Docstring
|
||||
Sets the legend ``title``.
|
||||
.. seealso:: title()
|
||||
%End
|
||||
|
||||
QString title() const;
|
||||
%Docstring
|
||||
Returns the legend title.
|
||||
.. seealso:: setTitle()
|
||||
:rtype: str
|
||||
%End
|
||||
|
||||
Qt::AlignmentFlag titleAlignment() const;
|
||||
%Docstring
|
||||
Returns the alignment of the legend title.
|
||||
.. seealso:: setTitleAlignment()
|
||||
:rtype: Qt.AlignmentFlag
|
||||
%End
|
||||
|
||||
void setTitleAlignment( Qt::AlignmentFlag alignment );
|
||||
%Docstring
|
||||
Sets the ``alignment`` of the legend title.
|
||||
.. seealso:: titleAlignment()
|
||||
%End
|
||||
|
||||
QgsLegendStyle &rstyle( QgsLegendStyle::Style s );
|
||||
%Docstring
|
||||
Returns reference to modifiable legend style.
|
||||
:rtype: QgsLegendStyle
|
||||
%End
|
||||
|
||||
QgsLegendStyle style( QgsLegendStyle::Style s ) const;
|
||||
%Docstring
|
||||
Returns legend style.
|
||||
:rtype: QgsLegendStyle
|
||||
%End
|
||||
|
||||
void setStyle( QgsLegendStyle::Style component, const QgsLegendStyle &style );
|
||||
%Docstring
|
||||
Sets the style of ``component`` to ``style`` for the legend.
|
||||
%End
|
||||
|
||||
QFont styleFont( QgsLegendStyle::Style component ) const;
|
||||
%Docstring
|
||||
Returns the font settings for a legend ``component``.
|
||||
.. seealso:: setStyleFont()
|
||||
:rtype: QFont
|
||||
%End
|
||||
|
||||
void setStyleFont( QgsLegendStyle::Style component, const QFont &font );
|
||||
%Docstring
|
||||
Sets the style ``font`` for a legend ``component``.
|
||||
.. seealso:: styleFont()
|
||||
%End
|
||||
|
||||
void setStyleMargin( QgsLegendStyle::Style component, double margin );
|
||||
%Docstring
|
||||
Set the ``margin`` for a legend ``component``.
|
||||
%End
|
||||
|
||||
void setStyleMargin( QgsLegendStyle::Style component, QgsLegendStyle::Side side, double margin );
|
||||
%Docstring
|
||||
Set the ``margin`` for a particular ``side`` of a legend ``component``.
|
||||
%End
|
||||
|
||||
double lineSpacing() const;
|
||||
%Docstring
|
||||
Returns the spacing in-between lines in layout units.
|
||||
.. seealso:: setLineSpacing()
|
||||
:rtype: float
|
||||
%End
|
||||
|
||||
void setLineSpacing( double spacing );
|
||||
%Docstring
|
||||
Sets the ``spacing`` in-between multiple lines.
|
||||
.. seealso:: lineSpacing()
|
||||
%End
|
||||
|
||||
double boxSpace() const;
|
||||
%Docstring
|
||||
Returns the legend box space.
|
||||
.. seealso:: setBoxSpace()
|
||||
:rtype: float
|
||||
%End
|
||||
|
||||
void setBoxSpace( double space );
|
||||
%Docstring
|
||||
Sets the legend box ``space``.
|
||||
.. seealso:: boxSpace()
|
||||
%End
|
||||
|
||||
double columnSpace() const;
|
||||
%Docstring
|
||||
Returns the legend column spacing.
|
||||
.. seealso:: setColumnSpace()
|
||||
:rtype: float
|
||||
%End
|
||||
|
||||
void setColumnSpace( double spacing );
|
||||
%Docstring
|
||||
Sets the legend column ``spacing``.
|
||||
.. seealso:: columnSpace()
|
||||
%End
|
||||
|
||||
QColor fontColor() const;
|
||||
%Docstring
|
||||
Returns the legend font color.
|
||||
.. seealso:: setFontColor()
|
||||
:rtype: QColor
|
||||
%End
|
||||
|
||||
void setFontColor( const QColor &color );
|
||||
%Docstring
|
||||
Sets the legend font ``color``.
|
||||
.. seealso:: fontColor()
|
||||
%End
|
||||
|
||||
double symbolWidth() const;
|
||||
%Docstring
|
||||
Returns the legend symbol width.
|
||||
.. seealso:: setSymbolWidth()
|
||||
:rtype: float
|
||||
%End
|
||||
|
||||
void setSymbolWidth( double width );
|
||||
%Docstring
|
||||
Sets the legend symbol ``width``.
|
||||
.. seealso:: symbolWidth()
|
||||
%End
|
||||
|
||||
double symbolHeight() const;
|
||||
%Docstring
|
||||
Returns the legend symbol height.
|
||||
.. seealso:: setSymbolHeight()
|
||||
:rtype: float
|
||||
%End
|
||||
|
||||
void setSymbolHeight( double height );
|
||||
%Docstring
|
||||
Sets the legend symbol ``height``.
|
||||
.. seealso:: symbolHeight()
|
||||
%End
|
||||
|
||||
double wmsLegendWidth() const;
|
||||
%Docstring
|
||||
Returns the WMS legend width.
|
||||
.. seealso:: setWmsLegendWidth()
|
||||
:rtype: float
|
||||
%End
|
||||
|
||||
void setWmsLegendWidth( double width );
|
||||
%Docstring
|
||||
Sets the WMS legend ``width``.
|
||||
.. seealso:: wmsLegendWidth()
|
||||
%End
|
||||
|
||||
double wmsLegendHeight() const;
|
||||
%Docstring
|
||||
Returns the WMS legend height.
|
||||
.. seealso:: setWmsLegendHeight()
|
||||
:rtype: float
|
||||
%End
|
||||
|
||||
void setWmsLegendHeight( double height );
|
||||
%Docstring
|
||||
Sets the WMS legend ``height``.
|
||||
.. seealso:: wmsLegendHeight()
|
||||
%End
|
||||
|
||||
void setWrapString( const QString &string );
|
||||
%Docstring
|
||||
Sets the legend text wrapping ``string``.
|
||||
.. seealso:: wrapString()
|
||||
%End
|
||||
|
||||
QString wrapString() const;
|
||||
%Docstring
|
||||
Returns the legend text wrapping string.
|
||||
.. seealso:: setWrapString()
|
||||
:rtype: str
|
||||
%End
|
||||
|
||||
int columnCount() const;
|
||||
%Docstring
|
||||
Returns the legend column count.
|
||||
.. seealso:: setColumnCount()
|
||||
:rtype: int
|
||||
%End
|
||||
|
||||
void setColumnCount( int count );
|
||||
%Docstring
|
||||
Sets the legend column ``count``.
|
||||
.. seealso:: columnCount()
|
||||
%End
|
||||
|
||||
bool splitLayer() const;
|
||||
%Docstring
|
||||
Returns whether the legend items from a single layer can be split
|
||||
over multiple columns.
|
||||
.. seealso:: setSplitLayer()
|
||||
:rtype: bool
|
||||
%End
|
||||
|
||||
void setSplitLayer( bool enabled );
|
||||
%Docstring
|
||||
Sets whether the legend items from a single layer can be split
|
||||
over multiple columns.
|
||||
.. seealso:: splitLayer()
|
||||
%End
|
||||
|
||||
bool equalColumnWidth() const;
|
||||
%Docstring
|
||||
Returns whether column widths should be equalized.
|
||||
.. seealso:: setEqualColumnWidth()
|
||||
:rtype: bool
|
||||
%End
|
||||
|
||||
void setEqualColumnWidth( bool equalize );
|
||||
%Docstring
|
||||
Sets whether column widths should be equalized.
|
||||
.. seealso:: equalColumnWidth()
|
||||
%End
|
||||
|
||||
bool drawRasterStroke() const;
|
||||
%Docstring
|
||||
Returns whether a stroke will be drawn around raster symbol items.
|
||||
.. seealso:: setDrawRasterStroke()
|
||||
.. seealso:: rasterStrokeColor()
|
||||
.. seealso:: rasterStrokeWidth()
|
||||
:rtype: bool
|
||||
%End
|
||||
|
||||
void setDrawRasterStroke( bool enabled );
|
||||
%Docstring
|
||||
Sets whether a stroke will be drawn around raster symbol items.
|
||||
\param enabled set to true to draw borders
|
||||
.. seealso:: drawRasterStroke()
|
||||
.. seealso:: setRasterStrokeColor()
|
||||
.. seealso:: setRasterStrokeWidth()
|
||||
%End
|
||||
|
||||
QColor rasterStrokeColor() const;
|
||||
%Docstring
|
||||
Returns the stroke color for the stroke drawn around raster symbol items. The stroke is
|
||||
only drawn if drawRasterStroke() is true.
|
||||
.. seealso:: setRasterStrokeColor()
|
||||
.. seealso:: drawRasterStroke()
|
||||
.. seealso:: rasterStrokeWidth()
|
||||
:rtype: QColor
|
||||
%End
|
||||
|
||||
void setRasterStrokeColor( const QColor &color );
|
||||
%Docstring
|
||||
Sets the stroke ``color`` for the stroke drawn around raster symbol items. The stroke is
|
||||
only drawn if drawRasterStroke() is true.
|
||||
.. seealso:: rasterStrokeColor()
|
||||
.. seealso:: setDrawRasterStroke()
|
||||
.. seealso:: setRasterStrokeWidth()
|
||||
%End
|
||||
|
||||
double rasterStrokeWidth() const;
|
||||
%Docstring
|
||||
Returns the stroke width (in layout units) for the stroke drawn around raster symbol items. The stroke is
|
||||
only drawn if drawRasterStroke() is true.
|
||||
.. seealso:: setRasterStrokeWidth()
|
||||
.. seealso:: drawRasterStroke()
|
||||
.. seealso:: rasterStrokeColor()
|
||||
:rtype: float
|
||||
%End
|
||||
|
||||
void setRasterStrokeWidth( double width );
|
||||
%Docstring
|
||||
Sets the stroke width for the stroke drawn around raster symbol items. The stroke is
|
||||
only drawn if drawRasterStroke() is true.
|
||||
.. seealso:: rasterStrokeWidth()
|
||||
.. seealso:: setDrawRasterStroke()
|
||||
.. seealso:: setRasterStrokeColor()
|
||||
%End
|
||||
|
||||
void setMap( QgsLayoutItemMap *map );
|
||||
%Docstring
|
||||
Sets the ``map`` to associate with the legend.
|
||||
.. seealso:: map()
|
||||
%End
|
||||
|
||||
QgsLayoutItemMap *map() const;
|
||||
%Docstring
|
||||
Returns the associated map.
|
||||
.. seealso:: setMap()
|
||||
:rtype: QgsLayoutItemMap
|
||||
%End
|
||||
|
||||
void updateLegend();
|
||||
%Docstring
|
||||
Updates the model and all legend entries.
|
||||
%End
|
||||
|
||||
void updateFilterByMap( bool redraw = true );
|
||||
%Docstring
|
||||
Updates the legend content when filtered by map.
|
||||
%End
|
||||
|
||||
|
||||
const QgsLegendSettings &legendSettings() const;
|
||||
%Docstring
|
||||
Returns the legend's renderer settings object.
|
||||
:rtype: QgsLegendSettings
|
||||
%End
|
||||
|
||||
virtual void paint( QPainter *painter, const QStyleOptionGraphicsItem *itemStyle, QWidget *pWidget );
|
||||
|
||||
|
||||
|
||||
public slots:
|
||||
|
||||
virtual void refreshDataDefinedProperty( const QgsLayoutObject::DataDefinedProperty property = QgsLayoutObject::AllProperties );
|
||||
|
||||
|
||||
protected:
|
||||
virtual void draw( QgsRenderContext &context, const QStyleOptionGraphicsItem *itemStyle = 0 );
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* This file has been generated automatically from *
|
||||
* *
|
||||
* src/core/layout/qgslayoutitemlegend.h *
|
||||
* *
|
||||
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||
************************************************************************/
|
||||
@ -405,6 +405,20 @@ Returns true if the map contains layers with blend modes or flattened layers for
|
||||
virtual QgsExpressionContext createExpressionContext() const;
|
||||
|
||||
|
||||
double mapUnitsToLayoutUnits() const;
|
||||
%Docstring
|
||||
Returns the conversion factor from map units to layout units.
|
||||
This is calculated using the width of the map item and the width of the
|
||||
current visible map extent.
|
||||
:rtype: float
|
||||
%End
|
||||
|
||||
QgsMapSettings mapSettings( const QgsRectangle &extent, QSizeF size, int dpi ) const;
|
||||
%Docstring
|
||||
Return map settings that will be used for drawing of the map.
|
||||
:rtype: QgsMapSettings
|
||||
%End
|
||||
|
||||
protected:
|
||||
|
||||
virtual void draw( QgsRenderContext &context, const QStyleOptionGraphicsItem *itemStyle = 0 );
|
||||
@ -414,12 +428,6 @@ Returns true if the map contains layers with blend modes or flattened layers for
|
||||
virtual bool readPropertiesFromElement( const QDomElement &element, const QDomDocument &document, const QgsReadWriteContext &context );
|
||||
|
||||
|
||||
QgsMapSettings mapSettings( const QgsRectangle &extent, QSizeF size, int dpi ) const;
|
||||
%Docstring
|
||||
Return map settings that will be used for drawing of the map.
|
||||
:rtype: QgsMapSettings
|
||||
%End
|
||||
|
||||
bool isDrawing() const;
|
||||
%Docstring
|
||||
True if a draw is already in progress
|
||||
@ -430,14 +438,6 @@ True if a draw is already in progress
|
||||
virtual QRectF boundingRect() const;
|
||||
|
||||
|
||||
double mapUnitsToLayoutUnits() const;
|
||||
%Docstring
|
||||
Returns the conversion factor from map units to layout units.
|
||||
This is calculated using the width of the map item and the width of the
|
||||
current visible map extent.
|
||||
:rtype: float
|
||||
%End
|
||||
|
||||
QPolygonF transformedMapPolygon() const;
|
||||
%Docstring
|
||||
Returns extent that considers rotation and shift with mOffsetX / mOffsetY
|
||||
|
||||
@ -105,6 +105,7 @@ class QgsLayoutItemRegistry : QObject
|
||||
LayoutMap,
|
||||
LayoutPicture,
|
||||
LayoutLabel,
|
||||
LayoutLegend,
|
||||
LayoutShape,
|
||||
LayoutPolygon,
|
||||
LayoutPolyline,
|
||||
|
||||
@ -180,6 +180,7 @@ SET(QGIS_APP_SRCS
|
||||
layout/qgslayoutitemslistview.cpp
|
||||
layout/qgslayoutappmenuprovider.cpp
|
||||
layout/qgslayoutlabelwidget.cpp
|
||||
layout/qgslayoutlegendwidget.cpp
|
||||
layout/qgslayoutmapwidget.cpp
|
||||
layout/qgslayoutmapgridwidget.cpp
|
||||
layout/qgslayoutpagepropertieswidget.cpp
|
||||
@ -383,6 +384,7 @@ SET (QGIS_APP_MOC_HDRS
|
||||
layout/qgslayoutguidewidget.h
|
||||
layout/qgslayoutitemslistview.h
|
||||
layout/qgslayoutlabelwidget.h
|
||||
layout/qgslayoutlegendwidget.h
|
||||
layout/qgslayoutmapwidget.h
|
||||
layout/qgslayoutmapgridwidget.h
|
||||
layout/qgslayoutpagepropertieswidget.h
|
||||
|
||||
@ -34,6 +34,7 @@
|
||||
#include "qgsmaplayerlegend.h"
|
||||
#include "qgsproject.h"
|
||||
#include "qgsvectorlayer.h"
|
||||
#include "qgslayoutitemlegend.h"
|
||||
|
||||
#include <QMessageBox>
|
||||
#include <QInputDialog>
|
||||
|
||||
@ -31,6 +31,8 @@
|
||||
#include "qgslayoutitempicture.h"
|
||||
#include "qgslayoutitemlabel.h"
|
||||
#include "qgslayoutlabelwidget.h"
|
||||
#include "qgslayoutitemlegend.h"
|
||||
#include "qgslayoutlegendwidget.h"
|
||||
#include "qgisapp.h"
|
||||
#include "qgsmapcanvas.h"
|
||||
|
||||
@ -110,6 +112,32 @@ void QgsLayoutAppUtils::registerGuiForKnownItemTypes()
|
||||
registry->addLayoutItemGuiMetadata( labelItemMetadata.release() );
|
||||
|
||||
|
||||
// legend item
|
||||
|
||||
auto legendItemMetadata = qgis::make_unique< QgsLayoutItemGuiMetadata >( QgsLayoutItemRegistry::LayoutLegend, QObject::tr( "Legend" ), QgsApplication::getThemeIcon( QStringLiteral( "/mActionAddLegend.svg" ) ),
|
||||
[ = ]( QgsLayoutItem * item )->QgsLayoutItemBaseWidget *
|
||||
{
|
||||
return new QgsLayoutLegendWidget( qobject_cast< QgsLayoutItemLegend * >( item ) );
|
||||
}, createRubberBand );
|
||||
legendItemMetadata->setItemAddedToLayoutFunction( [ = ]( QgsLayoutItem * item )
|
||||
{
|
||||
QgsLayoutItemLegend *legend = qobject_cast< QgsLayoutItemLegend * >( item );
|
||||
Q_ASSERT( legend );
|
||||
|
||||
QList<QgsLayoutItemMap *> mapItems;
|
||||
legend->layout()->layoutItems( mapItems );
|
||||
|
||||
if ( !mapItems.isEmpty() )
|
||||
{
|
||||
legend->setMap( mapItems.at( 0 ) );
|
||||
}
|
||||
|
||||
legend->updateLegend();
|
||||
} );
|
||||
|
||||
registry->addLayoutItemGuiMetadata( legendItemMetadata.release() );
|
||||
|
||||
|
||||
// shape items
|
||||
|
||||
auto createShapeWidget =
|
||||
|
||||
@ -48,7 +48,6 @@ QgsLayoutLabelWidget::QgsLayoutLabelWidget( QgsLayoutItemLabel *label )
|
||||
|
||||
//add widget for general composer item properties
|
||||
mItemPropertiesWidget = new QgsLayoutItemPropertiesWidget( this, label );
|
||||
//shapes don't use background or frame, since the symbol style is set through a QgsSymbolSelectorWidget
|
||||
mainLayout->addWidget( mItemPropertiesWidget );
|
||||
|
||||
mFontColorButton->setColorDialogTitle( tr( "Select Font Color" ) );
|
||||
|
||||
1154
src/app/layout/qgslayoutlegendwidget.cpp
Normal file
1154
src/app/layout/qgslayoutlegendwidget.cpp
Normal file
File diff suppressed because it is too large
Load Diff
135
src/app/layout/qgslayoutlegendwidget.h
Normal file
135
src/app/layout/qgslayoutlegendwidget.h
Normal file
@ -0,0 +1,135 @@
|
||||
/***************************************************************************
|
||||
qgslayoutlegendwidget.h
|
||||
-----------------------
|
||||
begin : October 2017
|
||||
copyright : (C) 2017 by Nyall Dawson
|
||||
email : nyall dot dawson at gmail dot com
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef QGSLAYOUTLEGENDWIDGET_H
|
||||
#define QGSLAYOUTLEGENDWIDGET_H
|
||||
|
||||
#include "ui_qgslayoutlegendwidgetbase.h"
|
||||
#include "qgslayoutitemwidget.h"
|
||||
#include <QWidget>
|
||||
#include <QItemDelegate>
|
||||
|
||||
class QgsLayoutItemLegend;
|
||||
|
||||
|
||||
/**
|
||||
* \ingroup app
|
||||
* A widget for setting properties relating to a layout legend.
|
||||
*/
|
||||
class QgsLayoutLegendWidget: public QgsLayoutItemBaseWidget, private Ui::QgsLayoutLegendWidgetBase
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit QgsLayoutLegendWidget( QgsLayoutItemLegend *legend );
|
||||
|
||||
//! Updates the legend layers and groups
|
||||
void updateLegend();
|
||||
|
||||
QgsLayoutItemLegend *legend() { return mLegend; }
|
||||
|
||||
protected:
|
||||
|
||||
bool setNewItem( QgsLayoutItem *item ) override;
|
||||
|
||||
public slots:
|
||||
|
||||
void mWrapCharLineEdit_textChanged( const QString &text );
|
||||
void mTitleLineEdit_textChanged( const QString &text );
|
||||
void mTitleAlignCombo_currentIndexChanged( int index );
|
||||
void mColumnCountSpinBox_valueChanged( int c );
|
||||
void mSplitLayerCheckBox_toggled( bool checked );
|
||||
void mEqualColumnWidthCheckBox_toggled( bool checked );
|
||||
void mSymbolWidthSpinBox_valueChanged( double d );
|
||||
void mSymbolHeightSpinBox_valueChanged( double d );
|
||||
void mWmsLegendWidthSpinBox_valueChanged( double d );
|
||||
void mWmsLegendHeightSpinBox_valueChanged( double d );
|
||||
void mTitleSpaceBottomSpinBox_valueChanged( double d );
|
||||
void mGroupSpaceSpinBox_valueChanged( double d );
|
||||
void mLayerSpaceSpinBox_valueChanged( double d );
|
||||
void mSymbolSpaceSpinBox_valueChanged( double d );
|
||||
void mIconLabelSpaceSpinBox_valueChanged( double d );
|
||||
void mFontColorButton_colorChanged( const QColor &newFontColor );
|
||||
void mBoxSpaceSpinBox_valueChanged( double d );
|
||||
void mColumnSpaceSpinBox_valueChanged( double d );
|
||||
void mLineSpacingSpinBox_valueChanged( double d );
|
||||
void mCheckBoxAutoUpdate_stateChanged( int state );
|
||||
void composerMapChanged( QgsLayoutItem *item );
|
||||
void mCheckboxResizeContents_toggled( bool checked );
|
||||
|
||||
void mRasterStrokeGroupBox_toggled( bool state );
|
||||
void mRasterStrokeWidthSpinBox_valueChanged( double d );
|
||||
void mRasterStrokeColorButton_colorChanged( const QColor &newColor );
|
||||
|
||||
//item manipulation
|
||||
void mMoveDownToolButton_clicked();
|
||||
void mMoveUpToolButton_clicked();
|
||||
void mRemoveToolButton_clicked();
|
||||
void mAddToolButton_clicked();
|
||||
void mEditPushButton_clicked();
|
||||
void mCountToolButton_clicked( bool checked );
|
||||
void mExpressionFilterButton_toggled( bool checked );
|
||||
void mFilterByMapToolButton_toggled( bool checked );
|
||||
void resetLayerNodeToDefaults();
|
||||
void mUpdateAllPushButton_clicked();
|
||||
void mAddGroupToolButton_clicked();
|
||||
|
||||
void mFilterLegendByAtlasCheckBox_toggled( bool checked );
|
||||
|
||||
void selectedChanged( const QModelIndex ¤t, const QModelIndex &previous );
|
||||
|
||||
void setCurrentNodeStyleFromAction();
|
||||
|
||||
private slots:
|
||||
//! Sets GUI according to state of mLegend
|
||||
void setGuiElements();
|
||||
|
||||
//! Update the enabling state of the filter by atlas button
|
||||
void updateFilterLegendByAtlasButton();
|
||||
|
||||
void mItemTreeView_doubleClicked( const QModelIndex &index );
|
||||
void titleFontChanged();
|
||||
void groupFontChanged();
|
||||
void layerFontChanged();
|
||||
void itemFontChanged();
|
||||
|
||||
private:
|
||||
QgsLayoutLegendWidget() = delete;
|
||||
void blockAllSignals( bool b );
|
||||
|
||||
QgsLayoutItemLegend *mLegend = nullptr;
|
||||
|
||||
QgsLayoutItemPropertiesWidget *mItemPropertiesWidget = nullptr;
|
||||
};
|
||||
|
||||
|
||||
class QgsLayoutLegendMenuProvider : public QgsLayerTreeViewMenuProvider
|
||||
{
|
||||
|
||||
public:
|
||||
QgsLayoutLegendMenuProvider( QgsLayerTreeView *view, QgsLayoutLegendWidget *w );
|
||||
|
||||
virtual QMenu *createContextMenu() override;
|
||||
|
||||
protected:
|
||||
QgsLayerTreeView *mView = nullptr;
|
||||
QgsLayoutLegendWidget *mWidget = nullptr;
|
||||
};
|
||||
|
||||
|
||||
#endif //QGSLAYOUTLEGENDWIDGET_H
|
||||
|
||||
@ -370,6 +370,7 @@ SET(QGIS_CORE_SRCS
|
||||
layout/qgslayoutitemgroup.cpp
|
||||
layout/qgslayoutitemgroupundocommand.cpp
|
||||
layout/qgslayoutitemlabel.cpp
|
||||
layout/qgslayoutitemlegend.cpp
|
||||
layout/qgslayoutitemmap.cpp
|
||||
layout/qgslayoutitemmapgrid.cpp
|
||||
layout/qgslayoutitemmapitem.cpp
|
||||
@ -730,6 +731,7 @@ SET(QGIS_CORE_MOC_HDRS
|
||||
layout/qgslayoutitemgroup.h
|
||||
layout/qgslayoutitemgroupundocommand.h
|
||||
layout/qgslayoutitemlabel.h
|
||||
layout/qgslayoutitemlegend.h
|
||||
layout/qgslayoutitemmap.h
|
||||
layout/qgslayoutitemmapgrid.h
|
||||
layout/qgslayoutitemmapitem.h
|
||||
|
||||
@ -32,6 +32,7 @@
|
||||
#include <QDomDocument>
|
||||
#include <QDomElement>
|
||||
#include <QPainter>
|
||||
#include "qgslayoutitemlegend.h"
|
||||
|
||||
QgsComposerLegend::QgsComposerLegend( QgsComposition *composition )
|
||||
: QgsComposerItem( composition )
|
||||
@ -45,6 +46,11 @@ QgsComposerLegend::QgsComposerLegend( QgsComposition *composition )
|
||||
connect( mComposition->project()->layerTreeRoot(), &QgsLayerTreeNode::customPropertyChanged, this, &QgsComposerLegend::nodeCustomPropertyChanged );
|
||||
}
|
||||
|
||||
QgsComposerLegend::~QgsComposerLegend()
|
||||
{
|
||||
delete mLegendModel;
|
||||
}
|
||||
|
||||
QgsComposerLegend::QgsComposerLegend()
|
||||
: QgsComposerItem( nullptr )
|
||||
{
|
||||
@ -91,7 +97,7 @@ void QgsComposerLegend::paint( QPainter *painter, const QStyleOptionGraphicsItem
|
||||
}
|
||||
mInitialMapScaleCalculated = true;
|
||||
|
||||
QgsLegendRenderer legendRenderer( mLegendModel.get(), mSettings );
|
||||
QgsLegendRenderer legendRenderer( mLegendModel, mSettings );
|
||||
legendRenderer.setLegendSize( mForceResize && mSizeToContents ? QSize() : rect().size() );
|
||||
|
||||
//adjust box if width or height is too small
|
||||
@ -152,7 +158,7 @@ QSizeF QgsComposerLegend::paintAndDetermineSize( QPainter *painter )
|
||||
doUpdateFilterByMap();
|
||||
}
|
||||
|
||||
QgsLegendRenderer legendRenderer( mLegendModel.get(), mSettings );
|
||||
QgsLegendRenderer legendRenderer( mLegendModel, mSettings );
|
||||
QSizeF size = legendRenderer.minimumSize();
|
||||
if ( painter )
|
||||
legendRenderer.drawLegend( painter );
|
||||
@ -174,7 +180,7 @@ void QgsComposerLegend::adjustBoxSize()
|
||||
return;
|
||||
}
|
||||
|
||||
QgsLegendRenderer legendRenderer( mLegendModel.get(), mSettings );
|
||||
QgsLegendRenderer legendRenderer( mLegendModel, mSettings );
|
||||
QSizeF size = legendRenderer.minimumSize();
|
||||
QgsDebugMsg( QString( "width = %1 height = %2" ).arg( size.width() ).arg( size.height() ) );
|
||||
if ( size.isValid() )
|
||||
@ -195,6 +201,11 @@ bool QgsComposerLegend::resizeToContents() const
|
||||
return mSizeToContents;
|
||||
}
|
||||
|
||||
QgsLegendModel *QgsComposerLegend::model()
|
||||
{
|
||||
return mLegendModel;
|
||||
}
|
||||
|
||||
void QgsComposerLegend::setCustomLayerTree( QgsLayerTree *rootGroup )
|
||||
{
|
||||
mLegendModel->setRootGroup( rootGroup ? rootGroup : ( mComposition ? mComposition->project()->layerTreeRoot() : nullptr ) );
|
||||
@ -717,45 +728,3 @@ void QgsComposerLegend::onAtlasEnded()
|
||||
mInAtlas = false;
|
||||
updateFilterByMap();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
#include "qgslayertreemodellegendnode.h"
|
||||
#include "qgsvectorlayer.h"
|
||||
|
||||
QgsLegendModel::QgsLegendModel( QgsLayerTree *rootNode, QObject *parent )
|
||||
: QgsLayerTreeModel( rootNode, parent )
|
||||
{
|
||||
setFlag( QgsLayerTreeModel::AllowLegendChangeState, false );
|
||||
setFlag( QgsLayerTreeModel::AllowNodeReorder, true );
|
||||
}
|
||||
|
||||
QVariant QgsLegendModel::data( const QModelIndex &index, int role ) const
|
||||
{
|
||||
// handle custom layer node labels
|
||||
if ( QgsLayerTreeNode *node = index2node( index ) )
|
||||
{
|
||||
if ( QgsLayerTree::isLayer( node ) && ( role == Qt::DisplayRole || role == Qt::EditRole ) && !node->customProperty( QStringLiteral( "legend/title-label" ) ).isNull() )
|
||||
{
|
||||
QgsLayerTreeLayer *nodeLayer = QgsLayerTree::toLayer( node );
|
||||
QString name = node->customProperty( QStringLiteral( "legend/title-label" ) ).toString();
|
||||
if ( nodeLayer->customProperty( QStringLiteral( "showFeatureCount" ), 0 ).toInt() && role == Qt::DisplayRole )
|
||||
{
|
||||
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( nodeLayer->layer() );
|
||||
if ( vlayer && vlayer->featureCount() >= 0 )
|
||||
name += QStringLiteral( " [%1]" ).arg( vlayer->featureCount() );
|
||||
}
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
return QgsLayerTreeModel::data( index, role );
|
||||
}
|
||||
|
||||
Qt::ItemFlags QgsLegendModel::flags( const QModelIndex &index ) const
|
||||
{
|
||||
// make the legend nodes selectable even if they are not by default
|
||||
if ( index2legendNode( index ) )
|
||||
return QgsLayerTreeModel::flags( index ) | Qt::ItemIsSelectable;
|
||||
|
||||
return QgsLayerTreeModel::flags( index );
|
||||
}
|
||||
|
||||
@ -25,31 +25,12 @@
|
||||
#include "qgslegendsettings.h"
|
||||
#include "qgslayertreegroup.h"
|
||||
|
||||
|
||||
class QgsLayerTreeModel;
|
||||
class QgsSymbol;
|
||||
class QgsComposerMap;
|
||||
class QgsLegendRenderer;
|
||||
|
||||
|
||||
/**
|
||||
* \ingroup core
|
||||
* Item model implementation based on layer tree model for composer legend.
|
||||
* Overrides some functionality of QgsLayerTreeModel to better fit the needs of composer legend.
|
||||
*
|
||||
* \since QGIS 2.6
|
||||
*/
|
||||
class CORE_EXPORT QgsLegendModel : public QgsLayerTreeModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
//! Construct the model based on the given layer tree
|
||||
QgsLegendModel( QgsLayerTree *rootNode, QObject *parent SIP_TRANSFERTHIS = 0 );
|
||||
|
||||
QVariant data( const QModelIndex &index, int role ) const override;
|
||||
|
||||
Qt::ItemFlags flags( const QModelIndex &index ) const override;
|
||||
};
|
||||
class QgsLegendModel;
|
||||
|
||||
|
||||
/**
|
||||
@ -62,6 +43,7 @@ class CORE_EXPORT QgsComposerLegend : public QgsComposerItem
|
||||
|
||||
public:
|
||||
QgsComposerLegend( QgsComposition *composition SIP_TRANSFERTHIS );
|
||||
~QgsComposerLegend();
|
||||
|
||||
//! Return correct graphics item type.
|
||||
virtual int type() const override { return ComposerLegend; }
|
||||
@ -95,7 +77,7 @@ class CORE_EXPORT QgsComposerLegend : public QgsComposerItem
|
||||
/**
|
||||
* Returns the legend model
|
||||
*/
|
||||
QgsLegendModel *model() { return mLegendModel.get(); }
|
||||
QgsLegendModel *model();
|
||||
|
||||
//! \since QGIS 2.6
|
||||
void setAutoUpdateModel( bool autoUpdate );
|
||||
@ -336,7 +318,7 @@ class CORE_EXPORT QgsComposerLegend : public QgsComposerItem
|
||||
//! use new custom layer tree and update model. if new root is null pointer, will use project's tree
|
||||
void setCustomLayerTree( QgsLayerTree *rootGroup );
|
||||
|
||||
std::unique_ptr< QgsLegendModel > mLegendModel;
|
||||
QgsLegendModel *mLegendModel = nullptr;
|
||||
std::unique_ptr< QgsLayerTreeGroup > mCustomLayerTree;
|
||||
|
||||
QgsLegendSettings mSettings;
|
||||
|
||||
@ -117,6 +117,23 @@ class CORE_EXPORT QgsLayoutItem : public QgsLayoutObject, public QGraphicsRectIt
|
||||
UndoLabelFont, //!< Label font
|
||||
UndoLabelMargin, //!< Label margin
|
||||
UndoLabelFontColor, //!< Label color
|
||||
UndoLegendText, //!< Legend text
|
||||
UndoLegendColumnCount, //!< Legend column count
|
||||
UndoLegendSymbolWidth, //!< Legend symbol width
|
||||
UndoLegendSymbolHeight, //!< Legend symbol height
|
||||
UndoLegendWmsLegendWidth, //!< Legend WMS width
|
||||
UndoLegendWmsLegendHeight, //!< Legend WMS height
|
||||
UndoLegendTitleSpaceBottom, //!< Legend title space
|
||||
UndoLegendGroupSpace, //!< Legend group spacing
|
||||
UndoLegendLayerSpace, //!< Legend layer spacing
|
||||
UndoLegendSymbolSpace, //!< Legend symbol spacing
|
||||
UndoLegendIconSymbolSpace, //!< Legend icon symbol space
|
||||
UndoLegendFontColor, //!< Legend font color
|
||||
UndoLegendBoxSpace, //!< Legend box space
|
||||
UndoLegendColumnSpace, //!< Legend column space
|
||||
UndoLegendLineSpacing, //!< Legend line spacing
|
||||
UndoLegendRasterStrokeWidth, //!< Legend raster stroke width
|
||||
UndoLegendRasterStrokeColor, //!< Legend raster stroke color
|
||||
UndoCustomCommand, //!< Base id for plugin based item undo commands
|
||||
};
|
||||
|
||||
|
||||
884
src/core/layout/qgslayoutitemlegend.cpp
Normal file
884
src/core/layout/qgslayoutitemlegend.cpp
Normal file
@ -0,0 +1,884 @@
|
||||
/***************************************************************************
|
||||
qgslayoutitemlegend.cpp
|
||||
-----------------------
|
||||
begin : October 2017
|
||||
copyright : (C) 2017 by Nyall Dawson
|
||||
email : nyall dot dawson at gmail dot com
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
#include <limits>
|
||||
|
||||
#include "qgslayoutitemlegend.h"
|
||||
#include "qgslayoutitemregistry.h"
|
||||
#include "qgslayoutitemmap.h"
|
||||
#include "qgslayout.h"
|
||||
#include "qgslayoutmodel.h"
|
||||
#include "qgslayertree.h"
|
||||
#include "qgslayertreemodel.h"
|
||||
#include "qgslegendrenderer.h"
|
||||
#include "qgslegendstyle.h"
|
||||
#include "qgslogger.h"
|
||||
#include "qgsmapsettings.h"
|
||||
#include "qgsproject.h"
|
||||
#include "qgssymbollayerutils.h"
|
||||
#include "qgslayertreeutils.h"
|
||||
#include <QDomDocument>
|
||||
#include <QDomElement>
|
||||
#include <QPainter>
|
||||
|
||||
QgsLayoutItemLegend::QgsLayoutItemLegend( QgsLayout *layout )
|
||||
: QgsLayoutItem( layout )
|
||||
, mLegendModel( new QgsLegendModel( layout->project()->layerTreeRoot() ) )
|
||||
{
|
||||
#if 0 //TODO
|
||||
connect( &layout->atlasComposition(), &QgsAtlasComposition::renderEnded, this, &QgsLayoutItemLegend::onAtlasEnded );
|
||||
connect( &layout->atlasComposition(), &QgsAtlasComposition::featureChanged, this, &QgsLayoutItemLegend::onAtlasFeature );
|
||||
#endif
|
||||
|
||||
// Connect to the main layertreeroot.
|
||||
// It serves in "auto update mode" as a medium between the main app legend and this one
|
||||
connect( mLayout->project()->layerTreeRoot(), &QgsLayerTreeNode::customPropertyChanged, this, &QgsLayoutItemLegend::nodeCustomPropertyChanged );
|
||||
}
|
||||
|
||||
QgsLayoutItemLegend *QgsLayoutItemLegend::create( QgsLayout *layout )
|
||||
{
|
||||
return new QgsLayoutItemLegend( layout );
|
||||
}
|
||||
|
||||
int QgsLayoutItemLegend::type() const
|
||||
{
|
||||
return QgsLayoutItemRegistry::LayoutLegend;
|
||||
}
|
||||
|
||||
QString QgsLayoutItemLegend::stringType() const
|
||||
{
|
||||
return QStringLiteral( "ItemLegend" );
|
||||
}
|
||||
|
||||
|
||||
void QgsLayoutItemLegend::paint( QPainter *painter, const QStyleOptionGraphicsItem *itemStyle, QWidget *pWidget )
|
||||
{
|
||||
if ( !painter )
|
||||
return;
|
||||
|
||||
if ( mFilterAskedForUpdate )
|
||||
{
|
||||
mFilterAskedForUpdate = false;
|
||||
doUpdateFilterByMap();
|
||||
}
|
||||
|
||||
int dpi = painter->device()->logicalDpiX();
|
||||
double dotsPerMM = dpi / 25.4;
|
||||
|
||||
if ( mLayout )
|
||||
{
|
||||
mSettings.setUseAdvancedEffects( mLayout->context().flags() & QgsLayoutContext::FlagUseAdvancedEffects );
|
||||
mSettings.setDpi( dpi );
|
||||
}
|
||||
if ( mMap && mLayout )
|
||||
{
|
||||
mSettings.setMmPerMapUnit( mLayout->convertFromLayoutUnits( mMap->mapUnitsToLayoutUnits(), QgsUnitTypes::LayoutMillimeters ).length() );
|
||||
|
||||
// use a temporary QgsMapSettings to find out real map scale
|
||||
QSizeF mapSizePixels = QSizeF( mMap->rect().width() * dotsPerMM, mMap->rect().height() * dotsPerMM );
|
||||
QgsRectangle mapExtent = mMap->extent();
|
||||
|
||||
QgsMapSettings ms = mMap->mapSettings( mapExtent, mapSizePixels, dpi );
|
||||
mSettings.setMapScale( ms.scale() );
|
||||
}
|
||||
mInitialMapScaleCalculated = true;
|
||||
|
||||
QgsLegendRenderer legendRenderer( mLegendModel.get(), mSettings );
|
||||
legendRenderer.setLegendSize( mForceResize && mSizeToContents ? QSize() : rect().size() );
|
||||
|
||||
//adjust box if width or height is too small
|
||||
if ( mSizeToContents )
|
||||
{
|
||||
QSizeF size = legendRenderer.minimumSize();
|
||||
if ( mForceResize )
|
||||
{
|
||||
mForceResize = false;
|
||||
//set new rect, respecting position mode and data defined size/position
|
||||
QRectF targetRect = QRectF( pos().x(), pos().y(), size.width(), size.height() );
|
||||
attemptSetSceneRect( targetRect );
|
||||
}
|
||||
else if ( size.height() > rect().height() || size.width() > rect().width() )
|
||||
{
|
||||
//need to resize box
|
||||
QRectF targetRect = QRectF( pos().x(), pos().y(), rect().width(), rect().height() );
|
||||
if ( size.height() > targetRect.height() )
|
||||
targetRect.setHeight( size.height() );
|
||||
if ( size.width() > rect().width() )
|
||||
targetRect.setWidth( size.width() );
|
||||
|
||||
//set new rect, respecting position mode and data defined size/position
|
||||
attemptSetSceneRect( targetRect );
|
||||
}
|
||||
}
|
||||
QgsLayoutItem::paint( painter, itemStyle, pWidget );
|
||||
}
|
||||
|
||||
void QgsLayoutItemLegend::draw( QgsRenderContext &context, const QStyleOptionGraphicsItem * )
|
||||
{
|
||||
QPainter *painter = context.painter();
|
||||
painter->save();
|
||||
|
||||
// painter is scaled to dots, so scale back to layout units
|
||||
painter->scale( context.scaleFactor(), context.scaleFactor() );
|
||||
|
||||
painter->setPen( QPen( QColor( 0, 0, 0 ) ) );
|
||||
|
||||
if ( !mSizeToContents )
|
||||
{
|
||||
// set a clip region to crop out parts of legend which don't fit
|
||||
QRectF thisPaintRect = QRectF( 0, 0, rect().width(), rect().height() );
|
||||
painter->setClipRect( thisPaintRect );
|
||||
}
|
||||
|
||||
QgsLegendRenderer legendRenderer( mLegendModel.get(), mSettings );
|
||||
legendRenderer.setLegendSize( mForceResize && mSizeToContents ? QSize() : rect().size() );
|
||||
|
||||
legendRenderer.drawLegend( painter );
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
void QgsLayoutItemLegend::adjustBoxSize()
|
||||
{
|
||||
if ( !mSizeToContents )
|
||||
return;
|
||||
|
||||
if ( !mInitialMapScaleCalculated )
|
||||
{
|
||||
// this is messy - but until we have painted the item we have no knowledge of the current DPI
|
||||
// and so cannot correctly calculate the map scale. This results in incorrect size calculations
|
||||
// for marker symbols with size in map units, causing the legends to initially expand to huge
|
||||
// sizes if we attempt to calculate the box size first.
|
||||
return;
|
||||
}
|
||||
|
||||
QgsLegendRenderer legendRenderer( mLegendModel.get(), mSettings );
|
||||
QSizeF size = legendRenderer.minimumSize();
|
||||
QgsDebugMsg( QString( "width = %1 height = %2" ).arg( size.width() ).arg( size.height() ) );
|
||||
if ( size.isValid() )
|
||||
{
|
||||
QRectF targetRect = QRectF( pos().x(), pos().y(), size.width(), size.height() );
|
||||
//set new rect, respecting position mode and data defined size/position
|
||||
attemptSetSceneRect( targetRect );
|
||||
}
|
||||
}
|
||||
|
||||
void QgsLayoutItemLegend::setResizeToContents( bool enabled )
|
||||
{
|
||||
mSizeToContents = enabled;
|
||||
}
|
||||
|
||||
bool QgsLayoutItemLegend::resizeToContents() const
|
||||
{
|
||||
return mSizeToContents;
|
||||
}
|
||||
|
||||
void QgsLayoutItemLegend::setCustomLayerTree( QgsLayerTree *rootGroup )
|
||||
{
|
||||
mLegendModel->setRootGroup( rootGroup ? rootGroup : ( mLayout ? mLayout->project()->layerTreeRoot() : nullptr ) );
|
||||
|
||||
mCustomLayerTree.reset( rootGroup );
|
||||
}
|
||||
|
||||
|
||||
void QgsLayoutItemLegend::setAutoUpdateModel( bool autoUpdate )
|
||||
{
|
||||
if ( autoUpdate == autoUpdateModel() )
|
||||
return;
|
||||
|
||||
setCustomLayerTree( autoUpdate ? nullptr : mLayout->project()->layerTreeRoot()->clone() );
|
||||
adjustBoxSize();
|
||||
updateFilterByMap( false );
|
||||
}
|
||||
|
||||
void QgsLayoutItemLegend::nodeCustomPropertyChanged( QgsLayerTreeNode *, const QString & )
|
||||
{
|
||||
if ( autoUpdateModel() )
|
||||
{
|
||||
// in "auto update" mode, some parameters on the main app legend may have been changed (expression filtering)
|
||||
// we must then call updateItem to reflect the changes
|
||||
updateFilterByMap( false );
|
||||
}
|
||||
}
|
||||
|
||||
bool QgsLayoutItemLegend::autoUpdateModel() const
|
||||
{
|
||||
return !mCustomLayerTree;
|
||||
}
|
||||
|
||||
void QgsLayoutItemLegend::setLegendFilterByMapEnabled( bool enabled )
|
||||
{
|
||||
mLegendFilterByMap = enabled;
|
||||
updateFilterByMap( false );
|
||||
}
|
||||
|
||||
void QgsLayoutItemLegend::setTitle( const QString &t )
|
||||
{
|
||||
mTitle = t;
|
||||
mSettings.setTitle( t );
|
||||
|
||||
if ( mLayout && id().isEmpty() )
|
||||
{
|
||||
//notify the model that the display name has changed
|
||||
mLayout->itemsModel()->updateItemDisplayName( this );
|
||||
}
|
||||
}
|
||||
QString QgsLayoutItemLegend::title() const
|
||||
{
|
||||
return mTitle;
|
||||
}
|
||||
|
||||
Qt::AlignmentFlag QgsLayoutItemLegend::titleAlignment() const
|
||||
{
|
||||
return mSettings.titleAlignment();
|
||||
}
|
||||
|
||||
void QgsLayoutItemLegend::setTitleAlignment( Qt::AlignmentFlag alignment )
|
||||
{
|
||||
mSettings.setTitleAlignment( alignment );
|
||||
}
|
||||
|
||||
QgsLegendStyle &QgsLayoutItemLegend::rstyle( QgsLegendStyle::Style s )
|
||||
{
|
||||
return mSettings.rstyle( s );
|
||||
}
|
||||
|
||||
QgsLegendStyle QgsLayoutItemLegend::style( QgsLegendStyle::Style s ) const
|
||||
{
|
||||
return mSettings.style( s );
|
||||
}
|
||||
|
||||
void QgsLayoutItemLegend::setStyle( QgsLegendStyle::Style s, const QgsLegendStyle &style )
|
||||
{
|
||||
mSettings.setStyle( s, style );
|
||||
}
|
||||
|
||||
QFont QgsLayoutItemLegend::styleFont( QgsLegendStyle::Style s ) const
|
||||
{
|
||||
return mSettings.style( s ).font();
|
||||
}
|
||||
|
||||
void QgsLayoutItemLegend::setStyleFont( QgsLegendStyle::Style s, const QFont &f )
|
||||
{
|
||||
rstyle( s ).setFont( f );
|
||||
}
|
||||
|
||||
void QgsLayoutItemLegend::setStyleMargin( QgsLegendStyle::Style s, double margin )
|
||||
{
|
||||
rstyle( s ).setMargin( margin );
|
||||
}
|
||||
|
||||
void QgsLayoutItemLegend::setStyleMargin( QgsLegendStyle::Style s, QgsLegendStyle::Side side, double margin )
|
||||
{
|
||||
rstyle( s ).setMargin( side, margin );
|
||||
}
|
||||
|
||||
double QgsLayoutItemLegend::lineSpacing() const
|
||||
{
|
||||
return mSettings.lineSpacing();
|
||||
}
|
||||
|
||||
void QgsLayoutItemLegend::setLineSpacing( double spacing )
|
||||
{
|
||||
mSettings.setLineSpacing( spacing );
|
||||
}
|
||||
|
||||
double QgsLayoutItemLegend::boxSpace() const
|
||||
{
|
||||
return mSettings.boxSpace();
|
||||
}
|
||||
|
||||
void QgsLayoutItemLegend::setBoxSpace( double s )
|
||||
{
|
||||
mSettings.setBoxSpace( s );
|
||||
}
|
||||
|
||||
double QgsLayoutItemLegend::columnSpace() const
|
||||
{
|
||||
return mSettings.columnSpace();
|
||||
}
|
||||
|
||||
void QgsLayoutItemLegend::setColumnSpace( double s )
|
||||
{
|
||||
mSettings.setColumnSpace( s );
|
||||
}
|
||||
|
||||
QColor QgsLayoutItemLegend::fontColor() const
|
||||
{
|
||||
return mSettings.fontColor();
|
||||
}
|
||||
|
||||
void QgsLayoutItemLegend::setFontColor( const QColor &c )
|
||||
{
|
||||
mSettings.setFontColor( c );
|
||||
}
|
||||
|
||||
double QgsLayoutItemLegend::symbolWidth() const
|
||||
{
|
||||
return mSettings.symbolSize().width();
|
||||
}
|
||||
|
||||
void QgsLayoutItemLegend::setSymbolWidth( double w )
|
||||
{
|
||||
mSettings.setSymbolSize( QSizeF( w, mSettings.symbolSize().height() ) );
|
||||
}
|
||||
|
||||
double QgsLayoutItemLegend::symbolHeight() const
|
||||
{
|
||||
return mSettings.symbolSize().height();
|
||||
}
|
||||
|
||||
void QgsLayoutItemLegend::setSymbolHeight( double h )
|
||||
{
|
||||
mSettings.setSymbolSize( QSizeF( mSettings.symbolSize().width(), h ) );
|
||||
}
|
||||
|
||||
double QgsLayoutItemLegend::wmsLegendWidth() const
|
||||
{
|
||||
return mSettings.wmsLegendSize().width();
|
||||
}
|
||||
|
||||
void QgsLayoutItemLegend::setWmsLegendWidth( double w )
|
||||
{
|
||||
mSettings.setWmsLegendSize( QSizeF( w, mSettings.wmsLegendSize().height() ) );
|
||||
}
|
||||
|
||||
double QgsLayoutItemLegend::wmsLegendHeight() const
|
||||
{
|
||||
return mSettings.wmsLegendSize().height();
|
||||
}
|
||||
void QgsLayoutItemLegend::setWmsLegendHeight( double h )
|
||||
{
|
||||
mSettings.setWmsLegendSize( QSizeF( mSettings.wmsLegendSize().width(), h ) );
|
||||
}
|
||||
|
||||
void QgsLayoutItemLegend::setWrapString( const QString &t )
|
||||
{
|
||||
mSettings.setWrapChar( t );
|
||||
}
|
||||
|
||||
QString QgsLayoutItemLegend::wrapString() const
|
||||
{
|
||||
return mSettings.wrapChar();
|
||||
}
|
||||
|
||||
int QgsLayoutItemLegend::columnCount() const
|
||||
{
|
||||
return mColumnCount;
|
||||
}
|
||||
|
||||
void QgsLayoutItemLegend::setColumnCount( int c )
|
||||
{
|
||||
mColumnCount = c;
|
||||
mSettings.setColumnCount( c );
|
||||
}
|
||||
|
||||
bool QgsLayoutItemLegend::splitLayer() const
|
||||
{
|
||||
return mSettings.splitLayer();
|
||||
}
|
||||
|
||||
void QgsLayoutItemLegend::setSplitLayer( bool s )
|
||||
{
|
||||
mSettings.setSplitLayer( s );
|
||||
}
|
||||
|
||||
bool QgsLayoutItemLegend::equalColumnWidth() const
|
||||
{
|
||||
return mSettings.equalColumnWidth();
|
||||
}
|
||||
|
||||
void QgsLayoutItemLegend::setEqualColumnWidth( bool s )
|
||||
{
|
||||
mSettings.setEqualColumnWidth( s );
|
||||
}
|
||||
|
||||
bool QgsLayoutItemLegend::drawRasterStroke() const
|
||||
{
|
||||
return mSettings.drawRasterStroke();
|
||||
}
|
||||
|
||||
void QgsLayoutItemLegend::setDrawRasterStroke( bool enabled )
|
||||
{
|
||||
mSettings.setDrawRasterStroke( enabled );
|
||||
}
|
||||
|
||||
QColor QgsLayoutItemLegend::rasterStrokeColor() const
|
||||
{
|
||||
return mSettings.rasterStrokeColor();
|
||||
}
|
||||
|
||||
void QgsLayoutItemLegend::setRasterStrokeColor( const QColor &color )
|
||||
{
|
||||
mSettings.setRasterStrokeColor( color );
|
||||
}
|
||||
|
||||
double QgsLayoutItemLegend::rasterStrokeWidth() const
|
||||
{
|
||||
return mSettings.rasterStrokeWidth();
|
||||
}
|
||||
|
||||
void QgsLayoutItemLegend::setRasterStrokeWidth( double width )
|
||||
{
|
||||
mSettings.setRasterStrokeWidth( width );
|
||||
}
|
||||
|
||||
void QgsLayoutItemLegend::synchronizeWithModel()
|
||||
{
|
||||
adjustBoxSize();
|
||||
updateFilterByMap( false );
|
||||
}
|
||||
|
||||
void QgsLayoutItemLegend::updateLegend()
|
||||
{
|
||||
adjustBoxSize();
|
||||
updateFilterByMap( false );
|
||||
}
|
||||
|
||||
#if 0//TODO
|
||||
bool QgsLayoutItemLegend::writeXml( QDomElement &elem, QDomDocument &doc ) const
|
||||
{
|
||||
if ( elem.isNull() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
QDomElement composerLegendElem = doc.createElement( QStringLiteral( "ComposerLegend" ) );
|
||||
elem.appendChild( composerLegendElem );
|
||||
|
||||
//write general properties
|
||||
composerLegendElem.setAttribute( QStringLiteral( "title" ), mTitle );
|
||||
composerLegendElem.setAttribute( QStringLiteral( "titleAlignment" ), QString::number( static_cast< int >( mSettings.titleAlignment() ) ) );
|
||||
composerLegendElem.setAttribute( QStringLiteral( "columnCount" ), QString::number( mColumnCount ) );
|
||||
composerLegendElem.setAttribute( QStringLiteral( "splitLayer" ), QString::number( mSettings.splitLayer() ) );
|
||||
composerLegendElem.setAttribute( QStringLiteral( "equalColumnWidth" ), QString::number( mSettings.equalColumnWidth() ) );
|
||||
|
||||
composerLegendElem.setAttribute( QStringLiteral( "boxSpace" ), QString::number( mSettings.boxSpace() ) );
|
||||
composerLegendElem.setAttribute( QStringLiteral( "columnSpace" ), QString::number( mSettings.columnSpace() ) );
|
||||
|
||||
composerLegendElem.setAttribute( QStringLiteral( "symbolWidth" ), QString::number( mSettings.symbolSize().width() ) );
|
||||
composerLegendElem.setAttribute( QStringLiteral( "symbolHeight" ), QString::number( mSettings.symbolSize().height() ) );
|
||||
composerLegendElem.setAttribute( QStringLiteral( "lineSpacing" ), QString::number( mSettings.lineSpacing() ) );
|
||||
|
||||
composerLegendElem.setAttribute( QStringLiteral( "rasterBorder" ), mSettings.drawRasterStroke() );
|
||||
composerLegendElem.setAttribute( QStringLiteral( "rasterBorderColor" ), QgsSymbolLayerUtils::encodeColor( mSettings.rasterStrokeColor() ) );
|
||||
composerLegendElem.setAttribute( QStringLiteral( "rasterBorderWidth" ), QString::number( mSettings.rasterStrokeWidth() ) );
|
||||
|
||||
composerLegendElem.setAttribute( QStringLiteral( "wmsLegendWidth" ), QString::number( mSettings.wmsLegendSize().width() ) );
|
||||
composerLegendElem.setAttribute( QStringLiteral( "wmsLegendHeight" ), QString::number( mSettings.wmsLegendSize().height() ) );
|
||||
composerLegendElem.setAttribute( QStringLiteral( "wrapChar" ), mSettings.wrapChar() );
|
||||
composerLegendElem.setAttribute( QStringLiteral( "fontColor" ), mSettings.fontColor().name() );
|
||||
|
||||
composerLegendElem.setAttribute( QStringLiteral( "resizeToContents" ), mSizeToContents );
|
||||
|
||||
if ( mMap )
|
||||
{
|
||||
composerLegendElem.setAttribute( QStringLiteral( "map" ), mMap->id() );
|
||||
}
|
||||
|
||||
QDomElement composerLegendStyles = doc.createElement( QStringLiteral( "styles" ) );
|
||||
composerLegendElem.appendChild( composerLegendStyles );
|
||||
|
||||
style( QgsLegendStyle::Title ).writeXml( QStringLiteral( "title" ), composerLegendStyles, doc );
|
||||
style( QgsLegendStyle::Group ).writeXml( QStringLiteral( "group" ), composerLegendStyles, doc );
|
||||
style( QgsLegendStyle::Subgroup ).writeXml( QStringLiteral( "subgroup" ), composerLegendStyles, doc );
|
||||
style( QgsLegendStyle::Symbol ).writeXml( QStringLiteral( "symbol" ), composerLegendStyles, doc );
|
||||
style( QgsLegendStyle::SymbolLabel ).writeXml( QStringLiteral( "symbolLabel" ), composerLegendStyles, doc );
|
||||
|
||||
if ( mCustomLayerTree )
|
||||
{
|
||||
// if not using auto-update - store the custom layer tree
|
||||
mCustomLayerTree->writeXml( composerLegendElem );
|
||||
}
|
||||
|
||||
if ( mLegendFilterByMap )
|
||||
{
|
||||
composerLegendElem.setAttribute( QStringLiteral( "legendFilterByMap" ), QStringLiteral( "1" ) );
|
||||
}
|
||||
composerLegendElem.setAttribute( QStringLiteral( "legendFilterByAtlas" ), mFilterOutAtlas ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
|
||||
|
||||
return _writeXml( composerLegendElem, doc );
|
||||
}
|
||||
|
||||
bool QgsLayoutItemLegend::readXml( const QDomElement &itemElem, const QDomDocument &doc )
|
||||
{
|
||||
if ( itemElem.isNull() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//read general properties
|
||||
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;
|
||||
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 );
|
||||
|
||||
QDomNodeList stylesNodeList = itemElem.elementsByTagName( QStringLiteral( "styles" ) );
|
||||
if ( !stylesNodeList.isEmpty() )
|
||||
{
|
||||
QDomNode stylesNode = stylesNodeList.at( 0 );
|
||||
for ( int i = 0; i < stylesNode.childNodes().size(); i++ )
|
||||
{
|
||||
QDomElement styleElem = stylesNode.childNodes().at( i ).toElement();
|
||||
QgsLegendStyle style;
|
||||
style.readXml( styleElem, doc );
|
||||
QString name = styleElem.attribute( QStringLiteral( "name" ) );
|
||||
QgsLegendStyle::Style s;
|
||||
if ( name == QLatin1String( "title" ) ) s = QgsLegendStyle::Title;
|
||||
else if ( name == QLatin1String( "group" ) ) s = QgsLegendStyle::Group;
|
||||
else if ( name == QLatin1String( "subgroup" ) ) s = QgsLegendStyle::Subgroup;
|
||||
else if ( name == QLatin1String( "symbol" ) ) s = QgsLegendStyle::Symbol;
|
||||
else if ( name == QLatin1String( "symbolLabel" ) ) s = QgsLegendStyle::SymbolLabel;
|
||||
else continue;
|
||||
setStyle( s, style );
|
||||
}
|
||||
}
|
||||
|
||||
//font color
|
||||
QColor fontClr;
|
||||
fontClr.setNamedColor( itemElem.attribute( QStringLiteral( "fontColor" ), QStringLiteral( "#000000" ) ) );
|
||||
mSettings.setFontColor( fontClr );
|
||||
|
||||
//spaces
|
||||
mSettings.setBoxSpace( itemElem.attribute( QStringLiteral( "boxSpace" ), 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.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.setDrawRasterStroke( itemElem.attribute( QStringLiteral( "rasterBorder" ), QStringLiteral( "1" ) ) != QLatin1String( "0" ) );
|
||||
mSettings.setRasterStrokeColor( QgsSymbolLayerUtils::decodeColor( itemElem.attribute( QStringLiteral( "rasterBorderColor" ), QStringLiteral( "0,0,0" ) ) ) );
|
||||
mSettings.setRasterStrokeWidth( itemElem.attribute( QStringLiteral( "rasterBorderWidth" ), QStringLiteral( "0" ) ).toDouble() );
|
||||
|
||||
mSettings.setWrapChar( itemElem.attribute( QStringLiteral( "wrapChar" ) ) );
|
||||
|
||||
mSizeToContents = itemElem.attribute( QStringLiteral( "resizeToContents" ), QStringLiteral( "1" ) ) != QLatin1String( "0" );
|
||||
|
||||
//composer map
|
||||
mLegendFilterByMap = itemElem.attribute( QStringLiteral( "legendFilterByMap" ), QStringLiteral( "0" ) ).toInt();
|
||||
if ( !itemElem.attribute( QStringLiteral( "map" ) ).isEmpty() )
|
||||
{
|
||||
setMap( mComposition->getComposerMapById( itemElem.attribute( QStringLiteral( "map" ) ).toInt() ) );
|
||||
}
|
||||
mFilterOutAtlas = itemElem.attribute( QStringLiteral( "legendFilterByAtlas" ), QStringLiteral( "0" ) ).toInt();
|
||||
|
||||
// QGIS >= 2.6
|
||||
QDomElement layerTreeElem = itemElem.firstChildElement( QStringLiteral( "layer-tree" ) );
|
||||
if ( layerTreeElem.isNull() )
|
||||
layerTreeElem = itemElem.firstChildElement( QStringLiteral( "layer-tree-group" ) );
|
||||
|
||||
if ( !layerTreeElem.isNull() )
|
||||
{
|
||||
std::unique_ptr< QgsLayerTree > tree( QgsLayerTree::readXml( layerTreeElem ) );
|
||||
if ( mComposition )
|
||||
tree->resolveReferences( mComposition->project(), true );
|
||||
setCustomLayerTree( tree.release() );
|
||||
}
|
||||
else
|
||||
setCustomLayerTree( nullptr );
|
||||
|
||||
//restore general composer item properties
|
||||
QDomNodeList composerItemList = itemElem.elementsByTagName( QStringLiteral( "ComposerItem" ) );
|
||||
if ( !composerItemList.isEmpty() )
|
||||
{
|
||||
QDomElement composerItemElem = composerItemList.at( 0 ).toElement();
|
||||
_readXml( composerItemElem, doc );
|
||||
}
|
||||
|
||||
// < 2.0 projects backward compatibility >>>>>
|
||||
//title font
|
||||
QString titleFontString = itemElem.attribute( QStringLiteral( "titleFont" ) );
|
||||
if ( !titleFontString.isEmpty() )
|
||||
{
|
||||
rstyle( QgsLegendStyle::Title ).rfont().fromString( titleFontString );
|
||||
}
|
||||
//group font
|
||||
QString groupFontString = itemElem.attribute( QStringLiteral( "groupFont" ) );
|
||||
if ( !groupFontString.isEmpty() )
|
||||
{
|
||||
rstyle( QgsLegendStyle::Group ).rfont().fromString( groupFontString );
|
||||
}
|
||||
|
||||
//layer font
|
||||
QString layerFontString = itemElem.attribute( QStringLiteral( "layerFont" ) );
|
||||
if ( !layerFontString.isEmpty() )
|
||||
{
|
||||
rstyle( QgsLegendStyle::Subgroup ).rfont().fromString( layerFontString );
|
||||
}
|
||||
//item font
|
||||
QString itemFontString = itemElem.attribute( QStringLiteral( "itemFont" ) );
|
||||
if ( !itemFontString.isEmpty() )
|
||||
{
|
||||
rstyle( QgsLegendStyle::SymbolLabel ).rfont().fromString( itemFontString );
|
||||
}
|
||||
|
||||
if ( !itemElem.attribute( QStringLiteral( "groupSpace" ) ).isEmpty() )
|
||||
{
|
||||
rstyle( QgsLegendStyle::Group ).setMargin( QgsLegendStyle::Top, itemElem.attribute( QStringLiteral( "groupSpace" ), QStringLiteral( "3.0" ) ).toDouble() );
|
||||
}
|
||||
if ( !itemElem.attribute( QStringLiteral( "layerSpace" ) ).isEmpty() )
|
||||
{
|
||||
rstyle( QgsLegendStyle::Subgroup ).setMargin( QgsLegendStyle::Top, itemElem.attribute( QStringLiteral( "layerSpace" ), QStringLiteral( "3.0" ) ).toDouble() );
|
||||
}
|
||||
if ( !itemElem.attribute( QStringLiteral( "symbolSpace" ) ).isEmpty() )
|
||||
{
|
||||
rstyle( QgsLegendStyle::Symbol ).setMargin( QgsLegendStyle::Top, itemElem.attribute( QStringLiteral( "symbolSpace" ), QStringLiteral( "2.0" ) ).toDouble() );
|
||||
rstyle( QgsLegendStyle::SymbolLabel ).setMargin( QgsLegendStyle::Top, itemElem.attribute( QStringLiteral( "symbolSpace" ), QStringLiteral( "2.0" ) ).toDouble() );
|
||||
}
|
||||
// <<<<<<< < 2.0 projects backward compatibility
|
||||
|
||||
emit itemChanged();
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
QString QgsLayoutItemLegend::displayName() const
|
||||
{
|
||||
if ( !id().isEmpty() )
|
||||
{
|
||||
return id();
|
||||
}
|
||||
|
||||
//if no id, default to portion of title text
|
||||
QString text = mSettings.title();
|
||||
if ( text.isEmpty() )
|
||||
{
|
||||
return tr( "<legend>" );
|
||||
}
|
||||
if ( text.length() > 25 )
|
||||
{
|
||||
return QString( tr( "%1..." ) ).arg( text.left( 25 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return text;
|
||||
}
|
||||
}
|
||||
|
||||
void QgsLayoutItemLegend::setMap( QgsLayoutItemMap *map )
|
||||
{
|
||||
if ( mMap )
|
||||
{
|
||||
disconnect( mMap, &QObject::destroyed, this, &QgsLayoutItemLegend::invalidateCurrentMap );
|
||||
disconnect( mMap, &QgsLayoutObject::changed, this, &QgsLayoutItemLegend::updateFilterByMapAndRedraw );
|
||||
disconnect( mMap, &QgsLayoutItemMap::extentChanged, this, &QgsLayoutItemLegend::updateFilterByMapAndRedraw );
|
||||
disconnect( mMap, &QgsLayoutItemMap::layerStyleOverridesChanged, this, &QgsLayoutItemLegend::mapLayerStyleOverridesChanged );
|
||||
}
|
||||
|
||||
mMap = map;
|
||||
|
||||
if ( map )
|
||||
{
|
||||
connect( map, &QObject::destroyed, this, &QgsLayoutItemLegend::invalidateCurrentMap );
|
||||
connect( map, &QgsLayoutObject::changed, this, &QgsLayoutItemLegend::updateFilterByMapAndRedraw );
|
||||
connect( map, &QgsLayoutItemMap::extentChanged, this, &QgsLayoutItemLegend::updateFilterByMapAndRedraw );
|
||||
connect( map, &QgsLayoutItemMap::layerStyleOverridesChanged, this, &QgsLayoutItemLegend::mapLayerStyleOverridesChanged );
|
||||
}
|
||||
|
||||
updateFilterByMap();
|
||||
}
|
||||
|
||||
void QgsLayoutItemLegend::invalidateCurrentMap()
|
||||
{
|
||||
setMap( nullptr );
|
||||
}
|
||||
|
||||
void QgsLayoutItemLegend::refreshDataDefinedProperty( const QgsLayoutObject::DataDefinedProperty property )
|
||||
{
|
||||
QgsExpressionContext context = createExpressionContext();
|
||||
|
||||
bool forceUpdate = false;
|
||||
//updates data defined properties and redraws item to match
|
||||
if ( property == QgsLayoutObject::LegendTitle || property == QgsLayoutObject::AllProperties )
|
||||
{
|
||||
bool ok = false;
|
||||
QString t = mDataDefinedProperties.valueAsString( QgsLayoutObject::LegendTitle, context, mTitle, &ok );
|
||||
if ( ok )
|
||||
{
|
||||
mSettings.setTitle( t );
|
||||
forceUpdate = true;
|
||||
}
|
||||
}
|
||||
if ( property == QgsLayoutObject::LegendColumnCount || property == QgsLayoutObject::AllProperties )
|
||||
{
|
||||
bool ok = false;
|
||||
int cols = mDataDefinedProperties.valueAsInt( QgsLayoutObject::LegendColumnCount, context, mColumnCount, &ok );
|
||||
if ( ok && cols >= 0 )
|
||||
{
|
||||
mSettings.setColumnCount( cols );
|
||||
forceUpdate = true;
|
||||
}
|
||||
}
|
||||
if ( forceUpdate )
|
||||
{
|
||||
adjustBoxSize();
|
||||
update();
|
||||
}
|
||||
|
||||
QgsLayoutItem::refreshDataDefinedProperty( property );
|
||||
}
|
||||
|
||||
|
||||
void QgsLayoutItemLegend::updateFilterByMapAndRedraw()
|
||||
{
|
||||
updateFilterByMap( true );
|
||||
}
|
||||
|
||||
void QgsLayoutItemLegend::mapLayerStyleOverridesChanged()
|
||||
{
|
||||
if ( !mMap )
|
||||
return;
|
||||
|
||||
// map's style has been changed, so make sure to update the legend here
|
||||
if ( mLegendFilterByMap )
|
||||
{
|
||||
// legend is being filtered by map, so we need to re run the hit test too
|
||||
// as the style overrides may also have affected the visible symbols
|
||||
updateFilterByMap( false );
|
||||
}
|
||||
else
|
||||
{
|
||||
mLegendModel->setLayerStyleOverrides( mMap->layerStyleOverrides() );
|
||||
|
||||
Q_FOREACH ( QgsLayerTreeLayer *nodeLayer, mLegendModel->rootGroup()->findLayers() )
|
||||
mLegendModel->refreshLayerLegend( nodeLayer );
|
||||
}
|
||||
|
||||
adjustBoxSize();
|
||||
updateFilterByMap( false );
|
||||
}
|
||||
|
||||
void QgsLayoutItemLegend::updateFilterByMap( bool redraw )
|
||||
{
|
||||
// ask for update
|
||||
// the actual update will take place before the redraw.
|
||||
// This is to avoid multiple calls to the filter
|
||||
mFilterAskedForUpdate = true;
|
||||
|
||||
if ( redraw )
|
||||
update();
|
||||
}
|
||||
|
||||
void QgsLayoutItemLegend::doUpdateFilterByMap()
|
||||
{
|
||||
if ( mMap )
|
||||
mLegendModel->setLayerStyleOverrides( mMap->layerStyleOverrides() );
|
||||
else
|
||||
mLegendModel->setLayerStyleOverrides( QMap<QString, QString>() );
|
||||
|
||||
|
||||
bool filterByExpression = QgsLayerTreeUtils::hasLegendFilterExpression( *( mCustomLayerTree ? mCustomLayerTree.get() : mLayout->project()->layerTreeRoot() ) );
|
||||
|
||||
if ( mMap && ( mLegendFilterByMap || filterByExpression || mInAtlas ) )
|
||||
{
|
||||
int dpi = mLayout->context().dpi();
|
||||
|
||||
QgsRectangle requestRectangle = mMap->requestedExtent();
|
||||
|
||||
QSizeF size( requestRectangle.width(), requestRectangle.height() );
|
||||
size *= mLayout->convertFromLayoutUnits( mMap->mapUnitsToLayoutUnits(), QgsUnitTypes::LayoutMillimeters ).length() * dpi / 25.4;
|
||||
|
||||
QgsMapSettings ms = mMap->mapSettings( requestRectangle, size, dpi );
|
||||
|
||||
QgsGeometry filterPolygon;
|
||||
if ( mInAtlas )
|
||||
{
|
||||
#if 0 //TODO
|
||||
filterPolygon = composition()->atlasComposition().currentGeometry( mMap->crs() );
|
||||
#endif
|
||||
}
|
||||
mLegendModel->setLegendFilter( &ms, /* useExtent */ mInAtlas || mLegendFilterByMap, filterPolygon, /* useExpressions */ true );
|
||||
}
|
||||
else
|
||||
mLegendModel->setLegendFilterByMap( nullptr );
|
||||
|
||||
mForceResize = true;
|
||||
}
|
||||
|
||||
void QgsLayoutItemLegend::setLegendFilterOutAtlas( bool doFilter )
|
||||
{
|
||||
mFilterOutAtlas = doFilter;
|
||||
}
|
||||
|
||||
bool QgsLayoutItemLegend::legendFilterOutAtlas() const
|
||||
{
|
||||
return mFilterOutAtlas;
|
||||
}
|
||||
|
||||
void QgsLayoutItemLegend::onAtlasFeature( QgsFeature *feat )
|
||||
{
|
||||
if ( !feat )
|
||||
return;
|
||||
mInAtlas = mFilterOutAtlas;
|
||||
updateFilterByMap();
|
||||
}
|
||||
|
||||
void QgsLayoutItemLegend::onAtlasEnded()
|
||||
{
|
||||
mInAtlas = false;
|
||||
updateFilterByMap();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
#include "qgslayertreemodellegendnode.h"
|
||||
#include "qgsvectorlayer.h"
|
||||
|
||||
QgsLegendModel::QgsLegendModel( QgsLayerTree *rootNode, QObject *parent )
|
||||
: QgsLayerTreeModel( rootNode, parent )
|
||||
{
|
||||
setFlag( QgsLayerTreeModel::AllowLegendChangeState, false );
|
||||
setFlag( QgsLayerTreeModel::AllowNodeReorder, true );
|
||||
}
|
||||
|
||||
QVariant QgsLegendModel::data( const QModelIndex &index, int role ) const
|
||||
{
|
||||
// handle custom layer node labels
|
||||
if ( QgsLayerTreeNode *node = index2node( index ) )
|
||||
{
|
||||
if ( QgsLayerTree::isLayer( node ) && ( role == Qt::DisplayRole || role == Qt::EditRole ) && !node->customProperty( QStringLiteral( "legend/title-label" ) ).isNull() )
|
||||
{
|
||||
QgsLayerTreeLayer *nodeLayer = QgsLayerTree::toLayer( node );
|
||||
QString name = node->customProperty( QStringLiteral( "legend/title-label" ) ).toString();
|
||||
if ( nodeLayer->customProperty( QStringLiteral( "showFeatureCount" ), 0 ).toInt() && role == Qt::DisplayRole )
|
||||
{
|
||||
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( nodeLayer->layer() );
|
||||
if ( vlayer && vlayer->featureCount() >= 0 )
|
||||
name += QStringLiteral( " [%1]" ).arg( vlayer->featureCount() );
|
||||
}
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
return QgsLayerTreeModel::data( index, role );
|
||||
}
|
||||
|
||||
Qt::ItemFlags QgsLegendModel::flags( const QModelIndex &index ) const
|
||||
{
|
||||
// make the legend nodes selectable even if they are not by default
|
||||
if ( index2legendNode( index ) )
|
||||
return QgsLayerTreeModel::flags( index ) | Qt::ItemIsSelectable;
|
||||
|
||||
return QgsLayerTreeModel::flags( index );
|
||||
}
|
||||
529
src/core/layout/qgslayoutitemlegend.h
Normal file
529
src/core/layout/qgslayoutitemlegend.h
Normal file
@ -0,0 +1,529 @@
|
||||
/***************************************************************************
|
||||
qgslayoutitemlegend.h
|
||||
---------------------
|
||||
begin : October 2017
|
||||
copyright : (C) 2017 by Nyall Dawson
|
||||
email : nyall dot dawson at gmail dot com
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef QGSLAYOUTITEMLEGEND_H
|
||||
#define QGSLAYOUTITEMLEGEND_H
|
||||
|
||||
#include "qgis_core.h"
|
||||
#include "qgis.h"
|
||||
#include "qgslayoutitem.h"
|
||||
#include "qgslayertreemodel.h"
|
||||
#include "qgslegendsettings.h"
|
||||
#include "qgslayertreegroup.h"
|
||||
|
||||
class QgsLayerTreeModel;
|
||||
class QgsSymbol;
|
||||
class QgsLayoutItemMap;
|
||||
class QgsLegendRenderer;
|
||||
|
||||
/**
|
||||
* \ingroup core
|
||||
* Item model implementation based on layer tree model for layout legend.
|
||||
*
|
||||
* Overrides some functionality of QgsLayerTreeModel to better fit the needs of layout legends.
|
||||
*
|
||||
* \since QGIS 2.6
|
||||
*/
|
||||
class CORE_EXPORT QgsLegendModel : public QgsLayerTreeModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
//! Construct the model based on the given layer tree
|
||||
QgsLegendModel( QgsLayerTree *rootNode, QObject *parent SIP_TRANSFERTHIS = 0 );
|
||||
|
||||
QVariant data( const QModelIndex &index, int role ) const override;
|
||||
|
||||
Qt::ItemFlags flags( const QModelIndex &index ) const override;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* \ingroup core
|
||||
* A layout item subclass for map legends.
|
||||
* \since QGIS 3.0
|
||||
*/
|
||||
class CORE_EXPORT QgsLayoutItemLegend : public QgsLayoutItem
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor for QgsLayoutItemLegend, with the specified parent \a layout.
|
||||
*/
|
||||
QgsLayoutItemLegend( QgsLayout *layout );
|
||||
|
||||
/**
|
||||
* Returns a new legend item for the specified \a layout.
|
||||
*
|
||||
* The caller takes responsibility for deleting the returned object.
|
||||
*/
|
||||
static QgsLayoutItemLegend *create( QgsLayout *layout ) SIP_FACTORY;
|
||||
|
||||
int type() const override;
|
||||
QString stringType() const override;
|
||||
//Overridden to show legend title
|
||||
QString displayName() const override;
|
||||
|
||||
/**
|
||||
* Sets the legend's item bounds to fit the whole legend content.
|
||||
*/
|
||||
void adjustBoxSize();
|
||||
|
||||
/**
|
||||
* Sets whether the legend should automatically resize to fit its contents.
|
||||
* \param enabled set to false to disable automatic resizing. The legend frame will not
|
||||
* be expanded to fit legend items, and items may be cropped from display.
|
||||
* \see resizeToContents()
|
||||
*/
|
||||
void setResizeToContents( bool enabled );
|
||||
|
||||
/**
|
||||
* Returns whether the legend should automatically resize to fit its contents.
|
||||
* \see setResizeToContents()
|
||||
*/
|
||||
bool resizeToContents() const;
|
||||
|
||||
/**
|
||||
* Returns the legend model.
|
||||
*/
|
||||
QgsLegendModel *model() { return mLegendModel.get(); }
|
||||
|
||||
/**
|
||||
* Sets whether the legend content should auto update to reflect changes in the project's
|
||||
* layer tree.
|
||||
* \see autoUpdateModel()
|
||||
*/
|
||||
void setAutoUpdateModel( bool autoUpdate );
|
||||
|
||||
/**
|
||||
* Returns whether the legend content should auto update to reflect changes in the project's
|
||||
* layer tree.
|
||||
* \see setAutoUpdateModel()
|
||||
*/
|
||||
bool autoUpdateModel() const;
|
||||
|
||||
/**
|
||||
* Set whether legend items should be filtered to show just the ones visible in the associated map.
|
||||
* \see legendFilterByMapEnabled()
|
||||
*/
|
||||
void setLegendFilterByMapEnabled( bool enabled );
|
||||
|
||||
/**
|
||||
* Find out whether legend items are filtered to show just the ones visible in the associated map
|
||||
* \see setLegendFilterByMapEnabled()
|
||||
*/
|
||||
bool legendFilterByMapEnabled() const { return mLegendFilterByMap; }
|
||||
|
||||
#if 0//TODO
|
||||
|
||||
/**
|
||||
* Update() overloading. Use it rather than update()
|
||||
*/
|
||||
virtual void updateItem() override;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* When set to true, during an atlas rendering, it will filter out legend elements
|
||||
* where features are outside the current atlas feature.
|
||||
* \see legendFilterOutAtlas()
|
||||
*/
|
||||
void setLegendFilterOutAtlas( bool doFilter );
|
||||
|
||||
/**
|
||||
* Returns whether to filter out legend elements outside of the current atlas feature.
|
||||
* \see setLegendFilterOutAtlas()
|
||||
*/
|
||||
bool legendFilterOutAtlas() const;
|
||||
|
||||
/**
|
||||
* Sets the legend \a title.
|
||||
* \see title()
|
||||
*/
|
||||
void setTitle( const QString &title );
|
||||
|
||||
/**
|
||||
* Returns the legend title.
|
||||
* \see setTitle()
|
||||
*/
|
||||
QString title() const;
|
||||
|
||||
/**
|
||||
* Returns the alignment of the legend title.
|
||||
* \see setTitleAlignment()
|
||||
*/
|
||||
Qt::AlignmentFlag titleAlignment() const;
|
||||
|
||||
/**
|
||||
* Sets the \a alignment of the legend title.
|
||||
* \see titleAlignment()
|
||||
*/
|
||||
void setTitleAlignment( Qt::AlignmentFlag alignment );
|
||||
|
||||
/**
|
||||
* Returns reference to modifiable legend style.
|
||||
*/
|
||||
QgsLegendStyle &rstyle( QgsLegendStyle::Style s );
|
||||
|
||||
/**
|
||||
* Returns legend style.
|
||||
*/
|
||||
QgsLegendStyle style( QgsLegendStyle::Style s ) const;
|
||||
|
||||
/**
|
||||
* Sets the style of \a component to \a style for the legend.
|
||||
*/
|
||||
void setStyle( QgsLegendStyle::Style component, const QgsLegendStyle &style );
|
||||
|
||||
/**
|
||||
* Returns the font settings for a legend \a component.
|
||||
* \see setStyleFont()
|
||||
*/
|
||||
QFont styleFont( QgsLegendStyle::Style component ) const;
|
||||
|
||||
/**
|
||||
* Sets the style \a font for a legend \a component.
|
||||
* \see styleFont()
|
||||
*/
|
||||
void setStyleFont( QgsLegendStyle::Style component, const QFont &font );
|
||||
|
||||
/**
|
||||
* Set the \a margin for a legend \a component.
|
||||
*/
|
||||
void setStyleMargin( QgsLegendStyle::Style component, double margin );
|
||||
|
||||
/**
|
||||
* Set the \a margin for a particular \a side of a legend \a component.
|
||||
*/
|
||||
void setStyleMargin( QgsLegendStyle::Style component, QgsLegendStyle::Side side, double margin );
|
||||
|
||||
/**
|
||||
* Returns the spacing in-between lines in layout units.
|
||||
* \see setLineSpacing()
|
||||
*/
|
||||
double lineSpacing() const;
|
||||
|
||||
/**
|
||||
* Sets the \a spacing in-between multiple lines.
|
||||
* \see lineSpacing()
|
||||
*/
|
||||
void setLineSpacing( double spacing );
|
||||
|
||||
/**
|
||||
* Returns the legend box space.
|
||||
* \see setBoxSpace()
|
||||
*/
|
||||
double boxSpace() const;
|
||||
|
||||
/**
|
||||
* Sets the legend box \a space.
|
||||
* \see boxSpace()
|
||||
*/
|
||||
void setBoxSpace( double space );
|
||||
|
||||
/**
|
||||
* Returns the legend column spacing.
|
||||
* \see setColumnSpace()
|
||||
*/
|
||||
double columnSpace() const;
|
||||
|
||||
/**
|
||||
* Sets the legend column \a spacing.
|
||||
* \see columnSpace()
|
||||
*/
|
||||
void setColumnSpace( double spacing );
|
||||
|
||||
/**
|
||||
* Returns the legend font color.
|
||||
* \see setFontColor()
|
||||
*/
|
||||
QColor fontColor() const;
|
||||
|
||||
/**
|
||||
* Sets the legend font \a color.
|
||||
* \see fontColor()
|
||||
*/
|
||||
void setFontColor( const QColor &color );
|
||||
|
||||
/**
|
||||
* Returns the legend symbol width.
|
||||
* \see setSymbolWidth()
|
||||
*/
|
||||
double symbolWidth() const;
|
||||
|
||||
/**
|
||||
* Sets the legend symbol \a width.
|
||||
* \see symbolWidth()
|
||||
*/
|
||||
void setSymbolWidth( double width );
|
||||
|
||||
/**
|
||||
* Returns the legend symbol height.
|
||||
* \see setSymbolHeight()
|
||||
*/
|
||||
double symbolHeight() const;
|
||||
|
||||
/**
|
||||
* Sets the legend symbol \a height.
|
||||
* \see symbolHeight()
|
||||
*/
|
||||
void setSymbolHeight( double height );
|
||||
|
||||
/**
|
||||
* Returns the WMS legend width.
|
||||
* \see setWmsLegendWidth()
|
||||
*/
|
||||
double wmsLegendWidth() const;
|
||||
|
||||
/**
|
||||
* Sets the WMS legend \a width.
|
||||
* \see wmsLegendWidth()
|
||||
*/
|
||||
void setWmsLegendWidth( double width );
|
||||
|
||||
/**
|
||||
* Returns the WMS legend height.
|
||||
* \see setWmsLegendHeight()
|
||||
*/
|
||||
double wmsLegendHeight() const;
|
||||
|
||||
/**
|
||||
* Sets the WMS legend \a height.
|
||||
* \see wmsLegendHeight()
|
||||
*/
|
||||
void setWmsLegendHeight( double height );
|
||||
|
||||
/**
|
||||
* Sets the legend text wrapping \a string.
|
||||
* \see wrapString()
|
||||
*/
|
||||
void setWrapString( const QString &string );
|
||||
|
||||
/**
|
||||
* Returns the legend text wrapping string.
|
||||
* \see setWrapString()
|
||||
*/
|
||||
QString wrapString() const;
|
||||
|
||||
/**
|
||||
* Returns the legend column count.
|
||||
* \see setColumnCount()
|
||||
*/
|
||||
int columnCount() const;
|
||||
|
||||
/**
|
||||
* Sets the legend column \a count.
|
||||
* \see columnCount()
|
||||
*/
|
||||
void setColumnCount( int count );
|
||||
|
||||
/**
|
||||
* Returns whether the legend items from a single layer can be split
|
||||
* over multiple columns.
|
||||
* \see setSplitLayer()
|
||||
*/
|
||||
bool splitLayer() const;
|
||||
|
||||
/**
|
||||
* Sets whether the legend items from a single layer can be split
|
||||
* over multiple columns.
|
||||
* \see splitLayer()
|
||||
*/
|
||||
void setSplitLayer( bool enabled );
|
||||
|
||||
/**
|
||||
* Returns whether column widths should be equalized.
|
||||
* \see setEqualColumnWidth()
|
||||
*/
|
||||
bool equalColumnWidth() const;
|
||||
|
||||
/**
|
||||
* Sets whether column widths should be equalized.
|
||||
* \see equalColumnWidth()
|
||||
*/
|
||||
void setEqualColumnWidth( bool equalize );
|
||||
|
||||
/**
|
||||
* Returns whether a stroke will be drawn around raster symbol items.
|
||||
* \see setDrawRasterStroke()
|
||||
* \see rasterStrokeColor()
|
||||
* \see rasterStrokeWidth()
|
||||
*/
|
||||
bool drawRasterStroke() const;
|
||||
|
||||
/**
|
||||
* Sets whether a stroke will be drawn around raster symbol items.
|
||||
* \param enabled set to true to draw borders
|
||||
* \see drawRasterStroke()
|
||||
* \see setRasterStrokeColor()
|
||||
* \see setRasterStrokeWidth()
|
||||
*/
|
||||
void setDrawRasterStroke( bool enabled );
|
||||
|
||||
/**
|
||||
* Returns the stroke color for the stroke drawn around raster symbol items. The stroke is
|
||||
* only drawn if drawRasterStroke() is true.
|
||||
* \see setRasterStrokeColor()
|
||||
* \see drawRasterStroke()
|
||||
* \see rasterStrokeWidth()
|
||||
*/
|
||||
QColor rasterStrokeColor() const;
|
||||
|
||||
/**
|
||||
* Sets the stroke \a color for the stroke drawn around raster symbol items. The stroke is
|
||||
* only drawn if drawRasterStroke() is true.
|
||||
* \see rasterStrokeColor()
|
||||
* \see setDrawRasterStroke()
|
||||
* \see setRasterStrokeWidth()
|
||||
*/
|
||||
void setRasterStrokeColor( const QColor &color );
|
||||
|
||||
/**
|
||||
* Returns the stroke width (in layout units) for the stroke drawn around raster symbol items. The stroke is
|
||||
* only drawn if drawRasterStroke() is true.
|
||||
* \see setRasterStrokeWidth()
|
||||
* \see drawRasterStroke()
|
||||
* \see rasterStrokeColor()
|
||||
*/
|
||||
double rasterStrokeWidth() const;
|
||||
|
||||
/**
|
||||
* Sets the stroke width for the stroke drawn around raster symbol items. The stroke is
|
||||
* only drawn if drawRasterStroke() is true.
|
||||
* \see rasterStrokeWidth()
|
||||
* \see setDrawRasterStroke()
|
||||
* \see setRasterStrokeColor()
|
||||
*/
|
||||
void setRasterStrokeWidth( double width );
|
||||
|
||||
/**
|
||||
* Sets the \a map to associate with the legend.
|
||||
* \see map()
|
||||
*/
|
||||
void setMap( QgsLayoutItemMap *map );
|
||||
|
||||
/**
|
||||
* Returns the associated map.
|
||||
* \see setMap()
|
||||
*/
|
||||
QgsLayoutItemMap *map() const { return mMap; }
|
||||
|
||||
/**
|
||||
* Updates the model and all legend entries.
|
||||
*/
|
||||
void updateLegend();
|
||||
|
||||
/**
|
||||
* Updates the legend content when filtered by map.
|
||||
*/
|
||||
void updateFilterByMap( bool redraw = true );
|
||||
|
||||
#if 0//TODO
|
||||
|
||||
/**
|
||||
* Stores state in Dom node
|
||||
* \param elem is Dom element corresponding to 'Composer' tag
|
||||
* \param doc Dom document
|
||||
*/
|
||||
bool writeXml( QDomElement &elem, QDomDocument &doc ) const override;
|
||||
|
||||
/**
|
||||
* Sets state from Dom document
|
||||
* \param itemElem is Dom node corresponding to item tag
|
||||
* \param doc is Dom document
|
||||
*/
|
||||
bool readXml( const QDomElement &itemElem, const QDomDocument &doc ) override;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Returns the legend's renderer settings object.
|
||||
*/
|
||||
const QgsLegendSettings &legendSettings() const { return mSettings; }
|
||||
|
||||
void paint( QPainter *painter, const QStyleOptionGraphicsItem *itemStyle, QWidget *pWidget ) override;
|
||||
|
||||
|
||||
public slots:
|
||||
|
||||
void refreshDataDefinedProperty( const QgsLayoutObject::DataDefinedProperty property = QgsLayoutObject::AllProperties ) override;
|
||||
|
||||
protected:
|
||||
void draw( QgsRenderContext &context, const QStyleOptionGraphicsItem *itemStyle = nullptr ) override;
|
||||
|
||||
private slots:
|
||||
|
||||
//! Data changed
|
||||
void synchronizeWithModel();
|
||||
|
||||
//! Removes the associated map if the map is deleted.
|
||||
void invalidateCurrentMap();
|
||||
|
||||
void updateFilterByMapAndRedraw();
|
||||
|
||||
|
||||
//! update legend in case style of associated map has changed
|
||||
void mapLayerStyleOverridesChanged();
|
||||
|
||||
//! react to atlas
|
||||
void onAtlasEnded();
|
||||
void onAtlasFeature( QgsFeature * );
|
||||
|
||||
void nodeCustomPropertyChanged( QgsLayerTreeNode *node, const QString &key );
|
||||
|
||||
private:
|
||||
QgsLayoutItemLegend() = delete;
|
||||
|
||||
//! use new custom layer tree and update model. if new root is null pointer, will use project's tree
|
||||
void setCustomLayerTree( QgsLayerTree *rootGroup );
|
||||
|
||||
std::unique_ptr< QgsLegendModel > mLegendModel;
|
||||
std::unique_ptr< QgsLayerTreeGroup > mCustomLayerTree;
|
||||
|
||||
QgsLegendSettings mSettings;
|
||||
|
||||
QString mTitle;
|
||||
int mColumnCount = 1;
|
||||
|
||||
QgsLayoutItemMap *mMap = nullptr;
|
||||
|
||||
bool mLegendFilterByMap = false;
|
||||
bool mLegendFilterByExpression = false;
|
||||
|
||||
//! whether to filter out legend elements outside of the atlas feature
|
||||
bool mFilterOutAtlas = false;
|
||||
|
||||
//! tag for update request
|
||||
bool mFilterAskedForUpdate = false;
|
||||
//! actual filter update
|
||||
void doUpdateFilterByMap();
|
||||
|
||||
bool mInAtlas = false;
|
||||
|
||||
//! Will be false until the associated map scale and DPI have been calculated
|
||||
bool mInitialMapScaleCalculated = false;
|
||||
|
||||
//! Will be true if the legend size should be totally reset at next paint
|
||||
bool mForceResize = false;
|
||||
|
||||
//! Will be true if the legend should be resized automatically to fit contents
|
||||
bool mSizeToContents = true;
|
||||
};
|
||||
|
||||
#endif // QGSLAYOUTITEMLEGEND_H
|
||||
|
||||
@ -396,17 +396,24 @@ class CORE_EXPORT QgsLayoutItemMap : public QgsLayoutItem
|
||||
|
||||
QgsExpressionContext createExpressionContext() const override;
|
||||
|
||||
protected:
|
||||
|
||||
void draw( QgsRenderContext &context, const QStyleOptionGraphicsItem *itemStyle = nullptr ) override;
|
||||
bool writePropertiesToElement( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const override;
|
||||
bool readPropertiesFromElement( const QDomElement &element, const QDomDocument &document, const QgsReadWriteContext &context ) override;
|
||||
/**
|
||||
* Returns the conversion factor from map units to layout units.
|
||||
* This is calculated using the width of the map item and the width of the
|
||||
* current visible map extent.
|
||||
*/
|
||||
double mapUnitsToLayoutUnits() const;
|
||||
|
||||
/**
|
||||
* Return map settings that will be used for drawing of the map.
|
||||
*/
|
||||
QgsMapSettings mapSettings( const QgsRectangle &extent, QSizeF size, int dpi ) const;
|
||||
|
||||
protected:
|
||||
|
||||
void draw( QgsRenderContext &context, const QStyleOptionGraphicsItem *itemStyle = nullptr ) override;
|
||||
bool writePropertiesToElement( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const override;
|
||||
bool readPropertiesFromElement( const QDomElement &element, const QDomDocument &document, const QgsReadWriteContext &context ) override;
|
||||
|
||||
//! True if a draw is already in progress
|
||||
bool isDrawing() const {return mDrawing;}
|
||||
|
||||
@ -422,13 +429,6 @@ class CORE_EXPORT QgsLayoutItemMap : public QgsLayoutItem
|
||||
// In case of annotations, the bounding rectangle can be larger than the map item rectangle
|
||||
QRectF boundingRect() const override;
|
||||
|
||||
/**
|
||||
* Returns the conversion factor from map units to layout units.
|
||||
* This is calculated using the width of the map item and the width of the
|
||||
* current visible map extent.
|
||||
*/
|
||||
double mapUnitsToLayoutUnits() const;
|
||||
|
||||
//! Returns extent that considers rotation and shift with mOffsetX / mOffsetY
|
||||
QPolygonF transformedMapPolygon() const;
|
||||
|
||||
@ -644,6 +644,7 @@ class CORE_EXPORT QgsLayoutItemMap : public QgsLayoutItem
|
||||
|
||||
friend class QgsLayoutItemMapGrid;
|
||||
friend class QgsLayoutItemMapOverview;
|
||||
friend class QgsLayoutItemLegend;
|
||||
friend class TestQgsLayoutMap;
|
||||
|
||||
};
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
#include "qgslayoutitemshape.h"
|
||||
#include "qgslayoutitemmap.h"
|
||||
#include "qgslayoutitemlabel.h"
|
||||
#include "qgslayoutitemlegend.h"
|
||||
#include "qgslayoutitempolygon.h"
|
||||
#include "qgslayoutitempolyline.h"
|
||||
#include "qgslayoutitempage.h"
|
||||
@ -54,6 +55,7 @@ bool QgsLayoutItemRegistry::populate()
|
||||
addLayoutItemType( new QgsLayoutItemMetadata( LayoutMap, QStringLiteral( "Map" ), QgsApplication::getThemeIcon( QStringLiteral( "/mActionAddMap.svg" ) ), QgsLayoutItemMap::create ) );
|
||||
addLayoutItemType( new QgsLayoutItemMetadata( LayoutPicture, QStringLiteral( "Picture" ), QgsApplication::getThemeIcon( QStringLiteral( "/mActionAddImage.svg" ) ), QgsLayoutItemPicture::create ) );
|
||||
addLayoutItemType( new QgsLayoutItemMetadata( LayoutLabel, QStringLiteral( "Label" ), QgsApplication::getThemeIcon( QStringLiteral( "/mActionLabel.svg" ) ), QgsLayoutItemLabel::create ) );
|
||||
addLayoutItemType( new QgsLayoutItemMetadata( LayoutLegend, QStringLiteral( "Legend" ), QgsApplication::getThemeIcon( QStringLiteral( "/mActionAddLegend.svg" ) ), QgsLayoutItemLegend::create ) );
|
||||
addLayoutItemType( new QgsLayoutItemMetadata( LayoutShape, QStringLiteral( "Shape" ), QgsApplication::getThemeIcon( QStringLiteral( "/mActionAddBasicRectangle.svg" ) ), []( QgsLayout * layout )
|
||||
{
|
||||
QgsLayoutItemShape *shape = new QgsLayoutItemShape( layout );
|
||||
|
||||
@ -187,6 +187,7 @@ class CORE_EXPORT QgsLayoutItemRegistry : public QObject
|
||||
LayoutMap, //!< Map item
|
||||
LayoutPicture, //!< Picture item
|
||||
LayoutLabel, //!< Label item
|
||||
LayoutLegend, //!< Legend item
|
||||
LayoutShape, //!< Shape item
|
||||
LayoutPolygon, //!< Polygon shape item
|
||||
LayoutPolyline, //!< Polyline shape item
|
||||
|
||||
@ -109,6 +109,7 @@ INCLUDE_DIRECTORIES(
|
||||
${CMAKE_SOURCE_DIR}/src/core/raster
|
||||
${CMAKE_SOURCE_DIR}/src/core/symbology
|
||||
${CMAKE_SOURCE_DIR}/src/core/composer
|
||||
${CMAKE_SOURCE_DIR}/src/core/layout
|
||||
${CMAKE_SOURCE_DIR}/src/core/layertree
|
||||
${CMAKE_SOURCE_DIR}/src/analysis/interpolation
|
||||
${CMAKE_SOURCE_DIR}/src/plugins/diagram_overlay
|
||||
|
||||
@ -53,6 +53,7 @@ INCLUDE_DIRECTORIES(
|
||||
${CMAKE_SOURCE_DIR}/src/core/symbology
|
||||
${CMAKE_SOURCE_DIR}/src/core/composer
|
||||
${CMAKE_SOURCE_DIR}/src/core/layertree
|
||||
${CMAKE_SOURCE_DIR}/src/core/layout
|
||||
${CMAKE_SOURCE_DIR}/src/gui
|
||||
${CMAKE_SOURCE_DIR}/src/gui/editorwidgets
|
||||
${CMAKE_SOURCE_DIR}/src/gui/editorwidgets/core
|
||||
|
||||
@ -67,7 +67,7 @@
|
||||
#include "qgslayerrestorer.h"
|
||||
#include "qgsdxfexport.h"
|
||||
#include "qgssymbollayerutils.h"
|
||||
|
||||
#include "qgslayoutitemlegend.h"
|
||||
|
||||
#include <QImage>
|
||||
#include <QPainter>
|
||||
|
||||
1187
src/ui/layout/qgslayoutlegendwidgetbase.ui
Normal file
1187
src/ui/layout/qgslayoutlegendwidgetbase.ui
Normal file
File diff suppressed because it is too large
Load Diff
@ -34,6 +34,7 @@
|
||||
#include "qgslayertreegroup.h"
|
||||
#include "qgslayertreelayer.h"
|
||||
#include "qgslayertree.h"
|
||||
#include "qgslayoutitemlegend.h"
|
||||
|
||||
#include <QObject>
|
||||
#include "qgstest.h"
|
||||
|
||||
@ -87,6 +87,7 @@ ADD_PYTHON_TEST(PyQgsLayoutGuide test_qgslayoutguides.py)
|
||||
ADD_PYTHON_TEST(PyQgsLayoutItem test_qgslayoutitem.py)
|
||||
ADD_PYTHON_TEST(PyQgsLayoutItemPropertiesDialog test_qgslayoutitempropertiesdialog.py)
|
||||
ADD_PYTHON_TEST(PyQgsLayoutLabel test_qgslayoutlabel.py)
|
||||
ADD_PYTHON_TEST(PyQgsLayoutLegend test_qgslayoutlegend.py)
|
||||
ADD_PYTHON_TEST(PyQgsLayoutMap test_qgslayoutmap.py)
|
||||
ADD_PYTHON_TEST(PyQgsLayoutMapGrid test_qgslayoutmapgrid.py)
|
||||
ADD_PYTHON_TEST(PyQgsLayoutPicture test_qgslayoutpicture.py)
|
||||
|
||||
242
tests/src/python/test_qgslayoutlegend.py
Normal file
242
tests/src/python/test_qgslayoutlegend.py
Normal file
@ -0,0 +1,242 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""QGIS Unit tests for QgsLayoutItemLegend.
|
||||
|
||||
.. note:: This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
"""
|
||||
__author__ = '(C) 2017 by Nyall Dawson'
|
||||
__date__ = '24/10/2017'
|
||||
__copyright__ = 'Copyright 2017, The QGIS Project'
|
||||
# This will get replaced with a git SHA1 when you do a git archive
|
||||
__revision__ = '$Format:%H$'
|
||||
|
||||
from qgis.PyQt.QtCore import QRectF
|
||||
from qgis.PyQt.QtGui import QColor
|
||||
|
||||
from qgis.core import (QgsLayoutItemLegend,
|
||||
QgsLayoutItemMap,
|
||||
QgsLayout,
|
||||
QgsMapSettings,
|
||||
QgsVectorLayer,
|
||||
QgsMarkerSymbol,
|
||||
QgsSingleSymbolRenderer,
|
||||
QgsRectangle,
|
||||
QgsProject,
|
||||
QgsLayoutObject,
|
||||
QgsProperty,
|
||||
QgsLayoutMeasurement)
|
||||
from qgis.testing import (start_app,
|
||||
unittest
|
||||
)
|
||||
from utilities import unitTestDataPath
|
||||
from qgslayoutchecker import QgsLayoutChecker
|
||||
import os
|
||||
|
||||
start_app()
|
||||
TEST_DATA_DIR = unitTestDataPath()
|
||||
|
||||
|
||||
class TestQgsLayoutItemLegend(unittest.TestCase):
|
||||
|
||||
def testInitialSizeSymbolMapUnits(self):
|
||||
"""Test initial size of legend with a symbol size in map units"""
|
||||
|
||||
point_path = os.path.join(TEST_DATA_DIR, 'points.shp')
|
||||
point_layer = QgsVectorLayer(point_path, 'points', 'ogr')
|
||||
QgsProject.instance().addMapLayers([point_layer])
|
||||
|
||||
marker_symbol = QgsMarkerSymbol.createSimple({'color': '#ff0000', 'outline_style': 'no', 'size': '5', 'size_unit': 'MapUnit'})
|
||||
|
||||
point_layer.setRenderer(QgsSingleSymbolRenderer(marker_symbol))
|
||||
|
||||
s = QgsMapSettings()
|
||||
s.setLayers([point_layer])
|
||||
layout = QgsLayout(QgsProject.instance())
|
||||
layout.initializeDefaults()
|
||||
|
||||
map = QgsLayoutItemMap(layout)
|
||||
map.attemptSetSceneRect(QRectF(20, 20, 80, 80))
|
||||
map.setFrameEnabled(True)
|
||||
map.setLayers([point_layer])
|
||||
layout.addLayoutItem(map)
|
||||
map.setExtent(point_layer.extent())
|
||||
|
||||
legend = QgsLayoutItemLegend(layout)
|
||||
legend.attemptSetSceneRect(QRectF(120, 20, 80, 80))
|
||||
legend.setFrameEnabled(True)
|
||||
legend.setFrameStrokeWidth(QgsLayoutMeasurement(2))
|
||||
legend.setBackgroundColor(QColor(200, 200, 200))
|
||||
legend.setTitle('')
|
||||
layout.addLayoutItem(legend)
|
||||
legend.setMap(map)
|
||||
|
||||
checker = QgsLayoutChecker(
|
||||
'composer_legend_mapunits', layout)
|
||||
checker.setControlPathPrefix("composer_legend")
|
||||
result, message = checker.testLayout()
|
||||
self.assertTrue(result, message)
|
||||
|
||||
QgsProject.instance().removeMapLayers([point_layer.id()])
|
||||
|
||||
def testResizeWithMapContent(self):
|
||||
"""Test test legend resizes to match map content"""
|
||||
|
||||
point_path = os.path.join(TEST_DATA_DIR, 'points.shp')
|
||||
point_layer = QgsVectorLayer(point_path, 'points', 'ogr')
|
||||
QgsProject.instance().addMapLayers([point_layer])
|
||||
|
||||
s = QgsMapSettings()
|
||||
s.setLayers([point_layer])
|
||||
layout = QgsLayout(QgsProject.instance())
|
||||
layout.initializeDefaults()
|
||||
|
||||
map = QgsLayoutItemMap(layout)
|
||||
map.attemptSetSceneRect(QRectF(20, 20, 80, 80))
|
||||
map.setFrameEnabled(True)
|
||||
map.setLayers([point_layer])
|
||||
layout.addLayoutItem(map)
|
||||
map.setExtent(point_layer.extent())
|
||||
|
||||
legend = QgsLayoutItemLegend(layout)
|
||||
legend.attemptSetSceneRect(QRectF(120, 20, 80, 80))
|
||||
legend.setFrameEnabled(True)
|
||||
legend.setFrameStrokeWidth(QgsLayoutMeasurement(2))
|
||||
legend.setBackgroundColor(QColor(200, 200, 200))
|
||||
legend.setTitle('')
|
||||
legend.setLegendFilterByMapEnabled(True)
|
||||
layout.addLayoutItem(legend)
|
||||
legend.setMap(map)
|
||||
|
||||
map.setExtent(QgsRectangle(-102.51, 41.16, -102.36, 41.30))
|
||||
|
||||
checker = QgsLayoutChecker(
|
||||
'composer_legend_size_content', layout)
|
||||
checker.setControlPathPrefix("composer_legend")
|
||||
result, message = checker.testLayout()
|
||||
self.assertTrue(result, message)
|
||||
|
||||
QgsProject.instance().removeMapLayers([point_layer.id()])
|
||||
|
||||
def testResizeDisabled(self):
|
||||
"""Test that test legend does not resize if auto size is disabled"""
|
||||
|
||||
point_path = os.path.join(TEST_DATA_DIR, 'points.shp')
|
||||
point_layer = QgsVectorLayer(point_path, 'points', 'ogr')
|
||||
QgsProject.instance().addMapLayers([point_layer])
|
||||
|
||||
s = QgsMapSettings()
|
||||
s.setLayers([point_layer])
|
||||
layout = QgsLayout(QgsProject.instance())
|
||||
layout.initializeDefaults()
|
||||
|
||||
map = QgsLayoutItemMap(layout)
|
||||
map.attemptSetSceneRect(QRectF(20, 20, 80, 80))
|
||||
map.setFrameEnabled(True)
|
||||
map.setLayers([point_layer])
|
||||
layout.addLayoutItem(map)
|
||||
map.setExtent(point_layer.extent())
|
||||
|
||||
legend = QgsLayoutItemLegend(layout)
|
||||
legend.attemptSetSceneRect(QRectF(120, 20, 80, 80))
|
||||
legend.setFrameEnabled(True)
|
||||
legend.setFrameStrokeWidth(QgsLayoutMeasurement(2))
|
||||
legend.setBackgroundColor(QColor(200, 200, 200))
|
||||
legend.setTitle('')
|
||||
legend.setLegendFilterByMapEnabled(True)
|
||||
|
||||
# disable auto resizing
|
||||
legend.setResizeToContents(False)
|
||||
|
||||
layout.addLayoutItem(legend)
|
||||
legend.setMap(map)
|
||||
|
||||
map.setExtent(QgsRectangle(-102.51, 41.16, -102.36, 41.30))
|
||||
|
||||
checker = QgsLayoutChecker(
|
||||
'composer_legend_noresize', layout)
|
||||
checker.setControlPathPrefix("composer_legend")
|
||||
result, message = checker.testLayout()
|
||||
self.assertTrue(result, message)
|
||||
|
||||
QgsProject.instance().removeMapLayers([point_layer.id()])
|
||||
|
||||
def testResizeDisabledCrop(self):
|
||||
"""Test that if legend resizing is disabled, and legend is too small, then content is cropped"""
|
||||
|
||||
point_path = os.path.join(TEST_DATA_DIR, 'points.shp')
|
||||
point_layer = QgsVectorLayer(point_path, 'points', 'ogr')
|
||||
QgsProject.instance().addMapLayers([point_layer])
|
||||
|
||||
s = QgsMapSettings()
|
||||
s.setLayers([point_layer])
|
||||
layout = QgsLayout(QgsProject.instance())
|
||||
layout.initializeDefaults()
|
||||
|
||||
map = QgsLayoutItemMap(layout)
|
||||
map.attemptSetSceneRect(QRectF(20, 20, 80, 80))
|
||||
map.setFrameEnabled(True)
|
||||
map.setLayers([point_layer])
|
||||
layout.addLayoutItem(map)
|
||||
map.setExtent(point_layer.extent())
|
||||
|
||||
legend = QgsLayoutItemLegend(layout)
|
||||
legend.attemptSetSceneRect(QRectF(120, 20, 20, 20))
|
||||
legend.setFrameEnabled(True)
|
||||
legend.setFrameStrokeWidth(QgsLayoutMeasurement(2))
|
||||
legend.setBackgroundColor(QColor(200, 200, 200))
|
||||
legend.setTitle('')
|
||||
legend.setLegendFilterByMapEnabled(True)
|
||||
|
||||
# disable auto resizing
|
||||
legend.setResizeToContents(False)
|
||||
|
||||
layout.addLayoutItem(legend)
|
||||
legend.setMap(map)
|
||||
|
||||
map.setExtent(QgsRectangle(-102.51, 41.16, -102.36, 41.30))
|
||||
|
||||
checker = QgsLayoutChecker(
|
||||
'composer_legend_noresize_crop', layout)
|
||||
checker.setControlPathPrefix("composer_legend")
|
||||
result, message = checker.testLayout()
|
||||
self.assertTrue(result, message)
|
||||
|
||||
QgsProject.instance().removeMapLayers([point_layer.id()])
|
||||
|
||||
def testDataDefinedTitle(self):
|
||||
layout = QgsLayout(QgsProject.instance())
|
||||
layout.initializeDefaults()
|
||||
|
||||
legend = QgsLayoutItemLegend(layout)
|
||||
layout.addLayoutItem(legend)
|
||||
|
||||
legend.setTitle('original')
|
||||
self.assertEqual(legend.title(), 'original')
|
||||
self.assertEqual(legend.legendSettings().title(), 'original')
|
||||
|
||||
legend.dataDefinedProperties().setProperty(QgsLayoutObject.LegendTitle, QgsProperty.fromExpression("'new'"))
|
||||
legend.refreshDataDefinedProperty()
|
||||
self.assertEqual(legend.title(), 'original')
|
||||
self.assertEqual(legend.legendSettings().title(), 'new')
|
||||
|
||||
def testDataDefinedColumnCount(self):
|
||||
layout = QgsLayout(QgsProject.instance())
|
||||
layout.initializeDefaults()
|
||||
|
||||
legend = QgsLayoutItemLegend(layout)
|
||||
layout.addLayoutItem(legend)
|
||||
|
||||
legend.setColumnCount(2)
|
||||
self.assertEqual(legend.columnCount(), 2)
|
||||
self.assertEqual(legend.legendSettings().columnCount(), 2)
|
||||
|
||||
legend.dataDefinedProperties().setProperty(QgsLayoutObject.LegendColumnCount, QgsProperty.fromExpression("5"))
|
||||
legend.refreshDataDefinedProperty()
|
||||
self.assertEqual(legend.columnCount(), 2)
|
||||
self.assertEqual(legend.legendSettings().columnCount(), 5)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 7.9 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 5.5 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 6.0 KiB After Width: | Height: | Size: 6.1 KiB |
Loading…
x
Reference in New Issue
Block a user