diff options
-rw-r--r-- | sw/CppunitTest_sw_core_theme.mk | 1 | ||||
-rw-r--r-- | sw/inc/shellio.hxx | 7 | ||||
-rw-r--r-- | sw/qa/core/theme/ThemeTest.cxx | 189 | ||||
-rw-r--r-- | sw/qa/core/theme/data/theme_bar.odt | bin | 0 -> 9447 bytes | |||
-rw-r--r-- | sw/qa/core/theme/data/theme_foo.fodt | 39 | ||||
-rw-r--r-- | sw/source/filter/basflt/shellio.cxx | 2 | ||||
-rw-r--r-- | sw/source/filter/xml/swxml.cxx | 4 | ||||
-rw-r--r-- | sw/source/uibase/dochdl/swdtflvr.cxx | 1 | ||||
-rw-r--r-- | xmloff/source/style/xmlstyle.cxx | 23 |
9 files changed, 266 insertions, 0 deletions
diff --git a/sw/CppunitTest_sw_core_theme.mk b/sw/CppunitTest_sw_core_theme.mk index 03b42a32e666..5938916bd9df 100644 --- a/sw/CppunitTest_sw_core_theme.mk +++ b/sw/CppunitTest_sw_core_theme.mk @@ -24,6 +24,7 @@ $(eval $(call gb_CppunitTest_use_libraries,sw_core_theme, \ docmodel \ sal \ sfx \ + sot \ subsequenttest \ sw \ swqahelper \ diff --git a/sw/inc/shellio.hxx b/sw/inc/shellio.hxx index 370f6f6daa68..1465db93be80 100644 --- a/sw/inc/shellio.hxx +++ b/sw/inc/shellio.hxx @@ -155,6 +155,7 @@ class SW_DLLPUBLIC SwReader: public SwDocFac OUString msBaseURL; bool mbSkipImages; bool mbSkipInvalidateNumRules = false; + bool mbIsInPaste = false; public: @@ -180,6 +181,8 @@ public: { mbSkipInvalidateNumRules = bSkipInvalidateNumRules; } + void SetInPaste(bool val) { mbIsInPaste = val; } + bool IsInPaste() const { return mbIsInPaste; } protected: void SetBaseURL( const OUString& rURL ) { msBaseURL = rURL; } @@ -232,6 +235,7 @@ protected: bool m_bHasAskTemplateName : 1; bool m_bIgnoreHTMLComments : 1; bool m_bSkipImages : 1; + bool m_bIsInPaste : 1 = false; virtual OUString GetTemplateName(SwDoc& rDoc) const; @@ -269,6 +273,9 @@ public: void SetIgnoreHTMLComments( bool bSet ) { m_bIgnoreHTMLComments = bSet; } + bool IsInPaste() const { return m_bIsInPaste; } + void SetInPaste(bool bSet) { m_bIsInPaste = bSet; } + virtual bool HasGlossaries() const; virtual bool ReadGlossaries( SwTextBlocks&, bool bSaveRelFiles ) const; diff --git a/sw/qa/core/theme/ThemeTest.cxx b/sw/qa/core/theme/ThemeTest.cxx index ce2be76edc65..9f33bafe33c1 100644 --- a/sw/qa/core/theme/ThemeTest.cxx +++ b/sw/qa/core/theme/ThemeTest.cxx @@ -9,17 +9,25 @@ #include <swmodeltestbase.hxx> +#include <com/sun/star/datatransfer/XTransferableSupplier.hpp> +#include <com/sun/star/ucb/SimpleFileAccess.hpp> + #include <memory> #include <docsh.hxx> #include <unotxdoc.hxx> #include <wrtsh.hxx> #include <drawdoc.hxx> #include <IDocumentDrawModelAccess.hxx> + +#include <comphelper/classids.hxx> +#include <comphelper/processfactory.hxx> #include <svx/svdpage.hxx> #include <docmodel/uno/UnoComplexColor.hxx> #include <docmodel/theme/Theme.hxx> #include <ThemeColorChanger.hxx> +#include <sot/exchange.hxx> #include <svx/ColorSets.hxx> +#include <vcl/transfer.hxx> using namespace css; @@ -479,6 +487,187 @@ CPPUNIT_TEST_FIXTURE(SwCoreThemeTest, testThemeChanging) } } +// A simple transferable, that provides only EMBED_SOURCE and OBJECTDESCRIPTOR flavors, taking +// data from an ODT file. This makes the transferable behave just like clipboard content created +// by Writer in a different instance, taking SwTransferable::PasteOLE path. +class TestSimpleFileTransferable : public cppu::WeakImplHelper<css::datatransfer::XTransferable> +{ +public: + TestSimpleFileTransferable(const OUString& fileURL); + css::uno::Any SAL_CALL getTransferData(const css::datatransfer::DataFlavor& flavor) override; + css::uno::Sequence<css::datatransfer::DataFlavor> SAL_CALL getTransferDataFlavors() override; + sal_Bool SAL_CALL isDataFlavorSupported(const css::datatransfer::DataFlavor& flavor) override; + +private: + OUString m_fileURL; +}; + +TestSimpleFileTransferable::TestSimpleFileTransferable(const OUString& fileURL) + : m_fileURL(fileURL) +{ +} + +css::uno::Any +TestSimpleFileTransferable::getTransferData(const css::datatransfer::DataFlavor& flavor) +{ + if (flavor.MimeType == SotExchange::GetFormatMimeType(SotClipboardFormatId::EMBED_SOURCE)) + { + auto xSFA(ucb::SimpleFileAccess::create(comphelper::getProcessComponentContext())); + auto xInputStream = xSFA->openFileRead(m_fileURL); + sal_Int32 bytes = xInputStream->available(); + css::uno::Sequence<sal_Int8> data; + CPPUNIT_ASSERT_EQUAL(bytes, xInputStream->readBytes(data, bytes)); + return css::uno::Any(data); + } + if (flavor.MimeType == SotExchange::GetFormatMimeType(SotClipboardFormatId::OBJECTDESCRIPTOR)) + { + TransferableObjectDescriptor aDesc; + aDesc.maClassName = SvGlobalName(SO3_SW_CLASSID); + SvMemoryStream aMemStm(1024, 1024); + WriteTransferableObjectDescriptor(aMemStm, aDesc); + css::uno::Sequence<sal_Int8> data(static_cast<const sal_Int8*>(aMemStm.GetData()), + aMemStm.GetSize()); + return css::uno::Any(data); + } + return {}; +} + +css::uno::Sequence<css::datatransfer::DataFlavor> +TestSimpleFileTransferable::getTransferDataFlavors() +{ + css::datatransfer::DataFlavor embed_source; + SotExchange::GetFormatDataFlavor(SotClipboardFormatId::EMBED_SOURCE, embed_source); + css::datatransfer::DataFlavor objectdescriptor; + SotExchange::GetFormatDataFlavor(SotClipboardFormatId::OBJECTDESCRIPTOR, objectdescriptor); + return { embed_source, objectdescriptor }; +} + +sal_Bool +TestSimpleFileTransferable::isDataFlavorSupported(const css::datatransfer::DataFlavor& flavor) +{ + if (flavor.MimeType == SotExchange::GetFormatMimeType(SotClipboardFormatId::EMBED_SOURCE)) + return true; + if (flavor.MimeType == SotExchange::GetFormatMimeType(SotClipboardFormatId::OBJECTDESCRIPTOR)) + return true; + return false; +} + +CPPUNIT_TEST_FIXTURE(SwCoreThemeTest, testTdf162715_customTransferable) +{ + // Given a document with a custom theme: + createSwDoc("theme_foo.fodt"); + + auto pDoc = getSwDoc(); + CPPUNIT_ASSERT(pDoc); + + auto pModel = pDoc->getIDocumentDrawModelAccess().GetDrawModel(); + CPPUNIT_ASSERT(pModel); + auto pTheme = pModel->getTheme().get(); + CPPUNIT_ASSERT(pTheme); + CPPUNIT_ASSERT_EQUAL(u"foo"_ustr, pTheme->GetName()); + CPPUNIT_ASSERT_EQUAL(u"colors_foo"_ustr, pTheme->getColorSet()->getName()); + CPPUNIT_ASSERT_EQUAL(Color(0x000080), pTheme->GetColor(model::ThemeColorType::Dark1)); + CPPUNIT_ASSERT_EQUAL(Color(0x008000), pTheme->GetColor(model::ThemeColorType::Dark2)); + + // Select all and check the original text in the document: + auto pWrtShell = pDoc->GetDocShell()->GetWrtShell(); + pWrtShell->SelAll(); + CPPUNIT_ASSERT_EQUAL(u"Theme foo"_ustr, pWrtShell->GetSelText()); + + // Create a transferable from another document with another custom theme, + // and insert (paste) its content over the selection: + css::uno::Reference<css::datatransfer::XTransferable> xTransferable( + new TestSimpleFileTransferable(createFileURL(u"theme_bar.odt"))); + css::uno::Reference<css::frame::XModel> xModel(mxComponent, css::uno::UNO_QUERY_THROW); + css::uno::Reference<css::datatransfer::XTransferableSupplier> xTS( + xModel->getCurrentController(), css::uno::UNO_QUERY_THROW); + xTS->insertTransferable(xTransferable); + + // Check that the paste is successful (the text has been replaced): + pWrtShell->SelAll(); + CPPUNIT_ASSERT_EQUAL(u"Theme bar"_ustr, pWrtShell->GetSelText()); + + // The original theme must not be replaced. + pTheme = pModel->getTheme().get(); + CPPUNIT_ASSERT(pTheme); + // Without the fix, this would fail, because the name was "bar": + CPPUNIT_ASSERT_EQUAL(u"foo"_ustr, pTheme->GetName()); + CPPUNIT_ASSERT_EQUAL(u"colors_foo"_ustr, pTheme->getColorSet()->getName()); + CPPUNIT_ASSERT_EQUAL(Color(0x000080), pTheme->GetColor(model::ThemeColorType::Dark1)); + CPPUNIT_ASSERT_EQUAL(Color(0x008000), pTheme->GetColor(model::ThemeColorType::Dark2)); +} + +CPPUNIT_TEST_FIXTURE(SwCoreThemeTest, testTdf162715_ownTransferable) +{ + css::uno::Reference<css::datatransfer::XTransferable> xTransferable; + { + // Given a document with a custom theme: + createSwDoc("theme_bar.odt"); + + auto pDoc = getSwDoc(); + CPPUNIT_ASSERT(pDoc); + + auto pModel = pDoc->getIDocumentDrawModelAccess().GetDrawModel(); + CPPUNIT_ASSERT(pModel); + auto pTheme = pModel->getTheme().get(); + CPPUNIT_ASSERT(pTheme); + CPPUNIT_ASSERT_EQUAL(u"bar"_ustr, pTheme->GetName()); + CPPUNIT_ASSERT_EQUAL(u"colors_bar"_ustr, pTheme->getColorSet()->getName()); + CPPUNIT_ASSERT_EQUAL(Color(0x606000), pTheme->GetColor(model::ThemeColorType::Dark1)); + CPPUNIT_ASSERT_EQUAL(Color(0x800000), pTheme->GetColor(model::ThemeColorType::Dark2)); + + // Select all and check the original text in the document: + auto pWrtShell = pDoc->GetDocShell()->GetWrtShell(); + pWrtShell->SelAll(); + CPPUNIT_ASSERT_EQUAL(u"Theme bar"_ustr, pWrtShell->GetSelText()); + + // Create a normal Writer's transferable out of the selection: + css::uno::Reference<css::frame::XModel> xModel(mxComponent, css::uno::UNO_QUERY_THROW); + css::uno::Reference<css::datatransfer::XTransferableSupplier> xTS( + xModel->getCurrentController(), css::uno::UNO_QUERY_THROW); + xTransferable = xTS->getTransferable(); + } + { + // Open another document with another custom theme: + createSwDoc("theme_foo.fodt"); + + auto pDoc = getSwDoc(); + CPPUNIT_ASSERT(pDoc); + + auto pModel = pDoc->getIDocumentDrawModelAccess().GetDrawModel(); + CPPUNIT_ASSERT(pModel); + auto pTheme = pModel->getTheme().get(); + CPPUNIT_ASSERT(pTheme); + CPPUNIT_ASSERT_EQUAL(u"foo"_ustr, pTheme->GetName()); + CPPUNIT_ASSERT_EQUAL(u"colors_foo"_ustr, pTheme->getColorSet()->getName()); + CPPUNIT_ASSERT_EQUAL(Color(0x000080), pTheme->GetColor(model::ThemeColorType::Dark1)); + CPPUNIT_ASSERT_EQUAL(Color(0x008000), pTheme->GetColor(model::ThemeColorType::Dark2)); + + // Select all and check the original text in the second document: + auto pWrtShell = pDoc->GetDocShell()->GetWrtShell(); + pWrtShell->SelAll(); + CPPUNIT_ASSERT_EQUAL(u"Theme foo"_ustr, pWrtShell->GetSelText()); + + // Insert (paste) the previously created transferable's content over the selection: + css::uno::Reference<css::frame::XModel> xModel(mxComponent, css::uno::UNO_QUERY_THROW); + css::uno::Reference<css::datatransfer::XTransferableSupplier> xTS( + xModel->getCurrentController(), css::uno::UNO_QUERY_THROW); + xTS->insertTransferable(xTransferable); + + // Check that the paste is successful (the text has been replaced): + pWrtShell->SelAll(); + CPPUNIT_ASSERT_EQUAL(u"Theme bar"_ustr, pWrtShell->GetSelText()); + + // The original theme must not be replaced. + pTheme = pModel->getTheme().get(); + CPPUNIT_ASSERT(pTheme); + CPPUNIT_ASSERT_EQUAL(u"foo"_ustr, pTheme->GetName()); + CPPUNIT_ASSERT_EQUAL(u"colors_foo"_ustr, pTheme->getColorSet()->getName()); + CPPUNIT_ASSERT_EQUAL(Color(0x000080), pTheme->GetColor(model::ThemeColorType::Dark1)); + CPPUNIT_ASSERT_EQUAL(Color(0x008000), pTheme->GetColor(model::ThemeColorType::Dark2)); + } +} + } // end anonymous namnespace CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sw/qa/core/theme/data/theme_bar.odt b/sw/qa/core/theme/data/theme_bar.odt Binary files differnew file mode 100644 index 000000000000..30892fcd03aa --- /dev/null +++ b/sw/qa/core/theme/data/theme_bar.odt diff --git a/sw/qa/core/theme/data/theme_foo.fodt b/sw/qa/core/theme/data/theme_foo.fodt new file mode 100644 index 000000000000..29837a34d54c --- /dev/null +++ b/sw/qa/core/theme/data/theme_foo.fodt @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text"> + <office:styles> + <loext:theme loext:name="foo"> + <loext:theme-colors loext:name="colors_foo"> + <loext:color loext:name="dark1" loext:color="#000080"/> + <loext:color loext:name="light1" loext:color="#ffffff"/> + <loext:color loext:name="dark2" loext:color="#008000"/> + <loext:color loext:name="light2" loext:color="#ffffff"/> + <loext:color loext:name="accent1" loext:color="#18a303"/> + <loext:color loext:name="accent2" loext:color="#0369a3"/> + <loext:color loext:name="accent3" loext:color="#a33e03"/> + <loext:color loext:name="accent4" loext:color="#8e03a3"/> + <loext:color loext:name="accent5" loext:color="#c99c00"/> + <loext:color loext:name="accent6" loext:color="#c9211e"/> + <loext:color loext:name="hyperlink" loext:color="#0000ee"/> + <loext:color loext:name="followed-hyperlink" loext:color="#551a8b"/> + </loext:theme-colors> + </loext:theme> + </office:styles> + <office:automatic-styles> + <style:style style:name="T1" style:family="text"> + <style:text-properties fo:color="#000080"> + <loext:char-complex-color loext:theme-type="dark1" loext:color-type="theme"/> + </style:text-properties> + </style:style> + <style:style style:name="T2" style:family="text"> + <style:text-properties fo:color="#008000"> + <loext:char-complex-color loext:theme-type="dark2" loext:color-type="theme"/> + </style:text-properties> + </style:style> + </office:automatic-styles> + <office:body> + <office:text> + <text:p><text:span text:style-name="T1">Theme</text:span> <text:span text:style-name="T2">foo</text:span></text:p> + </office:text> + </office:body> +</office:document>
\ No newline at end of file diff --git a/sw/source/filter/basflt/shellio.cxx b/sw/source/filter/basflt/shellio.cxx index 875d67d4321a..26fc61ab6b69 100644 --- a/sw/source/filter/basflt/shellio.cxx +++ b/sw/source/filter/basflt/shellio.cxx @@ -96,6 +96,7 @@ ErrCodeMsg SwReader::Read( const Reader& rOptions ) po->m_xStorage = mxStg; po->m_bInsertMode = nullptr != mpCursor; po->m_bSkipImages = mbSkipImages; + po->SetInPaste(IsInPaste()); // if a Medium is selected, get its Stream if( nullptr != (po->m_pMedium = mpMedium ) && @@ -394,6 +395,7 @@ ErrCodeMsg SwReader::Read( const Reader& rOptions ) po->SetBlockMode( false ); po->SetOrganizerMode( false ); po->SetIgnoreHTMLComments( false ); + po->SetInPaste(false); return nError; } diff --git a/sw/source/filter/xml/swxml.cxx b/sw/source/filter/xml/swxml.cxx index 36b8c91eac94..47a423ea340e 100644 --- a/sw/source/filter/xml/swxml.cxx +++ b/sw/source/filter/xml/swxml.cxx @@ -591,6 +591,8 @@ ErrCodeMsg XMLReader::Read( SwDoc &rDoc, const OUString& rBaseURL, SwPaM &rPaM, beans::PropertyAttribute::MAYBEVOID, 0 }, { u"SourceStorage"_ustr, 0, cppu::UnoType<embed::XStorage>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 }, + { u"IsInPaste"_ustr, 0, cppu::UnoType<bool>::get(), + beans::PropertyAttribute::MAYBEVOID, 0 }, }; uno::Reference< beans::XPropertySet > xInfoSet( comphelper::GenericPropertySet_CreateInstance( @@ -640,6 +642,8 @@ ErrCodeMsg XMLReader::Read( SwDoc &rDoc, const OUString& rBaseURL, SwPaM &rPaM, xInfoSet->setPropertyValue( u"SourceStorage"_ustr, Any( xStorage ) ); + xInfoSet->setPropertyValue(u"IsInPaste"_ustr, Any(IsInPaste())); + // prepare filter arguments, WARNING: the order is important! Sequence<Any> aFilterArgs{ Any(xInfoSet), Any(xStatusIndicator), diff --git a/sw/source/uibase/dochdl/swdtflvr.cxx b/sw/source/uibase/dochdl/swdtflvr.cxx index b5cd76930891..0ec3b35e86b9 100644 --- a/sw/source/uibase/dochdl/swdtflvr.cxx +++ b/sw/source/uibase/dochdl/swdtflvr.cxx @@ -2358,6 +2358,7 @@ bool SwTransferable::PasteOLE( const TransferableDataHelper& rData, SwWrtShell& { SwPaM &rPAM = *rSh.GetCursor(); SwReader aReader(xStore, OUString(), rPAM); + aReader.SetInPaste(true); if( ! aReader.Read( *pRead ).IsError() ) bRet = true; else if( bMsg ) diff --git a/xmloff/source/style/xmlstyle.cxx b/xmloff/source/style/xmlstyle.cxx index efc4da3e6842..e09ef37bfa12 100644 --- a/xmloff/source/style/xmlstyle.cxx +++ b/xmloff/source/style/xmlstyle.cxx @@ -21,6 +21,7 @@ #include <sal/config.h> +#include <com/sun/star/beans/XPropertySet.hpp> #include <com/sun/star/frame/XModel.hpp> #include <com/sun/star/container/XNameContainer.hpp> #include <com/sun/star/style/XStyleFamiliesSupplier.hpp> @@ -28,6 +29,8 @@ #include <com/sun/star/style/XAutoStyleFamily.hpp> #include <com/sun/star/drawing/XDrawPageSupplier.hpp> #include <PageMasterPropMapper.hxx> + +#include <comphelper/diagnose_ex.hxx> #include <sal/log.hxx> #include <svl/style.hxx> #include <utility> @@ -683,6 +686,26 @@ css::uno::Reference< css::xml::sax::XFastContextHandler > SvXMLStylesContext::cr { if (nElement == XML_ELEMENT(LO_EXT, XML_THEME)) { + if (auto xImportInfo = GetImport().getImportInfo()) + { + try + { + if (auto xPropertySetInfo = xImportInfo->getPropertySetInfo()) + { + if (xPropertySetInfo->hasPropertyByName(u"IsInPaste"_ustr)) + { + css::uno::Any value = xImportInfo->getPropertyValue(u"IsInPaste"_ustr); + if (bool b; (value >>= b) && b) + return nullptr; // do not import themes in paste mode + } + } + } + catch (const css::uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("xmloff"); + } + } + uno::Reference<uno::XInterface> xObject(GetImport().GetModel(), uno::UNO_QUERY); uno::Reference<drawing::XDrawPageSupplier> const xDrawPageSupplier(GetImport().GetModel(), uno::UNO_QUERY); if (xDrawPageSupplier.is()) |