If a SdrOle2Obj object is missing/broken show the preview set for it

if the object isn't valid, e.g. link to something that doesn't exist, set the fallback
graphic as mxGraphic so SdrOle2Obj::GetGraphic will show the fallback, otherwise
the failing mxObjRef.is test in SdrOle2Obj::GetGraphic means it doesn't get used

Change-Id: I8f1aea6b25dc216e01a0f888a44d10876bb1bebd
Reviewed-on: https://gerrit.libreoffice.org/83322
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
diff --git a/sc/qa/unit/data/ods/keep-preview-missing-obj-link.ods b/sc/qa/unit/data/ods/keep-preview-missing-obj-link.ods
new file mode 100644
index 0000000..e7b15fd
--- /dev/null
+++ b/sc/qa/unit/data/ods/keep-preview-missing-obj-link.ods
Binary files differ
diff --git a/sc/qa/unit/helper/qahelper.cxx b/sc/qa/unit/helper/qahelper.cxx
index 4ee21b9..b1d70b3 100644
--- a/sc/qa/unit/helper/qahelper.cxx
+++ b/sc/qa/unit/helper/qahelper.cxx
@@ -288,7 +288,7 @@ void testFormats(ScBootstrapFixture* pTest, ScDocument* pDoc, sal_Int32 nFormat)
    CPPUNIT_ASSERT_EQUAL(ScRangeList(ScRange(1,1,2,3,1,2)), rRange3);
}

const SdrOle2Obj* getSingleChartObject(ScDocument& rDoc, sal_uInt16 nPage)
const SdrOle2Obj* getSingleOleObject(ScDocument& rDoc, sal_uInt16 nPage)
{
    // Retrieve the chart object instance from the 2nd page (for the 2nd sheet).
    ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer();
@@ -324,14 +324,23 @@ const SdrOle2Obj* getSingleChartObject(ScDocument& rDoc, sal_uInt16 nPage)
        return nullptr;
    }

    const SdrOle2Obj& rOleObj = static_cast<const SdrOle2Obj&>(*pObj);
    if (!rOleObj.IsChart())
    return static_cast<const SdrOle2Obj*>(pObj);
}

const SdrOle2Obj* getSingleChartObject(ScDocument& rDoc, sal_uInt16 nPage)
{
    const SdrOle2Obj* pObj = getSingleOleObject(rDoc, nPage);

    if (!pObj)
        return pObj;

    if (!pObj->IsChart())
    {
        cout << "This should be a chart object." << endl;
        return nullptr;
    }

    return &rOleObj;
    return pObj;
}

std::vector<OUString> getChartRangeRepresentations(const SdrOle2Obj& rChartObj)
diff --git a/sc/qa/unit/helper/qahelper.hxx b/sc/qa/unit/helper/qahelper.hxx
index d0ad00b..fa284de 100644
--- a/sc/qa/unit/helper/qahelper.hxx
+++ b/sc/qa/unit/helper/qahelper.hxx
@@ -122,6 +122,8 @@ SCQAHELPER_DLLPUBLIC void testFile(const OUString& aFileName, ScDocument& rDoc, 
//need own handler because conditional formatting strings must be generated
SCQAHELPER_DLLPUBLIC void testCondFile(const OUString& aFileName, ScDocument* pDoc, SCTAB nTab);

SCQAHELPER_DLLPUBLIC const SdrOle2Obj* getSingleOleObject(ScDocument& rDoc, sal_uInt16 nPage);

SCQAHELPER_DLLPUBLIC const SdrOle2Obj* getSingleChartObject(ScDocument& rDoc, sal_uInt16 nPage);

SCQAHELPER_DLLPUBLIC std::vector<OUString> getChartRangeRepresentations(const SdrOle2Obj& rChartObj);
diff --git a/sc/qa/unit/subsequent_filters-test.cxx b/sc/qa/unit/subsequent_filters-test.cxx
index cba2aa7..9110505 100644
--- a/sc/qa/unit/subsequent_filters-test.cxx
+++ b/sc/qa/unit/subsequent_filters-test.cxx
@@ -250,6 +250,7 @@ public:
    void testVBAMacroFunctionODS();
    void testAutoheight2Rows();
    void testXLSDefColWidth();
    void testPreviewMissingObjLink();

    CPPUNIT_TEST_SUITE(ScFiltersTest);
    CPPUNIT_TEST(testBooleanFormatXLSX);
@@ -391,6 +392,7 @@ public:
    CPPUNIT_TEST(testVBAMacroFunctionODS);
    CPPUNIT_TEST(testAutoheight2Rows);
    CPPUNIT_TEST(testXLSDefColWidth);
    CPPUNIT_TEST(testPreviewMissingObjLink);

    CPPUNIT_TEST_SUITE_END();

@@ -4320,6 +4322,23 @@ void ScFiltersTest::testXLSDefColWidth()
    xDocSh->DoClose();
}

void ScFiltersTest::testPreviewMissingObjLink()
{
    ScDocShellRef xDocSh = loadDoc("keep-preview-missing-obj-link.", FORMAT_ODS);
    CPPUNIT_ASSERT_MESSAGE("Failed to load keep-preview-missing-obj-link.ods.", xDocSh.is());

    ScDocument& rDoc = xDocSh->GetDocument();

    // Retrieve the ole object
    const SdrOle2Obj* pOleObj = getSingleOleObject(rDoc, 0);
    CPPUNIT_ASSERT_MESSAGE("Failed to retrieve an ole object from the 2nd sheet.", pOleObj);

    const Graphic* pGraphic = pOleObj->GetGraphic();
    CPPUNIT_ASSERT_MESSAGE("the ole object links to a missing file, but we should retain its preview", pGraphic);

    xDocSh->DoClose();
}

ScFiltersTest::ScFiltersTest()
      : ScBootstrapFixture( "sc/qa/unit/data" )
{
diff --git a/svx/source/svdraw/svdoole2.cxx b/svx/source/svdraw/svdoole2.cxx
index 604d6c8..16617ec 100644
--- a/svx/source/svdraw/svdoole2.cxx
+++ b/svx/source/svdraw/svdoole2.cxx
@@ -1849,11 +1849,19 @@ bool SdrOle2Obj::IsChart() const
void SdrOle2Obj::SetGraphicToObj( const Graphic& aGraphic )
{
    mpImpl->mxObjRef.SetGraphic( aGraphic, OUString() );
    // if the object isn't valid, e.g. link to something that doesn't exist, set the fallback
    // graphic as mxGraphic so SdrOle2Obj::GetGraphic will show the fallback
    if (const Graphic* pObjGraphic = mpImpl->mxObjRef.is() ? nullptr : mpImpl->mxObjRef.GetGraphic())
        mpImpl->mxGraphic.reset(new Graphic(*pObjGraphic));
}

void SdrOle2Obj::SetGraphicToObj( const uno::Reference< io::XInputStream >& xGrStream, const OUString& aMediaType )
{
    mpImpl->mxObjRef.SetGraphicStream( xGrStream, aMediaType );
    // if the object isn't valid, e.g. link to something that doesn't exist, set the fallback
    // graphic as mxGraphic so SdrOle2Obj::GetGraphic will show the fallback
    if (const Graphic* pObjGraphic = mpImpl->mxObjRef.is() ? nullptr : mpImpl->mxObjRef.GetGraphic())
        mpImpl->mxGraphic.reset(new Graphic(*pObjGraphic));
}

bool SdrOle2Obj::IsCalc() const