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