sc/qa/unit/tiledrendering/SheetViewTest.cxx         |   36 ++++
 sc/source/ui/docshell/SheetViewOperationsTester.cxx |   33 +++-
 sc/source/ui/operation/DeleteCellOperation.cxx      |  148 +++++++++++++++++---
 3 files changed, 189 insertions(+), 28 deletions(-)

New commits:
commit 60a279a6e1e4c752c650b4b04349fb6e2fc01de3
Author:     Tomaž Vajngerl <[email protected]>
AuthorDate: Thu Feb 5 23:24:19 2026 +0900
Commit:     Miklos Vajna <[email protected]>
CommitDate: Fri Feb 13 15:00:58 2026 +0100

    sc: Reapply sorting and filtering on sync, unsort address and mark
    
    When we sync one default sheet to sheet view, reapply the sorting
    and filtering so the sheet view is the same as it was before we
    needed to sync.
    
    Also take into account sorting when we delete a cell in sheet view
    and we want to apply the operation to the default view. In that
    case we need to unsort to get the correct address and mark. This
    is currently implemented in DeleteCellOperation, but will be needed
    in other Operations as well.
    
    The test case was adapted for the more complex scenario.
    
    Change-Id: I37c91c5436059f732fad673aed79f3e16a9e77d6
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/198761
    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 7bd56d6ed019..5195601a964d 100644
--- a/sc/qa/unit/tiledrendering/SheetViewTest.cxx
+++ b/sc/qa/unit/tiledrendering/SheetViewTest.cxx
@@ -1046,12 +1046,22 @@ CPPUNIT_TEST_FIXTURE(SyncTest, 
testSync_DefaultView_DeleteCellOperation)
 
     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();
@@ -1064,9 +1074,11 @@ CPPUNIT_TEST_FIXTURE(SyncTest, 
testSync_DefaultView_DeleteCellOperation)
 
     OUString aExpected = expectedValues({ u"4", u"", u"3", u"7" });
     CPPUNIT_ASSERT_EQUAL(aExpected, getValues(mpTabViewDefaultView, 0, 1, 4));
-    CPPUNIT_ASSERT_EQUAL(aExpected, getValues(mpTabViewSheetView, 0, 1, 4));
     CPPUNIT_ASSERT_EQUAL(aExpected, getValues(pDocument, 0, 1, 4, 0));
-    CPPUNIT_ASSERT_EQUAL(aExpected, getValues(pDocument, 0, 1, 4, 1));
+
+    OUString aExpectedSorted = expectedValues({ u"7", u"4", u"3", 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_DeleteCellOperation)
@@ -1078,23 +1090,35 @@ CPPUNIT_TEST_FIXTURE(SyncTest, 
testSync_SheetView_DeleteCellOperation)
 
     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"_ustr) } }));
+                        comphelper::InitPropertySequence({ { "ToPoint", 
uno::Any(u"A4"_ustr) } }));
 
         dispatchCommand(mxComponent, u".uno:ClearContents"_ustr, {});
     }
 
-    OUString aExpected = expectedValues({ u"4", u"", u"3", u"7" });
+    OUString aExpected = expectedValues({ u"", u"5", u"3", u"7" });
     CPPUNIT_ASSERT_EQUAL(aExpected, getValues(mpTabViewDefaultView, 0, 1, 4));
-    CPPUNIT_ASSERT_EQUAL(aExpected, getValues(mpTabViewSheetView, 0, 1, 4));
     CPPUNIT_ASSERT_EQUAL(aExpected, getValues(pDocument, 0, 1, 4, 0));
-    CPPUNIT_ASSERT_EQUAL(aExpected, getValues(pDocument, 0, 1, 4, 1));
+
+    OUString aExpectedSorted = expectedValues({ u"7", u"5", u"3", u"" });
+    CPPUNIT_ASSERT_EQUAL(aExpectedSorted, getValues(mpTabViewSheetView, 0, 1, 
4));
+    CPPUNIT_ASSERT_EQUAL(aExpectedSorted, getValues(pDocument, 0, 1, 4, 1));
 }
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sc/source/ui/docshell/SheetViewOperationsTester.cxx 
b/sc/source/ui/docshell/SheetViewOperationsTester.cxx
index 37593c7382ab..216507a8f407 100644
--- a/sc/source/ui/docshell/SheetViewOperationsTester.cxx
+++ b/sc/source/ui/docshell/SheetViewOperationsTester.cxx
@@ -12,6 +12,8 @@
 #include <docsh.hxx>
 #include <viewdata.hxx>
 #include <sal/log.hxx>
+#include <dbdata.hxx>
+#include <queryparam.hxx>
 
 namespace sc
 {
@@ -161,13 +163,36 @@ void SheetViewOperationsTester::sync()
 
     std::shared_ptr<sc::SheetViewManager> pManager = 
rDocument.GetSheetViewManager(nTab);
 
-    if (!pManager->isEmpty())
+    if (pManager->isEmpty())
+        return;
+
+    for (auto const& pSheetView : pManager->getSheetViews())
     {
-        for (auto const& pSheetView : pManager->getSheetViews())
+        SCTAB nSheetViewTab = pSheetView->getTableNumber();
+
+        std::optional<ScQueryParam> oQueryParam;
+        std::optional<ScSortParam> oSortParam;
+        ScDBData* pNoNameData = rDocument.GetAnonymousDBData(nSheetViewTab);
+        if (pNoNameData && pNoNameData->HasAutoFilter())
         {
-            SCTAB nSheetViewTab = pSheetView->getTableNumber();
-            rDocument.OverwriteContent(nTab, nSheetViewTab);
+            if (pNoNameData->HasQueryParam())
+            {
+                oQueryParam.emplace();
+                pNoNameData->GetQueryParam(*oQueryParam);
+            }
+            if (pNoNameData->HasSortParam())
+            {
+                oSortParam.emplace();
+                pNoNameData->GetSortParam(*oSortParam);
+            }
         }
+
+        rDocument.OverwriteContent(nTab, nSheetViewTab);
+
+        if (oQueryParam)
+            rDocument.Query(nSheetViewTab, *oQueryParam, false, false);
+        if (oSortParam)
+            rDocument.Sort(nSheetViewTab, *oSortParam, false, false, nullptr, 
nullptr);
     }
 }
 
diff --git a/sc/source/ui/operation/DeleteCellOperation.cxx 
b/sc/source/ui/operation/DeleteCellOperation.cxx
index b07decd047e4..9d320e8e98df 100644
--- a/sc/source/ui/operation/DeleteCellOperation.cxx
+++ b/sc/source/ui/operation/DeleteCellOperation.cxx
@@ -14,6 +14,9 @@
 #include <markdata.hxx>
 #include <editable.hxx>
 #include <address.hxx>
+#include <viewdata.hxx>
+#include <SheetViewManager.hxx>
+#include <SheetView.hxx>
 
 #include <memory>
 
@@ -31,13 +34,115 @@ 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);
 
-    ScAddress const& rPos = mrPosition;
-    ScMarkData const& rMark = mrMark;
-
     ScDocument& rDoc = mrDocShell.GetDocument();
 
     if (mbRecord && !rDoc.IsUndoEnabled())
@@ -45,8 +150,12 @@ bool DeleteCellOperation::runImplementation()
 
     sc::SheetViewOperationsTester aSheetViewTester(ScDocShell::GetViewData());
 
+    // Convert taking sheet view sorting into account
+    ScAddress aPosition = convertAddress(mrPosition);
+    ScMarkData aMarkData = convertMark(mrMark);
+
     ScEditableTester aTester = ScEditableTester::CreateAndTestSelectedBlock(
-        rDoc, rPos.Col(), rPos.Row(), rPos.Col(), rPos.Row(), rMark);
+        rDoc, aPosition.Col(), aPosition.Row(), aPosition.Col(), 
aPosition.Row(), aMarkData);
     if (!aTester.IsEditable())
     {
         mrDocShell.ErrorMessage(aTester.GetMessageId());
@@ -54,12 +163,12 @@ bool DeleteCellOperation::runImplementation()
     }
 
     // no objects on protected tabs
-    bool bObjects
-        = (mnFlags & InsertDeleteFlags::OBJECTS) && 
!sc::DocFuncUtil::hasProtectedTab(rDoc, rMark);
+    bool bObjects = (mnFlags & InsertDeleteFlags::OBJECTS)
+                    && !sc::DocFuncUtil::hasProtectedTab(rDoc, aMarkData);
 
     sal_uInt16 nExtFlags = 0; // extra flags are needed only if attributes are 
deleted
     if (mnFlags & InsertDeleteFlags::ATTRIB)
-        mrDocShell.UpdatePaintExt(nExtFlags, ScRange(rPos));
+        mrDocShell.UpdatePaintExt(nExtFlags, ScRange(aPosition));
 
     //  order of operations:
     //  1) BeginDrawUndo
@@ -73,7 +182,8 @@ bool DeleteCellOperation::runImplementation()
         rDoc.BeginDrawUndo();
 
     if (bObjects)
-        rDoc.DeleteObjectsInArea(rPos.Col(), rPos.Row(), rPos.Col(), 
rPos.Row(), rMark);
+        rDoc.DeleteObjectsInArea(aPosition.Col(), aPosition.Row(), 
aPosition.Col(), aPosition.Row(),
+                                 aMarkData);
 
     // To keep track of all non-empty cells within the deleted area.
     std::shared_ptr<ScSimpleUndo::DataSpansType> pDataSpans;
@@ -81,24 +191,26 @@ bool DeleteCellOperation::runImplementation()
     ScDocumentUniquePtr pUndoDoc;
     if (mbRecord)
     {
-        pUndoDoc = sc::DocFuncUtil::createDeleteContentsUndoDoc(rDoc, rMark, 
ScRange(rPos), mnFlags,
-                                                                false);
-        pDataSpans = sc::DocFuncUtil::getNonEmptyCellSpans(rDoc, rMark, 
ScRange(rPos));
+        pUndoDoc = sc::DocFuncUtil::createDeleteContentsUndoDoc(rDoc, 
aMarkData, ScRange(aPosition),
+                                                                mnFlags, 
false);
+        pDataSpans = sc::DocFuncUtil::getNonEmptyCellSpans(rDoc, aMarkData, 
ScRange(aPosition));
     }
 
-    tools::Long nBefore(mrDocShell.GetTwipWidthHint(rPos));
-    rDoc.DeleteArea(rPos.Col(), rPos.Row(), rPos.Col(), rPos.Row(), rMark, 
mnFlags);
+    tools::Long nBefore(mrDocShell.GetTwipWidthHint(aPosition));
+    rDoc.DeleteArea(aPosition.Col(), aPosition.Row(), aPosition.Col(), 
aPosition.Row(), aMarkData,
+                    mnFlags);
 
     if (mbRecord)
     {
-        sc::DocFuncUtil::addDeleteContentsUndo(mrDocShell.GetUndoManager(), 
&mrDocShell, rMark,
-                                               ScRange(rPos), 
std::move(pUndoDoc), mnFlags,
+        sc::DocFuncUtil::addDeleteContentsUndo(mrDocShell.GetUndoManager(), 
&mrDocShell, aMarkData,
+                                               ScRange(aPosition), 
std::move(pUndoDoc), mnFlags,
                                                pDataSpans, false, bDrawUndo);
     }
 
-    if (!mrDocFunc.AdjustRowHeight(ScRange(rPos), true, mbApi))
-        mrDocShell.PostPaint(rPos.Col(), rPos.Row(), rPos.Tab(), rPos.Col(), 
rPos.Row(), rPos.Tab(),
-                             PaintPartFlags::Grid, nExtFlags, nBefore);
+    if (!mrDocFunc.AdjustRowHeight(ScRange(aPosition), true, mbApi))
+        mrDocShell.PostPaint(aPosition.Col(), aPosition.Row(), 
aPosition.Tab(), aPosition.Col(),
+                             aPosition.Row(), aPosition.Tab(), 
PaintPartFlags::Grid, nExtFlags,
+                             nBefore);
 
     if (sc::SheetViewOperationsTester::doesUnsync(meType))
         aSheetViewTester.sync();

Reply via email to