Commit 13d7247c authored by Thorsten Zachmann's avatar Thorsten Zachmann

Implemented intelligent paste of pages.

o When copying a page and the master page of that page already exists the
  master page is not created, instead the existing master page is used.
o When copying a page and the master page of that page does not
  yet exists the master page of that page is also created.
o When copying a master page a copy of the page is always
  created.


svn path=/trunk/koffice/; revision=736889
parent e0355fd1
......@@ -180,7 +180,8 @@ QList<KoPAPageBase *> KoPADocument::loadOdfPages( const KoXmlElement & body, KoP
bool KoPADocument::saveOasisPages( KoPASavingContext &paContext, QList<KoPAPageBase *> &pages, QList<KoPAPageBase *> &masterPages )
{
paContext.setOptions( KoPASavingContext::DrawId | KoPASavingContext::AutoStyleInStyleXml );
paContext.addOption( KoPASavingContext::DrawId );
paContext.addOption( KoPASavingContext::AutoStyleInStyleXml );
// save master pages
foreach( KoPAPageBase *page, masterPages ) {
......@@ -191,7 +192,7 @@ bool KoPADocument::saveOasisPages( KoPASavingContext &paContext, QList<KoPAPageB
bodyWriter.startElement( "office:body" );
bodyWriter.startElement( odfTagName( true ) );
paContext.setOptions( KoPASavingContext::DrawId );
paContext.removeOption( KoPASavingContext::AutoStyleInStyleXml );
// save pages
foreach ( KoPAPageBase *page, pages ) {
......
......@@ -20,14 +20,9 @@
#include "KoPAPastePage.h"
#include <QBuffer>
#include <QByteArray>
#include <QMimeData>
#include <QString>
#include <KoStore.h>
#include <KoOdfReadStore.h>
#include <KoXmlReader.h>
#include <KoDom.h>
#include <KoXmlNS.h>
#include <KoXmlWriter.h>
#include <KoOasisLoadingContext.h>
#include <KoOasisStyles.h>
#include "KoPALoadingContext.h"
......@@ -53,7 +48,7 @@ bool KoPAPastePage::process( const KoXmlElement & body, KoOdfReadStore & odfStor
KoPAPageBase * insertAfterPage = 0;
KoPAPageBase * insertAfterMasterPage = 0;
if ( dynamic_cast<KoPAMasterPage *>( m_activePage ) ) {
if ( dynamic_cast<KoPAMasterPage *>( m_activePage ) || m_activePage == 0 && pages.empty() ) {
insertAfterMasterPage = m_activePage;
insertAfterPage = m_doc->pages( false ).last();
}
......@@ -62,6 +57,72 @@ bool KoPAPastePage::process( const KoXmlElement & body, KoOdfReadStore & odfStor
insertAfterMasterPage = m_doc->pages( true ).last();
}
if ( ! pages.empty() ) {
KoGenStyles mainStyles;
QBuffer buffer;
buffer.open( QIODevice::WriteOnly );
KoXmlWriter xmlWriter( &buffer );
KoPASavingContext savingContext( xmlWriter, mainStyles, 1, KoShapeSavingContext::Store );
savingContext.addOption( KoShapeSavingContext::UniqueMasterPages );
QList<KoPAPageBase*> emptyList;
QList<KoPAPageBase*> existingMasterPages = m_doc->pages( true );
m_doc->saveOasisPages( savingContext, emptyList, existingMasterPages );
QMap<QString, KoPAMasterPage*> masterPageNames;
foreach ( KoPAPageBase * page, existingMasterPages )
{
KoPAMasterPage * masterPage = dynamic_cast<KoPAMasterPage*>( page );
Q_ASSERT( masterPage );
if ( masterPage ) {
QString masterPageName( savingContext.masterPageName( masterPage ) );
if ( !masterPageNames.contains( masterPageName ) ) {
masterPageNames.insert( masterPageName, masterPage );
}
}
}
m_doc->saveOasisPages( savingContext, emptyList, masterPages );
QMap<KoPAMasterPage*, KoPAMasterPage*> updateMasterPage;
foreach ( KoPAPageBase * page, masterPages )
{
KoPAMasterPage * masterPage = dynamic_cast<KoPAMasterPage*>( page );
Q_ASSERT( masterPage );
if ( masterPage ) {
QString masterPageName( savingContext.masterPageName( masterPage ) );
QMap<QString, KoPAMasterPage*>::const_iterator existingMasterPage( masterPageNames.find( masterPageName ) );
if ( existingMasterPage != masterPageNames.end() ) {
updateMasterPage.insert( masterPage, existingMasterPage.value() );
}
}
}
// update pages which have a duplicate master page
foreach ( KoPAPageBase * page, pages )
{
KoPAPage * p = dynamic_cast<KoPAPage*>( page );
Q_ASSERT( p );
if ( p ) {
KoPAMasterPage * masterPage( p->masterPage() );
QMap<KoPAMasterPage*, KoPAMasterPage*>::const_iterator pageIt( updateMasterPage.find( masterPage ) );
if ( pageIt != updateMasterPage.end() ) {
p->setMasterPage( pageIt.value() );
}
}
}
// delete dumplicate master pages;
QMap<KoPAMasterPage*, KoPAMasterPage*>::const_iterator pageIt( updateMasterPage.begin() );
for ( ; pageIt != updateMasterPage.end(); ++pageIt )
{
masterPages.removeAll( pageIt.key() );
delete pageIt.key();
}
}
// TODO use plural if it is more then one page
QUndoCommand * cmd = new QUndoCommand( i18n( "Paste Page" ) );
foreach( KoPAPageBase * masterPage, masterPages )
......
......@@ -22,13 +22,29 @@
#include "KoOdfPaste.h"
#include "kopageapp_export.h"
class KoPADocument;
class KoPAPageBase;
class KoPAPastePage : public KoOdfPaste
class KOPAGEAPP_TEST_EXPORT KoPAPastePage : public KoOdfPaste
{
public:
KoPAPastePage( KoPADocument * doc, KoPAPageBase * m_activePage );
/**
* Paste pages
*
* This uses intelligent paste of pages.
* o When copying a page and the master page of that page already exists the
* master page is not created, instead the existing master page is used.
* o When copying a page and the master page of that page does not yet exists
* the master page of that page is also created.
* o When copying a master page a copy of the page is always created.
*
* @param doc The document in which the pages are pasted.
* @param activePage The page after which the pages are pasted. If 0 at the
* pages are inserted at the beginning.
*/
KoPAPastePage( KoPADocument * doc, KoPAPageBase * activePage );
protected:
bool process( const KoXmlElement & body, KoOdfReadStore & odfStore );
......
......@@ -13,7 +13,6 @@ target_link_libraries(TestPAPageInsertCommand ${KDE4_KDECORE_LIBS} kopageapp ${
set(TestPAPageDeleteCommand_test_SRCS TestPAPageDeleteCommand.cpp )
kde4_add_unit_test(TestPAPageDeleteCommand TESTNAME libs-kopageapp-TestPAPageDeleteCommand ${TestPAPageDeleteCommand_test_SRCS})
target_link_libraries(TestPAPageDeleteCommand ${KDE4_KDECORE_LIBS} kopageapp ${QT_QTTEST_LIBRARY})
......@@ -22,9 +21,16 @@ target_link_libraries(TestPAPageDeleteCommand ${KDE4_KDECORE_LIBS} kopageapp ${
set(TestPAPageMoveCommand_test_SRCS TestPAPageMoveCommand.cpp )
kde4_add_unit_test(TestPAPageMoveCommand TESTNAME libs-kopageapp-TestPAPageMoveCommand ${TestPAPageMoveCommand_test_SRCS})
target_link_libraries(TestPAPageMoveCommand ${KDE4_KDECORE_LIBS} kopageapp ${QT_QTTEST_LIBRARY})
########### next target ###############
set(TestPACopyPastePage_test_SRCS TestPACopyPastePage.cpp )
kde4_add_unit_test(TestPACopyPastePage TESTNAME libs-kopageapp-TestPACopyPastePage ${TestPACopyPastePage_test_SRCS})
target_link_libraries(TestPACopyPastePage ${KDE4_KDECORE_LIBS} kopageapp ${QT_QTTEST_LIBRARY})
########### next target ###############
......@@ -33,7 +33,7 @@ public:
: KoPADocument( 0, 0 )
{}
KoView *createViewInstance( QWidget * /* parent */ ) { return 0; }
const char *odfTagName( bool ) { return ""; }
const char *odfTagName( bool b ) { return KoOdf::bodyContentElement( KoOdf::Presentation, b ); }
virtual KoOdf::DocumentType documentType() const { return KoOdf::Presentation; }
};
......
/* This file is part of the KDE project
* Copyright ( C ) 2007 Thorsten Zachmann <zachmann@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or ( at your option ) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "TestPACopyPastePage.h"
#include "PAMock.h"
#include "KoPAPage.h"
#include "KoPAPastePage.h"
#include "KoPAMasterPage.h"
#include "KoPAOdfPageSaveHelper.h"
#include <QClipboard>
#include <KoShapeLayer.h>
#include <KoPathShape.h>
#include <KoDrag.h>
#include <KoOdf.h>
#include <qtest_kde.h>
#include <kdebug.h>
void TestPACopyPastePage::copyAndPaste( MockDocument * doc, QList<KoPAPageBase *> & pages, KoPAPageBase * after )
{
paste( doc, copy( doc, pages ), after );
}
QMimeData * TestPACopyPastePage::copy( MockDocument * doc, QList<KoPAPageBase *> & pages )
{
KoPAOdfPageSaveHelper saveHelper( doc, pages );
KoDrag drag;
drag.setOdf( KoOdf::mimeType( doc->documentType() ), saveHelper );
return drag.mimeData();
}
void TestPACopyPastePage::paste( MockDocument * doc, QMimeData * data, KoPAPageBase * after )
{
if ( data->hasFormat( KoOdf::mimeType( doc->documentType() ) ) ) {
KoPAPastePage paste( doc, after );
paste.paste( doc->documentType(), data );
}
delete data;
}
void TestPACopyPastePage::addShape( KoPAPageBase * page )
{
KoPathShape * path = new KoPathShape();
path->lineTo( QPointF( 10, 0 ) );
path->lineTo( QPointF( 10, 10 ) );
path->setPosition( m_pos );
m_pos += QPointF( 1.0, 1.0 );
QList<KoShape*> shapes = page->iterator();
if ( !shapes.isEmpty() ) {
KoShapeLayer* layer = dynamic_cast<KoShapeLayer*>( shapes.last() );
layer->addChild( path );
}
}
void TestPACopyPastePage::copyPasteSinglePage()
{
MockDocument doc;
KoPAMasterPage * master1 = new KoPAMasterPage();
doc.insertPage( master1, 0 );
KoPAPage * page1 = new KoPAPage( master1 );
doc.insertPage( page1, 0 );
addShape( page1 );
QList<KoPAPageBase *> pages;
pages.append( page1 );
copyAndPaste( &doc, pages, page1 );
QVERIFY( doc.pages( true ).size() == 1 );
QVERIFY( doc.pages( false ).size() == 2 );
QVERIFY( doc.pages( false ).front() == page1 );
KoPAPageBase * page2 = doc.pages( false ).last();
QVERIFY( dynamic_cast<KoPAPage*>( page2 )->masterPage() == master1 );
copyAndPaste( &doc, pages, page1 );
QVERIFY( doc.pages( true ).size() == 1 );
QVERIFY( doc.pages( false ).size() == 3 );
QVERIFY( doc.pages( false )[0] == page1 );
QVERIFY( doc.pages( false )[2] == page2 );
KoPAPageBase * page3 = doc.pages( false )[1];
QVERIFY( dynamic_cast<KoPAPage*>( page3 )->masterPage() == master1 );
QVERIFY( page1 != page2 );
QVERIFY( page1 != page3 );
QVERIFY( page2 != page3 );
copyAndPaste( &doc, pages, 0 );
QVERIFY( doc.pages( true ).size() == 1 );
QVERIFY( doc.pages( false ).size() == 4 );
QVERIFY( doc.pages( false )[1] == page1 );
QVERIFY( doc.pages( false )[2] == page3 );
QVERIFY( doc.pages( false )[3] == page2 );
QMimeData * data = copy( &doc, pages );
addShape( master1 );
paste( &doc, data, page1 );
QVERIFY( doc.pages( true ).size() == 2 );
QVERIFY( doc.pages( true )[0] == master1 );
QVERIFY( doc.pages( false ).size() == 5 );
QVERIFY( doc.pages( false )[1] == page1 );
QVERIFY( doc.pages( false )[3] == page3 );
QVERIFY( doc.pages( false )[4] == page2 );
}
void TestPACopyPastePage::copyPasteSingleMasterPage()
{
MockDocument doc;
KoPAMasterPage * master1 = new KoPAMasterPage();
doc.insertPage( master1, 0 );
KoPAPage * page1 = new KoPAPage( master1 );
doc.insertPage( page1, 0 );
addShape( master1 );
QList<KoPAPageBase *> pages;
pages.append( master1 );
copyAndPaste( &doc, pages, master1 );
QVERIFY( doc.pages( false ).size() == 1 );
QVERIFY( doc.pages( true ).size() == 2 );
QVERIFY( doc.pages( true ).front() == master1 );
KoPAPageBase * master2 = doc.pages( true )[1];
copyAndPaste( &doc, pages, master1 );
QVERIFY( doc.pages( false ).size() == 1 );
QVERIFY( doc.pages( true ).size() == 3 );
QVERIFY( doc.pages( true )[0] == master1 );
QVERIFY( doc.pages( true )[2] == master2 );
KoPAPageBase * master3 = doc.pages( true )[1];
QVERIFY( master1 != master2 );
QVERIFY( master1 != master3 );
QVERIFY( master2 != master3 );
copyAndPaste( &doc, pages, 0 );
QVERIFY( doc.pages( false ).size() == 1 );
QVERIFY( doc.pages( true ).size() == 4 );
QVERIFY( doc.pages( true )[1] == master1 );
QVERIFY( doc.pages( true )[2] == master3 );
QVERIFY( doc.pages( true )[3] == master2 );
}
void TestPACopyPastePage::copyPasteMuliplePages()
{
MockDocument doc;
KoPAMasterPage * master1 = new KoPAMasterPage();
doc.insertPage( master1, 0 );
addShape( master1 );
KoPAMasterPage * master2 = new KoPAMasterPage();
doc.insertPage( master2, master1 );
addShape( master2 );
KoPAPage * page1 = new KoPAPage( master1 );
doc.insertPage( page1, 0 );
KoPAPage * page2 = new KoPAPage( master2 );
doc.insertPage( page2, page1 );
KoPAPage * page3 = new KoPAPage( master1 );
doc.insertPage( page3, page2 );
QList<KoPAPageBase *> pages;
pages.append( page1 );
pages.append( page2 );
copyAndPaste( &doc, pages, page2 );
QVERIFY( doc.pages( true ).size() == 2 );
QVERIFY( doc.pages( false ).size() == 5 );
QVERIFY( doc.pages( false )[0] == page1 );
QVERIFY( doc.pages( false )[1] == page2 );
QVERIFY( doc.pages( false )[4] == page3 );
KoPAPage * page4 = dynamic_cast<KoPAPage *>( doc.pages( false )[2] );
KoPAPage * page5 = dynamic_cast<KoPAPage *>( doc.pages( false )[3] );
QVERIFY( page4 != 0 );
QVERIFY( page4->masterPage() == master1 );
QVERIFY( page5 != 0 );
QVERIFY( page5->masterPage() == master2 );
QList<KoPAPageBase *> masterPages;
masterPages.append( master1 );
copyAndPaste( &doc, masterPages, master2 );
QVERIFY( doc.pages( true ).size() == 3 );
QVERIFY( doc.pages( true )[0] == master1 );
QVERIFY( doc.pages( true )[1] == master2 );
KoPAMasterPage * master3 = dynamic_cast<KoPAMasterPage *>( doc.pages( true )[2] );
QVERIFY( master3 != 0 );
KoPAPage * page6 = new KoPAPage( master3 );
doc.insertPage( page6, page3 );
pages.append( page6 );
QMimeData * data = copy( &doc, pages );
addShape( master2 );
paste( &doc, data, page6 );
QVERIFY( doc.pages( true ).size() == 4 );
QVERIFY( doc.pages( false ).size() == 9 );
QVERIFY( doc.pages( false )[0] == page1 );
QVERIFY( doc.pages( false )[1] == page2 );
QVERIFY( doc.pages( false )[2] == page4 );
QVERIFY( doc.pages( false )[3] == page5 );
QVERIFY( doc.pages( false )[4] == page3 );
QVERIFY( doc.pages( false )[5] == page6 );
KoPAPage * page7 = dynamic_cast<KoPAPage *>( doc.pages( false )[6] );
KoPAPage * page8 = dynamic_cast<KoPAPage *>( doc.pages( false )[7] );
KoPAPage * page9 = dynamic_cast<KoPAPage *>( doc.pages( false )[8] );
KoPAMasterPage * master4 = dynamic_cast<KoPAMasterPage *>( doc.pages( true )[3] );
QVERIFY( master4 != 0 );
QVERIFY( page7 != 0 );
QVERIFY( page7->masterPage() == master1 );
QVERIFY( page8 != 0 );
QVERIFY( page8->masterPage() == master4 );
QVERIFY( page9 != 0 );
QVERIFY( page9->masterPage() == master1 );
}
void TestPACopyPastePage::copyPasteMulipleMasterPages()
{
MockDocument doc;
KoPAMasterPage * master1 = new KoPAMasterPage();
doc.insertPage( master1, 0 );
KoPAPage * page1 = new KoPAPage( master1 );
doc.insertPage( page1, 0 );
KoPAMasterPage * master2 = new KoPAMasterPage();
doc.insertPage( master2, master1 );
QList<KoPAPageBase *> pages;
pages.append( master1 );
pages.append( master2 );
copyAndPaste( &doc, pages, master2 );
QVERIFY( doc.pages( false ).size() == 1 );
QVERIFY( doc.pages( true ).size() == 4 );
QVERIFY( doc.pages( true )[0] == master1 );
QVERIFY( doc.pages( true )[1] == master2 );
KoPAMasterPage * master3 = dynamic_cast<KoPAMasterPage *>( doc.pages( true )[2] );
QVERIFY( master3 != 0 );
KoPAMasterPage * master4 = dynamic_cast<KoPAMasterPage *>( doc.pages( true )[3] );
QVERIFY( master4 != 0 );
}
void TestPACopyPastePage::copyPasteMixedPages()
{
MockDocument doc;
KoPAMasterPage * master1 = new KoPAMasterPage();
doc.insertPage( master1, 0 );
KoPAPage * page1 = new KoPAPage( master1 );
doc.insertPage( page1, 0 );
KoPAMasterPage * master2 = new KoPAMasterPage();
doc.insertPage( master2, master1 );
QList<KoPAPageBase *> pages;
pages.append( page1 );
pages.append( master2 );
QMimeData * data = copy( &doc, pages );
addShape( master2 );
paste( &doc, data, page1 );
QVERIFY( doc.pages( false ).size() == 2 );
QVERIFY( doc.pages( true ).size() == 2 );
QVERIFY( doc.pages( true )[0] == master1 );
QVERIFY( doc.pages( true )[1] == master2 );
}
QTEST_KDEMAIN( TestPACopyPastePage, GUI )
#include "TestPACopyPastePage.moc"
/* This file is part of the KDE project
* Copyright ( C ) 2007 Thorsten Zachmann <zachmann@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or ( at your option ) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef TESTPACOPYPASTEPAGE_H
#define TESTPACOPYPASTEPAGE_H
#include <QtTest/QtTest>
class QMimeData;
class MockDocument;
class KoPAPageBase;
class TestPACopyPastePage : public QObject
{
Q_OBJECT
private:
void copyAndPaste( MockDocument * doc, QList<KoPAPageBase *> & pages, KoPAPageBase * after );
QMimeData * copy( MockDocument * doc, QList<KoPAPageBase *> & pages );
void paste( MockDocument * doc, QMimeData * data, KoPAPageBase * after );
void addShape( KoPAPageBase * page );
QPointF m_pos;
private slots:
void copyPasteSinglePage();
void copyPasteSingleMasterPage();
void copyPasteMuliplePages();
void copyPasteMulipleMasterPages();
void copyPasteMixedPages();
};
#endif /* TESTPACOPYPASTEPAGE_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment