54#include <QDesktopServices>
57#include <QInputDialog>
62#include <QStandardItemModel>
66#include "moc_qgsstylemanagerdialog.cpp"
68using namespace Qt::StringLiterals;
71 =
new QgsSettingsEntryString( u
"last-style-database-folder"_s, sTtreeStyleManager, QString(), u
"Last used folder for style databases"_s );
78QgsCheckableStyleModel::QgsCheckableStyleModel(
QgsStyleModel *sourceModel, QObject *parent,
bool readOnly )
80 , mStyle( sourceModel->style() )
81 , mReadOnly( readOnly )
84QgsCheckableStyleModel::QgsCheckableStyleModel(
QgsStyle *style, QObject *parent,
bool readOnly )
87 , mReadOnly( readOnly )
90void QgsCheckableStyleModel::setCheckable(
bool checkable )
92 if ( checkable == mCheckable )
95 mCheckable = checkable;
96 emit dataChanged( index( 0, 0 ), index( rowCount() - 1, 0 ), QVector<int>() << Qt::CheckStateRole );
99void QgsCheckableStyleModel::setCheckTag(
const QString &tag )
101 if ( tag == mCheckTag )
105 emit dataChanged( index( 0, 0 ), index( rowCount() - 1, 0 ), QVector<int>() << Qt::CheckStateRole );
108Qt::ItemFlags QgsCheckableStyleModel::flags(
const QModelIndex &index )
const
110 Qt::ItemFlags f = QgsStyleProxyModel::flags( index );
111 if ( !mReadOnly && mCheckable && index.column() == 0 )
112 f |= Qt::ItemIsUserCheckable;
115 f &= ~Qt::ItemIsEditable;
120QVariant QgsCheckableStyleModel::data(
const QModelIndex &index,
int role )
const
127 QFont f = QgsStyleProxyModel::data( index, role ).value<QFont>();
132 case Qt::CheckStateRole:
134 if ( !mCheckable || index.column() != 0 )
138 return tags.contains( mCheckTag ) ? Qt::Checked : Qt::Unchecked;
144 return QgsStyleProxyModel::data( index, role );
147bool QgsCheckableStyleModel::setData(
const QModelIndex &i,
const QVariant &value,
int role )
149 if ( i.row() < 0 || i.row() >= rowCount( QModelIndex() ) || ( role != Qt::EditRole && role != Qt::CheckStateRole ) )
155 if ( role == Qt::CheckStateRole )
157 if ( !mCheckable || mCheckTag.isEmpty() )
160 const QString name = data( index( i.row(),
QgsStyleModel::Name ), Qt::DisplayRole ).toString();
163 if ( value.toInt() == Qt::Checked )
164 return mStyle->tagSymbol( entity, name, QStringList() << mCheckTag );
166 return mStyle->detagSymbol( entity, name, QStringList() << mCheckTag );
168 return QgsStyleProxyModel::setData( i, value, role );
178QString QgsStyleManagerDialog::sPreviousTag;
181 : QDialog( parent, flags )
182 , mReadOnly( readOnly )
185 setCurrentStyle( style );
186 mStyleDatabaseWidget->hide();
190 : QDialog( parent, flags )
195 mProjectStyleModel->setShowDefaultStyle(
true );
196 mComboBoxStyleDatabase->setModel( mProjectStyleModel );
200 connect( mComboBoxStyleDatabase, qOverload<int>( &QComboBox::currentIndexChanged ),
this, [
this]() {
201 if ( mBlockStyleDatabaseChanges )
204 const QModelIndex index = mProjectStyleModel->index( mComboBoxStyleDatabase->currentIndex(), 0, QModelIndex() );
205 setCurrentStyle( mProjectStyleModel->styleFromIndex( index ) );
208 connect( mButtonAddStyleDatabase, &QAbstractButton::clicked,
this, [
this] { addStyleDatabase(
false ); } );
209 connect( mButtonNewStyleDatabase, &QAbstractButton::clicked,
this, [
this] { addStyleDatabase(
true ); } );
212void QgsStyleManagerDialog::init()
216 connect( tabItemType, &QTabWidget::currentChanged,
this, &QgsStyleManagerDialog::tabItemType_currentChanged );
220 QPushButton *downloadButton = buttonBox->addButton( tr(
"Browse Online Styles" ), QDialogButtonBox::ResetRole );
221 downloadButton->setToolTip( tr(
"Download new styles from the online QGIS style repository" ) );
223 connect( downloadButton, &QPushButton::clicked,
this, [] { QDesktopServices::openUrl( QUrl( u
"https://hub.qgis.org/styles/"_s ) ); } );
225 mMessageBar =
new QgsMessageBar();
226 mMessageBar->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed );
227 mVerticalLayout->insertWidget( 0, mMessageBar );
230 setWindowModality( Qt::WindowModal );
233 QgsSettings settings;
235 mSplitter->setSizes( QList<int>() << 170 << 540 );
236 mSplitter->restoreState( settings.
value( u
"Windows/StyleV2Manager/splitter"_s ).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 )
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 ) { addMaterialSettings(); } );
385 mMenuBtnAddItemAll->addAction( item );
387 mMenuBtnAddItemAll->addSeparator();
389 connect( item, &QAction::triggered,
this, [
this](
bool ) { addSymbol3D( u
"point"_s ); } );
390 mMenuBtnAddItemAll->addAction( item );
391 mMenuBtnAddItemSymbol3D->addAction( item );
393 connect( item, &QAction::triggered,
this, [
this](
bool ) { addSymbol3D( u
"line"_s ); } );
394 mMenuBtnAddItemAll->addAction( item );
395 mMenuBtnAddItemSymbol3D->addAction( item );
397 connect( item, &QAction::triggered,
this, [
this](
bool ) { addSymbol3D( u
"polygon"_s ); } );
398 mMenuBtnAddItemAll->addAction( item );
399 mMenuBtnAddItemSymbol3D->addAction( item );
402 mGroupMenu =
new QMenu(
this );
403 mGroupListMenu =
new QMenu( mGroupMenu );
404 mGroupListMenu->setTitle( tr(
"Add to Tag" ) );
405 mGroupListMenu->setEnabled(
false );
412 mGroupTreeContextMenu =
new QMenu(
this );
414 connect( actnAddTag, &QAction::triggered,
this, [
this](
bool ) {
addTag(); } );
415 connect( actnAddSmartgroup, &QAction::triggered,
this, [
this](
bool ) {
addSmartgroup(); } );
418 tabItemType_currentChanged( 0 );
420 connect( mButtonIconView, &QToolButton::toggled,
this, [
this](
bool active ) {
423 mSymbolViewStackedWidget->setCurrentIndex( 0 );
425 QgsSettings().setValue( u
"Windows/StyleV2Manager/lastIconView"_s, 0,
QgsSettings::Gui );
428 connect( mButtonListView, &QToolButton::toggled,
this, [
this](
bool active ) {
431 QgsSettings().setValue( u
"Windows/StyleV2Manager/lastIconView"_s, 1,
QgsSettings::Gui );
432 mSymbolViewStackedWidget->setCurrentIndex( 1 );
436 const int currentView = settings.
value( u
"Windows/StyleV2Manager/lastIconView"_s, 0,
QgsSettings::Gui ).toInt();
437 if ( currentView == 0 )
438 mButtonIconView->setChecked(
true );
440 mButtonListView->setChecked(
true );
442 mSymbolTreeView->header()->restoreState( settings.
value( u
"Windows/StyleV2Manager/treeState"_s, QByteArray(),
QgsSettings::Gui ).toByteArray() );
443 connect( mSymbolTreeView->header(), &QHeaderView::sectionResized,
this, [
this] {
445 QgsSettings().setValue( u
"Windows/StyleV2Manager/treeState"_s, mSymbolTreeView->header()->saveState(), QgsSettings::Gui );
448 const int thumbnailSize = settings.
value( u
"Windows/StyleV2Manager/thumbnailSize"_s, 0,
QgsSettings::Gui ).toInt();
449 mSliderIconSize->setValue( thumbnailSize );
450 connect( mSliderIconSize, &QSlider::valueChanged,
this, &QgsStyleManagerDialog::setThumbnailSize );
451 setThumbnailSize( thumbnailSize );
454void QgsStyleManagerDialog::setCurrentStyle(
QgsStyle *style )
456 if ( mStyle == style )
466 QgsCheckableStyleModel *oldModel = mModel;
469 const bool readOnly = isReadOnly();
472 if ( !mActionCopyToDefault )
474 mActionCopyToDefault =
new QAction( tr(
"Copy Selection to Default Style…" ),
this );
475 mShareMenu->insertAction( mActionCopyItem, mActionCopyToDefault );
476 connect( mActionCopyToDefault, &QAction::triggered,
this, &QgsStyleManagerDialog::copyItemsToDefault );
478 mCopyToDefaultButton->show();
479 mModel =
new QgsCheckableStyleModel( mStyle,
this, readOnly );
483 mCopyToDefaultButton->hide();
484 if ( mActionCopyToDefault )
486 mActionCopyToDefault->deleteLater();
487 mActionCopyToDefault =
nullptr;
491 mModel->addDesiredIconSize( mSymbolTreeView->iconSize() );
492 mModel->addDesiredIconSize( listItems->iconSize() );
493 mModel->addTargetScreenProperties( QgsScreenProperties( screen() ) );
495 mModel->setFilterString( searchBox->text() );
497 listItems->setModel( mModel );
498 mSymbolTreeView->setModel( mModel );
500 mSymbolTreeView->setSelectionModel( listItems->selectionModel() );
507 oldModel->deleteLater();
515 if ( mProjectStyleModel )
517 const QModelIndex styleIndex = mProjectStyleModel->indexFromStyle( mStyle );
518 mBlockStyleDatabaseChanges++;
519 mComboBoxStyleDatabase->setCurrentIndex( styleIndex.row() );
520 mBlockStyleDatabaseChanges--;
525 btnAddTag->setEnabled(
false );
526 btnAddSmartgroup->setEnabled(
false );
527 btnManageGroups->setEnabled(
false );
529 btnAddItem->setVisible(
false );
530 btnRemoveItem->setVisible(
false );
531 btnEditItem->setVisible(
false );
532 btnAddSmartgroup->setVisible(
false );
533 btnAddTag->setVisible(
false );
534 btnManageGroups->setVisible(
false );
536 delete mImportAction;
537 mImportAction =
nullptr;
539 mGroupTreeContextMenu->clear();
541 mGroupMenu->addAction( mActionCopyItem );
545 btnAddTag->setEnabled(
true );
546 btnAddSmartgroup->setEnabled(
true );
547 btnManageGroups->setEnabled(
true );
549 btnAddItem->setVisible(
true );
550 btnRemoveItem->setVisible(
true );
551 btnEditItem->setVisible(
true );
552 btnAddSmartgroup->setVisible(
true );
553 btnAddTag->setVisible(
true );
554 btnManageGroups->setVisible(
true );
556 if ( !mImportAction )
558 mImportAction =
new QAction( tr(
"Import Item(s)…" ),
this );
560 mShareMenu->insertAction( mShareMenu->actions().at( mShareMenu->actions().indexOf( mExportAction ) + 1 ), mImportAction );
564 mGroupTreeContextMenu->clear();
565 mGroupTreeContextMenu->addAction( actnEditSmartGroup );
566 mGroupTreeContextMenu->addAction( actnAddTag );
567 mGroupTreeContextMenu->addAction( actnAddSmartgroup );
568 mGroupTreeContextMenu->addAction( actnRemoveGroup );
571 mGroupMenu->addAction( actnAddFavorite );
572 mGroupMenu->addAction( actnRemoveFavorite );
573 mGroupMenu->addSeparator()->setParent(
this );
574 mGroupMenu->addMenu( mGroupListMenu );
575 mGroupMenu->addAction( actnDetag );
576 mGroupMenu->addSeparator()->setParent(
this );
577 mGroupMenu->addAction( actnRemoveItem );
578 mGroupMenu->addAction( actnEditItem );
579 mGroupMenu->addAction( mActionCopyItem );
580 mGroupMenu->addAction( mActionPasteItem );
581 mGroupMenu->addSeparator()->setParent(
this );
584 if ( mActionCopyToDefault )
586 mGroupMenu->addAction( mActionCopyToDefault );
588 mGroupMenu->addAction( actnExportAsPNG );
589 mGroupMenu->addAction( actnExportAsSVG );
592 const QModelIndexList prevIndex = groupTree->model()->match( groupTree->model()->index( 0, 0 ), Qt::UserRole + 1, sPreviousTag, 1, Qt::MatchFixedString | Qt::MatchCaseSensitive | Qt::MatchRecursive );
593 groupTree->setCurrentIndex( !prevIndex.empty() ? prevIndex.at( 0 ) : groupTree->model()->index( 0, 0 ) );
596 tabItemType_currentChanged( tabItemType->currentIndex() );
602void QgsStyleManagerDialog::currentStyleAboutToBeDestroyed()
613 settings.
setValue( u
"Windows/StyleV2Manager/splitter"_s, mSplitter->saveState() );
619void QgsStyleManagerDialog::tabItemType_currentChanged(
int )
629 searchBox->setPlaceholderText(
630 isSymbol ? tr(
"Filter symbols…" )
631 : isColorRamp ? tr(
"Filter color ramps…" )
632 : isTextFormat ? tr(
"Filter text symbols…" )
633 : isLabelSettings ? tr(
"Filter label settings…" )
634 : isLegendPatchShape ? tr(
"Filter legend patch shapes…" )
635 : isSymbol3D ? tr(
"Filter 3D symbols…" )
636 : tr(
"Filter materials…" )
639 const bool readOnly = isReadOnly();
640 if ( !readOnly && isColorRamp )
642 btnAddItem->setMenu( mMenuBtnAddItemColorRamp );
644 else if ( !readOnly && isLegendPatchShape )
646 btnAddItem->setMenu( mMenuBtnAddItemLegendPatchShape );
648 else if ( !readOnly && isSymbol3D )
650 btnAddItem->setMenu( mMenuBtnAddItemSymbol3D );
652 else if ( !readOnly && isMaterialSettings )
654 btnAddItem->setMenu(
nullptr );
656 else if ( !readOnly && isLabelSettings )
658 btnAddItem->setMenu( mMenuBtnAddItemLabelSettings );
660 else if ( !readOnly && !isSymbol && !isColorRamp )
662 btnAddItem->setMenu(
nullptr );
664 else if ( !readOnly && tabItemType->currentIndex() == 0 )
666 btnAddItem->setMenu( mMenuBtnAddItemAll );
670 btnAddItem->setMenu(
nullptr );
673 actnExportAsPNG->setVisible( isSymbol );
674 actnExportAsSVG->setVisible( isSymbol );
678 mModel->setEntityFilter(
687 mModel->setEntityFilterEnabled( !allTypesSelected() );
688 mModel->setSymbolTypeFilterEnabled( isSymbol && !allTypesSelected() );
689 if ( isSymbol && !allTypesSelected() )
696void QgsStyleManagerDialog::copyItemsToDefault()
698 const QList<ItemDetails> items = selectedItems();
699 if ( !items.empty() )
703 if ( !mBaseName.isEmpty() )
704 options.append( mBaseName );
707 defaultTags.sort( Qt::CaseInsensitive );
708 options.append( defaultTags );
709 const QString tags = QInputDialog::getItem(
this, tr(
"Import Items" ), tr(
"Additional tags to add (comma separated)" ), options, mBaseName.isEmpty() ? -1 : 0,
true, &ok );
713 const QStringList parts = tags.split(
',', Qt::SkipEmptyParts );
714 QStringList additionalTags;
715 additionalTags.reserve( parts.count() );
716 for (
const QString &tag : parts )
717 additionalTags << tag.trimmed();
719 auto cursorOverride = std::make_unique<QgsTemporaryCursorOverride>( Qt::WaitCursor );
720 const int count = copyItems( items, mStyle,
QgsStyle::defaultStyle(),
this, cursorOverride,
true, additionalTags,
false,
false );
721 cursorOverride.reset();
724 mMessageBar->pushSuccess( tr(
"Import Items" ), count > 1 ? tr(
"Successfully imported %n item(s).",
nullptr, count ) : tr(
"Successfully imported item." ) );
729void QgsStyleManagerDialog::copyItem()
731 const QList<ItemDetails> items = selectedItems();
735 ItemDetails details = items.at( 0 );
736 switch ( details.entityType )
740 std::unique_ptr<QgsSymbol> symbol( mStyle->symbol( details.name ) );
749 const QgsTextFormat format( mStyle->textFormat( details.name ) );
750 QApplication::clipboard()->setMimeData( format.toMimeData() );
756 const QgsPalLayerSettings labelSettings( mStyle->labelSettings( details.name ) );
757 QApplication::clipboard()->setMimeData( labelSettings.toMimeData() );
771void QgsStyleManagerDialog::pasteItem()
773 const QString defaultTag = groupTree->currentIndex().isValid() ? groupTree->currentIndex().data( GroupModelRoles::TagName ).toString() : QString();
777 QgsStyleSaveDialog saveDlg(
this );
778 saveDlg.setWindowTitle( tr(
"Paste Symbol" ) );
779 saveDlg.setDefaultTags( defaultTag );
780 if ( !saveDlg.exec() || saveDlg.name().isEmpty() )
783 if ( mStyle->symbolNames().contains( saveDlg.name() ) )
785 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 );
786 if ( res != QMessageBox::Yes )
790 mStyle->removeSymbol( saveDlg.name() );
793 QStringList symbolTags = saveDlg.tags().split(
',' );
794 QgsSymbol *newSymbol = tempSymbol.get();
795 mStyle->addSymbol( saveDlg.name(), tempSymbol.release() );
797 mStyle->saveSymbol( saveDlg.name(), newSymbol, saveDlg.isFavorite(), symbolTags );
807 saveDlg.setDefaultTags( defaultTag );
808 saveDlg.setWindowTitle( tr(
"Paste Label Settings" ) );
809 if ( !saveDlg.exec() || saveDlg.name().isEmpty() )
812 if ( mStyle->labelSettingsNames().contains( saveDlg.name() ) )
814 int res = QMessageBox::warning(
this, tr(
"Paste Label Settings" ), tr(
"A label setting with the name '%1' already exists. Overwrite?" ).arg( saveDlg.name() ), QMessageBox::Yes | QMessageBox::No );
815 if ( res != QMessageBox::Yes )
819 mStyle->removeLabelSettings( saveDlg.name() );
822 QStringList symbolTags = saveDlg.tags().split(
',' );
823 mStyle->addLabelSettings( saveDlg.name(), labelSettings );
825 mStyle->saveLabelSettings( saveDlg.name(), labelSettings, saveDlg.isFavorite(), symbolTags );
834 saveDlg.setDefaultTags( defaultTag );
835 saveDlg.setWindowTitle( tr(
"Paste Text Format" ) );
836 if ( !saveDlg.exec() || saveDlg.name().isEmpty() )
839 if ( mStyle->textFormatNames().contains( saveDlg.name() ) )
841 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 );
842 if ( res != QMessageBox::Yes )
846 mStyle->removeTextFormat( saveDlg.name() );
849 QStringList symbolTags = saveDlg.tags().split(
',' );
850 mStyle->addTextFormat( saveDlg.name(), format );
852 mStyle->saveTextFormat( saveDlg.name(), format, saveDlg.isFavorite(), symbolTags );
857void QgsStyleManagerDialog::setThumbnailSize(
int value )
862 const double spacing =
Qgis::UI_SCALE_FACTOR * fontMetrics().horizontalAdvance(
'X' ) * ( value * 2.2 + 14 );
864 listItems->setIconSize( QSize(
static_cast<int>( iconSize ),
static_cast<int>( iconSize * 0.9 ) ) );
865 listItems->setGridSize( QSize(
static_cast<int>( spacing ),
static_cast<int>( verticalSpacing ) ) );
868 mModel->addDesiredIconSize( listItems->iconSize() );
871 QgsSettings().setValue( u
"Windows/StyleV2Manager/thumbnailSize"_s, value,
QgsSettings::Gui );
874int QgsStyleManagerDialog::selectedItemType()
876 QModelIndex index = listItems->selectionModel()->currentIndex();
877 if ( !index.isValid() )
897bool QgsStyleManagerDialog::allTypesSelected()
const
899 return tabItemType->currentIndex() == 0;
902bool QgsStyleManagerDialog::isReadOnly()
const
904 return mReadOnly || ( mStyle && mStyle->isReadOnly() );
907QList<QgsStyleManagerDialog::ItemDetails> QgsStyleManagerDialog::selectedItems()
909 QList<QgsStyleManagerDialog::ItemDetails> res;
910 QModelIndexList indices = listItems->selectionModel()->selectedRows();
911 for (
const QModelIndex &index : indices )
913 if ( !index.isValid() )
920 details.name = mModel->data( mModel->index( index.row(),
QgsStyleModel::Name, index.parent() ), Qt::DisplayRole ).toString();
927int QgsStyleManagerDialog::copyItems(
928 const QList<QgsStyleManagerDialog::ItemDetails> &items,
931 QWidget *parentWidget,
932 std::unique_ptr<QgsTemporaryCursorOverride> &cursorOverride,
934 const QStringList &importTags,
936 bool ignoreSourceTags
940 bool overwriteAll =
true;
951 for (
auto &details : items )
953 QStringList symbolTags;
954 if ( !ignoreSourceTags )
956 symbolTags = src->
tagsOfSymbol( details.entityType, details.name );
959 bool addItemToFavorites =
false;
962 symbolTags << importTags;
963 addItemToFavorites = addToFavorites;
966 switch ( details.entityType )
970 std::unique_ptr<QgsSymbol> symbol( src->
symbol( details.name ) );
974 const bool hasDuplicateName = dst->
symbolNames().contains( details.name );
975 bool overwriteThis =
false;
977 addItemToFavorites = favoriteSymbols.contains( details.name );
979 if ( hasDuplicateName && prompt )
981 cursorOverride.reset();
982 int res = QMessageBox::warning(
984 isImport ? tr(
"Import Symbol" ) : tr(
"Export Symbol" ),
985 tr(
"A symbol with the name “%1” already exists.\nOverwrite?" ).arg( details.name ),
986 QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No | QMessageBox::NoToAll | QMessageBox::Cancel
988 cursorOverride = std::make_unique<QgsTemporaryCursorOverride>( Qt::WaitCursor );
991 case QMessageBox::Cancel:
994 case QMessageBox::No:
997 case QMessageBox::Yes:
998 overwriteThis =
true;
1001 case QMessageBox::YesToAll:
1003 overwriteAll =
true;
1006 case QMessageBox::NoToAll:
1008 overwriteAll =
false;
1015 if ( !hasDuplicateName || overwriteAll || overwriteThis )
1017 QgsSymbol *newSymbol = symbol.get();
1018 dst->
addSymbol( details.name, symbol.release() );
1019 dst->
saveSymbol( details.name, newSymbol, addItemToFavorites, symbolTags );
1027 std::unique_ptr<QgsColorRamp> ramp( src->
colorRamp( details.name ) );
1031 const bool hasDuplicateName = dst->
colorRampNames().contains( details.name );
1032 bool overwriteThis =
false;
1034 addItemToFavorites = favoriteColorramps.contains( details.name );
1036 if ( hasDuplicateName && prompt )
1038 cursorOverride.reset();
1039 int res = QMessageBox::warning(
1041 isImport ? tr(
"Import Color Ramp" ) : tr(
"Export Color Ramp" ),
1042 tr(
"A color ramp with the name “%1” already exists.\nOverwrite?" ).arg( details.name ),
1043 QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No | QMessageBox::NoToAll | QMessageBox::Cancel
1045 cursorOverride = std::make_unique<QgsTemporaryCursorOverride>( Qt::WaitCursor );
1048 case QMessageBox::Cancel:
1051 case QMessageBox::No:
1054 case QMessageBox::Yes:
1055 overwriteThis =
true;
1058 case QMessageBox::YesToAll:
1060 overwriteAll =
true;
1063 case QMessageBox::NoToAll:
1065 overwriteAll =
false;
1072 if ( !hasDuplicateName || overwriteAll || overwriteThis )
1074 QgsColorRamp *newRamp = ramp.get();
1076 dst->
saveColorRamp( details.name, newRamp, addItemToFavorites, symbolTags );
1084 const QgsTextFormat format( src->
textFormat( details.name ) );
1086 const bool hasDuplicateName = dst->
textFormatNames().contains( details.name );
1087 bool overwriteThis =
false;
1089 addItemToFavorites = favoriteTextFormats.contains( details.name );
1091 if ( hasDuplicateName && prompt )
1093 cursorOverride.reset();
1094 int res = QMessageBox::warning(
1096 isImport ? tr(
"Import Text Format" ) : tr(
"Export Text Format" ),
1097 tr(
"A text format with the name “%1” already exists.\nOverwrite?" ).arg( details.name ),
1098 QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No | QMessageBox::NoToAll | QMessageBox::Cancel
1100 cursorOverride = std::make_unique<QgsTemporaryCursorOverride>( Qt::WaitCursor );
1103 case QMessageBox::Cancel:
1106 case QMessageBox::No:
1109 case QMessageBox::Yes:
1110 overwriteThis =
true;
1113 case QMessageBox::YesToAll:
1115 overwriteAll =
true;
1118 case QMessageBox::NoToAll:
1120 overwriteAll =
false;
1128 if ( !hasDuplicateName || overwriteAll || overwriteThis )
1131 dst->
saveTextFormat( details.name, format, addItemToFavorites, symbolTags );
1139 const QgsPalLayerSettings settings( src->
labelSettings( details.name ) );
1142 bool overwriteThis =
false;
1144 addItemToFavorites = favoriteLabelSettings.contains( details.name );
1146 if ( hasDuplicateName && prompt )
1148 cursorOverride.reset();
1149 int res = QMessageBox::warning(
1151 isImport ? tr(
"Import Label Settings" ) : tr(
"Export Label Settings" ),
1152 tr(
"Label settings with the name “%1” already exist.\nOverwrite?" ).arg( details.name ),
1153 QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No | QMessageBox::NoToAll | QMessageBox::Cancel
1155 cursorOverride = std::make_unique<QgsTemporaryCursorOverride>( Qt::WaitCursor );
1158 case QMessageBox::Cancel:
1161 case QMessageBox::No:
1164 case QMessageBox::Yes:
1165 overwriteThis =
true;
1168 case QMessageBox::YesToAll:
1170 overwriteAll =
true;
1173 case QMessageBox::NoToAll:
1175 overwriteAll =
false;
1183 if ( !hasDuplicateName || overwriteAll || overwriteThis )
1186 dst->
saveLabelSettings( details.name, settings, addItemToFavorites, symbolTags );
1197 bool overwriteThis =
false;
1199 addItemToFavorites = favoriteLegendPatchShapes.contains( details.name );
1201 if ( hasDuplicateName && prompt )
1203 cursorOverride.reset();
1204 int res = QMessageBox::warning(
1206 isImport ? tr(
"Import Legend Patch Shape" ) : tr(
"Export Legend Patch Shape" ),
1207 tr(
"Legend patch shape with the name “%1” already exist.\nOverwrite?" ).arg( details.name ),
1208 QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No | QMessageBox::NoToAll | QMessageBox::Cancel
1210 cursorOverride = std::make_unique<QgsTemporaryCursorOverride>( Qt::WaitCursor );
1213 case QMessageBox::Cancel:
1216 case QMessageBox::No:
1219 case QMessageBox::Yes:
1220 overwriteThis =
true;
1223 case QMessageBox::YesToAll:
1225 overwriteAll =
true;
1228 case QMessageBox::NoToAll:
1230 overwriteAll =
false;
1238 if ( !hasDuplicateName || overwriteAll || overwriteThis )
1249 std::unique_ptr<QgsAbstract3DSymbol> symbol( src->
symbol3D( details.name ) );
1253 const bool hasDuplicateName = dst->
symbol3DNames().contains( details.name );
1254 bool overwriteThis =
false;
1256 addItemToFavorites = favorite3dSymbols.contains( details.name );
1258 if ( hasDuplicateName && prompt )
1260 cursorOverride.reset();
1261 int res = QMessageBox::warning(
1263 isImport ? tr(
"Import 3D Symbol" ) : tr(
"Export 3D Symbol" ),
1264 tr(
"A 3D symbol with the name “%1” already exists.\nOverwrite?" ).arg( details.name ),
1265 QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No | QMessageBox::NoToAll | QMessageBox::Cancel
1267 cursorOverride = std::make_unique<QgsTemporaryCursorOverride>( Qt::WaitCursor );
1270 case QMessageBox::Cancel:
1273 case QMessageBox::No:
1276 case QMessageBox::Yes:
1277 overwriteThis =
true;
1280 case QMessageBox::YesToAll:
1282 overwriteAll =
true;
1285 case QMessageBox::NoToAll:
1287 overwriteAll =
false;
1295 if ( !hasDuplicateName || overwriteAll || overwriteThis )
1297 QgsAbstract3DSymbol *newSymbol = symbol.get();
1298 dst->
addSymbol3D( details.name, symbol.release() );
1299 dst->
saveSymbol3D( details.name, newSymbol, addItemToFavorites, symbolTags );
1307 std::unique_ptr<QgsAbstractMaterialSettings > settings( src->
materialSettings( details.name ) );
1312 bool overwriteThis =
false;
1314 addItemToFavorites = favoriteMaterialSettings.contains( details.name );
1316 if ( hasDuplicateName && prompt )
1318 cursorOverride.reset();
1319 int res = QMessageBox::warning(
1321 isImport ? tr(
"Import Material" ) : tr(
"Export Material" ),
1322 tr(
"A material with the name “%1” already exists.\nOverwrite?" ).arg( details.name ),
1323 QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No | QMessageBox::NoToAll | QMessageBox::Cancel
1325 cursorOverride = std::make_unique<QgsTemporaryCursorOverride>( Qt::WaitCursor );
1328 case QMessageBox::Cancel:
1331 case QMessageBox::No:
1334 case QMessageBox::Yes:
1335 overwriteThis =
true;
1338 case QMessageBox::YesToAll:
1340 overwriteAll =
true;
1343 case QMessageBox::NoToAll:
1345 overwriteAll =
false;
1353 if ( !hasDuplicateName || overwriteAll || overwriteThis )
1355 QgsAbstractMaterialSettings *newSettings = settings.
get();
1371bool QgsStyleManagerDialog::addTextFormat()
1373 QgsTextFormat format;
1374 QgsTextFormatDialog formatDlg( format,
nullptr,
this );
1375 formatDlg.setWindowTitle( tr(
"New Text Format" ) );
1376 if ( !formatDlg.exec() )
1378 format = formatDlg.format();
1381 const QString defaultTag = groupTree->currentIndex().isValid() ? groupTree->currentIndex().data( GroupModelRoles::TagName ).toString() : QString();
1382 saveDlg.setDefaultTags( defaultTag );
1383 if ( !saveDlg.exec() )
1385 QString name = saveDlg.name();
1388 bool nameInvalid =
true;
1389 while ( nameInvalid )
1392 if ( name.isEmpty() )
1394 QMessageBox::warning(
this, tr(
"Save Text Format" ), tr(
"Cannot save text format without name. Enter a name." ) );
1396 else if ( mStyle->textFormatNames().contains( name ) )
1398 int res = QMessageBox::warning(
this, tr(
"Save Text Format" ), tr(
"Text format with name '%1' already exists. Overwrite?" ).arg( name ), QMessageBox::Yes | QMessageBox::No );
1399 if ( res == QMessageBox::Yes )
1401 mStyle->removeTextFormat( name );
1402 nameInvalid =
false;
1408 nameInvalid =
false;
1413 name = QInputDialog::getText(
this, tr(
"Text Format Name" ), tr(
"Please enter a name for new text format:" ), QLineEdit::Normal, name, &ok );
1421 QStringList symbolTags = saveDlg.tags().split(
',' );
1424 mStyle->addTextFormat( name, format );
1425 mStyle->saveTextFormat( name, format, saveDlg.isFavorite(), symbolTags );
1433 groupChanged( groupTree->selectionModel()->currentIndex() );
1444 switch ( tabItemType->currentIndex() )
1471 QModelIndex index = listItems->selectionModel()->currentIndex();
1472 if ( !index.isValid() )
1475 return mModel->data( mModel->index( index.row(),
QgsStyleModel::Name, index.parent() ), Qt::DisplayRole ).toString();
1480 bool changed =
false;
1491 changed = addTextFormat();
1510 changed = addMaterialSettings();
1514 Q_ASSERT(
false &&
"not implemented" );
1527 QString name = tr(
"new symbol" );
1528 QString dialogTitle;
1533 name = tr(
"new marker" );
1534 dialogTitle = tr(
"New Marker Symbol" );
1538 name = tr(
"new line" );
1539 dialogTitle = tr(
"New Line Symbol" );
1543 name = tr(
"new fill symbol" );
1544 dialogTitle = tr(
"New Fill Symbol" );
1547 Q_ASSERT(
false &&
"unknown symbol type" );
1557 dlg.setWindowTitle( dialogTitle );
1558 if ( dlg.exec() == 0 )
1565 const QString defaultTag = groupTree->currentIndex().isValid() ? groupTree->currentIndex().data( GroupModelRoles::TagName ).toString() : QString();
1567 if ( !saveDlg.exec() )
1573 name = saveDlg.
name();
1576 bool nameInvalid =
true;
1577 while ( nameInvalid )
1580 if ( name.isEmpty() )
1582 QMessageBox::warning(
this, tr(
"Save Symbol" ), tr(
"Cannot save symbol without name. Enter a name." ) );
1584 else if ( mStyle->symbolNames().contains( name ) )
1586 int res = QMessageBox::warning(
this, tr(
"Save Symbol" ), tr(
"Symbol with name '%1' already exists. Overwrite?" ).arg( name ), QMessageBox::Yes | QMessageBox::No );
1587 if ( res == QMessageBox::Yes )
1589 mStyle->removeSymbol( name );
1590 nameInvalid =
false;
1596 nameInvalid =
false;
1601 name = QInputDialog::getText(
this, tr(
"Symbol Name" ), tr(
"Please enter a name for new symbol:" ), QLineEdit::Normal, name, &ok );
1610 QStringList symbolTags = saveDlg.
tags().split(
',' );
1613 mStyle->addSymbol( name, symbol );
1614 mStyle->saveSymbol( name, symbol, saveDlg.
isFavorite(), symbolTags );
1623 QString rampType = type;
1625 if ( rampType.isEmpty() )
1630 QStringList rampTypeNames;
1631 rampTypeNames.reserve( rampTypes.size() );
1632 for (
const QPair<QString, QString> &type : rampTypes )
1633 rampTypeNames << type.second;
1634 const QString selectedRampTypeName = QInputDialog::getItem( parent, tr(
"Color Ramp Type" ), tr(
"Please select color ramp type:" ), rampTypeNames, 0,
false, &ok );
1635 if ( !ok || selectedRampTypeName.isEmpty() )
1638 rampType = rampTypes.value( rampTypeNames.indexOf( selectedRampTypeName ) ).first;
1641 QString name = tr(
"new ramp" );
1643 std::unique_ptr<QgsColorRamp> ramp;
1647 dlg.setWindowTitle( tr(
"New Gradient Color Ramp" ) );
1653 name = tr(
"new gradient ramp" );
1658 dlg.setWindowTitle( tr(
"New Random Color Ramp" ) );
1664 name = tr(
"new random ramp" );
1669 dlg.setWindowTitle( tr(
"New ColorBrewer Ramp" ) );
1680 dlg.setWindowTitle( tr(
"New Preset Color Ramp" ) );
1686 name = tr(
"new preset ramp" );
1691 dlg.setWindowTitle( tr(
"New cpt-city Color Ramp" ) );
1716 if ( !saveDlg.exec() )
1721 name = saveDlg.
name();
1724 bool nameInvalid =
true;
1725 while ( nameInvalid )
1728 if ( name.isEmpty() )
1730 QMessageBox::warning( parent, tr(
"Save Color Ramp" ), tr(
"Cannot save color ramp without name. Enter a name." ) );
1734 int res = QMessageBox::warning( parent, tr(
"Save Color Ramp" ), tr(
"Color ramp with name '%1' already exists. Overwrite?" ).arg( name ), QMessageBox::Yes | QMessageBox::No );
1735 if ( res == QMessageBox::Yes )
1737 nameInvalid =
false;
1743 nameInvalid =
false;
1748 name = QInputDialog::getText( parent, tr(
"Color Ramp Name" ), tr(
"Please enter a name for new color ramp:" ), QLineEdit::Normal, name, &ok );
1756 QStringList colorRampTags = saveDlg.
tags().split(
',' );
1768 mFavoritesGroupVisible = show;
1774 mSmartGroupVisible = show;
1786 setWindowState( windowState() & ~Qt::WindowMinimized );
1794 if ( !rampName.isEmpty() )
1806 if ( selectedItemType() < 3 )
1810 else if ( selectedItemType() == 3 )
1814 else if ( selectedItemType() == 4 )
1818 else if ( selectedItemType() == 5 )
1820 editLabelSettings();
1822 else if ( selectedItemType() == 6 )
1824 editLegendPatchShape();
1826 else if ( selectedItemType() == 7 )
1830 else if ( selectedItemType() == 8 )
1832 editMaterialSettings();
1836 Q_ASSERT(
false &&
"not implemented" );
1843 if ( symbolName.isEmpty() )
1846 std::unique_ptr<QgsSymbol> symbol( mStyle->symbol( symbolName ) );
1850 dlg.setWindowTitle( symbolName );
1852 dlg.
buttonBox()->button( QDialogButtonBox::Ok )->setEnabled(
false );
1858 mStyle->addSymbol( symbolName, symbol.release(),
true );
1866 if ( name.isEmpty() )
1869 std::unique_ptr<QgsColorRamp> ramp( mStyle->colorRamp( name ) );
1875 dlg.setWindowTitle( name );
1877 dlg.
buttonBox()->button( QDialogButtonBox::Ok )->setEnabled(
false );
1889 dlg.setWindowTitle( name );
1891 dlg.
buttonBox()->button( QDialogButtonBox::Ok )->setEnabled(
false );
1903 dlg.setWindowTitle( name );
1905 dlg.
buttonBox()->button( QDialogButtonBox::Ok )->setEnabled(
false );
1917 dlg.setWindowTitle( name );
1919 dlg.
buttonBox()->button( QDialogButtonBox::Ok )->setEnabled(
false );
1931 dlg.setWindowTitle( name );
1933 dlg.
buttonBox()->button( QDialogButtonBox::Ok )->setEnabled(
false );
1950 Q_ASSERT(
false &&
"invalid ramp type" );
1953 mStyle->addColorRamp( name, ramp.release(),
true );
1958bool QgsStyleManagerDialog::editTextFormat()
1961 if ( formatName.isEmpty() )
1968 dlg.setWindowTitle( formatName );
1970 dlg.buttonBox()->button( QDialogButtonBox::Ok )->setEnabled(
false );
1983 QgsPalLayerSettings settings;
1984 QgsLabelSettingsDialog settingsDlg( settings,
nullptr,
nullptr,
this, type );
1985 settingsDlg.setWindowTitle( tr(
"New Label Settings" ) );
1987 settingsDlg.buttonBox()->button( QDialogButtonBox::Ok )->setEnabled(
false );
1989 if ( !settingsDlg.exec() )
1992 settings = settingsDlg.settings();
1996 const QString defaultTag = groupTree->currentIndex().isValid() ? groupTree->currentIndex().data( GroupModelRoles::TagName ).toString() : QString();
1997 saveDlg.setDefaultTags( defaultTag );
1998 if ( !saveDlg.exec() )
2000 QString name = saveDlg.name();
2003 bool nameInvalid =
true;
2004 while ( nameInvalid )
2007 if ( name.isEmpty() )
2009 QMessageBox::warning(
this, tr(
"Save Label Settings" ), tr(
"Cannot save label settings without a name. Enter a name." ) );
2011 else if ( mStyle->labelSettingsNames().contains( name ) )
2013 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 );
2014 if ( res == QMessageBox::Yes )
2016 mStyle->removeLabelSettings( name );
2017 nameInvalid =
false;
2023 nameInvalid =
false;
2028 name = QInputDialog::getText(
this, tr(
"Label Settings Name" ), tr(
"Please enter a name for the new label settings:" ), QLineEdit::Normal, name, &ok );
2036 QStringList symbolTags = saveDlg.tags().split(
',' );
2039 mStyle->addLabelSettings( name, settings );
2040 mStyle->saveLabelSettings( name, settings, saveDlg.isFavorite(), symbolTags );
2046bool QgsStyleManagerDialog::editLabelSettings()
2049 if ( formatName.isEmpty() )
2052 QgsPalLayerSettings settings = mStyle->labelSettings( formatName );
2056 QgsLabelSettingsDialog dlg( settings,
nullptr,
nullptr,
this, geomType );
2057 dlg.setWindowTitle( formatName );
2061 settings = dlg.settings();
2065 mStyle->addLabelSettings( formatName, settings,
true );
2072 QgsLegendPatchShape shape = mStyle->defaultPatch( type, QSizeF( 10, 5 ) );
2073 QgsLegendPatchShapeDialog dialog( shape,
this );
2074 dialog.setWindowTitle( tr(
"New Legend Patch Shape" ) );
2076 dialog.buttonBox()->button( QDialogButtonBox::Ok )->setEnabled(
false );
2078 if ( !dialog.exec() )
2081 shape = dialog.shape();
2084 const QString defaultTag = groupTree->currentIndex().isValid() ? groupTree->currentIndex().data( GroupModelRoles::TagName ).toString() : QString();
2085 saveDlg.setDefaultTags( defaultTag );
2086 if ( !saveDlg.exec() )
2088 QString name = saveDlg.name();
2091 bool nameInvalid =
true;
2092 while ( nameInvalid )
2095 if ( name.isEmpty() )
2097 QMessageBox::warning(
this, tr(
"Save Legend Patch Shape" ), tr(
"Cannot save legend patch shapes without a name. Enter a name." ) );
2099 else if ( mStyle->legendPatchShapeNames().contains( name ) )
2101 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 );
2102 if ( res == QMessageBox::Yes )
2105 nameInvalid =
false;
2111 nameInvalid =
false;
2116 name = QInputDialog::getText(
this, tr(
"Legend Patch Shape Name" ), tr(
"Please enter a name for the new legend patch shape:" ), QLineEdit::Normal, name, &ok );
2124 QStringList symbolTags = saveDlg.tags().split(
',' );
2127 mStyle->addLegendPatchShape( name, shape );
2128 mStyle->saveLegendPatchShape( name, shape, saveDlg.isFavorite(), symbolTags );
2134bool QgsStyleManagerDialog::editLegendPatchShape()
2137 if ( shapeName.isEmpty() )
2140 QgsLegendPatchShape shape = mStyle->legendPatchShape( shapeName );
2145 QgsLegendPatchShapeDialog dlg( shape,
this );
2146 dlg.setWindowTitle( shapeName );
2150 shape = dlg.shape();
2153 mStyle->addLegendPatchShape( shapeName, shape,
true );
2158bool QgsStyleManagerDialog::addSymbol3D(
const QString &type )
2164 Qgs3DSymbolDialog dialog( symbol.get(),
this );
2165 dialog.setWindowTitle( tr(
"New 3D Symbol" ) );
2167 dialog.buttonBox()->button( QDialogButtonBox::Ok )->setEnabled(
false );
2169 if ( !dialog.exec() )
2172 symbol.reset( dialog.symbol() );
2177 const QString defaultTag = groupTree->currentIndex().isValid() ? groupTree->currentIndex().data( GroupModelRoles::TagName ).toString() : QString();
2178 saveDlg.setDefaultTags( defaultTag );
2179 if ( !saveDlg.exec() )
2181 QString name = saveDlg.name();
2184 bool nameInvalid =
true;
2185 while ( nameInvalid )
2188 if ( name.isEmpty() )
2190 QMessageBox::warning(
this, tr(
"Save 3D Symbol" ), tr(
"Cannot save 3D symbols without a name. Enter a name." ) );
2192 else if ( mStyle->symbol3DNames().contains( name ) )
2194 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 );
2195 if ( res == QMessageBox::Yes )
2198 nameInvalid =
false;
2204 nameInvalid =
false;
2209 name = QInputDialog::getText(
this, tr(
"3D Symbol Name" ), tr(
"Please enter a name for the new 3D symbol:" ), QLineEdit::Normal, name, &ok );
2217 QStringList symbolTags = saveDlg.tags().split(
',' );
2220 QgsAbstract3DSymbol *newSymbol = symbol.get();
2221 mStyle->addSymbol3D( name, symbol.release() );
2222 mStyle->saveSymbol3D( name, newSymbol, saveDlg.isFavorite(), symbolTags );
2228bool QgsStyleManagerDialog::editSymbol3D()
2231 if ( symbolName.isEmpty() )
2234 std::unique_ptr<QgsAbstract3DSymbol> symbol( mStyle->symbol3D( symbolName ) );
2239 Qgs3DSymbolDialog dlg( symbol.get(),
this );
2240 dlg.setWindowTitle( symbolName );
2244 symbol.reset( dlg.symbol() );
2249 mStyle->addSymbol3D( symbolName, symbol.release(),
true );
2254bool QgsStyleManagerDialog::addMaterialSettings()
2256 QgsMaterialWidgetDialog dialog(
nullptr,
this );
2257 dialog.setWindowTitle( tr(
"New Material" ) );
2259 dialog.buttonBox()->button( QDialogButtonBox::Ok )->setEnabled(
false );
2261 if ( !dialog.exec() )
2264 std::unique_ptr< QgsAbstractMaterialSettings > settings = dialog.settings();
2269 const QString defaultTag = groupTree->currentIndex().isValid() ? groupTree->currentIndex().data( GroupModelRoles::TagName ).toString() : QString();
2270 saveDlg.setDefaultTags( defaultTag );
2271 if ( !saveDlg.exec() )
2273 QString name = saveDlg.name();
2276 bool nameInvalid =
true;
2277 while ( nameInvalid )
2280 if ( name.isEmpty() )
2282 QMessageBox::warning(
this, tr(
"Save Material" ), tr(
"Cannot save materials without a name. Enter a name." ) );
2284 else if ( mStyle->materialSettingsNames().contains( name ) )
2286 int res = QMessageBox::warning(
this, tr(
"Save Material" ), tr(
"A material with the name '%1' already exists. Overwrite?" ).arg( name ), QMessageBox::Yes | QMessageBox::No );
2287 if ( res == QMessageBox::Yes )
2290 nameInvalid =
false;
2296 nameInvalid =
false;
2301 name = QInputDialog::getText(
this, tr(
"Material Name" ), tr(
"Please enter a name for the new material:" ), QLineEdit::Normal, name, &ok );
2309 QStringList symbolTags = saveDlg.tags().split(
',' );
2312 QgsAbstractMaterialSettings *newSettings = settings.get();
2313 mStyle->addMaterialSettings( name, settings.release() );
2314 mStyle->saveMaterialSettings( name, newSettings, saveDlg.isFavorite(), symbolTags );
2320bool QgsStyleManagerDialog::editMaterialSettings()
2323 if ( settingsName.isEmpty() )
2326 std::unique_ptr<QgsAbstractMaterialSettings> settings( mStyle->materialSettings( settingsName ) );
2331 QgsMaterialWidgetDialog dlg( settings.get(),
this );
2332 dlg.setWindowTitle( settingsName );
2336 settings = dlg.settings();
2341 mStyle->addMaterialSettings( settingsName, settings.release(),
true );
2346void QgsStyleManagerDialog::addStyleDatabase(
bool createNew )
2349 if ( initialFolder.isEmpty() )
2350 initialFolder = QDir::homePath();
2352 QString databasePath = createNew ? QFileDialog::getSaveFileName(
this, tr(
"Create Style Database" ), initialFolder, tr(
"Style databases" ) +
" (*.db)" )
2353 : QFileDialog::getOpenFileName( this, tr(
"Add Style Database" ), initialFolder, tr(
"Style databases" ) +
" (*.db *.xml)" );
2357 if ( !databasePath.isEmpty() )
2364 if ( QFile::exists( databasePath ) )
2366 QFile::remove( databasePath );
2371 QMessageBox::warning(
this, tr(
"Create Style Database" ), tr(
"The style database could not be created" ) );
2383 const QList<ItemDetails> items = selectedItems();
2385 if ( allTypesSelected() )
2387 if ( QMessageBox::Yes
2388 != QMessageBox::question(
this, tr(
"Remove Items" ), QString( tr(
"Do you really want to remove %n item(s)?",
nullptr,
static_cast< int >( items.count() ) ) ), QMessageBox::Yes, QMessageBox::No ) )
2395 if ( QMessageBox::Yes
2396 != QMessageBox::question(
this, tr(
"Remove Symbol" ), QString( tr(
"Do you really want to remove %n symbol(s)?",
nullptr,
static_cast< int >( items.count() ) ) ), QMessageBox::Yes, QMessageBox::No ) )
2401 if ( QMessageBox::Yes
2402 != QMessageBox::question(
this, tr(
"Remove Color Ramp" ), QString( tr(
"Do you really want to remove %n ramp(s)?",
nullptr,
static_cast< int >( items.count() ) ) ), QMessageBox::Yes, QMessageBox::No ) )
2407 if ( QMessageBox::Yes
2409 question(
this, tr(
"Remove Text Formats" ), QString( tr(
"Do you really want to remove %n text format(s)?",
nullptr,
static_cast< int >( items.count() ) ) ), QMessageBox::Yes, QMessageBox::No ) )
2414 if ( QMessageBox::Yes
2416 question(
this, tr(
"Remove Label Settings" ), QString( tr(
"Do you really want to remove %n label setting(s)?",
nullptr,
static_cast< int >( items.count() ) ) ), QMessageBox::Yes, QMessageBox::No ) )
2421 if ( QMessageBox::Yes
2423 question(
this, tr(
"Remove Legend Patch Shapes" ), QString( tr(
"Do you really want to remove %n legend patch shape(s)?",
nullptr,
static_cast< int >( items.count() ) ) ), QMessageBox::Yes, QMessageBox::No ) )
2428 if ( QMessageBox::Yes
2430 question(
this, tr(
"Remove 3D Symbols" ), QString( tr(
"Do you really want to remove %n 3D symbol(s)?",
nullptr,
static_cast< int >( items.count() ) ) ), QMessageBox::Yes, QMessageBox::No ) )
2435 if ( QMessageBox::Yes
2437 question(
this, tr(
"Remove Material" ), QString( tr(
"Do you really want to remove %n material(s)?",
nullptr,
static_cast< int >( items.count() ) ) ), QMessageBox::Yes, QMessageBox::No ) )
2444 for (
const ItemDetails &details : items )
2446 if ( details.name.isEmpty() )
2449 mStyle->removeEntityByName( details.entityType, details.name );
2470 QString dir = QFileDialog::getExistingDirectory(
this, tr(
"Export Selected Symbols as PNG" ), QDir::home().absolutePath(), QFileDialog::DontResolveSymlinks );
2476 QString dir = QFileDialog::getExistingDirectory(
this, tr(
"Export Selected Symbols as SVG" ), QDir::home().absolutePath(), QFileDialog::DontResolveSymlinks );
2483 if ( dir.isEmpty() )
2486 const QList<ItemDetails> items = selectedItems();
2487 for (
const ItemDetails &details : items )
2492 QString path = dir +
'/' + details.name +
'.' + format;
2493 std::unique_ptr<QgsSymbol> sym( mStyle->symbol( details.name ) );
2495 sym->exportImage( path, format, size );
2515 QFont font = item->font();
2516 font.setBold(
true );
2517 item->setFont( font );
2522 if ( mBlockGroupUpdates )
2525 QStandardItemModel *model = qobject_cast<QStandardItemModel *>( groupTree->model() );
2528 const bool readOnly = isReadOnly();
2530 if ( mFavoritesGroupVisible )
2532 QStandardItem *favoriteSymbols =
new QStandardItem( tr(
"Favorites" ) );
2533 favoriteSymbols->setData(
"favorite" );
2534 favoriteSymbols->setEditable(
false );
2536 model->appendRow( favoriteSymbols );
2539 QStandardItem *allSymbols =
new QStandardItem( tr(
"All" ) );
2540 allSymbols->setData(
"all" );
2541 allSymbols->setEditable(
false );
2543 model->appendRow( allSymbols );
2545 QStandardItem *taggroup =
new QStandardItem( QString() );
2546 taggroup->setData(
"tags" );
2547 taggroup->setEditable(
false );
2548 QStringList tags = mStyle->tags();
2550 for (
const QString &tag : std::as_const( tags ) )
2552 QStandardItem *item =
new QStandardItem( tag );
2553 item->setData( mStyle->tagId( tag ) );
2554 item->setData( tag, GroupModelRoles::TagName );
2555 item->setEditable( !readOnly );
2556 taggroup->appendRow( item );
2558 taggroup->setText( tr(
"Tags" ) );
2560 model->appendRow( taggroup );
2562 if ( mSmartGroupVisible )
2564 QStandardItem *smart =
new QStandardItem( tr(
"Smart Groups" ) );
2565 smart->setData(
"smartgroups" );
2566 smart->setEditable(
false );
2569 QgsSymbolGroupMap::const_iterator i = sgMap.constBegin();
2570 while ( i != sgMap.constEnd() )
2572 QStandardItem *item =
new QStandardItem( i.value() );
2573 item->setData( i.key() );
2574 item->setEditable( !readOnly );
2575 smart->appendRow( item );
2578 model->appendRow( smart );
2582 int rows = model->rowCount( model->indexFromItem( model->invisibleRootItem() ) );
2583 for (
int i = 0; i < rows; i++ )
2585 groupTree->setExpanded( model->indexFromItem( model->item( i ) ),
true );
2591 const QString category = index.data( Qt::UserRole + 1 ).toString();
2592 sPreviousTag = category;
2594 const bool readOnly = isReadOnly();
2596 if ( mGroupingMode && mModel )
2598 mModel->setTagId( -1 );
2599 mModel->setSmartGroupId( -1 );
2600 mModel->setFavoritesOnly(
false );
2601 mModel->setCheckTag( index.data( Qt::DisplayRole ).toString() );
2603 else if ( category ==
"all"_L1 || category ==
"tags"_L1 || category ==
"smartgroups"_L1 )
2606 if ( category ==
"tags"_L1 )
2608 actnAddTag->setEnabled( !readOnly );
2609 actnAddSmartgroup->setEnabled(
false );
2611 else if ( category ==
"smartgroups"_L1 )
2613 actnAddTag->setEnabled(
false );
2614 actnAddSmartgroup->setEnabled( !readOnly );
2619 mModel->setTagId( -1 );
2620 mModel->setSmartGroupId( -1 );
2621 mModel->setFavoritesOnly(
false );
2624 else if ( category ==
"favorite"_L1 )
2629 mModel->setTagId( -1 );
2630 mModel->setSmartGroupId( -1 );
2631 mModel->setFavoritesOnly(
true );
2634 else if ( index.parent().data( Qt::UserRole + 1 ) ==
"smartgroups" )
2636 actnRemoveGroup->setEnabled( !readOnly );
2637 btnManageGroups->setEnabled( !readOnly );
2638 const int groupId = index.data( Qt::UserRole + 1 ).toInt();
2641 mModel->setTagId( -1 );
2642 mModel->setSmartGroupId( groupId );
2643 mModel->setFavoritesOnly(
false );
2649 int tagId = index.data( Qt::UserRole + 1 ).toInt();
2652 mModel->setTagId( tagId );
2653 mModel->setSmartGroupId( -1 );
2654 mModel->setFavoritesOnly(
false );
2658 actnEditSmartGroup->setVisible(
false );
2659 actnAddTag->setVisible(
false );
2660 actnAddSmartgroup->setVisible(
false );
2661 actnRemoveGroup->setVisible(
false );
2662 actnTagSymbols->setVisible(
false );
2663 actnFinishTagging->setVisible(
false );
2665 if ( index.parent().isValid() )
2667 if ( index.parent().data( Qt::UserRole + 1 ).toString() ==
"smartgroups"_L1 )
2669 actnEditSmartGroup->setVisible( !mGroupingMode && !readOnly );
2671 else if ( index.parent().data( Qt::UserRole + 1 ).toString() ==
"tags"_L1 )
2673 actnAddTag->setVisible( !mGroupingMode && !readOnly );
2674 actnTagSymbols->setVisible( !mGroupingMode && !readOnly );
2675 actnFinishTagging->setVisible( mGroupingMode && !readOnly );
2677 actnRemoveGroup->setVisible( !readOnly );
2679 else if ( index.data( Qt::UserRole + 1 ) ==
"smartgroups" )
2681 actnAddSmartgroup->setVisible( !mGroupingMode && !readOnly );
2683 else if ( index.data( Qt::UserRole + 1 ) ==
"tags" )
2685 actnAddTag->setVisible( !mGroupingMode && !readOnly );
2694 QStandardItemModel *model = qobject_cast<QStandardItemModel *>( groupTree->model() );
2696 for (
int i = 0; i < groupTree->model()->rowCount(); i++ )
2698 index = groupTree->model()->index( i, 0 );
2699 QString data = index.data( Qt::UserRole + 1 ).toString();
2700 if ( data ==
"tags"_L1 )
2709 itemName = QInputDialog::getText(
this, tr(
"Add Tag" ), tr(
"Please enter name for the new tag:" ), QLineEdit::Normal, tr(
"New tag" ), &ok ).trimmed();
2710 if ( !ok || itemName.isEmpty() )
2713 int check = mStyle->tagId( itemName );
2716 mMessageBar->pushCritical( tr(
"Add Tag" ), tr(
"The tag “%1” already exists." ).arg( itemName ) );
2722 mBlockGroupUpdates++;
2723 id = mStyle->addTag( itemName );
2724 mBlockGroupUpdates--;
2728 mMessageBar->pushCritical( tr(
"Add Tag" ), tr(
"New tag could not be created — There was a problem with the symbol database." ) );
2732 QStandardItem *parentItem = model->itemFromIndex( index );
2733 QStandardItem *childItem =
new QStandardItem( itemName );
2734 childItem->setData(
id );
2735 childItem->setData( itemName, GroupModelRoles::TagName );
2736 parentItem->appendRow( childItem );
2746 QStandardItemModel *model = qobject_cast<QStandardItemModel *>( groupTree->model() );
2748 for (
int i = 0; i < groupTree->model()->rowCount(); i++ )
2750 index = groupTree->model()->index( i, 0 );
2751 QString data = index.data( Qt::UserRole + 1 ).toString();
2752 if ( data ==
"smartgroups"_L1 )
2761 if ( dlg.exec() == QDialog::Rejected )
2766 mBlockGroupUpdates++;
2768 mBlockGroupUpdates--;
2774 QStandardItem *parentItem = model->itemFromIndex( index );
2775 QStandardItem *childItem =
new QStandardItem( itemName );
2776 childItem->setData(
id );
2777 parentItem->appendRow( childItem );
2787 QStandardItemModel *model = qobject_cast<QStandardItemModel *>( groupTree->model() );
2788 QModelIndex index = groupTree->currentIndex();
2791 QString data = index.data( Qt::UserRole + 1 ).toString();
2792 if ( data ==
"all"_L1 || data ==
"favorite"_L1 || data ==
"tags"_L1 || index.data() ==
"smartgroups" )
2795 int err = QMessageBox::critical(
2797 tr(
"Remove Group" ),
2799 "Invalid selection. Cannot delete system defined categories.\n"
2800 "Kindly select a group or smart group you might want to delete."
2807 QStandardItem *parentItem = model->itemFromIndex( index.parent() );
2811 mBlockGroupUpdates++;
2813 if ( parentItem->data( Qt::UserRole + 1 ).toString() ==
"smartgroups"_L1 )
2822 mBlockGroupUpdates--;
2823 parentItem->removeRow( index.row() );
2831 QgsDebugMsgLevel( u
"Symbol group edited: data=%1 text=%2"_s.arg( item->data( Qt::UserRole + 1 ).toString(), item->text() ), 2 );
2832 int id = item->data( Qt::UserRole + 1 ).toInt();
2833 QString name = item->text();
2834 mBlockGroupUpdates++;
2835 if ( item->parent()->data( Qt::UserRole + 1 ) ==
"smartgroups" )
2843 mBlockGroupUpdates--;
2851 QStandardItemModel *treeModel = qobject_cast<QStandardItemModel *>( groupTree->model() );
2853 if ( mGroupingMode )
2855 mGroupingMode =
false;
2856 mModel->setCheckable(
false );
2857 actnTagSymbols->setVisible(
true );
2858 actnFinishTagging->setVisible(
false );
2869 listItems->setSelectionMode( QAbstractItemView::ExtendedSelection );
2870 mSymbolTreeView->setSelectionMode( QAbstractItemView::ExtendedSelection );
2874 bool validGroup =
false;
2876 QModelIndex present = groupTree->currentIndex();
2877 while ( present.parent().isValid() )
2879 if ( present.parent().data() ==
"Tags" )
2884 present = present.parent();
2889 mGroupingMode =
true;
2891 actnTagSymbols->setVisible(
false );
2892 actnFinishTagging->setVisible(
true );
2899 btnManageGroups->setEnabled(
true );
2901 mModel->setCheckable(
true );
2904 listItems->setSelectionMode( QAbstractItemView::NoSelection );
2905 mSymbolTreeView->setSelectionMode( QAbstractItemView::NoSelection );
2917 mModel->setFilterString( qword );
2922 actnEditItem->setEnabled( index.isValid() && !mGroupingMode && !isReadOnly() );
2927 Q_UNUSED( selected )
2928 Q_UNUSED( deselected )
2929 const bool nothingSelected = listItems->selectionModel()->selectedIndexes().empty();
2930 const bool readOnly = isReadOnly();
2931 actnRemoveItem->setDisabled( nothingSelected || readOnly );
2932 actnAddFavorite->setDisabled( nothingSelected || readOnly );
2933 actnRemoveFavorite->setDisabled( nothingSelected || readOnly );
2934 mGroupListMenu->setDisabled( nothingSelected || readOnly );
2935 actnDetag->setDisabled( nothingSelected || readOnly );
2936 actnExportAsPNG->setDisabled( nothingSelected );
2937 actnExportAsSVG->setDisabled( nothingSelected );
2938 if ( mActionCopyToDefault )
2939 mActionCopyToDefault->setDisabled( nothingSelected );
2940 mCopyToDefaultButton->setDisabled( nothingSelected );
2941 actnEditItem->setDisabled( nothingSelected || readOnly );
2946 const bool readOnly = isReadOnly();
2947 groupTree->setEnabled( enable );
2948 btnAddTag->setEnabled( enable && !readOnly );
2949 btnAddSmartgroup->setEnabled( enable && !readOnly );
2950 actnAddTag->setEnabled( enable && !readOnly );
2951 actnAddSmartgroup->setEnabled( enable && !readOnly );
2952 actnRemoveGroup->setEnabled( enable && !readOnly );
2953 btnManageGroups->setEnabled( !readOnly && ( enable || mGroupingMode ) );
2954 searchBox->setEnabled( enable );
2959 const bool readOnly = isReadOnly();
2960 actnRemoveGroup->setEnabled( enable && !readOnly );
2961 btnManageGroups->setEnabled( !readOnly && ( enable || mGroupingMode ) );
2966 QStandardItemModel *treeModel = qobject_cast<QStandardItemModel *>( groupTree->model() );
2967 for (
int i = 0; i < treeModel->rowCount(); i++ )
2969 treeModel->item( i )->setEnabled( enable );
2971 if ( treeModel->item( i )->data() ==
"smartgroups" )
2973 for (
int j = 0; j < treeModel->item( i )->rowCount(); j++ )
2975 treeModel->item( i )->child( j )->setEnabled( enable );
2982 for (
int i = 0; i < symbolBtnsLayout->count(); i++ )
2984 QWidget *w = symbolBtnsLayout->itemAt( i )->widget();
2986 w->setEnabled( enable );
2990 actnRemoveItem->setEnabled( enable );
2991 actnEditItem->setEnabled( enable );
2992 mActionCopyItem->setEnabled( enable );
2993 mActionPasteItem->setEnabled( enable );
2998 QPoint globalPos = groupTree->viewport()->mapToGlobal( point );
3000 QModelIndex index = groupTree->indexAt( point );
3001 if ( index.isValid() && !mGroupingMode )
3002 mGroupTreeContextMenu->popup( globalPos );
3007 QPoint globalPos = mSymbolViewStackedWidget->currentIndex() == 0 ? listItems->viewport()->mapToGlobal( point ) : mSymbolTreeView->viewport()->mapToGlobal( point );
3010 mGroupListMenu->clear();
3012 const QModelIndexList indices = listItems->selectionModel()->selectedRows();
3014 if ( !isReadOnly() )
3016 const QStringList currentTags = indices.count() == 1 ? indices.at( 0 ).data(
static_cast<int>(
QgsStyleModel::CustomRole::Tag ) ).toStringList() : QStringList();
3017 QAction *a =
nullptr;
3018 QStringList tags = mStyle->tags();
3020 for (
const QString &tag : std::as_const( tags ) )
3022 a =
new QAction( tag, mGroupListMenu );
3024 if ( indices.count() == 1 )
3026 a->setCheckable(
true );
3027 a->setChecked( currentTags.contains( tag ) );
3030 mGroupListMenu->addAction( a );
3033 if ( tags.count() > 0 )
3035 mGroupListMenu->addSeparator();
3037 a =
new QAction( tr(
"Create New Tag…" ), mGroupListMenu );
3038 connect( a, &QAction::triggered,
this, [
this](
bool ) {
tagSelectedSymbols(
true ); } );
3039 mGroupListMenu->addAction( a );
3042 const QList<ItemDetails> items = selectedItems();
3045 bool enablePaste =
false;
3051 const QMimeData *mimeData = QApplication::clipboard()->mimeData();
3052 if ( mimeData->hasFormat(
"application/qgis.labelsettings"_L1 ) )
3061 mActionPasteItem->setEnabled( enablePaste );
3063 mGroupMenu->popup( globalPos );
3071 const QList<ItemDetails> items = selectedItems();
3072 for (
const ItemDetails &details : items )
3074 mStyle->addFavorite( details.entityType, details.name );
3083 const QList<ItemDetails> items = selectedItems();
3084 for (
const ItemDetails &details : items )
3086 mStyle->removeFavorite( details.entityType, details.name );
3092 QAction *selectedItem = qobject_cast<QAction *>( sender() );
3095 const QList<ItemDetails> items = selectedItems();
3105 tag = mStyle->tag(
id );
3109 tag = selectedItem->data().toString();
3112 for (
const ItemDetails &details : items )
3114 mStyle->tagSymbol( details.entityType, details.name, QStringList( tag ) );
3124 QAction *selectedItem = qobject_cast<QAction *>( sender() );
3128 const QList<ItemDetails> items = selectedItems();
3129 for (
const ItemDetails &details : items )
3131 mStyle->detagSymbol( details.entityType, details.name );
3141 QStandardItemModel *treeModel = qobject_cast<QStandardItemModel *>( groupTree->model() );
3144 QModelIndex present = groupTree->currentIndex();
3145 if ( present.parent().data( Qt::UserRole + 1 ) !=
"smartgroups" )
3148 QMessageBox::critical(
this, tr(
"Edit Smart Group" ), tr(
"You have not selected a Smart Group. Kindly select a Smart Group to edit." ) );
3151 QStandardItem *item = treeModel->itemFromIndex( present );
3156 dlg.
setOperator( mStyle->smartgroupOperator( item->data().toInt() ) );
3159 if ( dlg.exec() == QDialog::Rejected )
3162 mBlockGroupUpdates++;
3165 mBlockGroupUpdates--;
3168 mMessageBar->pushCritical( tr(
"Edit Smart Group" ), tr(
"There was an error while editing the smart group." ) );
3172 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.
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.
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.
static QgsPalLayerSettings fromMimeData(const QMimeData *data, bool *ok=nullptr)
Attempts to parse the provided mime data as a QgsPalLayerSettings.
Qgis::GeometryType layerType
Geometry type of layers associated with these settings.
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 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...
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.
static QgsSettingsProxy get()
Returns a proxy for a QgsSettings object.
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
@ 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.
friend class QgsStyleExportImportDialog
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.
QgsTextFormat textFormat(const QString &name) const
Returns the text format with the specified name.
QStringList tags() const
Returns a list of all tags in the style database.
QStringList symbol3DNames() const
Returns a list of names of 3d symbols in the style.
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.
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.
@ MaterialSettingsEntity
Material settings.
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.
bool saveMaterialSettings(const QString &name, QgsAbstractMaterialSettings *settings, bool favorite, const QStringList &tags)
Adds 3D material settings to the database.
QStringList colorRampNames() const
Returns a list of names of color ramps.
std::unique_ptr< QgsAbstractMaterialSettings > materialSettings(const QString &name) const
Returns a new copy of the 3D material settings with the specified name.
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 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.
bool addMaterialSettings(const QString &name, QgsAbstractMaterialSettings *settings, bool update=false)
Adds a 3D material settings with the specified name to the style.
static QgsStyle * defaultStyle(bool initialize=true)
Returns the default application-wide style.
QStringList materialSettingsNames() const
Returns a list of names of 3D material settings in the 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 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.
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 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