19 #include <QMessageBox>
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;
147 initLayerCache( needsGeometry );
148 initModels( mapCanvas, request, loadFeatures );
150 mConditionalFormatWidget->
setLayer( mLayer );
152 mTableView->setModel( mFilterModel );
153 mFeatureListView->setModel( mFeatureListModel );
157 if ( mFeatureListPreviewButton->defaultAction() )
158 mFeatureListView->setDisplayExpression( mDisplayExpression );
165 if ( showFirstFeature && mFeatureListModel->
rowCount( ) > 0 )
166 mFeatureListView->setEditSelection(
QgsFeatureIds() << mFeatureListModel->
data( mFeatureListModel->index( 0, 0 ), QgsFeatureListModel::Role::FeatureRole ).value<
QgsFeature>().
id() );
169 void QgsDualView::initAttributeForm(
const QgsFeature &feature )
171 Q_ASSERT( !mAttributeForm );
177 mAttributeEditorScrollArea->setWidgetResizable(
true );
178 mAttributeEditor->layout()->addWidget( mAttributeEditorScrollArea );
179 mAttributeEditorScrollArea->setWidget( mAttributeForm );
183 mAttributeEditor->layout()->addWidget( mAttributeForm );
195 QgsMapCanvasUtils::flashMatchingFeatures( canvas, mLayer, filter );
202 QgsMapCanvasUtils::zoomToMatchingFeatures( canvas, mLayer, filter );
209 void QgsDualView::columnBoxInit()
212 const QList<QgsField> fields = mLayer->fields().toList();
214 const QString defaultField;
217 QString displayExpression = mLayer->displayExpression();
219 if ( displayExpression.isEmpty() )
222 displayExpression = QStringLiteral(
"'[Please define preview text]'" );
225 mFeatureListPreviewButton->addAction( mActionExpressionPreview );
226 mFeatureListPreviewButton->addAction( mActionPreviewColumnsMenu );
228 const auto constFields = fields;
231 const int fieldIndex = mLayer->fields().lookupField(
field.
name() );
232 if ( fieldIndex == -1 )
238 const QIcon icon = mLayer->fields().iconForField( fieldIndex );
239 const QString text = mLayer->attributeDisplayName( fieldIndex );
242 QAction *previewAction =
new QAction( icon, text, mFeatureListPreviewButton );
243 connect( previewAction, &QAction::triggered,
this, [ = ] { previewColumnChanged( previewAction, fieldName ); } );
244 mPreviewColumnsMenu->addAction( previewAction );
246 if ( text == defaultField )
248 mFeatureListPreviewButton->setDefaultAction( previewAction );
253 QMenu *sortMenu =
new QMenu(
this );
255 sortMenuAction->setMenu( sortMenu );
257 QAction *sortByPreviewExpressionAsc =
new QAction(
QgsApplication::getThemeIcon( QStringLiteral(
"sort.svg" ) ), tr(
"By Preview Expression (ascending)" ),
this );
258 connect( sortByPreviewExpressionAsc, &QAction::triggered,
this, [ = ]()
262 sortMenu->addAction( sortByPreviewExpressionAsc );
263 QAction *sortByPreviewExpressionDesc =
new QAction(
QgsApplication::getThemeIcon( QStringLiteral(
"sort-reverse.svg" ) ), tr(
"By Preview Expression (descending)" ),
this );
264 connect( sortByPreviewExpressionDesc, &QAction::triggered,
this, [ = ]()
268 sortMenu->addAction( sortByPreviewExpressionDesc );
269 QAction *sortByPreviewExpressionCustom =
new QAction(
QgsApplication::getThemeIcon( QStringLiteral(
"mIconExpressionPreview.svg" ) ), tr(
"By Custom Expression" ),
this );
270 connect( sortByPreviewExpressionCustom, &QAction::triggered,
this, [ = ]()
275 sortMenu->addAction( sortByPreviewExpressionCustom );
277 mFeatureListPreviewButton->addAction( sortMenuAction );
279 QAction *separator =
new QAction( mFeatureListPreviewButton );
280 separator->setSeparator(
true );
281 mFeatureListPreviewButton->addAction( separator );
282 restoreRecentDisplayExpressions();
285 if ( !mFeatureListPreviewButton->defaultAction() )
287 mFeatureListView->setDisplayExpression( displayExpression );
288 mFeatureListPreviewButton->setDefaultAction( mActionExpressionPreview );
289 setDisplayExpression( mFeatureListView->displayExpression() );
293 mFeatureListPreviewButton->defaultAction()->trigger();
299 setCurrentIndex(
view );
339 || ( mMasterModel->
rowCount() == 0 );
341 if ( !needsGeometry )
385 setBrowsingAutoPanScaleAllowed(
false );
392 setBrowsingAutoPanScaleAllowed(
true );
396 if ( requiresTableReload )
402 whileBlocking( mLayerCache )->setCacheGeometry( needsGeometry );
416 void QgsDualView::initLayerCache(
bool cacheGeometry )
420 const int cacheSize = settings.
value( QStringLiteral(
"qgis/attributeTableRowCache" ),
"10000" ).toInt();
426 rebuildFullLayerCache();
432 delete mFeatureListModel;
453 connect( mMasterModel, &QgsAttributeTableModel::rowsRemoved, mFilterModel, &QgsAttributeTableFilterModel::invalidate );
454 connect( mMasterModel, &QgsAttributeTableModel::rowsInserted, mFilterModel, &QgsAttributeTableFilterModel::invalidate );
462 void QgsDualView::restoreRecentDisplayExpressions()
464 const QVariantList previewExpressions = mLayer->customProperty( QStringLiteral(
"dualview/previewExpressions" ) ).toList();
466 for (
const QVariant &previewExpression : previewExpressions )
467 insertRecentlyUsedDisplayExpression( previewExpression.toString() );
470 void QgsDualView::saveRecentDisplayExpressions()
const
476 const QList<QAction *> actions = mFeatureListPreviewButton->actions();
479 int index = actions.indexOf( mLastDisplayExpressionAction );
482 QVariantList previewExpressions;
483 for ( ; index < actions.length(); ++index )
485 QAction *action = actions.at( index );
486 previewExpressions << action->property(
"previewExpression" );
489 mLayer->setCustomProperty( QStringLiteral(
"dualview/previewExpressions" ), previewExpressions );
493 void QgsDualView::setDisplayExpression(
const QString &expression )
495 mDisplayExpression = expression;
496 insertRecentlyUsedDisplayExpression( expression );
499 void QgsDualView::insertRecentlyUsedDisplayExpression(
const QString &expression )
501 const QList<QAction *> actions = mFeatureListPreviewButton->actions();
504 const int index = actions.indexOf( mLastDisplayExpressionAction );
507 for (
int i = 0; index + i < actions.length(); ++i )
509 QAction *action = actions.at( index );
510 if ( action->text() == expression || i >= 9 )
512 if ( action == mLastDisplayExpressionAction )
513 mLastDisplayExpressionAction =
nullptr;
514 mFeatureListPreviewButton->removeAction( action );
518 if ( !mLastDisplayExpressionAction )
519 mLastDisplayExpressionAction = action;
524 QString name = expression;
526 if ( expression.startsWith( QLatin1String(
"COALESCE( \"" ) ) && expression.endsWith( QLatin1String(
", '<NULL>' )" ) ) )
528 name = expression.mid( 11, expression.length() - 24 );
530 const int fieldIndex = mLayer->fields().indexOf( name );
531 if ( fieldIndex != -1 )
533 name = mLayer->attributeDisplayName( fieldIndex );
534 icon = mLayer->fields().iconForField( fieldIndex );
542 QAction *previewAction =
new QAction( icon, name, mFeatureListPreviewButton );
543 previewAction->setProperty(
"previewExpression", expression );
544 connect( previewAction, &QAction::triggered,
this, [expression,
this](
bool )
546 setDisplayExpression( expression );
547 mFeatureListPreviewButton->setText( expression );
551 mFeatureListPreviewButton->insertAction( mLastDisplayExpressionAction, previewAction );
552 mLastDisplayExpressionAction = previewAction;
555 void QgsDualView::updateEditSelectionProgress(
int progress,
int count )
557 mProgressCount->setText( QStringLiteral(
"%1 / %2" ).arg( progress + 1 ).arg( count ) );
558 mPreviousFeatureButton->setEnabled( progress > 0 );
559 mNextFeatureButton->setEnabled( progress + 1 < count );
560 mFirstFeatureButton->setEnabled( progress > 0 );
561 mLastFeatureButton->setEnabled( progress + 1 < count );
562 if ( mAttributeForm )
564 mAttributeForm->setVisible( count > 0 );
568 void QgsDualView::panOrZoomToFeature(
const QgsFeatureIds &featureset )
573 if ( mBrowsingAutoPanScaleAllowed )
575 if ( mAutoPanButton->isChecked() )
576 QTimer::singleShot( 0,
this, [ = ]()
580 else if ( mAutoZoomButton->isChecked() )
581 QTimer::singleShot( 0,
this, [ = ]()
586 if ( mFlashButton->isChecked() )
587 QTimer::singleShot( 0,
this, [ = ]()
591 mLastFeatureSet = featureset;
595 void QgsDualView::setBrowsingAutoPanScaleAllowed(
bool allowed )
597 if ( mBrowsingAutoPanScaleAllowed == allowed )
600 mBrowsingAutoPanScaleAllowed = allowed;
602 mAutoPanButton->setEnabled( allowed );
603 mAutoZoomButton->setEnabled( allowed );
605 const QString disabledHint = tr(
"(disabled when attribute table only shows features visible in the current map canvas extent)" );
607 mAutoPanButton->setToolTip( tr(
"Automatically pan to the current feature" ) + ( allowed ? QString() : QString(
' ' ) + disabledHint ) );
608 mAutoZoomButton->setToolTip( tr(
"Automatically zoom to the current feature" ) + ( allowed ? QString() : QString(
' ' ) + disabledHint ) );
611 void QgsDualView::panZoomGroupButtonToggled( QAbstractButton *button,
bool checked )
613 if ( button == mAutoPanButton && checked )
616 mAutoZoomButton->setChecked(
false );
618 else if ( button == mAutoZoomButton && checked )
621 mAutoPanButton->setChecked(
false );
628 if ( checked && mLayer->isSpatial() )
629 panOrZoomToFeature( mFeatureListView->currentEditSelection() );
632 void QgsDualView::flashButtonClicked(
bool clicked )
634 QgsSettings().
setValue( QStringLiteral(
"/qgis/attributeTable/featureListHighlightFeature" ), clicked );
641 canvas->
flashFeatureIds( mLayer, mFeatureListView->currentEditSelection() );
644 void QgsDualView::filterError(
const QString &errorMessage )
652 void QgsDualView::featureListAboutToChangeEditSelection(
bool &ok )
654 if ( !mAttributeForm )
657 if ( mLayer->isEditable() && !mAttributeForm->
save() )
661 void QgsDualView::featureListCurrentEditSelectionChanged(
const QgsFeature &feat )
663 if ( !mAttributeForm )
665 initAttributeForm( feat );
667 else if ( !mLayer->isEditable() || mAttributeForm->
save() )
671 featureset << feat.
id();
674 if ( mLayer->isSpatial() )
675 panOrZoomToFeature( featureset );
686 mFeatureListView->setCurrentFeatureEdited(
false );
687 mFeatureListView->setEditSelection( fids );
692 return mAttributeForm ? mAttributeForm->
save() :
false;
697 mConditionalFormatWidgetStack->setVisible( !mConditionalFormatWidgetStack->isVisible() );
702 if ( !mAttributeForm )
707 mPreviousView =
view();
720 if ( !mAttributeForm )
727 mAttributeForm->setVisible(
true );
732 mAttributeForm->setVisible( mFilterModel->rowCount( ) > 0 );
737 void QgsDualView::previewExpressionBuilder()
743 dlg.setWindowTitle( tr(
"Expression Based Preview" ) );
744 dlg.setExpressionText( mFeatureListView->displayExpression() );
746 if ( dlg.exec() == QDialog::Accepted )
748 mFeatureListView->setDisplayExpression( dlg.expressionText() );
749 mFeatureListPreviewButton->setDefaultAction( mActionExpressionPreview );
750 mFeatureListPreviewButton->setPopupMode( QToolButton::MenuButtonPopup );
753 setDisplayExpression( mFeatureListView->displayExpression() );
756 void QgsDualView::previewColumnChanged( QAction *previewAction,
const QString &expression )
758 if ( !mFeatureListView->setDisplayExpression( QStringLiteral(
"COALESCE( \"%1\", '<NULL>' )" ).arg( expression ) ) )
760 QMessageBox::warning(
this,
761 tr(
"Column Preview" ),
762 tr(
"Could not set column '%1' as preview column.\nParser error:\n%2" )
763 .arg( previewAction->text(), mFeatureListView->parserErrorString() )
768 mFeatureListPreviewButton->setText( previewAction->text() );
769 mFeatureListPreviewButton->setIcon( previewAction->icon() );
770 mFeatureListPreviewButton->setPopupMode( QToolButton::InstantPopup );
773 setDisplayExpression( mFeatureListView->displayExpression() );
783 return mFilterModel->rowCount();
788 const QModelIndex currentIndex = mTableView->currentIndex();
789 if ( !currentIndex.isValid() )
794 const QVariant var = mMasterModel->
data( currentIndex, Qt::DisplayRole );
795 QApplication::clipboard()->setText( var.toString() );
801 mProgressDlg->cancel();
806 if ( mAttributeForm )
815 saveRecentDisplayExpressions();
818 void QgsDualView::viewWillShowContextMenu( QMenu *menu,
const QModelIndex &masterIndex )
825 QAction *copyContentAction = menu->addAction( tr(
"Copy Cell Content" ) );
826 menu->addAction( copyContentAction );
827 connect( copyContentAction, &QAction::triggered,
this, [masterIndex,
this]
829 const QVariant var = mMasterModel->
data( masterIndex, Qt::DisplayRole );
830 QApplication::clipboard()->setText( var.toString() );
837 QAction *zoomToFeatureAction = menu->addAction( tr(
"Zoom to Feature" ) );
838 connect( zoomToFeatureAction, &QAction::triggered,
this, &QgsDualView::zoomToCurrentFeature );
840 QAction *panToFeatureAction = menu->addAction( tr(
"Pan to Feature" ) );
841 connect( panToFeatureAction, &QAction::triggered,
this, &QgsDualView::panToCurrentFeature );
843 QAction *flashFeatureAction = menu->addAction( tr(
"Flash Feature" ) );
844 connect( flashFeatureAction, &QAction::triggered,
this, &QgsDualView::flashCurrentFeature );
848 const QList<QgsAction> actions = mLayer->actions()->actions( QStringLiteral(
"Field" ) );
849 if ( !actions.isEmpty() )
851 QAction *a = menu->addAction( tr(
"Run Layer Action" ) );
852 a->setEnabled(
false );
854 for (
const QgsAction &action : actions )
856 if ( !action.runable() )
859 if ( vl && !vl->isEditable() && action.isEnabledOnlyWhenEditable() )
866 const QModelIndex rowSourceIndex = mMasterModel->index( masterIndex.row(), 0 );
867 if ( ! rowSourceIndex.isValid() )
874 if ( !registeredActions.isEmpty() )
877 menu->addSeparator();
889 if ( mLayer->selectedFeatureCount() > 1 && mLayer->selectedFeatureIds().contains( currentFid ) )
892 if ( !registeredActions.isEmpty() )
894 menu->addSeparator();
895 QAction *action = menu->addAction( tr(
"Actions on Selection (%1)" ).arg( mLayer->selectedFeatureCount() ) );
896 action->setEnabled(
false );
900 menu->addAction( action->text(), action, [ = ]() {action->triggerForFeatures( mLayer, mLayer->selectedFeatures() );} );
905 menu->addSeparator();
911 void QgsDualView::widgetWillShowContextMenu(
QgsActionMenu *menu,
const QModelIndex &atIndex )
917 void QgsDualView::showViewHeaderMenu( QPoint point )
919 const int col = mTableView->columnAt( point.x() );
921 delete mHorizontalHeaderMenu;
922 mHorizontalHeaderMenu =
new QMenu(
this );
924 QAction *hide =
new QAction( tr(
"&Hide Column" ), mHorizontalHeaderMenu );
925 connect( hide, &QAction::triggered,
this, &QgsDualView::hideColumn );
926 hide->setData( col );
927 mHorizontalHeaderMenu->addAction( hide );
928 QAction *setWidth =
new QAction( tr(
"&Set Width…" ), mHorizontalHeaderMenu );
929 connect( setWidth, &QAction::triggered,
this, &QgsDualView::resizeColumn );
930 setWidth->setData( col );
931 mHorizontalHeaderMenu->addAction( setWidth );
933 QAction *setWidthAllColumns =
new QAction( tr(
"&Set All Column Widths…" ), mHorizontalHeaderMenu );
934 connect( setWidthAllColumns, &QAction::triggered,
this, &QgsDualView::resizeAllColumns );
935 setWidthAllColumns->setData( col );
936 mHorizontalHeaderMenu->addAction( setWidthAllColumns );
938 QAction *optimizeWidth =
new QAction( tr(
"&Autosize" ), mHorizontalHeaderMenu );
939 connect( optimizeWidth, &QAction::triggered,
this, &QgsDualView::autosizeColumn );
940 optimizeWidth->setData( col );
941 mHorizontalHeaderMenu->addAction( optimizeWidth );
943 QAction *optimizeWidthAllColumns =
new QAction( tr(
"&Autosize All Columns" ), mHorizontalHeaderMenu );
944 connect( optimizeWidthAllColumns, &QAction::triggered,
this, &QgsDualView::autosizeAllColumns );
945 mHorizontalHeaderMenu->addAction( optimizeWidthAllColumns );
948 mHorizontalHeaderMenu->addSeparator();
949 QAction *organize =
new QAction( tr(
"&Organize Columns…" ), mHorizontalHeaderMenu );
950 connect( organize, &QAction::triggered,
this, &QgsDualView::organizeColumns );
951 mHorizontalHeaderMenu->addAction( organize );
952 QAction *sort =
new QAction( tr(
"&Sort…" ), mHorizontalHeaderMenu );
953 connect( sort, &QAction::triggered,
this, [ = ]() {modifySort();} );
954 mHorizontalHeaderMenu->addAction( sort );
956 mHorizontalHeaderMenu->popup( mTableView->horizontalHeader()->mapToGlobal( point ) );
959 void QgsDualView::organizeColumns()
967 if ( dialog.exec() == QDialog::Accepted )
974 void QgsDualView::tableColumnResized(
int column,
int width )
978 if ( sourceCol >= 0 && config.
columnWidth( sourceCol ) != width )
985 void QgsDualView::hideColumn()
987 QAction *action = qobject_cast<QAction *>( sender() );
988 const int col = action->data().toInt();
991 if ( sourceCol >= 0 )
998 void QgsDualView::resizeColumn()
1000 QAction *action = qobject_cast<QAction *>( sender() );
1001 const int col = action->data().toInt();
1007 if ( sourceCol >= 0 )
1010 const int width = QInputDialog::getInt(
this, tr(
"Set column width" ), tr(
"Enter column width" ),
1011 mTableView->columnWidth( col ),
1021 void QgsDualView::resizeAllColumns()
1023 QAction *action = qobject_cast<QAction *>( sender() );
1024 const int col = action->data().toInt();
1031 const int width = QInputDialog::getInt(
this, tr(
"Set Column Width" ), tr(
"Enter column width" ),
1032 mTableView->columnWidth( col ),
1036 const int colCount = mTableView->model()->columnCount();
1039 for (
int i = 0; i < colCount; i++ )
1048 void QgsDualView::autosizeColumn()
1050 QAction *action = qobject_cast<QAction *>( sender() );
1051 const int col = action->data().toInt();
1052 mTableView->resizeColumnToContents( col );
1055 void QgsDualView::autosizeAllColumns()
1057 mTableView->resizeColumnsToContents();
1060 bool QgsDualView::modifySort()
1068 orderByDlg.setWindowTitle( tr(
"Configure Attribute Table Sort Order" ) );
1069 QDialogButtonBox *dialogButtonBox =
new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
1070 QGridLayout *layout =
new QGridLayout();
1071 connect( dialogButtonBox, &QDialogButtonBox::accepted, &orderByDlg, &QDialog::accept );
1072 connect( dialogButtonBox, &QDialogButtonBox::rejected, &orderByDlg, &QDialog::reject );
1073 orderByDlg.setLayout( layout );
1075 QGroupBox *sortingGroupBox =
new QGroupBox();
1076 sortingGroupBox->setTitle( tr(
"Defined sort order in attribute table" ) );
1077 sortingGroupBox->setCheckable(
true );
1079 layout->addWidget( sortingGroupBox );
1080 sortingGroupBox->setLayout(
new QGridLayout() );
1085 expressionBuilder->
initWithLayer( mLayer, context, QStringLiteral(
"generic" ) );
1088 sortingGroupBox->layout()->addWidget( expressionBuilder );
1090 QCheckBox *cbxSortAscending =
new QCheckBox( tr(
"Sort ascending" ) );
1091 cbxSortAscending->setChecked( config.
sortOrder() == Qt::AscendingOrder );
1092 sortingGroupBox->layout()->addWidget( cbxSortAscending );
1094 layout->addWidget( dialogButtonBox );
1095 if ( orderByDlg.exec() )
1097 const Qt::SortOrder sortOrder = cbxSortAscending->isChecked() ? Qt::AscendingOrder : Qt::DescendingOrder;
1098 if ( sortingGroupBox->isChecked() )
1120 void QgsDualView::zoomToCurrentFeature()
1122 const QModelIndex currentIndex = mTableView->currentIndex();
1123 if ( !currentIndex.isValid() )
1129 ids.insert( mFilterModel->
rowToId( currentIndex ) );
1137 void QgsDualView::panToCurrentFeature()
1139 const QModelIndex currentIndex = mTableView->currentIndex();
1140 if ( !currentIndex.isValid() )
1146 ids.insert( mFilterModel->
rowToId( currentIndex ) );
1154 void QgsDualView::flashCurrentFeature()
1156 const QModelIndex currentIndex = mTableView->currentIndex();
1157 if ( !currentIndex.isValid() )
1163 ids.insert( mFilterModel->
rowToId( currentIndex ) );
1171 void QgsDualView::rebuildFullLayerCache()
1179 void QgsDualView::previewExpressionChanged(
const QString &expression )
1181 mLayer->setDisplayExpression( expression );
1184 void QgsDualView::onSortColumnChanged()
1188 cfg.
sortOrder() != mFilterModel->sortOrder() )
1196 void QgsDualView::updateSelectedFeatures()
1208 void QgsDualView::updateEditedAddedFeatures()
1220 void QgsDualView::extentChanged()
1233 void QgsDualView::featureFormAttributeChanged(
const QString &attribute,
const QVariant &value,
bool attributeChanged )
1235 Q_UNUSED( attribute )
1237 if ( attributeChanged )
1239 mFeatureListView->setCurrentFeatureEdited(
true );
1240 mAttributeForm->
save();
1263 mTableView->setFeatureSelectionManager( featureSelectionManager );
1264 mFeatureListView->setFeatureSelectionManager( featureSelectionManager );
1266 if ( mFeatureSelectionManager && mFeatureSelectionManager->parent() ==
this )
1267 delete mFeatureSelectionManager;
1269 mFeatureSelectionManager = featureSelectionManager;
1275 mConfig.
update( mLayer->fields() );
1276 mLayer->setAttributeTableConfig( mConfig );
1278 mTableView->setAttributeTableConfig( mConfig );
1284 mFilterModel->
sort( -1 );
1303 void QgsDualView::progress(
int i,
bool &cancel )
1305 if ( !mProgressDlg )
1307 mProgressDlg =
new QProgressDialog( tr(
"Loading features…" ), tr(
"Abort" ), 0, 0,
this );
1308 mProgressDlg->setWindowTitle( tr(
"Attribute Table" ) );
1309 mProgressDlg->setWindowModality( Qt::WindowModal );
1310 mProgressDlg->show();
1313 mProgressDlg->setLabelText( tr(
"%1 features loaded." ).arg( i ) );
1314 QCoreApplication::processEvents();
1316 cancel = mProgressDlg && mProgressDlg->wasCanceled();
1319 void QgsDualView::finished()
1321 delete mProgressDlg;
1322 mProgressDlg =
nullptr;
@ NoFilter
No spatial filtering of features.
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.
const QgsAttributeEditorContext * parentContext() const
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.
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.
QgsVectorLayer * layer() const
Returns the layer this filter acts on.
void setFilterMode(FilterMode filterMode)
Set the filter mode the filter will use.
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...
QgsMapCanvas * mapCanvas() const
Returns the map canvas.
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.
@ 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)
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 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 executeMapLayerAction(QgsMapLayerAction *action, const QModelIndex &idx) const
Execute a QgsMapLayerAction.
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.
QgsAttributeTableModel * masterModel() const
Returns the model which has the information about all features (not only filtered)
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.
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.
@ 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.
QgsFeatureRequest & disableFilter()
Disables any attribute/ID filtering.
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.
QList< QgsMapLayerAction * > mapLayerActions(QgsMapLayer *layer, QgsMapLayerAction::Targets targets=QgsMapLayerAction::AllActions)
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