Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
First steps towards free-form graphics item layer
Based on a port from the downstream Kadas application's item layer
type

Kudos to @manisandro
  • Loading branch information
nyalldawson committed Aug 5, 2020
1 parent 463e8ee commit 9f943f7
Show file tree
Hide file tree
Showing 3 changed files with 405 additions and 0 deletions.
114 changes: 114 additions & 0 deletions python/core/auto_generated/annotations/qgsannotationlayer.sip.in
@@ -0,0 +1,114 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/annotations/qgsannotationlayer.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/





class QgsAnnotationItem
{
%Docstring
*************************************************************************

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. *

**************************************************************************
%End

%TypeHeaderCode
#include "qgsannotationlayer.h"
%End
public:

QgsAnnotationItem *clone();

QgsCoordinateReferenceSystem crs() const;

void render( QgsRenderContext &context, QgsFeedback *feedback );

};

class QgsAnnotationLayer : QgsMapLayer
{

%TypeHeaderCode
#include "qgsannotationlayer.h"
%End
public:


struct LayerOptions
{

explicit LayerOptions( const QgsCoordinateTransformContext &transformContext );
%Docstring
Constructor for LayerOptions.
%End

QgsCoordinateTransformContext transformContext;

};


QgsAnnotationLayer( const QString &name, const QgsAnnotationLayer::LayerOptions &options );

void addItem( QgsAnnotationItem *item );


const QMap<QString, QgsAnnotationItem *> &items() const;

void setOpacity( double opacity );
double opacity() const;


virtual QgsAnnotationLayer *clone() const /Factory/;


virtual QgsMapLayerRenderer *createMapRenderer( QgsRenderContext &rendererContext ) /Factory/;


virtual QgsRectangle extent() const;


virtual void setTransformContext( const QgsCoordinateTransformContext &ctx );


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 );

protected:

};

class QgsAnnotationLayerRenderer : QgsMapLayerRenderer
{

%TypeHeaderCode
#include "qgsannotationlayer.h"
%End
public:

QgsAnnotationLayerRenderer( QgsAnnotationLayer *layer, QgsRenderContext &context );
~QgsAnnotationLayerRenderer();
virtual QgsFeedback *feedback() const;

virtual bool render();


};

/************************************************************************
* This file has been generated automatically from *
* *
* src/core/annotations/qgsannotationlayer.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
173 changes: 173 additions & 0 deletions src/core/annotations/qgsannotationlayer.cpp
@@ -0,0 +1,173 @@
/***************************************************************************
qgsannotationlayer.cpp
------------------
copyright : (C) 2019 by Sandro Mani
email : smani at sourcepole dot ch
***************************************************************************/

/***************************************************************************
* *
* 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 "qgsannotationlayer.h"
#include "qgsfeedback.h"
#include <QUuid>

QgsAnnotationLayer::QgsAnnotationLayer( const QString &name, const LayerOptions &options )
: QgsMapLayer( QgsMapLayerType::AnnotationLayer, name )
, mTransformContext( options.transformContext )
{
mValid = true;
}

void QgsAnnotationLayer::addItem( QgsAnnotationItem *item )
{
mItems.insert( QUuid::createUuid().toString(), item );
}

#if 0
QgsAnnotationItem *QgsAnnotationItem::takeItem( const QString &itemId )
{
return mItems.take( itemId );
}
#endif

QgsAnnotationLayer *QgsAnnotationLayer::clone() const
{
QgsAnnotationLayer::LayerOptions options( mTransformContext );
std::unique_ptr< QgsAnnotationLayer > layer = qgis::make_unique< QgsAnnotationLayer >( name(), options );
QgsMapLayer::clone( layer.get() );

layer->setOpacity( opacity() );

for ( auto it = mItems.constBegin(); it != mItems.constEnd(); ++it )
{
layer->mItems.insert( it.key(), ( *it )->clone() );
}

return layer.release();
}

QgsMapLayerRenderer *QgsAnnotationLayer::createMapRenderer( QgsRenderContext &rendererContext )
{
return new QgsAnnotationLayerRenderer( this, rendererContext );
}

QgsRectangle QgsAnnotationLayer::extent() const
{
QgsRectangle rect;
for ( auto it = mItems.constBegin(); it != mItems.constEnd(); ++it )
{
#if 0
QgsCoordinateTransform trans( it->crs(), crs(), mTransformContext );
if ( rect.isNull() )
{
rect = trans.transform( item->boundingBox() );
}
else
{
rect.combineExtentWith( trans.transform( item->boundingBox() ) );
}
#endif
}
return rect;
}

void QgsAnnotationLayer::setTransformContext( const QgsCoordinateTransformContext &ctx )
{
mTransformContext = ctx;
}

#if 0
QString QgsAnnotationLayer::pickItem( const QgsRectangle &pickRect, const QgsMapSettings &mapSettings ) const
{
for ( auto it = mItems.begin(), itEnd = mItems.end(); it != itEnd; ++it )
{
QgsCoordinateTransform crst( mapSettings.destinationCrs(), it.value()->crs(), transformContext() );
if ( it.value()->intersects( crst.transform( pickRect ), mapSettings ) )
{
return it.key();
}
}
return QString();
}

QString QgsAnnotationLayer::pickItem( const QgsPointXY &mapPos, const QgsMapSettings &mapSettings ) const
{
QgsRenderContext renderContext = QgsRenderContext::fromMapSettings( mapSettings );
double radiusmm = QgsSettings().value( "/Map/searchRadiusMM", Qgis::DEFAULT_SEARCH_RADIUS_MM ).toDouble();
radiusmm = radiusmm > 0 ? radiusmm : Qgis::DEFAULT_SEARCH_RADIUS_MM;
double radiusmu = radiusmm * renderContext.scaleFactor() * renderContext.mapToPixel().mapUnitsPerPixel();
QgsRectangle filterRect;
filterRect.setXMinimum( mapPos.x() - radiusmu );
filterRect.setXMaximum( mapPos.x() + radiusmu );
filterRect.setYMinimum( mapPos.y() - radiusmu );
filterRect.setYMaximum( mapPos.y() + radiusmu );
return pickItem( filterRect, mapSettings );
}

QRectF QgsAnnotationLayer::margin() const
{
bool empty = true;
QRectF rect;
for ( const KadasMapItem *item : mItems )
{
if ( empty )
{
rect = item->margin();
}
else
{
rect = rect.united( item->margin() );
}
}
return rect;
}
#endif

QgsAnnotationLayerRenderer::QgsAnnotationLayerRenderer( QgsAnnotationLayer *layer, QgsRenderContext &context )
: QgsMapLayerRenderer( layer->id(), &context )
, mFeedback( qgis::make_unique< QgsFeedback >() )
{
// clone items from layer
const QMap< QString, QgsAnnotationItem * > items = layer->items();
mItems.reserve( items.size() );
for ( auto it = items.constBegin(); it != items.constEnd(); ++it )
{
if ( it.value() )
mItems << ( *it )->clone();
}

// std::sort( mItems.begin(), mItems.end(), []( QgsAnnotationItem * a, QgsAnnotationItem * b ) { return a->zIndex() < b->zIndex(); } );
}

QgsAnnotationLayerRenderer::~QgsAnnotationLayerRenderer()
{
qDeleteAll( mItems );
}

QgsFeedback *QgsAnnotationLayerRenderer::feedback() const
{
return mFeedback.get();
}

bool QgsAnnotationLayerRenderer::render()
{
QgsRenderContext &context = *renderContext();

for ( QgsAnnotationItem *item : qgis::as_const( mItems ) )
{
if ( mFeedback->isCanceled() )
break;


renderContext()->setCoordinateTransform( QgsCoordinateTransform( item->crs(), context.coordinateTransform().destinationCrs(), context.transformContext() ) );
item->render( context, mFeedback.get() );
}
return true;
}

0 comments on commit 9f943f7

Please sign in to comment.