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 10017 : 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 0 : SFX_APP()->NotifyEvent( SfxEventHint(SFX_EVENT_PRINTDOC, GlobalEventConfig::GetEventName( STR_EVENT_PRINTDOC ), mpObjectShell ) );
324 : // FIXME: how to get all print options incl. AdditionalOptions easily?
325 0 : uno::Sequence < beans::PropertyValue > aOpts;
326 0 : mpObjectShell->Broadcast( SfxPrintingHint( view::PrintableState_JOB_STARTED, aOpts ) );
327 : }
328 0 : }
329 :
330 0 : void SfxPrinterController::jobFinished( com::sun::star::view::PrintableState nState )
331 : {
332 0 : if ( mpObjectShell )
333 : {
334 0 : bool bCopyJobSetup = false;
335 0 : mpObjectShell->Broadcast( SfxPrintingHint( nState ) );
336 0 : switch ( nState )
337 : {
338 : case view::PrintableState_JOB_FAILED :
339 : {
340 : // "real" problem (not simply printing cancelled by user)
341 0 : rtl::OUString aMsg( SfxResId(STR_NOSTARTPRINTER).toString() );
342 0 : if ( !m_bApi )
343 0 : ErrorBox( mpViewShell->GetWindow(), WB_OK | WB_DEF_OK, aMsg ).Execute();
344 : // intentionally no break
345 : }
346 : case view::PrintableState_JOB_ABORTED :
347 : {
348 : // printing not successful, reset DocInfo
349 0 : uno::Reference<document::XDocumentProperties> xDocProps(mpObjectShell->getDocProperties());
350 0 : xDocProps->setPrintedBy(m_aLastPrintedBy);
351 0 : xDocProps->setPrintDate(m_aLastPrinted);
352 0 : break;
353 : }
354 :
355 : case view::PrintableState_JOB_SPOOLED :
356 : case view::PrintableState_JOB_COMPLETED :
357 : {
358 0 : SfxBindings& rBind = mpViewShell->GetViewFrame()->GetBindings();
359 0 : rBind.Invalidate( SID_PRINTDOC );
360 0 : rBind.Invalidate( SID_PRINTDOCDIRECT );
361 0 : rBind.Invalidate( SID_SETUPPRINTER );
362 0 : bCopyJobSetup = ! m_bTempPrinter;
363 0 : break;
364 : }
365 :
366 : default:
367 0 : break;
368 : }
369 :
370 0 : if( bCopyJobSetup && mpViewShell )
371 : {
372 : // #i114306#
373 : // Note: this possibly creates a printer that gets immediately replaced
374 : // by a new one. The reason for this is that otherwise we would not get
375 : // the printer's SfxItemSet here to copy. Awkward, but at the moment there is no
376 : // other way here to get the item set.
377 0 : SfxPrinter* pDocPrt = mpViewShell->GetPrinter(sal_True);
378 0 : if( pDocPrt )
379 : {
380 0 : if( pDocPrt->GetName() == getPrinter()->GetName() )
381 0 : pDocPrt->SetJobSetup( getPrinter()->GetJobSetup() );
382 : else
383 : {
384 0 : SfxPrinter* pNewPrt = new SfxPrinter( pDocPrt->GetOptions().Clone(), getPrinter()->GetName() );
385 0 : pNewPrt->SetJobSetup( getPrinter()->GetJobSetup() );
386 0 : mpViewShell->SetPrinter( pNewPrt, SFX_PRINTER_PRINTER | SFX_PRINTER_JOBSETUP );
387 : }
388 : }
389 : }
390 :
391 0 : if ( m_bNeedsChange )
392 0 : mpObjectShell->EnableSetModified( m_bOrigStatus );
393 :
394 0 : if ( mpViewShell )
395 : {
396 0 : mpViewShell->pImp->m_pPrinterController.reset();
397 : }
398 : }
399 0 : }
400 :
401 : //====================================================================
402 :
403 : class SfxDialogExecutor_Impl
404 :
405 : /* [Description]
406 :
407 : An instance of this class is created for the life span of the
408 : printer dialogue, to create in its click handler for the additions by the
409 : virtual method of the derived SfxViewShell generated print options dialogue
410 : and to cache the options set there as SfxItemSet.
411 : */
412 :
413 : {
414 : private:
415 : SfxViewShell* _pViewSh;
416 : PrinterSetupDialog* _pSetupParent;
417 : SfxItemSet* _pOptions;
418 : sal_Bool _bHelpDisabled;
419 :
420 : DECL_LINK( Execute, void * );
421 :
422 : public:
423 : SfxDialogExecutor_Impl( SfxViewShell* pViewSh, PrinterSetupDialog* pParent );
424 : ~SfxDialogExecutor_Impl() { delete _pOptions; }
425 :
426 0 : Link GetLink() const { return LINK( this, SfxDialogExecutor_Impl, Execute); }
427 0 : const SfxItemSet* GetOptions() const { return _pOptions; }
428 0 : void DisableHelp() { _bHelpDisabled = sal_True; }
429 : };
430 :
431 : //--------------------------------------------------------------------
432 :
433 0 : SfxDialogExecutor_Impl::SfxDialogExecutor_Impl( SfxViewShell* pViewSh, PrinterSetupDialog* pParent ) :
434 :
435 : _pViewSh ( pViewSh ),
436 : _pSetupParent ( pParent ),
437 : _pOptions ( NULL ),
438 0 : _bHelpDisabled ( sal_False )
439 :
440 : {
441 0 : }
442 :
443 : //--------------------------------------------------------------------
444 :
445 0 : IMPL_LINK_NOARG(SfxDialogExecutor_Impl, Execute)
446 : {
447 : // Options noted locally
448 0 : if ( !_pOptions )
449 : {
450 : DBG_ASSERT( _pSetupParent, "no dialog parent" );
451 0 : if( _pSetupParent )
452 0 : _pOptions = ( (SfxPrinter*)_pSetupParent->GetPrinter() )->GetOptions().Clone();
453 : }
454 :
455 : // Create Dialog
456 : SfxPrintOptionsDialog* pDlg = new SfxPrintOptionsDialog( static_cast<Window*>(_pSetupParent),
457 0 : _pViewSh, _pOptions );
458 0 : if ( _bHelpDisabled )
459 0 : pDlg->DisableHelp();
460 0 : if ( pDlg->Execute() == RET_OK )
461 : {
462 0 : delete _pOptions;
463 0 : _pOptions = pDlg->GetOptions().Clone();
464 :
465 : }
466 0 : delete pDlg;
467 :
468 0 : return 0;
469 : }
470 :
471 : //-------------------------------------------------------------------------
472 :
473 0 : SfxPrinter* SfxViewShell::SetPrinter_Impl( SfxPrinter *pNewPrinter )
474 :
475 :
476 : /* Internal method for setting the differences between 'pNewPrinter' to the
477 : current printer. pNewPrinter is either taken over or deleted.
478 : */
479 :
480 : {
481 : // get current Printer
482 0 : SfxPrinter *pDocPrinter = GetPrinter();
483 :
484 : // Evaluate Printer Options
485 0 : bool bOriToDoc = false;
486 0 : bool bSizeToDoc = false;
487 0 : if ( &pDocPrinter->GetOptions() )
488 : {
489 0 : sal_uInt16 nWhich = GetPool().GetWhich(SID_PRINTER_CHANGESTODOC);
490 0 : const SfxFlagItem *pFlagItem = 0;
491 0 : pDocPrinter->GetOptions().GetItemState( nWhich, sal_False, (const SfxPoolItem**) &pFlagItem );
492 0 : bOriToDoc = pFlagItem ? (pFlagItem->GetValue() & SFX_PRINTER_CHG_ORIENTATION) : sal_False;
493 0 : bSizeToDoc = pFlagItem ? (pFlagItem->GetValue() & SFX_PRINTER_CHG_SIZE) : sal_False;
494 : }
495 :
496 : // Determine the previous format and size
497 0 : Orientation eOldOri = pDocPrinter->GetOrientation();
498 0 : Size aOldPgSz = pDocPrinter->GetPaperSizePixel();
499 :
500 : // Determine the new format and size
501 0 : Orientation eNewOri = pNewPrinter->GetOrientation();
502 0 : Size aNewPgSz = pNewPrinter->GetPaperSizePixel();
503 :
504 : // Determine the changes in page format
505 0 : sal_Bool bOriChg = (eOldOri != eNewOri) && bOriToDoc;
506 0 : sal_Bool bPgSzChg = ( aOldPgSz.Height() !=
507 0 : ( bOriChg ? aNewPgSz.Width() : aNewPgSz.Height() ) ||
508 0 : aOldPgSz.Width() !=
509 0 : ( bOriChg ? aNewPgSz.Height() : aNewPgSz.Width() ) ) &&
510 0 : bSizeToDoc;
511 :
512 : // Message and Flags for page format, summaries changes
513 0 : rtl::OUString aMsg;
514 0 : sal_uInt16 nNewOpt=0;
515 0 : if( bOriChg && bPgSzChg )
516 : {
517 0 : aMsg = SfxResId(STR_PRINT_NEWORISIZE).toString();
518 0 : nNewOpt = SFX_PRINTER_CHG_ORIENTATION | SFX_PRINTER_CHG_SIZE;
519 : }
520 0 : else if (bOriChg )
521 : {
522 0 : aMsg = SfxResId(STR_PRINT_NEWORI).toString();
523 0 : nNewOpt = SFX_PRINTER_CHG_ORIENTATION;
524 : }
525 0 : else if (bPgSzChg)
526 : {
527 0 : aMsg = SfxResId(STR_PRINT_NEWSIZE).toString();
528 0 : nNewOpt = SFX_PRINTER_CHG_SIZE;
529 : }
530 :
531 : // Summaries in this variable what has been changed.
532 0 : sal_uInt16 nChangedFlags = 0;
533 :
534 : // Ask if possible, if page format should be taken over from printer.
535 0 : if ( ( bOriChg || bPgSzChg ) &&
536 0 : RET_YES == QueryBox(0, WB_YES_NO | WB_DEF_OK, aMsg).Execute() )
537 : // Flags wich changes for <SetPrinter(SfxPrinter*)> are maintained
538 0 : nChangedFlags |= nNewOpt;
539 :
540 : // For the MAC to have its "temporary of class String" in next if()
541 0 : String aTempPrtName = pNewPrinter->GetName();
542 0 : String aDocPrtName = pDocPrinter->GetName();
543 :
544 : // Was the printer selection changed from Default to Specific
545 : // or the other way around?
546 0 : if ( (aTempPrtName != aDocPrtName) || (pDocPrinter->IsDefPrinter() != pNewPrinter->IsDefPrinter()) )
547 : {
548 0 : nChangedFlags |= SFX_PRINTER_PRINTER|SFX_PRINTER_JOBSETUP;
549 0 : pDocPrinter = pNewPrinter;
550 : }
551 : else
552 : {
553 : // Compare extra options
554 0 : if ( ! (pNewPrinter->GetOptions() == pDocPrinter->GetOptions()) )
555 : {
556 : // Option have changed
557 0 : pDocPrinter->SetOptions( pNewPrinter->GetOptions() );
558 0 : nChangedFlags |= SFX_PRINTER_OPTIONS;
559 : }
560 :
561 : // Compare JobSetups
562 0 : JobSetup aNewJobSetup = pNewPrinter->GetJobSetup();
563 0 : JobSetup aOldJobSetup = pDocPrinter->GetJobSetup();
564 0 : if ( aNewJobSetup != aOldJobSetup )
565 : {
566 0 : nChangedFlags |= SFX_PRINTER_JOBSETUP;
567 : }
568 :
569 : // Keep old changed Printer.
570 0 : pDocPrinter->SetPrinterProps( pNewPrinter );
571 0 : delete pNewPrinter;
572 : }
573 :
574 0 : if ( 0 != nChangedFlags )
575 : // SetPrinter will delete the old printer if it changes
576 0 : SetPrinter( pDocPrinter, nChangedFlags );
577 0 : return pDocPrinter;
578 : }
579 :
580 : //-------------------------------------------------------------------------
581 : // Sadly enough the problem arises with WIN32 that nothing is printed when
582 : // SID_PRINTDOCDIRECT auflaueft. At the moment the only known solution in this
583 : // case is to turn off the optimazation.
584 : #ifdef _MSC_VER
585 : #pragma optimize ( "", off )
586 : #endif
587 :
588 0 : void SfxViewShell::ExecPrint( const uno::Sequence < beans::PropertyValue >& rProps, sal_Bool bIsAPI, sal_Bool bIsDirect )
589 : {
590 : // get the current selection; our controller should know it
591 0 : Reference< frame::XController > xController( GetController() );
592 0 : Reference< view::XSelectionSupplier > xSupplier( xController, UNO_QUERY );
593 :
594 0 : Any aSelection;
595 0 : if( xSupplier.is() )
596 0 : aSelection = xSupplier->getSelection();
597 : else
598 0 : aSelection <<= GetObjectShell()->GetModel();
599 0 : Any aComplete( makeAny( GetObjectShell()->GetModel() ) );
600 0 : Any aViewProp( makeAny( xController ) );
601 0 : boost::shared_ptr<Printer> aPrt;
602 :
603 0 : const beans::PropertyValue* pVal = rProps.getConstArray();
604 0 : for( sal_Int32 i = 0; i < rProps.getLength(); i++ )
605 : {
606 0 : if ( pVal[i].Name == "PrinterName" )
607 : {
608 0 : rtl::OUString aPrinterName;
609 0 : pVal[i].Value >>= aPrinterName;
610 0 : aPrt.reset( new Printer( aPrinterName ) );
611 0 : break;
612 : }
613 : }
614 :
615 : boost::shared_ptr<vcl::PrinterController> pController( new SfxPrinterController(
616 : aPrt,
617 : aComplete,
618 : aSelection,
619 : aViewProp,
620 0 : GetRenderable(),
621 : bIsAPI,
622 : bIsDirect,
623 : this,
624 : rProps
625 0 : ) );
626 0 : pImp->m_pPrinterController = pController;
627 :
628 0 : SfxObjectShell *pObjShell = GetObjectShell();
629 : pController->setValue( rtl::OUString( "JobName" ),
630 0 : makeAny( rtl::OUString( pObjShell->GetTitle(0) ) ) );
631 :
632 : // FIXME: job setup
633 0 : SfxPrinter* pDocPrt = GetPrinter(sal_False);
634 0 : JobSetup aJobSetup = pDocPrt ? pDocPrt->GetJobSetup() : GetJobSetup();
635 0 : if( bIsDirect )
636 : aJobSetup.SetValue( String( "IsQuickJob" ),
637 0 : String( "true" ) );
638 :
639 0 : Printer::PrintJob( pController, aJobSetup );
640 0 : }
641 :
642 0 : Printer* SfxViewShell::GetActivePrinter() const
643 : {
644 : return (pImp->m_pPrinterController)
645 0 : ? pImp->m_pPrinterController->getPrinter().get() : 0;
646 : }
647 :
648 0 : void SfxViewShell::ExecPrint_Impl( SfxRequest &rReq )
649 : {
650 0 : sal_uInt16 nDialogRet = RET_CANCEL;
651 0 : SfxPrinter* pPrinter = 0;
652 0 : SfxDialogExecutor_Impl* pExecutor = 0;
653 0 : bool bSilent = false;
654 :
655 : // does the function have been called by the user interface or by an API call
656 0 : sal_Bool bIsAPI = rReq.GetArgs() && rReq.GetArgs()->Count();
657 0 : if ( bIsAPI )
658 : {
659 : // the function have been called by the API
660 :
661 : // Should it be visible on the user interface,
662 : // should it launch popup dialogue ?
663 0 : SFX_REQUEST_ARG(rReq, pSilentItem, SfxBoolItem, SID_SILENT, sal_False);
664 0 : bSilent = pSilentItem && pSilentItem->GetValue();
665 : }
666 :
667 : // no help button in dialogs if called from the help window
668 : // (pressing help button would exchange the current page inside the help
669 : // document that is going to be printed!)
670 0 : String aHelpFilterName( DEFINE_CONST_UNICODE("writer_web_HTML_help") );
671 0 : SfxMedium* pMedium = GetViewFrame()->GetObjectShell()->GetMedium();
672 0 : const SfxFilter* pFilter = pMedium ? pMedium->GetFilter() : NULL;
673 0 : sal_Bool bPrintOnHelp = ( pFilter && pFilter->GetFilterName() == aHelpFilterName );
674 :
675 0 : const sal_uInt16 nId = rReq.GetSlot();
676 0 : switch( nId )
677 : {
678 : case SID_PRINTDOC: // display the printer selection and properties dialogue : File > Printā¦
679 : case SID_PRINTDOCDIRECT: // Print the document directly, without displaying the dialogue
680 : {
681 0 : SfxObjectShell* pDoc = GetObjectShell();
682 :
683 : // derived class may decide to abort this
684 0 : if( pDoc == NULL || !pDoc->QuerySlotExecutable( nId ) )
685 : {
686 0 : rReq.SetReturnValue( SfxBoolItem( 0, sal_False ) );
687 : return;
688 : }
689 :
690 0 : if ( !bSilent && pDoc->QueryHiddenInformation( WhenPrinting, NULL ) != RET_YES )
691 : return;
692 :
693 0 : uno::Sequence < beans::PropertyValue > aProps;
694 0 : if ( bIsAPI )
695 : {
696 : // supported properties:
697 : // String PrinterName
698 : // String FileName
699 : // Int16 From
700 : // Int16 To
701 : // In16 Copies
702 : // String RangeText
703 : // bool Selection
704 : // bool Asynchron
705 : // bool Collate
706 : // bool Silent
707 :
708 : // the TransformItems function overwrite aProps
709 0 : TransformItems( nId, *rReq.GetArgs(), aProps, GetInterface()->GetSlot(nId) );
710 :
711 0 : for ( sal_Int32 nProp=0; nProp < aProps.getLength(); ++nProp )
712 : {
713 0 : if ( aProps[nProp].Name == "Copies" )
714 : {
715 0 : aProps[nProp]. Name = rtl::OUString("CopyCount");
716 : }
717 0 : else if ( aProps[nProp].Name == "RangeText" )
718 : {
719 0 : aProps[nProp]. Name = rtl::OUString("Pages");
720 : }
721 0 : else if ( aProps[nProp].Name == "Asynchron" )
722 : {
723 0 : aProps[nProp]. Name = rtl::OUString("Wait");
724 0 : sal_Bool bAsynchron = sal_False;
725 0 : aProps[nProp].Value >>= bAsynchron;
726 0 : aProps[nProp].Value <<= (sal_Bool) (!bAsynchron);
727 : }
728 0 : else if ( aProps[nProp].Name == "Silent" )
729 : {
730 0 : aProps[nProp]. Name = rtl::OUString("MonitorVisible");
731 0 : sal_Bool bPrintSilent = sal_False;
732 0 : aProps[nProp].Value >>= bPrintSilent;
733 0 : aProps[nProp].Value <<= (sal_Bool) (!bPrintSilent);
734 : }
735 : }
736 : }
737 :
738 : // we will add the "PrintSelectionOnly" or "HideHelpButton" properties
739 : // we have to increase the capacity of aProps
740 0 : sal_Int32 nLen = aProps.getLength();
741 0 : aProps.realloc( nLen + 1 );
742 :
743 : // HACK: writer sets the SID_SELECTION item when printing directly and expects
744 : // to get only the selection document in that case (see getSelectionObject)
745 : // however it also reacts to the PrintContent property. We need this distinction here, too,
746 : // else one of the combinations print / print direct and selection / all will not work.
747 : // it would be better if writer handled this internally
748 0 : if( nId == SID_PRINTDOCDIRECT )
749 : {
750 : // should we print only the selection or the whole document
751 0 : SFX_REQUEST_ARG(rReq, pSelectItem, SfxBoolItem, SID_SELECTION, sal_False);
752 0 : sal_Bool bSelection = ( pSelectItem != NULL && pSelectItem->GetValue() );
753 :
754 0 : aProps[nLen].Name = rtl::OUString( "PrintSelectionOnly" );
755 0 : aProps[nLen].Value = makeAny( bSelection );
756 : }
757 : else // if nId == SID_PRINTDOC ; nothing to do with the previous HACK
758 : {
759 : // should the printer selection and properties dialogue display an help button
760 0 : aProps[nLen].Name = rtl::OUString( "HideHelpButton" );
761 0 : aProps[nLen].Value = makeAny( bPrintOnHelp );
762 : }
763 :
764 0 : ExecPrint( aProps, bIsAPI, (nId == SID_PRINTDOCDIRECT) );
765 :
766 : // FIXME: Recording
767 0 : rReq.Done();
768 0 : break;
769 : }
770 : case SID_SETUPPRINTER : // display the printer settings dialogue : File > Printer Settingsā¦
771 : case SID_PRINTER_NAME : // only for recorded macros
772 : {
773 : // get printer and printer settings from the document
774 0 : SfxPrinter *pDocPrinter = GetPrinter(sal_True);
775 :
776 : // look for printer in parameters
777 0 : SFX_REQUEST_ARG( rReq, pPrinterItem, SfxStringItem, SID_PRINTER_NAME, sal_False );
778 0 : if ( pPrinterItem )
779 : {
780 : // use PrinterName parameter to create a printer
781 0 : pPrinter = new SfxPrinter( pDocPrinter->GetOptions().Clone(), ((const SfxStringItem*) pPrinterItem)->GetValue() );
782 :
783 : // if printer is unknown, it can't be used - now printer from document will be used
784 0 : if ( !pPrinter->IsKnown() )
785 0 : DELETEZ(pPrinter);
786 : }
787 :
788 0 : if ( SID_PRINTER_NAME == nId )
789 : {
790 : // just set a recorded printer name
791 0 : if ( pPrinter )
792 0 : SetPrinter( pPrinter, SFX_PRINTER_PRINTER );
793 : return;
794 : }
795 :
796 : // no PrinterName parameter in ItemSet or the PrinterName points to an unknown printer
797 0 : if ( !pPrinter )
798 : // use default printer from document
799 0 : pPrinter = pDocPrinter;
800 :
801 0 : if( !pPrinter || !pPrinter->IsValid() )
802 : {
803 : // no valid printer either in ItemSet or at the document
804 0 : if ( !bSilent )
805 0 : ErrorBox( NULL, WB_OK | WB_DEF_OK, SfxResId(STR_NODEFPRINTER).toString() ).Execute();
806 :
807 0 : rReq.SetReturnValue(SfxBoolItem(0,sal_False));
808 :
809 0 : break;
810 : }
811 :
812 : // FIXME: printer isn't used for printing anymore!
813 0 : if( pPrinter->IsPrinting() )
814 : {
815 : // if printer is busy, abort configuration
816 0 : if ( !bSilent )
817 0 : InfoBox( NULL, SfxResId(STR_ERROR_PRINTER_BUSY).toString() ).Execute();
818 0 : rReq.SetReturnValue(SfxBoolItem(0,sal_False));
819 :
820 : return;
821 : }
822 :
823 : // if no arguments are given, retrieve them from a dialog
824 0 : if ( !bIsAPI )
825 : {
826 : // PrinterDialog needs a temporary printer
827 0 : SfxPrinter* pDlgPrinter = pPrinter->Clone();
828 0 : nDialogRet = 0;
829 :
830 : // execute PrinterSetupDialog
831 0 : PrinterSetupDialog* pPrintSetupDlg = new PrinterSetupDialog( GetWindow() );
832 :
833 0 : if (pImp->m_bHasPrintOptions && HasPrintOptionsPage())
834 : {
835 : // additional controls for dialog
836 0 : pExecutor = new SfxDialogExecutor_Impl( this, pPrintSetupDlg );
837 0 : if ( bPrintOnHelp )
838 0 : pExecutor->DisableHelp();
839 0 : pPrintSetupDlg->SetOptionsHdl( pExecutor->GetLink() );
840 : }
841 :
842 0 : pPrintSetupDlg->SetPrinter( pDlgPrinter );
843 0 : nDialogRet = pPrintSetupDlg->Execute();
844 :
845 0 : if ( pExecutor && pExecutor->GetOptions() )
846 : {
847 0 : if ( nDialogRet == RET_OK )
848 : // remark: have to be recorded if possible!
849 0 : pDlgPrinter->SetOptions( *pExecutor->GetOptions() );
850 : else
851 : {
852 0 : pPrinter->SetOptions( *pExecutor->GetOptions() );
853 0 : SetPrinter( pPrinter, SFX_PRINTER_OPTIONS );
854 : }
855 : }
856 :
857 0 : DELETEZ( pPrintSetupDlg );
858 :
859 : // no recording of PrinterSetup except printer name (is printer dependent)
860 0 : rReq.Ignore();
861 :
862 0 : if ( nDialogRet == RET_OK )
863 : {
864 0 : if ( pPrinter->GetName() != pDlgPrinter->GetName() )
865 : {
866 : // user has changed the printer -> macro recording
867 0 : SfxRequest aReq( GetViewFrame(), SID_PRINTER_NAME );
868 0 : aReq.AppendItem( SfxStringItem( SID_PRINTER_NAME, pDlgPrinter->GetName() ) );
869 0 : aReq.Done();
870 : }
871 :
872 : // take the changes made in the dialog
873 0 : pPrinter = SetPrinter_Impl( pDlgPrinter );
874 :
875 : // forget new printer, it was taken over (as pPrinter) or deleted
876 0 : pDlgPrinter = NULL;
877 :
878 : }
879 : else
880 : {
881 : // PrinterDialog is used to transfer information on printing,
882 : // so it will only be deleted here if dialog was cancelled
883 0 : DELETEZ( pDlgPrinter );
884 0 : rReq.Ignore();
885 0 : if ( SID_PRINTDOC == nId )
886 0 : rReq.SetReturnValue(SfxBoolItem(0,sal_False));
887 : }
888 : }
889 : }
890 0 : }
891 : }
892 :
893 : // Turn on optimazation again.
894 : #ifdef _MSC_VER
895 : #pragma optimize ( "", on )
896 : #endif
897 :
898 : //--------------------------------------------------------------------
899 :
900 0 : SfxPrinter* SfxViewShell::GetPrinter( sal_Bool /*bCreate*/ )
901 : {
902 0 : return 0;
903 : }
904 :
905 : //--------------------------------------------------------------------
906 :
907 0 : sal_uInt16 SfxViewShell::SetPrinter( SfxPrinter* /*pNewPrinter*/, sal_uInt16 /*nDiffFlags*/, bool )
908 : {
909 0 : return 0;
910 : }
911 :
912 : //--------------------------------------------------------------------
913 :
914 0 : SfxTabPage* SfxViewShell::CreatePrintOptionsPage
915 : (
916 : Window* /*pParent*/,
917 : const SfxItemSet& /*rOptions*/
918 : )
919 : {
920 0 : return 0;
921 : }
922 :
923 0 : bool SfxViewShell::HasPrintOptionsPage() const
924 : {
925 0 : return false;
926 : }
927 :
928 0 : JobSetup SfxViewShell::GetJobSetup() const
929 : {
930 0 : return JobSetup();
931 : }
932 :
933 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|