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