Merge pull request #4380 from nyalldawson/clone_annotations

Add methods to clone annotations
This commit is contained in:
Nyall Dawson 2017-04-20 14:15:05 +10:00 committed by GitHub
commit 6ecb17f1fd
19 changed files with 130 additions and 1 deletions

View File

@ -25,6 +25,8 @@ class QgsAnnotation : QObject
QgsAnnotation( QObject* parent /TransferThis/ = nullptr ); QgsAnnotation( QObject* parent /TransferThis/ = nullptr );
virtual QgsAnnotation *clone() const = 0 /Factory/;
bool isVisible() const; bool isVisible() const;
void setVisible( bool visible ); void setVisible( bool visible );
@ -81,4 +83,6 @@ class QgsAnnotation : QObject
void _writeXml( QDomElement& itemElem, QDomDocument& doc ) const; void _writeXml( QDomElement& itemElem, QDomDocument& doc ) const;
void _readXml( const QDomElement& annotationElem, const QDomDocument& doc ); void _readXml( const QDomElement& annotationElem, const QDomDocument& doc );
void copyCommonProperties( QgsAnnotation *target ) const;
}; };

View File

@ -68,6 +68,16 @@ class QgsAnnotationManager : QObject
QList< QgsAnnotation * > annotations() const; QList< QgsAnnotation * > annotations() const;
%Docstring %Docstring
Returns a list of all annotations contained in the manager. Returns a list of all annotations contained in the manager.
\see cloneAnnotations()
:rtype: list of QgsAnnotation
%End
QList< QgsAnnotation * > cloneAnnotations() const /Factory/;
%Docstring
Returns a list containing clones of all annotations contained
in the manager. The caller takes responsibility for deleting
all returned annotations.
\see annotations()
:rtype: list of QgsAnnotation :rtype: list of QgsAnnotation
%End %End

View File

@ -31,6 +31,8 @@ class QgsHtmlAnnotation: QgsAnnotation
~QgsHtmlAnnotation(); ~QgsHtmlAnnotation();
virtual QgsHtmlAnnotation *clone() const /Factory/;
virtual QSizeF minimumFrameSize() const; virtual QSizeF minimumFrameSize() const;
void setSourceFile( const QString &htmlFile ); void setSourceFile( const QString &htmlFile );

View File

@ -26,6 +26,8 @@ class QgsSvgAnnotation: QgsAnnotation
Constructor for QgsSvgAnnotation. Constructor for QgsSvgAnnotation.
%End %End
virtual QgsSvgAnnotation *clone() const /Factory/;
virtual void writeXml( QDomElement &elem, QDomDocument &doc ) const; virtual void writeXml( QDomElement &elem, QDomDocument &doc ) const;
virtual void readXml( const QDomElement &itemElem, const QDomDocument &doc ); virtual void readXml( const QDomElement &itemElem, const QDomDocument &doc );

View File

@ -26,6 +26,8 @@ class QgsTextAnnotation: QgsAnnotation
Constructor for QgsTextAnnotation. Constructor for QgsTextAnnotation.
%End %End
virtual QgsTextAnnotation *clone() const /Factory/;
const QTextDocument *document() const; const QTextDocument *document() const;
%Docstring %Docstring
Returns the text document which will be rendered Returns the text document which will be rendered

View File

@ -7,6 +7,8 @@ class QgsFormAnnotation : QgsAnnotation
QgsFormAnnotation( QObject* parent /TransferThis/ = nullptr ); QgsFormAnnotation( QObject* parent /TransferThis/ = nullptr );
virtual QgsFormAnnotation *clone() const /Factory/;
QSizeF minimumFrameSize() const; QSizeF minimumFrameSize() const;
QSizeF preferredFrameSize() const; QSizeF preferredFrameSize() const;

View File

@ -431,3 +431,22 @@ void QgsAnnotation::_readXml( const QDomElement &annotationElem, const QDomDocum
emit mapLayerChanged(); emit mapLayerChanged();
} }
void QgsAnnotation::copyCommonProperties( QgsAnnotation *target ) const
{
target->mVisible = mVisible;
target->mHasFixedMapPosition = mHasFixedMapPosition;
target->mMapPosition = mMapPosition;
target->mMapPositionCrs = mMapPositionCrs;
target->mRelativePosition = mRelativePosition;
target->mOffsetFromReferencePoint = mOffsetFromReferencePoint;
target->mFrameSize = mFrameSize;
target->mMarkerSymbol.reset( mMarkerSymbol ? mMarkerSymbol->clone() : nullptr );
target->mContentsMargins = mContentsMargins;
target->mFillSymbol.reset( mFillSymbol ? mFillSymbol->clone() : nullptr );
target->mBalloonSegment = mBalloonSegment;
target->mBalloonSegmentPoint1 = mBalloonSegmentPoint1;
target->mBalloonSegmentPoint2 = mBalloonSegmentPoint2;
target->mMapLayer = mMapLayer;
target->mFeature = mFeature;
}

View File

@ -57,6 +57,12 @@ class CORE_EXPORT QgsAnnotation : public QObject
*/ */
QgsAnnotation( QObject *parent = nullptr ); QgsAnnotation( QObject *parent = nullptr );
/**
* Clones the annotation, returning a new copy of the annotation
* reflecting the annotation's current state.
*/
virtual QgsAnnotation *clone() const = 0;
/** /**
* Returns true if the annotation is visible and should be rendered. * Returns true if the annotation is visible and should be rendered.
* \see setVisible() * \see setVisible()
@ -293,6 +299,14 @@ class CORE_EXPORT QgsAnnotation : public QObject
*/ */
void _readXml( const QDomElement &annotationElem, const QDomDocument &doc ); void _readXml( const QDomElement &annotationElem, const QDomDocument &doc );
/**
* Copies common annotation properties to the \a targe
* annotation.
* Can be used within QgsAnnotation::clone() implementations
* to assist with creating copies.
*/
void copyCommonProperties( QgsAnnotation *target ) const;
private: private:
//! Check where to attach the balloon connection between frame and map point //! Check where to attach the balloon connection between frame and map point

View File

@ -73,6 +73,16 @@ QList<QgsAnnotation *> QgsAnnotationManager::annotations() const
return mAnnotations; return mAnnotations;
} }
QList<QgsAnnotation *> QgsAnnotationManager::cloneAnnotations() const
{
QList<QgsAnnotation *> results;
Q_FOREACH ( const QgsAnnotation *a, mAnnotations )
{
results << a->clone();
}
return results;
}
bool QgsAnnotationManager::readXml( const QDomElement &element, const QDomDocument &doc ) bool QgsAnnotationManager::readXml( const QDomElement &element, const QDomDocument &doc )
{ {
clear(); clear();

View File

@ -79,9 +79,18 @@ class CORE_EXPORT QgsAnnotationManager : public QObject
/** /**
* Returns a list of all annotations contained in the manager. * Returns a list of all annotations contained in the manager.
* \see cloneAnnotations()
*/ */
QList< QgsAnnotation * > annotations() const; QList< QgsAnnotation * > annotations() const;
/**
* Returns a list containing clones of all annotations contained
* in the manager. The caller takes responsibility for deleting
* all returned annotations.
* \see annotations()
*/
QList< QgsAnnotation * > cloneAnnotations() const SIP_FACTORY;
/** /**
* Reads the manager's state from a DOM element, restoring all annotations * Reads the manager's state from a DOM element, restoring all annotations
* present in the XML document. * present in the XML document.

View File

@ -47,6 +47,14 @@ QgsHtmlAnnotation::QgsHtmlAnnotation( QObject *parent )
connect( mWebPage->mainFrame(), &QWebFrame::javaScriptWindowObjectCleared, this, &QgsHtmlAnnotation::javascript ); connect( mWebPage->mainFrame(), &QWebFrame::javaScriptWindowObjectCleared, this, &QgsHtmlAnnotation::javascript );
} }
QgsHtmlAnnotation *QgsHtmlAnnotation::clone() const
{
std::unique_ptr< QgsHtmlAnnotation > c( new QgsHtmlAnnotation() );
copyCommonProperties( c.get() );
c->setSourceFile( mHtmlFile );
return c.release();
}
void QgsHtmlAnnotation::setSourceFile( const QString &htmlFile ) void QgsHtmlAnnotation::setSourceFile( const QString &htmlFile )
{ {
QFile file( htmlFile ); QFile file( htmlFile );

View File

@ -44,6 +44,8 @@ class CORE_EXPORT QgsHtmlAnnotation: public QgsAnnotation
~QgsHtmlAnnotation() = default; ~QgsHtmlAnnotation() = default;
QgsHtmlAnnotation *clone() const override SIP_FACTORY;
QSizeF minimumFrameSize() const override; QSizeF minimumFrameSize() const override;
/** /**

View File

@ -27,6 +27,14 @@ QgsSvgAnnotation::QgsSvgAnnotation( QObject *parent )
} }
QgsSvgAnnotation *QgsSvgAnnotation::clone() const
{
std::unique_ptr< QgsSvgAnnotation > c( new QgsSvgAnnotation() );
copyCommonProperties( c.get() );
c->setFilePath( mFilePath );
return c.release();
}
void QgsSvgAnnotation::writeXml( QDomElement &elem, QDomDocument &doc ) const void QgsSvgAnnotation::writeXml( QDomElement &elem, QDomDocument &doc ) const
{ {
QDomElement svgAnnotationElem = doc.createElement( QStringLiteral( "SVGAnnotationItem" ) ); QDomElement svgAnnotationElem = doc.createElement( QStringLiteral( "SVGAnnotationItem" ) );

View File

@ -39,6 +39,8 @@ class CORE_EXPORT QgsSvgAnnotation: public QgsAnnotation
*/ */
QgsSvgAnnotation( QObject *parent SIP_TRANSFERTHIS = nullptr ); QgsSvgAnnotation( QObject *parent SIP_TRANSFERTHIS = nullptr );
QgsSvgAnnotation *clone() const override SIP_FACTORY;
virtual void writeXml( QDomElement &elem, QDomDocument &doc ) const override; virtual void writeXml( QDomElement &elem, QDomDocument &doc ) const override;
virtual void readXml( const QDomElement &itemElem, const QDomDocument &doc ) override; virtual void readXml( const QDomElement &itemElem, const QDomDocument &doc ) override;

View File

@ -26,6 +26,14 @@ QgsTextAnnotation::QgsTextAnnotation( QObject *parent )
mDocument->setUseDesignMetrics( true ); mDocument->setUseDesignMetrics( true );
} }
QgsTextAnnotation *QgsTextAnnotation::clone() const
{
std::unique_ptr< QgsTextAnnotation > c( new QgsTextAnnotation() );
copyCommonProperties( c.get() );
c->setDocument( mDocument ? mDocument->clone() : nullptr );
return c.release();
}
const QTextDocument *QgsTextAnnotation::document() const const QTextDocument *QgsTextAnnotation::document() const
{ {
return mDocument.get(); return mDocument.get();

View File

@ -39,6 +39,8 @@ class CORE_EXPORT QgsTextAnnotation: public QgsAnnotation
*/ */
QgsTextAnnotation( QObject *parent SIP_TRANSFERTHIS = nullptr ); QgsTextAnnotation( QObject *parent SIP_TRANSFERTHIS = nullptr );
QgsTextAnnotation *clone() const override SIP_FACTORY;
/** /**
* Returns the text document which will be rendered * Returns the text document which will be rendered
* within the annotation. * within the annotation.

View File

@ -40,6 +40,14 @@ QgsFormAnnotation::QgsFormAnnotation( QObject *parent )
: QgsAnnotation( parent ) : QgsAnnotation( parent )
{} {}
QgsFormAnnotation *QgsFormAnnotation::clone() const
{
std::unique_ptr< QgsFormAnnotation > c( new QgsFormAnnotation() );
copyCommonProperties( c.get() );
c->setDesignerForm( mDesignerForm );
return c.release();
}
void QgsFormAnnotation::setDesignerForm( const QString &uiFile ) void QgsFormAnnotation::setDesignerForm( const QString &uiFile )
{ {
mDesignerForm = uiFile; mDesignerForm = uiFile;

View File

@ -39,6 +39,8 @@ class GUI_EXPORT QgsFormAnnotation: public QgsAnnotation
*/ */
QgsFormAnnotation( QObject *parent = nullptr ); QgsFormAnnotation( QObject *parent = nullptr );
QgsFormAnnotation *clone() const override SIP_FACTORY;
QSizeF minimumFrameSize() const override; QSizeF minimumFrameSize() const override;
//! Returns the optimal frame size //! Returns the optimal frame size
QSizeF preferredFrameSize() const; QSizeF preferredFrameSize() const;
@ -63,7 +65,7 @@ class GUI_EXPORT QgsFormAnnotation: public QgsAnnotation
/** /**
* Returns a new QgsFormAnnotation object. * Returns a new QgsFormAnnotation object.
*/ */
static QgsFormAnnotation *create() { return new QgsFormAnnotation(); } static QgsFormAnnotation *create() SIP_FACTORY { return new QgsFormAnnotation(); }
protected: protected:

15
tests/src/python/test_qgsannotation.py Normal file → Executable file
View File

@ -63,6 +63,11 @@ class TestQgsAnnotation(unittest.TestCase):
im = self.renderAnnotation(a, QPointF(20, 30)) im = self.renderAnnotation(a, QPointF(20, 30))
self.assertTrue(self.imageCheck('text_annotation', 'text_annotation', im)) self.assertTrue(self.imageCheck('text_annotation', 'text_annotation', im))
# check clone
clone = a.clone()
im = self.renderAnnotation(a, QPointF(20, 30))
self.assertTrue(self.imageCheck('text_annotation', 'text_annotation', im))
def testSvgAnnotation(self): def testSvgAnnotation(self):
""" test rendering a svg annotation""" """ test rendering a svg annotation"""
a = QgsSvgAnnotation() a = QgsSvgAnnotation()
@ -73,6 +78,11 @@ class TestQgsAnnotation(unittest.TestCase):
im = self.renderAnnotation(a, QPointF(20, 30)) im = self.renderAnnotation(a, QPointF(20, 30))
self.assertTrue(self.imageCheck('svg_annotation', 'svg_annotation', im)) self.assertTrue(self.imageCheck('svg_annotation', 'svg_annotation', im))
# check clone
clone = a.clone()
im = self.renderAnnotation(a, QPointF(20, 30))
self.assertTrue(self.imageCheck('svg_annotation', 'svg_annotation', im))
def testHtmlAnnotation(self): def testHtmlAnnotation(self):
""" test rendering a html annotation""" """ test rendering a html annotation"""
a = QgsHtmlAnnotation() a = QgsHtmlAnnotation()
@ -83,6 +93,11 @@ class TestQgsAnnotation(unittest.TestCase):
im = self.renderAnnotation(a, QPointF(20, 30)) im = self.renderAnnotation(a, QPointF(20, 30))
self.assertTrue(self.imageCheck('html_annotation', 'html_annotation', im)) self.assertTrue(self.imageCheck('html_annotation', 'html_annotation', im))
# check clone
clone = a.clone()
im = self.renderAnnotation(a, QPointF(20, 30))
self.assertTrue(self.imageCheck('html_annotation', 'html_annotation', im))
def testHtmlAnnotationWithFeature(self): def testHtmlAnnotationWithFeature(self):
""" test rendering a html annotation with a feature""" """ test rendering a html annotation with a feature"""
layer = QgsVectorLayer("Point?crs=EPSG:3111&field=station:string&field=suburb:string", layer = QgsVectorLayer("Point?crs=EPSG:3111&field=station:string&field=suburb:string",