summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBjoern Michaelsen <bjoern.michaelsen@libreoffice.org>2021-10-25 20:50:26 +0200
committerBjoern Michaelsen <bjoern.michaelsen@libreoffice.org>2021-10-29 13:24:01 +0200
commit3cfd63cb55ab1a7e6df53eaeb2a7623be05983d0 (patch)
treeebcc0a31ebf3fb0e42d00d1fec8bc9216f65cf83
parent3412c0f091c54da74ea6964062b9be302e126fe9 (diff)
tdf#140798, tdf#143815, tdf#141659: fix fly content hint handling
Also revert most of the test changes in 188ec34cf157ffee8c63f03f420ca9daafb5ff29, except in mailmerge, where 3bc8f90e9693f710f12632f69b9348c1c833c906 seems to have done some research and the old state wasnt particulary well-justified. In testSmartArtAnchoredInline the order of elements has changed. This exposes a bug in SwFEShell::Paste, which stops copying SpzFrameFormats (aka FlyFrameFormats and DrawFrameFormats) after having copied the first FlyFrameFormat, claiming other Flys will have been copied via FlyInFly. If there are DrawFrameFormats behind the FlyFrameFormats, they will be forgotten. So instead: - first copy the DrawFrameFormats - then copy the first FlyFrameFormat to not forget any Draw Formats. Also, give the format copying its own function, at 100 lines its annoying enough all by itself. Change-Id: I301e27ff94fb82cf0502457630acdcbfa342a566 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/124162 Tested-by: Jenkins Reviewed-by: Michael Stahl <michael.stahl@allotropia.de>
-rw-r--r--sw/qa/extras/ooxmlexport/ooxmlexport.cxx18
-rw-r--r--sw/qa/extras/ooxmlexport/ooxmlexport6.cxx10
-rw-r--r--sw/qa/extras/uiwriter/uiwriter3.cxx3
-rw-r--r--sw/source/core/frmedt/fecopy.cxx254
-rw-r--r--sw/source/core/layout/flycnt.cxx3
5 files changed, 145 insertions, 143 deletions
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx
index fcc5d6aebd4d..ce5092e01585 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx
@@ -481,31 +481,31 @@ CPPUNIT_TEST_FIXTURE(Test, testMsoPosition)
// We write the frames out in different order than they were read, so check it's the correct
// textbox first by checking width. These tests may need reordering if that gets fixed.
OUString style1 = getXPath(doc, "/w:ftr/w:p/w:r[3]/mc:AlternateContent/mc:Fallback/w:pict/v:rect", "style");
- CPPUNIT_ASSERT( style1.indexOf( ";width:36pt;" ) >= 0 );
- CPPUNIT_ASSERT( style1.indexOf( ";mso-position-horizontal-relative:text" ) >= 0 );
- CPPUNIT_ASSERT( style1.indexOf( ";mso-position-vertical-relative:text" ) >= 0 );
+ CPPUNIT_ASSERT( style1.indexOf( ";width:531pt;" ) >= 0 );
+ CPPUNIT_ASSERT( style1.indexOf( ";mso-position-vertical-relative:page" ) >= 0 );
+ CPPUNIT_ASSERT( style1.indexOf( ";mso-position-horizontal-relative:page" ) >= 0 );
OUString style2 = getXPath(doc, "/w:ftr/w:p/w:r[4]/mc:AlternateContent/mc:Fallback/w:pict/v:rect", "style");
CPPUNIT_ASSERT( style2.indexOf( ";width:549pt;" ) >= 0 );
CPPUNIT_ASSERT( style2.indexOf( ";mso-position-vertical-relative:text" ) >= 0 );
CPPUNIT_ASSERT( style2.indexOf( ";mso-position-horizontal:center" ) >= 0 );
CPPUNIT_ASSERT( style2.indexOf( ";mso-position-horizontal-relative:text" ) >= 0 );
OUString style3 = getXPath(doc, "/w:ftr/w:p/w:r[5]/mc:AlternateContent/mc:Fallback/w:pict/v:rect", "style");
- CPPUNIT_ASSERT( style3.indexOf( ";width:531pt;" ) >= 0 );
- CPPUNIT_ASSERT( style3.indexOf( ";mso-position-vertical-relative:page" ) >= 0 );
- CPPUNIT_ASSERT( style3.indexOf( ";mso-position-horizontal-relative:page" ) >= 0 );
+ CPPUNIT_ASSERT( style3.indexOf( ";width:36pt;" ) >= 0 );
+ CPPUNIT_ASSERT( style3.indexOf( ";mso-position-horizontal-relative:text" ) >= 0 );
+ CPPUNIT_ASSERT( style3.indexOf( ";mso-position-vertical-relative:text" ) >= 0 );
}
xmlDocUniquePtr doc = parseExport("word/header1.xml");
OUString style1 = getXPath(doc, "/w:hdr/w:p/w:r[2]/mc:AlternateContent/mc:Fallback/w:pict/v:rect", "style");
- CPPUNIT_ASSERT( style1.indexOf( ";width:138.15pt;" ) >= 0 );
+ CPPUNIT_ASSERT( style1.indexOf( ";width:335.75pt;" ) >= 0 );
CPPUNIT_ASSERT( style1.indexOf( ";mso-position-horizontal-relative:page" ) >= 0 );
CPPUNIT_ASSERT( style1.indexOf( ";mso-position-vertical-relative:page" ) >= 0 );
OUString style2 = getXPath(doc, "/w:hdr/w:p/w:r[3]/mc:AlternateContent/mc:Fallback/w:pict/v:rect", "style");
- CPPUNIT_ASSERT( style2.indexOf( ";width:163.8pt;" ) >= 0 );
+ CPPUNIT_ASSERT( style2.indexOf( ";width:138.15pt;" ) >= 0 );
CPPUNIT_ASSERT( style2.indexOf( ";mso-position-horizontal-relative:page" ) >= 0 );
CPPUNIT_ASSERT( style2.indexOf( ";mso-position-vertical-relative:page" ) >= 0 );
OUString style3 = getXPath(doc, "/w:hdr/w:p/w:r[4]/mc:AlternateContent/mc:Fallback/w:pict/v:rect", "style");
- CPPUNIT_ASSERT( style3.indexOf( ";width:335.75pt;" ) >= 0 );
+ CPPUNIT_ASSERT( style3.indexOf( ";width:163.8pt;" ) >= 0 );
CPPUNIT_ASSERT( style3.indexOf( ";mso-position-horizontal-relative:page" ) >= 0 );
CPPUNIT_ASSERT( style3.indexOf( ";mso-position-vertical-relative:page" ) >= 0 );
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport6.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport6.cxx
index bf666fafac1b..339613d0db93 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport6.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport6.cxx
@@ -714,14 +714,14 @@ CPPUNIT_TEST_FIXTURE(Test, testSmartArtAnchoredInline)
*/
xmlDocUniquePtr pXmlDoc = parseExport("word/document.xml");
- assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:r/w:drawing[1]/wp:anchor/wp:docPr","id","1");
- assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:r/w:drawing[1]/wp:anchor/wp:docPr","name","Diagram1");
+ assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:r/w:drawing[2]/wp:anchor/wp:docPr","id","2");
+ assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:r/w:drawing[2]/wp:anchor/wp:docPr","name","Diagram2");
- assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:r/mc:AlternateContent/mc:Choice/w:drawing/wp:anchor/wp:docPr","id","2");
+ assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:r/mc:AlternateContent/mc:Choice/w:drawing/wp:anchor/wp:docPr","id","3");
assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:r/mc:AlternateContent/mc:Choice/w:drawing/wp:anchor/wp:docPr","name","10-Point Star 3");
- assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:r/w:drawing[2]/wp:anchor/wp:docPr","id","3");
- assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:r/w:drawing[2]/wp:anchor/wp:docPr","name","Picture 1");
+ assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:r/w:drawing[1]/wp:anchor/wp:docPr","id","1");
+ assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:r/w:drawing[1]/wp:anchor/wp:docPr","name","Picture 1");
}
CPPUNIT_TEST_FIXTURE(Test, testFdo65833)
diff --git a/sw/qa/extras/uiwriter/uiwriter3.cxx b/sw/qa/extras/uiwriter/uiwriter3.cxx
index 3315fc897907..cdd255f10343 100644
--- a/sw/qa/extras/uiwriter/uiwriter3.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter3.cxx
@@ -257,8 +257,7 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest3, testTdf132911)
dispatchCommand(mxComponent, ".uno:Undo", {});
Scheduler::ProcessEventsToIdle();
CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xIndexAccess->getCount());
- //FIXME: tdf#143815: Number of images should be 4 and not 8
- CPPUNIT_ASSERT_EQUAL(8, getShapes());
+ CPPUNIT_ASSERT_EQUAL(4, getShapes());
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest3, testTdf61154)
diff --git a/sw/source/core/frmedt/fecopy.cxx b/sw/source/core/frmedt/fecopy.cxx
index ee031ba3df9d..fff8c546317c 100644
--- a/sw/source/core/frmedt/fecopy.cxx
+++ b/sw/source/core/frmedt/fecopy.cxx
@@ -70,6 +70,7 @@
#include <frameformats.hxx>
#include <vcl/virdev.hxx>
#include <svx/svdundo.hxx>
+#include <viewimp.hxx>
using namespace ::com::sun::star;
@@ -708,6 +709,123 @@ namespace {
}
}
+namespace {
+ bool lcl_PasteFlyOrDrawFormat(SwPaM& rPaM, SwFrameFormat* pCpyFormat, SwFEShell& rSh)
+ {
+ auto& rImp = *rSh.Imp();
+ auto& rDoc = *rSh.GetDoc();
+ auto& rDrawView = *rImp.GetDrawView();
+ if(rDrawView.IsGroupEntered() &&
+ RES_DRAWFRMFMT == pCpyFormat->Which() &&
+ (RndStdIds::FLY_AS_CHAR != pCpyFormat->GetAnchor().GetAnchorId()))
+ {
+ const SdrObject* pSdrObj = pCpyFormat->FindSdrObject();
+ if(pSdrObj)
+ {
+ SdrObject* pNew = rDoc.CloneSdrObj(*pSdrObj, false, false);
+ // Insert object sets any anchor position to 0.
+ // Therefore we calculate the absolute position here
+ // and after the insert the anchor of the object
+ // is set to the anchor of the group object.
+ tools::Rectangle aSnapRect = pNew->GetSnapRect();
+ if(pNew->GetAnchorPos().X() || pNew->GetAnchorPos().Y())
+ {
+ const Point aPoint(0, 0);
+ // OD 2004-04-05 #i26791# - direct drawing object
+ // positioning for group members
+ pNew->NbcSetAnchorPos(aPoint);
+ pNew->NbcSetSnapRect(aSnapRect);
+ }
+
+ rDrawView.InsertObjectAtView(pNew, *rImp.GetPageView());
+
+ Point aGrpAnchor(0, 0);
+ SdrObjList* pList = pNew->getParentSdrObjListFromSdrObject();
+ if(pList)
+ {
+ SdrObjGroup* pOwner(dynamic_cast<SdrObjGroup*>(pList->getSdrObjectFromSdrObjList()));
+
+ if(nullptr != pOwner)
+ aGrpAnchor = pOwner->GetAnchorPos();
+ }
+
+ // OD 2004-04-05 #i26791# - direct drawing object
+ // positioning for group members
+ pNew->NbcSetAnchorPos(aGrpAnchor);
+ pNew->SetSnapRect(aSnapRect);
+ return true;
+ }
+ }
+ SwFormatAnchor aAnchor(pCpyFormat->GetAnchor());
+ if ((RndStdIds::FLY_AT_PARA == aAnchor.GetAnchorId()) ||
+ (RndStdIds::FLY_AT_CHAR == aAnchor.GetAnchorId()) ||
+ (RndStdIds::FLY_AS_CHAR == aAnchor.GetAnchorId()))
+ {
+ SwPosition* pPos = rPaM.GetPoint();
+ // allow shapes (no controls) in header/footer
+ if(RES_DRAWFRMFMT == pCpyFormat->Which() && rDoc.IsInHeaderFooter(pPos->nNode))
+ {
+ const SdrObject *pCpyObj = pCpyFormat->FindSdrObject();
+ if(pCpyObj && CheckControlLayer(pCpyObj))
+ return true;
+ }
+ 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.
+ return true;
+ }
+ // Ignore TextBoxes, they are already handled in sw::DocumentLayoutManager::CopyLayoutFormat().
+ if(SwTextBoxHelper::isTextBox(pCpyFormat, RES_FLYFRMFMT))
+ return true;
+ aAnchor.SetAnchor(pPos);
+ }
+ else if(RndStdIds::FLY_AT_PAGE == aAnchor.GetAnchorId())
+ {
+ aAnchor.SetPageNum(rSh.GetPhyPageNum());
+ }
+ else if(RndStdIds::FLY_AT_FLY == aAnchor.GetAnchorId())
+ {
+ Point aPt;
+ (void)lcl_SetAnchor(*rPaM.GetPoint(), rPaM.GetNode(), nullptr, aPt, rSh, aAnchor, aPt, false);
+ }
+
+ SwFrameFormat* pNew = rDoc.getIDocumentLayoutAccess().CopyLayoutFormat(*pCpyFormat, aAnchor, true, true);
+
+ if(!pNew)
+ return true;
+ switch(pNew->Which())
+ {
+ case RES_FLYFRMFMT:
+ {
+ assert(dynamic_cast<SwFlyFrameFormat*>(pNew));
+ const Point aPt(rSh.GetCursorDocPos());
+ SwFlyFrame* pFlyFrame = static_cast<SwFlyFrameFormat*>(pNew)->GetFrame(&aPt);
+ if(pFlyFrame)
+ rSh.SelectFlyFrame(*pFlyFrame);
+ return false;
+ }
+ case RES_DRAWFRMFMT:
+ {
+ assert(dynamic_cast<SwDrawFrameFormat*>(pNew));
+ SwDrawFrameFormat* pDrawFormat = static_cast<SwDrawFrameFormat*>(pNew);
+ // #i52780# - drawing object has to be made visible on paste.
+ pDrawFormat->CallSwClientNotify(sw::DrawFrameFormatHint(sw::DrawFrameFormatHintId::PREPPASTING));
+ SdrObject* pObj = pDrawFormat->FindSdrObject();
+ rDrawView.MarkObj(pObj, rDrawView.GetSdrPageView());
+ // #i47455# - notify draw frame format
+ // that position attributes are already set.
+ pDrawFormat->PosAttrSet();
+ break;
+ }
+ default:
+ SAL_WARN("sw.core", "unknown fly type");
+ }
+ return true;
+ }
+}
+
bool SwFEShell::Paste(SwDoc& rClpDoc, bool bNestedTable)
{
CurrShell aCurr( this );
@@ -912,136 +1030,18 @@ bool SwFEShell::Paste(SwDoc& rClpDoc, bool bNestedTable)
break; // exit the "while-loop"
}
- else if( *aCpyPam.GetPoint() == *aCpyPam.GetMark() &&
- !rClpDoc.GetSpzFrameFormats()->empty() )
+ else if(*aCpyPam.GetPoint() == *aCpyPam.GetMark() && !rClpDoc.GetSpzFrameFormats()->empty())
{
// we need a DrawView
- if( !Imp()->GetDrawView() )
+ if(!Imp()->GetDrawView())
MakeDrawView();
-
- for ( auto pCpyFormat : *rClpDoc.GetSpzFrameFormats() )
- {
- bool bInsWithFormat = true;
-
- if( Imp()->GetDrawView()->IsGroupEntered() &&
- RES_DRAWFRMFMT == pCpyFormat->Which() &&
- (RndStdIds::FLY_AS_CHAR != pCpyFormat->GetAnchor().GetAnchorId()) )
- {
- const SdrObject* pSdrObj = pCpyFormat->FindSdrObject();
- if( pSdrObj )
- {
- SdrObject* pNew = GetDoc()->CloneSdrObj( *pSdrObj,
- false, false );
-
- // Insert object sets any anchor position to 0.
- // Therefore we calculate the absolute position here
- // and after the insert the anchor of the object
- // is set to the anchor of the group object.
- tools::Rectangle aSnapRect = pNew->GetSnapRect();
- if( pNew->GetAnchorPos().X() || pNew->GetAnchorPos().Y() )
- {
- const Point aPoint( 0, 0 );
- // OD 2004-04-05 #i26791# - direct drawing object
- // positioning for group members
- pNew->NbcSetAnchorPos( aPoint );
- pNew->NbcSetSnapRect( aSnapRect );
- }
-
- Imp()->GetDrawView()->InsertObjectAtView( pNew, *Imp()->GetPageView() );
-
- Point aGrpAnchor( 0, 0 );
- SdrObjList* pList = pNew->getParentSdrObjListFromSdrObject();
- if ( pList )
- {
- SdrObjGroup* pOwner(dynamic_cast< SdrObjGroup* >(pList->getSdrObjectFromSdrObjList()));
-
- if(nullptr != pOwner)
- {
- aGrpAnchor = pOwner->GetAnchorPos();
- }
- }
-
- // OD 2004-04-05 #i26791# - direct drawing object
- // positioning for group members
- pNew->NbcSetAnchorPos( aGrpAnchor );
- pNew->SetSnapRect( aSnapRect );
-
- bInsWithFormat = false;
- }
- }
-
- if( bInsWithFormat )
- {
- SwFormatAnchor aAnchor( pCpyFormat->GetAnchor() );
- if ((RndStdIds::FLY_AT_PARA == aAnchor.GetAnchorId()) ||
- (RndStdIds::FLY_AT_CHAR == aAnchor.GetAnchorId()) ||
- (RndStdIds::FLY_AS_CHAR == aAnchor.GetAnchorId()))
- {
- SwPosition* pPos = rPaM.GetPoint();
- // allow shapes (no controls) in header/footer
- if( RES_DRAWFRMFMT == pCpyFormat->Which() &&
- GetDoc()->IsInHeaderFooter( pPos->nNode ) )
- {
- const SdrObject *pCpyObj = pCpyFormat->FindSdrObject();
- 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))
- continue;
-
- aAnchor.SetAnchor( pPos );
- }
- else if ( RndStdIds::FLY_AT_PAGE == aAnchor.GetAnchorId() )
- {
- aAnchor.SetPageNum( GetPhyPageNum() );
- }
- else if( RndStdIds::FLY_AT_FLY == aAnchor.GetAnchorId() )
- {
- Point aPt;
- (void)lcl_SetAnchor( *rPaM.GetPoint(), rPaM.GetNode(),
- nullptr, aPt, *this, aAnchor, aPt, false );
- }
-
- SwFrameFormat * pNew = GetDoc()->getIDocumentLayoutAccess().CopyLayoutFormat( *pCpyFormat, aAnchor, true, true );
-
- if( pNew )
- {
- if( RES_FLYFRMFMT == pNew->Which() )
- {
- const Point aPt( GetCursorDocPos() );
- SwFlyFrame* pFlyFrame = static_cast<SwFlyFrameFormat*>(pNew)->
- GetFrame( &aPt );
- if( pFlyFrame )
- SelectFlyFrame( *pFlyFrame );
- // always pick the first FlyFrame only; the others
- // were copied to the clipboard via Fly in Fly
- break;
- }
- else
- {
- OSL_ENSURE( RES_DRAWFRMFMT == pNew->Which(), "New format.");
- // #i52780# - drawing object has to be made visible on paste.
- pNew->CallSwClientNotify(sw::DrawFrameFormatHint(sw::DrawFrameFormatHintId::PREPPASTING));
- SdrObject *pObj = pNew->FindSdrObject();
- SwDrawView *pDV = Imp()->GetDrawView();
- pDV->MarkObj( pObj, pDV->GetSdrPageView() );
- // #i47455# - notify draw frame format
- // that position attributes are already set.
- if (SwDrawFrameFormat *pDrawFormat = dynamic_cast<SwDrawFrameFormat*>(pNew))
- pDrawFormat->PosAttrSet();
- }
- }
- }
- }
+ for(auto pCpyFormat: *rClpDoc.GetSpzFrameFormats())
+ if(pCpyFormat->Which() != RES_FLYFRMFMT)
+ lcl_PasteFlyOrDrawFormat(rPaM, pCpyFormat, *this);
+ for(auto pCpyFormat: *rClpDoc.GetSpzFrameFormats())
+ if(pCpyFormat->Which() == RES_FLYFRMFMT)
+ if(!lcl_PasteFlyOrDrawFormat(rPaM, pCpyFormat, *this))
+ break;
}
else
{
diff --git a/sw/source/core/layout/flycnt.cxx b/sw/source/core/layout/flycnt.cxx
index b90469066c70..2ed6bb36b67a 100644
--- a/sw/source/core/layout/flycnt.cxx
+++ b/sw/source/core/layout/flycnt.cxx
@@ -86,7 +86,10 @@ SwFlyAtContentFrame::SwFlyAtContentFrame( SwFlyFrameFormat *pFormat, SwFrame* pS
void SwFlyAtContentFrame::SwClientNotify(const SwModify& rMod, const SfxHint& rHint)
{
if (rHint.GetId() != SfxHintId::SwLegacyModify)
+ {
+ SwFlyFrame::SwClientNotify(rMod, rHint);
return;
+ }
auto pLegacy = static_cast<const sw::LegacyModifyHint*>(&rHint);
const SwFormatAnchor* pAnch = pLegacy->m_pNew ? GetAnchorFromPoolItem(*pLegacy->m_pNew) : nullptr;
if(!pAnch)