sc/qa/unit/tiledrendering/SheetViewTest.cxx       |   86 +++++++++++++++++
 sc/source/ui/inc/operation/Operation.hxx          |    9 +
 sc/source/ui/operation/DeleteCellOperation.cxx    |  108 ----------------------
 sc/source/ui/operation/DeleteContentOperation.cxx |    9 +
 sc/source/ui/operation/Operation.cxx              |  108 ++++++++++++++++++++++
 5 files changed, 209 insertions(+), 111 deletions(-)

New commits:
commit c7ab242e6dd46c58e0265967aaa9aba172275c30
Author:     Tomaž Vajngerl <[email protected]>
AuthorDate: Fri Feb 6 14:41:51 2026 +0900
Commit:     Miklos Vajna <[email protected]>
CommitDate: Mon Feb 16 09:08:10 2026 +0100

    sc: Implement sync in DeleteContentOperation
    
    Sync all sheet view scenarios for delete content operation.
    
    Move the convertMark and convertAddress to Operation class, so
    we can reuse it in all Oeprations.
    
    Fix wrong parameter order when calling IsCellMarked in convertMark.
    
    Change-Id: I2301f3a3d21c601d368c816dc7157e3f55e2f9f8
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/198960
    Tested-by: Jenkins CollaboraOffice <[email protected]>
    Reviewed-by: Miklos Vajna <[email protected]>

diff --git a/sc/qa/unit/tiledrendering/SheetViewTest.cxx 
b/sc/qa/unit/tiledrendering/SheetViewTest.cxx
index 5195601a964d..50a7c906cb5a 100644
--- a/sc/qa/unit/tiledrendering/SheetViewTest.cxx
+++ b/sc/qa/unit/tiledrendering/SheetViewTest.cxx
@@ -1121,6 +1121,92 @@ CPPUNIT_TEST_FIXTURE(SyncTest, 
testSync_SheetView_DeleteCellOperation)
     CPPUNIT_ASSERT_EQUAL(aExpectedSorted, getValues(pDocument, 0, 1, 4, 1));
 }
 
+CPPUNIT_TEST_FIXTURE(SyncTest, testSync_DefaultView_DeleteContentOperation)
+{
+    // Create two views, and leave the second one current.
+    ScModelObj* pModelObj = createDoc("SheetView_AutoFilter.ods");
+    
pModelObj->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>());
+    ScDocument* pDocument = pModelObj->GetDocument();
+
+    setupViews();
+
+    CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }),
+                         getValues(pDocument, 0, 1, 4, 0));
+    CPPUNIT_ASSERT_EQUAL(expectedValues({ u"", u"", u"", u"" }), 
getValues(pDocument, 0, 1, 4, 1));
+
+    // Switch to Sheet View and Create
+    {
+        switchToSheetView();
+        dispatchCommand(mxComponent, u".uno:NewSheetView"_ustr, {});
+        dispatchCommand(mxComponent, u".uno:SortDescending"_ustr, {});
+    }
+
+    CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }),
+                         getValues(pDocument, 0, 1, 4, 0));
+    CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3" }),
+                         getValues(pDocument, 0, 1, 4, 1));
+
+    // Switch to Default View
+    {
+        switchToDefaultView();
+
+        dispatchCommand(
+            mxComponent, u".uno:GoToCell"_ustr,
+            comphelper::InitPropertySequence({ { "ToPoint", 
uno::Any(u"A3:A4"_ustr) } }));
+
+        dispatchCommand(mxComponent, u".uno:ClearContents"_ustr, {});
+    }
+
+    OUString aExpected = expectedValues({ u"4", u"", u"", u"7" });
+    CPPUNIT_ASSERT_EQUAL(aExpected, getValues(mpTabViewDefaultView, 0, 1, 4));
+    CPPUNIT_ASSERT_EQUAL(aExpected, getValues(pDocument, 0, 1, 4, 0));
+
+    OUString aExpectedSorted = expectedValues({ u"7", u"4", u"", u"" });
+    CPPUNIT_ASSERT_EQUAL(aExpectedSorted, getValues(mpTabViewSheetView, 0, 1, 
4));
+    CPPUNIT_ASSERT_EQUAL(aExpectedSorted, getValues(pDocument, 0, 1, 4, 1));
+}
+
+CPPUNIT_TEST_FIXTURE(SyncTest, testSync_SheetView_DeleteContentOperation)
+{
+    // Create two views, and leave the second one current.
+    ScModelObj* pModelObj = createDoc("SheetView_AutoFilter.ods");
+    
pModelObj->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>());
+    ScDocument* pDocument = pModelObj->GetDocument();
+
+    setupViews();
+
+    CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }),
+                         getValues(pDocument, 0, 1, 4, 0));
+    CPPUNIT_ASSERT_EQUAL(expectedValues({ u"", u"", u"", u"" }), 
getValues(pDocument, 0, 1, 4, 1));
+
+    // Switch to Sheet View and Create
+    {
+        switchToSheetView();
+
+        dispatchCommand(mxComponent, u".uno:NewSheetView"_ustr, {});
+        dispatchCommand(mxComponent, u".uno:SortDescending"_ustr, {});
+
+        CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7" }),
+                             getValues(pDocument, 0, 1, 4, 0));
+        CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"5", u"4", u"3" }),
+                             getValues(pDocument, 0, 1, 4, 1));
+
+        dispatchCommand(
+            mxComponent, u".uno:GoToCell"_ustr,
+            comphelper::InitPropertySequence({ { "ToPoint", 
uno::Any(u"A3:A4"_ustr) } }));
+
+        dispatchCommand(mxComponent, u".uno:ClearContents"_ustr, {});
+    }
+
+    OUString aExpected = expectedValues({ u"", u"", u"3", u"7" });
+    CPPUNIT_ASSERT_EQUAL(aExpected, getValues(mpTabViewDefaultView, 0, 1, 4));
+    CPPUNIT_ASSERT_EQUAL(aExpected, getValues(pDocument, 0, 1, 4, 0));
+
+    OUString aExpectedSorted = expectedValues({ u"7", u"3", u"", u"" });
+    CPPUNIT_ASSERT_EQUAL(aExpectedSorted, getValues(mpTabViewSheetView, 0, 1, 
4));
+    CPPUNIT_ASSERT_EQUAL(aExpectedSorted, getValues(pDocument, 0, 1, 4, 1));
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/inc/operation/Operation.hxx 
b/sc/source/ui/inc/operation/Operation.hxx
index f330f1b13c9c..596a7dbf26c7 100644
--- a/sc/source/ui/inc/operation/Operation.hxx
+++ b/sc/source/ui/inc/operation/Operation.hxx
@@ -11,6 +11,9 @@
 
 #include <SheetViewOperationsTester.hxx>
 
+class ScMarkData;
+class ScAddress;
+
 namespace sc
 {
 /** Operation is one atomic coarse change to the document model that can be 
run from UI or API
@@ -46,6 +49,12 @@ public:
     bool run() { return runImplementation(); }
     bool checkSheetViewProtection();
 
+    /** Convert address from a sheet view to the address in default view, take 
sorting into account. */
+    static ScAddress convertAddress(ScAddress const& rAddress);
+
+    /** Convert a mark from a sheet view to the mark in default view, take 
sorting into account. */
+    static ScMarkData convertMark(ScMarkData const& rMarkData);
+
     virtual bool runImplementation() = 0;
 };
 
diff --git a/sc/source/ui/operation/DeleteCellOperation.cxx 
b/sc/source/ui/operation/DeleteCellOperation.cxx
index 9d320e8e98df..fbd88156b078 100644
--- a/sc/source/ui/operation/DeleteCellOperation.cxx
+++ b/sc/source/ui/operation/DeleteCellOperation.cxx
@@ -14,9 +14,6 @@
 #include <markdata.hxx>
 #include <editable.hxx>
 #include <address.hxx>
-#include <viewdata.hxx>
-#include <SheetViewManager.hxx>
-#include <SheetView.hxx>
 
 #include <memory>
 
@@ -34,111 +31,6 @@ DeleteCellOperation::DeleteCellOperation(ScDocFunc& 
rDocFunc, ScDocShell& rDocSh
 {
 }
 
-namespace
-{
-std::shared_ptr<SheetView> getCurrentSheetView(ScViewData* pViewData)
-{
-    if (!pViewData)
-        return nullptr;
-
-    sc::SheetViewID nID = pViewData->GetSheetViewID();
-    if (nID == sc::DefaultSheetViewID)
-        return nullptr;
-
-    std::shared_ptr<sc::SheetViewManager> pSheetViewManager
-        = pViewData->GetCurrentSheetViewManager();
-    if (!pSheetViewManager)
-        return nullptr;
-
-    return pSheetViewManager->get(nID);
-}
-
-/** Convert address from a sheet view to the address in default view, take 
sorting into account. */
-ScAddress convertAddress(ScAddress const& rAddress)
-{
-    ScViewData* pViewData = ScDocShell::GetViewData();
-
-    std::shared_ptr<SheetView> pSheetView = getCurrentSheetView(pViewData);
-    if (!pSheetView)
-        return rAddress;
-
-    std::optional<SortOrderReverser> const& oSortOrder = 
pSheetView->getSortOrder();
-    if (!oSortOrder)
-        return rAddress;
-
-    SCTAB nTab = rAddress.Tab();
-    SCCOL nColumn = rAddress.Col();
-    SCROW nRow = rAddress.Row();
-
-    if (pViewData->GetTabNumber() != nTab)
-        return rAddress;
-
-    SCROW nUnsortedRow = oSortOrder->unsort(nRow, nColumn);
-    if (nUnsortedRow != nRow)
-    {
-        return ScAddress(nColumn, nUnsortedRow, nTab);
-    }
-    return rAddress;
-}
-
-/** Convert a mark from a sheet view to the mark in default view, take sorting 
into account. */
-ScMarkData convertMark(ScMarkData const& rMarkData)
-{
-    ScViewData* pViewData = ScDocShell::GetViewData();
-
-    std::shared_ptr<SheetView> pSheetView = getCurrentSheetView(pViewData);
-    if (!pSheetView)
-        return rMarkData;
-
-    std::optional<SortOrderReverser> const& oSortOrder = 
pSheetView->getSortOrder();
-    if (!oSortOrder)
-        return rMarkData;
-
-    ScMarkData aNewMark(rMarkData);
-    aNewMark.MarkToMulti();
-    bool bChanged = false;
-
-    for (const SCTAB& nTab : aNewMark)
-    {
-        if (pViewData->GetTabNumber() != nTab)
-            continue;
-
-        std::vector<std::pair<SCCOL, SCROW>> aMarkedCells;
-        SortOrderInfo const& rSortInfo = oSortOrder->maSortInfo;
-        for (SCROW nRow = rSortInfo.mnFirstRow; nRow <= rSortInfo.mnLastRow; 
++nRow)
-        {
-            for (SCROW nColumn = rSortInfo.mnFirstColumn; nColumn <= 
rSortInfo.mnLastColumn;
-                 ++nColumn)
-            {
-                if (aNewMark.IsCellMarked(nRow, nColumn))
-                {
-                    aNewMark.SetMultiMarkArea(ScRange(nColumn, nRow, nTab, 
nColumn, nRow, nTab),
-                                              false);
-                    aMarkedCells.emplace_back(nColumn, nRow);
-                }
-            }
-        }
-        for (auto & [ nColumn, nRow ] : aMarkedCells)
-        {
-            SCROW nUnsortedRow = oSortOrder->unsort(nRow, nColumn);
-            aNewMark.SetMultiMarkArea(
-                ScRange(nColumn, nUnsortedRow, nTab, nColumn, nUnsortedRow, 
nTab), true);
-            bChanged = true;
-        }
-    }
-
-    if (!bChanged)
-        return rMarkData;
-
-    if (bChanged && !aNewMark.HasAnyMultiMarks())
-        aNewMark.ResetMark();
-
-    aNewMark.MarkToSimple();
-
-    return aNewMark;
-}
-}
-
 bool DeleteCellOperation::runImplementation()
 {
     ScDocShellModificator aModificator(mrDocShell);
diff --git a/sc/source/ui/operation/DeleteContentOperation.cxx 
b/sc/source/ui/operation/DeleteContentOperation.cxx
index c1e50436017e..f269d49d523a 100644
--- a/sc/source/ui/operation/DeleteContentOperation.cxx
+++ b/sc/source/ui/operation/DeleteContentOperation.cxx
@@ -40,13 +40,14 @@ bool DeleteContentOperation::runImplementation()
         return false;
     }
 
+    ScMarkData aMultiMark = convertMark(mrMark);
+
     ScDocument& rDoc = mrDocShell.GetDocument();
 
     if (mbRecord && !rDoc.IsUndoEnabled())
         mbRecord = false;
 
-    if (!checkSheetViewProtection())
-        return false;
+    sc::SheetViewOperationsTester aSheetViewTester(ScDocShell::GetViewData());
 
     ScEditableTester aTester = ScEditableTester::CreateAndTestSelection(rDoc, 
mrMark);
     if (!aTester.IsEditable())
@@ -56,7 +57,6 @@ bool DeleteContentOperation::runImplementation()
         return false;
     }
 
-    ScMarkData aMultiMark = mrMark;
     aMultiMark.SetMarking(false); // for MarkToMulti
 
     ScDocumentUniquePtr pUndoDoc;
@@ -114,6 +114,9 @@ bool DeleteContentOperation::runImplementation()
                                                pDataSpans, bMulti, bDrawUndo);
     }
 
+    if (sc::SheetViewOperationsTester::doesUnsync(meType))
+        aSheetViewTester.sync();
+
     if (!mrDocFunc.AdjustRowHeight(aExtendedRange, true, mbApi))
         mrDocShell.PostPaint(aExtendedRange, PaintPartFlags::Grid, nExtFlags);
     else if (nExtFlags & SC_PF_LINES)
diff --git a/sc/source/ui/operation/Operation.cxx 
b/sc/source/ui/operation/Operation.cxx
index d37fb3908c35..471182de8b84 100644
--- a/sc/source/ui/operation/Operation.cxx
+++ b/sc/source/ui/operation/Operation.cxx
@@ -10,9 +10,117 @@
 #include <operation/Operation.hxx>
 #include <SheetViewOperationsTester.hxx>
 #include <docsh.hxx>
+#include <markdata.hxx>
+#include <address.hxx>
+#include <viewdata.hxx>
+#include <SheetViewManager.hxx>
+#include <SheetView.hxx>
 
 namespace sc
 {
+namespace
+{
+std::shared_ptr<SheetView> getCurrentSheetView(ScViewData* pViewData)
+{
+    if (!pViewData)
+        return nullptr;
+
+    sc::SheetViewID nID = pViewData->GetSheetViewID();
+    if (nID == sc::DefaultSheetViewID)
+        return nullptr;
+
+    std::shared_ptr<sc::SheetViewManager> pSheetViewManager
+        = pViewData->GetCurrentSheetViewManager();
+    if (!pSheetViewManager)
+        return nullptr;
+
+    return pSheetViewManager->get(nID);
+}
+}
+
+ScAddress Operation::convertAddress(ScAddress const& rAddress)
+{
+    ScViewData* pViewData = ScDocShell::GetViewData();
+
+    std::shared_ptr<SheetView> pSheetView = getCurrentSheetView(pViewData);
+    if (!pSheetView)
+        return rAddress;
+
+    std::optional<SortOrderReverser> const& oSortOrder = 
pSheetView->getSortOrder();
+    if (!oSortOrder)
+        return rAddress;
+
+    SCTAB nTab = rAddress.Tab();
+    SCCOL nColumn = rAddress.Col();
+    SCROW nRow = rAddress.Row();
+
+    if (pViewData->GetTabNumber() != nTab)
+        return rAddress;
+
+    SCROW nUnsortedRow = oSortOrder->unsort(nRow, nColumn);
+    if (nUnsortedRow != nRow)
+    {
+        return ScAddress(nColumn, nUnsortedRow, nTab);
+    }
+    return rAddress;
+}
+
+ScMarkData Operation::convertMark(ScMarkData const& rMarkData)
+{
+    ScViewData* pViewData = ScDocShell::GetViewData();
+
+    std::shared_ptr<SheetView> pSheetView = getCurrentSheetView(pViewData);
+    if (!pSheetView)
+        return rMarkData;
+
+    std::optional<SortOrderReverser> const& oSortOrder = 
pSheetView->getSortOrder();
+    if (!oSortOrder)
+        return rMarkData;
+
+    ScMarkData aNewMark(rMarkData);
+    aNewMark.MarkToMulti();
+    bool bChanged = false;
+
+    for (const SCTAB& nTab : aNewMark)
+    {
+        if (pViewData->GetTabNumber() != nTab)
+            continue;
+
+        std::vector<std::pair<SCCOL, SCROW>> aMarkedCells;
+        SortOrderInfo const& rSortInfo = oSortOrder->maSortInfo;
+        for (SCROW nRow = rSortInfo.mnFirstRow; nRow <= rSortInfo.mnLastRow; 
++nRow)
+        {
+            for (SCROW nColumn = rSortInfo.mnFirstColumn; nColumn <= 
rSortInfo.mnLastColumn;
+                 ++nColumn)
+            {
+                if (aNewMark.IsCellMarked(nColumn, nRow))
+                {
+                    aNewMark.SetMultiMarkArea(ScRange(nColumn, nRow, nTab, 
nColumn, nRow, nTab),
+                                              false);
+                    aMarkedCells.emplace_back(nColumn, nRow);
+                }
+            }
+        }
+        for (auto & [ nColumn, nRow ] : aMarkedCells)
+        {
+            SCROW nUnsortedRow = oSortOrder->unsort(nRow, nColumn);
+            aNewMark.SetMultiMarkArea(
+                ScRange(nColumn, nUnsortedRow, nTab, nColumn, nUnsortedRow, 
nTab), true);
+            bChanged = true;
+        }
+    }
+
+    if (!bChanged)
+        return rMarkData;
+
+    if (bChanged && !aNewMark.HasAnyMultiMarks())
+        aNewMark.ResetMark();
+
+    aNewMark.MarkToSimple();
+
+    return aNewMark;
+}
+
 bool Operation::checkSheetViewProtection()
 {
     sc::SheetViewOperationsTester aSheetViewTester(ScDocShell::GetViewData());

Reply via email to