47#include <QDomDocument>
50#include <QDomNodeList>
56#include "moc_qgsstyle.cpp"
58using namespace Qt::StringLiterals;
60#define STYLE_CURRENT_VERSION "2"
95QgsStyle *QgsStyle::sDefaultStyle =
nullptr;
101 simpleMarker->setStrokeWidth( 0.4 );
102 mPatchMarkerSymbol = std::make_unique< QgsMarkerSymbol >(
QgsSymbolLayerList() << simpleMarker.release() );
104 auto simpleLine = std::make_unique< QgsSimpleLineSymbolLayer >( QColor( 84, 176, 74 ), 0.6 );
105 mPatchLineSymbol = std::make_unique< QgsLineSymbol >(
QgsSymbolLayerList() << simpleLine.release() );
107 auto gradientFill = std::make_unique< QgsGradientFillSymbolLayer >( QColor( 66, 150, 63 ), QColor( 84, 176, 74 ) );
108 auto simpleOutline = std::make_unique< QgsSimpleLineSymbolLayer >( QColor( 56, 128, 54 ), 0.26 );
109 mPatchFillSymbol = std::make_unique< QgsFillSymbol >(
QgsSymbolLayerList() << gradientFill.release() << simpleOutline.release() );
130 switch ( entity->
type() )
166 static QString sStyleFilename;
167 if ( !sDefaultStyle )
173 if ( !QFile::exists( sStyleFilename ) )
176 sDefaultStyle->createDatabase( sStyleFilename );
181 sDefaultStyle->createStyleMetadataTableIfNeeded();
188 sDefaultStyle->mInitialized =
false;
191 sDefaultStyle->initializeDefaultStyle( sStyleFilename );
194 sDefaultStyle->setName( QObject::tr(
"Default" ) );
196 else if ( initialize && !sDefaultStyle->mInitialized )
199 sDefaultStyle->initializeDefaultStyle( sStyleFilename );
201 return sDefaultStyle;
204void QgsStyle::initializeDefaultStyle(
const QString &filename )
206 Q_ASSERT(
this == sDefaultStyle );
207 if (
this != sDefaultStyle )
223 delete sDefaultStyle;
224 sDefaultStyle =
nullptr;
229 qDeleteAll( mSymbols );
230 qDeleteAll( mColorRamps );
231 qDeleteAll( m3dSymbols );
232 qDeleteAll( mMaterialSettings );
236 mTextFormats.clear();
238 mMaterialSettings.clear();
241 mCachedFavorites.clear();
250 auto it = mSymbols.constFind(
name );
251 if ( it != mSymbols.constEnd() )
272 QDomDocument doc( u
"dummy"_s );
274 if ( symEl.isNull() )
281 QTextStream stream( &xmlArray );
282 symEl.save( stream, 4 );
283 QString query =
qgs_sqlite3_mprintf(
"INSERT INTO symbol VALUES (NULL, '%q', '%q', %d);",
name.toUtf8().constData(), xmlArray.constData(), ( favorite ? 1 : 0 ) );
285 if ( !runEmptyQuery( query ) )
287 QgsDebugError( u
"Couldn't insert symbol into the database!"_s );
347 return std::unique_ptr<QgsSymbol>( newSymbol );
352 return mSymbols.value(
name );
357 return static_cast< int >( mSymbols.count() );
362 return mSymbols.keys();
371 auto it = mColorRamps.constFind(
name );
372 if ( it != mColorRamps.constEnd() )
393 auto it = mTextFormats.find(
name );
394 if ( it != mTextFormats.end() )
397 mTextFormats.erase( it );
398 mTextFormats.insert(
name, format );
404 mTextFormats.insert(
name, format );
415 auto it = mLabelSettings.find(
name );
416 if ( it != mLabelSettings.end() )
419 mLabelSettings.erase( it );
420 mLabelSettings.insert(
name, settings );
426 mLabelSettings.insert(
name, settings );
437 auto it = mLegendPatchShapes.find(
name );
438 if ( it != mLegendPatchShapes.end() )
441 mLegendPatchShapes.erase( it );
442 mLegendPatchShapes.insert(
name, shape );
448 mLegendPatchShapes.insert(
name, shape );
459 auto it = m3dSymbols.constFind(
name );
460 if ( it != m3dSymbols.constEnd() )
481 auto it = mMaterialSettings.constFind(
name );
482 if ( it != mMaterialSettings.constEnd() )
486 mMaterialSettings.insert(
name, settings );
492 mMaterialSettings.insert(
name, settings );
503 QDomDocument doc( u
"dummy"_s );
506 if ( rampEl.isNull() )
508 QgsDebugError( u
"Couldn't convert color ramp to valid XML!"_s );
513 QTextStream stream( &xmlArray );
514 rampEl.save( stream, 4 );
515 QString query =
qgs_sqlite3_mprintf(
"INSERT INTO colorramp VALUES (NULL, '%q', '%q', %d);",
name.toUtf8().constData(), xmlArray.constData(), ( favorite ? 1 : 0 ) );
516 if ( !runEmptyQuery( query ) )
518 QgsDebugError( u
"Couldn't insert colorramp into the database!"_s );
540 return std::unique_ptr<QgsColorRamp>( ramp ? ramp->
clone() :
nullptr );
550 return static_cast< int >( mColorRamps.count() );
555 return mColorRamps.keys();
558void QgsStyle::handleDeferred3DSymbolCreation()
560 for (
auto it = mDeferred3DsymbolElements.constBegin(); it != mDeferred3DsymbolElements.constEnd(); ++it )
562 const QString symbolType = it.value().attribute( u
"type"_s );
576 mDeferred3DsymbolElements.clear();
579bool QgsStyle::openDatabase(
const QString &filename )
581 int rc = mCurrentDB.open( filename );
584 mErrorString = u
"Couldn't open the style database: %1"_s.arg( mCurrentDB.errorMessage() );
593 mErrorString.clear();
594 if ( !openDatabase( filename ) )
596 mErrorString = u
"Unable to create database"_s;
608 mErrorString.clear();
609 if ( !openDatabase( u
":memory:"_s ) )
611 mErrorString = u
"Unable to create temporary memory database"_s;
624 "CREATE TABLE symbol("
625 "id INTEGER PRIMARY KEY,"
629 "CREATE TABLE colorramp("
630 "id INTEGER PRIMARY KEY,"
634 "CREATE TABLE textformat("
635 "id INTEGER PRIMARY KEY,"
639 "CREATE TABLE labelsettings("
640 "id INTEGER PRIMARY KEY,"
644 "CREATE TABLE legendpatchshapes("
645 "id INTEGER PRIMARY KEY,"
649 "CREATE TABLE symbol3d("
650 "id INTEGER PRIMARY KEY,"
654 "CREATE TABLE materialsettings("
655 "id INTEGER PRIMARY KEY,"
660 "id INTEGER PRIMARY KEY,"
662 "CREATE TABLE tagmap("
663 "tag_id INTEGER NOT NULL,"
664 "symbol_id INTEGER);"
665 "CREATE TABLE ctagmap("
666 "tag_id INTEGER NOT NULL,"
667 "colorramp_id INTEGER);"
668 "CREATE TABLE tftagmap("
669 "tag_id INTEGER NOT NULL,"
670 "textformat_id INTEGER);"
671 "CREATE TABLE lstagmap("
672 "tag_id INTEGER NOT NULL,"
673 "labelsettings_id INTEGER);"
674 "CREATE TABLE lpstagmap("
675 "tag_id INTEGER NOT NULL,"
676 "legendpatchshape_id INTEGER);"
677 "CREATE TABLE symbol3dtagmap("
678 "tag_id INTEGER NOT NULL,"
679 "symbol3d_id INTEGER);"
680 "CREATE TABLE materialsettingstagmap("
681 "tag_id INTEGER NOT NULL,"
682 "materialsettings_id INTEGER);"
683 "CREATE TABLE smartgroup("
684 "id INTEGER PRIMARY KEY,"
688 runEmptyQuery( query );
693 mErrorString.clear();
696 if ( !openDatabase( filename ) )
698 mErrorString = u
"Unable to open database file specified"_s;
704 QString query =
qgs_sqlite3_mprintf(
"SELECT name FROM sqlite_master WHERE name='textformat'" );
707 statement = mCurrentDB.prepare( query, rc );
708 if ( rc != SQLITE_OK || sqlite3_step( statement.get() ) != SQLITE_ROW )
711 "CREATE TABLE textformat("
712 "id INTEGER PRIMARY KEY,"
716 "CREATE TABLE tftagmap("
717 "tag_id INTEGER NOT NULL,"
718 "textformat_id INTEGER);"
720 runEmptyQuery( query );
723 query =
qgs_sqlite3_mprintf(
"SELECT name FROM sqlite_master WHERE name='labelsettings'" );
724 statement = mCurrentDB.prepare( query, rc );
725 if ( rc != SQLITE_OK || sqlite3_step( statement.get() ) != SQLITE_ROW )
728 "CREATE TABLE labelsettings("
729 "id INTEGER PRIMARY KEY,"
733 "CREATE TABLE lstagmap("
734 "tag_id INTEGER NOT NULL,"
735 "labelsettings_id INTEGER);"
737 runEmptyQuery( query );
740 query =
qgs_sqlite3_mprintf(
"SELECT name FROM sqlite_master WHERE name='legendpatchshapes'" );
741 statement = mCurrentDB.prepare( query, rc );
742 if ( rc != SQLITE_OK || sqlite3_step( statement.get() ) != SQLITE_ROW )
745 "CREATE TABLE legendpatchshapes("
746 "id INTEGER PRIMARY KEY,"
750 "CREATE TABLE lpstagmap("
751 "tag_id INTEGER NOT NULL,"
752 "legendpatchshape_id INTEGER);"
754 runEmptyQuery( query );
758 statement = mCurrentDB.prepare( query, rc );
759 if ( rc != SQLITE_OK || sqlite3_step( statement.get() ) != SQLITE_ROW )
762 "CREATE TABLE symbol3d("
763 "id INTEGER PRIMARY KEY,"
767 "CREATE TABLE symbol3dtagmap("
768 "tag_id INTEGER NOT NULL,"
769 "symbol3d_id INTEGER);"
771 runEmptyQuery( query );
775 query =
qgs_sqlite3_mprintf(
"SELECT name FROM sqlite_master WHERE name='materialsettings'" );
776 statement = mCurrentDB.prepare( query, rc );
777 if ( rc != SQLITE_OK || sqlite3_step( statement.get() ) != SQLITE_ROW )
780 "CREATE TABLE materialsettings("
781 "id INTEGER PRIMARY KEY,"
785 "CREATE TABLE materialsettingstagmap("
786 "tag_id INTEGER NOT NULL,"
787 "materialsettings_id INTEGER);"
789 runEmptyQuery( query );
794 "UPDATE symbol SET favorite=0 WHERE favorite IS NULL;"
795 "UPDATE colorramp SET favorite=0 WHERE favorite IS NULL;"
796 "UPDATE textformat SET favorite=0 WHERE favorite IS NULL;"
797 "UPDATE labelsettings SET favorite=0 WHERE favorite IS NULL;"
798 "UPDATE legendpatchshapes SET favorite=0 WHERE favorite IS NULL;"
799 "UPDATE symbol3d SET favorite=0 WHERE favorite IS NULL;"
800 "UPDATE materialsettings SET favorite=0 WHERE favorite IS NULL;"
802 runEmptyQuery( query );
808 statement = mCurrentDB.prepare( query, rc );
810 while ( rc == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
816 if ( !doc.setContent( xmlstring ) )
822 QDomElement symElement = doc.documentElement();
825 mSymbols.insert( symbolName,
symbol.release() );
832 statement = mCurrentDB.prepare( query, rc );
833 while ( rc == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
839 if ( !doc.setContent( xmlstring ) )
844 QDomElement rampElement = doc.documentElement();
847 mColorRamps.insert( rampName, ramp.release() );
854 statement = mCurrentDB.prepare( query, rc );
855 while ( rc == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
861 if ( !doc.setContent( xmlstring ) )
866 QDomElement formatElement = doc.documentElement();
869 mTextFormats.insert( formatName, format );
876 statement = mCurrentDB.prepare( query, rc );
877 while ( rc == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
883 if ( !doc.setContent( xmlstring ) )
885 QgsDebugError(
"Cannot open label settings " + settingsName );
888 QDomElement settingsElement = doc.documentElement();
891 mLabelSettings.insert( settingsName, settings );
898 statement = mCurrentDB.prepare( query, rc );
899 while ( rc == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
905 if ( !doc.setContent( xmlstring ) )
907 QgsDebugError(
"Cannot open legend patch shape " + settingsName );
910 QDomElement settingsElement = doc.documentElement();
913 mLegendPatchShapes.insert( settingsName, shape );
920 statement = mCurrentDB.prepare( query, rc );
924 while ( rc == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
930 if ( !doc.setContent( xmlstring ) )
935 QDomElement settingsElement = doc.documentElement();
937 if ( !registry3dPopulated )
939 mDeferred3DsymbolElements.insert( settingsName, settingsElement );
943 const QString symbolType = settingsElement.attribute( u
"type"_s );
948 m3dSymbols.insert( settingsName,
symbol.release() );
962 statement = mCurrentDB.prepare( query, rc );
964 while ( rc == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
970 if ( !doc.setContent( xmlstring ) )
972 QgsDebugError(
"Cannot open material settings " + settingsName );
975 QDomElement settingsElement = doc.documentElement();
977 const QString materialType = settingsElement.attribute( u
"type"_s );
982 mMaterialSettings.insert( settingsName, settings.release() );
986 QgsDebugError(
"Cannot open material settings " + settingsName );
992 mFileName = filename;
993 createStyleMetadataTableIfNeeded();
999 mErrorString.clear();
1001 if ( !filename.isEmpty() )
1002 mFileName = filename;
1009 mFileName = filename;
1014 if ( mSymbols.contains( newName ) )
1024 mSymbols.insert( newName,
symbol );
1032 int symbolid =
symbolId( oldName );
1035 QgsDebugError( u
"No such symbol for tagging in database: "_s + oldName );
1054 if ( mColorRamps.contains( newName ) )
1056 QgsDebugError( u
"Color ramp of new name already exists."_s );
1064 mColorRamps.insert( newName, ramp );
1070 QString query =
qgs_sqlite3_mprintf(
"SELECT id FROM colorramp WHERE name='%q'", oldName.toUtf8().constData() );
1072 statement = mCurrentDB.prepare( query, nErr );
1073 if ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
1075 rampid = sqlite3_column_int( statement.get(), 0 );
1090 QDomDocument doc( u
"dummy"_s );
1093 if ( formatElem.isNull() )
1095 QgsDebugError( u
"Couldn't convert text format to valid XML!"_s );
1099 QByteArray xmlArray;
1100 QTextStream stream( &xmlArray );
1101 formatElem.save( stream, 4 );
1102 QString query =
qgs_sqlite3_mprintf(
"INSERT INTO textformat VALUES (NULL, '%q', '%q', %d);",
name.toUtf8().constData(), xmlArray.constData(), ( favorite ? 1 : 0 ) );
1103 if ( !runEmptyQuery( query ) )
1105 QgsDebugError( u
"Couldn't insert text format into the database!"_s );
1126 if ( mTextFormats.contains( newName ) )
1128 QgsDebugError( u
"Text format of new name already exists."_s );
1132 if ( !mTextFormats.contains( oldName ) )
1136 mTextFormats.insert( newName, format );
1142 QString query =
qgs_sqlite3_mprintf(
"SELECT id FROM textformat WHERE name='%q'", oldName.toUtf8().constData() );
1144 statement = mCurrentDB.prepare( query, nErr );
1145 if ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
1147 textFormatId = sqlite3_column_int( statement.get(), 0 );
1162 QDomDocument doc( u
"dummy"_s );
1165 if ( settingsElem.isNull() )
1167 QgsDebugError( u
"Couldn't convert label settings to valid XML!"_s );
1171 QByteArray xmlArray;
1172 QTextStream stream( &xmlArray );
1173 settingsElem.save( stream, 4 );
1174 QString query =
qgs_sqlite3_mprintf(
"INSERT INTO labelsettings VALUES (NULL, '%q', '%q', %d);",
name.toUtf8().constData(), xmlArray.constData(), ( favorite ? 1 : 0 ) );
1175 if ( !runEmptyQuery( query ) )
1177 QgsDebugError( u
"Couldn't insert label settings into the database!"_s );
1198 if ( mLabelSettings.contains( newName ) )
1200 QgsDebugError( u
"Label settings of new name already exists."_s );
1204 if ( !mLabelSettings.contains( oldName ) )
1208 mLabelSettings.insert( newName, settings );
1214 QString query =
qgs_sqlite3_mprintf(
"SELECT id FROM labelsettings WHERE name='%q'", oldName.toUtf8().constData() );
1216 statement = mCurrentDB.prepare( query, nErr );
1217 if ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
1234 QDomDocument doc( u
"dummy"_s );
1235 QDomElement shapeElem = doc.createElement( u
"shape"_s );
1238 QByteArray xmlArray;
1239 QTextStream stream( &xmlArray );
1240 shapeElem.save( stream, 4 );
1241 QString query =
qgs_sqlite3_mprintf(
"INSERT INTO legendpatchshapes VALUES (NULL, '%q', '%q', %d);",
name.toUtf8().constData(), xmlArray.constData(), ( favorite ? 1 : 0 ) );
1242 if ( !runEmptyQuery( query ) )
1244 QgsDebugError( u
"Couldn't insert legend patch shape into the database!"_s );
1259 if ( mLegendPatchShapes.contains( newName ) )
1261 QgsDebugError( u
"Legend patch shape of new name already exists."_s );
1265 if ( !mLegendPatchShapes.contains( oldName ) )
1269 mLegendPatchShapes.insert( newName, shape );
1275 QString query =
qgs_sqlite3_mprintf(
"SELECT id FROM legendpatchshapes WHERE name='%q'", oldName.toUtf8().constData() );
1277 statement = mCurrentDB.prepare( query, nErr );
1278 if ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
1296 auto it = mDefaultPatchCache[
static_cast< int >( type )].constFind( size );
1297 if ( it != mDefaultPatchCache[
static_cast< int >( type )].constEnd() )
1304 geom =
QgsGeometry( std::make_unique< QgsPoint >(
static_cast< int >( size.width() ) / 2,
static_cast< int >( size.height() ) / 2 ) );
1311 double y =
static_cast< int >( size.height() ) / 2 + 0.5;
1312 geom =
QgsGeometry( std::make_unique< QgsLineString >( ( QVector< double >() << 0 << size.width() ), ( QVector< double >() << y << y ) ) );
1320 QVector< double >() << 0 <<
static_cast< int >( size.width() ) <<
static_cast< int >( size.width() ) << 0 << 0,
1321 QVector< double >() <<
static_cast< int >( size.height() ) <<
static_cast< int >( size.height() ) << 0 << 0 <<
static_cast< int >( size.height() )
1332 mDefaultPatchCache[
static_cast< int >( type )][size] = res;
1339 return QList<QList<QPolygonF> >();
1341 auto it = mDefaultPatchQPolygonFCache[
static_cast< int >( type )].constFind( size );
1342 if ( it != mDefaultPatchQPolygonFCache[
static_cast< int >( type )].constEnd() )
1346 mDefaultPatchQPolygonFCache[
static_cast< int >( type )][size] = res;
1372 QDomDocument doc( u
"dummy"_s );
1373 QDomElement elem = doc.createElement( u
"symbol"_s );
1374 elem.setAttribute( u
"type"_s,
symbol->type() );
1377 QByteArray xmlArray;
1378 QTextStream stream( &xmlArray );
1379 elem.save( stream, 4 );
1380 QString query =
qgs_sqlite3_mprintf(
"INSERT INTO symbol3d VALUES (NULL, '%q', '%q', %d);",
name.toUtf8().constData(), xmlArray.constData(), ( favorite ? 1 : 0 ) );
1381 if ( !runEmptyQuery( query ) )
1383 QgsDebugError( u
"Couldn't insert 3d symbol into the database!"_s );
1398 if ( m3dSymbols.contains( newName ) )
1400 QgsDebugError( u
"3d symbol of new name already exists."_s );
1404 if ( !m3dSymbols.contains( oldName ) )
1408 m3dSymbols.insert( newName,
symbol );
1414 QString query =
qgs_sqlite3_mprintf(
"SELECT id FROM symbol3d WHERE name='%q'", oldName.toUtf8().constData() );
1416 statement = mCurrentDB.prepare( query, nErr );
1417 if ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
1432 return m3dSymbols.keys();
1438 QDomDocument doc( u
"dummy"_s );
1439 QDomElement elem = doc.createElement( u
"settings"_s );
1440 elem.setAttribute( u
"type"_s, settings->
type() );
1443 QByteArray xmlArray;
1444 QTextStream stream( &xmlArray );
1445 elem.save( stream, 4 );
1446 QString query =
qgs_sqlite3_mprintf(
"INSERT INTO materialsettings VALUES (NULL, '%q', '%q', %d);",
name.toUtf8().constData(), xmlArray.constData(), ( favorite ? 1 : 0 ) );
1447 if ( !runEmptyQuery( query ) )
1449 QgsDebugError( u
"Couldn't insert material settings into the database!"_s );
1464 if ( mMaterialSettings.contains( newName ) )
1466 QgsDebugError( u
"material settings of new name already exists."_s );
1470 if ( !mMaterialSettings.contains( oldName ) )
1472 std::unique_ptr< QgsAbstractMaterialSettings > settings( mMaterialSettings.take( oldName ) );
1474 mMaterialSettings.insert( newName, settings.release() );
1478 int materialSettingsId = 0;
1480 QString query =
qgs_sqlite3_mprintf(
"SELECT id FROM materialsettings WHERE name='%q'", oldName.toUtf8().constData() );
1482 statement = mCurrentDB.prepare( query, nErr );
1483 if ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
1485 materialSettingsId = sqlite3_column_int( statement.get(), 0 );
1498 return mMaterialSettings.keys();
1503 return static_cast< int >( mMaterialSettings.size() );
1508 auto it = mMaterialSettings.constFind(
name );
1509 if ( it != mMaterialSettings.constEnd() )
1510 return std::unique_ptr< QgsAbstractMaterialSettings >( it.value()->clone() );
1518 QgsDebugError( u
"Cannot Open database for getting favorite symbols"_s );
1519 return QStringList();
1528 return QStringList();
1531 query =
qgs_sqlite3_mprintf( u
"SELECT name FROM %1 WHERE favorite=1"_s.arg( entityTableName( type ) ).toLocal8Bit().data() );
1537 statement = mCurrentDB.prepare( query, nErr );
1539 QStringList symbols;
1540 while ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
1552 QgsDebugError( u
"Cannot open database to get symbols of tagid %1"_s.arg( tagid ) );
1553 return QStringList();
1562 return QStringList();
1565 subquery =
qgs_sqlite3_mprintf( u
"SELECT %1 FROM %2 WHERE tag_id=%d"_s.arg( tagmapEntityIdFieldName( type ), tagmapTableName( type ) ).toLocal8Bit().data(), tagid );
1571 statement = mCurrentDB.prepare( subquery, nErr );
1574 QStringList symbols;
1575 while ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
1577 int id = sqlite3_column_int( statement.get(), 0 );
1579 const QString query =
qgs_sqlite3_mprintf( u
"SELECT name FROM %1 WHERE id=%d"_s.arg( entityTableName( type ) ).toLocal8Bit().data(),
id );
1583 statement2 = mCurrentDB.prepare( query, rc );
1584 while ( rc == SQLITE_OK && sqlite3_step( statement2.get() ) == SQLITE_ROW )
1599 QString query =
qgs_sqlite3_mprintf(
"INSERT INTO tag VALUES (NULL, '%q')", tagname.toUtf8().constData() );
1601 statement = mCurrentDB.prepare( query, nErr );
1602 if ( nErr == SQLITE_OK )
1603 ( void ) sqlite3_step( statement.get() );
1609 return static_cast< int >( sqlite3_last_insert_rowid( mCurrentDB.get() ) );
1615 return QStringList();
1621 statement = mCurrentDB.prepare( query, nError );
1623 QStringList tagList;
1624 while ( nError == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
1634 const QString query =
qgs_sqlite3_mprintf( u
"UPDATE %1 SET name='%q' WHERE id=%d"_s.arg( entityTableName( type ) ).toLocal8Bit().data(), newName.toUtf8().constData(),
id );
1636 const bool result = runEmptyQuery( query );
1639 mErrorString = u
"Could not rename!"_s;
1643 mCachedTags.clear();
1644 mCachedFavorites.clear();
1669 bool groupRemoved =
false;
1674 query =
qgs_sqlite3_mprintf(
"DELETE FROM tag WHERE id=%d; DELETE FROM tagmap WHERE tag_id=%d",
id,
id );
1675 groupRemoved =
true;
1679 groupRemoved =
true;
1684 =
qgs_sqlite3_mprintf( u
"DELETE FROM %1 WHERE id=%d; DELETE FROM %2 WHERE %3=%d"_s.arg( entityTableName( type ), tagmapTableName( type ), tagmapEntityIdFieldName( type ) ).toLocal8Bit().data(),
id,
id );
1688 bool result =
false;
1689 if ( !runEmptyQuery( query ) )
1695 mCachedTags.clear();
1696 mCachedFavorites.clear();
1719 std::unique_ptr< QgsSymbol >
symbol( mSymbols.take(
name ) );
1728 std::unique_ptr< QgsAbstract3DSymbol >
symbol( m3dSymbols.take(
name ) );
1737 std::unique_ptr< QgsAbstractMaterialSettings > settings( mMaterialSettings.take(
name ) );
1746 std::unique_ptr< QgsColorRamp > ramp( mColorRamps.take(
name ) );
1754 auto it = mTextFormats.find(
name );
1755 if ( it == mTextFormats.end() )
1758 mTextFormats.erase( it );
1764 auto it = mLabelSettings.find(
name );
1765 if ( it == mLabelSettings.end() )
1768 mLabelSettings.erase( it );
1774 auto it = mLegendPatchShapes.find(
name );
1775 if ( it == mLegendPatchShapes.end() )
1778 mLegendPatchShapes.erase( it );
1785 QgsDebugError( u
"Sorry! Cannot open database to modify."_s );
1795 const bool result =
remove( type,
id );
1798 mCachedTags[type].remove(
name );
1799 mCachedFavorites[type].remove(
name );
1828bool QgsStyle::runEmptyQuery(
const QString &query )
1833 char *zErr =
nullptr;
1834 int nErr = sqlite3_exec( mCurrentDB.get(), query.toUtf8().constData(),
nullptr,
nullptr, &zErr );
1836 if ( nErr != SQLITE_OK )
1839 sqlite3_free( zErr );
1842 return nErr == SQLITE_OK;
1853 QgsDebugError( u
"Wrong entity value. cannot apply group"_s );
1857 query =
qgs_sqlite3_mprintf( u
"UPDATE %1 SET favorite=1 WHERE name='%q'"_s.arg( entityTableName( type ) ).toLocal8Bit().data(),
name.toUtf8().constData() );
1861 const bool res = runEmptyQuery( query );
1871 mCachedFavorites[type].insert(
name,
true );
1888 QgsDebugError( u
"Wrong entity value. cannot apply group"_s );
1892 query =
qgs_sqlite3_mprintf( u
"UPDATE %1 SET favorite=0 WHERE name='%q'"_s.arg( entityTableName( type ) ).toLocal8Bit().data(),
name.toUtf8().constData() );
1896 const bool res = runEmptyQuery( query );
1899 mCachedFavorites[type].insert(
name,
false );
1910 QgsDebugError( u
"Sorry! Cannot open database to search"_s );
1911 return QStringList();
1920 return QStringList();
1923 item = entityTableName( type );
1927 QString query =
qgs_sqlite3_mprintf(
"SELECT name FROM %q WHERE name LIKE '%%%q%%'", item.toUtf8().constData(), qword.toUtf8().constData() );
1931 statement = mCurrentDB.prepare( query, nErr );
1933 QSet< QString > symbols;
1934 while ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
1940 query =
qgs_sqlite3_mprintf(
"SELECT id FROM tag WHERE name LIKE '%%%q%%'", qword.toUtf8().constData() );
1941 statement = mCurrentDB.prepare( query, nErr );
1944 while ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
1949 QString dummy = tagids.join(
", "_L1 );
1950 query =
qgs_sqlite3_mprintf( u
"SELECT %1 FROM %2 WHERE tag_id IN (%q)"_s.arg( tagmapEntityIdFieldName( type ), tagmapTableName( type ) ).toLocal8Bit().data(), dummy.toUtf8().constData() );
1952 statement = mCurrentDB.prepare( query, nErr );
1954 QStringList symbolids;
1955 while ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
1960 dummy = symbolids.join(
", "_L1 );
1961 query =
qgs_sqlite3_mprintf(
"SELECT name FROM %q WHERE id IN (%q)", item.toUtf8().constData(), dummy.toUtf8().constData() );
1962 statement = mCurrentDB.prepare( query, nErr );
1963 while ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
1968 return QStringList( symbols.constBegin(), symbols.constEnd() );
1998 const auto constTags =
tags;
1999 for (
const QString &t : constTags )
2002 if ( !
tag.isEmpty() )
2014 QString query =
qgs_sqlite3_mprintf( u
"INSERT INTO %1 VALUES (%d,%d)"_s.arg( tagmapTableName( type ) ).toLocal8Bit().data(), tagid, symbolid );
2016 char *zErr =
nullptr;
2018 nErr = sqlite3_exec( mCurrentDB.get(), query.toUtf8().constData(),
nullptr,
nullptr, &zErr );
2022 sqlite3_free( zErr );
2028 clearCachedTags( type,
symbol );
2038 QgsDebugError( u
"Sorry! Cannot open database for detagging."_s );
2053 if ( symbolid == 0 )
2058 const auto constTags =
tags;
2059 for (
const QString &
tag : constTags )
2064 statement2 = mCurrentDB.prepare( query, nErr );
2067 if ( nErr == SQLITE_OK && sqlite3_step( statement2.get() ) == SQLITE_ROW )
2069 tagid = sqlite3_column_int( statement2.get(), 0 );
2075 const QString query =
qgs_sqlite3_mprintf( u
"DELETE FROM %1 WHERE tag_id=%d AND %2=%d"_s.arg( tagmapTableName( type ), tagmapEntityIdFieldName( type ) ).toLocal8Bit().data(), tagid, symbolid );
2076 runEmptyQuery( query );
2080 clearCachedTags( type,
symbol );
2093 QgsDebugError( u
"Sorry! Cannot open database for detagging."_s );
2108 if ( symbolid == 0 )
2114 const QString query =
qgs_sqlite3_mprintf( u
"DELETE FROM %1 WHERE %2=%d"_s.arg( tagmapTableName( type ), tagmapEntityIdFieldName( type ) ).toLocal8Bit().data(), symbolid );
2115 runEmptyQuery( query );
2117 clearCachedTags( type,
symbol );
2132 return QStringList();
2136 auto it = mCachedTags[type].constFind(
symbol );
2137 if ( it != mCachedTags[type].constEnd() )
2145 QgsDebugError( u
"Sorry! Cannot open database for getting the tags."_s );
2146 return QStringList();
2151 return QStringList();
2154 const QString query =
qgs_sqlite3_mprintf( u
"SELECT tag_id FROM %1 WHERE %2=%d"_s.arg( tagmapTableName( type ), tagmapEntityIdFieldName( type ) ).toLocal8Bit().data(), symbolid );
2158 statement = mCurrentDB.prepare( query, nErr );
2160 QStringList tagList;
2161 while ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
2163 QString subquery =
qgs_sqlite3_mprintf(
"SELECT name FROM tag WHERE id=%d", sqlite3_column_int( statement.get(), 0 ) );
2167 statement2 = mCurrentDB.prepare( subquery, pErr );
2168 if ( pErr == SQLITE_OK && sqlite3_step( statement2.get() ) == SQLITE_ROW )
2175 mCachedTags[type].insert(
symbol, tagList );
2184 QgsDebugError( u
"Sorry! Cannot open database for getting the tags."_s );
2196 auto it = mCachedFavorites[type].constFind(
name );
2197 if ( it != mCachedFavorites[type].constEnd() )
2203 const QStringList names =
allNames( type );
2204 if ( !names.contains(
name ) )
2210 for (
const QString &n : names )
2212 const bool isFav = favorites.contains( n );
2216 mCachedFavorites[type].insert( n, isFav );
2225 QgsDebugError( u
"Sorry! Cannot open database for getting the tags."_s );
2252 const QString query =
qgs_sqlite3_mprintf( u
"SELECT tag_id FROM %1 WHERE tag_id=%d AND %2=%d"_s.arg( tagmapTableName( type ), tagmapEntityIdFieldName( type ) ).toLocal8Bit().data(), tagid, symbolid );
2256 statement = mCurrentDB.prepare( query, nErr );
2258 return ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW );
2270 statement = mCurrentDB.prepare( query, nError );
2273 if ( nError == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
2281int QgsStyle::getId(
const QString &table,
const QString &name )
2283 QString lowerName(
name.toLower() );
2284 QString query =
qgs_sqlite3_mprintf(
"SELECT id FROM %q WHERE LOWER(name)='%q'", table.toUtf8().constData(), lowerName.toUtf8().constData() );
2288 statement = mCurrentDB.
prepare( query, nErr );
2291 if ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
2293 id = sqlite3_column_int( statement.get(), 0 );
2298 QString query =
qgs_sqlite3_mprintf(
"SELECT id FROM %q WHERE name='%q'", table.toUtf8().constData(),
name.toUtf8().constData() );
2300 sqlite3_statement_unique_ptr statement;
2302 statement = mCurrentDB.prepare( query, nErr );
2303 if ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
2305 id = sqlite3_column_int( statement.get(), 0 );
2312QString QgsStyle::getName(
const QString &table,
int id )
const
2314 QString query =
qgs_sqlite3_mprintf(
"SELECT name FROM %q WHERE id='%q'", table.toUtf8().constData(), QString::number(
id ).toUtf8().constData() );
2316 sqlite3_statement_unique_ptr statement;
2318 statement = mCurrentDB.prepare( query, nErr );
2321 if ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
2331 return getId( u
"symbol"_s,
name );
2336 return getId( entityTableName( type ),
name );
2341 return getId( u
"colorramp"_s,
name );
2346 return mTextFormats.value(
name );
2351 return static_cast< int >( mTextFormats.count() );
2356 return mTextFormats.keys();
2361 return getId( u
"textformat"_s,
name );
2366 return mLabelSettings.value(
name );
2371 return mLegendPatchShapes.value(
name );
2376 return static_cast< int >( mLegendPatchShapes.count() );
2381 auto it = mLegendPatchShapes.constFind(
name );
2382 if ( it == mLegendPatchShapes.constEnd() )
2385 return it.value().symbolType();
2390 auto it = m3dSymbols.constFind(
name );
2391 if ( it != m3dSymbols.constEnd() )
2392 return std::unique_ptr<QgsAbstract3DSymbol>( it.value()->clone() );
2398 return static_cast< int >( m3dSymbols.count() );
2403 auto it = m3dSymbols.constFind(
name );
2404 if ( it == m3dSymbols.constEnd() )
2405 return QList<Qgis::GeometryType>();
2407 return it.value()->compatibleGeometryTypes();
2412 auto it = mLabelSettings.constFind(
name );
2413 if ( it == mLabelSettings.constEnd() )
2416 return it.value().layerType;
2421 return static_cast< int >( mLabelSettings.count() );
2426 return mLabelSettings.keys();
2431 return getId( u
"labelsettings"_s,
name );
2436 return mLegendPatchShapes.keys();
2444 return mPatchMarkerSymbol.get();
2447 return mPatchLineSymbol.get();
2450 return mPatchFillSymbol.get();
2460 return getId( u
"tag"_s,
name );
2465 return getId( u
"smartgroup"_s,
name );
2499 return QStringList();
2504 return addSmartgroup(
name, op, conditions.values( u
"tag"_s ), conditions.values( u
"!tag"_s ), conditions.values( u
"name"_s ), conditions.values( u
"!name"_s ) );
2507int QgsStyle::addSmartgroup(
const QString &
name,
const QString &op,
const QStringList &matchTag,
const QStringList &noMatchTag,
const QStringList &matchName,
const QStringList &noMatchName )
2509 QDomDocument doc( u
"dummy"_s );
2510 QDomElement smartEl = doc.createElement( u
"smartgroup"_s );
2511 smartEl.setAttribute( u
"name"_s,
name );
2512 smartEl.setAttribute( u
"operator"_s, op );
2514 auto addCondition = [&doc, &smartEl](
const QString &constraint,
const QStringList ¶meters ) {
2515 for (
const QString ¶m : parameters )
2517 QDomElement condEl = doc.createElement( u
"condition"_s );
2518 condEl.setAttribute( u
"constraint"_s, constraint );
2519 condEl.setAttribute( u
"param"_s, param );
2520 smartEl.appendChild( condEl );
2523 addCondition( u
"tag"_s, matchTag );
2524 addCondition( u
"!tag"_s, noMatchTag );
2525 addCondition( u
"name"_s, matchName );
2526 addCondition( u
"!name"_s, noMatchName );
2528 QByteArray xmlArray;
2529 QTextStream stream( &xmlArray );
2530 smartEl.save( stream, 4 );
2531 QString query =
qgs_sqlite3_mprintf(
"INSERT INTO smartgroup VALUES (NULL, '%q', '%q')",
name.toUtf8().constData(), xmlArray.constData() );
2533 if ( runEmptyQuery( query ) )
2538 return static_cast< int >( sqlite3_last_insert_rowid( mCurrentDB.get() ) );
2542 QgsDebugError( u
"Couldn't add the smart group into the database!"_s );
2551 QgsDebugError( u
"Cannot open database for listing groups"_s );
2560 statement = mCurrentDB.prepare( query, nError );
2563 while ( nError == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
2576 QgsDebugError( u
"Cannot open database for listing groups"_s );
2577 return QStringList();
2585 statement = mCurrentDB.prepare( query, nError );
2588 while ( nError == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
2598 QStringList symbols;
2604 statement = mCurrentDB.prepare( query, nErr );
2605 if ( !( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW ) )
2607 return QStringList();
2613 if ( !doc.setContent( xmlstr ) )
2615 QgsDebugError( u
"Cannot open smartgroup id: %1"_s.arg(
id ) );
2617 QDomElement smartEl = doc.documentElement();
2618 QString op = smartEl.attribute( u
"operator"_s );
2619 QDomNodeList conditionNodes = smartEl.childNodes();
2621 bool firstSet =
true;
2622 for (
int i = 0; i < conditionNodes.count(); i++ )
2624 QDomElement condEl = conditionNodes.at( i ).toElement();
2625 QString constraint = condEl.attribute( u
"constraint"_s );
2626 QString param = condEl.attribute( u
"param"_s );
2628 QStringList resultNames;
2630 if ( constraint ==
"tag"_L1 )
2634 else if ( constraint ==
"name"_L1 )
2636 resultNames =
allNames( type ).filter( param, Qt::CaseInsensitive );
2638 else if ( constraint ==
"!tag"_L1 )
2642 for (
const QString &
name : unwanted )
2644 resultNames.removeAll(
name );
2647 else if ( constraint ==
"!name"_L1 )
2649 const QStringList all =
allNames( type );
2650 for (
const QString &str : all )
2652 if ( !str.contains( param, Qt::CaseInsensitive ) )
2660 symbols = resultNames;
2665 if ( op ==
"OR"_L1 )
2667 symbols << resultNames;
2669 else if ( op ==
"AND"_L1 )
2671 QStringList dummy = symbols;
2673 for (
const QString &result : std::as_const( resultNames ) )
2675 if ( dummy.contains( result ) )
2684 const QSet< QString > uniqueSet( symbols.constBegin(), symbols.constEnd() );
2685 QStringList unique( uniqueSet.begin(), uniqueSet.end() );
2686 std::sort( unique.begin(), unique.end() );
2694 QgsDebugError( u
"Cannot open database for listing groups"_s );
2704 statement = mCurrentDB.prepare( query, nError );
2705 if ( nError == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
2709 if ( !doc.setContent( xmlstr ) )
2711 QgsDebugError( u
"Cannot open smartgroup id: %1"_s.arg(
id ) );
2714 QDomElement smartEl = doc.documentElement();
2715 QDomNodeList conditionNodes = smartEl.childNodes();
2717 for (
int i = 0; i < conditionNodes.count(); i++ )
2719 QDomElement condEl = conditionNodes.at( i ).toElement();
2720 QString constraint = condEl.attribute( u
"constraint"_s );
2721 QString param = condEl.attribute( u
"param"_s );
2723 condition.insert( constraint, param );
2734 QgsDebugError( u
"Cannot open database for listing groups"_s );
2744 statement = mCurrentDB.prepare( query, nError );
2745 if ( nError == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
2749 if ( !doc.setContent( xmlstr ) )
2751 QgsDebugError( u
"Cannot open smartgroup id: %1"_s.arg(
id ) );
2753 QDomElement smartEl = doc.documentElement();
2754 op = smartEl.attribute( u
"operator"_s );
2762 if ( filename.isEmpty() )
2768 QDomDocument doc( u
"qgis_style"_s );
2769 QDomElement root = doc.createElement( u
"qgis_style"_s );
2771 doc.appendChild( root );
2782 QDomNodeList symbolsList = symbolsElem.elementsByTagName( u
"symbol"_s );
2783 int nbSymbols = symbolsList.count();
2784 for (
int i = 0; i < nbSymbols; ++i )
2786 QDomElement
symbol = symbolsList.at( i ).toElement();
2787 QString
name =
symbol.attribute( u
"name"_s );
2789 if (
tags.count() > 0 )
2791 symbol.setAttribute( u
"tags"_s,
tags.join(
',' ) );
2793 if ( favoriteSymbols.contains(
name ) )
2795 symbol.setAttribute( u
"favorite"_s, u
"1"_s );
2800 QDomElement rampsElem = doc.createElement( u
"colorramps"_s );
2801 for ( QMap<QString, QgsColorRamp *>::const_iterator itr = mColorRamps.constBegin(); itr != mColorRamps.constEnd(); ++itr )
2805 if (
tags.count() > 0 )
2807 rampEl.setAttribute( u
"tags"_s,
tags.join(
',' ) );
2809 if ( favoriteColorramps.contains( itr.key() ) )
2811 rampEl.setAttribute( u
"favorite"_s, u
"1"_s );
2813 rampsElem.appendChild( rampEl );
2817 QDomElement textFormatsElem = doc.createElement( u
"textformats"_s );
2818 for (
auto it = mTextFormats.constBegin(); it != mTextFormats.constEnd(); ++it )
2820 QDomElement textFormatEl = doc.createElement( u
"textformat"_s );
2821 textFormatEl.setAttribute( u
"name"_s, it.key() );
2823 textFormatEl.appendChild( textStyleEl );
2825 if (
tags.count() > 0 )
2827 textFormatEl.setAttribute( u
"tags"_s,
tags.join(
',' ) );
2829 if ( favoriteTextFormats.contains( it.key() ) )
2831 textFormatEl.setAttribute( u
"favorite"_s, u
"1"_s );
2833 textFormatsElem.appendChild( textFormatEl );
2837 QDomElement labelSettingsElem = doc.createElement( u
"labelsettings"_s );
2838 for (
auto it = mLabelSettings.constBegin(); it != mLabelSettings.constEnd(); ++it )
2840 QDomElement labelSettingsEl = doc.createElement( u
"labelsetting"_s );
2841 labelSettingsEl.setAttribute( u
"name"_s, it.key() );
2843 labelSettingsEl.appendChild( defEl );
2845 if (
tags.count() > 0 )
2847 labelSettingsEl.setAttribute( u
"tags"_s,
tags.join(
',' ) );
2849 if ( favoriteTextFormats.contains( it.key() ) )
2851 labelSettingsEl.setAttribute( u
"favorite"_s, u
"1"_s );
2853 labelSettingsElem.appendChild( labelSettingsEl );
2857 QDomElement legendPatchShapesElem = doc.createElement( u
"legendpatchshapes"_s );
2858 for (
auto it = mLegendPatchShapes.constBegin(); it != mLegendPatchShapes.constEnd(); ++it )
2860 QDomElement legendPatchShapeEl = doc.createElement( u
"legendpatchshape"_s );
2861 legendPatchShapeEl.setAttribute( u
"name"_s, it.key() );
2862 QDomElement defEl = doc.createElement( u
"definition"_s );
2864 legendPatchShapeEl.appendChild( defEl );
2866 if (
tags.count() > 0 )
2868 legendPatchShapeEl.setAttribute( u
"tags"_s,
tags.join(
',' ) );
2870 if ( favoriteLegendShapes.contains( it.key() ) )
2872 legendPatchShapeEl.setAttribute( u
"favorite"_s, u
"1"_s );
2874 legendPatchShapesElem.appendChild( legendPatchShapeEl );
2878 QDomElement symbols3DElem = doc.createElement( u
"symbols3d"_s );
2879 for (
auto it = m3dSymbols.constBegin(); it != m3dSymbols.constEnd(); ++it )
2881 QDomElement symbolEl = doc.createElement( u
"symbol3d"_s );
2882 symbolEl.setAttribute( u
"name"_s, it.key() );
2883 QDomElement defEl = doc.createElement( u
"definition"_s );
2884 defEl.setAttribute( u
"type"_s, it.value()->type() );
2886 symbolEl.appendChild( defEl );
2888 if (
tags.count() > 0 )
2890 symbolEl.setAttribute( u
"tags"_s,
tags.join(
',' ) );
2892 if ( favorite3DSymbols.contains( it.key() ) )
2894 symbolEl.setAttribute( u
"favorite"_s, u
"1"_s );
2896 symbols3DElem.appendChild( symbolEl );
2900 QDomElement materialSettingsElem = doc.createElement( u
"materialsettings"_s );
2901 for (
auto it = mMaterialSettings.constBegin(); it != mMaterialSettings.constEnd(); ++it )
2903 QDomElement materialSettingEl = doc.createElement( u
"material"_s );
2904 materialSettingEl.setAttribute( u
"name"_s, it.key() );
2905 QDomElement defEl = doc.createElement( u
"definition"_s );
2907 materialSettingEl.appendChild( defEl );
2909 if (
tags.count() > 0 )
2911 materialSettingEl.setAttribute( u
"tags"_s,
tags.join(
',' ) );
2913 if ( favoriteMaterialSettings.contains( it.key() ) )
2915 materialSettingEl.setAttribute( u
"favorite"_s, u
"1"_s );
2917 materialSettingsElem.appendChild( materialSettingEl );
2919 root.appendChild( symbolsElem );
2920 root.appendChild( rampsElem );
2921 root.appendChild( textFormatsElem );
2922 root.appendChild( labelSettingsElem );
2923 root.appendChild( legendPatchShapesElem );
2924 root.appendChild( symbols3DElem );
2925 root.appendChild( materialSettingsElem );
2928 QFile f( filename );
2929 if ( !f.open( QFile::WriteOnly | QIODevice::Truncate ) )
2931 mErrorString =
"Couldn't open file for writing: " + filename;
2935 QTextStream ts( &f );
2949 mErrorString = QString();
2950 QDomDocument doc( u
"style"_s );
2951 QFile f( filename );
2952 if ( !f.open( QFile::ReadOnly ) )
2954 mErrorString = u
"Unable to open the specified file"_s;
2959 if ( !doc.setContent( &f ) )
2961 mErrorString = u
"Unable to understand the style file: %1"_s.arg( filename );
2968 QDomElement docEl = doc.documentElement();
2969 if ( docEl.tagName() !=
"qgis_style"_L1 )
2971 mErrorString =
"Incorrect root tag in style: " + docEl.tagName();
2975 const QString version = docEl.attribute( u
"version"_s );
2978 mErrorString =
"Unknown style file version: " + version;
2984 QDomElement symbolsElement = docEl.firstChildElement( u
"symbols"_s );
2985 QDomElement e = symbolsElement.firstChildElement();
2989 runEmptyQuery( query );
2994 for ( ; !e.isNull(); e = e.nextSiblingElement() )
2996 const int entityAddedVersion = e.attribute( u
"addedVersion"_s ).toInt();
2997 if ( entityAddedVersion != 0 && sinceVersion != -1 && entityAddedVersion <= sinceVersion )
3003 if ( e.tagName() ==
"symbol"_L1 )
3005 QString
name = e.attribute( u
"name"_s );
3007 if ( e.hasAttribute( u
"tags"_s ) )
3009 tags = e.attribute( u
"tags"_s ).split(
',' );
3011 bool favorite =
false;
3012 if ( e.hasAttribute( u
"favorite"_s ) && e.attribute( u
"favorite"_s ) ==
"1"_L1 )
3020 QgsSymbol *symbolPtr =
symbol.get();
3040 for ( QMap<QString, QgsSymbol *>::iterator it = symbols.begin(); it != symbols.end(); ++it )
3047 QDomElement rampsElement = docEl.firstChildElement( u
"colorramps"_s );
3048 e = rampsElement.firstChildElement();
3049 for ( ; !e.isNull(); e = e.nextSiblingElement() )
3051 const int entityAddedVersion = e.attribute( u
"addedVersion"_s ).toInt();
3052 if ( entityAddedVersion != 0 && sinceVersion != -1 && entityAddedVersion <= sinceVersion )
3058 if ( e.tagName() ==
"colorramp"_L1 )
3060 QString
name = e.attribute( u
"name"_s );
3062 if ( e.hasAttribute( u
"tags"_s ) )
3064 tags = e.attribute( u
"tags"_s ).split(
',' );
3066 bool favorite =
false;
3067 if ( e.hasAttribute( u
"favorite"_s ) && e.attribute( u
"favorite"_s ) ==
"1"_L1 )
3075 QgsColorRamp *rampPtr = ramp.get();
3092 if ( qobject_cast< QGuiApplication * >( QCoreApplication::instance() ) )
3096 const QDomElement textFormatElement = docEl.firstChildElement( u
"textformats"_s );
3097 e = textFormatElement.firstChildElement();
3098 for ( ; !e.isNull(); e = e.nextSiblingElement() )
3100 const int entityAddedVersion = e.attribute( u
"addedVersion"_s ).toInt();
3101 if ( entityAddedVersion != 0 && sinceVersion != -1 && entityAddedVersion <= sinceVersion )
3107 if ( e.tagName() ==
"textformat"_L1 )
3109 QString
name = e.attribute( u
"name"_s );
3111 if ( e.hasAttribute( u
"tags"_s ) )
3113 tags = e.attribute( u
"tags"_s ).split(
',' );
3115 bool favorite =
false;
3116 if ( e.hasAttribute( u
"favorite"_s ) && e.attribute( u
"favorite"_s ) ==
"1"_L1 )
3121 QgsTextFormat format;
3122 const QDomElement styleElem = e.firstChildElement();
3123 format.
readXml( styleElem, QgsReadWriteContext() );
3140 const QDomElement labelSettingsElement = docEl.firstChildElement( u
"labelsettings"_s );
3141 e = labelSettingsElement.firstChildElement();
3142 for ( ; !e.isNull(); e = e.nextSiblingElement() )
3144 const int entityAddedVersion = e.attribute( u
"addedVersion"_s ).toInt();
3145 if ( entityAddedVersion != 0 && sinceVersion != -1 && entityAddedVersion <= sinceVersion )
3151 if ( e.tagName() ==
"labelsetting"_L1 )
3153 QString
name = e.attribute( u
"name"_s );
3155 if ( e.hasAttribute( u
"tags"_s ) )
3157 tags = e.attribute( u
"tags"_s ).split(
',' );
3159 bool favorite =
false;
3160 if ( e.hasAttribute( u
"favorite"_s ) && e.attribute( u
"favorite"_s ) ==
"1"_L1 )
3165 QgsPalLayerSettings settings;
3166 const QDomElement styleElem = e.firstChildElement();
3167 settings.
readXml( styleElem, QgsReadWriteContext() );
3185 const QDomElement legendPatchShapesElement = docEl.firstChildElement( u
"legendpatchshapes"_s );
3186 e = legendPatchShapesElement.firstChildElement();
3187 for ( ; !e.isNull(); e = e.nextSiblingElement() )
3189 const int entityAddedVersion = e.attribute( u
"addedVersion"_s ).toInt();
3190 if ( entityAddedVersion != 0 && sinceVersion != -1 && entityAddedVersion <= sinceVersion )
3196 if ( e.tagName() ==
"legendpatchshape"_L1 )
3198 QString
name = e.attribute( u
"name"_s );
3200 if ( e.hasAttribute( u
"tags"_s ) )
3202 tags = e.attribute( u
"tags"_s ).split(
',' );
3204 bool favorite =
false;
3205 if ( e.hasAttribute( u
"favorite"_s ) && e.attribute( u
"favorite"_s ) ==
"1"_L1 )
3210 QgsLegendPatchShape shape;
3211 const QDomElement shapeElem = e.firstChildElement();
3212 shape.
readXml( shapeElem, QgsReadWriteContext() );
3229 const QDomElement symbols3DElement = docEl.firstChildElement( u
"symbols3d"_s );
3230 e = symbols3DElement.firstChildElement();
3231 for ( ; !e.isNull(); e = e.nextSiblingElement() )
3233 const int entityAddedVersion = e.attribute( u
"addedVersion"_s ).toInt();
3234 if ( entityAddedVersion != 0 && sinceVersion != -1 && entityAddedVersion <= sinceVersion )
3240 if ( e.tagName() ==
"symbol3d"_L1 )
3242 QString
name = e.attribute( u
"name"_s );
3244 if ( e.hasAttribute( u
"tags"_s ) )
3246 tags = e.attribute( u
"tags"_s ).split(
',' );
3248 bool favorite =
false;
3249 if ( e.hasAttribute( u
"favorite"_s ) && e.attribute( u
"favorite"_s ) ==
"1"_L1 )
3254 const QDomElement symbolElem = e.firstChildElement();
3255 const QString type = symbolElem.attribute( u
"type"_s );
3259 sym->readXml( symbolElem, QgsReadWriteContext() );
3260 QgsAbstract3DSymbol *newSym = sym.get();
3278 const QDomElement materialSettingsElement = docEl.firstChildElement( u
"materialsettings"_s );
3279 e = materialSettingsElement.firstChildElement();
3280 for ( ; !e.isNull(); e = e.nextSiblingElement() )
3282 const int entityAddedVersion = e.attribute( u
"addedVersion"_s ).toInt();
3283 if ( entityAddedVersion != 0 && sinceVersion != -1 && entityAddedVersion <= sinceVersion )
3289 if ( e.tagName() ==
"material"_L1 )
3291 QString
name = e.attribute( u
"name"_s );
3293 if ( e.hasAttribute( u
"tags"_s ) )
3295 tags = e.attribute( u
"tags"_s ).split(
',' );
3297 bool favorite =
false;
3298 if ( e.hasAttribute( u
"favorite"_s ) && e.attribute( u
"favorite"_s ) ==
"1"_L1 )
3303 const QDomElement materialElem = e.firstChildElement();
3304 const QString type = materialElem.attribute( u
"type"_s );
3308 settings->
readXml( materialElem, QgsReadWriteContext() );
3309 QgsAbstractMaterialSettings *newMaterial = settings.get();
3325 runEmptyQuery( query );
3332 QFileInfo fileInfo( path );
3334 if ( fileInfo.suffix().compare(
"xml"_L1, Qt::CaseInsensitive ) != 0 )
3338 if ( !QFile::exists( path ) )
3341 QFile inputFile( path );
3342 if ( !inputFile.open( QIODevice::ReadOnly ) )
3345 QTextStream stream( &inputFile );
3346 const QString line = stream.readLine();
3347 return line ==
"<!DOCTYPE qgis_style>"_L1;
3362 mReadOnly = readOnly;
3365bool QgsStyle::updateSymbol( StyleEntity type,
const QString &name )
3367 QDomDocument doc( u
"dummy"_s );
3369 QByteArray xmlArray;
3370 QTextStream stream( &xmlArray );
3379 auto it = mSymbols.constFind(
name );
3380 if ( it == mSymbols.constEnd() || !it.value() )
3382 QgsDebugError( u
"Update request received for unavailable symbol"_s );
3387 if ( symEl.isNull() )
3389 QgsDebugError( u
"Couldn't convert symbol to valid XML!"_s );
3392 symEl.save( stream, 4 );
3393 query =
qgs_sqlite3_mprintf(
"UPDATE symbol SET xml='%q' WHERE name='%q';", xmlArray.constData(),
name.toUtf8().constData() );
3400 auto it = m3dSymbols.constFind(
name );
3401 if ( it == m3dSymbols.constEnd() || !it.value() )
3403 QgsDebugError( u
"Update request received for unavailable symbol"_s );
3407 symEl = doc.createElement( u
"symbol"_s );
3408 symEl.setAttribute( u
"type"_s, it.value()->type() );
3409 it.value()->writeXml( symEl, QgsReadWriteContext() );
3410 if ( symEl.isNull() )
3412 QgsDebugError( u
"Couldn't convert symbol to valid XML!"_s );
3415 symEl.save( stream, 4 );
3416 query =
qgs_sqlite3_mprintf(
"UPDATE symbol3d SET xml='%q' WHERE name='%q';", xmlArray.constData(),
name.toUtf8().constData() );
3423 auto it = mMaterialSettings.constFind(
name );
3424 if ( it == mMaterialSettings.constEnd() || !it.value() )
3426 QgsDebugError( u
"Update request received for unavailable material"_s );
3430 symEl = doc.createElement( u
"material"_s );
3431 it.value()->writeXml( symEl, QgsReadWriteContext() );
3432 if ( symEl.isNull() )
3434 QgsDebugError( u
"Couldn't convert material settings to valid XML!"_s );
3437 symEl.save( stream, 4 );
3438 query =
qgs_sqlite3_mprintf(
"UPDATE materialsettings SET xml='%q' WHERE name='%q';", xmlArray.constData(),
name.toUtf8().constData() );
3444 auto it = mColorRamps.constFind(
name );
3445 if ( it == mColorRamps.constEnd() || !it.value() )
3447 QgsDebugError( u
"Update requested for unavailable color ramp."_s );
3452 if ( symEl.isNull() )
3454 QgsDebugError( u
"Couldn't convert color ramp to valid XML!"_s );
3457 symEl.save( stream, 4 );
3458 query =
qgs_sqlite3_mprintf(
"UPDATE colorramp SET xml='%q' WHERE name='%q';", xmlArray.constData(),
name.toUtf8().constData() );
3464 auto it = mTextFormats.constFind(
name );
3465 if ( it == mTextFormats.constEnd() )
3467 QgsDebugError( u
"Update requested for unavailable text format."_s );
3471 symEl = it.value().writeXml( doc, QgsReadWriteContext() );
3472 if ( symEl.isNull() )
3474 QgsDebugError( u
"Couldn't convert text format to valid XML!"_s );
3477 symEl.save( stream, 4 );
3478 query =
qgs_sqlite3_mprintf(
"UPDATE textformat SET xml='%q' WHERE name='%q';", xmlArray.constData(),
name.toUtf8().constData() );
3484 auto it = mLabelSettings.constFind(
name );
3485 if ( it == mLabelSettings.constEnd() )
3487 QgsDebugError( u
"Update requested for unavailable label settings."_s );
3491 symEl = it.value().writeXml( doc, QgsReadWriteContext() );
3492 if ( symEl.isNull() )
3494 QgsDebugError( u
"Couldn't convert label settings to valid XML!"_s );
3497 symEl.save( stream, 4 );
3498 query =
qgs_sqlite3_mprintf(
"UPDATE labelsettings SET xml='%q' WHERE name='%q';", xmlArray.constData(),
name.toUtf8().constData() );
3504 auto it = mLegendPatchShapes.constFind(
name );
3505 if ( it == mLegendPatchShapes.constEnd() )
3507 QgsDebugError( u
"Update requested for unavailable legend patch shape."_s );
3511 symEl = doc.createElement( u
"shape"_s );
3512 it.value().writeXml( symEl, doc, QgsReadWriteContext() );
3513 symEl.save( stream, 4 );
3514 query =
qgs_sqlite3_mprintf(
"UPDATE legendpatchshapes SET xml='%q' WHERE name='%q';", xmlArray.constData(),
name.toUtf8().constData() );
3527 if ( !runEmptyQuery( query ) )
3529 QgsDebugError( u
"Couldn't update symbol into the database!"_s );
3566 mCachedTags[type].remove(
name );
3569bool QgsStyle::createStyleMetadataTableIfNeeded()
3572 QString query =
qgs_sqlite3_mprintf(
"SELECT name FROM sqlite_master WHERE name='stylemetadata'" );
3573 sqlite3_statement_unique_ptr statement;
3575 statement = mCurrentDB.prepare( query, rc );
3577 if ( rc != SQLITE_OK || sqlite3_step( statement.get() ) != SQLITE_ROW )
3581 "CREATE TABLE stylemetadata("
3582 "id INTEGER PRIMARY KEY,"
3586 runEmptyQuery( query );
3588 runEmptyQuery( query );
3597void QgsStyle::upgradeIfRequired()
3601 if ( !createStyleMetadataTableIfNeeded() )
3603 const QString query =
qgs_sqlite3_mprintf(
"SELECT value FROM stylemetadata WHERE key='version'" );
3605 sqlite3_statement_unique_ptr statement = mCurrentDB.prepare( query, rc );
3606 if ( rc == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
3618 runEmptyQuery( query );
3631 return u
"colorramp"_s;
3634 return u
"textformat"_s;
3637 return u
"labelsettings"_s;
3640 return u
"legendpatchshapes"_s;
3643 return u
"symbol3d"_s;
3646 return u
"materialsettings"_s;
3652 return u
"smartgroup"_s;
3665 return u
"ctagmap"_s;
3668 return u
"tftagmap"_s;
3671 return u
"lstagmap"_s;
3674 return u
"lpstagmap"_s;
3677 return u
"symbol3dtagmap"_s;
3680 return u
"materialsettingstagmap"_s;
3694 return u
"symbol_id"_s;
3697 return u
"colorramp_id"_s;
3700 return u
"textformat_id"_s;
3703 return u
"labelsettings_id"_s;
3706 return u
"legendpatchshape_id"_s;
3709 return u
"symbol3d_id"_s;
3712 return u
"materialsettings_id"_s;
@ ScaleArea
Calculate scale by the area.
GeometryType
The geometry types are used to group Qgis::WkbType in a coarse way.
static int versionInt()
Version number used for comparing versions using the "Check QGIS Version" function.
QStringList symbolTypes() const
Returns a list of all available symbol types.
Abstract base class for 3D symbols that are used by VectorLayer3DRenderer objects.
Abstract base class for material settings.
virtual void writeXml(QDomElement &element, const QgsReadWriteContext &) const
Writes settings to a DOM element.
virtual QString type() const =0
Returns the unique type name for the material.
static QString userStylePath()
Returns the path to user's style.
static QString defaultStylePath()
Returns the path to default style (works as a starting point).
static QgsMaterialRegistry * materialRegistry()
Returns registry of available 3D materials.
static Qgs3DSymbolRegistry * symbol3DRegistry()
Returns registry of available 3D symbols.
Abstract base class for color ramps.
virtual double value(int index) const =0
Returns relative value between [0,1] of color at specified index.
virtual QgsColorRamp * clone() const =0
Creates a clone of the color ramp.
A geometry is the spatial representation of a feature.
Represents a patch shape for use in map legends.
void readXml(const QDomElement &element, const QgsReadWriteContext &context)
Read settings from a DOM element.
QList< QList< QPolygonF > > toQPolygonF(Qgis::SymbolType type, QSizeF size) const
Converts the patch shape to a set of QPolygonF objects representing how the patch should be drawn for...
void writeXml(QDomElement &element, QDomDocument &doc, const QgsReadWriteContext &context) const
Write settings into a DOM element.
Qgis::SymbolType symbolType() const
Returns the symbol type associated with this patch.
Line string geometry type, with support for z-dimension and m-values.
std::unique_ptr< QgsAbstractMaterialSettings > createMaterialSettings(const QString &type) const
Creates a new instance of the material settings of the specified type.
Contains settings for how a map layer will be labeled.
void readXml(const QDomElement &elem, const QgsReadWriteContext &context)
Read settings from a DOM element.
QDomElement writeXml(QDomDocument &doc, const QgsReadWriteContext &context) const
Write settings into a DOM element.
QgsTextFormat defaultTextFormat() const
Returns the project default text format.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
const QgsProjectStyleSettings * styleSettings() const
Returns the project's style settings, which contains settings and properties relating to how a QgsPro...
A container for the context for various read/write operations on objects.
Scoped object for logging of the runtime for a single operation or group of operations.
static const QgsSettingsEntryInteger * settingsSymbolsListGroupsIndex
Settings entry for symbols list groups index.
A color ramp entity for QgsStyle databases.
QgsStyle::StyleEntity type() const override
Returns the type of style entity.
An interface for entities which can be placed in a QgsStyle database.
virtual QgsStyle::StyleEntity type() const =0
Returns the type of style entity.
A label settings entity for QgsStyle databases.
QgsStyle::StyleEntity type() const override
Returns the type of style entity.
A legend patch shape entity for QgsStyle databases.
QgsStyle::StyleEntity type() const override
Returns the type of style entity.
A 3D material settings entity for QgsStyle databases.
QgsStyle::StyleEntity type() const override
Returns the type of style entity.
A 3d symbol entity for QgsStyle databases.
QgsStyle::StyleEntity type() const override
Returns the type of style entity.
A symbol entity for QgsStyle databases.
QgsStyle::StyleEntity type() const override
Returns the type of style entity.
A text format entity for QgsStyle databases.
QgsStyle::StyleEntity type() const override
Returns the type of style entity.
A database of saved style entities, including symbols, color ramps, text formats and others.
bool addEntity(const QString &name, const QgsStyleEntityInterface *entity, bool update=false)
Adds an entity to the style, with the specified name.
std::unique_ptr< QgsColorRamp > colorRamp(const QString &name) const
Returns a new copy of the specified color ramp.
void setFileName(const QString &filename)
Sets the current file name of the style database.
void labelSettingsChanged(const QString &name)
Emitted whenever a label setting's definition is changed.
int colorRampCount()
Returns count of color ramps.
bool detagSymbol(StyleEntity type, const QString &symbol, const QStringList &tags)
Detags the symbol with the given list.
QgsTextFormat textFormat(const QString &name) const
Returns the text format with the specified name.
QStringList allNames(StyleEntity type) const
Returns a list of the names of all existing entities of the specified type.
QgsLegendPatchShape defaultPatch(Qgis::SymbolType type, QSizeF size) const
Returns the default legend patch shape for the given symbol type.
bool remove(StyleEntity type, int id)
Removes the specified entity from the database.
bool removeSymbol(const QString &name)
Removes symbol from style (and delete it).
void entityChanged(QgsStyle::StyleEntity entity, const QString &name)
Emitted whenever an entity's definition is changed.
bool removeLabelSettings(const QString &name)
Removes label settings from the style.
void labelSettingsAdded(const QString &name)
Emitted whenever label settings have been added to the style and the database has been updated as a r...
QStringList tags() const
Returns a list of all tags in the style database.
QString tag(int id) const
Returns the tag name for the given id.
QgsSmartConditionMap smartgroup(int id)
Returns the QgsSmartConditionMap for the given id.
bool renameColorRamp(const QString &oldName, const QString &newName)
Changes ramp's name.
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...
QStringList symbol3DNames() const
Returns a list of names of 3d symbols in the style.
bool tagSymbol(StyleEntity type, const QString &symbol, const QStringList &tags)
Tags the symbol with the tags in the list.
int entityId(StyleEntity type, const QString &name)
Returns the id in the style database for the given name of the specified entity type.
void rebuildIconPreviews()
Emitted whenever icon previews for entities in the style must be rebuilt.
bool saveLabelSettings(const QString &name, const QgsPalLayerSettings &settings, bool favorite, const QStringList &tags)
Adds label settings to the database.
Q_DECL_DEPRECATED bool save(const QString &filename=QString())
Saves style into a file.
std::unique_ptr< QgsSymbol > symbol(const QString &name)
Returns a NEW copy of symbol.
bool symbolHasTag(StyleEntity type, const QString &symbol, const QString &tag)
Returns whether a given tag is associated with the symbol.
void aboutToBeDestroyed()
Emitted just before the style object is destroyed.
QgsTextFormat defaultTextFormat(QgsStyle::TextFormatContext context=QgsStyle::TextFormatContext::Labeling) const
Returns the default text format to use for new text based objects in the specified context.
@ XML
Label settings definition (as XML).
@ Name
Label settings name.
bool createDatabase(const QString &filename)
Creates an on-disk database.
QStringList textFormatNames() const
Returns a list of names of text formats in the style.
const QgsColorRamp * colorRampRef(const QString &name) const
Returns a const pointer to a symbol (doesn't create new instance).
QStringList symbolsWithTag(StyleEntity type, int tagid) const
Returns the symbol names with which have the given tag.
bool addColorRamp(const QString &name, QgsColorRamp *colorRamp, bool update=false)
Adds a color ramp to the style.
bool removeTextFormat(const QString &name)
Removes a text format from the style.
void labelSettingsRemoved(const QString &name)
Emitted whenever label settings have been removed from the style and the database has been updated as...
QStringList symbolsOfSmartgroup(StyleEntity type, int id)
Returns the symbols for the smartgroup.
int labelSettingsCount() const
Returns count of label settings in the style.
StyleEntity
Enum for Entities involved in a style.
@ LabelSettingsEntity
Label settings.
@ TextFormatEntity
Text formats.
@ SmartgroupEntity
Smart groups.
@ Symbol3DEntity
3D symbol entity
@ ColorrampEntity
Color ramps.
@ LegendPatchShapeEntity
Legend patch shape.
@ MaterialSettingsEntity
Material settings.
QStringList tagsOfSymbol(StyleEntity type, const QString &symbol)
Returns the tags associated with the symbol.
void symbolRenamed(const QString &oldName, const QString &newName)
Emitted whenever a symbol has been renamed from oldName to newName.
QList< Qgis::GeometryType > symbol3DCompatibleGeometryTypes(const QString &name) const
Returns the list of the vector layer geometry types which are compatible with the 3D symbol with the ...
@ XML
Color ramp definition (as XML).
void groupsModified()
Emitted every time a tag or smartgroup has been added, removed, or renamed.
void clear()
Removes all contents of the style.
int smartgroupId(const QString &smartgroup)
Returns the database id for the given smartgroup 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 ...
void entityRenamed(QgsStyle::StyleEntity entity, const QString &oldName, const QString &newName)
Emitted whenever a entity of the specified type has been renamed from oldName to newName.
const QgsSymbol * symbolRef(const QString &name) const
Returns a const pointer to a symbol (doesn't create new instance).
int addSmartgroup(const QString &name, const QString &op, const QgsSmartConditionMap &conditions)
Adds a new smartgroup to the database and returns the id.
bool saveMaterialSettings(const QString &name, QgsAbstractMaterialSettings *settings, bool favorite, const QStringList &tags)
Adds 3D material settings to the database.
QStringList colorRampNames() const
Returns a list of names of color ramps.
std::unique_ptr< QgsAbstractMaterialSettings > materialSettings(const QString &name) const
Returns a new copy of the 3D material settings with the specified name.
void textFormatChanged(const QString &name)
Emitted whenever a text format's definition is changed.
bool addSymbol3D(const QString &name, QgsAbstract3DSymbol *symbol, bool update=false)
Adds a 3d symbol with the specified name to the style.
QStringList legendPatchShapeNames() const
Returns a list of names of legend patch shapes in the style.
bool renameLegendPatchShape(const QString &oldName, const QString &newName)
Changes a legend patch shape's name.
static void cleanDefaultStyle()
Deletes the default style. Only to be used by QgsApplication::exitQgis().
void symbolSaved(const QString &name, const QgsSymbol *symbol)
Emitted every time a new symbol has been added to the database.
void textFormatRenamed(const QString &oldName, const QString &newName)
Emitted whenever a text format has been renamed from oldName to newName.
void triggerIconRebuild()
Triggers emission of the rebuildIconPreviews() signal.
void setName(const QString &name)
Sets the name of the style.
bool removeEntityByName(StyleEntity type, const QString &name)
Removes the entry of the specified type with matching name from the database.
void labelSettingsRenamed(const QString &oldName, const QString &newName)
Emitted whenever label settings have been renamed from oldName to newName.
void initialized()
Emitted when the style database has been fully initialized.
@ XML
Text format definition (as XML).
int textFormatCount() const
Returns count of text formats in the style.
QStringList findSymbols(StyleEntity type, const QString &qword)
Returns the names of the symbols which have a matching 'substring' in its definition.
int tagId(const QString &tag)
Returns the database id for the given tag name.
void rampRenamed(const QString &oldName, const QString &newName)
Emitted whenever a color ramp has been renamed from oldName to newName.
bool exportXml(const QString &filename)
Exports the style as a XML file.
void createTables()
Creates tables structure for new database.
bool isReadOnly() const
Returns true if the style is considered a read-only library.
bool addLegendPatchShape(const QString &name, const QgsLegendPatchShape &shape, bool update=false)
Adds a legend patch shape with the specified name to the style.
int textFormatId(const QString &name)
Returns the ID in the style database for the given text format by name.
int symbolCount()
Returns count of symbols in style.
bool addMaterialSettings(const QString &name, QgsAbstractMaterialSettings *settings, bool update=false)
Adds a 3D material settings with the specified name to the style.
bool renameEntity(StyleEntity type, const QString &oldName, const QString &newName)
Renames an entity of the specified type from oldName to newName.
static QgsStyle * defaultStyle(bool initialize=true)
Returns the default application-wide style.
QStringList materialSettingsNames() const
Returns a list of names of 3D material settings in the style.
bool renameMaterialSettings(const QString &oldName, const QString &newName)
Changes a 3D material settings's name.
static bool isXmlStyleFile(const QString &path)
Tests if the file at path is a QGIS style XML file.
int symbol3DCount() const
Returns count of 3D symbols in the style.
bool createMemoryDatabase()
Creates a temporary memory database.
int colorrampId(const QString &name)
Returns the id in the style database for the given colorramp name returns 0 if not found.
bool saveSymbol(const QString &name, const QgsSymbol *symbol, bool favorite, const QStringList &tags)
Adds the symbol to the database with tags.
QStringList labelSettingsNames() const
Returns a list of names of label settings in the style.
bool load(const QString &filename)
Loads a file into the style.
QStringList smartgroupNames() const
Returns the smart groups list.
bool rename(StyleEntity type, int id, const QString &newName)
Renames the given entity with the specified id.
bool renameTextFormat(const QString &oldName, const QString &newName)
Changes a text format's name.
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...
bool removeFavorite(StyleEntity type, const QString &name)
Removes the specified symbol from favorites.
static QgsTextFormat defaultTextFormatForProject(QgsProject *project, QgsStyle::TextFormatContext context=QgsStyle::TextFormatContext::Labeling)
Returns the default text format to use for new text based objects for the specified project,...
int legendPatchShapesCount() const
Returns count of legend patch shapes in the style.
QgsSymbolGroupMap smartgroupsListMap()
Returns the smart groups map with id as key and name as value.
bool isFavorite(StyleEntity type, const QString &name)
Returns true if the symbol with matching type and name is marked as a favorite.
int symbolId(const QString &name)
Returns the id in the style database for the given symbol name returns 0 if not found.
bool saveLegendPatchShape(const QString &name, const QgsLegendPatchShape &shape, bool favorite, const QStringList &tags)
Adds a legend patch shape to the database.
QString name() const
Returns the name of the style.
int materialSettingsCount() const
Returns count of 3D material settings in the style.
QgsStyle(QObject *parent=nullptr)
Constructor for QgsStyle, with the specified parent object.
Qgis::GeometryType labelSettingsLayerType(const QString &name) const
Returns the layer geometry type corresponding to the label settings with the specified name,...
@ XML
Symbol definition (as XML).
bool renameLabelSettings(const QString &oldName, const QString &newName)
Changes a label setting's name.
bool renameSymbol3D(const QString &oldName, const QString &newName)
Changes a 3d symbol's name.
bool addTextFormat(const QString &name, const QgsTextFormat &format, bool update=false)
Adds a text format with the specified name to the style.
bool saveColorRamp(const QString &name, const QgsColorRamp *ramp, bool favorite, const QStringList &tags)
Adds the colorramp to the database.
void rampChanged(const QString &name)
Emitted whenever a color ramp's definition is changed.
QStringList symbolsOfFavorite(StyleEntity type) const
Returns the symbol names which are flagged as favorite.
void entityTagsChanged(QgsStyle::StyleEntity entity, const QString &name, const QStringList &newTags)
Emitted whenever an entity's tags are changed.
bool renameSymbol(const QString &oldName, const QString &newName)
Renames a symbol from oldName to newName.
bool removeColorRamp(const QString &name)
Removes color ramp from style (and delete it).
bool saveSymbol3D(const QString &name, QgsAbstract3DSymbol *symbol, bool favorite, const QStringList &tags)
Adds a 3d symbol to the database.
void favoritedChanged(QgsStyle::StyleEntity entity, const QString &name, bool isFavorite)
Emitted whenever an entity is either favorited or un-favorited.
QgsPalLayerSettings labelSettings(const QString &name) const
Returns the label settings with the specified name.
void entityRemoved(QgsStyle::StyleEntity entity, const QString &name)
Emitted whenever an entity of the specified type is removed from the style and the database has been ...
int labelSettingsId(const QString &name)
Returns the ID in the style database for the given label settings by name.
Qgis::SymbolType legendPatchShapeSymbolType(const QString &name) const
Returns the symbol type corresponding to the legend patch shape with the specified name,...
int addTag(const QString &tagName)
Adds a new tag and returns the tag's id.
const QgsSymbol * previewSymbolForPatchShape(const QgsLegendPatchShape &shape) const
Returns a symbol to use for rendering preview icons for a patch shape.
std::unique_ptr< QgsAbstract3DSymbol > symbol3D(const QString &name) const
Returns a new copy of the 3D symbol with the specified name.
bool addSymbol(const QString &name, QgsSymbol *symbol, bool update=false)
Adds a symbol to style and takes symbol's ownership.
QgsLegendPatchShape legendPatchShape(const QString &name) const
Returns the legend patch shape with the specified name.
void entityAdded(QgsStyle::StyleEntity entity, const QString &name)
Emitted every time a new entity has been added to the database.
QStringList symbolNames() const
Returns a list of names of symbols.
TextFormatContext
Text format context.
void symbolRemoved(const QString &name)
Emitted whenever a symbol has been removed from the style and the database has been updated as a resu...
void symbolChanged(const QString &name)
Emitted whenever a symbol's definition is changed.
bool addFavorite(StyleEntity type, const QString &name)
Adds the specified symbol to favorites.
QString smartgroupOperator(int id)
Returns the operator for the smartgroup.
bool saveTextFormat(const QString &name, const QgsTextFormat &format, bool favorite, const QStringList &tags)
Adds a text format to the database.
QList< QList< QPolygonF > > defaultPatchAsQPolygonF(Qgis::SymbolType type, QSizeF size) const
Returns the default patch geometry for the given symbol type and size as a set of QPolygonF objects (...
void textFormatRemoved(const QString &name)
Emitted whenever a text format has been removed from the style and the database has been updated as a...
void setReadOnly(bool readOnly)
Sets whether the style is considered a read-only library.
bool importXml(const QString &filename)
Imports the symbols and colorramps into the default style database from the given XML file.
bool addLabelSettings(const QString &name, const QgsPalLayerSettings &settings, bool update=false)
Adds label settings with the specified name to the style.
static std::unique_ptr< QgsColorRamp > loadColorRamp(QDomElement &element)
Creates a color ramp from the settings encoded in an XML element.
static std::unique_ptr< QgsSymbol > loadSymbol(const QDomElement &element, const QgsReadWriteContext &context)
Attempts to load a symbol from a DOM element.
static QDomElement saveSymbol(const QString &symbolName, const QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML.
static QDomElement saveColorRamp(const QString &name, const QgsColorRamp *ramp, QDomDocument &doc)
Encodes a color ramp's settings to an XML element.
static void resetSymbolLayerIds(QgsSymbol *symbol)
Regenerate recursively unique id from all symbol symbol layers.
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 ...
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.
Abstract base class for all rendered symbols.
Container for all settings relating to text rendering.
void readXml(const QDomElement &elem, const QgsReadWriteContext &context)
Read settings from a DOM element.
QDomElement writeXml(QDomDocument &doc, const QgsReadWriteContext &context) const
Write settings into a DOM element.
sqlite3_statement_unique_ptr prepare(const QString &sql, int &resultCode) const
Prepares a sql statement, returning the result.
Unique pointer for sqlite3 prepared statements, which automatically finalizes the statement when the ...
QString columnAsText(int column) const
Returns the column value from the current statement row as a string.
QMultiMap< QString, QString > QgsSmartConditionMap
A multimap to hold the smart group conditions as constraint and parameter pairs.
#define QgsDebugError(str)
QMap< QString, QgsSymbol * > QgsSymbolMap
QString qgs_sqlite3_mprintf(const char *format,...)
Wraps sqlite3_mprintf() by automatically freeing the memory.
LegendPatchTable
Columns available in the legend patch table.
@ LegendPatchTableId
Legend patch ID.
@ LegendPatchTableName
Legend patch name.
@ LegendPatchTableFavoriteId
Legend patch is favorite flag.
@ LegendPatchTableXML
Legend patch definition (as XML).
#define STYLE_CURRENT_VERSION
MaterialSettingsTable
Columns available in the 3D material settings table.
@ MaterialSettingsTableId
3d material settings ID
@ MaterialSettingsTableName
3d material settings name
@ MaterialSettingsTableFavoriteId
3d material settings is favorite flag
@ MaterialSettingsTableXML
3d material settings definition (as XML)
Symbol3DTable
Columns available in the 3d symbol table.
@ Symbol3DTableXML
3d symbol definition (as XML)
@ Symbol3DTableName
3d symbol name
@ Symbol3DTableFavoriteId
3d symbol is favorite flag
@ Symbol3DTableId
3d symbol ID
QMap< int, QString > QgsSymbolGroupMap
QList< QgsSymbolLayer * > QgsSymbolLayerList