sw/source/uibase/sidebar/CommentsPanel.cxx |  209 +++++++++++++++++++++--------
 sw/source/uibase/sidebar/CommentsPanel.hxx |   13 +
 sw/uiconfig/swriter/ui/commentspanel.ui    |    2 
 3 files changed, 172 insertions(+), 52 deletions(-)

New commits:
commit c1936307755ae75741c91f89f9bda3a4eed1a274
Author:     Mohit Marathe <mohitmara...@proton.me>
AuthorDate: Fri Jul 12 19:51:47 2024 +0530
Commit:     Sarper Akdemir <sarper.akde...@allotropia.de>
CommitDate: Fri Sep 13 12:37:00 2024 +0200

    sort comments by time or position
    
    Change-Id: I1f4014e20b4baaca0dde742e7384397c1311f926
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/170492
    Reviewed-by: Sarper Akdemir <sarper.akde...@allotropia.de>
    Tested-by: Jenkins

diff --git a/sw/source/uibase/sidebar/CommentsPanel.cxx 
b/sw/source/uibase/sidebar/CommentsPanel.cxx
index 1e5e3e4ea1eb..86f38f17829d 100644
--- a/sw/source/uibase/sidebar/CommentsPanel.cxx
+++ b/sw/source/uibase/sidebar/CommentsPanel.cxx
@@ -25,6 +25,8 @@
 #include <AnnotationWin.hxx>
 #include <fmtfld.hxx>
 #include <docufld.hxx>
+#include <txtfld.hxx>
+#include <ndtxt.hxx>
 #include <swmodule.hxx>
 #include <vcl/svapp.hxx>
 #include <rtl/ustring.hxx>
@@ -46,6 +48,7 @@
 #include <cmdid.h>
 
 #include "CommentsPanel.hxx"
+#include <pam.hxx>
 
 #include <com/sun/star/lang/IllegalArgumentException.hpp>
 
@@ -84,29 +87,15 @@ void Comment::InitControls(const SwPostItField* 
pPostItField)
     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)
+    OUString sDate = sw::sidebar::CommentsPanel::FormatDate(maDate);
+    OUString sTime = sw::sidebar::CommentsPanel::FormatTime(maTime);
+    if (mxDate->get_label() != sDate)
     {
-        sMeta = " " + rLocalData.getTime(pPostItField->GetTime(), false);
+        mxDate->set_label(sDate);
     }
-    if (mxTime->get_label() != sMeta)
+    if (mxTime->get_label() != sTime)
     {
-        mxTime->set_label(sMeta);
+        mxTime->set_label(sTime);
     }
 
     mxAuthor->set_label(msAuthor);
@@ -155,6 +144,9 @@ CommentsPanel::CommentsPanel(weld::Widget* pParent)
     , mxSortbyTime(m_xBuilder->weld_radio_button("sortby_time"))
     , mxThreadsContainer(m_xBuilder->weld_box("comment_threads"))
 {
+    mxSortbyPosition->connect_toggled(LINK(this, CommentsPanel, SortHdl));
+    mxSortbyTime->connect_toggled(LINK(this, CommentsPanel, SortHdl));
+
     SwView* pView = GetActiveView();
     if (!pView)
         return;
@@ -165,6 +157,8 @@ CommentsPanel::CommentsPanel(weld::Widget* pParent)
     StartListening(*mpPostItMgr);
 }
 
+IMPL_LINK_NOARG(CommentsPanel, SortHdl, weld::Toggleable&, void) { 
populateComments(); }
+
 void CommentsPanel::Notify(SfxBroadcaster& rBC, const SfxHint& rHint)
 {
     if (rHint.GetId() == SfxHintId::SwFormatField)
@@ -195,7 +189,8 @@ void CommentsPanel::Notify(SfxBroadcaster& rBC, const 
SfxHint& rHint)
             {
                 sw::annotation::SwAnnotationWin* pAnnotationWin
                     = mpPostItMgr->GetRemovedAnnotationWin(pField);
-                deleteComment(pAnnotationWin);
+                sal_uInt32 nId = getPostItId(pAnnotationWin);
+                deleteComment(nId);
                 break;
             }
             case SwFormatFieldHintWhich::FOCUS:
@@ -216,6 +211,34 @@ void CommentsPanel::Notify(SfxBroadcaster& rBC, const 
SfxHint& rHint)
     }
 }
 
+OUString CommentsPanel::FormatDate(Date& rDate)
+{
+    const SvtSysLocale aSysLocale;
+    const LocaleDataWrapper& rLocalData = aSysLocale.GetLocaleData();
+    OUString sMeta;
+    if (rDate.IsValidAndGregorian())
+    {
+        sMeta = rLocalData.getDate(rDate);
+    }
+    else
+    {
+        sMeta = SwResId(STR_NODATE);
+    }
+    return sMeta;
+}
+
+OUString CommentsPanel::FormatTime(tools::Time& rTime)
+{
+    const SvtSysLocale aSysLocale;
+    const LocaleDataWrapper& rLocalData = aSysLocale.GetLocaleData();
+    OUString sMeta;
+    if (rTime.GetTime() != 0)
+    {
+        sMeta = " " + rLocalData.getTime(rTime, false);
+    }
+    return sMeta;
+}
+
 sw::annotation::SwAnnotationWin* CommentsPanel::getRootCommentWin(const 
SwFormatField* pFormatField)
 {
     if (!pFormatField)
@@ -261,40 +284,125 @@ sw::annotation::SwAnnotationWin* 
CommentsPanel::getAnnotationWin(Comment* pComme
     return mpPostItMgr->GetAnnotationWin(pPostItField);
 }
 
+bool CommentsPanel::comp_dateTime(SwFormatField* a, SwFormatField* b)
+{
+    SwPostItField* pA = static_cast<SwPostItField*>(a->GetField());
+    SwPostItField* pB = static_cast<SwPostItField*>(b->GetField());
+
+    Date aDateA(pA->GetDateTime().GetDate());
+    tools::Time aTimeA(pA->GetDateTime().GetTime());
+    Date aDateB(pB->GetDateTime().GetDate());
+    tools::Time aTimeB(pB->GetDateTime().GetTime());
+
+    OUString sDateTimeA = FormatTime(aTimeA) + " " + FormatDate(aDateA);
+    OUString sDateTimeB = FormatTime(aTimeB) + " " + FormatDate(aDateB);
+
+    return sDateTimeA > sDateTimeB;
+}
+
+SwPosition CommentsPanel::getAnchorPosition(SwFormatField* pField)
+{
+    SwTextField* pTextField = pField->GetTextField();
+    SwTextNode* pTextNode = pTextField->GetpTextNode();
+
+    SwPosition aPos(*pTextNode, pTextField->GetStart());
+    return aPos;
+}
+
+bool CommentsPanel::comp_position(SwFormatField* a, SwFormatField* b)
+{
+    SwPosition aPosA = getAnchorPosition(a);
+    SwPosition aPosB = getAnchorPosition(b);
+
+    return aPosA < aPosB;
+}
+
 void CommentsPanel::populateComments()
 {
+    if (!mpCommentsMap.empty())
+    {
+        for (auto it = mpCommentsMap.begin(); it != mpCommentsMap.end();)
+        {
+            sal_uInt32 nId = it->first;
+            it++;
+            deleteComment(nId);
+        }
+    }
+
     if (!mpPostItMgr)
         return;
     std::vector<SwFormatField*> vFormatFields = 
mpPostItMgr->UpdatePostItsParentInfo();
+    if (mxSortbyTime->get_active())
+    {
+        std::sort(vFormatFields.begin(), vFormatFields.end(),
+                  [](SwFormatField* a, SwFormatField* b) {
+                      return sw::sidebar::CommentsPanel::comp_dateTime(a, b);
+                  });
+    }
+    else
+    {
+        std::stable_sort(vFormatFields.begin(), vFormatFields.end(),
+                         [](SwFormatField* a, SwFormatField* b) {
+                             return 
sw::sidebar::CommentsPanel::comp_position(a, b);
+                         });
+    }
 
     for (auto pFormatField : vFormatFields)
     {
         sw::annotation::SwAnnotationWin* pRootNote = 
getRootCommentWin(pFormatField);
         if (!pRootNote)
             continue;
-        sal_uInt32 nPostItId = getPostItId(pRootNote);
+        sal_uInt32 nRootId = getPostItId(pRootNote);
 
-        if (mpThreadsMap.find(nPostItId) != mpThreadsMap.end())
-            continue; // Skip if root comment is already present
+        if (mpThreadsMap.find(nRootId) != mpThreadsMap.end())
+        {
+            if (mxSortbyPosition->get_active())
+                continue;
+            else
+            {
+                auto pThread = mpThreadsMap[nRootId].get();
+                SwPostItField* pPostItField = 
static_cast<SwPostItField*>(pFormatField->GetField());
+                sal_uInt32 nId = pPostItField->GetPostItId();
+                auto pComment = 
std::make_unique<Comment>(pThread->getCommentBoxWidget(), *this);
+                
pThread->getCommentBoxWidget()->reorder_child(pComment->get_widget(),
+                                                              
pThread->mnComments++);
+                pComment->InitControls(pPostItField);
+                mpCommentsMap[nId] = std::move(pComment);
+                continue;
+            }
+        }
 
         auto pThread = std::make_unique<Thread>(mxThreadsContainer.get());
         mxThreadsContainer->reorder_child(pThread->get_widget(), mnThreads++);
 
-        for (sw::annotation::SwAnnotationWin* pCurrent = pRootNote;;)
+        if (mxSortbyPosition->get_active())
+        {
+            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;
+            }
+        }
+        else
         {
-            sal_uInt32 nId = getPostItId(pCurrent);
+            SwPostItField* pPostItField = 
static_cast<SwPostItField*>(pFormatField->GetField());
+            sal_uInt32 nId = pPostItField->GetPostItId();
             auto pComment = 
std::make_unique<Comment>(pThread->getCommentBoxWidget(), *this);
             
pThread->getCommentBoxWidget()->reorder_child(pComment->get_widget(),
                                                           
pThread->mnComments++);
-            pComment->InitControls(pCurrent->GetPostItField());
+            pComment->InitControls(pPostItField);
             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);
+        mpThreadsMap[nRootId] = std::move(pThread);
     }
 }
 
@@ -337,35 +445,34 @@ void CommentsPanel::addComment(const SwFormatField* 
pField)
         pComment->InitControls(pNote->GetPostItField());
         mpCommentsMap[nNoteId] = std::move(pComment);
     }
+    populateComments();
 }
 
-void CommentsPanel::deleteComment(sw::annotation::SwAnnotationWin* 
pAnnotationWin)
+void CommentsPanel::deleteComment(sal_uInt32 nId)
 {
-    if (!pAnnotationWin)
-        return;
-    sal_uInt32 nId = getPostItId(pAnnotationWin);
+    sw::annotation::SwAnnotationWin* pAnnotationWin = 
getAnnotationWin(mpCommentsMap[nId].get());
     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);
-    }
+    sw::annotation::SwAnnotationWin* pRootNote = 
getRootCommentWin(pFormatField);
+    // // 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 = mpThreadsMap[nId];
+    // }
+    // else
+    // {
+    //     pRootNote = getRootCommentWin(pFormatField);
+    // }
 
     sal_uInt32 nRootId = getPostItId(pRootNote);
 
     if (mpThreadsMap.find(nRootId) == mpThreadsMap.end())
-        return;
+        throw std::runtime_error("Cannot delete comment: Thread does not 
exist");
     auto& pComment = mpCommentsMap[nId];
     auto& pThread = mpThreadsMap[nRootId];
     if (!pComment)
-        return;
+        throw std::runtime_error("Cannot delete comment: Comment does not 
exist");
 
     pThread->getCommentBoxWidget()->move(pComment->get_widget(), nullptr);
     mpCommentsMap.erase(nId);
diff --git a/sw/source/uibase/sidebar/CommentsPanel.hxx 
b/sw/source/uibase/sidebar/CommentsPanel.hxx
index 3e20ac47798e..9c214d88bb56 100644
--- a/sw/source/uibase/sidebar/CommentsPanel.hxx
+++ b/sw/source/uibase/sidebar/CommentsPanel.hxx
@@ -126,6 +126,12 @@ public:
 
     void ReplyComment(Comment* pComment);
 
+    DECL_LINK(SortHdl, weld::Toggleable&, void);
+
+    // utility functions
+    static OUString FormatDate(Date& rDate);
+    static OUString FormatTime(tools::Time& rTime);
+
 private:
     SwPostItMgr* mpPostItMgr;
 
@@ -142,13 +148,18 @@ private:
 
     sal_uInt16 mnThreads = 0;
 
+    // utility functions
     sw::annotation::SwAnnotationWin* getRootCommentWin(const SwFormatField* 
pField);
     static sal_uInt32 getPostItId(sw::annotation::SwAnnotationWin* 
pAnnotationWin);
     sw::annotation::SwAnnotationWin* getAnnotationWin(Comment* pComment);
+    static bool comp_dateTime(SwFormatField* a, SwFormatField* b);
+    static SwPosition getAnchorPosition(SwFormatField* pField);
+    static bool comp_position(SwFormatField* a, SwFormatField* b);
 
+    // event handlers (To sync with AnnotationWin)
     void populateComments();
     void addComment(const SwFormatField* pField);
-    void deleteComment(sw::annotation::SwAnnotationWin* pAnnotationWin);
+    void deleteComment(sal_uInt32 nId);
     void setResolvedStatus(sw::annotation::SwAnnotationWin* pAnnotationWin);
     static void editComment(SwPostItField* pPostItField, Comment* pComment);
 };
diff --git a/sw/uiconfig/swriter/ui/commentspanel.ui 
b/sw/uiconfig/swriter/ui/commentspanel.ui
index da3f6d4f70cd..739e5f18a38c 100644
--- a/sw/uiconfig/swriter/ui/commentspanel.ui
+++ b/sw/uiconfig/swriter/ui/commentspanel.ui
@@ -59,6 +59,7 @@
                         <property name="halign">center</property>
                         <property name="hexpand">True</property>
                         <property name="use-underline">True</property>
+                        <property name="active">True</property>
                         <property name="draw-indicator">True</property>
                       </object>
                       <packing>
@@ -76,6 +77,7 @@
                         <property name="hexpand">True</property>
                         <property name="use-underline">True</property>
                         <property name="draw-indicator">True</property>
+                        <property name="group">sortby_position</property>
                       </object>
                       <packing>
                         <property name="left-attach">1</property>

Reply via email to