1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "prtsetup.hxx"
22 #include <strings.hrc>
24 #include <osl/thread.h>
26 #include <officecfg/Office/Common.hxx>
30 void RTSDialog::insertAllPPDValues(weld::ComboBox
& rBox
, const PPDParser
* pParser
, const PPDKey
* pKey
)
32 if( ! pKey
|| ! pParser
)
35 const PPDValue
* pValue
= nullptr;
38 for (int i
= 0; i
< pKey
->countValues(); ++i
)
40 pValue
= pKey
->getValue( i
);
41 if (pValue
->m_bCustomOption
)
43 aOptionText
= pParser
->translateOption( pKey
->getKey(), pValue
->m_aOption
) ;
45 OUString
sId(OUString::number(reinterpret_cast<sal_Int64
>(pValue
)));
46 int nCurrentPos
= rBox
.find_id(sId
);
47 if( m_aJobData
.m_aContext
.checkConstraints( pKey
, pValue
) )
49 if (nCurrentPos
== -1)
50 rBox
.append(sId
, aOptionText
);
54 if (nCurrentPos
!= -1)
55 rBox
.remove(nCurrentPos
);
58 pValue
= m_aJobData
.m_aContext
.getValue( pKey
);
59 if (pValue
&& !pValue
->m_bCustomOption
)
61 OUString
sId(OUString::number(reinterpret_cast<sal_IntPtr
>(pValue
)));
62 int nPos
= rBox
.find_id(sId
);
64 rBox
.set_active(nPos
);
67 rBox
.set_active_text(m_aInvalidString
);
74 RTSDialog::RTSDialog(const PrinterInfo
& rJobData
, weld::Window
* pParent
)
75 : GenericDialogController(pParent
, "vcl/ui/printerpropertiesdialog.ui", "PrinterPropertiesDialog")
76 , m_aJobData(rJobData
)
77 , m_aInvalidString(VclResId(SV_PRINT_INVALID_TXT
))
78 , m_bDataModified(false)
79 , m_xTabControl(m_xBuilder
->weld_notebook("notebook"))
80 , m_xOKButton(m_xBuilder
->weld_button("ok"))
81 , m_xCancelButton(m_xBuilder
->weld_button("cancel"))
82 , m_xPaperPage(new RTSPaperPage(m_xTabControl
->get_page("paper"), this))
83 , m_xDevicePage(new RTSDevicePage(m_xTabControl
->get_page("device"), this))
85 OUString
aTitle(m_xDialog
->get_title());
86 m_xDialog
->set_title(aTitle
.replaceAll("%s", m_aJobData
.m_aPrinterName
));
88 m_xTabControl
->connect_enter_page( LINK( this, RTSDialog
, ActivatePage
) );
89 m_xOKButton
->connect_clicked( LINK( this, RTSDialog
, ClickButton
) );
90 m_xCancelButton
->connect_clicked( LINK( this, RTSDialog
, ClickButton
) );
91 ActivatePage(m_xTabControl
->get_current_page_ident());
94 RTSDialog::~RTSDialog()
98 IMPL_LINK(RTSDialog
, ActivatePage
, const OString
&, rPage
, void)
100 if (rPage
== "paper")
101 m_xPaperPage
->update();
104 IMPL_LINK( RTSDialog
, ClickButton
, weld::Button
&, rButton
, void )
106 if (&rButton
== m_xOKButton
.get())
108 // refresh the changed values
112 m_aJobData
.m_eOrientation
= m_xPaperPage
->getOrientation() == 0 ?
113 orientation::Portrait
: orientation::Landscape
;
114 // assume use of paper size from printer setup if the user
115 // got here via File > Printer Settings ...
116 if ( m_aJobData
.meSetupMode
== PrinterSetupMode::DocumentGlobal
)
117 m_aJobData
.m_bPapersizeFromSetup
= true;
121 m_aJobData
.m_nColorDepth
= m_xDevicePage
->getDepth();
122 m_aJobData
.m_nColorDevice
= m_xDevicePage
->getColorDevice();
123 m_aJobData
.m_nPSLevel
= m_xDevicePage
->getLevel();
124 m_aJobData
.m_nPDFDevice
= m_xDevicePage
->getPDFDevice();
126 m_xDialog
->response(RET_OK
);
128 else if (&rButton
== m_xCancelButton
.get())
129 m_xDialog
->response(RET_CANCEL
);
136 RTSPaperPage::RTSPaperPage(weld::Widget
* pPage
, RTSDialog
* pDialog
)
137 : m_xBuilder(Application::CreateBuilder(pPage
, "vcl/ui/printerpaperpage.ui"))
139 , m_xContainer(m_xBuilder
->weld_widget("PrinterPaperPage"))
140 , m_xCbFromSetup(m_xBuilder
->weld_check_button("papersizefromsetup"))
141 , m_xPaperText(m_xBuilder
->weld_label("paperft"))
142 , m_xPaperBox(m_xBuilder
->weld_combo_box("paperlb"))
143 , m_xOrientText(m_xBuilder
->weld_label("orientft"))
144 , m_xOrientBox(m_xBuilder
->weld_combo_box("orientlb"))
145 , m_xDuplexText(m_xBuilder
->weld_label("duplexft"))
146 , m_xDuplexBox(m_xBuilder
->weld_combo_box("duplexlb"))
147 , m_xSlotText(m_xBuilder
->weld_label("slotft"))
148 , m_xSlotBox(m_xBuilder
->weld_combo_box("slotlb"))
151 m_xPaperBox
->connect_changed( LINK( this, RTSPaperPage
, SelectHdl
) );
152 m_xOrientBox
->connect_changed( LINK( this, RTSPaperPage
, SelectHdl
) );
153 m_xDuplexBox
->connect_changed( LINK( this, RTSPaperPage
, SelectHdl
) );
154 m_xSlotBox
->connect_changed( LINK( this, RTSPaperPage
, SelectHdl
) );
155 m_xCbFromSetup
->connect_toggled( LINK( this, RTSPaperPage
, CheckBoxHdl
) );
158 m_xDuplexBox
->append_text(m_pParent
->m_aInvalidString
);
160 // paper does not have an invalid entry
163 m_xSlotBox
->append_text(m_pParent
->m_aInvalidString
);
168 RTSPaperPage::~RTSPaperPage()
172 void RTSPaperPage::update()
174 const PPDKey
* pKey
= nullptr;
177 m_xOrientBox
->set_active(m_pParent
->m_aJobData
.m_eOrientation
== orientation::Portrait
? 0 : 1);
180 if( m_pParent
->m_aJobData
.m_pParser
&&
181 (pKey
= m_pParent
->m_aJobData
.m_pParser
->getKey( "Duplex" )) )
183 m_pParent
->insertAllPPDValues( *m_xDuplexBox
, m_pParent
->m_aJobData
.m_pParser
, pKey
);
187 m_xDuplexText
->set_sensitive( false );
188 m_xDuplexBox
->set_sensitive( false );
192 if( m_pParent
->m_aJobData
.m_pParser
&&
193 (pKey
= m_pParent
->m_aJobData
.m_pParser
->getKey( "PageSize" )) )
195 m_pParent
->insertAllPPDValues( *m_xPaperBox
, m_pParent
->m_aJobData
.m_pParser
, pKey
);
199 m_xPaperText
->set_sensitive( false );
200 m_xPaperBox
->set_sensitive( false );
204 if( m_pParent
->m_aJobData
.m_pParser
&&
205 (pKey
= m_pParent
->m_aJobData
.m_pParser
->getKey( "InputSlot" )) )
207 m_pParent
->insertAllPPDValues( *m_xSlotBox
, m_pParent
->m_aJobData
.m_pParser
, pKey
);
211 m_xSlotText
->set_sensitive( false );
212 m_xSlotBox
->set_sensitive( false );
215 if ( m_pParent
->m_aJobData
.meSetupMode
== PrinterSetupMode::SingleJob
)
217 m_xCbFromSetup
->show();
219 if ( m_pParent
->m_aJobData
.m_bPapersizeFromSetup
)
220 m_xCbFromSetup
->set_active(m_pParent
->m_aJobData
.m_bPapersizeFromSetup
);
221 // disable those, unless user wants to use papersize from printer prefs
222 // as they have no influence on what's going to be printed anyway
225 m_xPaperText
->set_sensitive( false );
226 m_xPaperBox
->set_sensitive( false );
227 m_xOrientText
->set_sensitive( false );
228 m_xOrientBox
->set_sensitive( false );
233 IMPL_LINK( RTSPaperPage
, SelectHdl
, weld::ComboBox
&, rBox
, void )
235 const PPDKey
* pKey
= nullptr;
236 if( &rBox
== m_xPaperBox
.get() )
238 if( m_pParent
->m_aJobData
.m_pParser
)
239 pKey
= m_pParent
->m_aJobData
.m_pParser
->getKey( "PageSize" );
241 else if( &rBox
== m_xDuplexBox
.get() )
243 if( m_pParent
->m_aJobData
.m_pParser
)
244 pKey
= m_pParent
->m_aJobData
.m_pParser
->getKey( "Duplex" );
246 else if( &rBox
== m_xSlotBox
.get() )
248 if( m_pParent
->m_aJobData
.m_pParser
)
249 pKey
= m_pParent
->m_aJobData
.m_pParser
->getKey( "InputSlot" );
251 else if( &rBox
== m_xOrientBox
.get() )
253 m_pParent
->m_aJobData
.m_eOrientation
= m_xOrientBox
->get_active() == 0 ? orientation::Portrait
: orientation::Landscape
;
257 PPDValue
* pValue
= reinterpret_cast<PPDValue
*>(rBox
.get_active_id().toInt64());
258 m_pParent
->m_aJobData
.m_aContext
.setValue( pKey
, pValue
);
262 m_pParent
->SetDataModified( true );
265 IMPL_LINK( RTSPaperPage
, CheckBoxHdl
, weld::ToggleButton
&, /*cBox*/, void )
267 bool bFromSetup
= m_xCbFromSetup
->get_active();
268 m_pParent
->m_aJobData
.m_bPapersizeFromSetup
= bFromSetup
;
269 m_xPaperText
->set_sensitive(bFromSetup
);
270 m_xPaperBox
->set_sensitive(bFromSetup
);
271 m_xOrientText
->set_sensitive(bFromSetup
);
272 m_xOrientBox
->set_sensitive(bFromSetup
);
273 m_pParent
->SetDataModified(true);
279 RTSDevicePage::RTSDevicePage(weld::Widget
* pPage
, RTSDialog
* pParent
)
280 : m_xBuilder(Application::CreateBuilder(pPage
, "vcl/ui/printerdevicepage.ui"))
281 , m_pCustomValue(nullptr)
283 , m_xContainer(m_xBuilder
->weld_widget("PrinterDevicePage"))
284 , m_xPPDKeyBox(m_xBuilder
->weld_tree_view("options"))
285 , m_xPPDValueBox(m_xBuilder
->weld_tree_view("values"))
286 , m_xCustomEdit(m_xBuilder
->weld_entry("custom"))
287 , m_xLevelBox(m_xBuilder
->weld_combo_box("level"))
288 , m_xSpaceBox(m_xBuilder
->weld_combo_box("colorspace"))
289 , m_xDepthBox(m_xBuilder
->weld_combo_box("colordepth"))
291 m_aReselectCustomIdle
.SetInvokeHandler(LINK(this, RTSDevicePage
, ImplHandleReselectHdl
));
292 m_aReselectCustomIdle
.SetDebugName("RTSDevicePage m_aReselectCustomIdle");
294 m_xPPDKeyBox
->set_size_request(m_xPPDKeyBox
->get_approximate_digit_width() * 32,
295 m_xPPDKeyBox
->get_height_rows(12));
297 m_xCustomEdit
->connect_changed(LINK(this, RTSDevicePage
, ModifyHdl
));
299 m_xPPDKeyBox
->connect_changed( LINK( this, RTSDevicePage
, SelectHdl
) );
300 m_xPPDValueBox
->connect_changed( LINK( this, RTSDevicePage
, SelectHdl
) );
302 switch( m_pParent
->m_aJobData
.m_nColorDevice
)
305 m_xSpaceBox
->set_active(0);
308 m_xSpaceBox
->set_active(1);
311 m_xSpaceBox
->set_active(2);
315 sal_Int32 nLevelEntryData
= 0; //automatic
316 if( m_pParent
->m_aJobData
.m_nPDFDevice
== 2 ) //explicit PDF
317 nLevelEntryData
= 10;
318 else if (m_pParent
->m_aJobData
.m_nPSLevel
> 0) //explicit PS Level
319 nLevelEntryData
= m_pParent
->m_aJobData
.m_nPSLevel
+1;
320 else if (m_pParent
->m_aJobData
.m_nPDFDevice
== 1) //automatically PDF
322 else if (m_pParent
->m_aJobData
.m_nPDFDevice
== -1) //explicitly PS from driver
325 bool bAutoIsPDF
= officecfg::Office::Common::Print::Option::Printer::PDFAsStandardPrintJobFormat::get();
327 assert(nLevelEntryData
!= 0
328 || "Generic Printer" == m_pParent
->m_aJobData
.m_aPrinterName
329 || int(bAutoIsPDF
) == m_pParent
->m_aJobData
.m_nPDFDevice
);
331 OUString sStr
= m_xLevelBox
->get_text(0);
332 OUString sId
= m_xLevelBox
->get_id(0);
333 m_xLevelBox
->insert(0, sStr
.replaceAll("%s", bAutoIsPDF
? m_xLevelBox
->get_text(5) : m_xLevelBox
->get_text(1)), &sId
, nullptr, nullptr);
334 m_xLevelBox
->remove(1);
336 for (int i
= 0; i
< m_xLevelBox
->get_count(); ++i
)
338 if (m_xLevelBox
->get_id(i
).toInt32() == nLevelEntryData
)
340 m_xLevelBox
->set_active(i
);
345 if (m_pParent
->m_aJobData
.m_nColorDepth
== 8)
346 m_xDepthBox
->set_active(0);
347 else if (m_pParent
->m_aJobData
.m_nColorDepth
== 24)
348 m_xDepthBox
->set_active(1);
351 if( m_pParent
->m_aJobData
.m_pParser
)
353 for( int i
= 0; i
< m_pParent
->m_aJobData
.m_pParser
->getKeys(); i
++ )
355 const PPDKey
* pKey
= m_pParent
->m_aJobData
.m_pParser
->getKey( i
);
357 // skip options already shown somewhere else
358 // also skip options from the "InstallableOptions" PPD group
359 // Options in that group define hardware features that are not
360 // job-specific and should better be handled in the system-wide
361 // printer configuration. Keyword is defined in PPD specification
362 // (version 4.3), section 5.4.
363 if( pKey
->isUIKey() &&
364 pKey
->getKey() != "PageSize" &&
365 pKey
->getKey() != "InputSlot" &&
366 pKey
->getKey() != "PageRegion" &&
367 pKey
->getKey() != "Duplex" &&
368 pKey
->getGroup() != "InstallableOptions")
370 OUString
aEntry( m_pParent
->m_aJobData
.m_pParser
->translateKey( pKey
->getKey() ) );
371 m_xPPDKeyBox
->append(OUString::number(reinterpret_cast<sal_Int64
>(pKey
)), aEntry
);
377 RTSDevicePage::~RTSDevicePage()
381 sal_uLong
RTSDevicePage::getDepth() const
383 sal_uInt16 nSelectPos
= m_xDepthBox
->get_active();
390 sal_uLong
RTSDevicePage::getColorDevice() const
392 sal_uInt16 nSelectPos
= m_xSpaceBox
->get_active();
405 sal_uLong
RTSDevicePage::getLevel() const
407 auto nLevel
= m_xLevelBox
->get_active_id().toInt32();
409 return 0; //automatic
410 return nLevel
< 10 ? nLevel
-1 : 0;
413 sal_uLong
RTSDevicePage::getPDFDevice() const
415 auto nLevel
= m_xLevelBox
->get_active_id().toInt32();
417 return 2; //explicitly PDF
418 else if (nLevel
== 0)
419 return 0; //automatic
420 return -1; //explicitly PS
423 IMPL_LINK(RTSDevicePage
, ModifyHdl
, weld::Entry
&, rEdit
, void)
427 m_pCustomValue
->m_aCustomOption
= rEdit
.get_text();
431 IMPL_LINK( RTSDevicePage
, SelectHdl
, weld::TreeView
&, rBox
, void )
433 if (&rBox
== m_xPPDKeyBox
.get())
435 const PPDKey
* pKey
= reinterpret_cast<PPDKey
*>(m_xPPDKeyBox
->get_selected_id().toInt64());
436 FillValueBox( pKey
);
438 else if (&rBox
== m_xPPDValueBox
.get())
440 const PPDKey
* pKey
= reinterpret_cast<PPDKey
*>(m_xPPDKeyBox
->get_selected_id().toInt64());
441 const PPDValue
* pValue
= reinterpret_cast<PPDValue
*>(m_xPPDValueBox
->get_selected_id().toInt64());
444 m_pParent
->m_aJobData
.m_aContext
.setValue( pKey
, pValue
);
445 ValueBoxChanged(pKey
);
448 m_pParent
->SetDataModified( true );
451 void RTSDevicePage::FillValueBox( const PPDKey
* pKey
)
453 m_xPPDValueBox
->clear();
454 m_xCustomEdit
->hide();
459 const PPDValue
* pValue
= nullptr;
460 for( int i
= 0; i
< pKey
->countValues(); i
++ )
462 pValue
= pKey
->getValue( i
);
463 if( m_pParent
->m_aJobData
.m_aContext
.checkConstraints( pKey
, pValue
) &&
464 m_pParent
->m_aJobData
.m_pParser
)
467 if (pValue
->m_bCustomOption
)
468 aEntry
= VclResId(SV_PRINT_CUSTOM_TXT
);
470 aEntry
= m_pParent
->m_aJobData
.m_pParser
->translateOption( pKey
->getKey(), pValue
->m_aOption
);
471 m_xPPDValueBox
->append(OUString::number(reinterpret_cast<sal_Int64
>(pValue
)), aEntry
);
474 pValue
= m_pParent
->m_aJobData
.m_aContext
.getValue( pKey
);
475 m_xPPDValueBox
->select_id(OUString::number(reinterpret_cast<sal_Int64
>(pValue
)));
477 ValueBoxChanged(pKey
);
480 IMPL_LINK_NOARG(RTSDevicePage
, ImplHandleReselectHdl
, Timer
*, void)
482 //in case selected entry is now not visible select it again to scroll it into view
483 m_xPPDValueBox
->select(m_xPPDValueBox
->get_selected_index());
486 void RTSDevicePage::ValueBoxChanged( const PPDKey
* pKey
)
488 const PPDValue
* pValue
= m_pParent
->m_aJobData
.m_aContext
.getValue(pKey
);
489 if (pValue
->m_bCustomOption
)
491 m_pCustomValue
= pValue
;
492 m_pParent
->m_aJobData
.m_aContext
.setValue(pKey
, pValue
);
493 m_xCustomEdit
->set_text(m_pCustomValue
->m_aCustomOption
);
494 m_xCustomEdit
->show();
495 m_aReselectCustomIdle
.Start();
498 m_xCustomEdit
->hide();
501 int SetupPrinterDriver(weld::Window
* pParent
, ::psp::PrinterInfo
& rJobData
)
504 RTSDialog
aDialog(rJobData
, pParent
);
506 // return 0 if cancel was pressed or if the data
507 // weren't modified, 1 otherwise
508 if (aDialog
.run() != RET_CANCEL
)
510 rJobData
= aDialog
.getSetup();
511 nRet
= aDialog
.GetDataModified() ? 1 : 0;
517 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */