[QGIS Commit] r11881 - in branches/symbology-ng-branch: resources src/core src/core/symbology-ng

svn_qgis at osgeo.org svn_qgis at osgeo.org
Sun Nov 1 18:47:56 EST 2009


Author: wonder
Date: 2009-11-01 18:47:56 -0500 (Sun, 01 Nov 2009)
New Revision: 11881

Modified:
   branches/symbology-ng-branch/resources/symbology-ng-style.xml
   branches/symbology-ng-branch/src/core/qgsvectorlayer.cpp
   branches/symbology-ng-branch/src/core/symbology-ng/qgsrendererv2.cpp
   branches/symbology-ng-branch/src/core/symbology-ng/qgsrendererv2.h
   branches/symbology-ng-branch/src/core/symbology-ng/qgsstylev2.cpp
   branches/symbology-ng-branch/src/core/symbology-ng/qgsstylev2.h
   branches/symbology-ng-branch/src/core/symbology-ng/qgssymbollayerv2utils.cpp
   branches/symbology-ng-branch/src/core/symbology-ng/qgssymbollayerv2utils.h
Log:
Added loading and saving of renderers v2 in project files.


Modified: branches/symbology-ng-branch/resources/symbology-ng-style.xml
===================================================================
--- branches/symbology-ng-branch/resources/symbology-ng-style.xml	2009-11-01 23:45:49 UTC (rev 11880)
+++ branches/symbology-ng-branch/resources/symbology-ng-style.xml	2009-11-01 23:47:56 UTC (rev 11881)
@@ -1,5 +1,6 @@
 <!DOCTYPE qgis_style>
 <qgis_style version="0" >
+ <symbols>
   <symbol type="marker" name="blue square" >
     <layer class="SimpleMarker" locked="0" >
       <prop k="angle" v="0" />
@@ -97,6 +98,8 @@
       <prop k="size" v="12" />
     </layer>
   </symbol>
+ </symbols>
+ <colorramps>
   <colorramp type="gradient" name="blue" >
     <prop k="color1" v="0,0,255" />
     <prop k="color2" v="207,205,255" />
@@ -109,4 +112,5 @@
     <prop k="color1" v="255,0,0" />
     <prop k="color2" v="255,255,0" />
   </colorramp>
+ </colorramps>
 </qgis_style>

Modified: branches/symbology-ng-branch/src/core/qgsvectorlayer.cpp
===================================================================
--- branches/symbology-ng-branch/src/core/qgsvectorlayer.cpp	2009-11-01 23:45:49 UTC (rev 11880)
+++ branches/symbology-ng-branch/src/core/qgsvectorlayer.cpp	2009-11-01 23:47:56 UTC (rev 11881)
@@ -2315,12 +2315,28 @@
     }
   }
 
-  QString errorMsg;
-  if ( !readSymbology( layer_node, errorMsg ) )
+  QDomElement rendererElement = layer_node.firstChildElement(RENDERER_TAG_NAME);
+  if (!rendererElement.isNull())
   {
-    return false;
+    // using renderer v2
+    setUsingRendererV2(true);
+
+    QgsFeatureRendererV2* r = QgsFeatureRendererV2::load(rendererElement);
+    if (r == NULL)
+      return false;
+    setRendererV2(r);
   }
+  else
+  {
+    // using renderer v1
+    setUsingRendererV2(false);
 
+    QString errorMsg;
+    if ( !readSymbology( layer_node, errorMsg ) )
+    {
+      return false;
+    }
+  }
 
   return mValid;               // should be true if read successfully
 
@@ -2455,14 +2471,20 @@
   }
 
   // renderer specific settings
-
-  QString errorMsg;
-  if ( !writeSymbology( layer_node, document, errorMsg ) )
+  if (mUsingRendererV2)
   {
-    return false;
+    QDomElement rendererElement = mRendererV2->save(document);
+    layer_node.appendChild(rendererElement);
   }
+  else
+  {
+    QString errorMsg;
+    if ( !writeSymbology( layer_node, document, errorMsg ) )
+    {
+      return false;
+    }
+  }
 
-
   return true;
 } // bool QgsVectorLayer::writeXml
 

Modified: branches/symbology-ng-branch/src/core/symbology-ng/qgsrendererv2.cpp
===================================================================
--- branches/symbology-ng-branch/src/core/symbology-ng/qgsrendererv2.cpp	2009-11-01 23:45:49 UTC (rev 11880)
+++ branches/symbology-ng-branch/src/core/symbology-ng/qgsrendererv2.cpp	2009-11-01 23:47:56 UTC (rev 11881)
@@ -1,14 +1,18 @@
 #include "qgsrendererv2.h"
 #include "qgssymbolv2.h"
+#include "qgssymbollayerv2utils.h"
 
 #include "qgsrendercontext.h"
 #include "qgsgeometry.h"
 #include "qgsfeature.h"
 #include "qgslogger.h"
 
+#include <QDomElement>
+#include <QDomDocument>
 #include <QPolygonF>
 
 
+
 static unsigned char* _getPoint(QPointF& pt, const QgsMapToPixel& mapToPixel, unsigned char* wkb)
 {
   wkb++; // jump over endian info
@@ -247,6 +251,40 @@
 }
 
 
+QgsFeatureRendererV2* QgsFeatureRendererV2::load(QDomElement& element)
+{
+  // <renderer-v2 type=""> ... </renderer-v2>
+
+  if (element.isNull())
+    return NULL;
+
+  // load renderer
+  QString rendererType = element.attribute("type");
+
+  // TODO: use renderer registry
+  if (rendererType == "singleSymbol")
+  {
+    return QgsSingleSymbolRendererV2::create(element);
+  }
+  else if (rendererType == "categorizedSymbol")
+  {
+    return QgsCategorizedSymbolRendererV2::create(element);
+  }
+  else if (rendererType == "graduatedSymbol")
+  {
+    return QgsGraduatedSymbolRendererV2::create(element);
+  }
+
+  // unknown renderer type
+  return NULL;
+}
+
+QDomElement QgsFeatureRendererV2::save(QDomDocument& doc)
+{
+  // create empty renderer element
+  return doc.createElement(RENDERER_TAG_NAME);
+}
+
 ///////////////////
 
 QgsSingleSymbolRendererV2::QgsSingleSymbolRendererV2(QgsSymbolV2* symbol)
@@ -310,6 +348,39 @@
   return lst;
 }
 
+QgsFeatureRendererV2* QgsSingleSymbolRendererV2::create(QDomElement& element)
+{
+  QDomElement symbolsElem = element.firstChildElement("symbols");
+  if (symbolsElem.isNull())
+    return NULL;
+
+  QgsSymbolV2Map symbolMap = QgsSymbolLayerV2Utils::loadSymbols(symbolsElem);
+
+  if (!symbolMap.contains("0"))
+    return NULL;
+
+  QgsSingleSymbolRendererV2* r = new QgsSingleSymbolRendererV2( symbolMap.take("0") );
+
+  // delete symbols if there are any more
+  QgsSymbolLayerV2Utils::clearSymbolMap(symbolMap);
+
+  // TODO: symbol levels
+  return r;
+}
+
+QDomElement QgsSingleSymbolRendererV2::save(QDomDocument& doc)
+{
+  QDomElement rendererElem = doc.createElement(RENDERER_TAG_NAME);
+  rendererElem.setAttribute("type", "singleSymbol");
+
+  QgsSymbolV2Map symbols;
+  symbols["0"] = mSymbol;
+  QDomElement symbolsElem = QgsSymbolLayerV2Utils::saveSymbols(symbols, doc);
+  rendererElem.appendChild(symbolsElem);
+
+  return rendererElem;
+}
+
 ///////////////////
 
 QgsRendererCategoryV2::QgsRendererCategoryV2(QVariant value, QgsSymbolV2* symbol, QString label)
@@ -513,6 +584,81 @@
   return lst;
 }
 
+QgsFeatureRendererV2* QgsCategorizedSymbolRendererV2::create(QDomElement& element)
+{
+  QDomElement symbolsElem = element.firstChildElement("symbols");
+  if (symbolsElem.isNull())
+    return NULL;
+
+  QDomElement catsElem = element.firstChildElement("categories");
+  if (catsElem.isNull())
+    return NULL;
+
+  QgsSymbolV2Map symbolMap = QgsSymbolLayerV2Utils::loadSymbols(symbolsElem);
+  QgsCategoryList cats;
+
+  QDomElement catElem = catsElem.firstChildElement();
+  while (!catElem.isNull())
+  {
+    if (catElem.tagName() == "category")
+    {
+      QVariant value = QVariant(catElem.attribute("value"));
+      QString symbolName = catElem.attribute("symbol");
+      QString label = catElem.attribute("label");
+      if (symbolMap.contains(symbolName))
+      {
+        QgsSymbolV2* symbol = symbolMap.take(symbolName);
+        cats.append( QgsRendererCategoryV2(value, symbol, label) );
+      }
+    }
+    catElem = catElem.nextSiblingElement();
+  }
+
+  int attrNum = element.attribute("attr").toInt();
+
+  QgsCategorizedSymbolRendererV2* r = new QgsCategorizedSymbolRendererV2(attrNum, cats);
+
+  // delete symbols if there are any more
+  QgsSymbolLayerV2Utils::clearSymbolMap(symbolMap);
+
+  // TODO: symbol levels
+  return r;
+}
+
+QDomElement QgsCategorizedSymbolRendererV2::save(QDomDocument& doc)
+{
+  QDomElement rendererElem = doc.createElement(RENDERER_TAG_NAME);
+  rendererElem.setAttribute("type", "categorizedSymbol");
+  rendererElem.setAttribute("attr", mAttrNum);
+
+  // categories
+  int i = 0;
+  QgsSymbolV2Map symbols;
+  QDomElement catsElem = doc.createElement("categories");
+  QgsCategoryList::const_iterator it = mCategories.constBegin();
+  for ( ; it != mCategories.end(); it++)
+  {
+    const QgsRendererCategoryV2& cat = *it;
+    QString symbolName = QString::number(i);
+    symbols.insert(symbolName, cat.symbol());
+
+    QDomElement catElem = doc.createElement("category");
+    catElem.setAttribute("value", cat.value().toString());
+    catElem.setAttribute("symbol", symbolName);
+    catElem.setAttribute("label", cat.label());
+    catsElem.appendChild(catElem);
+    i++;
+  }
+
+  rendererElem.appendChild(catsElem);
+
+  // save symbols
+  QDomElement symbolsElem = QgsSymbolLayerV2Utils::saveSymbols(symbols, doc);
+  rendererElem.appendChild(symbolsElem);
+
+  return rendererElem;
+}
+
 /////////////////////////
 // graduated
 
@@ -778,3 +924,82 @@
   
   return new QgsGraduatedSymbolRendererV2( attrNum, ranges );
 }
+
+
+
+QgsFeatureRendererV2* QgsGraduatedSymbolRendererV2::create(QDomElement& element)
+{
+  QDomElement symbolsElem = element.firstChildElement("symbols");
+  if (symbolsElem.isNull())
+    return NULL;
+
+  QDomElement rangesElem = element.firstChildElement("ranges");
+  if (rangesElem.isNull())
+    return NULL;
+
+  QgsSymbolV2Map symbolMap = QgsSymbolLayerV2Utils::loadSymbols(symbolsElem);
+  QgsRangeList ranges;
+
+  QDomElement rangeElem = rangesElem.firstChildElement();
+  while (!rangeElem.isNull())
+  {
+    if (rangeElem.tagName() == "range")
+    {
+      double lowerValue = rangeElem.attribute("lower").toDouble();
+      double upperValue = rangeElem.attribute("upper").toDouble();
+      QString symbolName = rangeElem.attribute("symbol");
+      QString label = rangeElem.attribute("label");
+      if (symbolMap.contains(symbolName))
+      {
+        QgsSymbolV2* symbol = symbolMap.take(symbolName);
+        ranges.append( QgsRendererRangeV2(lowerValue, upperValue, symbol, label) );
+      }
+    }
+    rangeElem = rangeElem.nextSiblingElement();
+  }
+
+  int attrNum = element.attribute("attr").toInt();
+
+  QgsGraduatedSymbolRendererV2* r = new QgsGraduatedSymbolRendererV2(attrNum, ranges);
+
+  // delete symbols if there are any more
+  QgsSymbolLayerV2Utils::clearSymbolMap(symbolMap);
+
+  // TODO: symbol levels
+  return r;
+}
+
+QDomElement QgsGraduatedSymbolRendererV2::save(QDomDocument& doc)
+{
+  QDomElement rendererElem = doc.createElement(RENDERER_TAG_NAME);
+  rendererElem.setAttribute("type", "graduatedSymbol");
+  rendererElem.setAttribute("attr", mAttrNum);
+
+  // ranges
+  int i = 0;
+  QgsSymbolV2Map symbols;
+  QDomElement rangesElem = doc.createElement("ranges");
+  QgsRangeList::const_iterator it = mRanges.constBegin();
+  for ( ; it != mRanges.end(); it++)
+  {
+    const QgsRendererRangeV2& range = *it;
+    QString symbolName = QString::number(i);
+    symbols.insert(symbolName, range.symbol());
+
+    QDomElement rangeElem = doc.createElement("range");
+    rangeElem.setAttribute("lower", range.lowerValue());
+    rangeElem.setAttribute("upper", range.upperValue());
+    rangeElem.setAttribute("symbol", symbolName);
+    rangeElem.setAttribute("label", range.label());
+    rangesElem.appendChild(rangeElem);
+    i++;
+  }
+
+  rendererElem.appendChild(rangesElem);
+
+  // save symbols
+  QDomElement symbolsElem = QgsSymbolLayerV2Utils::saveSymbols(symbols, doc);
+  rendererElem.appendChild(symbolsElem);
+
+  return rendererElem;
+}

Modified: branches/symbology-ng-branch/src/core/symbology-ng/qgsrendererv2.h
===================================================================
--- branches/symbology-ng-branch/src/core/symbology-ng/qgsrendererv2.h	2009-11-01 23:45:49 UTC (rev 11880)
+++ branches/symbology-ng-branch/src/core/symbology-ng/qgsrendererv2.h	2009-11-01 23:47:56 UTC (rev 11881)
@@ -9,12 +9,18 @@
 #include <QString>
 #include <QVariant>
 
+class QDomDocument;
+class QDomElement;
+
 class QgsSymbolV2;
 class QgsRenderContext;
 class QgsFeature;
 
 typedef QList<QgsSymbolV2*> QgsSymbolV2List;
+typedef QMap<QString, QgsSymbolV2* > QgsSymbolV2Map;
 
+#define RENDERER_TAG_NAME   "renderer-v2"
+
 ////////
 // symbol levels
 
@@ -80,6 +86,12 @@
 
   bool usingSymbolLevels() const { return mUsingSymbolLevels; }
   void setUsingSymbolLevels(bool usingSymbolLevels) { mUsingSymbolLevels = usingSymbolLevels; }
+
+  //! create a renderer from XML element
+  static QgsFeatureRendererV2* load(QDomElement& symbologyElem);
+
+  //! store renderer info to XML element
+  virtual QDomElement save(QDomDocument& doc);
   
 protected:
   QgsFeatureRendererV2(RendererType type);
@@ -114,6 +126,12 @@
 
   virtual QgsSymbolV2List symbols();
 
+  //! create renderer from XML element
+  static QgsFeatureRendererV2* create(QDomElement& element);
+
+  //! store renderer info to XML element
+  virtual QDomElement save(QDomDocument& doc);
+
 protected:
 	QgsSymbolV2* mSymbol;
 };
@@ -185,6 +203,12 @@
   int attributeIndex() const { return mAttrNum; }
   void setAttributeIndex(int attr) { mAttrNum = attr; }
 
+  //! create renderer from XML element
+  static QgsFeatureRendererV2* create(QDomElement& element);
+
+  //! store renderer info to XML element
+  virtual QDomElement save(QDomDocument& doc);
+
 protected:
   QgsCategoryList mCategories;
   int mAttrNum;
@@ -278,6 +302,12 @@
                   QgsSymbolV2* symbol,
                   QgsVectorColorRampV2* ramp);
 
+  //! create renderer from XML element
+  static QgsFeatureRendererV2* create(QDomElement& element);
+
+  //! store renderer info to XML element
+  virtual QDomElement save(QDomDocument& doc);
+
 protected:
   QgsRangeList mRanges;
   int mAttrNum;

Modified: branches/symbology-ng-branch/src/core/symbology-ng/qgsstylev2.cpp
===================================================================
--- branches/symbology-ng-branch/src/core/symbology-ng/qgsstylev2.cpp	2009-11-01 23:45:49 UTC (rev 11880)
+++ branches/symbology-ng-branch/src/core/symbology-ng/qgsstylev2.cpp	2009-11-01 23:47:56 UTC (rev 11881)
@@ -190,165 +190,42 @@
     mErrorString = "Unknown style file version: " + version;
     return false;
   }
-  
-  QDomNode node = docElem.firstChild();
-  QString name;
-  
-  while (!node.isNull())
+
+  // load symbols
+  QDomElement symbolsElement = docElem.firstChildElement("symbols");
+  if (!symbolsElement.isNull())
   {
-    QDomElement e = node.toElement();
-    if (!e.isNull()) // comments are null elements
-    {
-      if (e.tagName() == "symbol")
-      {
-        name = e.attribute("name");
-        QgsSymbolV2* symbol = loadSymbol(e);
-        if (symbol != NULL)
-          addSymbol(name, symbol);
-      }
-      else if (e.tagName() == "colorramp")
-      {
-        name = e.attribute("name");
-        QgsVectorColorRampV2* ramp = loadColorRamp(e);
-        if (ramp != NULL)
-          addColorRamp(name, ramp);
-      }
-      else
-      {
-        QgsDebugMsg("unknown tag: " + e.tagName());
-      }
-    } 
-    node = node.nextSibling();
+    mSymbols = QgsSymbolLayerV2Utils::loadSymbols(symbolsElement);
   }
-  
-  // now walk through the list of symbols and find those prefixed with @
-  // these symbols are sub-symbols of some other symbol layers
-  // e.g. symbol named "@foo at 1" is sub-symbol of layer 1 in symbol "foo"
-  QStringList subsymbols;
-  
-  for (QMap<QString, QgsSymbolV2*>::iterator it = mSymbols.begin(); it != mSymbols.end(); ++it)
+
+  // load color ramps
+  QDomElement rampsElement = docElem.firstChildElement("colorramps");
+  QDomElement e = rampsElement.firstChildElement();
+  while (!e.isNull())
   {
-    if (it.key()[0] != '@')
-      continue;
-    
-    // add to array (for deletion)
-    subsymbols.append(it.key());
-    
-    QStringList parts = it.key().split("@");
-    if (parts.count() < 3)
+    if (e.tagName() == "colorramp")
     {
-      QgsDebugMsg("found subsymbol with invalid name: "+it.key());
-      delete it.value(); // we must delete it
-      continue; // some invalid syntax
+      QgsVectorColorRampV2* ramp = loadColorRamp(e);
+      if (ramp != NULL)
+        addColorRamp(e.attribute("name"), ramp);
     }
-    QString symname = parts[1];
-    int symlayer = parts[2].toInt();
-    
-    if (!mSymbols.contains(symname))
+    else
     {
-      QgsDebugMsg("subsymbol references invalid symbol: " + symname);
-      delete it.value(); // we must delete it
-      continue;
+      QgsDebugMsg("unknown tag: " + e.tagName());
     }
-    
-    QgsSymbolV2* sym = mSymbols[symname];
-    if (symlayer < 0 || symlayer >= sym->symbolLayerCount())
-    {
-      QgsDebugMsg("subsymbol references invalid symbol layer: "+ QString::number(symlayer));
-      delete it.value(); // we must delete it
-      continue;
-    }
-    
-    // set subsymbol takes ownership
-    bool res = sym->symbolLayer(symlayer)->setSubSymbol( it.value() );
-    if (!res)
-    {
-      QgsDebugMsg("symbol layer refused subsymbol: " + it.key());
-    }
-    
-    
+    e = e.nextSiblingElement();
   }
-  
-  // now safely remove sub-symbol entries (they have been already deleted or the ownership was taken away)
-  for (int i = 0; i < subsymbols.count(); i++)
-    mSymbols.take(subsymbols[i]);
-  
+
   return true;
 }
 
 
-QgsSymbolV2* QgsStyleV2::loadSymbol(QDomElement& element)
-{
-  QgsSymbolLayerV2List layers;
-  QDomNode layerNode = element.firstChild();
-  
-  while (!layerNode.isNull())
-  {
-    QDomElement e = layerNode.toElement();
-    if (!e.isNull())
-    {
-      if (e.tagName() != "layer")
-      {
-        QgsDebugMsg("unknown tag " + e.tagName());
-      }
-      else
-      {
-        QgsSymbolLayerV2* layer = loadSymbolLayer(e);
-        if (layer != NULL)
-          layers.append(layer);
-      }
-    }
-    layerNode = layerNode.nextSibling();
-  }
-  
-  if (layers.count() == 0)
-  {
-    QgsDebugMsg("no layers for symbol");
-    return NULL;
-  }
-  
-  QString symbolType = element.attribute("type");
-  if (symbolType == "line")
-    return new QgsLineSymbolV2(layers);
-  else if (symbolType == "fill")
-    return new QgsFillSymbolV2(layers);
-  else if (symbolType == "marker")
-    return new QgsMarkerSymbolV2(layers);
-  else
-  {
-    QgsDebugMsg("unknown symbol type " + symbolType);
-    return NULL;
-  }  
-}
-
-QgsSymbolLayerV2* QgsStyleV2::loadSymbolLayer(QDomElement& element)
-{
-  QString layerClass = element.attribute("class");
-  bool locked = element.attribute("locked").toInt();
-  
-  // parse properties
-  QgsStringMap props = parseProperties(element);
-  
-  QgsSymbolLayerV2* layer;
-  layer = QgsSymbolLayerV2Registry::instance()->createSymbolLayer(layerClass, props);
-  if (layer)
-  {
-    layer->setLocked(locked);
-    return layer;
-  }
-  else
-  {
-    QgsDebugMsg("unknown class " + layerClass);
-    return NULL;
-  }
-}
-
 QgsVectorColorRampV2* QgsStyleV2::loadColorRamp(QDomElement& element)
 {
   QString rampType = element.attribute("type");
   
   // parse properties
-  QgsStringMap props = parseProperties(element);
+  QgsStringMap props = QgsSymbolLayerV2Utils::parseProperties(element);
   
   if (rampType == "gradient")
     return QgsVectorGradientColorRampV2::create(props);
@@ -362,43 +239,7 @@
 }
 
 
-QgsStringMap QgsStyleV2::parseProperties(QDomElement& element)
-{
-  QgsStringMap props;
-  QDomNode propNode = element.firstChild();
-  while (!propNode.isNull())
-  {
-    QDomElement e = propNode.toElement();
-    if (!e.isNull())
-    {
-      if (e.tagName() != "prop")
-      {
-        QgsDebugMsg("unknown tag " + e.tagName());
-      }
-      else
-      {
-        QString propKey = e.attribute("k");
-        QString propValue = e.attribute("v");
-        props[propKey] = propValue;
-      }
-    }
-    propNode = propNode.nextSibling();
-  }
-  return props;
-}
 
-void QgsStyleV2::saveProperties(QgsStringMap props, QDomDocument& doc, QDomElement& element)
-{
-  for (QgsStringMap::iterator it = props.begin(); it != props.end(); ++it)
-  {
-    QDomElement propEl = doc.createElement("prop");
-    propEl.setAttribute("k", it.key());
-    propEl.setAttribute("v", it.value());
-    element.appendChild(propEl);
-  }
-}
-
-
 bool QgsStyleV2::save(QString filename)
 {
   mErrorString = QString();
@@ -409,29 +250,20 @@
   QDomElement root = doc.createElement("qgis_style");
   root.setAttribute("version", STYLE_CURRENT_VERSION);
   doc.appendChild(root);
+
+  QDomElement symbolsElem = QgsSymbolLayerV2Utils::saveSymbols(mSymbols, doc);
+
+  QDomElement rampsElem = doc.createElement("colorramps");
   
-  QMap<QString, QgsSymbolV2*> subSymbols;
-  
-  // save symbols
-  for (QMap<QString, QgsSymbolV2*>::iterator its = mSymbols.begin(); its != mSymbols.end(); ++its)
-  {
-    QDomElement symEl = saveSymbol(its.key(), its.value(), doc, &subSymbols);
-    root.appendChild(symEl);
-  }
-  
-  // add subsymbols, don't allow subsymbols for them (to keep things simple)
-  for (QMap<QString, QgsSymbolV2*>::iterator itsub = subSymbols.begin(); itsub != subSymbols.end(); ++itsub)
-  {
-    QDomElement subsymEl = saveSymbol(itsub.key(), itsub.value(), doc);
-    root.appendChild(subsymEl);
-  }
-  
   // save color ramps
   for (QMap<QString, QgsVectorColorRampV2*>::iterator itr = mColorRamps.begin(); itr != mColorRamps.end(); ++itr)
   {
     QDomElement rampEl = saveColorRamp(itr.key(), itr.value(), doc);
-    root.appendChild(rampEl);
+    rampsElem.appendChild(rampEl);
   }
+
+  root.appendChild(symbolsElem);
+  root.appendChild(rampsElem);
   
   // save
   QFile f(filename);
@@ -447,49 +279,12 @@
   return true;
 }
 
-static QString _nameForSymbolType(QgsSymbolV2::SymbolType type)
-{
-  switch (type)
-  {
-    case QgsSymbolV2::Line: return "line";
-    case QgsSymbolV2::Marker: return "marker";
-    case QgsSymbolV2::Fill: return "fill";
-  }
-}
-
-QDomElement QgsStyleV2::saveSymbol(QString name, QgsSymbolV2* symbol, QDomDocument& doc, QgsSymbolV2Map* subSymbols)
-{
-  QDomElement symEl = doc.createElement("symbol");
-  symEl.setAttribute("type", _nameForSymbolType(symbol->type()) );
-  symEl.setAttribute("name", name);
-  
-  for (int i = 0; i < symbol->symbolLayerCount(); i++)
-  {
-    QgsSymbolLayerV2* layer = symbol->symbolLayer(i);
-    
-    QDomElement layerEl = doc.createElement("layer");
-    layerEl.setAttribute("class", layer->layerType());
-    layerEl.setAttribute("locked", layer->isLocked());
-    
-    if (subSymbols != NULL && layer->subSymbol() != NULL)
-    {
-      QString subname = QString("@%1@%2").arg(name).arg(i);
-      subSymbols->insert(subname, layer->subSymbol());
-    }
-    
-    saveProperties(layer->properties(), doc, layerEl);
-    symEl.appendChild(layerEl);
-  }
-
-  return symEl;
-}
-
 QDomElement QgsStyleV2::saveColorRamp(QString name, QgsVectorColorRampV2* ramp, QDomDocument& doc)
 {
   QDomElement rampEl = doc.createElement("colorramp");
   rampEl.setAttribute("type", ramp->type());
   rampEl.setAttribute("name", name);
   
-  saveProperties(ramp->properties(), doc, rampEl);
+  QgsSymbolLayerV2Utils::saveProperties(ramp->properties(), doc, rampEl);
   return rampEl;
 }

Modified: branches/symbology-ng-branch/src/core/symbology-ng/qgsstylev2.h
===================================================================
--- branches/symbology-ng-branch/src/core/symbology-ng/qgsstylev2.h	2009-11-01 23:45:49 UTC (rev 11880)
+++ branches/symbology-ng-branch/src/core/symbology-ng/qgsstylev2.h	2009-11-01 23:47:56 UTC (rev 11881)
@@ -14,7 +14,6 @@
 class QDomDocument;
 class QDomElement;
 
-typedef QMap<QString, QgsSymbolV2* > QgsSymbolV2Map;
 typedef QMap<QString, QgsVectorColorRampV2* > QgsVectorColorRampV2Map;
 
 class QgsStyleV2
@@ -79,16 +78,10 @@
   
 protected:
 
-  QgsStringMap parseProperties(QDomElement& element);
-  void saveProperties(QgsStringMap props, QDomDocument& doc, QDomElement& element);
-  
-  QgsSymbolV2* loadSymbol(QDomElement& element);
-  QgsSymbolLayerV2* loadSymbolLayer(QDomElement& element);
   QgsVectorColorRampV2* loadColorRamp(QDomElement& element);
   
-  QDomElement saveSymbol(QString name, QgsSymbolV2* symbol, QDomDocument& doc, QgsSymbolV2Map* subSymbols = NULL);
   QDomElement saveColorRamp(QString name, QgsVectorColorRampV2* ramp, QDomDocument& doc);
-  
+
   QgsSymbolV2Map mSymbols;
   QgsVectorColorRampV2Map mColorRamps;
   

Modified: branches/symbology-ng-branch/src/core/symbology-ng/qgssymbollayerv2utils.cpp
===================================================================
--- branches/symbology-ng-branch/src/core/symbology-ng/qgssymbollayerv2utils.cpp	2009-11-01 23:45:49 UTC (rev 11880)
+++ branches/symbology-ng-branch/src/core/symbology-ng/qgssymbollayerv2utils.cpp	2009-11-01 23:47:56 UTC (rev 11881)
@@ -2,10 +2,15 @@
 #include "qgssymbollayerv2utils.h"
 
 #include "qgssymbollayerv2.h"
+#include "qgssymbollayerv2registry.h"
 #include "qgssymbolv2.h"
 #include "qgsvectorcolorrampv2.h"
 
+#include "qgslogger.h"
+
 #include <QColor>
+#include <QDomNode>
+#include <QDomElement>
 #include <QIcon>
 #include <QPainter>
 
@@ -290,3 +295,252 @@
   newLine.append(pt_new);
   return newLine;
 }
+
+/////
+
+
+QgsSymbolV2* QgsSymbolLayerV2Utils::loadSymbol(QDomElement& element)
+{
+  QgsSymbolLayerV2List layers;
+  QDomNode layerNode = element.firstChild();
+
+  while (!layerNode.isNull())
+  {
+    QDomElement e = layerNode.toElement();
+    if (!e.isNull())
+    {
+      if (e.tagName() != "layer")
+      {
+        QgsDebugMsg("unknown tag " + e.tagName());
+      }
+      else
+      {
+        QgsSymbolLayerV2* layer = loadSymbolLayer(e);
+        if (layer != NULL)
+          layers.append(layer);
+      }
+    }
+    layerNode = layerNode.nextSibling();
+  }
+
+  if (layers.count() == 0)
+  {
+    QgsDebugMsg("no layers for symbol");
+    return NULL;
+  }
+
+  QString symbolType = element.attribute("type");
+  if (symbolType == "line")
+    return new QgsLineSymbolV2(layers);
+  else if (symbolType == "fill")
+    return new QgsFillSymbolV2(layers);
+  else if (symbolType == "marker")
+    return new QgsMarkerSymbolV2(layers);
+  else
+  {
+    QgsDebugMsg("unknown symbol type " + symbolType);
+    return NULL;
+  }
+}
+
+QgsSymbolLayerV2* QgsSymbolLayerV2Utils::loadSymbolLayer(QDomElement& element)
+{
+  QString layerClass = element.attribute("class");
+  bool locked = element.attribute("locked").toInt();
+
+  // parse properties
+  QgsStringMap props = parseProperties(element);
+
+  QgsSymbolLayerV2* layer;
+  layer = QgsSymbolLayerV2Registry::instance()->createSymbolLayer(layerClass, props);
+  if (layer)
+  {
+    layer->setLocked(locked);
+    return layer;
+  }
+  else
+  {
+    QgsDebugMsg("unknown class " + layerClass);
+    return NULL;
+  }
+}
+
+static QString _nameForSymbolType(QgsSymbolV2::SymbolType type)
+{
+  switch (type)
+  {
+    case QgsSymbolV2::Line: return "line";
+    case QgsSymbolV2::Marker: return "marker";
+    case QgsSymbolV2::Fill: return "fill";
+  }
+}
+
+QDomElement QgsSymbolLayerV2Utils::saveSymbol(QString name, QgsSymbolV2* symbol, QDomDocument& doc, QgsSymbolV2Map* subSymbols)
+{
+  QDomElement symEl = doc.createElement("symbol");
+  symEl.setAttribute("type", _nameForSymbolType(symbol->type()) );
+  symEl.setAttribute("name", name);
+
+  QgsDebugMsg("num layers " + QString::number(symbol->symbolLayerCount()));
+  for (int i = 0; i < symbol->symbolLayerCount(); i++)
+  {
+    QgsSymbolLayerV2* layer = symbol->symbolLayer(i);
+
+    QDomElement layerEl = doc.createElement("layer");
+    layerEl.setAttribute("class", layer->layerType());
+    layerEl.setAttribute("locked", layer->isLocked());
+
+    if (subSymbols != NULL && layer->subSymbol() != NULL)
+    {
+      QString subname = QString("@%1@%2").arg(name).arg(i);
+      subSymbols->insert(subname, layer->subSymbol());
+    }
+
+    saveProperties(layer->properties(), doc, layerEl);
+    symEl.appendChild(layerEl);
+  }
+
+  return symEl;
+}
+
+
+QgsStringMap QgsSymbolLayerV2Utils::parseProperties(QDomElement& element)
+{
+  QgsStringMap props;
+  QDomElement e = element.firstChildElement();
+  while (!e.isNull())
+  {
+    if (e.tagName() != "prop")
+    {
+      QgsDebugMsg("unknown tag " + e.tagName());
+    }
+    else
+    {
+      QString propKey = e.attribute("k");
+      QString propValue = e.attribute("v");
+      props[propKey] = propValue;
+    }
+    e = e.nextSiblingElement();
+  }
+  return props;
+}
+
+
+void QgsSymbolLayerV2Utils::saveProperties(QgsStringMap props, QDomDocument& doc, QDomElement& element)
+{
+  for (QgsStringMap::iterator it = props.begin(); it != props.end(); ++it)
+  {
+    QDomElement propEl = doc.createElement("prop");
+    propEl.setAttribute("k", it.key());
+    propEl.setAttribute("v", it.value());
+    element.appendChild(propEl);
+  }
+}
+
+QgsSymbolV2Map QgsSymbolLayerV2Utils::loadSymbols(QDomElement& element)
+{
+  // go through symbols one-by-one and load them
+
+  QgsSymbolV2Map symbols;
+  QDomElement e = element.firstChildElement();
+
+  while (!e.isNull())
+  {
+    if (e.tagName() == "symbol")
+    {
+      QgsSymbolV2* symbol = QgsSymbolLayerV2Utils::loadSymbol(e);
+      if (symbol != NULL)
+        symbols.insert(e.attribute("name"), symbol);
+    }
+    else
+    {
+      QgsDebugMsg("unknown tag: " + e.tagName());
+    }
+    e = e.nextSiblingElement();
+  }
+
+
+  // now walk through the list of symbols and find those prefixed with @
+  // these symbols are sub-symbols of some other symbol layers
+  // e.g. symbol named "@foo at 1" is sub-symbol of layer 1 in symbol "foo"
+  QStringList subsymbols;
+
+  for (QMap<QString, QgsSymbolV2*>::iterator it = symbols.begin(); it != symbols.end(); ++it)
+  {
+    if (it.key()[0] != '@')
+      continue;
+
+    // add to array (for deletion)
+    subsymbols.append(it.key());
+
+    QStringList parts = it.key().split("@");
+    if (parts.count() < 3)
+    {
+      QgsDebugMsg("found subsymbol with invalid name: "+it.key());
+      delete it.value(); // we must delete it
+      continue; // some invalid syntax
+    }
+    QString symname = parts[1];
+    int symlayer = parts[2].toInt();
+
+    if (!symbols.contains(symname))
+    {
+      QgsDebugMsg("subsymbol references invalid symbol: " + symname);
+      delete it.value(); // we must delete it
+      continue;
+    }
+
+    QgsSymbolV2* sym = symbols[symname];
+    if (symlayer < 0 || symlayer >= sym->symbolLayerCount())
+    {
+      QgsDebugMsg("subsymbol references invalid symbol layer: "+ QString::number(symlayer));
+      delete it.value(); // we must delete it
+      continue;
+    }
+
+    // set subsymbol takes ownership
+    bool res = sym->symbolLayer(symlayer)->setSubSymbol( it.value() );
+    if (!res)
+    {
+      QgsDebugMsg("symbol layer refused subsymbol: " + it.key());
+    }
+
+
+  }
+
+  // now safely remove sub-symbol entries (they have been already deleted or the ownership was taken away)
+  for (int i = 0; i < subsymbols.count(); i++)
+    symbols.take(subsymbols[i]);
+
+  return symbols;
+}
+
+QDomElement QgsSymbolLayerV2Utils::saveSymbols(QgsSymbolV2Map& symbols, QDomDocument& doc)
+{
+  QDomElement symbolsElem = doc.createElement("symbols");
+
+  QMap<QString, QgsSymbolV2*> subSymbols;
+
+  // save symbols
+  for (QMap<QString, QgsSymbolV2*>::iterator its = symbols.begin(); its != symbols.end(); ++its)
+  {
+    QDomElement symEl = saveSymbol(its.key(), its.value(), doc, &subSymbols);
+    symbolsElem.appendChild(symEl);
+  }
+
+  // add subsymbols, don't allow subsymbols for them (to keep things simple)
+  for (QMap<QString, QgsSymbolV2*>::iterator itsub = subSymbols.begin(); itsub != subSymbols.end(); ++itsub)
+  {
+    QDomElement subsymEl = saveSymbol(itsub.key(), itsub.value(), doc);
+    symbolsElem.appendChild(subsymEl);
+  }
+
+  return symbolsElem;
+}
+
+void QgsSymbolLayerV2Utils::clearSymbolMap(QgsSymbolV2Map& symbols)
+{
+  foreach (QString name, symbols.keys())
+    delete symbols.value(name);
+  symbols.clear();
+}

Modified: branches/symbology-ng-branch/src/core/symbology-ng/qgssymbollayerv2utils.h
===================================================================
--- branches/symbology-ng-branch/src/core/symbology-ng/qgssymbollayerv2utils.h	2009-11-01 23:45:49 UTC (rev 11880)
+++ branches/symbology-ng-branch/src/core/symbology-ng/qgssymbollayerv2utils.h	2009-11-01 23:47:56 UTC (rev 11881)
@@ -6,13 +6,16 @@
 #include <QMap>
 #include <Qt>
 
-typedef QMap<QString, QString> QgsStringMap;
-
 class QgsSymbolV2;
 class QgsSymbolLayerV2;
 class QgsVectorColorRampV2;
 
+typedef QMap<QString, QString> QgsStringMap;
+typedef QMap<QString, QgsSymbolV2* > QgsSymbolV2Map;
+
 class QColor;
+class QDomDocument;
+class QDomElement;
 class QIcon;
 class QPixmap;
 class QPointF;
@@ -45,6 +48,18 @@
   static QIcon colorRampPreviewIcon(QgsVectorColorRampV2* ramp, QSize size);
 
   static QPixmap colorRampPreviewPixmap(QgsVectorColorRampV2* ramp, QSize size);
+
+  static QgsSymbolV2* loadSymbol(QDomElement& element);
+  static QgsSymbolLayerV2* loadSymbolLayer(QDomElement& element);
+  static QDomElement saveSymbol(QString name, QgsSymbolV2* symbol, QDomDocument& doc, QgsSymbolV2Map* subSymbols = NULL);
+
+  static QgsStringMap parseProperties(QDomElement& element);
+  static void saveProperties(QgsStringMap props, QDomDocument& doc, QDomElement& element);
+
+  static QgsSymbolV2Map loadSymbols(QDomElement& element);
+  static QDomElement saveSymbols(QgsSymbolV2Map& symbols, QDomDocument& doc);
+
+  static void clearSymbolMap(QgsSymbolV2Map& symbols);
 };
 
 class QPolygonF;



More information about the QGIS-commit mailing list