Bump version to 24.04.3.4
[LibreOffice.git] / sfx2 / source / doc / printhelper.cxx
blob6ca15e6cdbd9d7d50be9c3349b624d9129f1110e
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/frame/XModel.hpp>
30 #include <com/sun/star/view/DuplexMode.hpp>
31 #include <comphelper/processfactory.hxx>
32 #include <comphelper/propertyvalue.hxx>
33 #include <svl/itemset.hxx>
34 #include <svl/lstner.hxx>
35 #include <unotools/tempfile.hxx>
36 #include <osl/file.hxx>
37 #include <osl/thread.hxx>
38 #include <tools/urlobj.hxx>
39 #include <comphelper/diagnose_ex.hxx>
40 #include <ucbhelper/content.hxx>
41 #include <comphelper/interfacecontainer4.hxx>
42 #include <cppuhelper/implbase.hxx>
43 #include <utility>
44 #include <vcl/settings.hxx>
45 #include <vcl/svapp.hxx>
47 #include <sfx2/viewfrm.hxx>
48 #include <sfx2/viewsh.hxx>
49 #include <sfx2/printer.hxx>
50 #include <sfx2/objsh.hxx>
51 #include <sfx2/event.hxx>
53 #define SFX_PRINTABLESTATE_CANCELJOB css::view::PrintableState(-2)
55 using namespace ::com::sun::star;
56 using namespace ::com::sun::star::uno;
58 struct IMPL_PrintListener_DataContainer : public SfxListener
60 SfxObjectShellRef m_pObjectShell;
61 std::mutex m_aMutex;
62 comphelper::OInterfaceContainerHelper4<view::XPrintJobListener> m_aJobListeners;
63 uno::Reference< css::view::XPrintJob> m_xPrintJob;
64 css::uno::Sequence< css::beans::PropertyValue > m_aPrintOptions;
66 explicit IMPL_PrintListener_DataContainer()
71 void Notify( SfxBroadcaster& aBC ,
72 const SfxHint& aHint ) override ;
75 static awt::Size impl_Size_Object2Struct( const Size& aSize )
77 awt::Size aReturnValue;
78 aReturnValue.Width = aSize.Width() ;
79 aReturnValue.Height = aSize.Height() ;
80 return aReturnValue ;
83 static Size impl_Size_Struct2Object( const awt::Size& aSize )
85 Size aReturnValue;
86 aReturnValue.setWidth( aSize.Width ) ;
87 aReturnValue.setHeight( aSize.Height ) ;
88 return aReturnValue ;
91 namespace {
93 class SfxPrintJob_Impl : public cppu::WeakImplHelper
95 css::view::XPrintJob
98 IMPL_PrintListener_DataContainer* m_pData;
100 public:
101 explicit SfxPrintJob_Impl( IMPL_PrintListener_DataContainer* pData );
102 virtual Sequence< css::beans::PropertyValue > SAL_CALL getPrintOptions( ) override;
103 virtual Sequence< css::beans::PropertyValue > SAL_CALL getPrinter( ) override;
104 virtual Reference< css::view::XPrintable > SAL_CALL getPrintable( ) override;
105 virtual void SAL_CALL cancelJob() override;
110 SfxPrintJob_Impl::SfxPrintJob_Impl( IMPL_PrintListener_DataContainer* pData )
111 : m_pData( pData )
115 Sequence< css::beans::PropertyValue > SAL_CALL SfxPrintJob_Impl::getPrintOptions()
117 return m_pData->m_aPrintOptions;
120 Sequence< css::beans::PropertyValue > SAL_CALL SfxPrintJob_Impl::getPrinter()
122 if( m_pData->m_pObjectShell.is() )
124 Reference < view::XPrintable > xPrintable( m_pData->m_pObjectShell->GetModel(), UNO_QUERY );
125 if ( xPrintable.is() )
126 return xPrintable->getPrinter();
128 return Sequence< css::beans::PropertyValue >();
131 Reference< css::view::XPrintable > SAL_CALL SfxPrintJob_Impl::getPrintable()
133 Reference < view::XPrintable > xPrintable( m_pData->m_pObjectShell.is() ? m_pData->m_pObjectShell->GetModel() : nullptr, UNO_QUERY );
134 return xPrintable;
137 void SAL_CALL SfxPrintJob_Impl::cancelJob()
139 // FIXME: how to cancel PrintJob via API?!
140 if( m_pData->m_pObjectShell.is() )
141 m_pData->m_pObjectShell->Broadcast( SfxPrintingHint( SFX_PRINTABLESTATE_CANCELJOB ) );
144 SfxPrintHelper::SfxPrintHelper()
146 m_pData.reset(new IMPL_PrintListener_DataContainer());
149 void SAL_CALL SfxPrintHelper::initialize( const css::uno::Sequence< css::uno::Any >& aArguments )
151 if ( !aArguments.hasElements() )
152 return;
154 css::uno::Reference < css::frame::XModel > xModel;
155 aArguments[0] >>= xModel;
156 m_pData->m_pObjectShell = SfxObjectShell::GetShellFromComponent(xModel);
157 if (m_pData->m_pObjectShell)
158 m_pData->StartListening(*m_pData->m_pObjectShell);
161 SfxPrintHelper::~SfxPrintHelper()
165 namespace
167 view::PaperFormat convertToPaperFormat(Paper eFormat)
169 view::PaperFormat eRet;
170 switch (eFormat)
172 case PAPER_A3:
173 eRet = view::PaperFormat_A3;
174 break;
175 case PAPER_A4:
176 eRet = view::PaperFormat_A4;
177 break;
178 case PAPER_A5:
179 eRet = view::PaperFormat_A5;
180 break;
181 case PAPER_B4_ISO:
182 eRet = view::PaperFormat_B4;
183 break;
184 case PAPER_B5_ISO:
185 eRet = view::PaperFormat_B5;
186 break;
187 case PAPER_LETTER:
188 eRet = view::PaperFormat_LETTER;
189 break;
190 case PAPER_LEGAL:
191 eRet = view::PaperFormat_LEGAL;
192 break;
193 case PAPER_TABLOID:
194 eRet = view::PaperFormat_TABLOID;
195 break;
196 case PAPER_USER:
197 default:
198 eRet = view::PaperFormat_USER;
199 break;
201 return eRet;
204 Paper convertToPaper(view::PaperFormat eFormat)
206 Paper eRet(PAPER_USER);
207 switch (eFormat)
209 case view::PaperFormat_A3:
210 eRet = PAPER_A3;
211 break;
212 case view::PaperFormat_A4:
213 eRet = PAPER_A4;
214 break;
215 case view::PaperFormat_A5:
216 eRet = PAPER_A5;
217 break;
218 case view::PaperFormat_B4:
219 eRet = PAPER_B4_ISO;
220 break;
221 case view::PaperFormat_B5:
222 eRet = PAPER_B5_ISO;
223 break;
224 case view::PaperFormat_LETTER:
225 eRet = PAPER_LETTER;
226 break;
227 case view::PaperFormat_LEGAL:
228 eRet = PAPER_LEGAL;
229 break;
230 case view::PaperFormat_TABLOID:
231 eRet = PAPER_TABLOID;
232 break;
233 case view::PaperFormat_USER:
234 eRet = PAPER_USER;
235 break;
236 case view::PaperFormat::PaperFormat_MAKE_FIXED_SIZE:
237 break;
238 //deliberate no default to force warn on a new papersize
240 return eRet;
245 // XPrintable
248 uno::Sequence< beans::PropertyValue > SAL_CALL SfxPrintHelper::getPrinter()
250 // object already disposed?
251 SolarMutexGuard aGuard;
253 // search for any view of this document that is currently printing
254 const Printer *pPrinter = nullptr;
255 SfxViewFrame *pViewFrm = m_pData->m_pObjectShell.is() ? SfxViewFrame::GetFirst( m_pData->m_pObjectShell.get(), false ) : nullptr;
256 SfxViewFrame* pFirst = pViewFrm;
257 while ( pViewFrm && !pPrinter )
259 pPrinter = pViewFrm->GetViewShell()->GetActivePrinter();
260 pViewFrm = SfxViewFrame::GetNext( *pViewFrm, m_pData->m_pObjectShell.get(), false );
263 // if no view is printing currently, use the permanent SfxPrinter instance
264 if ( !pPrinter && pFirst )
265 pPrinter = pFirst->GetViewShell()->GetPrinter(true);
267 if ( !pPrinter )
268 return uno::Sequence< beans::PropertyValue >();
270 return
272 comphelper::makePropertyValue("Name", pPrinter->GetName()),
273 comphelper::makePropertyValue("PaperOrientation", static_cast<view::PaperOrientation>(pPrinter->GetOrientation())),
274 comphelper::makePropertyValue("PaperFormat", convertToPaperFormat(pPrinter->GetPaper())),
275 comphelper::makePropertyValue("PaperSize", impl_Size_Object2Struct(pPrinter->GetPaperSize() )),
276 comphelper::makePropertyValue("IsBusy", pPrinter->IsPrinting()),
277 comphelper::makePropertyValue("CanSetPaperOrientation", pPrinter->HasSupport( PrinterSupport::SetOrientation )),
278 comphelper::makePropertyValue("CanSetPaperFormat", pPrinter->HasSupport( PrinterSupport::SetPaper )),
279 comphelper::makePropertyValue("CanSetPaperSize", pPrinter->HasSupport( PrinterSupport::SetPaperSize ))
284 // XPrintable
287 void SfxPrintHelper::impl_setPrinter(const uno::Sequence< beans::PropertyValue >& rPrinter,
288 VclPtr<SfxPrinter>& pPrinter,
289 SfxPrinterChangeFlags& nChangeFlags,
290 SfxViewShell*& pViewSh)
293 // Get old Printer
294 SfxViewFrame *pViewFrm = m_pData->m_pObjectShell.is() ?
295 SfxViewFrame::GetFirst( m_pData->m_pObjectShell.get(), false ) : nullptr;
296 if ( !pViewFrm )
297 return;
299 pViewSh = pViewFrm->GetViewShell();
300 pPrinter = pViewSh->GetPrinter(true);
301 if ( !pPrinter )
302 return;
304 // new Printer-Name available?
305 nChangeFlags = SfxPrinterChangeFlags::NONE;
306 sal_Int32 lDummy = 0;
307 auto pProp = std::find_if(rPrinter.begin(), rPrinter.end(),
308 [](const beans::PropertyValue &rProp) { return rProp.Name == "Name"; });
309 if (pProp != rPrinter.end())
311 OUString aPrinterName;
312 if ( ! ( pProp->Value >>= aPrinterName ) )
313 throw css::lang::IllegalArgumentException();
315 if ( aPrinterName != pPrinter->GetName() )
317 pPrinter = VclPtr<SfxPrinter>::Create( pPrinter->GetOptions().Clone(), aPrinterName );
318 nChangeFlags = SfxPrinterChangeFlags::PRINTER;
322 Size aSetPaperSize( 0, 0);
323 view::PaperFormat nPaperFormat = view::PaperFormat_USER;
325 // other properties
326 for ( const beans::PropertyValue &rProp : rPrinter )
328 // get Property-Value from printer description
329 // PaperOrientation-Property?
330 if ( rProp.Name == "PaperOrientation" )
332 view::PaperOrientation eOrient;
333 if ( !( rProp.Value >>= eOrient ) )
335 if ( !( rProp.Value >>= lDummy ) )
336 throw css::lang::IllegalArgumentException();
337 eOrient = static_cast<view::PaperOrientation>(lDummy);
340 if ( static_cast<Orientation>(eOrient) != pPrinter->GetOrientation() )
342 pPrinter->SetOrientation( static_cast<Orientation>(eOrient) );
343 nChangeFlags |= SfxPrinterChangeFlags::CHG_ORIENTATION;
347 // PaperFormat-Property?
348 else if ( rProp.Name == "PaperFormat" )
350 if ( !( rProp.Value >>= nPaperFormat ) )
352 if ( !( rProp.Value >>= lDummy ) )
353 throw css::lang::IllegalArgumentException();
354 nPaperFormat = static_cast<view::PaperFormat>(lDummy);
357 if ( convertToPaper(nPaperFormat) != pPrinter->GetPaper() )
359 pPrinter->SetPaper( convertToPaper(nPaperFormat) );
360 nChangeFlags |= SfxPrinterChangeFlags::CHG_SIZE;
364 // PaperSize-Property?
365 else if ( rProp.Name == "PaperSize" )
367 awt::Size aTempSize ;
368 if ( !( rProp.Value >>= aTempSize ) )
370 throw css::lang::IllegalArgumentException();
372 aSetPaperSize = impl_Size_Struct2Object(aTempSize);
375 // PrinterTray-Property
376 else if ( rProp.Name == "PrinterPaperTray" )
378 OUString aTmp;
379 if ( !( rProp.Value >>= aTmp ) )
380 throw css::lang::IllegalArgumentException();
381 const sal_uInt16 nCount = pPrinter->GetPaperBinCount();
382 for (sal_uInt16 nBin=0; nBin<nCount; nBin++)
384 OUString aName( pPrinter->GetPaperBinName(nBin) );
385 if ( aName == aTmp )
387 pPrinter->SetPaperBin(nBin);
388 break;
394 // The PaperSize may be set only when actually PAPER_USER
395 // applies, otherwise the driver could choose an invalid format.
396 if(nPaperFormat == view::PaperFormat_USER && aSetPaperSize.Width())
398 // Bug 56929 - MapMode of 100mm which recalculated when
399 // the device is set. Additionally only set if they were really changed.
400 aSetPaperSize = pPrinter->LogicToPixel(aSetPaperSize, MapMode(MapUnit::Map100thMM));
401 if( aSetPaperSize != pPrinter->GetPaperSizePixel() )
403 pPrinter->SetPaperSizeUser( pPrinter->PixelToLogic( aSetPaperSize ) );
404 nChangeFlags |= SfxPrinterChangeFlags::CHG_SIZE;
408 //wait until printing is done
409 SfxPrinter* pDocPrinter = pViewSh->GetPrinter();
410 while ( pDocPrinter->IsPrinting() && !Application::IsQuit())
411 Application::Yield();
414 void SAL_CALL SfxPrintHelper::setPrinter(const uno::Sequence< beans::PropertyValue >& rPrinter)
416 // object already disposed?
417 SolarMutexGuard aGuard;
419 SfxViewShell* pViewSh = nullptr;
420 VclPtr<SfxPrinter> pPrinter;
421 SfxPrinterChangeFlags nChangeFlags = SfxPrinterChangeFlags::NONE;
422 impl_setPrinter(rPrinter,pPrinter,nChangeFlags,pViewSh);
423 // set new printer
424 if ( pViewSh && pPrinter )
425 pViewSh->SetPrinter( pPrinter, nChangeFlags );
429 // ImplPrintWatch thread for asynchronous printing with moving temp. file to ucb location
431 namespace {
433 /* This implements a thread which will be started to wait for asynchronous
434 print jobs to temp. locally files. If they finish we move the temp. files
435 to their right locations by using the ucb.
437 class ImplUCBPrintWatcher : public ::osl::Thread
439 private:
440 /// of course we must know the printer which execute the job
441 VclPtr<SfxPrinter> m_pPrinter;
442 /// this describes the target location for the printed temp file
443 OUString m_sTargetURL;
444 /// it holds the temp file alive, till the print job will finish and remove it from disk automatically if the object die
445 ::utl::TempFileNamed* m_pTempFile;
447 public:
448 /* initialize this watcher but don't start it */
449 ImplUCBPrintWatcher( SfxPrinter* pPrinter, ::utl::TempFileNamed* pTempFile, OUString sTargetURL )
450 : m_pPrinter ( pPrinter )
451 , m_sTargetURL(std::move( sTargetURL ))
452 , m_pTempFile ( pTempFile )
455 /* waits for finishing of the print job and moves the temp file afterwards
456 Note: Starting of the job is done outside this thread!
457 But we have to free some of the given resources on heap!
459 void SAL_CALL run() override
461 osl_setThreadName("ImplUCBPrintWatcher");
463 /* SAFE { */
465 SolarMutexGuard aGuard;
466 while( m_pPrinter->IsPrinting() && !Application::IsQuit())
467 Application::Yield();
468 m_pPrinter.clear(); // don't delete it! It's borrowed only :-)
470 /* } SAFE */
472 // lock for further using of our member isn't necessary - because
473 // we run alone by definition. Nobody join for us nor use us...
474 moveAndDeleteTemp(&m_pTempFile,m_sTargetURL);
476 // finishing of this run() method will call onTerminate() automatically
477 // kill this thread there!
480 /* nobody wait for this thread. We must kill ourself ...
482 void SAL_CALL onTerminated() override
484 delete this;
487 /* static helper to move the temp. file to the target location by using the ucb
488 It's static to be usable from outside too. So it's not really necessary to start
489 the thread, if finishing of the job was detected outside this thread.
490 But it must be called without using a corresponding thread for the given parameter!
492 static void moveAndDeleteTemp( ::utl::TempFileNamed** ppTempFile, std::u16string_view sTargetURL )
494 // move the file
497 INetURLObject aSplitter(sTargetURL);
498 OUString sFileName = aSplitter.getName(
499 INetURLObject::LAST_SEGMENT,
500 true,
501 INetURLObject::DecodeMechanism::WithCharset);
502 if (aSplitter.removeSegment() && !sFileName.isEmpty())
504 ::ucbhelper::Content aSource(
505 (*ppTempFile)->GetURL(),
506 css::uno::Reference< css::ucb::XCommandEnvironment >(),
507 comphelper::getProcessComponentContext());
509 ::ucbhelper::Content aTarget(
510 aSplitter.GetMainURL(INetURLObject::DecodeMechanism::NONE),
511 css::uno::Reference< css::ucb::XCommandEnvironment >(),
512 comphelper::getProcessComponentContext());
514 aTarget.transferContent(
515 aSource,
516 ::ucbhelper::InsertOperation::Copy,
517 sFileName,
518 css::ucb::NameClash::OVERWRITE);
521 catch (const css::uno::Exception&)
523 TOOLS_WARN_EXCEPTION( "sfx.doc", "");
526 // kill the temp file!
527 delete *ppTempFile;
528 *ppTempFile = nullptr;
534 // XPrintable
536 void SAL_CALL SfxPrintHelper::print(const uno::Sequence< beans::PropertyValue >& rOptions)
538 if( Application::GetSettings().GetMiscSettings().GetDisablePrinting() )
539 return;
541 // object already disposed?
542 // object already disposed?
543 SolarMutexGuard aGuard;
545 // get view for sfx printing capabilities
546 SfxViewFrame *pViewFrm = m_pData->m_pObjectShell.is() ?
547 SfxViewFrame::GetFirst( m_pData->m_pObjectShell.get(), false ) : nullptr;
548 if ( !pViewFrm )
549 return;
550 SfxViewShell* pView = pViewFrm->GetViewShell();
551 if ( !pView )
552 return;
553 bool bMonitor = false;
554 // We need this information at the end of this method, if we start the vcl printer
555 // by executing the slot. Because if it is a ucb relevant URL we must wait for
556 // finishing the print job and move the temporary local file by using the ucb
557 // to the right location. But in case of no file name is given or it is already
558 // a local one we can suppress this special handling. Because then vcl makes all
559 // right for us.
560 OUString sUcbUrl;
561 ::utl::TempFileNamed* pUCBPrintTempFile = nullptr;
563 uno::Sequence < beans::PropertyValue > aCheckedArgs( rOptions.getLength() );
564 auto pCheckedArgs = aCheckedArgs.getArray();
565 sal_Int32 nProps = 0;
566 bool bWaitUntilEnd = false;
567 sal_Int16 nDuplexMode = css::view::DuplexMode::UNKNOWN;
568 for ( const beans::PropertyValue &rProp : rOptions )
570 // get Property-Value from options
571 // FileName-Property?
572 if ( rProp.Name == "FileName" )
574 // unpack th URL and check for a valid and well known protocol
575 OUString sTemp;
576 if (
577 ( rProp.Value.getValueType()!=cppu::UnoType<OUString>::get()) ||
578 (!(rProp.Value>>=sTemp))
581 throw css::lang::IllegalArgumentException();
584 OUString sPath;
585 OUString sURL (sTemp);
586 INetURLObject aCheck(sURL );
587 if (aCheck.GetProtocol()==INetProtocol::NotValid)
589 // OK - it's not a valid URL. But may it's a simple
590 // system path directly. It will be supported for historical
591 // reasons. Otherwise we break too much external code...
592 // We try to convert it to a file URL. If it's possible
593 // we put the system path to the item set and let vcl work with it.
594 // No ucb or thread will be necessary then. In case it couldn't be
595 // converted it's not a URL nor a system path. Then we can't accept
596 // this parameter and have to throw an exception.
597 const OUString& sSystemPath(sTemp);
598 OUString sFileURL;
599 if (::osl::FileBase::getFileURLFromSystemPath(sSystemPath,sFileURL)!=::osl::FileBase::E_None)
600 throw css::lang::IllegalArgumentException();
601 pCheckedArgs[nProps].Name = rProp.Name;
602 pCheckedArgs[nProps++].Value <<= sFileURL;
603 // and append the local filename
604 aCheckedArgs.realloc( aCheckedArgs.getLength()+1 );
605 pCheckedArgs = aCheckedArgs.getArray();
606 pCheckedArgs[nProps].Name = "LocalFileName";
607 pCheckedArgs[nProps++].Value <<= sTemp;
609 else
610 // It's a valid URL. but now we must know, if it is a local one or not.
611 // It's a question of using ucb or not!
612 if (osl::FileBase::getSystemPathFromFileURL(sURL, sPath) == osl::FileBase::E_None)
614 // it's a local file, we can use vcl without special handling
615 // And we have to use the system notation of the incoming URL.
616 // But it into the descriptor and let the slot be executed at
617 // the end of this method.
618 pCheckedArgs[nProps].Name = rProp.Name;
619 pCheckedArgs[nProps++].Value <<= sTemp;
620 // and append the local filename
621 aCheckedArgs.realloc( aCheckedArgs.getLength()+1 );
622 pCheckedArgs = aCheckedArgs.getArray();
623 pCheckedArgs[nProps].Name = "LocalFileName";
624 pCheckedArgs[nProps++].Value <<= sPath;
626 else
628 // it's a ucb target. So we must use a temp. file for vcl
629 // and move it after printing by using the ucb.
630 // Create a temp file on the heap (because it must delete the
631 // real file on disk automatically if it die - bt we have to share it with
632 // some other sources ... e.g. the ImplUCBPrintWatcher).
633 // And we put the name of this temp file to the descriptor instead
634 // of the URL. The URL we save for later using separately.
635 // Execution of the print job will be done later by executing
636 // a slot ...
637 if(!pUCBPrintTempFile)
638 pUCBPrintTempFile = new ::utl::TempFileNamed();
639 pUCBPrintTempFile->EnableKillingFile();
641 //FIXME: does it work?
642 pCheckedArgs[nProps].Name = "LocalFileName";
643 pCheckedArgs[nProps++].Value <<= pUCBPrintTempFile->GetFileName();
644 sUcbUrl = sURL;
648 // CopyCount-Property
649 else if ( rProp.Name == "CopyCount" )
651 sal_Int32 nCopies = 0;
652 if ( !( rProp.Value >>= nCopies ) )
653 throw css::lang::IllegalArgumentException();
654 pCheckedArgs[nProps].Name = rProp.Name;
655 pCheckedArgs[nProps++].Value <<= nCopies;
658 // Collate-Property
659 // Sort-Property (deprecated)
660 else if ( rProp.Name == "Collate" || rProp.Name == "Sort" )
662 bool bTemp;
663 if ( !(rProp.Value >>= bTemp) )
664 throw css::lang::IllegalArgumentException();
665 pCheckedArgs[nProps].Name = "Collate";
666 pCheckedArgs[nProps++].Value <<= bTemp;
669 else if ( rProp.Name == "SinglePrintJobs" )
671 bool bTemp;
672 if ( !(rProp.Value >>= bTemp) )
673 throw css::lang::IllegalArgumentException();
674 pCheckedArgs[nProps].Name = "SinglePrintJobs";
675 pCheckedArgs[nProps++].Value <<= bTemp;
678 else if ( rProp.Name == "JobName" )
680 OUString sTemp;
681 if( !(rProp.Value >>= sTemp) )
682 throw css::lang::IllegalArgumentException();
683 pCheckedArgs[nProps].Name = rProp.Name;
684 pCheckedArgs[nProps++].Value <<= sTemp;
687 // Pages-Property
688 else if ( rProp.Name == "Pages" )
690 OUString sTemp;
691 if( !(rProp.Value >>= sTemp) )
692 throw css::lang::IllegalArgumentException();
693 pCheckedArgs[nProps].Name = rProp.Name;
694 pCheckedArgs[nProps++].Value <<= sTemp;
697 // MonitorVisible
698 else if ( rProp.Name == "MonitorVisible" )
700 if( !(rProp.Value >>= bMonitor) )
701 throw css::lang::IllegalArgumentException();
702 pCheckedArgs[nProps].Name = rProp.Name;
703 pCheckedArgs[nProps++].Value <<= bMonitor;
706 // Wait
707 else if ( rProp.Name == "Wait" )
709 if ( !(rProp.Value >>= bWaitUntilEnd) )
710 throw css::lang::IllegalArgumentException();
711 pCheckedArgs[nProps].Name = rProp.Name;
712 pCheckedArgs[nProps++].Value <<= bWaitUntilEnd;
715 else if ( rProp.Name == "DuplexMode" )
717 if ( !(rProp.Value >>= nDuplexMode ) )
718 throw css::lang::IllegalArgumentException();
719 pCheckedArgs[nProps].Name = rProp.Name;
720 pCheckedArgs[nProps++].Value <<= nDuplexMode;
724 if ( nProps != aCheckedArgs.getLength() )
725 aCheckedArgs.realloc(nProps);
727 // Execute the print request every time.
728 // It doesn't matter if it is a real printer used or we print to a local file
729 // nor if we print to a temp file and move it afterwards by using the ucb.
730 // That will be handled later. see pUCBPrintFile below!
731 pView->ExecPrint( aCheckedArgs, true, false );
733 // Ok - may be execution before has finished (or started!) printing.
734 // And may it was a printing to a file.
735 // Now we have to check if we can move the file (if necessary) via UCB to its right location.
736 // Cases:
737 // a) printing finished => move the file directly and forget the watcher thread
738 // b) printing is asynchron and runs currently => start watcher thread and exit this method
739 // This thread make all necessary things by itself.
740 if (!pUCBPrintTempFile)
741 return;
743 // a)
744 SfxPrinter* pPrinter = pView->GetPrinter();
745 if ( ! pPrinter->IsPrinting() )
746 ImplUCBPrintWatcher::moveAndDeleteTemp(&pUCBPrintTempFile,sUcbUrl);
747 // b)
748 else
750 // Note: we create(d) some resource on the heap (thread and temp file).
751 // They will be deleted by the thread automatically if it finishes its run() method.
752 ImplUCBPrintWatcher* pWatcher = new ImplUCBPrintWatcher( pPrinter, pUCBPrintTempFile, sUcbUrl );
753 pWatcher->create();
757 void IMPL_PrintListener_DataContainer::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
759 const SfxPrintingHint* pPrintHint = dynamic_cast<const SfxPrintingHint*>(&rHint);
760 if ( &rBC != m_pObjectShell.get()
761 || !pPrintHint
762 || pPrintHint->GetWhich() == SFX_PRINTABLESTATE_CANCELJOB )
763 return;
765 if ( pPrintHint->GetWhich() == css::view::PrintableState_JOB_STARTED )
767 if ( !m_xPrintJob.is() )
768 m_xPrintJob = new SfxPrintJob_Impl( this );
769 m_aPrintOptions = pPrintHint->GetOptions();
772 std::unique_lock aGuard(m_aMutex);
773 if (!m_aJobListeners.getLength(aGuard))
774 return;
775 view::PrintJobEvent aEvent;
776 aEvent.Source = m_xPrintJob;
777 aEvent.State = pPrintHint->GetWhich();
779 comphelper::OInterfaceIteratorHelper4 pIterator(aGuard, m_aJobListeners);
780 aGuard.unlock();
781 while (pIterator.hasMoreElements())
782 pIterator.next()->printJobEvent( aEvent );
785 void SAL_CALL SfxPrintHelper::addPrintJobListener( const css::uno::Reference< css::view::XPrintJobListener >& xListener )
787 std::unique_lock aGuard(m_pData->m_aMutex);
788 m_pData->m_aJobListeners.addInterface( aGuard, xListener );
791 void SAL_CALL SfxPrintHelper::removePrintJobListener( const css::uno::Reference< css::view::XPrintJobListener >& xListener )
793 std::unique_lock aGuard(m_pData->m_aMutex);
794 m_pData->m_aJobListeners.removeInterface( aGuard, xListener );
798 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */