31#include "moc_qgsstylemodel.cpp"
33using namespace Qt::StringLiterals;
61 mTargetScreenProperties = properties;
66 return mTargetScreenProperties;
75 : QAbstractItemModel(
parent )
80 if ( mStyle->isInitialized() )
91void QgsStyleModel::initStyleModel()
96 mEntityNames.insert( entity, mStyle->
allNames( entity ) );
102 mTargetScreenProperties.insert( QgsScreenProperties() );
120 if ( sIconGenerator )
133 switch ( entityType )
140 name = mEntityNames[entityType].value(
index.row() - offsetForEntity( entityType ) );
146 case Qt::DisplayRole:
147 case Qt::ToolTipRole:
150 switch (
index.column() )
154 const QStringList tags = mStyle->tagsOfSymbol( entityType, name );
156 if ( role == Qt::ToolTipRole )
158 QString tooltip = u
"<h3>%1</h3><p><i>%2</i>"_s.arg( name, tags.count() > 0 ? tags.join(
", "_L1 ) : tr(
"Not tagged" ) );
162 for (
auto it = mTargetScreenProperties.constBegin(); it != mTargetScreenProperties.constEnd(); ++it )
164 if ( !maxDevicePixelRatioScreen.
isValid() || it->devicePixelRatio() > maxDevicePixelRatioScreen.
devicePixelRatio() )
165 maxDevicePixelRatioScreen = *it;
168 switch ( entityType )
173 std::unique_ptr< QgsSymbol > symbol( mStyle->symbol( name ) );
176 int width =
static_cast< int >(
Qgis::UI_SCALE_FACTOR * QFontMetrics(
data(
index, Qt::FontRole ).value< QFont >() ).horizontalAdvance(
'X' ) * 23 );
177 int height =
static_cast< int >( width / 1.61803398875 );
180 QBuffer buffer( &
data );
181 pm.save( &buffer,
"PNG", 100 );
182 tooltip += u
"<p><img src='data:image/png;base64, %3' width=\"%4\">"_s.arg( QString(
data.toBase64() ) ).arg( width );
189 int width =
static_cast< int >(
Qgis::UI_SCALE_FACTOR * QFontMetrics(
data(
index, Qt::FontRole ).value< QFont >() ).horizontalAdvance(
'X' ) * 23 );
190 int height =
static_cast< int >( width / 1.61803398875 );
194 QBuffer buffer( &
data );
195 pm.save( &buffer,
"PNG", 100 );
196 tooltip += u
"<p><img src='data:image/png;base64, %3' width=\"%4\">"_s.arg( QString(
data.toBase64() ) ).arg( width );
202 int width =
static_cast< int >(
Qgis::UI_SCALE_FACTOR * QFontMetrics(
data(
index, Qt::FontRole ).value< QFont >() ).horizontalAdvance(
'X' ) * 23 );
203 int height =
static_cast< int >( width / 1.61803398875 );
207 QBuffer buffer( &
data );
208 pm.save( &buffer,
"PNG", 100 );
209 tooltip += u
"<p><img src='data:image/png;base64, %3' width=\"%4\">"_s.arg( QString(
data.toBase64() ) ).arg( width );
215 int width =
static_cast< int >(
Qgis::UI_SCALE_FACTOR * QFontMetrics(
data(
index, Qt::FontRole ).value< QFont >() ).horizontalAdvance(
'X' ) * 23 );
216 int height =
static_cast< int >( width / 1.61803398875 );
219 if (
const QgsSymbol *symbol = mStyle->previewSymbolForPatchShape( shape ) )
223 QBuffer buffer( &
data );
224 pm.save( &buffer,
"PNG", 100 );
225 tooltip += u
"<p><img src='data:image/png;base64, %3' width=\"%4\">"_s.arg( QString(
data.toBase64() ) ).arg( width );
244 return mStyle->tagsOfSymbol( entityType, name ).join(
", "_L1 );
252 case Qt::DecorationRole:
257 if ( !mExpressionContext )
263 mExpressionContext = std::make_unique< QgsExpressionContext >();
267 switch (
index.column() )
270 switch ( entityType )
275 QIcon icon = mIconCache[entityType].value( name );
276 if ( !icon.isNull() )
279 std::unique_ptr< QgsSymbol > symbol( mStyle->symbol( name ) );
282 for (
auto it = mTargetScreenProperties.constBegin(); it != mTargetScreenProperties.constEnd(); ++it )
284 if ( mAdditionalSizes.isEmpty() )
287 for (
const QSize &s : mAdditionalSizes )
295 mIconCache[entityType].insert( name, icon );
301 QIcon icon = mIconCache[entityType].value( name );
302 if ( !icon.isNull() )
305 std::unique_ptr< QgsColorRamp > ramp( mStyle->colorRamp( name ) );
308 if ( mAdditionalSizes.isEmpty() )
310 for (
const QSize &s : mAdditionalSizes )
315 mIconCache[entityType].insert( name, icon );
322 QIcon icon = mIconCache[entityType].value( name );
323 if ( !icon.isNull() )
327 for (
auto it = mTargetScreenProperties.constBegin(); it != mTargetScreenProperties.constEnd(); ++it )
329 if ( mAdditionalSizes.isEmpty() )
331 for (
const QSize &s : mAdditionalSizes )
336 mIconCache[entityType].insert( name, icon );
343 QIcon icon = mIconCache[entityType].value( name );
344 if ( !icon.isNull() )
348 for (
auto it = mTargetScreenProperties.constBegin(); it != mTargetScreenProperties.constEnd(); ++it )
350 if ( mAdditionalSizes.isEmpty() )
352 for (
const QSize &s : mAdditionalSizes )
357 mIconCache[entityType].insert( name, icon );
364 QIcon icon = mIconCache[entityType].value( name );
365 if ( !icon.isNull() )
371 for (
auto it = mTargetScreenProperties.constBegin(); it != mTargetScreenProperties.constEnd(); ++it )
373 if (
const QgsSymbol *symbol = mStyle->previewSymbolForPatchShape( shape ) )
375 if ( mAdditionalSizes.isEmpty() )
378 for (
const QSize &s : mAdditionalSizes )
385 mIconCache[entityType].insert( name, icon );
395 QIcon icon = mIconCache[entityType].value( name );
396 if ( !icon.isNull() )
399 if ( sIconGenerator && !mPending3dSymbolIcons.contains( name ) )
401 mPending3dSymbolIcons.insert( name );
406 if ( mAdditionalSizes.isEmpty() )
408 for (
const QSize &s : mAdditionalSizes )
412 mIconCache[entityType].insert( name, icon );
435 return mStyle->tagsOfSymbol( entityType, name );
438 return mStyle->isFavorite( entityType, name );
442 switch ( entityType )
446 const QgsSymbol *symbol = mStyle->symbolRef( name );
447 return symbol ?
static_cast< int >( symbol->
type() ) : QVariant();
451 return static_cast< int >( mStyle->legendPatchShapeSymbolType( name ) );
466 switch ( entityType )
469 return static_cast< int >( mStyle->labelSettingsLayerType( name ) );
485 switch ( entityType )
490 const QList< Qgis::GeometryType > types = mStyle->symbol3DCompatibleGeometryTypes( name );
491 res.reserve( types.size() );
494 res << static_cast< int >( type );
515 return mStyle->name();
518 return mStyle->fileName();
530 if (
index.row() < 0 ||
index.row() >=
rowCount( QModelIndex() ) || role != Qt::EditRole )
533 switch (
index.column() )
539 switch ( entityType )
546 name = mEntityNames[entityType].value(
index.row() - offsetForEntity( entityType ) );
550 const QString newName = value.toString();
551 return mStyle->renameEntity( entityType, name, newName );
566 Qt::ItemFlags
flags = QAbstractItemModel::flags(
index );
569 return flags | Qt::ItemIsEditable;
579 return headerDataStatic( section, orientation, role );
582QVariant QgsStyleModel::headerDataStatic(
int section, Qt::Orientation orientation,
int role )
584 if ( role == Qt::DisplayRole )
586 if ( orientation == Qt::Vertical )
588 return QVariant( section );
595 return QVariant( tr(
"Name" ) );
598 return QVariant( tr(
"Tags" ) );
613 if ( !hasIndex( row, column,
parent ) )
614 return QModelIndex();
618 return createIndex( row, column );
621 return QModelIndex();
627 return QModelIndex();
636 count += mEntityNames[type].size();
649 if ( mAdditionalSizes.contains( size ) )
652 mAdditionalSizes << size;
654 if ( sIconGenerator )
655 sIconGenerator->setIconSizes( mAdditionalSizes );
662 if ( mTargetScreenProperties.contains( properties ) )
665 mTargetScreenProperties.insert( properties );
667 if ( sIconGenerator )
668 sIconGenerator->setTargetScreenProperties( mTargetScreenProperties );
675 sIconGenerator = generator;
681 mIconCache[type].remove( name );
682 const QStringList newSymbolNames = mStyle->
allNames( type );
685 const int newNameIndex = newSymbolNames.indexOf( name );
686 if ( newNameIndex < 0 )
689 const int offset = offsetForEntity( type );
690 beginInsertRows( QModelIndex(), newNameIndex + offset, newNameIndex + offset );
691 mEntityNames[type] = newSymbolNames;
697 mIconCache[type].remove( name );
698 const QStringList oldSymbolNames = mEntityNames[type];
699 const QStringList newSymbolNames = mStyle->allNames( type );
702 const int oldNameIndex = oldSymbolNames.indexOf( name );
703 if ( oldNameIndex < 0 )
706 const int offset = offsetForEntity( type );
707 beginRemoveRows( QModelIndex(), oldNameIndex + offset, oldNameIndex + offset );
708 mEntityNames[type] = newSymbolNames;
714 mIconCache[type].remove( name );
716 const int offset = offsetForEntity( type );
717 QModelIndex i =
index( offset + mEntityNames[type].indexOf( name ),
Tags );
718 emit dataChanged( i, i, QVector< int >() << Qt::DecorationRole );
723 const int offset = offsetForEntity( type );
724 QModelIndex i =
index( offset + mEntityNames[type].indexOf( name ),
Name );
728void QgsStyleModel::onEntityRename(
QgsStyle::StyleEntity type,
const QString &oldName,
const QString &newName )
730 mIconCache[type].remove( oldName );
731 const QStringList oldSymbolNames = mEntityNames[type];
732 const QStringList newSymbolNames = mStyle->allNames( type );
735 const int oldNameIndex = oldSymbolNames.indexOf( oldName );
736 if ( oldNameIndex < 0 )
740 const int newNameIndex = newSymbolNames.indexOf( newName );
741 if ( newNameIndex < 0 )
744 if ( newNameIndex == oldNameIndex )
746 mEntityNames[type] = newSymbolNames;
750 const int offset = offsetForEntity( type );
751 beginMoveRows( QModelIndex(), oldNameIndex + offset, oldNameIndex + offset, QModelIndex(), ( newNameIndex > oldNameIndex ? newNameIndex + 1 : newNameIndex ) + offset );
752 mEntityNames[type] = newSymbolNames;
756void QgsStyleModel::onTagsChanged(
int entity,
const QString &name,
const QStringList & )
759 int row = mEntityNames[type].indexOf( name ) + offsetForEntity( type );
772void QgsStyleModel::rebuildSymbolIcons()
775 mExpressionContext.reset();
779 emit dataChanged(
index( 0, 0 ),
index( lastRow, 0 ), QVector<int>() << Qt::DecorationRole );
783void QgsStyleModel::iconGenerated(
QgsStyle::StyleEntity type,
const QString &name,
const QIcon &icon )
785 int row = mEntityNames[type].indexOf( name ) + offsetForEntity( type );
790 mPending3dSymbolIcons.remove( name );
792 emit dataChanged(
index( row, 0 ),
index( row, 0 ) );
808 int maxRowForEntity = 0;
811 maxRowForEntity += mEntityNames[type].size();
812 if ( row < maxRowForEntity )
826 if ( type == entity )
829 offset += mEntityNames[type].size();
839 : QSortFilterProxyModel( parent )
843 setSourceModel( mModel );
847void QgsStyleProxyModel::initialize()
849 setSortCaseSensitivity( Qt::CaseInsensitive );
851 setDynamicSortFilter(
true );
860 if ( mSmartGroupId >= 0 )
875 if ( mSmartGroupId >= 0 )
882 : QSortFilterProxyModel( parent )
884 , mStyle( model->style() )
886 setSourceModel( mModel );
891 : QSortFilterProxyModel( parent )
892 , mCombinedModel( model )
894 setSourceModel( mCombinedModel );
900 if ( mFilterString.isEmpty() && !mEntityFilterEnabled && !mSymbolTypeFilterEnabled && mTagId < 0 && mSmartGroupId < 0 && !mFavoritesOnly && mTagFilter.isEmpty() )
903 const QModelIndex index = sourceModel()->index( source_row, 0, source_parent );
908 const QString name = sourceModel()->data( index ).toString();
912 if ( mEntityFilterEnabled && ( mEntityFilters.empty() || !mEntityFilters.contains( styleEntityType ) ) )
916 if ( mSymbolTypeFilterEnabled &&
symbolType != mSymbolType )
921 switch ( styleEntityType )
941 if ( !types.empty() && !types.contains( QVariant::fromValue( mLayerType ) ) )
948 if ( mTagId >= 0 && !mTaggedSymbolNames.contains( name ) )
951 if ( mSmartGroupId >= 0 && !mSmartGroupSymbolNames.contains( name ) )
954 if ( !mTagFilter.isEmpty() && !tags.contains( mTagFilter, Qt::CaseInsensitive ) )
960 if ( !mFilterString.isEmpty() )
964 const QStringList partsToMatch = mFilterString.trimmed().split(
' ' );
966 QStringList partsToSearch = name.split(
' ' );
967 for (
const QString &tag : tags )
969 partsToSearch.append( tag.split(
' ' ) );
972 for (
const QString &part : partsToMatch )
975 for (
const QString &partToSearch : std::as_const( partsToSearch ) )
977 if ( partToSearch.contains( part, Qt::CaseInsensitive ) )
995 if ( leftSource != rightSource )
996 return QString::localeAwareCompare( leftSource, rightSource ) < 0;
1000 return QString::localeAwareCompare( leftName, rightName ) < 0;
1005 mFilterString = filter;
1012 return mFavoritesOnly;
1024 mModel->addDesiredIconSize( size );
1025 if ( mCombinedModel )
1026 mCombinedModel->addDesiredIconSize( size );
1032 mModel->addTargetScreenProperties( properties );
1033 if ( mCombinedModel )
1034 mCombinedModel->addTargetScreenProperties( properties );
1039 return mSymbolTypeFilterEnabled;
1044 mSymbolTypeFilterEnabled = enabled;
1065 mTaggedSymbolNames.clear();
1069 mTaggedSymbolNames.append( mStyle->symbolsWithTag( entity, mTagId ) );
1099 mSmartGroupSymbolNames.clear();
1100 if ( mSmartGroupId >= 0 )
1103 mSmartGroupSymbolNames.append( mStyle->symbolsOfSmartgroup( entity, mSmartGroupId ) );
1111 return mSmartGroupId;
1127 return mEntityFilterEnabled;
1143 mEntityFilters = QList< QgsStyle::StyleEntity >() <<
entityFilter;
1149 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