31#include "moc_qgsstylemodel.cpp"
33using namespace Qt::StringLiterals;
62 mTargetScreenProperties = properties;
67 return mTargetScreenProperties;
76 : QAbstractItemModel(
parent )
81 if ( mStyle->isInitialized() )
92void QgsStyleModel::initStyleModel()
97 mEntityNames.insert( entity, mStyle->
allNames( entity ) );
103 mTargetScreenProperties.insert( QgsScreenProperties() );
121 if ( sIconGenerator )
134 switch ( entityType )
141 name = mEntityNames[ entityType ].value(
index.row() - offsetForEntity( entityType ) );
147 case Qt::DisplayRole:
148 case Qt::ToolTipRole:
151 switch (
index.column() )
155 const QStringList tags = mStyle->tagsOfSymbol( entityType, name );
157 if ( role == Qt::ToolTipRole )
159 QString tooltip = u
"<h3>%1</h3><p><i>%2</i>"_s.arg( name,
160 tags.count() > 0 ? tags.join(
", "_L1 ) : tr(
"Not tagged" ) );
164 for (
auto it = mTargetScreenProperties.constBegin(); it != mTargetScreenProperties.constEnd(); ++it )
166 if ( !maxDevicePixelRatioScreen.
isValid() || it->devicePixelRatio() > maxDevicePixelRatioScreen.
devicePixelRatio() )
167 maxDevicePixelRatioScreen = *it;
170 switch ( entityType )
175 std::unique_ptr< QgsSymbol > symbol( mStyle->symbol( name ) );
178 int width =
static_cast< int >(
Qgis::UI_SCALE_FACTOR * QFontMetrics(
data(
index, Qt::FontRole ).value< QFont >() ).horizontalAdvance(
'X' ) * 23 );
179 int height =
static_cast< int >( width / 1.61803398875 );
182 QBuffer buffer( &
data );
183 pm.save( &buffer,
"PNG", 100 );
184 tooltip += u
"<p><img src='data:image/png;base64, %3' width=\"%4\">"_s.arg( QString(
data.toBase64() ) ).arg( width );
191 int width =
static_cast< int >(
Qgis::UI_SCALE_FACTOR * QFontMetrics(
data(
index, Qt::FontRole ).value< QFont >() ).horizontalAdvance(
'X' ) * 23 );
192 int height =
static_cast< int >( width / 1.61803398875 );
196 QBuffer buffer( &
data );
197 pm.save( &buffer,
"PNG", 100 );
198 tooltip += u
"<p><img src='data:image/png;base64, %3' width=\"%4\">"_s.arg( QString(
data.toBase64() ) ).arg( width );
204 int width =
static_cast< int >(
Qgis::UI_SCALE_FACTOR * QFontMetrics(
data(
index, Qt::FontRole ).value< QFont >() ).horizontalAdvance(
'X' ) * 23 );
205 int height =
static_cast< int >( width / 1.61803398875 );
209 QBuffer buffer( &
data );
210 pm.save( &buffer,
"PNG", 100 );
211 tooltip += u
"<p><img src='data:image/png;base64, %3' width=\"%4\">"_s.arg( QString(
data.toBase64() ) ).arg( width );
217 int width =
static_cast< int >(
Qgis::UI_SCALE_FACTOR * QFontMetrics(
data(
index, Qt::FontRole ).value< QFont >() ).horizontalAdvance(
'X' ) * 23 );
218 int height =
static_cast< int >( width / 1.61803398875 );
221 if (
const QgsSymbol *symbol = mStyle->previewSymbolForPatchShape( shape ) )
225 QBuffer buffer( &
data );
226 pm.save( &buffer,
"PNG", 100 );
227 tooltip += u
"<p><img src='data:image/png;base64, %3' width=\"%4\">"_s.arg( QString(
data.toBase64() ) ).arg( width );
246 return mStyle->tagsOfSymbol( entityType, name ).join(
", "_L1 );
254 case Qt::DecorationRole:
259 if ( !mExpressionContext )
265 mExpressionContext = std::make_unique< QgsExpressionContext >();
269 switch (
index.column() )
272 switch ( entityType )
277 QIcon icon = mIconCache[ entityType ].value( name );
278 if ( !icon.isNull() )
281 std::unique_ptr< QgsSymbol > symbol( mStyle->symbol( name ) );
284 for (
auto it = mTargetScreenProperties.constBegin(); it != mTargetScreenProperties.constEnd(); ++it )
286 if ( mAdditionalSizes.isEmpty() )
289 for (
const QSize &s : mAdditionalSizes )
296 mIconCache[ entityType ].insert( name, icon );
302 QIcon icon = mIconCache[ entityType ].value( name );
303 if ( !icon.isNull() )
306 std::unique_ptr< QgsColorRamp > ramp( mStyle->colorRamp( name ) );
309 if ( mAdditionalSizes.isEmpty() )
311 for (
const QSize &s : mAdditionalSizes )
317 mIconCache[ entityType ].insert( name, icon );
324 QIcon icon = mIconCache[ entityType ].value( name );
325 if ( !icon.isNull() )
329 for (
auto it = mTargetScreenProperties.constBegin(); it != mTargetScreenProperties.constEnd(); ++it )
331 if ( mAdditionalSizes.isEmpty() )
333 for (
const QSize &s : mAdditionalSizes )
338 mIconCache[ entityType ].insert( name, icon );
345 QIcon icon = mIconCache[ entityType ].value( name );
346 if ( !icon.isNull() )
350 for (
auto it = mTargetScreenProperties.constBegin(); it != mTargetScreenProperties.constEnd(); ++it )
352 if ( mAdditionalSizes.isEmpty() )
354 for (
const QSize &s : mAdditionalSizes )
359 mIconCache[ entityType ].insert( name, icon );
366 QIcon icon = mIconCache[ entityType ].value( name );
367 if ( !icon.isNull() )
373 for (
auto it = mTargetScreenProperties.constBegin(); it != mTargetScreenProperties.constEnd(); ++it )
375 if (
const QgsSymbol *symbol = mStyle->previewSymbolForPatchShape( shape ) )
377 if ( mAdditionalSizes.isEmpty() )
380 for (
const QSize &s : mAdditionalSizes )
387 mIconCache[ entityType ].insert( name, icon );
397 QIcon icon = mIconCache[ entityType ].value( name );
398 if ( !icon.isNull() )
401 if ( sIconGenerator && !mPending3dSymbolIcons.contains( name ) )
403 mPending3dSymbolIcons.insert( name );
408 if ( mAdditionalSizes.isEmpty() )
410 for (
const QSize &s : mAdditionalSizes )
414 mIconCache[ entityType ].insert( name, icon );
437 return mStyle->tagsOfSymbol( entityType, name );
440 return mStyle->isFavorite( entityType, name );
444 switch ( entityType )
448 const QgsSymbol *symbol = mStyle->symbolRef( name );
449 return symbol ?
static_cast< int >( symbol->
type() ) : QVariant();
453 return static_cast< int >( mStyle->legendPatchShapeSymbolType( name ) );
468 switch ( entityType )
471 return static_cast< int >( mStyle->labelSettingsLayerType( name ) );
487 switch ( entityType )
492 const QList< Qgis::GeometryType > types = mStyle->symbol3DCompatibleGeometryTypes( name );
493 res.reserve( types.size() );
496 res << static_cast< int >( type );
517 return mStyle->name();
520 return mStyle->fileName();
532 if (
index.row() < 0 ||
index.row() >=
rowCount( QModelIndex() ) || role != Qt::EditRole )
535 switch (
index.column() )
541 switch ( entityType )
548 name = mEntityNames[ entityType ].value(
index.row() - offsetForEntity( entityType ) );
552 const QString newName = value.toString();
553 return mStyle->renameEntity( entityType, name, newName );
568 Qt::ItemFlags
flags = QAbstractItemModel::flags(
index );
571 return flags | Qt::ItemIsEditable;
581 return headerDataStatic( section, orientation, role );
584QVariant QgsStyleModel::headerDataStatic(
int section, Qt::Orientation orientation,
int role )
586 if ( role == Qt::DisplayRole )
588 if ( orientation == Qt::Vertical )
590 return QVariant( section );
597 return QVariant( tr(
"Name" ) );
600 return QVariant( tr(
"Tags" ) );
615 if ( !hasIndex( row, column,
parent ) )
616 return QModelIndex();
620 return createIndex( row, column );
623 return QModelIndex();
629 return QModelIndex();
638 count += mEntityNames[ type ].size();
651 if ( mAdditionalSizes.contains( size ) )
654 mAdditionalSizes << size;
656 if ( sIconGenerator )
657 sIconGenerator->setIconSizes( mAdditionalSizes );
664 if ( mTargetScreenProperties.contains( properties ) )
667 mTargetScreenProperties.insert( properties );
669 if ( sIconGenerator )
670 sIconGenerator->setTargetScreenProperties( mTargetScreenProperties );
677 sIconGenerator = generator;
683 mIconCache[ type ].remove( name );
684 const QStringList newSymbolNames = mStyle->
allNames( type );
687 const int newNameIndex = newSymbolNames.indexOf( name );
688 if ( newNameIndex < 0 )
691 const int offset = offsetForEntity( type );
692 beginInsertRows( QModelIndex(), newNameIndex + offset, newNameIndex + offset );
693 mEntityNames[ type ] = newSymbolNames;
699 mIconCache[ type ].remove( name );
700 const QStringList oldSymbolNames = mEntityNames[ type ];
701 const QStringList newSymbolNames = mStyle->allNames( type );
704 const int oldNameIndex = oldSymbolNames.indexOf( name );
705 if ( oldNameIndex < 0 )
708 const int offset = offsetForEntity( type );
709 beginRemoveRows( QModelIndex(), oldNameIndex + offset, oldNameIndex + offset );
710 mEntityNames[ type ] = newSymbolNames;
716 mIconCache[ type ].remove( name );
718 const int offset = offsetForEntity( type );
719 QModelIndex i =
index( offset + mEntityNames[ type ].indexOf( name ),
Tags );
720 emit dataChanged( i, i, QVector< int >() << Qt::DecorationRole );
725 const int offset = offsetForEntity( type );
726 QModelIndex i =
index( offset + mEntityNames[ type ].indexOf( name ),
Name );
730void QgsStyleModel::onEntityRename(
QgsStyle::StyleEntity type,
const QString &oldName,
const QString &newName )
732 mIconCache[ type ].remove( oldName );
733 const QStringList oldSymbolNames = mEntityNames[ type ];
734 const QStringList newSymbolNames = mStyle->allNames( type );
737 const int oldNameIndex = oldSymbolNames.indexOf( oldName );
738 if ( oldNameIndex < 0 )
742 const int newNameIndex = newSymbolNames.indexOf( newName );
743 if ( newNameIndex < 0 )
746 if ( newNameIndex == oldNameIndex )
748 mEntityNames[ type ] = newSymbolNames;
752 const int offset = offsetForEntity( type );
753 beginMoveRows( QModelIndex(), oldNameIndex + offset, oldNameIndex + offset, QModelIndex(), ( newNameIndex > oldNameIndex ? newNameIndex + 1 : newNameIndex ) + offset );
754 mEntityNames[ type ] = newSymbolNames;
758void QgsStyleModel::onTagsChanged(
int entity,
const QString &name,
const QStringList & )
761 int row = mEntityNames[type].indexOf( name ) + offsetForEntity( type );
774void QgsStyleModel::rebuildSymbolIcons()
777 mExpressionContext.reset();
781 emit dataChanged(
index( 0, 0 ),
index( lastRow, 0 ), QVector<int>() << Qt::DecorationRole );
785void QgsStyleModel::iconGenerated(
QgsStyle::StyleEntity type,
const QString &name,
const QIcon &icon )
787 int row = mEntityNames[type].indexOf( name ) + offsetForEntity( type );
792 mPending3dSymbolIcons.remove( name );
794 emit dataChanged(
index( row, 0 ),
index( row, 0 ) );
810 int maxRowForEntity = 0;
813 maxRowForEntity += mEntityNames[ type ].size();
814 if ( row < maxRowForEntity )
828 if ( type == entity )
831 offset += mEntityNames[ type ].size();
841 : QSortFilterProxyModel( parent )
845 setSourceModel( mModel );
849void QgsStyleProxyModel::initialize()
851 setSortCaseSensitivity( Qt::CaseInsensitive );
853 setDynamicSortFilter(
true );
863 if ( mSmartGroupId >= 0 )
879 if ( mSmartGroupId >= 0 )
886 : QSortFilterProxyModel( parent )
888 , mStyle( model->style() )
890 setSourceModel( mModel );
895 : QSortFilterProxyModel( parent )
896 , mCombinedModel( model )
898 setSourceModel( mCombinedModel );
904 if ( mFilterString.isEmpty() && !mEntityFilterEnabled && !mSymbolTypeFilterEnabled && mTagId < 0 && mSmartGroupId < 0 && !mFavoritesOnly && mTagFilter.isEmpty() )
907 const QModelIndex index = sourceModel()->index( source_row, 0, source_parent );
912 const QString name = sourceModel()->data( index ).toString();
916 if ( mEntityFilterEnabled && ( mEntityFilters.empty() || !mEntityFilters.contains( styleEntityType ) ) )
920 if ( mSymbolTypeFilterEnabled &&
symbolType != mSymbolType )
925 switch ( styleEntityType )
945 if ( !types.empty() && !types.contains( QVariant::fromValue( mLayerType ) ) )
952 if ( mTagId >= 0 && !mTaggedSymbolNames.contains( name ) )
955 if ( mSmartGroupId >= 0 && !mSmartGroupSymbolNames.contains( name ) )
958 if ( !mTagFilter.isEmpty() && !tags.contains( mTagFilter, Qt::CaseInsensitive ) )
964 if ( !mFilterString.isEmpty() )
968 const QStringList partsToMatch = mFilterString.trimmed().split(
' ' );
970 QStringList partsToSearch = name.split(
' ' );
971 for (
const QString &tag : tags )
973 partsToSearch.append( tag.split(
' ' ) );
976 for (
const QString &part : partsToMatch )
979 for (
const QString &partToSearch : std::as_const( partsToSearch ) )
981 if ( partToSearch.contains( part, Qt::CaseInsensitive ) )
999 if ( leftSource != rightSource )
1000 return QString::localeAwareCompare( leftSource, rightSource ) < 0;
1004 return QString::localeAwareCompare( leftName, rightName ) < 0;
1009 mFilterString = filter;
1016 return mFavoritesOnly;
1028 mModel->addDesiredIconSize( size );
1029 if ( mCombinedModel )
1030 mCombinedModel->addDesiredIconSize( size );
1036 mModel->addTargetScreenProperties( properties );
1037 if ( mCombinedModel )
1038 mCombinedModel->addTargetScreenProperties( properties );
1043 return mSymbolTypeFilterEnabled;
1048 mSymbolTypeFilterEnabled = enabled;
1069 mTaggedSymbolNames.clear();
1073 mTaggedSymbolNames.append( mStyle->symbolsWithTag( entity, mTagId ) );
1103 mSmartGroupSymbolNames.clear();
1104 if ( mSmartGroupId >= 0 )
1107 mSmartGroupSymbolNames.append( mStyle->symbolsOfSmartgroup( entity, mSmartGroupId ) );
1115 return mSmartGroupId;
1131 return mEntityFilterEnabled;
1147 mEntityFilters = QList< QgsStyle::StyleEntity >() <<
entityFilter;
1153 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