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 bdda0c123b28531f515c37faf804d9ed1659074f Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Mon Nov 2 21:01:14 2020 +0100 Commit: Caolán McNamara <caol...@redhat.com> CommitDate: Tue Nov 3 21:58:38 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. (cherry picked from commit 3ac675736066b47da7329269a01c1ef4a9cfe72a) Conflicts: sw/qa/core/frmedt/frmedt.cxx Change-Id: I3376beb414f91abfa6f3f5640f825ccae34911c2 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/105247 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caol...@redhat.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 c737187887c9..d0929c25d7f8 100644 --- a/sw/qa/core/frmedt/frmedt.cxx +++ b/sw/qa/core/frmedt/frmedt.cxx @@ -19,6 +19,7 @@ #include <drawdoc.hxx> #include <dcontact.hxx> #include <frameformats.hxx> +#include <swdtflvr.hxx> static char const DATA_DIRECTORY[] = "/sw/qa/core/frmedt/data/"; @@ -106,6 +107,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 2522c039ce0d..67027a4c5b9e 100644 --- a/sw/source/core/frmedt/fecopy.cxx +++ b/sw/source/core/frmedt/fecopy.cxx @@ -671,6 +671,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* pClpDoc, bool bNestedTable ) @@ -958,6 +993,13 @@ bool SwFEShell::Paste( SwDoc* pClpDoc, 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