17#include "moc_qgslabelingengineruleswidget.cpp"
26#include <QDialogButtonBox>
34 : 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] {
285 std::sort( actions.begin(), actions.end(), [](
const QAction *a,
const QAction *b ) ->
bool {
286 return QString::localeAwareCompare( a->text(), b->text() ) < 0;
288 mAddRuleMenu->addActions( actions );
291void QgsLabelingEngineRulesWidget::createRule(
const QString &
id )
296 rule->setName( rule->displayType() );
298 const QModelIndex newRuleIndex = mModel->
index( mModel->
rowCount() - 1, 0, QModelIndex() );
299 viewRules->selectionModel()->setCurrentIndex( newRuleIndex, QItemSelectionModel::SelectionFlag::ClearAndSelect );
300 editRule( newRuleIndex );
304void QgsLabelingEngineRulesWidget::editSelectedRule()
306 const QItemSelection selection = viewRules->selectionModel()->selection();
307 for (
const QItemSelectionRange &range : selection )
309 if ( range.isValid() )
311 const QModelIndex index = range.indexes().value( 0 );
318void QgsLabelingEngineRulesWidget::editRule(
const QModelIndex &index )
326 if ( rule->
id() ==
"minimumDistanceLabelToFeature" )
328 widget =
new QgsLabelingEngineRuleMinimumDistanceLabelToFeatureWidget();
330 else if ( rule->
id() ==
"minimumDistanceLabelToLabel" )
332 widget =
new QgsLabelingEngineRuleMinimumDistanceLabelToLabelWidget();
334 else if ( rule->
id() ==
"maximumDistanceLabelToFeature" )
336 widget =
new QgsLabelingEngineRuleMaximumDistanceLabelToFeatureWidget();
338 else if ( rule->
id() ==
"avoidLabelOverlapWithFeature" )
340 widget =
new QgsLabelingEngineRuleAvoidLabelOverlapWithFeatureWidget();
349 widget->
setPanelTitle( rule->
name().isEmpty() ? tr(
"Configure Rule" ) : rule->name() );
352 std::unique_ptr<QgsAbstractLabelingEngineRule> updatedRule( widget->
rule() );
361 dialog.setRule( rule );
364 std::unique_ptr<QgsAbstractLabelingEngineRule> updatedRule( dialog.rule() );
371void QgsLabelingEngineRulesWidget::removeRules()
373 const QItemSelection selection = viewRules->selectionModel()->selection();
375 for (
const QItemSelectionRange &range : selection )
377 if ( range.isValid() )
379 for (
int row = range.top(); row <= range.bottom(); ++row )
381 if ( !rows.contains( row ) )
387 std::sort( rows.begin(), rows.end() );
388 std::reverse( rows.begin(), rows.end() );
389 for (
int row : std::as_const( rows ) )
391 mModel->removeRow( row );
401 : QDialog( parent, flags )
403 setWindowTitle( tr(
"Configure Rules" ) );
404 setObjectName( QStringLiteral(
"QgsLabelingEngineRulesDialog" ) );
408 QVBoxLayout *layout =
new QVBoxLayout(
this );
409 layout->addWidget( mWidget );
411 mButtonBox =
new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal,
this );
412 layout->addWidget( mButtonBox );
417 connect( mButtonBox->button( QDialogButtonBox::Ok ), &QAbstractButton::clicked,
this, &QDialog::accept );
418 connect( mButtonBox->button( QDialogButtonBox::Cancel ), &QAbstractButton::clicked,
this, &QDialog::reject );
428 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.