summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sw/CppunitTest_sw_core_theme.mk1
-rw-r--r--sw/inc/shellio.hxx7
-rw-r--r--sw/qa/core/theme/ThemeTest.cxx189
-rw-r--r--sw/qa/core/theme/data/theme_bar.odtbin0 -> 9447 bytes
-rw-r--r--sw/qa/core/theme/data/theme_foo.fodt39
-rw-r--r--sw/source/filter/basflt/shellio.cxx2
-rw-r--r--sw/source/filter/xml/swxml.cxx4
-rw-r--r--sw/source/uibase/dochdl/swdtflvr.cxx1
-rw-r--r--xmloff/source/style/xmlstyle.cxx23
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
new file mode 100644
index 000000000000..30892fcd03aa
--- /dev/null
+++ b/sw/qa/core/theme/data/theme_bar.odt
Binary files differ
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())