17#include "moc_qgsstylemanagerdialog.cpp" 
   54#include <QInputDialog> 
   57#include <QStandardItemModel> 
   60#include <QDesktopServices> 
   74QgsCheckableStyleModel::QgsCheckableStyleModel( 
QgsStyleModel *sourceModel, QObject *parent, 
bool readOnly )
 
   76  , mStyle( sourceModel->style() )
 
   77  , mReadOnly( readOnly )
 
   81QgsCheckableStyleModel::QgsCheckableStyleModel( 
QgsStyle *style, QObject *parent, 
bool readOnly )
 
   84  , mReadOnly( readOnly )
 
   88void QgsCheckableStyleModel::setCheckable( 
bool checkable )
 
   90  if ( checkable == mCheckable )
 
   93  mCheckable = checkable;
 
   94  emit dataChanged( index( 0, 0 ), index( rowCount() - 1, 0 ), QVector<int>() << Qt::CheckStateRole );
 
   97void QgsCheckableStyleModel::setCheckTag( 
const QString &tag )
 
   99  if ( tag == mCheckTag )
 
  103  emit dataChanged( index( 0, 0 ), index( rowCount() - 1, 0 ), QVector<int>() << Qt::CheckStateRole );
 
  106Qt::ItemFlags QgsCheckableStyleModel::flags( 
const QModelIndex &index )
 const 
  108  Qt::ItemFlags f = QgsStyleProxyModel::flags( index );
 
  109  if ( !mReadOnly && mCheckable && index.column() == 0 )
 
  110    f |= Qt::ItemIsUserCheckable;
 
  113    f &= ~Qt::ItemIsEditable;
 
  118QVariant QgsCheckableStyleModel::data( 
const QModelIndex &index, 
int role )
 const 
  125      QFont f = QgsStyleProxyModel::data( index, role ).value<QFont>();
 
  130    case Qt::CheckStateRole:
 
  132      if ( !mCheckable || index.column() != 0 )
 
  136      return tags.contains( mCheckTag ) ? Qt::Checked : Qt::Unchecked;
 
  142  return QgsStyleProxyModel::data( index, role );
 
  145bool QgsCheckableStyleModel::setData( 
const QModelIndex &i, 
const QVariant &value, 
int role )
 
  147  if ( i.row() < 0 || i.row() >= rowCount( QModelIndex() ) || ( role != Qt::EditRole && role != Qt::CheckStateRole ) )
 
  153  if ( role == Qt::CheckStateRole )
 
  155    if ( !mCheckable || mCheckTag.isEmpty() )
 
  158    const QString name = data( index( i.row(), 
QgsStyleModel::Name ), Qt::DisplayRole ).toString();
 
  161    if ( value.toInt() == Qt::Checked )
 
  162      return mStyle->tagSymbol( entity, name, QStringList() << mCheckTag );
 
  164      return mStyle->detagSymbol( entity, name, QStringList() << mCheckTag );
 
  166  return QgsStyleProxyModel::setData( i, value, role );
 
  176QString QgsStyleManagerDialog::sPreviousTag;
 
  179  : QDialog( parent, flags )
 
  180  , mReadOnly( readOnly )
 
  183  setCurrentStyle( style );
 
  184  mStyleDatabaseWidget->hide();
 
 
  188  : QDialog( parent, flags )
 
  194  mComboBoxStyleDatabase->setModel( mProjectStyleModel );
 
  198  connect( mComboBoxStyleDatabase, qOverload<int>( &QComboBox::currentIndexChanged ), 
this, [
this]() {
 
  199    if ( mBlockStyleDatabaseChanges )
 
  202    const QModelIndex index = mProjectStyleModel->index( mComboBoxStyleDatabase->currentIndex(), 0, QModelIndex() );
 
  206  connect( mButtonAddStyleDatabase, &QAbstractButton::clicked, 
this, [
this] { addStyleDatabase( 
false ); } );
 
  207  connect( mButtonNewStyleDatabase, &QAbstractButton::clicked, 
this, [
this] { addStyleDatabase( 
true ); } );
 
 
  210void QgsStyleManagerDialog::init()
 
  214  connect( tabItemType, &QTabWidget::currentChanged, 
this, &QgsStyleManagerDialog::tabItemType_currentChanged );
 
  218  QPushButton *downloadButton = buttonBox->addButton( tr( 
"Browse Online Styles" ), QDialogButtonBox::ResetRole );
 
  219  downloadButton->setToolTip( tr( 
"Download new styles from the online QGIS style repository" ) );
 
  221  connect( downloadButton, &QPushButton::clicked, 
this, [] {
 
  222    QDesktopServices::openUrl( QUrl( QStringLiteral( 
"https://hub.qgis.org/styles/" ) ) );
 
  226  mMessageBar->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed );
 
  227  mVerticalLayout->insertWidget( 0, mMessageBar );
 
  230  setWindowModality( Qt::WindowModal );
 
  235  mSplitter->setSizes( QList<int>() << 170 << 540 );
 
  236  mSplitter->restoreState( settings.
value( QStringLiteral( 
"Windows/StyleV2Manager/splitter" ) ).toByteArray() );
 
  238  tabItemType->setDocumentMode( 
true );
 
  239  searchBox->setShowSearchIcon( 
true );
 
  240  searchBox->setPlaceholderText( tr( 
"Filter symbols…" ) );
 
  244  connect( btnEditItem, &QPushButton::clicked, 
this, [
this]( 
bool ) { 
editItem(); } );
 
  245  connect( actnEditItem, &QAction::triggered, 
this, [
this]( 
bool ) { 
editItem(); } );
 
  248  connect( btnAddItem, &QPushButton::clicked, 
this, [
this]( 
bool ) {
 
  250    if ( !btnAddItem->menu() )
 
  256  connect( btnRemoveItem, &QPushButton::clicked, 
this, [
this]( 
bool ) { 
removeItem(); } );
 
  257  connect( actnRemoveItem, &QAction::triggered, 
this, [
this]( 
bool ) { 
removeItem(); } );
 
  259  mShareMenu = 
new QMenu( tr( 
"Share Menu" ), 
this );
 
  260  mExportAction = 
new QAction( tr( 
"Export Item(s)…" ), 
this );
 
  262  mShareMenu->addAction( mExportAction );
 
  264  connect( mCopyToDefaultButton, &QPushButton::clicked, 
this, &QgsStyleManagerDialog::copyItemsToDefault );
 
  266  mActionCopyItem = 
new QAction( tr( 
"Copy Item" ), 
this );
 
  267  connect( mActionCopyItem, &QAction::triggered, 
this, &QgsStyleManagerDialog::copyItem );
 
  268  mActionPasteItem = 
new QAction( tr( 
"Paste Item…" ), 
this );
 
  269  connect( mActionPasteItem, &QAction::triggered, 
this, &QgsStyleManagerDialog::pasteItem );
 
  271  QShortcut *copyShortcut = 
new QShortcut( QKeySequence( QKeySequence::StandardKey::Copy ), 
this );
 
  272  connect( copyShortcut, &QShortcut::activated, 
this, &QgsStyleManagerDialog::copyItem );
 
  273  QShortcut *pasteShortcut = 
new QShortcut( QKeySequence( QKeySequence::StandardKey::Paste ), 
this );
 
  274  connect( pasteShortcut, &QShortcut::activated, 
this, &QgsStyleManagerDialog::pasteItem );
 
  275  QShortcut *removeShortcut = 
new QShortcut( QKeySequence( QKeySequence::StandardKey::Delete ), 
this );
 
  277  QShortcut *editShortcut = 
new QShortcut( QKeySequence( Qt::Key_Return ), 
this );
 
  280  mShareMenu->addSeparator();
 
  281  mShareMenu->addAction( actnExportAsPNG );
 
  282  mShareMenu->addAction( actnExportAsSVG );
 
  287  btnShare->setMenu( mShareMenu );
 
  289  listItems->setTextElideMode( Qt::TextElideMode::ElideRight );
 
  291  mSymbolTreeView->setIconSize( QSize( 
static_cast<int>( treeIconSize ), 
static_cast<int>( treeIconSize ) ) );
 
  293  listItems->setSelectionBehavior( QAbstractItemView::SelectRows );
 
  294  listItems->setSelectionMode( QAbstractItemView::ExtendedSelection );
 
  295  mSymbolTreeView->setSelectionMode( listItems->selectionMode() );
 
  297  QStandardItemModel *groupModel = 
new QStandardItemModel( groupTree );
 
  298  groupTree->setModel( groupModel );
 
  299  groupTree->setHeaderHidden( 
true );
 
  304  QMenu *groupMenu = 
new QMenu( tr( 
"Group Actions" ), 
this );
 
  306  groupMenu->addAction( actnTagSymbols );
 
  308  actnFinishTagging->setVisible( 
false );
 
  309  groupMenu->addAction( actnFinishTagging );
 
  310  groupMenu->addAction( actnEditSmartGroup );
 
  311  btnManageGroups->setMenu( groupMenu );
 
  316  groupTree->setContextMenuPolicy( Qt::CustomContextMenu );
 
  320  listItems->setContextMenuPolicy( Qt::CustomContextMenu );
 
  322  mSymbolTreeView->setContextMenuPolicy( Qt::CustomContextMenu );
 
  325  mMenuBtnAddItemAll = 
new QMenu( 
this );
 
  326  mMenuBtnAddItemColorRamp = 
new QMenu( 
this );
 
  327  mMenuBtnAddItemLabelSettings = 
new QMenu( 
this );
 
  328  mMenuBtnAddItemLegendPatchShape = 
new QMenu( 
this );
 
  329  mMenuBtnAddItemSymbol3D = 
new QMenu( 
this );
 
  333  mMenuBtnAddItemAll->addAction( item );
 
  336  mMenuBtnAddItemAll->addAction( item );
 
  339  mMenuBtnAddItemAll->addAction( item );
 
  340  mMenuBtnAddItemAll->addSeparator();
 
  343  for ( 
const QPair<QString, QString> &rampType : rampTypes )
 
  345    item = 
new QAction( 
QgsApplication::getThemeIcon( QStringLiteral( 
"styleicons/color.svg" ) ), tr( 
"%1…" ).arg( rampType.second ), 
this );
 
  346    connect( item, &QAction::triggered, 
this, [
this, rampType]( 
bool ) { 
addColorRamp( rampType.first ); } );
 
  347    mMenuBtnAddItemAll->addAction( item );
 
  348    mMenuBtnAddItemColorRamp->addAction( item );
 
  350  mMenuBtnAddItemAll->addSeparator();
 
  352  connect( item, &QAction::triggered, 
this, [
this]( 
bool ) { addTextFormat(); } );
 
  353  mMenuBtnAddItemAll->addAction( item );
 
  354  mMenuBtnAddItemAll->addSeparator();
 
  357  mMenuBtnAddItemAll->addAction( item );
 
  358  mMenuBtnAddItemLabelSettings->addAction( item );
 
  361  mMenuBtnAddItemAll->addAction( item );
 
  362  mMenuBtnAddItemLabelSettings->addAction( item );
 
  365  mMenuBtnAddItemAll->addAction( item );
 
  366  mMenuBtnAddItemLabelSettings->addAction( item );
 
  368  mMenuBtnAddItemAll->addSeparator();
 
  371  mMenuBtnAddItemAll->addAction( item );
 
  372  mMenuBtnAddItemLegendPatchShape->addAction( item );
 
  374  connect( item, &QAction::triggered, 
this, [
this]( 
bool ) { addLegendPatchShape( 
Qgis::SymbolType::Line ); } );
 
  375  mMenuBtnAddItemAll->addAction( item );
 
  376  mMenuBtnAddItemLegendPatchShape->addAction( item );
 
  378  connect( item, &QAction::triggered, 
this, [
this]( 
bool ) { addLegendPatchShape( 
Qgis::SymbolType::Fill ); } );
 
  379  mMenuBtnAddItemAll->addAction( item );
 
  380  mMenuBtnAddItemLegendPatchShape->addAction( item );
 
  382  mMenuBtnAddItemAll->addSeparator();
 
  384  connect( item, &QAction::triggered, 
this, [
this]( 
bool ) { addSymbol3D( QStringLiteral( 
"point" ) ); } );
 
  385  mMenuBtnAddItemAll->addAction( item );
 
  386  mMenuBtnAddItemSymbol3D->addAction( item );
 
  388  connect( item, &QAction::triggered, 
this, [
this]( 
bool ) { addSymbol3D( QStringLiteral( 
"line" ) ); } );
 
  389  mMenuBtnAddItemAll->addAction( item );
 
  390  mMenuBtnAddItemSymbol3D->addAction( item );
 
  392  connect( item, &QAction::triggered, 
this, [
this]( 
bool ) { addSymbol3D( QStringLiteral( 
"polygon" ) ); } );
 
  393  mMenuBtnAddItemAll->addAction( item );
 
  394  mMenuBtnAddItemSymbol3D->addAction( item );
 
  397  mGroupMenu = 
new QMenu( 
this );
 
  398  mGroupListMenu = 
new QMenu( mGroupMenu );
 
  399  mGroupListMenu->setTitle( tr( 
"Add to Tag" ) );
 
  400  mGroupListMenu->setEnabled( 
false );
 
  407  mGroupTreeContextMenu = 
new QMenu( 
this );
 
  409  connect( actnAddTag, &QAction::triggered, 
this, [
this]( 
bool ) { 
addTag(); } );
 
  410  connect( actnAddSmartgroup, &QAction::triggered, 
this, [
this]( 
bool ) { 
addSmartgroup(); } );
 
  413  tabItemType_currentChanged( 0 );
 
  415  connect( mButtonIconView, &QToolButton::toggled, 
this, [
this]( 
bool active ) {
 
  418      mSymbolViewStackedWidget->setCurrentIndex( 0 );
 
  423  connect( mButtonListView, &QToolButton::toggled, 
this, [
this]( 
bool active ) {
 
  427      mSymbolViewStackedWidget->setCurrentIndex( 1 );
 
  431  const int currentView = settings.
value( QStringLiteral( 
"Windows/StyleV2Manager/lastIconView" ), 0, 
QgsSettings::Gui ).toInt();
 
  432  if ( currentView == 0 )
 
  433    mButtonIconView->setChecked( 
true );
 
  435    mButtonListView->setChecked( 
true );
 
  437  mSymbolTreeView->header()->restoreState( settings.
value( QStringLiteral( 
"Windows/StyleV2Manager/treeState" ), QByteArray(), 
QgsSettings::Gui ).toByteArray() );
 
  438  connect( mSymbolTreeView->header(), &QHeaderView::sectionResized, 
this, [
this] {
 
  440    QgsSettings().setValue( QStringLiteral( 
"Windows/StyleV2Manager/treeState" ), mSymbolTreeView->header()->saveState(), QgsSettings::Gui );
 
  443  const int thumbnailSize = settings.
value( QStringLiteral( 
"Windows/StyleV2Manager/thumbnailSize" ), 0, 
QgsSettings::Gui ).toInt();
 
  444  mSliderIconSize->setValue( thumbnailSize );
 
  445  connect( mSliderIconSize, &QSlider::valueChanged, 
this, &QgsStyleManagerDialog::setThumbnailSize );
 
  446  setThumbnailSize( thumbnailSize );
 
  449void QgsStyleManagerDialog::setCurrentStyle( 
QgsStyle *style )
 
  451  if ( mStyle == style )
 
  461  QgsCheckableStyleModel *oldModel = mModel;
 
  464  const bool readOnly = isReadOnly();
 
  467    if ( !mActionCopyToDefault )
 
  469      mActionCopyToDefault = 
new QAction( tr( 
"Copy Selection to Default Style…" ), 
this );
 
  470      mShareMenu->insertAction( mActionCopyItem, mActionCopyToDefault );
 
  471      connect( mActionCopyToDefault, &QAction::triggered, 
this, &QgsStyleManagerDialog::copyItemsToDefault );
 
  473    mCopyToDefaultButton->show();
 
  474    mModel = 
new QgsCheckableStyleModel( mStyle, 
this, readOnly );
 
  478    mCopyToDefaultButton->hide();
 
  479    if ( mActionCopyToDefault )
 
  481      mActionCopyToDefault->deleteLater();
 
  482      mActionCopyToDefault = 
nullptr;
 
  486  mModel->addDesiredIconSize( mSymbolTreeView->iconSize() );
 
  487  mModel->addDesiredIconSize( listItems->iconSize() );
 
  490  mModel->setFilterString( searchBox->text() );
 
  492  listItems->setModel( mModel );
 
  493  mSymbolTreeView->setModel( mModel );
 
  495  mSymbolTreeView->setSelectionModel( listItems->selectionModel() );
 
  502    oldModel->deleteLater();
 
  510  if ( mProjectStyleModel )
 
  512    const QModelIndex styleIndex = mProjectStyleModel->
indexFromStyle( mStyle );
 
  513    mBlockStyleDatabaseChanges++;
 
  514    mComboBoxStyleDatabase->setCurrentIndex( styleIndex.row() );
 
  515    mBlockStyleDatabaseChanges--;
 
  520    btnAddTag->setEnabled( 
false );
 
  521    btnAddSmartgroup->setEnabled( 
false );
 
  522    btnManageGroups->setEnabled( 
false );
 
  524    btnAddItem->setVisible( 
false );
 
  525    btnRemoveItem->setVisible( 
false );
 
  526    btnEditItem->setVisible( 
false );
 
  527    btnAddSmartgroup->setVisible( 
false );
 
  528    btnAddTag->setVisible( 
false );
 
  529    btnManageGroups->setVisible( 
false );
 
  531    delete mImportAction;
 
  532    mImportAction = 
nullptr;
 
  534    mGroupTreeContextMenu->clear();
 
  536    mGroupMenu->addAction( mActionCopyItem );
 
  540    btnAddTag->setEnabled( 
true );
 
  541    btnAddSmartgroup->setEnabled( 
true );
 
  542    btnManageGroups->setEnabled( 
true );
 
  544    btnAddItem->setVisible( 
true );
 
  545    btnRemoveItem->setVisible( 
true );
 
  546    btnEditItem->setVisible( 
true );
 
  547    btnAddSmartgroup->setVisible( 
true );
 
  548    btnAddTag->setVisible( 
true );
 
  549    btnManageGroups->setVisible( 
true );
 
  551    if ( !mImportAction )
 
  553      mImportAction = 
new QAction( tr( 
"Import Item(s)…" ), 
this );
 
  555      mShareMenu->insertAction( mShareMenu->actions().at( mShareMenu->actions().indexOf( mExportAction ) + 1 ), mImportAction );
 
  559    mGroupTreeContextMenu->clear();
 
  560    mGroupTreeContextMenu->addAction( actnEditSmartGroup );
 
  561    mGroupTreeContextMenu->addAction( actnAddTag );
 
  562    mGroupTreeContextMenu->addAction( actnAddSmartgroup );
 
  563    mGroupTreeContextMenu->addAction( actnRemoveGroup );
 
  566    mGroupMenu->addAction( actnAddFavorite );
 
  567    mGroupMenu->addAction( actnRemoveFavorite );
 
  568    mGroupMenu->addSeparator()->setParent( 
this );
 
  569    mGroupMenu->addMenu( mGroupListMenu );
 
  570    mGroupMenu->addAction( actnDetag );
 
  571    mGroupMenu->addSeparator()->setParent( 
this );
 
  572    mGroupMenu->addAction( actnRemoveItem );
 
  573    mGroupMenu->addAction( actnEditItem );
 
  574    mGroupMenu->addAction( mActionCopyItem );
 
  575    mGroupMenu->addAction( mActionPasteItem );
 
  576    mGroupMenu->addSeparator()->setParent( 
this );
 
  579  if ( mActionCopyToDefault )
 
  581    mGroupMenu->addAction( mActionCopyToDefault );
 
  583  mGroupMenu->addAction( actnExportAsPNG );
 
  584  mGroupMenu->addAction( actnExportAsSVG );
 
  587  const QModelIndexList prevIndex = groupTree->model()->match( groupTree->model()->index( 0, 0 ), Qt::UserRole + 1, sPreviousTag, 1, Qt::MatchFixedString | Qt::MatchCaseSensitive | Qt::MatchRecursive );
 
  588  groupTree->setCurrentIndex( !prevIndex.empty() ? prevIndex.at( 0 ) : groupTree->model()->index( 0, 0 ) );
 
  591  tabItemType_currentChanged( tabItemType->currentIndex() );
 
  597void QgsStyleManagerDialog::currentStyleAboutToBeDestroyed()
 
  608  settings.
setValue( QStringLiteral( 
"Windows/StyleV2Manager/splitter" ), mSplitter->saveState() );
 
 
  615void QgsStyleManagerDialog::tabItemType_currentChanged( 
int )
 
  624  searchBox->setPlaceholderText( isSymbol ? tr( 
"Filter symbols…" ) : isColorRamp        ? tr( 
"Filter color ramps…" )
 
  625                                                                    : isTextFormat       ? tr( 
"Filter text symbols…" )
 
  626                                                                    : isLabelSettings    ? tr( 
"Filter label settings…" )
 
  627                                                                    : isLegendPatchShape ? tr( 
"Filter legend patch shapes…" )
 
  628                                                                                         : tr( 
"Filter 3D symbols…" ) );
 
  630  const bool readOnly = isReadOnly();
 
  631  if ( !readOnly && isColorRamp ) 
 
  633    btnAddItem->setMenu( mMenuBtnAddItemColorRamp );
 
  635  else if ( !readOnly && isLegendPatchShape ) 
 
  637    btnAddItem->setMenu( mMenuBtnAddItemLegendPatchShape );
 
  639  else if ( !readOnly && isSymbol3D ) 
 
  641    btnAddItem->setMenu( mMenuBtnAddItemSymbol3D );
 
  643  else if ( !readOnly && isLabelSettings ) 
 
  645    btnAddItem->setMenu( mMenuBtnAddItemLabelSettings );
 
  647  else if ( !readOnly && !isSymbol && !isColorRamp ) 
 
  649    btnAddItem->setMenu( 
nullptr );
 
  651  else if ( !readOnly && tabItemType->currentIndex() == 0 ) 
 
  653    btnAddItem->setMenu( mMenuBtnAddItemAll );
 
  657    btnAddItem->setMenu( 
nullptr );
 
  660  actnExportAsPNG->setVisible( isSymbol );
 
  661  actnExportAsSVG->setVisible( isSymbol );
 
  666                                                                                                           : isLabelSettings    ? 
QgsStyle::LabelSettingsEntity
 
  667                                                                                                           : isLegendPatchShape ? 
QgsStyle::LegendPatchShapeEntity
 
  669    mModel->setEntityFilterEnabled( !allTypesSelected() );
 
  670    mModel->setSymbolTypeFilterEnabled( isSymbol && !allTypesSelected() );
 
  671    if ( isSymbol && !allTypesSelected() )
 
  678void QgsStyleManagerDialog::copyItemsToDefault()
 
  680  const QList<ItemDetails> items = selectedItems();
 
  681  if ( !items.empty() )
 
  685    if ( !mBaseName.isEmpty() )
 
  686      options.append( mBaseName );
 
  689    defaultTags.sort( Qt::CaseInsensitive );
 
  690    options.append( defaultTags );
 
  691    const QString tags = QInputDialog::getItem( 
this, tr( 
"Import Items" ), tr( 
"Additional tags to add (comma separated)" ), options, mBaseName.isEmpty() ? -1 : 0, true, &ok );
 
  695    const QStringList parts = tags.split( 
',', Qt::SkipEmptyParts );
 
  696    QStringList additionalTags;
 
  697    additionalTags.reserve( parts.count() );
 
  698    for ( 
const QString &tag : parts )
 
  699      additionalTags << tag.trimmed();
 
  701    auto cursorOverride = std::make_unique<QgsTemporaryCursorOverride>( Qt::WaitCursor );
 
  702    const int count = copyItems( items, mStyle, 
QgsStyle::defaultStyle(), 
this, cursorOverride, 
true, additionalTags, 
false, 
false );
 
  703    cursorOverride.reset();
 
  706      mMessageBar->pushSuccess( tr( 
"Import Items" ), count > 1 ? tr( 
"Successfully imported %n item(s).", 
nullptr, count ) : tr( 
"Successfully imported item." ) );
 
  711void QgsStyleManagerDialog::copyItem()
 
  713  const QList<ItemDetails> items = selectedItems();
 
  717  ItemDetails details = items.at( 0 );
 
  718  switch ( details.entityType )
 
  722      std::unique_ptr<QgsSymbol> symbol( mStyle->
symbol( details.name ) );
 
  732      QApplication::clipboard()->setMimeData( format.toMimeData() );
 
  739      QApplication::clipboard()->setMimeData( format.toMimeData() );
 
  752void QgsStyleManagerDialog::pasteItem()
 
  754  const QString defaultTag = groupTree->currentIndex().isValid() ? groupTree->currentIndex().data( GroupModelRoles::TagName ).toString() : QString();
 
  759    saveDlg.setWindowTitle( tr( 
"Paste Symbol" ) );
 
  760    saveDlg.setDefaultTags( defaultTag );
 
  761    if ( !saveDlg.exec() || saveDlg.name().isEmpty() )
 
  764    if ( mStyle->
symbolNames().contains( saveDlg.name() ) )
 
  766      int res = QMessageBox::warning( 
this, tr( 
"Paste Symbol" ), tr( 
"A symbol with the name '%1' already exists. Overwrite?" ).arg( saveDlg.name() ), QMessageBox::Yes | QMessageBox::No );
 
  767      if ( res != QMessageBox::Yes )
 
  774    QStringList symbolTags = saveDlg.tags().split( 
',' );
 
  776    mStyle->
addSymbol( saveDlg.name(), tempSymbol.release() );
 
  778    mStyle->
saveSymbol( saveDlg.name(), newSymbol, saveDlg.isFavorite(), symbolTags );
 
  787    saveDlg.setDefaultTags( defaultTag );
 
  788    saveDlg.setWindowTitle( tr( 
"Paste Text Format" ) );
 
  789    if ( !saveDlg.exec() || saveDlg.name().isEmpty() )
 
  794      int res = QMessageBox::warning( 
this, tr( 
"Paste Text Format" ), tr( 
"A format with the name '%1' already exists. Overwrite?" ).arg( saveDlg.name() ), QMessageBox::Yes | QMessageBox::No );
 
  795      if ( res != QMessageBox::Yes )
 
  802    QStringList symbolTags = saveDlg.tags().split( 
',' );
 
  805    mStyle->
saveTextFormat( saveDlg.name(), format, saveDlg.isFavorite(), symbolTags );
 
  810void QgsStyleManagerDialog::setThumbnailSize( 
int value )
 
  815  const double spacing = 
Qgis::UI_SCALE_FACTOR * fontMetrics().horizontalAdvance( 
'X' ) * ( value * 2.2 + 14 );
 
  818  listItems->setIconSize( QSize( 
static_cast<int>( iconSize ), 
static_cast<int>( iconSize * 0.9 ) ) );
 
  819  listItems->setGridSize( QSize( 
static_cast<int>( spacing ), 
static_cast<int>( verticalSpacing ) ) );
 
  822    mModel->addDesiredIconSize( listItems->iconSize() );
 
  828int QgsStyleManagerDialog::selectedItemType()
 
  830  QModelIndex index = listItems->selectionModel()->currentIndex();
 
  831  if ( !index.isValid() )
 
  849bool QgsStyleManagerDialog::allTypesSelected()
 const 
  851  return tabItemType->currentIndex() == 0;
 
  854bool QgsStyleManagerDialog::isReadOnly()
 const 
  856  return mReadOnly || ( mStyle && mStyle->
isReadOnly() );
 
  859QList<QgsStyleManagerDialog::ItemDetails> QgsStyleManagerDialog::selectedItems()
 
  861  QList<QgsStyleManagerDialog::ItemDetails> res;
 
  862  QModelIndexList indices = listItems->selectionModel()->selectedRows();
 
  863  for ( 
const QModelIndex &index : indices )
 
  865    if ( !index.isValid() )
 
  872    details.name = mModel->data( mModel->index( index.row(), 
QgsStyleModel::Name, index.parent() ), Qt::DisplayRole ).toString();
 
  879int QgsStyleManagerDialog::copyItems( 
const QList<QgsStyleManagerDialog::ItemDetails> &items, 
QgsStyle *src, 
QgsStyle *dst, QWidget *parentWidget, std::unique_ptr<QgsTemporaryCursorOverride> &cursorOverride, 
bool isImport, 
const QStringList &importTags, 
bool addToFavorites, 
bool ignoreSourceTags )
 
  882  bool overwriteAll = 
true;
 
  892  for ( 
auto &details : items )
 
  894    QStringList symbolTags;
 
  895    if ( !ignoreSourceTags )
 
  897      symbolTags = src->
tagsOfSymbol( details.entityType, details.name );
 
  900    bool addItemToFavorites = 
false;
 
  903      symbolTags << importTags;
 
  904      addItemToFavorites = addToFavorites;
 
  907    switch ( details.entityType )
 
  911        std::unique_ptr<QgsSymbol> symbol( src->
symbol( details.name ) );
 
  915        const bool hasDuplicateName = dst->
symbolNames().contains( details.name );
 
  916        bool overwriteThis = 
false;
 
  918          addItemToFavorites = favoriteSymbols.contains( details.name );
 
  920        if ( hasDuplicateName && prompt )
 
  922          cursorOverride.reset();
 
  923          int res = QMessageBox::warning( parentWidget, isImport ? tr( 
"Import Symbol" ) : tr( 
"Export Symbol" ), tr( 
"A symbol with the name “%1” already exists.\nOverwrite?" ).arg( details.name ), QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No | QMessageBox::NoToAll | QMessageBox::Cancel );
 
  924          cursorOverride = std::make_unique<QgsTemporaryCursorOverride>( Qt::WaitCursor );
 
  927            case QMessageBox::Cancel:
 
  930            case QMessageBox::No:
 
  933            case QMessageBox::Yes:
 
  934              overwriteThis = 
true;
 
  937            case QMessageBox::YesToAll:
 
  942            case QMessageBox::NoToAll:
 
  944              overwriteAll = 
false;
 
  949        if ( !hasDuplicateName || overwriteAll || overwriteThis )
 
  952          dst->
addSymbol( details.name, symbol.release() );
 
  953          dst->
saveSymbol( details.name, newSymbol, addItemToFavorites, symbolTags );
 
  961        std::unique_ptr<QgsColorRamp> ramp( src->
colorRamp( details.name ) );
 
  965        const bool hasDuplicateName = dst->
colorRampNames().contains( details.name );
 
  966        bool overwriteThis = 
false;
 
  968          addItemToFavorites = favoriteColorramps.contains( details.name );
 
  970        if ( hasDuplicateName && prompt )
 
  972          cursorOverride.reset();
 
  973          int res = QMessageBox::warning( parentWidget, isImport ? tr( 
"Import Color Ramp" ) : tr( 
"Export Color Ramp" ), tr( 
"A color ramp with the name “%1” already exists.\nOverwrite?" ).arg( details.name ), QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No | QMessageBox::NoToAll | QMessageBox::Cancel );
 
  974          cursorOverride = std::make_unique<QgsTemporaryCursorOverride>( Qt::WaitCursor );
 
  977            case QMessageBox::Cancel:
 
  980            case QMessageBox::No:
 
  983            case QMessageBox::Yes:
 
  984              overwriteThis = 
true;
 
  987            case QMessageBox::YesToAll:
 
  992            case QMessageBox::NoToAll:
 
  994              overwriteAll = 
false;
 
  999        if ( !hasDuplicateName || overwriteAll || overwriteThis )
 
 1003          dst->
saveColorRamp( details.name, newRamp, addItemToFavorites, symbolTags );
 
 1013        const bool hasDuplicateName = dst->
textFormatNames().contains( details.name );
 
 1014        bool overwriteThis = 
false;
 
 1016          addItemToFavorites = favoriteTextFormats.contains( details.name );
 
 1018        if ( hasDuplicateName && prompt )
 
 1020          cursorOverride.reset();
 
 1021          int res = QMessageBox::warning( parentWidget, isImport ? tr( 
"Import Text Format" ) : tr( 
"Export Text Format" ), tr( 
"A text format with the name “%1” already exists.\nOverwrite?" ).arg( details.name ), QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No | QMessageBox::NoToAll | QMessageBox::Cancel );
 
 1022          cursorOverride = std::make_unique<QgsTemporaryCursorOverride>( Qt::WaitCursor );
 
 1025            case QMessageBox::Cancel:
 
 1028            case QMessageBox::No:
 
 1031            case QMessageBox::Yes:
 
 1032              overwriteThis = 
true;
 
 1035            case QMessageBox::YesToAll:
 
 1037              overwriteAll = 
true;
 
 1040            case QMessageBox::NoToAll:
 
 1042              overwriteAll = 
false;
 
 1047        if ( !hasDuplicateName || overwriteAll || overwriteThis )
 
 1050          dst->
saveTextFormat( details.name, format, addItemToFavorites, symbolTags );
 
 1061        bool overwriteThis = 
false;
 
 1063          addItemToFavorites = favoriteLabelSettings.contains( details.name );
 
 1065        if ( hasDuplicateName && prompt )
 
 1067          cursorOverride.reset();
 
 1068          int res = QMessageBox::warning( parentWidget, isImport ? tr( 
"Import Label Settings" ) : tr( 
"Export Label Settings" ), tr( 
"Label settings with the name “%1” already exist.\nOverwrite?" ).arg( details.name ), QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No | QMessageBox::NoToAll | QMessageBox::Cancel );
 
 1069          cursorOverride = std::make_unique<QgsTemporaryCursorOverride>( Qt::WaitCursor );
 
 1072            case QMessageBox::Cancel:
 
 1075            case QMessageBox::No:
 
 1078            case QMessageBox::Yes:
 
 1079              overwriteThis = 
true;
 
 1082            case QMessageBox::YesToAll:
 
 1084              overwriteAll = 
true;
 
 1087            case QMessageBox::NoToAll:
 
 1089              overwriteAll = 
false;
 
 1094        if ( !hasDuplicateName || overwriteAll || overwriteThis )
 
 1097          dst->
saveLabelSettings( details.name, settings, addItemToFavorites, symbolTags );
 
 1108        bool overwriteThis = 
false;
 
 1110          addItemToFavorites = favoriteLegendPatchShapes.contains( details.name );
 
 1112        if ( hasDuplicateName && prompt )
 
 1114          cursorOverride.reset();
 
 1115          int res = QMessageBox::warning( parentWidget, isImport ? tr( 
"Import Legend Patch Shape" ) : tr( 
"Export Legend Patch Shape" ), tr( 
"Legend patch shape with the name “%1” already exist.\nOverwrite?" ).arg( details.name ), QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No | QMessageBox::NoToAll | QMessageBox::Cancel );
 
 1116          cursorOverride = std::make_unique<QgsTemporaryCursorOverride>( Qt::WaitCursor );
 
 1119            case QMessageBox::Cancel:
 
 1122            case QMessageBox::No:
 
 1125            case QMessageBox::Yes:
 
 1126              overwriteThis = 
true;
 
 1129            case QMessageBox::YesToAll:
 
 1131              overwriteAll = 
true;
 
 1134            case QMessageBox::NoToAll:
 
 1136              overwriteAll = 
false;
 
 1141        if ( !hasDuplicateName || overwriteAll || overwriteThis )
 
 1152        std::unique_ptr<QgsAbstract3DSymbol> symbol( src->
symbol3D( details.name ) );
 
 1156        const bool hasDuplicateName = dst->
symbol3DNames().contains( details.name );
 
 1157        bool overwriteThis = 
false;
 
 1159          addItemToFavorites = favorite3dSymbols.contains( details.name );
 
 1161        if ( hasDuplicateName && prompt )
 
 1163          cursorOverride.reset();
 
 1164          int res = QMessageBox::warning( parentWidget, isImport ? tr( 
"Import 3D Symbol" ) : tr( 
"Export 3D Symbol" ), tr( 
"A 3D symbol with the name “%1” already exists.\nOverwrite?" ).arg( details.name ), QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No | QMessageBox::NoToAll | QMessageBox::Cancel );
 
 1165          cursorOverride = std::make_unique<QgsTemporaryCursorOverride>( Qt::WaitCursor );
 
 1168            case QMessageBox::Cancel:
 
 1171            case QMessageBox::No:
 
 1174            case QMessageBox::Yes:
 
 1175              overwriteThis = 
true;
 
 1178            case QMessageBox::YesToAll:
 
 1180              overwriteAll = 
true;
 
 1183            case QMessageBox::NoToAll:
 
 1185              overwriteAll = 
false;
 
 1190        if ( !hasDuplicateName || overwriteAll || overwriteThis )
 
 1193          dst->
addSymbol3D( details.name, symbol.release() );
 
 1194          dst->
saveSymbol3D( details.name, newSymbol, addItemToFavorites, symbolTags );
 
 1208bool QgsStyleManagerDialog::addTextFormat()
 
 1212  formatDlg.setWindowTitle( tr( 
"New Text Format" ) );
 
 1213  if ( !formatDlg.exec() )
 
 1215  format = formatDlg.format();
 
 1218  const QString defaultTag = groupTree->currentIndex().isValid() ? groupTree->currentIndex().data( GroupModelRoles::TagName ).toString() : QString();
 
 1219  saveDlg.setDefaultTags( defaultTag );
 
 1220  if ( !saveDlg.exec() )
 
 1222  QString name = saveDlg.name();
 
 1225  bool nameInvalid = 
true;
 
 1226  while ( nameInvalid )
 
 1229    if ( name.isEmpty() )
 
 1231      QMessageBox::warning( 
this, tr( 
"Save Text Format" ), tr( 
"Cannot save text format without name. Enter a name." ) );
 
 1235      int res = QMessageBox::warning( 
this, tr( 
"Save Text Format" ), tr( 
"Text format with name '%1' already exists. Overwrite?" ).arg( name ), QMessageBox::Yes | QMessageBox::No );
 
 1236      if ( res == QMessageBox::Yes )
 
 1239        nameInvalid = 
false;
 
 1245      nameInvalid = 
false;
 
 1250      name = QInputDialog::getText( 
this, tr( 
"Text Format Name" ), tr( 
"Please enter a name for new text format:" ), QLineEdit::Normal, name, &ok );
 
 1258  QStringList symbolTags = saveDlg.tags().split( 
',' );
 
 1262  mStyle->
saveTextFormat( name, format, saveDlg.isFavorite(), symbolTags );
 
 1270  groupChanged( groupTree->selectionModel()->currentIndex() );
 
 
 1283  switch ( tabItemType->currentIndex() )
 
 
 1308  QModelIndex index = listItems->selectionModel()->currentIndex();
 
 1309  if ( !index.isValid() )
 
 1312  return mModel->data( mModel->index( index.row(), 
QgsStyleModel::Name, index.parent() ), Qt::DisplayRole ).toString();
 
 
 1317  bool changed = 
false;
 
 1328    changed = addTextFormat();
 
 1347    Q_ASSERT( 
false && 
"not implemented" );
 
 
 1360  QString name = tr( 
"new symbol" );
 
 1361  QString dialogTitle;
 
 1366      name = tr( 
"new marker" );
 
 1367      dialogTitle = tr( 
"New Marker Symbol" );
 
 1371      name = tr( 
"new line" );
 
 1372      dialogTitle = tr( 
"New Line Symbol" );
 
 1376      name = tr( 
"new fill symbol" );
 
 1377      dialogTitle = tr( 
"New Fill Symbol" );
 
 1380      Q_ASSERT( 
false && 
"unknown symbol type" );
 
 1390  dlg.setWindowTitle( dialogTitle );
 
 1391  if ( dlg.exec() == 0 )
 
 1398  const QString defaultTag = groupTree->currentIndex().isValid() ? groupTree->currentIndex().data( GroupModelRoles::TagName ).toString() : QString();
 
 1400  if ( !saveDlg.exec() )
 
 1406  name = saveDlg.
name();
 
 1409  bool nameInvalid = 
true;
 
 1410  while ( nameInvalid )
 
 1413    if ( name.isEmpty() )
 
 1415      QMessageBox::warning( 
this, tr( 
"Save Symbol" ), tr( 
"Cannot save symbol without name. Enter a name." ) );
 
 1417    else if ( mStyle->
symbolNames().contains( name ) )
 
 1419      int res = QMessageBox::warning( 
this, tr( 
"Save Symbol" ), tr( 
"Symbol with name '%1' already exists. Overwrite?" ).arg( name ), QMessageBox::Yes | QMessageBox::No );
 
 1420      if ( res == QMessageBox::Yes )
 
 1423        nameInvalid = 
false;
 
 1429      nameInvalid = 
false;
 
 1434      name = QInputDialog::getText( 
this, tr( 
"Symbol Name" ), tr( 
"Please enter a name for new symbol:" ), QLineEdit::Normal, name, &ok );
 
 1443  QStringList symbolTags = saveDlg.
tags().split( 
',' );
 
 
 1456  QString rampType = type;
 
 1458  if ( rampType.isEmpty() )
 
 1463    QStringList rampTypeNames;
 
 1464    rampTypeNames.reserve( rampTypes.size() );
 
 1465    for ( 
const QPair<QString, QString> &type : rampTypes )
 
 1466      rampTypeNames << type.second;
 
 1467    const QString selectedRampTypeName = QInputDialog::getItem( parent, tr( 
"Color Ramp Type" ), tr( 
"Please select color ramp type:" ), rampTypeNames, 0, 
false, &ok );
 
 1468    if ( !ok || selectedRampTypeName.isEmpty() )
 
 1471    rampType = rampTypes.value( rampTypeNames.indexOf( selectedRampTypeName ) ).first;
 
 1474  QString name = tr( 
"new ramp" );
 
 1476  std::unique_ptr<QgsColorRamp> ramp;
 
 1480    dlg.setWindowTitle( tr( 
"New Gradient Color Ramp" ) );
 
 1486    name = tr( 
"new gradient ramp" );
 
 1491    dlg.setWindowTitle( tr( 
"New Random Color Ramp" ) );
 
 1497    name = tr( 
"new random ramp" );
 
 1502    dlg.setWindowTitle( tr( 
"New ColorBrewer Ramp" ) );
 
 1513    dlg.setWindowTitle( tr( 
"New Preset Color Ramp" ) );
 
 1519    name = tr( 
"new preset ramp" );
 
 1524    dlg.setWindowTitle( tr( 
"New cpt-city Color Ramp" ) );
 
 1544    QgsDebugError( QStringLiteral( 
"invalid ramp type %1" ).arg( rampType ) );
 
 1549  if ( !saveDlg.exec() )
 
 1554  name = saveDlg.
name();
 
 1557  bool nameInvalid = 
true;
 
 1558  while ( nameInvalid )
 
 1561    if ( name.isEmpty() )
 
 1563      QMessageBox::warning( parent, tr( 
"Save Color Ramp" ), tr( 
"Cannot save color ramp without name. Enter a name." ) );
 
 1567      int res = QMessageBox::warning( parent, tr( 
"Save Color Ramp" ), tr( 
"Color ramp with name '%1' already exists. Overwrite?" ).arg( name ), QMessageBox::Yes | QMessageBox::No );
 
 1568      if ( res == QMessageBox::Yes )
 
 1570        nameInvalid = 
false;
 
 1576      nameInvalid = 
false;
 
 1581      name = QInputDialog::getText( parent, tr( 
"Color Ramp Name" ), tr( 
"Please enter a name for new color ramp:" ), QLineEdit::Normal, name, &ok );
 
 1589  QStringList colorRampTags = saveDlg.
tags().split( 
',' );
 
 
 1601  mFavoritesGroupVisible = show;
 
 
 1607  mSmartGroupVisible = show;
 
 
 1619  setWindowState( windowState() & ~Qt::WindowMinimized );
 
 
 1627  if ( !rampName.isEmpty() )
 
 
 1639  if ( selectedItemType() < 3 )
 
 1643  else if ( selectedItemType() == 3 )
 
 1647  else if ( selectedItemType() == 4 )
 
 1651  else if ( selectedItemType() == 5 )
 
 1653    editLabelSettings();
 
 1655  else if ( selectedItemType() == 6 )
 
 1657    editLegendPatchShape();
 
 1659  else if ( selectedItemType() == 7 )
 
 1665    Q_ASSERT( 
false && 
"not implemented" );
 
 
 1672  if ( symbolName.isEmpty() )
 
 1675  std::unique_ptr<QgsSymbol> symbol( mStyle->
symbol( symbolName ) );
 
 1679  dlg.setWindowTitle( symbolName );
 
 1681    dlg.
buttonBox()->button( QDialogButtonBox::Ok )->setEnabled( 
false );
 
 1687  mStyle->
addSymbol( symbolName, symbol.release(), 
true );
 
 
 1695  if ( name.isEmpty() )
 
 1698  std::unique_ptr<QgsColorRamp> ramp( mStyle->
colorRamp( name ) );
 
 1704    dlg.setWindowTitle( name );
 
 1706      dlg.
buttonBox()->button( QDialogButtonBox::Ok )->setEnabled( 
false );
 
 1718    dlg.setWindowTitle( name );
 
 1720      dlg.
buttonBox()->button( QDialogButtonBox::Ok )->setEnabled( 
false );
 
 1732    dlg.setWindowTitle( name );
 
 1734      dlg.
buttonBox()->button( QDialogButtonBox::Ok )->setEnabled( 
false );
 
 1746    dlg.setWindowTitle( name );
 
 1748      dlg.
buttonBox()->button( QDialogButtonBox::Ok )->setEnabled( 
false );
 
 1760    dlg.setWindowTitle( name );
 
 1762      dlg.
buttonBox()->button( QDialogButtonBox::Ok )->setEnabled( 
false );
 
 1779    Q_ASSERT( 
false && 
"invalid ramp type" );
 
 
 1787bool QgsStyleManagerDialog::editTextFormat()
 
 1790  if ( formatName.isEmpty() )
 
 1797  dlg.setWindowTitle( formatName );
 
 1799    dlg.buttonBox()->button( QDialogButtonBox::Ok )->setEnabled( 
false );
 
 1813  QgsLabelSettingsDialog settingsDlg( settings, 
nullptr, 
nullptr, 
this, type );
 
 1814  settingsDlg.setWindowTitle( tr( 
"New Label Settings" ) );
 
 1816    settingsDlg.buttonBox()->button( QDialogButtonBox::Ok )->setEnabled( 
false );
 
 1818  if ( !settingsDlg.exec() )
 
 1821  settings = settingsDlg.settings();
 
 1825  const QString defaultTag = groupTree->currentIndex().isValid() ? groupTree->currentIndex().data( GroupModelRoles::TagName ).toString() : QString();
 
 1826  saveDlg.setDefaultTags( defaultTag );
 
 1827  if ( !saveDlg.exec() )
 
 1829  QString name = saveDlg.name();
 
 1832  bool nameInvalid = 
true;
 
 1833  while ( nameInvalid )
 
 1836    if ( name.isEmpty() )
 
 1838      QMessageBox::warning( 
this, tr( 
"Save Label Settings" ), tr( 
"Cannot save label settings without a name. Enter a name." ) );
 
 1842      int res = QMessageBox::warning( 
this, tr( 
"Save Label Settings" ), tr( 
"Label settings with the name '%1' already exist. Overwrite?" ).arg( name ), QMessageBox::Yes | QMessageBox::No );
 
 1843      if ( res == QMessageBox::Yes )
 
 1846        nameInvalid = 
false;
 
 1852      nameInvalid = 
false;
 
 1857      name = QInputDialog::getText( 
this, tr( 
"Label Settings Name" ), tr( 
"Please enter a name for the new label settings:" ), QLineEdit::Normal, name, &ok );
 
 1865  QStringList symbolTags = saveDlg.tags().split( 
',' );
 
 1875bool QgsStyleManagerDialog::editLabelSettings()
 
 1878  if ( formatName.isEmpty() )
 
 1885  QgsLabelSettingsDialog dlg( settings, 
nullptr, 
nullptr, 
this, geomType );
 
 1886  dlg.setWindowTitle( formatName );
 
 1890  settings = dlg.settings();
 
 1903  dialog.setWindowTitle( tr( 
"New Legend Patch Shape" ) );
 
 1905    dialog.buttonBox()->button( QDialogButtonBox::Ok )->setEnabled( 
false );
 
 1907  if ( !dialog.exec() )
 
 1910  shape = dialog.shape();
 
 1913  const QString defaultTag = groupTree->currentIndex().isValid() ? groupTree->currentIndex().data( GroupModelRoles::TagName ).toString() : QString();
 
 1914  saveDlg.setDefaultTags( defaultTag );
 
 1915  if ( !saveDlg.exec() )
 
 1917  QString name = saveDlg.name();
 
 1920  bool nameInvalid = 
true;
 
 1921  while ( nameInvalid )
 
 1924    if ( name.isEmpty() )
 
 1926      QMessageBox::warning( 
this, tr( 
"Save Legend Patch Shape" ), tr( 
"Cannot save legend patch shapes without a name. Enter a name." ) );
 
 1930      int res = QMessageBox::warning( 
this, tr( 
"Save Legend Patch Shape" ), tr( 
"A legend patch shape with the name '%1' already exists. Overwrite?" ).arg( name ), QMessageBox::Yes | QMessageBox::No );
 
 1931      if ( res == QMessageBox::Yes )
 
 1934        nameInvalid = 
false;
 
 1940      nameInvalid = 
false;
 
 1945      name = QInputDialog::getText( 
this, tr( 
"Legend Patch Shape Name" ), tr( 
"Please enter a name for the new legend patch shape:" ), QLineEdit::Normal, name, &ok );
 
 1953  QStringList symbolTags = saveDlg.tags().split( 
',' );
 
 1963bool QgsStyleManagerDialog::editLegendPatchShape()
 
 1966  if ( shapeName.isEmpty() )
 
 1975  dlg.setWindowTitle( shapeName );
 
 1979  shape = dlg.shape();
 
 1987bool QgsStyleManagerDialog::addSymbol3D( 
const QString &type )
 
 1994  dialog.setWindowTitle( tr( 
"New 3D Symbol" ) );
 
 1996    dialog.buttonBox()->button( QDialogButtonBox::Ok )->setEnabled( 
false );
 
 1998  if ( !dialog.exec() )
 
 2001  symbol.reset( dialog.symbol() );
 
 2006  const QString defaultTag = groupTree->currentIndex().isValid() ? groupTree->currentIndex().data( GroupModelRoles::TagName ).toString() : QString();
 
 2007  saveDlg.setDefaultTags( defaultTag );
 
 2008  if ( !saveDlg.exec() )
 
 2010  QString name = saveDlg.name();
 
 2013  bool nameInvalid = 
true;
 
 2014  while ( nameInvalid )
 
 2017    if ( name.isEmpty() )
 
 2019      QMessageBox::warning( 
this, tr( 
"Save 3D Symbol" ), tr( 
"Cannot save 3D symbols without a name. Enter a name." ) );
 
 2023      int res = QMessageBox::warning( 
this, tr( 
"Save 3D Symbol" ), tr( 
"A 3D symbol with the name '%1' already exists. Overwrite?" ).arg( name ), QMessageBox::Yes | QMessageBox::No );
 
 2024      if ( res == QMessageBox::Yes )
 
 2027        nameInvalid = 
false;
 
 2033      nameInvalid = 
false;
 
 2038      name = QInputDialog::getText( 
this, tr( 
"3D Symbol Name" ), tr( 
"Please enter a name for the new 3D symbol:" ), QLineEdit::Normal, name, &ok );
 
 2046  QStringList symbolTags = saveDlg.tags().split( 
',' );
 
 2051  mStyle->
saveSymbol3D( name, newSymbol, saveDlg.isFavorite(), symbolTags );
 
 2057bool QgsStyleManagerDialog::editSymbol3D()
 
 2060  if ( symbolName.isEmpty() )
 
 2063  std::unique_ptr<QgsAbstract3DSymbol> symbol( mStyle->
symbol3D( symbolName ) );
 
 2069  dlg.setWindowTitle( symbolName );
 
 2073  symbol.reset( dlg.symbol() );
 
 2078  mStyle->
addSymbol3D( symbolName, symbol.release(), 
true );
 
 2083void QgsStyleManagerDialog::addStyleDatabase( 
bool createNew )
 
 2086  if ( initialFolder.isEmpty() )
 
 2087    initialFolder = QDir::homePath();
 
 2089  QString databasePath = createNew
 
 2090                           ? QFileDialog::getSaveFileName(
 
 2092                               tr( 
"Create Style Database" ),
 
 2094                               tr( 
"Style databases" ) + 
" (*.db)" 
 2096                           : QFileDialog::getOpenFileName(
 
 2098                               tr( 
"Add Style Database" ),
 
 2100                               tr( 
"Style databases" ) + 
" (*.db *.xml)" 
 2105  if ( !databasePath.isEmpty() )
 
 2112      if ( QFile::exists( databasePath ) )
 
 2114        QFile::remove( databasePath );
 
 2119        QMessageBox::warning( 
this, tr( 
"Create Style Database" ), tr( 
"The style database could not be created" ) );
 
 2131  const QList<ItemDetails> items = selectedItems();
 
 2133  if ( allTypesSelected() )
 
 2135    if ( QMessageBox::Yes != QMessageBox::question( 
this, tr( 
"Remove Items" ), QString( tr( 
"Do you really want to remove %n item(s)?", 
nullptr, items.count() ) ), QMessageBox::Yes, QMessageBox::No ) )
 
 2142      if ( QMessageBox::Yes != QMessageBox::question( 
this, tr( 
"Remove Symbol" ), QString( tr( 
"Do you really want to remove %n symbol(s)?", 
nullptr, items.count() ) ), QMessageBox::Yes, QMessageBox::No ) )
 
 2147      if ( QMessageBox::Yes != QMessageBox::question( 
this, tr( 
"Remove Color Ramp" ), QString( tr( 
"Do you really want to remove %n ramp(s)?", 
nullptr, items.count() ) ), QMessageBox::Yes, QMessageBox::No ) )
 
 2152      if ( QMessageBox::Yes != QMessageBox::question( 
this, tr( 
"Remove Text Formats" ), QString( tr( 
"Do you really want to remove %n text format(s)?", 
nullptr, items.count() ) ), QMessageBox::Yes, QMessageBox::No ) )
 
 2157      if ( QMessageBox::Yes != QMessageBox::question( 
this, tr( 
"Remove Label Settings" ), QString( tr( 
"Do you really want to remove %n label setting(s)?", 
nullptr, items.count() ) ), QMessageBox::Yes, QMessageBox::No ) )
 
 2162      if ( QMessageBox::Yes != QMessageBox::question( 
this, tr( 
"Remove Legend Patch Shapes" ), QString( tr( 
"Do you really want to remove %n legend patch shape(s)?", 
nullptr, items.count() ) ), QMessageBox::Yes, QMessageBox::No ) )
 
 2167      if ( QMessageBox::Yes != QMessageBox::question( 
this, tr( 
"Remove 3D Symbols" ), QString( tr( 
"Do you really want to remove %n 3D symbol(s)?", 
nullptr, items.count() ) ), QMessageBox::Yes, QMessageBox::No ) )
 
 2174  for ( 
const ItemDetails &details : items )
 
 2176    if ( details.name.isEmpty() )
 
 
 2201  QString dir = QFileDialog::getExistingDirectory( 
this, tr( 
"Export Selected Symbols as PNG" ), QDir::home().absolutePath(), QFileDialog::DontResolveSymlinks );
 
 
 2207  QString dir = QFileDialog::getExistingDirectory( 
this, tr( 
"Export Selected Symbols as SVG" ), QDir::home().absolutePath(), QFileDialog::DontResolveSymlinks );
 
 
 2214  if ( dir.isEmpty() )
 
 2217  const QList<ItemDetails> items = selectedItems();
 
 2218  for ( 
const ItemDetails &details : items )
 
 2223    QString path = dir + 
'/' + details.name + 
'.' + format;
 
 2224    std::unique_ptr<QgsSymbol> sym( mStyle->
symbol( details.name ) );
 
 2226      sym->exportImage( path, format, size );
 
 
 2246  QFont font = item->font();
 
 2247  font.setBold( 
true );
 
 2248  item->setFont( font );
 
 
 2253  if ( mBlockGroupUpdates )
 
 2256  QStandardItemModel *model = qobject_cast<QStandardItemModel *>( groupTree->model() );
 
 2259  const bool readOnly = isReadOnly();
 
 2261  if ( mFavoritesGroupVisible )
 
 2263    QStandardItem *favoriteSymbols = 
new QStandardItem( tr( 
"Favorites" ) );
 
 2264    favoriteSymbols->setData( 
"favorite" );
 
 2265    favoriteSymbols->setEditable( 
false );
 
 2267    model->appendRow( favoriteSymbols );
 
 2270  QStandardItem *allSymbols = 
new QStandardItem( tr( 
"All" ) );
 
 2271  allSymbols->setData( 
"all" );
 
 2272  allSymbols->setEditable( 
false );
 
 2274  model->appendRow( allSymbols );
 
 2276  QStandardItem *taggroup = 
new QStandardItem( QString() ); 
 
 2277  taggroup->setData( 
"tags" );
 
 2278  taggroup->setEditable( 
false );
 
 2279  QStringList tags = mStyle->
tags();
 
 2281  for ( 
const QString &tag : std::as_const( tags ) )
 
 2283    QStandardItem *item = 
new QStandardItem( tag );
 
 2284    item->setData( mStyle->
tagId( tag ) );
 
 2285    item->setData( tag, GroupModelRoles::TagName );
 
 2286    item->setEditable( !readOnly );
 
 2287    taggroup->appendRow( item );
 
 2289  taggroup->setText( tr( 
"Tags" ) ); 
 
 2291  model->appendRow( taggroup );
 
 2293  if ( mSmartGroupVisible )
 
 2295    QStandardItem *smart = 
new QStandardItem( tr( 
"Smart Groups" ) );
 
 2296    smart->setData( 
"smartgroups" );
 
 2297    smart->setEditable( 
false );
 
 2300    QgsSymbolGroupMap::const_iterator i = sgMap.constBegin();
 
 2301    while ( i != sgMap.constEnd() )
 
 2303      QStandardItem *item = 
new QStandardItem( i.value() );
 
 2304      item->setData( i.key() );
 
 2305      item->setEditable( !readOnly );
 
 2306      smart->appendRow( item );
 
 2309    model->appendRow( smart );
 
 2313  int rows = model->rowCount( model->indexFromItem( model->invisibleRootItem() ) );
 
 2314  for ( 
int i = 0; i < rows; i++ )
 
 2316    groupTree->setExpanded( model->indexFromItem( model->item( i ) ), 
true );
 
 
 2322  const QString category = index.data( Qt::UserRole + 1 ).toString();
 
 2323  sPreviousTag = category;
 
 2325  const bool readOnly = isReadOnly();
 
 2327  if ( mGroupingMode && mModel )
 
 2329    mModel->setTagId( -1 );
 
 2330    mModel->setSmartGroupId( -1 );
 
 2331    mModel->setFavoritesOnly( 
false );
 
 2332    mModel->setCheckTag( index.data( Qt::DisplayRole ).toString() );
 
 2334  else if ( category == QLatin1String( 
"all" ) || category == QLatin1String( 
"tags" ) || category == QLatin1String( 
"smartgroups" ) )
 
 2337    if ( category == QLatin1String( 
"tags" ) )
 
 2339      actnAddTag->setEnabled( !readOnly );
 
 2340      actnAddSmartgroup->setEnabled( 
false );
 
 2342    else if ( category == QLatin1String( 
"smartgroups" ) )
 
 2344      actnAddTag->setEnabled( 
false );
 
 2345      actnAddSmartgroup->setEnabled( !readOnly );
 
 2350      mModel->setTagId( -1 );
 
 2351      mModel->setSmartGroupId( -1 );
 
 2352      mModel->setFavoritesOnly( 
false );
 
 2355  else if ( category == QLatin1String( 
"favorite" ) )
 
 2358    mModel->setTagId( -1 );
 
 2359    mModel->setSmartGroupId( -1 );
 
 2360    mModel->setFavoritesOnly( 
true );
 
 2362  else if ( index.parent().data( Qt::UserRole + 1 ) == 
"smartgroups" )
 
 2364    actnRemoveGroup->setEnabled( !readOnly );
 
 2365    btnManageGroups->setEnabled( !readOnly );
 
 2366    const int groupId = index.data( Qt::UserRole + 1 ).toInt();
 
 2369      mModel->setTagId( -1 );
 
 2370      mModel->setSmartGroupId( groupId );
 
 2371      mModel->setFavoritesOnly( 
false );
 
 2377    int tagId = index.data( Qt::UserRole + 1 ).toInt();
 
 2380      mModel->setTagId( tagId );
 
 2381      mModel->setSmartGroupId( -1 );
 
 2382      mModel->setFavoritesOnly( 
false );
 
 2386  actnEditSmartGroup->setVisible( 
false );
 
 2387  actnAddTag->setVisible( 
false );
 
 2388  actnAddSmartgroup->setVisible( 
false );
 
 2389  actnRemoveGroup->setVisible( 
false );
 
 2390  actnTagSymbols->setVisible( 
false );
 
 2391  actnFinishTagging->setVisible( 
false );
 
 2393  if ( index.parent().isValid() )
 
 2395    if ( index.parent().data( Qt::UserRole + 1 ).toString() == QLatin1String( 
"smartgroups" ) )
 
 2397      actnEditSmartGroup->setVisible( !mGroupingMode && !readOnly );
 
 2399    else if ( index.parent().data( Qt::UserRole + 1 ).toString() == QLatin1String( 
"tags" ) )
 
 2401      actnAddTag->setVisible( !mGroupingMode && !readOnly );
 
 2402      actnTagSymbols->setVisible( !mGroupingMode && !readOnly );
 
 2403      actnFinishTagging->setVisible( mGroupingMode && !readOnly );
 
 2405    actnRemoveGroup->setVisible( !readOnly );
 
 2407  else if ( index.data( Qt::UserRole + 1 ) == 
"smartgroups" )
 
 2409    actnAddSmartgroup->setVisible( !mGroupingMode && !readOnly );
 
 2411  else if ( index.data( Qt::UserRole + 1 ) == 
"tags" )
 
 2413    actnAddTag->setVisible( !mGroupingMode && !readOnly );
 
 
 2422  QStandardItemModel *model = qobject_cast<QStandardItemModel *>( groupTree->model() );
 
 2424  for ( 
int i = 0; i < groupTree->model()->rowCount(); i++ )
 
 2426    index = groupTree->model()->index( i, 0 );
 
 2427    QString data = index.data( Qt::UserRole + 1 ).toString();
 
 2428    if ( data == QLatin1String( 
"tags" ) )
 
 2437  itemName = QInputDialog::getText( 
this, tr( 
"Add Tag" ), tr( 
"Please enter name for the new tag:" ), QLineEdit::Normal, tr( 
"New tag" ), &ok ).trimmed();
 
 2438  if ( !ok || itemName.isEmpty() )
 
 2441  int check = mStyle->
tagId( itemName );
 
 2444    mMessageBar->pushCritical( tr( 
"Add Tag" ), tr( 
"The tag “%1” already exists." ).arg( itemName ) );
 
 2450  mBlockGroupUpdates++;
 
 2451  id = mStyle->
addTag( itemName );
 
 2452  mBlockGroupUpdates--;
 
 2456    mMessageBar->pushCritical( tr( 
"Add Tag" ), tr( 
"New tag could not be created — There was a problem with the symbol database." ) );
 
 2460  QStandardItem *parentItem = model->itemFromIndex( index );
 
 2461  QStandardItem *childItem = 
new QStandardItem( itemName );
 
 2462  childItem->setData( 
id );
 
 2463  childItem->setData( itemName, GroupModelRoles::TagName );
 
 2464  parentItem->appendRow( childItem );
 
 
 2474  QStandardItemModel *model = qobject_cast<QStandardItemModel *>( groupTree->model() );
 
 2476  for ( 
int i = 0; i < groupTree->model()->rowCount(); i++ )
 
 2478    index = groupTree->model()->index( i, 0 );
 
 2479    QString data = index.data( Qt::UserRole + 1 ).toString();
 
 2480    if ( data == QLatin1String( 
"smartgroups" ) )
 
 2489  if ( dlg.exec() == QDialog::Rejected )
 
 2494  mBlockGroupUpdates++;
 
 2496  mBlockGroupUpdates--;
 
 2502  QStandardItem *parentItem = model->itemFromIndex( index );
 
 2503  QStandardItem *childItem = 
new QStandardItem( itemName );
 
 2504  childItem->setData( 
id );
 
 2505  parentItem->appendRow( childItem );
 
 
 2515  QStandardItemModel *model = qobject_cast<QStandardItemModel *>( groupTree->model() );
 
 2516  QModelIndex index = groupTree->currentIndex();
 
 2519  QString data = index.data( Qt::UserRole + 1 ).toString();
 
 2520  if ( data == QLatin1String( 
"all" ) || data == QLatin1String( 
"favorite" ) || data == QLatin1String( 
"tags" ) || index.data() == 
"smartgroups" )
 
 2523    int err = QMessageBox::critical( 
this, tr( 
"Remove Group" ), tr( 
"Invalid selection. Cannot delete system defined categories.\n" 
 2524                                                                     "Kindly select a group or smart group you might want to delete." ) );
 
 2529  QStandardItem *parentItem = model->itemFromIndex( index.parent() );
 
 2533  mBlockGroupUpdates++;
 
 2535  if ( parentItem->data( Qt::UserRole + 1 ).toString() == QLatin1String( 
"smartgroups" ) )
 
 2544  mBlockGroupUpdates--;
 
 2545  parentItem->removeRow( index.row() );
 
 
 2553  QgsDebugMsgLevel( QStringLiteral( 
"Symbol group edited: data=%1 text=%2" ).arg( item->data( Qt::UserRole + 1 ).toString(), item->text() ), 2 );
 
 2554  int id = item->data( Qt::UserRole + 1 ).toInt();
 
 2555  QString name = item->text();
 
 2556  mBlockGroupUpdates++;
 
 2557  if ( item->parent()->data( Qt::UserRole + 1 ) == 
"smartgroups" )
 
 2565  mBlockGroupUpdates--;
 
 
 2573  QStandardItemModel *treeModel = qobject_cast<QStandardItemModel *>( groupTree->model() );
 
 2575  if ( mGroupingMode )
 
 2577    mGroupingMode = 
false;
 
 2578    mModel->setCheckable( 
false );
 
 2579    actnTagSymbols->setVisible( 
true );
 
 2580    actnFinishTagging->setVisible( 
false );
 
 2591    listItems->setSelectionMode( QAbstractItemView::ExtendedSelection );
 
 2592    mSymbolTreeView->setSelectionMode( QAbstractItemView::ExtendedSelection );
 
 2596    bool validGroup = 
false;
 
 2598    QModelIndex present = groupTree->currentIndex();
 
 2599    while ( present.parent().isValid() )
 
 2601      if ( present.parent().data() == 
"Tags" )
 
 2606      present = present.parent();
 
 2611    mGroupingMode = 
true;
 
 2613    actnTagSymbols->setVisible( 
false );
 
 2614    actnFinishTagging->setVisible( 
true );
 
 2621    btnManageGroups->setEnabled( 
true );
 
 2623    mModel->setCheckable( 
true );
 
 2626    listItems->setSelectionMode( QAbstractItemView::NoSelection );
 
 2627    mSymbolTreeView->setSelectionMode( QAbstractItemView::NoSelection );
 
 
 2641  mModel->setFilterString( qword );
 
 
 2646  actnEditItem->setEnabled( index.isValid() && !mGroupingMode && !isReadOnly() );
 
 
 2651  Q_UNUSED( selected )
 
 2652  Q_UNUSED( deselected )
 
 2653  const bool nothingSelected = listItems->selectionModel()->selectedIndexes().empty();
 
 2654  const bool readOnly = isReadOnly();
 
 2655  actnRemoveItem->setDisabled( nothingSelected || readOnly );
 
 2656  actnAddFavorite->setDisabled( nothingSelected || readOnly );
 
 2657  actnRemoveFavorite->setDisabled( nothingSelected || readOnly );
 
 2658  mGroupListMenu->setDisabled( nothingSelected || readOnly );
 
 2659  actnDetag->setDisabled( nothingSelected || readOnly );
 
 2660  actnExportAsPNG->setDisabled( nothingSelected );
 
 2661  actnExportAsSVG->setDisabled( nothingSelected );
 
 2662  if ( mActionCopyToDefault )
 
 2663    mActionCopyToDefault->setDisabled( nothingSelected );
 
 2664  mCopyToDefaultButton->setDisabled( nothingSelected );
 
 2665  actnEditItem->setDisabled( nothingSelected || readOnly );
 
 
 2670  const bool readOnly = isReadOnly();
 
 2671  groupTree->setEnabled( enable );
 
 2672  btnAddTag->setEnabled( enable && !readOnly );
 
 2673  btnAddSmartgroup->setEnabled( enable && !readOnly );
 
 2674  actnAddTag->setEnabled( enable && !readOnly );
 
 2675  actnAddSmartgroup->setEnabled( enable && !readOnly );
 
 2676  actnRemoveGroup->setEnabled( enable && !readOnly );
 
 2677  btnManageGroups->setEnabled( !readOnly && ( enable || mGroupingMode ) ); 
 
 2678  searchBox->setEnabled( enable );
 
 
 2683  const bool readOnly = isReadOnly();
 
 2684  actnRemoveGroup->setEnabled( enable && !readOnly );
 
 2685  btnManageGroups->setEnabled( !readOnly && ( enable || mGroupingMode ) ); 
 
 
 2690  QStandardItemModel *treeModel = qobject_cast<QStandardItemModel *>( groupTree->model() );
 
 2691  for ( 
int i = 0; i < treeModel->rowCount(); i++ )
 
 2693    treeModel->item( i )->setEnabled( enable );
 
 2695    if ( treeModel->item( i )->data() == 
"smartgroups" )
 
 2697      for ( 
int j = 0; j < treeModel->item( i )->rowCount(); j++ )
 
 2699        treeModel->item( i )->child( j )->setEnabled( enable );
 
 2706  for ( 
int i = 0; i < symbolBtnsLayout->count(); i++ )
 
 2708    QWidget *w = symbolBtnsLayout->itemAt( i )->widget();
 
 2710      w->setEnabled( enable );
 
 2714  actnRemoveItem->setEnabled( enable );
 
 2715  actnEditItem->setEnabled( enable );
 
 2716  mActionCopyItem->setEnabled( enable );
 
 2717  mActionPasteItem->setEnabled( enable );
 
 
 2722  QPoint globalPos = groupTree->viewport()->mapToGlobal( point );
 
 2724  QModelIndex index = groupTree->indexAt( point );
 
 2725  if ( index.isValid() && !mGroupingMode )
 
 2726    mGroupTreeContextMenu->popup( globalPos );
 
 
 2731  QPoint globalPos = mSymbolViewStackedWidget->currentIndex() == 0
 
 2732                       ? listItems->viewport()->mapToGlobal( point )
 
 2733                       : mSymbolTreeView->viewport()->mapToGlobal( point );
 
 2736  mGroupListMenu->clear();
 
 2738  const QModelIndexList indices = listItems->selectionModel()->selectedRows();
 
 2740  if ( !isReadOnly() )
 
 2742    const QStringList currentTags = indices.count() == 1 ? indices.at( 0 ).data( 
static_cast<int>( 
QgsStyleModel::CustomRole::Tag ) ).toStringList() : QStringList();
 
 2743    QAction *a = 
nullptr;
 
 2744    QStringList tags = mStyle->
tags();
 
 2746    for ( 
const QString &tag : std::as_const( tags ) )
 
 2748      a = 
new QAction( tag, mGroupListMenu );
 
 2750      if ( indices.count() == 1 )
 
 2752        a->setCheckable( 
true );
 
 2753        a->setChecked( currentTags.contains( tag ) );
 
 2756      mGroupListMenu->addAction( a );
 
 2759    if ( tags.count() > 0 )
 
 2761      mGroupListMenu->addSeparator();
 
 2763    a = 
new QAction( tr( 
"Create New Tag…" ), mGroupListMenu );
 
 2764    connect( a, &QAction::triggered, 
this, [
this]( 
bool ) { 
tagSelectedSymbols( 
true ); } );
 
 2765    mGroupListMenu->addAction( a );
 
 2768  const QList<ItemDetails> items = selectedItems();
 
 2771  bool enablePaste = 
false;
 
 2779  mActionPasteItem->setEnabled( enablePaste );
 
 2781  mGroupMenu->popup( globalPos );
 
 
 2789  const QList<ItemDetails> items = selectedItems();
 
 2790  for ( 
const ItemDetails &details : items )
 
 2792    mStyle->
addFavorite( details.entityType, details.name );
 
 
 2801  const QList<ItemDetails> items = selectedItems();
 
 2802  for ( 
const ItemDetails &details : items )
 
 
 2810  QAction *selectedItem = qobject_cast<QAction *>( sender() );
 
 2813    const QList<ItemDetails> items = selectedItems();
 
 2823      tag = mStyle->
tag( 
id );
 
 2827      tag = selectedItem->data().toString();
 
 2830    for ( 
const ItemDetails &details : items )
 
 2832      mStyle->
tagSymbol( details.entityType, details.name, QStringList( tag ) );
 
 
 2842  QAction *selectedItem = qobject_cast<QAction *>( sender() );
 
 2846    const QList<ItemDetails> items = selectedItems();
 
 2847    for ( 
const ItemDetails &details : items )
 
 2849      mStyle->
detagSymbol( details.entityType, details.name );
 
 
 2859  QStandardItemModel *treeModel = qobject_cast<QStandardItemModel *>( groupTree->model() );
 
 2862  QModelIndex present = groupTree->currentIndex();
 
 2863  if ( present.parent().data( Qt::UserRole + 1 ) != 
"smartgroups" )
 
 2866    QMessageBox::critical( 
this, tr( 
"Edit Smart Group" ), tr( 
"You have not selected a Smart Group. Kindly select a Smart Group to edit." ) );
 
 2869  QStandardItem *item = treeModel->itemFromIndex( present );
 
 2877  if ( dlg.exec() == QDialog::Rejected )
 
 2880  mBlockGroupUpdates++;
 
 2883  mBlockGroupUpdates--;
 
 2886    mMessageBar->pushCritical( tr( 
"Edit Smart Group" ), tr( 
"There was an error while editing the smart group." ) );
 
 2890  item->setData( 
id );
 
 
GeometryType
The geometry types are used to group Qgis::WkbType in a coarse way.
 
static const double UI_SCALE_FACTOR
UI scaling factor.
 
A dialog for configuring a 3D symbol.
 
Abstract base class for 3D symbols that are used by VectorLayer3DRenderer objects.
 
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
 
static QgsStyleModel * defaultStyleModel()
Returns a shared QgsStyleModel containing the default style library (see QgsStyle::defaultStyle()).
 
static Qgs3DSymbolRegistry * symbol3DRegistry()
Returns registry of available 3D symbols.
 
static QString iconPath(const QString &iconFile)
Returns path to the desired icon file.
 
A dialog which allows users to modify the properties of a QgsColorBrewerColorRamp.
 
QgsColorBrewerColorRamp ramp
 
QDialogButtonBox * buttonBox() const
Returns a reference to the dialog's button box.
 
Color ramp utilising "Color Brewer" preset color schemes.
 
QgsColorBrewerColorRamp * clone() const override
Creates a clone of the color ramp.
 
static QString typeString()
Returns the string identifier for QgsColorBrewerColorRamp.
 
QString schemeName() const
Returns the name of the color brewer color scheme.
 
int colors() const
Returns the number of colors in the ramp.
 
Abstract base class for color ramps.
 
static QList< QPair< QString, QString > > rampTypes()
Returns a list of available ramp types, where the first value in each item is the QgsColorRamp::type(...
 
A dialog which allows users to modify the properties of a QgsCptCityColorRamp.
 
bool saveAsGradientRamp() const
Returns true if the ramp should be converted to a QgsGradientColorRamp.
 
QDialogButtonBox * buttonBox() const
Returns a reference to the dialog's button box.
 
A color ramp from the CPT City collection.
 
QgsCptCityColorRamp * clone() const override
Creates a clone of the color ramp.
 
static QString typeString()
Returns the string identifier for QgsCptCityColorRamp.
 
QgsGradientColorRamp * cloneGradientRamp() const
 
QString schemeName() const
 
QString variantName() const
 
static QString ensureFileNameHasExtension(const QString &fileName, const QStringList &extensions)
Ensures that a fileName ends with an extension from the provided list of extensions.
 
A fill symbol type, for rendering Polygon and MultiPolygon geometries.
 
A dialog which allows users to modify the properties of a QgsGradientColorRamp.
 
QDialogButtonBox * buttonBox() const
Returns a reference to the dialog's button box.
 
QgsGradientColorRamp ramp
 
Gradient color ramp, which smoothly interpolates between two colors and also supports optional extra ...
 
static QString typeString()
Returns the string identifier for QgsGradientColorRamp.
 
QgsGradientColorRamp * clone() const override
Creates a clone of the color ramp.
 
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...
 
static void openHelp(const QString &key)
Opens help topic for the given help key using default system web browser.
 
static QIcon iconLine()
Returns an icon representing line geometries.
 
static QIcon iconPolygon()
Returns an icon representing polygon geometries.
 
static QIcon iconPoint()
Returns an icon representing point geometries.
 
A dialog for configuring a custom legend patch shape.
 
Represents a patch shape for use in map legends.
 
bool isNull() const
Returns true if the patch shape is a null QgsLegendPatchShape, which indicates that the default legen...
 
A dialog which allows users to modify the properties of a QgsLimitedRandomColorRamp.
 
QDialogButtonBox * buttonBox() const
Returns a reference to the dialog's button box.
 
QgsLimitedRandomColorRamp ramp
 
Constrained random color ramp, which returns random colors based on preset parameters.
 
static QString typeString()
Returns the string identifier for QgsLimitedRandomColorRamp.
 
QgsLimitedRandomColorRamp * clone() const override
Creates a clone of the color ramp.
 
A line symbol type, for rendering LineString and MultiLineString geometries.
 
A marker symbol type, for rendering Point and MultiPoint geometries.
 
A bar for displaying non-blocking messages to the user.
 
Contains settings for how a map layer will be labeled.
 
Qgis::GeometryType layerType
Geometry type of layers associated with these settings.
 
const QgsTextFormat & format() const
Returns the label text formatting settings, e.g., font settings, buffer settings, etc.
 
A dialog which allows users to modify the properties of a QgsPresetSchemeColorRamp.
 
QDialogButtonBox * buttonBox() const
Returns a reference to the dialog's button box.
 
QgsPresetSchemeColorRamp ramp
 
A scheme based color ramp consisting of a list of predefined colors.
 
static QString typeString()
Returns the string identifier for QgsPresetSchemeColorRamp.
 
QgsPresetSchemeColorRamp * clone() const override
Creates a clone of the color ramp.
 
List model representing the style databases associated with a QgsProject.
 
void setShowDefaultStyle(bool show)
Sets whether the default style should also be included in the model.
 
QModelIndex indexFromStyle(QgsStyle *style) const
Returns the model index corresponding to a style.
 
QgsStyle * styleFromIndex(const QModelIndex &index) const
Returns the style at the corresponding index.
 
void addStyleDatabasePath(const QString &path)
Adds a style database path to the project.
 
static QgsProject * instance()
Returns the QgsProject singleton instance.
 
const QgsProjectStyleSettings * styleSettings() const
Returns the project's style settings, which contains settings and properties relating to how a QgsPro...
 
Stores properties relating to a screen.
 
T value(const QString &dynamicKeyPart=QString()) const
Returns settings value.
 
bool setValue(const T &value, const QString &dynamicKeyPart=QString()) const
Set settings value.
 
Stores settings for use within QGIS.
 
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
 
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
 
A dialog for configuring a style smart group.
 
void setConditionMap(const QgsSmartConditionMap &)
sets up the GUI for the given conditionmap
 
QgsSmartConditionMap conditionMap()
returns the condition map
 
QString smartgroupName()
returns the value from mNameLineEdit
 
void setSmartgroupName(const QString &)
sets the smart group Name
 
void setOperator(const QString &)
sets the operator AND/OR
 
QString conditionOperator()
returns the AND/OR condition
 
A dialog allowing importing and exporting of entities from a QgsStyle.
 
@ Export
Export existing symbols mode.
 
@ Import
Import xml file mode.
 
Q_DECL_DEPRECATED bool removeSymbol()
 
void onClose()
Closes the dialog.
 
void groupRenamed(QStandardItem *item)
Triggered when a group item is renamed.
 
static const QgsSettingsEntryString * settingLastStyleDatabaseFolder
Last used folder for generic style database actions.
 
void addFavoriteSelectedSymbols()
Add selected symbols to favorites.
 
void selectedSymbolsChanged(const QItemSelection &selected, const QItemSelection &deselected)
Perform tasks when the selected symbols change.
 
void removeGroup()
Removes the selected tag or smartgroup.
 
void exportItems()
Triggers the dialog to export items.
 
void setFavoritesGroupVisible(bool show)
Sets whether the favorites group should be shown.
 
void grouptreeContextMenu(QPoint)
Context menu for the groupTree.
 
void setBold(QStandardItem *)
sets the text of the item with bold font
 
void filterSymbols(const QString &filter)
Sets the filter string to filter symbols by.
 
void addItem()
Triggers the dialog for adding a new item, based on the currently selected item type tab.
 
void tagSymbolsAction()
Toggles the interactive item tagging mode.
 
void editSmartgroupAction()
Triggers the dialog for editing the selected smart group.
 
void showHelp()
Opens the associated help.
 
void detagSelectedSymbols()
Remove all tags from selected symbols.
 
void enableSymbolInputs(bool)
Enables or disbables the symbol specific inputs.
 
bool addSymbol(int symbolType=-1)
add a new symbol to style
 
Q_DECL_DEPRECATED void populateTypes()
Populate combo box with known style items (symbols, color ramps).
 
void populateList()
Refreshes the list of items.
 
void removeItem()
Removes the current selected item.
 
void groupChanged(const QModelIndex &)
Triggered when the current group (or tag) is changed.
 
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.
 
void enableGroupInputs(bool)
Enables or disables the groupTree specific inputs.
 
int addTag()
Triggers the dialog to add a new tag.
 
void exportItemsSVG()
Triggers the dialog to export selected items as SVG files.
 
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.
 
void populateGroups()
populate the groups
 
Q_DECL_DEPRECATED bool removeColorRamp()
 
void importItems()
Triggers the dialog to import items.
 
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 ...
 
Q_DECL_DEPRECATED void regrouped(QStandardItem *)
 
Q_DECL_DEPRECATED void itemChanged(QStandardItem *item)
 
void exportItemsPNG()
Triggers the dialog to export selected items as PNG files.
 
void activate()
Raises, unminimizes and activates this window.
 
bool addColorRamp(const QString &type=QString())
Triggers adding a new color ramp.
 
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.
 
void enableItemsForGroupingMode(bool)
Enables or disables the groupTree items for grouping mode.
 
Q_DECL_DEPRECATED void setSymbolsChecked(const QStringList &)
 
void onFinished()
Called when the dialog is going to be closed.
 
void listitemsContextMenu(QPoint)
Context menu for the listItems ( symbols list )
 
void setSmartGroupsVisible(bool show)
Sets whether smart groups should be shown.
 
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.
 
void symbolSelected(const QModelIndex &)
Perform symbol specific tasks when selected.
 
void editItem()
Triggers the dialog for editing the current item.
 
void removeFavoriteSelectedSymbols()
Remove selected symbols from favorites.
 
int addSmartgroup()
Triggers the dialog to add a new smart group.
 
void tagSelectedSymbols(bool newTag=false)
Tag selected symbols using menu item selection.
 
QString currentItemName()
 
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.
 
A QAbstractItemModel subclass for showing symbol and color ramp entities contained within a QgsStyle ...
 
@ SymbolType
Symbol type (for symbol or legend patch shape entities)
 
@ Type
Style entity type, see QgsStyle::StyleEntity.
 
@ Tag
String list of tags.
 
A QSortFilterProxyModel subclass for showing filtered symbol and color ramps entries from a QgsStyle ...
 
A dialog for setting properties of a newly saved style.
 
bool isFavorite() const
Returns true if the favorite is checked for the symbol.
 
QString name() const
Returns the entered name for the new symbol.
 
void setDefaultTags(const QString &tags)
Sets the default tags for the newly created item.
 
QString tags() const
Returns any tags entered for the new symbol (as a comma separated value list).
 
A database of saved style entities, including symbols, color ramps, text formats and others.
 
bool detagSymbol(StyleEntity type, const QString &symbol, const QStringList &tags)
Detags the symbol with the given list.
 
QgsTextFormat textFormat(const QString &name) const
Returns the text format with the specified name.
 
QgsLegendPatchShape defaultPatch(Qgis::SymbolType type, QSizeF size) const
Returns the default legend patch shape for the given symbol type.
 
bool remove(StyleEntity type, int id)
Removes the specified entity from the database.
 
bool removeSymbol(const QString &name)
Removes symbol from style (and delete it)
 
bool removeLabelSettings(const QString &name)
Removes label settings from the style.
 
QStringList tags() const
Returns a list of all tags in the style database.
 
QString tag(int id) const
Returns the tag name for the given id.
 
QgsSmartConditionMap smartgroup(int id)
Returns the QgsSmartConditionMap for the given id.
 
QStringList symbol3DNames() const
Returns a list of names of 3d symbols in the style.
 
bool tagSymbol(StyleEntity type, const QString &symbol, const QStringList &tags)
Tags the symbol with the tags in the list.
 
bool saveLabelSettings(const QString &name, const QgsPalLayerSettings &settings, bool favorite, const QStringList &tags)
Adds label settings to the database.
 
void aboutToBeDestroyed()
Emitted just before the style object is destroyed.
 
bool createDatabase(const QString &filename)
Creates an on-disk database.
 
QStringList textFormatNames() const
Returns a list of names of text formats in the style.
 
bool addColorRamp(const QString &name, QgsColorRamp *colorRamp, bool update=false)
Adds a color ramp to the style.
 
bool removeTextFormat(const QString &name)
Removes a text format from the style.
 
QgsSymbol * symbol(const QString &name)
Returns a NEW copy of symbol.
 
StyleEntity
Enum for Entities involved in a style.
 
@ LabelSettingsEntity
Label settings.
 
@ TextFormatEntity
Text formats.
 
@ SmartgroupEntity
Smart groups.
 
@ Symbol3DEntity
3D symbol entity
 
@ ColorrampEntity
Color ramps.
 
@ LegendPatchShapeEntity
Legend patch shape.
 
QStringList tagsOfSymbol(StyleEntity type, const QString &symbol)
Returns the tags associated with the symbol.
 
void groupsModified()
Emitted every time a tag or smartgroup has been added, removed, or renamed.
 
int addSmartgroup(const QString &name, const QString &op, const QgsSmartConditionMap &conditions)
Adds a new smartgroup to the database and returns the id.
 
QStringList colorRampNames() const
Returns a list of names of color ramps.
 
bool addSymbol3D(const QString &name, QgsAbstract3DSymbol *symbol, bool update=false)
Adds a 3d symbol with the specified name to the style.
 
QStringList legendPatchShapeNames() const
Returns a list of names of legend patch shapes in the style.
 
void symbolSaved(const QString &name, const QgsSymbol *symbol)
Emitted every time a new symbol has been added to the database.
 
bool removeEntityByName(StyleEntity type, const QString &name)
Removes the entry of the specified type with matching name from the database.
 
int tagId(const QString &tag)
Returns the database id for the given tag name.
 
bool isReadOnly() const
Returns true if the style is considered a read-only library.
 
bool addLegendPatchShape(const QString &name, const QgsLegendPatchShape &shape, bool update=false)
Adds a legend patch shape with the specified name to the style.
 
QgsColorRamp * colorRamp(const QString &name) const
Returns a new copy of the specified color ramp.
 
static QgsStyle * defaultStyle(bool initialize=true)
Returns the default application-wide style.
 
bool saveSymbol(const QString &name, const QgsSymbol *symbol, bool favorite, const QStringList &tags)
Adds the symbol to the database with tags.
 
QStringList labelSettingsNames() const
Returns a list of names of label settings in the style.
 
bool rename(StyleEntity type, int id, const QString &newName)
Renames the given entity with the specified id.
 
bool removeFavorite(StyleEntity type, const QString &name)
Removes the specified symbol from favorites.
 
QgsSymbolGroupMap smartgroupsListMap()
Returns the smart groups map with id as key and name as value.
 
bool saveLegendPatchShape(const QString &name, const QgsLegendPatchShape &shape, bool favorite, const QStringList &tags)
Adds a legend patch shape to the database.
 
bool addTextFormat(const QString &name, const QgsTextFormat &format, bool update=false)
Adds a text format with the specified name to the style.
 
bool saveColorRamp(const QString &name, const QgsColorRamp *ramp, bool favorite, const QStringList &tags)
Adds the colorramp to the database.
 
QStringList symbolsOfFavorite(StyleEntity type) const
Returns the symbol names which are flagged as favorite.
 
bool saveSymbol3D(const QString &name, QgsAbstract3DSymbol *symbol, bool favorite, const QStringList &tags)
Adds a 3d symbol to the database.
 
QgsPalLayerSettings labelSettings(const QString &name) const
Returns the label settings with the specified name.
 
QgsAbstract3DSymbol * symbol3D(const QString &name) const
Returns a new copy of the 3D symbol with the specified name.
 
int addTag(const QString &tagName)
Adds a new tag and returns the tag's id.
 
bool addSymbol(const QString &name, QgsSymbol *symbol, bool update=false)
Adds a symbol to style and takes symbol's ownership.
 
QgsLegendPatchShape legendPatchShape(const QString &name) const
Returns the legend patch shape with the specified name.
 
QStringList symbolNames() const
Returns a list of names of symbols.
 
bool addFavorite(StyleEntity type, const QString &name)
Adds the specified symbol to favorites.
 
QString smartgroupOperator(int id)
Returns the operator for the smartgroup.
 
bool saveTextFormat(const QString &name, const QgsTextFormat &format, bool favorite, const QStringList &tags)
Adds a text format to the database.
 
bool addLabelSettings(const QString &name, const QgsPalLayerSettings &settings, bool update=false)
Adds label settings with the specified name to the style.
 
static std::unique_ptr< QgsSymbol > symbolFromMimeData(const QMimeData *data)
Attempts to parse mime data as a symbol.
 
static QMimeData * symbolToMimeData(const QgsSymbol *symbol)
Creates new mime data from a symbol.
 
A dialog that can be used to select and build a symbol.
 
QDialogButtonBox * buttonBox() const
Returns a reference to the dialog's button box.
 
Abstract base class for all rendered symbols.
 
Temporarily sets a cursor override for the QApplication for the lifetime of the object.
 
A simple dialog for customizing text formatting settings.
 
Container for all settings relating to text rendering.
 
static QgsTextFormat fromMimeData(const QMimeData *data, bool *ok=nullptr)
Attempts to parse the provided mime data as a QgsTextFormat.
 
QMultiMap< QString, QString > QgsSmartConditionMap
A multimap to hold the smart group conditions as constraint and parameter pairs.
 
QSize iconSize(bool dockableToolbar)
Returns the user-preferred size of a window's toolbar icons.
 
#define QgsDebugMsgLevel(str, level)
 
#define QgsDebugError(str)
 
QMap< int, QString > QgsSymbolGroupMap