Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 :
21 : #include "printhelper.hxx"
22 :
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/lang/XUnoTunnel.hpp>
30 : #include <com/sun/star/frame/XModel.hpp>
31 : #include <com/sun/star/lang/EventObject.hpp>
32 : #include <com/sun/star/view/DuplexMode.hpp>
33 : #include <comphelper/processfactory.hxx>
34 : #include <svl/lstner.hxx>
35 : #include <svl/stritem.hxx>
36 : #include <svl/intitem.hxx>
37 : #include <svl/eitem.hxx>
38 : #include <unotools/tempfile.hxx>
39 : #include <unotools/localfilehelper.hxx>
40 : #include <osl/file.hxx>
41 : #include <osl/thread.hxx>
42 : #include <tools/urlobj.hxx>
43 : #include <ucbhelper/content.hxx>
44 : #include <cppuhelper/interfacecontainer.hxx>
45 : #include <osl/mutex.hxx>
46 : #include <cppuhelper/implbase1.hxx>
47 :
48 : #include <sfx2/viewfrm.hxx>
49 : #include <sfx2/viewsh.hxx>
50 : #include <sfx2/dispatch.hxx>
51 : #include <sfx2/request.hxx>
52 : #include <sfx2/printer.hxx>
53 : #include <sfx2/app.hxx>
54 : #include <sfx2/objsh.hxx>
55 : #include <sfx2/event.hxx>
56 :
57 : using namespace ::com::sun::star;
58 : using namespace ::com::sun::star::uno;
59 :
60 530 : struct IMPL_PrintListener_DataContainer : public SfxListener
61 : {
62 : SfxObjectShellRef m_pObjectShell;
63 : ::cppu::OMultiTypeInterfaceContainerHelper m_aInterfaceContainer;
64 : uno::Reference< com::sun::star::view::XPrintJob> m_xPrintJob;
65 : ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > m_aPrintOptions;
66 :
67 501 : IMPL_PrintListener_DataContainer( ::osl::Mutex& aMutex)
68 : : m_pObjectShell ( 0 )
69 501 : , m_aInterfaceContainer ( aMutex )
70 : {
71 501 : }
72 :
73 :
74 : void Notify( SfxBroadcaster& aBC ,
75 : const SfxHint& aHint ) ;
76 : };
77 :
78 0 : awt::Size impl_Size_Object2Struct( const Size& aSize )
79 : {
80 0 : awt::Size aReturnValue;
81 0 : aReturnValue.Width = aSize.Width() ;
82 0 : aReturnValue.Height = aSize.Height() ;
83 0 : return aReturnValue ;
84 : }
85 :
86 0 : Size impl_Size_Struct2Object( const awt::Size& aSize )
87 : {
88 0 : Size aReturnValue;
89 0 : aReturnValue.Width() = aSize.Width ;
90 0 : aReturnValue.Height() = aSize.Height ;
91 0 : return aReturnValue ;
92 : }
93 :
94 0 : class SfxPrintJob_Impl : public cppu::WeakImplHelper1
95 : <
96 : com::sun::star::view::XPrintJob
97 : >
98 : {
99 : IMPL_PrintListener_DataContainer* m_pData;
100 :
101 : public:
102 : SfxPrintJob_Impl( IMPL_PrintListener_DataContainer* pData );
103 : virtual Sequence< ::com::sun::star::beans::PropertyValue > SAL_CALL getPrintOptions( ) throw (RuntimeException);
104 : virtual Sequence< ::com::sun::star::beans::PropertyValue > SAL_CALL getPrinter( ) throw (RuntimeException);
105 : virtual Reference< ::com::sun::star::view::XPrintable > SAL_CALL getPrintable( ) throw (RuntimeException);
106 : virtual void SAL_CALL cancelJob() throw (RuntimeException);
107 : };
108 :
109 0 : SfxPrintJob_Impl::SfxPrintJob_Impl( IMPL_PrintListener_DataContainer* pData )
110 0 : : m_pData( pData )
111 : {
112 0 : }
113 :
114 0 : Sequence< ::com::sun::star::beans::PropertyValue > SAL_CALL SfxPrintJob_Impl::getPrintOptions() throw (RuntimeException)
115 : {
116 0 : return m_pData->m_aPrintOptions;
117 : }
118 :
119 0 : Sequence< ::com::sun::star::beans::PropertyValue > SAL_CALL SfxPrintJob_Impl::getPrinter() throw (RuntimeException)
120 : {
121 0 : if( m_pData->m_pObjectShell.Is() )
122 : {
123 0 : Reference < view::XPrintable > xPrintable( m_pData->m_pObjectShell->GetModel(), UNO_QUERY );
124 0 : if ( xPrintable.is() )
125 0 : return xPrintable->getPrinter();
126 : }
127 0 : return Sequence< ::com::sun::star::beans::PropertyValue >();
128 : }
129 :
130 0 : Reference< ::com::sun::star::view::XPrintable > SAL_CALL SfxPrintJob_Impl::getPrintable() throw (RuntimeException)
131 : {
132 0 : Reference < view::XPrintable > xPrintable( m_pData->m_pObjectShell.Is() ? m_pData->m_pObjectShell->GetModel() : NULL, UNO_QUERY );
133 0 : return xPrintable;
134 : }
135 :
136 0 : void SAL_CALL SfxPrintJob_Impl::cancelJob() throw (RuntimeException)
137 : {
138 : // FIXME: how to cancel PrintJob via API?!
139 0 : if( m_pData->m_pObjectShell.Is() )
140 0 : m_pData->m_pObjectShell->Broadcast( SfxPrintingHint( -2 ) );
141 0 : }
142 :
143 501 : SfxPrintHelper::SfxPrintHelper()
144 : {
145 501 : m_pData = new IMPL_PrintListener_DataContainer(m_aMutex);
146 501 : }
147 :
148 501 : 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)
149 : {
150 501 : if ( aArguments.getLength() )
151 : {
152 501 : com::sun::star::uno::Reference < com::sun::star::frame::XModel > xModel;
153 501 : aArguments[0] >>= xModel;
154 501 : uno::Reference < lang::XUnoTunnel > xObj( xModel, uno::UNO_QUERY );
155 501 : uno::Sequence < sal_Int8 > aSeq( SvGlobalName( SFX_GLOBAL_CLASSID ).GetByteSequence() );
156 501 : sal_Int64 nHandle = xObj->getSomething( aSeq );
157 501 : if ( nHandle )
158 : {
159 501 : m_pData->m_pObjectShell = reinterpret_cast< SfxObjectShell* >( sal::static_int_cast< sal_IntPtr >( nHandle ));
160 501 : m_pData->StartListening(*m_pData->m_pObjectShell);
161 501 : }
162 : }
163 501 : }
164 :
165 795 : SfxPrintHelper::~SfxPrintHelper()
166 : {
167 265 : delete m_pData;
168 530 : }
169 :
170 : namespace
171 : {
172 0 : view::PaperFormat convertToPaperFormat(Paper eFormat)
173 : {
174 : view::PaperFormat eRet;
175 0 : switch (eFormat)
176 : {
177 : case PAPER_A3:
178 0 : eRet = view::PaperFormat_A3;
179 0 : break;
180 : case PAPER_A4:
181 0 : eRet = view::PaperFormat_A4;
182 0 : break;
183 : case PAPER_A5:
184 0 : eRet = view::PaperFormat_A5;
185 0 : break;
186 : case PAPER_B4_ISO:
187 0 : eRet = view::PaperFormat_B4;
188 0 : break;
189 : case PAPER_B5_ISO:
190 0 : eRet = view::PaperFormat_B5;
191 0 : break;
192 : case PAPER_LETTER:
193 0 : eRet = view::PaperFormat_LETTER;
194 0 : break;
195 : case PAPER_LEGAL:
196 0 : eRet = view::PaperFormat_LEGAL;
197 0 : break;
198 : case PAPER_TABLOID:
199 0 : eRet = view::PaperFormat_TABLOID;
200 0 : break;
201 : case PAPER_USER:
202 : default:
203 0 : eRet = view::PaperFormat_USER;
204 0 : break;
205 : }
206 0 : return eRet;
207 : }
208 :
209 0 : Paper convertToPaper(view::PaperFormat eFormat)
210 : {
211 0 : Paper eRet(PAPER_USER);
212 0 : switch (eFormat)
213 : {
214 : case view::PaperFormat_A3:
215 0 : eRet = PAPER_A3;
216 0 : break;
217 : case view::PaperFormat_A4:
218 0 : eRet = PAPER_A4;
219 0 : break;
220 : case view::PaperFormat_A5:
221 0 : eRet = PAPER_A5;
222 0 : break;
223 : case view::PaperFormat_B4:
224 0 : eRet = PAPER_B4_ISO;
225 0 : break;
226 : case view::PaperFormat_B5:
227 0 : eRet = PAPER_B5_ISO;
228 0 : break;
229 : case view::PaperFormat_LETTER:
230 0 : eRet = PAPER_LETTER;
231 0 : break;
232 : case view::PaperFormat_LEGAL:
233 0 : eRet = PAPER_LEGAL;
234 0 : break;
235 : case view::PaperFormat_TABLOID:
236 0 : eRet = PAPER_TABLOID;
237 0 : break;
238 : case view::PaperFormat_USER:
239 0 : eRet = PAPER_USER;
240 0 : break;
241 : case view::PaperFormat_MAKE_FIXED_SIZE:
242 0 : break;
243 : //deliberate no default to force warn on a new papersize
244 : }
245 0 : return eRet;
246 : }
247 : }
248 :
249 : //________________________________________________________________________________________________________
250 : // XPrintable
251 : //________________________________________________________________________________________________________
252 :
253 0 : uno::Sequence< beans::PropertyValue > SAL_CALL SfxPrintHelper::getPrinter() throw(::com::sun::star::uno::RuntimeException)
254 : {
255 : // object already disposed?
256 0 : SolarMutexGuard aGuard;
257 :
258 : // search for any view of this document that is currently printing
259 0 : const Printer *pPrinter = NULL;
260 0 : SfxViewFrame *pViewFrm = m_pData->m_pObjectShell.Is() ? SfxViewFrame::GetFirst( m_pData->m_pObjectShell, sal_False ) : 0;
261 0 : SfxViewFrame* pFirst = pViewFrm;
262 0 : while ( pViewFrm && !pPrinter )
263 : {
264 0 : pPrinter = pViewFrm->GetViewShell()->GetActivePrinter();
265 0 : pViewFrm = SfxViewFrame::GetNext( *pViewFrm, m_pData->m_pObjectShell, sal_False );
266 : }
267 :
268 : // if no view is printing currently, use the permanent SfxPrinter instance
269 0 : if ( !pPrinter && pFirst )
270 0 : pPrinter = pFirst->GetViewShell()->GetPrinter(sal_True);
271 :
272 0 : if ( !pPrinter )
273 0 : return uno::Sequence< beans::PropertyValue >();
274 :
275 0 : uno::Sequence< beans::PropertyValue > aPrinter(8);
276 :
277 0 : aPrinter.getArray()[7].Name = DEFINE_CONST_UNICODE( "CanSetPaperSize" );
278 0 : aPrinter.getArray()[7].Value <<= ( pPrinter->HasSupport( SUPPORT_SET_PAPERSIZE ) );
279 :
280 0 : aPrinter.getArray()[6].Name = DEFINE_CONST_UNICODE( "CanSetPaperFormat" );
281 0 : aPrinter.getArray()[6].Value <<= ( pPrinter->HasSupport( SUPPORT_SET_PAPER ) );
282 :
283 0 : aPrinter.getArray()[5].Name = DEFINE_CONST_UNICODE( "CanSetPaperOrientation" );
284 0 : aPrinter.getArray()[5].Value <<= ( pPrinter->HasSupport( SUPPORT_SET_ORIENTATION ) );
285 :
286 0 : aPrinter.getArray()[4].Name = DEFINE_CONST_UNICODE( "IsBusy" );
287 0 : aPrinter.getArray()[4].Value <<= ( pPrinter->IsPrinting() );
288 :
289 0 : aPrinter.getArray()[3].Name = DEFINE_CONST_UNICODE( "PaperSize" );
290 0 : awt::Size aSize = impl_Size_Object2Struct(pPrinter->GetPaperSize() );
291 0 : aPrinter.getArray()[3].Value <<= aSize;
292 :
293 0 : aPrinter.getArray()[2].Name = DEFINE_CONST_UNICODE( "PaperFormat" );
294 0 : view::PaperFormat eFormat = convertToPaperFormat(pPrinter->GetPaper());
295 0 : aPrinter.getArray()[2].Value <<= eFormat;
296 :
297 0 : aPrinter.getArray()[1].Name = DEFINE_CONST_UNICODE( "PaperOrientation" );
298 0 : view::PaperOrientation eOrient = (view::PaperOrientation)pPrinter->GetOrientation();
299 0 : aPrinter.getArray()[1].Value <<= eOrient;
300 :
301 0 : aPrinter.getArray()[0].Name = DEFINE_CONST_UNICODE( "Name" );
302 0 : String sStringTemp = pPrinter->GetName() ;
303 0 : aPrinter.getArray()[0].Value <<= ::rtl::OUString( sStringTemp );
304 :
305 0 : return aPrinter;
306 : }
307 :
308 : //________________________________________________________________________________________________________
309 : // XPrintable
310 : //________________________________________________________________________________________________________
311 :
312 0 : void SfxPrintHelper::impl_setPrinter(const uno::Sequence< beans::PropertyValue >& rPrinter,SfxPrinter*& pPrinter,sal_uInt16& nChangeFlags,SfxViewShell*& pViewSh)
313 :
314 : {
315 : // Get old Printer
316 0 : SfxViewFrame *pViewFrm = m_pData->m_pObjectShell.Is() ?
317 0 : SfxViewFrame::GetFirst( m_pData->m_pObjectShell, sal_False ) : 0;
318 0 : if ( !pViewFrm )
319 : return;
320 :
321 0 : pViewSh = pViewFrm->GetViewShell();
322 0 : pPrinter = pViewSh->GetPrinter(sal_True);
323 0 : if ( !pPrinter )
324 : return;
325 :
326 : // new Printer-Name available?
327 0 : nChangeFlags = 0;
328 0 : sal_Int32 lDummy = 0;
329 0 : for ( int n = 0; n < rPrinter.getLength(); ++n )
330 : {
331 : // get Property-Value from printer description
332 0 : const beans::PropertyValue &rProp = rPrinter.getConstArray()[n];
333 :
334 : // Name-Property?
335 0 : if ( rProp.Name.compareToAscii( "Name" ) == 0 )
336 : {
337 0 : ::rtl::OUString aPrinterName;
338 0 : if ( ! ( rProp.Value >>= aPrinterName ) )
339 0 : throw ::com::sun::star::lang::IllegalArgumentException();
340 :
341 0 : if ( aPrinterName != pPrinter->GetName() )
342 : {
343 0 : pPrinter = new SfxPrinter( pPrinter->GetOptions().Clone(), aPrinterName );
344 0 : nChangeFlags = SFX_PRINTER_PRINTER;
345 : }
346 0 : break;
347 : }
348 : }
349 :
350 0 : Size aSetPaperSize( 0, 0);
351 0 : view::PaperFormat nPaperFormat = view::PaperFormat_USER;
352 :
353 : // other properties
354 0 : for ( int i = 0; i < rPrinter.getLength(); ++i )
355 : {
356 : // get Property-Value from printer description
357 0 : const beans::PropertyValue &rProp = rPrinter.getConstArray()[i];
358 :
359 : // PaperOrientation-Property?
360 0 : if ( rProp.Name.compareToAscii( "PaperOrientation" ) == 0 )
361 : {
362 : view::PaperOrientation eOrient;
363 0 : if ( ( rProp.Value >>= eOrient ) == sal_False )
364 : {
365 0 : if ( ( rProp.Value >>= lDummy ) == sal_False )
366 0 : throw ::com::sun::star::lang::IllegalArgumentException();
367 0 : eOrient = ( view::PaperOrientation) lDummy;
368 : }
369 :
370 0 : if ( (Orientation) eOrient != pPrinter->GetOrientation() )
371 : {
372 0 : pPrinter->SetOrientation( (Orientation) eOrient );
373 0 : nChangeFlags |= SFX_PRINTER_CHG_ORIENTATION;
374 : }
375 : }
376 :
377 : // PaperFormat-Property?
378 0 : else if ( rProp.Name.compareToAscii( "PaperFormat" ) == 0 )
379 : {
380 0 : if ( ( rProp.Value >>= nPaperFormat ) == sal_False )
381 : {
382 0 : if ( ( rProp.Value >>= lDummy ) == sal_False )
383 0 : throw ::com::sun::star::lang::IllegalArgumentException();
384 0 : nPaperFormat = ( view::PaperFormat ) lDummy;
385 : }
386 :
387 0 : if ( convertToPaper(nPaperFormat) != pPrinter->GetPaper() )
388 : {
389 0 : pPrinter->SetPaper( convertToPaper(nPaperFormat) );
390 0 : nChangeFlags |= SFX_PRINTER_CHG_SIZE;
391 : }
392 : }
393 :
394 : // PaperSize-Property?
395 0 : else if ( rProp.Name.compareToAscii( "PaperSize" ) == 0 )
396 : {
397 0 : awt::Size aTempSize ;
398 0 : if ( ( rProp.Value >>= aTempSize ) == sal_False )
399 : {
400 0 : throw ::com::sun::star::lang::IllegalArgumentException();
401 : }
402 : else
403 : {
404 0 : aSetPaperSize = impl_Size_Struct2Object(aTempSize);
405 : }
406 : }
407 :
408 : // PrinterTray-Property
409 0 : else if ( rProp.Name.compareToAscii( "PrinterPaperTray" ) == 0 )
410 : {
411 0 : rtl::OUString aTmp;
412 0 : if ( ( rProp.Value >>= aTmp ) == sal_False )
413 0 : throw ::com::sun::star::lang::IllegalArgumentException();
414 0 : sal_uInt16 nCount = pPrinter->GetPaperBinCount();
415 0 : for (sal_uInt16 nBin=0; nBin<nCount; nBin++)
416 : {
417 0 : ::rtl::OUString aName( pPrinter->GetPaperBinName(nBin) );
418 0 : if ( aName == aTmp )
419 : {
420 0 : pPrinter->SetPaperBin(nBin);
421 : break;
422 : }
423 0 : }
424 : }
425 : }
426 :
427 : // The PaperSize may be set only when actually PAPER_USER
428 : // applies, otherwise the driver could choose a invalid format.
429 0 : if(nPaperFormat == view::PaperFormat_USER && aSetPaperSize.Width())
430 : {
431 : // Bug 56929 - MapMode of 100mm which recalculated when
432 : // the device is set. Additionally only set if they were really changed.
433 0 : aSetPaperSize = pPrinter->LogicToPixel( aSetPaperSize, MAP_100TH_MM );
434 0 : if( aSetPaperSize != pPrinter->GetPaperSizePixel() )
435 : {
436 0 : pPrinter->SetPaperSizeUser( pPrinter->PixelToLogic( aSetPaperSize ) );
437 0 : nChangeFlags |= SFX_PRINTER_CHG_SIZE;
438 : }
439 : }
440 :
441 : //wait until printing is done
442 0 : SfxPrinter* pDocPrinter = pViewSh->GetPrinter();
443 0 : while ( pDocPrinter->IsPrinting() )
444 0 : Application::Yield();
445 : }
446 :
447 0 : void SAL_CALL SfxPrintHelper::setPrinter(const uno::Sequence< beans::PropertyValue >& rPrinter)
448 : throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException)
449 : {
450 : // object already disposed?
451 0 : SolarMutexGuard aGuard;
452 :
453 0 : SfxViewShell* pViewSh = NULL;
454 0 : SfxPrinter* pPrinter = NULL;
455 0 : sal_uInt16 nChangeFlags = 0;
456 0 : impl_setPrinter(rPrinter,pPrinter,nChangeFlags,pViewSh);
457 : // set new printer
458 0 : if ( pViewSh && pPrinter )
459 0 : pViewSh->SetPrinter( pPrinter, nChangeFlags, false );
460 0 : }
461 :
462 : //________________________________________________________________________________________________________
463 : // ImplPrintWatch thread for asynchronous printing with moving temp. file to ucb location
464 : //________________________________________________________________________________________________________
465 :
466 : /* This implements a thread which will be started to wait for asynchronous
467 : print jobs to temp. localy files. If they finish we move the temp. files
468 : to her right locations by using the ucb.
469 : */
470 0 : class ImplUCBPrintWatcher : public ::osl::Thread
471 : {
472 : private:
473 : /// of course we must know the printer which execute the job
474 : SfxPrinter* m_pPrinter;
475 : /// this describes the target location for the printed temp file
476 : String m_sTargetURL;
477 : /// it holds the temp file alive, till the print job will finish and remove it from disk automaticly if the object die
478 : ::utl::TempFile* m_pTempFile;
479 :
480 : public:
481 : /* initialize this watcher but don't start it */
482 0 : ImplUCBPrintWatcher( SfxPrinter* pPrinter, ::utl::TempFile* pTempFile, const String& sTargetURL )
483 : : m_pPrinter ( pPrinter )
484 : , m_sTargetURL( sTargetURL )
485 0 : , m_pTempFile ( pTempFile )
486 0 : {}
487 :
488 : /* waits for finishing of the print job and moves the temp file afterwards
489 : Note: Starting of the job is done outside this thread!
490 : But we have to free some of the given resources on heap!
491 : */
492 0 : void SAL_CALL run()
493 : {
494 : /* SAFE { */
495 : {
496 0 : SolarMutexGuard aGuard;
497 0 : while( m_pPrinter->IsPrinting() )
498 0 : Application::Yield();
499 0 : m_pPrinter = NULL; // don't delete it! It's borrowed only :-)
500 : }
501 : /* } SAFE */
502 :
503 : // lock for further using of our member isn't neccessary - because
504 : // we truns alone by defenition. Nobody join for us nor use us ...
505 0 : moveAndDeleteTemp(&m_pTempFile,m_sTargetURL);
506 :
507 : // finishing of this run() method will call onTerminate() automaticly
508 : // kill this thread there!
509 0 : }
510 :
511 : /* nobody wait for this thread. We must kill ourself ...
512 : */
513 0 : void SAL_CALL onTerminated()
514 : {
515 0 : delete this;
516 0 : }
517 :
518 : /* static helper to move the temp. file to the target location by using the ucb
519 : It's static to be useable from outside too. So it's not realy neccessary to start
520 : the thread, if finishing of the job was detected outside this thread.
521 : But it must be called without using a corresponding thread for the given parameter!
522 : */
523 0 : static void moveAndDeleteTemp( ::utl::TempFile** ppTempFile, const String& sTargetURL )
524 : {
525 : // move the file
526 : try
527 : {
528 0 : INetURLObject aSplitter(sTargetURL);
529 : String sFileName = aSplitter.getName(
530 : INetURLObject::LAST_SEGMENT,
531 : true,
532 0 : INetURLObject::DECODE_WITH_CHARSET);
533 0 : if (aSplitter.removeSegment() && sFileName.Len()>0)
534 : {
535 : ::ucbhelper::Content aSource(
536 : ::rtl::OUString((*ppTempFile)->GetURL()),
537 : ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >(),
538 0 : comphelper::getProcessComponentContext());
539 :
540 : ::ucbhelper::Content aTarget(
541 : ::rtl::OUString(aSplitter.GetMainURL(INetURLObject::NO_DECODE)),
542 : ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >(),
543 0 : comphelper::getProcessComponentContext());
544 :
545 : aTarget.transferContent(
546 : aSource,
547 : ::ucbhelper::InsertOperation_COPY,
548 : ::rtl::OUString(sFileName),
549 0 : ::com::sun::star::ucb::NameClash::OVERWRITE);
550 0 : }
551 : }
552 0 : catch (const ::com::sun::star::ucb::ContentCreationException&)
553 : {
554 : OSL_FAIL("content create exception");
555 : }
556 0 : catch (const ::com::sun::star::ucb::CommandAbortedException&)
557 : {
558 : OSL_FAIL("command abort exception");
559 : }
560 0 : catch (const ::com::sun::star::uno::RuntimeException&)
561 : {
562 : OSL_FAIL("runtime exception");
563 : }
564 0 : catch (const ::com::sun::star::uno::Exception&)
565 : {
566 : OSL_FAIL("unknown exception");
567 : }
568 :
569 : // kill the temp file!
570 0 : delete *ppTempFile;
571 0 : *ppTempFile = NULL;
572 0 : }
573 : };
574 :
575 : //------------------------------------------------
576 :
577 : //________________________________________________________________________________________________________
578 : // XPrintable
579 : //________________________________________________________________________________________________________
580 0 : void SAL_CALL SfxPrintHelper::print(const uno::Sequence< beans::PropertyValue >& rOptions)
581 : throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException)
582 : {
583 0 : if( Application::GetSettings().GetMiscSettings().GetDisablePrinting() )
584 : return;
585 :
586 : // object already disposed?
587 : // object already disposed?
588 0 : SolarMutexGuard aGuard;
589 :
590 : // get view for sfx printing capabilities
591 0 : SfxViewFrame *pViewFrm = m_pData->m_pObjectShell.Is() ?
592 0 : SfxViewFrame::GetFirst( m_pData->m_pObjectShell, sal_False ) : 0;
593 0 : if ( !pViewFrm )
594 : return;
595 0 : SfxViewShell* pView = pViewFrm->GetViewShell();
596 0 : if ( !pView )
597 : return;
598 0 : sal_Bool bMonitor = sal_False;
599 : // We need this information at the end of this method, if we start the vcl printer
600 : // by executing the slot. Because if it is a ucb relevant URL we must wait for
601 : // finishing the print job and move the temporary local file by using the ucb
602 : // to the right location. But in case of no file name is given or it is already
603 : // a local one we can supress this special handling. Because then vcl makes all
604 : // right for us.
605 0 : String sUcbUrl;
606 0 : ::utl::TempFile* pUCBPrintTempFile = NULL;
607 :
608 0 : uno::Sequence < beans::PropertyValue > aCheckedArgs( rOptions.getLength() );
609 0 : sal_Int32 nProps = 0;
610 0 : sal_Bool bWaitUntilEnd = sal_False;
611 0 : sal_Int16 nDuplexMode = ::com::sun::star::view::DuplexMode::UNKNOWN;
612 0 : for ( int n = 0; n < rOptions.getLength(); ++n )
613 : {
614 : // get Property-Value from options
615 0 : const beans::PropertyValue &rProp = rOptions.getConstArray()[n];
616 :
617 : // FileName-Property?
618 0 : if ( rProp.Name.compareToAscii( "FileName" ) == 0 )
619 : {
620 : // unpack th URL and check for a valid and well known protocol
621 0 : ::rtl::OUString sTemp;
622 0 : if (
623 0 : ( rProp.Value.getValueType()!=::getCppuType((const ::rtl::OUString*)0)) ||
624 0 : (!(rProp.Value>>=sTemp))
625 : )
626 : {
627 0 : throw ::com::sun::star::lang::IllegalArgumentException();
628 : }
629 :
630 0 : String sPath ;
631 0 : String sURL (sTemp);
632 0 : INetURLObject aCheck(sURL );
633 0 : if (aCheck.GetProtocol()==INET_PROT_NOT_VALID)
634 : {
635 : // OK - it's not a valid URL. But may it's a simple
636 : // system path directly. It will be supported for historical
637 : // reasons. Otherwhise we break to much external code ...
638 : // We try to convert it to a file URL. If its possible
639 : // we put the system path to the item set and let vcl work with it.
640 : // No ucb or thread will be neccessary then. In case it couldnt be
641 : // converted its not an URL nor a system path. Then we can't accept
642 : // this parameter and have to throw an exception.
643 0 : ::rtl::OUString sSystemPath(sTemp);
644 0 : ::rtl::OUString sFileURL;
645 0 : if (::osl::FileBase::getFileURLFromSystemPath(sSystemPath,sFileURL)!=::osl::FileBase::E_None)
646 0 : throw ::com::sun::star::lang::IllegalArgumentException();
647 0 : aCheckedArgs[nProps].Name = rProp.Name;
648 0 : aCheckedArgs[nProps++].Value <<= sFileURL;
649 : // and append the local filename
650 0 : aCheckedArgs.realloc( aCheckedArgs.getLength()+1 );
651 0 : aCheckedArgs[nProps].Name = rtl::OUString("LocalFileName");
652 0 : aCheckedArgs[nProps++].Value <<= ::rtl::OUString( sTemp );
653 : }
654 : else
655 : // It's a valid URL. but now we must know, if it is a local one or not.
656 : // It's a question of using ucb or not!
657 0 : if (::utl::LocalFileHelper::ConvertURLToSystemPath(sURL,sPath))
658 : {
659 : // it's a local file, we can use vcl without special handling
660 : // And we have to use the system notation of the incoming URL.
661 : // But it into the descriptor and let the slot be executed at
662 : // the end of this method.
663 0 : aCheckedArgs[nProps].Name = rProp.Name;
664 0 : aCheckedArgs[nProps++].Value <<= sTemp;
665 : // and append the local filename
666 0 : aCheckedArgs.realloc( aCheckedArgs.getLength()+1 );
667 0 : aCheckedArgs[nProps].Name = rtl::OUString("LocalFileName");
668 0 : aCheckedArgs[nProps++].Value <<= ::rtl::OUString( sPath );
669 : }
670 : else
671 : {
672 : // it's an ucb target. So we must use a temp. file for vcl
673 : // and move it after printing by using the ucb.
674 : // Create a temp file on the heap (because it must delete the
675 : // real file on disk automaticly if it die - bt we have to share it with
676 : // some other sources ... e.g. the ImplUCBPrintWatcher).
677 : // And we put the name of this temp file to the descriptor instead
678 : // of the URL. The URL we save for later using seperatly.
679 : // Execution of the print job will be done later by executing
680 : // a slot ...
681 0 : pUCBPrintTempFile = new ::utl::TempFile();
682 0 : pUCBPrintTempFile->EnableKillingFile();
683 :
684 : //FIXME: does it work?
685 0 : aCheckedArgs[nProps].Name = rtl::OUString("LocalFileName");
686 0 : aCheckedArgs[nProps++].Value <<= ::rtl::OUString( pUCBPrintTempFile->GetFileName() );
687 0 : sUcbUrl = sURL;
688 0 : }
689 : }
690 :
691 : // CopyCount-Property
692 0 : else if ( rProp.Name.compareToAscii( "CopyCount" ) == 0 )
693 : {
694 0 : sal_Int32 nCopies = 0;
695 0 : if ( ( rProp.Value >>= nCopies ) == sal_False )
696 0 : throw ::com::sun::star::lang::IllegalArgumentException();
697 :
698 0 : aCheckedArgs[nProps].Name = rProp.Name;
699 0 : aCheckedArgs[nProps++].Value <<= nCopies;
700 : }
701 :
702 : // Collate-Property
703 : // Sort-Property (deprecated)
704 0 : else if ( rProp.Name.compareToAscii( "Collate" ) == 0 ||
705 0 : ( rProp.Name.compareToAscii( "Sort" ) == 0 ) )
706 : {
707 0 : sal_Bool bTemp = sal_Bool();
708 0 : if ( rProp.Value >>= bTemp )
709 : {
710 0 : aCheckedArgs[nProps].Name = rtl::OUString("Collate");
711 0 : aCheckedArgs[nProps++].Value <<= bTemp;
712 : }
713 : else
714 0 : throw ::com::sun::star::lang::IllegalArgumentException();
715 : }
716 :
717 : // Pages-Property
718 0 : else if ( rProp.Name.compareToAscii( "Pages" ) == 0 )
719 : {
720 0 : ::rtl::OUString sTemp;
721 0 : if( rProp.Value >>= sTemp )
722 : {
723 0 : aCheckedArgs[nProps].Name = rProp.Name;
724 0 : aCheckedArgs[nProps++].Value <<= sTemp;
725 : }
726 : else
727 0 : throw ::com::sun::star::lang::IllegalArgumentException();
728 : }
729 :
730 : // MonitorVisible
731 0 : else if ( rProp.Name.compareToAscii( "MonitorVisible" ) == 0 )
732 : {
733 0 : if( !(rProp.Value >>= bMonitor) )
734 0 : throw ::com::sun::star::lang::IllegalArgumentException();
735 0 : aCheckedArgs[nProps].Name = rProp.Name;
736 0 : aCheckedArgs[nProps++].Value <<= bMonitor;
737 : }
738 :
739 : // Wait
740 0 : else if ( rProp.Name.compareToAscii( "Wait" ) == 0 )
741 : {
742 0 : if ( !(rProp.Value >>= bWaitUntilEnd) )
743 0 : throw ::com::sun::star::lang::IllegalArgumentException();
744 0 : aCheckedArgs[nProps].Name = rProp.Name;
745 0 : aCheckedArgs[nProps++].Value <<= bWaitUntilEnd;
746 : }
747 :
748 0 : else if ( rProp.Name.compareToAscii( "DuplexMode" ) == 0 )
749 : {
750 0 : if ( !(rProp.Value >>= nDuplexMode ) )
751 0 : throw ::com::sun::star::lang::IllegalArgumentException();
752 0 : aCheckedArgs[nProps].Name = rProp.Name;
753 0 : aCheckedArgs[nProps++].Value <<= nDuplexMode;
754 : }
755 : }
756 :
757 0 : if ( nProps != aCheckedArgs.getLength() )
758 0 : aCheckedArgs.realloc(nProps);
759 :
760 : // Execute the print request every time.
761 : // It doesn'tmatter if it is a real printer used or we print to a local file
762 : // nor if we print to a temp file and move it afterwards by using the ucb.
763 : // That will be handled later. see pUCBPrintFile below!
764 0 : pView->ExecPrint( aCheckedArgs, sal_True, sal_False );
765 :
766 : // Ok - may be execution before has finished (or started!) printing.
767 : // And may it was a printing to a file.
768 : // Now we have to check if we can move the file (if neccessary) via ucb to his right location.
769 : // Cases:
770 : // a) printing finished => move the file directly and forget the watcher thread
771 : // b) printing is asynchron and runs currently => start watcher thread and exit this method
772 : // This thread make all neccessary things by itself.
773 0 : if (pUCBPrintTempFile!=NULL)
774 : {
775 : // a)
776 0 : SfxPrinter* pPrinter = pView->GetPrinter();
777 0 : if ( ! pPrinter->IsPrinting() )
778 0 : ImplUCBPrintWatcher::moveAndDeleteTemp(&pUCBPrintTempFile,sUcbUrl);
779 : // b)
780 : else
781 : {
782 : // Note: we create(d) some resource on the heap. (thread and tep file)
783 : // They will be delected by the thread automaticly if he finish his run() method.
784 0 : ImplUCBPrintWatcher* pWatcher = new ImplUCBPrintWatcher( pPrinter, pUCBPrintTempFile, sUcbUrl );
785 0 : pWatcher->create();
786 : }
787 0 : }
788 : }
789 :
790 10017 : void IMPL_PrintListener_DataContainer::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
791 : {
792 10017 : if ( &rBC == m_pObjectShell )
793 : {
794 10017 : SfxPrintingHint* pPrintHint = PTR_CAST( SfxPrintingHint, &rHint );
795 10017 : if ( pPrintHint )
796 : {
797 0 : if ( pPrintHint->GetWhich() == com::sun::star::view::PrintableState_JOB_STARTED )
798 : {
799 0 : if ( !m_xPrintJob.is() )
800 0 : m_xPrintJob = new SfxPrintJob_Impl( this );
801 0 : m_aPrintOptions = pPrintHint->GetOptions();
802 : }
803 0 : else if ( pPrintHint->GetWhich() != -2 ) // -2 : CancelPrintJob
804 : {
805 0 : view::PrintJobEvent aEvent;
806 0 : aEvent.Source = m_xPrintJob;
807 0 : aEvent.State = (com::sun::star::view::PrintableState) pPrintHint->GetWhich();
808 0 : ::cppu::OInterfaceContainerHelper* pContainer = m_aInterfaceContainer.getContainer( ::getCppuType( ( const uno::Reference< view::XPrintJobListener >*) NULL ) );
809 0 : if ( pContainer!=NULL )
810 : {
811 0 : ::cppu::OInterfaceIteratorHelper pIterator(*pContainer);
812 0 : while (pIterator.hasMoreElements())
813 0 : ((view::XPrintJobListener*)pIterator.next())->printJobEvent( aEvent );
814 0 : }
815 : }
816 : }
817 : }
818 10017 : }
819 :
820 501 : void SAL_CALL SfxPrintHelper::addPrintJobListener( const ::com::sun::star::uno::Reference< ::com::sun::star::view::XPrintJobListener >& xListener ) throw (::com::sun::star::uno::RuntimeException)
821 : {
822 501 : SolarMutexGuard aGuard;
823 501 : m_pData->m_aInterfaceContainer.addInterface( ::getCppuType((const uno::Reference < view::XPrintJobListener>*)0), xListener );
824 501 : }
825 :
826 0 : void SAL_CALL SfxPrintHelper::removePrintJobListener( const ::com::sun::star::uno::Reference< ::com::sun::star::view::XPrintJobListener >& xListener ) throw (::com::sun::star::uno::RuntimeException)
827 : {
828 0 : SolarMutexGuard aGuard;
829 0 : m_pData->m_aInterfaceContainer.removeInterface( ::getCppuType((const uno::Reference < view::XPrintJobListener>*)0), xListener );
830 0 : }
831 :
832 :
833 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|