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 <michael.stahl@collabora.com>
This commit is contained in:
Michael Stahl
2025-10-10 15:36:01 +02:00
parent ebca26e903
commit d072b5e09e
5 changed files with 62 additions and 26 deletions
+3 -1
View File
@@ -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);
+1
View File
@@ -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 )
{
+13 -2
View File
@@ -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)
+38 -20
View File
@@ -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;
}
+7 -3
View File
@@ -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 );