[QGIS Commit] r10921 - in trunk/qgis: images/themes/default src/app src/app/attributetable

svn_qgis at osgeo.org svn_qgis at osgeo.org
Sun Jun 14 10:21:44 EDT 2009


Author: wonder
Date: 2009-06-14 10:21:44 -0400 (Sun, 14 Jun 2009)
New Revision: 10921

Added:
   trunk/qgis/images/themes/default/mActionRedo.png
   trunk/qgis/images/themes/default/mActionUndo.png
   trunk/qgis/src/app/qgsundowidget.cpp
   trunk/qgis/src/app/qgsundowidget.h
Modified:
   trunk/qgis/src/app/CMakeLists.txt
   trunk/qgis/src/app/attributetable/qgsattributetablememorymodel.cpp
   trunk/qgis/src/app/attributetable/qgsattributetablemodel.cpp
   trunk/qgis/src/app/qgisapp.cpp
   trunk/qgis/src/app/qgisapp.h
   trunk/qgis/src/app/qgsmaptooladdfeature.cpp
   trunk/qgis/src/app/qgsmaptooladdisland.cpp
   trunk/qgis/src/app/qgsmaptooladdring.cpp
   trunk/qgis/src/app/qgsmaptooladdvertex.cpp
   trunk/qgis/src/app/qgsmaptooldeletepart.cpp
   trunk/qgis/src/app/qgsmaptooldeletering.cpp
   trunk/qgis/src/app/qgsmaptooldeletevertex.cpp
   trunk/qgis/src/app/qgsmaptoolidentify.cpp
   trunk/qgis/src/app/qgsmaptoolmovefeature.cpp
   trunk/qgis/src/app/qgsmaptoolmovevertex.cpp
   trunk/qgis/src/app/qgsmaptoolnodetool.cpp
   trunk/qgis/src/app/qgsmaptoolsimplify.cpp
   trunk/qgis/src/app/qgsmaptoolsplitfeatures.cpp
   trunk/qgis/src/app/qgsvectorlayerproperties.cpp
Log:
[FEATURE] Added undo/redo functionality for vector layer editing.

There are undo/redo actions in Edit menu, in Advanced digitizing toolbar
and there is a new dock widget displaying undo stack of active layer.


Added: trunk/qgis/images/themes/default/mActionRedo.png
===================================================================
(Binary files differ)


Property changes on: trunk/qgis/images/themes/default/mActionRedo.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/qgis/images/themes/default/mActionUndo.png
===================================================================
(Binary files differ)


Property changes on: trunk/qgis/images/themes/default/mActionUndo.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Modified: trunk/qgis/src/app/CMakeLists.txt
===================================================================
--- trunk/qgis/src/app/CMakeLists.txt	2009-06-14 14:17:18 UTC (rev 10920)
+++ trunk/qgis/src/app/CMakeLists.txt	2009-06-14 14:21:44 UTC (rev 10921)
@@ -60,6 +60,7 @@
   qgsshortcutsmanager.cpp
   qgssinglesymboldialog.cpp
   qgssnappingdialog.cpp
+  qgsundowidget.cpp
   qgsuniquevaluedialog.cpp
   qgsvectorlayerproperties.cpp
 
@@ -148,6 +149,7 @@
   qgsvectorlayerproperties.h
   qgsdbtablemodel.h
   qgsspatialitetablemodel.h
+  qgsundowidget.h
 
   composer/qgscomposer.h
   composer/qgscomposeritemwidget.h

Modified: trunk/qgis/src/app/attributetable/qgsattributetablememorymodel.cpp
===================================================================
--- trunk/qgis/src/app/attributetable/qgsattributetablememorymodel.cpp	2009-06-14 14:17:18 UTC (rev 10920)
+++ trunk/qgis/src/app/attributetable/qgsattributetablememorymodel.cpp	2009-06-14 14:21:44 UTC (rev 10921)
@@ -120,7 +120,9 @@
 // QgsDebugMsg(mFeatureMap[rowToId(index.row())].id());
     mFeatureMap[rowToId( index.row() )].changeAttribute( mAttributes[ index.column()], value );
     // propagate back to the layer
+    mLayer->beginEditCommand( tr("Attribute changed") );
     mLayer->changeAttributeValue( rowToId( index.row() ), mAttributes[ index.column()], value, true );
+    mLayer->endEditCommand();
   }
 
   if ( !mLayer->isModified() )

Modified: trunk/qgis/src/app/attributetable/qgsattributetablemodel.cpp
===================================================================
--- trunk/qgis/src/app/attributetable/qgsattributetablemodel.cpp	2009-06-14 14:17:18 UTC (rev 10920)
+++ trunk/qgis/src/app/attributetable/qgsattributetablemodel.cpp	2009-06-14 14:21:44 UTC (rev 10921)
@@ -393,8 +393,9 @@
   {
     mLastRowId = rowToId( index.row() );
     mLastRow = ( QgsAttributeMap * )( &( mFeat.attributeMap() ) );
-
+    mLayer->beginEditCommand( tr("Attribute changed") );
     mLayer->changeAttributeValue( rowToId( index.row() ), mAttributes[ index.column()], value, true );
+    mLayer->endEditCommand();
   }
 
   if ( !mLayer->isModified() )

Modified: trunk/qgis/src/app/qgisapp.cpp
===================================================================
--- trunk/qgis/src/app/qgisapp.cpp	2009-06-14 14:17:18 UTC (rev 10920)
+++ trunk/qgis/src/app/qgisapp.cpp	2009-06-14 14:21:44 UTC (rev 10921)
@@ -132,6 +132,7 @@
 #include "qgsrenderer.h"
 #include "qgsserversourceselect.h"
 #include "qgsshortcutsmanager.h"
+#include "qgsundowidget.h"
 #include "qgsvectordataprovider.h"
 #include "qgsvectorlayer.h"
 #include "ogr/qgsopenvectorlayerdialog.h"
@@ -363,6 +364,11 @@
   mInternalClipboard = new QgsClipboard; // create clipboard
   mQgisInterface = new QgisAppInterface( this ); // create the interfce
 
+  // create undo widget
+  mUndoWidget = new QgsUndoWidget( NULL, mMapCanvas);
+  addDockWidget(Qt::LeftDockWidgetArea, mUndoWidget);
+  mUndoWidget->hide();
+
   // set application's icon
   setWindowIcon( QPixmap( qgis_xpm ) );
 
@@ -583,11 +589,6 @@
   // Edit Menu Items
 
 #if 0
-  mActionUndo = new QAction( tr( "&Undo" ), this );
-  shortcuts->registerAction( mActionUndo, tr( "Ctrl+Z" ) );
-  mActionUndo->setStatusTip( tr( "Undo the last operation" ) );
-  connect( mActionUndo, SIGNAL( triggered ), this, SLOT( undo() ) );
-
   mActionCut = new QAction( tr( "Cu&t" ), this );
   shortcuts->registerAction( mActionCut, tr( "Ctrl+X" ) );
   mActionCut->setStatusTip( tr( "Cut the current selection's contents to the clipboard" ) );
@@ -604,6 +605,18 @@
   connect( mActionPaste, SIGNAL( triggered ), this, SLOT( paste() ) );
 #endif
 
+  mActionUndo = new QAction( getThemeIcon( "mActionUndo.png"), tr( "&Undo" ), this );
+  shortcuts->registerAction( mActionUndo, tr( "Ctrl+Z" ) );
+  mActionUndo->setStatusTip( tr( "Undo the last operation" ) );
+  mActionUndo->setEnabled( false );
+  // action connected to mUndoWidget::undo slot in setupConnections()
+
+  mActionRedo = new QAction( getThemeIcon( "mActionRedo.png"), tr( "&Redo" ), this );
+  shortcuts->registerAction( mActionRedo, tr( "Ctrl+Shift+Z" ) );
+  mActionRedo->setStatusTip( tr( "Redo the last operation" ) );
+  mActionRedo->setEnabled( false );
+  // action connected to mUndoWidget::redo slot in setupConnections()
+
   mActionCutFeatures = new QAction( getThemeIcon( "mActionEditCut.png" ), tr( "Cut Features" ), this );
   shortcuts->registerAction( mActionCutFeatures, tr( "Ctrl+X" ) );
   mActionCutFeatures->setStatusTip( tr( "Cut selected features" ) );
@@ -1132,11 +1145,14 @@
   mEditMenu = menuBar()->addMenu( tr( "&Edit" ) );
 
 #if 0
-  mEditMenu->addAction( mActionUndo );
   mEditMenu->addAction( mActionCut );
   mEditMenu->addAction( mActionCopy );
   mEditMenu->addAction( mActionPaste );
 #endif
+  mEditMenu->addAction( mActionUndo );
+  mEditMenu->addAction( mActionRedo );
+  mActionEditSeparator0 = mEditMenu->addSeparator();
+
   mEditMenu->addAction( mActionCutFeatures );
   mEditMenu->addAction( mActionCopyFeatures );
   mEditMenu->addAction( mActionPasteFeatures );
@@ -1360,6 +1376,8 @@
   mAdvancedDigitizeToolBar = addToolBar( tr( "Advanced Digitizing" ) );
   mAdvancedDigitizeToolBar->setIconSize( myIconSize );
   mAdvancedDigitizeToolBar->setObjectName( "Advanced Digitizing" );
+  mAdvancedDigitizeToolBar->addAction( mActionUndo );
+  mAdvancedDigitizeToolBar->addAction( mActionRedo );
   mAdvancedDigitizeToolBar->addAction( mActionSimplifyFeature );
   mAdvancedDigitizeToolBar->addAction( mActionAddRing );
   mAdvancedDigitizeToolBar->addAction( mActionAddIsland );
@@ -1638,6 +1656,8 @@
            mMapLegend, SLOT( addLayer( QgsMapLayer * ) ) );
   connect( mMapLegend, SIGNAL( currentLayerChanged( QgsMapLayer* ) ),
            this, SLOT( activateDeactivateLayerRelatedActions( QgsMapLayer* ) ) );
+  connect( mMapLegend, SIGNAL( currentLayerChanged( QgsMapLayer* ) ),
+           mUndoWidget, SLOT( layerChanged( QgsMapLayer* ) ) );
 
 
   //signal when mouse moved over window (coords display in status bar)
@@ -1664,7 +1684,12 @@
 
   connect( QgsProject::instance(), SIGNAL( layerLoaded( int, int ) ), this, SLOT( showProgress( int, int ) ) );
 
+  // setup undo/redo actions
+  connect( mActionUndo, SIGNAL( triggered() ), mUndoWidget, SLOT( undo() ) );
+  connect( mActionRedo, SIGNAL( triggered() ), mUndoWidget, SLOT( redo() ) );
+  connect( mUndoWidget, SIGNAL( undoStackChanged() ), this, SLOT(updateUndoActions()) );
 }
+
 void QgisApp::createCanvas()
 {
   // "theMapCanvas" used to find this canonical instance later
@@ -4083,13 +4108,14 @@
     return;
   }
 
-
+  vlayer->beginEditCommand( tr("Features deleted") );
   if ( !vlayer->deleteSelectedFeatures() )
   {
     QMessageBox::information( this, tr( "Problem deleting features" ),
                               tr( "A problem occured during deletion of features" ) );
   }
 
+  vlayer->endEditCommand();
   // notify the project we've made a change
   QgsProject::instance()->dirty( true );
 }
@@ -4228,6 +4254,8 @@
       }
     }
 
+    vl->beginEditCommand( tr("Merged features") );
+
     //create new feature
     QgsFeature newFeature;
     newFeature.setGeometry(unionGeom);
@@ -4241,6 +4269,8 @@
 
     vl->addFeature(newFeature, false);
 
+    vl->endEditCommand();;
+
     if(mapCanvas())
     {
       mapCanvas()->refresh();
@@ -4361,7 +4391,9 @@
     {
       QgsFeatureList features = selectionVectorLayer->selectedFeatures();
       clipboard()->replaceWithCopyOf( selectionVectorLayer->dataProvider()->fields(), features );
+      selectionVectorLayer->beginEditCommand( tr("Features cut") );
       selectionVectorLayer->deleteSelectedFeatures();
+      selectionVectorLayer->endEditCommand();
     }
   }
 }
@@ -4410,7 +4442,9 @@
 
     if ( pasteVectorLayer != 0 )
     {
+      pasteVectorLayer->beginEditCommand( tr("Features pasted") );
       pasteVectorLayer->addFeatures( clipboard()->copyOf() );
+      pasteVectorLayer->endEditCommand();
       mMapCanvas->refresh();
     }
   }
@@ -5420,6 +5454,8 @@
     mActionLayerProperties->setEnabled( false );
     mActionAddToOverview->setEnabled( false );
     mActionCopyFeatures->setEnabled( false );
+    mActionUndo->setEnabled( false );
+    mActionRedo->setEnabled( false );
     return;
   }
 
@@ -6139,3 +6175,20 @@
     return QPixmap( myDefaultPath );
   }
 }
+
+void QgisApp::updateUndoActions()
+{
+  bool canUndo = false, canRedo = false;
+  QgsMapLayer* layer = this->activeLayer();
+  if (layer)
+  {
+    QgsVectorLayer* vlayer = dynamic_cast<QgsVectorLayer*>( layer );
+    if ( vlayer && vlayer->isEditable() )
+    {
+      canUndo = vlayer->undoStack()->canUndo();
+      canRedo = vlayer->undoStack()->canRedo();
+    }
+  }
+  mActionUndo->setEnabled( canUndo );
+  mActionRedo->setEnabled( canRedo );
+}

Modified: trunk/qgis/src/app/qgisapp.h
===================================================================
--- trunk/qgis/src/app/qgisapp.h	2009-06-14 14:17:18 UTC (rev 10920)
+++ trunk/qgis/src/app/qgisapp.h	2009-06-14 14:21:44 UTC (rev 10921)
@@ -56,6 +56,7 @@
 class QgsPythonUtils;
 class QgsRasterLayer;
 class QgsRectangle;
+class QgsUndoWidget;
 class QgsVectorLayer;
 
 #include <QMainWindow>
@@ -341,6 +342,8 @@
     //! Zoom to selected features
     void zoomToSelected();
 
+    void updateUndoActions();
+
     //! cuts selected features on the active layer to the clipboard
     /**
        \param layerContainingSelection  The layer that the selection will be taken from
@@ -710,6 +713,9 @@
     QAction *mActionFileSeparator4;
     QAction *mActionExit;
 
+    QAction *mActionUndo;
+    QAction *mActionRedo;
+    QAction *mActionEditSeparator0;
     QAction *mActionCutFeatures;
     QAction *mActionCopyFeatures;
     QAction *mActionPasteFeatures;
@@ -958,6 +964,8 @@
 
     static QgisApp *smInstance;
 
+    QgsUndoWidget* mUndoWidget;
+
 };
 
 #endif

Modified: trunk/qgis/src/app/qgsmaptooladdfeature.cpp
===================================================================
--- trunk/qgis/src/app/qgsmaptooladdfeature.cpp	2009-06-14 14:17:18 UTC (rev 10920)
+++ trunk/qgis/src/app/qgsmaptooladdfeature.cpp	2009-06-14 14:21:44 UTC (rev 10921)
@@ -459,6 +459,7 @@
       bool isDisabledAttributeValuesDlg = settings.value( "/qgis/digitizing/disable_enter_attribute_values_dialog", false ).toBool();
       if ( isDisabledAttributeValuesDlg )
       {
+        vlayer->beginEditCommand( tr("Feature added") );
         if ( vlayer->addFeature( *f ) )
         {
           //add points to other features to keep topology up-to-date
@@ -468,12 +469,14 @@
             vlayer->addTopologicalPoints( f->geometry() );
           }
         }
+        vlayer->endEditCommand();
       }
       else
       {
         QgsAttributeDialog * mypDialog = new QgsAttributeDialog( vlayer, f );
         if ( mypDialog->exec() )
         {
+          vlayer->beginEditCommand( tr("Feature added") );
           if ( vlayer->addFeature( *f ) )
           {
             //add points to other features to keep topology up-to-date
@@ -483,6 +486,7 @@
               vlayer->addTopologicalPoints( f->geometry() );
             }
           }
+          vlayer->endEditCommand();
         }
         delete mypDialog;
       }

Modified: trunk/qgis/src/app/qgsmaptooladdisland.cpp
===================================================================
--- trunk/qgis/src/app/qgsmaptooladdisland.cpp	2009-06-14 14:17:18 UTC (rev 10920)
+++ trunk/qgis/src/app/qgsmaptooladdisland.cpp	2009-06-14 14:21:44 UTC (rev 10921)
@@ -101,8 +101,9 @@
 
     //close polygon
     mCaptureList.push_back( *mCaptureList.begin() );
-
+    vlayer->beginEditCommand( tr("Island added") );
     int errorCode = vlayer->addIsland( mCaptureList );
+    vlayer->endEditCommand();
     QString errorMessage;
 
     if ( errorCode != 0 )

Modified: trunk/qgis/src/app/qgsmaptooladdring.cpp
===================================================================
--- trunk/qgis/src/app/qgsmaptooladdring.cpp	2009-06-14 14:17:18 UTC (rev 10920)
+++ trunk/qgis/src/app/qgsmaptooladdring.cpp	2009-06-14 14:21:44 UTC (rev 10921)
@@ -81,7 +81,9 @@
     //close polygon
     mCaptureList.push_back( *mCaptureList.begin() );
 
+    vlayer->beginEditCommand( tr("Ring added") );
     int addRingReturnCode = vlayer->addRing( mCaptureList );
+    vlayer->endEditCommand();
     if ( addRingReturnCode != 0 )
     {
       QString errorMessage;

Modified: trunk/qgis/src/app/qgsmaptooladdvertex.cpp
===================================================================
--- trunk/qgis/src/app/qgsmaptooladdvertex.cpp	2009-06-14 14:17:18 UTC (rev 10920)
+++ trunk/qgis/src/app/qgsmaptooladdvertex.cpp	2009-06-14 14:21:44 UTC (rev 10921)
@@ -122,10 +122,12 @@
 
       //and change the feature points
       QList<QgsSnappingResult>::iterator sr_it = mRecentSnappingResults.begin();
+      vlayer->beginEditCommand( tr("Added vertex") );
       for ( ; sr_it != mRecentSnappingResults.end(); ++sr_it )
       {
         vlayer->insertVertex( snappedPointLayerCoord.x(), snappedPointLayerCoord.y(), sr_it->snappedAtGeometry, sr_it->afterVertexNr );
       }
+      vlayer->endEditCommand();
     }
   }
 

Modified: trunk/qgis/src/app/qgsmaptooldeletepart.cpp
===================================================================
--- trunk/qgis/src/app/qgsmaptooldeletepart.cpp	2009-06-14 14:17:18 UTC (rev 10920)
+++ trunk/qgis/src/app/qgsmaptooldeletepart.cpp	2009-06-14 14:21:44 UTC (rev 10921)
@@ -106,7 +106,9 @@
 
   if ( g->deletePart( partNum ) )
   {
+    vlayer->beginEditCommand( tr("Part of multipart feature deleted") );
     vlayer->changeGeometry( fId, g );
+    vlayer->endEditCommand();
     mCanvas->refresh();
   }
   else

Modified: trunk/qgis/src/app/qgsmaptooldeletering.cpp
===================================================================
--- trunk/qgis/src/app/qgsmaptooldeletering.cpp	2009-06-14 14:17:18 UTC (rev 10920)
+++ trunk/qgis/src/app/qgsmaptooldeletering.cpp	2009-06-14 14:21:44 UTC (rev 10921)
@@ -111,7 +111,9 @@
 
   if ( g->deleteRing( ringNum, partNum ) )
   {
+    vlayer->beginEditCommand( tr("Ring deleted") );
     vlayer->changeGeometry( fId, g );
+    vlayer->endEditCommand();
     mCanvas->refresh();
   }
 

Modified: trunk/qgis/src/app/qgsmaptooldeletevertex.cpp
===================================================================
--- trunk/qgis/src/app/qgsmaptooldeletevertex.cpp	2009-06-14 14:17:18 UTC (rev 10920)
+++ trunk/qgis/src/app/qgsmaptooldeletevertex.cpp	2009-06-14 14:21:44 UTC (rev 10921)
@@ -79,10 +79,12 @@
   if ( vlayer && mRecentSnappingResults.size() > 0 )
   {
     QList<QgsSnappingResult>::iterator sr_it = mRecentSnappingResults.begin();
+    vlayer->beginEditCommand( tr("Vertex deleted") );
     for ( ; sr_it != mRecentSnappingResults.end(); ++sr_it )
     {
       vlayer->deleteVertex( sr_it->snappedAtGeometry, sr_it->snappedVertexNr );
     }
+    vlayer->endEditCommand();
   }
 
   mCanvas->refresh();

Modified: trunk/qgis/src/app/qgsmaptoolidentify.cpp
===================================================================
--- trunk/qgis/src/app/qgsmaptoolidentify.cpp	2009-06-14 14:17:18 UTC (rev 10920)
+++ trunk/qgis/src/app/qgsmaptoolidentify.cpp	2009-06-14 14:21:44 UTC (rev 10921)
@@ -489,17 +489,25 @@
 
   QgsAttributeMap src = f.attributeMap();
 
+  layer->beginEditCommand( tr("Attribute changed") );
   QgsAttributeDialog *ad = new QgsAttributeDialog( layer, &f );
   if ( ad->exec() )
   {
     const QgsAttributeMap &dst = f.attributeMap();
-
     for ( QgsAttributeMap::const_iterator it = dst.begin(); it != dst.end(); it++ )
     {
       if ( !src.contains( it.key() ) || it.value() != src[it.key()] )
+      {
         layer->changeAttributeValue( f.id(), it.key(), it.value() );
+      }
     }
+    layer->endEditCommand();
   }
+  else
+  {
+    layer->destroyEditCommand();
+  }
+
   delete ad;
   mCanvas->refresh();
 }

Modified: trunk/qgis/src/app/qgsmaptoolmovefeature.cpp
===================================================================
--- trunk/qgis/src/app/qgsmaptoolmovefeature.cpp	2009-06-14 14:17:18 UTC (rev 10920)
+++ trunk/qgis/src/app/qgsmaptoolmovefeature.cpp	2009-06-14 14:21:44 UTC (rev 10921)
@@ -137,12 +137,12 @@
 
   double dx = stopPointLayerCoords.x() - startPointLayerCoords.x();
   double dy = stopPointLayerCoords.y() - startPointLayerCoords.y();
-
+  vlayer->beginEditCommand( tr("Feature moved") );
   vlayer->translateFeature( mMovedFeature, dx, dy );
-
   delete mRubberBand;
   mRubberBand = 0;
   mCanvas->refresh();
+  vlayer->endEditCommand();
 }
 
 //! called when map tool is being deactivated

Modified: trunk/qgis/src/app/qgsmaptoolmovevertex.cpp
===================================================================
--- trunk/qgis/src/app/qgsmaptoolmovevertex.cpp	2009-06-14 14:17:18 UTC (rev 10920)
+++ trunk/qgis/src/app/qgsmaptoolmovevertex.cpp	2009-06-14 14:21:44 UTC (rev 10921)
@@ -164,6 +164,7 @@
 
     snappedPointLayerCoord = toLayerCoordinates( vlayer, snappedPointMapCoord );
 
+    vlayer->beginEditCommand( tr("Vertex moved") );
     //and change the feature points
     QList<QgsSnappingResult>::iterator sr_it = mRecentSnappingResults.begin();
     for ( ; sr_it != mRecentSnappingResults.end(); ++sr_it )
@@ -173,6 +174,7 @@
         //error
       }
     }
+    vlayer->endEditCommand();
 
   }
 

Modified: trunk/qgis/src/app/qgsmaptoolnodetool.cpp
===================================================================
--- trunk/qgis/src/app/qgsmaptoolnodetool.cpp	2009-06-14 14:17:18 UTC (rev 10920)
+++ trunk/qgis/src/app/qgsmaptoolnodetool.cpp	2009-06-14 14:21:44 UTC (rev 10921)
@@ -438,7 +438,9 @@
       {
         QgsPoint coords = mCanvas->getCoordinateTransform()->toMapPoint( e->pos().x(),  e->pos().y() );
         //add vertex
+        vlayer->beginEditCommand( tr("Inserted vertex") );
         vlayer->insertVertex(coords.x(), coords.y(), mSelectionFeature->featureId(), snapResults.first().afterVertexNr );
+        vlayer->endEditCommand();
 
         mSelectionFeature->updateFromFeature();
       }
@@ -536,11 +538,14 @@
 
 void SelectionFeature::deleteSelectedVertexes()
 {
+  mVlayer->beginEditCommand( QObject::tr("Deleted vertices") );
+  int count = 0;
   for (int i = mVertexMap.size() -1; i > -1 ; i--)
   {
     if (mVertexMap[i].selected)
     {
       mVlayer->deleteVertex(mFeatureId, i);
+      count++;
 
       if (mVertexMap[i].equals != -1 && !mVertexMap[mVertexMap[i].equals].selected)
       {
@@ -548,12 +553,18 @@
       }
     }
   }
+  if (count)
+    mVlayer->endEditCommand();
+  else
+    mVlayer->destroyEditCommand(); // no changes...
+
   updateFromFeature();
 }
 
 
 void SelectionFeature::moveSelectedVertexes( double changeX, double changeY )
 {
+  mVlayer->beginEditCommand( QObject::tr("Moved vertices") );
   for (int i = mVertexMap.size() -1; i > -1 ; i--)
   {
     if (mVertexMap[i].selected)
@@ -570,6 +581,7 @@
       }
     }
   }
+  mVlayer->endEditCommand();
   updateFeature();
 }
 

Modified: trunk/qgis/src/app/qgsmaptoolsimplify.cpp
===================================================================
--- trunk/qgis/src/app/qgsmaptoolsimplify.cpp	2009-06-14 14:17:18 UTC (rev 10920)
+++ trunk/qgis/src/app/qgsmaptoolsimplify.cpp	2009-06-14 14:21:44 UTC (rev 10921)
@@ -111,7 +111,9 @@
     QgsSimplifyFeature::simplifyPolygon( mSelectedFeature, mTolerance );
   }
 
+  vlayer->beginEditCommand( tr("Geometry simplified") );
   vlayer->changeGeometry( mSelectedFeature.id(), mSelectedFeature.geometry() );
+  vlayer->endEditCommand();
 
   mCanvas->refresh();
 }

Modified: trunk/qgis/src/app/qgsmaptoolsplitfeatures.cpp
===================================================================
--- trunk/qgis/src/app/qgsmaptoolsplitfeatures.cpp	2009-06-14 14:17:18 UTC (rev 10920)
+++ trunk/qgis/src/app/qgsmaptoolsplitfeatures.cpp	2009-06-14 14:21:44 UTC (rev 10921)
@@ -79,7 +79,9 @@
 
     //bring up dialog if a split was not possible (polygon) or only done once (line)
     int topologicalEditing = QgsProject::instance()->readNumEntry( "Digitizing", "/TopologicalEditing", 0 );
+    vlayer->beginEditCommand( tr("Features split") );
     int returnCode = vlayer->splitFeatures( mCaptureList, topologicalEditing );
+    vlayer->endEditCommand();
     if ( returnCode == 4 )
     {
       QMessageBox::warning( 0, tr( "No feature split done" ), tr( "If there are selected features, the split tool only applies to the selected ones. If you like to split all features under the split line, clear the selection" ) );

Added: trunk/qgis/src/app/qgsundowidget.cpp
===================================================================
--- trunk/qgis/src/app/qgsundowidget.cpp	                        (rev 0)
+++ trunk/qgis/src/app/qgsundowidget.cpp	2009-06-14 14:21:44 UTC (rev 10921)
@@ -0,0 +1,159 @@
+#include "qgsundowidget.h"
+
+#include "qgsmaplayer.h"
+#include "qgsmapcanvas.h"
+
+#include "qgisapp.h"
+
+QgsUndoWidget::QgsUndoWidget( QWidget * parent, QgsMapCanvas * mapCanvas )
+    : QDockWidget( parent )
+{
+  setupUi(this);
+  setWidget(dockWidgetContents);
+  connect( this->undoButton, SIGNAL( clicked() ),
+           this, SLOT( undo( ) ) );
+
+  connect( this->redoButton, SIGNAL( clicked() ),
+           this, SLOT( redo( ) ) );
+  undoButton->setDisabled( true );
+  redoButton->setDisabled( true );
+  mMapCanvas = mapCanvas;
+  mUndoView = NULL;
+  mUndoStack = NULL;
+}
+
+
+void QgsUndoWidget::layerChanged( QgsMapLayer * layer)
+{
+   if (layer != NULL)
+   {
+      setUndoStack( layer->undoStack() );
+   }
+   else
+   {
+     destroyStack();
+   }
+   emit undoStackChanged();
+}
+
+
+void QgsUndoWidget::destroyStack()
+{
+   if (mUndoStack != NULL)
+   {
+     mUndoStack->clear();
+     mUndoStack = NULL;
+   }
+   if (mUndoView != NULL)
+   {
+     mUndoView->close();
+     mUndoView = NULL;
+   }
+}
+
+void QgsUndoWidget::undoChanged(bool value)
+{
+   undoButton->setDisabled( !value );
+   emit undoStackChanged();
+}
+
+void QgsUndoWidget::redoChanged(bool value)
+{
+   redoButton->setDisabled( !value );
+   emit undoStackChanged();
+}
+
+
+void QgsUndoWidget::indexChanged(int value)
+{
+   //redoButton->setDisabled( !value );
+   //canvas refresh
+   mMapCanvas->refresh();
+}
+
+void QgsUndoWidget::undo( )
+{
+  if (mUndoStack)
+    mUndoStack->undo();
+}
+
+void QgsUndoWidget::redo()
+{
+  if (mUndoStack)
+    mUndoStack->redo();
+}
+
+void QgsUndoWidget::setUndoStack(QUndoStack* undoStack)
+{
+  if (mUndoView != NULL)
+  {
+     mUndoView->close();
+     delete mUndoView;
+     mUndoView = NULL;
+  }
+        
+  mUndoStack = undoStack;
+        
+  mUndoView = new QUndoView(dockWidgetContents);
+  mUndoView->setStack(undoStack); 
+  mUndoView->setObjectName("undoView");
+  gridLayout->addWidget(mUndoView, 0, 0, 1, 2);
+  setWidget(dockWidgetContents);
+  connect(this->mUndoStack,  SIGNAL(canUndoChanged(bool)), this, SLOT(undoChanged(bool)));
+  connect(this->mUndoStack,  SIGNAL(canRedoChanged(bool)), this, SLOT(redoChanged(bool)));
+  connect(this->mUndoStack,  SIGNAL(indexChanged(int)), this, SLOT(indexChanged(int)));
+
+  this->undoButton->setDisabled( !mUndoStack->canUndo() );
+  this->redoButton->setDisabled( !mUndoStack->canRedo() );
+}
+
+
+
+void QgsUndoWidget::setupUi(QDockWidget *UndoWidget)
+{
+	if (UndoWidget->objectName().isEmpty())
+		UndoWidget->setObjectName(QString::fromUtf8("UndoWidget"));
+	UndoWidget->resize(350, 223);
+	UndoWidget->setMinimumSize(QSize(346, 220));
+	dockWidgetContents = new QWidget(UndoWidget);
+	dockWidgetContents->setObjectName(QString::fromUtf8("dockWidgetContents"));
+	gridLayout = new QGridLayout(dockWidgetContents);
+	gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
+	gridLayout->setContentsMargins(0, 0, 0, 0);
+	spacerItem = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
+	
+	gridLayout->addItem(spacerItem, 0, 0, 1, 1);
+	
+	undoButton = new QPushButton(dockWidgetContents);
+	undoButton->setObjectName(QString::fromUtf8("undoButton"));
+  undoButton->setIcon( QgisApp::instance()->getThemeIcon("mActionUndo.png") );
+	undoButton->setIconSize(QSize(24, 24));
+	
+	gridLayout->addWidget(undoButton, 1, 0, 1, 1);
+	
+	redoButton = new QPushButton(dockWidgetContents);
+	redoButton->setObjectName(QString::fromUtf8("redoButton"));
+  redoButton->setIcon( QgisApp::instance()->getThemeIcon("mActionRedo.png") );
+  redoButton->setIconSize(QSize(24, 24));
+	
+	gridLayout->addWidget(redoButton, 1, 1, 1, 1);
+	
+	spacerItem1 = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
+	
+	gridLayout->addItem(spacerItem1, 0, 1, 1, 1);
+	
+	UndoWidget->setWidget(dockWidgetContents);
+	
+	retranslateUi(UndoWidget);
+	
+	QMetaObject::connectSlotsByName(UndoWidget);
+} // setupUi
+
+void QgsUndoWidget::retranslateUi(QDockWidget *UndoWidget)
+{
+  UndoWidget->setWindowTitle(QApplication::translate("UndoWidget", "Undo/Redo", 0, QApplication::UnicodeUTF8));
+	undoButton->setText(QApplication::translate("UndoWidget", "Undo", 0, QApplication::UnicodeUTF8));
+	redoButton->setText(QApplication::translate("UndoWidget", "Redo", 0, QApplication::UnicodeUTF8));
+	Q_UNUSED(UndoWidget);
+}
+

Added: trunk/qgis/src/app/qgsundowidget.h
===================================================================
--- trunk/qgis/src/app/qgsundowidget.h	                        (rev 0)
+++ trunk/qgis/src/app/qgsundowidget.h	2009-06-14 14:21:44 UTC (rev 10921)
@@ -0,0 +1,90 @@
+#ifndef QGSUNDOWIDGET_H
+#define QGSUNDOWIDGET_H
+
+#include <QtCore/QVariant>
+#include <QtGui/QAction>
+#include <QtGui/QApplication>
+#include <QtGui/QButtonGroup>
+#include <QtGui/QDockWidget>
+#include <QtGui/QGridLayout>
+#include <QtGui/QPushButton>
+#include <QtGui/QSpacerItem>
+#include <QtGui/QWidget>
+#include <QUndoView>
+#include <QUndoStack>
+
+class QgsMapCanvas;
+class QgsMapLayer;
+
+/**
+ * Class that handles undo display fo undo commands
+ */
+class QgsUndoWidget : public QDockWidget
+{
+	Q_OBJECT
+public:
+    QWidget *dockWidgetContents;
+    QGridLayout *gridLayout;
+    QSpacerItem *spacerItem;
+    QPushButton *undoButton;
+    QPushButton *redoButton;
+    QSpacerItem *spacerItem1;
+
+    QgsUndoWidget(QWidget * parent, QgsMapCanvas* mapCanvas);
+    void setupUi(QDockWidget *UndoWidget);
+    void retranslateUi(QDockWidget *UndoWidget);
+
+    /**
+     * Setting new undo stack for undo view
+     */
+    void setUndoStack(QUndoStack * undoStack);
+
+    /**
+     * Handles destroying of stack when active layer is changed
+     */
+    void destroyStack();
+
+public slots:
+    /**
+     * Changes undo stack which is displayed by undo view
+     */
+    void layerChanged( QgsMapLayer * layer);
+
+    /**
+     * Slot to handle undo changed signal
+     */
+    void undoChanged(bool value);
+
+    /**
+     * Slot to handle redo changed signal
+     */
+    void redoChanged(bool value);
+
+    /**
+     * Slot to handle index changed signal
+     */
+    void indexChanged(int value);
+
+    /**
+     * Undo operation called from button push
+     */
+    void undo();
+
+    /**
+     * Redo operation called from button push
+     */
+    void redo();
+
+signals:
+    void undoStackChanged();
+
+private:
+    QUndoView * mUndoView;
+    QUndoStack * mUndoStack;
+    QgsMapCanvas* mMapCanvas;
+
+};
+
+
+#endif // QGSUNDOWIDGET_H
+

Modified: trunk/qgis/src/app/qgsvectorlayerproperties.cpp
===================================================================
--- trunk/qgis/src/app/qgsvectorlayerproperties.cpp	2009-06-14 14:17:18 UTC (rev 10920)
+++ trunk/qgis/src/app/qgsvectorlayerproperties.cpp	2009-06-14 14:21:44 UTC (rev 10921)
@@ -272,7 +272,17 @@
 bool QgsVectorLayerProperties::addAttribute( const QgsField &field )
 {
   QgsDebugMsg( "inserting attribute " + field.name() + " of type " + field.typeName() );
-  return layer->addAttribute( field );
+  layer->beginEditCommand( tr("Added attribute") );
+  if ( layer->addAttribute( field ) )
+  {
+    layer->endEditCommand();
+    return true;
+  }
+  else
+  {
+    layer->destroyEditCommand();
+    return false;
+  }
 }
 
 void QgsVectorLayerProperties::deleteAttribute()
@@ -287,7 +297,11 @@
   }
 
   for ( QList<int>::const_iterator it = idxs.begin(); it != idxs.end(); it++ )
+  {
+    layer->beginEditCommand( tr("Deleted attribute") );
     layer->deleteAttribute( *it );
+    layer->endEditCommand();
+  }
 }
 
 void QgsVectorLayerProperties::editingToggled()



More information about the QGIS-commit mailing list