00001
00002 #include "qgscategorizedsymbolrendererv2.h"
00003
00004 #include "qgssymbolv2.h"
00005 #include "qgssymbollayerv2utils.h"
00006 #include "qgsvectorcolorrampv2.h"
00007
00008 #include "qgsfeature.h"
00009 #include "qgsvectorlayer.h"
00010 #include "qgslogger.h"
00011
00012 #include <QDomDocument>
00013 #include <QDomElement>
00014 #include <QSettings>
00015
00016 QgsRendererCategoryV2::QgsRendererCategoryV2( QVariant value, QgsSymbolV2* symbol, QString label )
00017 : mValue( value ), mSymbol( symbol ), mLabel( label )
00018 {
00019 }
00020
00021 QgsRendererCategoryV2::QgsRendererCategoryV2( const QgsRendererCategoryV2& cat )
00022 : mValue( cat.mValue ), mLabel( cat.mLabel )
00023 {
00024 mSymbol = cat.mSymbol->clone();
00025 }
00026
00027
00028 QgsRendererCategoryV2::~QgsRendererCategoryV2()
00029 {
00030 delete mSymbol;
00031 }
00032
00033 QVariant QgsRendererCategoryV2::value() const
00034 {
00035 return mValue;
00036 }
00037
00038 QgsSymbolV2* QgsRendererCategoryV2::symbol() const
00039 {
00040 return mSymbol;
00041 }
00042
00043 QString QgsRendererCategoryV2::label() const
00044 {
00045 return mLabel;
00046 }
00047
00048 void QgsRendererCategoryV2::setValue( const QVariant &value )
00049 {
00050 mValue = value;
00051 }
00052
00053 void QgsRendererCategoryV2::setSymbol( QgsSymbolV2* s )
00054 {
00055 if ( mSymbol == s )
00056 return;
00057 delete mSymbol;
00058 mSymbol = s;
00059 }
00060
00061 void QgsRendererCategoryV2::setLabel( const QString &label )
00062 {
00063 mLabel = label;
00064 }
00065
00066 QString QgsRendererCategoryV2::dump()
00067 {
00068 return QString( "%1::%2::%3\n" ).arg( mValue.toString() ).arg( mLabel ).arg( mSymbol->dump() );
00069 }
00070
00072
00073 QgsCategorizedSymbolRendererV2::QgsCategorizedSymbolRendererV2( QString attrName, QgsCategoryList categories )
00074 : QgsFeatureRendererV2( "categorizedSymbol" ),
00075 mAttrName( attrName ),
00076 mCategories( categories ),
00077 mSourceSymbol( NULL ),
00078 mSourceColorRamp( NULL )
00079 {
00080 for ( int i = 0; i < mCategories.count(); ++i )
00081 {
00082 QgsRendererCategoryV2& cat = mCategories[i];
00083 if ( cat.symbol() == NULL )
00084 {
00085 QgsDebugMsg( "invalid symbol in a category! ignoring..." );
00086 mCategories.removeAt( i-- );
00087 }
00088
00089 }
00090 }
00091
00092 QgsCategorizedSymbolRendererV2::~QgsCategorizedSymbolRendererV2()
00093 {
00094 mCategories.clear();
00095 delete mSourceSymbol;
00096 delete mSourceColorRamp;
00097 }
00098
00099 void QgsCategorizedSymbolRendererV2::rebuildHash()
00100 {
00101 mSymbolHash.clear();
00102
00103 for ( int i = 0; i < mCategories.count(); ++i )
00104 {
00105 QgsRendererCategoryV2& cat = mCategories[i];
00106 mSymbolHash.insert( cat.value().toString(), cat.symbol() );
00107 }
00108 }
00109
00110 QgsSymbolV2* QgsCategorizedSymbolRendererV2::symbolForValue( QVariant value )
00111 {
00112
00113
00114 QHash<QString, QgsSymbolV2*>::iterator it = mSymbolHash.find( value.toString() );
00115 if ( it == mSymbolHash.end() )
00116 {
00117 if ( mSymbolHash.count() == 0 )
00118 QgsDebugMsg( "there are no hashed symbols!!!" );
00119 else
00120 QgsDebugMsg( "attribute value not found: " + value.toString() );
00121 return NULL;
00122 }
00123
00124 return *it;
00125 }
00126
00127 QgsSymbolV2* QgsCategorizedSymbolRendererV2::symbolForFeature( QgsFeature& feature )
00128 {
00129 const QgsAttributeMap& attrMap = feature.attributeMap();
00130 QgsAttributeMap::const_iterator ita = attrMap.find( mAttrNum );
00131 if ( ita == attrMap.end() )
00132 {
00133 QgsDebugMsg( "attribute '" + mAttrName + "' (index " + QString::number( mAttrNum ) + ") required by renderer not found" );
00134 return NULL;
00135 }
00136
00137
00138 QgsSymbolV2* symbol = symbolForValue( *ita );
00139
00140 if ( mRotationFieldIdx == -1 && mSizeScaleFieldIdx == -1 )
00141 return symbol;
00142
00143
00144 double rotation = 0;
00145 double sizeScale = 1;
00146 if ( mRotationFieldIdx != -1 )
00147 rotation = attrMap[mRotationFieldIdx].toDouble();
00148 if ( mSizeScaleFieldIdx != -1 )
00149 sizeScale = attrMap[mSizeScaleFieldIdx].toDouble();
00150
00151
00152 QgsSymbolV2* tempSymbol = mTempSymbols[ita->toString()];
00153
00154
00155 if ( tempSymbol->type() == QgsSymbolV2::Marker )
00156 {
00157 QgsMarkerSymbolV2* markerSymbol = static_cast<QgsMarkerSymbolV2*>( tempSymbol );
00158 if ( mRotationFieldIdx != -1 )
00159 markerSymbol->setAngle( rotation );
00160 if ( mSizeScaleFieldIdx != -1 )
00161 markerSymbol->setSize( sizeScale * static_cast<QgsMarkerSymbolV2*>( symbol )->size() );
00162 }
00163 else if ( tempSymbol->type() == QgsSymbolV2::Line )
00164 {
00165 QgsLineSymbolV2* lineSymbol = static_cast<QgsLineSymbolV2*>( tempSymbol );
00166 if ( mSizeScaleFieldIdx != -1 )
00167 lineSymbol->setWidth( sizeScale * static_cast<QgsLineSymbolV2*>( symbol )->width() );
00168 }
00169
00170 return tempSymbol;
00171 }
00172
00173 int QgsCategorizedSymbolRendererV2::categoryIndexForValue( QVariant val )
00174 {
00175 for ( int i = 0; i < mCategories.count(); i++ )
00176 {
00177 if ( mCategories[i].value() == val )
00178 return i;
00179 }
00180 return -1;
00181 }
00182
00183 bool QgsCategorizedSymbolRendererV2::updateCategoryValue( int catIndex, const QVariant &value )
00184 {
00185 if ( catIndex < 0 || catIndex >= mCategories.size() )
00186 return false;
00187 mCategories[catIndex].setValue( value );
00188 return true;
00189 }
00190
00191 bool QgsCategorizedSymbolRendererV2::updateCategorySymbol( int catIndex, QgsSymbolV2* symbol )
00192 {
00193 if ( catIndex < 0 || catIndex >= mCategories.size() )
00194 return false;
00195 mCategories[catIndex].setSymbol( symbol );
00196 return true;
00197 }
00198
00199 bool QgsCategorizedSymbolRendererV2::updateCategoryLabel( int catIndex, QString label )
00200 {
00201 if ( catIndex < 0 || catIndex >= mCategories.size() )
00202 return false;
00203 mCategories[catIndex].setLabel( label );
00204 return true;
00205 }
00206
00207 void QgsCategorizedSymbolRendererV2::addCategory( const QgsRendererCategoryV2 &cat )
00208 {
00209 if ( cat.symbol() == NULL )
00210 {
00211 QgsDebugMsg( "invalid symbol in a category! ignoring..." );
00212 }
00213 else
00214 {
00215 mCategories.append( cat );
00216 }
00217 }
00218
00219 bool QgsCategorizedSymbolRendererV2::deleteCategory( int catIndex )
00220 {
00221 if ( catIndex < 0 || catIndex >= mCategories.size() )
00222 return false;
00223
00224 mCategories.removeAt( catIndex );
00225 return true;
00226 }
00227
00228 void QgsCategorizedSymbolRendererV2::deleteAllCategories()
00229 {
00230 mCategories.clear();
00231 }
00232
00233 void QgsCategorizedSymbolRendererV2::startRender( QgsRenderContext& context, const QgsVectorLayer *vlayer )
00234 {
00235
00236 rebuildHash();
00237
00238
00239 mAttrNum = vlayer ? vlayer->fieldNameIndex( mAttrName ) : -1;
00240
00241 mRotationFieldIdx = ( mRotationField.isEmpty() ? -1 : vlayer->fieldNameIndex( mRotationField ) );
00242 mSizeScaleFieldIdx = ( mSizeScaleField.isEmpty() ? -1 : vlayer->fieldNameIndex( mSizeScaleField ) );
00243
00244 QgsCategoryList::iterator it = mCategories.begin();
00245 for ( ; it != mCategories.end(); ++it )
00246 {
00247 it->symbol()->startRender( context );
00248
00249 if ( mRotationFieldIdx != -1 || mSizeScaleFieldIdx != -1 )
00250 {
00251 QgsSymbolV2* tempSymbol = it->symbol()->clone();
00252 tempSymbol->setRenderHints(( mRotationFieldIdx != -1 ? QgsSymbolV2::DataDefinedRotation : 0 ) |
00253 ( mSizeScaleFieldIdx != -1 ? QgsSymbolV2::DataDefinedSizeScale : 0 ) );
00254 tempSymbol->startRender( context );
00255 mTempSymbols[ it->value().toString()] = tempSymbol;
00256 }
00257 }
00258
00259 }
00260
00261 void QgsCategorizedSymbolRendererV2::stopRender( QgsRenderContext& context )
00262 {
00263 QgsCategoryList::iterator it = mCategories.begin();
00264 for ( ; it != mCategories.end(); ++it )
00265 it->symbol()->stopRender( context );
00266
00267
00268 QHash<QString, QgsSymbolV2*>::iterator it2 = mTempSymbols.begin();
00269 for ( ; it2 != mTempSymbols.end(); ++it2 )
00270 {
00271 it2.value()->stopRender( context );
00272 delete it2.value();
00273 }
00274 mTempSymbols.clear();
00275 }
00276
00277 QList<QString> QgsCategorizedSymbolRendererV2::usedAttributes()
00278 {
00279 QList<QString> lst;
00280 lst.append( mAttrName );
00281 if ( !mRotationField.isEmpty() )
00282 lst.append( mRotationField );
00283 if ( !mSizeScaleField.isEmpty() )
00284 lst.append( mSizeScaleField );
00285 return lst;
00286 }
00287
00288 QString QgsCategorizedSymbolRendererV2::dump()
00289 {
00290 QString s = QString( "CATEGORIZED: idx %1\n" ).arg( mAttrName );
00291 for ( int i = 0; i < mCategories.count(); i++ )
00292 s += mCategories[i].dump();
00293 return s;
00294 }
00295
00296 QgsFeatureRendererV2* QgsCategorizedSymbolRendererV2::clone()
00297 {
00298 QgsCategorizedSymbolRendererV2* r = new QgsCategorizedSymbolRendererV2( mAttrName, mCategories );
00299 if ( mSourceSymbol )
00300 r->setSourceSymbol( mSourceSymbol->clone() );
00301 if ( mSourceColorRamp )
00302 r->setSourceColorRamp( mSourceColorRamp->clone() );
00303 r->setUsingSymbolLevels( usingSymbolLevels() );
00304 r->setRotationField( rotationField() );
00305 r->setSizeScaleField( sizeScaleField() );
00306 return r;
00307 }
00308
00309 QgsSymbolV2List QgsCategorizedSymbolRendererV2::symbols()
00310 {
00311 QgsSymbolV2List lst;
00312 for ( int i = 0; i < mCategories.count(); i++ )
00313 lst.append( mCategories[i].symbol() );
00314 return lst;
00315 }
00316
00317 QgsFeatureRendererV2* QgsCategorizedSymbolRendererV2::create( QDomElement& element )
00318 {
00319 QDomElement symbolsElem = element.firstChildElement( "symbols" );
00320 if ( symbolsElem.isNull() )
00321 return NULL;
00322
00323 QDomElement catsElem = element.firstChildElement( "categories" );
00324 if ( catsElem.isNull() )
00325 return NULL;
00326
00327 QgsSymbolV2Map symbolMap = QgsSymbolLayerV2Utils::loadSymbols( symbolsElem );
00328 QgsCategoryList cats;
00329
00330 QDomElement catElem = catsElem.firstChildElement();
00331 while ( !catElem.isNull() )
00332 {
00333 if ( catElem.tagName() == "category" )
00334 {
00335 QVariant value = QVariant( catElem.attribute( "value" ) );
00336 QString symbolName = catElem.attribute( "symbol" );
00337 QString label = catElem.attribute( "label" );
00338 if ( symbolMap.contains( symbolName ) )
00339 {
00340 QgsSymbolV2* symbol = symbolMap.take( symbolName );
00341 cats.append( QgsRendererCategoryV2( value, symbol, label ) );
00342 }
00343 }
00344 catElem = catElem.nextSiblingElement();
00345 }
00346
00347 QString attrName = element.attribute( "attr" );
00348
00349 QgsCategorizedSymbolRendererV2* r = new QgsCategorizedSymbolRendererV2( attrName, cats );
00350
00351
00352 QgsSymbolLayerV2Utils::clearSymbolMap( symbolMap );
00353
00354
00355 QDomElement sourceSymbolElem = element.firstChildElement( "source-symbol" );
00356 if ( !sourceSymbolElem.isNull() )
00357 {
00358 QgsSymbolV2Map sourceSymbolMap = QgsSymbolLayerV2Utils::loadSymbols( sourceSymbolElem );
00359 if ( sourceSymbolMap.contains( "0" ) )
00360 {
00361 r->setSourceSymbol( sourceSymbolMap.take( "0" ) );
00362 }
00363 QgsSymbolLayerV2Utils::clearSymbolMap( sourceSymbolMap );
00364 }
00365
00366
00367 QDomElement sourceColorRampElem = element.firstChildElement( "colorramp" );
00368 if ( !sourceColorRampElem.isNull() && sourceColorRampElem.attribute( "name" ) == "[source]" )
00369 {
00370 r->setSourceColorRamp( QgsSymbolLayerV2Utils::loadColorRamp( sourceColorRampElem ) );
00371 }
00372
00373 QDomElement rotationElem = element.firstChildElement( "rotation" );
00374 if ( !rotationElem.isNull() )
00375 r->setRotationField( rotationElem.attribute( "field" ) );
00376
00377 QDomElement sizeScaleElem = element.firstChildElement( "sizescale" );
00378 if ( !sizeScaleElem.isNull() )
00379 r->setSizeScaleField( sizeScaleElem.attribute( "field" ) );
00380
00381
00382 return r;
00383 }
00384
00385 QDomElement QgsCategorizedSymbolRendererV2::save( QDomDocument& doc )
00386 {
00387 QDomElement rendererElem = doc.createElement( RENDERER_TAG_NAME );
00388 rendererElem.setAttribute( "type", "categorizedSymbol" );
00389 rendererElem.setAttribute( "symbollevels", ( mUsingSymbolLevels ? "1" : "0" ) );
00390 rendererElem.setAttribute( "attr", mAttrName );
00391
00392
00393 int i = 0;
00394 QgsSymbolV2Map symbols;
00395 QDomElement catsElem = doc.createElement( "categories" );
00396 QgsCategoryList::const_iterator it = mCategories.constBegin();
00397 for ( ; it != mCategories.end(); it++ )
00398 {
00399 const QgsRendererCategoryV2& cat = *it;
00400 QString symbolName = QString::number( i );
00401 symbols.insert( symbolName, cat.symbol() );
00402
00403 QDomElement catElem = doc.createElement( "category" );
00404 catElem.setAttribute( "value", cat.value().toString() );
00405 catElem.setAttribute( "symbol", symbolName );
00406 catElem.setAttribute( "label", cat.label() );
00407 catsElem.appendChild( catElem );
00408 i++;
00409 }
00410
00411 rendererElem.appendChild( catsElem );
00412
00413
00414 QDomElement symbolsElem = QgsSymbolLayerV2Utils::saveSymbols( symbols, "symbols", doc );
00415 rendererElem.appendChild( symbolsElem );
00416
00417
00418 if ( mSourceSymbol )
00419 {
00420 QgsSymbolV2Map sourceSymbols;
00421 sourceSymbols.insert( "0", mSourceSymbol );
00422 QDomElement sourceSymbolElem = QgsSymbolLayerV2Utils::saveSymbols( sourceSymbols, "source-symbol", doc );
00423 rendererElem.appendChild( sourceSymbolElem );
00424 }
00425
00426
00427 if ( mSourceColorRamp )
00428 {
00429 QDomElement colorRampElem = QgsSymbolLayerV2Utils::saveColorRamp( "[source]", mSourceColorRamp, doc );
00430 rendererElem.appendChild( colorRampElem );
00431 }
00432
00433 QDomElement rotationElem = doc.createElement( "rotation" );
00434 rotationElem.setAttribute( "field", mRotationField );
00435 rendererElem.appendChild( rotationElem );
00436
00437 QDomElement sizeScaleElem = doc.createElement( "sizescale" );
00438 sizeScaleElem.setAttribute( "field", mSizeScaleField );
00439 rendererElem.appendChild( sizeScaleElem );
00440
00441 return rendererElem;
00442 }
00443
00444 QgsLegendSymbologyList QgsCategorizedSymbolRendererV2::legendSymbologyItems( QSize iconSize )
00445 {
00446 QSettings settings;
00447 bool showClassifiers = settings.value( "/qgis/showLegendClassifiers", false ).toBool();
00448
00449 QgsLegendSymbologyList lst;
00450 if ( showClassifiers )
00451 {
00452 lst << qMakePair( classAttribute(), QPixmap() );
00453 }
00454
00455 int count = categories().count();
00456 for ( int i = 0; i < count; i++ )
00457 {
00458 const QgsRendererCategoryV2& cat = categories()[i];
00459 QPixmap pix = QgsSymbolLayerV2Utils::symbolPreviewPixmap( cat.symbol(), iconSize );
00460 lst << qMakePair( cat.label(), pix );
00461 }
00462 return lst;
00463 }
00464
00465 QgsLegendSymbolList QgsCategorizedSymbolRendererV2::legendSymbolItems()
00466 {
00467 QSettings settings;
00468 bool showClassifiers = settings.value( "/qgis/showLegendClassifiers", false ).toBool();
00469
00470 QgsLegendSymbolList lst;
00471 if ( showClassifiers )
00472 {
00473 lst << qMakePair( classAttribute(), ( QgsSymbolV2* )0 );
00474 }
00475
00476 QgsCategoryList::const_iterator catIt = mCategories.constBegin();
00477 for ( ; catIt != mCategories.constEnd(); ++catIt )
00478 {
00479 lst << qMakePair( catIt->label(), catIt->symbol() );
00480 }
00481 return lst;
00482 }
00483
00484
00485 QgsSymbolV2* QgsCategorizedSymbolRendererV2::sourceSymbol()
00486 {
00487 return mSourceSymbol;
00488 }
00489 void QgsCategorizedSymbolRendererV2::setSourceSymbol( QgsSymbolV2* sym )
00490 {
00491 delete mSourceSymbol;
00492 mSourceSymbol = sym;
00493 }
00494
00495 QgsVectorColorRampV2* QgsCategorizedSymbolRendererV2::sourceColorRamp()
00496 {
00497 return mSourceColorRamp;
00498 }
00499 void QgsCategorizedSymbolRendererV2::setSourceColorRamp( QgsVectorColorRampV2* ramp )
00500 {
00501 delete mSourceColorRamp;
00502 mSourceColorRamp = ramp;
00503 }