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.