tdf#97601 sw: don't mark an already modified chart as modified

Regression from commit e2b260fc98 (sw: let
layout not mark embedded object as modified, 2014-06-03), an infinite
loop was caused by:

1) SwDoc::SetOLEObjModified() triggering the maOLEModifiedIdle Idle
2) which at the end called SwWrtShell::CalcAndSetScale()
3) which at the end called chart::ChartModel::setModified()
4) where chart code called back into SwDoc::SetOLEObjModified() via the
modification listener, and this happened again and again.

The original fix wanted to avoid marking the document as modified
without a user interaction, so fix the bug by only calling setModified()
if it prevents a not-modified -> modified transition. This keeps the
original bug fixed, but prevents the infinite loop, that is always a
modified -> modified transition.

Change-Id: I3b56a91afaacd3e0b7cb646a492fd15f1b5168ee
This commit is contained in:
Miklos Vajna
2016-03-08 09:03:39 +01:00
parent fcd8844cb0
commit 078c00e3a3
3 changed files with 30 additions and 2 deletions

Binary file not shown.

View File

@@ -81,6 +81,8 @@
#include "com/sun/star/beans/PropertyAttribute.hpp" #include "com/sun/star/beans/PropertyAttribute.hpp"
#include "com/sun/star/text/XTextField.hpp" #include "com/sun/star/text/XTextField.hpp"
#include "com/sun/star/text/TextMarkupType.hpp" #include "com/sun/star/text/TextMarkupType.hpp"
#include <com/sun/star/chart2/data/XDataSource.hpp>
#include <com/sun/star/document/XEmbeddedObjectSupplier2.hpp>
#include <osl/file.hxx> #include <osl/file.hxx>
#include <paratr.hxx> #include <paratr.hxx>
#include <drawfont.hxx> #include <drawfont.hxx>
@@ -154,6 +156,7 @@ public:
void testTdf80663(); void testTdf80663();
void testTdf57197(); void testTdf57197();
void testTdf90808(); void testTdf90808();
void testTdf97601();
void testTdf75137(); void testTdf75137();
void testTdf83798(); void testTdf83798();
void testTdf89714(); void testTdf89714();
@@ -243,6 +246,7 @@ public:
CPPUNIT_TEST(testTdf80663); CPPUNIT_TEST(testTdf80663);
CPPUNIT_TEST(testTdf57197); CPPUNIT_TEST(testTdf57197);
CPPUNIT_TEST(testTdf90808); CPPUNIT_TEST(testTdf90808);
CPPUNIT_TEST(testTdf97601);
CPPUNIT_TEST(testTdf75137); CPPUNIT_TEST(testTdf75137);
CPPUNIT_TEST(testTdf83798); CPPUNIT_TEST(testTdf83798);
CPPUNIT_TEST(testTdf89714); CPPUNIT_TEST(testTdf89714);
@@ -2387,6 +2391,30 @@ void SwUiWriterTest::testTdf90808()
CPPUNIT_ASSERT_THROW(xText->insertTextContent(xCursor, xNumBookmark2, true), css::lang::IllegalArgumentException); CPPUNIT_ASSERT_THROW(xText->insertTextContent(xCursor, xNumBookmark2, true), css::lang::IllegalArgumentException);
} }
void SwUiWriterTest::testTdf97601()
{
// Instructions from the bugreport to trigger an infinite loop.
createDoc("tdf97601.odt");
uno::Reference<text::XTextEmbeddedObjectsSupplier> xEmbeddedObjectsSupplier(mxComponent, uno::UNO_QUERY);
uno::Reference<container::XNameAccess> xEmbeddedObjects = xEmbeddedObjectsSupplier->getEmbeddedObjects();
uno::Reference<beans::XPropertySet> xChart;
xEmbeddedObjects->getByName("myChart") >>= xChart;
uno::Reference<chart2::data::XDataSource> xChartComponent;
xChart->getPropertyValue("Component") >>= xChartComponent;
uno::Sequence< uno::Reference<chart2::data::XLabeledDataSequence> > aDataSequences = xChartComponent->getDataSequences();
uno::Reference<document::XEmbeddedObjectSupplier2> xChartState(xChart, uno::UNO_QUERY);
xChartState->getExtendedControlOverEmbeddedObject()->changeState(1);
uno::Reference<util::XModifiable> xDataSequenceModifiable(aDataSequences[2]->getValues(), uno::UNO_QUERY);
xDataSequenceModifiable->setModified(true);
// Make sure that the chart is marked as modified.
uno::Reference<util::XModifiable> xModifiable(xChartComponent, uno::UNO_QUERY);
CPPUNIT_ASSERT_EQUAL(true, bool(xModifiable->isModified()));
calcLayout();
// This never returned.
Scheduler::ProcessEventsToIdle();
}
void SwUiWriterTest::testTdf75137() void SwUiWriterTest::testTdf75137()
{ {
SwDoc* pDoc = createDoc(); SwDoc* pDoc = createDoc();

View File

@@ -656,7 +656,7 @@ void SwWrtShell::CalcAndSetScale( svt::EmbeddedObjectRef& xObj,
aSz.Width = aSize.Width(); aSz.Width = aSize.Width();
aSz.Height = aSize.Height(); aSz.Height = aSize.Height();
// Action 'setVisualAreaSize' doesn't have to change the // Action 'setVisualAreaSize' doesn't have to turn on the
// modified state of the document, either. // modified state of the document, either.
bool bModified = false; bool bModified = false;
uno::Reference<util::XModifiable> xModifiable(xObj->getComponent(), uno::UNO_QUERY); uno::Reference<util::XModifiable> xModifiable(xObj->getComponent(), uno::UNO_QUERY);
@@ -664,7 +664,7 @@ void SwWrtShell::CalcAndSetScale( svt::EmbeddedObjectRef& xObj,
bModified = xModifiable->isModified(); bModified = xModifiable->isModified();
xObj->setVisualAreaSize( nAspect, aSz ); xObj->setVisualAreaSize( nAspect, aSz );
xModifiable.set(xObj->getComponent(), uno::UNO_QUERY); xModifiable.set(xObj->getComponent(), uno::UNO_QUERY);
if (xModifiable.is()) if (xModifiable.is() && xModifiable->isModified() && !bModified)
xModifiable->setModified(bModified); xModifiable->setModified(bModified);
// #i48419# - action 'UpdateReplacement' doesn't // #i48419# - action 'UpdateReplacement' doesn't