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 "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 <comphelper/processfactory.hxx>
27 #include <com/sun/star/beans/PropertyValue.hpp>
28 #include <com/sun/star/container/XNamed.hpp>
29 #include <com/sun/star/document/XExporter.hpp>
30 #include <com/sun/star/document/XFilter.hpp>
31 #include <com/sun/star/frame/XFrame.hpp>
32 #include <com/sun/star/io/XOutputStream.hpp>
33 #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
34 #include <com/sun/star/sheet/XSpreadsheet.hpp>
35 #include <com/sun/star/sheet/XSpreadsheetView.hpp>
36 #include <com/sun/star/view/PrintableState.hpp>
37 #include <com/sun/star/view/XSelectionSupplier.hpp>
39 #include <officecfg/Office/Common.hxx>
41 #include <rtl/ustring.hxx>
43 #include <unotools/streamwrap.hxx>
48 namespace frame
= com::sun::star::frame
;
49 namespace beans
= com::sun::star::beans
;
50 namespace container
= com::sun::star::container
;
51 namespace uno
= com::sun::star::uno
;
52 namespace document
= com::sun::star::document
;
53 namespace sheet
= com::sun::star::sheet
;
54 namespace io
= com::sun::star::io
;
55 namespace view
= com::sun::star::view
;
57 using vcl::unx::GtkPrintWrapper
;
64 GtkPrintDialog(vcl::PrinterController
& io_rController
);
66 GtkPrinter
* getPrinter() const
68 return m_xWrapper
->print_unix_dialog_get_selected_printer(GTK_PRINT_UNIX_DIALOG(m_pDialog
));
70 GtkPrintSettings
* getSettings() const
72 return m_xWrapper
->print_unix_dialog_get_settings(GTK_PRINT_UNIX_DIALOG(m_pDialog
));
74 void updateControllerPrintRange();
76 void ExportAsPDF(const OUString
&rFileURL
, GtkPrintSettings
* pSettings
) const;
80 static void UIOption_CheckHdl(GtkWidget
* i_pWidget
, GtkPrintDialog
* io_pThis
)
82 io_pThis
->impl_UIOption_CheckHdl(i_pWidget
);
84 static void UIOption_RadioHdl(GtkWidget
* i_pWidget
, GtkPrintDialog
* io_pThis
)
86 io_pThis
->impl_UIOption_RadioHdl(i_pWidget
);
88 static void UIOption_SelectHdl(GtkWidget
* i_pWidget
, GtkPrintDialog
* io_pThis
)
90 io_pThis
->impl_UIOption_SelectHdl(i_pWidget
);
94 beans::PropertyValue
* impl_queryPropertyValue(GtkWidget
* i_pWidget
) const;
95 void impl_checkOptionalControlDependencies();
97 void impl_UIOption_CheckHdl(GtkWidget
* i_pWidget
);
98 void impl_UIOption_RadioHdl(GtkWidget
* i_pWidget
);
99 void impl_UIOption_SelectHdl(GtkWidget
* i_pWidget
);
101 void impl_initDialog();
102 void impl_initCustomTab();
103 void impl_initPrintContent(uno::Sequence
<sal_Bool
> const& i_rDisabled
);
105 void impl_readFromSettings();
106 void impl_storeToSettings() const;
109 GtkWidget
* m_pDialog
;
110 vcl::PrinterController
& m_rController
;
111 std::map
<GtkWidget
*, OUString
> m_aControlToPropertyMap
;
112 std::map
<GtkWidget
*, sal_Int32
> m_aControlToNumValMap
;
113 std::shared_ptr
<GtkPrintWrapper
> m_xWrapper
;
116 struct GtkSalPrinter_Impl
118 OString m_sSpoolFile
;
120 GtkPrinter
* m_pPrinter
;
121 GtkPrintSettings
* m_pSettings
;
123 GtkSalPrinter_Impl();
124 ~GtkSalPrinter_Impl();
127 GtkSalPrinter_Impl::GtkSalPrinter_Impl()
133 GtkSalPrinter_Impl::~GtkSalPrinter_Impl()
137 g_object_unref(G_OBJECT(m_pPrinter
));
142 g_object_unref(G_OBJECT(m_pSettings
));
150 static GtkInstance
const&
151 lcl_getGtkSalInstance()
153 // we _know_ this is GtkInstance
154 return *static_cast<GtkInstance
*>(GetGtkSalData()->m_pInstance
);
158 lcl_useSystemPrintDialog()
160 return officecfg::Office::Common::Misc::UseSystemPrintDialog::get()
161 && officecfg::Office::Common::Misc::ExperimentalMode::get()
162 && lcl_getGtkSalInstance().getPrintWrapper()->supportsPrinting();
167 GtkSalPrinter::GtkSalPrinter(SalInfoPrinter
* const i_pInfoPrinter
)
168 : PspSalPrinter(i_pInfoPrinter
)
173 GtkSalPrinter::impl_doJob(
174 const OUString
* const i_pFileName
,
175 const OUString
& i_rJobName
,
176 const OUString
& i_rAppName
,
177 ImplJobSetup
* const io_pSetupData
,
179 const bool i_bCollate
,
180 vcl::PrinterController
& io_rController
)
182 io_rController
.setJobState(view::PrintableState_JOB_STARTED
);
183 io_rController
.jobStarted();
184 const bool bJobStarted(
185 PspSalPrinter::StartJob(i_pFileName
, i_rJobName
, i_rAppName
,
186 i_nCopies
, i_bCollate
, true, io_pSetupData
))
191 io_rController
.createProgressDialog();
192 const int nPages(io_rController
.getFilteredPageCount());
193 for (int nPage(0); nPage
!= nPages
; ++nPage
)
195 if (nPage
== nPages
- 1)
196 io_rController
.setLastPage(true);
197 io_rController
.printFilteredPage(nPage
);
199 io_rController
.setJobState(view::PrintableState_JOB_COMPLETED
);
206 GtkSalPrinter::StartJob(
207 const OUString
* const i_pFileName
,
208 const OUString
& i_rJobName
,
209 const OUString
& i_rAppName
,
210 ImplJobSetup
* io_pSetupData
,
211 vcl::PrinterController
& io_rController
)
213 if (!lcl_useSystemPrintDialog())
214 return PspSalPrinter::StartJob(i_pFileName
, i_rJobName
, i_rAppName
, io_pSetupData
, io_rController
);
218 m_xImpl
.reset(new GtkSalPrinter_Impl());
219 m_xImpl
->m_sJobName
= i_rJobName
;
223 sFileName
= OUStringToOString(*i_pFileName
, osl_getThreadTextEncoding());
225 GtkPrintDialog
aDialog(io_rController
);
228 io_rController
.abortJob();
231 aDialog
.updateControllerPrintRange();
232 m_xImpl
->m_pPrinter
= aDialog
.getPrinter();
233 m_xImpl
->m_pSettings
= aDialog
.getSettings();
236 if (const gchar
*uri
= gtk_print_settings_get(m_xImpl
->m_pSettings
, GTK_PRINT_SETTINGS_OUTPUT_URI
))
238 const gchar
*pStr
= gtk_print_settings_get(m_xImpl
->m_pSettings
, GTK_PRINT_SETTINGS_OUTPUT_FILE_FORMAT
);
239 if (pStr
&& !strcmp(pStr
, "pdf"))
241 aDialog
.ExportAsPDF(OUString((const sal_Char
*)uri
, strlen((const sal_Char
*)uri
), RTL_TEXTENCODING_UTF8
), m_xImpl
->m_pSettings
);
250 bool bCollate
= false;
252 //To-Do proper name, watch for encodings
253 sFileName
= OString("/tmp/hacking.ps");
254 m_xImpl
->m_sSpoolFile
= sFileName
;
256 OUString aFileName
= OStringToOUString(sFileName
, osl_getThreadTextEncoding());
258 //To-Do, swap ps/pdf for gtk_printer_accepts_ps()/gtk_printer_accepts_pdf() ?
260 return impl_doJob(&aFileName
, i_rJobName
, i_rAppName
, io_pSetupData
, nCopies
, bCollate
, io_rController
);
264 GtkSalPrinter::EndJob()
266 bool bRet
= PspSalPrinter::EndJob();
268 if (!lcl_useSystemPrintDialog())
273 if (!bRet
|| m_xImpl
->m_sSpoolFile
.isEmpty())
276 std::shared_ptr
<GtkPrintWrapper
> const xWrapper(lcl_getGtkSalInstance().getPrintWrapper());
278 GtkPageSetup
* pPageSetup
= xWrapper
->page_setup_new();
281 gtk_page_setup_set_orientation(pPageSetup
,);
282 gtk_page_setup_set_paper_size(pPageSetup
,);
283 gtk_page_setup_set_top_margin(pPageSetup
,);
284 gtk_page_setup_set_bottom_margin(pPageSetup
,);
285 gtk_page_setup_set_left_margin(pPageSetup
,);
286 gtk_page_setup_set_right_margin(pPageSetup
,);
289 GtkPrintJob
* const pJob
= xWrapper
->print_job_new(
290 OUStringToOString(m_xImpl
->m_sJobName
, RTL_TEXTENCODING_UTF8
).getStr(),
291 m_xImpl
->m_pPrinter
, m_xImpl
->m_pSettings
, pPageSetup
);
293 GError
* error
= NULL
;
294 bRet
= xWrapper
->print_job_set_source_file(pJob
, m_xImpl
->m_sSpoolFile
.getStr(), &error
);
296 xWrapper
->print_job_send(pJob
, NULL
, NULL
, NULL
);
299 //To-Do, do something with this
300 fprintf(stderr
, "error was %s\n", error
->message
);
304 g_object_unref(pPageSetup
);
307 //To-Do, remove temp spool file
317 GtkWidget
* const io_pWidget
,
318 const uno::Sequence
<OUString
>& i_rHelpTexts
,
319 const sal_Int32 i_nIndex
)
321 #if GTK_CHECK_VERSION(2,12,0)
322 if (i_nIndex
>= 0 && i_nIndex
< i_rHelpTexts
.getLength())
323 gtk_widget_set_tooltip_text(io_pWidget
,
324 OUStringToOString(i_rHelpTexts
.getConstArray()[i_nIndex
], RTL_TEXTENCODING_UTF8
).getStr());
334 GtkWidget
* const i_pChild
,
335 const OUString
&i_rText
,
336 const uno::Sequence
<OUString
> &i_rHelpTexts
,
337 sal_Int32
* const io_pCurHelpText
)
339 GtkWidget
* const pLabel
= gtk_label_new(NULL
);
340 lcl_setHelpText(pLabel
, i_rHelpTexts
, !io_pCurHelpText
? 0 : (*io_pCurHelpText
)++);
341 gtk_misc_set_alignment(GTK_MISC(pLabel
), 0.0, 0.5);
344 gchar
* const pText
= g_markup_printf_escaped("<b>%s</b>",
345 OUStringToOString(i_rText
, RTL_TEXTENCODING_UTF8
).getStr());
346 gtk_label_set_markup_with_mnemonic(GTK_LABEL(pLabel
), pText
);
350 GtkWidget
* const pFrame
= gtk_vbox_new(FALSE
, 6);
351 gtk_box_pack_start(GTK_BOX(pFrame
), pLabel
, FALSE
, FALSE
, 0);
353 GtkWidget
* const pAlignment
= gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
354 gtk_alignment_set_padding(GTK_ALIGNMENT(pAlignment
), 0, 0, 12, 0);
355 gtk_box_pack_start(GTK_BOX(pFrame
), pAlignment
, FALSE
, FALSE
, 0);
357 gtk_container_add(GTK_CONTAINER(pAlignment
), i_pChild
);
362 lcl_extractHelpTextsOrIds(
363 const beans::PropertyValue
& rEntry
,
364 uno::Sequence
<OUString
>& rHelpStrings
)
366 if (!(rEntry
.Value
>>= rHelpStrings
))
368 OUString aHelpString
;
369 if ((rEntry
.Value
>>= aHelpString
))
371 rHelpStrings
.realloc(1);
372 *rHelpStrings
.getArray() = aHelpString
;
378 lcl_combo_box_text_new()
380 #if GTK_CHECK_VERSION(3,0,0)
381 return gtk_combo_box_text_new();
383 return gtk_combo_box_new_text();
388 lcl_combo_box_text_append(GtkWidget
* const pWidget
, gchar
const* const pText
)
390 #if GTK_CHECK_VERSION(3,0,0)
391 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(pWidget
), pText
);
393 gtk_combo_box_append_text(GTK_COMBO_BOX(pWidget
), pText
);
399 GtkPrintDialog::GtkPrintDialog(vcl::PrinterController
& io_rController
)
400 : m_rController(io_rController
)
401 , m_xWrapper(lcl_getGtkSalInstance().getPrintWrapper())
403 assert(m_xWrapper
->supportsPrinting());
405 impl_initCustomTab();
406 impl_readFromSettings();
410 GtkPrintDialog::impl_initDialog()
412 //To-Do, like fpicker, set UI language
413 m_pDialog
= m_xWrapper
->print_unix_dialog_new(NULL
, NULL
);
415 vcl::Window
* const pTopWindow(Application::GetActiveTopWindow());
418 GtkSalFrame
* const pFrame(dynamic_cast<GtkSalFrame
*>(pTopWindow
->ImplGetFrame()));
421 GtkWindow
* const pParent(GTK_WINDOW(pFrame
->getWindow()));
423 gtk_window_set_transient_for(GTK_WINDOW(m_pDialog
), pParent
);
427 m_xWrapper
->print_unix_dialog_set_manual_capabilities(GTK_PRINT_UNIX_DIALOG(m_pDialog
),
428 GtkPrintCapabilities(GTK_PRINT_CAPABILITY_COPIES
429 | GTK_PRINT_CAPABILITY_COLLATE
430 | GTK_PRINT_CAPABILITY_REVERSE
431 | GTK_PRINT_CAPABILITY_GENERATE_PS
432 #if GTK_CHECK_VERSION(2,12,0)
433 | GTK_PRINT_CAPABILITY_NUMBER_UP
435 #if GTK_CHECK_VERSION(2,14,0)
436 | GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT
442 GtkPrintDialog::impl_initCustomTab()
444 typedef std::map
<OUString
, GtkWidget
*> DependencyMap_t
;
445 typedef std::vector
<std::pair
<GtkWidget
*, OUString
> > CustomTabs_t
;
447 const uno::Sequence
<beans::PropertyValue
>& rOptions(m_rController
.getUIOptions());
448 DependencyMap_t aPropertyToDependencyRowMap
;
449 CustomTabs_t aCustomTabs
;
450 GtkWidget
* pCurParent
= NULL
;
451 GtkWidget
* pCurTabPage
= NULL
;
452 GtkWidget
* pCurSubGroup
= NULL
;
453 GtkWidget
* pStandardPrintRangeContainer
= NULL
;
454 bool bIgnoreSubgroup
= false;
455 for (int i
= 0; i
!= rOptions
.getLength(); i
++)
457 uno::Sequence
<beans::PropertyValue
> aOptProp
;
458 rOptions
[i
].Value
>>= aOptProp
;
462 OUString aPropertyName
;
463 uno::Sequence
<OUString
> aChoices
;
464 uno::Sequence
<sal_Bool
> aChoicesDisabled
;
465 uno::Sequence
<OUString
> aHelpTexts
;
466 sal_Int64 nMinValue
= 0, nMaxValue
= 0;
467 sal_Int32 nCurHelpText
= 0;
468 OUString aDependsOnName
;
469 sal_Int32 nDependsOnValue
= 0;
470 bool bUseDependencyRow
= false;
471 bool bIgnore
= false;
472 GtkWidget
* pGroup
= NULL
;
473 bool bGtkInternal
= false;
476 //Next options if this one is empty
477 if ( aOptProp
.getLength() == 0)
480 for (int n
= 0; n
!= aOptProp
.getLength(); n
++)
482 const beans::PropertyValue
& rEntry(aOptProp
[ n
]);
483 if ( rEntry
.Name
== "Text" )
486 rEntry
.Value
>>= aValue
;
487 aText
= aValue
.replace('~', '_');
489 else if ( rEntry
.Name
== "ControlType" )
490 rEntry
.Value
>>= aCtrlType
;
491 else if ( rEntry
.Name
== "Choices" )
492 rEntry
.Value
>>= aChoices
;
493 else if ( rEntry
.Name
== "ChoicesDisabled" )
494 rEntry
.Value
>>= aChoicesDisabled
;
495 else if ( rEntry
.Name
== "Property" )
497 beans::PropertyValue aVal
;
498 rEntry
.Value
>>= aVal
;
499 aPropertyName
= aVal
.Name
;
501 else if ( rEntry
.Name
== "DependsOnName" )
502 rEntry
.Value
>>= aDependsOnName
;
503 else if ( rEntry
.Name
== "DependsOnEntry" )
504 rEntry
.Value
>>= nDependsOnValue
;
505 else if ( rEntry
.Name
== "AttachToDependency" )
506 rEntry
.Value
>>= bUseDependencyRow
;
507 else if ( rEntry
.Name
== "MinValue" )
508 rEntry
.Value
>>= nMinValue
;
509 else if ( rEntry
.Name
== "MaxValue" )
510 rEntry
.Value
>>= nMaxValue
;
511 else if ( rEntry
.Name
== "HelpId" )
513 uno::Sequence
<OUString
> aHelpIds
;
514 lcl_extractHelpTextsOrIds(rEntry
, aHelpIds
);
515 Help
* const pHelp
= Application::GetHelp();
518 const int nLen
= aHelpIds
.getLength();
519 aHelpTexts
.realloc(nLen
);
520 for (int j
= 0; j
!= nLen
; ++j
)
521 aHelpTexts
[j
] = pHelp
->GetHelpText(aHelpIds
[j
], 0);
524 aHelpTexts
= aHelpIds
;
526 else if ( rEntry
.Name
== "HelpText" )
527 lcl_extractHelpTextsOrIds(rEntry
, aHelpTexts
);
528 else if ( rEntry
.Name
== "InternalUIOnly" )
529 rEntry
.Value
>>= bIgnore
;
530 else if ( rEntry
.Name
== "Enabled" )
532 // Ignore this. We use UIControlOptions::isUIOptionEnabled
533 // to check whether a control should be enabled.
535 else if ( rEntry
.Name
== "GroupingHint" )
537 // Ignore this. We cannot add/modify controls to/on existing
538 // tabs of the Gtk print dialog.
542 SAL_INFO("vcl.gtk", "unhandled UI option entry: " << rEntry
.Name
);
546 if ( aPropertyName
== "PrintContent" )
549 if (aCtrlType
== "Group" || !pCurParent
)
551 pCurTabPage
= gtk_vbox_new(FALSE
, 12);
552 gtk_container_set_border_width(GTK_CONTAINER(pCurTabPage
), 6);
553 lcl_setHelpText(pCurTabPage
, aHelpTexts
, 0);
555 pCurParent
= pCurTabPage
;
556 aCustomTabs
.push_back(std::make_pair(pCurTabPage
, aText
));
558 else if (aCtrlType
== "Subgroup" && (pCurParent
/*|| bOnJobPageValue*/))
560 bIgnoreSubgroup
= bIgnore
;
563 pCurParent
= gtk_vbox_new(FALSE
, 12);
564 gtk_container_set_border_width(GTK_CONTAINER(pCurParent
), 0);
566 pCurSubGroup
= lcl_makeFrame(pCurParent
, aText
, aHelpTexts
, NULL
);
567 gtk_box_pack_start(GTK_BOX(pCurTabPage
), pCurSubGroup
, FALSE
, FALSE
, 0);
569 // special case: we need to map these to controls of the gtk print dialog
570 else if (bGtkInternal
)
572 if ( aPropertyName
== "PrintContent" )
574 // What to print? And, more importantly, is there a selection?
575 impl_initPrintContent(aChoicesDisabled
);
578 else if (bIgnoreSubgroup
|| bIgnore
)
582 // change handlers for all the controls set up in this block
583 // should be set _after_ the control has been made (in)active,
585 // 1. value of the property is _known_--we are using it to
586 // _set_ the control, right?--no need to change it back .-)
587 // 2. it may cause warning because the widget may not
588 // have been placed in m_aControlToPropertyMap yet
590 GtkWidget
* pWidget
= NULL
;
591 beans::PropertyValue
* pVal
= NULL
;
592 if (aCtrlType
== "Bool" && pCurParent
)
594 pWidget
= gtk_check_button_new_with_mnemonic(
595 OUStringToOString(aText
, RTL_TEXTENCODING_UTF8
).getStr());
596 lcl_setHelpText(pWidget
, aHelpTexts
, 0);
597 m_aControlToPropertyMap
[pWidget
] = aPropertyName
;
600 pVal
= m_rController
.getValue(aPropertyName
);
602 pVal
->Value
>>= bVal
;
603 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pWidget
), bVal
);
604 gtk_widget_set_sensitive(pWidget
,
605 m_rController
.isUIOptionEnabled(aPropertyName
) && pVal
!= NULL
);
606 g_signal_connect(pWidget
, "toggled", G_CALLBACK(GtkPrintDialog::UIOption_CheckHdl
), this);
608 else if (aCtrlType
== "Radio" && pCurParent
)
610 GtkWidget
* const pVbox
= gtk_vbox_new(FALSE
, 12);
611 gtk_container_set_border_width(GTK_CONTAINER(pVbox
), 0);
613 if (!aText
.isEmpty())
614 pGroup
= lcl_makeFrame(pVbox
, aText
, aHelpTexts
, &nCurHelpText
);
616 sal_Int32 nSelectVal
= 0;
617 pVal
= m_rController
.getValue(aPropertyName
);
618 if (pVal
&& pVal
->Value
.hasValue())
619 pVal
->Value
>>= nSelectVal
;
621 for (sal_Int32 m
= 0; m
!= aChoices
.getLength(); m
++)
623 pWidget
= gtk_radio_button_new_with_mnemonic_from_widget(
624 GTK_RADIO_BUTTON(m
== 0 ? NULL
: pWidget
),
625 OUStringToOString(aChoices
[m
].replace('~', '_'), RTL_TEXTENCODING_UTF8
).getStr());
626 lcl_setHelpText(pWidget
, aHelpTexts
, nCurHelpText
++);
627 m_aControlToPropertyMap
[pWidget
] = aPropertyName
;
628 m_aControlToNumValMap
[pWidget
] = m
;
629 GtkWidget
* const pRow
= gtk_hbox_new(FALSE
, 12);
630 gtk_box_pack_start(GTK_BOX(pVbox
), pRow
, FALSE
, FALSE
, 0);
631 gtk_box_pack_start(GTK_BOX(pRow
), pWidget
, FALSE
, FALSE
, 0);
632 aPropertyToDependencyRowMap
[aPropertyName
+ OUString::number(m
)] = pRow
;
633 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pWidget
), m
== nSelectVal
);
634 gtk_widget_set_sensitive(pWidget
,
635 m_rController
.isUIOptionEnabled(aPropertyName
) && pVal
!= NULL
);
636 g_signal_connect(pWidget
, "toggled",
637 G_CALLBACK(GtkPrintDialog::UIOption_RadioHdl
), this);
645 else if ((aCtrlType
== "List" ||
646 aCtrlType
== "Range" ||
650 GtkWidget
* const pHbox
= gtk_hbox_new(FALSE
, 12);
651 gtk_container_set_border_width(GTK_CONTAINER(pHbox
), 0);
653 if ( aCtrlType
== "List" )
655 pWidget
= lcl_combo_box_text_new();
657 for (sal_Int32 m
= 0; m
!= aChoices
.getLength(); m
++)
659 lcl_combo_box_text_append(pWidget
,
660 OUStringToOString(aChoices
[m
], RTL_TEXTENCODING_UTF8
).getStr());
663 sal_Int32 nSelectVal
= 0;
664 pVal
= m_rController
.getValue(aPropertyName
);
665 if (pVal
&& pVal
->Value
.hasValue())
666 pVal
->Value
>>= nSelectVal
;
667 gtk_combo_box_set_active(GTK_COMBO_BOX(pWidget
), nSelectVal
);
668 g_signal_connect(pWidget
, "changed", G_CALLBACK(GtkPrintDialog::UIOption_SelectHdl
), this);
670 else if (aCtrlType
== "Edit" && pCurParent
)
672 pWidget
= gtk_entry_new();
675 pVal
= m_rController
.getValue(aPropertyName
);
676 if (pVal
&& pVal
->Value
.hasValue())
677 pVal
->Value
>>= aCurVal
;
678 gtk_entry_set_text(GTK_ENTRY(pWidget
),
679 OUStringToOString(aCurVal
, RTL_TEXTENCODING_UTF8
).getStr());
681 else if (aCtrlType
== "Range" && pCurParent
)
683 pWidget
= gtk_spin_button_new_with_range(nMinValue
, nMaxValue
, 1.0);
685 sal_Int64 nCurVal
= 0;
686 pVal
= m_rController
.getValue(aPropertyName
);
687 if (pVal
&& pVal
->Value
.hasValue())
688 pVal
->Value
>>= nCurVal
;
689 gtk_spin_button_set_value(GTK_SPIN_BUTTON(pWidget
), nCurVal
);
692 lcl_setHelpText(pWidget
, aHelpTexts
, 0);
693 m_aControlToPropertyMap
[pWidget
] = aPropertyName
;
695 gtk_widget_set_sensitive(pWidget
,
696 m_rController
.isUIOptionEnabled(aPropertyName
) && pVal
!= NULL
);
698 if (!aText
.isEmpty())
700 GtkWidget
* const pLabel
= gtk_label_new_with_mnemonic(
701 OUStringToOString(aText
, RTL_TEXTENCODING_UTF8
).getStr());
702 gtk_label_set_mnemonic_widget(GTK_LABEL(pLabel
), pWidget
);
703 gtk_box_pack_start(GTK_BOX(pHbox
), pLabel
, FALSE
, FALSE
, 0);
706 gtk_box_pack_start(GTK_BOX(pHbox
), pWidget
, FALSE
, FALSE
, 0);
712 SAL_INFO("vcl.gtk", "unhandled option type: " << aCtrlType
);
714 GtkWidget
* pRow
= NULL
;
717 if (bUseDependencyRow
&& !aDependsOnName
.isEmpty())
719 pRow
= aPropertyToDependencyRowMap
[aDependsOnName
+ OUString::number(nDependsOnValue
)];
722 gtk_widget_destroy(pWidget
);
731 pRow
= gtk_hbox_new(FALSE
, 12);
732 gtk_box_pack_start(GTK_BOX(pCurParent
), pRow
, FALSE
, FALSE
, 0);
735 aPropertyToDependencyRowMap
[aPropertyName
+ OUString::number(0)] = pRow
;
736 gtk_box_pack_start(GTK_BOX(pRow
), pWidget
, FALSE
, FALSE
, 0);
741 if (pStandardPrintRangeContainer
)
742 gtk_widget_destroy(pStandardPrintRangeContainer
);
744 CustomTabs_t::const_reverse_iterator aEnd
= aCustomTabs
.rend();
745 for (CustomTabs_t::const_reverse_iterator aI
= aCustomTabs
.rbegin(); aI
!= aEnd
; ++aI
)
747 gtk_widget_show_all(aI
->first
);
748 m_xWrapper
->print_unix_dialog_add_custom_tab(GTK_PRINT_UNIX_DIALOG(m_pDialog
), aI
->first
,
749 gtk_label_new(OUStringToOString(aI
->second
, RTL_TEXTENCODING_UTF8
).getStr()));
754 GtkPrintDialog::impl_initPrintContent(uno::Sequence
<sal_Bool
> const& i_rDisabled
)
756 SAL_WARN_IF(i_rDisabled
.getLength() != 3, "vcl.gtk", "there is more choices than we expected");
757 if (i_rDisabled
.getLength() != 3)
760 GtkPrintUnixDialog
* const pDialog(GTK_PRINT_UNIX_DIALOG(m_pDialog
));
762 // XXX: This is a hack that depends on the number and the ordering of
763 // the controls in the rDisabled sequence (cf. the intialization of
764 // the "PrintContent" UI option in SwPrintUIOptions::SwPrintUIOptions,
765 // sw/source/core/view/printdata.cxx)
766 if (m_xWrapper
->supportsPrintSelection() && !i_rDisabled
[2])
768 m_xWrapper
->print_unix_dialog_set_support_selection(pDialog
, TRUE
);
769 m_xWrapper
->print_unix_dialog_set_has_selection(pDialog
, TRUE
);
772 beans::PropertyValue
* const pPrintContent(
773 m_rController
.getValue(OUString("PrintContent")));
777 sal_Int32
nSelectionType(0);
778 pPrintContent
->Value
>>= nSelectionType
;
779 GtkPrintSettings
* const pSettings(getSettings());
780 GtkPrintPages
ePrintPages(GTK_PRINT_PAGES_ALL
);
781 switch (nSelectionType
)
784 ePrintPages
= GTK_PRINT_PAGES_ALL
;
787 ePrintPages
= GTK_PRINT_PAGES_RANGES
;
790 #if GTK_CHECK_VERSION(2,14,0)
791 if (m_xWrapper
->supportsPrintSelection())
792 ePrintPages
= GTK_PRINT_PAGES_SELECTION
;
795 SAL_INFO("vcl.gtk", "the application wants to print a selection, but the present gtk version does not support it");
798 SAL_WARN("vcl.gtk", "unexpected selection type: " << nSelectionType
);
800 m_xWrapper
->print_settings_set_print_pages(pSettings
, ePrintPages
);
801 m_xWrapper
->print_unix_dialog_set_settings(pDialog
, pSettings
);
802 g_object_unref(G_OBJECT(pSettings
));
807 GtkPrintDialog::impl_checkOptionalControlDependencies()
809 for (std::map
<GtkWidget
*, OUString
>::iterator it
= m_aControlToPropertyMap
.begin();
810 it
!= m_aControlToPropertyMap
.end(); ++it
)
812 gtk_widget_set_sensitive(it
->first
, m_rController
.isUIOptionEnabled(it
->second
));
816 beans::PropertyValue
*
817 GtkPrintDialog::impl_queryPropertyValue(GtkWidget
* const i_pWidget
) const
819 beans::PropertyValue
* pVal(0);
820 std::map
<GtkWidget
*, OUString
>::const_iterator
aIt(m_aControlToPropertyMap
.find(i_pWidget
));
821 if (aIt
!= m_aControlToPropertyMap
.end())
823 pVal
= m_rController
.getValue(aIt
->second
);
824 SAL_WARN_IF(!pVal
, "vcl.gtk", "property value not found");
828 SAL_WARN("vcl.gtk", "changed control not in property map");
834 GtkPrintDialog::impl_UIOption_CheckHdl(GtkWidget
* const i_pWidget
)
836 beans::PropertyValue
* const pVal
= impl_queryPropertyValue(i_pWidget
);
839 const bool bVal
= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(i_pWidget
));
840 pVal
->Value
<<= bVal
;
842 impl_checkOptionalControlDependencies();
847 GtkPrintDialog::impl_UIOption_RadioHdl(GtkWidget
* const i_pWidget
)
849 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(i_pWidget
)))
851 beans::PropertyValue
* const pVal
= impl_queryPropertyValue(i_pWidget
);
852 std::map
<GtkWidget
*, sal_Int32
>::const_iterator it
= m_aControlToNumValMap
.find(i_pWidget
);
853 if (pVal
&& it
!= m_aControlToNumValMap
.end())
856 const sal_Int32 nVal
= it
->second
;
857 pVal
->Value
<<= nVal
;
859 impl_checkOptionalControlDependencies();
865 GtkPrintDialog::impl_UIOption_SelectHdl(GtkWidget
* const i_pWidget
)
867 beans::PropertyValue
* const pVal
= impl_queryPropertyValue(i_pWidget
);
870 const sal_Int32
nVal(gtk_combo_box_get_active(GTK_COMBO_BOX(i_pWidget
)));
871 pVal
->Value
<<= nVal
;
873 impl_checkOptionalControlDependencies();
878 GtkPrintDialog::run()
881 bool bContinue
= true;
885 const gint nStatus
= gtk_dialog_run(GTK_DIALOG(m_pDialog
));
888 case GTK_RESPONSE_HELP
:
889 fprintf(stderr
, "To-Do: Help ?\n");
892 case GTK_RESPONSE_OK
:
899 gtk_widget_hide(m_pDialog
);
900 impl_storeToSettings();
905 void GtkPrintDialog::ExportAsPDF(const OUString
&rFileURL
, GtkPrintSettings
*pSettings
) const
907 uno::Reference
< XDesktop2
> xDesktop
= Desktop::create( ::comphelper::getProcessComponentContext() );
908 uno::Reference
< XFrame
> xFrame(xDesktop
->getActiveFrame());
910 xFrame
= uno::Reference
< XFrame
>(xDesktop
, UNO_QUERY
);
912 uno::Reference
< XFilter
> xFilter(
913 ::comphelper::getProcessServiceFactory()->createInstance("com.sun.star.document.PDFFilter"),
918 uno::Reference
< XController
> xController
;
919 uno::Reference
< XComponent
> xDoc
;
921 xController
= xFrame
->getController();
922 if (xController
.is())
923 xDoc
= uno::Reference
< XComponent
>(xController
->getModel(), UNO_QUERY
);
925 SvFileStream
aStream(rFileURL
, STREAM_READWRITE
| StreamMode::SHARE_DENYWRITE
| StreamMode::TRUNC
);
926 uno::Reference
< XOutputStream
> xOStm(new utl::OOutputStreamWrapper(aStream
));
928 uno::Reference
< XExporter
> xExport(xFilter
, UNO_QUERY
);
929 xExport
->setSourceDocument(xDoc
);
930 uno::Sequence
<beans::PropertyValue
> aFilterData(2);
931 aFilterData
[0].Name
= "PageLayout";
932 aFilterData
[0].Value
<<= sal_Int32(0);
933 aFilterData
[1].Name
= "FirstPageOnLeft";
934 aFilterData
[1].Value
<<= sal_False
;
936 const gchar
*pStr
= gtk_print_settings_get(pSettings
, GTK_PRINT_SETTINGS_PRINT_PAGES
);
937 if (pStr
&& !strcmp(pStr
, "ranges"))
941 const GtkPageRange
* pRanges
= gtk_print_settings_get_page_ranges(pSettings
, &num_ranges
);
942 for (gint i
= 0; i
< num_ranges
; ++i
)
944 aRangeText
.Append(OUString::number(pRanges
[i
].start
+1));
945 if (pRanges
[i
].start
!= pRanges
[i
].end
)
947 aRangeText
.AppendAscii("-");
948 aRangeText
.Append(OUString::number(pRanges
[i
].end
+1));
951 if (i
!= num_ranges
-1)
952 aRangeText
.AppendAscii(",");
954 aFilterData
.realloc(aFilterData
.getLength()+1);
955 aFilterData
[aFilterData
.getLength()-1].Name
= "PageRange";
956 aFilterData
[aFilterData
.getLength()-1].Value
<<= OUString(aRangeText
);
958 else if (pStr
&& !strcmp(pStr
, "current"))
962 uno::Reference
< XSpreadsheetView
> xSpreadsheetView
;
963 uno::Reference
< XSpreadsheet
> xSheet
;
964 uno::Reference
< XSpreadsheetDocument
> xSheetDoc
;
965 uno::Reference
< XIndexAccess
> xSheets
;
966 uno::Reference
< XNamed
> xName
;
968 if (xController
.is())
969 xSpreadsheetView
= uno::Reference
< XSpreadsheetView
>(xController
, UNO_QUERY
);
970 if (xSpreadsheetView
.is())
971 xSheet
= uno::Reference
< XSpreadsheet
>(xSpreadsheetView
->getActiveSheet());
973 xName
= uno::Reference
< XNamed
>(xSheet
, UNO_QUERY
);
975 xSheetDoc
= uno::Reference
< XSpreadsheetDocument
>(xController
->getModel(), UNO_QUERY
);
977 xSheets
= uno::Reference
< XIndexAccess
>(xSheetDoc
->getSheets(), UNO_QUERY
);
980 const OUString
&rName
= xName
->getName();
984 for (i
= 0; i
< xSheets
->getCount(); ++i
)
986 uno::Reference
< XNamed
> xItem
=
987 uno::Reference
< XNamed
>(xSheets
->getByIndex(i
), UNO_QUERY
);
988 if (rName
== xItem
->getName())
992 if (i
< xSheets
->getCount())
994 aFilterData
.realloc(aFilterData
.getLength()+1);
995 aFilterData
[aFilterData
.getLength()-1].Name
= "PageRange";
996 aFilterData
[aFilterData
.getLength()-1].Value
<<= OUString(OUString::number(i
+ 1));
1002 #if GTK_CHECK_VERSION(2,17,5)
1003 if (gtk_print_unix_dialog_get_has_selection(GTK_PRINT_UNIX_DIALOG(m_pDialog
)))
1005 uno::Any aSelection
;
1008 if (xController
.is())
1010 uno::Reference
<view::XSelectionSupplier
> xView(xController
, UNO_QUERY
);
1012 xView
->getSelection() >>= aSelection
;
1015 catch (const uno::RuntimeException
&)
1018 if (aSelection
.hasValue())
1020 aFilterData
.realloc(aFilterData
.getLength()+1);
1021 aFilterData
[aFilterData
.getLength()-1].Name
= "Selection";
1022 aFilterData
[aFilterData
.getLength()-1].Value
<<= aSelection
;
1026 uno::Sequence
<beans::PropertyValue
> aArgs(2);
1027 aArgs
[0].Name
= "FilterData";
1028 aArgs
[0].Value
<<= aFilterData
;
1029 aArgs
[1].Name
= "OutputStream";
1030 aArgs
[1].Value
<<= xOStm
;
1031 xFilter
->filter(aArgs
);
1037 GtkPrintDialog::updateControllerPrintRange()
1039 GtkPrintSettings
* const pSettings(getSettings());
1040 // TODO: use get_print_pages
1041 if (const gchar
* const pStr
= m_xWrapper
->print_settings_get(pSettings
, GTK_PRINT_SETTINGS_PRINT_PAGES
))
1043 beans::PropertyValue
* pVal
= m_rController
.getValue(OUString("PrintRange"));
1045 pVal
= m_rController
.getValue(OUString("PrintContent"));
1046 SAL_WARN_IF(!pVal
, "vcl.gtk", "Nothing to map standard print options to!");
1050 if (!strcmp(pStr
, "all"))
1052 else if (!strcmp(pStr
, "ranges"))
1054 else if (!strcmp(pStr
, "selection"))
1056 pVal
->Value
<<= nVal
;
1060 pVal
= m_rController
.getValue(OUString("PageRange"));
1061 SAL_WARN_IF(!pVal
, "vcl.gtk", "PageRange doesn't exist!");
1064 OUStringBuffer sBuf
;
1066 const GtkPageRange
* const pRanges
= m_xWrapper
->print_settings_get_page_ranges(pSettings
, &num_ranges
);
1067 for (gint i
= 0; i
!= num_ranges
&& pRanges
; ++i
)
1069 sBuf
.append(sal_Int32(pRanges
[i
].start
+1));
1070 if (pRanges
[i
].start
!= pRanges
[i
].end
)
1073 sBuf
.append(sal_Int32(pRanges
[i
].end
+1));
1076 if (i
!= num_ranges
-1)
1079 pVal
->Value
<<= sBuf
.makeStringAndClear();
1084 g_object_unref(G_OBJECT(pSettings
));
1087 GtkPrintDialog::~GtkPrintDialog()
1089 gtk_widget_destroy(m_pDialog
);
1093 GtkPrintDialog::impl_readFromSettings()
1095 vcl::SettingsConfigItem
* const pItem(vcl::SettingsConfigItem::get());
1096 GtkPrintSettings
* const pSettings(getSettings());
1098 const OUString
aPrintDialogStr("PrintDialog");
1099 const OUString
aCopyCount(pItem
->getValue(aPrintDialogStr
,
1100 OUString("CopyCount")));
1101 const OUString
aCollate(pItem
->getValue(aPrintDialogStr
,
1102 OUString("Collate")));
1104 bool bChanged(false);
1106 const gint
nOldCopyCount(m_xWrapper
->print_settings_get_n_copies(pSettings
));
1107 const sal_Int32
nCopyCount(aCopyCount
.toInt32());
1108 if (nCopyCount
> 0 && nOldCopyCount
!= nCopyCount
)
1111 m_xWrapper
->print_settings_set_n_copies(pSettings
, sal::static_int_cast
<gint
>(nCopyCount
));
1114 const bool bOldCollate(m_xWrapper
->print_settings_get_collate(pSettings
));
1115 const bool bCollate(aCollate
.equalsIgnoreAsciiCase("true"));
1116 if (bOldCollate
!= bCollate
)
1119 m_xWrapper
->print_settings_set_collate(pSettings
, bCollate
);
1121 // TODO: wth was this var. meant for?
1124 m_xWrapper
->print_unix_dialog_set_settings(GTK_PRINT_UNIX_DIALOG(m_pDialog
), pSettings
);
1125 g_object_unref(G_OBJECT(pSettings
));
1129 GtkPrintDialog::impl_storeToSettings()
1132 vcl::SettingsConfigItem
* const pItem(vcl::SettingsConfigItem::get());
1133 GtkPrintSettings
* const pSettings(getSettings());
1135 const OUString
aPrintDialogStr("PrintDialog");
1136 pItem
->setValue(aPrintDialogStr
,
1137 OUString("CopyCount"),
1138 OUString::number(m_xWrapper
->print_settings_get_n_copies(pSettings
)));
1139 pItem
->setValue(aPrintDialogStr
,
1140 OUString("Collate"),
1141 m_xWrapper
->print_settings_get_collate(pSettings
)
1143 : OUString("false"))
1145 // pItem->setValue(aPrintDialog, OUString("ToFile"), );
1146 g_object_unref(G_OBJECT(pSettings
));
1151 GtkSalInfoPrinter::GetCapabilities(
1152 const ImplJobSetup
* const i_pSetupData
,
1153 const sal_uInt16 i_nType
)
1155 if (i_nType
== PRINTER_CAPABILITIES_EXTERNALDIALOG
&& lcl_useSystemPrintDialog())
1157 return PspSalInfoPrinter::GetCapabilities(i_pSetupData
, i_nType
);
1160 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */