officecfg/registry/data/org/openoffice/Office/UI/CalcCommands.xcu |   16 
 sc/Library_sc.mk                                                  |    2 
 sc/inc/globstr.hrc                                                |    2 
 sc/inc/sc.hrc                                                     |    8 
 sc/qa/unit/SparklineTest.cxx                                      |  239 
++++++++++
 sc/sdi/cellsh.sdi                                                 |    2 
 sc/sdi/scalc.sdi                                                  |   34 +
 sc/source/ui/docshell/docfunc.cxx                                 |   20 
 sc/source/ui/inc/docfunc.hxx                                      |    3 
 sc/source/ui/inc/undo/UndoGroupSparklines.hxx                     |   55 ++
 sc/source/ui/inc/undo/UndoUngroupSparklines.hxx                   |   53 ++
 sc/source/ui/undo/UndoGroupSparklines.cxx                         |   91 +++
 sc/source/ui/undo/UndoUngroupSparklines.cxx                       |   89 +++
 sc/source/ui/view/cellsh.cxx                                      |    6 
 sc/source/ui/view/cellsh1.cxx                                     |   29 +
 sc/source/ui/view/viewfun2.cxx                                    |    2 
 sc/uiconfig/scalc/popupmenu/cell.xml                              |    2 
 17 files changed, 649 insertions(+), 4 deletions(-)

New commits:
commit c6fecc628a60a3955c022f04020cdb515cc4fb6e
Author:     Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk>
AuthorDate: Sun Apr 3 09:02:38 2022 +0900
Commit:     Tomaž Vajngerl <qui...@gmail.com>
CommitDate: Wed Apr 6 02:59:02 2022 +0200

    sc: add Group and Ungroup to context menu for sparklines
    
    This change allows to group parklines together into a sparkline
    group, or ungroup them, so they use their own sparkline group.
    This also adds the undo and redo for this actions.
    
    Change-Id: I61b604203afaf2fe8c2d47b80082739ded15d6fb
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132545
    Tested-by: Tomaž Vajngerl <qui...@gmail.com>
    Reviewed-by: Tomaž Vajngerl <qui...@gmail.com>

diff --git a/officecfg/registry/data/org/openoffice/Office/UI/CalcCommands.xcu 
b/officecfg/registry/data/org/openoffice/Office/UI/CalcCommands.xcu
index 70f6b83ef8ed..2bd6210666e3 100644
--- a/officecfg/registry/data/org/openoffice/Office/UI/CalcCommands.xcu
+++ b/officecfg/registry/data/org/openoffice/Office/UI/CalcCommands.xcu
@@ -1106,6 +1106,22 @@
           <value>1</value>
         </prop>
       </node>
+      <node oor:name=".uno:GroupSparklines" oor:op="replace">
+        <prop oor:name="Label" oor:type="xs:string">
+          <value xml:lang="en-US">Group Sparklines</value>
+        </prop>
+        <prop oor:name="Properties" oor:type="xs:int">
+          <value>1</value>
+        </prop>
+      </node>
+      <node oor:name=".uno:UngroupSparklines" oor:op="replace">
+        <prop oor:name="Label" oor:type="xs:string">
+          <value xml:lang="en-US">Ungroup Sparklines</value>
+        </prop>
+        <prop oor:name="Properties" oor:type="xs:int">
+          <value>1</value>
+        </prop>
+      </node>
       <node oor:name=".uno:EditSparklineGroup" oor:op="replace">
         <prop oor:name="Label" oor:type="xs:string">
           <value xml:lang="en-US">Edit Sparkline Group...</value>
diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk
index 9eb23e39240e..743125bfef10 100644
--- a/sc/Library_sc.mk
+++ b/sc/Library_sc.mk
@@ -558,6 +558,8 @@ $(eval $(call gb_Library_add_exception_objects,sc,\
     sc/source/ui/undo/UndoEditSparklineGroup \
     sc/source/ui/undo/UndoDeleteSparkline \
     sc/source/ui/undo/UndoDeleteSparklineGroup \
+    sc/source/ui/undo/UndoUngroupSparklines \
+    sc/source/ui/undo/UndoGroupSparklines \
     sc/source/ui/unoobj/ChartRangeSelectionListener \
     sc/source/ui/unoobj/addruno \
     sc/source/ui/unoobj/afmtuno \
diff --git a/sc/inc/globstr.hrc b/sc/inc/globstr.hrc
index 6c9318179380..96d2dca307a5 100644
--- a/sc/inc/globstr.hrc
+++ b/sc/inc/globstr.hrc
@@ -543,6 +543,8 @@
 #define STR_UNDO_DELETE_SPARKLINE               
NC_("STR_UNDO_DELETE_SPARKLINE", "Delete Sparkline")
 #define STR_UNDO_DELETE_SPARKLINE_GROUP         
NC_("STR_UNDO_DELETE_SPARKLINE_GROUP", "Delete Sparkline Group")
 #define STR_UNDO_EDIT_SPARKLINE_GROUP           
NC_("STR_UNDO_EDIT_SPARKLINE_GROUP", "Edit Sparkline Group")
+#define STR_UNDO_GROUP_SPARKLINES               
NC_("STR_UNDO_GROUP_SPARKLINES", "Group Sparklines")
+#define STR_UNDO_UNGROUP_SPARKLINES             
NC_("STR_UNDO_UNGROUP_SPARKLINES", "Ungroup Sparklines")
 
 #endif
 
diff --git a/sc/inc/sc.hrc b/sc/inc/sc.hrc
index 3aecfc5cdb31..207dc4224e53 100644
--- a/sc/inc/sc.hrc
+++ b/sc/inc/sc.hrc
@@ -310,9 +310,11 @@ class SvxZoomSliderItem;
 #define FID_DEFINE_CURRENT_NAME (INSERT_MENU_START + 24)
 #define SID_INSERT_SPARKLINE    (INSERT_MENU_START + 25)
 #define SID_DELETE_SPARKLINE    (INSERT_MENU_START + 26)
-#define SID_EDIT_SPARKLINE_GROUP      (INSERT_MENU_START + 27)
-#define SID_DELETE_SPARKLINE_GROUP    (INSERT_MENU_START + 28)
-#define INSERT_MENU_END         (INSERT_MENU_START + 29)
+#define SID_EDIT_SPARKLINE_GROUP     (INSERT_MENU_START + 27)
+#define SID_DELETE_SPARKLINE_GROUP   (INSERT_MENU_START + 28)
+#define SID_GROUP_SPARKLINES    (INSERT_MENU_START + 29)
+#define SID_UNGROUP_SPARKLINES  (INSERT_MENU_START + 30)
+#define INSERT_MENU_END         (INSERT_MENU_START + 31)
 
 #define FORMAT_MENU_START       (INSERT_MENU_END)
 #define FID_CELL_FORMAT         (FORMAT_MENU_START)
diff --git a/sc/qa/unit/SparklineTest.cxx b/sc/qa/unit/SparklineTest.cxx
index aea9d45152e0..99efd55f8209 100644
--- a/sc/qa/unit/SparklineTest.cxx
+++ b/sc/qa/unit/SparklineTest.cxx
@@ -56,6 +56,8 @@ public:
     void testUndoRedoDeleteSparklineGroup();
     void testUndoRedoClearContentForSparkline();
     void testUndoRedoEditSparklineGroup();
+    void testUndoRedoUngroupSparklines();
+    void testUndoRedoGroupSparklines();
     void testSparklineList();
 
     CPPUNIT_TEST_SUITE(SparklineTest);
@@ -68,6 +70,8 @@ public:
     CPPUNIT_TEST(testUndoRedoDeleteSparklineGroup);
     CPPUNIT_TEST(testUndoRedoClearContentForSparkline);
     CPPUNIT_TEST(testUndoRedoEditSparklineGroup);
+    CPPUNIT_TEST(testUndoRedoUngroupSparklines);
+    CPPUNIT_TEST(testUndoRedoGroupSparklines);
     CPPUNIT_TEST(testSparklineList);
     CPPUNIT_TEST_SUITE_END();
 };
@@ -566,6 +570,241 @@ void SparklineTest::testUndoRedoEditSparklineGroup()
     xDocSh->DoClose();
 }
 
+void SparklineTest::testUndoRedoUngroupSparklines()
+{
+    ScDocShellRef xDocSh = loadEmptyDocument();
+    CPPUNIT_ASSERT(xDocSh);
+
+    ScDocument& rDocument = xDocSh->GetDocument();
+    ScTabViewShell* pViewShell = xDocSh->GetBestViewShell(false);
+    CPPUNIT_ASSERT(pViewShell);
+
+    auto& rDocFunc = xDocSh->GetDocFunc();
+
+    // insert test data - A1:A6
+    insertTestData(rDocument);
+
+    // Sparkline range
+    ScRange aDataRange(0, 0, 0, 3, 5, 0); //A1:D6
+    ScRange aRange(0, 6, 0, 3, 6, 0); // A7:D7
+
+    auto pSparklineGroup = std::make_shared<sc::SparklineGroup>();
+    CPPUNIT_ASSERT(rDocFunc.InsertSparklines(aDataRange, aRange, 
pSparklineGroup));
+
+    // Check Sparklines
+    {
+        CPPUNIT_ASSERT_EQUAL(true, rDocument.HasSparkline(ScAddress(0, 6, 
0))); // A7
+        CPPUNIT_ASSERT_EQUAL(true, rDocument.HasSparkline(ScAddress(1, 6, 0)));
+        CPPUNIT_ASSERT_EQUAL(true, rDocument.HasSparkline(ScAddress(2, 6, 0)));
+        CPPUNIT_ASSERT_EQUAL(true, rDocument.HasSparkline(ScAddress(3, 6, 
0))); // D7
+
+        auto pGroup1 = rDocument.GetSparkline(ScAddress(0, 6, 
0))->getSparklineGroup();
+        auto pGroup2 = rDocument.GetSparkline(ScAddress(1, 6, 
0))->getSparklineGroup();
+        auto pGroup3 = rDocument.GetSparkline(ScAddress(2, 6, 
0))->getSparklineGroup();
+        auto pGroup4 = rDocument.GetSparkline(ScAddress(3, 6, 
0))->getSparklineGroup();
+
+        CPPUNIT_ASSERT_EQUAL(pGroup1, pGroup2);
+        CPPUNIT_ASSERT_EQUAL(pGroup1, pGroup3);
+        CPPUNIT_ASSERT_EQUAL(pGroup1, pGroup4);
+        CPPUNIT_ASSERT_EQUAL(pGroup3, pGroup4);
+    }
+
+    CPPUNIT_ASSERT(rDocFunc.UngroupSparklines(ScRange(2, 6, 0, 3, 6, 0)));
+
+    // Check Sparklines
+    {
+        CPPUNIT_ASSERT_EQUAL(true, rDocument.HasSparkline(ScAddress(0, 6, 
0))); // A7
+        CPPUNIT_ASSERT_EQUAL(true, rDocument.HasSparkline(ScAddress(1, 6, 0)));
+        CPPUNIT_ASSERT_EQUAL(true, rDocument.HasSparkline(ScAddress(2, 6, 0)));
+        CPPUNIT_ASSERT_EQUAL(true, rDocument.HasSparkline(ScAddress(3, 6, 
0))); // D7
+
+        auto pGroup1 = rDocument.GetSparkline(ScAddress(0, 6, 
0))->getSparklineGroup();
+        auto pGroup2 = rDocument.GetSparkline(ScAddress(1, 6, 
0))->getSparklineGroup();
+        auto pGroup3 = rDocument.GetSparkline(ScAddress(2, 6, 
0))->getSparklineGroup();
+        auto pGroup4 = rDocument.GetSparkline(ScAddress(3, 6, 
0))->getSparklineGroup();
+
+        CPPUNIT_ASSERT_EQUAL(pGroup1, pGroup2);
+        CPPUNIT_ASSERT(pGroup1 != pGroup3);
+        CPPUNIT_ASSERT(pGroup1 != pGroup4);
+        CPPUNIT_ASSERT(pGroup3 != pGroup4);
+    }
+
+    // Undo
+    rDocument.GetUndoManager()->Undo();
+
+    // Check Sparklines
+    {
+        CPPUNIT_ASSERT_EQUAL(true, rDocument.HasSparkline(ScAddress(0, 6, 
0))); // A7
+        CPPUNIT_ASSERT_EQUAL(true, rDocument.HasSparkline(ScAddress(1, 6, 0)));
+        CPPUNIT_ASSERT_EQUAL(true, rDocument.HasSparkline(ScAddress(2, 6, 0)));
+        CPPUNIT_ASSERT_EQUAL(true, rDocument.HasSparkline(ScAddress(3, 6, 
0))); // D7
+
+        auto pGroup1 = rDocument.GetSparkline(ScAddress(0, 6, 
0))->getSparklineGroup();
+        auto pGroup2 = rDocument.GetSparkline(ScAddress(1, 6, 
0))->getSparklineGroup();
+        auto pGroup3 = rDocument.GetSparkline(ScAddress(2, 6, 
0))->getSparklineGroup();
+        auto pGroup4 = rDocument.GetSparkline(ScAddress(3, 6, 
0))->getSparklineGroup();
+
+        CPPUNIT_ASSERT_EQUAL(pGroup1, pGroup2);
+        CPPUNIT_ASSERT_EQUAL(pGroup1, pGroup3);
+        CPPUNIT_ASSERT_EQUAL(pGroup1, pGroup4);
+        CPPUNIT_ASSERT_EQUAL(pGroup3, pGroup4);
+    }
+
+    // Redo
+    rDocument.GetUndoManager()->Redo();
+
+    // Check Sparklines
+    {
+        CPPUNIT_ASSERT_EQUAL(true, rDocument.HasSparkline(ScAddress(0, 6, 
0))); // A7
+        CPPUNIT_ASSERT_EQUAL(true, rDocument.HasSparkline(ScAddress(1, 6, 0)));
+        CPPUNIT_ASSERT_EQUAL(true, rDocument.HasSparkline(ScAddress(2, 6, 0)));
+        CPPUNIT_ASSERT_EQUAL(true, rDocument.HasSparkline(ScAddress(3, 6, 
0))); // D7
+
+        auto pGroup1 = rDocument.GetSparkline(ScAddress(0, 6, 
0))->getSparklineGroup();
+        auto pGroup2 = rDocument.GetSparkline(ScAddress(1, 6, 
0))->getSparklineGroup();
+        auto pGroup3 = rDocument.GetSparkline(ScAddress(2, 6, 
0))->getSparklineGroup();
+        auto pGroup4 = rDocument.GetSparkline(ScAddress(3, 6, 
0))->getSparklineGroup();
+
+        CPPUNIT_ASSERT_EQUAL(pGroup1, pGroup2);
+        CPPUNIT_ASSERT(pGroup1 != pGroup3);
+        CPPUNIT_ASSERT(pGroup1 != pGroup4);
+        CPPUNIT_ASSERT(pGroup3 != pGroup4);
+    }
+
+    xDocSh->DoClose();
+}
+
+void SparklineTest::testUndoRedoGroupSparklines()
+{
+    ScDocShellRef xDocSh = loadEmptyDocument();
+    CPPUNIT_ASSERT(xDocSh);
+
+    ScDocument& rDocument = xDocSh->GetDocument();
+    ScTabViewShell* pViewShell = xDocSh->GetBestViewShell(false);
+    CPPUNIT_ASSERT(pViewShell);
+
+    auto& rDocFunc = xDocSh->GetDocFunc();
+
+    // insert test data - A1:A6
+    insertTestData(rDocument);
+
+    // Sparkline range
+    ScRange aDataRange(0, 0, 0, 3, 5, 0); //A1:D6
+    ScRange aRange(0, 6, 0, 3, 6, 0); // A7:D7
+
+    auto pSparklineGroup = std::make_shared<sc::SparklineGroup>();
+    CPPUNIT_ASSERT(rDocFunc.InsertSparklines(aDataRange, aRange, 
pSparklineGroup));
+
+    // Check Sparklines
+    {
+        CPPUNIT_ASSERT_EQUAL(true, rDocument.HasSparkline(ScAddress(0, 6, 
0))); // A7
+        CPPUNIT_ASSERT_EQUAL(true, rDocument.HasSparkline(ScAddress(1, 6, 0)));
+        CPPUNIT_ASSERT_EQUAL(true, rDocument.HasSparkline(ScAddress(2, 6, 0)));
+        CPPUNIT_ASSERT_EQUAL(true, rDocument.HasSparkline(ScAddress(3, 6, 
0))); // D7
+
+        auto pGroup1 = rDocument.GetSparkline(ScAddress(0, 6, 
0))->getSparklineGroup();
+        auto pGroup2 = rDocument.GetSparkline(ScAddress(1, 6, 
0))->getSparklineGroup();
+        auto pGroup3 = rDocument.GetSparkline(ScAddress(2, 6, 
0))->getSparklineGroup();
+        auto pGroup4 = rDocument.GetSparkline(ScAddress(3, 6, 
0))->getSparklineGroup();
+
+        CPPUNIT_ASSERT_EQUAL(pGroup1, pGroup2);
+        CPPUNIT_ASSERT_EQUAL(pGroup1, pGroup3);
+        CPPUNIT_ASSERT_EQUAL(pGroup1, pGroup4);
+        CPPUNIT_ASSERT_EQUAL(pGroup3, pGroup4);
+    }
+
+    CPPUNIT_ASSERT(rDocFunc.UngroupSparklines(ScRange(2, 6, 0, 3, 6, 0)));
+
+    // Check Sparklines
+    {
+        CPPUNIT_ASSERT_EQUAL(true, rDocument.HasSparkline(ScAddress(0, 6, 
0))); // A7
+        CPPUNIT_ASSERT_EQUAL(true, rDocument.HasSparkline(ScAddress(1, 6, 0)));
+        CPPUNIT_ASSERT_EQUAL(true, rDocument.HasSparkline(ScAddress(2, 6, 0)));
+        CPPUNIT_ASSERT_EQUAL(true, rDocument.HasSparkline(ScAddress(3, 6, 
0))); // D7
+
+        auto pGroup1 = rDocument.GetSparkline(ScAddress(0, 6, 
0))->getSparklineGroup();
+        auto pGroup2 = rDocument.GetSparkline(ScAddress(1, 6, 
0))->getSparklineGroup();
+        auto pGroup3 = rDocument.GetSparkline(ScAddress(2, 6, 
0))->getSparklineGroup();
+        auto pGroup4 = rDocument.GetSparkline(ScAddress(3, 6, 
0))->getSparklineGroup();
+
+        CPPUNIT_ASSERT_EQUAL(pGroup1, pGroup2);
+        CPPUNIT_ASSERT(pGroup1 != pGroup3);
+        CPPUNIT_ASSERT(pGroup1 != pGroup4);
+        CPPUNIT_ASSERT(pGroup3 != pGroup4);
+    }
+
+    {
+        auto pGroup = rDocument.GetSparkline(ScAddress(3, 6, 
0))->getSparklineGroup();
+        CPPUNIT_ASSERT(rDocFunc.GroupSparklines(ScRange(1, 6, 0, 3, 6, 0), 
pGroup));
+    }
+
+    // Check Sparklines
+    {
+        CPPUNIT_ASSERT_EQUAL(true, rDocument.HasSparkline(ScAddress(0, 6, 
0))); // A7
+        CPPUNIT_ASSERT_EQUAL(true, rDocument.HasSparkline(ScAddress(1, 6, 0)));
+        CPPUNIT_ASSERT_EQUAL(true, rDocument.HasSparkline(ScAddress(2, 6, 0)));
+        CPPUNIT_ASSERT_EQUAL(true, rDocument.HasSparkline(ScAddress(3, 6, 
0))); // D7
+
+        auto pGroup1 = rDocument.GetSparkline(ScAddress(0, 6, 
0))->getSparklineGroup();
+        auto pGroup2 = rDocument.GetSparkline(ScAddress(1, 6, 
0))->getSparklineGroup();
+        auto pGroup3 = rDocument.GetSparkline(ScAddress(2, 6, 
0))->getSparklineGroup();
+        auto pGroup4 = rDocument.GetSparkline(ScAddress(3, 6, 
0))->getSparklineGroup();
+
+        CPPUNIT_ASSERT(pGroup1 != pGroup2);
+        CPPUNIT_ASSERT(pGroup1 != pGroup3);
+        CPPUNIT_ASSERT(pGroup1 != pGroup4);
+        CPPUNIT_ASSERT_EQUAL(pGroup2, pGroup3);
+        CPPUNIT_ASSERT_EQUAL(pGroup2, pGroup4);
+        CPPUNIT_ASSERT_EQUAL(pGroup3, pGroup4);
+    }
+
+    // Undo
+    rDocument.GetUndoManager()->Undo();
+
+    // Check Sparklines
+    {
+        CPPUNIT_ASSERT_EQUAL(true, rDocument.HasSparkline(ScAddress(0, 6, 
0))); // A7
+        CPPUNIT_ASSERT_EQUAL(true, rDocument.HasSparkline(ScAddress(1, 6, 0)));
+        CPPUNIT_ASSERT_EQUAL(true, rDocument.HasSparkline(ScAddress(2, 6, 0)));
+        CPPUNIT_ASSERT_EQUAL(true, rDocument.HasSparkline(ScAddress(3, 6, 
0))); // D7
+
+        auto pGroup1 = rDocument.GetSparkline(ScAddress(0, 6, 
0))->getSparklineGroup();
+        auto pGroup2 = rDocument.GetSparkline(ScAddress(1, 6, 
0))->getSparklineGroup();
+        auto pGroup3 = rDocument.GetSparkline(ScAddress(2, 6, 
0))->getSparklineGroup();
+        auto pGroup4 = rDocument.GetSparkline(ScAddress(3, 6, 
0))->getSparklineGroup();
+
+        CPPUNIT_ASSERT_EQUAL(pGroup1, pGroup2);
+        CPPUNIT_ASSERT(pGroup1 != pGroup3);
+        CPPUNIT_ASSERT(pGroup1 != pGroup4);
+        CPPUNIT_ASSERT(pGroup3 != pGroup4);
+    }
+
+    // Redo
+    rDocument.GetUndoManager()->Redo();
+
+    // Check Sparklines
+    {
+        CPPUNIT_ASSERT_EQUAL(true, rDocument.HasSparkline(ScAddress(0, 6, 
0))); // A7
+        CPPUNIT_ASSERT_EQUAL(true, rDocument.HasSparkline(ScAddress(1, 6, 0)));
+        CPPUNIT_ASSERT_EQUAL(true, rDocument.HasSparkline(ScAddress(2, 6, 0)));
+        CPPUNIT_ASSERT_EQUAL(true, rDocument.HasSparkline(ScAddress(3, 6, 
0))); // D7
+
+        auto pGroup1 = rDocument.GetSparkline(ScAddress(0, 6, 
0))->getSparklineGroup();
+        auto pGroup2 = rDocument.GetSparkline(ScAddress(1, 6, 
0))->getSparklineGroup();
+        auto pGroup3 = rDocument.GetSparkline(ScAddress(2, 6, 
0))->getSparklineGroup();
+        auto pGroup4 = rDocument.GetSparkline(ScAddress(3, 6, 
0))->getSparklineGroup();
+
+        CPPUNIT_ASSERT(pGroup1 != pGroup2);
+        CPPUNIT_ASSERT(pGroup1 != pGroup3);
+        CPPUNIT_ASSERT(pGroup1 != pGroup4);
+        CPPUNIT_ASSERT_EQUAL(pGroup2, pGroup3);
+        CPPUNIT_ASSERT_EQUAL(pGroup2, pGroup4);
+        CPPUNIT_ASSERT_EQUAL(pGroup3, pGroup4);
+    }
+
+    xDocSh->DoClose();
+}
+
 void SparklineTest::testSparklineList()
 {
     ScDocShellRef xDocSh = loadEmptyDocument();
diff --git a/sc/sdi/cellsh.sdi b/sc/sdi/cellsh.sdi
index 2adf15b60f8f..8fb939d9bf74 100644
--- a/sc/sdi/cellsh.sdi
+++ b/sc/sdi/cellsh.sdi
@@ -239,6 +239,8 @@ interface CellSelection
     SID_DELETE_SPARKLINE                [ ExecMethod = ExecuteEdit; 
StateMethod = GetBlockState; ]
     SID_EDIT_SPARKLINE_GROUP            [ ExecMethod = ExecuteEdit; 
StateMethod = GetBlockState; ]
     SID_DELETE_SPARKLINE_GROUP          [ ExecMethod = ExecuteEdit; 
StateMethod = GetBlockState; ]
+    SID_GROUP_SPARKLINES                [ ExecMethod = ExecuteEdit; 
StateMethod = GetBlockState; ]
+    SID_UNGROUP_SPARKLINES              [ ExecMethod = ExecuteEdit; 
StateMethod = GetBlockState; ]
 
     SID_THESAURUS   [ ExecMethod = ExecuteEdit; StateMethod = GetCellState; ]
     SID_SPELL_DIALOG [ ExecMethod = ExecuteEdit; StateMethod = GetState; ]
diff --git a/sc/sdi/scalc.sdi b/sc/sdi/scalc.sdi
index c33ffa1cb7d8..ef823941d37a 100644
--- a/sc/sdi/scalc.sdi
+++ b/sc/sdi/scalc.sdi
@@ -2355,6 +2355,40 @@ SfxVoidItem DeleteSparklineGroup 
SID_DELETE_SPARKLINE_GROUP
     GroupId = SfxGroupId::Edit;
 ]
 
+SfxVoidItem GroupSparklines SID_GROUP_SPARKLINES
+()
+[
+    AutoUpdate = FALSE,
+    FastCall = FALSE,
+    ReadOnlyDoc = TRUE,
+    Toggle = FALSE,
+    Container = FALSE,
+    RecordAbsolute = FALSE,
+    RecordPerSet;
+
+    AccelConfig = TRUE,
+    MenuConfig = TRUE,
+    ToolBoxConfig = TRUE,
+    GroupId = SfxGroupId::Edit;
+]
+
+SfxVoidItem UngroupSparklines SID_UNGROUP_SPARKLINES
+()
+[
+    AutoUpdate = FALSE,
+    FastCall = FALSE,
+    ReadOnlyDoc = TRUE,
+    Toggle = FALSE,
+    Container = FALSE,
+    RecordAbsolute = FALSE,
+    RecordPerSet;
+
+    AccelConfig = TRUE,
+    MenuConfig = TRUE,
+    ToolBoxConfig = TRUE,
+    GroupId = SfxGroupId::Edit;
+]
+
 SfxVoidItem SearchResultsDialog SID_SEARCH_RESULTS_DIALOG
 (SfxBoolItem Visible SID_SEARCH_RESULTS_DIALOG)
 [
diff --git a/sc/source/ui/docshell/docfunc.cxx 
b/sc/source/ui/docshell/docfunc.cxx
index bb45db9a44ea..2f4ee0492aa2 100644
--- a/sc/source/ui/docshell/docfunc.cxx
+++ b/sc/source/ui/docshell/docfunc.cxx
@@ -101,6 +101,8 @@
 #include <undo/UndoDeleteSparkline.hxx>
 #include <undo/UndoDeleteSparklineGroup.hxx>
 #include <undo/UndoEditSparklineGroup.hxx>
+#include <undo/UndoUngroupSparklines.hxx>
+#include <undo/UndoGroupSparklines.hxx>
 #include <config_features.h>
 
 #include <memory>
@@ -5887,4 +5889,22 @@ bool 
ScDocFunc::ChangeSparklineGroupAttributes(std::shared_ptr<sc::SparklineGrou
     return true;
 }
 
+bool ScDocFunc::GroupSparklines(ScRange const& rRange, 
std::shared_ptr<sc::SparklineGroup> const& rpGroup)
+{
+    auto pUndo = std::make_unique<sc::UndoGroupSparklines>(rDocShell, rRange, 
rpGroup);
+    // ungroup sparklines by "redoing"
+    pUndo->Redo();
+    rDocShell.GetUndoManager()->AddUndoAction(std::move(pUndo));
+    return true;
+}
+
+bool ScDocFunc::UngroupSparklines(ScRange const& rRange)
+{
+    auto pUndo = std::make_unique<sc::UndoUngroupSparklines>(rDocShell, 
rRange);
+    // ungroup sparklines by "redoing"
+    pUndo->Redo();
+    rDocShell.GetUndoManager()->AddUndoAction(std::move(pUndo));
+    return true;
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/inc/docfunc.hxx b/sc/source/ui/inc/docfunc.hxx
index b1111fd48bbf..938f96835b4d 100644
--- a/sc/source/ui/inc/docfunc.hxx
+++ b/sc/source/ui/inc/docfunc.hxx
@@ -242,9 +242,10 @@ public:
 
     SC_DLLPUBLIC bool DeleteSparkline(ScAddress const& rAddress);
     SC_DLLPUBLIC bool DeleteSparklineGroup(std::shared_ptr<sc::SparklineGroup> 
const& pSparklineGroup, SCTAB nTab);
-
     SC_DLLPUBLIC bool 
ChangeSparklineGroupAttributes(std::shared_ptr<sc::SparklineGroup> const& 
pExistingSparklineGroup,
                                                      sc::SparklineAttributes 
const& rNewAttributes);
+    SC_DLLPUBLIC bool GroupSparklines(ScRange const& rRange, 
std::shared_ptr<sc::SparklineGroup> const& rpGroup);
+    SC_DLLPUBLIC bool UngroupSparklines(ScRange const& rRange);
 
 private:
     void ProtectDocument(const ScDocProtection& rProtect);
diff --git a/sc/source/ui/inc/undo/UndoGroupSparklines.hxx 
b/sc/source/ui/inc/undo/UndoGroupSparklines.hxx
new file mode 100644
index 000000000000..97bb3a9ee7ec
--- /dev/null
+++ b/sc/source/ui/inc/undo/UndoGroupSparklines.hxx
@@ -0,0 +1,55 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#pragma once
+
+#include <undobase.hxx>
+#include <memory>
+
+namespace sc
+{
+struct UndoGroupSparklinesData
+{
+    UndoGroupSparklinesData(ScAddress const& rAddress, ScRangeList const& 
rDataRangeList,
+                            std::shared_ptr<sc::SparklineGroup> const& rpGroup)
+        : m_aAddress(rAddress)
+        , m_aDataRangeList(rDataRangeList)
+        , m_pSparklineGroup(rpGroup)
+    {
+    }
+
+    ScAddress m_aAddress;
+    ScRangeList m_aDataRangeList;
+    std::shared_ptr<sc::SparklineGroup> m_pSparklineGroup;
+};
+
+/** Undo action for ungrouping sparklines */
+class UndoGroupSparklines : public ScSimpleUndo
+{
+private:
+    ScRange m_aRange;
+    std::shared_ptr<sc::SparklineGroup> m_pSparklineGroup;
+    std::vector<UndoGroupSparklinesData> m_aUndoData;
+
+public:
+    UndoGroupSparklines(ScDocShell& rDocShell, ScRange const& rRange,
+                        std::shared_ptr<sc::SparklineGroup> const& 
rpSparklineGroup);
+    virtual ~UndoGroupSparklines() override;
+
+    void Undo() override;
+    void Redo() override;
+    bool CanRepeat(SfxRepeatTarget& rTarget) const override;
+    void Repeat(SfxRepeatTarget& rTarget) override;
+    OUString GetComment() const override;
+};
+
+} // namespace sc
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/inc/undo/UndoUngroupSparklines.hxx 
b/sc/source/ui/inc/undo/UndoUngroupSparklines.hxx
new file mode 100644
index 000000000000..9f372f00e686
--- /dev/null
+++ b/sc/source/ui/inc/undo/UndoUngroupSparklines.hxx
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#pragma once
+
+#include <undobase.hxx>
+#include <memory>
+
+namespace sc
+{
+struct SparklineUndoData
+{
+    SparklineUndoData(ScAddress const& rAddress, ScRangeList const& 
rDataRangeList,
+                      std::shared_ptr<sc::SparklineGroup> const& rpGroup)
+        : m_aAddress(rAddress)
+        , m_aDataRangeList(rDataRangeList)
+        , m_pSparklineGroup(rpGroup)
+    {
+    }
+
+    ScAddress m_aAddress;
+    ScRangeList m_aDataRangeList;
+    std::shared_ptr<sc::SparklineGroup> m_pSparklineGroup;
+};
+
+/** Undo action for ungrouping sparklines */
+class UndoUngroupSparklines : public ScSimpleUndo
+{
+private:
+    ScRange m_aRange;
+    std::vector<SparklineUndoData> m_aUndoData;
+
+public:
+    UndoUngroupSparklines(ScDocShell& rDocShell, ScRange const& rRange);
+    virtual ~UndoUngroupSparklines() override;
+
+    void Undo() override;
+    void Redo() override;
+    bool CanRepeat(SfxRepeatTarget& rTarget) const override;
+    void Repeat(SfxRepeatTarget& rTarget) override;
+    OUString GetComment() const override;
+};
+
+} // namespace sc
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/undo/UndoGroupSparklines.cxx 
b/sc/source/ui/undo/UndoGroupSparklines.cxx
new file mode 100644
index 000000000000..ac2182714fc1
--- /dev/null
+++ b/sc/source/ui/undo/UndoGroupSparklines.cxx
@@ -0,0 +1,91 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#include <undo/UndoGroupSparklines.hxx>
+
+#include <globstr.hrc>
+#include <scresid.hxx>
+
+#include <Sparkline.hxx>
+#include <SparklineGroup.hxx>
+#include <SparklineAttributes.hxx>
+
+namespace sc
+{
+UndoGroupSparklines::UndoGroupSparklines(
+    ScDocShell& rDocShell, ScRange const& rRange,
+    std::shared_ptr<sc::SparklineGroup> const& rpSparklineGroup)
+    : ScSimpleUndo(&rDocShell)
+    , m_aRange(rRange)
+    , m_pSparklineGroup(rpSparklineGroup)
+{
+}
+
+UndoGroupSparklines::~UndoGroupSparklines() = default;
+
+void UndoGroupSparklines::Undo()
+{
+    BeginUndo();
+
+    ScDocument& rDocument = pDocShell->GetDocument();
+
+    for (auto& rUndoData : m_aUndoData)
+    {
+        rDocument.DeleteSparkline(rUndoData.m_aAddress);
+        auto* pCreated
+            = rDocument.CreateSparkline(rUndoData.m_aAddress, 
rUndoData.m_pSparklineGroup);
+        pCreated->setInputRange(rUndoData.m_aDataRangeList);
+    }
+
+    m_aUndoData.clear();
+
+    pDocShell->PostPaint(m_aRange, PaintPartFlags::All);
+
+    EndUndo();
+}
+
+void UndoGroupSparklines::Redo()
+{
+    BeginRedo();
+
+    ScDocument& rDocument = pDocShell->GetDocument();
+
+    for (ScAddress aAddress = m_aRange.aStart; aAddress.Col() <= 
m_aRange.aEnd.Col();
+         aAddress.IncCol())
+    {
+        aAddress.SetRow(m_aRange.aStart.Row());
+        for (; aAddress.Row() <= m_aRange.aEnd.Row(); aAddress.IncRow())
+        {
+            if (auto pSparkline = rDocument.GetSparkline(aAddress))
+            {
+                m_aUndoData.emplace_back(aAddress, pSparkline->getInputRange(),
+                                         pSparkline->getSparklineGroup());
+
+                rDocument.DeleteSparkline(aAddress);
+                auto* pCreated = rDocument.CreateSparkline(aAddress, 
m_pSparklineGroup);
+                pCreated->setInputRange(pSparkline->getInputRange());
+            }
+        }
+    }
+
+    pDocShell->PostPaint(m_aRange, PaintPartFlags::All);
+
+    EndRedo();
+}
+
+void UndoGroupSparklines::Repeat(SfxRepeatTarget& /*rTarget*/) {}
+
+bool UndoGroupSparklines::CanRepeat(SfxRepeatTarget& /*rTarget*/) const { 
return false; }
+
+OUString UndoGroupSparklines::GetComment() const { return 
ScResId(STR_UNDO_GROUP_SPARKLINES); }
+
+} // end sc namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/undo/UndoUngroupSparklines.cxx 
b/sc/source/ui/undo/UndoUngroupSparklines.cxx
new file mode 100644
index 000000000000..fe0201eb63d3
--- /dev/null
+++ b/sc/source/ui/undo/UndoUngroupSparklines.cxx
@@ -0,0 +1,89 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#include <undo/UndoUngroupSparklines.hxx>
+
+#include <globstr.hrc>
+#include <scresid.hxx>
+
+#include <Sparkline.hxx>
+#include <SparklineGroup.hxx>
+#include <SparklineAttributes.hxx>
+
+namespace sc
+{
+UndoUngroupSparklines::UndoUngroupSparklines(ScDocShell& rDocShell, ScRange 
const& rRange)
+    : ScSimpleUndo(&rDocShell)
+    , m_aRange(rRange)
+{
+}
+
+UndoUngroupSparklines::~UndoUngroupSparklines() = default;
+
+void UndoUngroupSparklines::Undo()
+{
+    BeginUndo();
+
+    ScDocument& rDocument = pDocShell->GetDocument();
+
+    for (SparklineUndoData& rUndoData : m_aUndoData)
+    {
+        rDocument.DeleteSparkline(rUndoData.m_aAddress);
+        auto* pCreated
+            = rDocument.CreateSparkline(rUndoData.m_aAddress, 
rUndoData.m_pSparklineGroup);
+        pCreated->setInputRange(rUndoData.m_aDataRangeList);
+    }
+
+    m_aUndoData.clear();
+
+    pDocShell->PostPaint(m_aRange, PaintPartFlags::All);
+
+    EndUndo();
+}
+
+void UndoUngroupSparklines::Redo()
+{
+    BeginRedo();
+
+    ScDocument& rDocument = pDocShell->GetDocument();
+
+    for (ScAddress aAddress = m_aRange.aStart; aAddress.Col() <= 
m_aRange.aEnd.Col();
+         aAddress.IncCol())
+    {
+        aAddress.SetRow(m_aRange.aStart.Row());
+        for (; aAddress.Row() <= m_aRange.aEnd.Row(); aAddress.IncRow())
+        {
+            if (auto pSparkline = rDocument.GetSparkline(aAddress))
+            {
+                auto const& rpGroup = pSparkline->getSparklineGroup();
+                m_aUndoData.emplace_back(aAddress, 
pSparkline->getInputRange(), rpGroup);
+                auto pSparklineGroupCopy
+                    = 
std::make_shared<sc::SparklineGroup>(rpGroup->getAttributes());
+                rDocument.DeleteSparkline(aAddress);
+                auto* pCreated = rDocument.CreateSparkline(aAddress, 
pSparklineGroupCopy);
+                pCreated->setInputRange(pSparkline->getInputRange());
+            }
+        }
+    }
+
+    pDocShell->PostPaint(m_aRange, PaintPartFlags::All);
+
+    EndRedo();
+}
+
+void UndoUngroupSparklines::Repeat(SfxRepeatTarget& /*rTarget*/) {}
+
+bool UndoUngroupSparklines::CanRepeat(SfxRepeatTarget& /*rTarget*/) const { 
return false; }
+
+OUString UndoUngroupSparklines::GetComment() const { return 
ScResId(STR_UNDO_UNGROUP_SPARKLINES); }
+
+} // end sc namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/view/cellsh.cxx b/sc/source/ui/view/cellsh.cxx
index 68be82997b7c..c3e7aab1d1dc 100644
--- a/sc/source/ui/view/cellsh.cxx
+++ b/sc/source/ui/view/cellsh.cxx
@@ -187,6 +187,12 @@ void ScCellShell::GetBlockState( SfxItemSet& rSet )
                 bDisable = !bSimpleArea;
             }
             break;
+            case SID_GROUP_SPARKLINES:
+            case SID_UNGROUP_SPARKLINES:
+            {
+                bDisable = !bSimpleArea;
+            }
+            break;
 
             case SID_DELETE_SPARKLINE:
             case SID_EDIT_SPARKLINE_GROUP:
diff --git a/sc/source/ui/view/cellsh1.cxx b/sc/source/ui/view/cellsh1.cxx
index 74d31f68fb89..fc221645a5d6 100644
--- a/sc/source/ui/view/cellsh1.cxx
+++ b/sc/source/ui/view/cellsh1.cxx
@@ -87,6 +87,7 @@
 #include <formulacell.hxx>
 #include <gridwin.hxx>
 #include <searchresults.hxx>
+#include <Sparkline.hxx>
 
 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
 #include <com/sun/star/lang/XInitialization.hpp>
@@ -1086,6 +1087,34 @@ void ScCellShell::ExecuteEdit( SfxRequest& rReq )
         }
         break;
 
+        case SID_GROUP_SPARKLINES:
+        {
+            ScRange aRange;
+            if (GetViewData().GetSimpleArea(aRange) == SC_MARK_SIMPLE)
+            {
+                ScAddress aCursorAddress(GetViewData().GetCurX(), 
GetViewData().GetCurY(), GetViewData().GetTabNo());
+                auto pSparkline = 
GetViewData().GetDocument().GetSparkline(aCursorAddress);
+                if (pSparkline)
+                {
+                    auto const& rpSparklineGroup = 
pSparkline->getSparklineGroup();
+                    
GetViewData().GetDocShell()->GetDocFunc().GroupSparklines(aRange, 
rpSparklineGroup);
+                }
+            }
+            rReq.Done();
+        }
+        break;
+
+        case SID_UNGROUP_SPARKLINES:
+        {
+            ScRange aRange;
+            if (GetViewData().GetSimpleArea(aRange) == SC_MARK_SIMPLE)
+            {
+                
GetViewData().GetDocShell()->GetDocFunc().UngroupSparklines(aRange);
+            }
+            rReq.Done();
+        }
+        break;
+
         //  disposal (Outlines)
         //  SID_AUTO_OUTLINE, SID_OUTLINE_DELETEALL in Execute (in docsh.idl)
 
diff --git a/sc/source/ui/view/viewfun2.cxx b/sc/source/ui/view/viewfun2.cxx
index 5d7d62d4ad84..f05be0e7eade 100644
--- a/sc/source/ui/view/viewfun2.cxx
+++ b/sc/source/ui/view/viewfun2.cxx
@@ -1458,6 +1458,8 @@ void ScViewFunc::FillSeries( FillDir eDir, FillCmd eCmd, 
FillDateCmd eDateCmd,
 void ScViewFunc::FillAuto( FillDir eDir, SCCOL nStartCol, SCROW nStartRow,
                             SCCOL nEndCol, SCROW nEndRow, sal_uLong nCount )
 {
+    printf ("FillAuto\n");
+
     SCTAB nTab = GetViewData().GetTabNo();
     ScRange aRange( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab );
     ScRange aSourceRange( aRange );
diff --git a/sc/uiconfig/scalc/popupmenu/cell.xml 
b/sc/uiconfig/scalc/popupmenu/cell.xml
index d2eab7422839..1de462b89fe1 100644
--- a/sc/uiconfig/scalc/popupmenu/cell.xml
+++ b/sc/uiconfig/scalc/popupmenu/cell.xml
@@ -69,6 +69,8 @@
       <menu:menuitem menu:id=".uno:DeleteSparkline"/>
       <menu:menuitem menu:id=".uno:DeleteSparklineGroup"/>
       <menu:menuitem menu:id=".uno:EditSparklineGroup"/>
+      <menu:menuitem menu:id=".uno:GroupSparklines"/>
+      <menu:menuitem menu:id=".uno:UngroupSparklines"/>
     </menu:menupopup>
   </menu:menu>
   <menu:menuseparator/>

Reply via email to