|
QGIS API Documentation
master-59fd5e0
|
00001 /*************************************************************************** 00002 qgsstylev2.cpp 00003 --------------------- 00004 begin : November 2009 00005 copyright : (C) 2009 by Martin Dobias 00006 email : wonder dot sk at gmail dot com 00007 *************************************************************************** 00008 * * 00009 * This program is free software; you can redistribute it and/or modify * 00010 * it under the terms of the GNU General Public License as published by * 00011 * the Free Software Foundation; either version 2 of the License, or * 00012 * (at your option) any later version. * 00013 * * 00014 ***************************************************************************/ 00015 00016 #include "qgsstylev2.h" 00017 00018 #include "qgssymbolv2.h" 00019 #include "qgsvectorcolorrampv2.h" 00020 00021 #include "qgssymbollayerv2registry.h" 00022 00023 #include "qgsapplication.h" 00024 #include "qgslogger.h" 00025 00026 #include <QDomDocument> 00027 #include <QDomElement> 00028 #include <QDomNode> 00029 #include <QDomNodeList> 00030 #include <QFile> 00031 #include <QTextStream> 00032 #include <QByteArray> 00033 00034 #include <sqlite3.h> 00035 00036 #define STYLE_CURRENT_VERSION "1" 00037 00038 QgsStyleV2 *QgsStyleV2::mDefaultStyle = 0; 00039 00040 00041 QgsStyleV2::QgsStyleV2() 00042 { 00043 mCurrentDB = 0; 00044 } 00045 00046 QgsStyleV2::~QgsStyleV2() 00047 { 00048 clear(); 00049 } 00050 00051 QgsStyleV2* QgsStyleV2::defaultStyle() // static 00052 { 00053 if ( !mDefaultStyle ) 00054 { 00055 QString styleFilename = QgsApplication::userStyleV2Path(); 00056 00057 // copy default style if user style doesn't exist 00058 if ( !QFile::exists( styleFilename ) ) 00059 { 00060 QFile::copy( QgsApplication::defaultStyleV2Path(), styleFilename ); 00061 } 00062 00063 mDefaultStyle = new QgsStyleV2; 00064 mDefaultStyle->load( styleFilename ); 00065 } 00066 return mDefaultStyle; 00067 } 00068 00069 00070 void QgsStyleV2::clear() 00071 { 00072 for ( QMap<QString, QgsSymbolV2*>::iterator its = mSymbols.begin(); its != mSymbols.end(); ++its ) 00073 delete its.value(); 00074 for ( QMap<QString, QgsVectorColorRampV2*>::iterator itr = mColorRamps.begin(); itr != mColorRamps.end(); ++itr ) 00075 delete itr.value(); 00076 00077 mSymbols.clear(); 00078 mColorRamps.clear(); 00079 if ( mCurrentDB ) 00080 sqlite3_close( mCurrentDB ); 00081 } 00082 00083 bool QgsStyleV2::addSymbol( QString name, QgsSymbolV2* symbol, bool update ) 00084 { 00085 if ( !symbol || name.isEmpty() ) 00086 return false; 00087 00088 // delete previous symbol (if any) 00089 if ( mSymbols.contains( name ) ) 00090 { 00091 // TODO remove groups and tags? 00092 delete mSymbols.value( name ); 00093 mSymbols.insert( name, symbol ); 00094 if ( update ) 00095 updateSymbol( SymbolEntity, name ); 00096 } 00097 else 00098 { 00099 mSymbols.insert( name, symbol ); 00100 if ( update ) 00101 saveSymbol( name, symbol, 0, QStringList() ); 00102 } 00103 00104 return true; 00105 } 00106 00107 bool QgsStyleV2::saveSymbol( QString name, QgsSymbolV2* symbol, int groupid, QStringList tags ) 00108 { 00109 // TODO add support for tags and groups 00110 Q_UNUSED( tags ); 00111 00112 QDomDocument doc( "dummy" ); 00113 QDomElement symEl = QgsSymbolLayerV2Utils::saveSymbol( name, symbol, doc ); 00114 if ( symEl.isNull() ) 00115 { 00116 QgsDebugMsg( "Couldn't convert symbol to valid XML!" ); 00117 return false; 00118 } 00119 00120 QByteArray xmlArray; 00121 QTextStream stream( &xmlArray ); 00122 symEl.save( stream, 4 ); 00123 char *query = sqlite3_mprintf( "INSERT INTO symbol VALUES (NULL, '%q', '%q', %d);", 00124 name.toUtf8().constData(), xmlArray.constData(), groupid ); 00125 00126 if ( !runEmptyQuery( query ) ) 00127 { 00128 QgsDebugMsg( "Couldn't insert symbol into the database!" ); 00129 return false; 00130 } 00131 00132 return true; 00133 } 00134 00135 bool QgsStyleV2::removeSymbol( QString name ) 00136 { 00137 QgsSymbolV2 *symbol = mSymbols.take( name ); 00138 if ( !symbol ) 00139 return false; 00140 00141 // remove from map and delete 00142 delete symbol; 00143 00144 // TODO 00145 // Simplify this work here, its STUPID to run two DB queries for the sake of remove() 00146 if ( !mCurrentDB ) 00147 { 00148 QgsDebugMsg( "Sorry! Cannot open database to tag." ); 00149 return false; 00150 } 00151 00152 int symbolid = symbolId( name ); 00153 if ( !symbolid ) 00154 { 00155 QgsDebugMsg( "No such symbol for deleting in database: " + name + ". Cheers." ); 00156 } 00157 00158 remove( SymbolEntity, symbolid ); 00159 00160 return true; 00161 } 00162 00163 QgsSymbolV2* QgsStyleV2::symbol( QString name ) 00164 { 00165 const QgsSymbolV2 *symbol = symbolRef( name ); 00166 return symbol ? symbol->clone() : 0; 00167 } 00168 00169 const QgsSymbolV2 *QgsStyleV2::symbolRef( QString name ) const 00170 { 00171 return mSymbols.value( name ); 00172 } 00173 00174 int QgsStyleV2::symbolCount() 00175 { 00176 return mSymbols.count(); 00177 } 00178 00179 QStringList QgsStyleV2::symbolNames() 00180 { 00181 return mSymbols.keys(); 00182 } 00183 00184 00185 bool QgsStyleV2::addColorRamp( QString name, QgsVectorColorRampV2* colorRamp, bool update ) 00186 { 00187 if ( !colorRamp || name.isEmpty() ) 00188 return false; 00189 00190 // delete previous color ramps (if any) 00191 if ( mColorRamps.contains( name ) ) 00192 { 00193 // TODO remove groups and tags? 00194 delete mColorRamps.value( name ); 00195 mColorRamps.insert( name, colorRamp ); 00196 if ( update ) 00197 updateSymbol( ColorrampEntity, name ); 00198 } 00199 else 00200 { 00201 mColorRamps.insert( name, colorRamp ); 00202 if ( update ) 00203 saveColorRamp( name, colorRamp, 0, QStringList() ); 00204 } 00205 00206 return true; 00207 } 00208 00209 bool QgsStyleV2::saveColorRamp( QString name, QgsVectorColorRampV2* ramp, int groupid, QStringList tags ) 00210 { 00211 // TODO add support for groups and tags 00212 Q_UNUSED( tags ); 00213 00214 // insert it into the database 00215 QDomDocument doc( "dummy" ); 00216 QDomElement rampEl = QgsSymbolLayerV2Utils::saveColorRamp( name, ramp, doc ); 00217 if ( rampEl.isNull() ) 00218 { 00219 QgsDebugMsg( "Couldn't convert color ramp to valid XML!" ); 00220 return false; 00221 } 00222 00223 QByteArray xmlArray; 00224 QTextStream stream( &xmlArray ); 00225 rampEl.save( stream, 4 ); 00226 char *query = sqlite3_mprintf( "INSERT INTO colorramp VALUES (NULL, '%q', '%q', %d);", 00227 name.toUtf8().constData(), xmlArray.constData(), groupid ); 00228 00229 if ( !runEmptyQuery( query ) ) 00230 { 00231 QgsDebugMsg( "Couldn't insert colorramp into the database!" ); 00232 return false; 00233 } 00234 00235 return true; 00236 } 00237 00238 bool QgsStyleV2::removeColorRamp( QString name ) 00239 { 00240 QgsVectorColorRampV2 *ramp = mColorRamps.take( name ); 00241 if ( !ramp ) 00242 return false; 00243 00244 char *query = sqlite3_mprintf( "DELETE FROM colorramp WHERE name='%q'", name.toUtf8().constData() ); 00245 if ( !runEmptyQuery( query ) ) 00246 { 00247 QgsDebugMsg( "Couldn't remove color ramp from the database." ); 00248 return false; 00249 } 00250 00251 delete ramp; 00252 00253 return true; 00254 } 00255 00256 QgsVectorColorRampV2* QgsStyleV2::colorRamp( QString name ) 00257 { 00258 const QgsVectorColorRampV2 *ramp = colorRampRef( name ); 00259 return ramp ? ramp->clone() : 0; 00260 } 00261 00262 const QgsVectorColorRampV2* QgsStyleV2::colorRampRef( QString name ) const 00263 { 00264 return mColorRamps.value( name ); 00265 } 00266 00267 int QgsStyleV2::colorRampCount() 00268 { 00269 return mColorRamps.count(); 00270 } 00271 00272 QStringList QgsStyleV2::colorRampNames() 00273 { 00274 return mColorRamps.keys(); 00275 } 00276 00277 bool QgsStyleV2::openDB( QString filename ) 00278 { 00279 int rc = sqlite3_open( filename.toUtf8(), &mCurrentDB ); 00280 if ( rc ) 00281 { 00282 mErrorString = "Couldn't open the style database: " + QString( sqlite3_errmsg( mCurrentDB ) ); 00283 sqlite3_close( mCurrentDB ); 00284 return false; 00285 } 00286 00287 return true; 00288 } 00289 00290 bool QgsStyleV2::load( QString filename ) 00291 { 00292 mErrorString.clear(); 00293 00294 // Open the sqlite database 00295 if ( !openDB( filename ) ) 00296 { 00297 mErrorString = "Unable to open database file specified"; 00298 QgsDebugMsg( mErrorString ); 00299 return false; 00300 } 00301 00302 // Make sure there are no Null fields in parenting symbols ang groups 00303 char *query = sqlite3_mprintf( "UPDATE symbol SET groupid=0 WHERE groupid IS NULL;" 00304 "UPDATE colorramp SET groupid=0 WHERE groupid IS NULL;" 00305 "UPDATE symgroup SET parent=0 WHERE parent IS NULL;" ); 00306 runEmptyQuery( query ); 00307 00308 // First create all the main symbols 00309 query = sqlite3_mprintf( "SELECT * FROM symbol" ); 00310 00311 sqlite3_stmt *ppStmt; 00312 int nError = sqlite3_prepare_v2( mCurrentDB, query, -1, &ppStmt, NULL ); 00313 while ( nError == SQLITE_OK && sqlite3_step( ppStmt ) == SQLITE_ROW ) 00314 { 00315 QDomDocument doc; 00316 QString symbol_name = QString::fromUtf8(( const char * ) sqlite3_column_text( ppStmt, SymbolName ) ); 00317 QString xmlstring = QString::fromUtf8(( const char * ) sqlite3_column_text( ppStmt, SymbolXML ) ); 00318 if ( !doc.setContent( xmlstring ) ) 00319 { 00320 QgsDebugMsg( "Cannot open symbol " + symbol_name ); 00321 continue; 00322 } 00323 00324 QDomElement symElement = doc.documentElement(); 00325 QgsSymbolV2 *symbol = QgsSymbolLayerV2Utils::loadSymbol( symElement ); 00326 if ( symbol != NULL ) 00327 mSymbols.insert( symbol_name, symbol ); 00328 } 00329 00330 sqlite3_finalize( ppStmt ); 00331 00332 query = sqlite3_mprintf( "SELECT * FROM colorramp" ); 00333 nError = sqlite3_prepare_v2( mCurrentDB, query, -1, &ppStmt, NULL ); 00334 while ( nError == SQLITE_OK && sqlite3_step( ppStmt ) == SQLITE_ROW ) 00335 { 00336 QDomDocument doc; 00337 QString ramp_name = QString::fromUtf8(( const char * ) sqlite3_column_text( ppStmt, ColorrampName ) ); 00338 QString xmlstring = QString::fromUtf8(( const char * ) sqlite3_column_text( ppStmt, ColorrampXML ) ); 00339 if ( !doc.setContent( xmlstring ) ) 00340 { 00341 QgsDebugMsg( "Cannot open symbol " + ramp_name ); 00342 continue; 00343 } 00344 QDomElement rampElement = doc.documentElement(); 00345 QgsVectorColorRampV2 *ramp = QgsSymbolLayerV2Utils::loadColorRamp( rampElement ); 00346 if ( ramp ) 00347 mColorRamps.insert( ramp_name, ramp ); 00348 } 00349 00350 mFileName = filename; 00351 return true; 00352 } 00353 00354 00355 00356 bool QgsStyleV2::save( QString filename ) 00357 { 00358 mErrorString.clear(); 00359 00360 if ( filename.isEmpty() ) 00361 filename = mFileName; 00362 00363 // TODO evaluate the requirement of this function and change implementation accordingly 00364 // TODO remove QEXPECT_FAIL from TestStyleV2::testSaveLoad() when done 00365 #if 0 00366 QDomDocument doc( "qgis_style" ); 00367 QDomElement root = doc.createElement( "qgis_style" ); 00368 root.setAttribute( "version", STYLE_CURRENT_VERSION ); 00369 doc.appendChild( root ); 00370 00371 QDomElement symbolsElem = QgsSymbolLayerV2Utils::saveSymbols( mSymbols, "symbols", doc ); 00372 00373 QDomElement rampsElem = doc.createElement( "colorramps" ); 00374 00375 // save color ramps 00376 for ( QMap<QString, QgsVectorColorRampV2*>::iterator itr = mColorRamps.begin(); itr != mColorRamps.end(); ++itr ) 00377 { 00378 QDomElement rampEl = QgsSymbolLayerV2Utils::saveColorRamp( itr.key(), itr.value(), doc ); 00379 rampsElem.appendChild( rampEl ); 00380 } 00381 00382 root.appendChild( symbolsElem ); 00383 root.appendChild( rampsElem ); 00384 00385 // save 00386 QFile f( filename ); 00387 if ( !f.open( QFile::WriteOnly ) ) 00388 { 00389 mErrorString = "Couldn't open file for writing: " + filename; 00390 return false; 00391 } 00392 QTextStream ts( &f ); 00393 doc.save( ts, 2 ); 00394 f.close(); 00395 #endif 00396 00397 mFileName = filename; 00398 return true; 00399 } 00400 00401 bool QgsStyleV2::renameSymbol( QString oldName, QString newName ) 00402 { 00403 QgsSymbolV2 *symbol = mSymbols.take( oldName ); 00404 if ( !symbol ) 00405 return false; 00406 00407 mSymbols.insert( newName, symbol ); 00408 00409 if ( !mCurrentDB ) 00410 { 00411 QgsDebugMsg( "Sorry! Cannot open database to tag." ); 00412 return false; 00413 } 00414 00415 int symbolid = symbolId( oldName ); 00416 if ( !symbolid ) 00417 { 00418 QgsDebugMsg( "No such symbol for tagging in database: " + oldName ); 00419 return false; 00420 } 00421 00422 rename( SymbolEntity, symbolid, newName ); 00423 00424 return true; 00425 } 00426 00427 bool QgsStyleV2::renameColorRamp( QString oldName, QString newName ) 00428 { 00429 QgsVectorColorRampV2 *ramp = mColorRamps.take( oldName ); 00430 if ( !ramp ) 00431 return false; 00432 00433 mColorRamps.insert( newName, ramp ); 00434 00435 int rampid = 0; 00436 sqlite3_stmt *ppStmt; 00437 char *query = sqlite3_mprintf( "SELECT id FROM colorramp WHERE name='%q'", oldName.toUtf8().constData() ); 00438 int nErr = sqlite3_prepare_v2( mCurrentDB, query, -1, &ppStmt, NULL ); 00439 if ( nErr == SQLITE_OK && sqlite3_step( ppStmt ) == SQLITE_ROW ) 00440 { 00441 rampid = sqlite3_column_int( ppStmt, 0 ); 00442 } 00443 sqlite3_finalize( ppStmt ); 00444 rename( ColorrampEntity, rampid, newName ); 00445 00446 return true; 00447 } 00448 00449 QStringList QgsStyleV2::groupNames() 00450 { 00451 QStringList groupNames; 00452 sqlite3_stmt *ppStmt; 00453 const char *query = "SELECT * FROM symgroup"; 00454 int nError = sqlite3_prepare_v2( mCurrentDB, query, -1, &ppStmt, NULL ); 00455 while ( nError == SQLITE_OK && sqlite3_step( ppStmt ) == SQLITE_ROW ) 00456 { 00457 groupNames << QString::fromUtf8(( const char * ) sqlite3_column_text( ppStmt, SymgroupName ) ); 00458 } 00459 sqlite3_finalize( ppStmt ); 00460 return groupNames; 00461 } 00462 00463 QgsSymbolGroupMap QgsStyleV2::childGroupNames( QString parent ) 00464 { 00465 // get the name list from the sqlite database and return as a QStringList 00466 if ( !mCurrentDB ) 00467 { 00468 QgsDebugMsg( "Cannot open database for listing groups" ); 00469 return QgsSymbolGroupMap(); 00470 } 00471 00472 char *query = 0; 00473 int nError; 00474 sqlite3_stmt *ppStmt; 00475 00476 // decide the query to be run based on parent group 00477 if ( parent == "" || parent == QString() ) 00478 { 00479 query = sqlite3_mprintf( "SELECT * FROM symgroup WHERE parent=0" ); 00480 } 00481 else 00482 { 00483 char *subquery = sqlite3_mprintf( "SELECT * FROM symgroup WHERE name='%q'", parent.toUtf8().constData() ); 00484 nError = sqlite3_prepare_v2( mCurrentDB, subquery, -1, &ppStmt, NULL ); 00485 if ( nError == SQLITE_OK && sqlite3_step( ppStmt ) == SQLITE_ROW ) 00486 { 00487 query = sqlite3_mprintf( "SELECT * FROM symgroup WHERE parent=%d", sqlite3_column_int( ppStmt, SymgroupId ) ); 00488 } 00489 sqlite3_finalize( ppStmt ); 00490 } 00491 00492 if ( !query ) 00493 return QgsSymbolGroupMap(); 00494 00495 QgsSymbolGroupMap groupNames; 00496 00497 // Now run the query and retrieve the group names 00498 nError = sqlite3_prepare_v2( mCurrentDB, query, -1, &ppStmt, NULL ); 00499 while ( nError == SQLITE_OK && sqlite3_step( ppStmt ) == SQLITE_ROW ) 00500 { 00501 QString group = QString::fromUtf8(( const char * ) sqlite3_column_text( ppStmt, SymgroupName ) ); 00502 groupNames.insert( sqlite3_column_int( ppStmt, SymgroupId ), group ); 00503 } 00504 00505 sqlite3_finalize( ppStmt ); 00506 00507 return groupNames; 00508 } 00509 00510 QStringList QgsStyleV2::symbolsOfGroup( StyleEntity type, int groupid ) 00511 { 00512 if ( !mCurrentDB ) 00513 { 00514 QgsDebugMsg( QString( "Cannot Open database for getting group symbols of groupid: %1" ).arg( groupid ) ); 00515 return QStringList(); 00516 } 00517 00518 char *query; 00519 if ( type == SymbolEntity ) 00520 { 00521 query = sqlite3_mprintf( "SELECT name FROM symbol WHERE groupid=%d", groupid ); 00522 } 00523 else if ( type == ColorrampEntity ) 00524 { 00525 query = sqlite3_mprintf( "SELECT name FROM colorramp WHERE groupid=%d", groupid ); 00526 } 00527 else 00528 { 00529 QgsDebugMsg( "No such style entity" ); 00530 return QStringList(); 00531 } 00532 00533 sqlite3_stmt *ppStmt; 00534 int nErr = sqlite3_prepare_v2( mCurrentDB, query, -1, &ppStmt, NULL ); 00535 00536 QStringList symbols; 00537 while ( nErr == SQLITE_OK && sqlite3_step( ppStmt ) == SQLITE_ROW ) 00538 { 00539 symbols << QString::fromUtf8(( const char * ) sqlite3_column_text( ppStmt, 0 ) ); 00540 } 00541 00542 sqlite3_finalize( ppStmt ); 00543 00544 return symbols; 00545 } 00546 00547 QStringList QgsStyleV2::symbolsWithTag( StyleEntity type, int tagid ) 00548 { 00549 if ( !mCurrentDB ) 00550 { 00551 QgsDebugMsg( QString( "Cannot open database to get symbols of tagid %1" ).arg( tagid ) ); 00552 return QStringList(); 00553 } 00554 00555 char *subquery; 00556 if ( type == SymbolEntity ) 00557 { 00558 subquery = sqlite3_mprintf( "SELECT symbol_id FROM tagmap WHERE tag_id=%d", tagid ); 00559 } 00560 else if ( type == ColorrampEntity ) 00561 { 00562 subquery = sqlite3_mprintf( "SELECT symbol_id FROM ctagmap WHERE tag_id=%d", tagid ); 00563 } 00564 else 00565 { 00566 QgsDebugMsg( "Unknown Entity" ); 00567 return QStringList(); 00568 } 00569 00570 sqlite3_stmt *ppStmt; 00571 int nErr = sqlite3_prepare_v2( mCurrentDB, subquery, -1, &ppStmt, NULL ); 00572 00573 // get the symbol <-> tag connection from table 'tagmap' 00574 QStringList symbols; 00575 while ( nErr == SQLITE_OK && sqlite3_step( ppStmt ) == SQLITE_ROW ) 00576 { 00577 int symbolId = sqlite3_column_int( ppStmt, 0 ); 00578 00579 char *query = type == SymbolEntity 00580 ? sqlite3_mprintf( "SELECT name FROM symbol WHERE id=%d", symbolId ) 00581 : sqlite3_mprintf( "SELECT name FROM colorramp WHERE id=%d", symbolId ); 00582 00583 sqlite3_stmt *ppStmt2; 00584 int sErr = sqlite3_prepare_v2( mCurrentDB, query, -1, &ppStmt2, NULL ); 00585 while ( sErr == SQLITE_OK && sqlite3_step( ppStmt2 ) == SQLITE_ROW ) 00586 { 00587 symbols << QString::fromUtf8(( const char * ) sqlite3_column_text( ppStmt2, 0 ) ); 00588 } 00589 sqlite3_finalize( ppStmt2 ); 00590 } 00591 sqlite3_finalize( ppStmt ); 00592 00593 return symbols; 00594 } 00595 00596 int QgsStyleV2::addGroup( QString groupName, int parentid ) 00597 { 00598 if ( !mCurrentDB ) 00599 return 0; 00600 00601 char *query = sqlite3_mprintf( "INSERT INTO symgroup VALUES (NULL, '%q', %d)", groupName.toUtf8().constData(), parentid ); 00602 00603 sqlite3_stmt *ppStmt; 00604 int nErr = sqlite3_prepare_v2( mCurrentDB, query, -1, &ppStmt, NULL ); 00605 if ( nErr == SQLITE_OK ) 00606 sqlite3_step( ppStmt ); 00607 00608 sqlite3_finalize( ppStmt ); 00609 00610 return ( int )sqlite3_last_insert_rowid( mCurrentDB ); 00611 } 00612 00613 int QgsStyleV2::addTag( QString tagname ) 00614 { 00615 if ( !mCurrentDB ) 00616 return 0; 00617 sqlite3_stmt *ppStmt; 00618 00619 char *query = sqlite3_mprintf( "INSERT INTO tag VALUES (NULL, '%q')", tagname.toUtf8().constData() ); 00620 int nErr = sqlite3_prepare_v2( mCurrentDB, query, -1, &ppStmt, NULL ); 00621 if ( nErr == SQLITE_OK ) 00622 sqlite3_step( ppStmt ); 00623 sqlite3_finalize( ppStmt ); 00624 00625 return ( int )sqlite3_last_insert_rowid( mCurrentDB ); 00626 } 00627 00628 void QgsStyleV2::rename( StyleEntity type, int id, QString newName ) 00629 { 00630 char *query; 00631 switch ( type ) 00632 { 00633 case SymbolEntity: 00634 query = sqlite3_mprintf( "UPDATE symbol SET name='%q' WHERE id=%d", newName.toUtf8().constData(), id ); 00635 break; 00636 case GroupEntity: 00637 query = sqlite3_mprintf( "UPDATE symgroup SET name='%q' WHERE id=%d", newName.toUtf8().constData(), id ); 00638 break; 00639 case TagEntity: 00640 query = sqlite3_mprintf( "UPDATE tag SET name='%q' WHERE id=%d", newName.toUtf8().constData(), id ); 00641 break; 00642 case ColorrampEntity: 00643 query = sqlite3_mprintf( "UPDATE colorramp SET name='%q' WHERE id=%d", newName.toUtf8().constData(), id ); 00644 break; 00645 case SmartgroupEntity: 00646 query = sqlite3_mprintf( "UPDATE smartgroup SET name='%q' WHERE id=%d", newName.toUtf8().constData(), id ); 00647 break; 00648 default: 00649 QgsDebugMsg( "Invalid Style Entity indicated" ); 00650 return; 00651 } 00652 if ( !runEmptyQuery( query ) ) 00653 mErrorString = "Could not rename!"; 00654 } 00655 00656 char* QgsStyleV2::getGroupRemoveQuery( int id ) 00657 { 00658 char *query = sqlite3_mprintf( "SELECT parent FROM symgroup WHERE id=%d", id ); 00659 00660 sqlite3_stmt *ppStmt; 00661 int err = sqlite3_prepare_v2( mCurrentDB, query, -1, &ppStmt, NULL ); 00662 00663 int parentid = 0; 00664 if ( err == SQLITE_OK && sqlite3_step( ppStmt ) == SQLITE_ROW ) 00665 parentid = sqlite3_column_int( ppStmt, 0 ); 00666 00667 sqlite3_finalize( ppStmt ); 00668 00669 return sqlite3_mprintf( "UPDATE symbol SET groupid=%d WHERE groupid=%d;" 00670 "UPDATE symgroup SET parent=%d WHERE parent=%d;" 00671 "DELETE FROM symgroup WHERE id=%d", parentid, id, parentid, id, id ); 00672 } 00673 00674 void QgsStyleV2::remove( StyleEntity type, int id ) 00675 { 00676 char *query; 00677 switch ( type ) 00678 { 00679 case SymbolEntity: 00680 query = sqlite3_mprintf( "DELETE FROM symbol WHERE id=%d; DELETE FROM tagmap WHERE symbol_id=%d", id, id ); 00681 break; 00682 case GroupEntity: 00683 query = getGroupRemoveQuery( id ); 00684 break; 00685 case TagEntity: 00686 query = sqlite3_mprintf( "DELETE FROM tag WHERE id=%d; DELETE FROM tagmap WHERE tag_id=%d", id, id ); 00687 break; 00688 case ColorrampEntity: 00689 query = sqlite3_mprintf( "DELETE FROM colorramp WHERE id=%d", id ); 00690 break; 00691 case SmartgroupEntity: 00692 query = sqlite3_mprintf( "DELETE FROM smartgroup WHERE id=%d", id ); 00693 break; 00694 default: 00695 QgsDebugMsg( "Invalid Style Entity indicated" ); 00696 return; 00697 } 00698 00699 if ( !runEmptyQuery( query ) ) 00700 { 00701 QgsDebugMsg( "Could not delete entity!" ); 00702 } 00703 } 00704 00705 bool QgsStyleV2::runEmptyQuery( char *query, bool freeQuery ) 00706 { 00707 if ( !mCurrentDB ) 00708 return false; 00709 00710 char *zErr = 0; 00711 int nErr = sqlite3_exec( mCurrentDB, query, NULL, NULL, &zErr ); 00712 00713 if ( freeQuery ) 00714 { 00715 sqlite3_free( query ); 00716 } 00717 00718 if ( nErr != SQLITE_OK ) 00719 { 00720 QgsDebugMsg( zErr ); 00721 } 00722 00723 return zErr == SQLITE_OK; 00724 } 00725 00726 bool QgsStyleV2::group( StyleEntity type, QString name, int groupid ) 00727 { 00728 char *query; 00729 00730 switch ( type ) 00731 { 00732 case SymbolEntity: 00733 query = sqlite3_mprintf( "UPDATE symbol SET groupid=%d WHERE name='%q'", groupid, name.toUtf8().constData() ); 00734 break; 00735 case ColorrampEntity: 00736 query = sqlite3_mprintf( "UPDATE colorramp SET groupid=%d WHERE name='%q'", groupid, name.toUtf8().constData() ); 00737 break; 00738 00739 default: 00740 QgsDebugMsg( "Wrong entity value. cannot apply group" ); 00741 return false; 00742 } 00743 00744 return runEmptyQuery( query ); 00745 } 00746 00747 QStringList QgsStyleV2::findSymbols( QString qword ) 00748 { 00749 if ( !mCurrentDB ) 00750 { 00751 QgsDebugMsg( "Sorry! Cannot open database to search" ); 00752 return QStringList(); 00753 } 00754 00755 char *query = sqlite3_mprintf( "SELECT name FROM symbol WHERE xml LIKE '%%%q%%'", qword.toUtf8().constData() ); 00756 00757 sqlite3_stmt *ppStmt; 00758 int nErr = sqlite3_prepare_v2( mCurrentDB, query, -1, &ppStmt, NULL ); 00759 00760 QStringList symbols; 00761 while ( nErr == SQLITE_OK && sqlite3_step( ppStmt ) == SQLITE_ROW ) 00762 { 00763 symbols << QString::fromUtf8(( const char * ) sqlite3_column_text( ppStmt, 0 ) ); 00764 } 00765 00766 sqlite3_finalize( ppStmt ); 00767 00768 00769 query = sqlite3_mprintf( "SELECT id FROM tag WHERE name LIKE '%%%q%%'", qword.toUtf8().constData() ); 00770 nErr = sqlite3_prepare_v2( mCurrentDB, query, -1, &ppStmt, NULL ); 00771 00772 QStringList tagids; 00773 while ( nErr == SQLITE_OK && sqlite3_step( ppStmt ) == SQLITE_ROW ) 00774 { 00775 tagids << QString::fromUtf8(( const char * ) sqlite3_column_text( ppStmt, 0 ) ); 00776 } 00777 00778 sqlite3_finalize( ppStmt ); 00779 00780 00781 QString dummy = tagids.join( ", " ); 00782 00783 query = sqlite3_mprintf( "SELECT symbol_id FROM tagmap WHERE tag_id IN (%q)", dummy.toUtf8().constData() ); 00784 nErr = sqlite3_prepare_v2( mCurrentDB, query, -1, &ppStmt, NULL ); 00785 00786 QStringList symbolids; 00787 while ( nErr == SQLITE_OK && sqlite3_step( ppStmt ) == SQLITE_ROW ) 00788 { 00789 symbolids << QString::fromUtf8(( const char * ) sqlite3_column_text( ppStmt, 0 ) ); 00790 } 00791 00792 sqlite3_finalize( ppStmt ); 00793 00794 00795 dummy = symbolids.join( ", " ); 00796 query = sqlite3_mprintf( "SELECT name FROM symbol WHERE id IN (%q)", dummy.toUtf8().constData() ); 00797 nErr = sqlite3_prepare_v2( mCurrentDB, query, -1, &ppStmt, NULL ); 00798 while ( nErr == SQLITE_OK && sqlite3_step( ppStmt ) == SQLITE_ROW ) 00799 { 00800 QString symbolName = QString::fromUtf8(( const char * ) sqlite3_column_text( ppStmt, 0 ) ); 00801 if ( !symbols.contains( symbolName ) ) 00802 symbols << symbolName; 00803 } 00804 00805 sqlite3_finalize( ppStmt ); 00806 00807 return symbols; 00808 } 00809 00810 bool QgsStyleV2::tagSymbol( StyleEntity type, QString symbol, QStringList tags ) 00811 { 00812 if ( !mCurrentDB ) 00813 { 00814 QgsDebugMsg( "Sorry! Cannot open database to tag." ); 00815 return false; 00816 } 00817 00818 int symbolid = type == SymbolEntity ? symbolId( symbol ) : colorrampId( symbol ); 00819 if ( !symbolid ) 00820 { 00821 QgsDebugMsg( "No such symbol for tagging in database: " + symbol ); 00822 return false; 00823 } 00824 00825 00826 foreach ( const QString &tag, tags ) 00827 { 00828 // sql: gets the id of the tag if present or insert the tag and get the id of the tag 00829 char *query = sqlite3_mprintf( "SELECT id FROM tag WHERE name='%q'", tag.toUtf8().constData() ); 00830 00831 sqlite3_stmt *ppStmt; 00832 int nErr = sqlite3_prepare_v2( mCurrentDB, query, -1, &ppStmt, NULL ); 00833 00834 int tagid; 00835 if ( nErr == SQLITE_OK && sqlite3_step( ppStmt ) == SQLITE_ROW ) 00836 { 00837 tagid = sqlite3_column_int( ppStmt, 0 ); 00838 } 00839 else 00840 { 00841 tagid = addTag( tag ); 00842 } 00843 00844 sqlite3_finalize( ppStmt ); 00845 00846 // Now map the tag to the symbol 00847 query = type == SymbolEntity 00848 ? sqlite3_mprintf( "INSERT INTO tagmap VALUES (%d,%d)", tagid, symbolid ) 00849 : sqlite3_mprintf( "INSERT INTO ctagmap VALUES (%d,%d)", tagid, symbolid ); 00850 00851 char *zErr = 0; 00852 nErr = sqlite3_exec( mCurrentDB, query, NULL, NULL, &zErr ); 00853 if ( nErr ) 00854 { 00855 QgsDebugMsg( zErr ); 00856 } 00857 } 00858 00859 return true; 00860 } 00861 00862 bool QgsStyleV2::detagSymbol( StyleEntity type, QString symbol, QStringList tags ) 00863 { 00864 if ( !mCurrentDB ) 00865 { 00866 QgsDebugMsg( "Sorry! Cannot open database for detgging." ); 00867 return false; 00868 } 00869 00870 char *query = type == SymbolEntity 00871 ? sqlite3_mprintf( "SELECT id FROM symbol WHERE name='%q'", symbol.toUtf8().constData() ) 00872 : sqlite3_mprintf( "SELECT id FROM colorramp WHERE name='%q'", symbol.toUtf8().constData() ); 00873 sqlite3_stmt *ppStmt; 00874 int nErr = sqlite3_prepare_v2( mCurrentDB, query, -1, &ppStmt, NULL ); 00875 00876 int symbolid = 0; 00877 if ( nErr == SQLITE_OK && sqlite3_step( ppStmt ) == SQLITE_ROW ) 00878 { 00879 symbolid = sqlite3_column_int( ppStmt, 0 ); 00880 } 00881 00882 sqlite3_finalize( ppStmt ); 00883 00884 foreach ( const QString &tag, tags ) 00885 { 00886 query = sqlite3_mprintf( "SELECT id FROM tag WHERE name='%q'", tag.toUtf8().constData() ); 00887 00888 sqlite3_stmt *ppStmt2; 00889 nErr = sqlite3_prepare_v2( mCurrentDB, query, -1, &ppStmt2, NULL ); 00890 00891 int tagid = 0; 00892 if ( nErr == SQLITE_OK && sqlite3_step( ppStmt2 ) == SQLITE_ROW ) 00893 { 00894 tagid = sqlite3_column_int( ppStmt2, 0 ); 00895 } 00896 00897 sqlite3_finalize( ppStmt2 ); 00898 00899 if ( tagid ) 00900 { 00901 // remove from the tagmap 00902 query = type == SymbolEntity 00903 ? sqlite3_mprintf( "DELETE FROM tagmap WHERE tag_id=%d AND symbol_id=%d", tagid, symbolid ) 00904 : sqlite3_mprintf( "DELETE FROM ctagmap WHERE tag_id=%d AND colorramp_id=%d", tagid, symbolid ); 00905 runEmptyQuery( query ); 00906 } 00907 } 00908 00909 // TODO Perform tag cleanup 00910 // check the number of entries for a given tag in the tagmap 00911 // if the count is 0, then remove( TagEntity, tagid ) 00912 return true; 00913 } 00914 00915 QStringList QgsStyleV2::tagsOfSymbol( StyleEntity type, QString symbol ) 00916 { 00917 if ( !mCurrentDB ) 00918 { 00919 QgsDebugMsg( "Sorry! Cannot open database for getting the tags." ); 00920 return QStringList(); 00921 } 00922 00923 int symbolid = type == SymbolEntity ? symbolId( symbol ) : colorrampId( symbol ); 00924 if ( !symbolid ) 00925 return QStringList(); 00926 00927 // get the ids of tags for the symbol 00928 char *query = type == SymbolEntity 00929 ? sqlite3_mprintf( "SELECT tag_id FROM tagmap WHERE symbol_id=%d", symbolid ) 00930 : sqlite3_mprintf( "SELECT tag_id FROM ctagmap WHERE colorramp_id=%d", symbolid ); 00931 00932 sqlite3_stmt *ppStmt; 00933 int nErr = sqlite3_prepare_v2( mCurrentDB, query, -1, &ppStmt, NULL ); 00934 00935 QStringList tagList; 00936 while ( nErr == SQLITE_OK && sqlite3_step( ppStmt ) == SQLITE_ROW ) 00937 { 00938 char *subquery = sqlite3_mprintf( "SELECT name FROM tag WHERE id=%d", sqlite3_column_int( ppStmt, 0 ) ); 00939 00940 sqlite3_stmt *ppStmt2; 00941 int pErr = sqlite3_prepare_v2( mCurrentDB, subquery, -1, &ppStmt2, NULL ); 00942 if ( pErr == SQLITE_OK && sqlite3_step( ppStmt2 ) == SQLITE_ROW ) 00943 { 00944 tagList << QString::fromUtf8(( const char * ) sqlite3_column_text( ppStmt2, 0 ) ); 00945 } 00946 sqlite3_finalize( ppStmt2 ); 00947 } 00948 00949 sqlite3_finalize( ppStmt ); 00950 00951 return tagList; 00952 } 00953 00954 int QgsStyleV2::getId( QString table, QString name ) 00955 { 00956 char *query = sqlite3_mprintf( "SELECT id FROM %q WHERE name='%q'", table.toUtf8().constData(), name.toUtf8().constData() ); 00957 00958 sqlite3_stmt *ppStmt; 00959 int nErr = sqlite3_prepare_v2( mCurrentDB, query, -1, &ppStmt, NULL ); 00960 00961 int id = 0; 00962 if ( nErr == SQLITE_OK && sqlite3_step( ppStmt ) == SQLITE_ROW ) 00963 { 00964 id = sqlite3_column_int( ppStmt, 0 ); 00965 } 00966 00967 sqlite3_finalize( ppStmt ); 00968 00969 return id; 00970 } 00971 00972 int QgsStyleV2::symbolId( QString name ) 00973 { 00974 return getId( "symbol", name ); 00975 } 00976 00977 int QgsStyleV2::colorrampId( QString name ) 00978 { 00979 return getId( "colorramp", name ); 00980 } 00981 00982 int QgsStyleV2::groupId( QString name ) 00983 { 00984 return getId( "symgroup", name ); 00985 } 00986 00987 int QgsStyleV2::tagId( QString name ) 00988 { 00989 return getId( "tag", name ); 00990 } 00991 00992 int QgsStyleV2::smartgroupId( QString name ) 00993 { 00994 return getId( "smartgroup", name ); 00995 } 00996 00997 int QgsStyleV2::addSmartgroup( QString name, QString op, QgsSmartConditionMap conditions ) 00998 { 00999 QDomDocument doc( "dummy" ); 01000 QDomElement smartEl = doc.createElement( "smartgroup" ); 01001 smartEl.setAttribute( "name", name ); 01002 smartEl.setAttribute( "operator", op ); 01003 01004 QStringList constraints; 01005 constraints << "tag" << "group" << "name" << "!tag" << "!group" << "!name"; 01006 01007 foreach ( const QString &constraint, constraints ) 01008 { 01009 QStringList parameters = conditions.values( constraint ); 01010 foreach ( const QString ¶m, parameters ) 01011 { 01012 QDomElement condEl = doc.createElement( "condition" ); 01013 condEl.setAttribute( "constraint", constraint ); 01014 condEl.setAttribute( "param", param ); 01015 smartEl.appendChild( condEl ); 01016 } 01017 } 01018 01019 QByteArray xmlArray; 01020 QTextStream stream( &xmlArray ); 01021 smartEl.save( stream, 4 ); 01022 char *query = sqlite3_mprintf( "INSERT INTO smartgroup VALUES (NULL, '%q', '%q')", 01023 name.toUtf8().constData(), xmlArray.constData() ); 01024 01025 if ( runEmptyQuery( query ) ) 01026 { 01027 return ( int )sqlite3_last_insert_rowid( mCurrentDB ); 01028 } 01029 else 01030 { 01031 QgsDebugMsg( "Couldn't insert symbol into the database!" ); 01032 return 0; 01033 } 01034 } 01035 01036 QgsSymbolGroupMap QgsStyleV2::smartgroupsListMap() 01037 { 01038 if ( !mCurrentDB ) 01039 { 01040 QgsDebugMsg( "Cannot open database for listing groups" ); 01041 return QgsSymbolGroupMap(); 01042 } 01043 01044 char *query = sqlite3_mprintf( "SELECT * FROM smartgroup" ); 01045 01046 // Now run the query and retrieve the group names 01047 sqlite3_stmt *ppStmt; 01048 int nError = sqlite3_prepare_v2( mCurrentDB, query, -1, &ppStmt, NULL ); 01049 01050 QgsSymbolGroupMap groupNames; 01051 while ( nError == SQLITE_OK && sqlite3_step( ppStmt ) == SQLITE_ROW ) 01052 { 01053 QString group = QString::fromUtf8(( const char * ) sqlite3_column_text( ppStmt, SmartgroupName ) ); 01054 groupNames.insert( sqlite3_column_int( ppStmt, SmartgroupId ), group ); 01055 } 01056 01057 sqlite3_finalize( ppStmt ); 01058 01059 return groupNames; 01060 } 01061 01062 QStringList QgsStyleV2::smartgroupNames() 01063 { 01064 if ( !mCurrentDB ) 01065 { 01066 QgsDebugMsg( "Cannot open database for listing groups" ); 01067 return QStringList(); 01068 } 01069 01070 char *query = sqlite3_mprintf( "SELECT name FROM smartgroup" ); 01071 01072 // Now run the query and retrieve the group names 01073 sqlite3_stmt *ppStmt; 01074 int nError = sqlite3_prepare_v2( mCurrentDB, query, -1, &ppStmt, NULL ); 01075 01076 QStringList groups; 01077 while ( nError == SQLITE_OK && sqlite3_step( ppStmt ) == SQLITE_ROW ) 01078 { 01079 groups << QString::fromUtf8(( const char * ) sqlite3_column_text( ppStmt, 0 ) ); 01080 } 01081 01082 sqlite3_finalize( ppStmt ); 01083 01084 return groups; 01085 } 01086 01087 QStringList QgsStyleV2::symbolsOfSmartgroup( StyleEntity type, int id ) 01088 { 01089 QStringList symbols; 01090 01091 char *query = sqlite3_mprintf( "SELECT xml FROM smartgroup WHERE id=%d", id ); 01092 01093 sqlite3_stmt *ppStmt; 01094 int nErr = sqlite3_prepare_v2( mCurrentDB, query, -1, &ppStmt, NULL ); 01095 if ( !( nErr == SQLITE_OK && sqlite3_step( ppStmt ) == SQLITE_ROW ) ) 01096 { 01097 sqlite3_finalize( ppStmt ); 01098 return QStringList(); 01099 } 01100 else 01101 { 01102 QDomDocument doc; 01103 QString xmlstr = QString::fromUtf8(( const char * ) sqlite3_column_text( ppStmt, 0 ) ); 01104 if ( !doc.setContent( xmlstr ) ) 01105 { 01106 QgsDebugMsg( QString( "Cannot open smartgroup id: %1" ).arg( id ) ); 01107 } 01108 QDomElement smartEl = doc.documentElement(); 01109 QString op = smartEl.attribute( "operator" ); 01110 QDomNodeList conditionNodes = smartEl.childNodes(); 01111 01112 bool firstSet = true; 01113 for ( int i = 0; i < conditionNodes.count(); i++ ) 01114 { 01115 QDomElement condEl = conditionNodes.at( i ).toElement(); 01116 QString constraint = condEl.attribute( "constraint" ); 01117 QString param = condEl.attribute( "param" ); 01118 01119 QStringList resultNames; 01120 // perform suitable action for the given constraint 01121 if ( constraint == "tag" ) 01122 { 01123 resultNames = symbolsWithTag( type, tagId( param ) ); 01124 } 01125 else if ( constraint == "group" ) 01126 { 01127 // XXX Validating group id might be a good idea here 01128 resultNames = symbolsOfGroup( type, groupId( param ) ); 01129 01130 } 01131 else if ( constraint == "name" ) 01132 { 01133 if ( type == SymbolEntity ) 01134 { 01135 resultNames = symbolNames().filter( param, Qt::CaseInsensitive ); 01136 } 01137 else 01138 { 01139 resultNames = colorRampNames().filter( param, Qt::CaseInsensitive ); 01140 } 01141 } 01142 else if ( constraint == "!tag" ) 01143 { 01144 resultNames = type == SymbolEntity ? symbolNames() : colorRampNames(); 01145 QStringList unwanted = symbolsWithTag( type, tagId( param ) ); 01146 foreach ( QString name, unwanted ) 01147 { 01148 resultNames.removeAll( name ); 01149 } 01150 } 01151 else if ( constraint == "!group" ) 01152 { 01153 resultNames = type == SymbolEntity ? symbolNames() : colorRampNames(); 01154 QStringList unwanted = symbolsOfGroup( type, groupId( param ) ); 01155 foreach ( QString name, unwanted ) 01156 { 01157 resultNames.removeAll( name ); 01158 } 01159 } 01160 else if ( constraint == "!name" ) 01161 { 01162 QStringList all = type == SymbolEntity ? symbolNames() : colorRampNames() ; 01163 foreach ( const QString &str, all ) 01164 { 01165 if ( !str.contains( param, Qt::CaseInsensitive ) ) 01166 resultNames << str; 01167 } 01168 } 01169 01170 // not apply the operator 01171 if ( firstSet ) 01172 { 01173 symbols = resultNames; 01174 firstSet = false; 01175 } 01176 else 01177 { 01178 if ( op == "OR" ) 01179 { 01180 symbols << resultNames; 01181 } 01182 else if ( op == "AND" ) 01183 { 01184 QStringList dummy = symbols; 01185 symbols.clear(); 01186 foreach ( const QString &result, resultNames ) 01187 { 01188 if ( dummy.contains( result ) ) 01189 symbols << result; 01190 } 01191 } 01192 } 01193 } // DOM loop ends here 01194 } 01195 01196 sqlite3_finalize( ppStmt ); 01197 01198 return symbols; 01199 } 01200 01201 QgsSmartConditionMap QgsStyleV2::smartgroup( int id ) 01202 { 01203 if ( !mCurrentDB ) 01204 { 01205 QgsDebugMsg( "Cannot open database for listing groups" ); 01206 return QgsSmartConditionMap(); 01207 } 01208 01209 QgsSmartConditionMap condition; 01210 01211 char *query = sqlite3_mprintf( "SELECT xml FROM smartgroup WHERE id=%d", id ); 01212 01213 sqlite3_stmt *ppStmt; 01214 int nError = sqlite3_prepare_v2( mCurrentDB, query, -1, &ppStmt, NULL ); 01215 if ( nError == SQLITE_OK && sqlite3_step( ppStmt ) == SQLITE_ROW ) 01216 { 01217 QDomDocument doc; 01218 QString xmlstr = QString::fromUtf8(( const char * ) sqlite3_column_text( ppStmt, 0 ) ); 01219 if ( !doc.setContent( xmlstr ) ) 01220 { 01221 QgsDebugMsg( QString( "Cannot open smartgroup id: %1" ).arg( id ) ); 01222 } 01223 01224 QDomElement smartEl = doc.documentElement(); 01225 QString op = smartEl.attribute( "operator" ); 01226 QDomNodeList conditionNodes = smartEl.childNodes(); 01227 01228 for ( int i = 0; i < conditionNodes.count(); i++ ) 01229 { 01230 QDomElement condEl = conditionNodes.at( i ).toElement(); 01231 QString constraint = condEl.attribute( "constraint" ); 01232 QString param = condEl.attribute( "param" ); 01233 01234 condition.insert( constraint, param ); 01235 } 01236 } 01237 01238 sqlite3_finalize( ppStmt ); 01239 01240 return condition; 01241 } 01242 01243 QString QgsStyleV2::smartgroupOperator( int id ) 01244 { 01245 if ( !mCurrentDB ) 01246 { 01247 QgsDebugMsg( "Cannot open database for listing groups" ); 01248 return QString(); 01249 } 01250 01251 QString op; 01252 01253 char *query = sqlite3_mprintf( "SELECT xml FROM smartgroup WHERE id=%d", id ); 01254 01255 sqlite3_stmt *ppStmt; 01256 int nError = sqlite3_prepare_v2( mCurrentDB, query, -1, &ppStmt, NULL ); 01257 if ( nError == SQLITE_OK && sqlite3_step( ppStmt ) == SQLITE_ROW ) 01258 { 01259 QDomDocument doc; 01260 QString xmlstr = QString::fromUtf8(( const char * ) sqlite3_column_text( ppStmt, 0 ) ); 01261 if ( !doc.setContent( xmlstr ) ) 01262 { 01263 QgsDebugMsg( QString( "Cannot open smartgroup id: %1" ).arg( id ) ); 01264 } 01265 QDomElement smartEl = doc.documentElement(); 01266 op = smartEl.attribute( "operator" ); 01267 } 01268 01269 sqlite3_finalize( ppStmt ); 01270 01271 return op; 01272 } 01273 01274 bool QgsStyleV2::exportXML( QString filename ) 01275 { 01276 if ( filename.isEmpty() ) 01277 { 01278 QgsDebugMsg( "Invalid filename for style export." ); 01279 return false; 01280 } 01281 01282 QDomDocument doc( "qgis_style" ); 01283 QDomElement root = doc.createElement( "qgis_style" ); 01284 root.setAttribute( "version", STYLE_CURRENT_VERSION ); 01285 doc.appendChild( root ); 01286 01287 // TODO work on the groups and tags 01288 QDomElement symbolsElem = QgsSymbolLayerV2Utils::saveSymbols( mSymbols, "symbols", doc ); 01289 QDomElement rampsElem = doc.createElement( "colorramps" ); 01290 01291 // save color ramps 01292 for ( QMap<QString, QgsVectorColorRampV2*>::iterator itr = mColorRamps.begin(); itr != mColorRamps.end(); ++itr ) 01293 { 01294 QDomElement rampEl = QgsSymbolLayerV2Utils::saveColorRamp( itr.key(), itr.value(), doc ); 01295 rampsElem.appendChild( rampEl ); 01296 } 01297 01298 root.appendChild( symbolsElem ); 01299 root.appendChild( rampsElem ); 01300 01301 // save 01302 QFile f( filename ); 01303 if ( !f.open( QFile::WriteOnly ) ) 01304 { 01305 mErrorString = "Couldn't open file for writing: " + filename; 01306 return false; 01307 } 01308 01309 QTextStream ts( &f ); 01310 doc.save( ts, 2 ); 01311 f.close(); 01312 01313 mFileName = filename; 01314 return true; 01315 } 01316 01317 bool QgsStyleV2::importXML( QString filename ) 01318 { 01319 mErrorString = QString(); 01320 QDomDocument doc( "style" ); 01321 QFile f( filename ); 01322 if ( !f.open( QFile::ReadOnly ) ) 01323 { 01324 mErrorString = "Unable to open the specified file"; 01325 QgsDebugMsg( "Error opening the style XML file." ); 01326 return false; 01327 } 01328 01329 if ( !doc.setContent( &f ) ) 01330 { 01331 mErrorString = QString( "Unable to understand the style file: %1" ).arg( filename ); 01332 QgsDebugMsg( "XML Parsing error" ); 01333 f.close(); 01334 return false; 01335 } 01336 f.close(); 01337 01338 QDomElement docEl = doc.documentElement(); 01339 if ( docEl.tagName() != "qgis_style" ) 01340 { 01341 mErrorString = "Incorrect root tag in style: " + docEl.tagName(); 01342 return false; 01343 } 01344 01345 QString version = docEl.attribute( "version" ); 01346 if ( version != STYLE_CURRENT_VERSION && version != "0" ) 01347 { 01348 mErrorString = "Unknown style file version: " + version; 01349 return false; 01350 } 01351 01352 QgsSymbolV2Map symbols; 01353 01354 QDomElement symbolsElement = docEl.firstChildElement( "symbols" ); 01355 QDomElement e = symbolsElement.firstChildElement(); 01356 01357 if ( version == STYLE_CURRENT_VERSION ) 01358 { 01359 // For the new style, load symbols individualy 01360 while ( !e.isNull() ) 01361 { 01362 if ( e.tagName() == "symbol" ) 01363 { 01364 QgsSymbolV2* symbol = QgsSymbolLayerV2Utils::loadSymbol( e ); 01365 if ( symbol ) 01366 { 01367 symbols.insert( e.attribute( "name" ), symbol ); 01368 } 01369 } 01370 else 01371 { 01372 QgsDebugMsg( "unknown tag: " + e.tagName() ); 01373 } 01374 e = e.nextSiblingElement(); 01375 } 01376 } 01377 else 01378 { 01379 // for the old version, use the utility function to solve @symbol@layer subsymbols 01380 symbols = QgsSymbolLayerV2Utils::loadSymbols( symbolsElement ); 01381 } 01382 01383 // save the symbols with proper name 01384 for ( QMap<QString, QgsSymbolV2*>::iterator it = symbols.begin(); it != symbols.end(); it++ ) 01385 { 01386 addSymbol( it.key(), it.value() ); 01387 } 01388 01389 // load color ramps 01390 QDomElement rampsElement = docEl.firstChildElement( "colorramps" ); 01391 e = rampsElement.firstChildElement(); 01392 while ( !e.isNull() ) 01393 { 01394 if ( e.tagName() == "colorramp" ) 01395 { 01396 QgsVectorColorRampV2* ramp = QgsSymbolLayerV2Utils::loadColorRamp( e ); 01397 if ( ramp ) 01398 { 01399 addColorRamp( e.attribute( "name" ), ramp ); 01400 } 01401 } 01402 else 01403 { 01404 QgsDebugMsg( "unknown tag: " + e.tagName() ); 01405 } 01406 e = e.nextSiblingElement(); 01407 } 01408 01409 mFileName = filename; 01410 return true; 01411 } 01412 01413 bool QgsStyleV2::updateSymbol( StyleEntity type, QString name ) 01414 { 01415 QDomDocument doc( "dummy" ); 01416 QDomElement symEl; 01417 QByteArray xmlArray; 01418 QTextStream stream( &xmlArray ); 01419 01420 char *query; 01421 01422 if ( type == SymbolEntity ) 01423 { 01424 // check if it is an existing symbol 01425 if ( !symbolNames().contains( name ) ) 01426 { 01427 QgsDebugMsg( "Update request received for unavailable symbol" ); 01428 return false; 01429 } 01430 01431 symEl = QgsSymbolLayerV2Utils::saveSymbol( name, symbol( name ), doc ); 01432 if ( symEl.isNull() ) 01433 { 01434 QgsDebugMsg( "Couldn't convert symbol to valid XML!" ); 01435 return false; 01436 } 01437 symEl.save( stream, 4 ); 01438 query = sqlite3_mprintf( "UPDATE symbol SET xml='%q' WHERE name='%q';", 01439 xmlArray.constData(), name.toUtf8().constData() ); 01440 } 01441 else if ( type == ColorrampEntity ) 01442 { 01443 if ( !colorRampNames().contains( name ) ) 01444 { 01445 QgsDebugMsg( "Update requested for unavailable color ramp." ); 01446 return false; 01447 } 01448 01449 symEl = QgsSymbolLayerV2Utils::saveColorRamp( name, colorRamp( name ), doc ); 01450 if ( symEl.isNull() ) 01451 { 01452 QgsDebugMsg( "Couldn't convert color ramp to valid XML!" ); 01453 return false; 01454 } 01455 symEl.save( stream, 4 ); 01456 query = sqlite3_mprintf( "UPDATE colorramp SET xml='%q' WHERE name='%q';", 01457 xmlArray.constData(), name.toUtf8().constData() ); 01458 } 01459 else 01460 { 01461 QgsDebugMsg( "Updating the unsupported StyleEntity" ); 01462 return false; 01463 } 01464 01465 01466 if ( !runEmptyQuery( query ) ) 01467 { 01468 QgsDebugMsg( "Couldn't insert symbol into the database!" ); 01469 return false; 01470 } 01471 return true; 01472 }