sw/inc/doc.hxx | 4 sw/qa/extras/inc/swmodeltestbase.hxx | 85 ++++++--- sw/qa/extras/mailmerge/data/10-testing-addresses.ods |binary sw/qa/extras/mailmerge/data/simple-mail-merge-2pages.odt |binary sw/qa/extras/mailmerge/data/simple-mail-merge.odt |binary sw/qa/extras/mailmerge/mailmerge.cxx | 138 +++++++++++++-- sw/source/core/doc/docnew.cxx | 34 +-- sw/source/ui/dbui/mmoutputpage.cxx | 55 +++++ sw/source/ui/dbui/mmoutputpage.hxx | 4 sw/source/uibase/dbui/dbmgr.cxx | 24 +- sw/source/uibase/inc/mmconfigitem.hxx | 4 11 files changed, 271 insertions(+), 77 deletions(-)
New commits: commit 9e05e45452bfc98c39f589b3f3b90c6596a638c9 Author: LuboÅ¡ LuÅák <[email protected]> Date: Thu Nov 6 16:51:33 2014 +0100 unittest verifying that mail merge correctly sets up marks for sub-documents I.e. the UNO bookmarks that are used for marking where each generated document starts inside the one large single document. Change-Id: I8069a3110cacd34b25aff6739ab248f490c3fa6a diff --git a/sw/qa/extras/mailmerge/mailmerge.cxx b/sw/qa/extras/mailmerge/mailmerge.cxx index efb356c..15a4ea0 100644 --- a/sw/qa/extras/mailmerge/mailmerge.cxx +++ b/sw/qa/extras/mailmerge/mailmerge.cxx @@ -33,7 +33,7 @@ class MMTest : public SwModelTestBase { - public: +public: MMTest() : SwModelTestBase("/sw/qa/extras/mailmerge/data/", "writer8") {} /** * Helper func used by each unit test to test the 'mail merge' code. @@ -64,6 +64,9 @@ class MMTest : public SwModelTestBase nCurOutputType = 0; } +protected: + // Returns page number of the first page of a MM document inside the large MM document (used in the SHELL case). + int documentStartPageNumber( int document ) const; }; #define DECLARE_MAILMERGE_TEST(TestName, filename, datasource, tablename, file, BaseClass) \ @@ -91,6 +94,30 @@ class MMTest : public SwModelTestBase #define DECLARE_FILE_MAILMERGE_TEST(TestName, filename, datasource, tablename) \ DECLARE_MAILMERGE_TEST(TestName, filename, datasource, tablename, true, MMTest) +int MMTest::documentStartPageNumber( int document ) const +{ // See SwMailMergeOutputPage::documentStartPageNumber() . + SwXTextDocument* pTxtDoc = dynamic_cast<SwXTextDocument *>(mxMMComponent.get()); + CPPUNIT_ASSERT(pTxtDoc); + SwWrtShell* shell = pTxtDoc->GetDocShell()->GetWrtShell(); + IDocumentMarkAccess* marks = shell->GetDoc()->getIDocumentMarkAccess(); + // Unfortunately, the pages are marked using UNO bookmarks, which have internals names, so they cannot be referred to by their names. + // Assume that there are no other UNO bookmarks than the ones used by mail merge, and that they are in the sorted order. + IDocumentMarkAccess::const_iterator_t mark; + int pos = 0; + for( mark = marks->getAllMarksBegin(); mark != marks->getAllMarksEnd() && pos < document; ++mark ) + { + if( IDocumentMarkAccess::GetType( **mark ) == IDocumentMarkAccess::UNO_BOOKMARK ) + ++pos; + } + CPPUNIT_ASSERT( pos == document ); + sal_uInt16 page, dummy; + shell->Push(); + shell->GotoMark( mark->get()); + shell->GetPageNum( page, dummy ); + shell->Pop(false); + return page; +} + DECLARE_SHELL_MAILMERGE_TEST(testMultiPageAnchoredDraws, "multiple-page-anchored-draws.odt", "4_v01.ods", "Tabelle1") { executeMailMerge(); @@ -190,6 +217,39 @@ DECLARE_FILE_MAILMERGE_TEST(test2Pages, "simple-mail-merge-2pages.odt", "10-test } } +DECLARE_SHELL_MAILMERGE_TEST(testPageBoundariesSimpleMailMerge, "simple-mail-merge.odt", "10-testing-addresses.ods", "testing-addresses") +{ + // This is like the test above, but this one uses the create-single-document-containing-everything-generated approach, + // and verifies that boundaries of the generated sub-documents are correct inside that document. + // These boundaries are done using "SwMailMergeOutputPage::documentStartPageNumber<number>" UNO bookmarks (see also + // SwMailMergeOutputPage::documentStartPageNumber() ). + executeMailMerge(); + // Here getPages() works on the source document, so get pages of the resulting one. + SwXTextDocument* pTxtDoc = dynamic_cast<SwXTextDocument *>(mxMMComponent.get()); + CPPUNIT_ASSERT(pTxtDoc); + CPPUNIT_ASSERT_EQUAL( sal_uInt16( 19 ), pTxtDoc->GetDocShell()->GetWrtShell()->GetPhyPageNum()); // 10 pages, but each sub-document starts on odd page number + for( int doc = 0; + doc < 10; + ++doc ) + { + CPPUNIT_ASSERT_EQUAL( doc * 2 + 1, documentStartPageNumber( doc )); + } +} + +DECLARE_SHELL_MAILMERGE_TEST(testPageBoundaries2Pages, "simple-mail-merge-2pages.odt", "10-testing-addresses.ods", "testing-addresses") +{ + executeMailMerge(); + SwXTextDocument* pTxtDoc = dynamic_cast<SwXTextDocument *>(mxMMComponent.get()); + CPPUNIT_ASSERT(pTxtDoc); + CPPUNIT_ASSERT_EQUAL( sal_uInt16( 20 ), pTxtDoc->GetDocShell()->GetWrtShell()->GetPhyPageNum()); // 20 pages, each sub-document starts on odd page number + for( int doc = 0; + doc < 10; + ++doc ) + { + CPPUNIT_ASSERT_EQUAL( doc * 2 + 1, documentStartPageNumber( doc )); + } +} + #endif CPPUNIT_PLUGIN_IMPLEMENT(); commit b1263c09c9f7ece4f4173b2738e91dcc0b580827 Author: LuboÅ¡ LuÅák <[email protected]> Date: Thu Nov 6 16:43:28 2014 +0100 name of mailmerge marks is actually irrelevant UNO bookmarks have internals names and ignore this Change-Id: I37baa4c9bcf9cec37f91e3b1d0fb2fad322ceda8 diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx index 2d1ce30..142faf4 100644 --- a/sw/source/uibase/dbui/dbmgr.cxx +++ b/sw/source/uibase/dbui/dbmgr.cxx @@ -1141,7 +1141,8 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, if (bMergeShell) { SwDocMergeInfo aMergeInfo; - aMergeInfo.startPageInTarget = pTargetDoc->getIDocumentMarkAccess()->makeMark( appendedDocStart, "MailMergeInternalStart" + OUString::number( nStartRow ), + // Name of the mark is actually irrelevant, UNO bookmarks have internals names. + aMergeInfo.startPageInTarget = pTargetDoc->getIDocumentMarkAccess()->makeMark( appendedDocStart, "", IDocumentMarkAccess::UNO_BOOKMARK ); aMergeInfo.nDBRow = nStartRow; rMergeDescriptor.pMailMergeConfigItem->AddMergedDocument( aMergeInfo ); commit 5f7bdec8207672c68c34dbbd833bf6b534cf182f Author: LuboÅ¡ LuÅák <[email protected]> Date: Wed Nov 5 20:46:49 2014 +0100 unit test to verify basic mail merge layout for 2 pages Change-Id: I2172d0185a2481700ffe152e58ebd5bd9c6a4fab diff --git a/sw/qa/extras/mailmerge/data/simple-mail-merge-2pages.odt b/sw/qa/extras/mailmerge/data/simple-mail-merge-2pages.odt new file mode 100644 index 0000000..c0a86ae Binary files /dev/null and b/sw/qa/extras/mailmerge/data/simple-mail-merge-2pages.odt differ diff --git a/sw/qa/extras/mailmerge/mailmerge.cxx b/sw/qa/extras/mailmerge/mailmerge.cxx index 78573b3..efb356c 100644 --- a/sw/qa/extras/mailmerge/mailmerge.cxx +++ b/sw/qa/extras/mailmerge/mailmerge.cxx @@ -164,6 +164,32 @@ DECLARE_FILE_MAILMERGE_TEST(testSimpleMailMerge, "simple-mail-merge.odt", "10-te } } +DECLARE_FILE_MAILMERGE_TEST(test2Pages, "simple-mail-merge-2pages.odt", "10-testing-addresses.ods", "testing-addresses") +{ + executeMailMerge(); + for( int doc = 0; + doc < 10; + ++doc ) + { + loadMailMergeDocument( doc ); + OUString lastname = "lastname" + OUString::number( doc + 1 ); + OUString firstname = "firstname" + OUString::number( doc + 1 ); + CPPUNIT_ASSERT_EQUAL( 2, getPages()); + CPPUNIT_ASSERT_EQUAL( OUString( "Fixed text." ), getRun( getParagraph( 1 ), 1 )->getString()); + CPPUNIT_ASSERT_EQUAL( lastname, getRun( getParagraph( 2 ), 1 )->getString()); + CPPUNIT_ASSERT_EQUAL( OUString( "Another fixed text." ), getRun( getParagraph( 3 ), 1 )->getString()); + CPPUNIT_ASSERT_EQUAL( OUString( "" ), getRun( getParagraph( 4 ), 1 )->getString()); // empty para at the end of page 1 + CPPUNIT_ASSERT_EQUAL( OUString( "Second page." ), getRun( getParagraph( 5 ), 1 )->getString()); + CPPUNIT_ASSERT_EQUAL( firstname, getRun( getParagraph( 6 ), 1 )->getString()); + // Also verify the layout. + CPPUNIT_ASSERT_EQUAL( lastname, parseDump("/root/page[1]/body/txt[2]/Special", "rText")); + CPPUNIT_ASSERT_EQUAL( OUString( "Fixed text." ), parseDump("/root/page[1]/body/txt[1]", "")); + CPPUNIT_ASSERT_EQUAL( OUString( "" ), parseDump("/root/page[1]/body/txt[4]", "")); + CPPUNIT_ASSERT_EQUAL( OUString( "Second page." ), parseDump("/root/page[2]/body/txt[1]", "")); + CPPUNIT_ASSERT_EQUAL( firstname, parseDump("/root/page[2]/body/txt[2]/Special", "rText")); + } +} + #endif CPPUNIT_PLUGIN_IMPLEMENT(); commit 3b72f55247a5d9b62490b66900d91f797674b50d Author: LuboÅ¡ LuÅák <[email protected]> Date: Wed Nov 5 20:26:25 2014 +0100 properly discard dumped layout on test document (re)loads Change-Id: I8673810e8c04cd128a691ee1c1e8c4731108b605 diff --git a/sw/qa/extras/inc/swmodeltestbase.hxx b/sw/qa/extras/inc/swmodeltestbase.hxx index dd6a481..413d016 100644 --- a/sw/qa/extras/inc/swmodeltestbase.hxx +++ b/sw/qa/extras/inc/swmodeltestbase.hxx @@ -362,6 +362,15 @@ private: xmlFreeTextWriter(pXmlWriter); } + void discardDumpedLayout() + { + if (mpXmlBuffer) + { + xmlBufferFree(mpXmlBuffer); + mpXmlBuffer = 0; + } + } + void calcLayout() { SwXTextDocument* pTxtDoc = dynamic_cast<SwXTextDocument *>(mxComponent.get()); @@ -610,6 +619,7 @@ protected: std::cout << pName << ","; mnStartTime = osl_getGlobalTimer(); mxComponent = loadFromDesktop(getURLFromSrc(pDir) + OUString::createFromAscii(pName), "com.sun.star.text.TextDocument"); + discardDumpedLayout(); if (mustCalcLayoutOf(pName)) calcLayout(); } @@ -629,6 +639,7 @@ protected: mxComponent = loadFromDesktop(mailMergeOutputURL + "/" + name, "com.sun.star.text.TextDocument"); CPPUNIT_ASSERT( mxComponent.is()); OString name2 = OUStringToOString( name, RTL_TEXTENCODING_UTF8 ); + discardDumpedLayout(); if (mustCalcLayoutOf(name2.getStr())) calcLayout(); } @@ -659,12 +670,7 @@ protected: validate(maTempFile.GetFileName(), test::ODF); } } - - if (mpXmlBuffer) - { - xmlBufferFree(mpXmlBuffer); - mpXmlBuffer = 0; - } + discardDumpedLayout(); if (mustCalcLayoutOf(filename)) calcLayout(); } @@ -685,11 +691,7 @@ protected: { sal_uInt32 nEndTime = osl_getGlobalTimer(); std::cout << (nEndTime - mnStartTime) << std::endl; - if (mpXmlBuffer) - { - xmlBufferFree(mpXmlBuffer); - mpXmlBuffer = 0; - } + discardDumpedLayout(); } /// Get page count. commit 0d349a49871301506c3a714c95bbe309bbd7eb1d Author: LuboÅ¡ LuÅák <[email protected]> Date: Wed Nov 5 20:21:35 2014 +0100 make parseDump() properly handle xml node content Change-Id: Ibb8859908c8e73377e1ee20b041b9ae76955d076 diff --git a/sw/qa/extras/inc/swmodeltestbase.hxx b/sw/qa/extras/inc/swmodeltestbase.hxx index f4c6841..dd6a481 100644 --- a/sw/qa/extras/inc/swmodeltestbase.hxx +++ b/sw/qa/extras/inc/swmodeltestbase.hxx @@ -430,7 +430,7 @@ protected: if (aAttribute.getLength()) aRet = OUString::createFromAscii((const char*)xmlGetProp(pXmlNode, BAD_CAST(aAttribute.getStr()))); else - aRet = OUString::createFromAscii((const char*)XML_GET_CONTENT(pXmlNode)); + aRet = OUString::createFromAscii((const char*)xmlNodeGetContent(pXmlNode)); xmlFreeDoc(pXmlDoc); commit 53eeff46cd98e1fb497023f4fe30e9421c189127 Author: LuboÅ¡ LuÅák <[email protected]> Date: Wed Nov 5 19:27:19 2014 +0100 basic test of mail merge working Change-Id: Ia72d1b2827bfb38ab39d7d0df04908874d25e124 diff --git a/sw/qa/extras/mailmerge/data/10-testing-addresses.ods b/sw/qa/extras/mailmerge/data/10-testing-addresses.ods new file mode 100644 index 0000000..33b82e6 Binary files /dev/null and b/sw/qa/extras/mailmerge/data/10-testing-addresses.ods differ diff --git a/sw/qa/extras/mailmerge/data/simple-mail-merge.odt b/sw/qa/extras/mailmerge/data/simple-mail-merge.odt new file mode 100644 index 0000000..34637d4 Binary files /dev/null and b/sw/qa/extras/mailmerge/data/simple-mail-merge.odt differ diff --git a/sw/qa/extras/mailmerge/mailmerge.cxx b/sw/qa/extras/mailmerge/mailmerge.cxx index 4ee1503..78573b3 100644 --- a/sw/qa/extras/mailmerge/mailmerge.cxx +++ b/sw/qa/extras/mailmerge/mailmerge.cxx @@ -149,6 +149,21 @@ DECLARE_FILE_MAILMERGE_TEST(testMissingDefaultLineColor, "missing-default-line-c CPPUNIT_ASSERT_EQUAL( OUString( "#000000" ), getXPath(pXmlDoc, "/office:document-styles/office:styles/style:default-style[1]/style:graphic-properties", "stroke-color")); } +DECLARE_FILE_MAILMERGE_TEST(testSimpleMailMerge, "simple-mail-merge.odt", "10-testing-addresses.ods", "testing-addresses") +{ + executeMailMerge(); + for( int doc = 0; + doc < 10; + ++doc ) + { + loadMailMergeDocument( doc ); + CPPUNIT_ASSERT_EQUAL( 1, getPages()); + CPPUNIT_ASSERT_EQUAL( OUString( "Fixed text." ), getRun( getParagraph( 1 ), 1 )->getString()); + CPPUNIT_ASSERT_EQUAL( OUString( "lastname" + OUString::number( doc + 1 )), getRun( getParagraph( 2 ), 1 )->getString()); + CPPUNIT_ASSERT_EQUAL( OUString( "Another fixed text." ), getRun( getParagraph( 3 ), 1 )->getString()); + } +} + #endif CPPUNIT_PLUGIN_IMPLEMENT(); commit 74720747d9c93b6d54dc7550a05b90b9b7d5a8a8 Author: LuboÅ¡ LuÅák <[email protected]> Date: Wed Nov 5 19:25:04 2014 +0100 do not register MM unittest databases with a prefix Since that makes SwDBManager::IsDataSourceOpen() return false because of different data sources (than the one the document was tested with manually), which prevents DocumentFieldsManager::UpdateExpFlds() from updating fields properly. Change-Id: I66f5f79d9fd39204eabb247aa92ec11acef56903 diff --git a/sw/qa/extras/inc/swmodeltestbase.hxx b/sw/qa/extras/inc/swmodeltestbase.hxx index da7921f..f4c6841 100644 --- a/sw/qa/extras/inc/swmodeltestbase.hxx +++ b/sw/qa/extras/inc/swmodeltestbase.hxx @@ -801,13 +801,13 @@ protected: xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("css3t"), BAD_CAST("http://www.w3.org/TR/css3-text/")); } - virtual OUString registerDBsource( const OUString &aURI, const OUString &aPrefix, const OUString &aWorkDir ) + virtual OUString registerDBsource( const OUString &aURI, const OUString &aWorkDir ) { OUString aDBName; DBuriMap::const_iterator pos = aDBuriMap.find( aURI ); if (pos == aDBuriMap.end()) { - aDBName = SwDBManager::LoadAndRegisterDataSource( aURI, &aPrefix, &aWorkDir ); + aDBName = SwDBManager::LoadAndRegisterDataSource( aURI, NULL, &aWorkDir ); aDBuriMap.insert( std::pair< OUString, OUString >( aURI, aDBName ) ); std::cout << "New datasource name: '" << aDBName << "'" << std::endl; } diff --git a/sw/qa/extras/mailmerge/mailmerge.cxx b/sw/qa/extras/mailmerge/mailmerge.cxx index d278db1..4ee1503 100644 --- a/sw/qa/extras/mailmerge/mailmerge.cxx +++ b/sw/qa/extras/mailmerge/mailmerge.cxx @@ -50,12 +50,11 @@ class MMTest : public SwModelTestBase preTest(filename); load(mpTestDocumentPath, filename); - const OUString aPrefix( "LOMM_" ); utl::TempFile aTempDir(nullptr, true); const OUString aWorkDir = aTempDir.GetURL(); const OUString aURI( getURLFromSrc(mpTestDocumentPath) + OUString::createFromAscii(datasource) ); - OUString aDBName = registerDBsource( aURI, aPrefix, aWorkDir ); - initMailMergeJobAndArgs( filename, tablename, aDBName, aPrefix, aWorkDir, file ); + OUString aDBName = registerDBsource( aURI, aWorkDir ); + initMailMergeJobAndArgs( filename, tablename, aDBName, "LOMM_", aWorkDir, file ); postTest(filename); verify(); commit b4bc6521759103a5a79819a082e7413737212a76 Author: LuboÅ¡ LuÅák <[email protected]> Date: Wed Nov 5 14:19:23 2014 +0100 make it possible to check mailmerge output files in unittests Change-Id: Ifa54445c8f46bb2ed5539870c5fce1a2e62beef7 diff --git a/sw/qa/extras/inc/swmodeltestbase.hxx b/sw/qa/extras/inc/swmodeltestbase.hxx index b642abc..da7921f 100644 --- a/sw/qa/extras/inc/swmodeltestbase.hxx +++ b/sw/qa/extras/inc/swmodeltestbase.hxx @@ -182,6 +182,8 @@ protected: utl::TempFile maTempFile; bool mbExported; ///< Does maTempFile already contain something useful? sal_Int16 nCurOutputType; + OUString mailMergeOutputURL; + OUString mailMergeOutputPrefix; protected: virtual OUString getTestName() { return OUString(); } @@ -612,6 +614,25 @@ protected: calcLayout(); } + /** + Loads number-th document from mail merge. Requires file output from mail merge. + */ + void loadMailMergeDocument( int number ) + { + assert( nCurOutputType == text::MailMergeType::FILE ); + if (mxComponent.is()) + mxComponent->dispose(); + OUString name = mailMergeOutputPrefix + OUString::number( number ) + ".odt"; + // Output name early, so in the case of a hang, the name of the hanging input file is visible. + std::cout << name << ","; + mnStartTime = osl_getGlobalTimer(); + mxComponent = loadFromDesktop(mailMergeOutputURL + "/" + name, "com.sun.star.text.TextDocument"); + CPPUNIT_ASSERT( mxComponent.is()); + OString name2 = OUStringToOString( name, RTL_TEXTENCODING_UTF8 ); + if (mustCalcLayoutOf(name2.getStr())) + calcLayout(); + } + void reload(const char* pFilter, const char* filename) { uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY); @@ -692,8 +713,25 @@ protected: if (!mbExported) return 0; + return parseExportInternal( maTempFile.GetURL(), rStreamName ); + } + + /** + * Like parseExport(), but for given mail merge document. + */ + xmlDocPtr parseMailMergeExport(int number, const OUString& rStreamName = OUString("word/document.xml")) + { + if (nCurOutputType != text::MailMergeType::FILE) + return 0; + + OUString name = mailMergeOutputPrefix + OUString::number( number ) + ".odt"; + return parseExportInternal( mailMergeOutputURL + "/" + name, rStreamName ); + } + + xmlDocPtr parseExportInternal( const OUString& url, const OUString& rStreamName ) + { // Read the XML stream we're interested in. - uno::Reference<packages::zip::XZipFileAccess2> xNameAccess = packages::zip::ZipFileAccess::createWithURL(comphelper::getComponentContext(m_xSFactory), maTempFile.GetURL()); + uno::Reference<packages::zip::XZipFileAccess2> xNameAccess = packages::zip::ZipFileAccess::createWithURL(comphelper::getComponentContext(m_xSFactory), url); uno::Reference<io::XInputStream> xInputStream(xNameAccess->getByName(rStreamName), uno::UNO_QUERY); boost::shared_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(xInputStream, true)); @@ -783,7 +821,7 @@ protected: } virtual void initMailMergeJobAndArgs( const char* filename, const char* tablename, const OUString &aDBName, - const OUString &aPrefix, const OUString &aWorkDir ) + const OUString &aPrefix, const OUString &aWorkDir, bool file ) { uno::Reference< task::XJob > xJob( getMultiServiceFactory()->createInstance( "com.sun.star.text.MailMerge" ), uno::UNO_QUERY_THROW ); mxJob.set( xJob ); @@ -793,7 +831,7 @@ protected: mSeqMailMergeArgs.realloc( seq_id ); seq_id = 0; - mSeqMailMergeArgs[ seq_id++ ] = beans::NamedValue( OUString( UNO_NAME_OUTPUT_TYPE ), uno::Any( text::MailMergeType::SHELL ) ); + mSeqMailMergeArgs[ seq_id++ ] = beans::NamedValue( OUString( UNO_NAME_OUTPUT_TYPE ), uno::Any( file ? text::MailMergeType::FILE : text::MailMergeType::SHELL ) ); mSeqMailMergeArgs[ seq_id++ ] = beans::NamedValue( OUString( UNO_NAME_DOCUMENT_URL ), uno::Any( ( OUString(getURLFromSrc(mpTestDocumentPath) + OUString::createFromAscii(filename)) ) ) ); mSeqMailMergeArgs[ seq_id++ ] = beans::NamedValue( OUString( UNO_NAME_DATA_SOURCE_NAME ), uno::Any( aDBName ) ); @@ -810,8 +848,6 @@ protected: { uno::Any res = mxJob->execute( mSeqMailMergeArgs ); - OUString aCurOutputURL; - OUString aCurFileNamePrefix; const beans::NamedValue *pArguments = mSeqMailMergeArgs.getConstArray(); bool bOk = true; sal_Int32 nArgs = mSeqMailMergeArgs.getLength(); @@ -822,9 +858,9 @@ protected: // all error checking was already done by the MM job execution if (rName == UNO_NAME_OUTPUT_URL) - bOk &= rValue >>= aCurOutputURL; + bOk &= rValue >>= mailMergeOutputURL; else if (rName == UNO_NAME_FILE_NAME_PREFIX) - bOk &= rValue >>= aCurFileNamePrefix; + bOk &= rValue >>= mailMergeOutputPrefix; else if (rName == UNO_NAME_OUTPUT_TYPE) bOk &= rValue >>= nCurOutputType; } @@ -839,10 +875,7 @@ protected: else { CPPUNIT_ASSERT(res == true); - mxMMComponent = loadFromDesktop( aCurOutputURL + "/" + aCurFileNamePrefix + "0.odt", - "com.sun.star.text.TextDocument"); - CPPUNIT_ASSERT(mxMMComponent.is()); - calcLayout(); + loadMailMergeDocument( 0 ); } } }; diff --git a/sw/qa/extras/mailmerge/mailmerge.cxx b/sw/qa/extras/mailmerge/mailmerge.cxx index 1260d69..d278db1 100644 --- a/sw/qa/extras/mailmerge/mailmerge.cxx +++ b/sw/qa/extras/mailmerge/mailmerge.cxx @@ -44,7 +44,7 @@ class MMTest : public SwModelTestBase * The 'verify' method actually has to execute the mail merge by * calling executeMailMerge() after modifying the job arguments. */ - void executeMailMergeTest(const char* filename, const char* datasource, const char* tablename = 0) + void executeMailMergeTest(const char* filename, const char* datasource, const char* tablename, bool file) { header(); preTest(filename); @@ -55,18 +55,19 @@ class MMTest : public SwModelTestBase const OUString aWorkDir = aTempDir.GetURL(); const OUString aURI( getURLFromSrc(mpTestDocumentPath) + OUString::createFromAscii(datasource) ); OUString aDBName = registerDBsource( aURI, aPrefix, aWorkDir ); - initMailMergeJobAndArgs( filename, tablename, aDBName, aPrefix, aWorkDir ); + initMailMergeJobAndArgs( filename, tablename, aDBName, aPrefix, aWorkDir, file ); postTest(filename); verify(); finish(); ::utl::removeTree(aWorkDir); + nCurOutputType = 0; } }; -#define DECLARE_MAILMERGE_TEST(TestName, filename, datasource, tablename, BaseClass) \ +#define DECLARE_MAILMERGE_TEST(TestName, filename, datasource, tablename, file, BaseClass) \ class TestName : public BaseClass { \ protected: \ virtual OUString getTestName() SAL_OVERRIDE { return OUString::createFromAscii(#TestName); } \ @@ -76,17 +77,22 @@ class MMTest : public SwModelTestBase CPPUNIT_TEST_SUITE_END(); \ \ void MailMerge() { \ - executeMailMergeTest(filename, datasource, tablename); \ + executeMailMergeTest(filename, datasource, tablename, file); \ } \ void verify() SAL_OVERRIDE; \ }; \ CPPUNIT_TEST_SUITE_REGISTRATION(TestName); \ void TestName::verify() -#define DECLARE_DFLT_MAILMERGE_TEST(TestName, filename, datasource, tablename) \ - DECLARE_MAILMERGE_TEST(TestName, filename, datasource, tablename, MMTest) +// Will generate the resulting document in mxMMDocument. +#define DECLARE_SHELL_MAILMERGE_TEST(TestName, filename, datasource, tablename) \ + DECLARE_MAILMERGE_TEST(TestName, filename, datasource, tablename, false, MMTest) -DECLARE_DFLT_MAILMERGE_TEST(testMultiPageAnchoredDraws, "multiple-page-anchored-draws.odt", "4_v01.ods", "Tabelle1") +// Will generate documents as files, use loadMailMergeDocument(). +#define DECLARE_FILE_MAILMERGE_TEST(TestName, filename, datasource, tablename) \ + DECLARE_MAILMERGE_TEST(TestName, filename, datasource, tablename, true, MMTest) + +DECLARE_SHELL_MAILMERGE_TEST(testMultiPageAnchoredDraws, "multiple-page-anchored-draws.odt", "4_v01.ods", "Tabelle1") { executeMailMerge(); @@ -117,19 +123,19 @@ DECLARE_DFLT_MAILMERGE_TEST(testMultiPageAnchoredDraws, "multiple-page-anchored- } } -DECLARE_DFLT_MAILMERGE_TEST(testMissingDefaultLineColor, "missing-default-line-color.ott", "one-empty-address.ods", "one-empty-address") +DECLARE_FILE_MAILMERGE_TEST(testMissingDefaultLineColor, "missing-default-line-color.ott", "one-empty-address.ods", "one-empty-address") { executeMailMerge(); // The document was created by LO version which didn't write out the default value for line color // (see XMLGraphicsDefaultStyle::SetDefaults()). - uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(mxMMComponent, uno::UNO_QUERY); + uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(mxComponent, uno::UNO_QUERY); uno::Reference<container::XIndexAccess> xDraws(xDrawPageSupplier->getDrawPage(), uno::UNO_QUERY); uno::Reference<beans::XPropertySet> xPropertySet(xDraws->getByIndex(0), uno::UNO_QUERY); // Lines do not have a line color. CPPUNIT_ASSERT( !xPropertySet->getPropertySetInfo()->hasPropertyByName( "LineColor" )); - SwXTextDocument* pTxtDoc = dynamic_cast<SwXTextDocument *>(mxMMComponent.get()); + SwXTextDocument* pTxtDoc = dynamic_cast<SwXTextDocument *>(mxComponent.get()); CPPUNIT_ASSERT(pTxtDoc); - uno::Reference< lang::XMultiServiceFactory > xFact( mxMMComponent, uno::UNO_QUERY ); + uno::Reference< lang::XMultiServiceFactory > xFact( mxComponent, uno::UNO_QUERY ); uno::Reference< beans::XPropertySet > xDefaults( xFact->createInstance( "com.sun.star.drawing.Defaults" ), uno::UNO_QUERY ); CPPUNIT_ASSERT( xDefaults.is()); uno::Reference< beans::XPropertySetInfo > xInfo( xDefaults->getPropertySetInfo()); @@ -138,6 +144,10 @@ DECLARE_DFLT_MAILMERGE_TEST(testMissingDefaultLineColor, "missing-default-line-c xDefaults->getPropertyValue( "LineColor" ) >>= lineColor; // And the default value is black (wasn't copied properly by mailmerge). CPPUNIT_ASSERT_EQUAL( COL_BLACK, lineColor ); + // And check that the resulting file has the proper default. + xmlDocPtr pXmlDoc = parseMailMergeExport( 0, "styles.xml" ); + CPPUNIT_ASSERT_EQUAL( OUString( "graphic" ), getXPath(pXmlDoc, "/office:document-styles/office:styles/style:default-style[1]", "family")); + CPPUNIT_ASSERT_EQUAL( OUString( "#000000" ), getXPath(pXmlDoc, "/office:document-styles/office:styles/style:default-style[1]/style:graphic-properties", "stroke-color")); } #endif commit f373aa0be0a2150c05de5b215f18ed8f0f333e83 Author: LuboÅ¡ LuÅák <[email protected]> Date: Wed Oct 22 13:20:49 2014 +0200 do not repeatedly relayout mailmerge document after each change When mailmerge uses a single document for all the generated documents, doing a layout of this increasingly large document after every generated document addition was getting slower and slower (no wonder). My recent changes should have removed all needs for any layout in progress, so it should be enough to just once calculate the final layout. The final layout still appears to be needed, leaving it as it is to get layout done on the fly puts e.g. 2-page documents on wrong starting page (maybe just invalidating something would fix that). Debug build shows warnings from vdraw.cxx about moving anchor from an invalid page because of broken layouting, but those were there already before, so I assume those are not really significant (or at least made worse by this commit). Change-Id: I62601ad6dccaa008783d1ce34c9e4f66f9621a56 diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx index 4a07408..2d1ce30 100644 --- a/sw/source/uibase/dbui/dbmgr.cxx +++ b/sw/source/uibase/dbui/dbmgr.cxx @@ -1135,8 +1135,6 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, ++targetDocPageCount; // Docs always start on odd pages (so offset must be even). SwNodeIndex appendedDocStart = pTargetDoc->AppendDoc(*rWorkShell.GetDoc(), nStartingPageNo, pTargetPageDesc, nDocNo == 1, targetDocPageCount); - // #i72820# calculate layout to be able to find the correct page index - pTargetShell->CalcLayout(); targetDocPageCount += rWorkShell.GetPageCnt(); if ( (nMaxDumpDocs < 0) || (nDocNo <= nMaxDumpDocs) ) lcl_SaveDoc( xTargetDocShell, "MergeDoc" ); @@ -1288,6 +1286,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, // Unfreeze target document layouts and correct all PageDescs. if(rMergeDescriptor.bCreateSingleFile) { + pTargetShell->CalcLayout(); std::set<SwRootFrm*> aAllLayouts = pTargetShell->GetDoc()->GetAllLayouts(); std::for_each( aAllLayouts.begin(), aAllLayouts.end(), ::std::bind2nd(::std::mem_fun(&SwRootFrm::FreezeLayout), false)); commit ae5afe9bcebdd220a457829d47882fe8a0cf69fd Author: LuboÅ¡ LuÅák <[email protected]> Date: Mon Oct 20 22:05:51 2014 +0200 compute page offset for mailmerge based on source document rather than target This removes another need for doing repeated and expensive layouts of the target document. Change-Id: Id78bc3ccc71c17e42f858dc9660866b9c94dea3a diff --git a/sw/inc/doc.hxx b/sw/inc/doc.hxx index 8a382e1..c8b88c2 100644 --- a/sw/inc/doc.hxx +++ b/sw/inc/doc.hxx @@ -1660,7 +1660,7 @@ public: SfxObjectShell* CreateCopy(bool bCallInitNew) const; SwNodeIndex AppendDoc(const SwDoc& rSource, sal_uInt16 nStartPageNumber, - SwPageDesc* pTargetPageDesc, bool bDeletePrevious = false ); + SwPageDesc* pTargetPageDesc, bool bDeletePrevious = false, int physicalPageOffset = 0 ); /** * Dumps the entire nodes structure to the given destination (file nodes.xml in the current directory by default) diff --git a/sw/source/core/doc/docnew.cxx b/sw/source/core/doc/docnew.cxx index 066f625..70bda8c 100644 --- a/sw/source/core/doc/docnew.cxx +++ b/sw/source/core/doc/docnew.cxx @@ -932,7 +932,7 @@ SfxObjectShell* SwDoc::CreateCopy(bool bCallInitNew ) const // appends all pages of source SwDoc - based on SwFEShell::Paste( SwDoc* ) SwNodeIndex SwDoc::AppendDoc(const SwDoc& rSource, sal_uInt16 const nStartPageNumber, - SwPageDesc *const pTargetPageDesc, bool const bDeletePrevious) + SwPageDesc *const pTargetPageDesc, bool const bDeletePrevious, int pageOffset) { // GetEndOfExtras + 1 = StartOfContent == no content node! // @see IDocumentContentOperations::CopyRange @@ -973,7 +973,6 @@ SwNodeIndex SwDoc::AppendDoc(const SwDoc& rSource, sal_uInt16 const nStartPageNu #endif SwWrtShell* pTargetShell = GetDocShell()->GetWrtShell(); - sal_uInt16 nPhysPageNumber = 0; if ( pTargetShell ) { #ifdef DBG_UTIL SAL_INFO( "sw.docappend", "Has target write shell" ); @@ -985,18 +984,6 @@ SwNodeIndex SwDoc::AppendDoc(const SwDoc& rSource, sal_uInt16 const nStartPageNu OUString name = pTargetPageDesc->GetName(); pTargetShell->InsertPageBreak( &name, nStartPageNumber ); } - - // -1 for the page break + -1, becauce it's an offset - nPhysPageNumber = pTargetShell->GetPhyPageNum() - 2; - if (bDeletePrevious) - nPhysPageNumber--; - - // We always start on an odd physical page number - if (1 == nPhysPageNumber % 2) - nPhysPageNumber++; -#ifdef DBG_UTIL - SAL_INFO( "sw.docappend", "PPNo " << nPhysPageNumber ); -#endif } #ifdef DBG_UTIL SAL_INFO( "sw.docappend", "Nd: " << CNTNT_DOC( this ) ); @@ -1154,10 +1141,10 @@ else continue; #ifdef DBG_UTIL SAL_INFO( "sw.docappend", "PaAn: " << aAnchor.GetPageNum() - << " => " << aAnchor.GetPageNum() + nPhysPageNumber ); + << " => " << aAnchor.GetPageNum() + pageOffset ); #endif - if ( nPhysPageNumber ) - aAnchor.SetPageNum( aAnchor.GetPageNum() + nPhysPageNumber ); + if ( pageOffset != 0 ) + aAnchor.SetPageNum( aAnchor.GetPageNum() + pageOffset ); this->getIDocumentLayoutAccess().CopyLayoutFmt( rCpyFmt, aAnchor, true, true ); } } diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx index c6f48fe..4a07408 100644 --- a/sw/source/uibase/dbui/dbmgr.cxx +++ b/sw/source/uibase/dbui/dbmgr.cxx @@ -979,6 +979,12 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, sal_Int32 nDocNo = 1; sal_Int32 nDocCount = 0; + // For single file mode, the number of pages in the target document so far, which is used + // by AppendDoc() to adjust position of page-bound objects. Getting this information directly + // from the target doc would require repeated layouts of the doc, which is expensive, but + // it can be manually computed from the source documents (for which we do layouts, so the page + // count is known, and there is a blank page between each of them in the target document). + int targetDocPageCount = 0; if( !IsMergeSilent() && bMergeShell && lcl_getCountFromResultSet( nDocCount, pImpl->pMergeData->xResultSet ) ) static_cast<CreateMonitor*>( pProgressDlg )->SetTotalCount( nDocCount ); @@ -1125,10 +1131,13 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, if ( (nMaxDumpDocs < 0) || (nDocNo <= nMaxDumpDocs) ) lcl_SaveDoc( xWorkDocSh, "WorkDoc", nDocNo ); + if( targetDocPageCount % 2 == 1 ) + ++targetDocPageCount; // Docs always start on odd pages (so offset must be even). SwNodeIndex appendedDocStart = pTargetDoc->AppendDoc(*rWorkShell.GetDoc(), - nStartingPageNo, pTargetPageDesc, nDocNo == 1); + nStartingPageNo, pTargetPageDesc, nDocNo == 1, targetDocPageCount); // #i72820# calculate layout to be able to find the correct page index pTargetShell->CalcLayout(); + targetDocPageCount += rWorkShell.GetPageCnt(); if ( (nMaxDumpDocs < 0) || (nDocNo <= nMaxDumpDocs) ) lcl_SaveDoc( xTargetDocShell, "MergeDoc" ); if (bMergeShell) commit a305a2c91420652db450b7f8edd140e1d69f42cf Author: LuboÅ¡ LuÅák <[email protected]> Date: Mon Oct 20 15:13:03 2014 +0200 use bookmarks to mark mailmerge parts in a mailmerge document (fdo#80823) Instead of page numbers, which - was somewhat fragile (and broken, as it was actually off-by-one) - required repeated re-layout of the increasingly large document, making mailmerge awfully slow. The re-layout is not removed by this commit, as it needs further checking whether it can be removed. See the bugreport for details. Change-Id: Ib09bd5f5a6a549c3d38ca40b0f32c0d2831fdd4c diff --git a/sw/inc/doc.hxx b/sw/inc/doc.hxx index eb1a240..8a382e1 100644 --- a/sw/inc/doc.hxx +++ b/sw/inc/doc.hxx @@ -1659,7 +1659,7 @@ public: ::sw::UndoManager const& GetUndoManager() const; SfxObjectShell* CreateCopy(bool bCallInitNew) const; - void AppendDoc(const SwDoc& rSource, sal_uInt16 nStartPageNumber, + SwNodeIndex AppendDoc(const SwDoc& rSource, sal_uInt16 nStartPageNumber, SwPageDesc* pTargetPageDesc, bool bDeletePrevious = false ); /** diff --git a/sw/source/core/doc/docnew.cxx b/sw/source/core/doc/docnew.cxx index a8405d5..066f625 100644 --- a/sw/source/core/doc/docnew.cxx +++ b/sw/source/core/doc/docnew.cxx @@ -931,7 +931,7 @@ SfxObjectShell* SwDoc::CreateCopy(bool bCallInitNew ) const } // appends all pages of source SwDoc - based on SwFEShell::Paste( SwDoc* ) -void SwDoc::AppendDoc(const SwDoc& rSource, sal_uInt16 const nStartPageNumber, +SwNodeIndex SwDoc::AppendDoc(const SwDoc& rSource, sal_uInt16 const nStartPageNumber, SwPageDesc *const pTargetPageDesc, bool const bDeletePrevious) { // GetEndOfExtras + 1 = StartOfContent == no content node! @@ -1020,6 +1020,9 @@ void SwDoc::AppendDoc(const SwDoc& rSource, sal_uInt16 const nStartPageNumber, this->GetIDocumentUndoRedo().StartUndo( UNDO_INSGLOSSARY, NULL ); this->getIDocumentFieldsAccess().LockExpFlds(); + // Position where the appended doc starts. Will be filled in later (uses GetEndOfContent() because SwNodeIndex has no default ctor). + SwNodeIndex aStartAppendIndex( GetNodes().GetEndOfContent() ); + { // ** // ** refer to SwFEShell::Paste, if you change the following code ** @@ -1132,6 +1135,12 @@ else << " EOE: " << GetNodes().GetEndOfExtras().GetIndex() ); #endif GetNodes().Delete( aDelIdx, iDelNodes ); + aStartAppendIndex = aFixupIdx; + } + else + { + aStartAppendIndex = aFixupIdx; + ++aStartAppendIndex; } } @@ -1160,6 +1169,8 @@ else if ( pTargetShell ) pTargetShell->EndAllAction(); + + return aStartAppendIndex; } sal_uInt16 SwTxtFmtColls::GetPos(const SwTxtFmtColl* p) const diff --git a/sw/source/ui/dbui/mmoutputpage.cxx b/sw/source/ui/dbui/mmoutputpage.cxx index 17f3b7e..0034007 100644 --- a/sw/source/ui/dbui/mmoutputpage.cxx +++ b/sw/source/ui/dbui/mmoutputpage.cxx @@ -553,6 +553,50 @@ IMPL_LINK_NOARG(SwMailMergeOutputPage, SaveCancelHdl_Impl) return 0; } +int SwMailMergeOutputPage::documentStartPageNumber( int document ) const +{ + SwMailMergeConfigItem& rConfigItem = m_pWizard->GetConfigItem(); + SwView* pTargetView = rConfigItem.GetTargetView(); + assert( pTargetView ); + SwCrsrShell& shell = pTargetView->GetWrtShell(); + const SwDocMergeInfo& info = rConfigItem.GetDocumentMergeInfo( document ); + sal_uInt16 page, dummy; + shell.Push(); + shell.GotoMark( info.startPageInTarget ); + shell.GetPageNum( page, dummy ); + shell.Pop(false); + return page; +} + +int SwMailMergeOutputPage::documentEndPageNumber( int document ) const +{ + SwMailMergeConfigItem& rConfigItem = m_pWizard->GetConfigItem(); + SwView* pTargetView = rConfigItem.GetTargetView(); + assert( pTargetView ); + SwWrtShell& shell = pTargetView->GetWrtShell(); + if( document < int( rConfigItem.GetMergedDocumentCount()) - 1 ) + { + // Go to the page before the starting page of the next merged document. + const SwDocMergeInfo& info = rConfigItem.GetDocumentMergeInfo( document + 1 ); + sal_uInt16 page, dummy; + shell.Push(); + shell.GotoMark( info.startPageInTarget ); + shell.EndPrvPg(); + shell.GetPageNum( page, dummy ); + shell.Pop(false); + return page; + } + else + { // This is the last merged document, so it ends on the page at which the document ends. + sal_uInt16 page, dummy; + shell.Push(); + shell.SttEndDoc( false ); // go to doc end + shell.GetPageNum( page, dummy ); + shell.Pop(false); + return page; + } +} + IMPL_LINK(SwMailMergeOutputPage, SaveOutputHdl_Impl, PushButton*, pButton) { SwMailMergeConfigItem& rConfigItem = m_pWizard->GetConfigItem(); @@ -655,7 +699,6 @@ IMPL_LINK(SwMailMergeOutputPage, SaveOutputHdl_Impl, PushButton*, pButton) for(sal_uInt32 nDoc = nBegin; nDoc < nEnd && !m_bCancelSaving; ++nDoc) { - SwDocMergeInfo& rInfo = rConfigItem.GetDocumentMergeInfo(nDoc); INetURLObject aURL(sPath); OUString sExtension = aURL.getExtension(); if (sExtension.isEmpty()) @@ -686,7 +729,7 @@ IMPL_LINK(SwMailMergeOutputPage, SaveOutputHdl_Impl, PushButton*, pButton) pTempView->GetDocShell()->GetDoc()->ReplaceDocumentProperties( *pTargetView->GetDocShell()->GetDoc(), true ); pTargetView->GetWrtShell().PastePages(pTempView->GetWrtShell(), - (sal_uInt16)rInfo.nStartPageInTarget, (sal_uInt16)rInfo.nEndPageInTarget ); + documentStartPageNumber( nDoc ), documentEndPageNumber( nDoc )); pTargetView->GetWrtShell().EndAction(); //then save it OUString sOutPath = aURL.GetMainURL(INetURLObject::DECODE_TO_IURI); @@ -801,12 +844,10 @@ IMPL_LINK_NOARG(SwMailMergeOutputPage, PrintHdl_Impl) nEnd = rConfigItem.GetMergedDocumentCount(); } rConfigItem.SetPrintRange( (sal_uInt16)nBegin, (sal_uInt16)nEnd ); - SwDocMergeInfo& rStartInfo = rConfigItem.GetDocumentMergeInfo(nBegin); - SwDocMergeInfo& rEndInfo = rConfigItem.GetDocumentMergeInfo(nEnd - 1); - OUString sPages(OUString::number( rStartInfo.nStartPageInTarget )); + OUString sPages(OUString::number( documentStartPageNumber( nBegin ))); sPages += " - "; - sPages += OUString::number( rEndInfo.nEndPageInTarget ); + sPages += OUString::number( documentEndPageNumber( nEnd - 1 )); pTargetView->SetMailMergeConfigItem(&rConfigItem, 0, false); if(m_pTempPrinter) @@ -1092,7 +1133,7 @@ IMPL_LINK(SwMailMergeOutputPage, SendDocumentsHdl_Impl, PushButton*, pButton) pTempView->GetDocShell()->GetDoc()->ReplaceDefaults( *pTargetView->GetDocShell()->GetDoc()); pTempView->GetDocShell()->GetDoc()->ReplaceDocumentProperties( *pTargetView->GetDocShell()->GetDoc(), true ); pTargetView->GetWrtShell().PastePages(pTempView->GetWrtShell(), - (sal_uInt16)rInfo.nStartPageInTarget, (sal_uInt16)rInfo.nEndPageInTarget ); + documentStartPageNumber( nDoc ), documentEndPageNumber( nDoc )); pTargetView->GetWrtShell().EndAction(); //then save it diff --git a/sw/source/ui/dbui/mmoutputpage.hxx b/sw/source/ui/dbui/mmoutputpage.hxx index 7355016..a31ddea 100644 --- a/sw/source/ui/dbui/mmoutputpage.hxx +++ b/sw/source/ui/dbui/mmoutputpage.hxx @@ -116,6 +116,10 @@ class SwMailMergeOutputPage : public svt::OWizardPage DECL_LINK(SendDocumentsHdl_Impl, PushButton*); DECL_LINK(DocumentSelectionHdl_Impl, RadioButton*); DECL_LINK(SaveCancelHdl_Impl, void *); + + int documentStartPageNumber( int document ) const; + int documentEndPageNumber( int document ) const; + protected: virtual bool canAdvance() const SAL_OVERRIDE; virtual void ActivatePage() SAL_OVERRIDE; diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx index 6f17f51..c6f48fe 100644 --- a/sw/source/uibase/dbui/dbmgr.cxx +++ b/sw/source/uibase/dbui/dbmgr.cxx @@ -1123,12 +1123,10 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, else pTargetPageDesc = pTargetShell->FindPageDescByName( sModifiedStartingPageDesc ); - sal_uInt16 nStartPage = pTargetShell->GetPageCnt(); if ( (nMaxDumpDocs < 0) || (nDocNo <= nMaxDumpDocs) ) lcl_SaveDoc( xWorkDocSh, "WorkDoc", nDocNo ); - pTargetDoc->AppendDoc(*rWorkShell.GetDoc(), + SwNodeIndex appendedDocStart = pTargetDoc->AppendDoc(*rWorkShell.GetDoc(), nStartingPageNo, pTargetPageDesc, nDocNo == 1); - // #i72820# calculate layout to be able to find the correct page index pTargetShell->CalcLayout(); if ( (nMaxDumpDocs < 0) || (nDocNo <= nMaxDumpDocs) ) @@ -1136,9 +1134,8 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, if (bMergeShell) { SwDocMergeInfo aMergeInfo; - aMergeInfo.nStartPageInTarget = nStartPage; - aMergeInfo.nEndPageInTarget = - nStartPage + pSourceShell->GetPageCnt() - 1; + aMergeInfo.startPageInTarget = pTargetDoc->getIDocumentMarkAccess()->makeMark( appendedDocStart, "MailMergeInternalStart" + OUString::number( nStartRow ), + IDocumentMarkAccess::UNO_BOOKMARK ); aMergeInfo.nDBRow = nStartRow; rMergeDescriptor.pMailMergeConfigItem->AddMergedDocument( aMergeInfo ); } diff --git a/sw/source/uibase/inc/mmconfigitem.hxx b/sw/source/uibase/inc/mmconfigitem.hxx index feeaed8..8117cfd 100644 --- a/sw/source/uibase/inc/mmconfigitem.hxx +++ b/sw/source/uibase/inc/mmconfigitem.hxx @@ -38,11 +38,11 @@ namespace com{namespace sun{namespace star{ class SwMailMergeConfigItem_Impl; class SwView; +namespace sw { namespace mark { class IMark; }} struct SwDocMergeInfo { - long nStartPageInTarget; - long nEndPageInTarget; + sw::mark::IMark* startPageInTarget; long nDBRow; };
_______________________________________________ Libreoffice-commits mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
