Add API to allow generation of icons for 3d symbols from app

(still not implement -- but a necessary prerequisite to proper icons)
This commit is contained in:
Nyall Dawson 2020-07-25 14:06:57 +10:00
parent c938de4827
commit 1484a30fef
7 changed files with 223 additions and 0 deletions

View File

@ -9,6 +9,7 @@
class QgsStyleModel: QAbstractItemModel
{
%Docstring
@ -85,6 +86,7 @@ This allows style icons to be generated at an icon size which
corresponds exactly to the view's icon size in which this model is used.
%End
};
class QgsStyleProxyModel: QSortFilterProxyModel

View File

@ -0,0 +1,37 @@
/***************************************************************************
qgs3dicongenerator.cpp
---------------
begin : July 2020
copyright : (C) 2020 by Nyall Dawson
email : nyall dot dawson at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgs3dicongenerator.h"
#include "qgsapplication.h"
Qgs3DIconGenerator::Qgs3DIconGenerator( QObject *parent )
: QgsAbstractStyleEntityIconGenerator( parent )
{
}
void Qgs3DIconGenerator::generateIcon( QgsStyle *, QgsStyle::StyleEntity type, const QString &name )
{
QIcon icon;
const QList< QSize > sizes = iconSizes();
if ( sizes.isEmpty() )
icon.addFile( QgsApplication::defaultThemePath() + QDir::separator() + QStringLiteral( "3d.svg" ), QSize( 24, 24 ) );
for ( const QSize &s : sizes )
{
icon.addFile( QgsApplication::defaultThemePath() + QDir::separator() + QStringLiteral( "3d.svg" ), s );
}
emit iconGenerated( type, name, icon );
}

View File

@ -0,0 +1,34 @@
/***************************************************************************
qgs3dicongenerator.h
---------------
begin : July 2020
copyright : (C) 2020 by Nyall Dawson
email : nyall dot dawson at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGS3DICONGENERATOR_H
#define QGS3DICONGENERATOR_H
#include "qgsstylemodel.h"
class QgsSymbol;
class Qgs3DIconGenerator : public QgsAbstractStyleEntityIconGenerator
{
Q_OBJECT
public:
Qgs3DIconGenerator( QObject *parent );
void generateIcon( QgsStyle *style, QgsStyle::StyleEntity type, const QString &name ) override;
};
#endif //QGS3DICONGENERATOR_H

View File

@ -262,6 +262,7 @@ IF (WITH_3D)
3d/qgs3danimationwidget.cpp
3d/qgs3danimationexportdialog.cpp
3d/qgs3dapputils.cpp
3d/qgs3dicongenerator.cpp
3d/qgs3dmapcanvas.cpp
3d/qgs3dmapcanvasdockwidget.cpp
3d/qgs3dmapconfigwidget.cpp

View File

@ -12657,6 +12657,8 @@ void QgisApp::init3D()
// initialize 3D registries
Qgs3D::initialize();
Qgs3DAppUtils::initialize();
QgsStyleModel::setIconGenerator( new Qgs3DIconGenerator( QgsApplication::defaultStyleModel() ) );
#else
mActionNew3DMapCanvas->setVisible( false );
#endif

View File

@ -27,6 +27,33 @@ const double ICON_PADDING_FACTOR = 0.16;
const auto ENTITIES = { QgsStyle::SymbolEntity, QgsStyle::ColorrampEntity, QgsStyle::TextFormatEntity, QgsStyle::LabelSettingsEntity, QgsStyle::LegendPatchShapeEntity, QgsStyle::Symbol3DEntity };
QgsAbstractStyleEntityIconGenerator *QgsStyleModel::sIconGenerator = nullptr;
//
// QgsAbstractStyleEntityIconGenerator
//
QgsAbstractStyleEntityIconGenerator::QgsAbstractStyleEntityIconGenerator( QObject *parent )
: QObject( parent )
{
}
void QgsAbstractStyleEntityIconGenerator::setIconSizes( const QList<QSize> &sizes )
{
mIconSizes = sizes;
}
QList<QSize> QgsAbstractStyleEntityIconGenerator::iconSizes() const
{
return mIconSizes;
}
//
// QgsStyleModel
//
QgsStyleModel::QgsStyleModel( QgsStyle *style, QObject *parent )
: QAbstractItemModel( parent )
, mStyle( style )
@ -55,6 +82,9 @@ QgsStyleModel::QgsStyleModel( QgsStyle *style, QObject *parent )
// if project color scheme changes, we need to redraw symbols - they may use project colors and accordingly
// need updating to reflect the new colors
connect( QgsProject::instance(), &QgsProject::projectColorsChanged, this, &QgsStyleModel::rebuildSymbolIcons );
if ( sIconGenerator )
connect( sIconGenerator, &QgsAbstractStyleEntityIconGenerator::iconGenerated, this, &QgsStyleModel::iconGenerated, Qt::QueuedConnection );
}
QVariant QgsStyleModel::data( const QModelIndex &index, int role ) const
@ -326,6 +356,13 @@ QVariant QgsStyleModel::data( const QModelIndex &index, int role ) const
if ( !icon.isNull() )
return icon;
if ( sIconGenerator && !mPending3dSymbolIcons.contains( name ) )
{
mPending3dSymbolIcons.insert( name );
sIconGenerator->generateIcon( mStyle, QgsStyle::Symbol3DEntity, name );
}
// TODO - use hourglass icon
if ( mAdditionalSizes.isEmpty() )
icon.addFile( QgsApplication::defaultThemePath() + QDir::separator() + QStringLiteral( "3d.svg" ), QSize( 24, 24 ) );
for ( const QSize &s : mAdditionalSizes )
@ -553,9 +590,19 @@ void QgsStyleModel::addDesiredIconSize( QSize size )
return;
mAdditionalSizes << size;
if ( sIconGenerator )
sIconGenerator->setIconSizes( mAdditionalSizes );
mIconCache.clear();
}
void QgsStyleModel::setIconGenerator( QgsAbstractStyleEntityIconGenerator *generator )
{
sIconGenerator = generator;
connect( sIconGenerator, &QgsAbstractStyleEntityIconGenerator::iconGenerated, QgsApplication::defaultStyleModel(), &QgsStyleModel::iconGenerated, Qt::QueuedConnection );
}
void QgsStyleModel::onEntityAdded( QgsStyle::StyleEntity type, const QString &name )
{
mIconCache[ type ].remove( name );
@ -651,6 +698,29 @@ void QgsStyleModel::rebuildSymbolIcons()
emit dataChanged( index( 0, 0 ), index( mEntityNames[ QgsStyle::SymbolEntity ].count() - 1, 0 ), QVector<int>() << Qt::DecorationRole );
}
void QgsStyleModel::iconGenerated( QgsStyle::StyleEntity type, const QString &name, const QIcon &icon )
{
int row = mEntityNames[type].indexOf( name ) + offsetForEntity( type );
switch ( type )
{
case QgsStyle::Symbol3DEntity:
mPending3dSymbolIcons.remove( name );
mIconCache[ QgsStyle::Symbol3DEntity ].insert( name, icon );
emit dataChanged( index( row, 0 ), index( row, 0 ) );
break;
case QgsStyle::SymbolEntity:
case QgsStyle::TagEntity:
case QgsStyle::ColorrampEntity:
case QgsStyle::LegendPatchShapeEntity:
case QgsStyle::TextFormatEntity:
case QgsStyle::SmartgroupEntity:
case QgsStyle::LabelSettingsEntity:
break;
}
}
QgsStyle::StyleEntity QgsStyleModel::entityTypeFromRow( int row ) const
{
int maxRowForEntity = 0;
@ -946,3 +1016,4 @@ void QgsStyleProxyModel::setEntityFilters( const QList<QgsStyle::StyleEntity> &f
mEntityFilters = filters;
invalidateFilter();
}

View File

@ -27,6 +27,68 @@
class QgsSymbol;
#ifndef SIP_RUN
/**
* \ingroup core
* \class QgsAbstractStyleEntityIconGenerator
*
* An abstract base class for icon generators for a QgsStyleModel.
*
* This base class allows for creation of specialised icon generators for
* entities in a style database, and allows for deferred icon generation.
*
* \note Not available in Python bindings
* \since QGIS 3.16
*/
class CORE_EXPORT QgsAbstractStyleEntityIconGenerator : public QObject
{
Q_OBJECT
public:
/**
* Constructor for QgsAbstractStyleEntityIconGenerator, with the specified \a parent
* object.
*/
QgsAbstractStyleEntityIconGenerator( QObject *parent );
/**
* Triggers generation of an icon for an entity from the specified \a style database,
* with matching entity \a type and \a name.
*/
virtual void generateIcon( QgsStyle *style, QgsStyle::StyleEntity type, const QString &name ) = 0;
/**
* Sets the list of icon \a sizes to generate.
*
* \see iconSizes()
*/
void setIconSizes( const QList< QSize > &sizes );
/**
* Returns the list of icon \a sizes to generate.
*
* \see setIconSizes()
*/
QList< QSize > iconSizes() const;
signals:
/**
* Emitted when the \a icon for the style entity with matching \a type and \a name
* has been generated.
*/
void iconGenerated( QgsStyle::StyleEntity type, const QString &name, const QIcon &icon );
private:
QList< QSize > mIconSizes;
};
#endif
/**
* \ingroup core
* \class QgsStyleModel
@ -99,6 +161,16 @@ class CORE_EXPORT QgsStyleModel: public QAbstractItemModel
*/
void addDesiredIconSize( QSize size );
/**
* Sets the icon \a generator to use for deferred style entity icon generation.
*
* Currently this is used for 3D symbol icons only.
*
* \note Not available in Python bindings
* \since QGIS 3.16
*/
static void setIconGenerator( QgsAbstractStyleEntityIconGenerator *generator ) SIP_SKIP;
private slots:
void onEntityAdded( QgsStyle::StyleEntity type, const QString &name );
@ -107,6 +179,7 @@ class CORE_EXPORT QgsStyleModel: public QAbstractItemModel
void onEntityRename( QgsStyle::StyleEntity type, const QString &oldName, const QString &newName );
void onTagsChanged( int entity, const QString &name, const QStringList &tags );
void rebuildSymbolIcons();
void iconGenerated( QgsStyle::StyleEntity type, const QString &name, const QIcon &icon );
private:
@ -119,6 +192,9 @@ class CORE_EXPORT QgsStyleModel: public QAbstractItemModel
mutable QHash< QgsStyle::StyleEntity, QHash< QString, QIcon > > mIconCache;
static QgsAbstractStyleEntityIconGenerator *sIconGenerator;
mutable QSet< QString > mPending3dSymbolIcons;
QgsStyle::StyleEntity entityTypeFromRow( int row ) const;
int offsetForEntity( QgsStyle::StyleEntity entity ) const;