Skip to content
Permalink
Browse files

Some undo/redo fixes for multiframe items

  • Loading branch information
nyalldawson committed Nov 7, 2017
1 parent c6eaf1f commit f04d438572797543af4ff38256653c37c979c41f
@@ -184,35 +184,6 @@ class QgsLayoutMultiFrame: QgsLayoutObject, QgsLayoutUndoObjectInterface
:rtype: bool
%End

QList<QgsLayoutFrame *> frames() const;
%Docstring
Returns a list of all child frames for this multiframe.
.. seealso:: frameCount()
:rtype: list of QgsLayoutFrame
%End

int frameCount() const;
%Docstring
Returns the number of frames associated with this multiframe.
.. seealso:: frames()
:rtype: int
%End

QgsLayoutFrame *frame( int index ) const;
%Docstring
Returns the child frame at a specified ``index`` from the multiframe.
.. seealso:: frameIndex()
:rtype: QgsLayoutFrame
%End

int frameIndex( QgsLayoutFrame *frame ) const;
%Docstring
Returns the index of a ``frame`` within the multiframe.
:return: index for frame if found, -1 if frame not found in multiframe
.. seealso:: frame()
:rtype: int
%End

QgsLayoutFrame *createNewFrame( QgsLayoutFrame *currentFrame, QPointF pos, QSizeF size );
%Docstring
Creates a new frame and adds it to the multi frame and layout.
@@ -92,6 +92,31 @@ class QgsLayoutUndoStack : QObject
Notifies the stack that an undo or redo action occurred for a specified ``item``.
%End

void blockCommands( bool blocked );
%Docstring
Sets whether undo commands for the layout should be temporarily blocked.

If ``blocked`` is true, subsequent undo commands will be blocked until a follow-up
call to blockCommands( false ) is made.

Note that calls to blockCommands are stacked, so two calls blocking the commands
will take two calls unblocking commands in order to release the block.

.. seealso:: isBlocked()
%End

bool isBlocked() const;
%Docstring
Returns true if undo commands are currently blocked.
.. seealso:: blockCommands()
:rtype: bool
%End

void push( QUndoCommand *command /Transfer/ );
%Docstring
Manually pushes a ``command`` to the stack, and takes ownership of the command.
%End

signals:

void undoRedoOccurredForItems( const QSet< QString > itemUuids );
@@ -41,7 +41,7 @@ QgsLayoutHtmlWidget::QgsLayoutHtmlWidget( QgsLayoutFrame *frame )
connect( mRadioUrlSource, &QRadioButton::clicked, this, &QgsLayoutHtmlWidget::mRadioUrlSource_clicked );
connect( mInsertExpressionButton, &QPushButton::clicked, this, &QgsLayoutHtmlWidget::mInsertExpressionButton_clicked );
connect( mReloadPushButton, &QPushButton::clicked, this, &QgsLayoutHtmlWidget::mReloadPushButton_clicked );
connect( mReloadPushButton2, &QPushButton::clicked, this, &QgsLayoutHtmlWidget::mReloadPushButton2_clicked );
connect( mReloadPushButton2, &QPushButton::clicked, this, &QgsLayoutHtmlWidget::mReloadPushButton_clicked );
connect( mAddFramePushButton, &QPushButton::clicked, this, &QgsLayoutHtmlWidget::mAddFramePushButton_clicked );
connect( mEmptyFrameCheckBox, &QCheckBox::toggled, this, &QgsLayoutHtmlWidget::mEmptyFrameCheckBox_toggled );
connect( mHideEmptyBgCheckBox, &QCheckBox::toggled, this, &QgsLayoutHtmlWidget::mHideEmptyBgCheckBox_toggled );
@@ -296,7 +296,6 @@ void QgsLayoutHtmlWidget::mRadioManualSource_clicked( bool checked )
blockSignals( true );
mHtml->beginCommand( tr( "Change HTML Source" ) );
mHtml->setContentMode( checked ? QgsLayoutItemHtml::ManualHtml : QgsLayoutItemHtml::Url );
mHtml->endCommand();
blockSignals( false );

mHtmlEditor->setEnabled( checked );
@@ -305,6 +304,7 @@ void QgsLayoutHtmlWidget::mRadioManualSource_clicked( bool checked )
mFileToolButton->setEnabled( !checked );

mHtml->loadHtml();
mHtml->endCommand();
}

void QgsLayoutHtmlWidget::mRadioUrlSource_clicked( bool checked )
@@ -317,7 +317,6 @@ void QgsLayoutHtmlWidget::mRadioUrlSource_clicked( bool checked )
blockSignals( true );
mHtml->beginCommand( tr( "Change HTML Source" ) );
mHtml->setContentMode( checked ? QgsLayoutItemHtml::Url : QgsLayoutItemHtml::ManualHtml );
mHtml->endCommand();
blockSignals( false );

mHtmlEditor->setEnabled( !checked );
@@ -326,6 +325,7 @@ void QgsLayoutHtmlWidget::mRadioUrlSource_clicked( bool checked )
mFileToolButton->setEnabled( checked );

mHtml->loadHtml();
mHtml->endCommand();
}

void QgsLayoutHtmlWidget::mInsertExpressionButton_clicked()
@@ -390,17 +390,11 @@ void QgsLayoutHtmlWidget::mReloadPushButton_clicked()
return;
}

if ( mHtml->layout() )
mHtml->layout()->undoStack()->blockCommands( true );
mHtml->loadHtml();
}

void QgsLayoutHtmlWidget::mReloadPushButton2_clicked()
{
if ( !mHtml )
{
return;
}

mHtml->loadHtml();
if ( mHtml->layout() )
mHtml->layout()->undoStack()->blockCommands( false );
}

void QgsLayoutHtmlWidget::mAddFramePushButton_clicked()
@@ -53,7 +53,6 @@ class QgsLayoutHtmlWidget: public QgsLayoutItemBaseWidget, private Ui::QgsLayout
void mInsertExpressionButton_clicked();

void mReloadPushButton_clicked();
void mReloadPushButton2_clicked();
void mAddFramePushButton_clicked();
void mEmptyFrameCheckBox_toggled( bool checked );
void mHideEmptyBgCheckBox_toggled( bool checked );
@@ -42,7 +42,7 @@ QgsLayout::QgsLayout( QgsProject *project )
QgsLayout::~QgsLayout()
{
// no need for undo commands when we're destroying the layout
mBlockUndoCommandCount++;
mUndoStack->blockCommands( true );

deleteAndRemoveMultiFrames();

@@ -410,22 +410,22 @@ void QgsLayout::addLayoutItem( QgsLayoutItem *item )
{
undoText = tr( "Create Item" );
}
if ( mBlockUndoCommandCount == 0 )
mUndoStack->stack()->push( new QgsLayoutItemAddItemCommand( item, undoText ) );
if ( !mUndoStack->isBlocked() )
mUndoStack->push( new QgsLayoutItemAddItemCommand( item, undoText ) );
}

void QgsLayout::removeLayoutItem( QgsLayoutItem *item )
{
std::unique_ptr< QgsLayoutItemDeleteUndoCommand > deleteCommand;
if ( mBlockUndoCommandCount == 0 )
if ( !mUndoStack->isBlocked() )
{
mUndoStack->beginMacro( tr( "Delete Items" ) );
deleteCommand.reset( new QgsLayoutItemDeleteUndoCommand( item, tr( "Delete Item" ) ) );
}
removeLayoutItemPrivate( item );
if ( deleteCommand )
{
mUndoStack->stack()->push( deleteCommand.release() );
mUndoStack->push( deleteCommand.release() );
mUndoStack->endMacro();
}
}
@@ -518,7 +518,7 @@ QgsLayoutItemGroup *QgsLayout::groupItems( const QList<QgsLayoutItem *> &items )
addLayoutItem( itemGroup.release() );

std::unique_ptr< QgsLayoutItemGroupUndoCommand > c( new QgsLayoutItemGroupUndoCommand( QgsLayoutItemGroupUndoCommand::Grouped, returnGroup, this, tr( "Group Items" ) ) );
mUndoStack->stack()->push( c.release() );
mUndoStack->push( c.release() );
mProject->setDirty( true );

#if 0
@@ -542,7 +542,7 @@ QList<QgsLayoutItem *> QgsLayout::ungroupItems( QgsLayoutItemGroup *group )
// Call this before removing group items so it can keep note
// of contents
std::unique_ptr< QgsLayoutItemGroupUndoCommand > c( new QgsLayoutItemGroupUndoCommand( QgsLayoutItemGroupUndoCommand::Ungrouped, group, this, tr( "Ungroup Items" ) ) );
mUndoStack->stack()->push( c.release() );
mUndoStack->push( c.release() );

mProject->setDirty( true );

@@ -559,8 +559,6 @@ class CORE_EXPORT QgsLayout : public QGraphicsScene, public QgsExpressionContext
std::unique_ptr< QgsLayoutUndoStack > mUndoStack;
QgsLayoutExporter mExporter;

int mBlockUndoCommandCount = 0;

//! List of multiframe objects
QSet<QgsLayoutMultiFrame *> mMultiFrames;

@@ -163,7 +163,7 @@ void QgsLayoutItem::setVisibility( const bool visible )
if ( command )
{
command->saveAfterState();
mLayout->undoStack()->stack()->push( command.release() );
mLayout->undoStack()->push( command.release() );
}

//inform model that visibility has changed
@@ -168,7 +168,7 @@ void QgsLayoutItemGroup::attemptMove( const QgsLayoutPoint &point, bool useRefer
if ( command )
{
command->saveAfterState();
mLayout->undoStack()->stack()->push( command.release() );
mLayout->undoStack()->push( command.release() );
}
}
//lastly move group item itself
@@ -220,7 +220,7 @@ void QgsLayoutItemGroup::attemptResize( const QgsLayoutSize &size, bool includes
if ( command )
{
command->saveAfterState();
mLayout->undoStack()->stack()->push( command.release() );
mLayout->undoStack()->push( command.release() );
}
}
QgsLayoutItem::attemptResize( size );
@@ -74,8 +74,10 @@ void QgsLayoutMultiFrame::setResizeMode( ResizeMode mode )
{
if ( mode != mResizeMode )
{
mLayout->undoStack()->beginMacro( tr( "Change Resize Mode" ) );
mResizeMode = mode;
recalculateFrameSizes();
mLayout->undoStack()->endMacro();
emit changed();
}
}
@@ -101,7 +103,7 @@ void QgsLayoutMultiFrame::recalculateFrameSizes()
}

if ( mBlockUndoCommands )
mLayout->mBlockUndoCommandCount++;
mLayout->undoStack()->blockCommands( true );

double currentY = 0;
double currentHeight = 0;
@@ -213,7 +215,7 @@ void QgsLayoutMultiFrame::recalculateFrameSizes()
}

if ( mBlockUndoCommands )
mLayout->mBlockUndoCommandCount--;
mLayout->undoStack()->blockCommands( false );
}

void QgsLayoutMultiFrame::recalculateFrameRects()
@@ -376,14 +378,14 @@ void QgsLayoutMultiFrame::removeFrame( int i, const bool removeEmptyPages )
mIsRecalculatingSize = true;
int pageNumber = frameItem->page();
//remove item, but don't create undo command
mLayout->mBlockUndoCommandCount++;
mLayout->undoStack()->blockCommands( true );
mLayout->removeLayoutItem( frameItem );
//if frame was the only item on the page, remove the page
if ( removeEmptyPages && mLayout->pageCollection()->pageIsEmpty( pageNumber ) )
{
mLayout->pageCollection()->deletePage( pageNumber );
}
mLayout->mBlockUndoCommandCount--;
mLayout->undoStack()->blockCommands( false );
mIsRecalculatingSize = false;
}
mFrameItems.removeAt( i );
@@ -402,12 +404,12 @@ void QgsLayoutMultiFrame::deleteFrames()
mBlockUpdates = true;
ResizeMode bkResizeMode = mResizeMode;
mResizeMode = UseExistingFrames;
mLayout->mBlockUndoCommandCount++;
mLayout->undoStack()->blockCommands( true );
for ( QgsLayoutFrame *frame : qgis::as_const( mFrameItems ) )
{
mLayout->removeLayoutItem( frame );
}
mLayout->mBlockUndoCommandCount--;
mLayout->undoStack()->blockCommands( false );
mFrameItems.clear();
mResizeMode = bkResizeMode;
mBlockUpdates = false;
@@ -460,6 +462,7 @@ bool QgsLayoutMultiFrame::readXml( const QDomElement &element, const QDomDocumen
}

mBlockUndoCommands = true;
mLayout->undoStack()->blockCommands( true );

readObjectPropertiesFromElement( element, doc, context );

@@ -491,6 +494,7 @@ bool QgsLayoutMultiFrame::readXml( const QDomElement &element, const QDomDocumen
bool result = readPropertiesFromElement( element, doc, context );

mBlockUndoCommands = false;
mLayout->undoStack()->blockCommands( false );
return result;
}

@@ -29,12 +29,14 @@ QgsLayoutUndoStack::QgsLayoutUndoStack( QgsLayout *layout )

void QgsLayoutUndoStack::beginMacro( const QString &commandText )
{
mUndoStack->beginMacro( commandText );
if ( mBlockedCommands == 0 )
mUndoStack->beginMacro( commandText );
}

void QgsLayoutUndoStack::endMacro()
{
mUndoStack->endMacro();
if ( mBlockedCommands == 0 )
mUndoStack->endMacro();
}

void QgsLayoutUndoStack::beginCommand( QgsLayoutUndoObjectInterface *object, const QString &commandText, int id )
@@ -54,13 +56,13 @@ void QgsLayoutUndoStack::endCommand()
return;

mActiveCommands.back()->saveAfterState();
if ( mActiveCommands.back()->containsChange() ) //protect against empty commands
if ( mBlockedCommands == 0 && mActiveCommands.back()->containsChange() ) //protect against empty commands
{
mUndoStack->push( mActiveCommands.back().release() );
mActiveCommands.pop_back();

mLayout->project()->setDirty( true );
}

mActiveCommands.pop_back();
}

void QgsLayoutUndoStack::cancelCommand()
@@ -81,6 +83,32 @@ void QgsLayoutUndoStack::notifyUndoRedoOccurred( QgsLayoutItem *item )
mUndoRedoOccurredItemUuids.insert( item->uuid() );
}

void QgsLayoutUndoStack::blockCommands( bool blocked )
{
if ( blocked )
{
mBlockedCommands++;
}
else
{
if ( mBlockedCommands > 0 )
mBlockedCommands--;
}
}

bool QgsLayoutUndoStack::isBlocked() const
{
return mBlockedCommands > 0;
}

void QgsLayoutUndoStack::push( QUndoCommand *cmd )
{
if ( mBlockedCommands > 0 )
delete cmd;
else
mUndoStack->push( cmd );
}

void QgsLayoutUndoStack::indexChanged()
{
if ( mUndoRedoOccurredItemUuids.empty() )

0 comments on commit f04d438

Please sign in to comment.
You can’t perform that action at this time.