mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-05 00:09:32 -04:00
Make common base class for annotation items which render in rect
And avoid a bunch of duplicate code
This commit is contained in:
parent
df4f29320b
commit
6127088395
@ -0,0 +1,5 @@
|
||||
# The following has been generated automatically from src/core/annotations/qgsannotationrectitem.h
|
||||
try:
|
||||
QgsAnnotationRectItem.__group__ = ['annotations']
|
||||
except NameError:
|
||||
pass
|
@ -380,14 +380,14 @@ Sets the ``unit`` for the :py:func:`~QgsAnnotationItem.offsetFromCallout`.
|
||||
|
||||
protected:
|
||||
|
||||
void copyCommonProperties( const QgsAnnotationItem *other );
|
||||
virtual void copyCommonProperties( const QgsAnnotationItem *other );
|
||||
%Docstring
|
||||
Copies common properties from the base class from an ``other`` item.
|
||||
|
||||
.. versionadded:: 3.22
|
||||
%End
|
||||
|
||||
bool writeCommonProperties( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const;
|
||||
virtual bool writeCommonProperties( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const;
|
||||
%Docstring
|
||||
Writes common properties from the base class into an XML ``element``.
|
||||
|
||||
@ -396,7 +396,7 @@ Writes common properties from the base class into an XML ``element``.
|
||||
.. versionadded:: 3.22
|
||||
%End
|
||||
|
||||
bool readCommonProperties( const QDomElement &element, const QgsReadWriteContext &context );
|
||||
virtual bool readCommonProperties( const QDomElement &element, const QgsReadWriteContext &context );
|
||||
%Docstring
|
||||
Reads common properties from the base class from the given DOM ``element``.
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
|
||||
|
||||
class QgsAnnotationPictureItem : QgsAnnotationItem
|
||||
class QgsAnnotationPictureItem : QgsAnnotationRectItem
|
||||
{
|
||||
%Docstring(signature="appended")
|
||||
An annotation item which renders a picture.
|
||||
@ -31,55 +31,16 @@ within the specified ``bounds`` geometry.
|
||||
|
||||
virtual QString type() const;
|
||||
|
||||
virtual Qgis::AnnotationItemFlags flags() const;
|
||||
|
||||
virtual void render( QgsRenderContext &context, QgsFeedback *feedback );
|
||||
|
||||
virtual bool writeXml( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const;
|
||||
|
||||
virtual QList< QgsAnnotationItemNode > nodesV2( const QgsAnnotationItemEditContext &context ) const;
|
||||
|
||||
virtual Qgis::AnnotationItemEditOperationResult applyEditV2( QgsAbstractAnnotationItemEditOperation *operation, const QgsAnnotationItemEditContext &context );
|
||||
|
||||
virtual QgsAnnotationItemEditOperationTransientResults *transientEditResultsV2( QgsAbstractAnnotationItemEditOperation *operation, const QgsAnnotationItemEditContext &context ) /Factory/;
|
||||
|
||||
|
||||
static QgsAnnotationPictureItem *create() /Factory/;
|
||||
%Docstring
|
||||
Creates a new polygon annotation item.
|
||||
%End
|
||||
|
||||
virtual bool readXml( const QDomElement &element, const QgsReadWriteContext &context );
|
||||
|
||||
virtual QgsAnnotationPictureItem *clone() const /Factory/;
|
||||
|
||||
virtual QgsRectangle boundingBox() const;
|
||||
|
||||
virtual QgsRectangle boundingBox( QgsRenderContext &context ) const;
|
||||
|
||||
|
||||
QgsRectangle bounds() const;
|
||||
static QgsAnnotationPictureItem *create() /Factory/;
|
||||
%Docstring
|
||||
Returns the bounds of the picture.
|
||||
|
||||
The coordinate reference system for the bounds will be the parent layer's :py:func:`QgsAnnotationLayer.crs()`.
|
||||
|
||||
When the :py:func:`~QgsAnnotationPictureItem.placementMode` is :py:class:`Qgis`.AnnotationPlacementMode.FixedSize then the picture will be placed
|
||||
at the center of the bounds.
|
||||
|
||||
.. seealso:: :py:func:`setBounds`
|
||||
%End
|
||||
|
||||
void setBounds( const QgsRectangle &bounds );
|
||||
%Docstring
|
||||
Sets the ``bounds`` of the picture.
|
||||
|
||||
The coordinate reference system for the bounds will be the parent layer's :py:func:`QgsAnnotationLayer.crs()`.
|
||||
|
||||
When the :py:func:`~QgsAnnotationPictureItem.placementMode` is :py:class:`Qgis`.AnnotationPlacementMode.FixedSize then the picture will be placed
|
||||
at the center of the bounds.
|
||||
|
||||
.. seealso:: :py:func:`bounds`
|
||||
Creates a new polygon annotation item.
|
||||
%End
|
||||
|
||||
QString path() const;
|
||||
@ -101,60 +62,6 @@ Sets the ``format`` and ``path`` of the image used to render the item.
|
||||
.. seealso:: :py:func:`path`
|
||||
|
||||
.. seealso:: :py:func:`format`
|
||||
%End
|
||||
|
||||
Qgis::AnnotationPlacementMode placementMode() const;
|
||||
%Docstring
|
||||
Returns the placement mode for the picture.
|
||||
|
||||
.. seealso:: :py:func:`setPlacementMode`
|
||||
%End
|
||||
|
||||
void setPlacementMode( Qgis::AnnotationPlacementMode mode );
|
||||
%Docstring
|
||||
Sets the placement ``mode`` for the picture.
|
||||
|
||||
.. seealso:: :py:func:`placementMode`
|
||||
%End
|
||||
|
||||
QSizeF fixedSize() const;
|
||||
%Docstring
|
||||
Returns the fixed size to use for the picture, when the :py:func:`~QgsAnnotationPictureItem.placementMode` is :py:class:`Qgis`.AnnotationPlacementMode.FixedSize.
|
||||
|
||||
Units are retrieved via :py:func:`~QgsAnnotationPictureItem.fixedSizeUnit`
|
||||
|
||||
.. seealso:: :py:func:`setFixedSize`
|
||||
|
||||
.. seealso:: :py:func:`fixedSizeUnit`
|
||||
%End
|
||||
|
||||
void setFixedSize( const QSizeF &size );
|
||||
%Docstring
|
||||
Sets the fixed ``size`` to use for the picture, when the :py:func:`~QgsAnnotationPictureItem.placementMode` is :py:class:`Qgis`.AnnotationPlacementMode.FixedSize.
|
||||
|
||||
Units are set via :py:func:`~QgsAnnotationPictureItem.setFixedSizeUnit`
|
||||
|
||||
.. seealso:: :py:func:`fixedSize`
|
||||
|
||||
.. seealso:: :py:func:`setFixedSizeUnit`
|
||||
%End
|
||||
|
||||
Qgis::RenderUnit fixedSizeUnit() const;
|
||||
%Docstring
|
||||
Returns the units to use for fixed picture sizes, when the :py:func:`~QgsAnnotationPictureItem.placementMode` is :py:class:`Qgis`.AnnotationPlacementMode.FixedSize.
|
||||
|
||||
.. seealso:: :py:func:`setFixedSizeUnit`
|
||||
|
||||
.. seealso:: :py:func:`fixedSize`
|
||||
%End
|
||||
|
||||
void setFixedSizeUnit( Qgis::RenderUnit unit );
|
||||
%Docstring
|
||||
Sets the ``unit`` to use for fixed picture sizes, when the :py:func:`~QgsAnnotationPictureItem.placementMode` is :py:class:`Qgis`.AnnotationPlacementMode.FixedSize.
|
||||
|
||||
.. seealso:: :py:func:`fixedSizeUnit`
|
||||
|
||||
.. seealso:: :py:func:`setFixedSize`
|
||||
%End
|
||||
|
||||
bool lockAspectRatio() const;
|
||||
@ -171,81 +78,10 @@ Sets whether the aspect ratio of the picture will be retained.
|
||||
.. seealso:: :py:func:`lockAspectRatio`
|
||||
%End
|
||||
|
||||
bool backgroundEnabled() const;
|
||||
%Docstring
|
||||
Returns ``True`` if the item's background should be rendered.
|
||||
protected:
|
||||
|
||||
.. seealso:: :py:func:`setBackgroundEnabled`
|
||||
virtual void renderInBounds( QgsRenderContext &context, const QRectF &painterBounds, QgsFeedback *feedback );
|
||||
|
||||
.. seealso:: :py:func:`backgroundSymbol`
|
||||
%End
|
||||
|
||||
void setBackgroundEnabled( bool enabled );
|
||||
%Docstring
|
||||
Sets whether the item's background should be rendered.
|
||||
|
||||
.. seealso:: :py:func:`backgroundEnabled`
|
||||
|
||||
.. seealso:: :py:func:`setBackgroundSymbol`
|
||||
%End
|
||||
|
||||
const QgsFillSymbol *backgroundSymbol() const;
|
||||
%Docstring
|
||||
Returns the symbol used to render the item's background.
|
||||
|
||||
.. seealso:: :py:func:`backgroundEnabled`
|
||||
|
||||
.. seealso:: :py:func:`setBackgroundSymbol`
|
||||
%End
|
||||
|
||||
void setBackgroundSymbol( QgsFillSymbol *symbol /Transfer/ );
|
||||
%Docstring
|
||||
Sets the ``symbol`` used to render the item's background.
|
||||
|
||||
The item takes ownership of the symbol.
|
||||
|
||||
.. seealso:: :py:func:`backgroundSymbol`
|
||||
|
||||
.. seealso:: :py:func:`setBackgroundEnabled`
|
||||
%End
|
||||
|
||||
bool frameEnabled() const;
|
||||
%Docstring
|
||||
Returns ``True`` if the item's frame should be rendered.
|
||||
|
||||
.. seealso:: :py:func:`setFrameEnabled`
|
||||
|
||||
.. seealso:: :py:func:`frameSymbol`
|
||||
%End
|
||||
|
||||
void setFrameEnabled( bool enabled );
|
||||
%Docstring
|
||||
Sets whether the item's frame should be rendered.
|
||||
|
||||
.. seealso:: :py:func:`frameEnabled`
|
||||
|
||||
.. seealso:: :py:func:`setFrameSymbol`
|
||||
%End
|
||||
|
||||
const QgsFillSymbol *frameSymbol() const;
|
||||
%Docstring
|
||||
Returns the symbol used to render the item's frame.
|
||||
|
||||
.. seealso:: :py:func:`frameEnabled`
|
||||
|
||||
.. seealso:: :py:func:`setFrameSymbol`
|
||||
%End
|
||||
|
||||
void setFrameSymbol( QgsFillSymbol *symbol /Transfer/ );
|
||||
%Docstring
|
||||
Sets the ``symbol`` used to render the item's frame.
|
||||
|
||||
The item takes ownership of the symbol.
|
||||
|
||||
.. seealso:: :py:func:`frameSymbol`
|
||||
|
||||
.. seealso:: :py:func:`setBackgroundEnabled`
|
||||
%End
|
||||
|
||||
private:
|
||||
QgsAnnotationPictureItem( const QgsAnnotationPictureItem &other );
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
|
||||
|
||||
class QgsAnnotationRectangleTextItem : QgsAnnotationItem
|
||||
class QgsAnnotationRectangleTextItem : QgsAnnotationRectItem
|
||||
{
|
||||
%Docstring(signature="appended")
|
||||
An annotation item which renders paragraphs of text within a rectangle.
|
||||
@ -33,16 +33,8 @@ within the specified ``bounds`` rectangle.
|
||||
|
||||
virtual Qgis::AnnotationItemFlags flags() const;
|
||||
|
||||
virtual void render( QgsRenderContext &context, QgsFeedback *feedback );
|
||||
|
||||
virtual bool writeXml( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const;
|
||||
|
||||
virtual QList< QgsAnnotationItemNode > nodesV2( const QgsAnnotationItemEditContext &context ) const;
|
||||
|
||||
virtual Qgis::AnnotationItemEditOperationResult applyEditV2( QgsAbstractAnnotationItemEditOperation *operation, const QgsAnnotationItemEditContext &context );
|
||||
|
||||
virtual QgsAnnotationItemEditOperationTransientResults *transientEditResultsV2( QgsAbstractAnnotationItemEditOperation *operation, const QgsAnnotationItemEditContext &context ) /Factory/;
|
||||
|
||||
|
||||
static QgsAnnotationRectangleTextItem *create() /Factory/;
|
||||
%Docstring
|
||||
@ -53,28 +45,6 @@ Creates a new rectangle text annotation item.
|
||||
|
||||
virtual QgsAnnotationRectangleTextItem *clone() const /Factory/;
|
||||
|
||||
virtual QgsRectangle boundingBox() const;
|
||||
|
||||
virtual QgsRectangle boundingBox( QgsRenderContext &context ) const;
|
||||
|
||||
|
||||
QgsRectangle bounds() const;
|
||||
%Docstring
|
||||
Returns the bounds of the text.
|
||||
|
||||
The coordinate reference system for the bounds will be the parent layer's :py:func:`QgsAnnotationLayer.crs()`.
|
||||
|
||||
.. seealso:: :py:func:`setBounds`
|
||||
%End
|
||||
|
||||
void setBounds( const QgsRectangle &bounds );
|
||||
%Docstring
|
||||
Sets the ``bounds`` of the text.
|
||||
|
||||
The coordinate reference system for the bounds will be the parent layer's :py:func:`QgsAnnotationLayer.crs()`.
|
||||
|
||||
.. seealso:: :py:func:`bounds`
|
||||
%End
|
||||
|
||||
QString text() const;
|
||||
%Docstring
|
||||
@ -88,60 +58,6 @@ Returns the text rendered by the item.
|
||||
Sets the ``text`` rendered by the item.
|
||||
|
||||
.. seealso:: :py:func:`text`
|
||||
%End
|
||||
|
||||
Qgis::AnnotationPlacementMode placementMode() const;
|
||||
%Docstring
|
||||
Returns the placement mode for the text.
|
||||
|
||||
.. seealso:: :py:func:`setPlacementMode`
|
||||
%End
|
||||
|
||||
void setPlacementMode( Qgis::AnnotationPlacementMode mode );
|
||||
%Docstring
|
||||
Sets the placement ``mode`` for the text.
|
||||
|
||||
.. seealso:: :py:func:`placementMode`
|
||||
%End
|
||||
|
||||
QSizeF fixedSize() const;
|
||||
%Docstring
|
||||
Returns the fixed size to use for the text, when the :py:func:`~QgsAnnotationRectangleTextItem.placementMode` is :py:class:`Qgis`.AnnotationPlacementMode.FixedSize.
|
||||
|
||||
Units are retrieved via :py:func:`~QgsAnnotationRectangleTextItem.fixedSizeUnit`
|
||||
|
||||
.. seealso:: :py:func:`setFixedSize`
|
||||
|
||||
.. seealso:: :py:func:`fixedSizeUnit`
|
||||
%End
|
||||
|
||||
void setFixedSize( const QSizeF &size );
|
||||
%Docstring
|
||||
Sets the fixed ``size`` to use for the text, when the :py:func:`~QgsAnnotationRectangleTextItem.placementMode` is :py:class:`Qgis`.AnnotationPlacementMode.FixedSize.
|
||||
|
||||
Units are set via :py:func:`~QgsAnnotationRectangleTextItem.setFixedSizeUnit`
|
||||
|
||||
.. seealso:: :py:func:`fixedSize`
|
||||
|
||||
.. seealso:: :py:func:`setFixedSizeUnit`
|
||||
%End
|
||||
|
||||
Qgis::RenderUnit fixedSizeUnit() const;
|
||||
%Docstring
|
||||
Returns the units to use for fixed text sizes, when the :py:func:`~QgsAnnotationRectangleTextItem.placementMode` is :py:class:`Qgis`.AnnotationPlacementMode.FixedSize.
|
||||
|
||||
.. seealso:: :py:func:`setFixedSizeUnit`
|
||||
|
||||
.. seealso:: :py:func:`fixedSize`
|
||||
%End
|
||||
|
||||
void setFixedSizeUnit( Qgis::RenderUnit unit );
|
||||
%Docstring
|
||||
Sets the ``unit`` to use for fixed text sizes, when the :py:func:`~QgsAnnotationRectangleTextItem.placementMode` is :py:class:`Qgis`.AnnotationPlacementMode.FixedSize.
|
||||
|
||||
.. seealso:: :py:func:`fixedSizeUnit`
|
||||
|
||||
.. seealso:: :py:func:`setFixedSize`
|
||||
%End
|
||||
|
||||
QgsTextFormat format() const;
|
||||
@ -170,82 +86,6 @@ Returns the text's alignment relative to the :py:func:`~QgsAnnotationRectangleTe
|
||||
Sets the text's ``alignment`` relative to the :py:func:`~QgsAnnotationRectangleTextItem.bounds` rectangle.
|
||||
|
||||
.. seealso:: :py:func:`alignment`
|
||||
%End
|
||||
|
||||
bool backgroundEnabled() const;
|
||||
%Docstring
|
||||
Returns ``True`` if the item's background should be rendered.
|
||||
|
||||
.. seealso:: :py:func:`setBackgroundEnabled`
|
||||
|
||||
.. seealso:: :py:func:`backgroundSymbol`
|
||||
%End
|
||||
|
||||
void setBackgroundEnabled( bool enabled );
|
||||
%Docstring
|
||||
Sets whether the item's background should be rendered.
|
||||
|
||||
.. seealso:: :py:func:`backgroundEnabled`
|
||||
|
||||
.. seealso:: :py:func:`setBackgroundSymbol`
|
||||
%End
|
||||
|
||||
const QgsFillSymbol *backgroundSymbol() const;
|
||||
%Docstring
|
||||
Returns the symbol used to render the item's background.
|
||||
|
||||
.. seealso:: :py:func:`backgroundEnabled`
|
||||
|
||||
.. seealso:: :py:func:`setBackgroundSymbol`
|
||||
%End
|
||||
|
||||
void setBackgroundSymbol( QgsFillSymbol *symbol /Transfer/ );
|
||||
%Docstring
|
||||
Sets the ``symbol`` used to render the item's background.
|
||||
|
||||
The item takes ownership of the symbol.
|
||||
|
||||
.. seealso:: :py:func:`backgroundSymbol`
|
||||
|
||||
.. seealso:: :py:func:`setBackgroundEnabled`
|
||||
%End
|
||||
|
||||
bool frameEnabled() const;
|
||||
%Docstring
|
||||
Returns ``True`` if the item's frame should be rendered.
|
||||
|
||||
.. seealso:: :py:func:`setFrameEnabled`
|
||||
|
||||
.. seealso:: :py:func:`frameSymbol`
|
||||
%End
|
||||
|
||||
void setFrameEnabled( bool enabled );
|
||||
%Docstring
|
||||
Sets whether the item's frame should be rendered.
|
||||
|
||||
.. seealso:: :py:func:`frameEnabled`
|
||||
|
||||
.. seealso:: :py:func:`setFrameSymbol`
|
||||
%End
|
||||
|
||||
const QgsFillSymbol *frameSymbol() const;
|
||||
%Docstring
|
||||
Returns the symbol used to render the item's frame.
|
||||
|
||||
.. seealso:: :py:func:`frameEnabled`
|
||||
|
||||
.. seealso:: :py:func:`setFrameSymbol`
|
||||
%End
|
||||
|
||||
void setFrameSymbol( QgsFillSymbol *symbol /Transfer/ );
|
||||
%Docstring
|
||||
Sets the ``symbol`` used to render the item's frame.
|
||||
|
||||
The item takes ownership of the symbol.
|
||||
|
||||
.. seealso:: :py:func:`frameSymbol`
|
||||
|
||||
.. seealso:: :py:func:`setBackgroundEnabled`
|
||||
%End
|
||||
|
||||
const QgsMargins &margins() const;
|
||||
@ -288,6 +128,11 @@ Returns the units for the margins between the item's frame and the interior text
|
||||
.. seealso:: :py:func:`margins`
|
||||
%End
|
||||
|
||||
protected:
|
||||
|
||||
virtual void renderInBounds( QgsRenderContext &context, const QRectF &painterBounds, QgsFeedback *feedback );
|
||||
|
||||
|
||||
private:
|
||||
QgsAnnotationRectangleTextItem( const QgsAnnotationRectangleTextItem &other );
|
||||
};
|
||||
|
@ -0,0 +1,231 @@
|
||||
/************************************************************************
|
||||
* This file has been generated automatically from *
|
||||
* *
|
||||
* src/core/annotations/qgsannotationrectitem.h *
|
||||
* *
|
||||
* Do not edit manually ! Edit header and run scripts/sipify.py again *
|
||||
************************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
class QgsAnnotationRectItem : QgsAnnotationItem
|
||||
{
|
||||
%Docstring(signature="appended")
|
||||
Abstract base class for annotation items which render annotations in a rectangular shape.
|
||||
|
||||
Subclasses should implement the pure virtual :py:func:`~render` method which takes a painter bounds argument.
|
||||
|
||||
.. versionadded:: 3.40
|
||||
%End
|
||||
|
||||
%TypeHeaderCode
|
||||
#include "qgsannotationrectitem.h"
|
||||
%End
|
||||
public:
|
||||
|
||||
QgsAnnotationRectItem( const QgsRectangle &bounds );
|
||||
%Docstring
|
||||
Constructor for QgsAnnotationRectItem, rendering the annotation
|
||||
within the specified ``bounds`` geometry.
|
||||
%End
|
||||
~QgsAnnotationRectItem();
|
||||
|
||||
virtual Qgis::AnnotationItemFlags flags() const;
|
||||
|
||||
virtual void render( QgsRenderContext &context, QgsFeedback *feedback );
|
||||
|
||||
virtual QList< QgsAnnotationItemNode > nodesV2( const QgsAnnotationItemEditContext &context ) const;
|
||||
|
||||
virtual Qgis::AnnotationItemEditOperationResult applyEditV2( QgsAbstractAnnotationItemEditOperation *operation, const QgsAnnotationItemEditContext &context );
|
||||
|
||||
virtual QgsAnnotationItemEditOperationTransientResults *transientEditResultsV2( QgsAbstractAnnotationItemEditOperation *operation, const QgsAnnotationItemEditContext &context ) /Factory/;
|
||||
|
||||
virtual QgsRectangle boundingBox() const;
|
||||
|
||||
virtual QgsRectangle boundingBox( QgsRenderContext &context ) const;
|
||||
|
||||
|
||||
QgsRectangle bounds() const;
|
||||
%Docstring
|
||||
Returns the bounds of the item.
|
||||
|
||||
The coordinate reference system for the item will be the parent layer's :py:func:`QgsAnnotationLayer.crs()`.
|
||||
|
||||
When the :py:func:`~QgsAnnotationRectItem.placementMode` is :py:class:`Qgis`.AnnotationPlacementMode.FixedSize then the item will be placed
|
||||
at the center of the bounds.
|
||||
|
||||
.. seealso:: :py:func:`setBounds`
|
||||
%End
|
||||
|
||||
void setBounds( const QgsRectangle &bounds );
|
||||
%Docstring
|
||||
Sets the ``bounds`` of the item.
|
||||
|
||||
The coordinate reference system for the bounds will be the parent layer's :py:func:`QgsAnnotationLayer.crs()`.
|
||||
|
||||
When the :py:func:`~QgsAnnotationRectItem.placementMode` is :py:class:`Qgis`.AnnotationPlacementMode.FixedSize then the item will be placed
|
||||
at the center of the bounds.
|
||||
|
||||
.. seealso:: :py:func:`bounds`
|
||||
%End
|
||||
|
||||
Qgis::AnnotationPlacementMode placementMode() const;
|
||||
%Docstring
|
||||
Returns the placement mode for the item.
|
||||
|
||||
.. seealso:: :py:func:`setPlacementMode`
|
||||
%End
|
||||
|
||||
void setPlacementMode( Qgis::AnnotationPlacementMode mode );
|
||||
%Docstring
|
||||
Sets the placement ``mode`` for the item.
|
||||
|
||||
.. seealso:: :py:func:`placementMode`
|
||||
%End
|
||||
|
||||
QSizeF fixedSize() const;
|
||||
%Docstring
|
||||
Returns the fixed size to use for the item, when the :py:func:`~QgsAnnotationRectItem.placementMode` is :py:class:`Qgis`.AnnotationPlacementMode.FixedSize.
|
||||
|
||||
Units are retrieved via :py:func:`~QgsAnnotationRectItem.fixedSizeUnit`
|
||||
|
||||
.. seealso:: :py:func:`setFixedSize`
|
||||
|
||||
.. seealso:: :py:func:`fixedSizeUnit`
|
||||
%End
|
||||
|
||||
void setFixedSize( const QSizeF &size );
|
||||
%Docstring
|
||||
Sets the fixed ``size`` to use for the item, when the :py:func:`~QgsAnnotationRectItem.placementMode` is :py:class:`Qgis`.AnnotationPlacementMode.FixedSize.
|
||||
|
||||
Units are set via :py:func:`~QgsAnnotationRectItem.setFixedSizeUnit`
|
||||
|
||||
.. seealso:: :py:func:`fixedSize`
|
||||
|
||||
.. seealso:: :py:func:`setFixedSizeUnit`
|
||||
%End
|
||||
|
||||
Qgis::RenderUnit fixedSizeUnit() const;
|
||||
%Docstring
|
||||
Returns the units to use for fixed item sizes, when the :py:func:`~QgsAnnotationRectItem.placementMode` is :py:class:`Qgis`.AnnotationPlacementMode.FixedSize.
|
||||
|
||||
.. seealso:: :py:func:`setFixedSizeUnit`
|
||||
|
||||
.. seealso:: :py:func:`fixedSize`
|
||||
%End
|
||||
|
||||
void setFixedSizeUnit( Qgis::RenderUnit unit );
|
||||
%Docstring
|
||||
Sets the ``unit`` to use for fixed item sizes, when the :py:func:`~QgsAnnotationRectItem.placementMode` is :py:class:`Qgis`.AnnotationPlacementMode.FixedSize.
|
||||
|
||||
.. seealso:: :py:func:`fixedSizeUnit`
|
||||
|
||||
.. seealso:: :py:func:`setFixedSize`
|
||||
%End
|
||||
|
||||
bool backgroundEnabled() const;
|
||||
%Docstring
|
||||
Returns ``True`` if the item's background should be rendered.
|
||||
|
||||
.. seealso:: :py:func:`setBackgroundEnabled`
|
||||
|
||||
.. seealso:: :py:func:`backgroundSymbol`
|
||||
%End
|
||||
|
||||
void setBackgroundEnabled( bool enabled );
|
||||
%Docstring
|
||||
Sets whether the item's background should be rendered.
|
||||
|
||||
.. seealso:: :py:func:`backgroundEnabled`
|
||||
|
||||
.. seealso:: :py:func:`setBackgroundSymbol`
|
||||
%End
|
||||
|
||||
const QgsFillSymbol *backgroundSymbol() const;
|
||||
%Docstring
|
||||
Returns the symbol used to render the item's background.
|
||||
|
||||
.. seealso:: :py:func:`backgroundEnabled`
|
||||
|
||||
.. seealso:: :py:func:`setBackgroundSymbol`
|
||||
%End
|
||||
|
||||
void setBackgroundSymbol( QgsFillSymbol *symbol /Transfer/ );
|
||||
%Docstring
|
||||
Sets the ``symbol`` used to render the item's background.
|
||||
|
||||
The item takes ownership of the symbol.
|
||||
|
||||
.. seealso:: :py:func:`backgroundSymbol`
|
||||
|
||||
.. seealso:: :py:func:`setBackgroundEnabled`
|
||||
%End
|
||||
|
||||
bool frameEnabled() const;
|
||||
%Docstring
|
||||
Returns ``True`` if the item's frame should be rendered.
|
||||
|
||||
.. seealso:: :py:func:`setFrameEnabled`
|
||||
|
||||
.. seealso:: :py:func:`frameSymbol`
|
||||
%End
|
||||
|
||||
void setFrameEnabled( bool enabled );
|
||||
%Docstring
|
||||
Sets whether the item's frame should be rendered.
|
||||
|
||||
.. seealso:: :py:func:`frameEnabled`
|
||||
|
||||
.. seealso:: :py:func:`setFrameSymbol`
|
||||
%End
|
||||
|
||||
const QgsFillSymbol *frameSymbol() const;
|
||||
%Docstring
|
||||
Returns the symbol used to render the item's frame.
|
||||
|
||||
.. seealso:: :py:func:`frameEnabled`
|
||||
|
||||
.. seealso:: :py:func:`setFrameSymbol`
|
||||
%End
|
||||
|
||||
void setFrameSymbol( QgsFillSymbol *symbol /Transfer/ );
|
||||
%Docstring
|
||||
Sets the ``symbol`` used to render the item's frame.
|
||||
|
||||
The item takes ownership of the symbol.
|
||||
|
||||
.. seealso:: :py:func:`frameSymbol`
|
||||
|
||||
.. seealso:: :py:func:`setBackgroundEnabled`
|
||||
%End
|
||||
|
||||
protected:
|
||||
virtual void copyCommonProperties( const QgsAnnotationItem *other );
|
||||
|
||||
virtual bool writeCommonProperties( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const;
|
||||
|
||||
virtual bool readCommonProperties( const QDomElement &element, const QgsReadWriteContext &context );
|
||||
|
||||
|
||||
virtual void renderInBounds( QgsRenderContext &context, const QRectF &painterRect, QgsFeedback *feedback ) = 0;
|
||||
%Docstring
|
||||
Renders the item to the specified render ``context``.
|
||||
|
||||
The ``painterRect`` argument specifies the bounds in painter units where the rectangular
|
||||
item should be rendered within.
|
||||
|
||||
The ``feedback`` argument can be used to detect render cancellations during expensive
|
||||
render operations.
|
||||
%End
|
||||
|
||||
private:
|
||||
QgsAnnotationRectItem( const QgsAnnotationRectItem &other );
|
||||
};
|
||||
/************************************************************************
|
||||
* This file has been generated automatically from *
|
||||
* *
|
||||
* src/core/annotations/qgsannotationrectitem.h *
|
||||
* *
|
||||
* Do not edit manually ! Edit header and run scripts/sipify.py again *
|
||||
************************************************************************/
|
@ -236,6 +236,7 @@
|
||||
%Include auto_generated/annotations/qgsannotationpointtextitem.sip
|
||||
%Include auto_generated/annotations/qgsannotationpolygonitem.sip
|
||||
%Include auto_generated/annotations/qgsannotationrectangletextitem.sip
|
||||
%Include auto_generated/annotations/qgsannotationrectitem.sip
|
||||
%Include auto_generated/annotations/qgshtmlannotation.sip
|
||||
%Include auto_generated/annotations/qgsrenderedannotationitemdetails.sip
|
||||
%Include auto_generated/annotations/qgssvgannotation.sip
|
||||
|
5
python/core/auto_additions/qgsannotationrectitem.py
Normal file
5
python/core/auto_additions/qgsannotationrectitem.py
Normal file
@ -0,0 +1,5 @@
|
||||
# The following has been generated automatically from src/core/annotations/qgsannotationrectitem.h
|
||||
try:
|
||||
QgsAnnotationRectItem.__group__ = ['annotations']
|
||||
except NameError:
|
||||
pass
|
@ -380,14 +380,14 @@ Sets the ``unit`` for the :py:func:`~QgsAnnotationItem.offsetFromCallout`.
|
||||
|
||||
protected:
|
||||
|
||||
void copyCommonProperties( const QgsAnnotationItem *other );
|
||||
virtual void copyCommonProperties( const QgsAnnotationItem *other );
|
||||
%Docstring
|
||||
Copies common properties from the base class from an ``other`` item.
|
||||
|
||||
.. versionadded:: 3.22
|
||||
%End
|
||||
|
||||
bool writeCommonProperties( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const;
|
||||
virtual bool writeCommonProperties( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const;
|
||||
%Docstring
|
||||
Writes common properties from the base class into an XML ``element``.
|
||||
|
||||
@ -396,7 +396,7 @@ Writes common properties from the base class into an XML ``element``.
|
||||
.. versionadded:: 3.22
|
||||
%End
|
||||
|
||||
bool readCommonProperties( const QDomElement &element, const QgsReadWriteContext &context );
|
||||
virtual bool readCommonProperties( const QDomElement &element, const QgsReadWriteContext &context );
|
||||
%Docstring
|
||||
Reads common properties from the base class from the given DOM ``element``.
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
|
||||
|
||||
class QgsAnnotationPictureItem : QgsAnnotationItem
|
||||
class QgsAnnotationPictureItem : QgsAnnotationRectItem
|
||||
{
|
||||
%Docstring(signature="appended")
|
||||
An annotation item which renders a picture.
|
||||
@ -31,55 +31,16 @@ within the specified ``bounds`` geometry.
|
||||
|
||||
virtual QString type() const;
|
||||
|
||||
virtual Qgis::AnnotationItemFlags flags() const;
|
||||
|
||||
virtual void render( QgsRenderContext &context, QgsFeedback *feedback );
|
||||
|
||||
virtual bool writeXml( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const;
|
||||
|
||||
virtual QList< QgsAnnotationItemNode > nodesV2( const QgsAnnotationItemEditContext &context ) const;
|
||||
|
||||
virtual Qgis::AnnotationItemEditOperationResult applyEditV2( QgsAbstractAnnotationItemEditOperation *operation, const QgsAnnotationItemEditContext &context );
|
||||
|
||||
virtual QgsAnnotationItemEditOperationTransientResults *transientEditResultsV2( QgsAbstractAnnotationItemEditOperation *operation, const QgsAnnotationItemEditContext &context ) /Factory/;
|
||||
|
||||
|
||||
static QgsAnnotationPictureItem *create() /Factory/;
|
||||
%Docstring
|
||||
Creates a new polygon annotation item.
|
||||
%End
|
||||
|
||||
virtual bool readXml( const QDomElement &element, const QgsReadWriteContext &context );
|
||||
|
||||
virtual QgsAnnotationPictureItem *clone() const /Factory/;
|
||||
|
||||
virtual QgsRectangle boundingBox() const;
|
||||
|
||||
virtual QgsRectangle boundingBox( QgsRenderContext &context ) const;
|
||||
|
||||
|
||||
QgsRectangle bounds() const;
|
||||
static QgsAnnotationPictureItem *create() /Factory/;
|
||||
%Docstring
|
||||
Returns the bounds of the picture.
|
||||
|
||||
The coordinate reference system for the bounds will be the parent layer's :py:func:`QgsAnnotationLayer.crs()`.
|
||||
|
||||
When the :py:func:`~QgsAnnotationPictureItem.placementMode` is :py:class:`Qgis`.AnnotationPlacementMode.FixedSize then the picture will be placed
|
||||
at the center of the bounds.
|
||||
|
||||
.. seealso:: :py:func:`setBounds`
|
||||
%End
|
||||
|
||||
void setBounds( const QgsRectangle &bounds );
|
||||
%Docstring
|
||||
Sets the ``bounds`` of the picture.
|
||||
|
||||
The coordinate reference system for the bounds will be the parent layer's :py:func:`QgsAnnotationLayer.crs()`.
|
||||
|
||||
When the :py:func:`~QgsAnnotationPictureItem.placementMode` is :py:class:`Qgis`.AnnotationPlacementMode.FixedSize then the picture will be placed
|
||||
at the center of the bounds.
|
||||
|
||||
.. seealso:: :py:func:`bounds`
|
||||
Creates a new polygon annotation item.
|
||||
%End
|
||||
|
||||
QString path() const;
|
||||
@ -101,60 +62,6 @@ Sets the ``format`` and ``path`` of the image used to render the item.
|
||||
.. seealso:: :py:func:`path`
|
||||
|
||||
.. seealso:: :py:func:`format`
|
||||
%End
|
||||
|
||||
Qgis::AnnotationPlacementMode placementMode() const;
|
||||
%Docstring
|
||||
Returns the placement mode for the picture.
|
||||
|
||||
.. seealso:: :py:func:`setPlacementMode`
|
||||
%End
|
||||
|
||||
void setPlacementMode( Qgis::AnnotationPlacementMode mode );
|
||||
%Docstring
|
||||
Sets the placement ``mode`` for the picture.
|
||||
|
||||
.. seealso:: :py:func:`placementMode`
|
||||
%End
|
||||
|
||||
QSizeF fixedSize() const;
|
||||
%Docstring
|
||||
Returns the fixed size to use for the picture, when the :py:func:`~QgsAnnotationPictureItem.placementMode` is :py:class:`Qgis`.AnnotationPlacementMode.FixedSize.
|
||||
|
||||
Units are retrieved via :py:func:`~QgsAnnotationPictureItem.fixedSizeUnit`
|
||||
|
||||
.. seealso:: :py:func:`setFixedSize`
|
||||
|
||||
.. seealso:: :py:func:`fixedSizeUnit`
|
||||
%End
|
||||
|
||||
void setFixedSize( const QSizeF &size );
|
||||
%Docstring
|
||||
Sets the fixed ``size`` to use for the picture, when the :py:func:`~QgsAnnotationPictureItem.placementMode` is :py:class:`Qgis`.AnnotationPlacementMode.FixedSize.
|
||||
|
||||
Units are set via :py:func:`~QgsAnnotationPictureItem.setFixedSizeUnit`
|
||||
|
||||
.. seealso:: :py:func:`fixedSize`
|
||||
|
||||
.. seealso:: :py:func:`setFixedSizeUnit`
|
||||
%End
|
||||
|
||||
Qgis::RenderUnit fixedSizeUnit() const;
|
||||
%Docstring
|
||||
Returns the units to use for fixed picture sizes, when the :py:func:`~QgsAnnotationPictureItem.placementMode` is :py:class:`Qgis`.AnnotationPlacementMode.FixedSize.
|
||||
|
||||
.. seealso:: :py:func:`setFixedSizeUnit`
|
||||
|
||||
.. seealso:: :py:func:`fixedSize`
|
||||
%End
|
||||
|
||||
void setFixedSizeUnit( Qgis::RenderUnit unit );
|
||||
%Docstring
|
||||
Sets the ``unit`` to use for fixed picture sizes, when the :py:func:`~QgsAnnotationPictureItem.placementMode` is :py:class:`Qgis`.AnnotationPlacementMode.FixedSize.
|
||||
|
||||
.. seealso:: :py:func:`fixedSizeUnit`
|
||||
|
||||
.. seealso:: :py:func:`setFixedSize`
|
||||
%End
|
||||
|
||||
bool lockAspectRatio() const;
|
||||
@ -171,81 +78,10 @@ Sets whether the aspect ratio of the picture will be retained.
|
||||
.. seealso:: :py:func:`lockAspectRatio`
|
||||
%End
|
||||
|
||||
bool backgroundEnabled() const;
|
||||
%Docstring
|
||||
Returns ``True`` if the item's background should be rendered.
|
||||
protected:
|
||||
|
||||
.. seealso:: :py:func:`setBackgroundEnabled`
|
||||
virtual void renderInBounds( QgsRenderContext &context, const QRectF &painterBounds, QgsFeedback *feedback );
|
||||
|
||||
.. seealso:: :py:func:`backgroundSymbol`
|
||||
%End
|
||||
|
||||
void setBackgroundEnabled( bool enabled );
|
||||
%Docstring
|
||||
Sets whether the item's background should be rendered.
|
||||
|
||||
.. seealso:: :py:func:`backgroundEnabled`
|
||||
|
||||
.. seealso:: :py:func:`setBackgroundSymbol`
|
||||
%End
|
||||
|
||||
const QgsFillSymbol *backgroundSymbol() const;
|
||||
%Docstring
|
||||
Returns the symbol used to render the item's background.
|
||||
|
||||
.. seealso:: :py:func:`backgroundEnabled`
|
||||
|
||||
.. seealso:: :py:func:`setBackgroundSymbol`
|
||||
%End
|
||||
|
||||
void setBackgroundSymbol( QgsFillSymbol *symbol /Transfer/ );
|
||||
%Docstring
|
||||
Sets the ``symbol`` used to render the item's background.
|
||||
|
||||
The item takes ownership of the symbol.
|
||||
|
||||
.. seealso:: :py:func:`backgroundSymbol`
|
||||
|
||||
.. seealso:: :py:func:`setBackgroundEnabled`
|
||||
%End
|
||||
|
||||
bool frameEnabled() const;
|
||||
%Docstring
|
||||
Returns ``True`` if the item's frame should be rendered.
|
||||
|
||||
.. seealso:: :py:func:`setFrameEnabled`
|
||||
|
||||
.. seealso:: :py:func:`frameSymbol`
|
||||
%End
|
||||
|
||||
void setFrameEnabled( bool enabled );
|
||||
%Docstring
|
||||
Sets whether the item's frame should be rendered.
|
||||
|
||||
.. seealso:: :py:func:`frameEnabled`
|
||||
|
||||
.. seealso:: :py:func:`setFrameSymbol`
|
||||
%End
|
||||
|
||||
const QgsFillSymbol *frameSymbol() const;
|
||||
%Docstring
|
||||
Returns the symbol used to render the item's frame.
|
||||
|
||||
.. seealso:: :py:func:`frameEnabled`
|
||||
|
||||
.. seealso:: :py:func:`setFrameSymbol`
|
||||
%End
|
||||
|
||||
void setFrameSymbol( QgsFillSymbol *symbol /Transfer/ );
|
||||
%Docstring
|
||||
Sets the ``symbol`` used to render the item's frame.
|
||||
|
||||
The item takes ownership of the symbol.
|
||||
|
||||
.. seealso:: :py:func:`frameSymbol`
|
||||
|
||||
.. seealso:: :py:func:`setBackgroundEnabled`
|
||||
%End
|
||||
|
||||
private:
|
||||
QgsAnnotationPictureItem( const QgsAnnotationPictureItem &other );
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
|
||||
|
||||
class QgsAnnotationRectangleTextItem : QgsAnnotationItem
|
||||
class QgsAnnotationRectangleTextItem : QgsAnnotationRectItem
|
||||
{
|
||||
%Docstring(signature="appended")
|
||||
An annotation item which renders paragraphs of text within a rectangle.
|
||||
@ -33,16 +33,8 @@ within the specified ``bounds`` rectangle.
|
||||
|
||||
virtual Qgis::AnnotationItemFlags flags() const;
|
||||
|
||||
virtual void render( QgsRenderContext &context, QgsFeedback *feedback );
|
||||
|
||||
virtual bool writeXml( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const;
|
||||
|
||||
virtual QList< QgsAnnotationItemNode > nodesV2( const QgsAnnotationItemEditContext &context ) const;
|
||||
|
||||
virtual Qgis::AnnotationItemEditOperationResult applyEditV2( QgsAbstractAnnotationItemEditOperation *operation, const QgsAnnotationItemEditContext &context );
|
||||
|
||||
virtual QgsAnnotationItemEditOperationTransientResults *transientEditResultsV2( QgsAbstractAnnotationItemEditOperation *operation, const QgsAnnotationItemEditContext &context ) /Factory/;
|
||||
|
||||
|
||||
static QgsAnnotationRectangleTextItem *create() /Factory/;
|
||||
%Docstring
|
||||
@ -53,28 +45,6 @@ Creates a new rectangle text annotation item.
|
||||
|
||||
virtual QgsAnnotationRectangleTextItem *clone() const /Factory/;
|
||||
|
||||
virtual QgsRectangle boundingBox() const;
|
||||
|
||||
virtual QgsRectangle boundingBox( QgsRenderContext &context ) const;
|
||||
|
||||
|
||||
QgsRectangle bounds() const;
|
||||
%Docstring
|
||||
Returns the bounds of the text.
|
||||
|
||||
The coordinate reference system for the bounds will be the parent layer's :py:func:`QgsAnnotationLayer.crs()`.
|
||||
|
||||
.. seealso:: :py:func:`setBounds`
|
||||
%End
|
||||
|
||||
void setBounds( const QgsRectangle &bounds );
|
||||
%Docstring
|
||||
Sets the ``bounds`` of the text.
|
||||
|
||||
The coordinate reference system for the bounds will be the parent layer's :py:func:`QgsAnnotationLayer.crs()`.
|
||||
|
||||
.. seealso:: :py:func:`bounds`
|
||||
%End
|
||||
|
||||
QString text() const;
|
||||
%Docstring
|
||||
@ -88,60 +58,6 @@ Returns the text rendered by the item.
|
||||
Sets the ``text`` rendered by the item.
|
||||
|
||||
.. seealso:: :py:func:`text`
|
||||
%End
|
||||
|
||||
Qgis::AnnotationPlacementMode placementMode() const;
|
||||
%Docstring
|
||||
Returns the placement mode for the text.
|
||||
|
||||
.. seealso:: :py:func:`setPlacementMode`
|
||||
%End
|
||||
|
||||
void setPlacementMode( Qgis::AnnotationPlacementMode mode );
|
||||
%Docstring
|
||||
Sets the placement ``mode`` for the text.
|
||||
|
||||
.. seealso:: :py:func:`placementMode`
|
||||
%End
|
||||
|
||||
QSizeF fixedSize() const;
|
||||
%Docstring
|
||||
Returns the fixed size to use for the text, when the :py:func:`~QgsAnnotationRectangleTextItem.placementMode` is :py:class:`Qgis`.AnnotationPlacementMode.FixedSize.
|
||||
|
||||
Units are retrieved via :py:func:`~QgsAnnotationRectangleTextItem.fixedSizeUnit`
|
||||
|
||||
.. seealso:: :py:func:`setFixedSize`
|
||||
|
||||
.. seealso:: :py:func:`fixedSizeUnit`
|
||||
%End
|
||||
|
||||
void setFixedSize( const QSizeF &size );
|
||||
%Docstring
|
||||
Sets the fixed ``size`` to use for the text, when the :py:func:`~QgsAnnotationRectangleTextItem.placementMode` is :py:class:`Qgis`.AnnotationPlacementMode.FixedSize.
|
||||
|
||||
Units are set via :py:func:`~QgsAnnotationRectangleTextItem.setFixedSizeUnit`
|
||||
|
||||
.. seealso:: :py:func:`fixedSize`
|
||||
|
||||
.. seealso:: :py:func:`setFixedSizeUnit`
|
||||
%End
|
||||
|
||||
Qgis::RenderUnit fixedSizeUnit() const;
|
||||
%Docstring
|
||||
Returns the units to use for fixed text sizes, when the :py:func:`~QgsAnnotationRectangleTextItem.placementMode` is :py:class:`Qgis`.AnnotationPlacementMode.FixedSize.
|
||||
|
||||
.. seealso:: :py:func:`setFixedSizeUnit`
|
||||
|
||||
.. seealso:: :py:func:`fixedSize`
|
||||
%End
|
||||
|
||||
void setFixedSizeUnit( Qgis::RenderUnit unit );
|
||||
%Docstring
|
||||
Sets the ``unit`` to use for fixed text sizes, when the :py:func:`~QgsAnnotationRectangleTextItem.placementMode` is :py:class:`Qgis`.AnnotationPlacementMode.FixedSize.
|
||||
|
||||
.. seealso:: :py:func:`fixedSizeUnit`
|
||||
|
||||
.. seealso:: :py:func:`setFixedSize`
|
||||
%End
|
||||
|
||||
QgsTextFormat format() const;
|
||||
@ -170,82 +86,6 @@ Returns the text's alignment relative to the :py:func:`~QgsAnnotationRectangleTe
|
||||
Sets the text's ``alignment`` relative to the :py:func:`~QgsAnnotationRectangleTextItem.bounds` rectangle.
|
||||
|
||||
.. seealso:: :py:func:`alignment`
|
||||
%End
|
||||
|
||||
bool backgroundEnabled() const;
|
||||
%Docstring
|
||||
Returns ``True`` if the item's background should be rendered.
|
||||
|
||||
.. seealso:: :py:func:`setBackgroundEnabled`
|
||||
|
||||
.. seealso:: :py:func:`backgroundSymbol`
|
||||
%End
|
||||
|
||||
void setBackgroundEnabled( bool enabled );
|
||||
%Docstring
|
||||
Sets whether the item's background should be rendered.
|
||||
|
||||
.. seealso:: :py:func:`backgroundEnabled`
|
||||
|
||||
.. seealso:: :py:func:`setBackgroundSymbol`
|
||||
%End
|
||||
|
||||
const QgsFillSymbol *backgroundSymbol() const;
|
||||
%Docstring
|
||||
Returns the symbol used to render the item's background.
|
||||
|
||||
.. seealso:: :py:func:`backgroundEnabled`
|
||||
|
||||
.. seealso:: :py:func:`setBackgroundSymbol`
|
||||
%End
|
||||
|
||||
void setBackgroundSymbol( QgsFillSymbol *symbol /Transfer/ );
|
||||
%Docstring
|
||||
Sets the ``symbol`` used to render the item's background.
|
||||
|
||||
The item takes ownership of the symbol.
|
||||
|
||||
.. seealso:: :py:func:`backgroundSymbol`
|
||||
|
||||
.. seealso:: :py:func:`setBackgroundEnabled`
|
||||
%End
|
||||
|
||||
bool frameEnabled() const;
|
||||
%Docstring
|
||||
Returns ``True`` if the item's frame should be rendered.
|
||||
|
||||
.. seealso:: :py:func:`setFrameEnabled`
|
||||
|
||||
.. seealso:: :py:func:`frameSymbol`
|
||||
%End
|
||||
|
||||
void setFrameEnabled( bool enabled );
|
||||
%Docstring
|
||||
Sets whether the item's frame should be rendered.
|
||||
|
||||
.. seealso:: :py:func:`frameEnabled`
|
||||
|
||||
.. seealso:: :py:func:`setFrameSymbol`
|
||||
%End
|
||||
|
||||
const QgsFillSymbol *frameSymbol() const;
|
||||
%Docstring
|
||||
Returns the symbol used to render the item's frame.
|
||||
|
||||
.. seealso:: :py:func:`frameEnabled`
|
||||
|
||||
.. seealso:: :py:func:`setFrameSymbol`
|
||||
%End
|
||||
|
||||
void setFrameSymbol( QgsFillSymbol *symbol /Transfer/ );
|
||||
%Docstring
|
||||
Sets the ``symbol`` used to render the item's frame.
|
||||
|
||||
The item takes ownership of the symbol.
|
||||
|
||||
.. seealso:: :py:func:`frameSymbol`
|
||||
|
||||
.. seealso:: :py:func:`setBackgroundEnabled`
|
||||
%End
|
||||
|
||||
const QgsMargins &margins() const;
|
||||
@ -288,6 +128,11 @@ Returns the units for the margins between the item's frame and the interior text
|
||||
.. seealso:: :py:func:`margins`
|
||||
%End
|
||||
|
||||
protected:
|
||||
|
||||
virtual void renderInBounds( QgsRenderContext &context, const QRectF &painterBounds, QgsFeedback *feedback );
|
||||
|
||||
|
||||
private:
|
||||
QgsAnnotationRectangleTextItem( const QgsAnnotationRectangleTextItem &other );
|
||||
};
|
||||
|
@ -0,0 +1,231 @@
|
||||
/************************************************************************
|
||||
* This file has been generated automatically from *
|
||||
* *
|
||||
* src/core/annotations/qgsannotationrectitem.h *
|
||||
* *
|
||||
* Do not edit manually ! Edit header and run scripts/sipify.py again *
|
||||
************************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
class QgsAnnotationRectItem : QgsAnnotationItem
|
||||
{
|
||||
%Docstring(signature="appended")
|
||||
Abstract base class for annotation items which render annotations in a rectangular shape.
|
||||
|
||||
Subclasses should implement the pure virtual :py:func:`~render` method which takes a painter bounds argument.
|
||||
|
||||
.. versionadded:: 3.40
|
||||
%End
|
||||
|
||||
%TypeHeaderCode
|
||||
#include "qgsannotationrectitem.h"
|
||||
%End
|
||||
public:
|
||||
|
||||
QgsAnnotationRectItem( const QgsRectangle &bounds );
|
||||
%Docstring
|
||||
Constructor for QgsAnnotationRectItem, rendering the annotation
|
||||
within the specified ``bounds`` geometry.
|
||||
%End
|
||||
~QgsAnnotationRectItem();
|
||||
|
||||
virtual Qgis::AnnotationItemFlags flags() const;
|
||||
|
||||
virtual void render( QgsRenderContext &context, QgsFeedback *feedback );
|
||||
|
||||
virtual QList< QgsAnnotationItemNode > nodesV2( const QgsAnnotationItemEditContext &context ) const;
|
||||
|
||||
virtual Qgis::AnnotationItemEditOperationResult applyEditV2( QgsAbstractAnnotationItemEditOperation *operation, const QgsAnnotationItemEditContext &context );
|
||||
|
||||
virtual QgsAnnotationItemEditOperationTransientResults *transientEditResultsV2( QgsAbstractAnnotationItemEditOperation *operation, const QgsAnnotationItemEditContext &context ) /Factory/;
|
||||
|
||||
virtual QgsRectangle boundingBox() const;
|
||||
|
||||
virtual QgsRectangle boundingBox( QgsRenderContext &context ) const;
|
||||
|
||||
|
||||
QgsRectangle bounds() const;
|
||||
%Docstring
|
||||
Returns the bounds of the item.
|
||||
|
||||
The coordinate reference system for the item will be the parent layer's :py:func:`QgsAnnotationLayer.crs()`.
|
||||
|
||||
When the :py:func:`~QgsAnnotationRectItem.placementMode` is :py:class:`Qgis`.AnnotationPlacementMode.FixedSize then the item will be placed
|
||||
at the center of the bounds.
|
||||
|
||||
.. seealso:: :py:func:`setBounds`
|
||||
%End
|
||||
|
||||
void setBounds( const QgsRectangle &bounds );
|
||||
%Docstring
|
||||
Sets the ``bounds`` of the item.
|
||||
|
||||
The coordinate reference system for the bounds will be the parent layer's :py:func:`QgsAnnotationLayer.crs()`.
|
||||
|
||||
When the :py:func:`~QgsAnnotationRectItem.placementMode` is :py:class:`Qgis`.AnnotationPlacementMode.FixedSize then the item will be placed
|
||||
at the center of the bounds.
|
||||
|
||||
.. seealso:: :py:func:`bounds`
|
||||
%End
|
||||
|
||||
Qgis::AnnotationPlacementMode placementMode() const;
|
||||
%Docstring
|
||||
Returns the placement mode for the item.
|
||||
|
||||
.. seealso:: :py:func:`setPlacementMode`
|
||||
%End
|
||||
|
||||
void setPlacementMode( Qgis::AnnotationPlacementMode mode );
|
||||
%Docstring
|
||||
Sets the placement ``mode`` for the item.
|
||||
|
||||
.. seealso:: :py:func:`placementMode`
|
||||
%End
|
||||
|
||||
QSizeF fixedSize() const;
|
||||
%Docstring
|
||||
Returns the fixed size to use for the item, when the :py:func:`~QgsAnnotationRectItem.placementMode` is :py:class:`Qgis`.AnnotationPlacementMode.FixedSize.
|
||||
|
||||
Units are retrieved via :py:func:`~QgsAnnotationRectItem.fixedSizeUnit`
|
||||
|
||||
.. seealso:: :py:func:`setFixedSize`
|
||||
|
||||
.. seealso:: :py:func:`fixedSizeUnit`
|
||||
%End
|
||||
|
||||
void setFixedSize( const QSizeF &size );
|
||||
%Docstring
|
||||
Sets the fixed ``size`` to use for the item, when the :py:func:`~QgsAnnotationRectItem.placementMode` is :py:class:`Qgis`.AnnotationPlacementMode.FixedSize.
|
||||
|
||||
Units are set via :py:func:`~QgsAnnotationRectItem.setFixedSizeUnit`
|
||||
|
||||
.. seealso:: :py:func:`fixedSize`
|
||||
|
||||
.. seealso:: :py:func:`setFixedSizeUnit`
|
||||
%End
|
||||
|
||||
Qgis::RenderUnit fixedSizeUnit() const;
|
||||
%Docstring
|
||||
Returns the units to use for fixed item sizes, when the :py:func:`~QgsAnnotationRectItem.placementMode` is :py:class:`Qgis`.AnnotationPlacementMode.FixedSize.
|
||||
|
||||
.. seealso:: :py:func:`setFixedSizeUnit`
|
||||
|
||||
.. seealso:: :py:func:`fixedSize`
|
||||
%End
|
||||
|
||||
void setFixedSizeUnit( Qgis::RenderUnit unit );
|
||||
%Docstring
|
||||
Sets the ``unit`` to use for fixed item sizes, when the :py:func:`~QgsAnnotationRectItem.placementMode` is :py:class:`Qgis`.AnnotationPlacementMode.FixedSize.
|
||||
|
||||
.. seealso:: :py:func:`fixedSizeUnit`
|
||||
|
||||
.. seealso:: :py:func:`setFixedSize`
|
||||
%End
|
||||
|
||||
bool backgroundEnabled() const;
|
||||
%Docstring
|
||||
Returns ``True`` if the item's background should be rendered.
|
||||
|
||||
.. seealso:: :py:func:`setBackgroundEnabled`
|
||||
|
||||
.. seealso:: :py:func:`backgroundSymbol`
|
||||
%End
|
||||
|
||||
void setBackgroundEnabled( bool enabled );
|
||||
%Docstring
|
||||
Sets whether the item's background should be rendered.
|
||||
|
||||
.. seealso:: :py:func:`backgroundEnabled`
|
||||
|
||||
.. seealso:: :py:func:`setBackgroundSymbol`
|
||||
%End
|
||||
|
||||
const QgsFillSymbol *backgroundSymbol() const;
|
||||
%Docstring
|
||||
Returns the symbol used to render the item's background.
|
||||
|
||||
.. seealso:: :py:func:`backgroundEnabled`
|
||||
|
||||
.. seealso:: :py:func:`setBackgroundSymbol`
|
||||
%End
|
||||
|
||||
void setBackgroundSymbol( QgsFillSymbol *symbol /Transfer/ );
|
||||
%Docstring
|
||||
Sets the ``symbol`` used to render the item's background.
|
||||
|
||||
The item takes ownership of the symbol.
|
||||
|
||||
.. seealso:: :py:func:`backgroundSymbol`
|
||||
|
||||
.. seealso:: :py:func:`setBackgroundEnabled`
|
||||
%End
|
||||
|
||||
bool frameEnabled() const;
|
||||
%Docstring
|
||||
Returns ``True`` if the item's frame should be rendered.
|
||||
|
||||
.. seealso:: :py:func:`setFrameEnabled`
|
||||
|
||||
.. seealso:: :py:func:`frameSymbol`
|
||||
%End
|
||||
|
||||
void setFrameEnabled( bool enabled );
|
||||
%Docstring
|
||||
Sets whether the item's frame should be rendered.
|
||||
|
||||
.. seealso:: :py:func:`frameEnabled`
|
||||
|
||||
.. seealso:: :py:func:`setFrameSymbol`
|
||||
%End
|
||||
|
||||
const QgsFillSymbol *frameSymbol() const;
|
||||
%Docstring
|
||||
Returns the symbol used to render the item's frame.
|
||||
|
||||
.. seealso:: :py:func:`frameEnabled`
|
||||
|
||||
.. seealso:: :py:func:`setFrameSymbol`
|
||||
%End
|
||||
|
||||
void setFrameSymbol( QgsFillSymbol *symbol /Transfer/ );
|
||||
%Docstring
|
||||
Sets the ``symbol`` used to render the item's frame.
|
||||
|
||||
The item takes ownership of the symbol.
|
||||
|
||||
.. seealso:: :py:func:`frameSymbol`
|
||||
|
||||
.. seealso:: :py:func:`setBackgroundEnabled`
|
||||
%End
|
||||
|
||||
protected:
|
||||
virtual void copyCommonProperties( const QgsAnnotationItem *other );
|
||||
|
||||
virtual bool writeCommonProperties( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const;
|
||||
|
||||
virtual bool readCommonProperties( const QDomElement &element, const QgsReadWriteContext &context );
|
||||
|
||||
|
||||
virtual void renderInBounds( QgsRenderContext &context, const QRectF &painterRect, QgsFeedback *feedback ) = 0;
|
||||
%Docstring
|
||||
Renders the item to the specified render ``context``.
|
||||
|
||||
The ``painterRect`` argument specifies the bounds in painter units where the rectangular
|
||||
item should be rendered within.
|
||||
|
||||
The ``feedback`` argument can be used to detect render cancellations during expensive
|
||||
render operations.
|
||||
%End
|
||||
|
||||
private:
|
||||
QgsAnnotationRectItem( const QgsAnnotationRectItem &other );
|
||||
};
|
||||
/************************************************************************
|
||||
* This file has been generated automatically from *
|
||||
* *
|
||||
* src/core/annotations/qgsannotationrectitem.h *
|
||||
* *
|
||||
* Do not edit manually ! Edit header and run scripts/sipify.py again *
|
||||
************************************************************************/
|
@ -236,6 +236,7 @@
|
||||
%Include auto_generated/annotations/qgsannotationpointtextitem.sip
|
||||
%Include auto_generated/annotations/qgsannotationpolygonitem.sip
|
||||
%Include auto_generated/annotations/qgsannotationrectangletextitem.sip
|
||||
%Include auto_generated/annotations/qgsannotationrectitem.sip
|
||||
%Include auto_generated/annotations/qgshtmlannotation.sip
|
||||
%Include auto_generated/annotations/qgsrenderedannotationitemdetails.sip
|
||||
%Include auto_generated/annotations/qgssvgannotation.sip
|
||||
|
@ -224,6 +224,7 @@ set(QGIS_CORE_SRCS
|
||||
annotations/qgsannotationpointtextitem.cpp
|
||||
annotations/qgsannotationpolygonitem.cpp
|
||||
annotations/qgsannotationrectangletextitem.cpp
|
||||
annotations/qgsannotationrectitem.cpp
|
||||
annotations/qgshtmlannotation.cpp
|
||||
annotations/qgsrenderedannotationitemdetails.cpp
|
||||
annotations/qgssvgannotation.cpp
|
||||
@ -1344,6 +1345,7 @@ set(QGIS_CORE_HDRS
|
||||
annotations/qgsannotationpointtextitem.h
|
||||
annotations/qgsannotationpolygonitem.h
|
||||
annotations/qgsannotationrectangletextitem.h
|
||||
annotations/qgsannotationrectitem.h
|
||||
annotations/qgsannotationregistry.h
|
||||
annotations/qgshtmlannotation.h
|
||||
annotations/qgsrenderedannotationitemdetails.h
|
||||
|
@ -389,7 +389,7 @@ class CORE_EXPORT QgsAnnotationItem
|
||||
*
|
||||
* \since QGIS 3.22
|
||||
*/
|
||||
void copyCommonProperties( const QgsAnnotationItem *other );
|
||||
virtual void copyCommonProperties( const QgsAnnotationItem *other );
|
||||
|
||||
/**
|
||||
* Writes common properties from the base class into an XML \a element.
|
||||
@ -397,7 +397,7 @@ class CORE_EXPORT QgsAnnotationItem
|
||||
* \see writeXml()
|
||||
* \since QGIS 3.22
|
||||
*/
|
||||
bool writeCommonProperties( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const;
|
||||
virtual bool writeCommonProperties( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const;
|
||||
|
||||
/**
|
||||
* Reads common properties from the base class from the given DOM \a element.
|
||||
@ -405,7 +405,7 @@ class CORE_EXPORT QgsAnnotationItem
|
||||
* \see readXml()
|
||||
* \since QGIS 3.22
|
||||
*/
|
||||
bool readCommonProperties( const QDomElement &element, const QgsReadWriteContext &context );
|
||||
virtual bool readCommonProperties( const QDomElement &element, const QgsReadWriteContext &context );
|
||||
|
||||
/**
|
||||
* Renders the item's callout.
|
||||
|
@ -21,35 +21,16 @@
|
||||
#include "qgssvgcache.h"
|
||||
#include "qgsgeometry.h"
|
||||
#include "qgsrendercontext.h"
|
||||
#include "qgsannotationitemnode.h"
|
||||
#include "qgsannotationitemeditoperation.h"
|
||||
#include "qgspainting.h"
|
||||
#include "qgsfillsymbol.h"
|
||||
#include "qgssymbollayerutils.h"
|
||||
#include "qgsfillsymbollayer.h"
|
||||
#include "qgslinesymbollayer.h"
|
||||
#include "qgsunittypes.h"
|
||||
#include "qgscalloutsregistry.h"
|
||||
#include "qgslinestring.h"
|
||||
#include "qgspolygon.h"
|
||||
|
||||
#include <QFileInfo>
|
||||
|
||||
QgsAnnotationPictureItem::QgsAnnotationPictureItem( Qgis::PictureFormat format, const QString &path, const QgsRectangle &bounds )
|
||||
: QgsAnnotationItem()
|
||||
, mBounds( bounds )
|
||||
: QgsAnnotationRectItem( bounds )
|
||||
{
|
||||
setPath( format, path );
|
||||
|
||||
mBackgroundSymbol = std::make_unique< QgsFillSymbol >(
|
||||
QgsSymbolLayerList
|
||||
{
|
||||
new QgsSimpleFillSymbolLayer( QColor( 255, 255, 255 ), Qt::BrushStyle::SolidPattern, QColor( 0, 0, 0 ), Qt::PenStyle::NoPen )
|
||||
}
|
||||
);
|
||||
QgsSimpleLineSymbolLayer *borderSymbol = new QgsSimpleLineSymbolLayer( QColor( 0, 0, 0 ) );
|
||||
borderSymbol->setPenJoinStyle( Qt::MiterJoin );
|
||||
mFrameSymbol = std::make_unique< QgsFillSymbol >( QgsSymbolLayerList{ borderSymbol } );
|
||||
}
|
||||
|
||||
QgsAnnotationPictureItem::~QgsAnnotationPictureItem() = default;
|
||||
@ -59,116 +40,9 @@ QString QgsAnnotationPictureItem::type() const
|
||||
return QStringLiteral( "picture" );
|
||||
}
|
||||
|
||||
Qgis::AnnotationItemFlags QgsAnnotationPictureItem::flags() const
|
||||
void QgsAnnotationPictureItem::renderInBounds( QgsRenderContext &context, const QRectF &painterBounds, QgsFeedback * )
|
||||
{
|
||||
switch ( mPlacementMode )
|
||||
{
|
||||
case Qgis::AnnotationPlacementMode::SpatialBounds:
|
||||
return Qgis::AnnotationItemFlag::SupportsCallouts;
|
||||
case Qgis::AnnotationPlacementMode::FixedSize:
|
||||
return Qgis::AnnotationItemFlag::ScaleDependentBoundingBox
|
||||
| Qgis::AnnotationItemFlag::SupportsCallouts;
|
||||
case Qgis::AnnotationPlacementMode::RelativeToMapFrame:
|
||||
return Qgis::AnnotationItemFlag::ScaleDependentBoundingBox;
|
||||
}
|
||||
BUILTIN_UNREACHABLE
|
||||
}
|
||||
|
||||
void QgsAnnotationPictureItem::render( QgsRenderContext &context, QgsFeedback *feedback )
|
||||
{
|
||||
QgsRectangle bounds = mBounds;
|
||||
if ( mPlacementMode != Qgis::AnnotationPlacementMode::RelativeToMapFrame && context.coordinateTransform().isValid() )
|
||||
{
|
||||
try
|
||||
{
|
||||
bounds = context.coordinateTransform().transformBoundingBox( mBounds );
|
||||
}
|
||||
catch ( QgsCsException & )
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool lockAspectRatio = mLockAspectRatio;
|
||||
QRectF painterBounds;
|
||||
|
||||
switch ( mPlacementMode )
|
||||
{
|
||||
case Qgis::AnnotationPlacementMode::SpatialBounds:
|
||||
painterBounds = context.mapToPixel().transformBounds( bounds.toRectF() );
|
||||
break;
|
||||
|
||||
case Qgis::AnnotationPlacementMode::FixedSize:
|
||||
{
|
||||
const double widthPixels = context.convertToPainterUnits( mFixedSize.width(), mFixedSizeUnit );
|
||||
const double heightPixels = context.convertToPainterUnits( mFixedSize.height(), mFixedSizeUnit );
|
||||
|
||||
if ( callout() && !calloutAnchor().isEmpty() )
|
||||
{
|
||||
QgsGeometry anchor = calloutAnchor();
|
||||
|
||||
const double calloutOffsetWidthPixels = context.convertToPainterUnits( offsetFromCallout().width(), offsetFromCalloutUnit() );
|
||||
const double calloutOffsetHeightPixels = context.convertToPainterUnits( offsetFromCallout().height(), offsetFromCalloutUnit() );
|
||||
|
||||
QPointF anchorPoint = anchor.asQPointF();
|
||||
if ( context.coordinateTransform().isValid() )
|
||||
{
|
||||
double x = anchorPoint.x();
|
||||
double y = anchorPoint.y();
|
||||
double z = 0.0;
|
||||
context.coordinateTransform().transformInPlace( x, y, z );
|
||||
anchorPoint = QPointF( x, y );
|
||||
}
|
||||
|
||||
context.mapToPixel().transformInPlace( anchorPoint.rx(), anchorPoint.ry() );
|
||||
|
||||
painterBounds = QRectF( anchorPoint.x() + calloutOffsetWidthPixels,
|
||||
anchorPoint.y() + calloutOffsetHeightPixels, widthPixels, heightPixels );
|
||||
}
|
||||
else
|
||||
{
|
||||
QPointF center = bounds.center().toQPointF();
|
||||
|
||||
context.mapToPixel().transformInPlace( center.rx(), center.ry() );
|
||||
painterBounds = QRectF( center.x() - widthPixels * 0.5,
|
||||
center.y() - heightPixels * 0.5,
|
||||
widthPixels, heightPixels );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Qgis::AnnotationPlacementMode::RelativeToMapFrame:
|
||||
{
|
||||
const double widthPixels = context.convertToPainterUnits( mFixedSize.width(), mFixedSizeUnit );
|
||||
const double heightPixels = context.convertToPainterUnits( mFixedSize.height(), mFixedSizeUnit );
|
||||
|
||||
QPointF center = bounds.center().toQPointF();
|
||||
center.rx() *= context.outputSize().width();
|
||||
center.ry() *= context.outputSize().height();
|
||||
|
||||
painterBounds = QRectF( center.x() - widthPixels * 0.5,
|
||||
center.y() - heightPixels * 0.5,
|
||||
widthPixels, heightPixels );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( painterBounds.width() < 1 || painterBounds.height() < 1 )
|
||||
return;
|
||||
|
||||
if ( mDrawBackground && mBackgroundSymbol )
|
||||
{
|
||||
mBackgroundSymbol->startRender( context );
|
||||
mBackgroundSymbol->renderPolygon( painterBounds, nullptr, nullptr, context );
|
||||
mBackgroundSymbol->stopRender( context );
|
||||
}
|
||||
|
||||
if ( mPlacementMode != Qgis::AnnotationPlacementMode::RelativeToMapFrame && callout() )
|
||||
{
|
||||
QgsCallout::QgsCalloutContext calloutContext;
|
||||
renderCallout( context, painterBounds, 0, calloutContext, feedback );
|
||||
}
|
||||
|
||||
bool fitsInCache = false;
|
||||
switch ( mFormat )
|
||||
{
|
||||
@ -229,379 +103,17 @@ void QgsAnnotationPictureItem::render( QgsRenderContext &context, QgsFeedback *f
|
||||
case Qgis::PictureFormat::Unknown:
|
||||
break;
|
||||
}
|
||||
|
||||
if ( mDrawFrame && mFrameSymbol )
|
||||
{
|
||||
mFrameSymbol->startRender( context );
|
||||
mFrameSymbol->renderPolygon( painterBounds, nullptr, nullptr, context );
|
||||
mFrameSymbol->stopRender( context );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool QgsAnnotationPictureItem::writeXml( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const
|
||||
{
|
||||
element.setAttribute( QStringLiteral( "lockAspect" ), mLockAspectRatio ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
|
||||
element.setAttribute( QStringLiteral( "xMin" ), qgsDoubleToString( mBounds.xMinimum() ) );
|
||||
element.setAttribute( QStringLiteral( "xMax" ), qgsDoubleToString( mBounds.xMaximum() ) );
|
||||
element.setAttribute( QStringLiteral( "yMin" ), qgsDoubleToString( mBounds.yMinimum() ) );
|
||||
element.setAttribute( QStringLiteral( "yMax" ), qgsDoubleToString( mBounds.yMaximum() ) );
|
||||
element.setAttribute( QStringLiteral( "path" ), mPath );
|
||||
element.setAttribute( QStringLiteral( "format" ), qgsEnumValueToKey( mFormat ) );
|
||||
element.setAttribute( QStringLiteral( "sizeMode" ), qgsEnumValueToKey( mPlacementMode ) );
|
||||
element.setAttribute( QStringLiteral( "fixedWidth" ), qgsDoubleToString( mFixedSize.width() ) );
|
||||
element.setAttribute( QStringLiteral( "fixedHeight" ), qgsDoubleToString( mFixedSize.height() ) );
|
||||
element.setAttribute( QStringLiteral( "fixedSizeUnit" ), QgsUnitTypes::encodeUnit( mFixedSizeUnit ) );
|
||||
|
||||
element.setAttribute( QStringLiteral( "backgroundEnabled" ), mDrawBackground ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
|
||||
if ( mBackgroundSymbol )
|
||||
{
|
||||
QDomElement backgroundElement = document.createElement( QStringLiteral( "backgroundSymbol" ) );
|
||||
backgroundElement.appendChild( QgsSymbolLayerUtils::saveSymbol( QStringLiteral( "backgroundSymbol" ), mBackgroundSymbol.get(), document, context ) );
|
||||
element.appendChild( backgroundElement );
|
||||
}
|
||||
|
||||
element.setAttribute( QStringLiteral( "frameEnabled" ), mDrawFrame ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
|
||||
if ( mFrameSymbol )
|
||||
{
|
||||
QDomElement frameElement = document.createElement( QStringLiteral( "frameSymbol" ) );
|
||||
frameElement.appendChild( QgsSymbolLayerUtils::saveSymbol( QStringLiteral( "frameSymbol" ), mFrameSymbol.get(), document, context ) );
|
||||
element.appendChild( frameElement );
|
||||
}
|
||||
|
||||
writeCommonProperties( element, document, context );
|
||||
return true;
|
||||
}
|
||||
|
||||
QList<QgsAnnotationItemNode> QgsAnnotationPictureItem::nodesV2( const QgsAnnotationItemEditContext &context ) const
|
||||
{
|
||||
QList<QgsAnnotationItemNode> res;
|
||||
switch ( mPlacementMode )
|
||||
{
|
||||
case Qgis::AnnotationPlacementMode::SpatialBounds:
|
||||
{
|
||||
res =
|
||||
{
|
||||
QgsAnnotationItemNode( QgsVertexId( 0, 0, 0 ), QgsPointXY( mBounds.xMinimum(), mBounds.yMinimum() ), Qgis::AnnotationItemNodeType::VertexHandle ),
|
||||
QgsAnnotationItemNode( QgsVertexId( 0, 0, 1 ), QgsPointXY( mBounds.xMaximum(), mBounds.yMinimum() ), Qgis::AnnotationItemNodeType::VertexHandle ),
|
||||
QgsAnnotationItemNode( QgsVertexId( 0, 0, 2 ), QgsPointXY( mBounds.xMaximum(), mBounds.yMaximum() ), Qgis::AnnotationItemNodeType::VertexHandle ),
|
||||
QgsAnnotationItemNode( QgsVertexId( 0, 0, 3 ), QgsPointXY( mBounds.xMinimum(), mBounds.yMaximum() ), Qgis::AnnotationItemNodeType::VertexHandle ),
|
||||
};
|
||||
|
||||
QgsPointXY calloutNodePoint;
|
||||
if ( !calloutAnchor().isEmpty() )
|
||||
{
|
||||
calloutNodePoint = calloutAnchor().asPoint();
|
||||
}
|
||||
else
|
||||
{
|
||||
calloutNodePoint = mBounds.center();
|
||||
}
|
||||
res.append( QgsAnnotationItemNode( QgsVertexId( 1, 0, 0 ), calloutNodePoint, Qgis::AnnotationItemNodeType::CalloutHandle ) );
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
case Qgis::AnnotationPlacementMode::FixedSize:
|
||||
{
|
||||
res =
|
||||
{
|
||||
QgsAnnotationItemNode( QgsVertexId( 0, 0, 0 ), mBounds.center(), Qgis::AnnotationItemNodeType::VertexHandle )
|
||||
};
|
||||
|
||||
QgsPointXY calloutNodePoint;
|
||||
if ( !calloutAnchor().isEmpty() )
|
||||
{
|
||||
calloutNodePoint = calloutAnchor().asPoint();
|
||||
}
|
||||
else
|
||||
{
|
||||
calloutNodePoint = QgsPointXY( context.currentItemBounds().xMinimum(), context.currentItemBounds().yMinimum() );
|
||||
}
|
||||
res.append( QgsAnnotationItemNode( QgsVertexId( 1, 0, 0 ), calloutNodePoint, Qgis::AnnotationItemNodeType::CalloutHandle ) );
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
case Qgis::AnnotationPlacementMode::RelativeToMapFrame:
|
||||
{
|
||||
return
|
||||
{
|
||||
QgsAnnotationItemNode( QgsVertexId( 0, 0, 0 ),
|
||||
context.currentItemBounds().center(), Qgis::AnnotationItemNodeType::VertexHandle )
|
||||
};
|
||||
}
|
||||
}
|
||||
BUILTIN_UNREACHABLE
|
||||
}
|
||||
|
||||
Qgis::AnnotationItemEditOperationResult QgsAnnotationPictureItem::applyEditV2( QgsAbstractAnnotationItemEditOperation *operation, const QgsAnnotationItemEditContext &context )
|
||||
{
|
||||
switch ( operation->type() )
|
||||
{
|
||||
case QgsAbstractAnnotationItemEditOperation::Type::MoveNode:
|
||||
{
|
||||
QgsAnnotationItemEditOperationMoveNode *moveOperation = dynamic_cast< QgsAnnotationItemEditOperationMoveNode * >( operation );
|
||||
if ( moveOperation->nodeId().part == 0 )
|
||||
{
|
||||
switch ( mPlacementMode )
|
||||
{
|
||||
case Qgis::AnnotationPlacementMode::SpatialBounds:
|
||||
{
|
||||
switch ( moveOperation->nodeId().vertex )
|
||||
{
|
||||
case 0:
|
||||
mBounds = QgsRectangle( moveOperation->after().x(),
|
||||
moveOperation->after().y(),
|
||||
mBounds.xMaximum(),
|
||||
mBounds.yMaximum() );
|
||||
break;
|
||||
case 1:
|
||||
mBounds = QgsRectangle( mBounds.xMinimum(),
|
||||
moveOperation->after().y(),
|
||||
moveOperation->after().x(),
|
||||
mBounds.yMaximum() );
|
||||
break;
|
||||
case 2:
|
||||
mBounds = QgsRectangle( mBounds.xMinimum(),
|
||||
mBounds.yMinimum(),
|
||||
moveOperation->after().x(),
|
||||
moveOperation->after().y() );
|
||||
break;
|
||||
case 3:
|
||||
mBounds = QgsRectangle( moveOperation->after().x(),
|
||||
mBounds.yMinimum(),
|
||||
mBounds.xMaximum(),
|
||||
moveOperation->after().y() );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return Qgis::AnnotationItemEditOperationResult::Success;
|
||||
}
|
||||
|
||||
case Qgis::AnnotationPlacementMode::FixedSize:
|
||||
{
|
||||
mBounds = QgsRectangle::fromCenterAndSize( moveOperation->after(),
|
||||
mBounds.width(),
|
||||
mBounds.height() );
|
||||
return Qgis::AnnotationItemEditOperationResult::Success;
|
||||
}
|
||||
|
||||
case Qgis::AnnotationPlacementMode::RelativeToMapFrame:
|
||||
{
|
||||
const double deltaX = moveOperation->translationXPixels() / context.renderContext().outputSize().width();
|
||||
const double deltaY = moveOperation->translationYPixels() / context.renderContext().outputSize().height();
|
||||
mBounds = QgsRectangle::fromCenterAndSize( QgsPointXY( mBounds.center().x() + deltaX, mBounds.center().y() + deltaY ),
|
||||
mBounds.width(), mBounds.height() );
|
||||
return Qgis::AnnotationItemEditOperationResult::Success;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( moveOperation->nodeId().part == 1 )
|
||||
{
|
||||
setCalloutAnchor( QgsGeometry::fromPoint( moveOperation->after() ) );
|
||||
if ( !callout() )
|
||||
{
|
||||
setCallout( QgsApplication::calloutRegistry()->defaultCallout() );
|
||||
}
|
||||
return Qgis::AnnotationItemEditOperationResult::Success;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case QgsAbstractAnnotationItemEditOperation::Type::TranslateItem:
|
||||
{
|
||||
QgsAnnotationItemEditOperationTranslateItem *moveOperation = qgis::down_cast< QgsAnnotationItemEditOperationTranslateItem * >( operation );
|
||||
switch ( mPlacementMode )
|
||||
{
|
||||
|
||||
case Qgis::AnnotationPlacementMode::SpatialBounds:
|
||||
mBounds = QgsRectangle( mBounds.xMinimum() + moveOperation->translationX(),
|
||||
mBounds.yMinimum() + moveOperation->translationY(),
|
||||
mBounds.xMaximum() + moveOperation->translationX(),
|
||||
mBounds.yMaximum() + moveOperation->translationY() );
|
||||
break;
|
||||
|
||||
case Qgis::AnnotationPlacementMode::FixedSize:
|
||||
{
|
||||
if ( callout() && !calloutAnchor().isEmpty() )
|
||||
{
|
||||
const double xOffset = context.renderContext().convertFromPainterUnits( moveOperation->translationXPixels(), offsetFromCalloutUnit() );
|
||||
const double yOffset = context.renderContext().convertFromPainterUnits( moveOperation->translationYPixels(), offsetFromCalloutUnit() );
|
||||
setOffsetFromCallout( QSizeF( offsetFromCallout().width() + xOffset, offsetFromCallout().height() + yOffset ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
mBounds = QgsRectangle( mBounds.xMinimum() + moveOperation->translationX(),
|
||||
mBounds.yMinimum() + moveOperation->translationY(),
|
||||
mBounds.xMaximum() + moveOperation->translationX(),
|
||||
mBounds.yMaximum() + moveOperation->translationY() );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Qgis::AnnotationPlacementMode::RelativeToMapFrame:
|
||||
{
|
||||
const double deltaX = moveOperation->translationXPixels() / context.renderContext().outputSize().width();
|
||||
const double deltaY = moveOperation->translationYPixels() / context.renderContext().outputSize().height();
|
||||
mBounds = QgsRectangle::fromCenterAndSize( QgsPointXY( mBounds.center().x() + deltaX, mBounds.center().y() + deltaY ),
|
||||
mBounds.width(), mBounds.height() );
|
||||
break;
|
||||
}
|
||||
}
|
||||
return Qgis::AnnotationItemEditOperationResult::Success;
|
||||
}
|
||||
|
||||
case QgsAbstractAnnotationItemEditOperation::Type::DeleteNode:
|
||||
case QgsAbstractAnnotationItemEditOperation::Type::AddNode:
|
||||
break;
|
||||
}
|
||||
return Qgis::AnnotationItemEditOperationResult::Invalid;
|
||||
}
|
||||
|
||||
QgsAnnotationItemEditOperationTransientResults *QgsAnnotationPictureItem::transientEditResultsV2( QgsAbstractAnnotationItemEditOperation *operation, const QgsAnnotationItemEditContext &context )
|
||||
{
|
||||
switch ( operation->type() )
|
||||
{
|
||||
case QgsAbstractAnnotationItemEditOperation::Type::MoveNode:
|
||||
{
|
||||
QgsAnnotationItemEditOperationMoveNode *moveOperation = dynamic_cast< QgsAnnotationItemEditOperationMoveNode * >( operation );
|
||||
if ( moveOperation->nodeId().part == 0 )
|
||||
{
|
||||
switch ( mPlacementMode )
|
||||
{
|
||||
case Qgis::AnnotationPlacementMode::SpatialBounds:
|
||||
{
|
||||
QgsRectangle modifiedBounds = mBounds;
|
||||
switch ( moveOperation->nodeId().vertex )
|
||||
{
|
||||
case 0:
|
||||
modifiedBounds.setXMinimum( moveOperation->after().x() );
|
||||
modifiedBounds.setYMinimum( moveOperation->after().y() );
|
||||
break;
|
||||
case 1:
|
||||
modifiedBounds.setXMaximum( moveOperation->after().x() );
|
||||
modifiedBounds.setYMinimum( moveOperation->after().y() );
|
||||
break;
|
||||
case 2:
|
||||
modifiedBounds.setXMaximum( moveOperation->after().x() );
|
||||
modifiedBounds.setYMaximum( moveOperation->after().y() );
|
||||
break;
|
||||
case 3:
|
||||
modifiedBounds.setXMinimum( moveOperation->after().x() );
|
||||
modifiedBounds.setYMaximum( moveOperation->after().y() );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return new QgsAnnotationItemEditOperationTransientResults( QgsGeometry::fromRect( modifiedBounds ) );
|
||||
}
|
||||
case Qgis::AnnotationPlacementMode::FixedSize:
|
||||
{
|
||||
const QgsRectangle currentBounds = context.currentItemBounds();
|
||||
const QgsRectangle newBounds = QgsRectangle::fromCenterAndSize( moveOperation->after(), currentBounds.width(), currentBounds.height() );
|
||||
return new QgsAnnotationItemEditOperationTransientResults( QgsGeometry::fromRect( newBounds ) );
|
||||
}
|
||||
case Qgis::AnnotationPlacementMode::RelativeToMapFrame:
|
||||
{
|
||||
const QgsRectangle currentBounds = context.currentItemBounds();
|
||||
const QgsRectangle newBounds = QgsRectangle::fromCenterAndSize( currentBounds.center() + ( moveOperation->after() - moveOperation->before() ),
|
||||
currentBounds.width(), currentBounds.height() );
|
||||
return new QgsAnnotationItemEditOperationTransientResults( QgsGeometry::fromRect( newBounds ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsAnnotationItemEditOperationMoveNode *moveOperation = dynamic_cast< QgsAnnotationItemEditOperationMoveNode * >( operation );
|
||||
return new QgsAnnotationItemEditOperationTransientResults( QgsGeometry( moveOperation->after().clone() ) );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case QgsAbstractAnnotationItemEditOperation::Type::TranslateItem:
|
||||
{
|
||||
QgsAnnotationItemEditOperationTranslateItem *moveOperation = qgis::down_cast< QgsAnnotationItemEditOperationTranslateItem * >( operation );
|
||||
switch ( mPlacementMode )
|
||||
{
|
||||
case Qgis::AnnotationPlacementMode::SpatialBounds:
|
||||
{
|
||||
const QgsRectangle modifiedBounds( mBounds.xMinimum() + moveOperation->translationX(),
|
||||
mBounds.yMinimum() + moveOperation->translationY(),
|
||||
mBounds.xMaximum() + moveOperation->translationX(),
|
||||
mBounds.yMaximum() + moveOperation->translationY() );
|
||||
return new QgsAnnotationItemEditOperationTransientResults( QgsGeometry::fromRect( modifiedBounds ) );
|
||||
}
|
||||
|
||||
case Qgis::AnnotationPlacementMode::FixedSize:
|
||||
{
|
||||
if ( callout() && !calloutAnchor().isEmpty() )
|
||||
{
|
||||
QgsGeometry anchor = calloutAnchor();
|
||||
|
||||
const double calloutOffsetWidthPixels = context.renderContext().convertToPainterUnits( offsetFromCallout().width(), offsetFromCalloutUnit() )
|
||||
+ moveOperation->translationXPixels();
|
||||
const double calloutOffsetHeightPixels = context.renderContext().convertToPainterUnits( offsetFromCallout().height(), offsetFromCalloutUnit() )
|
||||
+ moveOperation->translationYPixels();
|
||||
|
||||
QPointF anchorPoint = anchor.asQPointF();
|
||||
if ( context.renderContext().coordinateTransform().isValid() )
|
||||
{
|
||||
double x = anchorPoint.x();
|
||||
double y = anchorPoint.y();
|
||||
double z = 0.0;
|
||||
context.renderContext().coordinateTransform().transformInPlace( x, y, z );
|
||||
anchorPoint = QPointF( x, y );
|
||||
}
|
||||
|
||||
context.renderContext().mapToPixel().transformInPlace( anchorPoint.rx(), anchorPoint.ry() );
|
||||
|
||||
const double textOriginXPixels = anchorPoint.x() + calloutOffsetWidthPixels;
|
||||
const double textOriginYPixels = anchorPoint.y() + calloutOffsetHeightPixels;
|
||||
|
||||
const double widthPixels = context.renderContext().convertToPainterUnits( mFixedSize.width(), mFixedSizeUnit );
|
||||
const double heightPixels = context.renderContext().convertToPainterUnits( mFixedSize.height(), mFixedSizeUnit );
|
||||
|
||||
QgsLineString ls( QVector<QgsPointXY> { QgsPointXY( textOriginXPixels, textOriginYPixels ),
|
||||
QgsPointXY( textOriginXPixels + widthPixels, textOriginYPixels ),
|
||||
QgsPointXY( textOriginXPixels + widthPixels, textOriginYPixels + heightPixels ),
|
||||
QgsPointXY( textOriginXPixels, textOriginYPixels + heightPixels ),
|
||||
QgsPointXY( textOriginXPixels, textOriginYPixels )
|
||||
} );
|
||||
|
||||
QgsGeometry g( new QgsPolygon( ls.clone() ) );
|
||||
g.transform( context.renderContext().mapToPixel().transform().inverted() );
|
||||
g.transform( context.renderContext().coordinateTransform(), Qgis::TransformDirection::Reverse );
|
||||
return new QgsAnnotationItemEditOperationTransientResults( g );
|
||||
}
|
||||
else
|
||||
{
|
||||
const QgsRectangle currentBounds = context.currentItemBounds();
|
||||
const QgsRectangle newBounds = QgsRectangle::fromCenterAndSize( mBounds.center() + QgsVector( moveOperation->translationX(), moveOperation->translationY() ),
|
||||
currentBounds.width(), currentBounds.height() );
|
||||
return new QgsAnnotationItemEditOperationTransientResults( QgsGeometry::fromRect( newBounds ) );
|
||||
}
|
||||
}
|
||||
|
||||
case Qgis::AnnotationPlacementMode::RelativeToMapFrame:
|
||||
{
|
||||
const QgsRectangle currentBounds = context.currentItemBounds();
|
||||
const QgsRectangle newBounds = QgsRectangle::fromCenterAndSize( currentBounds.center() + QgsVector( moveOperation->translationX(), moveOperation->translationY() ),
|
||||
currentBounds.width(), currentBounds.height() );
|
||||
return new QgsAnnotationItemEditOperationTransientResults( QgsGeometry::fromRect( newBounds ) );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case QgsAbstractAnnotationItemEditOperation::Type::DeleteNode:
|
||||
case QgsAbstractAnnotationItemEditOperation::Type::AddNode:
|
||||
break;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QgsAnnotationPictureItem *QgsAnnotationPictureItem::create()
|
||||
{
|
||||
return new QgsAnnotationPictureItem( Qgis::PictureFormat::Unknown, QString(), QgsRectangle() );
|
||||
@ -610,205 +122,23 @@ QgsAnnotationPictureItem *QgsAnnotationPictureItem::create()
|
||||
bool QgsAnnotationPictureItem::readXml( const QDomElement &element, const QgsReadWriteContext &context )
|
||||
{
|
||||
mLockAspectRatio = element.attribute( QStringLiteral( "lockAspect" ), QStringLiteral( "1" ) ).toInt();
|
||||
mBounds.setXMinimum( element.attribute( QStringLiteral( "xMin" ) ).toDouble() );
|
||||
mBounds.setXMaximum( element.attribute( QStringLiteral( "xMax" ) ).toDouble() );
|
||||
mBounds.setYMinimum( element.attribute( QStringLiteral( "yMin" ) ).toDouble() );
|
||||
mBounds.setYMaximum( element.attribute( QStringLiteral( "yMax" ) ).toDouble() );
|
||||
|
||||
const Qgis::PictureFormat format = qgsEnumKeyToValue( element.attribute( QStringLiteral( "format" ) ), Qgis::PictureFormat::Unknown );
|
||||
setPath( format, element.attribute( QStringLiteral( "path" ) ) );
|
||||
|
||||
mPlacementMode = qgsEnumKeyToValue( element.attribute( QStringLiteral( "sizeMode" ) ), Qgis::AnnotationPlacementMode::SpatialBounds );
|
||||
|
||||
mFixedSize = QSizeF(
|
||||
element.attribute( QStringLiteral( "fixedWidth" ) ).toDouble(),
|
||||
element.attribute( QStringLiteral( "fixedHeight" ) ).toDouble()
|
||||
);
|
||||
mFixedSizeUnit = QgsUnitTypes::decodeRenderUnit( element.attribute( QStringLiteral( "fixedSizeUnit" ) ) );
|
||||
|
||||
mDrawBackground = element.attribute( QStringLiteral( "backgroundEnabled" ), QStringLiteral( "0" ) ).toInt();
|
||||
const QDomElement backgroundSymbolElem = element.firstChildElement( QStringLiteral( "backgroundSymbol" ) ).firstChildElement();
|
||||
if ( !backgroundSymbolElem.isNull() )
|
||||
{
|
||||
setBackgroundSymbol( QgsSymbolLayerUtils::loadSymbol< QgsFillSymbol >( backgroundSymbolElem, context ) );
|
||||
}
|
||||
|
||||
mDrawFrame = element.attribute( QStringLiteral( "frameEnabled" ), QStringLiteral( "0" ) ).toInt();
|
||||
const QDomElement frameSymbolElem = element.firstChildElement( QStringLiteral( "frameSymbol" ) ).firstChildElement();
|
||||
if ( !frameSymbolElem.isNull() )
|
||||
{
|
||||
setFrameSymbol( QgsSymbolLayerUtils::loadSymbol< QgsFillSymbol >( frameSymbolElem, context ) );
|
||||
}
|
||||
|
||||
readCommonProperties( element, context );
|
||||
return true;
|
||||
}
|
||||
|
||||
QgsAnnotationPictureItem *QgsAnnotationPictureItem::clone() const
|
||||
{
|
||||
std::unique_ptr< QgsAnnotationPictureItem > item = std::make_unique< QgsAnnotationPictureItem >( mFormat, mPath, mBounds );
|
||||
std::unique_ptr< QgsAnnotationPictureItem > item = std::make_unique< QgsAnnotationPictureItem >( mFormat, mPath, bounds() );
|
||||
item->setLockAspectRatio( mLockAspectRatio );
|
||||
item->setPlacementMode( mPlacementMode );
|
||||
item->setFixedSize( mFixedSize );
|
||||
item->setFixedSizeUnit( mFixedSizeUnit );
|
||||
|
||||
item->setBackgroundEnabled( mDrawBackground );
|
||||
if ( mBackgroundSymbol )
|
||||
item->setBackgroundSymbol( mBackgroundSymbol->clone() );
|
||||
|
||||
item->setFrameEnabled( mDrawFrame );
|
||||
if ( mFrameSymbol )
|
||||
item->setFrameSymbol( mFrameSymbol->clone() );
|
||||
|
||||
item->copyCommonProperties( this );
|
||||
return item.release();
|
||||
}
|
||||
|
||||
QgsRectangle QgsAnnotationPictureItem::boundingBox() const
|
||||
{
|
||||
QgsRectangle bounds;
|
||||
switch ( mPlacementMode )
|
||||
{
|
||||
case Qgis::AnnotationPlacementMode::SpatialBounds:
|
||||
{
|
||||
bounds = mBounds;
|
||||
if ( callout() && !calloutAnchor().isEmpty() )
|
||||
{
|
||||
QgsGeometry anchor = calloutAnchor();
|
||||
bounds.combineExtentWith( anchor.boundingBox() );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Qgis::AnnotationPlacementMode::FixedSize:
|
||||
if ( callout() && !calloutAnchor().isEmpty() )
|
||||
{
|
||||
bounds = calloutAnchor().boundingBox();
|
||||
}
|
||||
else
|
||||
{
|
||||
bounds = QgsRectangle( mBounds.center(), mBounds.center() );
|
||||
}
|
||||
break;
|
||||
|
||||
case Qgis::AnnotationPlacementMode::RelativeToMapFrame:
|
||||
bounds = mBounds;
|
||||
break;
|
||||
}
|
||||
|
||||
return bounds;
|
||||
}
|
||||
|
||||
QgsRectangle QgsAnnotationPictureItem::boundingBox( QgsRenderContext &context ) const
|
||||
{
|
||||
switch ( mPlacementMode )
|
||||
{
|
||||
case Qgis::AnnotationPlacementMode::SpatialBounds:
|
||||
return QgsAnnotationPictureItem::boundingBox();
|
||||
|
||||
case Qgis::AnnotationPlacementMode::FixedSize:
|
||||
{
|
||||
const double widthPixels = context.convertToPainterUnits( mFixedSize.width(), mFixedSizeUnit );
|
||||
const double heightPixels = context.convertToPainterUnits( mFixedSize.height(), mFixedSizeUnit );
|
||||
|
||||
QRectF boundsInPixels;
|
||||
if ( callout() && !calloutAnchor().isEmpty() )
|
||||
{
|
||||
QgsGeometry anchor = calloutAnchor();
|
||||
|
||||
const double calloutOffsetWidthPixels = context.convertToPainterUnits( offsetFromCallout().width(), offsetFromCalloutUnit() );
|
||||
const double calloutOffsetHeightPixels = context.convertToPainterUnits( offsetFromCallout().height(), offsetFromCalloutUnit() );
|
||||
|
||||
QPointF anchorPoint = anchor.asQPointF();
|
||||
if ( context.coordinateTransform().isValid() )
|
||||
{
|
||||
double x = anchorPoint.x();
|
||||
double y = anchorPoint.y();
|
||||
double z = 0.0;
|
||||
context.coordinateTransform().transformInPlace( x, y, z );
|
||||
anchorPoint = QPointF( x, y );
|
||||
}
|
||||
|
||||
context.mapToPixel().transformInPlace( anchorPoint.rx(), anchorPoint.ry() );
|
||||
|
||||
QgsRectangle textRect( anchorPoint.x() + calloutOffsetWidthPixels,
|
||||
anchorPoint.y() + calloutOffsetHeightPixels,
|
||||
anchorPoint.x() + calloutOffsetWidthPixels + widthPixels,
|
||||
anchorPoint.y() + calloutOffsetHeightPixels + heightPixels );
|
||||
QgsRectangle anchorRect( anchorPoint.x(), anchorPoint.y(), anchorPoint.x(), anchorPoint.y() );
|
||||
anchorRect.combineExtentWith( textRect );
|
||||
|
||||
boundsInPixels = anchorRect.toRectF();
|
||||
}
|
||||
else
|
||||
{
|
||||
QPointF center = mBounds.center().toQPointF();
|
||||
if ( context.coordinateTransform().isValid() )
|
||||
{
|
||||
double x = center.x();
|
||||
double y = center.y();
|
||||
double z = 0.0;
|
||||
context.coordinateTransform().transformInPlace( x, y, z );
|
||||
center = QPointF( x, y );
|
||||
}
|
||||
|
||||
context.mapToPixel().transformInPlace( center.rx(), center.ry() );
|
||||
boundsInPixels = QRectF( center.x() - widthPixels * 0.5,
|
||||
center.y() - heightPixels * 0.5,
|
||||
widthPixels, heightPixels );
|
||||
}
|
||||
const QgsPointXY topLeft = context.mapToPixel().toMapCoordinates( boundsInPixels.left(), boundsInPixels.top() );
|
||||
const QgsPointXY topRight = context.mapToPixel().toMapCoordinates( boundsInPixels.right(), boundsInPixels.top() );
|
||||
const QgsPointXY bottomLeft = context.mapToPixel().toMapCoordinates( boundsInPixels.left(), boundsInPixels.bottom() );
|
||||
const QgsPointXY bottomRight = context.mapToPixel().toMapCoordinates( boundsInPixels.right(), boundsInPixels.bottom() );
|
||||
|
||||
const QgsRectangle boundsMapUnits = QgsRectangle( topLeft.x(), bottomLeft.y(), bottomRight.x(), topRight.y() );
|
||||
QgsRectangle textRect = context.coordinateTransform().transformBoundingBox( boundsMapUnits, Qgis::TransformDirection::Reverse );
|
||||
return textRect;
|
||||
}
|
||||
|
||||
case Qgis::AnnotationPlacementMode::RelativeToMapFrame:
|
||||
{
|
||||
const double widthPixels = context.convertToPainterUnits( mFixedSize.width(), mFixedSizeUnit );
|
||||
const double heightPixels = context.convertToPainterUnits( mFixedSize.height(), mFixedSizeUnit );
|
||||
|
||||
QRectF boundsInPixels;
|
||||
|
||||
const double centerMapX = context.mapExtent().xMinimum() + mBounds.center().x() * context.mapExtent().width();
|
||||
const double centerMapY = context.mapExtent().yMaximum() - mBounds.center().y() * context.mapExtent().height();
|
||||
QPointF center( centerMapX, centerMapY );
|
||||
if ( context.coordinateTransform().isValid() )
|
||||
{
|
||||
double x = centerMapX;
|
||||
double y = centerMapY;
|
||||
double z = 0.0;
|
||||
context.coordinateTransform().transformInPlace( x, y, z );
|
||||
center = QPointF( x, y );
|
||||
}
|
||||
|
||||
context.mapToPixel().transformInPlace( center.rx(), center.ry() );
|
||||
boundsInPixels = QRectF( center.x() - widthPixels * 0.5,
|
||||
center.y() - heightPixels * 0.5,
|
||||
widthPixels, heightPixels );
|
||||
|
||||
const QgsPointXY topLeft = context.mapToPixel().toMapCoordinates( boundsInPixels.left(), boundsInPixels.top() );
|
||||
const QgsPointXY topRight = context.mapToPixel().toMapCoordinates( boundsInPixels.right(), boundsInPixels.top() );
|
||||
const QgsPointXY bottomLeft = context.mapToPixel().toMapCoordinates( boundsInPixels.left(), boundsInPixels.bottom() );
|
||||
const QgsPointXY bottomRight = context.mapToPixel().toMapCoordinates( boundsInPixels.right(), boundsInPixels.bottom() );
|
||||
|
||||
const QgsRectangle boundsMapUnits = QgsRectangle( topLeft.x(), bottomLeft.y(), bottomRight.x(), topRight.y() );
|
||||
QgsRectangle textRect = context.coordinateTransform().transformBoundingBox( boundsMapUnits, Qgis::TransformDirection::Reverse );
|
||||
return textRect;
|
||||
}
|
||||
}
|
||||
BUILTIN_UNREACHABLE
|
||||
}
|
||||
|
||||
void QgsAnnotationPictureItem::setBounds( const QgsRectangle &bounds )
|
||||
{
|
||||
mBounds = bounds;
|
||||
}
|
||||
|
||||
void QgsAnnotationPictureItem::setPath( Qgis::PictureFormat format, const QString &path )
|
||||
{
|
||||
mPath = path;
|
||||
@ -830,53 +160,3 @@ void QgsAnnotationPictureItem::setLockAspectRatio( bool locked )
|
||||
{
|
||||
mLockAspectRatio = locked;
|
||||
}
|
||||
|
||||
const QgsFillSymbol *QgsAnnotationPictureItem::backgroundSymbol() const
|
||||
{
|
||||
return mBackgroundSymbol.get();
|
||||
}
|
||||
|
||||
void QgsAnnotationPictureItem::setBackgroundSymbol( QgsFillSymbol *symbol )
|
||||
{
|
||||
mBackgroundSymbol.reset( symbol );
|
||||
}
|
||||
|
||||
const QgsFillSymbol *QgsAnnotationPictureItem::frameSymbol() const
|
||||
{
|
||||
return mFrameSymbol.get();
|
||||
}
|
||||
|
||||
void QgsAnnotationPictureItem::setFrameSymbol( QgsFillSymbol *symbol )
|
||||
{
|
||||
mFrameSymbol.reset( symbol );
|
||||
}
|
||||
|
||||
QSizeF QgsAnnotationPictureItem::fixedSize() const
|
||||
{
|
||||
return mFixedSize;
|
||||
}
|
||||
|
||||
void QgsAnnotationPictureItem::setFixedSize( const QSizeF &size )
|
||||
{
|
||||
mFixedSize = size;
|
||||
}
|
||||
|
||||
Qgis::RenderUnit QgsAnnotationPictureItem::fixedSizeUnit() const
|
||||
{
|
||||
return mFixedSizeUnit;
|
||||
}
|
||||
|
||||
void QgsAnnotationPictureItem::setFixedSizeUnit( Qgis::RenderUnit unit )
|
||||
{
|
||||
mFixedSizeUnit = unit;
|
||||
}
|
||||
|
||||
Qgis::AnnotationPlacementMode QgsAnnotationPictureItem::placementMode() const
|
||||
{
|
||||
return mPlacementMode;
|
||||
}
|
||||
|
||||
void QgsAnnotationPictureItem::setPlacementMode( Qgis::AnnotationPlacementMode mode )
|
||||
{
|
||||
mPlacementMode = mode;
|
||||
}
|
||||
|
@ -20,7 +20,7 @@
|
||||
|
||||
#include "qgis_core.h"
|
||||
#include "qgis_sip.h"
|
||||
#include "qgsannotationitem.h"
|
||||
#include "qgsannotationrectitem.h"
|
||||
|
||||
/**
|
||||
* \ingroup core
|
||||
@ -28,7 +28,7 @@
|
||||
*
|
||||
* \since QGIS 3.40
|
||||
*/
|
||||
class CORE_EXPORT QgsAnnotationPictureItem : public QgsAnnotationItem
|
||||
class CORE_EXPORT QgsAnnotationPictureItem : public QgsAnnotationRectItem
|
||||
{
|
||||
public:
|
||||
|
||||
@ -40,47 +40,15 @@ class CORE_EXPORT QgsAnnotationPictureItem : public QgsAnnotationItem
|
||||
~QgsAnnotationPictureItem() override;
|
||||
|
||||
QString type() const override;
|
||||
Qgis::AnnotationItemFlags flags() const override;
|
||||
void render( QgsRenderContext &context, QgsFeedback *feedback ) override;
|
||||
bool writeXml( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const override;
|
||||
QList< QgsAnnotationItemNode > nodesV2( const QgsAnnotationItemEditContext &context ) const override;
|
||||
Qgis::AnnotationItemEditOperationResult applyEditV2( QgsAbstractAnnotationItemEditOperation *operation, const QgsAnnotationItemEditContext &context ) override;
|
||||
QgsAnnotationItemEditOperationTransientResults *transientEditResultsV2( QgsAbstractAnnotationItemEditOperation *operation, const QgsAnnotationItemEditContext &context ) override SIP_FACTORY;
|
||||
bool readXml( const QDomElement &element, const QgsReadWriteContext &context ) override;
|
||||
QgsAnnotationPictureItem *clone() const override SIP_FACTORY;
|
||||
|
||||
/**
|
||||
* Creates a new polygon annotation item.
|
||||
*/
|
||||
static QgsAnnotationPictureItem *create() SIP_FACTORY;
|
||||
|
||||
bool readXml( const QDomElement &element, const QgsReadWriteContext &context ) override;
|
||||
QgsAnnotationPictureItem *clone() const override SIP_FACTORY;
|
||||
QgsRectangle boundingBox() const override;
|
||||
QgsRectangle boundingBox( QgsRenderContext &context ) const override;
|
||||
|
||||
/**
|
||||
* Returns the bounds of the picture.
|
||||
*
|
||||
* The coordinate reference system for the bounds will be the parent layer's QgsAnnotationLayer::crs().
|
||||
*
|
||||
* When the placementMode() is Qgis::AnnotationPlacementMode::FixedSize then the picture will be placed
|
||||
* at the center of the bounds.
|
||||
*
|
||||
* \see setBounds()
|
||||
*/
|
||||
QgsRectangle bounds() const { return mBounds; }
|
||||
|
||||
/**
|
||||
* Sets the \a bounds of the picture.
|
||||
*
|
||||
* The coordinate reference system for the bounds will be the parent layer's QgsAnnotationLayer::crs().
|
||||
*
|
||||
* When the placementMode() is Qgis::AnnotationPlacementMode::FixedSize then the picture will be placed
|
||||
* at the center of the bounds.
|
||||
*
|
||||
* \see bounds()
|
||||
*/
|
||||
void setBounds( const QgsRectangle &bounds );
|
||||
|
||||
/**
|
||||
* Returns the path of the image used to render the item.
|
||||
*
|
||||
@ -101,56 +69,6 @@ class CORE_EXPORT QgsAnnotationPictureItem : public QgsAnnotationItem
|
||||
*/
|
||||
void setPath( Qgis::PictureFormat format, const QString &path );
|
||||
|
||||
/**
|
||||
* Returns the placement mode for the picture.
|
||||
*
|
||||
* \see setPlacementMode()
|
||||
*/
|
||||
Qgis::AnnotationPlacementMode placementMode() const;
|
||||
|
||||
/**
|
||||
* Sets the placement \a mode for the picture.
|
||||
*
|
||||
* \see placementMode()
|
||||
*/
|
||||
void setPlacementMode( Qgis::AnnotationPlacementMode mode );
|
||||
|
||||
/**
|
||||
* Returns the fixed size to use for the picture, when the placementMode() is Qgis::AnnotationPlacementMode::FixedSize.
|
||||
*
|
||||
* Units are retrieved via fixedSizeUnit()
|
||||
*
|
||||
* \see setFixedSize()
|
||||
* \see fixedSizeUnit()
|
||||
*/
|
||||
QSizeF fixedSize() const;
|
||||
|
||||
/**
|
||||
* Sets the fixed \a size to use for the picture, when the placementMode() is Qgis::AnnotationPlacementMode::FixedSize.
|
||||
*
|
||||
* Units are set via setFixedSizeUnit()
|
||||
*
|
||||
* \see fixedSize()
|
||||
* \see setFixedSizeUnit()
|
||||
*/
|
||||
void setFixedSize( const QSizeF &size );
|
||||
|
||||
/**
|
||||
* Returns the units to use for fixed picture sizes, when the placementMode() is Qgis::AnnotationPlacementMode::FixedSize.
|
||||
*
|
||||
* \see setFixedSizeUnit()
|
||||
* \see fixedSize()
|
||||
*/
|
||||
Qgis::RenderUnit fixedSizeUnit() const;
|
||||
|
||||
/**
|
||||
* Sets the \a unit to use for fixed picture sizes, when the placementMode() is Qgis::AnnotationPlacementMode::FixedSize.
|
||||
*
|
||||
* \see fixedSizeUnit()
|
||||
* \see setFixedSize()
|
||||
*/
|
||||
void setFixedSizeUnit( Qgis::RenderUnit unit );
|
||||
|
||||
/**
|
||||
* Returns TRUE if the aspect ratio of the picture will be retained.
|
||||
*
|
||||
@ -165,89 +83,15 @@ class CORE_EXPORT QgsAnnotationPictureItem : public QgsAnnotationItem
|
||||
*/
|
||||
void setLockAspectRatio( bool locked );
|
||||
|
||||
/**
|
||||
* Returns TRUE if the item's background should be rendered.
|
||||
*
|
||||
* \see setBackgroundEnabled()
|
||||
* \see backgroundSymbol()
|
||||
*/
|
||||
bool backgroundEnabled() const { return mDrawBackground; }
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Sets whether the item's background should be rendered.
|
||||
*
|
||||
* \see backgroundEnabled()
|
||||
* \see setBackgroundSymbol()
|
||||
*/
|
||||
void setBackgroundEnabled( bool enabled ) { mDrawBackground = enabled; }
|
||||
|
||||
/**
|
||||
* Returns the symbol used to render the item's background.
|
||||
*
|
||||
* \see backgroundEnabled()
|
||||
* \see setBackgroundSymbol()
|
||||
*/
|
||||
const QgsFillSymbol *backgroundSymbol() const;
|
||||
|
||||
/**
|
||||
* Sets the \a symbol used to render the item's background.
|
||||
*
|
||||
* The item takes ownership of the symbol.
|
||||
*
|
||||
* \see backgroundSymbol()
|
||||
* \see setBackgroundEnabled()
|
||||
*/
|
||||
void setBackgroundSymbol( QgsFillSymbol *symbol SIP_TRANSFER );
|
||||
|
||||
/**
|
||||
* Returns TRUE if the item's frame should be rendered.
|
||||
*
|
||||
* \see setFrameEnabled()
|
||||
* \see frameSymbol()
|
||||
*/
|
||||
bool frameEnabled() const { return mDrawFrame; }
|
||||
|
||||
/**
|
||||
* Sets whether the item's frame should be rendered.
|
||||
*
|
||||
* \see frameEnabled()
|
||||
* \see setFrameSymbol()
|
||||
*/
|
||||
void setFrameEnabled( bool enabled ) { mDrawFrame = enabled; }
|
||||
|
||||
/**
|
||||
* Returns the symbol used to render the item's frame.
|
||||
*
|
||||
* \see frameEnabled()
|
||||
* \see setFrameSymbol()
|
||||
*/
|
||||
const QgsFillSymbol *frameSymbol() const;
|
||||
|
||||
/**
|
||||
* Sets the \a symbol used to render the item's frame.
|
||||
*
|
||||
* The item takes ownership of the symbol.
|
||||
*
|
||||
* \see frameSymbol()
|
||||
* \see setBackgroundEnabled()
|
||||
*/
|
||||
void setFrameSymbol( QgsFillSymbol *symbol SIP_TRANSFER );
|
||||
void renderInBounds( QgsRenderContext &context, const QRectF &painterBounds, QgsFeedback *feedback ) override;
|
||||
|
||||
private:
|
||||
|
||||
QString mPath;
|
||||
Qgis::PictureFormat mFormat = Qgis::PictureFormat::Unknown;
|
||||
Qgis::AnnotationPlacementMode mPlacementMode = Qgis::AnnotationPlacementMode::SpatialBounds;
|
||||
QgsRectangle mBounds;
|
||||
|
||||
QSizeF mFixedSize;
|
||||
Qgis::RenderUnit mFixedSizeUnit = Qgis::RenderUnit::Millimeters;
|
||||
|
||||
bool mLockAspectRatio = true;
|
||||
bool mDrawBackground = false;
|
||||
std::unique_ptr< QgsFillSymbol > mBackgroundSymbol;
|
||||
bool mDrawFrame = false;
|
||||
std::unique_ptr< QgsFillSymbol > mFrameSymbol;
|
||||
|
||||
#ifdef SIP_RUN
|
||||
QgsAnnotationPictureItem( const QgsAnnotationPictureItem &other );
|
||||
|
@ -18,28 +18,18 @@
|
||||
#include "qgsannotationrectangletextitem.h"
|
||||
#include "qgsgeometry.h"
|
||||
#include "qgsrendercontext.h"
|
||||
#include "qgsannotationitemnode.h"
|
||||
#include "qgsannotationitemeditoperation.h"
|
||||
#include "qgsfillsymbol.h"
|
||||
#include "qgssymbollayerutils.h"
|
||||
#include "qgsfillsymbollayer.h"
|
||||
#include "qgslinesymbollayer.h"
|
||||
#include "qgstextrenderer.h"
|
||||
#include "qgsunittypes.h"
|
||||
#include "qgsapplication.h"
|
||||
#include "qgscalloutsregistry.h"
|
||||
#include "qgspolygon.h"
|
||||
#include "qgslinestring.h"
|
||||
|
||||
QgsAnnotationRectangleTextItem::QgsAnnotationRectangleTextItem( const QString &text, const QgsRectangle &bounds )
|
||||
: QgsAnnotationItem()
|
||||
, mBounds( bounds )
|
||||
: QgsAnnotationRectItem( bounds )
|
||||
, mText( text )
|
||||
{
|
||||
mBackgroundSymbol = std::make_unique< QgsFillSymbol >( QgsSymbolLayerList { new QgsSimpleFillSymbolLayer( QColor( 255, 255, 255 ), Qt::BrushStyle::SolidPattern, QColor( 0, 0, 0 ), Qt::PenStyle::NoPen ) } );
|
||||
QgsSimpleLineSymbolLayer *borderSymbol = new QgsSimpleLineSymbolLayer( QColor( 0, 0, 0 ) );
|
||||
borderSymbol->setPenJoinStyle( Qt::MiterJoin );
|
||||
mFrameSymbol = std::make_unique< QgsFillSymbol >( QgsSymbolLayerList { borderSymbol } );
|
||||
setBackgroundEnabled( true );
|
||||
setFrameEnabled( true );
|
||||
}
|
||||
|
||||
QgsAnnotationRectangleTextItem::~QgsAnnotationRectangleTextItem() = default;
|
||||
@ -49,99 +39,8 @@ QString QgsAnnotationRectangleTextItem::type() const
|
||||
return QStringLiteral( "recttext" );
|
||||
}
|
||||
|
||||
void QgsAnnotationRectangleTextItem::render( QgsRenderContext &context, QgsFeedback *feedback )
|
||||
void QgsAnnotationRectangleTextItem::renderInBounds( QgsRenderContext &context, const QRectF &painterBounds, QgsFeedback * )
|
||||
{
|
||||
QgsRectangle bounds = mBounds;
|
||||
if ( mPlacementMode != Qgis::AnnotationPlacementMode::RelativeToMapFrame && context.coordinateTransform().isValid() )
|
||||
{
|
||||
try
|
||||
{
|
||||
bounds = context.coordinateTransform().transformBoundingBox( mBounds );
|
||||
}
|
||||
catch ( QgsCsException & )
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
QRectF painterBounds;
|
||||
switch ( mPlacementMode )
|
||||
{
|
||||
case Qgis::AnnotationPlacementMode::SpatialBounds:
|
||||
painterBounds = context.mapToPixel().transformBounds( bounds.toRectF() );
|
||||
break;
|
||||
|
||||
case Qgis::AnnotationPlacementMode::FixedSize:
|
||||
{
|
||||
const double widthPixels = context.convertToPainterUnits( mFixedSize.width(), mFixedSizeUnit );
|
||||
const double heightPixels = context.convertToPainterUnits( mFixedSize.height(), mFixedSizeUnit );
|
||||
|
||||
if ( callout() && !calloutAnchor().isEmpty() )
|
||||
{
|
||||
QgsGeometry anchor = calloutAnchor();
|
||||
|
||||
const double calloutOffsetWidthPixels = context.convertToPainterUnits( offsetFromCallout().width(), offsetFromCalloutUnit() );
|
||||
const double calloutOffsetHeightPixels = context.convertToPainterUnits( offsetFromCallout().height(), offsetFromCalloutUnit() );
|
||||
|
||||
QPointF anchorPoint = anchor.asQPointF();
|
||||
if ( context.coordinateTransform().isValid() )
|
||||
{
|
||||
double x = anchorPoint.x();
|
||||
double y = anchorPoint.y();
|
||||
double z = 0.0;
|
||||
context.coordinateTransform().transformInPlace( x, y, z );
|
||||
anchorPoint = QPointF( x, y );
|
||||
}
|
||||
|
||||
context.mapToPixel().transformInPlace( anchorPoint.rx(), anchorPoint.ry() );
|
||||
|
||||
painterBounds = QRectF( anchorPoint.x() + calloutOffsetWidthPixels,
|
||||
anchorPoint.y() + calloutOffsetHeightPixels, widthPixels, heightPixels );
|
||||
}
|
||||
else
|
||||
{
|
||||
QPointF center = bounds.center().toQPointF();
|
||||
|
||||
context.mapToPixel().transformInPlace( center.rx(), center.ry() );
|
||||
painterBounds = QRectF( center.x() - widthPixels * 0.5,
|
||||
center.y() - heightPixels * 0.5,
|
||||
widthPixels, heightPixels );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Qgis::AnnotationPlacementMode::RelativeToMapFrame:
|
||||
{
|
||||
const double widthPixels = context.convertToPainterUnits( mFixedSize.width(), mFixedSizeUnit );
|
||||
const double heightPixels = context.convertToPainterUnits( mFixedSize.height(), mFixedSizeUnit );
|
||||
|
||||
QPointF center = bounds.center().toQPointF();
|
||||
center.rx() *= context.outputSize().width();
|
||||
center.ry() *= context.outputSize().height();
|
||||
|
||||
painterBounds = QRectF( center.x() - widthPixels * 0.5,
|
||||
center.y() - heightPixels * 0.5,
|
||||
widthPixels, heightPixels );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( painterBounds.width() < 1 || painterBounds.height() < 1 )
|
||||
return;
|
||||
|
||||
if ( mDrawBackground && mBackgroundSymbol )
|
||||
{
|
||||
mBackgroundSymbol->startRender( context );
|
||||
mBackgroundSymbol->renderPolygon( painterBounds, nullptr, nullptr, context );
|
||||
mBackgroundSymbol->stopRender( context );
|
||||
}
|
||||
|
||||
if ( mPlacementMode != Qgis::AnnotationPlacementMode::RelativeToMapFrame && callout() )
|
||||
{
|
||||
QgsCallout::QgsCalloutContext calloutContext;
|
||||
renderCallout( context, painterBounds, 0, calloutContext, feedback );
|
||||
}
|
||||
|
||||
const double marginLeft = context.convertToPainterUnits( mMargins.left(), mMarginUnit );
|
||||
const double marginTop = context.convertToPainterUnits( mMargins.top(), mMarginUnit );
|
||||
const double marginRight = context.convertToPainterUnits( mMargins.right(), mMarginUnit );
|
||||
@ -163,13 +62,6 @@ void QgsAnnotationRectangleTextItem::render( QgsRenderContext &context, QgsFeedb
|
||||
QgsTextRenderer::convertQtVAlignment( mAlignment ),
|
||||
Qgis::TextRendererFlag::WrapLines );
|
||||
context.setFlag( Qgis::RenderContextFlag::ApplyScalingWorkaroundForTextRendering, prevWorkaroundFlag );
|
||||
|
||||
if ( mDrawFrame && mFrameSymbol )
|
||||
{
|
||||
mFrameSymbol->startRender( context );
|
||||
mFrameSymbol->renderPolygon( painterBounds, nullptr, nullptr, context );
|
||||
mFrameSymbol->stopRender( context );
|
||||
}
|
||||
}
|
||||
|
||||
bool QgsAnnotationRectangleTextItem::writeXml( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const
|
||||
@ -184,365 +76,10 @@ bool QgsAnnotationRectangleTextItem::writeXml( QDomElement &element, QDomDocumen
|
||||
element.setAttribute( QStringLiteral( "margins" ), mMargins.toString() );
|
||||
element.setAttribute( QStringLiteral( "marginUnit" ), QgsUnitTypes::encodeUnit( mMarginUnit ) );
|
||||
|
||||
element.setAttribute( QStringLiteral( "xMin" ), qgsDoubleToString( mBounds.xMinimum() ) );
|
||||
element.setAttribute( QStringLiteral( "xMax" ), qgsDoubleToString( mBounds.xMaximum() ) );
|
||||
element.setAttribute( QStringLiteral( "yMin" ), qgsDoubleToString( mBounds.yMinimum() ) );
|
||||
element.setAttribute( QStringLiteral( "yMax" ), qgsDoubleToString( mBounds.yMaximum() ) );
|
||||
|
||||
element.setAttribute( QStringLiteral( "sizeMode" ), qgsEnumValueToKey( mPlacementMode ) );
|
||||
element.setAttribute( QStringLiteral( "fixedWidth" ), qgsDoubleToString( mFixedSize.width() ) );
|
||||
element.setAttribute( QStringLiteral( "fixedHeight" ), qgsDoubleToString( mFixedSize.height() ) );
|
||||
element.setAttribute( QStringLiteral( "fixedSizeUnit" ), QgsUnitTypes::encodeUnit( mFixedSizeUnit ) );
|
||||
|
||||
element.setAttribute( QStringLiteral( "backgroundEnabled" ), mDrawBackground ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
|
||||
if ( mBackgroundSymbol )
|
||||
{
|
||||
QDomElement backgroundElement = document.createElement( QStringLiteral( "backgroundSymbol" ) );
|
||||
backgroundElement.appendChild( QgsSymbolLayerUtils::saveSymbol( QStringLiteral( "backgroundSymbol" ), mBackgroundSymbol.get(), document, context ) );
|
||||
element.appendChild( backgroundElement );
|
||||
}
|
||||
|
||||
element.setAttribute( QStringLiteral( "frameEnabled" ), mDrawFrame ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
|
||||
if ( mFrameSymbol )
|
||||
{
|
||||
QDomElement frameElement = document.createElement( QStringLiteral( "frameSymbol" ) );
|
||||
frameElement.appendChild( QgsSymbolLayerUtils::saveSymbol( QStringLiteral( "frameSymbol" ), mFrameSymbol.get(), document, context ) );
|
||||
element.appendChild( frameElement );
|
||||
}
|
||||
|
||||
writeCommonProperties( element, document, context );
|
||||
return true;
|
||||
}
|
||||
|
||||
QList<QgsAnnotationItemNode> QgsAnnotationRectangleTextItem::nodesV2( const QgsAnnotationItemEditContext &context ) const
|
||||
{
|
||||
QList<QgsAnnotationItemNode> res;
|
||||
switch ( mPlacementMode )
|
||||
{
|
||||
case Qgis::AnnotationPlacementMode::SpatialBounds:
|
||||
{
|
||||
res =
|
||||
{
|
||||
QgsAnnotationItemNode( QgsVertexId( 0, 0, 0 ), QgsPointXY( mBounds.xMinimum(), mBounds.yMinimum() ), Qgis::AnnotationItemNodeType::VertexHandle ),
|
||||
QgsAnnotationItemNode( QgsVertexId( 0, 0, 1 ), QgsPointXY( mBounds.xMaximum(), mBounds.yMinimum() ), Qgis::AnnotationItemNodeType::VertexHandle ),
|
||||
QgsAnnotationItemNode( QgsVertexId( 0, 0, 2 ), QgsPointXY( mBounds.xMaximum(), mBounds.yMaximum() ), Qgis::AnnotationItemNodeType::VertexHandle ),
|
||||
QgsAnnotationItemNode( QgsVertexId( 0, 0, 3 ), QgsPointXY( mBounds.xMinimum(), mBounds.yMaximum() ), Qgis::AnnotationItemNodeType::VertexHandle ),
|
||||
};
|
||||
|
||||
QgsPointXY calloutNodePoint;
|
||||
if ( !calloutAnchor().isEmpty() )
|
||||
{
|
||||
calloutNodePoint = calloutAnchor().asPoint();
|
||||
}
|
||||
else
|
||||
{
|
||||
calloutNodePoint = mBounds.center();
|
||||
}
|
||||
res.append( QgsAnnotationItemNode( QgsVertexId( 1, 0, 0 ), calloutNodePoint, Qgis::AnnotationItemNodeType::CalloutHandle ) );
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
case Qgis::AnnotationPlacementMode::FixedSize:
|
||||
{
|
||||
res =
|
||||
{
|
||||
QgsAnnotationItemNode( QgsVertexId( 0, 0, 0 ), mBounds.center(), Qgis::AnnotationItemNodeType::VertexHandle )
|
||||
};
|
||||
|
||||
QgsPointXY calloutNodePoint;
|
||||
if ( !calloutAnchor().isEmpty() )
|
||||
{
|
||||
calloutNodePoint = calloutAnchor().asPoint();
|
||||
}
|
||||
else
|
||||
{
|
||||
calloutNodePoint = QgsPointXY( context.currentItemBounds().xMinimum(), context.currentItemBounds().yMinimum() );
|
||||
}
|
||||
res.append( QgsAnnotationItemNode( QgsVertexId( 1, 0, 0 ), calloutNodePoint, Qgis::AnnotationItemNodeType::CalloutHandle ) );
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
case Qgis::AnnotationPlacementMode::RelativeToMapFrame:
|
||||
{
|
||||
return
|
||||
{
|
||||
QgsAnnotationItemNode( QgsVertexId( 0, 0, 0 ),
|
||||
context.currentItemBounds().center(), Qgis::AnnotationItemNodeType::VertexHandle )
|
||||
};
|
||||
}
|
||||
}
|
||||
BUILTIN_UNREACHABLE
|
||||
}
|
||||
|
||||
Qgis::AnnotationItemEditOperationResult QgsAnnotationRectangleTextItem::applyEditV2( QgsAbstractAnnotationItemEditOperation *operation, const QgsAnnotationItemEditContext &context )
|
||||
{
|
||||
switch ( operation->type() )
|
||||
{
|
||||
case QgsAbstractAnnotationItemEditOperation::Type::MoveNode:
|
||||
{
|
||||
QgsAnnotationItemEditOperationMoveNode *moveOperation = dynamic_cast< QgsAnnotationItemEditOperationMoveNode * >( operation );
|
||||
if ( moveOperation->nodeId().part == 0 )
|
||||
{
|
||||
switch ( mPlacementMode )
|
||||
{
|
||||
case Qgis::AnnotationPlacementMode::SpatialBounds:
|
||||
{
|
||||
switch ( moveOperation->nodeId().vertex )
|
||||
{
|
||||
case 0:
|
||||
mBounds = QgsRectangle( moveOperation->after().x(),
|
||||
moveOperation->after().y(),
|
||||
mBounds.xMaximum(),
|
||||
mBounds.yMaximum() );
|
||||
break;
|
||||
case 1:
|
||||
mBounds = QgsRectangle( mBounds.xMinimum(),
|
||||
moveOperation->after().y(),
|
||||
moveOperation->after().x(),
|
||||
mBounds.yMaximum() );
|
||||
break;
|
||||
case 2:
|
||||
mBounds = QgsRectangle( mBounds.xMinimum(),
|
||||
mBounds.yMinimum(),
|
||||
moveOperation->after().x(),
|
||||
moveOperation->after().y() );
|
||||
break;
|
||||
case 3:
|
||||
mBounds = QgsRectangle( moveOperation->after().x(),
|
||||
mBounds.yMinimum(),
|
||||
mBounds.xMaximum(),
|
||||
moveOperation->after().y() );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return Qgis::AnnotationItemEditOperationResult::Success;
|
||||
}
|
||||
|
||||
case Qgis::AnnotationPlacementMode::FixedSize:
|
||||
{
|
||||
mBounds = QgsRectangle::fromCenterAndSize( moveOperation->after(),
|
||||
mBounds.width(),
|
||||
mBounds.height() );
|
||||
return Qgis::AnnotationItemEditOperationResult::Success;
|
||||
}
|
||||
|
||||
case Qgis::AnnotationPlacementMode::RelativeToMapFrame:
|
||||
{
|
||||
const double deltaX = moveOperation->translationXPixels() / context.renderContext().outputSize().width();
|
||||
const double deltaY = moveOperation->translationYPixels() / context.renderContext().outputSize().height();
|
||||
mBounds = QgsRectangle::fromCenterAndSize( QgsPointXY( mBounds.center().x() + deltaX, mBounds.center().y() + deltaY ),
|
||||
mBounds.width(), mBounds.height() );
|
||||
return Qgis::AnnotationItemEditOperationResult::Success;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( moveOperation->nodeId().part == 1 )
|
||||
{
|
||||
setCalloutAnchor( QgsGeometry::fromPoint( moveOperation->after() ) );
|
||||
if ( !callout() )
|
||||
{
|
||||
setCallout( QgsApplication::calloutRegistry()->defaultCallout() );
|
||||
}
|
||||
return Qgis::AnnotationItemEditOperationResult::Success;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case QgsAbstractAnnotationItemEditOperation::Type::TranslateItem:
|
||||
{
|
||||
QgsAnnotationItemEditOperationTranslateItem *moveOperation = qgis::down_cast< QgsAnnotationItemEditOperationTranslateItem * >( operation );
|
||||
switch ( mPlacementMode )
|
||||
{
|
||||
|
||||
case Qgis::AnnotationPlacementMode::SpatialBounds:
|
||||
mBounds = QgsRectangle( mBounds.xMinimum() + moveOperation->translationX(),
|
||||
mBounds.yMinimum() + moveOperation->translationY(),
|
||||
mBounds.xMaximum() + moveOperation->translationX(),
|
||||
mBounds.yMaximum() + moveOperation->translationY() );
|
||||
break;
|
||||
|
||||
case Qgis::AnnotationPlacementMode::FixedSize:
|
||||
{
|
||||
if ( callout() && !calloutAnchor().isEmpty() )
|
||||
{
|
||||
const double xOffset = context.renderContext().convertFromPainterUnits( moveOperation->translationXPixels(), offsetFromCalloutUnit() );
|
||||
const double yOffset = context.renderContext().convertFromPainterUnits( moveOperation->translationYPixels(), offsetFromCalloutUnit() );
|
||||
setOffsetFromCallout( QSizeF( offsetFromCallout().width() + xOffset, offsetFromCallout().height() + yOffset ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
mBounds = QgsRectangle( mBounds.xMinimum() + moveOperation->translationX(),
|
||||
mBounds.yMinimum() + moveOperation->translationY(),
|
||||
mBounds.xMaximum() + moveOperation->translationX(),
|
||||
mBounds.yMaximum() + moveOperation->translationY() );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Qgis::AnnotationPlacementMode::RelativeToMapFrame:
|
||||
{
|
||||
const double deltaX = moveOperation->translationXPixels() / context.renderContext().outputSize().width();
|
||||
const double deltaY = moveOperation->translationYPixels() / context.renderContext().outputSize().height();
|
||||
mBounds = QgsRectangle::fromCenterAndSize( QgsPointXY( mBounds.center().x() + deltaX, mBounds.center().y() + deltaY ),
|
||||
mBounds.width(), mBounds.height() );
|
||||
break;
|
||||
}
|
||||
}
|
||||
return Qgis::AnnotationItemEditOperationResult::Success;
|
||||
}
|
||||
|
||||
case QgsAbstractAnnotationItemEditOperation::Type::DeleteNode:
|
||||
case QgsAbstractAnnotationItemEditOperation::Type::AddNode:
|
||||
break;
|
||||
}
|
||||
return Qgis::AnnotationItemEditOperationResult::Invalid;
|
||||
}
|
||||
|
||||
QgsAnnotationItemEditOperationTransientResults *QgsAnnotationRectangleTextItem::transientEditResultsV2( QgsAbstractAnnotationItemEditOperation *operation, const QgsAnnotationItemEditContext &context )
|
||||
{
|
||||
switch ( operation->type() )
|
||||
{
|
||||
case QgsAbstractAnnotationItemEditOperation::Type::MoveNode:
|
||||
{
|
||||
QgsAnnotationItemEditOperationMoveNode *moveOperation = dynamic_cast< QgsAnnotationItemEditOperationMoveNode * >( operation );
|
||||
if ( moveOperation->nodeId().part == 0 )
|
||||
{
|
||||
switch ( mPlacementMode )
|
||||
{
|
||||
case Qgis::AnnotationPlacementMode::SpatialBounds:
|
||||
{
|
||||
QgsRectangle modifiedBounds = mBounds;
|
||||
switch ( moveOperation->nodeId().vertex )
|
||||
{
|
||||
case 0:
|
||||
modifiedBounds.setXMinimum( moveOperation->after().x() );
|
||||
modifiedBounds.setYMinimum( moveOperation->after().y() );
|
||||
break;
|
||||
case 1:
|
||||
modifiedBounds.setXMaximum( moveOperation->after().x() );
|
||||
modifiedBounds.setYMinimum( moveOperation->after().y() );
|
||||
break;
|
||||
case 2:
|
||||
modifiedBounds.setXMaximum( moveOperation->after().x() );
|
||||
modifiedBounds.setYMaximum( moveOperation->after().y() );
|
||||
break;
|
||||
case 3:
|
||||
modifiedBounds.setXMinimum( moveOperation->after().x() );
|
||||
modifiedBounds.setYMaximum( moveOperation->after().y() );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return new QgsAnnotationItemEditOperationTransientResults( QgsGeometry::fromRect( modifiedBounds ) );
|
||||
}
|
||||
case Qgis::AnnotationPlacementMode::FixedSize:
|
||||
{
|
||||
const QgsRectangle currentBounds = context.currentItemBounds();
|
||||
const QgsRectangle newBounds = QgsRectangle::fromCenterAndSize( moveOperation->after(), currentBounds.width(), currentBounds.height() );
|
||||
return new QgsAnnotationItemEditOperationTransientResults( QgsGeometry::fromRect( newBounds ) );
|
||||
}
|
||||
case Qgis::AnnotationPlacementMode::RelativeToMapFrame:
|
||||
{
|
||||
const QgsRectangle currentBounds = context.currentItemBounds();
|
||||
const QgsRectangle newBounds = QgsRectangle::fromCenterAndSize( currentBounds.center() + ( moveOperation->after() - moveOperation->before() ),
|
||||
currentBounds.width(), currentBounds.height() );
|
||||
return new QgsAnnotationItemEditOperationTransientResults( QgsGeometry::fromRect( newBounds ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsAnnotationItemEditOperationMoveNode *moveOperation = dynamic_cast< QgsAnnotationItemEditOperationMoveNode * >( operation );
|
||||
return new QgsAnnotationItemEditOperationTransientResults( QgsGeometry( moveOperation->after().clone() ) );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case QgsAbstractAnnotationItemEditOperation::Type::TranslateItem:
|
||||
{
|
||||
QgsAnnotationItemEditOperationTranslateItem *moveOperation = qgis::down_cast< QgsAnnotationItemEditOperationTranslateItem * >( operation );
|
||||
switch ( mPlacementMode )
|
||||
{
|
||||
case Qgis::AnnotationPlacementMode::SpatialBounds:
|
||||
{
|
||||
const QgsRectangle modifiedBounds( mBounds.xMinimum() + moveOperation->translationX(),
|
||||
mBounds.yMinimum() + moveOperation->translationY(),
|
||||
mBounds.xMaximum() + moveOperation->translationX(),
|
||||
mBounds.yMaximum() + moveOperation->translationY() );
|
||||
return new QgsAnnotationItemEditOperationTransientResults( QgsGeometry::fromRect( modifiedBounds ) );
|
||||
}
|
||||
|
||||
case Qgis::AnnotationPlacementMode::FixedSize:
|
||||
{
|
||||
if ( callout() && !calloutAnchor().isEmpty() )
|
||||
{
|
||||
QgsGeometry anchor = calloutAnchor();
|
||||
|
||||
const double calloutOffsetWidthPixels = context.renderContext().convertToPainterUnits( offsetFromCallout().width(), offsetFromCalloutUnit() )
|
||||
+ moveOperation->translationXPixels();
|
||||
const double calloutOffsetHeightPixels = context.renderContext().convertToPainterUnits( offsetFromCallout().height(), offsetFromCalloutUnit() )
|
||||
+ moveOperation->translationYPixels();
|
||||
|
||||
QPointF anchorPoint = anchor.asQPointF();
|
||||
if ( context.renderContext().coordinateTransform().isValid() )
|
||||
{
|
||||
double x = anchorPoint.x();
|
||||
double y = anchorPoint.y();
|
||||
double z = 0.0;
|
||||
context.renderContext().coordinateTransform().transformInPlace( x, y, z );
|
||||
anchorPoint = QPointF( x, y );
|
||||
}
|
||||
|
||||
context.renderContext().mapToPixel().transformInPlace( anchorPoint.rx(), anchorPoint.ry() );
|
||||
|
||||
const double textOriginXPixels = anchorPoint.x() + calloutOffsetWidthPixels;
|
||||
const double textOriginYPixels = anchorPoint.y() + calloutOffsetHeightPixels;
|
||||
|
||||
const double widthPixels = context.renderContext().convertToPainterUnits( mFixedSize.width(), mFixedSizeUnit );
|
||||
const double heightPixels = context.renderContext().convertToPainterUnits( mFixedSize.height(), mFixedSizeUnit );
|
||||
|
||||
QgsLineString ls( QVector<QgsPointXY> { QgsPointXY( textOriginXPixels, textOriginYPixels ),
|
||||
QgsPointXY( textOriginXPixels + widthPixels, textOriginYPixels ),
|
||||
QgsPointXY( textOriginXPixels + widthPixels, textOriginYPixels + heightPixels ),
|
||||
QgsPointXY( textOriginXPixels, textOriginYPixels + heightPixels ),
|
||||
QgsPointXY( textOriginXPixels, textOriginYPixels )
|
||||
} );
|
||||
|
||||
QgsGeometry g( new QgsPolygon( ls.clone() ) );
|
||||
g.transform( context.renderContext().mapToPixel().transform().inverted() );
|
||||
g.transform( context.renderContext().coordinateTransform(), Qgis::TransformDirection::Reverse );
|
||||
return new QgsAnnotationItemEditOperationTransientResults( g );
|
||||
}
|
||||
else
|
||||
{
|
||||
const QgsRectangle currentBounds = context.currentItemBounds();
|
||||
const QgsRectangle newBounds = QgsRectangle::fromCenterAndSize( mBounds.center() + QgsVector( moveOperation->translationX(), moveOperation->translationY() ),
|
||||
currentBounds.width(), currentBounds.height() );
|
||||
return new QgsAnnotationItemEditOperationTransientResults( QgsGeometry::fromRect( newBounds ) );
|
||||
}
|
||||
}
|
||||
|
||||
case Qgis::AnnotationPlacementMode::RelativeToMapFrame:
|
||||
{
|
||||
const QgsRectangle currentBounds = context.currentItemBounds();
|
||||
const QgsRectangle newBounds = QgsRectangle::fromCenterAndSize( currentBounds.center() + QgsVector( moveOperation->translationX(), moveOperation->translationY() ),
|
||||
currentBounds.width(), currentBounds.height() );
|
||||
return new QgsAnnotationItemEditOperationTransientResults( QgsGeometry::fromRect( newBounds ) );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case QgsAbstractAnnotationItemEditOperation::Type::DeleteNode:
|
||||
case QgsAbstractAnnotationItemEditOperation::Type::AddNode:
|
||||
break;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QgsAnnotationRectangleTextItem *QgsAnnotationRectangleTextItem::create()
|
||||
{
|
||||
return new QgsAnnotationRectangleTextItem( QString(), QgsRectangle() );
|
||||
@ -560,57 +97,21 @@ bool QgsAnnotationRectangleTextItem::readXml( const QDomElement &element, const
|
||||
mTextFormat.readXml( textFormatElem, context );
|
||||
}
|
||||
|
||||
mBounds.setXMinimum( element.attribute( QStringLiteral( "xMin" ) ).toDouble() );
|
||||
mBounds.setXMaximum( element.attribute( QStringLiteral( "xMax" ) ).toDouble() );
|
||||
mBounds.setYMinimum( element.attribute( QStringLiteral( "yMin" ) ).toDouble() );
|
||||
mBounds.setYMaximum( element.attribute( QStringLiteral( "yMax" ) ).toDouble() );
|
||||
mPlacementMode = qgsEnumKeyToValue( element.attribute( QStringLiteral( "sizeMode" ) ), Qgis::AnnotationPlacementMode::SpatialBounds );
|
||||
mFixedSize = QSizeF(
|
||||
element.attribute( QStringLiteral( "fixedWidth" ) ).toDouble(),
|
||||
element.attribute( QStringLiteral( "fixedHeight" ) ).toDouble()
|
||||
);
|
||||
mFixedSizeUnit = QgsUnitTypes::decodeRenderUnit( element.attribute( QStringLiteral( "fixedSizeUnit" ) ) );
|
||||
|
||||
mMargins = QgsMargins::fromString( element.attribute( QStringLiteral( "margins" ) ) );
|
||||
mMarginUnit = QgsUnitTypes::decodeRenderUnit( element.attribute( QStringLiteral( "marginUnit" ), QgsUnitTypes::encodeUnit( Qgis::RenderUnit::Millimeters ) ) );
|
||||
|
||||
mAlignment = static_cast< Qt::Alignment >( element.attribute( QStringLiteral( "alignment" ) ).toInt() );
|
||||
|
||||
mDrawBackground = element.attribute( QStringLiteral( "backgroundEnabled" ), QStringLiteral( "1" ) ).toInt();
|
||||
const QDomElement backgroundSymbolElem = element.firstChildElement( QStringLiteral( "backgroundSymbol" ) ).firstChildElement();
|
||||
if ( !backgroundSymbolElem.isNull() )
|
||||
{
|
||||
setBackgroundSymbol( QgsSymbolLayerUtils::loadSymbol< QgsFillSymbol >( backgroundSymbolElem, context ) );
|
||||
}
|
||||
|
||||
mDrawFrame = element.attribute( QStringLiteral( "frameEnabled" ), QStringLiteral( "1" ) ).toInt();
|
||||
const QDomElement frameSymbolElem = element.firstChildElement( QStringLiteral( "frameSymbol" ) ).firstChildElement();
|
||||
if ( !frameSymbolElem.isNull() )
|
||||
{
|
||||
setFrameSymbol( QgsSymbolLayerUtils::loadSymbol< QgsFillSymbol >( frameSymbolElem, context ) );
|
||||
}
|
||||
|
||||
readCommonProperties( element, context );
|
||||
return true;
|
||||
}
|
||||
|
||||
QgsAnnotationRectangleTextItem *QgsAnnotationRectangleTextItem::clone() const
|
||||
{
|
||||
std::unique_ptr< QgsAnnotationRectangleTextItem > item = std::make_unique< QgsAnnotationRectangleTextItem >( mText, mBounds );
|
||||
std::unique_ptr< QgsAnnotationRectangleTextItem > item = std::make_unique< QgsAnnotationRectangleTextItem >( mText, bounds() );
|
||||
|
||||
item->setFormat( mTextFormat );
|
||||
item->setAlignment( mAlignment );
|
||||
item->setPlacementMode( mPlacementMode );
|
||||
item->setFixedSize( mFixedSize );
|
||||
item->setFixedSizeUnit( mFixedSizeUnit );
|
||||
|
||||
item->setBackgroundEnabled( mDrawBackground );
|
||||
if ( mBackgroundSymbol )
|
||||
item->setBackgroundSymbol( mBackgroundSymbol->clone() );
|
||||
|
||||
item->setFrameEnabled( mDrawFrame );
|
||||
if ( mFrameSymbol )
|
||||
item->setFrameSymbol( mFrameSymbol->clone() );
|
||||
|
||||
item->setMargins( mMargins );
|
||||
item->setMarginsUnit( mMarginUnit );
|
||||
@ -619,204 +120,9 @@ QgsAnnotationRectangleTextItem *QgsAnnotationRectangleTextItem::clone() const
|
||||
return item.release();
|
||||
}
|
||||
|
||||
QgsRectangle QgsAnnotationRectangleTextItem::boundingBox() const
|
||||
{
|
||||
QgsRectangle bounds;
|
||||
switch ( mPlacementMode )
|
||||
{
|
||||
case Qgis::AnnotationPlacementMode::SpatialBounds:
|
||||
{
|
||||
bounds = mBounds;
|
||||
if ( callout() && !calloutAnchor().isEmpty() )
|
||||
{
|
||||
QgsGeometry anchor = calloutAnchor();
|
||||
bounds.combineExtentWith( anchor.boundingBox() );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Qgis::AnnotationPlacementMode::FixedSize:
|
||||
if ( callout() && !calloutAnchor().isEmpty() )
|
||||
{
|
||||
bounds = calloutAnchor().boundingBox();
|
||||
}
|
||||
else
|
||||
{
|
||||
bounds = QgsRectangle( mBounds.center(), mBounds.center() );
|
||||
}
|
||||
break;
|
||||
|
||||
case Qgis::AnnotationPlacementMode::RelativeToMapFrame:
|
||||
bounds = mBounds;
|
||||
break;
|
||||
}
|
||||
|
||||
return bounds;
|
||||
}
|
||||
|
||||
QgsRectangle QgsAnnotationRectangleTextItem::boundingBox( QgsRenderContext &context ) const
|
||||
{
|
||||
switch ( mPlacementMode )
|
||||
{
|
||||
case Qgis::AnnotationPlacementMode::SpatialBounds:
|
||||
return QgsAnnotationRectangleTextItem::boundingBox();
|
||||
|
||||
case Qgis::AnnotationPlacementMode::FixedSize:
|
||||
{
|
||||
const double widthPixels = context.convertToPainterUnits( mFixedSize.width(), mFixedSizeUnit );
|
||||
const double heightPixels = context.convertToPainterUnits( mFixedSize.height(), mFixedSizeUnit );
|
||||
|
||||
QRectF boundsInPixels;
|
||||
if ( callout() && !calloutAnchor().isEmpty() )
|
||||
{
|
||||
QgsGeometry anchor = calloutAnchor();
|
||||
|
||||
const double calloutOffsetWidthPixels = context.convertToPainterUnits( offsetFromCallout().width(), offsetFromCalloutUnit() );
|
||||
const double calloutOffsetHeightPixels = context.convertToPainterUnits( offsetFromCallout().height(), offsetFromCalloutUnit() );
|
||||
|
||||
QPointF anchorPoint = anchor.asQPointF();
|
||||
if ( context.coordinateTransform().isValid() )
|
||||
{
|
||||
double x = anchorPoint.x();
|
||||
double y = anchorPoint.y();
|
||||
double z = 0.0;
|
||||
context.coordinateTransform().transformInPlace( x, y, z );
|
||||
anchorPoint = QPointF( x, y );
|
||||
}
|
||||
|
||||
context.mapToPixel().transformInPlace( anchorPoint.rx(), anchorPoint.ry() );
|
||||
|
||||
QgsRectangle textRect( anchorPoint.x() + calloutOffsetWidthPixels,
|
||||
anchorPoint.y() + calloutOffsetHeightPixels,
|
||||
anchorPoint.x() + calloutOffsetWidthPixels + widthPixels,
|
||||
anchorPoint.y() + calloutOffsetHeightPixels + heightPixels );
|
||||
QgsRectangle anchorRect( anchorPoint.x(), anchorPoint.y(), anchorPoint.x(), anchorPoint.y() );
|
||||
anchorRect.combineExtentWith( textRect );
|
||||
|
||||
boundsInPixels = anchorRect.toRectF();
|
||||
}
|
||||
else
|
||||
{
|
||||
QPointF center = mBounds.center().toQPointF();
|
||||
if ( context.coordinateTransform().isValid() )
|
||||
{
|
||||
double x = center.x();
|
||||
double y = center.y();
|
||||
double z = 0.0;
|
||||
context.coordinateTransform().transformInPlace( x, y, z );
|
||||
center = QPointF( x, y );
|
||||
}
|
||||
|
||||
context.mapToPixel().transformInPlace( center.rx(), center.ry() );
|
||||
boundsInPixels = QRectF( center.x() - widthPixels * 0.5,
|
||||
center.y() - heightPixels * 0.5,
|
||||
widthPixels, heightPixels );
|
||||
}
|
||||
const QgsPointXY topLeft = context.mapToPixel().toMapCoordinates( boundsInPixels.left(), boundsInPixels.top() );
|
||||
const QgsPointXY topRight = context.mapToPixel().toMapCoordinates( boundsInPixels.right(), boundsInPixels.top() );
|
||||
const QgsPointXY bottomLeft = context.mapToPixel().toMapCoordinates( boundsInPixels.left(), boundsInPixels.bottom() );
|
||||
const QgsPointXY bottomRight = context.mapToPixel().toMapCoordinates( boundsInPixels.right(), boundsInPixels.bottom() );
|
||||
|
||||
const QgsRectangle boundsMapUnits = QgsRectangle( topLeft.x(), bottomLeft.y(), bottomRight.x(), topRight.y() );
|
||||
QgsRectangle textRect = context.coordinateTransform().transformBoundingBox( boundsMapUnits, Qgis::TransformDirection::Reverse );
|
||||
return textRect;
|
||||
}
|
||||
|
||||
case Qgis::AnnotationPlacementMode::RelativeToMapFrame:
|
||||
{
|
||||
const double widthPixels = context.convertToPainterUnits( mFixedSize.width(), mFixedSizeUnit );
|
||||
const double heightPixels = context.convertToPainterUnits( mFixedSize.height(), mFixedSizeUnit );
|
||||
|
||||
QRectF boundsInPixels;
|
||||
|
||||
const double centerMapX = context.mapExtent().xMinimum() + mBounds.center().x() * context.mapExtent().width();
|
||||
const double centerMapY = context.mapExtent().yMaximum() - mBounds.center().y() * context.mapExtent().height();
|
||||
QPointF center( centerMapX, centerMapY );
|
||||
if ( context.coordinateTransform().isValid() )
|
||||
{
|
||||
double x = centerMapX;
|
||||
double y = centerMapY;
|
||||
double z = 0.0;
|
||||
context.coordinateTransform().transformInPlace( x, y, z );
|
||||
center = QPointF( x, y );
|
||||
}
|
||||
|
||||
context.mapToPixel().transformInPlace( center.rx(), center.ry() );
|
||||
boundsInPixels = QRectF( center.x() - widthPixels * 0.5,
|
||||
center.y() - heightPixels * 0.5,
|
||||
widthPixels, heightPixels );
|
||||
|
||||
const QgsPointXY topLeft = context.mapToPixel().toMapCoordinates( boundsInPixels.left(), boundsInPixels.top() );
|
||||
const QgsPointXY topRight = context.mapToPixel().toMapCoordinates( boundsInPixels.right(), boundsInPixels.top() );
|
||||
const QgsPointXY bottomLeft = context.mapToPixel().toMapCoordinates( boundsInPixels.left(), boundsInPixels.bottom() );
|
||||
const QgsPointXY bottomRight = context.mapToPixel().toMapCoordinates( boundsInPixels.right(), boundsInPixels.bottom() );
|
||||
|
||||
const QgsRectangle boundsMapUnits = QgsRectangle( topLeft.x(), bottomLeft.y(), bottomRight.x(), topRight.y() );
|
||||
QgsRectangle textRect = context.coordinateTransform().transformBoundingBox( boundsMapUnits, Qgis::TransformDirection::Reverse );
|
||||
return textRect;
|
||||
}
|
||||
}
|
||||
BUILTIN_UNREACHABLE
|
||||
}
|
||||
|
||||
void QgsAnnotationRectangleTextItem::setBounds( const QgsRectangle &bounds )
|
||||
{
|
||||
mBounds = bounds;
|
||||
}
|
||||
|
||||
Qgis::AnnotationPlacementMode QgsAnnotationRectangleTextItem::placementMode() const
|
||||
{
|
||||
return mPlacementMode;
|
||||
}
|
||||
|
||||
void QgsAnnotationRectangleTextItem::setPlacementMode( Qgis::AnnotationPlacementMode mode )
|
||||
{
|
||||
mPlacementMode = mode;
|
||||
}
|
||||
|
||||
QSizeF QgsAnnotationRectangleTextItem::fixedSize() const
|
||||
{
|
||||
return mFixedSize;
|
||||
}
|
||||
|
||||
void QgsAnnotationRectangleTextItem::setFixedSize( const QSizeF &size )
|
||||
{
|
||||
mFixedSize = size;
|
||||
}
|
||||
|
||||
Qgis::RenderUnit QgsAnnotationRectangleTextItem::fixedSizeUnit() const
|
||||
{
|
||||
return mFixedSizeUnit;
|
||||
}
|
||||
|
||||
void QgsAnnotationRectangleTextItem::setFixedSizeUnit( Qgis::RenderUnit unit )
|
||||
{
|
||||
mFixedSizeUnit = unit;
|
||||
}
|
||||
|
||||
const QgsFillSymbol *QgsAnnotationRectangleTextItem::backgroundSymbol() const
|
||||
{
|
||||
return mBackgroundSymbol.get();
|
||||
}
|
||||
|
||||
void QgsAnnotationRectangleTextItem::setBackgroundSymbol( QgsFillSymbol *symbol )
|
||||
{
|
||||
mBackgroundSymbol.reset( symbol );
|
||||
}
|
||||
|
||||
const QgsFillSymbol *QgsAnnotationRectangleTextItem::frameSymbol() const
|
||||
{
|
||||
return mFrameSymbol.get();
|
||||
}
|
||||
|
||||
void QgsAnnotationRectangleTextItem::setFrameSymbol( QgsFillSymbol *symbol )
|
||||
{
|
||||
mFrameSymbol.reset( symbol );
|
||||
}
|
||||
|
||||
Qgis::AnnotationItemFlags QgsAnnotationRectangleTextItem::flags() const
|
||||
{
|
||||
switch ( mPlacementMode )
|
||||
switch ( placementMode() )
|
||||
{
|
||||
case Qgis::AnnotationPlacementMode::SpatialBounds:
|
||||
return Qgis::AnnotationItemFlag::SupportsReferenceScale
|
||||
|
@ -20,7 +20,7 @@
|
||||
|
||||
#include "qgis_core.h"
|
||||
#include "qgis_sip.h"
|
||||
#include "qgsannotationitem.h"
|
||||
#include "qgsannotationrectitem.h"
|
||||
#include "qgstextformat.h"
|
||||
#include "qgsmargins.h"
|
||||
|
||||
@ -30,7 +30,7 @@
|
||||
*
|
||||
* \since QGIS 3.40
|
||||
*/
|
||||
class CORE_EXPORT QgsAnnotationRectangleTextItem : public QgsAnnotationItem
|
||||
class CORE_EXPORT QgsAnnotationRectangleTextItem : public QgsAnnotationRectItem
|
||||
{
|
||||
public:
|
||||
|
||||
@ -43,11 +43,7 @@ class CORE_EXPORT QgsAnnotationRectangleTextItem : public QgsAnnotationItem
|
||||
|
||||
QString type() const override;
|
||||
Qgis::AnnotationItemFlags flags() const override;
|
||||
void render( QgsRenderContext &context, QgsFeedback *feedback ) override;
|
||||
bool writeXml( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const override;
|
||||
QList< QgsAnnotationItemNode > nodesV2( const QgsAnnotationItemEditContext &context ) const override;
|
||||
Qgis::AnnotationItemEditOperationResult applyEditV2( QgsAbstractAnnotationItemEditOperation *operation, const QgsAnnotationItemEditContext &context ) override;
|
||||
QgsAnnotationItemEditOperationTransientResults *transientEditResultsV2( QgsAbstractAnnotationItemEditOperation *operation, const QgsAnnotationItemEditContext &context ) override SIP_FACTORY;
|
||||
|
||||
/**
|
||||
* Creates a new rectangle text annotation item.
|
||||
@ -56,26 +52,6 @@ class CORE_EXPORT QgsAnnotationRectangleTextItem : public QgsAnnotationItem
|
||||
|
||||
bool readXml( const QDomElement &element, const QgsReadWriteContext &context ) override;
|
||||
QgsAnnotationRectangleTextItem *clone() const override SIP_FACTORY;
|
||||
QgsRectangle boundingBox() const override;
|
||||
QgsRectangle boundingBox( QgsRenderContext &context ) const override;
|
||||
|
||||
/**
|
||||
* Returns the bounds of the text.
|
||||
*
|
||||
* The coordinate reference system for the bounds will be the parent layer's QgsAnnotationLayer::crs().
|
||||
*
|
||||
* \see setBounds()
|
||||
*/
|
||||
QgsRectangle bounds() const { return mBounds; }
|
||||
|
||||
/**
|
||||
* Sets the \a bounds of the text.
|
||||
*
|
||||
* The coordinate reference system for the bounds will be the parent layer's QgsAnnotationLayer::crs().
|
||||
*
|
||||
* \see bounds()
|
||||
*/
|
||||
void setBounds( const QgsRectangle &bounds );
|
||||
|
||||
/**
|
||||
* Returns the text rendered by the item.
|
||||
@ -91,56 +67,6 @@ class CORE_EXPORT QgsAnnotationRectangleTextItem : public QgsAnnotationItem
|
||||
*/
|
||||
void setText( const QString &text ) { mText = text; }
|
||||
|
||||
/**
|
||||
* Returns the placement mode for the text.
|
||||
*
|
||||
* \see setPlacementMode()
|
||||
*/
|
||||
Qgis::AnnotationPlacementMode placementMode() const;
|
||||
|
||||
/**
|
||||
* Sets the placement \a mode for the text.
|
||||
*
|
||||
* \see placementMode()
|
||||
*/
|
||||
void setPlacementMode( Qgis::AnnotationPlacementMode mode );
|
||||
|
||||
/**
|
||||
* Returns the fixed size to use for the text, when the placementMode() is Qgis::AnnotationPlacementMode::FixedSize.
|
||||
*
|
||||
* Units are retrieved via fixedSizeUnit()
|
||||
*
|
||||
* \see setFixedSize()
|
||||
* \see fixedSizeUnit()
|
||||
*/
|
||||
QSizeF fixedSize() const;
|
||||
|
||||
/**
|
||||
* Sets the fixed \a size to use for the text, when the placementMode() is Qgis::AnnotationPlacementMode::FixedSize.
|
||||
*
|
||||
* Units are set via setFixedSizeUnit()
|
||||
*
|
||||
* \see fixedSize()
|
||||
* \see setFixedSizeUnit()
|
||||
*/
|
||||
void setFixedSize( const QSizeF &size );
|
||||
|
||||
/**
|
||||
* Returns the units to use for fixed text sizes, when the placementMode() is Qgis::AnnotationPlacementMode::FixedSize.
|
||||
*
|
||||
* \see setFixedSizeUnit()
|
||||
* \see fixedSize()
|
||||
*/
|
||||
Qgis::RenderUnit fixedSizeUnit() const;
|
||||
|
||||
/**
|
||||
* Sets the \a unit to use for fixed text sizes, when the placementMode() is Qgis::AnnotationPlacementMode::FixedSize.
|
||||
*
|
||||
* \see fixedSizeUnit()
|
||||
* \see setFixedSize()
|
||||
*/
|
||||
void setFixedSizeUnit( Qgis::RenderUnit unit );
|
||||
|
||||
/**
|
||||
* Returns the text format used to render the text.
|
||||
*
|
||||
@ -169,74 +95,6 @@ class CORE_EXPORT QgsAnnotationRectangleTextItem : public QgsAnnotationItem
|
||||
*/
|
||||
void setAlignment( Qt::Alignment alignment );
|
||||
|
||||
/**
|
||||
* Returns TRUE if the item's background should be rendered.
|
||||
*
|
||||
* \see setBackgroundEnabled()
|
||||
* \see backgroundSymbol()
|
||||
*/
|
||||
bool backgroundEnabled() const { return mDrawBackground; }
|
||||
|
||||
/**
|
||||
* Sets whether the item's background should be rendered.
|
||||
*
|
||||
* \see backgroundEnabled()
|
||||
* \see setBackgroundSymbol()
|
||||
*/
|
||||
void setBackgroundEnabled( bool enabled ) { mDrawBackground = enabled; }
|
||||
|
||||
/**
|
||||
* Returns the symbol used to render the item's background.
|
||||
*
|
||||
* \see backgroundEnabled()
|
||||
* \see setBackgroundSymbol()
|
||||
*/
|
||||
const QgsFillSymbol *backgroundSymbol() const;
|
||||
|
||||
/**
|
||||
* Sets the \a symbol used to render the item's background.
|
||||
*
|
||||
* The item takes ownership of the symbol.
|
||||
*
|
||||
* \see backgroundSymbol()
|
||||
* \see setBackgroundEnabled()
|
||||
*/
|
||||
void setBackgroundSymbol( QgsFillSymbol *symbol SIP_TRANSFER );
|
||||
|
||||
/**
|
||||
* Returns TRUE if the item's frame should be rendered.
|
||||
*
|
||||
* \see setFrameEnabled()
|
||||
* \see frameSymbol()
|
||||
*/
|
||||
bool frameEnabled() const { return mDrawFrame; }
|
||||
|
||||
/**
|
||||
* Sets whether the item's frame should be rendered.
|
||||
*
|
||||
* \see frameEnabled()
|
||||
* \see setFrameSymbol()
|
||||
*/
|
||||
void setFrameEnabled( bool enabled ) { mDrawFrame = enabled; }
|
||||
|
||||
/**
|
||||
* Returns the symbol used to render the item's frame.
|
||||
*
|
||||
* \see frameEnabled()
|
||||
* \see setFrameSymbol()
|
||||
*/
|
||||
const QgsFillSymbol *frameSymbol() const;
|
||||
|
||||
/**
|
||||
* Sets the \a symbol used to render the item's frame.
|
||||
*
|
||||
* The item takes ownership of the symbol.
|
||||
*
|
||||
* \see frameSymbol()
|
||||
* \see setBackgroundEnabled()
|
||||
*/
|
||||
void setFrameSymbol( QgsFillSymbol *symbol SIP_TRANSFER );
|
||||
|
||||
/**
|
||||
* Returns the margins between the outside of the item's frame and the interior text.
|
||||
*
|
||||
@ -273,22 +131,16 @@ class CORE_EXPORT QgsAnnotationRectangleTextItem : public QgsAnnotationItem
|
||||
*/
|
||||
Qgis::RenderUnit marginsUnit() const { return mMarginUnit; }
|
||||
|
||||
private:
|
||||
protected:
|
||||
|
||||
Qgis::AnnotationPlacementMode mPlacementMode = Qgis::AnnotationPlacementMode::SpatialBounds;
|
||||
QgsRectangle mBounds;
|
||||
QSizeF mFixedSize;
|
||||
Qgis::RenderUnit mFixedSizeUnit = Qgis::RenderUnit::Millimeters;
|
||||
void renderInBounds( QgsRenderContext &context, const QRectF &painterBounds, QgsFeedback *feedback ) override;
|
||||
|
||||
private:
|
||||
|
||||
QString mText;
|
||||
QgsTextFormat mTextFormat;
|
||||
Qt::Alignment mAlignment = Qt::AlignLeft;
|
||||
|
||||
bool mDrawBackground = true;
|
||||
std::unique_ptr< QgsFillSymbol > mBackgroundSymbol;
|
||||
bool mDrawFrame = true;
|
||||
std::unique_ptr< QgsFillSymbol > mFrameSymbol;
|
||||
|
||||
QgsMargins mMargins;
|
||||
Qgis::RenderUnit mMarginUnit = Qgis::RenderUnit::Millimeters;
|
||||
|
||||
|
774
src/core/annotations/qgsannotationrectitem.cpp
Normal file
774
src/core/annotations/qgsannotationrectitem.cpp
Normal file
@ -0,0 +1,774 @@
|
||||
/***************************************************************************
|
||||
qgsannotationrectitem.cpp
|
||||
----------------
|
||||
begin : July 2024
|
||||
copyright : (C) 2024 by Nyall Dawson
|
||||
email : nyall dot dawson at gmail dot com
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "qgsannotationrectitem.h"
|
||||
#include "qgsapplication.h"
|
||||
#include "qgsgeometry.h"
|
||||
#include "qgsrendercontext.h"
|
||||
#include "qgsannotationitemnode.h"
|
||||
#include "qgsannotationitemeditoperation.h"
|
||||
#include "qgspainting.h"
|
||||
#include "qgsfillsymbol.h"
|
||||
#include "qgssymbollayerutils.h"
|
||||
#include "qgsfillsymbollayer.h"
|
||||
#include "qgslinesymbollayer.h"
|
||||
#include "qgscalloutsregistry.h"
|
||||
#include "qgslinestring.h"
|
||||
#include "qgspolygon.h"
|
||||
#include "qgsunittypes.h"
|
||||
|
||||
QgsAnnotationRectItem::QgsAnnotationRectItem( const QgsRectangle &bounds )
|
||||
: QgsAnnotationItem()
|
||||
, mBounds( bounds )
|
||||
{
|
||||
mBackgroundSymbol = std::make_unique< QgsFillSymbol >(
|
||||
QgsSymbolLayerList
|
||||
{
|
||||
new QgsSimpleFillSymbolLayer( QColor( 255, 255, 255 ), Qt::BrushStyle::SolidPattern, QColor( 0, 0, 0 ), Qt::PenStyle::NoPen )
|
||||
}
|
||||
);
|
||||
QgsSimpleLineSymbolLayer *borderSymbol = new QgsSimpleLineSymbolLayer( QColor( 0, 0, 0 ) );
|
||||
borderSymbol->setPenJoinStyle( Qt::MiterJoin );
|
||||
mFrameSymbol = std::make_unique< QgsFillSymbol >( QgsSymbolLayerList{ borderSymbol } );
|
||||
}
|
||||
|
||||
QgsAnnotationRectItem::~QgsAnnotationRectItem() = default;
|
||||
|
||||
Qgis::AnnotationItemFlags QgsAnnotationRectItem::flags() const
|
||||
{
|
||||
switch ( mPlacementMode )
|
||||
{
|
||||
case Qgis::AnnotationPlacementMode::SpatialBounds:
|
||||
return Qgis::AnnotationItemFlag::SupportsCallouts;
|
||||
case Qgis::AnnotationPlacementMode::FixedSize:
|
||||
return Qgis::AnnotationItemFlag::ScaleDependentBoundingBox
|
||||
| Qgis::AnnotationItemFlag::SupportsCallouts;
|
||||
case Qgis::AnnotationPlacementMode::RelativeToMapFrame:
|
||||
return Qgis::AnnotationItemFlag::ScaleDependentBoundingBox;
|
||||
}
|
||||
BUILTIN_UNREACHABLE
|
||||
}
|
||||
|
||||
void QgsAnnotationRectItem::render( QgsRenderContext &context, QgsFeedback *feedback )
|
||||
{
|
||||
QgsRectangle bounds = mBounds;
|
||||
if ( mPlacementMode != Qgis::AnnotationPlacementMode::RelativeToMapFrame && context.coordinateTransform().isValid() )
|
||||
{
|
||||
try
|
||||
{
|
||||
bounds = context.coordinateTransform().transformBoundingBox( mBounds );
|
||||
}
|
||||
catch ( QgsCsException & )
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
QRectF painterBounds;
|
||||
|
||||
switch ( mPlacementMode )
|
||||
{
|
||||
case Qgis::AnnotationPlacementMode::SpatialBounds:
|
||||
painterBounds = context.mapToPixel().transformBounds( bounds.toRectF() );
|
||||
break;
|
||||
|
||||
case Qgis::AnnotationPlacementMode::FixedSize:
|
||||
{
|
||||
const double widthPixels = context.convertToPainterUnits( mFixedSize.width(), mFixedSizeUnit );
|
||||
const double heightPixels = context.convertToPainterUnits( mFixedSize.height(), mFixedSizeUnit );
|
||||
|
||||
if ( callout() && !calloutAnchor().isEmpty() )
|
||||
{
|
||||
QgsGeometry anchor = calloutAnchor();
|
||||
|
||||
const double calloutOffsetWidthPixels = context.convertToPainterUnits( offsetFromCallout().width(), offsetFromCalloutUnit() );
|
||||
const double calloutOffsetHeightPixels = context.convertToPainterUnits( offsetFromCallout().height(), offsetFromCalloutUnit() );
|
||||
|
||||
QPointF anchorPoint = anchor.asQPointF();
|
||||
if ( context.coordinateTransform().isValid() )
|
||||
{
|
||||
double x = anchorPoint.x();
|
||||
double y = anchorPoint.y();
|
||||
double z = 0.0;
|
||||
context.coordinateTransform().transformInPlace( x, y, z );
|
||||
anchorPoint = QPointF( x, y );
|
||||
}
|
||||
|
||||
context.mapToPixel().transformInPlace( anchorPoint.rx(), anchorPoint.ry() );
|
||||
|
||||
painterBounds = QRectF( anchorPoint.x() + calloutOffsetWidthPixels,
|
||||
anchorPoint.y() + calloutOffsetHeightPixels, widthPixels, heightPixels );
|
||||
}
|
||||
else
|
||||
{
|
||||
QPointF center = bounds.center().toQPointF();
|
||||
|
||||
context.mapToPixel().transformInPlace( center.rx(), center.ry() );
|
||||
painterBounds = QRectF( center.x() - widthPixels * 0.5,
|
||||
center.y() - heightPixels * 0.5,
|
||||
widthPixels, heightPixels );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Qgis::AnnotationPlacementMode::RelativeToMapFrame:
|
||||
{
|
||||
const double widthPixels = context.convertToPainterUnits( mFixedSize.width(), mFixedSizeUnit );
|
||||
const double heightPixels = context.convertToPainterUnits( mFixedSize.height(), mFixedSizeUnit );
|
||||
|
||||
QPointF center = bounds.center().toQPointF();
|
||||
center.rx() *= context.outputSize().width();
|
||||
center.ry() *= context.outputSize().height();
|
||||
|
||||
painterBounds = QRectF( center.x() - widthPixels * 0.5,
|
||||
center.y() - heightPixels * 0.5,
|
||||
widthPixels, heightPixels );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( painterBounds.width() < 1 || painterBounds.height() < 1 )
|
||||
return;
|
||||
|
||||
if ( mDrawBackground && mBackgroundSymbol )
|
||||
{
|
||||
mBackgroundSymbol->startRender( context );
|
||||
mBackgroundSymbol->renderPolygon( painterBounds, nullptr, nullptr, context );
|
||||
mBackgroundSymbol->stopRender( context );
|
||||
}
|
||||
|
||||
if ( mPlacementMode != Qgis::AnnotationPlacementMode::RelativeToMapFrame && callout() )
|
||||
{
|
||||
QgsCallout::QgsCalloutContext calloutContext;
|
||||
renderCallout( context, painterBounds, 0, calloutContext, feedback );
|
||||
}
|
||||
|
||||
renderInBounds( context, painterBounds, feedback );
|
||||
|
||||
if ( mDrawFrame && mFrameSymbol )
|
||||
{
|
||||
mFrameSymbol->startRender( context );
|
||||
mFrameSymbol->renderPolygon( painterBounds, nullptr, nullptr, context );
|
||||
mFrameSymbol->stopRender( context );
|
||||
}
|
||||
}
|
||||
|
||||
QList<QgsAnnotationItemNode> QgsAnnotationRectItem::nodesV2( const QgsAnnotationItemEditContext &context ) const
|
||||
{
|
||||
QList<QgsAnnotationItemNode> res;
|
||||
switch ( mPlacementMode )
|
||||
{
|
||||
case Qgis::AnnotationPlacementMode::SpatialBounds:
|
||||
{
|
||||
res =
|
||||
{
|
||||
QgsAnnotationItemNode( QgsVertexId( 0, 0, 0 ), QgsPointXY( mBounds.xMinimum(), mBounds.yMinimum() ), Qgis::AnnotationItemNodeType::VertexHandle ),
|
||||
QgsAnnotationItemNode( QgsVertexId( 0, 0, 1 ), QgsPointXY( mBounds.xMaximum(), mBounds.yMinimum() ), Qgis::AnnotationItemNodeType::VertexHandle ),
|
||||
QgsAnnotationItemNode( QgsVertexId( 0, 0, 2 ), QgsPointXY( mBounds.xMaximum(), mBounds.yMaximum() ), Qgis::AnnotationItemNodeType::VertexHandle ),
|
||||
QgsAnnotationItemNode( QgsVertexId( 0, 0, 3 ), QgsPointXY( mBounds.xMinimum(), mBounds.yMaximum() ), Qgis::AnnotationItemNodeType::VertexHandle ),
|
||||
};
|
||||
|
||||
QgsPointXY calloutNodePoint;
|
||||
if ( !calloutAnchor().isEmpty() )
|
||||
{
|
||||
calloutNodePoint = calloutAnchor().asPoint();
|
||||
}
|
||||
else
|
||||
{
|
||||
calloutNodePoint = mBounds.center();
|
||||
}
|
||||
res.append( QgsAnnotationItemNode( QgsVertexId( 1, 0, 0 ), calloutNodePoint, Qgis::AnnotationItemNodeType::CalloutHandle ) );
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
case Qgis::AnnotationPlacementMode::FixedSize:
|
||||
{
|
||||
res =
|
||||
{
|
||||
QgsAnnotationItemNode( QgsVertexId( 0, 0, 0 ), mBounds.center(), Qgis::AnnotationItemNodeType::VertexHandle )
|
||||
};
|
||||
|
||||
QgsPointXY calloutNodePoint;
|
||||
if ( !calloutAnchor().isEmpty() )
|
||||
{
|
||||
calloutNodePoint = calloutAnchor().asPoint();
|
||||
}
|
||||
else
|
||||
{
|
||||
calloutNodePoint = QgsPointXY( context.currentItemBounds().xMinimum(), context.currentItemBounds().yMinimum() );
|
||||
}
|
||||
res.append( QgsAnnotationItemNode( QgsVertexId( 1, 0, 0 ), calloutNodePoint, Qgis::AnnotationItemNodeType::CalloutHandle ) );
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
case Qgis::AnnotationPlacementMode::RelativeToMapFrame:
|
||||
{
|
||||
return
|
||||
{
|
||||
QgsAnnotationItemNode( QgsVertexId( 0, 0, 0 ),
|
||||
context.currentItemBounds().center(), Qgis::AnnotationItemNodeType::VertexHandle )
|
||||
};
|
||||
}
|
||||
}
|
||||
BUILTIN_UNREACHABLE
|
||||
}
|
||||
|
||||
Qgis::AnnotationItemEditOperationResult QgsAnnotationRectItem::applyEditV2( QgsAbstractAnnotationItemEditOperation *operation, const QgsAnnotationItemEditContext &context )
|
||||
{
|
||||
switch ( operation->type() )
|
||||
{
|
||||
case QgsAbstractAnnotationItemEditOperation::Type::MoveNode:
|
||||
{
|
||||
QgsAnnotationItemEditOperationMoveNode *moveOperation = dynamic_cast< QgsAnnotationItemEditOperationMoveNode * >( operation );
|
||||
if ( moveOperation->nodeId().part == 0 )
|
||||
{
|
||||
switch ( mPlacementMode )
|
||||
{
|
||||
case Qgis::AnnotationPlacementMode::SpatialBounds:
|
||||
{
|
||||
switch ( moveOperation->nodeId().vertex )
|
||||
{
|
||||
case 0:
|
||||
mBounds = QgsRectangle( moveOperation->after().x(),
|
||||
moveOperation->after().y(),
|
||||
mBounds.xMaximum(),
|
||||
mBounds.yMaximum() );
|
||||
break;
|
||||
case 1:
|
||||
mBounds = QgsRectangle( mBounds.xMinimum(),
|
||||
moveOperation->after().y(),
|
||||
moveOperation->after().x(),
|
||||
mBounds.yMaximum() );
|
||||
break;
|
||||
case 2:
|
||||
mBounds = QgsRectangle( mBounds.xMinimum(),
|
||||
mBounds.yMinimum(),
|
||||
moveOperation->after().x(),
|
||||
moveOperation->after().y() );
|
||||
break;
|
||||
case 3:
|
||||
mBounds = QgsRectangle( moveOperation->after().x(),
|
||||
mBounds.yMinimum(),
|
||||
mBounds.xMaximum(),
|
||||
moveOperation->after().y() );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return Qgis::AnnotationItemEditOperationResult::Success;
|
||||
}
|
||||
|
||||
case Qgis::AnnotationPlacementMode::FixedSize:
|
||||
{
|
||||
mBounds = QgsRectangle::fromCenterAndSize( moveOperation->after(),
|
||||
mBounds.width(),
|
||||
mBounds.height() );
|
||||
return Qgis::AnnotationItemEditOperationResult::Success;
|
||||
}
|
||||
|
||||
case Qgis::AnnotationPlacementMode::RelativeToMapFrame:
|
||||
{
|
||||
const double deltaX = moveOperation->translationXPixels() / context.renderContext().outputSize().width();
|
||||
const double deltaY = moveOperation->translationYPixels() / context.renderContext().outputSize().height();
|
||||
mBounds = QgsRectangle::fromCenterAndSize( QgsPointXY( mBounds.center().x() + deltaX, mBounds.center().y() + deltaY ),
|
||||
mBounds.width(), mBounds.height() );
|
||||
return Qgis::AnnotationItemEditOperationResult::Success;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( moveOperation->nodeId().part == 1 )
|
||||
{
|
||||
setCalloutAnchor( QgsGeometry::fromPoint( moveOperation->after() ) );
|
||||
if ( !callout() )
|
||||
{
|
||||
setCallout( QgsApplication::calloutRegistry()->defaultCallout() );
|
||||
}
|
||||
return Qgis::AnnotationItemEditOperationResult::Success;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case QgsAbstractAnnotationItemEditOperation::Type::TranslateItem:
|
||||
{
|
||||
QgsAnnotationItemEditOperationTranslateItem *moveOperation = qgis::down_cast< QgsAnnotationItemEditOperationTranslateItem * >( operation );
|
||||
switch ( mPlacementMode )
|
||||
{
|
||||
|
||||
case Qgis::AnnotationPlacementMode::SpatialBounds:
|
||||
mBounds = QgsRectangle( mBounds.xMinimum() + moveOperation->translationX(),
|
||||
mBounds.yMinimum() + moveOperation->translationY(),
|
||||
mBounds.xMaximum() + moveOperation->translationX(),
|
||||
mBounds.yMaximum() + moveOperation->translationY() );
|
||||
break;
|
||||
|
||||
case Qgis::AnnotationPlacementMode::FixedSize:
|
||||
{
|
||||
if ( callout() && !calloutAnchor().isEmpty() )
|
||||
{
|
||||
const double xOffset = context.renderContext().convertFromPainterUnits( moveOperation->translationXPixels(), offsetFromCalloutUnit() );
|
||||
const double yOffset = context.renderContext().convertFromPainterUnits( moveOperation->translationYPixels(), offsetFromCalloutUnit() );
|
||||
setOffsetFromCallout( QSizeF( offsetFromCallout().width() + xOffset, offsetFromCallout().height() + yOffset ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
mBounds = QgsRectangle( mBounds.xMinimum() + moveOperation->translationX(),
|
||||
mBounds.yMinimum() + moveOperation->translationY(),
|
||||
mBounds.xMaximum() + moveOperation->translationX(),
|
||||
mBounds.yMaximum() + moveOperation->translationY() );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Qgis::AnnotationPlacementMode::RelativeToMapFrame:
|
||||
{
|
||||
const double deltaX = moveOperation->translationXPixels() / context.renderContext().outputSize().width();
|
||||
const double deltaY = moveOperation->translationYPixels() / context.renderContext().outputSize().height();
|
||||
mBounds = QgsRectangle::fromCenterAndSize( QgsPointXY( mBounds.center().x() + deltaX, mBounds.center().y() + deltaY ),
|
||||
mBounds.width(), mBounds.height() );
|
||||
break;
|
||||
}
|
||||
}
|
||||
return Qgis::AnnotationItemEditOperationResult::Success;
|
||||
}
|
||||
|
||||
case QgsAbstractAnnotationItemEditOperation::Type::DeleteNode:
|
||||
case QgsAbstractAnnotationItemEditOperation::Type::AddNode:
|
||||
break;
|
||||
}
|
||||
return Qgis::AnnotationItemEditOperationResult::Invalid;
|
||||
}
|
||||
|
||||
QgsAnnotationItemEditOperationTransientResults *QgsAnnotationRectItem::transientEditResultsV2( QgsAbstractAnnotationItemEditOperation *operation, const QgsAnnotationItemEditContext &context )
|
||||
{
|
||||
switch ( operation->type() )
|
||||
{
|
||||
case QgsAbstractAnnotationItemEditOperation::Type::MoveNode:
|
||||
{
|
||||
QgsAnnotationItemEditOperationMoveNode *moveOperation = dynamic_cast< QgsAnnotationItemEditOperationMoveNode * >( operation );
|
||||
if ( moveOperation->nodeId().part == 0 )
|
||||
{
|
||||
switch ( mPlacementMode )
|
||||
{
|
||||
case Qgis::AnnotationPlacementMode::SpatialBounds:
|
||||
{
|
||||
QgsRectangle modifiedBounds = mBounds;
|
||||
switch ( moveOperation->nodeId().vertex )
|
||||
{
|
||||
case 0:
|
||||
modifiedBounds.setXMinimum( moveOperation->after().x() );
|
||||
modifiedBounds.setYMinimum( moveOperation->after().y() );
|
||||
break;
|
||||
case 1:
|
||||
modifiedBounds.setXMaximum( moveOperation->after().x() );
|
||||
modifiedBounds.setYMinimum( moveOperation->after().y() );
|
||||
break;
|
||||
case 2:
|
||||
modifiedBounds.setXMaximum( moveOperation->after().x() );
|
||||
modifiedBounds.setYMaximum( moveOperation->after().y() );
|
||||
break;
|
||||
case 3:
|
||||
modifiedBounds.setXMinimum( moveOperation->after().x() );
|
||||
modifiedBounds.setYMaximum( moveOperation->after().y() );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return new QgsAnnotationItemEditOperationTransientResults( QgsGeometry::fromRect( modifiedBounds ) );
|
||||
}
|
||||
case Qgis::AnnotationPlacementMode::FixedSize:
|
||||
{
|
||||
const QgsRectangle currentBounds = context.currentItemBounds();
|
||||
const QgsRectangle newBounds = QgsRectangle::fromCenterAndSize( moveOperation->after(), currentBounds.width(), currentBounds.height() );
|
||||
return new QgsAnnotationItemEditOperationTransientResults( QgsGeometry::fromRect( newBounds ) );
|
||||
}
|
||||
case Qgis::AnnotationPlacementMode::RelativeToMapFrame:
|
||||
{
|
||||
const QgsRectangle currentBounds = context.currentItemBounds();
|
||||
const QgsRectangle newBounds = QgsRectangle::fromCenterAndSize( currentBounds.center() + ( moveOperation->after() - moveOperation->before() ),
|
||||
currentBounds.width(), currentBounds.height() );
|
||||
return new QgsAnnotationItemEditOperationTransientResults( QgsGeometry::fromRect( newBounds ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsAnnotationItemEditOperationMoveNode *moveOperation = dynamic_cast< QgsAnnotationItemEditOperationMoveNode * >( operation );
|
||||
return new QgsAnnotationItemEditOperationTransientResults( QgsGeometry( moveOperation->after().clone() ) );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case QgsAbstractAnnotationItemEditOperation::Type::TranslateItem:
|
||||
{
|
||||
QgsAnnotationItemEditOperationTranslateItem *moveOperation = qgis::down_cast< QgsAnnotationItemEditOperationTranslateItem * >( operation );
|
||||
switch ( mPlacementMode )
|
||||
{
|
||||
case Qgis::AnnotationPlacementMode::SpatialBounds:
|
||||
{
|
||||
const QgsRectangle modifiedBounds( mBounds.xMinimum() + moveOperation->translationX(),
|
||||
mBounds.yMinimum() + moveOperation->translationY(),
|
||||
mBounds.xMaximum() + moveOperation->translationX(),
|
||||
mBounds.yMaximum() + moveOperation->translationY() );
|
||||
return new QgsAnnotationItemEditOperationTransientResults( QgsGeometry::fromRect( modifiedBounds ) );
|
||||
}
|
||||
|
||||
case Qgis::AnnotationPlacementMode::FixedSize:
|
||||
{
|
||||
if ( callout() && !calloutAnchor().isEmpty() )
|
||||
{
|
||||
QgsGeometry anchor = calloutAnchor();
|
||||
|
||||
const double calloutOffsetWidthPixels = context.renderContext().convertToPainterUnits( offsetFromCallout().width(), offsetFromCalloutUnit() )
|
||||
+ moveOperation->translationXPixels();
|
||||
const double calloutOffsetHeightPixels = context.renderContext().convertToPainterUnits( offsetFromCallout().height(), offsetFromCalloutUnit() )
|
||||
+ moveOperation->translationYPixels();
|
||||
|
||||
QPointF anchorPoint = anchor.asQPointF();
|
||||
if ( context.renderContext().coordinateTransform().isValid() )
|
||||
{
|
||||
double x = anchorPoint.x();
|
||||
double y = anchorPoint.y();
|
||||
double z = 0.0;
|
||||
context.renderContext().coordinateTransform().transformInPlace( x, y, z );
|
||||
anchorPoint = QPointF( x, y );
|
||||
}
|
||||
|
||||
context.renderContext().mapToPixel().transformInPlace( anchorPoint.rx(), anchorPoint.ry() );
|
||||
|
||||
const double textOriginXPixels = anchorPoint.x() + calloutOffsetWidthPixels;
|
||||
const double textOriginYPixels = anchorPoint.y() + calloutOffsetHeightPixels;
|
||||
|
||||
const double widthPixels = context.renderContext().convertToPainterUnits( mFixedSize.width(), mFixedSizeUnit );
|
||||
const double heightPixels = context.renderContext().convertToPainterUnits( mFixedSize.height(), mFixedSizeUnit );
|
||||
|
||||
QgsLineString ls( QVector<QgsPointXY> { QgsPointXY( textOriginXPixels, textOriginYPixels ),
|
||||
QgsPointXY( textOriginXPixels + widthPixels, textOriginYPixels ),
|
||||
QgsPointXY( textOriginXPixels + widthPixels, textOriginYPixels + heightPixels ),
|
||||
QgsPointXY( textOriginXPixels, textOriginYPixels + heightPixels ),
|
||||
QgsPointXY( textOriginXPixels, textOriginYPixels )
|
||||
} );
|
||||
|
||||
QgsGeometry g( new QgsPolygon( ls.clone() ) );
|
||||
g.transform( context.renderContext().mapToPixel().transform().inverted() );
|
||||
g.transform( context.renderContext().coordinateTransform(), Qgis::TransformDirection::Reverse );
|
||||
return new QgsAnnotationItemEditOperationTransientResults( g );
|
||||
}
|
||||
else
|
||||
{
|
||||
const QgsRectangle currentBounds = context.currentItemBounds();
|
||||
const QgsRectangle newBounds = QgsRectangle::fromCenterAndSize( mBounds.center() + QgsVector( moveOperation->translationX(), moveOperation->translationY() ),
|
||||
currentBounds.width(), currentBounds.height() );
|
||||
return new QgsAnnotationItemEditOperationTransientResults( QgsGeometry::fromRect( newBounds ) );
|
||||
}
|
||||
}
|
||||
|
||||
case Qgis::AnnotationPlacementMode::RelativeToMapFrame:
|
||||
{
|
||||
const QgsRectangle currentBounds = context.currentItemBounds();
|
||||
const QgsRectangle newBounds = QgsRectangle::fromCenterAndSize( currentBounds.center() + QgsVector( moveOperation->translationX(), moveOperation->translationY() ),
|
||||
currentBounds.width(), currentBounds.height() );
|
||||
return new QgsAnnotationItemEditOperationTransientResults( QgsGeometry::fromRect( newBounds ) );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case QgsAbstractAnnotationItemEditOperation::Type::DeleteNode:
|
||||
case QgsAbstractAnnotationItemEditOperation::Type::AddNode:
|
||||
break;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QgsRectangle QgsAnnotationRectItem::boundingBox() const
|
||||
{
|
||||
QgsRectangle bounds;
|
||||
switch ( mPlacementMode )
|
||||
{
|
||||
case Qgis::AnnotationPlacementMode::SpatialBounds:
|
||||
{
|
||||
bounds = mBounds;
|
||||
if ( callout() && !calloutAnchor().isEmpty() )
|
||||
{
|
||||
QgsGeometry anchor = calloutAnchor();
|
||||
bounds.combineExtentWith( anchor.boundingBox() );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Qgis::AnnotationPlacementMode::FixedSize:
|
||||
if ( callout() && !calloutAnchor().isEmpty() )
|
||||
{
|
||||
bounds = calloutAnchor().boundingBox();
|
||||
}
|
||||
else
|
||||
{
|
||||
bounds = QgsRectangle( mBounds.center(), mBounds.center() );
|
||||
}
|
||||
break;
|
||||
|
||||
case Qgis::AnnotationPlacementMode::RelativeToMapFrame:
|
||||
bounds = mBounds;
|
||||
break;
|
||||
}
|
||||
|
||||
return bounds;
|
||||
}
|
||||
|
||||
QgsRectangle QgsAnnotationRectItem::boundingBox( QgsRenderContext &context ) const
|
||||
{
|
||||
switch ( mPlacementMode )
|
||||
{
|
||||
case Qgis::AnnotationPlacementMode::SpatialBounds:
|
||||
return QgsAnnotationRectItem::boundingBox();
|
||||
|
||||
case Qgis::AnnotationPlacementMode::FixedSize:
|
||||
{
|
||||
const double widthPixels = context.convertToPainterUnits( mFixedSize.width(), mFixedSizeUnit );
|
||||
const double heightPixels = context.convertToPainterUnits( mFixedSize.height(), mFixedSizeUnit );
|
||||
|
||||
QRectF boundsInPixels;
|
||||
if ( callout() && !calloutAnchor().isEmpty() )
|
||||
{
|
||||
QgsGeometry anchor = calloutAnchor();
|
||||
|
||||
const double calloutOffsetWidthPixels = context.convertToPainterUnits( offsetFromCallout().width(), offsetFromCalloutUnit() );
|
||||
const double calloutOffsetHeightPixels = context.convertToPainterUnits( offsetFromCallout().height(), offsetFromCalloutUnit() );
|
||||
|
||||
QPointF anchorPoint = anchor.asQPointF();
|
||||
if ( context.coordinateTransform().isValid() )
|
||||
{
|
||||
double x = anchorPoint.x();
|
||||
double y = anchorPoint.y();
|
||||
double z = 0.0;
|
||||
context.coordinateTransform().transformInPlace( x, y, z );
|
||||
anchorPoint = QPointF( x, y );
|
||||
}
|
||||
|
||||
context.mapToPixel().transformInPlace( anchorPoint.rx(), anchorPoint.ry() );
|
||||
|
||||
QgsRectangle textRect( anchorPoint.x() + calloutOffsetWidthPixels,
|
||||
anchorPoint.y() + calloutOffsetHeightPixels,
|
||||
anchorPoint.x() + calloutOffsetWidthPixels + widthPixels,
|
||||
anchorPoint.y() + calloutOffsetHeightPixels + heightPixels );
|
||||
QgsRectangle anchorRect( anchorPoint.x(), anchorPoint.y(), anchorPoint.x(), anchorPoint.y() );
|
||||
anchorRect.combineExtentWith( textRect );
|
||||
|
||||
boundsInPixels = anchorRect.toRectF();
|
||||
}
|
||||
else
|
||||
{
|
||||
QPointF center = mBounds.center().toQPointF();
|
||||
if ( context.coordinateTransform().isValid() )
|
||||
{
|
||||
double x = center.x();
|
||||
double y = center.y();
|
||||
double z = 0.0;
|
||||
context.coordinateTransform().transformInPlace( x, y, z );
|
||||
center = QPointF( x, y );
|
||||
}
|
||||
|
||||
context.mapToPixel().transformInPlace( center.rx(), center.ry() );
|
||||
boundsInPixels = QRectF( center.x() - widthPixels * 0.5,
|
||||
center.y() - heightPixels * 0.5,
|
||||
widthPixels, heightPixels );
|
||||
}
|
||||
const QgsPointXY topLeft = context.mapToPixel().toMapCoordinates( boundsInPixels.left(), boundsInPixels.top() );
|
||||
const QgsPointXY topRight = context.mapToPixel().toMapCoordinates( boundsInPixels.right(), boundsInPixels.top() );
|
||||
const QgsPointXY bottomLeft = context.mapToPixel().toMapCoordinates( boundsInPixels.left(), boundsInPixels.bottom() );
|
||||
const QgsPointXY bottomRight = context.mapToPixel().toMapCoordinates( boundsInPixels.right(), boundsInPixels.bottom() );
|
||||
|
||||
const QgsRectangle boundsMapUnits = QgsRectangle( topLeft.x(), bottomLeft.y(), bottomRight.x(), topRight.y() );
|
||||
QgsRectangle textRect = context.coordinateTransform().transformBoundingBox( boundsMapUnits, Qgis::TransformDirection::Reverse );
|
||||
return textRect;
|
||||
}
|
||||
|
||||
case Qgis::AnnotationPlacementMode::RelativeToMapFrame:
|
||||
{
|
||||
const double widthPixels = context.convertToPainterUnits( mFixedSize.width(), mFixedSizeUnit );
|
||||
const double heightPixels = context.convertToPainterUnits( mFixedSize.height(), mFixedSizeUnit );
|
||||
|
||||
QRectF boundsInPixels;
|
||||
|
||||
const double centerMapX = context.mapExtent().xMinimum() + mBounds.center().x() * context.mapExtent().width();
|
||||
const double centerMapY = context.mapExtent().yMaximum() - mBounds.center().y() * context.mapExtent().height();
|
||||
QPointF center( centerMapX, centerMapY );
|
||||
if ( context.coordinateTransform().isValid() )
|
||||
{
|
||||
double x = centerMapX;
|
||||
double y = centerMapY;
|
||||
double z = 0.0;
|
||||
context.coordinateTransform().transformInPlace( x, y, z );
|
||||
center = QPointF( x, y );
|
||||
}
|
||||
|
||||
context.mapToPixel().transformInPlace( center.rx(), center.ry() );
|
||||
boundsInPixels = QRectF( center.x() - widthPixels * 0.5,
|
||||
center.y() - heightPixels * 0.5,
|
||||
widthPixels, heightPixels );
|
||||
|
||||
const QgsPointXY topLeft = context.mapToPixel().toMapCoordinates( boundsInPixels.left(), boundsInPixels.top() );
|
||||
const QgsPointXY topRight = context.mapToPixel().toMapCoordinates( boundsInPixels.right(), boundsInPixels.top() );
|
||||
const QgsPointXY bottomLeft = context.mapToPixel().toMapCoordinates( boundsInPixels.left(), boundsInPixels.bottom() );
|
||||
const QgsPointXY bottomRight = context.mapToPixel().toMapCoordinates( boundsInPixels.right(), boundsInPixels.bottom() );
|
||||
|
||||
const QgsRectangle boundsMapUnits = QgsRectangle( topLeft.x(), bottomLeft.y(), bottomRight.x(), topRight.y() );
|
||||
QgsRectangle textRect = context.coordinateTransform().transformBoundingBox( boundsMapUnits, Qgis::TransformDirection::Reverse );
|
||||
return textRect;
|
||||
}
|
||||
}
|
||||
BUILTIN_UNREACHABLE
|
||||
}
|
||||
|
||||
void QgsAnnotationRectItem::setBounds( const QgsRectangle &bounds )
|
||||
{
|
||||
mBounds = bounds;
|
||||
}
|
||||
|
||||
const QgsFillSymbol *QgsAnnotationRectItem::backgroundSymbol() const
|
||||
{
|
||||
return mBackgroundSymbol.get();
|
||||
}
|
||||
|
||||
void QgsAnnotationRectItem::setBackgroundSymbol( QgsFillSymbol *symbol )
|
||||
{
|
||||
mBackgroundSymbol.reset( symbol );
|
||||
}
|
||||
|
||||
const QgsFillSymbol *QgsAnnotationRectItem::frameSymbol() const
|
||||
{
|
||||
return mFrameSymbol.get();
|
||||
}
|
||||
|
||||
void QgsAnnotationRectItem::setFrameSymbol( QgsFillSymbol *symbol )
|
||||
{
|
||||
mFrameSymbol.reset( symbol );
|
||||
}
|
||||
|
||||
void QgsAnnotationRectItem::copyCommonProperties( const QgsAnnotationItem *other )
|
||||
{
|
||||
if ( const QgsAnnotationRectItem *otherRect = dynamic_cast< const QgsAnnotationRectItem * >( other ) )
|
||||
{
|
||||
setPlacementMode( otherRect->mPlacementMode );
|
||||
setFixedSize( otherRect->mFixedSize );
|
||||
setFixedSizeUnit( otherRect->mFixedSizeUnit );
|
||||
|
||||
setBackgroundEnabled( otherRect->mDrawBackground );
|
||||
if ( otherRect->mBackgroundSymbol )
|
||||
setBackgroundSymbol( otherRect->mBackgroundSymbol->clone() );
|
||||
|
||||
setFrameEnabled( otherRect->mDrawFrame );
|
||||
if ( otherRect->mFrameSymbol )
|
||||
setFrameSymbol( otherRect->mFrameSymbol->clone() );
|
||||
}
|
||||
|
||||
QgsAnnotationItem::copyCommonProperties( other );
|
||||
}
|
||||
|
||||
bool QgsAnnotationRectItem::writeCommonProperties( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const
|
||||
{
|
||||
element.setAttribute( QStringLiteral( "xMin" ), qgsDoubleToString( mBounds.xMinimum() ) );
|
||||
element.setAttribute( QStringLiteral( "xMax" ), qgsDoubleToString( mBounds.xMaximum() ) );
|
||||
element.setAttribute( QStringLiteral( "yMin" ), qgsDoubleToString( mBounds.yMinimum() ) );
|
||||
element.setAttribute( QStringLiteral( "yMax" ), qgsDoubleToString( mBounds.yMaximum() ) );
|
||||
element.setAttribute( QStringLiteral( "sizeMode" ), qgsEnumValueToKey( mPlacementMode ) );
|
||||
element.setAttribute( QStringLiteral( "fixedWidth" ), qgsDoubleToString( mFixedSize.width() ) );
|
||||
element.setAttribute( QStringLiteral( "fixedHeight" ), qgsDoubleToString( mFixedSize.height() ) );
|
||||
element.setAttribute( QStringLiteral( "fixedSizeUnit" ), QgsUnitTypes::encodeUnit( mFixedSizeUnit ) );
|
||||
|
||||
element.setAttribute( QStringLiteral( "backgroundEnabled" ), mDrawBackground ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
|
||||
if ( mBackgroundSymbol )
|
||||
{
|
||||
QDomElement backgroundElement = document.createElement( QStringLiteral( "backgroundSymbol" ) );
|
||||
backgroundElement.appendChild( QgsSymbolLayerUtils::saveSymbol( QStringLiteral( "backgroundSymbol" ), mBackgroundSymbol.get(), document, context ) );
|
||||
element.appendChild( backgroundElement );
|
||||
}
|
||||
|
||||
element.setAttribute( QStringLiteral( "frameEnabled" ), mDrawFrame ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
|
||||
if ( mFrameSymbol )
|
||||
{
|
||||
QDomElement frameElement = document.createElement( QStringLiteral( "frameSymbol" ) );
|
||||
frameElement.appendChild( QgsSymbolLayerUtils::saveSymbol( QStringLiteral( "frameSymbol" ), mFrameSymbol.get(), document, context ) );
|
||||
element.appendChild( frameElement );
|
||||
}
|
||||
|
||||
return QgsAnnotationItem::writeCommonProperties( element, document, context );
|
||||
}
|
||||
|
||||
bool QgsAnnotationRectItem::readCommonProperties( const QDomElement &element, const QgsReadWriteContext &context )
|
||||
{
|
||||
mBounds.setXMinimum( element.attribute( QStringLiteral( "xMin" ) ).toDouble() );
|
||||
mBounds.setXMaximum( element.attribute( QStringLiteral( "xMax" ) ).toDouble() );
|
||||
mBounds.setYMinimum( element.attribute( QStringLiteral( "yMin" ) ).toDouble() );
|
||||
mBounds.setYMaximum( element.attribute( QStringLiteral( "yMax" ) ).toDouble() );
|
||||
|
||||
mPlacementMode = qgsEnumKeyToValue( element.attribute( QStringLiteral( "sizeMode" ) ), Qgis::AnnotationPlacementMode::SpatialBounds );
|
||||
|
||||
mFixedSize = QSizeF(
|
||||
element.attribute( QStringLiteral( "fixedWidth" ) ).toDouble(),
|
||||
element.attribute( QStringLiteral( "fixedHeight" ) ).toDouble()
|
||||
);
|
||||
mFixedSizeUnit = QgsUnitTypes::decodeRenderUnit( element.attribute( QStringLiteral( "fixedSizeUnit" ) ) );
|
||||
|
||||
mDrawBackground = element.attribute( QStringLiteral( "backgroundEnabled" ), QStringLiteral( "0" ) ).toInt();
|
||||
const QDomElement backgroundSymbolElem = element.firstChildElement( QStringLiteral( "backgroundSymbol" ) ).firstChildElement();
|
||||
if ( !backgroundSymbolElem.isNull() )
|
||||
{
|
||||
setBackgroundSymbol( QgsSymbolLayerUtils::loadSymbol< QgsFillSymbol >( backgroundSymbolElem, context ) );
|
||||
}
|
||||
|
||||
mDrawFrame = element.attribute( QStringLiteral( "frameEnabled" ), QStringLiteral( "0" ) ).toInt();
|
||||
const QDomElement frameSymbolElem = element.firstChildElement( QStringLiteral( "frameSymbol" ) ).firstChildElement();
|
||||
if ( !frameSymbolElem.isNull() )
|
||||
{
|
||||
setFrameSymbol( QgsSymbolLayerUtils::loadSymbol< QgsFillSymbol >( frameSymbolElem, context ) );
|
||||
}
|
||||
|
||||
return QgsAnnotationItem::readCommonProperties( element, context );
|
||||
}
|
||||
|
||||
QSizeF QgsAnnotationRectItem::fixedSize() const
|
||||
{
|
||||
return mFixedSize;
|
||||
}
|
||||
|
||||
void QgsAnnotationRectItem::setFixedSize( const QSizeF &size )
|
||||
{
|
||||
mFixedSize = size;
|
||||
}
|
||||
|
||||
Qgis::RenderUnit QgsAnnotationRectItem::fixedSizeUnit() const
|
||||
{
|
||||
return mFixedSizeUnit;
|
||||
}
|
||||
|
||||
void QgsAnnotationRectItem::setFixedSizeUnit( Qgis::RenderUnit unit )
|
||||
{
|
||||
mFixedSizeUnit = unit;
|
||||
}
|
||||
|
||||
Qgis::AnnotationPlacementMode QgsAnnotationRectItem::placementMode() const
|
||||
{
|
||||
return mPlacementMode;
|
||||
}
|
||||
|
||||
void QgsAnnotationRectItem::setPlacementMode( Qgis::AnnotationPlacementMode mode )
|
||||
{
|
||||
mPlacementMode = mode;
|
||||
}
|
227
src/core/annotations/qgsannotationrectitem.h
Normal file
227
src/core/annotations/qgsannotationrectitem.h
Normal file
@ -0,0 +1,227 @@
|
||||
/***************************************************************************
|
||||
qgsannotationrectitem.h
|
||||
----------------
|
||||
begin : July 2024
|
||||
copyright : (C) 2024 by Nyall Dawson
|
||||
email : nyall dot dawson at gmail dot com
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef QGSANNOTATIONRECTITEM_H
|
||||
#define QGSANNOTATIONRECTITEM_H
|
||||
|
||||
#include "qgis_core.h"
|
||||
#include "qgis_sip.h"
|
||||
#include "qgsannotationitem.h"
|
||||
|
||||
/**
|
||||
* \ingroup core
|
||||
* \brief Abstract base class for annotation items which render annotations in a rectangular shape.
|
||||
*
|
||||
* Subclasses should implement the pure virtual render() method which takes a painter bounds argument.
|
||||
*
|
||||
* \since QGIS 3.40
|
||||
*/
|
||||
class CORE_EXPORT QgsAnnotationRectItem : public QgsAnnotationItem
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor for QgsAnnotationRectItem, rendering the annotation
|
||||
* within the specified \a bounds geometry.
|
||||
*/
|
||||
QgsAnnotationRectItem( const QgsRectangle &bounds );
|
||||
~QgsAnnotationRectItem() override;
|
||||
|
||||
Qgis::AnnotationItemFlags flags() const override;
|
||||
void render( QgsRenderContext &context, QgsFeedback *feedback ) override;
|
||||
QList< QgsAnnotationItemNode > nodesV2( const QgsAnnotationItemEditContext &context ) const override;
|
||||
Qgis::AnnotationItemEditOperationResult applyEditV2( QgsAbstractAnnotationItemEditOperation *operation, const QgsAnnotationItemEditContext &context ) override;
|
||||
QgsAnnotationItemEditOperationTransientResults *transientEditResultsV2( QgsAbstractAnnotationItemEditOperation *operation, const QgsAnnotationItemEditContext &context ) override SIP_FACTORY;
|
||||
QgsRectangle boundingBox() const override;
|
||||
QgsRectangle boundingBox( QgsRenderContext &context ) const override;
|
||||
|
||||
/**
|
||||
* Returns the bounds of the item.
|
||||
*
|
||||
* The coordinate reference system for the item will be the parent layer's QgsAnnotationLayer::crs().
|
||||
*
|
||||
* When the placementMode() is Qgis::AnnotationPlacementMode::FixedSize then the item will be placed
|
||||
* at the center of the bounds.
|
||||
*
|
||||
* \see setBounds()
|
||||
*/
|
||||
QgsRectangle bounds() const { return mBounds; }
|
||||
|
||||
/**
|
||||
* Sets the \a bounds of the item.
|
||||
*
|
||||
* The coordinate reference system for the bounds will be the parent layer's QgsAnnotationLayer::crs().
|
||||
*
|
||||
* When the placementMode() is Qgis::AnnotationPlacementMode::FixedSize then the item will be placed
|
||||
* at the center of the bounds.
|
||||
*
|
||||
* \see bounds()
|
||||
*/
|
||||
void setBounds( const QgsRectangle &bounds );
|
||||
|
||||
/**
|
||||
* Returns the placement mode for the item.
|
||||
*
|
||||
* \see setPlacementMode()
|
||||
*/
|
||||
Qgis::AnnotationPlacementMode placementMode() const;
|
||||
|
||||
/**
|
||||
* Sets the placement \a mode for the item.
|
||||
*
|
||||
* \see placementMode()
|
||||
*/
|
||||
void setPlacementMode( Qgis::AnnotationPlacementMode mode );
|
||||
|
||||
/**
|
||||
* Returns the fixed size to use for the item, when the placementMode() is Qgis::AnnotationPlacementMode::FixedSize.
|
||||
*
|
||||
* Units are retrieved via fixedSizeUnit()
|
||||
*
|
||||
* \see setFixedSize()
|
||||
* \see fixedSizeUnit()
|
||||
*/
|
||||
QSizeF fixedSize() const;
|
||||
|
||||
/**
|
||||
* Sets the fixed \a size to use for the item, when the placementMode() is Qgis::AnnotationPlacementMode::FixedSize.
|
||||
*
|
||||
* Units are set via setFixedSizeUnit()
|
||||
*
|
||||
* \see fixedSize()
|
||||
* \see setFixedSizeUnit()
|
||||
*/
|
||||
void setFixedSize( const QSizeF &size );
|
||||
|
||||
/**
|
||||
* Returns the units to use for fixed item sizes, when the placementMode() is Qgis::AnnotationPlacementMode::FixedSize.
|
||||
*
|
||||
* \see setFixedSizeUnit()
|
||||
* \see fixedSize()
|
||||
*/
|
||||
Qgis::RenderUnit fixedSizeUnit() const;
|
||||
|
||||
/**
|
||||
* Sets the \a unit to use for fixed item sizes, when the placementMode() is Qgis::AnnotationPlacementMode::FixedSize.
|
||||
*
|
||||
* \see fixedSizeUnit()
|
||||
* \see setFixedSize()
|
||||
*/
|
||||
void setFixedSizeUnit( Qgis::RenderUnit unit );
|
||||
|
||||
/**
|
||||
* Returns TRUE if the item's background should be rendered.
|
||||
*
|
||||
* \see setBackgroundEnabled()
|
||||
* \see backgroundSymbol()
|
||||
*/
|
||||
bool backgroundEnabled() const { return mDrawBackground; }
|
||||
|
||||
/**
|
||||
* Sets whether the item's background should be rendered.
|
||||
*
|
||||
* \see backgroundEnabled()
|
||||
* \see setBackgroundSymbol()
|
||||
*/
|
||||
void setBackgroundEnabled( bool enabled ) { mDrawBackground = enabled; }
|
||||
|
||||
/**
|
||||
* Returns the symbol used to render the item's background.
|
||||
*
|
||||
* \see backgroundEnabled()
|
||||
* \see setBackgroundSymbol()
|
||||
*/
|
||||
const QgsFillSymbol *backgroundSymbol() const;
|
||||
|
||||
/**
|
||||
* Sets the \a symbol used to render the item's background.
|
||||
*
|
||||
* The item takes ownership of the symbol.
|
||||
*
|
||||
* \see backgroundSymbol()
|
||||
* \see setBackgroundEnabled()
|
||||
*/
|
||||
void setBackgroundSymbol( QgsFillSymbol *symbol SIP_TRANSFER );
|
||||
|
||||
/**
|
||||
* Returns TRUE if the item's frame should be rendered.
|
||||
*
|
||||
* \see setFrameEnabled()
|
||||
* \see frameSymbol()
|
||||
*/
|
||||
bool frameEnabled() const { return mDrawFrame; }
|
||||
|
||||
/**
|
||||
* Sets whether the item's frame should be rendered.
|
||||
*
|
||||
* \see frameEnabled()
|
||||
* \see setFrameSymbol()
|
||||
*/
|
||||
void setFrameEnabled( bool enabled ) { mDrawFrame = enabled; }
|
||||
|
||||
/**
|
||||
* Returns the symbol used to render the item's frame.
|
||||
*
|
||||
* \see frameEnabled()
|
||||
* \see setFrameSymbol()
|
||||
*/
|
||||
const QgsFillSymbol *frameSymbol() const;
|
||||
|
||||
/**
|
||||
* Sets the \a symbol used to render the item's frame.
|
||||
*
|
||||
* The item takes ownership of the symbol.
|
||||
*
|
||||
* \see frameSymbol()
|
||||
* \see setBackgroundEnabled()
|
||||
*/
|
||||
void setFrameSymbol( QgsFillSymbol *symbol SIP_TRANSFER );
|
||||
|
||||
protected:
|
||||
void copyCommonProperties( const QgsAnnotationItem *other ) override;
|
||||
bool writeCommonProperties( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const override;
|
||||
bool readCommonProperties( const QDomElement &element, const QgsReadWriteContext &context ) override;
|
||||
|
||||
/**
|
||||
* Renders the item to the specified render \a context.
|
||||
*
|
||||
* The \a painterRect argument specifies the bounds in painter units where the rectangular
|
||||
* item should be rendered within.
|
||||
*
|
||||
* The \a feedback argument can be used to detect render cancellations during expensive
|
||||
* render operations.
|
||||
*/
|
||||
virtual void renderInBounds( QgsRenderContext &context, const QRectF &painterRect, QgsFeedback *feedback ) = 0;
|
||||
|
||||
private:
|
||||
|
||||
Qgis::AnnotationPlacementMode mPlacementMode = Qgis::AnnotationPlacementMode::SpatialBounds;
|
||||
QgsRectangle mBounds;
|
||||
|
||||
QSizeF mFixedSize;
|
||||
Qgis::RenderUnit mFixedSizeUnit = Qgis::RenderUnit::Millimeters;
|
||||
bool mDrawBackground = false;
|
||||
std::unique_ptr< QgsFillSymbol > mBackgroundSymbol;
|
||||
bool mDrawFrame = false;
|
||||
std::unique_ptr< QgsFillSymbol > mFrameSymbol;
|
||||
|
||||
#ifdef SIP_RUN
|
||||
QgsAnnotationRectItem( const QgsAnnotationRectItem &other );
|
||||
#endif
|
||||
|
||||
};
|
||||
#endif // QGSANNOTATIONRECTITEM_H
|
Loading…
x
Reference in New Issue
Block a user