sw/CppunitTest_sw_uibase_dochdl.mk | 73 ++++++++++++++++++++++++++++++++++ sw/Module_sw.mk | 1 sw/qa/uibase/dochdl/dochdl.cxx | 75 +++++++++++++++++++++++++++++++++++ sw/source/uibase/dochdl/swdtflvr.cxx | 40 ++++++++++++++++++ sw/source/uibase/inc/swdtflvr.hxx | 3 + 5 files changed, 192 insertions(+)
New commits: commit 4da868767ff91825198e525d9aa773d73711723c Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Wed Apr 22 16:25:51 2020 +0200 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Wed Apr 22 19:31:50 2020 +0200 sw: prefer ODF over RTF when pasting from Writer Regression from commit e9e6d4b058e13165f3dde1ca7822eec97dfe8aa7 (tdf#116685: Make the RICHTEXT take precedence over EMBED_SOURCE., 2019-09-26), the problem was that now we always prefer RTF over ODF when pasting into Writer. The commit made sense for Calc->Writer paste, but it causes formatting loss for Writer -> Writer paste. The exact use-case was copy&paste of numberings where the pasted content got paragraph indent as direct formatting, so shift-tab at the paragraph start changed only the bullet type, not the indentation -- but it's easy to imagine several other cases where a roundtrip via ODF provides better results than RTF. Fix the problem by leaving the above commit in place, but extending SwTransferable::Paste() so that it prefers ODF over RTF in case of a Writer->Writer paste (and leaves the non-Writer -> Writer paste behavior unchanged to avoid the unwanted OLE objects). Conflicts: sw/Module_sw.mk sw/source/uibase/dochdl/swdtflvr.cxx Change-Id: Ida745bba65c5a210021cea0d267c02900fc6398a Reviewed-on: https://gerrit.libreoffice.org/c/core/+/92713 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Miklos Vajna <vmik...@collabora.com> diff --git a/sw/CppunitTest_sw_uibase_dochdl.mk b/sw/CppunitTest_sw_uibase_dochdl.mk new file mode 100644 index 000000000000..8bf0879f928d --- /dev/null +++ b/sw/CppunitTest_sw_uibase_dochdl.mk @@ -0,0 +1,73 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +#************************************************************************* +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +#************************************************************************* + +$(eval $(call gb_CppunitTest_CppunitTest,sw_uibase_dochdl)) + +$(eval $(call gb_CppunitTest_use_common_precompiled_header,sw_uibase_dochdl)) + +$(eval $(call gb_CppunitTest_add_exception_objects,sw_uibase_dochdl, \ + sw/qa/uibase/dochdl/dochdl \ +)) + +$(eval $(call gb_CppunitTest_use_libraries,sw_uibase_dochdl, \ + comphelper \ + cppu \ + cppuhelper \ + editeng \ + sal \ + sfx \ + svl \ + svx \ + svxcore \ + sw \ + test \ + unotest \ + utl \ + vcl \ +)) + +$(eval $(call gb_CppunitTest_use_externals,sw_uibase_dochdl,\ + boost_headers \ + libxml2 \ +)) + +$(eval $(call gb_CppunitTest_set_include,sw_uibase_dochdl,\ + -I$(SRCDIR)/sw/inc \ + -I$(SRCDIR)/sw/source/core/inc \ + -I$(SRCDIR)/sw/source/uibase/inc \ + -I$(SRCDIR)/sw/qa/extras/inc \ + $$(INCLUDE) \ +)) + +$(eval $(call gb_CppunitTest_use_api,sw_uibase_dochdl,\ + udkapi \ + offapi \ + oovbaapi \ +)) + +$(eval $(call gb_CppunitTest_use_ure,sw_uibase_dochdl)) +$(eval $(call gb_CppunitTest_use_vcl,sw_uibase_dochdl)) + +$(eval $(call gb_CppunitTest_use_rdb,sw_uibase_dochdl,services)) + +$(eval $(call gb_CppunitTest_use_custom_headers,sw_uibase_dochdl,\ + officecfg/registry \ +)) + +$(eval $(call gb_CppunitTest_use_configuration,sw_uibase_dochdl)) + +$(eval $(call gb_CppunitTest_use_uiconfigs,sw_uibase_dochdl, \ + modules/swriter \ +)) + +$(eval $(call gb_CppunitTest_use_more_fonts,sw_uibase_dochdl)) + +# vim: set noet sw=4 ts=4: diff --git a/sw/Module_sw.mk b/sw/Module_sw.mk index e2b4344af06c..6cd7dab3bc0a 100644 --- a/sw/Module_sw.mk +++ b/sw/Module_sw.mk @@ -100,6 +100,7 @@ $(eval $(call gb_Module_add_slowcheck_targets,sw,\ CppunitTest_sw_unowriter \ CppunitTest_sw_core_doc \ CppunitTest_sw_uibase_shells \ + CppunitTest_sw_uibase_dochdl \ CppunitTest_sw_core_layout \ CppunitTest_sw_core_text \ )) diff --git a/sw/qa/uibase/dochdl/dochdl.cxx b/sw/qa/uibase/dochdl/dochdl.cxx new file mode 100644 index 000000000000..07e50a78df36 --- /dev/null +++ b/sw/qa/uibase/dochdl/dochdl.cxx @@ -0,0 +1,75 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <swmodeltestbase.hxx> + +#include <sfx2/dispatch.hxx> +#include <sfx2/viewfrm.hxx> +#include <vcl/GraphicObject.hxx> +#include <svx/svdpage.hxx> +#include <editeng/eeitem.hxx> +#include <editeng/adjustitem.hxx> +#include <editeng/outlobj.hxx> +#include <editeng/editobj.hxx> +#include <vcl/transfer.hxx> + +#include <IDocumentContentOperations.hxx> +#include <cmdid.h> +#include <fmtanchr.hxx> +#include <view.hxx> +#include <wrtsh.hxx> +#include <IDocumentDrawModelAccess.hxx> +#include <drawdoc.hxx> +#include <swdtflvr.hxx> + +/// Covers sw/source/uibase/dochdl/ fixes. +class SwUibaseDochdlTest : public SwModelTestBase +{ +public: + SwDoc* createDoc(); +}; + +SwDoc* SwUibaseDochdlTest::createDoc() +{ + loadURL("private:factory/swriter", nullptr); + + SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get()); + CPPUNIT_ASSERT(pTextDoc); + return pTextDoc->GetDocShell()->GetDoc(); +} + +CPPUNIT_TEST_FIXTURE(SwUibaseDochdlTest, testSelectPasteFormat) +{ + // Create a new document and cut a character. + SwDoc* pDoc = createDoc(); + SwDocShell* pDocShell = pDoc->GetDocShell(); + SwWrtShell* pWrtShell = pDocShell->GetWrtShell(); + pWrtShell->Insert2("x"); + pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/true, 1, /*bBasicCall=*/false); + rtl::Reference<SwTransferable> pTransfer = new SwTransferable(*pWrtShell); + pTransfer->Cut(); + + // Decide what format to use when doing a Writer->Writer paste and both RTF and ODF is an + // available format. + TransferableDataHelper aHelper(pTransfer.get()); + sal_uInt8 nAction = EXCHG_OUT_ACTION_INSERT_STRING; + SotClipboardFormatId nFormat = SotClipboardFormatId::RICHTEXT; + SwTransferable::SelectPasteFormat(aHelper, nAction, nFormat); + + CPPUNIT_ASSERT_EQUAL(EXCHG_OUT_ACTION_INSERT_OLE, nAction); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 85 (EMBED_SOURCE) + // - Actual : 145 (RICHTEXT) + // i.e. RTF was selected for Writer->Writer out of process copying, which is worse than ODF. + CPPUNIT_ASSERT_EQUAL(SotClipboardFormatId::EMBED_SOURCE, nFormat); +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/dochdl/swdtflvr.cxx b/sw/source/uibase/dochdl/swdtflvr.cxx index 7dcf3b896aef..9ed8361bbfbe 100644 --- a/sw/source/uibase/dochdl/swdtflvr.cxx +++ b/sw/source/uibase/dochdl/swdtflvr.cxx @@ -130,6 +130,7 @@ #include <comphelper/lok.hxx> #include <sfx2/classificationhelper.hxx> #include <sfx2/sfxdlg.hxx> +#include <comphelper/classids.hxx> #include <memory> @@ -1174,6 +1175,41 @@ bool SwTransferable::IsPaste( const SwWrtShell& rSh, return bIsPaste; } +void SwTransferable::SelectPasteFormat(TransferableDataHelper& rData, sal_uInt8& nAction, + SotClipboardFormatId& nFormat) +{ + if (nFormat != SotClipboardFormatId::RICHTEXT) + { + return; + } + + if (!rData.HasFormat(SotClipboardFormatId::EMBED_SOURCE)) + { + return; + } + + if (!rData.HasFormat(SotClipboardFormatId::OBJECTDESCRIPTOR)) + { + return; + } + + TransferableObjectDescriptor aObjDesc; + if (!rData.GetTransferableObjectDescriptor(SotClipboardFormatId::OBJECTDESCRIPTOR, aObjDesc)) + { + return; + } + + if (aObjDesc.maClassName != SvGlobalName(SO3_SW_CLASSID)) + { + return; + } + + // At this point we know that we paste from Writer to Writer and the clipboard has the content + // in both RTF and ODF formats. Prefer ODF in this case. + nAction = EXCHG_OUT_ACTION_INSERT_OLE; + nFormat = SotClipboardFormatId::EMBED_SOURCE; +} + bool SwTransferable::Paste(SwWrtShell& rSh, TransferableDataHelper& rData, RndStdIds nAnchorType, bool bIgnoreComments) { sal_uInt8 nEventAction, nAction=0; @@ -1264,6 +1300,10 @@ bool SwTransferable::Paste(SwWrtShell& rSh, TransferableDataHelper& rData, RndSt return bPasted; } + // Tweak the format if necessary: the source application can be considered in this context, + // while not in sot/ code. + SwTransferable::SelectPasteFormat(rData, nAction, nFormat); + return EXCHG_INOUT_ACTION_NONE != nAction && SwTransferable::PasteData( rData, rSh, nAction, nActionFlags, nFormat, nDestination, false, false, nullptr, 0, false, nAnchorType, bIgnoreComments ); diff --git a/sw/source/uibase/inc/swdtflvr.hxx b/sw/source/uibase/inc/swdtflvr.hxx index ae34f203d2e3..79e938027aa4 100644 --- a/sw/source/uibase/inc/swdtflvr.hxx +++ b/sw/source/uibase/inc/swdtflvr.hxx @@ -220,6 +220,9 @@ public: static const css::uno::Sequence< sal_Int8 >& getUnoTunnelId(); virtual sal_Int64 SAL_CALL getSomething( const css::uno::Sequence< sal_Int8 >& rId ) override; + + static void SelectPasteFormat(TransferableDataHelper& rData, sal_uInt8& nAction, + SotClipboardFormatId& nFormat); }; #endif _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits