include/xmloff/xmltoken.hxx | 1 + sw/inc/AnnotationWin.hxx | 1 + sw/inc/docufld.hxx | 10 +++++++++- sw/inc/unoprnms.hxx | 1 + sw/source/core/fields/docufld.cxx | 23 +++++++++++++++++++++-- sw/source/core/inc/unofldmid.h | 1 + sw/source/core/unocore/unofield.cxx | 11 ++++++++++- sw/source/core/unocore/unomap.cxx | 1 + sw/source/uibase/docvw/AnnotationWin.cxx | 6 ++++++ sw/source/uibase/docvw/AnnotationWin2.cxx | 1 + sw/source/uibase/docvw/PostItMgr.cxx | 27 +++++++++++++++++++++++++-- sw/source/uibase/uno/unotxdoc.cxx | 3 +-- xmloff/inc/txtfldi.hxx | 1 + xmloff/source/core/xmltoken.cxx | 1 + xmloff/source/text/txtflde.cxx | 9 +++++++++ xmloff/source/text/txtfldi.cxx | 6 ++++++ xmloff/source/token/tokens.txt | 1 + 17 files changed, 96 insertions(+), 8 deletions(-)
New commits: commit d849504f6d4b9f4b169b2848588cc890a29ac8f9 Author: Gökay Şatır <gokaysa...@gmail.com> AuthorDate: Fri Sep 1 09:49:53 2023 +0300 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Tue Sep 5 14:21:08 2023 +0200 Added parent / child relationship to comments. Adding parent name of a comment into odf file when there is a parent. Signed-off-by: Gökay Şatır <gokaysa...@gmail.com> Change-Id: I08b5ab6eb11adcafcbf3559896d79d41b449b26a Reviewed-on: https://gerrit.libreoffice.org/c/core/+/156391 Reviewed-by: Miklos Vajna <vmik...@collabora.com> Tested-by: Miklos Vajna <vmik...@collabora.com> diff --git a/include/xmloff/xmltoken.hxx b/include/xmloff/xmltoken.hxx index b24f4ec0ce4d..da28c0f81c03 100644 --- a/include/xmloff/xmltoken.hxx +++ b/include/xmloff/xmltoken.hxx @@ -1504,6 +1504,7 @@ namespace xmloff::token { XML_PARAGRAPH_START_MARGIN, XML_PARALLEL, XML_PARAM, + XML_PARENT_NAME, XML_PARENT_STYLE_NAME, XML_PARSE_SQL_STATEMENT, XML_PARSED, diff --git a/sw/inc/AnnotationWin.hxx b/sw/inc/AnnotationWin.hxx index 08b8597a014f..4daa795886d1 100644 --- a/sw/inc/AnnotationWin.hxx +++ b/sw/inc/AnnotationWin.hxx @@ -194,6 +194,7 @@ class SAL_DLLPUBLIC_RTTI SwAnnotationWin final : public InterimItemWindow // Get annotation paraId or generate one if it doesn't exist sal_uInt32 GetParaId(); + sal_uInt32 GetPostItId(); // Used to generate a unique paraId static sal_uInt32 CreateUniqueParaId(); diff --git a/sw/inc/docufld.hxx b/sw/inc/docufld.hxx index 89a5341222db..2f4cb3208ddf 100644 --- a/sw/inc/docufld.hxx +++ b/sw/inc/docufld.hxx @@ -458,6 +458,8 @@ class SW_DLLPUBLIC SwPostItField final : public SwField sal_uInt32 m_nPostItId; sal_uInt32 m_nParentId; sal_uInt32 m_nParaId; + sal_uInt32 m_nParentPostItId; + OUString m_sParentName; /// Parent comment's name. public: static sal_uInt32 s_nLastPostItId; @@ -471,7 +473,9 @@ public: const bool bResolved = false, const sal_uInt32 nPostItId = 0, const sal_uInt32 nParentId = 0, - const sal_uInt32 nParaId = 0); + const sal_uInt32 nParaId = 0, + const sal_uInt32 nParentPostItId = 0, + const OUString aParentName = OUString()); SwPostItField(const SwPostItField&) = delete; SwPostItField* operator=(const SwPostItField&) = delete; @@ -486,7 +490,9 @@ public: tools::Time GetTime() const { return tools::Time(m_aDateTime.GetTime()); } sal_uInt32 GetPostItId() const { return m_nPostItId; } void SetPostItId(const sal_uInt32 nPostItId = 0); + void SetParentPostItId(const sal_uInt32 nParentPostItId = 0); sal_uInt32 GetParentId() const { return m_nParentId; } + sal_uInt32 GetParentPostItId() const { return m_nParentPostItId; } void SetParentId(const sal_uInt32 nParentId); sal_uInt32 GetParaId() const { return m_nParaId; } void SetParaId(const sal_uInt32 nParaId); @@ -502,6 +508,8 @@ public: const OUString& GetInitials() const { return m_sInitials;} void SetName(const OUString& rStr); const OUString& GetName() const { return m_sName;} + const OUString& GetParentName() const { return m_sParentName; } + void SetParentName(const OUString& rStr); const OutlinerParaObject* GetTextObject() const { return mpText ? &*mpText : nullptr;} void SetTextObject( std::optional<OutlinerParaObject> pText ); diff --git a/sw/inc/unoprnms.hxx b/sw/inc/unoprnms.hxx index 8b5328462d7d..d72883efdb9f 100644 --- a/sw/inc/unoprnms.hxx +++ b/sw/inc/unoprnms.hxx @@ -88,6 +88,7 @@ inline constexpr OUStringLiteral UNO_NAME_TEXT_RANGE = u"TextRange"; inline constexpr OUStringLiteral UNO_NAME_TEXT_BOX = u"TextBox"; inline constexpr OUStringLiteral UNO_NAME_TEXT_BOX_CONTENT = u"TextBoxContent"; inline constexpr OUStringLiteral UNO_NAME_NAME = u"Name"; +inline constexpr OUStringLiteral UNO_NAME_PARENT_NAME = u"ParentName"; inline constexpr OUStringLiteral UNO_NAME_CHAR_STYLE_NAME = u"CharStyleName"; inline constexpr OUStringLiteral UNO_NAME_ANCHOR_CHAR_STYLE_NAME = u"AnchorCharStyleName"; inline constexpr OUStringLiteral UNO_NAME_SUFFIX = u"Suffix"; diff --git a/sw/source/core/fields/docufld.cxx b/sw/source/core/fields/docufld.cxx index 689c758c77dd..2f0c78b56500 100644 --- a/sw/source/core/fields/docufld.cxx +++ b/sw/source/core/fields/docufld.cxx @@ -1743,7 +1743,9 @@ SwPostItField::SwPostItField( SwPostItFieldType* pT, const bool bResolved, const sal_uInt32 nPostItId, const sal_uInt32 nParentId, - const sal_uInt32 nParaId + const sal_uInt32 nParaId, + const sal_uInt32 nParentPostItId, + const OUString aParentName ) : SwField( pT ) , m_sText( std::move(aText) ) @@ -1754,6 +1756,8 @@ SwPostItField::SwPostItField( SwPostItFieldType* pT, , m_bResolved( bResolved ) , m_nParentId( nParentId ) , m_nParaId( nParaId ) + , m_nParentPostItId ( nParentPostItId ) + , m_sParentName( aParentName ) { m_nPostItId = nPostItId == 0 ? s_nLastPostItId++ : nPostItId; } @@ -1796,7 +1800,7 @@ bool SwPostItField::GetResolved() const std::unique_ptr<SwField> SwPostItField::Copy() const { std::unique_ptr<SwPostItField> pRet(new SwPostItField( static_cast<SwPostItFieldType*>(GetTyp()), m_sAuthor, m_sText, m_sInitials, m_sName, - m_aDateTime, m_bResolved, m_nPostItId, m_nParentId, m_nParaId)); + m_aDateTime, m_bResolved, m_nPostItId, m_nParentId, m_nParaId, m_nParentPostItId, m_sParentName)); if (mpText) pRet->SetTextObject( *mpText ); @@ -1835,6 +1839,10 @@ void SwPostItField::SetName(const OUString& rName) m_sName = rName; } +void SwPostItField::SetParentName(const OUString& rName) +{ + m_sParentName = rName; +} void SwPostItField::SetTextObject( std::optional<OutlinerParaObject> pText ) { @@ -1851,6 +1859,11 @@ void SwPostItField::SetPostItId(const sal_uInt32 nPostItId) m_nPostItId = nPostItId == 0 ? s_nLastPostItId++ : nPostItId; } +void SwPostItField::SetParentPostItId(const sal_uInt32 nParentPostItId) +{ + m_nParentPostItId = nParentPostItId; +} + void SwPostItField::SetParentId(const sal_uInt32 nParentId) { m_nParentId = nParentId; @@ -1879,6 +1892,9 @@ bool SwPostItField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const case FIELD_PROP_PAR4: rAny <<= m_sName; break; + case FIELD_PROP_PAR7: // PAR5 (Parent Para Id) and PAR6 (Para Id) are skipped - they are not written into xml. Used for file convertion. + rAny <<= m_sParentName; + break; case FIELD_PROP_BOOL1: rAny <<= m_bResolved; break; @@ -1953,6 +1969,9 @@ bool SwPostItField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId ) case FIELD_PROP_PAR4: rAny >>= m_sName; break; + case FIELD_PROP_PAR7: // PAR5 (Parent Para Id) and PAR6 (Para Id) are skipped - they are not written into xml. Used for file convertion. + rAny >>= m_sParentName; + break; case FIELD_PROP_BOOL1: rAny >>= m_bResolved; break; diff --git a/sw/source/core/inc/unofldmid.h b/sw/source/core/inc/unofldmid.h index f9b7d5bdc75e..59f4583f3d6f 100644 --- a/sw/source/core/inc/unofldmid.h +++ b/sw/source/core/inc/unofldmid.h @@ -49,6 +49,7 @@ #define FIELD_PROP_TEXT 34 #define FIELD_PROP_TITLE 35 #define FIELD_PROP_PAR6 36 +#define FIELD_PROP_PAR7 37 #endif diff --git a/sw/source/core/unocore/unofield.cxx b/sw/source/core/unocore/unofield.cxx index 8a63629e84ed..f1818c3c088f 100644 --- a/sw/source/core/unocore/unofield.cxx +++ b/sw/source/core/unocore/unofield.cxx @@ -1044,6 +1044,7 @@ struct SwFieldProperties_Impl OUString sPar4; OUString sPar5; OUString sPar6; + OUString sPar7; Date aDate; double fDouble; uno::Sequence<beans::PropertyValue> aPropSeq; @@ -1395,7 +1396,9 @@ void SAL_CALL SwXTextField::attach( m_pImpl->m_pProps->bBool1, // resolvedflag 0, // id nParentId, // parent id - nImportedId // imported para id + nImportedId, // imported para id + 0, // PostIt Parent ID. + m_pImpl->m_pProps->sPar7 ); if ( m_pImpl->m_xTextObject.is() ) { @@ -2235,6 +2238,9 @@ SwXTextField::setPropertyValue( case FIELD_PROP_PAR4: rValue >>= m_pImpl->m_pProps->sPar4; break; + case FIELD_PROP_PAR7: + rValue >>= m_pImpl->m_pProps->sPar7; + break; case FIELD_PROP_PAR5: rValue >>= m_pImpl->m_pProps->sPar5; break; @@ -2441,6 +2447,9 @@ uno::Any SAL_CALL SwXTextField::getPropertyValue(const OUString& rPropertyName) case FIELD_PROP_PAR4: aRet <<= m_pImpl->m_pProps->sPar4; break; + case FIELD_PROP_PAR7: + aRet <<= m_pImpl->m_pProps->sPar7; + break; case FIELD_PROP_PAR5: aRet <<= m_pImpl->m_pProps->sPar5; break; diff --git a/sw/source/core/unocore/unomap.cxx b/sw/source/core/unocore/unomap.cxx index 4594f10f33e1..d34599a39716 100644 --- a/sw/source/core/unocore/unomap.cxx +++ b/sw/source/core/unocore/unomap.cxx @@ -897,6 +897,7 @@ o3tl::span<const SfxItemPropertyMapEntry> SwUnoPropertyMapProvider::GetPropertyM {UNO_NAME_NAME, FIELD_PROP_PAR4, cppu::UnoType<OUString>::get(), PROPERTY_NONE, 0}, {UNO_NAME_PARA_ID_PARENT, FIELD_PROP_PAR5, cppu::UnoType<OUString>::get(), PROPERTY_NONE, 0}, {UNO_NAME_PARA_ID, FIELD_PROP_PAR6, cppu::UnoType<OUString>::get(), PROPERTY_NONE, 0}, + {UNO_NAME_PARENT_NAME, FIELD_PROP_PAR7, cppu::UnoType<OUString>::get(), PROPERTY_NONE, 0}, {UNO_NAME_RESOLVED, FIELD_PROP_BOOL1, cppu::UnoType<bool>::get(), PROPERTY_NONE, 0}, {UNO_NAME_DATE_TIME_VALUE, FIELD_PROP_DATE_TIME, cppu::UnoType<css::util::DateTime>::get(), PROPERTY_NONE, 0}, {UNO_NAME_DATE, FIELD_PROP_DATE, cppu::UnoType<css::util::Date>::get(), PROPERTY_NONE, 0}, diff --git a/sw/source/uibase/docvw/AnnotationWin.cxx b/sw/source/uibase/docvw/AnnotationWin.cxx index dcaf84550af6..711d612ef173 100644 --- a/sw/source/uibase/docvw/AnnotationWin.cxx +++ b/sw/source/uibase/docvw/AnnotationWin.cxx @@ -255,6 +255,12 @@ sal_uInt32 SwAnnotationWin::GetParaId() return nParaId; } +sal_uInt32 SwAnnotationWin::GetPostItId() +{ + auto pField = static_cast<SwPostItField*>(mpFormatField->GetField()); + return pField->GetPostItId(); +} + sal_uInt32 SwAnnotationWin::CreateUniqueParaId() { return comphelper::rng::uniform_uint_distribution(0, std::numeric_limits<sal_uInt32>::max()); diff --git a/sw/source/uibase/docvw/AnnotationWin2.cxx b/sw/source/uibase/docvw/AnnotationWin2.cxx index e8852a87f6e0..d4faa06482ba 100644 --- a/sw/source/uibase/docvw/AnnotationWin2.cxx +++ b/sw/source/uibase/docvw/AnnotationWin2.cxx @@ -1118,6 +1118,7 @@ void SwAnnotationWin::ExecuteCommand(sal_uInt16 nSlot) // Get newly created SwPostItField and set its paraIdParent auto pPostItField = mrMgr.GetLatestPostItField(); pPostItField->SetParentId(GetTopReplyNote()->GetParaId()); + pPostItField->SetParentPostItId(GetTopReplyNote()->GetPostItId()); } break; } diff --git a/sw/source/uibase/docvw/PostItMgr.cxx b/sw/source/uibase/docvw/PostItMgr.cxx index 07343fa42e47..07bf10be55c0 100644 --- a/sw/source/uibase/docvw/PostItMgr.cxx +++ b/sw/source/uibase/docvw/PostItMgr.cxx @@ -168,8 +168,7 @@ namespace { const OString sRects = comphelper::string::join("; ", aRects); aAnnotation.put("id", pField->GetPostItId()); - aAnnotation.put("parent", pWin->CalcParent()); - aAnnotation.put("paraIdParent", pField->GetParentId()); + aAnnotation.put("parentId", pField->GetParentPostItId()); aAnnotation.put("author", pField->GetPar1().toUtf8().getStr()); aAnnotation.put("text", pField->GetPar2().toUtf8().getStr()); aAnnotation.put("resolved", pField->GetResolved() ? "true" : "false"); @@ -1336,6 +1335,30 @@ void SwPostItMgr::AddPostIts(const bool bCheckExistence, const bool bFocus) SwFieldType* pType = mpView->GetDocShell()->GetDoc()->getIDocumentFieldsAccess().GetFieldType(SwFieldIds::Postit, OUString(),false); std::vector<SwFormatField*> vFormatFields; pType->CollectPostIts(vFormatFields, rIDRA, mpWrtShell->GetLayout()->IsHideRedlines()); + + for (std::vector<SwFormatField*>::iterator i = vFormatFields.begin(); i != vFormatFields.end(); i++) + { + SwPostItField *pChildPostIt = static_cast<SwPostItField*>((*i)->GetField()); + + if (pChildPostIt->GetParentId() != 0 || !pChildPostIt->GetParentName().isEmpty()) + { + for (std::vector<SwFormatField*>::iterator j = vFormatFields.begin(); j != vFormatFields.end(); j++) + { + SwPostItField *pParentPostIt = static_cast<SwPostItField*>((*j)->GetField()); + if (pChildPostIt->GetParentId() != 0 && pParentPostIt->GetParaId() == pChildPostIt->GetParentId()) + { + pChildPostIt->SetParentPostItId(pParentPostIt->GetPostItId()); + pChildPostIt->SetParentName(pParentPostIt->GetName()); + } + else if (!pParentPostIt->GetName().isEmpty() && pParentPostIt->GetName() == pChildPostIt->GetParentName()) + { + pChildPostIt->SetParentPostItId(pParentPostIt->GetPostItId()); + pChildPostIt->SetParentName(pParentPostIt->GetName()); + } + } + } + } + for(auto pFormatField : vFormatFields) InsertItem(pFormatField, bCheckExistence, bFocus); // if we just added the first one we have to update the view for centering diff --git a/sw/source/uibase/uno/unotxdoc.cxx b/sw/source/uibase/uno/unotxdoc.cxx index a4d953d4326a..34697711355a 100644 --- a/sw/source/uibase/uno/unotxdoc.cxx +++ b/sw/source/uibase/uno/unotxdoc.cxx @@ -3374,8 +3374,7 @@ void SwXTextDocument::getPostIts(tools::JsonWriter& rJsonWriter) auto commentNode = rJsonWriter.startStruct(); rJsonWriter.put("id", pField->GetPostItId()); - rJsonWriter.put("parent", pWin->CalcParent()); - rJsonWriter.put("paraIdParent", pField->GetParentId()); + rJsonWriter.put("parentId", pField->GetParentPostItId()); rJsonWriter.put("author", pField->GetPar1()); rJsonWriter.put("text", pField->GetPar2()); rJsonWriter.put("resolved", pField->GetResolved() ? "true" : "false"); diff --git a/xmloff/inc/txtfldi.hxx b/xmloff/inc/txtfldi.hxx index 243feb630fc8..0a15329c31ec 100644 --- a/xmloff/inc/txtfldi.hxx +++ b/xmloff/inc/txtfldi.hxx @@ -961,6 +961,7 @@ class XMLAnnotationImportContext final : public XMLTextFieldImportContext OUStringBuffer aAuthorBuffer; OUStringBuffer aInitialsBuffer; OUString aName; + OUString aParentName; OUStringBuffer aTextBuffer; OUStringBuffer aDateBuffer; OUString aResolved; diff --git a/xmloff/source/core/xmltoken.cxx b/xmloff/source/core/xmltoken.cxx index 2aac3fa4cfde..806d3a6e74e8 100644 --- a/xmloff/source/core/xmltoken.cxx +++ b/xmloff/source/core/xmltoken.cxx @@ -1517,6 +1517,7 @@ namespace xmloff::token { TOKEN( "paragraph-start-margin", XML_PARAGRAPH_START_MARGIN ), TOKEN( "parallel", XML_PARALLEL ), TOKEN( "param", XML_PARAM ), + TOKEN( "parent-name", XML_PARENT_NAME ), TOKEN( "parent-style-name", XML_PARENT_STYLE_NAME ), TOKEN( "parse-sql-statement", XML_PARSE_SQL_STATEMENT ), TOKEN( "parsed", XML_PARSED ), diff --git a/xmloff/source/text/txtflde.cxx b/xmloff/source/text/txtflde.cxx index 54341aab0b01..853df896f8c0 100644 --- a/xmloff/source/text/txtflde.cxx +++ b/xmloff/source/text/txtflde.cxx @@ -343,6 +343,7 @@ constexpr OUStringLiteral gsPropertyItems(u"Items"); constexpr OUStringLiteral gsPropertyLevel(u"Level"); constexpr OUStringLiteral gsPropertyMeasureKind(u"Kind"); constexpr OUStringLiteral gsPropertyName(u"Name"); +constexpr OUStringLiteral gsPropertyParentName(u"ParentName"); constexpr OUStringLiteral gsPropertyNumberFormat(u"NumberFormat"); constexpr OUStringLiteral gsPropertyNumberingSeparator(u"NumberingSeparator"); constexpr OUStringLiteral gsPropertyNumberingType(u"NumberingType"); @@ -1729,6 +1730,14 @@ void XMLTextFieldExport::ExportFieldHelper( { GetExport().AddAttribute(XML_NAMESPACE_OFFICE, XML_NAME, aName); } + + OUString aParentName; + rPropSet->getPropertyValue(gsPropertyParentName) >>= aParentName; + if (!aParentName.isEmpty()) + { + GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_PARENT_NAME, aParentName); + } + SvtSaveOptions::ODFSaneDefaultVersion eVersion = rExport.getSaneDefaultVersion(); if (eVersion & SvtSaveOptions::ODFSVER_EXTENDED) { diff --git a/xmloff/source/text/txtfldi.cxx b/xmloff/source/text/txtfldi.cxx index af2bd8aa2ac1..05d95281ef1b 100644 --- a/xmloff/source/text/txtfldi.cxx +++ b/xmloff/source/text/txtfldi.cxx @@ -106,6 +106,7 @@ constexpr OUStringLiteral sAPI_content = u"Content"; constexpr OUStringLiteral sAPI_author = u"Author"; constexpr OUStringLiteral sAPI_hint = u"Hint"; constexpr OUStringLiteral sAPI_name = u"Name"; +constexpr OUStringLiteral sAPI_parent_name = u"ParentName"; constexpr OUStringLiteral sAPI_sub_type = u"SubType"; constexpr OUStringLiteral sAPI_date_time_value = u"DateTimeValue"; constexpr OUStringLiteral sAPI_number_format = u"NumberFormat"; @@ -3146,6 +3147,8 @@ void XMLAnnotationImportContext::ProcessAttribute( aName = OUString::fromUtf8(sAttrValue); else if (nAttrToken == XML_ELEMENT(LO_EXT, XML_RESOLVED)) aResolved = OUString::fromUtf8(sAttrValue); + else if (nAttrToken == XML_ELEMENT(LO_EXT, XML_PARENT_NAME)) + aParentName = OUString::fromUtf8(sAttrValue); else XMLOFF_WARN_UNKNOWN_ATTR("xmloff", nAttrToken, sAttrValue); } @@ -3334,6 +3337,9 @@ void XMLAnnotationImportContext::PrepareField( if (!aName.isEmpty()) xPropertySet->setPropertyValue(sAPI_name, Any(aName)); + + if (!aParentName.isEmpty()) + xPropertySet->setPropertyValue(sAPI_parent_name, Any(aParentName)); } diff --git a/xmloff/source/token/tokens.txt b/xmloff/source/token/tokens.txt index ff4fbfddb1f5..acbdd629d225 100644 --- a/xmloff/source/token/tokens.txt +++ b/xmloff/source/token/tokens.txt @@ -1417,6 +1417,7 @@ paragraph-end-margin paragraph-start-margin parallel param +parent-name parent-style-name parse-sql-statement parsed