diff options
Diffstat (limited to 'vcl/unx/gtk3/gtk3salprn-gtk.cxx')
-rw-r--r-- | vcl/unx/gtk3/gtk3salprn-gtk.cxx | 954 |
1 files changed, 954 insertions, 0 deletions
diff --git a/vcl/unx/gtk3/gtk3salprn-gtk.cxx b/vcl/unx/gtk3/gtk3salprn-gtk.cxx new file mode 100644 index 000000000..62e88c919 --- /dev/null +++ b/vcl/unx/gtk3/gtk3salprn-gtk.cxx @@ -0,0 +1,954 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <unx/gtk/gtkprintwrapper.hxx> + +#include <unx/gtk/gtkdata.hxx> +#include <unx/gtk/gtkframe.hxx> +#include <unx/gtk/gtkinst.hxx> +#include <unx/gtk/gtkprn.hxx> + +#include <configsettings.hxx> +#include <vcl/help.hxx> +#include <vcl/print.hxx> +#include <vcl/svapp.hxx> +#include <vcl/window.hxx> + +#include <gtk/gtk.h> + +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/view/PrintableState.hpp> + +#include <officecfg/Office/Common.hxx> + +#include <rtl/ustrbuf.hxx> +#include <rtl/ustring.hxx> +#include <sal/log.hxx> + +#include <cstring> +#include <map> + +namespace beans = com::sun::star::beans; +namespace uno = com::sun::star::uno; +namespace view = com::sun::star::view; + +using vcl::unx::GtkPrintWrapper; + +namespace { + +class GtkPrintDialog +{ +public: + explicit GtkPrintDialog(vcl::PrinterController& io_rController); + bool run(); + GtkPrinter* getPrinter() const + { + return m_xWrapper->print_unix_dialog_get_selected_printer(GTK_PRINT_UNIX_DIALOG(m_pDialog)); + } + GtkPrintSettings* getSettings() const + { + return m_xWrapper->print_unix_dialog_get_settings(GTK_PRINT_UNIX_DIALOG(m_pDialog)); + } + void updateControllerPrintRange(); + + ~GtkPrintDialog(); + + static void UIOption_CheckHdl(GtkWidget* i_pWidget, GtkPrintDialog* io_pThis) + { + io_pThis->impl_UIOption_CheckHdl(i_pWidget); + } + static void UIOption_RadioHdl(GtkWidget* i_pWidget, GtkPrintDialog* io_pThis) + { + io_pThis->impl_UIOption_RadioHdl(i_pWidget); + } + static void UIOption_SelectHdl(GtkWidget* i_pWidget, GtkPrintDialog* io_pThis) + { + io_pThis->impl_UIOption_SelectHdl(i_pWidget); + } + +private: + beans::PropertyValue* impl_queryPropertyValue(GtkWidget* i_pWidget) const; + void impl_checkOptionalControlDependencies(); + + void impl_UIOption_CheckHdl(GtkWidget* i_pWidget); + void impl_UIOption_RadioHdl(GtkWidget* i_pWidget); + void impl_UIOption_SelectHdl(GtkWidget* i_pWidget); + + void impl_initDialog(); + void impl_initCustomTab(); + void impl_initPrintContent(uno::Sequence<sal_Bool> const& i_rDisabled); + + void impl_readFromSettings(); + void impl_storeToSettings() const; + +private: + GtkWidget* m_pDialog; + vcl::PrinterController& m_rController; + std::map<GtkWidget*, OUString> m_aControlToPropertyMap; + std::map<GtkWidget*, sal_Int32> m_aControlToNumValMap; + std::shared_ptr<GtkPrintWrapper> m_xWrapper; +}; + +} + +struct GtkSalPrinter_Impl +{ + OString m_sSpoolFile; + OUString m_sJobName; + GtkPrinter* m_pPrinter; + GtkPrintSettings* m_pSettings; + + GtkSalPrinter_Impl(); + ~GtkSalPrinter_Impl(); +}; + +GtkSalPrinter_Impl::GtkSalPrinter_Impl() + : m_pPrinter(nullptr) + , m_pSettings(nullptr) +{ +} + +GtkSalPrinter_Impl::~GtkSalPrinter_Impl() +{ + if (m_pPrinter) + { + g_object_unref(G_OBJECT(m_pPrinter)); + m_pPrinter = nullptr; + } + if (m_pSettings) + { + g_object_unref(G_OBJECT(m_pSettings)); + m_pSettings = nullptr; + } +} + +namespace +{ + +GtkInstance const& +lcl_getGtkSalInstance() +{ + // we _know_ this is GtkInstance + return *static_cast<GtkInstance*>(GetGtkSalData()->m_pInstance); +} + +bool +lcl_useSystemPrintDialog() +{ + return officecfg::Office::Common::Misc::UseSystemPrintDialog::get() + && officecfg::Office::Common::Misc::ExperimentalMode::get() + && lcl_getGtkSalInstance().getPrintWrapper()->supportsPrinting(); +} + +} + +GtkSalPrinter::GtkSalPrinter(SalInfoPrinter* const i_pInfoPrinter) + : PspSalPrinter(i_pInfoPrinter) +{ +} + +GtkSalPrinter::~GtkSalPrinter() = default; + +bool +GtkSalPrinter::impl_doJob( + const OUString* const i_pFileName, + const OUString& i_rJobName, + const OUString& i_rAppName, + ImplJobSetup* const io_pSetupData, + const bool i_bCollate, + vcl::PrinterController& io_rController) +{ + io_rController.setJobState(view::PrintableState_JOB_STARTED); + io_rController.jobStarted(); + const bool bJobStarted( + PspSalPrinter::StartJob(i_pFileName, i_rJobName, i_rAppName, + 1/*i_nCopies*/, i_bCollate, true, io_pSetupData)) + ; + + if (bJobStarted) + { + io_rController.createProgressDialog(); + const int nPages(io_rController.getFilteredPageCount()); + for (int nPage(0); nPage != nPages; ++nPage) + { + if (nPage == nPages - 1) + io_rController.setLastPage(true); + io_rController.printFilteredPage(nPage); + } + io_rController.setJobState(view::PrintableState_JOB_COMPLETED); + } + + return bJobStarted; +} + +bool +GtkSalPrinter::StartJob( + const OUString* const i_pFileName, + const OUString& i_rJobName, + const OUString& i_rAppName, + ImplJobSetup* io_pSetupData, + vcl::PrinterController& io_rController) +{ + if (!lcl_useSystemPrintDialog()) + return PspSalPrinter::StartJob(i_pFileName, i_rJobName, i_rAppName, io_pSetupData, io_rController); + + assert(!m_xImpl); + + m_xImpl.reset(new GtkSalPrinter_Impl()); + m_xImpl->m_sJobName = i_rJobName; + + OString sFileName; + if (i_pFileName) + sFileName = OUStringToOString(*i_pFileName, osl_getThreadTextEncoding()); + + GtkPrintDialog aDialog(io_rController); + if (!aDialog.run()) + { + io_rController.abortJob(); + return false; + } + aDialog.updateControllerPrintRange(); + m_xImpl->m_pPrinter = aDialog.getPrinter(); + m_xImpl->m_pSettings = aDialog.getSettings(); + + //To-Do proper name, watch for encodings + sFileName = OString("/tmp/hacking.ps"); + m_xImpl->m_sSpoolFile = sFileName; + + OUString aFileName = OStringToOUString(sFileName, osl_getThreadTextEncoding()); + + //To-Do, swap ps/pdf for gtk_printer_accepts_ps()/gtk_printer_accepts_pdf() ? + + return impl_doJob(&aFileName, i_rJobName, i_rAppName, io_pSetupData, /*bCollate*/false, io_rController); +} + +bool +GtkSalPrinter::EndJob() +{ + bool bRet = PspSalPrinter::EndJob(); + + if (!lcl_useSystemPrintDialog()) + return bRet; + + assert(m_xImpl); + + if (!bRet || m_xImpl->m_sSpoolFile.isEmpty()) + return bRet; + + std::shared_ptr<GtkPrintWrapper> const xWrapper(lcl_getGtkSalInstance().getPrintWrapper()); + + GtkPageSetup* pPageSetup = xWrapper->page_setup_new(); + + GtkPrintJob* const pJob = xWrapper->print_job_new( + OUStringToOString(m_xImpl->m_sJobName, RTL_TEXTENCODING_UTF8).getStr(), + m_xImpl->m_pPrinter, m_xImpl->m_pSettings, pPageSetup); + + GError* error = nullptr; + bRet = xWrapper->print_job_set_source_file(pJob, m_xImpl->m_sSpoolFile.getStr(), &error); + if (bRet) + xWrapper->print_job_send(pJob, nullptr, nullptr, nullptr); + else + { + //To-Do, do something with this + SAL_WARN("vcl.gtk3", "error was " << error->message); + g_error_free(error); + } + + g_object_unref(pPageSetup); + m_xImpl.reset(); + + //To-Do, remove temp spool file + + return bRet; +} + +namespace +{ + +void +lcl_setHelpText( + GtkWidget* const io_pWidget, + const uno::Sequence<OUString>& i_rHelpTexts, + const sal_Int32 i_nIndex) +{ + if (i_nIndex >= 0 && i_nIndex < i_rHelpTexts.getLength()) + gtk_widget_set_tooltip_text(io_pWidget, + OUStringToOString(i_rHelpTexts.getConstArray()[i_nIndex], RTL_TEXTENCODING_UTF8).getStr()); +} + +GtkWidget* +lcl_makeFrame( + GtkWidget* const i_pChild, + const OUString &i_rText, + const uno::Sequence<OUString> &i_rHelpTexts, + sal_Int32* const io_pCurHelpText) +{ + GtkWidget* const pLabel = gtk_label_new(nullptr); + lcl_setHelpText(pLabel, i_rHelpTexts, !io_pCurHelpText ? 0 : (*io_pCurHelpText)++); + gtk_misc_set_alignment(GTK_MISC(pLabel), 0.0, 0.5); + + { + gchar* const pText = g_markup_printf_escaped("<b>%s</b>", + OUStringToOString(i_rText, RTL_TEXTENCODING_UTF8).getStr()); + gtk_label_set_markup_with_mnemonic(GTK_LABEL(pLabel), pText); + g_free(pText); + } + + GtkWidget* const pFrame = gtk_vbox_new(FALSE, 6); + gtk_box_pack_start(GTK_BOX(pFrame), pLabel, FALSE, FALSE, 0); + + GtkWidget* const pAlignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0); + gtk_alignment_set_padding(GTK_ALIGNMENT(pAlignment), 0, 0, 12, 0); + gtk_box_pack_start(GTK_BOX(pFrame), pAlignment, FALSE, FALSE, 0); + + gtk_container_add(GTK_CONTAINER(pAlignment), i_pChild); + return pFrame; +} + +void +lcl_extractHelpTextsOrIds( + const beans::PropertyValue& rEntry, + uno::Sequence<OUString>& rHelpStrings) +{ + if (!(rEntry.Value >>= rHelpStrings)) + { + OUString aHelpString; + if (rEntry.Value >>= aHelpString) + { + rHelpStrings.realloc(1); + *rHelpStrings.getArray() = aHelpString; + } + } +} + +GtkWidget* +lcl_combo_box_text_new() +{ + return gtk_combo_box_text_new(); +} + +void +lcl_combo_box_text_append(GtkWidget* const pWidget, gchar const* const pText) +{ + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(pWidget), pText); +} + +} + +GtkPrintDialog::GtkPrintDialog(vcl::PrinterController& io_rController) + : m_rController(io_rController) + , m_xWrapper(lcl_getGtkSalInstance().getPrintWrapper()) +{ + assert(m_xWrapper->supportsPrinting()); + impl_initDialog(); + impl_initCustomTab(); + impl_readFromSettings(); +} + +void +GtkPrintDialog::impl_initDialog() +{ + //To-Do, like fpicker, set UI language + m_pDialog = m_xWrapper->print_unix_dialog_new(); + + vcl::Window* const pTopWindow(Application::GetActiveTopWindow()); + if (pTopWindow) + { + GtkSalFrame* const pFrame(dynamic_cast<GtkSalFrame*>(pTopWindow->ImplGetFrame())); + if (pFrame) + { + GtkWindow* const pParent(GTK_WINDOW(pFrame->getWindow())); + if (pParent) + gtk_window_set_transient_for(GTK_WINDOW(m_pDialog), pParent); + } + } + + m_xWrapper->print_unix_dialog_set_manual_capabilities(GTK_PRINT_UNIX_DIALOG(m_pDialog), + GtkPrintCapabilities(GTK_PRINT_CAPABILITY_COPIES + | GTK_PRINT_CAPABILITY_COLLATE + | GTK_PRINT_CAPABILITY_REVERSE + | GTK_PRINT_CAPABILITY_GENERATE_PS + | GTK_PRINT_CAPABILITY_NUMBER_UP + | GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT + )); +} + +void +GtkPrintDialog::impl_initCustomTab() +{ + typedef std::vector<std::pair<GtkWidget*, OUString> > CustomTabs_t; + + const uno::Sequence<beans::PropertyValue>& rOptions(m_rController.getUIOptions()); + std::map<OUString, GtkWidget*> aPropertyToDependencyRowMap; + CustomTabs_t aCustomTabs; + GtkWidget* pCurParent = nullptr; + GtkWidget* pCurTabPage = nullptr; + GtkWidget* pCurSubGroup = nullptr; + bool bIgnoreSubgroup = false; + for (const auto& rOption : rOptions) + { + uno::Sequence<beans::PropertyValue> aOptProp; + rOption.Value >>= aOptProp; + + OUString aCtrlType; + OUString aText; + OUString aPropertyName; + uno::Sequence<OUString> aChoices; + uno::Sequence<sal_Bool> aChoicesDisabled; + uno::Sequence<OUString> aHelpTexts; + sal_Int64 nMinValue = 0, nMaxValue = 0; + sal_Int32 nCurHelpText = 0; + OUString aDependsOnName; + sal_Int32 nDependsOnValue = 0; + bool bUseDependencyRow = false; + bool bIgnore = false; + GtkWidget* pGroup = nullptr; + bool bGtkInternal = false; + + //Fix fdo#69381 + //Next options if this one is empty + if (!aOptProp.hasElements()) + continue; + + for (const beans::PropertyValue& rEntry : std::as_const(aOptProp)) + { + if ( rEntry.Name == "Text" ) + { + OUString aValue; + rEntry.Value >>= aValue; + aText = aValue.replace('~', '_'); + } + else if ( rEntry.Name == "ControlType" ) + rEntry.Value >>= aCtrlType; + else if ( rEntry.Name == "Choices" ) + rEntry.Value >>= aChoices; + else if ( rEntry.Name == "ChoicesDisabled" ) + rEntry.Value >>= aChoicesDisabled; + else if ( rEntry.Name == "Property" ) + { + beans::PropertyValue aVal; + rEntry.Value >>= aVal; + aPropertyName = aVal.Name; + } + else if ( rEntry.Name == "DependsOnName" ) + rEntry.Value >>= aDependsOnName; + else if ( rEntry.Name == "DependsOnEntry" ) + rEntry.Value >>= nDependsOnValue; + else if ( rEntry.Name == "AttachToDependency" ) + rEntry.Value >>= bUseDependencyRow; + else if ( rEntry.Name == "MinValue" ) + rEntry.Value >>= nMinValue; + else if ( rEntry.Name == "MaxValue" ) + rEntry.Value >>= nMaxValue; + else if ( rEntry.Name == "HelpId" ) + { + uno::Sequence<OUString> aHelpIds; + lcl_extractHelpTextsOrIds(rEntry, aHelpIds); + Help* const pHelp = Application::GetHelp(); + if (pHelp) + { + const int nLen = aHelpIds.getLength(); + aHelpTexts.realloc(nLen); + std::transform(aHelpIds.begin(), aHelpIds.end(), aHelpTexts.begin(), + [&pHelp](const OUString& rHelpId) { return pHelp->GetHelpText(rHelpId, static_cast<weld::Widget*>(nullptr)); }); + } + else // fallback + aHelpTexts = aHelpIds; + } + else if ( rEntry.Name == "HelpText" ) + lcl_extractHelpTextsOrIds(rEntry, aHelpTexts); + else if ( rEntry.Name == "InternalUIOnly" ) + rEntry.Value >>= bIgnore; + else if ( rEntry.Name == "Enabled" ) + { + // Ignore this. We use UIControlOptions::isUIOptionEnabled + // to check whether a control should be enabled. + } + else if ( rEntry.Name == "GroupingHint" ) + { + // Ignore this. We cannot add/modify controls to/on existing + // tabs of the Gtk print dialog. + } + else + { + SAL_INFO("vcl.gtk", "unhandled UI option entry: " << rEntry.Name); + } + } + + if ( aPropertyName == "PrintContent" ) + bGtkInternal = true; + + if (aCtrlType == "Group" || !pCurParent) + { + pCurTabPage = gtk_vbox_new(FALSE, 12); + gtk_container_set_border_width(GTK_CONTAINER(pCurTabPage), 6); + lcl_setHelpText(pCurTabPage, aHelpTexts, 0); + + pCurParent = pCurTabPage; + aCustomTabs.emplace_back(pCurTabPage, aText); + } + else if (aCtrlType == "Subgroup") + { + bIgnoreSubgroup = bIgnore; + if (bIgnore) + continue; + pCurParent = gtk_vbox_new(FALSE, 12); + gtk_container_set_border_width(GTK_CONTAINER(pCurParent), 0); + + pCurSubGroup = lcl_makeFrame(pCurParent, aText, aHelpTexts, nullptr); + gtk_box_pack_start(GTK_BOX(pCurTabPage), pCurSubGroup, FALSE, FALSE, 0); + } + // special case: we need to map these to controls of the gtk print dialog + else if (bGtkInternal) + { + if ( aPropertyName == "PrintContent" ) + { + // What to print? And, more importantly, is there a selection? + impl_initPrintContent(aChoicesDisabled); + } + } + else if (bIgnoreSubgroup || bIgnore) + continue; + else + { + // change handlers for all the controls set up in this block + // should be set _after_ the control has been made (in)active, + // because: + // 1. value of the property is _known_--we are using it to + // _set_ the control, right?--no need to change it back .-) + // 2. it may cause warning because the widget may not + // have been placed in m_aControlToPropertyMap yet + + GtkWidget* pWidget = nullptr; + beans::PropertyValue* pVal = nullptr; + if (aCtrlType == "Bool" && pCurParent) + { + pWidget = gtk_check_button_new_with_mnemonic( + OUStringToOString(aText, RTL_TEXTENCODING_UTF8).getStr()); + lcl_setHelpText(pWidget, aHelpTexts, 0); + m_aControlToPropertyMap[pWidget] = aPropertyName; + + bool bVal = false; + pVal = m_rController.getValue(aPropertyName); + if (pVal) + pVal->Value >>= bVal; + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pWidget), bVal); + gtk_widget_set_sensitive(pWidget, + m_rController.isUIOptionEnabled(aPropertyName) && pVal != nullptr); + g_signal_connect(pWidget, "toggled", G_CALLBACK(GtkPrintDialog::UIOption_CheckHdl), this); + } + else if (aCtrlType == "Radio" && pCurParent) + { + GtkWidget* const pVbox = gtk_vbox_new(FALSE, 12); + gtk_container_set_border_width(GTK_CONTAINER(pVbox), 0); + + if (!aText.isEmpty()) + pGroup = lcl_makeFrame(pVbox, aText, aHelpTexts, &nCurHelpText); + + sal_Int32 nSelectVal = 0; + pVal = m_rController.getValue(aPropertyName); + if (pVal && pVal->Value.hasValue()) + pVal->Value >>= nSelectVal; + + for (sal_Int32 m = 0; m != aChoices.getLength(); m++) + { + pWidget = gtk_radio_button_new_with_mnemonic_from_widget( + GTK_RADIO_BUTTON(m == 0 ? nullptr : pWidget), + OUStringToOString(aChoices[m].replace('~', '_'), RTL_TEXTENCODING_UTF8).getStr()); + lcl_setHelpText(pWidget, aHelpTexts, nCurHelpText++); + m_aControlToPropertyMap[pWidget] = aPropertyName; + m_aControlToNumValMap[pWidget] = m; + GtkWidget* const pRow = gtk_hbox_new(FALSE, 12); + gtk_box_pack_start(GTK_BOX(pVbox), pRow, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(pRow), pWidget, FALSE, FALSE, 0); + aPropertyToDependencyRowMap[aPropertyName + OUString::number(m)] = pRow; + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pWidget), m == nSelectVal); + gtk_widget_set_sensitive(pWidget, + m_rController.isUIOptionEnabled(aPropertyName) && pVal != nullptr); + g_signal_connect(pWidget, "toggled", + G_CALLBACK(GtkPrintDialog::UIOption_RadioHdl), this); + } + + if (pGroup) + pWidget = pGroup; + else + pWidget = pVbox; + } + else if ((aCtrlType == "List" || + aCtrlType == "Range" || + aCtrlType == "Edit" + ) && pCurParent) + { + GtkWidget* const pHbox = gtk_hbox_new(FALSE, 12); + gtk_container_set_border_width(GTK_CONTAINER(pHbox), 0); + + if ( aCtrlType == "List" ) + { + pWidget = lcl_combo_box_text_new(); + + for (const auto& rChoice : std::as_const(aChoices)) + { + lcl_combo_box_text_append(pWidget, + OUStringToOString(rChoice, RTL_TEXTENCODING_UTF8).getStr()); + } + + sal_Int32 nSelectVal = 0; + pVal = m_rController.getValue(aPropertyName); + if (pVal && pVal->Value.hasValue()) + pVal->Value >>= nSelectVal; + gtk_combo_box_set_active(GTK_COMBO_BOX(pWidget), nSelectVal); + g_signal_connect(pWidget, "changed", G_CALLBACK(GtkPrintDialog::UIOption_SelectHdl), this); + } + else if (aCtrlType == "Edit" && pCurParent) + { + pWidget = gtk_entry_new(); + + OUString aCurVal; + pVal = m_rController.getValue(aPropertyName); + if (pVal && pVal->Value.hasValue()) + pVal->Value >>= aCurVal; + gtk_entry_set_text(GTK_ENTRY(pWidget), + OUStringToOString(aCurVal, RTL_TEXTENCODING_UTF8).getStr()); + } + else if (aCtrlType == "Range" && pCurParent) + { + pWidget = gtk_spin_button_new_with_range(nMinValue, nMaxValue, 1.0); + + sal_Int64 nCurVal = 0; + pVal = m_rController.getValue(aPropertyName); + if (pVal && pVal->Value.hasValue()) + pVal->Value >>= nCurVal; + gtk_spin_button_set_value(GTK_SPIN_BUTTON(pWidget), nCurVal); + } + + lcl_setHelpText(pWidget, aHelpTexts, 0); + m_aControlToPropertyMap[pWidget] = aPropertyName; + + gtk_widget_set_sensitive(pWidget, + m_rController.isUIOptionEnabled(aPropertyName) && pVal != nullptr); + + if (!aText.isEmpty()) + { + GtkWidget* const pLabel = gtk_label_new_with_mnemonic( + OUStringToOString(aText, RTL_TEXTENCODING_UTF8).getStr()); + gtk_label_set_mnemonic_widget(GTK_LABEL(pLabel), pWidget); + gtk_box_pack_start(GTK_BOX(pHbox), pLabel, FALSE, FALSE, 0); + } + + gtk_box_pack_start(GTK_BOX(pHbox), pWidget, FALSE, FALSE, 0); + + pWidget = pHbox; + + } + else + SAL_INFO("vcl.gtk", "unhandled option type: " << aCtrlType); + + GtkWidget* pRow = nullptr; + if (pWidget) + { + if (bUseDependencyRow && !aDependsOnName.isEmpty()) + { + pRow = aPropertyToDependencyRowMap[aDependsOnName + OUString::number(nDependsOnValue)]; + if (!pRow) + { + gtk_widget_destroy(pWidget); + pWidget = nullptr; + } + } + } + if (pWidget) + { + if (!pRow) + { + pRow = gtk_hbox_new(FALSE, 12); + gtk_box_pack_start(GTK_BOX(pCurParent), pRow, FALSE, FALSE, 0); + } + if (!pGroup) + aPropertyToDependencyRowMap[aPropertyName + OUString::number(0)] = pRow; + gtk_box_pack_start(GTK_BOX(pRow), pWidget, FALSE, FALSE, 0); + } + } + } + + CustomTabs_t::const_reverse_iterator aEnd = aCustomTabs.rend(); + for (CustomTabs_t::const_reverse_iterator aI = aCustomTabs.rbegin(); aI != aEnd; ++aI) + { + gtk_widget_show_all(aI->first); + m_xWrapper->print_unix_dialog_add_custom_tab(GTK_PRINT_UNIX_DIALOG(m_pDialog), aI->first, + gtk_label_new(OUStringToOString(aI->second, RTL_TEXTENCODING_UTF8).getStr())); + } +} + +void +GtkPrintDialog::impl_initPrintContent(uno::Sequence<sal_Bool> const& i_rDisabled) +{ + SAL_WARN_IF(i_rDisabled.getLength() != 3, "vcl.gtk", "there is more choices than we expected"); + if (i_rDisabled.getLength() != 3) + return; + + GtkPrintUnixDialog* const pDialog(GTK_PRINT_UNIX_DIALOG(m_pDialog)); + + // XXX: This is a hack that depends on the number and the ordering of + // the controls in the rDisabled sequence (cf. the initialization of + // the "PrintContent" UI option in SwPrintUIOptions::SwPrintUIOptions, + // sw/source/core/view/printdata.cxx) + if (m_xWrapper->supportsPrintSelection() && !i_rDisabled[2]) + { + m_xWrapper->print_unix_dialog_set_support_selection(pDialog, true); + m_xWrapper->print_unix_dialog_set_has_selection(pDialog, true); + } + + beans::PropertyValue* const pPrintContent( + m_rController.getValue(OUString("PrintContent"))); + + if (pPrintContent) + { + sal_Int32 nSelectionType(0); + pPrintContent->Value >>= nSelectionType; + GtkPrintSettings* const pSettings(getSettings()); + GtkPrintPages ePrintPages(GTK_PRINT_PAGES_ALL); + switch (nSelectionType) + { + case 0: + ePrintPages = GTK_PRINT_PAGES_ALL; + break; + case 1: + ePrintPages = GTK_PRINT_PAGES_RANGES; + break; + case 2: + if (m_xWrapper->supportsPrintSelection()) + ePrintPages = GTK_PRINT_PAGES_SELECTION; + else + SAL_INFO("vcl.gtk", "the application wants to print a selection, but the present gtk version does not support it"); + break; + default: + SAL_WARN("vcl.gtk", "unexpected selection type: " << nSelectionType); + } + m_xWrapper->print_settings_set_print_pages(pSettings, ePrintPages); + m_xWrapper->print_unix_dialog_set_settings(pDialog, pSettings); + g_object_unref(G_OBJECT(pSettings)); + } +} + +void +GtkPrintDialog::impl_checkOptionalControlDependencies() +{ + for (auto& rEntry : m_aControlToPropertyMap) + { + gtk_widget_set_sensitive(rEntry.first, m_rController.isUIOptionEnabled(rEntry.second)); + } +} + +beans::PropertyValue* +GtkPrintDialog::impl_queryPropertyValue(GtkWidget* const i_pWidget) const +{ + beans::PropertyValue* pVal(nullptr); + std::map<GtkWidget*, OUString>::const_iterator aIt(m_aControlToPropertyMap.find(i_pWidget)); + if (aIt != m_aControlToPropertyMap.end()) + { + pVal = m_rController.getValue(aIt->second); + SAL_WARN_IF(!pVal, "vcl.gtk", "property value not found"); + } + else + { + SAL_WARN("vcl.gtk", "changed control not in property map"); + } + return pVal; +} + +void +GtkPrintDialog::impl_UIOption_CheckHdl(GtkWidget* const i_pWidget) +{ + beans::PropertyValue* const pVal = impl_queryPropertyValue(i_pWidget); + if (pVal) + { + const bool bVal = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(i_pWidget)); + pVal->Value <<= bVal; + + impl_checkOptionalControlDependencies(); + } +} + +void +GtkPrintDialog::impl_UIOption_RadioHdl(GtkWidget* const i_pWidget) +{ + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(i_pWidget))) + { + beans::PropertyValue* const pVal = impl_queryPropertyValue(i_pWidget); + std::map<GtkWidget*, sal_Int32>::const_iterator it = m_aControlToNumValMap.find(i_pWidget); + if (pVal && it != m_aControlToNumValMap.end()) + { + + const sal_Int32 nVal = it->second; + pVal->Value <<= nVal; + + impl_checkOptionalControlDependencies(); + } + } +} + +void +GtkPrintDialog::impl_UIOption_SelectHdl(GtkWidget* const i_pWidget) +{ + beans::PropertyValue* const pVal = impl_queryPropertyValue(i_pWidget); + if (pVal) + { + const sal_Int32 nVal(gtk_combo_box_get_active(GTK_COMBO_BOX(i_pWidget))); + pVal->Value <<= nVal; + + impl_checkOptionalControlDependencies(); + } +} + +bool +GtkPrintDialog::run() +{ + bool bDoJob = false; + bool bContinue = true; + while (bContinue) + { + bContinue = false; + const gint nStatus = gtk_dialog_run(GTK_DIALOG(m_pDialog)); + switch (nStatus) + { + case GTK_RESPONSE_HELP: + SAL_WARN("vcl.gtk3", "To-Do: Help ?"); + bContinue = true; + break; + case GTK_RESPONSE_OK: + bDoJob = true; + break; + default: + break; + } + } + gtk_widget_hide(m_pDialog); + impl_storeToSettings(); + return bDoJob; +} + +void +GtkPrintDialog::updateControllerPrintRange() +{ + GtkPrintSettings* const pSettings(getSettings()); + // TODO: use get_print_pages + if (const gchar* const pStr = m_xWrapper->print_settings_get(pSettings, GTK_PRINT_SETTINGS_PRINT_PAGES)) + { + beans::PropertyValue* pVal = m_rController.getValue(OUString("PrintRange")); + if (!pVal) + pVal = m_rController.getValue(OUString("PrintContent")); + SAL_WARN_IF(!pVal, "vcl.gtk", "Nothing to map standard print options to!"); + if (pVal) + { + sal_Int32 nVal = 0; + if (!strcmp(pStr, "all")) + nVal = 0; + else if (!strcmp(pStr, "ranges")) + nVal = 1; + else if (!strcmp(pStr, "selection")) + nVal = 2; + pVal->Value <<= nVal; + + if (nVal == 1) + { + pVal = m_rController.getValue(OUString("PageRange")); + SAL_WARN_IF(!pVal, "vcl.gtk", "PageRange doesn't exist!"); + if (pVal) + { + OUStringBuffer sBuf; + gint num_ranges; + const GtkPageRange* const pRanges = m_xWrapper->print_settings_get_page_ranges(pSettings, &num_ranges); + for (gint i = 0; i != num_ranges && pRanges; ++i) + { + sBuf.append(sal_Int32(pRanges[i].start+1)); + if (pRanges[i].start != pRanges[i].end) + { + sBuf.append('-'); + sBuf.append(sal_Int32(pRanges[i].end+1)); + } + + if (i != num_ranges-1) + sBuf.append(','); + } + pVal->Value <<= sBuf.makeStringAndClear(); + } + } + } + } + g_object_unref(G_OBJECT(pSettings)); +} + +GtkPrintDialog::~GtkPrintDialog() +{ + gtk_widget_destroy(m_pDialog); +} + +void +GtkPrintDialog::impl_readFromSettings() +{ + vcl::SettingsConfigItem* const pItem(vcl::SettingsConfigItem::get()); + GtkPrintSettings* const pSettings(getSettings()); + + const OUString aPrintDialogStr("PrintDialog"); + const OUString aCopyCount(pItem->getValue(aPrintDialogStr, + "CopyCount")); + const OUString aCollate(pItem->getValue(aPrintDialogStr, + "Collate")); + + const gint nOldCopyCount(m_xWrapper->print_settings_get_n_copies(pSettings)); + const sal_Int32 nCopyCount(aCopyCount.toInt32()); + if (nCopyCount > 0 && nOldCopyCount != nCopyCount) + { + m_xWrapper->print_settings_set_n_copies(pSettings, sal::static_int_cast<gint>(nCopyCount)); + } + + const bool bOldCollate(m_xWrapper->print_settings_get_collate(pSettings)); + const bool bCollate(aCollate.equalsIgnoreAsciiCase("true")); + if (bOldCollate != bCollate) + { + m_xWrapper->print_settings_set_collate(pSettings, bCollate); + } + + m_xWrapper->print_unix_dialog_set_settings(GTK_PRINT_UNIX_DIALOG(m_pDialog), pSettings); + g_object_unref(G_OBJECT(pSettings)); +} + +void +GtkPrintDialog::impl_storeToSettings() +const +{ + vcl::SettingsConfigItem* const pItem(vcl::SettingsConfigItem::get()); + GtkPrintSettings* const pSettings(getSettings()); + + const OUString aPrintDialogStr("PrintDialog"); + pItem->setValue(aPrintDialogStr, + "CopyCount", + OUString::number(m_xWrapper->print_settings_get_n_copies(pSettings))); + pItem->setValue(aPrintDialogStr, + "Collate", + m_xWrapper->print_settings_get_collate(pSettings) + ? OUString("true") + : OUString("false")) + ; + // pItem->setValue(aPrintDialog, OUString("ToFile"), ); + g_object_unref(G_OBJECT(pSettings)); + pItem->Commit(); +} + +sal_uInt32 +GtkSalInfoPrinter::GetCapabilities( + const ImplJobSetup* const i_pSetupData, + const PrinterCapType i_nType) +{ + if (i_nType == PrinterCapType::ExternalDialog && lcl_useSystemPrintDialog()) + return 1; + return PspSalInfoPrinter::GetCapabilities(i_pSetupData, i_nType); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |