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