Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * This file is part of the LibreOffice project.
4 : : *
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/.
8 : : *
9 : : * This file incorporates work covered by the following license notice:
10 : : *
11 : : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : : * contributor license agreements. See the NOTICE file distributed
13 : : * with this work for additional information regarding copyright
14 : : * ownership. The ASF licenses this file to you under the Apache
15 : : * License, Version 2.0 (the "License"); you may not use this file
16 : : * except in compliance with the License. You may obtain a copy of
17 : : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : : */
19 : :
20 : : #include "vbahelper/vbadocumentsbase.hxx"
21 : :
22 : : #include <comphelper/mediadescriptor.hxx>
23 : : #include <comphelper/processfactory.hxx>
24 : : #include <cppuhelper/implbase1.hxx>
25 : : #include <cppuhelper/implbase3.hxx>
26 : : #include <com/sun/star/frame/XDesktop.hpp>
27 : : #include <com/sun/star/container/XEnumerationAccess.hpp>
28 : : #include <com/sun/star/frame/XComponentLoader.hpp>
29 : : #include <com/sun/star/lang/XComponent.hpp>
30 : : #include <com/sun/star/frame/XModel.hpp>
31 : : #include <com/sun/star/frame/XFrame.hpp>
32 : : #include <com/sun/star/frame/XTitle.hpp>
33 : : #include <com/sun/star/frame/FrameSearchFlag.hpp>
34 : : #include <com/sun/star/util/XModifiable.hpp>
35 : : #include <com/sun/star/frame/XStorable.hpp>
36 : : #include <com/sun/star/lang/DisposedException.hpp>
37 : : #include <com/sun/star/beans/PropertyVetoException.hpp>
38 : : #include <com/sun/star/util/XCloseable.hpp>
39 : : #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
40 : : #include <com/sun/star/document/XTypeDetection.hpp>
41 : : #include <com/sun/star/document/MacroExecMode.hpp>
42 : : #include <com/sun/star/uri/XUriReference.hpp>
43 : : #include <com/sun/star/uri/XUriReferenceFactory.hpp>
44 : : #include <com/sun/star/lang/XServiceInfo.hpp>
45 : : #include <sfx2/objsh.hxx>
46 : : #include <tools/urlobj.hxx>
47 : : #include <vbahelper/vbadocumentbase.hxx>
48 : : #include <boost/unordered_map.hpp>
49 : : #include <osl/file.hxx>
50 : :
51 : : #include "vbahelper/vbahelper.hxx"
52 : : #include "vbahelper/vbaapplicationbase.hxx"
53 : :
54 : : using namespace ::ooo::vba;
55 : : using namespace ::com::sun::star;
56 : :
57 : : static const char aSpreadsheetDocument[] = "com.sun.star.sheet.SpreadsheetDocument";
58 : : static const char aTextDocument[] = "com.sun.star.text.TextDocument";
59 : :
60 : : typedef boost::unordered_map< rtl::OUString,
61 : : sal_Int32, ::rtl::OUStringHash,
62 : : ::std::equal_to< ::rtl::OUString > > NameIndexHash;
63 : :
64 : : typedef std::vector < uno::Reference< frame::XModel > > Documents;
65 : :
66 : : typedef ::cppu::WeakImplHelper1< container::XEnumeration > DocumentsEnumImpl_BASE;
67 : :
68 : : // #FIXME clearly this is a candidate for some sort of helper base class as
69 : : // this is a copy of SelectedSheetsEnum ( vbawindow.cxx )
70 : :
71 [ # # ]: 0 : class DocumentsEnumImpl : public DocumentsEnumImpl_BASE
72 : : {
73 : : uno::Reference< uno::XComponentContext > m_xContext;
74 : : Documents m_documents;
75 : : Documents::const_iterator m_it;
76 : :
77 : : public:
78 [ # # ]: 0 : DocumentsEnumImpl( const uno::Reference< uno::XComponentContext >& xContext, const Documents& docs ) throw ( uno::RuntimeException ) : m_xContext( xContext ), m_documents( docs )
79 : : {
80 [ # # ]: 0 : m_it = m_documents.begin();
81 : 0 : }
82 [ # # ]: 0 : DocumentsEnumImpl( const uno::Reference< uno::XComponentContext >& xContext ) throw ( uno::RuntimeException ) : m_xContext( xContext )
83 : : {
84 : : uno::Reference< lang::XMultiComponentFactory > xSMgr(
85 [ # # ][ # # ]: 0 : m_xContext->getServiceManager(), uno::UNO_QUERY_THROW );
[ # # ]
86 : :
87 : : uno::Reference< frame::XDesktop > xDesktop
88 [ # # ][ # # ]: 0 : (xSMgr->createInstanceWithContext(::rtl::OUString("com.sun.star.frame.Desktop"), m_xContext), uno::UNO_QUERY_THROW );
[ # # ]
89 [ # # ][ # # ]: 0 : uno::Reference< container::XEnumeration > mxComponents = xDesktop->getComponents()->createEnumeration();
[ # # ][ # # ]
90 [ # # ][ # # ]: 0 : while( mxComponents->hasMoreElements() )
[ # # ]
91 : : {
92 [ # # ][ # # ]: 0 : uno::Reference< frame::XModel > xNext( mxComponents->nextElement(), uno::UNO_QUERY );
[ # # ]
93 [ # # ]: 0 : if ( xNext.is() )
94 [ # # ]: 0 : m_documents.push_back( xNext );
95 : 0 : }
96 [ # # ]: 0 : m_it = m_documents.begin();
97 : 0 : }
98 : : // XEnumeration
99 : 0 : virtual ::sal_Bool SAL_CALL hasMoreElements( ) throw (uno::RuntimeException)
100 : : {
101 [ # # ]: 0 : return m_it != m_documents.end();
102 : : }
103 : :
104 : 0 : virtual uno::Any SAL_CALL nextElement( ) throw (container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException)
105 : : {
106 [ # # ]: 0 : if ( !hasMoreElements() )
107 : : {
108 [ # # ]: 0 : throw container::NoSuchElementException();
109 : : }
110 [ # # ]: 0 : return makeAny( *(m_it++) );
111 : : }
112 : : };
113 : :
114 : : // #FIXME clearly this is also a candidate for some sort of helper base class as
115 : : // a very similar one is used in vbawindow ( SelectedSheetsEnumAccess )
116 : : // Maybe a template base class that does all of the operations on the hashmap
117 : : // and vector only, and the sub-class does everything else
118 : : // => ctor, createEnumeration & factory method need be defined ( to be called
119 : : // by getByIndex, getByName )
120 : : typedef ::cppu::WeakImplHelper3< container::XEnumerationAccess
121 : : , com::sun::star::container::XIndexAccess
122 : : , com::sun::star::container::XNameAccess
123 : : > DocumentsAccessImpl_BASE;
124 : :
125 [ # # ][ # # ]: 0 : class DocumentsAccessImpl : public DocumentsAccessImpl_BASE
126 : : {
127 : : uno::Reference< uno::XComponentContext > m_xContext;
128 : : Documents m_documents;
129 : : NameIndexHash namesToIndices;
130 : : VbaDocumentsBase::DOCUMENT_TYPE meDocType;
131 : : public:
132 [ # # ][ # # ]: 0 : DocumentsAccessImpl( const uno::Reference< uno::XComponentContext >& xContext, VbaDocumentsBase::DOCUMENT_TYPE eDocType ) throw (uno::RuntimeException) :m_xContext( xContext ), meDocType( eDocType )
133 : : {
134 [ # # ][ # # ]: 0 : uno::Reference< container::XEnumeration > xEnum = new DocumentsEnumImpl( m_xContext );
[ # # ]
135 : 0 : sal_Int32 nIndex=0;
136 [ # # ][ # # ]: 0 : while( xEnum->hasMoreElements() )
[ # # ]
137 : : {
138 [ # # ][ # # ]: 0 : uno::Reference< lang::XServiceInfo > xServiceInfo( xEnum->nextElement(), uno::UNO_QUERY );
[ # # ]
139 [ # # ][ # # ]: 0 : if ( xServiceInfo.is()
[ # # ][ # # ]
[ # # ][ # # ]
140 [ # # ][ # # ]: 0 : && ( ( xServiceInfo->supportsService( rtl::OUString(aSpreadsheetDocument) ) && meDocType == VbaDocumentsBase::EXCEL_DOCUMENT )
[ # # ][ # # ]
[ # # # # ]
141 [ # # ][ # # ]: 0 : || ( xServiceInfo->supportsService( rtl::OUString(aTextDocument) ) && meDocType == VbaDocumentsBase::WORD_DOCUMENT ) ) )
[ # # ][ # # ]
[ # # # # ]
142 : : {
143 [ # # ]: 0 : uno::Reference< frame::XModel > xModel( xServiceInfo, uno::UNO_QUERY_THROW ); // that the spreadsheetdocument is a xmodel is a given
144 [ # # ]: 0 : m_documents.push_back( xModel );
145 : 0 : rtl::OUString sName;
146 [ # # ][ # # ]: 0 : uno::Reference< ::ooo::vba::XDocumentBase > xVbaDocument = new VbaDocumentBase( uno::Reference< XHelperInterface >(), xContext, xModel );
[ # # ]
147 [ # # ]: 0 : if ( xVbaDocument.is() )
148 : : {
149 [ # # ][ # # ]: 0 : sName = xVbaDocument->getName();
150 : : }
151 [ # # ]: 0 : namesToIndices[ sName ] = nIndex++;
152 : : }
153 : 0 : }
154 : :
155 : 0 : }
156 : :
157 : : //XEnumerationAccess
158 : 0 : virtual uno::Reference< container::XEnumeration > SAL_CALL createEnumeration( ) throw (uno::RuntimeException)
159 : : {
160 [ # # ][ # # ]: 0 : return new DocumentsEnumImpl( m_xContext, m_documents );
161 : : }
162 : : // XIndexAccess
163 : 0 : virtual ::sal_Int32 SAL_CALL getCount( ) throw (uno::RuntimeException)
164 : : {
165 : 0 : return m_documents.size();
166 : : }
167 : 0 : virtual uno::Any SAL_CALL getByIndex( ::sal_Int32 Index ) throw ( lang::IndexOutOfBoundsException, lang::WrappedTargetException, uno::RuntimeException)
168 : : {
169 [ # # # # ]: 0 : if ( Index < 0
[ # # ]
170 : 0 : || static_cast< Documents::size_type >(Index) >= m_documents.size() )
171 [ # # ]: 0 : throw lang::IndexOutOfBoundsException();
172 : 0 : return makeAny( m_documents[ Index ] ); // returns xspreadsheetdoc
173 : : }
174 : :
175 : : //XElementAccess
176 : 0 : virtual uno::Type SAL_CALL getElementType( ) throw (uno::RuntimeException)
177 : : {
178 : 0 : return frame::XModel::static_type(0);
179 : : }
180 : :
181 : 0 : virtual ::sal_Bool SAL_CALL hasElements( ) throw (uno::RuntimeException)
182 : : {
183 : 0 : return (!m_documents.empty());
184 : : }
185 : :
186 : : //XNameAccess
187 : 0 : virtual uno::Any SAL_CALL getByName( const ::rtl::OUString& aName ) throw (container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException)
188 : : {
189 [ # # ]: 0 : NameIndexHash::const_iterator it = namesToIndices.find( aName );
190 [ # # ][ # # ]: 0 : if ( it == namesToIndices.end() )
191 [ # # ]: 0 : throw container::NoSuchElementException();
192 [ # # ][ # # ]: 0 : return makeAny( m_documents[ it->second ] );
193 : :
194 : : }
195 : :
196 : 0 : virtual uno::Sequence< ::rtl::OUString > SAL_CALL getElementNames( ) throw (uno::RuntimeException)
197 : : {
198 [ # # ]: 0 : uno::Sequence< ::rtl::OUString > names( namesToIndices.size() );
199 [ # # ]: 0 : ::rtl::OUString* pString = names.getArray();
200 [ # # ]: 0 : NameIndexHash::const_iterator it = namesToIndices.begin();
201 [ # # ]: 0 : NameIndexHash::const_iterator it_end = namesToIndices.end();
202 [ # # ]: 0 : for ( ; it != it_end; ++it, ++pString )
203 [ # # ]: 0 : *pString = it->first;
204 : 0 : return names;
205 : : }
206 : :
207 : 0 : virtual ::sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName ) throw (uno::RuntimeException)
208 : : {
209 [ # # ]: 0 : NameIndexHash::const_iterator it = namesToIndices.find( aName );
210 [ # # ]: 0 : return (it != namesToIndices.end());
211 : : }
212 : :
213 : : };
214 : :
215 [ # # ][ # # ]: 0 : VbaDocumentsBase::VbaDocumentsBase( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< css::uno::XComponentContext >& xContext, DOCUMENT_TYPE eDocType ) throw (uno::RuntimeException) : VbaDocumentsBase_BASE( xParent, xContext, uno::Reference< container::XIndexAccess >( new DocumentsAccessImpl( xContext, eDocType ) ) ), meDocType( eDocType )
[ # # ]
216 : : {
217 : 0 : }
218 : :
219 : : namespace {
220 : :
221 : 0 : void lclSetupComponent( const uno::Reference< lang::XComponent >& rxComponent, sal_Bool bScreenUpdating, sal_Bool bInteractive )
222 : : {
223 [ # # ]: 0 : if( !bScreenUpdating ) try
224 : : {
225 [ # # ][ # # ]: 0 : uno::Reference< frame::XModel >( rxComponent, uno::UNO_QUERY_THROW )->lockControllers();
[ # # ][ # # ]
226 : : }
227 : 0 : catch( uno::Exception& )
228 : : {
229 : : }
230 : :
231 [ # # ]: 0 : if( !bInteractive ) try
232 : : {
233 [ # # ]: 0 : uno::Reference< frame::XModel > xModel( rxComponent, uno::UNO_QUERY_THROW );
234 [ # # ][ # # ]: 0 : uno::Reference< frame::XController > xController( xModel->getCurrentController(), uno::UNO_SET_THROW );
[ # # ]
235 [ # # ][ # # ]: 0 : uno::Reference< frame::XFrame > xFrame( xController->getFrame(), uno::UNO_SET_THROW );
[ # # ]
236 [ # # ][ # # ]: 0 : uno::Reference< awt::XWindow >( xFrame->getContainerWindow(), uno::UNO_SET_THROW )->setEnable( sal_False );
[ # # ][ # # ]
[ # # ][ # # ]
237 : : }
238 : 0 : catch( uno::Exception& )
239 : : {
240 : : }
241 : 0 : }
242 : :
243 : : } // namespace
244 : :
245 : 0 : uno::Any VbaDocumentsBase::createDocument() throw (uno::RuntimeException)
246 : : {
247 : : // #163808# determine state of Application.ScreenUpdating and Application.Interactive symbols (before new document is opened)
248 [ # # ][ # # ]: 0 : uno::Reference< XApplicationBase > xApplication( Application(), uno::UNO_QUERY );
249 [ # # ][ # # ]: 0 : sal_Bool bScreenUpdating = !xApplication.is() || xApplication->getScreenUpdating();
[ # # ][ # # ]
250 [ # # ][ # # ]: 0 : sal_Bool bInteractive = !xApplication.is() || xApplication->getInteractive();
[ # # ][ # # ]
251 : :
252 : : uno::Reference< lang::XMultiComponentFactory > xSMgr(
253 [ # # ][ # # ]: 0 : mxContext->getServiceManager(), uno::UNO_QUERY_THROW );
[ # # ]
254 : :
255 : : uno::Reference< frame::XComponentLoader > xLoader(
256 [ # # ]: 0 : xSMgr->createInstanceWithContext(
257 : : ::rtl::OUString("com.sun.star.frame.Desktop"),
258 [ # # ][ # # ]: 0 : mxContext), uno::UNO_QUERY_THROW );
259 : 0 : rtl::OUString sURL;
260 [ # # ]: 0 : if( meDocType == WORD_DOCUMENT )
261 : 0 : sURL = rtl::OUString( "private:factory/swriter" );
262 [ # # ]: 0 : else if( meDocType == EXCEL_DOCUMENT )
263 : 0 : sURL = rtl::OUString( "private:factory/scalc" );
264 : : else
265 [ # # ]: 0 : throw uno::RuntimeException( rtl::OUString( "Not implemented" ), uno::Reference< uno::XInterface >() );
266 : :
267 : : // prepare the media descriptor
268 [ # # ]: 0 : ::comphelper::MediaDescriptor aMediaDesc;
269 [ # # ][ # # ]: 0 : aMediaDesc[ ::comphelper::MediaDescriptor::PROP_MACROEXECUTIONMODE() ] <<= document::MacroExecMode::USE_CONFIG;
[ # # ]
270 [ # # ][ # # ]: 0 : aMediaDesc.setComponentDataEntry( ::rtl::OUString( "ApplyFormDesignMode" ), uno::Any( false ) );
271 : :
272 : : // craete the new document
273 [ # # ]: 0 : uno::Reference< lang::XComponent > xComponent = xLoader->loadComponentFromURL(
274 : : sURL ,
275 : : rtl::OUString( "_blank" ), 0,
276 [ # # ][ # # ]: 0 : aMediaDesc.getAsConstPropertyValueList() );
[ # # ]
277 : :
278 : : // #163808# lock document controllers and container window if specified by application
279 [ # # ]: 0 : lclSetupComponent( xComponent, bScreenUpdating, bInteractive );
280 : :
281 [ # # ][ # # ]: 0 : return uno::makeAny( xComponent );
282 : : }
283 : :
284 : 0 : void VbaDocumentsBase::closeDocuments() throw (uno::RuntimeException)
285 : : {
286 : : // #FIXME this *MUST* be wrong documents::close surely closes ALL documents
287 : : // in the collection, use of getCurrentDocument here is totally wrong
288 : : /*
289 : : uno::Reference< lang::XMultiComponentFactory > xSMgr(
290 : : mxContext->getServiceManager(), uno::UNO_QUERY_THROW );
291 : : uno::Reference< frame::XModel > xModel( getCurrentDocument(), uno::UNO_QUERY_THROW );
292 : : rtl::OUString url = rtl::OUString( ".uno:CloseDoc");
293 : : dispatchRequests(xModel,url);
294 : : */
295 : 0 : }
296 : :
297 : : // #TODO# #FIXME# can any of the unused params below be used?
298 : 0 : uno::Any VbaDocumentsBase::openDocument( const rtl::OUString& rFileName, const uno::Any& ReadOnly, const uno::Sequence< beans::PropertyValue >& rProps ) throw (uno::RuntimeException)
299 : : {
300 : : // #163808# determine state of Application.ScreenUpdating and Application.Interactive symbols (before new document is opened)
301 [ # # ][ # # ]: 0 : uno::Reference< XApplicationBase > xApplication( Application(), uno::UNO_QUERY );
302 [ # # ][ # # ]: 0 : sal_Bool bScreenUpdating = !xApplication.is() || xApplication->getScreenUpdating();
[ # # ][ # # ]
303 [ # # ][ # # ]: 0 : sal_Bool bInteractive = !xApplication.is() || xApplication->getInteractive();
[ # # ][ # # ]
304 : :
305 : : // we need to detect if this is a URL, if not then assume its a file path
306 : 0 : rtl::OUString aURL;
307 [ # # ]: 0 : INetURLObject aObj;
308 [ # # ]: 0 : aObj.SetURL( rFileName );
309 : 0 : bool bIsURL = aObj.GetProtocol() != INET_PROT_NOT_VALID;
310 [ # # ]: 0 : if ( bIsURL )
311 : 0 : aURL = rFileName;
312 : : else
313 [ # # ]: 0 : osl::FileBase::getFileURLFromSystemPath( rFileName, aURL );
314 : : uno::Reference< lang::XMultiComponentFactory > xSMgr(
315 [ # # ][ # # ]: 0 : mxContext->getServiceManager(), uno::UNO_QUERY_THROW );
[ # # ]
316 : : uno::Reference< frame::XDesktop > xDesktop
317 [ # # ]: 0 : (xSMgr->createInstanceWithContext(::rtl::OUString("com.sun.star.frame.Desktop") , mxContext),
318 [ # # ][ # # ]: 0 : uno::UNO_QUERY_THROW );
319 : : uno::Reference< frame::XComponentLoader > xLoader(
320 [ # # ]: 0 : xSMgr->createInstanceWithContext(
321 : : ::rtl::OUString("com.sun.star.frame.Desktop"),
322 : 0 : mxContext),
323 [ # # ][ # # ]: 0 : uno::UNO_QUERY_THROW );
324 : :
325 [ # # ]: 0 : uno::Sequence< beans::PropertyValue > sProps( rProps );
326 [ # # ]: 0 : sProps.realloc( sProps.getLength() + 1 );
327 [ # # ]: 0 : sProps[ sProps.getLength() - 1 ].Name = rtl::OUString( "MacroExecutionMode" );
328 [ # # ][ # # ]: 0 : sProps[ sProps.getLength() - 1 ].Value <<= document::MacroExecMode::ALWAYS_EXECUTE_NO_WARN;
329 : :
330 [ # # ]: 0 : if ( ReadOnly.hasValue() )
331 : : {
332 : 0 : sal_Bool bIsReadOnly = sal_False; ReadOnly >>= bIsReadOnly;
333 [ # # ]: 0 : if ( bIsReadOnly )
334 : : {
335 [ # # ]: 0 : sProps.realloc( sProps.getLength() + 1 );
336 [ # # ]: 0 : sProps[ sProps.getLength() - 1 ].Name = rtl::OUString( "ReadOnly" );
337 [ # # ][ # # ]: 0 : sProps[ sProps.getLength() - 1 ].Value <<= true;
338 : : }
339 : : }
340 : :
341 [ # # ]: 0 : uno::Reference< lang::XComponent > xComponent = xLoader->loadComponentFromURL( aURL,
342 : : rtl::OUString( "_default" ),
343 : : frame::FrameSearchFlag::CREATE,
344 [ # # ]: 0 : sProps);
345 : :
346 : : // #163808# lock document controllers and container window if specified by application
347 [ # # ]: 0 : lclSetupComponent( xComponent, bScreenUpdating, bInteractive );
348 : :
349 [ # # ][ # # ]: 0 : return uno::makeAny( xComponent );
[ # # ]
350 : : }
351 : :
352 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|