sw/qa/core/frmedt/data/paste-fly-in-textbox.docx |binary sw/qa/core/frmedt/frmedt.cxx | 30 ++++++++++++++++ sw/source/core/frmedt/fecopy.cxx | 42 +++++++++++++++++++++++ 3 files changed, 72 insertions(+)
New commits: commit 3ac675736066b47da7329269a01c1ef4a9cfe72a Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Mon Nov 2 21:01:14 2020 +0100 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Tue Nov 3 09:01:49 2020 +0100 tdf#135893 sw paste: fix copying fly frame in textbox twice Regression from commit c7307c77254557646f33017af915f6808a861e29 (fdo#82191 sw::DocumentLayoutManager: copy textbox content of draw formats, 2014-08-15), the problem is that the fly+draw format copies the fly content recursively already, so when we would copy all special formats of the document, the inner fly frame is copied twice. This is normally not a problem for fly frames (where you can't select multiple fly frames at the same time), nor a problem for draw frames (which have no sw content), but it's a problem for the combination of these, TextBoxes. Fix the problem by ignoring fly frames which are anchored in such TextBoxes: we do the same for fly frames which have an associated draw format already. Change-Id: I3376beb414f91abfa6f3f5640f825ccae34911c2 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/105204 Tested-by: Jenkins Reviewed-by: Miklos Vajna <vmik...@collabora.com> diff --git a/sw/qa/core/frmedt/data/paste-fly-in-textbox.docx b/sw/qa/core/frmedt/data/paste-fly-in-textbox.docx new file mode 100644 index 000000000000..75bf13b13b67 Binary files /dev/null and b/sw/qa/core/frmedt/data/paste-fly-in-textbox.docx differ diff --git a/sw/qa/core/frmedt/frmedt.cxx b/sw/qa/core/frmedt/frmedt.cxx index b4074a73e12d..c0ea7e0566e9 100644 --- a/sw/qa/core/frmedt/frmedt.cxx +++ b/sw/qa/core/frmedt/frmedt.cxx @@ -22,6 +22,7 @@ #include <frameformats.hxx> #include <unotxdoc.hxx> #include <docsh.hxx> +#include <swdtflvr.hxx> char const DATA_DIRECTORY[] = "/sw/qa/core/frmedt/data/"; @@ -109,6 +110,35 @@ CPPUNIT_TEST_FIXTURE(SwCoreFrmedtTest, testVertPosFromBottomBoundingBox) CPPUNIT_ASSERT_EQUAL(-1 * nPagePrintAreaBottom, aBoundRect.Pos().getY()); } +CPPUNIT_TEST_FIXTURE(SwCoreFrmedtTest, testPasteFlyInTextBox) +{ + // Given a document that contains a textbox, which contains an sw image (fly frame) + load(DATA_DIRECTORY, "paste-fly-in-textbox.docx"); + SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get()); + SwDocShell* pDocShell = pTextDoc->GetDocShell(); + SwWrtShell* pWrtShell = pDocShell->GetWrtShell(); + SwDoc* pDoc = pDocShell->GetDoc(); + SdrPage* pPage = pDoc->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0); + SdrObject* pObject = pPage->GetObj(0); + pWrtShell->SelectObj(Point(), 0, pObject); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), pDoc->GetSpzFrameFormats()->GetFormatCount()); + rtl::Reference<SwTransferable> pTransfer = new SwTransferable(*pWrtShell); + pTransfer->Cut(); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), pDoc->GetSpzFrameFormats()->GetFormatCount()); + TransferableDataHelper aHelper(pTransfer.get()); + + // When pasting that to an empty document. + SwTransferable::Paste(*pWrtShell, aHelper); + + // Then we should have the image only once: 3 formats (draw+fly formats for the textbox and a + // fly format for the image). + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 3 + // - Actual : 4 + // i.e. the image was pasted twice. + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), pDoc->GetSpzFrameFormats()->GetFormatCount()); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/frmedt/fecopy.cxx b/sw/source/core/frmedt/fecopy.cxx index ca20591a9a61..9257514a2236 100644 --- a/sw/source/core/frmedt/fecopy.cxx +++ b/sw/source/core/frmedt/fecopy.cxx @@ -666,6 +666,41 @@ namespace { { return rPaM.HasMark() && *rPaM.GetPoint() != *rPaM.GetMark(); } + + /// Is pFormat anchored in a fly frame which has an associated draw format? + bool IsInTextBox(const SwFrameFormat* pFormat) + { + const SwFormatAnchor& rAnchor = pFormat->GetAnchor(); + const SwPosition* pPosition = rAnchor.GetContentAnchor(); + if (!pPosition) + { + return false; + } + + const SwStartNode* pFlyNode = pPosition->nNode.GetNode().FindFlyStartNode(); + if (!pFlyNode) + { + return false; + } + + for ( const auto& pSpzFormat : *pFormat->GetDoc()->GetSpzFrameFormats() ) + { + if (pSpzFormat->Which() != RES_FLYFRMFMT) + { + continue; + } + + const SwNodeIndex* pIdx = pSpzFormat->GetContent().GetContentIdx(); + if (!pIdx || pFlyNode != &pIdx->GetNode()) + { + continue; + } + + return SwTextBoxHelper::isTextBox(pSpzFormat, RES_FLYFRMFMT); + } + + return false; + } } bool SwFEShell::Paste(SwDoc& rClpDoc, bool bNestedTable) @@ -952,6 +987,13 @@ bool SwFEShell::Paste(SwDoc& rClpDoc, bool bNestedTable) if (pCpyObj && CheckControlLayer(pCpyObj)) continue; } + else if (pCpyFormat->Which() == RES_FLYFRMFMT && IsInTextBox(pCpyFormat)) + { + // This is a fly frame which is anchored in a TextBox, ignore it as + // it's already copied as part of copying the content of the + // TextBox. + continue; + } // Ignore TextBoxes, they are already handled in sw::DocumentLayoutManager::CopyLayoutFormat(). if (SwTextBoxHelper::isTextBox(pCpyFormat, RES_FLYFRMFMT)) _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits