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 )
167 mFeatureListView->setEditSelection(
QgsFeatureIds() << mFeatureListModel->
data( mFeatureListModel->index( 0, 0 ), QgsFeatureListModel::Role::FeatureRole ).value<
QgsFeature>().
id() );
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;
227 const int fieldIndex = mLayer->fields().lookupField(
field.
name() );
228 if ( fieldIndex == -1 )
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 );
340 || ( mMasterModel->
rowCount() == 0 );
342 if ( !needsGeometry )
374 filterFeatures( QStringLiteral(
"is_feature_valid() = false" ), context );
384 if ( !filterExpression.isEmpty() )
401 setBrowsingAutoPanScaleAllowed(
false );
409 setBrowsingAutoPanScaleAllowed(
true );
413 if ( requiresTableReload )
419 whileBlocking( mLayerCache )->setCacheGeometry( needsGeometry );
433void QgsDualView::initLayerCache(
bool cacheGeometry )
437 const int cacheSize = settings.
value( QStringLiteral(
"qgis/attributeTableRowCache" ),
"10000" ).toInt();
443 rebuildFullLayerCache();
449 delete mFeatureListModel;
470 connect( mMasterModel, &QgsAttributeTableModel::rowsRemoved, mFilterModel, &QgsAttributeTableFilterModel::invalidate );
471 connect( mMasterModel, &QgsAttributeTableModel::rowsInserted, mFilterModel, &QgsAttributeTableFilterModel::invalidate );
479void QgsDualView::restoreRecentDisplayExpressions()
481 const QVariantList previewExpressions = mLayer->customProperty( QStringLiteral(
"dualview/previewExpressions" ) ).toList();
483 for (
const QVariant &previewExpression : previewExpressions )
484 insertRecentlyUsedDisplayExpression( previewExpression.toString() );
487void QgsDualView::saveRecentDisplayExpressions()
const
493 const QList<QAction *> actions = mFeatureListPreviewButton->actions();
496 int index = actions.indexOf( mLastDisplayExpressionAction );
499 QVariantList previewExpressions;
500 for ( ; index < actions.length(); ++index )
502 QAction *action = actions.at( index );
503 previewExpressions << action->property(
"previewExpression" );
506 mLayer->setCustomProperty( QStringLiteral(
"dualview/previewExpressions" ), previewExpressions );
510void QgsDualView::setDisplayExpression(
const QString &expression )
512 mDisplayExpression = expression;
513 insertRecentlyUsedDisplayExpression( expression );
516void QgsDualView::insertRecentlyUsedDisplayExpression(
const QString &expression )
518 const QList<QAction *> actions = mFeatureListPreviewButton->actions();
521 const int index = actions.indexOf( mLastDisplayExpressionAction );
524 for (
int i = 0; index + i < actions.length(); ++i )
526 QAction *action = actions.at( index );
527 if ( action->text() == expression || i >= 9 )
529 if ( action == mLastDisplayExpressionAction )
530 mLastDisplayExpressionAction =
nullptr;
531 mFeatureListPreviewButton->removeAction( action );
535 if ( !mLastDisplayExpressionAction )
536 mLastDisplayExpressionAction = action;
541 QString name = expression;
543 if ( expression.startsWith( QLatin1String(
"COALESCE( \"" ) ) && expression.endsWith( QLatin1String(
", '<NULL>' )" ) ) )
545 name = expression.mid( 11, expression.length() - 24 );
547 const int fieldIndex = mLayer->fields().indexOf( name );
548 if ( fieldIndex != -1 )
550 name = mLayer->attributeDisplayName( fieldIndex );
551 icon = mLayer->fields().iconForField( fieldIndex );
559 QAction *previewAction =
new QAction( icon, name, mFeatureListPreviewButton );
560 previewAction->setProperty(
"previewExpression", expression );
561 connect( previewAction, &QAction::triggered,
this, [expression,
this](
bool )
563 setDisplayExpression( expression );
564 mFeatureListPreviewButton->setText( expression );
568 mFeatureListPreviewButton->insertAction( mLastDisplayExpressionAction, previewAction );
569 mLastDisplayExpressionAction = previewAction;
572void QgsDualView::updateEditSelectionProgress(
int progress,
int count )
574 mProgressCount->setText( QStringLiteral(
"%1 / %2" ).arg( progress + 1 ).arg( count ) );
575 mPreviousFeatureButton->setEnabled( progress > 0 );
576 mNextFeatureButton->setEnabled( progress + 1 < count );
577 mFirstFeatureButton->setEnabled( progress > 0 );
578 mLastFeatureButton->setEnabled( progress + 1 < count );
579 if ( mAttributeForm )
581 mAttributeForm->setVisible( count > 0 );
585void QgsDualView::panOrZoomToFeature(
const QgsFeatureIds &featureset )
590 if ( mBrowsingAutoPanScaleAllowed )
592 if ( mAutoPanButton->isChecked() )
593 QTimer::singleShot( 0,
this, [ = ]()
597 else if ( mAutoZoomButton->isChecked() )
598 QTimer::singleShot( 0,
this, [ = ]()
603 if ( mFlashButton->isChecked() )
604 QTimer::singleShot( 0,
this, [ = ]()
608 mLastFeatureSet = featureset;
612void QgsDualView::setBrowsingAutoPanScaleAllowed(
bool allowed )
614 if ( mBrowsingAutoPanScaleAllowed == allowed )
617 mBrowsingAutoPanScaleAllowed = allowed;
619 mAutoPanButton->setEnabled( allowed );
620 mAutoZoomButton->setEnabled( allowed );
622 const QString disabledHint = tr(
"(disabled when attribute table only shows features visible in the current map canvas extent)" );
624 mAutoPanButton->setToolTip( tr(
"Automatically pan to the current feature" ) + ( allowed ? QString() : QString(
' ' ) + disabledHint ) );
625 mAutoZoomButton->setToolTip( tr(
"Automatically zoom to the current feature" ) + ( allowed ? QString() : QString(
' ' ) + disabledHint ) );
628void QgsDualView::panZoomGroupButtonToggled( QAbstractButton *button,
bool checked )
630 if ( button == mAutoPanButton && checked )
633 mAutoZoomButton->setChecked(
false );
635 else if ( button == mAutoZoomButton && checked )
638 mAutoPanButton->setChecked(
false );
645 if ( checked && mLayer->isSpatial() )
646 panOrZoomToFeature( mFeatureListView->currentEditSelection() );
649void QgsDualView::flashButtonClicked(
bool clicked )
651 QgsSettings().
setValue( QStringLiteral(
"/qgis/attributeTable/featureListHighlightFeature" ), clicked );
658 canvas->
flashFeatureIds( mLayer, mFeatureListView->currentEditSelection() );
661void QgsDualView::filterError(
const QString &errorMessage )
669void QgsDualView::featureListAboutToChangeEditSelection(
bool &ok )
671 if ( !mAttributeForm )
674 if ( mLayer->isEditable() && !mAttributeForm->
save() )
678void QgsDualView::featureListCurrentEditSelectionChanged(
const QgsFeature &feat )
680 if ( !mAttributeForm )
682 initAttributeForm( feat );
684 else if ( !mLayer->isEditable() || mAttributeForm->
save() )
688 featureset << feat.
id();
691 if ( mLayer->isSpatial() )
692 panOrZoomToFeature( featureset );
703 mFeatureListView->setCurrentFeatureEdited(
false );
704 mFeatureListView->setEditSelection( fids );
709 return mAttributeForm ? mAttributeForm->
save() :
false;
714 mConditionalFormatWidgetStack->setVisible( !mConditionalFormatWidgetStack->isVisible() );
719 if ( !mAttributeForm )
724 mPreviousView =
view();
737 if ( !mAttributeForm )
744 mAttributeForm->setVisible(
true );
749 mAttributeForm->setVisible( mFilterModel->rowCount( ) > 0 );
754void QgsDualView::previewExpressionBuilder()
760 dlg.setWindowTitle( tr(
"Expression Based Preview" ) );
761 dlg.setExpressionText( mFeatureListView->displayExpression() );
763 if ( dlg.exec() == QDialog::Accepted )
765 mFeatureListView->setDisplayExpression( dlg.expressionText() );
766 mFeatureListPreviewButton->setDefaultAction( mActionExpressionPreview );
767 mFeatureListPreviewButton->setPopupMode( QToolButton::MenuButtonPopup );
770 setDisplayExpression( mFeatureListView->displayExpression() );
773void QgsDualView::previewColumnChanged( QAction *previewAction,
const QString &expression )
775 if ( !mFeatureListView->setDisplayExpression( QStringLiteral(
"COALESCE( \"%1\", '<NULL>' )" ).arg( expression ) ) )
777 QMessageBox::warning(
this,
778 tr(
"Column Preview" ),
779 tr(
"Could not set column '%1' as preview column.\nParser error:\n%2" )
780 .arg( previewAction->text(), mFeatureListView->parserErrorString() )
785 mFeatureListPreviewButton->setText( previewAction->text() );
786 mFeatureListPreviewButton->setIcon( previewAction->icon() );
787 mFeatureListPreviewButton->setPopupMode( QToolButton::InstantPopup );
790 setDisplayExpression( mFeatureListView->displayExpression() );
800 return mFilterModel->rowCount();
805 const QModelIndex currentIndex = mTableView->currentIndex();
806 if ( !currentIndex.isValid() )
811 const QVariant var = mMasterModel->
data( currentIndex, Qt::DisplayRole );
812 QApplication::clipboard()->setText( var.toString() );
818 mProgressDlg->cancel();
823 if ( mAttributeForm )
832 saveRecentDisplayExpressions();
835void QgsDualView::viewWillShowContextMenu( QMenu *menu,
const QModelIndex &masterIndex )
842 QAction *copyContentAction = menu->addAction( tr(
"Copy Cell Content" ) );
843 menu->addAction( copyContentAction );
844 connect( copyContentAction, &QAction::triggered,
this, [masterIndex,
this]
846 const QVariant var = mMasterModel->
data( masterIndex, Qt::DisplayRole );
847 QApplication::clipboard()->setText( var.toString() );
852 if ( canvas && vl && vl->isSpatial() )
854 QAction *zoomToFeatureAction = menu->addAction( tr(
"Zoom to Feature" ) );
855 connect( zoomToFeatureAction, &QAction::triggered,
this, &QgsDualView::zoomToCurrentFeature );
857 QAction *panToFeatureAction = menu->addAction( tr(
"Pan to Feature" ) );
858 connect( panToFeatureAction, &QAction::triggered,
this, &QgsDualView::panToCurrentFeature );
860 QAction *flashFeatureAction = menu->addAction( tr(
"Flash Feature" ) );
861 connect( flashFeatureAction, &QAction::triggered,
this, &QgsDualView::flashCurrentFeature );
865 const QList<QgsAction> actions = mLayer->actions()->actions( QStringLiteral(
"Field" ) );
866 if ( !actions.isEmpty() )
868 QAction *a = menu->addAction( tr(
"Run Layer Action" ) );
869 a->setEnabled(
false );
871 for (
const QgsAction &action : actions )
873 if ( !action.runable() )
876 if ( vl && !vl->isEditable() && action.isEnabledOnlyWhenEditable() )
883 const QModelIndex rowSourceIndex = mMasterModel->index( masterIndex.row(), 0 );
884 if ( ! rowSourceIndex.isValid() )
892 if ( !registeredActions.isEmpty() )
895 menu->addSeparator();
907 if ( mLayer->selectedFeatureCount() > 1 && mLayer->selectedFeatureIds().contains( currentFid ) )
910 if ( !registeredActions.isEmpty() )
912 menu->addSeparator();
913 QAction *action = menu->addAction( tr(
"Actions on Selection (%1)" ).arg( mLayer->selectedFeatureCount() ) );
914 action->setEnabled(
false );
919 menu->addAction( action->text(), action, [ = ]()
921 Q_NOWARN_DEPRECATED_PUSH
922 action->triggerForFeatures( mLayer, mLayer->selectedFeatures() );
923 Q_NOWARN_DEPRECATED_POP
924 action->triggerForFeatures( mLayer, mLayer->selectedFeatures(), context );
930 menu->addSeparator();
936void QgsDualView::widgetWillShowContextMenu(
QgsActionMenu *menu,
const QModelIndex &atIndex )
942void QgsDualView::showViewHeaderMenu( QPoint point )
944 const int col = mTableView->columnAt( point.x() );
946 delete mHorizontalHeaderMenu;
947 mHorizontalHeaderMenu =
new QMenu(
this );
949 QAction *hide =
new QAction( tr(
"&Hide Column" ), mHorizontalHeaderMenu );
950 connect( hide, &QAction::triggered,
this, &QgsDualView::hideColumn );
951 hide->setData( col );
952 mHorizontalHeaderMenu->addAction( hide );
953 QAction *setWidth =
new QAction( tr(
"&Set Width…" ), mHorizontalHeaderMenu );
954 connect( setWidth, &QAction::triggered,
this, &QgsDualView::resizeColumn );
955 setWidth->setData( col );
956 mHorizontalHeaderMenu->addAction( setWidth );
958 QAction *setWidthAllColumns =
new QAction( tr(
"&Set All Column Widths…" ), mHorizontalHeaderMenu );
959 connect( setWidthAllColumns, &QAction::triggered,
this, &QgsDualView::resizeAllColumns );
960 setWidthAllColumns->setData( col );
961 mHorizontalHeaderMenu->addAction( setWidthAllColumns );
963 QAction *optimizeWidth =
new QAction( tr(
"&Autosize" ), mHorizontalHeaderMenu );
964 connect( optimizeWidth, &QAction::triggered,
this, &QgsDualView::autosizeColumn );
965 optimizeWidth->setData( col );
966 mHorizontalHeaderMenu->addAction( optimizeWidth );
968 QAction *optimizeWidthAllColumns =
new QAction( tr(
"&Autosize All Columns" ), mHorizontalHeaderMenu );
969 connect( optimizeWidthAllColumns, &QAction::triggered,
this, &QgsDualView::autosizeAllColumns );
970 mHorizontalHeaderMenu->addAction( optimizeWidthAllColumns );
973 mHorizontalHeaderMenu->addSeparator();
974 QAction *organize =
new QAction( tr(
"&Organize Columns…" ), mHorizontalHeaderMenu );
975 connect( organize, &QAction::triggered,
this, &QgsDualView::organizeColumns );
976 mHorizontalHeaderMenu->addAction( organize );
977 QAction *sort =
new QAction( tr(
"&Sort…" ), mHorizontalHeaderMenu );
978 connect( sort, &QAction::triggered,
this, [ = ]() {modifySort();} );
979 mHorizontalHeaderMenu->addAction( sort );
981 mHorizontalHeaderMenu->popup( mTableView->horizontalHeader()->mapToGlobal( point ) );
984void QgsDualView::organizeColumns()
992 if ( dialog.exec() == QDialog::Accepted )
999void QgsDualView::tableColumnResized(
int column,
int width )
1003 if ( sourceCol >= 0 && config.
columnWidth( sourceCol ) != width )
1010void QgsDualView::hideColumn()
1012 QAction *action = qobject_cast<QAction *>( sender() );
1013 const int col = action->data().toInt();
1016 if ( sourceCol >= 0 )
1023void QgsDualView::resizeColumn()
1025 QAction *action = qobject_cast<QAction *>( sender() );
1026 const int col = action->data().toInt();
1032 if ( sourceCol >= 0 )
1035 const int width = QInputDialog::getInt(
this, tr(
"Set column width" ), tr(
"Enter column width" ),
1036 mTableView->columnWidth( col ),
1046void QgsDualView::resizeAllColumns()
1048 QAction *action = qobject_cast<QAction *>( sender() );
1049 const int col = action->data().toInt();
1056 const int width = QInputDialog::getInt(
this, tr(
"Set Column Width" ), tr(
"Enter column width" ),
1057 mTableView->columnWidth( col ),
1061 const int colCount = mTableView->model()->columnCount();
1064 for (
int i = 0; i < colCount; i++ )
1073void QgsDualView::autosizeColumn()
1075 QAction *action = qobject_cast<QAction *>( sender() );
1076 const int col = action->data().toInt();
1077 mTableView->resizeColumnToContents( col );
1080void QgsDualView::autosizeAllColumns()
1082 mTableView->resizeColumnsToContents();
1085bool QgsDualView::modifySort()
1093 orderByDlg.setWindowTitle( tr(
"Configure Attribute Table Sort Order" ) );
1094 QDialogButtonBox *dialogButtonBox =
new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
1095 QGridLayout *layout =
new QGridLayout();
1096 connect( dialogButtonBox, &QDialogButtonBox::accepted, &orderByDlg, &QDialog::accept );
1097 connect( dialogButtonBox, &QDialogButtonBox::rejected, &orderByDlg, &QDialog::reject );
1098 orderByDlg.setLayout( layout );
1100 QGroupBox *sortingGroupBox =
new QGroupBox();
1101 sortingGroupBox->setTitle( tr(
"Defined sort order in attribute table" ) );
1102 sortingGroupBox->setCheckable(
true );
1104 layout->addWidget( sortingGroupBox );
1105 sortingGroupBox->setLayout(
new QGridLayout() );
1110 expressionBuilder->
initWithLayer( mLayer, context, QStringLiteral(
"generic" ) );
1113 sortingGroupBox->layout()->addWidget( expressionBuilder );
1115 QCheckBox *cbxSortAscending =
new QCheckBox( tr(
"Sort ascending" ) );
1116 cbxSortAscending->setChecked( config.
sortOrder() == Qt::AscendingOrder );
1117 sortingGroupBox->layout()->addWidget( cbxSortAscending );
1119 layout->addWidget( dialogButtonBox );
1120 if ( orderByDlg.exec() )
1122 const Qt::SortOrder sortOrder = cbxSortAscending->isChecked() ? Qt::AscendingOrder : Qt::DescendingOrder;
1123 if ( sortingGroupBox->isChecked() )
1145void QgsDualView::zoomToCurrentFeature()
1147 const QModelIndex currentIndex = mTableView->currentIndex();
1148 if ( !currentIndex.isValid() )
1154 ids.insert( mFilterModel->
rowToId( currentIndex ) );
1162void QgsDualView::panToCurrentFeature()
1164 const QModelIndex currentIndex = mTableView->currentIndex();
1165 if ( !currentIndex.isValid() )
1171 ids.insert( mFilterModel->
rowToId( currentIndex ) );
1179void QgsDualView::flashCurrentFeature()
1181 const QModelIndex currentIndex = mTableView->currentIndex();
1182 if ( !currentIndex.isValid() )
1188 ids.insert( mFilterModel->
rowToId( currentIndex ) );
1196void QgsDualView::rebuildFullLayerCache()
1204void QgsDualView::previewExpressionChanged(
const QString &expression )
1206 mLayer->setDisplayExpression( expression );
1209void QgsDualView::onSortColumnChanged()
1213 cfg.
sortOrder() != mFilterModel->sortOrder() )
1221void QgsDualView::updateSelectedFeatures()
1233void QgsDualView::updateEditedAddedFeatures()
1245void QgsDualView::extentChanged()
1258void QgsDualView::featureFormAttributeChanged(
const QString &attribute,
const QVariant &value,
bool attributeChanged )
1260 Q_UNUSED( attribute )
1262 if ( attributeChanged )
1264 mFeatureListView->setCurrentFeatureEdited(
true );
1265 mAttributeForm->
save();
1288 mTableView->setFeatureSelectionManager( featureSelectionManager );
1289 mFeatureListView->setFeatureSelectionManager( featureSelectionManager );
1291 if ( mFeatureSelectionManager && mFeatureSelectionManager->parent() ==
this )
1292 delete mFeatureSelectionManager;
1294 mFeatureSelectionManager = featureSelectionManager;
1300 mConfig.
update( mLayer->fields() );
1301 mLayer->setAttributeTableConfig( mConfig );
1303 mTableView->setAttributeTableConfig( mConfig );
1309 mFilterModel->
sort( -1 );
1328void QgsDualView::progress(
int i,
bool &cancel )
1330 if ( !mProgressDlg )
1332 mProgressDlg =
new QProgressDialog( tr(
"Loading features…" ), tr(
"Abort" ), 0, 0,
this );
1333 mProgressDlg->setWindowTitle( tr(
"Attribute Table" ) );
1334 mProgressDlg->setWindowModality( Qt::WindowModal );
1335 mProgressDlg->show();
1338 mProgressDlg->setLabelText( tr(
"%L1 features loaded." ).arg( i ) );
1339 QCoreApplication::processEvents();
1341 cancel = mProgressDlg && mProgressDlg->wasCanceled();
1344void QgsDualView::finished()
1346 delete mProgressDlg;
1347 mProgressDlg =
nullptr;
@ 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.
Qt::SortOrder sortOrder() const
Gets the sort order.
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.
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").
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).
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.
QgsFeatureRequest & setFlags(QgsFeatureRequest::Flags flags)
Sets flags that affect how features will be fetched.
Flags flags() const
Returns the flags which affect how features are fetched.
QgsFeatureRequest & disableFilter()
Disables any attribute/ID filtering.
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
Qgis::SpatialFilterType spatialFilterType() const
Returns the spatial filter type which is currently set on this request.
FilterType filterType() const
Returns the attribute/ID filter type which is currently set on this request.
@ FilterNone
No filter is applied.
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.
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 (all coordinates zero or after call to setMinimal()).
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 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.
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