42 #include <QFileDialog>
43 #include <QInputDialog>
44 #include <QMessageBox>
45 #include <QPushButton>
46 #include <QStandardItemModel>
58 QgsCheckableStyleModel::QgsCheckableStyleModel(
QgsStyleModel *sourceModel, QObject *parent,
bool readOnly )
60 , mStyle( sourceModel->style() )
61 , mReadOnly( readOnly )
66 QgsCheckableStyleModel::QgsCheckableStyleModel(
QgsStyle *style, QObject *parent,
bool readOnly )
69 , mReadOnly( readOnly )
73 void QgsCheckableStyleModel::setCheckable(
bool checkable )
75 if ( checkable == mCheckable )
78 mCheckable = checkable;
79 emit dataChanged( index( 0, 0 ), index( rowCount() - 1, 0 ), QVector< int >() << Qt::CheckStateRole );
82 void QgsCheckableStyleModel::setCheckTag(
const QString &tag )
84 if ( tag == mCheckTag )
88 emit dataChanged( index( 0, 0 ), index( rowCount() - 1, 0 ), QVector< int >() << Qt::CheckStateRole );
91 Qt::ItemFlags QgsCheckableStyleModel::flags(
const QModelIndex &index )
const
93 Qt::ItemFlags f = QgsStyleProxyModel::flags( index );
94 if ( !mReadOnly && mCheckable && index.column() == 0 )
95 f |= Qt::ItemIsUserCheckable;
98 f &= ~Qt::ItemIsEditable;
103 QVariant QgsCheckableStyleModel::data(
const QModelIndex &index,
int role )
const
110 QFont f = QgsStyleProxyModel::data( index, role ).value< QFont >();
115 case Qt::CheckStateRole:
117 if ( !mCheckable || index.column() != 0 )
121 return tags.contains( mCheckTag ) ? Qt::Checked : Qt::Unchecked;
128 return QgsStyleProxyModel::data( index, role );
131 bool QgsCheckableStyleModel::setData(
const QModelIndex &i,
const QVariant &value,
int role )
133 if ( i.row() < 0 || i.row() >= rowCount( QModelIndex() ) ||
134 ( role != Qt::EditRole && role != Qt::CheckStateRole ) )
140 if ( role == Qt::CheckStateRole )
142 if ( !mCheckable || mCheckTag.isEmpty() )
145 const QString name = data( index( i.row(),
QgsStyleModel::Name ), Qt::DisplayRole ).toString();
148 if ( value.toInt() == Qt::Checked )
149 return mStyle->tagSymbol( entity, name, QStringList() << mCheckTag );
151 return mStyle->detagSymbol( entity, name, QStringList() << mCheckTag );
153 return QgsStyleProxyModel::setData( i, value, role );
164 : QDialog( parent, flags )
166 , mReadOnly( readOnly )
170 connect( tabItemType, &QTabWidget::currentChanged,
this, &QgsStyleManagerDialog::tabItemType_currentChanged );
175 mMessageBar->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed );
176 mVerticalLayout->insertWidget( 0, mMessageBar );
179 setWindowModality( Qt::WindowModal );
184 mSplitter->setSizes( QList<int>() << 170 << 540 );
185 mSplitter->restoreState( settings.
value( QStringLiteral(
"Windows/StyleV2Manager/splitter" ) ).toByteArray() );
187 tabItemType->setDocumentMode(
true );
188 searchBox->setShowSearchIcon(
true );
189 searchBox->setPlaceholderText( tr(
"Filter symbols…" ) );
193 connect( btnEditItem, &QPushButton::clicked,
this, [ = ](
bool ) {
editItem(); }
195 connect( actnEditItem, &QAction::triggered,
this, [ = ](
bool ) {
editItem(); }
200 connect( btnAddItem, &QPushButton::clicked,
this, [ = ](
bool ) {
addItem(); }
203 connect( btnRemoveItem, &QPushButton::clicked,
this, [ = ](
bool ) {
removeItem(); }
205 connect( actnRemoveItem, &QAction::triggered,
this, [ = ](
bool ) {
removeItem(); }
210 btnAddTag->setEnabled(
false );
211 btnAddSmartgroup->setEnabled(
false );
214 QMenu *shareMenu =
new QMenu( tr(
"Share Menu" ),
this );
215 QAction *exportAction =
new QAction( tr(
"Export Item(s)…" ),
this );
217 shareMenu->addAction( exportAction );
220 QAction *importAction =
new QAction( tr(
"Import Item(s)…" ),
this );
222 shareMenu->addAction( importAction );
227 mActionCopyToDefault =
new QAction( tr(
"Copy Selection to Default Style…" ),
this );
228 shareMenu->addAction( mActionCopyToDefault );
229 connect( mActionCopyToDefault, &QAction::triggered,
this, &QgsStyleManagerDialog::copyItemsToDefault );
230 connect( mCopyToDefaultButton, &QPushButton::clicked,
this, &QgsStyleManagerDialog::copyItemsToDefault );
234 mCopyToDefaultButton->hide();
237 mActionCopyItem =
new QAction( tr(
"Copy Item" ),
this );
238 connect( mActionCopyItem, &QAction::triggered,
this, &QgsStyleManagerDialog::copyItem );
239 mActionPasteItem =
new QAction( tr(
"Paste Item…" ),
this );
240 connect( mActionPasteItem, &QAction::triggered,
this, &QgsStyleManagerDialog::pasteItem );
242 shareMenu->addSeparator();
243 shareMenu->addAction( actnExportAsPNG );
244 shareMenu->addAction( actnExportAsSVG );
249 btnShare->setMenu( shareMenu );
251 #if QT_VERSION < QT_VERSION_CHECK(5, 11, 0)
256 listItems->setIconSize( QSize(
static_cast< int >(
iconSize ),
static_cast< int >(
iconSize * 0.9 ) ) );
257 #if QT_VERSION < QT_VERSION_CHECK(5, 11, 0)
262 mSymbolTreeView->setIconSize( QSize(
static_cast< int >( treeIconSize ),
static_cast< int >( treeIconSize ) ) );
265 :
new QgsCheckableStyleModel( mStyle,
this, mReadOnly );
266 mModel->addDesiredIconSize( listItems->iconSize() );
267 mModel->addDesiredIconSize( mSymbolTreeView->iconSize() );
268 listItems->setModel( mModel );
269 mSymbolTreeView->setModel( mModel );
271 listItems->setSelectionBehavior( QAbstractItemView::SelectRows );
272 listItems->setSelectionMode( QAbstractItemView::ExtendedSelection );
273 mSymbolTreeView->setSelectionModel( listItems->selectionModel() );
274 mSymbolTreeView->setSelectionMode( listItems->selectionMode() );
276 connect( listItems->selectionModel(), &QItemSelectionModel::currentChanged,
278 connect( listItems->selectionModel(), &QItemSelectionModel::selectionChanged,
281 QStandardItemModel *groupModel =
new QStandardItemModel( groupTree );
282 groupTree->setModel( groupModel );
283 groupTree->setHeaderHidden(
true );
285 groupTree->setCurrentIndex( groupTree->model()->index( 0, 0 ) );
287 connect( groupTree->selectionModel(), &QItemSelectionModel::currentChanged,
291 connect( groupModel, &QStandardItemModel::itemChanged,
297 QMenu *groupMenu =
new QMenu( tr(
"Group Actions" ),
this );
299 groupMenu->addAction( actnTagSymbols );
301 actnFinishTagging->setVisible(
false );
302 groupMenu->addAction( actnFinishTagging );
303 groupMenu->addAction( actnEditSmartGroup );
304 btnManageGroups->setMenu( groupMenu );
308 btnManageGroups->setEnabled(
false );
314 groupTree->setContextMenuPolicy( Qt::CustomContextMenu );
315 connect( groupTree, &QWidget::customContextMenuRequested,
319 listItems->setContextMenuPolicy( Qt::CustomContextMenu );
320 connect( listItems, &QWidget::customContextMenuRequested,
322 mSymbolTreeView->setContextMenuPolicy( Qt::CustomContextMenu );
323 connect( mSymbolTreeView, &QWidget::customContextMenuRequested,
328 mMenuBtnAddItemAll =
new QMenu(
this );
329 mMenuBtnAddItemColorRamp =
new QMenu(
this );
330 mMenuBtnAddItemLabelSettings =
new QMenu(
this );
331 mMenuBtnAddItemLegendPatchShape =
new QMenu(
this );
332 mMenuBtnAddItemSymbol3D =
new QMenu(
this );
336 mMenuBtnAddItemAll->addAction( item );
339 mMenuBtnAddItemAll->addAction( item );
342 mMenuBtnAddItemAll->addAction( item );
343 mMenuBtnAddItemAll->addSeparator();
346 for (
const QPair< QString, QString > &rampType : rampTypes )
348 item =
new QAction(
QgsApplication::getThemeIcon( QStringLiteral(
"styleicons/color.svg" ) ), tr(
"%1…" ).arg( rampType.second ),
this );
349 connect( item, &QAction::triggered,
this, [ = ](
bool ) {
addColorRamp( rampType.first ); } );
350 mMenuBtnAddItemAll->addAction( item );
351 mMenuBtnAddItemColorRamp->addAction( item );
353 mMenuBtnAddItemAll->addSeparator();
355 connect( item, &QAction::triggered,
this, [ = ](
bool ) { addTextFormat(); } );
356 mMenuBtnAddItemAll->addAction( item );
357 mMenuBtnAddItemAll->addSeparator();
360 mMenuBtnAddItemAll->addAction( item );
361 mMenuBtnAddItemLabelSettings->addAction( item );
364 mMenuBtnAddItemAll->addAction( item );
365 mMenuBtnAddItemLabelSettings->addAction( item );
368 mMenuBtnAddItemAll->addAction( item );
369 mMenuBtnAddItemLabelSettings->addAction( item );
371 mMenuBtnAddItemAll->addSeparator();
373 connect( item, &QAction::triggered,
this, [ = ](
bool ) { addLegendPatchShape(
QgsSymbol::Marker ); } );
374 mMenuBtnAddItemAll->addAction( item );
375 mMenuBtnAddItemLegendPatchShape->addAction( item );
377 connect( item, &QAction::triggered,
this, [ = ](
bool ) { addLegendPatchShape(
QgsSymbol::Line ); } );
378 mMenuBtnAddItemAll->addAction( item );
379 mMenuBtnAddItemLegendPatchShape->addAction( item );
381 connect( item, &QAction::triggered,
this, [ = ](
bool ) { addLegendPatchShape(
QgsSymbol::Fill ); } );
382 mMenuBtnAddItemAll->addAction( item );
383 mMenuBtnAddItemLegendPatchShape->addAction( item );
385 mMenuBtnAddItemAll->addSeparator();
387 connect( item, &QAction::triggered,
this, [ = ](
bool ) { addSymbol3D( QStringLiteral(
"point" ) ); } );
388 mMenuBtnAddItemAll->addAction( item );
389 mMenuBtnAddItemSymbol3D->addAction( item );
391 connect( item, &QAction::triggered,
this, [ = ](
bool ) { addSymbol3D( QStringLiteral(
"line" ) ); } );
392 mMenuBtnAddItemAll->addAction( item );
393 mMenuBtnAddItemSymbol3D->addAction( item );
395 connect( item, &QAction::triggered,
this, [ = ](
bool ) { addSymbol3D( QStringLiteral(
"polygon" ) ); } );
396 mMenuBtnAddItemAll->addAction( item );
397 mMenuBtnAddItemSymbol3D->addAction( item );
401 mGroupMenu =
new QMenu(
this );
402 mGroupListMenu =
new QMenu( mGroupMenu );
403 mGroupListMenu->setTitle( tr(
"Add to Tag" ) );
404 mGroupListMenu->setEnabled(
false );
408 mGroupMenu->addAction( actnAddFavorite );
410 mGroupMenu->addAction( actnRemoveFavorite );
411 mGroupMenu->addSeparator()->setParent(
this );
412 mGroupMenu->addMenu( mGroupListMenu );
413 actnDetag->setData( 0 );
415 mGroupMenu->addAction( actnDetag );
416 mGroupMenu->addSeparator()->setParent(
this );
417 mGroupMenu->addAction( actnRemoveItem );
418 mGroupMenu->addAction( actnEditItem );
419 mGroupMenu->addAction( mActionCopyItem );
420 mGroupMenu->addAction( mActionPasteItem );
421 mGroupMenu->addSeparator()->setParent(
this );
425 btnAddItem->setVisible(
false );
426 btnRemoveItem->setVisible(
false );
427 btnEditItem->setVisible(
false );
428 btnAddSmartgroup->setVisible(
false );
429 btnAddTag->setVisible(
false );
430 btnManageGroups->setVisible(
false );
432 mGroupMenu->addAction( mActionCopyItem );
434 if ( mActionCopyToDefault )
436 mGroupMenu->addAction( mActionCopyToDefault );
438 mGroupMenu->addAction( actnExportAsPNG );
439 mGroupMenu->addAction( actnExportAsSVG );
442 mGroupTreeContextMenu =
new QMenu(
this );
446 mGroupTreeContextMenu->addAction( actnEditSmartGroup );
447 connect( actnAddTag, &QAction::triggered,
this, [ = ](
bool ) {
addTag(); }
449 mGroupTreeContextMenu->addAction( actnAddTag );
450 connect( actnAddSmartgroup, &QAction::triggered,
this, [ = ](
bool ) {
addSmartgroup(); }
452 mGroupTreeContextMenu->addAction( actnAddSmartgroup );
454 mGroupTreeContextMenu->addAction( actnRemoveGroup );
457 tabItemType_currentChanged( 0 );
462 connect( mButtonIconView, &QToolButton::toggled,
this, [ = ](
bool active )
466 mSymbolViewStackedWidget->setCurrentIndex( 0 );
471 connect( mButtonListView, &QToolButton::toggled,
this, [ = ](
bool active )
476 mSymbolViewStackedWidget->setCurrentIndex( 1 );
480 const int currentView = settings.
value( QStringLiteral(
"Windows/StyleV2Manager/lastIconView" ), 0,
QgsSettings::Gui ).toInt();
481 if ( currentView == 0 )
482 mButtonIconView->setChecked(
true );
484 mButtonListView->setChecked(
true );
486 mSymbolTreeView->header()->restoreState( settings.
value( QStringLiteral(
"Windows/StyleV2Manager/treeState" ), QByteArray(),
QgsSettings::Gui ).toByteArray() );
487 connect( mSymbolTreeView->header(), &QHeaderView::sectionResized,
this, [
this]
490 QgsSettings().setValue( QStringLiteral(
"Windows/StyleV2Manager/treeState" ), mSymbolTreeView->header()->saveState(), QgsSettings::Gui );
499 if ( mModified && !mReadOnly )
505 settings.
setValue( QStringLiteral(
"Windows/StyleV2Manager/splitter" ), mSplitter->saveState() );
512 void QgsStyleManagerDialog::tabItemType_currentChanged(
int )
521 searchBox->setPlaceholderText( isSymbol ? tr(
"Filter symbols…" ) :
522 isColorRamp ? tr(
"Filter color ramps…" ) :
523 isTextFormat ? tr(
"Filter text symbols…" ) :
524 isLabelSettings ? tr(
"Filter label settings…" ) :
525 isLegendPatchShape ? tr(
"Filter legend patch shapes…" ) : tr(
"Filter 3D symbols…" ) );
527 if ( !mReadOnly && isColorRamp )
529 btnAddItem->setMenu( mMenuBtnAddItemColorRamp );
531 else if ( !mReadOnly && isLegendPatchShape )
533 btnAddItem->setMenu( mMenuBtnAddItemLegendPatchShape );
535 else if ( !mReadOnly && isSymbol3D )
537 btnAddItem->setMenu( mMenuBtnAddItemSymbol3D );
539 else if ( !mReadOnly && isLabelSettings )
541 btnAddItem->setMenu( mMenuBtnAddItemLabelSettings );
543 else if ( !mReadOnly && !isSymbol && !isColorRamp )
545 btnAddItem->setMenu(
nullptr );
547 else if ( !mReadOnly && tabItemType->currentIndex() == 0 )
549 btnAddItem->setMenu( mMenuBtnAddItemAll );
553 btnAddItem->setMenu(
nullptr );
556 actnExportAsPNG->setVisible( isSymbol );
557 actnExportAsSVG->setVisible( isSymbol );
560 mModel->setEntityFilterEnabled( !allTypesSelected() );
561 mModel->setSymbolTypeFilterEnabled( isSymbol && !allTypesSelected() );
562 if ( isSymbol && !allTypesSelected() )
568 void QgsStyleManagerDialog::copyItemsToDefault()
570 const QList< ItemDetails > items = selectedItems();
571 if ( !items.empty() )
575 if ( !mBaseName.isEmpty() )
576 options.append( mBaseName );
579 defaultTags.sort( Qt::CaseInsensitive );
580 options.append( defaultTags );
581 const QString tags = QInputDialog::getItem(
this, tr(
"Import Items" ),
582 tr(
"Additional tags to add (comma separated)" ), options, mBaseName.isEmpty() ? -1 : 0,
true, &ok );
586 const QStringList parts = tags.split(
',', QString::SkipEmptyParts );
587 QStringList additionalTags;
588 additionalTags.reserve( parts.count() );
589 for (
const QString &tag : parts )
590 additionalTags << tag.trimmed();
592 auto cursorOverride = qgis::make_unique< QgsTemporaryCursorOverride >( Qt::WaitCursor );
593 const int count = copyItems( items, mStyle,
QgsStyle::defaultStyle(),
this, cursorOverride,
true, additionalTags,
false,
false );
594 cursorOverride.reset();
597 mMessageBar->
pushSuccess( tr(
"Import Items" ), count > 1 ? tr(
"Successfully imported %1 items." ).arg( count ) : tr(
"Successfully imported item." ) );
602 void QgsStyleManagerDialog::copyItem()
604 const QList< ItemDetails > items = selectedItems();
608 ItemDetails details = items.at( 0 );
609 switch ( details.entityType )
613 std::unique_ptr< QgsSymbol > symbol( mStyle->
symbol( details.name ) );
623 QApplication::clipboard()->setMimeData( format.toMimeData() );
630 QApplication::clipboard()->setMimeData( format.toMimeData() );
644 void QgsStyleManagerDialog::pasteItem()
646 const QString defaultTag = groupTree->currentIndex().isValid() ? groupTree->currentIndex().data().toString() : QString();
650 QgsStyleSaveDialog saveDlg(
this );
651 saveDlg.setWindowTitle( tr(
"Paste Symbol" ) );
652 saveDlg.setDefaultTags( defaultTag );
653 if ( !saveDlg.exec() || saveDlg.name().isEmpty() )
656 if ( mStyle->
symbolNames().contains( saveDlg.name() ) )
658 int res = QMessageBox::warning(
this, tr(
"Paste Symbol" ),
659 tr(
"A symbol with the name '%1' already exists. Overwrite?" )
660 .arg( saveDlg.name() ),
661 QMessageBox::Yes | QMessageBox::No );
662 if ( res != QMessageBox::Yes )
669 QStringList symbolTags = saveDlg.tags().split(
',' );
671 mStyle->
addSymbol( saveDlg.name(), tempSymbol.release() );
673 mStyle->
saveSymbol( saveDlg.name(), newSymbol, saveDlg.isFavorite(), symbolTags );
682 saveDlg.setDefaultTags( defaultTag );
683 saveDlg.setWindowTitle( tr(
"Paste Text Format" ) );
684 if ( !saveDlg.exec() || saveDlg.name().isEmpty() )
689 int res = QMessageBox::warning(
this, tr(
"Paste Text Format" ),
690 tr(
"A format with the name '%1' already exists. Overwrite?" )
691 .arg( saveDlg.name() ),
692 QMessageBox::Yes | QMessageBox::No );
693 if ( res != QMessageBox::Yes )
700 QStringList symbolTags = saveDlg.tags().split(
',' );
703 mStyle->
saveTextFormat( saveDlg.name(), format, saveDlg.isFavorite(), symbolTags );
708 int QgsStyleManagerDialog::selectedItemType()
710 QModelIndex index = listItems->selectionModel()->currentIndex();
711 if ( !index.isValid() )
729 bool QgsStyleManagerDialog::allTypesSelected()
const
731 return tabItemType->currentIndex() == 0;
734 QList< QgsStyleManagerDialog::ItemDetails > QgsStyleManagerDialog::selectedItems()
736 QList<QgsStyleManagerDialog::ItemDetails > res;
737 QModelIndexList indices = listItems->selectionModel()->selectedRows();
738 for (
const QModelIndex &index : indices )
740 if ( !index.isValid() )
747 details.name = mModel->data( mModel->index( index.row(),
QgsStyleModel::Name, index.parent() ), Qt::DisplayRole ).toString();
754 int QgsStyleManagerDialog::copyItems(
const QList<QgsStyleManagerDialog::ItemDetails> &items,
QgsStyle *src,
QgsStyle *dst, QWidget *parentWidget,
755 std::unique_ptr< QgsTemporaryCursorOverride > &cursorOverride,
bool isImport,
const QStringList &importTags,
bool addToFavorites,
bool ignoreSourceTags )
758 bool overwriteAll =
true;
768 for (
auto &details : items )
770 QStringList symbolTags;
771 if ( !ignoreSourceTags )
773 symbolTags = src->
tagsOfSymbol( details.entityType, details.name );
776 bool addItemToFavorites =
false;
779 symbolTags << importTags;
780 addItemToFavorites = addToFavorites;
783 switch ( details.entityType )
787 std::unique_ptr< QgsSymbol > symbol( src->
symbol( details.name ) );
791 const bool hasDuplicateName = dst->
symbolNames().contains( details.name );
792 bool overwriteThis =
false;
794 addItemToFavorites = favoriteSymbols.contains( details.name );
796 if ( hasDuplicateName && prompt )
798 cursorOverride.reset();
799 int res = QMessageBox::warning( parentWidget, isImport ? tr(
"Import Symbol" ) : tr(
"Export Symbol" ),
800 tr(
"A symbol with the name “%1” already exists.\nOverwrite?" )
801 .arg( details.name ),
802 QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No | QMessageBox::NoToAll | QMessageBox::Cancel );
803 cursorOverride = qgis::make_unique< QgsTemporaryCursorOverride >( Qt::WaitCursor );
806 case QMessageBox::Cancel:
809 case QMessageBox::No:
812 case QMessageBox::Yes:
813 overwriteThis =
true;
816 case QMessageBox::YesToAll:
821 case QMessageBox::NoToAll:
823 overwriteAll =
false;
828 if ( !hasDuplicateName || overwriteAll || overwriteThis )
831 dst->
addSymbol( details.name, symbol.release() );
832 dst->
saveSymbol( details.name, newSymbol, addItemToFavorites, symbolTags );
840 std::unique_ptr< QgsColorRamp > ramp( src->
colorRamp( details.name ) );
844 const bool hasDuplicateName = dst->
colorRampNames().contains( details.name );
845 bool overwriteThis =
false;
847 addItemToFavorites = favoriteColorramps.contains( details.name );
849 if ( hasDuplicateName && prompt )
851 cursorOverride.reset();
852 int res = QMessageBox::warning( parentWidget, isImport ? tr(
"Import Color Ramp" ) : tr(
"Export Color Ramp" ),
853 tr(
"A color ramp with the name “%1” already exists.\nOverwrite?" )
854 .arg( details.name ),
855 QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No | QMessageBox::NoToAll | QMessageBox::Cancel );
856 cursorOverride = qgis::make_unique< QgsTemporaryCursorOverride >( Qt::WaitCursor );
859 case QMessageBox::Cancel:
862 case QMessageBox::No:
865 case QMessageBox::Yes:
866 overwriteThis =
true;
869 case QMessageBox::YesToAll:
874 case QMessageBox::NoToAll:
876 overwriteAll =
false;
881 if ( !hasDuplicateName || overwriteAll || overwriteThis )
885 dst->
saveColorRamp( details.name, newRamp, addItemToFavorites, symbolTags );
895 const bool hasDuplicateName = dst->
textFormatNames().contains( details.name );
896 bool overwriteThis =
false;
898 addItemToFavorites = favoriteTextFormats.contains( details.name );
900 if ( hasDuplicateName && prompt )
902 cursorOverride.reset();
903 int res = QMessageBox::warning( parentWidget, isImport ? tr(
"Import Text Format" ) : tr(
"Export Text Format" ),
904 tr(
"A text format with the name “%1” already exists.\nOverwrite?" )
905 .arg( details.name ),
906 QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No | QMessageBox::NoToAll | QMessageBox::Cancel );
907 cursorOverride = qgis::make_unique< QgsTemporaryCursorOverride >( Qt::WaitCursor );
910 case QMessageBox::Cancel:
913 case QMessageBox::No:
916 case QMessageBox::Yes:
917 overwriteThis =
true;
920 case QMessageBox::YesToAll:
925 case QMessageBox::NoToAll:
927 overwriteAll =
false;
932 if ( !hasDuplicateName || overwriteAll || overwriteThis )
935 dst->
saveTextFormat( details.name, format, addItemToFavorites, symbolTags );
946 bool overwriteThis =
false;
948 addItemToFavorites = favoriteLabelSettings.contains( details.name );
950 if ( hasDuplicateName && prompt )
952 cursorOverride.reset();
953 int res = QMessageBox::warning( parentWidget, isImport ? tr(
"Import Label Settings" ) : tr(
"Export Label Settings" ),
954 tr(
"Label settings with the name “%1” already exist.\nOverwrite?" )
955 .arg( details.name ),
956 QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No | QMessageBox::NoToAll | QMessageBox::Cancel );
957 cursorOverride = qgis::make_unique< QgsTemporaryCursorOverride >( Qt::WaitCursor );
960 case QMessageBox::Cancel:
963 case QMessageBox::No:
966 case QMessageBox::Yes:
967 overwriteThis =
true;
970 case QMessageBox::YesToAll:
975 case QMessageBox::NoToAll:
977 overwriteAll =
false;
982 if ( !hasDuplicateName || overwriteAll || overwriteThis )
985 dst->
saveLabelSettings( details.name, settings, addItemToFavorites, symbolTags );
996 bool overwriteThis =
false;
998 addItemToFavorites = favoriteLegendPatchShapes.contains( details.name );
1000 if ( hasDuplicateName && prompt )
1002 cursorOverride.reset();
1003 int res = QMessageBox::warning( parentWidget, isImport ? tr(
"Import Legend Patch Shape" ) : tr(
"Export Legend Patch Shape" ),
1004 tr(
"Legend patch shape with the name “%1” already exist.\nOverwrite?" )
1005 .arg( details.name ),
1006 QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No | QMessageBox::NoToAll | QMessageBox::Cancel );
1007 cursorOverride = qgis::make_unique< QgsTemporaryCursorOverride >( Qt::WaitCursor );
1010 case QMessageBox::Cancel:
1013 case QMessageBox::No:
1016 case QMessageBox::Yes:
1017 overwriteThis =
true;
1020 case QMessageBox::YesToAll:
1022 overwriteAll =
true;
1025 case QMessageBox::NoToAll:
1027 overwriteAll =
false;
1032 if ( !hasDuplicateName || overwriteAll || overwriteThis )
1043 std::unique_ptr< QgsAbstract3DSymbol > symbol( src->
symbol3D( details.name ) );
1047 const bool hasDuplicateName = dst->
symbol3DNames().contains( details.name );
1048 bool overwriteThis =
false;
1050 addItemToFavorites = favorite3dSymbols.contains( details.name );
1052 if ( hasDuplicateName && prompt )
1054 cursorOverride.reset();
1055 int res = QMessageBox::warning( parentWidget, isImport ? tr(
"Import 3D Symbol" ) : tr(
"Export 3D Symbol" ),
1056 tr(
"A 3D symbol with the name “%1” already exists.\nOverwrite?" )
1057 .arg( details.name ),
1058 QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No | QMessageBox::NoToAll | QMessageBox::Cancel );
1059 cursorOverride = qgis::make_unique< QgsTemporaryCursorOverride >( Qt::WaitCursor );
1062 case QMessageBox::Cancel:
1065 case QMessageBox::No:
1068 case QMessageBox::Yes:
1069 overwriteThis =
true;
1072 case QMessageBox::YesToAll:
1074 overwriteAll =
true;
1077 case QMessageBox::NoToAll:
1079 overwriteAll =
false;
1084 if ( !hasDuplicateName || overwriteAll || overwriteThis )
1087 dst->
addSymbol3D( details.name, symbol.release() );
1088 dst->
saveSymbol3D( details.name, newSymbol, addItemToFavorites, symbolTags );
1103 bool QgsStyleManagerDialog::addTextFormat()
1107 if ( !formatDlg.exec() )
1109 format = formatDlg.format();
1112 if ( !saveDlg.exec() )
1114 QString name = saveDlg.name();
1117 bool nameInvalid =
true;
1118 while ( nameInvalid )
1121 if ( name.isEmpty() )
1123 QMessageBox::warning(
this, tr(
"Save Text Format" ),
1124 tr(
"Cannot save text format without name. Enter a name." ) );
1128 int res = QMessageBox::warning(
this, tr(
"Save Text Format" ),
1129 tr(
"Text format with name '%1' already exists. Overwrite?" )
1131 QMessageBox::Yes | QMessageBox::No );
1132 if ( res == QMessageBox::Yes )
1135 nameInvalid =
false;
1141 nameInvalid =
false;
1146 name = QInputDialog::getText(
this, tr(
"Text Format Name" ),
1147 tr(
"Please enter a name for new text format:" ),
1148 QLineEdit::Normal, name, &ok );
1156 QStringList symbolTags = saveDlg.tags().split(
',' );
1160 mStyle->
saveTextFormat( name, format, saveDlg.isFavorite(), symbolTags );
1168 groupChanged( groupTree->selectionModel()->currentIndex() );
1181 switch ( tabItemType->currentIndex() )
1206 QModelIndex index = listItems->selectionModel()->currentIndex();
1207 if ( !index.isValid() )
1210 return mModel->data( mModel->index( index.row(),
QgsStyleModel::Name, index.parent() ), Qt::DisplayRole ).toString();
1215 bool changed =
false;
1226 changed = addTextFormat();
1245 Q_ASSERT(
false &&
"not implemented" );
1258 QString name = tr(
"new symbol" );
1263 name = tr(
"new marker" );
1267 name = tr(
"new line" );
1271 name = tr(
"new fill symbol" );
1274 Q_ASSERT(
false &&
"unknown symbol type" );
1284 if ( dlg.exec() == 0 )
1290 QgsStyleSaveDialog saveDlg(
this );
1291 if ( !saveDlg.exec() )
1297 name = saveDlg.name();
1300 bool nameInvalid =
true;
1301 while ( nameInvalid )
1304 if ( name.isEmpty() )
1306 QMessageBox::warning(
this, tr(
"Save Symbol" ),
1307 tr(
"Cannot save symbol without name. Enter a name." ) );
1309 else if ( mStyle->
symbolNames().contains( name ) )
1311 int res = QMessageBox::warning(
this, tr(
"Save Symbol" ),
1312 tr(
"Symbol with name '%1' already exists. Overwrite?" )
1314 QMessageBox::Yes | QMessageBox::No );
1315 if ( res == QMessageBox::Yes )
1318 nameInvalid =
false;
1324 nameInvalid =
false;
1329 name = QInputDialog::getText(
this, tr(
"Symbol Name" ),
1330 tr(
"Please enter a name for new symbol:" ),
1331 QLineEdit::Normal, name, &ok );
1340 QStringList symbolTags = saveDlg.tags().split(
',' );
1344 mStyle->
saveSymbol( name, symbol, saveDlg.isFavorite(), symbolTags );
1353 QString rampType = type;
1355 if ( rampType.isEmpty() )
1360 QStringList rampTypeNames;
1361 rampTypeNames.reserve( rampTypes.size() );
1362 for (
const QPair< QString, QString > &type : rampTypes )
1363 rampTypeNames << type.second;
1364 const QString selectedRampTypeName = QInputDialog::getItem( parent, tr(
"Color Ramp Type" ),
1365 tr(
"Please select color ramp type:" ), rampTypeNames, 0,
false, &ok );
1366 if ( !ok || selectedRampTypeName.isEmpty() )
1369 rampType = rampTypes.value( rampTypeNames.indexOf( selectedRampTypeName ) ).first;
1372 QString name = tr(
"new ramp" );
1374 std::unique_ptr< QgsColorRamp > ramp;
1383 name = tr(
"new gradient ramp" );
1393 name = tr(
"new random ramp" );
1413 name = tr(
"new preset ramp" );
1437 QgsDebugMsg( QStringLiteral(
"invalid ramp type %1" ).arg( rampType ) );
1442 if ( !saveDlg.exec() )
1447 name = saveDlg.name();
1450 bool nameInvalid =
true;
1451 while ( nameInvalid )
1454 if ( name.isEmpty() )
1456 QMessageBox::warning( parent, tr(
"Save Color Ramp" ),
1457 tr(
"Cannot save color ramp without name. Enter a name." ) );
1461 int res = QMessageBox::warning( parent, tr(
"Save Color Ramp" ),
1462 tr(
"Color ramp with name '%1' already exists. Overwrite?" )
1464 QMessageBox::Yes | QMessageBox::No );
1465 if ( res == QMessageBox::Yes )
1467 nameInvalid =
false;
1473 nameInvalid =
false;
1478 name = QInputDialog::getText( parent, tr(
"Color Ramp Name" ),
1479 tr(
"Please enter a name for new color ramp:" ),
1480 QLineEdit::Normal, name, &ok );
1488 QStringList colorRampTags = saveDlg.tags().split(
',' );
1493 style->
saveColorRamp( name, r, saveDlg.isFavorite(), colorRampTags );
1500 mFavoritesGroupVisible = show;
1506 mSmartGroupVisible = show;
1518 setWindowState( windowState() & ~Qt::WindowMinimized );
1526 if ( !rampName.isEmpty() )
1538 if ( selectedItemType() < 3 )
1542 else if ( selectedItemType() == 3 )
1546 else if ( selectedItemType() == 4 )
1550 else if ( selectedItemType() == 5 )
1552 editLabelSettings();
1554 else if ( selectedItemType() == 6 )
1556 editLegendPatchShape();
1558 else if ( selectedItemType() == 7 )
1564 Q_ASSERT(
false &&
"not implemented" );
1571 if ( symbolName.isEmpty() )
1574 std::unique_ptr< QgsSymbol > symbol( mStyle->
symbol( symbolName ) );
1579 dlg.
buttonBox()->button( QDialogButtonBox::Ok )->setEnabled(
false );
1585 mStyle->
addSymbol( symbolName, symbol.release(),
true );
1593 if ( name.isEmpty() )
1596 std::unique_ptr< QgsColorRamp > ramp( mStyle->
colorRamp( name ) );
1603 dlg.
buttonBox()->button( QDialogButtonBox::Ok )->setEnabled(
false );
1616 dlg.
buttonBox()->button( QDialogButtonBox::Ok )->setEnabled(
false );
1629 dlg.
buttonBox()->button( QDialogButtonBox::Ok )->setEnabled(
false );
1642 dlg.
buttonBox()->button( QDialogButtonBox::Ok )->setEnabled(
false );
1655 dlg.
buttonBox()->button( QDialogButtonBox::Ok )->setEnabled(
false );
1672 Q_ASSERT(
false &&
"invalid ramp type" );
1680 bool QgsStyleManagerDialog::editTextFormat()
1683 if ( formatName.isEmpty() )
1691 dlg.buttonBox()->button( QDialogButtonBox::Ok )->setEnabled(
false );
1705 QgsLabelSettingsDialog settingsDlg( settings,
nullptr,
nullptr,
this, type );
1707 settingsDlg.buttonBox()->button( QDialogButtonBox::Ok )->setEnabled(
false );
1709 if ( !settingsDlg.exec() )
1712 settings = settingsDlg.settings();
1716 if ( !saveDlg.exec() )
1718 QString name = saveDlg.name();
1721 bool nameInvalid =
true;
1722 while ( nameInvalid )
1725 if ( name.isEmpty() )
1727 QMessageBox::warning(
this, tr(
"Save Label Settings" ),
1728 tr(
"Cannot save label settings without a name. Enter a name." ) );
1732 int res = QMessageBox::warning(
this, tr(
"Save Label Settings" ),
1733 tr(
"Label settings with the name '%1' already exist. Overwrite?" )
1735 QMessageBox::Yes | QMessageBox::No );
1736 if ( res == QMessageBox::Yes )
1739 nameInvalid =
false;
1745 nameInvalid =
false;
1750 name = QInputDialog::getText(
this, tr(
"Label Settings Name" ),
1751 tr(
"Please enter a name for the new label settings:" ),
1752 QLineEdit::Normal, name, &ok );
1760 QStringList symbolTags = saveDlg.tags().split(
',' );
1770 bool QgsStyleManagerDialog::editLabelSettings()
1773 if ( formatName.isEmpty() )
1780 QgsLabelSettingsDialog dlg( settings,
nullptr,
nullptr,
this, geomType );
1784 settings = dlg.settings();
1798 dialog.buttonBox()->button( QDialogButtonBox::Ok )->setEnabled(
false );
1800 if ( !dialog.exec() )
1803 shape = dialog.shape();
1806 if ( !saveDlg.exec() )
1808 QString name = saveDlg.name();
1811 bool nameInvalid =
true;
1812 while ( nameInvalid )
1815 if ( name.isEmpty() )
1817 QMessageBox::warning(
this, tr(
"Save Legend Patch Shape" ),
1818 tr(
"Cannot save legend patch shapes without a name. Enter a name." ) );
1822 int res = QMessageBox::warning(
this, tr(
"Save Legend Patch Shape" ),
1823 tr(
"A legend patch shape with the name '%1' already exists. Overwrite?" )
1825 QMessageBox::Yes | QMessageBox::No );
1826 if ( res == QMessageBox::Yes )
1829 nameInvalid =
false;
1835 nameInvalid =
false;
1840 name = QInputDialog::getText(
this, tr(
"Legend Patch Shape Name" ),
1841 tr(
"Please enter a name for the new legend patch shape:" ),
1842 QLineEdit::Normal, name, &ok );
1850 QStringList symbolTags = saveDlg.tags().split(
',' );
1860 bool QgsStyleManagerDialog::editLegendPatchShape()
1863 if ( shapeName.isEmpty() )
1875 shape = dlg.shape();
1883 bool QgsStyleManagerDialog::addSymbol3D(
const QString &type )
1891 dialog.buttonBox()->button( QDialogButtonBox::Ok )->setEnabled(
false );
1893 if ( !dialog.exec() )
1896 symbol.reset( dialog.symbol() );
1901 if ( !saveDlg.exec() )
1903 QString name = saveDlg.name();
1906 bool nameInvalid =
true;
1907 while ( nameInvalid )
1910 if ( name.isEmpty() )
1912 QMessageBox::warning(
this, tr(
"Save 3D Symbol" ),
1913 tr(
"Cannot save 3D symbols without a name. Enter a name." ) );
1917 int res = QMessageBox::warning(
this, tr(
"Save 3D Symbol" ),
1918 tr(
"A 3D symbol with the name '%1' already exists. Overwrite?" )
1920 QMessageBox::Yes | QMessageBox::No );
1921 if ( res == QMessageBox::Yes )
1924 nameInvalid =
false;
1930 nameInvalid =
false;
1935 name = QInputDialog::getText(
this, tr(
"3D Symbol Name" ),
1936 tr(
"Please enter a name for the new 3D symbol:" ),
1937 QLineEdit::Normal, name, &ok );
1945 QStringList symbolTags = saveDlg.tags().split(
',' );
1950 mStyle->
saveSymbol3D( name, newSymbol, saveDlg.isFavorite(), symbolTags );
1956 bool QgsStyleManagerDialog::editSymbol3D()
1959 if ( symbolName.isEmpty() )
1962 std::unique_ptr< QgsAbstract3DSymbol > symbol( mStyle->
symbol3D( symbolName ) );
1971 symbol.reset( dlg.symbol() );
1976 mStyle->
addSymbol3D( symbolName, symbol.release(),
true );
1983 const QList< ItemDetails > items = selectedItems();
1985 if ( allTypesSelected() )
1987 if ( QMessageBox::Yes != QMessageBox::question(
this, tr(
"Remove Items" ),
1988 QString( tr(
"Do you really want to remove %n item(s)?",
nullptr, items.count() ) ),
1997 if ( QMessageBox::Yes != QMessageBox::question(
this, tr(
"Remove Symbol" ),
1998 QString( tr(
"Do you really want to remove %n symbol(s)?",
nullptr, items.count() ) ),
2005 if ( QMessageBox::Yes != QMessageBox::question(
this, tr(
"Remove Color Ramp" ),
2006 QString( tr(
"Do you really want to remove %n ramp(s)?",
nullptr, items.count() ) ),
2013 if ( QMessageBox::Yes != QMessageBox::question(
this, tr(
"Remove Text Formats" ),
2014 QString( tr(
"Do you really want to remove %n text format(s)?",
nullptr, items.count() ) ),
2021 if ( QMessageBox::Yes != QMessageBox::question(
this, tr(
"Remove Label Settings" ),
2022 QString( tr(
"Do you really want to remove %n label settings?",
nullptr, items.count() ) ),
2029 if ( QMessageBox::Yes != QMessageBox::question(
this, tr(
"Remove Legend Patch Shapes" ),
2030 QString( tr(
"Do you really want to remove %n legend patch shapes?",
nullptr, items.count() ) ),
2037 if ( QMessageBox::Yes != QMessageBox::question(
this, tr(
"Remove 3D Symbols" ),
2038 QString( tr(
"Do you really want to remove %n 3D symbols?",
nullptr, items.count() ) ),
2047 for (
const ItemDetails &details : items )
2049 if ( details.name.isEmpty() )
2074 QString dir = QFileDialog::getExistingDirectory(
this, tr(
"Export Selected Symbols as PNG" ),
2075 QDir::home().absolutePath(),
2076 QFileDialog::ShowDirsOnly
2077 | QFileDialog::DontResolveSymlinks );
2083 QString dir = QFileDialog::getExistingDirectory(
this, tr(
"Export Selected Symbols as SVG" ),
2084 QDir::home().absolutePath(),
2085 QFileDialog::ShowDirsOnly
2086 | QFileDialog::DontResolveSymlinks );
2093 if ( dir.isEmpty() )
2096 const QList< ItemDetails > items = selectedItems();
2097 for (
const ItemDetails &details : items )
2102 QString path = dir +
'/' + details.name +
'.' + format;
2103 std::unique_ptr< QgsSymbol > sym( mStyle->
symbol( details.name ) );
2105 sym->exportImage( path, format, size );
2125 QFont font = item->font();
2126 font.setBold(
true );
2127 item->setFont( font );
2132 if ( mBlockGroupUpdates )
2135 QStandardItemModel *model = qobject_cast<QStandardItemModel *>( groupTree->model() );
2138 if ( mFavoritesGroupVisible )
2140 QStandardItem *favoriteSymbols =
new QStandardItem( tr(
"Favorites" ) );
2141 favoriteSymbols->setData(
"favorite" );
2142 favoriteSymbols->setEditable(
false );
2144 model->appendRow( favoriteSymbols );
2147 QStandardItem *allSymbols =
new QStandardItem( tr(
"All" ) );
2148 allSymbols->setData(
"all" );
2149 allSymbols->setEditable(
false );
2151 model->appendRow( allSymbols );
2153 QStandardItem *taggroup =
new QStandardItem( QString() );
2154 taggroup->setData(
"tags" );
2155 taggroup->setEditable(
false );
2156 QStringList tags = mStyle->
tags();
2158 for (
const QString &tag : qgis::as_const( tags ) )
2160 QStandardItem *item =
new QStandardItem( tag );
2161 item->setData( mStyle->
tagId( tag ) );
2162 item->setEditable( !mReadOnly );
2163 taggroup->appendRow( item );
2165 taggroup->setText( tr(
"Tags" ) );
2167 model->appendRow( taggroup );
2169 if ( mSmartGroupVisible )
2171 QStandardItem *smart =
new QStandardItem( tr(
"Smart Groups" ) );
2172 smart->setData(
"smartgroups" );
2173 smart->setEditable(
false );
2176 QgsSymbolGroupMap::const_iterator i = sgMap.constBegin();
2177 while ( i != sgMap.constEnd() )
2179 QStandardItem *item =
new QStandardItem( i.value() );
2180 item->setData( i.key() );
2181 item->setEditable( !mReadOnly );
2182 smart->appendRow( item );
2185 model->appendRow( smart );
2189 int rows = model->rowCount( model->indexFromItem( model->invisibleRootItem() ) );
2190 for (
int i = 0; i < rows; i++ )
2192 groupTree->setExpanded( model->indexFromItem( model->item( i ) ),
true );
2198 QStringList groupSymbols;
2200 const QString category = index.data( Qt::UserRole + 1 ).toString();
2201 if ( mGroupingMode )
2203 mModel->setTagId( -1 );
2204 mModel->setSmartGroupId( -1 );
2205 mModel->setFavoritesOnly(
false );
2206 mModel->setCheckTag( index.data( Qt::DisplayRole ).toString() );
2208 else if ( category == QLatin1String(
"all" ) || category == QLatin1String(
"tags" ) || category == QLatin1String(
"smartgroups" ) )
2211 if ( category == QLatin1String(
"tags" ) )
2213 actnAddTag->setEnabled( !mReadOnly );
2214 actnAddSmartgroup->setEnabled(
false );
2216 else if ( category == QLatin1String(
"smartgroups" ) )
2218 actnAddTag->setEnabled(
false );
2219 actnAddSmartgroup->setEnabled( !mReadOnly );
2222 mModel->setTagId( -1 );
2223 mModel->setSmartGroupId( -1 );
2224 mModel->setFavoritesOnly(
false );
2226 else if ( category == QLatin1String(
"favorite" ) )
2229 mModel->setTagId( -1 );
2230 mModel->setSmartGroupId( -1 );
2231 mModel->setFavoritesOnly(
true );
2233 else if ( index.parent().data( Qt::UserRole + 1 ) ==
"smartgroups" )
2235 actnRemoveGroup->setEnabled( !mReadOnly );
2236 btnManageGroups->setEnabled( !mReadOnly );
2237 const int groupId = index.data( Qt::UserRole + 1 ).toInt();
2238 mModel->setTagId( -1 );
2239 mModel->setSmartGroupId( groupId );
2240 mModel->setFavoritesOnly(
false );
2245 int tagId = index.data( Qt::UserRole + 1 ).toInt();
2246 mModel->setTagId( tagId );
2247 mModel->setSmartGroupId( -1 );
2248 mModel->setFavoritesOnly(
false );
2251 actnEditSmartGroup->setVisible(
false );
2252 actnAddTag->setVisible(
false );
2253 actnAddSmartgroup->setVisible(
false );
2254 actnRemoveGroup->setVisible(
false );
2255 actnTagSymbols->setVisible(
false );
2256 actnFinishTagging->setVisible(
false );
2258 if ( index.parent().isValid() )
2260 if ( index.parent().data( Qt::UserRole + 1 ).toString() == QLatin1String(
"smartgroups" ) )
2262 actnEditSmartGroup->setVisible( !mGroupingMode && !mReadOnly );
2264 else if ( index.parent().data( Qt::UserRole + 1 ).toString() == QLatin1String(
"tags" ) )
2266 actnAddTag->setVisible( !mGroupingMode && !mReadOnly );
2267 actnTagSymbols->setVisible( !mGroupingMode && !mReadOnly );
2268 actnFinishTagging->setVisible( mGroupingMode && !mReadOnly );
2270 actnRemoveGroup->setVisible( !mReadOnly );
2272 else if ( index.data( Qt::UserRole + 1 ) ==
"smartgroups" )
2274 actnAddSmartgroup->setVisible( !mGroupingMode && !mReadOnly );
2276 else if ( index.data( Qt::UserRole + 1 ) ==
"tags" )
2278 actnAddTag->setVisible( !mGroupingMode && !mReadOnly );
2284 QStandardItemModel *model = qobject_cast<QStandardItemModel *>( groupTree->model() );
2286 for (
int i = 0; i < groupTree->model()->rowCount(); i++ )
2288 index = groupTree->model()->index( i, 0 );
2289 QString data = index.data( Qt::UserRole + 1 ).toString();
2290 if ( data == QLatin1String(
"tags" ) )
2299 itemName = QInputDialog::getText(
this, tr(
"Add Tag" ),
2300 tr(
"Please enter name for the new tag:" ), QLineEdit::Normal, tr(
"New tag" ), &ok ).trimmed();
2301 if ( !ok || itemName.isEmpty() )
2304 int check = mStyle->
tagId( itemName );
2307 mMessageBar->
pushCritical( tr(
"Add Tag" ), tr(
"The tag “%1” already exists." ).arg( itemName ) );
2313 mBlockGroupUpdates++;
2314 id = mStyle->
addTag( itemName );
2315 mBlockGroupUpdates--;
2319 mMessageBar->
pushCritical( tr(
"Add Tag" ), tr(
"New tag could not be created — There was a problem with the symbol database." ) );
2323 QStandardItem *parentItem = model->itemFromIndex( index );
2324 QStandardItem *childItem =
new QStandardItem( itemName );
2325 childItem->setData(
id );
2326 parentItem->appendRow( childItem );
2333 QStandardItemModel *model = qobject_cast<QStandardItemModel *>( groupTree->model() );
2335 for (
int i = 0; i < groupTree->model()->rowCount(); i++ )
2337 index = groupTree->model()->index( i, 0 );
2338 QString data = index.data( Qt::UserRole + 1 ).toString();
2339 if ( data == QLatin1String(
"smartgroups" ) )
2348 if ( dlg.exec() == QDialog::Rejected )
2353 mBlockGroupUpdates++;
2355 mBlockGroupUpdates--;
2361 QStandardItem *parentItem = model->itemFromIndex( index );
2362 QStandardItem *childItem =
new QStandardItem( itemName );
2363 childItem->setData(
id );
2364 parentItem->appendRow( childItem );
2371 QStandardItemModel *model = qobject_cast<QStandardItemModel *>( groupTree->model() );
2372 QModelIndex index = groupTree->currentIndex();
2375 QString data = index.data( Qt::UserRole + 1 ).toString();
2376 if ( data == QLatin1String(
"all" ) || data == QLatin1String(
"favorite" ) || data == QLatin1String(
"tags" ) || index.data() ==
"smartgroups" )
2379 int err = QMessageBox::critical(
this, tr(
"Remove Group" ),
2380 tr(
"Invalid selection. Cannot delete system defined categories.\n"
2381 "Kindly select a group or smart group you might want to delete." ) );
2386 QStandardItem *parentItem = model->itemFromIndex( index.parent() );
2390 mBlockGroupUpdates++;
2392 if ( parentItem->data( Qt::UserRole + 1 ).toString() == QLatin1String(
"smartgroups" ) )
2401 mBlockGroupUpdates--;
2402 parentItem->removeRow( index.row() );
2407 QgsDebugMsg( QStringLiteral(
"Symbol group edited: data=%1 text=%2" ).arg( item->data( Qt::UserRole + 1 ).toString(), item->text() ) );
2408 int id = item->data( Qt::UserRole + 1 ).toInt();
2409 QString name = item->text();
2410 mBlockGroupUpdates++;
2411 if ( item->parent()->data( Qt::UserRole + 1 ) ==
"smartgroups" )
2419 mBlockGroupUpdates--;
2424 QStandardItemModel *treeModel = qobject_cast<QStandardItemModel *>( groupTree->model() );
2426 if ( mGroupingMode )
2428 mGroupingMode =
false;
2429 mModel->setCheckable(
false );
2430 actnTagSymbols->setVisible(
true );
2431 actnFinishTagging->setVisible(
false );
2439 connect( treeModel, &QStandardItemModel::itemChanged,
2443 listItems->setSelectionMode( QAbstractItemView::ExtendedSelection );
2444 mSymbolTreeView->setSelectionMode( QAbstractItemView::ExtendedSelection );
2448 bool validGroup =
false;
2450 QModelIndex present = groupTree->currentIndex();
2451 while ( present.parent().isValid() )
2453 if ( present.parent().data() ==
"Tags" )
2458 present = present.parent();
2463 mGroupingMode =
true;
2465 actnTagSymbols->setVisible(
false );
2466 actnFinishTagging->setVisible(
true );
2468 disconnect( treeModel, &QStandardItemModel::itemChanged,
2474 btnManageGroups->setEnabled(
true );
2476 mModel->setCheckable(
true );
2479 listItems->setSelectionMode( QAbstractItemView::NoSelection );
2480 mSymbolTreeView->setSelectionMode( QAbstractItemView::NoSelection );
2494 mModel->setFilterString( qword );
2499 actnEditItem->setEnabled( index.isValid() && !mGroupingMode && !mReadOnly );
2504 Q_UNUSED( selected )
2505 Q_UNUSED( deselected )
2506 bool nothingSelected = listItems->selectionModel()->selectedIndexes().empty();
2507 actnRemoveItem->setDisabled( nothingSelected || mReadOnly );
2508 actnAddFavorite->setDisabled( nothingSelected || mReadOnly );
2509 actnRemoveFavorite->setDisabled( nothingSelected || mReadOnly );
2510 mGroupListMenu->setDisabled( nothingSelected || mReadOnly );
2511 actnDetag->setDisabled( nothingSelected || mReadOnly );
2512 actnExportAsPNG->setDisabled( nothingSelected );
2513 actnExportAsSVG->setDisabled( nothingSelected );
2514 if ( mActionCopyToDefault )
2515 mActionCopyToDefault->setDisabled( nothingSelected );
2516 mCopyToDefaultButton->setDisabled( nothingSelected );
2517 actnEditItem->setDisabled( nothingSelected || mReadOnly );
2522 groupTree->setEnabled( enable );
2523 btnAddTag->setEnabled( enable && !mReadOnly );
2524 btnAddSmartgroup->setEnabled( enable && !mReadOnly );
2525 actnAddTag->setEnabled( enable && !mReadOnly );
2526 actnAddSmartgroup->setEnabled( enable && !mReadOnly );
2527 actnRemoveGroup->setEnabled( enable && !mReadOnly );
2528 btnManageGroups->setEnabled( !mReadOnly && ( enable || mGroupingMode ) );
2529 searchBox->setEnabled( enable );
2534 actnRemoveGroup->setEnabled( enable && !mReadOnly );
2535 btnManageGroups->setEnabled( !mReadOnly && ( enable || mGroupingMode ) );
2540 QStandardItemModel *treeModel = qobject_cast<QStandardItemModel *>( groupTree->model() );
2541 for (
int i = 0; i < treeModel->rowCount(); i++ )
2543 treeModel->item( i )->setEnabled( enable );
2545 if ( treeModel->item( i )->data() ==
"smartgroups" )
2547 for (
int j = 0; j < treeModel->item( i )->rowCount(); j++ )
2549 treeModel->item( i )->child( j )->setEnabled( enable );
2556 for (
int i = 0; i < symbolBtnsLayout->count(); i++ )
2558 QWidget *w = symbolBtnsLayout->itemAt( i )->widget();
2560 w->setEnabled( enable );
2564 actnRemoveItem->setEnabled( enable );
2565 actnEditItem->setEnabled( enable );
2566 mActionCopyItem->setEnabled( enable );
2567 mActionPasteItem->setEnabled( enable );
2572 QPoint globalPos = groupTree->viewport()->mapToGlobal( point );
2574 QModelIndex index = groupTree->indexAt( point );
2575 if ( index.isValid() && !mGroupingMode )
2576 mGroupTreeContextMenu->popup( globalPos );
2581 QPoint globalPos = mSymbolViewStackedWidget->currentIndex() == 0
2582 ? listItems->viewport()->mapToGlobal( point )
2583 : mSymbolTreeView->viewport()->mapToGlobal( point );
2586 mGroupListMenu->clear();
2588 const QModelIndexList indices = listItems->selectionModel()->selectedRows();
2592 const QStringList currentTags = indices.count() == 1 ? indices.at( 0 ).data(
QgsStyleModel::TagRole ).toStringList() : QStringList();
2593 QAction *a =
nullptr;
2594 QStringList tags = mStyle->
tags();
2596 for (
const QString &tag : qgis::as_const( tags ) )
2598 a =
new QAction( tag, mGroupListMenu );
2600 if ( indices.count() == 1 )
2602 a->setCheckable(
true );
2603 a->setChecked( currentTags.contains( tag ) );
2607 mGroupListMenu->addAction( a );
2610 if ( tags.count() > 0 )
2612 mGroupListMenu->addSeparator();
2614 a =
new QAction( tr(
"Create New Tag…" ), mGroupListMenu );
2617 mGroupListMenu->addAction( a );
2620 const QList< ItemDetails > items = selectedItems();
2623 bool enablePaste =
false;
2631 mActionPasteItem->setEnabled( enablePaste );
2633 mGroupMenu->popup( globalPos );
2638 const QList< ItemDetails > items = selectedItems();
2639 for (
const ItemDetails &details : items )
2641 mStyle->
addFavorite( details.entityType, details.name );
2647 const QList< ItemDetails > items = selectedItems();
2648 for (
const ItemDetails &details : items )
2656 QAction *selectedItem = qobject_cast<QAction *>( sender() );
2659 const QList< ItemDetails > items = selectedItems();
2669 tag = mStyle->
tag(
id );
2673 tag = selectedItem->data().toString();
2676 for (
const ItemDetails &details : items )
2678 mStyle->
tagSymbol( details.entityType, details.name, QStringList( tag ) );
2685 QAction *selectedItem = qobject_cast<QAction *>( sender() );
2689 const QList< ItemDetails > items = selectedItems();
2690 for (
const ItemDetails &details : items )
2692 mStyle->
detagSymbol( details.entityType, details.name );
2699 QStandardItemModel *treeModel = qobject_cast<QStandardItemModel *>( groupTree->model() );
2702 QModelIndex present = groupTree->currentIndex();
2703 if ( present.parent().data( Qt::UserRole + 1 ) !=
"smartgroups" )
2706 QMessageBox::critical(
this, tr(
"Edit Smart Group" ),
2707 tr(
"You have not selected a Smart Group. Kindly select a Smart Group to edit." ) );
2710 QStandardItem *item = treeModel->itemFromIndex( present );
2718 if ( dlg.exec() == QDialog::Rejected )
2721 mBlockGroupUpdates++;
2724 mBlockGroupUpdates--;
2727 mMessageBar->
pushCritical( tr(
"Edit Smart Group" ), tr(
"There was an error while editing the smart group." ) );
2731 item->setData(
id );