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;
216 mFeatureListPreviewButton->addAction( mActionExpressionPreview );
217 mFeatureListPreviewButton->addAction( mActionPreviewColumnsMenu );
219 const auto constFields = fields;
222 const int fieldIndex = mLayer->fields().lookupField(
field.
name() );
223 if ( fieldIndex == -1 )
229 const QIcon icon = mLayer->fields().iconForField( fieldIndex );
230 const QString text = mLayer->attributeDisplayName( fieldIndex );
233 QAction *previewAction =
new QAction( icon, text, mFeatureListPreviewButton );
234 connect( previewAction, &QAction::triggered,
this, [ = ] { previewColumnChanged( previewAction, fieldName ); } );
235 mPreviewColumnsMenu->addAction( previewAction );
237 if ( text == defaultField )
239 mFeatureListPreviewButton->setDefaultAction( previewAction );
244 QMenu *sortMenu =
new QMenu(
this );
246 sortMenuAction->setMenu( sortMenu );
248 QAction *sortByPreviewExpressionAsc =
new QAction(
QgsApplication::getThemeIcon( QStringLiteral(
"sort.svg" ) ), tr(
"By Preview Expression (ascending)" ),
this );
249 connect( sortByPreviewExpressionAsc, &QAction::triggered,
this, [ = ]()
253 sortMenu->addAction( sortByPreviewExpressionAsc );
254 QAction *sortByPreviewExpressionDesc =
new QAction(
QgsApplication::getThemeIcon( QStringLiteral(
"sort-reverse.svg" ) ), tr(
"By Preview Expression (descending)" ),
this );
255 connect( sortByPreviewExpressionDesc, &QAction::triggered,
this, [ = ]()
259 sortMenu->addAction( sortByPreviewExpressionDesc );
260 QAction *sortByPreviewExpressionCustom =
new QAction(
QgsApplication::getThemeIcon( QStringLiteral(
"mIconExpressionPreview.svg" ) ), tr(
"By Custom Expression" ),
this );
261 connect( sortByPreviewExpressionCustom, &QAction::triggered,
this, [ = ]()
266 sortMenu->addAction( sortByPreviewExpressionCustom );
268 mFeatureListPreviewButton->addAction( sortMenuAction );
270 QAction *separator =
new QAction( mFeatureListPreviewButton );
271 separator->setSeparator(
true );
272 mFeatureListPreviewButton->addAction( separator );
273 restoreRecentDisplayExpressions();
276 if ( !mFeatureListPreviewButton->defaultAction() )
278 mFeatureListView->setDisplayExpression( mLayer->displayExpression() );
279 mFeatureListPreviewButton->setDefaultAction( mActionExpressionPreview );
280 const QString displayExpression = mFeatureListView->displayExpression();
281 setDisplayExpression( displayExpression.isEmpty() ? tr(
"'[Please define preview text]'" ) : displayExpression );
285 mFeatureListPreviewButton->defaultAction()->trigger();
291 setCurrentIndex(
view );
331 || ( mMasterModel->
rowCount() == 0 );
333 if ( !needsGeometry )
377 setBrowsingAutoPanScaleAllowed(
false );
384 setBrowsingAutoPanScaleAllowed(
true );
388 if ( requiresTableReload )
394 whileBlocking( mLayerCache )->setCacheGeometry( needsGeometry );
408 void QgsDualView::initLayerCache(
bool cacheGeometry )
412 const int cacheSize = settings.
value( QStringLiteral(
"qgis/attributeTableRowCache" ),
"10000" ).toInt();
418 rebuildFullLayerCache();
424 delete mFeatureListModel;
445 connect( mMasterModel, &QgsAttributeTableModel::rowsRemoved, mFilterModel, &QgsAttributeTableFilterModel::invalidate );
446 connect( mMasterModel, &QgsAttributeTableModel::rowsInserted, mFilterModel, &QgsAttributeTableFilterModel::invalidate );
454 void QgsDualView::restoreRecentDisplayExpressions()
456 const QVariantList previewExpressions = mLayer->customProperty( QStringLiteral(
"dualview/previewExpressions" ) ).toList();
458 for (
const QVariant &previewExpression : previewExpressions )
459 insertRecentlyUsedDisplayExpression( previewExpression.toString() );
462 void QgsDualView::saveRecentDisplayExpressions()
const
468 const QList<QAction *> actions = mFeatureListPreviewButton->actions();
471 int index = actions.indexOf( mLastDisplayExpressionAction );
474 QVariantList previewExpressions;
475 for ( ; index < actions.length(); ++index )
477 QAction *action = actions.at( index );
478 previewExpressions << action->property(
"previewExpression" );
481 mLayer->setCustomProperty( QStringLiteral(
"dualview/previewExpressions" ), previewExpressions );
485 void QgsDualView::setDisplayExpression(
const QString &expression )
487 mDisplayExpression = expression;
488 insertRecentlyUsedDisplayExpression( expression );
491 void QgsDualView::insertRecentlyUsedDisplayExpression(
const QString &expression )
493 const QList<QAction *> actions = mFeatureListPreviewButton->actions();
496 const int index = actions.indexOf( mLastDisplayExpressionAction );
499 for (
int i = 0; index + i < actions.length(); ++i )
501 QAction *action = actions.at( index );
502 if ( action->text() == expression || i >= 9 )
504 if ( action == mLastDisplayExpressionAction )
505 mLastDisplayExpressionAction =
nullptr;
506 mFeatureListPreviewButton->removeAction( action );
510 if ( !mLastDisplayExpressionAction )
511 mLastDisplayExpressionAction = action;
516 QString name = expression;
518 if ( expression.startsWith( QLatin1String(
"COALESCE( \"" ) ) && expression.endsWith( QLatin1String(
", '<NULL>' )" ) ) )
520 name = expression.mid( 11, expression.length() - 24 );
522 const int fieldIndex = mLayer->fields().indexOf( name );
523 if ( fieldIndex != -1 )
525 name = mLayer->attributeDisplayName( fieldIndex );
526 icon = mLayer->fields().iconForField( fieldIndex );
534 QAction *previewAction =
new QAction( icon, name, mFeatureListPreviewButton );
535 previewAction->setProperty(
"previewExpression", expression );
536 connect( previewAction, &QAction::triggered,
this, [expression,
this](
bool )
538 setDisplayExpression( expression );
539 mFeatureListPreviewButton->setText( expression );
543 mFeatureListPreviewButton->insertAction( mLastDisplayExpressionAction, previewAction );
544 mLastDisplayExpressionAction = previewAction;
547 void QgsDualView::updateEditSelectionProgress(
int progress,
int count )
549 mProgressCount->setText( QStringLiteral(
"%1 / %2" ).arg( progress + 1 ).arg( count ) );
550 mPreviousFeatureButton->setEnabled( progress > 0 );
551 mNextFeatureButton->setEnabled( progress + 1 < count );
552 mFirstFeatureButton->setEnabled( progress > 0 );
553 mLastFeatureButton->setEnabled( progress + 1 < count );
554 if ( mAttributeForm )
556 mAttributeForm->setVisible( count > 0 );
560 void QgsDualView::panOrZoomToFeature(
const QgsFeatureIds &featureset )
565 if ( mBrowsingAutoPanScaleAllowed )
567 if ( mAutoPanButton->isChecked() )
568 QTimer::singleShot( 0,
this, [ = ]()
572 else if ( mAutoZoomButton->isChecked() )
573 QTimer::singleShot( 0,
this, [ = ]()
578 if ( mFlashButton->isChecked() )
579 QTimer::singleShot( 0,
this, [ = ]()
583 mLastFeatureSet = featureset;
587 void QgsDualView::setBrowsingAutoPanScaleAllowed(
bool allowed )
589 if ( mBrowsingAutoPanScaleAllowed == allowed )
592 mBrowsingAutoPanScaleAllowed = allowed;
594 mAutoPanButton->setEnabled( allowed );
595 mAutoZoomButton->setEnabled( allowed );
597 const QString disabledHint = tr(
"(disabled when attribute table only shows features visible in the current map canvas extent)" );
599 mAutoPanButton->setToolTip( tr(
"Automatically pan to the current feature" ) + ( allowed ? QString() : QString(
' ' ) + disabledHint ) );
600 mAutoZoomButton->setToolTip( tr(
"Automatically zoom to the current feature" ) + ( allowed ? QString() : QString(
' ' ) + disabledHint ) );
603 void QgsDualView::panZoomGroupButtonToggled( QAbstractButton *button,
bool checked )
605 if ( button == mAutoPanButton && checked )
608 mAutoZoomButton->setChecked(
false );
610 else if ( button == mAutoZoomButton && checked )
613 mAutoPanButton->setChecked(
false );
620 if ( checked && mLayer->isSpatial() )
621 panOrZoomToFeature( mFeatureListView->currentEditSelection() );
624 void QgsDualView::flashButtonClicked(
bool clicked )
626 QgsSettings().
setValue( QStringLiteral(
"/qgis/attributeTable/featureListHighlightFeature" ), clicked );
633 canvas->
flashFeatureIds( mLayer, mFeatureListView->currentEditSelection() );
636 void QgsDualView::filterError(
const QString &errorMessage )
644 void QgsDualView::featureListAboutToChangeEditSelection(
bool &ok )
646 if ( !mAttributeForm )
649 if ( mLayer->isEditable() && !mAttributeForm->
save() )
653 void QgsDualView::featureListCurrentEditSelectionChanged(
const QgsFeature &feat )
655 if ( !mAttributeForm )
657 initAttributeForm( feat );
659 else if ( !mLayer->isEditable() || mAttributeForm->
save() )
663 featureset << feat.
id();
666 if ( mLayer->isSpatial() )
667 panOrZoomToFeature( featureset );
678 mFeatureListView->setCurrentFeatureEdited(
false );
679 mFeatureListView->setEditSelection( fids );
684 return mAttributeForm ? mAttributeForm->
save() :
false;
689 mConditionalFormatWidgetStack->setVisible( !mConditionalFormatWidgetStack->isVisible() );
694 if ( !mAttributeForm )
699 mPreviousView =
view();
712 if ( !mAttributeForm )
719 mAttributeForm->setVisible(
true );
724 mAttributeForm->setVisible( mFilterModel->rowCount( ) > 0 );
729 void QgsDualView::previewExpressionBuilder()
735 dlg.setWindowTitle( tr(
"Expression Based Preview" ) );
736 dlg.setExpressionText( mFeatureListView->displayExpression() );
738 if ( dlg.exec() == QDialog::Accepted )
740 mFeatureListView->setDisplayExpression( dlg.expressionText() );
741 mFeatureListPreviewButton->setDefaultAction( mActionExpressionPreview );
742 mFeatureListPreviewButton->setPopupMode( QToolButton::MenuButtonPopup );
745 setDisplayExpression( mFeatureListView->displayExpression() );
748 void QgsDualView::previewColumnChanged( QAction *previewAction,
const QString &expression )
750 if ( !mFeatureListView->setDisplayExpression( QStringLiteral(
"COALESCE( \"%1\", '<NULL>' )" ).arg( expression ) ) )
752 QMessageBox::warning(
this,
753 tr(
"Column Preview" ),
754 tr(
"Could not set column '%1' as preview column.\nParser error:\n%2" )
755 .arg( previewAction->text(), mFeatureListView->parserErrorString() )
760 mFeatureListPreviewButton->setText( previewAction->text() );
761 mFeatureListPreviewButton->setIcon( previewAction->icon() );
762 mFeatureListPreviewButton->setPopupMode( QToolButton::InstantPopup );
765 setDisplayExpression( mFeatureListView->displayExpression() );
775 return mFilterModel->rowCount();
780 const QModelIndex currentIndex = mTableView->currentIndex();
781 if ( !currentIndex.isValid() )
786 const QVariant var = mMasterModel->
data( currentIndex, Qt::DisplayRole );
787 QApplication::clipboard()->setText( var.toString() );
793 mProgressDlg->cancel();
798 if ( mAttributeForm )
807 saveRecentDisplayExpressions();
810 void QgsDualView::viewWillShowContextMenu( QMenu *menu,
const QModelIndex &masterIndex )
817 QAction *copyContentAction = menu->addAction( tr(
"Copy Cell Content" ) );
818 menu->addAction( copyContentAction );
819 connect( copyContentAction, &QAction::triggered,
this, [masterIndex,
this]
821 const QVariant var = mMasterModel->
data( masterIndex, Qt::DisplayRole );
822 QApplication::clipboard()->setText( var.toString() );
829 QAction *zoomToFeatureAction = menu->addAction( tr(
"Zoom to Feature" ) );
830 connect( zoomToFeatureAction, &QAction::triggered,
this, &QgsDualView::zoomToCurrentFeature );
832 QAction *panToFeatureAction = menu->addAction( tr(
"Pan to Feature" ) );
833 connect( panToFeatureAction, &QAction::triggered,
this, &QgsDualView::panToCurrentFeature );
835 QAction *flashFeatureAction = menu->addAction( tr(
"Flash Feature" ) );
836 connect( flashFeatureAction, &QAction::triggered,
this, &QgsDualView::flashCurrentFeature );
840 const QList<QgsAction> actions = mLayer->actions()->actions( QStringLiteral(
"Field" ) );
841 if ( !actions.isEmpty() )
843 QAction *a = menu->addAction( tr(
"Run Layer Action" ) );
844 a->setEnabled(
false );
846 for (
const QgsAction &action : actions )
848 if ( !action.runable() )
851 if ( vl && !vl->isEditable() && action.isEnabledOnlyWhenEditable() )
858 const QModelIndex rowSourceIndex = mMasterModel->index( masterIndex.row(), 0 );
859 if ( ! rowSourceIndex.isValid() )
866 if ( !registeredActions.isEmpty() )
869 menu->addSeparator();
881 if ( mLayer->selectedFeatureCount() > 1 && mLayer->selectedFeatureIds().contains( currentFid ) )
884 if ( !registeredActions.isEmpty() )
886 menu->addSeparator();
887 QAction *action = menu->addAction( tr(
"Actions on Selection (%1)" ).arg( mLayer->selectedFeatureCount() ) );
888 action->setEnabled(
false );
892 menu->addAction( action->text(), action, [ = ]() {action->triggerForFeatures( mLayer, mLayer->selectedFeatures() );} );
897 menu->addSeparator();
903 void QgsDualView::widgetWillShowContextMenu(
QgsActionMenu *menu,
const QModelIndex &atIndex )
909 void QgsDualView::showViewHeaderMenu( QPoint point )
911 const int col = mTableView->columnAt( point.x() );
913 delete mHorizontalHeaderMenu;
914 mHorizontalHeaderMenu =
new QMenu(
this );
916 QAction *hide =
new QAction( tr(
"&Hide Column" ), mHorizontalHeaderMenu );
917 connect( hide, &QAction::triggered,
this, &QgsDualView::hideColumn );
918 hide->setData( col );
919 mHorizontalHeaderMenu->addAction( hide );
920 QAction *setWidth =
new QAction( tr(
"&Set Width…" ), mHorizontalHeaderMenu );
921 connect( setWidth, &QAction::triggered,
this, &QgsDualView::resizeColumn );
922 setWidth->setData( col );
923 mHorizontalHeaderMenu->addAction( setWidth );
925 QAction *setWidthAllColumns =
new QAction( tr(
"&Set All Column Widths…" ), mHorizontalHeaderMenu );
926 connect( setWidthAllColumns, &QAction::triggered,
this, &QgsDualView::resizeAllColumns );
927 setWidthAllColumns->setData( col );
928 mHorizontalHeaderMenu->addAction( setWidthAllColumns );
930 QAction *optimizeWidth =
new QAction( tr(
"&Autosize" ), mHorizontalHeaderMenu );
931 connect( optimizeWidth, &QAction::triggered,
this, &QgsDualView::autosizeColumn );
932 optimizeWidth->setData( col );
933 mHorizontalHeaderMenu->addAction( optimizeWidth );
935 QAction *optimizeWidthAllColumns =
new QAction( tr(
"&Autosize All Columns" ), mHorizontalHeaderMenu );
936 connect( optimizeWidthAllColumns, &QAction::triggered,
this, &QgsDualView::autosizeAllColumns );
937 mHorizontalHeaderMenu->addAction( optimizeWidthAllColumns );
940 mHorizontalHeaderMenu->addSeparator();
941 QAction *organize =
new QAction( tr(
"&Organize Columns…" ), mHorizontalHeaderMenu );
942 connect( organize, &QAction::triggered,
this, &QgsDualView::organizeColumns );
943 mHorizontalHeaderMenu->addAction( organize );
944 QAction *sort =
new QAction( tr(
"&Sort…" ), mHorizontalHeaderMenu );
945 connect( sort, &QAction::triggered,
this, [ = ]() {modifySort();} );
946 mHorizontalHeaderMenu->addAction( sort );
948 mHorizontalHeaderMenu->popup( mTableView->horizontalHeader()->mapToGlobal( point ) );
951 void QgsDualView::organizeColumns()
959 if ( dialog.exec() == QDialog::Accepted )
966 void QgsDualView::tableColumnResized(
int column,
int width )
970 if ( sourceCol >= 0 && config.
columnWidth( sourceCol ) != width )
977 void QgsDualView::hideColumn()
979 QAction *action = qobject_cast<QAction *>( sender() );
980 const int col = action->data().toInt();
983 if ( sourceCol >= 0 )
990 void QgsDualView::resizeColumn()
992 QAction *action = qobject_cast<QAction *>( sender() );
993 const int col = action->data().toInt();
999 if ( sourceCol >= 0 )
1002 const int width = QInputDialog::getInt(
this, tr(
"Set column width" ), tr(
"Enter column width" ),
1003 mTableView->columnWidth( col ),
1013 void QgsDualView::resizeAllColumns()
1015 QAction *action = qobject_cast<QAction *>( sender() );
1016 const int col = action->data().toInt();
1023 const int width = QInputDialog::getInt(
this, tr(
"Set Column Width" ), tr(
"Enter column width" ),
1024 mTableView->columnWidth( col ),
1028 const int colCount = mTableView->model()->columnCount();
1031 for (
int i = 0; i < colCount; i++ )
1040 void QgsDualView::autosizeColumn()
1042 QAction *action = qobject_cast<QAction *>( sender() );
1043 const int col = action->data().toInt();
1044 mTableView->resizeColumnToContents( col );
1047 void QgsDualView::autosizeAllColumns()
1049 mTableView->resizeColumnsToContents();
1052 bool QgsDualView::modifySort()
1060 orderByDlg.setWindowTitle( tr(
"Configure Attribute Table Sort Order" ) );
1061 QDialogButtonBox *dialogButtonBox =
new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
1062 QGridLayout *layout =
new QGridLayout();
1063 connect( dialogButtonBox, &QDialogButtonBox::accepted, &orderByDlg, &QDialog::accept );
1064 connect( dialogButtonBox, &QDialogButtonBox::rejected, &orderByDlg, &QDialog::reject );
1065 orderByDlg.setLayout( layout );
1067 QGroupBox *sortingGroupBox =
new QGroupBox();
1068 sortingGroupBox->setTitle( tr(
"Defined sort order in attribute table" ) );
1069 sortingGroupBox->setCheckable(
true );
1071 layout->addWidget( sortingGroupBox );
1072 sortingGroupBox->setLayout(
new QGridLayout() );
1077 expressionBuilder->
initWithLayer( mLayer, context, QStringLiteral(
"generic" ) );
1080 sortingGroupBox->layout()->addWidget( expressionBuilder );
1082 QCheckBox *cbxSortAscending =
new QCheckBox( tr(
"Sort ascending" ) );
1083 cbxSortAscending->setChecked( config.
sortOrder() == Qt::AscendingOrder );
1084 sortingGroupBox->layout()->addWidget( cbxSortAscending );
1086 layout->addWidget( dialogButtonBox );
1087 if ( orderByDlg.exec() )
1089 const Qt::SortOrder sortOrder = cbxSortAscending->isChecked() ? Qt::AscendingOrder : Qt::DescendingOrder;
1090 if ( sortingGroupBox->isChecked() )
1112 void QgsDualView::zoomToCurrentFeature()
1114 const QModelIndex currentIndex = mTableView->currentIndex();
1115 if ( !currentIndex.isValid() )
1121 ids.insert( mFilterModel->
rowToId( currentIndex ) );
1129 void QgsDualView::panToCurrentFeature()
1131 const QModelIndex currentIndex = mTableView->currentIndex();
1132 if ( !currentIndex.isValid() )
1138 ids.insert( mFilterModel->
rowToId( currentIndex ) );
1146 void QgsDualView::flashCurrentFeature()
1148 const QModelIndex currentIndex = mTableView->currentIndex();
1149 if ( !currentIndex.isValid() )
1155 ids.insert( mFilterModel->
rowToId( currentIndex ) );
1163 void QgsDualView::rebuildFullLayerCache()
1171 void QgsDualView::previewExpressionChanged(
const QString &expression )
1173 mLayer->setDisplayExpression( expression );
1176 void QgsDualView::onSortColumnChanged()
1180 cfg.
sortOrder() != mFilterModel->sortOrder() )
1188 void QgsDualView::updateSelectedFeatures()
1200 void QgsDualView::updateEditedAddedFeatures()
1212 void QgsDualView::extentChanged()
1225 void QgsDualView::featureFormAttributeChanged(
const QString &attribute,
const QVariant &value,
bool attributeChanged )
1227 Q_UNUSED( attribute )
1229 if ( attributeChanged )
1231 mFeatureListView->setCurrentFeatureEdited(
true );
1232 mAttributeForm->
save();
1255 mTableView->setFeatureSelectionManager( featureSelectionManager );
1256 mFeatureListView->setFeatureSelectionManager( featureSelectionManager );
1258 if ( mFeatureSelectionManager && mFeatureSelectionManager->parent() ==
this )
1259 delete mFeatureSelectionManager;
1261 mFeatureSelectionManager = featureSelectionManager;
1267 mConfig.
update( mLayer->fields() );
1268 mLayer->setAttributeTableConfig( mConfig );
1270 mTableView->setAttributeTableConfig( mConfig );
1276 mFilterModel->
sort( -1 );
1295 void QgsDualView::progress(
int i,
bool &cancel )
1297 if ( !mProgressDlg )
1299 mProgressDlg =
new QProgressDialog( tr(
"Loading features…" ), tr(
"Abort" ), 0, 0,
this );
1300 mProgressDlg->setWindowTitle( tr(
"Attribute Table" ) );
1301 mProgressDlg->setWindowModality( Qt::WindowModal );
1302 mProgressDlg->show();
1305 mProgressDlg->setLabelText( tr(
"%L1 features loaded." ).arg( i ) );
1306 QCoreApplication::processEvents();
1308 cancel = mProgressDlg && mProgressDlg->wasCanceled();
1311 void QgsDualView::finished()
1313 delete mProgressDlg;
1314 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