summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPranav Kant <pranavk@collabora.co.uk>2017-01-24 14:07:45 +0530
committerpranavk <pranavk@collabora.co.uk>2017-01-27 11:50:02 +0000
commit5f5073a84518e4a8660e0153c2e218fb75a85ec4 (patch)
tree586e7c8193d67e2e8c53c0d04f14a09d25ecbf44
parenta623b3a449dfcddaad5b621ff1c0b7a520edf4d6 (diff)
lok: Implement new callbacks for comment notifications
Change-Id: I298183b295c68c4a39cb1f6fffe4b89b4eaee0f3 Reviewed-on: https://gerrit.libreoffice.org/33469 Reviewed-by: pranavk <pranavk@collabora.co.uk> Tested-by: pranavk <pranavk@collabora.co.uk>
-rw-r--r--include/LibreOfficeKit/LibreOfficeKitEnums.h26
-rw-r--r--libreofficekit/source/gtk/lokdocview.cxx4
-rw-r--r--sw/inc/PostItMgr.hxx2
-rw-r--r--sw/source/uibase/docvw/PostItMgr.cxx158
4 files changed, 154 insertions, 36 deletions
diff --git a/include/LibreOfficeKit/LibreOfficeKitEnums.h b/include/LibreOfficeKit/LibreOfficeKitEnums.h
index f3dccd037830..8a59b4cc8ad1 100644
--- a/include/LibreOfficeKit/LibreOfficeKitEnums.h
+++ b/include/LibreOfficeKit/LibreOfficeKitEnums.h
@@ -467,6 +467,32 @@ typedef enum
* - 'action' is 'Modify'.
*/
LOK_CALLBACK_REDLINE_TABLE_ENTRY_MODIFIED = 31,
+
+ /**
+ * There is some change in comments in the document
+ *
+ * The payload example:
+ * {
+ * "comment": {
+ * "action": "Add",
+ * "id": "11",
+ * "parent": "4",
+ * "author": "Unknown Author",
+ * "text": "",
+ * "dateTime": "2016-08-18T13:13:00",
+ * "anchorPos": "4529, 3906",
+ * "textRange": "1418, 3906, 3111, 919"
+ * }
+ * }
+ *
+ * The format is the same as an entry of
+ * lok::Document::getCommandValues('.uno:ViewAnnotations'), extra
+ * fields:
+ *
+ * - 'action' can be 'Add', 'Remove' or 'Modify' depending on whether
+ * comment has been added, removed or modified.
+ */
+ LOK_CALLBACK_COMMENT = 32
}
LibreOfficeKitCallbackType;
diff --git a/libreofficekit/source/gtk/lokdocview.cxx b/libreofficekit/source/gtk/lokdocview.cxx
index c9c32afcab40..1cd2c05c2567 100644
--- a/libreofficekit/source/gtk/lokdocview.cxx
+++ b/libreofficekit/source/gtk/lokdocview.cxx
@@ -426,6 +426,8 @@ callbackTypeToString (int nType)
return "LOK_CALLBACK_REDLINE_TABLE_SIZE_CHANGED";
case LOK_CALLBACK_REDLINE_TABLE_ENTRY_MODIFIED:
return "LOK_CALLBACK_REDLINE_TABLE_ENTRY_MODIFIED";
+ case LOK_CALLBACK_COMMENT:
+ return "LOK_CALLBACK_COMMENT";
}
g_assert(false);
return nullptr;
@@ -1395,6 +1397,8 @@ callback (gpointer pData)
{
break;
}
+ case LOK_CALLBACK_COMMENT:
+ break;
default:
g_assert(false);
break;
diff --git a/sw/inc/PostItMgr.hxx b/sw/inc/PostItMgr.hxx
index 68887aa73a5d..97448fdd513d 100644
--- a/sw/inc/PostItMgr.hxx
+++ b/sw/inc/PostItMgr.hxx
@@ -186,7 +186,7 @@ class SwPostItMgr: public SfxListener
sw::sidebarwindows::SwSidebarWin* GetSidebarWin(const SfxBroadcaster* pBroadcaster) const;
- void InsertItem( SfxBroadcaster* pItem, bool bCheckExistance, bool bFocus);
+ SwSidebarItem* InsertItem( SfxBroadcaster* pItem, bool bCheckExistance, bool bFocus);
void RemoveItem( SfxBroadcaster* pBroadcast );
public:
diff --git a/sw/source/uibase/docvw/PostItMgr.cxx b/sw/source/uibase/docvw/PostItMgr.cxx
index d169a89a99b8..43b1b55b7db0 100644
--- a/sw/source/uibase/docvw/PostItMgr.cxx
+++ b/sw/source/uibase/docvw/PostItMgr.cxx
@@ -17,11 +17,13 @@
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
+#include <boost/property_tree/json_parser.hpp>
+
#include "PostItMgr.hxx"
#include <postithelper.hxx>
-#include <SidebarWin.hxx>
#include <AnnotationWin.hxx>
+#include <SidebarWin.hxx>
#include <frmsidebarwincontainer.hxx>
#include <accmap.hxx>
@@ -53,6 +55,7 @@
#include <docary.hxx>
#include <SwRewriter.hxx>
#include <tools/color.hxx>
+#include <unotools/datetime.hxx>
#include <swmodule.hxx>
#include <annotation.hrc>
@@ -75,6 +78,8 @@
#include <i18nlangtag/mslangid.hxx>
#include <i18nlangtag/lang.h>
#include <comphelper/lok.hxx>
+#include <comphelper/string.hxx>
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
#include "annotsh.hxx"
#include "swabstdlg.hxx"
@@ -94,37 +99,89 @@
using namespace sw::sidebarwindows;
-bool comp_pos(const SwSidebarItem* a, const SwSidebarItem* b)
-{
- // sort by anchor position
- SwPosition aPosAnchorA = a->GetAnchorPosition();
- SwPosition aPosAnchorB = b->GetAnchorPosition();
+namespace {
- bool aAnchorAInFooter = false;
- bool aAnchorBInFooter = false;
+ enum class CommentNotificationType { Add, Remove, Modify };
- // is the anchor placed in Footnote or the Footer?
- if( aPosAnchorA.nNode.GetNode().FindFootnoteStartNode() || aPosAnchorA.nNode.GetNode().FindFooterStartNode() )
- aAnchorAInFooter = true;
- if( aPosAnchorB.nNode.GetNode().FindFootnoteStartNode() || aPosAnchorB.nNode.GetNode().FindFooterStartNode() )
- aAnchorBInFooter = true;
+ bool comp_pos(const SwSidebarItem* a, const SwSidebarItem* b)
+ {
+ // sort by anchor position
+ SwPosition aPosAnchorA = a->GetAnchorPosition();
+ SwPosition aPosAnchorB = b->GetAnchorPosition();
- // fdo#34800
- // if AnchorA is in footnote, and AnchorB isn't
- // we do not want to change over the position
- if( aAnchorAInFooter && !aAnchorBInFooter )
- return false;
- // if aAnchorA is not placed in a footnote, and aAnchorB is
- // force a change over
- else if( !aAnchorAInFooter && aAnchorBInFooter )
- return true;
- // If neither or both are in the footer, compare the positions.
- // Since footnotes are in Inserts section of nodes array and footers
- // in Autotext section, all footnotes precede any footers so no need
- // to check that.
- else
- return aPosAnchorA < aPosAnchorB;
-}
+ bool aAnchorAInFooter = false;
+ bool aAnchorBInFooter = false;
+
+ // is the anchor placed in Footnote or the Footer?
+ if( aPosAnchorA.nNode.GetNode().FindFootnoteStartNode() || aPosAnchorA.nNode.GetNode().FindFooterStartNode() )
+ aAnchorAInFooter = true;
+ if( aPosAnchorB.nNode.GetNode().FindFootnoteStartNode() || aPosAnchorB.nNode.GetNode().FindFooterStartNode() )
+ aAnchorBInFooter = true;
+
+ // fdo#34800
+ // if AnchorA is in footnote, and AnchorB isn't
+ // we do not want to change over the position
+ if( aAnchorAInFooter && !aAnchorBInFooter )
+ return false;
+ // if aAnchorA is not placed in a footnote, and aAnchorB is
+ // force a change over
+ else if( !aAnchorAInFooter && aAnchorBInFooter )
+ return true;
+ // If neither or both are in the footer, compare the positions.
+ // Since footnotes are in Inserts section of nodes array and footers
+ // in Autotext section, all footnotes precede any footers so no need
+ // to check that.
+ else
+ return aPosAnchorA < aPosAnchorB;
+ }
+
+ /// Emits LOK notification about one addition/removal/change of a comment
+ void lcl_CommentNotification(const SwView* pView, const CommentNotificationType nType, const SwSidebarItem* pItem, const sal_uInt32 nPostItId)
+ {
+ if (!comphelper::LibreOfficeKit::isActive())
+ return;
+
+ boost::property_tree::ptree aAnnotation;
+ aAnnotation.put("action", (nType == CommentNotificationType::Add ? "Add" :
+ (nType == CommentNotificationType::Remove ? "Remove" :
+ (nType == CommentNotificationType::Modify ? "Modify" : "???"))));
+ aAnnotation.put("id", nPostItId);
+ if (nType != CommentNotificationType::Remove && pItem != nullptr)
+ {
+ sw::annotation::SwAnnotationWin* pWin = static_cast<sw::annotation::SwAnnotationWin*>((pItem)->pPostIt.get());
+
+ const SwPostItField* pField = pWin->GetPostItField();
+ const std::string aAnchorPos = std::to_string(pWin->GetAnchorPos().X()) + ", " + std::to_string(pWin->GetAnchorPos().Y());
+ std::vector<OString> aRects;
+ for (const basegfx::B2DRange& aRange : pWin->GetAnnotationTextRanges())
+ {
+ const SwRect rect(aRange.getMinX(), aRange.getMinY(), aRange.getWidth(), aRange.getHeight());
+ aRects.push_back(rect.SVRect().toString());
+ }
+ const OString sRects = comphelper::string::join("; ", aRects);
+
+ aAnnotation.put("id", pField->GetPostItId());
+ aAnnotation.put("reply", pWin->IsFollow());
+ aAnnotation.put("author", pField->GetPar1().toUtf8().getStr());
+ aAnnotation.put("text", pField->GetPar2().toUtf8().getStr());
+ aAnnotation.put("dateTime", utl::toISO8601(pField->GetDateTime().GetUNODateTime()));
+ aAnnotation.put("anchorPos", aAnchorPos.c_str());
+ aAnnotation.put("textRange", sRects.getStr());
+ }
+
+ boost::property_tree::ptree aTree;
+ aTree.add_child("comment", aAnnotation);
+ std::stringstream aStream;
+ boost::property_tree::write_json(aStream, aTree);
+ std::string aPayload = aStream.str();
+
+ if (pView)
+ {
+ pView->libreOfficeKitViewCallback(LOK_CALLBACK_COMMENT, aPayload.c_str());
+ }
+ }
+
+} // anonymous namespace
SwPostItMgr::SwPostItMgr(SwView* pView)
: mpView(pView)
@@ -216,21 +273,27 @@ void SwPostItMgr::CheckForRemovedPostIts()
}
}
-void SwPostItMgr::InsertItem(SfxBroadcaster* pItem, bool bCheckExistance, bool bFocus)
+SwSidebarItem* SwPostItMgr::InsertItem(SfxBroadcaster* pItem, bool bCheckExistance, bool bFocus)
{
+ SwSidebarItem* pAnnotationItem = nullptr;
if (bCheckExistance)
{
for(std::list<SwSidebarItem*>::iterator i = mvPostItFields.begin(); i != mvPostItFields.end() ; ++i)
{
if ( (*i)->GetBroadCaster() == pItem )
- return;
+ return pAnnotationItem;
}
}
mbLayout = bFocus;
+
if (dynamic_cast< const SwFormatField *>( pItem ) != nullptr)
- mvPostItFields.push_back(new SwAnnotationItem(static_cast<SwFormatField&>(*pItem), bFocus) );
+ {
+ pAnnotationItem = new SwAnnotationItem(static_cast<SwFormatField&>(*pItem), bFocus);
+ mvPostItFields.push_back(pAnnotationItem);
+ }
OSL_ENSURE(dynamic_cast< const SwFormatField *>( pItem ) != nullptr,"Mgr::InsertItem: seems like new stuff was added");
StartListening(*pItem);
+ return pAnnotationItem;
}
void SwPostItMgr::RemoveItem( SfxBroadcaster* pBroadcast )
@@ -282,9 +345,22 @@ void SwPostItMgr::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
if ( pField->IsFieldInDoc() )
{
bool bEmpty = !HasNotes();
- InsertItem( pField, true, false );
+ SwSidebarItem* pItem = InsertItem( pField, true, false );
+
if (bEmpty && !mvPostItFields.empty())
PrepareView(true);
+
+ // If LOK has disabled tiled annotations, emit annotation callbacks
+ if (comphelper::LibreOfficeKit::isActive() && !comphelper::LibreOfficeKit::isTiledAnnotations())
+ {
+ CalcRects();
+ Show();
+
+ if (pItem && pItem->pPostIt)
+ {
+ lcl_CommentNotification(mpView, CommentNotificationType::Add, pItem, 0);
+ }
+ }
}
else
{
@@ -302,6 +378,13 @@ void SwPostItMgr::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
break;
}
RemoveItem(pField);
+
+ // If LOK has disabled tiled annotations, emit annotation callbacks
+ if (comphelper::LibreOfficeKit::isActive() && !comphelper::LibreOfficeKit::isTiledAnnotations())
+ {
+ SwPostItField* pPostItField = static_cast<SwPostItField*>(pField->GetField());
+ lcl_CommentNotification(mpView, CommentNotificationType::Remove, nullptr, pPostItField->GetPostItId());
+ }
}
break;
}
@@ -313,7 +396,7 @@ void SwPostItMgr::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
}
case SwFormatFieldHintWhich::CHANGED:
{
- SwFormatField* pFormatField = dynamic_cast<SwFormatField*>(&rBC);
+ SwFormatField* pFormatField = dynamic_cast<SwFormatField*>(&rBC);
for(std::list<SwSidebarItem*>::iterator i = mvPostItFields.begin(); i != mvPostItFields.end() ; ++i)
{
if ( pFormatField == (*i)->GetBroadCaster() )
@@ -323,6 +406,12 @@ void SwPostItMgr::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
(*i)->pPostIt->SetPostItText();
mbLayout = true;
}
+
+ // If LOK has disabled tiled annotations, emit annotation callbacks
+ if (comphelper::LibreOfficeKit::isActive() && !comphelper::LibreOfficeKit::isTiledAnnotations())
+ {
+ lcl_CommentNotification(mpView, CommentNotificationType::Modify, *i, 0);
+ }
break;
}
}
@@ -458,7 +547,6 @@ bool SwPostItMgr::CalcRects()
bRepair = true;
continue;
}
-
const SwRect aOldAnchorRect( pItem->maLayoutInfo.mPosition );
const SwPostItHelper::SwLayoutStatus eOldLayoutStatus = pItem->mLayoutStatus;
const sal_uLong nOldStartNodeIdx( pItem->maLayoutInfo.mnStartNodeIdx );