include/xmloff/txtimp.hxx | 2 +- sw/inc/doc.hxx | 4 ++++ sw/inc/unoparagraph.hxx | 3 +++ 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, 38 insertions(+), 5 deletions(-)
New commits: commit 3ad25e14325aabc84572f7ba097e57436a975754 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 12:12:51 2025 +0500 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 c04e577c6573..46700459321f 100644 --- a/include/xmloff/txtimp.hxx +++ b/include/xmloff/txtimp.hxx @@ -162,7 +162,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 3e3652fab936..fb34700187d2 100644 --- a/sw/inc/doc.hxx +++ b/sw/inc/doc.hxx @@ -47,6 +47,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; @@ -1703,6 +1705,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 cbdfe202a1cb..096b442f8cf6 100644 --- a/sw/inc/unoparagraph.hxx +++ b/sw/inc/unoparagraph.hxx @@ -200,6 +200,9 @@ public: /// tries to return less data, but may return more than just text fields rtl::Reference<SwXTextPortionEnumeration> createTextFieldsEnumeration(); + +private: + bool m_bDeleteWithoutCorrection = false; }; 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 dab5270588e3..9c6a53a34037 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> @@ -359,6 +360,12 @@ SwXParagraph::setPropertyValue(const OUString& rPropertyName, const uno::Any& rValue) { SolarMutexGuard aGuard; + // See XMLTextImportHelper::DeleteParagraph + if (rPropertyName == "DeleteWithoutCorrection") + { + m_bDeleteWithoutCorrection = true; + return; + } m_pImpl->SetPropertyValues_Impl( { rPropertyName }, { rValue } ); } @@ -1254,7 +1261,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_pImpl->m_Mutex); m_pImpl->m_EventListeners.disposeAndClear(aGuard2, ev); diff --git a/sw/source/filter/xml/xmltbli.cxx b/sw/source/filter/xml/xmltbli.cxx index b2d312cad2e5..6b1fb43fd7c6 100644 --- a/sw/source/filter/xml/xmltbli.cxx +++ b/sw/source/filter/xml/xmltbli.cxx @@ -587,7 +587,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 56d21a5196f8..714713e79804 100644 --- a/xmloff/source/text/txtimp.cxx +++ b/xmloff/source/text/txtimp.cxx @@ -766,7 +766,7 @@ void XMLTextImportHelper::InsertTextContent( } } -void XMLTextImportHelper::DeleteParagraph() +void XMLTextImportHelper::DeleteParagraph(bool dontCorrectBookmarks) { assert(m_xImpl->m_xText.is()); assert(m_xImpl->m_xCursor.is()); @@ -786,6 +786,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; }