include/svx/annotation/Annotation.hxx | 29 ++---- svx/source/annotation/Annotation.cxx | 151 ++++++++++++++++++++-------------- 2 files changed, 104 insertions(+), 76 deletions(-)
New commits: commit dedf0c1bcbbf4fc9e2df3acd69906a01da1737e7 Author: Caolán McNamara <caolan.mcnam...@collabora.com> AuthorDate: Sun Sep 7 21:27:51 2025 +0100 Commit: Caolán McNamara <caolan.mcnam...@collabora.com> CommitDate: Fri Sep 12 09:37:43 2025 +0200 cid#1659918 Data race condition and cid#1660133 Data race condition cid#1660238 Data race condition etc. Change-Id: Ic0278e430c62abda92e8ce0e590a4726a4488b30 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/190791 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com> diff --git a/include/svx/annotation/Annotation.hxx b/include/svx/annotation/Annotation.hxx index 56944c97a20a..e0180d72d431 100644 --- a/include/svx/annotation/Annotation.hxx +++ b/include/svx/annotation/Annotation.hxx @@ -89,9 +89,6 @@ struct SVXCORE_DLLPUBLIC AnnotationData OUString m_Initials; css::util::DateTime m_DateTime; OUString m_Text; - - void get(Annotation& rAnnotation); - void set(Annotation& rAnnotation); }; /** Annotation object, responsible for handling of the annotation. @@ -103,6 +100,11 @@ class SVXCORE_DLLPUBLIC Annotation : public ::comphelper::WeakComponentImplHelper<css::office::XAnnotation>, public ::cppu::PropertySetMixin<css::office::XAnnotation> { +private: + css::uno::Reference<css::text::XText> getTextRangeImpl(const std::unique_lock<std::mutex>& g); + OUString GetTextImpl(const std::unique_lock<std::mutex>& g); + void SetTextImpl(OUString const& rText, const std::unique_lock<std::mutex>& g); + protected: SdrPage* mpPage; UniqueID maUniqueID; @@ -135,20 +137,8 @@ public: } // Changes without triggering notification broadcast - const css::geometry::RealPoint2D& GetPosition() const { return m_Position; } - void SetPosition(const css::geometry::RealPoint2D& rValue) { m_Position = rValue; } - - const css::geometry::RealSize2D& GetSize() const { return m_Size; } - void SetSize(const css::geometry::RealSize2D& rValue) { m_Size = rValue; } - - const OUString& GetAuthor() const { return m_Author; } - void SetAuthor(const OUString& rValue) { m_Author = rValue; } - - const OUString& GetInitials() const { return m_Initials; } - void SetInitials(const OUString& rValue) { m_Initials = rValue; } - - const css::util::DateTime& GetDateTime() const { return m_DateTime; } - void SetDateTime(const css::util::DateTime& rValue) { m_DateTime = rValue; } + void SetPosition(const css::geometry::RealPoint2D& rValue); + void SetSize(const css::geometry::RealSize2D& rValue); virtual css::uno::Reference<css::text::XText> SAL_CALL getTextRange() override; @@ -160,6 +150,11 @@ public: OUString GetText(); void SetText(OUString const& rText); + + OString ToJSON(CommentNotificationType nType); + void toData(AnnotationData& rData); + void fromData(const AnnotationData& rData); + const rtl::Reference<sdr::annotation::TextApiObject>& getTextApiObject() { return m_TextRange; } SdrModel* GetModel() const; diff --git a/svx/source/annotation/Annotation.cxx b/svx/source/annotation/Annotation.cxx index af516a20b535..0d6caa17d4ee 100644 --- a/svx/source/annotation/Annotation.cxx +++ b/svx/source/annotation/Annotation.cxx @@ -22,42 +22,6 @@ namespace sdr::annotation { namespace { -OString lcl_LOKGetCommentPayload(CommentNotificationType nType, Annotation& rAnnotation) -{ - tools::JsonWriter aJsonWriter; - { - auto aCommentNode = aJsonWriter.startNode("comment"); - - aJsonWriter.put( - "action", - (nType == CommentNotificationType::Add - ? "Add" - : (nType == CommentNotificationType::Remove - ? "Remove" - : (nType == CommentNotificationType::Modify ? "Modify" : "???")))); - aJsonWriter.put("id", rAnnotation.GetId()); - - if (nType != CommentNotificationType::Remove) - { - aJsonWriter.put("id", rAnnotation.GetId()); - aJsonWriter.put("author", rAnnotation.GetAuthor()); - aJsonWriter.put("dateTime", utl::toISO8601(rAnnotation.GetDateTime())); - aJsonWriter.put("text", rAnnotation.GetText()); - SdrPage const* pPage = rAnnotation.getPage(); - aJsonWriter.put("parthash", pPage ? OString::number(pPage->GetUniqueID()) : OString()); - geometry::RealPoint2D const aPoint = rAnnotation.GetPosition(); - geometry::RealSize2D const aSize = rAnnotation.GetSize(); - tools::Rectangle aRectangle( - Point(std::round(o3tl::toTwips(aPoint.X, o3tl::Length::mm)), - std::round(o3tl::toTwips(aPoint.Y, o3tl::Length::mm))), - Size(std::round(o3tl::toTwips(aSize.Width, o3tl::Length::mm)), - std::round(o3tl::toTwips(aSize.Height, o3tl::Length::mm)))); - aJsonWriter.put("rectangle", aRectangle.toString()); - } - } - return aJsonWriter.finishAndGetAsOString(); -} - /** Undo/redo a modification of an annotation - change of annotation data */ class UndoAnnotation : public SdrUndoAction { @@ -66,20 +30,20 @@ public: : SdrUndoAction(*rAnnotation.GetModel()) , mrAnnotation(rAnnotation) { - maUndoData.get(mrAnnotation); + mrAnnotation.toData(maUndoData); } void Undo() override { - maRedoData.get(mrAnnotation); - maUndoData.set(mrAnnotation); + mrAnnotation.toData(maRedoData); + mrAnnotation.fromData(maUndoData); LOKCommentNotifyAll(CommentNotificationType::Modify, mrAnnotation); } void Redo() override { - maUndoData.get(mrAnnotation); - maRedoData.set(mrAnnotation); + mrAnnotation.toData(maUndoData); + mrAnnotation.fromData(maRedoData); LOKCommentNotifyAll(CommentNotificationType::Modify, mrAnnotation); } @@ -98,7 +62,7 @@ void LOKCommentNotify(CommentNotificationType nType, const SfxViewShell* pViewSh if (!comphelper::LibreOfficeKit::isActive() || comphelper::LibreOfficeKit::isTiledAnnotations()) return; - OString aPayload = lcl_LOKGetCommentPayload(nType, rAnnotation); + OString aPayload = rAnnotation.ToJSON(nType); pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_COMMENT, aPayload); } @@ -108,7 +72,7 @@ void LOKCommentNotifyAll(CommentNotificationType nType, Annotation& rAnnotation) if (!comphelper::LibreOfficeKit::isActive() || comphelper::LibreOfficeKit::isTiledAnnotations()) return; - OString aPayload = lcl_LOKGetCommentPayload(nType, rAnnotation); + OString aPayload = rAnnotation.ToJSON(nType); const SfxViewShell* pViewShell = SfxViewShell::GetFirst(); while (pViewShell) @@ -118,24 +82,26 @@ void LOKCommentNotifyAll(CommentNotificationType nType, Annotation& rAnnotation) } } -void AnnotationData::get(Annotation& rAnnotation) +void Annotation::toData(AnnotationData& rData) { - m_Position = rAnnotation.GetPosition(); - m_Size = rAnnotation.GetSize(); - m_Author = rAnnotation.GetAuthor(); - m_Initials = rAnnotation.GetInitials(); - m_DateTime = rAnnotation.GetDateTime(); - m_Text = rAnnotation.GetText(); + std::unique_lock g(m_aMutex); + rData.m_Position = m_Position; + rData.m_Size = m_Size; + rData.m_Author = m_Author; + rData.m_Initials = m_Initials; + rData.m_DateTime = m_DateTime; + rData.m_Text = GetTextImpl(g); } -void AnnotationData::set(Annotation& rAnnotation) +void Annotation::fromData(const AnnotationData& rData) { - rAnnotation.SetPosition(m_Position); - rAnnotation.SetSize(m_Size); - rAnnotation.SetAuthor(m_Author); - rAnnotation.SetInitials(m_Initials); - rAnnotation.SetDateTime(m_DateTime); - rAnnotation.SetText(m_Text); + std::unique_lock g(m_aMutex); + m_Position = rData.m_Position; + m_Size = rData.m_Size; + m_Author = rData.m_Author; + m_Initials = rData.m_Initials; + m_DateTime = rData.m_DateTime; + SetTextImpl(rData.m_Text, g); } Annotation::Annotation(const css::uno::Reference<css::uno::XComponentContext>& rxContext, @@ -163,19 +129,36 @@ std::unique_ptr<SdrUndoAction> Annotation::createUndoAnnotation() OUString Annotation::GetText() { - uno::Reference<text::XText> xText(getTextRange()); + std::unique_lock g(m_aMutex); + return GetTextImpl(g); +} + +OUString Annotation::GetTextImpl(const std::unique_lock<std::mutex>& g) +{ + uno::Reference<text::XText> xText(getTextRangeImpl(g)); return xText->getString(); } void Annotation::SetText(OUString const& rText) { - uno::Reference<text::XText> xText(getTextRange()); + std::unique_lock g(m_aMutex); + SetTextImpl(rText, g); +} + +void Annotation::SetTextImpl(OUString const& rText, const std::unique_lock<std::mutex>& g) +{ + uno::Reference<text::XText> xText(getTextRangeImpl(g)); return xText->setString(rText); } uno::Reference<text::XText> SAL_CALL Annotation::getTextRange() { std::unique_lock g(m_aMutex); + return getTextRangeImpl(g); +} + +uno::Reference<text::XText> Annotation::getTextRangeImpl(const std::unique_lock<std::mutex>& /*g*/) +{ if (!m_TextRange.is() && mpPage != nullptr) { m_TextRange = sdr::annotation::TextApiObject::create(&mpPage->getSdrModelFromSdrPage()); @@ -183,6 +166,18 @@ uno::Reference<text::XText> SAL_CALL Annotation::getTextRange() return m_TextRange; } +void Annotation::SetPosition(const css::geometry::RealPoint2D& rValue) +{ + std::unique_lock g(m_aMutex); + m_Position = rValue; +} + +void Annotation::SetSize(const css::geometry::RealSize2D& rValue) +{ + std::unique_lock g(m_aMutex); + m_Size = rValue; +} + void Annotation::disposing(std::unique_lock<std::mutex>& /*rGuard*/) { mpPage = nullptr; @@ -210,6 +205,44 @@ SdrObject* Annotation::findAnnotationObject() return nullptr; } +OString Annotation::ToJSON(CommentNotificationType nType) +{ + tools::JsonWriter aJsonWriter; + + { + auto aCommentNode = aJsonWriter.startNode("comment"); + + aJsonWriter.put( + "action", + (nType == CommentNotificationType::Add + ? "Add" + : (nType == CommentNotificationType::Remove + ? "Remove" + : (nType == CommentNotificationType::Modify ? "Modify" : "???")))); + + std::unique_lock g(m_aMutex); + sal_uInt64 id = maUniqueID.getID(); + aJsonWriter.put("id", id); + if (nType != CommentNotificationType::Remove) + { + aJsonWriter.put("id", id); + aJsonWriter.put("author", m_Author); + aJsonWriter.put("dateTime", utl::toISO8601(m_DateTime)); + aJsonWriter.put("text", GetTextImpl(g)); + aJsonWriter.put("parthash", + mpPage ? OString::number(mpPage->GetUniqueID()) : OString()); + tools::Rectangle aRectangle( + Point(std::round(o3tl::toTwips(m_Position.X, o3tl::Length::mm)), + std::round(o3tl::toTwips(m_Position.Y, o3tl::Length::mm))), + Size(std::round(o3tl::toTwips(m_Size.Width, o3tl::Length::mm)), + std::round(o3tl::toTwips(m_Size.Height, o3tl::Length::mm)))); + aJsonWriter.put("rectangle", aRectangle.toString()); + } + } + + return aJsonWriter.finishAndGetAsOString(); +} + } // namespace sdr::annotation /* vim:set shiftwidth=4 softtabstop=4 expandtab: */