include/tools/datetimeutils.hxx                              |    2 
 officecfg/registry/data/org/openoffice/Office/UI/Sidebar.xcu |   58 +
 sw/Library_sw.mk                                             |    1 
 sw/UIConfig_swriter.mk                                       |    3 
 sw/inc/AnnotationWin.hxx                                     |    1 
 sw/inc/PostItMgr.hxx                                         |    7 
 sw/source/uibase/docvw/PostItMgr.cxx                         |   27 
 sw/source/uibase/sidebar/CommentsPanel.cxx                   |  443 +++++++++++
 sw/source/uibase/sidebar/CommentsPanel.hxx                   |  156 +++
 sw/source/uibase/sidebar/SwPanelFactory.cxx                  |   11 
 sw/uiconfig/swriter/ui/commentspanel.ui                      |  306 +++++++
 sw/uiconfig/swriter/ui/commentsthread.ui                     |   40 
 sw/uiconfig/swriter/ui/commentwidget.ui                      |  170 ++++
 tools/source/datetime/datetimeutils.cxx                      |    6 
 14 files changed, 1228 insertions(+), 3 deletions(-)

New commits:
commit be16c6cf5c14c17ec3e7d860636e5c7b2cd7f654
Author:     Mohit Marathe <[email protected]>
AuthorDate: Fri May 17 14:00:18 2024 +0530
Commit:     Sarper Akdemir <[email protected]>
CommitDate: Fri Sep 13 12:35:45 2024 +0200

    sw: add Comments Panel in sidebar
    
    This commit adds a sidebar deck for comments.
    It has all the functionalities of the old comments
    shown via annotation window.
    
    Change-Id: Ibab0e21a54c097d0f42bddb1d07da74319970135
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167840
    Tested-by: Jenkins
    Reviewed-by: Sarper Akdemir <[email protected]>

diff --git a/include/tools/datetimeutils.hxx b/include/tools/datetimeutils.hxx
index deb7d7ee4f4c..96abd8fd71df 100644
--- a/include/tools/datetimeutils.hxx
+++ b/include/tools/datetimeutils.hxx
@@ -20,6 +20,8 @@ TOOLS_DLLPUBLIC OUString DateTimeToOUString(const DateTime& 
rDateTime);
 // This function converts a 'Date' object to an 'OString' object in ISO-8601 
representation
 TOOLS_DLLPUBLIC OString DateToOString(const Date& rDate);
 
+TOOLS_DLLPUBLIC OString TimeToOString(const tools::Time& rTime);
+
 // This function converts a 'Date' object to an 'OUString' object in 
DD/MM/YYYY format
 TOOLS_DLLPUBLIC OUString DateToDDMMYYYYOUString(const Date& rDate);
 
diff --git a/officecfg/registry/data/org/openoffice/Office/UI/Sidebar.xcu 
b/officecfg/registry/data/org/openoffice/Office/UI/Sidebar.xcu
index 1e9475993207..543d13edf274 100644
--- a/officecfg/registry/data/org/openoffice/Office/UI/Sidebar.xcu
+++ b/officecfg/registry/data/org/openoffice/Office/UI/Sidebar.xcu
@@ -81,6 +81,29 @@
         </prop>
       </node>
 
+      <node oor:name="CommentsDeck" oor:op="replace">
+        <prop oor:name="Title" oor:type="xs:string">
+          <value xml:lang="en-US">Comments</value>
+        </prop>
+        <prop oor:name="IsExperimental" oor:type="xs:boolean">
+          <value>true</value>
+        </prop>
+        <prop oor:name="Id" oor:type="xs:string">
+          <value>CommentsDeck</value>
+        </prop>
+        <prop oor:name="IconURL" oor:type="xs:string">
+          <value>private:graphicrepository/cmd/lc_showannotations.png</value>
+        </prop>
+        <prop oor:name="ContextList">
+          <value oor:separator=";">
+            WriterVariants, any, visible ;
+          </value>
+        </prop>
+        <prop oor:name="OrderIndex" oor:type="xs:int">
+          <value>900</value>
+        </prop>
+      </node>
+
       <node oor:name="A11yCheckDeck" oor:op="replace">
         <prop oor:name="Title" oor:type="xs:string">
           <value xml:lang="en-US">Accessibility Check</value>
@@ -618,6 +641,41 @@
         </prop>
       </node>
 
+      <node oor:name="CommentsPanel" oor:op="replace">
+        <prop oor:name="Title" oor:type="xs:string">
+          <value xml:lang="en-US">Comments</value>
+        </prop>
+        <prop oor:name="IsExperimental" oor:type="xs:boolean">
+          <value>true</value>
+        </prop>
+        <prop oor:name="TitleBarIsOptional" oor:type="xs:boolean">
+          <value>true</value>
+        </prop>
+        <prop oor:name="Id" oor:type="xs:string">
+          <value>CommentsPanel</value>
+        </prop>
+        <prop oor:name="DeckId" oor:type="xs:string">
+          <value>CommentsDeck</value>
+        </prop>
+        <prop oor:name="DefaultMenuCommand">
+          <value></value>
+        </prop>
+        <prop oor:name="ContextList">
+          <value oor:separator=";">
+            WriterVariants, any, visible ;
+          </value>
+        </prop>
+        <prop oor:name="ImplementationURL" oor:type="xs:string">
+          
<value>private:resource/toolpanel/SwPanelFactory/CommentsPanel</value>
+        </prop>
+        <prop oor:name="OrderIndex" oor:type="xs:int">
+          <value>100</value>
+        </prop>
+        <prop oor:name="WantsAWT" oor:type="xs:boolean">
+          <value>false</value>
+        </prop>
+      </node>
+
       <node oor:name="A11yCheckIssuesPanel" oor:op="replace">
         <prop oor:name="Title" oor:type="xs:string">
           <value xml:lang="en-US">Accessibility Issues</value>
diff --git a/sw/Library_sw.mk b/sw/Library_sw.mk
index 872ae8812286..fd0c261c1878 100644
--- a/sw/Library_sw.mk
+++ b/sw/Library_sw.mk
@@ -735,6 +735,7 @@ $(eval $(call gb_Library_add_exception_objects,sw,\
     sw/source/uibase/sidebar/ThemePanel \
     sw/source/uibase/sidebar/SwPanelFactory \
     sw/source/uibase/sidebar/WriterInspectorTextPanel \
+    sw/source/uibase/sidebar/CommentsPanel \
     sw/source/uibase/sidebar/A11yCheckIssuesPanel \
     sw/source/uibase/sidebar/QuickFindPanel \
     sw/source/uibase/table/chartins \
diff --git a/sw/UIConfig_swriter.mk b/sw/UIConfig_swriter.mk
index 262123969dae..a96ee9dd9749 100644
--- a/sw/UIConfig_swriter.mk
+++ b/sw/UIConfig_swriter.mk
@@ -285,6 +285,9 @@ $(eval $(call gb_UIConfig_add_uifiles,modules/swriter,\
        sw/uiconfig/swriter/ui/pagestylespanel \
        sw/uiconfig/swriter/ui/pageheaderpanel \
        sw/uiconfig/swriter/ui/pagefooterpanel \
+       sw/uiconfig/swriter/ui/commentspanel \
+       sw/uiconfig/swriter/ui/commentsthread \
+       sw/uiconfig/swriter/ui/commentwidget \
        sw/uiconfig/swriter/ui/a11ycheckissuespanel \
        sw/uiconfig/swriter/ui/poseditbox \
        sw/uiconfig/swriter/ui/sidebarwrap \
diff --git a/sw/inc/AnnotationWin.hxx b/sw/inc/AnnotationWin.hxx
index 32f7b77f4829..d5f31937409f 100644
--- a/sw/inc/AnnotationWin.hxx
+++ b/sw/inc/AnnotationWin.hxx
@@ -71,6 +71,7 @@ class SAL_DLLPUBLIC_RTTI SwAnnotationWin final : public 
InterimItemWindow
         void    Delete();
         void    GotoPos();
         const SwPostItField* GetPostItField() const { return mpField; }
+        SwFormatField* GetFormatField() const { return mpFormatField; }
         void UpdateText(const OUString& aText);
 
         OUString GetAuthor() const;
diff --git a/sw/inc/PostItMgr.hxx b/sw/inc/PostItMgr.hxx
index f11c821240cd..610c3c79a07b 100644
--- a/sw/inc/PostItMgr.hxx
+++ b/sw/inc/PostItMgr.hxx
@@ -82,7 +82,8 @@ struct FieldShadowState
     }
 };
 
-class SAL_DLLPUBLIC_RTTI SwPostItMgr final : public SfxListener
+class SAL_DLLPUBLIC_RTTI SwPostItMgr final : public SfxListener,
+                                             public SfxBroadcaster
 {
     private:
         SwView*                         mpView;
@@ -141,9 +142,11 @@ class SAL_DLLPUBLIC_RTTI SwPostItMgr final : public 
SfxListener
         typedef std::vector< std::unique_ptr<SwSidebarItem> >::const_iterator 
const_iterator;
         const_iterator begin()  const { return mvPostItFields.begin(); }
         const_iterator end()    const { return mvPostItFields.end();  }
+        const std::vector<std::unique_ptr<SwSidebarItem>>& GetPostItFields() { 
return mvPostItFields; }
 
         void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) override;
 
+        std::vector<SwFormatField*> UpdatePostItsParentInfo();
         void LayoutPostIts();
         bool CalcRects();
 
@@ -169,6 +172,8 @@ class SAL_DLLPUBLIC_RTTI SwPostItMgr final : public 
SfxListener
         void ToggleResolved(sal_uInt32 nPostItId);
         void ToggleResolvedForThread(sal_uInt32 nPostItId);
 
+        sw::annotation::SwAnnotationWin* GetRemovedAnnotationWin(const 
SfxBroadcaster* pBroadcast);
+
         void ExecuteFormatAllDialog(SwView& rView);
         void FormatAll(const SfxItemSet &rNewAttr);
 
diff --git a/sw/source/uibase/docvw/PostItMgr.cxx 
b/sw/source/uibase/docvw/PostItMgr.cxx
index 589f6c02a9cd..56abcb248cfd 100644
--- a/sw/source/uibase/docvw/PostItMgr.cxx
+++ b/sw/source/uibase/docvw/PostItMgr.cxx
@@ -319,6 +319,17 @@ SwSidebarItem* SwPostItMgr::InsertItem(SfxBroadcaster* 
pItem, bool bCheckExisten
     return pAnnotationItem;
 }
 
+sw::annotation::SwAnnotationWin* SwPostItMgr::GetRemovedAnnotationWin( const 
SfxBroadcaster* pBroadcast )
+{
+    auto i = std::find_if(mvPostItFields.begin(), mvPostItFields.end(),
+        [&pBroadcast](const std::unique_ptr<SwSidebarItem>& pField) { return 
pField->GetBroadcaster() == pBroadcast; });
+    if (i != mvPostItFields.end())
+    {
+        return (*i)->mpPostIt;
+    }
+    return nullptr;
+}
+
 void SwPostItMgr::RemoveItem( SfxBroadcaster* pBroadcast )
 {
     EndListening(*pBroadcast);
@@ -400,6 +411,7 @@ void SwPostItMgr::Notify( SfxBroadcaster& rBC, const 
SfxHint& rHint )
                             mbLayout = true;
                         break;
                     }
+                    this->Broadcast(rHint);
                     RemoveItem(pField);
 
                     // If LOK has disabled tiled annotations, emit annotation 
callbacks
@@ -430,6 +442,7 @@ void SwPostItMgr::Notify( SfxBroadcaster& rBC, const 
SfxHint& rHint )
                         {
                             postItField->mpPostIt->SetPostItText();
                             mbLayout = true;
+                            this->Forward(rBC, rHint);
                         }
 
                         // If LOK has disabled tiled annotations, emit 
annotation callbacks
@@ -821,6 +834,9 @@ void SwPostItMgr::LayoutPostIts()
                         if (pPostIt)
                             pPostIt->HideNote();
                     }
+                    SwFormatField* pFormatField = &(pItem->GetFormatField());
+                    SwFormatFieldHintWhich nWhich = 
SwFormatFieldHintWhich::INSERTED;
+                    this->Broadcast(SwFormatFieldHint(pFormatField, nWhich, 
mpView));
                 }
 
                 if (!aVisiblePostItList.empty() && ShowNotes())
@@ -1331,9 +1347,8 @@ bool 
SwPostItMgr::LayoutByPage(std::vector<SwAnnotationWin*> &aVisiblePostItList
     return bScrollbars;
  }
 
-void SwPostItMgr::AddPostIts(const bool bCheckExistence, const bool bFocus)
+std::vector<SwFormatField*> SwPostItMgr::UpdatePostItsParentInfo()
 {
-    const bool bEmpty = mvPostItFields.empty();
     IDocumentRedlineAccess const& 
rIDRA(mpWrtShell->getIDocumentRedlineAccess());
     SwFieldType* pType = 
mpView->GetDocShell()->GetDoc()->getIDocumentFieldsAccess().GetFieldType(SwFieldIds::Postit,
 OUString(),false);
     std::vector<SwFormatField*> vFormatFields;
@@ -1361,6 +1376,14 @@ void SwPostItMgr::AddPostIts(const bool bCheckExistence, 
const bool bFocus)
             }
         }
     }
+    return vFormatFields;
+}
+
+
+void SwPostItMgr::AddPostIts(const bool bCheckExistence, const bool bFocus)
+{
+    const bool bEmpty = mvPostItFields.empty();
+    std::vector<SwFormatField*> vFormatFields = UpdatePostItsParentInfo();
 
     for(auto pFormatField : vFormatFields)
         InsertItem(pFormatField, bCheckExistence, bFocus);
diff --git a/sw/source/uibase/sidebar/CommentsPanel.cxx 
b/sw/source/uibase/sidebar/CommentsPanel.cxx
new file mode 100644
index 000000000000..1e5e3e4ea1eb
--- /dev/null
+++ b/sw/source/uibase/sidebar/CommentsPanel.cxx
@@ -0,0 +1,443 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; 
fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+#include <sfx2/bindings.hxx>
+
+#include <PostItMgr.hxx>
+#include <postithelper.hxx>
+#include <AnnotationWin.hxx>
+#include <fmtfld.hxx>
+#include <docufld.hxx>
+#include <swmodule.hxx>
+#include <vcl/svapp.hxx>
+#include <rtl/ustring.hxx>
+#include <xmloff/xmlmetae.hxx>
+#include <tools/datetimeutils.hxx>
+#include <swtypes.hxx>
+#include <view.hxx>
+#include <wrtsh.hxx>
+#include <tools/date.hxx>
+#include <tools/datetime.hxx>
+#include <tools/time.hxx>
+#include <unotools/localedatawrapper.hxx>
+#include <unotools/syslocale.hxx>
+#include <tools/link.hxx>
+#include <editeng/outliner.hxx>
+#include <editeng/editeng.hxx>
+
+#include <strings.hrc>
+#include <cmdid.h>
+
+#include "CommentsPanel.hxx"
+
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+
+namespace sw::sidebar
+{
+Comment::Comment(weld::Container* pParent, CommentsPanel& rCommentsPanel)
+    : mxBuilder(Application::CreateBuilder(pParent, 
"modules/swriter/ui/commentwidget.ui"))
+    , mxContainer(mxBuilder->weld_container("Comment"))
+    , mxAuthor(mxBuilder->weld_label("authorlabel"))
+    , mxDate(mxBuilder->weld_label("datelabel"))
+    , mxTime(mxBuilder->weld_label("timelabel"))
+    , mxReply(mxBuilder->weld_button("replybutton"))
+    , mxResolve(mxBuilder->weld_check_button("resolvebutton"))
+    , mxTextView(mxBuilder->weld_text_view("textview"))
+    , mrCommentsPanel(rCommentsPanel)
+    , maDate(Date::EMPTY)
+    , maTime(tools::Time::EMPTY)
+    , mbResolved(false)
+{
+    mxTextView->connect_focus_out(LINK(this, Comment, OnFocusOut));
+    mxResolve->connect_toggled(LINK(this, Comment, ResolveClicked));
+    mxReply->connect_clicked(LINK(this, Comment, ReplyClicked));
+}
+
+Comment::~Comment() {}
+
+void Comment::InitControls(const SwPostItField* pPostItField)
+{
+    if (!pPostItField)
+        return;
+    msText = pPostItField->GetText();
+    msAuthor = pPostItField->GetPar1();
+    msInitials = pPostItField->GetInitials();
+    msName = pPostItField->GetName();
+    maDate = Date(pPostItField->GetDateTime().GetDate());
+    maTime = tools::Time(pPostItField->GetDateTime().GetTime());
+    mbResolved = pPostItField->GetResolved();
+
+    // Format date and time according to the system locale
+    const SvtSysLocale aSysLocale;
+    const LocaleDataWrapper& rLocalData = aSysLocale.GetLocaleData();
+    OUString sMeta;
+    if (maDate.IsValidAndGregorian())
+    {
+        sMeta = rLocalData.getDate(maDate);
+    }
+    else
+    {
+        sMeta = SwResId(STR_NODATE);
+    }
+    if (mxDate->get_label() != sMeta)
+    {
+        mxDate->set_label(sMeta);
+    }
+    if (pPostItField->GetTime().GetTime() != 0)
+    {
+        sMeta = " " + rLocalData.getTime(pPostItField->GetTime(), false);
+    }
+    if (mxTime->get_label() != sMeta)
+    {
+        mxTime->set_label(sMeta);
+    }
+
+    mxAuthor->set_label(msAuthor);
+    mxAuthor->set_tooltip_text(msAuthor);
+    mxResolve->set_active(mbResolved);
+    mxTextView->set_text(msText);
+}
+
+IMPL_LINK_NOARG(Comment, OnFocusOut, weld::Widget&, void) { 
mrCommentsPanel.EditComment(this); }
+
+IMPL_LINK_NOARG(Comment, ResolveClicked, weld::Toggleable&, void)
+{
+    mrCommentsPanel.ToggleResolved(this);
+}
+
+IMPL_LINK_NOARG(Comment, ReplyClicked, weld::Button&, void) { 
mrCommentsPanel.ReplyComment(this); }
+
+Thread::Thread(weld::Container* pParent)
+    : mxBuilder(Application::CreateBuilder(pParent, 
"modules/swriter/ui/commentsthread.ui"))
+    , mxContainer(mxBuilder->weld_container("Thread"))
+    , mxCommentBox(mxBuilder->weld_box("comments_box"))
+    , mxText(mxBuilder->weld_label("commentedtext"))
+{
+    // mxContainer->set_size_request(-1, 
mxContainer->get_preferred_size().Height());
+}
+
+Thread::~Thread() {}
+
+std::unique_ptr<PanelLayout> CommentsPanel::Create(weld::Widget* pParent)
+{
+    if (pParent == nullptr)
+        throw ::com::sun::star::lang::IllegalArgumentException(
+            "no parent window given to CommentsPanel::Create", nullptr, 0);
+    return std::make_unique<CommentsPanel>(pParent);
+}
+
+CommentsPanel::CommentsPanel(weld::Widget* pParent)
+    : PanelLayout(pParent, "CommentsPanel", 
"modules/swriter/ui/commentspanel.ui")
+    , mpPostItMgr(nullptr)
+    , mxFilterAuthor(m_xBuilder->weld_combo_box("filter_author"))
+    , mxFilterTime(m_xBuilder->weld_combo_box("filter_time"))
+    , mxShowTime(m_xBuilder->weld_check_button("show_time"))
+    , mxShowResolved(m_xBuilder->weld_check_button("show_resolved"))
+    , mxShowReference(m_xBuilder->weld_check_button("show_reference"))
+    , mxSortbyPosition(m_xBuilder->weld_radio_button("sortby_position"))
+    , mxSortbyTime(m_xBuilder->weld_radio_button("sortby_time"))
+    , mxThreadsContainer(m_xBuilder->weld_box("comment_threads"))
+{
+    SwView* pView = GetActiveView();
+    if (!pView)
+        return;
+    SwWrtShell& rSh = pView->GetWrtShell();
+    mpPostItMgr = rSh.GetPostItMgr();
+    populateComments();
+
+    StartListening(*mpPostItMgr);
+}
+
+void CommentsPanel::Notify(SfxBroadcaster& rBC, const SfxHint& rHint)
+{
+    if (rHint.GetId() == SfxHintId::SwFormatField)
+    {
+        const SwFormatFieldHint* pFormatHint = static_cast<const 
SwFormatFieldHint*>(&rHint);
+        const SwFormatField* pField = pFormatHint->GetField();
+        switch (pFormatHint->Which())
+        {
+            case SwFormatFieldHintWhich::INSERTED:
+            {
+                if (!pField)
+                {
+                    break;
+                }
+                // get field to be inserted from hint
+                if (pField->IsFieldInDoc())
+                {
+                    addComment(pField);
+                }
+                else
+                {
+                    OSL_FAIL("Inserted field not in document!");
+                }
+                break;
+            }
+            case SwFormatFieldHintWhich::REMOVED:
+            case SwFormatFieldHintWhich::REDLINED_DELETION:
+            {
+                sw::annotation::SwAnnotationWin* pAnnotationWin
+                    = mpPostItMgr->GetRemovedAnnotationWin(pField);
+                deleteComment(pAnnotationWin);
+                break;
+            }
+            case SwFormatFieldHintWhich::FOCUS:
+            {
+                break;
+            }
+            case SwFormatFieldHintWhich::CHANGED:
+            case SwFormatFieldHintWhich::RESOLVED:
+            {
+                SwFormatField* pFormatField = 
dynamic_cast<SwFormatField*>(&rBC);
+                SwPostItField* pPostItField = 
static_cast<SwPostItField*>(pFormatField->GetField());
+                sw::annotation::SwAnnotationWin* pAnnotationWin
+                    = mpPostItMgr->GetAnnotationWin(pPostItField);
+                setResolvedStatus(pAnnotationWin);
+                break;
+            }
+        }
+    }
+}
+
+sw::annotation::SwAnnotationWin* CommentsPanel::getRootCommentWin(const 
SwFormatField* pFormatField)
+{
+    if (!pFormatField)
+        return nullptr;
+    const SwPostItField* pPostItField = static_cast<const 
SwPostItField*>(pFormatField->GetField());
+    sw::annotation::SwAnnotationWin* pAnnotationWin = 
mpPostItMgr->GetAnnotationWin(pPostItField);
+    if (!pAnnotationWin)
+        return nullptr;
+    sw::annotation::SwAnnotationWin* pRootNote = 
pAnnotationWin->GetTopReplyNote();
+    return pRootNote;
+}
+
+sal_uInt32 CommentsPanel::getPostItId(sw::annotation::SwAnnotationWin* 
pAnnotationWin)
+{
+    const SwPostItField* pField = pAnnotationWin->GetPostItField();
+    return pField->GetPostItId();
+}
+
+sw::annotation::SwAnnotationWin* CommentsPanel::getAnnotationWin(Comment* 
pComment)
+{
+    sal_uInt32 nPostItId = 0;
+    for (auto & [ rId, rComment ] : mpCommentsMap)
+    {
+        if (rComment.get() != pComment)
+        {
+            continue;
+        }
+        nPostItId = rId;
+        break;
+    }
+    auto& vPostItFields = mpPostItMgr->GetPostItFields();
+    SwPostItField* pPostItField = nullptr;
+    for (auto& pItem : vPostItFields)
+    {
+        SwFormatField* pFormatField = &pItem->GetFormatField();
+        SwPostItField* pField = 
static_cast<SwPostItField*>(pFormatField->GetField());
+        if (pField->GetPostItId() == nPostItId)
+        {
+            pPostItField = pField;
+            break;
+        }
+    }
+    return mpPostItMgr->GetAnnotationWin(pPostItField);
+}
+
+void CommentsPanel::populateComments()
+{
+    if (!mpPostItMgr)
+        return;
+    std::vector<SwFormatField*> vFormatFields = 
mpPostItMgr->UpdatePostItsParentInfo();
+
+    for (auto pFormatField : vFormatFields)
+    {
+        sw::annotation::SwAnnotationWin* pRootNote = 
getRootCommentWin(pFormatField);
+        if (!pRootNote)
+            continue;
+        sal_uInt32 nPostItId = getPostItId(pRootNote);
+
+        if (mpThreadsMap.find(nPostItId) != mpThreadsMap.end())
+            continue; // Skip if root comment is already present
+
+        auto pThread = std::make_unique<Thread>(mxThreadsContainer.get());
+        mxThreadsContainer->reorder_child(pThread->get_widget(), mnThreads++);
+
+        for (sw::annotation::SwAnnotationWin* pCurrent = pRootNote;;)
+        {
+            sal_uInt32 nId = getPostItId(pCurrent);
+            auto pComment = 
std::make_unique<Comment>(pThread->getCommentBoxWidget(), *this);
+            
pThread->getCommentBoxWidget()->reorder_child(pComment->get_widget(),
+                                                          
pThread->mnComments++);
+            pComment->InitControls(pCurrent->GetPostItField());
+            mpCommentsMap[nId] = std::move(pComment);
+            sw::annotation::SwAnnotationWin* next
+                = mpPostItMgr->GetNextPostIt(KEY_PAGEDOWN, pCurrent);
+            if (!next || next->GetTopReplyNote() != pRootNote)
+                break;
+            pCurrent = next;
+        }
+        mpThreadsMap[nPostItId] = std::move(pThread);
+    }
+}
+
+void CommentsPanel::addComment(const SwFormatField* pField)
+{
+    // Get id of the note
+    const SwPostItField* pPostItField = static_cast<const 
SwPostItField*>(pField->GetField());
+    sal_uInt32 nNoteId = pPostItField->GetPostItId();
+
+    if (mpCommentsMap.contains(nNoteId))
+        return;
+
+    // Get id of the root note
+    sw::annotation::SwAnnotationWin* pRootNote = getRootCommentWin(pField);
+    if (!pRootNote)
+        return;
+    sal_uInt32 nRootId = getPostItId(pRootNote);
+
+    sw::annotation::SwAnnotationWin* pNote
+        = mpPostItMgr->GetAnnotationWin(static_cast<const 
SwPostItField*>(pField->GetField()));
+    // If comment is added to an existing thread
+    if (mpThreadsMap.find(nRootId) != mpThreadsMap.end())
+    {
+        auto& pThread = mpThreadsMap[nRootId];
+        auto pComment = 
std::make_unique<Comment>(pThread->getCommentBoxWidget(), *this);
+        pThread->getCommentBoxWidget()->reorder_child(pComment->get_widget(),
+                                                      pThread->mnComments++);
+        pComment->InitControls(pNote->GetPostItField());
+        mpCommentsMap[nNoteId] = std::move(pComment);
+    }
+    // If a new thread is created
+    else
+    {
+        auto pThread = std::make_unique<Thread>(mxThreadsContainer.get());
+        mxThreadsContainer->reorder_child(pThread->get_widget(), mnThreads++);
+        auto pComment = 
std::make_unique<Comment>(pThread->getCommentBoxWidget(), *this);
+        pThread->getCommentBoxWidget()->reorder_child(pComment->get_widget(),
+                                                      pThread->mnComments++);
+        mpThreadsMap[nRootId] = std::move(pThread);
+        pComment->InitControls(pNote->GetPostItField());
+        mpCommentsMap[nNoteId] = std::move(pComment);
+    }
+}
+
+void CommentsPanel::deleteComment(sw::annotation::SwAnnotationWin* 
pAnnotationWin)
+{
+    if (!pAnnotationWin)
+        return;
+    sal_uInt32 nId = getPostItId(pAnnotationWin);
+    SwFormatField* pFormatField = pAnnotationWin->GetFormatField();
+    sw::annotation::SwAnnotationWin* pRootNote = nullptr;
+    // If the root comment is deleted, the new root comment of the thread 
should be the next comment in the thread
+    // but due to a bug `getRootCommentWin` returns root comment of some 
other/random thread so we completely lose
+    // access to the current thread.
+    if (mpThreadsMap.find(nId) != mpThreadsMap.end())
+    {
+        pRootNote = pAnnotationWin;
+    }
+    else
+    {
+        pRootNote = getRootCommentWin(pFormatField);
+    }
+
+    sal_uInt32 nRootId = getPostItId(pRootNote);
+
+    if (mpThreadsMap.find(nRootId) == mpThreadsMap.end())
+        return;
+    auto& pComment = mpCommentsMap[nId];
+    auto& pThread = mpThreadsMap[nRootId];
+    if (!pComment)
+        return;
+
+    pThread->getCommentBoxWidget()->move(pComment->get_widget(), nullptr);
+    mpCommentsMap.erase(nId);
+
+    // If the last comment in the thread is deleted, delete the thread
+    if (--pThread->mnComments == 0)
+    {
+        mxThreadsContainer->move(pThread->get_widget(), nullptr);
+        if (mpThreadsMap.find(nRootId) != mpThreadsMap.end())
+            mpThreadsMap.erase(nRootId);
+    }
+}
+
+void CommentsPanel::setResolvedStatus(sw::annotation::SwAnnotationWin* 
pAnnotationWin)
+{
+    sal_uInt32 nId = getPostItId(pAnnotationWin);
+    if (mpCommentsMap.find(nId) == mpCommentsMap.end())
+        return;
+    auto& pComment = mpCommentsMap[nId];
+    if (!pComment)
+        return;
+    SwPostItField* pPostItField = 
const_cast<SwPostItField*>(pAnnotationWin->GetPostItField());
+    if (pPostItField->GetResolved() == pComment->mbResolved)
+    {
+        editComment(pPostItField, pComment.get());
+        return;
+    }
+    pComment->mbResolved = pPostItField->GetResolved();
+    pComment->mxResolve->set_active(pComment->mbResolved);
+}
+
+void CommentsPanel::editComment(SwPostItField* pPostItField, Comment* pComment)
+{
+    OUString sText = pPostItField->GetText();
+    pComment->SetCommentText(sText);
+    pComment->mxTextView->set_text(sText);
+}
+
+void CommentsPanel::EditComment(Comment* pComment)
+{
+    if (!pComment)
+        return;
+    const OUString sText = pComment->mxTextView->get_text();
+
+    sw::annotation::SwAnnotationWin* pWin = getAnnotationWin(pComment);
+    Outliner* pOutliner = pWin->GetOutliner();
+    pOutliner->Clear();
+    pOutliner->SetText(sText, pOutliner->GetParagraph(0));
+}
+
+void CommentsPanel::ToggleResolved(Comment* pComment)
+{
+    if (!pComment)
+        return;
+    sw::annotation::SwAnnotationWin* pWin = getAnnotationWin(pComment);
+    pWin->ToggleResolved();
+}
+
+void CommentsPanel::ReplyComment(Comment* pComment)
+{
+    if (!pComment)
+        return;
+    sw::annotation::SwAnnotationWin* pWin = getAnnotationWin(pComment);
+    pWin->ExecuteCommand(FN_REPLY);
+}
+
+CommentsPanel::~CommentsPanel() {}
+
+void CommentsPanel::NotifyItemUpdate(const sal_uInt16 /*nSid*/, const 
SfxItemState /* eState */,
+                                     const SfxPoolItem* pState)
+{
+    if (!pState) //disposed
+        return;
+}
+}
diff --git a/sw/source/uibase/sidebar/CommentsPanel.hxx 
b/sw/source/uibase/sidebar/CommentsPanel.hxx
new file mode 100644
index 000000000000..3e20ac47798e
--- /dev/null
+++ b/sw/source/uibase/sidebar/CommentsPanel.hxx
@@ -0,0 +1,156 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; 
fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <memory>
+
+#include <sfx2/sidebar/PanelLayout.hxx>
+#include <sfx2/sidebar/ControllerItem.hxx>
+#include <AnnotationWin.hxx>
+#include <svl/poolitem.hxx>
+#include <tools/link.hxx>
+#include <vcl/weld.hxx>
+#include <PostItMgr.hxx>
+#include <postithelper.hxx>
+#include <view.hxx>
+#include <tools/date.hxx>
+#include <tools/datetime.hxx>
+#include <tools/time.hxx>
+
+class SwWrtShell;
+class SwView;
+class SwPostItField;
+class SwFormatField;
+class SwAnnotationWin;
+class SfxBroadcaster;
+class SwPostItMgr;
+class SwSidebarItem;
+
+namespace sw::sidebar
+{
+class CommentsPanel;
+class Comment final
+{
+    friend class CommentsPanel;
+
+private:
+    std::unique_ptr<weld::Builder> mxBuilder;
+    std::unique_ptr<weld::Container> mxContainer;
+    std::unique_ptr<weld::Label> mxAuthor;
+    std::unique_ptr<weld::Label> mxDate;
+    std::unique_ptr<weld::Label> mxTime;
+    std::unique_ptr<weld::Button> mxReply;
+    std::unique_ptr<weld::CheckButton> mxResolve;
+    std::unique_ptr<weld::TextView> mxTextView;
+
+    sw::sidebar::CommentsPanel& mrCommentsPanel;
+    OUString msText;
+    OUString msAuthor;
+    OUString msInitials; //Initials of Author.
+    OUString msName; //Name of the comment
+    Date maDate;
+    tools::Time maTime;
+
+public:
+    Comment(weld::Container* pParent, CommentsPanel& rCommentsPanel);
+    ~Comment();
+    weld::Widget* get_widget() const { return mxContainer.get(); }
+
+    DECL_LINK(ReplyClicked, weld::Button&, void);
+    DECL_LINK(ResolveClicked, weld::Toggleable&, void);
+    DECL_LINK(OnFocusOut, weld::Widget&, void);
+
+    bool mbResolved;
+
+    void InitControls(const SwPostItField* pPostItField);
+    void SetCommentText(OUString sText) { msText = sText; }
+};
+
+class Thread final
+{
+    friend class CommentsPanel;
+
+private:
+    std::unique_ptr<weld::Builder> mxBuilder;
+    std::unique_ptr<weld::Container> mxContainer;
+    std::unique_ptr<weld::Box> mxCommentBox;
+    std::unique_ptr<weld::Label> mxText;
+
+public:
+    Thread(weld::Container* pParent);
+    ~Thread();
+    weld::Widget* get_widget() const { return mxContainer.get(); }
+    weld::Box* getCommentBoxWidget() const { return mxCommentBox.get(); }
+
+    sal_uInt16 mnComments = 0;
+};
+
+class CommentsPanel : public PanelLayout,
+                      public 
::sfx2::sidebar::ControllerItem::ItemUpdateReceiverInterface,
+                      public SfxListener
+{
+public:
+    static std::unique_ptr<PanelLayout> Create(weld::Widget* pParent);
+
+    virtual void NotifyItemUpdate(const sal_uInt16 nSId, const SfxItemState 
eState,
+                                  const SfxPoolItem* pState) override;
+
+    virtual void GetControlState(const sal_uInt16 /*nSId*/,
+                                 boost::property_tree::ptree& /*rState*/) 
override{};
+
+    CommentsPanel(weld::Widget* pParent);
+    virtual ~CommentsPanel() override;
+
+    void Notify(SfxBroadcaster& rBC, const SfxHint& rHint) override;
+
+    void EditComment(Comment* pComment);
+
+    void ToggleResolved(Comment* pComment);
+
+    void ReplyComment(Comment* pComment);
+
+private:
+    SwPostItMgr* mpPostItMgr;
+
+    std::unordered_map<sal_uInt32, std::unique_ptr<Thread>> mpThreadsMap;
+    std::unordered_map<sal_uInt32, std::unique_ptr<Comment>> mpCommentsMap;
+    std::unique_ptr<weld::ComboBox> mxFilterAuthor;
+    std::unique_ptr<weld::ComboBox> mxFilterTime;
+    std::unique_ptr<weld::CheckButton> mxShowTime;
+    std::unique_ptr<weld::CheckButton> mxShowResolved;
+    std::unique_ptr<weld::CheckButton> mxShowReference;
+    std::unique_ptr<weld::RadioButton> mxSortbyPosition;
+    std::unique_ptr<weld::RadioButton> mxSortbyTime;
+    std::unique_ptr<weld::Box> mxThreadsContainer;
+
+    sal_uInt16 mnThreads = 0;
+
+    sw::annotation::SwAnnotationWin* getRootCommentWin(const SwFormatField* 
pField);
+    static sal_uInt32 getPostItId(sw::annotation::SwAnnotationWin* 
pAnnotationWin);
+    sw::annotation::SwAnnotationWin* getAnnotationWin(Comment* pComment);
+
+    void populateComments();
+    void addComment(const SwFormatField* pField);
+    void deleteComment(sw::annotation::SwAnnotationWin* pAnnotationWin);
+    void setResolvedStatus(sw::annotation::SwAnnotationWin* pAnnotationWin);
+    static void editComment(SwPostItField* pPostItField, Comment* pComment);
+};
+
+} //end of namespace sw::sidebar
diff --git a/sw/source/uibase/sidebar/SwPanelFactory.cxx 
b/sw/source/uibase/sidebar/SwPanelFactory.cxx
index 4e5cd83d4116..31f2a3f60ee2 100644
--- a/sw/source/uibase/sidebar/SwPanelFactory.cxx
+++ b/sw/source/uibase/sidebar/SwPanelFactory.cxx
@@ -20,6 +20,7 @@
 #include <com/sun/star/ui/XUIElementFactory.hpp>
 
 #include "A11yCheckIssuesPanel.hxx"
+#include "CommentsPanel.hxx"
 #include "ThemePanel.hxx"
 #include "StylePresetsPanel.hxx"
 #include "PageStylesPanel.hxx"
@@ -40,6 +41,7 @@
 #include <comphelper/namedvaluecollection.hxx>
 #include <comphelper/compbase.hxx>
 #include <cppuhelper/supportsservice.hxx>
+#include <officecfg/Office/Common.hxx>
 
 
 using namespace css;
@@ -198,6 +200,15 @@ Reference<ui::XUIElement> SAL_CALL 
SwPanelFactory::createUIElement (
         xElement = sfx2::sidebar::SidebarPanelBase::Create(
                         rsResourceURL, xFrame, std::move(xPanel), 
ui::LayoutSize(-1,-1,-1));
     }
+    else if (rsResourceURL.endsWith("/CommentsPanel"))
+    {
+        if (officecfg::Office::Common::Misc::ExperimentalMode::get())
+        {
+            std::unique_ptr<PanelLayout> xPanel = 
sw::sidebar::CommentsPanel::Create(pParent);
+            xElement = sfx2::sidebar::SidebarPanelBase::Create(
+                            rsResourceURL, xFrame, std::move(xPanel), 
ui::LayoutSize(-1,-1,-1));
+        }
+    }
     else if (rsResourceURL.endsWith("/A11yCheckIssuesPanel"))
     {
         std::unique_ptr<PanelLayout> xPanel = 
sw::sidebar::A11yCheckIssuesPanel::Create(pParent, pBindings);
diff --git a/sw/uiconfig/swriter/ui/commentspanel.ui 
b/sw/uiconfig/swriter/ui/commentspanel.ui
new file mode 100644
index 000000000000..da3f6d4f70cd
--- /dev/null
+++ b/sw/uiconfig/swriter/ui/commentspanel.ui
@@ -0,0 +1,306 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.40.0 -->
+<interface domain="sw">
+  <requires lib="gtk+" version="3.20"/>
+  <!-- n-columns=1 n-rows=1 -->
+  <object class="GtkGrid" id="CommentsPanel">
+    <property name="visible">True</property>
+    <property name="can-focus">False</property>
+    <property name="hexpand">True</property>
+    <property name="vexpand">True</property>
+    <child>
+      <!-- n-columns=1 n-rows=2 -->
+      <object class="GtkGrid">
+        <property name="visible">True</property>
+        <property name="can-focus">False</property>
+        <property name="hexpand">True</property>
+        <property name="vexpand">True</property>
+        <property name="border-width">6</property>
+        <child>
+          <object class="GtkExpander" id="options">
+            <property name="visible">True</property>
+            <property name="can-focus">True</property>
+            <property name="expanded">True</property>
+            <child>
+              <!-- n-columns=2 n-rows=3 -->
+              <object class="GtkGrid" id="grid1">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="hexpand">True</property>
+                <property name="row-spacing">6</property>
+                <property name="column-spacing">6</property>
+                <child>
+                  <object class="GtkLabel" id="label_sortby">
+                    <property name="visible">True</property>
+                    <property name="can-focus">False</property>
+                    <property name="halign">center</property>
+                    <property name="hexpand">True</property>
+                    <property name="label" translatable="yes" 
context="commentspanel|label_sortby">Sort by:</property>
+                    <property name="use-underline">True</property>
+                    <property name="mnemonic-widget">sortby_options</property>
+                  </object>
+                  <packing>
+                    <property name="left-attach">0</property>
+                    <property name="top-attach">2</property>
+                  </packing>
+                </child>
+                <child>
+                  <!-- n-columns=2 n-rows=1 -->
+                  <object class="GtkGrid" id="sortby_options">
+                    <property name="visible">True</property>
+                    <property name="can-focus">False</property>
+                    <property name="hexpand">True</property>
+                    <child>
+                      <object class="GtkRadioButton" id="sortby_position">
+                        <property name="label" translatable="yes" 
context="commentspanel|radiobutton_position">Position</property>
+                        <property name="visible">True</property>
+                        <property name="can-focus">True</property>
+                        <property name="receives-default">False</property>
+                        <property name="halign">center</property>
+                        <property name="hexpand">True</property>
+                        <property name="use-underline">True</property>
+                        <property name="draw-indicator">True</property>
+                      </object>
+                      <packing>
+                        <property name="left-attach">0</property>
+                        <property name="top-attach">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkRadioButton" id="sortby_time">
+                        <property name="label" translatable="yes" 
context="commentspanel|radiobutton_time">Time</property>
+                        <property name="visible">True</property>
+                        <property name="can-focus">True</property>
+                        <property name="receives-default">False</property>
+                        <property name="halign">center</property>
+                        <property name="hexpand">True</property>
+                        <property name="use-underline">True</property>
+                        <property name="draw-indicator">True</property>
+                      </object>
+                      <packing>
+                        <property name="left-attach">1</property>
+                        <property name="top-attach">0</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="left-attach">1</property>
+                    <property name="top-attach">2</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="label_show">
+                    <property name="visible">True</property>
+                    <property name="can-focus">False</property>
+                    <property name="halign">center</property>
+                    <property name="hexpand">True</property>
+                    <property name="label" translatable="yes" 
context="commentspanel|label_show">Show:</property>
+                    <property name="use-underline">True</property>
+                    <property name="mnemonic-widget">show_options</property>
+                  </object>
+                  <packing>
+                    <property name="left-attach">0</property>
+                    <property name="top-attach">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <!-- n-columns=3 n-rows=1 -->
+                  <object class="GtkGrid" id="show_options">
+                    <property name="visible">True</property>
+                    <property name="can-focus">False</property>
+                    <child>
+                      <object class="GtkCheckButton" id="show_time">
+                        <property name="label" translatable="yes" 
context="commentspanel|checkbutton_time">Time</property>
+                        <property name="visible">True</property>
+                        <property name="can-focus">True</property>
+                        <property name="receives-default">False</property>
+                        <property name="halign">center</property>
+                        <property name="hexpand">True</property>
+                        <property name="use-underline">True</property>
+                        <property name="draw-indicator">True</property>
+                      </object>
+                      <packing>
+                        <property name="left-attach">0</property>
+                        <property name="top-attach">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkCheckButton" id="show_resolved">
+                        <property name="label" translatable="yes" 
context="commentspanel|checkbutton_resolved">Resolved</property>
+                        <property name="visible">True</property>
+                        <property name="can-focus">True</property>
+                        <property name="receives-default">False</property>
+                        <property name="halign">center</property>
+                        <property name="hexpand">True</property>
+                        <property name="use-underline">True</property>
+                        <property name="draw-indicator">True</property>
+                      </object>
+                      <packing>
+                        <property name="left-attach">1</property>
+                        <property name="top-attach">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkCheckButton" id="show_reference">
+                        <property name="label" translatable="yes" 
context="commentspanel|checkbutton_reference">Reference</property>
+                        <property name="visible">True</property>
+                        <property name="can-focus">True</property>
+                        <property name="receives-default">False</property>
+                        <property name="halign">center</property>
+                        <property name="hexpand">True</property>
+                        <property name="use-underline">True</property>
+                        <property name="draw-indicator">True</property>
+                      </object>
+                      <packing>
+                        <property name="left-attach">2</property>
+                        <property name="top-attach">0</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="left-attach">1</property>
+                    <property name="top-attach">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="label_filter">
+                    <property name="visible">True</property>
+                    <property name="can-focus">False</property>
+                    <property name="halign">center</property>
+                    <property name="valign">start</property>
+                    <property name="hexpand">True</property>
+                    <property name="label" translatable="yes" 
context="commentspanel|label_filter">Filter:</property>
+                    <property name="use-underline">True</property>
+                    <property name="mnemonic-widget">filter_options</property>
+                  </object>
+                  <packing>
+                    <property name="left-attach">0</property>
+                    <property name="top-attach">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <!-- n-columns=2 n-rows=2 -->
+                  <object class="GtkGrid" id="filter_options">
+                    <property name="visible">True</property>
+                    <property name="can-focus">False</property>
+                    <property name="row-spacing">3</property>
+                    <property name="column-spacing">6</property>
+                    <child>
+                      <object class="GtkLabel" id="label_author">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="halign">start</property>
+                        <property name="hexpand">True</property>
+                        <property name="label" translatable="yes" 
context="commentspanel|label_author">Author</property>
+                        <property name="use-underline">True</property>
+                        <property 
name="mnemonic-widget">filter_author</property>
+                      </object>
+                      <packing>
+                        <property name="left-attach">1</property>
+                        <property name="top-attach">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkLabel" id="label_time">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="halign">start</property>
+                        <property name="hexpand">True</property>
+                        <property name="label" translatable="yes" 
context="commentspanel|label_time">Time</property>
+                        <property name="use-underline">True</property>
+                        <property name="mnemonic-widget">filter_time</property>
+                      </object>
+                      <packing>
+                        <property name="left-attach">1</property>
+                        <property name="top-attach">1</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkComboBoxText" id="filter_author">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="hexpand">True</property>
+                      </object>
+                      <packing>
+                        <property name="left-attach">0</property>
+                        <property name="top-attach">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkComboBoxText" id="filter_time">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="hexpand">True</property>
+                      </object>
+                      <packing>
+                        <property name="left-attach">0</property>
+                        <property name="top-attach">1</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="left-attach">1</property>
+                    <property name="top-attach">0</property>
+                  </packing>
+                </child>
+              </object>
+            </child>
+            <child type="label">
+              <object class="GtkLabel" id="options_label">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="label" translatable="yes" 
context="commentspanel|options_label">Options</property>
+                <attributes>
+                  <attribute name="weight" value="ultrabold"/>
+                </attributes>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="left-attach">0</property>
+            <property name="top-attach">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkScrolledWindow" id="scrolledwindow">
+            <property name="visible">True</property>
+            <property name="can-focus">True</property>
+            <property name="hexpand">True</property>
+            <property name="vexpand">True</property>
+            <property name="hscrollbar-policy">never</property>
+            <child>
+              <object class="GtkViewport">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="hexpand">True</property>
+                <property name="vexpand">True</property>
+                <child>
+                  <object class="GtkBox" id="comment_threads">
+                    <property name="visible">True</property>
+                    <property name="can-focus">False</property>
+                    <property name="valign">start</property>
+                    <property name="hexpand">True</property>
+                    <property name="vexpand">True</property>
+                    <property name="orientation">vertical</property>
+                    <property name="baseline-position">top</property>
+                    <child>
+                      <placeholder/>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="left-attach">0</property>
+            <property name="top-attach">1</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="left-attach">0</property>
+        <property name="top-attach">0</property>
+      </packing>
+    </child>
+  </object>
+</interface>
diff --git a/sw/uiconfig/swriter/ui/commentsthread.ui 
b/sw/uiconfig/swriter/ui/commentsthread.ui
new file mode 100644
index 000000000000..9960a3fe63cb
--- /dev/null
+++ b/sw/uiconfig/swriter/ui/commentsthread.ui
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.40.0 -->
+<interface domain="sw">
+  <requires lib="gtk+" version="3.20"/>
+  <!-- n-columns=1 n-rows=1 -->
+  <object class="GtkGrid" id="Thread">
+    <property name="visible">True</property>
+    <property name="can-focus">False</property>
+    <child>
+      <object class="GtkExpander">
+        <property name="visible">True</property>
+        <property name="can-focus">True</property>
+        <property name="hexpand">True</property>
+        <property name="expanded">True</property>
+        <child>
+          <object class="GtkBox" id="comments_box">
+            <property name="visible">True</property>
+            <property name="can-focus">False</property>
+            <property name="orientation">vertical</property>
+            <child>
+              <placeholder/>
+            </child>
+          </object>
+        </child>
+        <child type="label">
+          <object class="GtkLabel" id="commentedtext">
+            <property name="visible">True</property>
+            <property name="can-focus">False</property>
+            <property name="hexpand">True</property>
+            <property name="label" translatable="yes" 
context="commentspanel|referencetext">commentedtext</property>
+          </object>
+        </child>
+      </object>
+      <packing>
+        <property name="left-attach">0</property>
+        <property name="top-attach">0</property>
+      </packing>
+    </child>
+  </object>
+</interface>
diff --git a/sw/uiconfig/swriter/ui/commentwidget.ui 
b/sw/uiconfig/swriter/ui/commentwidget.ui
new file mode 100644
index 000000000000..7d0e66480eb4
--- /dev/null
+++ b/sw/uiconfig/swriter/ui/commentwidget.ui
@@ -0,0 +1,170 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.40.0 -->
+<interface domain="sw">
+  <requires lib="gtk+" version="3.20"/>
+  <!-- n-columns=1 n-rows=1 -->
+  <object class="GtkGrid" id="Comment">
+    <property name="visible">True</property>
+    <property name="can-focus">False</property>
+    <child>
+      <object class="GtkExpander">
+        <property name="height-request">-1</property>
+        <property name="visible">True</property>
+        <property name="can-focus">True</property>
+        <property name="valign">start</property>
+        <property name="hexpand">True</property>
+        <property name="vexpand">True</property>
+        <property name="expanded">True</property>
+        <property name="label-fill">True</property>
+        <property name="resize-toplevel">True</property>
+        <child>
+          <!-- n-columns=1 n-rows=2 -->
+          <object class="GtkGrid">
+            <property name="height-request">-1</property>
+            <property name="visible">True</property>
+            <property name="can-focus">False</property>
+            <property name="valign">start</property>
+            <property name="hexpand">True</property>
+            <property name="vexpand">True</property>
+            <child>
+              <!-- n-columns=5 n-rows=1 -->
+              <object class="GtkGrid" id="grid1">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="valign">start</property>
+                <property name="column-homogeneous">True</property>
+                <child>
+                  <object class="GtkLabel" id="authorlabel">
+                    <property name="visible">True</property>
+                    <property name="can-focus">False</property>
+                    <property name="hexpand">True</property>
+                    <property name="label" translatable="yes" 
context="commentspanel|authorlabel">author</property>
+                  </object>
+                  <packing>
+                    <property name="left-attach">0</property>
+                    <property name="top-attach">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="datelabel">
+                    <property name="visible">True</property>
+                    <property name="can-focus">False</property>
+                    <property name="hexpand">True</property>
+                    <property name="label" translatable="yes" 
context="commentspanel|datelabel">date</property>
+                  </object>
+                  <packing>
+                    <property name="left-attach">1</property>
+                    <property name="top-attach">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkButton" id="replybutton">
+                    <property name="label" translatable="yes" 
context="commentspanel|replybutton">Reply</property>
+                    <property name="visible">True</property>
+                    <property name="can-focus">True</property>
+                    <property name="receives-default">True</property>
+                    <property name="hexpand">True</property>
+                  </object>
+                  <packing>
+                    <property name="left-attach">3</property>
+                    <property name="top-attach">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="timelabel">
+                    <property name="visible">True</property>
+                    <property name="can-focus">False</property>
+                    <property name="hexpand">True</property>
+                    <property name="label" translatable="yes" 
context="commentspanel|timelabel">time</property>
+                  </object>
+                  <packing>
+                    <property name="left-attach">2</property>
+                    <property name="top-attach">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkCheckButton" id="resolvebutton">
+                    <property name="label" translatable="yes" 
context="commentspanel|resolvebutton"> </property>
+                    <property name="visible">True</property>
+                    <property name="can-focus">True</property>
+                    <property name="receives-default">False</property>
+                    <property name="halign">center</property>
+                    <property name="draw-indicator">True</property>
+                  </object>
+                  <packing>
+                    <property name="left-attach">4</property>
+                    <property name="top-attach">0</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="left-attach">0</property>
+                <property name="top-attach">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkScrolledWindow">
+                <property name="height-request">100</property>
+                <property name="visible">True</property>
+                <property name="can-focus">True</property>
+                <property name="valign">start</property>
+                <property name="hexpand">True</property>
+                <property name="vexpand">True</property>
+                <property name="shadow-type">in</property>
+                <child>
+                  <object class="GtkViewport">
+                    <property name="height-request">100</property>
+                    <property name="visible">True</property>
+                    <property name="can-focus">False</property>
+                    <property name="valign">start</property>
+                    <child>
+                      <object class="GtkBox">
+                        <property name="height-request">100</property>
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="valign">start</property>
+                        <property name="orientation">vertical</property>
+                        <child>
+                          <object class="GtkTextView" id="textview">
+                            <property name="height-request">100</property>
+                            <property name="visible">True</property>
+                            <property name="can-focus">True</property>
+                            <property name="valign">start</property>
+                            <property name="hexpand">True</property>
+                            <property name="vexpand">True</property>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="left-attach">0</property>
+                <property name="top-attach">1</property>
+              </packing>
+            </child>
+          </object>
+        </child>
+        <child type="label">
+          <object class="GtkLabel" id="collapsecommentbutton">
+            <property name="visible">True</property>
+            <property name="can-focus">False</property>
+            <property name="label" translatable="yes" 
context="commentspanel|collapsecommentbutton">collapse</property>
+            <property name="use-underline">True</property>
+            <property name="mnemonic-widget">textview</property>
+          </object>
+        </child>
+      </object>
+      <packing>
+        <property name="left-attach">0</property>
+        <property name="top-attach">0</property>
+      </packing>
+    </child>
+  </object>
+</interface>
diff --git a/tools/source/datetime/datetimeutils.cxx 
b/tools/source/datetime/datetimeutils.cxx
index 345e18f4a721..b102b1f410e5 100644
--- a/tools/source/datetime/datetimeutils.cxx
+++ b/tools/source/datetime/datetimeutils.cxx
@@ -74,6 +74,12 @@ OString DateToOString( const Date& rDate )
     return DateTimeToOString( DateTime( rDate, aTime ) );
 }
 
+OString TimeToOString( const tools::Time& rTime )
+{
+    Date aDate( Date::EMPTY );
+    return DateTimeToOString( DateTime( aDate, rTime ) );
+}
+
 OUString DateToDDMMYYYYOUString( const Date& rDate )
 {
     OUStringBuffer aBuffer( 25 );

Reply via email to