Use correct object
[LibreOffice.git] / sfx2 / source / view / viewprn.cxx
blobbc885e5670c7f87a31689e8771d1eeaba3cf8ee1
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <memory>
22 #include <com/sun/star/document/XDocumentProperties.hpp>
23 #include <com/sun/star/view/XRenderable.hpp>
24 #include <com/sun/star/view/XSelectionSupplier.hpp>
26 #include <comphelper/propertyvalue.hxx>
27 #include <officecfg/Office/Common.hxx>
28 #include <sal/log.hxx>
29 #include <utility>
30 #include <vcl/svapp.hxx>
31 #include <vcl/weld.hxx>
32 #include <svtools/prnsetup.hxx>
33 #include <svl/flagitem.hxx>
34 #include <svl/stritem.hxx>
35 #include <svl/eitem.hxx>
36 #include <unotools/useroptions.hxx>
37 #include <tools/datetime.hxx>
38 #include <sfx2/bindings.hxx>
39 #include <sfx2/objface.hxx>
40 #include <sfx2/viewsh.hxx>
41 #include "viewimp.hxx"
42 #include <sfx2/viewfrm.hxx>
43 #include <sfx2/printer.hxx>
44 #include <sfx2/sfxresid.hxx>
45 #include <sfx2/request.hxx>
46 #include <sfx2/objsh.hxx>
47 #include <sfx2/event.hxx>
48 #include <sfx2/docfile.hxx>
49 #include <sfx2/docfilt.hxx>
50 #include <sfx2/sfxsids.hrc>
51 #include <sfx2/strings.hrc>
52 #include <sfx2/sfxuno.hxx>
53 #include <sfx2/tabdlg.hxx>
55 #include <toolkit/awt/vclxdevice.hxx>
57 #include "prnmon.hxx"
59 using namespace com::sun::star;
60 using namespace com::sun::star::uno;
62 class SfxPrinterController : public vcl::PrinterController, public SfxListener
64 Any maCompleteSelection;
65 Any maSelection;
66 Reference< view::XRenderable > mxRenderable;
67 mutable VclPtr<Printer> mpLastPrinter;
68 mutable Reference<awt::XDevice> mxDevice;
69 SfxViewShell* mpViewShell;
70 SfxObjectShell* mpObjectShell;
71 bool m_bJobStarted;
72 bool m_bOrigStatus;
73 bool m_bNeedsChange;
74 bool m_bApi;
75 bool m_bTempPrinter;
76 util::DateTime m_aLastPrinted;
77 OUString m_aLastPrintedBy;
79 Sequence< beans::PropertyValue > getMergedOptions() const;
80 const Any& getSelectionObject() const;
82 public:
83 SfxPrinterController( const VclPtr<Printer>& i_rPrinter,
84 Any i_Complete,
85 Any i_Selection,
86 const Any& i_rViewProp,
87 const Reference< view::XRenderable >& i_xRender,
88 bool i_bApi, bool i_bDirect,
89 SfxViewShell* pView,
90 const uno::Sequence< beans::PropertyValue >& rProps
93 virtual void Notify( SfxBroadcaster&, const SfxHint& ) override;
95 virtual int getPageCount() const override;
96 virtual Sequence< beans::PropertyValue > getPageParameters( int i_nPage ) const override;
97 virtual void printPage( int i_nPage ) const override;
98 virtual void jobStarted() override;
99 virtual void jobFinished( css::view::PrintableState ) override;
102 SfxPrinterController::SfxPrinterController( const VclPtr<Printer>& i_rPrinter,
103 Any i_Complete,
104 Any i_Selection,
105 const Any& i_rViewProp,
106 const Reference< view::XRenderable >& i_xRender,
107 bool i_bApi, bool i_bDirect,
108 SfxViewShell* pView,
109 const uno::Sequence< beans::PropertyValue >& rProps
111 : PrinterController(i_rPrinter, pView ? pView->GetFrameWeld() : nullptr)
112 , maCompleteSelection(std::move( i_Complete ))
113 , maSelection(std::move( i_Selection ))
114 , mxRenderable( i_xRender )
115 , mpLastPrinter( nullptr )
116 , mpViewShell( pView )
117 , mpObjectShell(nullptr)
118 , m_bJobStarted( false )
119 , m_bOrigStatus( false )
120 , m_bNeedsChange( false )
121 , m_bApi(i_bApi)
122 , m_bTempPrinter( i_rPrinter )
124 if ( mpViewShell )
126 StartListening( *mpViewShell );
127 mpObjectShell = mpViewShell->GetObjectShell();
128 StartListening( *mpObjectShell );
131 // initialize extra ui options
132 if( mxRenderable.is() )
134 for (const auto& rProp : rProps)
135 setValue( rProp.Name, rProp.Value );
137 Sequence< beans::PropertyValue > aRenderOptions{
138 comphelper::makePropertyValue(u"ExtraPrintUIOptions"_ustr, Any{}),
139 comphelper::makePropertyValue(u"View"_ustr, i_rViewProp),
140 comphelper::makePropertyValue(u"IsPrinter"_ustr, true)
144 const Sequence< beans::PropertyValue > aRenderParms( mxRenderable->getRenderer( 0 , getSelectionObject(), aRenderOptions ) );
145 for( const auto& rRenderParm : aRenderParms )
147 if ( rRenderParm.Name == "ExtraPrintUIOptions" )
149 Sequence< beans::PropertyValue > aUIProps;
150 rRenderParm.Value >>= aUIProps;
151 setUIOptions( aUIProps );
153 else if( rRenderParm.Name == "NUp" )
155 setValue( rRenderParm.Name, rRenderParm.Value );
159 catch( lang::IllegalArgumentException& )
161 // the first renderer should always be available for the UI options,
162 // but catch the exception to be safe
166 // set some job parameters
167 setValue( u"IsApi"_ustr, Any( i_bApi ) );
168 setValue( u"IsDirect"_ustr, Any( i_bDirect ) );
169 setValue( u"IsPrinter"_ustr, Any( true ) );
170 setValue( u"View"_ustr, i_rViewProp );
173 void SfxPrinterController::Notify( SfxBroadcaster& , const SfxHint& rHint )
175 if ( rHint.GetId() == SfxHintId::Dying )
177 EndListening(*mpViewShell);
178 EndListening(*mpObjectShell);
179 dialogsParentClosing();
180 mpViewShell = nullptr;
181 mpObjectShell = nullptr;
185 const Any& SfxPrinterController::getSelectionObject() const
187 const beans::PropertyValue* pVal = getValue( u"PrintSelectionOnly"_ustr );
188 if( pVal )
190 bool bSel = false;
191 pVal->Value >>= bSel;
192 return bSel ? maSelection : maCompleteSelection;
195 sal_Int32 nChoice = 0;
196 pVal = getValue( u"PrintContent"_ustr );
197 if( pVal )
198 pVal->Value >>= nChoice;
200 return (nChoice > 1) ? maSelection : maCompleteSelection;
203 Sequence< beans::PropertyValue > SfxPrinterController::getMergedOptions() const
205 VclPtr<Printer> xPrinter( getPrinter() );
206 if( xPrinter.get() != mpLastPrinter )
208 mpLastPrinter = xPrinter.get();
209 rtl::Reference<VCLXDevice> pXDevice = new VCLXDevice();
210 pXDevice->SetOutputDevice( mpLastPrinter );
211 mxDevice.set( pXDevice );
214 Sequence< beans::PropertyValue > aRenderOptions{ comphelper::makePropertyValue(
215 u"RenderDevice"_ustr, mxDevice) };
217 aRenderOptions = getJobProperties( aRenderOptions );
218 return aRenderOptions;
221 int SfxPrinterController::getPageCount() const
223 int nPages = 0;
224 VclPtr<Printer> xPrinter( getPrinter() );
225 if( mxRenderable.is() && xPrinter )
227 Sequence< beans::PropertyValue > aJobOptions( getMergedOptions() );
230 nPages = mxRenderable->getRendererCount( getSelectionObject(), aJobOptions );
232 catch (lang::DisposedException &)
234 SAL_WARN("sfx", "SfxPrinterController: document disposed while printing");
235 const_cast<SfxPrinterController*>(this)->setJobState(
236 view::PrintableState_JOB_ABORTED);
239 return nPages;
242 Sequence< beans::PropertyValue > SfxPrinterController::getPageParameters( int i_nPage ) const
244 VclPtr<Printer> xPrinter( getPrinter() );
245 Sequence< beans::PropertyValue > aResult;
247 if (mxRenderable.is() && xPrinter)
249 Sequence< beans::PropertyValue > aJobOptions( getMergedOptions() );
252 aResult = mxRenderable->getRenderer( i_nPage, getSelectionObject(), aJobOptions );
254 catch( lang::IllegalArgumentException& )
257 catch (lang::DisposedException &)
259 SAL_WARN("sfx", "SfxPrinterController: document disposed while printing");
260 const_cast<SfxPrinterController*>(this)->setJobState(
261 view::PrintableState_JOB_ABORTED);
264 return aResult;
267 void SfxPrinterController::printPage( int i_nPage ) const
269 VclPtr<Printer> xPrinter( getPrinter() );
270 if( !mxRenderable.is() || !xPrinter )
271 return;
273 Sequence< beans::PropertyValue > aJobOptions( getMergedOptions() );
276 mxRenderable->render( i_nPage, getSelectionObject(), aJobOptions );
278 catch( lang::IllegalArgumentException& )
280 // don't care enough about nonexistent page here
281 // to provoke a crash
283 catch (lang::DisposedException &)
285 SAL_WARN("sfx", "SfxPrinterController: document disposed while printing");
286 const_cast<SfxPrinterController*>(this)->setJobState(
287 view::PrintableState_JOB_ABORTED);
291 void SfxPrinterController::jobStarted()
293 if ( !mpObjectShell )
294 return;
296 m_bJobStarted = true;
298 m_bOrigStatus = mpObjectShell->IsEnableSetModified();
300 // check configuration: shall update of printing information in DocInfo set the document to "modified"?
301 if (m_bOrigStatus && !officecfg::Office::Common::Print::PrintingModifiesDocument::get())
303 mpObjectShell->EnableSetModified( false );
304 m_bNeedsChange = true;
307 // refresh document info
308 uno::Reference<document::XDocumentProperties> xDocProps(mpObjectShell->getDocProperties());
309 m_aLastPrintedBy = xDocProps->getPrintedBy();
310 m_aLastPrinted = xDocProps->getPrintDate();
312 xDocProps->setPrintedBy( mpObjectShell->IsUseUserData()
313 ? SvtUserOptions().GetFullName()
314 : OUString() );
315 ::DateTime now( ::DateTime::SYSTEM );
317 xDocProps->setPrintDate( now.GetUNODateTime() );
319 uno::Sequence < beans::PropertyValue > aOpts;
320 aOpts = getJobProperties( aOpts );
322 uno::Reference< frame::XController2 > xController;
323 if ( mpViewShell )
324 xController.set( mpViewShell->GetController(), uno::UNO_QUERY );
326 mpObjectShell->Broadcast( SfxPrintingHint(
327 view::PrintableState_JOB_STARTED, aOpts, mpObjectShell, xController ) );
330 void SfxPrinterController::jobFinished( css::view::PrintableState nState )
332 if ( !mpObjectShell )
333 return;
335 bool bCopyJobSetup = false;
336 mpObjectShell->Broadcast( SfxPrintingHint( nState ) );
337 switch ( nState )
339 case view::PrintableState_JOB_SPOOLING_FAILED :
340 case view::PrintableState_JOB_FAILED :
342 // "real" problem (not simply printing cancelled by user)
343 OUString aMsg( SfxResId(STR_NOSTARTPRINTER) );
344 if ( !m_bApi && mpViewShell )
346 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(mpViewShell->GetFrameWeld(),
347 VclMessageType::Warning, VclButtonsType::Ok,
348 aMsg));
349 xBox->run();
351 [[fallthrough]];
353 case view::PrintableState_JOB_ABORTED :
355 // printing not successful, reset DocInfo if the job started and so DocInfo was modified
356 if (m_bJobStarted)
358 uno::Reference<document::XDocumentProperties> xDocProps(mpObjectShell->getDocProperties());
359 xDocProps->setPrintedBy(m_aLastPrintedBy);
360 xDocProps->setPrintDate(m_aLastPrinted);
362 break;
365 case view::PrintableState_JOB_SPOOLED :
366 case view::PrintableState_JOB_COMPLETED :
368 if (mpViewShell)
370 SfxBindings& rBind = mpViewShell->GetViewFrame().GetBindings();
371 rBind.Invalidate( SID_PRINTDOC );
372 rBind.Invalidate( SID_PRINTDOCDIRECT );
373 rBind.Invalidate( SID_SETUPPRINTER );
374 bCopyJobSetup = ! m_bTempPrinter;
376 break;
379 default:
380 break;
383 if( bCopyJobSetup && mpViewShell )
385 // #i114306#
386 // Note: this possibly creates a printer that gets immediately replaced
387 // by a new one. The reason for this is that otherwise we would not get
388 // the printer's SfxItemSet here to copy. Awkward, but at the moment there is no
389 // other way here to get the item set.
390 SfxPrinter* pDocPrt = mpViewShell->GetPrinter(true);
391 if( pDocPrt )
393 if( pDocPrt->GetName() == getPrinter()->GetName() )
394 pDocPrt->SetJobSetup( getPrinter()->GetJobSetup() );
395 else
397 VclPtr<SfxPrinter> pNewPrt = VclPtr<SfxPrinter>::Create( pDocPrt->GetOptions().Clone(), getPrinter()->GetName() );
398 pNewPrt->SetJobSetup( getPrinter()->GetJobSetup() );
399 mpViewShell->SetPrinter( pNewPrt, SfxPrinterChangeFlags::PRINTER | SfxPrinterChangeFlags::JOBSETUP );
404 if ( m_bNeedsChange )
405 mpObjectShell->EnableSetModified( m_bOrigStatus );
407 if ( mpViewShell )
409 mpViewShell->pImpl->m_xPrinterController.reset();
413 namespace {
416 An instance of this class is created for the life span of the
417 printer dialogue, to create in its click handler for the additions by the
418 virtual method of the derived SfxViewShell generated print options dialogue
419 and to cache the options set there as SfxItemSet.
421 class SfxDialogExecutor_Impl
423 private:
424 SfxViewShell* _pViewSh;
425 PrinterSetupDialog& _rSetupParent;
426 std::unique_ptr<SfxItemSet> _pOptions;
427 bool _bHelpDisabled;
429 DECL_LINK( Execute, weld::Button&, void );
431 public:
432 SfxDialogExecutor_Impl( SfxViewShell* pViewSh, PrinterSetupDialog& rParent );
434 Link<weld::Button&, void> GetLink() const { return LINK(const_cast<SfxDialogExecutor_Impl*>(this), SfxDialogExecutor_Impl, Execute); }
435 const SfxItemSet* GetOptions() const { return _pOptions.get(); }
436 void DisableHelp() { _bHelpDisabled = true; }
441 SfxDialogExecutor_Impl::SfxDialogExecutor_Impl( SfxViewShell* pViewSh, PrinterSetupDialog& rParent ) :
443 _pViewSh ( pViewSh ),
444 _rSetupParent ( rParent ),
445 _bHelpDisabled ( false )
450 IMPL_LINK_NOARG(SfxDialogExecutor_Impl, Execute, weld::Button&, void)
452 // Options noted locally
453 if ( !_pOptions )
455 _pOptions = static_cast<SfxPrinter*>( _rSetupParent.GetPrinter() )->GetOptions().Clone();
458 assert(_pOptions);
459 if (!_pOptions)
460 return;
462 // Create Dialog
463 SfxPrintOptionsDialog aDlg(_rSetupParent.GetFrameWeld(), _pViewSh, _pOptions.get() );
464 if (_bHelpDisabled)
465 aDlg.DisableHelp();
466 if (aDlg.run() == RET_OK)
468 _pOptions = aDlg.GetOptions().Clone();
473 Internal method for setting the differences between 'pNewPrinter' to the
474 current printer. pNewPrinter is either taken over or deleted.
476 void SfxViewShell::SetPrinter_Impl( VclPtr<SfxPrinter>& pNewPrinter )
478 // get current Printer
479 SfxPrinter *pDocPrinter = GetPrinter();
481 // Evaluate Printer Options
482 const SfxFlagItem *pFlagItem = pDocPrinter->GetOptions().GetItemIfSet( SID_PRINTER_CHANGESTODOC, false );
483 bool bOriToDoc = pFlagItem && (static_cast<SfxPrinterChangeFlags>(pFlagItem->GetValue()) & SfxPrinterChangeFlags::CHG_ORIENTATION);
484 bool bSizeToDoc = pFlagItem && (static_cast<SfxPrinterChangeFlags>(pFlagItem->GetValue()) & SfxPrinterChangeFlags::CHG_SIZE);
486 // Determine the previous format and size
487 Orientation eOldOri = pDocPrinter->GetOrientation();
488 Size aOldPgSz = pDocPrinter->GetPaperSizePixel();
490 // Determine the new format and size
491 Orientation eNewOri = pNewPrinter->GetOrientation();
492 Size aNewPgSz = pNewPrinter->GetPaperSizePixel();
494 // Determine the changes in page format
495 bool bOriChg = (eOldOri != eNewOri) && bOriToDoc;
496 bool bPgSzChg = ( aOldPgSz.Height() !=
497 ( bOriChg ? aNewPgSz.Width() : aNewPgSz.Height() ) ||
498 aOldPgSz.Width() !=
499 ( bOriChg ? aNewPgSz.Height() : aNewPgSz.Width() ) ) &&
500 bSizeToDoc;
502 // Message and Flags for page format changes
503 OUString aMsg;
504 SfxPrinterChangeFlags nNewOpt = SfxPrinterChangeFlags::NONE;
505 if( bOriChg && bPgSzChg )
507 aMsg = SfxResId(STR_PRINT_NEWORISIZE);
508 nNewOpt = SfxPrinterChangeFlags::CHG_ORIENTATION | SfxPrinterChangeFlags::CHG_SIZE;
510 else if (bOriChg )
512 aMsg = SfxResId(STR_PRINT_NEWORI);
513 nNewOpt = SfxPrinterChangeFlags::CHG_ORIENTATION;
515 else if (bPgSzChg)
517 aMsg = SfxResId(STR_PRINT_NEWSIZE);
518 nNewOpt = SfxPrinterChangeFlags::CHG_SIZE;
521 // Summarize in this variable what has been changed.
522 SfxPrinterChangeFlags nChangedFlags = SfxPrinterChangeFlags::NONE;
524 // Ask if possible, if page format should be taken over from printer.
525 if (bOriChg || bPgSzChg)
527 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(nullptr,
528 VclMessageType::Question, VclButtonsType::YesNo,
529 aMsg));
530 if (RET_YES == xBox->run())
532 // Flags with changes for <SetPrinter(SfxPrinter*)> are maintained
533 nChangedFlags |= nNewOpt;
537 // Was the printer selection changed from Default to Specific
538 // or the other way around?
539 if ( (pNewPrinter->GetName() != pDocPrinter->GetName())
540 || (pDocPrinter->IsDefPrinter() != pNewPrinter->IsDefPrinter()) )
542 nChangedFlags |= SfxPrinterChangeFlags::PRINTER|SfxPrinterChangeFlags::JOBSETUP;
543 if ( ! (pNewPrinter->GetOptions() == pDocPrinter->GetOptions()) )
545 nChangedFlags |= SfxPrinterChangeFlags::OPTIONS;
548 pDocPrinter = pNewPrinter;
550 else
552 // Compare extra options
553 if ( ! (pNewPrinter->GetOptions() == pDocPrinter->GetOptions()) )
555 // Option have changed
556 pDocPrinter->SetOptions( pNewPrinter->GetOptions() );
557 nChangedFlags |= SfxPrinterChangeFlags::OPTIONS;
560 // Compare JobSetups
561 JobSetup aNewJobSetup = pNewPrinter->GetJobSetup();
562 JobSetup aOldJobSetup = pDocPrinter->GetJobSetup();
563 if ( aNewJobSetup != aOldJobSetup )
565 nChangedFlags |= SfxPrinterChangeFlags::JOBSETUP;
568 // Keep old changed Printer.
569 pDocPrinter->SetPrinterProps( pNewPrinter );
570 pNewPrinter.disposeAndClear();
573 if ( SfxPrinterChangeFlags::NONE != nChangedFlags )
574 // SetPrinter will delete the old printer if it changes
575 SetPrinter( pDocPrinter, nChangedFlags );
578 void SfxViewShell::StartPrint( const uno::Sequence < beans::PropertyValue >& rProps, bool bIsAPI, bool bIsDirect )
580 assert( !pImpl->m_xPrinterController );
582 // get the current selection; our controller should know it
583 Reference< frame::XController > xController( GetController() );
584 Reference< view::XSelectionSupplier > xSupplier( xController, UNO_QUERY );
586 Any aSelection;
587 if( xSupplier.is() )
588 aSelection = xSupplier->getSelection();
589 else
590 aSelection <<= GetObjectShell()->GetModel();
591 Any aComplete( Any( GetObjectShell()->GetModel() ) );
592 Any aViewProp( xController );
593 VclPtr<Printer> aPrt;
595 const beans::PropertyValue* pVal = std::find_if(rProps.begin(), rProps.end(),
596 [](const beans::PropertyValue& rVal) { return rVal.Name == "PrinterName"; });
597 if (pVal != rProps.end())
599 OUString aPrinterName;
600 pVal->Value >>= aPrinterName;
601 aPrt.reset( VclPtr<Printer>::Create( aPrinterName ) );
604 std::shared_ptr<vcl::PrinterController> xNewController(std::make_shared<SfxPrinterController>(
605 aPrt,
606 aComplete,
607 aSelection,
608 aViewProp,
609 GetRenderable(),
610 bIsAPI,
611 bIsDirect,
612 this,
613 rProps
615 pImpl->m_xPrinterController = xNewController;
617 // When no JobName was specified via com::sun::star::view::PrintOptions::JobName ,
618 // use the document title as default job name
619 css::beans::PropertyValue* pJobNameVal = xNewController->getValue(u"JobName"_ustr);
620 if (!pJobNameVal)
622 if (SfxObjectShell* pDoc = GetObjectShell())
624 xNewController->setValue(u"JobName"_ustr, Any(pDoc->GetTitle(1)));
625 xNewController->setPrinterModified(mbPrinterSettingsModified);
630 void SfxViewShell::ExecPrint( const uno::Sequence < beans::PropertyValue >& rProps, bool bIsAPI, bool bIsDirect )
632 StartPrint( rProps, bIsAPI, bIsDirect );
633 // FIXME: job setup
634 SfxPrinter* pDocPrt = GetPrinter();
635 JobSetup aJobSetup = pDocPrt ? pDocPrt->GetJobSetup() : JobSetup();
636 Printer::PrintJob( GetPrinterController(), aJobSetup );
639 const std::shared_ptr< vcl::PrinterController >& SfxViewShell::GetPrinterController() const
641 return pImpl->m_xPrinterController;
644 Printer* SfxViewShell::GetActivePrinter() const
646 return pImpl->m_xPrinterController
647 ? pImpl->m_xPrinterController->getPrinter().get() : nullptr;
650 void SfxViewShell::ExecPrint_Impl( SfxRequest &rReq )
652 sal_uInt16 nDialogRet = RET_CANCEL;
653 VclPtr<SfxPrinter> pPrinter;
654 bool bSilent = false;
656 // does the function have been called by the user interface or by an API call
657 bool bIsAPI = rReq.GetArgs() && rReq.GetArgs()->Count();
658 if ( bIsAPI )
660 // the function have been called by the API
662 // Should it be visible on the user interface,
663 // should it launch popup dialogue ?
664 const SfxBoolItem* pSilentItem = rReq.GetArg<SfxBoolItem>(SID_SILENT);
665 bSilent = pSilentItem && pSilentItem->GetValue();
668 // no help button in dialogs if called from the help window
669 // (pressing help button would exchange the current page inside the help
670 // document that is going to be printed!)
671 SfxMedium* pMedium = GetViewFrame().GetObjectShell()->GetMedium();
672 std::shared_ptr<const SfxFilter> pFilter = pMedium ? pMedium->GetFilter() : nullptr;
673 bool bPrintOnHelp = ( pFilter && pFilter->GetFilterName() == "writer_web_HTML_help" );
675 const sal_uInt16 nId = rReq.GetSlot();
676 switch( nId )
678 case SID_PRINTDOC: // display the printer selection and properties dialogue : File > Print...
679 case SID_PRINTDOCDIRECT: // Print the document directly, without displaying the dialogue
681 SfxObjectShell* pDoc = GetObjectShell();
683 // derived class may decide to abort this
684 if( pDoc == nullptr || !pDoc->QuerySlotExecutable( nId ) )
686 rReq.SetReturnValue( SfxBoolItem( 0, false ) );
687 return;
690 pDoc->QueryHiddenInformation(HiddenWarningFact::WhenPrinting);
692 // should we print only the selection or the whole document
693 const SfxBoolItem* pSelectItem = rReq.GetArg<SfxBoolItem>(SID_SELECTION);
694 bool bSelection = ( pSelectItem != nullptr && pSelectItem->GetValue() );
695 // detect non api call from writer ( that adds SID_SELECTION ) and reset bIsAPI
696 if ( pSelectItem && rReq.GetArgs()->Count() == 1 )
697 bIsAPI = false;
699 uno::Sequence < beans::PropertyValue > aProps;
700 if ( bIsAPI )
702 // supported properties:
703 // String PrinterName
704 // String FileName
705 // Int16 From
706 // Int16 To
707 // In16 Copies
708 // String RangeText
709 // bool Selection
710 // bool Asynchron
711 // bool Collate
712 // bool Silent
714 // the TransformItems function overwrite aProps
715 TransformItems( nId, *rReq.GetArgs(), aProps, GetInterface()->GetSlot(nId) );
717 for ( auto& rProp : asNonConstRange(aProps) )
719 if ( rProp.Name == "Copies" )
721 rProp.Name = "CopyCount";
723 else if ( rProp.Name == "RangeText" )
725 rProp.Name = "Pages";
727 else if ( rProp.Name == "Asynchron" )
729 rProp.Name = "Wait";
730 bool bAsynchron = false;
731 rProp.Value >>= bAsynchron;
732 rProp.Value <<= !bAsynchron;
734 else if ( rProp.Name == "Silent" )
736 rProp.Name = "MonitorVisible";
737 bool bPrintSilent = false;
738 rProp.Value >>= bPrintSilent;
739 rProp.Value <<= !bPrintSilent;
744 // we will add the "PrintSelectionOnly" or "HideHelpButton" properties
745 // we have to increase the capacity of aProps
746 sal_Int32 nLen = aProps.getLength();
747 aProps.realloc( nLen + 1 );
748 auto pProps = aProps.getArray();
750 // HACK: writer sets the SID_SELECTION item when printing directly and expects
751 // to get only the selection document in that case (see getSelectionObject)
752 // however it also reacts to the PrintContent property. We need this distinction here, too,
753 // else one of the combinations print / print direct and selection / all will not work.
754 // it would be better if writer handled this internally
755 if( nId == SID_PRINTDOCDIRECT )
757 pProps[nLen].Name = "PrintSelectionOnly";
758 pProps[nLen].Value <<= bSelection;
760 else // if nId == SID_PRINTDOC ; nothing to do with the previous HACK
762 // should the printer selection and properties dialogue display an help button
763 pProps[nLen].Name = "HideHelpButton";
764 pProps[nLen].Value <<= bPrintOnHelp;
767 ExecPrint( aProps, bIsAPI, (nId == SID_PRINTDOCDIRECT) );
769 // FIXME: Recording
770 rReq.Done();
771 break;
774 case SID_PRINTER_NAME: // for recorded macros
776 // get printer and printer settings from the document
777 SfxPrinter* pDocPrinter = GetPrinter(true);
778 const SfxStringItem* pPrinterItem = rReq.GetArg<SfxStringItem>(SID_PRINTER_NAME);
779 if (!pPrinterItem)
781 rReq.Ignore();
782 break;
784 // use PrinterName parameter to create a printer
785 pPrinter = VclPtr<SfxPrinter>::Create(pDocPrinter->GetOptions().Clone(),
786 pPrinterItem->GetValue());
788 if (!pPrinter->IsKnown())
790 pPrinter.disposeAndClear();
791 rReq.Ignore();
792 break;
794 SetPrinter(pPrinter, SfxPrinterChangeFlags::PRINTER);
795 rReq.Done();
796 break;
798 case SID_SETUPPRINTER : // display the printer settings dialog : File > Printer Settings...
800 // get printer and printer settings from the document
801 SfxPrinter *pDocPrinter = GetPrinter(true);
803 // look for printer in parameters
804 const SfxStringItem* pPrinterItem = rReq.GetArg<SfxStringItem>(SID_PRINTER_NAME);
805 if ( pPrinterItem )
807 // use PrinterName parameter to create a printer
808 pPrinter = VclPtr<SfxPrinter>::Create( pDocPrinter->GetOptions().Clone(), pPrinterItem->GetValue() );
810 // if printer is unknown, it can't be used - now printer from document will be used
811 if ( !pPrinter->IsKnown() )
812 pPrinter.disposeAndClear();
815 // no PrinterName parameter in ItemSet or the PrinterName points to an unknown printer
816 if ( !pPrinter )
817 // use default printer from document
818 pPrinter = pDocPrinter;
820 if( !pPrinter || !pPrinter->IsValid() )
822 // no valid printer either in ItemSet or at the document
823 if ( !bSilent )
825 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(nullptr,
826 VclMessageType::Warning, VclButtonsType::Ok,
827 SfxResId(STR_NODEFPRINTER)));
828 xBox->run();
831 rReq.SetReturnValue(SfxBoolItem(0,false));
833 break;
836 // FIXME: printer isn't used for printing anymore!
837 if( pPrinter->IsPrinting() )
839 // if printer is busy, abort configuration
840 if ( !bSilent )
842 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(nullptr,
843 VclMessageType::Info, VclButtonsType::Ok,
844 SfxResId(STR_ERROR_PRINTER_BUSY)));
845 xBox->run();
847 rReq.SetReturnValue(SfxBoolItem(0,false));
849 return;
852 // Open Printer Setup dialog (needs a temporary printer)
853 VclPtr<SfxPrinter> pDlgPrinter = pPrinter->Clone();
854 PrinterSetupDialog aPrintSetupDlg(GetFrameWeld());
855 std::unique_ptr<SfxDialogExecutor_Impl> pExecutor;
857 if (pImpl->m_bHasPrintOptions && HasPrintOptionsPage())
859 // additional controls for dialog
860 pExecutor.reset(new SfxDialogExecutor_Impl(this, aPrintSetupDlg));
861 if (bPrintOnHelp)
862 pExecutor->DisableHelp();
863 aPrintSetupDlg.SetOptionsHdl(pExecutor->GetLink());
866 aPrintSetupDlg.SetPrinter(pDlgPrinter);
867 nDialogRet = aPrintSetupDlg.run();
869 if (pExecutor && pExecutor->GetOptions())
871 if (nDialogRet == RET_OK)
872 // remark: have to be recorded if possible!
873 pDlgPrinter->SetOptions(*pExecutor->GetOptions());
874 else
876 pPrinter->SetOptions(*pExecutor->GetOptions());
877 SetPrinter(pPrinter, SfxPrinterChangeFlags::OPTIONS);
881 // no recording of PrinterSetup except printer name (is printer dependent)
882 rReq.Ignore();
884 if (nDialogRet == RET_OK)
886 if (pPrinter->GetName() != pDlgPrinter->GetName())
888 // user has changed the printer -> macro recording
889 SfxRequest aReq(GetViewFrame(), SID_PRINTER_NAME);
890 aReq.AppendItem(SfxStringItem(SID_PRINTER_NAME, pDlgPrinter->GetName()));
891 aReq.Done();
894 // take the changes made in the dialog
895 SetPrinter_Impl(pDlgPrinter);
897 // forget new printer, it was taken over (as pPrinter) or deleted
898 pDlgPrinter = nullptr;
899 mbPrinterSettingsModified = true;
901 else
903 // PrinterDialog is used to transfer information on printing,
904 // so it will only be deleted here if dialog was cancelled
905 pDlgPrinter.disposeAndClear();
906 rReq.Ignore();
908 break;
913 SfxPrinter* SfxViewShell::GetPrinter( bool /*bCreate*/ )
915 return nullptr;
918 sal_uInt16 SfxViewShell::SetPrinter( SfxPrinter* /*pNewPrinter*/, SfxPrinterChangeFlags /*nDiffFlags*/ )
920 return 0;
923 std::unique_ptr<SfxTabPage> SfxViewShell::CreatePrintOptionsPage(weld::Container*, weld::DialogController*, const SfxItemSet&)
925 return nullptr;
928 bool SfxViewShell::HasPrintOptionsPage() const
930 return false;
933 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */