sc/qa/unit/tiledrendering/SheetViewTest.cxx | 150 ++++++++-- sc/qa/unit/tiledrendering/data/SheetView_AutoFilter_Formulas.ods |binary sc/source/ui/docshell/SheetViewOperationsTester.cxx | 5 sc/source/ui/inc/SheetViewOperationsTester.hxx | 1 sc/source/ui/inc/operation/Operation.hxx | 2 sc/source/ui/operation/Operation.cxx | 11 sc/source/ui/operation/SetEditTextOperation.cxx | 22 - sc/source/ui/operation/SetFormulaOperation.cxx | 22 - sc/source/ui/operation/SetStringOperation.cxx | 22 - sc/source/ui/operation/SetValueOperation.cxx | 22 - sc/source/ui/view/viewfunc.cxx | 22 - 11 files changed, 190 insertions(+), 89 deletions(-)
New commits: commit b5b8db699e03bb9c0a44a37b1e76c088ca940794 Author: Tomaž Vajngerl <[email protected]> AuthorDate: Wed Feb 11 15:59:39 2026 +0900 Commit: Miklos Vajna <[email protected]> CommitDate: Mon Feb 16 13:57:37 2026 +0100 sc: Implement sync operations for set operations, logging Implemented syncing for various set operations (most notably SetFormulaOperation), which is used when we set a value to a cell. Added logging when an operation is executed and log the result of the operation at the end. This can be useful to see what is happening (logged) when an operation is run. Change-Id: I3fc56d55d19be3e00e75a5d662c337273a7fb82b Reviewed-on: https://gerrit.libreoffice.org/c/core/+/199182 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 b2db66c40b8c..b7f412882343 100644 --- a/sc/qa/unit/tiledrendering/SheetViewTest.cxx +++ b/sc/qa/unit/tiledrendering/SheetViewTest.cxx @@ -87,6 +87,75 @@ protected: return aString; } + + void gotoCell(std::u16string_view aCellAddress) + { + dispatchCommand( + mxComponent, u".uno:GoToCell"_ustr, + comphelper::InitPropertySequence({ { "ToPoint", uno::Any(OUString(aCellAddress)) } })); + } + + void createNewSheetViewInCurrentView() + { + dispatchCommand(mxComponent, u".uno:NewSheetView"_ustr, {}); + } + + void sortAscendingForCell(std::u16string_view aCellAddress) + { + gotoCell(aCellAddress); + dispatchCommand(mxComponent, u".uno:SortAscending"_ustr, {}); + } + + void sortDescendingForCell(std::u16string_view aCellAddress) + { + gotoCell(aCellAddress); + dispatchCommand(mxComponent, u".uno:SortDescending"_ustr, {}); + } +}; + +/** 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(); + } }; /** Check auto-filter sorting. @@ -1018,50 +1087,71 @@ CPPUNIT_TEST_FIXTURE(SheetViewTest, testSyncAfterSorting_SortInDefaultAndSheetVi } } -/** Test class that contains methods commonly used for testing sync of sheet views. */ -class SyncTest : public SheetViewTest +CPPUNIT_TEST_FIXTURE(SyncTest, testSyncAfterSorting_SortInDefaultAndSheetView_Formulas) { -public: - void tearDown() override - { - maSheetView = std::nullopt; - maDefaultView = std::nullopt; - SheetViewTest::tearDown(); - } + // Input is an test file that uses formulas instead of values. + // This test checks if the sorting of the document behaves the same + // for formulas as values. + ScModelObj* pModelObj = createDoc("SheetView_AutoFilter_Formulas.ods"); + pModelObj->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>()); -protected: - std::optional<ScTestViewCallback> maSheetView; - std::optional<ScTestViewCallback> maDefaultView; - ScTabViewShell* mpTabViewSheetView = nullptr; - ScTabViewShell* mpTabViewDefaultView = nullptr; + setupViews(); - void setupViews() + // Switch to Sheet View and Create { - maSheetView.emplace(); - mpTabViewSheetView = maSheetView->getTabViewShell(); + switchToSheetView(); - SfxLokHelper::createView(); - Scheduler::ProcessEventsToIdle(); + createNewSheetViewInCurrentView(); - maDefaultView.emplace(); - mpTabViewDefaultView = maDefaultView->getTabViewShell(); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7", u"1", u"6" }), + getValues(mpTabViewDefaultView, 0, 1, 6)); - CPPUNIT_ASSERT(mpTabViewSheetView != mpTabViewDefaultView); - CPPUNIT_ASSERT(maSheetView->getViewID() != maDefaultView->getViewID()); + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7", u"1", u"6" }), + getValues(mpTabViewSheetView, 0, 1, 6)); + + // Sort AutoFilter + sortAscendingForCell(u"A1"); + + // No change to sorted values + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"4", u"5", u"3", u"7", u"1", u"6" }), + getValues(mpTabViewDefaultView, 0, 1, 6)); + // Expect sorted values for the sheet view + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"1", u"3", u"4", u"5", u"6", u"7" }), + getValues(mpTabViewSheetView, 0, 1, 6)); } - void switchToSheetView() + // Switch to Default view and sort { - SfxLokHelper::setView(maSheetView->getViewID()); - Scheduler::ProcessEventsToIdle(); + switchToDefaultView(); + + // Sort AutoFilter + sortDescendingForCell(u"A1"); + + // Expect sorted values for the default view + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"6", u"5", u"4", u"3", u"1" }), + getValues(mpTabViewDefaultView, 0, 1, 6)); + + // Previously sorted values - no change + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"1", u"3", u"4", u"5", u"6", u"7" }), + getValues(mpTabViewSheetView, 0, 1, 6)); } - void switchToDefaultView() + // Switch to Sheet view and set a value { - SfxLokHelper::setView(maDefaultView->getViewID()); - Scheduler::ProcessEventsToIdle(); + switchToSheetView(); + + // Change "4" to "44" + typeCharsInCell(std::string("=40+4"), 0, 3, mpTabViewSheetView, pModelObj); + + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"7", u"6", u"5", u"44", u"3", u"1" }), + getValues(mpTabViewDefaultView, 0, 1, 6)); + + // Result in { u"1", u"3", u"4", u"5", u"6", u"7" } but we resort the sheet view immediately + // so we get { u"1", u"3", u"5", u"6", u"7", u"44" }. + CPPUNIT_ASSERT_EQUAL(expectedValues({ u"1", u"3", u"5", u"6", u"7", u"44" }), + getValues(mpTabViewSheetView, 0, 1, 6)); } -}; +} CPPUNIT_TEST_FIXTURE(SyncTest, testSync_DefaultView_DeleteCellOperation) { diff --git a/sc/qa/unit/tiledrendering/data/SheetView_AutoFilter_Formulas.ods b/sc/qa/unit/tiledrendering/data/SheetView_AutoFilter_Formulas.ods new file mode 100644 index 000000000000..f36104bf3079 Binary files /dev/null and b/sc/qa/unit/tiledrendering/data/SheetView_AutoFilter_Formulas.ods differ diff --git a/sc/source/ui/docshell/SheetViewOperationsTester.cxx b/sc/source/ui/docshell/SheetViewOperationsTester.cxx index dc7c39ce58d9..2ef2c6b986a5 100644 --- a/sc/source/ui/docshell/SheetViewOperationsTester.cxx +++ b/sc/source/ui/docshell/SheetViewOperationsTester.cxx @@ -255,5 +255,10 @@ bool SheetViewOperationsTester::check(OperationType eOperationType) const return true; } + +std::string_view SheetViewOperationsTester::operationName(OperationType eType) +{ + return getOperationName(eType); +} } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/SheetViewOperationsTester.hxx b/sc/source/ui/inc/SheetViewOperationsTester.hxx index 898d7d735299..da97348a7850 100644 --- a/sc/source/ui/inc/SheetViewOperationsTester.hxx +++ b/sc/source/ui/inc/SheetViewOperationsTester.hxx @@ -82,6 +82,7 @@ public: } static bool doesUnsync(OperationType eOperationType); + static std::string_view operationName(OperationType eType); bool check(OperationType eOperationType) const; void sync(); }; diff --git a/sc/source/ui/inc/operation/Operation.hxx b/sc/source/ui/inc/operation/Operation.hxx index 596a7dbf26c7..0d98e1b2048e 100644 --- a/sc/source/ui/inc/operation/Operation.hxx +++ b/sc/source/ui/inc/operation/Operation.hxx @@ -46,7 +46,7 @@ public: { } - bool run() { return runImplementation(); } + bool run(); bool checkSheetViewProtection(); /** Convert address from a sheet view to the address in default view, take sorting into account. */ diff --git a/sc/source/ui/operation/Operation.cxx b/sc/source/ui/operation/Operation.cxx index 579c194e7393..9abbf62e862e 100644 --- a/sc/source/ui/operation/Operation.cxx +++ b/sc/source/ui/operation/Operation.cxx @@ -15,6 +15,7 @@ #include <viewdata.hxx> #include <SheetViewManager.hxx> #include <SheetView.hxx> +#include <sal/log.hxx> namespace sc { @@ -151,6 +152,16 @@ bool Operation::checkSheetViewProtection() sc::SheetViewOperationsTester aSheetViewTester(ScDocShell::GetViewData()); return aSheetViewTester.check(meType); } + +bool Operation::run() +{ + SAL_INFO("sc", + "Running operation '" << SheetViewOperationsTester::operationName(meType) << "'."); + bool bResult = runImplementation(); + SAL_INFO("sc", "Operation '" << SheetViewOperationsTester::operationName(meType) + << (bResult ? "' succeded." : "' failed.")); + return bResult; +} } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/operation/SetEditTextOperation.cxx b/sc/source/ui/operation/SetEditTextOperation.cxx index 5f97070192cd..9b2f3175ec65 100644 --- a/sc/source/ui/operation/SetEditTextOperation.cxx +++ b/sc/source/ui/operation/SetEditTextOperation.cxx @@ -35,38 +35,42 @@ SetEditTextOperation::SetEditTextOperation(ScDocFunc& rDocFunc, ScDocShell& rDoc bool SetEditTextOperation::runImplementation() { - ScAddress const& rPos = mrPosition; + ScAddress aPosition = convertAddress(mrPosition); + + sc::SheetViewOperationsTester aSheetViewTester(ScDocShell::GetViewData()); ScDocShellModificator aModificator(mrDocShell); ScDocument& rDoc = mrDocShell.GetDocument(); bool bUndo = rDoc.IsUndoEnabled(); - bool bHeight = rDoc.HasAttrib(ScRange(rPos), HasAttrFlags::NeedHeight); + bool bHeight = rDoc.HasAttrib(ScRange(aPosition), HasAttrFlags::NeedHeight); ScCellValue aOldVal; if (bUndo) - aOldVal.assign(rDoc, rPos); + aOldVal.assign(rDoc, aPosition); - rDoc.SetEditText(rPos, mrEditObject.Clone()); + rDoc.SetEditText(aPosition, mrEditObject.Clone()); if (bUndo) { SfxUndoManager* pUndoMgr = mrDocShell.GetUndoManager(); ScCellValue aNewVal; - aNewVal.assign(rDoc, rPos); + aNewVal.assign(rDoc, aPosition); pUndoMgr->AddUndoAction( - std::make_unique<ScUndoSetCell>(&mrDocShell, rPos, aOldVal, aNewVal)); + std::make_unique<ScUndoSetCell>(&mrDocShell, aPosition, aOldVal, aNewVal)); } + aSheetViewTester.sync(); + if (bHeight) - mrDocFunc.AdjustRowHeight(ScRange(rPos), true, mbApi); + mrDocFunc.AdjustRowHeight(ScRange(aPosition), true, mbApi); - mrDocShell.PostPaintCell(rPos); + mrDocShell.PostPaintCell(aPosition); aModificator.SetDocumentModified(); // #103934#; notify editline and cell in edit mode if (mbApi) - mrDocFunc.NotifyInputHandler(rPos); + mrDocFunc.NotifyInputHandler(aPosition); return true; } diff --git a/sc/source/ui/operation/SetFormulaOperation.cxx b/sc/source/ui/operation/SetFormulaOperation.cxx index 01b6f4d2440c..2eb844283cb9 100644 --- a/sc/source/ui/operation/SetFormulaOperation.cxx +++ b/sc/source/ui/operation/SetFormulaOperation.cxx @@ -36,22 +36,24 @@ SetFormulaOperation::SetFormulaOperation(ScDocFunc& rDocFunc, ScDocShell& rDocSh bool SetFormulaOperation::runImplementation() { - ScAddress const& rPos = mrPosition; + ScAddress aPosition = convertAddress(mrPosition); ScFormulaCell* pCell(mpFormulaCell); std::unique_ptr<ScFormulaCell> xCell(mpFormulaCell); + sc::SheetViewOperationsTester aSheetViewTester(ScDocShell::GetViewData()); + ScDocShellModificator aModificator(mrDocShell); ScDocument& rDoc = mrDocShell.GetDocument(); bool bUndo = rDoc.IsUndoEnabled(); - bool bHeight = rDoc.HasAttrib(ScRange(rPos), HasAttrFlags::NeedHeight); + bool bHeight = rDoc.HasAttrib(ScRange(aPosition), HasAttrFlags::NeedHeight); ScCellValue aOldVal; if (bUndo) - aOldVal.assign(rDoc, rPos); + aOldVal.assign(rDoc, aPosition); - pCell = rDoc.SetFormulaCell(rPos, xCell.release()); + pCell = rDoc.SetFormulaCell(aPosition, xCell.release()); // For performance reasons API calls may disable calculation while // operating and recalculate once when done. If through user interaction @@ -69,20 +71,22 @@ bool SetFormulaOperation::runImplementation() { SfxUndoManager* pUndoMgr = mrDocShell.GetUndoManager(); ScCellValue aNewVal; - aNewVal.assign(rDoc, rPos); + aNewVal.assign(rDoc, aPosition); pUndoMgr->AddUndoAction( - std::make_unique<ScUndoSetCell>(&mrDocShell, rPos, aOldVal, aNewVal)); + std::make_unique<ScUndoSetCell>(&mrDocShell, aPosition, aOldVal, aNewVal)); } + aSheetViewTester.sync(); + if (bHeight) - mrDocFunc.AdjustRowHeight(ScRange(rPos), true, mbApi); + mrDocFunc.AdjustRowHeight(ScRange(aPosition), true, mbApi); - mrDocShell.PostPaintCell(rPos); + mrDocShell.PostPaintCell(aPosition); aModificator.SetDocumentModified(); // #103934#; notify editline and cell in edit mode if (mbApi) - mrDocFunc.NotifyInputHandler(rPos); + mrDocFunc.NotifyInputHandler(aPosition); return true; } diff --git a/sc/source/ui/operation/SetStringOperation.cxx b/sc/source/ui/operation/SetStringOperation.cxx index ec74cbd7750d..050492df5179 100644 --- a/sc/source/ui/operation/SetStringOperation.cxx +++ b/sc/source/ui/operation/SetStringOperation.cxx @@ -34,40 +34,44 @@ SetStringOperation::SetStringOperation(ScDocFunc& rDocFunc, ScDocShell& rDocShel bool SetStringOperation::runImplementation() { - ScAddress const& rPos = mrPosition; + ScAddress aPosition = convertAddress(mrPosition); + sc::SheetViewOperationsTester aSheetViewTester(ScDocShell::GetViewData()); ScDocShellModificator aModificator(mrDocShell); + ScDocument& rDoc = mrDocShell.GetDocument(); bool bUndo = rDoc.IsUndoEnabled(); - bool bHeight = rDoc.HasAttrib(ScRange(rPos), HasAttrFlags::NeedHeight); + bool bHeight = rDoc.HasAttrib(ScRange(aPosition), HasAttrFlags::NeedHeight); ScCellValue aOldVal; if (bUndo) - aOldVal.assign(rDoc, rPos); + aOldVal.assign(rDoc, aPosition); ScSetStringParam aParam; aParam.setTextInput(); - rDoc.SetString(rPos, mrString, &aParam); + rDoc.SetString(aPosition, mrString, &aParam); if (bUndo) { SfxUndoManager* pUndoMgr = mrDocShell.GetUndoManager(); ScCellValue aNewVal; - aNewVal.assign(rDoc, rPos); + aNewVal.assign(rDoc, aPosition); pUndoMgr->AddUndoAction( - std::make_unique<ScUndoSetCell>(&mrDocShell, rPos, aOldVal, aNewVal)); + std::make_unique<ScUndoSetCell>(&mrDocShell, aPosition, aOldVal, aNewVal)); } + aSheetViewTester.sync(); + if (bHeight) - mrDocFunc.AdjustRowHeight(ScRange(rPos), true, mbApi); + mrDocFunc.AdjustRowHeight(ScRange(aPosition), true, mbApi); - mrDocShell.PostPaintCell(rPos); + mrDocShell.PostPaintCell(aPosition); aModificator.SetDocumentModified(); // #103934#; notify editline and cell in edit mode if (mbApi) - mrDocFunc.NotifyInputHandler(rPos); + mrDocFunc.NotifyInputHandler(aPosition); return true; } diff --git a/sc/source/ui/operation/SetValueOperation.cxx b/sc/source/ui/operation/SetValueOperation.cxx index a0250cc6ea92..a58f45973ad5 100644 --- a/sc/source/ui/operation/SetValueOperation.cxx +++ b/sc/source/ui/operation/SetValueOperation.cxx @@ -33,37 +33,41 @@ SetValueOperation::SetValueOperation(ScDocFunc& rDocFunc, ScDocShell& rDocShell, bool SetValueOperation::runImplementation() { - ScAddress const& rPos = mrPosition; + ScAddress aPosition = convertAddress(mrPosition); + + sc::SheetViewOperationsTester aSheetViewTester(ScDocShell::GetViewData()); ScDocShellModificator aModificator(mrDocShell); ScDocument& rDoc = mrDocShell.GetDocument(); bool bUndo = rDoc.IsUndoEnabled(); - bool bHeight = rDoc.HasAttrib(ScRange(rPos), HasAttrFlags::NeedHeight); + bool bHeight = rDoc.HasAttrib(ScRange(aPosition), HasAttrFlags::NeedHeight); ScCellValue aOldVal; if (bUndo) - aOldVal.assign(rDoc, rPos); + aOldVal.assign(rDoc, aPosition); - rDoc.SetValue(rPos, mfValue); + rDoc.SetValue(aPosition, mfValue); if (bUndo) { SfxUndoManager* pUndoMgr = mrDocShell.GetUndoManager(); ScCellValue aNewVal; - aNewVal.assign(rDoc, rPos); + aNewVal.assign(rDoc, aPosition); pUndoMgr->AddUndoAction( - std::make_unique<ScUndoSetCell>(&mrDocShell, rPos, aOldVal, aNewVal)); + std::make_unique<ScUndoSetCell>(&mrDocShell, aPosition, aOldVal, aNewVal)); } + aSheetViewTester.sync(); + if (bHeight) - mrDocFunc.AdjustRowHeight(ScRange(rPos), true, mbApi); + mrDocFunc.AdjustRowHeight(ScRange(aPosition), true, mbApi); - mrDocShell.PostPaintCell(rPos); + mrDocShell.PostPaintCell(aPosition); aModificator.SetDocumentModified(); // #103934#; notify editline and cell in edit mode if (mbApi) - mrDocFunc.NotifyInputHandler(rPos); + mrDocFunc.NotifyInputHandler(aPosition); return true; } diff --git a/sc/source/ui/view/viewfunc.cxx b/sc/source/ui/view/viewfunc.cxx index a3247278c3d8..b1e0f5fc5114 100644 --- a/sc/source/ui/view/viewfunc.cxx +++ b/sc/source/ui/view/viewfunc.cxx @@ -808,29 +808,7 @@ void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, if ( bFormula ) { - SCTAB nSelectedTab = aMark.GetFirstSelected(); applyFormulaToCell(*this, nCol, nRow, nTab, rString, pData, xModificator, aMark, bMatrixExpand, bRecord, bNumFmtChanged); - if (rDoc.IsSheetViewHolder(nSelectedTab)) - return; - - auto pManager = rDoc.GetSheetViewManager(nSelectedTab); - - for (auto const& pSheetView : pManager->getSheetViews()) - { - if (!pSheetView) - continue; - - SCTAB nSheetViewTab = pSheetView->getTableNumber(); - - ScMarkData aSheetViewMark(rDoc.GetSheetLimits()); - aSheetViewMark.SelectTable(nSheetViewTab, false); - ScRange aSheetViewRange(aMark.GetMarkArea()); - aSheetViewRange.aStart.SetTab(nSheetViewTab); - aSheetViewRange.aEnd.SetTab(nSheetViewTab); - aSheetViewMark.SetMarkArea(aSheetViewRange); - - applyFormulaToCell(*this, nCol, nRow, nSheetViewTab, rString, pData, xModificator, aSheetViewMark, bMatrixExpand, bRecord, bNumFmtChanged); - } } else {
