1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 #include "WpftLoader.hxx"
12 #include <com/sun/star/beans/PropertyValue.hpp>
13 #include <com/sun/star/container/NoSuchElementException.hpp>
14 #include <com/sun/star/container/XNameAccess.hpp>
15 #include <com/sun/star/document/XExtendedFilterDetection.hpp>
16 #include <com/sun/star/document/XFilter.hpp>
17 #include <com/sun/star/document/XImporter.hpp>
18 #include <com/sun/star/document/XTypeDetection.hpp>
19 #include <com/sun/star/frame/XController.hpp>
20 #include <com/sun/star/frame/XDesktop2.hpp>
21 #include <com/sun/star/frame/XModel.hpp>
22 #include <com/sun/star/io/XInputStream.hpp>
23 #include <com/sun/star/lang/IllegalArgumentException.hpp>
24 #include <com/sun/star/lang/XComponent.hpp>
25 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
26 #include <com/sun/star/ucb/XContent.hpp>
27 #include <com/sun/star/uno/XComponentContext.hpp>
28 #include <com/sun/star/util/XCloseable.hpp>
30 #include <ucbhelper/content.hxx>
32 namespace beans
= com::sun::star::beans
;
33 namespace container
= com::sun::star::container
;
34 namespace document
= com::sun::star::document
;
35 namespace frame
= com::sun::star::frame
;
36 namespace lang
= com::sun::star::lang
;
37 namespace ucb
= com::sun::star::ucb
;
38 namespace uno
= com::sun::star::uno
;
39 namespace util
= com::sun::star::util
;
41 namespace writerperfect
45 WpftLoader::WpftLoader(const OUString
& rURL
,
46 const css::uno::Reference
<css::document::XFilter
>& rxFilter
,
47 const OUString
& rFactoryURL
,
48 const css::uno::Reference
<css::frame::XDesktop2
>& rxDesktop
,
49 const css::uno::Reference
<css::container::XNameAccess
>& rxTypeMap
,
50 const css::uno::Reference
<css::uno::XComponentContext
>& rxContext
)
52 , m_aFactoryURL(rFactoryURL
)
54 , m_xDesktop(rxDesktop
)
55 , m_xTypeMap(rxTypeMap
)
56 , m_xContext(rxContext
)
62 WpftLoader::WpftLoader(const css::uno::Reference
<css::io::XInputStream
>& rxInputStream
,
63 const css::uno::Reference
<css::document::XFilter
>& rxFilter
,
64 const OUString
& rFactoryURL
,
65 const css::uno::Reference
<css::frame::XDesktop2
>& rxDesktop
,
66 const css::uno::Reference
<css::uno::XComponentContext
>& rxContext
)
67 : m_xInputStream(rxInputStream
)
68 , m_aFactoryURL(rFactoryURL
)
70 , m_xDesktop(rxDesktop
)
71 , m_xContext(rxContext
)
77 WpftLoader::~WpftLoader()
88 const css::uno::Reference
<css::lang::XComponent
>& WpftLoader::getDocument() const { return m_xDoc
; }
90 bool WpftLoader::impl_load()
92 // create an empty frame
93 m_xDoc
.set(m_xDesktop
->loadComponentFromURL(m_aFactoryURL
, "_blank", 0,
94 uno::Sequence
<beans::PropertyValue
>()),
97 // Find the model and frame. We need them later.
98 m_xFrame
.set(m_xDoc
, uno::UNO_QUERY
);
99 uno::Reference
<frame::XModel
> xModel(m_xDoc
, uno::UNO_QUERY
);
100 uno::Reference
<frame::XController
> xController(m_xDoc
, uno::UNO_QUERY
);
104 xController
= m_xFrame
->getController();
105 xModel
= xController
->getModel();
107 else if (xModel
.is())
109 xController
= xModel
->getCurrentController();
110 m_xFrame
= xController
->getFrame();
112 else if (xController
.is())
114 m_xFrame
= xController
->getFrame();
115 xModel
= xController
->getModel();
118 if (!m_xFrame
.is() || !xModel
.is())
119 throw uno::RuntimeException();
121 // try to import the document (and load it into the prepared frame)
124 const uno::Reference
<document::XImporter
> xImporter(m_xFilter
, uno::UNO_QUERY_THROW
);
126 xImporter
->setTargetDocument(m_xDoc
);
128 uno::Sequence
<beans::PropertyValue
> aDescriptor(3);
129 aDescriptor
[0].Name
= "URL";
130 aDescriptor
[0].Value
<<= m_aURL
;
131 if (m_xInputStream
.is())
133 aDescriptor
[1].Name
= "InputStream";
134 aDescriptor
[1].Value
<<= m_xInputStream
;
138 ucbhelper::Content
aContent(m_aURL
, uno::Reference
<ucb::XCommandEnvironment
>(),
140 aDescriptor
[1].Name
= "InputStream";
141 aDescriptor
[1].Value
<<= aContent
.openStream();
142 aDescriptor
[2].Name
= "UCBContent";
143 aDescriptor
[2].Value
<<= aContent
.get();
146 const uno::Reference
<document::XExtendedFilterDetection
> xDetector(m_xFilter
,
147 uno::UNO_QUERY_THROW
);
149 const OUString
aTypeName(xDetector
->detect(aDescriptor
));
150 if (aTypeName
.isEmpty())
151 throw lang::IllegalArgumentException();
154 impl_detectFilterName(aDescriptor
, aTypeName
);
156 xModel
->lockControllers();
157 const bool bLoaded
= m_xFilter
->filter(aDescriptor
);
158 xModel
->unlockControllers();
161 catch (const uno::Exception
&)
169 void WpftLoader::impl_dispose()
171 // close the opened document
172 uno::Reference
<util::XCloseable
> xCloseable(m_xFrame
, uno::UNO_QUERY
);
174 xCloseable
->close(true);
175 else if (m_xDoc
.is())
181 void WpftLoader::impl_detectFilterName(uno::Sequence
<beans::PropertyValue
>& rDescriptor
,
182 const OUString
& rTypeName
)
185 = std::any_of(rDescriptor
.begin(), rDescriptor
.end(),
186 [](const beans::PropertyValue
& rProp
) { return "FilterName" == rProp
.Name
; });
190 uno::Sequence
<beans::PropertyValue
> aTypes
;
191 if (m_xTypeMap
->getByName(rTypeName
) >>= aTypes
)
193 for (const auto& rType
: std::as_const(aTypes
))
195 OUString aFilterName
;
196 if (("PreferredFilter" == rType
.Name
) && (rType
.Value
>>= aFilterName
))
198 const sal_Int32 nDescriptorLen
= rDescriptor
.getLength();
199 rDescriptor
.realloc(nDescriptorLen
+ 1);
200 rDescriptor
[nDescriptorLen
].Name
= "FilterName";
201 rDescriptor
[nDescriptorLen
].Value
<<= aFilterName
;
207 throw container::NoSuchElementException();
212 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */