20#include <QProgressDialog>
22#include <QInputDialog>
52 : QStackedWidget( parent )
61 mTableView->horizontalHeader()->setContextMenuPolicy( Qt::CustomContextMenu );
62 connect( mTableView->horizontalHeader(), &QHeaderView::customContextMenuRequested,
this, &QgsDualView::showViewHeaderMenu );
65 mConditionalFormatWidgetStack->hide();
67 mConditionalFormatWidgetStack->setMainPanel( mConditionalFormatWidget );
71 mConditionalSplitter->restoreState( settings.
value( QStringLiteral(
"/qgis/attributeTable/splitterState" ), QByteArray() ).toByteArray() );
73 mPreviewColumnsMenu =
new QMenu(
this );
74 mActionPreviewColumnsMenu->setMenu( mPreviewColumnsMenu );
80 connect( mActionExpressionPreview, &QAction::triggered,
this, &QgsDualView::previewExpressionBuilder );
89 auto createShortcuts = [ = ](
const QString & objectName, void (
QgsFeatureListView::* slot )() )
95 connect( sc, &QShortcut::activated, mFeatureListView, slot );
102 QButtonGroup *buttonGroup =
new QButtonGroup(
this );
103 buttonGroup->setExclusive(
false );
107 QAbstractButton *bt = buttonGroup->button(
static_cast<int>( action ) );
109 bt->setChecked(
true );
110 connect( buttonGroup, qOverload< QAbstractButton *, bool >( &QButtonGroup::buttonToggled ),
this, &QgsDualView::panZoomGroupButtonToggled );
111 mFlashButton->setChecked(
QgsSettings().value( QStringLiteral(
"/qgis/attributeTable/featureListHighlightFeature" ),
true ).toBool() );
112 connect( mFlashButton, &QToolButton::clicked,
this, &QgsDualView::flashButtonClicked );
118 settings.
setValue( QStringLiteral(
"/qgis/attributeTable/splitterState" ), mConditionalSplitter->saveState() );
127 delete mAttributeForm;
128 mAttributeForm =
nullptr;
138 mEditorContext = context;
143 const bool needsGeometry = mLayer->conditionalStyles()->rulesNeedGeometry() ||
148 initLayerCache( needsGeometry );
149 initModels( mapCanvas, request, loadFeatures );
151 mConditionalFormatWidget->
setLayer( mLayer );
153 mTableView->setModel( mFilterModel );
154 mFeatureListView->setModel( mFeatureListModel );
158 if ( mFeatureListPreviewButton->defaultAction() )
159 mFeatureListView->setDisplayExpression( mDisplayExpression );
166 if ( showFirstFeature && mFeatureListModel->
rowCount( ) > 0 )
170void QgsDualView::initAttributeForm(
const QgsFeature &feature )
172 Q_ASSERT( !mAttributeForm );
178 mAttributeEditorScrollArea->setWidgetResizable(
true );
179 mAttributeEditor->layout()->addWidget( mAttributeEditorScrollArea );
180 mAttributeEditorScrollArea->setWidget( mAttributeForm );
184 mAttributeEditor->layout()->addWidget( mAttributeForm );
189 mAttributeForm->setMinimumWidth( 200 );
200 QgsMapCanvasUtils::flashMatchingFeatures( canvas, mLayer, filter );
207 QgsMapCanvasUtils::zoomToMatchingFeatures( canvas, mLayer, filter );
214void QgsDualView::columnBoxInit()
217 const QList<QgsField> fields = mLayer->fields().toList();
219 const QString defaultField;
221 mFeatureListPreviewButton->addAction( mActionExpressionPreview );
222 mFeatureListPreviewButton->addAction( mActionPreviewColumnsMenu );
224 const auto constFields = fields;
225 for (
const QgsField &field : constFields )
227 const int fieldIndex = mLayer->fields().lookupField( field.name() );
228 if ( fieldIndex == -1 )
231 const QString fieldName = field.name();
234 const QIcon icon = mLayer->fields().iconForField( fieldIndex );
235 const QString text = mLayer->attributeDisplayName( fieldIndex );
238 QAction *previewAction =
new QAction( icon, text, mFeatureListPreviewButton );
239 connect( previewAction, &QAction::triggered,
this, [ = ] { previewColumnChanged( previewAction, fieldName ); } );
240 mPreviewColumnsMenu->addAction( previewAction );
242 if ( text == defaultField )
244 mFeatureListPreviewButton->setDefaultAction( previewAction );
249 QMenu *sortMenu =
new QMenu(
this );
251 sortMenuAction->setMenu( sortMenu );
253 QAction *sortByPreviewExpressionAsc =
new QAction(
QgsApplication::getThemeIcon( QStringLiteral(
"sort.svg" ) ), tr(
"By Preview Expression (ascending)" ),
this );
254 connect( sortByPreviewExpressionAsc, &QAction::triggered,
this, [ = ]()
258 sortMenu->addAction( sortByPreviewExpressionAsc );
259 QAction *sortByPreviewExpressionDesc =
new QAction(
QgsApplication::getThemeIcon( QStringLiteral(
"sort-reverse.svg" ) ), tr(
"By Preview Expression (descending)" ),
this );
260 connect( sortByPreviewExpressionDesc, &QAction::triggered,
this, [ = ]()
264 sortMenu->addAction( sortByPreviewExpressionDesc );
265 QAction *sortByPreviewExpressionCustom =
new QAction(
QgsApplication::getThemeIcon( QStringLiteral(
"mIconExpressionPreview.svg" ) ), tr(
"By Custom Expression" ),
this );
266 connect( sortByPreviewExpressionCustom, &QAction::triggered,
this, [ = ]()
271 sortMenu->addAction( sortByPreviewExpressionCustom );
273 mFeatureListPreviewButton->addAction( sortMenuAction );
275 QAction *separator =
new QAction( mFeatureListPreviewButton );
276 separator->setSeparator(
true );
277 mFeatureListPreviewButton->addAction( separator );
278 restoreRecentDisplayExpressions();
281 if ( !mFeatureListPreviewButton->defaultAction() )
283 mFeatureListView->setDisplayExpression( mLayer->displayExpression() );
284 mFeatureListPreviewButton->setDefaultAction( mActionExpressionPreview );
285 const QString displayExpression = mFeatureListView->displayExpression();
286 setDisplayExpression( displayExpression.isEmpty() ? tr(
"'[Please define preview text]'" ) : displayExpression );
290 mFeatureListPreviewButton->defaultAction()->trigger();
296 setCurrentIndex(
view );
343 || ( mMasterModel->
rowCount() == 0 );
345 if ( !needsGeometry )
377 filterFeatures( QStringLiteral(
"is_feature_valid() = false" ), context );
387 if ( !filterExpression.isEmpty() )
404 setBrowsingAutoPanScaleAllowed(
false );
412 setBrowsingAutoPanScaleAllowed(
true );
416 if ( requiresTableReload )
422 whileBlocking( mLayerCache )->setCacheGeometry( needsGeometry );
436void QgsDualView::initLayerCache(
bool cacheGeometry )
440 const int cacheSize = settings.
value( QStringLiteral(
"qgis/attributeTableRowCache" ),
"10000" ).toInt();
447 rebuildFullLayerCache();
453 delete mFeatureListModel;
474 connect( mMasterModel, &QgsAttributeTableModel::rowsRemoved, mFilterModel, &QgsAttributeTableFilterModel::invalidate );
475 connect( mMasterModel, &QgsAttributeTableModel::rowsInserted, mFilterModel, &QgsAttributeTableFilterModel::invalidate );
482void QgsDualView::restoreRecentDisplayExpressions()
484 const QVariantList previewExpressions = mLayer->customProperty( QStringLiteral(
"dualview/previewExpressions" ) ).toList();
486 for (
const QVariant &previewExpression : previewExpressions )
487 insertRecentlyUsedDisplayExpression( previewExpression.toString() );
490void QgsDualView::saveRecentDisplayExpressions()
const
496 const QList<QAction *> actions = mFeatureListPreviewButton->actions();
499 int index = actions.indexOf( mLastDisplayExpressionAction );
502 QVariantList previewExpressions;
503 for ( ; index < actions.length(); ++index )
505 QAction *action = actions.at( index );
506 previewExpressions << action->property(
"previewExpression" );
509 mLayer->setCustomProperty( QStringLiteral(
"dualview/previewExpressions" ), previewExpressions );
513void QgsDualView::setDisplayExpression(
const QString &expression )
515 mDisplayExpression = expression;
516 insertRecentlyUsedDisplayExpression( expression );
519void QgsDualView::insertRecentlyUsedDisplayExpression(
const QString &expression )
521 const QList<QAction *> actions = mFeatureListPreviewButton->actions();
524 const int index = actions.indexOf( mLastDisplayExpressionAction );
527 for (
int i = 0; index + i < actions.length(); ++i )
529 QAction *action = actions.at( index );
530 if ( action->text() == expression || i >= 9 )
532 if ( action == mLastDisplayExpressionAction )
533 mLastDisplayExpressionAction =
nullptr;
534 mFeatureListPreviewButton->removeAction( action );
538 if ( !mLastDisplayExpressionAction )
539 mLastDisplayExpressionAction = action;
544 QString name = expression;
546 if ( expression.startsWith( QLatin1String(
"COALESCE( \"" ) ) && expression.endsWith( QLatin1String(
", '<NULL>' )" ) ) )
548 name = expression.mid( 11, expression.length() - 24 );
550 const int fieldIndex = mLayer->fields().indexOf( name );
551 if ( fieldIndex != -1 )
553 name = mLayer->attributeDisplayName( fieldIndex );
554 icon = mLayer->fields().iconForField( fieldIndex );
562 QAction *previewAction =
new QAction( icon, name, mFeatureListPreviewButton );
563 previewAction->setProperty(
"previewExpression", expression );
564 connect( previewAction, &QAction::triggered,
this, [expression,
this](
bool )
566 setDisplayExpression( expression );
567 mFeatureListPreviewButton->setText( expression );
571 mFeatureListPreviewButton->insertAction( mLastDisplayExpressionAction, previewAction );
572 mLastDisplayExpressionAction = previewAction;
575void QgsDualView::updateEditSelectionProgress(
int progress,
int count )
577 mProgressCount->setText( QStringLiteral(
"%1 / %2" ).arg( progress + 1 ).arg( count ) );
578 mPreviousFeatureButton->setEnabled( progress > 0 );
579 mNextFeatureButton->setEnabled( progress + 1 < count );
580 mFirstFeatureButton->setEnabled( progress > 0 );
581 mLastFeatureButton->setEnabled( progress + 1 < count );
582 if ( mAttributeForm )
584 mAttributeForm->setVisible( count > 0 );
588void QgsDualView::panOrZoomToFeature(
const QgsFeatureIds &featureset )
593 if ( mBrowsingAutoPanScaleAllowed )
595 if ( mAutoPanButton->isChecked() )
596 QTimer::singleShot( 0,
this, [ = ]()
600 else if ( mAutoZoomButton->isChecked() )
601 QTimer::singleShot( 0,
this, [ = ]()
606 if ( mFlashButton->isChecked() )
607 QTimer::singleShot( 0,
this, [ = ]()
611 mLastFeatureSet = featureset;
615void QgsDualView::setBrowsingAutoPanScaleAllowed(
bool allowed )
617 if ( mBrowsingAutoPanScaleAllowed == allowed )
620 mBrowsingAutoPanScaleAllowed = allowed;
622 mAutoPanButton->setEnabled( allowed );
623 mAutoZoomButton->setEnabled( allowed );
625 const QString disabledHint = tr(
"(disabled when attribute table only shows features visible in the current map canvas extent)" );
627 mAutoPanButton->setToolTip( tr(
"Automatically pan to the current feature" ) + ( allowed ? QString() : QString(
' ' ) + disabledHint ) );
628 mAutoZoomButton->setToolTip( tr(
"Automatically zoom to the current feature" ) + ( allowed ? QString() : QString(
' ' ) + disabledHint ) );
631void QgsDualView::panZoomGroupButtonToggled( QAbstractButton *button,
bool checked )
633 if ( button == mAutoPanButton && checked )
636 mAutoZoomButton->setChecked(
false );
638 else if ( button == mAutoZoomButton && checked )
641 mAutoPanButton->setChecked(
false );
648 if ( checked && mLayer->isSpatial() )
649 panOrZoomToFeature( mFeatureListView->currentEditSelection() );
652void QgsDualView::flashButtonClicked(
bool clicked )
654 QgsSettings().
setValue( QStringLiteral(
"/qgis/attributeTable/featureListHighlightFeature" ), clicked );
661 canvas->
flashFeatureIds( mLayer, mFeatureListView->currentEditSelection() );
664void QgsDualView::filterError(
const QString &errorMessage )
672void QgsDualView::featureListAboutToChangeEditSelection(
bool &ok )
674 if ( !mAttributeForm )
677 if ( mLayer->isEditable() && !mAttributeForm->
save() )
681void QgsDualView::featureListCurrentEditSelectionChanged(
const QgsFeature &feat )
683 if ( !mAttributeForm )
685 initAttributeForm( feat );
687 else if ( !mLayer->isEditable() || mAttributeForm->
save() )
691 featureset << feat.
id();
694 if ( mLayer->isSpatial() )
695 panOrZoomToFeature( featureset );
706 mFeatureListView->setCurrentFeatureEdited(
false );
707 mFeatureListView->setEditSelection( fids );
712 return mAttributeForm ? mAttributeForm->
save() :
false;
717 mConditionalFormatWidgetStack->setVisible( !mConditionalFormatWidgetStack->isVisible() );
722 if ( !mAttributeForm )
727 mPreviousView =
view();
740 if ( !mAttributeForm )
747 mAttributeForm->setVisible(
true );
752 mAttributeForm->setVisible( mFilterModel->rowCount( ) > 0 );
757void QgsDualView::previewExpressionBuilder()
763 dlg.setWindowTitle( tr(
"Expression Based Preview" ) );
764 dlg.setExpressionText( mFeatureListView->displayExpression() );
766 if ( dlg.exec() == QDialog::Accepted )
768 mFeatureListView->setDisplayExpression( dlg.expressionText() );
769 mFeatureListPreviewButton->setDefaultAction( mActionExpressionPreview );
770 mFeatureListPreviewButton->setPopupMode( QToolButton::MenuButtonPopup );
773 setDisplayExpression( mFeatureListView->displayExpression() );
776void QgsDualView::previewColumnChanged( QAction *previewAction,
const QString &expression )
778 if ( !mFeatureListView->setDisplayExpression( QStringLiteral(
"COALESCE( \"%1\", '<NULL>' )" ).arg( expression ) ) )
780 QMessageBox::warning(
this,
781 tr(
"Column Preview" ),
782 tr(
"Could not set column '%1' as preview column.\nParser error:\n%2" )
783 .arg( previewAction->text(), mFeatureListView->parserErrorString() )
788 mFeatureListPreviewButton->setText( previewAction->text() );
789 mFeatureListPreviewButton->setIcon( previewAction->icon() );
790 mFeatureListPreviewButton->setPopupMode( QToolButton::InstantPopup );
793 setDisplayExpression( mFeatureListView->displayExpression() );
803 return mFilterModel->rowCount();
808 const QModelIndex currentIndex = mTableView->currentIndex();
809 if ( !currentIndex.isValid() )
814 const QVariant var = mMasterModel->
data( currentIndex, Qt::DisplayRole );
815 QApplication::clipboard()->setText( var.toString() );
821 mProgressDlg->cancel();
826 if ( mAttributeForm )
835 saveRecentDisplayExpressions();
838void QgsDualView::viewWillShowContextMenu( QMenu *menu,
const QModelIndex &masterIndex )
845 QAction *copyContentAction = menu->addAction( tr(
"Copy Cell Content" ) );
846 menu->addAction( copyContentAction );
847 connect( copyContentAction, &QAction::triggered,
this, [masterIndex,
this]
849 const QVariant var = mMasterModel->
data( masterIndex, Qt::DisplayRole );
850 QApplication::clipboard()->setText( var.toString() );
855 if ( canvas && vl && vl->isSpatial() )
857 QAction *zoomToFeatureAction = menu->addAction( tr(
"Zoom to Feature" ) );
858 connect( zoomToFeatureAction, &QAction::triggered,
this, &QgsDualView::zoomToCurrentFeature );
860 QAction *panToFeatureAction = menu->addAction( tr(
"Pan to Feature" ) );
861 connect( panToFeatureAction, &QAction::triggered,
this, &QgsDualView::panToCurrentFeature );
863 QAction *flashFeatureAction = menu->addAction( tr(
"Flash Feature" ) );
864 connect( flashFeatureAction, &QAction::triggered,
this, &QgsDualView::flashCurrentFeature );
868 const QList<QgsAction> actions = mLayer->actions()->actions( QStringLiteral(
"Field" ) );
869 if ( !actions.isEmpty() )
871 QAction *a = menu->addAction( tr(
"Run Layer Action" ) );
872 a->setEnabled(
false );
874 for (
const QgsAction &action : actions )
876 if ( !action.runable() )
879 if ( vl && !vl->isEditable() && action.isEnabledOnlyWhenEditable() )
886 const QModelIndex rowSourceIndex = mMasterModel->index( masterIndex.row(), 0 );
887 if ( ! rowSourceIndex.isValid() )
895 if ( !registeredActions.isEmpty() )
898 menu->addSeparator();
910 if ( mLayer->selectedFeatureCount() > 1 && mLayer->selectedFeatureIds().contains( currentFid ) )
913 if ( !registeredActions.isEmpty() )
915 menu->addSeparator();
916 QAction *action = menu->addAction( tr(
"Actions on Selection (%1)" ).arg( mLayer->selectedFeatureCount() ) );
917 action->setEnabled(
false );
922 menu->addAction( action->text(), action, [ = ]()
924 Q_NOWARN_DEPRECATED_PUSH
925 action->triggerForFeatures( mLayer, mLayer->selectedFeatures() );
926 Q_NOWARN_DEPRECATED_POP
927 action->triggerForFeatures( mLayer, mLayer->selectedFeatures(), context );
933 menu->addSeparator();
939void QgsDualView::widgetWillShowContextMenu(
QgsActionMenu *menu,
const QModelIndex &atIndex )
945void QgsDualView::showViewHeaderMenu( QPoint point )
947 const int col = mTableView->columnAt( point.x() );
949 delete mHorizontalHeaderMenu;
950 mHorizontalHeaderMenu =
new QMenu(
this );
952 QAction *hide =
new QAction( tr(
"&Hide Column" ), mHorizontalHeaderMenu );
953 connect( hide, &QAction::triggered,
this, &QgsDualView::hideColumn );
954 hide->setData( col );
955 mHorizontalHeaderMenu->addAction( hide );
956 QAction *setWidth =
new QAction( tr(
"&Set Width…" ), mHorizontalHeaderMenu );
957 connect( setWidth, &QAction::triggered,
this, &QgsDualView::resizeColumn );
958 setWidth->setData( col );
959 mHorizontalHeaderMenu->addAction( setWidth );
961 QAction *setWidthAllColumns =
new QAction( tr(
"&Set All Column Widths…" ), mHorizontalHeaderMenu );
962 connect( setWidthAllColumns, &QAction::triggered,
this, &QgsDualView::resizeAllColumns );
963 setWidthAllColumns->setData( col );
964 mHorizontalHeaderMenu->addAction( setWidthAllColumns );
966 QAction *optimizeWidth =
new QAction( tr(
"&Autosize" ), mHorizontalHeaderMenu );
967 connect( optimizeWidth, &QAction::triggered,
this, &QgsDualView::autosizeColumn );
968 optimizeWidth->setData( col );
969 mHorizontalHeaderMenu->addAction( optimizeWidth );
971 QAction *optimizeWidthAllColumns =
new QAction( tr(
"&Autosize All Columns" ), mHorizontalHeaderMenu );
972 connect( optimizeWidthAllColumns, &QAction::triggered,
this, &QgsDualView::autosizeAllColumns );
973 mHorizontalHeaderMenu->addAction( optimizeWidthAllColumns );
976 mHorizontalHeaderMenu->addSeparator();
977 QAction *organize =
new QAction( tr(
"&Organize Columns…" ), mHorizontalHeaderMenu );
978 connect( organize, &QAction::triggered,
this, &QgsDualView::organizeColumns );
979 mHorizontalHeaderMenu->addAction( organize );
980 QAction *sort =
new QAction( tr(
"&Sort…" ), mHorizontalHeaderMenu );
981 connect( sort, &QAction::triggered,
this, [ = ]() {modifySort();} );
982 mHorizontalHeaderMenu->addAction( sort );
984 mHorizontalHeaderMenu->popup( mTableView->horizontalHeader()->mapToGlobal( point ) );
987void QgsDualView::organizeColumns()
995 if ( dialog.exec() == QDialog::Accepted )
1002void QgsDualView::tableColumnResized(
int column,
int width )
1006 if ( sourceCol >= 0 && config.
columnWidth( sourceCol ) != width )
1013void QgsDualView::hideColumn()
1015 QAction *action = qobject_cast<QAction *>( sender() );
1016 const int col = action->data().toInt();
1019 if ( sourceCol >= 0 )
1026void QgsDualView::resizeColumn()
1028 QAction *action = qobject_cast<QAction *>( sender() );
1029 const int col = action->data().toInt();
1035 if ( sourceCol >= 0 )
1038 const int width = QInputDialog::getInt(
this, tr(
"Set column width" ), tr(
"Enter column width" ),
1039 mTableView->columnWidth( col ),
1049void QgsDualView::resizeAllColumns()
1051 QAction *action = qobject_cast<QAction *>( sender() );
1052 const int col = action->data().toInt();
1059 const int width = QInputDialog::getInt(
this, tr(
"Set Column Width" ), tr(
"Enter column width" ),
1060 mTableView->columnWidth( col ),
1064 const int colCount = mTableView->model()->columnCount();
1067 for (
int i = 0; i < colCount; i++ )
1076void QgsDualView::autosizeColumn()
1078 QAction *action = qobject_cast<QAction *>( sender() );
1079 const int col = action->data().toInt();
1080 mTableView->resizeColumnToContents( col );
1083void QgsDualView::autosizeAllColumns()
1085 mTableView->resizeColumnsToContents();
1088bool QgsDualView::modifySort()
1096 orderByDlg.setWindowTitle( tr(
"Configure Attribute Table Sort Order" ) );
1097 QDialogButtonBox *dialogButtonBox =
new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
1098 QGridLayout *layout =
new QGridLayout();
1099 connect( dialogButtonBox, &QDialogButtonBox::accepted, &orderByDlg, &QDialog::accept );
1100 connect( dialogButtonBox, &QDialogButtonBox::rejected, &orderByDlg, &QDialog::reject );
1101 orderByDlg.setLayout( layout );
1103 QGroupBox *sortingGroupBox =
new QGroupBox();
1104 sortingGroupBox->setTitle( tr(
"Defined sort order in attribute table" ) );
1105 sortingGroupBox->setCheckable(
true );
1107 layout->addWidget( sortingGroupBox );
1108 sortingGroupBox->setLayout(
new QGridLayout() );
1113 expressionBuilder->
initWithLayer( mLayer, context, QStringLiteral(
"generic" ) );
1116 sortingGroupBox->layout()->addWidget( expressionBuilder );
1118 QCheckBox *cbxSortAscending =
new QCheckBox( tr(
"Sort ascending" ) );
1119 cbxSortAscending->setChecked( config.
sortOrder() == Qt::AscendingOrder );
1120 sortingGroupBox->layout()->addWidget( cbxSortAscending );
1122 layout->addWidget( dialogButtonBox );
1123 if ( orderByDlg.exec() )
1125 const Qt::SortOrder sortOrder = cbxSortAscending->isChecked() ? Qt::AscendingOrder : Qt::DescendingOrder;
1126 if ( sortingGroupBox->isChecked() )
1150 QSet<int> attributes;
1154 const QVector<QgsAttributeTableConfig::ColumnConfig> constColumnconfigs { config.
columns() };
1163 const QSet<int> colAttrs { attributes };
1164 for (
const int attrIdx : std::as_const( colAttrs ) )
1173 std::sort( attrs.begin(), attrs.end() );
1177void QgsDualView::zoomToCurrentFeature()
1179 const QModelIndex currentIndex = mTableView->currentIndex();
1180 if ( !currentIndex.isValid() )
1186 ids.insert( mFilterModel->
rowToId( currentIndex ) );
1194void QgsDualView::panToCurrentFeature()
1196 const QModelIndex currentIndex = mTableView->currentIndex();
1197 if ( !currentIndex.isValid() )
1203 ids.insert( mFilterModel->
rowToId( currentIndex ) );
1211void QgsDualView::flashCurrentFeature()
1213 const QModelIndex currentIndex = mTableView->currentIndex();
1214 if ( !currentIndex.isValid() )
1220 ids.insert( mFilterModel->
rowToId( currentIndex ) );
1228void QgsDualView::rebuildFullLayerCache()
1236void QgsDualView::previewExpressionChanged(
const QString &expression )
1238 mLayer->setDisplayExpression( expression );
1241void QgsDualView::onSortColumnChanged()
1245 cfg.
sortOrder() != mFilterModel->sortOrder() )
1253void QgsDualView::updateSelectedFeatures()
1265void QgsDualView::updateEditedAddedFeatures()
1277void QgsDualView::extentChanged()
1290void QgsDualView::featureFormAttributeChanged(
const QString &attribute,
const QVariant &value,
bool attributeChanged )
1292 Q_UNUSED( attribute )
1294 if ( attributeChanged )
1296 mFeatureListView->setCurrentFeatureEdited(
true );
1297 mAttributeForm->
save();
1320 mTableView->setFeatureSelectionManager( featureSelectionManager );
1321 mFeatureListView->setFeatureSelectionManager( featureSelectionManager );
1323 if ( mFeatureSelectionManager && mFeatureSelectionManager->parent() ==
this )
1324 delete mFeatureSelectionManager;
1326 mFeatureSelectionManager = featureSelectionManager;
1332 mConfig.
update( mLayer->fields() );
1333 mLayer->setAttributeTableConfig( mConfig );
1335 mTableView->setAttributeTableConfig( mConfig );
1346 mFilterModel->
sort( -1 );
1365void QgsDualView::progress(
int i,
bool &cancel )
1367 if ( !mProgressDlg )
1369 mProgressDlg =
new QProgressDialog( tr(
"Loading features…" ), tr(
"Abort" ), 0, 0,
this );
1370 mProgressDlg->setWindowTitle( tr(
"Attribute Table" ) );
1371 mProgressDlg->setWindowModality( Qt::WindowModal );
1372 mProgressDlg->show();
1375 mProgressDlg->setLabelText( tr(
"%L1 features loaded." ).arg( i ) );
1376 QCoreApplication::processEvents();
1378 cancel = mProgressDlg && mProgressDlg->wasCanceled();
1381void QgsDualView::finished()
1383 delete mProgressDlg;
1384 mProgressDlg =
nullptr;
@ 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.
Utility class that encapsulates an action based on vector attributes.
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
This class contains context information for attribute editor widgets.
QgsMessageBar * mainMessageBar()
Returns the main message bar.
@ 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
This is 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.
QString sortExpression() const
The expression which is used to sort the attribute table.
FilterMode filterMode()
The current filterModel.
void sort(int column, Qt::SortOrder order=Qt::AscendingOrder) override
Sort by the given column using the given order.
QgsMapCanvas * mapCanvas() const
Returns the map canvas.
void setFilterMode(FilterMode filterMode)
Set the filter mode the filter will use.
QString filterExpression() const
Returns the stored filter expression string.
void setAttributeTableConfig(const QgsAttributeTableConfig &config, bool force=false)
Set the attribute table configuration to control which fields are shown, in which order they are show...
void disconnectFilterModeConnections()
Disconnect the connections set for the current filterMode.
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 (since QGIS 3.30)
@ 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 filterFeatures()
Updates the filtered features in the filter model.
void setFilterExpression(const QgsExpression &expression, const QgsExpressionContext &context)
Set the expression and the context to be stored in case of the features need to be filtered again (li...
virtual void setFilteredFeatures(const QgsFeatureIds &ids)
Specify a list of features, which the filter will accept.
QgsFeatureId rowToId(const QModelIndex &row)
Returns the feature id for a given model index.
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)
QgsVectorLayer * layer() const
Returns the layer this filter acts on.
void setSelectedOnTop(bool selectedOnTop)
Changes the sort order of the features.
void sortColumnChanged(int column, Qt::SortOrder order)
Emitted whenever the sort column is changed.
A model backed by a QgsVectorLayerCache which is able to provide feature/attribute information to a Q...
const QgsFeatureRequest & request() const
Gets the the feature request.
void fieldConditionalStyleChanged(const QString &fieldName)
Handles updating the model when the conditional style for a field changes.
void modelChanged()
Model has been changed.
void executeMapLayerAction(QgsMapLayerAction *action, const QModelIndex &idx, const QgsMapLayerActionContext &context=QgsMapLayerActionContext()) const
Execute a QgsMapLayerAction.
void progress(int i, bool &cancel)
void setRequest(const QgsFeatureRequest &request)
Set a request that will be used to fill this attribute table model.
int rowCount(const QModelIndex &parent=QModelIndex()) const override
Returns the number of rows.
void setEditorContext(const QgsAttributeEditorContext &context)
Sets the context in which this table is shown.
void setShowValidityState(bool show)
Sets whether the attribute table will add a visual feedback to cells when an attribute constraint is ...
QgsFeatureId rowToId(int row) const
Maps row to feature id.
virtual void loadLayer()
Loads the layer into the model Preferably to be called, before using this model as source for any oth...
void setExtraColumns(int extraColumns)
Empty extra columns to announce from this model.
void executeAction(QUuid action, const QModelIndex &idx) const
Execute an action.
QVariant data(const QModelIndex &index, int role) const override
Returns data on the given index.
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.
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...
Class for parsing and evaluation of expressions (formerly called "search strings").
QSet< int > referencedAttributeIndexes(const QgsFields &fields) const
Returns a list of field name indexes obtained from the provided fields.
int rowCount(const QModelIndex &parent=QModelIndex()) const override
void setSortByDisplayExpression(bool sortByDisplayExpression, Qt::SortOrder order=Qt::AscendingOrder)
Sort this model by its display expression.
QVariant data(const QModelIndex &index, int role) const override
Shows a list of features and renders a 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)
This class 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...
Encapsulate a field in an attribute table or data source.
@ OriginExpression
Field is calculated from an expression.
FieldOrigin fieldOrigin(int fieldIdx) const
Returns the field's origin (value from an enumeration).
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.
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.
const QgsMapSettings & mapSettings() const
Gets access to properties used for map rendering.
QgsRectangle extent() const
Returns the current zoom extent of the map canvas.
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.
An action which can run on map layers The class can be used in two manners:
void layerModified()
Emitted when modifications has been done on layer.
QgsPointXY mapToLayerCoordinates(const QgsMapLayer *layer, QgsPointXY point) const
transform point coordinates from output CRS to layer's CRS
void pushWarning(const QString &title, const QString &message)
Pushes a warning message that must be manually dismissed by the user.
Dialog for organising (hiding and reordering) columns in the attributes table.
A rectangle specified with double values.
bool isNull() const
Test if the rectangle is null (holding no spatial information).
This class is a composition of two QSettings instances:
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
void setEnumValue(const QString &key, const T &value, const Section section=NoSection)
Set the value of a setting based on an enum.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
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.
@ SelectAtId
Fast access to features using their ID.
This class caches features of a given QgsVectorLayer.
void setFullCache(bool fullCache)
This enables or disables full caching.
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.
Represents a vector layer which manages a vector based data sets.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
QString expressionField(int index) const
Returns the expression used for a given expression field.
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.
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.