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 verticalHeader()->viewport()->installEventFilter(
this );
61 connect( verticalHeader(), &QHeaderView::sectionPressed,
this, [ = ](
int row ) {
selectRow( row,
true ); } );
63 connect( horizontalHeader(), &QHeaderView::sectionResized,
this, &QgsAttributeTableView::columnSizeChanged );
64 connect( horizontalHeader(), &QHeaderView::sortIndicatorChanged,
this, &QgsAttributeTableView::showHorizontalSortIndicator );
70 if (
object == verticalHeader()->viewport() )
72 switch ( event->type() )
74 case QEvent::MouseButtonPress:
78 case QEvent::MouseButtonRelease:
86 return QTableView::eventFilter(
object, event );
92 const auto constColumns = config.
columns();
95 if ( columnConfig.hidden )
98 if ( columnConfig.width >= 0 )
100 setColumnWidth( i, columnConfig.width );
104 setColumnWidth( i, horizontalHeader()->defaultSectionSize() );
117 QModelIndexList indexList;
120 QModelIndex index = mFilterModel->
fidToIndex(
id );
124 std::sort( indexList.begin(), indexList.end() );
125 QList<QgsFeatureId> ids;
126 for (
const QModelIndex &index : indexList )
136 mFilterModel = filterModel;
137 QTableView::setModel( mFilterModel );
141 connect( mFilterModel, &QObject::destroyed,
this, &QgsAttributeTableView::modelDeleted );
145 delete mFeatureSelectionModel;
146 mFeatureSelectionModel =
nullptr;
150 if ( !mFeatureSelectionManager )
155 mFeatureSelectionModel =
new QgsFeatureSelectionModel( mFilterModel, mFilterModel, mFeatureSelectionManager, mFilterModel );
156 setSelectionModel( mFeatureSelectionModel );
171 delete mFeatureSelectionManager;
173 mFeatureSelectionManager = featureSelectionManager;
175 if ( mFeatureSelectionModel )
179 QWidget *QgsAttributeTableView::createActionWidget(
QgsFeatureId fid )
183 QToolButton *toolButton =
nullptr;
184 QWidget *container =
nullptr;
188 toolButton =
new QToolButton();
189 toolButton->setToolButtonStyle( Qt::ToolButtonTextBesideIcon );
190 toolButton->setPopupMode( QToolButton::MenuButtonPopup );
191 container = toolButton;
195 container =
new QWidget();
196 container->setLayout(
new QHBoxLayout() );
197 container->layout()->setMargin( 0 );
200 QList< QAction * > actionList;
201 QAction *defaultAction =
nullptr;
204 QList<QgsAction> actions = mFilterModel->
layer()->
actions()->
actions( QStringLiteral(
"Feature" ) );
205 const auto constActions = actions;
206 for (
const QgsAction &action : constActions )
208 if ( !mFilterModel->
layer()->
isEditable() && action.isEnabledOnlyWhenEditable() )
211 QString actionTitle = !action.shortTitle().isEmpty() ? action.shortTitle() : action.icon().isNull() ? action.name() : QString();
212 QAction *act =
new QAction( action.icon(), actionTitle, container );
213 act->setToolTip( action.name() );
214 act->setData(
"user_action" );
215 act->setProperty(
"fid", fid );
216 act->setProperty(
"action_id", action.id() );
217 connect( act, &QAction::triggered,
this, &QgsAttributeTableView::actionTriggered );
228 QAction *action =
new QAction( mapLayerAction->icon(), mapLayerAction->text(), container );
229 action->setData(
"map_layer_action" );
230 action->setToolTip( mapLayerAction->text() );
231 action->setProperty(
"fid", fid );
232 action->setProperty(
"action", qVariantFromValue( qobject_cast<QObject *>( mapLayerAction ) ) );
233 connect( action, &QAction::triggered,
this, &QgsAttributeTableView::actionTriggered );
234 actionList << action;
236 if ( !defaultAction &&
238 defaultAction = action;
241 if ( !defaultAction && !actionList.isEmpty() )
242 defaultAction = actionList.at( 0 );
244 const auto constActionList = actionList;
245 for ( QAction *act : constActionList )
249 toolButton->addAction( act );
251 if ( act == defaultAction )
252 toolButton->setDefaultAction( act );
254 container = toolButton;
258 QToolButton *btn =
new QToolButton;
259 btn->setDefaultAction( act );
260 container->layout()->addWidget( btn );
266 static_cast< QHBoxLayout *
>( container->layout() )->addStretch();
271 if ( toolButton && !toolButton->actions().isEmpty() && actions->defaultAction() == -1 )
272 toolButton->setDefaultAction( toolButton->actions().at( 0 ) );
282 settings.
setValue( QStringLiteral(
"BetterAttributeTable/geometry" ), QVariant(
saveGeometry() ) );
287 setSelectionMode( QAbstractItemView::NoSelection );
288 QTableView::mousePressEvent( event );
289 setSelectionMode( QAbstractItemView::ExtendedSelection );
294 setSelectionMode( QAbstractItemView::NoSelection );
295 QTableView::mouseReleaseEvent( event );
296 setSelectionMode( QAbstractItemView::ExtendedSelection );
301 setSelectionMode( QAbstractItemView::NoSelection );
302 QTableView::mouseMoveEvent( event );
303 setSelectionMode( QAbstractItemView::ExtendedSelection );
308 switch ( event->key() )
317 setSelectionMode( QAbstractItemView::NoSelection );
318 QTableView::keyPressEvent( event );
319 setSelectionMode( QAbstractItemView::ExtendedSelection );
323 QTableView::keyPressEvent( event );
330 const auto constIndexes = indexes;
331 for (
const QModelIndex &index : constIndexes )
339 setDirtyRegion( viewport()->rect() );
344 QItemSelection selection;
345 selection.append( QItemSelectionRange( mFilterModel->index( 0, 0 ), mFilterModel->index( mFilterModel->rowCount() - 1, 0 ) ) );
346 mFeatureSelectionModel->
selectFeatures( selection, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows );
352 mActionPopup =
nullptr;
354 QModelIndex idx = indexAt( event->pos() );
355 if ( !idx.isValid() )
364 mActionPopup =
new QMenu(
this );
366 mActionPopup->addAction( tr(
"Select All" ),
this, SLOT(
selectAll() ), QKeySequence::SelectAll );
371 if ( !mActionPopup->actions().isEmpty() )
373 mActionPopup->popup( event->globalPos() );
387 void QgsAttributeTableView::modelDeleted()
389 mFilterModel =
nullptr;
390 mFeatureSelectionManager =
nullptr;
391 mFeatureSelectionModel =
nullptr;
396 if ( selectionBehavior() == QTableView::SelectColumns
397 || ( selectionMode() == QTableView::SingleSelection
398 && selectionBehavior() == QTableView::SelectItems ) )
401 if ( row >= 0 && row < model()->rowCount() )
403 int column = horizontalHeader()->logicalIndexAt( isRightToLeft() ? viewport()->width() : 0 );
404 QModelIndex index = model()->index( row, column );
405 QItemSelectionModel::SelectionFlags command = selectionCommand( index );
406 selectionModel()->setCurrentIndex( index, QItemSelectionModel::NoUpdate );
407 if ( ( anchor && !( command & QItemSelectionModel::Current ) )
408 || ( selectionMode() == QTableView::SingleSelection ) )
409 mRowSectionAnchor = row;
411 if ( selectionMode() != QTableView::SingleSelection
412 && command.testFlag( QItemSelectionModel::Toggle ) )
415 mCtrlDragSelectionFlag = mFeatureSelectionModel->
isSelected( index )
416 ? QItemSelectionModel::Deselect : QItemSelectionModel::Select;
417 command &= ~QItemSelectionModel::Toggle;
418 command |= mCtrlDragSelectionFlag;
420 command |= QItemSelectionModel::Current;
423 QModelIndex tl = model()->index( std::min( mRowSectionAnchor, row ), 0 );
424 QModelIndex br = model()->index( std::max( mRowSectionAnchor, row ), model()->columnCount() - 1 );
425 if ( verticalHeader()->sectionsMoved() && tl.row() != br.row() )
426 setSelection( visualRect( tl ) | visualRect( br ), command );
428 mFeatureSelectionModel->
selectFeatures( QItemSelection( tl, br ), command );
432 void QgsAttributeTableView::showHorizontalSortIndicator()
434 horizontalHeader()->setSortIndicatorShown(
true );
437 void QgsAttributeTableView::actionTriggered()
439 QAction *action = qobject_cast<QAction *>( sender() );
440 QgsFeatureId fid = action->property(
"fid" ).toLongLong();
445 if ( action->data().toString() == QLatin1String(
"user_action" ) )
449 else if ( action->data().toString() == QLatin1String(
"map_layer_action" ) )
451 QObject *
object = action->property(
"action" ).value<QObject *>();
460 void QgsAttributeTableView::columnSizeChanged(
int index,
int oldWidth,
int newWidth )
466 void QgsAttributeTableView::onActionColumnItemPainted(
const QModelIndex &index )
468 if ( !indexWidget( index ) )
471 mActionWidgets.insert( index, widget );
472 setIndexWidget( index, widget );
476 void QgsAttributeTableView::recreateActionWidgets()
478 QMap< QModelIndex, QWidget * >::const_iterator it = mActionWidgets.constBegin();
479 for ( ; it != mActionWidgets.constEnd(); ++it )
484 setIndexWidget( it.key(), nullptr );
486 mActionWidgets.clear();
QgsActionManager * actions()
Returns all layer actions defined on this layer.
QgsVectorLayer * layer() const
Returns the layer this filter acts on.
QVariant data(const QModelIndex &index, int role) const override
Provides a table view of features of a QgsVectorLayer.
virtual bool isSelected(QgsFeatureId fid)
Returns the selection status of a given feature id.
void doAction(QUuid actionId, const QgsFeature &feature, int defaultValueIndex=0, const QgsExpressionContextScope &scope=QgsExpressionContextScope())
Does the given action.
QSet< QgsFeatureId > QgsFeatureIds
void willShowContextMenu(QMenu *menu, const QModelIndex &atIndex)
Emitted in order to provide a hook to add additional* menu entries to the context menu...
QgsAttributeTableView(QWidget *parent=nullptr)
Constructor for QgsAttributeTableView.
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 readOnlyChanged()
Emitted when the read only state of this layer is changed.
virtual void selectFeatures(const QItemSelection &selection, QItemSelectionModel::SelectionFlags command)
Select features on this table.
QList< QgsAction > actions(const QString &actionScope=QString()) const
Returns a list of actions that are available in the given action scope.
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...
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
void selectAll() override
void actionColumnItemPainted(const QModelIndex &index) const
Emitted when an action column item is painted.
void enableSync(bool enable)
Enables or disables synchronisation to the QgsVectorLayer When synchronisation is disabled...
void setFeatureSelectionModel(QgsFeatureSelectionModel *featureSelectionModel)
void mouseReleaseEvent(QMouseEvent *event) override
Called for mouse release events on a table cell.
void saveGeometry(QWidget *widget, const QString &keyName)
Save the wigget geometry into settings.
Get the feature id of the feature in this row.
bool isEditable() const FINAL
Returns true if the provider is in editing mode.
bool restoreGeometry(QWidget *widget, const QString &keyName)
Restore the wigget geometry from settings.
ActionWidgetStyle actionWidgetStyle() const
Gets the style of the action widget.
void requestRepaint()
Request a repaint of the visible items of connected views.
Utility class that encapsulates an action based on vector attributes.
virtual const QgsFeatureIds & selectedFeatureIds() const =0
Returns reference to identifiers of selected features.
void editingStopped()
Emitted when edited changes have been successfully written to the data provider.
void mousePressEvent(QMouseEvent *event) override
Called for mouse press events on a table cell.
This class wraps a request for features to a vector layer (or directly its vector data provider)...
virtual void setFeatureSelectionManager(QgsIFeatureSelectionManager *featureSelectionManager)
void changed()
Triggered when an action is added or removed from the registry.
QgsAction defaultAction(const QString &actionScope)
Each scope can have a default action.
virtual void setModel(QgsAttributeTableFilterModel *filterModel)
void editingStarted()
Emitted when editing on this layer has started.
void mouseMoveEvent(QMouseEvent *event) override
Called for mouse move events on a table cell.
QVector< QgsAttributeTableConfig::ColumnConfig > columns() const
Gets the list with all columns and their configuration.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
A tool button with a drop-down to select the current action.
void setFeatureSelectionManager(QgsIFeatureSelectionManager *featureSelectionManager)
setFeatureSelectionManager
A delegate item class for QgsAttributeTable (see Qt documentation for QItemDelegate).
void setAttributeTableConfig(const QgsAttributeTableConfig &config)
Set the attribute table config which should be used to control the appearance of the attribute table...
QList< QgsMapLayerAction * > mapLayerActions(QgsMapLayer *layer, QgsMapLayerAction::Targets targets=QgsMapLayerAction::AllActions)
Returns the map layer actions which can run on the specified layer.
Defines the configuration of a column in the attribute table.
virtual void selectRow(int row)
QUuid id() const
Returns a unique id for this action.
virtual void _q_selectRow(int row)
bool nextFeature(QgsFeature &f)
This is a container for configuration of the attribute table.
Is an interface class to abstract feature selection handling.
void closeEvent(QCloseEvent *event) override
Saves geometry to the settings on close.
Represents a vector layer which manages a vector based data sets.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &featureRequest=QgsFeatureRequest())
Query this VectorLayerCache for features.
static QgsMapLayerActionRegistry * mapLayerActionRegistry()
Returns the global map layer action registry, used for registering map layer actions.
void triggerForFeature(QgsMapLayer *layer, const QgsFeature *feature)
Triggers the action with the specified layer and feature.
An action which can run on map layers.
QList< QgsFeatureId > selectedFeaturesIds() const
Returns the selected features in the attribute table in table sorted order.
void keyPressEvent(QKeyEvent *event) override
Called for key press events Disables selection change by only pressing an arrow key.
void contextMenuEvent(QContextMenuEvent *event) override
Is called when the context menu will be shown.
QgsVectorLayerCache * layerCache() const
Returns the layerCache this filter acts on.
QModelIndex fidToIndex(QgsFeatureId fid) override