sc/qa/unit/tiledrendering2/data/multi-selection.ods |binary
 sc/qa/unit/tiledrendering2/tiledrendering2.cxx      |   45 ++++++++++++++++++++
 sc/source/ui/view/viewfun3.cxx                      |    8 +++
 3 files changed, 53 insertions(+)

New commits:
commit 4ffe06a81866a2c9f8598d194e04c114cc083119
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Fri Apr 19 08:51:34 2024 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Fri Apr 19 17:14:37 2024 +0200

    cool#8789 sc lok: fix copy for multi-selections
    
    Select A1+A3 in Calc, copy, try to paste in B1, nothing happens.
    
    This is because lok::Document::getSelectionTypeAndText() for a Calc
    document ends up in ScViewFunc::CopyToTransferable(), which only handles
    the SC_MARK_SIMPLE* cases.
    
    Fix the problem by implementing support for SC_MARK_MULTI, similar to
    what ScCellShell::ExecuteEdit() does in the SID_COPY case, which also
    calls CopyToClip().
    
    Keep the test highlevel as the Calc shell doesn't seem to have an easy
    function to do the same as the Ctrl-click on a cell without duplicating
    lots of code in the testcase.
    
    Change-Id: I641d9db95ca391a4f39d96aeeb33422129262288
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166279
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Tested-by: Jenkins

diff --git a/sc/qa/unit/tiledrendering2/data/multi-selection.ods 
b/sc/qa/unit/tiledrendering2/data/multi-selection.ods
new file mode 100644
index 000000000000..9436aaf93c26
Binary files /dev/null and 
b/sc/qa/unit/tiledrendering2/data/multi-selection.ods differ
diff --git a/sc/qa/unit/tiledrendering2/tiledrendering2.cxx 
b/sc/qa/unit/tiledrendering2/tiledrendering2.cxx
index 058e7deb0883..65a85c685b33 100644
--- a/sc/qa/unit/tiledrendering2/tiledrendering2.cxx
+++ b/sc/qa/unit/tiledrendering2/tiledrendering2.cxx
@@ -17,6 +17,8 @@
 #include <sfx2/lokhelper.hxx>
 #include <test/lokcallback.hxx>
 #include <vcl/scheduler.hxx>
+#include <comphelper/propertyvalue.hxx>
+#include <comphelper/string.hxx>
 
 #include <docuno.hxx>
 
@@ -79,6 +81,7 @@ class ViewCallback final
 
 public:
     std::map<std::string, boost::property_tree::ptree> m_aStateChanges;
+    tools::Rectangle m_aCellCursorBounds;
     TestLokCallbackWrapper m_callbackWrapper;
 
     ViewCallback()
@@ -108,6 +111,20 @@ public:
     {
         switch (nType)
         {
+            case LOK_CALLBACK_CELL_CURSOR:
+            {
+                uno::Sequence<OUString> aSeq = 
comphelper::string::convertCommaSeparated(
+                    OUString::createFromAscii(pPayload));
+                m_aCellCursorBounds = tools::Rectangle();
+                if (aSeq.getLength() >= 4)
+                {
+                    m_aCellCursorBounds.SetLeft(aSeq[0].toInt32());
+                    m_aCellCursorBounds.SetTop(aSeq[1].toInt32());
+                    m_aCellCursorBounds.setWidth(aSeq[2].toInt32());
+                    m_aCellCursorBounds.setHeight(aSeq[3].toInt32());
+                }
+            }
+            break;
             case LOK_CALLBACK_STATE_CHANGED:
             {
                 std::stringstream aStream(pPayload);
@@ -159,6 +176,34 @@ CPPUNIT_TEST_FIXTURE(Test, testSidebarLocale)
     std::string aLocale = it->second.get<std::string>("locale");
     CPPUNIT_ASSERT_EQUAL(std::string("de-DE"), aLocale);
 }
+
+CPPUNIT_TEST_FIXTURE(Test, testCopyMultiSelection)
+{
+    // Given a document with A1 and A3 as selected cells:
+    ScModelObj* pModelObj = createDoc("multi-selection.ods");
+    ViewCallback aView1;
+    // Get the center of A3:
+    uno::Sequence<beans::PropertyValue> aPropertyValues = {
+        comphelper::makePropertyValue("ToPoint", OUString("$A$3")),
+    };
+    dispatchCommand(mxComponent, ".uno:GoToCell", aPropertyValues);
+    Point aPoint = aView1.m_aCellCursorBounds.Center();
+    // Go to A1:
+    aPropertyValues = {
+        comphelper::makePropertyValue("ToPoint", OUString("$A$1")),
+    };
+    dispatchCommand(mxComponent, ".uno:GoToCell", aPropertyValues);
+    // Ctrl-click on A3:
+    int nCtrl = KEY_MOD1;
+    pModelObj->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONDOWN, aPoint.getX(), 
aPoint.getY(), 1,
+                              MOUSE_LEFT, nCtrl);
+
+    // When getting the selection:
+    uno::Reference<datatransfer::XTransferable> xTransferable = 
pModelObj->getSelection();
+
+    // Make sure we get A1+A3 instead of an error:
+    CPPUNIT_ASSERT(xTransferable.is());
+}
 }
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sc/source/ui/view/viewfun3.cxx b/sc/source/ui/view/viewfun3.cxx
index ee2cccf72f35..1c918ff1c04d 100644
--- a/sc/source/ui/view/viewfun3.cxx
+++ b/sc/source/ui/view/viewfun3.cxx
@@ -458,6 +458,14 @@ rtl::Reference<ScTransferObj> 
ScViewFunc::CopyToTransferable()
             return new ScTransferObj( std::move(pClipDoc), std::move(aObjDesc) 
);
         }
     }
+    else if (eMarkType == SC_MARK_MULTI)
+    {
+        ScDocumentUniquePtr pClipDoc(new ScDocument(SCDOCMODE_CLIP));
+        // This takes care of the input line and calls CopyToClipMultiRange() 
for us.
+        CopyToClip(pClipDoc.get(), /*bCut=*/false, /*bApi=*/true);
+        TransferableObjectDescriptor aObjDesc;
+        return new ScTransferObj(std::move(pClipDoc), std::move(aObjDesc));
+    }
 
     return nullptr;
 }

Reply via email to