17 #include <QHeaderView>
19 #include <QToolButton>
20 #include <QHBoxLayout>
22 #include "qgssettings.h"
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()->setContentsMargins( 0, 0, 0, 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 ) );
291 QgsSettings settings;
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();
503 QModelIndex index = mFilterModel->
fidToIndex( fid );
505 if ( !index.isValid() )
510 QModelIndex selectionIndex = index.sibling( index.row(), col );
512 if ( !selectionIndex.isValid() )
515 selectionModel()->setCurrentIndex( index, QItemSelectionModel::SelectCurrent );
QList< QgsAction > actions(const QString &actionScope=QString()) const
Returns a list of actions that are available in the given action scope.
void doAction(QUuid actionId, const QgsFeature &feature, int defaultValueIndex=0, const QgsExpressionContextScope &scope=QgsExpressionContextScope())
Does the given action.
QgsAction defaultAction(const QString &actionScope)
Each scope can have a default action.
Utility class that encapsulates an action based on vector attributes.
QUuid id() const
Returns a unique id for this action.
This is a container for configuration of the attribute table.
QVector< QgsAttributeTableConfig::ColumnConfig > columns() const
Gets the list with all columns and their configuration.
@ DropDown
A tool button with a drop-down to select the current action.
@ ButtonList
A list of buttons.
ActionWidgetStyle actionWidgetStyle() const
Gets the style of the action widget.
QString sortExpression() const
Gets the expression used for sorting.
A delegate item class for QgsAttributeTable (see Qt documentation for QItemDelegate).
void actionColumnItemPainted(const QModelIndex &index) const
Emitted when an action column item is painted.
void setFeatureSelectionModel(QgsFeatureSelectionModel *featureSelectionModel)
QgsVectorLayer * layer() const
Returns the layer this filter acts on.
QModelIndex fidToIndex(QgsFeatureId fid) override
QVariant data(const QModelIndex &index, int role) const override
QModelIndex mapToMaster(const QModelIndex &proxyIndex) const
QgsVectorLayerCache * layerCache() const
Returns the layerCache this filter acts on.
@ FeatureIdRole
Get the feature id of the feature in this row.
Provides a table view of features of a QgsVectorLayer.
void willShowContextMenu(QMenu *menu, const QModelIndex &atIndex)
Emitted in order to provide a hook to add additional* menu entries to the context menu.
QList< QgsFeatureId > selectedFeaturesIds() const
Returns the selected features in the attribute table in table sorted order.
void setFeatureSelectionManager(QgsIFeatureSelectionManager *featureSelectionManager)
setFeatureSelectionManager
void mouseMoveEvent(QMouseEvent *event) override
Called for mouse move events on a table cell.
virtual void selectRow(int row)
QgsAttributeTableView(QWidget *parent=nullptr)
Constructor for QgsAttributeTableView.
void selectAll() override
void scrollToFeature(const QgsFeatureId &fid, int column=-1)
Scroll to a feature with a given fid.
void mouseReleaseEvent(QMouseEvent *event) override
Called for mouse release events on a table cell.
void contextMenuEvent(QContextMenuEvent *event) override
Is called when the context menu will be shown.
virtual void _q_selectRow(int row)
void closeEvent(QCloseEvent *event) override
Saves geometry to the settings on close.
void mousePressEvent(QMouseEvent *event) override
Called for mouse press events on a table cell.
void keyPressEvent(QKeyEvent *event) override
Called for key press events Disables selection change by only pressing an arrow key.
void setAttributeTableConfig(const QgsAttributeTableConfig &config)
Set the attribute table config which should be used to control the appearance of the attribute table.
void columnResized(int column, int width)
Emitted when a column in the view has been resized.
bool eventFilter(QObject *object, QEvent *event) override
This event filter is installed on the verticalHeader to intercept mouse press and release events.
virtual void setModel(QgsAttributeTableFilterModel *filterModel)
bool nextFeature(QgsFeature &f)
This class wraps a request for features to a vector layer (or directly its vector data provider).
void enableSync(bool enable)
Enables or disables synchronisation to the QgsVectorLayer When synchronisation is disabled,...
virtual void selectFeatures(const QItemSelection &selection, QItemSelectionModel::SelectionFlags command)
Select features on this table.
virtual bool isSelected(QgsFeatureId fid)
Returns the selection status of a given feature id.
virtual void setFeatureSelectionManager(QgsIFeatureSelectionManager *featureSelectionManager)
void requestRepaint()
Request a repaint of the visible items of connected views.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
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.
virtual const QgsFeatureIds & selectedFeatureIds() const =0
Returns reference to identifiers of selected features.
QList< QgsMapLayerAction * > mapLayerActions(QgsMapLayer *layer, QgsMapLayerAction::Targets targets=QgsMapLayerAction::AllActions)
Returns the map layer actions which can run on the specified layer.
void changed()
Triggered when an action is added or removed from the registry.
An action which can run on map layers The class can be used in two manners:
QgsFeatureIterator getFeatures(const QgsFeatureRequest &featureRequest=QgsFeatureRequest())
Query this VectorLayerCache for features.
Represents a vector layer which manages a vector based data sets.
void editingStopped()
Emitted when edited changes have been successfully written to the data provider.
void editingStarted()
Emitted when editing on this layer has started.
bool isEditable() const FINAL
Returns true if the provider is in editing mode.
QgsActionManager * actions()
Returns all layer actions defined on this layer.
void readOnlyChanged()
Emitted when the read only state of this layer is changed.
bool restoreGeometry(QWidget *widget, const QString &keyName)
Restore the wigget geometry from settings.
void saveGeometry(QWidget *widget, const QString &keyName)
Save the wigget geometry into settings.
QSet< QgsFeatureId > QgsFeatureIds
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
Defines the configuration of a column in the attribute table.