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 8192 : 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 4114 : explicit IMPL_PrintListener_DataContainer( ::osl::Mutex& aMutex)
71 : : m_pObjectShell ( 0 )
72 4114 : , m_aInterfaceContainer ( aMutex )
73 : {
74 4114 : }
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 : explicit 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 4114 : SfxPrintHelper::SfxPrintHelper()
147 : {
148 4114 : m_pData = new IMPL_PrintListener_DataContainer(m_aMutex);
149 4114 : }
150 :
151 4114 : 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 4114 : if ( aArguments.getLength() )
154 : {
155 4114 : com::sun::star::uno::Reference < com::sun::star::frame::XModel > xModel;
156 4114 : aArguments[0] >>= xModel;
157 8228 : uno::Reference < lang::XUnoTunnel > xObj( xModel, uno::UNO_QUERY );
158 8228 : uno::Sequence < sal_Int8 > aSeq( SvGlobalName( SFX_GLOBAL_CLASSID ).GetByteSequence() );
159 4114 : sal_Int64 nHandle = xObj->getSomething( aSeq );
160 4114 : if ( nHandle )
161 : {
162 4114 : m_pData->m_pObjectShell = reinterpret_cast< SfxObjectShell* >( sal::static_int_cast< sal_IntPtr >( nHandle ));
163 4114 : m_pData->StartListening(*m_pData->m_pObjectShell);
164 4114 : }
165 : }
166 4114 : }
167 :
168 12288 : SfxPrintHelper::~SfxPrintHelper()
169 : {
170 4096 : delete m_pData;
171 8192 : }
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,
316 : SfxPrinter*& pPrinter,
317 : SfxPrinterChangeFlags& nChangeFlags,
318 : SfxViewShell*& pViewSh)
319 :
320 : {
321 : // Get old Printer
322 0 : SfxViewFrame *pViewFrm = m_pData->m_pObjectShell.Is() ?
323 0 : SfxViewFrame::GetFirst( m_pData->m_pObjectShell, false ) : 0;
324 0 : if ( !pViewFrm )
325 0 : return;
326 :
327 0 : pViewSh = pViewFrm->GetViewShell();
328 0 : pPrinter = pViewSh->GetPrinter(true);
329 0 : if ( !pPrinter )
330 0 : return;
331 :
332 : // new Printer-Name available?
333 0 : nChangeFlags = SfxPrinterChangeFlags::NONE;
334 0 : sal_Int32 lDummy = 0;
335 0 : for ( int n = 0; n < rPrinter.getLength(); ++n )
336 : {
337 : // get Property-Value from printer description
338 0 : const beans::PropertyValue &rProp = rPrinter.getConstArray()[n];
339 :
340 : // Name-Property?
341 0 : if ( rProp.Name == "Name" )
342 : {
343 0 : OUString aPrinterName;
344 0 : if ( ! ( rProp.Value >>= aPrinterName ) )
345 0 : throw ::com::sun::star::lang::IllegalArgumentException();
346 :
347 0 : if ( aPrinterName != pPrinter->GetName() )
348 : {
349 0 : pPrinter = VclPtr<SfxPrinter>::Create( pPrinter->GetOptions().Clone(), aPrinterName );
350 0 : nChangeFlags = SfxPrinterChangeFlags::PRINTER;
351 : }
352 0 : break;
353 : }
354 : }
355 :
356 0 : Size aSetPaperSize( 0, 0);
357 0 : view::PaperFormat nPaperFormat = view::PaperFormat_USER;
358 :
359 : // other properties
360 0 : for ( int i = 0; i < rPrinter.getLength(); ++i )
361 : {
362 : // get Property-Value from printer description
363 0 : const beans::PropertyValue &rProp = rPrinter.getConstArray()[i];
364 :
365 : // PaperOrientation-Property?
366 0 : if ( rProp.Name == "PaperOrientation" )
367 : {
368 : view::PaperOrientation eOrient;
369 0 : if ( !( rProp.Value >>= eOrient ) )
370 : {
371 0 : if ( !( rProp.Value >>= lDummy ) )
372 0 : throw ::com::sun::star::lang::IllegalArgumentException();
373 0 : eOrient = ( view::PaperOrientation) lDummy;
374 : }
375 :
376 0 : if ( (Orientation) eOrient != pPrinter->GetOrientation() )
377 : {
378 0 : pPrinter->SetOrientation( (Orientation) eOrient );
379 0 : nChangeFlags |= SfxPrinterChangeFlags::CHG_ORIENTATION;
380 : }
381 : }
382 :
383 : // PaperFormat-Property?
384 0 : else if ( rProp.Name == "PaperFormat" )
385 : {
386 0 : if ( !( rProp.Value >>= nPaperFormat ) )
387 : {
388 0 : if ( !( rProp.Value >>= lDummy ) )
389 0 : throw ::com::sun::star::lang::IllegalArgumentException();
390 0 : nPaperFormat = ( view::PaperFormat ) lDummy;
391 : }
392 :
393 0 : if ( convertToPaper(nPaperFormat) != pPrinter->GetPaper() )
394 : {
395 0 : pPrinter->SetPaper( convertToPaper(nPaperFormat) );
396 0 : nChangeFlags |= SfxPrinterChangeFlags::CHG_SIZE;
397 : }
398 : }
399 :
400 : // PaperSize-Property?
401 0 : else if ( rProp.Name == "PaperSize" )
402 : {
403 0 : awt::Size aTempSize ;
404 0 : if ( !( rProp.Value >>= aTempSize ) )
405 : {
406 0 : throw ::com::sun::star::lang::IllegalArgumentException();
407 : }
408 : else
409 : {
410 0 : aSetPaperSize = impl_Size_Struct2Object(aTempSize);
411 : }
412 : }
413 :
414 : // PrinterTray-Property
415 0 : else if ( rProp.Name == "PrinterPaperTray" )
416 : {
417 0 : OUString aTmp;
418 0 : if ( !( rProp.Value >>= aTmp ) )
419 0 : throw ::com::sun::star::lang::IllegalArgumentException();
420 0 : sal_uInt16 nCount = pPrinter->GetPaperBinCount();
421 0 : for (sal_uInt16 nBin=0; nBin<nCount; nBin++)
422 : {
423 0 : OUString aName( pPrinter->GetPaperBinName(nBin) );
424 0 : if ( aName == aTmp )
425 : {
426 0 : pPrinter->SetPaperBin(nBin);
427 0 : break;
428 : }
429 0 : }
430 : }
431 : }
432 :
433 : // The PaperSize may be set only when actually PAPER_USER
434 : // applies, otherwise the driver could choose a invalid format.
435 0 : if(nPaperFormat == view::PaperFormat_USER && aSetPaperSize.Width())
436 : {
437 : // Bug 56929 - MapMode of 100mm which recalculated when
438 : // the device is set. Additionally only set if they were really changed.
439 0 : aSetPaperSize = pPrinter->LogicToPixel( aSetPaperSize, MAP_100TH_MM );
440 0 : if( aSetPaperSize != pPrinter->GetPaperSizePixel() )
441 : {
442 0 : pPrinter->SetPaperSizeUser( pPrinter->PixelToLogic( aSetPaperSize ) );
443 0 : nChangeFlags |= SfxPrinterChangeFlags::CHG_SIZE;
444 : }
445 : }
446 :
447 : //wait until printing is done
448 0 : SfxPrinter* pDocPrinter = pViewSh->GetPrinter();
449 0 : while ( pDocPrinter->IsPrinting() )
450 0 : Application::Yield();
451 : }
452 :
453 0 : void SAL_CALL SfxPrintHelper::setPrinter(const uno::Sequence< beans::PropertyValue >& rPrinter)
454 : throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException, std::exception)
455 : {
456 : // object already disposed?
457 0 : SolarMutexGuard aGuard;
458 :
459 0 : SfxViewShell* pViewSh = NULL;
460 0 : SfxPrinter* pPrinter = NULL;
461 0 : SfxPrinterChangeFlags nChangeFlags = SfxPrinterChangeFlags::NONE;
462 0 : impl_setPrinter(rPrinter,pPrinter,nChangeFlags,pViewSh);
463 : // set new printer
464 0 : if ( pViewSh && pPrinter )
465 0 : pViewSh->SetPrinter( pPrinter, nChangeFlags, false );
466 0 : }
467 :
468 :
469 : // ImplPrintWatch thread for asynchronous printing with moving temp. file to ucb location
470 :
471 :
472 : /* This implements a thread which will be started to wait for asynchronous
473 : print jobs to temp. localy files. If they finish we move the temp. files
474 : to her right locations by using the ucb.
475 : */
476 0 : class ImplUCBPrintWatcher : public ::osl::Thread
477 : {
478 : private:
479 : /// of course we must know the printer which execute the job
480 : VclPtr<SfxPrinter> m_pPrinter;
481 : /// this describes the target location for the printed temp file
482 : OUString m_sTargetURL;
483 : /// it holds the temp file alive, till the print job will finish and remove it from disk automatically if the object die
484 : ::utl::TempFile* m_pTempFile;
485 :
486 : public:
487 : /* initialize this watcher but don't start it */
488 0 : ImplUCBPrintWatcher( SfxPrinter* pPrinter, ::utl::TempFile* pTempFile, const OUString& sTargetURL )
489 : : m_pPrinter ( pPrinter )
490 : , m_sTargetURL( sTargetURL )
491 0 : , m_pTempFile ( pTempFile )
492 0 : {}
493 :
494 : /* waits for finishing of the print job and moves the temp file afterwards
495 : Note: Starting of the job is done outside this thread!
496 : But we have to free some of the given resources on heap!
497 : */
498 0 : void SAL_CALL run() SAL_OVERRIDE
499 : {
500 0 : osl_setThreadName("ImplUCBPrintWatcher");
501 :
502 : /* SAFE { */
503 : {
504 0 : SolarMutexGuard aGuard;
505 0 : while( m_pPrinter->IsPrinting() )
506 0 : Application::Yield();
507 0 : m_pPrinter.clear(); // don't delete it! It's borrowed only :-)
508 : }
509 : /* } SAFE */
510 :
511 : // lock for further using of our member isn't necessary - because
512 : // we truns alone by defenition. Nobody join for us nor use us ...
513 0 : moveAndDeleteTemp(&m_pTempFile,m_sTargetURL);
514 :
515 : // finishing of this run() method will call onTerminate() automatically
516 : // kill this thread there!
517 0 : }
518 :
519 : /* nobody wait for this thread. We must kill ourself ...
520 : */
521 0 : void SAL_CALL onTerminated() SAL_OVERRIDE
522 : {
523 0 : delete this;
524 0 : }
525 :
526 : /* static helper to move the temp. file to the target location by using the ucb
527 : It's static to be useable from outside too. So it's not really necessary to start
528 : the thread, if finishing of the job was detected outside this thread.
529 : But it must be called without using a corresponding thread for the given parameter!
530 : */
531 0 : static void moveAndDeleteTemp( ::utl::TempFile** ppTempFile, const OUString& sTargetURL )
532 : {
533 : // move the file
534 : try
535 : {
536 0 : INetURLObject aSplitter(sTargetURL);
537 : OUString sFileName = aSplitter.getName(
538 : INetURLObject::LAST_SEGMENT,
539 : true,
540 0 : INetURLObject::DECODE_WITH_CHARSET);
541 0 : if (aSplitter.removeSegment() && !sFileName.isEmpty())
542 : {
543 : ::ucbhelper::Content aSource(
544 : OUString((*ppTempFile)->GetURL()),
545 : ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >(),
546 0 : comphelper::getProcessComponentContext());
547 :
548 : ::ucbhelper::Content aTarget(
549 : OUString(aSplitter.GetMainURL(INetURLObject::NO_DECODE)),
550 : ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >(),
551 0 : comphelper::getProcessComponentContext());
552 :
553 : aTarget.transferContent(
554 : aSource,
555 : ::ucbhelper::InsertOperation_COPY,
556 : OUString(sFileName),
557 0 : ::com::sun::star::ucb::NameClash::OVERWRITE);
558 0 : }
559 : }
560 0 : catch (const ::com::sun::star::ucb::ContentCreationException&)
561 : {
562 : OSL_FAIL("content create exception");
563 : }
564 0 : catch (const ::com::sun::star::ucb::CommandAbortedException&)
565 : {
566 : OSL_FAIL("command abort exception");
567 : }
568 0 : catch (const ::com::sun::star::uno::RuntimeException&)
569 : {
570 : OSL_FAIL("runtime exception");
571 : }
572 0 : catch (const ::com::sun::star::uno::Exception&)
573 : {
574 : OSL_FAIL("unknown exception");
575 : }
576 :
577 : // kill the temp file!
578 0 : delete *ppTempFile;
579 0 : *ppTempFile = NULL;
580 0 : }
581 : };
582 :
583 :
584 :
585 :
586 : // XPrintable
587 :
588 0 : void SAL_CALL SfxPrintHelper::print(const uno::Sequence< beans::PropertyValue >& rOptions)
589 : throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException, std::exception)
590 : {
591 0 : if( Application::GetSettings().GetMiscSettings().GetDisablePrinting() )
592 0 : return;
593 :
594 : // object already disposed?
595 : // object already disposed?
596 0 : SolarMutexGuard aGuard;
597 :
598 : // get view for sfx printing capabilities
599 0 : SfxViewFrame *pViewFrm = m_pData->m_pObjectShell.Is() ?
600 0 : SfxViewFrame::GetFirst( m_pData->m_pObjectShell, false ) : 0;
601 0 : if ( !pViewFrm )
602 0 : return;
603 0 : SfxViewShell* pView = pViewFrm->GetViewShell();
604 0 : if ( !pView )
605 0 : return;
606 0 : bool bMonitor = false;
607 : // We need this information at the end of this method, if we start the vcl printer
608 : // by executing the slot. Because if it is a ucb relevant URL we must wait for
609 : // finishing the print job and move the temporary local file by using the ucb
610 : // to the right location. But in case of no file name is given or it is already
611 : // a local one we can suppress this special handling. Because then vcl makes all
612 : // right for us.
613 0 : OUString sUcbUrl;
614 0 : ::utl::TempFile* pUCBPrintTempFile = NULL;
615 :
616 0 : uno::Sequence < beans::PropertyValue > aCheckedArgs( rOptions.getLength() );
617 0 : sal_Int32 nProps = 0;
618 0 : bool bWaitUntilEnd = false;
619 0 : sal_Int16 nDuplexMode = ::com::sun::star::view::DuplexMode::UNKNOWN;
620 0 : for ( int n = 0; n < rOptions.getLength(); ++n )
621 : {
622 : // get Property-Value from options
623 0 : const beans::PropertyValue &rProp = rOptions.getConstArray()[n];
624 :
625 : // FileName-Property?
626 0 : if ( rProp.Name == "FileName" )
627 : {
628 : // unpack th URL and check for a valid and well known protocol
629 0 : OUString sTemp;
630 0 : if (
631 0 : ( rProp.Value.getValueType()!=cppu::UnoType<OUString>::get()) ||
632 0 : (!(rProp.Value>>=sTemp))
633 : )
634 : {
635 0 : throw ::com::sun::star::lang::IllegalArgumentException();
636 : }
637 :
638 0 : OUString sPath ;
639 0 : OUString sURL (sTemp);
640 0 : INetURLObject aCheck(sURL );
641 0 : if (aCheck.GetProtocol()==INetProtocol::NotValid)
642 : {
643 : // OK - it's not a valid URL. But may it's a simple
644 : // system path directly. It will be supported for historical
645 : // reasons. Otherwhise we break to much external code ...
646 : // We try to convert it to a file URL. If its possible
647 : // we put the system path to the item set and let vcl work with it.
648 : // No ucb or thread will be necessary then. In case it couldnt be
649 : // converted its not an URL nor a system path. Then we can't accept
650 : // this parameter and have to throw an exception.
651 0 : OUString sSystemPath(sTemp);
652 0 : OUString sFileURL;
653 0 : if (::osl::FileBase::getFileURLFromSystemPath(sSystemPath,sFileURL)!=::osl::FileBase::E_None)
654 0 : throw ::com::sun::star::lang::IllegalArgumentException();
655 0 : aCheckedArgs[nProps].Name = rProp.Name;
656 0 : aCheckedArgs[nProps++].Value <<= sFileURL;
657 : // and append the local filename
658 0 : aCheckedArgs.realloc( aCheckedArgs.getLength()+1 );
659 0 : aCheckedArgs[nProps].Name = "LocalFileName";
660 0 : aCheckedArgs[nProps++].Value <<= OUString( sTemp );
661 : }
662 : else
663 : // It's a valid URL. but now we must know, if it is a local one or not.
664 : // It's a question of using ucb or not!
665 0 : if (::utl::LocalFileHelper::ConvertURLToSystemPath(sURL,sPath))
666 : {
667 : // it's a local file, we can use vcl without special handling
668 : // And we have to use the system notation of the incoming URL.
669 : // But it into the descriptor and let the slot be executed at
670 : // the end of this method.
671 0 : aCheckedArgs[nProps].Name = rProp.Name;
672 0 : aCheckedArgs[nProps++].Value <<= sTemp;
673 : // and append the local filename
674 0 : aCheckedArgs.realloc( aCheckedArgs.getLength()+1 );
675 0 : aCheckedArgs[nProps].Name = "LocalFileName";
676 0 : aCheckedArgs[nProps++].Value <<= sPath;
677 : }
678 : else
679 : {
680 : // it's an ucb target. So we must use a temp. file for vcl
681 : // and move it after printing by using the ucb.
682 : // Create a temp file on the heap (because it must delete the
683 : // real file on disk automatically if it die - bt we have to share it with
684 : // some other sources ... e.g. the ImplUCBPrintWatcher).
685 : // And we put the name of this temp file to the descriptor instead
686 : // of the URL. The URL we save for later using separately.
687 : // Execution of the print job will be done later by executing
688 : // a slot ...
689 0 : if(!pUCBPrintTempFile)
690 0 : pUCBPrintTempFile = new ::utl::TempFile();
691 0 : pUCBPrintTempFile->EnableKillingFile();
692 :
693 : //FIXME: does it work?
694 0 : aCheckedArgs[nProps].Name = "LocalFileName";
695 0 : aCheckedArgs[nProps++].Value <<= OUString( pUCBPrintTempFile->GetFileName() );
696 0 : sUcbUrl = sURL;
697 0 : }
698 : }
699 :
700 : // CopyCount-Property
701 0 : else if ( rProp.Name == "CopyCount" )
702 : {
703 0 : sal_Int32 nCopies = 0;
704 0 : if ( !( rProp.Value >>= nCopies ) )
705 0 : throw ::com::sun::star::lang::IllegalArgumentException();
706 :
707 0 : aCheckedArgs[nProps].Name = rProp.Name;
708 0 : aCheckedArgs[nProps++].Value <<= nCopies;
709 : }
710 :
711 : // Collate-Property
712 : // Sort-Property (deprecated)
713 0 : else if ( rProp.Name == "Collate" || rProp.Name == "Sort" )
714 : {
715 : bool bTemp;
716 0 : if ( rProp.Value >>= bTemp )
717 : {
718 0 : aCheckedArgs[nProps].Name = "Collate";
719 0 : aCheckedArgs[nProps++].Value <<= bTemp;
720 : }
721 : else
722 0 : throw ::com::sun::star::lang::IllegalArgumentException();
723 : }
724 :
725 : // Pages-Property
726 0 : else if ( rProp.Name == "Pages" )
727 : {
728 0 : OUString sTemp;
729 0 : if( rProp.Value >>= sTemp )
730 : {
731 0 : aCheckedArgs[nProps].Name = rProp.Name;
732 0 : aCheckedArgs[nProps++].Value <<= sTemp;
733 : }
734 : else
735 0 : throw ::com::sun::star::lang::IllegalArgumentException();
736 : }
737 :
738 : // MonitorVisible
739 0 : else if ( rProp.Name == "MonitorVisible" )
740 : {
741 0 : if( !(rProp.Value >>= bMonitor) )
742 0 : throw ::com::sun::star::lang::IllegalArgumentException();
743 0 : aCheckedArgs[nProps].Name = rProp.Name;
744 0 : aCheckedArgs[nProps++].Value <<= bMonitor;
745 : }
746 :
747 : // Wait
748 0 : else if ( rProp.Name == "Wait" )
749 : {
750 0 : if ( !(rProp.Value >>= bWaitUntilEnd) )
751 0 : throw ::com::sun::star::lang::IllegalArgumentException();
752 0 : aCheckedArgs[nProps].Name = rProp.Name;
753 0 : aCheckedArgs[nProps++].Value <<= bWaitUntilEnd;
754 : }
755 :
756 0 : else if ( rProp.Name == "DuplexMode" )
757 : {
758 0 : if ( !(rProp.Value >>= nDuplexMode ) )
759 0 : throw ::com::sun::star::lang::IllegalArgumentException();
760 0 : aCheckedArgs[nProps].Name = rProp.Name;
761 0 : aCheckedArgs[nProps++].Value <<= nDuplexMode;
762 : }
763 : }
764 :
765 0 : if ( nProps != aCheckedArgs.getLength() )
766 0 : aCheckedArgs.realloc(nProps);
767 :
768 : // Execute the print request every time.
769 : // It doesn'tmatter if it is a real printer used or we print to a local file
770 : // nor if we print to a temp file and move it afterwards by using the ucb.
771 : // That will be handled later. see pUCBPrintFile below!
772 0 : pView->ExecPrint( aCheckedArgs, true, false );
773 :
774 : // Ok - may be execution before has finished (or started!) printing.
775 : // And may it was a printing to a file.
776 : // Now we have to check if we can move the file (if necessary) via ucb to his right location.
777 : // Cases:
778 : // a) printing finished => move the file directly and forget the watcher thread
779 : // b) printing is asynchron and runs currently => start watcher thread and exit this method
780 : // This thread make all necessary things by itself.
781 0 : if (pUCBPrintTempFile)
782 : {
783 : // a)
784 0 : SfxPrinter* pPrinter = pView->GetPrinter();
785 0 : if ( ! pPrinter->IsPrinting() )
786 0 : ImplUCBPrintWatcher::moveAndDeleteTemp(&pUCBPrintTempFile,sUcbUrl);
787 : // b)
788 : else
789 : {
790 : // Note: we create(d) some resource on the heap. (thread and tep file)
791 : // They will be deleted by the thread automatically if he finish his run() method.
792 0 : ImplUCBPrintWatcher* pWatcher = new ImplUCBPrintWatcher( pPrinter, pUCBPrintTempFile, sUcbUrl );
793 0 : pWatcher->create();
794 : }
795 0 : }
796 : }
797 :
798 232926 : void IMPL_PrintListener_DataContainer::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
799 : {
800 232926 : const SfxPrintingHint* pPrintHint = dynamic_cast<const SfxPrintingHint*>(&rHint);
801 465852 : if ( &rBC != m_pObjectShell
802 232926 : || !pPrintHint
803 232926 : || pPrintHint->GetWhich() == SFX_PRINTABLESTATE_CANCELJOB )
804 465852 : return;
805 :
806 0 : if ( pPrintHint->GetWhich() == com::sun::star::view::PrintableState_JOB_STARTED )
807 : {
808 0 : if ( !m_xPrintJob.is() )
809 0 : m_xPrintJob = new SfxPrintJob_Impl( this );
810 0 : m_aPrintOptions = pPrintHint->GetOptions();
811 : }
812 :
813 : ::cppu::OInterfaceContainerHelper* pContainer = m_aInterfaceContainer.getContainer(
814 0 : cppu::UnoType<view::XPrintJobListener>::get());
815 0 : if ( !pContainer )
816 0 : return;
817 :
818 0 : view::PrintJobEvent aEvent;
819 0 : aEvent.Source = m_xPrintJob;
820 0 : aEvent.State = (com::sun::star::view::PrintableState) pPrintHint->GetWhich();
821 :
822 0 : ::cppu::OInterfaceIteratorHelper pIterator(*pContainer);
823 0 : while (pIterator.hasMoreElements())
824 0 : static_cast<view::XPrintJobListener*>(pIterator.next())->printJobEvent( aEvent );
825 : }
826 :
827 4114 : 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)
828 : {
829 4114 : SolarMutexGuard aGuard;
830 4114 : m_pData->m_aInterfaceContainer.addInterface( cppu::UnoType<view::XPrintJobListener>::get(), xListener );
831 4114 : }
832 :
833 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)
834 : {
835 0 : SolarMutexGuard aGuard;
836 0 : m_pData->m_aInterfaceContainer.removeInterface( cppu::UnoType<view::XPrintJobListener>::get(), xListener );
837 648 : }
838 :
839 :
840 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|