sc/qa/unit/tiledrendering/SheetViewTest.cxx | 129 ++++++++++++++++++++ sc/source/ui/docshell/SheetViewOperationsTester.cxx | 34 +++++ sc/source/ui/inc/SheetViewOperationsTester.hxx | 2 sc/source/ui/operation/DeleteCellOperation.cxx | 5 sc/source/ui/view/viewfunc.cxx | 2 5 files changed, 169 insertions(+), 3 deletions(-)
New commits: commit 6a87e40ab9f8baa36607d73e47a0dccd00523503 Author: Tomaž Vajngerl <[email protected]> AuthorDate: Tue Feb 3 15:29:31 2026 +0900 Commit: Miklos Vajna <[email protected]> CommitDate: Fri Feb 13 14:45:11 2026 +0100 sc: Implement sync of sheet views with delete cell operation Implement sync between default view and sheet view by changing (deleting in this case) the default view and overwriting the sheet view data (for all sheet views currently registered) from the default view. Change-Id: I023d7295fa8ffebe079ef40cbe67607b52f83740 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/198734 Reviewed-by: Miklos Vajna <[email protected]> Tested-by: Jenkins CollaboraOffice <[email protected]> diff --git a/sc/qa/unit/tiledrendering/SheetViewTest.cxx b/sc/qa/unit/tiledrendering/SheetViewTest.cxx index 0c45fae4bb43..7bd56d6ed019 100644 --- a/sc/qa/unit/tiledrendering/SheetViewTest.cxx +++ b/sc/qa/unit/tiledrendering/SheetViewTest.cxx @@ -63,6 +63,30 @@ protected: return aString; } + + static OUString getValues(ScDocument* pDocument, SCCOL nCol, SCROW nStartRow, SCROW nEndRow, + SCTAB nTab) + { + OUString aString; + + size_t nSize = nEndRow - nStartRow + 1; + + bool bFirst = true; + + for (size_t nIndex = 0; nIndex < nSize; nIndex++) + { + OUString aValue = pDocument->GetString({ nCol, SCROW(nStartRow + nIndex), nTab }); + if (bFirst) + { + bFirst = false; + aString = u"\""_ustr + aValue + u"\""_ustr; + } + else + aString += u", \""_ustr + aValue + u"\""_ustr; + } + + return aString; + } }; /** Check auto-filter sorting. @@ -968,6 +992,111 @@ CPPUNIT_TEST_FIXTURE(SheetViewTest, testSyncAfterSorting_SortInDefaultAndSheetVi } } +/** Test class that contains methods commonly used for testing sync of sheet views. */ +class SyncTest : public SheetViewTest +{ +public: + void tearDown() override + { + maSheetView = std::nullopt; + maDefaultView = std::nullopt; + SheetViewTest::tearDown(); + } + +protected: + std::optional<ScTestViewCallback> maSheetView; + std::optional<ScTestViewCallback> maDefaultView; + ScTabViewShell* mpTabViewSheetView = nullptr; + ScTabViewShell* mpTabViewDefaultView = nullptr; + + void setupViews() + { + maSheetView.emplace(); + mpTabViewSheetView = maSheetView->getTabViewShell(); + + SfxLokHelper::createView(); + Scheduler::ProcessEventsToIdle(); + + maDefaultView.emplace(); + mpTabViewDefaultView = maDefaultView->getTabViewShell(); + + CPPUNIT_ASSERT(mpTabViewSheetView != mpTabViewDefaultView); + CPPUNIT_ASSERT(maSheetView->getViewID() != maDefaultView->getViewID()); + } + + void switchToSheetView() + { + SfxLokHelper::setView(maSheetView->getViewID()); + Scheduler::ProcessEventsToIdle(); + } + + void switchToDefaultView() + { + SfxLokHelper::setView(maDefaultView->getViewID()); + Scheduler::ProcessEventsToIdle(); + } +}; + +CPPUNIT_TEST_FIXTURE(SyncTest, testSync_DefaultView_DeleteCellOperation) +{ + // 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(); + + // Switch to Sheet View and Create + { + switchToSheetView(); + dispatchCommand(mxComponent, u".uno:NewSheetView"_ustr, {}); + } + + // Switch to Default View + { + switchToDefaultView(); + + dispatchCommand(mxComponent, u".uno:GoToCell"_ustr, + comphelper::InitPropertySequence({ { "ToPoint", uno::Any(u"A3"_ustr) } })); + + dispatchCommand(mxComponent, u".uno:ClearContents"_ustr, {}); + } + + 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)); +} + +CPPUNIT_TEST_FIXTURE(SyncTest, testSync_SheetView_DeleteCellOperation) +{ + // 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(); + + // Switch to Sheet View and Create + { + switchToSheetView(); + + dispatchCommand(mxComponent, u".uno:NewSheetView"_ustr, {}); + + dispatchCommand(mxComponent, u".uno:GoToCell"_ustr, + comphelper::InitPropertySequence({ { "ToPoint", uno::Any(u"A3"_ustr) } })); + + dispatchCommand(mxComponent, u".uno:ClearContents"_ustr, {}); + } + + 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)); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/docshell/SheetViewOperationsTester.cxx b/sc/source/ui/docshell/SheetViewOperationsTester.cxx index 91f6cd0e4c11..37593c7382ab 100644 --- a/sc/source/ui/docshell/SheetViewOperationsTester.cxx +++ b/sc/source/ui/docshell/SheetViewOperationsTester.cxx @@ -137,6 +137,40 @@ constexpr bool doesUnsyncSheetView(OperationType eOperationType) } // end anonymous namespace +bool SheetViewOperationsTester::doesUnsync(OperationType eOperationType) +{ + bool bOperationAllowed = eOperationType == OperationType::EnterData + || eOperationType == OperationType::SetNormalString; + return !bOperationAllowed; +} + +void SheetViewOperationsTester::sync() +{ + if (!mpViewData) + { + return; + } + + auto& rDocument = mpViewData->GetDocument(); + SCTAB nTab = mpViewData->GetTabNumber(); + + if (rDocument.IsSheetViewHolder(nTab)) + { + return; + } + + std::shared_ptr<sc::SheetViewManager> pManager = rDocument.GetSheetViewManager(nTab); + + if (!pManager->isEmpty()) + { + for (auto const& pSheetView : pManager->getSheetViews()) + { + SCTAB nSheetViewTab = pSheetView->getTableNumber(); + rDocument.OverwriteContent(nTab, nSheetViewTab); + } + } +} + bool SheetViewOperationsTester::check(OperationType eOperationType) const { if (!mpViewData) diff --git a/sc/source/ui/inc/SheetViewOperationsTester.hxx b/sc/source/ui/inc/SheetViewOperationsTester.hxx index 1c25fba0e2ed..b0e3281b308b 100644 --- a/sc/source/ui/inc/SheetViewOperationsTester.hxx +++ b/sc/source/ui/inc/SheetViewOperationsTester.hxx @@ -77,7 +77,9 @@ public: { } + static bool doesUnsync(OperationType eOperationType); bool check(OperationType eOperationType) const; + void sync(); }; } diff --git a/sc/source/ui/operation/DeleteCellOperation.cxx b/sc/source/ui/operation/DeleteCellOperation.cxx index 1eefcf4479d1..b07decd047e4 100644 --- a/sc/source/ui/operation/DeleteCellOperation.cxx +++ b/sc/source/ui/operation/DeleteCellOperation.cxx @@ -44,8 +44,6 @@ bool DeleteCellOperation::runImplementation() mbRecord = false; sc::SheetViewOperationsTester aSheetViewTester(ScDocShell::GetViewData()); - if (!aSheetViewTester.check(meType)) - return false; ScEditableTester aTester = ScEditableTester::CreateAndTestSelectedBlock( rDoc, rPos.Col(), rPos.Row(), rPos.Col(), rPos.Row(), rMark); @@ -102,6 +100,9 @@ bool DeleteCellOperation::runImplementation() mrDocShell.PostPaint(rPos.Col(), rPos.Row(), rPos.Tab(), rPos.Col(), rPos.Row(), rPos.Tab(), PaintPartFlags::Grid, nExtFlags, nBefore); + if (sc::SheetViewOperationsTester::doesUnsync(meType)) + aSheetViewTester.sync(); + aModificator.SetDocumentModified(); return true; diff --git a/sc/source/ui/view/viewfunc.cxx b/sc/source/ui/view/viewfunc.cxx index 23d4e1b718b3..91cb4f23ce5b 100644 --- a/sc/source/ui/view/viewfunc.cxx +++ b/sc/source/ui/view/viewfunc.cxx @@ -2346,7 +2346,7 @@ void ScViewFunc::DeleteContents( InsertDeleteFlags nFlags ) { aMarkRange.aStart.SetCol(GetViewData().GetCurX()); aMarkRange.aStart.SetRow(GetViewData().GetCurY()); - aMarkRange.aStart.SetTab(GetViewData().CurrentTabForData()); + aMarkRange.aStart.SetTab(GetViewData().GetTabNumber()); aMarkRange.aEnd = aMarkRange.aStart; if ( rDoc.HasAttrib( aMarkRange, HasAttrFlags::Merged ) ) {
