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;
143 const bool needsGeometry = mLayer->conditionalStyles()->rulesNeedGeometry() ||
148 initLayerCache( needsGeometry );
149 initModels( mapCanvas, request, loadFeatures );
151 mConditionalFormatWidget->
setLayer( mLayer );
153 mTableView->setModel( mFilterModel );
154 mFeatureListView->setModel( mFeatureListModel );
158 if ( mFeatureListPreviewButton->defaultAction() )
159 mFeatureListView->setDisplayExpression( mDisplayExpression );
166 if ( showFirstFeature && mFeatureListModel->
rowCount( ) > 0 )
167 mFeatureListView->setEditSelection(
QgsFeatureIds() << mFeatureListModel->
data( mFeatureListModel->index( 0, 0 ), QgsFeatureListModel::Role::FeatureRole ).value<
QgsFeature>().
id() );
170 void QgsDualView::initAttributeForm(
const QgsFeature &feature )
172 Q_ASSERT( !mAttributeForm );
178 mAttributeEditorScrollArea->setWidgetResizable(
true );
179 mAttributeEditor->layout()->addWidget( mAttributeEditorScrollArea );
180 mAttributeEditorScrollArea->setWidget( mAttributeForm );
184 mAttributeEditor->layout()->addWidget( mAttributeForm );
196 QgsMapCanvasUtils::flashMatchingFeatures( canvas, mLayer, filter );
203 QgsMapCanvasUtils::zoomToMatchingFeatures( canvas, mLayer, filter );
210 void QgsDualView::columnBoxInit()
213 const QList<QgsField> fields = mLayer->fields().toList();
215 const QString defaultField;
217 mFeatureListPreviewButton->addAction( mActionExpressionPreview );
218 mFeatureListPreviewButton->addAction( mActionPreviewColumnsMenu );
220 const auto constFields = fields;
223 const int fieldIndex = mLayer->fields().lookupField(
field.
name() );
224 if ( fieldIndex == -1 )
230 const QIcon icon = mLayer->fields().iconForField( fieldIndex );
231 const QString text = mLayer->attributeDisplayName( fieldIndex );
234 QAction *previewAction =
new QAction( icon, text, mFeatureListPreviewButton );
235 connect( previewAction, &QAction::triggered,
this, [ = ] { previewColumnChanged( previewAction, fieldName ); } );
236 mPreviewColumnsMenu->addAction( previewAction );
238 if ( text == defaultField )
240 mFeatureListPreviewButton->setDefaultAction( previewAction );
245 QMenu *sortMenu =
new QMenu(
this );
247 sortMenuAction->setMenu( sortMenu );
249 QAction *sortByPreviewExpressionAsc =
new QAction(
QgsApplication::getThemeIcon( QStringLiteral(
"sort.svg" ) ), tr(
"By Preview Expression (ascending)" ),
this );
250 connect( sortByPreviewExpressionAsc, &QAction::triggered,
this, [ = ]()
254 sortMenu->addAction( sortByPreviewExpressionAsc );
255 QAction *sortByPreviewExpressionDesc =
new QAction(
QgsApplication::getThemeIcon( QStringLiteral(
"sort-reverse.svg" ) ), tr(
"By Preview Expression (descending)" ),
this );
256 connect( sortByPreviewExpressionDesc, &QAction::triggered,
this, [ = ]()
260 sortMenu->addAction( sortByPreviewExpressionDesc );
261 QAction *sortByPreviewExpressionCustom =
new QAction(
QgsApplication::getThemeIcon( QStringLiteral(
"mIconExpressionPreview.svg" ) ), tr(
"By Custom Expression" ),
this );
262 connect( sortByPreviewExpressionCustom, &QAction::triggered,
this, [ = ]()
267 sortMenu->addAction( sortByPreviewExpressionCustom );
269 mFeatureListPreviewButton->addAction( sortMenuAction );
271 QAction *separator =
new QAction( mFeatureListPreviewButton );
272 separator->setSeparator(
true );
273 mFeatureListPreviewButton->addAction( separator );
274 restoreRecentDisplayExpressions();
277 if ( !mFeatureListPreviewButton->defaultAction() )
279 mFeatureListView->setDisplayExpression( mLayer->displayExpression() );
280 mFeatureListPreviewButton->setDefaultAction( mActionExpressionPreview );
281 const QString displayExpression = mFeatureListView->displayExpression();
282 setDisplayExpression( displayExpression.isEmpty() ? tr(
"'[Please define preview text]'" ) : displayExpression );
286 mFeatureListPreviewButton->defaultAction()->trigger();
292 setCurrentIndex(
view );
332 || ( mMasterModel->
rowCount() == 0 );
334 if ( !needsGeometry )
378 setBrowsingAutoPanScaleAllowed(
false );
385 setBrowsingAutoPanScaleAllowed(
true );
389 if ( requiresTableReload )
395 whileBlocking( mLayerCache )->setCacheGeometry( needsGeometry );
409 void QgsDualView::initLayerCache(
bool cacheGeometry )
413 const int cacheSize = settings.
value( QStringLiteral(
"qgis/attributeTableRowCache" ),
"10000" ).toInt();
419 rebuildFullLayerCache();
425 delete mFeatureListModel;
446 connect( mMasterModel, &QgsAttributeTableModel::rowsRemoved, mFilterModel, &QgsAttributeTableFilterModel::invalidate );
447 connect( mMasterModel, &QgsAttributeTableModel::rowsInserted, mFilterModel, &QgsAttributeTableFilterModel::invalidate );
455 void QgsDualView::restoreRecentDisplayExpressions()
457 const QVariantList previewExpressions = mLayer->customProperty( QStringLiteral(
"dualview/previewExpressions" ) ).toList();
459 for (
const QVariant &previewExpression : previewExpressions )
460 insertRecentlyUsedDisplayExpression( previewExpression.toString() );
463 void QgsDualView::saveRecentDisplayExpressions()
const
469 const QList<QAction *> actions = mFeatureListPreviewButton->actions();
472 int index = actions.indexOf( mLastDisplayExpressionAction );
475 QVariantList previewExpressions;
476 for ( ; index < actions.length(); ++index )
478 QAction *action = actions.at( index );
479 previewExpressions << action->property(
"previewExpression" );
482 mLayer->setCustomProperty( QStringLiteral(
"dualview/previewExpressions" ), previewExpressions );
486 void QgsDualView::setDisplayExpression(
const QString &expression )
488 mDisplayExpression = expression;
489 insertRecentlyUsedDisplayExpression( expression );
492 void QgsDualView::insertRecentlyUsedDisplayExpression(
const QString &expression )
494 const QList<QAction *> actions = mFeatureListPreviewButton->actions();
497 const int index = actions.indexOf( mLastDisplayExpressionAction );
500 for (
int i = 0; index + i < actions.length(); ++i )
502 QAction *action = actions.at( index );
503 if ( action->text() == expression || i >= 9 )
505 if ( action == mLastDisplayExpressionAction )
506 mLastDisplayExpressionAction =
nullptr;
507 mFeatureListPreviewButton->removeAction( action );
511 if ( !mLastDisplayExpressionAction )
512 mLastDisplayExpressionAction = action;
517 QString name = expression;
519 if ( expression.startsWith( QLatin1String(
"COALESCE( \"" ) ) && expression.endsWith( QLatin1String(
", '<NULL>' )" ) ) )
521 name = expression.mid( 11, expression.length() - 24 );
523 const int fieldIndex = mLayer->fields().indexOf( name );
524 if ( fieldIndex != -1 )
526 name = mLayer->attributeDisplayName( fieldIndex );
527 icon = mLayer->fields().iconForField( fieldIndex );
535 QAction *previewAction =
new QAction( icon, name, mFeatureListPreviewButton );
536 previewAction->setProperty(
"previewExpression", expression );
537 connect( previewAction, &QAction::triggered,
this, [expression,
this](
bool )
539 setDisplayExpression( expression );
540 mFeatureListPreviewButton->setText( expression );
544 mFeatureListPreviewButton->insertAction( mLastDisplayExpressionAction, previewAction );
545 mLastDisplayExpressionAction = previewAction;
548 void QgsDualView::updateEditSelectionProgress(
int progress,
int count )
550 mProgressCount->setText( QStringLiteral(
"%1 / %2" ).arg( progress + 1 ).arg( count ) );
551 mPreviousFeatureButton->setEnabled( progress > 0 );
552 mNextFeatureButton->setEnabled( progress + 1 < count );
553 mFirstFeatureButton->setEnabled( progress > 0 );
554 mLastFeatureButton->setEnabled( progress + 1 < count );
555 if ( mAttributeForm )
557 mAttributeForm->setVisible( count > 0 );
561 void QgsDualView::panOrZoomToFeature(
const QgsFeatureIds &featureset )
566 if ( mBrowsingAutoPanScaleAllowed )
568 if ( mAutoPanButton->isChecked() )
569 QTimer::singleShot( 0,
this, [ = ]()
573 else if ( mAutoZoomButton->isChecked() )
574 QTimer::singleShot( 0,
this, [ = ]()
579 if ( mFlashButton->isChecked() )
580 QTimer::singleShot( 0,
this, [ = ]()
584 mLastFeatureSet = featureset;
588 void QgsDualView::setBrowsingAutoPanScaleAllowed(
bool allowed )
590 if ( mBrowsingAutoPanScaleAllowed == allowed )
593 mBrowsingAutoPanScaleAllowed = allowed;
595 mAutoPanButton->setEnabled( allowed );
596 mAutoZoomButton->setEnabled( allowed );
598 const QString disabledHint = tr(
"(disabled when attribute table only shows features visible in the current map canvas extent)" );
600 mAutoPanButton->setToolTip( tr(
"Automatically pan to the current feature" ) + ( allowed ? QString() : QString(
' ' ) + disabledHint ) );
601 mAutoZoomButton->setToolTip( tr(
"Automatically zoom to the current feature" ) + ( allowed ? QString() : QString(
' ' ) + disabledHint ) );
604 void QgsDualView::panZoomGroupButtonToggled( QAbstractButton *button,
bool checked )
606 if ( button == mAutoPanButton && checked )
609 mAutoZoomButton->setChecked(
false );
611 else if ( button == mAutoZoomButton && checked )
614 mAutoPanButton->setChecked(
false );
621 if ( checked && mLayer->isSpatial() )
622 panOrZoomToFeature( mFeatureListView->currentEditSelection() );
625 void QgsDualView::flashButtonClicked(
bool clicked )
627 QgsSettings().
setValue( QStringLiteral(
"/qgis/attributeTable/featureListHighlightFeature" ), clicked );
634 canvas->
flashFeatureIds( mLayer, mFeatureListView->currentEditSelection() );
637 void QgsDualView::filterError(
const QString &errorMessage )
645 void QgsDualView::featureListAboutToChangeEditSelection(
bool &ok )
647 if ( !mAttributeForm )
650 if ( mLayer->isEditable() && !mAttributeForm->
save() )
654 void QgsDualView::featureListCurrentEditSelectionChanged(
const QgsFeature &feat )
656 if ( !mAttributeForm )
658 initAttributeForm( feat );
660 else if ( !mLayer->isEditable() || mAttributeForm->
save() )
664 featureset << feat.
id();
667 if ( mLayer->isSpatial() )
668 panOrZoomToFeature( featureset );
679 mFeatureListView->setCurrentFeatureEdited(
false );
680 mFeatureListView->setEditSelection( fids );
685 return mAttributeForm ? mAttributeForm->
save() :
false;
690 mConditionalFormatWidgetStack->setVisible( !mConditionalFormatWidgetStack->isVisible() );
695 if ( !mAttributeForm )
700 mPreviousView =
view();
713 if ( !mAttributeForm )
720 mAttributeForm->setVisible(
true );
725 mAttributeForm->setVisible( mFilterModel->rowCount( ) > 0 );
730 void QgsDualView::previewExpressionBuilder()
736 dlg.setWindowTitle( tr(
"Expression Based Preview" ) );
737 dlg.setExpressionText( mFeatureListView->displayExpression() );
739 if ( dlg.exec() == QDialog::Accepted )
741 mFeatureListView->setDisplayExpression( dlg.expressionText() );
742 mFeatureListPreviewButton->setDefaultAction( mActionExpressionPreview );
743 mFeatureListPreviewButton->setPopupMode( QToolButton::MenuButtonPopup );
746 setDisplayExpression( mFeatureListView->displayExpression() );
749 void QgsDualView::previewColumnChanged( QAction *previewAction,
const QString &expression )
751 if ( !mFeatureListView->setDisplayExpression( QStringLiteral(
"COALESCE( \"%1\", '<NULL>' )" ).arg( expression ) ) )
753 QMessageBox::warning(
this,
754 tr(
"Column Preview" ),
755 tr(
"Could not set column '%1' as preview column.\nParser error:\n%2" )
756 .arg( previewAction->text(), mFeatureListView->parserErrorString() )
761 mFeatureListPreviewButton->setText( previewAction->text() );
762 mFeatureListPreviewButton->setIcon( previewAction->icon() );
763 mFeatureListPreviewButton->setPopupMode( QToolButton::InstantPopup );
766 setDisplayExpression( mFeatureListView->displayExpression() );
776 return mFilterModel->rowCount();
781 const QModelIndex currentIndex = mTableView->currentIndex();
782 if ( !currentIndex.isValid() )
787 const QVariant var = mMasterModel->
data( currentIndex, Qt::DisplayRole );
788 QApplication::clipboard()->setText( var.toString() );
794 mProgressDlg->cancel();
799 if ( mAttributeForm )
808 saveRecentDisplayExpressions();
811 void QgsDualView::viewWillShowContextMenu( QMenu *menu,
const QModelIndex &masterIndex )
818 QAction *copyContentAction = menu->addAction( tr(
"Copy Cell Content" ) );
819 menu->addAction( copyContentAction );
820 connect( copyContentAction, &QAction::triggered,
this, [masterIndex,
this]
822 const QVariant var = mMasterModel->
data( masterIndex, Qt::DisplayRole );
823 QApplication::clipboard()->setText( var.toString() );
830 QAction *zoomToFeatureAction = menu->addAction( tr(
"Zoom to Feature" ) );
831 connect( zoomToFeatureAction, &QAction::triggered,
this, &QgsDualView::zoomToCurrentFeature );
833 QAction *panToFeatureAction = menu->addAction( tr(
"Pan to Feature" ) );
834 connect( panToFeatureAction, &QAction::triggered,
this, &QgsDualView::panToCurrentFeature );
836 QAction *flashFeatureAction = menu->addAction( tr(
"Flash Feature" ) );
837 connect( flashFeatureAction, &QAction::triggered,
this, &QgsDualView::flashCurrentFeature );
841 const QList<QgsAction> actions = mLayer->actions()->actions( QStringLiteral(
"Field" ) );
842 if ( !actions.isEmpty() )
844 QAction *a = menu->addAction( tr(
"Run Layer Action" ) );
845 a->setEnabled(
false );
847 for (
const QgsAction &action : actions )
849 if ( !action.runable() )
852 if ( vl && !vl->isEditable() && action.isEnabledOnlyWhenEditable() )
859 const QModelIndex rowSourceIndex = mMasterModel->index( masterIndex.row(), 0 );
860 if ( ! rowSourceIndex.isValid() )
867 if ( !registeredActions.isEmpty() )
870 menu->addSeparator();
882 if ( mLayer->selectedFeatureCount() > 1 && mLayer->selectedFeatureIds().contains( currentFid ) )
885 if ( !registeredActions.isEmpty() )
887 menu->addSeparator();
888 QAction *action = menu->addAction( tr(
"Actions on Selection (%1)" ).arg( mLayer->selectedFeatureCount() ) );
889 action->setEnabled(
false );
893 menu->addAction( action->text(), action, [ = ]() {action->triggerForFeatures( mLayer, mLayer->selectedFeatures() );} );
898 menu->addSeparator();
904 void QgsDualView::widgetWillShowContextMenu(
QgsActionMenu *menu,
const QModelIndex &atIndex )
910 void QgsDualView::showViewHeaderMenu( QPoint point )
912 const int col = mTableView->columnAt( point.x() );
914 delete mHorizontalHeaderMenu;
915 mHorizontalHeaderMenu =
new QMenu(
this );
917 QAction *hide =
new QAction( tr(
"&Hide Column" ), mHorizontalHeaderMenu );
918 connect( hide, &QAction::triggered,
this, &QgsDualView::hideColumn );
919 hide->setData( col );
920 mHorizontalHeaderMenu->addAction( hide );
921 QAction *setWidth =
new QAction( tr(
"&Set Width…" ), mHorizontalHeaderMenu );
922 connect( setWidth, &QAction::triggered,
this, &QgsDualView::resizeColumn );
923 setWidth->setData( col );
924 mHorizontalHeaderMenu->addAction( setWidth );
926 QAction *setWidthAllColumns =
new QAction( tr(
"&Set All Column Widths…" ), mHorizontalHeaderMenu );
927 connect( setWidthAllColumns, &QAction::triggered,
this, &QgsDualView::resizeAllColumns );
928 setWidthAllColumns->setData( col );
929 mHorizontalHeaderMenu->addAction( setWidthAllColumns );
931 QAction *optimizeWidth =
new QAction( tr(
"&Autosize" ), mHorizontalHeaderMenu );
932 connect( optimizeWidth, &QAction::triggered,
this, &QgsDualView::autosizeColumn );
933 optimizeWidth->setData( col );
934 mHorizontalHeaderMenu->addAction( optimizeWidth );
936 QAction *optimizeWidthAllColumns =
new QAction( tr(
"&Autosize All Columns" ), mHorizontalHeaderMenu );
937 connect( optimizeWidthAllColumns, &QAction::triggered,
this, &QgsDualView::autosizeAllColumns );
938 mHorizontalHeaderMenu->addAction( optimizeWidthAllColumns );
941 mHorizontalHeaderMenu->addSeparator();
942 QAction *organize =
new QAction( tr(
"&Organize Columns…" ), mHorizontalHeaderMenu );
943 connect( organize, &QAction::triggered,
this, &QgsDualView::organizeColumns );
944 mHorizontalHeaderMenu->addAction( organize );
945 QAction *sort =
new QAction( tr(
"&Sort…" ), mHorizontalHeaderMenu );
946 connect( sort, &QAction::triggered,
this, [ = ]() {modifySort();} );
947 mHorizontalHeaderMenu->addAction( sort );
949 mHorizontalHeaderMenu->popup( mTableView->horizontalHeader()->mapToGlobal( point ) );
952 void QgsDualView::organizeColumns()
960 if ( dialog.exec() == QDialog::Accepted )
967 void QgsDualView::tableColumnResized(
int column,
int width )
971 if ( sourceCol >= 0 && config.
columnWidth( sourceCol ) != width )
978 void QgsDualView::hideColumn()
980 QAction *action = qobject_cast<QAction *>( sender() );
981 const int col = action->data().toInt();
984 if ( sourceCol >= 0 )
991 void QgsDualView::resizeColumn()
993 QAction *action = qobject_cast<QAction *>( sender() );
994 const int col = action->data().toInt();
1000 if ( sourceCol >= 0 )
1003 const int width = QInputDialog::getInt(
this, tr(
"Set column width" ), tr(
"Enter column width" ),
1004 mTableView->columnWidth( col ),
1014 void QgsDualView::resizeAllColumns()
1016 QAction *action = qobject_cast<QAction *>( sender() );
1017 const int col = action->data().toInt();
1024 const int width = QInputDialog::getInt(
this, tr(
"Set Column Width" ), tr(
"Enter column width" ),
1025 mTableView->columnWidth( col ),
1029 const int colCount = mTableView->model()->columnCount();
1032 for (
int i = 0; i < colCount; i++ )
1041 void QgsDualView::autosizeColumn()
1043 QAction *action = qobject_cast<QAction *>( sender() );
1044 const int col = action->data().toInt();
1045 mTableView->resizeColumnToContents( col );
1048 void QgsDualView::autosizeAllColumns()
1050 mTableView->resizeColumnsToContents();
1053 bool QgsDualView::modifySort()
1061 orderByDlg.setWindowTitle( tr(
"Configure Attribute Table Sort Order" ) );
1062 QDialogButtonBox *dialogButtonBox =
new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
1063 QGridLayout *layout =
new QGridLayout();
1064 connect( dialogButtonBox, &QDialogButtonBox::accepted, &orderByDlg, &QDialog::accept );
1065 connect( dialogButtonBox, &QDialogButtonBox::rejected, &orderByDlg, &QDialog::reject );
1066 orderByDlg.setLayout( layout );
1068 QGroupBox *sortingGroupBox =
new QGroupBox();
1069 sortingGroupBox->setTitle( tr(
"Defined sort order in attribute table" ) );
1070 sortingGroupBox->setCheckable(
true );
1072 layout->addWidget( sortingGroupBox );
1073 sortingGroupBox->setLayout(
new QGridLayout() );
1078 expressionBuilder->
initWithLayer( mLayer, context, QStringLiteral(
"generic" ) );
1081 sortingGroupBox->layout()->addWidget( expressionBuilder );
1083 QCheckBox *cbxSortAscending =
new QCheckBox( tr(
"Sort ascending" ) );
1084 cbxSortAscending->setChecked( config.
sortOrder() == Qt::AscendingOrder );
1085 sortingGroupBox->layout()->addWidget( cbxSortAscending );
1087 layout->addWidget( dialogButtonBox );
1088 if ( orderByDlg.exec() )
1090 const Qt::SortOrder sortOrder = cbxSortAscending->isChecked() ? Qt::AscendingOrder : Qt::DescendingOrder;
1091 if ( sortingGroupBox->isChecked() )
1113 void QgsDualView::zoomToCurrentFeature()
1115 const QModelIndex currentIndex = mTableView->currentIndex();
1116 if ( !currentIndex.isValid() )
1122 ids.insert( mFilterModel->
rowToId( currentIndex ) );
1130 void QgsDualView::panToCurrentFeature()
1132 const QModelIndex currentIndex = mTableView->currentIndex();
1133 if ( !currentIndex.isValid() )
1139 ids.insert( mFilterModel->
rowToId( currentIndex ) );
1147 void QgsDualView::flashCurrentFeature()
1149 const QModelIndex currentIndex = mTableView->currentIndex();
1150 if ( !currentIndex.isValid() )
1156 ids.insert( mFilterModel->
rowToId( currentIndex ) );
1164 void QgsDualView::rebuildFullLayerCache()
1172 void QgsDualView::previewExpressionChanged(
const QString &expression )
1174 mLayer->setDisplayExpression( expression );
1177 void QgsDualView::onSortColumnChanged()
1181 cfg.
sortOrder() != mFilterModel->sortOrder() )
1189 void QgsDualView::updateSelectedFeatures()
1201 void QgsDualView::updateEditedAddedFeatures()
1213 void QgsDualView::extentChanged()
1226 void QgsDualView::featureFormAttributeChanged(
const QString &attribute,
const QVariant &value,
bool attributeChanged )
1228 Q_UNUSED( attribute )
1230 if ( attributeChanged )
1232 mFeatureListView->setCurrentFeatureEdited(
true );
1233 mAttributeForm->
save();
1256 mTableView->setFeatureSelectionManager( featureSelectionManager );
1257 mFeatureListView->setFeatureSelectionManager( featureSelectionManager );
1259 if ( mFeatureSelectionManager && mFeatureSelectionManager->parent() ==
this )
1260 delete mFeatureSelectionManager;
1262 mFeatureSelectionManager = featureSelectionManager;
1268 mConfig.
update( mLayer->fields() );
1269 mLayer->setAttributeTableConfig( mConfig );
1271 mTableView->setAttributeTableConfig( mConfig );
1277 mFilterModel->
sort( -1 );
1296 void QgsDualView::progress(
int i,
bool &cancel )
1298 if ( !mProgressDlg )
1300 mProgressDlg =
new QProgressDialog( tr(
"Loading features…" ), tr(
"Abort" ), 0, 0,
this );
1301 mProgressDlg->setWindowTitle( tr(
"Attribute Table" ) );
1302 mProgressDlg->setWindowModality( Qt::WindowModal );
1303 mProgressDlg->show();
1306 mProgressDlg->setLabelText( tr(
"%L1 features loaded." ).arg( i ) );
1307 QCoreApplication::processEvents();
1309 cancel = mProgressDlg && mProgressDlg->wasCanceled();
1312 void QgsDualView::finished()
1314 delete mProgressDlg;
1315 mProgressDlg =
nullptr;