49#include <QInputDialog>
52#include <QProgressDialog>
57#include "moc_qgsdualview.cpp"
59using namespace Qt::StringLiterals;
67const std::unique_ptr<QgsSettingsEntryVariant> QgsDualView::conditionalFormattingSplitterState = std::make_unique<
69const std::unique_ptr<QgsSettingsEntryVariant> QgsDualView::attributeEditorSplitterState = std::make_unique<
73 : QStackedWidget( parent )
82 mTableView->horizontalHeader()->setContextMenuPolicy( Qt::CustomContextMenu );
83 connect( mTableView->horizontalHeader(), &QHeaderView::customContextMenuRequested,
this, &QgsDualView::showViewHeaderMenu );
86 mConditionalFormatWidgetStack->hide();
88 mConditionalFormatWidgetStack->setMainPanel( mConditionalFormatWidget );
89 mConditionalFormatWidget->setDockMode(
true );
93 conditionalFormattingSplitterState->copyValueFromKey( u
"/qgis/attributeTable/splitterState"_s,
true );
94 mConditionalSplitter->restoreState( conditionalFormattingSplitterState->value().toByteArray() );
95 mAttributeEditorViewSplitter->restoreState( attributeEditorSplitterState->value().toByteArray() );
97 mPreviewColumnsMenu =
new QMenu(
this );
98 mActionPreviewColumnsMenu->setMenu( mPreviewColumnsMenu );
102 mActionExpressionPreview->setText( tr(
"Expression" ) );
105 connect( mActionExpressionPreview, &QAction::triggered,
this, &QgsDualView::previewExpressionBuilder );
114 auto createShortcuts = [
this](
const QString &objectName, void (
QgsFeatureListView::*slot )() ) {
119 connect( sc, &QShortcut::activated, mFeatureListView, slot );
126 QButtonGroup *buttonGroup =
new QButtonGroup(
this );
127 buttonGroup->setExclusive(
false );
131 QAbstractButton *bt = buttonGroup->button(
static_cast<int>( action ) );
133 bt->setChecked(
true );
134 connect( buttonGroup, qOverload<QAbstractButton *, bool>( &QButtonGroup::buttonToggled ),
this, &QgsDualView::panZoomGroupButtonToggled );
136 connect( mFlashButton, &QToolButton::clicked,
this, &QgsDualView::flashButtonClicked );
147 delete mAttributeForm;
148 mAttributeForm =
nullptr;
155 mConfig.update( mLayer->fields() );
159 mEditorContext = context;
166 const bool needsGeometry = mLayer->conditionalStyles()->rulesNeedGeometry()
172 initLayerCache( needsGeometry );
173 initModels( mapCanvas, request, loadFeatures );
175 mConditionalFormatWidget->setLayer( mLayer );
177 mTableView->setModel( mFilterModel );
178 mFeatureListView->setModel( mFeatureListModel );
183 if ( mFeatureListPreviewButton->defaultAction() )
185 mFeatureListView->setDisplayExpression( mDisplayExpression );
195 if ( showFirstFeature && mFeatureListModel->rowCount() > 0 )
206void QgsDualView::initAttributeForm(
const QgsFeature &feature )
208 Q_ASSERT( !mAttributeForm );
214 mAttributeEditorScrollArea->setWidgetResizable(
true );
215 mAttributeEditor->layout()->addWidget( mAttributeEditorScrollArea );
216 mAttributeEditorScrollArea->setWidget( mAttributeForm );
220 mAttributeEditor->layout()->addWidget( mAttributeForm );
225 mAttributeForm->setMinimumWidth( 200 );
233 if ( QgsMapCanvas *canvas = mFilterModel->mapCanvas() )
239 if ( QgsMapCanvas *canvas = mFilterModel->mapCanvas() )
248void QgsDualView::columnBoxInit()
251 const QList<QgsField> fields = mLayer->fields().toList();
252 const QString displayExpression = mLayer->displayExpression();
254 mFeatureListPreviewButton->addAction( mActionExpressionPreview );
255 mFeatureListPreviewButton->addAction( mActionPreviewColumnsMenu );
257 QAction *defaultFieldAction =
nullptr;
258 const auto constFields = fields;
259 for (
const QgsField &field : constFields )
261 const int fieldIndex = mLayer->fields().lookupField( field.name() );
262 if ( fieldIndex == -1 )
265 const QString fieldName = field.name();
268 const QIcon fieldIcon = mLayer->fields().iconForField( fieldIndex );
269 const QString fieldDisplayName = mLayer->attributeDisplayName( fieldIndex );
272 QAction *previewAction =
new QAction( fieldIcon, fieldDisplayName, mFeatureListPreviewButton );
273 connect( previewAction, &QAction::triggered,
this, [
this, previewAction, fieldName] { previewColumnChanged( previewAction, fieldName ); } );
274 mPreviewColumnsMenu->addAction( previewAction );
276 if ( fieldDisplayName == displayExpression
277 || u
"COALESCE( \"%1\", '<NULL>' )"_s.arg( fieldDisplayName ) == displayExpression
278 || u
"\"%1\""_s.arg( fieldDisplayName ) == displayExpression
279 || fieldName == displayExpression
280 || u
"COALESCE( \"%1\", '<NULL>' )"_s.arg( fieldName ) == displayExpression
281 || u
"\"%1\""_s.arg( fieldName ) == displayExpression )
283 defaultFieldAction = previewAction;
288 QMenu *sortMenu =
new QMenu(
this );
290 sortMenuAction->setMenu( sortMenu );
292 QAction *sortByPreviewExpressionAsc =
new QAction(
QgsApplication::getThemeIcon( u
"sort.svg"_s ), tr(
"By Display Name (Ascending)" ),
this );
293 connect( sortByPreviewExpressionAsc, &QAction::triggered,
this, [
this]() { mFeatureListModel->setSortByDisplayExpression(
true, Qt::AscendingOrder ); } );
294 sortMenu->addAction( sortByPreviewExpressionAsc );
295 QAction *sortByPreviewExpressionDesc =
new QAction(
QgsApplication::getThemeIcon( u
"sort-reverse.svg"_s ), tr(
"By Display Name (Descending)" ),
this );
296 connect( sortByPreviewExpressionDesc, &QAction::triggered,
this, [
this]() { mFeatureListModel->setSortByDisplayExpression(
true, Qt::DescendingOrder ); } );
297 sortMenu->addAction( sortByPreviewExpressionDesc );
298 QAction *sortByPreviewExpressionCustom =
new QAction(
QgsApplication::getThemeIcon( u
"mIconExpressionPreview.svg"_s ), tr(
"By Custom Expression" ),
this );
299 connect( sortByPreviewExpressionCustom, &QAction::triggered,
this, [
this]() {
301 mFeatureListModel->setSortByDisplayExpression(
false );
303 sortMenu->addAction( sortByPreviewExpressionCustom );
305 mFeatureListPreviewButton->addAction( sortMenuAction );
307 QAction *separator =
new QAction( mFeatureListPreviewButton );
308 separator->setSeparator(
true );
309 mFeatureListPreviewButton->addAction( separator );
310 restoreRecentDisplayExpressions();
312 mSkipDisplayExpressionChangedSignal =
true;
313 if ( defaultFieldAction )
315 mFeatureListPreviewButton->setDefaultAction( defaultFieldAction );
316 mFeatureListPreviewButton->defaultAction()->trigger();
320 mActionExpressionPreview->setToolTip( displayExpression );
321 mFeatureListPreviewButton->setDefaultAction( mActionExpressionPreview );
323 mFeatureListView->setDisplayExpression( displayExpression );
324 setDisplayExpression( displayExpression.isEmpty() ? tr(
"'[Please define preview text]'" ) : displayExpression );
326 mSkipDisplayExpressionChangedSignal =
false;
331 setCurrentIndex(
view );
336 return mFilterModel->filterMode();
347 switch ( mFilterModel->filterMode() )
371 mMasterModel->setShowValidityState(
false );
381 const bool requiresTableReload = ( request.
filterType() != Qgis::Qgis::FeatureRequestFilterType::NoFilter
384 || ( mMasterModel->rowCount() == 0 );
396 if ( mFilterModel->mapCanvas() )
398 const QgsRectangle rect = mFilterModel->mapCanvas()->mapSettings().mapToLayerCoordinates( mLayer, mFilterModel->mapCanvas()->extent() );
413 mMasterModel->setShowValidityState(
true );
425 if ( !filterExpression.isEmpty() )
442 setBrowsingAutoPanScaleAllowed(
false );
450 setBrowsingAutoPanScaleAllowed(
true );
454 if ( requiresTableReload )
457 mFilterModel->disconnectFilterModeConnections();
459 mMasterModel->setRequest( request );
460 whileBlocking( mLayerCache )->setCacheGeometry( needsGeometry );
461 mMasterModel->loadLayer();
471 mFilterModel->setSelectedOnTop( selectedOnTop );
474void QgsDualView::initLayerCache(
bool cacheGeometry )
484 rebuildFullLayerCache();
490 delete mFeatureListModel;
494 mMasterModel =
new QgsAttributeTableModel( mLayerCache,
this );
495 mMasterModel->setRequest( request );
496 mMasterModel->setEditorContext( mEditorContext );
497 mMasterModel->setExtraColumns( 1 );
505 mMasterModel->loadLayer();
507 mFilterModel =
new QgsAttributeTableFilterModel( mapCanvas, mMasterModel, mMasterModel );
511 connect( mMasterModel, &QgsAttributeTableModel::rowsRemoved, mFilterModel, &QgsAttributeTableFilterModel::invalidate );
512 connect( mMasterModel, &QgsAttributeTableModel::rowsInserted, mFilterModel, &QgsAttributeTableFilterModel::invalidate );
516 mFeatureListModel =
new QgsFeatureListModel( mFilterModel, mFilterModel );
519void QgsDualView::restoreRecentDisplayExpressions()
521 const QVariantList previewExpressions = mLayer->customProperty( u
"dualview/previewExpressions"_s ).toList();
523 for (
const QVariant &previewExpression : previewExpressions )
525 insertRecentlyUsedDisplayExpression( previewExpression.toString() );
529void QgsDualView::saveRecentDisplayExpressions()
const
535 const QList<QAction *> actions = mFeatureListPreviewButton->actions();
538 int index = actions.indexOf( mLastDisplayExpressionAction );
541 QVariantList previewExpressions;
542 for ( ; index < actions.length(); ++index )
544 QAction *action = actions.at( index );
545 previewExpressions << action->property(
"previewExpression" );
548 mLayer->setCustomProperty( u
"dualview/previewExpressions"_s, previewExpressions );
552void QgsDualView::setDisplayExpression(
const QString &expression )
554 mDisplayExpression = expression;
555 insertRecentlyUsedDisplayExpression( expression );
558void QgsDualView::insertRecentlyUsedDisplayExpression(
const QString &expression )
560 const QList<QAction *> actions = mFeatureListPreviewButton->actions();
563 const int index = actions.indexOf( mLastDisplayExpressionAction );
566 for (
int i = 0; index + i < actions.length(); ++i )
568 QAction *action = actions.at( index );
569 if ( action->text() == expression || i >= 9 )
571 if ( action == mLastDisplayExpressionAction )
573 mLastDisplayExpressionAction =
nullptr;
575 mFeatureListPreviewButton->removeAction( action );
579 if ( !mLastDisplayExpressionAction )
581 mLastDisplayExpressionAction = action;
587 QString name = expression;
589 if ( expression.startsWith(
"COALESCE( \""_L1 ) && expression.endsWith(
", '<NULL>' )"_L1 ) )
591 name = expression.mid( 11, expression.length() - 24 );
593 const int fieldIndex = mLayer->fields().indexOf( name );
594 if ( fieldIndex != -1 )
596 name = mLayer->attributeDisplayName( fieldIndex );
597 icon = mLayer->fields().iconForField( fieldIndex );
605 QAction *previewAction =
new QAction( icon, name, mFeatureListPreviewButton );
606 previewAction->setProperty(
"previewExpression", expression );
607 connect( previewAction, &QAction::triggered,
this, [expression,
this](
bool ) {
608 setDisplayExpression( expression );
609 mFeatureListPreviewButton->setText( tr(
"Expression" ) );
610 mFeatureListPreviewButton->setToolTip( expression );
613 mFeatureListPreviewButton->insertAction( mLastDisplayExpressionAction, previewAction );
614 mLastDisplayExpressionAction = previewAction;
617void QgsDualView::updateEditSelectionProgress(
int progress,
int count )
619 mProgressCount->setText( u
"%1 / %2"_s.arg( progress + 1 ).arg( count ) );
620 mPreviousFeatureButton->setEnabled( progress > 0 );
621 mNextFeatureButton->setEnabled( progress + 1 < count );
622 mFirstFeatureButton->setEnabled( progress > 0 );
623 mLastFeatureButton->setEnabled( progress + 1 < count );
624 if ( mAttributeForm )
626 mAttributeForm->setVisible( count > 0 );
630void QgsDualView::panOrZoomToFeature(
const QgsFeatureIds &featureset )
632 QgsMapCanvas *canvas = mFilterModel->mapCanvas();
635 if ( mBrowsingAutoPanScaleAllowed )
637 if ( mAutoPanButton->isChecked() )
638 QTimer::singleShot( 0,
this, [
this, featureset, canvas]() { canvas->
panToFeatureIds( mLayer, featureset,
false ); } );
639 else if ( mAutoZoomButton->isChecked() )
640 QTimer::singleShot( 0,
this, [
this, featureset, canvas]() { canvas->
zoomToFeatureIds( mLayer, featureset ); } );
642 if ( mFlashButton->isChecked() )
643 QTimer::singleShot( 0,
this, [
this, featureset, canvas]() { canvas->
flashFeatureIds( mLayer, featureset ); } );
644 mLastFeatureSet = featureset;
648void QgsDualView::setBrowsingAutoPanScaleAllowed(
bool allowed )
650 if ( mBrowsingAutoPanScaleAllowed == allowed )
653 mBrowsingAutoPanScaleAllowed = allowed;
655 mAutoPanButton->setEnabled( allowed );
656 mAutoZoomButton->setEnabled( allowed );
658 const QString disabledHint = tr(
"(disabled when attribute table only shows features visible in the current map canvas extent)" );
660 mAutoPanButton->setToolTip( tr(
"Automatically pan to the current feature" ) + ( allowed ? QString() : QString(
' ' ) + disabledHint ) );
661 mAutoZoomButton->setToolTip( tr(
"Automatically zoom to the current feature" ) + ( allowed ? QString() : QString(
' ' ) + disabledHint ) );
664void QgsDualView::panZoomGroupButtonToggled( QAbstractButton *button,
bool checked )
666 if ( button == mAutoPanButton && checked )
668 QgsSettings().setEnumValue( u
"/qgis/attributeTable/featureListBrowsingAction"_s,
PanToFeature );
669 mAutoZoomButton->setChecked(
false );
671 else if ( button == mAutoZoomButton && checked )
673 QgsSettings().setEnumValue( u
"/qgis/attributeTable/featureListBrowsingAction"_s,
ZoomToFeature );
674 mAutoPanButton->setChecked(
false );
678 QgsSettings().setEnumValue( u
"/qgis/attributeTable/featureListBrowsingAction"_s,
NoAction );
681 if ( checked && mLayer->isSpatial() )
682 panOrZoomToFeature( mFeatureListView->currentEditSelection() );
685void QgsDualView::flashButtonClicked(
bool clicked )
691 QgsMapCanvas *canvas = mFilterModel->mapCanvas();
694 canvas->
flashFeatureIds( mLayer, mFeatureListView->currentEditSelection() );
697void QgsDualView::filterError(
const QString &errorMessage )
699 if ( mEditorContext.mainMessageBar() )
701 mEditorContext.mainMessageBar()->pushWarning( tr(
"An error occurred while filtering features" ), errorMessage );
705void QgsDualView::featureListAboutToChangeEditSelection(
bool &ok )
707 if ( !mAttributeForm )
710 if ( mLayer->isEditable() && !mAttributeForm->save() )
714void QgsDualView::featureListCurrentEditSelectionChanged(
const QgsFeature &feat )
716 if ( !mAttributeForm )
718 initAttributeForm( feat );
720 else if ( !mLayer->isEditable() || mAttributeForm->save() )
722 mAttributeForm->setFeature( feat );
724 featureset << feat.
id();
727 if ( mLayer->isSpatial() )
728 panOrZoomToFeature( featureset );
738 mFeatureListView->setCurrentFeatureEdited(
false );
739 mFeatureListView->setEditSelection( fids );
744 return mAttributeForm ? mAttributeForm->save() :
false;
749 mConditionalFormatWidgetStack->setVisible( !mConditionalFormatWidgetStack->isVisible() );
754 if ( !mAttributeForm )
759 mPreviousView =
view();
772 if ( !mAttributeForm )
779 mAttributeForm->setVisible(
true );
784 mAttributeForm->setVisible( mFilterModel->rowCount() > 0 );
788void QgsDualView::previewExpressionBuilder()
794 dlg.setWindowTitle( tr(
"Expression Based Preview" ) );
795 dlg.setExpressionText( mFeatureListView->displayExpression() );
797 if ( dlg.exec() == QDialog::Accepted )
799 mFeatureListView->setDisplayExpression( dlg.expressionText() );
800 mActionExpressionPreview->setToolTip( dlg.expressionText() );
802 mFeatureListPreviewButton->setDefaultAction( mActionExpressionPreview );
803 mFeatureListPreviewButton->setPopupMode( QToolButton::MenuButtonPopup );
806 setDisplayExpression( mFeatureListView->displayExpression() );
809void QgsDualView::previewColumnChanged( QAction *previewAction,
const QString &expression )
811 if ( !mFeatureListView->setDisplayExpression( u
"COALESCE( \"%1\", '<NULL>' )"_s.arg( expression ) ) )
813 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() ) );
817 mFeatureListPreviewButton->setText( previewAction->text() );
818 mFeatureListPreviewButton->setIcon( previewAction->icon() );
819 mFeatureListPreviewButton->setPopupMode( QToolButton::InstantPopup );
822 setDisplayExpression( mFeatureListView->displayExpression() );
827 return mMasterModel->rowCount();
832 return mFilterModel->rowCount();
837 const QModelIndex currentIndex = mTableView->currentIndex();
838 if ( !currentIndex.isValid() )
843 const QVariant var = mMasterModel->data( currentIndex, Qt::DisplayRole );
844 QApplication::clipboard()->setText( var.toString() );
850 mProgressDlg->cancel();
855 if ( mAttributeForm )
857 mAttributeForm->parentFormValueChanged( attribute, newValue );
864 saveRecentDisplayExpressions();
871 conditionalFormattingSplitterState->setValue( mConditionalSplitter->saveState() );
872 attributeEditorSplitterState->setValue( mAttributeEditorViewSplitter->saveState() );
875void QgsDualView::viewWillShowContextMenu( QMenu *menu,
const QModelIndex &masterIndex )
882 const QVariant displayValue = mMasterModel->data( masterIndex, Qt::DisplayRole );
884 if ( displayValue.isValid() )
887 QString previewDisplayValue = displayValue.toString();
888 if ( previewDisplayValue.length() > 12 )
890 previewDisplayValue.truncate( 12 );
891 previewDisplayValue.append( u
"…"_s );
895 QAction *copyContentAction = menu->addAction( tr(
"Copy Cell Content (%1)" ).arg( previewDisplayValue ) );
896 menu->addAction( copyContentAction );
897 connect( copyContentAction, &QAction::triggered,
this, [displayValue] { QApplication::clipboard()->setText( displayValue.toString() ); } );
900 const QVariant rawValue = mMasterModel->data( masterIndex, Qt::EditRole );
901 if ( rawValue.isValid() )
904 QString previewRawValue = rawValue.toString();
905 if ( previewRawValue.length() > 12 )
907 previewRawValue.truncate( 12 );
908 previewRawValue.append( u
"…"_s );
911 QAction *copyRawContentAction = menu->addAction( tr(
"Copy Raw Value (%1)" ).arg( previewRawValue ) );
912 menu->addAction( copyRawContentAction );
913 connect( copyRawContentAction, &QAction::triggered,
this, [rawValue] { QApplication::clipboard()->setText( rawValue.toString() ); } );
916 QgsVectorLayer *vl = mFilterModel->layer();
917 QgsMapCanvas *canvas = mFilterModel->mapCanvas();
920 QAction *zoomToFeatureAction = menu->addAction( tr(
"Zoom to Feature" ) );
921 connect( zoomToFeatureAction, &QAction::triggered,
this, &QgsDualView::zoomToCurrentFeature );
923 QAction *panToFeatureAction = menu->addAction( tr(
"Pan to Feature" ) );
924 connect( panToFeatureAction, &QAction::triggered,
this, &QgsDualView::panToCurrentFeature );
926 QAction *flashFeatureAction = menu->addAction( tr(
"Flash Feature" ) );
927 connect( flashFeatureAction, &QAction::triggered,
this, &QgsDualView::flashCurrentFeature );
931 const QList<QgsAction> actions = mLayer->actions()->actions( u
"Field"_s );
932 if ( !actions.isEmpty() )
934 QAction *a = menu->addAction( tr(
"Run Layer Action" ) );
935 a->setEnabled(
false );
937 for (
const QgsAction &action : actions )
939 if ( !action.runable() )
942 if ( vl && !vl->
isEditable() && action.isEnabledOnlyWhenEditable() )
945 QgsAttributeTableAction *a =
new QgsAttributeTableAction( action.name(),
this, action.id(), masterIndex );
949 const QModelIndex rowSourceIndex = mMasterModel->index( masterIndex.row(), 0 );
950 if ( !rowSourceIndex.isValid() )
956 QgsMapLayerActionContext context;
958 if ( !registeredActions.isEmpty() )
961 menu->addSeparator();
963 for ( QgsMapLayerAction *action : registeredActions )
965 QgsAttributeTableMapLayerAction *a =
new QgsAttributeTableMapLayerAction( action->text(),
this, action, rowSourceIndex );
972 const QgsFeatureId currentFid = mMasterModel->rowToId( masterIndex.row() );
973 if ( mLayer->selectedFeatureCount() > 1 && mLayer->selectedFeatureIds().contains( currentFid ) )
976 if ( !registeredActions.isEmpty() )
978 menu->addSeparator();
979 QAction *action = menu->addAction( tr(
"Actions on Selection (%1)" ).arg( mLayer->selectedFeatureCount() ) );
980 action->setEnabled(
false );
982 QgsMapLayerActionContext context;
983 for ( QgsMapLayerAction *action : registeredActions )
985 menu->addAction( action->text(), action, [
this, action, context]() {
986 Q_NOWARN_DEPRECATED_PUSH
987 action->triggerForFeatures( mLayer, mLayer->selectedFeatures() );
988 Q_NOWARN_DEPRECATED_POP
989 action->triggerForFeatures( mLayer, mLayer->selectedFeatures(), context );
995 menu->addSeparator();
996 QgsAttributeTableAction *a =
new QgsAttributeTableAction( tr(
"Open Form" ),
this, QUuid(), rowSourceIndex );
1001void QgsDualView::widgetWillShowContextMenu(
QgsActionMenu *menu,
const QModelIndex &atIndex )
1007void QgsDualView::showViewHeaderMenu( QPoint point )
1009 const int col = mTableView->columnAt( point.x() );
1011 delete mHorizontalHeaderMenu;
1012 mHorizontalHeaderMenu =
new QMenu(
this );
1014 QAction *hide =
new QAction( tr(
"&Hide Column" ), mHorizontalHeaderMenu );
1015 connect( hide, &QAction::triggered,
this, &QgsDualView::hideColumn );
1016 hide->setData( col );
1017 mHorizontalHeaderMenu->addAction( hide );
1018 QAction *setWidth =
new QAction( tr(
"&Set Width…" ), mHorizontalHeaderMenu );
1019 connect( setWidth, &QAction::triggered,
this, &QgsDualView::resizeColumn );
1020 setWidth->setData( col );
1021 mHorizontalHeaderMenu->addAction( setWidth );
1023 QAction *setWidthAllColumns =
new QAction( tr(
"&Set All Column Widths…" ), mHorizontalHeaderMenu );
1024 connect( setWidthAllColumns, &QAction::triggered,
this, &QgsDualView::resizeAllColumns );
1025 setWidthAllColumns->setData( col );
1026 mHorizontalHeaderMenu->addAction( setWidthAllColumns );
1028 QAction *optimizeWidth =
new QAction( tr(
"&Autosize" ), mHorizontalHeaderMenu );
1029 connect( optimizeWidth, &QAction::triggered,
this, &QgsDualView::autosizeColumn );
1030 optimizeWidth->setData( col );
1031 mHorizontalHeaderMenu->addAction( optimizeWidth );
1033 QAction *optimizeWidthAllColumns =
new QAction( tr(
"&Autosize All Columns" ), mHorizontalHeaderMenu );
1034 connect( optimizeWidthAllColumns, &QAction::triggered,
this, &QgsDualView::autosizeAllColumns );
1035 mHorizontalHeaderMenu->addAction( optimizeWidthAllColumns );
1038 mHorizontalHeaderMenu->addSeparator();
1039 QAction *organize =
new QAction( tr(
"&Organize Columns…" ), mHorizontalHeaderMenu );
1040 connect( organize, &QAction::triggered,
this, &QgsDualView::organizeColumns );
1041 mHorizontalHeaderMenu->addAction( organize );
1042 QAction *sort =
new QAction( tr(
"&Sort…" ), mHorizontalHeaderMenu );
1043 connect( sort, &QAction::triggered,
this, [
this]() { modifySort(); } );
1044 mHorizontalHeaderMenu->addAction( sort );
1046 mConfig.update( mLayer->fields() );
1048 int fieldIndex = -1;
1050 fieldIndex = mLayer->fields().indexFromName( mConfig.columns().at( mConfig.mapVisibleColumnToIndex( col ) ).name );
1051 const Qgis::FieldOrigin fieldOrigin = mLayer->fields().fieldOrigin( fieldIndex );
1053 mHorizontalHeaderMenu->addSeparator();
1055 const QgsVectorLayer *vl = mFilterModel->layer();
1056 const QgsVectorDataProvider *dataProvider = vl->
dataProvider();
1058 const bool layerIsReadOnly { vl->
readOnly() };
1061 bool fieldCalculatorEnabled =
false;
1063 switch ( fieldOrigin )
1067 fieldCalculatorEnabled = canChangeAttributeValue;
1072 const QgsVectorLayerJoinInfo *info = mLayer->joinBuffer()->joinForFieldIndex( fieldIndex, mLayer->fields(), srcFieldIndex );
1073 const QgsVectorLayer *joinedLayer = info->
joinLayer();
1074 const QgsVectorDataProvider *joinedDataProvider = joinedLayer->
dataProvider();
1076 const bool joinedLayerIsReadOnly { joinedLayer->
readOnly() };
1079 fieldCalculatorEnabled = joinedLayerCanChangeAttributeValue;
1089 QAction *fieldCalculator =
new QAction( tr(
"Open &Field Calculator…" ), mHorizontalHeaderMenu );
1090 connect( fieldCalculator, &QAction::triggered,
this, &QgsDualView::fieldCalculator );
1091 fieldCalculator->setData( fieldIndex );
1092 mHorizontalHeaderMenu->addAction( fieldCalculator );
1094 fieldCalculator->setEnabled( fieldCalculatorEnabled );
1096 mHorizontalHeaderMenu->popup( mTableView->horizontalHeader()->mapToGlobal( point ) );
1099void QgsDualView::organizeColumns()
1107 if ( dialog.exec() == QDialog::Accepted )
1109 const QgsAttributeTableConfig config = dialog.config();
1114void QgsDualView::tableColumnResized(
int column,
int width )
1116 QgsAttributeTableConfig config = mConfig;
1118 if ( sourceCol >= 0 && config.
columnWidth( sourceCol ) != width )
1125void QgsDualView::hideColumn()
1127 QAction *action = qobject_cast<QAction *>( sender() );
1128 const int col = action->data().toInt();
1129 QgsAttributeTableConfig config = mConfig;
1131 if ( sourceCol >= 0 )
1138void QgsDualView::fieldCalculator()
1140 QAction *action = qobject_cast<QAction *>( sender() );
1141 const int fieldIndex = action->data().toInt();
1142 mConfig.update( mLayer->fields() );
1143 QgsFieldCalculator calc( mLayer,
this, fieldIndex );
1144 if ( calc.exec() == QDialog::Accepted )
1146 int col = mMasterModel->fieldCol( calc.changedAttributeId() );
1149 mMasterModel->reload( mMasterModel->index( 0, col ), mMasterModel->index( mMasterModel->rowCount() - 1, col ) );
1153void QgsDualView::resizeColumn()
1155 QAction *action = qobject_cast<QAction *>( sender() );
1156 const int col = action->data().toInt();
1160 QgsAttributeTableConfig config = mConfig;
1162 if ( sourceCol >= 0 )
1165 const int width = QInputDialog::getInt(
this, tr(
"Set column width" ), tr(
"Enter column width" ), mTableView->columnWidth( col ), 0, 1000, 10, &ok );
1174void QgsDualView::resizeAllColumns()
1176 QAction *action = qobject_cast<QAction *>( sender() );
1177 const int col = action->data().toInt();
1181 QgsAttributeTableConfig config = mConfig;
1184 const int width = QInputDialog::getInt(
this, tr(
"Set Column Width" ), tr(
"Enter column width" ), mTableView->columnWidth( col ), 1, 1000, 10, &ok );
1187 const int colCount = mTableView->model()->columnCount();
1190 for (
int i = 0; i < colCount; i++ )
1199void QgsDualView::autosizeColumn()
1201 QAction *action = qobject_cast<QAction *>( sender() );
1202 const int col = action->data().toInt();
1203 mTableView->resizeColumnToContents( col );
1206void QgsDualView::autosizeAllColumns()
1208 mTableView->resizeColumnsToContents();
1211bool QgsDualView::modifySort()
1216 QgsAttributeTableConfig config = mConfig;
1219 orderByDlg.setWindowTitle( tr(
"Configure Attribute Table Sort Order" ) );
1220 QDialogButtonBox *dialogButtonBox =
new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
1221 QGridLayout *layout =
new QGridLayout();
1222 connect( dialogButtonBox, &QDialogButtonBox::accepted, &orderByDlg, &QDialog::accept );
1223 connect( dialogButtonBox, &QDialogButtonBox::rejected, &orderByDlg, &QDialog::reject );
1224 orderByDlg.setLayout( layout );
1226 QGroupBox *sortingGroupBox =
new QGroupBox();
1227 sortingGroupBox->setTitle( tr(
"Defined sort order in attribute table" ) );
1228 sortingGroupBox->setCheckable(
true );
1230 layout->addWidget( sortingGroupBox );
1231 sortingGroupBox->setLayout(
new QGridLayout() );
1233 QgsExpressionBuilderWidget *expressionBuilder =
new QgsExpressionBuilderWidget();
1236 expressionBuilder->
initWithLayer( mLayer, context, u
"generic"_s );
1239 sortingGroupBox->layout()->addWidget( expressionBuilder );
1241 QCheckBox *cbxSortAscending =
new QCheckBox( tr(
"Sort ascending" ) );
1242 cbxSortAscending->setChecked( config.
sortOrder() == Qt::AscendingOrder );
1243 sortingGroupBox->layout()->addWidget( cbxSortAscending );
1245 layout->addWidget( dialogButtonBox );
1246 if ( orderByDlg.exec() )
1248 const Qt::SortOrder sortOrder = cbxSortAscending->isChecked() ? Qt::AscendingOrder : Qt::DescendingOrder;
1249 if ( sortingGroupBox->isChecked() )
1271 QSet<int> attributes;
1275 const QVector<QgsAttributeTableConfig::ColumnConfig> constColumnconfigs { config.
columns() };
1284 const QSet<int> colAttrs { attributes };
1285 for (
const int attrIdx : std::as_const( colAttrs ) )
1294 std::sort( attrs.begin(), attrs.end() );
1298void QgsDualView::zoomToCurrentFeature()
1300 const QModelIndex currentIndex = mTableView->currentIndex();
1301 if ( !currentIndex.isValid() )
1307 ids.insert( mFilterModel->rowToId( currentIndex ) );
1308 QgsMapCanvas *canvas = mFilterModel->mapCanvas();
1315void QgsDualView::panToCurrentFeature()
1317 const QModelIndex currentIndex = mTableView->currentIndex();
1318 if ( !currentIndex.isValid() )
1324 ids.insert( mFilterModel->rowToId( currentIndex ) );
1325 QgsMapCanvas *canvas = mFilterModel->mapCanvas();
1332void QgsDualView::flashCurrentFeature()
1334 const QModelIndex currentIndex = mTableView->currentIndex();
1335 if ( !currentIndex.isValid() )
1341 ids.insert( mFilterModel->rowToId( currentIndex ) );
1342 QgsMapCanvas *canvas = mFilterModel->mapCanvas();
1349void QgsDualView::rebuildFullLayerCache()
1354 mLayerCache->setFullCache(
true );
1357void QgsDualView::previewExpressionChanged(
const QString &expression )
1359 if ( !mSkipDisplayExpressionChangedSignal )
1361 mLayer->setDisplayExpression( expression );
1365void QgsDualView::onSortColumnChanged()
1376void QgsDualView::updateSelectedFeatures()
1378 QgsFeatureRequest r = mMasterModel->request();
1383 mMasterModel->setRequest( r );
1384 mMasterModel->loadLayer();
1388void QgsDualView::updateEditedAddedFeatures()
1390 QgsFeatureRequest r = mMasterModel->request();
1395 mMasterModel->setRequest( r );
1396 mMasterModel->loadLayer();
1400void QgsDualView::extentChanged()
1402 QgsFeatureRequest r = mMasterModel->request();
1405 const QgsRectangle rect = mFilterModel->mapCanvas()->mapSettings().mapToLayerCoordinates( mLayer, mFilterModel->mapCanvas()->extent() );
1407 mMasterModel->setRequest( r );
1408 mMasterModel->loadLayer();
1413void QgsDualView::featureFormAttributeChanged(
const QString &attribute,
const QVariant &value,
bool attributeChanged )
1415 Q_UNUSED( attribute )
1417 if ( attributeChanged )
1419 mFeatureListView->setCurrentFeatureEdited(
true );
1420 mAttributeForm->save();
1431 mFilterModel->setFilterExpression( filterExpression, context );
1432 mFilterModel->filterFeatures();
1437 return mFilterModel->filteredFeatures();
1443 mMasterModel->setRequest( request );
1448 mTableView->setFeatureSelectionManager( featureSelectionManager );
1449 mFeatureListView->setFeatureSelectionManager( featureSelectionManager );
1451 if ( mFeatureSelectionManager && mFeatureSelectionManager->parent() ==
this )
1452 delete mFeatureSelectionManager;
1454 mFeatureSelectionManager = featureSelectionManager;
1460 mConfig.
update( mLayer->fields() );
1461 mLayer->setAttributeTableConfig( mConfig );
1462 mFilterModel->setAttributeTableConfig( mConfig );
1463 mTableView->setAttributeTableConfig( mConfig );
1469 mLayerCache->setCacheGeometry(
true );
1473 mMasterModel->setRequest( request );
1474 mLayerCache->setCacheSubsetOfAttributes( attributes );
1480 mFilterModel->sort( -1 );
1485 mConfig.setSortOrder( sortOrder );
1491 return mFilterModel->sortExpression();
1499void QgsDualView::progress(
int i,
bool &cancel )
1501 if ( !mProgressDlg )
1503 mProgressDlg =
new QProgressDialog( tr(
"Loading features…" ), tr(
"Abort" ), 0, 0,
this );
1504 mProgressDlg->setWindowTitle( tr(
"Attribute Table" ) );
1505 mProgressDlg->setWindowModality( Qt::WindowModal );
1506 mProgressDlg->show();
1509 mProgressDlg->setLabelText( tr(
"%L1 features loaded." ).arg( i ) );
1510 QCoreApplication::processEvents();
1512 cancel = mProgressDlg && mProgressDlg->wasCanceled();
1515void QgsDualView::finished()
1517 delete mProgressDlg;
1518 mProgressDlg =
nullptr;
1527 mDualView->masterModel()->executeAction( mAction, mFieldIdx );
1533 editedIds << mDualView->masterModel()->rowToId( mFieldIdx.row() );
1534 mDualView->setCurrentEditSelection( editedIds );
1545 mDualView->masterModel()->executeMapLayerAction( mAction, mFieldIdx, context );
AttributeTableFilterMode
Defines how rows in attribute tables should be filtered.
@ ShowSelected
Show only selected features.
@ ShowAll
Show all features.
@ ShowInvalid
Show only features not respecting constraints.
@ ShowVisible
Show only visible features (depends on the map canvas).
@ ShowFilteredList
Show only features whose IDs are on the filter list.
@ ShowEdited
Show only features which have unsaved changes.
@ 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.
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.
Qgis::AttributeTableFilterMode filterMode() const
Gets the filter mode.
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.
void setFilterMode(Qgis::AttributeTableFilterMode filterMode)
Set the filter mode.
static QgsAttributeList requiredAttributes(const QgsVectorLayer *layer)
Returns the list of required attributes according to the attribute table configuration of the layer,...
void setMultiEditEnabled(bool enabled)
Sets whether multi edit mode is enabled.
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.
QgsFeatureIds filteredFeatures() const
Gets a list of currently visible feature ids.
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 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.