QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
qgsstylemanagerdialog.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsstylemanagerdialog.cpp
3  ---------------------
4  begin : November 2009
5  copyright : (C) 2009 by Martin Dobias
6  email : wonder dot sk at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include "qgsstylemanagerdialog.h"
17 #include "qgsstylesavedialog.h"
18 
19 #include "qgssymbol.h"
20 #include "qgssymbollayerutils.h"
21 #include "qgscolorramp.h"
22 
31 #include "qgssettings.h"
32 #include "qgsstylemodel.h"
33 #include "qgsmessagebar.h"
34 #include "qgstextformatwidget.h"
35 #include "qgslabelinggui.h"
37 #include "qgsabstract3dsymbol.h"
38 #include "qgs3dsymbolregistry.h"
39 #include "qgs3dsymbolwidget.h"
40 #include "qgsfillsymbol.h"
41 #include "qgslinesymbol.h"
42 #include "qgsmarkersymbol.h"
43 #include "qgsiconutils.h"
44 #include "qgsproject.h"
46 #include "qgsfileutils.h"
47 
48 #include <QAction>
49 #include <QFile>
50 #include <QFileDialog>
51 #include <QInputDialog>
52 #include <QMessageBox>
53 #include <QPushButton>
54 #include <QStandardItemModel>
55 #include <QMenu>
56 #include <QClipboard>
57 #include <QDesktopServices>
58 #include <QUrl>
59 #include <QShortcut>
60 
61 #include "qgsapplication.h"
62 #include "qgslogger.h"
63 
64 //
65 // QgsCheckableStyleModel
66 //
67 
69 QgsCheckableStyleModel::QgsCheckableStyleModel( QgsStyleModel *sourceModel, QObject *parent, bool readOnly )
70  : QgsStyleProxyModel( sourceModel, parent )
71  , mStyle( sourceModel->style() )
72  , mReadOnly( readOnly )
73 {
74 
75 }
76 
77 QgsCheckableStyleModel::QgsCheckableStyleModel( QgsStyle *style, QObject *parent, bool readOnly )
78  : QgsStyleProxyModel( style, parent )
79  , mStyle( style )
80  , mReadOnly( readOnly )
81 {
82 }
83 
84 void QgsCheckableStyleModel::setCheckable( bool checkable )
85 {
86  if ( checkable == mCheckable )
87  return;
88 
89  mCheckable = checkable;
90  emit dataChanged( index( 0, 0 ), index( rowCount() - 1, 0 ), QVector< int >() << Qt::CheckStateRole );
91 }
92 
93 void QgsCheckableStyleModel::setCheckTag( const QString &tag )
94 {
95  if ( tag == mCheckTag )
96  return;
97 
98  mCheckTag = tag;
99  emit dataChanged( index( 0, 0 ), index( rowCount() - 1, 0 ), QVector< int >() << Qt::CheckStateRole );
100 }
101 
102 Qt::ItemFlags QgsCheckableStyleModel::flags( const QModelIndex &index ) const
103 {
104  Qt::ItemFlags f = QgsStyleProxyModel::flags( index );
105  if ( !mReadOnly && mCheckable && index.column() == 0 )
106  f |= Qt::ItemIsUserCheckable;
107 
108  if ( mReadOnly )
109  f &= ~Qt::ItemIsEditable;
110 
111  return f;
112 }
113 
114 QVariant QgsCheckableStyleModel::data( const QModelIndex &index, int role ) const
115 {
116  switch ( role )
117  {
118  case Qt::FontRole:
119  {
120  // drop font size to get reasonable amount of item name shown
121  QFont f = QgsStyleProxyModel::data( index, role ).value< QFont >();
122  f.setPointSize( 9 );
123  return f;
124  }
125 
126  case Qt::CheckStateRole:
127  {
128  if ( !mCheckable || index.column() != 0 )
129  return QVariant();
130 
131  const QStringList tags = data( index, QgsStyleModel::TagRole ).toStringList();
132  return tags.contains( mCheckTag ) ? Qt::Checked : Qt::Unchecked;
133  }
134 
135  default:
136  break;
137 
138  }
139  return QgsStyleProxyModel::data( index, role );
140 }
141 
142 bool QgsCheckableStyleModel::setData( const QModelIndex &i, const QVariant &value, int role )
143 {
144  if ( i.row() < 0 || i.row() >= rowCount( QModelIndex() ) ||
145  ( role != Qt::EditRole && role != Qt::CheckStateRole ) )
146  return false;
147 
148  if ( mReadOnly )
149  return false;
150 
151  if ( role == Qt::CheckStateRole )
152  {
153  if ( !mCheckable || mCheckTag.isEmpty() )
154  return false;
155 
156  const QString name = data( index( i.row(), QgsStyleModel::Name ), Qt::DisplayRole ).toString();
157  const QgsStyle::StyleEntity entity = static_cast< QgsStyle::StyleEntity >( data( i, QgsStyleModel::TypeRole ).toInt() );
158 
159  if ( value.toInt() == Qt::Checked )
160  return mStyle->tagSymbol( entity, name, QStringList() << mCheckTag );
161  else
162  return mStyle->detagSymbol( entity, name, QStringList() << mCheckTag );
163  }
164  return QgsStyleProxyModel::setData( i, value, role );
165 }
167 
168 //
169 // QgsStyleManagerDialog
170 //
171 
172 #include "qgsgui.h"
173 
174 QString QgsStyleManagerDialog::sPreviousTag;
175 
176 QgsStyleManagerDialog::QgsStyleManagerDialog( QgsStyle *style, QWidget *parent, Qt::WindowFlags flags, bool readOnly )
177  : QDialog( parent, flags )
178  , mReadOnly( readOnly )
179 {
180  init();
181  setCurrentStyle( style );
182  mStyleDatabaseWidget->hide();
183 }
184 
185 QgsStyleManagerDialog::QgsStyleManagerDialog( QWidget *parent, Qt::WindowFlags flags )
186  : QDialog( parent, flags )
187 {
188  init();
189 
190  mProjectStyleModel = new QgsProjectStyleDatabaseModel( QgsProject::instance()->styleSettings(), this );
191  mProjectStyleModel->setShowDefaultStyle( true );
192  mComboBoxStyleDatabase->setModel( mProjectStyleModel );
193 
194  setCurrentStyle( QgsStyle::defaultStyle() );
195 
196  connect( mComboBoxStyleDatabase, qOverload< int >( &QComboBox::currentIndexChanged ), this, [ = ]()
197  {
198  if ( mBlockStyleDatabaseChanges )
199  return;
200 
201  const QModelIndex index = mProjectStyleModel->index( mComboBoxStyleDatabase->currentIndex(), 0, QModelIndex() );
202  setCurrentStyle( mProjectStyleModel->styleFromIndex( index ) );
203  } );
204 
205  connect( mButtonAddStyleDatabase, &QAbstractButton::clicked, this, [ = ] { addStyleDatabase( false ); } );
206  connect( mButtonNewStyleDatabase, &QAbstractButton::clicked, this, [ = ] { addStyleDatabase( true ); } );
207 
208 #if QT_VERSION < QT_VERSION_CHECK(5, 13, 0)
209  // you don't get nice stuff
210  mStyleDatabaseWidget->hide();
211 #endif
212 }
213 
214 void QgsStyleManagerDialog::init()
215 {
216  setupUi( this );
218  connect( tabItemType, &QTabWidget::currentChanged, this, &QgsStyleManagerDialog::tabItemType_currentChanged );
219  connect( buttonBox, &QDialogButtonBox::helpRequested, this, &QgsStyleManagerDialog::showHelp );
220  connect( buttonBox, &QDialogButtonBox::rejected, this, &QgsStyleManagerDialog::onClose );
221 
222  QPushButton *downloadButton = buttonBox->addButton( tr( "Browse Online Styles" ), QDialogButtonBox::ResetRole );
223  downloadButton->setToolTip( tr( "Download new styles from the online QGIS style repository" ) );
224  downloadButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionFindReplace.svg" ) ) );
225  connect( downloadButton, &QPushButton::clicked, this, [ = ]
226  {
227  QDesktopServices::openUrl( QUrl( QStringLiteral( "https://plugins.qgis.org/styles" ) ) );
228  } );
229 
230  mMessageBar = new QgsMessageBar();
231  mMessageBar->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed );
232  mVerticalLayout->insertWidget( 0, mMessageBar );
233 
234 #ifdef Q_OS_MAC
235  setWindowModality( Qt::WindowModal );
236 #endif
237 
238  QgsSettings settings;
239 
240  mSplitter->setSizes( QList<int>() << 170 << 540 );
241  mSplitter->restoreState( settings.value( QStringLiteral( "Windows/StyleV2Manager/splitter" ) ).toByteArray() );
242 
243  tabItemType->setDocumentMode( true );
244  searchBox->setShowSearchIcon( true );
245  searchBox->setPlaceholderText( tr( "Filter symbols…" ) );
246 
247  connect( this, &QDialog::finished, this, &QgsStyleManagerDialog::onFinished );
248  connect( listItems, &QAbstractItemView::doubleClicked, this, &QgsStyleManagerDialog::editItem );
249  connect( btnEditItem, &QPushButton::clicked, this, [ = ]( bool ) { editItem(); }
250  );
251  connect( actnEditItem, &QAction::triggered, this, [ = ]( bool ) { editItem(); }
252  );
253 
254 
255  connect( btnAddItem, &QPushButton::clicked, this, [ = ]( bool )
256  {
257  // only show add item if the btn doesn't have a menu -- otherwise it should show the menu instead!
258  if ( !btnAddItem->menu() )
259  {
260  addItem();
261  }
262  }
263  );
264 
265  connect( btnRemoveItem, &QPushButton::clicked, this, [ = ]( bool ) { removeItem(); }
266  );
267  connect( actnRemoveItem, &QAction::triggered, this, [ = ]( bool ) { removeItem(); }
268  );
269 
270  mShareMenu = new QMenu( tr( "Share Menu" ), this );
271  mExportAction = new QAction( tr( "Export Item(s)…" ), this );
272  mExportAction->setIcon( QIcon( QgsApplication::iconPath( "mActionFileSave.svg" ) ) );
273  mShareMenu->addAction( mExportAction );
274 
275  connect( mCopyToDefaultButton, &QPushButton::clicked, this, &QgsStyleManagerDialog::copyItemsToDefault );
276 
277  mActionCopyItem = new QAction( tr( "Copy Item" ), this );
278  connect( mActionCopyItem, &QAction::triggered, this, &QgsStyleManagerDialog::copyItem );
279  mActionPasteItem = new QAction( tr( "Paste Item…" ), this );
280  connect( mActionPasteItem, &QAction::triggered, this, &QgsStyleManagerDialog::pasteItem );
281 
282  QShortcut *copyShortcut = new QShortcut( QKeySequence( QKeySequence::StandardKey::Copy ), this );
283  connect( copyShortcut, &QShortcut::activated, this, &QgsStyleManagerDialog::copyItem );
284  QShortcut *pasteShortcut = new QShortcut( QKeySequence( QKeySequence::StandardKey::Paste ), this );
285  connect( pasteShortcut, &QShortcut::activated, this, &QgsStyleManagerDialog::pasteItem );
286  QShortcut *removeShortcut = new QShortcut( QKeySequence( QKeySequence::StandardKey::Delete ), this );
287  connect( removeShortcut, &QShortcut::activated, this, &QgsStyleManagerDialog::removeItem );
288  QShortcut *editShortcut = new QShortcut( QKeySequence( Qt::Key_Return ), this );
289  connect( editShortcut, &QShortcut::activated, this, &QgsStyleManagerDialog::editItem );
290 
291  mShareMenu->addSeparator();
292  mShareMenu->addAction( actnExportAsPNG );
293  mShareMenu->addAction( actnExportAsSVG );
294 
295  connect( actnExportAsPNG, &QAction::triggered, this, &QgsStyleManagerDialog::exportItemsPNG );
296  connect( actnExportAsSVG, &QAction::triggered, this, &QgsStyleManagerDialog::exportItemsSVG );
297  connect( mExportAction, &QAction::triggered, this, &QgsStyleManagerDialog::exportItems );
298  btnShare->setMenu( mShareMenu );
299 
300  listItems->setTextElideMode( Qt::TextElideMode::ElideRight );
301  double treeIconSize = Qgis::UI_SCALE_FACTOR * fontMetrics().horizontalAdvance( 'X' ) * 2;
302  mSymbolTreeView->setIconSize( QSize( static_cast< int >( treeIconSize ), static_cast< int >( treeIconSize ) ) );
303 
304  listItems->setSelectionBehavior( QAbstractItemView::SelectRows );
305  listItems->setSelectionMode( QAbstractItemView::ExtendedSelection );
306  mSymbolTreeView->setSelectionMode( listItems->selectionMode() );
307 
308  QStandardItemModel *groupModel = new QStandardItemModel( groupTree );
309  groupTree->setModel( groupModel );
310  groupTree->setHeaderHidden( true );
311 
312  connect( groupTree->selectionModel(), &QItemSelectionModel::currentChanged,
314  connect( groupModel, &QStandardItemModel::itemChanged, this, &QgsStyleManagerDialog::groupRenamed );
315 
316  QMenu *groupMenu = new QMenu( tr( "Group Actions" ), this );
317  connect( actnTagSymbols, &QAction::triggered, this, &QgsStyleManagerDialog::tagSymbolsAction );
318  groupMenu->addAction( actnTagSymbols );
319  connect( actnFinishTagging, &QAction::triggered, this, &QgsStyleManagerDialog::tagSymbolsAction );
320  actnFinishTagging->setVisible( false );
321  groupMenu->addAction( actnFinishTagging );
322  groupMenu->addAction( actnEditSmartGroup );
323  btnManageGroups->setMenu( groupMenu );
324 
325  connect( searchBox, &QLineEdit::textChanged, this, &QgsStyleManagerDialog::filterSymbols );
326 
327  // Context menu for groupTree
328  groupTree->setContextMenuPolicy( Qt::CustomContextMenu );
329  connect( groupTree, &QWidget::customContextMenuRequested,
331 
332  // Context menu for listItems
333  listItems->setContextMenuPolicy( Qt::CustomContextMenu );
334  connect( listItems, &QWidget::customContextMenuRequested,
336  mSymbolTreeView->setContextMenuPolicy( Qt::CustomContextMenu );
337  connect( mSymbolTreeView, &QWidget::customContextMenuRequested,
339 
340  mMenuBtnAddItemAll = new QMenu( this );
341  mMenuBtnAddItemColorRamp = new QMenu( this );
342  mMenuBtnAddItemLabelSettings = new QMenu( this );
343  mMenuBtnAddItemLegendPatchShape = new QMenu( this );
344  mMenuBtnAddItemSymbol3D = new QMenu( this );
345 
346  QAction *item = new QAction( QgsIconUtils::iconPoint(), tr( "Marker…" ), this );
347  connect( item, &QAction::triggered, this, [ = ]( bool ) { addSymbol( static_cast< int >( Qgis::SymbolType::Marker ) ); } );
348  mMenuBtnAddItemAll->addAction( item );
349  item = new QAction( QgsIconUtils::iconLine(), tr( "Line…" ), this );
350  connect( item, &QAction::triggered, this, [ = ]( bool ) { addSymbol( static_cast< int >( Qgis::SymbolType::Line ) ); } );
351  mMenuBtnAddItemAll->addAction( item );
352  item = new QAction( QgsIconUtils::iconPolygon(), tr( "Fill…" ), this );
353  connect( item, &QAction::triggered, this, [ = ]( bool ) { addSymbol( static_cast< int >( Qgis::SymbolType::Fill ) ); } );
354  mMenuBtnAddItemAll->addAction( item );
355  mMenuBtnAddItemAll->addSeparator();
356 
357  const QList< QPair< QString, QString > > rampTypes = QgsColorRamp::rampTypes();
358  for ( const QPair< QString, QString > &rampType : rampTypes )
359  {
360  item = new QAction( QgsApplication::getThemeIcon( QStringLiteral( "styleicons/color.svg" ) ), tr( "%1…" ).arg( rampType.second ), this );
361  connect( item, &QAction::triggered, this, [ = ]( bool ) { addColorRamp( rampType.first ); } );
362  mMenuBtnAddItemAll->addAction( item );
363  mMenuBtnAddItemColorRamp->addAction( item );
364  }
365  mMenuBtnAddItemAll->addSeparator();
366  item = new QAction( QgsApplication::getThemeIcon( QStringLiteral( "mIconFieldText.svg" ) ), tr( "Text Format…" ), this );
367  connect( item, &QAction::triggered, this, [ = ]( bool ) { addTextFormat(); } );
368  mMenuBtnAddItemAll->addAction( item );
369  mMenuBtnAddItemAll->addSeparator();
370  item = new QAction( QgsApplication::getThemeIcon( QStringLiteral( "labelingSingle.svg" ) ), tr( "Point Label Settings…" ), this );
371  connect( item, &QAction::triggered, this, [ = ]( bool ) { addLabelSettings( QgsWkbTypes::PointGeometry ); } );
372  mMenuBtnAddItemAll->addAction( item );
373  mMenuBtnAddItemLabelSettings->addAction( item );
374  item = new QAction( QgsApplication::getThemeIcon( QStringLiteral( "labelingSingle.svg" ) ), tr( "Line Label Settings…" ), this );
375  connect( item, &QAction::triggered, this, [ = ]( bool ) { addLabelSettings( QgsWkbTypes::LineGeometry ); } );
376  mMenuBtnAddItemAll->addAction( item );
377  mMenuBtnAddItemLabelSettings->addAction( item );
378  item = new QAction( QgsApplication::getThemeIcon( QStringLiteral( "labelingSingle.svg" ) ), tr( "Polygon Label Settings…" ), this );
379  connect( item, &QAction::triggered, this, [ = ]( bool ) { addLabelSettings( QgsWkbTypes::PolygonGeometry ); } );
380  mMenuBtnAddItemAll->addAction( item );
381  mMenuBtnAddItemLabelSettings->addAction( item );
382 
383  mMenuBtnAddItemAll->addSeparator();
384  item = new QAction( QgsApplication::getThemeIcon( QStringLiteral( "legend.svg" ) ), tr( "Marker Legend Patch Shape…" ), this );
385  connect( item, &QAction::triggered, this, [ = ]( bool ) { addLegendPatchShape( Qgis::SymbolType::Marker ); } );
386  mMenuBtnAddItemAll->addAction( item );
387  mMenuBtnAddItemLegendPatchShape->addAction( item );
388  item = new QAction( QgsApplication::getThemeIcon( QStringLiteral( "legend.svg" ) ), tr( "Line Legend Patch Shape…" ), this );
389  connect( item, &QAction::triggered, this, [ = ]( bool ) { addLegendPatchShape( Qgis::SymbolType::Line ); } );
390  mMenuBtnAddItemAll->addAction( item );
391  mMenuBtnAddItemLegendPatchShape->addAction( item );
392  item = new QAction( QgsApplication::getThemeIcon( QStringLiteral( "legend.svg" ) ), tr( "Fill Legend Patch Shape…" ), this );
393  connect( item, &QAction::triggered, this, [ = ]( bool ) { addLegendPatchShape( Qgis::SymbolType::Fill ); } );
394  mMenuBtnAddItemAll->addAction( item );
395  mMenuBtnAddItemLegendPatchShape->addAction( item );
396 
397  mMenuBtnAddItemAll->addSeparator();
398  item = new QAction( QgsApplication::getThemeIcon( QStringLiteral( "3d.svg" ) ), tr( "3D Point Symbol…" ), this );
399  connect( item, &QAction::triggered, this, [ = ]( bool ) { addSymbol3D( QStringLiteral( "point" ) ); } );
400  mMenuBtnAddItemAll->addAction( item );
401  mMenuBtnAddItemSymbol3D->addAction( item );
402  item = new QAction( QgsApplication::getThemeIcon( QStringLiteral( "3d.svg" ) ), tr( "3D Line Symbol…" ), this );
403  connect( item, &QAction::triggered, this, [ = ]( bool ) { addSymbol3D( QStringLiteral( "line" ) ); } );
404  mMenuBtnAddItemAll->addAction( item );
405  mMenuBtnAddItemSymbol3D->addAction( item );
406  item = new QAction( QgsApplication::getThemeIcon( QStringLiteral( "3d.svg" ) ), tr( "3D Polygon Symbol…" ), this );
407  connect( item, &QAction::triggered, this, [ = ]( bool ) { addSymbol3D( QStringLiteral( "polygon" ) ); } );
408  mMenuBtnAddItemAll->addAction( item );
409  mMenuBtnAddItemSymbol3D->addAction( item );
410 
411  // Context menu for symbols/colorramps. The menu entries for every group are created when displaying the menu.
412  mGroupMenu = new QMenu( this );
413  mGroupListMenu = new QMenu( mGroupMenu );
414  mGroupListMenu->setTitle( tr( "Add to Tag" ) );
415  mGroupListMenu->setEnabled( false );
416 
417  connect( actnAddFavorite, &QAction::triggered, this, &QgsStyleManagerDialog::addFavoriteSelectedSymbols );
418  connect( actnRemoveFavorite, &QAction::triggered, this, &QgsStyleManagerDialog::removeFavoriteSelectedSymbols );
419  connect( actnDetag, &QAction::triggered, this, &QgsStyleManagerDialog::detagSelectedSymbols );
420 
421  // Context menu for the group tree
422  mGroupTreeContextMenu = new QMenu( this );
423  connect( actnEditSmartGroup, &QAction::triggered, this, &QgsStyleManagerDialog::editSmartgroupAction );
424  connect( actnAddTag, &QAction::triggered, this, [ = ]( bool ) { addTag(); } );
425  connect( actnAddSmartgroup, &QAction::triggered, this, [ = ]( bool ) { addSmartgroup(); } );
426  connect( actnRemoveGroup, &QAction::triggered, this, &QgsStyleManagerDialog::removeGroup );
427 
428  tabItemType_currentChanged( 0 );
429 
430  connect( mButtonIconView, &QToolButton::toggled, this, [ = ]( bool active )
431  {
432  if ( active )
433  {
434  mSymbolViewStackedWidget->setCurrentIndex( 0 );
435  // note -- we have to save state here and not in destructor, as new symbol list widgets are created before the previous ones are destroyed
436  QgsSettings().setValue( QStringLiteral( "Windows/StyleV2Manager/lastIconView" ), 0, QgsSettings::Gui );
437  }
438  } );
439  connect( mButtonListView, &QToolButton::toggled, this, [ = ]( bool active )
440  {
441  if ( active )
442  {
443  QgsSettings().setValue( QStringLiteral( "Windows/StyleV2Manager/lastIconView" ), 1, QgsSettings::Gui );
444  mSymbolViewStackedWidget->setCurrentIndex( 1 );
445  }
446  } );
447  // restore previous view
448  const int currentView = settings.value( QStringLiteral( "Windows/StyleV2Manager/lastIconView" ), 0, QgsSettings::Gui ).toInt();
449  if ( currentView == 0 )
450  mButtonIconView->setChecked( true );
451  else
452  mButtonListView->setChecked( true );
453 
454  mSymbolTreeView->header()->restoreState( settings.value( QStringLiteral( "Windows/StyleV2Manager/treeState" ), QByteArray(), QgsSettings::Gui ).toByteArray() );
455  connect( mSymbolTreeView->header(), &QHeaderView::sectionResized, this, [this]
456  {
457  // note -- we have to save state here and not in destructor, as new symbol list widgets are created before the previous ones are destroyed
458  QgsSettings().setValue( QStringLiteral( "Windows/StyleV2Manager/treeState" ), mSymbolTreeView->header()->saveState(), QgsSettings::Gui );
459  } );
460 
461  const int thumbnailSize = settings.value( QStringLiteral( "Windows/StyleV2Manager/thumbnailSize" ), 0, QgsSettings::Gui ).toInt();
462  mSliderIconSize->setValue( thumbnailSize );
463  connect( mSliderIconSize, &QSlider::valueChanged, this, &QgsStyleManagerDialog::setThumbnailSize );
464  setThumbnailSize( thumbnailSize );
465 }
466 
467 void QgsStyleManagerDialog::setCurrentStyle( QgsStyle *style )
468 {
469  if ( mStyle == style )
470  return;
471 
472  if ( mStyle )
473  {
474  disconnect( mStyle, &QgsStyle::symbolSaved, this, &QgsStyleManagerDialog::populateList );
476  disconnect( mStyle, &QgsStyle::aboutToBeDestroyed, this, &QgsStyleManagerDialog::currentStyleAboutToBeDestroyed );
477  }
478 
479  QgsCheckableStyleModel *oldModel = mModel;
480 
481  mStyle = style;
482  const bool readOnly = isReadOnly();
483  if ( mStyle != QgsStyle::defaultStyle() )
484  {
485  if ( !mActionCopyToDefault )
486  {
487  mActionCopyToDefault = new QAction( tr( "Copy Selection to Default Style…" ), this );
488  mShareMenu->insertAction( mActionCopyItem, mActionCopyToDefault );
489  connect( mActionCopyToDefault, &QAction::triggered, this, &QgsStyleManagerDialog::copyItemsToDefault );
490  }
491  mCopyToDefaultButton->show();
492  mModel = new QgsCheckableStyleModel( mStyle, this, readOnly );
493  }
494  else
495  {
496  mCopyToDefaultButton->hide();
497  if ( mActionCopyToDefault )
498  {
499  mActionCopyToDefault->deleteLater();
500  mActionCopyToDefault = nullptr;
501  }
502  mModel = new QgsCheckableStyleModel( QgsApplication::defaultStyleModel(), this, readOnly );
503  }
504  mModel->addDesiredIconSize( mSymbolTreeView->iconSize() );
505  mModel->addDesiredIconSize( listItems->iconSize() );
506  mModel->setFilterString( searchBox->text() );
507 
508  listItems->setModel( mModel );
509  mSymbolTreeView->setModel( mModel );
510 
511  mSymbolTreeView->setSelectionModel( listItems->selectionModel() );
512 
513  connect( listItems->selectionModel(), &QItemSelectionModel::currentChanged,
515  connect( listItems->selectionModel(), &QItemSelectionModel::selectionChanged,
517 
518  if ( oldModel )
519  {
520  oldModel->deleteLater();
521  oldModel = nullptr;
522  }
523 
526  connect( mStyle, &QgsStyle::aboutToBeDestroyed, this, &QgsStyleManagerDialog::currentStyleAboutToBeDestroyed );
527 
528  if ( mProjectStyleModel )
529  {
530  const QModelIndex styleIndex = mProjectStyleModel->indexFromStyle( mStyle );
531  mBlockStyleDatabaseChanges++;
532  mComboBoxStyleDatabase->setCurrentIndex( styleIndex.row() );
533  mBlockStyleDatabaseChanges--;
534  }
535 
536  if ( readOnly )
537  {
538  btnAddTag->setEnabled( false );
539  btnAddSmartgroup->setEnabled( false );
540  btnManageGroups->setEnabled( false );
541 
542  btnAddItem->setVisible( false );
543  btnRemoveItem->setVisible( false );
544  btnEditItem->setVisible( false );
545  btnAddSmartgroup->setVisible( false );
546  btnAddTag->setVisible( false );
547  btnManageGroups->setVisible( false );
548 
549  delete mImportAction;
550  mImportAction = nullptr;
551 
552  mGroupTreeContextMenu->clear();
553  mGroupMenu->clear();
554  mGroupMenu->addAction( mActionCopyItem );
555  }
556  else
557  {
558  btnAddTag->setEnabled( true );
559  btnAddSmartgroup->setEnabled( true );
560  btnManageGroups->setEnabled( true );
561 
562  btnAddItem->setVisible( true );
563  btnRemoveItem->setVisible( true );
564  btnEditItem->setVisible( true );
565  btnAddSmartgroup->setVisible( true );
566  btnAddTag->setVisible( true );
567  btnManageGroups->setVisible( true );
568 
569  if ( !mImportAction )
570  {
571  mImportAction = new QAction( tr( "Import Item(s)…" ), this );
572  mImportAction->setIcon( QIcon( QgsApplication::iconPath( "mActionFileOpen.svg" ) ) );
573  mShareMenu->insertAction( mShareMenu->actions().at( mShareMenu->actions().indexOf( mExportAction ) + 1 ), mImportAction );
574  connect( mImportAction, &QAction::triggered, this, &QgsStyleManagerDialog::importItems );
575  }
576 
577  mGroupTreeContextMenu->clear();
578  mGroupTreeContextMenu->addAction( actnEditSmartGroup );
579  mGroupTreeContextMenu->addAction( actnAddTag );
580  mGroupTreeContextMenu->addAction( actnAddSmartgroup );
581  mGroupTreeContextMenu->addAction( actnRemoveGroup );
582 
583  mGroupMenu->clear();
584  mGroupMenu->addAction( actnAddFavorite );
585  mGroupMenu->addAction( actnRemoveFavorite );
586  mGroupMenu->addSeparator()->setParent( this );
587  mGroupMenu->addMenu( mGroupListMenu );
588  mGroupMenu->addAction( actnDetag );
589  mGroupMenu->addSeparator()->setParent( this );
590  mGroupMenu->addAction( actnRemoveItem );
591  mGroupMenu->addAction( actnEditItem );
592  mGroupMenu->addAction( mActionCopyItem );
593  mGroupMenu->addAction( mActionPasteItem );
594  mGroupMenu->addSeparator()->setParent( this );
595  }
596 
597  if ( mActionCopyToDefault )
598  {
599  mGroupMenu->addAction( mActionCopyToDefault );
600  }
601  mGroupMenu->addAction( actnExportAsPNG );
602  mGroupMenu->addAction( actnExportAsSVG );
603 
604  populateGroups();
605  const QModelIndexList prevIndex = groupTree->model()->match( groupTree->model()->index( 0, 0 ), Qt::UserRole + 1, sPreviousTag, 1, Qt::MatchFixedString | Qt::MatchCaseSensitive | Qt::MatchRecursive );
606  groupTree->setCurrentIndex( !prevIndex.empty() ? prevIndex.at( 0 ) : groupTree->model()->index( 0, 0 ) );
607  populateList();
608 
609  tabItemType_currentChanged( tabItemType->currentIndex() );
610 
611  // set initial disabled state for actions requiring a selection
612  selectedSymbolsChanged( QItemSelection(), QItemSelection() );
613 }
614 
615 void QgsStyleManagerDialog::currentStyleAboutToBeDestroyed()
616 {
617  if ( mStyle != QgsStyle::defaultStyle() )
618  {
619  setCurrentStyle( QgsStyle::defaultStyle() );
620  }
621 }
622 
624 {
625  QgsSettings settings;
626  settings.setValue( QStringLiteral( "Windows/StyleV2Manager/splitter" ), mSplitter->saveState() );
627 }
628 
630 {
631 }
632 
633 void QgsStyleManagerDialog::tabItemType_currentChanged( int )
634 {
635  // when in Color Ramp tab, add menu to add item button and hide "Export symbols as PNG/SVG"
636  const bool isSymbol = currentItemType() != 3 && currentItemType() != 4 && currentItemType() != 5 && currentItemType() != 6 && currentItemType() != 7;
637  const bool isColorRamp = currentItemType() == 3;
638  const bool isTextFormat = currentItemType() == 4;
639  const bool isLabelSettings = currentItemType() == 5;
640  const bool isLegendPatchShape = currentItemType() == 6;
641  const bool isSymbol3D = currentItemType() == 7;
642  searchBox->setPlaceholderText( isSymbol ? tr( "Filter symbols…" ) :
643  isColorRamp ? tr( "Filter color ramps…" ) :
644  isTextFormat ? tr( "Filter text symbols…" ) :
645  isLabelSettings ? tr( "Filter label settings…" ) :
646  isLegendPatchShape ? tr( "Filter legend patch shapes…" ) : tr( "Filter 3D symbols…" ) );
647 
648  const bool readOnly = isReadOnly();
649  if ( !readOnly && isColorRamp ) // color ramp tab
650  {
651  btnAddItem->setMenu( mMenuBtnAddItemColorRamp );
652  }
653  else if ( !readOnly && isLegendPatchShape ) // legend patch shape tab
654  {
655  btnAddItem->setMenu( mMenuBtnAddItemLegendPatchShape );
656  }
657  else if ( !readOnly && isSymbol3D ) // legend patch shape tab
658  {
659  btnAddItem->setMenu( mMenuBtnAddItemSymbol3D );
660  }
661  else if ( !readOnly && isLabelSettings ) // label settings tab
662  {
663  btnAddItem->setMenu( mMenuBtnAddItemLabelSettings );
664  }
665  else if ( !readOnly && !isSymbol && !isColorRamp ) // text format tab
666  {
667  btnAddItem->setMenu( nullptr );
668  }
669  else if ( !readOnly && tabItemType->currentIndex() == 0 ) // all symbols tab
670  {
671  btnAddItem->setMenu( mMenuBtnAddItemAll );
672  }
673  else
674  {
675  btnAddItem->setMenu( nullptr );
676  }
677 
678  actnExportAsPNG->setVisible( isSymbol );
679  actnExportAsSVG->setVisible( isSymbol );
680 
681  if ( mModel )
682  {
683  mModel->setEntityFilter( isSymbol ? QgsStyle::SymbolEntity : ( isColorRamp ? QgsStyle::ColorrampEntity : isTextFormat ? QgsStyle::TextFormatEntity : isLabelSettings ? QgsStyle::LabelSettingsEntity : isLegendPatchShape ? QgsStyle::LegendPatchShapeEntity : QgsStyle::Symbol3DEntity ) );
684  mModel->setEntityFilterEnabled( !allTypesSelected() );
685  mModel->setSymbolTypeFilterEnabled( isSymbol && !allTypesSelected() );
686  if ( isSymbol && !allTypesSelected() )
687  mModel->setSymbolType( static_cast< Qgis::SymbolType >( currentItemType() ) );
688  }
689 
690  populateList();
691 }
692 
693 void QgsStyleManagerDialog::copyItemsToDefault()
694 {
695  const QList< ItemDetails > items = selectedItems();
696  if ( !items.empty() )
697  {
698  bool ok = false;
699  QStringList options;
700  if ( !mBaseName.isEmpty() )
701  options.append( mBaseName );
702 
703  QStringList defaultTags = QgsStyle::defaultStyle()->tags();
704  defaultTags.sort( Qt::CaseInsensitive );
705  options.append( defaultTags );
706  const QString tags = QInputDialog::getItem( this, tr( "Import Items" ),
707  tr( "Additional tags to add (comma separated)" ), options, mBaseName.isEmpty() ? -1 : 0, true, &ok );
708  if ( !ok )
709  return;
710 
711 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
712  const QStringList parts = tags.split( ',', QString::SkipEmptyParts );
713 #else
714  const QStringList parts = tags.split( ',', Qt::SkipEmptyParts );
715 #endif
716  QStringList additionalTags;
717  additionalTags.reserve( parts.count() );
718  for ( const QString &tag : parts )
719  additionalTags << tag.trimmed();
720 
721  auto cursorOverride = std::make_unique< QgsTemporaryCursorOverride >( Qt::WaitCursor );
722  const int count = copyItems( items, mStyle, QgsStyle::defaultStyle(), this, cursorOverride, true, additionalTags, false, false );
723  cursorOverride.reset();
724  if ( count > 0 )
725  {
726  mMessageBar->pushSuccess( tr( "Import Items" ), count > 1 ? tr( "Successfully imported %n item(s).", nullptr, count ) : tr( "Successfully imported item." ) );
727  }
728  }
729 }
730 
731 void QgsStyleManagerDialog::copyItem()
732 {
733  const QList< ItemDetails > items = selectedItems();
734  if ( items.empty() )
735  return;
736 
737  ItemDetails details = items.at( 0 );
738  switch ( details.entityType )
739  {
741  {
742  std::unique_ptr< QgsSymbol > symbol( mStyle->symbol( details.name ) );
743  if ( !symbol )
744  return;
745  QApplication::clipboard()->setMimeData( QgsSymbolLayerUtils::symbolToMimeData( symbol.get() ) );
746  break;
747  }
748 
750  {
751  const QgsTextFormat format( mStyle->textFormat( details.name ) );
752  QApplication::clipboard()->setMimeData( format.toMimeData() );
753  break;
754  }
755 
757  {
758  const QgsTextFormat format( mStyle->labelSettings( details.name ).format() );
759  QApplication::clipboard()->setMimeData( format.toMimeData() );
760  break;
761  }
762 
766  case QgsStyle::TagEntity:
768  return;
769 
770  }
771 }
772 
773 void QgsStyleManagerDialog::pasteItem()
774 {
775  const QString defaultTag = groupTree->currentIndex().isValid() ? groupTree->currentIndex().data( GroupModelRoles::TagName ).toString() : QString();
776  std::unique_ptr< QgsSymbol > tempSymbol( QgsSymbolLayerUtils::symbolFromMimeData( QApplication::clipboard()->mimeData() ) );
777  if ( tempSymbol )
778  {
779  QgsStyleSaveDialog saveDlg( this );
780  saveDlg.setWindowTitle( tr( "Paste Symbol" ) );
781  saveDlg.setDefaultTags( defaultTag );
782  if ( !saveDlg.exec() || saveDlg.name().isEmpty() )
783  return;
784 
785  if ( mStyle->symbolNames().contains( saveDlg.name() ) )
786  {
787  int res = QMessageBox::warning( this, tr( "Paste Symbol" ),
788  tr( "A symbol with the name '%1' already exists. Overwrite?" )
789  .arg( saveDlg.name() ),
790  QMessageBox::Yes | QMessageBox::No );
791  if ( res != QMessageBox::Yes )
792  {
793  return;
794  }
795  mStyle->removeSymbol( saveDlg.name() );
796  }
797 
798  QStringList symbolTags = saveDlg.tags().split( ',' );
799  QgsSymbol *newSymbol = tempSymbol.get();
800  mStyle->addSymbol( saveDlg.name(), tempSymbol.release() );
801  // make sure the symbol is stored
802  mStyle->saveSymbol( saveDlg.name(), newSymbol, saveDlg.isFavorite(), symbolTags );
803  return;
804  }
805 
806  bool ok = false;
807  const QgsTextFormat format = QgsTextFormat::fromMimeData( QApplication::clipboard()->mimeData(), &ok );
808  if ( ok )
809  {
810  QgsStyleSaveDialog saveDlg( this, QgsStyle::TextFormatEntity );
811  saveDlg.setDefaultTags( defaultTag );
812  saveDlg.setWindowTitle( tr( "Paste Text Format" ) );
813  if ( !saveDlg.exec() || saveDlg.name().isEmpty() )
814  return;
815 
816  if ( mStyle->textFormatNames().contains( saveDlg.name() ) )
817  {
818  int res = QMessageBox::warning( this, tr( "Paste Text Format" ),
819  tr( "A format with the name '%1' already exists. Overwrite?" )
820  .arg( saveDlg.name() ),
821  QMessageBox::Yes | QMessageBox::No );
822  if ( res != QMessageBox::Yes )
823  {
824  return;
825  }
826  mStyle->removeTextFormat( saveDlg.name() );
827  }
828 
829  QStringList symbolTags = saveDlg.tags().split( ',' );
830  mStyle->addTextFormat( saveDlg.name(), format );
831  // make sure the foprmatis stored
832  mStyle->saveTextFormat( saveDlg.name(), format, saveDlg.isFavorite(), symbolTags );
833  return;
834  }
835 }
836 
837 void QgsStyleManagerDialog::setThumbnailSize( int value )
838 {
839  // value ranges from 0-10
840  const double iconSize = Qgis::UI_SCALE_FACTOR * fontMetrics().horizontalAdvance( 'X' ) * ( value * 2.5 + 10 );
841  // set a grid size which allows sufficient vertical spacing to fit reasonably sized entity names
842  const double spacing = Qgis::UI_SCALE_FACTOR * fontMetrics().horizontalAdvance( 'X' ) * ( value * 2.2 + 14 );
843  const double verticalSpacing = Qgis::UI_SCALE_FACTOR * fontMetrics().horizontalAdvance( 'X' ) * 7
844  + iconSize * 0.8;
845  listItems->setIconSize( QSize( static_cast< int >( iconSize ), static_cast< int >( iconSize * 0.9 ) ) );
846  listItems->setGridSize( QSize( static_cast< int >( spacing ), static_cast< int >( verticalSpacing ) ) );
847  if ( mModel )
848  {
849  mModel->addDesiredIconSize( listItems->iconSize() );
850  }
851 
852  QgsSettings().setValue( QStringLiteral( "Windows/StyleV2Manager/thumbnailSize" ), value, QgsSettings::Gui );
853 }
854 
855 int QgsStyleManagerDialog::selectedItemType()
856 {
857  QModelIndex index = listItems->selectionModel()->currentIndex();
858  if ( !index.isValid() )
859  return 0;
860 
861  const QgsStyle::StyleEntity entity = static_cast< QgsStyle::StyleEntity >( mModel->data( index, QgsStyleModel::TypeRole ).toInt() );
862  if ( entity == QgsStyle::ColorrampEntity )
863  return 3;
864  else if ( entity == QgsStyle::TextFormatEntity )
865  return 4;
866  else if ( entity == QgsStyle::LabelSettingsEntity )
867  return 5;
868  else if ( entity == QgsStyle::LegendPatchShapeEntity )
869  return 6;
870  else if ( entity == QgsStyle::Symbol3DEntity )
871  return 7;
872 
873  return mModel->data( index, QgsStyleModel::SymbolTypeRole ).toInt();
874 }
875 
876 bool QgsStyleManagerDialog::allTypesSelected() const
877 {
878  return tabItemType->currentIndex() == 0;
879 }
880 
881 bool QgsStyleManagerDialog::isReadOnly() const
882 {
883  return mReadOnly || ( mStyle && mStyle->isReadOnly() );
884 }
885 
886 QList< QgsStyleManagerDialog::ItemDetails > QgsStyleManagerDialog::selectedItems()
887 {
888  QList<QgsStyleManagerDialog::ItemDetails > res;
889  QModelIndexList indices = listItems->selectionModel()->selectedRows();
890  for ( const QModelIndex &index : indices )
891  {
892  if ( !index.isValid() )
893  continue;
894 
895  ItemDetails details;
896  details.entityType = static_cast< QgsStyle::StyleEntity >( mModel->data( index, QgsStyleModel::TypeRole ).toInt() );
897  if ( details.entityType == QgsStyle::SymbolEntity )
898  details.symbolType = static_cast< Qgis::SymbolType >( mModel->data( index, QgsStyleModel::SymbolTypeRole ).toInt() );
899  details.name = mModel->data( mModel->index( index.row(), QgsStyleModel::Name, index.parent() ), Qt::DisplayRole ).toString();
900 
901  res << details;
902  }
903  return res;
904 }
905 
906 int QgsStyleManagerDialog::copyItems( const QList<QgsStyleManagerDialog::ItemDetails> &items, QgsStyle *src, QgsStyle *dst, QWidget *parentWidget,
907  std::unique_ptr< QgsTemporaryCursorOverride > &cursorOverride, bool isImport, const QStringList &importTags, bool addToFavorites, bool ignoreSourceTags )
908 {
909  bool prompt = true;
910  bool overwriteAll = true;
911  int count = 0;
912 
913  const QStringList favoriteSymbols = src->symbolsOfFavorite( QgsStyle::SymbolEntity );
914  const QStringList favoriteColorramps = src->symbolsOfFavorite( QgsStyle::ColorrampEntity );
915  const QStringList favoriteTextFormats = src->symbolsOfFavorite( QgsStyle::TextFormatEntity );
916  const QStringList favoriteLabelSettings = src->symbolsOfFavorite( QgsStyle::LabelSettingsEntity );
917  const QStringList favoriteLegendPatchShapes = src->symbolsOfFavorite( QgsStyle::LegendPatchShapeEntity );
918  const QStringList favorite3dSymbols = src->symbolsOfFavorite( QgsStyle::Symbol3DEntity );
919 
920  for ( auto &details : items )
921  {
922  QStringList symbolTags;
923  if ( !ignoreSourceTags )
924  {
925  symbolTags = src->tagsOfSymbol( details.entityType, details.name );
926  }
927 
928  bool addItemToFavorites = false;
929  if ( isImport )
930  {
931  symbolTags << importTags;
932  addItemToFavorites = addToFavorites;
933  }
934 
935  switch ( details.entityType )
936  {
938  {
939  std::unique_ptr< QgsSymbol > symbol( src->symbol( details.name ) );
940  if ( !symbol )
941  continue;
942 
943  const bool hasDuplicateName = dst->symbolNames().contains( details.name );
944  bool overwriteThis = false;
945  if ( isImport )
946  addItemToFavorites = favoriteSymbols.contains( details.name );
947 
948  if ( hasDuplicateName && prompt )
949  {
950  cursorOverride.reset();
951  int res = QMessageBox::warning( parentWidget, isImport ? tr( "Import Symbol" ) : tr( "Export Symbol" ),
952  tr( "A symbol with the name “%1” already exists.\nOverwrite?" )
953  .arg( details.name ),
954  QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No | QMessageBox::NoToAll | QMessageBox::Cancel );
955  cursorOverride = std::make_unique< QgsTemporaryCursorOverride >( Qt::WaitCursor );
956  switch ( res )
957  {
958  case QMessageBox::Cancel:
959  return count;
960 
961  case QMessageBox::No:
962  continue;
963 
964  case QMessageBox::Yes:
965  overwriteThis = true;
966  break;
967 
968  case QMessageBox::YesToAll:
969  prompt = false;
970  overwriteAll = true;
971  break;
972 
973  case QMessageBox::NoToAll:
974  prompt = false;
975  overwriteAll = false;
976  break;
977  }
978  }
979 
980  if ( !hasDuplicateName || overwriteAll || overwriteThis )
981  {
982  QgsSymbol *newSymbol = symbol.get();
983  dst->addSymbol( details.name, symbol.release() );
984  dst->saveSymbol( details.name, newSymbol, addItemToFavorites, symbolTags );
985  count++;
986  }
987  break;
988  }
989 
991  {
992  std::unique_ptr< QgsColorRamp > ramp( src->colorRamp( details.name ) );
993  if ( !ramp )
994  continue;
995 
996  const bool hasDuplicateName = dst->colorRampNames().contains( details.name );
997  bool overwriteThis = false;
998  if ( isImport )
999  addItemToFavorites = favoriteColorramps.contains( details.name );
1000 
1001  if ( hasDuplicateName && prompt )
1002  {
1003  cursorOverride.reset();
1004  int res = QMessageBox::warning( parentWidget, isImport ? tr( "Import Color Ramp" ) : tr( "Export Color Ramp" ),
1005  tr( "A color ramp with the name “%1” already exists.\nOverwrite?" )
1006  .arg( details.name ),
1007  QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No | QMessageBox::NoToAll | QMessageBox::Cancel );
1008  cursorOverride = std::make_unique< QgsTemporaryCursorOverride >( Qt::WaitCursor );
1009  switch ( res )
1010  {
1011  case QMessageBox::Cancel:
1012  return count;
1013 
1014  case QMessageBox::No:
1015  continue;
1016 
1017  case QMessageBox::Yes:
1018  overwriteThis = true;
1019  break;
1020 
1021  case QMessageBox::YesToAll:
1022  prompt = false;
1023  overwriteAll = true;
1024  break;
1025 
1026  case QMessageBox::NoToAll:
1027  prompt = false;
1028  overwriteAll = false;
1029  break;
1030  }
1031  }
1032 
1033  if ( !hasDuplicateName || overwriteAll || overwriteThis )
1034  {
1035  QgsColorRamp *newRamp = ramp.get();
1036  dst->addColorRamp( details.name, ramp.release() );
1037  dst->saveColorRamp( details.name, newRamp, addItemToFavorites, symbolTags );
1038  count++;
1039  }
1040  break;
1041  }
1042 
1044  {
1045  const QgsTextFormat format( src->textFormat( details.name ) );
1046 
1047  const bool hasDuplicateName = dst->textFormatNames().contains( details.name );
1048  bool overwriteThis = false;
1049  if ( isImport )
1050  addItemToFavorites = favoriteTextFormats.contains( details.name );
1051 
1052  if ( hasDuplicateName && prompt )
1053  {
1054  cursorOverride.reset();
1055  int res = QMessageBox::warning( parentWidget, isImport ? tr( "Import Text Format" ) : tr( "Export Text Format" ),
1056  tr( "A text format with the name “%1” already exists.\nOverwrite?" )
1057  .arg( details.name ),
1058  QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No | QMessageBox::NoToAll | QMessageBox::Cancel );
1059  cursorOverride = std::make_unique< QgsTemporaryCursorOverride >( Qt::WaitCursor );
1060  switch ( res )
1061  {
1062  case QMessageBox::Cancel:
1063  return count;
1064 
1065  case QMessageBox::No:
1066  continue;
1067 
1068  case QMessageBox::Yes:
1069  overwriteThis = true;
1070  break;
1071 
1072  case QMessageBox::YesToAll:
1073  prompt = false;
1074  overwriteAll = true;
1075  break;
1076 
1077  case QMessageBox::NoToAll:
1078  prompt = false;
1079  overwriteAll = false;
1080  break;
1081  }
1082  }
1083 
1084  if ( !hasDuplicateName || overwriteAll || overwriteThis )
1085  {
1086  dst->addTextFormat( details.name, format );
1087  dst->saveTextFormat( details.name, format, addItemToFavorites, symbolTags );
1088  count++;
1089  }
1090  break;
1091  }
1092 
1094  {
1095  const QgsPalLayerSettings settings( src->labelSettings( details.name ) );
1096 
1097  const bool hasDuplicateName = dst->labelSettingsNames().contains( details.name );
1098  bool overwriteThis = false;
1099  if ( isImport )
1100  addItemToFavorites = favoriteLabelSettings.contains( details.name );
1101 
1102  if ( hasDuplicateName && prompt )
1103  {
1104  cursorOverride.reset();
1105  int res = QMessageBox::warning( parentWidget, isImport ? tr( "Import Label Settings" ) : tr( "Export Label Settings" ),
1106  tr( "Label settings with the name “%1” already exist.\nOverwrite?" )
1107  .arg( details.name ),
1108  QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No | QMessageBox::NoToAll | QMessageBox::Cancel );
1109  cursorOverride = std::make_unique< QgsTemporaryCursorOverride >( Qt::WaitCursor );
1110  switch ( res )
1111  {
1112  case QMessageBox::Cancel:
1113  return count;
1114 
1115  case QMessageBox::No:
1116  continue;
1117 
1118  case QMessageBox::Yes:
1119  overwriteThis = true;
1120  break;
1121 
1122  case QMessageBox::YesToAll:
1123  prompt = false;
1124  overwriteAll = true;
1125  break;
1126 
1127  case QMessageBox::NoToAll:
1128  prompt = false;
1129  overwriteAll = false;
1130  break;
1131  }
1132  }
1133 
1134  if ( !hasDuplicateName || overwriteAll || overwriteThis )
1135  {
1136  dst->addLabelSettings( details.name, settings );
1137  dst->saveLabelSettings( details.name, settings, addItemToFavorites, symbolTags );
1138  count++;
1139  }
1140  break;
1141  }
1142 
1144  {
1145  const QgsLegendPatchShape shape( src->legendPatchShape( details.name ) );
1146 
1147  const bool hasDuplicateName = dst->legendPatchShapeNames().contains( details.name );
1148  bool overwriteThis = false;
1149  if ( isImport )
1150  addItemToFavorites = favoriteLegendPatchShapes.contains( details.name );
1151 
1152  if ( hasDuplicateName && prompt )
1153  {
1154  cursorOverride.reset();
1155  int res = QMessageBox::warning( parentWidget, isImport ? tr( "Import Legend Patch Shape" ) : tr( "Export Legend Patch Shape" ),
1156  tr( "Legend patch shape with the name “%1” already exist.\nOverwrite?" )
1157  .arg( details.name ),
1158  QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No | QMessageBox::NoToAll | QMessageBox::Cancel );
1159  cursorOverride = std::make_unique< QgsTemporaryCursorOverride >( Qt::WaitCursor );
1160  switch ( res )
1161  {
1162  case QMessageBox::Cancel:
1163  return count;
1164 
1165  case QMessageBox::No:
1166  continue;
1167 
1168  case QMessageBox::Yes:
1169  overwriteThis = true;
1170  break;
1171 
1172  case QMessageBox::YesToAll:
1173  prompt = false;
1174  overwriteAll = true;
1175  break;
1176 
1177  case QMessageBox::NoToAll:
1178  prompt = false;
1179  overwriteAll = false;
1180  break;
1181  }
1182  }
1183 
1184  if ( !hasDuplicateName || overwriteAll || overwriteThis )
1185  {
1186  dst->addLegendPatchShape( details.name, shape );
1187  dst->saveLegendPatchShape( details.name, shape, addItemToFavorites, symbolTags );
1188  count++;
1189  }
1190  break;
1191  }
1192 
1194  {
1195  std::unique_ptr< QgsAbstract3DSymbol > symbol( src->symbol3D( details.name ) );
1196  if ( !symbol )
1197  continue;
1198 
1199  const bool hasDuplicateName = dst->symbol3DNames().contains( details.name );
1200  bool overwriteThis = false;
1201  if ( isImport )
1202  addItemToFavorites = favorite3dSymbols.contains( details.name );
1203 
1204  if ( hasDuplicateName && prompt )
1205  {
1206  cursorOverride.reset();
1207  int res = QMessageBox::warning( parentWidget, isImport ? tr( "Import 3D Symbol" ) : tr( "Export 3D Symbol" ),
1208  tr( "A 3D symbol with the name “%1” already exists.\nOverwrite?" )
1209  .arg( details.name ),
1210  QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No | QMessageBox::NoToAll | QMessageBox::Cancel );
1211  cursorOverride = std::make_unique< QgsTemporaryCursorOverride >( Qt::WaitCursor );
1212  switch ( res )
1213  {
1214  case QMessageBox::Cancel:
1215  return count;
1216 
1217  case QMessageBox::No:
1218  continue;
1219 
1220  case QMessageBox::Yes:
1221  overwriteThis = true;
1222  break;
1223 
1224  case QMessageBox::YesToAll:
1225  prompt = false;
1226  overwriteAll = true;
1227  break;
1228 
1229  case QMessageBox::NoToAll:
1230  prompt = false;
1231  overwriteAll = false;
1232  break;
1233  }
1234  }
1235 
1236  if ( !hasDuplicateName || overwriteAll || overwriteThis )
1237  {
1238  QgsAbstract3DSymbol *newSymbol = symbol.get();
1239  dst->addSymbol3D( details.name, symbol.release() );
1240  dst->saveSymbol3D( details.name, newSymbol, addItemToFavorites, symbolTags );
1241  count++;
1242  }
1243  break;
1244  }
1245 
1246  case QgsStyle::TagEntity:
1248  break;
1249 
1250  }
1251  }
1252  return count;
1253 }
1254 
1255 bool QgsStyleManagerDialog::addTextFormat()
1256 {
1257  QgsTextFormat format;
1258  QgsTextFormatDialog formatDlg( format, nullptr, this );
1259  formatDlg.setWindowTitle( tr( "New Text Format" ) );
1260  if ( !formatDlg.exec() )
1261  return false;
1262  format = formatDlg.format();
1263 
1264  QgsStyleSaveDialog saveDlg( this, QgsStyle::TextFormatEntity );
1265  const QString defaultTag = groupTree->currentIndex().isValid() ? groupTree->currentIndex().data( GroupModelRoles::TagName ).toString() : QString();
1266  saveDlg.setDefaultTags( defaultTag );
1267  if ( !saveDlg.exec() )
1268  return false;
1269  QString name = saveDlg.name();
1270 
1271  // request valid/unique name
1272  bool nameInvalid = true;
1273  while ( nameInvalid )
1274  {
1275  // validate name
1276  if ( name.isEmpty() )
1277  {
1278  QMessageBox::warning( this, tr( "Save Text Format" ),
1279  tr( "Cannot save text format without name. Enter a name." ) );
1280  }
1281  else if ( mStyle->textFormatNames().contains( name ) )
1282  {
1283  int res = QMessageBox::warning( this, tr( "Save Text Format" ),
1284  tr( "Text format with name '%1' already exists. Overwrite?" )
1285  .arg( name ),
1286  QMessageBox::Yes | QMessageBox::No );
1287  if ( res == QMessageBox::Yes )
1288  {
1289  mStyle->removeTextFormat( name );
1290  nameInvalid = false;
1291  }
1292  }
1293  else
1294  {
1295  // valid name
1296  nameInvalid = false;
1297  }
1298  if ( nameInvalid )
1299  {
1300  bool ok;
1301  name = QInputDialog::getText( this, tr( "Text Format Name" ),
1302  tr( "Please enter a name for new text format:" ),
1303  QLineEdit::Normal, name, &ok );
1304  if ( !ok )
1305  {
1306  return false;
1307  }
1308  }
1309  }
1310 
1311  QStringList symbolTags = saveDlg.tags().split( ',' );
1312 
1313  // add new format to style and re-populate the list
1314  mStyle->addTextFormat( name, format );
1315  mStyle->saveTextFormat( name, format, saveDlg.isFavorite(), symbolTags );
1316 
1317  mModified = true;
1318  return true;
1319 }
1320 
1322 {
1323  groupChanged( groupTree->selectionModel()->currentIndex() );
1324 }
1325 
1326 void QgsStyleManagerDialog::populateSymbols( const QStringList &, bool )
1327 {
1328 }
1329 
1330 void QgsStyleManagerDialog::populateColorRamps( const QStringList &, bool )
1331 {
1332 }
1333 
1335 {
1336  switch ( tabItemType->currentIndex() )
1337  {
1338  case 1:
1339  return static_cast< int >( Qgis::SymbolType::Marker );
1340  case 2:
1341  return static_cast< int >( Qgis::SymbolType::Line );
1342  case 3:
1343  return static_cast< int >( Qgis::SymbolType::Fill );
1344  case 4:
1345  return 3;
1346  case 5:
1347  return 4;
1348  case 6:
1349  return 5;
1350  case 7:
1351  return 6;
1352  case 8:
1353  return 7;
1354  default:
1355  return 0;
1356  }
1357 }
1358 
1360 {
1361  QModelIndex index = listItems->selectionModel()->currentIndex();
1362  if ( !index.isValid() )
1363  return QString();
1364 
1365  return mModel->data( mModel->index( index.row(), QgsStyleModel::Name, index.parent() ), Qt::DisplayRole ).toString();
1366 }
1367 
1369 {
1370  bool changed = false;
1371  if ( currentItemType() < 3 )
1372  {
1373  changed = addSymbol();
1374  }
1375  else if ( currentItemType() == 3 )
1376  {
1377  changed = addColorRamp();
1378  }
1379  else if ( currentItemType() == 4 )
1380  {
1381  changed = addTextFormat();
1382  }
1383  else if ( currentItemType() == 5 )
1384  {
1385  // actually never hit, because we present a submenu when adding label settings
1386  // changed = addLabelSettings();
1387  }
1388  else if ( currentItemType() == 6 )
1389  {
1390  // actually never hit, because we present a submenu when adding legend patches
1391  // changed = addLegendPatchShape();
1392  }
1393  else if ( currentItemType() == 7 )
1394  {
1395  // actually never hit, because we present a submenu when adding 3d symbols
1396  // changed = addSymbol3D();
1397  }
1398  else
1399  {
1400  Q_ASSERT( false && "not implemented" );
1401  }
1402 
1403  if ( changed )
1404  {
1405  populateList();
1406  }
1407 }
1408 
1409 bool QgsStyleManagerDialog::addSymbol( int symbolType )
1410 {
1411  // create new symbol with current type
1412  QgsSymbol *symbol = nullptr;
1413  QString name = tr( "new symbol" );
1414  QString dialogTitle;
1415  switch ( symbolType == -1 ? currentItemType() : symbolType )
1416  {
1417  case static_cast< int >( Qgis::SymbolType::Marker ):
1418  symbol = new QgsMarkerSymbol();
1419  name = tr( "new marker" );
1420  dialogTitle = tr( "New Marker Symbol" );
1421  break;
1422  case static_cast< int>( Qgis::SymbolType::Line ):
1423  symbol = new QgsLineSymbol();
1424  name = tr( "new line" );
1425  dialogTitle = tr( "New Line Symbol" );
1426  break;
1427  case static_cast< int >( Qgis::SymbolType::Fill ):
1428  symbol = new QgsFillSymbol();
1429  name = tr( "new fill symbol" );
1430  dialogTitle = tr( "New Fill Symbol" );
1431  break;
1432  default:
1433  Q_ASSERT( false && "unknown symbol type" );
1434  return false;
1435  }
1436 
1437  // get symbol design
1438  // NOTE : Set the parent widget as "this" to notify the Symbol selector
1439  // that, it is being called by Style Manager, so recursive calling
1440  // of style manager and symbol selector can be arrested
1441  // See also: editSymbol()
1442  QgsSymbolSelectorDialog dlg( symbol, mStyle, nullptr, this );
1443  dlg.setWindowTitle( dialogTitle );
1444  if ( dlg.exec() == 0 )
1445  {
1446  delete symbol;
1447  return false;
1448  }
1449 
1450  QgsStyleSaveDialog saveDlg( this );
1451  const QString defaultTag = groupTree->currentIndex().isValid() ? groupTree->currentIndex().data( GroupModelRoles::TagName ).toString() : QString();
1452  saveDlg.setDefaultTags( defaultTag );
1453  if ( !saveDlg.exec() )
1454  {
1455  delete symbol;
1456  return false;
1457  }
1458 
1459  name = saveDlg.name();
1460 
1461  // request valid/unique name
1462  bool nameInvalid = true;
1463  while ( nameInvalid )
1464  {
1465  // validate name
1466  if ( name.isEmpty() )
1467  {
1468  QMessageBox::warning( this, tr( "Save Symbol" ),
1469  tr( "Cannot save symbol without name. Enter a name." ) );
1470  }
1471  else if ( mStyle->symbolNames().contains( name ) )
1472  {
1473  int res = QMessageBox::warning( this, tr( "Save Symbol" ),
1474  tr( "Symbol with name '%1' already exists. Overwrite?" )
1475  .arg( name ),
1476  QMessageBox::Yes | QMessageBox::No );
1477  if ( res == QMessageBox::Yes )
1478  {
1479  mStyle->removeSymbol( name );
1480  nameInvalid = false;
1481  }
1482  }
1483  else
1484  {
1485  // valid name
1486  nameInvalid = false;
1487  }
1488  if ( nameInvalid )
1489  {
1490  bool ok;
1491  name = QInputDialog::getText( this, tr( "Symbol Name" ),
1492  tr( "Please enter a name for new symbol:" ),
1493  QLineEdit::Normal, name, &ok );
1494  if ( !ok )
1495  {
1496  delete symbol;
1497  return false;
1498  }
1499  }
1500  }
1501 
1502  QStringList symbolTags = saveDlg.tags().split( ',' );
1503 
1504  // add new symbol to style and re-populate the list
1505  mStyle->addSymbol( name, symbol );
1506  mStyle->saveSymbol( name, symbol, saveDlg.isFavorite(), symbolTags );
1507 
1508  mModified = true;
1509  return true;
1510 }
1511 
1512 
1513 QString QgsStyleManagerDialog::addColorRampStatic( QWidget *parent, QgsStyle *style, const QString &type )
1514 {
1515  QString rampType = type;
1516 
1517  if ( rampType.isEmpty() )
1518  {
1519  // let the user choose the color ramp type if rampType is not given
1520  bool ok = true;
1521  const QList< QPair< QString, QString > > rampTypes = QgsColorRamp::rampTypes();
1522  QStringList rampTypeNames;
1523  rampTypeNames.reserve( rampTypes.size() );
1524  for ( const QPair< QString, QString > &type : rampTypes )
1525  rampTypeNames << type.second;
1526  const QString selectedRampTypeName = QInputDialog::getItem( parent, tr( "Color Ramp Type" ),
1527  tr( "Please select color ramp type:" ), rampTypeNames, 0, false, &ok );
1528  if ( !ok || selectedRampTypeName.isEmpty() )
1529  return QString();
1530 
1531  rampType = rampTypes.value( rampTypeNames.indexOf( selectedRampTypeName ) ).first;
1532  }
1533 
1534  QString name = tr( "new ramp" );
1535 
1536  std::unique_ptr< QgsColorRamp > ramp;
1537  if ( rampType == QgsGradientColorRamp::typeString() )
1538  {
1540  dlg.setWindowTitle( tr( "New Gradient Color Ramp" ) );
1541  if ( !dlg.exec() )
1542  {
1543  return QString();
1544  }
1545  ramp.reset( dlg.ramp().clone() );
1546  name = tr( "new gradient ramp" );
1547  }
1548  else if ( rampType == QgsLimitedRandomColorRamp::typeString() )
1549  {
1551  dlg.setWindowTitle( tr( "New Random Color Ramp" ) );
1552  if ( !dlg.exec() )
1553  {
1554  return QString();
1555  }
1556  ramp.reset( dlg.ramp().clone() );
1557  name = tr( "new random ramp" );
1558  }
1559  else if ( rampType == QgsColorBrewerColorRamp::typeString() )
1560  {
1562  dlg.setWindowTitle( tr( "New ColorBrewer Ramp" ) );
1563  if ( !dlg.exec() )
1564  {
1565  return QString();
1566  }
1567  ramp.reset( dlg.ramp().clone() );
1568  name = dlg.ramp().schemeName() + QString::number( dlg.ramp().colors() );
1569  }
1570  else if ( rampType == QgsPresetSchemeColorRamp::typeString() )
1571  {
1573  dlg.setWindowTitle( tr( "New Preset Color Ramp" ) );
1574  if ( !dlg.exec() )
1575  {
1576  return QString();
1577  }
1578  ramp.reset( dlg.ramp().clone() );
1579  name = tr( "new preset ramp" );
1580  }
1581  else if ( rampType == QgsCptCityColorRamp::typeString() )
1582  {
1583  QgsCptCityColorRampDialog dlg( QgsCptCityColorRamp( QString(), QString() ), parent );
1584  dlg.setWindowTitle( tr( "New cpt-city Color Ramp" ) );
1585  if ( !dlg.exec() )
1586  {
1587  return QString();
1588  }
1589  // name = dlg.selectedName();
1590  name = QFileInfo( dlg.ramp().schemeName() ).baseName() + dlg.ramp().variantName();
1591  if ( dlg.saveAsGradientRamp() )
1592  {
1593  ramp.reset( dlg.ramp().cloneGradientRamp() );
1594  }
1595  else
1596  {
1597  ramp.reset( dlg.ramp().clone() );
1598  }
1599  }
1600  else
1601  {
1602  // Q_ASSERT( 0 && "invalid ramp type" );
1603  // bailing out is rather harsh!
1604  QgsDebugMsg( QStringLiteral( "invalid ramp type %1" ).arg( rampType ) );
1605  return QString();
1606  }
1607 
1608  QgsStyleSaveDialog saveDlg( parent, QgsStyle::ColorrampEntity );
1609  if ( !saveDlg.exec() )
1610  {
1611  return QString();
1612  }
1613 
1614  name = saveDlg.name();
1615 
1616  // get valid/unique name
1617  bool nameInvalid = true;
1618  while ( nameInvalid )
1619  {
1620  // validate name
1621  if ( name.isEmpty() )
1622  {
1623  QMessageBox::warning( parent, tr( "Save Color Ramp" ),
1624  tr( "Cannot save color ramp without name. Enter a name." ) );
1625  }
1626  else if ( style->colorRampNames().contains( name ) )
1627  {
1628  int res = QMessageBox::warning( parent, tr( "Save Color Ramp" ),
1629  tr( "Color ramp with name '%1' already exists. Overwrite?" )
1630  .arg( name ),
1631  QMessageBox::Yes | QMessageBox::No );
1632  if ( res == QMessageBox::Yes )
1633  {
1634  nameInvalid = false;
1635  }
1636  }
1637  else
1638  {
1639  // valid name
1640  nameInvalid = false;
1641  }
1642  if ( nameInvalid )
1643  {
1644  bool ok;
1645  name = QInputDialog::getText( parent, tr( "Color Ramp Name" ),
1646  tr( "Please enter a name for new color ramp:" ),
1647  QLineEdit::Normal, name, &ok );
1648  if ( !ok )
1649  {
1650  return QString();
1651  }
1652  }
1653  }
1654 
1655  QStringList colorRampTags = saveDlg.tags().split( ',' );
1656  QgsColorRamp *r = ramp.release();
1657 
1658  // add new symbol to style and re-populate the list
1659  style->addColorRamp( name, r );
1660  style->saveColorRamp( name, r, saveDlg.isFavorite(), colorRampTags );
1661 
1662  return name;
1663 }
1664 
1666 {
1667  mFavoritesGroupVisible = show;
1668  populateGroups();
1669 }
1670 
1672 {
1673  mSmartGroupVisible = show;
1674  populateGroups();
1675 }
1676 
1677 void QgsStyleManagerDialog::setBaseStyleName( const QString &name )
1678 {
1679  mBaseName = name;
1680 }
1681 
1683 {
1684  raise();
1685  setWindowState( windowState() & ~Qt::WindowMinimized );
1686  activateWindow();
1687 }
1688 
1689 bool QgsStyleManagerDialog::addColorRamp( const QString &type )
1690 {
1691  // pass the action text, which is the color ramp type
1692  QString rampName = addColorRampStatic( this, mStyle, type );
1693  if ( !rampName.isEmpty() )
1694  {
1695  mModified = true;
1696  populateList();
1697  return true;
1698  }
1699 
1700  return false;
1701 }
1702 
1704 {
1705  if ( selectedItemType() < 3 )
1706  {
1707  editSymbol();
1708  }
1709  else if ( selectedItemType() == 3 )
1710  {
1711  editColorRamp();
1712  }
1713  else if ( selectedItemType() == 4 )
1714  {
1715  editTextFormat();
1716  }
1717  else if ( selectedItemType() == 5 )
1718  {
1719  editLabelSettings();
1720  }
1721  else if ( selectedItemType() == 6 )
1722  {
1723  editLegendPatchShape();
1724  }
1725  else if ( selectedItemType() == 7 )
1726  {
1727  editSymbol3D();
1728  }
1729  else
1730  {
1731  Q_ASSERT( false && "not implemented" );
1732  }
1733 }
1734 
1736 {
1737  QString symbolName = currentItemName();
1738  if ( symbolName.isEmpty() )
1739  return false;
1740 
1741  std::unique_ptr< QgsSymbol > symbol( mStyle->symbol( symbolName ) );
1742 
1743  // let the user edit the symbol and update list when done
1744  QgsSymbolSelectorDialog dlg( symbol.get(), mStyle, nullptr, this );
1745  dlg.setWindowTitle( symbolName );
1746  if ( isReadOnly() )
1747  dlg.buttonBox()->button( QDialogButtonBox::Ok )->setEnabled( false );
1748 
1749  if ( !dlg.exec() )
1750  return false;
1751 
1752  // by adding symbol to style with the same name the old effectively gets overwritten
1753  mStyle->addSymbol( symbolName, symbol.release(), true );
1754  mModified = true;
1755  return true;
1756 }
1757 
1759 {
1760  QString name = currentItemName();
1761  if ( name.isEmpty() )
1762  return false;
1763 
1764  std::unique_ptr< QgsColorRamp > ramp( mStyle->colorRamp( name ) );
1765 
1766  if ( ramp->type() == QgsGradientColorRamp::typeString() )
1767  {
1768  QgsGradientColorRamp *gradRamp = static_cast<QgsGradientColorRamp *>( ramp.get() );
1769  QgsGradientColorRampDialog dlg( *gradRamp, this );
1770  dlg.setWindowTitle( name );
1771  if ( isReadOnly() )
1772  dlg.buttonBox()->button( QDialogButtonBox::Ok )->setEnabled( false );
1773 
1774  if ( !dlg.exec() )
1775  {
1776  return false;
1777  }
1778  ramp.reset( dlg.ramp().clone() );
1779  }
1780  else if ( ramp->type() == QgsLimitedRandomColorRamp::typeString() )
1781  {
1782  QgsLimitedRandomColorRamp *randRamp = static_cast<QgsLimitedRandomColorRamp *>( ramp.get() );
1783  QgsLimitedRandomColorRampDialog dlg( *randRamp, this );
1784  dlg.setWindowTitle( name );
1785  if ( isReadOnly() )
1786  dlg.buttonBox()->button( QDialogButtonBox::Ok )->setEnabled( false );
1787 
1788  if ( !dlg.exec() )
1789  {
1790  return false;
1791  }
1792  ramp.reset( dlg.ramp().clone() );
1793  }
1794  else if ( ramp->type() == QgsColorBrewerColorRamp::typeString() )
1795  {
1796  QgsColorBrewerColorRamp *brewerRamp = static_cast<QgsColorBrewerColorRamp *>( ramp.get() );
1797  QgsColorBrewerColorRampDialog dlg( *brewerRamp, this );
1798  dlg.setWindowTitle( name );
1799  if ( isReadOnly() )
1800  dlg.buttonBox()->button( QDialogButtonBox::Ok )->setEnabled( false );
1801 
1802  if ( !dlg.exec() )
1803  {
1804  return false;
1805  }
1806  ramp.reset( dlg.ramp().clone() );
1807  }
1808  else if ( ramp->type() == QgsPresetSchemeColorRamp::typeString() )
1809  {
1810  QgsPresetSchemeColorRamp *presetRamp = static_cast<QgsPresetSchemeColorRamp *>( ramp.get() );
1811  QgsPresetColorRampDialog dlg( *presetRamp, this );
1812  dlg.setWindowTitle( name );
1813  if ( isReadOnly() )
1814  dlg.buttonBox()->button( QDialogButtonBox::Ok )->setEnabled( false );
1815 
1816  if ( !dlg.exec() )
1817  {
1818  return false;
1819  }
1820  ramp.reset( dlg.ramp().clone() );
1821  }
1822  else if ( ramp->type() == QgsCptCityColorRamp::typeString() )
1823  {
1824  QgsCptCityColorRamp *cptCityRamp = static_cast<QgsCptCityColorRamp *>( ramp.get() );
1825  QgsCptCityColorRampDialog dlg( *cptCityRamp, this );
1826  dlg.setWindowTitle( name );
1827  if ( isReadOnly() )
1828  dlg.buttonBox()->button( QDialogButtonBox::Ok )->setEnabled( false );
1829 
1830  if ( !dlg.exec() )
1831  {
1832  return false;
1833  }
1834  if ( dlg.saveAsGradientRamp() )
1835  {
1836  ramp.reset( dlg.ramp().cloneGradientRamp() );
1837  }
1838  else
1839  {
1840  ramp.reset( dlg.ramp().clone() );
1841  }
1842  }
1843  else
1844  {
1845  Q_ASSERT( false && "invalid ramp type" );
1846  }
1847 
1848  mStyle->addColorRamp( name, ramp.release(), true );
1849  mModified = true;
1850  return true;
1851 }
1852 
1853 bool QgsStyleManagerDialog::editTextFormat()
1854 {
1855  const QString formatName = currentItemName();
1856  if ( formatName.isEmpty() )
1857  return false;
1858 
1859  QgsTextFormat format = mStyle->textFormat( formatName );
1860 
1861  // let the user edit the format and update list when done
1862  QgsTextFormatDialog dlg( format, nullptr, this );
1863  dlg.setWindowTitle( formatName );
1864  if ( isReadOnly() )
1865  dlg.buttonBox()->button( QDialogButtonBox::Ok )->setEnabled( false );
1866 
1867  if ( !dlg.exec() )
1868  return false;
1869 
1870  // by adding format to style with the same name the old effectively gets overwritten
1871  mStyle->addTextFormat( formatName, dlg.format(), true );
1872  mModified = true;
1873  return true;
1874 }
1875 
1876 bool QgsStyleManagerDialog::addLabelSettings( QgsWkbTypes::GeometryType type )
1877 {
1878  QgsPalLayerSettings settings;
1879  QgsLabelSettingsDialog settingsDlg( settings, nullptr, nullptr, this, type );
1880  settingsDlg.setWindowTitle( tr( "New Label Settings" ) );
1881  if ( isReadOnly() )
1882  settingsDlg.buttonBox()->button( QDialogButtonBox::Ok )->setEnabled( false );
1883 
1884  if ( !settingsDlg.exec() )
1885  return false;
1886 
1887  settings = settingsDlg.settings();
1888  settings.layerType = type;
1889 
1890  QgsStyleSaveDialog saveDlg( this, QgsStyle::LabelSettingsEntity );
1891  const QString defaultTag = groupTree->currentIndex().isValid() ? groupTree->currentIndex().data( GroupModelRoles::TagName ).toString() : QString();
1892  saveDlg.setDefaultTags( defaultTag );
1893  if ( !saveDlg.exec() )
1894  return false;
1895  QString name = saveDlg.name();
1896 
1897  // request valid/unique name
1898  bool nameInvalid = true;
1899  while ( nameInvalid )
1900  {
1901  // validate name
1902  if ( name.isEmpty() )
1903  {
1904  QMessageBox::warning( this, tr( "Save Label Settings" ),
1905  tr( "Cannot save label settings without a name. Enter a name." ) );
1906  }
1907  else if ( mStyle->labelSettingsNames().contains( name ) )
1908  {
1909  int res = QMessageBox::warning( this, tr( "Save Label Settings" ),
1910  tr( "Label settings with the name '%1' already exist. Overwrite?" )
1911  .arg( name ),
1912  QMessageBox::Yes | QMessageBox::No );
1913  if ( res == QMessageBox::Yes )
1914  {
1915  mStyle->removeLabelSettings( name );
1916  nameInvalid = false;
1917  }
1918  }
1919  else
1920  {
1921  // valid name
1922  nameInvalid = false;
1923  }
1924  if ( nameInvalid )
1925  {
1926  bool ok;
1927  name = QInputDialog::getText( this, tr( "Label Settings Name" ),
1928  tr( "Please enter a name for the new label settings:" ),
1929  QLineEdit::Normal, name, &ok );
1930  if ( !ok )
1931  {
1932  return false;
1933  }
1934  }
1935  }
1936 
1937  QStringList symbolTags = saveDlg.tags().split( ',' );
1938 
1939  // add new format to style and re-populate the list
1940  mStyle->addLabelSettings( name, settings );
1941  mStyle->saveLabelSettings( name, settings, saveDlg.isFavorite(), symbolTags );
1942 
1943  mModified = true;
1944  return true;
1945 }
1946 
1947 bool QgsStyleManagerDialog::editLabelSettings()
1948 {
1949  const QString formatName = currentItemName();
1950  if ( formatName.isEmpty() )
1951  return false;
1952 
1953  QgsPalLayerSettings settings = mStyle->labelSettings( formatName );
1954  QgsWkbTypes::GeometryType geomType = settings.layerType;
1955 
1956  // let the user edit the settings and update list when done
1957  QgsLabelSettingsDialog dlg( settings, nullptr, nullptr, this, geomType );
1958  dlg.setWindowTitle( formatName );
1959  if ( !dlg.exec() )
1960  return false;
1961 
1962  settings = dlg.settings();
1963  settings.layerType = geomType;
1964 
1965  // by adding format to style with the same name the old effectively gets overwritten
1966  mStyle->addLabelSettings( formatName, settings, true );
1967  mModified = true;
1968  return true;
1969 }
1970 
1971 bool QgsStyleManagerDialog::addLegendPatchShape( Qgis::SymbolType type )
1972 {
1973  QgsLegendPatchShape shape = mStyle->defaultPatch( type, QSizeF( 10, 5 ) );
1974  QgsLegendPatchShapeDialog dialog( shape, this );
1975  dialog.setWindowTitle( tr( "New Legend Patch Shape" ) );
1976  if ( isReadOnly() )
1977  dialog.buttonBox()->button( QDialogButtonBox::Ok )->setEnabled( false );
1978 
1979  if ( !dialog.exec() )
1980  return false;
1981 
1982  shape = dialog.shape();
1983 
1984  QgsStyleSaveDialog saveDlg( this, QgsStyle::LegendPatchShapeEntity );
1985  const QString defaultTag = groupTree->currentIndex().isValid() ? groupTree->currentIndex().data( GroupModelRoles::TagName ).toString() : QString();
1986  saveDlg.setDefaultTags( defaultTag );
1987  if ( !saveDlg.exec() )
1988  return false;
1989  QString name = saveDlg.name();
1990 
1991  // request valid/unique name
1992  bool nameInvalid = true;
1993  while ( nameInvalid )
1994  {
1995  // validate name
1996  if ( name.isEmpty() )
1997  {
1998  QMessageBox::warning( this, tr( "Save Legend Patch Shape" ),
1999  tr( "Cannot save legend patch shapes without a name. Enter a name." ) );
2000  }
2001  else if ( mStyle->legendPatchShapeNames().contains( name ) )
2002  {
2003  int res = QMessageBox::warning( this, tr( "Save Legend Patch Shape" ),
2004  tr( "A legend patch shape with the name '%1' already exists. Overwrite?" )
2005  .arg( name ),
2006  QMessageBox::Yes | QMessageBox::No );
2007  if ( res == QMessageBox::Yes )
2008  {
2010  nameInvalid = false;
2011  }
2012  }
2013  else
2014  {
2015  // valid name
2016  nameInvalid = false;
2017  }
2018  if ( nameInvalid )
2019  {
2020  bool ok;
2021  name = QInputDialog::getText( this, tr( "Legend Patch Shape Name" ),
2022  tr( "Please enter a name for the new legend patch shape:" ),
2023  QLineEdit::Normal, name, &ok );
2024  if ( !ok )
2025  {
2026  return false;
2027  }
2028  }
2029  }
2030 
2031  QStringList symbolTags = saveDlg.tags().split( ',' );
2032 
2033  // add new shape to style and re-populate the list
2034  mStyle->addLegendPatchShape( name, shape );
2035  mStyle->saveLegendPatchShape( name, shape, saveDlg.isFavorite(), symbolTags );
2036 
2037  mModified = true;
2038  return true;
2039 }
2040 
2041 bool QgsStyleManagerDialog::editLegendPatchShape()
2042 {
2043  const QString shapeName = currentItemName();
2044  if ( shapeName.isEmpty() )
2045  return false;
2046 
2047  QgsLegendPatchShape shape = mStyle->legendPatchShape( shapeName );
2048  if ( shape.isNull() )
2049  return false;
2050 
2051  // let the user edit the shape and update list when done
2052  QgsLegendPatchShapeDialog dlg( shape, this );
2053  dlg.setWindowTitle( shapeName );
2054  if ( !dlg.exec() )
2055  return false;
2056 
2057  shape = dlg.shape();
2058 
2059  // by adding shape to style with the same name the old effectively gets overwritten
2060  mStyle->addLegendPatchShape( shapeName, shape, true );
2061  mModified = true;
2062  return true;
2063 }
2064 
2065 bool QgsStyleManagerDialog::addSymbol3D( const QString &type )
2066 {
2067  std::unique_ptr< QgsAbstract3DSymbol > symbol( QgsApplication::symbol3DRegistry()->createSymbol( type ) );
2068  if ( !symbol )
2069  return false;
2070 
2071  Qgs3DSymbolDialog dialog( symbol.get(), this );
2072  dialog.setWindowTitle( tr( "New 3D Symbol" ) );
2073  if ( isReadOnly() )
2074  dialog.buttonBox()->button( QDialogButtonBox::Ok )->setEnabled( false );
2075 
2076  if ( !dialog.exec() )
2077  return false;
2078 
2079  symbol.reset( dialog.symbol() );
2080  if ( !symbol )
2081  return false;
2082 
2083  QgsStyleSaveDialog saveDlg( this, QgsStyle::Symbol3DEntity );
2084  const QString defaultTag = groupTree->currentIndex().isValid() ? groupTree->currentIndex().data( GroupModelRoles::TagName ).toString() : QString();
2085  saveDlg.setDefaultTags( defaultTag );
2086  if ( !saveDlg.exec() )
2087  return false;
2088  QString name = saveDlg.name();
2089 
2090  // request valid/unique name
2091  bool nameInvalid = true;
2092  while ( nameInvalid )
2093  {
2094  // validate name
2095  if ( name.isEmpty() )
2096  {
2097  QMessageBox::warning( this, tr( "Save 3D Symbol" ),
2098  tr( "Cannot save 3D symbols without a name. Enter a name." ) );
2099  }
2100  else if ( mStyle->symbol3DNames().contains( name ) )
2101  {
2102  int res = QMessageBox::warning( this, tr( "Save 3D Symbol" ),
2103  tr( "A 3D symbol with the name '%1' already exists. Overwrite?" )
2104  .arg( name ),
2105  QMessageBox::Yes | QMessageBox::No );
2106  if ( res == QMessageBox::Yes )
2107  {
2109  nameInvalid = false;
2110  }
2111  }
2112  else
2113  {
2114  // valid name
2115  nameInvalid = false;
2116  }
2117  if ( nameInvalid )
2118  {
2119  bool ok;
2120  name = QInputDialog::getText( this, tr( "3D Symbol Name" ),
2121  tr( "Please enter a name for the new 3D symbol:" ),
2122  QLineEdit::Normal, name, &ok );
2123  if ( !ok )
2124  {
2125  return false;
2126  }
2127  }
2128  }
2129 
2130  QStringList symbolTags = saveDlg.tags().split( ',' );
2131 
2132  // add new shape to style and re-populate the list
2133  QgsAbstract3DSymbol *newSymbol = symbol.get();
2134  mStyle->addSymbol3D( name, symbol.release() );
2135  mStyle->saveSymbol3D( name, newSymbol, saveDlg.isFavorite(), symbolTags );
2136 
2137  mModified = true;
2138  return true;
2139 }
2140 
2141 bool QgsStyleManagerDialog::editSymbol3D()
2142 {
2143  const QString symbolName = currentItemName();
2144  if ( symbolName.isEmpty() )
2145  return false;
2146 
2147  std::unique_ptr< QgsAbstract3DSymbol > symbol( mStyle->symbol3D( symbolName ) );
2148  if ( !symbol )
2149  return false;
2150 
2151  // let the user edit the symbol and update list when done
2152  Qgs3DSymbolDialog dlg( symbol.get(), this );
2153  dlg.setWindowTitle( symbolName );
2154  if ( !dlg.exec() )
2155  return false;
2156 
2157  symbol.reset( dlg.symbol() );
2158  if ( !symbol )
2159  return false;
2160 
2161  // by adding symbol to style with the same name the old effectively gets overwritten
2162  mStyle->addSymbol3D( symbolName, symbol.release(), true );
2163  mModified = true;
2164  return true;
2165 }
2166 
2167 void QgsStyleManagerDialog::addStyleDatabase( bool createNew )
2168 {
2170  if ( initialFolder.isEmpty() )
2171  initialFolder = QDir::homePath();
2172 
2173  QString databasePath = createNew
2174  ? QFileDialog::getSaveFileName(
2175  this,
2176  tr( "Create Style Database" ),
2177  initialFolder,
2178  tr( "Style databases" ) + " (*.db)" )
2179  : QFileDialog::getOpenFileName(
2180  this,
2181  tr( "Add Style Database" ),
2182  initialFolder,
2183  tr( "Style databases" ) + " (*.db *.xml)" );
2184  if ( ! databasePath.isEmpty() )
2185  {
2186  QgsStyleManagerDialog::settingLastStyleDatabaseFolder.setValue( QFileInfo( databasePath ).path() );
2187 
2188  if ( createNew )
2189  {
2190  databasePath = QgsFileUtils::ensureFileNameHasExtension( databasePath, { QStringLiteral( "db" )} );
2191  if ( QFile::exists( databasePath ) )
2192  {
2193  QFile::remove( databasePath );
2194  }
2195  QgsStyle s;
2196  if ( !s.createDatabase( databasePath ) )
2197  {
2198  QMessageBox::warning( this, tr( "Create Style Database" ), tr( "The style database could not be created" ) );
2199  return;
2200  }
2201  }
2202 
2204  setCurrentStyle( QgsProject::instance()->styleSettings()->styleAtPath( databasePath ) );
2205  }
2206 }
2207 
2209 {
2210  const QList< ItemDetails > items = selectedItems();
2211 
2212  if ( allTypesSelected() )
2213  {
2214  if ( QMessageBox::Yes != QMessageBox::question( this, tr( "Remove Items" ),
2215  QString( tr( "Do you really want to remove %n item(s)?", nullptr, items.count() ) ),
2216  QMessageBox::Yes,
2217  QMessageBox::No ) )
2218  return;
2219  }
2220  else
2221  {
2222  if ( currentItemType() < 3 )
2223  {
2224  if ( QMessageBox::Yes != QMessageBox::question( this, tr( "Remove Symbol" ),
2225  QString( tr( "Do you really want to remove %n symbol(s)?", nullptr, items.count() ) ),
2226  QMessageBox::Yes,
2227  QMessageBox::No ) )
2228  return;
2229  }
2230  else if ( currentItemType() == 3 )
2231  {
2232  if ( QMessageBox::Yes != QMessageBox::question( this, tr( "Remove Color Ramp" ),
2233  QString( tr( "Do you really want to remove %n ramp(s)?", nullptr, items.count() ) ),
2234  QMessageBox::Yes,
2235  QMessageBox::No ) )
2236  return;
2237  }
2238  else if ( currentItemType() == 4 )
2239  {
2240  if ( QMessageBox::Yes != QMessageBox::question( this, tr( "Remove Text Formats" ),
2241  QString( tr( "Do you really want to remove %n text format(s)?", nullptr, items.count() ) ),
2242  QMessageBox::Yes,
2243  QMessageBox::No ) )
2244  return;
2245  }
2246  else if ( currentItemType() == 5 )
2247  {
2248  if ( QMessageBox::Yes != QMessageBox::question( this, tr( "Remove Label Settings" ),
2249  QString( tr( "Do you really want to remove %n label setting(s)?", nullptr, items.count() ) ),
2250  QMessageBox::Yes,
2251  QMessageBox::No ) )
2252  return;
2253  }
2254  else if ( currentItemType() == 6 )
2255  {
2256  if ( QMessageBox::Yes != QMessageBox::question( this, tr( "Remove Legend Patch Shapes" ),
2257  QString( tr( "Do you really want to remove %n legend patch shape(s)?", nullptr, items.count() ) ),
2258  QMessageBox::Yes,
2259  QMessageBox::No ) )
2260  return;
2261  }
2262  else if ( currentItemType() == 7 )
2263  {
2264  if ( QMessageBox::Yes != QMessageBox::question( this, tr( "Remove 3D Symbols" ),
2265  QString( tr( "Do you really want to remove %n 3D symbol(s)?", nullptr, items.count() ) ),
2266  QMessageBox::Yes,
2267  QMessageBox::No ) )
2268  return;
2269  }
2270  }
2271 
2272  QgsTemporaryCursorOverride override( Qt::WaitCursor );
2273 
2274  for ( const ItemDetails &details : items )
2275  {
2276  if ( details.name.isEmpty() )
2277  continue;
2278 
2279  mStyle->removeEntityByName( details.entityType, details.name );
2280  }
2281 
2282  mModified = true;
2283 }
2284 
2286 {
2287  return false;
2288 }
2289 
2291 {
2292  return false;
2293 }
2294 
2295 void QgsStyleManagerDialog::itemChanged( QStandardItem * )
2296 {
2297 }
2298 
2300 {
2301  QString dir = QFileDialog::getExistingDirectory( this, tr( "Export Selected Symbols as PNG" ),
2302  QDir::home().absolutePath(),
2303  QFileDialog::DontResolveSymlinks );
2304  exportSelectedItemsImages( dir, QStringLiteral( "png" ), QSize( 32, 32 ) );
2305 }
2306 
2308 {
2309  QString dir = QFileDialog::getExistingDirectory( this, tr( "Export Selected Symbols as SVG" ),
2310  QDir::home().absolutePath(),
2311  QFileDialog::DontResolveSymlinks );
2312  exportSelectedItemsImages( dir, QStringLiteral( "svg" ), QSize( 32, 32 ) );
2313 }
2314 
2315 
2316 void QgsStyleManagerDialog::exportSelectedItemsImages( const QString &dir, const QString &format, QSize size )
2317 {
2318  if ( dir.isEmpty() )
2319  return;
2320 
2321  const QList< ItemDetails > items = selectedItems();
2322  for ( const ItemDetails &details : items )
2323  {
2324  if ( details.entityType != QgsStyle::SymbolEntity )
2325  continue;
2326 
2327  QString path = dir + '/' + details.name + '.' + format;
2328  std::unique_ptr< QgsSymbol > sym( mStyle->symbol( details.name ) );
2329  if ( sym )
2330  sym->exportImage( path, format, size );
2331  }
2332 }
2333 
2335 {
2337  dlg.exec();
2338 }
2339 
2341 {
2343  dlg.exec();
2344  populateList();
2345  populateGroups();
2346 }
2347 
2348 void QgsStyleManagerDialog::setBold( QStandardItem *item )
2349 {
2350  QFont font = item->font();
2351  font.setBold( true );
2352  item->setFont( font );
2353 }
2354 
2356 {
2357  if ( mBlockGroupUpdates )
2358  return;
2359 
2360  QStandardItemModel *model = qobject_cast<QStandardItemModel *>( groupTree->model() );
2361  model->clear();
2362 
2363  const bool readOnly = isReadOnly();
2364 
2365  if ( mFavoritesGroupVisible )
2366  {
2367  QStandardItem *favoriteSymbols = new QStandardItem( tr( "Favorites" ) );
2368  favoriteSymbols->setData( "favorite" );
2369  favoriteSymbols->setEditable( false );
2370  setBold( favoriteSymbols );
2371  model->appendRow( favoriteSymbols );
2372  }
2373 
2374  QStandardItem *allSymbols = new QStandardItem( tr( "All" ) );
2375  allSymbols->setData( "all" );
2376  allSymbols->setEditable( false );
2377  setBold( allSymbols );
2378  model->appendRow( allSymbols );
2379 
2380  QStandardItem *taggroup = new QStandardItem( QString() ); //require empty name to get first order groups
2381  taggroup->setData( "tags" );
2382  taggroup->setEditable( false );
2383  QStringList tags = mStyle->tags();
2384  tags.sort();
2385  for ( const QString &tag : std::as_const( tags ) )
2386  {
2387  QStandardItem *item = new QStandardItem( tag );
2388  item->setData( mStyle->tagId( tag ) );
2389  item->setData( tag, GroupModelRoles::TagName );
2390  item->setEditable( !readOnly );
2391  taggroup->appendRow( item );
2392  }
2393  taggroup->setText( tr( "Tags" ) );//set title later
2394  setBold( taggroup );
2395  model->appendRow( taggroup );
2396 
2397  if ( mSmartGroupVisible )
2398  {
2399  QStandardItem *smart = new QStandardItem( tr( "Smart Groups" ) );
2400  smart->setData( "smartgroups" );
2401  smart->setEditable( false );
2402  setBold( smart );
2403  QgsSymbolGroupMap sgMap = mStyle->smartgroupsListMap();
2404  QgsSymbolGroupMap::const_iterator i = sgMap.constBegin();
2405  while ( i != sgMap.constEnd() )
2406  {
2407  QStandardItem *item = new QStandardItem( i.value() );
2408  item->setData( i.key() );
2409  item->setEditable( !readOnly );
2410  smart->appendRow( item );
2411  ++i;
2412  }
2413  model->appendRow( smart );
2414  }
2415 
2416  // expand things in the group tree
2417  int rows = model->rowCount( model->indexFromItem( model->invisibleRootItem() ) );
2418  for ( int i = 0; i < rows; i++ )
2419  {
2420  groupTree->setExpanded( model->indexFromItem( model->item( i ) ), true );
2421  }
2422 }
2423 
2424 void QgsStyleManagerDialog::groupChanged( const QModelIndex &index )
2425 {
2426  QStringList groupSymbols;
2427 
2428  const QString category = index.data( Qt::UserRole + 1 ).toString();
2429  sPreviousTag = category;
2430 
2431  const bool readOnly = isReadOnly();
2432 
2433  if ( mGroupingMode && mModel )
2434  {
2435  mModel->setTagId( -1 );
2436  mModel->setSmartGroupId( -1 );
2437  mModel->setFavoritesOnly( false );
2438  mModel->setCheckTag( index.data( Qt::DisplayRole ).toString() );
2439  }
2440  else if ( category == QLatin1String( "all" ) || category == QLatin1String( "tags" ) || category == QLatin1String( "smartgroups" ) )
2441  {
2442  enableGroupInputs( false );
2443  if ( category == QLatin1String( "tags" ) )
2444  {
2445  actnAddTag->setEnabled( !readOnly );
2446  actnAddSmartgroup->setEnabled( false );
2447  }
2448  else if ( category == QLatin1String( "smartgroups" ) )
2449  {
2450  actnAddTag->setEnabled( false );
2451  actnAddSmartgroup->setEnabled( !readOnly );
2452  }
2453 
2454  if ( mModel )
2455  {
2456  mModel->setTagId( -1 );
2457  mModel->setSmartGroupId( -1 );
2458  mModel->setFavoritesOnly( false );
2459  }
2460  }
2461  else if ( category == QLatin1String( "favorite" ) )
2462  {
2463  enableGroupInputs( false );
2464  mModel->setTagId( -1 );
2465  mModel->setSmartGroupId( -1 );
2466  mModel->setFavoritesOnly( true );
2467  }
2468  else if ( index.parent().data( Qt::UserRole + 1 ) == "smartgroups" )
2469  {
2470  actnRemoveGroup->setEnabled( !readOnly );
2471  btnManageGroups->setEnabled( !readOnly );
2472  const int groupId = index.data( Qt::UserRole + 1 ).toInt();
2473  if ( mModel )
2474  {
2475  mModel->setTagId( -1 );
2476  mModel->setSmartGroupId( groupId );
2477  mModel->setFavoritesOnly( false );
2478  }
2479  }
2480  else // tags
2481  {
2482  enableGroupInputs( true );
2483  int tagId = index.data( Qt::UserRole + 1 ).toInt();
2484  if ( mModel )
2485  {
2486  mModel->setTagId( tagId );
2487  mModel->setSmartGroupId( -1 );
2488  mModel->setFavoritesOnly( false );
2489  }
2490  }
2491 
2492  actnEditSmartGroup->setVisible( false );
2493  actnAddTag->setVisible( false );
2494  actnAddSmartgroup->setVisible( false );
2495  actnRemoveGroup->setVisible( false );
2496  actnTagSymbols->setVisible( false );
2497  actnFinishTagging->setVisible( false );
2498 
2499  if ( index.parent().isValid() )
2500  {
2501  if ( index.parent().data( Qt::UserRole + 1 ).toString() == QLatin1String( "smartgroups" ) )
2502  {
2503  actnEditSmartGroup->setVisible( !mGroupingMode && !readOnly );
2504  }
2505  else if ( index.parent().data( Qt::UserRole + 1 ).toString() == QLatin1String( "tags" ) )
2506  {
2507  actnAddTag->setVisible( !mGroupingMode && !readOnly );
2508  actnTagSymbols->setVisible( !mGroupingMode && !readOnly );
2509  actnFinishTagging->setVisible( mGroupingMode && !readOnly );
2510  }
2511  actnRemoveGroup->setVisible( !readOnly );
2512  }
2513  else if ( index.data( Qt::UserRole + 1 ) == "smartgroups" )
2514  {
2515  actnAddSmartgroup->setVisible( !mGroupingMode && !readOnly );
2516  }
2517  else if ( index.data( Qt::UserRole + 1 ) == "tags" )
2518  {
2519  actnAddTag->setVisible( !mGroupingMode && !readOnly );
2520  }
2521 }
2522 
2524 {
2525  if ( isReadOnly() )
2526  return 0;
2527 
2528  QStandardItemModel *model = qobject_cast<QStandardItemModel *>( groupTree->model() );
2529  QModelIndex index;
2530  for ( int i = 0; i < groupTree->model()->rowCount(); i++ )
2531  {
2532  index = groupTree->model()->index( i, 0 );
2533  QString data = index.data( Qt::UserRole + 1 ).toString();
2534  if ( data == QLatin1String( "tags" ) )
2535  {
2536  break;
2537  }
2538  }
2539 
2540  QString itemName;
2541  int id;
2542  bool ok;
2543  itemName = QInputDialog::getText( this, tr( "Add Tag" ),
2544  tr( "Please enter name for the new tag:" ), QLineEdit::Normal, tr( "New tag" ), &ok ).trimmed();
2545  if ( !ok || itemName.isEmpty() )
2546  return 0;
2547 
2548  int check = mStyle->tagId( itemName );
2549  if ( check > 0 )
2550  {
2551  mMessageBar->pushCritical( tr( "Add Tag" ), tr( "The tag “%1” already exists." ).arg( itemName ) );
2552  return 0;
2553  }
2554 
2555  // block the auto-repopulation of groups when the style emits groupsModified
2556  // instead, we manually update the model items for better state retention
2557  mBlockGroupUpdates++;
2558  id = mStyle->addTag( itemName );
2559  mBlockGroupUpdates--;
2560 
2561  if ( !id )
2562  {
2563  mMessageBar->pushCritical( tr( "Add Tag" ), tr( "New tag could not be created — There was a problem with the symbol database." ) );
2564  return 0;
2565  }
2566 
2567  QStandardItem *parentItem = model->itemFromIndex( index );
2568  QStandardItem *childItem = new QStandardItem( itemName );
2569  childItem->setData( id );
2570  childItem->setData( itemName, GroupModelRoles::TagName );
2571  parentItem->appendRow( childItem );
2572 
2573  return id;
2574 }
2575 
2577 {
2578  if ( isReadOnly() )
2579  return 0;
2580 
2581  QStandardItemModel *model = qobject_cast<QStandardItemModel *>( groupTree->model() );
2582  QModelIndex index;
2583  for ( int i = 0; i < groupTree->model()->rowCount(); i++ )
2584  {
2585  index = groupTree->model()->index( i, 0 );
2586  QString data = index.data( Qt::UserRole + 1 ).toString();
2587  if ( data == QLatin1String( "smartgroups" ) )
2588  {
2589  break;
2590  }
2591  }
2592 
2593  QString itemName;
2594  int id;
2595  QgsSmartGroupEditorDialog dlg( mStyle, this );
2596  if ( dlg.exec() == QDialog::Rejected )
2597  return 0;
2598 
2599  // block the auto-repopulation of groups when the style emits groupsModified
2600  // instead, we manually update the model items for better state retention
2601  mBlockGroupUpdates++;
2602  id = mStyle->addSmartgroup( dlg.smartgroupName(), dlg.conditionOperator(), dlg.conditionMap() );
2603  mBlockGroupUpdates--;
2604 
2605  if ( !id )
2606  return 0;
2607  itemName = dlg.smartgroupName();
2608 
2609  QStandardItem *parentItem = model->itemFromIndex( index );
2610  QStandardItem *childItem = new QStandardItem( itemName );
2611  childItem->setData( id );
2612  parentItem->appendRow( childItem );
2613 
2614  return id;
2615 }
2616 
2618 {
2619  if ( isReadOnly() )
2620  return;
2621 
2622  QStandardItemModel *model = qobject_cast<QStandardItemModel *>( groupTree->model() );
2623  QModelIndex index = groupTree->currentIndex();
2624 
2625  // do not allow removal of system-defined groupings
2626  QString data = index.data( Qt::UserRole + 1 ).toString();
2627  if ( data == QLatin1String( "all" ) || data == QLatin1String( "favorite" ) || data == QLatin1String( "tags" ) || index.data() == "smartgroups" )
2628  {
2629  // should never appear -- blocked by GUI
2630  int err = QMessageBox::critical( this, tr( "Remove Group" ),
2631  tr( "Invalid selection. Cannot delete system defined categories.\n"
2632  "Kindly select a group or smart group you might want to delete." ) );
2633  if ( err )
2634  return;
2635  }
2636 
2637  QStandardItem *parentItem = model->itemFromIndex( index.parent() );
2638 
2639  // block the auto-repopulation of groups when the style emits groupsModified
2640  // instead, we manually update the model items for better state retention
2641  mBlockGroupUpdates++;
2642 
2643  if ( parentItem->data( Qt::UserRole + 1 ).toString() == QLatin1String( "smartgroups" ) )
2644  {
2645  mStyle->remove( QgsStyle::SmartgroupEntity, index.data( Qt::UserRole + 1 ).toInt() );
2646  }
2647  else
2648  {
2649  mStyle->remove( QgsStyle::TagEntity, index.data( Qt::UserRole + 1 ).toInt() );
2650  }
2651 
2652  mBlockGroupUpdates--;
2653  parentItem->removeRow( index.row() );
2654 }
2655 
2656 void QgsStyleManagerDialog::groupRenamed( QStandardItem *item )
2657 {
2658  if ( isReadOnly() )
2659  return;
2660 
2661  QgsDebugMsg( QStringLiteral( "Symbol group edited: data=%1 text=%2" ).arg( item->data( Qt::UserRole + 1 ).toString(), item->text() ) );
2662  int id = item->data( Qt::UserRole + 1 ).toInt();
2663  QString name = item->text();
2664  mBlockGroupUpdates++;
2665  if ( item->parent()->data( Qt::UserRole + 1 ) == "smartgroups" )
2666  {
2667  mStyle->rename( QgsStyle::SmartgroupEntity, id, name );
2668  }
2669  else
2670  {
2671  mStyle->rename( QgsStyle::TagEntity, id, name );
2672  }
2673  mBlockGroupUpdates--;
2674 }
2675 
2677 {
2678  if ( isReadOnly() )
2679  return;
2680 
2681  QStandardItemModel *treeModel = qobject_cast<QStandardItemModel *>( groupTree->model() );
2682 
2683  if ( mGroupingMode )
2684  {
2685  mGroupingMode = false;
2686  mModel->setCheckable( false );
2687  actnTagSymbols->setVisible( true );
2688  actnFinishTagging->setVisible( false );
2689  // disconnect slot which handles regrouping
2690 
2691  // disable all items except groups in groupTree
2693  groupChanged( groupTree->currentIndex() );
2694 
2695  // Finally: Reconnect all Symbol editing functionalities
2696  connect( treeModel, &QStandardItemModel::itemChanged,
2698 
2699  // Reset the selection mode
2700  listItems->setSelectionMode( QAbstractItemView::ExtendedSelection );
2701  mSymbolTreeView->setSelectionMode( QAbstractItemView::ExtendedSelection );
2702  }
2703  else
2704  {
2705  bool validGroup = false;
2706  // determine whether it is a valid group
2707  QModelIndex present = groupTree->currentIndex();
2708  while ( present.parent().isValid() )
2709  {
2710  if ( present.parent().data() == "Tags" )
2711  {
2712  validGroup = true;
2713  break;
2714  }
2715  present = present.parent();
2716  }
2717  if ( !validGroup )
2718  return;
2719 
2720  mGroupingMode = true;
2721  // Change visibility of actions
2722  actnTagSymbols->setVisible( false );
2723  actnFinishTagging->setVisible( true );
2724  // Remove all Symbol editing functionalities
2725  disconnect( treeModel, &QStandardItemModel::itemChanged,
2727 
2728  // disable all items except groups in groupTree
2729  enableItemsForGroupingMode( false );
2730  groupChanged( groupTree->currentIndex() );
2731  btnManageGroups->setEnabled( true );
2732 
2733  mModel->setCheckable( true );
2734 
2735  // No selection should be possible
2736  listItems->setSelectionMode( QAbstractItemView::NoSelection );
2737  mSymbolTreeView->setSelectionMode( QAbstractItemView::NoSelection );
2738  }
2739 }
2740 
2741 void QgsStyleManagerDialog::regrouped( QStandardItem * )
2742 {
2743 }
2744 
2745 void QgsStyleManagerDialog::setSymbolsChecked( const QStringList & )
2746 {
2747 }
2748 
2749 void QgsStyleManagerDialog::filterSymbols( const QString &qword )
2750 {
2751  mModel->setFilterString( qword );
2752 }
2753 
2754 void QgsStyleManagerDialog::symbolSelected( const QModelIndex &index )
2755 {
2756  actnEditItem->setEnabled( index.isValid() && !mGroupingMode && !isReadOnly() );
2757 }
2758 
2759 void QgsStyleManagerDialog::selectedSymbolsChanged( const QItemSelection &selected, const QItemSelection &deselected )
2760 {
2761  Q_UNUSED( selected )
2762  Q_UNUSED( deselected )
2763  const bool nothingSelected = listItems->selectionModel()->selectedIndexes().empty();
2764  const bool readOnly = isReadOnly();
2765  actnRemoveItem->setDisabled( nothingSelected || readOnly );
2766  actnAddFavorite->setDisabled( nothingSelected || readOnly );
2767  actnRemoveFavorite->setDisabled( nothingSelected || readOnly );
2768  mGroupListMenu->setDisabled( nothingSelected || readOnly );
2769  actnDetag->setDisabled( nothingSelected || readOnly );
2770  actnExportAsPNG->setDisabled( nothingSelected );
2771  actnExportAsSVG->setDisabled( nothingSelected );
2772  if ( mActionCopyToDefault )
2773  mActionCopyToDefault->setDisabled( nothingSelected );
2774  mCopyToDefaultButton->setDisabled( nothingSelected );
2775  actnEditItem->setDisabled( nothingSelected || readOnly );
2776 }
2777 
2779 {
2780  const bool readOnly = isReadOnly();
2781  groupTree->setEnabled( enable );
2782  btnAddTag->setEnabled( enable && !readOnly );
2783  btnAddSmartgroup->setEnabled( enable && !readOnly );
2784  actnAddTag->setEnabled( enable && !readOnly );
2785  actnAddSmartgroup->setEnabled( enable && !readOnly );
2786  actnRemoveGroup->setEnabled( enable && !readOnly );
2787  btnManageGroups->setEnabled( !readOnly && ( enable || mGroupingMode ) ); // always enabled in grouping mode, as it is the only way to leave grouping mode
2788  searchBox->setEnabled( enable );
2789 }
2790 
2792 {
2793  const bool readOnly = isReadOnly();
2794  actnRemoveGroup->setEnabled( enable && !readOnly );
2795  btnManageGroups->setEnabled( !readOnly && ( enable || mGroupingMode ) ); // always enabled in grouping mode, as it is the only way to leave grouping mode
2796 }
2797 
2799 {
2800  QStandardItemModel *treeModel = qobject_cast<QStandardItemModel *>( groupTree->model() );
2801  for ( int i = 0; i < treeModel->rowCount(); i++ )
2802  {
2803  treeModel->item( i )->setEnabled( enable );
2804 
2805  if ( treeModel->item( i )->data() == "smartgroups" )
2806  {
2807  for ( int j = 0; j < treeModel->item( i )->rowCount(); j++ )
2808  {
2809  treeModel->item( i )->child( j )->setEnabled( enable );
2810  }
2811  }
2812  }
2813 
2814  // The buttons
2815  // NOTE: if you ever change the layout name in the .ui file edit here too
2816  for ( int i = 0; i < symbolBtnsLayout->count(); i++ )
2817  {
2818  QWidget *w = symbolBtnsLayout->itemAt( i )->widget();
2819  if ( w )
2820  w->setEnabled( enable );
2821  }
2822 
2823  // The actions
2824  actnRemoveItem->setEnabled( enable );
2825  actnEditItem->setEnabled( enable );
2826  mActionCopyItem->setEnabled( enable );
2827  mActionPasteItem->setEnabled( enable );
2828 }
2829 
2831 {
2832  QPoint globalPos = groupTree->viewport()->mapToGlobal( point );
2833 
2834  QModelIndex index = groupTree->indexAt( point );
2835  if ( index.isValid() && !mGroupingMode )
2836  mGroupTreeContextMenu->popup( globalPos );
2837 }
2838 
2840 {
2841  QPoint globalPos = mSymbolViewStackedWidget->currentIndex() == 0
2842  ? listItems->viewport()->mapToGlobal( point )
2843  : mSymbolTreeView->viewport()->mapToGlobal( point );
2844 
2845  // Clear all actions and create new actions for every group
2846  mGroupListMenu->clear();
2847 
2848  const QModelIndexList indices = listItems->selectionModel()->selectedRows();
2849 
2850  if ( !isReadOnly() )
2851  {
2852  const QStringList currentTags = indices.count() == 1 ? indices.at( 0 ).data( QgsStyleModel::TagRole ).toStringList() : QStringList();
2853  QAction *a = nullptr;
2854  QStringList tags = mStyle->tags();
2855  tags.sort();
2856  for ( const QString &tag : std::as_const( tags ) )
2857  {
2858  a = new QAction( tag, mGroupListMenu );
2859  a->setData( tag );
2860  if ( indices.count() == 1 )
2861  {
2862  a->setCheckable( true );
2863  a->setChecked( currentTags.contains( tag ) );
2864  }
2865  connect( a, &QAction::triggered, this, [ = ]( bool ) { tagSelectedSymbols(); }
2866  );
2867  mGroupListMenu->addAction( a );
2868  }
2869 
2870  if ( tags.count() > 0 )
2871  {
2872  mGroupListMenu->addSeparator();
2873  }
2874  a = new QAction( tr( "Create New Tag…" ), mGroupListMenu );
2875  connect( a, &QAction::triggered, this, [ = ]( bool ) { tagSelectedSymbols( true ); }
2876  );
2877  mGroupListMenu->addAction( a );
2878  }
2879 
2880  const QList< ItemDetails > items = selectedItems();
2881  mActionCopyItem->setEnabled( !items.isEmpty() && ( items.at( 0 ).entityType != QgsStyle::ColorrampEntity ) );
2882 
2883  bool enablePaste = false;
2884  std::unique_ptr< QgsSymbol > tempSymbol( QgsSymbolLayerUtils::symbolFromMimeData( QApplication::clipboard()->mimeData() ) );
2885  if ( tempSymbol )
2886  enablePaste = true;
2887  else
2888  {
2889  ( void )QgsTextFormat::fromMimeData( QApplication::clipboard()->mimeData(), &enablePaste );
2890  }
2891  mActionPasteItem->setEnabled( enablePaste );
2892 
2893  mGroupMenu->popup( globalPos );
2894 }
2895 
2897 {
2898  if ( isReadOnly() )
2899  return;
2900 
2901  const QList< ItemDetails > items = selectedItems();
2902  for ( const ItemDetails &details : items )
2903  {
2904  mStyle->addFavorite( details.entityType, details.name );
2905  }
2906 }
2907 
2909 {
2910  if ( isReadOnly() )
2911  return;
2912 
2913  const QList< ItemDetails > items = selectedItems();
2914  for ( const ItemDetails &details : items )
2915  {
2916  mStyle->removeFavorite( details.entityType, details.name );
2917  }
2918 }
2919 
2921 {
2922  QAction *selectedItem = qobject_cast<QAction *>( sender() );
2923  if ( selectedItem )
2924  {
2925  const QList< ItemDetails > items = selectedItems();
2926  QString tag;
2927  if ( newTag )
2928  {
2929  int id = addTag();
2930  if ( id == 0 )
2931  {
2932  return;
2933  }
2934 
2935  tag = mStyle->tag( id );
2936  }
2937  else
2938  {
2939  tag = selectedItem->data().toString();
2940  }
2941 
2942  for ( const ItemDetails &details : items )
2943  {
2944  mStyle->tagSymbol( details.entityType, details.name, QStringList( tag ) );
2945  }
2946  }
2947 }
2948 
2950 {
2951  if ( isReadOnly() )
2952  return;
2953 
2954  QAction *selectedItem = qobject_cast<QAction *>( sender() );
2955 
2956  if ( selectedItem )
2957  {
2958  const QList< ItemDetails > items = selectedItems();
2959  for ( const ItemDetails &details : items )
2960  {
2961  mStyle->detagSymbol( details.entityType, details.name );
2962  }
2963  }
2964 }
2965 
2967 {
2968  if ( isReadOnly() )
2969  return;
2970 
2971  QStandardItemModel *treeModel = qobject_cast<QStandardItemModel *>( groupTree->model() );
2972 
2973  // determine whether it is a valid group
2974  QModelIndex present = groupTree->currentIndex();
2975  if ( present.parent().data( Qt::UserRole + 1 ) != "smartgroups" )
2976  {
2977  // should never appear - blocked by GUI logic
2978  QMessageBox::critical( this, tr( "Edit Smart Group" ),
2979  tr( "You have not selected a Smart Group. Kindly select a Smart Group to edit." ) );
2980  return;
2981  }
2982  QStandardItem *item = treeModel->itemFromIndex( present );
2983 
2984  QgsSmartGroupEditorDialog dlg( mStyle, this );
2985  QgsSmartConditionMap map = mStyle->smartgroup( present.data( Qt::UserRole + 1 ).toInt() );
2986  dlg.setSmartgroupName( item->text() );
2987  dlg.setOperator( mStyle->smartgroupOperator( item->data().toInt() ) );
2988  dlg.setConditionMap( map );
2989 
2990  if ( dlg.exec() == QDialog::Rejected )
2991  return;
2992 
2993  mBlockGroupUpdates++;
2994  mStyle->remove( QgsStyle::SmartgroupEntity, item->data().toInt() );
2995  int id = mStyle->addSmartgroup( dlg.smartgroupName(), dlg.conditionOperator(), dlg.conditionMap() );
2996  mBlockGroupUpdates--;
2997  if ( !id )
2998  {
2999  mMessageBar->pushCritical( tr( "Edit Smart Group" ), tr( "There was an error while editing the smart group." ) );
3000  return;
3001  }
3002  item->setText( dlg.smartgroupName() );
3003  item->setData( id );
3004 
3005  groupChanged( present );
3006 }
3007 
3009 {
3010  reject();
3011 }
3012 
3014 {
3015  QgsHelp::openHelp( QStringLiteral( "style_library/style_manager.html" ) );
3016 }
3017 
QgsSymbolSelectorDialog
Definition: qgssymbolselectordialog.h:276
QgsPresetColorRampDialog::buttonBox
QDialogButtonBox * buttonBox() const
Returns a reference to the dialog's button box.
Definition: qgspresetcolorrampdialog.cpp:127
QgsStyle::saveTextFormat
bool saveTextFormat(const QString &name, const QgsTextFormat &format, bool favorite, const QStringList &tags)
Adds a text format to the database.
Definition: qgsstyle.cpp:941
QgsColorRamp
Abstract base class for color ramps.
Definition: qgscolorramp.h:29
QgsProjectStyleDatabaseModel::indexFromStyle
QModelIndex indexFromStyle(QgsStyle *style) const
Returns the model index corresponding to a style.
Definition: qgsprojectstylesettings.cpp:544
QgsStyleManagerDialog::currentItemName
QString currentItemName()
Definition: qgsstylemanagerdialog.cpp:1359
QgsPresetSchemeColorRamp::clone
QgsPresetSchemeColorRamp * clone() const override
Creates a clone of the color ramp.
Definition: qgscolorrampimpl.cpp:1231
QgsStyleManagerDialog::QgsStyleManagerDialog
QgsStyleManagerDialog(QgsStyle *style, QWidget *parent=nullptr, Qt::WindowFlags flags=Qt::WindowFlags(), bool readOnly=false)
Constructor for QgsStyleManagerDialog, with the specified parent widget and window flags.
Definition: qgsstylemanagerdialog.cpp:176
QgsColorBrewerColorRampDialog::ramp
QgsColorBrewerColorRamp ramp
Definition: qgscolorbrewercolorrampdialog.h:89
QgsSymbolSelectorDialog::buttonBox
QDialogButtonBox * buttonBox() const
Returns a reference to the dialog's button box.
Definition: qgssymbolselectordialog.cpp:936
QgsPresetColorRampDialog
A dialog which allows users to modify the properties of a QgsPresetSchemeColorRamp.
Definition: qgspresetcolorrampdialog.h:86
QgsStyle::ColorrampEntity
@ ColorrampEntity
Color ramps.
Definition: qgsstyle.h:182
QgsGradientColorRamp
Gradient color ramp, which smoothly interpolates between two colors and also supports optional extra ...
Definition: qgscolorrampimpl.h:136
QgsColorBrewerColorRamp::clone
QgsColorBrewerColorRamp * clone() const override
Creates a clone of the color ramp.
Definition: qgscolorrampimpl.cpp:896
QgsStyle::tagSymbol
bool tagSymbol(StyleEntity type, const QString &symbol, const QStringList &tags)
Tags the symbol with the tags in the list.
Definition: qgsstyle.cpp:1755
QgsStyleModel
A QAbstractItemModel subclass for showing symbol and color ramp entities contained within a QgsStyle ...
Definition: qgsstylemodel.h:107
qgsprojectstylesettings.h
Qgis::SymbolType::Fill
@ Fill
Fill symbol.
Qgis::SymbolType::Line
@ Line
Line symbol.
QgsSettings::value
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
Definition: qgssettings.cpp:161
QgsStyleManagerDialog::itemChanged
Q_DECL_DEPRECATED void itemChanged(QStandardItem *item)
Definition: qgsstylemanagerdialog.cpp:2295
QgsColorRamp::rampTypes
static QList< QPair< QString, QString > > rampTypes()
Returns a list of available ramp types, where the first value in each item is the QgsColorRamp::type(...
Definition: qgscolorramp.cpp:21
QgsLimitedRandomColorRampDialog::ramp
QgsLimitedRandomColorRamp ramp
Definition: qgslimitedrandomcolorrampdialog.h:101
QgsStyle::removeEntityByName
bool removeEntityByName(StyleEntity type, const QString &name)
Removes the entry of the specified type with matching name from the database.
Definition: qgsstyle.cpp:1502
QgsIconUtils::iconPolygon
static QIcon iconPolygon()
Returns an icon representing polygon geometries.
Definition: qgsiconutils.cpp:54
QgsProjectStyleDatabaseModel
List model representing the style databases associated with a QgsProject.
Definition: qgsprojectstylesettings.h:297
QgsStyle::createDatabase
bool createDatabase(const QString &filename)
Creates an on-disk database.
Definition: qgsstyle.cpp:516
QgsCptCityColorRampDialog::saveAsGradientRamp
bool saveAsGradientRamp() const
Returns true if the ramp should be converted to a QgsGradientColorRamp.
Definition: qgscptcitycolorrampdialog.cpp:501
QgsStyle::textFormat
QgsTextFormat textFormat(const QString &name) const
Returns the text format with the specified name.
Definition: qgsstyle.cpp:2120
QgsPalLayerSettings
Contains settings for how a map layer will be labeled.
Definition: qgspallabeling.h:86
qgsstylemanagerdialog.h
QgsStyle::symbolsOfFavorite
QStringList symbolsOfFavorite(StyleEntity type) const
Returns the symbol names which are flagged as favorite.
Definition: qgsstyle.cpp:1301
QgsSymbolLayerUtils::symbolFromMimeData
static QgsSymbol * symbolFromMimeData(const QMimeData *data)
Attempts to parse mime data as a symbol.
Definition: qgssymbollayerutils.cpp:3305
QgsStyleManagerDialog::removeColorRamp
Q_DECL_DEPRECATED bool removeColorRamp()
Definition: qgsstylemanagerdialog.cpp:2290
qgsgui.h
QgsStyle::labelSettingsNames
QStringList labelSettingsNames() const
Returns a list of names of label settings in the style.
Definition: qgsstyle.cpp:2194
QgsPresetSchemeColorRamp
A scheme based color ramp consisting of a list of predefined colors.
Definition: qgscolorrampimpl.h:543
QgsLegendPatchShapeDialog
A dialog for configuring a custom legend patch shape.
Definition: qgslegendpatchshapewidget.h:79
QgsStyleManagerDialog::populateSymbols
Q_DECL_DEPRECATED void populateSymbols(const QStringList &symbolNames, bool checkable=false)
Populates the list view with symbols of the current type with the given names.
Definition: qgsstylemanagerdialog.cpp:1326
qgssymbollayerutils.h
QgsStyleManagerDialog::enableItemsForGroupingMode
void enableItemsForGroupingMode(bool)
Enables or disables the groupTree items for grouping mode.
Definition: qgsstylemanagerdialog.cpp:2798
QgsGradientColorRampDialog
A dialog which allows users to modify the properties of a QgsGradientColorRamp.
Definition: qgsgradientcolorrampdialog.h:38
QgsStyleManagerDialog::exportSelectedItemsImages
void exportSelectedItemsImages(const QString &dir, const QString &format, QSize size)
Triggers the dialog to export selected items as images of the specified format and size.
Definition: qgsstylemanagerdialog.cpp:2316
QgsApplication::symbol3DRegistry
static Qgs3DSymbolRegistry * symbol3DRegistry()
Returns registry of available 3D symbols.
Definition: qgsapplication.cpp:2490
QgsStyleManagerDialog::settingLastStyleDatabaseFolder
static const QgsSettingsEntryString settingLastStyleDatabaseFolder
Last used folder for generic style database actions.
Definition: qgsstylemanagerdialog.h:81
QgsCptCityColorRampDialog::ramp
QgsCptCityColorRamp ramp
Definition: qgscptcitycolorrampdialog.h:45
QgsGradientColorRamp::clone
QgsGradientColorRamp * clone() const override
Creates a clone of the color ramp.
Definition: qgscolorrampimpl.cpp:415
QgsTextFormatDialog
A simple dialog for customizing text formatting settings.
Definition: qgstextformatwidget.h:333
QgsStyleManagerDialog::addColorRamp
bool addColorRamp(const QString &type=QString())
Triggers adding a new color ramp.
Definition: qgsstylemanagerdialog.cpp:1689
QgsIconUtils::iconLine
static QIcon iconLine()
Returns an icon representing line geometries.
Definition: qgsiconutils.cpp:49
QgsStyle::addFavorite
bool addFavorite(StyleEntity type, const QString &name)
Adds the specified symbol to favorites.
Definition: qgsstyle.cpp:1626
QgsProject::instance
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:480
QgsStyleManagerDialog::groupRenamed
void groupRenamed(QStandardItem *item)
Triggered when a group item is renamed.
Definition: qgsstylemanagerdialog.cpp:2656
QgsStyleManagerDialog::regrouped
Q_DECL_DEPRECATED void regrouped(QStandardItem *)
Definition: qgsstylemanagerdialog.cpp:2741
QgsStyleManagerDialog::populateColorRamps
Q_DECL_DEPRECATED void populateColorRamps(const QStringList &colorRamps, bool checkable=false)
Populates the list view with color ramps of the current type with the given names.
Definition: qgsstylemanagerdialog.cpp:1330
QgsSettings
This class is a composition of two QSettings instances:
Definition: qgssettings.h:61
QgsCptCityColorRamp::variantName
QString variantName() const
Definition: qgscolorrampimpl.h:763
QgsStyle::addSymbol3D
bool addSymbol3D(const QString &name, QgsAbstract3DSymbol *symbol, bool update=false)
Adds a 3d symbol with the specified name to the style.
Definition: qgsstyle.cpp:400
QgsStyleManagerDialog::activate
void activate()
Raises, unminimizes and activates this window.
Definition: qgsstylemanagerdialog.cpp:1682
QgsStyleManagerDialog::editSymbol
bool editSymbol()
Definition: qgsstylemanagerdialog.cpp:1735
QgsSymbol
Abstract base class for all rendered symbols.
Definition: qgssymbol.h:92
QgsStyle::LegendPatchShapeEntity
@ LegendPatchShapeEntity
Legend patch shape (since QGIS 3.14)
Definition: qgsstyle.h:186
QgsDebugMsg
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
QgsProject::styleSettings
const QgsProjectStyleSettings * styleSettings() const
Returns the project's style settings, which contains settings and properties relating to how a QgsPro...
Definition: qgsproject.cpp:3501
QgsApplication::iconPath
static QString iconPath(const QString &iconFile)
Returns path to the desired icon file.
Definition: qgsapplication.cpp:682
QgsStyle::saveColorRamp
bool saveColorRamp(const QString &name, QgsColorRamp *ramp, bool favorite, const QStringList &tags)
Adds the colorramp to the database.
Definition: qgsstyle.cpp:421
QgsStyleManagerDialog::setBaseStyleName
void setBaseStyleName(const QString &name)
Sets the base name for the style, which is used by the dialog to reflect the original style/XML file ...
Definition: qgsstylemanagerdialog.cpp:1677
QgsStyleManagerDialog::addColorRampStatic
static QString addColorRampStatic(QWidget *parent, QgsStyle *style, const QString &RampType=QString())
Opens the add color ramp dialog, returning the new color ramp's name if the ramp has been added.
Definition: qgsstylemanagerdialog.cpp:1513
QgsStyleManagerDialog::removeItem
void removeItem()
Removes the current selected item.
Definition: qgsstylemanagerdialog.cpp:2208
qgsabstract3dsymbol.h
QgsColorBrewerColorRamp::typeString
static QString typeString()
Returns the string identifier for QgsColorBrewerColorRamp.
Definition: qgscolorrampimpl.h:645
qgs3dsymbolregistry.h
QgsLimitedRandomColorRamp
Constrained random color ramp, which returns random colors based on preset parameters.
Definition: qgscolorrampimpl.h:340
QgsStyleManagerDialog::removeFavoriteSelectedSymbols
void removeFavoriteSelectedSymbols()
Remove selected symbols from favorites.
Definition: qgsstylemanagerdialog.cpp:2908
qgsstylesavedialog.h
QgsWkbTypes::PolygonGeometry
@ PolygonGeometry
Definition: qgswkbtypes.h:144
QgsColorBrewerColorRamp
Color ramp utilising "Color Brewer" preset color schemes.
Definition: qgscolorrampimpl.h:615
QgsStyle::symbol
QgsSymbol * symbol(const QString &name)
Returns a NEW copy of symbol.
Definition: qgsstyle.cpp:291
TagName
@ TagName
Tag name.
Definition: qgsstyle.h:100
QgsCptCityColorRamp::cloneGradientRamp
QgsGradientColorRamp * cloneGradientRamp() const
Definition: qgscolorrampimpl.cpp:993
QgsLegendPatchShape
Represents a patch shape for use in map legends.
Definition: qgslegendpatchshape.h:33
QgsStyle::SymbolEntity
@ SymbolEntity
Symbols.
Definition: qgsstyle.h:180
QgsStyleManagerDialog::groupChanged
void groupChanged(const QModelIndex &)
Triggered when the current group (or tag) is changed.
Definition: qgsstylemanagerdialog.cpp:2424
QgsStyle::symbol3DNames
QStringList symbol3DNames() const
Returns a list of names of 3d symbols in the style.
Definition: qgsstyle.cpp:1296
QgsCptCityColorRampDialog::buttonBox
QDialogButtonBox * buttonBox() const
Returns a reference to the dialog's button box.
Definition: qgscptcitycolorrampdialog.cpp:508
QgsStyle::addColorRamp
bool addColorRamp(const QString &name, QgsColorRamp *colorRamp, bool update=false)
Adds a color ramp to the style.
Definition: qgsstyle.cpp:313
QgsStyle::TagEntity
@ TagEntity
Tags.
Definition: qgsstyle.h:181
QgsGuiUtils::iconSize
QSize iconSize(bool dockableToolbar)
Returns the user-preferred size of a window's toolbar icons.
Definition: qgsguiutils.cpp:264
QgsLimitedRandomColorRampDialog::buttonBox
QDialogButtonBox * buttonBox() const
Returns a reference to the dialog's button box.
Definition: qgslimitedrandomcolorrampdialog.cpp:145
QgsColorBrewerColorRampDialog::buttonBox
QDialogButtonBox * buttonBox() const
Returns a reference to the dialog's button box.
Definition: qgscolorbrewercolorrampdialog.cpp:142
QgsStyle::LabelSettingsEntity
@ LabelSettingsEntity
Label settings.
Definition: qgsstyle.h:185
QgsStyle::defaultStyle
static QgsStyle * defaultStyle()
Returns default application-wide style.
Definition: qgsstyle.cpp:145
QgsStyleManagerDialog::removeSymbol
Q_DECL_DEPRECATED bool removeSymbol()
Definition: qgsstylemanagerdialog.cpp:2285
QgsSymbolLayerUtils::symbolToMimeData
static QMimeData * symbolToMimeData(const QgsSymbol *symbol)
Creates new mime data from a symbol.
Definition: qgssymbollayerutils.cpp:3287
qgsapplication.h
QgsStyle::symbol3D
QgsAbstract3DSymbol * symbol3D(const QString &name) const
Returns a new copy of the 3D symbol with the specified name.
Definition: qgsstyle.cpp:2163
QgsCptCityColorRamp::typeString
static QString typeString()
Returns the string identifier for QgsCptCityColorRamp.
Definition: qgscolorrampimpl.h:750
QgsSmartGroupEditorDialog::setSmartgroupName
void setSmartgroupName(const QString &)
sets the smart group Name
Definition: qgssmartgroupeditordialog.cpp:196
QgsStyleModel::TypeRole
@ TypeRole
Style entity type, see QgsStyle::StyleEntity.
Definition: qgsstylemodel.h:123
QgsGradientColorRamp::typeString
static QString typeString()
Returns the string identifier for QgsGradientColorRamp.
Definition: qgscolorrampimpl.h:165
QgsStyleManagerDialog::exportItems
void exportItems()
Triggers the dialog to export items.
Definition: qgsstylemanagerdialog.cpp:2334
QgsStyle::detagSymbol
bool detagSymbol(StyleEntity type, const QString &symbol, const QStringList &tags)
Detags the symbol with the given list.
Definition: qgsstyle.cpp:1818
QgsGui::enableAutoGeometryRestore
static void enableAutoGeometryRestore(QWidget *widget, const QString &key=QString())
Register the widget to allow its position to be automatically saved and restored when open and closed...
Definition: qgsgui.cpp:180
QgsPresetSchemeColorRamp::typeString
static QString typeString()
Returns the string identifier for QgsPresetSchemeColorRamp.
Definition: qgscolorrampimpl.h:588
QgsStyleManagerDialog::onClose
void onClose()
Closes the dialog.
Definition: qgsstylemanagerdialog.cpp:3008
QgsTextFormat
Container for all settings relating to text rendering.
Definition: qgstextformat.h:40
qgscolorbrewercolorrampdialog.h
QgsAbstract3DSymbol
Abstract base class for 3D symbols that are used by VectorLayer3DRenderer objects.
Definition: qgsabstract3dsymbol.h:46
QgsStyle::addSmartgroup
int addSmartgroup(const QString &name, const QString &op, const QgsSmartConditionMap &conditions)
Adds a new smartgroup to the database and returns the id.
Definition: qgsstyle.cpp:2269
QgsColorBrewerColorRampDialog
A dialog which allows users to modify the properties of a QgsColorBrewerColorRamp.
Definition: qgscolorbrewercolorrampdialog.h:86
QgsStyleManagerDialog::addSmartgroup
int addSmartgroup()
Triggers the dialog to add a new smart group.
Definition: qgsstylemanagerdialog.cpp:2576
QgsLimitedRandomColorRamp::clone
QgsLimitedRandomColorRamp * clone() const override
Creates a clone of the color ramp.
Definition: qgscolorrampimpl.cpp:675
QgsProjectStyleDatabaseModel::styleFromIndex
QgsStyle * styleFromIndex(const QModelIndex &index) const
Returns the style at the corresponding index.
Definition: qgsprojectstylesettings.cpp:532
qgstextformatwidget.h
QgsStyle::addSymbol
bool addSymbol(const QString &name, QgsSymbol *symbol, bool update=false)
Adds a symbol to style and takes symbol's ownership.
Definition: qgsstyle.cpp:197
QgsStyle::addLegendPatchShape
bool addLegendPatchShape(const QString &name, const QgsLegendPatchShape &shape, bool update=false)
Adds a legend patch shape with the specified name to the style.
Definition: qgsstyle.cpp:379
Qgis::SymbolType
SymbolType
Symbol types.
Definition: qgis.h:205
QgsStyleManagerDialog::grouptreeContextMenu
void grouptreeContextMenu(QPoint)
Context menu for the groupTree.
Definition: qgsstylemanagerdialog.cpp:2830
QgsCptCityColorRampDialog
A dialog which allows users to modify the properties of a QgsCptCityColorRamp.
Definition: qgscptcitycolorrampdialog.h:42
QgsStyle::Symbol3DEntity
@ Symbol3DEntity
3D symbol entity (since QGIS 3.14)
Definition: qgsstyle.h:187
QgsColorBrewerColorRamp::colors
int colors() const
Returns the number of colors in the ramp.
Definition: qgscolorrampimpl.h:663
QgsProjectStyleSettings::addStyleDatabasePath
void addStyleDatabasePath(const QString &path)
Adds a style database path to the project.
Definition: qgsprojectstylesettings.cpp:354
QgsTextFormat::fromMimeData
static QgsTextFormat fromMimeData(const QMimeData *data, bool *ok=nullptr)
Attempts to parse the provided mime data as a QgsTextFormat.
Definition: qgstextformat.cpp:789
qgscolorramp.h
QgsMarkerSymbol
A marker symbol type, for rendering Point and MultiPoint geometries.
Definition: qgsmarkersymbol.h:30
QgsStyle::removeFavorite
bool removeFavorite(StyleEntity type, const QString &name)
Removes the specified symbol from favorites.
Definition: qgsstyle.cpp:1662
QgsStyleExportImportDialog::Import
@ Import
Import xml file mode.
Definition: qgsstyleexportimportdialog.h:50
QgsStyleModel::TagRole
@ TagRole
String list of tags.
Definition: qgsstylemodel.h:124
QgsStyleManagerDialog::editItem
void editItem()
Triggers the dialog for editing the current item.
Definition: qgsstylemanagerdialog.cpp:1703
QgsStyle::tag
QString tag(int id) const
Returns the tag name for the given id.
Definition: qgsstyle.cpp:2040
QgsStyleManagerDialog::detagSelectedSymbols
void detagSelectedSymbols()
Remove all tags from selected symbols.
Definition: qgsstylemanagerdialog.cpp:2949
QgsCptCityColorRamp::schemeName
QString schemeName() const
Definition: qgscolorrampimpl.h:762
QgsPalLayerSettings::format
const QgsTextFormat & format() const
Returns the label text formatting settings, e.g., font settings, buffer settings, etc.
Definition: qgspallabeling.h:841
QgsStyleManagerDialog::enableGroupInputs
void enableGroupInputs(bool)
Enables or disables the groupTree specific inputs.
Definition: qgsstylemanagerdialog.cpp:2791
QgsCptCityColorRamp::clone
QgsCptCityColorRamp * clone() const override
Creates a clone of the color ramp.
Definition: qgscolorrampimpl.cpp:971
QgsApplication::defaultStyleModel
static QgsStyleModel * defaultStyleModel()
Returns a shared QgsStyleModel containing the default style library (see QgsStyle::defaultStyle()).
Definition: qgsapplication.cpp:2445
QgsColorBrewerColorRamp::schemeName
QString schemeName() const
Returns the name of the color brewer color scheme.
Definition: qgscolorrampimpl.h:657
QgsStyleManagerDialog::importItems
void importItems()
Triggers the dialog to import items.
Definition: qgsstylemanagerdialog.cpp:2340
QgsStyle::tags
QStringList tags() const
Returns a list of all tags in the style database.
Definition: qgsstyle.cpp:1401
QgsStyleManagerDialog::enableSymbolInputs
void enableSymbolInputs(bool)
Enables or disbables the symbol specific inputs.
Definition: qgsstylemanagerdialog.cpp:2778
QgsMessageBar
A bar for displaying non-blocking messages to the user.
Definition: qgsmessagebar.h:60
QgsLineSymbol
A line symbol type, for rendering LineString and MultiLineString geometries.
Definition: qgslinesymbol.h:29
qgssmartgroupeditordialog.h
QgsStyleManagerDialog::setBold
void setBold(QStandardItem *)
sets the text of the item with bold font
Definition: qgsstylemanagerdialog.cpp:2348
QgsStyleManagerDialog::setFavoritesGroupVisible
void setFavoritesGroupVisible(bool show)
Sets whether the favorites group should be shown.
Definition: qgsstylemanagerdialog.cpp:1665
QgsStyle::SmartgroupEntity
@ SmartgroupEntity
Smart groups.
Definition: qgsstyle.h:183
Qgis::UI_SCALE_FACTOR
static const double UI_SCALE_FACTOR
UI scaling factor.
Definition: qgis.h:2043
QgsStyleManagerDialog::editSmartgroupAction
void editSmartgroupAction()
Triggers the dialog for editing the selected smart group.
Definition: qgsstylemanagerdialog.cpp:2966
QgsStyleManagerDialog::addFavoriteSelectedSymbols
void addFavoriteSelectedSymbols()
Add selected symbols to favorites.
Definition: qgsstylemanagerdialog.cpp:2896
QgsStyle::smartgroupsListMap
QgsSymbolGroupMap smartgroupsListMap()
Returns the smart groups map with id as key and name as value.
Definition: qgsstyle.cpp:2323
QgsLimitedRandomColorRampDialog
A dialog which allows users to modify the properties of a QgsLimitedRandomColorRamp.
Definition: qgslimitedrandomcolorrampdialog.h:98
QgsStyleManagerDialog::editColorRamp
bool editColorRamp()
Definition: qgsstylemanagerdialog.cpp:1758
qgsmessagebar.h
qgsstylemodel.h
QgsStyle::groupsModified
void groupsModified()
Emitted every time a tag or smartgroup has been added, removed, or renamed.
QgsIconUtils::iconPoint
static QIcon iconPoint()
Returns an icon representing point geometries.
Definition: qgsiconutils.cpp:44
QgsSmartGroupEditorDialog::setOperator
void setOperator(const QString &)
sets the operator AND/OR
Definition: qgssmartgroupeditordialog.cpp:191
QgsSettings::setValue
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
Definition: qgssettings.cpp:279
QgsStyle::removeLabelSettings
bool removeLabelSettings(const QString &name)
Removes label settings from the style.
Definition: qgsstyle.cpp:1053
QgsStyleManagerDialog::symbolSelected
void symbolSelected(const QModelIndex &)
Perform symbol specific tasks when selected.
Definition: qgsstylemanagerdialog.cpp:2754
qgsfileutils.h
QgsSmartGroupEditorDialog::setConditionMap
void setConditionMap(const QgsSmartConditionMap &)
sets up the GUI for the given conditionmap
Definition: qgssmartgroupeditordialog.cpp:160
QgsStyleManagerDialog::onFinished
void onFinished()
Called when the dialog is going to be closed.
Definition: qgsstylemanagerdialog.cpp:623
qgssymbolselectordialog.h
QgsStyleManagerDialog::tagSelectedSymbols
void tagSelectedSymbols(bool newTag=false)
Tag selected symbols using menu item selection.
Definition: qgsstylemanagerdialog.cpp:2920
qgsstyleexportimportdialog.h
QgsStyle::symbolNames
QStringList symbolNames() const
Returns a list of names of symbols.
Definition: qgsstyle.cpp:307
QgsStyleModel::SymbolTypeRole
@ SymbolTypeRole
Symbol type (for symbol or legend patch shape entities)
Definition: qgsstylemodel.h:126
QgsStyleManagerDialog::setSymbolsChecked
Q_DECL_DEPRECATED void setSymbolsChecked(const QStringList &)
Definition: qgsstylemanagerdialog.cpp:2745
QgsSmartGroupEditorDialog::conditionOperator
QString conditionOperator()
returns the AND/OR condition
Definition: qgssmartgroupeditordialog.cpp:155
QgsStyleManagerDialog::populateList
void populateList()
Refreshes the list of items.
Definition: qgsstylemanagerdialog.cpp:1321
QgsStyleManagerDialog::removeGroup
void removeGroup()
Removes the selected tag or smartgroup.
Definition: qgsstylemanagerdialog.cpp:2617
QgsStyle::aboutToBeDestroyed
void aboutToBeDestroyed()
Emitted just before the style object is destroyed.
QgsStyle::smartgroup
QgsSmartConditionMap smartgroup(int id)
Returns the QgsSmartConditionMap for the given id.
Definition: qgsstyle.cpp:2464
QgsStyle::removeSymbol
bool removeSymbol(const QString &name)
Removes symbol from style (and delete it)
Definition: qgsstyle.cpp:257
qgs3dsymbolwidget.h
QgsWkbTypes::LineGeometry
@ LineGeometry
Definition: qgswkbtypes.h:143
QgsFileUtils::ensureFileNameHasExtension
static QString ensureFileNameHasExtension(const QString &fileName, const QStringList &extensions)
Ensures that a fileName ends with an extension from the provided list of extensions.
Definition: qgsfileutils.cpp:111
QgsWkbTypes::PointGeometry
@ PointGeometry
Definition: qgswkbtypes.h:142
QgsStyleManagerDialog::listitemsContextMenu
void listitemsContextMenu(QPoint)
Context menu for the listItems ( symbols list )
Definition: qgsstylemanagerdialog.cpp:2839
QgsStyle::legendPatchShape
QgsLegendPatchShape legendPatchShape(const QString &name) const
Returns the legend patch shape with the specified name.
Definition: qgsstyle.cpp:2145
QgsStyleManagerDialog::populateGroups
void populateGroups()
populate the groups
Definition: qgsstylemanagerdialog.cpp:2355
QgsStyle::textFormatNames
QStringList textFormatNames() const
Returns a list of names of text formats in the style.
Definition: qgsstyle.cpp:2130
QgsGradientColorRampDialog::ramp
QgsGradientColorRamp ramp
Definition: qgsgradientcolorrampdialog.h:41
QgsStyleExportImportDialog::Export
@ Export
Export existing symbols mode.
Definition: qgsstyleexportimportdialog.h:49
QgsStyleManagerDialog::tagSymbolsAction
void tagSymbolsAction()
Toggles the interactive item tagging mode.
Definition: qgsstylemanagerdialog.cpp:2676
QgsWkbTypes::GeometryType
GeometryType
The geometry types are used to group QgsWkbTypes::Type in a coarse way.
Definition: qgswkbtypes.h:140
QgsSettingsEntryByReference::value
T value(const QString &dynamicKeyPart=QString()) const
Returns settings value.
Definition: qgssettingsentry.h:379
QgsStyleManagerDialog::filterSymbols
void filterSymbols(const QString &filter)
Sets the filter string to filter symbols by.
Definition: qgsstylemanagerdialog.cpp:2749
QgsStyle::rename
bool rename(StyleEntity type, int id, const QString &newName)
Renames the given entity with the specified id.
Definition: qgsstyle.cpp:1421
QgsStyle
Definition: qgsstyle.h:159
QgsStyle::TextFormatEntity
@ TextFormatEntity
Text formats.
Definition: qgsstyle.h:184
QgsHelp::openHelp
static void openHelp(const QString &key)
Opens help topic for the given help key using default system web browser.
Definition: qgshelp.cpp:36
QgsStyle::isReadOnly
bool isReadOnly() const
Returns true if the style is considered a read-only library.
Definition: qgsstyle.cpp:3059
QgsStyleManagerDialog::exportItemsSVG
void exportItemsSVG()
Triggers the dialog to export selected items as SVG files.
Definition: qgsstylemanagerdialog.cpp:2307
qgsmarkersymbol.h
QgsSymbolGroupMap
QMap< int, QString > QgsSymbolGroupMap
Definition: qgsstyle.h:42
QgsStyleManagerDialog::setSmartGroupsVisible
void setSmartGroupsVisible(bool show)
Sets whether smart groups should be shown.
Definition: qgsstylemanagerdialog.cpp:1671
QgsStyleManagerDialog::addTag
int addTag()
Triggers the dialog to add a new tag.
Definition: qgsstylemanagerdialog.cpp:2523
QgsStyle::symbolSaved
void symbolSaved(const QString &name, QgsSymbol *symbol)
Emitted every time a new symbol has been added to the database.
qgssettings.h
qgslimitedrandomcolorrampdialog.h
QgsStyle::smartgroupOperator
QString smartgroupOperator(int id)
Returns the operator for the smartgroup.
Definition: qgsstyle.cpp:2504
QgsFillSymbol
A fill symbol type, for rendering Polygon and MultiPolygon geometries.
Definition: qgsfillsymbol.h:29
QgsStyleManagerDialog::showHelp
void showHelp()
Opens the associated help.
Definition: qgsstylemanagerdialog.cpp:3013
QgsStyleManagerDialog::addItem
void addItem()
Triggers the dialog for adding a new item, based on the currently selected item type tab.
Definition: qgsstylemanagerdialog.cpp:1368
qgsiconutils.h
QgsStyle::defaultPatch
QgsLegendPatchShape defaultPatch(Qgis::SymbolType type, QSizeF size) const
Returns the default legend patch shape for the given symbol type.
Definition: qgsstyle.cpp:1157
QgsSmartGroupEditorDialog::smartgroupName
QString smartgroupName()
returns the value from mNameLineEdit
Definition: qgssmartgroupeditordialog.cpp:98
QgsStyleManagerDialog::populateTypes
Q_DECL_DEPRECATED void populateTypes()
Populate combo box with known style items (symbols, color ramps).
Definition: qgsstylemanagerdialog.cpp:629
qgsgradientcolorrampdialog.h
QgsSettingsEntryByReference::setValue
bool setValue(const T &value, const QString &dynamicKeyPart=QString()) const
Set settings value.
Definition: qgssettingsentry.h:424
QgsStyle::addLabelSettings
bool addLabelSettings(const QString &name, const QgsPalLayerSettings &settings, bool update=false)
Adds label settings with the specified name to the style.
Definition: qgsstyle.cpp:358
QgsStyle::saveSymbol
bool saveSymbol(const QString &name, QgsSymbol *symbol, bool favorite, const QStringList &tags)
Adds the symbol to the database with tags.
Definition: qgsstyle.cpp:221
QgsStyle::colorRampNames
QStringList colorRampNames() const
Returns a list of names of color ramps.
Definition: qgsstyle.cpp:478
QgsSmartGroupEditorDialog::conditionMap
QgsSmartConditionMap conditionMap()
returns the condition map
Definition: qgssmartgroupeditordialog.cpp:142
QgsApplication::getThemeIcon
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
Definition: qgsapplication.cpp:693
QgsStyleManagerDialog::selectedSymbolsChanged
void selectedSymbolsChanged(const QItemSelection &selected, const QItemSelection &deselected)
Perform tasks when the selected symbols change.
Definition: qgsstylemanagerdialog.cpp:2759
QgsCptCityColorRamp
Definition: qgscolorrampimpl.h:714
QgsStyle::remove
bool remove(StyleEntity type, int id)
Removes the specified entity from the database.
Definition: qgsstyle.cpp:1456
QgsGradientColorRampDialog::buttonBox
QDialogButtonBox * buttonBox() const
Returns a reference to the dialog's button box.
Definition: qgsgradientcolorrampdialog.cpp:213
qgslogger.h
QgsStyle::saveLegendPatchShape
bool saveLegendPatchShape(const QString &name, const QgsLegendPatchShape &shape, bool favorite, const QStringList &tags)
Adds a legend patch shape to the database.
Definition: qgsstyle.cpp:1093
QgsStyle::legendPatchShapeNames
QStringList legendPatchShapeNames() const
Returns a list of names of legend patch shapes in the style.
Definition: qgsstyle.cpp:2204
qgscptcitycolorrampdialog.h
QgsStyle::tagsOfSymbol
QStringList tagsOfSymbol(StyleEntity type, const QString &symbol)
Returns the tags associated with the symbol.
Definition: qgsstyle.cpp:1911
QgsProjectStyleDatabaseModel::setShowDefaultStyle
void setShowDefaultStyle(bool show)
Sets whether the default style should also be included in the model.
Definition: qgsprojectstylesettings.cpp:569
QgsStyle::removeTextFormat
bool removeTextFormat(const QString &name)
Removes a text format from the style.
Definition: qgsstyle.cpp:977
qgspresetcolorrampdialog.h
QgsStyle::addTextFormat
bool addTextFormat(const QString &name, const QgsTextFormat &format, bool update=false)
Adds a text format with the specified name to the style.
Definition: qgsstyle.cpp:337
QgsStyleManagerDialog::addSymbol
bool addSymbol(int symbolType=-1)
add a new symbol to style
Definition: qgsstylemanagerdialog.cpp:1409
QgsStyleProxyModel
A QSortFilterProxyModel subclass for showing filtered symbol and color ramps entries from a QgsStyle ...
Definition: qgsstylemodel.h:222
QgsStyle::labelSettings
QgsPalLayerSettings labelSettings(const QString &name) const
Returns the label settings with the specified name.
Definition: qgsstyle.cpp:2140
qgsfillsymbol.h
QgsSmartConditionMap
QMultiMap< QString, QString > QgsSmartConditionMap
Definition: qgsstyle.h:79
QgsPalLayerSettings::layerType
QgsWkbTypes::GeometryType layerType
Geometry type of layers associated with these settings.
Definition: qgspallabeling.h:739
qgssymbol.h
QgsLimitedRandomColorRamp::typeString
static QString typeString()
Returns the string identifier for QgsLimitedRandomColorRamp.
Definition: qgscolorrampimpl.h:375
QgsStyleExportImportDialog
Definition: qgsstyleexportimportdialog.h:40
QgsStyle::saveLabelSettings
bool saveLabelSettings(const QString &name, const QgsPalLayerSettings &settings, bool favorite, const QStringList &tags)
Adds label settings to the database.
Definition: qgsstyle.cpp:1017
QgsStyleManagerDialog::currentItemType
int currentItemType()
Definition: qgsstylemanagerdialog.cpp:1334
qgsproject.h
qgslabelinggui.h
Qgs3DSymbolDialog
A dialog for configuring a 3D symbol.
Definition: qgs3dsymbolwidget.h:77
QgsStyle::colorRamp
QgsColorRamp * colorRamp(const QString &name) const
Returns a new copy of the specified color ramp.
Definition: qgsstyle.cpp:462
Qgis::SymbolType::Marker
@ Marker
Marker symbol.
QgsSmartGroupEditorDialog
Definition: qgssmartgroupeditordialog.h:71
QgsStyleManagerDialog::exportItemsPNG
void exportItemsPNG()
Triggers the dialog to export selected items as PNG files.
Definition: qgsstylemanagerdialog.cpp:2299
QgsTemporaryCursorOverride
Temporarily sets a cursor override for the QApplication for the lifetime of the object.
Definition: qgsguiutils.h:220
QgsPresetColorRampDialog::ramp
QgsPresetSchemeColorRamp ramp
Definition: qgspresetcolorrampdialog.h:89
QgsSettings::Gui
@ Gui
Definition: qgssettings.h:71
QgsStyle::tagId
int tagId(const QString &tag)
Returns the database id for the given tag name.
Definition: qgsstyle.cpp:2228
QgsStyleModel::Name
@ Name
Name column.
Definition: qgsstylemodel.h:116
qgslinesymbol.h
QgsStyle::StyleEntity
StyleEntity
Enum for Entities involved in a style.
Definition: qgsstyle.h:178
QgsStyle::saveSymbol3D
bool saveSymbol3D(const QString &name, QgsAbstract3DSymbol *symbol, bool favorite, const QStringList &tags)
Adds a 3d symbol to the database.
Definition: qgsstyle.cpp:1231
qgslegendpatchshapewidget.h
QgsLegendPatchShape::isNull
bool isNull() const
Returns true if the patch shape is a null QgsLegendPatchShape, which indicates that the default legen...
Definition: qgslegendpatchshape.cpp:32
QgsStyle::addTag
int addTag(const QString &tagName)
Adds a new tag and returns the tag's id.
Definition: qgsstyle.cpp:1381