Branch libreoffice-5-0-4
[LibreOffice.git] / vcl / unx / gtk / gdi / salprn-gtk.cxx
blob650276c3a1f4ad1842d2c13cd6996460bc99122f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/.
8 */
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"
23 #include <gtk/gtk.h>
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>
45 #include <cstring>
46 #include <map>
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;
59 using uno::UNO_QUERY;
61 class GtkPrintDialog
63 public:
64 GtkPrintDialog(vcl::PrinterController& io_rController);
65 bool run();
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();
75 #if 0
76 void ExportAsPDF(const OUString &rFileURL, GtkPrintSettings* pSettings) const;
77 #endif
78 ~GtkPrintDialog();
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);
93 private:
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;
108 private:
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;
119 OUString m_sJobName;
120 GtkPrinter* m_pPrinter;
121 GtkPrintSettings* m_pSettings;
123 GtkSalPrinter_Impl();
124 ~GtkSalPrinter_Impl();
127 GtkSalPrinter_Impl::GtkSalPrinter_Impl()
128 : m_pPrinter(0)
129 , m_pSettings(0)
133 GtkSalPrinter_Impl::~GtkSalPrinter_Impl()
135 if (m_pPrinter)
137 g_object_unref(G_OBJECT(m_pPrinter));
138 m_pPrinter = NULL;
140 if (m_pSettings)
142 g_object_unref(G_OBJECT(m_pSettings));
143 m_pSettings = NULL;
147 namespace
150 static GtkInstance const&
151 lcl_getGtkSalInstance()
153 // we _know_ this is GtkInstance
154 return *static_cast<GtkInstance*>(GetGtkSalData()->m_pInstance);
157 static bool
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)
172 bool
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,
178 const int i_nCopies,
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))
189 if (bJobStarted)
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);
202 return bJobStarted;
205 bool
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);
216 assert(!m_xImpl);
218 m_xImpl.reset(new GtkSalPrinter_Impl());
219 m_xImpl->m_sJobName = i_rJobName;
221 OString sFileName;
222 if (i_pFileName)
223 sFileName = OUStringToOString(*i_pFileName, osl_getThreadTextEncoding());
225 GtkPrintDialog aDialog(io_rController);
226 if (!aDialog.run())
228 io_rController.abortJob();
229 return false;
231 aDialog.updateControllerPrintRange();
232 m_xImpl->m_pPrinter = aDialog.getPrinter();
233 m_xImpl->m_pSettings = aDialog.getSettings();
235 #if 0
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);
242 bDoJob = false;
246 if (!bDoJob)
247 return false;
248 #endif
249 int nCopies = 1;
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);
263 bool
264 GtkSalPrinter::EndJob()
266 bool bRet = PspSalPrinter::EndJob();
268 if (!lcl_useSystemPrintDialog())
269 return bRet;
271 assert(m_xImpl);
273 if (!bRet || m_xImpl->m_sSpoolFile.isEmpty())
274 return bRet;
276 std::shared_ptr<GtkPrintWrapper> const xWrapper(lcl_getGtkSalInstance().getPrintWrapper());
278 GtkPageSetup* pPageSetup = xWrapper->page_setup_new();
279 #if 0
280 //todo
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,);
287 #endif
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);
295 if (bRet)
296 xWrapper->print_job_send(pJob, NULL, NULL, NULL);
297 else
299 //To-Do, do something with this
300 fprintf(stderr, "error was %s\n", error->message);
301 g_error_free(error);
304 g_object_unref(pPageSetup);
305 m_xImpl.reset();
307 //To-Do, remove temp spool file
309 return bRet;
312 namespace
315 static void
316 lcl_setHelpText(
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());
325 #else
326 (void)io_pWidget;
327 (void)i_rHelpTexts;
328 (void)i_nIndex;
329 #endif
332 static GtkWidget*
333 lcl_makeFrame(
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);
347 g_free(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);
358 return pFrame;
361 static void
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;
377 static GtkWidget*
378 lcl_combo_box_text_new()
380 #if GTK_CHECK_VERSION(3,0,0)
381 return gtk_combo_box_text_new();
382 #else
383 return gtk_combo_box_new_text();
384 #endif
387 static void
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);
392 #else
393 gtk_combo_box_append_text(GTK_COMBO_BOX(pWidget), pText);
394 #endif
399 GtkPrintDialog::GtkPrintDialog(vcl::PrinterController& io_rController)
400 : m_rController(io_rController)
401 , m_xWrapper(lcl_getGtkSalInstance().getPrintWrapper())
403 assert(m_xWrapper->supportsPrinting());
404 impl_initDialog();
405 impl_initCustomTab();
406 impl_readFromSettings();
409 void
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());
416 if (pTopWindow)
418 GtkSalFrame* const pFrame(dynamic_cast<GtkSalFrame*>(pTopWindow->ImplGetFrame()));
419 if (pFrame)
421 GtkWindow* const pParent(GTK_WINDOW(pFrame->getWindow()));
422 if (pParent)
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
434 #endif
435 #if GTK_CHECK_VERSION(2,14,0)
436 | GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT
437 #endif
441 void
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;
460 OUString aCtrlType;
461 OUString aText;
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;
475 //Fix fdo#69381
476 //Next options if this one is empty
477 if ( aOptProp.getLength() == 0)
478 continue;
480 for (int n = 0; n != aOptProp.getLength(); n++)
482 const beans::PropertyValue& rEntry(aOptProp[ n ]);
483 if ( rEntry.Name == "Text" )
485 OUString aValue;
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();
516 if (pHelp)
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);
523 else // fallback
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.
540 else
542 SAL_INFO("vcl.gtk", "unhandled UI option entry: " << rEntry.Name);
546 if ( aPropertyName == "PrintContent" )
547 bGtkInternal = true;
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;
561 if (bIgnore)
562 continue;
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)
579 continue;
580 else
582 // change handlers for all the controls set up in this block
583 // should be set _after_ the control has been made (in)active,
584 // because:
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;
599 bool bVal = false;
600 pVal = m_rController.getValue(aPropertyName);
601 if (pVal)
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);
640 if (pGroup)
641 pWidget = pGroup;
642 else
643 pWidget = pVbox;
645 else if ((aCtrlType == "List" ||
646 aCtrlType == "Range" ||
647 aCtrlType == "Edit"
648 ) && pCurParent)
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();
674 OUString aCurVal;
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);
708 pWidget = pHbox;
711 else
712 SAL_INFO("vcl.gtk", "unhandled option type: " << aCtrlType);
714 GtkWidget* pRow = NULL;
715 if (pWidget)
717 if (bUseDependencyRow && !aDependsOnName.isEmpty())
719 pRow = aPropertyToDependencyRowMap[aDependsOnName + OUString::number(nDependsOnValue)];
720 if (!pRow)
722 gtk_widget_destroy(pWidget);
723 pWidget = NULL;
727 if (pWidget)
729 if (!pRow)
731 pRow = gtk_hbox_new(FALSE, 12);
732 gtk_box_pack_start(GTK_BOX(pCurParent), pRow, FALSE, FALSE, 0);
734 if (!pGroup)
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()));
753 void
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)
758 return;
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")));
775 if (pPrintContent)
777 sal_Int32 nSelectionType(0);
778 pPrintContent->Value >>= nSelectionType;
779 GtkPrintSettings* const pSettings(getSettings());
780 GtkPrintPages ePrintPages(GTK_PRINT_PAGES_ALL);
781 switch (nSelectionType)
783 case 0:
784 ePrintPages = GTK_PRINT_PAGES_ALL;
785 break;
786 case 1:
787 ePrintPages = GTK_PRINT_PAGES_RANGES;
788 break;
789 case 2:
790 #if GTK_CHECK_VERSION(2,14,0)
791 if (m_xWrapper->supportsPrintSelection())
792 ePrintPages = GTK_PRINT_PAGES_SELECTION;
793 else
794 #endif
795 SAL_INFO("vcl.gtk", "the application wants to print a selection, but the present gtk version does not support it");
796 break;
797 default:
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));
806 void
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");
826 else
828 SAL_WARN("vcl.gtk", "changed control not in property map");
830 return pVal;
833 void
834 GtkPrintDialog::impl_UIOption_CheckHdl(GtkWidget* const i_pWidget)
836 beans::PropertyValue* const pVal = impl_queryPropertyValue(i_pWidget);
837 if (pVal)
839 const bool bVal = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(i_pWidget));
840 pVal->Value <<= bVal;
842 impl_checkOptionalControlDependencies();
846 void
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();
864 void
865 GtkPrintDialog::impl_UIOption_SelectHdl(GtkWidget* const i_pWidget)
867 beans::PropertyValue* const pVal = impl_queryPropertyValue(i_pWidget);
868 if (pVal)
870 const sal_Int32 nVal(gtk_combo_box_get_active(GTK_COMBO_BOX(i_pWidget)));
871 pVal->Value <<= nVal;
873 impl_checkOptionalControlDependencies();
877 bool
878 GtkPrintDialog::run()
880 bool bDoJob = false;
881 bool bContinue = true;
882 while (bContinue)
884 bContinue = false;
885 const gint nStatus = gtk_dialog_run(GTK_DIALOG(m_pDialog));
886 switch (nStatus)
888 case GTK_RESPONSE_HELP:
889 fprintf(stderr, "To-Do: Help ?\n");
890 bContinue = true;
891 break;
892 case GTK_RESPONSE_OK:
893 bDoJob = true;
894 break;
895 default:
896 break;
899 gtk_widget_hide(m_pDialog);
900 impl_storeToSettings();
901 return bDoJob;
904 #if 0
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());
909 if (!xFrame.is())
910 xFrame = uno::Reference < XFrame >(xDesktop, UNO_QUERY);
912 uno::Reference < XFilter > xFilter(
913 ::comphelper::getProcessServiceFactory()->createInstance("com.sun.star.document.PDFFilter"),
914 UNO_QUERY);
916 if (xFilter.is())
918 uno::Reference< XController > xController;
919 uno::Reference< XComponent > xDoc;
920 if (xFrame.is())
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"))
939 String aRangeText;
940 gint num_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());
972 if (xSheet.is())
973 xName = uno::Reference < XNamed >(xSheet, UNO_QUERY);
974 if (xName.is())
975 xSheetDoc = uno::Reference< XSpreadsheetDocument >(xController->getModel(), UNO_QUERY);
976 if (xSheetDoc.is())
977 xSheets = uno::Reference< XIndexAccess >(xSheetDoc->getSheets(), UNO_QUERY);
978 if (xSheets.is())
980 const OUString &rName = xName->getName();
982 sal_Int32 i;
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())
989 break;
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));
1000 catch (...) {}
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);
1011 if (xView.is())
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;
1025 #endif
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);
1034 #endif
1036 void
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"));
1044 if (!pVal)
1045 pVal = m_rController.getValue(OUString("PrintContent"));
1046 SAL_WARN_IF(!pVal, "vcl.gtk", "Nothing to map standard print options to!");
1047 if (pVal)
1049 sal_Int32 nVal = 0;
1050 if (!strcmp(pStr, "all"))
1051 nVal = 0;
1052 else if (!strcmp(pStr, "ranges"))
1053 nVal = 1;
1054 else if (!strcmp(pStr, "selection"))
1055 nVal = 2;
1056 pVal->Value <<= nVal;
1058 if (nVal == 1)
1060 pVal = m_rController.getValue(OUString("PageRange"));
1061 SAL_WARN_IF(!pVal, "vcl.gtk", "PageRange doesn't exist!");
1062 if (pVal)
1064 OUStringBuffer sBuf;
1065 gint num_ranges;
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)
1072 sBuf.append('-');
1073 sBuf.append(sal_Int32(pRanges[i].end+1));
1076 if (i != num_ranges-1)
1077 sBuf.append(',');
1079 pVal->Value <<= sBuf.makeStringAndClear();
1084 g_object_unref(G_OBJECT(pSettings));
1087 GtkPrintDialog::~GtkPrintDialog()
1089 gtk_widget_destroy(m_pDialog);
1092 void
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)
1110 bChanged = true;
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)
1118 bChanged = true;
1119 m_xWrapper->print_settings_set_collate(pSettings, bCollate);
1121 // TODO: wth was this var. meant for?
1122 (void) bChanged;
1124 m_xWrapper->print_unix_dialog_set_settings(GTK_PRINT_UNIX_DIALOG(m_pDialog), pSettings);
1125 g_object_unref(G_OBJECT(pSettings));
1128 void
1129 GtkPrintDialog::impl_storeToSettings()
1130 const
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)
1142 ? OUString("true")
1143 : OUString("false"))
1145 // pItem->setValue(aPrintDialog, OUString("ToFile"), );
1146 g_object_unref(G_OBJECT(pSettings));
1147 pItem->Commit();
1150 sal_uLong
1151 GtkSalInfoPrinter::GetCapabilities(
1152 const ImplJobSetup* const i_pSetupData,
1153 const sal_uInt16 i_nType)
1155 if (i_nType == PRINTER_CAPABILITIES_EXTERNALDIALOG && lcl_useSystemPrintDialog())
1156 return 1;
1157 return PspSalInfoPrinter::GetCapabilities(i_pSetupData, i_nType);
1160 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */