34#include "moc_qgsfeaturelistview.cpp"
39 setSelectionMode( QAbstractItemView::ExtendedSelection );
41 mUpdateEditSelectionTimerWithSelection.setSingleShot(
true );
42 connect( &mUpdateEditSelectionTimerWithSelection, &QTimer::timeout,
this, [
this]() {
43 updateEditSelection(
true );
46 mUpdateEditSelectionTimerWithSelection.setInterval( 0 );
48 mUpdateEditSelectionTimerWithoutSelection.setSingleShot(
true );
49 connect( &mUpdateEditSelectionTimerWithoutSelection, &QTimer::timeout,
this, [
this]() {
50 updateEditSelection(
false );
53 mUpdateEditSelectionTimerWithoutSelection.setInterval( 0 );
58 return mModel->layerCache();
66 delete mFeatureSelectionModel;
67 delete mCurrentEditSelectionModel;
69 mCurrentEditSelectionModel =
new QItemSelectionModel( mModel->masterModel(),
this );
70 if ( !mFeatureSelectionManager )
73 mFeatureSelectionManager = mOwnedFeatureSelectionManager;
77 setSelectionModel( mFeatureSelectionModel );
79 ensureEditSelection( true );
82 if ( mItemDelegate && mItemDelegate->parent() ==
this )
88 mItemDelegate->setEditSelectionModel( mCurrentEditSelectionModel );
89 setItemDelegate( mItemDelegate );
91 mItemDelegate->setFeatureSelectionModel( mFeatureSelectionModel );
94 connect( mCurrentEditSelectionModel, &QItemSelectionModel::selectionChanged,
this, &QgsFeatureListView::editSelectionChanged );
96 connect(
featureListModel, &QgsFeatureListModel::rowsRemoved,
this, [
this]() { ensureEditSelection(); } );
97 connect(
featureListModel, &QgsFeatureListModel::rowsInserted,
this, [
this]() { ensureEditSelection(); } );
98 connect(
featureListModel, &QgsFeatureListModel::modelReset,
this, [
this]() { ensureEditSelection(); } );
103 if ( mModel->setDisplayExpression( expression ) )
116 return mModel->displayExpression();
121 return mModel->parserErrorString();
127 const QModelIndexList selectedIndexes = mCurrentEditSelectionModel->selectedIndexes();
128 for (
const QModelIndex &idx : selectedIndexes )
137 mItemDelegate->setCurrentFeatureEdited( state );
138 viewport()->update( visualRegionForSelection( mCurrentEditSelectionModel->selection() ) );
143 if ( event->button() != Qt::LeftButton )
145 QListView::mousePressEvent( event );
151 const QPoint pos =
event->pos();
153 const QModelIndex index = indexAt( pos );
157 mDragMode = DragMode::MoveSelection;
158 if ( index.isValid() )
159 setEditSelection( mModel->mapToMaster( index ), QItemSelectionModel::ClearAndSelect );
163 mDragMode = DragMode::ExpandSelection;
164 mFeatureSelectionModel->enableSync(
false );
165 selectRow( index,
true );
171 QgsDebugError( QStringLiteral(
"No model assigned to this view" ) );
175void QgsFeatureListView::editSelectionChanged(
const QItemSelection &selected,
const QItemSelection &deselected )
177 if ( isVisible() && updatesEnabled() )
181 viewport()->update( visualRegionForSelection( localDeselected ) | visualRegionForSelection( localSelected ) );
185 if ( !selected.isEmpty() )
187 const QModelIndexList indexList = selected.indexes();
188 if ( !indexList.isEmpty() )
190 QgsFeature selectedFeature;
191 mModel->featureByIndex( mModel->mapFromMaster( indexList.first() ), selectedFeature );
192 mLastEditSelectionFid = selectedFeature.
id();
196 const QItemSelection currentSelection = mCurrentEditSelectionModel->selection();
197 if ( currentSelection.size() == 1 )
199 QModelIndexList indexList = currentSelection.indexes();
200 if ( !indexList.isEmpty() )
203 mModel->featureByIndex( mModel->mapFromMaster( indexList.first() ), feat );
209 else if ( mModel->rowCount() == 0 )
217 QItemSelection selection;
218 selection.append( QItemSelectionRange( mModel->index( 0, 0 ), mModel->index( mModel->rowCount() - 1, 0 ) ) );
220 mFeatureSelectionModel->selectFeatures( selection, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows );
225 QItemSelection selection;
226 QModelIndex firstModelIdx;
228 const auto constFids = fids;
231 const QModelIndex modelIdx = mModel->fidToIdx( fid );
233 if ( !firstModelIdx.isValid() )
234 firstModelIdx = modelIdx;
236 selection.append( QItemSelectionRange( mModel->mapToMaster( modelIdx ) ) );
244 mCurrentEditSelectionModel->select( selection, QItemSelectionModel::ClearAndSelect );
245 scrollTo( firstModelIdx );
255 Q_ASSERT( index.model() == mModel->masterModel() || !index.isValid() );
259 mCurrentEditSelectionModel->select( index, command );
266 const auto constIndexes = indexes;
267 for (
const QModelIndex &index : constIndexes )
275 setDirtyRegion( viewport()->rect() );
282 const QPoint pos =
event->pos();
283 const QModelIndex index = indexAt( pos );
287 case QgsFeatureListView::DragMode::Inactive:
290 case QgsFeatureListView::DragMode::ExpandSelection:
292 selectRow( index,
false );
296 case QgsFeatureListView::DragMode::MoveSelection:
298 if ( index.isValid() )
299 setEditSelection( mModel->mapToMaster( index ), QItemSelectionModel::ClearAndSelect );
306 QgsDebugError( QStringLiteral(
"No model assigned to this view" ) );
312 if ( event->button() != Qt::LeftButton )
314 QListView::mouseReleaseEvent( event );
320 case QgsFeatureListView::DragMode::ExpandSelection:
321 if ( mFeatureSelectionModel )
322 mFeatureSelectionModel->enableSync(
true );
324 case QgsFeatureListView::DragMode::Inactive:
325 case QgsFeatureListView::DragMode::MoveSelection:
329 mDragMode = DragMode::Inactive;
334 switch ( event->key() )
337 editOtherFeature( Previous );
341 editOtherFeature( Next );
345 QListView::keyPressEvent( event );
349void QgsFeatureListView::editOtherFeature( QgsFeatureListView::PositionInList positionInList )
352 if ( 0 != mCurrentEditSelectionModel->selectedIndexes().count() )
354 const QModelIndex localIndex = mModel->
mapFromMaster( mCurrentEditSelectionModel->selectedIndexes().first() );
355 currentRow = localIndex.row();
358 QModelIndex newLocalIndex;
359 QModelIndex newIndex;
361 switch ( positionInList )
364 newLocalIndex = mModel->index( 0, 0 );
368 newLocalIndex = mModel->index( currentRow - 1, 0 );
372 newLocalIndex = mModel->index( currentRow + 1, 0 );
376 newLocalIndex = mModel->index( mModel->rowCount() - 1, 0 );
380 newIndex = mModel->mapToMaster( newLocalIndex );
381 if ( newIndex.isValid() )
384 scrollTo( newLocalIndex );
390 const QModelIndex index = indexAt( event->pos() );
392 if ( index.isValid() )
404 menu->exec( event->globalPos() );
408void QgsFeatureListView::selectRow(
const QModelIndex &index,
bool anchor )
410 QItemSelectionModel::SelectionFlags command = selectionCommand( index );
411 const int row = index.row();
416 if ( selectionMode() != QListView::SingleSelection
417 && command.testFlag( QItemSelectionModel::Toggle ) )
420 mCtrlDragSelectionFlag = mFeatureSelectionModel->
isSelected( index )
421 ? QItemSelectionModel::Deselect
422 : QItemSelectionModel::Select;
423 command &= ~QItemSelectionModel::Toggle;
424 command |= mCtrlDragSelectionFlag;
426 command |= QItemSelectionModel::Current;
429 const QModelIndex tl = model()->index( std::min( mRowAnchor, row ), 0 );
430 const QModelIndex br = model()->index( std::max( mRowAnchor, row ), model()->columnCount() - 1 );
432 mFeatureSelectionModel->selectFeatures( QItemSelection( tl, br ), command );
435void QgsFeatureListView::ensureEditSelection(
bool inSelection )
439 mUpdateEditSelectionTimerWithSelection.start();
443 mUpdateEditSelectionTimerWithoutSelection.start();
447void QgsFeatureListView::updateEditSelection(
bool inSelection )
449 if ( !mModel->rowCount() )
457 const QModelIndexList selectedIndexes = mCurrentEditSelectionModel->selectedIndexes();
463 bool editSelectionUpdateRequested =
false;
466 bool validEditSelectionAvailable =
false;
468 if ( selectedIndexes.isEmpty() || !selectedIndexes.first().isValid() || mModel->mapFromMaster( selectedIndexes.first() ).row() == -1 )
470 validEditSelectionAvailable =
false;
474 validEditSelectionAvailable =
true;
482 if ( !validEditSelectionAvailable )
484 editSelectionUpdateRequested =
true;
491 if ( !selectedFids.contains( mModel->idxToFid( mModel->mapFromMaster( selectedIndexes.first() ) ) ) )
493 editSelectionUpdateRequested =
true;
501 if ( !validEditSelectionAvailable )
502 editSelectionUpdateRequested =
true;
505 if ( editSelectionUpdateRequested )
512 int rowToSelect = -1;
522 if ( selectedFids.isEmpty() )
528 const int rowCount = mModel->rowCount();
529 for (
int i = 0; i < rowCount; i++ )
531 if ( selectedFids.contains( mModel->idxToFid( mModel->index( i, 0 ) ) ) )
538 if ( rowToSelect == -1 && !validEditSelectionAvailable )
544 if ( rowToSelect != -1 )
546 setEditSelection( mModel->mapToMaster( mModel->index( rowToSelect, 0 ) ), QItemSelectionModel::ClearAndSelect );
553 mFeatureSelectionManager = featureSelectionManager;
555 if ( mFeatureSelectionModel )
556 mFeatureSelectionModel->setFeatureSelectionManager( mFeatureSelectionManager );
559 if ( mOwnedFeatureSelectionManager )
561 mOwnedFeatureSelectionManager->deleteLater();
562 mOwnedFeatureSelectionManager =
nullptr;
@ FeatureId
Get the feature id of the feature in this row.
A proxy model for feature lists.
virtual QModelIndex mapFromMaster(const QModelIndex &sourceIndex) const
@ FeatureWithGeometryRole
Feature with all attributes and geometry,.
virtual QItemSelection mapSelectionFromMaster(const QItemSelection &selection) const
Custom item delegate for feature list views.
void currentEditSelectionProgressChanged(int progress, int count)
Emitted whenever the current edit selection has been changed.
const QString displayExpression() const
Returns the expression which is currently used to render the features.
void keyPressEvent(QKeyEvent *event) override
void contextMenuEvent(QContextMenuEvent *event) override
void setCurrentFeatureEdited(bool state)
Sets if the currently shown form has received any edit events so far.
void displayExpressionChanged(const QString &expression)
Emitted whenever the display expression is successfully changed.
void repaintRequested(const QModelIndexList &indexes)
void mouseMoveEvent(QMouseEvent *event) override
void setEditSelection(const QgsFeatureIds &fids)
Set the feature(s) to be edited.
void setFeatureSelectionManager(QgsIFeatureSelectionManager *featureSelectionManager)
setFeatureSelectionManager
QgsFeatureIds currentEditSelection()
Gets the currentEditSelection.
void mousePressEvent(QMouseEvent *event) override
bool setDisplayExpression(const QString &displayExpression)
The display expression is an expression used to render the fields into a single string which is displ...
void selectAll() override
Select all currently visible features.
QgsVectorLayerCache * layerCache()
Returns the layer cache.
QString parserErrorString()
Returns a detailed message about errors while parsing a QgsExpression.
void mouseReleaseEvent(QMouseEvent *event) override
void willShowContextMenu(QgsActionMenu *menu, const QModelIndex &atIndex)
Emitted when the context menu is created to add the specific actions to it.
QgsFeatureListModel * featureListModel()
Gets the featureListModel used by this view.
QgsFeatureListView(QWidget *parent=nullptr)
Creates a feature list view.
virtual void setModel(QgsFeatureListModel *featureListModel)
Set the QgsFeatureListModel which is used to retrieve information.
void currentEditSelectionChanged(QgsFeature &feat)
Emitted whenever the current edit selection has been changed.
void aboutToChangeEditSelection(bool &ok)
Item selection model for selecting features.
virtual bool isSelected(QgsFeatureId fid)
Returns the selection status of a given feature id.
void requestRepaint(const QModelIndexList &indexes)
Request a repaint of a list of model indexes.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Is an interface class to abstract feature selection handling.
Caches features for a given QgsVectorLayer.
QgsVectorLayer * layer()
Returns the layer to which this cache belongs.
Manages vector layer selections.
Q_INVOKABLE const QgsFeatureIds & selectedFeatureIds() const
Returns a list of the selected features IDs in this layer.
void attributeValueChanged(QgsFeatureId fid, int idx, const QVariant &value)
Emitted whenever an attribute value change is done in the edit buffer.
void selectionChanged(const QgsFeatureIds &selected, const QgsFeatureIds &deselected, bool clearAndSelect)
Emitted when selection was changed.
QSet< QgsFeatureId > QgsFeatureIds
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
#define QgsDebugError(str)