Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Add explicit API call for style model icon sizes
  • Loading branch information
nyalldawson committed Sep 13, 2018
1 parent e6084a6 commit 9406247
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 15 deletions.
16 changes: 16 additions & 0 deletions python/core/auto_generated/symbology/qgsstylemodel.sip.in
Expand Up @@ -63,6 +63,14 @@ The ``style`` object must exist for the lifetime of this model.
virtual int columnCount( const QModelIndex &parent = QModelIndex() ) const;


void addDesiredIconSize( QSize size );
%Docstring
Adds an additional icon ``size`` to generate for Qt.DecorationRole data.

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
Expand Down Expand Up @@ -236,6 +244,14 @@ Returns true if the model is showing only favorited entities.
Sets whether the model should show only favorited entities.

.. seealso:: :py:func:`setFavoritesOnly`
%End

void addDesiredIconSize( QSize size );
%Docstring
Adds an additional icon ``size`` to generate for Qt.DecorationRole data.

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

public slots:
Expand Down
23 changes: 14 additions & 9 deletions src/core/symbology/qgsstylemodel.cpp
Expand Up @@ -71,13 +71,8 @@ QVariant QgsStyleModel::data( const QModelIndex &index, int role ) const

case Qt::DecorationRole:
{
// check the model custom property for icon sizes to generate. This is used
// by instances of the model to indicate the required sizes for decorations in all
// views connected to the model, and allows the model to have size responsive icons.
// By using a QObject property we avoid having public GUI/view related API within
// the model, and mostly avoid view related properties contaminating the pure model...
const QVariantList iconSizes = property( "icon_sizes" ).toList();

// Generate icons at all additional sizes specified for the model.
// This allows the model to have size responsive icons.
switch ( index.column() )
{
case Name:
Expand All @@ -87,7 +82,7 @@ QVariant QgsStyleModel::data( const QModelIndex &index, int role ) const
QIcon icon;
icon.addPixmap( QgsSymbolLayerUtils::symbolPreviewPixmap( symbol.get(), QSize( 24, 24 ), 1 ) );

for ( const QVariant &size : iconSizes )
for ( const QVariant &size : mAdditionalSizes )
{
QSize s = size.toSize();
icon.addPixmap( QgsSymbolLayerUtils::symbolPreviewPixmap( symbol.get(), s, static_cast< int >( s.width() * ICON_PADDING_FACTOR ) ) );
Expand All @@ -100,7 +95,7 @@ QVariant QgsStyleModel::data( const QModelIndex &index, int role ) const
std::unique_ptr< QgsColorRamp > ramp( mStyle->colorRamp( name ) );
QIcon icon;
icon.addPixmap( QgsSymbolLayerUtils::colorRampPreviewPixmap( ramp.get(), QSize( 24, 24 ), 1 ) );
for ( const QVariant &size : iconSizes )
for ( const QVariant &size : mAdditionalSizes )
{
QSize s = size.toSize();
icon.addPixmap( QgsSymbolLayerUtils::colorRampPreviewPixmap( ramp.get(), s, static_cast< int >( s.width() * ICON_PADDING_FACTOR ) ) );
Expand Down Expand Up @@ -237,6 +232,11 @@ int QgsStyleModel::columnCount( const QModelIndex & ) const
return 2;
}

void QgsStyleModel::addDesiredIconSize( QSize size )
{
mAdditionalSizes << size;
}

void QgsStyleModel::onSymbolAdded( const QString &name, QgsSymbol * )
{
const QStringList oldSymbolNames = mSymbolNames;
Expand Down Expand Up @@ -466,6 +466,11 @@ void QgsStyleProxyModel::setFavoritesOnly( bool favoritesOnly )
invalidateFilter();
}

void QgsStyleProxyModel::addDesiredIconSize( QSize size )
{
mModel->addDesiredIconSize( size );
}

bool QgsStyleProxyModel::symbolTypeFilterEnabled() const
{
return mSymbolTypeFilterEnabled;
Expand Down
17 changes: 17 additions & 0 deletions src/core/symbology/qgsstylemodel.h
Expand Up @@ -75,6 +75,14 @@ class CORE_EXPORT QgsStyleModel: public QAbstractItemModel
int rowCount( const QModelIndex &parent = QModelIndex() ) const override;
int columnCount( const QModelIndex &parent = QModelIndex() ) const override;

/**
* Adds an additional icon \a size to generate for Qt::DecorationRole data.
*
* 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.
*/
void addDesiredIconSize( QSize size );

private slots:

void onSymbolAdded( const QString &name, QgsSymbol *symbol );
Expand All @@ -90,6 +98,7 @@ class CORE_EXPORT QgsStyleModel: public QAbstractItemModel
QgsStyle *mStyle = nullptr;
QStringList mSymbolNames;
QStringList mRampNames;
QList< QSize > mAdditionalSizes;

};

Expand Down Expand Up @@ -252,6 +261,14 @@ class CORE_EXPORT QgsStyleProxyModel: public QSortFilterProxyModel
*/
void setFavoritesOnly( bool favoritesOnly );

/**
* Adds an additional icon \a size to generate for Qt::DecorationRole data.
*
* 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.
*/
void addDesiredIconSize( QSize size );

public slots:

/**
Expand Down
2 changes: 1 addition & 1 deletion src/gui/symbology/qgssymbolslistwidget.cpp
Expand Up @@ -121,7 +121,7 @@ QgsSymbolsListWidget::QgsSymbolsListWidget( QgsSymbol *symbol, QgsStyle *style,
double iconSize = Qgis::UI_SCALE_FACTOR * fontMetrics().width( 'X' ) * 10;
viewSymbols->setIconSize( QSize( static_cast< int >( iconSize ), static_cast< int >( iconSize * 0.9 ) ) ); // ~100, 90 on low dpi

mModel->sourceModel()->setProperty( "icon_sizes", QVariantList() << viewSymbols->iconSize() );
mModel->addDesiredIconSize( viewSymbols->iconSize() );
viewSymbols->setModel( mModel );

connect( viewSymbols->selectionModel(), &QItemSelectionModel::currentChanged, this, &QgsSymbolsListWidget::setSymbolFromStyle );
Expand Down
12 changes: 7 additions & 5 deletions tests/src/python/test_qgsstylemodel.py
Expand Up @@ -728,17 +728,18 @@ def testIconSize(self):
ramp_a = QgsLimitedRandomColorRamp(5)
self.assertTrue(style.addColorRamp('ramp a', ramp_a, True))

model = QgsStyleModel(style)
self.assertEqual(model.rowCount(), 2)
for i in range(2):
model = QgsStyleModel(style)
self.assertEqual(model.rowCount(), 2)
icon = model.data(model.index(i, 0), Qt.DecorationRole)
# by default, only 24x24 icon
self.assertEqual(icon.availableSizes(), [QSize(24, 24)])
self.assertEqual(icon.actualSize(QSize(10, 10)), QSize(10, 10))
self.assertEqual(icon.actualSize(QSize(24, 24)), QSize(24, 24))
self.assertEqual(icon.actualSize(QSize(90, 90)), QSize(24, 24))

model.setProperty('icon_sizes', [QSize(24, 24), QSize(100, 90)])
model.addDesiredIconSize(QSize(24, 24))
model.addDesiredIconSize(QSize(100, 90))
icon = model.data(model.index(i, 0), Qt.DecorationRole)
self.assertEqual(icon.availableSizes(), [QSize(24, 24), QSize(100, 90)])
self.assertEqual(icon.actualSize(QSize(10, 10)), QSize(10, 10))
Expand All @@ -747,7 +748,9 @@ def testIconSize(self):
self.assertEqual(icon.actualSize(QSize(90, 90)), QSize(90, 81))
self.assertEqual(icon.actualSize(QSize(125, 125)), QSize(100, 90))

model.setProperty('icon_sizes', [QSize(100, 90), QSize(200, 180)])
model = QgsStyleModel(style)
model.addDesiredIconSize(QSize(100, 90))
model.addDesiredIconSize(QSize(200, 180))
icon = model.data(model.index(i, 0), Qt.DecorationRole)
self.assertEqual(icon.availableSizes(), [QSize(24, 24), QSize(100, 90), QSize(200, 180)])
self.assertEqual(icon.actualSize(QSize(10, 10)), QSize(10, 10))
Expand All @@ -756,7 +759,6 @@ def testIconSize(self):
self.assertEqual(icon.actualSize(QSize(90, 90)), QSize(90, 81))
self.assertEqual(icon.actualSize(QSize(125, 125)), QSize(125, 112))
self.assertEqual(icon.actualSize(QSize(225, 225)), QSize(200, 180))
model.setProperty('icon_sizes', None)

def testSetData(self):
"""
Expand Down

0 comments on commit 9406247

Please sign in to comment.