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