357 changes: 357 additions & 0 deletions src/core/composer/qgscomposition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@
#include "qgscomposeritem.h"
#include "qgscomposermap.h"
#include "qgspaperitem.h"
#include "qgscomposerarrow.h"
#include "qgscomposerlabel.h"
#include "qgscomposerlegend.h"
#include "qgscomposermap.h"
#include "qgscomposeritemgroup.h"
#include "qgscomposerpicture.h"
#include "qgscomposerscalebar.h"
#include "qgscomposershape.h"
#include "qgscomposerattributetable.h"
#include "qgslogger.h"
#include <QDomDocument>
#include <QDomElement>
Expand Down Expand Up @@ -252,6 +261,145 @@ bool QgsComposition::readXML( const QDomElement& compositionElem, const QDomDocu
return true;
}

void QgsComposition::addItemsFromXML( const QDomElement& elem, const QDomDocument& doc, bool addUndoCommands, QPointF* pos )
{
QDomNodeList composerLabelList = elem.elementsByTagName( "ComposerLabel" );
for ( int i = 0; i < composerLabelList.size(); ++i )
{
QDomElement currentComposerLabelElem = composerLabelList.at( i ).toElement();
QgsComposerLabel* newLabel = new QgsComposerLabel( this );
newLabel->readXML( currentComposerLabelElem, doc );
if ( pos )
{
newLabel->setItemPosition( pos->x(), pos->y() );
}
addComposerLabel( newLabel );
if ( addUndoCommands )
{
pushAddRemoveCommand( newLabel, tr( "Label added" ) );
}
}
// map
QDomNodeList composerMapList = elem.elementsByTagName( "ComposerMap" );
for ( int i = 0; i < composerMapList.size(); ++i )
{
QDomElement currentComposerMapElem = composerMapList.at( i ).toElement();
QgsComposerMap* newMap = new QgsComposerMap( this );
newMap->readXML( currentComposerMapElem, doc );
if ( pos )
{
newMap->setItemPosition( pos->x(), pos->y() );
}
addComposerMap( newMap );
if ( addUndoCommands )
{
pushAddRemoveCommand( newMap, tr( "Map added" ) );
}
}
// arrow
QDomNodeList composerArrowList = elem.elementsByTagName( "ComposerArrow" );
for ( int i = 0; i < composerArrowList.size(); ++i )
{
QDomElement currentComposerArrowElem = composerArrowList.at( i ).toElement();
QgsComposerArrow* newArrow = new QgsComposerArrow( this );
newArrow->readXML( currentComposerArrowElem, doc );
if ( pos )
{
newArrow->setItemPosition( pos->x(), pos->y() );
}
addComposerArrow( newArrow );
if ( addUndoCommands )
{
pushAddRemoveCommand( newArrow, tr( "Arrow added" ) );
}
}
// scalebar
QDomNodeList composerScaleBarList = elem.elementsByTagName( "ComposerScaleBar" );
for ( int i = 0; i < composerScaleBarList.size(); ++i )
{
QDomElement currentComposerScaleBarElem = composerScaleBarList.at( i ).toElement();
QgsComposerScaleBar* newScaleBar = new QgsComposerScaleBar( this );
newScaleBar->readXML( currentComposerScaleBarElem, doc );
if ( pos )
{
newScaleBar->setItemPosition( pos->x(), pos->y() );
}
addComposerScaleBar( newScaleBar );
if ( addUndoCommands )
{
pushAddRemoveCommand( newScaleBar, tr( "Scale bar added" ) );
}
}
// shape
QDomNodeList composerShapeList = elem.elementsByTagName( "ComposerShape" );
for ( int i = 0; i < composerShapeList.size(); ++i )
{
QDomElement currentComposerShapeElem = composerShapeList.at( i ).toElement();
QgsComposerShape* newShape = new QgsComposerShape( this );
newShape->readXML( currentComposerShapeElem, doc );
if ( pos )
{
newShape->setItemPosition( pos->x(), pos->y() );
}
addComposerShape( newShape );
if ( addUndoCommands )
{
pushAddRemoveCommand( newShape, tr( "Shape added" ) );
}
}
// picture
QDomNodeList composerPictureList = elem.elementsByTagName( "ComposerPicture" );
for ( int i = 0; i < composerPictureList.size(); ++i )
{
QDomElement currentComposerPictureElem = composerPictureList.at( i ).toElement();
QgsComposerPicture* newPicture = new QgsComposerPicture( this );
newPicture->readXML( currentComposerPictureElem, doc );
if ( pos )
{
newPicture->setItemPosition( pos->x(), pos->y() );
}
addComposerPicture( newPicture );
if ( addUndoCommands )
{
pushAddRemoveCommand( newPicture, tr( "Picture added" ) );
}
}
// legend
QDomNodeList composerLegendList = elem.elementsByTagName( "ComposerLegend" );
for ( int i = 0; i < composerLegendList.size(); ++i )
{
QDomElement currentComposerLegendElem = composerLegendList.at( i ).toElement();
QgsComposerLegend* newLegend = new QgsComposerLegend( this );
newLegend->readXML( currentComposerLegendElem, doc );
if ( pos )
{
newLegend->setItemPosition( pos->x(), pos->y() );
}
addComposerLegend( newLegend );
if ( addUndoCommands )
{
pushAddRemoveCommand( newLegend, tr( "Legend added" ) );
}
}
// table
QDomNodeList composerTableList = elem.elementsByTagName( "ComposerAttributeTable" );
for ( int i = 0; i < composerTableList.size(); ++i )
{
QDomElement currentComposerTableElem = composerTableList.at( i ).toElement();
QgsComposerAttributeTable* newTable = new QgsComposerAttributeTable( this );
newTable->readXML( currentComposerTableElem, doc );
if ( pos )
{
newTable->setItemPosition( pos->x(), pos->y() );
}
addComposerTable( newTable );
if ( addUndoCommands )
{
pushAddRemoveCommand( newTable, tr( "Table added" ) );
}
}
}

void QgsComposition::addItemToZList( QgsComposerItem* item )
{
if ( !item )
Expand Down Expand Up @@ -833,3 +981,212 @@ void QgsComposition::cancelCommand()
delete mActiveCommand;
mActiveCommand = 0;
}

void QgsComposition::addComposerArrow( QgsComposerArrow* arrow )
{
addItem( arrow );
emit composerArrowAdded( arrow );
clearSelection();
arrow->setSelected( true );
emit selectedItemChanged( arrow );
//pushAddRemoveCommand( arrow, tr( "Arrow added" ) );
}

void QgsComposition::addComposerLabel( QgsComposerLabel* label )
{
addItem( label );
emit composerLabelAdded( label );
clearSelection();
label->setSelected( true );
emit selectedItemChanged( label );
//pushAddRemoveCommand( label, tr( "Label added" ) );
}

void QgsComposition::addComposerMap( QgsComposerMap* map )
{
addItem( map );
//set default preview mode to cache. Must be done here between adding composer map to scene and emiting signal
map->setPreviewMode( QgsComposerMap::Cache );
map->cache();
emit composerMapAdded( map );
clearSelection();
map->setSelected( true );
emit selectedItemChanged( map );
//pushAddRemoveCommand( map, tr( "Map added" ) );
}

void QgsComposition::addComposerScaleBar( QgsComposerScaleBar* scaleBar )
{
//take first available map
QList<const QgsComposerMap*> mapItemList = composerMapItems();
if ( mapItemList.size() > 0 )
{
scaleBar->setComposerMap( mapItemList.at( 0 ) );
}
scaleBar->applyDefaultSize(); //4 segments, 1/5 of composer map width
addItem( scaleBar );
emit composerScaleBarAdded( scaleBar );
clearSelection();
scaleBar->setSelected( true );
emit selectedItemChanged( scaleBar );
//pushAddRemoveCommand( scaleBar, tr( "Scale bar added" ) );
}

void QgsComposition::addComposerLegend( QgsComposerLegend* legend )
{
//take first available map
QList<const QgsComposerMap*> mapItemList = composerMapItems();
if ( mapItemList.size() > 0 )
{
legend->setComposerMap( mapItemList.at( 0 ) );
}
addItem( legend );
emit composerLegendAdded( legend );
clearSelection();
legend->setSelected( true );
emit selectedItemChanged( legend );
//pushAddRemoveCommand( legend, tr( "Legend added" ) );
}

void QgsComposition::addComposerPicture( QgsComposerPicture* picture )
{
addItem( picture );
emit composerPictureAdded( picture );
clearSelection();
picture->setSelected( true );
emit selectedItemChanged( picture );
//pushAddRemoveCommand( picture, tr( "Picture added" ) );
}

void QgsComposition::addComposerShape( QgsComposerShape* shape )
{
addItem( shape );
emit composerShapeAdded( shape );
clearSelection();
shape->setSelected( true );
emit selectedItemChanged( shape );
//pushAddRemoveCommand( shape, tr( "Shape added" ) );
}

void QgsComposition::addComposerTable( QgsComposerAttributeTable* table )
{
addItem( table );
emit composerTableAdded( table );
clearSelection();
table->setSelected( true );
emit selectedItemChanged( table );
//pushAddRemoveCommand( table, tr( "Table added" ) );
}

void QgsComposition::removeComposerItem( QgsComposerItem* item )
{
QgsComposerMap* map = dynamic_cast<QgsComposerMap *>( item );
if ( !map || !map->isDrawing() ) //don't delete a composer map while it draws
{
removeItem( item );
QgsComposerItemGroup* itemGroup = dynamic_cast<QgsComposerItemGroup*>( item );
if ( itemGroup )
{
//add add/remove item command for every item in the group
QUndoCommand* parentCommand = new QUndoCommand( tr( "Remove item group" ) );

QSet<QgsComposerItem*> groupedItems = itemGroup->items();
QSet<QgsComposerItem*>::iterator it = groupedItems.begin();
for ( ; it != groupedItems.end(); ++it )
{
QgsAddRemoveItemCommand* subcommand = new QgsAddRemoveItemCommand( QgsAddRemoveItemCommand::Removed, *it, this, "", parentCommand );
connectAddRemoveCommandSignals( subcommand );
emit itemRemoved( *it );
}

undoStack()->push( parentCommand );
delete itemGroup;
emit itemRemoved( itemGroup );
}
else
{
emit itemRemoved( item );
pushAddRemoveCommand( item, tr( "Item deleted" ), QgsAddRemoveItemCommand::Removed );
}
}
}

void QgsComposition::pushAddRemoveCommand( QgsComposerItem* item, const QString& text, QgsAddRemoveItemCommand::State state )
{
QgsAddRemoveItemCommand* c = new QgsAddRemoveItemCommand( state, item, this, text );
connectAddRemoveCommandSignals( c );
undoStack()->push( c );
}

void QgsComposition::connectAddRemoveCommandSignals( QgsAddRemoveItemCommand* c )
{
if ( !c )
{
return;
}

QObject::connect( c, SIGNAL( itemRemoved( QgsComposerItem* ) ), this, SIGNAL( itemRemoved( QgsComposerItem* ) ) );
QObject::connect( c, SIGNAL( itemAdded( QgsComposerItem* ) ), this, SLOT( sendItemAddedSignal( QgsComposerItem* ) ) );
}

void QgsComposition::sendItemAddedSignal( QgsComposerItem* item )
{
//cast and send proper signal
item->setSelected( true );
QgsComposerArrow* arrow = dynamic_cast<QgsComposerArrow*>( item );
if ( arrow )
{
emit composerArrowAdded( arrow );
emit selectedItemChanged( arrow );
return;
}
QgsComposerLabel* label = dynamic_cast<QgsComposerLabel*>( item );
if ( label )
{
emit composerLabelAdded( label );
emit selectedItemChanged( label );
return;
}
QgsComposerMap* map = dynamic_cast<QgsComposerMap*>( item );
if ( map )
{
emit composerMapAdded( map );
emit selectedItemChanged( map );
return;
}
QgsComposerScaleBar* scalebar = dynamic_cast<QgsComposerScaleBar*>( item );
if ( scalebar )
{
emit composerScaleBarAdded( scalebar );
emit selectedItemChanged( scalebar );
return;
}
QgsComposerLegend* legend = dynamic_cast<QgsComposerLegend*>( item );
if ( legend )
{
emit composerLegendAdded( legend );
emit selectedItemChanged( legend );
return;
}
QgsComposerPicture* picture = dynamic_cast<QgsComposerPicture*>( item );
if ( picture )
{
emit composerPictureAdded( picture );
emit selectedItemChanged( picture );
return;
}
QgsComposerShape* shape = dynamic_cast<QgsComposerShape*>( item );
if ( shape )
{
emit composerShapeAdded( shape );
emit selectedItemChanged( shape );
return;
}
QgsComposerAttributeTable* table = dynamic_cast<QgsComposerAttributeTable*>( item );
if ( table )
{
emit composerTableAdded( table );
emit selectedItemChanged( table );
return;
}
}
67 changes: 66 additions & 1 deletion src/core/composer/qgscomposition.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,23 @@
#include <QUndoStack>

#include "qgscomposeritemcommand.h"
#include "qgsaddremoveitemcommand.h"

class QgsComposerItem;
class QgsComposerMap;
class QgsPaperItem;
class QGraphicsRectItem;
class QgsMapRenderer;

class QDomElement;
class QgsComposerArrow;
class QgsComposerItem;
class QgsComposerLabel;
class QgsComposerLegend;
class QgsComposerMap;
class QgsComposerPicture;
class QgsComposerScaleBar;
class QgsComposerShape;
class QgsComposerAttributeTable;

/** \ingroup MapComposer
* Graphics scene for map printing. The class manages the paper item which always
Expand Down Expand Up @@ -132,6 +141,13 @@ class CORE_EXPORT QgsComposition: public QGraphicsScene
/**Reads settings from xml file*/
bool readXML( const QDomElement& compositionElem, const QDomDocument& doc );

/**Add items from XML representation to the graphics scene (for project file reading, pasting items from clipboard)
@param elem items parent element, e.g. <Composer> or <ComposerItemClipboard>
@param doc xml document
@param addUndoCommands insert AddItem commands if true (e.g. for copy/paste)
@param pos item position. Optional, take position from xml if 0*/
void addItemsFromXML( const QDomElement& elem, const QDomDocument& doc, bool addUndoCommands = false, QPointF* pos = 0 );

/**Adds item to z list. Usually called from constructor of QgsComposerItem*/
void addItemToZList( QgsComposerItem* item );
/**Removes item from z list. Usually called from destructor of QgsComposerItem*/
Expand Down Expand Up @@ -173,6 +189,32 @@ class CORE_EXPORT QgsComposition: public QGraphicsScene
/**Deletes current command*/
void cancelCommand();

/**Adds an arrow item to the graphics scene and advices composer to create a widget for it (through signal)*/
void addComposerArrow( QgsComposerArrow* arrow );
/**Adds label to the graphics scene and advices composer to create a widget for it (through signal)*/
void addComposerLabel( QgsComposerLabel* label );
/**Adds map to the graphics scene and advices composer to create a widget for it (through signal)*/
void addComposerMap( QgsComposerMap* map );
/**Adds scale bar to the graphics scene and advices composer to create a widget for it (through signal)*/
void addComposerScaleBar( QgsComposerScaleBar* scaleBar );
/**Adds legend to the graphics scene and advices composer to create a widget for it (through signal)*/
void addComposerLegend( QgsComposerLegend* legend );
/**Adds picture to the graphics scene and advices composer to create a widget for it (through signal)*/
void addComposerPicture( QgsComposerPicture* picture );
/**Adds a composer shape to the graphics scene and advices composer to create a widget for it (through signal)*/
void addComposerShape( QgsComposerShape* shape );
/**Adds a composer table to the graphics scene and advices composer to create a widget for it (through signal)*/
void addComposerTable( QgsComposerAttributeTable* table );

/**Remove item from the graphics scene. Additionally to QGraphicsScene::removeItem, this function considers undo/redo command*/
void removeComposerItem( QgsComposerItem* item );

/**Convenience function to create a QgsAddRemoveItemCommand, connect its signals and push it to the undo stack*/
void pushAddRemoveCommand( QgsComposerItem* item, const QString& text, QgsAddRemoveItemCommand::State state = QgsAddRemoveItemCommand::Added );

public slots:
/**Casts object to the proper subclass type and calls corresponding itemAdded signal*/
void sendItemAddedSignal( QgsComposerItem* item );

private:
/**Pointer to map renderer of QGIS main map*/
Expand Down Expand Up @@ -216,8 +258,31 @@ class CORE_EXPORT QgsComposition: public QGraphicsScene
void loadSettings();
void saveSettings();

void connectAddRemoveCommandSignals( QgsAddRemoveItemCommand* c );

signals:
void paperSizeChanged();

/**Is emitted when selected item changed. If 0, no item is selected*/
void selectedItemChanged( QgsComposerItem* selected );
/**Is emitted when new composer arrow has been added to the view*/
void composerArrowAdded( QgsComposerArrow* arrow );
/**Is emitted when new composer label has been added to the view*/
void composerLabelAdded( QgsComposerLabel* label );
/**Is emitted when new composer map has been added to the view*/
void composerMapAdded( QgsComposerMap* map );
/**Is emitted when new composer scale bar has been added*/
void composerScaleBarAdded( QgsComposerScaleBar* scalebar );
/**Is emitted when a new composer legend has been added*/
void composerLegendAdded( QgsComposerLegend* legend );
/**Is emitted when a new composer picture has been added*/
void composerPictureAdded( QgsComposerPicture* picture );
/**Is emitted when a new composer shape has been added*/
void composerShapeAdded( QgsComposerShape* shape );
/**Is emitted when a new composer table has been added*/
void composerTableAdded( QgsComposerAttributeTable* table );
/**Is emitted when a composer item has been removed from the scene*/
void itemRemoved( QgsComposerItem* );
};

#endif
Expand Down
466 changes: 94 additions & 372 deletions src/gui/qgscomposerview.cpp

Large diffs are not rendered by default.

50 changes: 1 addition & 49 deletions src/gui/qgscomposerview.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,38 +80,12 @@ class GUI_EXPORT QgsComposerView: public QGraphicsView
/**Returns the composition or 0 in case of error*/
QgsComposition* composition();

/**Adds an arrow item to the graphics scene and advices composer to create a widget for it (through signal)*/
void addComposerArrow( QgsComposerArrow* arrow );
/**Adds label to the graphics scene and advices composer to create a widget for it (through signal)*/
void addComposerLabel( QgsComposerLabel* label );
/**Adds map to the graphics scene and advices composer to create a widget for it (through signal)*/
void addComposerMap( QgsComposerMap* map );
/**Adds scale bar to the graphics scene and advices composer to create a widget for it (through signal)*/
void addComposerScaleBar( QgsComposerScaleBar* scaleBar );
/**Adds legend to the graphics scene and advices composer to create a widget for it (through signal)*/
void addComposerLegend( QgsComposerLegend* legend );
/**Adds picture to the graphics scene and advices composer to create a widget for it (through signal)*/
void addComposerPicture( QgsComposerPicture* picture );
/**Adds a composer shape to the graphics scene and advices composer to create a widget for it (through signal)*/
void addComposerShape( QgsComposerShape* shape );
/**Adds a composer table to the graphics scene and advices composer to create a widget for it (through signal)*/
void addComposerTable( QgsComposerAttributeTable* table );

/**Remove item from the graphics scene*/
void removeItem( QgsComposerItem* item );

/**Add items from XML representation to the graphics scene (for pasting items from clipboard)*/
void addItemsfromXML( const QDomElement& docElem, const QDomDocument& doc );

/**Returns the composer main window*/
QMainWindow* composerWindow();

void setPaintingEnabled( bool enabled ) { mPaintingEnabled = enabled; }
bool paintingEnabled() const { return mPaintingEnabled; }

/**Convenience function to create a QgsAddRemoveItemCommand, connect its signals and push it to the undo stack*/
void pushAddRemoveCommand( QgsComposerItem* item, const QString& text, QgsAddRemoveItemCommand::State state = QgsAddRemoveItemCommand::Added );

protected:
void mousePressEvent( QMouseEvent* );
void mouseReleaseEvent( QMouseEvent* );
Expand Down Expand Up @@ -146,33 +120,11 @@ class GUI_EXPORT QgsComposerView: public QGraphicsView

bool mPaintingEnabled;

void connectAddRemoveCommandSignals( QgsAddRemoveItemCommand* c );


public slots:
/**Casts object to the proper subclass type and calls corresponding itemAdded signal*/
void sendItemAddedSignal( QgsComposerItem* item );
//void connectAddRemoveCommandSignals( QgsAddRemoveItemCommand* c );

signals:
/**Is emitted when selected item changed. If 0, no item is selected*/
void selectedItemChanged( QgsComposerItem* selected );
/**Is emitted when new composer arrow has been added to the view*/
void composerArrowAdded( QgsComposerArrow* arrow );
/**Is emitted when new composer label has been added to the view*/
void composerLabelAdded( QgsComposerLabel* label );
/**Is emitted when new composer map has been added to the view*/
void composerMapAdded( QgsComposerMap* map );
/**Is emitted when new composer scale bar has been added*/
void composerScaleBarAdded( QgsComposerScaleBar* scalebar );
/**Is emitted when a new composer legend has been added*/
void composerLegendAdded( QgsComposerLegend* legend );
/**Is emitted when a new composer picture has been added*/
void composerPictureAdded( QgsComposerPicture* picture );
/**Is emitted when a new composer shape has been added*/
void composerShapeAdded( QgsComposerShape* shape );
/**Is emitted when a new composer table has been added*/
void composerTableAdded( QgsComposerAttributeTable* table );
/**Is emitted when a composer item has been removed from the scene*/
void itemRemoved( QgsComposerItem* );
/**Current action (e.g. adding composer map) has been finished. The purpose of this signal is that
QgsComposer may set the selection tool again*/
Expand Down