17#include "moc_qgslabelingengineruleswidget.cpp"
27#include <QDialogButtonBox>
35 : QAbstractItemModel( parent )
43 return Qt::ItemFlags();
45 Qt::ItemFlags res = Qt::ItemIsSelectable;
48 res |= Qt::ItemIsEnabled | Qt::ItemIsEditable;
51 if (
index.column() == 0 )
53 res |= Qt::ItemIsUserCheckable;
71 return static_cast<int>( mRules.size() );
97 return tr(
"This rule is not available for use on this system." );
102 case Qt::CheckStateRole:
104 if (
index.column() != 0 )
106 return rule->
active() ? Qt::Checked : Qt::Unchecked;
118 if ( hasIndex( row, column,
parent ) )
120 return createIndex( row, column, row );
123 return QModelIndex();
128 if ( row < 0 || row >=
static_cast<int>( mRules.size() ) )
131 beginRemoveRows(
parent, row, row + count - 1 );
132 for (
int i = 0; i < count; i++ )
134 if ( row <
static_cast<int>( mRules.size() ) )
136 mRules.erase( mRules.begin() + row );
145 if ( !
index.isValid() )
154 case Qt::CheckStateRole:
156 rule->
setActive( value.toInt() == Qt::Checked );
163 if (
index.column() == 0 )
165 rule->
setName( value.toString() );
185 mRules.emplace_back( rule->clone() );
192 beginInsertRows( QModelIndex(),
static_cast<int>( mRules.size() ),
static_cast<int>( mRules.size() ) );
193 mRules.emplace_back( std::move( rule ) );
199 if ( !
index.isValid() )
202 if (
index.row() < 0 ||
index.row() >=
static_cast<int>( mRules.size() ) )
205 return mRules[
index.row()].get();
210 if ( !
index.isValid() )
213 if (
index.row() < 0 ||
index.row() >=
static_cast<int>( mRules.size() ) )
216 mRules[
index.row()] = std::move( rule );
222 QList<QgsAbstractLabelingEngineRule *> res;
223 res.reserve(
static_cast<int>( mRules.size() ) );
224 for (
auto &it : mRules )
226 res.append( it->clone() );
244 viewRules->setModel( mModel );
245 viewRules->setHeaderHidden(
true );
247 mAddRuleMenu =
new QMenu(
this );
248 connect( mAddRuleMenu, &QMenu::aboutToShow,
this, &QgsLabelingEngineRulesWidget::createTypesMenu );
250 btnAddRule->setMenu( mAddRuleMenu );
251 btnAddRule->setPopupMode( QToolButton::InstantPopup );
253 connect( btnEditRule, &QToolButton::clicked,
this, &QgsLabelingEngineRulesWidget::editSelectedRule );
254 connect( btnRemoveRule, &QToolButton::clicked,
this, &QgsLabelingEngineRulesWidget::removeRules );
256 connect( viewRules, &QAbstractItemView::doubleClicked,
this, &QgsLabelingEngineRulesWidget::editRule );
266 return mModel->
rules();
269void QgsLabelingEngineRulesWidget::createTypesMenu()
271 mAddRuleMenu->clear();
274 QList<QAction *> actions;
275 for (
const QString &
id : ruleIds )
281 connect( action, &QAction::triggered,
this, [
this,
id] {
286 std::sort( actions.begin(), actions.end(), [](
const QAction *a,
const QAction *b ) ->
bool {
287 return QString::localeAwareCompare( a->text(), b->text() ) < 0;
289 mAddRuleMenu->addActions( actions );
292void QgsLabelingEngineRulesWidget::createRule(
const QString &
id )
297 rule->setName( rule->displayType() );
299 const QModelIndex newRuleIndex = mModel->
index( mModel->
rowCount() - 1, 0, QModelIndex() );
300 viewRules->selectionModel()->setCurrentIndex( newRuleIndex, QItemSelectionModel::SelectionFlag::ClearAndSelect );
301 editRule( newRuleIndex );
305void QgsLabelingEngineRulesWidget::editSelectedRule()
307 const QItemSelection selection = viewRules->selectionModel()->selection();
308 for (
const QItemSelectionRange &range : selection )
310 if ( range.isValid() )
312 const QModelIndex index = range.indexes().value( 0 );
319void QgsLabelingEngineRulesWidget::editRule(
const QModelIndex &index )
327 if ( rule->
id() ==
"minimumDistanceLabelToFeature" )
329 widget =
new QgsLabelingEngineRuleMinimumDistanceLabelToFeatureWidget();
331 else if ( rule->
id() ==
"minimumDistanceLabelToLabel" )
333 widget =
new QgsLabelingEngineRuleMinimumDistanceLabelToLabelWidget();
335 else if ( rule->
id() ==
"maximumDistanceLabelToFeature" )
337 widget =
new QgsLabelingEngineRuleMaximumDistanceLabelToFeatureWidget();
339 else if ( rule->
id() ==
"avoidLabelOverlapWithFeature" )
341 widget =
new QgsLabelingEngineRuleAvoidLabelOverlapWithFeatureWidget();
350 widget->
setPanelTitle( rule->
name().isEmpty() ? tr(
"Configure Rule" ) : rule->name() );
353 std::unique_ptr<QgsAbstractLabelingEngineRule> updatedRule( widget->
rule() );
362 dialog.setRule( rule );
365 std::unique_ptr<QgsAbstractLabelingEngineRule> updatedRule( dialog.rule() );
372void QgsLabelingEngineRulesWidget::removeRules()
374 const QItemSelection selection = viewRules->selectionModel()->selection();
376 for (
const QItemSelectionRange &range : selection )
378 if ( range.isValid() )
380 for (
int row = range.top(); row <= range.bottom(); ++row )
382 if ( !rows.contains( row ) )
388 std::sort( rows.begin(), rows.end() );
389 std::reverse( rows.begin(), rows.end() );
390 for (
int row : std::as_const( rows ) )
392 mModel->removeRow( row );
402 : QDialog( parent, flags )
404 setWindowTitle( tr(
"Configure Rules" ) );
405 setObjectName( QStringLiteral(
"QgsLabelingEngineRulesDialog" ) );
409 QVBoxLayout *layout =
new QVBoxLayout(
this );
410 layout->addWidget( mWidget );
412 mButtonBox =
new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::Help, Qt::Horizontal,
this );
413 layout->addWidget( mButtonBox );
418 connect( mButtonBox->button( QDialogButtonBox::Ok ), &QAbstractButton::clicked,
this, &QDialog::accept );
419 connect( mButtonBox->button( QDialogButtonBox::Cancel ), &QAbstractButton::clicked,
this, &QDialog::reject );
420 connect( mButtonBox, &QDialogButtonBox::helpRequested,
this, [=] {
421 QgsHelp::openHelp( QStringLiteral(
"working_with_vector/vector_properties.html#labeling-rules" ) );
432 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...
static void openHelp(const QString &key)
Opens help topic for the given help key using default system web browser.
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.