Skip to content

Commit

Permalink
Basic storage and restore of annotation layers in projects
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Aug 5, 2020
1 parent 4c04254 commit c523063
Show file tree
Hide file tree
Showing 7 changed files with 249 additions and 11 deletions.
Expand Up @@ -63,12 +63,16 @@ Constructor for LayerOptions.
virtual QgsRectangle extent() const;



virtual void setTransformContext( const QgsCoordinateTransformContext &context );

virtual bool readXml( const QDomNode &layerNode, QgsReadWriteContext &context );

virtual bool writeSymbology( QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context, StyleCategories categories = AllStyleCategories ) const;
virtual bool readSymbology( const QDomNode &node, QString &errorMessage, QgsReadWriteContext &context, StyleCategories categories = AllStyleCategories );
virtual bool writeXml( QDomNode &layer_node, QDomDocument &doc, const QgsReadWriteContext &context ) const;

virtual bool writeSymbology( QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &, StyleCategories categories = AllStyleCategories ) const;

virtual bool readSymbology( const QDomNode &node, QString &errorMessage, QgsReadWriteContext &context, StyleCategories categories = AllStyleCategories );

virtual QgsDataProvider *dataProvider();

Expand Down
3 changes: 2 additions & 1 deletion src/app/qgslayertreeviewnocrsindicator.cpp
Expand Up @@ -21,6 +21,7 @@
#include "qgsvectorlayer.h"
#include "qgisapp.h"
#include "qgsprojectionselectiondialog.h"
#include "qgsannotationlayer.h"

QgsLayerTreeViewNoCrsIndicatorProvider::QgsLayerTreeViewNoCrsIndicatorProvider( QgsLayerTreeView *view )
: QgsLayerTreeViewIndicatorProvider( view )
Expand Down Expand Up @@ -50,7 +51,7 @@ void QgsLayerTreeViewNoCrsIndicatorProvider::onIndicatorClicked( const QModelInd

bool QgsLayerTreeViewNoCrsIndicatorProvider::acceptLayer( QgsMapLayer *layer )
{
return layer && layer->isValid() && layer->isSpatial() && !layer->crs().isValid();
return layer && layer->isValid() && layer->isSpatial() && !layer->crs().isValid() && !qobject_cast< QgsAnnotationLayer * >( layer );
}

QString QgsLayerTreeViewNoCrsIndicatorProvider::iconName( QgsMapLayer *layer )
Expand Down
90 changes: 90 additions & 0 deletions src/core/annotations/qgsannotationitem.cpp
Expand Up @@ -15,3 +15,93 @@
***************************************************************************/

#include "qgsannotationitem.h"
#include "qgssymbol.h"
#include "qgssymbollayerutils.h"


QgsAnnotationItem::QgsAnnotationItem( const QgsCoordinateReferenceSystem &crs )
: mCrs( crs )
{

}

QgsMarkerItem::QgsMarkerItem( QgsPointXY point, const QgsCoordinateReferenceSystem &crs )
: QgsAnnotationItem( crs )
, mPoint( point )
, mSymbol( qgis::make_unique< QgsMarkerSymbol >() )
{

}

QgsMarkerItem::~QgsMarkerItem() = default;

QString QgsMarkerItem::type() const
{
return QStringLiteral( "marker" );
}

void QgsMarkerItem::render( QgsRenderContext &context, QgsFeedback * )
{
QPointF pt;
if ( context.coordinateTransform().isValid() )
{
double x = mPoint.x();
double y = mPoint.y();
double z = 0.0;
context.coordinateTransform().transformInPlace( x, y, z );
pt = QPointF( x, y );
}
else
pt = mPoint.toQPointF();

context.mapToPixel().transformInPlace( pt.rx(), pt.ry() );

mSymbol->startRender( context );
mSymbol->renderPoint( pt, nullptr, context );
mSymbol->stopRender( context );
}

bool QgsMarkerItem::writeXml( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const
{
element.setAttribute( QStringLiteral( "x" ), qgsDoubleToString( mPoint.x() ) );
element.setAttribute( QStringLiteral( "y" ), qgsDoubleToString( mPoint.y() ) );
crs().writeXml( element, document );

element.appendChild( QgsSymbolLayerUtils::saveSymbol( QStringLiteral( "markerSymbol" ), mSymbol.get(), document, context ) );

return true;
}

QgsMarkerItem *QgsMarkerItem::create( QDomElement &element, const QgsReadWriteContext &context )
{
const double x = element.attribute( QStringLiteral( "x" ) ).toDouble();
const double y = element.attribute( QStringLiteral( "y" ) ).toDouble();

QgsCoordinateReferenceSystem crs;
crs.readXml( element );

std::unique_ptr< QgsMarkerItem > item = qgis::make_unique< QgsMarkerItem >( QgsPointXY( x, y ), crs );

const QDomElement symbolElem = element.firstChildElement( QStringLiteral( "symbol" ) );
if ( !symbolElem.isNull() )
item->setSymbol( QgsSymbolLayerUtils::loadSymbol< QgsMarkerSymbol >( symbolElem, context ) );

return item.release();
}

QgsMarkerItem *QgsMarkerItem::clone()
{
std::unique_ptr< QgsMarkerItem > item = qgis::make_unique< QgsMarkerItem >( mPoint, crs() );
item->setSymbol( mSymbol->clone() );
return item.release();
}

const QgsMarkerSymbol *QgsMarkerItem::symbol() const
{
return mSymbol.get();
}

void QgsMarkerItem::setSymbol( QgsMarkerSymbol *symbol )
{
mSymbol.reset( symbol );
}
52 changes: 50 additions & 2 deletions src/core/annotations/qgsannotationitem.h
Expand Up @@ -23,19 +23,67 @@
#include "qgsrendercontext.h"

class QgsFeedback;
class QgsMarkerSymbol;

class CORE_EXPORT QgsAnnotationItem
{
public:

QgsAnnotationItem *clone() { return nullptr; }
QgsAnnotationItem( const QgsCoordinateReferenceSystem &crs );

#ifndef SIP_RUN
QgsAnnotationItem( const QgsAnnotationItem &other ) = delete;
QgsAnnotationItem &operator=( const QgsAnnotationItem &other ) = delete;
#endif

virtual ~QgsAnnotationItem() = default;

virtual QgsAnnotationItem *clone() = 0 SIP_FACTORY;
virtual QString type() const = 0;

QgsCoordinateReferenceSystem crs() const { return QgsCoordinateReferenceSystem(); }

void render( QgsRenderContext &context, QgsFeedback *feedback ) {}
virtual void render( QgsRenderContext &context, QgsFeedback *feedback ) = 0;
virtual bool writeXml( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const = 0;

int zIndex() const { return 0; }

private:

QgsCoordinateReferenceSystem mCrs;

#ifdef SIP_RUN
QgsAnnotationItem( const QgsAnnotationItem &other );
#endif

};

class CORE_EXPORT QgsMarkerItem : public QgsAnnotationItem
{
public:

QgsMarkerItem( QgsPointXY point, const QgsCoordinateReferenceSystem &crs );
~QgsMarkerItem() override;

QString type() const override;
void render( QgsRenderContext &context, QgsFeedback *feedback ) override;
bool writeXml( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const override;
static QgsMarkerItem *create( QDomElement &element, const QgsReadWriteContext &context ) SIP_FACTORY;

QgsMarkerItem *clone() override SIP_FACTORY;

const QgsMarkerSymbol *symbol() const;
void setSymbol( QgsMarkerSymbol *symbol SIP_TRANSFER );

private:

QgsPointXY mPoint;
std::unique_ptr< QgsMarkerSymbol > mSymbol;

#ifdef SIP_RUN
QgsMarkerItem( const QgsMarkerItem &other );
#endif

};

#endif // QGSANNOTATIONITEM_H
90 changes: 90 additions & 0 deletions src/core/annotations/qgsannotationlayer.cpp
Expand Up @@ -17,6 +17,7 @@
#include "qgsannotationlayer.h"
#include "qgsannotationlayerrenderer.h"
#include "qgsannotationitem.h"
#include "qgslogger.h"
#include <QUuid>

QgsAnnotationLayer::QgsAnnotationLayer( const QString &name, const LayerOptions &options )
Expand Down Expand Up @@ -93,6 +94,95 @@ void QgsAnnotationLayer::setTransformContext( const QgsCoordinateTransformContex
mDataProvider->setTransformContext( context );
}

bool QgsAnnotationLayer::readXml( const QDomNode &layerNode, QgsReadWriteContext &context )
{
if ( mReadFlags & QgsMapLayer::FlagDontResolveLayers )
{
return false;
}

qDeleteAll( mItems );
mItems.clear();

QDomNodeList itemsElements = layerNode.toElement().elementsByTagName( QStringLiteral( "items" ) );
if ( itemsElements.size() == 0 )
return false;

QDomNodeList items = itemsElements.at( 0 ).childNodes();
for ( int i = 0; i < items.size(); ++i )
{
QDomElement itemElement = items.at( i ).toElement();
const QString id = itemElement.attribute( QStringLiteral( "id" ) );
const QString type = itemElement.attribute( QStringLiteral( "type" ) );
if ( type == "marker" )
{
std::unique_ptr< QgsMarkerItem > marker( QgsMarkerItem::create( itemElement, context ) );
mItems.insert( id, marker.release() );
}
}

QString errorMsg;
readSymbology( layerNode, errorMsg, context );

return mValid;
}

bool QgsAnnotationLayer::writeXml( QDomNode &layer_node, QDomDocument &doc, const QgsReadWriteContext &context ) const
{
// first get the layer element so that we can append the type attribute
QDomElement mapLayerNode = layer_node.toElement();

if ( mapLayerNode.isNull() || ( QLatin1String( "maplayer" ) != mapLayerNode.nodeName() ) )
{
QgsDebugMsgLevel( QStringLiteral( "can't find <maplayer>" ), 2 );
return false;
}

mapLayerNode.setAttribute( QStringLiteral( "type" ), QStringLiteral( "annotation" ) );

QDomElement itemsElement = doc.createElement( "items" );
for ( auto it = mItems.constBegin(); it != mItems.constEnd(); ++it )
{
QDomElement itemElement = doc.createElement( "item" );
itemElement.setAttribute( QStringLiteral( "type" ), ( *it )->type() );
itemElement.setAttribute( QStringLiteral( "id" ), it.key() );
( *it )->writeXml( itemElement, doc, context );
itemsElement.appendChild( itemElement );
}
mapLayerNode.appendChild( itemsElement );

// renderer specific settings
QString errorMsg;
return writeSymbology( layer_node, doc, errorMsg, context );
}

bool QgsAnnotationLayer::writeSymbology( QDomNode &node, QDomDocument &doc, QString &, const QgsReadWriteContext &, QgsMapLayer::StyleCategories categories ) const
{
// add the layer opacity
if ( categories.testFlag( Rendering ) )
{
QDomElement layerOpacityElem = doc.createElement( QStringLiteral( "layerOpacity" ) );
QDomText layerOpacityText = doc.createTextNode( QString::number( opacity() ) );
layerOpacityElem.appendChild( layerOpacityText );
node.appendChild( layerOpacityElem );
}
return true;
}

bool QgsAnnotationLayer::readSymbology( const QDomNode &node, QString &, QgsReadWriteContext &, QgsMapLayer::StyleCategories categories )
{
if ( categories.testFlag( Rendering ) )
{
QDomNode layerOpacityNode = node.namedItem( QStringLiteral( "layerOpacity" ) );
if ( !layerOpacityNode.isNull() )
{
QDomElement e = layerOpacityNode.toElement();
setOpacity( e.text().toDouble() );
}
}
return true;
}

QgsDataProvider *QgsAnnotationLayer::dataProvider()
{
return mDataProvider.get();
Expand Down
10 changes: 5 additions & 5 deletions src/core/annotations/qgsannotationlayer.h
Expand Up @@ -77,12 +77,12 @@ class CORE_EXPORT QgsAnnotationLayer : public QgsMapLayer
virtual QString pickItem( const QgsRectangle &pickRect, const QgsMapSettings &mapSettings ) const;
QString pickItem( const QgsPointXY &mapPos, const QgsMapSettings &mapSettings ) const;
#endif
void setTransformContext( const QgsCoordinateTransformContext &context ) override;

bool writeSymbology( QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context, StyleCategories categories = AllStyleCategories ) const override { return true; }
bool readSymbology( const QDomNode &node, QString &errorMessage, QgsReadWriteContext &context, StyleCategories categories = AllStyleCategories ) override { return true; }


void setTransformContext( const QgsCoordinateTransformContext &context ) override;
bool readXml( const QDomNode &layerNode, QgsReadWriteContext &context ) override;
bool writeXml( QDomNode &layer_node, QDomDocument &doc, const QgsReadWriteContext &context ) const override;
bool writeSymbology( QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &, StyleCategories categories = AllStyleCategories ) const override;
bool readSymbology( const QDomNode &node, QString &errorMessage, QgsReadWriteContext &context, StyleCategories categories = AllStyleCategories ) override;
QgsDataProvider *dataProvider() override;
const QgsDataProvider *dataProvider() const override SIP_SKIP;

Expand Down
7 changes: 6 additions & 1 deletion src/core/qgsproject.cpp
Expand Up @@ -62,6 +62,7 @@
#include "qgsprojecttimesettings.h"
#include "qgsvectortilelayer.h"
#include "qgsruntimeprofiler.h"
#include "qgsannotationlayer.h"

#include <algorithm>
#include <QApplication>
Expand Down Expand Up @@ -1140,7 +1141,11 @@ bool QgsProject::addLayer( const QDomElement &layerElem, QList<QDomNode> &broken
QString typeName = layerElem.attribute( QStringLiteral( "name" ) );
mapLayer.reset( QgsApplication::pluginLayerRegistry()->createLayer( typeName ) );
}

else if ( type == QLatin1String( "annotation" ) )
{
QgsAnnotationLayer::LayerOptions options( mTransformContext );
mapLayer = qgis::make_unique<QgsAnnotationLayer>( QString(), options );
}
if ( !mapLayer )
{
QgsDebugMsg( QStringLiteral( "Unable to create layer" ) );
Expand Down

0 comments on commit c523063

Please sign in to comment.