Kaydet (Commit) 5f5073a8 authored tarafından Pranav Kant's avatar Pranav Kant Kaydeden (comit) pranavk

lok: Implement new callbacks for comment notifications

Change-Id: I298183b295c68c4a39cb1f6fffe4b89b4eaee0f3
Reviewed-on: https://gerrit.libreoffice.org/33469Reviewed-by: 's avatarpranavk <pranavk@collabora.co.uk>
Tested-by: 's avatarpranavk <pranavk@collabora.co.uk>
üst a623b3a4
...@@ -467,6 +467,32 @@ typedef enum ...@@ -467,6 +467,32 @@ typedef enum
* - 'action' is 'Modify'. * - 'action' is 'Modify'.
*/ */
LOK_CALLBACK_REDLINE_TABLE_ENTRY_MODIFIED = 31, 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; LibreOfficeKitCallbackType;
......
...@@ -426,6 +426,8 @@ callbackTypeToString (int nType) ...@@ -426,6 +426,8 @@ callbackTypeToString (int nType)
return "LOK_CALLBACK_REDLINE_TABLE_SIZE_CHANGED"; return "LOK_CALLBACK_REDLINE_TABLE_SIZE_CHANGED";
case LOK_CALLBACK_REDLINE_TABLE_ENTRY_MODIFIED: case LOK_CALLBACK_REDLINE_TABLE_ENTRY_MODIFIED:
return "LOK_CALLBACK_REDLINE_TABLE_ENTRY_MODIFIED"; return "LOK_CALLBACK_REDLINE_TABLE_ENTRY_MODIFIED";
case LOK_CALLBACK_COMMENT:
return "LOK_CALLBACK_COMMENT";
} }
g_assert(false); g_assert(false);
return nullptr; return nullptr;
...@@ -1395,6 +1397,8 @@ callback (gpointer pData) ...@@ -1395,6 +1397,8 @@ callback (gpointer pData)
{ {
break; break;
} }
case LOK_CALLBACK_COMMENT:
break;
default: default:
g_assert(false); g_assert(false);
break; break;
......
...@@ -186,7 +186,7 @@ class SwPostItMgr: public SfxListener ...@@ -186,7 +186,7 @@ class SwPostItMgr: public SfxListener
sw::sidebarwindows::SwSidebarWin* GetSidebarWin(const SfxBroadcaster* pBroadcaster) const; 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 ); void RemoveItem( SfxBroadcaster* pBroadcast );
public: public:
......
...@@ -17,11 +17,13 @@ ...@@ -17,11 +17,13 @@
* the License at http://www.apache.org/licenses/LICENSE-2.0 . * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/ */
#include <boost/property_tree/json_parser.hpp>
#include "PostItMgr.hxx" #include "PostItMgr.hxx"
#include <postithelper.hxx> #include <postithelper.hxx>
#include <SidebarWin.hxx>
#include <AnnotationWin.hxx> #include <AnnotationWin.hxx>
#include <SidebarWin.hxx>
#include <frmsidebarwincontainer.hxx> #include <frmsidebarwincontainer.hxx>
#include <accmap.hxx> #include <accmap.hxx>
...@@ -53,6 +55,7 @@ ...@@ -53,6 +55,7 @@
#include <docary.hxx> #include <docary.hxx>
#include <SwRewriter.hxx> #include <SwRewriter.hxx>
#include <tools/color.hxx> #include <tools/color.hxx>
#include <unotools/datetime.hxx>
#include <swmodule.hxx> #include <swmodule.hxx>
#include <annotation.hrc> #include <annotation.hrc>
...@@ -75,6 +78,8 @@ ...@@ -75,6 +78,8 @@
#include <i18nlangtag/mslangid.hxx> #include <i18nlangtag/mslangid.hxx>
#include <i18nlangtag/lang.h> #include <i18nlangtag/lang.h>
#include <comphelper/lok.hxx> #include <comphelper/lok.hxx>
#include <comphelper/string.hxx>
#include <LibreOfficeKit/LibreOfficeKitEnums.h>
#include "annotsh.hxx" #include "annotsh.hxx"
#include "swabstdlg.hxx" #include "swabstdlg.hxx"
...@@ -94,37 +99,89 @@ ...@@ -94,37 +99,89 @@
using namespace sw::sidebarwindows; using namespace sw::sidebarwindows;
bool comp_pos(const SwSidebarItem* a, const SwSidebarItem* b) namespace {
{
// sort by anchor position
SwPosition aPosAnchorA = a->GetAnchorPosition();
SwPosition aPosAnchorB = b->GetAnchorPosition();
bool aAnchorAInFooter = false; enum class CommentNotificationType { Add, Remove, Modify };
bool aAnchorBInFooter = false;
// is the anchor placed in Footnote or the Footer? bool comp_pos(const SwSidebarItem* a, const SwSidebarItem* b)
if( aPosAnchorA.nNode.GetNode().FindFootnoteStartNode() || aPosAnchorA.nNode.GetNode().FindFooterStartNode() ) {
aAnchorAInFooter = true; // sort by anchor position
if( aPosAnchorB.nNode.GetNode().FindFootnoteStartNode() || aPosAnchorB.nNode.GetNode().FindFooterStartNode() ) SwPosition aPosAnchorA = a->GetAnchorPosition();
aAnchorBInFooter = true; SwPosition aPosAnchorB = b->GetAnchorPosition();
// fdo#34800 bool aAnchorAInFooter = false;
// if AnchorA is in footnote, and AnchorB isn't bool aAnchorBInFooter = false;
// we do not want to change over the position
if( aAnchorAInFooter && !aAnchorBInFooter ) // is the anchor placed in Footnote or the Footer?
return false; if( aPosAnchorA.nNode.GetNode().FindFootnoteStartNode() || aPosAnchorA.nNode.GetNode().FindFooterStartNode() )
// if aAnchorA is not placed in a footnote, and aAnchorB is aAnchorAInFooter = true;
// force a change over if( aPosAnchorB.nNode.GetNode().FindFootnoteStartNode() || aPosAnchorB.nNode.GetNode().FindFooterStartNode() )
else if( !aAnchorAInFooter && aAnchorBInFooter ) aAnchorBInFooter = true;
return true;
// If neither or both are in the footer, compare the positions. // fdo#34800
// Since footnotes are in Inserts section of nodes array and footers // if AnchorA is in footnote, and AnchorB isn't
// in Autotext section, all footnotes precede any footers so no need // we do not want to change over the position
// to check that. if( aAnchorAInFooter && !aAnchorBInFooter )
else return false;
return aPosAnchorA < aPosAnchorB; // 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) SwPostItMgr::SwPostItMgr(SwView* pView)
: mpView(pView) : mpView(pView)
...@@ -216,21 +273,27 @@ void SwPostItMgr::CheckForRemovedPostIts() ...@@ -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) if (bCheckExistance)
{ {
for(std::list<SwSidebarItem*>::iterator i = mvPostItFields.begin(); i != mvPostItFields.end() ; ++i) for(std::list<SwSidebarItem*>::iterator i = mvPostItFields.begin(); i != mvPostItFields.end() ; ++i)
{ {
if ( (*i)->GetBroadCaster() == pItem ) if ( (*i)->GetBroadCaster() == pItem )
return; return pAnnotationItem;
} }
} }
mbLayout = bFocus; mbLayout = bFocus;
if (dynamic_cast< const SwFormatField *>( pItem ) != nullptr) 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"); OSL_ENSURE(dynamic_cast< const SwFormatField *>( pItem ) != nullptr,"Mgr::InsertItem: seems like new stuff was added");
StartListening(*pItem); StartListening(*pItem);
return pAnnotationItem;
} }
void SwPostItMgr::RemoveItem( SfxBroadcaster* pBroadcast ) void SwPostItMgr::RemoveItem( SfxBroadcaster* pBroadcast )
...@@ -282,9 +345,22 @@ void SwPostItMgr::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) ...@@ -282,9 +345,22 @@ void SwPostItMgr::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
if ( pField->IsFieldInDoc() ) if ( pField->IsFieldInDoc() )
{ {
bool bEmpty = !HasNotes(); bool bEmpty = !HasNotes();
InsertItem( pField, true, false ); SwSidebarItem* pItem = InsertItem( pField, true, false );
if (bEmpty && !mvPostItFields.empty()) if (bEmpty && !mvPostItFields.empty())
PrepareView(true); 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 else
{ {
...@@ -302,6 +378,13 @@ void SwPostItMgr::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) ...@@ -302,6 +378,13 @@ void SwPostItMgr::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
break; break;
} }
RemoveItem(pField); 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; break;
} }
...@@ -313,7 +396,7 @@ void SwPostItMgr::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) ...@@ -313,7 +396,7 @@ void SwPostItMgr::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
} }
case SwFormatFieldHintWhich::CHANGED: 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) for(std::list<SwSidebarItem*>::iterator i = mvPostItFields.begin(); i != mvPostItFields.end() ; ++i)
{ {
if ( pFormatField == (*i)->GetBroadCaster() ) if ( pFormatField == (*i)->GetBroadCaster() )
...@@ -323,6 +406,12 @@ void SwPostItMgr::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) ...@@ -323,6 +406,12 @@ void SwPostItMgr::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
(*i)->pPostIt->SetPostItText(); (*i)->pPostIt->SetPostItText();
mbLayout = true; 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; break;
} }
} }
...@@ -458,7 +547,6 @@ bool SwPostItMgr::CalcRects() ...@@ -458,7 +547,6 @@ bool SwPostItMgr::CalcRects()
bRepair = true; bRepair = true;
continue; continue;
} }
const SwRect aOldAnchorRect( pItem->maLayoutInfo.mPosition ); const SwRect aOldAnchorRect( pItem->maLayoutInfo.mPosition );
const SwPostItHelper::SwLayoutStatus eOldLayoutStatus = pItem->mLayoutStatus; const SwPostItHelper::SwLayoutStatus eOldLayoutStatus = pItem->mLayoutStatus;
const sal_uLong nOldStartNodeIdx( pItem->maLayoutInfo.mnStartNodeIdx ); const sal_uLong nOldStartNodeIdx( pItem->maLayoutInfo.mnStartNodeIdx );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment