mirror of
https://github.com/qgis/QGIS.git
synced 2025-03-02 00:02:12 -05:00
Partial 3d symbol style manager work
This commit is contained in:
parent
0ec238b703
commit
6e40962510
@ -96,6 +96,7 @@ Constructor for QgsStyle.
|
||||
TextFormatEntity,
|
||||
LabelSettingsEntity,
|
||||
LegendPatchShapeEntity,
|
||||
Symbol3DEntity,
|
||||
};
|
||||
|
||||
bool addEntity( const QString &name, const QgsStyleEntityInterface *entity, bool update = false );
|
||||
@ -186,6 +187,21 @@ Returns ``True`` if the operation was successful.
|
||||
Adding legend patch shapes with the name of existing ones replaces them.
|
||||
|
||||
.. versionadded:: 3.14
|
||||
%End
|
||||
|
||||
bool addSymbol3D( const QString &name, QgsAbstract3DSymbol *symbol /Transfer/, bool update = false );
|
||||
%Docstring
|
||||
Adds a 3d ``symbol`` with the specified ``name`` to the style. Ownership of ``symbol`` is transferred.
|
||||
|
||||
If ``update`` is set to ``True``, the style database will be automatically updated with the new legend patch shape.
|
||||
|
||||
Returns ``True`` if the operation was successful.
|
||||
|
||||
.. note::
|
||||
|
||||
Adding 3d symbols with the name of existing ones replaces them.
|
||||
|
||||
.. versionadded:: 3.16
|
||||
%End
|
||||
|
||||
int addTag( const QString &tagName );
|
||||
@ -311,6 +327,29 @@ with the specified ``name``, or QgsSymbol.Hybrid
|
||||
if a matching legend patch shape is not present.
|
||||
|
||||
.. versionadded:: 3.14
|
||||
%End
|
||||
|
||||
QgsAbstract3DSymbol *symbol3D( const QString &name ) const /Factory/;
|
||||
%Docstring
|
||||
Returns a new copy of the 3D symbol with the specified ``name``.
|
||||
|
||||
.. versionadded:: 3.16
|
||||
%End
|
||||
|
||||
int symbol3DCount() const;
|
||||
%Docstring
|
||||
Returns count of 3D symbols in the style.
|
||||
|
||||
.. versionadded:: 3.16
|
||||
%End
|
||||
|
||||
QString symbol3DType( const QString &name ) const;
|
||||
%Docstring
|
||||
Returns the symbol type corresponding to the 3d symbol
|
||||
with the specified ``name``, or an empty string
|
||||
if a matching 3d symbol is not present.
|
||||
|
||||
.. versionadded:: 3.16
|
||||
%End
|
||||
|
||||
QgsWkbTypes::GeometryType labelSettingsLayerType( const QString &name ) const;
|
||||
@ -663,6 +702,34 @@ Returns the default patch geometry for the given symbol ``type`` and ``size`` as
|
||||
.. seealso:: :py:func:`defaultPatch`
|
||||
|
||||
.. versionadded:: 3.14
|
||||
%End
|
||||
|
||||
bool saveSymbol3D( const QString &name, QgsAbstract3DSymbol *symbol /Transfer/, bool favorite, const QStringList &tags );
|
||||
%Docstring
|
||||
Adds a 3d ``symbol`` to the database.
|
||||
|
||||
:param name: is the name of the 3d symbol
|
||||
:param symbol: 3d symbol to save. Ownership is transferred.
|
||||
:param favorite: is a boolean value to specify whether the 3d symbol should be added to favorites
|
||||
:param tags: is a list of tags that are associated with the 3d symbol
|
||||
|
||||
:return: returns the success state of the save operation
|
||||
|
||||
.. versionadded:: 3.16
|
||||
%End
|
||||
|
||||
bool renameSymbol3D( const QString &oldName, const QString &newName );
|
||||
%Docstring
|
||||
Changes a 3d symbol's name.
|
||||
|
||||
.. versionadded:: 3.16
|
||||
%End
|
||||
|
||||
QStringList symbol3DNames() const;
|
||||
%Docstring
|
||||
Returns a list of names of 3d symbols in the style.
|
||||
|
||||
.. versionadded:: 3.16
|
||||
%End
|
||||
|
||||
bool createDatabase( const QString &filename );
|
||||
@ -1241,6 +1308,36 @@ Returns the entity's legend patch shape.
|
||||
|
||||
};
|
||||
|
||||
class QgsStyleSymbol3DEntity : QgsStyleEntityInterface
|
||||
{
|
||||
%Docstring
|
||||
A 3d symbol entity for QgsStyle databases.
|
||||
|
||||
.. versionadded:: 3.16
|
||||
%End
|
||||
|
||||
%TypeHeaderCode
|
||||
#include "qgsstyle.h"
|
||||
%End
|
||||
public:
|
||||
|
||||
QgsStyleSymbol3DEntity( const QgsAbstract3DSymbol *symbol );
|
||||
%Docstring
|
||||
Constructor for QgsStyleSymbol3DEntity, with the specified ``symbol``.
|
||||
|
||||
Ownership of ``symbol`` is NOT transferred.
|
||||
%End
|
||||
|
||||
virtual QgsStyle::StyleEntity type() const;
|
||||
|
||||
|
||||
const QgsAbstract3DSymbol *symbol() const;
|
||||
%Docstring
|
||||
Returns the entity's symbol.
|
||||
%End
|
||||
|
||||
};
|
||||
|
||||
/************************************************************************
|
||||
* This file has been generated automatically from *
|
||||
* *
|
||||
|
@ -29,6 +29,8 @@
|
||||
#include "qgslinesymbollayer.h"
|
||||
#include "qgsfillsymbollayer.h"
|
||||
#include "qgsruntimeprofiler.h"
|
||||
#include "qgsabstract3dsymbol.h"
|
||||
#include "qgs3dsymbolregistry.h"
|
||||
|
||||
#include <QDomDocument>
|
||||
#include <QDomElement>
|
||||
@ -54,6 +56,17 @@ enum LegendPatchTable
|
||||
LegendPatchTableFavoriteId, //!< Legend patch is favorite flag
|
||||
};
|
||||
|
||||
/**
|
||||
* Columns available in the 3d symbol table.
|
||||
*/
|
||||
enum Symbol3DTable
|
||||
{
|
||||
Symbol3DTableId, //!< 3d symbol ID
|
||||
Symbol3DTableName, //!< 3d symbol name
|
||||
Symbol3DTableXML, //!< 3d symbol definition (as XML)
|
||||
Symbol3DTableFavoriteId, //!< 3d symbol is favorite flag
|
||||
};
|
||||
|
||||
|
||||
QgsStyle *QgsStyle::sDefaultStyle = nullptr;
|
||||
|
||||
@ -100,6 +113,9 @@ bool QgsStyle::addEntity( const QString &name, const QgsStyleEntityInterface *en
|
||||
case LegendPatchShapeEntity:
|
||||
return addLegendPatchShape( name, static_cast< const QgsStyleLegendPatchShapeEntity * >( entity )->shape(), update );
|
||||
|
||||
case Symbol3DEntity:
|
||||
return addSymbol3D( name, static_cast< const QgsStyleSymbol3DEntity * >( entity )->symbol()->clone(), update );
|
||||
|
||||
case TagEntity:
|
||||
case SmartgroupEntity:
|
||||
break;
|
||||
@ -147,10 +163,12 @@ void QgsStyle::clear()
|
||||
{
|
||||
qDeleteAll( mSymbols );
|
||||
qDeleteAll( mColorRamps );
|
||||
qDeleteAll( m3dSymbols );
|
||||
|
||||
mSymbols.clear();
|
||||
mColorRamps.clear();
|
||||
mTextFormats.clear();
|
||||
m3dSymbols.clear();
|
||||
|
||||
mCachedTags.clear();
|
||||
mCachedFavorites.clear();
|
||||
@ -238,6 +256,9 @@ bool QgsStyle::renameEntity( QgsStyle::StyleEntity type, const QString &oldName,
|
||||
case LegendPatchShapeEntity:
|
||||
return renameLegendPatchShape( oldName, newName );
|
||||
|
||||
case Symbol3DEntity:
|
||||
return renameSymbol3D( oldName, newName );
|
||||
|
||||
case TagEntity:
|
||||
case SmartgroupEntity:
|
||||
return false;
|
||||
@ -354,6 +375,27 @@ bool QgsStyle::addLegendPatchShape( const QString &name, const QgsLegendPatchSha
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QgsStyle::addSymbol3D( const QString &name, QgsAbstract3DSymbol *symbol, bool update )
|
||||
{
|
||||
// delete previous symbol (if any)
|
||||
if ( m3dSymbols.contains( name ) )
|
||||
{
|
||||
// TODO remove groups and tags?
|
||||
delete m3dSymbols.take( name );
|
||||
m3dSymbols.insert( name, symbol );
|
||||
if ( update )
|
||||
updateSymbol( Symbol3DEntity, name );
|
||||
}
|
||||
else
|
||||
{
|
||||
m3dSymbols.insert( name, symbol );
|
||||
if ( update )
|
||||
saveSymbol3D( name, symbol, false, QStringList() );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QgsStyle::saveColorRamp( const QString &name, QgsColorRamp *ramp, bool favorite, const QStringList &tags )
|
||||
{
|
||||
// insert it into the database
|
||||
@ -483,6 +525,11 @@ void QgsStyle::createTables()
|
||||
"name TEXT UNIQUE,"\
|
||||
"xml TEXT,"\
|
||||
"favorite INTEGER);"\
|
||||
"CREATE TABLE symbol3d("\
|
||||
"id INTEGER PRIMARY KEY,"\
|
||||
"name TEXT UNIQUE,"\
|
||||
"xml TEXT,"\
|
||||
"favorite INTEGER);"\
|
||||
"CREATE TABLE tag("\
|
||||
"id INTEGER PRIMARY KEY,"\
|
||||
"name TEXT);"\
|
||||
@ -501,6 +548,9 @@ void QgsStyle::createTables()
|
||||
"CREATE TABLE lpstagmap("\
|
||||
"tag_id INTEGER NOT NULL,"\
|
||||
"legendpatchshape_id INTEGER);"\
|
||||
"CREATE TABLE symbol3dtagmap("\
|
||||
"tag_id INTEGER NOT NULL,"\
|
||||
"symbol3d_id INTEGER);"\
|
||||
"CREATE TABLE smartgroup("\
|
||||
"id INTEGER PRIMARY KEY,"\
|
||||
"name TEXT,"\
|
||||
@ -567,6 +617,21 @@ bool QgsStyle::load( const QString &filename )
|
||||
"legendpatchshape_id INTEGER);" );
|
||||
runEmptyQuery( query );
|
||||
}
|
||||
// make sure 3d symbol table exists
|
||||
query = QgsSqlite3Mprintf( "SELECT name FROM sqlite_master WHERE name='symbol3d'" );
|
||||
statement = mCurrentDB.prepare( query, rc );
|
||||
if ( rc != SQLITE_OK || sqlite3_step( statement.get() ) != SQLITE_ROW )
|
||||
{
|
||||
query = QgsSqlite3Mprintf( "CREATE TABLE symbol3d("\
|
||||
"id INTEGER PRIMARY KEY,"\
|
||||
"name TEXT UNIQUE,"\
|
||||
"xml TEXT,"\
|
||||
"favorite INTEGER);"\
|
||||
"CREATE TABLE symbol3dtagmap("\
|
||||
"tag_id INTEGER NOT NULL,"\
|
||||
"symbol3d_id INTEGER);" );
|
||||
runEmptyQuery( query );
|
||||
}
|
||||
|
||||
// Make sure there are no Null fields in parenting symbols and groups
|
||||
query = QgsSqlite3Mprintf( "UPDATE symbol SET favorite=0 WHERE favorite IS NULL;"
|
||||
@ -574,6 +639,7 @@ bool QgsStyle::load( const QString &filename )
|
||||
"UPDATE textformat SET favorite=0 WHERE favorite IS NULL;"
|
||||
"UPDATE labelsettings SET favorite=0 WHERE favorite IS NULL;"
|
||||
"UPDATE legendpatchshapes SET favorite=0 WHERE favorite IS NULL;"
|
||||
"UPDATE symbol3d SET favorite=0 WHERE favorite IS NULL;"
|
||||
);
|
||||
runEmptyQuery( query );
|
||||
|
||||
@ -690,6 +756,38 @@ bool QgsStyle::load( const QString &filename )
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
QgsScopedRuntimeProfile profile( tr( "Load 3d symbols shapes" ) );
|
||||
query = QgsSqlite3Mprintf( "SELECT * FROM symbol3d" );
|
||||
statement = mCurrentDB.prepare( query, rc );
|
||||
while ( rc == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
|
||||
{
|
||||
QDomDocument doc;
|
||||
const QString settingsName = statement.columnAsText( Symbol3DTableName );
|
||||
QgsScopedRuntimeProfile profile( settingsName );
|
||||
const QString xmlstring = statement.columnAsText( Symbol3DTableXML );
|
||||
if ( !doc.setContent( xmlstring ) )
|
||||
{
|
||||
QgsDebugMsg( "Cannot open 3d symbol " + settingsName );
|
||||
continue;
|
||||
}
|
||||
QDomElement settingsElement = doc.documentElement();
|
||||
|
||||
const QString symbolType = settingsElement.attribute( QStringLiteral( "type" ) );
|
||||
std::unique_ptr< QgsAbstract3DSymbol > symbol( QgsApplication::symbol3DRegistry()->createSymbol( symbolType ) );
|
||||
if ( symbol )
|
||||
{
|
||||
symbol->readXml( settingsElement, QgsReadWriteContext() );
|
||||
m3dSymbols.insert( settingsName, symbol.release() );
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsDebugMsg( "Cannot open 3d symbol " + settingsName );
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mFileName = filename;
|
||||
return true;
|
||||
}
|
||||
@ -1082,6 +1180,74 @@ QList<QList<QPolygonF> > QgsStyle::defaultPatchAsQPolygonF( QgsSymbol::SymbolTyp
|
||||
return res;
|
||||
}
|
||||
|
||||
bool QgsStyle::saveSymbol3D( const QString &name, QgsAbstract3DSymbol *symbol, bool favorite, const QStringList &tags )
|
||||
{
|
||||
// insert it into the database
|
||||
QDomDocument doc( QStringLiteral( "dummy" ) );
|
||||
QDomElement elem = doc.createElement( QStringLiteral( "symbol" ) );
|
||||
elem.setAttribute( QStringLiteral( "type" ), symbol->type() );
|
||||
symbol->writeXml( elem, QgsReadWriteContext() );
|
||||
|
||||
QByteArray xmlArray;
|
||||
QTextStream stream( &xmlArray );
|
||||
stream.setCodec( "UTF-8" );
|
||||
elem.save( stream, 4 );
|
||||
auto query = QgsSqlite3Mprintf( "INSERT INTO symbol3d VALUES (NULL, '%q', '%q', %d);",
|
||||
name.toUtf8().constData(), xmlArray.constData(), ( favorite ? 1 : 0 ) );
|
||||
if ( !runEmptyQuery( query ) )
|
||||
{
|
||||
QgsDebugMsg( QStringLiteral( "Couldn't insert 3d symbol into the database!" ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
mCachedFavorites[ Symbol3DEntity ].insert( name, favorite );
|
||||
|
||||
tagSymbol( Symbol3DEntity, name, tags );
|
||||
|
||||
emit entityAdded( Symbol3DEntity, name );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QgsStyle::renameSymbol3D( const QString &oldName, const QString &newName )
|
||||
{
|
||||
if ( m3dSymbols.contains( newName ) )
|
||||
{
|
||||
QgsDebugMsg( QStringLiteral( "3d symbol of new name already exists." ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !m3dSymbols.contains( oldName ) )
|
||||
return false;
|
||||
QgsAbstract3DSymbol *symbol = m3dSymbols.take( oldName );
|
||||
|
||||
m3dSymbols.insert( newName, symbol );
|
||||
mCachedTags[Symbol3DEntity ].remove( oldName );
|
||||
mCachedFavorites[ Symbol3DEntity ].remove( oldName );
|
||||
|
||||
int labelSettingsId = 0;
|
||||
sqlite3_statement_unique_ptr statement;
|
||||
auto query = QgsSqlite3Mprintf( "SELECT id FROM symbol3d WHERE name='%q'", oldName.toUtf8().constData() );
|
||||
int nErr;
|
||||
statement = mCurrentDB.prepare( query, nErr );
|
||||
if ( nErr == SQLITE_OK && sqlite3_step( statement.get() ) == SQLITE_ROW )
|
||||
{
|
||||
labelSettingsId = sqlite3_column_int( statement.get(), 0 );
|
||||
}
|
||||
const bool result = rename( Symbol3DEntity, labelSettingsId, newName );
|
||||
if ( result )
|
||||
{
|
||||
emit entityRenamed( Symbol3DEntity, oldName, newName );
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
QStringList QgsStyle::symbol3DNames() const
|
||||
{
|
||||
return m3dSymbols.keys();
|
||||
}
|
||||
|
||||
QStringList QgsStyle::symbolsOfFavorite( StyleEntity type ) const
|
||||
{
|
||||
if ( !mCurrentDB )
|
||||
@ -1300,6 +1466,15 @@ bool QgsStyle::removeEntityByName( QgsStyle::StyleEntity type, const QString &na
|
||||
break;
|
||||
}
|
||||
|
||||
case QgsStyle::Symbol3DEntity:
|
||||
{
|
||||
std::unique_ptr< QgsAbstract3DSymbol > symbol( m3dSymbols.take( name ) );
|
||||
if ( !symbol )
|
||||
return false;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case QgsStyle::ColorrampEntity:
|
||||
{
|
||||
std::unique_ptr< QgsColorRamp > ramp( mColorRamps.take( name ) );
|
||||
@ -1935,6 +2110,24 @@ QgsSymbol::SymbolType QgsStyle::legendPatchShapeSymbolType( const QString &name
|
||||
return mLegendPatchShapes.value( name ).symbolType();
|
||||
}
|
||||
|
||||
QgsAbstract3DSymbol *QgsStyle::symbol3D( const QString &name ) const
|
||||
{
|
||||
return m3dSymbols.contains( name ) ? m3dSymbols.value( name )->clone() : nullptr;
|
||||
}
|
||||
|
||||
int QgsStyle::symbol3DCount() const
|
||||
{
|
||||
return m3dSymbols.count();
|
||||
}
|
||||
|
||||
QString QgsStyle::symbol3DType( const QString &name ) const
|
||||
{
|
||||
if ( !m3dSymbols.contains( name ) )
|
||||
return QString();
|
||||
|
||||
return m3dSymbols.value( name )->type();
|
||||
}
|
||||
|
||||
QgsWkbTypes::GeometryType QgsStyle::labelSettingsLayerType( const QString &name ) const
|
||||
{
|
||||
if ( !mLabelSettings.contains( name ) )
|
||||
@ -2011,6 +2204,9 @@ QStringList QgsStyle::allNames( QgsStyle::StyleEntity type ) const
|
||||
case LegendPatchShapeEntity:
|
||||
return legendPatchShapeNames();
|
||||
|
||||
case Symbol3DEntity:
|
||||
return symbol3DNames();
|
||||
|
||||
case TagEntity:
|
||||
return tags();
|
||||
|
||||
@ -2299,6 +2495,8 @@ bool QgsStyle::exportXml( const QString &filename )
|
||||
const QStringList favoriteSymbols = symbolsOfFavorite( SymbolEntity );
|
||||
const QStringList favoriteColorramps = symbolsOfFavorite( ColorrampEntity );
|
||||
const QStringList favoriteTextFormats = symbolsOfFavorite( TextFormatEntity );
|
||||
const QStringList favoriteLegendShapes = symbolsOfFavorite( LegendPatchShapeEntity );
|
||||
const QStringList favorite3DSymbols = symbolsOfFavorite( Symbol3DEntity );
|
||||
|
||||
// save symbols and attach tags
|
||||
QDomElement symbolsElem = QgsSymbolLayerUtils::saveSymbols( mSymbols, QStringLiteral( "symbols" ), doc, QgsReadWriteContext() );
|
||||
@ -2390,18 +2588,41 @@ bool QgsStyle::exportXml( const QString &filename )
|
||||
{
|
||||
legendPatchShapeEl.setAttribute( QStringLiteral( "tags" ), tags.join( ',' ) );
|
||||
}
|
||||
if ( favoriteTextFormats.contains( it.key() ) )
|
||||
if ( favoriteLegendShapes.contains( it.key() ) )
|
||||
{
|
||||
legendPatchShapeEl.setAttribute( QStringLiteral( "favorite" ), QStringLiteral( "1" ) );
|
||||
}
|
||||
legendPatchShapesElem.appendChild( legendPatchShapeEl );
|
||||
}
|
||||
|
||||
// save symbols and attach tags
|
||||
QDomElement symbols3DElem = doc.createElement( QStringLiteral( "symbols3d" ) );
|
||||
for ( auto it = m3dSymbols.constBegin(); it != m3dSymbols.constEnd(); ++it )
|
||||
{
|
||||
QDomElement symbolEl = doc.createElement( QStringLiteral( "symbol3d" ) );
|
||||
symbolEl.setAttribute( QStringLiteral( "name" ), it.key() );
|
||||
QDomElement defEl = doc.createElement( QStringLiteral( "definition" ) );
|
||||
defEl.setAttribute( QStringLiteral( "type" ), it.value()->type() );
|
||||
it.value()->writeXml( defEl, QgsReadWriteContext() );
|
||||
symbolEl.appendChild( defEl );
|
||||
QStringList tags = tagsOfSymbol( Symbol3DEntity, it.key() );
|
||||
if ( tags.count() > 0 )
|
||||
{
|
||||
symbolEl.setAttribute( QStringLiteral( "tags" ), tags.join( ',' ) );
|
||||
}
|
||||
if ( favorite3DSymbols.contains( it.key() ) )
|
||||
{
|
||||
symbolEl.setAttribute( QStringLiteral( "favorite" ), QStringLiteral( "1" ) );
|
||||
}
|
||||
symbols3DElem.appendChild( symbolEl );
|
||||
}
|
||||
|
||||
root.appendChild( symbolsElem );
|
||||
root.appendChild( rampsElem );
|
||||
root.appendChild( textFormatsElem );
|
||||
root.appendChild( labelSettingsElem );
|
||||
root.appendChild( legendPatchShapesElem );
|
||||
root.appendChild( symbols3DElem );
|
||||
|
||||
// save
|
||||
QFile f( filename );
|
||||
@ -2702,6 +2923,56 @@ bool QgsStyle::importXml( const QString &filename, int sinceVersion )
|
||||
}
|
||||
}
|
||||
|
||||
// load 3d symbols
|
||||
if ( version == STYLE_CURRENT_VERSION )
|
||||
{
|
||||
const QDomElement symbols3DElement = docEl.firstChildElement( QStringLiteral( "symbols3d" ) );
|
||||
e = symbols3DElement.firstChildElement();
|
||||
while ( !e.isNull() )
|
||||
{
|
||||
const int entityAddedVersion = e.attribute( QStringLiteral( "addedVersion" ) ).toInt();
|
||||
if ( entityAddedVersion != 0 && sinceVersion != -1 && entityAddedVersion <= sinceVersion )
|
||||
{
|
||||
// skip the symbol, should already be present
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( e.tagName() == QLatin1String( "symbol3d" ) )
|
||||
{
|
||||
QString name = e.attribute( QStringLiteral( "name" ) );
|
||||
QStringList tags;
|
||||
if ( e.hasAttribute( QStringLiteral( "tags" ) ) )
|
||||
{
|
||||
tags = e.attribute( QStringLiteral( "tags" ) ).split( ',' );
|
||||
}
|
||||
bool favorite = false;
|
||||
if ( e.hasAttribute( QStringLiteral( "favorite" ) ) && e.attribute( QStringLiteral( "favorite" ) ) == QStringLiteral( "1" ) )
|
||||
{
|
||||
favorite = true;
|
||||
}
|
||||
|
||||
const QDomElement symbolElem = e.firstChildElement();
|
||||
const QString type = symbolElem.attribute( QStringLiteral( "type" ) );
|
||||
std::unique_ptr< QgsAbstract3DSymbol > sym( QgsApplication::symbol3DRegistry()->createSymbol( type ) );
|
||||
if ( sym )
|
||||
{
|
||||
sym->readXml( symbolElem, QgsReadWriteContext() );
|
||||
QgsAbstract3DSymbol *newSym = sym.get();
|
||||
addSymbol3D( name, sym.release() );
|
||||
if ( mCurrentDB )
|
||||
{
|
||||
saveSymbol3D( name, newSym, favorite, tags );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsDebugMsg( "unknown tag: " + e.tagName() );
|
||||
}
|
||||
e = e.nextSiblingElement();
|
||||
}
|
||||
}
|
||||
|
||||
query = QgsSqlite3Mprintf( "COMMIT TRANSACTION;" );
|
||||
runEmptyQuery( query );
|
||||
|
||||
@ -2762,6 +3033,29 @@ bool QgsStyle::updateSymbol( StyleEntity type, const QString &name )
|
||||
break;
|
||||
}
|
||||
|
||||
case Symbol3DEntity:
|
||||
{
|
||||
// check if it is an existing symbol
|
||||
if ( !symbol3DNames().contains( name ) )
|
||||
{
|
||||
QgsDebugMsg( QStringLiteral( "Update request received for unavailable symbol" ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
symEl = doc.createElement( QStringLiteral( "symbol" ) );
|
||||
symEl.setAttribute( QStringLiteral( "type" ), m3dSymbols.value( name )->type() );
|
||||
m3dSymbols.value( name )->writeXml( symEl, QgsReadWriteContext() );
|
||||
if ( symEl.isNull() )
|
||||
{
|
||||
QgsDebugMsg( QStringLiteral( "Couldn't convert symbol to valid XML!" ) );
|
||||
return false;
|
||||
}
|
||||
symEl.save( stream, 4 );
|
||||
query = QgsSqlite3Mprintf( "UPDATE symbol3d SET xml='%q' WHERE name='%q';",
|
||||
xmlArray.constData(), name.toUtf8().constData() );
|
||||
break;
|
||||
}
|
||||
|
||||
case ColorrampEntity:
|
||||
{
|
||||
if ( !colorRampNames().contains( name ) )
|
||||
@ -2879,6 +3173,7 @@ bool QgsStyle::updateSymbol( StyleEntity type, const QString &name )
|
||||
case LegendPatchShapeEntity:
|
||||
case TagEntity:
|
||||
case SmartgroupEntity:
|
||||
case Symbol3DEntity:
|
||||
break;
|
||||
}
|
||||
emit entityChanged( type, name );
|
||||
@ -2953,6 +3248,9 @@ QString QgsStyle::entityTableName( QgsStyle::StyleEntity type )
|
||||
case LegendPatchShapeEntity:
|
||||
return QStringLiteral( "legendpatchshapes" );
|
||||
|
||||
case Symbol3DEntity:
|
||||
return QStringLiteral( "symbol3d" );
|
||||
|
||||
case TagEntity:
|
||||
return QStringLiteral( "tag" );
|
||||
|
||||
@ -2981,6 +3279,9 @@ QString QgsStyle::tagmapTableName( QgsStyle::StyleEntity type )
|
||||
case LegendPatchShapeEntity:
|
||||
return QStringLiteral( "lpstagmap" );
|
||||
|
||||
case Symbol3DEntity:
|
||||
return QStringLiteral( "symbol3dtagmap" );
|
||||
|
||||
case TagEntity:
|
||||
case SmartgroupEntity:
|
||||
break;
|
||||
@ -3007,6 +3308,9 @@ QString QgsStyle::tagmapEntityIdFieldName( QgsStyle::StyleEntity type )
|
||||
case LegendPatchShapeEntity:
|
||||
return QStringLiteral( "legendpatchshape_id" );
|
||||
|
||||
case Symbol3DEntity:
|
||||
return QStringLiteral( "symbol3d_id" );
|
||||
|
||||
case TagEntity:
|
||||
case SmartgroupEntity:
|
||||
break;
|
||||
@ -3038,3 +3342,8 @@ QgsStyle::StyleEntity QgsStyleLegendPatchShapeEntity::type() const
|
||||
{
|
||||
return QgsStyle::LegendPatchShapeEntity;
|
||||
}
|
||||
|
||||
QgsStyle::StyleEntity QgsStyleSymbol3DEntity::type() const
|
||||
{
|
||||
return QgsStyle::Symbol3DEntity;
|
||||
}
|
||||
|
@ -184,6 +184,7 @@ class CORE_EXPORT QgsStyle : public QObject
|
||||
TextFormatEntity, //!< Text formats
|
||||
LabelSettingsEntity, //!< Label settings
|
||||
LegendPatchShapeEntity, //!< Legend patch shape (since QGIS 3.14)
|
||||
Symbol3DEntity, //!< 3D symbol entity (since QGIS 3.14)
|
||||
};
|
||||
|
||||
/**
|
||||
@ -256,6 +257,18 @@ class CORE_EXPORT QgsStyle : public QObject
|
||||
*/
|
||||
bool addLegendPatchShape( const QString &name, const QgsLegendPatchShape &shape, bool update = false );
|
||||
|
||||
/**
|
||||
* Adds a 3d \a symbol with the specified \a name to the style. Ownership of \a symbol is transferred.
|
||||
*
|
||||
* If \a update is set to TRUE, the style database will be automatically updated with the new legend patch shape.
|
||||
*
|
||||
* Returns TRUE if the operation was successful.
|
||||
*
|
||||
* \note Adding 3d symbols with the name of existing ones replaces them.
|
||||
* \since QGIS 3.16
|
||||
*/
|
||||
bool addSymbol3D( const QString &name, QgsAbstract3DSymbol *symbol SIP_TRANSFER, bool update = false );
|
||||
|
||||
/**
|
||||
* Adds a new tag and returns the tag's id
|
||||
*
|
||||
@ -378,6 +391,28 @@ class CORE_EXPORT QgsStyle : public QObject
|
||||
*/
|
||||
QgsSymbol::SymbolType legendPatchShapeSymbolType( const QString &name ) const;
|
||||
|
||||
/**
|
||||
* Returns a new copy of the 3D symbol with the specified \a name.
|
||||
*
|
||||
* \since QGIS 3.16
|
||||
*/
|
||||
QgsAbstract3DSymbol *symbol3D( const QString &name ) const SIP_FACTORY;
|
||||
|
||||
/**
|
||||
* Returns count of 3D symbols in the style.
|
||||
* \since QGIS 3.16
|
||||
*/
|
||||
int symbol3DCount() const;
|
||||
|
||||
/**
|
||||
* Returns the symbol type corresponding to the 3d symbol
|
||||
* with the specified \a name, or an empty string
|
||||
* if a matching 3d symbol is not present.
|
||||
*
|
||||
* \since QGIS 3.16
|
||||
*/
|
||||
QString symbol3DType( const QString &name ) const;
|
||||
|
||||
/**
|
||||
* Returns the layer geometry type corresponding to the label settings
|
||||
* with the specified \a name, or QgsWkbTypes::UnknownGeometry
|
||||
@ -688,6 +723,32 @@ class CORE_EXPORT QgsStyle : public QObject
|
||||
*/
|
||||
QList< QList< QPolygonF > > defaultPatchAsQPolygonF( QgsSymbol::SymbolType type, QSizeF size ) const;
|
||||
|
||||
/**
|
||||
* Adds a 3d \a symbol to the database.
|
||||
*
|
||||
* \param name is the name of the 3d symbol
|
||||
* \param symbol 3d symbol to save. Ownership is transferred.
|
||||
* \param favorite is a boolean value to specify whether the 3d symbol should be added to favorites
|
||||
* \param tags is a list of tags that are associated with the 3d symbol
|
||||
* \returns returns the success state of the save operation
|
||||
*
|
||||
* \since QGIS 3.16
|
||||
*/
|
||||
bool saveSymbol3D( const QString &name, QgsAbstract3DSymbol *symbol SIP_TRANSFER, bool favorite, const QStringList &tags );
|
||||
|
||||
/**
|
||||
* Changes a 3d symbol's name.
|
||||
*
|
||||
* \since QGIS 3.16
|
||||
*/
|
||||
bool renameSymbol3D( const QString &oldName, const QString &newName );
|
||||
|
||||
/**
|
||||
* Returns a list of names of 3d symbols in the style.
|
||||
* \since QGIS 3.16
|
||||
*/
|
||||
QStringList symbol3DNames() const;
|
||||
|
||||
/**
|
||||
* Creates an on-disk database
|
||||
*
|
||||
@ -1006,6 +1067,7 @@ class CORE_EXPORT QgsStyle : public QObject
|
||||
QgsTextFormatMap mTextFormats;
|
||||
QgsLabelSettingsMap mLabelSettings;
|
||||
QMap<QString, QgsLegendPatchShape > mLegendPatchShapes;
|
||||
QMap<QString, QgsAbstract3DSymbol * > m3dSymbols;
|
||||
|
||||
QHash< QgsStyle::StyleEntity, QHash< QString, QStringList > > mCachedTags;
|
||||
QHash< QgsStyle::StyleEntity, QHash< QString, bool > > mCachedFavorites;
|
||||
@ -1278,4 +1340,35 @@ class CORE_EXPORT QgsStyleLegendPatchShapeEntity : public QgsStyleEntityInterfac
|
||||
QgsLegendPatchShape mShape;
|
||||
};
|
||||
|
||||
/**
|
||||
* \class QgsStyleSymbol3DEntity
|
||||
* \ingroup core
|
||||
* A 3d symbol entity for QgsStyle databases.
|
||||
* \since QGIS 3.16
|
||||
*/
|
||||
class CORE_EXPORT QgsStyleSymbol3DEntity : public QgsStyleEntityInterface
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor for QgsStyleSymbol3DEntity, with the specified \a symbol.
|
||||
*
|
||||
* Ownership of \a symbol is NOT transferred.
|
||||
*/
|
||||
QgsStyleSymbol3DEntity( const QgsAbstract3DSymbol *symbol )
|
||||
: mSymbol( symbol )
|
||||
{}
|
||||
|
||||
QgsStyle::StyleEntity type() const override;
|
||||
|
||||
/**
|
||||
* Returns the entity's symbol.
|
||||
*/
|
||||
const QgsAbstract3DSymbol *symbol() const { return mSymbol; }
|
||||
|
||||
private:
|
||||
|
||||
const QgsAbstract3DSymbol *mSymbol = nullptr;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -175,6 +175,7 @@ QVariant QgsStyleModel::data( const QModelIndex &index, int role ) const
|
||||
case QgsStyle::ColorrampEntity:
|
||||
case QgsStyle::TagEntity:
|
||||
case QgsStyle::SmartgroupEntity:
|
||||
case QgsStyle::Symbol3DEntity:
|
||||
break;
|
||||
}
|
||||
return tooltip;
|
||||
@ -317,6 +318,7 @@ QVariant QgsStyleModel::data( const QModelIndex &index, int role ) const
|
||||
|
||||
case QgsStyle::TagEntity:
|
||||
case QgsStyle::SmartgroupEntity:
|
||||
case QgsStyle::Symbol3DEntity:
|
||||
return QVariant();
|
||||
}
|
||||
break;
|
||||
@ -354,6 +356,7 @@ QVariant QgsStyleModel::data( const QModelIndex &index, int role ) const
|
||||
case QgsStyle::SmartgroupEntity:
|
||||
case QgsStyle::LabelSettingsEntity:
|
||||
case QgsStyle::TextFormatEntity:
|
||||
case QgsStyle::Symbol3DEntity:
|
||||
return QVariant();
|
||||
}
|
||||
return QVariant();
|
||||
|
@ -1256,6 +1256,7 @@ INCLUDE_DIRECTORIES(
|
||||
${CMAKE_SOURCE_DIR}/src/gui/vectortile
|
||||
${CMAKE_SOURCE_DIR}/src/gui/tableeditor
|
||||
${CMAKE_SOURCE_DIR}/src/core
|
||||
${CMAKE_SOURCE_DIR}/src/core/3d
|
||||
${CMAKE_SOURCE_DIR}/src/core/annotations
|
||||
${CMAKE_SOURCE_DIR}/src/core/auth
|
||||
${CMAKE_SOURCE_DIR}/src/core/callouts
|
||||
|
@ -681,6 +681,7 @@ void QgsLabelingGui::setFormatFromStyle( const QString &name, QgsStyle::StyleEnt
|
||||
case QgsStyle::SmartgroupEntity:
|
||||
case QgsStyle::TextFormatEntity:
|
||||
case QgsStyle::LegendPatchShapeEntity:
|
||||
case QgsStyle::Symbol3DEntity:
|
||||
{
|
||||
QgsTextFormatWidget::setFormatFromStyle( name, type );
|
||||
return;
|
||||
@ -781,6 +782,7 @@ void QgsLabelingGui::saveFormat()
|
||||
case QgsStyle::TagEntity:
|
||||
case QgsStyle::SmartgroupEntity:
|
||||
case QgsStyle::LegendPatchShapeEntity:
|
||||
case QgsStyle::Symbol3DEntity:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -204,6 +204,13 @@ void QgsStyleItemsListWidget::setEntityType( QgsStyle::StyleEntity type )
|
||||
groupsCombo->setItemText( allGroup, tr( "All Legend Patch Shapes" ) );
|
||||
break;
|
||||
|
||||
case QgsStyle::Symbol3DEntity:
|
||||
btnSaveSymbol->setText( tr( "Save 3D Symbol…" ) );
|
||||
btnSaveSymbol->setToolTip( tr( "Save 3D symbol to styles" ) );
|
||||
if ( allGroup >= 0 )
|
||||
groupsCombo->setItemText( allGroup, tr( "All 3D Symbols" ) );
|
||||
break;
|
||||
|
||||
case QgsStyle::TagEntity:
|
||||
case QgsStyle::SmartgroupEntity:
|
||||
break;
|
||||
@ -330,6 +337,10 @@ void QgsStyleItemsListWidget::populateGroups()
|
||||
allText = tr( "All Legend Patch Shapes" );
|
||||
break;
|
||||
|
||||
case QgsStyle::Symbol3DEntity:
|
||||
allText = tr( "All 3D Symbols" );
|
||||
break;
|
||||
|
||||
case QgsStyle::TagEntity:
|
||||
case QgsStyle::SmartgroupEntity:
|
||||
break;
|
||||
|
@ -1814,6 +1814,7 @@ void QgsTextFormatWidget::setFormatFromStyle( const QString &name, QgsStyle::Sty
|
||||
case QgsStyle::TagEntity:
|
||||
case QgsStyle::SmartgroupEntity:
|
||||
case QgsStyle::LegendPatchShapeEntity:
|
||||
case QgsStyle::Symbol3DEntity:
|
||||
return;
|
||||
|
||||
case QgsStyle::TextFormatEntity:
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "qgstextformatwidget.h"
|
||||
#include "qgslabelinggui.h"
|
||||
#include "qgslegendpatchshapewidget.h"
|
||||
#include "qgsabstract3dsymbol.h"
|
||||
#include <QAction>
|
||||
#include <QFile>
|
||||
#include <QFileDialog>
|
||||
@ -614,6 +615,7 @@ void QgsStyleManagerDialog::copyItem()
|
||||
|
||||
case QgsStyle::ColorrampEntity:
|
||||
case QgsStyle::LegendPatchShapeEntity:
|
||||
case QgsStyle::Symbol3DEntity:
|
||||
case QgsStyle::TagEntity:
|
||||
case QgsStyle::SmartgroupEntity:
|
||||
return;
|
||||
@ -1014,6 +1016,59 @@ int QgsStyleManagerDialog::copyItems( const QList<QgsStyleManagerDialog::ItemDet
|
||||
break;
|
||||
}
|
||||
|
||||
case QgsStyle::Symbol3DEntity:
|
||||
{
|
||||
std::unique_ptr< QgsAbstract3DSymbol > symbol( src->symbol3D( details.name ) );
|
||||
if ( !symbol )
|
||||
continue;
|
||||
|
||||
const bool hasDuplicateName = dst->symbol3DNames().contains( details.name );
|
||||
bool overwriteThis = false;
|
||||
if ( isImport )
|
||||
addItemToFavorites = favoriteSymbols.contains( details.name );
|
||||
|
||||
if ( hasDuplicateName && prompt )
|
||||
{
|
||||
cursorOverride.reset();
|
||||
int res = QMessageBox::warning( parentWidget, isImport ? tr( "Import 3D Symbol" ) : tr( "Export 3D Symbol" ),
|
||||
tr( "A 3D symbol with the name “%1” already exists.\nOverwrite?" )
|
||||
.arg( details.name ),
|
||||
QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No | QMessageBox::NoToAll | QMessageBox::Cancel );
|
||||
cursorOverride = qgis::make_unique< QgsTemporaryCursorOverride >( Qt::WaitCursor );
|
||||
switch ( res )
|
||||
{
|
||||
case QMessageBox::Cancel:
|
||||
return count;
|
||||
|
||||
case QMessageBox::No:
|
||||
continue;
|
||||
|
||||
case QMessageBox::Yes:
|
||||
overwriteThis = true;
|
||||
break;
|
||||
|
||||
case QMessageBox::YesToAll:
|
||||
prompt = false;
|
||||
overwriteAll = true;
|
||||
break;
|
||||
|
||||
case QMessageBox::NoToAll:
|
||||
prompt = false;
|
||||
overwriteAll = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !hasDuplicateName || overwriteAll || overwriteThis )
|
||||
{
|
||||
QgsAbstract3DSymbol *newSymbol = symbol.get();
|
||||
dst->addSymbol3D( details.name, symbol.release() );
|
||||
dst->saveSymbol3D( details.name, newSymbol, addItemToFavorites, symbolTags );
|
||||
count++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case QgsStyle::TagEntity:
|
||||
case QgsStyle::SmartgroupEntity:
|
||||
break;
|
||||
|
@ -65,6 +65,11 @@ QgsStyleSaveDialog::QgsStyleSaveDialog( QWidget *parent, QgsStyle::StyleEntity t
|
||||
possibleEntities << QgsStyle::LegendPatchShapeEntity;
|
||||
break;
|
||||
|
||||
case QgsStyle::Symbol3DEntity:
|
||||
this->setWindowTitle( tr( "Save New 3D Symbol" ) );
|
||||
possibleEntities << QgsStyle::Symbol3DEntity;
|
||||
break;
|
||||
|
||||
case QgsStyle::TagEntity:
|
||||
case QgsStyle::SmartgroupEntity:
|
||||
break;
|
||||
@ -101,6 +106,10 @@ QgsStyleSaveDialog::QgsStyleSaveDialog( QWidget *parent, QgsStyle::StyleEntity t
|
||||
mComboSaveAs->addItem( QgsApplication::getThemeIcon( QStringLiteral( "legend.svg" ) ), tr( "Legend Patch Shape" ), e );
|
||||
break;
|
||||
|
||||
case QgsStyle::Symbol3DEntity:
|
||||
mComboSaveAs->addItem( QgsApplication::getThemeIcon( QStringLiteral( "3d.svg" ) ), tr( "3D Symbol" ), e );
|
||||
break;
|
||||
|
||||
case QgsStyle::TagEntity:
|
||||
case QgsStyle::SmartgroupEntity:
|
||||
break;
|
||||
|
@ -7,6 +7,7 @@ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_SOURCE_DIR}/external/kdbush/include
|
||||
${CMAKE_SOURCE_DIR}/external/nlohmann
|
||||
${CMAKE_SOURCE_DIR}/src/core
|
||||
${CMAKE_SOURCE_DIR}/src/core/3d
|
||||
${CMAKE_SOURCE_DIR}/src/core/annotations
|
||||
${CMAKE_SOURCE_DIR}/src/core/auth
|
||||
${CMAKE_SOURCE_DIR}/src/core/callouts
|
||||
|
@ -50,6 +50,8 @@
|
||||
#include "qgslayertreelayer.h"
|
||||
#include "qgslayertreeutils.h"
|
||||
#include "qgsmaplayerlegend.h"
|
||||
#include "qgsabstract3dsymbol.h"
|
||||
#include "qgs3dsymbolregistry.h"
|
||||
|
||||
/**
|
||||
* \ingroup UnitTests
|
||||
@ -86,6 +88,7 @@ class TestStyle : public QObject
|
||||
void testCreateTextFormats();
|
||||
void testCreateLabelSettings();
|
||||
void testCreateLegendPatchShapes();
|
||||
void testCreate3dSymbol();
|
||||
void testLoadColorRamps();
|
||||
void testSaveLoad();
|
||||
void testFavorites();
|
||||
@ -96,6 +99,21 @@ class TestStyle : public QObject
|
||||
|
||||
};
|
||||
|
||||
|
||||
class Dummy3DSymbol : public QgsAbstract3DSymbol
|
||||
{
|
||||
public:
|
||||
static QgsAbstract3DSymbol *create() { return new Dummy3DSymbol; }
|
||||
QString type() const override { return QStringLiteral( "dummy" ); }
|
||||
QgsAbstract3DSymbol *clone() const override { Dummy3DSymbol *res = new Dummy3DSymbol(); res->id = id; return res; }
|
||||
void readXml( const QDomElement &elem, const QgsReadWriteContext & ) override { id = elem.attribute( QStringLiteral( "id" ) ); }
|
||||
void writeXml( QDomElement &elem, const QgsReadWriteContext & ) const override { elem.setAttribute( QStringLiteral( "id" ), id ); }
|
||||
|
||||
QString id;
|
||||
|
||||
};
|
||||
|
||||
|
||||
TestStyle::TestStyle() = default;
|
||||
|
||||
// slots
|
||||
@ -123,6 +141,9 @@ void TestStyle::initTestCase()
|
||||
QgsCptCityArchive::initArchives();
|
||||
|
||||
mReport += QLatin1String( "<h1>Style Tests</h1>\n" );
|
||||
|
||||
QgsApplication::symbol3DRegistry()->addSymbolType( new Qgs3DSymbolMetadata( QStringLiteral( "dummy" ), QObject::tr( "Dummy" ),
|
||||
&Dummy3DSymbol::create, nullptr, nullptr ) );
|
||||
}
|
||||
|
||||
void TestStyle::cleanupTestCase()
|
||||
@ -417,6 +438,68 @@ void TestStyle::testCreateLegendPatchShapes()
|
||||
QVERIFY( mStyle->legendPatchShapeNames().contains( QStringLiteral( "test_settings2" ) ) );
|
||||
}
|
||||
|
||||
void TestStyle::testCreate3dSymbol()
|
||||
{
|
||||
QVERIFY( mStyle->symbol3DNames().isEmpty() );
|
||||
QCOMPARE( mStyle->symbol3DCount(), 0 );
|
||||
// non existent settings, should be default
|
||||
QVERIFY( !mStyle->symbol3D( QString( "blah" ) ) );
|
||||
|
||||
QSignalSpy spy( mStyle, &QgsStyle::entityAdded );
|
||||
QSignalSpy spyChanged( mStyle, &QgsStyle::entityChanged );
|
||||
// add symbol
|
||||
Dummy3DSymbol symbol;
|
||||
symbol.id = QStringLiteral( "xxx" );
|
||||
QVERIFY( mStyle->addSymbol3D( "test_settings", symbol.clone(), true ) );
|
||||
QCOMPARE( spy.count(), 1 );
|
||||
QCOMPARE( spyChanged.count(), 0 );
|
||||
|
||||
QVERIFY( mStyle->symbol3DNames().contains( QStringLiteral( "test_settings" ) ) );
|
||||
QCOMPARE( mStyle->symbol3DCount(), 1 );
|
||||
std::unique_ptr< Dummy3DSymbol > retrieved( dynamic_cast< Dummy3DSymbol * >( mStyle->symbol3D( QStringLiteral( "test_settings" ) ) ) );
|
||||
QCOMPARE( retrieved->id, QStringLiteral( "xxx" ) );
|
||||
symbol.id = QStringLiteral( "yyy" );
|
||||
QVERIFY( mStyle->addSymbol3D( "test_settings", symbol.clone(), true ) );
|
||||
QVERIFY( mStyle->symbol3DNames().contains( QStringLiteral( "test_settings" ) ) );
|
||||
QCOMPARE( mStyle->symbol3DCount(), 1 );
|
||||
retrieved.reset( dynamic_cast< Dummy3DSymbol * >( mStyle->symbol3D( QStringLiteral( "test_settings" ) ) ) );
|
||||
QCOMPARE( retrieved->id, QStringLiteral( "yyy" ) );
|
||||
QCOMPARE( spy.count(), 1 );
|
||||
QCOMPARE( spyChanged.count(), 1 );
|
||||
|
||||
symbol.id = QStringLiteral( "zzz" );
|
||||
QVERIFY( mStyle->addSymbol3D( "test_format2", symbol.clone(), true ) );
|
||||
QVERIFY( mStyle->symbol3DNames().contains( QStringLiteral( "test_format2" ) ) );
|
||||
QCOMPARE( mStyle->symbol3DCount(), 2 );
|
||||
retrieved.reset( dynamic_cast< Dummy3DSymbol * >( mStyle->symbol3D( QStringLiteral( "test_settings" ) ) ) );
|
||||
QCOMPARE( retrieved->id, QStringLiteral( "yyy" ) );
|
||||
retrieved.reset( dynamic_cast< Dummy3DSymbol * >( mStyle->symbol3D( QStringLiteral( "test_format2" ) ) ) );
|
||||
QCOMPARE( retrieved->id, QStringLiteral( "zzz" ) );
|
||||
QCOMPARE( spy.count(), 2 );
|
||||
QCOMPARE( spyChanged.count(), 1 );
|
||||
|
||||
// save and restore
|
||||
QVERIFY( mStyle->exportXml( QDir::tempPath() + "/text_style.xml" ) );
|
||||
|
||||
QgsStyle style2;
|
||||
QVERIFY( style2.importXml( QDir::tempPath() + "/text_style.xml" ) );
|
||||
|
||||
QVERIFY( style2.symbol3DNames().contains( QStringLiteral( "test_settings" ) ) );
|
||||
QVERIFY( style2.symbol3DNames().contains( QStringLiteral( "test_format2" ) ) );
|
||||
QCOMPARE( style2.symbol3DCount(), 2 );
|
||||
retrieved.reset( dynamic_cast< Dummy3DSymbol * >( style2.symbol3D( QStringLiteral( "test_settings" ) ) ) );
|
||||
QCOMPARE( retrieved->id, QStringLiteral( "yyy" ) );
|
||||
retrieved.reset( dynamic_cast< Dummy3DSymbol * >( style2.symbol3D( QStringLiteral( "test_format2" ) ) ) );
|
||||
QCOMPARE( retrieved->id, QStringLiteral( "zzz" ) );
|
||||
|
||||
QCOMPARE( mStyle->allNames( QgsStyle::Symbol3DEntity ), QStringList() << QStringLiteral( "test_format2" )
|
||||
<< QStringLiteral( "test_settings" ) );
|
||||
|
||||
QgsStyleSymbol3DEntity entity( &symbol );
|
||||
QVERIFY( mStyle->addEntity( "test_settings2", &entity, true ) );
|
||||
QVERIFY( mStyle->symbol3DNames().contains( QStringLiteral( "test_settings2" ) ) );
|
||||
}
|
||||
|
||||
void TestStyle::testLoadColorRamps()
|
||||
{
|
||||
QStringList colorRamps = mStyle->colorRampNames();
|
||||
@ -499,6 +582,7 @@ void TestStyle::testFavorites()
|
||||
QVERIFY( !mStyle->isFavorite( QgsStyle::LabelSettingsEntity, QStringLiteral( "AaaaaaaaaA" ) ) );
|
||||
QVERIFY( !mStyle->isFavorite( QgsStyle::ColorrampEntity, QStringLiteral( "AaaaaaaaaA" ) ) );
|
||||
QVERIFY( !mStyle->isFavorite( QgsStyle::LegendPatchShapeEntity, QStringLiteral( "AaaaaaaaaA" ) ) );
|
||||
QVERIFY( !mStyle->isFavorite( QgsStyle::Symbol3DEntity, QStringLiteral( "AaaaaaaaaA" ) ) );
|
||||
|
||||
// add some symbols to favorites
|
||||
std::unique_ptr< QgsMarkerSymbol > sym1( QgsMarkerSymbol::createSimple( QgsStringMap() ) );
|
||||
@ -652,6 +736,32 @@ void TestStyle::testFavorites()
|
||||
favorites = mStyle->symbolsOfFavorite( QgsStyle::LegendPatchShapeEntity );
|
||||
QCOMPARE( favorites.count(), 0 );
|
||||
QVERIFY( !mStyle->isFavorite( QgsStyle::LegendPatchShapeEntity, QStringLiteral( "settings_1" ) ) );
|
||||
|
||||
// symbol 3d
|
||||
Dummy3DSymbol symbol3d1;
|
||||
QVERIFY( mStyle->addSymbol3D( QStringLiteral( "settings_1" ), symbol3d1.clone(), true ) );
|
||||
favorites = mStyle->symbolsOfFavorite( QgsStyle::Symbol3DEntity );
|
||||
QCOMPARE( favorites.count(), 0 );
|
||||
QVERIFY( !mStyle->isFavorite( QgsStyle::Symbol3DEntity, QStringLiteral( "settings_1" ) ) );
|
||||
|
||||
mStyle->addFavorite( QgsStyle::Symbol3DEntity, QStringLiteral( "settings_1" ) );
|
||||
QCOMPARE( favoriteChangedSpy.count(), 11 );
|
||||
QCOMPARE( favoriteChangedSpy.at( 10 ).at( 0 ).toInt(), static_cast< int >( QgsStyle::Symbol3DEntity ) );
|
||||
QCOMPARE( favoriteChangedSpy.at( 10 ).at( 1 ).toString(), QStringLiteral( "settings_1" ) );
|
||||
QCOMPARE( favoriteChangedSpy.at( 10 ).at( 2 ).toBool(), true );
|
||||
favorites = mStyle->symbolsOfFavorite( QgsStyle::Symbol3DEntity );
|
||||
QCOMPARE( favorites.count(), 1 );
|
||||
QVERIFY( favorites.contains( QStringLiteral( "settings_1" ) ) );
|
||||
QVERIFY( mStyle->isFavorite( QgsStyle::Symbol3DEntity, QStringLiteral( "settings_1" ) ) );
|
||||
|
||||
mStyle->removeFavorite( QgsStyle::Symbol3DEntity, QStringLiteral( "settings_1" ) );
|
||||
QCOMPARE( favoriteChangedSpy.count(), 12 );
|
||||
QCOMPARE( favoriteChangedSpy.at( 11 ).at( 0 ).toInt(), static_cast< int >( QgsStyle::Symbol3DEntity ) );
|
||||
QCOMPARE( favoriteChangedSpy.at( 11 ).at( 1 ).toString(), QStringLiteral( "settings_1" ) );
|
||||
QCOMPARE( favoriteChangedSpy.at( 11 ).at( 2 ).toBool(), false );
|
||||
favorites = mStyle->symbolsOfFavorite( QgsStyle::Symbol3DEntity );
|
||||
QCOMPARE( favorites.count(), 0 );
|
||||
QVERIFY( !mStyle->isFavorite( QgsStyle::Symbol3DEntity, QStringLiteral( "settings_1" ) ) );
|
||||
}
|
||||
|
||||
void TestStyle::testTags()
|
||||
@ -1090,6 +1200,69 @@ void TestStyle::testTags()
|
||||
QCOMPARE( tagsChangedSpy.at( 34 ).at( 0 ).toInt(), static_cast< int >( QgsStyle::LegendPatchShapeEntity ) );
|
||||
QCOMPARE( tagsChangedSpy.at( 34 ).at( 1 ).toString(), QStringLiteral( "shape1" ) );
|
||||
QCOMPARE( tagsChangedSpy.at( 34 ).at( 2 ).toStringList(), QStringList() );
|
||||
|
||||
|
||||
// 3d symbols
|
||||
// tag format
|
||||
Dummy3DSymbol symbol3d1;
|
||||
QVERIFY( mStyle->addSymbol3D( "3dsymbol1", symbol3d1.clone(), true ) );
|
||||
Dummy3DSymbol symbol3d2;
|
||||
QVERIFY( mStyle->addSymbol3D( "3dsymbol2", symbol3d2.clone(), true ) );
|
||||
|
||||
QVERIFY( mStyle->tagSymbol( QgsStyle::Symbol3DEntity, "3dsymbol1", QStringList() << "blue" << "starry" ) );
|
||||
QCOMPARE( tagsChangedSpy.count(), 38 );
|
||||
QCOMPARE( tagsChangedSpy.at( 37 ).at( 0 ).toInt(), static_cast< int>( QgsStyle::Symbol3DEntity ) );
|
||||
QCOMPARE( tagsChangedSpy.at( 37 ).at( 1 ).toString(), QStringLiteral( "3dsymbol1" ) );
|
||||
QCOMPARE( tagsChangedSpy.at( 37 ).at( 2 ).toStringList(), QStringList() << QStringLiteral( "blue" ) << QStringLiteral( "starry" ) );
|
||||
|
||||
QVERIFY( mStyle->tagSymbol( QgsStyle::Symbol3DEntity, "3dsymbol2", QStringList() << "red" << "circle" ) );
|
||||
QCOMPARE( tagsChangedSpy.count(), 39 );
|
||||
QCOMPARE( tagsChangedSpy.at( 38 ).at( 0 ).toInt(), static_cast< int>( QgsStyle::Symbol3DEntity ) );
|
||||
QCOMPARE( tagsChangedSpy.at( 38 ).at( 1 ).toString(), QStringLiteral( "3dsymbol2" ) );
|
||||
QCOMPARE( tagsChangedSpy.at( 38 ).at( 2 ).toStringList(), QStringList() << QStringLiteral( "red" ) << QStringLiteral( "circle" ) );
|
||||
|
||||
//bad format name
|
||||
QVERIFY( !mStyle->tagSymbol( QgsStyle::Symbol3DEntity, "no patch", QStringList() << "red" << "circle" ) );
|
||||
QCOMPARE( tagsChangedSpy.count(), 39 );
|
||||
//tag which hasn't been added yet
|
||||
QVERIFY( mStyle->tagSymbol( QgsStyle::Symbol3DEntity, "3dsymbol2", QStringList() << "red patch" ) );
|
||||
QCOMPARE( tagsChangedSpy.count(), 40 );
|
||||
QCOMPARE( tagsChangedSpy.at( 39 ).at( 0 ).toInt(), static_cast< int>( QgsStyle::Symbol3DEntity ) );
|
||||
QCOMPARE( tagsChangedSpy.at( 39 ).at( 1 ).toString(), QStringLiteral( "3dsymbol2" ) );
|
||||
QCOMPARE( tagsChangedSpy.at( 39 ).at( 2 ).toStringList(), QStringList() << QStringLiteral( "red" ) << QStringLiteral( "circle" ) << QStringLiteral( "red patch" ) );
|
||||
|
||||
tags = mStyle->tags();
|
||||
QVERIFY( tags.contains( QStringLiteral( "red patch" ) ) );
|
||||
|
||||
//check that tags have been applied
|
||||
tags = mStyle->tagsOfSymbol( QgsStyle::Symbol3DEntity, QStringLiteral( "3dsymbol1" ) );
|
||||
QCOMPARE( tags.count(), 2 );
|
||||
QVERIFY( tags.contains( "blue" ) );
|
||||
QVERIFY( tags.contains( "starry" ) );
|
||||
tags = mStyle->tagsOfSymbol( QgsStyle::Symbol3DEntity, QStringLiteral( "3dsymbol2" ) );
|
||||
QCOMPARE( tags.count(), 3 );
|
||||
QVERIFY( tags.contains( "red" ) );
|
||||
QVERIFY( tags.contains( "circle" ) );
|
||||
QVERIFY( tags.contains( "red patch" ) );
|
||||
|
||||
//remove a tag, including a non-present tag
|
||||
QVERIFY( mStyle->detagSymbol( QgsStyle::Symbol3DEntity, "3dsymbol1", QStringList() << "bad" << "blue" ) );
|
||||
tags = mStyle->tagsOfSymbol( QgsStyle::Symbol3DEntity, QStringLiteral( "3dsymbol1" ) );
|
||||
QCOMPARE( tags.count(), 1 );
|
||||
QVERIFY( tags.contains( "starry" ) );
|
||||
QCOMPARE( tagsChangedSpy.count(), 41 );
|
||||
QCOMPARE( tagsChangedSpy.at( 40 ).at( 0 ).toInt(), static_cast< int >( QgsStyle::Symbol3DEntity ) );
|
||||
QCOMPARE( tagsChangedSpy.at( 40 ).at( 1 ).toString(), QStringLiteral( "3dsymbol1" ) );
|
||||
QCOMPARE( tagsChangedSpy.at( 40 ).at( 2 ).toStringList(), QStringList() << QStringLiteral( "starry" ) );
|
||||
|
||||
// completely detag symbol
|
||||
QVERIFY( mStyle->detagSymbol( QgsStyle::Symbol3DEntity, QStringLiteral( "3dsymbol1" ) ) );
|
||||
tags = mStyle->tagsOfSymbol( QgsStyle::Symbol3DEntity, QStringLiteral( "3dsymbol1" ) );
|
||||
QCOMPARE( tags.count(), 0 );
|
||||
QCOMPARE( tagsChangedSpy.count(), 42 );
|
||||
QCOMPARE( tagsChangedSpy.at( 41 ).at( 0 ).toInt(), static_cast< int >( QgsStyle::Symbol3DEntity ) );
|
||||
QCOMPARE( tagsChangedSpy.at( 41 ).at( 1 ).toString(), QStringLiteral( "3dsymbol1" ) );
|
||||
QCOMPARE( tagsChangedSpy.at( 41 ).at( 2 ).toStringList(), QStringList() );
|
||||
}
|
||||
|
||||
void TestStyle::testSmartGroup()
|
||||
@ -1125,6 +1298,11 @@ void TestStyle::testSmartGroup()
|
||||
QgsLegendPatchShape shape2;
|
||||
QVERIFY( style.addLegendPatchShape( "different shp bbb", shape2, true ) );
|
||||
|
||||
Dummy3DSymbol symbol3d1;
|
||||
QVERIFY( style.addSymbol3D( "symbol3D a", symbol3d1.clone(), true ) );
|
||||
Dummy3DSymbol symbol3d2;
|
||||
QVERIFY( style.addSymbol3D( "different symbol3D bbb", symbol3d2.clone(), true ) );
|
||||
|
||||
QVERIFY( style.smartgroupNames().empty() );
|
||||
QVERIFY( style.smartgroup( 5 ).isEmpty() );
|
||||
QCOMPARE( style.smartgroupId( QStringLiteral( "no exist" ) ), 0 );
|
||||
@ -1144,6 +1322,7 @@ void TestStyle::testSmartGroup()
|
||||
QCOMPARE( style.symbolsOfSmartgroup( QgsStyle::TextFormatEntity, 1 ), QStringList() << QStringLiteral( "format a" ) );
|
||||
QCOMPARE( style.symbolsOfSmartgroup( QgsStyle::LabelSettingsEntity, 1 ), QStringList() << QStringLiteral( "settings a" ) );
|
||||
QCOMPARE( style.symbolsOfSmartgroup( QgsStyle::LegendPatchShapeEntity, 1 ), QStringList() << QStringLiteral( "shp a" ) );
|
||||
QCOMPARE( style.symbolsOfSmartgroup( QgsStyle::Symbol3DEntity, 1 ), QStringList() << QStringLiteral( "symbol3D a" ) );
|
||||
|
||||
res = style.addSmartgroup( QStringLiteral( "tag" ), QStringLiteral( "OR" ), QStringList(), QStringList(), QStringList() << "c", QStringList() << "a" );
|
||||
QCOMPARE( res, 2 );
|
||||
@ -1158,6 +1337,7 @@ void TestStyle::testSmartGroup()
|
||||
QCOMPARE( style.symbolsOfSmartgroup( QgsStyle::TextFormatEntity, 2 ), QStringList() << QStringLiteral( "different text bbb" ) );
|
||||
QCOMPARE( style.symbolsOfSmartgroup( QgsStyle::LabelSettingsEntity, 2 ), QStringList() << QStringLiteral( "different l bbb" ) );
|
||||
QCOMPARE( style.symbolsOfSmartgroup( QgsStyle::LegendPatchShapeEntity, 2 ), QStringList() << QStringLiteral( "different shp bbb" ) );
|
||||
QCOMPARE( style.symbolsOfSmartgroup( QgsStyle::Symbol3DEntity, 2 ), QStringList() << QStringLiteral( "different symbol3D bbb" ) );
|
||||
|
||||
// tag some symbols
|
||||
style.tagSymbol( QgsStyle::SymbolEntity, "symbolA", QStringList() << "red" << "blue" );
|
||||
@ -1170,6 +1350,8 @@ void TestStyle::testSmartGroup()
|
||||
style.tagSymbol( QgsStyle::LabelSettingsEntity, "different l bbb", QStringList() << "blue" << "red" );
|
||||
style.tagSymbol( QgsStyle::LegendPatchShapeEntity, "shp a", QStringList() << "blue" );
|
||||
style.tagSymbol( QgsStyle::LegendPatchShapeEntity, "different shp bbb", QStringList() << "blue" << "red" );
|
||||
style.tagSymbol( QgsStyle::Symbol3DEntity, "symbol3D a", QStringList() << "blue" );
|
||||
style.tagSymbol( QgsStyle::Symbol3DEntity, "different symbol3D bbb", QStringList() << "blue" << "red" );
|
||||
|
||||
// adding tags modifies groups!
|
||||
QCOMPARE( groupModifiedSpy.count(), 4 );
|
||||
@ -1187,6 +1369,7 @@ void TestStyle::testSmartGroup()
|
||||
QCOMPARE( style.symbolsOfSmartgroup( QgsStyle::TextFormatEntity, 3 ), QStringList() << QStringLiteral( "format a" ) );
|
||||
QCOMPARE( style.symbolsOfSmartgroup( QgsStyle::LabelSettingsEntity, 3 ), QStringList() << QStringLiteral( "settings a" ) );
|
||||
QCOMPARE( style.symbolsOfSmartgroup( QgsStyle::LegendPatchShapeEntity, 3 ), QStringList() << QStringLiteral( "shp a" ) );
|
||||
QCOMPARE( style.symbolsOfSmartgroup( QgsStyle::Symbol3DEntity, 3 ), QStringList() << QStringLiteral( "symbol3D a" ) );
|
||||
|
||||
res = style.addSmartgroup( QStringLiteral( "combined" ), QStringLiteral( "AND" ), QStringList() << "blue", QStringList(), QStringList(), QStringList() << "a" );
|
||||
QCOMPARE( res, 4 );
|
||||
@ -1201,6 +1384,7 @@ void TestStyle::testSmartGroup()
|
||||
QCOMPARE( style.symbolsOfSmartgroup( QgsStyle::TextFormatEntity, 4 ), QStringList() << QStringLiteral( "different text bbb" ) );
|
||||
QCOMPARE( style.symbolsOfSmartgroup( QgsStyle::LabelSettingsEntity, 4 ), QStringList() << QStringLiteral( "different l bbb" ) );
|
||||
QCOMPARE( style.symbolsOfSmartgroup( QgsStyle::LegendPatchShapeEntity, 4 ), QStringList() << QStringLiteral( "different shp bbb" ) );
|
||||
QCOMPARE( style.symbolsOfSmartgroup( QgsStyle::Symbol3DEntity, 4 ), QStringList() << QStringLiteral( "different symbol3D bbb" ) );
|
||||
|
||||
style.remove( QgsStyle::SmartgroupEntity, 1 );
|
||||
QCOMPARE( style.smartgroupNames(), QStringList() << QStringLiteral( "tag" ) << QStringLiteral( "tags" ) << QStringLiteral( "combined" ) );
|
||||
@ -1265,6 +1449,10 @@ class TestVisitor : public QgsStyleEntityVisitorInterface
|
||||
mFound << QStringLiteral( "patch: %1 %2 %3" ).arg( entity.description, entity.identifier, static_cast< const QgsStyleLegendPatchShapeEntity * >( entity.entity )->shape().geometry().asWkt() );
|
||||
break;
|
||||
|
||||
case QgsStyle::Symbol3DEntity:
|
||||
mFound << QStringLiteral( "symbol 3d: %1 %2 %3" ).arg( entity.description, entity.identifier, static_cast< const QgsStyleSymbol3DEntity * >( entity.entity )->symbol()->type() );
|
||||
break;
|
||||
|
||||
case QgsStyle::TagEntity:
|
||||
case QgsStyle::SmartgroupEntity:
|
||||
break;
|
||||
|
Loading…
x
Reference in New Issue
Block a user