sw/inc/fesh.hxx | 4 +- sw/source/core/doc/doclay.cxx | 1 sw/source/core/frmedt/fecopy.cxx | 15 +++++++-- sw/source/uibase/dochdl/swdtflvr.cxx | 58 ++++++++++++++++++++++------------- sw/source/uibase/inc/swdtflvr.hxx | 10 ++++-- 5 files changed, 62 insertions(+), 26 deletions(-)
New commits: commit d072b5e09e1c7f759c797b7ba1ee89a3bfef8858 Author: Michael Stahl <[email protected]> AuthorDate: Fri Oct 10 13:41:22 2025 +0200 Commit: Michael Stahl <[email protected]> CommitDate: Fri Oct 10 15:36:01 2025 +0200 tdf#51850 sw: AutoCaption for a single pasted image AutoCaption mostly isn't enabled for clipboard paste, except for one special case. For the case when the source is outside LO, let SwTransferable::PasteGrf() set a flag that the caption should be inserted (the SwPasteSdr::Insert case), which can then be handled at the end. PasteFileList() appears to be used when an image file is copied from Nautilus. For internal paste, it gets more complicated because SwFEShell::Paste() knows what was inserted, but caption can only be added later, outside of any StartAction()/EndAction(), because if an action is pending, SwWrtShell::GetSelectionType() does not return useful results, and the lcl_InsertLabel() ends up erroneously inserting a text node next to the SwGrfNode. Change-Id: I3e16f407fd409a0f315be139376ad9e5f0b526cd Reviewed-on: https://gerrit.libreoffice.org/c/core/+/192165 Tested-by: Jenkins Reviewed-by: Michael Stahl <[email protected]> diff --git a/sw/inc/fesh.hxx b/sw/inc/fesh.hxx index ae25ec87b3ab..1aaa5cd0dd25 100644 --- a/sw/inc/fesh.hxx +++ b/sw/inc/fesh.hxx @@ -258,7 +258,9 @@ public: /// Copy and Paste methods for internal clipboard. /// bDeleteRedlines: if content inside a delete redline should be stripped away in rClpDoc. SW_DLLPUBLIC void Copy( SwDoc& rClpDoc, const OUString* pNewClpText = nullptr, bool bDeleteRedlines = true ); - SW_DLLPUBLIC bool Paste( SwDoc& rClpDoc, bool bNestedTable = false ); + // @return possibly a pasted fly frame to be captioned + SW_DLLPUBLIC ::std::pair<bool, SwFrameFormat const*> + Paste(SwDoc& rClpDoc, bool bNestedTable = false); /// Paste some pages into another doc - used in mailmerge. SW_DLLPUBLIC void PastePages( SwFEShell& rToFill, sal_uInt16 nStartPage, sal_uInt16 nEndPage); diff --git a/sw/source/core/doc/doclay.cxx b/sw/source/core/doc/doclay.cxx index b6ceedb74674..fdef5c76f427 100644 --- a/sw/source/core/doc/doclay.cxx +++ b/sw/source/core/doc/doclay.cxx @@ -685,6 +685,7 @@ lcl_InsertLabel(SwDoc & rDoc, SwTextFormatColls *const pTextFormatCollTable, { SwStartNode *pSttNd = rDoc.GetNodes()[nNdIdx]->GetStartNode(); assert(pSttNd && "No StartNode in InsertLabel."); + assert(!rDoc.GetNodes()[nNdIdx+1]->IsGrfNode() && !rDoc.GetNodes()[nNdIdx+1]->IsOLENode()); // these need to be SwLabelType::Object SwNodeOffset nNode; if( bBefore ) { diff --git a/sw/source/core/frmedt/fecopy.cxx b/sw/source/core/frmedt/fecopy.cxx index 174e60b3187a..c0ee3c3f6e1c 100644 --- a/sw/source/core/frmedt/fecopy.cxx +++ b/sw/source/core/frmedt/fecopy.cxx @@ -844,7 +844,8 @@ namespace { } } -bool SwFEShell::Paste(SwDoc& rClpDoc, bool bNestedTable) +::std::pair<bool, SwFrameFormat const*> +SwFEShell::Paste(SwDoc& rClpDoc, bool const bNestedTable) { CurrShell aCurr( this ); // then till end of the nodes array @@ -864,6 +865,8 @@ bool SwFEShell::Paste(SwDoc& rClpDoc, bool bNestedTable) SwTableNode *const pSrcNd = aCpyPam.GetMarkNode().GetTableNode(); bool bRet = true; + SwFrameFormat const* pNewFlyToCaption{nullptr}; + StartAllAction(); GetDoc()->GetIDocumentUndoRedo().StartUndo( SwUndoId::INSGLOSSARY, nullptr ); GetDoc()->getIDocumentFieldsAccess().LockExpFields(); @@ -1076,6 +1079,14 @@ bool SwFEShell::Paste(SwDoc& rClpDoc, bool bNestedTable) { lcl_InitSelectFlyOrDrawFormat(pFlyFormat, *this, isSelect); } + if (isSelect && inserted.size() == 1) + { + if (inserted.front()->Which() == RES_FLYFRMFMT + && GetDoc()->GetNodes()[inserted.front()->GetContent().GetContentIdx()->GetIndex() + 1]->IsGrfNode()) + { + pNewFlyToCaption = inserted.front(); + } + } } else { @@ -1166,7 +1177,7 @@ bool SwFEShell::Paste(SwDoc& rClpDoc, bool bNestedTable) GetDoc()->getIDocumentFieldsAccess().UpdateFields(false); EndAllAction(); - return bRet; + return {bRet, pNewFlyToCaption}; } void SwFEShell::PastePages( SwFEShell& rToFill, sal_uInt16 nStartPage, sal_uInt16 nEndPage) diff --git a/sw/source/uibase/dochdl/swdtflvr.cxx b/sw/source/uibase/dochdl/swdtflvr.cxx index 9b9bf0574496..0167b7e6f42e 100644 --- a/sw/source/uibase/dochdl/swdtflvr.cxx +++ b/sw/source/uibase/dochdl/swdtflvr.cxx @@ -1907,7 +1907,8 @@ bool SwTransferable::PasteData( const TransferableDataHelper& rData, case SotClipboardFormatId::GDIMETAFILE: bRet = SwTransferable::PasteGrf( rData, rSh, nFormat, SwPasteSdr::Insert,pPt, - nActionFlags, nDropAction, bNeedToSelectBeforePaste); + nActionFlags, nDropAction, bNeedToSelectBeforePaste, + &bCallAutoCaption); break; case SotClipboardFormatId::XFORMS: @@ -1926,14 +1927,14 @@ bool SwTransferable::PasteData( const TransferableDataHelper& rData, : EXCHG_IN_ACTION_LINK == nAction ? SwPasteSdr::SetAttr : SwPasteSdr::Insert), - pPt, nActionFlags, nullptr ); + pPt, nActionFlags, &bCallAutoCaption); break; case SotClipboardFormatId::FILE_LIST: // then insert as graphics only bRet = SwTransferable::PasteFileList( rData, rSh, EXCHG_IN_ACTION_LINK == nAction, - pPt, bMsg ); + pPt, bMsg, &bCallAutoCaption ); break; case SotClipboardFormatId::SONLK: @@ -1963,13 +1964,10 @@ bool SwTransferable::PasteData( const TransferableDataHelper& rData, case EXCHG_OUT_ACTION_INSERT_FILE: { - bool graphicInserted; bRet = SwTransferable::PasteFileName( rData, rSh, nFormat, SwPasteSdr::Insert, pPt, nActionFlags, - &graphicInserted ); - if( graphicInserted ) - bCallAutoCaption = true; + &bCallAutoCaption); } break; @@ -2035,7 +2033,8 @@ bool SwTransferable::PasteData( const TransferableDataHelper& rData, case SotClipboardFormatId::UNIFORMRESOURCELOCATOR: bRet = SwTransferable::PasteGrf( rData, rSh, nFormat, SwPasteSdr::SetAttr, pPt, - nActionFlags, nDropAction, bNeedToSelectBeforePaste); + nActionFlags, nDropAction, bNeedToSelectBeforePaste, + nullptr/*no caption?*/); break; default: OSL_FAIL( "unknown format" ); @@ -2054,7 +2053,8 @@ bool SwTransferable::PasteData( const TransferableDataHelper& rData, case EXCHG_OUT_ACTION_INSERT_GRAPH: bRet = SwTransferable::PasteGrf( rData, rSh, nFormat, SwPasteSdr::Insert, pPt, - nActionFlags, nDropAction, bNeedToSelectBeforePaste, nAnchorType ); + nActionFlags, nDropAction, bNeedToSelectBeforePaste, + &bCallAutoCaption, nAnchorType); break; case EXCHG_OUT_ACTION_REPLACE_DRAWOBJ: @@ -2069,7 +2069,8 @@ bool SwTransferable::PasteData( const TransferableDataHelper& rData, case EXCHG_OUT_ACTION_REPLACE_GRAPH: bRet = SwTransferable::PasteGrf( rData, rSh, nFormat, SwPasteSdr::Replace,pPt, - nActionFlags, nDropAction, bNeedToSelectBeforePaste); + nActionFlags, nDropAction, bNeedToSelectBeforePaste, + nullptr/*no caption for replace?*/); break; case EXCHG_OUT_ACTION_INSERT_INTERACTIVE: @@ -2876,7 +2877,9 @@ bool SwTransferable::PasteSdrFormat( const TransferableDataHelper& rData, bool SwTransferable::PasteGrf( const TransferableDataHelper& rData, SwWrtShell& rSh, SotClipboardFormatId nFormat, SwPasteSdr nAction, const Point* pPt, - SotExchangeActionFlags nActionFlags, sal_Int8 nDropAction, bool bNeedToSelectBeforePaste, RndStdIds nAnchorType ) + SotExchangeActionFlags const nActionFlags, sal_Int8 const nDropAction, + bool const bNeedToSelectBeforePaste, bool *const pbCallAutoCaption, + RndStdIds const nAnchorType) { bool bRet = false; @@ -3094,6 +3097,10 @@ bool SwTransferable::PasteGrf( const TransferableDataHelper& rData, SwWrtShell& else { rSh.Pop(SwCursorShell::PopMode::DeleteStack); + if (pbCallAutoCaption) + { // only possible if selected + *pbCallAutoCaption = true; + } } } } @@ -3196,13 +3203,10 @@ bool SwTransferable::PasteFileName( const TransferableDataHelper& rData, SwWrtShell& rSh, SotClipboardFormatId nFormat, SwPasteSdr nAction, const Point* pPt, SotExchangeActionFlags nActionFlags, - bool * graphicInserted) + bool *const pbCallAutoCaption) { bool bRet = SwTransferable::PasteGrf( rData, rSh, nFormat, nAction, - pPt, nActionFlags, 0, false); - if (graphicInserted != nullptr) { - *graphicInserted = bRet; - } + pPt, nActionFlags, 0, false, pbCallAutoCaption); if( !bRet ) { OUString sFile, sDesc; @@ -3395,7 +3399,8 @@ bool SwTransferable::PasteDBData( const TransferableDataHelper& rData, bool SwTransferable::PasteFileList( const TransferableDataHelper& rData, SwWrtShell& rSh, bool bLink, - const Point* pPt, bool bMsg ) + const Point* pPt, bool bMsg, + bool *const pbCallAutoCaption) { bool bRet = false; FileList aFileList; @@ -3412,7 +3417,9 @@ bool SwTransferable::PasteFileList( const TransferableDataHelper& rData, TransferableDataHelper aData( pHlp ); if( SwTransferable::PasteFileName( aData, rSh, SotClipboardFormatId::SIMPLE_FILE, nAct, - pPt, SotExchangeActionFlags::NONE, nullptr )) + pPt, SotExchangeActionFlags::NONE, + // only caption a single image (PasteGrf only sets true for Insert) + aFileList.Count() == 1 ? pbCallAutoCaption : nullptr)) { if( bLink ) { @@ -3897,7 +3904,7 @@ bool SwTransferable::PrivatePaste(SwWrtShell& rShell, SwPasteContext* pContext, const SelectionType nSelection = rShell.GetSelectionType(); - SwTrnsfrActionAndUndo aAction( &rShell ); + ::std::optional<SwTrnsfrActionAndUndo> oAction(&rShell); bool bKillPaMs = false; @@ -3953,9 +3960,13 @@ bool SwTransferable::PrivatePaste(SwWrtShell& rShell, SwPasteContext* pContext, } bool bRet = true; + SwFrameFormat const* pNewFlyToCaption{nullptr}; // m_pWrtShell is nullptr when the source document is closed already. if (!m_pWrtShell || lcl_checkClassification(m_pWrtShell->GetDoc(), rShell.GetDoc())) - bRet = rShell.Paste(m_pClpDocFac->GetDoc(), ePasteTable == PasteTableType::PASTE_TABLE); + { + ::std::tie(bRet, pNewFlyToCaption) = rShell.Paste( + m_pClpDocFac->GetDoc(), ePasteTable == PasteTableType::PASTE_TABLE); + } if( bKillPaMs ) rShell.KillPams(); @@ -3964,6 +3975,13 @@ bool SwTransferable::PrivatePaste(SwWrtShell& rShell, SwPasteContext* pContext, if( bRet && bSmart && ((bInWrd && !bEndWrd )|| bSttWrd) ) rShell.SwEditShell::Insert(' '); + oAction.reset(); // inserting caption does not work when ActionPend() + + if (pNewFlyToCaption) + { + rShell.GetView().AutoCaption(GRAPHIC_CAP); + } + return bRet; } diff --git a/sw/source/uibase/inc/swdtflvr.hxx b/sw/source/uibase/inc/swdtflvr.hxx index 9c6c00561050..2301d783ba02 100644 --- a/sw/source/uibase/inc/swdtflvr.hxx +++ b/sw/source/uibase/inc/swdtflvr.hxx @@ -126,7 +126,9 @@ class SAL_DLLPUBLIC_RTTI SwTransferable final : public TransferableHelper static bool PasteGrf( const TransferableDataHelper& rData, SwWrtShell& rSh, SotClipboardFormatId nFormat, SwPasteSdr nAction, const Point* pPt, - SotExchangeActionFlags nActionFlags, sal_Int8 nDropAction, bool bNeedToSelectBeforePaste, RndStdIds nAnchorType = RndStdIds::FLY_AT_PARA ); + SotExchangeActionFlags nActionFlags, sal_Int8 nDropAction, + bool bNeedToSelectBeforePaste, bool * pbCallAutoCaption, + RndStdIds nAnchorType = RndStdIds::FLY_AT_PARA); static bool PasteImageMap( const TransferableDataHelper& rData, SwWrtShell& rSh ); @@ -136,7 +138,8 @@ class SAL_DLLPUBLIC_RTTI SwTransferable final : public TransferableHelper static bool PasteFileName( const TransferableDataHelper& rData, SwWrtShell& rSh, SotClipboardFormatId nFormat, SwPasteSdr nAction, - const Point* pPt, SotExchangeActionFlags nActionFlags, bool * graphicInserted ); + const Point* pPt, SotExchangeActionFlags nActionFlags, + bool * pbCallAutoCaption); static bool PasteDBData( const TransferableDataHelper& rData, SwWrtShell& rSh, SotClipboardFormatId nFormat, bool bLink, const Point* pDragPt, @@ -144,7 +147,8 @@ class SAL_DLLPUBLIC_RTTI SwTransferable final : public TransferableHelper static bool PasteFileList( const TransferableDataHelper& rData, SwWrtShell& rSh, bool bLink, - const Point* pPt, bool bMsg ); + const Point* pPt, bool bMsg, + bool * pbCallAutoCaption); bool PrivatePaste( SwWrtShell& rShell, SwPasteContext* pContext = nullptr, PasteTableType ePasteTable = PasteTableType::PASTE_DEFAULT );
