diff --git a/sw/qa/core/edit/data/compare-new.odt b/sw/qa/core/edit/data/compare-new.odt new file mode 100644 index 000000000000..50b6ae83f46f Binary files /dev/null and b/sw/qa/core/edit/data/compare-new.odt differ diff --git a/sw/qa/core/edit/data/compare-old.odt b/sw/qa/core/edit/data/compare-old.odt new file mode 100644 index 000000000000..e3200824433c Binary files /dev/null and b/sw/qa/core/edit/data/compare-old.odt differ diff --git a/sw/qa/core/edit/edit.cxx b/sw/qa/core/edit/edit.cxx index 270490688315..21f187ebee59 100644 --- a/sw/qa/core/edit/edit.cxx +++ b/sw/qa/core/edit/edit.cxx @@ -9,7 +9,13 @@ #include +#include + #include +#include +#include +#include +#include #include #include @@ -32,6 +38,33 @@ public: { } }; + +/// LOK view callback for test purposes. +struct ViewCallback +{ + std::vector m_aStateChanges; + + static void callback(int nType, const char* pPayload, void* pData); + void callbackImpl(int nType, const char* pPayload); +}; + +void ViewCallback::callback(int nType, const char* pPayload, void* pData) +{ + static_cast(pData)->callbackImpl(nType, pPayload); +} + +void ViewCallback::callbackImpl(int nType, const char* pPayload) +{ + switch (nType) + { + case LOK_CALLBACK_STATE_CHANGED: + { + OUString aPayload = OUString::fromUtf8(pPayload); + m_aStateChanges.push_back(aPayload); + } + break; + } +} } CPPUNIT_TEST_FIXTURE(Test, testRedlineHidden) @@ -451,6 +484,53 @@ CPPUNIT_TEST_FIXTURE(Test, testRedlineReinstateSelf) CPPUNIT_ASSERT_EQUAL(static_cast(1), rRedlines.size()); } +CPPUNIT_TEST_FIXTURE(Test, testDocumentCompareCallback) +{ + // Set up LOK: + comphelper::LibreOfficeKit::setActive(true); + + // Given a new document: + createSwDoc("compare-new.odt"); + SwDocShell* pDocShell = getSwDocShell(); + SwWrtShell* pWrtShell = pDocShell->GetWrtShell(); + ViewCallback aCallback; + TestLokCallbackWrapper aCallbackWrapper(&ViewCallback::callback, &aCallback); + pWrtShell->GetSfxViewShell()->setLibreOfficeKitViewCallback(&aCallbackWrapper); + aCallbackWrapper.setLOKViewId(SfxLokHelper::getView(*pWrtShell->GetSfxViewShell())); + + // When comparing with an old document: + OUString aOther = createFileURL(u"compare-old.odt"); + uno::Sequence aArgs = { + comphelper::makePropertyValue("URL", aOther), + comphelper::makePropertyValue("NoAcceptDialog", true), + }; + dispatchCommand(mxComponent, ".uno:CompareDocuments", aArgs); + + // Then make sure a JSON callback with the expected content is emitted: + auto it = std::find_if(aCallback.m_aStateChanges.begin(), aCallback.m_aStateChanges.end(), + [](const OUString& i) -> bool { return i.startsWith("{"); }); + CPPUNIT_ASSERT(it != aCallback.m_aStateChanges.end()); + std::stringstream aStream((std::string(it->toUtf8()))); + boost::property_tree::ptree aTree; + boost::property_tree::read_json(aStream, aTree); + CPPUNIT_ASSERT_EQUAL(std::string("CompareDocumentsProperties"), + aTree.get("commandName")); + CPPUNIT_ASSERT_EQUAL(std::string("Alice"), + aTree.get("state.metadata.otherDocument.modifiedBy")); + CPPUNIT_ASSERT_EQUAL(std::string("2010-02-12T13:51:17.860434211"), + aTree.get("state.metadata.otherDocument.modificationDate")); + CPPUNIT_ASSERT_EQUAL(std::string("Bob"), + aTree.get("state.metadata.thisDocument.modifiedBy")); + CPPUNIT_ASSERT_EQUAL(std::string("2026-02-12T13:52:55.923182809"), + aTree.get("state.metadata.thisDocument.modificationDate")); + + // Tear down LOK: + pWrtShell->GetSfxViewShell()->setLibreOfficeKitViewCallback(nullptr); + mxComponent->dispose(); + mxComponent.clear(); + comphelper::LibreOfficeKit::setActive(false); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sw/source/core/edit/editsh.cxx b/sw/source/core/edit/editsh.cxx index a81cedd695c6..9a11b8e7c391 100644 --- a/sw/source/core/edit/editsh.cxx +++ b/sw/source/core/edit/editsh.cxx @@ -17,6 +17,8 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include + #include #include #include @@ -27,6 +29,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -59,6 +64,7 @@ #include #include #include +#include using namespace com::sun::star; @@ -888,11 +894,57 @@ sal_Int32 SwEditShell::GetLineCount() return nRet; } +namespace +{ +/// Write document compare metadata about rDoc into rWriter. +void WriteCompareDocMetadata(tools::JsonWriter& rWriter, const SwDoc& rDoc) +{ + const SwDocShell* pDocShell = rDoc.GetDocShell(); + if (!pDocShell) + { + return; + } + + uno::Reference xDPS(pDocShell->GetModel(), + uno::UNO_QUERY); + uno::Reference xDocProps = xDPS->getDocumentProperties(); + rWriter.put("modifiedBy", xDocProps->getModifiedBy()); + + util::DateTime aModificationDate = xDocProps->getModificationDate(); + OUStringBuffer aBuffer; + sax::Converter::convertDateTime(aBuffer, aModificationDate, nullptr, true); + rWriter.put("modificationDate", aBuffer.makeStringAndClear()); +} +} + tools::Long SwEditShell::CompareDoc( const SwDoc& rDoc ) { + SwDoc* pThisDoc = GetDoc(); StartAllAction(); - tools::Long nRet = GetDoc()->CompareDoc( rDoc ); + tools::Long nRet = pThisDoc->CompareDoc( rDoc ); EndAllAction(); + + SfxViewShell* pSfxViewShell = GetSfxViewShell(); + if (pSfxViewShell && pSfxViewShell->getLibreOfficeKitViewCallback()) + { + tools::JsonWriter aWriter; + aWriter.put("commandName", "CompareDocumentsProperties"); + { + auto aState = aWriter.startNode("state"); + auto aMetadata = aWriter.startNode("metadata"); + { + auto aDocument = aWriter.startNode("otherDocument"); + WriteCompareDocMetadata(aWriter, rDoc); + } + { + auto aDocument = aWriter.startNode("thisDocument"); + WriteCompareDocMetadata(aWriter, *pThisDoc); + } + } + OString aPayload = aWriter.finishAndGetAsOString(); + pSfxViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_STATE_CHANGED, aPayload); + } + return nRet; }