Version 7.1.7.1, tag libreoffice-7.1.7.1
[LibreOffice.git] / sfx2 / source / doc / printhelper.cxx
blobe2ce74172288c87dc80fdc1e31e9eb21fafbdc51
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/lang/XUnoTunnel.hpp>
32 #include <com/sun/star/frame/XModel.hpp>
33 #include <com/sun/star/view/DuplexMode.hpp>
34 #include <comphelper/processfactory.hxx>
35 #include <svl/itemset.hxx>
36 #include <svl/lstner.hxx>
37 #include <unotools/tempfile.hxx>
38 #include <osl/file.hxx>
39 #include <osl/thread.hxx>
40 #include <tools/urlobj.hxx>
41 #include <ucbhelper/content.hxx>
42 #include <cppuhelper/interfacecontainer.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 ::cppu::OMultiTypeInterfaceContainerHelper 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() )
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() )
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::ucb::ContentCreationException&)
544 OSL_FAIL("content create exception");
546 catch (const css::ucb::CommandAbortedException&)
548 OSL_FAIL("command abort exception");
550 catch (const css::uno::RuntimeException&)
552 OSL_FAIL("runtime exception");
554 catch (const css::uno::Exception&)
556 OSL_FAIL("unknown exception");
559 // kill the temp file!
560 delete *ppTempFile;
561 *ppTempFile = nullptr;
567 // XPrintable
569 void SAL_CALL SfxPrintHelper::print(const uno::Sequence< beans::PropertyValue >& rOptions)
571 if( Application::GetSettings().GetMiscSettings().GetDisablePrinting() )
572 return;
574 // object already disposed?
575 // object already disposed?
576 SolarMutexGuard aGuard;
578 // get view for sfx printing capabilities
579 SfxViewFrame *pViewFrm = m_pData->m_pObjectShell.is() ?
580 SfxViewFrame::GetFirst( m_pData->m_pObjectShell.get(), false ) : nullptr;
581 if ( !pViewFrm )
582 return;
583 SfxViewShell* pView = pViewFrm->GetViewShell();
584 if ( !pView )
585 return;
586 bool bMonitor = false;
587 // We need this information at the end of this method, if we start the vcl printer
588 // by executing the slot. Because if it is a ucb relevant URL we must wait for
589 // finishing the print job and move the temporary local file by using the ucb
590 // to the right location. But in case of no file name is given or it is already
591 // a local one we can suppress this special handling. Because then vcl makes all
592 // right for us.
593 OUString sUcbUrl;
594 ::utl::TempFile* pUCBPrintTempFile = nullptr;
596 uno::Sequence < beans::PropertyValue > aCheckedArgs( rOptions.getLength() );
597 sal_Int32 nProps = 0;
598 bool bWaitUntilEnd = false;
599 sal_Int16 nDuplexMode = css::view::DuplexMode::UNKNOWN;
600 for ( const beans::PropertyValue &rProp : rOptions )
602 // get Property-Value from options
603 // FileName-Property?
604 if ( rProp.Name == "FileName" )
606 // unpack th URL and check for a valid and well known protocol
607 OUString sTemp;
608 if (
609 ( rProp.Value.getValueType()!=cppu::UnoType<OUString>::get()) ||
610 (!(rProp.Value>>=sTemp))
613 throw css::lang::IllegalArgumentException();
616 OUString sPath;
617 OUString sURL (sTemp);
618 INetURLObject aCheck(sURL );
619 if (aCheck.GetProtocol()==INetProtocol::NotValid)
621 // OK - it's not a valid URL. But may it's a simple
622 // system path directly. It will be supported for historical
623 // reasons. Otherwise we break too much external code...
624 // We try to convert it to a file URL. If it's possible
625 // we put the system path to the item set and let vcl work with it.
626 // No ucb or thread will be necessary then. In case it couldn't be
627 // converted it's not a URL nor a system path. Then we can't accept
628 // this parameter and have to throw an exception.
629 const OUString& sSystemPath(sTemp);
630 OUString sFileURL;
631 if (::osl::FileBase::getFileURLFromSystemPath(sSystemPath,sFileURL)!=::osl::FileBase::E_None)
632 throw css::lang::IllegalArgumentException();
633 aCheckedArgs[nProps].Name = rProp.Name;
634 aCheckedArgs[nProps++].Value <<= sFileURL;
635 // and append the local filename
636 aCheckedArgs.realloc( aCheckedArgs.getLength()+1 );
637 aCheckedArgs[nProps].Name = "LocalFileName";
638 aCheckedArgs[nProps++].Value <<= sTemp;
640 else
641 // It's a valid URL. but now we must know, if it is a local one or not.
642 // It's a question of using ucb or not!
643 if (osl::FileBase::getSystemPathFromFileURL(sURL, sPath) == osl::FileBase::E_None)
645 // it's a local file, we can use vcl without special handling
646 // And we have to use the system notation of the incoming URL.
647 // But it into the descriptor and let the slot be executed at
648 // the end of this method.
649 aCheckedArgs[nProps].Name = rProp.Name;
650 aCheckedArgs[nProps++].Value <<= sTemp;
651 // and append the local filename
652 aCheckedArgs.realloc( aCheckedArgs.getLength()+1 );
653 aCheckedArgs[nProps].Name = "LocalFileName";
654 aCheckedArgs[nProps++].Value <<= sPath;
656 else
658 // it's a ucb target. So we must use a temp. file for vcl
659 // and move it after printing by using the ucb.
660 // Create a temp file on the heap (because it must delete the
661 // real file on disk automatically if it die - bt we have to share it with
662 // some other sources ... e.g. the ImplUCBPrintWatcher).
663 // And we put the name of this temp file to the descriptor instead
664 // of the URL. The URL we save for later using separately.
665 // Execution of the print job will be done later by executing
666 // a slot ...
667 if(!pUCBPrintTempFile)
668 pUCBPrintTempFile = new ::utl::TempFile();
669 pUCBPrintTempFile->EnableKillingFile();
671 //FIXME: does it work?
672 aCheckedArgs[nProps].Name = "LocalFileName";
673 aCheckedArgs[nProps++].Value <<= pUCBPrintTempFile->GetFileName();
674 sUcbUrl = sURL;
678 // CopyCount-Property
679 else if ( rProp.Name == "CopyCount" )
681 sal_Int32 nCopies = 0;
682 if ( !( rProp.Value >>= nCopies ) )
683 throw css::lang::IllegalArgumentException();
684 aCheckedArgs[nProps].Name = rProp.Name;
685 aCheckedArgs[nProps++].Value <<= nCopies;
688 // Collate-Property
689 // Sort-Property (deprecated)
690 else if ( rProp.Name == "Collate" || rProp.Name == "Sort" )
692 bool bTemp;
693 if ( !(rProp.Value >>= bTemp) )
694 throw css::lang::IllegalArgumentException();
695 aCheckedArgs[nProps].Name = "Collate";
696 aCheckedArgs[nProps++].Value <<= bTemp;
699 else if ( rProp.Name == "SinglePrintJobs" )
701 bool bTemp;
702 if ( !(rProp.Value >>= bTemp) )
703 throw css::lang::IllegalArgumentException();
704 aCheckedArgs[nProps].Name = "SinglePrintJobs";
705 aCheckedArgs[nProps++].Value <<= bTemp;
708 // Pages-Property
709 else if ( rProp.Name == "Pages" )
711 OUString sTemp;
712 if( !(rProp.Value >>= sTemp) )
713 throw css::lang::IllegalArgumentException();
714 aCheckedArgs[nProps].Name = rProp.Name;
715 aCheckedArgs[nProps++].Value <<= sTemp;
718 // MonitorVisible
719 else if ( rProp.Name == "MonitorVisible" )
721 if( !(rProp.Value >>= bMonitor) )
722 throw css::lang::IllegalArgumentException();
723 aCheckedArgs[nProps].Name = rProp.Name;
724 aCheckedArgs[nProps++].Value <<= bMonitor;
727 // Wait
728 else if ( rProp.Name == "Wait" )
730 if ( !(rProp.Value >>= bWaitUntilEnd) )
731 throw css::lang::IllegalArgumentException();
732 aCheckedArgs[nProps].Name = rProp.Name;
733 aCheckedArgs[nProps++].Value <<= bWaitUntilEnd;
736 else if ( rProp.Name == "DuplexMode" )
738 if ( !(rProp.Value >>= nDuplexMode ) )
739 throw css::lang::IllegalArgumentException();
740 aCheckedArgs[nProps].Name = rProp.Name;
741 aCheckedArgs[nProps++].Value <<= nDuplexMode;
745 if ( nProps != aCheckedArgs.getLength() )
746 aCheckedArgs.realloc(nProps);
748 // Execute the print request every time.
749 // It doesn't matter if it is a real printer used or we print to a local file
750 // nor if we print to a temp file and move it afterwards by using the ucb.
751 // That will be handled later. see pUCBPrintFile below!
752 pView->ExecPrint( aCheckedArgs, true, false );
754 // Ok - may be execution before has finished (or started!) printing.
755 // And may it was a printing to a file.
756 // Now we have to check if we can move the file (if necessary) via UCB to its right location.
757 // Cases:
758 // a) printing finished => move the file directly and forget the watcher thread
759 // b) printing is asynchron and runs currently => start watcher thread and exit this method
760 // This thread make all necessary things by itself.
761 if (!pUCBPrintTempFile)
762 return;
764 // a)
765 SfxPrinter* pPrinter = pView->GetPrinter();
766 if ( ! pPrinter->IsPrinting() )
767 ImplUCBPrintWatcher::moveAndDeleteTemp(&pUCBPrintTempFile,sUcbUrl);
768 // b)
769 else
771 // Note: we create(d) some resource on the heap (thread and temp file).
772 // They will be deleted by the thread automatically if it finishes its run() method.
773 ImplUCBPrintWatcher* pWatcher = new ImplUCBPrintWatcher( pPrinter, pUCBPrintTempFile, sUcbUrl );
774 pWatcher->create();
778 void IMPL_PrintListener_DataContainer::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
780 const SfxPrintingHint* pPrintHint = dynamic_cast<const SfxPrintingHint*>(&rHint);
781 if ( &rBC != m_pObjectShell.get()
782 || !pPrintHint
783 || pPrintHint->GetWhich() == SFX_PRINTABLESTATE_CANCELJOB )
784 return;
786 if ( pPrintHint->GetWhich() == css::view::PrintableState_JOB_STARTED )
788 if ( !m_xPrintJob.is() )
789 m_xPrintJob = new SfxPrintJob_Impl( this );
790 m_aPrintOptions = pPrintHint->GetOptions();
793 ::cppu::OInterfaceContainerHelper* pContainer = m_aInterfaceContainer.getContainer(
794 cppu::UnoType<view::XPrintJobListener>::get());
795 if ( !pContainer )
796 return;
798 view::PrintJobEvent aEvent;
799 aEvent.Source = m_xPrintJob;
800 aEvent.State = pPrintHint->GetWhich();
802 ::cppu::OInterfaceIteratorHelper pIterator(*pContainer);
803 while (pIterator.hasMoreElements())
804 static_cast<view::XPrintJobListener*>(pIterator.next())->printJobEvent( aEvent );
807 void SAL_CALL SfxPrintHelper::addPrintJobListener( const css::uno::Reference< css::view::XPrintJobListener >& xListener )
809 SolarMutexGuard aGuard;
810 m_pData->m_aInterfaceContainer.addInterface( cppu::UnoType<view::XPrintJobListener>::get(), xListener );
813 void SAL_CALL SfxPrintHelper::removePrintJobListener( const css::uno::Reference< css::view::XPrintJobListener >& xListener )
815 SolarMutexGuard aGuard;
816 m_pData->m_aInterfaceContainer.removeInterface( cppu::UnoType<view::XPrintJobListener>::get(), xListener );
820 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */