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