bump product version to 7.2.5.1
[LibreOffice.git] / desktop / source / app / dispatchwatcher.cxx
blob0e39415d8fab1fc85d7fe1a386cfa1a82936234d
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
22 #include <sal/log.hxx>
23 #include <sfx2/docfile.hxx>
24 #include <sfx2/docfilt.hxx>
25 #include <sfx2/fcontnr.hxx>
26 #include <svl/fstathelper.hxx>
28 #include <app.hxx>
29 #include "dispatchwatcher.hxx"
30 #include "officeipcthread.hxx"
31 #include <rtl/ustring.hxx>
32 #include <comphelper/processfactory.hxx>
33 #include <comphelper/string.hxx>
34 #include <comphelper/synchronousdispatch.hxx>
35 #include <com/sun/star/io/IOException.hpp>
36 #include <com/sun/star/util/XCloseable.hpp>
37 #include <com/sun/star/util/CloseVetoException.hpp>
38 #include <com/sun/star/task/InteractionHandler.hpp>
39 #include <com/sun/star/util/URL.hpp>
40 #include <com/sun/star/frame/Desktop.hpp>
41 #include <com/sun/star/container/XContainerQuery.hpp>
42 #include <com/sun/star/container/XEnumeration.hpp>
43 #include <com/sun/star/frame/XDispatch.hpp>
44 #include <com/sun/star/frame/XNotifyingDispatch.hpp>
45 #include <com/sun/star/beans/PropertyValue.hpp>
46 #include <com/sun/star/view/XPrintable.hpp>
47 #include <com/sun/star/util/URLTransformer.hpp>
48 #include <com/sun/star/util/XURLTransformer.hpp>
49 #include <com/sun/star/document/MacroExecMode.hpp>
50 #include <com/sun/star/document/XTypeDetection.hpp>
51 #include <com/sun/star/document/UpdateDocMode.hpp>
52 #include <com/sun/star/frame/XStorable.hpp>
53 #include <com/sun/star/script/XLibraryContainer2.hpp>
54 #include <com/sun/star/document/XEmbeddedScripts.hpp>
56 #include <comphelper/sequence.hxx>
57 #include <tools/diagnose_ex.h>
58 #include <tools/urlobj.hxx>
59 #include <unotools/mediadescriptor.hxx>
60 #include <unotools/tempfile.hxx>
62 #include <osl/thread.hxx>
63 #include <osl/file.hxx>
64 #include <iostream>
65 #include <string_view>
67 using namespace ::osl;
68 using namespace ::com::sun::star::uno;
69 using namespace ::com::sun::star::util;
70 using namespace ::com::sun::star::lang;
71 using namespace ::com::sun::star::frame;
72 using namespace ::com::sun::star::container;
73 using namespace ::com::sun::star::beans;
74 using namespace ::com::sun::star::view;
75 using namespace ::com::sun::star::task;
76 using namespace ::com::sun::star::document;
78 namespace document = ::com::sun::star::document;
80 namespace desktop
83 namespace {
85 struct DispatchHolder
87 DispatchHolder( const URL& rURL, Reference< XDispatch > const & rDispatch ) :
88 aURL( rURL ), xDispatch( rDispatch ) {}
90 URL aURL;
91 Reference< XDispatch > xDispatch;
94 std::shared_ptr<const SfxFilter> impl_lookupExportFilterForUrl( std::u16string_view rUrl, std::u16string_view rFactory )
96 // create the list of filters
97 OUString sQuery = "getSortedFilterList()"
98 ":module=" +
99 OUString::Concat(rFactory) + // use long name here !
100 ":iflags=" +
101 OUString::number(static_cast<sal_Int32>(SfxFilterFlags::EXPORT)) +
102 ":eflags=" +
103 OUString::number(static_cast<int>(SFX_FILTER_NOTINSTALLED));
105 const Reference< XComponentContext > xContext( comphelper::getProcessComponentContext() );
106 const Reference< XContainerQuery > xFilterFactory(
107 xContext->getServiceManager()->createInstanceWithContext( "com.sun.star.document.FilterFactory", xContext ),
108 UNO_QUERY_THROW );
110 std::shared_ptr<const SfxFilter> pBestMatch;
112 const Reference< XEnumeration > xFilterEnum(
113 xFilterFactory->createSubSetEnumerationByQuery( sQuery ), UNO_SET_THROW );
114 while ( xFilterEnum->hasMoreElements() )
116 comphelper::SequenceAsHashMap aFilterProps( xFilterEnum->nextElement() );
117 const OUString aName( aFilterProps.getUnpackedValueOrDefault( "Name", OUString() ) );
118 if ( !aName.isEmpty() )
120 std::shared_ptr<const SfxFilter> pFilter( SfxFilter::GetFilterByName( aName ) );
121 if ( pFilter && pFilter->CanExport() && pFilter->GetWildcard().Matches( rUrl ) )
123 if ( !pBestMatch || ( SfxFilterFlags::PREFERED & pFilter->GetFilterFlags() ) )
124 pBestMatch = pFilter;
129 return pBestMatch;
132 std::shared_ptr<const SfxFilter> impl_getExportFilterFromUrl(
133 const OUString& rUrl, const OUString& rFactory)
137 const Reference< XComponentContext > xContext( comphelper::getProcessComponentContext() );
138 const Reference< document::XTypeDetection > xTypeDetector(
139 xContext->getServiceManager()->createInstanceWithContext( "com.sun.star.document.TypeDetection", xContext ),
140 UNO_QUERY_THROW );
141 const OUString aTypeName( xTypeDetector->queryTypeByURL( rUrl ) );
143 std::shared_ptr<const SfxFilter> pFilter( SfxFilterMatcher( rFactory ).GetFilter4EA( aTypeName, SfxFilterFlags::EXPORT ) );
144 if ( !pFilter )
145 pFilter = impl_lookupExportFilterForUrl( rUrl, rFactory );
146 if ( !pFilter )
148 OUString aTempName;
149 FileBase::getSystemPathFromFileURL( rUrl, aTempName );
150 OString aSource = OUStringToOString ( aTempName, osl_getThreadTextEncoding() );
151 std::cerr << "Error: no export filter for " << aSource << " found, aborting." << std::endl;
154 return pFilter;
156 catch ( const Exception& )
158 return nullptr;
162 OUString impl_GuessFilter( const OUString& rUrlOut, const OUString& rDocService )
164 OUString aOutFilter;
165 std::shared_ptr<const SfxFilter> pOutFilter = impl_getExportFilterFromUrl( rUrlOut, rDocService );
166 if (pOutFilter)
167 aOutFilter = pOutFilter->GetFilterName();
169 return aOutFilter;
172 /// dump scripts in a document to the console.
173 void scriptCat(const Reference< XModel >& xDoc )
175 Reference< XEmbeddedScripts > xScriptAccess( xDoc, UNO_QUERY );
176 if (!xScriptAccess)
178 std::cout << "No script access\n";
179 return;
182 // ignore xScriptAccess->getDialogLibraries() for now
183 Reference< css::script::XLibraryContainer2 > xLibraries(
184 xScriptAccess->getBasicLibraries() );
186 if ( !xLibraries.is() )
188 std::cout << "No script libraries\n";
189 return;
192 const Sequence< OUString > aLibNames = xLibraries->getElementNames();
193 std::cout << "Libraries: " << aLibNames.getLength() << "\n";
194 for (OUString const & libName : aLibNames)
196 std::cout << "Library: '" << libName << "' children: ";
197 Reference< XNameContainer > xContainer;
198 try {
199 if (!xLibraries->isLibraryLoaded( libName ))
200 xLibraries->loadLibrary( libName );
201 xContainer = Reference< XNameContainer >(
202 xLibraries->getByName( libName ), UNO_QUERY );
204 catch (const css::uno::Exception &e)
206 std::cout << "[" << libName << "] - failed to load library: " << e.Message << "\n";
207 continue;
209 if( !xContainer.is() )
210 std::cout << "0\n";
211 else
213 Sequence< OUString > aObjectNames = xContainer->getElementNames();
215 std::cout << aObjectNames.getLength() << "\n\n";
216 for ( sal_Int32 j = 0 ; j < aObjectNames.getLength() ; ++j )
218 OUString &rObjectName = aObjectNames[j];
222 Any aCode = xContainer->getByName( rObjectName );
223 OUString aCodeString;
225 if (! (aCode >>= aCodeString ) )
226 std::cout << "[" << rObjectName << "] - error fetching code\n";
227 else
228 std::cout << "[" << rObjectName << "]\n"
229 << aCodeString.trim()
230 << "\n[/" << rObjectName << "]\n";
232 catch (const css::uno::Exception &e)
234 std::cout << "[" << rObjectName << "] - exception " << e.Message << " fetching code\n";
237 if (j < aObjectNames.getLength() - 1)
238 std::cout << "\n----------------------------------------------------------\n";
239 std::cout << "\n";
245 // Perform batch print
246 void batchPrint( const OUString &rPrinterName, const Reference< XPrintable > &xDoc,
247 const INetURLObject &aObj, const OUString &aName )
249 OUString aFilterOut;
250 OUString aPrinterName;
251 sal_Int32 nPathIndex = rPrinterName.lastIndexOf( ';' );
252 if( nPathIndex != -1 )
253 aFilterOut=rPrinterName.copy( nPathIndex+1 );
254 if( nPathIndex != 0 )
255 aPrinterName=rPrinterName.copy( 0, nPathIndex );
257 INetURLObject aOutFilename( aObj );
258 aOutFilename.SetExtension( u"pdf" );
259 FileBase::getFileURLFromSystemPath( aFilterOut, aFilterOut );
260 OUString aOutFile = aFilterOut + "/" + aOutFilename.getName();
262 OUString aTempName;
263 FileBase::getSystemPathFromFileURL( aName, aTempName );
264 OString aSource8 = OUStringToOString ( aTempName, osl_getThreadTextEncoding() );
265 FileBase::getSystemPathFromFileURL( aOutFile, aTempName );
266 OString aTargetURL8 = OUStringToOString(aTempName, osl_getThreadTextEncoding() );
268 std::cout << "print " << aSource8 << " -> " << aTargetURL8;
269 std::cout << " using " << (aPrinterName.isEmpty() ? "<default_printer>" : OUStringToOString( aPrinterName, osl_getThreadTextEncoding() ));
270 std::cout << std::endl;
272 // create the custom printer, if given
273 Sequence < PropertyValue > aPrinterArgs( 1 );
274 if( !aPrinterName.isEmpty() )
276 aPrinterArgs[0].Name = "Name";
277 aPrinterArgs[0].Value <<= aPrinterName;
278 xDoc->setPrinter( aPrinterArgs );
281 // print ( also without user interaction )
282 aPrinterArgs.realloc(2);
283 aPrinterArgs[0].Name = "FileName";
284 aPrinterArgs[0].Value <<= aOutFile;
285 aPrinterArgs[1].Name = "Wait";
286 aPrinterArgs[1].Value <<= true;
287 xDoc->print( aPrinterArgs );
290 } // anonymous namespace
292 DispatchWatcher::DispatchWatcher()
293 : m_nRequestCount(0)
298 DispatchWatcher::~DispatchWatcher()
303 bool DispatchWatcher::executeDispatchRequests( const std::vector<DispatchRequest>& aDispatchRequestsList, bool bNoTerminate )
305 Reference< XDesktop2 > xDesktop = css::frame::Desktop::create( ::comphelper::getProcessComponentContext() );
307 std::vector< DispatchHolder > aDispatches;
308 bool bSetInputFilter = false;
309 OUString aForcedInputFilter;
311 for (auto const & aDispatchRequest: aDispatchRequestsList)
313 // Set Input Filter
314 if ( aDispatchRequest.aRequestType == REQUEST_INFILTER )
316 bSetInputFilter = true;
317 aForcedInputFilter = aDispatchRequest.aURL;
318 RequestHandler::RequestsCompleted();
319 continue;
322 // create parameter array
323 std::vector<PropertyValue> aArgs;
325 // mark request as user interaction from outside
326 aArgs.emplace_back("Referer", 0, Any(OUString("private:OpenEvent")),
327 PropertyState_DIRECT_VALUE);
329 OUString aTarget("_default");
331 if ( aDispatchRequest.aRequestType == REQUEST_PRINT ||
332 aDispatchRequest.aRequestType == REQUEST_PRINTTO ||
333 aDispatchRequest.aRequestType == REQUEST_BATCHPRINT ||
334 aDispatchRequest.aRequestType == REQUEST_CONVERSION ||
335 aDispatchRequest.aRequestType == REQUEST_CAT ||
336 aDispatchRequest.aRequestType == REQUEST_SCRIPT_CAT)
338 // documents opened for printing are opened readonly because they must be opened as a
339 // new document and this document could be open already
340 aArgs.emplace_back("ReadOnly", 0, Any(true), PropertyState_DIRECT_VALUE);
341 // always open a new document for printing, because it must be disposed afterwards
342 aArgs.emplace_back("OpenNewView", 0, Any(true), PropertyState_DIRECT_VALUE);
343 // printing is done in a hidden view
344 aArgs.emplace_back("Hidden", 0, Any(true), PropertyState_DIRECT_VALUE);
345 // load document for printing without user interaction
346 aArgs.emplace_back("Silent", 0, Any(true), PropertyState_DIRECT_VALUE);
348 // hidden documents should never be put into open tasks
349 aTarget = "_blank";
351 else
353 Reference < XInteractionHandler2 > xInteraction(
354 InteractionHandler::createWithParent(::comphelper::getProcessComponentContext(), nullptr) );
356 aArgs.emplace_back("InteractionHandler", 0, Any(xInteraction),
357 PropertyState_DIRECT_VALUE);
359 aArgs.emplace_back("MacroExecutionMode", 0,
360 Any(css::document::MacroExecMode::USE_CONFIG),
361 PropertyState_DIRECT_VALUE);
363 aArgs.emplace_back("UpdateDocMode", 0,
364 Any(css::document::UpdateDocMode::ACCORDING_TO_CONFIG),
365 PropertyState_DIRECT_VALUE);
368 if ( !aDispatchRequest.aPreselectedFactory.isEmpty() )
370 aArgs.emplace_back(utl::MediaDescriptor::PROP_DOCUMENTSERVICE(), 0,
371 Any(aDispatchRequest.aPreselectedFactory),
372 PropertyState_DIRECT_VALUE);
375 OUString aName( GetURL_Impl( aDispatchRequest.aURL, aDispatchRequest.aCwdUrl ) );
377 // load the document ... if they are loadable!
378 // Otherwise try to dispatch it ...
379 Reference < XPrintable > xDoc;
381 ( aName.startsWith( ".uno" ) ) ||
382 ( aName.startsWith( "slot:" ) ) ||
383 ( aName.startsWith( "macro:" ) ) ||
384 ( aName.startsWith("vnd.sun.star.script") )
387 // Attention: URL must be parsed full. Otherwise some detections on it will fail!
388 // It doesn't matter, if parser isn't available. Because; We try loading of URL then ...
389 URL aURL ;
390 aURL.Complete = aName;
392 Reference < XDispatch > xDispatcher ;
393 Reference < XURLTransformer > xParser ( URLTransformer::create(::comphelper::getProcessComponentContext()) );
395 if( xParser.is() )
396 xParser->parseStrict( aURL );
398 xDispatcher = xDesktop->queryDispatch( aURL, OUString(), 0 );
399 SAL_WARN_IF(
400 !xDispatcher.is(), "desktop.app",
401 "unsupported dispatch request <" << aName << ">");
402 if( xDispatcher.is() )
405 osl::MutexGuard aGuard(m_mutex);
406 // Remember request so we can find it in statusChanged!
407 m_nRequestCount++;
410 // Use local vector to store dispatcher because we have to fill our request container before
411 // we can dispatch. Otherwise it would be possible that statusChanged is called before we dispatched all requests!!
412 aDispatches.emplace_back( aURL, xDispatcher );
415 else if ( aName.startsWith( "service:" ) )
417 // TODO: the dispatch has to be done for loadComponentFromURL as well.
418 URL aURL ;
419 aURL.Complete = aName;
421 Reference < XDispatch > xDispatcher ;
422 Reference < XURLTransformer > xParser ( URLTransformer::create(::comphelper::getProcessComponentContext()) );
424 if( xParser.is() )
425 xParser->parseStrict( aURL );
427 xDispatcher = xDesktop->queryDispatch( aURL, OUString(), 0 );
429 if( xDispatcher.is() )
433 // We have to be listener to catch errors during dispatching URLs.
434 // Otherwise it would be possible to have an office running without an open
435 // window!!
436 Sequence < PropertyValue > aArgs2(1);
437 aArgs2[0].Name = "SynchronMode";
438 aArgs2[0].Value <<= true;
439 Reference < XNotifyingDispatch > xDisp( xDispatcher, UNO_QUERY );
440 if ( xDisp.is() )
441 xDisp->dispatchWithNotification( aURL, aArgs2, this );
442 else
443 xDispatcher->dispatch( aURL, aArgs2 );
445 catch (const css::uno::Exception&)
447 TOOLS_WARN_EXCEPTION(
448 "desktop.app",
449 "Desktop::OpenDefault() ignoring Exception while calling XNotifyingDispatch");
453 else
455 INetURLObject aObj( aName );
456 if ( aObj.GetProtocol() == INetProtocol::PrivSoffice )
457 aTarget = "_default";
459 // Set "AsTemplate" argument according to request type
460 if ( aDispatchRequest.aRequestType == REQUEST_FORCENEW ||
461 aDispatchRequest.aRequestType == REQUEST_FORCEOPEN )
463 aArgs.emplace_back("AsTemplate", 0,
464 Any(aDispatchRequest.aRequestType == REQUEST_FORCENEW),
465 PropertyState_DIRECT_VALUE);
468 // if we are called in viewmode, open document read-only
469 if(aDispatchRequest.aRequestType == REQUEST_VIEW) {
470 aArgs.emplace_back("ReadOnly", 0, Any(true), PropertyState_DIRECT_VALUE);
473 // if we are called with --show set Start in mediadescriptor
474 if(aDispatchRequest.aRequestType == REQUEST_START) {
475 aArgs.emplace_back("StartPresentation", 0, Any(true), PropertyState_DIRECT_VALUE);
478 // Force input filter, if possible
479 if( bSetInputFilter )
481 sal_Int32 nFilterOptionsIndex = 0;
482 aArgs.emplace_back("FilterName", 0,
483 Any(aForcedInputFilter.getToken(0, ':', nFilterOptionsIndex)),
484 PropertyState_DIRECT_VALUE);
486 if (0 < nFilterOptionsIndex)
488 aArgs.emplace_back("FilterOptions", 0,
489 Any(aForcedInputFilter.copy(nFilterOptionsIndex)),
490 PropertyState_DIRECT_VALUE);
494 // This is a synchron loading of a component so we don't have to deal with our statusChanged listener mechanism.
497 xDoc.set(comphelper::SynchronousDispatch::dispatch(
498 xDesktop, aName, aTarget, comphelper::containerToSequence(aArgs)),
499 UNO_QUERY);
501 catch (const css::lang::IllegalArgumentException&)
503 TOOLS_WARN_EXCEPTION(
504 "desktop.app",
505 "Dispatchwatcher IllegalArgumentException while calling loadComponentFromURL");
507 catch (const css::io::IOException&)
509 TOOLS_WARN_EXCEPTION(
510 "desktop.app",
511 "Dispatchwatcher IOException while calling loadComponentFromURL");
513 if ( aDispatchRequest.aRequestType == REQUEST_OPEN ||
514 aDispatchRequest.aRequestType == REQUEST_VIEW ||
515 aDispatchRequest.aRequestType == REQUEST_START ||
516 aDispatchRequest.aRequestType == REQUEST_FORCEOPEN ||
517 aDispatchRequest.aRequestType == REQUEST_FORCENEW )
519 // request is completed
520 RequestHandler::RequestsCompleted();
522 else if ( aDispatchRequest.aRequestType == REQUEST_PRINT ||
523 aDispatchRequest.aRequestType == REQUEST_PRINTTO ||
524 aDispatchRequest.aRequestType == REQUEST_BATCHPRINT ||
525 aDispatchRequest.aRequestType == REQUEST_CONVERSION ||
526 aDispatchRequest.aRequestType == REQUEST_CAT ||
527 aDispatchRequest.aRequestType == REQUEST_SCRIPT_CAT )
529 if ( xDoc.is() )
531 // Do we need to save the document in a different format?
532 if ( aDispatchRequest.aRequestType == REQUEST_CONVERSION ||
533 aDispatchRequest.aRequestType == REQUEST_CAT )
535 // FIXME: factor out into a method ...
536 Reference< XStorable > xStorable( xDoc, UNO_QUERY );
537 if ( xStorable.is() ) {
538 OUString aParam = aDispatchRequest.aPrinterName;
539 sal_Int32 nPathIndex = aParam.lastIndexOf( ';' );
540 sal_Int32 nFilterIndex = aParam.indexOf( ':' );
541 sal_Int32 nImgFilterIndex = aParam.lastIndexOf( '|' );
542 if( nPathIndex < nFilterIndex )
543 nFilterIndex = -1;
545 OUString aFilterOut;
546 OUString aImgOut;
547 OUString aFilter;
548 OUString aFilterExt;
549 bool bGuess = false;
551 if( nFilterIndex >= 0 )
553 aFilter = aParam.copy( nFilterIndex+1, nPathIndex-nFilterIndex-1 );
554 aFilterExt = aParam.copy( 0, nFilterIndex );
556 else
558 // Guess
559 bGuess = true;
560 aFilterExt = aParam.copy( 0, nPathIndex );
563 if( nImgFilterIndex >= 0 )
565 aImgOut = aParam.copy( nImgFilterIndex+1 );
566 aFilterOut = aParam.copy( nPathIndex+1, nImgFilterIndex-nPathIndex-1 );
568 else
569 aFilterOut = aParam.copy( nPathIndex+1 );
571 FileBase::getFileURLFromSystemPath( aFilterOut, aFilterOut );
572 INetURLObject aOutFilename(aFilterOut);
573 aOutFilename.Append(aObj.getName(INetURLObject::LAST_SEGMENT, true,
574 INetURLObject::DecodeMechanism::NONE));
575 aOutFilename.SetExtension(aFilterExt);
576 OUString aOutFile
577 = aOutFilename.GetMainURL(INetURLObject::DecodeMechanism::NONE);
579 std::unique_ptr<utl::TempFile> fileForCat;
580 if( aDispatchRequest.aRequestType == REQUEST_CAT )
582 fileForCat = std::make_unique<utl::TempFile>();
583 if (fileForCat->IsValid())
584 fileForCat->EnableKillingFile();
585 else
586 std::cerr << "Error: Cannot create temporary file..." << std::endl ;
587 aOutFile = fileForCat->GetURL();
590 if ( bGuess )
592 OUString aDocService;
593 Reference< XModel > xModel( xDoc, UNO_QUERY );
594 if ( xModel.is() )
596 utl::MediaDescriptor aMediaDesc( xModel->getArgs() );
597 aDocService = aMediaDesc.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_DOCUMENTSERVICE(), OUString() );
599 aFilter = impl_GuessFilter( aOutFile, aDocService );
602 bool bMultiFileTarget = false;
604 if (aFilter.isEmpty())
606 std::cerr << "Error: no export filter" << std::endl;
608 else
610 sal_Int32 nFilterOptionsIndex = aFilter.indexOf(':');
611 sal_Int32 nProps = ( 0 < nFilterOptionsIndex ) ? 4 : 3;
613 if ( !aImgOut.isEmpty() )
614 nProps +=1;
615 Sequence<PropertyValue> conversionProperties( nProps );
616 conversionProperties[0].Name = "ConversionRequestOrigin";
617 conversionProperties[0].Value <<= OUString("CommandLine");
618 conversionProperties[1].Name = "Overwrite";
619 conversionProperties[1].Value <<= true;
621 conversionProperties[2].Name = "FilterName";
622 if( 0 < nFilterOptionsIndex )
624 OUString sFilterName = aFilter.copy(0, nFilterOptionsIndex);
625 OUString sFilterOptions = aFilter.copy(nFilterOptionsIndex + 1);
627 if (sFilterName == "Text - txt - csv (StarCalc)")
629 sal_Int32 nIdx(0);
630 // If the 11th token is '-1' then we export a file
631 // per sheet where the file name is based on the suggested
632 // output filename concatenated with the sheet name, so adjust
633 // the output and overwrite messages
634 // If the 11th token is not present or numeric 0 then the
635 // default sheet is exported with the output filename. If it
636 // is numeric >0 then that sheet (1-based) with the output
637 // filename concatenated with the sheet name. So even if
638 // that is a single file, the multi file target mechanism is
639 // used.
640 const OUString aTok(sFilterOptions.getToken(11, ',', nIdx));
641 // Actual validity is checked in Calc, here just check for
642 // presence of numeric value at start.
643 bMultiFileTarget = (!aTok.isEmpty() && aTok.toInt32() != 0);
646 conversionProperties[2].Value <<= sFilterName;
648 conversionProperties[3].Name = "FilterOptions";
649 conversionProperties[3].Value <<= sFilterOptions;
651 else
653 conversionProperties[2].Value <<= aFilter;
656 if ( !aImgOut.isEmpty() )
658 assert(conversionProperties[nProps-1].Name.isEmpty());
659 conversionProperties[nProps-1].Name = "ImageFilter";
660 conversionProperties[nProps-1].Value <<= aImgOut;
663 OUString aTempName;
664 FileBase::getSystemPathFromFileURL(aName, aTempName);
665 OString aSource8 = OUStringToOString(aTempName, osl_getThreadTextEncoding());
666 FileBase::getSystemPathFromFileURL(aOutFile, aTempName);
667 OString aTargetURL8 = OUStringToOString(aTempName, osl_getThreadTextEncoding());
668 if (aDispatchRequest.aRequestType != REQUEST_CAT)
670 std::cout << "convert " << aSource8;
671 if (!bMultiFileTarget)
672 std::cout << " -> " << aTargetURL8;
673 std::cout << " using filter : " << OUStringToOString(aFilter, osl_getThreadTextEncoding()) << std::endl;
674 if (!bMultiFileTarget && FStatHelper::IsDocument(aOutFile))
675 std::cout << "Overwriting: " << OUStringToOString(aTempName, osl_getThreadTextEncoding()) << std::endl ;
679 xStorable->storeToURL(aOutFile, conversionProperties);
681 catch (const Exception& rException)
683 std::cerr << "Error: Please verify input parameters...";
684 if (!rException.Message.isEmpty())
685 std::cerr << " (" << rException.Message << ")";
686 std::cerr << std::endl;
689 if (fileForCat && fileForCat->IsValid())
691 SvStream* aStream = fileForCat->GetStream(StreamMode::STD_READ);
692 while (aStream->good())
694 OString aStr;
695 aStream->ReadLine(aStr, SAL_MAX_INT32);
696 for (sal_Int32 i = 0; i < aStr.getLength(); ++i)
698 std::cout << aStr[i];
700 std::cout << std::endl;
706 else if ( aDispatchRequest.aRequestType == REQUEST_SCRIPT_CAT )
708 Reference< XModel > xModel( xDoc, UNO_QUERY );
709 if( xModel.is() )
710 scriptCat( xModel );
712 else if ( aDispatchRequest.aRequestType == REQUEST_BATCHPRINT )
714 batchPrint( aDispatchRequest.aPrinterName, xDoc, aObj, aName );
716 else
718 if ( aDispatchRequest.aRequestType == REQUEST_PRINTTO )
720 // create the printer
721 Sequence < PropertyValue > aPrinterArgs( 1 );
722 aPrinterArgs[0].Name = "Name";
723 aPrinterArgs[0].Value <<= aDispatchRequest.aPrinterName;
724 xDoc->setPrinter( aPrinterArgs );
727 // print ( also without user interaction )
728 Sequence < PropertyValue > aPrinterArgs( 1 );
729 aPrinterArgs[0].Name = "Wait";
730 aPrinterArgs[0].Value <<= true;
731 xDoc->print( aPrinterArgs );
734 else
736 std::cerr << "Error: source file could not be loaded" << std::endl;
739 // remove the document
742 Reference < XCloseable > xClose( xDoc, UNO_QUERY );
743 if ( xClose.is() )
744 xClose->close( true );
745 else
747 Reference < XComponent > xComp( xDoc, UNO_QUERY );
748 if ( xComp.is() )
749 xComp->dispose();
752 catch (const css::util::CloseVetoException&)
756 // request is completed
757 RequestHandler::RequestsCompleted();
762 if ( !aDispatches.empty() )
764 // Execute all asynchronous dispatches now after we placed them into our request container!
765 Sequence < PropertyValue > aArgs( 2 );
766 aArgs[0].Name = "Referer";
767 aArgs[0].Value <<= OUString("private:OpenEvent");
768 aArgs[1].Name = "SynchronMode";
769 aArgs[1].Value <<= true;
771 for (const DispatchHolder & aDispatche : aDispatches)
773 Reference< XDispatch > xDispatch = aDispatche.xDispatch;
774 Reference < XNotifyingDispatch > xDisp( xDispatch, UNO_QUERY );
775 if ( xDisp.is() )
776 xDisp->dispatchWithNotification( aDispatche.aURL, aArgs, this );
777 else
780 osl::MutexGuard aGuard(m_mutex);
781 m_nRequestCount--;
783 xDispatch->dispatch( aDispatche.aURL, aArgs );
788 ::osl::ClearableMutexGuard aGuard(m_mutex);
789 bool bEmpty = (m_nRequestCount == 0);
790 aGuard.clear();
792 // No more asynchronous requests?
793 // The requests are removed from the request container after they called back to this
794 // implementation via statusChanged!!
795 if ( bEmpty && !bNoTerminate /*m_aRequestContainer.empty()*/ )
797 // We have to check if we have an open task otherwise we have to shutdown the office.
798 Reference< XElementAccess > xList = xDesktop->getFrames();
800 if ( !xList->hasElements() )
802 // We don't have any task open so we have to shutdown ourself!!
803 return xDesktop->terminate();
807 return false;
811 void SAL_CALL DispatchWatcher::disposing( const css::lang::EventObject& )
816 void SAL_CALL DispatchWatcher::dispatchFinished( const DispatchResultEvent& )
818 osl::ClearableMutexGuard aGuard(m_mutex);
819 sal_Int16 nCount = --m_nRequestCount;
820 aGuard.clear();
821 RequestHandler::RequestsCompleted();
822 if ( !nCount && !RequestHandler::AreRequestsPending() )
824 // We have to check if we have an open task otherwise we have to shutdown the office.
825 Reference< XDesktop2 > xDesktop = css::frame::Desktop::create( ::comphelper::getProcessComponentContext() );
826 Reference< XElementAccess > xList = xDesktop->getFrames();
828 if ( !xList->hasElements() )
830 // We don't have any task open so we have to shutdown ourself!!
831 xDesktop->terminate();
836 } // namespace desktop
838 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */