26 #include <QDomDocument> 27 #include <QDomElement> 29 #include <QDomNodeList> 31 #include <QTextStream> 37 #define STYLE_CURRENT_VERSION "2" 39 QgsStyle *QgsStyle::sDefaultStyle =
nullptr;
48 switch ( entity->
type() )
51 if ( !static_cast< const QgsStyleSymbolEntity * >( entity )->symbol() )
53 return addSymbol( name, static_cast< const QgsStyleSymbolEntity * >( entity )->
symbol()->clone(), update );
56 if ( !static_cast< const QgsStyleColorRampEntity * >( entity )->ramp() )
58 return addColorRamp( name, static_cast< const QgsStyleColorRampEntity * >( entity )->ramp()->clone(), update );
61 return addTextFormat( name, static_cast< const QgsStyleTextFormatEntity * >( entity )->format(), update );
64 return addLabelSettings( name, static_cast< const QgsStyleLabelSettingsEntity * >( entity )->settings(), update );
81 if ( !QFile::exists( styleFilename ) )
93 sDefaultStyle->
load( styleFilename );
101 delete sDefaultStyle;
102 sDefaultStyle =
nullptr;
107 qDeleteAll( mSymbols );
108 qDeleteAll( mColorRamps );
112 mTextFormats.clear();
113 mCachedColorRampTags.clear();
114 mCachedSymbolTags.clear();
115 mCachedTextFormatTags.clear();
116 mCachedLabelSettingsTags.clear();
118 mCachedSymbolFavorites.clear();
119 mCachedColorRampFavorites.clear();
120 mCachedTextFormatFavorites.clear();
121 mCachedLabelSettingsFavorites.clear();
126 if ( !symbol || name.isEmpty() )
130 if ( mSymbols.contains( name ) )
133 delete mSymbols.value( name );
134 mSymbols.insert( name, symbol );
140 mSymbols.insert( name, symbol );
142 saveSymbol( name, symbol,
false, QStringList() );
151 QDomDocument doc( QStringLiteral(
"dummy" ) );
153 if ( symEl.isNull() )
155 QgsDebugMsg( QStringLiteral(
"Couldn't convert symbol to valid XML!" ) );
160 QTextStream stream( &xmlArray );
161 stream.setCodec(
"UTF-8" );
162 symEl.save( stream, 4 );
163 auto query =
QgsSqlite3Mprintf(
"INSERT INTO symbol VALUES (NULL, '%q', '%q', %d);",
164 name.toUtf8().constData(), xmlArray.constData(), ( favorite ? 1 : 0 ) );
166 if ( !runEmptyQuery( query ) )
168 QgsDebugMsg( QStringLiteral(
"Couldn't insert symbol into the database!" ) );
172 mCachedSymbolFavorites[ name ] = favorite;
194 QgsDebugMsg( QStringLiteral(
"Sorry! Cannot open database to tag." ) );
201 QgsDebugMsg(
"No such symbol for deleting in database: " + name +
". Cheers." );
207 mCachedSymbolTags.remove( name );
208 mCachedSymbolFavorites.remove( name );
217 return symbol ? symbol->
clone() :
nullptr;
222 return mSymbols.value( name );
227 return mSymbols.count();
232 return mSymbols.keys();
238 if ( !colorRamp || name.isEmpty() )
242 if ( mColorRamps.contains( name ) )
245 delete mColorRamps.value( name );
246 mColorRamps.insert( name, colorRamp );
252 mColorRamps.insert( name, colorRamp );
263 if ( mTextFormats.contains( name ) )
266 mTextFormats.remove( name );
267 mTextFormats.insert( name, format );
273 mTextFormats.insert( name, format );
284 if ( mLabelSettings.contains( name ) )
287 mLabelSettings.remove( name );
288 mLabelSettings.insert( name, settings );
294 mLabelSettings.insert( name, settings );
305 QDomDocument doc( QStringLiteral(
"dummy" ) );
308 if ( rampEl.isNull() )
310 QgsDebugMsg( QStringLiteral(
"Couldn't convert color ramp to valid XML!" ) );
315 QTextStream stream( &xmlArray );
316 stream.setCodec(
"UTF-8" );
317 rampEl.save( stream, 4 );
318 auto query =
QgsSqlite3Mprintf(
"INSERT INTO colorramp VALUES (NULL, '%q', '%q', %d);",
319 name.toUtf8().constData(), xmlArray.constData(), ( favorite ? 1 : 0 ) );
320 if ( !runEmptyQuery( query ) )
322 QgsDebugMsg( QStringLiteral(
"Couldn't insert colorramp into the database!" ) );
326 mCachedColorRampFavorites[ name ] = favorite;
337 std::unique_ptr< QgsColorRamp > ramp( mColorRamps.take( name ) );
341 auto query =
QgsSqlite3Mprintf(
"DELETE FROM colorramp WHERE name='%q'", name.toUtf8().constData() );
342 if ( !runEmptyQuery( query ) )
344 QgsDebugMsg( QStringLiteral(
"Couldn't remove color ramp from the database." ) );
348 mCachedColorRampTags.remove( name );
349 mCachedColorRampFavorites.remove( name );
359 return ramp ? ramp->
clone() :
nullptr;
364 return mColorRamps.value( name );
369 return mColorRamps.count();
374 return mColorRamps.keys();
377 bool QgsStyle::openDatabase(
const QString &filename )
379 int rc = mCurrentDB.
open( filename );
382 mErrorString = QStringLiteral(
"Couldn't open the style database: %1" ).arg( mCurrentDB.
errorMessage() );
391 mErrorString.clear();
392 if ( !openDatabase( filename ) )
394 mErrorString = QStringLiteral(
"Unable to create database" );
406 mErrorString.clear();
407 if ( !openDatabase( QStringLiteral(
":memory:" ) ) )
409 mErrorString = QStringLiteral(
"Unable to create temporary memory database" );
422 "id INTEGER PRIMARY KEY,"\
425 "favorite INTEGER);"\
426 "CREATE TABLE colorramp("\
427 "id INTEGER PRIMARY KEY,"\
430 "favorite INTEGER);"\
431 "CREATE TABLE textformat("\
432 "id INTEGER PRIMARY KEY,"\
435 "favorite INTEGER);"\
436 "CREATE TABLE labelsettings("\
437 "id INTEGER PRIMARY KEY,"\
440 "favorite INTEGER);"\
442 "id INTEGER PRIMARY KEY,"\
444 "CREATE TABLE tagmap("\
445 "tag_id INTEGER NOT NULL,"\
446 "symbol_id INTEGER);"\
447 "CREATE TABLE ctagmap("\
448 "tag_id INTEGER NOT NULL,"\
449 "colorramp_id INTEGER);"\
450 "CREATE TABLE tftagmap("\
451 "tag_id INTEGER NOT NULL,"\
452 "textformat_id INTEGER);"\
453 "CREATE TABLE lstagmap("\
454 "tag_id INTEGER NOT NULL,"\
455 "labelsettings_id INTEGER);"\
456 "CREATE TABLE smartgroup("\
457 "id INTEGER PRIMARY KEY,"\
460 runEmptyQuery( query );
465 mErrorString.clear();
468 if ( !openDatabase( filename ) )
470 mErrorString = QStringLiteral(
"Unable to open database file specified" );
476 auto query =
QgsSqlite3Mprintf(
"SELECT name FROM sqlite_master WHERE name='textformat'" );
479 statement = mCurrentDB.
prepare( query, rc );
480 if ( rc != SQLITE_OK || sqlite3_step( statement.get() ) != SQLITE_ROW )
483 "id INTEGER PRIMARY KEY,"\
486 "favorite INTEGER);"\
487 "CREATE TABLE tftagmap("\
488 "tag_id INTEGER NOT NULL,"\
489 "textformat_id INTEGER);" );
490 runEmptyQuery( query );
493 query =
QgsSqlite3Mprintf(
"SELECT name FROM sqlite_master WHERE name='labelsettings'" );
494 statement = mCurrentDB.
prepare( query, rc );
495 if ( rc != SQLITE_OK || sqlite3_step( statement.get() ) != SQLITE_ROW )
498 "id INTEGER PRIMARY KEY,"\
501 "favorite INTEGER);"\
502 "CREATE TABLE lstagmap("\
503 "tag_id INTEGER NOT NULL,"\
504 "labelsettings_id INTEGER);" );
505 runEmptyQuery( query );
509 query =
QgsSqlite3Mprintf(
"UPDATE symbol SET favorite=0 WHERE favorite IS NULL;" 510 "UPDATE colorramp SET favorite=0 WHERE favorite IS NULL;" 511 "UPDATE textformat SET favorite=0 WHERE favorite IS NULL;" 512 "UPDATE labelsettings SET favorite=0 WHERE favorite IS NULL;" 514 runEmptyQuery( query );
518 statement = mCurrentDB.
prepare( query, rc );
520 while ( rc == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
525 if ( !doc.setContent( xmlstring ) )
527 QgsDebugMsg(
"Cannot open symbol " + symbol_name );
531 QDomElement symElement = doc.documentElement();
534 mSymbols.insert( symbol_name, symbol );
538 statement = mCurrentDB.
prepare( query, rc );
539 while ( rc == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
544 if ( !doc.setContent( xmlstring ) )
549 QDomElement rampElement = doc.documentElement();
552 mColorRamps.insert( ramp_name, ramp );
556 statement = mCurrentDB.
prepare( query, rc );
557 while ( rc == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
562 if ( !doc.setContent( xmlstring ) )
564 QgsDebugMsg(
"Cannot open text format " + formatName );
567 QDomElement formatElement = doc.documentElement();
570 mTextFormats.insert( formatName, format );
574 statement = mCurrentDB.
prepare( query, rc );
575 while ( rc == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
580 if ( !doc.setContent( xmlstring ) )
582 QgsDebugMsg(
"Cannot open label settings " + settingsName );
585 QDomElement settingsElement = doc.documentElement();
588 mLabelSettings.insert( settingsName, settings );
591 mFileName = filename;
599 mErrorString.clear();
601 if ( filename.isEmpty() )
602 filename = mFileName;
607 QDomDocument doc(
"qgis_style" );
608 QDomElement root = doc.createElement(
"qgis_style" );
610 doc.appendChild( root );
614 QDomElement rampsElem = doc.createElement(
"colorramps" );
617 for ( QMap<QString, QgsColorRamp *>::iterator itr = mColorRamps.begin(); itr != mColorRamps.end(); ++itr )
620 rampsElem.appendChild( rampEl );
623 root.appendChild( symbolsElem );
624 root.appendChild( rampsElem );
628 if ( !f.open( QFile::WriteOnly ) )
630 mErrorString =
"Couldn't open file for writing: " + filename;
633 QTextStream ts( &f );
634 ts.setCodec(
"UTF-8" );
639 mFileName = filename;
645 if ( mSymbols.contains( newName ) )
647 QgsDebugMsg( QStringLiteral(
"Symbol of new name already exists" ) );
655 mSymbols.insert( newName, symbol );
659 QgsDebugMsg( QStringLiteral(
"Sorry! Cannot open database to tag." ) );
666 QgsDebugMsg( QStringLiteral(
"No such symbol for tagging in database: " ) + oldName );
670 mCachedSymbolTags.remove( oldName );
671 mCachedSymbolFavorites.remove( oldName );
682 if ( mColorRamps.contains( newName ) )
684 QgsDebugMsg( QStringLiteral(
"Color ramp of new name already exists." ) );
692 mColorRamps.insert( newName, ramp );
693 mCachedColorRampTags.remove( oldName );
694 mCachedColorRampFavorites.remove( oldName );
698 auto query =
QgsSqlite3Mprintf(
"SELECT id FROM colorramp WHERE name='%q'", oldName.toUtf8().constData() );
700 statement = mCurrentDB.
prepare( query, nErr );
701 if ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
703 rampid = sqlite3_column_int( statement.get(), 0 );
715 QDomDocument doc( QStringLiteral(
"dummy" ) );
718 if ( formatElem.isNull() )
720 QgsDebugMsg( QStringLiteral(
"Couldn't convert text format to valid XML!" ) );
725 QTextStream stream( &xmlArray );
726 stream.setCodec(
"UTF-8" );
727 formatElem.save( stream, 4 );
728 auto query =
QgsSqlite3Mprintf(
"INSERT INTO textformat VALUES (NULL, '%q', '%q', %d);",
729 name.toUtf8().constData(), xmlArray.constData(), ( favorite ? 1 : 0 ) );
730 if ( !runEmptyQuery( query ) )
732 QgsDebugMsg( QStringLiteral(
"Couldn't insert text format into the database!" ) );
736 mCachedTextFormatFavorites[ name ] = favorite;
747 if ( !mTextFormats.contains( name ) )
750 mTextFormats.remove( name );
752 auto query =
QgsSqlite3Mprintf(
"DELETE FROM textformat WHERE name='%q'", name.toUtf8().constData() );
753 if ( !runEmptyQuery( query ) )
755 QgsDebugMsg( QStringLiteral(
"Couldn't remove text format from the database." ) );
759 mCachedTextFormatTags.remove( name );
760 mCachedTextFormatFavorites.remove( name );
770 if ( mTextFormats.contains( newName ) )
772 QgsDebugMsg( QStringLiteral(
"Text format of new name already exists." ) );
776 if ( !mTextFormats.contains( oldName ) )
780 mTextFormats.insert( newName, format );
781 mCachedTextFormatTags.remove( oldName );
782 mCachedTextFormatFavorites.remove( oldName );
786 auto query =
QgsSqlite3Mprintf(
"SELECT id FROM textformat WHERE name='%q'", oldName.toUtf8().constData() );
788 statement = mCurrentDB.
prepare( query, nErr );
789 if ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
791 textFormatId = sqlite3_column_int( statement.get(), 0 );
803 QDomDocument doc( QStringLiteral(
"dummy" ) );
806 if ( settingsElem.isNull() )
808 QgsDebugMsg( QStringLiteral(
"Couldn't convert label settings to valid XML!" ) );
813 QTextStream stream( &xmlArray );
814 stream.setCodec(
"UTF-8" );
815 settingsElem.save( stream, 4 );
816 auto query =
QgsSqlite3Mprintf(
"INSERT INTO labelsettings VALUES (NULL, '%q', '%q', %d);",
817 name.toUtf8().constData(), xmlArray.constData(), ( favorite ? 1 : 0 ) );
818 if ( !runEmptyQuery( query ) )
820 QgsDebugMsg( QStringLiteral(
"Couldn't insert label settings into the database!" ) );
824 mCachedLabelSettingsFavorites[ name ] = favorite;
835 if ( !mLabelSettings.contains( name ) )
838 mLabelSettings.remove( name );
840 auto query =
QgsSqlite3Mprintf(
"DELETE FROM labelsettings WHERE name='%q'", name.toUtf8().constData() );
841 if ( !runEmptyQuery( query ) )
843 QgsDebugMsg( QStringLiteral(
"Couldn't remove label settings from the database." ) );
847 mCachedLabelSettingsTags.remove( name );
848 mCachedLabelSettingsFavorites.remove( name );
857 if ( mLabelSettings.contains( newName ) )
859 QgsDebugMsg( QStringLiteral(
"Label settings of new name already exists." ) );
863 if ( !mLabelSettings.contains( oldName ) )
867 mLabelSettings.insert( newName, settings );
868 mCachedLabelSettingsTags.remove( oldName );
869 mCachedLabelSettingsFavorites.remove( oldName );
873 auto query =
QgsSqlite3Mprintf(
"SELECT id FROM labelsettings WHERE name='%q'", oldName.toUtf8().constData() );
875 statement = mCurrentDB.
prepare( query, nErr );
876 if ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
878 labelSettingsId = sqlite3_column_int( statement.get(), 0 );
891 QgsDebugMsg( QStringLiteral(
"Cannot Open database for getting favorite symbols" ) );
892 return QStringList();
916 QgsDebugMsg( QStringLiteral(
"No such style entity" ) );
917 return QStringList();
922 statement = mCurrentDB.
prepare( query, nErr );
925 while ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
937 QgsDebugMsg( QStringLiteral(
"Cannot open database to get symbols of tagid %1" ).arg( tagid ) );
938 return QStringList();
945 subquery =
QgsSqlite3Mprintf(
"SELECT symbol_id FROM tagmap WHERE tag_id=%d", tagid );
949 subquery =
QgsSqlite3Mprintf(
"SELECT colorramp_id FROM ctagmap WHERE tag_id=%d", tagid );
953 subquery =
QgsSqlite3Mprintf(
"SELECT textformat_id FROM tftagmap WHERE tag_id=%d", tagid );
957 subquery =
QgsSqlite3Mprintf(
"SELECT labelsettings_id FROM lstagmap WHERE tag_id=%d", tagid );
963 return QStringList();
968 statement = mCurrentDB.
prepare( subquery, nErr );
972 while ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
974 int id = sqlite3_column_int( statement.get(), 0 );
1002 statement2 = mCurrentDB.
prepare( query, rc );
1003 while ( rc == SQLITE_OK && sqlite3_step( statement2.get() ) == SQLITE_ROW )
1018 auto query =
QgsSqlite3Mprintf(
"INSERT INTO tag VALUES (NULL, '%q')", tagname.toUtf8().constData() );
1020 statement = mCurrentDB.
prepare( query, nErr );
1021 if ( nErr == SQLITE_OK )
1022 ( void )sqlite3_step( statement.get() );
1025 settings.
setValue( QStringLiteral(
"qgis/symbolsListGroupsIndex" ), 0 );
1029 return static_cast< int >( sqlite3_last_insert_rowid( mCurrentDB.get() ) );
1035 return QStringList();
1041 statement = mCurrentDB.
prepare( query, nError );
1043 QStringList tagList;
1044 while ( nError == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
1058 query =
QgsSqlite3Mprintf(
"UPDATE symbol SET name='%q' WHERE id=%d", newName.toUtf8().constData(), id );
1061 query =
QgsSqlite3Mprintf(
"UPDATE colorramp SET name='%q' WHERE id=%d", newName.toUtf8().constData(), id );
1064 query =
QgsSqlite3Mprintf(
"UPDATE textformat SET name='%q' WHERE id=%d", newName.toUtf8().constData(), id );
1067 query =
QgsSqlite3Mprintf(
"UPDATE labelsettings SET name='%q' WHERE id=%d", newName.toUtf8().constData(), id );
1070 query =
QgsSqlite3Mprintf(
"UPDATE tag SET name='%q' WHERE id=%d", newName.toUtf8().constData(), id );
1073 query =
QgsSqlite3Mprintf(
"UPDATE smartgroup SET name='%q' WHERE id=%d", newName.toUtf8().constData(), id );
1076 const bool result = runEmptyQuery( query );
1079 mErrorString = QStringLiteral(
"Could not rename!" );
1083 mCachedColorRampTags.clear();
1084 mCachedSymbolTags.clear();
1085 mCachedTextFormatTags.clear();
1086 mCachedLabelSettingsTags.clear();
1087 mCachedSymbolFavorites.clear();
1088 mCachedColorRampFavorites.clear();
1089 mCachedTextFormatFavorites.clear();
1090 mCachedLabelSettingsFavorites.clear();
1118 bool groupRemoved =
false;
1123 query =
QgsSqlite3Mprintf(
"DELETE FROM symbol WHERE id=%d; DELETE FROM tagmap WHERE symbol_id=%d",
id,
id );
1135 query =
QgsSqlite3Mprintf(
"DELETE FROM tag WHERE id=%d; DELETE FROM tagmap WHERE tag_id=%d",
id,
id );
1136 groupRemoved =
true;
1140 groupRemoved =
true;
1144 bool result =
false;
1145 if ( !runEmptyQuery( query ) )
1147 QgsDebugMsg( QStringLiteral(
"Could not delete entity!" ) );
1151 mCachedColorRampTags.clear();
1152 mCachedSymbolTags.clear();
1153 mCachedTextFormatTags.clear();
1154 mCachedLabelSettingsTags.clear();
1155 mCachedSymbolFavorites.clear();
1156 mCachedColorRampFavorites.clear();
1157 mCachedTextFormatFavorites.clear();
1158 mCachedLabelSettingsFavorites.clear();
1163 settings.
setValue( QStringLiteral(
"qgis/symbolsListGroupsIndex" ), 0 );
1172 bool QgsStyle::runEmptyQuery(
const QString &query )
1177 char *zErr =
nullptr;
1178 int nErr = sqlite3_exec( mCurrentDB.get(), query.toUtf8().constData(),
nullptr,
nullptr, &zErr );
1180 if ( nErr != SQLITE_OK )
1183 sqlite3_free( zErr );
1186 return nErr == SQLITE_OK;
1196 query =
QgsSqlite3Mprintf(
"UPDATE symbol SET favorite=1 WHERE name='%q'", name.toUtf8().constData() );
1199 query =
QgsSqlite3Mprintf(
"UPDATE colorramp SET favorite=1 WHERE name='%q'", name.toUtf8().constData() );
1202 query =
QgsSqlite3Mprintf(
"UPDATE textformat SET favorite=1 WHERE name='%q'", name.toUtf8().constData() );
1205 query =
QgsSqlite3Mprintf(
"UPDATE labelsettings SET favorite=1 WHERE name='%q'", name.toUtf8().constData() );
1210 QgsDebugMsg( QStringLiteral(
"Wrong entity value. cannot apply group" ) );
1214 const bool res = runEmptyQuery( query );
1220 mCachedSymbolFavorites[ name ] =
true;
1223 mCachedColorRampFavorites[ name ] =
true;
1226 mCachedTextFormatFavorites[ name ] =
true;
1229 mCachedLabelSettingsFavorites[ name ] =
true;
1248 query =
QgsSqlite3Mprintf(
"UPDATE symbol SET favorite=0 WHERE name='%q'", name.toUtf8().constData() );
1251 query =
QgsSqlite3Mprintf(
"UPDATE colorramp SET favorite=0 WHERE name='%q'", name.toUtf8().constData() );
1254 query =
QgsSqlite3Mprintf(
"UPDATE textformat SET favorite=0 WHERE name='%q'", name.toUtf8().constData() );
1257 query =
QgsSqlite3Mprintf(
"UPDATE labelsettings SET favorite=0 WHERE name='%q'", name.toUtf8().constData() );
1262 QgsDebugMsg( QStringLiteral(
"Wrong entity value. cannot apply group" ) );
1266 const bool res = runEmptyQuery( query );
1272 mCachedSymbolFavorites[ name ] =
false;
1275 mCachedColorRampFavorites[ name ] =
false;
1278 mCachedTextFormatFavorites[ name ] =
false;
1281 mCachedLabelSettingsFavorites[ name ] =
false;
1297 QgsDebugMsg( QStringLiteral(
"Sorry! Cannot open database to search" ) );
1298 return QStringList();
1306 item = QStringLiteral(
"symbol" );
1310 item = QStringLiteral(
"colorramp" );
1314 item = QStringLiteral(
"textformat" );
1318 item = QStringLiteral(
"labelsettings" );
1323 return QStringList();
1327 item.toUtf8().constData(), qword.toUtf8().constData() );
1330 int nErr; statement = mCurrentDB.
prepare( query, nErr );
1332 QSet< QString > symbols;
1333 while ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
1339 query =
QgsSqlite3Mprintf(
"SELECT id FROM tag WHERE name LIKE '%%%q%%'", qword.toUtf8().constData() );
1340 statement = mCurrentDB.
prepare( query, nErr );
1343 while ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
1348 QString dummy = tagids.join( QStringLiteral(
", " ) );
1354 dummy.toUtf8().constData() );
1358 query =
QgsSqlite3Mprintf(
"SELECT colorramp_id FROM ctagmap WHERE tag_id IN (%q)",
1359 dummy.toUtf8().constData() );
1363 query =
QgsSqlite3Mprintf(
"SELECT textformat_id FROM tftagmap WHERE tag_id IN (%q)",
1364 dummy.toUtf8().constData() );
1368 query =
QgsSqlite3Mprintf(
"SELECT labelsettings_id FROM lstagmap WHERE tag_id IN (%q)",
1369 dummy.toUtf8().constData() );
1374 return QStringList();
1377 statement = mCurrentDB.
prepare( query, nErr );
1379 QStringList symbolids;
1380 while ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
1385 dummy = symbolids.join( QStringLiteral(
", " ) );
1387 item.toUtf8().constData(), dummy.toUtf8().constData() );
1388 statement = mCurrentDB.
prepare( query, nErr );
1389 while ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
1394 return symbols.toList();
1401 QgsDebugMsg( QStringLiteral(
"Sorry! Cannot open database to tag." ) );
1432 QgsDebugMsg( QStringLiteral(
"No such symbol for tagging in database: " ) + symbol );
1437 const auto constTags =
tags;
1438 for (
const QString &t : constTags )
1441 if ( !tag.isEmpty() )
1444 int tagid(
tagId( tag ) );
1457 query =
QgsSqlite3Mprintf(
"INSERT INTO tagmap VALUES (%d,%d)", tagid, symbolid );
1461 query =
QgsSqlite3Mprintf(
"INSERT INTO ctagmap VALUES (%d,%d)", tagid, symbolid );
1465 query =
QgsSqlite3Mprintf(
"INSERT INTO tftagmap VALUES (%d,%d)", tagid, symbolid );
1469 query =
QgsSqlite3Mprintf(
"INSERT INTO lstagmap VALUES (%d,%d)", tagid, symbolid );
1477 char *zErr =
nullptr;
1479 nErr = sqlite3_exec( mCurrentDB.get(), query.toUtf8().constData(),
nullptr,
nullptr, &zErr );
1483 sqlite3_free( zErr );
1489 clearCachedTags( type, symbol );
1499 QgsDebugMsg( QStringLiteral(
"Sorry! Cannot open database for detagging." ) );
1507 query =
QgsSqlite3Mprintf(
"SELECT id FROM symbol WHERE name='%q'", symbol.toUtf8().constData() );
1511 query =
QgsSqlite3Mprintf(
"SELECT id FROM colorramp WHERE name='%q'", symbol.toUtf8().constData() );
1515 query =
QgsSqlite3Mprintf(
"SELECT id FROM textformat WHERE name='%q'", symbol.toUtf8().constData() );
1519 query =
QgsSqlite3Mprintf(
"SELECT id FROM labelsettings WHERE name='%q'", symbol.toUtf8().constData() );
1527 int nErr; statement = mCurrentDB.
prepare( query, nErr );
1530 if ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
1532 symbolid = sqlite3_column_int( statement.get(), 0 );
1539 const auto constTags =
tags;
1540 for (
const QString &
tag : constTags )
1545 statement2 = mCurrentDB.
prepare( query, nErr );
1548 if ( nErr == SQLITE_OK && sqlite3_step( statement2.get() ) == SQLITE_ROW )
1550 tagid = sqlite3_column_int( statement2.get(), 0 );
1560 query =
QgsSqlite3Mprintf(
"DELETE FROM tagmap WHERE tag_id=%d AND symbol_id=%d", tagid, symbolid );
1564 query =
QgsSqlite3Mprintf(
"DELETE FROM ctagmap WHERE tag_id=%d AND colorramp_id=%d", tagid, symbolid );
1568 query =
QgsSqlite3Mprintf(
"DELETE FROM tftagmap WHERE tag_id=%d AND textformat_id=%d", tagid, symbolid );
1572 query =
QgsSqlite3Mprintf(
"DELETE FROM lstagmap WHERE tag_id=%d AND labelsettings_id=%d", tagid, symbolid );
1580 runEmptyQuery( query );
1584 clearCachedTags( type, symbol );
1597 QgsDebugMsg( QStringLiteral(
"Sorry! Cannot open database for detagging." ) );
1605 query =
QgsSqlite3Mprintf(
"SELECT id FROM symbol WHERE name='%q'", symbol.toUtf8().constData() );
1609 query =
QgsSqlite3Mprintf(
"SELECT id FROM colorramp WHERE name='%q'", symbol.toUtf8().constData() );
1613 query =
QgsSqlite3Mprintf(
"SELECT id FROM textformat WHERE name='%q'", symbol.toUtf8().constData() );
1617 query =
QgsSqlite3Mprintf(
"SELECT id FROM labelsettings WHERE name='%q'", symbol.toUtf8().constData() );
1627 statement = mCurrentDB.
prepare( query, nErr );
1630 if ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
1632 symbolid = sqlite3_column_int( statement.get(), 0 );
1647 query =
QgsSqlite3Mprintf(
"DELETE FROM ctagmap WHERE colorramp_id=%d", symbolid );
1651 query =
QgsSqlite3Mprintf(
"DELETE FROM tftagmap WHERE textformat_id=%d", symbolid );
1655 query =
QgsSqlite3Mprintf(
"DELETE FROM lstagmap WHERE labelsettings_id=%d", symbolid );
1663 runEmptyQuery( query );
1665 clearCachedTags( type, symbol );
1679 if ( mCachedSymbolTags.contains( symbol ) )
1680 return mCachedSymbolTags.value( symbol );
1684 if ( mCachedColorRampTags.contains( symbol ) )
1685 return mCachedColorRampTags.value( symbol );
1689 if ( mCachedTextFormatTags.contains( symbol ) )
1690 return mCachedTextFormatTags.value( symbol );
1694 if ( mCachedLabelSettingsTags.contains( symbol ) )
1695 return mCachedLabelSettingsTags.value( symbol );
1705 QgsDebugMsg( QStringLiteral(
"Sorry! Cannot open database for getting the tags." ) );
1706 return QStringList();
1735 return QStringList();
1742 query =
QgsSqlite3Mprintf(
"SELECT tag_id FROM tagmap WHERE symbol_id=%d", symbolid );
1746 query =
QgsSqlite3Mprintf(
"SELECT tag_id FROM ctagmap WHERE colorramp_id=%d", symbolid );
1750 query =
QgsSqlite3Mprintf(
"SELECT tag_id FROM tftagmap WHERE textformat_id=%d", symbolid );
1754 query =
QgsSqlite3Mprintf(
"SELECT tag_id FROM lstagmap WHERE labelsettings_id=%d", symbolid );
1759 return QStringList();
1763 int nErr; statement = mCurrentDB.
prepare( query, nErr );
1765 QStringList tagList;
1766 while ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
1768 auto subquery =
QgsSqlite3Mprintf(
"SELECT name FROM tag WHERE id=%d", sqlite3_column_int( statement.get(), 0 ) );
1772 statement2 = mCurrentDB.
prepare( subquery, pErr );
1773 if ( pErr == SQLITE_OK && sqlite3_step( statement2.get() ) == SQLITE_ROW )
1783 mCachedSymbolTags[
symbol ] = tagList;
1787 mCachedColorRampTags[
symbol ] = tagList;
1791 mCachedTextFormatTags[
symbol ] = tagList;
1795 mCachedLabelSettingsTags[
symbol ] = tagList;
1810 QgsDebugMsg( QStringLiteral(
"Sorry! Cannot open database for getting the tags." ) );
1817 if ( mCachedSymbolFavorites.contains( name ) )
1818 return mCachedSymbolFavorites.value( name );
1822 if ( mCachedColorRampFavorites.contains( name ) )
1823 return mCachedColorRampFavorites.value( name );
1827 if ( mCachedTextFormatFavorites.contains( name ) )
1828 return mCachedTextFormatFavorites.value( name );
1832 if ( mCachedLabelSettingsFavorites.contains( name ) )
1833 return mCachedLabelSettingsFavorites.value( name );
1841 const QStringList names =
allNames( type );
1842 if ( !names.contains( name ) )
1848 for (
const QString &n : names )
1850 const bool isFav = favorites.contains( n );
1857 mCachedSymbolFavorites[n] = isFav;
1861 mCachedColorRampFavorites[ n ] = isFav;
1865 mCachedTextFormatFavorites[ n ] = isFav;
1869 mCachedLabelSettingsFavorites[ n ] = isFav;
1884 QgsDebugMsg( QStringLiteral(
"Sorry! Cannot open database for getting the tags." ) );
1916 int tagid =
tagId( tag );
1928 query =
QgsSqlite3Mprintf(
"SELECT tag_id FROM tagmap WHERE tag_id=%d AND symbol_id=%d", tagid, symbolid );
1932 query =
QgsSqlite3Mprintf(
"SELECT tag_id FROM ctagmap WHERE tag_id=%d AND colorramp_id=%d", tagid, symbolid );
1936 query =
QgsSqlite3Mprintf(
"SELECT tag_id FROM tftagmap WHERE tag_id=%d AND textformat_id=%d", tagid, symbolid );
1940 query =
QgsSqlite3Mprintf(
"SELECT tag_id FROM lstagmap WHERE tag_id=%d AND labelsettings_id=%d", tagid, symbolid );
1948 int nErr; statement = mCurrentDB.
prepare( query, nErr );
1950 return ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW );
1962 statement = mCurrentDB.
prepare( query, nError );
1965 if ( nError == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
1973 int QgsStyle::getId(
const QString &table,
const QString &name )
1975 QString lowerName( name.toLower() );
1976 auto query =
QgsSqlite3Mprintf(
"SELECT id FROM %q WHERE LOWER(name)='%q'", table.toUtf8().constData(), lowerName.toUtf8().constData() );
1979 int nErr; statement = mCurrentDB.
prepare( query, nErr );
1982 if ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
1984 id = sqlite3_column_int( statement.get(), 0 );
1989 auto query =
QgsSqlite3Mprintf(
"SELECT id FROM %q WHERE name='%q'", table.toUtf8().constData(), name.toUtf8().constData() );
1992 int nErr; statement = mCurrentDB.
prepare( query, nErr );
1993 if ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
1995 id = sqlite3_column_int( statement.get(), 0 );
2002 QString QgsStyle::getName(
const QString &table,
int id )
const 2004 auto query =
QgsSqlite3Mprintf(
"SELECT name FROM %q WHERE id='%q'", table.toUtf8().constData(), QString::number(
id ).toUtf8().constData() );
2007 int nErr; statement = mCurrentDB.
prepare( query, nErr );
2010 if ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
2020 return getId( QStringLiteral(
"symbol" ), name );
2025 return getId( QStringLiteral(
"colorramp" ), name );
2030 return mTextFormats.value( name );
2035 return mTextFormats.count();
2040 return mTextFormats.keys();
2045 return getId( QStringLiteral(
"textformat" ), name );
2050 return mLabelSettings.value( name );
2055 if ( !mLabelSettings.contains( name ) )
2058 return mLabelSettings.value( name ).layerType;
2063 return mLabelSettings.count();
2068 return mLabelSettings.keys();
2073 return getId( QStringLiteral(
"labelsettings" ), name );
2078 return getId( QStringLiteral(
"tag" ), name );
2083 return getId( QStringLiteral(
"smartgroup" ), name );
2108 return QStringList();
2113 return addSmartgroup( name, op, conditions.values( QStringLiteral(
"tag" ) ),
2114 conditions.values( QStringLiteral(
"!tag" ) ),
2115 conditions.values( QStringLiteral(
"name" ) ),
2116 conditions.values( QStringLiteral(
"!name" ) ) );
2119 int QgsStyle::addSmartgroup(
const QString &name,
const QString &op,
const QStringList &matchTag,
const QStringList &noMatchTag,
const QStringList &matchName,
const QStringList &noMatchName )
2121 QDomDocument doc( QStringLiteral(
"dummy" ) );
2122 QDomElement smartEl = doc.createElement( QStringLiteral(
"smartgroup" ) );
2123 smartEl.setAttribute( QStringLiteral(
"name" ), name );
2124 smartEl.setAttribute( QStringLiteral(
"operator" ), op );
2126 auto addCondition = [&doc, &smartEl](
const QString & constraint,
const QStringList & parameters )
2128 for (
const QString ¶m : parameters )
2130 QDomElement condEl = doc.createElement( QStringLiteral(
"condition" ) );
2131 condEl.setAttribute( QStringLiteral(
"constraint" ), constraint );
2132 condEl.setAttribute( QStringLiteral(
"param" ), param );
2133 smartEl.appendChild( condEl );
2136 addCondition( QStringLiteral(
"tag" ), matchTag );
2137 addCondition( QStringLiteral(
"!tag" ), noMatchTag );
2138 addCondition( QStringLiteral(
"name" ), matchName );
2139 addCondition( QStringLiteral(
"!name" ), noMatchName );
2141 QByteArray xmlArray;
2142 QTextStream stream( &xmlArray );
2143 stream.setCodec(
"UTF-8" );
2144 smartEl.save( stream, 4 );
2145 auto query =
QgsSqlite3Mprintf(
"INSERT INTO smartgroup VALUES (NULL, '%q', '%q')",
2146 name.toUtf8().constData(), xmlArray.constData() );
2148 if ( runEmptyQuery( query ) )
2151 settings.
setValue( QStringLiteral(
"qgis/symbolsListGroupsIndex" ), 0 );
2154 return static_cast< int >( sqlite3_last_insert_rowid( mCurrentDB.get() ) );
2158 QgsDebugMsg( QStringLiteral(
"Couldn't insert symbol into the database!" ) );
2167 QgsDebugMsg( QStringLiteral(
"Cannot open database for listing groups" ) );
2176 statement = mCurrentDB.
prepare( query, nError );
2179 while ( nError == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
2182 groupNames.insert( sqlite3_column_int( statement.get(),
SmartgroupId ), group );
2192 QgsDebugMsg( QStringLiteral(
"Cannot open database for listing groups" ) );
2193 return QStringList();
2201 statement = mCurrentDB.
prepare( query, nError );
2204 while ( nError == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
2214 QStringList symbols;
2219 int nErr; statement = mCurrentDB.
prepare( query, nErr );
2220 if ( !( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW ) )
2222 return QStringList();
2228 if ( !doc.setContent( xmlstr ) )
2230 QgsDebugMsg( QStringLiteral(
"Cannot open smartgroup id: %1" ).arg(
id ) );
2232 QDomElement smartEl = doc.documentElement();
2233 QString op = smartEl.attribute( QStringLiteral(
"operator" ) );
2234 QDomNodeList conditionNodes = smartEl.childNodes();
2236 bool firstSet =
true;
2237 for (
int i = 0; i < conditionNodes.count(); i++ )
2239 QDomElement condEl = conditionNodes.at( i ).toElement();
2240 QString constraint = condEl.attribute( QStringLiteral(
"constraint" ) );
2241 QString param = condEl.attribute( QStringLiteral(
"param" ) );
2243 QStringList resultNames;
2245 if ( constraint == QLatin1String(
"tag" ) )
2249 else if ( constraint == QLatin1String(
"name" ) )
2251 resultNames =
allNames( type ).filter( param, Qt::CaseInsensitive );
2253 else if ( constraint == QLatin1String(
"!tag" ) )
2257 for (
const QString &name : unwanted )
2259 resultNames.removeAll( name );
2262 else if ( constraint == QLatin1String(
"!name" ) )
2264 const QStringList all =
allNames( type );
2265 for (
const QString &str : all )
2267 if ( !str.contains( param, Qt::CaseInsensitive ) )
2275 symbols = resultNames;
2280 if ( op == QLatin1String(
"OR" ) )
2282 symbols << resultNames;
2284 else if ( op == QLatin1String(
"AND" ) )
2286 QStringList dummy = symbols;
2288 for (
const QString &result : qgis::as_const( resultNames ) )
2290 if ( dummy.contains( result ) )
2299 QStringList unique = symbols.toSet().toList();
2300 std::sort( unique.begin(), unique.end() );
2308 QgsDebugMsg( QStringLiteral(
"Cannot open database for listing groups" ) );
2318 statement = mCurrentDB.
prepare( query, nError );
2319 if ( nError == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
2323 if ( !doc.setContent( xmlstr ) )
2325 QgsDebugMsg( QStringLiteral(
"Cannot open smartgroup id: %1" ).arg(
id ) );
2328 QDomElement smartEl = doc.documentElement();
2329 QDomNodeList conditionNodes = smartEl.childNodes();
2331 for (
int i = 0; i < conditionNodes.count(); i++ )
2333 QDomElement condEl = conditionNodes.at( i ).toElement();
2334 QString constraint = condEl.attribute( QStringLiteral(
"constraint" ) );
2335 QString param = condEl.attribute( QStringLiteral(
"param" ) );
2337 condition.insert( constraint, param );
2348 QgsDebugMsg( QStringLiteral(
"Cannot open database for listing groups" ) );
2358 statement = mCurrentDB.
prepare( query, nError );
2359 if ( nError == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
2363 if ( !doc.setContent( xmlstr ) )
2365 QgsDebugMsg( QStringLiteral(
"Cannot open smartgroup id: %1" ).arg(
id ) );
2367 QDomElement smartEl = doc.documentElement();
2368 op = smartEl.attribute( QStringLiteral(
"operator" ) );
2376 if ( filename.isEmpty() )
2378 QgsDebugMsg( QStringLiteral(
"Invalid filename for style export." ) );
2382 QDomDocument doc( QStringLiteral(
"qgis_style" ) );
2383 QDomElement root = doc.createElement( QStringLiteral(
"qgis_style" ) );
2385 doc.appendChild( root );
2393 QDomNodeList symbolsList = symbolsElem.elementsByTagName( QStringLiteral(
"symbol" ) );
2394 int nbSymbols = symbolsList.count();
2395 for (
int i = 0; i < nbSymbols; ++i )
2397 QDomElement
symbol = symbolsList.at( i ).toElement();
2398 QString name = symbol.attribute( QStringLiteral(
"name" ) );
2400 if ( tags.count() > 0 )
2402 symbol.setAttribute( QStringLiteral(
"tags" ), tags.join(
',' ) );
2404 if ( favoriteSymbols.contains( name ) )
2406 symbol.setAttribute( QStringLiteral(
"favorite" ), QStringLiteral(
"1" ) );
2411 QDomElement rampsElem = doc.createElement( QStringLiteral(
"colorramps" ) );
2412 for ( QMap<QString, QgsColorRamp *>::const_iterator itr = mColorRamps.constBegin(); itr != mColorRamps.constEnd(); ++itr )
2416 if ( tags.count() > 0 )
2418 rampEl.setAttribute( QStringLiteral(
"tags" ), tags.join(
',' ) );
2420 if ( favoriteColorramps.contains( itr.key() ) )
2422 rampEl.setAttribute( QStringLiteral(
"favorite" ), QStringLiteral(
"1" ) );
2424 rampsElem.appendChild( rampEl );
2428 QDomElement textFormatsElem = doc.createElement( QStringLiteral(
"textformats" ) );
2429 for (
auto it = mTextFormats.constBegin(); it != mTextFormats.constEnd(); ++it )
2431 QDomElement textFormatEl = doc.createElement( QStringLiteral(
"textformat" ) );
2432 textFormatEl.setAttribute( QStringLiteral(
"name" ), it.key() );
2434 textFormatEl.appendChild( textStyleEl );
2436 if ( tags.count() > 0 )
2438 textFormatEl.setAttribute( QStringLiteral(
"tags" ), tags.join(
',' ) );
2440 if ( favoriteTextFormats.contains( it.key() ) )
2442 textFormatEl.setAttribute( QStringLiteral(
"favorite" ), QStringLiteral(
"1" ) );
2444 textFormatsElem.appendChild( textFormatEl );
2448 QDomElement labelSettingsElem = doc.createElement( QStringLiteral(
"labelsettings" ) );
2449 for (
auto it = mLabelSettings.constBegin(); it != mLabelSettings.constEnd(); ++it )
2451 QDomElement labelSettingsEl = doc.createElement( QStringLiteral(
"labelsetting" ) );
2452 labelSettingsEl.setAttribute( QStringLiteral(
"name" ), it.key() );
2454 labelSettingsEl.appendChild( defEl );
2456 if ( tags.count() > 0 )
2458 labelSettingsEl.setAttribute( QStringLiteral(
"tags" ), tags.join(
',' ) );
2460 if ( favoriteTextFormats.contains( it.key() ) )
2462 labelSettingsEl.setAttribute( QStringLiteral(
"favorite" ), QStringLiteral(
"1" ) );
2464 labelSettingsElem.appendChild( labelSettingsEl );
2467 root.appendChild( symbolsElem );
2468 root.appendChild( rampsElem );
2469 root.appendChild( textFormatsElem );
2470 root.appendChild( labelSettingsElem );
2473 QFile f( filename );
2474 if ( !f.open( QFile::WriteOnly | QIODevice::Truncate ) )
2476 mErrorString =
"Couldn't open file for writing: " + filename;
2480 QTextStream ts( &f );
2481 ts.setCodec(
"UTF-8" );
2485 mFileName = filename;
2491 mErrorString = QString();
2492 QDomDocument doc( QStringLiteral(
"style" ) );
2493 QFile f( filename );
2494 if ( !f.open( QFile::ReadOnly ) )
2496 mErrorString = QStringLiteral(
"Unable to open the specified file" );
2497 QgsDebugMsg( QStringLiteral(
"Error opening the style XML file." ) );
2501 if ( !doc.setContent( &f ) )
2503 mErrorString = QStringLiteral(
"Unable to understand the style file: %1" ).arg( filename );
2504 QgsDebugMsg( QStringLiteral(
"XML Parsing error" ) );
2510 QDomElement docEl = doc.documentElement();
2511 if ( docEl.tagName() != QLatin1String(
"qgis_style" ) )
2513 mErrorString =
"Incorrect root tag in style: " + docEl.tagName();
2517 const QString version = docEl.attribute( QStringLiteral(
"version" ) );
2518 if ( version != QLatin1String(
STYLE_CURRENT_VERSION ) && version != QLatin1String(
"0" ) && version != QLatin1String(
"1" ) )
2520 mErrorString =
"Unknown style file version: " + version;
2526 QDomElement symbolsElement = docEl.firstChildElement( QStringLiteral(
"symbols" ) );
2527 QDomElement e = symbolsElement.firstChildElement();
2531 runEmptyQuery( query );
2536 while ( !e.isNull() )
2538 if ( e.tagName() == QLatin1String(
"symbol" ) )
2540 QString name = e.attribute( QStringLiteral(
"name" ) );
2542 if ( e.hasAttribute( QStringLiteral(
"tags" ) ) )
2544 tags = e.attribute( QStringLiteral(
"tags" ) ).split(
',' );
2546 bool favorite =
false;
2547 if ( e.hasAttribute( QStringLiteral(
"favorite" ) ) && e.attribute( QStringLiteral(
"favorite" ) ) == QStringLiteral(
"1" ) )
2566 e = e.nextSiblingElement();
2575 for ( QMap<QString, QgsSymbol *>::iterator it = symbols.begin(); it != symbols.end(); ++it )
2582 QDomElement rampsElement = docEl.firstChildElement( QStringLiteral(
"colorramps" ) );
2583 e = rampsElement.firstChildElement();
2584 while ( !e.isNull() )
2586 if ( e.tagName() == QLatin1String(
"colorramp" ) )
2588 QString name = e.attribute( QStringLiteral(
"name" ) );
2590 if ( e.hasAttribute( QStringLiteral(
"tags" ) ) )
2592 tags = e.attribute( QStringLiteral(
"tags" ) ).split(
',' );
2594 bool favorite =
false;
2595 if ( e.hasAttribute( QStringLiteral(
"favorite" ) ) && e.attribute( QStringLiteral(
"favorite" ) ) == QStringLiteral(
"1" ) )
2614 e = e.nextSiblingElement();
2620 const QDomElement textFormatElement = docEl.firstChildElement( QStringLiteral(
"textformats" ) );
2621 e = textFormatElement.firstChildElement();
2622 while ( !e.isNull() )
2624 if ( e.tagName() == QLatin1String(
"textformat" ) )
2626 QString name = e.attribute( QStringLiteral(
"name" ) );
2628 if ( e.hasAttribute( QStringLiteral(
"tags" ) ) )
2630 tags = e.attribute( QStringLiteral(
"tags" ) ).split(
',' );
2632 bool favorite =
false;
2633 if ( e.hasAttribute( QStringLiteral(
"favorite" ) ) && e.attribute( QStringLiteral(
"favorite" ) ) == QStringLiteral(
"1" ) )
2639 const QDomElement styleElem = e.firstChildElement();
2651 e = e.nextSiblingElement();
2658 const QDomElement labelSettingsElement = docEl.firstChildElement( QStringLiteral(
"labelsettings" ) );
2659 e = labelSettingsElement.firstChildElement();
2660 while ( !e.isNull() )
2662 if ( e.tagName() == QLatin1String(
"labelsetting" ) )
2664 QString name = e.attribute( QStringLiteral(
"name" ) );
2666 if ( e.hasAttribute( QStringLiteral(
"tags" ) ) )
2668 tags = e.attribute( QStringLiteral(
"tags" ) ).split(
',' );
2670 bool favorite =
false;
2671 if ( e.hasAttribute( QStringLiteral(
"favorite" ) ) && e.attribute( QStringLiteral(
"favorite" ) ) == QStringLiteral(
"1" ) )
2677 const QDomElement styleElem = e.firstChildElement();
2689 e = e.nextSiblingElement();
2695 runEmptyQuery( query );
2697 mFileName = filename;
2703 QFileInfo fileInfo( path );
2705 if ( fileInfo.suffix().compare( QLatin1String(
"xml" ), Qt::CaseInsensitive ) != 0 )
2709 if ( !QFile::exists( path ) )
2712 QFile inputFile( path );
2713 if ( !inputFile.open( QIODevice::ReadOnly ) )
2716 QTextStream stream( &inputFile );
2717 const QString line = stream.readLine();
2718 return line == QLatin1String(
"<!DOCTYPE qgis_style>" );
2721 bool QgsStyle::updateSymbol(
StyleEntity type,
const QString &name )
2723 QDomDocument doc( QStringLiteral(
"dummy" ) );
2725 QByteArray xmlArray;
2726 QTextStream stream( &xmlArray );
2727 stream.setCodec(
"UTF-8" );
2738 QgsDebugMsg( QStringLiteral(
"Update request received for unavailable symbol" ) );
2743 if ( symEl.isNull() )
2745 QgsDebugMsg( QStringLiteral(
"Couldn't convert symbol to valid XML!" ) );
2748 symEl.save( stream, 4 );
2750 xmlArray.constData(), name.toUtf8().constData() );
2758 QgsDebugMsg( QStringLiteral(
"Update requested for unavailable color ramp." ) );
2762 std::unique_ptr< QgsColorRamp > ramp(
colorRamp( name ) );
2764 if ( symEl.isNull() )
2766 QgsDebugMsg( QStringLiteral(
"Couldn't convert color ramp to valid XML!" ) );
2769 symEl.save( stream, 4 );
2771 xmlArray.constData(), name.toUtf8().constData() );
2779 QgsDebugMsg( QStringLiteral(
"Update requested for unavailable text format." ) );
2785 if ( symEl.isNull() )
2787 QgsDebugMsg( QStringLiteral(
"Couldn't convert text format to valid XML!" ) );
2790 symEl.save( stream, 4 );
2792 xmlArray.constData(), name.toUtf8().constData() );
2800 QgsDebugMsg( QStringLiteral(
"Update requested for unavailable label settings." ) );
2806 if ( symEl.isNull() )
2808 QgsDebugMsg( QStringLiteral(
"Couldn't convert label settings to valid XML!" ) );
2811 symEl.save( stream, 4 );
2812 query =
QgsSqlite3Mprintf(
"UPDATE labelsettings SET xml='%q' WHERE name='%q';",
2813 xmlArray.constData(), name.toUtf8().constData() );
2820 QgsDebugMsg( QStringLiteral(
"Updating the unsupported StyleEntity" ) );
2826 if ( !runEmptyQuery( query ) )
2828 QgsDebugMsg( QStringLiteral(
"Couldn't insert symbol into the database!" ) );
2864 mCachedSymbolTags.remove( name );
2868 mCachedColorRampTags.remove( name );
2872 mCachedTextFormatTags.remove( name );
2876 mCachedLabelSettingsTags.remove( name );
bool exportXml(const QString &filename)
Exports the style as a XML file.
QStringList allNames(StyleEntity type) const
Returns a list of the names of all existing entities of the specified type.
The class is used as a container of context for various read/write operations on other objects...
void clear()
Removes all contents of the style.
const QgsColorRamp * colorRampRef(const QString &name) const
Returns a const pointer to a symbol (doesn't create new instance)
bool addEntity(const QString &name, const QgsStyleEntityInterface *entity, bool update=false)
Adds an entity to the style, with the specified name.
bool addTextFormat(const QString &name, const QgsTextFormat &format, bool update=false)
Adds a text format with the specified name to the style.
bool addColorRamp(const QString &name, QgsColorRamp *colorRamp, bool update=false)
Adds a color ramp to the style.
void symbolSaved(const QString &name, QgsSymbol *symbol)
Emitted every time a new symbol has been added to the database.
static QString userStylePath()
Returns the path to user's style.
bool symbolHasTag(StyleEntity type, const QString &symbol, const QString &tag)
Returns whether a given tag is associated with the symbol.
bool save(QString filename=QString())
Saves style into a file (will use current filename if empty string is passed)
void textFormatAdded(const QString &name)
Emitted whenever a text format has been added to the style and the database has been updated as a res...
void readXml(const QDomElement &elem, const QgsReadWriteContext &context)
Read settings from a DOM element.
Abstract base class for all rendered symbols.
An interface for entities which can be placed in a QgsStyle database.
This class is a composition of two QSettings instances:
QStringList symbolsWithTag(StyleEntity type, int tagid) const
Returns the symbol names with which have the given tag.
void entityTagsChanged(QgsStyle::StyleEntity entity, const QString &name, const QStringList &newTags)
Emitted whenever an entity's tags are changed.
Unique pointer for sqlite3 prepared statements, which automatically finalizes the statement when the ...
void createTables()
Creates tables structure for new database.
bool load(const QString &filename)
Loads a file into the style.
virtual QgsColorRamp * clone() const =0
Creates a clone of the color ramp.
bool addLabelSettings(const QString &name, const QgsPalLayerSettings &settings, bool update=false)
Adds label settings with the specified name to the style.
QStringList tagsOfSymbol(StyleEntity type, const QString &symbol)
Returns the tags associated with the symbol.
Abstract base class for color ramps.
QMap< int, QString > QgsSymbolGroupMap
bool saveColorRamp(const QString &name, QgsColorRamp *ramp, bool favorite, const QStringList &tags)
Adds the colorramp to the DB.
static QDomElement saveColorRamp(const QString &name, QgsColorRamp *ramp, QDomDocument &doc)
Encodes a color ramp's settings to an XML element.
int textFormatCount() const
Returns count of text formats in the style.
bool tagSymbol(StyleEntity type, const QString &symbol, const QStringList &tags)
Tags the symbol with the tags in the list.
static QDomElement saveSymbol(const QString &symbolName, const QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML.
Symbol definition (as XML)
int labelSettingsId(const QString &name)
Returns the ID in the style database for the given label settings by name.
void textFormatRemoved(const QString &name)
Emitted whenever a text format has been removed from the style and the database has been updated as a...
static QgsSymbol * loadSymbol(const QDomElement &element, const QgsReadWriteContext &context)
Attempts to load a symbol from a DOM element.
void rampChanged(const QString &name)
Emitted whenever a color ramp's definition is changed.
QgsColorRamp * colorRamp(const QString &name) const
Returns a new copy of the specified color ramp.
bool removeColorRamp(const QString &name)
Removes color ramp from style (and delete it)
bool rename(StyleEntity type, int id, const QString &newName)
Renames the given entity with the specified id.
void rampAdded(const QString &name)
Emitted whenever a color ramp has been added to the style and the database has been updated as a resu...
#define STYLE_CURRENT_VERSION
static QgsStyle * defaultStyle()
Returns default application-wide style.
StyleEntity
Enum for Entities involved in a style.
int labelSettingsCount() const
Returns count of label settings in the style.
static QString defaultStylePath()
Returns the path to default style (works as a starting point).
bool isFavorite(StyleEntity type, const QString &name)
Returns true if the symbol with matching type and name is marked as a favorite.
QString errorMessage() const
Returns the most recent error message encountered by the database.
QgsStyle::StyleEntity type() const override
Returns the type of style entity.
int symbolCount()
Returns count of symbols in style.
bool renameSymbol(const QString &oldName, const QString &newName)
Renames a symbol from oldName to newName.
QStringList textFormatNames() const
Returns a list of names of text formats in the style.
QgsPalLayerSettings labelSettings(const QString &name) const
Returns the label settings with the specified name.
void rampRemoved(const QString &name)
Emitted whenever a color ramp has been removed from the style and the database has been updated as a ...
QString tag(int id) const
Returns the tag name for the given id.
void labelSettingsRemoved(const QString &name)
Emitted whenever label settings have been removed from the style and the database has been updated as...
bool importXml(const QString &filename)
Imports the symbols and colorramps into the default style database from the given XML file...
const QgsSymbol * symbolRef(const QString &name) const
Returns a const pointer to a symbol (doesn't create new instance)
static QDomElement saveSymbols(QgsSymbolMap &symbols, const QString &tagName, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a collection of symbols to XML with specified tagName for the top-level element.
QStringList labelSettingsNames() const
Returns a list of names of label settings in the style.
bool removeFavorite(StyleEntity type, const QString &name)
Removes the specified symbol from favorites.
QDomElement writeXml(QDomDocument &doc, const QgsReadWriteContext &context) const
Write settings into a DOM element.
int textFormatId(const QString &name)
Returns the ID in the style database for the given text format by name.
bool remove(StyleEntity type, int id)
Removes the specified entity from the db.
QStringList findSymbols(StyleEntity type, const QString &qword)
Returns the names of the symbols which have a matching 'substring' in its definition.
void groupsModified()
Emitted every time a tag or smartgroup has been added, removed, or renamed.
QgsStyle()=default
Constructor for QgsStyle.
int addTag(const QString &tagName)
Adds a new tag and returns the tag's id.
static void cleanDefaultStyle()
Deletes the default style. Only to be used by QgsApplication::exitQgis()
QString columnAsText(int column) const
Returns the column value from the current statement row as a string.
static QgsColorRamp * loadColorRamp(QDomElement &element)
Creates a color ramp from the settings encoded in an XML element.
bool createMemoryDatabase()
Creates a temporary memory database.
QString smartgroupOperator(int id)
Returns the operator for the smartgroup clumsy implementation TODO create a class for smartgroups...
static bool isXmlStyleFile(const QString &path)
Tests if the file at path is a QGIS style XML file.
sqlite3_statement_unique_ptr prepare(const QString &sql, int &resultCode) const
Prepares a sql statement, returning the result.
void symbolRenamed(const QString &oldName, const QString &newName)
Emitted whenever a symbol has been renamed from oldName to newName.
static QgsSymbolMap loadSymbols(QDomElement &element, const QgsReadWriteContext &context)
Reads a collection of symbols from XML and returns them in a map. Caller is responsible for deleting ...
int open(const QString &path)
Opens the database at the specified file path.
void labelSettingsChanged(const QString &name)
Emitted whenever a label setting's definition is changed.
QgsTextFormat textFormat(const QString &name) const
Returns the text format with the specified name.
void textFormatRenamed(const QString &oldName, const QString &newName)
Emitted whenever a text format has been renamed from oldName to newName.
QDomElement writeXml(QDomDocument &doc, const QgsReadWriteContext &context) const
Write settings into a DOM element.
void favoritedChanged(QgsStyle::StyleEntity entity, const QString &name, bool isFavorite)
Emitted whenever an entity is either favorited or un-favorited.
QgsSmartConditionMap smartgroup(int id)
Returns the QgsSmartConditionMap for the given id.
void symbolRemoved(const QString &name)
Emitted whenever a symbol has been removed from the style and the database has been updated as a resu...
QStringList symbolsOfSmartgroup(StyleEntity type, int id)
Returns the symbols for the smartgroup.
int smartgroupId(const QString &smartgroup)
Returns the DB id for the given smartgroup name.
int tagId(const QString &tag)
Returns the DB id for the given tag name.
QgsStyle::StyleEntity type() const override
Returns the type of style entity.
GeometryType
The geometry types are used to group QgsWkbTypes::Type in a coarse way.
void readXml(const QDomElement &elem, const QgsReadWriteContext &context)
Read settings from a DOM element.
bool saveTextFormat(const QString &name, const QgsTextFormat &format, bool favorite, const QStringList &tags)
Adds a text format to the database.
bool addSymbol(const QString &name, QgsSymbol *symbol, bool update=false)
Adds a symbol to style and takes symbol's ownership.
bool removeTextFormat(const QString &name)
Removes a text format from the style.
QStringList tags() const
Returns a list of all tags in the style database.
void rampRenamed(const QString &oldName, const QString &newName)
Emitted whenever a color ramp has been renamed from oldName to newName.
virtual QgsStyle::StyleEntity type() const =0
Returns the type of style entity.
void textFormatChanged(const QString &name)
Emitted whenever a text format's definition is changed.
int addSmartgroup(const QString &name, const QString &op, const QgsSmartConditionMap &conditions)
Adds a new smartgroup to the database and returns the id.
Text format definition (as XML)
void symbolChanged(const QString &name)
Emitted whenever a symbol's definition is changed.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
bool createDatabase(const QString &filename)
Creates an on-disk database.
virtual QgsSymbol * clone() const =0
Returns a deep copy of this symbol.
int colorrampId(const QString &name)
Returns the id in the style database for the given colorramp name returns 0 if not found...
int symbolId(const QString &name)
Returns the id in the style database for the given symbol name returns 0 if not found.
QStringList colorRampNames() const
Returns a list of names of color ramps.
QMap< QString, QgsSymbol *> QgsSymbolMap
QgsStyle::StyleEntity type() const override
Returns the type of style entity.
bool renameLabelSettings(const QString &oldName, const QString &newName)
Changes a label setting's name.
bool renameColorRamp(const QString &oldName, const QString &newName)
Changes ramp's name.
QgsWkbTypes::GeometryType labelSettingsLayerType(const QString &name) const
Returns the layer geometry type corresponding to the label settings with the specified name...
int colorRampCount()
Returns count of color ramps.
void labelSettingsRenamed(const QString &oldName, const QString &newName)
Emitted whenever label settings have been renamed from oldName to newName.
QString QgsSqlite3Mprintf(const char *format,...)
Wraps sqlite3_mprintf() by automatically freeing the memory.
void labelSettingsAdded(const QString &name)
Emitted whenever label settings have been added to the style and the database has been updated as a r...
QgsSymbol * symbol(const QString &name)
Returns a NEW copy of symbol.
bool saveSymbol(const QString &name, QgsSymbol *symbol, bool favorite, const QStringList &tags)
Adds the symbol to the DB with the tags.
bool removeSymbol(const QString &name)
Removes symbol from style (and delete it)
Container for all settings relating to text rendering.
bool saveLabelSettings(const QString &name, const QgsPalLayerSettings &settings, bool favorite, const QStringList &tags)
Adds label settings to the database.
bool addFavorite(StyleEntity type, const QString &name)
Adds the specified symbol to favorites.
Label settings definition (as XML)
bool removeLabelSettings(const QString &name)
Removes label settings from the style.
bool renameTextFormat(const QString &oldName, const QString &newName)
Changes a text format's name.
bool detagSymbol(StyleEntity type, const QString &symbol, const QStringList &tags)
Detags the symbol with the given list.
QStringList symbolsOfFavorite(StyleEntity type) const
Returns the symbol names which are flagged as favorite.
Color ramp definition (as XML)
QMultiMap< QString, QString > QgsSmartConditionMap
A multimap to hold the smart group conditions as constraint and parameter pairs.
QgsStyle::StyleEntity type() const override
Returns the type of style entity.
QgsSymbolGroupMap smartgroupsListMap()
Returns the smart groups map with id as key and name as value.
QStringList smartgroupNames() const
Returns the smart groups list.
QStringList symbolNames() const
Returns a list of names of symbols.