update dev300-m58
[ooovba.git] / sfx2 / source / doc / printhelper.cxx
blobca0e28d3222ee804820e5cc93130110855ca7b72
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: printhelper.cxx,v $
10 * $Revision: 1.5 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sfx2.hxx"
34 #include "printhelper.hxx"
36 #include <com/sun/star/view/XPrintJob.hpp>
37 #include <com/sun/star/awt/Size.hpp>
38 #include <com/sun/star/lang/IllegalArgumentException.hpp>
39 #include <com/sun/star/view/PaperFormat.hpp>
40 #include <com/sun/star/view/PaperOrientation.hpp>
41 #include <com/sun/star/ucb/NameClash.hpp>
42 #include <com/sun/star/lang/XUnoTunnel.hpp>
43 #include <com/sun/star/frame/XModel.hpp>
44 #include <com/sun/star/lang/EventObject.hpp>
46 #include <svtools/lstner.hxx>
47 #include <svtools/stritem.hxx>
48 #include <svtools/intitem.hxx>
49 #include <svtools/eitem.hxx>
50 #include <unotools/tempfile.hxx>
51 #include <unotools/localfilehelper.hxx>
52 #include <osl/file.hxx>
53 #include <osl/thread.hxx>
54 #include <tools/urlobj.hxx>
55 #include <ucbhelper/content.hxx>
56 #include <cppuhelper/interfacecontainer.hxx>
57 #include <vos/mutex.hxx>
58 #include <svtools/printdlg.hxx>
59 #include <cppuhelper/implbase1.hxx>
61 #include <sfx2/viewfrm.hxx>
62 #include <sfx2/viewsh.hxx>
63 #include <sfx2/dispatch.hxx>
64 #include <sfx2/request.hxx>
65 #include <sfx2/printer.hxx>
66 #include <sfx2/app.hxx>
67 #include <sfx2/objsh.hxx>
68 #include <sfx2/event.hxx>
70 using namespace ::com::sun::star;
71 using namespace ::com::sun::star::uno;
73 struct IMPL_PrintListener_DataContainer : public SfxListener
75 SfxObjectShellRef m_pObjectShell;
76 ::cppu::OMultiTypeInterfaceContainerHelper m_aInterfaceContainer;
77 uno::Reference< com::sun::star::view::XPrintJob> m_xPrintJob;
78 ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > m_aPrintOptions;
80 IMPL_PrintListener_DataContainer( ::osl::Mutex& aMutex)
81 : m_pObjectShell ( 0 )
82 , m_aInterfaceContainer ( aMutex )
87 void Notify( SfxBroadcaster& aBC ,
88 const SfxHint& aHint ) ;
91 awt::Size impl_Size_Object2Struct( const Size& aSize )
93 awt::Size aReturnValue;
94 aReturnValue.Width = aSize.Width() ;
95 aReturnValue.Height = aSize.Height() ;
96 return aReturnValue ;
99 Size impl_Size_Struct2Object( const awt::Size& aSize )
101 Size aReturnValue;
102 aReturnValue.Width() = aSize.Width ;
103 aReturnValue.Height() = aSize.Height ;
104 return aReturnValue ;
107 class SfxPrintJob_Impl : public cppu::WeakImplHelper1
109 com::sun::star::view::XPrintJob
112 IMPL_PrintListener_DataContainer* m_pData;
114 public:
115 SfxPrintJob_Impl( IMPL_PrintListener_DataContainer* pData );
116 virtual Sequence< ::com::sun::star::beans::PropertyValue > SAL_CALL getPrintOptions( ) throw (RuntimeException);
117 virtual Sequence< ::com::sun::star::beans::PropertyValue > SAL_CALL getPrinter( ) throw (RuntimeException);
118 virtual Reference< ::com::sun::star::view::XPrintable > SAL_CALL getPrintable( ) throw (RuntimeException);
119 virtual void SAL_CALL cancelJob() throw (RuntimeException);
122 SfxPrintJob_Impl::SfxPrintJob_Impl( IMPL_PrintListener_DataContainer* pData )
123 : m_pData( pData )
127 Sequence< ::com::sun::star::beans::PropertyValue > SAL_CALL SfxPrintJob_Impl::getPrintOptions() throw (RuntimeException)
129 return m_pData->m_aPrintOptions;
132 Sequence< ::com::sun::star::beans::PropertyValue > SAL_CALL SfxPrintJob_Impl::getPrinter() throw (RuntimeException)
134 if( m_pData->m_pObjectShell.Is() )
136 Reference < view::XPrintable > xPrintable( m_pData->m_pObjectShell->GetModel(), UNO_QUERY );
137 if ( xPrintable.is() )
138 return xPrintable->getPrinter();
140 return Sequence< ::com::sun::star::beans::PropertyValue >();
143 Reference< ::com::sun::star::view::XPrintable > SAL_CALL SfxPrintJob_Impl::getPrintable() throw (RuntimeException)
145 Reference < view::XPrintable > xPrintable( m_pData->m_pObjectShell.Is() ? m_pData->m_pObjectShell->GetModel() : NULL, UNO_QUERY );
146 return xPrintable;
149 void SAL_CALL SfxPrintJob_Impl::cancelJob() throw (RuntimeException)
151 if( m_pData->m_pObjectShell.Is() )
152 m_pData->m_pObjectShell->Broadcast( SfxPrintingHint( -2, NULL, NULL ) );
155 SfxPrintHelper::SfxPrintHelper()
157 m_pData = new IMPL_PrintListener_DataContainer(m_aMutex);
160 void SAL_CALL SfxPrintHelper::initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException)
162 if ( aArguments.getLength() )
164 com::sun::star::uno::Reference < com::sun::star::frame::XModel > xModel;
165 aArguments[0] >>= xModel;
166 uno::Reference < lang::XUnoTunnel > xObj( xModel, uno::UNO_QUERY );
167 uno::Sequence < sal_Int8 > aSeq( SvGlobalName( SFX_GLOBAL_CLASSID ).GetByteSequence() );
168 sal_Int64 nHandle = xObj->getSomething( aSeq );
169 if ( nHandle )
171 m_pData->m_pObjectShell = reinterpret_cast< SfxObjectShell* >( sal::static_int_cast< sal_IntPtr >( nHandle ));
172 m_pData->StartListening(*m_pData->m_pObjectShell);
177 SfxPrintHelper::~SfxPrintHelper()
179 delete m_pData;
182 namespace
184 view::PaperFormat convertToPaperFormat(Paper eFormat)
186 view::PaperFormat eRet;
187 switch (eFormat)
189 case PAPER_A3:
190 eRet = view::PaperFormat_A3;
191 break;
192 case PAPER_A4:
193 eRet = view::PaperFormat_A4;
194 break;
195 case PAPER_A5:
196 eRet = view::PaperFormat_A5;
197 break;
198 case PAPER_B4_ISO:
199 eRet = view::PaperFormat_B4;
200 break;
201 case PAPER_B5_ISO:
202 eRet = view::PaperFormat_B5;
203 break;
204 case PAPER_LETTER:
205 eRet = view::PaperFormat_LETTER;
206 break;
207 case PAPER_LEGAL:
208 eRet = view::PaperFormat_LEGAL;
209 break;
210 case PAPER_TABLOID:
211 eRet = view::PaperFormat_TABLOID;
212 break;
213 case PAPER_USER:
214 default:
215 eRet = view::PaperFormat_USER;
216 break;
218 return eRet;
221 Paper convertToPaper(view::PaperFormat eFormat)
223 Paper eRet(PAPER_USER);
224 switch (eFormat)
226 case view::PaperFormat_A3:
227 eRet = PAPER_A3;
228 break;
229 case view::PaperFormat_A4:
230 eRet = PAPER_A4;
231 break;
232 case view::PaperFormat_A5:
233 eRet = PAPER_A5;
234 break;
235 case view::PaperFormat_B4:
236 eRet = PAPER_B4_ISO;
237 break;
238 case view::PaperFormat_B5:
239 eRet = PAPER_B5_ISO;
240 break;
241 case view::PaperFormat_LETTER:
242 eRet = PAPER_LETTER;
243 break;
244 case view::PaperFormat_LEGAL:
245 eRet = PAPER_LEGAL;
246 break;
247 case view::PaperFormat_TABLOID:
248 eRet = PAPER_TABLOID;
249 break;
250 case view::PaperFormat_USER:
251 eRet = PAPER_USER;
252 break;
253 case view::PaperFormat_MAKE_FIXED_SIZE:
254 break;
255 //deliberate no default to force warn on a new papersize
257 return eRet;
261 //________________________________________________________________________________________________________
262 // XPrintable
263 //________________________________________________________________________________________________________
265 uno::Sequence< beans::PropertyValue > SAL_CALL SfxPrintHelper::getPrinter() throw(::com::sun::star::uno::RuntimeException)
267 // object already disposed?
268 ::vos::OGuard aGuard( Application::GetSolarMutex() );
270 // Printer beschaffen
271 SfxViewFrame *pViewFrm = m_pData->m_pObjectShell.Is() ?
272 SfxViewFrame::GetFirst( m_pData->m_pObjectShell, 0, sal_False ) : 0;
273 if ( !pViewFrm )
274 return uno::Sequence< beans::PropertyValue >();
276 const SfxPrinter *pPrinter = pViewFrm->GetViewShell()->GetPrinter(sal_True);
277 if ( !pPrinter )
278 return uno::Sequence< beans::PropertyValue >();
280 // Printer Eigenschaften uebertragen
281 uno::Sequence< beans::PropertyValue > aPrinter(8);
283 aPrinter.getArray()[7].Name = DEFINE_CONST_UNICODE( "CanSetPaperSize" );
284 aPrinter.getArray()[7].Value <<= ( pPrinter->HasSupport( SUPPORT_SET_PAPERSIZE ) );
286 aPrinter.getArray()[6].Name = DEFINE_CONST_UNICODE( "CanSetPaperFormat" );
287 aPrinter.getArray()[6].Value <<= ( pPrinter->HasSupport( SUPPORT_SET_PAPER ) );
289 aPrinter.getArray()[5].Name = DEFINE_CONST_UNICODE( "CanSetPaperOrientation" );
290 aPrinter.getArray()[5].Value <<= ( pPrinter->HasSupport( SUPPORT_SET_ORIENTATION ) );
292 aPrinter.getArray()[4].Name = DEFINE_CONST_UNICODE( "IsBusy" );
293 aPrinter.getArray()[4].Value <<= ( pPrinter->IsPrinting() );
295 aPrinter.getArray()[3].Name = DEFINE_CONST_UNICODE( "PaperSize" );
296 awt::Size aSize = impl_Size_Object2Struct(pPrinter->GetPaperSize() );
297 aPrinter.getArray()[3].Value <<= aSize;
299 aPrinter.getArray()[2].Name = DEFINE_CONST_UNICODE( "PaperFormat" );
300 view::PaperFormat eFormat = convertToPaperFormat(pPrinter->GetPaper());
301 aPrinter.getArray()[2].Value <<= eFormat;
303 aPrinter.getArray()[1].Name = DEFINE_CONST_UNICODE( "PaperOrientation" );
304 view::PaperOrientation eOrient = (view::PaperOrientation)pPrinter->GetOrientation();
305 aPrinter.getArray()[1].Value <<= eOrient;
307 aPrinter.getArray()[0].Name = DEFINE_CONST_UNICODE( "Name" );
308 String sStringTemp = pPrinter->GetName() ;
309 aPrinter.getArray()[0].Value <<= ::rtl::OUString( sStringTemp );
311 return aPrinter;
314 //________________________________________________________________________________________________________
315 // XPrintable
316 //________________________________________________________________________________________________________
318 void SfxPrintHelper::impl_setPrinter(const uno::Sequence< beans::PropertyValue >& rPrinter,SfxPrinter*& pPrinter,sal_uInt16& nChangeFlags,SfxViewShell*& pViewSh)
321 // alten Printer beschaffen
322 SfxViewFrame *pViewFrm = m_pData->m_pObjectShell.Is() ?
323 SfxViewFrame::GetFirst( m_pData->m_pObjectShell, 0, sal_False ) : 0;
324 if ( !pViewFrm )
325 return;
327 pViewSh = pViewFrm->GetViewShell();
328 pPrinter = pViewSh->GetPrinter(sal_True);
329 if ( !pPrinter )
330 return;
332 // new Printer-Name available?
333 nChangeFlags = 0;
334 sal_Int32 lDummy = 0;
335 for ( int n = 0; n < rPrinter.getLength(); ++n )
337 // get Property-Value from printer description
338 const beans::PropertyValue &rProp = rPrinter.getConstArray()[n];
340 // Name-Property?
341 if ( rProp.Name.compareToAscii( "Name" ) == 0 )
343 OUSTRING sTemp;
344 if ( ( rProp.Value >>= sTemp ) == sal_False )
345 throw ::com::sun::star::lang::IllegalArgumentException();
347 String aPrinterName( sTemp ) ;
348 if ( aPrinterName != pPrinter->GetName() )
350 pPrinter = new SfxPrinter( pPrinter->GetOptions().Clone(), aPrinterName );
351 nChangeFlags = SFX_PRINTER_PRINTER;
353 break;
357 Size aSetPaperSize( 0, 0);
358 view::PaperFormat nPaperFormat = view::PaperFormat_USER;
360 // other properties
361 for ( int i = 0; i < rPrinter.getLength(); ++i )
363 // get Property-Value from printer description
364 const beans::PropertyValue &rProp = rPrinter.getConstArray()[i];
366 // PaperOrientation-Property?
367 if ( rProp.Name.compareToAscii( "PaperOrientation" ) == 0 )
369 view::PaperOrientation eOrient;
370 if ( ( rProp.Value >>= eOrient ) == sal_False )
372 if ( ( rProp.Value >>= lDummy ) == sal_False )
373 throw ::com::sun::star::lang::IllegalArgumentException();
374 eOrient = ( view::PaperOrientation) lDummy;
377 if ( (Orientation) eOrient != pPrinter->GetOrientation() )
379 pPrinter->SetOrientation( (Orientation) eOrient );
380 nChangeFlags |= SFX_PRINTER_CHG_ORIENTATION;
384 // PaperFormat-Property?
385 else if ( rProp.Name.compareToAscii( "PaperFormat" ) == 0 )
387 if ( ( rProp.Value >>= nPaperFormat ) == sal_False )
389 if ( ( rProp.Value >>= lDummy ) == sal_False )
390 throw ::com::sun::star::lang::IllegalArgumentException();
391 nPaperFormat = ( view::PaperFormat ) lDummy;
394 if ( convertToPaper(nPaperFormat) != pPrinter->GetPaper() )
396 pPrinter->SetPaper( convertToPaper(nPaperFormat) );
397 nChangeFlags |= SFX_PRINTER_CHG_SIZE;
401 // PaperSize-Property?
402 else if ( rProp.Name.compareToAscii( "PaperSize" ) == 0 )
404 awt::Size aTempSize ;
405 if ( ( rProp.Value >>= aTempSize ) == sal_False )
407 throw ::com::sun::star::lang::IllegalArgumentException();
409 else
411 aSetPaperSize = impl_Size_Struct2Object(aTempSize);
415 // PrinterTray-Property
416 else if ( rProp.Name.compareToAscii( "PrinterPaperTray" ) == 0 )
418 rtl::OUString aTmp;
419 if ( ( rProp.Value >>= aTmp ) == sal_False )
420 throw ::com::sun::star::lang::IllegalArgumentException();
421 USHORT nCount = pPrinter->GetPaperBinCount();
422 for (USHORT nBin=0; nBin<nCount; nBin++)
424 ::rtl::OUString aName( pPrinter->GetPaperBinName(nBin) );
425 if ( aName == aTmp )
427 pPrinter->SetPaperBin(nBin);
428 break;
434 //os 12.11.98: die PaperSize darf nur gesetzt werden, wenn tatsaechlich
435 //PAPER_USER gilt, sonst koennte vom Treiber ein falsches Format gewaehlt werden
436 if(nPaperFormat == view::PaperFormat_USER && aSetPaperSize.Width())
438 //JP 23.09.98 - Bug 56929 - MapMode von 100mm in die am
439 // Device gesetzten umrechnen. Zusaetzlich nur dann
440 // setzen, wenn sie wirklich veraendert wurden.
441 aSetPaperSize = pPrinter->LogicToPixel( aSetPaperSize, MAP_100TH_MM );
442 if( aSetPaperSize != pPrinter->GetPaperSizePixel() )
444 pPrinter->SetPaperSizeUser( pPrinter->PixelToLogic( aSetPaperSize ) );
445 nChangeFlags |= SFX_PRINTER_CHG_SIZE;
449 // #96772#: wait until printing is done
450 SfxPrinter* pDocPrinter = pViewSh->GetPrinter();
451 while ( pDocPrinter->IsPrinting() )
452 Application::Yield();
455 void SAL_CALL SfxPrintHelper::setPrinter(const uno::Sequence< beans::PropertyValue >& rPrinter)
456 throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException)
458 // object already disposed?
459 ::vos::OGuard aGuard( Application::GetSolarMutex() );
461 SfxViewShell* pViewSh = NULL;
462 SfxPrinter* pPrinter = NULL;
463 sal_uInt16 nChangeFlags = 0;
464 impl_setPrinter(rPrinter,pPrinter,nChangeFlags,pViewSh);
465 // set new printer
466 if ( pViewSh && pPrinter )
467 pViewSh->SetPrinter( pPrinter, nChangeFlags, false );
470 //________________________________________________________________________________________________________
471 // ImplPrintWatch thread for asynchronous printing with moving temp. file to ucb location
472 //________________________________________________________________________________________________________
474 /* This implements a thread which will be started to wait for asynchronous
475 print jobs to temp. localy files. If they finish we move the temp. files
476 to her right locations by using the ucb.
478 class ImplUCBPrintWatcher : public ::osl::Thread
480 private:
481 /// of course we must know the printer which execute the job
482 SfxPrinter* m_pPrinter;
483 /// this describes the target location for the printed temp file
484 String m_sTargetURL;
485 /// it holds the temp file alive, till the print job will finish and remove it from disk automaticly if the object die
486 ::utl::TempFile* m_pTempFile;
488 public:
489 /* initialize this watcher but don't start it */
490 ImplUCBPrintWatcher( SfxPrinter* pPrinter, ::utl::TempFile* pTempFile, const String& sTargetURL )
491 : m_pPrinter ( pPrinter )
492 , m_sTargetURL( sTargetURL )
493 , m_pTempFile ( pTempFile )
496 /* waits for finishing of the print job and moves the temp file afterwards
497 Note: Starting of the job is done outside this thread!
498 But we have to free some of the given ressources on heap!
500 void SAL_CALL run()
502 /* SAFE { */
504 ::vos::OGuard aGuard( Application::GetSolarMutex() );
505 while( m_pPrinter->IsPrinting() )
506 Application::Yield();
507 m_pPrinter = NULL; // don't delete it! It's borrowed only :-)
509 /* } SAFE */
511 // lock for further using of our member isn't neccessary - because
512 // we truns alone by defenition. Nobody join for us nor use us ...
513 ImplUCBPrintWatcher::moveAndDeleteTemp(&m_pTempFile,m_sTargetURL);
515 // finishing of this run() method will call onTerminate() automaticly
516 // kill this thread there!
519 /* nobody wait for this thread. We must kill ourself ...
521 void SAL_CALL onTerminated()
523 delete this;
526 /* static helper to move the temp. file to the target location by using the ucb
527 It's static to be useable from outside too. So it's not realy neccessary to start
528 the thread, if finishing of the job was detected outside this thread.
529 But it must be called without using a corresponding thread for the given parameter!
531 static void moveAndDeleteTemp( ::utl::TempFile** ppTempFile, const String& sTargetURL )
533 // move the file
536 INetURLObject aSplitter(sTargetURL);
537 String sFileName = aSplitter.getName(
538 INetURLObject::LAST_SEGMENT,
539 true,
540 INetURLObject::DECODE_WITH_CHARSET);
541 if (aSplitter.removeSegment() && sFileName.Len()>0)
543 ::ucbhelper::Content aSource(
544 ::rtl::OUString((*ppTempFile)->GetURL()),
545 ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >());
547 ::ucbhelper::Content aTarget(
548 ::rtl::OUString(aSplitter.GetMainURL(INetURLObject::NO_DECODE)),
549 ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >());
551 aTarget.transferContent(
552 aSource,
553 ::ucbhelper::InsertOperation_COPY,
554 ::rtl::OUString(sFileName),
555 ::com::sun::star::ucb::NameClash::OVERWRITE);
558 catch( ::com::sun::star::ucb::ContentCreationException& ) { DBG_ERROR("content create exception"); }
559 catch( ::com::sun::star::ucb::CommandAbortedException& ) { DBG_ERROR("command abort exception"); }
560 catch( ::com::sun::star::uno::RuntimeException& ) { DBG_ERROR("runtime exception"); }
561 catch( ::com::sun::star::uno::Exception& ) { DBG_ERROR("unknown exception"); }
563 // kill the temp file!
564 delete *ppTempFile;
565 *ppTempFile = NULL;
569 //------------------------------------------------
571 //________________________________________________________________________________________________________
572 // XPrintable
573 //________________________________________________________________________________________________________
574 void SAL_CALL SfxPrintHelper::print(const uno::Sequence< beans::PropertyValue >& rOptions)
575 throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException)
577 if( Application::GetSettings().GetMiscSettings().GetDisablePrinting() )
578 return;
580 // object already disposed?
581 // object already disposed?
582 ::vos::OGuard aGuard( Application::GetSolarMutex() );
584 // get view for sfx printing capabilities
585 SfxViewFrame *pViewFrm = m_pData->m_pObjectShell.Is() ?
586 SfxViewFrame::GetFirst( m_pData->m_pObjectShell, 0, sal_False ) : 0;
587 if ( !pViewFrm )
588 return;
589 SfxViewShell* pView = pViewFrm->GetViewShell();
590 if ( !pView )
591 return;
593 SfxAllItemSet aArgs( pView->GetPool() );
594 sal_Bool bMonitor = sal_False;
595 // We need this information at the end of this method, if we start the vcl printer
596 // by executing the slot. Because if it is a ucb relevant URL we must wait for
597 // finishing the print job and move the temporary local file by using the ucb
598 // to the right location. But in case of no file name is given or it is already
599 // a local one we can supress this special handling. Because then vcl makes all
600 // right for us.
601 String sUcbUrl;
602 ::utl::TempFile* pUCBPrintTempFile = NULL;
604 sal_Bool bWaitUntilEnd = sal_False;
605 for ( int n = 0; n < rOptions.getLength(); ++n )
607 // get Property-Value from options
608 const beans::PropertyValue &rProp = rOptions.getConstArray()[n];
610 // FileName-Property?
611 if ( rProp.Name.compareToAscii( "FileName" ) == 0 )
613 // unpack th URL and check for a valid and well known protocol
614 OUSTRING sTemp;
615 if (
616 ( rProp.Value.getValueType()!=::getCppuType((const OUSTRING*)0)) ||
617 (!(rProp.Value>>=sTemp))
620 throw ::com::sun::star::lang::IllegalArgumentException();
623 String sPath ;
624 String sURL (sTemp);
625 INetURLObject aCheck(sURL );
626 if (aCheck.GetProtocol()==INET_PROT_NOT_VALID)
628 // OK - it's not a valid URL. But may it's a simple
629 // system path directly. It will be supported for historical
630 // reasons. Otherwhise we break to much external code ...
631 // We try to convert it to a file URL. If its possible
632 // we put the system path to the item set and let vcl work with it.
633 // No ucb or thread will be neccessary then. In case it couldnt be
634 // converted its not an URL nor a system path. Then we can't accept
635 // this parameter and have to throw an exception.
636 ::rtl::OUString sSystemPath(sTemp);
637 ::rtl::OUString sFileURL ;
638 if (::osl::FileBase::getFileURLFromSystemPath(sSystemPath,sFileURL)!=::osl::FileBase::E_None)
639 throw ::com::sun::star::lang::IllegalArgumentException();
640 aArgs.Put( SfxStringItem(SID_FILE_NAME,sTemp) );
642 else
643 // It's a valid URL. but now we must know, if it is a local one or not.
644 // It's a question of using ucb or not!
645 if (::utl::LocalFileHelper::ConvertURLToSystemPath(sURL,sPath))
647 // it's a local file, we can use vcl without special handling
648 // And we have to use the system notation of the incoming URL.
649 // But it into the descriptor and let the slot be executed at
650 // the end of this method.
651 aArgs.Put( SfxStringItem(SID_FILE_NAME,sPath) );
653 else
655 // it's an ucb target. So we must use a temp. file for vcl
656 // and move it after printing by using the ucb.
657 // Create a temp file on the heap (because it must delete the
658 // real file on disk automaticly if it die - bt we have to share it with
659 // some other sources ... e.g. the ImplUCBPrintWatcher).
660 // And we put the name of this temp file to the descriptor instead
661 // of the URL. The URL we save for later using seperatly.
662 // Execution of the print job will be done later by executing
663 // a slot ...
664 pUCBPrintTempFile = new ::utl::TempFile();
665 pUCBPrintTempFile->EnableKillingFile();
666 aArgs.Put( SfxStringItem(SID_FILE_NAME,pUCBPrintTempFile->GetFileName()) );
667 sUcbUrl = sURL;
671 // CopyCount-Property
672 else if ( rProp.Name.compareToAscii( "CopyCount" ) == 0 )
674 sal_Int32 nCopies = 0;
675 if ( ( rProp.Value >>= nCopies ) == sal_False )
676 throw ::com::sun::star::lang::IllegalArgumentException();
677 aArgs.Put( SfxInt16Item( SID_PRINT_COPIES, (USHORT) nCopies ) );
680 // Collate-Property
681 else if ( rProp.Name.compareToAscii( "Collate" ) == 0 )
683 sal_Bool bTemp = sal_Bool();
684 if ( rProp.Value >>= bTemp )
685 aArgs.Put( SfxBoolItem( SID_PRINT_COLLATE, bTemp ) );
686 else
687 throw ::com::sun::star::lang::IllegalArgumentException();
690 // Sort-Property
691 else if ( rProp.Name.compareToAscii( "Sort" ) == 0 )
693 sal_Bool bTemp = sal_Bool();
694 if( rProp.Value >>= bTemp )
695 aArgs.Put( SfxBoolItem( SID_PRINT_SORT, bTemp ) );
696 else
697 throw ::com::sun::star::lang::IllegalArgumentException();
700 // Pages-Property
701 else if ( rProp.Name.compareToAscii( "Pages" ) == 0 )
703 OUSTRING sTemp;
704 if( rProp.Value >>= sTemp )
705 aArgs.Put( SfxStringItem( SID_PRINT_PAGES, String( sTemp ) ) );
706 else
707 throw ::com::sun::star::lang::IllegalArgumentException();
710 // MonitorVisible
711 else if ( rProp.Name.compareToAscii( "MonitorVisible" ) == 0 )
713 if( !(rProp.Value >>= bMonitor) )
714 throw ::com::sun::star::lang::IllegalArgumentException();
717 // MonitorVisible
718 else if ( rProp.Name.compareToAscii( "Wait" ) == 0 )
720 if ( !(rProp.Value >>= bWaitUntilEnd) )
721 throw ::com::sun::star::lang::IllegalArgumentException();
725 // Execute the print request every time.
726 // It doesn'tmatter if it is a real printer used or we print to a local file
727 // nor if we print to a temp file and move it afterwards by using the ucb.
728 // That will be handled later. see pUCBPrintFile below!
729 aArgs.Put( SfxBoolItem( SID_SILENT, !bMonitor ) );
730 if ( bWaitUntilEnd )
731 aArgs.Put( SfxBoolItem( SID_ASYNCHRON, sal_False ) );
732 SfxRequest aReq( SID_PRINTDOC, SFX_CALLMODE_SYNCHRON | SFX_CALLMODE_API, pView->GetPool() );
733 aReq.SetArgs( aArgs );
734 pView->ExecuteSlot( aReq );
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 neccessary) via ucb to his right location.
739 // Cases:
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 neccessary things by itself.
743 if (pUCBPrintTempFile!=NULL)
745 // a)
746 SfxPrinter* pPrinter = pView->GetPrinter();
747 if ( ! pPrinter->IsPrinting() )
748 ImplUCBPrintWatcher::moveAndDeleteTemp(&pUCBPrintTempFile,sUcbUrl);
749 // b)
750 else
752 // Note: we create(d) some ressource on the heap. (thread and tep file)
753 // They will be delected by the thread automaticly if he finish his run() method.
754 ImplUCBPrintWatcher* pWatcher = new ImplUCBPrintWatcher( pPrinter, pUCBPrintTempFile, sUcbUrl );
755 pWatcher->create();
760 void IMPL_PrintListener_DataContainer::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
762 if ( &rBC == m_pObjectShell )
764 SfxPrintingHint* pPrintHint = PTR_CAST( SfxPrintingHint, &rHint );
765 if ( pPrintHint )
767 if ( pPrintHint->GetWhich() == -1 ) // -1 : Initialisation of PrintOptions
769 if ( !m_xPrintJob.is() )
770 m_xPrintJob = new SfxPrintJob_Impl( this );
772 PrintDialog* pDlg = pPrintHint->GetPrintDialog();
773 Printer* pPrinter = pPrintHint->GetPrinter();
774 ::rtl::OUString aPrintFile ( ( pPrinter && pPrinter->IsPrintFileEnabled() ) ? pPrinter->GetPrintFile() : String() );
775 ::rtl::OUString aRangeText ( ( pDlg && pDlg->IsRangeChecked(PRINTDIALOG_RANGE) ) ? pDlg->GetRangeText() : String() );
776 sal_Bool bSelectionOnly = ( ( pDlg && pDlg->IsRangeChecked(PRINTDIALOG_SELECTION) ) ? sal_True : sal_False );
778 sal_Int32 nArgs = 2;
779 if ( aPrintFile.getLength() )
780 nArgs++;
781 if ( aRangeText.getLength() )
782 nArgs++;
783 else if ( bSelectionOnly )
784 nArgs++;
786 m_aPrintOptions.realloc(nArgs);
787 m_aPrintOptions[0].Name = DEFINE_CONST_UNICODE("CopyCount");
788 m_aPrintOptions[0].Value <<= (sal_Int16) (pPrinter ? pPrinter->GetCopyCount() : 1 );
789 m_aPrintOptions[1].Name = DEFINE_CONST_UNICODE("Collate");
790 m_aPrintOptions[1].Value <<= (sal_Bool) (pDlg ? pDlg->IsCollateChecked() : sal_False );
792 if ( bSelectionOnly )
794 m_aPrintOptions[2].Name = DEFINE_CONST_UNICODE("Selection");
795 m_aPrintOptions[2].Value <<= bSelectionOnly;
797 else if ( aRangeText.getLength() )
799 m_aPrintOptions[2].Name = DEFINE_CONST_UNICODE("Pages");
800 m_aPrintOptions[2].Value <<= aRangeText;
803 if ( aPrintFile.getLength() )
805 m_aPrintOptions[nArgs-1].Name = DEFINE_CONST_UNICODE("FileName");
806 m_aPrintOptions[nArgs-1].Value <<= aPrintFile;
809 else if ( pPrintHint->GetWhich() == -3 ) // -3 : AdditionalPrintOptions
811 uno::Sequence < beans::PropertyValue >& lOldOpts = m_aPrintOptions;
812 const uno::Sequence < beans::PropertyValue >& lNewOpts = pPrintHint->GetAdditionalOptions();
813 sal_Int32 nOld = lOldOpts.getLength();
814 sal_Int32 nAdd = lNewOpts.getLength();
815 lOldOpts.realloc( nOld + nAdd );
817 // assume that all new elements are overwriting old ones and so don't need to be added
818 sal_Int32 nTotal = nOld;
819 for ( sal_Int32 n=0; n<nAdd; n++ )
821 sal_Int32 m;
822 for ( m=0; m<nOld; m++ )
823 if ( lNewOpts[n].Name == lOldOpts[m].Name )
824 // new option overwrites old one
825 break;
827 if ( m == nOld )
829 // this is a new option, so add it to the resulting sequence - counter must be incremented
830 lOldOpts[nTotal].Name = lNewOpts[n].Name;
831 lOldOpts[nTotal++].Value = lNewOpts[n].Value;
833 else
834 // overwrite old option with new value, counter stays unmodified
835 lOldOpts[m].Value = lNewOpts[n].Value;
838 if ( nTotal != lOldOpts.getLength() )
839 // at least one new options has overwritten an old one, so we allocated too much
840 lOldOpts.realloc( nTotal );
842 else if ( pPrintHint->GetWhich() != -2 ) // -2 : CancelPrintJob
844 view::PrintJobEvent aEvent;
845 aEvent.Source = m_xPrintJob;
846 aEvent.State = (com::sun::star::view::PrintableState) pPrintHint->GetWhich();
847 ::cppu::OInterfaceContainerHelper* pContainer = m_aInterfaceContainer.getContainer( ::getCppuType( ( const uno::Reference< view::XPrintJobListener >*) NULL ) );
848 if ( pContainer!=NULL )
850 ::cppu::OInterfaceIteratorHelper pIterator(*pContainer);
851 while (pIterator.hasMoreElements())
852 ((view::XPrintJobListener*)pIterator.next())->printJobEvent( aEvent );
859 void SAL_CALL SfxPrintHelper::addPrintJobListener( const ::com::sun::star::uno::Reference< ::com::sun::star::view::XPrintJobListener >& xListener ) throw (::com::sun::star::uno::RuntimeException)
861 ::vos::OGuard aGuard( Application::GetSolarMutex() );
862 m_pData->m_aInterfaceContainer.addInterface( ::getCppuType((const uno::Reference < view::XPrintJobListener>*)0), xListener );
865 void SAL_CALL SfxPrintHelper::removePrintJobListener( const ::com::sun::star::uno::Reference< ::com::sun::star::view::XPrintJobListener >& xListener ) throw (::com::sun::star::uno::RuntimeException)
867 ::vos::OGuard aGuard( Application::GetSolarMutex() );
868 m_pData->m_aInterfaceContainer.removeInterface( ::getCppuType((const uno::Reference < view::XPrintJobListener>*)0), xListener );