sc/inc/SheetViewManager.hxx | 7 + sc/qa/unit/tiledrendering/SheetViewTest.cxx | 134 +++++++++++++++++++++------- sc/source/core/data/SheetViewManager.cxx | 36 +++++++ sc/source/core/data/table3.cxx | 7 + sc/source/ui/view/viewfunc.cxx | 3 5 files changed, 157 insertions(+), 30 deletions(-)
New commits: commit 6b126561dd0d1fa7caf26360c29cd6e6a2265454 Author: Tomaž Vajngerl <[email protected]> AuthorDate: Thu Sep 4 14:05:08 2025 +0200 Commit: Miklos Vajna <[email protected]> CommitDate: Fri Jan 23 10:19:38 2026 +0100 sc: store sort order and reverse the sort for default view We store the sort order of the default view in SheetViewManager, so we can reverse the sort when the sheet view is changed. Tested scenarios are when the auto-filter is sorted in the default view, and the sheet view is changed. Additional scenario is when the auto-filter is sorted again (for example descending following with the ascending order) and the changing the sheet view should still work correctly. Change-Id: Ic42e8a51d6ce17db6b2df80bafb62f6f8c48a6a8 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/190599 Reviewed-by: Tomaž Vajngerl <[email protected]> Tested-by: Jenkins Reviewed-on: https://gerrit.libreoffice.org/c/core/+/197818 Reviewed-by: Miklos Vajna <[email protected]> Tested-by: Jenkins CollaboraOffice <[email protected]> diff --git a/sc/inc/SheetViewManager.hxx b/sc/inc/SheetViewManager.hxx index dc2bf8677230..a0e6527b1d11 100644 --- a/sc/inc/SheetViewManager.hxx +++ b/sc/inc/SheetViewManager.hxx @@ -28,6 +28,10 @@ private: std::vector<std::shared_ptr<SheetView>> maViews; sal_Int32 maNameCounter = 0; + std::vector<SCCOLROW> maOrder; + SCROW mnFirstRow; + SCROW mnLastRow; + bool isValidSheetViewID(SheetViewID nID) const { return nID >= 0 && o3tl::make_unsigned(nID) < maViews.size(); @@ -65,6 +69,9 @@ public: void unsyncAllSheetViews(); static OUString defaultViewName(); + + void addOrderIndices(std::vector<SCCOLROW> const& rOrder, SCROW firstRow, SCROW lastRow); + SCROW unsort(SCROW nRow); }; } diff --git a/sc/qa/unit/tiledrendering/SheetViewTest.cxx b/sc/qa/unit/tiledrendering/SheetViewTest.cxx index f6578715240e..aae9dbb1f2ed 100644 --- a/sc/qa/unit/tiledrendering/SheetViewTest.cxx +++ b/sc/qa/unit/tiledrendering/SheetViewTest.cxx @@ -23,6 +23,23 @@ using namespace css; class SheetViewTest : public ScTiledRenderingTest { +protected: + static bool checkValues(ScTabViewShell* pTabView, SCCOL nCol, SCROW nStartRow, SCROW nEndRow, + std::vector<std::u16string_view> const& rValues) + { + size_t nSize = nEndRow - nStartRow + 1; + if (nSize != rValues.size()) + return false; + + for (size_t nIndex = 0; nIndex < nSize; nIndex++) + { + OUString value = pTabView->GetCurrentString(nCol, nStartRow + nIndex); + if (value != rValues[nIndex]) + return false; + } + + return true; + } }; /** Check auto-filter sorting. @@ -54,20 +71,14 @@ CPPUNIT_TEST_FIXTURE(SheetViewTest, testSheetViewAutoFilter) Scheduler::ProcessEventsToIdle(); // Check AutoFilter values - CPPUNIT_ASSERT_EQUAL(u"4"_ustr, pTabView1->GetCurrentString(0, 1)); - CPPUNIT_ASSERT_EQUAL(u"5"_ustr, pTabView1->GetCurrentString(0, 2)); - CPPUNIT_ASSERT_EQUAL(u"3"_ustr, pTabView1->GetCurrentString(0, 3)); - CPPUNIT_ASSERT_EQUAL(u"7"_ustr, pTabView1->GetCurrentString(0, 4)); + CPPUNIT_ASSERT(checkValues(pTabView1, 0, 1, 4, { u"4", u"5", u"3", u"7" })); // Switch to view 2 SfxLokHelper::setView(aView2.getViewID()); Scheduler::ProcessEventsToIdle(); // Check auto-filter values - CPPUNIT_ASSERT_EQUAL(u"4"_ustr, pTabView2->GetCurrentString(0, 1)); - CPPUNIT_ASSERT_EQUAL(u"5"_ustr, pTabView2->GetCurrentString(0, 2)); - CPPUNIT_ASSERT_EQUAL(u"3"_ustr, pTabView2->GetCurrentString(0, 3)); - CPPUNIT_ASSERT_EQUAL(u"7"_ustr, pTabView2->GetCurrentString(0, 4)); + CPPUNIT_ASSERT(checkValues(pTabView2, 0, 1, 4, { u"4", u"5", u"3", u"7" })); // Check what sheet we currently have selected for view 1 & 2 CPPUNIT_ASSERT_EQUAL(SCTAB(0), pTabView1->GetViewData().GetTabNumber()); @@ -88,16 +99,10 @@ CPPUNIT_TEST_FIXTURE(SheetViewTest, testSheetViewAutoFilter) CPPUNIT_ASSERT_EQUAL(SCTAB(0), pTabView2->GetViewData().GetTabNumber()); // Check view 2 - sorted - CPPUNIT_ASSERT_EQUAL(u"7"_ustr, pTabView2->GetCurrentString(0, 1)); - CPPUNIT_ASSERT_EQUAL(u"5"_ustr, pTabView2->GetCurrentString(0, 2)); - CPPUNIT_ASSERT_EQUAL(u"4"_ustr, pTabView2->GetCurrentString(0, 3)); - CPPUNIT_ASSERT_EQUAL(u"3"_ustr, pTabView2->GetCurrentString(0, 4)); + CPPUNIT_ASSERT(checkValues(pTabView2, 0, 1, 4, { u"7", u"5", u"4", u"3" })); // Check view 1 - unsorted - CPPUNIT_ASSERT_EQUAL(u"4"_ustr, pTabView1->GetCurrentString(0, 1)); - CPPUNIT_ASSERT_EQUAL(u"5"_ustr, pTabView1->GetCurrentString(0, 2)); - CPPUNIT_ASSERT_EQUAL(u"3"_ustr, pTabView1->GetCurrentString(0, 3)); - CPPUNIT_ASSERT_EQUAL(u"7"_ustr, pTabView1->GetCurrentString(0, 4)); + CPPUNIT_ASSERT(checkValues(pTabView1, 0, 1, 4, { u"4", u"5", u"3", u"7" })); } CPPUNIT_TEST_FIXTURE(SheetViewTest, testSyncValuesBetweenMainSheetAndSheetView) @@ -213,15 +218,8 @@ CPPUNIT_TEST_FIXTURE(SheetViewTest, testRemoveSheetView) Scheduler::ProcessEventsToIdle(); // Check AutoFilter values for each view - CPPUNIT_ASSERT_EQUAL(u"4"_ustr, pTabView1->GetCurrentString(0, 1)); - CPPUNIT_ASSERT_EQUAL(u"5"_ustr, pTabView1->GetCurrentString(0, 2)); - CPPUNIT_ASSERT_EQUAL(u"3"_ustr, pTabView1->GetCurrentString(0, 3)); - CPPUNIT_ASSERT_EQUAL(u"7"_ustr, pTabView1->GetCurrentString(0, 4)); - - CPPUNIT_ASSERT_EQUAL(u"4"_ustr, pTabView2->GetCurrentString(0, 1)); - CPPUNIT_ASSERT_EQUAL(u"5"_ustr, pTabView2->GetCurrentString(0, 2)); - CPPUNIT_ASSERT_EQUAL(u"3"_ustr, pTabView2->GetCurrentString(0, 3)); - CPPUNIT_ASSERT_EQUAL(u"7"_ustr, pTabView2->GetCurrentString(0, 4)); + CPPUNIT_ASSERT(checkValues(pTabView1, 0, 1, 4, { u"4", u"5", u"3", u"7" })); + CPPUNIT_ASSERT(checkValues(pTabView2, 0, 1, 4, { u"4", u"5", u"3", u"7" })); // Switch to View2 SfxLokHelper::setView(aView2.getViewID()); @@ -232,10 +230,8 @@ CPPUNIT_TEST_FIXTURE(SheetViewTest, testRemoveSheetView) Scheduler::ProcessEventsToIdle(); // Check values are sorted for view 2 - CPPUNIT_ASSERT_EQUAL(u"7"_ustr, pTabView2->GetCurrentString(0, 1)); - CPPUNIT_ASSERT_EQUAL(u"5"_ustr, pTabView2->GetCurrentString(0, 2)); - CPPUNIT_ASSERT_EQUAL(u"4"_ustr, pTabView2->GetCurrentString(0, 3)); - CPPUNIT_ASSERT_EQUAL(u"3"_ustr, pTabView2->GetCurrentString(0, 4)); + CPPUNIT_ASSERT(checkValues(pTabView1, 0, 1, 4, { u"4", u"5", u"3", u"7" })); + CPPUNIT_ASSERT(checkValues(pTabView2, 0, 1, 4, { u"7", u"5", u"4", u"3" })); // Sheet view must be present auto pSheetViewManager = pDocument->GetSheetViewManager(0); @@ -731,6 +727,86 @@ CPPUNIT_TEST_FIXTURE(SheetViewTest, testRenderStateInSheetView) CPPUNIT_ASSERT_EQUAL("S;Default"_ostr, pModelObj->getViewRenderState()); } +CPPUNIT_TEST_FIXTURE(SheetViewTest, testSyncAfterSorting_DefaultViewSort) +{ + // Two related scenarios tested: + // 1. Auto-filter is sorted in the default view, then the data is changed in a sheet view. + // In this case the sheet view is unsorted and the default view is sorted, so the data + // in the default view needs to be first unsorted so the correct cell is changed. + // 2. Continuation of scenario 1, where the default view is sorted again (ascending then + // descending order). In this case the sort orders must be combined correctly, so the + // change in the sheet view would still change the correct cell in default view. + + // Create two views, and leave the second one current. + ScModelObj* pModelObj = createDoc("SheetView_AutoFilter.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>()); + + // Setup views + ScTestViewCallback aSheetView; + ScTabViewShell* pTabViewSheetView = aSheetView.getTabViewShell(); + + SfxLokHelper::createView(); + Scheduler::ProcessEventsToIdle(); + + ScTestViewCallback aDefaultView; + ScTabViewShell* pTabViewDefaultView = aDefaultView.getTabViewShell(); + + CPPUNIT_ASSERT(pTabViewSheetView != pTabViewDefaultView); + CPPUNIT_ASSERT(aSheetView.getViewID() != aDefaultView.getViewID()); + + // Switch to Sheet View and Create + { + SfxLokHelper::setView(aSheetView.getViewID()); + Scheduler::ProcessEventsToIdle(); + + CPPUNIT_ASSERT_EQUAL(SCTAB(0), pTabViewSheetView->GetViewData().GetTabNumber()); + CPPUNIT_ASSERT_EQUAL(SCTAB(0), pTabViewDefaultView->GetViewData().GetTabNumber()); + + dispatchCommand(mxComponent, u".uno:NewSheetView"_ustr, {}); + + CPPUNIT_ASSERT_EQUAL(SCTAB(0), pTabViewSheetView->GetViewData().GetTabNumber()); + CPPUNIT_ASSERT_EQUAL(SCTAB(0), pTabViewDefaultView->GetViewData().GetTabNumber()); + } + + // Switch to Default View + { + SfxLokHelper::setView(aDefaultView.getViewID()); + Scheduler::ProcessEventsToIdle(); + + CPPUNIT_ASSERT_EQUAL(SCTAB(0), pTabViewSheetView->GetViewData().GetTabNumber()); + CPPUNIT_ASSERT_EQUAL(SCTAB(0), pTabViewDefaultView->GetViewData().GetTabNumber()); + + // Sort AutoFilter ascending + dispatchCommand(mxComponent, u".uno:SortAscending"_ustr, {}); + + CPPUNIT_ASSERT_EQUAL(SCTAB(0), pTabViewSheetView->GetViewData().GetTabNumber()); + CPPUNIT_ASSERT_EQUAL(SCTAB(0), pTabViewDefaultView->GetViewData().GetTabNumber()); + + // Check values + CPPUNIT_ASSERT(checkValues(pTabViewDefaultView, 0, 1, 4, { u"3", u"4", u"5", u"7" })); + CPPUNIT_ASSERT(checkValues(pTabViewSheetView, 0, 1, 4, { u"4", u"5", u"3", u"7" })); + + typeCharsInCell(std::string("9"), 0, 1, pTabViewDefaultView, pModelObj); + + // Check values + CPPUNIT_ASSERT(checkValues(pTabViewDefaultView, 0, 1, 4, { u"9", u"4", u"5", u"7" })); + CPPUNIT_ASSERT(checkValues(pTabViewSheetView, 0, 1, 4, { u"4", u"5", u"9", u"7" })); + + // Sort AutoFilter AGAIN descending + dispatchCommand(mxComponent, u".uno:SortDescending"_ustr, {}); + + // Check values + CPPUNIT_ASSERT(checkValues(pTabViewDefaultView, 0, 1, 4, { u"9", u"7", u"5", u"4" })); + CPPUNIT_ASSERT(checkValues(pTabViewSheetView, 0, 1, 4, { u"4", u"5", u"9", u"7" })); + + typeCharsInCell(std::string("6"), 0, 3, pTabViewDefaultView, pModelObj); + + // Check values + CPPUNIT_ASSERT(checkValues(pTabViewDefaultView, 0, 1, 4, { u"9", u"7", u"6", u"4" })); + CPPUNIT_ASSERT(checkValues(pTabViewSheetView, 0, 1, 4, { u"4", u"6", u"9", u"7" })); + } +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/core/data/SheetViewManager.cxx b/sc/source/core/data/SheetViewManager.cxx index 77d66d3102ee..a7bd35f8545f 100644 --- a/sc/source/core/data/SheetViewManager.cxx +++ b/sc/source/core/data/SheetViewManager.cxx @@ -129,6 +129,42 @@ OUString SheetViewManager::generateName() } OUString SheetViewManager::defaultViewName() { return ScResId(STR_SHEET_VIEW_DEFAULT_VIEW_NAME); } + +void SheetViewManager::addOrderIndices(std::vector<SCCOLROW> const& rOrder, SCROW nFirstRow, + SCROW nLastRow) +{ + mnFirstRow = nFirstRow; + mnLastRow = nLastRow; + if (maOrder.empty()) + { + maOrder = rOrder; + } + else + { + assert(maOrder.size() == rOrder.size()); + std::vector<SCCOLROW> newOrder(maOrder.size()); + for (size_t nIndex = 0; nIndex < maOrder.size(); ++nIndex) + { + size_t nSortedIndex = rOrder[nIndex]; + newOrder[nIndex] = maOrder[nSortedIndex - 1]; + } + maOrder = newOrder; + } +} + +SCROW SheetViewManager::unsort(SCROW nRow) +{ + if (maOrder.empty()) + return nRow; + + if (nRow >= mnFirstRow && nRow <= mnLastRow) + { + size_t index = nRow - mnFirstRow; + auto nUnsortedRow = mnFirstRow + maOrder[index] - 1; + return nUnsortedRow; + } + return nRow; +} } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx index c976be11bd33..ad928acd38a7 100644 --- a/sc/source/core/data/table3.cxx +++ b/sc/source/core/data/table3.cxx @@ -62,6 +62,7 @@ #include <drwlayer.hxx> #include <queryevaluator.hxx> #include <scopetools.hxx> +#include <SheetViewManager.hxx> #include <svl/sharedstringpool.hxx> @@ -1752,6 +1753,12 @@ void ScTable::Sort( pUndo->maDataAreaExtras.mnStartRow = nRow1; pUndo->maOrderIndices = pArray->GetOrderIndices(); } + + bool bAutoFilter = GetDoc().HasAutoFilter(rSortParam.nCol1, nRow1, GetTab()); + if (bAutoFilter) + { + GetSheetViewManager()->addOrderIndices(pArray->GetOrderIndices(), nRow1, nLastRow); + } } } else diff --git a/sc/source/ui/view/viewfunc.cxx b/sc/source/ui/view/viewfunc.cxx index ae1863d8866d..e927c114ef27 100644 --- a/sc/source/ui/view/viewfunc.cxx +++ b/sc/source/ui/view/viewfunc.cxx @@ -845,7 +845,8 @@ void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, continue; SCTAB nSheetViewTab = pSheetView->getTableNumber(); - applyText(*this, nCol, nRow, nSheetViewTab, rString, bNumFmtChanged); + SCROW nUnsortedRow = pManager->unsort(nRow); + applyText(*this, nCol, nUnsortedRow, nSheetViewTab, rString, bNumFmtChanged); } } applyText(*this, nCol, nRow, rTab, rString, bNumFmtChanged);
