Files
loongoffice/desktop/source/app/dispatchwatcher.cxx
Maxim Monastirsky 9df3a83c30 Base the convert-to detection on the actual service
There is no need to run a type detection on the input
file (for a second time!), just to get the document service.

This also simplifies the conversion of some generic formats
like HTML and RTF, using Calc export filters. Previously
setting both input and output filters was required. Now it's
enough to set the input filter, or simply use --calc.

Change-Id: I825e0fe3e7368d6649acb434b13de53a4523064a
2014-08-22 00:02:06 +03:00

773 lines
32 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <sfx2/docfile.hxx>
#include <sfx2/docfilt.hxx>
#include <sfx2/fcontnr.hxx>
#include <osl/file.hxx>
#include <sfx2/app.hxx>
#include <svl/fstathelper.hxx>
#include "app.hxx"
#include "dispatchwatcher.hxx"
#include <rtl/ustring.hxx>
#include <comphelper/processfactory.hxx>
#include <comphelper/synchronousdispatch.hxx>
#include <com/sun/star/util/XCloseable.hpp>
#include <com/sun/star/util/CloseVetoException.hpp>
#include <com/sun/star/task/InteractionHandler.hpp>
#include <com/sun/star/util/URL.hpp>
#include <com/sun/star/frame/Desktop.hpp>
#include <com/sun/star/container/XContainerQuery.hpp>
#include <com/sun/star/container/XEnumeration.hpp>
#include <com/sun/star/frame/XFramesSupplier.hpp>
#include <com/sun/star/frame/XDispatch.hpp>
#include <com/sun/star/frame/XComponentLoader.hpp>
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/view/XPrintable.hpp>
#include <com/sun/star/frame/XDispatchProvider.hpp>
#include <com/sun/star/util/URLTransformer.hpp>
#include <com/sun/star/util/XURLTransformer.hpp>
#include <com/sun/star/document/MacroExecMode.hpp>
#include <com/sun/star/document/XTypeDetection.hpp>
#include <com/sun/star/document/UpdateDocMode.hpp>
#include <com/sun/star/frame/XStorable.hpp>
#include <tools/urlobj.hxx>
#include <unotools/mediadescriptor.hxx>
#include <vector>
#include <osl/thread.hxx>
#include <osl/file.hxx>
#include <osl/file.h>
#include <rtl/instance.hxx>
#include <iostream>
using namespace ::osl;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::util;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::frame;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::view;
using namespace ::com::sun::star::task;
namespace document = ::com::sun::star::document;
namespace desktop
{
struct DispatchHolder
{
DispatchHolder( const URL& rURL, Reference< XDispatch >& rDispatch ) :
aURL( rURL ), xDispatch( rDispatch ) {}
URL aURL;
OUString cwdUrl;
Reference< XDispatch > xDispatch;
};
namespace
{
const SfxFilter* impl_lookupExportFilterForUrl( const rtl::OUString& rUrl, const rtl::OUString& rFactory )
{
// create the list of filters
OUStringBuffer sQuery(256);
sQuery.append("getSortedFilterList()");
sQuery.append(":module=");
sQuery.append(rFactory); // use long name here !
sQuery.append(":iflags=");
sQuery.append(OUString::number(SFX_FILTER_EXPORT));
sQuery.append(":eflags=");
sQuery.append(OUString::number(SFX_FILTER_NOTINSTALLED));
const Reference< XComponentContext > xContext( comphelper::getProcessComponentContext() );
const Reference< XContainerQuery > xFilterFactory(
xContext->getServiceManager()->createInstanceWithContext( "com.sun.star.document.FilterFactory", xContext ),
UNO_QUERY_THROW );
const SfxFilter* pBestMatch = 0;
const Reference< XEnumeration > xFilterEnum(
xFilterFactory->createSubSetEnumerationByQuery( sQuery.makeStringAndClear() ), UNO_QUERY_THROW );
while ( xFilterEnum->hasMoreElements() )
{
comphelper::SequenceAsHashMap aFilterProps( xFilterEnum->nextElement() );
const rtl::OUString aName( aFilterProps.getUnpackedValueOrDefault( "Name", rtl::OUString() ) );
if ( !aName.isEmpty() )
{
const SfxFilter* const pFilter( SfxFilter::GetFilterByName( aName ) );
if ( pFilter && pFilter->CanExport() && pFilter->GetWildcard().Matches( rUrl ) )
{
if ( !pBestMatch || ( SFX_FILTER_PREFERED & pFilter->GetFilterFlags() ) )
pBestMatch = pFilter;
}
}
}
return pBestMatch;
}
const SfxFilter* impl_getExportFilterFromUrl( const rtl::OUString& rUrl, const rtl::OUString& rFactory ) try
{
const Reference< XComponentContext > xContext( comphelper::getProcessComponentContext() );
const Reference< document::XTypeDetection > xTypeDetector(
xContext->getServiceManager()->createInstanceWithContext( "com.sun.star.document.TypeDetection", xContext ),
UNO_QUERY_THROW );
const rtl::OUString aTypeName( xTypeDetector->queryTypeByURL( rUrl ) );
const SfxFilter* pFilter( SfxFilterMatcher( rFactory ).GetFilter4EA( aTypeName, SFX_FILTER_EXPORT ) );
if ( !pFilter )
pFilter = impl_lookupExportFilterForUrl( rUrl, rFactory );
if ( !pFilter )
{
SAL_INFO( "desktop.app", "no export filter for " << rUrl << "found, using the default filter for " << rFactory );
pFilter = SfxFilter::GetDefaultFilterFromFactory( rFactory );
}
return pFilter;
}
catch ( const Exception& )
{
return 0;
}
OUString impl_GuessFilter( const OUString& rUrlOut, const OUString& rDocService )
{
OUString aOutFilter;
const SfxFilter* pOutFilter = impl_getExportFilterFromUrl( rUrlOut, rDocService );
if (pOutFilter)
aOutFilter = pOutFilter->GetFilterName();
return aOutFilter;
}
}
namespace
{
class theWatcherMutex : public rtl::Static<Mutex, theWatcherMutex> {};
}
Mutex& DispatchWatcher::GetMutex()
{
return theWatcherMutex::get();
}
// Create or get the dispatch watcher implementation. This implementation must be
// a singleton to prevent access to the framework after it wants to terminate.
DispatchWatcher* DispatchWatcher::GetDispatchWatcher()
{
static Reference< XInterface > xDispatchWatcher;
static DispatchWatcher* pDispatchWatcher = NULL;
if ( !xDispatchWatcher.is() )
{
::osl::MutexGuard aGuard( GetMutex() );
if ( !xDispatchWatcher.is() )
{
pDispatchWatcher = new DispatchWatcher();
// We have to hold a reference to ourself forever to prevent our own destruction.
xDispatchWatcher = static_cast< cppu::OWeakObject *>( pDispatchWatcher );
}
}
return pDispatchWatcher;
}
DispatchWatcher::DispatchWatcher()
: m_nRequestCount(0)
{
}
DispatchWatcher::~DispatchWatcher()
{
}
bool DispatchWatcher::executeDispatchRequests( const DispatchList& aDispatchRequestsList, bool bNoTerminate )
{
Reference< XDesktop2 > xDesktop = css::frame::Desktop::create( ::comphelper::getProcessComponentContext() );
DispatchList::const_iterator p;
std::vector< DispatchHolder > aDispatches;
OUString aAsTemplateArg( "AsTemplate" );
bool bSetInputFilter = false;
OUString aForcedInputFilter;
for ( p = aDispatchRequestsList.begin(); p != aDispatchRequestsList.end(); ++p )
{
const DispatchRequest& aDispatchRequest = *p;
// create parameter array
sal_Int32 nCount = 4;
if ( !aDispatchRequest.aPreselectedFactory.isEmpty() )
nCount++;
// Set Input Filter
if ( aDispatchRequest.aRequestType == REQUEST_INFILTER )
{
bSetInputFilter = true;
aForcedInputFilter = aDispatchRequest.aURL;
OfficeIPCThread::RequestsCompleted( 1 );
continue;
}
// we need more properties for a print/print to request
if ( aDispatchRequest.aRequestType == REQUEST_PRINT ||
aDispatchRequest.aRequestType == REQUEST_PRINTTO ||
aDispatchRequest.aRequestType == REQUEST_BATCHPRINT ||
aDispatchRequest.aRequestType == REQUEST_CONVERSION)
nCount++;
Sequence < PropertyValue > aArgs( nCount );
// mark request as user interaction from outside
aArgs[0].Name = "Referer";
aArgs[0].Value <<= OUString("private:OpenEvent");
if ( aDispatchRequest.aRequestType == REQUEST_PRINT ||
aDispatchRequest.aRequestType == REQUEST_PRINTTO ||
aDispatchRequest.aRequestType == REQUEST_BATCHPRINT ||
aDispatchRequest.aRequestType == REQUEST_CONVERSION)
{
aArgs[1].Name = "ReadOnly";
aArgs[2].Name = "OpenNewView";
aArgs[3].Name = "Hidden";
aArgs[4].Name = "Silent";
}
else
{
Reference < XInteractionHandler2 > xInteraction(
InteractionHandler::createWithParent(::comphelper::getProcessComponentContext(), 0) );
aArgs[1].Name = "InteractionHandler";
aArgs[1].Value <<= xInteraction;
sal_Int16 nMacroExecMode = ::com::sun::star::document::MacroExecMode::USE_CONFIG;
aArgs[2].Name = "MacroExecutionMode";
aArgs[2].Value <<= nMacroExecMode;
sal_Int16 nUpdateDoc = ::com::sun::star::document::UpdateDocMode::ACCORDING_TO_CONFIG;
aArgs[3].Name = "UpdateDocMode";
aArgs[3].Value <<= nUpdateDoc;
}
if ( !aDispatchRequest.aPreselectedFactory.isEmpty() )
{
aArgs[nCount-1].Name = utl::MediaDescriptor::PROP_DOCUMENTSERVICE();
aArgs[nCount-1].Value <<= aDispatchRequest.aPreselectedFactory;
}
OUString aName( GetURL_Impl( aDispatchRequest.aURL, aDispatchRequest.aCwdUrl ) );
OUString aTarget("_default");
if ( aDispatchRequest.aRequestType == REQUEST_PRINT ||
aDispatchRequest.aRequestType == REQUEST_PRINTTO ||
aDispatchRequest.aRequestType == REQUEST_BATCHPRINT ||
aDispatchRequest.aRequestType == REQUEST_CONVERSION)
{
// documents opened for printing are opened readonly because they must be opened as a new document and this
// document could be open already
aArgs[1].Value <<= sal_True;
// always open a new document for printing, because it must be disposed afterwards
aArgs[2].Value <<= sal_True;
// printing is done in a hidden view
aArgs[3].Value <<= sal_True;
// load document for printing without user interaction
aArgs[4].Value <<= sal_True;
// hidden documents should never be put into open tasks
aTarget = "_blank";
}
// load the document ... if they are loadable!
// Otherwise try to dispatch it ...
Reference < XPrintable > xDoc;
if(
( aName.startsWith( ".uno" ) ) ||
( aName.startsWith( "slot:" ) ) ||
( aName.startsWith( "macro:" ) ) ||
( aName.startsWith("vnd.sun.star.script") )
)
{
// Attention: URL must be parsed full. Otherwise some detections on it will fail!
// It doesn't matter, if parser isn't available. Because; We try loading of URL then ...
URL aURL ;
aURL.Complete = aName;
Reference < XDispatch > xDispatcher ;
Reference < XURLTransformer > xParser ( URLTransformer::create(::comphelper::getProcessComponentContext()) );
if( xParser.is() )
xParser->parseStrict( aURL );
xDispatcher = xDesktop->queryDispatch( aURL, OUString(), 0 );
if( xDispatcher.is() )
{
{
::osl::ClearableMutexGuard aGuard( GetMutex() );
// Remember request so we can find it in statusChanged!
m_aRequestContainer.insert( DispatchWatcherHashMap::value_type( aURL.Complete, (sal_Int32)1 ) );
m_nRequestCount++;
}
// Use local vector to store dispatcher because we have to fill our request container before
// we can dispatch. Otherwise it would be possible that statusChanged is called before we dispatched all requests!!
aDispatches.push_back( DispatchHolder( aURL, xDispatcher ));
}
}
else if ( ( aName.startsWith( "service:" ) ) )
{
// TODO: the dispatch has to be done for loadComponentFromURL as well. Please ask AS for more details.
URL aURL ;
aURL.Complete = aName;
Reference < XDispatch > xDispatcher ;
Reference < XURLTransformer > xParser ( URLTransformer::create(::comphelper::getProcessComponentContext()) );
if( xParser.is() )
xParser->parseStrict( aURL );
xDispatcher = xDesktop->queryDispatch( aURL, OUString(), 0 );
if( xDispatcher.is() )
{
try
{
// We have to be listener to catch errors during dispatching URLs.
// Otherwise it would be possible to have an office running without an open
// window!!
Sequence < PropertyValue > aArgs2(1);
aArgs2[0].Name = "SynchronMode";
aArgs2[0].Value <<= sal_True;
Reference < XNotifyingDispatch > xDisp( xDispatcher, UNO_QUERY );
if ( xDisp.is() )
xDisp->dispatchWithNotification( aURL, aArgs2, DispatchWatcher::GetDispatchWatcher() );
else
xDispatcher->dispatch( aURL, aArgs2 );
}
catch (const ::com::sun::star::uno::Exception& e)
{
SAL_WARN(
"desktop.app",
"Desktop::OpenDefault() ignoring Exception while"
" calling XNotifyingDispatch: \"" << e.Message
<< "\"");
}
}
}
else
{
INetURLObject aObj( aName );
if ( aObj.GetProtocol() == INET_PROT_PRIVATE )
aTarget = "_default";
// Set "AsTemplate" argument according to request type
if ( aDispatchRequest.aRequestType == REQUEST_FORCENEW ||
aDispatchRequest.aRequestType == REQUEST_FORCEOPEN )
{
sal_Int32 nIndex = aArgs.getLength();
aArgs.realloc( nIndex+1 );
aArgs[nIndex].Name = aAsTemplateArg;
if ( aDispatchRequest.aRequestType == REQUEST_FORCENEW )
aArgs[nIndex].Value <<= sal_True;
else
aArgs[nIndex].Value <<= sal_False;
}
// if we are called in viewmode, open document read-only
if(aDispatchRequest.aRequestType == REQUEST_VIEW) {
sal_Int32 nIndex = aArgs.getLength();
aArgs.realloc(nIndex+1);
aArgs[nIndex].Name = "ReadOnly";
aArgs[nIndex].Value <<= sal_True;
}
// if we are called with -start set Start in mediadescriptor
if(aDispatchRequest.aRequestType == REQUEST_START) {
sal_Int32 nIndex = aArgs.getLength();
aArgs.realloc(nIndex+1);
aArgs[nIndex].Name = "StartPresentation";
aArgs[nIndex].Value <<= sal_True;
}
// Force input filter, if possible
if( bSetInputFilter )
{
sal_Int32 nIndex = aArgs.getLength();
aArgs.realloc(nIndex+1);
aArgs[nIndex].Name = "FilterName";
sal_Int32 nFilterOptionsIndex = aForcedInputFilter.indexOf( ':' );
if( 0 < nFilterOptionsIndex )
{
aArgs[nIndex].Value <<= aForcedInputFilter.copy( 0, nFilterOptionsIndex );
nIndex = aArgs.getLength();
aArgs.realloc(nIndex+1);
aArgs[nIndex].Name = "FilterOptions";
aArgs[nIndex].Value <<= aForcedInputFilter.copy( nFilterOptionsIndex+1 );
}
else
{
aArgs[nIndex].Value <<= aForcedInputFilter;
}
}
// This is a synchron loading of a component so we don't have to deal with our statusChanged listener mechanism.
try
{
xDoc = Reference < XPrintable >( ::comphelper::SynchronousDispatch::dispatch( xDesktop, aName, aTarget, 0, aArgs ), UNO_QUERY );
}
catch (const ::com::sun::star::lang::IllegalArgumentException& iae)
{
SAL_WARN(
"desktop.app",
"Dispatchwatcher IllegalArgumentException while calling"
" loadComponentFromURL: \"" << iae.Message << "\"");
}
catch (const com::sun::star::io::IOException& ioe)
{
SAL_WARN(
"desktop.app",
"Dispatchwatcher IOException while calling"
" loadComponentFromURL: \"" << ioe.Message << "\"");
}
if ( aDispatchRequest.aRequestType == REQUEST_OPEN ||
aDispatchRequest.aRequestType == REQUEST_VIEW ||
aDispatchRequest.aRequestType == REQUEST_START ||
aDispatchRequest.aRequestType == REQUEST_FORCEOPEN ||
aDispatchRequest.aRequestType == REQUEST_FORCENEW )
{
// request is completed
OfficeIPCThread::RequestsCompleted( 1 );
}
else if ( aDispatchRequest.aRequestType == REQUEST_PRINT ||
aDispatchRequest.aRequestType == REQUEST_PRINTTO ||
aDispatchRequest.aRequestType == REQUEST_BATCHPRINT ||
aDispatchRequest.aRequestType == REQUEST_CONVERSION ||
aDispatchRequest.aRequestType == REQUEST_CAT )
{
if ( xDoc.is() )
{
if ( aDispatchRequest.aRequestType == REQUEST_CONVERSION || aDispatchRequest.aRequestType == REQUEST_CAT ) {
Reference< XStorable > xStorable( xDoc, UNO_QUERY );
if ( xStorable.is() ) {
OUString aParam = aDispatchRequest.aPrinterName;
sal_Int32 nPathIndex = aParam.lastIndexOf( ';' );
sal_Int32 nFilterIndex = aParam.indexOf( ':' );
if( nPathIndex < nFilterIndex )
nFilterIndex = -1;
OUString aFilterOut=aParam.copy( nPathIndex+1 );
OUString aFilter;
OUString aFilterExt;
bool bGuess = false;
if( nFilterIndex >= 0 )
{
aFilter = aParam.copy( nFilterIndex+1, nPathIndex-nFilterIndex-1 );
aFilterExt = aParam.copy( 0, nFilterIndex );
}
else
{
// Guess
bGuess = true;
aFilterExt = aParam.copy( 0, nPathIndex );
}
INetURLObject aOutFilename( aObj );
aOutFilename.SetExtension( aFilterExt );
FileBase::getFileURLFromSystemPath( aFilterOut, aFilterOut );
OUString aOutFile = aFilterOut+
"/" +
aOutFilename.getName();
OUString fileForCat;
if( aDispatchRequest.aRequestType == REQUEST_CAT )
{
if( ::osl::FileBase::createTempFile(0, 0, &fileForCat) != ::osl::FileBase::E_None )
fprintf( stderr, "Error: Cannot create temporary file...\n" );
aOutFile = fileForCat;
}
if ( bGuess )
{
OUString aDocService;
Reference< XModel > xModel( xDoc, UNO_QUERY );
if ( xModel.is() )
{
utl::MediaDescriptor aMediaDesc( xModel->getArgs() );
aDocService = aMediaDesc.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_DOCUMENTSERVICE(), OUString() );
}
aFilter = impl_GuessFilter( aOutFile, aDocService );
}
sal_Int32 nFilterOptionsIndex = aFilter.indexOf( ':' );
Sequence<PropertyValue> conversionProperties( 0 < nFilterOptionsIndex ? 3 : 2 );
conversionProperties[0].Name = "Overwrite";
conversionProperties[0].Value <<= sal_True;
conversionProperties[1].Name = "FilterName";
if( 0 < nFilterOptionsIndex )
{
conversionProperties[1].Value <<= aFilter.copy( 0, nFilterOptionsIndex );
conversionProperties[2].Name = "FilterOptions";
conversionProperties[2].Value <<= aFilter.copy( nFilterOptionsIndex+1 );
}
else
{
conversionProperties[1].Value <<= aFilter;
}
OUString aTempName;
FileBase::getSystemPathFromFileURL( aName, aTempName );
OString aSource8 = OUStringToOString ( aTempName, RTL_TEXTENCODING_UTF8 );
FileBase::getSystemPathFromFileURL( aOutFile, aTempName );
OString aTargetURL8 = OUStringToOString(aTempName, RTL_TEXTENCODING_UTF8 );
if( aDispatchRequest.aRequestType != REQUEST_CAT )
{
printf("convert %s -> %s using %s\n", aSource8.getStr(), aTargetURL8.getStr(),
OUStringToOString( aFilter, RTL_TEXTENCODING_UTF8 ).getStr());
if( FStatHelper::IsDocument( aOutFile ) )
printf("Overwriting: %s\n",OUStringToOString( aTempName, RTL_TEXTENCODING_UTF8 ).getStr() );
}
try
{
xStorable->storeToURL( aOutFile, conversionProperties );
}
catch (const Exception&)
{
fprintf( stderr, "Error: Please reverify input parameters...\n" );
}
if( aDispatchRequest.aRequestType == REQUEST_CAT )
{
osl::File aFile( fileForCat );
osl::File::RC aRC = aFile.open( osl_File_OpenFlag_Read );
if( aRC != osl::File::E_None )
{
fprintf( stderr, "Error: Cannot read from temp file\n" );
}
else
{
sal_Bool eof;
for( ;; )
{
aFile.isEndOfFile( &eof );
if( eof )
break;
rtl::ByteSequence bseq;
aFile.readLine( bseq );
unsigned const char * aStr = reinterpret_cast< unsigned char const * >( bseq.getConstArray() );
for( sal_Int32 i = 0; i < bseq.getLength(); i++ )
{
std::cout << aStr[i];
}
std::cout << "\n";
}
aFile.close();
osl::File::remove( fileForCat );
}
}
}
} else if ( aDispatchRequest.aRequestType == REQUEST_BATCHPRINT ) {
OUString aParam = aDispatchRequest.aPrinterName;
sal_Int32 nPathIndex = aParam.lastIndexOf( ';' );
OUString aFilterOut;
OUString aPrinterName;
if( nPathIndex != -1 )
aFilterOut=aParam.copy( nPathIndex+1 );
if( nPathIndex != 0 )
aPrinterName=aParam.copy( 0, nPathIndex );
INetURLObject aOutFilename( aObj );
aOutFilename.SetExtension( "ps" );
FileBase::getFileURLFromSystemPath( aFilterOut, aFilterOut );
OUString aOutFile = aFilterOut+
"/" +
aOutFilename.getName();
OUString aTempName;
FileBase::getSystemPathFromFileURL( aName, aTempName );
OString aSource8 = OUStringToOString ( aTempName, RTL_TEXTENCODING_UTF8 );
FileBase::getSystemPathFromFileURL( aOutFile, aTempName );
OString aTargetURL8 = OUStringToOString(aTempName, RTL_TEXTENCODING_UTF8 );
printf("print %s -> %s using %s\n", aSource8.getStr(), aTargetURL8.getStr(),
aPrinterName.isEmpty() ?
"<default_printer>" : OUStringToOString( aPrinterName, RTL_TEXTENCODING_UTF8 ).getStr() );
// create the custom printer, if given
Sequence < PropertyValue > aPrinterArgs( 1 );
if( !aPrinterName.isEmpty() )
{
aPrinterArgs[0].Name = "Name";
aPrinterArgs[0].Value <<= aPrinterName;
xDoc->setPrinter( aPrinterArgs );
}
// print ( also without user interaction )
aPrinterArgs.realloc(2);
aPrinterArgs[0].Name = "FileName";
aPrinterArgs[0].Value <<= aOutFile;
aPrinterArgs[1].Name = "Wait";
aPrinterArgs[1].Value <<= true;
xDoc->print( aPrinterArgs );
} else {
if ( aDispatchRequest.aRequestType == REQUEST_PRINTTO )
{
// create the printer
Sequence < PropertyValue > aPrinterArgs( 1 );
aPrinterArgs[0].Name = "Name";
aPrinterArgs[0].Value <<= OUString( aDispatchRequest.aPrinterName );
xDoc->setPrinter( aPrinterArgs );
}
// print ( also without user interaction )
Sequence < PropertyValue > aPrinterArgs( 1 );
aPrinterArgs[0].Name = "Wait";
aPrinterArgs[0].Value <<= true;
xDoc->print( aPrinterArgs );
}
}
else
{
// place error message here ...
}
// remove the document
try
{
Reference < XCloseable > xClose( xDoc, UNO_QUERY );
if ( xClose.is() )
xClose->close( sal_True );
else
{
Reference < XComponent > xComp( xDoc, UNO_QUERY );
if ( xComp.is() )
xComp->dispose();
}
}
catch (const com::sun::star::util::CloseVetoException&)
{
}
// request is completed
OfficeIPCThread::RequestsCompleted( 1 );
}
}
}
if ( !aDispatches.empty() )
{
// Execute all asynchronous dispatches now after we placed them into our request container!
Sequence < PropertyValue > aArgs( 2 );
aArgs[0].Name = "Referer";
aArgs[0].Value <<= OUString("private:OpenEvent");
aArgs[1].Name = "SynchronMode";
aArgs[1].Value <<= sal_True;
for ( sal_uInt32 n = 0; n < aDispatches.size(); n++ )
{
Reference< XDispatch > xDispatch = aDispatches[n].xDispatch;
Reference < XNotifyingDispatch > xDisp( xDispatch, UNO_QUERY );
if ( xDisp.is() )
xDisp->dispatchWithNotification( aDispatches[n].aURL, aArgs, this );
else
{
::osl::ClearableMutexGuard aGuard( GetMutex() );
m_nRequestCount--;
aGuard.clear();
xDispatch->dispatch( aDispatches[n].aURL, aArgs );
}
}
}
::osl::ClearableMutexGuard aGuard( GetMutex() );
bool bEmpty = (m_nRequestCount == 0);
aGuard.clear();
// No more asynchronous requests?
// The requests are removed from the request container after they called back to this
// implementation via statusChanged!!
if ( bEmpty && !bNoTerminate /*m_aRequestContainer.empty()*/ )
{
// We have to check if we have an open task otherwise we have to shutdown the office.
aGuard.clear();
Reference< XElementAccess > xList( xDesktop->getFrames(), UNO_QUERY );
if ( !xList->hasElements() )
{
// We don't have any task open so we have to shutdown ourself!!
return xDesktop->terminate();
}
}
return false;
}
void SAL_CALL DispatchWatcher::disposing( const ::com::sun::star::lang::EventObject& )
throw(::com::sun::star::uno::RuntimeException, std::exception)
{
}
void SAL_CALL DispatchWatcher::dispatchFinished( const DispatchResultEvent& ) throw( RuntimeException, std::exception )
{
osl::ClearableMutexGuard aGuard( GetMutex() );
sal_Int16 nCount = --m_nRequestCount;
aGuard.clear();
OfficeIPCThread::RequestsCompleted( 1 );
if ( !nCount && !OfficeIPCThread::AreRequestsPending() )
{
// We have to check if we have an open task otherwise we have to shutdown the office.
Reference< XDesktop2 > xDesktop = css::frame::Desktop::create( ::comphelper::getProcessComponentContext() );
Reference< XElementAccess > xList( xDesktop->getFrames(), UNO_QUERY );
if ( !xList->hasElements() )
{
// We don't have any task open so we have to shutdown ourself!!
xDesktop->terminate();
}
}
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */