[QGIS Commit] r11291 - in branches/symbology-ng-branch/src: core plugins/labeling

svn_qgis at osgeo.org svn_qgis at osgeo.org
Sat Aug 8 12:02:43 EDT 2009


Author: wonder
Date: 2009-08-08 12:02:41 -0400 (Sat, 08 Aug 2009)
New Revision: 11291

Modified:
   branches/symbology-ng-branch/src/core/qgsvectorlayer.cpp
   branches/symbology-ng-branch/src/core/qgsvectorlayer.h
   branches/symbology-ng-branch/src/plugins/labeling/labeling.cpp
   branches/symbology-ng-branch/src/plugins/labeling/labeling.h
   branches/symbology-ng-branch/src/plugins/labeling/labelinggui.cpp
   branches/symbology-ng-branch/src/plugins/labeling/labelinggui.h
   branches/symbology-ng-branch/src/plugins/labeling/pallabeling.cpp
   branches/symbology-ng-branch/src/plugins/labeling/pallabeling.h
Log:
Labeling hooks replaced with labeling engine interface (nicer solution).
Added loading/saving of labeling into the project files (using layer's custom properties)


Modified: branches/symbology-ng-branch/src/core/qgsvectorlayer.cpp
===================================================================
--- branches/symbology-ng-branch/src/core/qgsvectorlayer.cpp	2009-08-07 11:58:50 UTC (rev 11290)
+++ branches/symbology-ng-branch/src/core/qgsvectorlayer.cpp	2009-08-08 16:02:41 UTC (rev 11291)
@@ -111,8 +111,7 @@
     mActiveCommand( NULL ),
     mRendererV2( NULL ),
     mUsingRendererV2( false ),
-    mLabelingPrepareLayerHook( NULL ),
-    mLabelingRegisterFeatureHook( NULL )
+    mLabelingEngine( NULL )
 {
   mActions = new QgsAttributeAction;
 
@@ -687,7 +686,7 @@
     mRendererV2->renderFeature(fet, rendererContext);
 
     if ( labeling )
-      mLabelingRegisterFeatureHook(fet, mLabelingLayerContext);
+      mLabelingEngine->registerFeature(this, fet);
   }
 
   mRendererV2->stopRender(rendererContext);
@@ -712,7 +711,7 @@
     features[sym].append( fet );
 
     if ( labeling )
-      mLabelingRegisterFeatureHook(fet, mLabelingLayerContext);
+      mLabelingEngine->registerFeature(this, fet);
   }
 
   // find out the order
@@ -773,10 +772,10 @@
       QgsDebugMsg("attrs: " + QString::number(attributes[0]));
 
     bool labeling = FALSE;
-    if ( mLabelingPrepareLayerHook && mLabelingRegisterFeatureHook )
+    if ( mLabelingEngine )
     {
       int attrIndex;
-      if (mLabelingPrepareLayerHook(mLabelingContext, mLabelingLayerContext, attrIndex))
+      if (mLabelingEngine->prepareLayer(this, attrIndex))
       {
         if (!attributes.contains(attrIndex))
           attributes << attrIndex;
@@ -831,10 +830,10 @@
     QgsAttributeList attributes = mRenderer->classificationAttributes();
 
     bool labeling = FALSE;
-    if (mLabelingPrepareLayerHook)
+    if (mLabelingEngine)
     {
       int attrIndex;
-      if (mLabelingPrepareLayerHook(mLabelingContext, mLabelingLayerContext, attrIndex))
+      if (mLabelingEngine->prepareLayer(this, attrIndex))
       {
         if (!attributes.contains(attrIndex))
           attributes << attrIndex;
@@ -911,9 +910,9 @@
           rendererContext.rasterScaleFactor(),
           rendererContext.drawEditingInformation() );
 
-        if (labeling && mLabelingRegisterFeatureHook)
+        if (labeling && mLabelingEngine)
         {
-          mLabelingRegisterFeatureHook(fet, mLabelingLayerContext);
+          mLabelingEngine->registerFeature(this, fet);
         }
 
         ++featureCount;
@@ -2229,15 +2228,9 @@
   return mLabelOn;
 }
 
-void QgsVectorLayer::setLabelingHooks(LabelingPrepareLayerHook prepareLayerHook,
-                                      LabelingRegisterFeatureHook registerFeatureHook,
-                                      void* context,
-                                      void* layerContext)
+void QgsVectorLayer::setLabelingEngine(QgsLabelingEngineInterface* engine)
 {
-  mLabelingPrepareLayerHook = prepareLayerHook;
-  mLabelingRegisterFeatureHook = registerFeatureHook;
-  mLabelingContext = context;
-  mLabelingLayerContext = layerContext;
+  mLabelingEngine = engine;
 }
 
 

Modified: branches/symbology-ng-branch/src/core/qgsvectorlayer.h
===================================================================
--- branches/symbology-ng-branch/src/core/qgsvectorlayer.h	2009-08-07 11:58:50 UTC (rev 11290)
+++ branches/symbology-ng-branch/src/core/qgsvectorlayer.h	2009-08-08 16:02:41 UTC (rev 11291)
@@ -53,10 +53,18 @@
 typedef QSet<int> QgsFeatureIds;
 typedef QSet<int> QgsAttributeIds;
 
-typedef int (*LabelingPrepareLayerHook)(void*, void*, int&);
-typedef void (*LabelingRegisterFeatureHook)(QgsFeature&, void*);
+class QgsLabelingEngineInterface
+{
+public:
+  virtual ~QgsLabelingEngineInterface() {}
+  virtual int prepareLayer(QgsVectorLayer* layer, int& attrIndex) = 0;
+  virtual void registerFeature(QgsVectorLayer* layer, QgsFeature& feat) = 0;
+  //void calculateLabeling() = 0;
+  //void drawLabeling(QgsRenderContext& context) = 0;
+};
 
 
+
 /** \ingroup core
  * Vector layer backed by a data source provider.
  */
@@ -348,10 +356,7 @@
     /** Label is on */
     bool hasLabelsEnabled( void ) const;
 
-    void setLabelingHooks(LabelingPrepareLayerHook prepareLayerHook,
-                          LabelingRegisterFeatureHook registerFeatureHook,
-                          void* mLabelingContext,
-                          void* mLabelingLayerContext);
+    void setLabelingEngine(QgsLabelingEngineInterface* engine);
 
     /** Returns true if the provider is in editing mode */
     virtual bool isEditable() const;
@@ -733,10 +738,7 @@
     /** Label */
     QgsLabel *mLabel;
 
-    LabelingPrepareLayerHook mLabelingPrepareLayerHook;
-    LabelingRegisterFeatureHook mLabelingRegisterFeatureHook;
-    void* mLabelingContext;
-    void* mLabelingLayerContext;
+    QgsLabelingEngineInterface* mLabelingEngine;
 
 
     /** Display labels */

Modified: branches/symbology-ng-branch/src/plugins/labeling/labeling.cpp
===================================================================
--- branches/symbology-ng-branch/src/plugins/labeling/labeling.cpp	2009-08-07 11:58:50 UTC (rev 11290)
+++ branches/symbology-ng-branch/src/plugins/labeling/labeling.cpp	2009-08-08 16:02:41 UTC (rev 11291)
@@ -23,6 +23,7 @@
 #include <qgisgui.h>
 #include <qgsmapcanvas.h>
 #include <qgsvectorlayer.h>
+#include <qgsmaplayerregistry.h>
 
 #include "labeling.h"
 #include "labelinggui.h"
@@ -124,6 +125,20 @@
 
   connect( mQGisIface->mapCanvas(), SIGNAL( renderComplete( QPainter * ) ), this, SLOT( doLabeling( QPainter * ) ) );
 
+  // connect to newly added layers so the labeling hook will be set up
+  connect( QgsMapLayerRegistry::instance(), SIGNAL(layerWasAdded(QgsMapLayer*)), this, SLOT(layerWasAdded(QgsMapLayer*)) );
+
+  // add labeling hooks to all existing layers
+  QMap<QString, QgsMapLayer*>& layers = QgsMapLayerRegistry::instance()->mapLayers();
+  for (QMap<QString, QgsMapLayer*>::iterator it = layers.begin(); it != layers.end(); ++it)
+  {
+    QgsMapLayer* layer = it.value();
+    if (layer->type() == QgsMapLayer::VectorLayer)
+    {
+      QgsVectorLayer* vlayer = dynamic_cast<QgsVectorLayer*>(layer);
+      vlayer->setLabelingEngine(mLBL);
+    }
+  }
 }
 
 void Labeling::doLabeling( QPainter * painter )
@@ -143,15 +158,14 @@
     QMessageBox::warning(mQGisIface->mainWindow(), "Labeling", "Please select a vector layer first.");
     return;
   }
-  //QgsVectorLayer* vlayer = static_cast<QgsVectorLayer*>(layer);
+  QgsVectorLayer* vlayer = dynamic_cast<QgsVectorLayer*>(layer);
 
-  LabelingGui myPluginGui( mLBL, layer->getLayerID(), mQGisIface->mainWindow() );
+  LabelingGui myPluginGui( mLBL, vlayer, mQGisIface->mainWindow() );
 
   if (myPluginGui.exec())
   {
-    // alter labeling
-    mLBL->removeLayer(layer->getLayerID());
-    mLBL->addLayer( myPluginGui.layerSettings() );
+    // alter labeling - save the changes
+    myPluginGui.layerSettings().writeToLayer(vlayer);
 
     // trigger refresh
     mQGisIface->mapCanvas()->refresh();
@@ -170,6 +184,21 @@
   mQGisIface->mapCanvas()->unsetMapTool(mTool);
   delete mTool;
 
+  // remove labeling hook from all layers!
+  QMap<QString, QgsMapLayer*>& layers = QgsMapLayerRegistry::instance()->mapLayers();
+  for (QMap<QString, QgsMapLayer*>::iterator it = layers.begin(); it != layers.end(); ++it)
+  {
+    QgsMapLayer* layer = it.value();
+    if (layer->type() == QgsMapLayer::VectorLayer)
+    {
+      QgsVectorLayer* vlayer = dynamic_cast<QgsVectorLayer*>(layer);
+      vlayer->setLabelingEngine(NULL);
+    }
+  }
+
+  disconnect( QgsMapLayerRegistry::instance(), SIGNAL(layerWasAdded(QgsMapLayer*)), this, SLOT(layerWasAdded(QgsMapLayer*)) );
+  disconnect( mQGisIface->mapCanvas(), SIGNAL( renderComplete( QPainter * ) ), this, SLOT( doLabeling( QPainter * ) ) );
+
   // remove the GUI
   mQGisIface->removePluginMenu( "&Labeling", mQActionPointer );
   mQGisIface->removeToolBarIcon( mQActionPointer );
@@ -181,7 +210,17 @@
   delete mLBL;
 }
 
+void Labeling::layerWasAdded( QgsMapLayer* layer )
+{
+  if (layer->type() != QgsMapLayer::VectorLayer)
+    return; // not interested in rasters
 
+  QgsVectorLayer* vlayer = dynamic_cast<QgsVectorLayer*>(layer);
+  // add labeling hook for the newly added layer
+  vlayer->setLabelingEngine(mLBL);
+}
+
+
 //////////////////////////////////////////////////////////////////////////
 //
 //

Modified: branches/symbology-ng-branch/src/plugins/labeling/labeling.h
===================================================================
--- branches/symbology-ng-branch/src/plugins/labeling/labeling.h	2009-08-07 11:58:50 UTC (rev 11290)
+++ branches/symbology-ng-branch/src/plugins/labeling/labeling.h	2009-08-08 16:02:41 UTC (rev 11291)
@@ -24,6 +24,8 @@
 //QGIS includes
 #include "../qgisplugin.h"
 
+#include "qgsmaplayer.h" // for MOC
+
 //forward declarations
 class QAction;
 class QPainter;
@@ -62,6 +64,8 @@
     //! start labeling map tool
     void setTool();
 
+    void layerWasAdded( QgsMapLayer* theMapLayer );
+
   private:
 
     //! Pointer to the QGIS interface object

Modified: branches/symbology-ng-branch/src/plugins/labeling/labelinggui.cpp
===================================================================
--- branches/symbology-ng-branch/src/plugins/labeling/labelinggui.cpp	2009-08-07 11:58:50 UTC (rev 11290)
+++ branches/symbology-ng-branch/src/plugins/labeling/labelinggui.cpp	2009-08-08 16:02:41 UTC (rev 11291)
@@ -32,8 +32,8 @@
 
 
 
-LabelingGui::LabelingGui( PalLabeling* lbl, QString layerId, QWidget* parent )
-    : QDialog( parent ), mLBL( lbl ), mLayerId( layerId )
+LabelingGui::LabelingGui( PalLabeling* lbl, QgsVectorLayer* layer, QWidget* parent )
+    : QDialog( parent ), mLBL( lbl ), mLayer( layer )
 {
   setupUi( this );
 
@@ -45,7 +45,7 @@
   connect(btnEngineSettings, SIGNAL(clicked()), this, SLOT(showEngineConfigDialog()) );
 
   // set placement methods page based on geometry type
-  switch (layer()->geometryType())
+  switch (layer->geometryType())
   {
     case QGis::Point:
       stackedPlacement->setCurrentWidget(pagePoint);
@@ -62,77 +62,69 @@
 
   populateFieldNames();
 
-  const LayerSettings& lyr = lbl->layer(layerId);
-  if (!lyr.layerId.isEmpty())
+  // load labeling settings from layer
+  LayerSettings lyr;
+  lyr.readFromLayer(layer);
+
+  // placement
+  switch (lyr.placement)
   {
-    // load the labeling settings
+    case LayerSettings::AroundPoint:
+      radAroundPoint->setChecked(true);
+      radAroundCentroid->setChecked(true);
+      spinDistPoint->setValue(lyr.dist);
+      //spinAngle->setValue(lyr.angle);
+      break;
+    case LayerSettings::OverPoint:
+      radOverPoint->setChecked(true);
+      radOverCentroid->setChecked(true);
+      break;
+    case LayerSettings::Line:
+      radLineParallel->setChecked(true);
+      radPolygonPerimeter->setChecked(true);
 
-    // placement
-    switch (lyr.placement)
-    {
-      case LayerSettings::AroundPoint:
-        radAroundPoint->setChecked(true);
-        radAroundCentroid->setChecked(true);
-        spinDistPoint->setValue(lyr.dist);
-        //spinAngle->setValue(lyr.angle);
-        break;
-      case LayerSettings::OverPoint:
-        radOverPoint->setChecked(true);
-        radOverCentroid->setChecked(true);
-        break;
-      case LayerSettings::Line:
-        radLineParallel->setChecked(true);
-        radPolygonPerimeter->setChecked(true);
+      spinDistLine->setValue(lyr.dist);
+      chkLineAbove->setChecked( lyr.placementFlags & LayerSettings::AboveLine );
+      chkLineBelow->setChecked( lyr.placementFlags & LayerSettings::BelowLine );
+      chkLineOn->setChecked( lyr.placementFlags & LayerSettings::OnLine );
+      if ( lyr.placementFlags & LayerSettings::MapOrientation )
+        radOrientationMap->setChecked(true);
+      else
+        radOrientationLine->setChecked(true);
+      break;
+    case LayerSettings::Curved:
+      radLineCurved->setChecked(true);
+      break;
+    case LayerSettings::Horizontal:
+      radPolygonHorizontal->setChecked(true);
+      radLineHorizontal->setChecked(true);
+      break;
+    case LayerSettings::Free:
+      radPolygonFree->setChecked(true);
+      break;
+    default:
+      Q_ASSERT(0 && "NOOO!");
+  }
 
-        spinDistLine->setValue(lyr.dist);
-        chkLineAbove->setChecked( lyr.placementFlags & LayerSettings::AboveLine );
-        chkLineBelow->setChecked( lyr.placementFlags & LayerSettings::BelowLine );
-        chkLineOn->setChecked( lyr.placementFlags & LayerSettings::OnLine );
-        if ( lyr.placementFlags & LayerSettings::MapOrientation )
-          radOrientationMap->setChecked(true);
-        else
-          radOrientationLine->setChecked(true);
-        break;
-      case LayerSettings::Curved:
-        radLineCurved->setChecked(true);
-        break;
-      case LayerSettings::Horizontal:
-        radPolygonHorizontal->setChecked(true);
-        radLineHorizontal->setChecked(true);
-        break;
-      case LayerSettings::Free:
-        radPolygonFree->setChecked(true);
-        break;
-      default:
-        Q_ASSERT(0 && "NOOO!");
-    }
+  cboFieldName->setCurrentIndex( cboFieldName->findText(lyr.fieldName) );
+  chkEnableLabeling->setChecked( lyr.enabled );
+  sliderPriority->setValue( lyr.priority );
+  chkNoObstacle->setChecked( !lyr.obstacle );
+  chkLabelPerFeaturePart->setChecked( lyr.labelPerPart );
 
-    cboFieldName->setCurrentIndex( cboFieldName->findText(lyr.fieldName) );
-    chkEnableLabeling->setChecked( lyr.enabled );
-    sliderPriority->setValue( lyr.priority );
-    chkNoObstacle->setChecked( !lyr.obstacle );
-    chkLabelPerFeaturePart->setChecked( lyr.labelPerPart );
-
-    bool scaleBased = (lyr.scaleMin != 0 && lyr.scaleMax != 0);
-    chkScaleBasedVisibility->setChecked(scaleBased);
-    if (scaleBased)
-    {
-      spinScaleMin->setValue(lyr.scaleMin);
-      spinScaleMax->setValue(lyr.scaleMax);
-    }
-
-    bool buffer = (lyr.bufferSize != 0);
-    chkBuffer->setChecked(buffer);
-    if (buffer)
-      spinBufferSize->setValue(lyr.bufferSize);
-  }
-  else
+  bool scaleBased = (lyr.scaleMin != 0 && lyr.scaleMax != 0);
+  chkScaleBasedVisibility->setChecked(scaleBased);
+  if (scaleBased)
   {
-    // set enabled by default
-    chkEnableLabeling->setChecked( true );
-
+    spinScaleMin->setValue(lyr.scaleMin);
+    spinScaleMax->setValue(lyr.scaleMax);
   }
 
+  bool buffer = (lyr.bufferSize != 0);
+  chkBuffer->setChecked(buffer);
+  if (buffer)
+    spinBufferSize->setValue(lyr.bufferSize);
+
   btnTextColor->setColor( lyr.textColor );
   btnBufferColor->setColor( lyr.bufferColor );
   updateFont( lyr.textFont );
@@ -157,18 +149,9 @@
 {
 }
 
-QgsVectorLayer* LabelingGui::layer()
-{
-  QgsMapLayer* layer = QgsMapLayerRegistry::instance()->mapLayer(mLayerId);
-  if (layer == NULL || layer->type() != QgsMapLayer::VectorLayer)
-    return NULL;
-  return static_cast<QgsVectorLayer*>(layer);
-}
-
 LayerSettings LabelingGui::layerSettings()
 {
   LayerSettings lyr;
-  lyr.layerId = mLayerId;
   lyr.fieldName = cboFieldName->currentText();
 
   lyr.dist = 0;
@@ -249,7 +232,7 @@
 
 void LabelingGui::populateFieldNames()
 {
-  QgsFieldMap fields = layer()->dataProvider()->fields();
+  QgsFieldMap fields = mLayer->dataProvider()->fields();
   for (QgsFieldMap::iterator it = fields.begin(); it != fields.end(); it++)
   {
     cboFieldName->addItem(it->name());

Modified: branches/symbology-ng-branch/src/plugins/labeling/labelinggui.h
===================================================================
--- branches/symbology-ng-branch/src/plugins/labeling/labelinggui.h	2009-08-07 11:58:50 UTC (rev 11290)
+++ branches/symbology-ng-branch/src/plugins/labeling/labelinggui.h	2009-08-08 16:02:41 UTC (rev 11291)
@@ -21,9 +21,7 @@
 #include <QDialog>
 #include <ui_labelingguibase.h>
 
-//class PalLabeling;
 class QgsVectorLayer;
-//struct PalLabeling::LayerSettings;
 
 #include "pallabeling.h"
 
@@ -32,7 +30,7 @@
   Q_OBJECT
 
   public:
-    LabelingGui( PalLabeling* lbl, QString layerId, QWidget* parent );
+    LabelingGui( PalLabeling* lbl, QgsVectorLayer* layer, QWidget* parent );
     ~LabelingGui();
 
     LayerSettings layerSettings();
@@ -52,11 +50,9 @@
     void populateFieldNames();
     void updateFont(QFont font);
 
-    QgsVectorLayer* layer();
-
   private:
     PalLabeling* mLBL;
-    QString mLayerId;
+    QgsVectorLayer* mLayer;
 };
 
 #endif

Modified: branches/symbology-ng-branch/src/plugins/labeling/pallabeling.cpp
===================================================================
--- branches/symbology-ng-branch/src/plugins/labeling/pallabeling.cpp	2009-08-07 11:58:50 UTC (rev 11290)
+++ branches/symbology-ng-branch/src/plugins/labeling/pallabeling.cpp	2009-08-08 16:02:41 UTC (rev 11291)
@@ -89,13 +89,24 @@
 LayerSettings::LayerSettings()
   : palLayer(NULL), fontMetrics(NULL), ct(NULL)
 {
+  placement = AroundPoint;
+  placementFlags = 0;
+  //textFont = QFont();
+  textColor = Qt::black;
+  enabled = false;
+  priority = 5;
+  obstacle = true;
+  dist = 0;
+  scaleMin = 0;
+  scaleMax = 0;
+  bufferSize = 1;
   bufferColor = Qt::white;
+  labelPerPart = false;
 }
 
 LayerSettings::LayerSettings(const LayerSettings& s)
 {
   // copy only permanent stuff
-  layerId = s.layerId;
   fieldName = s.fieldName;
   placement = s.placement;
   placementFlags = s.placementFlags;
@@ -124,6 +135,72 @@
   delete ct;
 }
 
+static QColor _readColor(QgsVectorLayer* layer, QString property)
+{
+  int r = layer->customProperty(property+"R").toInt();
+  int g = layer->customProperty(property+"G").toInt();
+  int b = layer->customProperty(property+"B").toInt();
+  return QColor(r,g,b);
+}
+
+static void _writeColor(QgsVectorLayer* layer, QString property, QColor color)
+{
+  layer->setCustomProperty(property+"R", color.red());
+  layer->setCustomProperty(property+"G", color.green());
+  layer->setCustomProperty(property+"B", color.blue());
+}
+
+void LayerSettings::readFromLayer(QgsVectorLayer* layer)
+{
+  if (layer->customProperty("labeling").toString() != QString("pal"))
+    return; // there's no information available
+
+  fieldName = layer->customProperty("labeling/fieldName").toString();
+  placement = (Placement) layer->customProperty("labeling/placement").toInt();
+  placementFlags = layer->customProperty("labeling/placementFlags").toUInt();
+  QString fontFamily = layer->customProperty("labeling/fontFamily").toString();
+  int fontSize = layer->customProperty("labeling/fontSize").toInt();
+  int fontWeight = layer->customProperty("labeling/fontWeight").toInt();
+  bool fontItalic = layer->customProperty("labeling/fontItalic").toBool();
+  textFont = QFont(fontFamily, fontSize, fontWeight, fontItalic);
+  textColor = _readColor(layer, "labeling/textColor");
+  enabled = layer->customProperty("labeling/enabled").toBool();
+  priority = layer->customProperty("labeling/priority").toInt();
+  obstacle = layer->customProperty("labeling/obstacle").toBool();
+  dist = layer->customProperty("labeling/dist").toDouble();
+  scaleMin = layer->customProperty("labeling/scaleMin").toInt();
+  scaleMax = layer->customProperty("labeling/scaleMax").toInt();
+  bufferSize = layer->customProperty("labeling/bufferSize").toInt();
+  bufferColor = _readColor(layer, "labeling/bufferColor");
+  labelPerPart = layer->customProperty("labeling/labelPerPart").toInt();
+}
+
+void LayerSettings::writeToLayer(QgsVectorLayer* layer)
+{
+  // this is a mark that labeling information is present
+  layer->setCustomProperty("labeling", "pal");
+
+  layer->setCustomProperty("labeling/fieldName", fieldName);
+  layer->setCustomProperty("labeling/placement", placement);
+  layer->setCustomProperty("labeling/placementFlags", (unsigned int)placementFlags);
+
+  layer->setCustomProperty("labeling/fontFamily", textFont.family());
+  layer->setCustomProperty("labeling/fontSize", textFont.pointSize());
+  layer->setCustomProperty("labeling/fontWeight", textFont.weight());
+  layer->setCustomProperty("labeling/fontItalic", textFont.italic());
+
+  _writeColor(layer, "labeling/textColor", textColor);
+  layer->setCustomProperty("labeling/enabled", enabled);
+  layer->setCustomProperty("labeling/priority", priority);
+  layer->setCustomProperty("labeling/obstacle", obstacle);
+  layer->setCustomProperty("labeling/dist", dist);
+  layer->setCustomProperty("labeling/scaleMin", scaleMin);
+  layer->setCustomProperty("labeling/scaleMax", scaleMax);
+  layer->setCustomProperty("labeling/bufferSize", bufferSize);
+  _writeColor(layer, "labeling/bufferColor", bufferColor);
+  layer->setCustomProperty("labeling/labelPerPart", labelPerPart);
+}
+
 void LayerSettings::calculateLabelSize(QString text, double& labelX, double& labelY)
 {
   //QFontMetrics fontMetrics(textFont);
@@ -195,76 +272,32 @@
 PalLabeling::~PalLabeling()
 {
   delete mPal;
-
-  // make sure to remove hooks from all layers
-  while (mLayers.count())
-  {
-    removeLayer(mLayers[0].layerId);
-  }
 }
 
 
-void PalLabeling::addLayer(LayerSettings layerSettings)
+int PalLabeling::prepareLayer(QgsVectorLayer* layer, int& attrIndex)
 {
-  mLayers.append(layerSettings);
+  // start with a temporary settings class, find out labeling info
+  LayerSettings lyrTmp;
+  lyrTmp.readFromLayer(layer);
 
-  QgsVectorLayer* vlayer = (QgsVectorLayer*) QgsMapLayerRegistry::instance()->mapLayer(layerSettings.layerId);
-
-  LayerSettings& lyr = mLayers[ mLayers.count()-1 ]; // make sure we have the right pointer
-  vlayer->setLabelingHooks(PalLabeling::prepareLayerHook, PalLabeling::registerFeatureHook, this, &lyr);
-}
-
-void PalLabeling::removeLayer(QString layerId)
-{
-  for (int i = 0; i < mLayers.count(); i++)
-  {
-    if (mLayers.at(i).layerId == layerId)
-    {
-      QgsVectorLayer* vlayer = (QgsVectorLayer*) QgsMapLayerRegistry::instance()->mapLayer(mLayers.at(i).layerId);
-      if (vlayer) { vlayer->setLabelingHooks(NULL, NULL, NULL, NULL); }
-
-      mLayers.removeAt(i);
-      return;
-    }
-  }
-}
-
-const LayerSettings& PalLabeling::layer(QString layerId)
-{
-  for (int i = 0; i < mLayers.count(); i++)
-  {
-    if (mLayers.at(i).layerId == layerId)
-    {
-      return mLayers.at(i);
-    }
-  }
-  return mInvalidLayer;
-}
-
-
-
-int PalLabeling::prepareLayerHook(void* context, void* layerContext, int& attrIndex)
-{
-  PalLabeling* thisClass = (PalLabeling*) context;
-  LayerSettings* lyr = (LayerSettings*) layerContext;
-
-  if (!lyr->enabled)
+  if (!lyrTmp.enabled)
     return 0;
 
-  QgsVectorLayer* vlayer = (QgsVectorLayer*) QgsMapLayerRegistry::instance()->mapLayer(lyr->layerId);
-  if (vlayer == NULL)
-    return 0;
-
   // find out which field will be needed
-  int fldIndex = vlayer->dataProvider()->fieldNameIndex(lyr->fieldName);
+  int fldIndex = layer->dataProvider()->fieldNameIndex(lyrTmp.fieldName);
   if (fldIndex == -1)
     return 0;
   attrIndex = fldIndex;
 
+  // add layer settings to the pallabeling hashtable: <QgsVectorLayer*, LayerSettings>
+  mActiveLayers.insert(layer, lyrTmp);
+  // start using the reference to the layer in hashtable instead of local instance
+  LayerSettings& lyr = mActiveLayers[layer];
 
   // how to place the labels
   Arrangement arrangement;
-  switch (lyr->placement)
+  switch (lyr.placement)
   {
     case LayerSettings::AroundPoint: arrangement = P_POINT; break;
     case LayerSettings::OverPoint:   arrangement = P_POINT_OVER; break;
@@ -275,42 +308,44 @@
   }
 
   // create the pal layer
-  double priority = 1 - lyr->priority/10.0; // convert 0..10 --> 1..0
+  double priority = 1 - lyr.priority/10.0; // convert 0..10 --> 1..0
   double min_scale = -1, max_scale = -1;
-  if (lyr->scaleMin != 0 && lyr->scaleMax != 0)
+  if (lyr.scaleMin != 0 && lyr.scaleMax != 0)
   {
-    min_scale = lyr->scaleMin;
-    max_scale = lyr->scaleMax;
+    min_scale = lyr.scaleMin;
+    max_scale = lyr.scaleMax;
   }
 
-  Layer* l = thisClass->mPal->addLayer(lyr->layerId.toLocal8Bit().data(), min_scale, max_scale, arrangement, METER, priority, lyr->obstacle, true, true);
+  Layer* l = mPal->addLayer(layer->getLayerID().toLocal8Bit().data(),
+                            min_scale, max_scale, arrangement,
+                            METER, priority, lyr.obstacle, true, true);
 
-  if ( lyr->placementFlags )
-    l->setArrangementFlags( lyr->placementFlags );
+  if ( lyr.placementFlags )
+    l->setArrangementFlags( lyr.placementFlags );
 
   // set label mode (label per feature is the default)
-  l->setLabelMode( lyr->labelPerPart ? Layer::LabelPerFeaturePart : Layer::LabelPerFeature );
+  l->setLabelMode( lyr.labelPerPart ? Layer::LabelPerFeaturePart : Layer::LabelPerFeature );
 
   // save the pal layer to our layer context (with some additional info)
-  lyr->palLayer = l;
-  lyr->fieldIndex = fldIndex;
-  lyr->fontMetrics = new QFontMetrics(lyr->textFont);
-  lyr->fontBaseline = lyr->fontMetrics->boundingRect("X").bottom(); // dummy text to find out how many pixels of the text are below the baseline
-  lyr->xform = thisClass->mMapRenderer->coordinateTransform();
-  if (thisClass->mMapRenderer->hasCrsTransformEnabled())
-    lyr->ct = new QgsCoordinateTransform( vlayer->srs(), thisClass->mMapRenderer->destinationSrs() );
+  lyr.palLayer = l;
+  lyr.fieldIndex = fldIndex;
+  lyr.fontMetrics = new QFontMetrics(lyr.textFont);
+  lyr.fontBaseline = lyr.fontMetrics->boundingRect("X").bottom(); // dummy text to find out how many pixels of the text are below the baseline
+  lyr.xform = mMapRenderer->coordinateTransform();
+  if (mMapRenderer->hasCrsTransformEnabled())
+    lyr.ct = new QgsCoordinateTransform( layer->srs(), mMapRenderer->destinationSrs() );
   else
-    lyr->ct = NULL;
-  lyr->ptZero = lyr->xform->toMapCoordinates( 0,0 );
-  lyr->ptOne = lyr->xform->toMapCoordinates( 1,0 );
+    lyr.ct = NULL;
+  lyr.ptZero = lyr.xform->toMapCoordinates( 0,0 );
+  lyr.ptOne = lyr.xform->toMapCoordinates( 1,0 );
 
   return 1; // init successful
 }
 
-void PalLabeling::registerFeatureHook(QgsFeature& f, void* layerContext)
+
+void PalLabeling::registerFeature(QgsVectorLayer* layer, QgsFeature& f)
 {
-  LayerSettings* lyr = (LayerSettings*) layerContext;
-  lyr->registerFeature(f);
+  mActiveLayers[layer].registerFeature(f);
 }
 
 
@@ -339,6 +374,17 @@
   mPal->setPolyP(mCandPolygon);
 }
 
+LayerSettings& PalLabeling::layer(const char* layerName)
+{
+  QHash<QgsVectorLayer*, LayerSettings>::iterator lit;
+  for (lit = mActiveLayers.begin(); lit != mActiveLayers.end(); ++lit)
+  {
+    LayerSettings& lyr = lit.value();
+    if (lyr.palLayer->getName() == layerName)
+      return lyr;
+  }
+  return mInvalidLayerSettings;
+}
 
 
 void PalLabeling::doLabeling(QPainter* painter, QgsRectangle extent)
@@ -361,6 +407,7 @@
   catch ( std::exception& e )
   {
     std::cerr << "PAL EXCEPTION :-( " << e.what() << std::endl;
+    mActiveLayers.clear(); // clean up
     return;
   }
 
@@ -409,13 +456,16 @@
   delete labels;
 
   // delete all allocated geometries for features
-  for (int i = 0; i < mLayers.count(); i++)
+  QHash<QgsVectorLayer*, LayerSettings>::iterator lit;
+  for (lit = mActiveLayers.begin(); lit != mActiveLayers.end(); ++lit)
   {
-    LayerSettings& lyr = mLayers[i];
+    LayerSettings& lyr = lit.value();
     for (QList<MyLabel*>::iterator git = lyr.geometries.begin(); git != lyr.geometries.end(); ++git)
       delete *git;
     lyr.geometries.clear();
   }
+  // labeling is done: clear the active layers hashtable
+  mActiveLayers.clear();
 
   // re-create PAL
   initPal();

Modified: branches/symbology-ng-branch/src/plugins/labeling/pallabeling.h
===================================================================
--- branches/symbology-ng-branch/src/plugins/labeling/pallabeling.h	2009-08-07 11:58:50 UTC (rev 11290)
+++ branches/symbology-ng-branch/src/plugins/labeling/pallabeling.h	2009-08-08 16:02:41 UTC (rev 11291)
@@ -23,6 +23,8 @@
 class QgsFeature;
 #include "qgspoint.h"
 
+#include "qgsvectorlayer.h" // definition of QgsLabelingEngineInterface
+
 class MyLabel;
 
 class LayerSettings
@@ -50,10 +52,9 @@
     MapOrientation = 8
   };
 
-  QString layerId;
   QString fieldName;
   Placement placement;
-  unsigned long placementFlags;
+  unsigned int placementFlags;
   QFont textFont;
   QColor textColor;
   bool enabled;
@@ -71,6 +72,9 @@
   // implementation of register feature hook
   void registerFeature(QgsFeature& f);
 
+  void readFromLayer(QgsVectorLayer* layer);
+  void writeToLayer(QgsVectorLayer* layer);
+
   // temporary stuff: set when layer gets prepared
   pal::Layer* palLayer;
   int fieldIndex;
@@ -91,20 +95,16 @@
   double cost;
 };
 
-class PalLabeling
+class PalLabeling : public QgsLabelingEngineInterface
 {
 public:
     PalLabeling(QgsMapRenderer* renderer);
     ~PalLabeling();
 
+    LayerSettings& layer(const char* layerName);
+
     void doLabeling(QPainter* painter, QgsRectangle extent);
 
-    void addLayer(LayerSettings layerSettings);
-
-    void removeLayer(QString layerId);
-
-    const LayerSettings& layer(QString layerId);
-
     void numCandidatePositions(int& candPoint, int& candLine, int& candPolygon);
     void setNumCandidatePositions(int candPoint, int candLine, int candPolygon);
 
@@ -120,10 +120,12 @@
     bool isShowingAllLabels() const { return mShowingAllLabels; }
     void setShowingAllLabels(bool showing) { mShowingAllLabels = showing; }
 
+    // implemented methods from labeling engine interface
+
     //! hook called when drawing layer before issuing select()
-    static int prepareLayerHook(void* context, void* layerContext, int& attrIndex);
+    virtual int prepareLayer(QgsVectorLayer* layer, int& attrIndex);
     //! hook called when drawing for every feature in a layer
-    static void registerFeatureHook(QgsFeature& f, void* layerContext);
+    virtual void registerFeature(QgsVectorLayer* layer, QgsFeature& feat);
 
 
     void drawLabelCandidateRect( pal::LabelPosition* lp, QPainter* painter, const QgsMapToPixel* xform );
@@ -135,9 +137,10 @@
     void initPal();
 
 protected:
-    QList<LayerSettings> mLayers;
-    LayerSettings mInvalidLayer;
-
+    // temporary hashtable of layer settings, being filled during labeling, cleared once labeling's done
+    QHash<QgsVectorLayer*, LayerSettings> mActiveLayers;
+    LayerSettings mInvalidLayerSettings;
+    
     QgsMapRenderer* mMapRenderer;
     int mCandPoint, mCandLine, mCandPolygon;
     Search mSearch;



More information about the QGIS-commit mailing list