sc drawstyles: Clipboard support
- Paste as Calc's own format (default in Calc, results with an
OLE object elsewhere), should preserve style assignment. This
can be in one of two ways: Either copy the shape itself, or a
cell range that includes a shape.
- Similarly, copying or moving a whole sheet to another document
should also preserve the style.
- Paste as drawing format (default in other apps, also default
in Calc when copying shapes from other apps), should preserve
the formatting as direct formatting. Pasting into Calc will
also assign the default style to that shape.
Change-Id: Icb951dad1a77ba9ced706c33c928980d1ec7f8ac
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/149753
Tested-by: Jenkins
Reviewed-by: Maxim Monastirsky <momonasmon@gmail.com>
diff --git a/sc/inc/stlpool.hxx b/sc/inc/stlpool.hxx
index 51694a4..131b82c 100644
--- a/sc/inc/stlpool.hxx
+++ b/sc/inc/stlpool.hxx
@@ -45,8 +45,10 @@ public:
void CreateStandardStyles();
void CopyStdStylesFrom( ScStyleSheetPool* pSrcPool );
void CopyStyleFrom( ScStyleSheetPool* pSrcPool,
const OUString& rName, SfxStyleFamily eFamily );
void CopyUsedGraphicStylesFrom( SfxStyleSheetBasePool* pSrcPool );
void CopyStyleFrom( SfxStyleSheetBasePool* pSrcPool,
const OUString& rName, SfxStyleFamily eFamily,
bool bNewStyleHierarchy = false );
bool HasStandardStyles() const { return bHasStandardStyles; }
diff --git a/sc/source/core/data/documen9.cxx b/sc/source/core/data/documen9.cxx
index 34c25c7..f63c1ee 100644
--- a/sc/source/core/data/documen9.cxx
+++ b/sc/source/core/data/documen9.cxx
@@ -45,6 +45,7 @@
#include <rechead.hxx>
#include <poolhelp.hxx>
#include <docpool.hxx>
#include <stlpool.hxx>
#include <editutil.hxx>
#include <charthelper.hxx>
#include <conditio.hxx>
@@ -76,6 +77,12 @@ void ScDocument::TransferDrawPage(const ScDocument& rSrcDoc, SCTAB nSrcPos, SCTA
SdrObject* pOldObject = aIter.Next();
while (pOldObject)
{
// Copy style sheet
auto pStyleSheet = pOldObject->GetStyleSheet();
if (pStyleSheet)
GetStyleSheetPool()->CopyStyleFrom(rSrcDoc.GetStyleSheetPool(),
pStyleSheet->GetName(), pStyleSheet->GetFamily(), true);
// Clone to target SdrModel
rtl::Reference<SdrObject> pNewObject(pOldObject->CloneSdrObject(*mpDrawLayer));
pNewObject->NbcMove(Size(0,0));
diff --git a/sc/source/core/data/drwlayer.cxx b/sc/source/core/data/drwlayer.cxx
index 263c569..a316205 100644
--- a/sc/source/core/data/drwlayer.cxx
+++ b/sc/source/core/data/drwlayer.cxx
@@ -385,8 +385,11 @@ SdrModel* ScDrawLayer::AllocModel() const
{
// Allocated model (for clipboard etc) must not have a pointer
// to the original model's document, pass NULL as document:
auto pNewModel = std::make_unique<ScDrawLayer>(nullptr, aName);
auto pNewPool = static_cast<ScStyleSheetPool*>(pNewModel->GetStyleSheetPool());
pNewPool->CopyUsedGraphicStylesFrom(GetStyleSheetPool());
return new ScDrawLayer( nullptr, aName );
return pNewModel.release();
}
bool ScDrawLayer::ScAddPage( SCTAB nTab )
@@ -1930,6 +1933,12 @@ void ScDrawLayer::CopyFromClip( ScDrawLayer* pClipModel, SCTAB nSourceTab, const
if (bObjectInArea && (pOldObject->GetLayer() != SC_LAYER_INTERN)
&& !IsNoteCaption(pOldObject))
{
// Copy style sheet
auto pStyleSheet = pOldObject->GetStyleSheet();
if (pStyleSheet && !bSameDoc)
pDoc->GetStyleSheetPool()->CopyStyleFrom(pClipDoc->GetStyleSheetPool(),
pStyleSheet->GetName(), pStyleSheet->GetFamily(), true);
// Clone to target SdrModel
rtl::Reference<SdrObject> pNewObject(pOldObject->CloneSdrObject(*this));
diff --git a/sc/source/core/data/stlpool.cxx b/sc/source/core/data/stlpool.cxx
index e7f6d26..6a45048 100644
--- a/sc/source/core/data/stlpool.cxx
+++ b/sc/source/core/data/stlpool.cxx
@@ -125,8 +125,9 @@ void ScStyleSheetPool::Remove( SfxStyleSheetBase* pStyle )
}
}
void ScStyleSheetPool::CopyStyleFrom( ScStyleSheetPool* pSrcPool,
const OUString& rName, SfxStyleFamily eFamily )
void ScStyleSheetPool::CopyStyleFrom( SfxStyleSheetBasePool* pSrcPool,
const OUString& rName, SfxStyleFamily eFamily,
bool bNewStyleHierarchy )
{
// this is the Dest-Pool
@@ -136,8 +137,10 @@ void ScStyleSheetPool::CopyStyleFrom( ScStyleSheetPool* pSrcPool,
const SfxItemSet& rSourceSet = pStyleSheet->GetItemSet();
SfxStyleSheetBase* pDestSheet = Find( rName, eFamily );
if (pDestSheet && bNewStyleHierarchy)
return;
if (!pDestSheet)
pDestSheet = &Make( rName, eFamily );
pDestSheet = &Make( rName, eFamily, pStyleSheet->GetMask() );
SfxItemSet& rDestSet = pDestSheet->GetItemSet();
rDestSet.PutExtended( rSourceSet, SfxItemState::DONTCARE, SfxItemState::DEFAULT );
@@ -176,6 +179,38 @@ void ScStyleSheetPool::CopyStyleFrom( ScStyleSheetPool* pSrcPool,
}
}
}
const OUString aParentName = pStyleSheet->GetParent();
if (!bNewStyleHierarchy || aParentName.isEmpty())
return;
CopyStyleFrom(pSrcPool, aParentName, eFamily, bNewStyleHierarchy);
pDestSheet->SetParent(aParentName);
}
void ScStyleSheetPool::CopyUsedGraphicStylesFrom(SfxStyleSheetBasePool* pSrcPool)
{
// this is the Dest-Pool
std::vector<std::pair<SfxStyleSheetBase*, OUString>> aNewStyles;
auto pSrcSheet = pSrcPool->First(SfxStyleFamily::Frame);
while (pSrcSheet)
{
if (pSrcSheet->IsUsed() && !Find(pSrcSheet->GetName(), pSrcSheet->GetFamily()))
{
auto pDestSheet = &Make(pSrcSheet->GetName(), pSrcSheet->GetFamily(), pSrcSheet->GetMask());
aNewStyles.emplace_back(pDestSheet, pSrcSheet->GetParent());
SfxItemSet& rDestSet = pDestSheet->GetItemSet();
rDestSet.Put(pSrcSheet->GetItemSet());
}
pSrcSheet = pSrcPool->Next();
}
for (const auto& style : aNewStyles)
style.first->SetParent(style.second);
}
// Standard templates
@@ -185,6 +220,7 @@ void ScStyleSheetPool::CopyStdStylesFrom( ScStyleSheetPool* pSrcPool )
// Copy Default styles
CopyStyleFrom( pSrcPool, ScResId(STR_STYLENAME_STANDARD), SfxStyleFamily::Para );
CopyStyleFrom( pSrcPool, ScResId(STR_STYLENAME_STANDARD), SfxStyleFamily::Frame );
CopyStyleFrom( pSrcPool, ScResId(STR_STYLENAME_STANDARD), SfxStyleFamily::Page );
CopyStyleFrom( pSrcPool, ScResId(STR_STYLENAME_REPORT), SfxStyleFamily::Page );
}
diff --git a/sc/source/ui/app/drwtrans.cxx b/sc/source/ui/app/drwtrans.cxx
index 569fd6e..8dae3e5 100644
--- a/sc/source/ui/app/drwtrans.cxx
+++ b/sc/source/ui/app/drwtrans.cxx
@@ -54,6 +54,9 @@
#include <viewdata.hxx>
#include <scmod.hxx>
#include <dragdata.hxx>
#include <stlpool.hxx>
#include <scresid.hxx>
#include <globstr.hrc>
#include <editeng/eeitem.hxx>
@@ -358,7 +361,11 @@ bool ScDrawTransferObj::GetData( const css::datatransfer::DataFlavor& rFlavor, c
}
else if ( nFormat == SotClipboardFormatId::DRAWING )
{
bOK = SetObject( m_pModel.get(), SCDRAWTRANS_TYPE_DRAWMODEL, rFlavor );
SdrView aView(*m_pModel);
SdrPageView* pPv = aView.ShowSdrPage(aView.GetModel().GetPage(0));
aView.MarkAllObj( pPv );
auto pNewModel = aView.CreateMarkedObjModel();
bOK = SetObject( pNewModel.get(), SCDRAWTRANS_TYPE_DRAWMODEL, rFlavor );
}
else if ( nFormat == SotClipboardFormatId::BITMAP
|| nFormat == SotClipboardFormatId::PNG
@@ -429,19 +436,20 @@ bool ScDrawTransferObj::WriteObject( tools::SvRef<SotTempStream>& rxOStm, void*
case SCDRAWTRANS_TYPE_DRAWMODEL:
{
SdrModel* pDrawModel = static_cast<SdrModel*>(pUserObject);
pDrawModel->BurnInStyleSheetAttributes();
rxOStm->SetBufferSize( 0xff00 );
// for the changed pool defaults from drawing layer pool set those
// attributes as hard attributes to preserve them for saving
const SfxItemPool& rItemPool = m_pModel->GetItemPool();
const SfxItemPool& rItemPool = pDrawModel->GetItemPool();
const SvxFontHeightItem& rDefaultFontHeight = rItemPool.GetDefaultItem(EE_CHAR_FONTHEIGHT);
// SW should have no MasterPages
OSL_ENSURE(0 == m_pModel->GetMasterPageCount(), "SW with MasterPages (!)");
OSL_ENSURE(0 == pDrawModel->GetMasterPageCount(), "SW with MasterPages (!)");
for(sal_uInt16 a(0); a < m_pModel->GetPageCount(); a++)
for(sal_uInt16 a(0); a < pDrawModel->GetPageCount(); a++)
{
const SdrPage* pPage(m_pModel->GetPage(a));
const SdrPage* pPage(pDrawModel->GetPage(a));
SdrObjListIter aIter(pPage, SdrIterMode::DeepNoGroups);
while(aIter.IsMore())
@@ -677,6 +685,10 @@ void ScDrawTransferObj::InitDocShell()
ScDocument& rDestDoc = pDocSh->GetDocument();
rDestDoc.InitDrawLayer( pDocSh );
auto pPool = rDestDoc.GetStyleSheetPool();
pPool->CopyStyleFrom(m_pModel->GetStyleSheetPool(), ScResId(STR_STYLENAME_STANDARD), SfxStyleFamily::Frame);
pPool->CopyUsedGraphicStylesFrom(m_pModel->GetStyleSheetPool());
SdrModel* pDestModel = rDestDoc.GetDrawLayer();
// #i71538# use complete SdrViews
// SdrExchangeView aDestView( pDestModel );
diff --git a/sc/source/ui/app/transobj.cxx b/sc/source/ui/app/transobj.cxx
index d0fbd02..138b078 100644
--- a/sc/source/ui/app/transobj.cxx
+++ b/sc/source/ui/app/transobj.cxx
@@ -677,6 +677,9 @@ void ScTransferObj::InitDocShell(bool bLimitToPageSize)
m_pDoc->GetName( m_aBlock.aStart.Tab(), aTabName );
rDestDoc.RenameTab( 0, aTabName );
if (m_pDoc->GetDrawLayer() || m_pDoc->HasNotes())
pDocSh->MakeDrawLayer();
rDestDoc.CopyStdStylesFrom(*m_pDoc);
SCCOL nStartX = m_aBlock.aStart.Col();
@@ -716,9 +719,6 @@ void ScTransferObj::InitDocShell(bool bLimitToPageSize)
}
}
if (m_pDoc->GetDrawLayer() || m_pDoc->HasNotes())
pDocSh->MakeDrawLayer();
// cell range is copied to the original position, but on the first sheet
// -> bCutMode must be set
// pDoc is always a Clipboard-document
diff --git a/sc/source/ui/view/viewfun5.cxx b/sc/source/ui/view/viewfun5.cxx
index d1a6e59..f57eca0 100644
--- a/sc/source/ui/view/viewfun5.cxx
+++ b/sc/source/ui/view/viewfun5.cxx
@@ -565,18 +565,15 @@ bool ScViewFunc::PasteDataFormat( SotClipboardFormatId nFormatId,
MakeDrawLayer(); // before loading model, so 3D factory has been created
ScDocShellRef aDragShellRef( new ScDocShell );
aDragShellRef->MakeDrawLayer();
aDragShellRef->DoInitNew();
std::unique_ptr<FmFormModel> pModel(
new FmFormModel(
nullptr,
aDragShellRef.get()));
ScDrawLayer* pModel = aDragShellRef->GetDocument().GetDrawLayer();
pModel->GetItemPool().FreezeIdRanges();
xStm->Seek(0);
css::uno::Reference< css::io::XInputStream > xInputStream( new utl::OInputStreamWrapper( *xStm ) );
SvxDrawingLayerImport( pModel.get(), xInputStream );
SvxDrawingLayerImport( pModel, xInputStream );
// set everything to right layer:
size_t nObjCount = 0;
@@ -598,8 +595,7 @@ bool ScViewFunc::PasteDataFormat( SotClipboardFormatId nFormatId,
nObjCount += pPage->GetObjCount(); // count group object only once
}
PasteDraw(aPos, pModel.get(), (nObjCount > 1), u"A", u"B"); // grouped if more than 1 object
pModel.reset();
PasteDraw(aPos, pModel, (nObjCount > 1), u"A", u"B"); // grouped if more than 1 object
aDragShellRef->DoClose();
bRet = true;
}
diff --git a/sc/source/ui/view/viewfun7.cxx b/sc/source/ui/view/viewfun7.cxx
index 76ede14..f704256 100644
--- a/sc/source/ui/view/viewfun7.cxx
+++ b/sc/source/ui/view/viewfun7.cxx
@@ -47,6 +47,7 @@
#include <docsh.hxx>
#include <dragdata.hxx>
#include <gridwin.hxx>
#include <stlpool.hxx>
bool bPasteIsMove = false;
@@ -213,10 +214,15 @@ void ScViewFunc::PasteDraw( const Point& rLogicPos, SdrModel* pModel,
ScChartHelper::GetChartNames( aExcludedChartNames, pPage );
}
// #89247# Set flag for ScDocument::UpdateChartListeners() which is
// called during paste.
if ( !bSameDocClipboard )
{
auto pPool = static_cast<ScStyleSheetPool*>(pScDrawView->GetModel().GetStyleSheetPool());
pPool->CopyUsedGraphicStylesFrom(pModel->GetStyleSheetPool());
// #89247# Set flag for ScDocument::UpdateChartListeners() which is
// called during paste.
GetViewData().GetDocument().SetPastingDrawFromOtherDoc( true );
}
pScDrawView->Paste(*pModel, aPos, nullptr, nOptions);
diff --git a/svx/source/sdr/properties/attributeproperties.cxx b/svx/source/sdr/properties/attributeproperties.cxx
index 7f141b8..d4a0017 100644
--- a/svx/source/sdr/properties/attributeproperties.cxx
+++ b/svx/source/sdr/properties/attributeproperties.cxx
@@ -195,7 +195,7 @@ namespace sdr::properties
pTargetStyleSheet = dynamic_cast< SfxStyleSheet* >(
pTargetStyleSheetPool->Find(
rProps.GetStyleSheet()->GetName(),
SfxStyleFamily::All));
rProps.GetStyleSheet()->GetFamily()));
}
}
}