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 <com/sun/star/document/XDocumentProperties.hpp>
22 : #include <com/sun/star/view/PrintableState.hpp>
23 : #include "com/sun/star/view/XRenderable.hpp"
24 :
25 : #include <svl/itempool.hxx>
26 : #include <vcl/msgbox.hxx>
27 : #include <svtools/prnsetup.hxx>
28 : #include <svl/flagitem.hxx>
29 : #include <svl/stritem.hxx>
30 : #include <svl/intitem.hxx>
31 : #include <svl/eitem.hxx>
32 : #include <sfx2/app.hxx>
33 : #include <unotools/useroptions.hxx>
34 : #include <unotools/printwarningoptions.hxx>
35 : #include <tools/datetime.hxx>
36 : #include <sfx2/bindings.hxx>
37 : #include <sfx2/objface.hxx>
38 : #include <sfx2/viewsh.hxx>
39 : #include "viewimp.hxx"
40 : #include <sfx2/viewfrm.hxx>
41 : #include <sfx2/prnmon.hxx>
42 : #include "sfx2/sfxresid.hxx"
43 : #include <sfx2/request.hxx>
44 : #include <sfx2/objsh.hxx>
45 : #include "sfxtypes.hxx"
46 : #include <sfx2/event.hxx>
47 : #include <sfx2/docfile.hxx>
48 : #include <sfx2/docfilt.hxx>
49 :
50 : #include "toolkit/awt/vclxdevice.hxx"
51 :
52 : #include "view.hrc"
53 : #include "helpid.hrc"
54 :
55 : using namespace com::sun::star;
56 : using namespace com::sun::star::uno;
57 :
58 20997 : TYPEINIT1(SfxPrintingHint, SfxHint);
59 :
60 : // -----------------------------------------------------------------------
61 : class SfxPrinterController : public vcl::PrinterController, public SfxListener
62 : {
63 : Any maCompleteSelection;
64 : Any maSelection;
65 : Reference< view::XRenderable > mxRenderable;
66 : mutable Printer* mpLastPrinter;
67 : mutable Reference<awt::XDevice> mxDevice;
68 : SfxViewShell* mpViewShell;
69 : SfxObjectShell* mpObjectShell;
70 : sal_Bool m_bOrigStatus;
71 : sal_Bool m_bNeedsChange;
72 : sal_Bool m_bApi;
73 : sal_Bool m_bTempPrinter;
74 : util::DateTime m_aLastPrinted;
75 : ::rtl::OUString m_aLastPrintedBy;
76 :
77 : Sequence< beans::PropertyValue > getMergedOptions() const;
78 : const Any& getSelectionObject() const;
79 : public:
80 : SfxPrinterController( const boost::shared_ptr<Printer>& i_rPrinter,
81 : const Any& i_rComplete,
82 : const Any& i_rSelection,
83 : const Any& i_rViewProp,
84 : const Reference< view::XRenderable >& i_xRender,
85 : sal_Bool i_bApi, sal_Bool i_bDirect,
86 : SfxViewShell* pView,
87 : const uno::Sequence< beans::PropertyValue >& rProps
88 : );
89 :
90 : virtual ~SfxPrinterController();
91 : virtual void Notify( SfxBroadcaster&, const SfxHint& );
92 :
93 : virtual int getPageCount() const;
94 : virtual Sequence< beans::PropertyValue > getPageParameters( int i_nPage ) const;
95 : virtual void printPage( int i_nPage ) const;
96 : virtual void jobStarted();
97 : virtual void jobFinished( com::sun::star::view::PrintableState );
98 : };
99 :
100 0 : SfxPrinterController::SfxPrinterController( const boost::shared_ptr<Printer>& i_rPrinter,
101 : const Any& i_rComplete,
102 : const Any& i_rSelection,
103 : const Any& i_rViewProp,
104 : const Reference< view::XRenderable >& i_xRender,
105 : sal_Bool i_bApi, sal_Bool i_bDirect,
106 : SfxViewShell* pView,
107 : const uno::Sequence< beans::PropertyValue >& rProps
108 : )
109 : : PrinterController( i_rPrinter)
110 : , maCompleteSelection( i_rComplete )
111 : , maSelection( i_rSelection )
112 : , mxRenderable( i_xRender )
113 : , mpLastPrinter( NULL )
114 : , mpViewShell( pView )
115 : , mpObjectShell(0)
116 : , m_bOrigStatus( sal_False )
117 : , m_bNeedsChange( sal_False )
118 : , m_bApi(i_bApi)
119 0 : , m_bTempPrinter( i_rPrinter.get() != NULL )
120 : {
121 0 : if ( mpViewShell )
122 : {
123 0 : StartListening( *mpViewShell );
124 0 : mpObjectShell = mpViewShell->GetObjectShell();
125 0 : StartListening( *mpObjectShell );
126 : }
127 :
128 : // initialize extra ui options
129 0 : if( mxRenderable.is() )
130 : {
131 0 : for (sal_Int32 nProp=0; nProp < rProps.getLength(); ++nProp)
132 0 : setValue( rProps[nProp].Name, rProps[nProp].Value );
133 :
134 0 : Sequence< beans::PropertyValue > aRenderOptions( 3 );
135 0 : aRenderOptions[0].Name = rtl::OUString( "ExtraPrintUIOptions" );
136 0 : aRenderOptions[1].Name = rtl::OUString( "View" );
137 0 : aRenderOptions[1].Value = i_rViewProp;
138 0 : aRenderOptions[2].Name = rtl::OUString( "IsPrinter" );
139 0 : aRenderOptions[2].Value <<= sal_True;
140 : try
141 : {
142 0 : Sequence< beans::PropertyValue > aRenderParms( mxRenderable->getRenderer( 0 , getSelectionObject(), aRenderOptions ) );
143 0 : int nProps = aRenderParms.getLength();
144 0 : for( int i = 0; i < nProps; i++ )
145 : {
146 0 : if ( aRenderParms[i].Name == "ExtraPrintUIOptions" )
147 : {
148 0 : Sequence< beans::PropertyValue > aUIProps;
149 0 : aRenderParms[i].Value >>= aUIProps;
150 0 : setUIOptions( aUIProps );
151 : }
152 0 : else if( aRenderParms[i].Name == "NUp" )
153 : {
154 0 : setValue( aRenderParms[i].Name, aRenderParms[i].Value );
155 : }
156 0 : }
157 : }
158 0 : catch( lang::IllegalArgumentException& )
159 : {
160 : // the first renderer should always be available for the UI options,
161 : // but catch the exception to be safe
162 0 : }
163 : }
164 :
165 : // set some job parameters
166 0 : setValue( rtl::OUString( "IsApi" ), makeAny( i_bApi ) );
167 0 : setValue( rtl::OUString( "IsDirect" ), makeAny( i_bDirect ) );
168 0 : setValue( rtl::OUString( "IsPrinter" ), makeAny( sal_True ) );
169 0 : setValue( rtl::OUString( "View" ), i_rViewProp );
170 0 : }
171 :
172 0 : void SfxPrinterController::Notify( SfxBroadcaster& , const SfxHint& rHint )
173 : {
174 0 : if ( rHint.IsA(TYPE(SfxSimpleHint)) )
175 : {
176 0 : if ( ((SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING )
177 : {
178 0 : EndListening(*mpViewShell);
179 0 : EndListening(*mpObjectShell);
180 0 : mpViewShell = 0;
181 0 : mpObjectShell = 0;
182 : }
183 : }
184 0 : }
185 :
186 0 : SfxPrinterController::~SfxPrinterController()
187 : {
188 0 : }
189 :
190 0 : const Any& SfxPrinterController::getSelectionObject() const
191 : {
192 0 : const beans::PropertyValue* pVal = getValue( rtl::OUString( "PrintSelectionOnly" ) );
193 0 : if( pVal )
194 : {
195 0 : sal_Bool bSel = sal_False;
196 0 : pVal->Value >>= bSel;
197 0 : return bSel ? maSelection : maCompleteSelection;
198 : }
199 :
200 0 : sal_Int32 nChoice = 0;
201 0 : pVal = getValue( rtl::OUString( "PrintContent" ) );
202 0 : if( pVal )
203 0 : pVal->Value >>= nChoice;
204 0 : return (nChoice > 1) ? maSelection : maCompleteSelection;
205 : }
206 :
207 0 : Sequence< beans::PropertyValue > SfxPrinterController::getMergedOptions() const
208 : {
209 0 : boost::shared_ptr<Printer> pPrinter( getPrinter() );
210 0 : if( pPrinter.get() != mpLastPrinter )
211 : {
212 0 : mpLastPrinter = pPrinter.get();
213 0 : VCLXDevice* pXDevice = new VCLXDevice();
214 0 : pXDevice->SetOutputDevice( mpLastPrinter );
215 0 : mxDevice = Reference< awt::XDevice >( pXDevice );
216 : }
217 :
218 0 : Sequence< beans::PropertyValue > aRenderOptions( 1 );
219 0 : aRenderOptions[ 0 ].Name = rtl::OUString( "RenderDevice" );
220 0 : aRenderOptions[ 0 ].Value <<= mxDevice;
221 :
222 0 : aRenderOptions = getJobProperties( aRenderOptions );
223 0 : return aRenderOptions;
224 : }
225 :
226 0 : int SfxPrinterController::getPageCount() const
227 : {
228 0 : int nPages = 0;
229 0 : boost::shared_ptr<Printer> pPrinter( getPrinter() );
230 0 : if( mxRenderable.is() && pPrinter )
231 : {
232 0 : Sequence< beans::PropertyValue > aJobOptions( getMergedOptions() );
233 : try
234 : {
235 0 : nPages = mxRenderable->getRendererCount( getSelectionObject(), aJobOptions );
236 : }
237 0 : catch (lang::DisposedException &)
238 : {
239 : OSL_TRACE("SfxPrinterController: document disposed while printing");
240 : const_cast<SfxPrinterController*>(this)->setJobState(
241 0 : view::PrintableState_JOB_ABORTED);
242 0 : }
243 : }
244 0 : return nPages;
245 : }
246 :
247 0 : Sequence< beans::PropertyValue > SfxPrinterController::getPageParameters( int i_nPage ) const
248 : {
249 0 : boost::shared_ptr<Printer> pPrinter( getPrinter() );
250 0 : Sequence< beans::PropertyValue > aResult;
251 :
252 0 : if( mxRenderable.is() && pPrinter )
253 : {
254 0 : Sequence< beans::PropertyValue > aJobOptions( getMergedOptions() );
255 : try
256 : {
257 0 : aResult = mxRenderable->getRenderer( i_nPage, getSelectionObject(), aJobOptions );
258 : }
259 0 : catch( lang::IllegalArgumentException& )
260 : {
261 : }
262 0 : catch (lang::DisposedException &)
263 : {
264 : OSL_TRACE("SfxPrinterController: document disposed while printing");
265 : const_cast<SfxPrinterController*>(this)->setJobState(
266 0 : view::PrintableState_JOB_ABORTED);
267 0 : }
268 : }
269 0 : return aResult;
270 : }
271 :
272 0 : void SfxPrinterController::printPage( int i_nPage ) const
273 : {
274 0 : boost::shared_ptr<Printer> pPrinter( getPrinter() );
275 0 : if( mxRenderable.is() && pPrinter )
276 : {
277 0 : Sequence< beans::PropertyValue > aJobOptions( getMergedOptions() );
278 : try
279 : {
280 0 : mxRenderable->render( i_nPage, getSelectionObject(), aJobOptions );
281 : }
282 0 : catch( lang::IllegalArgumentException& )
283 : {
284 : // don't care enough about nonexistant page here
285 : // to provoke a crash
286 : }
287 0 : catch (lang::DisposedException &)
288 : {
289 : OSL_TRACE("SfxPrinterController: document disposed while printing");
290 : const_cast<SfxPrinterController*>(this)->setJobState(
291 0 : view::PrintableState_JOB_ABORTED);
292 0 : }
293 0 : }
294 0 : }
295 :
296 0 : void SfxPrinterController::jobStarted()
297 : {
298 0 : if ( mpObjectShell )
299 : {
300 0 : m_bOrigStatus = mpObjectShell->IsEnableSetModified();
301 :
302 : // check configuration: shall update of printing information in DocInfo set the document to "modified"?
303 0 : if ( m_bOrigStatus && !SvtPrintWarningOptions().IsModifyDocumentOnPrintingAllowed() )
304 : {
305 0 : mpObjectShell->EnableSetModified( sal_False );
306 0 : m_bNeedsChange = sal_True;
307 : }
308 :
309 : // refresh document info
310 0 : uno::Reference<document::XDocumentProperties> xDocProps(mpObjectShell->getDocProperties());
311 0 : m_aLastPrintedBy = xDocProps->getPrintedBy();
312 0 : m_aLastPrinted = xDocProps->getPrintDate();
313 :
314 0 : xDocProps->setPrintedBy( mpObjectShell->IsUseUserData()
315 : ? ::rtl::OUString( SvtUserOptions().GetFullName() )
316 0 : : ::rtl::OUString() );
317 0 : ::DateTime now( ::DateTime::SYSTEM );
318 :
319 0 : xDocProps->setPrintDate( util::DateTime(
320 0 : now.Get100Sec(), now.GetSec(), now.GetMin(), now.GetHour(),
321 0 : now.GetDay(), now.GetMonth(), now.GetYear() ) );
322 :
323 : // FIXME: how to get all print options incl. AdditionalOptions easily?
324 0 : uno::Sequence < beans::PropertyValue > aOpts;
325 0 : mpObjectShell->Broadcast( SfxPrintingHint( view::PrintableState_JOB_STARTED, aOpts ) );
326 : }
327 0 : }
328 :
329 0 : void SfxPrinterController::jobFinished( com::sun::star::view::PrintableState nState )
330 : {
331 0 : if ( mpObjectShell )
332 : {
333 0 : bool bCopyJobSetup = false;
334 0 : mpObjectShell->Broadcast( SfxPrintingHint( nState ) );
335 0 : switch ( nState )
336 : {
337 : case view::PrintableState_JOB_FAILED :
338 : {
339 : // "real" problem (not simply printing cancelled by user)
340 0 : rtl::OUString aMsg( SfxResId(STR_NOSTARTPRINTER).toString() );
341 0 : if ( !m_bApi )
342 0 : ErrorBox( mpViewShell->GetWindow(), WB_OK | WB_DEF_OK, aMsg ).Execute();
343 : // intentionally no break
344 : }
345 : case view::PrintableState_JOB_ABORTED :
346 : {
347 : // printing not successful, reset DocInfo
348 0 : uno::Reference<document::XDocumentProperties> xDocProps(mpObjectShell->getDocProperties());
349 0 : xDocProps->setPrintedBy(m_aLastPrintedBy);
350 0 : xDocProps->setPrintDate(m_aLastPrinted);
351 0 : break;
352 : }
353 :
354 : case view::PrintableState_JOB_SPOOLED :
355 : case view::PrintableState_JOB_COMPLETED :
356 : {
357 0 : SfxBindings& rBind = mpViewShell->GetViewFrame()->GetBindings();
358 0 : rBind.Invalidate( SID_PRINTDOC );
359 0 : rBind.Invalidate( SID_PRINTDOCDIRECT );
360 0 : rBind.Invalidate( SID_SETUPPRINTER );
361 0 : bCopyJobSetup = ! m_bTempPrinter;
362 0 : break;
363 : }
364 :
365 : default:
366 0 : break;
367 : }
368 :
369 0 : if( bCopyJobSetup && mpViewShell )
370 : {
371 : // #i114306#
372 : // Note: this possibly creates a printer that gets immediately replaced
373 : // by a new one. The reason for this is that otherwise we would not get
374 : // the printer's SfxItemSet here to copy. Awkward, but at the moment there is no
375 : // other way here to get the item set.
376 0 : SfxPrinter* pDocPrt = mpViewShell->GetPrinter(sal_True);
377 0 : if( pDocPrt )
378 : {
379 0 : if( pDocPrt->GetName() == getPrinter()->GetName() )
380 0 : pDocPrt->SetJobSetup( getPrinter()->GetJobSetup() );
381 : else
382 : {
383 0 : SfxPrinter* pNewPrt = new SfxPrinter( pDocPrt->GetOptions().Clone(), getPrinter()->GetName() );
384 0 : pNewPrt->SetJobSetup( getPrinter()->GetJobSetup() );
385 0 : mpViewShell->SetPrinter( pNewPrt, SFX_PRINTER_PRINTER | SFX_PRINTER_JOBSETUP );
386 : }
387 : }
388 : }
389 :
390 0 : if ( m_bNeedsChange )
391 0 : mpObjectShell->EnableSetModified( m_bOrigStatus );
392 :
393 0 : if ( mpViewShell )
394 : {
395 0 : mpViewShell->pImp->m_pPrinterController.reset();
396 : }
397 : }
398 0 : }
399 :
400 : //====================================================================
401 :
402 : class SfxDialogExecutor_Impl
403 :
404 : /* [Description]
405 :
406 : An instance of this class is created for the life span of the
407 : printer dialogue, to create in its click handler for the additions by the
408 : virtual method of the derived SfxViewShell generated print options dialogue
409 : and to cache the options set there as SfxItemSet.
410 : */
411 :
412 : {
413 : private:
414 : SfxViewShell* _pViewSh;
415 : PrinterSetupDialog* _pSetupParent;
416 : SfxItemSet* _pOptions;
417 : sal_Bool _bHelpDisabled;
418 :
419 : DECL_LINK( Execute, void * );
420 :
421 : public:
422 : SfxDialogExecutor_Impl( SfxViewShell* pViewSh, PrinterSetupDialog* pParent );
423 : ~SfxDialogExecutor_Impl() { delete _pOptions; }
424 :
425 0 : Link GetLink() const { return LINK( this, SfxDialogExecutor_Impl, Execute); }
426 0 : const SfxItemSet* GetOptions() const { return _pOptions; }
427 0 : void DisableHelp() { _bHelpDisabled = sal_True; }
428 : };
429 :
430 : //--------------------------------------------------------------------
431 :
432 0 : SfxDialogExecutor_Impl::SfxDialogExecutor_Impl( SfxViewShell* pViewSh, PrinterSetupDialog* pParent ) :
433 :
434 : _pViewSh ( pViewSh ),
435 : _pSetupParent ( pParent ),
436 : _pOptions ( NULL ),
437 0 : _bHelpDisabled ( sal_False )
438 :
439 : {
440 0 : }
441 :
442 : //--------------------------------------------------------------------
443 :
444 0 : IMPL_LINK_NOARG(SfxDialogExecutor_Impl, Execute)
445 : {
446 : // Options noted locally
447 0 : if ( !_pOptions )
448 : {
449 : DBG_ASSERT( _pSetupParent, "no dialog parent" );
450 0 : if( _pSetupParent )
451 0 : _pOptions = ( (SfxPrinter*)_pSetupParent->GetPrinter() )->GetOptions().Clone();
452 : }
453 :
454 : // Create Dialog
455 : SfxPrintOptionsDialog* pDlg = new SfxPrintOptionsDialog( static_cast<Window*>(_pSetupParent),
456 0 : _pViewSh, _pOptions );
457 0 : if ( _bHelpDisabled )
458 0 : pDlg->DisableHelp();
459 0 : if ( pDlg->Execute() == RET_OK )
460 : {
461 0 : delete _pOptions;
462 0 : _pOptions = pDlg->GetOptions().Clone();
463 :
464 : }
465 0 : delete pDlg;
466 :
467 0 : return 0;
468 : }
469 :
470 : //-------------------------------------------------------------------------
471 :
472 0 : SfxPrinter* SfxViewShell::SetPrinter_Impl( SfxPrinter *pNewPrinter )
473 :
474 :
475 : /* Internal method for setting the differences between 'pNewPrinter' to the
476 : current printer. pNewPrinter is either taken over or deleted.
477 : */
478 :
479 : {
480 : // get current Printer
481 0 : SfxPrinter *pDocPrinter = GetPrinter();
482 :
483 : // Evaluate Printer Options
484 0 : bool bOriToDoc = false;
485 0 : bool bSizeToDoc = false;
486 0 : if ( &pDocPrinter->GetOptions() )
487 : {
488 0 : sal_uInt16 nWhich = GetPool().GetWhich(SID_PRINTER_CHANGESTODOC);
489 0 : const SfxFlagItem *pFlagItem = 0;
490 0 : pDocPrinter->GetOptions().GetItemState( nWhich, sal_False, (const SfxPoolItem**) &pFlagItem );
491 0 : bOriToDoc = pFlagItem ? (pFlagItem->GetValue() & SFX_PRINTER_CHG_ORIENTATION) : sal_False;
492 0 : bSizeToDoc = pFlagItem ? (pFlagItem->GetValue() & SFX_PRINTER_CHG_SIZE) : sal_False;
493 : }
494 :
495 : // Determine the previous format and size
496 0 : Orientation eOldOri = pDocPrinter->GetOrientation();
497 0 : Size aOldPgSz = pDocPrinter->GetPaperSizePixel();
498 :
499 : // Determine the new format and size
500 0 : Orientation eNewOri = pNewPrinter->GetOrientation();
501 0 : Size aNewPgSz = pNewPrinter->GetPaperSizePixel();
502 :
503 : // Determine the changes in page format
504 0 : sal_Bool bOriChg = (eOldOri != eNewOri) && bOriToDoc;
505 0 : sal_Bool bPgSzChg = ( aOldPgSz.Height() !=
506 0 : ( bOriChg ? aNewPgSz.Width() : aNewPgSz.Height() ) ||
507 0 : aOldPgSz.Width() !=
508 0 : ( bOriChg ? aNewPgSz.Height() : aNewPgSz.Width() ) ) &&
509 0 : bSizeToDoc;
510 :
511 : // Message and Flags for page format, summaries changes
512 0 : rtl::OUString aMsg;
513 0 : sal_uInt16 nNewOpt=0;
514 0 : if( bOriChg && bPgSzChg )
515 : {
516 0 : aMsg = SfxResId(STR_PRINT_NEWORISIZE).toString();
517 0 : nNewOpt = SFX_PRINTER_CHG_ORIENTATION | SFX_PRINTER_CHG_SIZE;
518 : }
519 0 : else if (bOriChg )
520 : {
521 0 : aMsg = SfxResId(STR_PRINT_NEWORI).toString();
522 0 : nNewOpt = SFX_PRINTER_CHG_ORIENTATION;
523 : }
524 0 : else if (bPgSzChg)
525 : {
526 0 : aMsg = SfxResId(STR_PRINT_NEWSIZE).toString();
527 0 : nNewOpt = SFX_PRINTER_CHG_SIZE;
528 : }
529 :
530 : // Summaries in this variable what has been changed.
531 0 : sal_uInt16 nChangedFlags = 0;
532 :
533 : // Ask if possible, if page format should be taken over from printer.
534 0 : if ( ( bOriChg || bPgSzChg ) &&
535 0 : RET_YES == QueryBox(0, WB_YES_NO | WB_DEF_OK, aMsg).Execute() )
536 : // Flags wich changes for <SetPrinter(SfxPrinter*)> are maintained
537 0 : nChangedFlags |= nNewOpt;
538 :
539 : // For the MAC to have its "temporary of class String" in next if()
540 0 : String aTempPrtName = pNewPrinter->GetName();
541 0 : String aDocPrtName = pDocPrinter->GetName();
542 :
543 : // Was the printer selection changed from Default to Specific
544 : // or the other way around?
545 0 : if ( (aTempPrtName != aDocPrtName) || (pDocPrinter->IsDefPrinter() != pNewPrinter->IsDefPrinter()) )
546 : {
547 0 : nChangedFlags |= SFX_PRINTER_PRINTER|SFX_PRINTER_JOBSETUP;
548 0 : pDocPrinter = pNewPrinter;
549 : }
550 : else
551 : {
552 : // Compare extra options
553 0 : if ( ! (pNewPrinter->GetOptions() == pDocPrinter->GetOptions()) )
554 : {
555 : // Option have changed
556 0 : pDocPrinter->SetOptions( pNewPrinter->GetOptions() );
557 0 : nChangedFlags |= SFX_PRINTER_OPTIONS;
558 : }
559 :
560 : // Compare JobSetups
561 0 : JobSetup aNewJobSetup = pNewPrinter->GetJobSetup();
562 0 : JobSetup aOldJobSetup = pDocPrinter->GetJobSetup();
563 0 : if ( aNewJobSetup != aOldJobSetup )
564 : {
565 0 : nChangedFlags |= SFX_PRINTER_JOBSETUP;
566 : }
567 :
568 : // Keep old changed Printer.
569 0 : pDocPrinter->SetPrinterProps( pNewPrinter );
570 0 : delete pNewPrinter;
571 : }
572 :
573 0 : if ( 0 != nChangedFlags )
574 : // SetPrinter will delete the old printer if it changes
575 0 : SetPrinter( pDocPrinter, nChangedFlags );
576 0 : return pDocPrinter;
577 : }
578 :
579 : //-------------------------------------------------------------------------
580 : // Sadly enough the problem arises with WIN32 that nothing is printed when
581 : // SID_PRINTDOCDIRECT auflaueft. At the moment the only known solution in this
582 : // case is to turn off the optimazation.
583 : #ifdef _MSC_VER
584 : #pragma optimize ( "", off )
585 : #endif
586 :
587 0 : void SfxViewShell::ExecPrint( const uno::Sequence < beans::PropertyValue >& rProps, sal_Bool bIsAPI, sal_Bool bIsDirect )
588 : {
589 : // get the current selection; our controller should know it
590 0 : Reference< frame::XController > xController( GetController() );
591 0 : Reference< view::XSelectionSupplier > xSupplier( xController, UNO_QUERY );
592 :
593 0 : Any aSelection;
594 0 : if( xSupplier.is() )
595 0 : aSelection = xSupplier->getSelection();
596 : else
597 0 : aSelection <<= GetObjectShell()->GetModel();
598 0 : Any aComplete( makeAny( GetObjectShell()->GetModel() ) );
599 0 : Any aViewProp( makeAny( xController ) );
600 0 : boost::shared_ptr<Printer> aPrt;
601 :
602 0 : const beans::PropertyValue* pVal = rProps.getConstArray();
603 0 : for( sal_Int32 i = 0; i < rProps.getLength(); i++ )
604 : {
605 0 : if ( pVal[i].Name == "PrinterName" )
606 : {
607 0 : rtl::OUString aPrinterName;
608 0 : pVal[i].Value >>= aPrinterName;
609 0 : aPrt.reset( new Printer( aPrinterName ) );
610 0 : break;
611 : }
612 : }
613 :
614 : boost::shared_ptr<vcl::PrinterController> pController( new SfxPrinterController(
615 : aPrt,
616 : aComplete,
617 : aSelection,
618 : aViewProp,
619 0 : GetRenderable(),
620 : bIsAPI,
621 : bIsDirect,
622 : this,
623 : rProps
624 0 : ) );
625 0 : pImp->m_pPrinterController = pController;
626 :
627 0 : SfxObjectShell *pObjShell = GetObjectShell();
628 : pController->setValue( rtl::OUString( "JobName" ),
629 0 : makeAny( rtl::OUString( pObjShell->GetTitle(0) ) ) );
630 :
631 : // FIXME: job setup
632 0 : SfxPrinter* pDocPrt = GetPrinter(sal_False);
633 0 : JobSetup aJobSetup = pDocPrt ? pDocPrt->GetJobSetup() : GetJobSetup();
634 0 : if( bIsDirect )
635 : aJobSetup.SetValue( String( "IsQuickJob" ),
636 0 : String( "true" ) );
637 :
638 0 : Printer::PrintJob( pController, aJobSetup );
639 0 : }
640 :
641 0 : Printer* SfxViewShell::GetActivePrinter() const
642 : {
643 : return (pImp->m_pPrinterController)
644 0 : ? pImp->m_pPrinterController->getPrinter().get() : 0;
645 : }
646 :
647 0 : void SfxViewShell::ExecPrint_Impl( SfxRequest &rReq )
648 : {
649 0 : sal_uInt16 nDialogRet = RET_CANCEL;
650 0 : SfxPrinter* pPrinter = 0;
651 0 : SfxDialogExecutor_Impl* pExecutor = 0;
652 0 : bool bSilent = false;
653 :
654 : // does the function have been called by the user interface or by an API call
655 0 : sal_Bool bIsAPI = rReq.IsAPI();
656 0 : if ( bIsAPI )
657 : {
658 : // the function have been called by the API
659 :
660 : // Should it be visible on the user interface,
661 : // should it launch popup dialogue ?
662 0 : SFX_REQUEST_ARG(rReq, pSilentItem, SfxBoolItem, SID_SILENT, sal_False);
663 0 : bSilent = pSilentItem && pSilentItem->GetValue();
664 : }
665 :
666 : // no help button in dialogs if called from the help window
667 : // (pressing help button would exchange the current page inside the help
668 : // document that is going to be printed!)
669 0 : String aHelpFilterName( DEFINE_CONST_UNICODE("writer_web_HTML_help") );
670 0 : SfxMedium* pMedium = GetViewFrame()->GetObjectShell()->GetMedium();
671 0 : const SfxFilter* pFilter = pMedium ? pMedium->GetFilter() : NULL;
672 0 : sal_Bool bPrintOnHelp = ( pFilter && pFilter->GetFilterName() == aHelpFilterName );
673 :
674 0 : const sal_uInt16 nId = rReq.GetSlot();
675 0 : switch( nId )
676 : {
677 : case SID_PRINTDOC: // display the printer selection and properties dialogue : File > Printā¦
678 : case SID_PRINTDOCDIRECT: // Print the document directly, without displaying the dialogue
679 : {
680 0 : SfxObjectShell* pDoc = GetObjectShell();
681 :
682 : // derived class may decide to abort this
683 0 : if( pDoc == NULL || !pDoc->QuerySlotExecutable( nId ) )
684 : {
685 0 : rReq.SetReturnValue( SfxBoolItem( 0, sal_False ) );
686 : return;
687 : }
688 :
689 0 : if ( !bSilent && pDoc->QueryHiddenInformation( WhenPrinting, NULL ) != RET_YES )
690 : return;
691 :
692 0 : uno::Sequence < beans::PropertyValue > aProps;
693 0 : if ( bIsAPI )
694 : {
695 : // supported properties:
696 : // String PrinterName
697 : // String FileName
698 : // Int16 From
699 : // Int16 To
700 : // In16 Copies
701 : // String RangeText
702 : // bool Selection
703 : // bool Asynchron
704 : // bool Collate
705 : // bool Silent
706 :
707 : // the TransformItems function overwrite aProps
708 0 : TransformItems( nId, *rReq.GetArgs(), aProps, GetInterface()->GetSlot(nId) );
709 :
710 0 : for ( sal_Int32 nProp=0; nProp < aProps.getLength(); ++nProp )
711 : {
712 0 : if ( aProps[nProp].Name == "Copies" )
713 : {
714 0 : aProps[nProp]. Name = rtl::OUString("CopyCount");
715 : }
716 0 : else if ( aProps[nProp].Name == "RangeText" )
717 : {
718 0 : aProps[nProp]. Name = rtl::OUString("Pages");
719 : }
720 0 : else if ( aProps[nProp].Name == "Asynchron" )
721 : {
722 0 : aProps[nProp]. Name = rtl::OUString("Wait");
723 0 : sal_Bool bAsynchron = sal_False;
724 0 : aProps[nProp].Value >>= bAsynchron;
725 0 : aProps[nProp].Value <<= (sal_Bool) (!bAsynchron);
726 : }
727 0 : else if ( aProps[nProp].Name == "Silent" )
728 : {
729 0 : aProps[nProp]. Name = rtl::OUString("MonitorVisible");
730 0 : sal_Bool bPrintSilent = sal_False;
731 0 : aProps[nProp].Value >>= bPrintSilent;
732 0 : aProps[nProp].Value <<= (sal_Bool) (!bPrintSilent);
733 : }
734 : }
735 : }
736 :
737 : // we will add the "PrintSelectionOnly" or "HideHelpButton" properties
738 : // we have to increase the capacity of aProps
739 0 : sal_Int32 nLen = aProps.getLength();
740 0 : aProps.realloc( nLen + 1 );
741 :
742 : // HACK: writer sets the SID_SELECTION item when printing directly and expects
743 : // to get only the selection document in that case (see getSelectionObject)
744 : // however it also reacts to the PrintContent property. We need this distinction here, too,
745 : // else one of the combinations print / print direct and selection / all will not work.
746 : // it would be better if writer handled this internally
747 0 : if( nId == SID_PRINTDOCDIRECT )
748 : {
749 : // should we print only the selection or the whole document
750 0 : SFX_REQUEST_ARG(rReq, pSelectItem, SfxBoolItem, SID_SELECTION, sal_False);
751 0 : sal_Bool bSelection = ( pSelectItem != NULL && pSelectItem->GetValue() );
752 :
753 0 : aProps[nLen].Name = rtl::OUString( "PrintSelectionOnly" );
754 0 : aProps[nLen].Value = makeAny( bSelection );
755 : }
756 : else // if nId == SID_PRINTDOC ; nothing to do with the previous HACK
757 : {
758 : // should the printer selection and properties dialogue display an help button
759 0 : aProps[nLen].Name = rtl::OUString( "HideHelpButton" );
760 0 : aProps[nLen].Value = makeAny( bPrintOnHelp );
761 : }
762 :
763 0 : ExecPrint( aProps, bIsAPI, (nId == SID_PRINTDOCDIRECT) );
764 :
765 : // FIXME: Recording
766 0 : rReq.Done();
767 0 : break;
768 : }
769 : case SID_SETUPPRINTER : // display the printer settings dialogue : File > Printer Settingsā¦
770 : case SID_PRINTER_NAME : // only for recorded macros
771 : {
772 : // get printer and printer settings from the document
773 0 : SfxPrinter *pDocPrinter = GetPrinter(sal_True);
774 :
775 : // look for printer in parameters
776 0 : SFX_REQUEST_ARG( rReq, pPrinterItem, SfxStringItem, SID_PRINTER_NAME, sal_False );
777 0 : if ( pPrinterItem )
778 : {
779 : // use PrinterName parameter to create a printer
780 0 : pPrinter = new SfxPrinter( pDocPrinter->GetOptions().Clone(), ((const SfxStringItem*) pPrinterItem)->GetValue() );
781 :
782 : // if printer is unknown, it can't be used - now printer from document will be used
783 0 : if ( !pPrinter->IsKnown() )
784 0 : DELETEZ(pPrinter);
785 : }
786 :
787 0 : if ( SID_PRINTER_NAME == nId )
788 : {
789 : // just set a recorded printer name
790 0 : if ( pPrinter )
791 0 : SetPrinter( pPrinter, SFX_PRINTER_PRINTER );
792 : return;
793 : }
794 :
795 : // no PrinterName parameter in ItemSet or the PrinterName points to an unknown printer
796 0 : if ( !pPrinter )
797 : // use default printer from document
798 0 : pPrinter = pDocPrinter;
799 :
800 0 : if( !pPrinter || !pPrinter->IsValid() )
801 : {
802 : // no valid printer either in ItemSet or at the document
803 0 : if ( !bSilent )
804 0 : ErrorBox( NULL, WB_OK | WB_DEF_OK, SfxResId(STR_NODEFPRINTER).toString() ).Execute();
805 :
806 0 : rReq.SetReturnValue(SfxBoolItem(0,sal_False));
807 :
808 0 : break;
809 : }
810 :
811 : // FIXME: printer isn't used for printing anymore!
812 0 : if( pPrinter->IsPrinting() )
813 : {
814 : // if printer is busy, abort configuration
815 0 : if ( !bSilent )
816 0 : InfoBox( NULL, SfxResId(STR_ERROR_PRINTER_BUSY).toString() ).Execute();
817 0 : rReq.SetReturnValue(SfxBoolItem(0,sal_False));
818 :
819 : return;
820 : }
821 :
822 : // if no arguments are given, retrieve them from a dialog
823 0 : if ( !bIsAPI )
824 : {
825 : // PrinterDialog needs a temporary printer
826 0 : SfxPrinter* pDlgPrinter = pPrinter->Clone();
827 0 : nDialogRet = 0;
828 :
829 : // execute PrinterSetupDialog
830 0 : PrinterSetupDialog* pPrintSetupDlg = new PrinterSetupDialog( GetWindow() );
831 :
832 0 : if (pImp->m_bHasPrintOptions && HasPrintOptionsPage())
833 : {
834 : // additional controls for dialog
835 0 : pExecutor = new SfxDialogExecutor_Impl( this, pPrintSetupDlg );
836 0 : if ( bPrintOnHelp )
837 0 : pExecutor->DisableHelp();
838 0 : pPrintSetupDlg->SetOptionsHdl( pExecutor->GetLink() );
839 : }
840 :
841 0 : pPrintSetupDlg->SetPrinter( pDlgPrinter );
842 0 : nDialogRet = pPrintSetupDlg->Execute();
843 :
844 0 : if ( pExecutor && pExecutor->GetOptions() )
845 : {
846 0 : if ( nDialogRet == RET_OK )
847 : // remark: have to be recorded if possible!
848 0 : pDlgPrinter->SetOptions( *pExecutor->GetOptions() );
849 : else
850 : {
851 0 : pPrinter->SetOptions( *pExecutor->GetOptions() );
852 0 : SetPrinter( pPrinter, SFX_PRINTER_OPTIONS );
853 : }
854 : }
855 :
856 0 : DELETEZ( pPrintSetupDlg );
857 :
858 : // no recording of PrinterSetup except printer name (is printer dependent)
859 0 : rReq.Ignore();
860 :
861 0 : if ( nDialogRet == RET_OK )
862 : {
863 0 : if ( pPrinter->GetName() != pDlgPrinter->GetName() )
864 : {
865 : // user has changed the printer -> macro recording
866 0 : SfxRequest aReq( GetViewFrame(), SID_PRINTER_NAME );
867 0 : aReq.AppendItem( SfxStringItem( SID_PRINTER_NAME, pDlgPrinter->GetName() ) );
868 0 : aReq.Done();
869 : }
870 :
871 : // take the changes made in the dialog
872 0 : pPrinter = SetPrinter_Impl( pDlgPrinter );
873 :
874 : // forget new printer, it was taken over (as pPrinter) or deleted
875 0 : pDlgPrinter = NULL;
876 :
877 : }
878 : else
879 : {
880 : // PrinterDialog is used to transfer information on printing,
881 : // so it will only be deleted here if dialog was cancelled
882 0 : DELETEZ( pDlgPrinter );
883 0 : rReq.Ignore();
884 0 : if ( SID_PRINTDOC == nId )
885 0 : rReq.SetReturnValue(SfxBoolItem(0,sal_False));
886 : }
887 : }
888 : }
889 0 : }
890 : }
891 :
892 : // Turn on optimazation again.
893 : #ifdef _MSC_VER
894 : #pragma optimize ( "", on )
895 : #endif
896 :
897 : //--------------------------------------------------------------------
898 :
899 0 : SfxPrinter* SfxViewShell::GetPrinter( sal_Bool /*bCreate*/ )
900 : {
901 0 : return 0;
902 : }
903 :
904 : //--------------------------------------------------------------------
905 :
906 0 : sal_uInt16 SfxViewShell::SetPrinter( SfxPrinter* /*pNewPrinter*/, sal_uInt16 /*nDiffFlags*/, bool )
907 : {
908 0 : return 0;
909 : }
910 :
911 : //--------------------------------------------------------------------
912 :
913 0 : SfxTabPage* SfxViewShell::CreatePrintOptionsPage
914 : (
915 : Window* /*pParent*/,
916 : const SfxItemSet& /*rOptions*/
917 : )
918 : {
919 0 : return 0;
920 : }
921 :
922 0 : bool SfxViewShell::HasPrintOptionsPage() const
923 : {
924 0 : return false;
925 : }
926 :
927 0 : JobSetup SfxViewShell::GetJobSetup() const
928 : {
929 0 : return JobSetup();
930 : }
931 :
932 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|