35#include "moc_qgsfeaturelistview.cpp"
37using namespace Qt::StringLiterals;
42 setSelectionMode( QAbstractItemView::ExtendedSelection );
44 mUpdateEditSelectionTimerWithSelection.setSingleShot(
true );
45 connect( &mUpdateEditSelectionTimerWithSelection, &QTimer::timeout,
this, [
this]() { updateEditSelection(
true ); } );
47 mUpdateEditSelectionTimerWithSelection.setInterval( 0 );
49 mUpdateEditSelectionTimerWithoutSelection.setSingleShot(
true );
50 connect( &mUpdateEditSelectionTimerWithoutSelection, &QTimer::timeout,
this, [
this]() { updateEditSelection(
false ); } );
52 mUpdateEditSelectionTimerWithoutSelection.setInterval( 0 );
57 return mModel->layerCache();
65 delete mFeatureSelectionModel;
66 delete mCurrentEditSelectionModel;
68 mCurrentEditSelectionModel =
new QItemSelectionModel( mModel->masterModel(),
this );
69 if ( !mFeatureSelectionManager )
72 mFeatureSelectionManager = mOwnedFeatureSelectionManager;
76 setSelectionModel( mFeatureSelectionModel );
79 if ( mItemDelegate && mItemDelegate->parent() ==
this )
85 mItemDelegate->setEditSelectionModel( mCurrentEditSelectionModel );
86 setItemDelegate( mItemDelegate );
88 mItemDelegate->setFeatureSelectionModel( mFeatureSelectionModel );
90 mFeatureSelectionModel,
96 connect( mCurrentEditSelectionModel, &QItemSelectionModel::selectionChanged,
this, &QgsFeatureListView::editSelectionChanged );
98 connect(
featureListModel, &QgsFeatureListModel::rowsRemoved,
this, [
this]() { ensureEditSelection(); } );
99 connect(
featureListModel, &QgsFeatureListModel::rowsInserted,
this, [
this]() { ensureEditSelection(); } );
100 connect(
featureListModel, &QgsFeatureListModel::modelReset,
this, [
this]() { ensureEditSelection(); } );
105 if ( mModel->setDisplayExpression( expression ) )
118 return mModel->displayExpression();
123 return mModel->parserErrorString();
129 const QModelIndexList selectedIndexes = mCurrentEditSelectionModel->selectedIndexes();
130 for (
const QModelIndex &idx : selectedIndexes )
139 mItemDelegate->setCurrentFeatureEdited( state );
140 viewport()->update( visualRegionForSelection( mCurrentEditSelectionModel->selection() ) );
145 if ( event->button() != Qt::LeftButton )
147 QListView::mousePressEvent( event );
153 const QPoint pos =
event->pos();
155 const QModelIndex index = indexAt( pos );
159 mDragMode = DragMode::MoveSelection;
160 if ( index.isValid() )
161 setEditSelection( mModel->mapToMaster( index ), QItemSelectionModel::ClearAndSelect );
165 mDragMode = DragMode::ExpandSelection;
166 mFeatureSelectionModel->enableSync(
false );
167 selectRow( index,
true );
177void QgsFeatureListView::editSelectionChanged(
const QItemSelection &selected,
const QItemSelection &deselected )
179 if ( isVisible() && updatesEnabled() )
183 viewport()->update( visualRegionForSelection( localDeselected ) | visualRegionForSelection( localSelected ) );
187 if ( !selected.isEmpty() )
189 const QModelIndexList indexList = selected.indexes();
190 if ( !indexList.isEmpty() )
192 QgsFeature selectedFeature;
193 mModel->featureByIndex( mModel->mapFromMaster( indexList.first() ), selectedFeature );
194 mLastEditSelectionFid = selectedFeature.
id();
198 const QItemSelection currentSelection = mCurrentEditSelectionModel->selection();
199 if ( currentSelection.size() == 1 )
201 QModelIndexList indexList = currentSelection.indexes();
202 if ( !indexList.isEmpty() )
205 mModel->featureByIndex( mModel->mapFromMaster( indexList.first() ), feat );
211 else if ( mModel->rowCount() == 0 )
219 QItemSelection selection;
220 selection.append( QItemSelectionRange( mModel->index( 0, 0 ), mModel->index( mModel->rowCount() - 1, 0 ) ) );
222 mFeatureSelectionModel->selectFeatures( selection, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows );
227 QItemSelection selection;
228 QModelIndex firstModelIdx;
230 const auto constFids = fids;
233 const QModelIndex modelIdx = mModel->fidToIdx( fid );
235 if ( !firstModelIdx.isValid() )
236 firstModelIdx = modelIdx;
238 selection.append( QItemSelectionRange( mModel->mapToMaster( modelIdx ) ) );
246 mCurrentEditSelectionModel->select( selection, QItemSelectionModel::ClearAndSelect );
247 scrollTo( firstModelIdx );
257 Q_ASSERT( index.model() == mModel->masterModel() || !index.isValid() );
261 mCurrentEditSelectionModel->select( index, command );
268 const auto constIndexes = indexes;
269 for (
const QModelIndex &index : constIndexes )
277 setDirtyRegion( viewport()->rect() );
284 const QPoint pos =
event->pos();
285 const QModelIndex index = indexAt( pos );
289 case QgsFeatureListView::DragMode::Inactive:
292 case QgsFeatureListView::DragMode::ExpandSelection:
294 selectRow( index,
false );
298 case QgsFeatureListView::DragMode::MoveSelection:
300 if ( index.isValid() )
301 setEditSelection( mModel->mapToMaster( index ), QItemSelectionModel::ClearAndSelect );
314 if ( event->button() != Qt::LeftButton )
316 QListView::mouseReleaseEvent( event );
322 case QgsFeatureListView::DragMode::ExpandSelection:
323 if ( mFeatureSelectionModel )
324 mFeatureSelectionModel->enableSync(
true );
326 case QgsFeatureListView::DragMode::Inactive:
327 case QgsFeatureListView::DragMode::MoveSelection:
331 mDragMode = DragMode::Inactive;
336 switch ( event->key() )
339 editOtherFeature( Previous );
343 editOtherFeature( Next );
347 QListView::keyPressEvent( event );
351void QgsFeatureListView::editOtherFeature( QgsFeatureListView::PositionInList positionInList )
354 if ( 0 != mCurrentEditSelectionModel->selectedIndexes().count() )
356 const QModelIndex localIndex = mModel->
mapFromMaster( mCurrentEditSelectionModel->selectedIndexes().first() );
357 currentRow = localIndex.row();
360 QModelIndex newLocalIndex;
361 QModelIndex newIndex;
363 switch ( positionInList )
366 newLocalIndex = mModel->index( 0, 0 );
370 newLocalIndex = mModel->index( currentRow - 1, 0 );
374 newLocalIndex = mModel->index( currentRow + 1, 0 );
378 newLocalIndex = mModel->index( mModel->rowCount() - 1, 0 );
382 newIndex = mModel->mapToMaster( newLocalIndex );
383 if ( newIndex.isValid() )
386 scrollTo( newLocalIndex );
392 const QModelIndex index = indexAt( event->pos() );
394 if ( index.isValid() )
406 menu->exec( event->globalPos() );
410void QgsFeatureListView::selectRow(
const QModelIndex &index,
bool anchor )
412 QItemSelectionModel::SelectionFlags command = selectionCommand( index );
413 const int row = index.row();
418 if ( selectionMode() != QListView::SingleSelection && command.testFlag( QItemSelectionModel::Toggle ) )
421 mCtrlDragSelectionFlag = mFeatureSelectionModel->
isSelected( index ) ? QItemSelectionModel::Deselect : QItemSelectionModel::Select;
422 command &= ~QItemSelectionModel::Toggle;
423 command |= mCtrlDragSelectionFlag;
425 command |= QItemSelectionModel::Current;
428 const QModelIndex tl = model()->index( std::min( mRowAnchor, row ), 0 );
429 const QModelIndex br = model()->index( std::max( mRowAnchor, row ), model()->columnCount() - 1 );
431 mFeatureSelectionModel->selectFeatures( QItemSelection( tl, br ), command );
434void QgsFeatureListView::ensureEditSelection(
bool inSelection )
438 mUpdateEditSelectionTimerWithSelection.start();
442 mUpdateEditSelectionTimerWithoutSelection.start();
446void QgsFeatureListView::updateEditSelection(
bool inSelection )
448 if ( !mModel->rowCount() )
456 const QModelIndexList selectedIndexes = mCurrentEditSelectionModel->selectedIndexes();
462 bool editSelectionUpdateRequested =
false;
465 bool validEditSelectionAvailable =
false;
467 if ( selectedIndexes.isEmpty() || !selectedIndexes.first().isValid() || mModel->mapFromMaster( selectedIndexes.first() ).row() == -1 )
469 validEditSelectionAvailable =
false;
473 validEditSelectionAvailable =
true;
481 if ( !validEditSelectionAvailable )
483 editSelectionUpdateRequested =
true;
490 if ( !selectedFids.contains( mModel->idxToFid( mModel->mapFromMaster( selectedIndexes.first() ) ) ) )
492 editSelectionUpdateRequested =
true;
500 if ( !validEditSelectionAvailable )
501 editSelectionUpdateRequested =
true;
504 if ( editSelectionUpdateRequested )
511 int rowToSelect = -1;
521 if ( selectedFids.isEmpty() )
527 const int rowCount = mModel->rowCount();
528 for (
int i = 0; i < rowCount; i++ )
530 if ( selectedFids.contains( mModel->idxToFid( mModel->index( i, 0 ) ) ) )
537 if ( rowToSelect == -1 && !validEditSelectionAvailable )
543 if ( rowToSelect != -1 )
545 setEditSelection( mModel->mapToMaster( mModel->index( rowToSelect, 0 ) ), QItemSelectionModel::ClearAndSelect );
552 mFeatureSelectionManager = featureSelectionManager;
554 if ( mFeatureSelectionModel )
555 mFeatureSelectionModel->setFeatureSelectionManager( mFeatureSelectionManager );
558 if ( mOwnedFeatureSelectionManager )
560 mOwnedFeatureSelectionManager->deleteLater();
561 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)