diff options
-rw-r--r-- | sw/inc/pagedesc.hxx | 6 | ||||
-rw-r--r-- | sw/qa/extras/ooxmlexport/ooxmlexport10.cxx | 5 | ||||
-rw-r--r-- | sw/qa/extras/ooxmlexport/ooxmlexport14.cxx | 3 | ||||
-rw-r--r-- | sw/qa/extras/ooxmlimport/ooxmlimport.cxx | 6 | ||||
-rw-r--r-- | sw/qa/extras/uiwriter/uiwriter.cxx | 4 | ||||
-rw-r--r-- | sw/qa/uitest/data/TestHiddenHeadersFooters.docx | bin | 0 -> 18063 bytes | |||
-rw-r--r-- | sw/qa/uitest/writer_tests7/tdf141158.py | 47 | ||||
-rw-r--r-- | sw/source/core/doc/docdesc.cxx | 30 | ||||
-rw-r--r-- | sw/source/core/doc/docfmt.cxx | 11 | ||||
-rw-r--r-- | sw/source/core/layout/pagedesc.cxx | 96 | ||||
-rw-r--r-- | sw/source/core/unocore/unostyle.cxx | 32 | ||||
-rw-r--r-- | writerfilter/source/dmapper/DomainMapper_Impl.cxx | 24 |
12 files changed, 247 insertions, 17 deletions
diff --git a/sw/inc/pagedesc.hxx b/sw/inc/pagedesc.hxx index 0d29eb0ca6e3..4178361349d6 100644 --- a/sw/inc/pagedesc.hxx +++ b/sw/inc/pagedesc.hxx @@ -223,6 +223,12 @@ public: /// Used to restore hidden header/footer formats. const SwFrameFormat* GetStashedFrameFormat(bool bHeader, bool bLeft, bool bFirst) const; + /// Checks if the pagedescriptor has a stashed format according to the parameters or not. + bool HasStashedFormat(bool bHeader, bool bLeft, bool bFirst); + + /// Gives the feature of removing the stashed format by hand if it is neccessarry. + void RemoveStashedFormat(bool bHeader, bool bLeft, bool bFirst); + /// Same as WriteUseOn(), but the >= HeaderShare part of the bitfield is not modified. inline void SetUseOn( UseOnPage eNew ); inline UseOnPage GetUseOn() const; diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport10.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport10.cxx index c33f99cb4322..ba6a6a6a98e2 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport10.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport10.cxx @@ -688,7 +688,9 @@ DECLARE_OOXMLEXPORT_TEST(testBnc875718, "bnc875718.docx") // is not SwXBodyText but rather SwXHeadFootText uno::Reference<text::XTextFramesSupplier> xTextFramesSupplier(mxComponent, uno::UNO_QUERY); uno::Reference<container::XIndexAccess> xIndexAccess(xTextFramesSupplier->getTextFrames(), uno::UNO_QUERY); - for( int i = 0; + // The sample bugdoc has 3 footer.xml and has a textframe in each. The first one is hidden + // and it has no text in its anchored text range: it is anchored to body text. Ignoring... + for( int i = 1; i < xIndexAccess->getCount(); ++i ) { @@ -700,6 +702,7 @@ DECLARE_OOXMLEXPORT_TEST(testBnc875718, "bnc875718.docx") // Also check that the footer contents are not in the body text. uno::Reference<text::XTextDocument> textDocument(mxComponent, uno::UNO_QUERY); uno::Reference<text::XText> text = textDocument->getText(); + CPPUNIT_ASSERT(text); //Do not crash on empty content CPPUNIT_ASSERT_EQUAL( OUString( "Text" ), text->getString()); } diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx index cd3ca2f39e46..951a4d8650f2 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx @@ -670,7 +670,8 @@ DECLARE_OOXMLEXPORT_TEST(testTdf130167_spilloverHeaderShape, "testTdf130167_spil uno::Reference<container::XIndexAccess> xNameAccess( xTextGraphicObjectsSupplier->getGraphicObjects(), uno::UNO_QUERY); // graphics from discarded headers were being added to the text body. Reduced from 5 to 2 shapes overall. - CPPUNIT_ASSERT(xNameAccess->getCount() < 4); + // CPPUNIT_ASSERT(xNameAccess->getCount() <= 4); -> What about hidden headers? + CPPUNIT_ASSERT_LESS(sal_Int32(6), xNameAccess->getCount()); } DECLARE_OOXMLEXPORT_TEST(testTdf124986, "tdf124986.docx") diff --git a/sw/qa/extras/ooxmlimport/ooxmlimport.cxx b/sw/qa/extras/ooxmlimport/ooxmlimport.cxx index 216fb0de07c0..59a2688232c8 100644 --- a/sw/qa/extras/ooxmlimport/ooxmlimport.cxx +++ b/sw/qa/extras/ooxmlimport/ooxmlimport.cxx @@ -564,10 +564,10 @@ DECLARE_OOXMLIMPORT_TEST(testN779627, "n779627.docx") sal_Int32(9), nLeftMargin); /* - * Another problem tested with this document is the unnecessary loading of the shapes - * anchored to a discarded header or footer + * Another problem tested with this document is the loading of the shapes + * anchored to a hidden header or footer */ - CPPUNIT_ASSERT_EQUAL(0, getShapes()); + CPPUNIT_ASSERT_EQUAL(2, getShapes()); } DECLARE_OOXMLIMPORT_TEST(testN779627b, "n779627b.docx") diff --git a/sw/qa/extras/uiwriter/uiwriter.cxx b/sw/qa/extras/uiwriter/uiwriter.cxx index e47594a27b42..f56cf50d328d 100644 --- a/sw/qa/extras/uiwriter/uiwriter.cxx +++ b/sw/qa/extras/uiwriter/uiwriter.cxx @@ -5055,7 +5055,9 @@ void SwUiWriterTest::testTdf92648() SwDoc* pDoc = createDoc("tdf92648.docx"); SdrPage* pPage = pDoc->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0); // Make sure we have ten draw shapes. - CPPUNIT_ASSERT_EQUAL(sal_Int32(10), SwTextBoxHelper::getCount(pPage)); + // Yes, we have if the left/right pages have different header/footer, + // but if not we have only nine of them: + CPPUNIT_ASSERT_EQUAL(sal_Int32(9), SwTextBoxHelper::getCount(pPage)); // and the text boxes haven't got zero height sal_Int32 nCount = 0; for (const SwFrameFormat* pFormat : *pDoc->GetSpzFrameFormats()) diff --git a/sw/qa/uitest/data/TestHiddenHeadersFooters.docx b/sw/qa/uitest/data/TestHiddenHeadersFooters.docx Binary files differnew file mode 100644 index 000000000000..f33482a93ba1 --- /dev/null +++ b/sw/qa/uitest/data/TestHiddenHeadersFooters.docx diff --git a/sw/qa/uitest/writer_tests7/tdf141158.py b/sw/qa/uitest/writer_tests7/tdf141158.py new file mode 100644 index 000000000000..906035e37e89 --- /dev/null +++ b/sw/qa/uitest/writer_tests7/tdf141158.py @@ -0,0 +1,47 @@ +# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*- + +from uitest.framework import UITestCase +from libreoffice.uno.propertyvalue import mkPropertyValues +from uitest.uihelper.common import get_state_as_dict +import importlib +import pathlib +import org.libreoffice.unotest +from uitest.uihelper.common import select_pos +import time + +def get_url_for_data_file(file_name): + return pathlib.Path(org.libreoffice.unotest.makeCopyFromTDOC(file_name)).as_uri() + + +class TestTdf141158(UITestCase): + def test_tdf141158(self): + # load the desired bugdoc + self.ui_test.load_file(get_url_for_data_file("TestHiddenHeadersFooters.docx")) + xWriterDoc = self.xUITest.getTopFocusWindow() + xWriterEdit = xWriterDoc.getChild("writer_edit") + document = self.ui_test.get_component() + # open the page styles dialog and select the headers tab + self.xUITest.executeCommand(".uno:PageStyleName") + TemplateDialog8 = self.xUITest.getTopFocusWindow() + xTabs = TemplateDialog8.getChild("tabcontrol") + select_pos(xTabs, "4") + # make the same left right page header state to off and apply the setting + checkSameLR = TemplateDialog8.getChild("checkSameLR") + checkSameLR.executeAction("CLICK",tuple()) + ok = TemplateDialog8.getChild("ok") + self.ui_test.close_dialog_through_button(ok) + time.sleep(1) + # go to the left header + xWriterEdit.executeAction("GOTO", mkPropertyValues({"PAGE": "2"})) + self.xUITest.executeCommand(".uno:JumpToHeader") + # get the text of the header + xPageSytle = document.getStyleFamilies().getByIndex(2) + xHeaderText = xPageSytle.getByIndex(0).HeaderText.String + xHeaderLeftText = xPageSytle.getByIndex(0).HeaderTextLeft.String + # without the fix in place it was "Right Header" (lost hidden left header), + # with the fix it should pass... + self.assertEqual("Left Header", xHeaderLeftText) + time.sleep(1) + self.ui_test.close_doc() + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/sw/source/core/doc/docdesc.cxx b/sw/source/core/doc/docdesc.cxx index 8450691eea9c..561d828d839e 100644 --- a/sw/source/core/doc/docdesc.cxx +++ b/sw/source/core/doc/docdesc.cxx @@ -400,11 +400,11 @@ void SwDoc::ChgPageDesc( size_t i, const SwPageDesc &rChged ) const bool bStashLeftHead = !rDesc.IsHeaderShared() && rChged.IsHeaderShared(); const bool bStashFirstMasterHead = !rDesc.IsFirstShared() && rChged.IsFirstShared(); const bool bStashFirstLeftHead = (!rDesc.IsHeaderShared() && rChged.IsHeaderShared()) || (!rDesc.IsFirstShared() && rChged.IsFirstShared()); - if (bStashLeftHead && rLeftHead.GetRegisteredIn()) + if (bStashLeftHead && rLeftHead.GetRegisteredIn() && !rDesc.HasStashedFormat(true, true, false)) rDesc.StashFrameFormat(rChged.GetLeft(), true, true, false); - if (bStashFirstMasterHead && rFirstMasterHead.GetRegisteredIn()) + if (bStashFirstMasterHead && rFirstMasterHead.GetRegisteredIn() && !rDesc.HasStashedFormat(true, false, true)) rDesc.StashFrameFormat(rChged.GetFirstMaster(), true, false, true); - if (bStashFirstLeftHead && rFirstLeftHead.GetRegisteredIn()) + if (bStashFirstLeftHead && rFirstLeftHead.GetRegisteredIn() && !rDesc.HasStashedFormat(true, true, true)) rDesc.StashFrameFormat(rChged.GetFirstLeft(), true, true, true); // Stash footer formats as needed. @@ -414,11 +414,11 @@ void SwDoc::ChgPageDesc( size_t i, const SwPageDesc &rChged ) const bool bStashLeftFoot = !rDesc.IsFooterShared() && rChged.IsFooterShared(); const bool bStashFirstMasterFoot = !rDesc.IsFirstShared() && rChged.IsFirstShared(); const bool bStashFirstLeftFoot = (!rDesc.IsFooterShared() && rChged.IsFooterShared()) || (!rDesc.IsFirstShared() && rChged.IsFirstShared()); - if (bStashLeftFoot && rLeftFoot.GetRegisteredIn()) + if (bStashLeftFoot && rLeftFoot.GetRegisteredIn() && !rDesc.HasStashedFormat(false, true, false)) rDesc.StashFrameFormat(rChged.GetLeft(), false, true, false); - if (bStashFirstMasterFoot && rFirstMasterFoot.GetRegisteredIn()) + if (bStashFirstMasterFoot && rFirstMasterFoot.GetRegisteredIn() && !rDesc.HasStashedFormat(false, false, true)) rDesc.StashFrameFormat(rChged.GetFirstMaster(), false, false, true); - if (bStashFirstLeftFoot && rFirstLeftFoot.GetRegisteredIn()) + if (bStashFirstLeftFoot && rFirstLeftFoot.GetRegisteredIn() && !rDesc.HasStashedFormat(false, true, true)) rDesc.StashFrameFormat(rChged.GetFirstLeft(), false, true, true); GetIDocumentUndoRedo().AppendUndo(std::make_unique<SwUndoPageDesc>(rDesc, rChged, this)); @@ -474,6 +474,15 @@ void SwDoc::ChgPageDesc( size_t i, const SwPageDesc &rChged ) CopyMasterHeader(rChged, pStashedFirstMasterFormat ? pStashedFirstMasterFormat->GetHeader() : rMasterHead, rDesc, false, true); // Copy first master CopyMasterHeader(rChged, pStashedFirstLeftFormat ? pStashedFirstLeftFormat->GetHeader() : rMasterHead, rDesc, true, true); // Copy first left + if (pStashedLeftFormat) + rDesc.RemoveStashedFormat(true, true, false); + + if (pStashedFirstMasterFormat) + rDesc.RemoveStashedFormat(true, false, true); + + if (pStashedFirstLeftFormat) + rDesc.RemoveStashedFormat(true, true, true); + rDesc.ChgHeaderShare( rChged.IsHeaderShared() ); // Synch Footer. @@ -489,6 +498,15 @@ void SwDoc::ChgPageDesc( size_t i, const SwPageDesc &rChged ) CopyMasterFooter(rChged, pStashedFirstMasterFoot ? pStashedFirstMasterFoot->GetFooter() : rMasterFoot, rDesc, false, true); // Copy first master CopyMasterFooter(rChged, pStashedFirstLeftFoot ? pStashedFirstLeftFoot->GetFooter() : rMasterFoot, rDesc, true, true); // Copy first left + if (pStashedLeftFormat) + rDesc.RemoveStashedFormat(false, true, false); + + if (pStashedFirstMasterFoot) + rDesc.RemoveStashedFormat(false, false, true); + + if (pStashedFirstLeftFoot) + rDesc.RemoveStashedFormat(false, true, true); + rDesc.ChgFooterShare( rChged.IsFooterShared() ); // there is just one first shared flag for both header and footer? rDesc.ChgFirstShare( rChged.IsFirstShared() ); diff --git a/sw/source/core/doc/docfmt.cxx b/sw/source/core/doc/docfmt.cxx index a552585df6ab..77df6303c053 100644 --- a/sw/source/core/doc/docfmt.cxx +++ b/sw/source/core/doc/docfmt.cxx @@ -1523,6 +1523,17 @@ void SwDoc::CopyPageDesc( const SwPageDesc& rSrcDesc, SwPageDesc& rDstDesc, rDstDesc.GetFirstMaster().CallSwClientNotify(aHint); rDstDesc.GetFirstLeft().CallSwClientNotify(aHint); } + + // Copy the stashed formats as well between the page descriptors... + for (bool bFirst : { true, false }) + for (bool bLeft : { true, false }) + for (bool bHeader : { true, false }) + { + if (!bLeft && !bFirst) + continue; + if (auto pStashedFormat = rSrcDesc.GetStashedFrameFormat(bHeader, bLeft, bFirst)) + rDstDesc.StashFrameFormat(*pStashedFormat, bHeader, bLeft, bFirst); + } } void SwDoc::ReplaceStyles( const SwDoc& rSource, bool bIncludePageStyles ) diff --git a/sw/source/core/layout/pagedesc.cxx b/sw/source/core/layout/pagedesc.cxx index 8b8b5282abbf..c5c9c31ab7b9 100644 --- a/sw/source/core/layout/pagedesc.cxx +++ b/sw/source/core/layout/pagedesc.cxx @@ -436,7 +436,9 @@ void SwPageDesc::StashFrameFormat(const SwFrameFormat& rFormat, bool bHeader, bo } else { - SAL_WARN("sw", "Stashing the right page header/footer is pointless."); + SAL_WARN( + "sw", + "SwPageDesc::StashFrameFormat: Stashing the right page header/footer is pointless."); } } @@ -459,17 +461,101 @@ const SwFrameFormat* SwPageDesc::GetStashedFrameFormat(bool bHeader, bool bLeft, if (pFormat) { - const SwFrameFormat* retVal = pFormat->get(); - pFormat->reset(); - return retVal; + return pFormat->get(); } else { - SAL_WARN("sw", "Right page format is never stashed."); + SAL_WARN("sw", "SwPageDesc::GetStashedFrameFormat: Right page format is never stashed."); return nullptr; } } +bool SwPageDesc::HasStashedFormat(bool bHeader, bool bLeft, bool bFirst) +{ + if (bHeader) + { + if (bLeft && !bFirst) + { + return m_aStashedHeader.m_pStashedLeft != nullptr; + } + else if (!bLeft && bFirst) + { + return m_aStashedHeader.m_pStashedFirst != nullptr; + } + else if (bLeft && bFirst) + { + return m_aStashedHeader.m_pStashedFirstLeft != nullptr; + } + else + { + SAL_WARN("sw", "SwPageDesc::HasStashedFormat: Right page format is never stashed."); + return false; + } + } + else + { + if (bLeft && !bFirst) + { + return m_aStashedFooter.m_pStashedLeft != nullptr; + } + else if (!bLeft && bFirst) + { + return m_aStashedFooter.m_pStashedFirst != nullptr; + } + else if (bLeft && bFirst) + { + return m_aStashedFooter.m_pStashedFirstLeft != nullptr; + } + else + { + SAL_WARN("sw", "SwPageDesc::HasStashedFormat: Right page format is never stashed."); + return false; + } + } +} + +void SwPageDesc::RemoveStashedFormat(bool bHeader, bool bLeft, bool bFirst) +{ + if (bHeader) + { + if (bLeft && !bFirst) + { + m_aStashedHeader.m_pStashedLeft.reset(); + } + else if (!bLeft && bFirst) + { + m_aStashedHeader.m_pStashedFirst.reset(); + } + else if (bLeft && bFirst) + { + m_aStashedHeader.m_pStashedFirstLeft.reset(); + } + else + { + SAL_WARN("sw", "SwPageDesc::RemoveStashedFormat: Right page format is never stashed."); + } + } + else + { + if (bLeft && !bFirst) + { + m_aStashedFooter.m_pStashedLeft.reset(); + } + else if (!bLeft && bFirst) + { + m_aStashedFooter.m_pStashedFirst.reset(); + } + else if (bLeft && bFirst) + { + m_aStashedFooter.m_pStashedFirstLeft.reset(); + } + else + { + SAL_WARN("sw", "SwPageDesc::RemoveStashedFormat: Right page format is never stashed."); + } + } +} + // Page styles static const char* STR_POOLPAGE[] = { diff --git a/sw/source/core/unocore/unostyle.cxx b/sw/source/core/unocore/unostyle.cxx index 9b3dc09f8e7a..a695cfdafa47 100644 --- a/sw/source/core/unocore/unostyle.cxx +++ b/sw/source/core/unocore/unostyle.cxx @@ -3300,6 +3300,38 @@ void SwXPageStyle::setPropertyValue(const OUString& rPropertyName, const uno::An SolarMutexGuard aGuard; const uno::Sequence<OUString> aProperties(&rPropertyName, 1); const uno::Sequence<uno::Any> aValues(&rValue, 1); + + // Trick: if the Domain Mapper changes the props of shared header/footer, + // store the old ones in time for later use. + const bool bIsHeader = rPropertyName == UNO_NAME_HEADER_IS_SHARED; + const bool bIsFooter = rPropertyName == UNO_NAME_FOOTER_IS_SHARED; + if ((bIsFooter || bIsHeader) && rValue == uno::Any(true)) + { + // Find the matching page descriptor + for (size_t i = 0; i < GetDoc()->GetPageDescCnt(); i++) + { + auto pPageDesc = &GetDoc()->GetPageDesc(i); + // If we have the right page descriptor stash the neccessary formats in import time. + if (pPageDesc->GetName() == GetStyleName()) + { + auto pLeftHeader = pPageDesc->GetLeft().GetHeader().GetHeaderFormat(); + if (bIsHeader && pLeftHeader) + { + pPageDesc->StashFrameFormat(pPageDesc->GetLeft(), true, true, false); + pPageDesc->StashFrameFormat(pPageDesc->GetFirstMaster(), true, false, true); + pPageDesc->StashFrameFormat(pPageDesc->GetFirstLeft(), true, true, true); + } + auto pLeftFooter = pPageDesc->GetLeft().GetFooter().GetFooterFormat(); + if (bIsFooter && pLeftFooter) + { + pPageDesc->StashFrameFormat(pPageDesc->GetLeft(), false, true, false); + pPageDesc->StashFrameFormat(pPageDesc->GetFirstMaster(), false, false, true); + pPageDesc->StashFrameFormat(pPageDesc->GetFirstLeft(), false, true, true); + } + } + } + } + // And set the props... as we did it before. SetPropertyValues_Impl(aProperties, aValues); } diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx index d83ed06526f8..44ab9fdf3b36 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx @@ -2587,6 +2587,30 @@ void DomainMapper_Impl::PushPageHeaderFooter(bool bHeader, SectionPropertyMap::P : xText->createTextCursorByRange(xText->getStart()))); m_bDiscardHeaderFooter = false; // set only on success! } + // If we have *hidden* header footer + else if (bLeft && !GetSettingsTable()->GetEvenAndOddHeaders()) + { + bool bIsShared; + // Turn on the headers + xPageStyle->setPropertyValue(getPropertyName(ePropIsOn), uno::makeAny(true)); + // Store the state of the previous state of shared prop + xPageStyle->getPropertyValue(getPropertyName(ePropShared)) >>= bIsShared; + // Turn on the shared prop in order to save the headers/footers in time + xPageStyle->setPropertyValue(getPropertyName(ePropShared), uno::makeAny(false)); + // Add the content of the headers footers to the doc + uno::Reference<text::XText> xText; + xPageStyle->getPropertyValue(getPropertyName(bLeft ? ePropTextLeft : ePropText)) + >>= xText; + + m_aTextAppendStack.push( + TextAppendContext(uno::Reference<text::XTextAppend>(xText, uno::UNO_QUERY_THROW), + m_bIsNewDoc ? uno::Reference<text::XTextCursor>() + : xText->createTextCursorByRange(xText->getStart()))); + m_bDiscardHeaderFooter = false; // set only on success! + // Restore the original state of the shared prop after we stored the neccessary values. + xPageStyle->setPropertyValue(getPropertyName(ePropShared), uno::makeAny(bIsShared)); + } + } catch( const uno::Exception& ) { |