30#include "moc_qgsstylemodel.cpp"
59 mTargetScreenProperties = properties;
64 return mTargetScreenProperties;
73 : QAbstractItemModel(
parent )
78 if ( mStyle->isInitialized() )
89void QgsStyleModel::initStyleModel()
94 mEntityNames.insert( entity, mStyle->
allNames( entity ) );
100 mTargetScreenProperties.insert( QgsScreenProperties() );
118 if ( sIconGenerator )
131 switch ( entityType )
138 name = mEntityNames[ entityType ].value(
index.row() - offsetForEntity( entityType ) );
144 case Qt::DisplayRole:
145 case Qt::ToolTipRole:
148 switch (
index.column() )
152 const QStringList tags = mStyle->tagsOfSymbol( entityType, name );
154 if ( role == Qt::ToolTipRole )
156 QString tooltip = QStringLiteral(
"<h3>%1</h3><p><i>%2</i>" ).arg( name,
157 tags.count() > 0 ? tags.join( QLatin1String(
", " ) ) : tr(
"Not tagged" ) );
161 for (
auto it = mTargetScreenProperties.constBegin(); it != mTargetScreenProperties.constEnd(); ++it )
163 if ( !maxDevicePixelRatioScreen.
isValid() || it->devicePixelRatio() > maxDevicePixelRatioScreen.
devicePixelRatio() )
164 maxDevicePixelRatioScreen = *it;
167 switch ( entityType )
172 std::unique_ptr< QgsSymbol > symbol( mStyle->symbol( name ) );
175 int width =
static_cast< int >(
Qgis::UI_SCALE_FACTOR * QFontMetrics(
data(
index, Qt::FontRole ).value< QFont >() ).horizontalAdvance(
'X' ) * 23 );
176 int height =
static_cast< int >( width / 1.61803398875 );
179 QBuffer buffer( &
data );
180 pm.save( &buffer,
"PNG", 100 );
181 tooltip += QStringLiteral(
"<p><img src='data:image/png;base64, %3' width=\"%4\">" ).arg( QString(
data.toBase64() ) ).arg( width );
188 int width =
static_cast< int >(
Qgis::UI_SCALE_FACTOR * QFontMetrics(
data(
index, Qt::FontRole ).value< QFont >() ).horizontalAdvance(
'X' ) * 23 );
189 int height =
static_cast< int >( width / 1.61803398875 );
193 QBuffer buffer( &
data );
194 pm.save( &buffer,
"PNG", 100 );
195 tooltip += QStringLiteral(
"<p><img src='data:image/png;base64, %3' width=\"%4\">" ).arg( QString(
data.toBase64() ) ).arg( width );
201 int width =
static_cast< int >(
Qgis::UI_SCALE_FACTOR * QFontMetrics(
data(
index, Qt::FontRole ).value< QFont >() ).horizontalAdvance(
'X' ) * 23 );
202 int height =
static_cast< int >( width / 1.61803398875 );
206 QBuffer buffer( &
data );
207 pm.save( &buffer,
"PNG", 100 );
208 tooltip += QStringLiteral(
"<p><img src='data:image/png;base64, %3' width=\"%4\">" ).arg( QString(
data.toBase64() ) ).arg( width );
214 int width =
static_cast< int >(
Qgis::UI_SCALE_FACTOR * QFontMetrics(
data(
index, Qt::FontRole ).value< QFont >() ).horizontalAdvance(
'X' ) * 23 );
215 int height =
static_cast< int >( width / 1.61803398875 );
218 if (
const QgsSymbol *symbol = mStyle->previewSymbolForPatchShape( shape ) )
222 QBuffer buffer( &
data );
223 pm.save( &buffer,
"PNG", 100 );
224 tooltip += QStringLiteral(
"<p><img src='data:image/png;base64, %3' width=\"%4\">" ).arg( QString(
data.toBase64() ) ).arg( width );
243 return mStyle->tagsOfSymbol( entityType, name ).join( QLatin1String(
", " ) );
251 case Qt::DecorationRole:
256 if ( !mExpressionContext )
262 mExpressionContext = std::make_unique< QgsExpressionContext >();
266 switch (
index.column() )
269 switch ( entityType )
274 QIcon icon = mIconCache[ entityType ].value( name );
275 if ( !icon.isNull() )
278 std::unique_ptr< QgsSymbol > symbol( mStyle->symbol( name ) );
281 for (
auto it = mTargetScreenProperties.constBegin(); it != mTargetScreenProperties.constEnd(); ++it )
283 if ( mAdditionalSizes.isEmpty() )
286 for (
const QSize &s : mAdditionalSizes )
293 mIconCache[ entityType ].insert( name, icon );
299 QIcon icon = mIconCache[ entityType ].value( name );
300 if ( !icon.isNull() )
303 std::unique_ptr< QgsColorRamp > ramp( mStyle->colorRamp( name ) );
306 if ( mAdditionalSizes.isEmpty() )
308 for (
const QSize &s : mAdditionalSizes )
314 mIconCache[ entityType ].insert( name, icon );
321 QIcon icon = mIconCache[ entityType ].value( name );
322 if ( !icon.isNull() )
326 for (
auto it = mTargetScreenProperties.constBegin(); it != mTargetScreenProperties.constEnd(); ++it )
328 if ( mAdditionalSizes.isEmpty() )
330 for (
const QSize &s : mAdditionalSizes )
335 mIconCache[ entityType ].insert( name, icon );
342 QIcon icon = mIconCache[ entityType ].value( name );
343 if ( !icon.isNull() )
347 for (
auto it = mTargetScreenProperties.constBegin(); it != mTargetScreenProperties.constEnd(); ++it )
349 if ( mAdditionalSizes.isEmpty() )
351 for (
const QSize &s : mAdditionalSizes )
356 mIconCache[ entityType ].insert( name, icon );
363 QIcon icon = mIconCache[ entityType ].value( name );
364 if ( !icon.isNull() )
370 for (
auto it = mTargetScreenProperties.constBegin(); it != mTargetScreenProperties.constEnd(); ++it )
372 if (
const QgsSymbol *symbol = mStyle->previewSymbolForPatchShape( shape ) )
374 if ( mAdditionalSizes.isEmpty() )
377 for (
const QSize &s : mAdditionalSizes )
384 mIconCache[ entityType ].insert( name, icon );
394 QIcon icon = mIconCache[ entityType ].value( name );
395 if ( !icon.isNull() )
398 if ( sIconGenerator && !mPending3dSymbolIcons.contains( name ) )
400 mPending3dSymbolIcons.insert( name );
405 if ( mAdditionalSizes.isEmpty() )
407 for (
const QSize &s : mAdditionalSizes )
411 mIconCache[ entityType ].insert( name, icon );
434 return mStyle->tagsOfSymbol( entityType, name );
437 return mStyle->isFavorite( entityType, name );
441 switch ( entityType )
445 const QgsSymbol *symbol = mStyle->symbolRef( name );
446 return symbol ?
static_cast< int >( symbol->
type() ) : QVariant();
450 return static_cast< int >( mStyle->legendPatchShapeSymbolType( name ) );
465 switch ( entityType )
468 return static_cast< int >( mStyle->labelSettingsLayerType( name ) );
484 switch ( entityType )
489 const QList< Qgis::GeometryType > types = mStyle->symbol3DCompatibleGeometryTypes( name );
490 res.reserve( types.size() );
493 res << static_cast< int >( type );
514 return mStyle->name();
517 return mStyle->fileName();
529 if (
index.row() < 0 ||
index.row() >=
rowCount( QModelIndex() ) || role != Qt::EditRole )
532 switch (
index.column() )
538 switch ( entityType )
545 name = mEntityNames[ entityType ].value(
index.row() - offsetForEntity( entityType ) );
549 const QString newName = value.toString();
550 return mStyle->renameEntity( entityType, name, newName );
565 Qt::ItemFlags
flags = QAbstractItemModel::flags(
index );
568 return flags | Qt::ItemIsEditable;
578 return headerDataStatic( section, orientation, role );
581QVariant QgsStyleModel::headerDataStatic(
int section, Qt::Orientation orientation,
int role )
583 if ( role == Qt::DisplayRole )
585 if ( orientation == Qt::Vertical )
587 return QVariant( section );
594 return QVariant( tr(
"Name" ) );
597 return QVariant( tr(
"Tags" ) );
612 if ( !hasIndex( row, column,
parent ) )
613 return QModelIndex();
617 return createIndex( row, column );
620 return QModelIndex();
626 return QModelIndex();
635 count += mEntityNames[ type ].size();
648 if ( mAdditionalSizes.contains( size ) )
651 mAdditionalSizes << size;
653 if ( sIconGenerator )
654 sIconGenerator->setIconSizes( mAdditionalSizes );
661 if ( mTargetScreenProperties.contains( properties ) )
664 mTargetScreenProperties.insert( properties );
666 if ( sIconGenerator )
667 sIconGenerator->setTargetScreenProperties( mTargetScreenProperties );
674 sIconGenerator = generator;
680 mIconCache[ type ].remove( name );
681 const QStringList newSymbolNames = mStyle->
allNames( type );
684 const int newNameIndex = newSymbolNames.indexOf( name );
685 if ( newNameIndex < 0 )
688 const int offset = offsetForEntity( type );
689 beginInsertRows( QModelIndex(), newNameIndex + offset, newNameIndex + offset );
690 mEntityNames[ type ] = newSymbolNames;
696 mIconCache[ type ].remove( name );
697 const QStringList oldSymbolNames = mEntityNames[ type ];
698 const QStringList newSymbolNames = mStyle->allNames( type );
701 const int oldNameIndex = oldSymbolNames.indexOf( name );
702 if ( oldNameIndex < 0 )
705 const int offset = offsetForEntity( type );
706 beginRemoveRows( QModelIndex(), oldNameIndex + offset, oldNameIndex + offset );
707 mEntityNames[ type ] = newSymbolNames;
713 mIconCache[ type ].remove( name );
715 const int offset = offsetForEntity( type );
716 QModelIndex i =
index( offset + mEntityNames[ type ].indexOf( name ),
Tags );
717 emit dataChanged( i, i, QVector< int >() << Qt::DecorationRole );
722 const int offset = offsetForEntity( type );
723 QModelIndex i =
index( offset + mEntityNames[ type ].indexOf( name ),
Name );
727void QgsStyleModel::onEntityRename(
QgsStyle::StyleEntity type,
const QString &oldName,
const QString &newName )
729 mIconCache[ type ].remove( oldName );
730 const QStringList oldSymbolNames = mEntityNames[ type ];
731 const QStringList newSymbolNames = mStyle->allNames( type );
734 const int oldNameIndex = oldSymbolNames.indexOf( oldName );
735 if ( oldNameIndex < 0 )
739 const int newNameIndex = newSymbolNames.indexOf( newName );
740 if ( newNameIndex < 0 )
743 if ( newNameIndex == oldNameIndex )
745 mEntityNames[ type ] = newSymbolNames;
749 const int offset = offsetForEntity( type );
750 beginMoveRows( QModelIndex(), oldNameIndex + offset, oldNameIndex + offset, QModelIndex(), ( newNameIndex > oldNameIndex ? newNameIndex + 1 : newNameIndex ) + offset );
751 mEntityNames[ type ] = newSymbolNames;
755void QgsStyleModel::onTagsChanged(
int entity,
const QString &name,
const QStringList & )
758 int row = mEntityNames[type].indexOf( name ) + offsetForEntity( type );
771void QgsStyleModel::rebuildSymbolIcons()
774 mExpressionContext.reset();
778 emit dataChanged(
index( 0, 0 ),
index( lastRow, 0 ), QVector<int>() << Qt::DecorationRole );
782void QgsStyleModel::iconGenerated(
QgsStyle::StyleEntity type,
const QString &name,
const QIcon &icon )
784 int row = mEntityNames[type].indexOf( name ) + offsetForEntity( type );
789 mPending3dSymbolIcons.remove( name );
791 emit dataChanged(
index( row, 0 ),
index( row, 0 ) );
807 int maxRowForEntity = 0;
810 maxRowForEntity += mEntityNames[ type ].size();
811 if ( row < maxRowForEntity )
825 if ( type == entity )
828 offset += mEntityNames[ type ].size();
838 : QSortFilterProxyModel( parent )
842 setSourceModel( mModel );
846void QgsStyleProxyModel::initialize()
848 setSortCaseSensitivity( Qt::CaseInsensitive );
850 setDynamicSortFilter(
true );
860 if ( mSmartGroupId >= 0 )
876 if ( mSmartGroupId >= 0 )
883 : QSortFilterProxyModel( parent )
885 , mStyle( model->style() )
887 setSourceModel( mModel );
892 : QSortFilterProxyModel( parent )
893 , mCombinedModel( model )
895 setSourceModel( mCombinedModel );
901 if ( mFilterString.isEmpty() && !mEntityFilterEnabled && !mSymbolTypeFilterEnabled && mTagId < 0 && mSmartGroupId < 0 && !mFavoritesOnly && mTagFilter.isEmpty() )
904 const QModelIndex index = sourceModel()->index( source_row, 0, source_parent );
909 const QString name = sourceModel()->data( index ).toString();
913 if ( mEntityFilterEnabled && ( mEntityFilters.empty() || !mEntityFilters.contains( styleEntityType ) ) )
917 if ( mSymbolTypeFilterEnabled &&
symbolType != mSymbolType )
922 switch ( styleEntityType )
942 if ( !types.empty() && !types.contains( QVariant::fromValue( mLayerType ) ) )
949 if ( mTagId >= 0 && !mTaggedSymbolNames.contains( name ) )
952 if ( mSmartGroupId >= 0 && !mSmartGroupSymbolNames.contains( name ) )
955 if ( !mTagFilter.isEmpty() && !tags.contains( mTagFilter, Qt::CaseInsensitive ) )
961 if ( !mFilterString.isEmpty() )
965 const QStringList partsToMatch = mFilterString.trimmed().split(
' ' );
967 QStringList partsToSearch = name.split(
' ' );
968 for (
const QString &tag : tags )
970 partsToSearch.append( tag.split(
' ' ) );
973 for (
const QString &part : partsToMatch )
976 for (
const QString &partToSearch : std::as_const( partsToSearch ) )
978 if ( partToSearch.contains( part, Qt::CaseInsensitive ) )
996 if ( leftSource != rightSource )
997 return QString::localeAwareCompare( leftSource, rightSource ) < 0;
1001 return QString::localeAwareCompare( leftName, rightName ) < 0;
1006 mFilterString = filter;
1013 return mFavoritesOnly;
1025 mModel->addDesiredIconSize( size );
1026 if ( mCombinedModel )
1027 mCombinedModel->addDesiredIconSize( size );
1033 mModel->addTargetScreenProperties( properties );
1034 if ( mCombinedModel )
1035 mCombinedModel->addTargetScreenProperties( properties );
1040 return mSymbolTypeFilterEnabled;
1045 mSymbolTypeFilterEnabled = enabled;
1066 mTaggedSymbolNames.clear();
1070 mTaggedSymbolNames.append( mStyle->symbolsWithTag( entity, mTagId ) );
1100 mSmartGroupSymbolNames.clear();
1101 if ( mSmartGroupId >= 0 )
1104 mSmartGroupSymbolNames.append( mStyle->symbolsOfSmartgroup( entity, mSmartGroupId ) );
1112 return mSmartGroupId;
1128 return mEntityFilterEnabled;
1144 mEntityFilters = QList< QgsStyle::StyleEntity >() <<
entityFilter;
1150 mEntityFilters = filters;
GeometryType
The geometry types are used to group Qgis::WkbType in a coarse way.
static const double UI_SCALE_FACTOR
UI scaling factor.
An abstract base class for icon generators for a QgsStyleModel.
void setTargetScreenProperties(const QSet< QgsScreenProperties > &properties)
Sets the target screen properties to use when generating icons.
void setIconSizes(const QList< QSize > &sizes)
Sets the list of icon sizes to generate.
QgsAbstractStyleEntityIconGenerator(QObject *parent)
Constructor for QgsAbstractStyleEntityIconGenerator, with the specified parent object.
QSet< QgsScreenProperties > targetScreenProperties() const
Returns the target screen properties to use when generating icons.
QList< QSize > iconSizes() const
Returns the list of icon sizes to generate.
void iconGenerated(QgsStyle::StyleEntity type, const QString &name, const QIcon &icon)
Emitted when the icon for the style entity with matching type and name has been generated.
static QString defaultThemePath()
Returns the path to the default theme directory.
static QgsImageCache * imageCache()
Returns the application's image cache, used for caching resampled versions of raster images.
static QgsSvgCache * svgCache()
Returns the application's SVG cache, used for caching SVG images and handling parameter replacement w...
static QgsStyleModel * defaultStyleModel()
Returns a shared QgsStyleModel containing the default style library (see QgsStyle::defaultStyle()).
A model which contains entities from multiple QgsStyle databases.
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
void remoteImageFetched(const QString &url)
Emitted when the cache has finished retrieving an image file from a remote url.
Represents a patch shape for use in map legends.
bool isNull() const
Returns true if the patch shape is a null QgsLegendPatchShape, which indicates that the default legen...
Contains settings for how a map layer will be labeled.
static QPixmap labelSettingsPreviewPixmap(const QgsPalLayerSettings &settings, QSize size, const QString &previewText=QString(), int padding=0, const QgsScreenProperties &screen=QgsScreenProperties())
Returns a pixmap preview for label settings.
Stores properties relating to a screen.
double devicePixelRatio() const
Returns the ratio between physical pixels and device-independent pixels for the screen.
bool isValid() const
Returns true if the properties are valid.
A QAbstractItemModel subclass for showing symbol and color ramp entities contained within a QgsStyle ...
@ IsFavorite
Whether entity is flagged as a favorite.
@ LayerType
Layer type (for label settings entities).
@ IsTitle
True if the index corresponds to a title item.
@ SymbolType
Symbol type (for symbol or legend patch shape entities).
@ StyleFileName
File name of associated QgsStyle (QgsStyle::fileName()).
@ Type
Style entity type, see QgsStyle::StyleEntity.
@ CompatibleGeometryTypes
Compatible layer geometry types (for 3D symbols).
@ Tag
String list of tags.
@ StyleName
Name of associated QgsStyle (QgsStyle::name()).
Qt::ItemFlags flags(const QModelIndex &index) const override
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
int columnCount(const QModelIndex &parent=QModelIndex()) const override
QVariant data(const QModelIndex &index, int role) const override
static void setIconGenerator(QgsAbstractStyleEntityIconGenerator *generator)
Sets the icon generator to use for deferred style entity icon generation.
int rowCount(const QModelIndex &parent=QModelIndex()) const override
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole) override
QModelIndex parent(const QModelIndex &index) const override
void addTargetScreenProperties(const QgsScreenProperties &properties)
Adds additional target screen properties to use when generating icons for Qt::DecorationRole data.
QgsStyleModel(QgsStyle *style, QObject *parent=nullptr)
Constructor for QgsStyleModel, for the specified style and parent object.
QgsStyle * style()
Returns the style managed by the model.
void addDesiredIconSize(QSize size)
Adds an additional icon size to generate for Qt::DecorationRole data.
void setEntityFilter(QgsStyle::StyleEntity filter)
Sets the style entity type filter.
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override
bool favoritesOnly() const
Returns true if the model is showing only favorited entities.
void setSymbolTypeFilterEnabled(bool enabled)
Sets whether filtering by symbol type is enabled.
void setTagId(int id)
Sets a tag id to filter style entities by.
QString tagString() const
Returns the tag string used to filter style entities by.
Qgis::SymbolType symbolType() const
Returns the symbol type filter.
void setTagString(const QString &tag)
Sets a tag to filter style entities by.
QgsStyle::StyleEntity entityFilter() const
Returns the style entity type filter.
QgsStyleProxyModel(QgsStyle *style, QObject *parent=nullptr)
Constructor for QgsStyleProxyModel, for the specified style and parent object.
int tagId() const
Returns the tag id used to filter style entities by.
void setEntityFilters(const QList< QgsStyle::StyleEntity > &filters)
Sets the style entity type filters.
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override
void setFavoritesOnly(bool favoritesOnly)
Sets whether the model should show only favorited entities.
void setSymbolType(Qgis::SymbolType type)
Sets the symbol type filter.
bool entityFilterEnabled() const
Returns true if filtering by entity type is enabled.
Qgis::GeometryType layerType() const
Returns the layer type filter, or Qgis::GeometryType::Unknown if no layer type filter is present.
void addDesiredIconSize(QSize size)
Adds an additional icon size to generate for Qt::DecorationRole data.
void addTargetScreenProperties(const QgsScreenProperties &properties)
Adds additional target screen properties to use when generating icons for Qt::DecorationRole data.
void setEntityFilterEnabled(bool enabled)
Sets whether filtering by entity type is enabled.
void setSmartGroupId(int id)
Sets a smart group id to filter style entities by.
bool symbolTypeFilterEnabled() const
Returns true if filtering by symbol type is enabled.
int smartGroupId() const
Returns the smart group id used to filter style entities by.
void setFilterString(const QString &filter)
Sets a filter string, such that only symbol entities with names matching the specified string will be...
void setLayerType(Qgis::GeometryType type)
Sets the layer type filter.
A database of saved style entities, including symbols, color ramps, text formats and others.
QStringList allNames(StyleEntity type) const
Returns a list of the names of all existing entities of the specified type.
void entityChanged(QgsStyle::StyleEntity entity, const QString &name)
Emitted whenever an entity's definition is changed.
void rebuildIconPreviews()
Emitted whenever icon previews for entities in the style must be rebuilt.
StyleEntity
Enum for Entities involved in a style.
@ LabelSettingsEntity
Label settings.
@ TextFormatEntity
Text formats.
@ SmartgroupEntity
Smart groups.
@ Symbol3DEntity
3D symbol entity
@ ColorrampEntity
Color ramps.
@ LegendPatchShapeEntity
Legend patch shape.
void entityRenamed(QgsStyle::StyleEntity entity, const QString &oldName, const QString &newName)
Emitted whenever a entity of the specified type has been renamed from oldName to newName.
void initialized()
Emitted when the style database has been fully initialized.
void entityTagsChanged(QgsStyle::StyleEntity entity, const QString &name, const QStringList &newTags)
Emitted whenever an entity's tags are changed.
void favoritedChanged(QgsStyle::StyleEntity entity, const QString &name, bool isFavorite)
Emitted whenever an entity is either favorited or un-favorited.
void entityRemoved(QgsStyle::StyleEntity entity, const QString &name)
Emitted whenever an entity of the specified type is removed from the style and the database has been ...
void entityAdded(QgsStyle::StyleEntity entity, const QString &name)
Emitted every time a new entity has been added to the database.
void remoteSvgFetched(const QString &url)
Emitted when the cache has finished retrieving an SVG file from a remote url.
static QPixmap colorRampPreviewPixmap(QgsColorRamp *ramp, QSize size, int padding=0, Qt::Orientation direction=Qt::Horizontal, bool flipDirection=false, bool drawTransparentBackground=true)
Returns a pixmap preview for a color ramp.
static QPixmap symbolPreviewPixmap(const QgsSymbol *symbol, QSize size, int padding=0, QgsRenderContext *customContext=nullptr, bool selected=false, const QgsExpressionContext *expressionContext=nullptr, const QgsLegendPatchShape *shape=nullptr, const QgsScreenProperties &screen=QgsScreenProperties())
Returns a pixmap preview for a color ramp.
Abstract base class for all rendered symbols.
Qgis::SymbolType type() const
Returns the symbol's type.
Container for all settings relating to text rendering.
static QPixmap textFormatPreviewPixmap(const QgsTextFormat &format, QSize size, const QString &previewText=QString(), int padding=0, const QgsScreenProperties &screen=QgsScreenProperties())
Returns a pixmap preview for a text format.
const double ICON_PADDING_FACTOR