35#include <QInputDialog>
46#include "moc_qgsmasksourceselectionwidget.cpp"
48using namespace Qt::StringLiterals;
50static void expandAll( QTreeWidgetItem *item )
52 for (
int i = 0; i < item->childCount(); i++ )
53 expandAll( item->child( i ) );
54 item->setExpanded(
true );
59 std::cout << ref.
layerId().toLocal8Bit().constData() <<
"/" << ref.
symbolLayerIdV2().toLocal8Bit().constData();
65 QVBoxLayout *vbox =
new QVBoxLayout();
66 vbox->setContentsMargins( 0, 0, 0, 0 );
68 QHBoxLayout *hLayout =
new QHBoxLayout();
70 mSetComboBox =
new QComboBox();
72 mManagerModel->setAllowEmptyObject(
true );
74 mManagerProxyModel->setSourceModel( mManagerModel );
75 mSetComboBox->setModel( mManagerProxyModel );
76 connect( mSetComboBox, qOverload< int >( &QComboBox::currentIndexChanged ),
this, &QgsMaskSourceSelectionWidget::selectedSetChanged );
78 mSetsToolButton =
new QToolButton();
79 mSetsToolButton->setText( u
"…"_s );
80 mSetsToolButton->setPopupMode( QToolButton::InstantPopup );
82 QMenu *toolMenu =
new QMenu( mSetsToolButton );
83 connect( toolMenu, &QMenu::aboutToShow,
this, [
this] {
84 const bool isCustomSelected = isCustomSet();
85 mRemoveAction->setEnabled( !isCustomSelected );
86 mRenameAction->setEnabled( !isCustomSelected );
88 QAction *addAction =
new QAction( tr(
"New Selective Masking Set…" ), toolMenu );
89 connect( addAction, &QAction::triggered,
this, &QgsMaskSourceSelectionWidget::newSet );
90 toolMenu->addAction( addAction );
91 mRemoveAction =
new QAction( tr(
"Remove Set…" ), toolMenu );
92 connect( mRemoveAction, &QAction::triggered,
this, &QgsMaskSourceSelectionWidget::removeSet );
93 toolMenu->addAction( mRemoveAction );
94 mRenameAction =
new QAction( tr(
"Rename Set…" ), toolMenu );
95 connect( mRenameAction, &QAction::triggered,
this, &QgsMaskSourceSelectionWidget::renameSet );
96 toolMenu->addAction( mRenameAction );
97 mSetsToolButton->setMenu( toolMenu );
99 hLayout->addWidget(
new QLabel( tr(
"Preset" ) ) );
100 hLayout->addWidget( mSetComboBox, 1 );
101 hLayout->addWidget( mSetsToolButton, 1 );
102 vbox->addLayout( hLayout );
104 mTree =
new QTreeWidget(
this );
105 mTree->setHeaderHidden(
true );
107 connect( mTree, &QTreeWidget::itemChanged,
this, &QgsMaskSourceSelectionWidget::onItemChanged );
109 vbox->addWidget( mTree, 1 );
116 mBlockChangedSignals++;
123 SymbolLayerFillVisitor( QTreeWidgetItem *layerItem,
const QgsVectorLayer *layer, QHash<QgsSymbolLayerReference, QTreeWidgetItem *> &items, QScreen *screen )
124 : mLayerItem( layerItem )
143 : sl( _sl ), symbol( _symbol ) {};
147 QList<TreeNode> children;
151 bool visitSymbol( TreeNode &parent,
const QString &identifier,
const QgsSymbol *symbol, QVector<int> rootPath )
159 QVector<int> indexPath = rootPath;
160 indexPath.append( idx );
162 TreeNode node( symbol, sl );
163 if ( ( sl->
layerType() ==
"MaskMarker" ) || ( subSymbol && visitSymbol( node, identifier, subSymbol, indexPath ) ) )
166 parent.children << node;
178 const QgsSymbol *symbol = symbolEntity->symbol();
182 TreeNode node( symbol );
183 if ( visitSymbol( node, leaf.
identifier, symbol, {} ) )
189 void createItems(
const QString &leafDescription, QTreeWidgetItem *rootItem,
const TreeNode &node )
191 QTreeWidgetItem *item =
nullptr;
195 item =
new QTreeWidgetItem( rootItem, QStringList() << ( mCurrentDescription + leafDescription ) );
197 item->setIcon( 0, icon );
202 item =
new QTreeWidgetItem( rootItem );
204 item->setIcon( 0, slIcon );
205 if ( node.sl->layerType() ==
"MaskMarker" )
207 item->setText( 0, QObject::tr(
"Mask symbol layer" ) );
208 item->setFlags( item->flags() | Qt::ItemIsUserCheckable );
209 item->setCheckState( 0, Qt::Unchecked );
216 rootItem->addChild( item );
218 for ( TreeNode child : node.children )
219 createItems( leafDescription, item, child );
223 QString mCurrentDescription;
224 QTreeWidgetItem *mLayerItem;
226 QHash<QgsSymbolLayerReference, QTreeWidgetItem *> &mItems;
227 QPointer<QScreen> mScreen;
233 LabelMasksVisitor( QTreeWidgetItem *layerItem,
const QgsVectorLayer *layer, QHash<QgsSymbolLayerReference, QTreeWidgetItem *> &items )
234 : mLayerItem( layerItem ), mLayer( layer ), mItems( items )
251 if ( labelSettingsEntity->settings().format().mask().enabled() )
253 const QString maskTitle = currentRule.isEmpty()
254 ? QObject::tr(
"Label mask" )
255 : QObject::tr(
"Label mask for '%1' rule" ).arg( currentDescription );
256 QTreeWidgetItem *slItem =
new QTreeWidgetItem( mLayerItem, QStringList() << maskTitle );
257 slItem->setFlags( slItem->flags() | Qt::ItemIsUserCheckable );
258 slItem->setCheckState( 0, Qt::Unchecked );
259 mLayerItem->addChild( slItem );
266 QHash<QString, QHash<QString, QSet<QgsSymbolLayerId>>> masks;
269 QString currentDescription;
270 QTreeWidgetItem *mLayerItem;
272 QHash<QgsSymbolLayerReference, QTreeWidgetItem *> &mItems;
286 auto layerItem = std::make_unique<QTreeWidgetItem>( mTree, QStringList() << layer->
name() );
287 layerItem->setData( 0, Qt::UserRole, QVariant::fromValue( vl ) );
291 LabelMasksVisitor lblVisitor( layerItem.get(), vl, mItems );
295 SymbolLayerFillVisitor slVisitor( layerItem.get(), vl, mItems, screen() );
298 if ( layerItem->childCount() > 0 )
299 mTree->addTopLevelItem( layerItem.release() );
302 expandAll( mTree->invisibleRootItem() );
303 mBlockChangedSignals--;
310 const QModelIndex selectedIndex = mManagerProxyModel->mapToSource( mManagerProxyModel->index( mSetComboBox->currentIndex(), 0 ) );
314 set.
setName( mManagerModel->data( selectedIndex, Qt::DisplayRole ).toString() );
318 for (
auto it = mItems.begin(); it != mItems.end(); it++ )
320 if ( it.value()->checkState( 0 ) == Qt::Checked )
324 const bool isLabeling = ref.
layerId().startsWith(
"__labels__" );
345 mBlockChangedSignals++;
346 for (
auto it = mItems.begin(); it != mItems.end(); it++ )
348 it.value()->setCheckState( 0, Qt::Unchecked );
351 const QVector< QgsSelectiveMaskSource > sources = set.
sources();
355 switch ( source.sourceType() )
358 layerId = source.layerId();
361 layerId = u
"__labels__%1"_s.arg( source.layerId() );
365 if ( it != mItems.end() )
367 it.value()->setCheckState( 0, Qt::Checked );
372 mSetComboBox->setCurrentIndex( 0 );
376 mSetComboBox->setCurrentIndex( mSetComboBox->findText( set.
name() ) );
378 mBlockChangedSignals--;
381void QgsMaskSourceSelectionWidget::selectedSetChanged()
383 mBlockChangedSignals++;
384 if ( !isCustomSet() )
386 const QModelIndex selectedIndex = mManagerProxyModel->mapToSource( mManagerProxyModel->index( mSetComboBox->currentIndex(), 0 ) );
391 mBlockChangedSignals--;
396void QgsMaskSourceSelectionWidget::emitChanged()
398 if ( !mBlockChangedSignals )
404void QgsMaskSourceSelectionWidget::onItemChanged()
406 if ( mBlockChangedSignals )
409 if ( !isCustomSet() )
411 const QgsSelectiveMaskingSourceSet set =
sourceSet();
417void QgsMaskSourceSelectionWidget::newSet()
421 QStringList existingNames;
423 existingNames.reserve( sets.size() );
424 for (
const QgsSelectiveMaskingSourceSet &set : sets )
426 existingNames << set.
name();
429 QgsNewNameDialog dlg( tr(
"selective masking set" ), newTitle, QStringList(), existingNames, Qt::CaseSensitive,
this );
430 dlg.setWindowTitle( tr(
"Create Selective Masking Set" ) );
431 dlg.setHintString( tr(
"Enter a unique selective masking set name" ) );
432 dlg.setOverwriteEnabled(
false );
433 dlg.setAllowEmptyName(
false );
434 dlg.setConflictingNameWarning( tr(
"A masking set with this name already exists." ) );
436 if ( dlg.exec() != QDialog::Accepted )
441 QgsSelectiveMaskingSourceSet newSet;
442 newSet.setName( dlg.name() );
444 mSetComboBox->setCurrentIndex( mSetComboBox->findText( newSet.name() ) );
447void QgsMaskSourceSelectionWidget::removeSet()
452 const QString setName = mSetComboBox->currentText();
453 if ( QMessageBox::warning(
this, tr(
"Remove Selective Masking Set" ), tr(
"Do you really want to remove the selective masking set “%1”?" ).arg( setName ), QMessageBox::Ok | QMessageBox::Cancel ) != QMessageBox::Ok )
458 mSetComboBox->setCurrentIndex( 0 );
462void QgsMaskSourceSelectionWidget::renameSet()
467 const QString setName = mSetComboBox->currentText();
469 QStringList existingNames;
471 existingNames.reserve( sets.size() );
472 for (
const QgsSelectiveMaskingSourceSet &set : sets )
474 if ( set.
name() != setName )
475 existingNames << set.
name();
478 QgsNewNameDialog dlg( tr(
"selective masking set" ), setName, QStringList(), existingNames, Qt::CaseSensitive,
this );
479 dlg.setWindowTitle( tr(
"Rename Selective Masking Set" ) );
480 dlg.setHintString( tr(
"Enter a unique selective masking set name" ) );
481 dlg.setOverwriteEnabled(
false );
482 dlg.setAllowEmptyName(
false );
483 dlg.setConflictingNameWarning( tr(
"A masking set with this name already exists." ) );
485 if ( dlg.exec() != QDialog::Accepted )
493bool QgsMaskSourceSelectionWidget::isCustomSet()
const
495 const QModelIndex selectedIndex = mManagerProxyModel->mapToSource( mManagerProxyModel->index( mSetComboBox->currentIndex(), 0 ) );
@ Label
A mask generated from a labeling provider.
@ SymbolLayer
A mask generated from a symbol layer.
@ Millimeters
Millimeters.
virtual bool accept(QgsStyleEntityVisitorInterface *visitor) const
Accepts the specified symbology visitor, causing it to visit all symbols associated with the labeling...
virtual bool accept(QgsStyleEntityVisitorInterface *visitor) const
Accepts the specified symbology visitor, causing it to visit all symbols associated with the renderer...
QList< QgsLayerTreeLayer * > findLayers() const
Find all layer nodes.
Layer tree node points to a map layer.
Base class for all map layer types.
Struct for storing maximum and minimum scales for measurements in map units.
static QgsProject * instance()
Returns the QgsProject singleton instance.
QgsLayerTree * layerTreeRoot() const
Returns pointer to the root (invisible) node of the project's layer tree.
const QgsSelectiveMaskingSourceSetManager * selectiveMaskingSourceSetManager() const
Returns the project's selective masking set manager, which manages storage of a set of selective mask...
Stores properties relating to a screen.
Encapsulates a single source for selective masking (e.g.
void setSourceId(const QString &id)
Sets the symbol layer or label rule id.
void setLayerId(const QString &id)
Sets the source layer id.
void setSourceType(Qgis::SelectiveMaskSourceType type)
Sets the source type.
List model representing the selective masking source sets available in a selective masking source set...
QVariant data(const QModelIndex &index, int role) const override
@ IsEmptyObject
true if row represents the empty object
@ SetId
Selective masking source set unique ID.
QSortFilterProxyModel subclass for QgsSelectiveMaskingSourceSetManagerModel.
bool renameSet(const QString &oldName, const QString &newName)
Renames a set in the manager from oldName to newName.
QVector< QgsSelectiveMaskingSourceSet > sets() const
Returns a list of all sets contained in the manager.
QgsSelectiveMaskingSourceSet setById(const QString &id) const
Returns the set with a matching id, or an invalid set if no matching sets were found.
bool addSet(const QgsSelectiveMaskingSourceSet &set)
Adds a set to the manager.
QString generateUniqueTitle() const
Generates a unique title for a new set, which does not clash with any already contained by the manage...
bool removeSet(const QString &name)
Removes the set with matching name from the manager.
bool updateSet(const QgsSelectiveMaskingSourceSet &set)
Updates the definition of a set already in the manager.
Represents a named set of selective masking sources (QgsSelectiveMaskSource).
void setName(const QString &name)
Sets the set's unique name.
void setId(const QString &id)
Sets the unique identifier for the set.
QVector< QgsSelectiveMaskSource > sources() const
Returns the list of selective mask sources configured in this set.
void append(const QgsSelectiveMaskSource &source)
Appends a source to the set.
QString name() const
Returns the set's unique name.
bool isValid() const
Returns true if the source set is valid, or false if it is invalid (default constructed).
virtual QgsStyle::StyleEntity type() const =0
Returns the type of style entity.
An interface for classes which can visit style entity (e.g.
@ SymbolRule
Rule based symbology or label child rule.
A label settings entity for QgsStyle databases.
A symbol entity for QgsStyle databases.
@ LabelSettingsEntity
Label settings.
Type used to refer to a specific symbol layer in a symbol of a layer.
QString symbolLayerIdV2() const
The symbol layer's id.
QString layerId() const
The referenced vector layer / feature renderer.
static QIcon symbolLayerPreviewIcon(const QgsSymbolLayer *layer, Qgis::RenderUnit u, QSize size, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::SymbolType parentSymbolType=Qgis::SymbolType::Hybrid, QgsMapLayer *mapLayer=nullptr, const QgsScreenProperties &screen=QgsScreenProperties())
Draws a symbol layer preview to an icon.
static QIcon symbolPreviewIcon(const QgsSymbol *symbol, QSize size, int padding=0, QgsLegendPatchShape *shape=nullptr, const QgsScreenProperties &screen=QgsScreenProperties())
Returns an icon preview for a color ramp.
Abstract base class for symbol layers.
virtual QString layerType() const =0
Returns a string that represents this layer type.
virtual QgsSymbol * subSymbol()
Returns the symbol's sub symbol, if present.
Abstract base class for all rendered symbols.
int symbolLayerCount() const
Returns the total number of symbol layers contained in the symbol.
Represents a vector layer which manages a vector based dataset.
const QgsAbstractVectorLayerLabeling * labeling() const
Access to const labeling configuration.
QgsFeatureRenderer * renderer()
Returns the feature renderer used for rendering the features in the layer in 2D map views.
int scaleIconSize(int standardSize)
Scales an icon size to compensate for display pixel density, making the icon size hi-dpi friendly,...
Contains information relating to a node (i.e.
QString identifier
A string identifying the node.
QString description
A string describing the node.
QgsStyleEntityVisitorInterface::NodeType type
Node type.
Contains information relating to the style entity currently being visited.
QString description
A string describing the style entity.
const QgsStyleEntityInterface * entity
Reference to style entity being visited.
QString identifier
A string identifying the style entity.