33#include "moc_qgssourcefieldsproperties.cpp"
35using namespace Qt::StringLiterals;
45 layout()->setContentsMargins( 0, 0, 0, 0 );
56 connect( mAddAttributeButton, &QAbstractButton::clicked,
this, &QgsSourceFieldsProperties::addAttributeClicked );
57 connect( mDeleteAttributeButton, &QAbstractButton::clicked,
this, &QgsSourceFieldsProperties::deleteAttributeClicked );
58 connect( mCalculateFieldButton, &QAbstractButton::clicked,
this, &QgsSourceFieldsProperties::calculateFieldClicked );
59 connect( mSaveLayerEditsButton, &QAbstractButton::clicked,
this, &QgsSourceFieldsProperties::saveLayerEditsClicked );
69 mFieldsList->setSelectionBehavior( QAbstractItemView::SelectRows );
70 mFieldsList->setDragDropMode( QAbstractItemView::DragOnly );
71 mFieldsList->setHorizontalHeaderItem(
AttrIdCol,
new QTableWidgetItem( tr(
"Id" ) ) );
72 mFieldsList->setHorizontalHeaderItem(
AttrNameCol,
new QTableWidgetItem( tr(
"Name" ) ) );
73 mFieldsList->setHorizontalHeaderItem(
AttrTypeCol,
new QTableWidgetItem( tr(
"Type" ) ) );
74 mFieldsList->setHorizontalHeaderItem(
AttrTypeNameCol,
new QTableWidgetItem( tr(
"Type name" ) ) );
75 mFieldsList->setHorizontalHeaderItem(
AttrLengthCol,
new QTableWidgetItem( tr(
"Length" ) ) );
76 mFieldsList->setHorizontalHeaderItem(
AttrPrecCol,
new QTableWidgetItem( tr(
"Precision" ) ) );
77 mFieldsList->setHorizontalHeaderItem(
AttrCommentCol,
new QTableWidgetItem( tr(
"Comment" ) ) );
78 const auto configurationFlagsWi =
new QTableWidgetItem( tr(
"Configuration" ) );
79 configurationFlagsWi->setToolTip( tr(
"Configures the field" ) );
81 mFieldsList->setHorizontalHeaderItem(
AttrAliasCol,
new QTableWidgetItem( tr(
"Alias" ) ) );
82 const auto fieldDomainWidget =
new QTableWidgetItem( tr(
"Field Domain" ) );
83 fieldDomainWidget->setToolTip( tr(
"Field domain associated with the field" ) );
86 mFieldsList->setSortingEnabled(
true );
87 mFieldsList->sortByColumn( 0, Qt::AscendingOrder );
88 mFieldsList->setSelectionBehavior( QAbstractItemView::SelectRows );
89 mFieldsList->setSelectionMode( QAbstractItemView::ExtendedSelection );
90 mFieldsList->horizontalHeader()->setStretchLastSection(
true );
91 mFieldsList->verticalHeader()->hide();
104 disconnect( mFieldsList, &QTableWidget::cellChanged,
this, &QgsSourceFieldsProperties::attributesListCellChanged );
108 mFieldsList->setRowCount( 0 );
110 for (
int i = 0; i < fields.
count(); ++i )
113 if (
mLayer->dataProvider() )
118 mFieldsList->resizeColumnsToContents();
119 connect( mFieldsList, &QTableWidget::cellChanged,
this, &QgsSourceFieldsProperties::attributesListCellChanged );
121 connect( mFieldsList, &QTableWidget::cellPressed,
this, &QgsSourceFieldsProperties::attributesListCellPressed );
124 updateFieldRenamingStatus();
127void QgsSourceFieldsProperties::updateFieldRenamingStatus()
131 for (
int row = 0; row < mFieldsList->rowCount(); ++row )
133 if ( canRenameFields )
134 mFieldsList->item( row,
AttrNameCol )->setFlags( mFieldsList->item( row,
AttrNameCol )->flags() | Qt::ItemIsEditable );
136 mFieldsList->item( row,
AttrNameCol )->setFlags( mFieldsList->item( row,
AttrNameCol )->flags() & ~Qt::ItemIsEditable );
140void QgsSourceFieldsProperties::updateExpression()
142 QToolButton *btn = qobject_cast<QToolButton *>( sender() );
145 const int index = btn->property(
"Index" ).toInt();
147 const QString exp =
mLayer->expressionField( index );
149 QgsExpressionContext context;
152 QgsExpressionBuilderDialog dlg(
mLayer, exp,
nullptr, u
"generic"_s, context );
156 mLayer->updateExpressionField( index, dlg.expressionText() );
161void QgsSourceFieldsProperties::attributeAdded(
int idx )
163 const bool sorted = mFieldsList->isSortingEnabled();
165 mFieldsList->setSortingEnabled(
false );
167 const QgsFields &fields =
mLayer->fields();
168 const int row = mFieldsList->rowCount();
169 mFieldsList->insertRow( row );
170 setRow( row, idx, fields.
at( idx ) );
171 mFieldsList->setCurrentCell( row, idx );
173 const QColor expressionColor = QColor( 103, 0, 243, 44 );
174 const QColor joinColor = QColor( 0, 243, 79, 44 );
175 const QColor defaultColor = QColor( 252, 255, 79, 44 );
177 for (
int i = 0; i < mFieldsList->columnCount(); i++ )
182 switch (
mLayer->fields().fieldOrigin( idx ) )
187 mFieldsList->item( row, i )->setBackground( expressionColor );
191 mFieldsList->item( row, i )->setBackground( joinColor );
195 if ( defaultColor.isValid() )
196 mFieldsList->item( row, i )->setBackground( defaultColor );
202 mFieldsList->setSortingEnabled(
true );
204 if (
mLayer->dataProvider() )
211void QgsSourceFieldsProperties::attributeDeleted(
int idx )
223 QTableWidgetItem *dataItem =
new QTableWidgetItem();
224 dataItem->setData( Qt::DisplayRole, idx );
225 dataItem->setIcon(
mLayer->fields().iconForField( idx,
true ) );
226 mFieldsList->setItem( row,
AttrIdCol, dataItem );
233 mFieldsList->setItem( row,
AttrNameCol,
new QTableWidgetItem( field.
name() ) );
234 mFieldsList->setItem( row,
AttrAliasCol,
new QTableWidgetItem( field.
alias() ) );
237 mFieldsList->setItem( row,
AttrLengthCol,
new QTableWidgetItem( QString::number( field.
length() ) ) );
238 mFieldsList->setItem( row,
AttrPrecCol,
new QTableWidgetItem( QString::number( field.
precision() ) ) );
242 QWidget *expressionWidget =
new QWidget;
243 expressionWidget->setLayout(
new QHBoxLayout );
244 QToolButton *editExpressionButton =
new QToolButton;
245 editExpressionButton->setProperty(
"Index", idx );
247 connect( editExpressionButton, &QAbstractButton::clicked,
this, &QgsSourceFieldsProperties::updateExpression );
248 expressionWidget->layout()->setContentsMargins( 0, 0, 0, 0 );
249 expressionWidget->layout()->addWidget( editExpressionButton );
250 expressionWidget->layout()->addWidget(
new QLabel(
mLayer->expressionField( idx ) ) );
251 expressionWidget->setStyleSheet(
"*[class~=\"QWidget\"] { background-color: rgba( 103, 0, 243, 0.12 ); } QToolButton { background-color: rgba( 203, 100, 243, 0.6 ); }" );
252 mFieldsList->setCellWidget( row,
AttrCommentCol, expressionWidget );
264 mFieldsList->item( row, i )->setFlags( mFieldsList->item( row, i )->flags() & ~Qt::ItemIsEditable );
266 mFieldsList->item( row, i )->setToolTip( tr(
"Edit alias in the Form config tab" ) );
269 if ( canRenameFields )
270 mFieldsList->item( row,
AttrNameCol )->setFlags( mFieldsList->item( row,
AttrNameCol )->flags() | Qt::ItemIsEditable );
272 mFieldsList->item( row,
AttrNameCol )->setFlags( mFieldsList->item( row,
AttrNameCol )->flags() & ~Qt::ItemIsEditable );
290 mLayer->beginEditCommand( tr(
"Added attribute" ) );
291 if (
mLayer->addAttribute( field ) )
298 mLayer->destroyEditCommand();
299 QMessageBox::critical(
this, tr(
"Add Field" ), tr(
"Failed to add field '%1' of type '%2'. Is the field name unique?" ).arg( field.
name(), field.
typeName() ) );
309void QgsSourceFieldsProperties::applyToLayer(
QgsVectorLayer *layer )
311 for (
int i = 0; i < mFieldsList->rowCount(); i++ )
313 const int idx = mFieldsList->item( i,
AttrIdCol )->data( Qt::DisplayRole ).toInt();
320 for (
int r = 0; r < model->rowCount(); ++r )
322 const QModelIndex index = model->index( r, 0 );
324 const bool active = model->
data( index, Qt::CheckStateRole ).value<Qt::CheckState>() == Qt::Checked ?
true : false;
325 flags.setFlag( flag, active );
334void QgsSourceFieldsProperties::editingToggled()
337 updateFieldRenamingStatus();
340void QgsSourceFieldsProperties::addAttributeClicked()
347 QgsAddAttrDialog dialog(
mLayer,
this );
348 if ( dialog.exec() == QDialog::Accepted )
355void QgsSourceFieldsProperties::deleteAttributeClicked()
357 QSet<int> providerFields;
358 QSet<int> expressionFields;
359 const auto constSelectedItems = mFieldsList->selectedItems();
360 for ( QTableWidgetItem *item : constSelectedItems )
362 if ( item->column() == 0 )
369 expressionFields << idx;
371 providerFields << idx;
375 if ( !expressionFields.isEmpty() )
376 mLayer->deleteAttributes( expressionFields.values() );
378 if ( !providerFields.isEmpty() )
380 mLayer->beginEditCommand( tr(
"Deleted attributes" ) );
381 if (
mLayer->deleteAttributes( providerFields.values() ) )
384 mLayer->destroyEditCommand();
388void QgsSourceFieldsProperties::calculateFieldClicked()
395 QgsFieldCalculator calc(
mLayer,
this );
396 if ( calc.exec() == QDialog::Accepted )
402void QgsSourceFieldsProperties::saveLayerEditsClicked()
404 mLayer->commitChanges(
false );
407void QgsSourceFieldsProperties::attributesListCellChanged(
int row,
int column )
413 QTableWidgetItem *nameItem = mFieldsList->item( row, column );
415 if ( !nameItem || nameItem->text().isEmpty() || !
mLayer->fields().exists( idx ) ||
mLayer->fields().at( idx ).name() == nameItem->text() )
418 mLayer->beginEditCommand( tr(
"Rename attribute" ) );
419 if (
mLayer->renameAttribute( idx, nameItem->text() ) )
425 mLayer->destroyEditCommand();
426 QMessageBox::critical(
this, tr(
"Rename Field" ), tr(
"Failed to rename field to '%1'. Is the field name unique?" ).arg( nameItem->text() ) );
431void QgsSourceFieldsProperties::attributesListCellPressed(
int ,
int )
446 if (
mLayer->isEditable() )
450 mToggleEditingButton->setChecked(
true );
451 mSaveLayerEditsButton->setEnabled(
true );
452 mSaveLayerEditsButton->setChecked(
true );
456 mToggleEditingButton->setChecked(
false );
457 mAddAttributeButton->setEnabled(
false );
458 mSaveLayerEditsButton->setEnabled(
false );
461 mDeleteAttributeButton->setEnabled( !mFieldsList->selectedItems().isEmpty() );
463 const auto constSelectedItems = mFieldsList->selectedItems();
464 for ( QTableWidgetItem *item : constSelectedItems )
466 if ( item->column() == 0 )
471 mDeleteAttributeButton->setEnabled(
false );
@ AddAttributes
Allows addition of new attributes (fields).
@ ReadFieldDomains
Provider can read field domains and their properties.
@ RenameAttributes
Supports renaming attributes (fields).
@ DeleteAttributes
Allows deletion of attributes (fields).
@ ChangeAttributeValues
Allows modification of attribute values.
QFlags< VectorProviderCapability > VectorProviderCapabilities
Vector data provider capabilities.
@ Expression
Field is calculated from an expression.
@ Join
Field originates from a joined layer.
FieldConfigurationFlag
Configuration flags for fields These flags are meant to be user-configurable and are not describing a...
@ NoFlag
No flag is defined.
QFlags< FieldConfigurationFlag > FieldConfigurationFlags
Configuration flags for fields These flags are meant to be user-configurable and are not describing a...
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
QComboBox subclass which allows selecting multiple items.
QgsCheckableItemModel * model() const
Returns the custom item model which handles checking the items.
void addItemWithCheckState(const QString &text, Qt::CheckState state, const QVariant &userData=QVariant())
Adds an item to the combobox with the given text, check state (stored in the Qt::CheckStateRole) and ...
QStandardItemModel subclass which makes all items checkable by default.
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
Returns the data stored under the given role for the item referred to by the index.
static QgsExpressionContextScope * projectScope(const QgsProject *project)
Creates a new scope which contains variables and functions relating to a QGIS project.
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context.
QString domainName() const
Returns the associated field domain name, for providers which support field domains.
Encapsulate a field in an attribute table or data source.
QString typeName() const
Gets the field type.
QString friendlyTypeString() const
Returns a user friendly, translated representation of the field type.
static QString readableConfigurationFlag(Qgis::FieldConfigurationFlag flag)
Returns the readable and translated value of the configuration flag.
QgsFieldConstraints constraints
Container of fields for a vector layer.
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
void editingStopped()
Emitted when edited changes have been successfully written to the data provider.
void editingStarted()
Emitted when editing on this layer has started.
static QgsProject * instance()
Returns the QgsProject singleton instance.
@ AttrConfigurationFlagsCol
QList< QTableWidgetItem * > mIndexedWidgets
QgsSourceFieldsProperties(QgsVectorLayer *layer, QWidget *parent=nullptr)
bool addAttribute(const QgsField &field)
Adds an attribute to the table (but does not commit it yet).
void setRow(int row, int idx, const QgsField &field)
Base class for vector data providers.
virtual Q_INVOKABLE Qgis::VectorProviderCapabilities capabilities() const
Returns flags containing the supported capabilities.
Represents a vector layer which manages a vector based dataset.
bool isEditable() const final
Returns true if the provider is in editing mode.
void setFieldConfigurationFlags(int index, Qgis::FieldConfigurationFlags flags)
Sets the configuration flags of the field at given index.
void attributeAdded(int idx)
Will be emitted, when a new attribute has been added to this vector layer.
void attributeDeleted(int idx)
Will be emitted, when an attribute has been deleted from this vector layer.
Qgis::FieldConfigurationFlags fieldConfigurationFlags(int index) const
Returns the configuration flags of the field at given index.
QgsVectorDataProvider * dataProvider() final
Returns the layer's data provider, it may be nullptr.
const QList< T > qgsEnumList()
Returns a list all enum entries.
#define QgsDebugMsgLevel(str, level)