sc/inc/cellsuno.hxx | 12 ++++++++ sc/qa/extras/macros-test.cxx | 57 +++++++++++++++++++++++++++++++++++++++ sc/source/ui/unoobj/cellsuno.cxx | 48 ++++++++++++++++++++++++-------- 3 files changed, 105 insertions(+), 12 deletions(-)
New commits: commit a0403b6eb25a99f6225e0f77f4b14d78f4045c9e Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Fri May 2 09:55:27 2025 +0200 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Fri May 2 16:39:08 2025 +0200 tdf#47479: Do not modify range of sheet / column / row in notifications Change-Id: I2c5afa5397e3a98806908a2f73f8d654e83fb890 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/184889 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> diff --git a/sc/inc/cellsuno.hxx b/sc/inc/cellsuno.hxx index 98ef58e9ae02..4e65c6d3e790 100644 --- a/sc/inc/cellsuno.hxx +++ b/sc/inc/cellsuno.hxx @@ -227,6 +227,9 @@ protected: SC_DLLPUBLIC virtual void SetOnePropertyValue( const SfxItemPropertyMapEntry* pEntry, const css::uno::Any& aValue ); + ScRangeList& AccessRanges() { return aRanges; } + SC_DLLPUBLIC virtual void AdjustUpdatedRanges(UpdateRefMode mode); + public: ScCellRangesBase(ScDocShell* pDocSh, const ScRange& rR); ScCellRangesBase(ScDocShell* pDocSh, ScRangeList aR); @@ -935,6 +938,9 @@ public: virtual OUString SAL_CALL getImplementationName() override; virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; + +protected: + void AdjustUpdatedRanges(UpdateRefMode mode) override; }; using ScTableColumnObj_BASE = cppu::ImplInheritanceHelper<ScCellRangeObj, @@ -966,6 +972,9 @@ public: virtual OUString SAL_CALL getImplementationName() override; virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; + +protected: + void AdjustUpdatedRanges(UpdateRefMode mode) override; }; class ScTableRowObj final : public ScCellRangeObj @@ -991,6 +1000,9 @@ public: virtual OUString SAL_CALL getImplementationName() override; virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; + +protected: + void AdjustUpdatedRanges(UpdateRefMode mode) override; }; class ScCellsObj final : public cppu::WeakImplHelper< diff --git a/sc/qa/extras/macros-test.cxx b/sc/qa/extras/macros-test.cxx index 6e2b81a01ecd..c9148f64854d 100644 --- a/sc/qa/extras/macros-test.cxx +++ b/sc/qa/extras/macros-test.cxx @@ -17,8 +17,11 @@ #include <document.hxx> #include <scitems.hxx> +#include <com/sun/star/sheet/XCellRangeAddressable.hpp> +#include <com/sun/star/sheet/XCellRangeMovement.hpp> #include <com/sun/star/sheet/XFunctionAccess.hpp> #include <com/sun/star/sheet/XSpreadsheet.hpp> +#include <com/sun/star/table/XColumnRowRange.hpp> #include <com/sun/star/script/XLibraryContainerPassword.hpp> #include <com/sun/star/drawing/XDrawPageSupplier.hpp> @@ -919,6 +922,60 @@ CPPUNIT_TEST_FIXTURE(ScMacrosTest, testTdf159412) CPPUNIT_ASSERT_EQUAL(u"1 Long/2 Double"_ustr, aReturnValue); } +CPPUNIT_TEST_FIXTURE(ScMacrosTest, testTdf47479) +{ + createScDoc(); + uno::Reference<sheet::XSpreadsheetDocument> xDoc(mxComponent, UNO_QUERY_THROW); + auto xSheets = xDoc->getSheets().queryThrow<container::XIndexAccess>(); + auto xSheet = xSheets->getByIndex(0).queryThrow<sheet::XCellRangeMovement>(); + auto xSheetAddressable = xSheet.queryThrow<sheet::XCellRangeAddressable>(); + auto xColRowRange = xSheet.queryThrow<table::XColumnRowRange>(); + auto xColAddressable + = xColRowRange->getColumns()->getByIndex(1).queryThrow<sheet::XCellRangeAddressable>(); + auto xRowAddressable + = xColRowRange->getRows()->getByIndex(1).queryThrow<sheet::XCellRangeAddressable>(); + css::table::CellRangeAddress origSheetRange = xSheetAddressable->getRangeAddress(); + css::table::CellRangeAddress origColRange = xColAddressable->getRangeAddress(); + css::table::CellRangeAddress origRowRange = xRowAddressable->getRangeAddress(); + css::table::CellRangeAddress addressToRemove(origSheetRange.Sheet, 1, 1, 1, 1); + + xSheet->removeRange(addressToRemove, css::sheet::CellDeleteMode_UP); + + auto currentRange = xSheetAddressable->getRangeAddress(); + CPPUNIT_ASSERT_EQUAL(origSheetRange.Sheet, currentRange.Sheet); + CPPUNIT_ASSERT_EQUAL(origSheetRange.StartColumn, currentRange.StartColumn); + CPPUNIT_ASSERT_EQUAL(origSheetRange.StartRow, currentRange.StartRow); + CPPUNIT_ASSERT_EQUAL(origSheetRange.EndColumn, currentRange.EndColumn); + // Without the fix, this would fail with + // - Expected: 1048575 + // - Actual : 0 + CPPUNIT_ASSERT_EQUAL(origSheetRange.EndRow, currentRange.EndRow); + + xSheet->removeRange(addressToRemove, css::sheet::CellDeleteMode_LEFT); + + currentRange = xColAddressable->getRangeAddress(); + CPPUNIT_ASSERT_EQUAL(origColRange.Sheet, currentRange.Sheet); + CPPUNIT_ASSERT_EQUAL(origColRange.StartColumn, currentRange.StartColumn); + // Without the fix, this would fail with + // - Expected: 0 + // - Actual : 2 + CPPUNIT_ASSERT_EQUAL(origColRange.StartRow, currentRange.StartRow); + CPPUNIT_ASSERT_EQUAL(origColRange.EndColumn, currentRange.EndColumn); + CPPUNIT_ASSERT_EQUAL(origColRange.EndRow, currentRange.EndRow); + + xSheet->removeRange(origColRange, css::sheet::CellDeleteMode_UP); + + currentRange = xRowAddressable->getRangeAddress(); + CPPUNIT_ASSERT_EQUAL(origRowRange.Sheet, currentRange.Sheet); + // Without the fix, this would fail with + // - Expected: 0 + // - Actual : 2 + CPPUNIT_ASSERT_EQUAL(origRowRange.StartColumn, currentRange.StartColumn); + CPPUNIT_ASSERT_EQUAL(origRowRange.StartRow, currentRange.StartRow); + CPPUNIT_ASSERT_EQUAL(origRowRange.EndColumn, currentRange.EndColumn); + CPPUNIT_ASSERT_EQUAL(origRowRange.EndRow, currentRange.EndRow); +} + ScMacrosTest::ScMacrosTest() : ScModelTestBase(u"/sc/qa/extras/testdocuments"_ustr) { diff --git a/sc/source/ui/unoobj/cellsuno.cxx b/sc/source/ui/unoobj/cellsuno.cxx index a7818ad31b9e..b86f03e6df06 100644 --- a/sc/source/ui/unoobj/cellsuno.cxx +++ b/sc/source/ui/unoobj/cellsuno.cxx @@ -1475,6 +1475,8 @@ const ScMarkData* ScCellRangesBase::GetMarkData() return pMarkData.get(); } +void ScCellRangesBase::AdjustUpdatedRanges(UpdateRefMode) {} + void ScCellRangesBase::Notify( SfxBroadcaster&, const SfxHint& rHint ) { const SfxHintId nId = rHint.GetId(); @@ -1546,18 +1548,7 @@ void ScCellRangesBase::Notify( SfxBroadcaster&, const SfxHint& rHint ) if ( aRanges.UpdateReference( pRefHint->GetMode(), &rDoc, pRefHint->GetRange(), pRefHint->GetDx(), pRefHint->GetDy(), pRefHint->GetDz() ) ) { - if ( pRefHint->GetMode() == URM_INSDEL - && aRanges.size() == 1 - && dynamic_cast<ScTableSheetObj*>(this) - ) - { - // #101755#; the range size of a sheet does not change - ScRange & rR = aRanges.front(); - rR.aStart.SetCol(0); - rR.aStart.SetRow(0); - rR.aEnd.SetCol(rDoc.MaxCol()); - rR.aEnd.SetRow(rDoc.MaxRow()); - } + AdjustUpdatedRanges(pRefHint->GetMode()); RefChanged(); // any change of the range address is broadcast to value (modify) listeners @@ -6392,6 +6383,17 @@ SCTAB ScTableSheetObj::GetTab_Impl() const return 0; } +void ScTableSheetObj::AdjustUpdatedRanges(UpdateRefMode mode) +{ + if (mode == URM_INSDEL) + { + ScRangeList& rRanges = AccessRanges(); + // #101755#, tdf#47479: the range of a sheet does not change + rRanges.RemoveAll(); + rRanges.push_back(GetRange()); + } +} + // former XSheet uno::Reference<table::XTableCharts> SAL_CALL ScTableSheetObj::getCharts() @@ -8195,6 +8197,17 @@ const SfxItemPropertyMap& ScTableColumnObj::GetItemPropertyMap() return pColPropSet->getPropertyMap(); } +void ScTableColumnObj::AdjustUpdatedRanges(UpdateRefMode mode) +{ + if (mode == URM_INSDEL) + { + ScRangeList& rRanges = AccessRanges(); + // tdf#47479: the range of a column does not change + rRanges.RemoveAll(); + rRanges.push_back(GetRange()); + } +} + ScTableRowObj::ScTableRowObj(ScDocShell* pDocSh, SCROW nRow, SCTAB nTab) : ScCellRangeObj( pDocSh, ScRange(0,nRow,nTab, pDocSh->GetDocument().MaxCol(),nRow,nTab) ), pRowPropSet(lcl_GetRowPropertySet()) @@ -8344,6 +8357,17 @@ const SfxItemPropertyMap& ScTableRowObj::GetItemPropertyMap() return pRowPropSet->getPropertyMap(); } +void ScTableRowObj::AdjustUpdatedRanges(UpdateRefMode mode) +{ + if (mode == URM_INSDEL) + { + ScRangeList& rRanges = AccessRanges(); + // tdf#47479: the range of a row does not change + rRanges.RemoveAll(); + rRanges.push_back(GetRange()); + } +} + ScCellsObj::ScCellsObj(ScDocShell* pDocSh, ScRangeList aR) : pDocShell( pDocSh ), aRanges(std::move( aR ))