include/xmloff/txtimp.hxx | 2 +- sw/inc/doc.hxx | 4 ++++ sw/inc/unoparagraph.hxx | 1 + sw/source/core/doc/doccorr.cxx | 3 ++- sw/source/core/unocore/unoparagraph.cxx | 15 ++++++++++++++- sw/source/filter/xml/xmltbli.cxx | 2 +- xmloff/source/text/txtimp.cxx | 14 +++++++++++++- 7 files changed, 36 insertions(+), 5 deletions(-)
New commits: commit f9b487f44fc8a65febafc5ea713e493369be9445 Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Wed Mar 26 21:13:40 2025 +0500 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Thu Mar 27 07:52:47 2025 +0100 tdf#165918: Avoid bookmarks correction when removing temporary nodes When loading a table, each cell contains an extra node, which is dropped when finalizing the cell. The removal of the node calls SwDoc::CorrAbs, which it turn calls MarkManager::correctMarksAbsolute. The latter looks through all existing bookmarks, checking if they need to be corrected. In documents with lots of tables and lots of bookmarks, the time taken by eack following call to SwDoc::CorrAbs grows quadratically. We know, that these extra nodes in cells do not affect bookmarks, and it is safe to just skip these specific nodes from bookmark correction. This speeds up loading bugdoc by 40% in my testing. Change-Id: I61b587d04c9ae2301d9fef497885fb76c2d3ae74 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/183348 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> diff --git a/include/xmloff/txtimp.hxx b/include/xmloff/txtimp.hxx index ea6515a952d9..c9e9d451afc7 100644 --- a/include/xmloff/txtimp.hxx +++ b/include/xmloff/txtimp.hxx @@ -160,7 +160,7 @@ public: void InsertString( std::u16string_view rChars, bool& rIgnoreLeadingSpace ); // Delete current paragraph - void DeleteParagraph(); + void DeleteParagraph(bool dontCorrectBookmarks = false); void InsertControlCharacter( sal_Int16 nControl ); void InsertTextContent( css::uno::Reference< css::text::XTextContent > const & xContent); diff --git a/sw/inc/doc.hxx b/sw/inc/doc.hxx index 394195589919..cb98f4b532ec 100644 --- a/sw/inc/doc.hxx +++ b/sw/inc/doc.hxx @@ -46,6 +46,7 @@ #include <set> #include <tuple> #include <unordered_map> +#include <utility> #include <vector> namespace editeng { class SvxBorderLine; } @@ -330,6 +331,7 @@ private: bool mbClipBoard : 1; //< TRUE: this document represents the clipboard bool mbColumnSelection : 1; //< TRUE: this content has been created by a column selection (clipboard docs only) bool mbIsPrepareSelAll : 1; + bool mbDontCorrectBookmarks = false; enum MissingDictionary { False = -1, Undefined = 0, True = 1 }; MissingDictionary meDictionaryMissing; @@ -1755,6 +1757,8 @@ public: static bool HasParagraphDirectFormatting(const SwPosition& rPos); + bool SetDontCorrectBookmarks(bool val) { return std::exchange(mbDontCorrectBookmarks, val); } + private: // Copies master header to left / first one, if necessary - used by ChgPageDesc(). void CopyMasterHeader(const SwPageDesc &rChged, const SwFormatHeader &rHead, SwPageDesc &pDesc, bool bLeft, bool bFirst); diff --git a/sw/inc/unoparagraph.hxx b/sw/inc/unoparagraph.hxx index 42572649ded2..13e84825c33f 100644 --- a/sw/inc/unoparagraph.hxx +++ b/sw/inc/unoparagraph.hxx @@ -234,6 +234,7 @@ private: ::comphelper::OInterfaceContainerHelper4<css::lang::XEventListener> m_EventListeners; SfxItemPropertySet const& m_rPropSet; bool m_bIsDescriptor; + bool m_bDeleteWithoutCorrection = false; sal_Int32 m_nSelectionStartPos; sal_Int32 m_nSelectionEndPos; OUString m_sText; diff --git a/sw/source/core/doc/doccorr.cxx b/sw/source/core/doc/doccorr.cxx index 783e1aa2346f..61cad6e1eca4 100644 --- a/sw/source/core/doc/doccorr.cxx +++ b/sw/source/core/doc/doccorr.cxx @@ -179,7 +179,8 @@ void SwDoc::CorrAbs(const SwNode& rOldNode, SwPosition aNewPos(rNewPos); aNewPos.AdjustContent(nOffset); - getIDocumentMarkAccess()->correctMarksAbsolute(rOldNode, rNewPos, nOffset); + if (!mbDontCorrectBookmarks) + getIDocumentMarkAccess()->correctMarksAbsolute(rOldNode, rNewPos, nOffset); // fix redlines { SwRedlineTable& rTable = getIDocumentRedlineAccess().GetRedlineTable(); diff --git a/sw/source/core/unocore/unoparagraph.cxx b/sw/source/core/unocore/unoparagraph.cxx index 9696897e95e9..89a7edbad5c8 100644 --- a/sw/source/core/unocore/unoparagraph.cxx +++ b/sw/source/core/unocore/unoparagraph.cxx @@ -54,6 +54,7 @@ #include <com/sun/star/drawing/BitmapMode.hpp> #include <comphelper/propertyvalue.hxx> +#include <comphelper/scopeguard.hxx> #include <comphelper/sequence.hxx> #include <comphelper/servicehelper.hxx> #include <editeng/unoipset.hxx> @@ -291,6 +292,12 @@ SwXParagraph::setPropertyValue(const OUString& rPropertyName, const uno::Any& rValue) { SolarMutexGuard aGuard; + // See XMLTextImportHelper::DeleteParagraph + if (rPropertyName == "DeleteWithoutCorrection") + { + m_bDeleteWithoutCorrection = true; + return; + } SetPropertyValues_Impl( { rPropertyName }, { rValue } ); } @@ -1182,7 +1189,13 @@ void SAL_CALL SwXParagraph::dispose() if (pTextNode) { SwCursor aCursor( SwPosition( *pTextNode ), nullptr ); - pTextNode->GetDoc().getIDocumentContentOperations().DelFullPara(aCursor); + { + auto& rDoc = pTextNode->GetDoc(); + comphelper::ScopeGuard aGuard2( + [&rDoc, restore = rDoc.SetDontCorrectBookmarks(m_bDeleteWithoutCorrection)]() + { rDoc.SetDontCorrectBookmarks(restore); }); + rDoc.getIDocumentContentOperations().DelFullPara(aCursor); + } lang::EventObject const ev(getXWeak()); std::unique_lock aGuard2(m_Mutex); m_EventListeners.disposeAndClear(aGuard2, ev); diff --git a/sw/source/filter/xml/xmltbli.cxx b/sw/source/filter/xml/xmltbli.cxx index 5d55d355b76b..a64efde0b759 100644 --- a/sw/source/filter/xml/xmltbli.cxx +++ b/sw/source/filter/xml/xmltbli.cxx @@ -586,7 +586,7 @@ void SwXMLTableCellContext_Impl::endFastElement(sal_Int32 ) { if( m_bHasTextContent ) { - GetImport().GetTextImport()->DeleteParagraph(); + GetImport().GetTextImport()->DeleteParagraph(true); if( m_nColRepeat > 1 && m_nColSpan == 1 ) { // The original text is invalid after deleting the last diff --git a/xmloff/source/text/txtimp.cxx b/xmloff/source/text/txtimp.cxx index 43dade94fcca..35ceb8d2898e 100644 --- a/xmloff/source/text/txtimp.cxx +++ b/xmloff/source/text/txtimp.cxx @@ -764,7 +764,7 @@ void XMLTextImportHelper::InsertTextContent( } } -void XMLTextImportHelper::DeleteParagraph() +void XMLTextImportHelper::DeleteParagraph(bool dontCorrectBookmarks) { assert(m_xImpl->m_xText.is()); assert(m_xImpl->m_xCursor.is()); @@ -784,6 +784,18 @@ void XMLTextImportHelper::DeleteParagraph() assert(xComp.is()); if( xComp.is() ) { + if (dontCorrectBookmarks) + { + try + { + // See SwXParagraph::setPropertyValue + if (auto xProps = xComp.query<beans::XPropertySet>()) + xProps->setPropertyValue(u"DeleteWithoutCorrection"_ustr, {}); + } + catch (const beans::UnknownPropertyException&) + { + } + } xComp->dispose(); bDelete = false; }