[QGIS Commit] r12769 - in trunk/qgis: python/core python/gui src/core/symbology-ng src/gui/symbology-ng

svn_qgis at osgeo.org svn_qgis at osgeo.org
Fri Jan 15 12:54:18 EST 2010


Author: wonder
Date: 2010-01-15 12:54:18 -0500 (Fri, 15 Jan 2010)
New Revision: 12769

Modified:
   trunk/qgis/python/core/symbology-ng-core.sip
   trunk/qgis/python/gui/symbology-ng-gui.sip
   trunk/qgis/src/core/symbology-ng/qgsrendererv2.cpp
   trunk/qgis/src/core/symbology-ng/qgsrendererv2registry.cpp
   trunk/qgis/src/core/symbology-ng/qgsrendererv2registry.h
   trunk/qgis/src/core/symbology-ng/qgssymbollayerv2registry.cpp
   trunk/qgis/src/core/symbology-ng/qgssymbollayerv2registry.h
   trunk/qgis/src/gui/symbology-ng/qgsrendererv2propertiesdialog.cpp
   trunk/qgis/src/gui/symbology-ng/qgssymbolv2propertiesdialog.cpp
Log:
symbology-ng: updates to symbol layer registry and renderer registry so that they can be used from python.
Added wrappers for these two registries and their metadata classes.


Modified: trunk/qgis/python/core/symbology-ng-core.sip
===================================================================
--- trunk/qgis/python/core/symbology-ng-core.sip	2010-01-15 16:27:13 UTC (rev 12768)
+++ trunk/qgis/python/core/symbology-ng-core.sip	2010-01-15 17:54:18 UTC (rev 12769)
@@ -3,6 +3,15 @@
 
 typedef QList< QPair<QString, QPixmap> > QgsLegendSymbologyList;
 
+
+// this is a workaround for an error in generated code by SIP
+// to ensure it will recognize the class name
+%ModuleHeaderCode
+class QgsRendererV2Widget;
+class QgsSymbolLayerV2Widget;
+%End
+
+
 ///////////////
 
 /*
@@ -608,31 +617,25 @@
 
 //////////
 
-//typedef QgsSymbolLayerV2 * ( * QgsSymbolLayerV2CreateFunc )( const QgsStringMap& );
-//typedef QgsSymbolLayerV2Widget*( *QgsSymbolLayerV2WidgetFunc )();
+class QgsSymbolLayerV2Widget /External/;
 
-
-class QgsSymbolLayerV2Metadata
+class QgsSymbolLayerV2AbstractMetadata
 {
 %TypeHeaderCode
 #include <qgssymbollayerv2registry.h>
 %End
 
-public:
-  /** construct invalid metadata */
-  QgsSymbolLayerV2Metadata();
+  public:
+    /** construct metadata */
+    QgsSymbolLayerV2AbstractMetadata( QString name, QgsSymbolV2::SymbolType type );
 
-  /** construct metadata */
-  // TODO
-  //QgsSymbolLayerV2Metadata(QString name, QgsSymbolV2::SymbolType type,
-  //                         QgsSymbolLayerV2CreateFunc pfCreate,
-  //                         QgsSymbolLayerV2WidgetFunc pfWidget);
+    QString name() const;
+    QgsSymbolV2::SymbolType type() const;
 
-  QString name() const;
-  QgsSymbolV2::SymbolType type();
-  // TODO QgsSymbolLayerV2CreateFunc createFunction() const;
-  // TODO QgsSymbolLayerV2WidgetFunc widgetFunction() const;
-
+    /** create a symbol layer of this type given the map of properties. */
+    virtual QgsSymbolLayerV2* createSymbolLayer( const QgsStringMap& map ) = 0 /Factory/;
+    /** create widget for symbol layer of this type. Can return NULL if there's no GUI */
+    virtual QgsSymbolLayerV2Widget* createSymbolLayerWidget() /Factory/;
 };
 
 //////////
@@ -649,13 +652,16 @@
   static QgsSymbolLayerV2Registry* instance();
 
   //! return metadata for specified symbol layer
-  QgsSymbolLayerV2Metadata symbolLayerMetadata(QString name) const;
+  QgsSymbolLayerV2AbstractMetadata* symbolLayerMetadata(QString name) const;
 
   //! register a new symbol layer type
-  void addSymbolLayerType(const QgsSymbolLayerV2Metadata& metadata);
+  void addSymbolLayerType(QgsSymbolLayerV2AbstractMetadata* metadata /Transfer/);
 
   //! create a new instance of symbol layer given symbol layer name and properties
-  QgsSymbolLayerV2* createSymbolLayer(QString name, const QgsStringMap& properties) const /Factory/;
+  // TODO: disabled in PyQGIS because if used with symbol layer from Python
+  //   the combination of /Factory/ annotation QgsSymbolLayerV2AbstractMetadata::createSymbolLayer()
+  //   and here is deadly: results in premature deallocation of the symbol layer -> segfaults
+  //QgsSymbolLayerV2* createSymbolLayer(QString name, const QgsStringMap& properties) const /Factory/;
 
   //! return a list of available symbol layers for a specified symbol type
   QStringList symbolLayersForType(QgsSymbolV2::SymbolType type);
@@ -665,6 +671,7 @@
 
 protected:
   QgsSymbolLayerV2Registry();
+  ~QgsSymbolLayerV2Registry();
 
 };
 
@@ -787,3 +794,57 @@
   static void rendererV2toV1(QgsVectorLayer* layer);
 
 };
+
+////////////
+
+class QgsRendererV2Widget /External/;
+
+class QgsRendererV2AbstractMetadata
+{
+%TypeHeaderCode
+#include <qgsrendererv2registry.h>
+%End
+
+  public:
+    QgsRendererV2AbstractMetadata( QString name, QString visibleName, QString iconName = QString() );
+
+    QString name() const;
+    QString visibleName() const;
+    QString iconName() const;
+
+    /** Return new instance of the renderer given the DOM element. Returns NULL on error.
+     * Pure virtual function: must be implemented in derived classes.  */
+    virtual QgsFeatureRendererV2* createRenderer( QDomElement& elem ) = 0 /Factory/;
+    /** Return new instance of settings widget for the renderer. Returns NULL on error. */
+    virtual QgsRendererV2Widget* createRendererWidget( QgsVectorLayer* layer, QgsStyleV2* style, QgsFeatureRendererV2* renderer ) /Factory/;
+
+};
+
+
+class QgsRendererV2Registry
+{
+%TypeHeaderCode
+#include <qgsrendererv2registry.h>
+%End
+
+  public:
+
+    static QgsRendererV2Registry* instance();
+
+    //! add a renderer to registry. Takes ownership of the metadata object.
+    bool addRenderer( QgsRendererV2AbstractMetadata* metadata /Transfer/ );
+
+    //! remove renderer from registry
+    bool removeRenderer( QString rendererName );
+
+    //! get metadata for particular renderer. Returns NULL if not found in registry.
+    QgsRendererV2AbstractMetadata* rendererMetadata( QString rendererName );
+
+    //! return a list of available renderers
+    QStringList renderersList();
+
+  protected:
+    //! protected constructor
+    QgsRendererV2Registry();
+    ~QgsRendererV2Registry();
+};

Modified: trunk/qgis/python/gui/symbology-ng-gui.sip
===================================================================
--- trunk/qgis/python/gui/symbology-ng-gui.sip	2010-01-15 16:27:13 UTC (rev 12768)
+++ trunk/qgis/python/gui/symbology-ng-gui.sip	2010-01-15 17:54:18 UTC (rev 12769)
@@ -96,3 +96,38 @@
   void symbolModified();
 
 };
+
+
+
+class QgsSymbolLayerV2Widget : QWidget
+{
+%TypeHeaderCode
+#include <qgssymbollayerv2widget.h>
+%End
+
+  public:
+    QgsSymbolLayerV2Widget( QWidget* parent );
+    virtual ~QgsSymbolLayerV2Widget();
+
+    virtual void setSymbolLayer( QgsSymbolLayerV2* layer ) = 0;
+    virtual QgsSymbolLayerV2* symbolLayer() = 0;
+
+  signals:
+    void changed();
+};
+
+class QgsRendererV2Widget : QWidget
+{
+%TypeHeaderCode
+#include <qgsrendererv2widget.h>
+%End
+
+  public:
+    QgsRendererV2Widget( QgsVectorLayer* layer, QgsStyleV2* style );
+
+    virtual ~QgsRendererV2Widget();
+
+    //! return pointer to the renderer (no transfer of ownership)
+    virtual QgsFeatureRendererV2* renderer() = 0;
+
+};

Modified: trunk/qgis/src/core/symbology-ng/qgsrendererv2.cpp
===================================================================
--- trunk/qgis/src/core/symbology-ng/qgsrendererv2.cpp	2010-01-15 16:27:13 UTC (rev 12768)
+++ trunk/qgis/src/core/symbology-ng/qgsrendererv2.cpp	2010-01-15 17:54:18 UTC (rev 12769)
@@ -311,13 +311,11 @@
   // load renderer
   QString rendererType = element.attribute( "type" );
 
-  QgsRendererV2CreateFunc pfCreate = QgsRendererV2Registry::instance()->rendererMetadata( rendererType ).createFunction();
-
-  // unknown renderer type?
-  if ( pfCreate == NULL )
+  QgsRendererV2AbstractMetadata* m = QgsRendererV2Registry::instance()->rendererMetadata( rendererType );
+  if (m == NULL)
     return NULL;
 
-  QgsFeatureRendererV2* r = pfCreate( element );
+  QgsFeatureRendererV2* r = m->createRenderer( element );
   if ( r )
     r->setUsingSymbolLevels( element.attribute( "symbollevels", "0" ).toInt() );
 

Modified: trunk/qgis/src/core/symbology-ng/qgsrendererv2registry.cpp
===================================================================
--- trunk/qgis/src/core/symbology-ng/qgsrendererv2registry.cpp	2010-01-15 16:27:13 UTC (rev 12768)
+++ trunk/qgis/src/core/symbology-ng/qgsrendererv2registry.cpp	2010-01-15 17:54:18 UTC (rev 12769)
@@ -11,20 +11,29 @@
 QgsRendererV2Registry::QgsRendererV2Registry()
 {
   // add default renderers
-  addRenderer( QgsRendererV2Metadata( "singleSymbol",
+  addRenderer( new QgsRendererV2Metadata( "singleSymbol",
                                       QObject::tr( "Single Symbol" ),
                                       QgsSingleSymbolRendererV2::create,
                                       "rendererSingleSymbol.png" ) );
-  addRenderer( QgsRendererV2Metadata( "categorizedSymbol",
+  addRenderer( new QgsRendererV2Metadata( "categorizedSymbol",
                                       QObject::tr( "Categorized" ),
                                       QgsCategorizedSymbolRendererV2::create,
                                       "rendererCategorizedSymbol.png" ) );
-  addRenderer( QgsRendererV2Metadata( "graduatedSymbol",
+  addRenderer( new QgsRendererV2Metadata( "graduatedSymbol",
                                       QObject::tr( "Graduated" ),
                                       QgsGraduatedSymbolRendererV2::create,
                                       "rendererGraduatedSymbol.png" ) );
 }
 
+QgsRendererV2Registry::~QgsRendererV2Registry()
+{
+  foreach (QString name, mRenderers.keys())
+  {
+    delete mRenderers[name];
+  }
+  mRenderers.clear();
+}
+
 QgsRendererV2Registry* QgsRendererV2Registry::instance()
 {
   if ( !mInstance )
@@ -34,34 +43,32 @@
 }
 
 
-void QgsRendererV2Registry::addRenderer( const QgsRendererV2Metadata& metadata )
+bool QgsRendererV2Registry::addRenderer( QgsRendererV2AbstractMetadata* metadata )
 {
-  mRenderers[metadata.name()] = metadata;
-  mRenderersOrder << metadata.name();
+  if (metadata == NULL || mRenderers.contains(metadata->name()) )
+    return false;
+
+  mRenderers[metadata->name()] = metadata;
+  mRenderersOrder << metadata->name();
+  return true;
 }
 
 bool QgsRendererV2Registry::removeRenderer( QString rendererName )
 {
   if ( !mRenderers.contains( rendererName ) )
     return false;
+
+  delete mRenderers[rendererName];
   mRenderers.remove( rendererName );
   mRenderersOrder.removeAll( rendererName );
   return true;
 }
 
-QgsRendererV2Metadata QgsRendererV2Registry::rendererMetadata( QString rendererName )
+QgsRendererV2AbstractMetadata* QgsRendererV2Registry::rendererMetadata( QString rendererName )
 {
   return mRenderers.value( rendererName );
 }
 
-bool QgsRendererV2Registry::setRendererWidgetFunction( QString name, QgsRendererV2WidgetFunc f )
-{
-  if ( !mRenderers.contains( name ) )
-    return false;
-  mRenderers[name].setWidgetFunction( f );
-  return true;
-}
-
 QStringList QgsRendererV2Registry::renderersList()
 {
   return mRenderersOrder;

Modified: trunk/qgis/src/core/symbology-ng/qgsrendererv2registry.h
===================================================================
--- trunk/qgis/src/core/symbology-ng/qgsrendererv2registry.h	2010-01-15 16:27:13 UTC (rev 12768)
+++ trunk/qgis/src/core/symbology-ng/qgsrendererv2registry.h	2010-01-15 17:54:18 UTC (rev 12769)
@@ -10,15 +10,48 @@
 class QgsStyleV2;
 class QgsRendererV2Widget;
 
+/**
+ Stores metadata about one renderer class.
+
+ @note It's necessary to implement createRenderer() function.
+   In C++ you can use QgsRendererV2Metadata convenience class.
+ */
+class CORE_EXPORT QgsRendererV2AbstractMetadata
+{
+  public:
+    QgsRendererV2AbstractMetadata( QString name, QString visibleName, QString iconName = QString() )
+        : mName( name ), mVisibleName( visibleName ), mIconName( iconName ) {}
+
+    QString name() const { return mName; }
+    QString visibleName() const { return mVisibleName; }
+    QString iconName() const { return mIconName; }
+
+    /** Return new instance of the renderer given the DOM element. Returns NULL on error.
+     * Pure virtual function: must be implemented in derived classes.  */
+    virtual QgsFeatureRendererV2* createRenderer( QDomElement& elem ) = 0;
+    /** Return new instance of settings widget for the renderer. Returns NULL on error. */
+    virtual QgsRendererV2Widget* createRendererWidget( QgsVectorLayer* layer, QgsStyleV2* style, QgsFeatureRendererV2* renderer )
+      { return NULL; }
+
+  protected:
+    //! name used within QGIS for identification (the same what renderer's type() returns)
+    QString mName;
+    //! name visible for users (translatable)
+    QString mVisibleName;
+    //! icon to be shown in the renderer properties dialog
+    QString mIconName;
+};
+
+
 typedef QgsFeatureRendererV2*( *QgsRendererV2CreateFunc )( QDomElement& );
 typedef QgsRendererV2Widget*( *QgsRendererV2WidgetFunc )( QgsVectorLayer*, QgsStyleV2*, QgsFeatureRendererV2* );
 
-class CORE_EXPORT QgsRendererV2Metadata
+/**
+ Convenience metadata class that uses static functions to create renderer and its widget.
+ */
+class CORE_EXPORT QgsRendererV2Metadata : public QgsRendererV2AbstractMetadata
 {
   public:
-    /** construct invalid metadata */
-    QgsRendererV2Metadata()
-        : mName(), mVisibleName(), mCreateFunc( NULL ), mIconName(), mWidgetFunc( NULL ) {}
 
     /** construct metadata */
     QgsRendererV2Metadata( QString name,
@@ -26,25 +59,20 @@
                            QgsRendererV2CreateFunc pfCreate,
                            QString iconName = QString(),
                            QgsRendererV2WidgetFunc pfWidget = NULL )
-        : mName( name ), mVisibleName( visibleName ), mCreateFunc( pfCreate ), mIconName( iconName ), mWidgetFunc( pfWidget ) {}
+        : QgsRendererV2AbstractMetadata( name, visibleName, iconName ), mCreateFunc( pfCreate ), mWidgetFunc( pfWidget ) {}
 
-    QString name() const { return mName; }
-    QString visibleName() const { return mVisibleName; }
-    QString iconName() const { return mIconName; }
+    virtual QgsFeatureRendererV2* createRenderer( QDomElement& elem ) { return mCreateFunc ? mCreateFunc(elem):NULL; }
+    virtual QgsRendererV2Widget* createRendererWidget( QgsVectorLayer* layer, QgsStyleV2* style, QgsFeatureRendererV2* renderer )
+      { return mWidgetFunc ? mWidgetFunc(layer, style, renderer) : NULL; }
+
     QgsRendererV2CreateFunc createFunction() const { return mCreateFunc; }
     QgsRendererV2WidgetFunc widgetFunction() const { return mWidgetFunc; }
 
     void setWidgetFunction( QgsRendererV2WidgetFunc f ) { mWidgetFunc = f; }
 
   protected:
-    //! name used within QGIS for identification (the same what renderer's type() returns)
-    QString mName;
-    //! name visible for users (translatable)
-    QString mVisibleName;
     //! pointer to function that creates an instance of the renderer when loading project / style
     QgsRendererV2CreateFunc mCreateFunc;
-    //! icon to be shown in the renderer properties dialog
-    QString mIconName;
     //! pointer to function that creates a widget for configuration of renderer's params
     QgsRendererV2WidgetFunc mWidgetFunc;
 };
@@ -60,28 +88,26 @@
 
     static QgsRendererV2Registry* instance();
 
-    //! add a renderer to registry
-    void addRenderer( const QgsRendererV2Metadata& metadata );
+    //! add a renderer to registry. Takes ownership of the metadata object.
+    bool addRenderer( QgsRendererV2AbstractMetadata* metadata );
 
     //! remove renderer from registry
     bool removeRenderer( QString rendererName );
 
-    //! get factory method for particular renderer
-    QgsRendererV2Metadata rendererMetadata( QString rendererName );
+    //! get metadata for particular renderer. Returns NULL if not found in registry.
+    QgsRendererV2AbstractMetadata* rendererMetadata( QString rendererName );
 
-    //! assign a widget factory to particular renderer
-    bool setRendererWidgetFunction( QString name, QgsRendererV2WidgetFunc f );
-
     //! return a list of available renderers
     QStringList renderersList();
 
   protected:
     //! protected constructor
     QgsRendererV2Registry();
+    ~QgsRendererV2Registry();
 
     static QgsRendererV2Registry* mInstance;
 
-    QMap<QString, QgsRendererV2Metadata> mRenderers;
+    QMap<QString, QgsRendererV2AbstractMetadata*> mRenderers;
 
     //! list to keep order in which renderers have been added
     QStringList mRenderersOrder;

Modified: trunk/qgis/src/core/symbology-ng/qgssymbollayerv2registry.cpp
===================================================================
--- trunk/qgis/src/core/symbology-ng/qgssymbollayerv2registry.cpp	2010-01-15 16:27:13 UTC (rev 12768)
+++ trunk/qgis/src/core/symbology-ng/qgssymbollayerv2registry.cpp	2010-01-15 17:54:18 UTC (rev 12769)
@@ -10,41 +10,47 @@
 QgsSymbolLayerV2Registry::QgsSymbolLayerV2Registry()
 {
   // init registry with known symbol layers
-  addSymbolLayerType( QgsSymbolLayerV2Metadata( "SimpleLine", QgsSymbolV2::Line,
+  addSymbolLayerType( new QgsSymbolLayerV2Metadata( "SimpleLine", QgsSymbolV2::Line,
                       QgsSimpleLineSymbolLayerV2::create ) );
-  addSymbolLayerType( QgsSymbolLayerV2Metadata( "MarkerLine", QgsSymbolV2::Line,
+  addSymbolLayerType( new QgsSymbolLayerV2Metadata( "MarkerLine", QgsSymbolV2::Line,
                       QgsMarkerLineSymbolLayerV2::create ) );
-  addSymbolLayerType( QgsSymbolLayerV2Metadata( "LineDecoration", QgsSymbolV2::Line,
+  addSymbolLayerType( new QgsSymbolLayerV2Metadata( "LineDecoration", QgsSymbolV2::Line,
                       QgsLineDecorationSymbolLayerV2::create ) );
 
-  addSymbolLayerType( QgsSymbolLayerV2Metadata( "SimpleMarker", QgsSymbolV2::Marker,
+  addSymbolLayerType( new QgsSymbolLayerV2Metadata( "SimpleMarker", QgsSymbolV2::Marker,
                       QgsSimpleMarkerSymbolLayerV2::create ) );
-  addSymbolLayerType( QgsSymbolLayerV2Metadata( "SvgMarker", QgsSymbolV2::Marker,
+  addSymbolLayerType( new QgsSymbolLayerV2Metadata( "SvgMarker", QgsSymbolV2::Marker,
                       QgsSvgMarkerSymbolLayerV2::create ) );
 
-  addSymbolLayerType( QgsSymbolLayerV2Metadata( "SimpleFill", QgsSymbolV2::Fill,
+  addSymbolLayerType( new QgsSymbolLayerV2Metadata( "SimpleFill", QgsSymbolV2::Fill,
                       QgsSimpleFillSymbolLayerV2::create ) );
 }
 
-void QgsSymbolLayerV2Registry::addSymbolLayerType( const QgsSymbolLayerV2Metadata& metadata )
+QgsSymbolLayerV2Registry::~QgsSymbolLayerV2Registry()
 {
-  mMetadata[metadata.name()] = metadata;
+  foreach (QString name, mMetadata.keys())
+  {
+    delete mMetadata[name];
+  }
+  mMetadata.clear();
 }
 
-bool QgsSymbolLayerV2Registry::setLayerTypeWidgetFunction( QString name, QgsSymbolLayerV2WidgetFunc f )
+bool QgsSymbolLayerV2Registry::addSymbolLayerType( QgsSymbolLayerV2AbstractMetadata* metadata )
 {
-  if ( !mMetadata.contains( name ) )
+  if ( metadata == NULL || mMetadata.contains( metadata->name() ) )
     return false;
-  mMetadata[name].setWidgetFunction( f );
+
+  mMetadata[metadata->name()] = metadata;
   return true;
 }
 
-QgsSymbolLayerV2Metadata QgsSymbolLayerV2Registry::symbolLayerMetadata( QString name ) const
+
+QgsSymbolLayerV2AbstractMetadata* QgsSymbolLayerV2Registry::symbolLayerMetadata( QString name ) const
 {
   if ( mMetadata.contains( name ) )
     return mMetadata.value( name );
   else
-    return QgsSymbolLayerV2Metadata();
+    return NULL;
 }
 
 QgsSymbolLayerV2Registry* QgsSymbolLayerV2Registry::instance()
@@ -76,16 +82,16 @@
   if ( !mMetadata.contains( name ) )
     return NULL;
 
-  return mMetadata[name].createFunction()( properties );
+  return mMetadata[name]->createSymbolLayer( properties );
 }
 
 QStringList QgsSymbolLayerV2Registry::symbolLayersForType( QgsSymbolV2::SymbolType type )
 {
   QStringList lst;
-  QMap<QString, QgsSymbolLayerV2Metadata>::ConstIterator it = mMetadata.begin();
+  QMap<QString, QgsSymbolLayerV2AbstractMetadata*>::ConstIterator it = mMetadata.begin();
   for ( ; it != mMetadata.end(); ++it )
   {
-    if ( it->type() == type )
+    if ( (*it)->type() == type )
       lst.append( it.key() );
   }
   return lst;

Modified: trunk/qgis/src/core/symbology-ng/qgssymbollayerv2registry.h
===================================================================
--- trunk/qgis/src/core/symbology-ng/qgssymbollayerv2registry.h	2010-01-15 16:27:13 UTC (rev 12768)
+++ trunk/qgis/src/core/symbology-ng/qgssymbollayerv2registry.h	2010-01-15 17:54:18 UTC (rev 12769)
@@ -5,40 +5,60 @@
 #include "qgssymbolv2.h"
 #include "qgssymbollayerv2.h"
 
-typedef QgsSymbolLayerV2*( *QgsSymbolLayerV2CreateFunc )( const QgsStringMap& );
-typedef QgsSymbolLayerV2Widget*( *QgsSymbolLayerV2WidgetFunc )();
-
 /**
  Stores metadata about one symbol layer class.
+
+ @note It's necessary to implement createSymbolLayer() function.
+   In C++ you can use QgsSymbolLayerV2Metadata convenience class.
  */
-class CORE_EXPORT QgsSymbolLayerV2Metadata
+class CORE_EXPORT QgsSymbolLayerV2AbstractMetadata
 {
   public:
-    /** construct invalid metadata */
-    QgsSymbolLayerV2Metadata()
-        : mName(), mCreateFunc( NULL ), mWidgetFunc( NULL ) {}
+    QgsSymbolLayerV2AbstractMetadata( QString name, QgsSymbolV2::SymbolType type )
+        : mName( name ), mType( type ) {}
 
-    /** construct metadata */
-    QgsSymbolLayerV2Metadata( QString name, QgsSymbolV2::SymbolType type,
-                              QgsSymbolLayerV2CreateFunc pfCreate,
-                              QgsSymbolLayerV2WidgetFunc pfWidget = NULL )
-        : mName( name ), mType( type ), mCreateFunc( pfCreate ), mWidgetFunc( pfWidget ) {}
-
     QString name() const { return mName; }
     QgsSymbolV2::SymbolType type() const { return mType; }
-    QgsSymbolLayerV2CreateFunc createFunction() const { return mCreateFunc; }
-    QgsSymbolLayerV2WidgetFunc widgetFunction() const { return mWidgetFunc; }
 
-    void setWidgetFunction( QgsSymbolLayerV2WidgetFunc f ) { mWidgetFunc = f; }
+    /** create a symbol layer of this type given the map of properties. */
+    virtual QgsSymbolLayerV2* createSymbolLayer( const QgsStringMap& map ) = 0;
+    /** create widget for symbol layer of this type. Can return NULL if there's no GUI */
+    virtual QgsSymbolLayerV2Widget* createSymbolLayerWidget() { return NULL; }
 
   protected:
     QString mName;
     QgsSymbolV2::SymbolType mType;
-    QgsSymbolLayerV2CreateFunc mCreateFunc;
-    QgsSymbolLayerV2WidgetFunc mWidgetFunc;
 };
 
+typedef QgsSymbolLayerV2*( *QgsSymbolLayerV2CreateFunc )( const QgsStringMap& );
+typedef QgsSymbolLayerV2Widget*( *QgsSymbolLayerV2WidgetFunc )();
+
 /**
+ Convenience metadata class that uses static functions to create symbol layer and its widget.
+ */
+class CORE_EXPORT QgsSymbolLayerV2Metadata : public QgsSymbolLayerV2AbstractMetadata
+{
+public:
+  QgsSymbolLayerV2Metadata( QString name, QgsSymbolV2::SymbolType type,
+                            QgsSymbolLayerV2CreateFunc pfCreate,
+                            QgsSymbolLayerV2WidgetFunc pfWidget = NULL )
+      : QgsSymbolLayerV2AbstractMetadata( name, type ), mCreateFunc( pfCreate ), mWidgetFunc( pfWidget ) {}
+
+  QgsSymbolLayerV2CreateFunc createFunction() const { return mCreateFunc; }
+  QgsSymbolLayerV2WidgetFunc widgetFunction() const { return mWidgetFunc; }
+
+  void setWidgetFunction( QgsSymbolLayerV2WidgetFunc f ) { mWidgetFunc = f; }
+
+  virtual QgsSymbolLayerV2* createSymbolLayer( const QgsStringMap& map ) { return mCreateFunc ? mCreateFunc(map) : NULL; }
+  virtual QgsSymbolLayerV2Widget* createSymbolLayerWidget() { return mWidgetFunc ? mWidgetFunc() : NULL; }
+
+protected:
+  QgsSymbolLayerV2CreateFunc mCreateFunc;
+  QgsSymbolLayerV2WidgetFunc mWidgetFunc;
+};
+
+
+/**
  Registry of available symbol layer classes.
  Implemented as a singleton.
  */
@@ -49,15 +69,12 @@
     //! return the single instance of this class (instantiate it if not exists)
     static QgsSymbolLayerV2Registry* instance();
 
-    //! return metadata for specified symbol layer
-    QgsSymbolLayerV2Metadata symbolLayerMetadata( QString name ) const;
+    //! return metadata for specified symbol layer. Returns NULL if not found
+    QgsSymbolLayerV2AbstractMetadata* symbolLayerMetadata( QString name ) const;
 
-    //! register a new symbol layer type
-    void addSymbolLayerType( const QgsSymbolLayerV2Metadata& metadata );
+    //! register a new symbol layer type. Takes ownership of the metadata instance.
+    bool addSymbolLayerType( QgsSymbolLayerV2AbstractMetadata* metadata );
 
-    //! set layer type's widget function
-    bool setLayerTypeWidgetFunction( QString name, QgsSymbolLayerV2WidgetFunc f );
-
     //! create a new instance of symbol layer given symbol layer name and properties
     QgsSymbolLayerV2* createSymbolLayer( QString name, const QgsStringMap& properties = QgsStringMap() ) const;
 
@@ -69,9 +86,10 @@
 
   protected:
     QgsSymbolLayerV2Registry();
+    ~QgsSymbolLayerV2Registry();
 
     static QgsSymbolLayerV2Registry* mInstance;
-    QMap<QString, QgsSymbolLayerV2Metadata> mMetadata;
+    QMap<QString, QgsSymbolLayerV2AbstractMetadata*> mMetadata;
 
 };
 

Modified: trunk/qgis/src/gui/symbology-ng/qgsrendererv2propertiesdialog.cpp
===================================================================
--- trunk/qgis/src/gui/symbology-ng/qgsrendererv2propertiesdialog.cpp	2010-01-15 16:27:13 UTC (rev 12768)
+++ trunk/qgis/src/gui/symbology-ng/qgsrendererv2propertiesdialog.cpp	2010-01-15 17:54:18 UTC (rev 12769)
@@ -18,6 +18,33 @@
 #include <QKeyEvent>
 #include <QMessageBox>
 
+static bool _initRendererWidgetFunction(QString name, QgsRendererV2WidgetFunc f )
+{
+  QgsRendererV2Registry* reg = QgsRendererV2Registry::instance();
+  QgsRendererV2AbstractMetadata* am = reg->rendererMetadata( name );
+  if (am == NULL)
+    return false;
+  QgsRendererV2Metadata* m = dynamic_cast<QgsRendererV2Metadata*>(am);
+  if (m == NULL)
+    return false;
+
+  m->setWidgetFunction(f);
+  QgsDebugMsg("Set for "+name);
+  return true;
+}
+
+static void _initRendererWidgetFunctions()
+{
+  static bool initialized = false;
+  if (initialized)
+    return;
+
+  _initRendererWidgetFunction( "singleSymbol", QgsSingleSymbolRendererV2Widget::create );
+  _initRendererWidgetFunction( "categorizedSymbol", QgsCategorizedSymbolRendererV2Widget::create );
+  _initRendererWidgetFunction( "graduatedSymbol", QgsGraduatedSymbolRendererV2Widget::create );
+  initialized = true;
+}
+
 QgsRendererV2PropertiesDialog::QgsRendererV2PropertiesDialog( QgsVectorLayer* layer, QgsStyleV2* style, bool embedded )
     : mLayer( layer ), mStyle( style ), mActiveWidget( NULL )
 {
@@ -35,25 +62,20 @@
   connect( btnOldSymbology, SIGNAL( clicked() ), this, SLOT( useOldSymbology() ) );
 
   // initialize registry's widget functions
-  QgsRendererV2Registry* reg = QgsRendererV2Registry::instance();
-  if ( reg->rendererMetadata( "singleSymbol" ).widgetFunction() == NULL )
-  {
-    reg->setRendererWidgetFunction( "singleSymbol", QgsSingleSymbolRendererV2Widget::create );
-    reg->setRendererWidgetFunction( "categorizedSymbol", QgsCategorizedSymbolRendererV2Widget::create );
-    reg->setRendererWidgetFunction( "graduatedSymbol", QgsGraduatedSymbolRendererV2Widget::create );
-  }
+  _initRendererWidgetFunctions();
 
   QPixmap pix;
+  QgsRendererV2Registry* reg = QgsRendererV2Registry::instance();
   QStringList renderers = reg->renderersList();
   foreach( QString name, renderers )
   {
-    QgsRendererV2Metadata m = reg->rendererMetadata( name );
+    QgsRendererV2AbstractMetadata* m = reg->rendererMetadata( name );
 
-    QString iconPath = QgsApplication::defaultThemePath() + m.iconName();
+    QString iconPath = QgsApplication::defaultThemePath() + m->iconName();
     if ( !pix.load( iconPath, "png" ) )
       pix = QPixmap();
 
-    cboRenderers->addItem( QIcon( pix ), m.visibleName(), name );
+    cboRenderers->addItem( QIcon( pix ), m->visibleName(), name );
   }
 
   cboRenderers->setCurrentIndex( -1 ); // set no current renderer
@@ -105,12 +127,15 @@
     mActiveWidget = NULL;
   }
 
-  QgsRendererV2Metadata m = QgsRendererV2Registry::instance()->rendererMetadata( rendererName );
-  QgsRendererV2WidgetFunc fWidget = m.widgetFunction();
-  if ( fWidget != NULL )
+  QgsRendererV2Widget* w = NULL;
+  QgsRendererV2AbstractMetadata* m = QgsRendererV2Registry::instance()->rendererMetadata( rendererName );
+  if ( m != NULL )
+    w = m->createRendererWidget( mLayer, mStyle, mLayer->rendererV2()->clone() );
+
+  if ( w != NULL )
   {
     // instantiate the widget and set as active
-    mActiveWidget = fWidget( mLayer, mStyle, mLayer->rendererV2()->clone() );
+    mActiveWidget = w;
     stackedWidget->addWidget( mActiveWidget );
     stackedWidget->setCurrentWidget( mActiveWidget );
 

Modified: trunk/qgis/src/gui/symbology-ng/qgssymbolv2propertiesdialog.cpp
===================================================================
--- trunk/qgis/src/gui/symbology-ng/qgssymbolv2propertiesdialog.cpp	2010-01-15 16:27:13 UTC (rev 12768)
+++ trunk/qgis/src/gui/symbology-ng/qgssymbolv2propertiesdialog.cpp	2010-01-15 17:54:18 UTC (rev 12769)
@@ -10,10 +10,12 @@
 #include "qgssymbollayerv2registry.h"
 
 #include "qgsapplication.h"
+#include "qgslogger.h"
 
 #include "qgssymbollayerv2widget.h"
 #include "qgssymbolv2.h" //for the unit
 
+
 static const int SymbolLayerItemType = QStandardItem::UserType + 1;
 
 class SymbolLayerItem : public QStandardItem
@@ -68,6 +70,47 @@
 
 //////////
 
+static bool _initWidgetFunction( QString name, QgsSymbolLayerV2WidgetFunc f )
+{
+  QgsSymbolLayerV2Registry* reg = QgsSymbolLayerV2Registry::instance();
+
+  QgsSymbolLayerV2AbstractMetadata* abstractMetadata = reg->symbolLayerMetadata(name);
+  if (abstractMetadata == NULL)
+  {
+    QgsDebugMsg("Failed to find symbol layer's entry in registry: "+name);
+    return false;
+  }
+  QgsSymbolLayerV2Metadata* metadata = dynamic_cast<QgsSymbolLayerV2Metadata*>(abstractMetadata);
+  if (metadata == NULL)
+  {
+    QgsDebugMsg("Failed to cast symbol layer's metadata: "+name);
+    return false;
+  }
+  metadata->setWidgetFunction(f);
+  return true;
+}
+
+static void _initWidgetFunctions()
+{
+  static bool initialized = false;
+  if (initialized)
+    return;
+
+  _initWidgetFunction( "SimpleLine", QgsSimpleLineSymbolLayerV2Widget::create );
+  _initWidgetFunction( "MarkerLine", QgsMarkerLineSymbolLayerV2Widget::create );
+  _initWidgetFunction( "LineDecoration", QgsLineDecorationSymbolLayerV2Widget::create );
+
+  _initWidgetFunction( "SimpleMarker", QgsSimpleMarkerSymbolLayerV2Widget::create );
+  _initWidgetFunction( "SvgMarker", QgsSvgMarkerSymbolLayerV2Widget::create );
+
+  _initWidgetFunction( "SimpleFill", QgsSimpleFillSymbolLayerV2Widget::create );
+
+  initialized = true;
+}
+
+
+//////////
+
 QgsSymbolV2PropertiesDialog::QgsSymbolV2PropertiesDialog( QgsSymbolV2* symbol, QWidget* parent )
     : QDialog( parent ), mSymbol( symbol )
 {
@@ -82,15 +125,8 @@
 
   // set widget functions
   // (should be probably moved somewhere else)
-  QgsSymbolLayerV2Registry::instance()->setLayerTypeWidgetFunction( "SimpleLine", QgsSimpleLineSymbolLayerV2Widget::create );
-  QgsSymbolLayerV2Registry::instance()->setLayerTypeWidgetFunction( "MarkerLine", QgsMarkerLineSymbolLayerV2Widget::create );
-  QgsSymbolLayerV2Registry::instance()->setLayerTypeWidgetFunction( "LineDecoration", QgsLineDecorationSymbolLayerV2Widget::create );
+  _initWidgetFunctions();
 
-  QgsSymbolLayerV2Registry::instance()->setLayerTypeWidgetFunction( "SimpleMarker", QgsSimpleMarkerSymbolLayerV2Widget::create );
-  QgsSymbolLayerV2Registry::instance()->setLayerTypeWidgetFunction( "SvgMarker", QgsSvgMarkerSymbolLayerV2Widget::create );
-
-  QgsSymbolLayerV2Registry::instance()->setLayerTypeWidgetFunction( "SimpleFill", QgsSimpleFillSymbolLayerV2Widget::create );
-
   loadSymbol();
 
   connect( btnUp, SIGNAL( clicked() ), this, SLOT( moveLayerUp() ) );
@@ -198,11 +234,11 @@
   for ( int i = 0; i < layerTypes.count(); i++ )
   {
     QString layerType = layerTypes[i];
-    QgsSymbolLayerV2WidgetFunc f = pReg->symbolLayerMetadata( layerType ).widgetFunction();
-    if ( f == NULL ) // check whether the function is assigned
+    QgsSymbolLayerV2AbstractMetadata* am = pReg->symbolLayerMetadata( layerType );
+    if ( am == NULL ) // check whether the metadata is assigned
       continue;
 
-    QgsSymbolLayerV2Widget* w = f();
+    QgsSymbolLayerV2Widget* w = am->createSymbolLayerWidget();
     if ( w == NULL ) // check whether the function returns correct widget
       continue;
 
@@ -288,12 +324,12 @@
 
   // get creation function for new layer from registry
   QgsSymbolLayerV2Registry* pReg = QgsSymbolLayerV2Registry::instance();
-  QgsSymbolLayerV2CreateFunc f = pReg->symbolLayerMetadata( newLayerType ).createFunction();
-  if ( f == NULL ) // check whether the function is assigned
+  QgsSymbolLayerV2AbstractMetadata* am = pReg->symbolLayerMetadata( newLayerType );
+  if ( am == NULL ) // check whether the metadata is assigned
     return;
 
   // change layer to a new (with different type)
-  QgsSymbolLayerV2* newLayer = f( QgsStringMap() );
+  QgsSymbolLayerV2* newLayer = am->createSymbolLayer( QgsStringMap() );
   mSymbol->changeSymbolLayer( currentLayerIndex(), newLayer );
 
   updateSymbolLayerWidget( newLayer );



More information about the QGIS-commit mailing list