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/layout.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 : #include <boost/scoped_ptr.hpp>
50 :
51 : #include "view.hrc"
52 : #include "helpid.hrc"
53 :
54 : using namespace com::sun::star;
55 : using namespace com::sun::star::uno;
56 :
57 : class SfxPrinterController : public vcl::PrinterController, public SfxListener
58 : {
59 : Any maCompleteSelection;
60 : Any maSelection;
61 : Reference< view::XRenderable > mxRenderable;
62 : mutable Printer* mpLastPrinter;
63 : mutable Reference<awt::XDevice> mxDevice;
64 : SfxViewShell* mpViewShell;
65 : SfxObjectShell* mpObjectShell;
66 : bool m_bOrigStatus;
67 : bool m_bNeedsChange;
68 : bool m_bApi;
69 : bool m_bTempPrinter;
70 : util::DateTime m_aLastPrinted;
71 : OUString m_aLastPrintedBy;
72 :
73 : Sequence< beans::PropertyValue > getMergedOptions() const;
74 : const Any& getSelectionObject() const;
75 :
76 : public:
77 : SfxPrinterController( const boost::shared_ptr<Printer>& i_rPrinter,
78 : const Any& i_rComplete,
79 : const Any& i_rSelection,
80 : const Any& i_rViewProp,
81 : const Reference< view::XRenderable >& i_xRender,
82 : bool i_bApi, bool i_bDirect,
83 : SfxViewShell* pView,
84 : const uno::Sequence< beans::PropertyValue >& rProps
85 : );
86 :
87 : virtual ~SfxPrinterController();
88 : virtual void Notify( SfxBroadcaster&, const SfxHint& ) SAL_OVERRIDE;
89 :
90 : virtual int getPageCount() const SAL_OVERRIDE;
91 : virtual Sequence< beans::PropertyValue > getPageParameters( int i_nPage ) const SAL_OVERRIDE;
92 : virtual void printPage( int i_nPage ) const SAL_OVERRIDE;
93 : virtual void jobStarted() SAL_OVERRIDE;
94 : virtual void jobFinished( com::sun::star::view::PrintableState ) SAL_OVERRIDE;
95 : };
96 :
97 0 : SfxPrinterController::SfxPrinterController( const boost::shared_ptr<Printer>& i_rPrinter,
98 : const Any& i_rComplete,
99 : const Any& i_rSelection,
100 : const Any& i_rViewProp,
101 : const Reference< view::XRenderable >& i_xRender,
102 : bool i_bApi, bool i_bDirect,
103 : SfxViewShell* pView,
104 : const uno::Sequence< beans::PropertyValue >& rProps
105 : )
106 : : PrinterController( i_rPrinter)
107 : , maCompleteSelection( i_rComplete )
108 : , maSelection( i_rSelection )
109 : , mxRenderable( i_xRender )
110 : , mpLastPrinter( NULL )
111 : , mpViewShell( pView )
112 : , mpObjectShell(0)
113 : , m_bOrigStatus( false )
114 : , m_bNeedsChange( false )
115 : , m_bApi(i_bApi)
116 0 : , m_bTempPrinter( i_rPrinter.get() != NULL )
117 : {
118 0 : if ( mpViewShell )
119 : {
120 0 : StartListening( *mpViewShell );
121 0 : mpObjectShell = mpViewShell->GetObjectShell();
122 0 : StartListening( *mpObjectShell );
123 : }
124 :
125 : // initialize extra ui options
126 0 : if( mxRenderable.is() )
127 : {
128 0 : for (sal_Int32 nProp=0; nProp < rProps.getLength(); ++nProp)
129 0 : setValue( rProps[nProp].Name, rProps[nProp].Value );
130 :
131 0 : Sequence< beans::PropertyValue > aRenderOptions( 3 );
132 0 : aRenderOptions[0].Name = "ExtraPrintUIOptions";
133 0 : aRenderOptions[1].Name = "View" ;
134 0 : aRenderOptions[1].Value = i_rViewProp;
135 0 : aRenderOptions[2].Name = "IsPrinter";
136 0 : aRenderOptions[2].Value <<= sal_True;
137 : try
138 : {
139 0 : Sequence< beans::PropertyValue > aRenderParms( mxRenderable->getRenderer( 0 , getSelectionObject(), aRenderOptions ) );
140 0 : int nProps = aRenderParms.getLength();
141 0 : for( int i = 0; i < nProps; i++ )
142 : {
143 0 : if ( aRenderParms[i].Name == "ExtraPrintUIOptions" )
144 : {
145 0 : Sequence< beans::PropertyValue > aUIProps;
146 0 : aRenderParms[i].Value >>= aUIProps;
147 0 : setUIOptions( aUIProps );
148 : }
149 0 : else if( aRenderParms[i].Name == "NUp" )
150 : {
151 0 : setValue( aRenderParms[i].Name, aRenderParms[i].Value );
152 : }
153 0 : }
154 : }
155 0 : catch( lang::IllegalArgumentException& )
156 : {
157 : // the first renderer should always be available for the UI options,
158 : // but catch the exception to be safe
159 0 : }
160 : }
161 :
162 : // set some job parameters
163 0 : setValue( OUString( "IsApi" ), makeAny( i_bApi ) );
164 0 : setValue( OUString( "IsDirect" ), makeAny( i_bDirect ) );
165 0 : setValue( OUString( "IsPrinter" ), makeAny( sal_True ) );
166 0 : setValue( OUString( "View" ), i_rViewProp );
167 0 : }
168 :
169 0 : void SfxPrinterController::Notify( SfxBroadcaster& , const SfxHint& rHint )
170 : {
171 0 : const SfxSimpleHint* pSimpleHint = dynamic_cast<const SfxSimpleHint*>(&rHint);
172 0 : if ( pSimpleHint )
173 : {
174 0 : if ( pSimpleHint->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 : SfxGetpApp()->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 : MessageDialog(mpViewShell->GetWindow(), 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(const_cast<SfxDialogExecutor_Impl*>(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 = static_cast<SfxPrinter*>( _pSetupParent->GetPrinter() )->GetOptions().Clone();
449 : }
450 :
451 : assert(_pOptions);
452 0 : if (!_pOptions)
453 0 : return 0;
454 :
455 : // Create Dialog
456 : boost::scoped_ptr<SfxPrintOptionsDialog> pDlg(new SfxPrintOptionsDialog( static_cast<vcl::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 :
467 0 : return 0;
468 : }
469 :
470 : /**
471 : Internal method for setting the differences between 'pNewPrinter' to the
472 : current printer. pNewPrinter is either taken over or deleted.
473 : */
474 0 : SfxPrinter* SfxViewShell::SetPrinter_Impl( SfxPrinter *pNewPrinter )
475 : {
476 : // get current Printer
477 0 : SfxPrinter *pDocPrinter = GetPrinter();
478 :
479 : // Evaluate Printer Options
480 0 : sal_uInt16 nWhich = GetPool().GetWhich(SID_PRINTER_CHANGESTODOC);
481 0 : const SfxFlagItem *pFlagItem = 0;
482 0 : pDocPrinter->GetOptions().GetItemState( nWhich, false, (const SfxPoolItem**) &pFlagItem );
483 0 : bool bOriToDoc = pFlagItem && (pFlagItem->GetValue() & SFX_PRINTER_CHG_ORIENTATION);
484 0 : bool bSizeToDoc = pFlagItem && (pFlagItem->GetValue() & SFX_PRINTER_CHG_SIZE);
485 :
486 : // Determine the previous format and size
487 0 : Orientation eOldOri = pDocPrinter->GetOrientation();
488 0 : Size aOldPgSz = pDocPrinter->GetPaperSizePixel();
489 :
490 : // Determine the new format and size
491 0 : Orientation eNewOri = pNewPrinter->GetOrientation();
492 0 : Size aNewPgSz = pNewPrinter->GetPaperSizePixel();
493 :
494 : // Determine the changes in page format
495 0 : bool bOriChg = (eOldOri != eNewOri) && bOriToDoc;
496 0 : bool bPgSzChg = ( aOldPgSz.Height() !=
497 0 : ( bOriChg ? aNewPgSz.Width() : aNewPgSz.Height() ) ||
498 0 : aOldPgSz.Width() !=
499 0 : ( bOriChg ? aNewPgSz.Height() : aNewPgSz.Width() ) ) &&
500 0 : bSizeToDoc;
501 :
502 : // Message and Flags for page format, summaries changes
503 0 : OUString aMsg;
504 0 : sal_uInt16 nNewOpt=0;
505 0 : if( bOriChg && bPgSzChg )
506 : {
507 0 : aMsg = SfxResId(STR_PRINT_NEWORISIZE).toString();
508 0 : nNewOpt = SFX_PRINTER_CHG_ORIENTATION | SFX_PRINTER_CHG_SIZE;
509 : }
510 0 : else if (bOriChg )
511 : {
512 0 : aMsg = SfxResId(STR_PRINT_NEWORI).toString();
513 0 : nNewOpt = SFX_PRINTER_CHG_ORIENTATION;
514 : }
515 0 : else if (bPgSzChg)
516 : {
517 0 : aMsg = SfxResId(STR_PRINT_NEWSIZE).toString();
518 0 : nNewOpt = SFX_PRINTER_CHG_SIZE;
519 : }
520 :
521 : // Summaries in this variable what has been changed.
522 0 : sal_uInt16 nChangedFlags = 0;
523 :
524 : // Ask if possible, if page format should be taken over from printer.
525 0 : if ( ( bOriChg || bPgSzChg ) &&
526 0 : RET_YES == MessageDialog(NULL, aMsg, VCL_MESSAGE_QUESTION, VCL_BUTTONS_YES_NO).Execute() )
527 : {
528 : // Flags with changes for <SetPrinter(SfxPrinter*)> are maintained
529 0 : nChangedFlags |= nNewOpt;
530 : }
531 :
532 : // For the MAC to have its "temporary of class String" in next if()
533 0 : OUString aTempPrtName = pNewPrinter->GetName();
534 0 : OUString aDocPrtName = pDocPrinter->GetName();
535 :
536 : // Was the printer selection changed from Default to Specific
537 : // or the other way around?
538 0 : if ( (aTempPrtName != aDocPrtName) || (pDocPrinter->IsDefPrinter() != pNewPrinter->IsDefPrinter()) )
539 : {
540 0 : nChangedFlags |= SFX_PRINTER_PRINTER|SFX_PRINTER_JOBSETUP;
541 0 : pDocPrinter = pNewPrinter;
542 : }
543 : else
544 : {
545 : // Compare extra options
546 0 : if ( ! (pNewPrinter->GetOptions() == pDocPrinter->GetOptions()) )
547 : {
548 : // Option have changed
549 0 : pDocPrinter->SetOptions( pNewPrinter->GetOptions() );
550 0 : nChangedFlags |= SFX_PRINTER_OPTIONS;
551 : }
552 :
553 : // Compare JobSetups
554 0 : JobSetup aNewJobSetup = pNewPrinter->GetJobSetup();
555 0 : JobSetup aOldJobSetup = pDocPrinter->GetJobSetup();
556 0 : if ( aNewJobSetup != aOldJobSetup )
557 : {
558 0 : nChangedFlags |= SFX_PRINTER_JOBSETUP;
559 : }
560 :
561 : // Keep old changed Printer.
562 0 : pDocPrinter->SetPrinterProps( pNewPrinter );
563 0 : delete pNewPrinter;
564 : }
565 :
566 0 : if ( 0 != nChangedFlags )
567 : // SetPrinter will delete the old printer if it changes
568 0 : SetPrinter( pDocPrinter, nChangedFlags );
569 0 : return pDocPrinter;
570 : }
571 :
572 0 : void SfxViewShell::ExecPrint( const uno::Sequence < beans::PropertyValue >& rProps, bool bIsAPI, bool bIsDirect )
573 : {
574 : // get the current selection; our controller should know it
575 0 : Reference< frame::XController > xController( GetController() );
576 0 : Reference< view::XSelectionSupplier > xSupplier( xController, UNO_QUERY );
577 :
578 0 : Any aSelection;
579 0 : if( xSupplier.is() )
580 0 : aSelection = xSupplier->getSelection();
581 : else
582 0 : aSelection <<= GetObjectShell()->GetModel();
583 0 : Any aComplete( makeAny( GetObjectShell()->GetModel() ) );
584 0 : Any aViewProp( makeAny( xController ) );
585 0 : boost::shared_ptr<Printer> aPrt;
586 :
587 0 : const beans::PropertyValue* pVal = rProps.getConstArray();
588 0 : for( sal_Int32 i = 0; i < rProps.getLength(); i++ )
589 : {
590 0 : if ( pVal[i].Name == "PrinterName" )
591 : {
592 0 : OUString aPrinterName;
593 0 : pVal[i].Value >>= aPrinterName;
594 0 : aPrt.reset( new Printer( aPrinterName ) );
595 0 : break;
596 : }
597 : }
598 :
599 : boost::shared_ptr<vcl::PrinterController> pController( new SfxPrinterController(
600 : aPrt,
601 : aComplete,
602 : aSelection,
603 : aViewProp,
604 0 : GetRenderable(),
605 : bIsAPI,
606 : bIsDirect,
607 : this,
608 : rProps
609 0 : ) );
610 0 : pImp->m_pPrinterController = pController;
611 :
612 0 : SfxObjectShell *pObjShell = GetObjectShell();
613 : pController->setValue( OUString( "JobName" ),
614 0 : makeAny( OUString( pObjShell->GetTitle(0) ) ) );
615 :
616 : // FIXME: job setup
617 0 : SfxPrinter* pDocPrt = GetPrinter(false);
618 0 : JobSetup aJobSetup = pDocPrt ? pDocPrt->GetJobSetup() : GetJobSetup();
619 0 : Printer::PrintJob( pController, aJobSetup );
620 0 : }
621 :
622 0 : Printer* SfxViewShell::GetActivePrinter() const
623 : {
624 : return (pImp->m_pPrinterController)
625 0 : ? pImp->m_pPrinterController->getPrinter().get() : 0;
626 : }
627 :
628 0 : void SfxViewShell::ExecPrint_Impl( SfxRequest &rReq )
629 : {
630 0 : sal_uInt16 nDialogRet = RET_CANCEL;
631 0 : SfxPrinter* pPrinter = 0;
632 0 : bool bSilent = false;
633 :
634 : // does the function have been called by the user interface or by an API call
635 0 : bool bIsAPI = rReq.GetArgs() && rReq.GetArgs()->Count();
636 0 : if ( bIsAPI )
637 : {
638 : // the function have been called by the API
639 :
640 : // Should it be visible on the user interface,
641 : // should it launch popup dialogue ?
642 0 : SFX_REQUEST_ARG(rReq, pSilentItem, SfxBoolItem, SID_SILENT, false);
643 0 : bSilent = pSilentItem && pSilentItem->GetValue();
644 : }
645 :
646 : // no help button in dialogs if called from the help window
647 : // (pressing help button would exchange the current page inside the help
648 : // document that is going to be printed!)
649 0 : OUString aHelpFilterName( "writer_web_HTML_help" );
650 0 : SfxMedium* pMedium = GetViewFrame()->GetObjectShell()->GetMedium();
651 0 : const SfxFilter* pFilter = pMedium ? pMedium->GetFilter() : NULL;
652 0 : bool bPrintOnHelp = ( pFilter && pFilter->GetFilterName() == aHelpFilterName );
653 :
654 0 : const sal_uInt16 nId = rReq.GetSlot();
655 0 : switch( nId )
656 : {
657 : case SID_PRINTDOC: // display the printer selection and properties dialogue : File > Print...
658 : case SID_PRINTDOCDIRECT: // Print the document directly, without displaying the dialogue
659 : {
660 0 : SfxObjectShell* pDoc = GetObjectShell();
661 :
662 : // derived class may decide to abort this
663 0 : if( pDoc == NULL || !pDoc->QuerySlotExecutable( nId ) )
664 : {
665 0 : rReq.SetReturnValue( SfxBoolItem( 0, false ) );
666 0 : return;
667 : }
668 :
669 0 : if ( !bSilent && pDoc->QueryHiddenInformation( WhenPrinting, NULL ) != RET_YES )
670 0 : return;
671 :
672 : // should we print only the selection or the whole document
673 0 : SFX_REQUEST_ARG(rReq, pSelectItem, SfxBoolItem, SID_SELECTION, false);
674 0 : bool bSelection = ( pSelectItem != NULL && pSelectItem->GetValue() );
675 : // detect non api call from writer ( that adds SID_SELECTION ) and reset bIsAPI
676 0 : if ( pSelectItem && rReq.GetArgs()->Count() == 1 )
677 0 : bIsAPI = false;
678 :
679 0 : uno::Sequence < beans::PropertyValue > aProps;
680 0 : if ( bIsAPI )
681 : {
682 : // supported properties:
683 : // String PrinterName
684 : // String FileName
685 : // Int16 From
686 : // Int16 To
687 : // In16 Copies
688 : // String RangeText
689 : // bool Selection
690 : // bool Asynchron
691 : // bool Collate
692 : // bool Silent
693 :
694 : // the TransformItems function overwrite aProps
695 0 : TransformItems( nId, *rReq.GetArgs(), aProps, GetInterface()->GetSlot(nId) );
696 :
697 0 : for ( sal_Int32 nProp=0; nProp < aProps.getLength(); ++nProp )
698 : {
699 0 : if ( aProps[nProp].Name == "Copies" )
700 : {
701 0 : aProps[nProp]. Name = "CopyCount";
702 : }
703 0 : else if ( aProps[nProp].Name == "RangeText" )
704 : {
705 0 : aProps[nProp]. Name = "Pages";
706 : }
707 0 : else if ( aProps[nProp].Name == "Asynchron" )
708 : {
709 0 : aProps[nProp]. Name = "Wait";
710 0 : bool bAsynchron = false;
711 0 : aProps[nProp].Value >>= bAsynchron;
712 0 : aProps[nProp].Value <<= (!bAsynchron);
713 : }
714 0 : else if ( aProps[nProp].Name == "Silent" )
715 : {
716 0 : aProps[nProp]. Name = "MonitorVisible";
717 0 : bool bPrintSilent = false;
718 0 : aProps[nProp].Value >>= bPrintSilent;
719 0 : aProps[nProp].Value <<= (!bPrintSilent);
720 : }
721 : }
722 : }
723 :
724 : // we will add the "PrintSelectionOnly" or "HideHelpButton" properties
725 : // we have to increase the capacity of aProps
726 0 : sal_Int32 nLen = aProps.getLength();
727 0 : aProps.realloc( nLen + 1 );
728 :
729 : // HACK: writer sets the SID_SELECTION item when printing directly and expects
730 : // to get only the selection document in that case (see getSelectionObject)
731 : // however it also reacts to the PrintContent property. We need this distinction here, too,
732 : // else one of the combinations print / print direct and selection / all will not work.
733 : // it would be better if writer handled this internally
734 0 : if( nId == SID_PRINTDOCDIRECT )
735 : {
736 0 : aProps[nLen].Name = "PrintSelectionOnly";
737 0 : aProps[nLen].Value = makeAny( bSelection );
738 : }
739 : else // if nId == SID_PRINTDOC ; nothing to do with the previous HACK
740 : {
741 : // should the printer selection and properties dialogue display an help button
742 0 : aProps[nLen].Name = "HideHelpButton";
743 0 : aProps[nLen].Value = makeAny( bPrintOnHelp );
744 : }
745 :
746 0 : ExecPrint( aProps, bIsAPI, (nId == SID_PRINTDOCDIRECT) );
747 :
748 : // FIXME: Recording
749 0 : rReq.Done();
750 0 : break;
751 : }
752 :
753 : case SID_SETUPPRINTER : // display the printer settings dialogue : File > Printer Settings...
754 : case SID_PRINTER_NAME : // only for recorded macros
755 : {
756 : // get printer and printer settings from the document
757 0 : SfxPrinter *pDocPrinter = GetPrinter(true);
758 :
759 : // look for printer in parameters
760 0 : SFX_REQUEST_ARG( rReq, pPrinterItem, SfxStringItem, SID_PRINTER_NAME, false );
761 0 : if ( pPrinterItem )
762 : {
763 : // use PrinterName parameter to create a printer
764 0 : pPrinter = new SfxPrinter( pDocPrinter->GetOptions().Clone(), ((const SfxStringItem*) pPrinterItem)->GetValue() );
765 :
766 : // if printer is unknown, it can't be used - now printer from document will be used
767 0 : if ( !pPrinter->IsKnown() )
768 0 : DELETEZ(pPrinter);
769 : }
770 :
771 0 : if ( SID_PRINTER_NAME == nId )
772 : {
773 : // just set a recorded printer name
774 0 : if ( pPrinter )
775 0 : SetPrinter( pPrinter, SFX_PRINTER_PRINTER );
776 0 : return;
777 : }
778 :
779 : // no PrinterName parameter in ItemSet or the PrinterName points to an unknown printer
780 0 : if ( !pPrinter )
781 : // use default printer from document
782 0 : pPrinter = pDocPrinter;
783 :
784 0 : if( !pPrinter || !pPrinter->IsValid() )
785 : {
786 : // no valid printer either in ItemSet or at the document
787 0 : if ( !bSilent )
788 0 : MessageDialog(NULL, SfxResId(STR_NODEFPRINTER)).Execute();
789 :
790 0 : rReq.SetReturnValue(SfxBoolItem(0,false));
791 :
792 0 : break;
793 : }
794 :
795 : // FIXME: printer isn't used for printing anymore!
796 0 : if( pPrinter->IsPrinting() )
797 : {
798 : // if printer is busy, abort configuration
799 0 : if ( !bSilent )
800 0 : MessageDialog(NULL, SfxResId(STR_ERROR_PRINTER_BUSY), VCL_MESSAGE_INFO).Execute();
801 0 : rReq.SetReturnValue(SfxBoolItem(0,false));
802 :
803 0 : return;
804 : }
805 :
806 : // if no arguments are given, retrieve them from a dialog
807 0 : if ( !bIsAPI )
808 : {
809 : // PrinterDialog needs a temporary printer
810 0 : SfxPrinter* pDlgPrinter = pPrinter->Clone();
811 0 : nDialogRet = 0;
812 :
813 : // execute PrinterSetupDialog
814 0 : PrinterSetupDialog* pPrintSetupDlg = new PrinterSetupDialog( GetWindow() );
815 0 : SfxDialogExecutor_Impl* pExecutor = 0;
816 :
817 0 : if (pImp->m_bHasPrintOptions && HasPrintOptionsPage())
818 : {
819 : // additional controls for dialog
820 0 : pExecutor = new SfxDialogExecutor_Impl( this, pPrintSetupDlg );
821 0 : if ( bPrintOnHelp )
822 0 : pExecutor->DisableHelp();
823 0 : pPrintSetupDlg->SetOptionsHdl( pExecutor->GetLink() );
824 : }
825 :
826 0 : pPrintSetupDlg->SetPrinter( pDlgPrinter );
827 0 : nDialogRet = pPrintSetupDlg->Execute();
828 :
829 0 : if ( pExecutor && pExecutor->GetOptions() )
830 : {
831 0 : if ( nDialogRet == RET_OK )
832 : // remark: have to be recorded if possible!
833 0 : pDlgPrinter->SetOptions( *pExecutor->GetOptions() );
834 : else
835 : {
836 0 : pPrinter->SetOptions( *pExecutor->GetOptions() );
837 0 : SetPrinter( pPrinter, SFX_PRINTER_OPTIONS );
838 : }
839 : }
840 :
841 0 : DELETEZ( pPrintSetupDlg );
842 0 : delete pExecutor;
843 :
844 : // no recording of PrinterSetup except printer name (is printer dependent)
845 0 : rReq.Ignore();
846 :
847 0 : if ( nDialogRet == RET_OK )
848 : {
849 0 : if ( pPrinter->GetName() != pDlgPrinter->GetName() )
850 : {
851 : // user has changed the printer -> macro recording
852 0 : SfxRequest aReq( GetViewFrame(), SID_PRINTER_NAME );
853 0 : aReq.AppendItem( SfxStringItem( SID_PRINTER_NAME, pDlgPrinter->GetName() ) );
854 0 : aReq.Done();
855 : }
856 :
857 : // take the changes made in the dialog
858 0 : SetPrinter_Impl( pDlgPrinter );
859 :
860 : // forget new printer, it was taken over (as pPrinter) or deleted
861 0 : pDlgPrinter = NULL;
862 :
863 : }
864 : else
865 : {
866 : // PrinterDialog is used to transfer information on printing,
867 : // so it will only be deleted here if dialog was cancelled
868 0 : DELETEZ( pDlgPrinter );
869 0 : rReq.Ignore();
870 : }
871 : }
872 : }
873 0 : }
874 : }
875 :
876 0 : SfxPrinter* SfxViewShell::GetPrinter( bool /*bCreate*/ )
877 : {
878 0 : return 0;
879 : }
880 :
881 0 : sal_uInt16 SfxViewShell::SetPrinter( SfxPrinter* /*pNewPrinter*/, sal_uInt16 /*nDiffFlags*/, bool )
882 : {
883 0 : return 0;
884 : }
885 :
886 0 : SfxTabPage* SfxViewShell::CreatePrintOptionsPage
887 : (
888 : vcl::Window* /*pParent*/,
889 : const SfxItemSet& /*rOptions*/
890 : )
891 : {
892 0 : return 0;
893 : }
894 :
895 0 : bool SfxViewShell::HasPrintOptionsPage() const
896 : {
897 0 : return false;
898 : }
899 :
900 0 : JobSetup SfxViewShell::GetJobSetup() const
901 : {
902 0 : return JobSetup();
903 951 : }
904 :
905 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|