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