17 #include <QHeaderView>
19 #include <QToolButton>
20 #include <QHBoxLayout>
40 : QTableView( parent )
43 restoreGeometry( settings.
value( QStringLiteral(
"BetterAttributeTable/geometry" ) ).toByteArray() );
46 horizontalHeader()->setHighlightSections(
false );
50 setItemDelegate( mTableDelegate );
52 setEditTriggers( QAbstractItemView::AllEditTriggers );
54 setSelectionBehavior( QAbstractItemView::SelectRows );
55 setSelectionMode( QAbstractItemView::ExtendedSelection );
56 setSortingEnabled(
true );
57 horizontalHeader()->setSortIndicatorShown(
false );
59 setHorizontalScrollMode( QAbstractItemView::ScrollPerPixel );
61 verticalHeader()->viewport()->installEventFilter(
this );
63 connect( verticalHeader(), &QHeaderView::sectionPressed,
this, [ = ](
int row ) {
selectRow( row,
true ); } );
65 connect( horizontalHeader(), &QHeaderView::sectionResized,
this, &QgsAttributeTableView::columnSizeChanged );
66 connect( horizontalHeader(), &QHeaderView::sortIndicatorChanged,
this, &QgsAttributeTableView::showHorizontalSortIndicator );
72 if (
object == verticalHeader()->viewport() )
74 switch ( event->type() )
76 case QEvent::MouseButtonPress:
80 case QEvent::MouseButtonRelease:
88 return QTableView::eventFilter(
object, event );
94 const auto constColumns = config.
columns();
97 if ( columnConfig.hidden )
100 if ( columnConfig.width >= 0 )
102 setColumnWidth( i, columnConfig.width );
106 setColumnWidth( i, horizontalHeader()->defaultSectionSize() );
112 horizontalHeader()->setSortIndicatorShown(
false );
121 QModelIndexList indexList;
124 QModelIndex index = mFilterModel->
fidToIndex(
id );
128 std::sort( indexList.begin(), indexList.end() );
129 QList<QgsFeatureId> ids;
130 for (
const QModelIndex &index : indexList )
140 mFilterModel = filterModel;
141 QTableView::setModel( mFilterModel );
145 connect( mFilterModel, &QObject::destroyed,
this, &QgsAttributeTableView::modelDeleted );
149 delete mFeatureSelectionModel;
150 mFeatureSelectionModel =
nullptr;
154 if ( !mFeatureSelectionManager )
157 mFeatureSelectionManager = mOwnedFeatureSelectionManager;
160 mFeatureSelectionModel =
new QgsFeatureSelectionModel( mFilterModel, mFilterModel, mFeatureSelectionManager, mFilterModel );
161 setSelectionModel( mFeatureSelectionModel );
176 mFeatureSelectionManager = featureSelectionManager;
178 if ( mFeatureSelectionModel )
182 if ( mOwnedFeatureSelectionManager )
184 mOwnedFeatureSelectionManager->deleteLater();
185 mOwnedFeatureSelectionManager =
nullptr;
189 QWidget *QgsAttributeTableView::createActionWidget(
QgsFeatureId fid )
193 QToolButton *toolButton =
nullptr;
194 QWidget *container =
nullptr;
198 toolButton =
new QToolButton();
199 toolButton->setToolButtonStyle( Qt::ToolButtonTextBesideIcon );
200 toolButton->setPopupMode( QToolButton::MenuButtonPopup );
201 container = toolButton;
205 container =
new QWidget();
206 container->setLayout(
new QHBoxLayout() );
207 container->layout()->setMargin( 0 );
210 QList< QAction * > actionList;
211 QAction *defaultAction =
nullptr;
214 QList<QgsAction> actions = mFilterModel->
layer()->
actions()->
actions( QStringLiteral(
"Feature" ) );
215 const auto constActions = actions;
216 for (
const QgsAction &action : constActions )
218 if ( !mFilterModel->
layer()->
isEditable() && action.isEnabledOnlyWhenEditable() )
221 QString actionTitle = !action.shortTitle().isEmpty() ? action.shortTitle() : action.icon().isNull() ? action.name() : QString();
222 QAction *act =
new QAction( action.icon(), actionTitle, container );
223 act->setToolTip( action.name() );
224 act->setData(
"user_action" );
225 act->setProperty(
"fid", fid );
226 act->setProperty(
"action_id", action.id() );
227 connect( act, &QAction::triggered,
this, &QgsAttributeTableView::actionTriggered );
238 QAction *action =
new QAction( mapLayerAction->icon(), mapLayerAction->text(), container );
239 action->setData(
"map_layer_action" );
240 action->setToolTip( mapLayerAction->text() );
241 action->setProperty(
"fid", fid );
242 action->setProperty(
"action", QVariant::fromValue( qobject_cast<QObject *>( mapLayerAction ) ) );
243 connect( action, &QAction::triggered,
this, &QgsAttributeTableView::actionTriggered );
244 actionList << action;
246 if ( !defaultAction &&
248 defaultAction = action;
251 if ( !defaultAction && !actionList.isEmpty() )
252 defaultAction = actionList.at( 0 );
254 const auto constActionList = actionList;
255 for ( QAction *act : constActionList )
259 toolButton->addAction( act );
261 if ( act == defaultAction )
262 toolButton->setDefaultAction( act );
264 container = toolButton;
268 QToolButton *btn =
new QToolButton;
269 btn->setDefaultAction( act );
270 container->layout()->addWidget( btn );
276 static_cast< QHBoxLayout *
>( container->layout() )->addStretch();
281 if ( toolButton && !toolButton->actions().isEmpty() && actions->defaultAction() == -1 )
282 toolButton->setDefaultAction( toolButton->actions().at( 0 ) );
292 settings.
setValue( QStringLiteral(
"BetterAttributeTable/geometry" ), QVariant(
saveGeometry() ) );
297 setSelectionMode( QAbstractItemView::NoSelection );
298 QTableView::mousePressEvent( event );
299 setSelectionMode( QAbstractItemView::ExtendedSelection );
304 setSelectionMode( QAbstractItemView::NoSelection );
305 QTableView::mouseReleaseEvent( event );
306 setSelectionMode( QAbstractItemView::ExtendedSelection );
311 setSelectionMode( QAbstractItemView::NoSelection );
312 QTableView::mouseMoveEvent( event );
313 setSelectionMode( QAbstractItemView::ExtendedSelection );
318 switch ( event->key() )
327 setSelectionMode( QAbstractItemView::NoSelection );
328 QTableView::keyPressEvent( event );
329 setSelectionMode( QAbstractItemView::ExtendedSelection );
333 QTableView::keyPressEvent( event );
340 const auto constIndexes = indexes;
341 for (
const QModelIndex &index : constIndexes )
349 setDirtyRegion( viewport()->rect() );
354 QItemSelection selection;
355 selection.append( QItemSelectionRange( mFilterModel->index( 0, 0 ), mFilterModel->index( mFilterModel->rowCount() - 1, 0 ) ) );
356 mFeatureSelectionModel->
selectFeatures( selection, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows );
362 mActionPopup =
nullptr;
364 const QModelIndex idx = mFilterModel->
mapToMaster( indexAt( event->pos() ) );
365 if ( !idx.isValid() )
374 mActionPopup =
new QMenu(
this );
376 QAction *selectAllAction = mActionPopup->addAction( tr(
"Select All" ) );
377 selectAllAction->setShortcut( QKeySequence::SelectAll );
383 if ( !mActionPopup->actions().isEmpty() )
385 mActionPopup->popup( event->globalPos() );
399 void QgsAttributeTableView::modelDeleted()
401 mFilterModel =
nullptr;
402 mFeatureSelectionManager =
nullptr;
403 mFeatureSelectionModel =
nullptr;
408 if ( selectionBehavior() == QTableView::SelectColumns
409 || ( selectionMode() == QTableView::SingleSelection
410 && selectionBehavior() == QTableView::SelectItems ) )
413 if ( row >= 0 && row < model()->rowCount() )
415 int column = horizontalHeader()->logicalIndexAt( isRightToLeft() ? viewport()->width() : 0 );
416 QModelIndex index = model()->index( row, column );
417 QItemSelectionModel::SelectionFlags command = selectionCommand( index );
418 selectionModel()->setCurrentIndex( index, QItemSelectionModel::NoUpdate );
419 if ( ( anchor && !( command & QItemSelectionModel::Current ) )
420 || ( selectionMode() == QTableView::SingleSelection ) )
421 mRowSectionAnchor = row;
423 if ( selectionMode() != QTableView::SingleSelection
424 && command.testFlag( QItemSelectionModel::Toggle ) )
427 mCtrlDragSelectionFlag = mFeatureSelectionModel->
isSelected( index )
428 ? QItemSelectionModel::Deselect : QItemSelectionModel::Select;
429 command &= ~QItemSelectionModel::Toggle;
430 command |= mCtrlDragSelectionFlag;
432 command |= QItemSelectionModel::Current;
435 QModelIndex tl = model()->index( std::min( mRowSectionAnchor, row ), 0 );
436 QModelIndex br = model()->index( std::max( mRowSectionAnchor, row ), model()->columnCount() - 1 );
437 if ( verticalHeader()->sectionsMoved() && tl.row() != br.row() )
438 setSelection( visualRect( tl ) | visualRect( br ), command );
440 mFeatureSelectionModel->
selectFeatures( QItemSelection( tl, br ), command );
444 void QgsAttributeTableView::showHorizontalSortIndicator()
446 horizontalHeader()->setSortIndicatorShown(
true );
449 void QgsAttributeTableView::actionTriggered()
451 QAction *action = qobject_cast<QAction *>( sender() );
452 QgsFeatureId fid = action->property(
"fid" ).toLongLong();
457 if ( action->data().toString() == QLatin1String(
"user_action" ) )
461 else if ( action->data().toString() == QLatin1String(
"map_layer_action" ) )
463 QObject *
object = action->property(
"action" ).value<QObject *>();
467 layerAction->triggerForFeature( mFilterModel->
layer(), f );
472 void QgsAttributeTableView::columnSizeChanged(
int index,
int oldWidth,
int newWidth )
478 void QgsAttributeTableView::onActionColumnItemPainted(
const QModelIndex &index )
480 if ( !indexWidget( index ) )
483 mActionWidgets.insert( index, widget );
484 setIndexWidget( index, widget );
488 void QgsAttributeTableView::recreateActionWidgets()
490 QMap< QModelIndex, QWidget * >::const_iterator it = mActionWidgets.constBegin();
491 for ( ; it != mActionWidgets.constEnd(); ++it )
496 setIndexWidget( it.key(),
nullptr );
498 mActionWidgets.clear();