LibreOffice Module vcl (master)  1
print3.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <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>
27 #include <comphelper/sequence.hxx>
28 #include <sal/types.h>
29 #include <sal/log.hxx>
30 #include <tools/debug.hxx>
31 
32 #include <printdlg.hxx>
33 #include <svdata.hxx>
34 #include <salinst.hxx>
35 #include <salprn.hxx>
36 #include <strings.hrc>
37 
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>
44 
45 #include <unordered_map>
46 #include <unordered_set>
47 
48 using namespace vcl;
49 
51 {
52  struct CacheEntry
53  {
56  };
57 
58  std::vector< CacheEntry > maPages;
59  std::vector< sal_Int32 > maPageNumbers;
60  std::vector< sal_Int32 > maCacheRanking;
61 
62  static const sal_Int32 nCacheSize = 6;
63 
64  void updateRanking( sal_Int32 nLastHit )
65  {
66  if( maCacheRanking[0] != nLastHit )
67  {
68  for( sal_Int32 i = nCacheSize-1; i > 0; i-- )
69  maCacheRanking[i] = maCacheRanking[i-1];
70  maCacheRanking[0] = nLastHit;
71  }
72  }
73 
74 public:
76  : maPages( nCacheSize )
77  , maPageNumbers( nCacheSize, -1 )
78  , maCacheRanking( nCacheSize )
79  {
80  for( sal_Int32 i = 0; i < nCacheSize; i++ )
81  maCacheRanking[i] = nCacheSize - i - 1;
82  }
83 
84  // caution: does not ensure uniqueness
85  void insert( sal_Int32 i_nPageNo, const GDIMetaFile& i_rPage, const PrinterController::PageSize& i_rSize )
86  {
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 );
94  }
95 
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 )
100  {
101  for( sal_Int32 i = 0; i < nCacheSize; ++i )
102  {
103  if( maPageNumbers[i] == i_nPageNo )
104  {
105  updateRanking( i );
106  o_rPageFile = maPages[i].aPage;
107  o_rSize = maPages[i].aSize;
108  return true;
109  }
110  }
111  return false;
112  }
113 
114  void invalidate()
115  {
116  for( sal_Int32 i = 0; i < nCacheSize; ++i )
117  {
118  maPageNumbers[i] = -1;
119  maPages[i].aPage.Clear();
120  maCacheRanking[i] = nCacheSize - i - 1;
121  }
122  }
123 };
124 
126 {
127 public:
129  {
130  OUString maDependsOnName;
131  sal_Int32 mnDependsOnEntry;
132 
133  ControlDependency() : mnDependsOnEntry( -1 ) {}
134  };
135 
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;
139 
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;
154  css::view::PrintableState meJobState;
155 
157 
158  std::shared_ptr<vcl::PrintProgressDialog> mxProgress;
159 
161 
162  // set by user through printer properties subdialog of printer settings dialog
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;
171 
172  // N.B. Apparently we have three levels of paper tray settings
173  // (latter overrides former):
174  // 1. default tray
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...
184 
186  mbFirstPage( true ),
187  mbLastPage( false ),
188  mbReversePageOrder( false ),
189  mbPapersizeFromSetup( false ),
190  mbPapersizeFromUser( false ),
191  mbPrinterModified( false ),
192  meJobState( css::view::PrintableState_JOB_STARTED ),
193  mnDefaultPaperBin( -1 ),
194  mnFixedPaperBin( -1 )
195  {}
196 
198  {
199  if (mxProgress)
200  {
201  mxProgress->response(RET_CANCEL);
202  mxProgress.reset();
203  }
204  }
205 
206  const Size& getRealPaperSize( const Size& i_rPageSize, bool bNoNUP ) const
207  {
208  if ( mbPapersizeFromUser )
209  return maUserPageSize;
210  if( mbPapersizeFromSetup )
211  return maDefaultPageSize;
212  if( maMultiPage.nRows * maMultiPage.nColumns > 1 && ! bNoNUP )
213  return maMultiPage.aPaperSize;
214  return i_rPageSize;
215  }
216  bool isFixedPageSize() const
217  { return mbPapersizeFromSetup; }
218  PrinterController::PageSize modifyJobSetup( const css::uno::Sequence< css::beans::PropertyValue >& i_rProps );
220 };
221 
223  : mpImplData( new ImplPrinterControllerData )
224 {
225  mpImplData->mxPrinter = i_xPrinter;
226  mpImplData->mxWindow = i_xWindow;
227 }
228 
229 static OUString queryFile( Printer const * pPrinter )
230 {
231  OUString aResult;
232 
233  css::uno::Reference< css::uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
234  css::uno::Reference< css::ui::dialogs::XFilePicker3 > xFilePicker = css::ui::dialogs::FilePicker::createWithMode(xContext, css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION);
235 
236  try
237  {
238 #ifdef UNX
239  // add PostScript and PDF
240  bool bPS = true, bPDF = true;
241  if( pPrinter )
242  {
243  if( pPrinter->GetCapabilities( PrinterCapType::PDF ) )
244  bPS = false;
245  else
246  bPDF = false;
247  }
248  if( bPS )
249  xFilePicker->appendFilter( "PostScript", "*.ps" );
250  if( bPDF )
251  xFilePicker->appendFilter( "Portable Document Format", "*.pdf" );
252 #elif defined WNT
253  (void)pPrinter;
254  xFilePicker->appendFilter( "*.PRN", "*.prn" );
255 #endif
256  // add arbitrary files
257  xFilePicker->appendFilter(VclResId(SV_STDTEXT_ALLFILETYPES), "*.*");
258  }
259  catch (const css::lang::IllegalArgumentException&)
260  {
261  SAL_WARN( "vcl.gdi", "caught IllegalArgumentException when registering filter" );
262  }
263 
264  if( xFilePicker->execute() == css::ui::dialogs::ExecutableDialogResults::OK )
265  {
266  css::uno::Sequence< OUString > aPathSeq( xFilePicker->getSelectedFiles() );
267  INetURLObject aObj( aPathSeq[0] );
268  aResult = aObj.PathToFileName();
269  }
270  return aResult;
271 }
272 
274 {
275  std::shared_ptr<PrinterController> mxController;
277 
278  PrintJobAsync(const std::shared_ptr<PrinterController>& i_xController,
279  const JobSetup& i_rInitSetup)
280  : mxController( i_xController ), maInitSetup( i_rInitSetup )
281  {}
282 
283  DECL_LINK( ExecJob, void*, void );
284 };
285 
286 IMPL_LINK_NOARG(PrintJobAsync, ExecJob, void*, void)
287 {
288  Printer::ImplPrintJob(mxController, maInitSetup);
289 
290  // clean up, do not access members after this
291  delete this;
292 }
293 
294 void Printer::PrintJob(const std::shared_ptr<PrinterController>& i_xController,
295  const JobSetup& i_rInitSetup)
296 {
297  bool bSynchronous = false;
298  css::beans::PropertyValue* pVal = i_xController->getValue( "Wait" );
299  if( pVal )
300  pVal->Value >>= bSynchronous;
301 
302  if( bSynchronous )
303  ImplPrintJob(i_xController, i_rInitSetup);
304  else
305  {
306  PrintJobAsync* pAsync = new PrintJobAsync(i_xController, i_rInitSetup);
307  Application::PostUserEvent( LINK( pAsync, PrintJobAsync, ExecJob ) );
308  }
309 }
310 
311 bool Printer::PreparePrintJob(std::shared_ptr<PrinterController> xController,
312  const JobSetup& i_rInitSetup)
313 {
314  // check if there is a default printer; if not, show an error box (if appropriate)
315  if( GetDefaultPrinterName().isEmpty() )
316  {
317  if (xController->isShowDialogs())
318  {
319  VclPtr<vcl::Window> xParent = xController->getWindow();
320  std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(xParent ? xParent->GetFrameWeld() : nullptr, "vcl/ui/errornoprinterdialog.ui"));
321  std::unique_ptr<weld::MessageDialog> xBox(xBuilder->weld_message_dialog("ErrorNoPrinterDialog"));
322  xBox->run();
323  }
324  xController->setValue( "IsDirect",
325  css::uno::makeAny( false ) );
326  }
327 
328  // setup printer
329 
330  // #i114306# changed behavior back from persistence
331  // if no specific printer is already set, create the default printer
332  if (!xController->getPrinter())
333  {
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());
339  }
340 
341  // reset last page property
342  xController->setLastPage(false);
343 
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
350 
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");
355  if( ! pContentVal )
356  pContentVal = xController->getValue("PrintContent");
357 
358  // case 1: UNO API has set "Pages"
359  css::beans::PropertyValue* pPagesVal = xController->getValue("Pages");
360  if( pPagesVal )
361  {
362  OUString aPagesVal;
363  pPagesVal->Value >>= aPagesVal;
364  if( !aPagesVal.isEmpty() )
365  {
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
369  if( pContentVal )
370  {
371  pContentVal->Value <<= sal_Int32( 1 );
372  xController->setValue("PageRange", pPagesVal->Value);
373  }
374  }
375  }
376  // case 2: is "All" selected ?
377  else if( pContentVal )
378  {
379  sal_Int32 nContent = -1;
380  if( pContentVal->Value >>= nContent )
381  {
382  if( nContent == 0 )
383  {
384  // do not overwrite PageRange if it is already set
385  css::beans::PropertyValue* pRangeVal = xController->getValue("PageRange");
386  OUString aRange;
387  if( pRangeVal )
388  pRangeVal->Value >>= aRange;
389  if( aRange.isEmpty() )
390  {
391  sal_Int32 nPages = xController->getPageCount();
392  if( nPages > 0 )
393  {
394  OUStringBuffer aBuf( 32 );
395  aBuf.append( "1" );
396  if( nPages > 1 )
397  {
398  aBuf.append( "-" );
399  aBuf.append( nPages );
400  }
401  xController->setValue("PageRange", css::uno::makeAny(aBuf.makeStringAndClear()));
402  }
403  }
404  }
405  }
406  }
407 
408  css::beans::PropertyValue* pReverseVal = xController->getValue("PrintReverse");
409  if( pReverseVal )
410  {
411  bool bReverse = false;
412  pReverseVal->Value >>= bReverse;
413  xController->setReversePrint( bReverse );
414  }
415 
416  css::beans::PropertyValue* pPapersizeFromSetupVal = xController->getValue("PapersizeFromSetup");
417  if( pPapersizeFromSetupVal )
418  {
419  bool bPapersizeFromSetup = false;
420  pPapersizeFromSetupVal->Value >>= bPapersizeFromSetup;
421  xController->setPapersizeFromSetup(bPapersizeFromSetup);
422  }
423 
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 )
428  {
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);
433  if( nValue >= 0 )
434  aMPS.nLeftMargin = nValue;
435  nValue = xController->getIntProperty("NUpPageMarginRight", aMPS.nRightMargin);
436  if( nValue >= 0 )
437  aMPS.nRightMargin = nValue;
438  nValue = xController->getIntProperty( "NUpPageMarginTop", aMPS.nTopMargin );
439  if( nValue >= 0 )
440  aMPS.nTopMargin = nValue;
441  nValue = xController->getIntProperty( "NUpPageMarginBottom", aMPS.nBottomMargin );
442  if( nValue >= 0 )
443  aMPS.nBottomMargin = nValue;
444  nValue = xController->getIntProperty( "NUpHorizontalSpacing", aMPS.nHorizontalSpacing );
445  if( nValue >= 0 )
446  aMPS.nHorizontalSpacing = nValue;
447  nValue = xController->getIntProperty( "NUpVerticalSpacing", aMPS.nVerticalSpacing );
448  if( nValue >= 0 )
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) )
456  {
457  aMPS.aPaperSize.setWidth( aSizeVal.Width );
458  aMPS.aPaperSize.setHeight( aSizeVal.Height );
459  }
460 
461  xController->setMultipage( aMPS );
462  }
463 
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() )
467  {
468  if( xController->getFilteredPageCount() == 0 )
469  {
470  VclPtr<vcl::Window> xParent = xController->getWindow();
471  std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(xParent ? xParent->GetFrameWeld() : nullptr, "vcl/ui/errornocontentdialog.ui"));
472  std::unique_ptr<weld::MessageDialog> xBox(xBuilder->weld_message_dialog("ErrorNoContentDialog"));
473  xBox->run();
474  return false;
475  }
476  }
477 
478  // check if the printer brings up its own dialog
479  // in that case leave the work to that dialog
480  if( ! xController->getPrinter()->GetCapabilities( PrinterCapType::ExternalDialog ) &&
481  ! xController->isDirectPrint() &&
482  xController->isShowDialogs()
483  )
484  {
485  try
486  {
487  VclPtr<vcl::Window> xParent = xController->getWindow();
488  ScopedVclPtrInstance< PrintDialog > aDlg( xParent, xController );
489  if( ! aDlg->Execute() )
490  {
491  xController->abortJob();
492  return false;
493  }
494  if( aDlg->isPrintToFile() )
495  {
496  OUString aFile = queryFile( xController->getPrinter().get() );
497  if( aFile.isEmpty() )
498  {
499  xController->abortJob();
500  return false;
501  }
502  xController->setValue( "LocalFileName",
503  css::uno::makeAny( aFile ) );
504  }
505  else if( aDlg->isSingleJobs() )
506  {
507  xController->setValue( "PrintCollateAsSingleJobs",
508  css::uno::makeAny( true ) );
509  }
510  }
511  catch (const std::bad_alloc&)
512  {
513  }
514  }
515 
516  xController->pushPropertiesToPrinter();
517  return true;
518 }
519 
520 bool Printer::ExecutePrintJob(const std::shared_ptr<PrinterController>& xController)
521 {
522  OUString aJobName;
523  css::beans::PropertyValue* pJobNameVal = xController->getValue( "JobName" );
524  if( pJobNameVal )
525  pJobNameVal->Value >>= aJobName;
526 
527  return xController->getPrinter()->StartJob( aJobName, xController );
528 }
529 
530 void Printer::FinishPrintJob(const std::shared_ptr<PrinterController>& xController)
531 {
532  xController->resetPaperToLastConfigured();
533  xController->jobFinished( xController->getJobState() );
534 }
535 
536 void Printer::ImplPrintJob(const std::shared_ptr<PrinterController>& xController,
537  const JobSetup& i_rInitSetup)
538 {
539  if (PreparePrintJob(xController, i_rInitSetup))
540  {
541  ExecutePrintJob(xController);
542  }
543  FinishPrintJob(xController);
544 }
545 
546 bool Printer::StartJob( const OUString& i_rJobName, std::shared_ptr<vcl::PrinterController> const & i_xController)
547 {
548  mnError = ERRCODE_NONE;
549 
550  if ( IsDisplayPrinter() )
551  return false;
552 
553  if ( IsJobActive() || IsPrinting() )
554  return false;
555 
556  sal_uInt32 nCopies = mnCopyCount;
557  bool bCollateCopy = mbCollateCopy;
558  bool bUserCopy = false;
559 
560  if ( nCopies > 1 )
561  {
562  const sal_uInt32 nDevCopy = GetCapabilities( bCollateCopy
565 
566  // need to do copies by hand ?
567  if ( nCopies > nDevCopy )
568  {
569  bUserCopy = true;
570  nCopies = 1;
571  bCollateCopy = false;
572  }
573  }
574  else
575  bCollateCopy = false;
576 
577  ImplSVData* pSVData = ImplGetSVData();
578  mpPrinter = pSVData->mpDefInst->CreatePrinter( mpInfoPrinter );
579 
580  if (!mpPrinter)
581  return false;
582 
583  bool bSinglePrintJobs = false;
584  css::beans::PropertyValue* pSingleValue = i_xController->getValue("PrintCollateAsSingleJobs");
585  if( pSingleValue )
586  {
587  pSingleValue->Value >>= bSinglePrintJobs;
588  }
589 
590  css::beans::PropertyValue* pFileValue = i_xController->getValue("LocalFileName");
591  if( pFileValue )
592  {
593  OUString aFile;
594  pFileValue->Value >>= aFile;
595  if( !aFile.isEmpty() )
596  {
597  mbPrintFile = true;
598  maPrintFile = aFile;
599  bSinglePrintJobs = false;
600  }
601  }
602 
603  OUString* pPrintFile = nullptr;
604  if ( mbPrintFile )
605  pPrintFile = &maPrintFile;
606  mpPrinterOptions->ReadFromConfig( mbPrintFile );
607 
608  mbPrinting = true;
609  if( GetCapabilities( PrinterCapType::UsePullModel ) )
610  {
611  mbJobActive = true;
612  // SAL layer does all necessary page printing
613  // and also handles showing a dialog
614  // that also means it must call jobStarted when the dialog is finished
615  // it also must set the JobState of the Controller
616  if( mpPrinter->StartJob( pPrintFile,
617  i_rJobName,
619  &maJobSetup.ImplGetData(),
620  *i_xController) )
621  {
622  EndJob();
623  }
624  else
625  {
626  mnError = ImplSalPrinterErrorCodeToVCL(mpPrinter->GetErrorCode());
627  if ( !mnError )
628  mnError = PRINTER_GENERALERROR;
629  mbPrinting = false;
630  mpPrinter.reset();
631  mbJobActive = false;
632 
633  GDIMetaFile aDummyFile;
634  i_xController->setLastPage(true);
635  i_xController->getFilteredPageFile(0, aDummyFile);
636 
637  return false;
638  }
639  }
640  else
641  {
642  // possibly a dialog has been shown
643  // now the real job starts
644  i_xController->setJobState( css::view::PrintableState_JOB_STARTED );
645  i_xController->jobStarted();
646 
647  int nJobs = 1;
648  int nOuterRepeatCount = 1;
649  int nInnerRepeatCount = 1;
650  if( bUserCopy )
651  {
652  if( mbCollateCopy )
653  nOuterRepeatCount = mnCopyCount;
654  else
655  nInnerRepeatCount = mnCopyCount;
656  }
657  if( bSinglePrintJobs )
658  {
659  nJobs = mnCopyCount;
660  nCopies = 1;
661  nOuterRepeatCount = nInnerRepeatCount = 1;
662  }
663 
664  for( int nJobIteration = 0; nJobIteration < nJobs; nJobIteration++ )
665  {
666  bool bError = false;
667  if( mpPrinter->StartJob( pPrintFile,
668  i_rJobName,
670  nCopies,
671  bCollateCopy,
672  i_xController->isDirectPrint(),
673  &maJobSetup.ImplGetData() ) )
674  {
675  bool bAborted = false;
676  mbJobActive = true;
677  i_xController->createProgressDialog();
678  const int nPages = i_xController->getFilteredPageCount();
679  // abort job, if no pages will be printed.
680  if ( nPages == 0 )
681  {
682  i_xController->abortJob();
683  bAborted = true;
684  }
685  for( int nOuterIteration = 0; nOuterIteration < nOuterRepeatCount && ! bAborted; nOuterIteration++ )
686  {
687  for( int nPage = 0; nPage < nPages && ! bAborted; nPage++ )
688  {
689  for( int nInnerIteration = 0; nInnerIteration < nInnerRepeatCount && ! bAborted; nInnerIteration++ )
690  {
691  if( nPage == nPages-1 &&
692  nOuterIteration == nOuterRepeatCount-1 &&
693  nInnerIteration == nInnerRepeatCount-1 &&
694  nJobIteration == nJobs-1 )
695  {
696  i_xController->setLastPage(true);
697  }
698  i_xController->printFilteredPage(nPage);
699  if (i_xController->isProgressCanceled())
700  {
701  i_xController->abortJob();
702  }
703  if (i_xController->getJobState() ==
704  css::view::PrintableState_JOB_ABORTED)
705  {
706  bAborted = true;
707  }
708  }
709  }
710  // FIXME: duplex ?
711  }
712  EndJob();
713 
714  if( nJobIteration < nJobs-1 )
715  {
716  mpPrinter = pSVData->mpDefInst->CreatePrinter( mpInfoPrinter );
717 
718  if ( mpPrinter )
719  mbPrinting = true;
720  else
721  bError = true;
722  }
723  }
724  else
725  bError = true;
726 
727  if( bError )
728  {
729  mnError = mpPrinter ? ImplSalPrinterErrorCodeToVCL(mpPrinter->GetErrorCode()) : ERRCODE_NONE;
730  if ( !mnError )
731  mnError = PRINTER_GENERALERROR;
732  i_xController->setJobState( mnError == PRINTER_ABORT
733  ? css::view::PrintableState_JOB_ABORTED
734  : css::view::PrintableState_JOB_FAILED );
735  mbPrinting = false;
736  mpPrinter.reset();
737 
738  return false;
739  }
740  }
741 
742  if (i_xController->getJobState() == css::view::PrintableState_JOB_STARTED)
743  i_xController->setJobState(css::view::PrintableState_JOB_SPOOLED);
744  }
745 
746  // make last used printer persistent for UI jobs
747  if (i_xController->isShowDialogs() && !i_xController->isDirectPrint())
748  {
750  pItem->setValue( "PrintDialog",
751  "LastPrinterUsed",
752  GetName()
753  );
754  }
755 
756  return true;
757 }
758 
760 {
761 }
762 
763 css::view::PrintableState PrinterController::getJobState() const
764 {
765  return mpImplData->meJobState;
766 }
767 
768 void PrinterController::setJobState( css::view::PrintableState i_eState )
769 {
770  mpImplData->meJobState = i_eState;
771 }
772 
774 {
775  return mpImplData->mxPrinter;
776 }
777 
779 {
780  return mpImplData->mxWindow;
781 }
782 
784 {
785  mpImplData->mxPrinter = i_rPrinter;
786  setValue( "Name",
787  css::uno::makeAny( i_rPrinter->GetName() ) );
788  mpImplData->mnDefaultPaperBin = mpImplData->mxPrinter->GetPaperBin();
789  mpImplData->mxPrinter->Push();
790  mpImplData->mxPrinter->SetMapMode(MapMode(MapUnit::Map100thMM));
791  mpImplData->maDefaultPageSize = mpImplData->mxPrinter->GetPaperSize();
792  mpImplData->mbPapersizeFromUser = false;
793  mpImplData->mxPrinter->Pop();
794  mpImplData->mnFixedPaperBin = -1;
795 }
796 
797 void PrinterController::resetPrinterOptions( bool i_bFileOutput )
798 {
799  PrinterOptions aOpt;
800  aOpt.ReadFromConfig( i_bFileOutput );
801  mpImplData->mxPrinter->SetPrinterOptions( aOpt );
802 }
803 
805 {
806  bool bRet = false;
807 
808  // Important to hold printer alive while doing setup etc.
809  VclPtr< Printer > xPrinter = mpImplData->mxPrinter;
810 
811  if( xPrinter.get() )
812  {
813  xPrinter->Push();
814  xPrinter->SetMapMode(MapMode(MapUnit::Map100thMM));
815 
816  // get current data
817  Size aPaperSize(xPrinter->GetPaperSize());
818  Orientation eOrientation = xPrinter->GetOrientation();
819  sal_uInt16 nPaperBin = xPrinter->GetPaperBin();
820 
821  // reset paper size back to last configured size, not
822  // whatever happens to be the current page
823  // (but only if the printer config has changed, otherwise
824  // don't override printer page auto-detection - tdf#91362)
826  {
828  }
829 
830  // call driver setup
831  bRet = xPrinter->Setup( i_pParent, PrinterSetupMode::SingleJob );
832  SAL_WARN_IF(xPrinter != mpImplData->mxPrinter, "vcl.gdi",
833  "Printer changed underneath us during setup");
834  xPrinter = mpImplData->mxPrinter;
835 
836  Size aNewPaperSize(xPrinter->GetPaperSize());
837  if (bRet)
838  {
839  bool bInvalidateCache = false;
841 
842  // was papersize overridden ? if so we need to take action if we're
843  // configured to use the driver papersize
844  if (aNewPaperSize != mpImplData->maDefaultPageSize)
845  {
846  mpImplData->maDefaultPageSize = aNewPaperSize;
847  bInvalidateCache = getPapersizeFromSetup();
848  }
849 
850  // was bin overridden ? if so we need to take action
851  sal_uInt16 nNewPaperBin = xPrinter->GetPaperBin();
852  if (nNewPaperBin != nPaperBin)
853  {
854  mpImplData->mnFixedPaperBin = nNewPaperBin;
855  bInvalidateCache = true;
856  }
857 
858  if (bInvalidateCache)
859  {
860  mpImplData->maPageCache.invalidate();
861  }
862  }
863  else
864  {
865  //restore to whatever it was before we entered this method
866  xPrinter->SetOrientation( eOrientation );
867  if (aPaperSize != aNewPaperSize)
868  xPrinter->SetPaperSizeUser(aPaperSize, !mpImplData->isFixedPageSize());
869  }
870  xPrinter->Pop();
871  }
872 }
873 
874 PrinterController::PageSize vcl::ImplPrinterControllerData::modifyJobSetup( const css::uno::Sequence< css::beans::PropertyValue >& i_rProps )
875 {
876  PrinterController::PageSize aPageSize;
877  aPageSize.aSize = mxPrinter->GetPaperSize();
878  css::awt::Size aSetSize, aIsSize;
879  sal_Int32 nPaperBin = mnDefaultPaperBin;
880  for( const auto& rProp : i_rProps )
881  {
882  if ( rProp.Name == "PreferredPageSize" )
883  {
884  rProp.Value >>= aSetSize;
885  }
886  else if ( rProp.Name == "PageSize" )
887  {
888  rProp.Value >>= aIsSize;
889  }
890  else if ( rProp.Name == "PageIncludesNonprintableArea" )
891  {
892  bool bVal = false;
893  rProp.Value >>= bVal;
894  aPageSize.bFullPaper = bVal;
895  }
896  else if ( rProp.Name == "PrinterPaperTray" )
897  {
898  sal_Int32 nBin = -1;
899  rProp.Value >>= nBin;
900  if( nBin >= 0 && nBin < static_cast<sal_Int32>(mxPrinter->GetPaperBinCount()) )
901  nPaperBin = nBin;
902  }
903  }
904 
905  Size aCurSize( mxPrinter->GetPaperSize() );
906  if( aSetSize.Width && aSetSize.Height )
907  {
908  Size aSetPaperSize( aSetSize.Width, aSetSize.Height );
909  Size aRealPaperSize( getRealPaperSize( aSetPaperSize, true/*bNoNUP*/ ) );
910  if( aRealPaperSize != aCurSize )
911  aIsSize = aSetSize;
912  }
913 
914  if( aIsSize.Width && aIsSize.Height )
915  {
916  aPageSize.aSize.setWidth( aIsSize.Width );
917  aPageSize.aSize.setHeight( aIsSize.Height );
918 
919  Size aRealPaperSize( getRealPaperSize( aPageSize.aSize, true/*bNoNUP*/ ) );
920  if( aRealPaperSize != aCurSize )
921  mxPrinter->SetPaperSizeUser( aRealPaperSize, ! isFixedPageSize() );
922  }
923 
924  // paper bin set from properties in print dialog overrides
925  // application default for a page
926  if ( mnFixedPaperBin != -1 )
927  nPaperBin = mnFixedPaperBin;
928 
929  if( nPaperBin != -1 && nPaperBin != mxPrinter->GetPaperBin() )
930  mxPrinter->SetPaperBin( nPaperBin );
931 
932  return aPageSize;
933 }
934 
935 //fdo#61886
936 
937 //when printing is finished, set the paper size of the printer to either what
938 //the user explicitly set as the desired paper size, or fallback to whatever
939 //the printer had before printing started. That way it doesn't contain the last
940 //paper size of a multiple paper size using document when we are in our normal
941 //auto accept document paper size mode and end up overwriting the original
942 //paper size setting for file->printer_settings just by pressing "ok" in the
943 //print dialog
945 {
946  mxPrinter->Push();
947  mxPrinter->SetMapMode(MapMode(MapUnit::Map100thMM));
948  Size aCurSize(mxPrinter->GetPaperSize());
949  if (aCurSize != maDefaultPageSize)
950  mxPrinter->SetPaperSizeUser(maDefaultPageSize, !isFixedPageSize());
951  mxPrinter->Pop();
952 }
953 
955 {
956  const MapMode aMapMode( MapUnit::Map100thMM );
957 
958  mpImplData->mxPrinter->Push();
959  mpImplData->mxPrinter->SetMapMode( aMapMode );
960  int nPages = getPageCount();
961  mpImplData->mxPrinter->Pop();
962  return nPages;
963 }
964 
965 css::uno::Sequence< css::beans::PropertyValue > PrinterController::getPageParametersProtected( int i_nPage ) const
966 {
967  const MapMode aMapMode( MapUnit::Map100thMM );
968 
969  mpImplData->mxPrinter->Push();
970  mpImplData->mxPrinter->SetMapMode( aMapMode );
971  css::uno::Sequence< css::beans::PropertyValue > aResult( getPageParameters( i_nPage ) );
972  mpImplData->mxPrinter->Pop();
973  return aResult;
974 }
975 
976 PrinterController::PageSize PrinterController::getPageFile( int i_nUnfilteredPage, GDIMetaFile& o_rMtf, bool i_bMayUseCache )
977 {
978  // update progress if necessary
979  if( mpImplData->mxProgress )
980  {
981  // do nothing if printing is canceled
982  if( mpImplData->mxProgress->isCanceled() )
984  mpImplData->mxProgress->tick();
985  Application::Reschedule( true );
986  }
987 
988  if( i_bMayUseCache )
989  {
990  PrinterController::PageSize aPageSize;
991  if( mpImplData->maPageCache.get( i_nUnfilteredPage, o_rMtf, aPageSize ) )
992  {
993  return aPageSize;
994  }
995  }
996  else
997  mpImplData->maPageCache.invalidate();
998 
999  o_rMtf.Clear();
1000 
1001  // get page parameters
1002  css::uno::Sequence< css::beans::PropertyValue > aPageParm( getPageParametersProtected( i_nUnfilteredPage ) );
1003  const MapMode aMapMode( MapUnit::Map100thMM );
1004 
1005  mpImplData->mxPrinter->Push();
1006  mpImplData->mxPrinter->SetMapMode( aMapMode );
1007 
1008  // modify job setup if necessary
1009  PrinterController::PageSize aPageSize = mpImplData->modifyJobSetup( aPageParm );
1010 
1011  o_rMtf.SetPrefSize( aPageSize.aSize );
1012  o_rMtf.SetPrefMapMode( aMapMode );
1013 
1014  mpImplData->mxPrinter->EnableOutput( false );
1015 
1016  o_rMtf.Record( mpImplData->mxPrinter.get() );
1017 
1018  printPage( i_nUnfilteredPage );
1019 
1020  o_rMtf.Stop();
1021  o_rMtf.WindStart();
1022  mpImplData->mxPrinter->Pop();
1023 
1024  if( i_bMayUseCache )
1025  mpImplData->maPageCache.insert( i_nUnfilteredPage, o_rMtf, aPageSize );
1026 
1027  // reset "FirstPage" property to false now we've gotten at least our first one
1028  mpImplData->mbFirstPage = false;
1029 
1030  return aPageSize;
1031 }
1032 
1033 static void appendSubPage( GDIMetaFile& o_rMtf, const tools::Rectangle& i_rClipRect, GDIMetaFile& io_rSubPage, bool i_bDrawBorder )
1034 {
1035  // intersect all clipregion actions with our clip rect
1036  io_rSubPage.WindStart();
1037  io_rSubPage.Clip( i_rClipRect );
1038 
1039  // save gstate
1040  o_rMtf.AddAction( new MetaPushAction( PushFlags::ALL ) );
1041 
1042  // clip to page rect
1043  o_rMtf.AddAction( new MetaClipRegionAction( vcl::Region( i_rClipRect ), true ) );
1044 
1045  // append the subpage
1046  io_rSubPage.WindStart();
1047  io_rSubPage.Play( o_rMtf );
1048 
1049  // restore gstate
1050  o_rMtf.AddAction( new MetaPopAction() );
1051 
1052  // draw a border
1053  if( i_bDrawBorder )
1054  {
1055  // save gstate
1057  o_rMtf.AddAction( new MetaMapModeAction( MapMode( MapUnit::Map100thMM ) ) );
1058 
1059  tools::Rectangle aBorderRect( i_rClipRect );
1060  o_rMtf.AddAction( new MetaLineColorAction( COL_BLACK, true ) );
1061  o_rMtf.AddAction( new MetaFillColorAction( COL_TRANSPARENT, false ) );
1062  o_rMtf.AddAction( new MetaRectAction( aBorderRect ) );
1063 
1064  // restore gstate
1065  o_rMtf.AddAction( new MetaPopAction() );
1066  }
1067 }
1068 
1069 PrinterController::PageSize PrinterController::getFilteredPageFile( int i_nFilteredPage, GDIMetaFile& o_rMtf, bool i_bMayUseCache )
1070 {
1071  const MultiPageSetup& rMPS( mpImplData->maMultiPage );
1072  int nSubPages = rMPS.nRows * rMPS.nColumns;
1073  if( nSubPages < 1 )
1074  nSubPages = 1;
1075 
1076  // reverse sheet order
1077  if( mpImplData->mbReversePageOrder )
1078  {
1079  int nDocPages = getFilteredPageCount();
1080  i_nFilteredPage = nDocPages - 1 - i_nFilteredPage;
1081  }
1082 
1083  // there is no filtering to be done (and possibly the page size of the
1084  // original page is to be set), when N-Up is "neutral" that is there is
1085  // only one subpage and the margins are 0
1086  if( nSubPages == 1 &&
1087  rMPS.nLeftMargin == 0 && rMPS.nRightMargin == 0 &&
1088  rMPS.nTopMargin == 0 && rMPS.nBottomMargin == 0 )
1089  {
1090  PrinterController::PageSize aPageSize = getPageFile( i_nFilteredPage, o_rMtf, i_bMayUseCache );
1091  if (mpImplData->meJobState != css::view::PrintableState_JOB_STARTED)
1092  { // rhbz#657394: check that we are still printing...
1093  return PrinterController::PageSize();
1094  }
1095  Size aPaperSize = mpImplData->getRealPaperSize( aPageSize.aSize, true );
1096  mpImplData->mxPrinter->SetMapMode( MapMode( MapUnit::Map100thMM ) );
1097  mpImplData->mxPrinter->SetPaperSizeUser( aPaperSize, ! mpImplData->isFixedPageSize() );
1098  if( aPaperSize != aPageSize.aSize )
1099  {
1100  // user overridden page size, center Metafile
1101  o_rMtf.WindStart();
1102  long nDX = (aPaperSize.Width() - aPageSize.aSize.Width()) / 2;
1103  long nDY = (aPaperSize.Height() - aPageSize.aSize.Height()) / 2;
1104  o_rMtf.Move( nDX, nDY, mpImplData->mxPrinter->GetDPIX(), mpImplData->mxPrinter->GetDPIY() );
1105  o_rMtf.WindStart();
1106  o_rMtf.SetPrefSize( aPaperSize );
1107  aPageSize.aSize = aPaperSize;
1108  }
1109  return aPageSize;
1110  }
1111 
1112  // set last page property really only on the very last page to be rendered
1113  // that is on the last subpage of a NUp run
1114  bool bIsLastPage = mpImplData->mbLastPage;
1115  mpImplData->mbLastPage = false;
1116 
1117  Size aPaperSize( mpImplData->getRealPaperSize( mpImplData->maMultiPage.aPaperSize, false ) );
1118 
1119  // multi page area: page size minus margins + one time spacing right and down
1120  // the added spacing is so each subpage can be calculated including its spacing
1121  Size aMPArea( aPaperSize );
1122  aMPArea.AdjustWidth( -(rMPS.nLeftMargin + rMPS.nRightMargin) );
1123  aMPArea.AdjustWidth(rMPS.nHorizontalSpacing );
1124  aMPArea.AdjustHeight( -(rMPS.nTopMargin + rMPS.nBottomMargin) );
1125  aMPArea.AdjustHeight(rMPS.nVerticalSpacing );
1126 
1127  // determine offsets
1128  long nAdvX = aMPArea.Width() / rMPS.nColumns;
1129  long nAdvY = aMPArea.Height() / rMPS.nRows;
1130 
1131  // determine size of a "cell" subpage, leave a little space around pages
1132  Size aSubPageSize( nAdvX - rMPS.nHorizontalSpacing, nAdvY - rMPS.nVerticalSpacing );
1133 
1134  o_rMtf.Clear();
1135  o_rMtf.SetPrefSize( aPaperSize );
1136  o_rMtf.SetPrefMapMode( MapMode( MapUnit::Map100thMM ) );
1137  o_rMtf.AddAction( new MetaMapModeAction( MapMode( MapUnit::Map100thMM ) ) );
1138 
1139  int nDocPages = getPageCountProtected();
1140  if (mpImplData->meJobState != css::view::PrintableState_JOB_STARTED)
1141  { // rhbz#657394: check that we are still printing...
1142  return PrinterController::PageSize();
1143  }
1144  for( int nSubPage = 0; nSubPage < nSubPages; nSubPage++ )
1145  {
1146  // map current sub page to real page
1147  int nPage = i_nFilteredPage * nSubPages + nSubPage;
1148  if( nSubPage == nSubPages-1 ||
1149  nPage == nDocPages-1 )
1150  {
1151  mpImplData->mbLastPage = bIsLastPage;
1152  }
1153  if( nPage >= 0 && nPage < nDocPages )
1154  {
1155  GDIMetaFile aPageFile;
1156  PrinterController::PageSize aPageSize = getPageFile( nPage, aPageFile, i_bMayUseCache );
1157  if( aPageSize.aSize.Width() && aPageSize.aSize.Height() )
1158  {
1159  long nCellX = 0, nCellY = 0;
1160  switch( rMPS.nOrder )
1161  {
1162  case NupOrderType::LRTB:
1163  nCellX = (nSubPage % rMPS.nColumns);
1164  nCellY = (nSubPage / rMPS.nColumns);
1165  break;
1166  case NupOrderType::TBLR:
1167  nCellX = (nSubPage / rMPS.nRows);
1168  nCellY = (nSubPage % rMPS.nRows);
1169  break;
1170  case NupOrderType::RLTB:
1171  nCellX = rMPS.nColumns - 1 - (nSubPage % rMPS.nColumns);
1172  nCellY = (nSubPage / rMPS.nColumns);
1173  break;
1174  case NupOrderType::TBRL:
1175  nCellX = rMPS.nColumns - 1 - (nSubPage / rMPS.nRows);
1176  nCellY = (nSubPage % rMPS.nRows);
1177  break;
1178  }
1179  // scale the metafile down to a sub page size
1180  double fScaleX = double(aSubPageSize.Width())/double(aPageSize.aSize.Width());
1181  double fScaleY = double(aSubPageSize.Height())/double(aPageSize.aSize.Height());
1182  double fScale = std::min( fScaleX, fScaleY );
1183  aPageFile.Scale( fScale, fScale );
1184  aPageFile.WindStart();
1185 
1186  // move the subpage so it is centered in its "cell"
1187  long nOffX = (aSubPageSize.Width() - long(double(aPageSize.aSize.Width()) * fScale)) / 2;
1188  long nOffY = (aSubPageSize.Height() - long(double(aPageSize.aSize.Height()) * fScale)) / 2;
1189  long nX = rMPS.nLeftMargin + nOffX + nAdvX * nCellX;
1190  long nY = rMPS.nTopMargin + nOffY + nAdvY * nCellY;
1191  aPageFile.Move( nX, nY, mpImplData->mxPrinter->GetDPIX(), mpImplData->mxPrinter->GetDPIY() );
1192  aPageFile.WindStart();
1193  // calculate border rectangle
1194  tools::Rectangle aSubPageRect( Point( nX, nY ),
1195  Size( long(double(aPageSize.aSize.Width())*fScale),
1196  long(double(aPageSize.aSize.Height())*fScale) ) );
1197 
1198  // append subpage to page
1199  appendSubPage( o_rMtf, aSubPageRect, aPageFile, rMPS.bDrawBorder );
1200  }
1201  }
1202  }
1203  o_rMtf.WindStart();
1204 
1205  // subsequent getPageFile calls have changed the paper, reset it to current value
1206  mpImplData->mxPrinter->SetMapMode( MapMode( MapUnit::Map100thMM ) );
1207  mpImplData->mxPrinter->SetPaperSizeUser( aPaperSize, ! mpImplData->isFixedPageSize() );
1208 
1209  return PrinterController::PageSize( aPaperSize, true );
1210 }
1211 
1213 {
1214  int nDiv = mpImplData->maMultiPage.nRows * mpImplData->maMultiPage.nColumns;
1215  if( nDiv < 1 )
1216  nDiv = 1;
1217  return (getPageCountProtected() + (nDiv-1)) / nDiv;
1218 }
1219 
1221 {
1222  DrawModeFlags nRestoreDrawMode = mpImplData->mxPrinter->GetDrawMode();
1223  sal_Int32 nMaxBmpDPIX = mpImplData->mxPrinter->GetDPIX();
1224  sal_Int32 nMaxBmpDPIY = mpImplData->mxPrinter->GetDPIY();
1225 
1226  const PrinterOptions& rPrinterOptions = mpImplData->mxPrinter->GetPrinterOptions();
1227 
1228  static const sal_Int32 OPTIMAL_BMP_RESOLUTION = 300;
1229  static const sal_Int32 NORMAL_BMP_RESOLUTION = 200;
1230 
1231  if( rPrinterOptions.IsReduceBitmaps() )
1232  {
1233  // calculate maximum resolution for bitmap graphics
1234  if( PrinterBitmapMode::Optimal == rPrinterOptions.GetReducedBitmapMode() )
1235  {
1236  nMaxBmpDPIX = std::min( sal_Int32(OPTIMAL_BMP_RESOLUTION), nMaxBmpDPIX );
1237  nMaxBmpDPIY = std::min( sal_Int32(OPTIMAL_BMP_RESOLUTION), nMaxBmpDPIY );
1238  }
1239  else if( PrinterBitmapMode::Normal == rPrinterOptions.GetReducedBitmapMode() )
1240  {
1241  nMaxBmpDPIX = std::min( sal_Int32(NORMAL_BMP_RESOLUTION), nMaxBmpDPIX );
1242  nMaxBmpDPIY = std::min( sal_Int32(NORMAL_BMP_RESOLUTION), nMaxBmpDPIY );
1243  }
1244  else
1245  {
1246  nMaxBmpDPIX = std::min( sal_Int32(rPrinterOptions.GetReducedBitmapResolution()), nMaxBmpDPIX );
1247  nMaxBmpDPIY = std::min( sal_Int32(rPrinterOptions.GetReducedBitmapResolution()), nMaxBmpDPIY );
1248  }
1249  }
1250 
1251  // convert to greyscales
1252  if( rPrinterOptions.IsConvertToGreyscales() )
1253  {
1254  mpImplData->mxPrinter->SetDrawMode( mpImplData->mxPrinter->GetDrawMode() |
1257  }
1258 
1259  // disable transparency output
1260  if( rPrinterOptions.IsReduceTransparency() && ( PrinterTransparencyMode::NONE == rPrinterOptions.GetReducedTransparencyMode() ) )
1261  {
1262  mpImplData->mxPrinter->SetDrawMode( mpImplData->mxPrinter->GetDrawMode() | DrawModeFlags::NoTransparency );
1263  }
1264 
1265  Color aBg( COL_TRANSPARENT ); // default: let RemoveTransparenciesFromMetaFile do its own background logic
1266  if( mpImplData->maMultiPage.nRows * mpImplData->maMultiPage.nColumns > 1 )
1267  {
1268  // in N-Up printing we have no "page" background operation
1269  // we also have no way to determine the paper color
1270  // so let's go for white, which will kill 99.9% of the real cases
1271  aBg = COL_WHITE;
1272  }
1273  mpImplData->mxPrinter->RemoveTransparenciesFromMetaFile( i_rIn, o_rOut, nMaxBmpDPIX, nMaxBmpDPIY,
1274  rPrinterOptions.IsReduceTransparency(),
1276  rPrinterOptions.IsReduceBitmaps() && rPrinterOptions.IsReducedBitmapIncludesTransparency(),
1277  aBg
1278  );
1279  return nRestoreDrawMode;
1280 }
1281 
1283 {
1284  if( mpImplData->meJobState != css::view::PrintableState_JOB_STARTED )
1285  return; // rhbz#657394: check that we are still printing...
1286 
1287  GDIMetaFile aPageFile;
1288  PrinterController::PageSize aPageSize = getFilteredPageFile( i_nPage, aPageFile );
1289 
1290  if( mpImplData->mxProgress )
1291  {
1292  // do nothing if printing is canceled
1293  if( mpImplData->mxProgress->isCanceled() )
1294  {
1295  setJobState( css::view::PrintableState_JOB_ABORTED );
1296  return;
1297  }
1298  }
1299 
1300  // in N-Up printing set the correct page size
1301  mpImplData->mxPrinter->SetMapMode(MapMode(MapUnit::Map100thMM));
1302  // aPageSize was filtered through mpImplData->getRealPaperSize already by getFilteredPageFile()
1303  mpImplData->mxPrinter->SetPaperSizeUser( aPageSize.aSize, ! mpImplData->isFixedPageSize() );
1304  if( mpImplData->mnFixedPaperBin != -1 &&
1305  mpImplData->mxPrinter->GetPaperBin() != mpImplData->mnFixedPaperBin )
1306  {
1307  mpImplData->mxPrinter->SetPaperBin( mpImplData->mnFixedPaperBin );
1308  }
1309 
1310  // if full paper is meant to be used, move the output to accommodate for pageoffset
1311  if( aPageSize.bFullPaper )
1312  {
1313  Point aPageOffset( mpImplData->mxPrinter->GetPageOffset() );
1314  aPageFile.WindStart();
1315  aPageFile.Move( -aPageOffset.X(), -aPageOffset.Y(), mpImplData->mxPrinter->GetDPIX(), mpImplData->mxPrinter->GetDPIY() );
1316  }
1317 
1318  GDIMetaFile aCleanedFile;
1319  DrawModeFlags nRestoreDrawMode = removeTransparencies( aPageFile, aCleanedFile );
1320 
1321  mpImplData->mxPrinter->EnableOutput();
1322 
1323  // actually print the page
1324  mpImplData->mxPrinter->ImplStartPage();
1325 
1326  mpImplData->mxPrinter->Push();
1327  aCleanedFile.WindStart();
1328  aCleanedFile.Play( mpImplData->mxPrinter.get() );
1329  mpImplData->mxPrinter->Pop();
1330 
1331  mpImplData->mxPrinter->ImplEndPage();
1332 
1333  mpImplData->mxPrinter->SetDrawMode( nRestoreDrawMode );
1334 }
1335 
1337 {
1338 }
1339 
1340 void PrinterController::jobFinished( css::view::PrintableState )
1341 {
1342 }
1343 
1345 {
1346  setJobState( css::view::PrintableState_JOB_ABORTED );
1347  // applications (well, sw) depend on a page request with "IsLastPage" = true
1348  // to free resources, else they (well, sw) will crash eventually
1349  setLastPage( true );
1350 
1351  if (mpImplData->mxProgress)
1352  {
1353  mpImplData->mxProgress->response(RET_CANCEL);
1354  mpImplData->mxProgress.reset();
1355  }
1356 
1357  GDIMetaFile aMtf;
1358  getPageFile( 0, aMtf );
1359 }
1360 
1361 void PrinterController::setLastPage( bool i_bLastPage )
1362 {
1363  mpImplData->mbLastPage = i_bLastPage;
1364 }
1365 
1366 void PrinterController::setReversePrint( bool i_bReverse )
1367 {
1368  mpImplData->mbReversePageOrder = i_bReverse;
1369 }
1370 
1371 void PrinterController::setPapersizeFromSetup( bool i_bPapersizeFromSetup )
1372 {
1373  mpImplData->mbPapersizeFromSetup = i_bPapersizeFromSetup;
1374  mpImplData->mxPrinter->SetPrinterSettingsPreferred( i_bPapersizeFromSetup );
1375  if ( i_bPapersizeFromSetup )
1376  mpImplData->mbPapersizeFromUser = !i_bPapersizeFromSetup;
1377 }
1378 
1380 {
1381  return mpImplData->mbPapersizeFromSetup;
1382 }
1383 
1385 {
1386  return mpImplData->maDefaultPageSize;
1387 }
1388 
1390 {
1391  mpImplData->mbPapersizeFromUser = true;
1392  mpImplData->mbPapersizeFromSetup = false;
1393  mpImplData->mxPrinter->SetPrinterSettingsPreferred( false );
1394 
1395  mpImplData->maUserPageSize = i_aUserSize;
1396 }
1397 
1399 {
1400  return mpImplData->maUserPageSize;
1401 }
1402 
1404 {
1405  return mpImplData->mbPapersizeFromUser;
1406 }
1407 
1408 void PrinterController::setPrinterModified( bool i_bPrinterModified )
1409 {
1410  mpImplData->mbPrinterModified = i_bPrinterModified;
1411 }
1412 
1414 {
1415  return mpImplData->mbPrinterModified;
1416 }
1417 
1418 css::uno::Sequence< css::beans::PropertyValue > PrinterController::getJobProperties( const css::uno::Sequence< css::beans::PropertyValue >& i_rMergeList ) const
1419 {
1420  std::unordered_set< OUString > aMergeSet;
1421  size_t nResultLen = size_t(i_rMergeList.getLength()) + mpImplData->maUIProperties.size() + 3;
1422  for( const auto& rPropVal : i_rMergeList )
1423  aMergeSet.insert( rPropVal.Name );
1424 
1425  css::uno::Sequence< css::beans::PropertyValue > aResult( nResultLen );
1426  std::copy(i_rMergeList.begin(), i_rMergeList.end(), aResult.begin());
1427  int nCur = i_rMergeList.getLength();
1428  for(const css::beans::PropertyValue & rPropVal : mpImplData->maUIProperties)
1429  {
1430  if( aMergeSet.find( rPropVal.Name ) == aMergeSet.end() )
1431  aResult[nCur++] = rPropVal;
1432  }
1433  // append IsFirstPage
1434  if( aMergeSet.find( "IsFirstPage" ) == aMergeSet.end() )
1435  {
1436  css::beans::PropertyValue aVal;
1437  aVal.Name = "IsFirstPage";
1438  aVal.Value <<= mpImplData->mbFirstPage;
1439  aResult[nCur++] = aVal;
1440  }
1441  // append IsLastPage
1442  if( aMergeSet.find( "IsLastPage" ) == aMergeSet.end() )
1443  {
1444  css::beans::PropertyValue aVal;
1445  aVal.Name = "IsLastPage";
1446  aVal.Value <<= mpImplData->mbLastPage;
1447  aResult[nCur++] = aVal;
1448  }
1449  // append IsPrinter
1450  if( aMergeSet.find( "IsPrinter" ) == aMergeSet.end() )
1451  {
1452  css::beans::PropertyValue aVal;
1453  aVal.Name = "IsPrinter";
1454  aVal.Value <<= true;
1455  aResult[nCur++] = aVal;
1456  }
1457  aResult.realloc( nCur );
1458  return aResult;
1459 }
1460 
1461 const css::uno::Sequence< css::beans::PropertyValue >& PrinterController::getUIOptions() const
1462 {
1463  return mpImplData->maUIOptions;
1464 }
1465 
1466 css::beans::PropertyValue* PrinterController::getValue( const OUString& i_rProperty )
1467 {
1468  std::unordered_map< OUString, size_t >::const_iterator it =
1469  mpImplData->maPropertyToIndex.find( i_rProperty );
1470  return it != mpImplData->maPropertyToIndex.end() ? &mpImplData->maUIProperties[it->second] : nullptr;
1471 }
1472 
1473 const css::beans::PropertyValue* PrinterController::getValue( const OUString& i_rProperty ) const
1474 {
1475  std::unordered_map< OUString, size_t >::const_iterator it =
1476  mpImplData->maPropertyToIndex.find( i_rProperty );
1477  return it != mpImplData->maPropertyToIndex.end() ? &mpImplData->maUIProperties[it->second] : nullptr;
1478 }
1479 
1480 void PrinterController::setValue( const OUString& i_rPropertyName, const css::uno::Any& i_rValue )
1481 {
1482  css::beans::PropertyValue aVal;
1483  aVal.Name = i_rPropertyName;
1484  aVal.Value = i_rValue;
1485 
1486  setValue( aVal );
1487 }
1488 
1489 void PrinterController::setValue( const css::beans::PropertyValue& i_rPropertyValue )
1490 {
1491  std::unordered_map< OUString, size_t >::const_iterator it =
1492  mpImplData->maPropertyToIndex.find( i_rPropertyValue.Name );
1493  if( it != mpImplData->maPropertyToIndex.end() )
1494  mpImplData->maUIProperties[ it->second ] = i_rPropertyValue;
1495  else
1496  {
1497  // insert correct index into property map
1498  mpImplData->maPropertyToIndex[ i_rPropertyValue.Name ] = mpImplData->maUIProperties.size();
1499  mpImplData->maUIProperties.push_back( i_rPropertyValue );
1500  mpImplData->maUIPropertyEnabled.push_back( true );
1501  }
1502 }
1503 
1504 void PrinterController::setUIOptions( const css::uno::Sequence< css::beans::PropertyValue >& i_rOptions )
1505 {
1506  SAL_WARN_IF( mpImplData->maUIOptions.hasElements(), "vcl.gdi", "setUIOptions called twice !" );
1507 
1508  mpImplData->maUIOptions = i_rOptions;
1509 
1510  for( const auto& rOpt : i_rOptions )
1511  {
1512  css::uno::Sequence< css::beans::PropertyValue > aOptProp;
1513  rOpt.Value >>= aOptProp;
1514  bool bIsEnabled = true;
1515  bool bHaveProperty = false;
1516  OUString aPropName;
1518  css::uno::Sequence< sal_Bool > aChoicesDisabled;
1519  for( const css::beans::PropertyValue& rEntry : std::as_const(aOptProp) )
1520  {
1521  if ( rEntry.Name == "Property" )
1522  {
1523  css::beans::PropertyValue aVal;
1524  rEntry.Value >>= aVal;
1525  DBG_ASSERT( mpImplData->maPropertyToIndex.find( aVal.Name )
1526  == mpImplData->maPropertyToIndex.end(), "duplicate property entry" );
1527  setValue( aVal );
1528  aPropName = aVal.Name;
1529  bHaveProperty = true;
1530  }
1531  else if ( rEntry.Name == "Enabled" )
1532  {
1533  bool bValue = true;
1534  rEntry.Value >>= bValue;
1535  bIsEnabled = bValue;
1536  }
1537  else if ( rEntry.Name == "DependsOnName" )
1538  {
1539  rEntry.Value >>= aDep.maDependsOnName;
1540  }
1541  else if ( rEntry.Name == "DependsOnEntry" )
1542  {
1543  rEntry.Value >>= aDep.mnDependsOnEntry;
1544  }
1545  else if ( rEntry.Name == "ChoicesDisabled" )
1546  {
1547  rEntry.Value >>= aChoicesDisabled;
1548  }
1549  }
1550  if( bHaveProperty )
1551  {
1552  vcl::ImplPrinterControllerData::PropertyToIndexMap::const_iterator it =
1553  mpImplData->maPropertyToIndex.find( aPropName );
1554  // sanity check
1555  if( it != mpImplData->maPropertyToIndex.end() )
1556  {
1557  mpImplData->maUIPropertyEnabled[ it->second ] = bIsEnabled;
1558  }
1559  if( !aDep.maDependsOnName.isEmpty() )
1560  mpImplData->maControlDependencies[ aPropName ] = aDep;
1561  if( aChoicesDisabled.hasElements() )
1562  mpImplData->maChoiceDisableMap[ aPropName ] = aChoicesDisabled;
1563  }
1564  }
1565 }
1566 
1567 bool PrinterController::isUIOptionEnabled( const OUString& i_rProperty ) const
1568 {
1569  bool bEnabled = false;
1570  std::unordered_map< OUString, size_t >::const_iterator prop_it =
1571  mpImplData->maPropertyToIndex.find( i_rProperty );
1572  if( prop_it != mpImplData->maPropertyToIndex.end() )
1573  {
1574  bEnabled = mpImplData->maUIPropertyEnabled[prop_it->second];
1575 
1576  if( bEnabled )
1577  {
1578  // check control dependencies
1579  vcl::ImplPrinterControllerData::ControlDependencyMap::const_iterator it =
1580  mpImplData->maControlDependencies.find( i_rProperty );
1581  if( it != mpImplData->maControlDependencies.end() )
1582  {
1583  // check if the dependency is enabled
1584  // if the dependency is disabled, we are too
1585  bEnabled = isUIOptionEnabled( it->second.maDependsOnName );
1586 
1587  if( bEnabled )
1588  {
1589  // does the dependency have the correct value ?
1590  const css::beans::PropertyValue* pVal = getValue( it->second.maDependsOnName );
1591  OSL_ENSURE( pVal, "unknown property in dependency" );
1592  if( pVal )
1593  {
1594  sal_Int32 nDepVal = 0;
1595  bool bDepVal = false;
1596  if( pVal->Value >>= nDepVal )
1597  {
1598  bEnabled = (nDepVal == it->second.mnDependsOnEntry) || (it->second.mnDependsOnEntry == -1);
1599  }
1600  else if( pVal->Value >>= bDepVal )
1601  {
1602  // could be a dependency on a checked boolean
1603  // in this case the dependency is on a non zero for checked value
1604  bEnabled = ( bDepVal && it->second.mnDependsOnEntry != 0) ||
1605  ( ! bDepVal && it->second.mnDependsOnEntry == 0);
1606  }
1607  else
1608  {
1609  // if the type does not match something is awry
1610  OSL_FAIL( "strange type in control dependency" );
1611  bEnabled = false;
1612  }
1613  }
1614  }
1615  }
1616  }
1617  }
1618  return bEnabled;
1619 }
1620 
1621 bool PrinterController::isUIChoiceEnabled( const OUString& i_rProperty, sal_Int32 i_nValue ) const
1622 {
1623  bool bEnabled = true;
1624  ImplPrinterControllerData::ChoiceDisableMap::const_iterator it =
1625  mpImplData->maChoiceDisableMap.find( i_rProperty );
1626  if(it != mpImplData->maChoiceDisableMap.end() )
1627  {
1628  const css::uno::Sequence< sal_Bool >& rDisabled( it->second );
1629  if( i_nValue >= 0 && i_nValue < rDisabled.getLength() )
1630  bEnabled = ! rDisabled[i_nValue];
1631  }
1632  return bEnabled;
1633 }
1634 
1635 OUString PrinterController::makeEnabled( const OUString& i_rProperty )
1636 {
1637  OUString aDependency;
1638 
1639  vcl::ImplPrinterControllerData::ControlDependencyMap::const_iterator it =
1640  mpImplData->maControlDependencies.find( i_rProperty );
1641  if( it != mpImplData->maControlDependencies.end() )
1642  {
1643  if( isUIOptionEnabled( it->second.maDependsOnName ) )
1644  {
1645  aDependency = it->second.maDependsOnName;
1646  const css::beans::PropertyValue* pVal = getValue( aDependency );
1647  OSL_ENSURE( pVal, "unknown property in dependency" );
1648  if( pVal )
1649  {
1650  sal_Int32 nDepVal = 0;
1651  bool bDepVal = false;
1652  if( pVal->Value >>= nDepVal )
1653  {
1654  if( it->second.mnDependsOnEntry != -1 )
1655  {
1656  setValue( aDependency, css::uno::makeAny( sal_Int32( it->second.mnDependsOnEntry ) ) );
1657  }
1658  }
1659  else if( pVal->Value >>= bDepVal )
1660  {
1661  setValue( aDependency, css::uno::makeAny( it->second.mnDependsOnEntry != 0 ) );
1662  }
1663  else
1664  {
1665  // if the type does not match something is awry
1666  OSL_FAIL( "strange type in control dependency" );
1667  }
1668  }
1669  }
1670  }
1671 
1672  return aDependency;
1673 }
1674 
1676 {
1677  if (!mpImplData->mxProgress)
1678  {
1679  bool bShow = true;
1680  css::beans::PropertyValue* pMonitor = getValue( "MonitorVisible" );
1681  if( pMonitor )
1682  pMonitor->Value >>= bShow;
1683  else
1684  {
1685  const css::beans::PropertyValue* pVal = getValue( "IsApi" );
1686  if( pVal )
1687  {
1688  bool bApi = false;
1689  pVal->Value >>= bApi;
1690  bShow = ! bApi;
1691  }
1692  }
1693 
1694  if( bShow && ! Application::IsHeadlessModeEnabled() )
1695  {
1696  VclPtr<vcl::Window> xParent = getWindow();
1697  mpImplData->mxProgress.reset(new PrintProgressDialog(xParent ? xParent->GetFrameWeld() : nullptr, getPageCountProtected()));
1698  weld::DialogController::runAsync(mpImplData->mxProgress, [](sal_Int32 /*nResult*/){});
1699  }
1700  }
1701  else
1702  {
1703  mpImplData->mxProgress->response(RET_CANCEL);
1704  mpImplData->mxProgress.reset();
1705  }
1706 }
1707 
1709 {
1710  return mpImplData->mxProgress && mpImplData->mxProgress->isCanceled();
1711 }
1712 
1714 {
1715  mpImplData->maMultiPage = i_rMPS;
1716 }
1717 
1719 {
1720  return mpImplData->maMultiPage;
1721 }
1722 
1724 {
1725  mpImplData->resetPaperToLastConfigured();
1726 }
1727 
1729 {
1730  sal_Int32 nCopyCount = 1;
1731  // set copycount and collate
1732  const css::beans::PropertyValue* pVal = getValue( "CopyCount" );
1733  if( pVal )
1734  pVal->Value >>= nCopyCount;
1735  bool bCollate = false;
1736  pVal = getValue( "Collate" );
1737  if( pVal )
1738  pVal->Value >>= bCollate;
1739  mpImplData->mxPrinter->SetCopyCount( static_cast<sal_uInt16>(nCopyCount), bCollate );
1740 
1741  // duplex mode
1742  pVal = getValue( "DuplexMode" );
1743  if( pVal )
1744  {
1745  sal_Int16 nDuplex = css::view::DuplexMode::UNKNOWN;
1746  pVal->Value >>= nDuplex;
1747  switch( nDuplex )
1748  {
1749  case css::view::DuplexMode::OFF: mpImplData->mxPrinter->SetDuplexMode( DuplexMode::Off ); break;
1750  case css::view::DuplexMode::LONGEDGE: mpImplData->mxPrinter->SetDuplexMode( DuplexMode::LongEdge ); break;
1751  case css::view::DuplexMode::SHORTEDGE: mpImplData->mxPrinter->SetDuplexMode( DuplexMode::ShortEdge ); break;
1752  }
1753  }
1754 }
1755 
1757 {
1758  bool bApi = getBoolProperty( "IsApi", false );
1759  return ! bApi && ! Application::IsHeadlessModeEnabled();
1760 }
1761 
1763 {
1764  bool bDirect = getBoolProperty( "IsDirect", false );
1765  return bDirect;
1766 }
1767 
1768 bool PrinterController::getBoolProperty( const OUString& i_rProperty, bool i_bFallback ) const
1769 {
1770  bool bRet = i_bFallback;
1771  const css::beans::PropertyValue* pVal = getValue( i_rProperty );
1772  if( pVal )
1773  pVal->Value >>= bRet;
1774  return bRet;
1775 }
1776 
1777 sal_Int32 PrinterController::getIntProperty( const OUString& i_rProperty, sal_Int32 i_nFallback ) const
1778 {
1779  sal_Int32 nRet = i_nFallback;
1780  const css::beans::PropertyValue* pVal = getValue( i_rProperty );
1781  if( pVal )
1782  pVal->Value >>= nRet;
1783  return nRet;
1784 }
1785 
1786 /*
1787  * PrinterOptionsHelper
1788 **/
1789 css::uno::Any PrinterOptionsHelper::getValue( const OUString& i_rPropertyName ) const
1790 {
1791  css::uno::Any aRet;
1792  std::unordered_map< OUString, css::uno::Any >::const_iterator it =
1793  m_aPropertyMap.find( i_rPropertyName );
1794  if( it != m_aPropertyMap.end() )
1795  aRet = it->second;
1796  return aRet;
1797 }
1798 
1799 bool PrinterOptionsHelper::getBoolValue( const OUString& i_rPropertyName, bool i_bDefault ) const
1800 {
1801  bool bRet = false;
1802  css::uno::Any aVal( getValue( i_rPropertyName ) );
1803  return (aVal >>= bRet) ? bRet : i_bDefault;
1804 }
1805 
1806 sal_Int64 PrinterOptionsHelper::getIntValue( const OUString& i_rPropertyName, sal_Int64 i_nDefault ) const
1807 {
1808  sal_Int64 nRet = 0;
1809  css::uno::Any aVal( getValue( i_rPropertyName ) );
1810  return (aVal >>= nRet) ? nRet : i_nDefault;
1811 }
1812 
1813 OUString PrinterOptionsHelper::getStringValue( const OUString& i_rPropertyName ) const
1814 {
1815  OUString aRet;
1816  css::uno::Any aVal( getValue( i_rPropertyName ) );
1817  return (aVal >>= aRet) ? aRet : OUString();
1818 }
1819 
1820 bool PrinterOptionsHelper::processProperties( const css::uno::Sequence< css::beans::PropertyValue >& i_rNewProp )
1821 {
1822  bool bChanged = false;
1823 
1824  for( const auto& rVal : i_rNewProp )
1825  {
1826  std::unordered_map< OUString, css::uno::Any >::iterator it =
1827  m_aPropertyMap.find( rVal.Name );
1828 
1829  bool bElementChanged = (it == m_aPropertyMap.end()) || (it->second != rVal.Value);
1830  if( bElementChanged )
1831  {
1832  m_aPropertyMap[ rVal.Name ] = rVal.Value;
1833  bChanged = true;
1834  }
1835  }
1836  return bChanged;
1837 }
1838 
1839 void PrinterOptionsHelper::appendPrintUIOptions( css::uno::Sequence< css::beans::PropertyValue >& io_rProps ) const
1840 {
1841  if( !m_aUIProperties.empty() )
1842  {
1843  sal_Int32 nIndex = io_rProps.getLength();
1844  io_rProps.realloc( nIndex+1 );
1845  css::beans::PropertyValue aVal;
1846  aVal.Name = "ExtraPrintUIOptions";
1848  io_rProps[ nIndex ] = aVal;
1849  }
1850 }
1851 
1852 css::uno::Any PrinterOptionsHelper::setUIControlOpt(const css::uno::Sequence< OUString >& i_rIDs,
1853  const OUString& i_rTitle,
1854  const css::uno::Sequence< OUString >& i_rHelpIds,
1855  const OUString& i_rType,
1856  const css::beans::PropertyValue* i_pVal,
1857  const PrinterOptionsHelper::UIControlOptions& i_rControlOptions)
1858 {
1859  sal_Int32 nElements =
1860  2 // ControlType + ID
1861  + (i_rTitle.isEmpty() ? 0 : 1) // Text
1862  + (i_rHelpIds.hasElements() ? 1 : 0) // HelpId
1863  + (i_pVal ? 1 : 0) // Property
1864  + i_rControlOptions.maAddProps.size() // additional props
1865  + (i_rControlOptions.maGroupHint.isEmpty() ? 0 : 1) // grouping
1866  + (i_rControlOptions.mbInternalOnly ? 1 : 0) // internal hint
1867  + (i_rControlOptions.mbEnabled ? 0 : 1) // enabled
1868  ;
1869  if( !i_rControlOptions.maDependsOnName.isEmpty() )
1870  {
1871  nElements += 1;
1872  if( i_rControlOptions.mnDependsOnEntry != -1 )
1873  nElements += 1;
1874  if( i_rControlOptions.mbAttachToDependency )
1875  nElements += 1;
1876  }
1877 
1878  css::uno::Sequence< css::beans::PropertyValue > aCtrl( nElements );
1879  sal_Int32 nUsed = 0;
1880  if( !i_rTitle.isEmpty() )
1881  {
1882  aCtrl[nUsed ].Name = "Text";
1883  aCtrl[nUsed++].Value <<= i_rTitle;
1884  }
1885  if( i_rHelpIds.hasElements() )
1886  {
1887  aCtrl[nUsed ].Name = "HelpId";
1888  aCtrl[nUsed++].Value <<= i_rHelpIds;
1889  }
1890  aCtrl[nUsed ].Name = "ControlType";
1891  aCtrl[nUsed++].Value <<= i_rType;
1892  aCtrl[nUsed ].Name = "ID";
1893  aCtrl[nUsed++].Value <<= i_rIDs;
1894  if( i_pVal )
1895  {
1896  aCtrl[nUsed ].Name = "Property";
1897  aCtrl[nUsed++].Value <<= *i_pVal;
1898  }
1899  if( !i_rControlOptions.maDependsOnName.isEmpty() )
1900  {
1901  aCtrl[nUsed ].Name = "DependsOnName";
1902  aCtrl[nUsed++].Value <<= i_rControlOptions.maDependsOnName;
1903  if( i_rControlOptions.mnDependsOnEntry != -1 )
1904  {
1905  aCtrl[nUsed ].Name = "DependsOnEntry";
1906  aCtrl[nUsed++].Value <<= i_rControlOptions.mnDependsOnEntry;
1907  }
1908  if( i_rControlOptions.mbAttachToDependency )
1909  {
1910  aCtrl[nUsed ].Name = "AttachToDependency";
1911  aCtrl[nUsed++].Value <<= i_rControlOptions.mbAttachToDependency;
1912  }
1913  }
1914  if( !i_rControlOptions.maGroupHint.isEmpty() )
1915  {
1916  aCtrl[nUsed ].Name = "GroupingHint";
1917  aCtrl[nUsed++].Value <<= i_rControlOptions.maGroupHint;
1918  }
1919  if( i_rControlOptions.mbInternalOnly )
1920  {
1921  aCtrl[nUsed ].Name = "InternalUIOnly";
1922  aCtrl[nUsed++].Value <<= true;
1923  }
1924  if( ! i_rControlOptions.mbEnabled )
1925  {
1926  aCtrl[nUsed ].Name = "Enabled";
1927  aCtrl[nUsed++].Value <<= false;
1928  }
1929 
1930  sal_Int32 nAddProps = i_rControlOptions.maAddProps.size();
1931  for( sal_Int32 i = 0; i < nAddProps; i++ )
1932  aCtrl[ nUsed++ ] = i_rControlOptions.maAddProps[i];
1933 
1934  SAL_WARN_IF( nUsed != nElements, "vcl.gdi", "nUsed != nElements, probable heap corruption" );
1935 
1936  return css::uno::makeAny( aCtrl );
1937 }
1938 
1939 css::uno::Any PrinterOptionsHelper::setGroupControlOpt(const OUString& i_rID,
1940  const OUString& i_rTitle,
1941  const OUString& i_rHelpId)
1942 {
1943  css::uno::Sequence< OUString > aHelpId;
1944  if( !i_rHelpId.isEmpty() )
1945  {
1946  aHelpId.realloc( 1 );
1947  *aHelpId.getArray() = i_rHelpId;
1948  }
1949  css::uno::Sequence< OUString > aIds { i_rID };
1950  return setUIControlOpt(aIds, i_rTitle, aHelpId, "Group");
1951 }
1952 
1953 css::uno::Any PrinterOptionsHelper::setSubgroupControlOpt(const OUString& i_rID,
1954  const OUString& i_rTitle,
1955  const OUString& i_rHelpId,
1956  const PrinterOptionsHelper::UIControlOptions& i_rControlOptions)
1957 {
1958  css::uno::Sequence< OUString > aHelpId;
1959  if( !i_rHelpId.isEmpty() )
1960  {
1961  aHelpId.realloc( 1 );
1962  *aHelpId.getArray() = i_rHelpId;
1963  }
1964  css::uno::Sequence< OUString > aIds { i_rID };
1965  return setUIControlOpt(aIds, i_rTitle, aHelpId, "Subgroup", nullptr, i_rControlOptions);
1966 }
1967 
1968 css::uno::Any PrinterOptionsHelper::setBoolControlOpt(const OUString& i_rID,
1969  const OUString& i_rTitle,
1970  const OUString& i_rHelpId,
1971  const OUString& i_rProperty,
1972  bool i_bValue,
1973  const PrinterOptionsHelper::UIControlOptions& i_rControlOptions)
1974 {
1975  css::uno::Sequence< OUString > aHelpId;
1976  if( !i_rHelpId.isEmpty() )
1977  {
1978  aHelpId.realloc( 1 );
1979  *aHelpId.getArray() = i_rHelpId;
1980  }
1981  css::beans::PropertyValue aVal;
1982  aVal.Name = i_rProperty;
1983  aVal.Value <<= i_bValue;
1984  css::uno::Sequence< OUString > aIds { i_rID };
1985  return setUIControlOpt(aIds, i_rTitle, aHelpId, "Bool", &aVal, i_rControlOptions);
1986 }
1987 
1988 css::uno::Any PrinterOptionsHelper::setChoiceRadiosControlOpt(const css::uno::Sequence< OUString >& i_rIDs,
1989  const OUString& i_rTitle,
1990  const css::uno::Sequence< OUString >& i_rHelpId,
1991  const OUString& i_rProperty,
1992  const css::uno::Sequence< OUString >& i_rChoices,
1993  sal_Int32 i_nValue,
1994  const css::uno::Sequence< sal_Bool >& i_rDisabledChoices,
1995  const PrinterOptionsHelper::UIControlOptions& i_rControlOptions)
1996 {
1997  UIControlOptions aOpt( i_rControlOptions );
1998  sal_Int32 nUsed = aOpt.maAddProps.size();
1999  aOpt.maAddProps.resize( nUsed + 1 + (i_rDisabledChoices.hasElements() ? 1 : 0) );
2000  aOpt.maAddProps[nUsed].Name = "Choices";
2001  aOpt.maAddProps[nUsed].Value <<= i_rChoices;
2002  if( i_rDisabledChoices.hasElements() )
2003  {
2004  aOpt.maAddProps[nUsed+1].Name = "ChoicesDisabled";
2005  aOpt.maAddProps[nUsed+1].Value <<= i_rDisabledChoices;
2006  }
2007 
2008  css::beans::PropertyValue aVal;
2009  aVal.Name = i_rProperty;
2010  aVal.Value <<= i_nValue;
2011  return setUIControlOpt(i_rIDs, i_rTitle, i_rHelpId, "Radio", &aVal, aOpt);
2012 }
2013 
2014 css::uno::Any PrinterOptionsHelper::setChoiceListControlOpt(const OUString& i_rID,
2015  const OUString& i_rTitle,
2016  const css::uno::Sequence< OUString >& i_rHelpId,
2017  const OUString& i_rProperty,
2018  const css::uno::Sequence< OUString >& i_rChoices,
2019  sal_Int32 i_nValue,
2020  const css::uno::Sequence< sal_Bool >& i_rDisabledChoices,
2021  const PrinterOptionsHelper::UIControlOptions& i_rControlOptions)
2022 {
2023  UIControlOptions aOpt( i_rControlOptions );
2024  sal_Int32 nUsed = aOpt.maAddProps.size();
2025  aOpt.maAddProps.resize( nUsed + 1 + (i_rDisabledChoices.hasElements() ? 1 : 0) );
2026  aOpt.maAddProps[nUsed].Name = "Choices";
2027  aOpt.maAddProps[nUsed].Value <<= i_rChoices;
2028  if( i_rDisabledChoices.hasElements() )
2029  {
2030  aOpt.maAddProps[nUsed+1].Name = "ChoicesDisabled";
2031  aOpt.maAddProps[nUsed+1].Value <<= i_rDisabledChoices;
2032  }
2033 
2034  css::beans::PropertyValue aVal;
2035  aVal.Name = i_rProperty;
2036  aVal.Value <<= i_nValue;
2037  css::uno::Sequence< OUString > aIds { i_rID };
2038  return setUIControlOpt(aIds, i_rTitle, i_rHelpId, "List", &aVal, aOpt);
2039 }
2040 
2041 css::uno::Any PrinterOptionsHelper::setRangeControlOpt(const OUString& i_rID,
2042  const OUString& i_rTitle,
2043  const OUString& i_rHelpId,
2044  const OUString& i_rProperty,
2045  sal_Int32 i_nValue,
2046  sal_Int32 i_nMinValue,
2047  sal_Int32 i_nMaxValue,
2048  const PrinterOptionsHelper::UIControlOptions& i_rControlOptions)
2049 {
2050  UIControlOptions aOpt( i_rControlOptions );
2051  if( i_nMaxValue >= i_nMinValue )
2052  {
2053  sal_Int32 nUsed = aOpt.maAddProps.size();
2054  aOpt.maAddProps.resize( nUsed + 2 );
2055  aOpt.maAddProps[nUsed ].Name = "MinValue";
2056  aOpt.maAddProps[nUsed++].Value <<= i_nMinValue;
2057  aOpt.maAddProps[nUsed ].Name = "MaxValue";
2058  aOpt.maAddProps[nUsed++].Value <<= i_nMaxValue;
2059  }
2060 
2061  css::uno::Sequence< OUString > aHelpId;
2062  if( !i_rHelpId.isEmpty() )
2063  {
2064  aHelpId.realloc( 1 );
2065  *aHelpId.getArray() = i_rHelpId;
2066  }
2067  css::beans::PropertyValue aVal;
2068  aVal.Name = i_rProperty;
2069  aVal.Value <<= i_nValue;
2070  css::uno::Sequence< OUString > aIds { i_rID };
2071  return setUIControlOpt(aIds, i_rTitle, aHelpId, "Range", &aVal, aOpt);
2072 }
2073 
2074 css::uno::Any PrinterOptionsHelper::setEditControlOpt(const OUString& i_rID,
2075  const OUString& i_rTitle,
2076  const OUString& i_rHelpId,
2077  const OUString& i_rProperty,
2078  const OUString& i_rValue,
2079  const PrinterOptionsHelper::UIControlOptions& i_rControlOptions)
2080 {
2081  css::uno::Sequence< OUString > aHelpId;
2082  if( !i_rHelpId.isEmpty() )
2083  {
2084  aHelpId.realloc( 1 );
2085  *aHelpId.getArray() = i_rHelpId;
2086  }
2087  css::beans::PropertyValue aVal;
2088  aVal.Name = i_rProperty;
2089  aVal.Value <<= i_rValue;
2090  css::uno::Sequence< OUString > aIds { i_rID };
2091  return setUIControlOpt(aIds, i_rTitle, aHelpId, "Edit", &aVal, i_rControlOptions);
2092 }
2093 
2094 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static OUString GetDisplayName()
Get the default name of the application for message dialogs and printing.
Definition: svapp.cxx:1174
static css::uno::Any setChoiceRadiosControlOpt(const css::uno::Sequence< OUString > &i_rIDs, const OUString &i_rTitle, const css::uno::Sequence< OUString > &i_rHelpId, const OUString &i_rProperty, const css::uno::Sequence< OUString > &i_rChoices, sal_Int32 i_nValue, const css::uno::Sequence< sal_Bool > &i_rDisabledChoices=css::uno::Sequence< sal_Bool >(), const UIControlOptions &i_rControlOptions=UIControlOptions())
Show a set of choices as radio buttons.
Definition: print3.cxx:1988
static void PrintJob(const std::shared_ptr< vcl::PrinterController > &i_pController, const JobSetup &i_rInitSetup)
Execute a print job.
Definition: print3.cxx:294
VCL_DLLPRIVATE void setPrinter(const VclPtr< Printer > &)
Definition: print3.cxx:783
long Width() const
bool isDirectPrint() const
Definition: print3.cxx:1762
bool getBoolValue(const OUString &i_rPropertyName, bool i_bDefault) const
Definition: print3.cxx:1799
const css::uno::Sequence< css::beans::PropertyValue > & getUIOptions() const
Definition: print3.cxx:1461
const OUString & GetName() const
Definition: print.hxx:276
Orientation
Definition: Exif.hxx:25
Size aSize
In 100th mm.
Definition: print.hxx:426
constexpr::Color COL_BLACK(0x00, 0x00, 0x00)
std::vector< css::beans::PropertyValue > maUIProperties
Definition: print3.cxx:143
std::unordered_map< OUString, css::uno::Sequence< sal_Bool > > ChoiceDisableMap
Definition: print3.cxx:138
PrintJobAsync(const std::shared_ptr< PrinterController > &i_xController, const JobSetup &i_rInitSetup)
Definition: print3.cxx:278
VCL_DLLPRIVATE bool isPaperSizeFromUser() const
Definition: print3.cxx:1403
DrawModeFlags
Definition: outdev.hxx:200
std::unordered_map< OUString, css::uno::Any > m_aPropertyMap
Definition: print.hxx:569
JobSetup const maInitSetup
Definition: print3.cxx:276
sal_uInt16 GetPaperBin() const
Definition: print.cxx:1188
VCL_DLLPRIVATE void setupPrinter(weld::Window *i_pDlgParent)
Definition: print3.cxx:804
long Height() const
vcl::PrinterController::MultiPageSetup maMultiPage
Definition: print3.cxx:156
void setJobState(css::view::PrintableState)
Definition: print3.cxx:768
VCL_DLLPRIVATE bool getPapersizeFromSetup() const
Definition: print3.cxx:1379
std::vector< css::beans::PropertyValue > m_aUIProperties
Definition: print.hxx:571
VCL_DLLPRIVATE Size & getPaperSizeFromUser() const
Definition: print3.cxx:1398
VCL_DLLPRIVATE DrawModeFlags removeTransparencies(GDIMetaFile const &i_rIn, GDIMetaFile &o_rOut)
Definition: print3.cxx:1220
bool isProgressCanceled() const
Definition: print3.cxx:1708
void SetPrefSize(const Size &rSize)
Definition: gdimtf.hxx:174
aBuf
void Clear()
Definition: gdimtf.cxx:243
PrinterController::PageSize aSize
Definition: print3.cxx:55
static ImplSVEvent * PostUserEvent(const Link< void *, void > &rLink, void *pCaller=nullptr, bool bReferenceLink=false)
Post a user event to the default window.
Definition: svapp.cxx:997
PrinterTransparencyMode GetReducedTransparencyMode() const
Definition: print.hxx:130
static bool ExecutePrintJob(const std::shared_ptr< vcl::PrinterController > &i_pController)
Definition: print3.cxx:520
std::vector< sal_Int32 > maPageNumbers
Definition: print3.cxx:59
VCL_DLLPRIVATE bool StartJob(const OUString &rJobName, std::shared_ptr< vcl::PrinterController > const &)
Definition: print3.cxx:546
void printFilteredPage(int i_nPage)
Definition: print3.cxx:1282
VCL_DLLPRIVATE Size & getPaperSizeSetup() const
Definition: print3.cxx:1384
std::vector< sal_Int32 > maCacheRanking
Definition: print3.cxx:60
bool IsReduceBitmaps() const
Definition: print.hxx:144
static void FinishPrintJob(const std::shared_ptr< vcl::PrinterController > &i_pController)
Definition: print3.cxx:530
void Clip(const tools::Rectangle &)
Definition: gdimtf.cxx:710
Orientation GetOrientation() const
Definition: print.cxx:1147
void SetMapMode()
Definition: map.cxx:655
VCL_DLLPRIVATE const MultiPageSetup & getMultipage() const
Definition: print3.cxx:1718
void updateRanking(sal_Int32 nLastHit)
Definition: print3.cxx:64
bool IsReducedBitmapIncludesTransparency() const
Definition: print.hxx:154
std::unordered_map< OUString, size_t > PropertyToIndexMap
Definition: print3.cxx:136
virtual css::uno::Sequence< css::beans::PropertyValue > getPageParameters(int i_nPage) const =0
Get the page parameters.
static bool runAsync(const std::shared_ptr< DialogController > &rController, const std::function< void(sal_Int32)> &)
weld::Window * GetFrameWeld() const
Definition: window2.cxx:858
css::view::PrintableState meJobState
Definition: print3.cxx:154
std::vector< css::beans::PropertyValue > maAddProps
Definition: print.hxx:619
A construction helper for ScopedVclPtr.
Definition: vclptr.hxx:407
constexpr::Color COL_TRANSPARENT(0xFF, 0xFF, 0xFF, 0xFF)
VCL_DLLPRIVATE css::uno::Sequence< css::beans::PropertyValue > getPageParametersProtected(int i_nPage) const
Definition: print3.cxx:965
VCL_DLLPRIVATE void resetPaperToLastConfigured()
Definition: print3.cxx:1723
std::vector< CacheEntry > maPages
Definition: print3.cxx:58
void Record(OutputDevice *pOutDev)
Definition: gdimtf.cxx:284
VCL_DLLPRIVATE void pushPropertiesToPrinter()
Definition: print3.cxx:1728
css::uno::Sequence< css::beans::PropertyValue > maUIOptions
Definition: print3.cxx:142
OUString makeEnabled(const OUString &rPropName)
MakeEnabled will change the property rPropName depends on to the value.
Definition: print3.cxx:1635
int getFilteredPageCount() const
Definition: print3.cxx:1212
static css::uno::Any setSubgroupControlOpt(const OUString &i_rID, const OUString &i_rTitle, const OUString &i_rHelpId, const UIControlOptions &i_rControlOptions=UIControlOptions())
Show and set the label of a VclFrame of id i_rID.
Definition: print3.cxx:1953
VCL_DLLPRIVATE void setPaperSizeFromUser(Size i_aUserSize)
Definition: print3.cxx:1389
#define PRINTER_GENERALERROR
Definition: errcode.hxx:268
static css::uno::Any setRangeControlOpt(const OUString &i_rID, const OUString &i_rTitle, const OUString &i_rHelpId, const OUString &i_rProperty, sal_Int32 i_nValue, sal_Int32 i_nMinValue, sal_Int32 i_nMaxValue, const UIControlOptions &i_rControlOptions)
Show an integer range (e.g.
Definition: print3.cxx:2041
void Play(GDIMetaFile &rMtf)
Definition: gdimtf.cxx:295
std::unique_ptr< ImplPrinterControllerData > mpImplData
Definition: print.hxx:395
void ReadFromConfig(bool bFile)
Read printer options from configuration.
Definition: print.cxx:107
sal_Int32 nElements
void setLastPage(bool i_bLastPage)
Definition: print3.cxx:1361
virtual int getPageCount() const =0
App must override this.
bool getBoolProperty(const OUString &i_rPropertyName, bool i_bFallback) const
Get a bool property.
Definition: print3.cxx:1768
bool SetPaperSizeUser(const Size &rSize)
Definition: print.cxx:1347
static bool PreparePrintJob(std::shared_ptr< vcl::PrinterController > i_pController, const JobSetup &i_rInitSetup)
Definition: print3.cxx:311
ImplSVData * ImplGetSVData()
Definition: svdata.cxx:67
VCL_DLLPRIVATE void setPapersizeFromSetup(bool i_bPapersizeFromSetup)
Definition: print3.cxx:1371
static void VCL_DLLPRIVATE ImplPrintJob(const std::shared_ptr< vcl::PrinterController > &i_pController, const JobSetup &i_rInitSetup)
Implementation detail of PrintJob being asynchronous.
Definition: print3.cxx:536
css::beans::PropertyValue * getValue(const OUString &i_rPropertyName)
Get the PropertyValue of a Property.
Definition: print3.cxx:1466
static bool Reschedule(bool bHandleAllCurrentEvents=false)
Attempt to process current pending event(s)
Definition: svapp.cxx:457
#define DBG_ASSERT(sCon, aError)
sal_uInt16 GetReducedBitmapResolution() const
Definition: print.hxx:150
void setValue(const OUString &rGroup, const OUString &rKey, const OUString &rValue)
static css::uno::Any setEditControlOpt(const OUString &i_rID, const OUString &i_rTitle, const OUString &i_rHelpId, const OUString &i_rProperty, const OUString &i_rValue, const UIControlOptions &i_rControlOptions)
Show a string field.
Definition: print3.cxx:2074
void insert(sal_Int32 i_nPageNo, const GDIMetaFile &i_rPage, const PrinterController::PageSize &i_rSize)
Definition: print3.cxx:85
PrinterController(const VclPtr< Printer > &, const VclPtr< vcl::Window > &)
Definition: print3.cxx:222
int i
void setPrinterModified(bool i_bPapersizeFromSetup)
Definition: print3.cxx:1408
virtual void jobFinished(css::view::PrintableState)
Definition: print3.cxx:1340
void appendPrintUIOptions(css::uno::Sequence< css::beans::PropertyValue > &io_rProps) const
Append to a sequence of property values the ui property sequence passed at creation.
Definition: print3.cxx:1839
ControlDependencyMap maControlDependencies
Definition: print3.cxx:146
bool isPrintToFile() const
Definition: printdlg.cxx:1772
PrinterController::PageSize modifyJobSetup(const css::uno::Sequence< css::beans::PropertyValue > &i_rProps)
Definition: print3.cxx:874
virtual void printPage(int i_nPage) const =0
App must override this.
void WindStart()
Definition: gdimtf.cxx:526
std::shared_ptr< vcl::PrintProgressDialog > mxProgress
Definition: print3.cxx:158
PrinterBitmapMode GetReducedBitmapMode() const
Definition: print.hxx:147
static void appendSubPage(GDIMetaFile &o_rMtf, const tools::Rectangle &i_rClipRect, GDIMetaFile &io_rSubPage, bool i_bDrawBorder)
Definition: print3.cxx:1033
VclPtr< vcl::Window > mxWindow
Definition: print3.cxx:141
virtual short Execute()
Definition: dialog.cxx:1058
bool isShowDialogs() const
Definition: print3.cxx:1756
bool isSingleJobs() const
Definition: printdlg.hxx:119
PageSize getFilteredPageFile(int i_nFilteredPage, GDIMetaFile &o_rMtf, bool i_bMayUseCache=false)
Definition: print3.cxx:1069
OUString getStringValue(const OUString &i_rPropertyName) const
Definition: print3.cxx:1813
VCL_DLLPRIVATE int getPageCountProtected() const
Definition: print3.cxx:954
void Stop()
Definition: gdimtf.cxx:513
A construction helper for a temporary VclPtr.
Definition: vclptr.hxx:275
static css::uno::Any setGroupControlOpt(const OUString &i_rID, const OUString &i_rTitle, const OUString &i_rHelpId)
Show and set the title of a TagPage of id i_rID.
Definition: print3.cxx:1939
const VclPtr< vcl::Window > & getWindow() const
Definition: print3.cxx:778
bool isFixedPageSize() const
Definition: print3.cxx:216
const Size & getRealPaperSize(const Size &i_rPageSize, bool bNoNUP) const
Definition: print3.cxx:206
bool isUIOptionEnabled(const OUString &rPropName) const
Enable/disable an option; this can be used to implement dialog logic.
Definition: print3.cxx:1567
OUString const & GetPrinterName() const
Definition: jobset.cxx:216
bool Setup(weld::Window *pWindow, PrinterSetupMode eMode=PrinterSetupMode::DocumentGlobal)
Definition: print.cxx:993
#define PRINTER_ABORT
Definition: errcode.hxx:267
static OUString queryFile(Printer const *pPrinter)
Definition: print3.cxx:229
static bool IsHeadlessModeEnabled()
Determines if headless mode is enabled.
Definition: svapp.cxx:1499
ChoiceDisableMap maChoiceDisableMap
Definition: print3.cxx:147
#define SAL_WARN_IF(condition, area, stream)
#define ERRCODE_NONE
Definition: errcode.hxx:198
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
void AddAction(const rtl::Reference< MetaAction > &pAction)
Definition: gdimtf.cxx:539
bool SetOrientation(Orientation eOrient)
Definition: print.cxx:1111
void Move(long nX, long nY)
Definition: gdimtf.cxx:607
const VclPtr< Printer > & getPrinter() const
Definition: print3.cxx:773
virtual void jobStarted()
Will be called after a possible dialog has been shown and the real printjob starts.
Definition: print3.cxx:1336
virtual std::unique_ptr< SalPrinter > CreatePrinter(SalInfoPrinter *pInfoPrinter)=0
VCL_DLLPRIVATE void resetPrinterOptions(bool i_bFileOutput)
Definition: print3.cxx:797
void invalidate()
Definition: print3.cxx:114
void Scale(double fScaleX, double fScaleY)
Definition: gdimtf.cxx:684
sal_Int32 getIntProperty(const OUString &i_rPropertyName, sal_Int32 i_nFallback) const
Get an int property.
Definition: print3.cxx:1777
VCL_DLLPRIVATE PageSize getPageFile(int i_inUnfilteredPage, GDIMetaFile &rMtf, bool i_bMayUseCache=false)
Definition: print3.cxx:976
bool processProperties(const css::uno::Sequence< css::beans::PropertyValue > &i_rNewProp)
Process a new set of properties.
Definition: print3.cxx:1820
Reference< XComponentContext > getProcessComponentContext()
VCL_DLLPRIVATE void setMultipage(const MultiPageSetup &)
Definition: print3.cxx:1713
css::uno::Any getValue(const OUString &i_rPropertyName) const
Definition: print3.cxx:1789
virtual ~PrinterController()
Definition: print3.cxx:759
constexpr::Color COL_WHITE(0xFF, 0xFF, 0xFF)
bool GetPrinterSettingsPreferred() const
Definition: print.cxx:1193
PropertyToIndexMap maPropertyToIndex
Definition: print3.cxx:145
static css::uno::Any setBoolControlOpt(const OUString &i_rID, const OUString &i_rTitle, const OUString &i_rHelpId, const OUString &i_rProperty, bool i_bValue, const UIControlOptions &i_rControlOptions=UIControlOptions())
Show a bool option as a checkbox.
Definition: print3.cxx:1968
bool isUIChoiceEnabled(const OUString &rPropName, sal_Int32 nChoice) const
Definition: print3.cxx:1621
bool getPrinterModified() const
Definition: print3.cxx:1413
VCL_DLLPRIVATE void setReversePrint(bool i_bReverse)
Definition: print3.cxx:1366
reference_type * get() const
Get the body.
Definition: vclptr.hxx:143
static weld::Builder * CreateBuilder(weld::Widget *pParent, const OUString &rUIFile)
Definition: builder.cxx:144
#define SAL_WARN(area, stream)
OUString VclResId(const char *pId)
Definition: svdata.cxx:258
std::unordered_map< OUString, ControlDependency > ControlDependencyMap
Definition: print3.cxx:137
VclPtr< Printer > mxPrinter
Definition: print3.cxx:140
std::vector< bool > maUIPropertyEnabled
Definition: print3.cxx:144
css::uno::Sequence< css::beans::PropertyValue > getJobProperties(const css::uno::Sequence< css::beans::PropertyValue > &i_rMergeList) const
For implementations: get current job properties as changed by e.g.
Definition: print3.cxx:1418
NupOrderType
Definition: print.hxx:387
bool bFullPaper
Full paper, not only imageable area is printed.
Definition: print.hxx:429
static SettingsConfigItem * get()
static css::uno::Any setChoiceListControlOpt(const OUString &i_rID, const OUString &i_rTitle, const css::uno::Sequence< OUString > &i_rHelpId, const OUString &i_rProperty, const css::uno::Sequence< OUString > &i_rChoices, sal_Int32 i_nValue, const css::uno::Sequence< sal_Bool > &i_rDisabledChoices=css::uno::Sequence< sal_Bool >(), const UIControlOptions &i_rControlOptions=UIControlOptions())
Show a set of choices in a list box.
Definition: print3.cxx:2014
bool IsReduceTransparency() const
Definition: print.hxx:127
sal_uInt32 GetCapabilities(PrinterCapType nType) const
Definition: print.cxx:942
IMPL_LINK_NOARG(QuickSelectionEngine_Data, SearchStringTimeout, Timer *, void)
void Push(PushFlags nFlags=PushFlags::ALL)
Definition: outdevstate.cxx:60
void setWidth(long nWidth)
std::shared_ptr< PrinterController > mxController
Definition: print3.cxx:275
SalInstance * mpDefInst
Definition: svdata.hxx:341
static css::uno::Any setUIControlOpt(const css::uno::Sequence< OUString > &i_rIDs, const OUString &i_rTitle, const css::uno::Sequence< OUString > &i_rHelpId, const OUString &i_rType, const css::beans::PropertyValue *i_pValue=nullptr, const UIControlOptions &i_rControlOptions=UIControlOptions())
Show general control.
Definition: print3.cxx:1852
sal_Int64 getIntValue(const OUString &i_rPropertyName, sal_Int64 i_nDefault) const
Definition: print3.cxx:1806
css::view::PrintableState getJobState() const
Definition: print3.cxx:763
void setValue(const OUString &i_rPropertyName, const css::uno::Any &i_rValue)
Set a property value - can also be used to add another UI property.
Definition: print3.cxx:1480
void SetPrefMapMode(const MapMode &rMapMode)
Definition: gdimtf.hxx:177
bool IsConvertToGreyscales() const
Definition: print.hxx:158
Size GetPaperSize() const
Definition: print.hxx:330
void setHeight(long nHeight)
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo