summaryrefslogtreecommitdiffstats
path: root/sfx2/source/view/viewprn.cxx
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--sfx2/source/view/viewprn.cxx916
1 files changed, 916 insertions, 0 deletions
diff --git a/sfx2/source/view/viewprn.cxx b/sfx2/source/view/viewprn.cxx
new file mode 100644
index 000000000..975dad2a6
--- /dev/null
+++ b/sfx2/source/view/viewprn.cxx
@@ -0,0 +1,916 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <memory>
+
+#include <com/sun/star/document/XDocumentProperties.hpp>
+#include <com/sun/star/view/XRenderable.hpp>
+#include <com/sun/star/view/XSelectionSupplier.hpp>
+
+#include <comphelper/propertyvalue.hxx>
+#include <officecfg/Office/Common.hxx>
+#include <sal/log.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/weld.hxx>
+#include <svtools/prnsetup.hxx>
+#include <svl/flagitem.hxx>
+#include <svl/stritem.hxx>
+#include <svl/eitem.hxx>
+#include <unotools/useroptions.hxx>
+#include <tools/datetime.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/objface.hxx>
+#include <sfx2/viewsh.hxx>
+#include "viewimp.hxx"
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/printer.hxx>
+#include <sfx2/sfxresid.hxx>
+#include <sfx2/request.hxx>
+#include <sfx2/objsh.hxx>
+#include <sfx2/event.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/docfilt.hxx>
+#include <sfx2/sfxsids.hrc>
+#include <sfx2/strings.hrc>
+#include <sfx2/sfxuno.hxx>
+#include <sfx2/tabdlg.hxx>
+
+#include <toolkit/awt/vclxdevice.hxx>
+
+#include "prnmon.hxx"
+
+using namespace com::sun::star;
+using namespace com::sun::star::uno;
+
+class SfxPrinterController : public vcl::PrinterController, public SfxListener
+{
+ Any maCompleteSelection;
+ Any maSelection;
+ Reference< view::XRenderable > mxRenderable;
+ mutable VclPtr<Printer> mpLastPrinter;
+ mutable Reference<awt::XDevice> mxDevice;
+ SfxViewShell* mpViewShell;
+ SfxObjectShell* mpObjectShell;
+ bool m_bOrigStatus;
+ bool m_bNeedsChange;
+ bool m_bApi;
+ bool m_bTempPrinter;
+ util::DateTime m_aLastPrinted;
+ OUString m_aLastPrintedBy;
+
+ Sequence< beans::PropertyValue > getMergedOptions() const;
+ const Any& getSelectionObject() const;
+
+public:
+ SfxPrinterController( const VclPtr<Printer>& i_rPrinter,
+ const Any& i_rComplete,
+ const Any& i_rSelection,
+ const Any& i_rViewProp,
+ const Reference< view::XRenderable >& i_xRender,
+ bool i_bApi, bool i_bDirect,
+ SfxViewShell* pView,
+ const uno::Sequence< beans::PropertyValue >& rProps
+ );
+
+ virtual void Notify( SfxBroadcaster&, const SfxHint& ) override;
+
+ virtual int getPageCount() const override;
+ virtual Sequence< beans::PropertyValue > getPageParameters( int i_nPage ) const override;
+ virtual void printPage( int i_nPage ) const override;
+ virtual void jobStarted() override;
+ virtual void jobFinished( css::view::PrintableState ) override;
+};
+
+SfxPrinterController::SfxPrinterController( const VclPtr<Printer>& i_rPrinter,
+ const Any& i_rComplete,
+ const Any& i_rSelection,
+ const Any& i_rViewProp,
+ const Reference< view::XRenderable >& i_xRender,
+ bool i_bApi, bool i_bDirect,
+ SfxViewShell* pView,
+ const uno::Sequence< beans::PropertyValue >& rProps
+ )
+ : PrinterController(i_rPrinter, pView ? pView->GetFrameWeld() : nullptr)
+ , maCompleteSelection( i_rComplete )
+ , maSelection( i_rSelection )
+ , mxRenderable( i_xRender )
+ , mpLastPrinter( nullptr )
+ , mpViewShell( pView )
+ , mpObjectShell(nullptr)
+ , m_bOrigStatus( false )
+ , m_bNeedsChange( false )
+ , m_bApi(i_bApi)
+ , m_bTempPrinter( i_rPrinter )
+{
+ if ( mpViewShell )
+ {
+ StartListening( *mpViewShell );
+ mpObjectShell = mpViewShell->GetObjectShell();
+ StartListening( *mpObjectShell );
+ }
+
+ // initialize extra ui options
+ if( mxRenderable.is() )
+ {
+ for (const auto& rProp : rProps)
+ setValue( rProp.Name, rProp.Value );
+
+ Sequence< beans::PropertyValue > aRenderOptions{
+ comphelper::makePropertyValue("ExtraPrintUIOptions", Any{}),
+ comphelper::makePropertyValue("View", i_rViewProp),
+ comphelper::makePropertyValue("IsPrinter", true)
+ };
+ try
+ {
+ const Sequence< beans::PropertyValue > aRenderParms( mxRenderable->getRenderer( 0 , getSelectionObject(), aRenderOptions ) );
+ for( const auto& rRenderParm : aRenderParms )
+ {
+ if ( rRenderParm.Name == "ExtraPrintUIOptions" )
+ {
+ Sequence< beans::PropertyValue > aUIProps;
+ rRenderParm.Value >>= aUIProps;
+ setUIOptions( aUIProps );
+ }
+ else if( rRenderParm.Name == "NUp" )
+ {
+ setValue( rRenderParm.Name, rRenderParm.Value );
+ }
+ }
+ }
+ catch( lang::IllegalArgumentException& )
+ {
+ // the first renderer should always be available for the UI options,
+ // but catch the exception to be safe
+ }
+ }
+
+ // set some job parameters
+ setValue( "IsApi", Any( i_bApi ) );
+ setValue( "IsDirect", Any( i_bDirect ) );
+ setValue( "IsPrinter", Any( true ) );
+ setValue( "View", i_rViewProp );
+}
+
+void SfxPrinterController::Notify( SfxBroadcaster& , const SfxHint& rHint )
+{
+ if ( rHint.GetId() == SfxHintId::Dying )
+ {
+ EndListening(*mpViewShell);
+ EndListening(*mpObjectShell);
+ dialogsParentClosing();
+ mpViewShell = nullptr;
+ mpObjectShell = nullptr;
+ }
+}
+
+const Any& SfxPrinterController::getSelectionObject() const
+{
+ const beans::PropertyValue* pVal = getValue( OUString( "PrintSelectionOnly" ) );
+ if( pVal )
+ {
+ bool bSel = false;
+ pVal->Value >>= bSel;
+ return bSel ? maSelection : maCompleteSelection;
+ }
+
+ sal_Int32 nChoice = 0;
+ pVal = getValue( OUString( "PrintContent" ) );
+ if( pVal )
+ pVal->Value >>= nChoice;
+
+ return (nChoice > 1) ? maSelection : maCompleteSelection;
+}
+
+Sequence< beans::PropertyValue > SfxPrinterController::getMergedOptions() const
+{
+ VclPtr<Printer> xPrinter( getPrinter() );
+ if( xPrinter.get() != mpLastPrinter )
+ {
+ mpLastPrinter = xPrinter.get();
+ rtl::Reference<VCLXDevice> pXDevice = new VCLXDevice();
+ pXDevice->SetOutputDevice( mpLastPrinter );
+ mxDevice.set( pXDevice );
+ }
+
+ Sequence< beans::PropertyValue > aRenderOptions{ comphelper::makePropertyValue(
+ "RenderDevice", mxDevice) };
+
+ aRenderOptions = getJobProperties( aRenderOptions );
+ return aRenderOptions;
+}
+
+int SfxPrinterController::getPageCount() const
+{
+ int nPages = 0;
+ VclPtr<Printer> xPrinter( getPrinter() );
+ if( mxRenderable.is() && xPrinter )
+ {
+ Sequence< beans::PropertyValue > aJobOptions( getMergedOptions() );
+ try
+ {
+ nPages = mxRenderable->getRendererCount( getSelectionObject(), aJobOptions );
+ }
+ catch (lang::DisposedException &)
+ {
+ SAL_WARN("sfx", "SfxPrinterController: document disposed while printing");
+ const_cast<SfxPrinterController*>(this)->setJobState(
+ view::PrintableState_JOB_ABORTED);
+ }
+ }
+ return nPages;
+}
+
+Sequence< beans::PropertyValue > SfxPrinterController::getPageParameters( int i_nPage ) const
+{
+ VclPtr<Printer> xPrinter( getPrinter() );
+ Sequence< beans::PropertyValue > aResult;
+
+ if (mxRenderable.is() && xPrinter)
+ {
+ Sequence< beans::PropertyValue > aJobOptions( getMergedOptions() );
+ try
+ {
+ aResult = mxRenderable->getRenderer( i_nPage, getSelectionObject(), aJobOptions );
+ }
+ catch( lang::IllegalArgumentException& )
+ {
+ }
+ catch (lang::DisposedException &)
+ {
+ SAL_WARN("sfx", "SfxPrinterController: document disposed while printing");
+ const_cast<SfxPrinterController*>(this)->setJobState(
+ view::PrintableState_JOB_ABORTED);
+ }
+ }
+ return aResult;
+}
+
+void SfxPrinterController::printPage( int i_nPage ) const
+{
+ VclPtr<Printer> xPrinter( getPrinter() );
+ if( !mxRenderable.is() || !xPrinter )
+ return;
+
+ Sequence< beans::PropertyValue > aJobOptions( getMergedOptions() );
+ try
+ {
+ mxRenderable->render( i_nPage, getSelectionObject(), aJobOptions );
+ }
+ catch( lang::IllegalArgumentException& )
+ {
+ // don't care enough about nonexistent page here
+ // to provoke a crash
+ }
+ catch (lang::DisposedException &)
+ {
+ SAL_WARN("sfx", "SfxPrinterController: document disposed while printing");
+ const_cast<SfxPrinterController*>(this)->setJobState(
+ view::PrintableState_JOB_ABORTED);
+ }
+}
+
+void SfxPrinterController::jobStarted()
+{
+ if ( !mpObjectShell )
+ return;
+
+ m_bOrigStatus = mpObjectShell->IsEnableSetModified();
+
+ // check configuration: shall update of printing information in DocInfo set the document to "modified"?
+ if (m_bOrigStatus && !officecfg::Office::Common::Print::PrintingModifiesDocument::get())
+ {
+ mpObjectShell->EnableSetModified( false );
+ m_bNeedsChange = true;
+ }
+
+ // refresh document info
+ uno::Reference<document::XDocumentProperties> xDocProps(mpObjectShell->getDocProperties());
+ m_aLastPrintedBy = xDocProps->getPrintedBy();
+ m_aLastPrinted = xDocProps->getPrintDate();
+
+ xDocProps->setPrintedBy( mpObjectShell->IsUseUserData()
+ ? SvtUserOptions().GetFullName()
+ : OUString() );
+ ::DateTime now( ::DateTime::SYSTEM );
+
+ xDocProps->setPrintDate( now.GetUNODateTime() );
+
+ uno::Sequence < beans::PropertyValue > aOpts;
+ aOpts = getJobProperties( aOpts );
+
+ uno::Reference< frame::XController2 > xController;
+ if ( mpViewShell )
+ xController.set( mpViewShell->GetController(), uno::UNO_QUERY );
+
+ mpObjectShell->Broadcast( SfxPrintingHint(
+ view::PrintableState_JOB_STARTED, aOpts, mpObjectShell, xController ) );
+}
+
+void SfxPrinterController::jobFinished( css::view::PrintableState nState )
+{
+ if ( !mpObjectShell )
+ return;
+
+ bool bCopyJobSetup = false;
+ mpObjectShell->Broadcast( SfxPrintingHint( nState ) );
+ switch ( nState )
+ {
+ case view::PrintableState_JOB_SPOOLING_FAILED :
+ case view::PrintableState_JOB_FAILED :
+ {
+ // "real" problem (not simply printing cancelled by user)
+ OUString aMsg( SfxResId(STR_NOSTARTPRINTER) );
+ if ( !m_bApi )
+ {
+ std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(mpViewShell->GetFrameWeld(),
+ VclMessageType::Warning, VclButtonsType::Ok,
+ aMsg));
+ xBox->run();
+ }
+ [[fallthrough]];
+ }
+ case view::PrintableState_JOB_ABORTED :
+ {
+ // printing not successful, reset DocInfo
+ uno::Reference<document::XDocumentProperties> xDocProps(mpObjectShell->getDocProperties());
+ xDocProps->setPrintedBy(m_aLastPrintedBy);
+ xDocProps->setPrintDate(m_aLastPrinted);
+ break;
+ }
+
+ case view::PrintableState_JOB_SPOOLED :
+ case view::PrintableState_JOB_COMPLETED :
+ {
+ SfxBindings& rBind = mpViewShell->GetViewFrame()->GetBindings();
+ rBind.Invalidate( SID_PRINTDOC );
+ rBind.Invalidate( SID_PRINTDOCDIRECT );
+ rBind.Invalidate( SID_SETUPPRINTER );
+ bCopyJobSetup = ! m_bTempPrinter;
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ if( bCopyJobSetup && mpViewShell )
+ {
+ // #i114306#
+ // Note: this possibly creates a printer that gets immediately replaced
+ // by a new one. The reason for this is that otherwise we would not get
+ // the printer's SfxItemSet here to copy. Awkward, but at the moment there is no
+ // other way here to get the item set.
+ SfxPrinter* pDocPrt = mpViewShell->GetPrinter(true);
+ if( pDocPrt )
+ {
+ if( pDocPrt->GetName() == getPrinter()->GetName() )
+ pDocPrt->SetJobSetup( getPrinter()->GetJobSetup() );
+ else
+ {
+ VclPtr<SfxPrinter> pNewPrt = VclPtr<SfxPrinter>::Create( pDocPrt->GetOptions().Clone(), getPrinter()->GetName() );
+ pNewPrt->SetJobSetup( getPrinter()->GetJobSetup() );
+ mpViewShell->SetPrinter( pNewPrt, SfxPrinterChangeFlags::PRINTER | SfxPrinterChangeFlags::JOBSETUP );
+ }
+ }
+ }
+
+ if ( m_bNeedsChange )
+ mpObjectShell->EnableSetModified( m_bOrigStatus );
+
+ if ( mpViewShell )
+ {
+ mpViewShell->pImpl->m_xPrinterController.reset();
+ }
+}
+
+namespace {
+
+/**
+ An instance of this class is created for the life span of the
+ printer dialogue, to create in its click handler for the additions by the
+ virtual method of the derived SfxViewShell generated print options dialogue
+ and to cache the options set there as SfxItemSet.
+*/
+class SfxDialogExecutor_Impl
+{
+private:
+ SfxViewShell* _pViewSh;
+ PrinterSetupDialog& _rSetupParent;
+ std::unique_ptr<SfxItemSet> _pOptions;
+ bool _bHelpDisabled;
+
+ DECL_LINK( Execute, weld::Button&, void );
+
+public:
+ SfxDialogExecutor_Impl( SfxViewShell* pViewSh, PrinterSetupDialog& rParent );
+
+ Link<weld::Button&, void> GetLink() const { return LINK(const_cast<SfxDialogExecutor_Impl*>(this), SfxDialogExecutor_Impl, Execute); }
+ const SfxItemSet* GetOptions() const { return _pOptions.get(); }
+ void DisableHelp() { _bHelpDisabled = true; }
+};
+
+}
+
+SfxDialogExecutor_Impl::SfxDialogExecutor_Impl( SfxViewShell* pViewSh, PrinterSetupDialog& rParent ) :
+
+ _pViewSh ( pViewSh ),
+ _rSetupParent ( rParent ),
+ _bHelpDisabled ( false )
+
+{
+}
+
+IMPL_LINK_NOARG(SfxDialogExecutor_Impl, Execute, weld::Button&, void)
+{
+ // Options noted locally
+ if ( !_pOptions )
+ {
+ _pOptions = static_cast<SfxPrinter*>( _rSetupParent.GetPrinter() )->GetOptions().Clone();
+ }
+
+ assert(_pOptions);
+ if (!_pOptions)
+ return;
+
+ // Create Dialog
+ SfxPrintOptionsDialog aDlg(_rSetupParent.GetFrameWeld(), _pViewSh, _pOptions.get() );
+ if (_bHelpDisabled)
+ aDlg.DisableHelp();
+ if (aDlg.run() == RET_OK)
+ {
+ _pOptions = aDlg.GetOptions().Clone();
+ }
+}
+
+/**
+ Internal method for setting the differences between 'pNewPrinter' to the
+ current printer. pNewPrinter is either taken over or deleted.
+*/
+void SfxViewShell::SetPrinter_Impl( VclPtr<SfxPrinter>& pNewPrinter )
+{
+ // get current Printer
+ SfxPrinter *pDocPrinter = GetPrinter();
+
+ // Evaluate Printer Options
+ const SfxFlagItem *pFlagItem = pDocPrinter->GetOptions().GetItemIfSet( SID_PRINTER_CHANGESTODOC, false );
+ bool bOriToDoc = pFlagItem && (static_cast<SfxPrinterChangeFlags>(pFlagItem->GetValue()) & SfxPrinterChangeFlags::CHG_ORIENTATION);
+ bool bSizeToDoc = pFlagItem && (static_cast<SfxPrinterChangeFlags>(pFlagItem->GetValue()) & SfxPrinterChangeFlags::CHG_SIZE);
+
+ // Determine the previous format and size
+ Orientation eOldOri = pDocPrinter->GetOrientation();
+ Size aOldPgSz = pDocPrinter->GetPaperSizePixel();
+
+ // Determine the new format and size
+ Orientation eNewOri = pNewPrinter->GetOrientation();
+ Size aNewPgSz = pNewPrinter->GetPaperSizePixel();
+
+ // Determine the changes in page format
+ bool bOriChg = (eOldOri != eNewOri) && bOriToDoc;
+ bool bPgSzChg = ( aOldPgSz.Height() !=
+ ( bOriChg ? aNewPgSz.Width() : aNewPgSz.Height() ) ||
+ aOldPgSz.Width() !=
+ ( bOriChg ? aNewPgSz.Height() : aNewPgSz.Width() ) ) &&
+ bSizeToDoc;
+
+ // Message and Flags for page format changes
+ OUString aMsg;
+ SfxPrinterChangeFlags nNewOpt = SfxPrinterChangeFlags::NONE;
+ if( bOriChg && bPgSzChg )
+ {
+ aMsg = SfxResId(STR_PRINT_NEWORISIZE);
+ nNewOpt = SfxPrinterChangeFlags::CHG_ORIENTATION | SfxPrinterChangeFlags::CHG_SIZE;
+ }
+ else if (bOriChg )
+ {
+ aMsg = SfxResId(STR_PRINT_NEWORI);
+ nNewOpt = SfxPrinterChangeFlags::CHG_ORIENTATION;
+ }
+ else if (bPgSzChg)
+ {
+ aMsg = SfxResId(STR_PRINT_NEWSIZE);
+ nNewOpt = SfxPrinterChangeFlags::CHG_SIZE;
+ }
+
+ // Summarize in this variable what has been changed.
+ SfxPrinterChangeFlags nChangedFlags = SfxPrinterChangeFlags::NONE;
+
+ // Ask if possible, if page format should be taken over from printer.
+ if (bOriChg || bPgSzChg)
+ {
+ std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(nullptr,
+ VclMessageType::Question, VclButtonsType::YesNo,
+ aMsg));
+ if (RET_YES == xBox->run())
+ {
+ // Flags with changes for <SetPrinter(SfxPrinter*)> are maintained
+ nChangedFlags |= nNewOpt;
+ }
+ }
+
+ // Was the printer selection changed from Default to Specific
+ // or the other way around?
+ if ( (pNewPrinter->GetName() != pDocPrinter->GetName())
+ || (pDocPrinter->IsDefPrinter() != pNewPrinter->IsDefPrinter()) )
+ {
+ nChangedFlags |= SfxPrinterChangeFlags::PRINTER|SfxPrinterChangeFlags::JOBSETUP;
+ if ( ! (pNewPrinter->GetOptions() == pDocPrinter->GetOptions()) )
+ {
+ nChangedFlags |= SfxPrinterChangeFlags::OPTIONS;
+ }
+
+ pDocPrinter = pNewPrinter;
+ }
+ else
+ {
+ // Compare extra options
+ if ( ! (pNewPrinter->GetOptions() == pDocPrinter->GetOptions()) )
+ {
+ // Option have changed
+ pDocPrinter->SetOptions( pNewPrinter->GetOptions() );
+ nChangedFlags |= SfxPrinterChangeFlags::OPTIONS;
+ }
+
+ // Compare JobSetups
+ JobSetup aNewJobSetup = pNewPrinter->GetJobSetup();
+ JobSetup aOldJobSetup = pDocPrinter->GetJobSetup();
+ if ( aNewJobSetup != aOldJobSetup )
+ {
+ nChangedFlags |= SfxPrinterChangeFlags::JOBSETUP;
+ }
+
+ // Keep old changed Printer.
+ pDocPrinter->SetPrinterProps( pNewPrinter );
+ pNewPrinter.disposeAndClear();
+ }
+
+ if ( SfxPrinterChangeFlags::NONE != nChangedFlags )
+ // SetPrinter will delete the old printer if it changes
+ SetPrinter( pDocPrinter, nChangedFlags );
+}
+
+void SfxViewShell::StartPrint( const uno::Sequence < beans::PropertyValue >& rProps, bool bIsAPI, bool bIsDirect )
+{
+ assert( !pImpl->m_xPrinterController );
+
+ // get the current selection; our controller should know it
+ Reference< frame::XController > xController( GetController() );
+ Reference< view::XSelectionSupplier > xSupplier( xController, UNO_QUERY );
+
+ Any aSelection;
+ if( xSupplier.is() )
+ aSelection = xSupplier->getSelection();
+ else
+ aSelection <<= GetObjectShell()->GetModel();
+ Any aComplete( Any( GetObjectShell()->GetModel() ) );
+ Any aViewProp( xController );
+ VclPtr<Printer> aPrt;
+
+ const beans::PropertyValue* pVal = std::find_if(rProps.begin(), rProps.end(),
+ [](const beans::PropertyValue& rVal) { return rVal.Name == "PrinterName"; });
+ if (pVal != rProps.end())
+ {
+ OUString aPrinterName;
+ pVal->Value >>= aPrinterName;
+ aPrt.reset( VclPtr<Printer>::Create( aPrinterName ) );
+ }
+
+ std::shared_ptr<vcl::PrinterController> xNewController(std::make_shared<SfxPrinterController>(
+ aPrt,
+ aComplete,
+ aSelection,
+ aViewProp,
+ GetRenderable(),
+ bIsAPI,
+ bIsDirect,
+ this,
+ rProps
+ ));
+ pImpl->m_xPrinterController = xNewController;
+
+ SfxObjectShell *pObjShell = GetObjectShell();
+ xNewController->setValue( "JobName",
+ Any( pObjShell->GetTitle(1) ) );
+ xNewController->setPrinterModified( mbPrinterSettingsModified );
+}
+
+void SfxViewShell::ExecPrint( const uno::Sequence < beans::PropertyValue >& rProps, bool bIsAPI, bool bIsDirect )
+{
+ StartPrint( rProps, bIsAPI, bIsDirect );
+ // FIXME: job setup
+ SfxPrinter* pDocPrt = GetPrinter();
+ JobSetup aJobSetup = pDocPrt ? pDocPrt->GetJobSetup() : JobSetup();
+ Printer::PrintJob( GetPrinterController(), aJobSetup );
+}
+
+const std::shared_ptr< vcl::PrinterController >& SfxViewShell::GetPrinterController() const
+{
+ return pImpl->m_xPrinterController;
+}
+
+Printer* SfxViewShell::GetActivePrinter() const
+{
+ return pImpl->m_xPrinterController
+ ? pImpl->m_xPrinterController->getPrinter().get() : nullptr;
+}
+
+void SfxViewShell::ExecPrint_Impl( SfxRequest &rReq )
+{
+ sal_uInt16 nDialogRet = RET_CANCEL;
+ VclPtr<SfxPrinter> pPrinter;
+ bool bSilent = false;
+
+ // does the function have been called by the user interface or by an API call
+ bool bIsAPI = rReq.GetArgs() && rReq.GetArgs()->Count();
+ if ( bIsAPI )
+ {
+ // the function have been called by the API
+
+ // Should it be visible on the user interface,
+ // should it launch popup dialogue ?
+ const SfxBoolItem* pSilentItem = rReq.GetArg<SfxBoolItem>(SID_SILENT);
+ bSilent = pSilentItem && pSilentItem->GetValue();
+ }
+
+ // no help button in dialogs if called from the help window
+ // (pressing help button would exchange the current page inside the help
+ // document that is going to be printed!)
+ SfxMedium* pMedium = GetViewFrame()->GetObjectShell()->GetMedium();
+ std::shared_ptr<const SfxFilter> pFilter = pMedium ? pMedium->GetFilter() : nullptr;
+ bool bPrintOnHelp = ( pFilter && pFilter->GetFilterName() == "writer_web_HTML_help" );
+
+ const sal_uInt16 nId = rReq.GetSlot();
+ switch( nId )
+ {
+ case SID_PRINTDOC: // display the printer selection and properties dialogue : File > Print...
+ case SID_PRINTDOCDIRECT: // Print the document directly, without displaying the dialogue
+ {
+ SfxObjectShell* pDoc = GetObjectShell();
+
+ // derived class may decide to abort this
+ if( pDoc == nullptr || !pDoc->QuerySlotExecutable( nId ) )
+ {
+ rReq.SetReturnValue( SfxBoolItem( 0, false ) );
+ return;
+ }
+
+ if ( !bSilent && pDoc->QueryHiddenInformation( HiddenWarningFact::WhenPrinting, nullptr ) != RET_YES )
+ return;
+
+ // should we print only the selection or the whole document
+ const SfxBoolItem* pSelectItem = rReq.GetArg<SfxBoolItem>(SID_SELECTION);
+ bool bSelection = ( pSelectItem != nullptr && pSelectItem->GetValue() );
+ // detect non api call from writer ( that adds SID_SELECTION ) and reset bIsAPI
+ if ( pSelectItem && rReq.GetArgs()->Count() == 1 )
+ bIsAPI = false;
+
+ uno::Sequence < beans::PropertyValue > aProps;
+ if ( bIsAPI )
+ {
+ // supported properties:
+ // String PrinterName
+ // String FileName
+ // Int16 From
+ // Int16 To
+ // In16 Copies
+ // String RangeText
+ // bool Selection
+ // bool Asynchron
+ // bool Collate
+ // bool Silent
+
+ // the TransformItems function overwrite aProps
+ TransformItems( nId, *rReq.GetArgs(), aProps, GetInterface()->GetSlot(nId) );
+
+ for ( auto& rProp : asNonConstRange(aProps) )
+ {
+ if ( rProp.Name == "Copies" )
+ {
+ rProp.Name = "CopyCount";
+ }
+ else if ( rProp.Name == "RangeText" )
+ {
+ rProp.Name = "Pages";
+ }
+ else if ( rProp.Name == "Asynchron" )
+ {
+ rProp.Name = "Wait";
+ bool bAsynchron = false;
+ rProp.Value >>= bAsynchron;
+ rProp.Value <<= !bAsynchron;
+ }
+ else if ( rProp.Name == "Silent" )
+ {
+ rProp.Name = "MonitorVisible";
+ bool bPrintSilent = false;
+ rProp.Value >>= bPrintSilent;
+ rProp.Value <<= !bPrintSilent;
+ }
+ }
+ }
+
+ // we will add the "PrintSelectionOnly" or "HideHelpButton" properties
+ // we have to increase the capacity of aProps
+ sal_Int32 nLen = aProps.getLength();
+ aProps.realloc( nLen + 1 );
+ auto pProps = aProps.getArray();
+
+ // HACK: writer sets the SID_SELECTION item when printing directly and expects
+ // to get only the selection document in that case (see getSelectionObject)
+ // however it also reacts to the PrintContent property. We need this distinction here, too,
+ // else one of the combinations print / print direct and selection / all will not work.
+ // it would be better if writer handled this internally
+ if( nId == SID_PRINTDOCDIRECT )
+ {
+ pProps[nLen].Name = "PrintSelectionOnly";
+ pProps[nLen].Value <<= bSelection;
+ }
+ else // if nId == SID_PRINTDOC ; nothing to do with the previous HACK
+ {
+ // should the printer selection and properties dialogue display an help button
+ pProps[nLen].Name = "HideHelpButton";
+ pProps[nLen].Value <<= bPrintOnHelp;
+ }
+
+ ExecPrint( aProps, bIsAPI, (nId == SID_PRINTDOCDIRECT) );
+
+ // FIXME: Recording
+ rReq.Done();
+ break;
+ }
+
+ case SID_PRINTER_NAME: // for recorded macros
+ {
+ // get printer and printer settings from the document
+ SfxPrinter* pDocPrinter = GetPrinter(true);
+ const SfxStringItem* pPrinterItem = rReq.GetArg<SfxStringItem>(SID_PRINTER_NAME);
+ if (!pPrinterItem)
+ {
+ rReq.Ignore();
+ break;
+ }
+ // use PrinterName parameter to create a printer
+ pPrinter = VclPtr<SfxPrinter>::Create(pDocPrinter->GetOptions().Clone(),
+ pPrinterItem->GetValue());
+
+ if (!pPrinter->IsKnown())
+ {
+ pPrinter.disposeAndClear();
+ rReq.Ignore();
+ break;
+ }
+ SetPrinter(pPrinter, SfxPrinterChangeFlags::PRINTER);
+ rReq.Done();
+ break;
+ }
+ case SID_SETUPPRINTER : // display the printer settings dialog : File > Printer Settings...
+ {
+ // get printer and printer settings from the document
+ SfxPrinter *pDocPrinter = GetPrinter(true);
+
+ // look for printer in parameters
+ const SfxStringItem* pPrinterItem = rReq.GetArg<SfxStringItem>(SID_PRINTER_NAME);
+ if ( pPrinterItem )
+ {
+ // use PrinterName parameter to create a printer
+ pPrinter = VclPtr<SfxPrinter>::Create( pDocPrinter->GetOptions().Clone(), pPrinterItem->GetValue() );
+
+ // if printer is unknown, it can't be used - now printer from document will be used
+ if ( !pPrinter->IsKnown() )
+ pPrinter.disposeAndClear();
+ }
+
+ // no PrinterName parameter in ItemSet or the PrinterName points to an unknown printer
+ if ( !pPrinter )
+ // use default printer from document
+ pPrinter = pDocPrinter;
+
+ if( !pPrinter || !pPrinter->IsValid() )
+ {
+ // no valid printer either in ItemSet or at the document
+ if ( !bSilent )
+ {
+ std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(nullptr,
+ VclMessageType::Warning, VclButtonsType::Ok,
+ SfxResId(STR_NODEFPRINTER)));
+ xBox->run();
+ }
+
+ rReq.SetReturnValue(SfxBoolItem(0,false));
+
+ break;
+ }
+
+ // FIXME: printer isn't used for printing anymore!
+ if( pPrinter->IsPrinting() )
+ {
+ // if printer is busy, abort configuration
+ if ( !bSilent )
+ {
+ std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(nullptr,
+ VclMessageType::Info, VclButtonsType::Ok,
+ SfxResId(STR_ERROR_PRINTER_BUSY)));
+ xBox->run();
+ }
+ rReq.SetReturnValue(SfxBoolItem(0,false));
+
+ return;
+ }
+
+ // Open Printer Setup dialog (needs a temporary printer)
+ VclPtr<SfxPrinter> pDlgPrinter = pPrinter->Clone();
+ PrinterSetupDialog aPrintSetupDlg(GetFrameWeld());
+ std::unique_ptr<SfxDialogExecutor_Impl> pExecutor;
+
+ if (pImpl->m_bHasPrintOptions && HasPrintOptionsPage())
+ {
+ // additional controls for dialog
+ pExecutor.reset(new SfxDialogExecutor_Impl(this, aPrintSetupDlg));
+ if (bPrintOnHelp)
+ pExecutor->DisableHelp();
+ aPrintSetupDlg.SetOptionsHdl(pExecutor->GetLink());
+ }
+
+ aPrintSetupDlg.SetPrinter(pDlgPrinter);
+ nDialogRet = aPrintSetupDlg.run();
+
+ if (pExecutor && pExecutor->GetOptions())
+ {
+ if (nDialogRet == RET_OK)
+ // remark: have to be recorded if possible!
+ pDlgPrinter->SetOptions(*pExecutor->GetOptions());
+ else
+ {
+ pPrinter->SetOptions(*pExecutor->GetOptions());
+ SetPrinter(pPrinter, SfxPrinterChangeFlags::OPTIONS);
+ }
+ }
+
+ // no recording of PrinterSetup except printer name (is printer dependent)
+ rReq.Ignore();
+
+ if (nDialogRet == RET_OK)
+ {
+ if (pPrinter->GetName() != pDlgPrinter->GetName())
+ {
+ // user has changed the printer -> macro recording
+ SfxRequest aReq(GetViewFrame(), SID_PRINTER_NAME);
+ aReq.AppendItem(SfxStringItem(SID_PRINTER_NAME, pDlgPrinter->GetName()));
+ aReq.Done();
+ }
+
+ // take the changes made in the dialog
+ SetPrinter_Impl(pDlgPrinter);
+
+ // forget new printer, it was taken over (as pPrinter) or deleted
+ pDlgPrinter = nullptr;
+ mbPrinterSettingsModified = true;
+ }
+ else
+ {
+ // PrinterDialog is used to transfer information on printing,
+ // so it will only be deleted here if dialog was cancelled
+ pDlgPrinter.disposeAndClear();
+ rReq.Ignore();
+ }
+ break;
+ }
+ }
+}
+
+SfxPrinter* SfxViewShell::GetPrinter( bool /*bCreate*/ )
+{
+ return nullptr;
+}
+
+sal_uInt16 SfxViewShell::SetPrinter( SfxPrinter* /*pNewPrinter*/, SfxPrinterChangeFlags /*nDiffFlags*/ )
+{
+ return 0;
+}
+
+std::unique_ptr<SfxTabPage> SfxViewShell::CreatePrintOptionsPage(weld::Container*, weld::DialogController*, const SfxItemSet&)
+{
+ return nullptr;
+}
+
+bool SfxViewShell::HasPrintOptionsPage() const
+{
+ return false;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */