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