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