20#include <QProgressDialog>
22#include <QInputDialog>
30#include "moc_qgsdualview.cpp"
53 : QStackedWidget( parent )
62 mTableView->horizontalHeader()->setContextMenuPolicy( Qt::CustomContextMenu );
63 connect( mTableView->horizontalHeader(), &QHeaderView::customContextMenuRequested,
this, &QgsDualView::showViewHeaderMenu );
66 mConditionalFormatWidgetStack->hide();
68 mConditionalFormatWidgetStack->setMainPanel( mConditionalFormatWidget );
72 mConditionalSplitter->restoreState( settings.
value( QStringLiteral(
"/qgis/attributeTable/splitterState" ), QByteArray() ).toByteArray() );
74 mPreviewColumnsMenu =
new QMenu(
this );
75 mActionPreviewColumnsMenu->setMenu( mPreviewColumnsMenu );
81 connect( mActionExpressionPreview, &QAction::triggered,
this, &QgsDualView::previewExpressionBuilder );
90 auto createShortcuts = [ = ](
const QString & objectName, void (
QgsFeatureListView::* slot )() )
96 connect( sc, &QShortcut::activated, mFeatureListView, slot );
103 QButtonGroup *buttonGroup =
new QButtonGroup(
this );
104 buttonGroup->setExclusive(
false );
108 QAbstractButton *bt = buttonGroup->button(
static_cast<int>( action ) );
110 bt->setChecked(
true );
111 connect( buttonGroup, qOverload< QAbstractButton *, bool >( &QButtonGroup::buttonToggled ),
this, &QgsDualView::panZoomGroupButtonToggled );
112 mFlashButton->setChecked(
QgsSettings().value( QStringLiteral(
"/qgis/attributeTable/featureListHighlightFeature" ),
true ).toBool() );
113 connect( mFlashButton, &QToolButton::clicked,
this, &QgsDualView::flashButtonClicked );
119 settings.
setValue( QStringLiteral(
"/qgis/attributeTable/splitterState" ), mConditionalSplitter->saveState() );
128 delete mAttributeForm;
129 mAttributeForm =
nullptr;
139 mEditorContext = context;
146 const bool needsGeometry = mLayer->conditionalStyles()->rulesNeedGeometry() ||
152 initLayerCache( needsGeometry );
153 initModels( mapCanvas, request, loadFeatures );
155 mConditionalFormatWidget->
setLayer( mLayer );
157 mTableView->setModel( mFilterModel );
158 mFeatureListView->setModel( mFeatureListModel );
163 if ( mFeatureListPreviewButton->defaultAction() )
164 mFeatureListView->setDisplayExpression( mDisplayExpression );
171 if ( showFirstFeature && mFeatureListModel->
rowCount( ) > 0 )
175void QgsDualView::initAttributeForm(
const QgsFeature &feature )
177 Q_ASSERT( !mAttributeForm );
183 mAttributeEditorScrollArea->setWidgetResizable(
true );
184 mAttributeEditor->layout()->addWidget( mAttributeEditorScrollArea );
185 mAttributeEditorScrollArea->setWidget( mAttributeForm );
189 mAttributeEditor->layout()->addWidget( mAttributeForm );
194 mAttributeForm->setMinimumWidth( 200 );
205 QgsMapCanvasUtils::flashMatchingFeatures( canvas, mLayer, filter );
212 QgsMapCanvasUtils::zoomToMatchingFeatures( canvas, mLayer, filter );
219void QgsDualView::columnBoxInit()
222 const QList<QgsField> fields = mLayer->fields().toList();
224 const QString defaultField;
226 mFeatureListPreviewButton->addAction( mActionExpressionPreview );
227 mFeatureListPreviewButton->addAction( mActionPreviewColumnsMenu );
229 const auto constFields = fields;
230 for (
const QgsField &field : constFields )
232 const int fieldIndex = mLayer->fields().lookupField( field.name() );
233 if ( fieldIndex == -1 )
236 const QString fieldName = field.name();
239 const QIcon icon = mLayer->fields().iconForField( fieldIndex );
240 const QString text = mLayer->attributeDisplayName( fieldIndex );
243 QAction *previewAction =
new QAction( icon, text, mFeatureListPreviewButton );
244 connect( previewAction, &QAction::triggered,
this, [ = ] { previewColumnChanged( previewAction, fieldName ); } );
245 mPreviewColumnsMenu->addAction( previewAction );
247 if ( text == defaultField )
249 mFeatureListPreviewButton->setDefaultAction( previewAction );
254 QMenu *sortMenu =
new QMenu(
this );
256 sortMenuAction->setMenu( sortMenu );
258 QAction *sortByPreviewExpressionAsc =
new QAction(
QgsApplication::getThemeIcon( QStringLiteral(
"sort.svg" ) ), tr(
"By Preview Expression (ascending)" ),
this );
259 connect( sortByPreviewExpressionAsc, &QAction::triggered,
this, [ = ]()
263 sortMenu->addAction( sortByPreviewExpressionAsc );
264 QAction *sortByPreviewExpressionDesc =
new QAction(
QgsApplication::getThemeIcon( QStringLiteral(
"sort-reverse.svg" ) ), tr(
"By Preview Expression (descending)" ),
this );
265 connect( sortByPreviewExpressionDesc, &QAction::triggered,
this, [ = ]()
269 sortMenu->addAction( sortByPreviewExpressionDesc );
270 QAction *sortByPreviewExpressionCustom =
new QAction(
QgsApplication::getThemeIcon( QStringLiteral(
"mIconExpressionPreview.svg" ) ), tr(
"By Custom Expression" ),
this );
271 connect( sortByPreviewExpressionCustom, &QAction::triggered,
this, [ = ]()
276 sortMenu->addAction( sortByPreviewExpressionCustom );
278 mFeatureListPreviewButton->addAction( sortMenuAction );
280 QAction *separator =
new QAction( mFeatureListPreviewButton );
281 separator->setSeparator(
true );
282 mFeatureListPreviewButton->addAction( separator );
283 restoreRecentDisplayExpressions();
286 if ( !mFeatureListPreviewButton->defaultAction() )
288 mFeatureListView->setDisplayExpression( mLayer->displayExpression() );
289 mFeatureListPreviewButton->setDefaultAction( mActionExpressionPreview );
290 const QString displayExpression = mFeatureListView->displayExpression();
291 setDisplayExpression( displayExpression.isEmpty() ? tr(
"'[Please define preview text]'" ) : displayExpression );
295 mFeatureListPreviewButton->defaultAction()->trigger();
301 setCurrentIndex(
view );
348 || ( mMasterModel->
rowCount() == 0 );
379 filterFeatures( QStringLiteral(
"is_feature_valid() = false" ), context );
389 if ( !filterExpression.isEmpty() )
406 setBrowsingAutoPanScaleAllowed(
false );
414 setBrowsingAutoPanScaleAllowed(
true );
418 if ( requiresTableReload )
424 whileBlocking( mLayerCache )->setCacheGeometry( needsGeometry );
438void QgsDualView::initLayerCache(
bool cacheGeometry )
442 const int cacheSize = settings.
value( QStringLiteral(
"qgis/attributeTableRowCache" ),
"10000" ).toInt();
449 rebuildFullLayerCache();
455 delete mFeatureListModel;
476 connect( mMasterModel, &QgsAttributeTableModel::rowsRemoved, mFilterModel, &QgsAttributeTableFilterModel::invalidate );
477 connect( mMasterModel, &QgsAttributeTableModel::rowsInserted, mFilterModel, &QgsAttributeTableFilterModel::invalidate );
484void QgsDualView::restoreRecentDisplayExpressions()
486 const QVariantList previewExpressions = mLayer->customProperty( QStringLiteral(
"dualview/previewExpressions" ) ).toList();
488 for (
const QVariant &previewExpression : previewExpressions )
489 insertRecentlyUsedDisplayExpression( previewExpression.toString() );
492void QgsDualView::saveRecentDisplayExpressions()
const
498 const QList<QAction *> actions = mFeatureListPreviewButton->actions();
501 int index = actions.indexOf( mLastDisplayExpressionAction );
504 QVariantList previewExpressions;
505 for ( ; index < actions.length(); ++index )
507 QAction *action = actions.at( index );
508 previewExpressions << action->property(
"previewExpression" );
511 mLayer->setCustomProperty( QStringLiteral(
"dualview/previewExpressions" ), previewExpressions );
515void QgsDualView::setDisplayExpression(
const QString &expression )
517 mDisplayExpression = expression;
518 insertRecentlyUsedDisplayExpression( expression );
521void QgsDualView::insertRecentlyUsedDisplayExpression(
const QString &expression )
523 const QList<QAction *> actions = mFeatureListPreviewButton->actions();
526 const int index = actions.indexOf( mLastDisplayExpressionAction );
529 for (
int i = 0; index + i < actions.length(); ++i )
531 QAction *action = actions.at( index );
532 if ( action->text() == expression || i >= 9 )
534 if ( action == mLastDisplayExpressionAction )
535 mLastDisplayExpressionAction =
nullptr;
536 mFeatureListPreviewButton->removeAction( action );
540 if ( !mLastDisplayExpressionAction )
541 mLastDisplayExpressionAction = action;
546 QString name = expression;
548 if ( expression.startsWith( QLatin1String(
"COALESCE( \"" ) ) && expression.endsWith( QLatin1String(
", '<NULL>' )" ) ) )
550 name = expression.mid( 11, expression.length() - 24 );
552 const int fieldIndex = mLayer->fields().indexOf( name );
553 if ( fieldIndex != -1 )
555 name = mLayer->attributeDisplayName( fieldIndex );
556 icon = mLayer->fields().iconForField( fieldIndex );
564 QAction *previewAction =
new QAction( icon, name, mFeatureListPreviewButton );
565 previewAction->setProperty(
"previewExpression", expression );
566 connect( previewAction, &QAction::triggered,
this, [expression,
this](
bool )
568 setDisplayExpression( expression );
569 mFeatureListPreviewButton->setText( expression );
573 mFeatureListPreviewButton->insertAction( mLastDisplayExpressionAction, previewAction );
574 mLastDisplayExpressionAction = previewAction;
577void QgsDualView::updateEditSelectionProgress(
int progress,
int count )
579 mProgressCount->setText( QStringLiteral(
"%1 / %2" ).arg( progress + 1 ).arg( count ) );
580 mPreviousFeatureButton->setEnabled( progress > 0 );
581 mNextFeatureButton->setEnabled( progress + 1 < count );
582 mFirstFeatureButton->setEnabled( progress > 0 );
583 mLastFeatureButton->setEnabled( progress + 1 < count );
584 if ( mAttributeForm )
586 mAttributeForm->setVisible( count > 0 );
590void QgsDualView::panOrZoomToFeature(
const QgsFeatureIds &featureset )
595 if ( mBrowsingAutoPanScaleAllowed )
597 if ( mAutoPanButton->isChecked() )
598 QTimer::singleShot( 0,
this, [ = ]()
602 else if ( mAutoZoomButton->isChecked() )
603 QTimer::singleShot( 0,
this, [ = ]()
608 if ( mFlashButton->isChecked() )
609 QTimer::singleShot( 0,
this, [ = ]()
613 mLastFeatureSet = featureset;
617void QgsDualView::setBrowsingAutoPanScaleAllowed(
bool allowed )
619 if ( mBrowsingAutoPanScaleAllowed == allowed )
622 mBrowsingAutoPanScaleAllowed = allowed;
624 mAutoPanButton->setEnabled( allowed );
625 mAutoZoomButton->setEnabled( allowed );
627 const QString disabledHint = tr(
"(disabled when attribute table only shows features visible in the current map canvas extent)" );
629 mAutoPanButton->setToolTip( tr(
"Automatically pan to the current feature" ) + ( allowed ? QString() : QString(
' ' ) + disabledHint ) );
630 mAutoZoomButton->setToolTip( tr(
"Automatically zoom to the current feature" ) + ( allowed ? QString() : QString(
' ' ) + disabledHint ) );
633void QgsDualView::panZoomGroupButtonToggled( QAbstractButton *button,
bool checked )
635 if ( button == mAutoPanButton && checked )
638 mAutoZoomButton->setChecked(
false );
640 else if ( button == mAutoZoomButton && checked )
643 mAutoPanButton->setChecked(
false );
650 if ( checked && mLayer->isSpatial() )
651 panOrZoomToFeature( mFeatureListView->currentEditSelection() );
654void QgsDualView::flashButtonClicked(
bool clicked )
656 QgsSettings().
setValue( QStringLiteral(
"/qgis/attributeTable/featureListHighlightFeature" ), clicked );
663 canvas->
flashFeatureIds( mLayer, mFeatureListView->currentEditSelection() );
666void QgsDualView::filterError(
const QString &errorMessage )
674void QgsDualView::featureListAboutToChangeEditSelection(
bool &ok )
676 if ( !mAttributeForm )
679 if ( mLayer->isEditable() && !mAttributeForm->
save() )
683void QgsDualView::featureListCurrentEditSelectionChanged(
const QgsFeature &feat )
685 if ( !mAttributeForm )
687 initAttributeForm( feat );
689 else if ( !mLayer->isEditable() || mAttributeForm->
save() )
693 featureset << feat.
id();
696 if ( mLayer->isSpatial() )
697 panOrZoomToFeature( featureset );
708 mFeatureListView->setCurrentFeatureEdited(
false );
709 mFeatureListView->setEditSelection( fids );
714 return mAttributeForm ? mAttributeForm->
save() :
false;
719 mConditionalFormatWidgetStack->setVisible( !mConditionalFormatWidgetStack->isVisible() );
724 if ( !mAttributeForm )
729 mPreviousView =
view();
742 if ( !mAttributeForm )
749 mAttributeForm->setVisible(
true );
754 mAttributeForm->setVisible( mFilterModel->rowCount( ) > 0 );
759void QgsDualView::previewExpressionBuilder()
765 dlg.setWindowTitle( tr(
"Expression Based Preview" ) );
766 dlg.setExpressionText( mFeatureListView->displayExpression() );
768 if ( dlg.exec() == QDialog::Accepted )
770 mFeatureListView->setDisplayExpression( dlg.expressionText() );
771 mFeatureListPreviewButton->setDefaultAction( mActionExpressionPreview );
772 mFeatureListPreviewButton->setPopupMode( QToolButton::MenuButtonPopup );
775 setDisplayExpression( mFeatureListView->displayExpression() );
778void QgsDualView::previewColumnChanged( QAction *previewAction,
const QString &expression )
780 if ( !mFeatureListView->setDisplayExpression( QStringLiteral(
"COALESCE( \"%1\", '<NULL>' )" ).arg( expression ) ) )
782 QMessageBox::warning(
this,
783 tr(
"Column Preview" ),
784 tr(
"Could not set column '%1' as preview column.\nParser error:\n%2" )
785 .arg( previewAction->text(), mFeatureListView->parserErrorString() )
790 mFeatureListPreviewButton->setText( previewAction->text() );
791 mFeatureListPreviewButton->setIcon( previewAction->icon() );
792 mFeatureListPreviewButton->setPopupMode( QToolButton::InstantPopup );
795 setDisplayExpression( mFeatureListView->displayExpression() );
805 return mFilterModel->rowCount();
810 const QModelIndex currentIndex = mTableView->currentIndex();
811 if ( !currentIndex.isValid() )
816 const QVariant var = mMasterModel->
data( currentIndex, Qt::DisplayRole );
817 QApplication::clipboard()->setText( var.toString() );
823 mProgressDlg->cancel();
828 if ( mAttributeForm )
837 saveRecentDisplayExpressions();
840void QgsDualView::viewWillShowContextMenu( QMenu *menu,
const QModelIndex &masterIndex )
847 QAction *copyContentAction = menu->addAction( tr(
"Copy Cell Content" ) );
848 menu->addAction( copyContentAction );
849 connect( copyContentAction, &QAction::triggered,
this, [masterIndex,
this]
851 const QVariant var = mMasterModel->
data( masterIndex, Qt::DisplayRole );
852 QApplication::clipboard()->setText( var.toString() );
857 if ( canvas && vl && vl->isSpatial() )
859 QAction *zoomToFeatureAction = menu->addAction( tr(
"Zoom to Feature" ) );
860 connect( zoomToFeatureAction, &QAction::triggered,
this, &QgsDualView::zoomToCurrentFeature );
862 QAction *panToFeatureAction = menu->addAction( tr(
"Pan to Feature" ) );
863 connect( panToFeatureAction, &QAction::triggered,
this, &QgsDualView::panToCurrentFeature );
865 QAction *flashFeatureAction = menu->addAction( tr(
"Flash Feature" ) );
866 connect( flashFeatureAction, &QAction::triggered,
this, &QgsDualView::flashCurrentFeature );
870 const QList<QgsAction> actions = mLayer->actions()->actions( QStringLiteral(
"Field" ) );
871 if ( !actions.isEmpty() )
873 QAction *a = menu->addAction( tr(
"Run Layer Action" ) );
874 a->setEnabled(
false );
876 for (
const QgsAction &action : actions )
878 if ( !action.runable() )
881 if ( vl && !vl->isEditable() && action.isEnabledOnlyWhenEditable() )
888 const QModelIndex rowSourceIndex = mMasterModel->index( masterIndex.row(), 0 );
889 if ( ! rowSourceIndex.isValid() )
897 if ( !registeredActions.isEmpty() )
900 menu->addSeparator();
912 if ( mLayer->selectedFeatureCount() > 1 && mLayer->selectedFeatureIds().contains( currentFid ) )
915 if ( !registeredActions.isEmpty() )
917 menu->addSeparator();
918 QAction *action = menu->addAction( tr(
"Actions on Selection (%1)" ).arg( mLayer->selectedFeatureCount() ) );
919 action->setEnabled(
false );
924 menu->addAction( action->text(), action, [ = ]()
926 Q_NOWARN_DEPRECATED_PUSH
927 action->triggerForFeatures( mLayer, mLayer->selectedFeatures() );
928 Q_NOWARN_DEPRECATED_POP
929 action->triggerForFeatures( mLayer, mLayer->selectedFeatures(), context );
935 menu->addSeparator();
941void QgsDualView::widgetWillShowContextMenu(
QgsActionMenu *menu,
const QModelIndex &atIndex )
947void QgsDualView::showViewHeaderMenu( QPoint point )
949 const int col = mTableView->columnAt( point.x() );
951 delete mHorizontalHeaderMenu;
952 mHorizontalHeaderMenu =
new QMenu(
this );
954 QAction *hide =
new QAction( tr(
"&Hide Column" ), mHorizontalHeaderMenu );
955 connect( hide, &QAction::triggered,
this, &QgsDualView::hideColumn );
956 hide->setData( col );
957 mHorizontalHeaderMenu->addAction( hide );
958 QAction *setWidth =
new QAction( tr(
"&Set Width…" ), mHorizontalHeaderMenu );
959 connect( setWidth, &QAction::triggered,
this, &QgsDualView::resizeColumn );
960 setWidth->setData( col );
961 mHorizontalHeaderMenu->addAction( setWidth );
963 QAction *setWidthAllColumns =
new QAction( tr(
"&Set All Column Widths…" ), mHorizontalHeaderMenu );
964 connect( setWidthAllColumns, &QAction::triggered,
this, &QgsDualView::resizeAllColumns );
965 setWidthAllColumns->setData( col );
966 mHorizontalHeaderMenu->addAction( setWidthAllColumns );
968 QAction *optimizeWidth =
new QAction( tr(
"&Autosize" ), mHorizontalHeaderMenu );
969 connect( optimizeWidth, &QAction::triggered,
this, &QgsDualView::autosizeColumn );
970 optimizeWidth->setData( col );
971 mHorizontalHeaderMenu->addAction( optimizeWidth );
973 QAction *optimizeWidthAllColumns =
new QAction( tr(
"&Autosize All Columns" ), mHorizontalHeaderMenu );
974 connect( optimizeWidthAllColumns, &QAction::triggered,
this, &QgsDualView::autosizeAllColumns );
975 mHorizontalHeaderMenu->addAction( optimizeWidthAllColumns );
978 mHorizontalHeaderMenu->addSeparator();
979 QAction *organize =
new QAction( tr(
"&Organize Columns…" ), mHorizontalHeaderMenu );
980 connect( organize, &QAction::triggered,
this, &QgsDualView::organizeColumns );
981 mHorizontalHeaderMenu->addAction( organize );
982 QAction *sort =
new QAction( tr(
"&Sort…" ), mHorizontalHeaderMenu );
983 connect( sort, &QAction::triggered,
this, [ = ]() {modifySort();} );
984 mHorizontalHeaderMenu->addAction( sort );
986 mHorizontalHeaderMenu->popup( mTableView->horizontalHeader()->mapToGlobal( point ) );
989void QgsDualView::organizeColumns()
997 if ( dialog.exec() == QDialog::Accepted )
1004void QgsDualView::tableColumnResized(
int column,
int width )
1008 if ( sourceCol >= 0 && config.
columnWidth( sourceCol ) != width )
1015void QgsDualView::hideColumn()
1017 QAction *action = qobject_cast<QAction *>( sender() );
1018 const int col = action->data().toInt();
1021 if ( sourceCol >= 0 )
1028void QgsDualView::resizeColumn()
1030 QAction *action = qobject_cast<QAction *>( sender() );
1031 const int col = action->data().toInt();
1037 if ( sourceCol >= 0 )
1040 const int width = QInputDialog::getInt(
this, tr(
"Set column width" ), tr(
"Enter column width" ),
1041 mTableView->columnWidth( col ),
1051void QgsDualView::resizeAllColumns()
1053 QAction *action = qobject_cast<QAction *>( sender() );
1054 const int col = action->data().toInt();
1061 const int width = QInputDialog::getInt(
this, tr(
"Set Column Width" ), tr(
"Enter column width" ),
1062 mTableView->columnWidth( col ),
1066 const int colCount = mTableView->model()->columnCount();
1069 for (
int i = 0; i < colCount; i++ )
1078void QgsDualView::autosizeColumn()
1080 QAction *action = qobject_cast<QAction *>( sender() );
1081 const int col = action->data().toInt();
1082 mTableView->resizeColumnToContents( col );
1085void QgsDualView::autosizeAllColumns()
1087 mTableView->resizeColumnsToContents();
1090bool QgsDualView::modifySort()
1098 orderByDlg.setWindowTitle( tr(
"Configure Attribute Table Sort Order" ) );
1099 QDialogButtonBox *dialogButtonBox =
new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
1100 QGridLayout *layout =
new QGridLayout();
1101 connect( dialogButtonBox, &QDialogButtonBox::accepted, &orderByDlg, &QDialog::accept );
1102 connect( dialogButtonBox, &QDialogButtonBox::rejected, &orderByDlg, &QDialog::reject );
1103 orderByDlg.setLayout( layout );
1105 QGroupBox *sortingGroupBox =
new QGroupBox();
1106 sortingGroupBox->setTitle( tr(
"Defined sort order in attribute table" ) );
1107 sortingGroupBox->setCheckable(
true );
1109 layout->addWidget( sortingGroupBox );
1110 sortingGroupBox->setLayout(
new QGridLayout() );
1115 expressionBuilder->
initWithLayer( mLayer, context, QStringLiteral(
"generic" ) );
1118 sortingGroupBox->layout()->addWidget( expressionBuilder );
1120 QCheckBox *cbxSortAscending =
new QCheckBox( tr(
"Sort ascending" ) );
1121 cbxSortAscending->setChecked( config.
sortOrder() == Qt::AscendingOrder );
1122 sortingGroupBox->layout()->addWidget( cbxSortAscending );
1124 layout->addWidget( dialogButtonBox );
1125 if ( orderByDlg.exec() )
1127 const Qt::SortOrder sortOrder = cbxSortAscending->isChecked() ? Qt::AscendingOrder : Qt::DescendingOrder;
1128 if ( sortingGroupBox->isChecked() )
1151 QSet<int> attributes;
1155 const QVector<QgsAttributeTableConfig::ColumnConfig> constColumnconfigs { config.
columns() };
1164 const QSet<int> colAttrs { attributes };
1165 for (
const int attrIdx : std::as_const( colAttrs ) )
1174 std::sort( attrs.begin(), attrs.end() );
1178void QgsDualView::zoomToCurrentFeature()
1180 const QModelIndex currentIndex = mTableView->currentIndex();
1181 if ( !currentIndex.isValid() )
1187 ids.insert( mFilterModel->
rowToId( currentIndex ) );
1195void QgsDualView::panToCurrentFeature()
1197 const QModelIndex currentIndex = mTableView->currentIndex();
1198 if ( !currentIndex.isValid() )
1204 ids.insert( mFilterModel->
rowToId( currentIndex ) );
1212void QgsDualView::flashCurrentFeature()
1214 const QModelIndex currentIndex = mTableView->currentIndex();
1215 if ( !currentIndex.isValid() )
1221 ids.insert( mFilterModel->
rowToId( currentIndex ) );
1229void QgsDualView::rebuildFullLayerCache()
1237void QgsDualView::previewExpressionChanged(
const QString &expression )
1239 mLayer->setDisplayExpression( expression );
1242void QgsDualView::onSortColumnChanged()
1246 cfg.
sortOrder() != mFilterModel->sortOrder() )
1254void QgsDualView::updateSelectedFeatures()
1266void QgsDualView::updateEditedAddedFeatures()
1278void QgsDualView::extentChanged()
1291void QgsDualView::featureFormAttributeChanged(
const QString &attribute,
const QVariant &value,
bool attributeChanged )
1293 Q_UNUSED( attribute )
1295 if ( attributeChanged )
1297 mFeatureListView->setCurrentFeatureEdited(
true );
1298 mAttributeForm->
save();
1321 mTableView->setFeatureSelectionManager( featureSelectionManager );
1322 mFeatureListView->setFeatureSelectionManager( featureSelectionManager );
1324 if ( mFeatureSelectionManager && mFeatureSelectionManager->parent() ==
this )
1325 delete mFeatureSelectionManager;
1327 mFeatureSelectionManager = featureSelectionManager;
1333 mConfig.
update( mLayer->fields() );
1334 mLayer->setAttributeTableConfig( mConfig );
1336 mTableView->setAttributeTableConfig( mConfig );
1354 mFilterModel->
sort( -1 );
1373void QgsDualView::progress(
int i,
bool &cancel )
1375 if ( !mProgressDlg )
1377 mProgressDlg =
new QProgressDialog( tr(
"Loading features…" ), tr(
"Abort" ), 0, 0,
this );
1378 mProgressDlg->setWindowTitle( tr(
"Attribute Table" ) );
1379 mProgressDlg->setWindowModality( Qt::WindowModal );
1380 mProgressDlg->show();
1383 mProgressDlg->setLabelText( tr(
"%L1 features loaded." ).arg( i ) );
1384 QCoreApplication::processEvents();
1386 cancel = mProgressDlg && mProgressDlg->wasCanceled();
1389void QgsDualView::finished()
1391 delete mProgressDlg;
1392 mProgressDlg =
nullptr;
@ SelectAtId
Fast access to features using their ID.
@ 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.
@ Expression
Field is calculated from an expression.
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.
@ 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()
Emitted when the 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 finished()
Emitted when the model has completely loaded all features.
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").
bool needsGeometry() const
Returns true if the expression uses feature geometry for some computation.
QSet< int > referencedAttributeIndexes(const QgsFields &fields) const
Returns a list of field name indexes obtained from the provided fields.
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.
Qgis::FieldOrigin fieldOrigin(int fieldIdx) const
Returns the field's origin (value from an enumeration).
Q_INVOKABLE int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
static QgsEditorWidgetRegistry * editorWidgetRegistry()
Returns the global editor widget registry, used for managing all known edit widget factories.
static QgsShortcutsManager * shortcutsManager()
Returns the global shortcuts manager, used for managing a QAction and QShortcut sequences.
static QgsMapLayerActionRegistry * mapLayerActionRegistry()
Returns the global map layer action registry, used for registering map layer actions.
Is an interface class to abstract feature selection handling.
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.
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.
QString expressionField(int index) const
Returns the expression used for a given expression field.
void afterCommitChanges()
Emitted after changes are committed to the data provider.
QgsAttributeTableConfig attributeTableConfig() const
Returns the attribute table configuration object.
void selectionChanged(const QgsFeatureIds &selected, const QgsFeatureIds &deselected, bool clearAndSelect)
Emitted when selection was changed.
void updatedFields()
Emitted whenever the fields available from this layer have been changed.
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.