Bump version to 24.04.3.4
[LibreOffice.git] / sfx2 / source / view / viewprn.cxx
blob19fddbffdfa0c8e20bbf70f6654a44f8586b73ed
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_bOrigStatus;
72 bool m_bNeedsChange;
73 bool m_bApi;
74 bool m_bTempPrinter;
75 util::DateTime m_aLastPrinted;
76 OUString m_aLastPrintedBy;
78 Sequence< beans::PropertyValue > getMergedOptions() const;
79 const Any& getSelectionObject() const;
81 public:
82 SfxPrinterController( const VclPtr<Printer>& i_rPrinter,
83 Any i_Complete,
84 Any i_Selection,
85 const Any& i_rViewProp,
86 const Reference< view::XRenderable >& i_xRender,
87 bool i_bApi, bool i_bDirect,
88 SfxViewShell* pView,
89 const uno::Sequence< beans::PropertyValue >& rProps
92 virtual void Notify( SfxBroadcaster&, const SfxHint& ) override;
94 virtual int getPageCount() const override;
95 virtual Sequence< beans::PropertyValue > getPageParameters( int i_nPage ) const override;
96 virtual void printPage( int i_nPage ) const override;
97 virtual void jobStarted() override;
98 virtual void jobFinished( css::view::PrintableState ) override;
101 SfxPrinterController::SfxPrinterController( const VclPtr<Printer>& i_rPrinter,
102 Any i_Complete,
103 Any i_Selection,
104 const Any& i_rViewProp,
105 const Reference< view::XRenderable >& i_xRender,
106 bool i_bApi, bool i_bDirect,
107 SfxViewShell* pView,
108 const uno::Sequence< beans::PropertyValue >& rProps
110 : PrinterController(i_rPrinter, pView ? pView->GetFrameWeld() : nullptr)
111 , maCompleteSelection(std::move( i_Complete ))
112 , maSelection(std::move( i_Selection ))
113 , mxRenderable( i_xRender )
114 , mpLastPrinter( nullptr )
115 , mpViewShell( pView )
116 , mpObjectShell(nullptr)
117 , m_bOrigStatus( false )
118 , m_bNeedsChange( false )
119 , m_bApi(i_bApi)
120 , m_bTempPrinter( i_rPrinter )
122 if ( mpViewShell )
124 StartListening( *mpViewShell );
125 mpObjectShell = mpViewShell->GetObjectShell();
126 StartListening( *mpObjectShell );
129 // initialize extra ui options
130 if( mxRenderable.is() )
132 for (const auto& rProp : rProps)
133 setValue( rProp.Name, rProp.Value );
135 Sequence< beans::PropertyValue > aRenderOptions{
136 comphelper::makePropertyValue("ExtraPrintUIOptions", Any{}),
137 comphelper::makePropertyValue("View", i_rViewProp),
138 comphelper::makePropertyValue("IsPrinter", true)
142 const Sequence< beans::PropertyValue > aRenderParms( mxRenderable->getRenderer( 0 , getSelectionObject(), aRenderOptions ) );
143 for( const auto& rRenderParm : aRenderParms )
145 if ( rRenderParm.Name == "ExtraPrintUIOptions" )
147 Sequence< beans::PropertyValue > aUIProps;
148 rRenderParm.Value >>= aUIProps;
149 setUIOptions( aUIProps );
151 else if( rRenderParm.Name == "NUp" )
153 setValue( rRenderParm.Name, rRenderParm.Value );
157 catch( lang::IllegalArgumentException& )
159 // the first renderer should always be available for the UI options,
160 // but catch the exception to be safe
164 // set some job parameters
165 setValue( "IsApi", Any( i_bApi ) );
166 setValue( "IsDirect", Any( i_bDirect ) );
167 setValue( "IsPrinter", Any( true ) );
168 setValue( "View", i_rViewProp );
171 void SfxPrinterController::Notify( SfxBroadcaster& , const SfxHint& rHint )
173 if ( rHint.GetId() == SfxHintId::Dying )
175 EndListening(*mpViewShell);
176 EndListening(*mpObjectShell);
177 dialogsParentClosing();
178 mpViewShell = nullptr;
179 mpObjectShell = nullptr;
183 const Any& SfxPrinterController::getSelectionObject() const
185 const beans::PropertyValue* pVal = getValue( OUString( "PrintSelectionOnly" ) );
186 if( pVal )
188 bool bSel = false;
189 pVal->Value >>= bSel;
190 return bSel ? maSelection : maCompleteSelection;
193 sal_Int32 nChoice = 0;
194 pVal = getValue( OUString( "PrintContent" ) );
195 if( pVal )
196 pVal->Value >>= nChoice;
198 return (nChoice > 1) ? maSelection : maCompleteSelection;
201 Sequence< beans::PropertyValue > SfxPrinterController::getMergedOptions() const
203 VclPtr<Printer> xPrinter( getPrinter() );
204 if( xPrinter.get() != mpLastPrinter )
206 mpLastPrinter = xPrinter.get();
207 rtl::Reference<VCLXDevice> pXDevice = new VCLXDevice();
208 pXDevice->SetOutputDevice( mpLastPrinter );
209 mxDevice.set( pXDevice );
212 Sequence< beans::PropertyValue > aRenderOptions{ comphelper::makePropertyValue(
213 "RenderDevice", mxDevice) };
215 aRenderOptions = getJobProperties( aRenderOptions );
216 return aRenderOptions;
219 int SfxPrinterController::getPageCount() const
221 int nPages = 0;
222 VclPtr<Printer> xPrinter( getPrinter() );
223 if( mxRenderable.is() && xPrinter )
225 Sequence< beans::PropertyValue > aJobOptions( getMergedOptions() );
228 nPages = mxRenderable->getRendererCount( getSelectionObject(), aJobOptions );
230 catch (lang::DisposedException &)
232 SAL_WARN("sfx", "SfxPrinterController: document disposed while printing");
233 const_cast<SfxPrinterController*>(this)->setJobState(
234 view::PrintableState_JOB_ABORTED);
237 return nPages;
240 Sequence< beans::PropertyValue > SfxPrinterController::getPageParameters( int i_nPage ) const
242 VclPtr<Printer> xPrinter( getPrinter() );
243 Sequence< beans::PropertyValue > aResult;
245 if (mxRenderable.is() && xPrinter)
247 Sequence< beans::PropertyValue > aJobOptions( getMergedOptions() );
250 aResult = mxRenderable->getRenderer( i_nPage, getSelectionObject(), aJobOptions );
252 catch( lang::IllegalArgumentException& )
255 catch (lang::DisposedException &)
257 SAL_WARN("sfx", "SfxPrinterController: document disposed while printing");
258 const_cast<SfxPrinterController*>(this)->setJobState(
259 view::PrintableState_JOB_ABORTED);
262 return aResult;
265 void SfxPrinterController::printPage( int i_nPage ) const
267 VclPtr<Printer> xPrinter( getPrinter() );
268 if( !mxRenderable.is() || !xPrinter )
269 return;
271 Sequence< beans::PropertyValue > aJobOptions( getMergedOptions() );
274 mxRenderable->render( i_nPage, getSelectionObject(), aJobOptions );
276 catch( lang::IllegalArgumentException& )
278 // don't care enough about nonexistent page here
279 // to provoke a crash
281 catch (lang::DisposedException &)
283 SAL_WARN("sfx", "SfxPrinterController: document disposed while printing");
284 const_cast<SfxPrinterController*>(this)->setJobState(
285 view::PrintableState_JOB_ABORTED);
289 void SfxPrinterController::jobStarted()
291 if ( !mpObjectShell )
292 return;
294 m_bOrigStatus = mpObjectShell->IsEnableSetModified();
296 // check configuration: shall update of printing information in DocInfo set the document to "modified"?
297 if (m_bOrigStatus && !officecfg::Office::Common::Print::PrintingModifiesDocument::get())
299 mpObjectShell->EnableSetModified( false );
300 m_bNeedsChange = true;
303 // refresh document info
304 uno::Reference<document::XDocumentProperties> xDocProps(mpObjectShell->getDocProperties());
305 m_aLastPrintedBy = xDocProps->getPrintedBy();
306 m_aLastPrinted = xDocProps->getPrintDate();
308 xDocProps->setPrintedBy( mpObjectShell->IsUseUserData()
309 ? SvtUserOptions().GetFullName()
310 : OUString() );
311 ::DateTime now( ::DateTime::SYSTEM );
313 xDocProps->setPrintDate( now.GetUNODateTime() );
315 uno::Sequence < beans::PropertyValue > aOpts;
316 aOpts = getJobProperties( aOpts );
318 uno::Reference< frame::XController2 > xController;
319 if ( mpViewShell )
320 xController.set( mpViewShell->GetController(), uno::UNO_QUERY );
322 mpObjectShell->Broadcast( SfxPrintingHint(
323 view::PrintableState_JOB_STARTED, aOpts, mpObjectShell, xController ) );
326 void SfxPrinterController::jobFinished( css::view::PrintableState nState )
328 if ( !mpObjectShell )
329 return;
331 bool bCopyJobSetup = false;
332 mpObjectShell->Broadcast( SfxPrintingHint( nState ) );
333 switch ( nState )
335 case view::PrintableState_JOB_SPOOLING_FAILED :
336 case view::PrintableState_JOB_FAILED :
338 // "real" problem (not simply printing cancelled by user)
339 OUString aMsg( SfxResId(STR_NOSTARTPRINTER) );
340 if ( !m_bApi )
342 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(mpViewShell->GetFrameWeld(),
343 VclMessageType::Warning, VclButtonsType::Ok,
344 aMsg));
345 xBox->run();
347 [[fallthrough]];
349 case view::PrintableState_JOB_ABORTED :
351 // printing not successful, reset DocInfo
352 uno::Reference<document::XDocumentProperties> xDocProps(mpObjectShell->getDocProperties());
353 xDocProps->setPrintedBy(m_aLastPrintedBy);
354 xDocProps->setPrintDate(m_aLastPrinted);
355 break;
358 case view::PrintableState_JOB_SPOOLED :
359 case view::PrintableState_JOB_COMPLETED :
361 SfxBindings& rBind = mpViewShell->GetViewFrame().GetBindings();
362 rBind.Invalidate( SID_PRINTDOC );
363 rBind.Invalidate( SID_PRINTDOCDIRECT );
364 rBind.Invalidate( SID_SETUPPRINTER );
365 bCopyJobSetup = ! m_bTempPrinter;
366 break;
369 default:
370 break;
373 if( bCopyJobSetup && mpViewShell )
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 SfxPrinter* pDocPrt = mpViewShell->GetPrinter(true);
381 if( pDocPrt )
383 if( pDocPrt->GetName() == getPrinter()->GetName() )
384 pDocPrt->SetJobSetup( getPrinter()->GetJobSetup() );
385 else
387 VclPtr<SfxPrinter> pNewPrt = VclPtr<SfxPrinter>::Create( pDocPrt->GetOptions().Clone(), getPrinter()->GetName() );
388 pNewPrt->SetJobSetup( getPrinter()->GetJobSetup() );
389 mpViewShell->SetPrinter( pNewPrt, SfxPrinterChangeFlags::PRINTER | SfxPrinterChangeFlags::JOBSETUP );
394 if ( m_bNeedsChange )
395 mpObjectShell->EnableSetModified( m_bOrigStatus );
397 if ( mpViewShell )
399 mpViewShell->pImpl->m_xPrinterController.reset();
403 namespace {
406 An instance of this class is created for the life span of the
407 printer dialogue, to create in its click handler for the additions by the
408 virtual method of the derived SfxViewShell generated print options dialogue
409 and to cache the options set there as SfxItemSet.
411 class SfxDialogExecutor_Impl
413 private:
414 SfxViewShell* _pViewSh;
415 PrinterSetupDialog& _rSetupParent;
416 std::unique_ptr<SfxItemSet> _pOptions;
417 bool _bHelpDisabled;
419 DECL_LINK( Execute, weld::Button&, void );
421 public:
422 SfxDialogExecutor_Impl( SfxViewShell* pViewSh, PrinterSetupDialog& rParent );
424 Link<weld::Button&, void> GetLink() const { return LINK(const_cast<SfxDialogExecutor_Impl*>(this), SfxDialogExecutor_Impl, Execute); }
425 const SfxItemSet* GetOptions() const { return _pOptions.get(); }
426 void DisableHelp() { _bHelpDisabled = true; }
431 SfxDialogExecutor_Impl::SfxDialogExecutor_Impl( SfxViewShell* pViewSh, PrinterSetupDialog& rParent ) :
433 _pViewSh ( pViewSh ),
434 _rSetupParent ( rParent ),
435 _bHelpDisabled ( false )
440 IMPL_LINK_NOARG(SfxDialogExecutor_Impl, Execute, weld::Button&, void)
442 // Options noted locally
443 if ( !_pOptions )
445 _pOptions = static_cast<SfxPrinter*>( _rSetupParent.GetPrinter() )->GetOptions().Clone();
448 assert(_pOptions);
449 if (!_pOptions)
450 return;
452 // Create Dialog
453 SfxPrintOptionsDialog aDlg(_rSetupParent.GetFrameWeld(), _pViewSh, _pOptions.get() );
454 if (_bHelpDisabled)
455 aDlg.DisableHelp();
456 if (aDlg.run() == RET_OK)
458 _pOptions = aDlg.GetOptions().Clone();
463 Internal method for setting the differences between 'pNewPrinter' to the
464 current printer. pNewPrinter is either taken over or deleted.
466 void SfxViewShell::SetPrinter_Impl( VclPtr<SfxPrinter>& pNewPrinter )
468 // get current Printer
469 SfxPrinter *pDocPrinter = GetPrinter();
471 // Evaluate Printer Options
472 const SfxFlagItem *pFlagItem = pDocPrinter->GetOptions().GetItemIfSet( SID_PRINTER_CHANGESTODOC, false );
473 bool bOriToDoc = pFlagItem && (static_cast<SfxPrinterChangeFlags>(pFlagItem->GetValue()) & SfxPrinterChangeFlags::CHG_ORIENTATION);
474 bool bSizeToDoc = pFlagItem && (static_cast<SfxPrinterChangeFlags>(pFlagItem->GetValue()) & SfxPrinterChangeFlags::CHG_SIZE);
476 // Determine the previous format and size
477 Orientation eOldOri = pDocPrinter->GetOrientation();
478 Size aOldPgSz = pDocPrinter->GetPaperSizePixel();
480 // Determine the new format and size
481 Orientation eNewOri = pNewPrinter->GetOrientation();
482 Size aNewPgSz = pNewPrinter->GetPaperSizePixel();
484 // Determine the changes in page format
485 bool bOriChg = (eOldOri != eNewOri) && bOriToDoc;
486 bool bPgSzChg = ( aOldPgSz.Height() !=
487 ( bOriChg ? aNewPgSz.Width() : aNewPgSz.Height() ) ||
488 aOldPgSz.Width() !=
489 ( bOriChg ? aNewPgSz.Height() : aNewPgSz.Width() ) ) &&
490 bSizeToDoc;
492 // Message and Flags for page format changes
493 OUString aMsg;
494 SfxPrinterChangeFlags nNewOpt = SfxPrinterChangeFlags::NONE;
495 if( bOriChg && bPgSzChg )
497 aMsg = SfxResId(STR_PRINT_NEWORISIZE);
498 nNewOpt = SfxPrinterChangeFlags::CHG_ORIENTATION | SfxPrinterChangeFlags::CHG_SIZE;
500 else if (bOriChg )
502 aMsg = SfxResId(STR_PRINT_NEWORI);
503 nNewOpt = SfxPrinterChangeFlags::CHG_ORIENTATION;
505 else if (bPgSzChg)
507 aMsg = SfxResId(STR_PRINT_NEWSIZE);
508 nNewOpt = SfxPrinterChangeFlags::CHG_SIZE;
511 // Summarize in this variable what has been changed.
512 SfxPrinterChangeFlags nChangedFlags = SfxPrinterChangeFlags::NONE;
514 // Ask if possible, if page format should be taken over from printer.
515 if (bOriChg || bPgSzChg)
517 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(nullptr,
518 VclMessageType::Question, VclButtonsType::YesNo,
519 aMsg));
520 if (RET_YES == xBox->run())
522 // Flags with changes for <SetPrinter(SfxPrinter*)> are maintained
523 nChangedFlags |= nNewOpt;
527 // Was the printer selection changed from Default to Specific
528 // or the other way around?
529 if ( (pNewPrinter->GetName() != pDocPrinter->GetName())
530 || (pDocPrinter->IsDefPrinter() != pNewPrinter->IsDefPrinter()) )
532 nChangedFlags |= SfxPrinterChangeFlags::PRINTER|SfxPrinterChangeFlags::JOBSETUP;
533 if ( ! (pNewPrinter->GetOptions() == pDocPrinter->GetOptions()) )
535 nChangedFlags |= SfxPrinterChangeFlags::OPTIONS;
538 pDocPrinter = pNewPrinter;
540 else
542 // Compare extra options
543 if ( ! (pNewPrinter->GetOptions() == pDocPrinter->GetOptions()) )
545 // Option have changed
546 pDocPrinter->SetOptions( pNewPrinter->GetOptions() );
547 nChangedFlags |= SfxPrinterChangeFlags::OPTIONS;
550 // Compare JobSetups
551 JobSetup aNewJobSetup = pNewPrinter->GetJobSetup();
552 JobSetup aOldJobSetup = pDocPrinter->GetJobSetup();
553 if ( aNewJobSetup != aOldJobSetup )
555 nChangedFlags |= SfxPrinterChangeFlags::JOBSETUP;
558 // Keep old changed Printer.
559 pDocPrinter->SetPrinterProps( pNewPrinter );
560 pNewPrinter.disposeAndClear();
563 if ( SfxPrinterChangeFlags::NONE != nChangedFlags )
564 // SetPrinter will delete the old printer if it changes
565 SetPrinter( pDocPrinter, nChangedFlags );
568 void SfxViewShell::StartPrint( const uno::Sequence < beans::PropertyValue >& rProps, bool bIsAPI, bool bIsDirect )
570 assert( !pImpl->m_xPrinterController );
572 // get the current selection; our controller should know it
573 Reference< frame::XController > xController( GetController() );
574 Reference< view::XSelectionSupplier > xSupplier( xController, UNO_QUERY );
576 Any aSelection;
577 if( xSupplier.is() )
578 aSelection = xSupplier->getSelection();
579 else
580 aSelection <<= GetObjectShell()->GetModel();
581 Any aComplete( Any( GetObjectShell()->GetModel() ) );
582 Any aViewProp( xController );
583 VclPtr<Printer> aPrt;
585 const beans::PropertyValue* pVal = std::find_if(rProps.begin(), rProps.end(),
586 [](const beans::PropertyValue& rVal) { return rVal.Name == "PrinterName"; });
587 if (pVal != rProps.end())
589 OUString aPrinterName;
590 pVal->Value >>= aPrinterName;
591 aPrt.reset( VclPtr<Printer>::Create( aPrinterName ) );
594 std::shared_ptr<vcl::PrinterController> xNewController(std::make_shared<SfxPrinterController>(
595 aPrt,
596 aComplete,
597 aSelection,
598 aViewProp,
599 GetRenderable(),
600 bIsAPI,
601 bIsDirect,
602 this,
603 rProps
605 pImpl->m_xPrinterController = xNewController;
607 // When no JobName was specified via com::sun::star::view::PrintOptions::JobName ,
608 // use the document title as default job name
609 css::beans::PropertyValue* pJobNameVal = xNewController->getValue("JobName");
610 if (!pJobNameVal)
612 if (SfxObjectShell* pDoc = GetObjectShell())
614 xNewController->setValue("JobName", Any(pDoc->GetTitle(1)));
615 xNewController->setPrinterModified(mbPrinterSettingsModified);
620 void SfxViewShell::ExecPrint( const uno::Sequence < beans::PropertyValue >& rProps, bool bIsAPI, bool bIsDirect )
622 StartPrint( rProps, bIsAPI, bIsDirect );
623 // FIXME: job setup
624 SfxPrinter* pDocPrt = GetPrinter();
625 JobSetup aJobSetup = pDocPrt ? pDocPrt->GetJobSetup() : JobSetup();
626 Printer::PrintJob( GetPrinterController(), aJobSetup );
629 const std::shared_ptr< vcl::PrinterController >& SfxViewShell::GetPrinterController() const
631 return pImpl->m_xPrinterController;
634 Printer* SfxViewShell::GetActivePrinter() const
636 return pImpl->m_xPrinterController
637 ? pImpl->m_xPrinterController->getPrinter().get() : nullptr;
640 void SfxViewShell::ExecPrint_Impl( SfxRequest &rReq )
642 sal_uInt16 nDialogRet = RET_CANCEL;
643 VclPtr<SfxPrinter> pPrinter;
644 bool bSilent = false;
646 // does the function have been called by the user interface or by an API call
647 bool bIsAPI = rReq.GetArgs() && rReq.GetArgs()->Count();
648 if ( bIsAPI )
650 // the function have been called by the API
652 // Should it be visible on the user interface,
653 // should it launch popup dialogue ?
654 const SfxBoolItem* pSilentItem = rReq.GetArg<SfxBoolItem>(SID_SILENT);
655 bSilent = pSilentItem && pSilentItem->GetValue();
658 // no help button in dialogs if called from the help window
659 // (pressing help button would exchange the current page inside the help
660 // document that is going to be printed!)
661 SfxMedium* pMedium = GetViewFrame().GetObjectShell()->GetMedium();
662 std::shared_ptr<const SfxFilter> pFilter = pMedium ? pMedium->GetFilter() : nullptr;
663 bool bPrintOnHelp = ( pFilter && pFilter->GetFilterName() == "writer_web_HTML_help" );
665 const sal_uInt16 nId = rReq.GetSlot();
666 switch( nId )
668 case SID_PRINTDOC: // display the printer selection and properties dialogue : File > Print...
669 case SID_PRINTDOCDIRECT: // Print the document directly, without displaying the dialogue
671 SfxObjectShell* pDoc = GetObjectShell();
673 // derived class may decide to abort this
674 if( pDoc == nullptr || !pDoc->QuerySlotExecutable( nId ) )
676 rReq.SetReturnValue( SfxBoolItem( 0, false ) );
677 return;
680 pDoc->QueryHiddenInformation(HiddenWarningFact::WhenPrinting);
682 // should we print only the selection or the whole document
683 const SfxBoolItem* pSelectItem = rReq.GetArg<SfxBoolItem>(SID_SELECTION);
684 bool bSelection = ( pSelectItem != nullptr && pSelectItem->GetValue() );
685 // detect non api call from writer ( that adds SID_SELECTION ) and reset bIsAPI
686 if ( pSelectItem && rReq.GetArgs()->Count() == 1 )
687 bIsAPI = false;
689 uno::Sequence < beans::PropertyValue > aProps;
690 if ( bIsAPI )
692 // supported properties:
693 // String PrinterName
694 // String FileName
695 // Int16 From
696 // Int16 To
697 // In16 Copies
698 // String RangeText
699 // bool Selection
700 // bool Asynchron
701 // bool Collate
702 // bool Silent
704 // the TransformItems function overwrite aProps
705 TransformItems( nId, *rReq.GetArgs(), aProps, GetInterface()->GetSlot(nId) );
707 for ( auto& rProp : asNonConstRange(aProps) )
709 if ( rProp.Name == "Copies" )
711 rProp.Name = "CopyCount";
713 else if ( rProp.Name == "RangeText" )
715 rProp.Name = "Pages";
717 else if ( rProp.Name == "Asynchron" )
719 rProp.Name = "Wait";
720 bool bAsynchron = false;
721 rProp.Value >>= bAsynchron;
722 rProp.Value <<= !bAsynchron;
724 else if ( rProp.Name == "Silent" )
726 rProp.Name = "MonitorVisible";
727 bool bPrintSilent = false;
728 rProp.Value >>= bPrintSilent;
729 rProp.Value <<= !bPrintSilent;
734 // we will add the "PrintSelectionOnly" or "HideHelpButton" properties
735 // we have to increase the capacity of aProps
736 sal_Int32 nLen = aProps.getLength();
737 aProps.realloc( nLen + 1 );
738 auto pProps = aProps.getArray();
740 // HACK: writer sets the SID_SELECTION item when printing directly and expects
741 // to get only the selection document in that case (see getSelectionObject)
742 // however it also reacts to the PrintContent property. We need this distinction here, too,
743 // else one of the combinations print / print direct and selection / all will not work.
744 // it would be better if writer handled this internally
745 if( nId == SID_PRINTDOCDIRECT )
747 pProps[nLen].Name = "PrintSelectionOnly";
748 pProps[nLen].Value <<= bSelection;
750 else // if nId == SID_PRINTDOC ; nothing to do with the previous HACK
752 // should the printer selection and properties dialogue display an help button
753 pProps[nLen].Name = "HideHelpButton";
754 pProps[nLen].Value <<= bPrintOnHelp;
757 ExecPrint( aProps, bIsAPI, (nId == SID_PRINTDOCDIRECT) );
759 // FIXME: Recording
760 rReq.Done();
761 break;
764 case SID_PRINTER_NAME: // for recorded macros
766 // get printer and printer settings from the document
767 SfxPrinter* pDocPrinter = GetPrinter(true);
768 const SfxStringItem* pPrinterItem = rReq.GetArg<SfxStringItem>(SID_PRINTER_NAME);
769 if (!pPrinterItem)
771 rReq.Ignore();
772 break;
774 // use PrinterName parameter to create a printer
775 pPrinter = VclPtr<SfxPrinter>::Create(pDocPrinter->GetOptions().Clone(),
776 pPrinterItem->GetValue());
778 if (!pPrinter->IsKnown())
780 pPrinter.disposeAndClear();
781 rReq.Ignore();
782 break;
784 SetPrinter(pPrinter, SfxPrinterChangeFlags::PRINTER);
785 rReq.Done();
786 break;
788 case SID_SETUPPRINTER : // display the printer settings dialog : File > Printer Settings...
790 // get printer and printer settings from the document
791 SfxPrinter *pDocPrinter = GetPrinter(true);
793 // look for printer in parameters
794 const SfxStringItem* pPrinterItem = rReq.GetArg<SfxStringItem>(SID_PRINTER_NAME);
795 if ( pPrinterItem )
797 // use PrinterName parameter to create a printer
798 pPrinter = VclPtr<SfxPrinter>::Create( pDocPrinter->GetOptions().Clone(), pPrinterItem->GetValue() );
800 // if printer is unknown, it can't be used - now printer from document will be used
801 if ( !pPrinter->IsKnown() )
802 pPrinter.disposeAndClear();
805 // no PrinterName parameter in ItemSet or the PrinterName points to an unknown printer
806 if ( !pPrinter )
807 // use default printer from document
808 pPrinter = pDocPrinter;
810 if( !pPrinter || !pPrinter->IsValid() )
812 // no valid printer either in ItemSet or at the document
813 if ( !bSilent )
815 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(nullptr,
816 VclMessageType::Warning, VclButtonsType::Ok,
817 SfxResId(STR_NODEFPRINTER)));
818 xBox->run();
821 rReq.SetReturnValue(SfxBoolItem(0,false));
823 break;
826 // FIXME: printer isn't used for printing anymore!
827 if( pPrinter->IsPrinting() )
829 // if printer is busy, abort configuration
830 if ( !bSilent )
832 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(nullptr,
833 VclMessageType::Info, VclButtonsType::Ok,
834 SfxResId(STR_ERROR_PRINTER_BUSY)));
835 xBox->run();
837 rReq.SetReturnValue(SfxBoolItem(0,false));
839 return;
842 // Open Printer Setup dialog (needs a temporary printer)
843 VclPtr<SfxPrinter> pDlgPrinter = pPrinter->Clone();
844 PrinterSetupDialog aPrintSetupDlg(GetFrameWeld());
845 std::unique_ptr<SfxDialogExecutor_Impl> pExecutor;
847 if (pImpl->m_bHasPrintOptions && HasPrintOptionsPage())
849 // additional controls for dialog
850 pExecutor.reset(new SfxDialogExecutor_Impl(this, aPrintSetupDlg));
851 if (bPrintOnHelp)
852 pExecutor->DisableHelp();
853 aPrintSetupDlg.SetOptionsHdl(pExecutor->GetLink());
856 aPrintSetupDlg.SetPrinter(pDlgPrinter);
857 nDialogRet = aPrintSetupDlg.run();
859 if (pExecutor && pExecutor->GetOptions())
861 if (nDialogRet == RET_OK)
862 // remark: have to be recorded if possible!
863 pDlgPrinter->SetOptions(*pExecutor->GetOptions());
864 else
866 pPrinter->SetOptions(*pExecutor->GetOptions());
867 SetPrinter(pPrinter, SfxPrinterChangeFlags::OPTIONS);
871 // no recording of PrinterSetup except printer name (is printer dependent)
872 rReq.Ignore();
874 if (nDialogRet == RET_OK)
876 if (pPrinter->GetName() != pDlgPrinter->GetName())
878 // user has changed the printer -> macro recording
879 SfxRequest aReq(GetViewFrame(), SID_PRINTER_NAME);
880 aReq.AppendItem(SfxStringItem(SID_PRINTER_NAME, pDlgPrinter->GetName()));
881 aReq.Done();
884 // take the changes made in the dialog
885 SetPrinter_Impl(pDlgPrinter);
887 // forget new printer, it was taken over (as pPrinter) or deleted
888 pDlgPrinter = nullptr;
889 mbPrinterSettingsModified = true;
891 else
893 // PrinterDialog is used to transfer information on printing,
894 // so it will only be deleted here if dialog was cancelled
895 pDlgPrinter.disposeAndClear();
896 rReq.Ignore();
898 break;
903 SfxPrinter* SfxViewShell::GetPrinter( bool /*bCreate*/ )
905 return nullptr;
908 sal_uInt16 SfxViewShell::SetPrinter( SfxPrinter* /*pNewPrinter*/, SfxPrinterChangeFlags /*nDiffFlags*/ )
910 return 0;
913 std::unique_ptr<SfxTabPage> SfxViewShell::CreatePrintOptionsPage(weld::Container*, weld::DialogController*, const SfxItemSet&)
915 return nullptr;
918 bool SfxViewShell::HasPrintOptionsPage() const
920 return false;
923 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */