25#include <QDialogButtonBox>
33 : QAbstractItemModel( parent )
42 return Qt::ItemFlags();
44 Qt::ItemFlags res = Qt::ItemIsSelectable;
47 res |= Qt::ItemIsEnabled | Qt::ItemIsEditable;
50 if (
index.column() == 0 )
52 res |= Qt::ItemIsUserCheckable;
70 return static_cast< int >( mRules.size() );
96 return tr(
"This rule is not available for use on this system." );
101 case Qt::CheckStateRole:
103 if (
index.column() != 0 )
105 return rule->
active() ? Qt::Checked : Qt::Unchecked;
117 if ( hasIndex( row, column,
parent ) )
119 return createIndex( row, column, row );
122 return QModelIndex();
127 if ( row < 0 || row >=
static_cast< int >( mRules.size() ) )
130 beginRemoveRows(
parent, row, row + count - 1 );
131 for (
int i = 0; i < count; i++ )
133 if ( row <
static_cast< int >( mRules.size() ) )
135 mRules.erase( mRules.begin() + row );
144 if ( !
index.isValid() )
153 case Qt::CheckStateRole:
155 rule->
setActive( value.toInt() == Qt::Checked );
162 if (
index.column() == 0 )
164 rule->
setName( value.toString() );
184 mRules.emplace_back( rule->clone() );
191 beginInsertRows( QModelIndex(),
static_cast< int >( mRules.size() ),
static_cast< int >( mRules.size() ) );
192 mRules.emplace_back( std::move( rule ) );
198 if ( !
index.isValid() )
201 if (
index.row() < 0 ||
index.row() >=
static_cast< int >( mRules.size() ) )
204 return mRules[
index.row() ].get();
209 if ( !
index.isValid() )
212 if (
index.row() < 0 ||
index.row() >=
static_cast< int >( mRules.size() ) )
215 mRules[
index.row() ] = std::move( rule );
221 QList<QgsAbstractLabelingEngineRule *> res;
222 res.reserve(
static_cast< int >( mRules.size() ) );
223 for (
auto &it : mRules )
225 res.append( it->clone() );
243 viewRules->setModel( mModel );
244 viewRules->setHeaderHidden(
true );
246 mAddRuleMenu =
new QMenu(
this );
247 connect( mAddRuleMenu, &QMenu::aboutToShow,
this, &QgsLabelingEngineRulesWidget::createTypesMenu );
249 btnAddRule->setMenu( mAddRuleMenu );
250 btnAddRule->setPopupMode( QToolButton::InstantPopup );
252 connect( btnEditRule, &QToolButton::clicked,
this, &QgsLabelingEngineRulesWidget::editSelectedRule );
253 connect( btnRemoveRule, &QToolButton::clicked,
this, &QgsLabelingEngineRulesWidget::removeRules );
255 connect( viewRules, &QAbstractItemView::doubleClicked,
this, &QgsLabelingEngineRulesWidget::editRule );
265 return mModel->
rules();
268void QgsLabelingEngineRulesWidget::createTypesMenu()
270 mAddRuleMenu->clear();
273 QList< QAction * > actions;
274 for (
const QString &
id : ruleIds )
280 connect( action, &QAction::triggered,
this, [
this,
id ]
286 std::sort( actions.begin(), actions.end(), [](
const QAction * a,
const QAction * b ) ->
bool
288 return QString::localeAwareCompare( a->text(), b->text() ) < 0;
290 mAddRuleMenu->addActions( actions );
293void QgsLabelingEngineRulesWidget::createRule(
const QString &
id )
298 rule->setName( rule->displayType() );
300 const QModelIndex newRuleIndex = mModel->
index( mModel->
rowCount() - 1, 0, QModelIndex() );
301 viewRules->selectionModel()->setCurrentIndex( newRuleIndex, QItemSelectionModel::SelectionFlag::ClearAndSelect );
302 editRule( newRuleIndex );
306void QgsLabelingEngineRulesWidget::editSelectedRule()
308 const QItemSelection selection = viewRules->selectionModel()->selection();
309 for (
const QItemSelectionRange &range : selection )
311 if ( range.isValid() )
313 const QModelIndex index = range.indexes().value( 0 );
320void QgsLabelingEngineRulesWidget::editRule(
const QModelIndex &index )
328 if ( rule->
id() ==
"minimumDistanceLabelToFeature" )
330 widget =
new QgsLabelingEngineRuleMinimumDistanceLabelToFeatureWidget();
332 else if ( rule->
id() ==
"minimumDistanceLabelToLabel" )
334 widget =
new QgsLabelingEngineRuleMinimumDistanceLabelToLabelWidget();
336 else if ( rule->
id() ==
"maximumDistanceLabelToFeature" )
338 widget =
new QgsLabelingEngineRuleMaximumDistanceLabelToFeatureWidget();
340 else if ( rule->
id() ==
"avoidLabelOverlapWithFeature" )
342 widget =
new QgsLabelingEngineRuleAvoidLabelOverlapWithFeatureWidget();
351 widget->
setPanelTitle( rule->
name().isEmpty() ? tr(
"Configure Rule" ) : rule->name() );
355 std::unique_ptr< QgsAbstractLabelingEngineRule > updatedRule( widget->
rule() );
364 dialog.setRule( rule );
367 std::unique_ptr< QgsAbstractLabelingEngineRule > updatedRule( dialog.rule() );
374void QgsLabelingEngineRulesWidget::removeRules()
376 const QItemSelection selection = viewRules->selectionModel()->selection();
378 for (
const QItemSelectionRange &range : selection )
380 if ( range.isValid() )
382 for (
int row = range.top(); row <= range.bottom(); ++row )
384 if ( !rows.contains( row ) )
390 std::sort( rows.begin(), rows.end() );
391 std::reverse( rows.begin(), rows.end() );
392 for (
int row : std::as_const( rows ) )
394 mModel->removeRow( row );
404 : QDialog( parent, flags )
406 setWindowTitle( tr(
"Configure Rules" ) );
407 setObjectName( QStringLiteral(
"QgsLabelingEngineRulesDialog" ) );
411 QVBoxLayout *layout =
new QVBoxLayout(
this );
412 layout->addWidget( mWidget );
414 mButtonBox =
new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal,
this );
415 layout->addWidget( mButtonBox );
420 connect( mButtonBox->button( QDialogButtonBox::Ok ), &QAbstractButton::clicked,
this, &QDialog::accept );
421 connect( mButtonBox->button( QDialogButtonBox::Cancel ), &QAbstractButton::clicked,
this, &QDialog::reject );
431 return mWidget->
rules();
Abstract base class for labeling engine rules.
void setActive(bool active)
Sets whether the rule is active.
virtual bool isAvailable() const
Returns true if the rule is available for use within the current QGIS environment.
bool active() const
Returns true if the rule is active.
QString name() const
Returns the name for this instance of the rule.
virtual QString displayType() const =0
Returns a user-friendly, translated string representing the rule type.
virtual QString description() const
Returns a user-friendly description of the rule.
void setName(const QString &name)
Sets the name for this instance of the rule.
virtual QString id() const =0
Returns a string uniquely identifying the rule subclass.
static QgsLabelingEngineRuleRegistry * labelingEngineRuleRegistry()
Gets the registry of available labeling engine rules.
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...
A simple dialog for customizing a labeling engine rule.
QStringList ruleIds() const
Returns a list of the rule IDs for rules present in the registry.
QList< QgsAbstractLabelingEngineRule * > rules() const
Returns the rules shown in the dialog.
void setRules(const QList< QgsAbstractLabelingEngineRule * > &rules)
Sets the rules to show in the dialog.
QgsLabelingEngineRulesDialog(QWidget *parent=nullptr, Qt::WindowFlags flags=QgsGuiUtils::ModalDialogFlags)
Constructor for QgsLabelingEngineRulesDialog.
A model for configuration of a list of labeling engine rules.
QModelIndex index(int row, int column, const QModelIndex &parent) const override
int columnCount(const QModelIndex &parent=QModelIndex()) const override
void setRules(const QList< QgsAbstractLabelingEngineRule * > &rules)
Sets the rules to include in the model.
QModelIndex parent(const QModelIndex &child) const override
QgsLabelingEngineRulesModel(QObject *parent=nullptr)
Constructor for QgsLabelingEngineRulesModel.
QList< QgsAbstractLabelingEngineRule * > rules() const
Returns the rules shown in the widget.
QgsAbstractLabelingEngineRule * ruleAtIndex(const QModelIndex &index) const
Returns the rule at the specified model index.
bool removeRows(int row, int count, const QModelIndex &parent=QModelIndex()) override
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole) override
void addRule(std::unique_ptr< QgsAbstractLabelingEngineRule > &rule)
Adds a rule to the model.
int rowCount(const QModelIndex &parent=QModelIndex()) const override
Qt::ItemFlags flags(const QModelIndex &index) const override
~QgsLabelingEngineRulesModel() override
void changeRule(const QModelIndex &index, std::unique_ptr< QgsAbstractLabelingEngineRule > &rule)
Swaps the rule at the specified index for a new rule.