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 );
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();
444 rebuildFullLayerCache();
450 delete mFeatureListModel;
471 connect( mMasterModel, &QgsAttributeTableModel::rowsRemoved, mFilterModel, &QgsAttributeTableFilterModel::invalidate );
472 connect( mMasterModel, &QgsAttributeTableModel::rowsInserted, mFilterModel, &QgsAttributeTableFilterModel::invalidate );
480void QgsDualView::restoreRecentDisplayExpressions()
482 const QVariantList previewExpressions = mLayer->customProperty( QStringLiteral(
"dualview/previewExpressions" ) ).toList();
484 for (
const QVariant &previewExpression : previewExpressions )
485 insertRecentlyUsedDisplayExpression( previewExpression.toString() );
488void QgsDualView::saveRecentDisplayExpressions()
const
494 const QList<QAction *> actions = mFeatureListPreviewButton->actions();
497 int index = actions.indexOf( mLastDisplayExpressionAction );
500 QVariantList previewExpressions;
501 for ( ; index < actions.length(); ++index )
503 QAction *action = actions.at( index );
504 previewExpressions << action->property(
"previewExpression" );
507 mLayer->setCustomProperty( QStringLiteral(
"dualview/previewExpressions" ), previewExpressions );
511void QgsDualView::setDisplayExpression(
const QString &expression )
513 mDisplayExpression = expression;
514 insertRecentlyUsedDisplayExpression( expression );
517void QgsDualView::insertRecentlyUsedDisplayExpression(
const QString &expression )
519 const QList<QAction *> actions = mFeatureListPreviewButton->actions();
522 const int index = actions.indexOf( mLastDisplayExpressionAction );
525 for (
int i = 0; index + i < actions.length(); ++i )
527 QAction *action = actions.at( index );
528 if ( action->text() == expression || i >= 9 )
530 if ( action == mLastDisplayExpressionAction )
531 mLastDisplayExpressionAction =
nullptr;
532 mFeatureListPreviewButton->removeAction( action );
536 if ( !mLastDisplayExpressionAction )
537 mLastDisplayExpressionAction = action;
542 QString name = expression;
544 if ( expression.startsWith( QLatin1String(
"COALESCE( \"" ) ) && expression.endsWith( QLatin1String(
", '<NULL>' )" ) ) )
546 name = expression.mid( 11, expression.length() - 24 );
548 const int fieldIndex = mLayer->fields().indexOf( name );
549 if ( fieldIndex != -1 )
551 name = mLayer->attributeDisplayName( fieldIndex );
552 icon = mLayer->fields().iconForField( fieldIndex );
560 QAction *previewAction =
new QAction( icon, name, mFeatureListPreviewButton );
561 previewAction->setProperty(
"previewExpression", expression );
562 connect( previewAction, &QAction::triggered,
this, [expression,
this](
bool )
564 setDisplayExpression( expression );
565 mFeatureListPreviewButton->setText( expression );
569 mFeatureListPreviewButton->insertAction( mLastDisplayExpressionAction, previewAction );
570 mLastDisplayExpressionAction = previewAction;
573void QgsDualView::updateEditSelectionProgress(
int progress,
int count )
575 mProgressCount->setText( QStringLiteral(
"%1 / %2" ).arg( progress + 1 ).arg( count ) );
576 mPreviousFeatureButton->setEnabled( progress > 0 );
577 mNextFeatureButton->setEnabled( progress + 1 < count );
578 mFirstFeatureButton->setEnabled( progress > 0 );
579 mLastFeatureButton->setEnabled( progress + 1 < count );
580 if ( mAttributeForm )
582 mAttributeForm->setVisible( count > 0 );
586void QgsDualView::panOrZoomToFeature(
const QgsFeatureIds &featureset )
591 if ( mBrowsingAutoPanScaleAllowed )
593 if ( mAutoPanButton->isChecked() )
594 QTimer::singleShot( 0,
this, [ = ]()
598 else if ( mAutoZoomButton->isChecked() )
599 QTimer::singleShot( 0,
this, [ = ]()
604 if ( mFlashButton->isChecked() )
605 QTimer::singleShot( 0,
this, [ = ]()
609 mLastFeatureSet = featureset;
613void QgsDualView::setBrowsingAutoPanScaleAllowed(
bool allowed )
615 if ( mBrowsingAutoPanScaleAllowed == allowed )
618 mBrowsingAutoPanScaleAllowed = allowed;
620 mAutoPanButton->setEnabled( allowed );
621 mAutoZoomButton->setEnabled( allowed );
623 const QString disabledHint = tr(
"(disabled when attribute table only shows features visible in the current map canvas extent)" );
625 mAutoPanButton->setToolTip( tr(
"Automatically pan to the current feature" ) + ( allowed ? QString() : QString(
' ' ) + disabledHint ) );
626 mAutoZoomButton->setToolTip( tr(
"Automatically zoom to the current feature" ) + ( allowed ? QString() : QString(
' ' ) + disabledHint ) );
629void QgsDualView::panZoomGroupButtonToggled( QAbstractButton *button,
bool checked )
631 if ( button == mAutoPanButton && checked )
634 mAutoZoomButton->setChecked(
false );
636 else if ( button == mAutoZoomButton && checked )
639 mAutoPanButton->setChecked(
false );
646 if ( checked && mLayer->isSpatial() )
647 panOrZoomToFeature( mFeatureListView->currentEditSelection() );
650void QgsDualView::flashButtonClicked(
bool clicked )
652 QgsSettings().
setValue( QStringLiteral(
"/qgis/attributeTable/featureListHighlightFeature" ), clicked );
659 canvas->
flashFeatureIds( mLayer, mFeatureListView->currentEditSelection() );
662void QgsDualView::filterError(
const QString &errorMessage )
670void QgsDualView::featureListAboutToChangeEditSelection(
bool &ok )
672 if ( !mAttributeForm )
675 if ( mLayer->isEditable() && !mAttributeForm->
save() )
679void QgsDualView::featureListCurrentEditSelectionChanged(
const QgsFeature &feat )
681 if ( !mAttributeForm )
683 initAttributeForm( feat );
685 else if ( !mLayer->isEditable() || mAttributeForm->
save() )
689 featureset << feat.
id();
692 if ( mLayer->isSpatial() )
693 panOrZoomToFeature( featureset );
704 mFeatureListView->setCurrentFeatureEdited(
false );
705 mFeatureListView->setEditSelection( fids );
710 return mAttributeForm ? mAttributeForm->
save() :
false;
715 mConditionalFormatWidgetStack->setVisible( !mConditionalFormatWidgetStack->isVisible() );
720 if ( !mAttributeForm )
725 mPreviousView =
view();
738 if ( !mAttributeForm )
745 mAttributeForm->setVisible(
true );
750 mAttributeForm->setVisible( mFilterModel->rowCount( ) > 0 );
755void QgsDualView::previewExpressionBuilder()
761 dlg.setWindowTitle( tr(
"Expression Based Preview" ) );
762 dlg.setExpressionText( mFeatureListView->displayExpression() );
764 if ( dlg.exec() == QDialog::Accepted )
766 mFeatureListView->setDisplayExpression( dlg.expressionText() );
767 mFeatureListPreviewButton->setDefaultAction( mActionExpressionPreview );
768 mFeatureListPreviewButton->setPopupMode( QToolButton::MenuButtonPopup );
771 setDisplayExpression( mFeatureListView->displayExpression() );
774void QgsDualView::previewColumnChanged( QAction *previewAction,
const QString &expression )
776 if ( !mFeatureListView->setDisplayExpression( QStringLiteral(
"COALESCE( \"%1\", '<NULL>' )" ).arg( expression ) ) )
778 QMessageBox::warning(
this,
779 tr(
"Column Preview" ),
780 tr(
"Could not set column '%1' as preview column.\nParser error:\n%2" )
781 .arg( previewAction->text(), mFeatureListView->parserErrorString() )
786 mFeatureListPreviewButton->setText( previewAction->text() );
787 mFeatureListPreviewButton->setIcon( previewAction->icon() );
788 mFeatureListPreviewButton->setPopupMode( QToolButton::InstantPopup );
791 setDisplayExpression( mFeatureListView->displayExpression() );
801 return mFilterModel->rowCount();
806 const QModelIndex currentIndex = mTableView->currentIndex();
807 if ( !currentIndex.isValid() )
812 const QVariant var = mMasterModel->
data( currentIndex, Qt::DisplayRole );
813 QApplication::clipboard()->setText( var.toString() );
819 mProgressDlg->cancel();
824 if ( mAttributeForm )
833 saveRecentDisplayExpressions();
836void QgsDualView::viewWillShowContextMenu( QMenu *menu,
const QModelIndex &masterIndex )
843 QAction *copyContentAction = menu->addAction( tr(
"Copy Cell Content" ) );
844 menu->addAction( copyContentAction );
845 connect( copyContentAction, &QAction::triggered,
this, [masterIndex,
this]
847 const QVariant var = mMasterModel->
data( masterIndex, Qt::DisplayRole );
848 QApplication::clipboard()->setText( var.toString() );
853 if ( canvas && vl && vl->isSpatial() )
855 QAction *zoomToFeatureAction = menu->addAction( tr(
"Zoom to Feature" ) );
856 connect( zoomToFeatureAction, &QAction::triggered,
this, &QgsDualView::zoomToCurrentFeature );
858 QAction *panToFeatureAction = menu->addAction( tr(
"Pan to Feature" ) );
859 connect( panToFeatureAction, &QAction::triggered,
this, &QgsDualView::panToCurrentFeature );
861 QAction *flashFeatureAction = menu->addAction( tr(
"Flash Feature" ) );
862 connect( flashFeatureAction, &QAction::triggered,
this, &QgsDualView::flashCurrentFeature );
866 const QList<QgsAction> actions = mLayer->actions()->actions( QStringLiteral(
"Field" ) );
867 if ( !actions.isEmpty() )
869 QAction *a = menu->addAction( tr(
"Run Layer Action" ) );
870 a->setEnabled(
false );
872 for (
const QgsAction &action : actions )
874 if ( !action.runable() )
877 if ( vl && !vl->isEditable() && action.isEnabledOnlyWhenEditable() )
884 const QModelIndex rowSourceIndex = mMasterModel->index( masterIndex.row(), 0 );
885 if ( ! rowSourceIndex.isValid() )
893 if ( !registeredActions.isEmpty() )
896 menu->addSeparator();
908 if ( mLayer->selectedFeatureCount() > 1 && mLayer->selectedFeatureIds().contains( currentFid ) )
911 if ( !registeredActions.isEmpty() )
913 menu->addSeparator();
914 QAction *action = menu->addAction( tr(
"Actions on Selection (%1)" ).arg( mLayer->selectedFeatureCount() ) );
915 action->setEnabled(
false );
920 menu->addAction( action->text(), action, [ = ]()
922 Q_NOWARN_DEPRECATED_PUSH
923 action->triggerForFeatures( mLayer, mLayer->selectedFeatures() );
924 Q_NOWARN_DEPRECATED_POP
925 action->triggerForFeatures( mLayer, mLayer->selectedFeatures(), context );
931 menu->addSeparator();
937void QgsDualView::widgetWillShowContextMenu(
QgsActionMenu *menu,
const QModelIndex &atIndex )
943void QgsDualView::showViewHeaderMenu( QPoint point )
945 const int col = mTableView->columnAt( point.x() );
947 delete mHorizontalHeaderMenu;
948 mHorizontalHeaderMenu =
new QMenu(
this );
950 QAction *hide =
new QAction( tr(
"&Hide Column" ), mHorizontalHeaderMenu );
951 connect( hide, &QAction::triggered,
this, &QgsDualView::hideColumn );
952 hide->setData( col );
953 mHorizontalHeaderMenu->addAction( hide );
954 QAction *setWidth =
new QAction( tr(
"&Set Width…" ), mHorizontalHeaderMenu );
955 connect( setWidth, &QAction::triggered,
this, &QgsDualView::resizeColumn );
956 setWidth->setData( col );
957 mHorizontalHeaderMenu->addAction( setWidth );
959 QAction *setWidthAllColumns =
new QAction( tr(
"&Set All Column Widths…" ), mHorizontalHeaderMenu );
960 connect( setWidthAllColumns, &QAction::triggered,
this, &QgsDualView::resizeAllColumns );
961 setWidthAllColumns->setData( col );
962 mHorizontalHeaderMenu->addAction( setWidthAllColumns );
964 QAction *optimizeWidth =
new QAction( tr(
"&Autosize" ), mHorizontalHeaderMenu );
965 connect( optimizeWidth, &QAction::triggered,
this, &QgsDualView::autosizeColumn );
966 optimizeWidth->setData( col );
967 mHorizontalHeaderMenu->addAction( optimizeWidth );
969 QAction *optimizeWidthAllColumns =
new QAction( tr(
"&Autosize All Columns" ), mHorizontalHeaderMenu );
970 connect( optimizeWidthAllColumns, &QAction::triggered,
this, &QgsDualView::autosizeAllColumns );
971 mHorizontalHeaderMenu->addAction( optimizeWidthAllColumns );
974 mHorizontalHeaderMenu->addSeparator();
975 QAction *organize =
new QAction( tr(
"&Organize Columns…" ), mHorizontalHeaderMenu );
976 connect( organize, &QAction::triggered,
this, &QgsDualView::organizeColumns );
977 mHorizontalHeaderMenu->addAction( organize );
978 QAction *sort =
new QAction( tr(
"&Sort…" ), mHorizontalHeaderMenu );
979 connect( sort, &QAction::triggered,
this, [ = ]() {modifySort();} );
980 mHorizontalHeaderMenu->addAction( sort );
982 mHorizontalHeaderMenu->popup( mTableView->horizontalHeader()->mapToGlobal( point ) );
985void QgsDualView::organizeColumns()
993 if ( dialog.exec() == QDialog::Accepted )
1000void QgsDualView::tableColumnResized(
int column,
int width )
1004 if ( sourceCol >= 0 && config.
columnWidth( sourceCol ) != width )
1011void QgsDualView::hideColumn()
1013 QAction *action = qobject_cast<QAction *>( sender() );
1014 const int col = action->data().toInt();
1017 if ( sourceCol >= 0 )
1024void QgsDualView::resizeColumn()
1026 QAction *action = qobject_cast<QAction *>( sender() );
1027 const int col = action->data().toInt();
1033 if ( sourceCol >= 0 )
1036 const int width = QInputDialog::getInt(
this, tr(
"Set column width" ), tr(
"Enter column width" ),
1037 mTableView->columnWidth( col ),
1047void QgsDualView::resizeAllColumns()
1049 QAction *action = qobject_cast<QAction *>( sender() );
1050 const int col = action->data().toInt();
1057 const int width = QInputDialog::getInt(
this, tr(
"Set Column Width" ), tr(
"Enter column width" ),
1058 mTableView->columnWidth( col ),
1062 const int colCount = mTableView->model()->columnCount();
1065 for (
int i = 0; i < colCount; i++ )
1074void QgsDualView::autosizeColumn()
1076 QAction *action = qobject_cast<QAction *>( sender() );
1077 const int col = action->data().toInt();
1078 mTableView->resizeColumnToContents( col );
1081void QgsDualView::autosizeAllColumns()
1083 mTableView->resizeColumnsToContents();
1086bool QgsDualView::modifySort()
1094 orderByDlg.setWindowTitle( tr(
"Configure Attribute Table Sort Order" ) );
1095 QDialogButtonBox *dialogButtonBox =
new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
1096 QGridLayout *layout =
new QGridLayout();
1097 connect( dialogButtonBox, &QDialogButtonBox::accepted, &orderByDlg, &QDialog::accept );
1098 connect( dialogButtonBox, &QDialogButtonBox::rejected, &orderByDlg, &QDialog::reject );
1099 orderByDlg.setLayout( layout );
1101 QGroupBox *sortingGroupBox =
new QGroupBox();
1102 sortingGroupBox->setTitle( tr(
"Defined sort order in attribute table" ) );
1103 sortingGroupBox->setCheckable(
true );
1105 layout->addWidget( sortingGroupBox );
1106 sortingGroupBox->setLayout(
new QGridLayout() );
1111 expressionBuilder->
initWithLayer( mLayer, context, QStringLiteral(
"generic" ) );
1114 sortingGroupBox->layout()->addWidget( expressionBuilder );
1116 QCheckBox *cbxSortAscending =
new QCheckBox( tr(
"Sort ascending" ) );
1117 cbxSortAscending->setChecked( config.
sortOrder() == Qt::AscendingOrder );
1118 sortingGroupBox->layout()->addWidget( cbxSortAscending );
1120 layout->addWidget( dialogButtonBox );
1121 if ( orderByDlg.exec() )
1123 const Qt::SortOrder sortOrder = cbxSortAscending->isChecked() ? Qt::AscendingOrder : Qt::DescendingOrder;
1124 if ( sortingGroupBox->isChecked() )
1148 QSet<int> attributes;
1152 const QVector<QgsAttributeTableConfig::ColumnConfig> constColumnconfigs { config.
columns() };
1161 const QSet<int> colAttrs { attributes };
1162 for (
const int attrIdx : std::as_const( colAttrs ) )
1171 std::sort( attrs.begin(), attrs.end() );
1175void QgsDualView::zoomToCurrentFeature()
1177 const QModelIndex currentIndex = mTableView->currentIndex();
1178 if ( !currentIndex.isValid() )
1184 ids.insert( mFilterModel->
rowToId( currentIndex ) );
1192void QgsDualView::panToCurrentFeature()
1194 const QModelIndex currentIndex = mTableView->currentIndex();
1195 if ( !currentIndex.isValid() )
1201 ids.insert( mFilterModel->
rowToId( currentIndex ) );
1209void QgsDualView::flashCurrentFeature()
1211 const QModelIndex currentIndex = mTableView->currentIndex();
1212 if ( !currentIndex.isValid() )
1218 ids.insert( mFilterModel->
rowToId( currentIndex ) );
1226void QgsDualView::rebuildFullLayerCache()
1234void QgsDualView::previewExpressionChanged(
const QString &expression )
1236 mLayer->setDisplayExpression( expression );
1239void QgsDualView::onSortColumnChanged()
1243 cfg.
sortOrder() != mFilterModel->sortOrder() )
1251void QgsDualView::updateSelectedFeatures()
1263void QgsDualView::updateEditedAddedFeatures()
1275void QgsDualView::extentChanged()
1288void QgsDualView::featureFormAttributeChanged(
const QString &attribute,
const QVariant &value,
bool attributeChanged )
1290 Q_UNUSED( attribute )
1292 if ( attributeChanged )
1294 mFeatureListView->setCurrentFeatureEdited(
true );
1295 mAttributeForm->
save();
1318 mTableView->setFeatureSelectionManager( featureSelectionManager );
1319 mFeatureListView->setFeatureSelectionManager( featureSelectionManager );
1321 if ( mFeatureSelectionManager && mFeatureSelectionManager->parent() ==
this )
1322 delete mFeatureSelectionManager;
1324 mFeatureSelectionManager = featureSelectionManager;
1330 mConfig.
update( mLayer->fields() );
1331 mLayer->setAttributeTableConfig( mConfig );
1333 mTableView->setAttributeTableConfig( mConfig );
1344 mFilterModel->
sort( -1 );
1363void QgsDualView::progress(
int i,
bool &cancel )
1365 if ( !mProgressDlg )
1367 mProgressDlg =
new QProgressDialog( tr(
"Loading features…" ), tr(
"Abort" ), 0, 0,
this );
1368 mProgressDlg->setWindowTitle( tr(
"Attribute Table" ) );
1369 mProgressDlg->setWindowModality( Qt::WindowModal );
1370 mProgressDlg->show();
1373 mProgressDlg->setLabelText( tr(
"%L1 features loaded." ).arg( i ) );
1374 QCoreApplication::processEvents();
1376 cancel = mProgressDlg && mProgressDlg->wasCanceled();
1379void QgsDualView::finished()
1381 delete mProgressDlg;
1382 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.
@ 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).
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 & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
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.
@ 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.