QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
qgssvgselectorwidget.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgssvgselectorwidget.cpp - group and preview selector for SVG files
3  built off of work in qgssymbollayerwidget
4 
5  ---------------------
6  begin : April 2, 2013
7  copyright : (C) 2013 by Larry Shaffer
8  email : larrys at dakcarto dot com
9  ***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 #include "qgssvgselectorwidget.h"
18 
19 #include "qgsapplication.h"
20 #include "qgslogger.h"
21 #include "qgspathresolver.h"
22 #include "qgsproject.h"
23 #include "qgssvgcache.h"
24 #include "qgssymbollayerutils.h"
25 #include "qgssettings.h"
26 #include "qgsgui.h"
27 
28 #include <QAbstractListModel>
29 #include <QCheckBox>
30 #include <QDir>
31 #include <QFileDialog>
32 #include <QModelIndex>
33 #include <QPixmapCache>
34 #include <QStyle>
35 #include <QTime>
36 #include <QMenu>
37 
38 // QgsSvgSelectorLoader
39 
41 QgsSvgSelectorLoader::QgsSvgSelectorLoader( QObject *parent )
42  : QThread( parent )
43 {
44 }
45 
46 QgsSvgSelectorLoader::~QgsSvgSelectorLoader()
47 {
48  stop();
49 }
50 
51 void QgsSvgSelectorLoader::run()
52 {
53  mCanceled = false;
54  mQueuedSvgs.clear();
55  mTraversedPaths.clear();
56 
57  // start with a small initial timeout (ms)
58  mTimerThreshold = 10;
59  mTimer.start();
60 
61  loadPath( mPath );
62 
63  if ( !mQueuedSvgs.isEmpty() )
64  {
65  // make sure we notify model of any remaining queued svgs (ie svgs added since last foundSvgs() signal was emitted)
66  emit foundSvgs( mQueuedSvgs );
67  }
68  mQueuedSvgs.clear();
69 }
70 
71 void QgsSvgSelectorLoader::stop()
72 {
73  mCanceled = true;
74  while ( isRunning() ) {}
75 }
76 
77 void QgsSvgSelectorLoader::loadPath( const QString &path )
78 {
79  if ( mCanceled )
80  return;
81 
82  // QgsDebugMsg( QStringLiteral( "loading path: %1" ).arg( path ) );
83 
84  if ( path.isEmpty() )
85  {
86  QStringList svgPaths = QgsApplication::svgPaths();
87  const auto constSvgPaths = svgPaths;
88  for ( const QString &svgPath : constSvgPaths )
89  {
90  if ( mCanceled )
91  return;
92 
93  if ( !svgPath.isEmpty() )
94  {
95  loadPath( svgPath );
96  }
97  }
98  }
99  else
100  {
101  QDir dir( path );
102 
103  //guard against circular symbolic links
104  QString canonicalPath = dir.canonicalPath();
105  if ( mTraversedPaths.contains( canonicalPath ) )
106  return;
107 
108  mTraversedPaths.insert( canonicalPath );
109 
110  loadImages( path );
111 
112  const auto constEntryList = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
113  for ( const QString &item : constEntryList )
114  {
115  if ( mCanceled )
116  return;
117 
118  QString newPath = dir.path() + '/' + item;
119  loadPath( newPath );
120  // QgsDebugMsg( QStringLiteral( "added path: %1" ).arg( newPath ) );
121  }
122  }
123 }
124 
125 void QgsSvgSelectorLoader::loadImages( const QString &path )
126 {
127  QDir dir( path );
128  const auto constEntryList = dir.entryList( QStringList( "*.svg" ), QDir::Files );
129  for ( const QString &item : constEntryList )
130  {
131  if ( mCanceled )
132  return;
133 
134  // TODO test if it is correct SVG
135  QString svgPath = dir.path() + '/' + item;
136  // QgsDebugMsg( QStringLiteral( "adding svg: %1" ).arg( svgPath ) );
137 
138  // add it to the list of queued SVGs
139  mQueuedSvgs << svgPath;
140 
141  // we need to avoid spamming the model with notifications about new svgs, so foundSvgs
142  // is only emitted for blocks of SVGs (otherwise the view goes all flickery)
143  if ( mTimer.elapsed() > mTimerThreshold && !mQueuedSvgs.isEmpty() )
144  {
145  emit foundSvgs( mQueuedSvgs );
146  mQueuedSvgs.clear();
147 
148  // increase the timer threshold - this ensures that the first lots of svgs loaded are added
149  // to the view quickly, but as the list grows new svgs are added at a slower rate.
150  // ie, good for initial responsiveness but avoid being spammy as the list grows.
151  if ( mTimerThreshold < 1000 )
152  mTimerThreshold *= 2;
153  mTimer.restart();
154  }
155  }
156 }
157 
158 
159 //
160 // QgsSvgGroupLoader
161 //
162 
163 QgsSvgGroupLoader::QgsSvgGroupLoader( QObject *parent )
164  : QThread( parent )
165 {
166 
167 }
168 
169 QgsSvgGroupLoader::~QgsSvgGroupLoader()
170 {
171  stop();
172 }
173 
174 void QgsSvgGroupLoader::run()
175 {
176  mCanceled = false;
177  mTraversedPaths.clear();
178 
179  while ( !mCanceled && !mParentPaths.isEmpty() )
180  {
181  QString parentPath = mParentPaths.takeFirst();
182  loadGroup( parentPath );
183  }
184 }
185 
186 void QgsSvgGroupLoader::stop()
187 {
188  mCanceled = true;
189  while ( isRunning() ) {}
190 }
191 
192 void QgsSvgGroupLoader::loadGroup( const QString &parentPath )
193 {
194  QDir parentDir( parentPath );
195 
196  //guard against circular symbolic links
197  QString canonicalPath = parentDir.canonicalPath();
198  if ( mTraversedPaths.contains( canonicalPath ) )
199  return;
200 
201  mTraversedPaths.insert( canonicalPath );
202 
203  const auto constEntryList = parentDir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
204  for ( const QString &item : constEntryList )
205  {
206  if ( mCanceled )
207  return;
208 
209  emit foundPath( parentPath, item );
210  mParentPaths.append( parentDir.path() + '/' + item );
211  }
212 }
213 
215 
216 //,
217 // QgsSvgSelectorListModel
218 //
219 
221  : QAbstractListModel( parent )
222  , mSvgLoader( new QgsSvgSelectorLoader( this ) )
223  , mIconSize( iconSize )
224 {
225  mSvgLoader->setPath( QString() );
226  connect( mSvgLoader, &QgsSvgSelectorLoader::foundSvgs, this, &QgsSvgSelectorListModel::addSvgs );
227  mSvgLoader->start();
228 }
229 
230 QgsSvgSelectorListModel::QgsSvgSelectorListModel( QObject *parent, const QString &path, int iconSize )
231  : QAbstractListModel( parent )
232  , mSvgLoader( new QgsSvgSelectorLoader( this ) )
233  , mIconSize( iconSize )
234 {
235  mSvgLoader->setPath( path );
236  connect( mSvgLoader, &QgsSvgSelectorLoader::foundSvgs, this, &QgsSvgSelectorListModel::addSvgs );
237  mSvgLoader->start();
238 }
239 
240 int QgsSvgSelectorListModel::rowCount( const QModelIndex &parent ) const
241 {
242  Q_UNUSED( parent )
243  return mSvgFiles.count();
244 }
245 
246 QPixmap QgsSvgSelectorListModel::createPreview( const QString &entry ) const
247 {
248  // render SVG file
249  QColor fill, stroke;
250  double strokeWidth, fillOpacity, strokeOpacity;
251  bool fillParam, fillOpacityParam, strokeParam, strokeWidthParam, strokeOpacityParam;
252  bool hasDefaultFillColor = false, hasDefaultFillOpacity = false, hasDefaultStrokeColor = false,
253  hasDefaultStrokeWidth = false, hasDefaultStrokeOpacity = false;
254  QgsApplication::svgCache()->containsParams( entry, fillParam, hasDefaultFillColor, fill,
255  fillOpacityParam, hasDefaultFillOpacity, fillOpacity,
256  strokeParam, hasDefaultStrokeColor, stroke,
257  strokeWidthParam, hasDefaultStrokeWidth, strokeWidth,
258  strokeOpacityParam, hasDefaultStrokeOpacity, strokeOpacity );
259 
260  //if defaults not set in symbol, use these values
261  if ( !hasDefaultFillColor )
262  fill = QColor( 200, 200, 200 );
263  fill.setAlphaF( hasDefaultFillOpacity ? fillOpacity : 1.0 );
264  if ( !hasDefaultStrokeColor )
265  stroke = Qt::black;
266  stroke.setAlphaF( hasDefaultStrokeOpacity ? strokeOpacity : 1.0 );
267  if ( !hasDefaultStrokeWidth )
268  strokeWidth = 0.2;
269 
270  bool fitsInCache; // should always fit in cache at these sizes (i.e. under 559 px ^ 2, or half cache size)
271  QImage img = QgsApplication::svgCache()->svgAsImage( entry, mIconSize, fill, stroke, strokeWidth, 3.5 /*appr. 88 dpi*/, fitsInCache );
272  return QPixmap::fromImage( img );
273 }
274 
275 QVariant QgsSvgSelectorListModel::data( const QModelIndex &index, int role ) const
276 {
277  QString entry = mSvgFiles.at( index.row() );
278 
279  if ( role == Qt::DecorationRole ) // icon
280  {
281  QPixmap *pixmap = nullptr;
282  if ( !QPixmapCache::find( entry, pixmap ) || !pixmap )
283  {
284  QPixmap newPixmap = createPreview( entry );
285  QPixmapCache::insert( entry, newPixmap );
286  return newPixmap;
287  }
288  else
289  {
290  return *pixmap;
291  }
292  }
293  else if ( role == Qt::UserRole || role == Qt::ToolTipRole )
294  {
295  return entry;
296  }
297 
298  return QVariant();
299 }
300 
301 void QgsSvgSelectorListModel::addSvgs( const QStringList &svgs )
302 {
303  beginInsertRows( QModelIndex(), mSvgFiles.count(), mSvgFiles.count() + svgs.size() - 1 );
304  mSvgFiles.append( svgs );
305  endInsertRows();
306 }
307 
308 
309 
310 
311 
312 //--- QgsSvgSelectorGroupsModel
313 
315  : QStandardItemModel( parent )
316  , mLoader( new QgsSvgGroupLoader( this ) )
317 {
318  QStringList svgPaths = QgsApplication::svgPaths();
319  QStandardItem *parentItem = invisibleRootItem();
320  QStringList parentPaths;
321  parentPaths.reserve( svgPaths.size() );
322 
323  for ( int i = 0; i < svgPaths.size(); i++ )
324  {
325  QDir dir( svgPaths.at( i ) );
326  QStandardItem *baseGroup = nullptr;
327 
328  if ( dir.path().contains( QgsApplication::pkgDataPath() ) )
329  {
330  baseGroup = new QStandardItem( tr( "App Symbols" ) );
331  }
332  else if ( dir.path().contains( QgsApplication::qgisSettingsDirPath() ) )
333  {
334  baseGroup = new QStandardItem( tr( "User Symbols" ) );
335  }
336  else
337  {
338  baseGroup = new QStandardItem( dir.dirName() );
339  }
340  baseGroup->setData( QVariant( svgPaths.at( i ) ) );
341  baseGroup->setEditable( false );
342  baseGroup->setCheckable( false );
343  baseGroup->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "mIconFolder.svg" ) ) );
344  baseGroup->setToolTip( dir.path() );
345  parentItem->appendRow( baseGroup );
346  parentPaths << svgPaths.at( i );
347  mPathItemHash.insert( svgPaths.at( i ), baseGroup );
348  QgsDebugMsg( QStringLiteral( "SVG base path %1: %2" ).arg( i ).arg( baseGroup->data().toString() ) );
349  }
350  mLoader->setParentPaths( parentPaths );
351  connect( mLoader, &QgsSvgGroupLoader::foundPath, this, &QgsSvgSelectorGroupsModel::addPath );
352  mLoader->start();
353 }
354 
356 {
357  mLoader->stop();
358 }
359 
360 void QgsSvgSelectorGroupsModel::addPath( const QString &parentPath, const QString &item )
361 {
362  QStandardItem *parentGroup = mPathItemHash.value( parentPath );
363  if ( !parentGroup )
364  return;
365 
366  QString fullPath = parentPath + '/' + item;
367  QStandardItem *group = new QStandardItem( item );
368  group->setData( QVariant( fullPath ) );
369  group->setEditable( false );
370  group->setCheckable( false );
371  group->setToolTip( fullPath );
372  group->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "mIconFolder.svg" ) ) );
373  parentGroup->appendRow( group );
374  mPathItemHash.insert( fullPath, group );
375 }
376 
377 
378 //-- QgsSvgSelectorWidget
379 
381  : QWidget( parent )
382 {
383  // TODO: in-code gui setup with option to vertically or horizontally stack SVG groups/images widgets
384  setupUi( this );
385 
386  connect( mSvgSourceLineEdit, &QgsAbstractFileContentSourceLineEdit::sourceChanged, this, &QgsSvgSelectorWidget::svgSourceChanged );
387 
388 #if QT_VERSION < QT_VERSION_CHECK(5, 11, 0)
389  mIconSize = std::max( 30, static_cast< int >( std::round( Qgis::UI_SCALE_FACTOR * fontMetrics().width( 'X' ) * 3 ) ) );
390 #else
391  mIconSize = std::max( 30, static_cast< int >( std::round( Qgis::UI_SCALE_FACTOR * fontMetrics().horizontalAdvance( 'X' ) * 3 ) ) );
392 #endif
393  mImagesListView->setGridSize( QSize( mIconSize * 1.2, mIconSize * 1.2 ) );
394 
395  mGroupsTreeView->setHeaderHidden( true );
396  populateList();
397 
398  connect( mImagesListView->selectionModel(), &QItemSelectionModel::currentChanged,
399  this, &QgsSvgSelectorWidget::svgSelectionChanged );
400  connect( mGroupsTreeView->selectionModel(), &QItemSelectionModel::currentChanged,
401  this, &QgsSvgSelectorWidget::populateIcons );
402 }
403 
404 void QgsSvgSelectorWidget::setSvgPath( const QString &svgPath )
405 {
406  mCurrentSvgPath = svgPath;
407 
408  whileBlocking( mSvgSourceLineEdit )->setSource( svgPath );
409 
410  mImagesListView->selectionModel()->blockSignals( true );
411  QAbstractItemModel *m = mImagesListView->model();
412  QItemSelectionModel *selModel = mImagesListView->selectionModel();
413  for ( int i = 0; i < m->rowCount(); i++ )
414  {
415  QModelIndex idx( m->index( i, 0 ) );
416  if ( m->data( idx ).toString() == svgPath )
417  {
418  selModel->select( idx, QItemSelectionModel::SelectCurrent );
419  selModel->setCurrentIndex( idx, QItemSelectionModel::SelectCurrent );
420  mImagesListView->scrollTo( idx );
421  break;
422  }
423  }
424  mImagesListView->selectionModel()->blockSignals( false );
425 }
426 
428 {
429  return mCurrentSvgPath;
430 }
431 
432 void QgsSvgSelectorWidget::updateCurrentSvgPath( const QString &svgPath )
433 {
434  mCurrentSvgPath = svgPath;
435  emit svgSelected( currentSvgPath() );
436 }
437 
438 void QgsSvgSelectorWidget::svgSelectionChanged( const QModelIndex &idx )
439 {
440  QString filePath = idx.data( Qt::UserRole ).toString();
441  whileBlocking( mSvgSourceLineEdit )->setSource( filePath );
442  updateCurrentSvgPath( filePath );
443 }
444 
445 void QgsSvgSelectorWidget::populateIcons( const QModelIndex &idx )
446 {
447  QString path = idx.data( Qt::UserRole + 1 ).toString();
448 
449  QAbstractItemModel *oldModel = mImagesListView->model();
450  QgsSvgSelectorListModel *m = new QgsSvgSelectorListModel( mImagesListView, path, mIconSize );
451  mImagesListView->setModel( m );
452  delete oldModel; //explicitly delete old model to force any background threads to stop
453 
454  connect( mImagesListView->selectionModel(), &QItemSelectionModel::currentChanged,
455  this, &QgsSvgSelectorWidget::svgSelectionChanged );
456 }
457 
458 void QgsSvgSelectorWidget::svgSourceChanged( const QString &text )
459 {
460  QString resolvedPath = QgsSymbolLayerUtils::svgSymbolNameToPath( text, QgsProject::instance()->pathResolver() );
461  bool validSVG = !resolvedPath.isNull();
462 
463  updateCurrentSvgPath( validSVG ? resolvedPath : text );
464 }
465 
467 {
468  QgsSvgSelectorGroupsModel *g = new QgsSvgSelectorGroupsModel( mGroupsTreeView );
469  mGroupsTreeView->setModel( g );
470  // Set the tree expanded at the first level
471  int rows = g->rowCount( g->indexFromItem( g->invisibleRootItem() ) );
472  for ( int i = 0; i < rows; i++ )
473  {
474  mGroupsTreeView->setExpanded( g->indexFromItem( g->item( i ) ), true );
475  }
476 
477  // Initially load the icons in the List view without any grouping
478  QAbstractItemModel *oldModel = mImagesListView->model();
479  QgsSvgSelectorListModel *m = new QgsSvgSelectorListModel( mImagesListView );
480  mImagesListView->setModel( m );
481  delete oldModel; //explicitly delete old model to force any background threads to stop
482 }
483 
484 //-- QgsSvgSelectorDialog
485 
486 QgsSvgSelectorDialog::QgsSvgSelectorDialog( QWidget *parent, Qt::WindowFlags fl,
487  QDialogButtonBox::StandardButtons buttons,
488  Qt::Orientation orientation )
489  : QDialog( parent, fl )
490 {
491  // TODO: pass 'orientation' to QgsSvgSelectorWidget for customizing its layout, once implemented
492  Q_UNUSED( orientation )
493 
494  // create buttonbox
495  mButtonBox = new QDialogButtonBox( buttons, orientation, this );
496  connect( mButtonBox, &QDialogButtonBox::accepted, this, &QDialog::accept );
497  connect( mButtonBox, &QDialogButtonBox::rejected, this, &QDialog::reject );
498 
499  setMinimumSize( 480, 320 );
500 
501  // dialog's layout
502  mLayout = new QVBoxLayout();
503  mSvgSelector = new QgsSvgSelectorWidget( this );
504  mLayout->addWidget( mSvgSelector );
505 
506  mLayout->addWidget( mButtonBox );
507  setLayout( mLayout );
508 }
509 
qgssvgcache.h
QgsApplication::getThemeIcon
static QIcon getThemeIcon(const QString &name)
Helper to get a theme icon.
Definition: qgsapplication.cpp:626
QgsSvgSelectorListModel::data
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
Definition: qgssvgselectorwidget.cpp:275
qgsgui.h
QgsSvgSelectorDialog::QgsSvgSelectorDialog
QgsSvgSelectorDialog(QWidget *parent=nullptr, Qt::WindowFlags fl=QgsGuiUtils::ModalDialogFlags, QDialogButtonBox::StandardButtons buttons=QDialogButtonBox::Close|QDialogButtonBox::Ok, Qt::Orientation orientation=Qt::Horizontal)
Constructor for QgsSvgSelectorDialog.
Definition: qgssvgselectorwidget.cpp:486
qgssymbollayerutils.h
qgspathresolver.h
QgsSvgCache::svgAsImage
QImage svgAsImage(const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth, double widthScaleFactor, bool &fitsInCache, double fixedAspectRatio=0, bool blocking=false)
Gets SVG as QImage.
Definition: qgssvgcache.cpp:122
QgsSvgSelectorListModel::rowCount
int rowCount(const QModelIndex &parent=QModelIndex()) const override
Definition: qgssvgselectorwidget.cpp:240
QgsProject::instance
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:468
QgsApplication::svgPaths
static QStringList svgPaths()
Returns the paths to svg directories.
Definition: qgsapplication.cpp:1049
QgsDebugMsg
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
QgsSvgCache::containsParams
void containsParams(const QString &path, bool &hasFillParam, QColor &defaultFillColor, bool &hasStrokeParam, QColor &defaultStrokeColor, bool &hasStrokeWidthParam, double &defaultStrokeWidth, bool blocking=false) const
Tests if an svg file contains parameters for fill, stroke color, stroke width.
Definition: qgssvgcache.cpp:225
QgsGuiUtils::iconSize
QSize iconSize(bool dockableToolbar)
Returns the user-preferred size of a window's toolbar icons.
Definition: qgsguiutils.cpp:250
qgsapplication.h
QgsApplication::qgisSettingsDirPath
static QString qgisSettingsDirPath()
Returns the path to the settings directory in user's home dir.
Definition: qgsapplication.cpp:993
QgsSvgSelectorWidget::setSvgPath
void setSvgPath(const QString &svgPath)
Accepts absolute paths.
Definition: qgssvgselectorwidget.cpp:404
whileBlocking
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition: qgis.h:262
QgsSvgSelectorListModel::mSvgFiles
QStringList mSvgFiles
Definition: qgssvgselectorwidget.h:207
Qgis::UI_SCALE_FACTOR
static const double UI_SCALE_FACTOR
UI scaling factor.
Definition: qgis.h:182
QgsApplication::pkgDataPath
static QString pkgDataPath()
Returns the common root path of all application data directories.
Definition: qgsapplication.cpp:578
QgsSvgSelectorListModel
A model for displaying SVG files with a preview icon.
Definition: qgssvgselectorwidget.h:182
QgsSvgSelectorDialog::mButtonBox
QDialogButtonBox * mButtonBox
Definition: qgssvgselectorwidget.h:317
QgsApplication::svgCache
static QgsSvgCache * svgCache()
Returns the application's SVG cache, used for caching SVG images and handling parameter replacement w...
Definition: qgsapplication.cpp:2178
QgsSvgSelectorWidget::QgsSvgSelectorWidget
QgsSvgSelectorWidget(QWidget *parent=nullptr)
Constructor for QgsSvgSelectorWidget.
Definition: qgssvgselectorwidget.cpp:380
QgsSvgSelectorWidget::currentSvgPath
QString currentSvgPath() const
Definition: qgssvgselectorwidget.cpp:427
QgsSvgSelectorGroupsModel::QgsSvgSelectorGroupsModel
QgsSvgSelectorGroupsModel(QObject *parent)
Definition: qgssvgselectorwidget.cpp:314
QgsSvgSelectorWidget::svgSelected
void svgSelected(const QString &path)
QgsSvgSelectorGroupsModel
A model for displaying SVG search paths.
Definition: qgssvgselectorwidget.h:234
QgsSvgSelectorDialog::mLayout
QVBoxLayout * mLayout
Definition: qgssvgselectorwidget.h:316
QgsSymbolLayerUtils::svgSymbolNameToPath
static QString svgSymbolNameToPath(const QString &name, const QgsPathResolver &pathResolver)
Determines an SVG symbol's path from its name.
Definition: qgssymbollayerutils.cpp:3941
qgssettings.h
QgsSvgSelectorGroupsModel::~QgsSvgSelectorGroupsModel
~QgsSvgSelectorGroupsModel() override
Definition: qgssvgselectorwidget.cpp:355
QgsSvgSelectorWidget
Definition: qgssvgselectorwidget.h:255
qgslogger.h
qgssvgselectorwidget.h
QgsSvgSelectorWidget::populateList
void populateList()
Definition: qgssvgselectorwidget.cpp:466
QgsAbstractFileContentSourceLineEdit::sourceChanged
void sourceChanged(const QString &source)
Emitted whenever the file source is changed in the widget.
qgsproject.h
QgsSvgSelectorDialog::mSvgSelector
QgsSvgSelectorWidget * mSvgSelector
Definition: qgssvgselectorwidget.h:318
QgsSvgSelectorListModel::QgsSvgSelectorListModel
QgsSvgSelectorListModel(QObject *parent, int iconSize=30)
Constructor for QgsSvgSelectorListModel.
Definition: qgssvgselectorwidget.cpp:220