48#include <QInputDialog>
51#include <QProgressDialog>
56#include "moc_qgsdualview.cpp"
58using namespace Qt::StringLiterals;
63const std::unique_ptr<QgsSettingsEntryVariant> QgsDualView::conditionalFormattingSplitterState = std::make_unique<
65const std::unique_ptr<QgsSettingsEntryVariant> QgsDualView::attributeEditorSplitterState = std::make_unique<
69 : QStackedWidget( parent )
78 mTableView->horizontalHeader()->setContextMenuPolicy( Qt::CustomContextMenu );
79 connect( mTableView->horizontalHeader(), &QHeaderView::customContextMenuRequested,
this, &QgsDualView::showViewHeaderMenu );
82 mConditionalFormatWidgetStack->hide();
84 mConditionalFormatWidgetStack->setMainPanel( mConditionalFormatWidget );
85 mConditionalFormatWidget->setDockMode(
true );
89 conditionalFormattingSplitterState->copyValueFromKey( u
"/qgis/attributeTable/splitterState"_s,
true );
90 mConditionalSplitter->restoreState( conditionalFormattingSplitterState->value().toByteArray() );
91 mAttributeEditorViewSplitter->restoreState( attributeEditorSplitterState->value().toByteArray() );
93 mPreviewColumnsMenu =
new QMenu(
this );
94 mActionPreviewColumnsMenu->setMenu( mPreviewColumnsMenu );
98 mActionExpressionPreview->setText( tr(
"Expression" ) );
101 connect( mActionExpressionPreview, &QAction::triggered,
this, &QgsDualView::previewExpressionBuilder );
110 auto createShortcuts = [
this](
const QString &objectName, void (
QgsFeatureListView::*slot )() ) {
115 connect( sc, &QShortcut::activated, mFeatureListView, slot );
122 QButtonGroup *buttonGroup =
new QButtonGroup(
this );
123 buttonGroup->setExclusive(
false );
127 QAbstractButton *bt = buttonGroup->button(
static_cast<int>( action ) );
129 bt->setChecked(
true );
130 connect( buttonGroup, qOverload<QAbstractButton *, bool>( &QButtonGroup::buttonToggled ),
this, &QgsDualView::panZoomGroupButtonToggled );
132 connect( mFlashButton, &QToolButton::clicked,
this, &QgsDualView::flashButtonClicked );
143 delete mAttributeForm;
144 mAttributeForm =
nullptr;
151 mEditorContext = context;
158 const bool needsGeometry = mLayer->conditionalStyles()->rulesNeedGeometry()
164 initLayerCache( needsGeometry );
165 initModels( mapCanvas, request, loadFeatures );
167 mConditionalFormatWidget->setLayer( mLayer );
169 mTableView->setModel( mFilterModel );
170 mFeatureListView->setModel( mFeatureListModel );
175 if ( mFeatureListPreviewButton->defaultAction() )
177 mFeatureListView->setDisplayExpression( mDisplayExpression );
187 if ( showFirstFeature && mFeatureListModel->rowCount() > 0 )
198void QgsDualView::initAttributeForm(
const QgsFeature &feature )
200 Q_ASSERT( !mAttributeForm );
206 mAttributeEditorScrollArea->setWidgetResizable(
true );
207 mAttributeEditor->layout()->addWidget( mAttributeEditorScrollArea );
208 mAttributeEditorScrollArea->setWidget( mAttributeForm );
212 mAttributeEditor->layout()->addWidget( mAttributeForm );
217 mAttributeForm->setMinimumWidth( 200 );
225 if ( QgsMapCanvas *canvas = mFilterModel->mapCanvas() )
231 if ( QgsMapCanvas *canvas = mFilterModel->mapCanvas() )
240void QgsDualView::columnBoxInit()
243 const QList<QgsField> fields = mLayer->fields().toList();
244 const QString displayExpression = mLayer->displayExpression();
246 mFeatureListPreviewButton->addAction( mActionExpressionPreview );
247 mFeatureListPreviewButton->addAction( mActionPreviewColumnsMenu );
249 QAction *defaultFieldAction =
nullptr;
250 const auto constFields = fields;
251 for (
const QgsField &field : constFields )
253 const int fieldIndex = mLayer->fields().lookupField( field.name() );
254 if ( fieldIndex == -1 )
257 const QString fieldName = field.name();
260 const QIcon fieldIcon = mLayer->fields().iconForField( fieldIndex );
261 const QString fieldDisplayName = mLayer->attributeDisplayName( fieldIndex );
264 QAction *previewAction =
new QAction( fieldIcon, fieldDisplayName, mFeatureListPreviewButton );
265 connect( previewAction, &QAction::triggered,
this, [
this, previewAction, fieldName] { previewColumnChanged( previewAction, fieldName ); } );
266 mPreviewColumnsMenu->addAction( previewAction );
268 if ( fieldDisplayName == displayExpression
269 || u
"COALESCE( \"%1\", '<NULL>' )"_s.arg( fieldDisplayName ) == displayExpression
270 || u
"\"%1\""_s.arg( fieldDisplayName ) == displayExpression
271 || fieldName == displayExpression
272 || u
"COALESCE( \"%1\", '<NULL>' )"_s.arg( fieldName ) == displayExpression
273 || u
"\"%1\""_s.arg( fieldName ) == displayExpression )
275 defaultFieldAction = previewAction;
280 QMenu *sortMenu =
new QMenu(
this );
282 sortMenuAction->setMenu( sortMenu );
284 QAction *sortByPreviewExpressionAsc =
new QAction(
QgsApplication::getThemeIcon( u
"sort.svg"_s ), tr(
"By Display Name (Ascending)" ),
this );
285 connect( sortByPreviewExpressionAsc, &QAction::triggered,
this, [
this]() { mFeatureListModel->setSortByDisplayExpression(
true, Qt::AscendingOrder ); } );
286 sortMenu->addAction( sortByPreviewExpressionAsc );
287 QAction *sortByPreviewExpressionDesc =
new QAction(
QgsApplication::getThemeIcon( u
"sort-reverse.svg"_s ), tr(
"By Display Name (Descending)" ),
this );
288 connect( sortByPreviewExpressionDesc, &QAction::triggered,
this, [
this]() { mFeatureListModel->setSortByDisplayExpression(
true, Qt::DescendingOrder ); } );
289 sortMenu->addAction( sortByPreviewExpressionDesc );
290 QAction *sortByPreviewExpressionCustom =
new QAction(
QgsApplication::getThemeIcon( u
"mIconExpressionPreview.svg"_s ), tr(
"By Custom Expression" ),
this );
291 connect( sortByPreviewExpressionCustom, &QAction::triggered,
this, [
this]() {
293 mFeatureListModel->setSortByDisplayExpression(
false );
295 sortMenu->addAction( sortByPreviewExpressionCustom );
297 mFeatureListPreviewButton->addAction( sortMenuAction );
299 QAction *separator =
new QAction( mFeatureListPreviewButton );
300 separator->setSeparator(
true );
301 mFeatureListPreviewButton->addAction( separator );
302 restoreRecentDisplayExpressions();
304 if ( defaultFieldAction )
306 mFeatureListPreviewButton->setDefaultAction( defaultFieldAction );
307 mFeatureListPreviewButton->defaultAction()->trigger();
311 mActionExpressionPreview->setToolTip( displayExpression );
312 mFeatureListPreviewButton->setDefaultAction( mActionExpressionPreview );
314 mFeatureListView->setDisplayExpression( displayExpression );
315 setDisplayExpression( displayExpression.isEmpty() ? tr(
"'[Please define preview text]'" ) : displayExpression );
321 setCurrentIndex(
view );
332 switch ( mFilterModel->filterMode() )
356 mMasterModel->setShowValidityState(
false );
366 const bool requiresTableReload = ( request.
filterType() != Qgis::Qgis::FeatureRequestFilterType::NoFilter
369 || ( mMasterModel->rowCount() == 0 );
381 if ( mFilterModel->mapCanvas() )
383 const QgsRectangle rect = mFilterModel->mapCanvas()->mapSettings().mapToLayerCoordinates( mLayer, mFilterModel->mapCanvas()->extent() );
398 mMasterModel->setShowValidityState(
true );
410 if ( !filterExpression.isEmpty() )
427 setBrowsingAutoPanScaleAllowed(
false );
435 setBrowsingAutoPanScaleAllowed(
true );
439 if ( requiresTableReload )
442 mFilterModel->disconnectFilterModeConnections();
444 mMasterModel->setRequest( request );
445 whileBlocking( mLayerCache )->setCacheGeometry( needsGeometry );
446 mMasterModel->loadLayer();
456 mFilterModel->setSelectedOnTop( selectedOnTop );
459void QgsDualView::initLayerCache(
bool cacheGeometry )
463 const int cacheSize = settings.
value( u
"qgis/attributeTableRowCache"_s,
"10000" ).toInt();
470 rebuildFullLayerCache();
476 delete mFeatureListModel;
480 mMasterModel =
new QgsAttributeTableModel( mLayerCache,
this );
481 mMasterModel->setRequest( request );
482 mMasterModel->setEditorContext( mEditorContext );
483 mMasterModel->setExtraColumns( 1 );
491 mMasterModel->loadLayer();
493 mFilterModel =
new QgsAttributeTableFilterModel( mapCanvas, mMasterModel, mMasterModel );
497 connect( mMasterModel, &QgsAttributeTableModel::rowsRemoved, mFilterModel, &QgsAttributeTableFilterModel::invalidate );
498 connect( mMasterModel, &QgsAttributeTableModel::rowsInserted, mFilterModel, &QgsAttributeTableFilterModel::invalidate );
502 mFeatureListModel =
new QgsFeatureListModel( mFilterModel, mFilterModel );
505void QgsDualView::restoreRecentDisplayExpressions()
507 const QVariantList previewExpressions = mLayer->customProperty( u
"dualview/previewExpressions"_s ).toList();
509 for (
const QVariant &previewExpression : previewExpressions )
511 insertRecentlyUsedDisplayExpression( previewExpression.toString() );
515void QgsDualView::saveRecentDisplayExpressions()
const
521 const QList<QAction *> actions = mFeatureListPreviewButton->actions();
524 int index = actions.indexOf( mLastDisplayExpressionAction );
527 QVariantList previewExpressions;
528 for ( ; index < actions.length(); ++index )
530 QAction *action = actions.at( index );
531 previewExpressions << action->property(
"previewExpression" );
534 mLayer->setCustomProperty( u
"dualview/previewExpressions"_s, previewExpressions );
538void QgsDualView::setDisplayExpression(
const QString &expression )
540 mDisplayExpression = expression;
541 insertRecentlyUsedDisplayExpression( expression );
544void QgsDualView::insertRecentlyUsedDisplayExpression(
const QString &expression )
546 const QList<QAction *> actions = mFeatureListPreviewButton->actions();
549 const int index = actions.indexOf( mLastDisplayExpressionAction );
552 for (
int i = 0; index + i < actions.length(); ++i )
554 QAction *action = actions.at( index );
555 if ( action->text() == expression || i >= 9 )
557 if ( action == mLastDisplayExpressionAction )
559 mLastDisplayExpressionAction =
nullptr;
561 mFeatureListPreviewButton->removeAction( action );
565 if ( !mLastDisplayExpressionAction )
567 mLastDisplayExpressionAction = action;
573 QString name = expression;
575 if ( expression.startsWith(
"COALESCE( \""_L1 ) && expression.endsWith(
", '<NULL>' )"_L1 ) )
577 name = expression.mid( 11, expression.length() - 24 );
579 const int fieldIndex = mLayer->fields().indexOf( name );
580 if ( fieldIndex != -1 )
582 name = mLayer->attributeDisplayName( fieldIndex );
583 icon = mLayer->fields().iconForField( fieldIndex );
591 QAction *previewAction =
new QAction( icon, name, mFeatureListPreviewButton );
592 previewAction->setProperty(
"previewExpression", expression );
593 connect( previewAction, &QAction::triggered,
this, [expression,
this](
bool ) {
594 setDisplayExpression( expression );
595 mFeatureListPreviewButton->setText( tr(
"Expression" ) );
596 mFeatureListPreviewButton->setToolTip( expression );
599 mFeatureListPreviewButton->insertAction( mLastDisplayExpressionAction, previewAction );
600 mLastDisplayExpressionAction = previewAction;
603void QgsDualView::updateEditSelectionProgress(
int progress,
int count )
605 mProgressCount->setText( u
"%1 / %2"_s.arg( progress + 1 ).arg( count ) );
606 mPreviousFeatureButton->setEnabled( progress > 0 );
607 mNextFeatureButton->setEnabled( progress + 1 < count );
608 mFirstFeatureButton->setEnabled( progress > 0 );
609 mLastFeatureButton->setEnabled( progress + 1 < count );
610 if ( mAttributeForm )
612 mAttributeForm->setVisible( count > 0 );
616void QgsDualView::panOrZoomToFeature(
const QgsFeatureIds &featureset )
618 QgsMapCanvas *canvas = mFilterModel->mapCanvas();
621 if ( mBrowsingAutoPanScaleAllowed )
623 if ( mAutoPanButton->isChecked() )
624 QTimer::singleShot( 0,
this, [
this, featureset, canvas]() { canvas->
panToFeatureIds( mLayer, featureset,
false ); } );
625 else if ( mAutoZoomButton->isChecked() )
626 QTimer::singleShot( 0,
this, [
this, featureset, canvas]() { canvas->
zoomToFeatureIds( mLayer, featureset ); } );
628 if ( mFlashButton->isChecked() )
629 QTimer::singleShot( 0,
this, [
this, featureset, canvas]() { canvas->
flashFeatureIds( mLayer, featureset ); } );
630 mLastFeatureSet = featureset;
634void QgsDualView::setBrowsingAutoPanScaleAllowed(
bool allowed )
636 if ( mBrowsingAutoPanScaleAllowed == allowed )
639 mBrowsingAutoPanScaleAllowed = allowed;
641 mAutoPanButton->setEnabled( allowed );
642 mAutoZoomButton->setEnabled( allowed );
644 const QString disabledHint = tr(
"(disabled when attribute table only shows features visible in the current map canvas extent)" );
646 mAutoPanButton->setToolTip( tr(
"Automatically pan to the current feature" ) + ( allowed ? QString() : QString(
' ' ) + disabledHint ) );
647 mAutoZoomButton->setToolTip( tr(
"Automatically zoom to the current feature" ) + ( allowed ? QString() : QString(
' ' ) + disabledHint ) );
650void QgsDualView::panZoomGroupButtonToggled( QAbstractButton *button,
bool checked )
652 if ( button == mAutoPanButton && checked )
654 QgsSettings().setEnumValue( u
"/qgis/attributeTable/featureListBrowsingAction"_s,
PanToFeature );
655 mAutoZoomButton->setChecked(
false );
657 else if ( button == mAutoZoomButton && checked )
659 QgsSettings().setEnumValue( u
"/qgis/attributeTable/featureListBrowsingAction"_s,
ZoomToFeature );
660 mAutoPanButton->setChecked(
false );
664 QgsSettings().setEnumValue( u
"/qgis/attributeTable/featureListBrowsingAction"_s,
NoAction );
667 if ( checked && mLayer->isSpatial() )
668 panOrZoomToFeature( mFeatureListView->currentEditSelection() );
671void QgsDualView::flashButtonClicked(
bool clicked )
677 QgsMapCanvas *canvas = mFilterModel->mapCanvas();
680 canvas->
flashFeatureIds( mLayer, mFeatureListView->currentEditSelection() );
683void QgsDualView::filterError(
const QString &errorMessage )
685 if ( mEditorContext.mainMessageBar() )
687 mEditorContext.mainMessageBar()->pushWarning( tr(
"An error occurred while filtering features" ), errorMessage );
691void QgsDualView::featureListAboutToChangeEditSelection(
bool &ok )
693 if ( !mAttributeForm )
696 if ( mLayer->isEditable() && !mAttributeForm->save() )
700void QgsDualView::featureListCurrentEditSelectionChanged(
const QgsFeature &feat )
702 if ( !mAttributeForm )
704 initAttributeForm( feat );
706 else if ( !mLayer->isEditable() || mAttributeForm->save() )
708 mAttributeForm->setFeature( feat );
710 featureset << feat.
id();
713 if ( mLayer->isSpatial() )
714 panOrZoomToFeature( featureset );
724 mFeatureListView->setCurrentFeatureEdited(
false );
725 mFeatureListView->setEditSelection( fids );
730 return mAttributeForm ? mAttributeForm->save() :
false;
735 mConditionalFormatWidgetStack->setVisible( !mConditionalFormatWidgetStack->isVisible() );
740 if ( !mAttributeForm )
745 mPreviousView =
view();
758 if ( !mAttributeForm )
765 mAttributeForm->setVisible(
true );
770 mAttributeForm->setVisible( mFilterModel->rowCount() > 0 );
774void QgsDualView::previewExpressionBuilder()
780 dlg.setWindowTitle( tr(
"Expression Based Preview" ) );
781 dlg.setExpressionText( mFeatureListView->displayExpression() );
783 if ( dlg.exec() == QDialog::Accepted )
785 mFeatureListView->setDisplayExpression( dlg.expressionText() );
786 mActionExpressionPreview->setToolTip( dlg.expressionText() );
788 mFeatureListPreviewButton->setDefaultAction( mActionExpressionPreview );
789 mFeatureListPreviewButton->setPopupMode( QToolButton::MenuButtonPopup );
792 setDisplayExpression( mFeatureListView->displayExpression() );
795void QgsDualView::previewColumnChanged( QAction *previewAction,
const QString &expression )
797 if ( !mFeatureListView->setDisplayExpression( u
"COALESCE( \"%1\", '<NULL>' )"_s.arg( expression ) ) )
799 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() ) );
803 mFeatureListPreviewButton->setText( previewAction->text() );
804 mFeatureListPreviewButton->setIcon( previewAction->icon() );
805 mFeatureListPreviewButton->setPopupMode( QToolButton::InstantPopup );
808 setDisplayExpression( mFeatureListView->displayExpression() );
813 return mMasterModel->rowCount();
818 return mFilterModel->rowCount();
823 const QModelIndex currentIndex = mTableView->currentIndex();
824 if ( !currentIndex.isValid() )
829 const QVariant var = mMasterModel->data( currentIndex, Qt::DisplayRole );
830 QApplication::clipboard()->setText( var.toString() );
836 mProgressDlg->cancel();
841 if ( mAttributeForm )
843 mAttributeForm->parentFormValueChanged( attribute, newValue );
850 saveRecentDisplayExpressions();
857 conditionalFormattingSplitterState->setValue( mConditionalSplitter->saveState() );
858 attributeEditorSplitterState->setValue( mAttributeEditorViewSplitter->saveState() );
861void QgsDualView::viewWillShowContextMenu( QMenu *menu,
const QModelIndex &masterIndex )
868 const QVariant displayValue = mMasterModel->data( masterIndex, Qt::DisplayRole );
870 if ( displayValue.isValid() )
873 QString previewDisplayValue = displayValue.toString();
874 if ( previewDisplayValue.length() > 12 )
876 previewDisplayValue.truncate( 12 );
877 previewDisplayValue.append( u
"…"_s );
881 QAction *copyContentAction = menu->addAction( tr(
"Copy Cell Content (%1)" ).arg( previewDisplayValue ) );
882 menu->addAction( copyContentAction );
883 connect( copyContentAction, &QAction::triggered,
this, [displayValue] { QApplication::clipboard()->setText( displayValue.toString() ); } );
886 const QVariant rawValue = mMasterModel->data( masterIndex, Qt::EditRole );
887 if ( rawValue.isValid() )
890 QString previewRawValue = rawValue.toString();
891 if ( previewRawValue.length() > 12 )
893 previewRawValue.truncate( 12 );
894 previewRawValue.append( u
"…"_s );
897 QAction *copyRawContentAction = menu->addAction( tr(
"Copy Raw Value (%1)" ).arg( previewRawValue ) );
898 menu->addAction( copyRawContentAction );
899 connect( copyRawContentAction, &QAction::triggered,
this, [rawValue] { QApplication::clipboard()->setText( rawValue.toString() ); } );
902 QgsVectorLayer *vl = mFilterModel->layer();
903 QgsMapCanvas *canvas = mFilterModel->mapCanvas();
906 QAction *zoomToFeatureAction = menu->addAction( tr(
"Zoom to Feature" ) );
907 connect( zoomToFeatureAction, &QAction::triggered,
this, &QgsDualView::zoomToCurrentFeature );
909 QAction *panToFeatureAction = menu->addAction( tr(
"Pan to Feature" ) );
910 connect( panToFeatureAction, &QAction::triggered,
this, &QgsDualView::panToCurrentFeature );
912 QAction *flashFeatureAction = menu->addAction( tr(
"Flash Feature" ) );
913 connect( flashFeatureAction, &QAction::triggered,
this, &QgsDualView::flashCurrentFeature );
917 const QList<QgsAction> actions = mLayer->actions()->actions( u
"Field"_s );
918 if ( !actions.isEmpty() )
920 QAction *a = menu->addAction( tr(
"Run Layer Action" ) );
921 a->setEnabled(
false );
923 for (
const QgsAction &action : actions )
925 if ( !action.runable() )
928 if ( vl && !vl->
isEditable() && action.isEnabledOnlyWhenEditable() )
931 QgsAttributeTableAction *a =
new QgsAttributeTableAction( action.name(),
this, action.id(), masterIndex );
935 const QModelIndex rowSourceIndex = mMasterModel->index( masterIndex.row(), 0 );
936 if ( !rowSourceIndex.isValid() )
942 QgsMapLayerActionContext context;
944 if ( !registeredActions.isEmpty() )
947 menu->addSeparator();
949 for ( QgsMapLayerAction *action : registeredActions )
951 QgsAttributeTableMapLayerAction *a =
new QgsAttributeTableMapLayerAction( action->text(),
this, action, rowSourceIndex );
958 const QgsFeatureId currentFid = mMasterModel->rowToId( masterIndex.row() );
959 if ( mLayer->selectedFeatureCount() > 1 && mLayer->selectedFeatureIds().contains( currentFid ) )
962 if ( !registeredActions.isEmpty() )
964 menu->addSeparator();
965 QAction *action = menu->addAction( tr(
"Actions on Selection (%1)" ).arg( mLayer->selectedFeatureCount() ) );
966 action->setEnabled(
false );
968 QgsMapLayerActionContext context;
969 for ( QgsMapLayerAction *action : registeredActions )
971 menu->addAction( action->text(), action, [
this, action, context]() {
972 Q_NOWARN_DEPRECATED_PUSH
973 action->triggerForFeatures( mLayer, mLayer->selectedFeatures() );
974 Q_NOWARN_DEPRECATED_POP
975 action->triggerForFeatures( mLayer, mLayer->selectedFeatures(), context );
981 menu->addSeparator();
982 QgsAttributeTableAction *a =
new QgsAttributeTableAction( tr(
"Open Form" ),
this, QUuid(), rowSourceIndex );
987void QgsDualView::widgetWillShowContextMenu(
QgsActionMenu *menu,
const QModelIndex &atIndex )
993void QgsDualView::showViewHeaderMenu( QPoint point )
995 const int col = mTableView->columnAt( point.x() );
997 delete mHorizontalHeaderMenu;
998 mHorizontalHeaderMenu =
new QMenu(
this );
1000 QAction *hide =
new QAction( tr(
"&Hide Column" ), mHorizontalHeaderMenu );
1001 connect( hide, &QAction::triggered,
this, &QgsDualView::hideColumn );
1002 hide->setData( col );
1003 mHorizontalHeaderMenu->addAction( hide );
1004 QAction *setWidth =
new QAction( tr(
"&Set Width…" ), mHorizontalHeaderMenu );
1005 connect( setWidth, &QAction::triggered,
this, &QgsDualView::resizeColumn );
1006 setWidth->setData( col );
1007 mHorizontalHeaderMenu->addAction( setWidth );
1009 QAction *setWidthAllColumns =
new QAction( tr(
"&Set All Column Widths…" ), mHorizontalHeaderMenu );
1010 connect( setWidthAllColumns, &QAction::triggered,
this, &QgsDualView::resizeAllColumns );
1011 setWidthAllColumns->setData( col );
1012 mHorizontalHeaderMenu->addAction( setWidthAllColumns );
1014 QAction *optimizeWidth =
new QAction( tr(
"&Autosize" ), mHorizontalHeaderMenu );
1015 connect( optimizeWidth, &QAction::triggered,
this, &QgsDualView::autosizeColumn );
1016 optimizeWidth->setData( col );
1017 mHorizontalHeaderMenu->addAction( optimizeWidth );
1019 QAction *optimizeWidthAllColumns =
new QAction( tr(
"&Autosize All Columns" ), mHorizontalHeaderMenu );
1020 connect( optimizeWidthAllColumns, &QAction::triggered,
this, &QgsDualView::autosizeAllColumns );
1021 mHorizontalHeaderMenu->addAction( optimizeWidthAllColumns );
1024 mHorizontalHeaderMenu->addSeparator();
1025 QAction *organize =
new QAction( tr(
"&Organize Columns…" ), mHorizontalHeaderMenu );
1026 connect( organize, &QAction::triggered,
this, &QgsDualView::organizeColumns );
1027 mHorizontalHeaderMenu->addAction( organize );
1028 QAction *sort =
new QAction( tr(
"&Sort…" ), mHorizontalHeaderMenu );
1029 connect( sort, &QAction::triggered,
this, [
this]() { modifySort(); } );
1030 mHorizontalHeaderMenu->addAction( sort );
1032 mConfig.update( mLayer->fields() );
1034 int fieldIndex = -1;
1036 fieldIndex = mLayer->fields().indexFromName( mConfig.columns().at( mConfig.mapVisibleColumnToIndex( col ) ).name );
1037 const Qgis::FieldOrigin fieldOrigin = mLayer->fields().fieldOrigin( fieldIndex );
1039 mHorizontalHeaderMenu->addSeparator();
1041 const QgsVectorLayer *vl = mFilterModel->layer();
1042 const QgsVectorDataProvider *dataProvider = vl->
dataProvider();
1044 const bool layerIsReadOnly { vl->
readOnly() };
1047 bool fieldCalculatorEnabled =
false;
1049 switch ( fieldOrigin )
1053 fieldCalculatorEnabled = canChangeAttributeValue;
1058 const QgsVectorLayerJoinInfo *info = mLayer->joinBuffer()->joinForFieldIndex( fieldIndex, mLayer->fields(), srcFieldIndex );
1059 const QgsVectorLayer *joinedLayer = info->
joinLayer();
1060 const QgsVectorDataProvider *joinedDataProvider = joinedLayer->
dataProvider();
1062 const bool joinedLayerIsReadOnly { joinedLayer->
readOnly() };
1065 fieldCalculatorEnabled = joinedLayerCanChangeAttributeValue;
1075 QAction *fieldCalculator =
new QAction( tr(
"Open &Field Calculator…" ), mHorizontalHeaderMenu );
1076 connect( fieldCalculator, &QAction::triggered,
this, &QgsDualView::fieldCalculator );
1077 fieldCalculator->setData( fieldIndex );
1078 mHorizontalHeaderMenu->addAction( fieldCalculator );
1080 fieldCalculator->setEnabled( fieldCalculatorEnabled );
1082 mHorizontalHeaderMenu->popup( mTableView->horizontalHeader()->mapToGlobal( point ) );
1085void QgsDualView::organizeColumns()
1093 if ( dialog.exec() == QDialog::Accepted )
1095 const QgsAttributeTableConfig config = dialog.config();
1100void QgsDualView::tableColumnResized(
int column,
int width )
1102 QgsAttributeTableConfig config = mConfig;
1104 if ( sourceCol >= 0 && config.
columnWidth( sourceCol ) != width )
1111void QgsDualView::hideColumn()
1113 QAction *action = qobject_cast<QAction *>( sender() );
1114 const int col = action->data().toInt();
1115 QgsAttributeTableConfig config = mConfig;
1117 if ( sourceCol >= 0 )
1124void QgsDualView::fieldCalculator()
1126 QAction *action = qobject_cast<QAction *>( sender() );
1127 const int fieldIndex = action->data().toInt();
1128 mConfig.update( mLayer->fields() );
1129 QgsFieldCalculator calc( mLayer,
this, fieldIndex );
1130 if ( calc.exec() == QDialog::Accepted )
1132 int col = mMasterModel->fieldCol( calc.changedAttributeId() );
1135 mMasterModel->reload( mMasterModel->index( 0, col ), mMasterModel->index( mMasterModel->rowCount() - 1, col ) );
1139void QgsDualView::resizeColumn()
1141 QAction *action = qobject_cast<QAction *>( sender() );
1142 const int col = action->data().toInt();
1146 QgsAttributeTableConfig config = mConfig;
1148 if ( sourceCol >= 0 )
1151 const int width = QInputDialog::getInt(
this, tr(
"Set column width" ), tr(
"Enter column width" ), mTableView->columnWidth( col ), 0, 1000, 10, &ok );
1160void QgsDualView::resizeAllColumns()
1162 QAction *action = qobject_cast<QAction *>( sender() );
1163 const int col = action->data().toInt();
1167 QgsAttributeTableConfig config = mConfig;
1170 const int width = QInputDialog::getInt(
this, tr(
"Set Column Width" ), tr(
"Enter column width" ), mTableView->columnWidth( col ), 1, 1000, 10, &ok );
1173 const int colCount = mTableView->model()->columnCount();
1176 for (
int i = 0; i < colCount; i++ )
1185void QgsDualView::autosizeColumn()
1187 QAction *action = qobject_cast<QAction *>( sender() );
1188 const int col = action->data().toInt();
1189 mTableView->resizeColumnToContents( col );
1192void QgsDualView::autosizeAllColumns()
1194 mTableView->resizeColumnsToContents();
1197bool QgsDualView::modifySort()
1202 QgsAttributeTableConfig config = mConfig;
1205 orderByDlg.setWindowTitle( tr(
"Configure Attribute Table Sort Order" ) );
1206 QDialogButtonBox *dialogButtonBox =
new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
1207 QGridLayout *layout =
new QGridLayout();
1208 connect( dialogButtonBox, &QDialogButtonBox::accepted, &orderByDlg, &QDialog::accept );
1209 connect( dialogButtonBox, &QDialogButtonBox::rejected, &orderByDlg, &QDialog::reject );
1210 orderByDlg.setLayout( layout );
1212 QGroupBox *sortingGroupBox =
new QGroupBox();
1213 sortingGroupBox->setTitle( tr(
"Defined sort order in attribute table" ) );
1214 sortingGroupBox->setCheckable(
true );
1216 layout->addWidget( sortingGroupBox );
1217 sortingGroupBox->setLayout(
new QGridLayout() );
1219 QgsExpressionBuilderWidget *expressionBuilder =
new QgsExpressionBuilderWidget();
1222 expressionBuilder->
initWithLayer( mLayer, context, u
"generic"_s );
1225 sortingGroupBox->layout()->addWidget( expressionBuilder );
1227 QCheckBox *cbxSortAscending =
new QCheckBox( tr(
"Sort ascending" ) );
1228 cbxSortAscending->setChecked( config.
sortOrder() == Qt::AscendingOrder );
1229 sortingGroupBox->layout()->addWidget( cbxSortAscending );
1231 layout->addWidget( dialogButtonBox );
1232 if ( orderByDlg.exec() )
1234 const Qt::SortOrder sortOrder = cbxSortAscending->isChecked() ? Qt::AscendingOrder : Qt::DescendingOrder;
1235 if ( sortingGroupBox->isChecked() )
1257 QSet<int> attributes;
1261 const QVector<QgsAttributeTableConfig::ColumnConfig> constColumnconfigs { config.
columns() };
1270 const QSet<int> colAttrs { attributes };
1271 for (
const int attrIdx : std::as_const( colAttrs ) )
1280 std::sort( attrs.begin(), attrs.end() );
1284void QgsDualView::zoomToCurrentFeature()
1286 const QModelIndex currentIndex = mTableView->currentIndex();
1287 if ( !currentIndex.isValid() )
1293 ids.insert( mFilterModel->rowToId( currentIndex ) );
1294 QgsMapCanvas *canvas = mFilterModel->mapCanvas();
1301void QgsDualView::panToCurrentFeature()
1303 const QModelIndex currentIndex = mTableView->currentIndex();
1304 if ( !currentIndex.isValid() )
1310 ids.insert( mFilterModel->rowToId( currentIndex ) );
1311 QgsMapCanvas *canvas = mFilterModel->mapCanvas();
1318void QgsDualView::flashCurrentFeature()
1320 const QModelIndex currentIndex = mTableView->currentIndex();
1321 if ( !currentIndex.isValid() )
1327 ids.insert( mFilterModel->rowToId( currentIndex ) );
1328 QgsMapCanvas *canvas = mFilterModel->mapCanvas();
1335void QgsDualView::rebuildFullLayerCache()
1340 mLayerCache->setFullCache(
true );
1343void QgsDualView::previewExpressionChanged(
const QString &expression )
1345 mLayer->setDisplayExpression( expression );
1348void QgsDualView::onSortColumnChanged()
1359void QgsDualView::updateSelectedFeatures()
1361 QgsFeatureRequest r = mMasterModel->request();
1366 mMasterModel->setRequest( r );
1367 mMasterModel->loadLayer();
1371void QgsDualView::updateEditedAddedFeatures()
1373 QgsFeatureRequest r = mMasterModel->request();
1378 mMasterModel->setRequest( r );
1379 mMasterModel->loadLayer();
1383void QgsDualView::extentChanged()
1385 QgsFeatureRequest r = mMasterModel->request();
1388 const QgsRectangle rect = mFilterModel->mapCanvas()->mapSettings().mapToLayerCoordinates( mLayer, mFilterModel->mapCanvas()->extent() );
1390 mMasterModel->setRequest( r );
1391 mMasterModel->loadLayer();
1396void QgsDualView::featureFormAttributeChanged(
const QString &attribute,
const QVariant &value,
bool attributeChanged )
1398 Q_UNUSED( attribute )
1400 if ( attributeChanged )
1402 mFeatureListView->setCurrentFeatureEdited(
true );
1403 mAttributeForm->save();
1414 mFilterModel->setFilterExpression( filterExpression, context );
1415 mFilterModel->filterFeatures();
1421 mMasterModel->setRequest( request );
1426 mTableView->setFeatureSelectionManager( featureSelectionManager );
1427 mFeatureListView->setFeatureSelectionManager( featureSelectionManager );
1429 if ( mFeatureSelectionManager && mFeatureSelectionManager->parent() ==
this )
1430 delete mFeatureSelectionManager;
1432 mFeatureSelectionManager = featureSelectionManager;
1438 mConfig.
update( mLayer->fields() );
1439 mLayer->setAttributeTableConfig( mConfig );
1440 mFilterModel->setAttributeTableConfig( mConfig );
1441 mTableView->setAttributeTableConfig( mConfig );
1447 mLayerCache->setCacheGeometry(
true );
1451 mMasterModel->setRequest( request );
1452 mLayerCache->setCacheSubsetOfAttributes( attributes );
1458 mFilterModel->sort( -1 );
1463 mConfig.setSortOrder( sortOrder );
1469 return mFilterModel->sortExpression();
1477void QgsDualView::progress(
int i,
bool &cancel )
1479 if ( !mProgressDlg )
1481 mProgressDlg =
new QProgressDialog( tr(
"Loading features…" ), tr(
"Abort" ), 0, 0,
this );
1482 mProgressDlg->setWindowTitle( tr(
"Attribute Table" ) );
1483 mProgressDlg->setWindowModality( Qt::WindowModal );
1484 mProgressDlg->show();
1487 mProgressDlg->setLabelText( tr(
"%L1 features loaded." ).arg( i ) );
1488 QCoreApplication::processEvents();
1490 cancel = mProgressDlg && mProgressDlg->wasCanceled();
1493void QgsDualView::finished()
1495 delete mProgressDlg;
1496 mProgressDlg =
nullptr;
1505 mDualView->masterModel()->executeAction( mAction, mFieldIdx );
1511 editedIds << mDualView->masterModel()->rowToId( mFieldIdx.row() );
1512 mDualView->setCurrentEditSelection( editedIds );
1523 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
Settings entry for whether features are highlighted/flashed in the feature list.
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.
A boolean settings entry.
A variant settings entry.
static QgsSettingsTreeNode * sTreeAttributeTable
static QgsSettingsTreeNode * sTreeWindowState
Stores settings for use within QGIS.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
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.