desktop/qa/desktop_lib/test_desktop_lib.cxx | 56 +++++++++++++++++++++++-- include/sfx2/objsh.hxx | 2 include/tools/link.hxx | 61 ++++++++++++++++++++++++++++ sc/source/ui/docshell/docsh.cxx | 6 ++ sc/source/ui/inc/docsh.hxx | 2 sfx2/source/doc/objserv.cxx | 1 sfx2/source/doc/objstor.cxx | 7 +++ 7 files changed, 130 insertions(+), 5 deletions(-)
New commits: commit e867404fbe7e0ff0d6f2573292c19b3a178a412d Author: Ashod Nakashian <[email protected]> AuthorDate: Thu Aug 22 09:15:15 2019 -0400 Commit: Andras Timar <[email protected]> CommitDate: Tue Sep 3 13:44:47 2019 +0200 sc: LOK: commit cell edits before saveas Users typically don't recognize that changes done to a cell need to be committed (typically by hitting RETURN) before they are saved to file. This is especially true on the web. This patch commits any in-flight changes before SaveAs. This is currently done only for LOK and unconditionally at that. This can be controlled via a flag, if there is such a use-case. Reviewed-on: https://gerrit.libreoffice.org/78012 Reviewed-by: Ashod Nakashian <[email protected]> Tested-by: Ashod Nakashian <[email protected]> (cherry picked from commit cc7eb4d345e3fede698a3f255c1938d275305c14) Change-Id: I2a88b2f1df47be764058f4505561b22830d9d67a Reviewed-on: https://gerrit.libreoffice.org/78455 Reviewed-by: Andras Timar <[email protected]> Tested-by: Andras Timar <[email protected]> diff --git a/desktop/qa/desktop_lib/test_desktop_lib.cxx b/desktop/qa/desktop_lib/test_desktop_lib.cxx index 67e66832bbff..c08cdaeb41bc 100644 --- a/desktop/qa/desktop_lib/test_desktop_lib.cxx +++ b/desktop/qa/desktop_lib/test_desktop_lib.cxx @@ -86,6 +86,7 @@ public: comphelper::LibreOfficeKit::setActive(false); }; + LibLODocument_Impl* loadDocUrl(const OUString& rFileURL, LibreOfficeKitDocumentType eType); LibLODocument_Impl* loadDoc(const char* pName, LibreOfficeKitDocumentType eType = LOK_DOCTYPE_TEXT); void closeDoc(); static void callback(int nType, const char* pPayload, void* pData); @@ -140,6 +141,7 @@ public: void testTextSelectionHandles(); void testComplexSelection(); void testDialogPaste(); + void testCalcSaveAs(); void testABI(); CPPUNIT_TEST_SUITE(DesktopLOKTest); @@ -192,6 +194,7 @@ public: CPPUNIT_TEST(testTextSelectionHandles); CPPUNIT_TEST(testComplexSelection); CPPUNIT_TEST(testDialogPaste); + CPPUNIT_TEST(testCalcSaveAs); CPPUNIT_TEST(testABI); CPPUNIT_TEST_SUITE_END(); @@ -237,10 +240,8 @@ static Control* GetFocusControl(vcl::Window const * pParent) return nullptr; } -LibLODocument_Impl* DesktopLOKTest::loadDoc(const char* pName, LibreOfficeKitDocumentType eType) +LibLODocument_Impl* DesktopLOKTest::loadDocUrl(const OUString& rFileURL, LibreOfficeKitDocumentType eType) { - OUString aFileURL; - createFileURL(OUString::createFromAscii(pName), aFileURL); OUString aService; switch (eType) { @@ -257,7 +258,7 @@ LibLODocument_Impl* DesktopLOKTest::loadDoc(const char* pName, LibreOfficeKitDoc CPPUNIT_ASSERT(false); break; } - mxComponent = loadFromDesktop(aFileURL, aService); + mxComponent = loadFromDesktop(rFileURL, aService); if (!mxComponent.is()) { CPPUNIT_ASSERT(false); @@ -266,6 +267,13 @@ LibLODocument_Impl* DesktopLOKTest::loadDoc(const char* pName, LibreOfficeKitDoc return m_pDocument.get(); } +LibLODocument_Impl* DesktopLOKTest::loadDoc(const char* pName, LibreOfficeKitDocumentType eType) +{ + OUString aFileURL; + createFileURL(OUString::createFromAscii(pName), aFileURL); + return loadDocUrl(aFileURL, eType); +} + void DesktopLOKTest::closeDoc() { if (mxComponent.is()) @@ -1748,6 +1756,7 @@ void DesktopLOKTest::testRedlineCalc() class ViewCallback { public: + OString m_aCellFormula; bool m_bTilesInvalidated; tools::Rectangle m_aOwnCursor; boost::property_tree::ptree m_aCommentCallbackResult; @@ -1792,6 +1801,11 @@ public: m_aCommentCallbackResult = m_aCommentCallbackResult.get_child("comment"); } break; + case LOK_CALLBACK_CELL_FORMULA: + { + m_aCellFormula = aPayload; + } + break; } } }; @@ -2590,6 +2604,40 @@ void DesktopLOKTest::testComplexSelection() CPPUNIT_ASSERT_EQUAL(static_cast<int>(LOK_SELTYPE_COMPLEX), pDocument->pClass->getSelectionType(pDocument)); } +void DesktopLOKTest::testCalcSaveAs() +{ + comphelper::LibreOfficeKit::setActive(); + + LibLODocument_Impl* pDocument = loadDoc("sheets.ods"); + CPPUNIT_ASSERT(pDocument); + + // Enter some text, but don't commit. + pDocument->pClass->postKeyEvent(pDocument, LOK_KEYEVENT_KEYINPUT, 'X', 0); + pDocument->pClass->postKeyEvent(pDocument, LOK_KEYEVENT_KEYUP, 'X', 0); + Scheduler::ProcessEventsToIdle(); + + // Save as a new file. + OUString aNewFileUrl = "file:///tmp/saveas.ods"; + pDocument->pClass->saveAs(pDocument, aNewFileUrl.toUtf8().getStr(), nullptr, nullptr); + closeDoc(); + + // Load the new document and verify that the in-flight changes are saved. + pDocument = loadDocUrl(aNewFileUrl, LOK_DOCTYPE_SPREADSHEET); + CPPUNIT_ASSERT(pDocument); + + ViewCallback aView; + pDocument->m_pDocumentClass->initializeForRendering(pDocument, "{}"); + pDocument->m_pDocumentClass->registerCallback(pDocument, &ViewCallback::callback, &aView); + + pDocument->pClass->postKeyEvent(pDocument, LOK_KEYEVENT_KEYINPUT, 0, KEY_RIGHT); + pDocument->pClass->postKeyEvent(pDocument, LOK_KEYEVENT_KEYUP, 0, KEY_RIGHT); + pDocument->pClass->postKeyEvent(pDocument, LOK_KEYEVENT_KEYINPUT, 0, KEY_LEFT); + pDocument->pClass->postKeyEvent(pDocument, LOK_KEYEVENT_KEYUP, 0, KEY_LEFT); + Scheduler::ProcessEventsToIdle(); + + CPPUNIT_ASSERT_EQUAL(OString("X"), aView.m_aCellFormula); +} + namespace { constexpr size_t classOffset(int i) diff --git a/include/sfx2/objsh.hxx b/include/sfx2/objsh.hxx index 8f3b43a9ce2d..027eedb860f6 100644 --- a/include/sfx2/objsh.hxx +++ b/include/sfx2/objsh.hxx @@ -318,6 +318,8 @@ public: // TODO/LATER: currently only overridden in Calc, should be made non-virtual virtual bool DoSaveCompleted( SfxMedium* pNewStor=nullptr, bool bRegisterRecent=true ); + /// Terminate any in-flight editing. Used before saving, primarily by Calc to commit cell changes. + virtual void TerminateEditing() {} bool LoadOwnFormat( SfxMedium& pMedium ); virtual bool SaveAsOwnFormat( SfxMedium& pMedium ); diff --git a/sc/source/ui/docshell/docsh.cxx b/sc/source/ui/docshell/docsh.cxx index 59fe24a832ec..789d69132f78 100644 --- a/sc/source/ui/docshell/docsh.cxx +++ b/sc/source/ui/docshell/docsh.cxx @@ -1779,6 +1779,12 @@ void popFileName(OUString& rPath) } +void ScDocShell::TerminateEditing() +{ + // Commit any cell changes before saving. + SC_MOD()->InputEnterHandler(); +} + bool ScDocShell::SaveAs( SfxMedium& rMedium ) { OUString aCurPath; // empty for new document that hasn't been saved. diff --git a/sc/source/ui/inc/docsh.hxx b/sc/source/ui/inc/docsh.hxx index 90b6840a9524..1e99ea3e6a73 100644 --- a/sc/source/ui/inc/docsh.hxx +++ b/sc/source/ui/inc/docsh.hxx @@ -204,6 +204,8 @@ public: virtual void SetVisArea( const tools::Rectangle & rVisArea ) override; + virtual void TerminateEditing() override; + using SfxObjectShell::GetVisArea; virtual tools::Rectangle GetVisArea( sal_uInt16 nAspect ) const override; diff --git a/sfx2/source/doc/objserv.cxx b/sfx2/source/doc/objserv.cxx index 73bc90490f22..b3e4985451c2 100644 --- a/sfx2/source/doc/objserv.cxx +++ b/sfx2/source/doc/objserv.cxx @@ -281,7 +281,6 @@ bool SfxObjectShell::APISaveAs_Impl(const OUString& aFileName, SfxItemSet& rItem { bool bOk = false; - if ( GetMedium() ) { OUString aFilterName; diff --git a/sfx2/source/doc/objstor.cxx b/sfx2/source/doc/objstor.cxx index 8abd39cc9dec..53fe2e344214 100644 --- a/sfx2/source/doc/objstor.cxx +++ b/sfx2/source/doc/objstor.cxx @@ -2664,6 +2664,7 @@ bool SfxObjectShell::CommonSaveAs_Impl(const INetURLObject& aURL, const OUString return false; } + const SfxBoolItem* pCopyStreamItem = rItemSet.GetItem<SfxBoolItem>(SID_COPY_STREAM_IF_POSSIBLE, false); if ( bSaveTo && pCopyStreamItem && pCopyStreamItem->GetValue() && !IsModified() ) { @@ -2821,6 +2822,12 @@ bool SfxObjectShell::PreDoSaveAs_Impl(const OUString& rFileName, const OUString& return false; } + if (comphelper::LibreOfficeKit::isActive()) + { + // Before saving, commit in-flight changes. + TerminateEditing(); + } + // check if a "SaveTo" is wanted, no "SaveAs" const SfxBoolItem* pSaveToItem = pMergedParamsTmp->GetItem<SfxBoolItem>(SID_SAVETO, false); bool bCopyTo = GetCreateMode() == SfxObjectCreateMode::EMBEDDED || (pSaveToItem && pSaveToItem->GetValue()); commit 4db20315045a8d0fa82f5562123854e159b999aa Author: Ashod Nakashian <[email protected]> AuthorDate: Sun May 12 17:16:27 2019 -0400 Commit: Andras Timar <[email protected]> CommitDate: Tue Sep 3 13:44:34 2019 +0200 Link: support tracing link source and target By adding a couple of members to Link, we are now able to trace the target function name and the file:line where the Link instance in question was created (provided the LINK macro is used). This gives the invaluable ability to track down the source of a Link instance in the debugger, provided we have enabled this feature, which is enabled in DBG_UTIL automatically, unless explicitly enabled. Of course it is also possible to judiciously add LOG/fprintf statements to chase this info, if not outright track all links, if so we wish, by dumping from Link::Call, or at construction time of Link. Change-Id: Iab1dce31a179d28aaa1f20228e9e0405973b5e9b Reviewed-on: https://gerrit.libreoffice.org/72208 Tested-by: Jenkins CollaboraOffice <[email protected]> Reviewed-by: Jan Holesovsky <[email protected]> (cherry picked from commit aad7bd5ede2b3088098df69f143a92799931fd58) Reviewed-on: https://gerrit.libreoffice.org/78454 Reviewed-by: Andras Timar <[email protected]> Tested-by: Andras Timar <[email protected]> diff --git a/include/tools/link.hxx b/include/tools/link.hxx index c4989e0593f3..d4816df9b31c 100644 --- a/include/tools/link.hxx +++ b/include/tools/link.hxx @@ -24,6 +24,19 @@ #include <sal/types.h> +/// Support tracing link source and target. +/// When debugging async events, it's often critical +/// to find out not only where a link leads (i.e. the target +/// function), but also where it was created (file:line). +/// This adds support to track this information and allow +/// for logging/printing, and introspecting in the debugger. +#ifndef TRACE_LINKS +# ifdef DBG_UTIL +# define TRACE_LINKS 1 +# include <cstdio> +# endif +#endif + #define DECL_LINK(Member, ArgType, RetType) \ static RetType LinkStub##Member(void *, ArgType); \ RetType Member(ArgType) @@ -67,18 +80,47 @@ RetType Class::Member( \ SAL_UNUSED_PARAMETER Class *, SAL_UNUSED_PARAMETER ArgType) +#if TRACE_LINKS +#define XSTRINGIFY(X) #X +#define STRINGIFY(X) XSTRINGIFY(X) +#define LINK(Instance, Class, Member) ::tools::detail::makeLink( \ + ::tools::detail::castTo<Class *>(Instance), &Class::LinkStub##Member, __FILE__, __LINE__, STRINGIFY(Class::LinkStub##Member)) +#else #define LINK(Instance, Class, Member) ::tools::detail::makeLink( \ ::tools::detail::castTo<Class *>(Instance), &Class::LinkStub##Member) +#endif template<typename Arg, typename Ret> class SAL_WARN_UNUSED Link { public: typedef Ret Stub(void *, Arg); +#if TRACE_LINKS + Link() + : function_(nullptr) + , instance_(nullptr) + , file_("unknown") + , line_(0) + , target_("unknown") + { + } + + Link(void* instance, Stub* function, const char* const file = "unknown", const int line = 0, + const char* const target = "unknown") + : function_(function) + , instance_(instance) + , file_(file) + , line_(line) + , target_(target) + { + } + +#else Link(): function_(nullptr), instance_(nullptr) {} Link(void * instance, Stub * function): function_(function), instance_(instance) {} +#endif Ret Call(Arg data) const { return function_ == nullptr ? Ret() : (*function_)(instance_, data); } @@ -103,9 +145,21 @@ public: void *GetInstance() const { return instance_; } +#if TRACE_LINKS + const char* getSourceFilename() const { return file_; } + int getSourceLineNumber() const { return line_; } + const char* getTargetName() const { return target_; } +#endif + private: Stub * function_; void * instance_; + +#if TRACE_LINKS + const char* file_; + int line_; + const char* target_; +#endif }; // Class used to indicate that the Call() parameter is not in use: @@ -118,10 +172,17 @@ namespace tools { namespace detail { template<typename To, typename From> To castTo(From from) { return static_cast<To>(from); } +#if TRACE_LINKS +template<typename Arg, typename Ret> +Link<Arg, Ret> makeLink(void * instance, Ret (* function)(void *, Arg), const char* file, int line, const char* target) { + return Link<Arg, Ret>(instance, function, file, line, target); +} +#else template<typename Arg, typename Ret> Link<Arg, Ret> makeLink(void * instance, Ret (* function)(void *, Arg)) { return Link<Arg, Ret>(instance, function); } +#endif } } _______________________________________________ Libreoffice-commits mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
