1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
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 class SfxPrintJob_Impl
;
61 struct IMPL_PrintListener_DataContainer
: public SfxListener
63 SfxObjectShellRef m_pObjectShell
;
65 comphelper::OInterfaceContainerHelper4
<view::XPrintJobListener
> m_aJobListeners
;
66 rtl::Reference
<SfxPrintJob_Impl
> m_xPrintJob
;
67 css::uno::Sequence
< css::beans::PropertyValue
> m_aPrintOptions
;
69 explicit IMPL_PrintListener_DataContainer()
74 void Notify( SfxBroadcaster
& aBC
,
75 const SfxHint
& aHint
) override
;
78 static awt::Size
impl_Size_Object2Struct( const Size
& aSize
)
80 awt::Size aReturnValue
;
81 aReturnValue
.Width
= aSize
.Width() ;
82 aReturnValue
.Height
= aSize
.Height() ;
86 static Size
impl_Size_Struct2Object( const awt::Size
& aSize
)
89 aReturnValue
.setWidth( aSize
.Width
) ;
90 aReturnValue
.setHeight( aSize
.Height
) ;
96 class SfxPrintJob_Impl
: public cppu::WeakImplHelper
101 IMPL_PrintListener_DataContainer
* m_pData
;
104 explicit SfxPrintJob_Impl( IMPL_PrintListener_DataContainer
* pData
);
105 virtual Sequence
< css::beans::PropertyValue
> SAL_CALL
getPrintOptions( ) override
;
106 virtual Sequence
< css::beans::PropertyValue
> SAL_CALL
getPrinter( ) override
;
107 virtual Reference
< css::view::XPrintable
> SAL_CALL
getPrintable( ) override
;
108 virtual void SAL_CALL
cancelJob() override
;
113 SfxPrintJob_Impl::SfxPrintJob_Impl( IMPL_PrintListener_DataContainer
* pData
)
118 Sequence
< css::beans::PropertyValue
> SAL_CALL
SfxPrintJob_Impl::getPrintOptions()
120 return m_pData
->m_aPrintOptions
;
123 Sequence
< css::beans::PropertyValue
> SAL_CALL
SfxPrintJob_Impl::getPrinter()
125 if( m_pData
->m_pObjectShell
.is() )
127 Reference
< view::XPrintable
> xPrintable( m_pData
->m_pObjectShell
->GetModel(), UNO_QUERY
);
128 if ( xPrintable
.is() )
129 return xPrintable
->getPrinter();
131 return Sequence
< css::beans::PropertyValue
>();
134 Reference
< css::view::XPrintable
> SAL_CALL
SfxPrintJob_Impl::getPrintable()
136 Reference
< view::XPrintable
> xPrintable( m_pData
->m_pObjectShell
.is() ? m_pData
->m_pObjectShell
->GetModel() : nullptr, UNO_QUERY
);
140 void SAL_CALL
SfxPrintJob_Impl::cancelJob()
142 // FIXME: how to cancel PrintJob via API?!
143 if( m_pData
->m_pObjectShell
.is() )
144 m_pData
->m_pObjectShell
->Broadcast( SfxPrintingHint( SFX_PRINTABLESTATE_CANCELJOB
) );
147 SfxPrintHelper::SfxPrintHelper()
149 m_pData
.reset(new IMPL_PrintListener_DataContainer());
152 void SAL_CALL
SfxPrintHelper::initialize( const css::uno::Sequence
< css::uno::Any
>& aArguments
)
154 if ( !aArguments
.hasElements() )
157 css::uno::Reference
< css::frame::XModel
> xModel
;
158 aArguments
[0] >>= xModel
;
159 m_pData
->m_pObjectShell
= SfxObjectShell::GetShellFromComponent(xModel
);
160 if (m_pData
->m_pObjectShell
)
161 m_pData
->StartListening(*m_pData
->m_pObjectShell
);
164 SfxPrintHelper::~SfxPrintHelper()
170 view::PaperFormat
convertToPaperFormat(Paper eFormat
)
172 view::PaperFormat eRet
;
176 eRet
= view::PaperFormat_A3
;
179 eRet
= view::PaperFormat_A4
;
182 eRet
= view::PaperFormat_A5
;
185 eRet
= view::PaperFormat_B4
;
188 eRet
= view::PaperFormat_B5
;
191 eRet
= view::PaperFormat_LETTER
;
194 eRet
= view::PaperFormat_LEGAL
;
197 eRet
= view::PaperFormat_TABLOID
;
201 eRet
= view::PaperFormat_USER
;
207 Paper
convertToPaper(view::PaperFormat eFormat
)
209 Paper
eRet(PAPER_USER
);
212 case view::PaperFormat_A3
:
215 case view::PaperFormat_A4
:
218 case view::PaperFormat_A5
:
221 case view::PaperFormat_B4
:
224 case view::PaperFormat_B5
:
227 case view::PaperFormat_LETTER
:
230 case view::PaperFormat_LEGAL
:
233 case view::PaperFormat_TABLOID
:
234 eRet
= PAPER_TABLOID
;
236 case view::PaperFormat_USER
:
239 case view::PaperFormat::PaperFormat_MAKE_FIXED_SIZE
:
241 //deliberate no default to force warn on a new papersize
251 uno::Sequence
< beans::PropertyValue
> SAL_CALL
SfxPrintHelper::getPrinter()
253 // object already disposed?
254 SolarMutexGuard aGuard
;
256 // search for any view of this document that is currently printing
257 const Printer
*pPrinter
= nullptr;
258 SfxViewFrame
*pViewFrm
= m_pData
->m_pObjectShell
.is() ? SfxViewFrame::GetFirst( m_pData
->m_pObjectShell
.get(), false ) : nullptr;
259 SfxViewFrame
* pFirst
= pViewFrm
;
260 while ( pViewFrm
&& !pPrinter
)
262 pPrinter
= pViewFrm
->GetViewShell()->GetActivePrinter();
263 pViewFrm
= SfxViewFrame::GetNext( *pViewFrm
, m_pData
->m_pObjectShell
.get(), false );
266 // if no view is printing currently, use the permanent SfxPrinter instance
267 if ( !pPrinter
&& pFirst
)
268 pPrinter
= pFirst
->GetViewShell()->GetPrinter(true);
271 return uno::Sequence
< beans::PropertyValue
>();
275 comphelper::makePropertyValue(u
"Name"_ustr
, pPrinter
->GetName()),
276 comphelper::makePropertyValue(u
"PaperOrientation"_ustr
, static_cast<view::PaperOrientation
>(pPrinter
->GetOrientation())),
277 comphelper::makePropertyValue(u
"PaperFormat"_ustr
, convertToPaperFormat(pPrinter
->GetPaper())),
278 comphelper::makePropertyValue(u
"PaperSize"_ustr
, impl_Size_Object2Struct(pPrinter
->GetPaperSize() )),
279 comphelper::makePropertyValue(u
"IsBusy"_ustr
, pPrinter
->IsPrinting()),
280 comphelper::makePropertyValue(u
"CanSetPaperOrientation"_ustr
, pPrinter
->HasSupport( PrinterSupport::SetOrientation
)),
281 comphelper::makePropertyValue(u
"CanSetPaperFormat"_ustr
, pPrinter
->HasSupport( PrinterSupport::SetPaper
)),
282 comphelper::makePropertyValue(u
"CanSetPaperSize"_ustr
, pPrinter
->HasSupport( PrinterSupport::SetPaperSize
))
290 void SfxPrintHelper::impl_setPrinter(const uno::Sequence
< beans::PropertyValue
>& rPrinter
,
291 VclPtr
<SfxPrinter
>& pPrinter
,
292 SfxPrinterChangeFlags
& nChangeFlags
,
293 SfxViewShell
*& pViewSh
)
297 SfxViewFrame
*pViewFrm
= m_pData
->m_pObjectShell
.is() ?
298 SfxViewFrame::GetFirst( m_pData
->m_pObjectShell
.get(), false ) : nullptr;
302 pViewSh
= pViewFrm
->GetViewShell();
303 pPrinter
= pViewSh
->GetPrinter(true);
307 // new Printer-Name available?
308 nChangeFlags
= SfxPrinterChangeFlags::NONE
;
309 sal_Int32 lDummy
= 0;
310 auto pProp
= std::find_if(rPrinter
.begin(), rPrinter
.end(),
311 [](const beans::PropertyValue
&rProp
) { return rProp
.Name
== "Name"; });
312 if (pProp
!= rPrinter
.end())
314 OUString aPrinterName
;
315 if ( ! ( pProp
->Value
>>= aPrinterName
) )
316 throw css::lang::IllegalArgumentException();
318 if ( aPrinterName
!= pPrinter
->GetName() )
320 pPrinter
= VclPtr
<SfxPrinter
>::Create( pPrinter
->GetOptions().Clone(), aPrinterName
);
321 nChangeFlags
= SfxPrinterChangeFlags::PRINTER
;
325 Size
aSetPaperSize( 0, 0);
326 view::PaperFormat nPaperFormat
= view::PaperFormat_USER
;
329 for ( const beans::PropertyValue
&rProp
: rPrinter
)
331 // get Property-Value from printer description
332 // PaperOrientation-Property?
333 if ( rProp
.Name
== "PaperOrientation" )
335 view::PaperOrientation eOrient
;
336 if ( !( rProp
.Value
>>= eOrient
) )
338 if ( !( rProp
.Value
>>= lDummy
) )
339 throw css::lang::IllegalArgumentException();
340 eOrient
= static_cast<view::PaperOrientation
>(lDummy
);
343 if ( static_cast<Orientation
>(eOrient
) != pPrinter
->GetOrientation() )
345 pPrinter
->SetOrientation( static_cast<Orientation
>(eOrient
) );
346 nChangeFlags
|= SfxPrinterChangeFlags::CHG_ORIENTATION
;
350 // PaperFormat-Property?
351 else if ( rProp
.Name
== "PaperFormat" )
353 if ( !( rProp
.Value
>>= nPaperFormat
) )
355 if ( !( rProp
.Value
>>= lDummy
) )
356 throw css::lang::IllegalArgumentException();
357 nPaperFormat
= static_cast<view::PaperFormat
>(lDummy
);
360 if ( convertToPaper(nPaperFormat
) != pPrinter
->GetPaper() )
362 pPrinter
->SetPaper( convertToPaper(nPaperFormat
) );
363 nChangeFlags
|= SfxPrinterChangeFlags::CHG_SIZE
;
367 // PaperSize-Property?
368 else if ( rProp
.Name
== "PaperSize" )
370 awt::Size aTempSize
;
371 if ( !( rProp
.Value
>>= aTempSize
) )
373 throw css::lang::IllegalArgumentException();
375 aSetPaperSize
= impl_Size_Struct2Object(aTempSize
);
378 // PrinterTray-Property
379 else if ( rProp
.Name
== "PrinterPaperTray" )
382 if ( !( rProp
.Value
>>= aTmp
) )
383 throw css::lang::IllegalArgumentException();
384 const sal_uInt16 nCount
= pPrinter
->GetPaperBinCount();
385 for (sal_uInt16 nBin
=0; nBin
<nCount
; nBin
++)
387 OUString
aName( pPrinter
->GetPaperBinName(nBin
) );
390 pPrinter
->SetPaperBin(nBin
);
397 // The PaperSize may be set only when actually PAPER_USER
398 // applies, otherwise the driver could choose an invalid format.
399 if(nPaperFormat
== view::PaperFormat_USER
&& aSetPaperSize
.Width())
401 // Bug 56929 - MapMode of 100mm which recalculated when
402 // the device is set. Additionally only set if they were really changed.
403 aSetPaperSize
= pPrinter
->LogicToPixel(aSetPaperSize
, MapMode(MapUnit::Map100thMM
));
404 if( aSetPaperSize
!= pPrinter
->GetPaperSizePixel() )
406 pPrinter
->SetPaperSizeUser( pPrinter
->PixelToLogic( aSetPaperSize
) );
407 nChangeFlags
|= SfxPrinterChangeFlags::CHG_SIZE
;
411 //wait until printing is done
412 SfxPrinter
* pDocPrinter
= pViewSh
->GetPrinter();
413 while ( pDocPrinter
->IsPrinting() && !Application::IsQuit())
414 Application::Yield();
417 void SAL_CALL
SfxPrintHelper::setPrinter(const uno::Sequence
< beans::PropertyValue
>& rPrinter
)
419 // object already disposed?
420 SolarMutexGuard aGuard
;
422 SfxViewShell
* pViewSh
= nullptr;
423 VclPtr
<SfxPrinter
> pPrinter
;
424 SfxPrinterChangeFlags nChangeFlags
= SfxPrinterChangeFlags::NONE
;
425 impl_setPrinter(rPrinter
,pPrinter
,nChangeFlags
,pViewSh
);
427 if ( pViewSh
&& pPrinter
)
428 pViewSh
->SetPrinter( pPrinter
, nChangeFlags
);
432 // ImplPrintWatch thread for asynchronous printing with moving temp. file to ucb location
436 /* This implements a thread which will be started to wait for asynchronous
437 print jobs to temp. locally files. If they finish we move the temp. files
438 to their right locations by using the ucb.
440 class ImplUCBPrintWatcher
: public ::osl::Thread
443 /// of course we must know the printer which execute the job
444 VclPtr
<SfxPrinter
> m_pPrinter
;
445 /// this describes the target location for the printed temp file
446 OUString m_sTargetURL
;
447 /// it holds the temp file alive, till the print job will finish and remove it from disk automatically if the object die
448 ::utl::TempFileNamed
* m_pTempFile
;
451 /* initialize this watcher but don't start it */
452 ImplUCBPrintWatcher( SfxPrinter
* pPrinter
, ::utl::TempFileNamed
* pTempFile
, OUString sTargetURL
)
453 : m_pPrinter ( pPrinter
)
454 , m_sTargetURL(std::move( sTargetURL
))
455 , m_pTempFile ( pTempFile
)
458 /* waits for finishing of the print job and moves the temp file afterwards
459 Note: Starting of the job is done outside this thread!
460 But we have to free some of the given resources on heap!
462 void SAL_CALL
run() override
464 osl_setThreadName("ImplUCBPrintWatcher");
468 SolarMutexGuard aGuard
;
469 while( m_pPrinter
->IsPrinting() && !Application::IsQuit())
470 Application::Yield();
471 m_pPrinter
.clear(); // don't delete it! It's borrowed only :-)
475 // lock for further using of our member isn't necessary - because
476 // we run alone by definition. Nobody join for us nor use us...
477 moveAndDeleteTemp(&m_pTempFile
,m_sTargetURL
);
479 // finishing of this run() method will call onTerminate() automatically
480 // kill this thread there!
483 /* nobody wait for this thread. We must kill ourself ...
485 void SAL_CALL
onTerminated() override
490 /* static helper to move the temp. file to the target location by using the ucb
491 It's static to be usable from outside too. So it's not really necessary to start
492 the thread, if finishing of the job was detected outside this thread.
493 But it must be called without using a corresponding thread for the given parameter!
495 static void moveAndDeleteTemp( ::utl::TempFileNamed
** ppTempFile
, std::u16string_view sTargetURL
)
500 INetURLObject
aSplitter(sTargetURL
);
501 OUString sFileName
= aSplitter
.getName(
502 INetURLObject::LAST_SEGMENT
,
504 INetURLObject::DecodeMechanism::WithCharset
);
505 if (aSplitter
.removeSegment() && !sFileName
.isEmpty())
507 ::ucbhelper::Content
aSource(
508 (*ppTempFile
)->GetURL(),
509 css::uno::Reference
< css::ucb::XCommandEnvironment
>(),
510 comphelper::getProcessComponentContext());
512 ::ucbhelper::Content
aTarget(
513 aSplitter
.GetMainURL(INetURLObject::DecodeMechanism::NONE
),
514 css::uno::Reference
< css::ucb::XCommandEnvironment
>(),
515 comphelper::getProcessComponentContext());
517 aTarget
.transferContent(
519 ::ucbhelper::InsertOperation::Copy
,
521 css::ucb::NameClash::OVERWRITE
);
524 catch (const css::uno::Exception
&)
526 TOOLS_WARN_EXCEPTION( "sfx.doc", "");
529 // kill the temp file!
531 *ppTempFile
= nullptr;
539 void SAL_CALL
SfxPrintHelper::print(const uno::Sequence
< beans::PropertyValue
>& rOptions
)
541 if( Application::GetSettings().GetMiscSettings().GetDisablePrinting() )
544 // object already disposed?
545 // object already disposed?
546 SolarMutexGuard aGuard
;
548 // get view for sfx printing capabilities
549 SfxViewFrame
*pViewFrm
= m_pData
->m_pObjectShell
.is() ?
550 SfxViewFrame::GetFirst( m_pData
->m_pObjectShell
.get(), false ) : nullptr;
553 SfxViewShell
* pView
= pViewFrm
->GetViewShell();
556 bool bMonitor
= false;
557 // We need this information at the end of this method, if we start the vcl printer
558 // by executing the slot. Because if it is a ucb relevant URL we must wait for
559 // finishing the print job and move the temporary local file by using the ucb
560 // to the right location. But in case of no file name is given or it is already
561 // a local one we can suppress this special handling. Because then vcl makes all
564 ::utl::TempFileNamed
* pUCBPrintTempFile
= nullptr;
566 uno::Sequence
< beans::PropertyValue
> aCheckedArgs( rOptions
.getLength() );
567 auto pCheckedArgs
= aCheckedArgs
.getArray();
568 sal_Int32 nProps
= 0;
569 bool bWaitUntilEnd
= false;
570 sal_Int16 nDuplexMode
= css::view::DuplexMode::UNKNOWN
;
571 for ( const beans::PropertyValue
&rProp
: rOptions
)
573 // get Property-Value from options
574 // FileName-Property?
575 if ( rProp
.Name
== "FileName" )
577 // unpack th URL and check for a valid and well known protocol
580 ( rProp
.Value
.getValueType()!=cppu::UnoType
<OUString
>::get()) ||
581 (!(rProp
.Value
>>=sTemp
))
584 throw css::lang::IllegalArgumentException();
588 OUString
sURL (sTemp
);
589 INetURLObject
aCheck(sURL
);
590 if (aCheck
.GetProtocol()==INetProtocol::NotValid
)
592 // OK - it's not a valid URL. But may it's a simple
593 // system path directly. It will be supported for historical
594 // reasons. Otherwise we break too much external code...
595 // We try to convert it to a file URL. If it's possible
596 // we put the system path to the item set and let vcl work with it.
597 // No ucb or thread will be necessary then. In case it couldn't be
598 // converted it's not a URL nor a system path. Then we can't accept
599 // this parameter and have to throw an exception.
600 const OUString
& sSystemPath(sTemp
);
602 if (::osl::FileBase::getFileURLFromSystemPath(sSystemPath
,sFileURL
)!=::osl::FileBase::E_None
)
603 throw css::lang::IllegalArgumentException();
604 pCheckedArgs
[nProps
].Name
= rProp
.Name
;
605 pCheckedArgs
[nProps
++].Value
<<= sFileURL
;
606 // and append the local filename
607 aCheckedArgs
.realloc( aCheckedArgs
.getLength()+1 );
608 pCheckedArgs
= aCheckedArgs
.getArray();
609 pCheckedArgs
[nProps
].Name
= "LocalFileName";
610 pCheckedArgs
[nProps
++].Value
<<= sTemp
;
613 // It's a valid URL. but now we must know, if it is a local one or not.
614 // It's a question of using ucb or not!
615 if (osl::FileBase::getSystemPathFromFileURL(sURL
, sPath
) == osl::FileBase::E_None
)
617 // it's a local file, we can use vcl without special handling
618 // And we have to use the system notation of the incoming URL.
619 // But it into the descriptor and let the slot be executed at
620 // the end of this method.
621 pCheckedArgs
[nProps
].Name
= rProp
.Name
;
622 pCheckedArgs
[nProps
++].Value
<<= sTemp
;
623 // and append the local filename
624 aCheckedArgs
.realloc( aCheckedArgs
.getLength()+1 );
625 pCheckedArgs
= aCheckedArgs
.getArray();
626 pCheckedArgs
[nProps
].Name
= "LocalFileName";
627 pCheckedArgs
[nProps
++].Value
<<= sPath
;
631 // it's a ucb target. So we must use a temp. file for vcl
632 // and move it after printing by using the ucb.
633 // Create a temp file on the heap (because it must delete the
634 // real file on disk automatically if it die - bt we have to share it with
635 // some other sources ... e.g. the ImplUCBPrintWatcher).
636 // And we put the name of this temp file to the descriptor instead
637 // of the URL. The URL we save for later using separately.
638 // Execution of the print job will be done later by executing
640 if(!pUCBPrintTempFile
)
641 pUCBPrintTempFile
= new ::utl::TempFileNamed();
642 pUCBPrintTempFile
->EnableKillingFile();
644 //FIXME: does it work?
645 pCheckedArgs
[nProps
].Name
= "LocalFileName";
646 pCheckedArgs
[nProps
++].Value
<<= pUCBPrintTempFile
->GetFileName();
651 // CopyCount-Property
652 else if ( rProp
.Name
== "CopyCount" )
654 sal_Int32 nCopies
= 0;
655 if ( !( rProp
.Value
>>= nCopies
) )
656 throw css::lang::IllegalArgumentException();
657 pCheckedArgs
[nProps
].Name
= rProp
.Name
;
658 pCheckedArgs
[nProps
++].Value
<<= nCopies
;
662 // Sort-Property (deprecated)
663 else if ( rProp
.Name
== "Collate" || rProp
.Name
== "Sort" )
666 if ( !(rProp
.Value
>>= bTemp
) )
667 throw css::lang::IllegalArgumentException();
668 pCheckedArgs
[nProps
].Name
= "Collate";
669 pCheckedArgs
[nProps
++].Value
<<= bTemp
;
672 else if ( rProp
.Name
== "SinglePrintJobs" )
675 if ( !(rProp
.Value
>>= bTemp
) )
676 throw css::lang::IllegalArgumentException();
677 pCheckedArgs
[nProps
].Name
= "SinglePrintJobs";
678 pCheckedArgs
[nProps
++].Value
<<= bTemp
;
681 else if ( rProp
.Name
== "JobName" )
684 if( !(rProp
.Value
>>= sTemp
) )
685 throw css::lang::IllegalArgumentException();
686 pCheckedArgs
[nProps
].Name
= rProp
.Name
;
687 pCheckedArgs
[nProps
++].Value
<<= sTemp
;
691 else if ( rProp
.Name
== "Pages" )
694 if( !(rProp
.Value
>>= sTemp
) )
695 throw css::lang::IllegalArgumentException();
696 pCheckedArgs
[nProps
].Name
= rProp
.Name
;
697 pCheckedArgs
[nProps
++].Value
<<= sTemp
;
701 else if ( rProp
.Name
== "MonitorVisible" )
703 if( !(rProp
.Value
>>= bMonitor
) )
704 throw css::lang::IllegalArgumentException();
705 pCheckedArgs
[nProps
].Name
= rProp
.Name
;
706 pCheckedArgs
[nProps
++].Value
<<= bMonitor
;
710 else if ( rProp
.Name
== "Wait" )
712 if ( !(rProp
.Value
>>= bWaitUntilEnd
) )
713 throw css::lang::IllegalArgumentException();
714 pCheckedArgs
[nProps
].Name
= rProp
.Name
;
715 pCheckedArgs
[nProps
++].Value
<<= bWaitUntilEnd
;
718 else if ( rProp
.Name
== "DuplexMode" )
720 if ( !(rProp
.Value
>>= nDuplexMode
) )
721 throw css::lang::IllegalArgumentException();
722 pCheckedArgs
[nProps
].Name
= rProp
.Name
;
723 pCheckedArgs
[nProps
++].Value
<<= nDuplexMode
;
727 if ( nProps
!= aCheckedArgs
.getLength() )
728 aCheckedArgs
.realloc(nProps
);
730 // Execute the print request every time.
731 // It doesn't matter if it is a real printer used or we print to a local file
732 // nor if we print to a temp file and move it afterwards by using the ucb.
733 // That will be handled later. see pUCBPrintFile below!
734 pView
->ExecPrint( aCheckedArgs
, true, false );
736 // Ok - may be execution before has finished (or started!) printing.
737 // And may it was a printing to a file.
738 // Now we have to check if we can move the file (if necessary) via UCB to its right location.
740 // a) printing finished => move the file directly and forget the watcher thread
741 // b) printing is asynchron and runs currently => start watcher thread and exit this method
742 // This thread make all necessary things by itself.
743 if (!pUCBPrintTempFile
)
747 SfxPrinter
* pPrinter
= pView
->GetPrinter();
748 if ( ! pPrinter
->IsPrinting() )
749 ImplUCBPrintWatcher::moveAndDeleteTemp(&pUCBPrintTempFile
,sUcbUrl
);
753 // Note: we create(d) some resource on the heap (thread and temp file).
754 // They will be deleted by the thread automatically if it finishes its run() method.
755 ImplUCBPrintWatcher
* pWatcher
= new ImplUCBPrintWatcher( pPrinter
, pUCBPrintTempFile
, sUcbUrl
);
760 void IMPL_PrintListener_DataContainer::Notify( SfxBroadcaster
& rBC
, const SfxHint
& rHint
)
762 if (rHint
.GetId() != SfxHintId::ThisIsAnSfxEventHint
)
764 const SfxEventHint
& rEventHint
= static_cast<const SfxEventHint
&>(rHint
);
765 if (rEventHint
.GetEventId() != SfxEventHintId::PrintDoc
)
767 const SfxPrintingHint
* pPrintHint
= static_cast<const SfxPrintingHint
*>(&rHint
);
768 if ( &rBC
!= m_pObjectShell
.get()
769 || pPrintHint
->GetWhich() == SFX_PRINTABLESTATE_CANCELJOB
)
772 if ( pPrintHint
->GetWhich() == css::view::PrintableState_JOB_STARTED
)
774 if ( !m_xPrintJob
.is() )
775 m_xPrintJob
= new SfxPrintJob_Impl( this );
776 m_aPrintOptions
= pPrintHint
->GetOptions();
779 std::unique_lock
aGuard(m_aMutex
);
780 if (!m_aJobListeners
.getLength(aGuard
))
782 view::PrintJobEvent aEvent
;
783 aEvent
.Source
= getXWeak(m_xPrintJob
.get());
784 aEvent
.State
= pPrintHint
->GetWhich();
786 comphelper::OInterfaceIteratorHelper4
pIterator(aGuard
, m_aJobListeners
);
788 while (pIterator
.hasMoreElements())
789 pIterator
.next()->printJobEvent( aEvent
);
792 void SAL_CALL
SfxPrintHelper::addPrintJobListener( const css::uno::Reference
< css::view::XPrintJobListener
>& xListener
)
794 std::unique_lock
aGuard(m_pData
->m_aMutex
);
795 m_pData
->m_aJobListeners
.addInterface( aGuard
, xListener
);
798 void SAL_CALL
SfxPrintHelper::removePrintJobListener( const css::uno::Reference
< css::view::XPrintJobListener
>& xListener
)
800 std::unique_lock
aGuard(m_pData
->m_aMutex
);
801 m_pData
->m_aJobListeners
.removeInterface( aGuard
, xListener
);
805 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */