QGIS API Documentation  3.22.4-Białowieża (ce8e65e95e)
qgsfeatureselectionmodel.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsfeatureselectionmodel.cpp
3  ---------------------
4  begin : April 2013
5  copyright : (C) 2013 by Matthias Kuhn
6  email : matthias at opengis dot ch
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 #include "qgsattributetablemodel.h"
16 #include "qgsfeaturemodel.h"
19 #include "qgsvectorlayer.h"
20 #include "qgslogger.h"
21 
22 QgsFeatureSelectionModel::QgsFeatureSelectionModel( QAbstractItemModel *model, QgsFeatureModel *featureModel, QgsIFeatureSelectionManager *featureSelectionManager, QObject *parent )
23  : QItemSelectionModel( model, parent )
24  , mFeatureModel( featureModel )
25  , mSyncEnabled( true )
26  , mClearAndSelectBuffer( false )
27 {
28  setFeatureSelectionManager( featureSelectionManager );
29 }
30 
32 {
33  mSyncEnabled = enable;
34 
35  if ( mSyncEnabled )
36  {
37  if ( mClearAndSelectBuffer )
38  {
39  mFeatureSelectionManager->setSelectedFeatures( mSelectedBuffer );
40  }
41  else
42  {
43  mFeatureSelectionManager->select( mSelectedBuffer );
44  mFeatureSelectionManager->deselect( mDeselectedBuffer );
45  }
46 
47  mSelectedBuffer.clear();
48  mDeselectedBuffer.clear();
49  mClearAndSelectBuffer = false;
50  }
51 }
52 
54 {
55  if ( mSelectedBuffer.contains( fid ) )
56  return true;
57 
58  if ( mDeselectedBuffer.contains( fid ) )
59  return false;
60 
61  if ( !mClearAndSelectBuffer && mFeatureSelectionManager->selectedFeatureIds().contains( fid ) )
62  return true;
63 
64  return false;
65 }
66 
67 bool QgsFeatureSelectionModel::isSelected( const QModelIndex &index )
68 {
69  return isSelected( index.model()->data( index, QgsAttributeTableModel::FeatureIdRole ).toLongLong() );
70 }
71 
72 void QgsFeatureSelectionModel::selectFeatures( const QItemSelection &selection, QItemSelectionModel::SelectionFlags command )
73 {
74  QgsFeatureIds ids;
75 
76  QgsDebugMsg( QStringLiteral( "Index count: %1" ).arg( selection.indexes().size() ) );
77 
78  const auto constIndexes = selection.indexes();
79  for ( const QModelIndex &index : constIndexes )
80  {
81  const QgsFeatureId id = index.model()->data( index, QgsAttributeTableModel::FeatureIdRole ).toLongLong();
82 
83  ids << id;
84  }
85 
86  disconnect( mFeatureSelectionManager, &QgsIFeatureSelectionManager::selectionChanged, this, &QgsFeatureSelectionModel::layerSelectionChanged );
87 
88  if ( command.testFlag( QItemSelectionModel::ClearAndSelect ) )
89  {
90  if ( !mSyncEnabled )
91  {
92  mClearAndSelectBuffer = true;
93  const auto constIds = ids;
94  for ( const QgsFeatureId id : constIds )
95  {
96  if ( !mDeselectedBuffer.remove( id ) )
97  {
98  mSelectedBuffer.insert( id );
99  }
100  }
101  }
102  else
103  {
104  mFeatureSelectionManager->setSelectedFeatures( ids );
105  }
106  }
107  else if ( command.testFlag( QItemSelectionModel::Select ) )
108  {
109  if ( !mSyncEnabled )
110  {
111  const auto constIds = ids;
112  for ( const QgsFeatureId id : constIds )
113  {
114  if ( !mDeselectedBuffer.remove( id ) )
115  {
116  mSelectedBuffer.insert( id );
117  }
118  }
119  }
120  else
121  {
122  mFeatureSelectionManager->select( ids );
123  }
124  }
125  else if ( command.testFlag( QItemSelectionModel::Deselect ) )
126  {
127  if ( !mSyncEnabled )
128  {
129  const auto constIds = ids;
130  for ( const QgsFeatureId id : constIds )
131  {
132  if ( !mSelectedBuffer.remove( id ) )
133  {
134  mDeselectedBuffer.insert( id );
135  }
136  }
137  }
138  else
139  {
140  mFeatureSelectionManager->deselect( ids );
141  }
142  }
143 
144  connect( mFeatureSelectionManager, &QgsIFeatureSelectionManager::selectionChanged, this, &QgsFeatureSelectionModel::layerSelectionChanged );
145 
146  QModelIndexList updatedIndexes;
147  const auto indexes = selection.indexes();
148  for ( const QModelIndex &idx : indexes )
149  {
150  updatedIndexes.append( expandIndexToRow( idx ) );
151  }
152 
153  emit requestRepaint( updatedIndexes );
154 }
155 
157 {
158  if ( mFeatureSelectionManager )
159  disconnect( mFeatureSelectionManager, &QgsIFeatureSelectionManager::selectionChanged, this, &QgsFeatureSelectionModel::layerSelectionChanged );
160 
161  mFeatureSelectionManager = featureSelectionManager;
162 
163  connect( mFeatureSelectionManager, &QgsIFeatureSelectionManager::selectionChanged, this, &QgsFeatureSelectionModel::layerSelectionChanged );
164 }
165 
166 void QgsFeatureSelectionModel::layerSelectionChanged( const QgsFeatureIds &selected, const QgsFeatureIds &deselected, bool clearAndSelect )
167 {
168  if ( clearAndSelect )
169  {
170  emit requestRepaint();
171  }
172  else
173  {
174  QModelIndexList updatedIndexes;
175  const auto constSelected = selected;
176  for ( const QgsFeatureId fid : constSelected )
177  {
178  updatedIndexes.append( expandIndexToRow( mFeatureModel->fidToIndex( fid ) ) );
179  }
180 
181  const auto constDeselected = deselected;
182  for ( const QgsFeatureId fid : constDeselected )
183  {
184  updatedIndexes.append( expandIndexToRow( mFeatureModel->fidToIndex( fid ) ) );
185  }
186 
187  emit requestRepaint( updatedIndexes );
188  }
189 }
190 
191 QModelIndexList QgsFeatureSelectionModel::expandIndexToRow( const QModelIndex &index ) const
192 {
193  QModelIndexList indexes;
194  const QAbstractItemModel *model = index.model();
195  const int row = index.row();
196 
197  if ( !model )
198  return indexes;
199 
200  const int columns = model->columnCount();
201  indexes.reserve( columns );
202  for ( int column = 0; column < columns; ++column )
203  {
204  indexes.append( model->index( row, column ) );
205  }
206 
207  return indexes;
208 }
@ FeatureIdRole
Get the feature id of the feature in this row.
virtual QModelIndex fidToIndex(QgsFeatureId fid)=0
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.
QgsFeatureSelectionModel(QAbstractItemModel *model, QgsFeatureModel *featureModel, QgsIFeatureSelectionManager *featureSelectionHandler, QObject *parent)
virtual void setFeatureSelectionManager(QgsIFeatureSelectionManager *featureSelectionManager)
void requestRepaint()
Request a repaint of the visible items of connected views.
Is an interface class to abstract feature selection handling.
virtual void select(const QgsFeatureIds &ids)=0
Select features by feature ids.
void selectionChanged(const QgsFeatureIds &selected, const QgsFeatureIds &deselected, bool clearAndSelect)
Emitted when selection was changed.
virtual const QgsFeatureIds & selectedFeatureIds() const =0
Returns reference to identifiers of selected features.
virtual void deselect(const QgsFeatureIds &ids)=0
Deselect features by feature ids.
virtual void setSelectedFeatures(const QgsFeatureIds &ids)=0
Change selection to the new set of features.
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeatureid.h:37
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
Definition: qgsfeatureid.h:28
#define QgsDebugMsg(str)
Definition: qgslogger.h:38