diff options
author | Pranav Kant <pranavk@collabora.co.uk> | 2017-01-24 14:07:45 +0530 |
---|---|---|
committer | pranavk <pranavk@collabora.co.uk> | 2017-01-27 11:50:02 +0000 |
commit | 5f5073a84518e4a8660e0153c2e218fb75a85ec4 (patch) | |
tree | 586e7c8193d67e2e8c53c0d04f14a09d25ecbf44 | |
parent | a623b3a449dfcddaad5b621ff1c0b7a520edf4d6 (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.h | 26 | ||||
-rw-r--r-- | libreofficekit/source/gtk/lokdocview.cxx | 4 | ||||
-rw-r--r-- | sw/inc/PostItMgr.hxx | 2 | ||||
-rw-r--r-- | sw/source/uibase/docvw/PostItMgr.cxx | 158 |
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 ); |