[QGIS Commit] r12104 - trunk/qgis/src/app/attributetable

svn_qgis at osgeo.org svn_qgis at osgeo.org
Sat Nov 14 11:24:50 EST 2009


Author: wonder
Date: 2009-11-14 11:24:49 -0500 (Sat, 14 Nov 2009)
New Revision: 12104

Modified:
   trunk/qgis/src/app/attributetable/qgsattributetabledialog.cpp
   trunk/qgis/src/app/attributetable/qgsattributetabledialog.h
   trunk/qgis/src/app/attributetable/qgsattributetableview.cpp
   trunk/qgis/src/app/attributetable/qgsattributetableview.h
Log:
Applied patch from ticket #1927.
It adds some improvements to selection handling in attribute table (see the ticket for details).
Contributed by German Carillo - thanks!


Modified: trunk/qgis/src/app/attributetable/qgsattributetabledialog.cpp
===================================================================
--- trunk/qgis/src/app/attributetable/qgsattributetabledialog.cpp	2009-11-14 11:21:34 UTC (rev 12103)
+++ trunk/qgis/src/app/attributetable/qgsattributetabledialog.cpp	2009-11-14 16:24:49 UTC (rev 12104)
@@ -115,6 +115,7 @@
   connect( mLayer, SIGNAL( selectionChanged() ), this, SLOT( updateSelectionFromLayer() ) );
   connect( mLayer, SIGNAL( layerDeleted() ), this, SLOT( close() ) );
   connect( mView->verticalHeader(), SIGNAL( sectionClicked( int ) ), this, SLOT( updateRowSelection( int ) ) );
+  connect( mView->verticalHeader(), SIGNAL( sectionPressed( int ) ), this, SLOT( updateRowPressed( int ) ) );
   connect( mModel, SIGNAL( modelChanged() ), this, SLOT( updateSelection() ) );
 
   mLastClickedHeaderIndex = 0;
@@ -262,8 +263,6 @@
 void QgsAttributeTableDialog::updateSelection()
 {
   QModelIndex index;
-  mView->setSelectionMode( QAbstractItemView::MultiSelection );
-
   QItemSelection selection;
 
   QgsFeatureIds::Iterator it = mSelectedFeatures.begin();
@@ -277,7 +276,6 @@
 
   mSelectionModel->select( selection, QItemSelectionModel::ClearAndSelect );// | QItemSelectionModel::Columns);
   mView->setSelectionModel( mSelectionModel );
-  mView->setSelectionMode( QAbstractItemView::NoSelection );
 
   /*for (int i = 0; i < mModel->rowCount(); ++i)
   {
@@ -288,127 +286,200 @@
   */
 }
 
+void QgsAttributeTableDialog::updateRowPressed( int index )
+{
+  mView->setSelectionMode( QAbstractItemView::ExtendedSelection );
+  mIndexPressed = index;
+}
+
 void QgsAttributeTableDialog::updateRowSelection( int index )
 {
-  // map index to filter model
-  //index = mFilterModel->mapFromSource(mModel->index(index, 0)).row();
+  bool bDrag;
 
-  if ( mView->shiftPressed() )
+  if ( mIndexPressed == index )
+    bDrag = false;
+  else
+    bDrag = true;
+
+  QString key = "";
+  if ( QApplication::keyboardModifiers() == Qt::ControlModifier )
+    key = "Control";
+  else if ( QApplication::keyboardModifiers() == Qt::ShiftModifier )
+    key = "Shift";
+
+  int first, last;
+
+  if ( bDrag )
   {
-    QgsDebugMsg( "shift" );
-    // get the first and last index of the rows to be selected/deselected
-    int first, last;
-    if ( index > mLastClickedHeaderIndex )
+    if ( mIndexPressed < index )
     {
-      first = mLastClickedHeaderIndex + 1;
-      last = index;
+      first = mIndexPressed;
+      mLastClickedHeaderIndex = last = index;
     }
-    else if ( index == mLastClickedHeaderIndex )
-    {
-      // row was selected and now it is shift-clicked
-      // ignore the shift and deselect the row
-      first = last = index;
-    }
     else
     {
-      first = index;
-      last = mLastClickedHeaderIndex - 1;
+      last = mIndexPressed;
+      mLastClickedHeaderIndex = first = index;
     }
 
-    // for all the rows update the selection, without starting a new selection
-    if ( first <= last )
-      updateRowSelection( first, last, false );
-
-    mLastClickedHeaderIndex = last;
+    updateRowSelection( first, last, 3 );
+    mView->setSelectionMode( QAbstractItemView::NoSelection );
+    return;
   }
-  else if ( mView->ctrlPressed() )
+  else // No drag
   {
-    QgsDebugMsg( "ctrl" );
-    // update the single row selection, without starting a new selection
-    updateRowSelection( index, index, false );
+    if ( key == "Shift" )
+    {
+      QgsDebugMsg( "shift" );
+      // get the first and last index of the rows to be selected/deselected
+      first = last = 0;
 
-    // the next shift would start from here
-    mLastClickedHeaderIndex = index;
-  }
-  else
-  {
-    QgsDebugMsg( "ordinary click" );
-    // update the single row selection, start a new selection if the row was not selected
-    updateRowSelection( index, index, true );
+      if ( index > mLastClickedHeaderIndex )
+      {
+        first = mLastClickedHeaderIndex;
+        last = index;
+      }
+      else if ( index == mLastClickedHeaderIndex )
+      {
+        // row was selected and now it is shift-clicked
+        first = last = index;
+      }
+      else
+      {
+        first = index;
+        last = mLastClickedHeaderIndex;
+      }
 
-    // the next shift would start from here
-    mLastClickedHeaderIndex = index;
+      // for all the rows update the selection, without starting a new selection
+      if ( first <= last )
+        updateRowSelection( first, last, 1 );
+    }
+    else if ( key == "Control" )
+    {
+      QgsDebugMsg( "ctrl" );
+      // update the single row selection, without starting a new selection
+      updateRowSelection( index, index, 2 );
+
+      // the next shift would start from here
+      mLastClickedHeaderIndex = index;
+    }
+    else // Single click
+    {
+      // Start a new selection if the row was not selected
+      updateRowSelection( index, index, 0 );
+
+      // the next shift would start from here
+      mLastClickedHeaderIndex = index;
+    }
   }
+  mView->setSelectionMode( QAbstractItemView::NoSelection );
 }
 
-// fast row deselection needed
-void QgsAttributeTableDialog::updateRowSelection( int first, int last, bool startNewSelection )
+void QgsAttributeTableDialog::updateRowSelection( int first, int last, int clickType )
 {
+  // clickType= 0:Single click, 1:Shift, 2:Ctrl, 3: Dragged click
   disconnect( mLayer, SIGNAL( selectionChanged() ), this, SLOT( updateSelectionFromLayer() ) );
 
-  //index = mFilterModel->mapFromSource(mModel->index(index, 0)).row();
   // Id must be mapped to table/view row
   QModelIndex index = mFilterModel->mapToSource( mFilterModel->index( first, 0 ) );
   int fid = mModel->rowToId( index.row() );
   bool wasSelected = mSelectedFeatures.contains( fid );
 
   // new selection should be created
-  if ( startNewSelection )
+  if ( clickType == 0 ) // Single click
   {
-    mView->clearSelection();
-    mSelectedFeatures.clear();
+    if ( mSelectedFeatures.size() == 1 and wasSelected ) // One item selected
+        return // Click over a selected item doesn't do anything
 
-    if ( wasSelected )
-    {
-      mLayer->removeSelection();
-      connect( mLayer, SIGNAL( selectionChanged() ), this, SLOT( updateSelectionFromLayer() ) );
-      return;
-    }
-
-    // set clicked row to current
     mView->setCurrentIndex( mFilterModel->index( first, 0 ) );
-    mView->setSelectionMode( QAbstractItemView::SingleSelection );
-
-    //QModelIndex index = mFilterModel->mapFromSource(mModel->index(first, 0));
-
     mView->selectRow( first );
-    mView->setSelectionMode( QAbstractItemView::NoSelection );
 
+    mSelectedFeatures.clear();
     mSelectedFeatures.insert( fid );
-    //mLayer->setSelectedFeatures(mSelectedFeatures);
     mLayer->removeSelection();
     mLayer->select( fid );
-    //mFilterModel->invalidate();
     connect( mLayer, SIGNAL( selectionChanged() ), this, SLOT( updateSelectionFromLayer() ) );
     return;
   }
+  else if ( clickType == 1 ) // Shift
+  {
+    QgsFeatureIds newSelection;
 
-  // existing selection should be updated
-  for ( int i = first; i <= last; ++i )
-  {
-    if ( i > first )
+    for ( int i = first; i <= last; ++i )
     {
-      // Id must be mapped to table/view row
-      index = mFilterModel->mapToSource( mFilterModel->index( i, 0 ) );
-      fid = mModel->rowToId( index.row() );
-      wasSelected = mSelectedFeatures.contains( fid );
+      if ( i >= first )
+      {
+        // Id must be mapped to table/view row
+        index = mFilterModel->mapToSource( mFilterModel->index( i, 0 ) );
+        fid = mModel->rowToId( index.row() );
+      }
+      newSelection.insert( fid );
     }
 
+    // Remove items in mSelectedFeatures if they aren't in mNewSelection
+    QgsFeatureIds::Iterator it = mSelectedFeatures.begin();
+    while ( it != mSelectedFeatures.end() ) {
+      if ( !newSelection.contains( *it ) ) {
+        it = mSelectedFeatures.erase( it );
+      } else {
+        ++it;
+      }
+    }
+
+    // Append the other fids in range first-last to mSelectedFeatures
+    QgsFeatureIds::Iterator itNew = newSelection.begin();
+    for ( ; itNew != newSelection.end(); ++itNew )
+    {
+      if ( !mSelectedFeatures.contains( *itNew ) )
+      {
+        mSelectedFeatures.insert( *itNew );
+      }
+    }
+  }
+  else if ( clickType == 2 ) // Ctrl
+  {
+    // existing selection should be updated
     if ( wasSelected )
       mSelectedFeatures.remove( fid );
     else
       mSelectedFeatures.insert( fid );
   }
-  //mFilterModel->invalidate();
+  else if ( clickType == 3 ) // Dragged click
+  {
+    QgsFeatureIds newSelection;
 
-  /*
-  QItemSelection selection;
-  QModelIndex leftUpIndex = mFilterModel->index(first, 0);
-  QModelIndex rightBottomIndex = mFilterModel->index(last, mModel->columnCount() - 1);
-  selection.append(QItemSelectionRange(leftUpIndex, rightBottomIndex));
-  mSelectionModel->select(selection, QItemSelectionModel::Select);
-  mView->setSelectionModel(mSelectionModel);
-  */
+    for ( int i = first; i <= last; ++i )
+    {
+      if ( i >= first )
+      {
+        // Id must be mapped to table/view row
+        index = mFilterModel->mapToSource( mFilterModel->index( i, 0 ) );
+        fid = mModel->rowToId( index.row() );
+      }
+      newSelection.insert( fid );
+    }
+
+    // Remove items in mSelectedFeatures if they aren't in mNewSelection
+    QgsFeatureIds::Iterator it = mSelectedFeatures.begin();
+    while ( it != mSelectedFeatures.end() ) {
+      if ( !newSelection.contains( *it ) ) {
+        it = mSelectedFeatures.erase( it );
+      } else {
+        ++it;
+      }
+    }
+
+    // Append the other fids in range first-last to mSelectedFeatures
+    QgsFeatureIds::Iterator itNew = newSelection.begin();
+    for ( ; itNew != newSelection.end(); ++itNew )
+    {
+      if ( !mSelectedFeatures.contains( *itNew ) )
+      {
+        mSelectedFeatures.insert( *itNew );
+      }
+    }
+  }
+
   updateSelection();
   mLayer->setSelectedFeatures( mSelectedFeatures );
   connect( mLayer, SIGNAL( selectionChanged() ), this, SLOT( updateSelectionFromLayer() ) );

Modified: trunk/qgis/src/app/attributetable/qgsattributetabledialog.h
===================================================================
--- trunk/qgis/src/app/attributetable/qgsattributetabledialog.h	2009-11-14 11:21:34 UTC (rev 12103)
+++ trunk/qgis/src/app/attributetable/qgsattributetabledialog.h	2009-11-14 16:24:49 UTC (rev 12104)
@@ -87,12 +87,16 @@
      */
     void updateRowSelection( int index );
     /**
+     * Updates the index pressed
+     */
+    void updateRowPressed( int index );
+    /**
      * Updates selection of specifed rows
      * @param first first row
      * @param last last row
-     * @param startNewSelection if true, then new selection is started
+     * @param clickType 0:Single click, 1:Shift, 2:Ctrl, 3:dragged click
      */
-    void updateRowSelection( int first, int last, bool startNewSelection );
+    void updateRowSelection( int first, int last, int clickType );
 
     /**
      * Toggle showing of selected line only
@@ -183,6 +187,7 @@
     QgsAttributeTableFilterModel *mFilterModel;
     QgsVectorLayer *mLayer;
     QgsFeatureIds mSelectedFeatures;
+    int mIndexPressed;
 
     QItemSelectionModel* mSelectionModel;
     int mLastClickedHeaderIndex;

Modified: trunk/qgis/src/app/attributetable/qgsattributetableview.cpp
===================================================================
--- trunk/qgis/src/app/attributetable/qgsattributetableview.cpp	2009-11-14 11:21:34 UTC (rev 12103)
+++ trunk/qgis/src/app/attributetable/qgsattributetableview.cpp	2009-11-14 16:24:49 UTC (rev 12104)
@@ -42,8 +42,6 @@
   setSelectionMode( QAbstractItemView::NoSelection );
   setSortingEnabled( true );
 
-  mShiftPressed = false;
-  mCtrlPressed = false;
 }
 
 void QgsAttributeTableView::setLayer( QgsVectorLayer* layer )
@@ -73,25 +71,3 @@
   QSettings settings;
   settings.setValue( "/BetterAttributeTable/geometry", QVariant( saveGeometry() ) );
 }
-
-void QgsAttributeTableView::keyPressEvent( QKeyEvent *event )
-{
-  // shift pressed
-  if ( event->key() == Qt::Key_Shift )// && event->modifiers() & Qt::ShiftModifier)
-    mShiftPressed = true;
-  else if ( event->key() == Qt::Key_Control )
-    mCtrlPressed = true;
-  else
-    QTableView::keyPressEvent( event );
-}
-
-void QgsAttributeTableView::keyReleaseEvent( QKeyEvent *event )
-{
-  // workaround for some Qt bug
-  if ( event->key() == Qt::Key_Shift || event->key() == -1 )
-    mShiftPressed = false;
-  else if ( event->key() == Qt::Key_Control )
-    mCtrlPressed = false;
-  else
-    QTableView::keyReleaseEvent( event );
-}

Modified: trunk/qgis/src/app/attributetable/qgsattributetableview.h
===================================================================
--- trunk/qgis/src/app/attributetable/qgsattributetableview.h	2009-11-14 11:21:34 UTC (rev 12103)
+++ trunk/qgis/src/app/attributetable/qgsattributetableview.h	2009-11-14 16:24:49 UTC (rev 12104)
@@ -41,29 +41,8 @@
      * @param event not used
      */
     void closeEvent( QCloseEvent *event );
-    /**
-     * Handles Ctrl or Shift key press
-     * @param event the key pressed
-     */
-    void keyPressEvent( QKeyEvent *event );
-    /**
-     * Handles Ctrl or Shift key release
-     * @param event the key released
-     */
-    void keyReleaseEvent( QKeyEvent *event );
-    /**
-     * Returns true if shift was pressed
-     */
-    bool shiftPressed() { return mShiftPressed; }
-    /**
-     * Returns true if ctrl was pressed
-     */
-    bool ctrlPressed() { return mCtrlPressed; }
 
   private:
-    bool mShiftPressed;
-    bool mCtrlPressed;
-
     QgsAttributeTableModel* mModel;
     QgsAttributeTableFilterModel* mFilterModel;
 };



More information about the QGIS-commit mailing list