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