[composer] Fix stacking of items breaks after pasting items. Make sure pasted items are always placed in correct order on top of composition.

This commit is contained in:
Nyall Dawson 2014-02-06 20:38:37 +11:00
parent 167d9b8a5f
commit d22f7e8b9d
4 changed files with 90 additions and 10 deletions

View File

@ -277,6 +277,9 @@ class QgsComposition : QGraphicsScene
after reading all the items from xml file*/ after reading all the items from xml file*/
void sortZList(); void sortZList();
/**Rebuilds the z order list based on current order of items in scene*/
void refreshZList();
/**Snaps a scene coordinate point to grid*/ /**Snaps a scene coordinate point to grid*/
QPointF snapPointToGrid( const QPointF& scenePoint ) const; QPointF snapPointToGrid( const QPointF& scenePoint ) const;

View File

@ -2628,7 +2628,9 @@ void QgsComposer::readXML( const QDomElement& composerElem, const QDomDocument&
mComposition->setWorldFileMap( worldFileMap ); mComposition->setWorldFileMap( worldFileMap );
} }
mComposition->sortZList(); //make sure z values are consistent
mComposition->refreshZList();
mView->setComposition( mComposition ); mView->setComposition( mComposition );
if ( mUndoView ) if ( mUndoView )

View File

@ -721,6 +721,12 @@ void QgsComposition::addItemsFromXML( const QDomElement& elem, const QDomDocumen
bool addUndoCommands, QPointF* pos, bool pasteInPlace ) bool addUndoCommands, QPointF* pos, bool pasteInPlace )
{ {
QPointF* pasteInPlacePt = 0; QPointF* pasteInPlacePt = 0;
//if we are adding items to a composition which already contains items, we need to make sure
//these items are placed at the top of the composition and that zValues are not duplicated
//so, calculate an offset which needs to be added to the zValue of created items
int zOrderOffset = mItemZList.size();
if ( pasteInPlace ) if ( pasteInPlace )
{ {
pasteInPlacePt = new QPointF( 0, pageNumberAt( *pos ) * ( mPageHeight + mSpaceBetweenPages ) ); pasteInPlacePt = new QPointF( 0, pageNumberAt( *pos ) * ( mPageHeight + mSpaceBetweenPages ) );
@ -744,6 +750,7 @@ void QgsComposition::addItemsFromXML( const QDomElement& elem, const QDomDocumen
} }
} }
addComposerLabel( newLabel ); addComposerLabel( newLabel );
newLabel->setZValue( newLabel->zValue() + zOrderOffset );
if ( addUndoCommands ) if ( addUndoCommands )
{ {
pushAddRemoveCommand( newLabel, tr( "Label added" ) ); pushAddRemoveCommand( newLabel, tr( "Label added" ) );
@ -764,7 +771,7 @@ void QgsComposition::addItemsFromXML( const QDomElement& elem, const QDomDocumen
newMap->setPreviewMode( QgsComposerMap::Rectangle ); newMap->setPreviewMode( QgsComposerMap::Rectangle );
} }
addComposerMap( newMap, false ); addComposerMap( newMap, false );
newMap->setZValue( newMap->zValue() + zOrderOffset );
if ( pos ) if ( pos )
{ {
if ( pasteInPlace ) if ( pasteInPlace )
@ -818,6 +825,7 @@ void QgsComposition::addItemsFromXML( const QDomElement& elem, const QDomDocumen
} }
} }
addComposerArrow( newArrow ); addComposerArrow( newArrow );
newArrow->setZValue( newArrow->zValue() + zOrderOffset );
if ( addUndoCommands ) if ( addUndoCommands )
{ {
pushAddRemoveCommand( newArrow, tr( "Arrow added" ) ); pushAddRemoveCommand( newArrow, tr( "Arrow added" ) );
@ -843,6 +851,7 @@ void QgsComposition::addItemsFromXML( const QDomElement& elem, const QDomDocumen
} }
} }
addComposerScaleBar( newScaleBar ); addComposerScaleBar( newScaleBar );
newScaleBar->setZValue( newScaleBar->zValue() + zOrderOffset );
if ( addUndoCommands ) if ( addUndoCommands )
{ {
pushAddRemoveCommand( newScaleBar, tr( "Scale bar added" ) ); pushAddRemoveCommand( newScaleBar, tr( "Scale bar added" ) );
@ -870,6 +879,7 @@ void QgsComposition::addItemsFromXML( const QDomElement& elem, const QDomDocumen
} }
} }
addComposerShape( newShape ); addComposerShape( newShape );
newShape->setZValue( newShape->zValue() + zOrderOffset );
if ( addUndoCommands ) if ( addUndoCommands )
{ {
pushAddRemoveCommand( newShape, tr( "Shape added" ) ); pushAddRemoveCommand( newShape, tr( "Shape added" ) );
@ -895,6 +905,7 @@ void QgsComposition::addItemsFromXML( const QDomElement& elem, const QDomDocumen
} }
} }
addComposerPicture( newPicture ); addComposerPicture( newPicture );
newPicture->setZValue( newPicture->zValue() + zOrderOffset );
if ( addUndoCommands ) if ( addUndoCommands )
{ {
pushAddRemoveCommand( newPicture, tr( "Picture added" ) ); pushAddRemoveCommand( newPicture, tr( "Picture added" ) );
@ -920,6 +931,7 @@ void QgsComposition::addItemsFromXML( const QDomElement& elem, const QDomDocumen
} }
} }
addComposerLegend( newLegend ); addComposerLegend( newLegend );
newLegend->setZValue( newLegend->zValue() + zOrderOffset );
if ( addUndoCommands ) if ( addUndoCommands )
{ {
pushAddRemoveCommand( newLegend, tr( "Legend added" ) ); pushAddRemoveCommand( newLegend, tr( "Legend added" ) );
@ -945,12 +957,14 @@ void QgsComposition::addItemsFromXML( const QDomElement& elem, const QDomDocumen
} }
} }
addComposerTable( newTable ); addComposerTable( newTable );
newTable->setZValue( newTable->zValue() + zOrderOffset );
if ( addUndoCommands ) if ( addUndoCommands )
{ {
pushAddRemoveCommand( newTable, tr( "Table added" ) ); pushAddRemoveCommand( newTable, tr( "Table added" ) );
} }
} }
// html // html
//TODO - fix this. pasting html items has no effect
QDomNodeList composerHtmlList = elem.elementsByTagName( "ComposerHtml" ); QDomNodeList composerHtmlList = elem.elementsByTagName( "ComposerHtml" );
for ( int i = 0; i < composerHtmlList.size(); ++i ) for ( int i = 0; i < composerHtmlList.size(); ++i )
{ {
@ -959,10 +973,19 @@ void QgsComposition::addItemsFromXML( const QDomElement& elem, const QDomDocumen
newHtml->readXML( currentHtmlElem, doc ); newHtml->readXML( currentHtmlElem, doc );
newHtml->setCreateUndoCommands( true ); newHtml->setCreateUndoCommands( true );
this->addMultiFrame( newHtml ); this->addMultiFrame( newHtml );
//offset z values for frames
//TODO - fix this after fixing html item paste
/*for ( int frameIdx = 0; frameIdx < newHtml->frameCount(); ++frameIdx )
{
QgsComposerFrame * frame = newHtml->frame( frameIdx );
frame->setZValue( frame->zValue() + zOrderOffset );
}*/
} }
// groups (must be last as it references uuids of above items) // groups (must be last as it references uuids of above items)
//TODO - pasted groups lose group properties, since the uuids of group items
//changes
QDomNodeList groupList = elem.elementsByTagName( "ComposerItemGroup" ); QDomNodeList groupList = elem.elementsByTagName( "ComposerItemGroup" );
for ( int i = 0; i < groupList.size(); ++i ) for ( int i = 0; i < groupList.size(); ++i )
{ {
@ -971,6 +994,12 @@ void QgsComposition::addItemsFromXML( const QDomElement& elem, const QDomDocumen
newGroup->readXML( groupElem, doc ); newGroup->readXML( groupElem, doc );
addItem( newGroup ); addItem( newGroup );
} }
//Since this function adds items grouped by type, and each item is added to end of
//z order list in turn, it will now be inconsistent with the actual order of items in the scene.
//Make sure z order list matches the actual order of items in the scene.
refreshZList();
} }
void QgsComposition::addItemToZList( QgsComposerItem* item ) void QgsComposition::addItemToZList( QgsComposerItem* item )
@ -1385,27 +1414,41 @@ void QgsComposition::unlockAllItems()
mUndoStack.push( parentCommand ); mUndoStack.push( parentCommand );
} }
void QgsComposition::updateZValues() void QgsComposition::updateZValues( bool addUndoCommands )
{ {
int counter = 1; int counter = 1;
QLinkedList<QgsComposerItem*>::iterator it = mItemZList.begin(); QLinkedList<QgsComposerItem*>::iterator it = mItemZList.begin();
QgsComposerItem* currentItem = 0; QgsComposerItem* currentItem = 0;
QUndoCommand* parentCommand = new QUndoCommand( tr( "Item z-order changed" ) ); QUndoCommand* parentCommand;
if ( addUndoCommands )
{
parentCommand = new QUndoCommand( tr( "Item z-order changed" ) );
}
for ( ; it != mItemZList.end(); ++it ) for ( ; it != mItemZList.end(); ++it )
{ {
currentItem = *it; currentItem = *it;
if ( currentItem ) if ( currentItem )
{ {
QgsComposerItemCommand* subcommand = new QgsComposerItemCommand( *it, "", parentCommand ); QgsComposerItemCommand* subcommand;
if ( addUndoCommands )
{
subcommand = new QgsComposerItemCommand( *it, "", parentCommand );
subcommand->savePreviousState(); subcommand->savePreviousState();
}
currentItem->setZValue( counter ); currentItem->setZValue( counter );
if ( addUndoCommands )
{
subcommand->saveAfterState(); subcommand->saveAfterState();
} }
}
++counter; ++counter;
} }
if ( addUndoCommands )
{
mUndoStack.push( parentCommand ); mUndoStack.push( parentCommand );
} }
}
void QgsComposition::sortZList() void QgsComposition::sortZList()
{ {
@ -1433,6 +1476,35 @@ void QgsComposition::sortZList()
mItemZList = sortedList; mItemZList = sortedList;
} }
void QgsComposition::refreshZList()
{
QLinkedList<QgsComposerItem*> sortedList;
//rebuild the item z order list based on the current zValues of items in the scene
//get items in descending zValue order
QList<QGraphicsItem*> itemList = items();
QList<QGraphicsItem*>::iterator itemIt = itemList.begin();
for ( ; itemIt != itemList.end(); ++itemIt )
{
QgsComposerItem* composerItem = dynamic_cast<QgsComposerItem*>( *itemIt );
if ( composerItem )
{
if ( composerItem->type() != QgsComposerItem::ComposerPaper && composerItem->type() != QgsComposerItem::ComposerFrame )
{
//since the z order list is in ascending zValue order (opposite order to itemList), we prepend each item
sortedList.prepend( composerItem );
}
}
}
mItemZList = sortedList;
//Finally, rebuild the zValue of all items to remove any duplicate zValues and make sure there's
//no missing zValues.
updateZValues( false );
}
QPointF QgsComposition::snapPointToGrid( const QPointF& scenePoint ) const QPointF QgsComposition::snapPointToGrid( const QPointF& scenePoint ) const
{ {
if ( !mSnapToGrid || mSnapGridResolution <= 0 ) if ( !mSnapToGrid || mSnapGridResolution <= 0 )

View File

@ -333,6 +333,9 @@ class CORE_EXPORT QgsComposition : public QGraphicsScene
after reading all the items from xml file*/ after reading all the items from xml file*/
void sortZList(); void sortZList();
/**Rebuilds the z order list based on current order of items in scene*/
void refreshZList();
/**Snaps a scene coordinate point to grid*/ /**Snaps a scene coordinate point to grid*/
QPointF snapPointToGrid( const QPointF& scenePoint ) const; QPointF snapPointToGrid( const QPointF& scenePoint ) const;
@ -511,7 +514,7 @@ class CORE_EXPORT QgsComposition : public QGraphicsScene
QgsComposition(); //default constructor is forbidden QgsComposition(); //default constructor is forbidden
/**Reset z-values of items based on position in z list*/ /**Reset z-values of items based on position in z list*/
void updateZValues(); void updateZValues( bool addUndoCommands = true );
/**Returns the bounding rectangle of the selected items in scene coordinates /**Returns the bounding rectangle of the selected items in scene coordinates
@return 0 in case of success*/ @return 0 in case of success*/