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