diff --git a/src/gui/qgscomposerview.cpp b/src/gui/qgscomposerview.cpp
index 05935cd..5202bdb 100644
--- a/src/gui/qgscomposerview.cpp
+++ b/src/gui/qgscomposerview.cpp
@@ -18,6 +18,9 @@
 #include <QMainWindow>
 #include <QMouseEvent>
 #include <QKeyEvent>
+#include <QClipboard>
+#include <QMimeData>
+#include <QCursor>
 
 #include "qgscomposerview.h"
 #include "qgscomposerarrow.h"
@@ -30,6 +33,7 @@
 #include "qgscomposershape.h"
 #include "qgscomposerattributetable.h"
 #include "qgslogger.h"
+#include "qgsapplication.h"
 
 QgsComposerView::QgsComposerView( QWidget* parent, const char* name, Qt::WFlags f )
     : QGraphicsView( parent )
@@ -394,40 +398,57 @@ void QgsComposerView::keyPressEvent( QKeyEvent * e )
   QList<QgsComposerItem*> composerItemList = composition()->selectedComposerItems();
   QList<QgsComposerItem*>::iterator itemIt = composerItemList.begin();
 
-  //delete selected items
-  if ( e->key() == Qt::Key_Delete || e->key() == Qt::Key_Backspace )
+  if ( e->matches( QKeySequence::Copy ) || e->matches( QKeySequence::Cut ) )
   {
+    QDomDocument doc;
+    QDomElement documentElement = doc.createElement( "ComposerCopyItem" );//?
     for ( ; itemIt != composerItemList.end(); ++itemIt )
     {
-      QgsComposerMap* map = dynamic_cast<QgsComposerMap *>( *itemIt );
-      if ( !map || !map->isDrawing() ) //don't delete a composer map while it draws
+      // copy each item in a group
+      QgsComposerItemGroup* itemGroup = dynamic_cast<QgsComposerItemGroup*>( *itemIt );
+      if ( itemGroup && composition() )
       {
-        composition()->removeItem( *itemIt );
-        QgsComposerItemGroup* itemGroup = dynamic_cast<QgsComposerItemGroup*>( *itemIt );
-        if ( itemGroup && composition() )
-        {
-          //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, composition(), "", parentCommand );
-            connectAddRemoveCommandSignals( subcommand );
-            emit itemRemoved( *it );
-          }
-
-          composition()->undoStack()->push( parentCommand );
-          delete itemGroup;
-          emit itemRemoved( itemGroup );
-        }
-        else
+        QSet<QgsComposerItem*> groupedItems = itemGroup->items();
+        QSet<QgsComposerItem*>::iterator it = groupedItems.begin();
+        for ( ; it != groupedItems.end(); ++it )
         {
-          emit itemRemoved( *itemIt );
-          pushAddRemoveCommand( *itemIt, tr( "Item deleted" ), QgsAddRemoveItemCommand::Removed );
+          ( *it )->writeXML( documentElement, doc );
         }
       }
+      ( *itemIt )->writeXML( documentElement, doc );
+
+      if ( e->matches( QKeySequence::Cut ) )
+      {
+        removeItem( *itemIt );
+      }
+    }
+
+    doc.appendChild( documentElement );
+    QMimeData *mimeData = new QMimeData;
+    mimeData->setData( "text/xml", doc.toByteArray() );
+    QClipboard *clipboard = QApplication::clipboard();
+    clipboard->setMimeData( mimeData );
+  }
+
+  if ( e->matches( QKeySequence::Paste ) )
+  {
+    QDomDocument doc;
+    QClipboard *clipboard = QApplication::clipboard();
+    if ( doc.setContent( clipboard->mimeData()->data("text/xml") ) )
+    {
+      QDomElement docElem = doc.documentElement();
+      if (docElem.tagName() == "ComposerCopyItem")
+      {
+        addItemsfromXML( docElem, doc );
+      }
+    }
+  }
+  //delete selected items
+  if ( e->key() == Qt::Key_Delete || e->key() == Qt::Key_Backspace )
+  {
+    for ( ; itemIt != composerItemList.end(); ++itemIt )
+    {
+      removeItem(*itemIt);
     }
   }
 
@@ -673,6 +694,39 @@ void QgsComposerView::ungroupItems()
   }
 }
 
+void QgsComposerView::removeItem( QgsComposerItem* item )
+{
+    QgsComposerMap* map = dynamic_cast<QgsComposerMap *>( item );
+    if ( !map || !map->isDrawing() ) //don't delete a composer map while it draws
+    {
+      composition()->removeItem( item );
+      QgsComposerItemGroup* itemGroup = dynamic_cast<QgsComposerItemGroup*>( item );
+      if ( itemGroup && composition() )
+      {
+        //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, composition(), "", parentCommand );
+          connectAddRemoveCommandSignals( subcommand );
+          emit itemRemoved( *it );
+        }
+
+        composition()->undoStack()->push( parentCommand );
+        delete itemGroup;
+        emit itemRemoved( itemGroup );
+      }
+      else
+      {
+        emit itemRemoved( item );
+        pushAddRemoveCommand( item, tr( "Item deleted" ), QgsAddRemoveItemCommand::Removed );
+      }
+    }
+}
+
 void QgsComposerView::sendItemAddedSignal( QgsComposerItem* item )
 {
   //cast and send proper signal
@@ -778,3 +832,98 @@ void QgsComposerView::pushAddRemoveCommand( QgsComposerItem* item, const QString
   connectAddRemoveCommandSignals( c );
   composition()->undoStack()->push( c );
 }
+
+void QgsComposerView::addItemsfromXML( const QDomElement& docElem, const QDomDocument& doc)
+{
+  QPointF scenePoint = mapToScene( mapFromGlobal(QCursor::pos()) );
+
+  // label
+  QDomNodeList composerLabelList = docElem.elementsByTagName( "ComposerLabel" );
+  for ( int i = 0; i < composerLabelList.size(); ++i )
+  {
+    QDomElement currentComposerLabelElem = composerLabelList.at( i ).toElement();
+    QgsComposerLabel* newLabel = new QgsComposerLabel( composition() );
+    newLabel->readXML( currentComposerLabelElem, doc );
+    newLabel->setItemPosition( scenePoint.x(), scenePoint.y() );
+    addComposerLabel( newLabel );
+    emit actionFinished();
+  }
+  // arrow
+  QDomNodeList composerArrowList = docElem.elementsByTagName( "ComposerArrow" );
+  for ( int i = 0; i < composerArrowList.size(); ++i )
+  {
+    QDomElement currentComposerArrowElem = composerArrowList.at( i ).toElement();
+    QgsComposerArrow* newArrow = new QgsComposerArrow( composition() );
+    newArrow->readXML( currentComposerArrowElem, doc );
+    newArrow->setItemPosition( scenePoint.x(), scenePoint.y() );
+    addComposerArrow( newArrow );
+    emit actionFinished();
+  }
+  // scalebar
+  QDomNodeList composerScaleBarList = docElem.elementsByTagName( "ComposerScaleBar" );
+  for ( int i = 0; i < composerScaleBarList.size(); ++i )
+  {
+    QDomElement currentComposerScaleBarElem = composerScaleBarList.at( i ).toElement();
+    QgsComposerScaleBar* newScaleBar = new QgsComposerScaleBar( composition() );
+    newScaleBar->readXML( currentComposerScaleBarElem, doc );
+    newScaleBar->setItemPosition( scenePoint.x(), scenePoint.y() );
+    addComposerScaleBar( newScaleBar );
+    emit actionFinished();
+  }
+  // shape
+  QDomNodeList composerShapeList = docElem.elementsByTagName( "ComposerShape" );
+  for ( int i = 0; i < composerShapeList.size(); ++i )
+  {
+    QDomElement currentComposerShapeElem = composerShapeList.at( i ).toElement();
+    QgsComposerShape* newShape = new QgsComposerShape( composition() );
+    newShape->readXML( currentComposerShapeElem, doc );
+    newShape->setItemPosition( scenePoint.x(), scenePoint.y() );
+    addComposerShape( newShape );
+    emit actionFinished();
+  }
+  // picture
+  QDomNodeList composerPictureList = docElem.elementsByTagName( "ComposerPicture" );
+  for ( int i = 0; i < composerPictureList.size(); ++i )
+  {
+    QDomElement currentComposerPictureElem = composerPictureList.at( i ).toElement();
+    QgsComposerPicture* newPicture = new QgsComposerPicture( composition() );
+    newPicture->readXML( currentComposerPictureElem, doc );
+    newPicture->setItemPosition( scenePoint.x(), scenePoint.y() );
+    addComposerPicture( newPicture );
+    emit actionFinished();
+  }
+  // legend
+  QDomNodeList composerLegendList = docElem.elementsByTagName( "ComposerLegend" );
+  for ( int i = 0; i < composerLegendList.size(); ++i )
+  {
+    QDomElement currentComposerLegendElem = composerLegendList.at( i ).toElement();
+    QgsComposerLegend* newLegend = new QgsComposerLegend( composition() );
+    newLegend->readXML( currentComposerLegendElem, doc );
+    newLegend->setItemPosition( scenePoint.x(), scenePoint.y() );
+    addComposerLegend( newLegend );
+    emit actionFinished();
+  }
+  // table
+  QDomNodeList composerTableList = docElem.elementsByTagName( "ComposerAttributeTable" );
+  for ( int i = 0; i < composerTableList.size(); ++i )
+  {
+    QDomElement currentComposerTableElem = composerTableList.at( i ).toElement();
+    QgsComposerAttributeTable* newTable = new QgsComposerAttributeTable( composition() );
+    newTable->readXML( currentComposerTableElem, doc );
+    newTable->setItemPosition( scenePoint.x(), scenePoint.y() );
+    addComposerTable( newTable );
+    emit actionFinished();
+  }
+  // table
+  QDomNodeList composerMapList = docElem.elementsByTagName( "ComposerMap" );
+  for ( int i = 0; i < composerMapList.size(); ++i )
+  {
+    QDomElement currentComposerMapElem = composerMapList.at( i ).toElement();
+    QgsComposerMap* newMap = new QgsComposerMap( composition() );
+    newMap->readXML( currentComposerMapElem, doc );
+    newMap->setItemPosition( scenePoint.x(), scenePoint.y() );
+    addComposerMap( newMap );
+    emit actionFinished();
+  }
+}
diff --git a/src/gui/qgscomposerview.h b/src/gui/qgscomposerview.h
index 80fad57..ab57cab 100644
--- a/src/gui/qgscomposerview.h
+++ b/src/gui/qgscomposerview.h
@@ -18,6 +18,8 @@
 #define QGSCOMPOSERVIEW_H
 
 #include <QGraphicsView>
+#include <QDomDocument>
+#include <QDomElement>
 #include "qgsaddremoveitemcommand.h"
 
 class QKeyEvent;
@@ -95,6 +97,9 @@ class GUI_EXPORT QgsComposerView: public QGraphicsView
     /**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 );
+
     /**Returns the composer main window*/
     QMainWindow* composerWindow();
 
@@ -104,6 +109,9 @@ class GUI_EXPORT QgsComposerView: public QGraphicsView
     /**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 );
 
+    /**Add items from XML representation to the graphics scene (for pasting items from clipboard)*/
+    void addItemsfromXML( const QDomElement& docElem, const QDomDocument& doc );
+
   protected:
     void mousePressEvent( QMouseEvent* );
     void mouseReleaseEvent( QMouseEvent* );
