LanguageTool: don't crash if REST protocol isn't set
[LibreOffice.git] / sfx2 / source / doc / printhelper.cxx
blob2f0874ea976eae0e02cf0023f13f9292f5080f1d
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 .
21 #include "printhelper.hxx"
23 #include <com/sun/star/view/XPrintJob.hpp>
24 #include <com/sun/star/awt/Size.hpp>
25 #include <com/sun/star/lang/IllegalArgumentException.hpp>
26 #include <com/sun/star/view/PaperFormat.hpp>
27 #include <com/sun/star/view/PaperOrientation.hpp>
28 #include <com/sun/star/ucb/NameClash.hpp>
29 #include <com/sun/star/ucb/ContentCreationException.hpp>
30 #include <com/sun/star/ucb/CommandAbortedException.hpp>
31 #include <com/sun/star/frame/XModel.hpp>
32 #include <com/sun/star/view/DuplexMode.hpp>
33 #include <comphelper/processfactory.hxx>
34 #include <svl/itemset.hxx>
35 #include <svl/lstner.hxx>
36 #include <unotools/tempfile.hxx>
37 #include <osl/file.hxx>
38 #include <osl/thread.hxx>
39 #include <tools/urlobj.hxx>
40 #include <tools/diagnose_ex.h>
41 #include <ucbhelper/content.hxx>
42 #include <comphelper/multicontainer2.hxx>
43 #include <osl/mutex.hxx>
44 #include <cppuhelper/implbase.hxx>
45 #include <vcl/settings.hxx>
46 #include <vcl/svapp.hxx>
48 #include <sfx2/viewfrm.hxx>
49 #include <sfx2/viewsh.hxx>
50 #include <sfx2/printer.hxx>
51 #include <sfx2/objsh.hxx>
52 #include <sfx2/event.hxx>
54 #define SFX_PRINTABLESTATE_CANCELJOB css::view::PrintableState(-2)
56 using namespace ::com::sun::star;
57 using namespace ::com::sun::star::uno;
59 struct IMPL_PrintListener_DataContainer : public SfxListener
61 SfxObjectShellRef m_pObjectShell;
62 comphelper::OMultiTypeInterfaceContainerHelper2 m_aInterfaceContainer;
63 uno::Reference< css::view::XPrintJob> m_xPrintJob;
64 css::uno::Sequence< css::beans::PropertyValue > m_aPrintOptions;
66 explicit IMPL_PrintListener_DataContainer( ::osl::Mutex& aMutex)
67 : m_aInterfaceContainer ( aMutex )
72 void Notify( SfxBroadcaster& aBC ,
73 const SfxHint& aHint ) override ;
76 static awt::Size impl_Size_Object2Struct( const Size& aSize )
78 awt::Size aReturnValue;
79 aReturnValue.Width = aSize.Width() ;
80 aReturnValue.Height = aSize.Height() ;
81 return aReturnValue ;
84 static Size impl_Size_Struct2Object( const awt::Size& aSize )
86 Size aReturnValue;
87 aReturnValue.setWidth( aSize.Width ) ;
88 aReturnValue.setHeight( aSize.Height ) ;
89 return aReturnValue ;
92 namespace {
94 class SfxPrintJob_Impl : public cppu::WeakImplHelper
96 css::view::XPrintJob
99 IMPL_PrintListener_DataContainer* m_pData;
101 public:
102 explicit SfxPrintJob_Impl( IMPL_PrintListener_DataContainer* pData );
103 virtual Sequence< css::beans::PropertyValue > SAL_CALL getPrintOptions( ) override;
104 virtual Sequence< css::beans::PropertyValue > SAL_CALL getPrinter( ) override;
105 virtual Reference< css::view::XPrintable > SAL_CALL getPrintable( ) override;
106 virtual void SAL_CALL cancelJob() override;
111 SfxPrintJob_Impl::SfxPrintJob_Impl( IMPL_PrintListener_DataContainer* pData )
112 : m_pData( pData )
116 Sequence< css::beans::PropertyValue > SAL_CALL SfxPrintJob_Impl::getPrintOptions()
118 return m_pData->m_aPrintOptions;
121 Sequence< css::beans::PropertyValue > SAL_CALL SfxPrintJob_Impl::getPrinter()
123 if( m_pData->m_pObjectShell.is() )
125 Reference < view::XPrintable > xPrintable( m_pData->m_pObjectShell->GetModel(), UNO_QUERY );
126 if ( xPrintable.is() )
127 return xPrintable->getPrinter();
129 return Sequence< css::beans::PropertyValue >();
132 Reference< css::view::XPrintable > SAL_CALL SfxPrintJob_Impl::getPrintable()
134 Reference < view::XPrintable > xPrintable( m_pData->m_pObjectShell.is() ? m_pData->m_pObjectShell->GetModel() : nullptr, UNO_QUERY );
135 return xPrintable;
138 void SAL_CALL SfxPrintJob_Impl::cancelJob()
140 // FIXME: how to cancel PrintJob via API?!
141 if( m_pData->m_pObjectShell.is() )
142 m_pData->m_pObjectShell->Broadcast( SfxPrintingHint( SFX_PRINTABLESTATE_CANCELJOB ) );
145 SfxPrintHelper::SfxPrintHelper()
147 m_pData.reset(new IMPL_PrintListener_DataContainer(m_aMutex));
150 void SAL_CALL SfxPrintHelper::initialize( const css::uno::Sequence< css::uno::Any >& aArguments )
152 if ( !aArguments.hasElements() )
153 return;
155 css::uno::Reference < css::frame::XModel > xModel;
156 aArguments[0] >>= xModel;
157 m_pData->m_pObjectShell = SfxObjectShell::GetShellFromComponent(xModel);
158 if (m_pData->m_pObjectShell)
159 m_pData->StartListening(*m_pData->m_pObjectShell);
162 SfxPrintHelper::~SfxPrintHelper()
166 namespace
168 view::PaperFormat convertToPaperFormat(Paper eFormat)
170 view::PaperFormat eRet;
171 switch (eFormat)
173 case PAPER_A3:
174 eRet = view::PaperFormat_A3;
175 break;
176 case PAPER_A4:
177 eRet = view::PaperFormat_A4;
178 break;
179 case PAPER_A5:
180 eRet = view::PaperFormat_A5;
181 break;
182 case PAPER_B4_ISO:
183 eRet = view::PaperFormat_B4;
184 break;
185 case PAPER_B5_ISO:
186 eRet = view::PaperFormat_B5;
187 break;
188 case PAPER_LETTER:
189 eRet = view::PaperFormat_LETTER;
190 break;
191 case PAPER_LEGAL:
192 eRet = view::PaperFormat_LEGAL;
193 break;
194 case PAPER_TABLOID:
195 eRet = view::PaperFormat_TABLOID;
196 break;
197 case PAPER_USER:
198 default:
199 eRet = view::PaperFormat_USER;
200 break;
202 return eRet;
205 Paper convertToPaper(view::PaperFormat eFormat)
207 Paper eRet(PAPER_USER);
208 switch (eFormat)
210 case view::PaperFormat_A3:
211 eRet = PAPER_A3;
212 break;
213 case view::PaperFormat_A4:
214 eRet = PAPER_A4;
215 break;
216 case view::PaperFormat_A5:
217 eRet = PAPER_A5;
218 break;
219 case view::PaperFormat_B4:
220 eRet = PAPER_B4_ISO;
221 break;
222 case view::PaperFormat_B5:
223 eRet = PAPER_B5_ISO;
224 break;
225 case view::PaperFormat_LETTER:
226 eRet = PAPER_LETTER;
227 break;
228 case view::PaperFormat_LEGAL:
229 eRet = PAPER_LEGAL;
230 break;
231 case view::PaperFormat_TABLOID:
232 eRet = PAPER_TABLOID;
233 break;
234 case view::PaperFormat_USER:
235 eRet = PAPER_USER;
236 break;
237 case view::PaperFormat::PaperFormat_MAKE_FIXED_SIZE:
238 break;
239 //deliberate no default to force warn on a new papersize
241 return eRet;
246 // XPrintable
249 uno::Sequence< beans::PropertyValue > SAL_CALL SfxPrintHelper::getPrinter()
251 // object already disposed?
252 SolarMutexGuard aGuard;
254 // search for any view of this document that is currently printing
255 const Printer *pPrinter = nullptr;
256 SfxViewFrame *pViewFrm = m_pData->m_pObjectShell.is() ? SfxViewFrame::GetFirst( m_pData->m_pObjectShell.get(), false ) : nullptr;
257 SfxViewFrame* pFirst = pViewFrm;
258 while ( pViewFrm && !pPrinter )
260 pPrinter = pViewFrm->GetViewShell()->GetActivePrinter();
261 pViewFrm = SfxViewFrame::GetNext( *pViewFrm, m_pData->m_pObjectShell.get(), false );
264 // if no view is printing currently, use the permanent SfxPrinter instance
265 if ( !pPrinter && pFirst )
266 pPrinter = pFirst->GetViewShell()->GetPrinter(true);
268 if ( !pPrinter )
269 return uno::Sequence< beans::PropertyValue >();
271 uno::Sequence< beans::PropertyValue > aPrinter(8);
273 aPrinter.getArray()[7].Name = "CanSetPaperSize";
274 aPrinter.getArray()[7].Value <<= pPrinter->HasSupport( PrinterSupport::SetPaperSize );
276 aPrinter.getArray()[6].Name = "CanSetPaperFormat";
277 aPrinter.getArray()[6].Value <<= pPrinter->HasSupport( PrinterSupport::SetPaper );
279 aPrinter.getArray()[5].Name = "CanSetPaperOrientation";
280 aPrinter.getArray()[5].Value <<= pPrinter->HasSupport( PrinterSupport::SetOrientation );
282 aPrinter.getArray()[4].Name = "IsBusy";
283 aPrinter.getArray()[4].Value <<= pPrinter->IsPrinting();
285 aPrinter.getArray()[3].Name = "PaperSize";
286 awt::Size aSize = impl_Size_Object2Struct(pPrinter->GetPaperSize() );
287 aPrinter.getArray()[3].Value <<= aSize;
289 aPrinter.getArray()[2].Name = "PaperFormat";
290 view::PaperFormat eFormat = convertToPaperFormat(pPrinter->GetPaper());
291 aPrinter.getArray()[2].Value <<= eFormat;
293 aPrinter.getArray()[1].Name = "PaperOrientation";
294 view::PaperOrientation eOrient = static_cast<view::PaperOrientation>(pPrinter->GetOrientation());
295 aPrinter.getArray()[1].Value <<= eOrient;
297 aPrinter.getArray()[0].Name = "Name";
298 OUString sStringTemp = pPrinter->GetName() ;
299 aPrinter.getArray()[0].Value <<= sStringTemp;
301 return aPrinter;
305 // XPrintable
308 void SfxPrintHelper::impl_setPrinter(const uno::Sequence< beans::PropertyValue >& rPrinter,
309 VclPtr<SfxPrinter>& pPrinter,
310 SfxPrinterChangeFlags& nChangeFlags,
311 SfxViewShell*& pViewSh)
314 // Get old Printer
315 SfxViewFrame *pViewFrm = m_pData->m_pObjectShell.is() ?
316 SfxViewFrame::GetFirst( m_pData->m_pObjectShell.get(), false ) : nullptr;
317 if ( !pViewFrm )
318 return;
320 pViewSh = pViewFrm->GetViewShell();
321 pPrinter = pViewSh->GetPrinter(true);
322 if ( !pPrinter )
323 return;
325 // new Printer-Name available?
326 nChangeFlags = SfxPrinterChangeFlags::NONE;
327 sal_Int32 lDummy = 0;
328 auto pProp = std::find_if(rPrinter.begin(), rPrinter.end(),
329 [](const beans::PropertyValue &rProp) { return rProp.Name == "Name"; });
330 if (pProp != rPrinter.end())
332 OUString aPrinterName;
333 if ( ! ( pProp->Value >>= aPrinterName ) )
334 throw css::lang::IllegalArgumentException();
336 if ( aPrinterName != pPrinter->GetName() )
338 pPrinter = VclPtr<SfxPrinter>::Create( pPrinter->GetOptions().Clone(), aPrinterName );
339 nChangeFlags = SfxPrinterChangeFlags::PRINTER;
343 Size aSetPaperSize( 0, 0);
344 view::PaperFormat nPaperFormat = view::PaperFormat_USER;
346 // other properties
347 for ( const beans::PropertyValue &rProp : rPrinter )
349 // get Property-Value from printer description
350 // PaperOrientation-Property?
351 if ( rProp.Name == "PaperOrientation" )
353 view::PaperOrientation eOrient;
354 if ( !( rProp.Value >>= eOrient ) )
356 if ( !( rProp.Value >>= lDummy ) )
357 throw css::lang::IllegalArgumentException();
358 eOrient = static_cast<view::PaperOrientation>(lDummy);
361 if ( static_cast<Orientation>(eOrient) != pPrinter->GetOrientation() )
363 pPrinter->SetOrientation( static_cast<Orientation>(eOrient) );
364 nChangeFlags |= SfxPrinterChangeFlags::CHG_ORIENTATION;
368 // PaperFormat-Property?
369 else if ( rProp.Name == "PaperFormat" )
371 if ( !( rProp.Value >>= nPaperFormat ) )
373 if ( !( rProp.Value >>= lDummy ) )
374 throw css::lang::IllegalArgumentException();
375 nPaperFormat = static_cast<view::PaperFormat>(lDummy);
378 if ( convertToPaper(nPaperFormat) != pPrinter->GetPaper() )
380 pPrinter->SetPaper( convertToPaper(nPaperFormat) );
381 nChangeFlags |= SfxPrinterChangeFlags::CHG_SIZE;
385 // PaperSize-Property?
386 else if ( rProp.Name == "PaperSize" )
388 awt::Size aTempSize ;
389 if ( !( rProp.Value >>= aTempSize ) )
391 throw css::lang::IllegalArgumentException();
393 aSetPaperSize = impl_Size_Struct2Object(aTempSize);
396 // PrinterTray-Property
397 else if ( rProp.Name == "PrinterPaperTray" )
399 OUString aTmp;
400 if ( !( rProp.Value >>= aTmp ) )
401 throw css::lang::IllegalArgumentException();
402 const sal_uInt16 nCount = pPrinter->GetPaperBinCount();
403 for (sal_uInt16 nBin=0; nBin<nCount; nBin++)
405 OUString aName( pPrinter->GetPaperBinName(nBin) );
406 if ( aName == aTmp )
408 pPrinter->SetPaperBin(nBin);
409 break;
415 // The PaperSize may be set only when actually PAPER_USER
416 // applies, otherwise the driver could choose an invalid format.
417 if(nPaperFormat == view::PaperFormat_USER && aSetPaperSize.Width())
419 // Bug 56929 - MapMode of 100mm which recalculated when
420 // the device is set. Additionally only set if they were really changed.
421 aSetPaperSize = pPrinter->LogicToPixel(aSetPaperSize, MapMode(MapUnit::Map100thMM));
422 if( aSetPaperSize != pPrinter->GetPaperSizePixel() )
424 pPrinter->SetPaperSizeUser( pPrinter->PixelToLogic( aSetPaperSize ) );
425 nChangeFlags |= SfxPrinterChangeFlags::CHG_SIZE;
429 //wait until printing is done
430 SfxPrinter* pDocPrinter = pViewSh->GetPrinter();
431 while ( pDocPrinter->IsPrinting() && !Application::IsQuit())
432 Application::Yield();
435 void SAL_CALL SfxPrintHelper::setPrinter(const uno::Sequence< beans::PropertyValue >& rPrinter)
437 // object already disposed?
438 SolarMutexGuard aGuard;
440 SfxViewShell* pViewSh = nullptr;
441 VclPtr<SfxPrinter> pPrinter;
442 SfxPrinterChangeFlags nChangeFlags = SfxPrinterChangeFlags::NONE;
443 impl_setPrinter(rPrinter,pPrinter,nChangeFlags,pViewSh);
444 // set new printer
445 if ( pViewSh && pPrinter )
446 pViewSh->SetPrinter( pPrinter, nChangeFlags );
450 // ImplPrintWatch thread for asynchronous printing with moving temp. file to ucb location
452 namespace {
454 /* This implements a thread which will be started to wait for asynchronous
455 print jobs to temp. locally files. If they finish we move the temp. files
456 to their right locations by using the ucb.
458 class ImplUCBPrintWatcher : public ::osl::Thread
460 private:
461 /// of course we must know the printer which execute the job
462 VclPtr<SfxPrinter> m_pPrinter;
463 /// this describes the target location for the printed temp file
464 OUString m_sTargetURL;
465 /// it holds the temp file alive, till the print job will finish and remove it from disk automatically if the object die
466 ::utl::TempFile* m_pTempFile;
468 public:
469 /* initialize this watcher but don't start it */
470 ImplUCBPrintWatcher( SfxPrinter* pPrinter, ::utl::TempFile* pTempFile, const OUString& sTargetURL )
471 : m_pPrinter ( pPrinter )
472 , m_sTargetURL( sTargetURL )
473 , m_pTempFile ( pTempFile )
476 /* waits for finishing of the print job and moves the temp file afterwards
477 Note: Starting of the job is done outside this thread!
478 But we have to free some of the given resources on heap!
480 void SAL_CALL run() override
482 osl_setThreadName("ImplUCBPrintWatcher");
484 /* SAFE { */
486 SolarMutexGuard aGuard;
487 while( m_pPrinter->IsPrinting() && !Application::IsQuit())
488 Application::Yield();
489 m_pPrinter.clear(); // don't delete it! It's borrowed only :-)
491 /* } SAFE */
493 // lock for further using of our member isn't necessary - because
494 // we run alone by definition. Nobody join for us nor use us...
495 moveAndDeleteTemp(&m_pTempFile,m_sTargetURL);
497 // finishing of this run() method will call onTerminate() automatically
498 // kill this thread there!
501 /* nobody wait for this thread. We must kill ourself ...
503 void SAL_CALL onTerminated() override
505 delete this;
508 /* static helper to move the temp. file to the target location by using the ucb
509 It's static to be usable from outside too. So it's not really necessary to start
510 the thread, if finishing of the job was detected outside this thread.
511 But it must be called without using a corresponding thread for the given parameter!
513 static void moveAndDeleteTemp( ::utl::TempFile** ppTempFile, const OUString& sTargetURL )
515 // move the file
518 INetURLObject aSplitter(sTargetURL);
519 OUString sFileName = aSplitter.getName(
520 INetURLObject::LAST_SEGMENT,
521 true,
522 INetURLObject::DecodeMechanism::WithCharset);
523 if (aSplitter.removeSegment() && !sFileName.isEmpty())
525 ::ucbhelper::Content aSource(
526 (*ppTempFile)->GetURL(),
527 css::uno::Reference< css::ucb::XCommandEnvironment >(),
528 comphelper::getProcessComponentContext());
530 ::ucbhelper::Content aTarget(
531 aSplitter.GetMainURL(INetURLObject::DecodeMechanism::NONE),
532 css::uno::Reference< css::ucb::XCommandEnvironment >(),
533 comphelper::getProcessComponentContext());
535 aTarget.transferContent(
536 aSource,
537 ::ucbhelper::InsertOperation::Copy,
538 sFileName,
539 css::ucb::NameClash::OVERWRITE);
542 catch (const css::uno::Exception&)
544 TOOLS_WARN_EXCEPTION( "sfx.doc", "");
547 // kill the temp file!
548 delete *ppTempFile;
549 *ppTempFile = nullptr;
555 // XPrintable
557 void SAL_CALL SfxPrintHelper::print(const uno::Sequence< beans::PropertyValue >& rOptions)
559 if( Application::GetSettings().GetMiscSettings().GetDisablePrinting() )
560 return;
562 // object already disposed?
563 // object already disposed?
564 SolarMutexGuard aGuard;
566 // get view for sfx printing capabilities
567 SfxViewFrame *pViewFrm = m_pData->m_pObjectShell.is() ?
568 SfxViewFrame::GetFirst( m_pData->m_pObjectShell.get(), false ) : nullptr;
569 if ( !pViewFrm )
570 return;
571 SfxViewShell* pView = pViewFrm->GetViewShell();
572 if ( !pView )
573 return;
574 bool bMonitor = false;
575 // We need this information at the end of this method, if we start the vcl printer
576 // by executing the slot. Because if it is a ucb relevant URL we must wait for
577 // finishing the print job and move the temporary local file by using the ucb
578 // to the right location. But in case of no file name is given or it is already
579 // a local one we can suppress this special handling. Because then vcl makes all
580 // right for us.
581 OUString sUcbUrl;
582 ::utl::TempFile* pUCBPrintTempFile = nullptr;
584 uno::Sequence < beans::PropertyValue > aCheckedArgs( rOptions.getLength() );
585 auto pCheckedArgs = aCheckedArgs.getArray();
586 sal_Int32 nProps = 0;
587 bool bWaitUntilEnd = false;
588 sal_Int16 nDuplexMode = css::view::DuplexMode::UNKNOWN;
589 for ( const beans::PropertyValue &rProp : rOptions )
591 // get Property-Value from options
592 // FileName-Property?
593 if ( rProp.Name == "FileName" )
595 // unpack th URL and check for a valid and well known protocol
596 OUString sTemp;
597 if (
598 ( rProp.Value.getValueType()!=cppu::UnoType<OUString>::get()) ||
599 (!(rProp.Value>>=sTemp))
602 throw css::lang::IllegalArgumentException();
605 OUString sPath;
606 OUString sURL (sTemp);
607 INetURLObject aCheck(sURL );
608 if (aCheck.GetProtocol()==INetProtocol::NotValid)
610 // OK - it's not a valid URL. But may it's a simple
611 // system path directly. It will be supported for historical
612 // reasons. Otherwise we break too much external code...
613 // We try to convert it to a file URL. If it's possible
614 // we put the system path to the item set and let vcl work with it.
615 // No ucb or thread will be necessary then. In case it couldn't be
616 // converted it's not a URL nor a system path. Then we can't accept
617 // this parameter and have to throw an exception.
618 const OUString& sSystemPath(sTemp);
619 OUString sFileURL;
620 if (::osl::FileBase::getFileURLFromSystemPath(sSystemPath,sFileURL)!=::osl::FileBase::E_None)
621 throw css::lang::IllegalArgumentException();
622 pCheckedArgs[nProps].Name = rProp.Name;
623 pCheckedArgs[nProps++].Value <<= sFileURL;
624 // and append the local filename
625 aCheckedArgs.realloc( aCheckedArgs.getLength()+1 );
626 pCheckedArgs = aCheckedArgs.getArray();
627 pCheckedArgs[nProps].Name = "LocalFileName";
628 pCheckedArgs[nProps++].Value <<= sTemp;
630 else
631 // It's a valid URL. but now we must know, if it is a local one or not.
632 // It's a question of using ucb or not!
633 if (osl::FileBase::getSystemPathFromFileURL(sURL, sPath) == osl::FileBase::E_None)
635 // it's a local file, we can use vcl without special handling
636 // And we have to use the system notation of the incoming URL.
637 // But it into the descriptor and let the slot be executed at
638 // the end of this method.
639 pCheckedArgs[nProps].Name = rProp.Name;
640 pCheckedArgs[nProps++].Value <<= sTemp;
641 // and append the local filename
642 aCheckedArgs.realloc( aCheckedArgs.getLength()+1 );
643 pCheckedArgs = aCheckedArgs.getArray();
644 pCheckedArgs[nProps].Name = "LocalFileName";
645 pCheckedArgs[nProps++].Value <<= sPath;
647 else
649 // it's a ucb target. So we must use a temp. file for vcl
650 // and move it after printing by using the ucb.
651 // Create a temp file on the heap (because it must delete the
652 // real file on disk automatically if it die - bt we have to share it with
653 // some other sources ... e.g. the ImplUCBPrintWatcher).
654 // And we put the name of this temp file to the descriptor instead
655 // of the URL. The URL we save for later using separately.
656 // Execution of the print job will be done later by executing
657 // a slot ...
658 if(!pUCBPrintTempFile)
659 pUCBPrintTempFile = new ::utl::TempFile();
660 pUCBPrintTempFile->EnableKillingFile();
662 //FIXME: does it work?
663 pCheckedArgs[nProps].Name = "LocalFileName";
664 pCheckedArgs[nProps++].Value <<= pUCBPrintTempFile->GetFileName();
665 sUcbUrl = sURL;
669 // CopyCount-Property
670 else if ( rProp.Name == "CopyCount" )
672 sal_Int32 nCopies = 0;
673 if ( !( rProp.Value >>= nCopies ) )
674 throw css::lang::IllegalArgumentException();
675 pCheckedArgs[nProps].Name = rProp.Name;
676 pCheckedArgs[nProps++].Value <<= nCopies;
679 // Collate-Property
680 // Sort-Property (deprecated)
681 else if ( rProp.Name == "Collate" || rProp.Name == "Sort" )
683 bool bTemp;
684 if ( !(rProp.Value >>= bTemp) )
685 throw css::lang::IllegalArgumentException();
686 pCheckedArgs[nProps].Name = "Collate";
687 pCheckedArgs[nProps++].Value <<= bTemp;
690 else if ( rProp.Name == "SinglePrintJobs" )
692 bool bTemp;
693 if ( !(rProp.Value >>= bTemp) )
694 throw css::lang::IllegalArgumentException();
695 pCheckedArgs[nProps].Name = "SinglePrintJobs";
696 pCheckedArgs[nProps++].Value <<= bTemp;
699 // Pages-Property
700 else if ( rProp.Name == "Pages" )
702 OUString sTemp;
703 if( !(rProp.Value >>= sTemp) )
704 throw css::lang::IllegalArgumentException();
705 pCheckedArgs[nProps].Name = rProp.Name;
706 pCheckedArgs[nProps++].Value <<= sTemp;
709 // MonitorVisible
710 else if ( rProp.Name == "MonitorVisible" )
712 if( !(rProp.Value >>= bMonitor) )
713 throw css::lang::IllegalArgumentException();
714 pCheckedArgs[nProps].Name = rProp.Name;
715 pCheckedArgs[nProps++].Value <<= bMonitor;
718 // Wait
719 else if ( rProp.Name == "Wait" )
721 if ( !(rProp.Value >>= bWaitUntilEnd) )
722 throw css::lang::IllegalArgumentException();
723 pCheckedArgs[nProps].Name = rProp.Name;
724 pCheckedArgs[nProps++].Value <<= bWaitUntilEnd;
727 else if ( rProp.Name == "DuplexMode" )
729 if ( !(rProp.Value >>= nDuplexMode ) )
730 throw css::lang::IllegalArgumentException();
731 pCheckedArgs[nProps].Name = rProp.Name;
732 pCheckedArgs[nProps++].Value <<= nDuplexMode;
736 if ( nProps != aCheckedArgs.getLength() )
737 aCheckedArgs.realloc(nProps);
739 // Execute the print request every time.
740 // It doesn't matter if it is a real printer used or we print to a local file
741 // nor if we print to a temp file and move it afterwards by using the ucb.
742 // That will be handled later. see pUCBPrintFile below!
743 pView->ExecPrint( aCheckedArgs, true, false );
745 // Ok - may be execution before has finished (or started!) printing.
746 // And may it was a printing to a file.
747 // Now we have to check if we can move the file (if necessary) via UCB to its right location.
748 // Cases:
749 // a) printing finished => move the file directly and forget the watcher thread
750 // b) printing is asynchron and runs currently => start watcher thread and exit this method
751 // This thread make all necessary things by itself.
752 if (!pUCBPrintTempFile)
753 return;
755 // a)
756 SfxPrinter* pPrinter = pView->GetPrinter();
757 if ( ! pPrinter->IsPrinting() )
758 ImplUCBPrintWatcher::moveAndDeleteTemp(&pUCBPrintTempFile,sUcbUrl);
759 // b)
760 else
762 // Note: we create(d) some resource on the heap (thread and temp file).
763 // They will be deleted by the thread automatically if it finishes its run() method.
764 ImplUCBPrintWatcher* pWatcher = new ImplUCBPrintWatcher( pPrinter, pUCBPrintTempFile, sUcbUrl );
765 pWatcher->create();
769 void IMPL_PrintListener_DataContainer::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
771 const SfxPrintingHint* pPrintHint = dynamic_cast<const SfxPrintingHint*>(&rHint);
772 if ( &rBC != m_pObjectShell.get()
773 || !pPrintHint
774 || pPrintHint->GetWhich() == SFX_PRINTABLESTATE_CANCELJOB )
775 return;
777 if ( pPrintHint->GetWhich() == css::view::PrintableState_JOB_STARTED )
779 if ( !m_xPrintJob.is() )
780 m_xPrintJob = new SfxPrintJob_Impl( this );
781 m_aPrintOptions = pPrintHint->GetOptions();
784 comphelper::OInterfaceContainerHelper2* pContainer = m_aInterfaceContainer.getContainer(
785 cppu::UnoType<view::XPrintJobListener>::get());
786 if ( !pContainer )
787 return;
789 view::PrintJobEvent aEvent;
790 aEvent.Source = m_xPrintJob;
791 aEvent.State = pPrintHint->GetWhich();
793 comphelper::OInterfaceIteratorHelper2 pIterator(*pContainer);
794 while (pIterator.hasMoreElements())
795 static_cast<view::XPrintJobListener*>(pIterator.next())->printJobEvent( aEvent );
798 void SAL_CALL SfxPrintHelper::addPrintJobListener( const css::uno::Reference< css::view::XPrintJobListener >& xListener )
800 SolarMutexGuard aGuard;
801 m_pData->m_aInterfaceContainer.addInterface( cppu::UnoType<view::XPrintJobListener>::get(), xListener );
804 void SAL_CALL SfxPrintHelper::removePrintJobListener( const css::uno::Reference< css::view::XPrintJobListener >& xListener )
806 SolarMutexGuard aGuard;
807 m_pData->m_aInterfaceContainer.removeInterface( cppu::UnoType<view::XPrintJobListener>::get(), xListener );
811 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */