1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 <vcl/weld.hxx>
21 #include <vcl/print.hxx>
22 #include <vcl/svapp.hxx>
23 #include <vcl/metaact.hxx>
24 #include <vcl/configsettings.hxx>
25 #include <tools/urlobj.hxx>
26 #include <comphelper/processfactory.hxx>
27 #include <comphelper/sequence.hxx>
28 #include <sal/types.h>
29 #include <sal/log.hxx>
30 #include <tools/debug.hxx>
32 #include <printdlg.hxx>
34 #include <salinst.hxx>
36 #include <strings.hrc>
38 #include <com/sun/star/ui/dialogs/FilePicker.hpp>
39 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
40 #include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
41 #include <com/sun/star/view/DuplexMode.hpp>
42 #include <com/sun/star/lang/IllegalArgumentException.hpp>
43 #include <com/sun/star/awt/Size.hpp>
45 #include <unordered_map>
46 #include <unordered_set>
55 PrinterController::PageSize aSize
;
58 std::vector
< CacheEntry
> maPages
;
59 std::vector
< sal_Int32
> maPageNumbers
;
60 std::vector
< sal_Int32
> maCacheRanking
;
62 static const sal_Int32 nCacheSize
= 6;
64 void updateRanking( sal_Int32 nLastHit
)
66 if( maCacheRanking
[0] != nLastHit
)
68 for( sal_Int32 i
= nCacheSize
-1; i
> 0; i
-- )
69 maCacheRanking
[i
] = maCacheRanking
[i
-1];
70 maCacheRanking
[0] = nLastHit
;
76 : maPages( nCacheSize
)
77 , maPageNumbers( nCacheSize
, -1 )
78 , maCacheRanking( nCacheSize
)
80 for( sal_Int32 i
= 0; i
< nCacheSize
; i
++ )
81 maCacheRanking
[i
] = nCacheSize
- i
- 1;
84 // caution: does not ensure uniqueness
85 void insert( sal_Int32 i_nPageNo
, const GDIMetaFile
& i_rPage
, const PrinterController::PageSize
& i_rSize
)
87 sal_Int32 nReplacePage
= maCacheRanking
.back();
88 maPages
[ nReplacePage
].aPage
= i_rPage
;
89 maPages
[ nReplacePage
].aSize
= i_rSize
;
90 maPageNumbers
[ nReplacePage
] = i_nPageNo
;
91 // cache insertion means in our case, the page was just queried
92 // so update the ranking
93 updateRanking( nReplacePage
);
96 // caution: bad algorithm; should there ever be reason to increase the cache size beyond 6
97 // this needs to be urgently rewritten. However do NOT increase the cache size lightly,
98 // whole pages can be rather memory intensive
99 bool get( sal_Int32 i_nPageNo
, GDIMetaFile
& o_rPageFile
, PrinterController::PageSize
& o_rSize
)
101 for( sal_Int32 i
= 0; i
< nCacheSize
; ++i
)
103 if( maPageNumbers
[i
] == i_nPageNo
)
106 o_rPageFile
= maPages
[i
].aPage
;
107 o_rSize
= maPages
[i
].aSize
;
116 for( sal_Int32 i
= 0; i
< nCacheSize
; ++i
)
118 maPageNumbers
[i
] = -1;
119 maPages
[i
].aPage
.Clear();
120 maCacheRanking
[i
] = nCacheSize
- i
- 1;
125 class vcl::ImplPrinterControllerData
128 struct ControlDependency
130 OUString maDependsOnName
;
131 sal_Int32 mnDependsOnEntry
;
133 ControlDependency() : mnDependsOnEntry( -1 ) {}
136 typedef std::unordered_map
< OUString
, size_t > PropertyToIndexMap
;
137 typedef std::unordered_map
< OUString
, ControlDependency
> ControlDependencyMap
;
138 typedef std::unordered_map
< OUString
, css::uno::Sequence
< sal_Bool
> > ChoiceDisableMap
;
140 VclPtr
< Printer
> mxPrinter
;
141 weld::Window
* mpWindow
;
142 css::uno::Sequence
< css::beans::PropertyValue
> maUIOptions
;
143 std::vector
< css::beans::PropertyValue
> maUIProperties
;
144 std::vector
< bool > maUIPropertyEnabled
;
145 PropertyToIndexMap maPropertyToIndex
;
146 ControlDependencyMap maControlDependencies
;
147 ChoiceDisableMap maChoiceDisableMap
;
150 bool mbReversePageOrder
;
151 bool mbPapersizeFromSetup
;
152 bool mbPapersizeFromUser
;
153 bool mbPrinterModified
;
154 css::view::PrintableState meJobState
;
156 vcl::PrinterController::MultiPageSetup maMultiPage
;
158 std::shared_ptr
<vcl::PrintProgressDialog
> mxProgress
;
160 ImplPageCache maPageCache
;
162 // set by user through printer properties subdialog of printer settings dialog
163 Size maDefaultPageSize
;
164 // set by user through print dialog
166 // set by user through printer properties subdialog of printer settings dialog
167 sal_Int32 mnDefaultPaperBin
;
168 // Set by user through printer properties subdialog of print dialog.
169 // Overrides application-set tray for a page.
170 sal_Int32 mnFixedPaperBin
;
172 // N.B. Apparently we have three levels of paper tray settings
173 // (latter overrides former):
175 // 2. tray set for a concrete page by an application, e.g., writer
176 // allows setting a printer tray (for the default printer) for a
177 // page style. This setting can be overridden by user by selecting
178 // "Use only paper tray from printer preferences" on the Options
179 // page in the print dialog, in which case the default tray is
180 // used for all pages.
181 // 3. tray set in printer properties the printer dialog
182 // I'm not quite sure why 1. and 3. are distinct, but the commit
183 // history suggests this is intentional...
185 ImplPrinterControllerData() :
189 mbReversePageOrder( false ),
190 mbPapersizeFromSetup( false ),
191 mbPapersizeFromUser( false ),
192 mbPrinterModified( false ),
193 meJobState( css::view::PrintableState_JOB_STARTED
),
194 mnDefaultPaperBin( -1 ),
195 mnFixedPaperBin( -1 )
198 ~ImplPrinterControllerData()
202 mxProgress
->response(RET_CANCEL
);
207 const Size
& getRealPaperSize( const Size
& i_rPageSize
, bool bNoNUP
) const
209 if ( mbPapersizeFromUser
)
210 return maUserPageSize
;
211 if( mbPapersizeFromSetup
)
212 return maDefaultPageSize
;
213 if( maMultiPage
.nRows
* maMultiPage
.nColumns
> 1 && ! bNoNUP
)
214 return maMultiPage
.aPaperSize
;
217 bool isFixedPageSize() const
218 { return mbPapersizeFromSetup
; }
219 PrinterController::PageSize
modifyJobSetup( const css::uno::Sequence
< css::beans::PropertyValue
>& i_rProps
);
220 void resetPaperToLastConfigured();
223 PrinterController::PrinterController(const VclPtr
<Printer
>& i_xPrinter
, weld::Window
* i_pWindow
)
224 : mpImplData( new ImplPrinterControllerData
)
226 mpImplData
->mxPrinter
= i_xPrinter
;
227 mpImplData
->mpWindow
= i_pWindow
;
230 static OUString
queryFile( Printer
const * pPrinter
)
234 css::uno::Reference
< css::uno::XComponentContext
> xContext( ::comphelper::getProcessComponentContext() );
235 css::uno::Reference
< css::ui::dialogs::XFilePicker3
> xFilePicker
= css::ui::dialogs::FilePicker::createWithMode(xContext
, css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION
);
240 // add PostScript and PDF
241 bool bPS
= true, bPDF
= true;
244 if( pPrinter
->GetCapabilities( PrinterCapType::PDF
) )
250 xFilePicker
->appendFilter( "PostScript", "*.ps" );
252 xFilePicker
->appendFilter( "Portable Document Format", "*.pdf" );
255 xFilePicker
->appendFilter( "*.PRN", "*.prn" );
257 // add arbitrary files
258 xFilePicker
->appendFilter(VclResId(SV_STDTEXT_ALLFILETYPES
), "*.*");
260 catch (const css::lang::IllegalArgumentException
&)
262 SAL_WARN( "vcl.gdi", "caught IllegalArgumentException when registering filter" );
265 if( xFilePicker
->execute() == css::ui::dialogs::ExecutableDialogResults::OK
)
267 css::uno::Sequence
< OUString
> aPathSeq( xFilePicker
->getSelectedFiles() );
268 INetURLObject
aObj( aPathSeq
[0] );
269 aResult
= aObj
.PathToFileName();
276 std::shared_ptr
<PrinterController
> mxController
;
277 JobSetup
const maInitSetup
;
279 PrintJobAsync(const std::shared_ptr
<PrinterController
>& i_xController
,
280 const JobSetup
& i_rInitSetup
)
281 : mxController( i_xController
), maInitSetup( i_rInitSetup
)
284 DECL_LINK( ExecJob
, void*, void );
287 IMPL_LINK_NOARG(PrintJobAsync
, ExecJob
, void*, void)
289 Printer::ImplPrintJob(mxController
, maInitSetup
);
291 // clean up, do not access members after this
295 void Printer::PrintJob(const std::shared_ptr
<PrinterController
>& i_xController
,
296 const JobSetup
& i_rInitSetup
)
298 bool bSynchronous
= false;
299 css::beans::PropertyValue
* pVal
= i_xController
->getValue( "Wait" );
301 pVal
->Value
>>= bSynchronous
;
304 ImplPrintJob(i_xController
, i_rInitSetup
);
307 PrintJobAsync
* pAsync
= new PrintJobAsync(i_xController
, i_rInitSetup
);
308 Application::PostUserEvent( LINK( pAsync
, PrintJobAsync
, ExecJob
) );
312 bool Printer::PreparePrintJob(std::shared_ptr
<PrinterController
> xController
,
313 const JobSetup
& i_rInitSetup
)
315 // check if there is a default printer; if not, show an error box (if appropriate)
316 if( GetDefaultPrinterName().isEmpty() )
318 if (xController
->isShowDialogs())
320 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(xController
->getWindow(), "vcl/ui/errornoprinterdialog.ui"));
321 std::unique_ptr
<weld::MessageDialog
> xBox(xBuilder
->weld_message_dialog("ErrorNoPrinterDialog"));
324 xController
->setValue( "IsDirect",
325 css::uno::makeAny( false ) );
330 // #i114306# changed behavior back from persistence
331 // if no specific printer is already set, create the default printer
332 if (!xController
->getPrinter())
334 OUString
aPrinterName( i_rInitSetup
.GetPrinterName() );
335 VclPtrInstance
<Printer
> xPrinter( aPrinterName
);
336 xPrinter
->SetJobSetup(i_rInitSetup
);
337 xController
->setPrinter(xPrinter
);
338 xController
->setPapersizeFromSetup(xPrinter
->GetPrinterSettingsPreferred());
341 // reset last page property
342 xController
->setLastPage(false);
344 // update "PageRange" property inferring from other properties:
345 // case 1: "Pages" set from UNO API ->
346 // setup "Print Selection" and insert "PageRange" attribute
347 // case 2: "All pages" is selected
348 // update "Page range" attribute to have a sensible default,
349 // but leave "All" as selected
351 // "Pages" attribute from API is now equivalent to "PageRange"
352 // AND "PrintContent" = 1 except calc where it is "PrintRange" = 1
353 // Argh ! That sure needs cleaning up
354 css::beans::PropertyValue
* pContentVal
= xController
->getValue("PrintRange");
356 pContentVal
= xController
->getValue("PrintContent");
358 // case 1: UNO API has set "Pages"
359 css::beans::PropertyValue
* pPagesVal
= xController
->getValue("Pages");
363 pPagesVal
->Value
>>= aPagesVal
;
364 if( !aPagesVal
.isEmpty() )
366 // "Pages" attribute from API is now equivalent to "PageRange"
367 // AND "PrintContent" = 1 except calc where it is "PrintRange" = 1
368 // Argh ! That sure needs cleaning up
371 pContentVal
->Value
<<= sal_Int32( 1 );
372 xController
->setValue("PageRange", pPagesVal
->Value
);
376 // case 2: is "All" selected ?
377 else if( pContentVal
)
379 sal_Int32 nContent
= -1;
380 if( pContentVal
->Value
>>= nContent
)
384 // do not overwrite PageRange if it is already set
385 css::beans::PropertyValue
* pRangeVal
= xController
->getValue("PageRange");
388 pRangeVal
->Value
>>= aRange
;
389 if( aRange
.isEmpty() )
391 sal_Int32 nPages
= xController
->getPageCount();
394 OUStringBuffer
aBuf( 32 );
399 aBuf
.append( nPages
);
401 xController
->setValue("PageRange", css::uno::makeAny(aBuf
.makeStringAndClear()));
408 css::beans::PropertyValue
* pReverseVal
= xController
->getValue("PrintReverse");
411 bool bReverse
= false;
412 pReverseVal
->Value
>>= bReverse
;
413 xController
->setReversePrint( bReverse
);
416 css::beans::PropertyValue
* pPapersizeFromSetupVal
= xController
->getValue("PapersizeFromSetup");
417 if( pPapersizeFromSetupVal
)
419 bool bPapersizeFromSetup
= false;
420 pPapersizeFromSetupVal
->Value
>>= bPapersizeFromSetup
;
421 xController
->setPapersizeFromSetup(bPapersizeFromSetup
);
424 // setup NUp printing from properties
425 sal_Int32 nRows
= xController
->getIntProperty("NUpRows", 1);
426 sal_Int32 nCols
= xController
->getIntProperty("NUpColumns", 1);
427 if( nRows
> 1 || nCols
> 1 )
429 PrinterController::MultiPageSetup aMPS
;
430 aMPS
.nRows
= std::max
<sal_Int32
>(nRows
, 1);
431 aMPS
.nColumns
= std::max
<sal_Int32
>(nCols
, 1);
432 sal_Int32 nValue
= xController
->getIntProperty("NUpPageMarginLeft", aMPS
.nLeftMargin
);
434 aMPS
.nLeftMargin
= nValue
;
435 nValue
= xController
->getIntProperty("NUpPageMarginRight", aMPS
.nRightMargin
);
437 aMPS
.nRightMargin
= nValue
;
438 nValue
= xController
->getIntProperty( "NUpPageMarginTop", aMPS
.nTopMargin
);
440 aMPS
.nTopMargin
= nValue
;
441 nValue
= xController
->getIntProperty( "NUpPageMarginBottom", aMPS
.nBottomMargin
);
443 aMPS
.nBottomMargin
= nValue
;
444 nValue
= xController
->getIntProperty( "NUpHorizontalSpacing", aMPS
.nHorizontalSpacing
);
446 aMPS
.nHorizontalSpacing
= nValue
;
447 nValue
= xController
->getIntProperty( "NUpVerticalSpacing", aMPS
.nVerticalSpacing
);
449 aMPS
.nVerticalSpacing
= nValue
;
450 aMPS
.bDrawBorder
= xController
->getBoolProperty( "NUpDrawBorder", aMPS
.bDrawBorder
);
451 aMPS
.nOrder
= static_cast<NupOrderType
>(xController
->getIntProperty( "NUpSubPageOrder", static_cast<sal_Int32
>(aMPS
.nOrder
) ));
452 aMPS
.aPaperSize
= xController
->getPrinter()->PixelToLogic( xController
->getPrinter()->GetPaperSizePixel(), MapMode( MapUnit::Map100thMM
) );
453 css::beans::PropertyValue
* pPgSizeVal
= xController
->getValue( "NUpPaperSize" );
454 css::awt::Size aSizeVal
;
455 if( pPgSizeVal
&& (pPgSizeVal
->Value
>>= aSizeVal
) )
457 aMPS
.aPaperSize
.setWidth( aSizeVal
.Width
);
458 aMPS
.aPaperSize
.setHeight( aSizeVal
.Height
);
461 xController
->setMultipage( aMPS
);
464 // in direct print case check whether there is anything to print.
465 // if not, show an errorbox (if appropriate)
466 if( xController
->isShowDialogs() && xController
->isDirectPrint() )
468 if( xController
->getFilteredPageCount() == 0 )
470 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(xController
->getWindow(), "vcl/ui/errornocontentdialog.ui"));
471 std::unique_ptr
<weld::MessageDialog
> xBox(xBuilder
->weld_message_dialog("ErrorNoContentDialog"));
477 // check if the printer brings up its own dialog
478 // in that case leave the work to that dialog
479 if( ! xController
->getPrinter()->GetCapabilities( PrinterCapType::ExternalDialog
) &&
480 ! xController
->isDirectPrint() &&
481 xController
->isShowDialogs()
486 PrintDialog
aDlg(xController
->getWindow(), xController
);
489 xController
->abortJob();
492 if (aDlg
.isPrintToFile())
494 OUString aFile
= queryFile( xController
->getPrinter().get() );
495 if( aFile
.isEmpty() )
497 xController
->abortJob();
500 xController
->setValue( "LocalFileName",
501 css::uno::makeAny( aFile
) );
503 else if (aDlg
.isSingleJobs())
505 xController
->setValue( "PrintCollateAsSingleJobs",
506 css::uno::makeAny( true ) );
509 catch (const std::bad_alloc
&)
514 xController
->pushPropertiesToPrinter();
518 bool Printer::ExecutePrintJob(const std::shared_ptr
<PrinterController
>& xController
)
521 css::beans::PropertyValue
* pJobNameVal
= xController
->getValue( "JobName" );
523 pJobNameVal
->Value
>>= aJobName
;
525 return xController
->getPrinter()->StartJob( aJobName
, xController
);
528 void Printer::FinishPrintJob(const std::shared_ptr
<PrinterController
>& xController
)
530 xController
->resetPaperToLastConfigured();
531 xController
->jobFinished( xController
->getJobState() );
534 void Printer::ImplPrintJob(const std::shared_ptr
<PrinterController
>& xController
,
535 const JobSetup
& i_rInitSetup
)
537 if (PreparePrintJob(xController
, i_rInitSetup
))
539 ExecutePrintJob(xController
);
541 FinishPrintJob(xController
);
544 bool Printer::StartJob( const OUString
& i_rJobName
, std::shared_ptr
<vcl::PrinterController
> const & i_xController
)
546 mnError
= ERRCODE_NONE
;
548 if ( IsDisplayPrinter() )
551 if ( IsJobActive() || IsPrinting() )
554 sal_uInt32 nCopies
= mnCopyCount
;
555 bool bCollateCopy
= mbCollateCopy
;
556 bool bUserCopy
= false;
560 const sal_uInt32 nDevCopy
= GetCapabilities( bCollateCopy
561 ? PrinterCapType::CollateCopies
562 : PrinterCapType::Copies
);
564 // need to do copies by hand ?
565 if ( nCopies
> nDevCopy
)
569 bCollateCopy
= false;
573 bCollateCopy
= false;
575 ImplSVData
* pSVData
= ImplGetSVData();
576 mpPrinter
= pSVData
->mpDefInst
->CreatePrinter( mpInfoPrinter
);
581 bool bSinglePrintJobs
= false;
582 css::beans::PropertyValue
* pSingleValue
= i_xController
->getValue("PrintCollateAsSingleJobs");
585 pSingleValue
->Value
>>= bSinglePrintJobs
;
588 css::beans::PropertyValue
* pFileValue
= i_xController
->getValue("LocalFileName");
592 pFileValue
->Value
>>= aFile
;
593 if( !aFile
.isEmpty() )
597 bSinglePrintJobs
= false;
601 OUString
* pPrintFile
= nullptr;
603 pPrintFile
= &maPrintFile
;
604 mpPrinterOptions
->ReadFromConfig( mbPrintFile
);
607 if( GetCapabilities( PrinterCapType::UsePullModel
) )
610 // SAL layer does all necessary page printing
611 // and also handles showing a dialog
612 // that also means it must call jobStarted when the dialog is finished
613 // it also must set the JobState of the Controller
614 if( mpPrinter
->StartJob( pPrintFile
,
616 Application::GetDisplayName(),
617 &maJobSetup
.ImplGetData(),
624 mnError
= ImplSalPrinterErrorCodeToVCL(mpPrinter
->GetErrorCode());
626 mnError
= PRINTER_GENERALERROR
;
631 GDIMetaFile aDummyFile
;
632 i_xController
->setLastPage(true);
633 i_xController
->getFilteredPageFile(0, aDummyFile
);
640 // possibly a dialog has been shown
641 // now the real job starts
642 i_xController
->setJobState( css::view::PrintableState_JOB_STARTED
);
643 i_xController
->jobStarted();
646 int nOuterRepeatCount
= 1;
647 int nInnerRepeatCount
= 1;
651 nOuterRepeatCount
= mnCopyCount
;
653 nInnerRepeatCount
= mnCopyCount
;
655 if( bSinglePrintJobs
)
659 nOuterRepeatCount
= nInnerRepeatCount
= 1;
662 for( int nJobIteration
= 0; nJobIteration
< nJobs
; nJobIteration
++ )
665 if( mpPrinter
->StartJob( pPrintFile
,
667 Application::GetDisplayName(),
670 i_xController
->isDirectPrint(),
671 &maJobSetup
.ImplGetData() ) )
673 bool bAborted
= false;
675 i_xController
->createProgressDialog();
676 const int nPages
= i_xController
->getFilteredPageCount();
677 // abort job, if no pages will be printed.
680 i_xController
->abortJob();
683 for( int nOuterIteration
= 0; nOuterIteration
< nOuterRepeatCount
&& ! bAborted
; nOuterIteration
++ )
685 for( int nPage
= 0; nPage
< nPages
&& ! bAborted
; nPage
++ )
687 for( int nInnerIteration
= 0; nInnerIteration
< nInnerRepeatCount
&& ! bAborted
; nInnerIteration
++ )
689 if( nPage
== nPages
-1 &&
690 nOuterIteration
== nOuterRepeatCount
-1 &&
691 nInnerIteration
== nInnerRepeatCount
-1 &&
692 nJobIteration
== nJobs
-1 )
694 i_xController
->setLastPage(true);
696 i_xController
->printFilteredPage(nPage
);
697 if (i_xController
->isProgressCanceled())
699 i_xController
->abortJob();
701 if (i_xController
->getJobState() ==
702 css::view::PrintableState_JOB_ABORTED
)
712 if( nJobIteration
< nJobs
-1 )
714 mpPrinter
= pSVData
->mpDefInst
->CreatePrinter( mpInfoPrinter
);
727 mnError
= mpPrinter
? ImplSalPrinterErrorCodeToVCL(mpPrinter
->GetErrorCode()) : ERRCODE_NONE
;
729 mnError
= PRINTER_GENERALERROR
;
730 i_xController
->setJobState( mnError
== PRINTER_ABORT
731 ? css::view::PrintableState_JOB_ABORTED
732 : css::view::PrintableState_JOB_FAILED
);
740 if (i_xController
->getJobState() == css::view::PrintableState_JOB_STARTED
)
741 i_xController
->setJobState(css::view::PrintableState_JOB_SPOOLED
);
744 // make last used printer persistent for UI jobs
745 if (i_xController
->isShowDialogs() && !i_xController
->isDirectPrint())
747 SettingsConfigItem
* pItem
= SettingsConfigItem::get();
748 pItem
->setValue( "PrintDialog",
757 PrinterController::~PrinterController()
761 css::view::PrintableState
PrinterController::getJobState() const
763 return mpImplData
->meJobState
;
766 void PrinterController::setJobState( css::view::PrintableState i_eState
)
768 mpImplData
->meJobState
= i_eState
;
771 const VclPtr
<Printer
>& PrinterController::getPrinter() const
773 return mpImplData
->mxPrinter
;
776 weld::Window
* PrinterController::getWindow() const
778 return mpImplData
->mpWindow
;
781 void PrinterController::setPrinter( const VclPtr
<Printer
>& i_rPrinter
)
783 mpImplData
->mxPrinter
= i_rPrinter
;
785 css::uno::makeAny( i_rPrinter
->GetName() ) );
786 mpImplData
->mnDefaultPaperBin
= mpImplData
->mxPrinter
->GetPaperBin();
787 mpImplData
->mxPrinter
->Push();
788 mpImplData
->mxPrinter
->SetMapMode(MapMode(MapUnit::Map100thMM
));
789 mpImplData
->maDefaultPageSize
= mpImplData
->mxPrinter
->GetPaperSize();
790 mpImplData
->mbPapersizeFromUser
= false;
791 mpImplData
->mxPrinter
->Pop();
792 mpImplData
->mnFixedPaperBin
= -1;
795 void PrinterController::resetPrinterOptions( bool i_bFileOutput
)
798 aOpt
.ReadFromConfig( i_bFileOutput
);
799 mpImplData
->mxPrinter
->SetPrinterOptions( aOpt
);
802 void PrinterController::setupPrinter( weld::Window
* i_pParent
)
806 // Important to hold printer alive while doing setup etc.
807 VclPtr
< Printer
> xPrinter
= mpImplData
->mxPrinter
;
812 xPrinter
->SetMapMode(MapMode(MapUnit::Map100thMM
));
815 Size
aPaperSize(xPrinter
->GetPaperSize());
816 Orientation eOrientation
= xPrinter
->GetOrientation();
817 sal_uInt16 nPaperBin
= xPrinter
->GetPaperBin();
819 // reset paper size back to last configured size, not
820 // whatever happens to be the current page
821 // (but only if the printer config has changed, otherwise
822 // don't override printer page auto-detection - tdf#91362)
823 if (getPrinterModified() || getPapersizeFromSetup())
825 resetPaperToLastConfigured();
829 bRet
= xPrinter
->Setup( i_pParent
, PrinterSetupMode::SingleJob
);
830 SAL_WARN_IF(xPrinter
!= mpImplData
->mxPrinter
, "vcl.gdi",
831 "Printer changed underneath us during setup");
832 xPrinter
= mpImplData
->mxPrinter
;
834 Size
aNewPaperSize(xPrinter
->GetPaperSize());
837 bool bInvalidateCache
= false;
838 setPapersizeFromSetup(xPrinter
->GetPrinterSettingsPreferred());
840 // was papersize overridden ? if so we need to take action if we're
841 // configured to use the driver papersize
842 if (aNewPaperSize
!= mpImplData
->maDefaultPageSize
)
844 mpImplData
->maDefaultPageSize
= aNewPaperSize
;
845 bInvalidateCache
= getPapersizeFromSetup();
848 // was bin overridden ? if so we need to take action
849 sal_uInt16 nNewPaperBin
= xPrinter
->GetPaperBin();
850 if (nNewPaperBin
!= nPaperBin
)
852 mpImplData
->mnFixedPaperBin
= nNewPaperBin
;
853 bInvalidateCache
= true;
856 if (bInvalidateCache
)
858 mpImplData
->maPageCache
.invalidate();
863 //restore to whatever it was before we entered this method
864 xPrinter
->SetOrientation( eOrientation
);
865 if (aPaperSize
!= aNewPaperSize
)
866 xPrinter
->SetPaperSizeUser(aPaperSize
, !mpImplData
->isFixedPageSize());
872 PrinterController::PageSize
vcl::ImplPrinterControllerData::modifyJobSetup( const css::uno::Sequence
< css::beans::PropertyValue
>& i_rProps
)
874 PrinterController::PageSize aPageSize
;
875 aPageSize
.aSize
= mxPrinter
->GetPaperSize();
876 css::awt::Size aSetSize
, aIsSize
;
877 sal_Int32 nPaperBin
= mnDefaultPaperBin
;
878 for( const auto& rProp
: i_rProps
)
880 if ( rProp
.Name
== "PreferredPageSize" )
882 rProp
.Value
>>= aSetSize
;
884 else if ( rProp
.Name
== "PageSize" )
886 rProp
.Value
>>= aIsSize
;
888 else if ( rProp
.Name
== "PageIncludesNonprintableArea" )
891 rProp
.Value
>>= bVal
;
892 aPageSize
.bFullPaper
= bVal
;
894 else if ( rProp
.Name
== "PrinterPaperTray" )
897 rProp
.Value
>>= nBin
;
898 if( nBin
>= 0 && nBin
< static_cast<sal_Int32
>(mxPrinter
->GetPaperBinCount()) )
903 Size
aCurSize( mxPrinter
->GetPaperSize() );
904 if( aSetSize
.Width
&& aSetSize
.Height
)
906 Size
aSetPaperSize( aSetSize
.Width
, aSetSize
.Height
);
907 Size
aRealPaperSize( getRealPaperSize( aSetPaperSize
, true/*bNoNUP*/ ) );
908 if( aRealPaperSize
!= aCurSize
)
912 if( aIsSize
.Width
&& aIsSize
.Height
)
914 aPageSize
.aSize
.setWidth( aIsSize
.Width
);
915 aPageSize
.aSize
.setHeight( aIsSize
.Height
);
917 Size
aRealPaperSize( getRealPaperSize( aPageSize
.aSize
, true/*bNoNUP*/ ) );
918 if( aRealPaperSize
!= aCurSize
)
919 mxPrinter
->SetPaperSizeUser( aRealPaperSize
, ! isFixedPageSize() );
922 // paper bin set from properties in print dialog overrides
923 // application default for a page
924 if ( mnFixedPaperBin
!= -1 )
925 nPaperBin
= mnFixedPaperBin
;
927 if( nPaperBin
!= -1 && nPaperBin
!= mxPrinter
->GetPaperBin() )
928 mxPrinter
->SetPaperBin( nPaperBin
);
935 //when printing is finished, set the paper size of the printer to either what
936 //the user explicitly set as the desired paper size, or fallback to whatever
937 //the printer had before printing started. That way it doesn't contain the last
938 //paper size of a multiple paper size using document when we are in our normal
939 //auto accept document paper size mode and end up overwriting the original
940 //paper size setting for file->printer_settings just by pressing "ok" in the
942 void vcl::ImplPrinterControllerData::resetPaperToLastConfigured()
945 mxPrinter
->SetMapMode(MapMode(MapUnit::Map100thMM
));
946 Size
aCurSize(mxPrinter
->GetPaperSize());
947 if (aCurSize
!= maDefaultPageSize
)
948 mxPrinter
->SetPaperSizeUser(maDefaultPageSize
, !isFixedPageSize());
952 int PrinterController::getPageCountProtected() const
954 const MapMode
aMapMode( MapUnit::Map100thMM
);
956 mpImplData
->mxPrinter
->Push();
957 mpImplData
->mxPrinter
->SetMapMode( aMapMode
);
958 int nPages
= getPageCount();
959 mpImplData
->mxPrinter
->Pop();
963 css::uno::Sequence
< css::beans::PropertyValue
> PrinterController::getPageParametersProtected( int i_nPage
) const
965 const MapMode
aMapMode( MapUnit::Map100thMM
);
967 mpImplData
->mxPrinter
->Push();
968 mpImplData
->mxPrinter
->SetMapMode( aMapMode
);
969 css::uno::Sequence
< css::beans::PropertyValue
> aResult( getPageParameters( i_nPage
) );
970 mpImplData
->mxPrinter
->Pop();
974 PrinterController::PageSize
PrinterController::getPageFile( int i_nUnfilteredPage
, GDIMetaFile
& o_rMtf
, bool i_bMayUseCache
)
976 // update progress if necessary
977 if( mpImplData
->mxProgress
)
979 // do nothing if printing is canceled
980 if( mpImplData
->mxProgress
->isCanceled() )
981 return PrinterController::PageSize();
982 mpImplData
->mxProgress
->tick();
983 Application::Reschedule( true );
988 PrinterController::PageSize aPageSize
;
989 if( mpImplData
->maPageCache
.get( i_nUnfilteredPage
, o_rMtf
, aPageSize
) )
995 mpImplData
->maPageCache
.invalidate();
999 // get page parameters
1000 css::uno::Sequence
< css::beans::PropertyValue
> aPageParm( getPageParametersProtected( i_nUnfilteredPage
) );
1001 const MapMode
aMapMode( MapUnit::Map100thMM
);
1003 mpImplData
->mxPrinter
->Push();
1004 mpImplData
->mxPrinter
->SetMapMode( aMapMode
);
1006 // modify job setup if necessary
1007 PrinterController::PageSize aPageSize
= mpImplData
->modifyJobSetup( aPageParm
);
1009 o_rMtf
.SetPrefSize( aPageSize
.aSize
);
1010 o_rMtf
.SetPrefMapMode( aMapMode
);
1012 mpImplData
->mxPrinter
->EnableOutput( false );
1014 o_rMtf
.Record( mpImplData
->mxPrinter
.get() );
1016 printPage( i_nUnfilteredPage
);
1020 mpImplData
->mxPrinter
->Pop();
1022 if( i_bMayUseCache
)
1023 mpImplData
->maPageCache
.insert( i_nUnfilteredPage
, o_rMtf
, aPageSize
);
1025 // reset "FirstPage" property to false now we've gotten at least our first one
1026 mpImplData
->mbFirstPage
= false;
1031 static void appendSubPage( GDIMetaFile
& o_rMtf
, const tools::Rectangle
& i_rClipRect
, GDIMetaFile
& io_rSubPage
, bool i_bDrawBorder
)
1033 // intersect all clipregion actions with our clip rect
1034 io_rSubPage
.WindStart();
1035 io_rSubPage
.Clip( i_rClipRect
);
1038 o_rMtf
.AddAction( new MetaPushAction( PushFlags::ALL
) );
1040 // clip to page rect
1041 o_rMtf
.AddAction( new MetaClipRegionAction( vcl::Region( i_rClipRect
), true ) );
1043 // append the subpage
1044 io_rSubPage
.WindStart();
1045 io_rSubPage
.Play( o_rMtf
);
1048 o_rMtf
.AddAction( new MetaPopAction() );
1054 o_rMtf
.AddAction( new MetaPushAction( PushFlags::LINECOLOR
| PushFlags::FILLCOLOR
| PushFlags::CLIPREGION
| PushFlags::MAPMODE
) );
1055 o_rMtf
.AddAction( new MetaMapModeAction( MapMode( MapUnit::Map100thMM
) ) );
1057 tools::Rectangle
aBorderRect( i_rClipRect
);
1058 o_rMtf
.AddAction( new MetaLineColorAction( COL_BLACK
, true ) );
1059 o_rMtf
.AddAction( new MetaFillColorAction( COL_TRANSPARENT
, false ) );
1060 o_rMtf
.AddAction( new MetaRectAction( aBorderRect
) );
1063 o_rMtf
.AddAction( new MetaPopAction() );
1067 PrinterController::PageSize
PrinterController::getFilteredPageFile( int i_nFilteredPage
, GDIMetaFile
& o_rMtf
, bool i_bMayUseCache
)
1069 const MultiPageSetup
& rMPS( mpImplData
->maMultiPage
);
1070 int nSubPages
= rMPS
.nRows
* rMPS
.nColumns
;
1074 // reverse sheet order
1075 if( mpImplData
->mbReversePageOrder
)
1077 int nDocPages
= getFilteredPageCount();
1078 i_nFilteredPage
= nDocPages
- 1 - i_nFilteredPage
;
1081 // there is no filtering to be done (and possibly the page size of the
1082 // original page is to be set), when N-Up is "neutral" that is there is
1083 // only one subpage and the margins are 0
1084 if( nSubPages
== 1 &&
1085 rMPS
.nLeftMargin
== 0 && rMPS
.nRightMargin
== 0 &&
1086 rMPS
.nTopMargin
== 0 && rMPS
.nBottomMargin
== 0 )
1088 PrinterController::PageSize aPageSize
= getPageFile( i_nFilteredPage
, o_rMtf
, i_bMayUseCache
);
1089 if (mpImplData
->meJobState
!= css::view::PrintableState_JOB_STARTED
)
1090 { // rhbz#657394: check that we are still printing...
1091 return PrinterController::PageSize();
1093 Size aPaperSize
= mpImplData
->getRealPaperSize( aPageSize
.aSize
, true );
1094 mpImplData
->mxPrinter
->SetMapMode( MapMode( MapUnit::Map100thMM
) );
1095 mpImplData
->mxPrinter
->SetPaperSizeUser( aPaperSize
, ! mpImplData
->isFixedPageSize() );
1096 if( aPaperSize
!= aPageSize
.aSize
)
1098 // user overridden page size, center Metafile
1100 long nDX
= (aPaperSize
.Width() - aPageSize
.aSize
.Width()) / 2;
1101 long nDY
= (aPaperSize
.Height() - aPageSize
.aSize
.Height()) / 2;
1102 o_rMtf
.Move( nDX
, nDY
, mpImplData
->mxPrinter
->GetDPIX(), mpImplData
->mxPrinter
->GetDPIY() );
1104 o_rMtf
.SetPrefSize( aPaperSize
);
1105 aPageSize
.aSize
= aPaperSize
;
1110 // set last page property really only on the very last page to be rendered
1111 // that is on the last subpage of a NUp run
1112 bool bIsLastPage
= mpImplData
->mbLastPage
;
1113 mpImplData
->mbLastPage
= false;
1115 Size
aPaperSize( mpImplData
->getRealPaperSize( mpImplData
->maMultiPage
.aPaperSize
, false ) );
1117 // multi page area: page size minus margins + one time spacing right and down
1118 // the added spacing is so each subpage can be calculated including its spacing
1119 Size
aMPArea( aPaperSize
);
1120 aMPArea
.AdjustWidth( -(rMPS
.nLeftMargin
+ rMPS
.nRightMargin
) );
1121 aMPArea
.AdjustWidth(rMPS
.nHorizontalSpacing
);
1122 aMPArea
.AdjustHeight( -(rMPS
.nTopMargin
+ rMPS
.nBottomMargin
) );
1123 aMPArea
.AdjustHeight(rMPS
.nVerticalSpacing
);
1125 // determine offsets
1126 long nAdvX
= aMPArea
.Width() / rMPS
.nColumns
;
1127 long nAdvY
= aMPArea
.Height() / rMPS
.nRows
;
1129 // determine size of a "cell" subpage, leave a little space around pages
1130 Size
aSubPageSize( nAdvX
- rMPS
.nHorizontalSpacing
, nAdvY
- rMPS
.nVerticalSpacing
);
1133 o_rMtf
.SetPrefSize( aPaperSize
);
1134 o_rMtf
.SetPrefMapMode( MapMode( MapUnit::Map100thMM
) );
1135 o_rMtf
.AddAction( new MetaMapModeAction( MapMode( MapUnit::Map100thMM
) ) );
1137 int nDocPages
= getPageCountProtected();
1138 if (mpImplData
->meJobState
!= css::view::PrintableState_JOB_STARTED
)
1139 { // rhbz#657394: check that we are still printing...
1140 return PrinterController::PageSize();
1142 for( int nSubPage
= 0; nSubPage
< nSubPages
; nSubPage
++ )
1144 // map current sub page to real page
1145 int nPage
= i_nFilteredPage
* nSubPages
+ nSubPage
;
1146 if( nSubPage
== nSubPages
-1 ||
1147 nPage
== nDocPages
-1 )
1149 mpImplData
->mbLastPage
= bIsLastPage
;
1151 if( nPage
>= 0 && nPage
< nDocPages
)
1153 GDIMetaFile aPageFile
;
1154 PrinterController::PageSize aPageSize
= getPageFile( nPage
, aPageFile
, i_bMayUseCache
);
1155 if( aPageSize
.aSize
.Width() && aPageSize
.aSize
.Height() )
1157 long nCellX
= 0, nCellY
= 0;
1158 switch( rMPS
.nOrder
)
1160 case NupOrderType::LRTB
:
1161 nCellX
= (nSubPage
% rMPS
.nColumns
);
1162 nCellY
= (nSubPage
/ rMPS
.nColumns
);
1164 case NupOrderType::TBLR
:
1165 nCellX
= (nSubPage
/ rMPS
.nRows
);
1166 nCellY
= (nSubPage
% rMPS
.nRows
);
1168 case NupOrderType::RLTB
:
1169 nCellX
= rMPS
.nColumns
- 1 - (nSubPage
% rMPS
.nColumns
);
1170 nCellY
= (nSubPage
/ rMPS
.nColumns
);
1172 case NupOrderType::TBRL
:
1173 nCellX
= rMPS
.nColumns
- 1 - (nSubPage
/ rMPS
.nRows
);
1174 nCellY
= (nSubPage
% rMPS
.nRows
);
1177 // scale the metafile down to a sub page size
1178 double fScaleX
= double(aSubPageSize
.Width())/double(aPageSize
.aSize
.Width());
1179 double fScaleY
= double(aSubPageSize
.Height())/double(aPageSize
.aSize
.Height());
1180 double fScale
= std::min( fScaleX
, fScaleY
);
1181 aPageFile
.Scale( fScale
, fScale
);
1182 aPageFile
.WindStart();
1184 // move the subpage so it is centered in its "cell"
1185 long nOffX
= (aSubPageSize
.Width() - long(double(aPageSize
.aSize
.Width()) * fScale
)) / 2;
1186 long nOffY
= (aSubPageSize
.Height() - long(double(aPageSize
.aSize
.Height()) * fScale
)) / 2;
1187 long nX
= rMPS
.nLeftMargin
+ nOffX
+ nAdvX
* nCellX
;
1188 long nY
= rMPS
.nTopMargin
+ nOffY
+ nAdvY
* nCellY
;
1189 aPageFile
.Move( nX
, nY
, mpImplData
->mxPrinter
->GetDPIX(), mpImplData
->mxPrinter
->GetDPIY() );
1190 aPageFile
.WindStart();
1191 // calculate border rectangle
1192 tools::Rectangle
aSubPageRect( Point( nX
, nY
),
1193 Size( long(double(aPageSize
.aSize
.Width())*fScale
),
1194 long(double(aPageSize
.aSize
.Height())*fScale
) ) );
1196 // append subpage to page
1197 appendSubPage( o_rMtf
, aSubPageRect
, aPageFile
, rMPS
.bDrawBorder
);
1203 // subsequent getPageFile calls have changed the paper, reset it to current value
1204 mpImplData
->mxPrinter
->SetMapMode( MapMode( MapUnit::Map100thMM
) );
1205 mpImplData
->mxPrinter
->SetPaperSizeUser( aPaperSize
, ! mpImplData
->isFixedPageSize() );
1207 return PrinterController::PageSize( aPaperSize
, true );
1210 int PrinterController::getFilteredPageCount() const
1212 int nDiv
= mpImplData
->maMultiPage
.nRows
* mpImplData
->maMultiPage
.nColumns
;
1215 return (getPageCountProtected() + (nDiv
-1)) / nDiv
;
1218 DrawModeFlags
PrinterController::removeTransparencies( GDIMetaFile
const & i_rIn
, GDIMetaFile
& o_rOut
)
1220 DrawModeFlags nRestoreDrawMode
= mpImplData
->mxPrinter
->GetDrawMode();
1221 sal_Int32 nMaxBmpDPIX
= mpImplData
->mxPrinter
->GetDPIX();
1222 sal_Int32 nMaxBmpDPIY
= mpImplData
->mxPrinter
->GetDPIY();
1224 const PrinterOptions
& rPrinterOptions
= mpImplData
->mxPrinter
->GetPrinterOptions();
1226 static const sal_Int32 OPTIMAL_BMP_RESOLUTION
= 300;
1227 static const sal_Int32 NORMAL_BMP_RESOLUTION
= 200;
1229 if( rPrinterOptions
.IsReduceBitmaps() )
1231 // calculate maximum resolution for bitmap graphics
1232 if( PrinterBitmapMode::Optimal
== rPrinterOptions
.GetReducedBitmapMode() )
1234 nMaxBmpDPIX
= std::min( sal_Int32(OPTIMAL_BMP_RESOLUTION
), nMaxBmpDPIX
);
1235 nMaxBmpDPIY
= std::min( sal_Int32(OPTIMAL_BMP_RESOLUTION
), nMaxBmpDPIY
);
1237 else if( PrinterBitmapMode::Normal
== rPrinterOptions
.GetReducedBitmapMode() )
1239 nMaxBmpDPIX
= std::min( sal_Int32(NORMAL_BMP_RESOLUTION
), nMaxBmpDPIX
);
1240 nMaxBmpDPIY
= std::min( sal_Int32(NORMAL_BMP_RESOLUTION
), nMaxBmpDPIY
);
1244 nMaxBmpDPIX
= std::min( sal_Int32(rPrinterOptions
.GetReducedBitmapResolution()), nMaxBmpDPIX
);
1245 nMaxBmpDPIY
= std::min( sal_Int32(rPrinterOptions
.GetReducedBitmapResolution()), nMaxBmpDPIY
);
1249 // convert to greyscales
1250 if( rPrinterOptions
.IsConvertToGreyscales() )
1252 mpImplData
->mxPrinter
->SetDrawMode( mpImplData
->mxPrinter
->GetDrawMode() |
1253 ( DrawModeFlags::GrayLine
| DrawModeFlags::GrayFill
| DrawModeFlags::GrayText
|
1254 DrawModeFlags::GrayBitmap
| DrawModeFlags::GrayGradient
) );
1257 // disable transparency output
1258 if( rPrinterOptions
.IsReduceTransparency() && ( PrinterTransparencyMode::NONE
== rPrinterOptions
.GetReducedTransparencyMode() ) )
1260 mpImplData
->mxPrinter
->SetDrawMode( mpImplData
->mxPrinter
->GetDrawMode() | DrawModeFlags::NoTransparency
);
1263 Color
aBg( COL_TRANSPARENT
); // default: let RemoveTransparenciesFromMetaFile do its own background logic
1264 if( mpImplData
->maMultiPage
.nRows
* mpImplData
->maMultiPage
.nColumns
> 1 )
1266 // in N-Up printing we have no "page" background operation
1267 // we also have no way to determine the paper color
1268 // so let's go for white, which will kill 99.9% of the real cases
1271 mpImplData
->mxPrinter
->RemoveTransparenciesFromMetaFile( i_rIn
, o_rOut
, nMaxBmpDPIX
, nMaxBmpDPIY
,
1272 rPrinterOptions
.IsReduceTransparency(),
1273 rPrinterOptions
.GetReducedTransparencyMode() == PrinterTransparencyMode::Auto
,
1274 rPrinterOptions
.IsReduceBitmaps() && rPrinterOptions
.IsReducedBitmapIncludesTransparency(),
1277 return nRestoreDrawMode
;
1280 void PrinterController::printFilteredPage( int i_nPage
)
1282 if( mpImplData
->meJobState
!= css::view::PrintableState_JOB_STARTED
)
1283 return; // rhbz#657394: check that we are still printing...
1285 GDIMetaFile aPageFile
;
1286 PrinterController::PageSize aPageSize
= getFilteredPageFile( i_nPage
, aPageFile
);
1288 if( mpImplData
->mxProgress
)
1290 // do nothing if printing is canceled
1291 if( mpImplData
->mxProgress
->isCanceled() )
1293 setJobState( css::view::PrintableState_JOB_ABORTED
);
1298 // in N-Up printing set the correct page size
1299 mpImplData
->mxPrinter
->SetMapMode(MapMode(MapUnit::Map100thMM
));
1300 // aPageSize was filtered through mpImplData->getRealPaperSize already by getFilteredPageFile()
1301 mpImplData
->mxPrinter
->SetPaperSizeUser( aPageSize
.aSize
, ! mpImplData
->isFixedPageSize() );
1302 if( mpImplData
->mnFixedPaperBin
!= -1 &&
1303 mpImplData
->mxPrinter
->GetPaperBin() != mpImplData
->mnFixedPaperBin
)
1305 mpImplData
->mxPrinter
->SetPaperBin( mpImplData
->mnFixedPaperBin
);
1308 // if full paper is meant to be used, move the output to accommodate for pageoffset
1309 if( aPageSize
.bFullPaper
)
1311 Point
aPageOffset( mpImplData
->mxPrinter
->GetPageOffset() );
1312 aPageFile
.WindStart();
1313 aPageFile
.Move( -aPageOffset
.X(), -aPageOffset
.Y(), mpImplData
->mxPrinter
->GetDPIX(), mpImplData
->mxPrinter
->GetDPIY() );
1316 GDIMetaFile aCleanedFile
;
1317 DrawModeFlags nRestoreDrawMode
= removeTransparencies( aPageFile
, aCleanedFile
);
1319 mpImplData
->mxPrinter
->EnableOutput();
1321 // actually print the page
1322 mpImplData
->mxPrinter
->ImplStartPage();
1324 mpImplData
->mxPrinter
->Push();
1325 aCleanedFile
.WindStart();
1326 aCleanedFile
.Play( mpImplData
->mxPrinter
.get() );
1327 mpImplData
->mxPrinter
->Pop();
1329 mpImplData
->mxPrinter
->ImplEndPage();
1331 mpImplData
->mxPrinter
->SetDrawMode( nRestoreDrawMode
);
1334 void PrinterController::jobStarted()
1338 void PrinterController::jobFinished( css::view::PrintableState
)
1342 void PrinterController::abortJob()
1344 setJobState( css::view::PrintableState_JOB_ABORTED
);
1345 // applications (well, sw) depend on a page request with "IsLastPage" = true
1346 // to free resources, else they (well, sw) will crash eventually
1347 setLastPage( true );
1349 if (mpImplData
->mxProgress
)
1351 mpImplData
->mxProgress
->response(RET_CANCEL
);
1352 mpImplData
->mxProgress
.reset();
1356 getPageFile( 0, aMtf
);
1359 void PrinterController::setLastPage( bool i_bLastPage
)
1361 mpImplData
->mbLastPage
= i_bLastPage
;
1364 void PrinterController::setReversePrint( bool i_bReverse
)
1366 mpImplData
->mbReversePageOrder
= i_bReverse
;
1369 void PrinterController::setPapersizeFromSetup( bool i_bPapersizeFromSetup
)
1371 mpImplData
->mbPapersizeFromSetup
= i_bPapersizeFromSetup
;
1372 mpImplData
->mxPrinter
->SetPrinterSettingsPreferred( i_bPapersizeFromSetup
);
1373 if ( i_bPapersizeFromSetup
)
1374 mpImplData
->mbPapersizeFromUser
= !i_bPapersizeFromSetup
;
1377 bool PrinterController::getPapersizeFromSetup() const
1379 return mpImplData
->mbPapersizeFromSetup
;
1382 Size
& PrinterController::getPaperSizeSetup() const
1384 return mpImplData
->maDefaultPageSize
;
1387 void PrinterController::setPaperSizeFromUser( Size i_aUserSize
)
1389 mpImplData
->mbPapersizeFromUser
= true;
1390 mpImplData
->mbPapersizeFromSetup
= false;
1391 mpImplData
->mxPrinter
->SetPrinterSettingsPreferred( false );
1393 mpImplData
->maUserPageSize
= i_aUserSize
;
1396 Size
& PrinterController::getPaperSizeFromUser() const
1398 return mpImplData
->maUserPageSize
;
1401 bool PrinterController::isPaperSizeFromUser() const
1403 return mpImplData
->mbPapersizeFromUser
;
1406 void PrinterController::setPrinterModified( bool i_bPrinterModified
)
1408 mpImplData
->mbPrinterModified
= i_bPrinterModified
;
1411 bool PrinterController::getPrinterModified() const
1413 return mpImplData
->mbPrinterModified
;
1416 css::uno::Sequence
< css::beans::PropertyValue
> PrinterController::getJobProperties( const css::uno::Sequence
< css::beans::PropertyValue
>& i_rMergeList
) const
1418 std::unordered_set
< OUString
> aMergeSet
;
1419 size_t nResultLen
= size_t(i_rMergeList
.getLength()) + mpImplData
->maUIProperties
.size() + 3;
1420 for( const auto& rPropVal
: i_rMergeList
)
1421 aMergeSet
.insert( rPropVal
.Name
);
1423 css::uno::Sequence
< css::beans::PropertyValue
> aResult( nResultLen
);
1424 std::copy(i_rMergeList
.begin(), i_rMergeList
.end(), aResult
.begin());
1425 int nCur
= i_rMergeList
.getLength();
1426 for(const css::beans::PropertyValue
& rPropVal
: mpImplData
->maUIProperties
)
1428 if( aMergeSet
.find( rPropVal
.Name
) == aMergeSet
.end() )
1429 aResult
[nCur
++] = rPropVal
;
1431 // append IsFirstPage
1432 if( aMergeSet
.find( "IsFirstPage" ) == aMergeSet
.end() )
1434 css::beans::PropertyValue aVal
;
1435 aVal
.Name
= "IsFirstPage";
1436 aVal
.Value
<<= mpImplData
->mbFirstPage
;
1437 aResult
[nCur
++] = aVal
;
1439 // append IsLastPage
1440 if( aMergeSet
.find( "IsLastPage" ) == aMergeSet
.end() )
1442 css::beans::PropertyValue aVal
;
1443 aVal
.Name
= "IsLastPage";
1444 aVal
.Value
<<= mpImplData
->mbLastPage
;
1445 aResult
[nCur
++] = aVal
;
1448 if( aMergeSet
.find( "IsPrinter" ) == aMergeSet
.end() )
1450 css::beans::PropertyValue aVal
;
1451 aVal
.Name
= "IsPrinter";
1452 aVal
.Value
<<= true;
1453 aResult
[nCur
++] = aVal
;
1455 aResult
.realloc( nCur
);
1459 const css::uno::Sequence
< css::beans::PropertyValue
>& PrinterController::getUIOptions() const
1461 return mpImplData
->maUIOptions
;
1464 css::beans::PropertyValue
* PrinterController::getValue( const OUString
& i_rProperty
)
1466 std::unordered_map
< OUString
, size_t >::const_iterator it
=
1467 mpImplData
->maPropertyToIndex
.find( i_rProperty
);
1468 return it
!= mpImplData
->maPropertyToIndex
.end() ? &mpImplData
->maUIProperties
[it
->second
] : nullptr;
1471 const css::beans::PropertyValue
* PrinterController::getValue( const OUString
& i_rProperty
) const
1473 std::unordered_map
< OUString
, size_t >::const_iterator it
=
1474 mpImplData
->maPropertyToIndex
.find( i_rProperty
);
1475 return it
!= mpImplData
->maPropertyToIndex
.end() ? &mpImplData
->maUIProperties
[it
->second
] : nullptr;
1478 void PrinterController::setValue( const OUString
& i_rPropertyName
, const css::uno::Any
& i_rValue
)
1480 css::beans::PropertyValue aVal
;
1481 aVal
.Name
= i_rPropertyName
;
1482 aVal
.Value
= i_rValue
;
1487 void PrinterController::setValue( const css::beans::PropertyValue
& i_rPropertyValue
)
1489 std::unordered_map
< OUString
, size_t >::const_iterator it
=
1490 mpImplData
->maPropertyToIndex
.find( i_rPropertyValue
.Name
);
1491 if( it
!= mpImplData
->maPropertyToIndex
.end() )
1492 mpImplData
->maUIProperties
[ it
->second
] = i_rPropertyValue
;
1495 // insert correct index into property map
1496 mpImplData
->maPropertyToIndex
[ i_rPropertyValue
.Name
] = mpImplData
->maUIProperties
.size();
1497 mpImplData
->maUIProperties
.push_back( i_rPropertyValue
);
1498 mpImplData
->maUIPropertyEnabled
.push_back( true );
1502 void PrinterController::setUIOptions( const css::uno::Sequence
< css::beans::PropertyValue
>& i_rOptions
)
1504 SAL_WARN_IF( mpImplData
->maUIOptions
.hasElements(), "vcl.gdi", "setUIOptions called twice !" );
1506 mpImplData
->maUIOptions
= i_rOptions
;
1508 for( const auto& rOpt
: i_rOptions
)
1510 css::uno::Sequence
< css::beans::PropertyValue
> aOptProp
;
1511 rOpt
.Value
>>= aOptProp
;
1512 bool bIsEnabled
= true;
1513 bool bHaveProperty
= false;
1515 vcl::ImplPrinterControllerData::ControlDependency aDep
;
1516 css::uno::Sequence
< sal_Bool
> aChoicesDisabled
;
1517 for( const css::beans::PropertyValue
& rEntry
: std::as_const(aOptProp
) )
1519 if ( rEntry
.Name
== "Property" )
1521 css::beans::PropertyValue aVal
;
1522 rEntry
.Value
>>= aVal
;
1523 DBG_ASSERT( mpImplData
->maPropertyToIndex
.find( aVal
.Name
)
1524 == mpImplData
->maPropertyToIndex
.end(), "duplicate property entry" );
1526 aPropName
= aVal
.Name
;
1527 bHaveProperty
= true;
1529 else if ( rEntry
.Name
== "Enabled" )
1532 rEntry
.Value
>>= bValue
;
1533 bIsEnabled
= bValue
;
1535 else if ( rEntry
.Name
== "DependsOnName" )
1537 rEntry
.Value
>>= aDep
.maDependsOnName
;
1539 else if ( rEntry
.Name
== "DependsOnEntry" )
1541 rEntry
.Value
>>= aDep
.mnDependsOnEntry
;
1543 else if ( rEntry
.Name
== "ChoicesDisabled" )
1545 rEntry
.Value
>>= aChoicesDisabled
;
1550 vcl::ImplPrinterControllerData::PropertyToIndexMap::const_iterator it
=
1551 mpImplData
->maPropertyToIndex
.find( aPropName
);
1553 if( it
!= mpImplData
->maPropertyToIndex
.end() )
1555 mpImplData
->maUIPropertyEnabled
[ it
->second
] = bIsEnabled
;
1557 if( !aDep
.maDependsOnName
.isEmpty() )
1558 mpImplData
->maControlDependencies
[ aPropName
] = aDep
;
1559 if( aChoicesDisabled
.hasElements() )
1560 mpImplData
->maChoiceDisableMap
[ aPropName
] = aChoicesDisabled
;
1565 bool PrinterController::isUIOptionEnabled( const OUString
& i_rProperty
) const
1567 bool bEnabled
= false;
1568 std::unordered_map
< OUString
, size_t >::const_iterator prop_it
=
1569 mpImplData
->maPropertyToIndex
.find( i_rProperty
);
1570 if( prop_it
!= mpImplData
->maPropertyToIndex
.end() )
1572 bEnabled
= mpImplData
->maUIPropertyEnabled
[prop_it
->second
];
1576 // check control dependencies
1577 vcl::ImplPrinterControllerData::ControlDependencyMap::const_iterator it
=
1578 mpImplData
->maControlDependencies
.find( i_rProperty
);
1579 if( it
!= mpImplData
->maControlDependencies
.end() )
1581 // check if the dependency is enabled
1582 // if the dependency is disabled, we are too
1583 bEnabled
= isUIOptionEnabled( it
->second
.maDependsOnName
);
1587 // does the dependency have the correct value ?
1588 const css::beans::PropertyValue
* pVal
= getValue( it
->second
.maDependsOnName
);
1589 OSL_ENSURE( pVal
, "unknown property in dependency" );
1592 sal_Int32 nDepVal
= 0;
1593 bool bDepVal
= false;
1594 if( pVal
->Value
>>= nDepVal
)
1596 bEnabled
= (nDepVal
== it
->second
.mnDependsOnEntry
) || (it
->second
.mnDependsOnEntry
== -1);
1598 else if( pVal
->Value
>>= bDepVal
)
1600 // could be a dependency on a checked boolean
1601 // in this case the dependency is on a non zero for checked value
1602 bEnabled
= ( bDepVal
&& it
->second
.mnDependsOnEntry
!= 0) ||
1603 ( ! bDepVal
&& it
->second
.mnDependsOnEntry
== 0);
1607 // if the type does not match something is awry
1608 OSL_FAIL( "strange type in control dependency" );
1619 bool PrinterController::isUIChoiceEnabled( const OUString
& i_rProperty
, sal_Int32 i_nValue
) const
1621 bool bEnabled
= true;
1622 ImplPrinterControllerData::ChoiceDisableMap::const_iterator it
=
1623 mpImplData
->maChoiceDisableMap
.find( i_rProperty
);
1624 if(it
!= mpImplData
->maChoiceDisableMap
.end() )
1626 const css::uno::Sequence
< sal_Bool
>& rDisabled( it
->second
);
1627 if( i_nValue
>= 0 && i_nValue
< rDisabled
.getLength() )
1628 bEnabled
= ! rDisabled
[i_nValue
];
1633 OUString
PrinterController::makeEnabled( const OUString
& i_rProperty
)
1635 OUString aDependency
;
1637 vcl::ImplPrinterControllerData::ControlDependencyMap::const_iterator it
=
1638 mpImplData
->maControlDependencies
.find( i_rProperty
);
1639 if( it
!= mpImplData
->maControlDependencies
.end() )
1641 if( isUIOptionEnabled( it
->second
.maDependsOnName
) )
1643 aDependency
= it
->second
.maDependsOnName
;
1644 const css::beans::PropertyValue
* pVal
= getValue( aDependency
);
1645 OSL_ENSURE( pVal
, "unknown property in dependency" );
1648 sal_Int32 nDepVal
= 0;
1649 bool bDepVal
= false;
1650 if( pVal
->Value
>>= nDepVal
)
1652 if( it
->second
.mnDependsOnEntry
!= -1 )
1654 setValue( aDependency
, css::uno::makeAny( sal_Int32( it
->second
.mnDependsOnEntry
) ) );
1657 else if( pVal
->Value
>>= bDepVal
)
1659 setValue( aDependency
, css::uno::makeAny( it
->second
.mnDependsOnEntry
!= 0 ) );
1663 // if the type does not match something is awry
1664 OSL_FAIL( "strange type in control dependency" );
1673 void PrinterController::createProgressDialog()
1675 if (!mpImplData
->mxProgress
)
1678 css::beans::PropertyValue
* pMonitor
= getValue( "MonitorVisible" );
1680 pMonitor
->Value
>>= bShow
;
1683 const css::beans::PropertyValue
* pVal
= getValue( "IsApi" );
1687 pVal
->Value
>>= bApi
;
1692 if( bShow
&& ! Application::IsHeadlessModeEnabled() )
1694 mpImplData
->mxProgress
.reset(new PrintProgressDialog(getWindow(), getPageCountProtected()));
1695 weld::DialogController::runAsync(mpImplData
->mxProgress
, [](sal_Int32
/*nResult*/){});
1700 mpImplData
->mxProgress
->response(RET_CANCEL
);
1701 mpImplData
->mxProgress
.reset();
1705 bool PrinterController::isProgressCanceled() const
1707 return mpImplData
->mxProgress
&& mpImplData
->mxProgress
->isCanceled();
1710 void PrinterController::setMultipage( const MultiPageSetup
& i_rMPS
)
1712 mpImplData
->maMultiPage
= i_rMPS
;
1715 const PrinterController::MultiPageSetup
& PrinterController::getMultipage() const
1717 return mpImplData
->maMultiPage
;
1720 void PrinterController::resetPaperToLastConfigured()
1722 mpImplData
->resetPaperToLastConfigured();
1725 void PrinterController::pushPropertiesToPrinter()
1727 sal_Int32 nCopyCount
= 1;
1728 // set copycount and collate
1729 const css::beans::PropertyValue
* pVal
= getValue( "CopyCount" );
1731 pVal
->Value
>>= nCopyCount
;
1732 bool bCollate
= false;
1733 pVal
= getValue( "Collate" );
1735 pVal
->Value
>>= bCollate
;
1736 mpImplData
->mxPrinter
->SetCopyCount( static_cast<sal_uInt16
>(nCopyCount
), bCollate
);
1739 pVal
= getValue( "DuplexMode" );
1742 sal_Int16 nDuplex
= css::view::DuplexMode::UNKNOWN
;
1743 pVal
->Value
>>= nDuplex
;
1746 case css::view::DuplexMode::OFF
: mpImplData
->mxPrinter
->SetDuplexMode( DuplexMode::Off
); break;
1747 case css::view::DuplexMode::LONGEDGE
: mpImplData
->mxPrinter
->SetDuplexMode( DuplexMode::LongEdge
); break;
1748 case css::view::DuplexMode::SHORTEDGE
: mpImplData
->mxPrinter
->SetDuplexMode( DuplexMode::ShortEdge
); break;
1753 bool PrinterController::isShowDialogs() const
1755 bool bApi
= getBoolProperty( "IsApi", false );
1756 return ! bApi
&& ! Application::IsHeadlessModeEnabled();
1759 bool PrinterController::isDirectPrint() const
1761 bool bDirect
= getBoolProperty( "IsDirect", false );
1765 bool PrinterController::getBoolProperty( const OUString
& i_rProperty
, bool i_bFallback
) const
1767 bool bRet
= i_bFallback
;
1768 const css::beans::PropertyValue
* pVal
= getValue( i_rProperty
);
1770 pVal
->Value
>>= bRet
;
1774 sal_Int32
PrinterController::getIntProperty( const OUString
& i_rProperty
, sal_Int32 i_nFallback
) const
1776 sal_Int32 nRet
= i_nFallback
;
1777 const css::beans::PropertyValue
* pVal
= getValue( i_rProperty
);
1779 pVal
->Value
>>= nRet
;
1784 * PrinterOptionsHelper
1786 css::uno::Any
PrinterOptionsHelper::getValue( const OUString
& i_rPropertyName
) const
1789 std::unordered_map
< OUString
, css::uno::Any
>::const_iterator it
=
1790 m_aPropertyMap
.find( i_rPropertyName
);
1791 if( it
!= m_aPropertyMap
.end() )
1796 bool PrinterOptionsHelper::getBoolValue( const OUString
& i_rPropertyName
, bool i_bDefault
) const
1799 css::uno::Any
aVal( getValue( i_rPropertyName
) );
1800 return (aVal
>>= bRet
) ? bRet
: i_bDefault
;
1803 sal_Int64
PrinterOptionsHelper::getIntValue( const OUString
& i_rPropertyName
, sal_Int64 i_nDefault
) const
1806 css::uno::Any
aVal( getValue( i_rPropertyName
) );
1807 return (aVal
>>= nRet
) ? nRet
: i_nDefault
;
1810 OUString
PrinterOptionsHelper::getStringValue( const OUString
& i_rPropertyName
) const
1813 css::uno::Any
aVal( getValue( i_rPropertyName
) );
1814 return (aVal
>>= aRet
) ? aRet
: OUString();
1817 bool PrinterOptionsHelper::processProperties( const css::uno::Sequence
< css::beans::PropertyValue
>& i_rNewProp
)
1819 bool bChanged
= false;
1821 for( const auto& rVal
: i_rNewProp
)
1823 std::unordered_map
< OUString
, css::uno::Any
>::iterator it
=
1824 m_aPropertyMap
.find( rVal
.Name
);
1826 bool bElementChanged
= (it
== m_aPropertyMap
.end()) || (it
->second
!= rVal
.Value
);
1827 if( bElementChanged
)
1829 m_aPropertyMap
[ rVal
.Name
] = rVal
.Value
;
1836 void PrinterOptionsHelper::appendPrintUIOptions( css::uno::Sequence
< css::beans::PropertyValue
>& io_rProps
) const
1838 if( !m_aUIProperties
.empty() )
1840 sal_Int32 nIndex
= io_rProps
.getLength();
1841 io_rProps
.realloc( nIndex
+1 );
1842 css::beans::PropertyValue aVal
;
1843 aVal
.Name
= "ExtraPrintUIOptions";
1844 aVal
.Value
<<= comphelper::containerToSequence(m_aUIProperties
);
1845 io_rProps
[ nIndex
] = aVal
;
1849 css::uno::Any
PrinterOptionsHelper::setUIControlOpt(const css::uno::Sequence
< OUString
>& i_rIDs
,
1850 const OUString
& i_rTitle
,
1851 const css::uno::Sequence
< OUString
>& i_rHelpIds
,
1852 const OUString
& i_rType
,
1853 const css::beans::PropertyValue
* i_pVal
,
1854 const PrinterOptionsHelper::UIControlOptions
& i_rControlOptions
)
1856 sal_Int32 nElements
=
1857 2 // ControlType + ID
1858 + (i_rTitle
.isEmpty() ? 0 : 1) // Text
1859 + (i_rHelpIds
.hasElements() ? 1 : 0) // HelpId
1860 + (i_pVal
? 1 : 0) // Property
1861 + i_rControlOptions
.maAddProps
.size() // additional props
1862 + (i_rControlOptions
.maGroupHint
.isEmpty() ? 0 : 1) // grouping
1863 + (i_rControlOptions
.mbInternalOnly
? 1 : 0) // internal hint
1864 + (i_rControlOptions
.mbEnabled
? 0 : 1) // enabled
1866 if( !i_rControlOptions
.maDependsOnName
.isEmpty() )
1869 if( i_rControlOptions
.mnDependsOnEntry
!= -1 )
1871 if( i_rControlOptions
.mbAttachToDependency
)
1875 css::uno::Sequence
< css::beans::PropertyValue
> aCtrl( nElements
);
1876 sal_Int32 nUsed
= 0;
1877 if( !i_rTitle
.isEmpty() )
1879 aCtrl
[nUsed
].Name
= "Text";
1880 aCtrl
[nUsed
++].Value
<<= i_rTitle
;
1882 if( i_rHelpIds
.hasElements() )
1884 aCtrl
[nUsed
].Name
= "HelpId";
1885 aCtrl
[nUsed
++].Value
<<= i_rHelpIds
;
1887 aCtrl
[nUsed
].Name
= "ControlType";
1888 aCtrl
[nUsed
++].Value
<<= i_rType
;
1889 aCtrl
[nUsed
].Name
= "ID";
1890 aCtrl
[nUsed
++].Value
<<= i_rIDs
;
1893 aCtrl
[nUsed
].Name
= "Property";
1894 aCtrl
[nUsed
++].Value
<<= *i_pVal
;
1896 if( !i_rControlOptions
.maDependsOnName
.isEmpty() )
1898 aCtrl
[nUsed
].Name
= "DependsOnName";
1899 aCtrl
[nUsed
++].Value
<<= i_rControlOptions
.maDependsOnName
;
1900 if( i_rControlOptions
.mnDependsOnEntry
!= -1 )
1902 aCtrl
[nUsed
].Name
= "DependsOnEntry";
1903 aCtrl
[nUsed
++].Value
<<= i_rControlOptions
.mnDependsOnEntry
;
1905 if( i_rControlOptions
.mbAttachToDependency
)
1907 aCtrl
[nUsed
].Name
= "AttachToDependency";
1908 aCtrl
[nUsed
++].Value
<<= i_rControlOptions
.mbAttachToDependency
;
1911 if( !i_rControlOptions
.maGroupHint
.isEmpty() )
1913 aCtrl
[nUsed
].Name
= "GroupingHint";
1914 aCtrl
[nUsed
++].Value
<<= i_rControlOptions
.maGroupHint
;
1916 if( i_rControlOptions
.mbInternalOnly
)
1918 aCtrl
[nUsed
].Name
= "InternalUIOnly";
1919 aCtrl
[nUsed
++].Value
<<= true;
1921 if( ! i_rControlOptions
.mbEnabled
)
1923 aCtrl
[nUsed
].Name
= "Enabled";
1924 aCtrl
[nUsed
++].Value
<<= false;
1927 sal_Int32 nAddProps
= i_rControlOptions
.maAddProps
.size();
1928 for( sal_Int32 i
= 0; i
< nAddProps
; i
++ )
1929 aCtrl
[ nUsed
++ ] = i_rControlOptions
.maAddProps
[i
];
1931 SAL_WARN_IF( nUsed
!= nElements
, "vcl.gdi", "nUsed != nElements, probable heap corruption" );
1933 return css::uno::makeAny( aCtrl
);
1936 css::uno::Any
PrinterOptionsHelper::setGroupControlOpt(const OUString
& i_rID
,
1937 const OUString
& i_rTitle
,
1938 const OUString
& i_rHelpId
)
1940 css::uno::Sequence
< OUString
> aHelpId
;
1941 if( !i_rHelpId
.isEmpty() )
1943 aHelpId
.realloc( 1 );
1944 *aHelpId
.getArray() = i_rHelpId
;
1946 css::uno::Sequence
< OUString
> aIds
{ i_rID
};
1947 return setUIControlOpt(aIds
, i_rTitle
, aHelpId
, "Group");
1950 css::uno::Any
PrinterOptionsHelper::setSubgroupControlOpt(const OUString
& i_rID
,
1951 const OUString
& i_rTitle
,
1952 const OUString
& i_rHelpId
,
1953 const PrinterOptionsHelper::UIControlOptions
& i_rControlOptions
)
1955 css::uno::Sequence
< OUString
> aHelpId
;
1956 if( !i_rHelpId
.isEmpty() )
1958 aHelpId
.realloc( 1 );
1959 *aHelpId
.getArray() = i_rHelpId
;
1961 css::uno::Sequence
< OUString
> aIds
{ i_rID
};
1962 return setUIControlOpt(aIds
, i_rTitle
, aHelpId
, "Subgroup", nullptr, i_rControlOptions
);
1965 css::uno::Any
PrinterOptionsHelper::setBoolControlOpt(const OUString
& i_rID
,
1966 const OUString
& i_rTitle
,
1967 const OUString
& i_rHelpId
,
1968 const OUString
& i_rProperty
,
1970 const PrinterOptionsHelper::UIControlOptions
& i_rControlOptions
)
1972 css::uno::Sequence
< OUString
> aHelpId
;
1973 if( !i_rHelpId
.isEmpty() )
1975 aHelpId
.realloc( 1 );
1976 *aHelpId
.getArray() = i_rHelpId
;
1978 css::beans::PropertyValue aVal
;
1979 aVal
.Name
= i_rProperty
;
1980 aVal
.Value
<<= i_bValue
;
1981 css::uno::Sequence
< OUString
> aIds
{ i_rID
};
1982 return setUIControlOpt(aIds
, i_rTitle
, aHelpId
, "Bool", &aVal
, i_rControlOptions
);
1985 css::uno::Any
PrinterOptionsHelper::setChoiceRadiosControlOpt(const css::uno::Sequence
< OUString
>& i_rIDs
,
1986 const OUString
& i_rTitle
,
1987 const css::uno::Sequence
< OUString
>& i_rHelpId
,
1988 const OUString
& i_rProperty
,
1989 const css::uno::Sequence
< OUString
>& i_rChoices
,
1991 const css::uno::Sequence
< sal_Bool
>& i_rDisabledChoices
,
1992 const PrinterOptionsHelper::UIControlOptions
& i_rControlOptions
)
1994 UIControlOptions
aOpt( i_rControlOptions
);
1995 sal_Int32 nUsed
= aOpt
.maAddProps
.size();
1996 aOpt
.maAddProps
.resize( nUsed
+ 1 + (i_rDisabledChoices
.hasElements() ? 1 : 0) );
1997 aOpt
.maAddProps
[nUsed
].Name
= "Choices";
1998 aOpt
.maAddProps
[nUsed
].Value
<<= i_rChoices
;
1999 if( i_rDisabledChoices
.hasElements() )
2001 aOpt
.maAddProps
[nUsed
+1].Name
= "ChoicesDisabled";
2002 aOpt
.maAddProps
[nUsed
+1].Value
<<= i_rDisabledChoices
;
2005 css::beans::PropertyValue aVal
;
2006 aVal
.Name
= i_rProperty
;
2007 aVal
.Value
<<= i_nValue
;
2008 return setUIControlOpt(i_rIDs
, i_rTitle
, i_rHelpId
, "Radio", &aVal
, aOpt
);
2011 css::uno::Any
PrinterOptionsHelper::setChoiceListControlOpt(const OUString
& i_rID
,
2012 const OUString
& i_rTitle
,
2013 const css::uno::Sequence
< OUString
>& i_rHelpId
,
2014 const OUString
& i_rProperty
,
2015 const css::uno::Sequence
< OUString
>& i_rChoices
,
2017 const css::uno::Sequence
< sal_Bool
>& i_rDisabledChoices
,
2018 const PrinterOptionsHelper::UIControlOptions
& i_rControlOptions
)
2020 UIControlOptions
aOpt( i_rControlOptions
);
2021 sal_Int32 nUsed
= aOpt
.maAddProps
.size();
2022 aOpt
.maAddProps
.resize( nUsed
+ 1 + (i_rDisabledChoices
.hasElements() ? 1 : 0) );
2023 aOpt
.maAddProps
[nUsed
].Name
= "Choices";
2024 aOpt
.maAddProps
[nUsed
].Value
<<= i_rChoices
;
2025 if( i_rDisabledChoices
.hasElements() )
2027 aOpt
.maAddProps
[nUsed
+1].Name
= "ChoicesDisabled";
2028 aOpt
.maAddProps
[nUsed
+1].Value
<<= i_rDisabledChoices
;
2031 css::beans::PropertyValue aVal
;
2032 aVal
.Name
= i_rProperty
;
2033 aVal
.Value
<<= i_nValue
;
2034 css::uno::Sequence
< OUString
> aIds
{ i_rID
};
2035 return setUIControlOpt(aIds
, i_rTitle
, i_rHelpId
, "List", &aVal
, aOpt
);
2038 css::uno::Any
PrinterOptionsHelper::setRangeControlOpt(const OUString
& i_rID
,
2039 const OUString
& i_rTitle
,
2040 const OUString
& i_rHelpId
,
2041 const OUString
& i_rProperty
,
2043 sal_Int32 i_nMinValue
,
2044 sal_Int32 i_nMaxValue
,
2045 const PrinterOptionsHelper::UIControlOptions
& i_rControlOptions
)
2047 UIControlOptions
aOpt( i_rControlOptions
);
2048 if( i_nMaxValue
>= i_nMinValue
)
2050 sal_Int32 nUsed
= aOpt
.maAddProps
.size();
2051 aOpt
.maAddProps
.resize( nUsed
+ 2 );
2052 aOpt
.maAddProps
[nUsed
].Name
= "MinValue";
2053 aOpt
.maAddProps
[nUsed
++].Value
<<= i_nMinValue
;
2054 aOpt
.maAddProps
[nUsed
].Name
= "MaxValue";
2055 aOpt
.maAddProps
[nUsed
++].Value
<<= i_nMaxValue
;
2058 css::uno::Sequence
< OUString
> aHelpId
;
2059 if( !i_rHelpId
.isEmpty() )
2061 aHelpId
.realloc( 1 );
2062 *aHelpId
.getArray() = i_rHelpId
;
2064 css::beans::PropertyValue aVal
;
2065 aVal
.Name
= i_rProperty
;
2066 aVal
.Value
<<= i_nValue
;
2067 css::uno::Sequence
< OUString
> aIds
{ i_rID
};
2068 return setUIControlOpt(aIds
, i_rTitle
, aHelpId
, "Range", &aVal
, aOpt
);
2071 css::uno::Any
PrinterOptionsHelper::setEditControlOpt(const OUString
& i_rID
,
2072 const OUString
& i_rTitle
,
2073 const OUString
& i_rHelpId
,
2074 const OUString
& i_rProperty
,
2075 const OUString
& i_rValue
,
2076 const PrinterOptionsHelper::UIControlOptions
& i_rControlOptions
)
2078 css::uno::Sequence
< OUString
> aHelpId
;
2079 if( !i_rHelpId
.isEmpty() )
2081 aHelpId
.realloc( 1 );
2082 *aHelpId
.getArray() = i_rHelpId
;
2084 css::beans::PropertyValue aVal
;
2085 aVal
.Name
= i_rProperty
;
2086 aVal
.Value
<<= i_rValue
;
2087 css::uno::Sequence
< OUString
> aIds
{ i_rID
};
2088 return setUIControlOpt(aIds
, i_rTitle
, aHelpId
, "Edit", &aVal
, i_rControlOptions
);
2091 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */