sc/inc/clipcontext.hxx              |    5 ++++-
 sc/source/core/data/clipcontext.cxx |    4 ++--
 sc/source/core/data/column.cxx      |    6 ++++--
 sc/source/core/data/document.cxx    |   14 ++++++++++----
 sc/source/core/data/drwlayer.cxx    |   29 +++++++++++++++++++++++++++++
 5 files changed, 49 insertions(+), 9 deletions(-)

New commits:
commit 709866a3b8e073fab4937dcf91dcd33ff1d2bc13
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Sun Mar 3 02:04:24 2024 +0600
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Sun Mar 3 01:05:32 2024 +0100

    tdf#99969: make sure to copy the chart source ranges to clipboard
    
    ... even when they are outside of the copied cell range. Otherwise,
    it is  impossible to transfer the missing data when switching to
    own data on paste.
    
    The copy of the missing ranges avoids copying cell attributes, for
    performance reasons, but also to avoid overwriting the attributes
    of already copied cells. Otherwise, ScDrawLayer::CopyToClip would
    need the bKeepScenarioFlags, or the CopyToClipContext used in the
    caller ScDocument::CopyToClip, for consistent copy; or a method to
    avoid overwriting already copied cells (this change simply copies
    all chart ranges, withiut checking if they were copied already).
    
    Change-Id: Id02e0c20517e7e8a17bb0a31d1b230196cda1a58
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164294
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/sc/inc/clipcontext.hxx b/sc/inc/clipcontext.hxx
index a6c989a004f7..8c3bc1730af1 100644
--- a/sc/inc/clipcontext.hxx
+++ b/sc/inc/clipcontext.hxx
@@ -161,12 +161,15 @@ public:
 class CopyToClipContext final : public ClipContextBase
 {
     bool mbKeepScenarioFlags:1;
+    bool mbCopyChartRanges : 1 = false; // Copying ranges not included in 
selection:
+                                        // only copy data, not cell attributes
 
 public:
-    CopyToClipContext(ScDocument& rDoc, bool bKeepScenarioFlags);
+    CopyToClipContext(ScDocument& rDoc, bool bKeepScenarioFlags, bool 
bCopyChartRanges = false);
     virtual ~CopyToClipContext() override;
 
     bool isKeepScenarioFlags() const;
+    bool isCopyChartRanges() const { return mbCopyChartRanges; }
 };
 
 class CopyToDocContext final : public ClipContextBase
diff --git a/sc/source/core/data/clipcontext.cxx 
b/sc/source/core/data/clipcontext.cxx
index 4e6b925070d6..fc6f136d0372 100644
--- a/sc/source/core/data/clipcontext.cxx
+++ b/sc/source/core/data/clipcontext.cxx
@@ -403,8 +403,8 @@ bool CopyFromClipContext::isDateCell( const ScColumn& rCol, 
SCROW nRow ) const
 }
 
 CopyToClipContext::CopyToClipContext(
-    ScDocument& rDoc, bool bKeepScenarioFlags) :
-    ClipContextBase(rDoc), mbKeepScenarioFlags(bKeepScenarioFlags) {}
+    ScDocument& rDoc, bool bKeepScenarioFlags, bool bCopyChartRanges) :
+    ClipContextBase(rDoc), mbKeepScenarioFlags(bKeepScenarioFlags), 
mbCopyChartRanges(bCopyChartRanges) {}
 
 CopyToClipContext::~CopyToClipContext() {}
 
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index 22d8cec28bc3..34524e444dc3 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -879,14 +879,16 @@ public:
 void ScColumn::CopyToClip(
     sc::CopyToClipContext& rCxt, SCROW nRow1, SCROW nRow2, ScColumn& rColumn ) 
const
 {
-    pAttrArray->CopyArea( nRow1, nRow2, 0, *rColumn.pAttrArray,
-                          rCxt.isKeepScenarioFlags() ? (ScMF::All & 
~ScMF::Scenario) : ScMF::All );
+    if (!rCxt.isCopyChartRanges()) // No need to copy attributes for chart 
ranges
+        pAttrArray->CopyArea( nRow1, nRow2, 0, *rColumn.pAttrArray,
+                              rCxt.isKeepScenarioFlags() ? (ScMF::All & 
~ScMF::Scenario) : ScMF::All );
 
     {
         CopyToClipHandler aFunc(GetDoc(), *this, rColumn, 
rCxt.getBlockPosition(rColumn.nTab, rColumn.nCol));
         sc::ParseBlock(maCells.begin(), maCells, aFunc, nRow1, nRow2);
     }
 
+    if (!rCxt.isCopyChartRanges()) // No need to copy attributes for chart 
ranges
     {
         CopyTextAttrToClipHandler aFunc(rColumn.maCellTextAttrs);
         sc::ParseBlock(maCellTextAttrs.begin(), maCellTextAttrs, aFunc, nRow1, 
nRow2);
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index 7ad5a3e2ae89..c5f3f50e0f30 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -2223,6 +2223,7 @@ void ScDocument::CopyToClip(const ScClipParam& rClipParam,
     sc::CopyToClipContext aCxt(*pClipDoc, bKeepScenarioFlags);
     CopyRangeNamesToClip(pClipDoc, aClipRange, pMarks);
 
+    // 1. Copy selected cells
     for (SCTAB i = 0; i < nEndTab; ++i)
     {
         if (!maTabs[i] || i >= pClipDoc->GetTableCount() || 
!pClipDoc->maTabs[i])
@@ -2232,12 +2233,17 @@ void ScDocument::CopyToClip(const ScClipParam& 
rClipParam,
             continue;
 
         maTabs[i]->CopyToClip(aCxt, rClipParam.maRanges, 
pClipDoc->maTabs[i].get());
+    }
 
-        if (mpDrawLayer && bIncludeObjects)
+    // 2. Copy drawing objects in the selection. Do in after the first "copy 
cells" pass, because
+    // the embedded objects (charts) coud reference cells from tabs not (yet) 
copied; doing it now
+    // allows to know what is already copied, to not owerwrite attributes of 
already copied data.
+    if (mpDrawLayer && bIncludeObjects)
+    {
+        for (SCTAB i = 0; i < nEndTab; ++i)
         {
-            //  also copy drawing objects
-            tools::Rectangle aObjRect = GetMMRect(
-                aClipRange.aStart.Col(), aClipRange.aStart.Row(), 
aClipRange.aEnd.Col(), aClipRange.aEnd.Row(), i);
+            tools::Rectangle aObjRect = GetMMRect(aClipRange.aStart.Col(), 
aClipRange.aStart.Row(),
+                                                  aClipRange.aEnd.Col(), 
aClipRange.aEnd.Row(), i);
             mpDrawLayer->CopyToClip(pClipDoc, i, aObjRect);
         }
     }
diff --git a/sc/source/core/data/drwlayer.cxx b/sc/source/core/data/drwlayer.cxx
index e404d6afbdc3..b9b22791969e 100644
--- a/sc/source/core/data/drwlayer.cxx
+++ b/sc/source/core/data/drwlayer.cxx
@@ -88,6 +88,7 @@
 #include <docpool.hxx>
 #include <detfunc.hxx>
 #include <basegfx/matrix/b2dhommatrix.hxx>
+#include <clipcontext.hxx>
 #include <clipparam.hxx>
 
 #include <memory>
@@ -1834,6 +1835,34 @@ void ScDrawLayer::CopyToClip( ScDocument* pClipDoc, 
SCTAB nTab, const tools::Rec
 
             pDestPage->InsertObject(pNewObject.get());
 
+            // Store the chart's source data to the clipboad document, even 
when it's out of the
+            // copied range. It will be ignored when pasted to the same 
document; when pasted to
+            // another document, ScDocument::mpClipParam will provide the 
actually copied ranges,
+            // and the data copied here will be used to break connection and 
switch to own data
+            // in ScDrawLayer::CopyFromClip.
+            if (xOldChart && !xOldChart->hasInternalDataProvider())
+            {
+                sc::CopyToClipContext aCxt(*pClipDoc, false, true);
+                OUString aChartName = 
static_cast<SdrOle2Obj*>(pOldObject)->GetPersistName();
+                std::vector<ScRangeList> aRangesVector;
+                pDoc->GetChartRanges(aChartName, aRangesVector, *pDoc);
+                for (const ScRangeList& ranges : aRangesVector)
+                {
+                    for (const ScRange& r : ranges)
+                    {
+                        for (SCTAB i = r.aStart.Tab(); i <= r.aEnd.Tab(); ++i)
+                        {
+                            ScTable* pTab = pDoc->FetchTable(i);
+                            ScTable* pClipTab = pClipDoc->FetchTable(i);
+                            if (!pTab || !pClipTab)
+                                continue;
+                            pTab->CopyToClip(aCxt, r.aStart.Col(), 
r.aStart.Row(), r.aEnd.Col(),
+                                             r.aEnd.Row(), pClipTab);
+                        }
+                    }
+                }
+            }
+
             //  no undo needed in clipboard document
             //  charts are not updated
         }

Reply via email to