Skip to content

Commit 84d4853

Browse files
committed
Use model for symbol list view in symbol panel
Fixes hi-dpi issues
1 parent 22c8bef commit 84d4853

File tree

3 files changed

+85
-72
lines changed

3 files changed

+85
-72
lines changed

python/gui/auto_generated/symbology/qgssymbolslistwidget.sip.in

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,6 @@ Returns the vector layer associated with the widget.
7171
void addSymbolToStyle();
7272
void saveSymbol();
7373

74-
void symbolAddedToStyle( const QString &name, QgsSymbol *symbol );
75-
7674
void populateGroups();
7775
%Docstring
7876
Pupulates the groups combo box with available tags and smartgroups

src/gui/symbology/qgssymbolslistwidget.cpp

Lines changed: 67 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "qgsnewauxiliarylayerdialog.h"
3131
#include "qgsauxiliarystorage.h"
3232
#include "qgssvgcache.h"
33+
#include "qgsstylemodel.h"
3334

3435
#include <QAction>
3536
#include <QString>
@@ -44,6 +45,37 @@
4445
#include <QPushButton>
4546

4647

48+
//
49+
// QgsReadOnlyStyleModel
50+
//
51+
QgsReadOnlyStyleModel::QgsReadOnlyStyleModel( QgsStyle *style, QObject *parent )
52+
: QgsStyleProxyModel( style, parent )
53+
{
54+
55+
}
56+
57+
Qt::ItemFlags QgsReadOnlyStyleModel::flags( const QModelIndex &index ) const
58+
{
59+
return QgsStyleProxyModel::flags( index ) & ~Qt::ItemIsEditable;
60+
}
61+
62+
QVariant QgsReadOnlyStyleModel::data( const QModelIndex &index, int role ) const
63+
{
64+
if ( role == Qt::FontRole )
65+
{
66+
// drop font size to get reasonable amount of item name shown
67+
QFont f = QgsStyleProxyModel::data( index, role ).value< QFont >();
68+
f.setPointSize( 10 );
69+
return f;
70+
}
71+
return QgsStyleProxyModel::data( index, role );
72+
}
73+
74+
75+
//
76+
// QgsSymbolsListWidget
77+
//
78+
4779
QgsSymbolsListWidget::QgsSymbolsListWidget( QgsSymbol *symbol, QgsStyle *style, QMenu *menu, QWidget *parent, QgsVectorLayer *layer )
4880
: QWidget( parent )
4981
, mSymbol( symbol )
@@ -58,6 +90,15 @@ QgsSymbolsListWidget::QgsSymbolsListWidget( QgsSymbol *symbol, QgsStyle *style,
5890
mSymbolUnitWidget->setUnits( QgsUnitTypes::RenderUnitList() << QgsUnitTypes::RenderMillimeters << QgsUnitTypes::RenderMetersInMapUnits << QgsUnitTypes::RenderMapUnits << QgsUnitTypes::RenderPixels
5991
<< QgsUnitTypes::RenderPoints << QgsUnitTypes::RenderInches );
6092

93+
mModel = new QgsReadOnlyStyleModel( mStyle, this );
94+
mModel->setEntityFilterEnabled( true );
95+
mModel->setEntityFilter( QgsStyle::SymbolEntity );
96+
if ( mSymbol )
97+
{
98+
mModel->setSymbolTypeFilterEnabled( true );
99+
mModel->setSymbolType( mSymbol->type() );
100+
}
101+
61102
btnAdvanced->hide(); // advanced button is hidden by default
62103
if ( menu ) // show it if there is a menu pointer
63104
{
@@ -73,11 +114,15 @@ QgsSymbolsListWidget::QgsSymbolsListWidget( QgsSymbol *symbol, QgsStyle *style,
73114
mClipFeaturesAction->setCheckable( true );
74115
connect( mClipFeaturesAction, &QAction::toggled, this, &QgsSymbolsListWidget::clipFeaturesToggled );
75116

76-
QStandardItemModel *model = new QStandardItemModel( viewSymbols );
77-
viewSymbols->setModel( model );
117+
double iconSize = Qgis::UI_SCALE_FACTOR * fontMetrics().width( 'X' ) * 10;
118+
viewSymbols->setIconSize( QSize( static_cast< int >( iconSize ), static_cast< int >( iconSize * 0.9 ) ) ); // ~100, 90 on low dpi
119+
viewSymbols->setGridSize( QSize( static_cast< int >( iconSize * 1.2 ), static_cast< int >( iconSize * 1.1 ) ) ); // ~120,110 on low dpi
120+
121+
mModel->sourceModel()->setProperty( "icon_sizes", QVariantList() << viewSymbols->iconSize() );
122+
viewSymbols->setModel( mModel );
123+
78124
connect( viewSymbols->selectionModel(), &QItemSelectionModel::currentChanged, this, &QgsSymbolsListWidget::setSymbolFromStyle );
79125

80-
connect( mStyle, &QgsStyle::symbolSaved, this, &QgsSymbolsListWidget::symbolAddedToStyle );
81126
connect( mStyle, &QgsStyle::groupsModified, this, &QgsSymbolsListWidget::populateGroups );
82127

83128
connect( openStyleManagerButton, &QPushButton::pressed, this, &QgsSymbolsListWidget::openStyleManager );
@@ -121,7 +166,7 @@ QgsSymbolsListWidget::QgsSymbolsListWidget( QgsSymbol *symbol, QgsStyle *style,
121166
// have been generated using the temporary "downloading" svg. In this case
122167
// we require the preview to be regenerated to use the correct fetched
123168
// svg
124-
connect( QgsApplication::svgCache(), &QgsSvgCache::remoteSvgFetched, this, &QgsSymbolsListWidget::populateSymbolView );
169+
connect( QgsApplication::svgCache(), &QgsSvgCache::remoteSvgFetched, this, &QgsSymbolsListWidget::updateModelFilters );
125170
}
126171

127172
QgsSymbolsListWidget::~QgsSymbolsListWidget()
@@ -254,71 +299,36 @@ void QgsSymbolsListWidget::populateGroups()
254299
index = settings.value( QStringLiteral( "qgis/symbolsListGroupsIndex" ), 0 ).toInt();
255300
groupsCombo->setCurrentIndex( index );
256301

257-
populateSymbolView();
302+
updateModelFilters();
258303
}
259304

260-
void QgsSymbolsListWidget::populateSymbolView()
305+
void QgsSymbolsListWidget::updateModelFilters()
261306
{
262-
QStringList symbols;
263-
QString text = groupsCombo->currentText();
264-
int id;
307+
const QString text = groupsCombo->currentText();
265308

266309
if ( groupsCombo->currentData().toString() == QLatin1String( "favorite" ) )
267310
{
268-
symbols = mStyle->symbolsOfFavorite( QgsStyle::SymbolEntity );
311+
mModel->setFavoritesOnly( true );
312+
mModel->setTagId( -1 );
313+
mModel->setSmartGroupId( -1 );
269314
}
270315
else if ( groupsCombo->currentData().toString() == QLatin1String( "all" ) )
271316
{
272-
symbols = mStyle->symbolNames();
317+
mModel->setFavoritesOnly( false );
318+
mModel->setTagId( -1 );
319+
mModel->setSmartGroupId( -1 );
273320
}
274321
else if ( groupsCombo->currentData().toString() == QLatin1String( "smartgroup" ) )
275322
{
276-
id = mStyle->smartgroupId( text );
277-
symbols = mStyle->symbolsOfSmartgroup( QgsStyle::SymbolEntity, id );
323+
mModel->setFavoritesOnly( false );
324+
mModel->setTagId( -1 );
325+
mModel->setSmartGroupId( mStyle->smartgroupId( text ) );
278326
}
279327
else
280328
{
281-
id = mStyle->tagId( text );
282-
symbols = mStyle->symbolsWithTag( QgsStyle::SymbolEntity, id );
283-
}
284-
285-
symbols.sort();
286-
populateSymbols( symbols );
287-
}
288-
289-
void QgsSymbolsListWidget::populateSymbols( const QStringList &names )
290-
{
291-
QSize previewSize = viewSymbols->iconSize();
292-
293-
QStandardItemModel *model = qobject_cast<QStandardItemModel *>( viewSymbols->model() );
294-
if ( !model )
295-
{
296-
return;
297-
}
298-
model->clear();
299-
300-
for ( int i = 0; i < names.count(); i++ )
301-
{
302-
std::unique_ptr< QgsSymbol > s( mStyle->symbol( names[i] ) );
303-
if ( !s || s->type() != mSymbol->type() )
304-
{
305-
continue;
306-
}
307-
QStringList tags = mStyle->tagsOfSymbol( QgsStyle::SymbolEntity, names[i] );
308-
QStandardItem *item = new QStandardItem( names[i] );
309-
item->setData( names[i], Qt::UserRole ); //so we can load symbol with that name
310-
item->setText( names[i] );
311-
item->setToolTip( QStringLiteral( "<b>%1</b><br><i>%2</i>" ).arg( names[i], tags.count() > 0 ? tags.join( QStringLiteral( ", " ) ) : tr( "Not tagged" ) ) );
312-
item->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable );
313-
// Set font to 10points to show reasonable text
314-
QFont itemFont = item->font();
315-
itemFont.setPointSize( 10 );
316-
item->setFont( itemFont );
317-
// create preview icon
318-
QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( s.get(), previewSize, 15 );
319-
item->setIcon( icon );
320-
// add to model
321-
model->appendRow( item );
329+
mModel->setFavoritesOnly( false );
330+
mModel->setTagId( mStyle->tagId( text ) );
331+
mModel->setSmartGroupId( -1 );
322332
}
323333
}
324334

@@ -327,7 +337,7 @@ void QgsSymbolsListWidget::openStyleManager()
327337
QgsStyleManagerDialog dlg( mStyle, this );
328338
dlg.exec();
329339

330-
populateSymbolView();
340+
updateModelFilters(); // probably not needed -- the model should automatically update if any changes were made
331341
}
332342

333343
void QgsSymbolsListWidget::clipFeaturesToggled( bool checked )
@@ -439,13 +449,6 @@ void QgsSymbolsListWidget::updateAssistantSymbol()
439449
mWidthDDBtn->setSymbol( mAssistantSymbol );
440450
}
441451

442-
void QgsSymbolsListWidget::symbolAddedToStyle( const QString &name, QgsSymbol *symbol )
443-
{
444-
Q_UNUSED( name );
445-
Q_UNUSED( symbol );
446-
populateSymbolView();
447-
}
448-
449452
void QgsSymbolsListWidget::addSymbolToStyle()
450453
{
451454
bool ok;
@@ -472,7 +475,6 @@ void QgsSymbolsListWidget::addSymbolToStyle()
472475

473476
// make sure the symbol is stored
474477
mStyle->saveSymbol( name, mSymbol->clone(), false, QStringList() );
475-
populateSymbolView();
476478
}
477479

478480
void QgsSymbolsListWidget::saveSymbol()
@@ -636,7 +638,7 @@ void QgsSymbolsListWidget::updateSymbolInfo()
636638

637639
void QgsSymbolsListWidget::setSymbolFromStyle( const QModelIndex &index )
638640
{
639-
QString symbolName = index.data( Qt::UserRole ).toString();
641+
QString symbolName = mModel->data( mModel->index( index.row(), QgsStyleModel::Name ) ).toString();
640642
lblSymbolName->setText( symbolName );
641643
// get new instance of symbol from style
642644
std::unique_ptr< QgsSymbol > s( mStyle->symbol( symbolName ) );
@@ -663,5 +665,5 @@ void QgsSymbolsListWidget::groupsCombo_currentIndexChanged( int index )
663665
QgsSettings settings;
664666
settings.setValue( QStringLiteral( "qgis/symbolsListGroupsIndex" ), index );
665667

666-
populateSymbolView();
668+
updateModelFilters();
667669
}

src/gui/symbology/qgssymbolslistwidget.h

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
#include "qgssymbolwidgetcontext.h"
2222
#include "qgssymbollayer.h"
23-
23+
#include "qgsstylemodel.h"
2424
#include <QWidget>
2525
#include "qgis_gui.h"
2626

@@ -29,6 +29,21 @@ class QgsStyle;
2929

3030
class QMenu;
3131

32+
#ifndef SIP_RUN
33+
///@cond PRIVATE
34+
class QgsReadOnlyStyleModel : public QgsStyleProxyModel
35+
{
36+
Q_OBJECT
37+
public:
38+
39+
explicit QgsReadOnlyStyleModel( QgsStyle *style, QObject *parent = nullptr );
40+
Qt::ItemFlags flags( const QModelIndex &index ) const override;
41+
QVariant data( const QModelIndex &index, int role ) const override;
42+
43+
};
44+
#endif
45+
///@endcond
46+
3247
/**
3348
* \ingroup gui
3449
* \class QgsSymbolsListWidget
@@ -83,8 +98,6 @@ class GUI_EXPORT QgsSymbolsListWidget : public QWidget, private Ui::SymbolsListW
8398
void addSymbolToStyle();
8499
void saveSymbol();
85100

86-
void symbolAddedToStyle( const QString &name, QgsSymbol *symbol );
87-
88101
//! Pupulates the groups combo box with available tags and smartgroups
89102
void populateGroups();
90103

@@ -104,7 +117,7 @@ class GUI_EXPORT QgsSymbolsListWidget : public QWidget, private Ui::SymbolsListW
104117
void updateAssistantSymbol();
105118
void opacityChanged( double value );
106119
void createAuxiliaryField();
107-
void populateSymbolView();
120+
void updateModelFilters();
108121

109122
private:
110123
QgsSymbol *mSymbol = nullptr;
@@ -114,8 +127,8 @@ class GUI_EXPORT QgsSymbolsListWidget : public QWidget, private Ui::SymbolsListW
114127
QAction *mClipFeaturesAction = nullptr;
115128
QgsVectorLayer *mLayer = nullptr;
116129
QgsMapCanvas *mMapCanvas = nullptr;
130+
QgsStyleProxyModel *mModel = nullptr;
117131

118-
void populateSymbols( const QStringList &symbols );
119132
void updateSymbolColor();
120133
void updateSymbolInfo();
121134
QgsSymbolWidgetContext mContext;

0 commit comments

Comments
 (0)