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 13894 : 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 6950 : IMPL_PrintListener_DataContainer( ::osl::Mutex& aMutex)
71 : : m_pObjectShell ( 0 )
72 6950 : , m_aInterfaceContainer ( aMutex )
73 : {
74 6950 : }
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 6950 : SfxPrintHelper::SfxPrintHelper()
147 : {
148 6950 : m_pData = new IMPL_PrintListener_DataContainer(m_aMutex);
149 6950 : }
150 :
151 6950 : 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 6950 : if ( aArguments.getLength() )
154 : {
155 6950 : com::sun::star::uno::Reference < com::sun::star::frame::XModel > xModel;
156 6950 : aArguments[0] >>= xModel;
157 13900 : uno::Reference < lang::XUnoTunnel > xObj( xModel, uno::UNO_QUERY );
158 13900 : uno::Sequence < sal_Int8 > aSeq( SvGlobalName( SFX_GLOBAL_CLASSID ).GetByteSequence() );
159 6950 : sal_Int64 nHandle = xObj->getSomething( aSeq );
160 6950 : if ( nHandle )
161 : {
162 6950 : m_pData->m_pObjectShell = reinterpret_cast< SfxObjectShell* >( sal::static_int_cast< sal_IntPtr >( nHandle ));
163 6950 : m_pData->StartListening(*m_pData->m_pObjectShell);
164 6950 : }
165 : }
166 6950 : }
167 :
168 20841 : SfxPrintHelper::~SfxPrintHelper()
169 : {
170 6947 : delete m_pData;
171 13894 : }
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 automatically 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 0 : osl_setThreadName("ImplUCBPrintWatcher");
498 :
499 : /* SAFE { */
500 : {
501 0 : SolarMutexGuard aGuard;
502 0 : while( m_pPrinter->IsPrinting() )
503 0 : Application::Yield();
504 0 : m_pPrinter = NULL; // don't delete it! It's borrowed only :-)
505 : }
506 : /* } SAFE */
507 :
508 : // lock for further using of our member isn't necessary - because
509 : // we truns alone by defenition. Nobody join for us nor use us ...
510 0 : moveAndDeleteTemp(&m_pTempFile,m_sTargetURL);
511 :
512 : // finishing of this run() method will call onTerminate() automatically
513 : // kill this thread there!
514 0 : }
515 :
516 : /* nobody wait for this thread. We must kill ourself ...
517 : */
518 0 : void SAL_CALL onTerminated() SAL_OVERRIDE
519 : {
520 0 : delete this;
521 0 : }
522 :
523 : /* static helper to move the temp. file to the target location by using the ucb
524 : It's static to be useable from outside too. So it's not really necessary to start
525 : the thread, if finishing of the job was detected outside this thread.
526 : But it must be called without using a corresponding thread for the given parameter!
527 : */
528 0 : static void moveAndDeleteTemp( ::utl::TempFile** ppTempFile, const OUString& sTargetURL )
529 : {
530 : // move the file
531 : try
532 : {
533 0 : INetURLObject aSplitter(sTargetURL);
534 : OUString sFileName = aSplitter.getName(
535 : INetURLObject::LAST_SEGMENT,
536 : true,
537 0 : INetURLObject::DECODE_WITH_CHARSET);
538 0 : if (aSplitter.removeSegment() && !sFileName.isEmpty())
539 : {
540 : ::ucbhelper::Content aSource(
541 : OUString((*ppTempFile)->GetURL()),
542 : ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >(),
543 0 : comphelper::getProcessComponentContext());
544 :
545 : ::ucbhelper::Content aTarget(
546 : OUString(aSplitter.GetMainURL(INetURLObject::NO_DECODE)),
547 : ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >(),
548 0 : comphelper::getProcessComponentContext());
549 :
550 : aTarget.transferContent(
551 : aSource,
552 : ::ucbhelper::InsertOperation_COPY,
553 : OUString(sFileName),
554 0 : ::com::sun::star::ucb::NameClash::OVERWRITE);
555 0 : }
556 : }
557 0 : catch (const ::com::sun::star::ucb::ContentCreationException&)
558 : {
559 : OSL_FAIL("content create exception");
560 : }
561 0 : catch (const ::com::sun::star::ucb::CommandAbortedException&)
562 : {
563 : OSL_FAIL("command abort exception");
564 : }
565 0 : catch (const ::com::sun::star::uno::RuntimeException&)
566 : {
567 : OSL_FAIL("runtime exception");
568 : }
569 0 : catch (const ::com::sun::star::uno::Exception&)
570 : {
571 : OSL_FAIL("unknown exception");
572 : }
573 :
574 : // kill the temp file!
575 0 : delete *ppTempFile;
576 0 : *ppTempFile = NULL;
577 0 : }
578 : };
579 :
580 :
581 :
582 :
583 : // XPrintable
584 :
585 0 : void SAL_CALL SfxPrintHelper::print(const uno::Sequence< beans::PropertyValue >& rOptions)
586 : throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException, std::exception)
587 : {
588 0 : if( Application::GetSettings().GetMiscSettings().GetDisablePrinting() )
589 0 : return;
590 :
591 : // object already disposed?
592 : // object already disposed?
593 0 : SolarMutexGuard aGuard;
594 :
595 : // get view for sfx printing capabilities
596 0 : SfxViewFrame *pViewFrm = m_pData->m_pObjectShell.Is() ?
597 0 : SfxViewFrame::GetFirst( m_pData->m_pObjectShell, false ) : 0;
598 0 : if ( !pViewFrm )
599 0 : return;
600 0 : SfxViewShell* pView = pViewFrm->GetViewShell();
601 0 : if ( !pView )
602 0 : return;
603 0 : bool bMonitor = false;
604 : // We need this information at the end of this method, if we start the vcl printer
605 : // by executing the slot. Because if it is a ucb relevant URL we must wait for
606 : // finishing the print job and move the temporary local file by using the ucb
607 : // to the right location. But in case of no file name is given or it is already
608 : // a local one we can suppress this special handling. Because then vcl makes all
609 : // right for us.
610 0 : OUString sUcbUrl;
611 0 : ::utl::TempFile* pUCBPrintTempFile = NULL;
612 :
613 0 : uno::Sequence < beans::PropertyValue > aCheckedArgs( rOptions.getLength() );
614 0 : sal_Int32 nProps = 0;
615 0 : bool bWaitUntilEnd = false;
616 0 : sal_Int16 nDuplexMode = ::com::sun::star::view::DuplexMode::UNKNOWN;
617 0 : for ( int n = 0; n < rOptions.getLength(); ++n )
618 : {
619 : // get Property-Value from options
620 0 : const beans::PropertyValue &rProp = rOptions.getConstArray()[n];
621 :
622 : // FileName-Property?
623 0 : if ( rProp.Name.equalsAscii( "FileName" ) )
624 : {
625 : // unpack th URL and check for a valid and well known protocol
626 0 : OUString sTemp;
627 0 : if (
628 0 : ( rProp.Value.getValueType()!=cppu::UnoType<OUString>::get()) ||
629 0 : (!(rProp.Value>>=sTemp))
630 : )
631 : {
632 0 : throw ::com::sun::star::lang::IllegalArgumentException();
633 : }
634 :
635 0 : OUString sPath ;
636 0 : OUString sURL (sTemp);
637 0 : INetURLObject aCheck(sURL );
638 0 : if (aCheck.GetProtocol()==INET_PROT_NOT_VALID)
639 : {
640 : // OK - it's not a valid URL. But may it's a simple
641 : // system path directly. It will be supported for historical
642 : // reasons. Otherwhise we break to much external code ...
643 : // We try to convert it to a file URL. If its possible
644 : // we put the system path to the item set and let vcl work with it.
645 : // No ucb or thread will be necessary then. In case it couldnt be
646 : // converted its not an URL nor a system path. Then we can't accept
647 : // this parameter and have to throw an exception.
648 0 : OUString sSystemPath(sTemp);
649 0 : OUString sFileURL;
650 0 : if (::osl::FileBase::getFileURLFromSystemPath(sSystemPath,sFileURL)!=::osl::FileBase::E_None)
651 0 : throw ::com::sun::star::lang::IllegalArgumentException();
652 0 : aCheckedArgs[nProps].Name = rProp.Name;
653 0 : aCheckedArgs[nProps++].Value <<= sFileURL;
654 : // and append the local filename
655 0 : aCheckedArgs.realloc( aCheckedArgs.getLength()+1 );
656 0 : aCheckedArgs[nProps].Name = "LocalFileName";
657 0 : aCheckedArgs[nProps++].Value <<= OUString( sTemp );
658 : }
659 : else
660 : // It's a valid URL. but now we must know, if it is a local one or not.
661 : // It's a question of using ucb or not!
662 0 : if (::utl::LocalFileHelper::ConvertURLToSystemPath(sURL,sPath))
663 : {
664 : // it's a local file, we can use vcl without special handling
665 : // And we have to use the system notation of the incoming URL.
666 : // But it into the descriptor and let the slot be executed at
667 : // the end of this method.
668 0 : aCheckedArgs[nProps].Name = rProp.Name;
669 0 : aCheckedArgs[nProps++].Value <<= sTemp;
670 : // and append the local filename
671 0 : aCheckedArgs.realloc( aCheckedArgs.getLength()+1 );
672 0 : aCheckedArgs[nProps].Name = "LocalFileName";
673 0 : aCheckedArgs[nProps++].Value <<= sPath;
674 : }
675 : else
676 : {
677 : // it's an ucb target. So we must use a temp. file for vcl
678 : // and move it after printing by using the ucb.
679 : // Create a temp file on the heap (because it must delete the
680 : // real file on disk automatically if it die - bt we have to share it with
681 : // some other sources ... e.g. the ImplUCBPrintWatcher).
682 : // And we put the name of this temp file to the descriptor instead
683 : // of the URL. The URL we save for later using separately.
684 : // Execution of the print job will be done later by executing
685 : // a slot ...
686 0 : if(!pUCBPrintTempFile)
687 0 : pUCBPrintTempFile = new ::utl::TempFile();
688 0 : pUCBPrintTempFile->EnableKillingFile();
689 :
690 : //FIXME: does it work?
691 0 : aCheckedArgs[nProps].Name = "LocalFileName";
692 0 : aCheckedArgs[nProps++].Value <<= OUString( pUCBPrintTempFile->GetFileName() );
693 0 : sUcbUrl = sURL;
694 0 : }
695 : }
696 :
697 : // CopyCount-Property
698 0 : else if ( rProp.Name.equalsAscii( "CopyCount" ) )
699 : {
700 0 : sal_Int32 nCopies = 0;
701 0 : if ( !( rProp.Value >>= nCopies ) )
702 0 : throw ::com::sun::star::lang::IllegalArgumentException();
703 :
704 0 : aCheckedArgs[nProps].Name = rProp.Name;
705 0 : aCheckedArgs[nProps++].Value <<= nCopies;
706 : }
707 :
708 : // Collate-Property
709 : // Sort-Property (deprecated)
710 0 : else if ( rProp.Name.equalsAscii( "Collate" ) ||
711 0 : rProp.Name.equalsAscii( "Sort" ) )
712 : {
713 : bool bTemp;
714 0 : if ( rProp.Value >>= bTemp )
715 : {
716 0 : aCheckedArgs[nProps].Name = "Collate";
717 0 : aCheckedArgs[nProps++].Value <<= bTemp;
718 : }
719 : else
720 0 : throw ::com::sun::star::lang::IllegalArgumentException();
721 : }
722 :
723 : // Pages-Property
724 0 : else if ( rProp.Name.equalsAscii( "Pages" ) )
725 : {
726 0 : OUString sTemp;
727 0 : if( rProp.Value >>= sTemp )
728 : {
729 0 : aCheckedArgs[nProps].Name = rProp.Name;
730 0 : aCheckedArgs[nProps++].Value <<= sTemp;
731 : }
732 : else
733 0 : throw ::com::sun::star::lang::IllegalArgumentException();
734 : }
735 :
736 : // MonitorVisible
737 0 : else if ( rProp.Name.equalsAscii( "MonitorVisible" ) )
738 : {
739 0 : if( !(rProp.Value >>= bMonitor) )
740 0 : throw ::com::sun::star::lang::IllegalArgumentException();
741 0 : aCheckedArgs[nProps].Name = rProp.Name;
742 0 : aCheckedArgs[nProps++].Value <<= bMonitor;
743 : }
744 :
745 : // Wait
746 0 : else if ( rProp.Name.equalsAscii( "Wait" ) )
747 : {
748 0 : if ( !(rProp.Value >>= bWaitUntilEnd) )
749 0 : throw ::com::sun::star::lang::IllegalArgumentException();
750 0 : aCheckedArgs[nProps].Name = rProp.Name;
751 0 : aCheckedArgs[nProps++].Value <<= bWaitUntilEnd;
752 : }
753 :
754 0 : else if ( rProp.Name.equalsAscii( "DuplexMode" ) )
755 : {
756 0 : if ( !(rProp.Value >>= nDuplexMode ) )
757 0 : throw ::com::sun::star::lang::IllegalArgumentException();
758 0 : aCheckedArgs[nProps].Name = rProp.Name;
759 0 : aCheckedArgs[nProps++].Value <<= nDuplexMode;
760 : }
761 : }
762 :
763 0 : if ( nProps != aCheckedArgs.getLength() )
764 0 : aCheckedArgs.realloc(nProps);
765 :
766 : // Execute the print request every time.
767 : // It doesn'tmatter if it is a real printer used or we print to a local file
768 : // nor if we print to a temp file and move it afterwards by using the ucb.
769 : // That will be handled later. see pUCBPrintFile below!
770 0 : pView->ExecPrint( aCheckedArgs, true, false );
771 :
772 : // Ok - may be execution before has finished (or started!) printing.
773 : // And may it was a printing to a file.
774 : // Now we have to check if we can move the file (if necessary) via ucb to his right location.
775 : // Cases:
776 : // a) printing finished => move the file directly and forget the watcher thread
777 : // b) printing is asynchron and runs currently => start watcher thread and exit this method
778 : // This thread make all necessary things by itself.
779 0 : if (pUCBPrintTempFile)
780 : {
781 : // a)
782 0 : SfxPrinter* pPrinter = pView->GetPrinter();
783 0 : if ( ! pPrinter->IsPrinting() )
784 0 : ImplUCBPrintWatcher::moveAndDeleteTemp(&pUCBPrintTempFile,sUcbUrl);
785 : // b)
786 : else
787 : {
788 : // Note: we create(d) some resource on the heap. (thread and tep file)
789 : // They will be deleted by the thread automatically if he finish his run() method.
790 0 : ImplUCBPrintWatcher* pWatcher = new ImplUCBPrintWatcher( pPrinter, pUCBPrintTempFile, sUcbUrl );
791 0 : pWatcher->create();
792 : }
793 0 : }
794 : }
795 :
796 303756 : void IMPL_PrintListener_DataContainer::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
797 : {
798 303756 : const SfxPrintingHint* pPrintHint = dynamic_cast<const SfxPrintingHint*>(&rHint);
799 607512 : if ( &rBC != m_pObjectShell
800 303756 : || !pPrintHint
801 303756 : || pPrintHint->GetWhich() == SFX_PRINTABLESTATE_CANCELJOB )
802 607512 : return;
803 :
804 0 : if ( pPrintHint->GetWhich() == com::sun::star::view::PrintableState_JOB_STARTED )
805 : {
806 0 : if ( !m_xPrintJob.is() )
807 0 : m_xPrintJob = new SfxPrintJob_Impl( this );
808 0 : m_aPrintOptions = pPrintHint->GetOptions();
809 : }
810 :
811 : ::cppu::OInterfaceContainerHelper* pContainer = m_aInterfaceContainer.getContainer(
812 0 : cppu::UnoType<view::XPrintJobListener>::get());
813 0 : if ( !pContainer )
814 0 : return;
815 :
816 0 : view::PrintJobEvent aEvent;
817 0 : aEvent.Source = m_xPrintJob;
818 0 : aEvent.State = (com::sun::star::view::PrintableState) pPrintHint->GetWhich();
819 :
820 0 : ::cppu::OInterfaceIteratorHelper pIterator(*pContainer);
821 0 : while (pIterator.hasMoreElements())
822 0 : static_cast<view::XPrintJobListener*>(pIterator.next())->printJobEvent( aEvent );
823 : }
824 :
825 6950 : 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)
826 : {
827 6950 : SolarMutexGuard aGuard;
828 6950 : m_pData->m_aInterfaceContainer.addInterface( cppu::UnoType<view::XPrintJobListener>::get(), xListener );
829 6950 : }
830 :
831 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)
832 : {
833 0 : SolarMutexGuard aGuard;
834 0 : m_pData->m_aInterfaceContainer.removeInterface( cppu::UnoType<view::XPrintJobListener>::get(), xListener );
835 951 : }
836 :
837 :
838 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|