Update undo/redo widget and vector layer rollback

- Allows for any number of undo/redo commands with only one refresh
- Significantly decreases time needed to cancel or redo many edits
- Disable undo/redo dock's widgets and toolbar actions when layer not in editing mode
This commit is contained in:
Larry Shaffer 2012-12-14 01:30:13 -07:00
parent 051fe31e22
commit 9069f3bb90
4 changed files with 49 additions and 21 deletions

View File

@ -5238,7 +5238,8 @@ bool QgisApp::toggleEditing( QgsMapLayer *layer, bool allowCancel )
res = false;
}
vlayer->triggerRepaint();
// canvas refreshes handled in QgsUndoWidget::indexChanged
//vlayer->triggerRepaint();
break;
default:
@ -7215,11 +7216,16 @@ void QgisApp::activateDeactivateLayerRelatedActions( QgsMapLayer* layer )
mActionToggleEditing->setEnabled( canChangeAttributes && !vlayer->isReadOnly() );
mActionToggleEditing->setChecked( vlayer->isEditable() );
mActionSaveEdits->setEnabled( canChangeAttributes && vlayer->isEditable() );
mUndoWidget->dockContents()->setEnabled( vlayer->isEditable() );
updateUndoActions();
}
else
{
mActionToggleEditing->setEnabled( false );
mActionSaveEdits->setEnabled( false );
mUndoWidget->dockContents()->setEnabled( false );
mActionUndo->setEnabled( false );
mActionRedo->setEnabled( false );
}
if ( dprovider->capabilities() & QgsVectorDataProvider::AddFeatures )

View File

@ -37,6 +37,8 @@ QgsUndoWidget::QgsUndoWidget( QWidget * parent, QgsMapCanvas * mapCanvas )
mMapCanvas = mapCanvas;
mUndoView = NULL;
mUndoStack = NULL;
mPreviousIndex = 0;
mPreviousCount = 0;
}
@ -80,13 +82,25 @@ void QgsUndoWidget::redoChanged( bool value )
emit undoStackChanged();
}
void QgsUndoWidget::indexChanged( int value )
void QgsUndoWidget::indexChanged( int curIndx )
{
Q_UNUSED( value );
//redoButton->setDisabled( !value );
//canvas refresh
mMapCanvas->refresh();
// this is called twice when a non-current command is clicked in QUndoView
// first call has offset, second call will have offset of 0
int curCount = 0;
if ( mUndoStack )
{
curCount = mUndoStack->count();
}
bool cmdAdded = ( curIndx == curCount && mPreviousCount == ( curCount - 1 ) );
int offset = qAbs( mPreviousIndex - curIndx );
// avoid refresh when only a command was added to stack (i.e. no undo/redo action)
if ( offset > 1 || ( offset == 1 && !cmdAdded ) )
{
mMapCanvas->refresh();
}
mPreviousIndex = curIndx;
mPreviousCount = curCount;
}
void QgsUndoWidget::undo( )
@ -111,20 +125,19 @@ void QgsUndoWidget::setUndoStack( QUndoStack* undoStack )
}
mUndoStack = undoStack;
mPreviousIndex = mUndoStack->index();
mPreviousCount = mUndoStack->count();
mUndoView = new QUndoView( dockWidgetContents );
mUndoView->setStack( undoStack );
mUndoView->setObjectName( "undoView" );
gridLayout->addWidget( mUndoView, 0, 0, 1, 2 );
setWidget( dockWidgetContents );
connect( mUndoStack, SIGNAL( canUndoChanged( bool ) ), this, SLOT( undoChanged( bool ) ) );
connect( mUndoStack, SIGNAL( canRedoChanged( bool ) ), this, SLOT( redoChanged( bool ) ) );
connect( mUndoStack, SIGNAL( canUndoChanged( bool ) ), this, SLOT( undoChanged( bool ) ) );
connect( mUndoStack, SIGNAL( canRedoChanged( bool ) ), this, SLOT( redoChanged( bool ) ) );
// indexChanged() triggers a refresh. but it gets triggered also when a new action
// is done, resulting in two refreshes. For now let's trigger the refresh from
// vector layer: it causes potentially multiple refreshes when moving more commands
// back, but avoids double refresh in common case when adding commands to the stack
//connect(mUndoStack, SIGNAL(indexChanged(int)), this, SLOT(indexChanged(int)));
// gets triggered also when a new command is added to stack, and twice when clicking a command in QUndoView
connect( mUndoStack, SIGNAL( indexChanged( int ) ), this, SLOT( indexChanged( int ) ) );
undoButton->setDisabled( !mUndoStack->canUndo() );
redoButton->setDisabled( !mUndoStack->canRedo() );

View File

@ -58,6 +58,12 @@ class QgsUndoWidget : public QDockWidget
*/
void destroyStack();
/**
* Access to dock's contents
* @note added in 1.9
*/
QWidget* dockContents() { return dockWidgetContents; }
public slots:
/**
* Changes undo stack which is displayed by undo view
@ -77,7 +83,7 @@ class QgsUndoWidget : public QDockWidget
/**
* Slot to handle index changed signal
*/
void indexChanged( int value );
void indexChanged( int curIndx );
/**
* Undo operation called from button push
@ -97,6 +103,8 @@ class QgsUndoWidget : public QDockWidget
QUndoStack * mUndoStack;
QgsMapCanvas* mMapCanvas;
int mPreviousIndex;
int mPreviousCount;
};

View File

@ -4256,10 +4256,9 @@ bool QgsVectorLayer::rollBack()
if ( isModified() )
{
while ( undoStack()->canUndo() )
{
undoStack()->undo();
}
// new undo stack roll back method
// old method of calling every undo could cause many canvas refreshes
undoStack()->setIndex( 0 );
Q_ASSERT( mAddedAttributeIds.isEmpty() );
Q_ASSERT( mDeletedAttributeIds.isEmpty() );
@ -5240,7 +5239,8 @@ void QgsVectorLayer::redoEditCommand( QgsUndoCommand* cmd )
setModified( true );
// it's not ideal to trigger refresh from here
triggerRepaint();
// canvas refreshes handled in QgsUndoWidget::indexChanged
//triggerRepaint();
}
void QgsVectorLayer::undoEditCommand( QgsUndoCommand* cmd )
@ -5363,7 +5363,8 @@ void QgsVectorLayer::undoEditCommand( QgsUndoCommand* cmd )
setModified( true );
// it's not ideal to trigger refresh from here
triggerRepaint();
// canvas refreshes handled in QgsUndoWidget::indexChanged
//triggerRepaint();
}
void QgsVectorLayer::setCheckedState( int idx, QString checked, QString unchecked )