patch_for_bug_1927.txt

New row selection on attribute table - gcarrillo -, 2009-09-11 08:35 PM

Download (13.2 KB)

 
1
Index: src/app/attributetable/qgsattributetableview.cpp
2
===================================================================
3
--- src/app/attributetable/qgsattributetableview.cpp	(revision: 11578)
4
+++ src/app/attributetable/qgsattributetableview.cpp	(copia de trabajo)
5
@@ -42,8 +42,6 @@
6
   setSelectionMode( QAbstractItemView::NoSelection );
7
   setSortingEnabled( true );
8

    
9
-  mShiftPressed = false;
10
-  mCtrlPressed = false;
11
 }
12

    
13
 void QgsAttributeTableView::setLayer( QgsVectorLayer* layer )
14
@@ -73,25 +71,3 @@
15
   QSettings settings;
16
   settings.setValue( "/BetterAttributeTable/geometry", QVariant( saveGeometry() ) );
17
 }
18
-
19
-void QgsAttributeTableView::keyPressEvent( QKeyEvent *event )
20
-{
21
-  // shift pressed
22
-  if ( event->key() == Qt::Key_Shift )// && event->modifiers() & Qt::ShiftModifier)
23
-    mShiftPressed = true;
24
-  else if ( event->key() == Qt::Key_Control )
25
-    mCtrlPressed = true;
26
-  else
27
-    QTableView::keyPressEvent( event );
28
-}
29
-
30
-void QgsAttributeTableView::keyReleaseEvent( QKeyEvent *event )
31
-{
32
-  // workaround for some Qt bug
33
-  if ( event->key() == Qt::Key_Shift || event->key() == -1 )
34
-    mShiftPressed = false;
35
-  else if ( event->key() == Qt::Key_Control )
36
-    mCtrlPressed = false;
37
-  else
38
-    QTableView::keyReleaseEvent( event );
39
-}
40
Index: src/app/attributetable/qgsattributetabledialog.cpp
41
===================================================================
42
--- src/app/attributetable/qgsattributetabledialog.cpp	(revision: 11578)
43
+++ src/app/attributetable/qgsattributetabledialog.cpp	(copia de trabajo)
44
@@ -102,6 +102,7 @@
45
   connect( mLayer, SIGNAL( selectionChanged() ), this, SLOT( updateSelectionFromLayer() ) );
46
   connect( mLayer, SIGNAL( layerDeleted() ), this, SLOT( close() ) );
47
   connect( mView->verticalHeader(), SIGNAL( sectionClicked( int ) ), this, SLOT( updateRowSelection( int ) ) );
48
+  connect( mView->verticalHeader(), SIGNAL( sectionPressed( int ) ), this, SLOT( updateRowPressed( int ) ) );
49
   connect( mModel, SIGNAL( modelChanged() ), this, SLOT( updateSelection() ) );
50

    
51
   mLastClickedHeaderIndex = 0;
52
@@ -249,8 +250,6 @@
53
 void QgsAttributeTableDialog::updateSelection()
54
 {
55
   QModelIndex index;
56
-  mView->setSelectionMode( QAbstractItemView::MultiSelection );
57
-
58
   QItemSelection selection;
59

    
60
   QgsFeatureIds::Iterator it = mSelectedFeatures.begin();
61
@@ -264,7 +263,6 @@
62

    
63
   mSelectionModel->select( selection, QItemSelectionModel::ClearAndSelect );// | QItemSelectionModel::Columns);
64
   mView->setSelectionModel( mSelectionModel );
65
-  mView->setSelectionMode( QAbstractItemView::NoSelection );
66

    
67
   /*for (int i = 0; i < mModel->rowCount(); ++i)
68
   {
69
@@ -275,127 +273,200 @@
70
   */
71
 }
72

    
73
+void QgsAttributeTableDialog::updateRowPressed( int index )
74
+{
75
+  mView->setSelectionMode( QAbstractItemView::ExtendedSelection );
76
+  mIndexPressed = index;
77
+}
78
+
79
 void QgsAttributeTableDialog::updateRowSelection( int index )
80
 {
81
-  // map index to filter model
82
-  //index = mFilterModel->mapFromSource(mModel->index(index, 0)).row();
83
+  bool bDrag;
84

    
85
-  if ( mView->shiftPressed() )
86
+  if ( mIndexPressed == index )
87
+    bDrag = false;
88
+  else
89
+    bDrag = true;
90
+
91
+  QString key = "";
92
+  if ( QApplication::keyboardModifiers() == Qt::ControlModifier )
93
+    key = "Control";
94
+  else if ( QApplication::keyboardModifiers() == Qt::ShiftModifier )
95
+    key = "Shift";
96
+
97
+  int first, last;
98
+
99
+  if ( bDrag )
100
   {
101
-    QgsDebugMsg( "shift" );
102
-    // get the first and last index of the rows to be selected/deselected
103
-    int first, last;
104
-    if ( index > mLastClickedHeaderIndex )
105
+    if ( mIndexPressed < index )
106
     {
107
-      first = mLastClickedHeaderIndex + 1;
108
-      last = index;
109
+      first = mIndexPressed;
110
+      mLastClickedHeaderIndex = last = index;
111
     }
112
-    else if ( index == mLastClickedHeaderIndex )
113
-    {
114
-      // row was selected and now it is shift-clicked
115
-      // ignore the shift and deselect the row
116
-      first = last = index;
117
-    }
118
     else
119
     {
120
-      first = index;
121
-      last = mLastClickedHeaderIndex - 1;
122
+      last = mIndexPressed;
123
+      mLastClickedHeaderIndex = first = index;
124
     }
125

    
126
-    // for all the rows update the selection, without starting a new selection
127
-    if ( first <= last )
128
-      updateRowSelection( first, last, false );
129
-
130
-    mLastClickedHeaderIndex = last;
131
+    updateRowSelection( first, last, 3 );
132
+    mView->setSelectionMode( QAbstractItemView::NoSelection );
133
+    return;
134
   }
135
-  else if ( mView->ctrlPressed() )
136
+  else // No drag
137
   {
138
-    QgsDebugMsg( "ctrl" );
139
-    // update the single row selection, without starting a new selection
140
-    updateRowSelection( index, index, false );
141
+    if ( key == "Shift" )
142
+    {
143
+      QgsDebugMsg( "shift" );
144
+      // get the first and last index of the rows to be selected/deselected
145
+      first = last = 0;
146

    
147
-    // the next shift would start from here
148
-    mLastClickedHeaderIndex = index;
149
-  }
150
-  else
151
-  {
152
-    QgsDebugMsg( "ordinary click" );
153
-    // update the single row selection, start a new selection if the row was not selected
154
-    updateRowSelection( index, index, true );
155
+      if ( index > mLastClickedHeaderIndex )
156
+      {
157
+        first = mLastClickedHeaderIndex;
158
+        last = index;
159
+      }
160
+      else if ( index == mLastClickedHeaderIndex )
161
+      {
162
+        // row was selected and now it is shift-clicked
163
+        first = last = index;
164
+      }
165
+      else
166
+      {
167
+        first = index;
168
+        last = mLastClickedHeaderIndex;
169
+      }
170

    
171
-    // the next shift would start from here
172
-    mLastClickedHeaderIndex = index;
173
+      // for all the rows update the selection, without starting a new selection
174
+      if ( first <= last )
175
+        updateRowSelection( first, last, 1 );
176
+    }
177
+    else if ( key == "Control" )
178
+    {
179
+      QgsDebugMsg( "ctrl" );
180
+      // update the single row selection, without starting a new selection
181
+      updateRowSelection( index, index, 2 );
182
+
183
+      // the next shift would start from here
184
+      mLastClickedHeaderIndex = index;
185
+    }
186
+    else // Single click
187
+    {
188
+      // Start a new selection if the row was not selected
189
+      updateRowSelection( index, index, 0 );
190
+
191
+      // the next shift would start from here
192
+      mLastClickedHeaderIndex = index;
193
+    }
194
   }
195
+  mView->setSelectionMode( QAbstractItemView::NoSelection );
196
 }
197

    
198
-// fast row deselection needed
199
-void QgsAttributeTableDialog::updateRowSelection( int first, int last, bool startNewSelection )
200
+void QgsAttributeTableDialog::updateRowSelection( int first, int last, int clickType )
201
 {
202
+  // clickType= 0:Single click, 1:Shift, 2:Ctrl, 3: Dragged click
203
   disconnect( mLayer, SIGNAL( selectionChanged() ), this, SLOT( updateSelectionFromLayer() ) );
204

    
205
-  //index = mFilterModel->mapFromSource(mModel->index(index, 0)).row();
206
   // Id must be mapped to table/view row
207
   QModelIndex index = mFilterModel->mapToSource( mFilterModel->index( first, 0 ) );
208
   int fid = mModel->rowToId( index.row() );
209
   bool wasSelected = mSelectedFeatures.contains( fid );
210

    
211
   // new selection should be created
212
-  if ( startNewSelection )
213
+  if ( clickType == 0 ) // Single click
214
   {
215
-    mView->clearSelection();
216
-    mSelectedFeatures.clear();
217
+    if ( mSelectedFeatures.size() == 1 and wasSelected ) // One item selected
218
+        return // Click over a selected item doesn't do anything
219

    
220
-    if ( wasSelected )
221
-    {
222
-      mLayer->removeSelection();
223
-      connect( mLayer, SIGNAL( selectionChanged() ), this, SLOT( updateSelectionFromLayer() ) );
224
-      return;
225
-    }
226
-
227
-    // set clicked row to current
228
     mView->setCurrentIndex( mFilterModel->index( first, 0 ) );
229
-    mView->setSelectionMode( QAbstractItemView::SingleSelection );
230
-
231
-    //QModelIndex index = mFilterModel->mapFromSource(mModel->index(first, 0));
232
-
233
     mView->selectRow( first );
234
-    mView->setSelectionMode( QAbstractItemView::NoSelection );
235

    
236
+    mSelectedFeatures.clear();
237
     mSelectedFeatures.insert( fid );
238
-    //mLayer->setSelectedFeatures(mSelectedFeatures);
239
     mLayer->removeSelection();
240
     mLayer->select( fid );
241
-    //mFilterModel->invalidate();
242
     connect( mLayer, SIGNAL( selectionChanged() ), this, SLOT( updateSelectionFromLayer() ) );
243
     return;
244
   }
245
+  else if ( clickType == 1 ) // Shift
246
+  {
247
+    QgsFeatureIds newSelection;
248

    
249
-  // existing selection should be updated
250
-  for ( int i = first; i <= last; ++i )
251
-  {
252
-    if ( i > first )
253
+    for ( int i = first; i <= last; ++i )
254
     {
255
-      // Id must be mapped to table/view row
256
-      index = mFilterModel->mapToSource( mFilterModel->index( i, 0 ) );
257
-      fid = mModel->rowToId( index.row() );
258
-      wasSelected = mSelectedFeatures.contains( fid );
259
+      if ( i >= first )
260
+      {
261
+        // Id must be mapped to table/view row
262
+        index = mFilterModel->mapToSource( mFilterModel->index( i, 0 ) );
263
+        fid = mModel->rowToId( index.row() );
264
+      }
265
+      newSelection.insert( fid );
266
     }
267

    
268
+    // Remove items in mSelectedFeatures if they aren't in mNewSelection
269
+    QgsFeatureIds::Iterator it = mSelectedFeatures.begin();
270
+    while ( it != mSelectedFeatures.end() ) {
271
+      if ( !newSelection.contains( *it ) ) {
272
+        it = mSelectedFeatures.erase( it );
273
+      } else {
274
+        ++it;
275
+      }
276
+    }
277
+
278
+    // Append the other fids in range first-last to mSelectedFeatures
279
+    QgsFeatureIds::Iterator itNew = newSelection.begin();
280
+    for ( ; itNew != newSelection.end(); ++itNew )
281
+    {
282
+      if ( !mSelectedFeatures.contains( *itNew ) )
283
+      {
284
+        mSelectedFeatures.insert( *itNew );
285
+      }
286
+    }
287
+  }
288
+  else if ( clickType == 2 ) // Ctrl
289
+  {
290
+    // existing selection should be updated
291
     if ( wasSelected )
292
       mSelectedFeatures.remove( fid );
293
     else
294
       mSelectedFeatures.insert( fid );
295
   }
296
-  //mFilterModel->invalidate();
297
+  else if ( clickType == 3 ) // Dragged click
298
+  {
299
+    QgsFeatureIds newSelection;
300

    
301
-  /*
302
-  QItemSelection selection;
303
-  QModelIndex leftUpIndex = mFilterModel->index(first, 0);
304
-  QModelIndex rightBottomIndex = mFilterModel->index(last, mModel->columnCount() - 1);
305
-  selection.append(QItemSelectionRange(leftUpIndex, rightBottomIndex));
306
-  mSelectionModel->select(selection, QItemSelectionModel::Select);
307
-  mView->setSelectionModel(mSelectionModel);
308
-  */
309
+    for ( int i = first; i <= last; ++i )
310
+    {
311
+      if ( i >= first )
312
+      {
313
+        // Id must be mapped to table/view row
314
+        index = mFilterModel->mapToSource( mFilterModel->index( i, 0 ) );
315
+        fid = mModel->rowToId( index.row() );
316
+      }
317
+      newSelection.insert( fid );
318
+    }
319
+
320
+    // Remove items in mSelectedFeatures if they aren't in mNewSelection
321
+    QgsFeatureIds::Iterator it = mSelectedFeatures.begin();
322
+    while ( it != mSelectedFeatures.end() ) {
323
+      if ( !newSelection.contains( *it ) ) {
324
+        it = mSelectedFeatures.erase( it );
325
+      } else {
326
+        ++it;
327
+      }
328
+    }
329
+
330
+    // Append the other fids in range first-last to mSelectedFeatures
331
+    QgsFeatureIds::Iterator itNew = newSelection.begin();
332
+    for ( ; itNew != newSelection.end(); ++itNew )
333
+    {
334
+      if ( !mSelectedFeatures.contains( *itNew ) )
335
+      {
336
+        mSelectedFeatures.insert( *itNew );
337
+      }
338
+    }
339
+  }
340
+
341
   updateSelection();
342
   mLayer->setSelectedFeatures( mSelectedFeatures );
343
   connect( mLayer, SIGNAL( selectionChanged() ), this, SLOT( updateSelectionFromLayer() ) );
344
Index: src/app/attributetable/qgsattributetableview.h
345
===================================================================
346
--- src/app/attributetable/qgsattributetableview.h	(revision: 11578)
347
+++ src/app/attributetable/qgsattributetableview.h	(copia de trabajo)
348
@@ -41,29 +41,8 @@
349
      * @param event not used
350
      */
351
     void closeEvent( QCloseEvent *event );
352
-    /**
353
-     * Handles Ctrl or Shift key press
354
-     * @param event the key pressed
355
-     */
356
-    void keyPressEvent( QKeyEvent *event );
357
-    /**
358
-     * Handles Ctrl or Shift key release
359
-     * @param event the key released
360
-     */
361
-    void keyReleaseEvent( QKeyEvent *event );
362
-    /**
363
-     * Returns true if shift was pressed
364
-     */
365
-    bool shiftPressed() { return mShiftPressed; }
366
-    /**
367
-     * Returns true if ctrl was pressed
368
-     */
369
-    bool ctrlPressed() { return mCtrlPressed; }
370

    
371
   private:
372
-    bool mShiftPressed;
373
-    bool mCtrlPressed;
374
-
375
     QgsAttributeTableModel* mModel;
376
     QgsAttributeTableFilterModel* mFilterModel;
377
 };
378
Index: src/app/attributetable/qgsattributetabledialog.h
379
===================================================================
380
--- src/app/attributetable/qgsattributetabledialog.h	(revision: 11578)
381
+++ src/app/attributetable/qgsattributetabledialog.h	(copia de trabajo)
382
@@ -90,12 +90,16 @@
383
      */
384
     void updateRowSelection( int index );
385
     /**
386
+     * Updates the index pressed
387
+     */
388
+    void updateRowPressed( int index );
389
+    /**
390
      * Updates selection of specifed rows
391
      * @param first first row
392
      * @param last last row
393
-     * @param startNewSelection if true, then new selection is started
394
+     * @param clickType 0:Single click, 1:Shift, 2:Ctrl, 3:dragged click
395
      */
396
-    void updateRowSelection( int first, int last, bool startNewSelection );
397
+    void updateRowSelection( int first, int last, int clickType );
398

    
399
     /**
400
      * Toggle showing of selected line only
401
@@ -178,6 +182,7 @@
402
     QgsAttributeTableFilterModel *mFilterModel;
403
     QgsVectorLayer *mLayer;
404
     QgsFeatureIds mSelectedFeatures;
405
+    int mIndexPressed;
406

    
407
     QItemSelectionModel* mSelectionModel;
408
     int mLastClickedHeaderIndex;