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/.
10 #include <unx/gtk/gtkprintwrapper.hxx>
12 #include <unx/gtk/gtkdata.hxx>
13 #include <unx/gtk/gtkframe.hxx>
14 #include <unx/gtk/gtkinst.hxx>
15 #include <unx/gtk/gtkprn.hxx>
17 #include <vcl/configsettings.hxx>
18 #include <vcl/help.hxx>
19 #include <vcl/print.hxx>
20 #include <vcl/svapp.hxx>
21 #include <vcl/window.hxx>
25 #include <com/sun/star/beans/PropertyValue.hpp>
26 #include <com/sun/star/view/PrintableState.hpp>
28 #include <officecfg/Office/Common.hxx>
30 #include <rtl/ustring.hxx>
31 #include <sal/log.hxx>
36 namespace beans
= com::sun::star::beans
;
37 namespace uno
= com::sun::star::uno
;
38 namespace view
= com::sun::star::view
;
40 using vcl::unx::GtkPrintWrapper
;
47 explicit GtkPrintDialog(vcl::PrinterController
& io_rController
);
49 GtkPrinter
* getPrinter() const
51 return m_xWrapper
->print_unix_dialog_get_selected_printer(GTK_PRINT_UNIX_DIALOG(m_pDialog
));
53 GtkPrintSettings
* getSettings() const
55 return m_xWrapper
->print_unix_dialog_get_settings(GTK_PRINT_UNIX_DIALOG(m_pDialog
));
57 void updateControllerPrintRange();
61 static void UIOption_CheckHdl(GtkWidget
* i_pWidget
, GtkPrintDialog
* io_pThis
)
63 io_pThis
->impl_UIOption_CheckHdl(i_pWidget
);
65 static void UIOption_RadioHdl(GtkWidget
* i_pWidget
, GtkPrintDialog
* io_pThis
)
67 io_pThis
->impl_UIOption_RadioHdl(i_pWidget
);
69 static void UIOption_SelectHdl(GtkWidget
* i_pWidget
, GtkPrintDialog
* io_pThis
)
71 io_pThis
->impl_UIOption_SelectHdl(i_pWidget
);
75 beans::PropertyValue
* impl_queryPropertyValue(GtkWidget
* i_pWidget
) const;
76 void impl_checkOptionalControlDependencies();
78 void impl_UIOption_CheckHdl(GtkWidget
* i_pWidget
);
79 void impl_UIOption_RadioHdl(GtkWidget
* i_pWidget
);
80 void impl_UIOption_SelectHdl(GtkWidget
* i_pWidget
);
82 void impl_initDialog();
83 void impl_initCustomTab();
84 void impl_initPrintContent(uno::Sequence
<sal_Bool
> const& i_rDisabled
);
86 void impl_readFromSettings();
87 void impl_storeToSettings() const;
91 vcl::PrinterController
& m_rController
;
92 std::map
<GtkWidget
*, OUString
> m_aControlToPropertyMap
;
93 std::map
<GtkWidget
*, sal_Int32
> m_aControlToNumValMap
;
94 std::shared_ptr
<GtkPrintWrapper
> m_xWrapper
;
97 struct GtkSalPrinter_Impl
101 GtkPrinter
* m_pPrinter
;
102 GtkPrintSettings
* m_pSettings
;
104 GtkSalPrinter_Impl();
105 ~GtkSalPrinter_Impl();
108 GtkSalPrinter_Impl::GtkSalPrinter_Impl()
109 : m_pPrinter(nullptr)
110 , m_pSettings(nullptr)
114 GtkSalPrinter_Impl::~GtkSalPrinter_Impl()
118 g_object_unref(G_OBJECT(m_pPrinter
));
119 m_pPrinter
= nullptr;
123 g_object_unref(G_OBJECT(m_pSettings
));
124 m_pSettings
= nullptr;
132 lcl_getGtkSalInstance()
134 // we _know_ this is GtkInstance
135 return *static_cast<GtkInstance
*>(GetGtkSalData()->m_pInstance
);
139 lcl_useSystemPrintDialog()
141 return officecfg::Office::Common::Misc::UseSystemPrintDialog::get()
142 && officecfg::Office::Common::Misc::ExperimentalMode::get()
143 && lcl_getGtkSalInstance().getPrintWrapper()->supportsPrinting();
148 GtkSalPrinter::GtkSalPrinter(SalInfoPrinter
* const i_pInfoPrinter
)
149 : PspSalPrinter(i_pInfoPrinter
)
153 GtkSalPrinter::~GtkSalPrinter() = default;
156 GtkSalPrinter::impl_doJob(
157 const OUString
* const i_pFileName
,
158 const OUString
& i_rJobName
,
159 const OUString
& i_rAppName
,
160 ImplJobSetup
* const io_pSetupData
,
161 const bool i_bCollate
,
162 vcl::PrinterController
& io_rController
)
164 io_rController
.setJobState(view::PrintableState_JOB_STARTED
);
165 io_rController
.jobStarted();
166 const bool bJobStarted(
167 PspSalPrinter::StartJob(i_pFileName
, i_rJobName
, i_rAppName
,
168 1/*i_nCopies*/, i_bCollate
, true, io_pSetupData
))
173 io_rController
.createProgressDialog();
174 const int nPages(io_rController
.getFilteredPageCount());
175 for (int nPage(0); nPage
!= nPages
; ++nPage
)
177 if (nPage
== nPages
- 1)
178 io_rController
.setLastPage(true);
179 io_rController
.printFilteredPage(nPage
);
181 io_rController
.setJobState(view::PrintableState_JOB_COMPLETED
);
188 GtkSalPrinter::StartJob(
189 const OUString
* const i_pFileName
,
190 const OUString
& i_rJobName
,
191 const OUString
& i_rAppName
,
192 ImplJobSetup
* io_pSetupData
,
193 vcl::PrinterController
& io_rController
)
195 if (!lcl_useSystemPrintDialog())
196 return PspSalPrinter::StartJob(i_pFileName
, i_rJobName
, i_rAppName
, io_pSetupData
, io_rController
);
200 m_xImpl
.reset(new GtkSalPrinter_Impl());
201 m_xImpl
->m_sJobName
= i_rJobName
;
205 sFileName
= OUStringToOString(*i_pFileName
, osl_getThreadTextEncoding());
207 GtkPrintDialog
aDialog(io_rController
);
210 io_rController
.abortJob();
213 aDialog
.updateControllerPrintRange();
214 m_xImpl
->m_pPrinter
= aDialog
.getPrinter();
215 m_xImpl
->m_pSettings
= aDialog
.getSettings();
217 //To-Do proper name, watch for encodings
218 sFileName
= OString("/tmp/hacking.ps");
219 m_xImpl
->m_sSpoolFile
= sFileName
;
221 OUString aFileName
= OStringToOUString(sFileName
, osl_getThreadTextEncoding());
223 //To-Do, swap ps/pdf for gtk_printer_accepts_ps()/gtk_printer_accepts_pdf() ?
225 return impl_doJob(&aFileName
, i_rJobName
, i_rAppName
, io_pSetupData
, /*bCollate*/false, io_rController
);
229 GtkSalPrinter::EndJob()
231 bool bRet
= PspSalPrinter::EndJob();
233 if (!lcl_useSystemPrintDialog())
238 if (!bRet
|| m_xImpl
->m_sSpoolFile
.isEmpty())
241 std::shared_ptr
<GtkPrintWrapper
> const xWrapper(lcl_getGtkSalInstance().getPrintWrapper());
243 GtkPageSetup
* pPageSetup
= xWrapper
->page_setup_new();
245 GtkPrintJob
* const pJob
= xWrapper
->print_job_new(
246 OUStringToOString(m_xImpl
->m_sJobName
, RTL_TEXTENCODING_UTF8
).getStr(),
247 m_xImpl
->m_pPrinter
, m_xImpl
->m_pSettings
, pPageSetup
);
249 GError
* error
= nullptr;
250 bRet
= xWrapper
->print_job_set_source_file(pJob
, m_xImpl
->m_sSpoolFile
.getStr(), &error
);
252 xWrapper
->print_job_send(pJob
, nullptr, nullptr, nullptr);
255 //To-Do, do something with this
256 fprintf(stderr
, "error was %s\n", error
->message
);
260 g_object_unref(pPageSetup
);
263 //To-Do, remove temp spool file
273 GtkWidget
* const io_pWidget
,
274 const uno::Sequence
<OUString
>& i_rHelpTexts
,
275 const sal_Int32 i_nIndex
)
277 if (i_nIndex
>= 0 && i_nIndex
< i_rHelpTexts
.getLength())
278 gtk_widget_set_tooltip_text(io_pWidget
,
279 OUStringToOString(i_rHelpTexts
.getConstArray()[i_nIndex
], RTL_TEXTENCODING_UTF8
).getStr());
284 GtkWidget
* const i_pChild
,
285 const OUString
&i_rText
,
286 const uno::Sequence
<OUString
> &i_rHelpTexts
,
287 sal_Int32
* const io_pCurHelpText
)
289 GtkWidget
* const pLabel
= gtk_label_new(nullptr);
290 lcl_setHelpText(pLabel
, i_rHelpTexts
, !io_pCurHelpText
? 0 : (*io_pCurHelpText
)++);
291 gtk_misc_set_alignment(GTK_MISC(pLabel
), 0.0, 0.5);
294 gchar
* const pText
= g_markup_printf_escaped("<b>%s</b>",
295 OUStringToOString(i_rText
, RTL_TEXTENCODING_UTF8
).getStr());
296 gtk_label_set_markup_with_mnemonic(GTK_LABEL(pLabel
), pText
);
300 GtkWidget
* const pFrame
= gtk_vbox_new(FALSE
, 6);
301 gtk_box_pack_start(GTK_BOX(pFrame
), pLabel
, FALSE
, FALSE
, 0);
303 GtkWidget
* const pAlignment
= gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
304 gtk_alignment_set_padding(GTK_ALIGNMENT(pAlignment
), 0, 0, 12, 0);
305 gtk_box_pack_start(GTK_BOX(pFrame
), pAlignment
, FALSE
, FALSE
, 0);
307 gtk_container_add(GTK_CONTAINER(pAlignment
), i_pChild
);
312 lcl_extractHelpTextsOrIds(
313 const beans::PropertyValue
& rEntry
,
314 uno::Sequence
<OUString
>& rHelpStrings
)
316 if (!(rEntry
.Value
>>= rHelpStrings
))
318 OUString aHelpString
;
319 if (rEntry
.Value
>>= aHelpString
)
321 rHelpStrings
.realloc(1);
322 *rHelpStrings
.getArray() = aHelpString
;
328 lcl_combo_box_text_new()
330 return gtk_combo_box_text_new();
334 lcl_combo_box_text_append(GtkWidget
* const pWidget
, gchar
const* const pText
)
336 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(pWidget
), pText
);
341 GtkPrintDialog::GtkPrintDialog(vcl::PrinterController
& io_rController
)
342 : m_rController(io_rController
)
343 , m_xWrapper(lcl_getGtkSalInstance().getPrintWrapper())
345 assert(m_xWrapper
->supportsPrinting());
347 impl_initCustomTab();
348 impl_readFromSettings();
352 GtkPrintDialog::impl_initDialog()
354 //To-Do, like fpicker, set UI language
355 m_pDialog
= m_xWrapper
->print_unix_dialog_new();
357 vcl::Window
* const pTopWindow(Application::GetActiveTopWindow());
360 GtkSalFrame
* const pFrame(dynamic_cast<GtkSalFrame
*>(pTopWindow
->ImplGetFrame()));
363 GtkWindow
* const pParent(GTK_WINDOW(pFrame
->getWindow()));
365 gtk_window_set_transient_for(GTK_WINDOW(m_pDialog
), pParent
);
369 m_xWrapper
->print_unix_dialog_set_manual_capabilities(GTK_PRINT_UNIX_DIALOG(m_pDialog
),
370 GtkPrintCapabilities(GTK_PRINT_CAPABILITY_COPIES
371 | GTK_PRINT_CAPABILITY_COLLATE
372 | GTK_PRINT_CAPABILITY_REVERSE
373 | GTK_PRINT_CAPABILITY_GENERATE_PS
374 | GTK_PRINT_CAPABILITY_NUMBER_UP
375 | GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT
380 GtkPrintDialog::impl_initCustomTab()
382 typedef std::vector
<std::pair
<GtkWidget
*, OUString
> > CustomTabs_t
;
384 const uno::Sequence
<beans::PropertyValue
>& rOptions(m_rController
.getUIOptions());
385 std::map
<OUString
, GtkWidget
*> aPropertyToDependencyRowMap
;
386 CustomTabs_t aCustomTabs
;
387 GtkWidget
* pCurParent
= nullptr;
388 GtkWidget
* pCurTabPage
= nullptr;
389 GtkWidget
* pCurSubGroup
= nullptr;
390 bool bIgnoreSubgroup
= false;
391 for (const auto& rOption
: rOptions
)
393 uno::Sequence
<beans::PropertyValue
> aOptProp
;
394 rOption
.Value
>>= aOptProp
;
398 OUString aPropertyName
;
399 uno::Sequence
<OUString
> aChoices
;
400 uno::Sequence
<sal_Bool
> aChoicesDisabled
;
401 uno::Sequence
<OUString
> aHelpTexts
;
402 sal_Int64 nMinValue
= 0, nMaxValue
= 0;
403 sal_Int32 nCurHelpText
= 0;
404 OUString aDependsOnName
;
405 sal_Int32 nDependsOnValue
= 0;
406 bool bUseDependencyRow
= false;
407 bool bIgnore
= false;
408 GtkWidget
* pGroup
= nullptr;
409 bool bGtkInternal
= false;
412 //Next options if this one is empty
413 if (!aOptProp
.hasElements())
416 for (const beans::PropertyValue
& rEntry
: std::as_const(aOptProp
))
418 if ( rEntry
.Name
== "Text" )
421 rEntry
.Value
>>= aValue
;
422 aText
= aValue
.replace('~', '_');
424 else if ( rEntry
.Name
== "ControlType" )
425 rEntry
.Value
>>= aCtrlType
;
426 else if ( rEntry
.Name
== "Choices" )
427 rEntry
.Value
>>= aChoices
;
428 else if ( rEntry
.Name
== "ChoicesDisabled" )
429 rEntry
.Value
>>= aChoicesDisabled
;
430 else if ( rEntry
.Name
== "Property" )
432 beans::PropertyValue aVal
;
433 rEntry
.Value
>>= aVal
;
434 aPropertyName
= aVal
.Name
;
436 else if ( rEntry
.Name
== "DependsOnName" )
437 rEntry
.Value
>>= aDependsOnName
;
438 else if ( rEntry
.Name
== "DependsOnEntry" )
439 rEntry
.Value
>>= nDependsOnValue
;
440 else if ( rEntry
.Name
== "AttachToDependency" )
441 rEntry
.Value
>>= bUseDependencyRow
;
442 else if ( rEntry
.Name
== "MinValue" )
443 rEntry
.Value
>>= nMinValue
;
444 else if ( rEntry
.Name
== "MaxValue" )
445 rEntry
.Value
>>= nMaxValue
;
446 else if ( rEntry
.Name
== "HelpId" )
448 uno::Sequence
<OUString
> aHelpIds
;
449 lcl_extractHelpTextsOrIds(rEntry
, aHelpIds
);
450 Help
* const pHelp
= Application::GetHelp();
453 const int nLen
= aHelpIds
.getLength();
454 aHelpTexts
.realloc(nLen
);
455 std::transform(aHelpIds
.begin(), aHelpIds
.end(), aHelpTexts
.begin(),
456 [&pHelp
](const OUString
& rHelpId
) { return pHelp
->GetHelpText(rHelpId
, static_cast<weld::Widget
*>(nullptr)); });
459 aHelpTexts
= aHelpIds
;
461 else if ( rEntry
.Name
== "HelpText" )
462 lcl_extractHelpTextsOrIds(rEntry
, aHelpTexts
);
463 else if ( rEntry
.Name
== "InternalUIOnly" )
464 rEntry
.Value
>>= bIgnore
;
465 else if ( rEntry
.Name
== "Enabled" )
467 // Ignore this. We use UIControlOptions::isUIOptionEnabled
468 // to check whether a control should be enabled.
470 else if ( rEntry
.Name
== "GroupingHint" )
472 // Ignore this. We cannot add/modify controls to/on existing
473 // tabs of the Gtk print dialog.
477 SAL_INFO("vcl.gtk", "unhandled UI option entry: " << rEntry
.Name
);
481 if ( aPropertyName
== "PrintContent" )
484 if (aCtrlType
== "Group" || !pCurParent
)
486 pCurTabPage
= gtk_vbox_new(FALSE
, 12);
487 gtk_container_set_border_width(GTK_CONTAINER(pCurTabPage
), 6);
488 lcl_setHelpText(pCurTabPage
, aHelpTexts
, 0);
490 pCurParent
= pCurTabPage
;
491 aCustomTabs
.emplace_back(pCurTabPage
, aText
);
493 else if (aCtrlType
== "Subgroup")
495 bIgnoreSubgroup
= bIgnore
;
498 pCurParent
= gtk_vbox_new(FALSE
, 12);
499 gtk_container_set_border_width(GTK_CONTAINER(pCurParent
), 0);
501 pCurSubGroup
= lcl_makeFrame(pCurParent
, aText
, aHelpTexts
, nullptr);
502 gtk_box_pack_start(GTK_BOX(pCurTabPage
), pCurSubGroup
, FALSE
, FALSE
, 0);
504 // special case: we need to map these to controls of the gtk print dialog
505 else if (bGtkInternal
)
507 if ( aPropertyName
== "PrintContent" )
509 // What to print? And, more importantly, is there a selection?
510 impl_initPrintContent(aChoicesDisabled
);
513 else if (bIgnoreSubgroup
|| bIgnore
)
517 // change handlers for all the controls set up in this block
518 // should be set _after_ the control has been made (in)active,
520 // 1. value of the property is _known_--we are using it to
521 // _set_ the control, right?--no need to change it back .-)
522 // 2. it may cause warning because the widget may not
523 // have been placed in m_aControlToPropertyMap yet
525 GtkWidget
* pWidget
= nullptr;
526 beans::PropertyValue
* pVal
= nullptr;
527 if (aCtrlType
== "Bool" && pCurParent
)
529 pWidget
= gtk_check_button_new_with_mnemonic(
530 OUStringToOString(aText
, RTL_TEXTENCODING_UTF8
).getStr());
531 lcl_setHelpText(pWidget
, aHelpTexts
, 0);
532 m_aControlToPropertyMap
[pWidget
] = aPropertyName
;
535 pVal
= m_rController
.getValue(aPropertyName
);
537 pVal
->Value
>>= bVal
;
538 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pWidget
), bVal
);
539 gtk_widget_set_sensitive(pWidget
,
540 m_rController
.isUIOptionEnabled(aPropertyName
) && pVal
!= nullptr);
541 g_signal_connect(pWidget
, "toggled", G_CALLBACK(GtkPrintDialog::UIOption_CheckHdl
), this);
543 else if (aCtrlType
== "Radio" && pCurParent
)
545 GtkWidget
* const pVbox
= gtk_vbox_new(FALSE
, 12);
546 gtk_container_set_border_width(GTK_CONTAINER(pVbox
), 0);
548 if (!aText
.isEmpty())
549 pGroup
= lcl_makeFrame(pVbox
, aText
, aHelpTexts
, &nCurHelpText
);
551 sal_Int32 nSelectVal
= 0;
552 pVal
= m_rController
.getValue(aPropertyName
);
553 if (pVal
&& pVal
->Value
.hasValue())
554 pVal
->Value
>>= nSelectVal
;
556 for (sal_Int32 m
= 0; m
!= aChoices
.getLength(); m
++)
558 pWidget
= gtk_radio_button_new_with_mnemonic_from_widget(
559 GTK_RADIO_BUTTON(m
== 0 ? nullptr : pWidget
),
560 OUStringToOString(aChoices
[m
].replace('~', '_'), RTL_TEXTENCODING_UTF8
).getStr());
561 lcl_setHelpText(pWidget
, aHelpTexts
, nCurHelpText
++);
562 m_aControlToPropertyMap
[pWidget
] = aPropertyName
;
563 m_aControlToNumValMap
[pWidget
] = m
;
564 GtkWidget
* const pRow
= gtk_hbox_new(FALSE
, 12);
565 gtk_box_pack_start(GTK_BOX(pVbox
), pRow
, FALSE
, FALSE
, 0);
566 gtk_box_pack_start(GTK_BOX(pRow
), pWidget
, FALSE
, FALSE
, 0);
567 aPropertyToDependencyRowMap
[aPropertyName
+ OUString::number(m
)] = pRow
;
568 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pWidget
), m
== nSelectVal
);
569 gtk_widget_set_sensitive(pWidget
,
570 m_rController
.isUIOptionEnabled(aPropertyName
) && pVal
!= nullptr);
571 g_signal_connect(pWidget
, "toggled",
572 G_CALLBACK(GtkPrintDialog::UIOption_RadioHdl
), this);
580 else if ((aCtrlType
== "List" ||
581 aCtrlType
== "Range" ||
585 GtkWidget
* const pHbox
= gtk_hbox_new(FALSE
, 12);
586 gtk_container_set_border_width(GTK_CONTAINER(pHbox
), 0);
588 if ( aCtrlType
== "List" )
590 pWidget
= lcl_combo_box_text_new();
592 for (const auto& rChoice
: std::as_const(aChoices
))
594 lcl_combo_box_text_append(pWidget
,
595 OUStringToOString(rChoice
, RTL_TEXTENCODING_UTF8
).getStr());
598 sal_Int32 nSelectVal
= 0;
599 pVal
= m_rController
.getValue(aPropertyName
);
600 if (pVal
&& pVal
->Value
.hasValue())
601 pVal
->Value
>>= nSelectVal
;
602 gtk_combo_box_set_active(GTK_COMBO_BOX(pWidget
), nSelectVal
);
603 g_signal_connect(pWidget
, "changed", G_CALLBACK(GtkPrintDialog::UIOption_SelectHdl
), this);
605 else if (aCtrlType
== "Edit" && pCurParent
)
607 pWidget
= gtk_entry_new();
610 pVal
= m_rController
.getValue(aPropertyName
);
611 if (pVal
&& pVal
->Value
.hasValue())
612 pVal
->Value
>>= aCurVal
;
613 gtk_entry_set_text(GTK_ENTRY(pWidget
),
614 OUStringToOString(aCurVal
, RTL_TEXTENCODING_UTF8
).getStr());
616 else if (aCtrlType
== "Range" && pCurParent
)
618 pWidget
= gtk_spin_button_new_with_range(nMinValue
, nMaxValue
, 1.0);
620 sal_Int64 nCurVal
= 0;
621 pVal
= m_rController
.getValue(aPropertyName
);
622 if (pVal
&& pVal
->Value
.hasValue())
623 pVal
->Value
>>= nCurVal
;
624 gtk_spin_button_set_value(GTK_SPIN_BUTTON(pWidget
), nCurVal
);
627 lcl_setHelpText(pWidget
, aHelpTexts
, 0);
628 m_aControlToPropertyMap
[pWidget
] = aPropertyName
;
630 gtk_widget_set_sensitive(pWidget
,
631 m_rController
.isUIOptionEnabled(aPropertyName
) && pVal
!= nullptr);
633 if (!aText
.isEmpty())
635 GtkWidget
* const pLabel
= gtk_label_new_with_mnemonic(
636 OUStringToOString(aText
, RTL_TEXTENCODING_UTF8
).getStr());
637 gtk_label_set_mnemonic_widget(GTK_LABEL(pLabel
), pWidget
);
638 gtk_box_pack_start(GTK_BOX(pHbox
), pLabel
, FALSE
, FALSE
, 0);
641 gtk_box_pack_start(GTK_BOX(pHbox
), pWidget
, FALSE
, FALSE
, 0);
647 SAL_INFO("vcl.gtk", "unhandled option type: " << aCtrlType
);
649 GtkWidget
* pRow
= nullptr;
652 if (bUseDependencyRow
&& !aDependsOnName
.isEmpty())
654 pRow
= aPropertyToDependencyRowMap
[aDependsOnName
+ OUString::number(nDependsOnValue
)];
657 gtk_widget_destroy(pWidget
);
666 pRow
= gtk_hbox_new(FALSE
, 12);
667 gtk_box_pack_start(GTK_BOX(pCurParent
), pRow
, FALSE
, FALSE
, 0);
670 aPropertyToDependencyRowMap
[aPropertyName
+ OUString::number(0)] = pRow
;
671 gtk_box_pack_start(GTK_BOX(pRow
), pWidget
, FALSE
, FALSE
, 0);
676 CustomTabs_t::const_reverse_iterator aEnd
= aCustomTabs
.rend();
677 for (CustomTabs_t::const_reverse_iterator aI
= aCustomTabs
.rbegin(); aI
!= aEnd
; ++aI
)
679 gtk_widget_show_all(aI
->first
);
680 m_xWrapper
->print_unix_dialog_add_custom_tab(GTK_PRINT_UNIX_DIALOG(m_pDialog
), aI
->first
,
681 gtk_label_new(OUStringToOString(aI
->second
, RTL_TEXTENCODING_UTF8
).getStr()));
686 GtkPrintDialog::impl_initPrintContent(uno::Sequence
<sal_Bool
> const& i_rDisabled
)
688 SAL_WARN_IF(i_rDisabled
.getLength() != 3, "vcl.gtk", "there is more choices than we expected");
689 if (i_rDisabled
.getLength() != 3)
692 GtkPrintUnixDialog
* const pDialog(GTK_PRINT_UNIX_DIALOG(m_pDialog
));
694 // XXX: This is a hack that depends on the number and the ordering of
695 // the controls in the rDisabled sequence (cf. the initialization of
696 // the "PrintContent" UI option in SwPrintUIOptions::SwPrintUIOptions,
697 // sw/source/core/view/printdata.cxx)
698 if (m_xWrapper
->supportsPrintSelection() && !i_rDisabled
[2])
700 m_xWrapper
->print_unix_dialog_set_support_selection(pDialog
, TRUE
);
701 m_xWrapper
->print_unix_dialog_set_has_selection(pDialog
, TRUE
);
704 beans::PropertyValue
* const pPrintContent(
705 m_rController
.getValue(OUString("PrintContent")));
709 sal_Int32
nSelectionType(0);
710 pPrintContent
->Value
>>= nSelectionType
;
711 GtkPrintSettings
* const pSettings(getSettings());
712 GtkPrintPages
ePrintPages(GTK_PRINT_PAGES_ALL
);
713 switch (nSelectionType
)
716 ePrintPages
= GTK_PRINT_PAGES_ALL
;
719 ePrintPages
= GTK_PRINT_PAGES_RANGES
;
722 if (m_xWrapper
->supportsPrintSelection())
723 ePrintPages
= GTK_PRINT_PAGES_SELECTION
;
725 SAL_INFO("vcl.gtk", "the application wants to print a selection, but the present gtk version does not support it");
728 SAL_WARN("vcl.gtk", "unexpected selection type: " << nSelectionType
);
730 m_xWrapper
->print_settings_set_print_pages(pSettings
, ePrintPages
);
731 m_xWrapper
->print_unix_dialog_set_settings(pDialog
, pSettings
);
732 g_object_unref(G_OBJECT(pSettings
));
737 GtkPrintDialog::impl_checkOptionalControlDependencies()
739 for (auto& rEntry
: m_aControlToPropertyMap
)
741 gtk_widget_set_sensitive(rEntry
.first
, m_rController
.isUIOptionEnabled(rEntry
.second
));
745 beans::PropertyValue
*
746 GtkPrintDialog::impl_queryPropertyValue(GtkWidget
* const i_pWidget
) const
748 beans::PropertyValue
* pVal(nullptr);
749 std::map
<GtkWidget
*, OUString
>::const_iterator
aIt(m_aControlToPropertyMap
.find(i_pWidget
));
750 if (aIt
!= m_aControlToPropertyMap
.end())
752 pVal
= m_rController
.getValue(aIt
->second
);
753 SAL_WARN_IF(!pVal
, "vcl.gtk", "property value not found");
757 SAL_WARN("vcl.gtk", "changed control not in property map");
763 GtkPrintDialog::impl_UIOption_CheckHdl(GtkWidget
* const i_pWidget
)
765 beans::PropertyValue
* const pVal
= impl_queryPropertyValue(i_pWidget
);
768 const bool bVal
= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(i_pWidget
));
769 pVal
->Value
<<= bVal
;
771 impl_checkOptionalControlDependencies();
776 GtkPrintDialog::impl_UIOption_RadioHdl(GtkWidget
* const i_pWidget
)
778 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(i_pWidget
)))
780 beans::PropertyValue
* const pVal
= impl_queryPropertyValue(i_pWidget
);
781 std::map
<GtkWidget
*, sal_Int32
>::const_iterator it
= m_aControlToNumValMap
.find(i_pWidget
);
782 if (pVal
&& it
!= m_aControlToNumValMap
.end())
785 const sal_Int32 nVal
= it
->second
;
786 pVal
->Value
<<= nVal
;
788 impl_checkOptionalControlDependencies();
794 GtkPrintDialog::impl_UIOption_SelectHdl(GtkWidget
* const i_pWidget
)
796 beans::PropertyValue
* const pVal
= impl_queryPropertyValue(i_pWidget
);
799 const sal_Int32
nVal(gtk_combo_box_get_active(GTK_COMBO_BOX(i_pWidget
)));
800 pVal
->Value
<<= nVal
;
802 impl_checkOptionalControlDependencies();
807 GtkPrintDialog::run()
810 bool bContinue
= true;
814 const gint nStatus
= gtk_dialog_run(GTK_DIALOG(m_pDialog
));
817 case GTK_RESPONSE_HELP
:
818 fprintf(stderr
, "To-Do: Help ?\n");
821 case GTK_RESPONSE_OK
:
828 gtk_widget_hide(m_pDialog
);
829 impl_storeToSettings();
834 GtkPrintDialog::updateControllerPrintRange()
836 GtkPrintSettings
* const pSettings(getSettings());
837 // TODO: use get_print_pages
838 if (const gchar
* const pStr
= m_xWrapper
->print_settings_get(pSettings
, GTK_PRINT_SETTINGS_PRINT_PAGES
))
840 beans::PropertyValue
* pVal
= m_rController
.getValue(OUString("PrintRange"));
842 pVal
= m_rController
.getValue(OUString("PrintContent"));
843 SAL_WARN_IF(!pVal
, "vcl.gtk", "Nothing to map standard print options to!");
847 if (!strcmp(pStr
, "all"))
849 else if (!strcmp(pStr
, "ranges"))
851 else if (!strcmp(pStr
, "selection"))
853 pVal
->Value
<<= nVal
;
857 pVal
= m_rController
.getValue(OUString("PageRange"));
858 SAL_WARN_IF(!pVal
, "vcl.gtk", "PageRange doesn't exist!");
863 const GtkPageRange
* const pRanges
= m_xWrapper
->print_settings_get_page_ranges(pSettings
, &num_ranges
);
864 for (gint i
= 0; i
!= num_ranges
&& pRanges
; ++i
)
866 sBuf
.append(sal_Int32(pRanges
[i
].start
+1));
867 if (pRanges
[i
].start
!= pRanges
[i
].end
)
870 sBuf
.append(sal_Int32(pRanges
[i
].end
+1));
873 if (i
!= num_ranges
-1)
876 pVal
->Value
<<= sBuf
.makeStringAndClear();
881 g_object_unref(G_OBJECT(pSettings
));
884 GtkPrintDialog::~GtkPrintDialog()
886 gtk_widget_destroy(m_pDialog
);
890 GtkPrintDialog::impl_readFromSettings()
892 vcl::SettingsConfigItem
* const pItem(vcl::SettingsConfigItem::get());
893 GtkPrintSettings
* const pSettings(getSettings());
895 const OUString
aPrintDialogStr("PrintDialog");
896 const OUString
aCopyCount(pItem
->getValue(aPrintDialogStr
,
898 const OUString
aCollate(pItem
->getValue(aPrintDialogStr
,
901 const gint
nOldCopyCount(m_xWrapper
->print_settings_get_n_copies(pSettings
));
902 const sal_Int32
nCopyCount(aCopyCount
.toInt32());
903 if (nCopyCount
> 0 && nOldCopyCount
!= nCopyCount
)
905 m_xWrapper
->print_settings_set_n_copies(pSettings
, sal::static_int_cast
<gint
>(nCopyCount
));
908 const bool bOldCollate(m_xWrapper
->print_settings_get_collate(pSettings
));
909 const bool bCollate(aCollate
.equalsIgnoreAsciiCase("true"));
910 if (bOldCollate
!= bCollate
)
912 m_xWrapper
->print_settings_set_collate(pSettings
, bCollate
);
915 m_xWrapper
->print_unix_dialog_set_settings(GTK_PRINT_UNIX_DIALOG(m_pDialog
), pSettings
);
916 g_object_unref(G_OBJECT(pSettings
));
920 GtkPrintDialog::impl_storeToSettings()
923 vcl::SettingsConfigItem
* const pItem(vcl::SettingsConfigItem::get());
924 GtkPrintSettings
* const pSettings(getSettings());
926 const OUString
aPrintDialogStr("PrintDialog");
927 pItem
->setValue(aPrintDialogStr
,
929 OUString::number(m_xWrapper
->print_settings_get_n_copies(pSettings
)));
930 pItem
->setValue(aPrintDialogStr
,
932 m_xWrapper
->print_settings_get_collate(pSettings
)
936 // pItem->setValue(aPrintDialog, OUString("ToFile"), );
937 g_object_unref(G_OBJECT(pSettings
));
942 GtkSalInfoPrinter::GetCapabilities(
943 const ImplJobSetup
* const i_pSetupData
,
944 const PrinterCapType i_nType
)
946 if (i_nType
== PrinterCapType::ExternalDialog
&& lcl_useSystemPrintDialog())
948 return PspSalInfoPrinter::GetCapabilities(i_pSetupData
, i_nType
);
951 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */