diff options
author | Miklos Vajna <vmiklos@collabora.com> | 2020-01-15 17:54:52 +0100 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.com> | 2020-05-04 11:55:36 +0200 |
commit | eca5e17c62a04fc941ca237799fd6e931be87308 (patch) | |
tree | f7ab150724753d2c16e3f7c77487143f91260df2 | |
parent | 072af1b01c783b4ee7c9005ac2c15355e8a2f74d (diff) |
DOCX import: improve support for headers/footers from cont sect break
A continuous section break in a DOCX file can set new headers/footers
which start appearing from the next page. In general, this is not
something Writer supports, but commit
08f13ab85b5c65b5dc8adfa15918fb3e426fcc3c (tdf#112202 writerfilter,sw:
fix loss of headers, 2019-12-16) improved the situation significantly
here.
Build on top of that and add support for a few more cases:
1) When checking for the last paragraph of the previous section, detect
when that last paragraph is so small so in practice that's not the last
one.
2) Handle when the text node in question has no explicit break type set,
only a SwFormatPageDesc (which implicitly causes a page break).
3) When setting the page style to show the correct header/footer, don't
set the page style on the previous paragraph directly, rather update the
"next style" of the already set page style. (This is safe, as we never
reuse the same Writer page style for multiple Word sections.)
Change-Id: Iede196b864af5123c5637f82432ed6e0f7e7241a
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/86870
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Tested-by: Jenkins
(cherry picked from commit 9a50e8f2bcde95233e4b38707c521ada90fcd6af)
-rw-r--r-- | sw/qa/extras/ooxmlexport/data/cont-sect-break-header-footer.docx | bin | 0 -> 18294 bytes | |||
-rw-r--r-- | sw/qa/extras/ooxmlexport/ooxmlexport14.cxx | 26 | ||||
-rw-r--r-- | writerfilter/source/dmapper/PropertyMap.cxx | 25 |
3 files changed, 50 insertions, 1 deletions
diff --git a/sw/qa/extras/ooxmlexport/data/cont-sect-break-header-footer.docx b/sw/qa/extras/ooxmlexport/data/cont-sect-break-header-footer.docx Binary files differnew file mode 100644 index 000000000000..61c18298d083 --- /dev/null +++ b/sw/qa/extras/ooxmlexport/data/cont-sect-break-header-footer.docx diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx index 375c6d874021..445f245d0160 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx @@ -339,6 +339,32 @@ DECLARE_OOXMLEXPORT_TEST(testHyphenationAuto, "hyphenation.odt") assertXPath(pXmlStyles, "/w:styles/w:docDefaults/w:pPrDefault/w:pPr/w:suppressAutoHyphens", "val", "true"); } +DECLARE_OOXMLIMPORT_TEST(testContSectBreakHeaderFooter, "cont-sect-break-header-footer.docx") +{ + // Load a document with a continuous section break on page 2. + CPPUNIT_ASSERT_EQUAL(OUString("First page header, section 1"), + parseDump("/root/page[1]/header/txt/text()")); + CPPUNIT_ASSERT_EQUAL(OUString("First page footer, section 1"), + parseDump("/root/page[1]/footer/txt/text()")); + // Make sure the header stays like this; if we naively just update the page style name of the + // first para on page 2, then this would be 'Header, section 2', which is incorrect. + CPPUNIT_ASSERT_EQUAL(OUString("First page header, section 2"), + parseDump("/root/page[2]/header/txt/text()")); + CPPUNIT_ASSERT_EQUAL(OUString("First page footer, section 2"), + parseDump("/root/page[2]/footer/txt/text()")); + // This is inherited from page 2. + CPPUNIT_ASSERT_EQUAL(OUString("Header, section 2"), + parseDump("/root/page[3]/header/txt/text()")); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 1 + // - Actual : 0 + // - xpath should match exactly 1 node + // i.e. the footer had no text (inherited from page 2), while the correct behavior is to provide + // the own footer text. + CPPUNIT_ASSERT_EQUAL(OUString("Footer, section 3"), + parseDump("/root/page[3]/footer/txt/text()")); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerfilter/source/dmapper/PropertyMap.cxx b/writerfilter/source/dmapper/PropertyMap.cxx index fbc471415b4c..2d085b5775dd 100644 --- a/writerfilter/source/dmapper/PropertyMap.cxx +++ b/writerfilter/source/dmapper/PropertyMap.cxx @@ -1457,9 +1457,11 @@ void SectionPropertyMap::CloseSectionGroup( DomainMapper_Impl& rDM_Impl ) } } } + uno::Reference<text::XParagraphCursor> const xPCursor(xCursor, + uno::UNO_QUERY_THROW); + float fCharHeight = 0; if (!isFound) { // HACK: try the last paragraph of the previous section - uno::Reference<text::XParagraphCursor> const xPCursor(xCursor, uno::UNO_QUERY_THROW); xPCursor->gotoPreviousParagraph(false); uno::Reference<beans::XPropertySet> const xPSCursor(xCursor, uno::UNO_QUERY_THROW); style::BreakType bt; @@ -1468,6 +1470,27 @@ void SectionPropertyMap::CloseSectionGroup( DomainMapper_Impl& rDM_Impl ) { xPSCursor->setPropertyValue(getPropertyName(PROP_PAGE_DESC_NAME), uno::makeAny(m_sFollowPageStyleName)); + isFound = true; + } + else + { + xPSCursor->getPropertyValue("CharHeight") >>= fCharHeight; + } + } + if (!isFound && fCharHeight <= 1.0) + { + // If still not found, see if the last paragraph is ~invisible, and work with + // the last-in-practice paragraph. + xPCursor->gotoPreviousParagraph(false); + uno::Reference<beans::XPropertySet> xPropertySet(xCursor, uno::UNO_QUERY_THROW); + OUString aPageDescName; + if ((xPropertySet->getPropertyValue("PageDescName") >>= aPageDescName) + && !aPageDescName.isEmpty()) + { + uno::Reference<beans::XPropertySet> xPageStyle( + rDM_Impl.GetPageStyles()->getByName(aPageDescName), uno::UNO_QUERY); + xPageStyle->setPropertyValue("FollowStyle", + uno::makeAny(m_sFollowPageStyleName)); } } } |