35 #include <QDomDocument>
36 #include <QDomElement>
38 #include <QDomNodeList>
40 #include <QTextStream>
46 #define STYLE_CURRENT_VERSION "2"
71 QgsStyle *QgsStyle::sDefaultStyle =
nullptr;
77 simpleMarker->setStrokeWidth( 0.4 );
78 mPatchMarkerSymbol = qgis::make_unique< QgsMarkerSymbol >(
QgsSymbolLayerList() << simpleMarker.release() );
80 std::unique_ptr< QgsSimpleLineSymbolLayer > simpleLine = qgis::make_unique< QgsSimpleLineSymbolLayer >( QColor( 84, 176, 74 ), 0.6 );
81 mPatchLineSymbol = qgis::make_unique< QgsLineSymbol >(
QgsSymbolLayerList() << simpleLine.release() );
83 std::unique_ptr< QgsGradientFillSymbolLayer > gradientFill = qgis::make_unique< QgsGradientFillSymbolLayer >( QColor( 66, 150, 63 ), QColor( 84, 176, 74 ) );
84 std::unique_ptr< QgsSimpleLineSymbolLayer > simpleOutline = qgis::make_unique< QgsSimpleLineSymbolLayer >( QColor( 56, 128, 54 ), 0.26 );
85 mPatchFillSymbol = qgis::make_unique< QgsFillSymbol >(
QgsSymbolLayerList() << gradientFill.release() << simpleOutline.release() );
95 switch ( entity->
type() )
129 if ( !sDefaultStyle )
135 if ( !QFile::exists( styleFilename ) )
147 if ( sDefaultStyle->
load( styleFilename ) )
149 sDefaultStyle->upgradeIfRequired();
153 return sDefaultStyle;
158 delete sDefaultStyle;
159 sDefaultStyle =
nullptr;
164 qDeleteAll( mSymbols );
165 qDeleteAll( mColorRamps );
166 qDeleteAll( m3dSymbols );
170 mTextFormats.clear();
174 mCachedFavorites.clear();
179 if ( !
symbol || name.isEmpty() )
183 if ( mSymbols.contains( name ) )
186 delete mSymbols.value( name );
187 mSymbols.insert( name,
symbol );
193 mSymbols.insert( name,
symbol );
204 QDomDocument doc( QStringLiteral(
"dummy" ) );
206 if ( symEl.isNull() )
208 QgsDebugMsg( QStringLiteral(
"Couldn't convert symbol to valid XML!" ) );
213 QTextStream stream( &xmlArray );
214 stream.setCodec(
"UTF-8" );
215 symEl.save( stream, 4 );
217 name.toUtf8().constData(), xmlArray.constData(), ( favorite ? 1 : 0 ) );
219 if ( !runEmptyQuery( query ) )
221 QgsDebugMsg( QStringLiteral(
"Couldn't insert symbol into the database!" ) );
225 mCachedFavorites[
SymbolEntity ].insert( name, favorite );
277 return mSymbols.value( name );
282 return mSymbols.count();
287 return mSymbols.keys();
297 if ( mColorRamps.contains( name ) )
300 delete mColorRamps.value( name );
318 if ( mTextFormats.contains( name ) )
321 mTextFormats.remove( name );
322 mTextFormats.insert( name, format );
328 mTextFormats.insert( name, format );
339 if ( mLabelSettings.contains( name ) )
342 mLabelSettings.remove( name );
343 mLabelSettings.insert( name, settings );
349 mLabelSettings.insert( name, settings );
360 if ( mLegendPatchShapes.contains( name ) )
363 mLegendPatchShapes.remove( name );
364 mLegendPatchShapes.insert( name, shape );
370 mLegendPatchShapes.insert( name, shape );
381 if ( m3dSymbols.contains( name ) )
384 delete m3dSymbols.take( name );
385 m3dSymbols.insert( name,
symbol );
391 m3dSymbols.insert( name,
symbol );
402 QDomDocument doc( QStringLiteral(
"dummy" ) );
405 if ( rampEl.isNull() )
407 QgsDebugMsg( QStringLiteral(
"Couldn't convert color ramp to valid XML!" ) );
412 QTextStream stream( &xmlArray );
413 stream.setCodec(
"UTF-8" );
414 rampEl.save( stream, 4 );
415 QString query =
qgs_sqlite3_mprintf(
"INSERT INTO colorramp VALUES (NULL, '%q', '%q', %d);",
416 name.toUtf8().constData(), xmlArray.constData(), ( favorite ? 1 : 0 ) );
417 if ( !runEmptyQuery( query ) )
419 QgsDebugMsg( QStringLiteral(
"Couldn't insert colorramp into the database!" ) );
441 return ramp ? ramp->
clone() :
nullptr;
446 return mColorRamps.value( name );
451 return mColorRamps.count();
456 return mColorRamps.keys();
459 void QgsStyle::handleDeferred3DSymbolCreation()
461 for (
auto it = mDeferred3DsymbolElements.constBegin(); it != mDeferred3DsymbolElements.constEnd(); ++it )
463 const QString symbolType = it.value().attribute( QStringLiteral(
"type" ) );
473 QgsDebugMsg(
"Cannot open 3d symbol " + it.key() );
477 mDeferred3DsymbolElements.clear();
480 bool QgsStyle::openDatabase(
const QString &filename )
482 int rc = mCurrentDB.
open( filename );
485 mErrorString = QStringLiteral(
"Couldn't open the style database: %1" ).arg( mCurrentDB.
errorMessage() );
494 mErrorString.clear();
495 if ( !openDatabase( filename ) )
497 mErrorString = QStringLiteral(
"Unable to create database" );
509 mErrorString.clear();
510 if ( !openDatabase( QStringLiteral(
":memory:" ) ) )
512 mErrorString = QStringLiteral(
"Unable to create temporary memory database" );
525 "id INTEGER PRIMARY KEY,"\
528 "favorite INTEGER);"\
529 "CREATE TABLE colorramp("\
530 "id INTEGER PRIMARY KEY,"\
533 "favorite INTEGER);"\
534 "CREATE TABLE textformat("\
535 "id INTEGER PRIMARY KEY,"\
538 "favorite INTEGER);"\
539 "CREATE TABLE labelsettings("\
540 "id INTEGER PRIMARY KEY,"\
543 "favorite INTEGER);"\
544 "CREATE TABLE legendpatchshapes("\
545 "id INTEGER PRIMARY KEY,"\
548 "favorite INTEGER);"\
549 "CREATE TABLE symbol3d("\
550 "id INTEGER PRIMARY KEY,"\
553 "favorite INTEGER);"\
555 "id INTEGER PRIMARY KEY,"\
557 "CREATE TABLE tagmap("\
558 "tag_id INTEGER NOT NULL,"\
559 "symbol_id INTEGER);"\
560 "CREATE TABLE ctagmap("\
561 "tag_id INTEGER NOT NULL,"\
562 "colorramp_id INTEGER);"\
563 "CREATE TABLE tftagmap("\
564 "tag_id INTEGER NOT NULL,"\
565 "textformat_id INTEGER);"\
566 "CREATE TABLE lstagmap("\
567 "tag_id INTEGER NOT NULL,"\
568 "labelsettings_id INTEGER);"\
569 "CREATE TABLE lpstagmap("\
570 "tag_id INTEGER NOT NULL,"\
571 "legendpatchshape_id INTEGER);"\
572 "CREATE TABLE symbol3dtagmap("\
573 "tag_id INTEGER NOT NULL,"\
574 "symbol3d_id INTEGER);"\
575 "CREATE TABLE smartgroup("\
576 "id INTEGER PRIMARY KEY,"\
579 runEmptyQuery( query );
584 mErrorString.clear();
587 if ( !openDatabase( filename ) )
589 mErrorString = QStringLiteral(
"Unable to open database file specified" );
595 QString query =
qgs_sqlite3_mprintf(
"SELECT name FROM sqlite_master WHERE name='textformat'" );
598 statement = mCurrentDB.
prepare( query, rc );
599 if ( rc != SQLITE_OK || sqlite3_step( statement.get() ) != SQLITE_ROW )
602 "id INTEGER PRIMARY KEY,"\
605 "favorite INTEGER);"\
606 "CREATE TABLE tftagmap("\
607 "tag_id INTEGER NOT NULL,"\
608 "textformat_id INTEGER);" );
609 runEmptyQuery( query );
612 query =
qgs_sqlite3_mprintf(
"SELECT name FROM sqlite_master WHERE name='labelsettings'" );
613 statement = mCurrentDB.
prepare( query, rc );
614 if ( rc != SQLITE_OK || sqlite3_step( statement.get() ) != SQLITE_ROW )
617 "id INTEGER PRIMARY KEY,"\
620 "favorite INTEGER);"\
621 "CREATE TABLE lstagmap("\
622 "tag_id INTEGER NOT NULL,"\
623 "labelsettings_id INTEGER);" );
624 runEmptyQuery( query );
627 query =
qgs_sqlite3_mprintf(
"SELECT name FROM sqlite_master WHERE name='legendpatchshapes'" );
628 statement = mCurrentDB.
prepare( query, rc );
629 if ( rc != SQLITE_OK || sqlite3_step( statement.get() ) != SQLITE_ROW )
632 "id INTEGER PRIMARY KEY,"\
635 "favorite INTEGER);"\
636 "CREATE TABLE lpstagmap("\
637 "tag_id INTEGER NOT NULL,"\
638 "legendpatchshape_id INTEGER);" );
639 runEmptyQuery( query );
643 statement = mCurrentDB.
prepare( query, rc );
644 if ( rc != SQLITE_OK || sqlite3_step( statement.get() ) != SQLITE_ROW )
647 "id INTEGER PRIMARY KEY,"\
650 "favorite INTEGER);"\
651 "CREATE TABLE symbol3dtagmap("\
652 "tag_id INTEGER NOT NULL,"\
653 "symbol3d_id INTEGER);" );
654 runEmptyQuery( query );
659 "UPDATE colorramp SET favorite=0 WHERE favorite IS NULL;"
660 "UPDATE textformat SET favorite=0 WHERE favorite IS NULL;"
661 "UPDATE labelsettings SET favorite=0 WHERE favorite IS NULL;"
662 "UPDATE legendpatchshapes SET favorite=0 WHERE favorite IS NULL;"
663 "UPDATE symbol3d SET favorite=0 WHERE favorite IS NULL;"
665 runEmptyQuery( query );
671 statement = mCurrentDB.
prepare( query, rc );
673 while ( rc == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
679 if ( !doc.setContent( xmlstring ) )
685 QDomElement symElement = doc.documentElement();
688 mSymbols.insert( symbolName,
symbol );
695 statement = mCurrentDB.
prepare( query, rc );
696 while ( rc == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
702 if ( !doc.setContent( xmlstring ) )
707 QDomElement rampElement = doc.documentElement();
710 mColorRamps.insert( rampName, ramp );
717 statement = mCurrentDB.
prepare( query, rc );
718 while ( rc == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
724 if ( !doc.setContent( xmlstring ) )
726 QgsDebugMsg(
"Cannot open text format " + formatName );
729 QDomElement formatElement = doc.documentElement();
732 mTextFormats.insert( formatName, format );
739 statement = mCurrentDB.
prepare( query, rc );
740 while ( rc == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
746 if ( !doc.setContent( xmlstring ) )
748 QgsDebugMsg(
"Cannot open label settings " + settingsName );
751 QDomElement settingsElement = doc.documentElement();
754 mLabelSettings.insert( settingsName, settings );
761 statement = mCurrentDB.
prepare( query, rc );
762 while ( rc == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
768 if ( !doc.setContent( xmlstring ) )
770 QgsDebugMsg(
"Cannot open legend patch shape " + settingsName );
773 QDomElement settingsElement = doc.documentElement();
776 mLegendPatchShapes.insert( settingsName, shape );
783 statement = mCurrentDB.
prepare( query, rc );
787 while ( rc == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
793 if ( !doc.setContent( xmlstring ) )
795 QgsDebugMsg(
"Cannot open 3d symbol " + settingsName );
798 QDomElement settingsElement = doc.documentElement();
800 if ( !registry3dPopulated )
802 mDeferred3DsymbolElements.insert( settingsName, settingsElement );
806 const QString symbolType = settingsElement.attribute( QStringLiteral(
"type" ) );
811 m3dSymbols.insert( settingsName,
symbol.release() );
815 QgsDebugMsg(
"Cannot open 3d symbol " + settingsName );
822 mFileName = filename;
830 mErrorString.clear();
832 if ( filename.isEmpty() )
833 filename = mFileName;
838 QDomDocument doc(
"qgis_style" );
839 QDomElement root = doc.createElement(
"qgis_style" );
841 doc.appendChild( root );
845 QDomElement rampsElem = doc.createElement(
"colorramps" );
848 for ( QMap<QString, QgsColorRamp *>::iterator itr = mColorRamps.begin(); itr != mColorRamps.end(); ++itr )
851 rampsElem.appendChild( rampEl );
854 root.appendChild( symbolsElem );
855 root.appendChild( rampsElem );
859 if ( !f.open( QFile::WriteOnly ) )
861 mErrorString =
"Couldn't open file for writing: " + filename;
864 QTextStream ts( &f );
865 ts.setCodec(
"UTF-8" );
870 mFileName = filename;
876 if ( mSymbols.contains( newName ) )
878 QgsDebugMsg( QStringLiteral(
"Symbol of new name already exists" ) );
886 mSymbols.insert( newName,
symbol );
890 QgsDebugMsg( QStringLiteral(
"Sorry! Cannot open database to tag." ) );
897 QgsDebugMsg( QStringLiteral(
"No such symbol for tagging in database: " ) + oldName );
916 if ( mColorRamps.contains( newName ) )
918 QgsDebugMsg( QStringLiteral(
"Color ramp of new name already exists." ) );
926 mColorRamps.insert( newName, ramp );
932 QString query =
qgs_sqlite3_mprintf(
"SELECT id FROM colorramp WHERE name='%q'", oldName.toUtf8().constData() );
934 statement = mCurrentDB.
prepare( query, nErr );
935 if ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
937 rampid = sqlite3_column_int( statement.get(), 0 );
952 QDomDocument doc( QStringLiteral(
"dummy" ) );
955 if ( formatElem.isNull() )
957 QgsDebugMsg( QStringLiteral(
"Couldn't convert text format to valid XML!" ) );
962 QTextStream stream( &xmlArray );
963 stream.setCodec(
"UTF-8" );
964 formatElem.save( stream, 4 );
965 QString query =
qgs_sqlite3_mprintf(
"INSERT INTO textformat VALUES (NULL, '%q', '%q', %d);",
966 name.toUtf8().constData(), xmlArray.constData(), ( favorite ? 1 : 0 ) );
967 if ( !runEmptyQuery( query ) )
969 QgsDebugMsg( QStringLiteral(
"Couldn't insert text format into the database!" ) );
990 if ( mTextFormats.contains( newName ) )
992 QgsDebugMsg( QStringLiteral(
"Text format of new name already exists." ) );
996 if ( !mTextFormats.contains( oldName ) )
1000 mTextFormats.insert( newName, format );
1006 QString query =
qgs_sqlite3_mprintf(
"SELECT id FROM textformat WHERE name='%q'", oldName.toUtf8().constData() );
1008 statement = mCurrentDB.
prepare( query, nErr );
1009 if ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
1011 textFormatId = sqlite3_column_int( statement.get(), 0 );
1026 QDomDocument doc( QStringLiteral(
"dummy" ) );
1029 if ( settingsElem.isNull() )
1031 QgsDebugMsg( QStringLiteral(
"Couldn't convert label settings to valid XML!" ) );
1035 QByteArray xmlArray;
1036 QTextStream stream( &xmlArray );
1037 stream.setCodec(
"UTF-8" );
1038 settingsElem.save( stream, 4 );
1039 QString query =
qgs_sqlite3_mprintf(
"INSERT INTO labelsettings VALUES (NULL, '%q', '%q', %d);",
1040 name.toUtf8().constData(), xmlArray.constData(), ( favorite ? 1 : 0 ) );
1041 if ( !runEmptyQuery( query ) )
1043 QgsDebugMsg( QStringLiteral(
"Couldn't insert label settings into the database!" ) );
1064 if ( mLabelSettings.contains( newName ) )
1066 QgsDebugMsg( QStringLiteral(
"Label settings of new name already exists." ) );
1070 if ( !mLabelSettings.contains( oldName ) )
1074 mLabelSettings.insert( newName, settings );
1080 QString query =
qgs_sqlite3_mprintf(
"SELECT id FROM labelsettings WHERE name='%q'", oldName.toUtf8().constData() );
1082 statement = mCurrentDB.
prepare( query, nErr );
1083 if ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
1100 QDomDocument doc( QStringLiteral(
"dummy" ) );
1101 QDomElement shapeElem = doc.createElement( QStringLiteral(
"shape" ) );
1104 QByteArray xmlArray;
1105 QTextStream stream( &xmlArray );
1106 stream.setCodec(
"UTF-8" );
1107 shapeElem.save( stream, 4 );
1108 QString query =
qgs_sqlite3_mprintf(
"INSERT INTO legendpatchshapes VALUES (NULL, '%q', '%q', %d);",
1109 name.toUtf8().constData(), xmlArray.constData(), ( favorite ? 1 : 0 ) );
1110 if ( !runEmptyQuery( query ) )
1112 QgsDebugMsg( QStringLiteral(
"Couldn't insert legend patch shape into the database!" ) );
1127 if ( mLegendPatchShapes.contains( newName ) )
1129 QgsDebugMsg( QStringLiteral(
"Legend patch shape of new name already exists." ) );
1133 if ( !mLegendPatchShapes.contains( oldName ) )
1137 mLegendPatchShapes.insert( newName, shape );
1143 QString query =
qgs_sqlite3_mprintf(
"SELECT id FROM legendpatchshapes WHERE name='%q'", oldName.toUtf8().constData() );
1145 statement = mCurrentDB.
prepare( query, nErr );
1146 if ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
1164 if ( mDefaultPatchCache[ type ].contains( size ) )
1165 return mDefaultPatchCache[ type ].value( size );
1171 geom =
QgsGeometry( qgis::make_unique< QgsPoint >(
static_cast< int >( size.width() ) / 2,
static_cast< int >( size.height() ) / 2 ) );
1178 double y =
static_cast< int >( size.height() ) / 2 + 0.5;
1179 geom =
QgsGeometry( qgis::make_unique< QgsLineString >( ( QVector< double >() << 0 << size.width() ),
1180 ( QVector< double >() << y << y ) ) );
1186 geom =
QgsGeometry( qgis::make_unique< QgsPolygon >(
1187 new QgsLineString( QVector< double >() << 0 <<
static_cast< int >( size.width() ) <<
static_cast< int >( size.width() ) << 0 << 0,
1188 QVector< double >() <<
static_cast< int >( size.height() ) <<
static_cast< int >( size.height() ) << 0 << 0 <<
static_cast< int >( size.height() ) ) ) );
1197 mDefaultPatchCache[ type ][size ] = res;
1204 return QList<QList<QPolygonF> >();
1206 if ( mDefaultPatchQPolygonFCache[ type ].contains( size ) )
1207 return mDefaultPatchQPolygonFCache[ type ].value( size );
1210 mDefaultPatchQPolygonFCache[ type ][size ] = res;
1217 QDomDocument doc( QStringLiteral(
"dummy" ) );
1218 QDomElement elem = doc.createElement( QStringLiteral(
"symbol" ) );
1219 elem.setAttribute( QStringLiteral(
"type" ),
symbol->
type() );
1222 QByteArray xmlArray;
1223 QTextStream stream( &xmlArray );
1224 stream.setCodec(
"UTF-8" );
1225 elem.save( stream, 4 );
1226 QString query =
qgs_sqlite3_mprintf(
"INSERT INTO symbol3d VALUES (NULL, '%q', '%q', %d);",
1227 name.toUtf8().constData(), xmlArray.constData(), ( favorite ? 1 : 0 ) );
1228 if ( !runEmptyQuery( query ) )
1230 QgsDebugMsg( QStringLiteral(
"Couldn't insert 3d symbol into the database!" ) );
1245 if ( m3dSymbols.contains( newName ) )
1247 QgsDebugMsg( QStringLiteral(
"3d symbol of new name already exists." ) );
1251 if ( !m3dSymbols.contains( oldName ) )
1255 m3dSymbols.insert( newName,
symbol );
1261 QString query =
qgs_sqlite3_mprintf(
"SELECT id FROM symbol3d WHERE name='%q'", oldName.toUtf8().constData() );
1263 statement = mCurrentDB.
prepare( query, nErr );
1264 if ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
1279 return m3dSymbols.keys();
1286 QgsDebugMsg( QStringLiteral(
"Cannot Open database for getting favorite symbols" ) );
1287 return QStringList();
1295 QgsDebugMsg( QStringLiteral(
"No such style entity" ) );
1296 return QStringList();
1299 query =
qgs_sqlite3_mprintf( QStringLiteral(
"SELECT name FROM %1 WHERE favorite=1" ).arg( entityTableName( type ) ).toLocal8Bit().data() );
1305 statement = mCurrentDB.
prepare( query, nErr );
1307 QStringList symbols;
1308 while ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
1320 QgsDebugMsg( QStringLiteral(
"Cannot open database to get symbols of tagid %1" ).arg( tagid ) );
1321 return QStringList();
1329 QgsDebugMsg( QStringLiteral(
"Unknown Entity" ) );
1330 return QStringList();
1333 subquery =
qgs_sqlite3_mprintf( QStringLiteral(
"SELECT %1 FROM %2 WHERE tag_id=%d" ).arg( tagmapEntityIdFieldName( type ),
1334 tagmapTableName( type ) ).toLocal8Bit().data(), tagid );
1340 statement = mCurrentDB.
prepare( subquery, nErr );
1343 QStringList symbols;
1344 while ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
1346 int id = sqlite3_column_int( statement.get(), 0 );
1348 const QString query =
qgs_sqlite3_mprintf( QStringLiteral(
"SELECT name FROM %1 WHERE id=%d" ).arg( entityTableName( type ) ).toLocal8Bit().data(),
id );
1352 statement2 = mCurrentDB.
prepare( query, rc );
1353 while ( rc == SQLITE_OK && sqlite3_step( statement2.get() ) == SQLITE_ROW )
1368 QString query =
qgs_sqlite3_mprintf(
"INSERT INTO tag VALUES (NULL, '%q')", tagname.toUtf8().constData() );
1370 statement = mCurrentDB.
prepare( query, nErr );
1371 if ( nErr == SQLITE_OK )
1372 ( void )sqlite3_step( statement.get() );
1375 settings.
setValue( QStringLiteral(
"qgis/symbolsListGroupsIndex" ), 0 );
1379 return static_cast< int >( sqlite3_last_insert_rowid( mCurrentDB.get() ) );
1385 return QStringList();
1391 statement = mCurrentDB.
prepare( query, nError );
1393 QStringList tagList;
1394 while ( nError == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
1404 const QString query =
qgs_sqlite3_mprintf( QStringLiteral(
"UPDATE %1 SET name='%q' WHERE id=%d" ).arg( entityTableName( type ) ).toLocal8Bit().data(), newName.toUtf8().constData(),
id );
1406 const bool result = runEmptyQuery( query );
1409 mErrorString = QStringLiteral(
"Could not rename!" );
1413 mCachedTags.clear();
1414 mCachedFavorites.clear();
1439 bool groupRemoved =
false;
1444 query =
qgs_sqlite3_mprintf(
"DELETE FROM tag WHERE id=%d; DELETE FROM tagmap WHERE tag_id=%d",
id,
id );
1445 groupRemoved =
true;
1449 groupRemoved =
true;
1453 query =
qgs_sqlite3_mprintf( QStringLiteral(
"DELETE FROM %1 WHERE id=%d; DELETE FROM %2 WHERE %3=%d" ).arg(
1454 entityTableName( type ),
1455 tagmapTableName( type ),
1456 tagmapEntityIdFieldName( type )
1457 ).toLocal8Bit().data(),
id,
id );
1461 bool result =
false;
1462 if ( !runEmptyQuery( query ) )
1464 QgsDebugMsg( QStringLiteral(
"Could not delete entity!" ) );
1468 mCachedTags.clear();
1469 mCachedFavorites.clear();
1474 settings.
setValue( QStringLiteral(
"qgis/symbolsListGroupsIndex" ), 0 );
1493 std::unique_ptr< QgsSymbol >
symbol( mSymbols.take( name ) );
1502 std::unique_ptr< QgsAbstract3DSymbol >
symbol( m3dSymbols.take( name ) );
1511 std::unique_ptr< QgsColorRamp > ramp( mColorRamps.take( name ) );
1519 if ( !mTextFormats.contains( name ) )
1522 mTextFormats.remove( name );
1528 if ( !mLabelSettings.contains( name ) )
1531 mLabelSettings.remove( name );
1537 if ( !mLegendPatchShapes.contains( name ) )
1540 mLegendPatchShapes.remove( name );
1547 QgsDebugMsg( QStringLiteral(
"Sorry! Cannot open database to modify." ) );
1551 const int id =
entityId( type, name );
1554 QgsDebugMsg(
"No matching entity for deleting in database: " + name );
1557 const bool result =
remove( type,
id );
1560 mCachedTags[ type ].remove( name );
1561 mCachedFavorites[ type ].remove( name );
1590 bool QgsStyle::runEmptyQuery(
const QString &query )
1595 char *zErr =
nullptr;
1596 int nErr = sqlite3_exec( mCurrentDB.get(), query.toUtf8().constData(),
nullptr,
nullptr, &zErr );
1598 if ( nErr != SQLITE_OK )
1601 sqlite3_free( zErr );
1604 return nErr == SQLITE_OK;
1615 QgsDebugMsg( QStringLiteral(
"Wrong entity value. cannot apply group" ) );
1619 query =
qgs_sqlite3_mprintf( QStringLiteral(
"UPDATE %1 SET favorite=1 WHERE name='%q'" ).arg( entityTableName( type ) ).toLocal8Bit().data(),
1620 name.toUtf8().constData() );
1624 const bool res = runEmptyQuery( query );
1634 mCachedFavorites[ type ].insert( name,
true );
1651 QgsDebugMsg( QStringLiteral(
"Wrong entity value. cannot apply group" ) );
1655 query =
qgs_sqlite3_mprintf( QStringLiteral(
"UPDATE %1 SET favorite=0 WHERE name='%q'" ).arg( entityTableName( type ) ).toLocal8Bit().data(), name.toUtf8().constData() );
1659 const bool res = runEmptyQuery( query );
1662 mCachedFavorites[ type ].insert( name,
false );
1673 QgsDebugMsg( QStringLiteral(
"Sorry! Cannot open database to search" ) );
1674 return QStringList();
1683 return QStringList();
1686 item = entityTableName( type );
1691 item.toUtf8().constData(), qword.toUtf8().constData() );
1694 int nErr; statement = mCurrentDB.
prepare( query, nErr );
1696 QSet< QString > symbols;
1697 while ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
1703 query =
qgs_sqlite3_mprintf(
"SELECT id FROM tag WHERE name LIKE '%%%q%%'", qword.toUtf8().constData() );
1704 statement = mCurrentDB.
prepare( query, nErr );
1707 while ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
1712 QString dummy = tagids.join( QLatin1String(
", " ) );
1713 query =
qgs_sqlite3_mprintf( QStringLiteral(
"SELECT %1 FROM %2 WHERE tag_id IN (%q)" ).arg( tagmapEntityIdFieldName( type ),
1714 tagmapTableName( type ) ).toLocal8Bit().data(), dummy.toUtf8().constData() );
1716 statement = mCurrentDB.
prepare( query, nErr );
1718 QStringList symbolids;
1719 while ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
1724 dummy = symbolids.join( QLatin1String(
", " ) );
1726 item.toUtf8().constData(), dummy.toUtf8().constData() );
1727 statement = mCurrentDB.
prepare( query, nErr );
1728 while ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
1733 return qgis::setToList( symbols );
1740 QgsDebugMsg( QStringLiteral(
"Sorry! Cannot open database to tag." ) );
1758 QgsDebugMsg( QStringLiteral(
"No such symbol for tagging in database: " ) +
symbol );
1763 const auto constTags =
tags;
1764 for (
const QString &t : constTags )
1767 if ( !
tag.isEmpty() )
1779 QString query =
qgs_sqlite3_mprintf( QStringLiteral(
"INSERT INTO %1 VALUES (%d,%d)" ).arg( tagmapTableName( type ) ).toLocal8Bit().data(), tagid, symbolid );
1781 char *zErr =
nullptr;
1783 nErr = sqlite3_exec( mCurrentDB.get(), query.toUtf8().constData(),
nullptr,
nullptr, &zErr );
1787 sqlite3_free( zErr );
1793 clearCachedTags( type,
symbol );
1803 QgsDebugMsg( QStringLiteral(
"Sorry! Cannot open database for detagging." ) );
1818 if ( symbolid == 0 )
1823 const auto constTags =
tags;
1824 for (
const QString &
tag : constTags )
1829 statement2 = mCurrentDB.
prepare( query, nErr );
1832 if ( nErr == SQLITE_OK && sqlite3_step( statement2.get() ) == SQLITE_ROW )
1834 tagid = sqlite3_column_int( statement2.get(), 0 );
1840 const QString query =
qgs_sqlite3_mprintf( QStringLiteral(
"DELETE FROM %1 WHERE tag_id=%d AND %2=%d" ).arg( tagmapTableName( type ), tagmapEntityIdFieldName( type ) ).toLocal8Bit().data(), tagid, symbolid );
1841 runEmptyQuery( query );
1845 clearCachedTags( type,
symbol );
1858 QgsDebugMsg( QStringLiteral(
"Sorry! Cannot open database for detagging." ) );
1873 if ( symbolid == 0 )
1879 const QString query =
qgs_sqlite3_mprintf( QStringLiteral(
"DELETE FROM %1 WHERE %2=%d" ).arg( tagmapTableName( type ),
1880 tagmapEntityIdFieldName( type ) ).toLocal8Bit().data(), symbolid );
1881 runEmptyQuery( query );
1883 clearCachedTags( type,
symbol );
1898 return QStringList();
1901 if ( mCachedTags[ type ].contains(
symbol ) )
1902 return mCachedTags[ type ].value(
symbol );
1908 QgsDebugMsg( QStringLiteral(
"Sorry! Cannot open database for getting the tags." ) );
1909 return QStringList();
1914 return QStringList();
1917 const QString query =
qgs_sqlite3_mprintf( QStringLiteral(
"SELECT tag_id FROM %1 WHERE %2=%d" ).arg( tagmapTableName( type ),
1918 tagmapEntityIdFieldName( type ) ).toLocal8Bit().data(), symbolid );
1921 int nErr; statement = mCurrentDB.
prepare( query, nErr );
1923 QStringList tagList;
1924 while ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
1926 QString subquery =
qgs_sqlite3_mprintf(
"SELECT name FROM tag WHERE id=%d", sqlite3_column_int( statement.get(), 0 ) );
1930 statement2 = mCurrentDB.
prepare( subquery, pErr );
1931 if ( pErr == SQLITE_OK && sqlite3_step( statement2.get() ) == SQLITE_ROW )
1938 mCachedTags[ type ].insert(
symbol, tagList );
1947 QgsDebugMsg( QStringLiteral(
"Sorry! Cannot open database for getting the tags." ) );
1958 if ( mCachedFavorites[ type ].contains( name ) )
1959 return mCachedFavorites[ type ].value( name );
1963 const QStringList names =
allNames( type );
1964 if ( !names.contains( name ) )
1970 for (
const QString &n : names )
1972 const bool isFav = favorites.contains( n );
1976 mCachedFavorites[ type ].insert( n, isFav );
1985 QgsDebugMsg( QStringLiteral(
"Sorry! Cannot open database for getting the tags." ) );
2012 const QString query =
qgs_sqlite3_mprintf( QStringLiteral(
"SELECT tag_id FROM %1 WHERE tag_id=%d AND %2=%d" ).arg( tagmapTableName( type ),
2013 tagmapEntityIdFieldName( type ) ).toLocal8Bit().data(), tagid, symbolid );
2016 int nErr; statement = mCurrentDB.
prepare( query, nErr );
2018 return ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW );
2030 statement = mCurrentDB.
prepare( query, nError );
2033 if ( nError == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
2041 int QgsStyle::getId(
const QString &table,
const QString &name )
2043 QString lowerName( name.toLower() );
2044 QString query =
qgs_sqlite3_mprintf(
"SELECT id FROM %q WHERE LOWER(name)='%q'", table.toUtf8().constData(), lowerName.toUtf8().constData() );
2047 int nErr; statement = mCurrentDB.
prepare( query, nErr );
2050 if ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
2052 id = sqlite3_column_int( statement.get(), 0 );
2057 QString query =
qgs_sqlite3_mprintf(
"SELECT id FROM %q WHERE name='%q'", table.toUtf8().constData(), name.toUtf8().constData() );
2060 int nErr; statement = mCurrentDB.
prepare( query, nErr );
2061 if ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
2063 id = sqlite3_column_int( statement.get(), 0 );
2070 QString QgsStyle::getName(
const QString &table,
int id )
const
2072 QString query =
qgs_sqlite3_mprintf(
"SELECT name FROM %q WHERE id='%q'", table.toUtf8().constData(), QString::number(
id ).toUtf8().constData() );
2075 int nErr; statement = mCurrentDB.
prepare( query, nErr );
2078 if ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
2088 return getId( QStringLiteral(
"symbol" ), name );
2093 return getId( entityTableName( type ), name );
2098 return getId( QStringLiteral(
"colorramp" ), name );
2103 return mTextFormats.value( name );
2108 return mTextFormats.count();
2113 return mTextFormats.keys();
2118 return getId( QStringLiteral(
"textformat" ), name );
2123 return mLabelSettings.value( name );
2128 return mLegendPatchShapes.value( name );
2133 return mLegendPatchShapes.count();
2138 if ( !mLegendPatchShapes.contains( name ) )
2141 return mLegendPatchShapes.value( name ).symbolType();
2146 return m3dSymbols.contains( name ) ? m3dSymbols.value( name )->clone() :
nullptr;
2151 return m3dSymbols.count();
2156 if ( !m3dSymbols.contains( name ) )
2157 return QList<QgsWkbTypes::GeometryType>();
2159 return m3dSymbols.value( name )->compatibleGeometryTypes();
2164 if ( !mLabelSettings.contains( name ) )
2167 return mLabelSettings.value( name ).layerType;
2172 return mLabelSettings.count();
2177 return mLabelSettings.keys();
2182 return getId( QStringLiteral(
"labelsettings" ), name );
2187 return mLegendPatchShapes.keys();
2195 return mPatchMarkerSymbol.get();
2198 return mPatchLineSymbol.get();
2201 return mPatchFillSymbol.get();
2211 return getId( QStringLiteral(
"tag" ), name );
2216 return getId( QStringLiteral(
"smartgroup" ), name );
2247 return QStringList();
2252 return addSmartgroup( name, op, conditions.values( QStringLiteral(
"tag" ) ),
2253 conditions.values( QStringLiteral(
"!tag" ) ),
2254 conditions.values( QStringLiteral(
"name" ) ),
2255 conditions.values( QStringLiteral(
"!name" ) ) );
2258 int QgsStyle::addSmartgroup(
const QString &name,
const QString &op,
const QStringList &matchTag,
const QStringList &noMatchTag,
const QStringList &matchName,
const QStringList &noMatchName )
2260 QDomDocument doc( QStringLiteral(
"dummy" ) );
2261 QDomElement smartEl = doc.createElement( QStringLiteral(
"smartgroup" ) );
2262 smartEl.setAttribute( QStringLiteral(
"name" ), name );
2263 smartEl.setAttribute( QStringLiteral(
"operator" ), op );
2265 auto addCondition = [&doc, &smartEl](
const QString & constraint,
const QStringList & parameters )
2267 for (
const QString ¶m : parameters )
2269 QDomElement condEl = doc.createElement( QStringLiteral(
"condition" ) );
2270 condEl.setAttribute( QStringLiteral(
"constraint" ), constraint );
2271 condEl.setAttribute( QStringLiteral(
"param" ), param );
2272 smartEl.appendChild( condEl );
2275 addCondition( QStringLiteral(
"tag" ), matchTag );
2276 addCondition( QStringLiteral(
"!tag" ), noMatchTag );
2277 addCondition( QStringLiteral(
"name" ), matchName );
2278 addCondition( QStringLiteral(
"!name" ), noMatchName );
2280 QByteArray xmlArray;
2281 QTextStream stream( &xmlArray );
2282 stream.setCodec(
"UTF-8" );
2283 smartEl.save( stream, 4 );
2285 name.toUtf8().constData(), xmlArray.constData() );
2287 if ( runEmptyQuery( query ) )
2290 settings.
setValue( QStringLiteral(
"qgis/symbolsListGroupsIndex" ), 0 );
2293 return static_cast< int >( sqlite3_last_insert_rowid( mCurrentDB.get() ) );
2297 QgsDebugMsg( QStringLiteral(
"Couldn't insert symbol into the database!" ) );
2306 QgsDebugMsg( QStringLiteral(
"Cannot open database for listing groups" ) );
2315 statement = mCurrentDB.
prepare( query, nError );
2318 while ( nError == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
2321 groupNames.insert( sqlite3_column_int( statement.get(),
SmartgroupId ), group );
2331 QgsDebugMsg( QStringLiteral(
"Cannot open database for listing groups" ) );
2332 return QStringList();
2340 statement = mCurrentDB.
prepare( query, nError );
2343 while ( nError == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
2353 QStringList symbols;
2358 int nErr; statement = mCurrentDB.
prepare( query, nErr );
2359 if ( !( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW ) )
2361 return QStringList();
2367 if ( !doc.setContent( xmlstr ) )
2369 QgsDebugMsg( QStringLiteral(
"Cannot open smartgroup id: %1" ).arg(
id ) );
2371 QDomElement smartEl = doc.documentElement();
2372 QString op = smartEl.attribute( QStringLiteral(
"operator" ) );
2373 QDomNodeList conditionNodes = smartEl.childNodes();
2375 bool firstSet =
true;
2376 for (
int i = 0; i < conditionNodes.count(); i++ )
2378 QDomElement condEl = conditionNodes.at( i ).toElement();
2379 QString constraint = condEl.attribute( QStringLiteral(
"constraint" ) );
2380 QString param = condEl.attribute( QStringLiteral(
"param" ) );
2382 QStringList resultNames;
2384 if ( constraint == QLatin1String(
"tag" ) )
2388 else if ( constraint == QLatin1String(
"name" ) )
2390 resultNames =
allNames( type ).filter( param, Qt::CaseInsensitive );
2392 else if ( constraint == QLatin1String(
"!tag" ) )
2396 for (
const QString &name : unwanted )
2398 resultNames.removeAll( name );
2401 else if ( constraint == QLatin1String(
"!name" ) )
2403 const QStringList all =
allNames( type );
2404 for (
const QString &str : all )
2406 if ( !str.contains( param, Qt::CaseInsensitive ) )
2414 symbols = resultNames;
2419 if ( op == QLatin1String(
"OR" ) )
2421 symbols << resultNames;
2423 else if ( op == QLatin1String(
"AND" ) )
2425 QStringList dummy = symbols;
2427 for (
const QString &result : qgis::as_const( resultNames ) )
2429 if ( dummy.contains( result ) )
2438 QStringList unique = qgis::setToList( qgis::listToSet( symbols ) );
2439 std::sort( unique.begin(), unique.end() );
2447 QgsDebugMsg( QStringLiteral(
"Cannot open database for listing groups" ) );
2457 statement = mCurrentDB.
prepare( query, nError );
2458 if ( nError == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
2462 if ( !doc.setContent( xmlstr ) )
2464 QgsDebugMsg( QStringLiteral(
"Cannot open smartgroup id: %1" ).arg(
id ) );
2467 QDomElement smartEl = doc.documentElement();
2468 QDomNodeList conditionNodes = smartEl.childNodes();
2470 for (
int i = 0; i < conditionNodes.count(); i++ )
2472 QDomElement condEl = conditionNodes.at( i ).toElement();
2473 QString constraint = condEl.attribute( QStringLiteral(
"constraint" ) );
2474 QString param = condEl.attribute( QStringLiteral(
"param" ) );
2476 condition.insert( constraint, param );
2487 QgsDebugMsg( QStringLiteral(
"Cannot open database for listing groups" ) );
2497 statement = mCurrentDB.
prepare( query, nError );
2498 if ( nError == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
2502 if ( !doc.setContent( xmlstr ) )
2504 QgsDebugMsg( QStringLiteral(
"Cannot open smartgroup id: %1" ).arg(
id ) );
2506 QDomElement smartEl = doc.documentElement();
2507 op = smartEl.attribute( QStringLiteral(
"operator" ) );
2515 if ( filename.isEmpty() )
2517 QgsDebugMsg( QStringLiteral(
"Invalid filename for style export." ) );
2521 QDomDocument doc( QStringLiteral(
"qgis_style" ) );
2522 QDomElement root = doc.createElement( QStringLiteral(
"qgis_style" ) );
2524 doc.appendChild( root );
2534 QDomNodeList symbolsList = symbolsElem.elementsByTagName( QStringLiteral(
"symbol" ) );
2535 int nbSymbols = symbolsList.count();
2536 for (
int i = 0; i < nbSymbols; ++i )
2538 QDomElement
symbol = symbolsList.at( i ).toElement();
2539 QString name =
symbol.attribute( QStringLiteral(
"name" ) );
2541 if (
tags.count() > 0 )
2543 symbol.setAttribute( QStringLiteral(
"tags" ),
tags.join(
',' ) );
2545 if ( favoriteSymbols.contains( name ) )
2547 symbol.setAttribute( QStringLiteral(
"favorite" ), QStringLiteral(
"1" ) );
2552 QDomElement rampsElem = doc.createElement( QStringLiteral(
"colorramps" ) );
2553 for ( QMap<QString, QgsColorRamp *>::const_iterator itr = mColorRamps.constBegin(); itr != mColorRamps.constEnd(); ++itr )
2557 if (
tags.count() > 0 )
2559 rampEl.setAttribute( QStringLiteral(
"tags" ),
tags.join(
',' ) );
2561 if ( favoriteColorramps.contains( itr.key() ) )
2563 rampEl.setAttribute( QStringLiteral(
"favorite" ), QStringLiteral(
"1" ) );
2565 rampsElem.appendChild( rampEl );
2569 QDomElement textFormatsElem = doc.createElement( QStringLiteral(
"textformats" ) );
2570 for (
auto it = mTextFormats.constBegin(); it != mTextFormats.constEnd(); ++it )
2572 QDomElement textFormatEl = doc.createElement( QStringLiteral(
"textformat" ) );
2573 textFormatEl.setAttribute( QStringLiteral(
"name" ), it.key() );
2575 textFormatEl.appendChild( textStyleEl );
2577 if (
tags.count() > 0 )
2579 textFormatEl.setAttribute( QStringLiteral(
"tags" ),
tags.join(
',' ) );
2581 if ( favoriteTextFormats.contains( it.key() ) )
2583 textFormatEl.setAttribute( QStringLiteral(
"favorite" ), QStringLiteral(
"1" ) );
2585 textFormatsElem.appendChild( textFormatEl );
2589 QDomElement labelSettingsElem = doc.createElement( QStringLiteral(
"labelsettings" ) );
2590 for (
auto it = mLabelSettings.constBegin(); it != mLabelSettings.constEnd(); ++it )
2592 QDomElement labelSettingsEl = doc.createElement( QStringLiteral(
"labelsetting" ) );
2593 labelSettingsEl.setAttribute( QStringLiteral(
"name" ), it.key() );
2595 labelSettingsEl.appendChild( defEl );
2597 if (
tags.count() > 0 )
2599 labelSettingsEl.setAttribute( QStringLiteral(
"tags" ),
tags.join(
',' ) );
2601 if ( favoriteTextFormats.contains( it.key() ) )
2603 labelSettingsEl.setAttribute( QStringLiteral(
"favorite" ), QStringLiteral(
"1" ) );
2605 labelSettingsElem.appendChild( labelSettingsEl );
2609 QDomElement legendPatchShapesElem = doc.createElement( QStringLiteral(
"legendpatchshapes" ) );
2610 for (
auto it = mLegendPatchShapes.constBegin(); it != mLegendPatchShapes.constEnd(); ++it )
2612 QDomElement legendPatchShapeEl = doc.createElement( QStringLiteral(
"legendpatchshape" ) );
2613 legendPatchShapeEl.setAttribute( QStringLiteral(
"name" ), it.key() );
2614 QDomElement defEl = doc.createElement( QStringLiteral(
"definition" ) );
2616 legendPatchShapeEl.appendChild( defEl );
2618 if (
tags.count() > 0 )
2620 legendPatchShapeEl.setAttribute( QStringLiteral(
"tags" ),
tags.join(
',' ) );
2622 if ( favoriteLegendShapes.contains( it.key() ) )
2624 legendPatchShapeEl.setAttribute( QStringLiteral(
"favorite" ), QStringLiteral(
"1" ) );
2626 legendPatchShapesElem.appendChild( legendPatchShapeEl );
2630 QDomElement symbols3DElem = doc.createElement( QStringLiteral(
"symbols3d" ) );
2631 for (
auto it = m3dSymbols.constBegin(); it != m3dSymbols.constEnd(); ++it )
2633 QDomElement symbolEl = doc.createElement( QStringLiteral(
"symbol3d" ) );
2634 symbolEl.setAttribute( QStringLiteral(
"name" ), it.key() );
2635 QDomElement defEl = doc.createElement( QStringLiteral(
"definition" ) );
2636 defEl.setAttribute( QStringLiteral(
"type" ), it.value()->type() );
2638 symbolEl.appendChild( defEl );
2640 if (
tags.count() > 0 )
2642 symbolEl.setAttribute( QStringLiteral(
"tags" ),
tags.join(
',' ) );
2644 if ( favorite3DSymbols.contains( it.key() ) )
2646 symbolEl.setAttribute( QStringLiteral(
"favorite" ), QStringLiteral(
"1" ) );
2648 symbols3DElem.appendChild( symbolEl );
2651 root.appendChild( symbolsElem );
2652 root.appendChild( rampsElem );
2653 root.appendChild( textFormatsElem );
2654 root.appendChild( labelSettingsElem );
2655 root.appendChild( legendPatchShapesElem );
2656 root.appendChild( symbols3DElem );
2659 QFile f( filename );
2660 if ( !f.open( QFile::WriteOnly | QIODevice::Truncate ) )
2662 mErrorString =
"Couldn't open file for writing: " + filename;
2666 QTextStream ts( &f );
2667 ts.setCodec(
"UTF-8" );
2671 mFileName = filename;
2682 mErrorString = QString();
2683 QDomDocument doc( QStringLiteral(
"style" ) );
2684 QFile f( filename );
2685 if ( !f.open( QFile::ReadOnly ) )
2687 mErrorString = QStringLiteral(
"Unable to open the specified file" );
2688 QgsDebugMsg( QStringLiteral(
"Error opening the style XML file." ) );
2692 if ( !doc.setContent( &f ) )
2694 mErrorString = QStringLiteral(
"Unable to understand the style file: %1" ).arg( filename );
2695 QgsDebugMsg( QStringLiteral(
"XML Parsing error" ) );
2701 QDomElement docEl = doc.documentElement();
2702 if ( docEl.tagName() != QLatin1String(
"qgis_style" ) )
2704 mErrorString =
"Incorrect root tag in style: " + docEl.tagName();
2708 const QString version = docEl.attribute( QStringLiteral(
"version" ) );
2709 if ( version != QLatin1String(
STYLE_CURRENT_VERSION ) && version != QLatin1String(
"0" ) && version != QLatin1String(
"1" ) )
2711 mErrorString =
"Unknown style file version: " + version;
2717 QDomElement symbolsElement = docEl.firstChildElement( QStringLiteral(
"symbols" ) );
2718 QDomElement e = symbolsElement.firstChildElement();
2722 runEmptyQuery( query );
2727 while ( !e.isNull() )
2729 const int entityAddedVersion = e.attribute( QStringLiteral(
"addedVersion" ) ).toInt();
2730 if ( entityAddedVersion != 0 && sinceVersion != -1 && entityAddedVersion <= sinceVersion )
2736 if ( e.tagName() == QLatin1String(
"symbol" ) )
2738 QString name = e.attribute( QStringLiteral(
"name" ) );
2740 if ( e.hasAttribute( QStringLiteral(
"tags" ) ) )
2742 tags = e.attribute( QStringLiteral(
"tags" ) ).split(
',' );
2744 bool favorite =
false;
2745 if ( e.hasAttribute( QStringLiteral(
"favorite" ) ) && e.attribute( QStringLiteral(
"favorite" ) ) == QLatin1String(
"1" ) )
2764 e = e.nextSiblingElement();
2773 for ( QMap<QString, QgsSymbol *>::iterator it = symbols.begin(); it != symbols.end(); ++it )
2780 QDomElement rampsElement = docEl.firstChildElement( QStringLiteral(
"colorramps" ) );
2781 e = rampsElement.firstChildElement();
2782 while ( !e.isNull() )
2784 const int entityAddedVersion = e.attribute( QStringLiteral(
"addedVersion" ) ).toInt();
2785 if ( entityAddedVersion != 0 && sinceVersion != -1 && entityAddedVersion <= sinceVersion )
2791 if ( e.tagName() == QLatin1String(
"colorramp" ) )
2793 QString name = e.attribute( QStringLiteral(
"name" ) );
2795 if ( e.hasAttribute( QStringLiteral(
"tags" ) ) )
2797 tags = e.attribute( QStringLiteral(
"tags" ) ).split(
',' );
2799 bool favorite =
false;
2800 if ( e.hasAttribute( QStringLiteral(
"favorite" ) ) && e.attribute( QStringLiteral(
"favorite" ) ) == QLatin1String(
"1" ) )
2819 e = e.nextSiblingElement();
2825 const QDomElement textFormatElement = docEl.firstChildElement( QStringLiteral(
"textformats" ) );
2826 e = textFormatElement.firstChildElement();
2827 while ( !e.isNull() )
2829 const int entityAddedVersion = e.attribute( QStringLiteral(
"addedVersion" ) ).toInt();
2830 if ( entityAddedVersion != 0 && sinceVersion != -1 && entityAddedVersion <= sinceVersion )
2836 if ( e.tagName() == QLatin1String(
"textformat" ) )
2838 QString name = e.attribute( QStringLiteral(
"name" ) );
2840 if ( e.hasAttribute( QStringLiteral(
"tags" ) ) )
2842 tags = e.attribute( QStringLiteral(
"tags" ) ).split(
',' );
2844 bool favorite =
false;
2845 if ( e.hasAttribute( QStringLiteral(
"favorite" ) ) && e.attribute( QStringLiteral(
"favorite" ) ) == QLatin1String(
"1" ) )
2851 const QDomElement styleElem = e.firstChildElement();
2863 e = e.nextSiblingElement();
2870 const QDomElement labelSettingsElement = docEl.firstChildElement( QStringLiteral(
"labelsettings" ) );
2871 e = labelSettingsElement.firstChildElement();
2872 while ( !e.isNull() )
2874 const int entityAddedVersion = e.attribute( QStringLiteral(
"addedVersion" ) ).toInt();
2875 if ( entityAddedVersion != 0 && sinceVersion != -1 && entityAddedVersion <= sinceVersion )
2881 if ( e.tagName() == QLatin1String(
"labelsetting" ) )
2883 QString name = e.attribute( QStringLiteral(
"name" ) );
2885 if ( e.hasAttribute( QStringLiteral(
"tags" ) ) )
2887 tags = e.attribute( QStringLiteral(
"tags" ) ).split(
',' );
2889 bool favorite =
false;
2890 if ( e.hasAttribute( QStringLiteral(
"favorite" ) ) && e.attribute( QStringLiteral(
"favorite" ) ) == QLatin1String(
"1" ) )
2896 const QDomElement styleElem = e.firstChildElement();
2908 e = e.nextSiblingElement();
2915 const QDomElement legendPatchShapesElement = docEl.firstChildElement( QStringLiteral(
"legendpatchshapes" ) );
2916 e = legendPatchShapesElement.firstChildElement();
2917 while ( !e.isNull() )
2919 const int entityAddedVersion = e.attribute( QStringLiteral(
"addedVersion" ) ).toInt();
2920 if ( entityAddedVersion != 0 && sinceVersion != -1 && entityAddedVersion <= sinceVersion )
2926 if ( e.tagName() == QLatin1String(
"legendpatchshape" ) )
2928 QString name = e.attribute( QStringLiteral(
"name" ) );
2930 if ( e.hasAttribute( QStringLiteral(
"tags" ) ) )
2932 tags = e.attribute( QStringLiteral(
"tags" ) ).split(
',' );
2934 bool favorite =
false;
2935 if ( e.hasAttribute( QStringLiteral(
"favorite" ) ) && e.attribute( QStringLiteral(
"favorite" ) ) == QLatin1String(
"1" ) )
2941 const QDomElement shapeElem = e.firstChildElement();
2953 e = e.nextSiblingElement();
2960 const QDomElement symbols3DElement = docEl.firstChildElement( QStringLiteral(
"symbols3d" ) );
2961 e = symbols3DElement.firstChildElement();
2962 while ( !e.isNull() )
2964 const int entityAddedVersion = e.attribute( QStringLiteral(
"addedVersion" ) ).toInt();
2965 if ( entityAddedVersion != 0 && sinceVersion != -1 && entityAddedVersion <= sinceVersion )
2971 if ( e.tagName() == QLatin1String(
"symbol3d" ) )
2973 QString name = e.attribute( QStringLiteral(
"name" ) );
2975 if ( e.hasAttribute( QStringLiteral(
"tags" ) ) )
2977 tags = e.attribute( QStringLiteral(
"tags" ) ).split(
',' );
2979 bool favorite =
false;
2980 if ( e.hasAttribute( QStringLiteral(
"favorite" ) ) && e.attribute( QStringLiteral(
"favorite" ) ) == QLatin1String(
"1" ) )
2985 const QDomElement symbolElem = e.firstChildElement();
2986 const QString type = symbolElem.attribute( QStringLiteral(
"type" ) );
3003 e = e.nextSiblingElement();
3008 runEmptyQuery( query );
3010 mFileName = filename;
3016 QFileInfo fileInfo( path );
3018 if ( fileInfo.suffix().compare( QLatin1String(
"xml" ), Qt::CaseInsensitive ) != 0 )
3022 if ( !QFile::exists( path ) )
3025 QFile inputFile( path );
3026 if ( !inputFile.open( QIODevice::ReadOnly ) )
3029 QTextStream stream( &inputFile );
3030 const QString line = stream.readLine();
3031 return line == QLatin1String(
"<!DOCTYPE qgis_style>" );
3034 bool QgsStyle::updateSymbol( StyleEntity type,
const QString &name )
3036 QDomDocument doc( QStringLiteral(
"dummy" ) );
3038 QByteArray xmlArray;
3039 QTextStream stream( &xmlArray );
3040 stream.setCodec(
"UTF-8" );
3051 QgsDebugMsg( QStringLiteral(
"Update request received for unavailable symbol" ) );
3056 if ( symEl.isNull() )
3058 QgsDebugMsg( QStringLiteral(
"Couldn't convert symbol to valid XML!" ) );
3061 symEl.save( stream, 4 );
3063 xmlArray.constData(), name.toUtf8().constData() );
3072 QgsDebugMsg( QStringLiteral(
"Update request received for unavailable symbol" ) );
3076 symEl = doc.createElement( QStringLiteral(
"symbol" ) );
3077 symEl.setAttribute( QStringLiteral(
"type" ), m3dSymbols.value( name )->type() );
3079 if ( symEl.isNull() )
3081 QgsDebugMsg( QStringLiteral(
"Couldn't convert symbol to valid XML!" ) );
3084 symEl.save( stream, 4 );
3086 xmlArray.constData(), name.toUtf8().constData() );
3094 QgsDebugMsg( QStringLiteral(
"Update requested for unavailable color ramp." ) );
3098 std::unique_ptr< QgsColorRamp > ramp(
colorRamp( name ) );
3100 if ( symEl.isNull() )
3102 QgsDebugMsg( QStringLiteral(
"Couldn't convert color ramp to valid XML!" ) );
3105 symEl.save( stream, 4 );
3107 xmlArray.constData(), name.toUtf8().constData() );
3115 QgsDebugMsg( QStringLiteral(
"Update requested for unavailable text format." ) );
3121 if ( symEl.isNull() )
3123 QgsDebugMsg( QStringLiteral(
"Couldn't convert text format to valid XML!" ) );
3126 symEl.save( stream, 4 );
3128 xmlArray.constData(), name.toUtf8().constData() );
3136 QgsDebugMsg( QStringLiteral(
"Update requested for unavailable label settings." ) );
3142 if ( symEl.isNull() )
3144 QgsDebugMsg( QStringLiteral(
"Couldn't convert label settings to valid XML!" ) );
3147 symEl.save( stream, 4 );
3149 xmlArray.constData(), name.toUtf8().constData() );
3157 QgsDebugMsg( QStringLiteral(
"Update requested for unavailable legend patch shape." ) );
3162 symEl = doc.createElement( QStringLiteral(
"shape" ) );
3164 symEl.save( stream, 4 );
3166 xmlArray.constData(), name.toUtf8().constData() );
3173 QgsDebugMsg( QStringLiteral(
"Updating the unsupported StyleEntity" ) );
3179 if ( !runEmptyQuery( query ) )
3181 QgsDebugMsg( QStringLiteral(
"Couldn't insert symbol into the database!" ) );
3217 mCachedTags[ type ].remove( name );
3220 void QgsStyle::upgradeIfRequired()
3223 QString query =
qgs_sqlite3_mprintf(
"SELECT name FROM sqlite_master WHERE name='stylemetadata'" );
3227 statement = mCurrentDB.
prepare( query, rc );
3229 if ( rc != SQLITE_OK || sqlite3_step( statement.get() ) != SQLITE_ROW )
3233 "id INTEGER PRIMARY KEY,"\
3236 runEmptyQuery( query );
3237 query =
qgs_sqlite3_mprintf(
"INSERT INTO stylemetadata VALUES (NULL, '%q', '%q')",
"version",
"31200" );
3238 runEmptyQuery( query );
3245 statement = mCurrentDB.
prepare( query, rc );
3246 if ( rc == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
3258 runEmptyQuery( query );
3268 return QStringLiteral(
"symbol" );
3271 return QStringLiteral(
"colorramp" );
3274 return QStringLiteral(
"textformat" );
3277 return QStringLiteral(
"labelsettings" );
3280 return QStringLiteral(
"legendpatchshapes" );
3283 return QStringLiteral(
"symbol3d" );
3286 return QStringLiteral(
"tag" );
3289 return QStringLiteral(
"smartgroup" );
3299 return QStringLiteral(
"tagmap" );
3302 return QStringLiteral(
"ctagmap" );
3305 return QStringLiteral(
"tftagmap" );
3308 return QStringLiteral(
"lstagmap" );
3311 return QStringLiteral(
"lpstagmap" );
3314 return QStringLiteral(
"symbol3dtagmap" );
3328 return QStringLiteral(
"symbol_id" );
3331 return QStringLiteral(
"colorramp_id" );
3334 return QStringLiteral(
"textformat_id" );
3337 return QStringLiteral(
"labelsettings_id" );
3340 return QStringLiteral(
"legendpatchshape_id" );
3343 return QStringLiteral(
"symbol3d_id" );