Skip to content

Commit

Permalink
Add registration of item types to QgsLayoutItemRegistry
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Jul 3, 2017
1 parent bfb4556 commit d23abf9
Show file tree
Hide file tree
Showing 6 changed files with 399 additions and 2 deletions.
106 changes: 106 additions & 0 deletions python/core/layout/qgslayoutitemregistry.sip
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,70 @@



class QgsLayoutItemAbstractMetadata
{
%Docstring
Stores metadata about one layout item class.
.. note::

In C++ you can use QgsSymbolLayerMetadata convenience class.
.. versionadded:: 3.0
%End

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

QgsLayoutItemAbstractMetadata( int type, const QString &visibleName );
%Docstring
Constructor for QgsLayoutItemAbstractMetadata with the specified class ``type``
and ``visibleName``.
%End

virtual ~QgsLayoutItemAbstractMetadata();

int type() const;
%Docstring
Returns the unique item type code for the layout item class.
:rtype: int
%End

QString visibleName() const;
%Docstring
Returns a translated, user visible name for the layout item class.
:rtype: str
%End

virtual QgsLayoutItem *createItem( QgsLayout *layout, const QVariantMap &properties ) = 0 /Factory/;
%Docstring
Creates a layout item of this class for a specified ``layout``, given the map of ``properties``.
:rtype: QgsLayoutItem
%End

virtual QWidget *createItemWidget() /Factory/;
%Docstring
Creates a configuration widget for layout items of this type. Can return None if no configuration GUI is required.
:rtype: QWidget
%End

virtual void resolvePaths( QVariantMap &properties, const QgsPathResolver &pathResolver, bool saving );
%Docstring
Resolve paths in the item's ``properties`` (if there are any paths).
When ``saving`` is true, paths are converted from absolute to relative,
when ``saving`` is false, paths are converted from relative to absolute.
This ensures that paths in project files can be relative, but in item
instances the paths are always absolute.
%End

};







class QgsLayoutItemRegistry : QObject
{
%Docstring
Expand Down Expand Up @@ -43,7 +107,49 @@ class QgsLayoutItemRegistry : QObject
QgsApplication.layoutItemRegistry().
%End

~QgsLayoutItemRegistry();


QgsLayoutItemAbstractMetadata *itemMetadata( int type ) const;
%Docstring
Returns the metadata for the specified item ``type``. Returns None if
a corresponding type was not found in the registry.
:rtype: QgsLayoutItemAbstractMetadata
%End

bool addLayoutItemType( QgsLayoutItemAbstractMetadata *metadata /Transfer/ );
%Docstring
Registers a new layout item type. Takes ownership of the metadata instance.
:rtype: bool
%End

QgsLayoutItem *createItem( int type, QgsLayout *layout, const QVariantMap &properties = QVariantMap() ) const /Factory/;
%Docstring
Creates a new instance of a layout item given the item ``type``, target ``layout`` and ``properties``.
:rtype: QgsLayoutItem
%End

QWidget *createItemWidget( int type ) const /Factory/;
%Docstring
Creates a new instance of a layout item configuration widget for the specified item ``type``.
:rtype: QWidget
%End

void resolvePaths( int type, QVariantMap &properties, const QgsPathResolver &pathResolver, bool saving ) const;
%Docstring
Resolve paths in properties of a particular symbol layer.
This normally means converting relative paths to absolute paths when loading
and converting absolute paths to relative paths when saving.
%End

QMap< int, QString> itemTypes() const;
%Docstring
Returns a map of available item types to translated name.
:rtype: QMap< int, str>
%End

private:
QgsLayoutItemRegistry( const QgsLayoutItemRegistry &rh );
};


Expand Down
2 changes: 1 addition & 1 deletion python/core/symbology-ng/qgssymbollayerregistry.sip
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ Create a symbol layer of this type given the map of properties.
Resolve paths in symbol layer's properties (if there are any paths).
When saving is true, paths are converted from absolute to relative,
when saving is false, paths are converted from relative to absolute.
This ensures that paths in project files are absolute, but in symbol layer
This ensures that paths in project files can be relative, but in symbol layer
instances the paths are always absolute
.. versionadded:: 3.0
%End
Expand Down
55 changes: 55 additions & 0 deletions src/core/layout/qgslayoutitemregistry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,58 @@ QgsLayoutItemRegistry::QgsLayoutItemRegistry( QObject *parent )
{

}

QgsLayoutItemRegistry::~QgsLayoutItemRegistry()
{
qDeleteAll( mMetadata );
}

QgsLayoutItemAbstractMetadata *QgsLayoutItemRegistry::itemMetadata( int type ) const
{
return mMetadata.value( type );
}

bool QgsLayoutItemRegistry::addLayoutItemType( QgsLayoutItemAbstractMetadata *metadata )
{
if ( !metadata || mMetadata.contains( metadata->type() ) )
return false;

mMetadata[metadata->type()] = metadata;
return true;
}

QgsLayoutItem *QgsLayoutItemRegistry::createItem( int type, QgsLayout *layout, const QVariantMap &properties ) const
{
if ( !mMetadata.contains( type ) )
return nullptr;

return mMetadata[type]->createItem( layout, properties );
}

QWidget *QgsLayoutItemRegistry::createItemWidget( int type ) const
{
if ( !mMetadata.contains( type ) )
return nullptr;

return mMetadata[type]->createItemWidget();
}

void QgsLayoutItemRegistry::resolvePaths( int type, QVariantMap &properties, const QgsPathResolver &pathResolver, bool saving ) const
{
if ( !mMetadata.contains( type ) )
return;

mMetadata[type]->resolvePaths( properties, pathResolver, saving );

}

QMap<int, QString> QgsLayoutItemRegistry::itemTypes() const
{
QMap<int, QString> types;
QMap<int, QgsLayoutItemAbstractMetadata *>::ConstIterator it = mMetadata.constBegin();
for ( ; it != mMetadata.constEnd(); ++it )
{
types.insert( it.key(), it.value()->visibleName() );
}
return types;
}
186 changes: 186 additions & 0 deletions src/core/layout/qgslayoutitemregistry.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,152 @@
#define QGSLAYOUTITEMREGISTRY_H

#include "qgis_core.h"
#include "qgis_sip.h"
#include "qgspathresolver.h"
#include <QGraphicsItem> //for QGraphicsItem::UserType
#include <functional>

class QgsLayout;
class QgsLayoutItem;

/**
* \ingroup core
* \brief Stores metadata about one layout item class.
* \note In C++ you can use QgsSymbolLayerMetadata convenience class.
* \since QGIS 3.0
*/
class CORE_EXPORT QgsLayoutItemAbstractMetadata
{
public:

/**
* Constructor for QgsLayoutItemAbstractMetadata with the specified class \a type
* and \a visibleName.
*/
QgsLayoutItemAbstractMetadata( int type, const QString &visibleName )
: mType( type )
, mVisibleName( visibleName )
{}

virtual ~QgsLayoutItemAbstractMetadata() = default;

/**
* Returns the unique item type code for the layout item class.
*/
int type() const { return mType; }

/**
* Returns a translated, user visible name for the layout item class.
*/
QString visibleName() const { return mVisibleName; }

/**
* Creates a layout item of this class for a specified \a layout, given the map of \a properties.
*/
virtual QgsLayoutItem *createItem( QgsLayout *layout, const QVariantMap &properties ) = 0 SIP_FACTORY;

/**
* Creates a configuration widget for layout items of this type. Can return nullptr if no configuration GUI is required.
*/
virtual QWidget *createItemWidget() SIP_FACTORY { return nullptr; }

/**
* Resolve paths in the item's \a properties (if there are any paths).
* When \a saving is true, paths are converted from absolute to relative,
* when \a saving is false, paths are converted from relative to absolute.
* This ensures that paths in project files can be relative, but in item
* instances the paths are always absolute.
*/
virtual void resolvePaths( QVariantMap &properties, const QgsPathResolver &pathResolver, bool saving )
{
Q_UNUSED( properties );
Q_UNUSED( pathResolver );
Q_UNUSED( saving );
}

private:

int mType = -1;
QString mVisibleName;
};

//! Layout item creation function
typedef std::function<QgsLayoutItem *( QgsLayout *, const QVariantMap & )> QgsLayoutItemCreateFunc SIP_SKIP;

//! Layout item configuration widget creation function
typedef std::function<QWidget *()> QgsLayoutItemWidgetFunc SIP_SKIP;

//! Layout item path resolver function
typedef std::function<void( QVariantMap &, const QgsPathResolver &, bool )> QgsLayoutItemPathResolverFunc SIP_SKIP;

#ifndef SIP_RUN

/**
* \ingroup core
* Convenience metadata class that uses static functions to create layout items and their configuration widgets.
* \since QGIS 3.0
* \note not available in Python bindings
*/
class CORE_EXPORT QgsLayoutItemMetadata : public QgsLayoutItemAbstractMetadata
{
public:

/**
* Constructor for QgsLayoutItemMetadata with the specified class \a type
* and \a visibleName, and function pointers for the various item and
* configuration widget creation functions.
*/
QgsLayoutItemMetadata( int type, const QString &visibleName,
QgsLayoutItemCreateFunc pfCreate,
QgsLayoutItemPathResolverFunc pfPathResolver = nullptr,
QgsLayoutItemWidgetFunc pfWidget = nullptr )
: QgsLayoutItemAbstractMetadata( type, visibleName )
, mCreateFunc( pfCreate )
, mWidgetFunc( pfWidget )
, mPathResolverFunc( pfPathResolver )
{}

/**
* Returns the classes' item creation function.
*/
QgsLayoutItemCreateFunc createFunction() const { return mCreateFunc; }

/**
* Returns the classes' configuration widget creation function.
* \see setWidgetFunction()
*/
QgsLayoutItemWidgetFunc widgetFunction() const { return mWidgetFunc; }

/**
* Returns the classes' path resolver function.
*/
QgsLayoutItemPathResolverFunc pathResolverFunction() const { return mPathResolverFunc; }

/**
* Sets the classes' configuration widget creation \a function.
* \see widgetFunction()
*/
void setWidgetFunction( QgsLayoutItemWidgetFunc function ) { mWidgetFunc = function; }

virtual QgsLayoutItem *createItem( QgsLayout *layout, const QVariantMap &properties ) override { return mCreateFunc ? mCreateFunc( layout, properties ) : nullptr; }
virtual QWidget *createItemWidget() override { return mWidgetFunc ? mWidgetFunc() : nullptr; }
virtual void resolvePaths( QVariantMap &properties, const QgsPathResolver &pathResolver, bool saving ) override
{
if ( mPathResolverFunc )
mPathResolverFunc( properties, pathResolver, saving );
}

protected:
QgsLayoutItemCreateFunc mCreateFunc = nullptr;
QgsLayoutItemWidgetFunc mWidgetFunc = nullptr;
QgsLayoutItemPathResolverFunc mPathResolverFunc = nullptr;

};

#endif



/**
* \ingroup core
* \class QgsLayoutItemRegistry
Expand Down Expand Up @@ -57,8 +199,52 @@ class CORE_EXPORT QgsLayoutItemRegistry : public QObject
*/
QgsLayoutItemRegistry( QObject *parent = nullptr );

~QgsLayoutItemRegistry();

//! QgsLayoutItemRegistry cannot be copied.
QgsLayoutItemRegistry( const QgsLayoutItemRegistry &rh ) = delete;
//! QgsLayoutItemRegistryQgsLayoutItemRegistry cannot be copied.
QgsLayoutItemRegistry &operator=( const QgsLayoutItemRegistry &rh ) = delete;

/**
* Returns the metadata for the specified item \a type. Returns nullptr if
* a corresponding type was not found in the registry.
*/
QgsLayoutItemAbstractMetadata *itemMetadata( int type ) const;

/**
* Registers a new layout item type. Takes ownership of the metadata instance.
*/
bool addLayoutItemType( QgsLayoutItemAbstractMetadata *metadata SIP_TRANSFER );

/**
* Creates a new instance of a layout item given the item \a type, target \a layout and \a properties.
*/
QgsLayoutItem *createItem( int type, QgsLayout *layout, const QVariantMap &properties = QVariantMap() ) const SIP_FACTORY;

/**
* Creates a new instance of a layout item configuration widget for the specified item \a type.
*/
QWidget *createItemWidget( int type ) const SIP_FACTORY;

/**
* Resolve paths in properties of a particular symbol layer.
* This normally means converting relative paths to absolute paths when loading
* and converting absolute paths to relative paths when saving.
*/
void resolvePaths( int type, QVariantMap &properties, const QgsPathResolver &pathResolver, bool saving ) const;

/**
* Returns a map of available item types to translated name.
*/
QMap< int, QString> itemTypes() const;

private:
#ifdef SIP_RUN
QgsLayoutItemRegistry( const QgsLayoutItemRegistry &rh );
#endif

QMap<int, QgsLayoutItemAbstractMetadata *> mMetadata;

};

Expand Down
Loading

0 comments on commit d23abf9

Please sign in to comment.