48#include <QInputDialog>
51#include <QProgressDialog>
56#include "moc_qgsdualview.cpp"
58using namespace Qt::StringLiterals;
66const std::unique_ptr<QgsSettingsEntryVariant> QgsDualView::conditionalFormattingSplitterState = std::make_unique<
68const std::unique_ptr<QgsSettingsEntryVariant> QgsDualView::attributeEditorSplitterState = std::make_unique<
72 : QStackedWidget( parent )
81 mTableView->horizontalHeader()->setContextMenuPolicy( Qt::CustomContextMenu );
82 connect( mTableView->horizontalHeader(), &QHeaderView::customContextMenuRequested,
this, &QgsDualView::showViewHeaderMenu );
85 mConditionalFormatWidgetStack->hide();
87 mConditionalFormatWidgetStack->setMainPanel( mConditionalFormatWidget );
88 mConditionalFormatWidget->setDockMode(
true );
92 conditionalFormattingSplitterState->copyValueFromKey( u
"/qgis/attributeTable/splitterState"_s,
true );
93 mConditionalSplitter->restoreState( conditionalFormattingSplitterState->value().toByteArray() );
94 mAttributeEditorViewSplitter->restoreState( attributeEditorSplitterState->value().toByteArray() );
96 mPreviewColumnsMenu =
new QMenu(
this );
97 mActionPreviewColumnsMenu->setMenu( mPreviewColumnsMenu );
101 mActionExpressionPreview->setText( tr(
"Expression" ) );
104 connect( mActionExpressionPreview, &QAction::triggered,
this, &QgsDualView::previewExpressionBuilder );
113 auto createShortcuts = [
this](
const QString &objectName, void (
QgsFeatureListView::*slot )() ) {
118 connect( sc, &QShortcut::activated, mFeatureListView, slot );
125 QButtonGroup *buttonGroup =
new QButtonGroup(
this );
126 buttonGroup->setExclusive(
false );
130 QAbstractButton *bt = buttonGroup->button(
static_cast<int>( action ) );
132 bt->setChecked(
true );
133 connect( buttonGroup, qOverload<QAbstractButton *, bool>( &QButtonGroup::buttonToggled ),
this, &QgsDualView::panZoomGroupButtonToggled );
135 connect( mFlashButton, &QToolButton::clicked,
this, &QgsDualView::flashButtonClicked );
146 delete mAttributeForm;
147 mAttributeForm =
nullptr;
154 mEditorContext = context;
161 const bool needsGeometry = mLayer->conditionalStyles()->rulesNeedGeometry()
167 initLayerCache( needsGeometry );
168 initModels( mapCanvas, request, loadFeatures );
170 mConditionalFormatWidget->setLayer( mLayer );
172 mTableView->setModel( mFilterModel );
173 mFeatureListView->setModel( mFeatureListModel );
178 if ( mFeatureListPreviewButton->defaultAction() )
180 mFeatureListView->setDisplayExpression( mDisplayExpression );
190 if ( showFirstFeature && mFeatureListModel->rowCount() > 0 )
201void QgsDualView::initAttributeForm(
const QgsFeature &feature )
203 Q_ASSERT( !mAttributeForm );
209 mAttributeEditorScrollArea->setWidgetResizable(
true );
210 mAttributeEditor->layout()->addWidget( mAttributeEditorScrollArea );
211 mAttributeEditorScrollArea->setWidget( mAttributeForm );
215 mAttributeEditor->layout()->addWidget( mAttributeForm );
220 mAttributeForm->setMinimumWidth( 200 );
228 if ( QgsMapCanvas *canvas = mFilterModel->mapCanvas() )
234 if ( QgsMapCanvas *canvas = mFilterModel->mapCanvas() )
243void QgsDualView::columnBoxInit()
246 const QList<QgsField> fields = mLayer->fields().toList();
247 const QString displayExpression = mLayer->displayExpression();
249 mFeatureListPreviewButton->addAction( mActionExpressionPreview );
250 mFeatureListPreviewButton->addAction( mActionPreviewColumnsMenu );
252 QAction *defaultFieldAction =
nullptr;
253 const auto constFields = fields;
254 for (
const QgsField &field : constFields )
256 const int fieldIndex = mLayer->fields().lookupField( field.name() );
257 if ( fieldIndex == -1 )
260 const QString fieldName = field.name();
263 const QIcon fieldIcon = mLayer->fields().iconForField( fieldIndex );
264 const QString fieldDisplayName = mLayer->attributeDisplayName( fieldIndex );
267 QAction *previewAction =
new QAction( fieldIcon, fieldDisplayName, mFeatureListPreviewButton );
268 connect( previewAction, &QAction::triggered,
this, [
this, previewAction, fieldName] { previewColumnChanged( previewAction, fieldName ); } );
269 mPreviewColumnsMenu->addAction( previewAction );
271 if ( fieldDisplayName == displayExpression
272 || u
"COALESCE( \"%1\", '<NULL>' )"_s.arg( fieldDisplayName ) == displayExpression
273 || u
"\"%1\""_s.arg( fieldDisplayName ) == displayExpression
274 || fieldName == displayExpression
275 || u
"COALESCE( \"%1\", '<NULL>' )"_s.arg( fieldName ) == displayExpression
276 || u
"\"%1\""_s.arg( fieldName ) == displayExpression )
278 defaultFieldAction = previewAction;
283 QMenu *sortMenu =
new QMenu(
this );
285 sortMenuAction->setMenu( sortMenu );
287 QAction *sortByPreviewExpressionAsc =
new QAction(
QgsApplication::getThemeIcon( u
"sort.svg"_s ), tr(
"By Display Name (Ascending)" ),
this );
288 connect( sortByPreviewExpressionAsc, &QAction::triggered,
this, [
this]() { mFeatureListModel->setSortByDisplayExpression(
true, Qt::AscendingOrder ); } );
289 sortMenu->addAction( sortByPreviewExpressionAsc );
290 QAction *sortByPreviewExpressionDesc =
new QAction(
QgsApplication::getThemeIcon( u
"sort-reverse.svg"_s ), tr(
"By Display Name (Descending)" ),
this );
291 connect( sortByPreviewExpressionDesc, &QAction::triggered,
this, [
this]() { mFeatureListModel->setSortByDisplayExpression(
true, Qt::DescendingOrder ); } );
292 sortMenu->addAction( sortByPreviewExpressionDesc );
293 QAction *sortByPreviewExpressionCustom =
new QAction(
QgsApplication::getThemeIcon( u
"mIconExpressionPreview.svg"_s ), tr(
"By Custom Expression" ),
this );
294 connect( sortByPreviewExpressionCustom, &QAction::triggered,
this, [
this]() {
296 mFeatureListModel->setSortByDisplayExpression(
false );
298 sortMenu->addAction( sortByPreviewExpressionCustom );
300 mFeatureListPreviewButton->addAction( sortMenuAction );
302 QAction *separator =
new QAction( mFeatureListPreviewButton );
303 separator->setSeparator(
true );
304 mFeatureListPreviewButton->addAction( separator );
305 restoreRecentDisplayExpressions();
307 if ( defaultFieldAction )
309 mFeatureListPreviewButton->setDefaultAction( defaultFieldAction );
310 mFeatureListPreviewButton->defaultAction()->trigger();
314 mActionExpressionPreview->setToolTip( displayExpression );
315 mFeatureListPreviewButton->setDefaultAction( mActionExpressionPreview );
317 mFeatureListView->setDisplayExpression( displayExpression );
318 setDisplayExpression( displayExpression.isEmpty() ? tr(
"'[Please define preview text]'" ) : displayExpression );
324 setCurrentIndex(
view );
335 switch ( mFilterModel->filterMode() )
359 mMasterModel->setShowValidityState(
false );
369 const bool requiresTableReload = ( request.
filterType() != Qgis::Qgis::FeatureRequestFilterType::NoFilter
372 || ( mMasterModel->rowCount() == 0 );
384 if ( mFilterModel->mapCanvas() )
386 const QgsRectangle rect = mFilterModel->mapCanvas()->mapSettings().mapToLayerCoordinates( mLayer, mFilterModel->mapCanvas()->extent() );
401 mMasterModel->setShowValidityState(
true );
413 if ( !filterExpression.isEmpty() )
430 setBrowsingAutoPanScaleAllowed(
false );
438 setBrowsingAutoPanScaleAllowed(
true );
442 if ( requiresTableReload )
445 mFilterModel->disconnectFilterModeConnections();
447 mMasterModel->setRequest( request );
448 whileBlocking( mLayerCache )->setCacheGeometry( needsGeometry );
449 mMasterModel->loadLayer();
459 mFilterModel->setSelectedOnTop( selectedOnTop );
462void QgsDualView::initLayerCache(
bool cacheGeometry )
472 rebuildFullLayerCache();
478 delete mFeatureListModel;
482 mMasterModel =
new QgsAttributeTableModel( mLayerCache,
this );
483 mMasterModel->setRequest( request );
484 mMasterModel->setEditorContext( mEditorContext );
485 mMasterModel->setExtraColumns( 1 );
493 mMasterModel->loadLayer();
495 mFilterModel =
new QgsAttributeTableFilterModel( mapCanvas, mMasterModel, mMasterModel );
499 connect( mMasterModel, &QgsAttributeTableModel::rowsRemoved, mFilterModel, &QgsAttributeTableFilterModel::invalidate );
500 connect( mMasterModel, &QgsAttributeTableModel::rowsInserted, mFilterModel, &QgsAttributeTableFilterModel::invalidate );
504 mFeatureListModel =
new QgsFeatureListModel( mFilterModel, mFilterModel );
507void QgsDualView::restoreRecentDisplayExpressions()
509 const QVariantList previewExpressions = mLayer->customProperty( u
"dualview/previewExpressions"_s ).toList();
511 for (
const QVariant &previewExpression : previewExpressions )
513 insertRecentlyUsedDisplayExpression( previewExpression.toString() );
517void QgsDualView::saveRecentDisplayExpressions()
const
523 const QList<QAction *> actions = mFeatureListPreviewButton->actions();
526 int index = actions.indexOf( mLastDisplayExpressionAction );
529 QVariantList previewExpressions;
530 for ( ; index < actions.length(); ++index )
532 QAction *action = actions.at( index );
533 previewExpressions << action->property(
"previewExpression" );
536 mLayer->setCustomProperty( u
"dualview/previewExpressions"_s, previewExpressions );
540void QgsDualView::setDisplayExpression(
const QString &expression )
542 mDisplayExpression = expression;
543 insertRecentlyUsedDisplayExpression( expression );
546void QgsDualView::insertRecentlyUsedDisplayExpression(
const QString &expression )
548 const QList<QAction *> actions = mFeatureListPreviewButton->actions();
551 const int index = actions.indexOf( mLastDisplayExpressionAction );
554 for (
int i = 0; index + i < actions.length(); ++i )
556 QAction *action = actions.at( index );
557 if ( action->text() == expression || i >= 9 )
559 if ( action == mLastDisplayExpressionAction )
561 mLastDisplayExpressionAction =
nullptr;
563 mFeatureListPreviewButton->removeAction( action );
567 if ( !mLastDisplayExpressionAction )
569 mLastDisplayExpressionAction = action;
575 QString name = expression;
577 if ( expression.startsWith(
"COALESCE( \""_L1 ) && expression.endsWith(
", '<NULL>' )"_L1 ) )
579 name = expression.mid( 11, expression.length() - 24 );
581 const int fieldIndex = mLayer->fields().indexOf( name );
582 if ( fieldIndex != -1 )
584 name = mLayer->attributeDisplayName( fieldIndex );
585 icon = mLayer->fields().iconForField( fieldIndex );
593 QAction *previewAction =
new QAction( icon, name, mFeatureListPreviewButton );
594 previewAction->setProperty(
"previewExpression", expression );
595 connect( previewAction, &QAction::triggered,
this, [expression,
this](
bool ) {
596 setDisplayExpression( expression );
597 mFeatureListPreviewButton->setText( tr(
"Expression" ) );
598 mFeatureListPreviewButton->setToolTip( expression );
601 mFeatureListPreviewButton->insertAction( mLastDisplayExpressionAction, previewAction );
602 mLastDisplayExpressionAction = previewAction;
605void QgsDualView::updateEditSelectionProgress(
int progress,
int count )
607 mProgressCount->setText( u
"%1 / %2"_s.arg( progress + 1 ).arg( count ) );
608 mPreviousFeatureButton->setEnabled( progress > 0 );
609 mNextFeatureButton->setEnabled( progress + 1 < count );
610 mFirstFeatureButton->setEnabled( progress > 0 );
611 mLastFeatureButton->setEnabled( progress + 1 < count );
612 if ( mAttributeForm )
614 mAttributeForm->setVisible( count > 0 );
618void QgsDualView::panOrZoomToFeature(
const QgsFeatureIds &featureset )
620 QgsMapCanvas *canvas = mFilterModel->mapCanvas();
623 if ( mBrowsingAutoPanScaleAllowed )
625 if ( mAutoPanButton->isChecked() )
626 QTimer::singleShot( 0,
this, [
this, featureset, canvas]() { canvas->
panToFeatureIds( mLayer, featureset,
false ); } );
627 else if ( mAutoZoomButton->isChecked() )
628 QTimer::singleShot( 0,
this, [
this, featureset, canvas]() { canvas->
zoomToFeatureIds( mLayer, featureset ); } );
630 if ( mFlashButton->isChecked() )
631 QTimer::singleShot( 0,
this, [
this, featureset, canvas]() { canvas->
flashFeatureIds( mLayer, featureset ); } );
632 mLastFeatureSet = featureset;
636void QgsDualView::setBrowsingAutoPanScaleAllowed(
bool allowed )
638 if ( mBrowsingAutoPanScaleAllowed == allowed )
641 mBrowsingAutoPanScaleAllowed = allowed;
643 mAutoPanButton->setEnabled( allowed );
644 mAutoZoomButton->setEnabled( allowed );
646 const QString disabledHint = tr(
"(disabled when attribute table only shows features visible in the current map canvas extent)" );
648 mAutoPanButton->setToolTip( tr(
"Automatically pan to the current feature" ) + ( allowed ? QString() : QString(
' ' ) + disabledHint ) );
649 mAutoZoomButton->setToolTip( tr(
"Automatically zoom to the current feature" ) + ( allowed ? QString() : QString(
' ' ) + disabledHint ) );
652void QgsDualView::panZoomGroupButtonToggled( QAbstractButton *button,
bool checked )
654 if ( button == mAutoPanButton && checked )
656 QgsSettings().setEnumValue( u
"/qgis/attributeTable/featureListBrowsingAction"_s,
PanToFeature );
657 mAutoZoomButton->setChecked(
false );
659 else if ( button == mAutoZoomButton && checked )
661 QgsSettings().setEnumValue( u
"/qgis/attributeTable/featureListBrowsingAction"_s,
ZoomToFeature );
662 mAutoPanButton->setChecked(
false );
666 QgsSettings().setEnumValue( u
"/qgis/attributeTable/featureListBrowsingAction"_s,
NoAction );
669 if ( checked && mLayer->isSpatial() )
670 panOrZoomToFeature( mFeatureListView->currentEditSelection() );
673void QgsDualView::flashButtonClicked(
bool clicked )
679 QgsMapCanvas *canvas = mFilterModel->mapCanvas();
682 canvas->
flashFeatureIds( mLayer, mFeatureListView->currentEditSelection() );
685void QgsDualView::filterError(
const QString &errorMessage )
687 if ( mEditorContext.mainMessageBar() )
689 mEditorContext.mainMessageBar()->pushWarning( tr(
"An error occurred while filtering features" ), errorMessage );
693void QgsDualView::featureListAboutToChangeEditSelection(
bool &ok )
695 if ( !mAttributeForm )
698 if ( mLayer->isEditable() && !mAttributeForm->save() )
702void QgsDualView::featureListCurrentEditSelectionChanged(
const QgsFeature &feat )
704 if ( !mAttributeForm )
706 initAttributeForm( feat );
708 else if ( !mLayer->isEditable() || mAttributeForm->save() )
710 mAttributeForm->setFeature( feat );
712 featureset << feat.
id();
715 if ( mLayer->isSpatial() )
716 panOrZoomToFeature( featureset );
726 mFeatureListView->setCurrentFeatureEdited(
false );
727 mFeatureListView->setEditSelection( fids );
732 return mAttributeForm ? mAttributeForm->save() :
false;
737 mConditionalFormatWidgetStack->setVisible( !mConditionalFormatWidgetStack->isVisible() );
742 if ( !mAttributeForm )
747 mPreviousView =
view();
760 if ( !mAttributeForm )
767 mAttributeForm->setVisible(
true );
772 mAttributeForm->setVisible( mFilterModel->rowCount() > 0 );
776void QgsDualView::previewExpressionBuilder()
782 dlg.setWindowTitle( tr(
"Expression Based Preview" ) );
783 dlg.setExpressionText( mFeatureListView->displayExpression() );
785 if ( dlg.exec() == QDialog::Accepted )
787 mFeatureListView->setDisplayExpression( dlg.expressionText() );
788 mActionExpressionPreview->setToolTip( dlg.expressionText() );
790 mFeatureListPreviewButton->setDefaultAction( mActionExpressionPreview );
791 mFeatureListPreviewButton->setPopupMode( QToolButton::MenuButtonPopup );
794 setDisplayExpression( mFeatureListView->displayExpression() );
797void QgsDualView::previewColumnChanged( QAction *previewAction,
const QString &expression )
799 if ( !mFeatureListView->setDisplayExpression( u
"COALESCE( \"%1\", '<NULL>' )"_s.arg( expression ) ) )
801 QMessageBox::warning(
this, tr(
"Column Display Name" ), tr(
"Could not set column '%1' as display name.\nParser error:\n%2" ).arg( previewAction->text(), mFeatureListView->parserErrorString() ) );
805 mFeatureListPreviewButton->setText( previewAction->text() );
806 mFeatureListPreviewButton->setIcon( previewAction->icon() );
807 mFeatureListPreviewButton->setPopupMode( QToolButton::InstantPopup );
810 setDisplayExpression( mFeatureListView->displayExpression() );
815 return mMasterModel->rowCount();
820 return mFilterModel->rowCount();
825 const QModelIndex currentIndex = mTableView->currentIndex();
826 if ( !currentIndex.isValid() )
831 const QVariant var = mMasterModel->data( currentIndex, Qt::DisplayRole );
832 QApplication::clipboard()->setText( var.toString() );
838 mProgressDlg->cancel();
843 if ( mAttributeForm )
845 mAttributeForm->parentFormValueChanged( attribute, newValue );
852 saveRecentDisplayExpressions();
859 conditionalFormattingSplitterState->setValue( mConditionalSplitter->saveState() );
860 attributeEditorSplitterState->setValue( mAttributeEditorViewSplitter->saveState() );
863void QgsDualView::viewWillShowContextMenu( QMenu *menu,
const QModelIndex &masterIndex )
870 const QVariant displayValue = mMasterModel->data( masterIndex, Qt::DisplayRole );
872 if ( displayValue.isValid() )
875 QString previewDisplayValue = displayValue.toString();
876 if ( previewDisplayValue.length() > 12 )
878 previewDisplayValue.truncate( 12 );
879 previewDisplayValue.append( u
"…"_s );
883 QAction *copyContentAction = menu->addAction( tr(
"Copy Cell Content (%1)" ).arg( previewDisplayValue ) );
884 menu->addAction( copyContentAction );
885 connect( copyContentAction, &QAction::triggered,
this, [displayValue] { QApplication::clipboard()->setText( displayValue.toString() ); } );
888 const QVariant rawValue = mMasterModel->data( masterIndex, Qt::EditRole );
889 if ( rawValue.isValid() )
892 QString previewRawValue = rawValue.toString();
893 if ( previewRawValue.length() > 12 )
895 previewRawValue.truncate( 12 );
896 previewRawValue.append( u
"…"_s );
899 QAction *copyRawContentAction = menu->addAction( tr(
"Copy Raw Value (%1)" ).arg( previewRawValue ) );
900 menu->addAction( copyRawContentAction );
901 connect( copyRawContentAction, &QAction::triggered,
this, [rawValue] { QApplication::clipboard()->setText( rawValue.toString() ); } );
904 QgsVectorLayer *vl = mFilterModel->layer();
905 QgsMapCanvas *canvas = mFilterModel->mapCanvas();
908 QAction *zoomToFeatureAction = menu->addAction( tr(
"Zoom to Feature" ) );
909 connect( zoomToFeatureAction, &QAction::triggered,
this, &QgsDualView::zoomToCurrentFeature );
911 QAction *panToFeatureAction = menu->addAction( tr(
"Pan to Feature" ) );
912 connect( panToFeatureAction, &QAction::triggered,
this, &QgsDualView::panToCurrentFeature );
914 QAction *flashFeatureAction = menu->addAction( tr(
"Flash Feature" ) );
915 connect( flashFeatureAction, &QAction::triggered,
this, &QgsDualView::flashCurrentFeature );
919 const QList<QgsAction> actions = mLayer->actions()->actions( u
"Field"_s );
920 if ( !actions.isEmpty() )
922 QAction *a = menu->addAction( tr(
"Run Layer Action" ) );
923 a->setEnabled(
false );
925 for (
const QgsAction &action : actions )
927 if ( !action.runable() )
930 if ( vl && !vl->
isEditable() && action.isEnabledOnlyWhenEditable() )
933 QgsAttributeTableAction *a =
new QgsAttributeTableAction( action.name(),
this, action.id(), masterIndex );
937 const QModelIndex rowSourceIndex = mMasterModel->index( masterIndex.row(), 0 );
938 if ( !rowSourceIndex.isValid() )
944 QgsMapLayerActionContext context;
946 if ( !registeredActions.isEmpty() )
949 menu->addSeparator();
951 for ( QgsMapLayerAction *action : registeredActions )
953 QgsAttributeTableMapLayerAction *a =
new QgsAttributeTableMapLayerAction( action->text(),
this, action, rowSourceIndex );
960 const QgsFeatureId currentFid = mMasterModel->rowToId( masterIndex.row() );
961 if ( mLayer->selectedFeatureCount() > 1 && mLayer->selectedFeatureIds().contains( currentFid ) )
964 if ( !registeredActions.isEmpty() )
966 menu->addSeparator();
967 QAction *action = menu->addAction( tr(
"Actions on Selection (%1)" ).arg( mLayer->selectedFeatureCount() ) );
968 action->setEnabled(
false );
970 QgsMapLayerActionContext context;
971 for ( QgsMapLayerAction *action : registeredActions )
973 menu->addAction( action->text(), action, [
this, action, context]() {
974 Q_NOWARN_DEPRECATED_PUSH
975 action->triggerForFeatures( mLayer, mLayer->selectedFeatures() );
976 Q_NOWARN_DEPRECATED_POP
977 action->triggerForFeatures( mLayer, mLayer->selectedFeatures(), context );
983 menu->addSeparator();
984 QgsAttributeTableAction *a =
new QgsAttributeTableAction( tr(
"Open Form" ),
this, QUuid(), rowSourceIndex );
989void QgsDualView::widgetWillShowContextMenu(
QgsActionMenu *menu,
const QModelIndex &atIndex )
995void QgsDualView::showViewHeaderMenu( QPoint point )
997 const int col = mTableView->columnAt( point.x() );
999 delete mHorizontalHeaderMenu;
1000 mHorizontalHeaderMenu =
new QMenu(
this );
1002 QAction *hide =
new QAction( tr(
"&Hide Column" ), mHorizontalHeaderMenu );
1003 connect( hide, &QAction::triggered,
this, &QgsDualView::hideColumn );
1004 hide->setData( col );
1005 mHorizontalHeaderMenu->addAction( hide );
1006 QAction *setWidth =
new QAction( tr(
"&Set Width…" ), mHorizontalHeaderMenu );
1007 connect( setWidth, &QAction::triggered,
this, &QgsDualView::resizeColumn );
1008 setWidth->setData( col );
1009 mHorizontalHeaderMenu->addAction( setWidth );
1011 QAction *setWidthAllColumns =
new QAction( tr(
"&Set All Column Widths…" ), mHorizontalHeaderMenu );
1012 connect( setWidthAllColumns, &QAction::triggered,
this, &QgsDualView::resizeAllColumns );
1013 setWidthAllColumns->setData( col );
1014 mHorizontalHeaderMenu->addAction( setWidthAllColumns );
1016 QAction *optimizeWidth =
new QAction( tr(
"&Autosize" ), mHorizontalHeaderMenu );
1017 connect( optimizeWidth, &QAction::triggered,
this, &QgsDualView::autosizeColumn );
1018 optimizeWidth->setData( col );
1019 mHorizontalHeaderMenu->addAction( optimizeWidth );
1021 QAction *optimizeWidthAllColumns =
new QAction( tr(
"&Autosize All Columns" ), mHorizontalHeaderMenu );
1022 connect( optimizeWidthAllColumns, &QAction::triggered,
this, &QgsDualView::autosizeAllColumns );
1023 mHorizontalHeaderMenu->addAction( optimizeWidthAllColumns );
1026 mHorizontalHeaderMenu->addSeparator();
1027 QAction *organize =
new QAction( tr(
"&Organize Columns…" ), mHorizontalHeaderMenu );
1028 connect( organize, &QAction::triggered,
this, &QgsDualView::organizeColumns );
1029 mHorizontalHeaderMenu->addAction( organize );
1030 QAction *sort =
new QAction( tr(
"&Sort…" ), mHorizontalHeaderMenu );
1031 connect( sort, &QAction::triggered,
this, [
this]() { modifySort(); } );
1032 mHorizontalHeaderMenu->addAction( sort );
1034 mConfig.update( mLayer->fields() );
1036 int fieldIndex = -1;
1038 fieldIndex = mLayer->fields().indexFromName( mConfig.columns().at( mConfig.mapVisibleColumnToIndex( col ) ).name );
1039 const Qgis::FieldOrigin fieldOrigin = mLayer->fields().fieldOrigin( fieldIndex );
1041 mHorizontalHeaderMenu->addSeparator();
1043 const QgsVectorLayer *vl = mFilterModel->layer();
1044 const QgsVectorDataProvider *dataProvider = vl->
dataProvider();
1046 const bool layerIsReadOnly { vl->
readOnly() };
1049 bool fieldCalculatorEnabled =
false;
1051 switch ( fieldOrigin )
1055 fieldCalculatorEnabled = canChangeAttributeValue;
1060 const QgsVectorLayerJoinInfo *info = mLayer->joinBuffer()->joinForFieldIndex( fieldIndex, mLayer->fields(), srcFieldIndex );
1061 const QgsVectorLayer *joinedLayer = info->
joinLayer();
1062 const QgsVectorDataProvider *joinedDataProvider = joinedLayer->
dataProvider();
1064 const bool joinedLayerIsReadOnly { joinedLayer->
readOnly() };
1067 fieldCalculatorEnabled = joinedLayerCanChangeAttributeValue;
1077 QAction *fieldCalculator =
new QAction( tr(
"Open &Field Calculator…" ), mHorizontalHeaderMenu );
1078 connect( fieldCalculator, &QAction::triggered,
this, &QgsDualView::fieldCalculator );
1079 fieldCalculator->setData( fieldIndex );
1080 mHorizontalHeaderMenu->addAction( fieldCalculator );
1082 fieldCalculator->setEnabled( fieldCalculatorEnabled );
1084 mHorizontalHeaderMenu->popup( mTableView->horizontalHeader()->mapToGlobal( point ) );
1087void QgsDualView::organizeColumns()
1095 if ( dialog.exec() == QDialog::Accepted )
1097 const QgsAttributeTableConfig config = dialog.config();
1102void QgsDualView::tableColumnResized(
int column,
int width )
1104 QgsAttributeTableConfig config = mConfig;
1106 if ( sourceCol >= 0 && config.
columnWidth( sourceCol ) != width )
1113void QgsDualView::hideColumn()
1115 QAction *action = qobject_cast<QAction *>( sender() );
1116 const int col = action->data().toInt();
1117 QgsAttributeTableConfig config = mConfig;
1119 if ( sourceCol >= 0 )
1126void QgsDualView::fieldCalculator()
1128 QAction *action = qobject_cast<QAction *>( sender() );
1129 const int fieldIndex = action->data().toInt();
1130 mConfig.update( mLayer->fields() );
1131 QgsFieldCalculator calc( mLayer,
this, fieldIndex );
1132 if ( calc.exec() == QDialog::Accepted )
1134 int col = mMasterModel->fieldCol( calc.changedAttributeId() );
1137 mMasterModel->reload( mMasterModel->index( 0, col ), mMasterModel->index( mMasterModel->rowCount() - 1, col ) );
1141void QgsDualView::resizeColumn()
1143 QAction *action = qobject_cast<QAction *>( sender() );
1144 const int col = action->data().toInt();
1148 QgsAttributeTableConfig config = mConfig;
1150 if ( sourceCol >= 0 )
1153 const int width = QInputDialog::getInt(
this, tr(
"Set column width" ), tr(
"Enter column width" ), mTableView->columnWidth( col ), 0, 1000, 10, &ok );
1162void QgsDualView::resizeAllColumns()
1164 QAction *action = qobject_cast<QAction *>( sender() );
1165 const int col = action->data().toInt();
1169 QgsAttributeTableConfig config = mConfig;
1172 const int width = QInputDialog::getInt(
this, tr(
"Set Column Width" ), tr(
"Enter column width" ), mTableView->columnWidth( col ), 1, 1000, 10, &ok );
1175 const int colCount = mTableView->model()->columnCount();
1178 for (
int i = 0; i < colCount; i++ )
1187void QgsDualView::autosizeColumn()
1189 QAction *action = qobject_cast<QAction *>( sender() );
1190 const int col = action->data().toInt();
1191 mTableView->resizeColumnToContents( col );
1194void QgsDualView::autosizeAllColumns()
1196 mTableView->resizeColumnsToContents();
1199bool QgsDualView::modifySort()
1204 QgsAttributeTableConfig config = mConfig;
1207 orderByDlg.setWindowTitle( tr(
"Configure Attribute Table Sort Order" ) );
1208 QDialogButtonBox *dialogButtonBox =
new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
1209 QGridLayout *layout =
new QGridLayout();
1210 connect( dialogButtonBox, &QDialogButtonBox::accepted, &orderByDlg, &QDialog::accept );
1211 connect( dialogButtonBox, &QDialogButtonBox::rejected, &orderByDlg, &QDialog::reject );
1212 orderByDlg.setLayout( layout );
1214 QGroupBox *sortingGroupBox =
new QGroupBox();
1215 sortingGroupBox->setTitle( tr(
"Defined sort order in attribute table" ) );
1216 sortingGroupBox->setCheckable(
true );
1218 layout->addWidget( sortingGroupBox );
1219 sortingGroupBox->setLayout(
new QGridLayout() );
1221 QgsExpressionBuilderWidget *expressionBuilder =
new QgsExpressionBuilderWidget();
1224 expressionBuilder->
initWithLayer( mLayer, context, u
"generic"_s );
1227 sortingGroupBox->layout()->addWidget( expressionBuilder );
1229 QCheckBox *cbxSortAscending =
new QCheckBox( tr(
"Sort ascending" ) );
1230 cbxSortAscending->setChecked( config.
sortOrder() == Qt::AscendingOrder );
1231 sortingGroupBox->layout()->addWidget( cbxSortAscending );
1233 layout->addWidget( dialogButtonBox );
1234 if ( orderByDlg.exec() )
1236 const Qt::SortOrder sortOrder = cbxSortAscending->isChecked() ? Qt::AscendingOrder : Qt::DescendingOrder;
1237 if ( sortingGroupBox->isChecked() )
1259 QSet<int> attributes;
1263 const QVector<QgsAttributeTableConfig::ColumnConfig> constColumnconfigs { config.
columns() };
1272 const QSet<int> colAttrs { attributes };
1273 for (
const int attrIdx : std::as_const( colAttrs ) )
1282 std::sort( attrs.begin(), attrs.end() );
1286void QgsDualView::zoomToCurrentFeature()
1288 const QModelIndex currentIndex = mTableView->currentIndex();
1289 if ( !currentIndex.isValid() )
1295 ids.insert( mFilterModel->rowToId( currentIndex ) );
1296 QgsMapCanvas *canvas = mFilterModel->mapCanvas();
1303void QgsDualView::panToCurrentFeature()
1305 const QModelIndex currentIndex = mTableView->currentIndex();
1306 if ( !currentIndex.isValid() )
1312 ids.insert( mFilterModel->rowToId( currentIndex ) );
1313 QgsMapCanvas *canvas = mFilterModel->mapCanvas();
1320void QgsDualView::flashCurrentFeature()
1322 const QModelIndex currentIndex = mTableView->currentIndex();
1323 if ( !currentIndex.isValid() )
1329 ids.insert( mFilterModel->rowToId( currentIndex ) );
1330 QgsMapCanvas *canvas = mFilterModel->mapCanvas();
1337void QgsDualView::rebuildFullLayerCache()
1342 mLayerCache->setFullCache(
true );
1345void QgsDualView::previewExpressionChanged(
const QString &expression )
1347 mLayer->setDisplayExpression( expression );
1350void QgsDualView::onSortColumnChanged()
1361void QgsDualView::updateSelectedFeatures()
1363 QgsFeatureRequest r = mMasterModel->request();
1368 mMasterModel->setRequest( r );
1369 mMasterModel->loadLayer();
1373void QgsDualView::updateEditedAddedFeatures()
1375 QgsFeatureRequest r = mMasterModel->request();
1380 mMasterModel->setRequest( r );
1381 mMasterModel->loadLayer();
1385void QgsDualView::extentChanged()
1387 QgsFeatureRequest r = mMasterModel->request();
1390 const QgsRectangle rect = mFilterModel->mapCanvas()->mapSettings().mapToLayerCoordinates( mLayer, mFilterModel->mapCanvas()->extent() );
1392 mMasterModel->setRequest( r );
1393 mMasterModel->loadLayer();
1398void QgsDualView::featureFormAttributeChanged(
const QString &attribute,
const QVariant &value,
bool attributeChanged )
1400 Q_UNUSED( attribute )
1402 if ( attributeChanged )
1404 mFeatureListView->setCurrentFeatureEdited(
true );
1405 mAttributeForm->save();
1416 mFilterModel->setFilterExpression( filterExpression, context );
1417 mFilterModel->filterFeatures();
1423 mMasterModel->setRequest( request );
1428 mTableView->setFeatureSelectionManager( featureSelectionManager );
1429 mFeatureListView->setFeatureSelectionManager( featureSelectionManager );
1431 if ( mFeatureSelectionManager && mFeatureSelectionManager->parent() ==
this )
1432 delete mFeatureSelectionManager;
1434 mFeatureSelectionManager = featureSelectionManager;
1440 mConfig.
update( mLayer->fields() );
1441 mLayer->setAttributeTableConfig( mConfig );
1442 mFilterModel->setAttributeTableConfig( mConfig );
1443 mTableView->setAttributeTableConfig( mConfig );
1449 mLayerCache->setCacheGeometry(
true );
1453 mMasterModel->setRequest( request );
1454 mLayerCache->setCacheSubsetOfAttributes( attributes );
1460 mFilterModel->sort( -1 );
1465 mConfig.setSortOrder( sortOrder );
1471 return mFilterModel->sortExpression();
1479void QgsDualView::progress(
int i,
bool &cancel )
1481 if ( !mProgressDlg )
1483 mProgressDlg =
new QProgressDialog( tr(
"Loading features…" ), tr(
"Abort" ), 0, 0,
this );
1484 mProgressDlg->setWindowTitle( tr(
"Attribute Table" ) );
1485 mProgressDlg->setWindowModality( Qt::WindowModal );
1486 mProgressDlg->show();
1489 mProgressDlg->setLabelText( tr(
"%L1 features loaded." ).arg( i ) );
1490 QCoreApplication::processEvents();
1492 cancel = mProgressDlg && mProgressDlg->wasCanceled();
1495void QgsDualView::finished()
1497 delete mProgressDlg;
1498 mProgressDlg =
nullptr;
1507 mDualView->masterModel()->executeAction( mAction, mFieldIdx );
1513 editedIds << mDualView->masterModel()->rowToId( mFieldIdx.row() );
1514 mDualView->setCurrentEditSelection( editedIds );
1525 mDualView->masterModel()->executeMapLayerAction( mAction, mFieldIdx, context );
@ SelectAtId
Fast access to features using their ID.
@ ChangeAttributeValues
Allows modification of attribute values.
@ NoFilter
No filter is applied.
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
@ NoFilter
No spatial filtering of features.
@ MultipleFeatures
Action targets multiple features from a layer.
@ Layer
Action targets a complete layer.
@ SingleFeature
Action targets a single feature from a layer.
QFlags< VectorProviderCapability > VectorProviderCapabilities
Vector data provider capabilities.
@ Provider
Field originates from the underlying data provider of the vector layer.
@ Edit
Field has been temporarily added in editing mode.
@ Unknown
The field origin has not been specified.
@ Expression
Field is calculated from an expression.
@ Join
Field originates from a joined layer.
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
Contains context information for attribute editor widgets.
@ SearchMode
Form values are used for searching/filtering the layer.
@ SingleEditMode
Single edit mode, for editing a single feature.
@ MultiEditMode
Multi edit mode, for editing fields of multiple features at once.
const QgsAttributeEditorContext * parentContext() const
A container for configuration of the attribute table.
void setSortExpression(const QString &sortExpression)
Set the sort expression used for sorting.
@ Field
This column represents a field.
Qt::SortOrder sortOrder() const
Gets the sort order.
QVector< QgsAttributeTableConfig::ColumnConfig > columns() const
Gets the list with all columns and their configuration.
int mapVisibleColumnToIndex(int visibleColumn) const
Maps a visible column index to its original column index.
void update(const QgsFields &fields)
Update the configuration with the given fields.
void setSortOrder(Qt::SortOrder sortOrder)
Set the sort order.
int columnWidth(int column) const
Returns the width of a column, or -1 if column should use default width.
void setColumnHidden(int column, bool hidden)
Sets whether the specified column should be hidden.
QString sortExpression() const
Gets the expression used for sorting.
void setColumnWidth(int column, int width)
Sets the width of a column.
FilterMode
The filter mode defines how the rows should be filtered.
@ ShowFilteredList
Show only features whose ids are on the filter list. {.
@ ShowVisible
Show only visible features (depends on the map canvas).
@ ShowSelected
Show only selected features.
@ ShowInvalid
Show only features not respecting constraints.
@ ShowEdited
Show only features which have unsaved changes.
@ ShowAll
Show all features.
void filterError(const QString &errorMessage)
Emitted when an error occurred while filtering features.
void featuresFiltered()
Emitted when the filtering of the features has been done.
void visibleReloaded()
Emitted when the the visible features on extend are reloaded (the list is created).
void sortColumnChanged(int column, Qt::SortOrder order)
Emitted whenever the sort column is changed.
void fieldConditionalStyleChanged(const QString &fieldName)
Handles updating the model when the conditional style for a field changes.
void modelChanged()
Emitted when the model has been changed.
void progress(int i, bool &cancel)
void finished()
Emitted when the model has completely loaded all features.
void willShowContextMenu(QMenu *menu, const QModelIndex &atIndex)
Emitted in order to provide a hook to add additional* menu entries to the context menu.
void columnResized(int column, int width)
Emitted when a column in the view has been resized.
void showContextMenuExternally(QgsActionMenu *menu, QgsFeatureId fid)
Emitted when selecting context menu on the feature list to create the context menu individually.
void copyCellContent() const
Copy the content of the selected cell in the clipboard.
ViewMode
The view modes, in which this widget can present information.
@ AttributeEditor
Show a list of the features, where one can be chosen and the according attribute dialog will be prese...
void setFeatureSelectionManager(QgsIFeatureSelectionManager *featureSelectionManager)
Set the feature selection model.
static QgsAttributeList requiredAttributes(const QgsVectorLayer *layer)
Returns the list of required attributes according to the attribute table configuration of the layer,...
QgsAttributeTableFilterModel::FilterMode filterMode()
Gets the filter mode.
void setMultiEditEnabled(bool enabled)
Sets whether multi edit mode is enabled.
QgsFeatureIds filteredFeatures()
Gets a list of currently visible feature ids.
void cancelProgress()
Cancel the progress dialog (if any).
void filterChanged()
Emitted whenever the filter changes.
static const QgsSettingsEntryBool * settingsFeatureListHighlightFeature
static const QgsSettingsEntryInteger * settingsAttributeTableRowCache
QgsDualView(QWidget *parent=nullptr)
Constructor.
void setAttributeTableConfig(const QgsAttributeTableConfig &config)
Set the attribute table config which should be used to control the appearance of the attribute table.
ViewMode view() const
Returns the current view mode.
int featureCount()
Returns the number of features on the layer.
Q_DECL_DEPRECATED void setFilteredFeatures(const QgsFeatureIds &filteredFeatures)
Set a list of currently visible features.
void formModeChanged(QgsAttributeEditorContext::Mode mode)
Emitted when the form changes mode.
FeatureListBrowsingAction
Action on the map canvas when browsing the list of features.
@ NoAction
No action is done.
@ PanToFeature
The map is panned to the center of the feature bounding-box.
@ ZoomToFeature
The map is zoomed to contained the feature bounding-box.
void hideEvent(QHideEvent *event) override
QgsAttributeTableConfig attributeTableConfig() const
The config used for the attribute table.
void filterExpressionSet(const QString &expression, QgsAttributeForm::FilterType type)
Emitted when a filter expression is set using the view.
void init(QgsVectorLayer *layer, QgsMapCanvas *mapCanvas, const QgsFeatureRequest &request=QgsFeatureRequest(), const QgsAttributeEditorContext &context=QgsAttributeEditorContext(), bool loadFeatures=true, bool showFirstFeature=true)
Has to be called to initialize the dual view.
bool saveEditChanges()
saveEditChanges
void openConditionalStyles()
void toggleSearchMode(bool enabled)
Toggles whether search mode should be enabled in the form.
void displayExpressionChanged(const QString &expression)
Emitted whenever the display expression is successfully changed.
void setSortExpression(const QString &sortExpression, Qt::SortOrder sortOrder=Qt::AscendingOrder)
Set the expression used for sorting the table and feature list.
void setRequest(const QgsFeatureRequest &request)
Set the request.
void parentFormValueChanged(const QString &attribute, const QVariant &value)
Called in embedded forms when an attribute value in the parent form has changed.
QgsAttributeTableModel * masterModel() const
Returns the model which has the information about all features (not only filtered).
void setCurrentEditSelection(const QgsFeatureIds &fids)
Set the current edit selection in the AttributeEditor mode.
int filteredFeatureCount()
Returns the number of features which are currently visible, according to the filter restrictions.
QString sortExpression() const
Gets the expression used for sorting the table and feature list.
void setFilterMode(QgsAttributeTableFilterModel::FilterMode filterMode)
Set the filter mode.
void setView(ViewMode view)
Change the current view mode.
void setSelectedOnTop(bool selectedOnTop)
Toggle the selectedOnTop flag.
void filterFeatures(const QgsExpression &filterExpression, const QgsExpressionContext &context)
Sets the expression and Updates the filtered features in the filter model.
A generic dialog for building expression strings.
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
Handles parsing and evaluation of expressions (formerly called "search strings").
bool needsGeometry() const
Returns true if the expression uses feature geometry for some computation.
QSet< int > referencedAttributeIndexes(const QgsFields &fields) const
Returns a list of field name indexes obtained from the provided fields.
@ FeatureRole
Feature with all attributes and no geometry.
Shows a list of features and renders an edit button next to each feature.
void currentEditSelectionProgressChanged(int progress, int count)
Emitted whenever the current edit selection has been changed.
void editNextFeature()
editNextFeature will try to edit next feature of the list
void editLastFeature()
editLastFeature will try to edit the last feature of the list
void editFirstFeature()
editFirstFeature will try to edit the first feature of the list
void displayExpressionChanged(const QString &expression)
Emitted whenever the display expression is successfully changed.
void editPreviousFeature()
editPreviousFeature will try to edit previous feature of the list
void willShowContextMenu(QgsActionMenu *menu, const QModelIndex &atIndex)
Emitted when the context menu is created to add the specific actions to it.
void currentEditSelectionChanged(QgsFeature &feat)
Emitted whenever the current edit selection has been changed.
void aboutToChangeEditSelection(bool &ok)
Wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFlags(Qgis::FeatureRequestFlags flags)
Sets flags that affect how features will be fetched.
QgsRectangle filterRect() const
Returns the rectangle from which features will be taken.
QgsFeatureRequest & setFilterFids(const QgsFeatureIds &fids)
Sets the feature IDs that should be fetched.
Qgis::FeatureRequestFilterType filterType() const
Returns the attribute/ID filter type which is currently set on this request.
Qgis::FeatureRequestFlags flags() const
Returns the flags which affect how features are fetched.
QgsFeatureRequest & disableFilter()
Disables any attribute/ID filtering.
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
Qgis::SpatialFilterType spatialFilterType() const
Returns the spatial filter type which is currently set on this request.
QgsFeatureRequest & setFilterRect(const QgsRectangle &rectangle)
Sets the rectangle from which features will be taken.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Qgis::FieldOrigin fieldOrigin(int fieldIdx) const
Returns the field's origin (value from an enumeration).
Q_INVOKABLE int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
static QgsEditorWidgetRegistry * editorWidgetRegistry()
Returns the global editor widget registry, used for managing all known edit widget factories.
static QgsShortcutsManager * shortcutsManager()
Returns the global shortcuts manager, used for managing a QAction and QShortcut sequences.
static QgsMapLayerActionRegistry * mapLayerActionRegistry()
Returns the global map layer action registry, used for registering map layer actions.
Is an interface class to abstract feature selection handling.
static long zoomToMatchingFeatures(QgsMapCanvas *canvas, QgsVectorLayer *layer, const QString &filter)
Zooms a map canvas to features from the specified layer which match the given filter expression strin...
static long flashMatchingFeatures(QgsMapCanvas *canvas, QgsVectorLayer *layer, const QString &filter)
Flashes features from the specified layer which match the given filter expression string with a map c...
Map canvas is a class for displaying all GIS data types on a canvas.
void extentsChanged()
Emitted when the extents of the map change.
void panToFeatureIds(QgsVectorLayer *layer, const QgsFeatureIds &ids, bool alwaysRecenter=true)
Centers canvas extent to feature ids.
void flashFeatureIds(QgsVectorLayer *layer, const QgsFeatureIds &ids, const QColor &startColor=QColor(255, 0, 0, 255), const QColor &endColor=QColor(255, 0, 0, 0), int flashes=3, int duration=500)
Causes a set of features with matching ids from a vector layer to flash within the canvas.
void zoomToFeatureIds(QgsVectorLayer *layer, const QgsFeatureIds &ids)
Set canvas extent to the bounding box of a set of features.
Encapsulates the context in which a QgsMapLayerAction action is executed.
QList< QgsMapLayerAction * > mapLayerActions(QgsMapLayer *layer, Qgis::MapLayerActionTargets targets=Qgis::MapLayerActionTarget::AllActions, const QgsMapLayerActionContext &context=QgsMapLayerActionContext())
Returns the map layer actions which can run on the specified layer.
void layerModified()
Emitted when modifications has been done on layer.
A rectangle specified with double values.
T value(const QString &dynamicKeyPart=QString()) const
Returns settings value.
A boolean settings entry.
An integer settings entry.
A variant settings entry.
static QgsSettingsTreeNode * sTreeAttributeTable
static QgsSettingsTreeNode * sTreeWindowState
Stores settings for use within QGIS.
T enumValue(const QString &key, const T &defaultValue, const Section section=NoSection)
Returns the setting value for a setting based on an enum.
QShortcut * shortcutByName(const QString &name) const
Returns a shortcut by its name, or nullptr if nothing found.
static QVariant createNullVariant(QMetaType::Type metaType)
Helper method to properly create a null QVariant from a metaType Returns the created QVariant.
virtual Q_INVOKABLE Qgis::VectorProviderCapabilities capabilities() const
Returns flags containing the supported capabilities.
Caches features for a given QgsVectorLayer.
void finished()
When filling the cache, this signal gets emitted once the cache is fully initialized.
void invalidated()
The cache has been invalidated and cleared.
void setCacheSubsetOfAttributes(const QgsAttributeList &attributes)
Set the list (possibly a subset) of attributes to be cached.
void progress(int i, bool &cancel)
When filling the cache, this signal gets emitted periodically to notify about the progress and to be ...
void setCacheGeometry(bool cacheGeometry)
Enable or disable the caching of geometries.
bool isEditable() const
Returns whether joined fields may be edited through the form of the target layer.
QgsVectorLayer * joinLayer() const
Returns joined layer (may be nullptr if the reference was set by layer ID and not resolved yet).
Represents a vector layer which manages a vector based dataset.
bool isEditable() const final
Returns true if the provider is in editing mode.
bool isSpatial() const final
Returns true if this is a geometry layer and false in case of NoGeometry (table only) or UnknownGeome...
QString expressionField(int index) const
Returns the expression used for a given expression field.
void afterCommitChanges()
Emitted after changes are committed to the data provider.
QgsAttributeTableConfig attributeTableConfig() const
Returns the attribute table configuration object.
void selectionChanged(const QgsFeatureIds &selected, const QgsFeatureIds &deselected, bool clearAndSelect)
Emitted when selection was changed.
void updatedFields()
Emitted whenever the fields available from this layer have been changed.
QgsVectorDataProvider * dataProvider() final
Returns the layer's data provider, it may be nullptr.
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
QSet< QgsFeatureId > QgsFeatureIds
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
QList< int > QgsAttributeList
Defines the configuration of a column in the attribute table.