Skip to content
Permalink
Browse files

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

(still not implement -- but a necessary prerequisite to proper icons)
  • Loading branch information
nyalldawson committed Jul 29, 2020
1 parent c938de4 commit 1484a30fef8d412d251866cdb66b96debc4af601
@@ -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
@@ -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 );
}
@@ -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
@@ -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
@@ -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
@@ -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();
}

@@ -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;

0 comments on commit 1484a30

Please sign in to comment.
You can’t perform that action at this time.