summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLászló Németh <nemeth@numbertext.org>2019-12-11 15:38:05 +0100
committerLászló Németh <nemeth@numbertext.org>2019-12-14 17:58:54 +0100
commit1e278d1d0cfb1d5375195aa764739f00633f21e8 (patch)
tree13e94f15370305dec09a0d209b71a863e60f8eba
parent9f9a0557c16a6b274ba60f5efc983978d1a88762 (diff)
tdf#37156 Writer menu: Paste as Nested table
Paste table data in Writer tables overwrites the content of the existing cells, when the cursor is there in an empty cell or at the beginning of the first paragraph of a table cell. Using the new Paste Special option "As Nested Table" of table popup (local) menu and Edit->Paste Special, (based on the new .uno:PasteNestedTable command), clipboard content (including native tables or tables copied from Calc or other spreadsheets) are inserted as nested tables in empty cells and at cell starting cursor positions. Change-Id: I32807200883651e492ae280efce7bf9806f22283 Reviewed-on: https://gerrit.libreoffice.org/85094 Tested-by: Jenkins Reviewed-by: László Németh <nemeth@numbertext.org>
-rw-r--r--officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu11
-rw-r--r--sw/inc/cmdid.h1
-rw-r--r--sw/inc/fesh.hxx6
-rw-r--r--sw/inc/view.hxx1
-rw-r--r--sw/sdi/_basesh.sdi7
-rw-r--r--sw/sdi/swriter.sdi18
-rw-r--r--sw/source/core/frmedt/fecopy.cxx4
-rw-r--r--sw/source/uibase/dochdl/swdtflvr.cxx32
-rw-r--r--sw/source/uibase/inc/swdtflvr.hxx8
-rw-r--r--sw/source/uibase/shells/basesh.cxx17
-rw-r--r--sw/source/uibase/uiview/view.cxx16
-rw-r--r--sw/uiconfig/swriter/menubar/menubar.xml1
-rw-r--r--sw/uiconfig/swriter/popupmenu/table.xml1
13 files changed, 107 insertions, 16 deletions
diff --git a/officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu b/officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu
index ce664af0e1bd..ac60dc4e32ca 100644
--- a/officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu
+++ b/officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu
@@ -1523,6 +1523,17 @@
<value>1</value>
</prop>
</node>
+ <node oor:name=".uno:PasteNestedTable" oor:op="replace">
+ <prop oor:name="Label" oor:type="xs:string">
+ <value xml:lang="en-US">Paste as Nested Table</value>
+ </prop>
+ <prop oor:name="PopupLabel" oor:type="xs:string">
+ <value xml:lang="en-US">As Nested Table</value>
+ </prop>
+ <prop oor:name="Properties" oor:type="xs:int">
+ <value>1</value>
+ </prop>
+ </node>
<node oor:name=".uno:DeleteRows" oor:op="replace">
<prop oor:name="Label" oor:type="xs:string">
<value xml:lang="en-US">Delete Rows</value>
diff --git a/sw/inc/cmdid.h b/sw/inc/cmdid.h
index 6b49d5a91e51..6aba5e4d72d4 100644
--- a/sw/inc/cmdid.h
+++ b/sw/inc/cmdid.h
@@ -343,6 +343,7 @@
#define FN_TABLE_SELECT_ALL (FN_FORMAT + 115) /* */
#define FN_TABLE_INSERT_COL_AFTER (FN_FORMAT + 116) /* */
#define FN_TABLE_SET_READ_ONLY_CELLS (FN_FORMAT + 117) /* protect table cells */
+#define FN_PASTE_NESTED_TABLE (FN_FORMAT + 118) /* instead of the cell-by-cell copy between source and target tables */
#define FN_TABLE_UNSET_READ_ONLY_CELLS (FN_FORMAT + 119) /* undo table cell protection */
#define FN_TABLE_HEADLINE_REPEAT (FN_FORMAT + 120) /* also used in SwXTextTable*/
#define FN_TABLE_ADJUST_CELLS (FN_FORMAT + 121) /* */
diff --git a/sw/inc/fesh.hxx b/sw/inc/fesh.hxx
index f60f92cff44e..b928420ea824 100644
--- a/sw/inc/fesh.hxx
+++ b/sw/inc/fesh.hxx
@@ -252,7 +252,7 @@ public:
/// Copy and Paste methods for internal clipboard.
void Copy( SwDoc* pClpDoc, const OUString* pNewClpText = nullptr );
- bool Paste( SwDoc* pClpDoc );
+ bool Paste( SwDoc* pClpDoc, bool bNestedTable = false );
/// Paste some pages into another doc - used in mailmerge.
void PastePages( SwFEShell& rToFill, sal_uInt16 nStartPage, sal_uInt16 nEndPage);
@@ -643,6 +643,10 @@ public:
SwTable::SearchType m_eTableInsertMode;
SwTable::SearchType GetTableInsertMode() const { return m_eTableInsertMode; }
void SetTableInsertMode( SwTable::SearchType eFlag ) { m_eTableInsertMode = eFlag; }
+ /// table copied to the clipboard by the last private copy
+ bool bTableCopied;
+ bool GetTableCopied() { return bTableCopied; }
+ void SetTableCopied( bool bCopied ) { bTableCopied = bCopied; }
bool DeleteTableSel(); ///< Current selection, may be whole table.
diff --git a/sw/inc/view.hxx b/sw/inc/view.hxx
index 13f73dc09123..1ce11c33bda6 100644
--- a/sw/inc/view.hxx
+++ b/sw/inc/view.hxx
@@ -589,6 +589,7 @@ public:
// Status changes now notified from the clipboard.
bool IsPasteAllowed();
bool IsPasteSpecialAllowed();
+ bool IsPasteSpreadsheet(bool bHasOwnTableCopied);
// Enable mail merge - mail merge field dialog enabled
void EnableMailMerge();
diff --git a/sw/sdi/_basesh.sdi b/sw/sdi/_basesh.sdi
index 472198cdc922..886ae2863a9f 100644
--- a/sw/sdi/_basesh.sdi
+++ b/sw/sdi/_basesh.sdi
@@ -115,6 +115,13 @@ interface BaseTextSelection
DisableFlags="SfxDisableFlags::SwOnProtectedCursor";
]
+ FN_PASTE_NESTED_TABLE // status(final|play)
+ [
+ ExecMethod = ExecClpbrd ;
+ StateMethod = StateClpbrd ;
+ DisableFlags="SfxDisableFlags::SwOnProtectedCursor";
+ ]
+
FN_REPAGINATE // status(final|play)
[
ExecMethod = Execute ;
diff --git a/sw/sdi/swriter.sdi b/sw/sdi/swriter.sdi
index 78dfda33e744..321804cda1bf 100644
--- a/sw/sdi/swriter.sdi
+++ b/sw/sdi/swriter.sdi
@@ -2681,6 +2681,24 @@ SfxVoidItem InsertColumnsAfter FN_TABLE_INSERT_COL_AFTER
GroupId = SfxGroupId::Table;
]
+SfxVoidItem PasteNestedTable FN_PASTE_NESTED_TABLE
+()
+[
+ AutoUpdate = FALSE,
+ FastCall = TRUE,
+ ReadOnlyDoc = FALSE,
+ Toggle = FALSE,
+ Container = FALSE,
+ RecordAbsolute = FALSE,
+ RecordPerSet;
+ Asynchron;
+
+ AccelConfig = FALSE,
+ MenuConfig = TRUE,
+ ToolBoxConfig = TRUE,
+ GroupId = SfxGroupId::Edit;
+]
+
SfxUInt16Item InsertSection FN_INSERT_REGION
(SfxUInt16Item Columns SID_ATTR_COLUMNS,SfxStringItem RegionName FN_PARAM_REGION_NAME,SfxStringItem RegionCondition FN_PARAM_REGION_CONDITION,SfxBoolItem RegionHidden FN_PARAM_REGION_HIDDEN,SfxBoolItem RegionProtect FN_PARAM_REGION_PROTECT,SfxStringItem LinkName FN_PARAM_1,SfxStringItem FilterName FN_PARAM_2,SfxStringItem SubRegion FN_PARAM_3)
[
diff --git a/sw/source/core/frmedt/fecopy.cxx b/sw/source/core/frmedt/fecopy.cxx
index 8dadded1e2a6..ed91aa86b851 100644
--- a/sw/source/core/frmedt/fecopy.cxx
+++ b/sw/source/core/frmedt/fecopy.cxx
@@ -672,7 +672,7 @@ namespace {
}
}
-bool SwFEShell::Paste( SwDoc* pClpDoc )
+bool SwFEShell::Paste( SwDoc* pClpDoc, bool bNestedTable )
{
SET_CURR_SHELL( this );
OSL_ENSURE( pClpDoc, "no clipboard document" );
@@ -818,6 +818,8 @@ bool SwFEShell::Paste( SwDoc* pClpDoc )
SwTableNode *const pDestNd(GetDoc()->IsIdxInTable(rPaM.GetPoint()->nNode));
if (pSrcNd && nullptr != pDestNd &&
+ // not a forced nested table insertion
+ !bNestedTable &&
// are we at the beginning of the cell? (if not, we will insert a nested table)
// first paragraph of the cell?
rPaM.GetNode().GetIndex() == rPaM.GetNode().FindTableBoxStartNode()->GetIndex()+1 &&
diff --git a/sw/source/uibase/dochdl/swdtflvr.cxx b/sw/source/uibase/dochdl/swdtflvr.cxx
index bb140e9742af..72ef1889f9f6 100644
--- a/sw/source/uibase/dochdl/swdtflvr.cxx
+++ b/sw/source/uibase/dochdl/swdtflvr.cxx
@@ -893,6 +893,9 @@ int SwTransferable::PrepareForCopy( bool bIsCut )
if ( m_pWrtShell->GetTableInsertMode() != SwTable::SEARCH_NONE )
m_pWrtShell->SetTableInsertMode( SwTable::SEARCH_NONE );
+ if ( m_pWrtShell->GetTableCopied() )
+ m_pWrtShell->SetTableCopied( false );
+
OUString sGrfNm;
const SelectionType nSelection = m_pWrtShell->GetSelectionType();
if( nSelection == SelectionType::Graphic )
@@ -1025,6 +1028,8 @@ int SwTransferable::PrepareForCopy( bool bIsCut )
m_eBufferType = TransferBufferType::Table | m_eBufferType;
bDDELink = m_pWrtShell->HasWholeTabSelection();
+ m_pWrtShell->SetTableCopied(true);
+
if ( bIsCut && (SelectionType::TableRow | SelectionType::TableCol) & nSelection )
m_pWrtShell->SetTableInsertMode( (SelectionType::TableRow & nSelection) ? SwTable::SEARCH_ROW : SwTable::SEARCH_COL );
}
@@ -1360,7 +1365,7 @@ bool SwTransferable::IsPaste( const SwWrtShell& rSh,
return bIsPaste;
}
-bool SwTransferable::Paste(SwWrtShell& rSh, TransferableDataHelper& rData, RndStdIds nAnchorType, bool bIgnoreComments)
+bool SwTransferable::Paste(SwWrtShell& rSh, TransferableDataHelper& rData, RndStdIds nAnchorType, bool bIgnoreComments, bool bNestedTable)
{
SwPasteContext aPasteContext(rSh);
@@ -1432,14 +1437,17 @@ bool SwTransferable::Paste(SwWrtShell& rSh, TransferableDataHelper& rData, RndSt
nLevel++;
} while (rSh.GetDoc()->IsIdxInTable(rSh.GetCursor()->GetNode()) != nullptr);
if ( SwTransferable::PasteData( rData, rSh, EXCHG_OUT_ACTION_INSERT_STRING, nActionFlags, SotClipboardFormatId::HTML,
- nDestination, false, false, nullptr, 0, false, nAnchorType, bIgnoreComments, &aPasteContext ))
+ nDestination, false, false, nullptr, 0, false, nAnchorType, bIgnoreComments, &aPasteContext, bNestedTable ))
{
pDispatch->Execute(FN_CHAR_LEFT, SfxCallMode::SYNCHRON);
pDispatch->Execute(FN_TABLE_SELECT_ALL, SfxCallMode::SYNCHRON);
pDispatch->Execute(SID_COPY, SfxCallMode::SYNCHRON);
for(sal_uInt32 a = 0; a < 1 + (nLevel * 2); a++)
pDispatch->Execute(SID_UNDO, SfxCallMode::SYNCHRON);
- pDispatch->Execute(SID_PASTE, SfxCallMode::SYNCHRON);
+ if (bNestedTable)
+ pDispatch->Execute(FN_PASTE_NESTED_TABLE, SfxCallMode::SYNCHRON);
+ else
+ pDispatch->Execute(SID_PASTE, SfxCallMode::SYNCHRON);
return true;
} else {
for(sal_uInt32 a = 0; a < (nLevel * 2); a++)
@@ -1502,7 +1510,7 @@ bool SwTransferable::Paste(SwWrtShell& rSh, TransferableDataHelper& rData, RndSt
// paste rows
bool bResult = SwTransferable::PasteData( rData, rSh, nAction, nActionFlags, nFormat,
- nDestination, false, false, nullptr, 0, false, nAnchorType, bIgnoreComments, &aPasteContext );
+ nDestination, false, false, nullptr, 0, false, nAnchorType, bIgnoreComments, &aPasteContext, bNestedTable );
// restore cursor position
if (pMark != nullptr)
@@ -1534,7 +1542,7 @@ bool SwTransferable::Paste(SwWrtShell& rSh, TransferableDataHelper& rData, RndSt
return EXCHG_INOUT_ACTION_NONE != nAction &&
SwTransferable::PasteData( rData, rSh, nAction, nActionFlags, nFormat,
- nDestination, false, false, nullptr, 0, false, nAnchorType, bIgnoreComments, &aPasteContext );
+ nDestination, false, false, nullptr, 0, false, nAnchorType, bIgnoreComments, &aPasteContext, bNestedTable );
}
bool SwTransferable::PasteData( TransferableDataHelper& rData,
@@ -1545,7 +1553,8 @@ bool SwTransferable::PasteData( TransferableDataHelper& rData,
const Point* pPt, sal_Int8 nDropAction,
bool bPasteSelection, RndStdIds nAnchorType,
bool bIgnoreComments,
- SwPasteContext* pContext )
+ SwPasteContext* pContext,
+ bool bNestedTable )
{
SwWait aWait( *rSh.GetView().GetDocShell(), false );
std::unique_ptr<SwTrnsfrActionAndUndo, o3tl::default_delete<SwTrnsfrActionAndUndo>> pAction;
@@ -1651,7 +1660,7 @@ bool SwTransferable::PasteData( TransferableDataHelper& rData,
EXCHG_OUT_ACTION_INSERT_PRIVATE == nAction )
{
// then internal paste
- bRet = pTunneledTrans->PrivatePaste(rSh, pContext);
+ bRet = pTunneledTrans->PrivatePaste(rSh, pContext, bNestedTable);
}
else if( EXCHG_INOUT_ACTION_NONE != nAction )
{
@@ -3197,6 +3206,11 @@ bool SwTransferable::IsPasteSpecial( const SwWrtShell& rWrtShell,
return aClipboardFormatItem.Count() > 0;
}
+bool SwTransferable::IsPasteOwnFormat( const TransferableDataHelper& rData )
+{
+ return ( GetSwTransferable( rData ) != nullptr );
+}
+
bool SwTransferable::PasteFormat( SwWrtShell& rSh,
TransferableDataHelper& rData,
SotClipboardFormatId nFormat )
@@ -3621,7 +3635,7 @@ bool lcl_checkClassification(SwDoc* pSourceDoc, SwDoc* pDestinationDoc)
}
-bool SwTransferable::PrivatePaste(SwWrtShell& rShell, SwPasteContext* pContext)
+bool SwTransferable::PrivatePaste(SwWrtShell& rShell, SwPasteContext* pContext, bool bNestedTable)
{
// first, ask for the SelectionType, then action-bracketing !!!!
// (otherwise it's not pasted into a TableSelection!!!)
@@ -3683,7 +3697,7 @@ bool SwTransferable::PrivatePaste(SwWrtShell& rShell, SwPasteContext* pContext)
bool bRet = true;
// 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());
+ bRet = rShell.Paste(m_pClpDocFac->GetDoc(), bNestedTable);
if( bKillPaMs )
rShell.KillPams();
diff --git a/sw/source/uibase/inc/swdtflvr.hxx b/sw/source/uibase/inc/swdtflvr.hxx
index 680e808767b8..c63b1987afc4 100644
--- a/sw/source/uibase/inc/swdtflvr.hxx
+++ b/sw/source/uibase/inc/swdtflvr.hxx
@@ -138,7 +138,7 @@ class SW_DLLPUBLIC SwTransferable : public TransferableHelper
bool PrivateDrop( SwWrtShell& rSh, const Point& rDragPt, bool bMove,
bool bIsXSelection );
- bool PrivatePaste( SwWrtShell& rShell, SwPasteContext* pContext = nullptr );
+ bool PrivatePaste( SwWrtShell& rShell, SwPasteContext* pContext = nullptr, bool bNestedTable = false );
void SetDataForDragAndDrop( const Point& rSttPos );
@@ -180,7 +180,7 @@ public:
// paste - methods and helper methods for the paste
static bool IsPaste( const SwWrtShell&, const TransferableDataHelper& );
- static bool Paste( SwWrtShell&, TransferableDataHelper&, RndStdIds nAnchorType = RndStdIds::FLY_AT_PARA, bool bIgnoreComments = false );
+ static bool Paste( SwWrtShell&, TransferableDataHelper&, RndStdIds nAnchorType = RndStdIds::FLY_AT_PARA, bool bIgnoreComments = false, bool bTableInCell = false );
static bool PasteData( TransferableDataHelper& rData,
SwWrtShell& rSh, sal_uInt8 nAction, SotExchangeActionFlags nActionFlags,
SotClipboardFormatId nFormat,
@@ -189,10 +189,12 @@ public:
const Point* pDDPos = nullptr, sal_Int8 nDropAction = 0,
bool bPasteSelection = false, RndStdIds nAnchorType = RndStdIds::FLY_AT_PARA,
bool bIgnoreComments = false,
- SwPasteContext* pContext = nullptr );
+ SwPasteContext* pContext = nullptr,
+ bool bNestedTable = false );
static bool IsPasteSpecial( const SwWrtShell& rWrtShell,
const TransferableDataHelper& );
+ static bool IsPasteOwnFormat( const TransferableDataHelper& );
static bool PasteUnformatted( SwWrtShell& rSh, TransferableDataHelper& );
/**
* @brief PrePasteSpecial Prepares the given dialog without actually running it
diff --git a/sw/source/uibase/shells/basesh.cxx b/sw/source/uibase/shells/basesh.cxx
index ff9598c84b37..c9e5a8ec15bf 100644
--- a/sw/source/uibase/shells/basesh.cxx
+++ b/sw/source/uibase/shells/basesh.cxx
@@ -258,6 +258,7 @@ void SwBaseShell::ExecClpbrd(SfxRequest &rReq)
SwWrtShell &rSh = GetShell();
sal_uInt16 nId = rReq.GetSlot();
bool bIgnore = false;
+ bool bPasteNestedTable = false;
switch( nId )
{
case SID_CUT:
@@ -280,6 +281,9 @@ void SwBaseShell::ExecClpbrd(SfxRequest &rReq)
}
return;
+ case FN_PASTE_NESTED_TABLE:
+ bPasteNestedTable = true;
+ [[fallthrough]];
case SID_PASTE:
{
TransferableDataHelper aDataHelper(
@@ -299,7 +303,7 @@ void SwBaseShell::ExecClpbrd(SfxRequest &rReq)
const SfxBoolItem* pIgnoreComments = rReq.GetArg<SfxBoolItem>(FN_PARAM_2);
if (pIgnoreComments)
bIgnoreComments = pIgnoreComments->GetValue();
- SwTransferable::Paste(rSh, aDataHelper, nAnchorType, bIgnoreComments);
+ SwTransferable::Paste(rSh, aDataHelper, nAnchorType, bIgnoreComments, bPasteNestedTable);
if( rSh.IsFrameSelected() || rSh.IsObjSelected() )
rSh.EnterSelFrameMode();
@@ -466,6 +470,17 @@ void SwBaseShell::StateClpbrd(SfxItemSet &rSet)
rSet.DisableItem( nWhich );
break;
+ case FN_PASTE_NESTED_TABLE:
+ if( !rSh.IsCursorInTable()
+ || !GetView().IsPasteSpecialAllowed()
+ || rSh.CursorInsideInputField()
+ // disable if not a native Writer table and not a spreadsheet format
+ || !GetView().IsPasteSpreadsheet(rSh.GetTableCopied()) )
+ {
+ rSet.DisableItem( nWhich );
+ }
+ break;
+
case SID_PASTE:
if( !GetView().IsPasteAllowed() )
{
diff --git a/sw/source/uibase/uiview/view.cxx b/sw/source/uibase/uiview/view.cxx
index 58c7d77349b3..25d394f1f364 100644
--- a/sw/source/uibase/uiview/view.cxx
+++ b/sw/source/uibase/uiview/view.cxx
@@ -594,7 +594,7 @@ void SwView::CheckReadonlyState()
SID_DELETE, FN_BACKSPACE, FN_SHIFT_BACKSPACE,
SID_UNDO,
SID_REDO, SID_REPEAT, SID_PASTE,
- SID_PASTE_UNFORMATTED,
+ SID_PASTE_UNFORMATTED, FN_PASTE_NESTED_TABLE,
SID_PASTE_SPECIAL, SID_SBA_BRW_INSERT,
SID_BACKGROUND_COLOR, FN_INSERT_BOOKMARK, SID_CHARMAP_CONTROL,
SID_CHARMAP, SID_EMOJI_CONTROL, FN_INSERT_SOFT_HYPHEN,
@@ -1848,6 +1848,20 @@ bool SwView::IsPasteSpecialAllowed()
return m_bPasteSpecialState;
}
+bool SwView::IsPasteSpreadsheet(bool bHasOwnTableCopied)
+{
+ TransferableDataHelper aDataHelper(
+ TransferableDataHelper::CreateFromSystemClipboard(
+ &GetEditWin()) );
+ if( aDataHelper.GetXTransferable().is() )
+ {
+ if (bHasOwnTableCopied && SwTransferable::IsPasteOwnFormat( aDataHelper ))
+ return true;
+ return aDataHelper.HasFormat( SotClipboardFormatId::SYLK ) || aDataHelper.HasFormat( SotClipboardFormatId::SYLK_BIGCAPS );
+ }
+ return false;
+}
+
void SwView::NotifyDBChanged()
{
GetViewImpl()->GetUNOObject_Impl()->NotifyDBChanged();
diff --git a/sw/uiconfig/swriter/menubar/menubar.xml b/sw/uiconfig/swriter/menubar/menubar.xml
index bd57b91564da..77e1ebae5f57 100644
--- a/sw/uiconfig/swriter/menubar/menubar.xml
+++ b/sw/uiconfig/swriter/menubar/menubar.xml
@@ -105,6 +105,7 @@
<menu:menupopup>
<menu:menuitem menu:id=".uno:PasteUnformatted"/>
<menu:menuitem menu:id=".uno:PasteSpecial"/>
+ <menu:menuitem menu:id=".uno:PasteNestedTable"/>
</menu:menupopup>
</menu:menu>
<menu:menuseparator/>
diff --git a/sw/uiconfig/swriter/popupmenu/table.xml b/sw/uiconfig/swriter/popupmenu/table.xml
index 09470cab6d34..4baf20af019d 100644
--- a/sw/uiconfig/swriter/popupmenu/table.xml
+++ b/sw/uiconfig/swriter/popupmenu/table.xml
@@ -13,6 +13,7 @@
<menu:menuitem menu:id=".uno:Paste"/>
<menu:menu menu:id=".uno:PasteSpecialMenu">
<menu:menupopup>
+ <menu:menuitem menu:id=".uno:PasteNestedTable"/>
<menu:menuitem menu:id=".uno:PasteUnformatted"/>
<menu:menuitem menu:id=".uno:PasteSpecial"/>
</menu:menupopup>