Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : #include <gtk/gtk.h>
7 : #include <gtk/gtkunixprint.h>
8 : #include <stdlib.h>
9 :
10 : #include "mozilla/ArrayUtils.h"
11 :
12 : #include "mozcontainer.h"
13 : #include "nsIPrintSettings.h"
14 : #include "nsIWidget.h"
15 : #include "nsPrintDialogGTK.h"
16 : #include "nsPrintSettingsGTK.h"
17 : #include "nsString.h"
18 : #include "nsReadableUtils.h"
19 : #include "nsIFile.h"
20 : #include "nsIStringBundle.h"
21 : #include "nsIPrintSettingsService.h"
22 : #include "nsIDOMWindow.h"
23 : #include "nsPIDOMWindow.h"
24 : #include "nsIBaseWindow.h"
25 : #include "nsIDocShellTreeItem.h"
26 : #include "nsIDocShell.h"
27 : #include "WidgetUtils.h"
28 :
29 : using namespace mozilla;
30 : using namespace mozilla::widget;
31 :
32 : static const char header_footer_tags[][4] = {"", "&T", "&U", "&D", "&P", "&PT"};
33 :
34 : #define CUSTOM_VALUE_INDEX gint(ArrayLength(header_footer_tags))
35 :
36 : static GtkWindow *
37 0 : get_gtk_window_for_nsiwidget(nsIWidget *widget)
38 : {
39 0 : return GTK_WINDOW(widget->GetNativeData(NS_NATIVE_SHELLWIDGET));
40 : }
41 :
42 : static void
43 0 : ShowCustomDialog(GtkComboBox *changed_box, gpointer user_data)
44 : {
45 0 : if (gtk_combo_box_get_active(changed_box) != CUSTOM_VALUE_INDEX) {
46 0 : g_object_set_data(G_OBJECT(changed_box), "previous-active", GINT_TO_POINTER(gtk_combo_box_get_active(changed_box)));
47 0 : return;
48 : }
49 :
50 0 : GtkWindow* printDialog = GTK_WINDOW(user_data);
51 : nsCOMPtr<nsIStringBundleService> bundleSvc =
52 0 : do_GetService(NS_STRINGBUNDLE_CONTRACTID);
53 :
54 0 : nsCOMPtr<nsIStringBundle> printBundle;
55 0 : bundleSvc->CreateBundle("chrome://global/locale/printdialog.properties", getter_AddRefs(printBundle));
56 0 : nsXPIDLString intlString;
57 :
58 0 : printBundle->GetStringFromName(u"headerFooterCustom", getter_Copies(intlString));
59 0 : GtkWidget* prompt_dialog = gtk_dialog_new_with_buttons(NS_ConvertUTF16toUTF8(intlString).get(), printDialog,
60 : #if (MOZ_WIDGET_GTK == 2)
61 : (GtkDialogFlags)(GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR),
62 : #else
63 : (GtkDialogFlags)(GTK_DIALOG_MODAL),
64 : #endif
65 : GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
66 : GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
67 0 : nullptr);
68 0 : gtk_dialog_set_default_response(GTK_DIALOG(prompt_dialog), GTK_RESPONSE_ACCEPT);
69 0 : gtk_dialog_set_alternative_button_order(GTK_DIALOG(prompt_dialog),
70 : GTK_RESPONSE_ACCEPT,
71 : GTK_RESPONSE_REJECT,
72 0 : -1);
73 :
74 0 : printBundle->GetStringFromName(u"customHeaderFooterPrompt", getter_Copies(intlString));
75 0 : GtkWidget* custom_label = gtk_label_new(NS_ConvertUTF16toUTF8(intlString).get());
76 0 : GtkWidget* custom_entry = gtk_entry_new();
77 0 : GtkWidget* question_icon = gtk_image_new_from_stock(GTK_STOCK_DIALOG_QUESTION, GTK_ICON_SIZE_DIALOG);
78 :
79 : // To be convenient, prefill the textbox with the existing value, if any, and select it all so they can easily
80 : // both edit it and type in a new one.
81 0 : const char* current_text = (const char*) g_object_get_data(G_OBJECT(changed_box), "custom-text");
82 0 : if (current_text) {
83 0 : gtk_entry_set_text(GTK_ENTRY(custom_entry), current_text);
84 0 : gtk_editable_select_region(GTK_EDITABLE(custom_entry), 0, -1);
85 : }
86 0 : gtk_entry_set_activates_default(GTK_ENTRY(custom_entry), TRUE);
87 :
88 0 : GtkWidget* custom_vbox = gtk_vbox_new(TRUE, 2);
89 0 : gtk_box_pack_start(GTK_BOX(custom_vbox), custom_label, FALSE, FALSE, 0);
90 0 : gtk_box_pack_start(GTK_BOX(custom_vbox), custom_entry, FALSE, FALSE, 5); // Make entry 5px underneath label
91 0 : GtkWidget* custom_hbox = gtk_hbox_new(FALSE, 2);
92 0 : gtk_box_pack_start(GTK_BOX(custom_hbox), question_icon, FALSE, FALSE, 0);
93 0 : gtk_box_pack_start(GTK_BOX(custom_hbox), custom_vbox, FALSE, FALSE, 10); // Make question icon 10px away from content
94 0 : gtk_container_set_border_width(GTK_CONTAINER(custom_hbox), 2);
95 0 : gtk_widget_show_all(custom_hbox);
96 :
97 0 : gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(prompt_dialog))),
98 0 : custom_hbox, FALSE, FALSE, 0);
99 0 : gint diag_response = gtk_dialog_run(GTK_DIALOG(prompt_dialog));
100 :
101 0 : if (diag_response == GTK_RESPONSE_ACCEPT) {
102 0 : const gchar* response_text = gtk_entry_get_text(GTK_ENTRY(custom_entry));
103 0 : g_object_set_data_full(G_OBJECT(changed_box), "custom-text", strdup(response_text), (GDestroyNotify) free);
104 0 : g_object_set_data(G_OBJECT(changed_box), "previous-active", GINT_TO_POINTER(CUSTOM_VALUE_INDEX));
105 : } else {
106 : // Go back to the previous index
107 0 : gint previous_active = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(changed_box), "previous-active"));
108 0 : gtk_combo_box_set_active(changed_box, previous_active);
109 : }
110 :
111 0 : gtk_widget_destroy(prompt_dialog);
112 : }
113 :
114 : class nsPrintDialogWidgetGTK {
115 : public:
116 : nsPrintDialogWidgetGTK(nsPIDOMWindowOuter *aParent,
117 : nsIPrintSettings *aPrintSettings);
118 0 : ~nsPrintDialogWidgetGTK() { gtk_widget_destroy(dialog); }
119 : NS_ConvertUTF16toUTF8 GetUTF8FromBundle(const char* aKey);
120 : gint Run();
121 :
122 : nsresult ImportSettings(nsIPrintSettings *aNSSettings);
123 : nsresult ExportSettings(nsIPrintSettings *aNSSettings);
124 :
125 : private:
126 : GtkWidget* dialog;
127 : GtkWidget* radio_as_laid_out;
128 : GtkWidget* radio_selected_frame;
129 : GtkWidget* radio_separate_frames;
130 : GtkWidget* shrink_to_fit_toggle;
131 : GtkWidget* print_bg_colors_toggle;
132 : GtkWidget* print_bg_images_toggle;
133 : GtkWidget* selection_only_toggle;
134 : GtkWidget* header_dropdown[3]; // {left, center, right}
135 : GtkWidget* footer_dropdown[3];
136 :
137 : nsCOMPtr<nsIStringBundle> printBundle;
138 :
139 : bool useNativeSelection;
140 :
141 : GtkWidget* ConstructHeaderFooterDropdown(const char16_t *currentString);
142 : const char* OptionWidgetToString(GtkWidget *dropdown);
143 :
144 : /* Code to copy between GTK and NS print settings structures.
145 : * In the following,
146 : * "Import" means to copy from NS to GTK
147 : * "Export" means to copy from GTK to NS
148 : */
149 : void ExportFramePrinting(nsIPrintSettings *aNS, GtkPrintSettings *aSettings);
150 : void ExportHeaderFooter(nsIPrintSettings *aNS);
151 : };
152 :
153 0 : nsPrintDialogWidgetGTK::nsPrintDialogWidgetGTK(nsPIDOMWindowOuter *aParent,
154 0 : nsIPrintSettings *aSettings)
155 : {
156 0 : nsCOMPtr<nsIWidget> widget = WidgetUtils::DOMWindowToWidget(aParent);
157 0 : NS_ASSERTION(widget, "Need a widget for dialog to be modal.");
158 0 : GtkWindow* gtkParent = get_gtk_window_for_nsiwidget(widget);
159 0 : NS_ASSERTION(gtkParent, "Need a GTK window for dialog to be modal.");
160 :
161 0 : nsCOMPtr<nsIStringBundleService> bundleSvc = do_GetService(NS_STRINGBUNDLE_CONTRACTID);
162 0 : bundleSvc->CreateBundle("chrome://global/locale/printdialog.properties", getter_AddRefs(printBundle));
163 :
164 0 : dialog = gtk_print_unix_dialog_new(GetUTF8FromBundle("printTitleGTK").get(), gtkParent);
165 :
166 0 : gtk_print_unix_dialog_set_manual_capabilities(GTK_PRINT_UNIX_DIALOG(dialog),
167 : GtkPrintCapabilities(
168 : GTK_PRINT_CAPABILITY_PAGE_SET
169 : | GTK_PRINT_CAPABILITY_COPIES
170 : | GTK_PRINT_CAPABILITY_COLLATE
171 : | GTK_PRINT_CAPABILITY_REVERSE
172 : | GTK_PRINT_CAPABILITY_SCALE
173 : | GTK_PRINT_CAPABILITY_GENERATE_PDF
174 : | GTK_PRINT_CAPABILITY_GENERATE_PS
175 : )
176 0 : );
177 :
178 : // The vast majority of magic numbers in this widget construction are padding. e.g. for
179 : // the set_border_width below, 12px matches that of just about every other window.
180 0 : GtkWidget* custom_options_tab = gtk_vbox_new(FALSE, 0);
181 0 : gtk_container_set_border_width(GTK_CONTAINER(custom_options_tab), 12);
182 0 : GtkWidget* tab_label = gtk_label_new(GetUTF8FromBundle("optionsTabLabelGTK").get());
183 :
184 : int16_t frameUIFlag;
185 0 : aSettings->GetHowToEnableFrameUI(&frameUIFlag);
186 0 : radio_as_laid_out = gtk_radio_button_new_with_mnemonic(nullptr, GetUTF8FromBundle("asLaidOut").get());
187 0 : if (frameUIFlag == nsIPrintSettings::kFrameEnableNone)
188 0 : gtk_widget_set_sensitive(radio_as_laid_out, FALSE);
189 :
190 0 : radio_selected_frame = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(radio_as_laid_out),
191 0 : GetUTF8FromBundle("selectedFrame").get());
192 0 : if (frameUIFlag == nsIPrintSettings::kFrameEnableNone ||
193 0 : frameUIFlag == nsIPrintSettings::kFrameEnableAsIsAndEach)
194 0 : gtk_widget_set_sensitive(radio_selected_frame, FALSE);
195 :
196 0 : radio_separate_frames = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(radio_as_laid_out),
197 0 : GetUTF8FromBundle("separateFrames").get());
198 0 : if (frameUIFlag == nsIPrintSettings::kFrameEnableNone)
199 0 : gtk_widget_set_sensitive(radio_separate_frames, FALSE);
200 :
201 : // "Print Frames" options label, bold and center-aligned
202 0 : GtkWidget* print_frames_label = gtk_label_new(nullptr);
203 0 : char* pangoMarkup = g_markup_printf_escaped("<b>%s</b>", GetUTF8FromBundle("printFramesTitleGTK").get());
204 0 : gtk_label_set_markup(GTK_LABEL(print_frames_label), pangoMarkup);
205 0 : g_free(pangoMarkup);
206 0 : gtk_misc_set_alignment(GTK_MISC(print_frames_label), 0, 0);
207 :
208 : // Align the radio buttons slightly so they appear to fall under the aforementioned label as per the GNOME HIG
209 0 : GtkWidget* frames_radio_container = gtk_alignment_new(0, 0, 0, 0);
210 0 : gtk_alignment_set_padding(GTK_ALIGNMENT(frames_radio_container), 8, 0, 12, 0);
211 :
212 : // Radio buttons for the print frames options
213 0 : GtkWidget* frames_radio_list = gtk_vbox_new(TRUE, 2);
214 0 : gtk_box_pack_start(GTK_BOX(frames_radio_list), radio_as_laid_out, FALSE, FALSE, 0);
215 0 : gtk_box_pack_start(GTK_BOX(frames_radio_list), radio_selected_frame, FALSE, FALSE, 0);
216 0 : gtk_box_pack_start(GTK_BOX(frames_radio_list), radio_separate_frames, FALSE, FALSE, 0);
217 0 : gtk_container_add(GTK_CONTAINER(frames_radio_container), frames_radio_list);
218 :
219 : // Check buttons for shrink-to-fit and print selection
220 0 : GtkWidget* check_buttons_container = gtk_vbox_new(TRUE, 2);
221 0 : shrink_to_fit_toggle = gtk_check_button_new_with_mnemonic(GetUTF8FromBundle("shrinkToFit").get());
222 0 : gtk_box_pack_start(GTK_BOX(check_buttons_container), shrink_to_fit_toggle, FALSE, FALSE, 0);
223 :
224 : // GTK+2.18 and above allow us to add a "Selection" option to the main settings screen,
225 : // rather than adding an option on a custom tab like we must do on older versions.
226 : bool canSelectText;
227 0 : aSettings->GetPrintOptions(nsIPrintSettings::kEnableSelectionRB, &canSelectText);
228 0 : if (gtk_major_version > 2 ||
229 0 : (gtk_major_version == 2 && gtk_minor_version >= 18)) {
230 0 : useNativeSelection = true;
231 0 : g_object_set(dialog,
232 : "support-selection", TRUE,
233 : "has-selection", canSelectText,
234 : "embed-page-setup", TRUE,
235 0 : nullptr);
236 : } else {
237 0 : useNativeSelection = false;
238 0 : selection_only_toggle = gtk_check_button_new_with_mnemonic(GetUTF8FromBundle("selectionOnly").get());
239 0 : gtk_widget_set_sensitive(selection_only_toggle, canSelectText);
240 0 : gtk_box_pack_start(GTK_BOX(check_buttons_container), selection_only_toggle, FALSE, FALSE, 0);
241 : }
242 :
243 : // Check buttons for printing background
244 0 : GtkWidget* appearance_buttons_container = gtk_vbox_new(TRUE, 2);
245 0 : print_bg_colors_toggle = gtk_check_button_new_with_mnemonic(GetUTF8FromBundle("printBGColors").get());
246 0 : print_bg_images_toggle = gtk_check_button_new_with_mnemonic(GetUTF8FromBundle("printBGImages").get());
247 0 : gtk_box_pack_start(GTK_BOX(appearance_buttons_container), print_bg_colors_toggle, FALSE, FALSE, 0);
248 0 : gtk_box_pack_start(GTK_BOX(appearance_buttons_container), print_bg_images_toggle, FALSE, FALSE, 0);
249 :
250 : // "Appearance" options label, bold and center-aligned
251 0 : GtkWidget* appearance_label = gtk_label_new(nullptr);
252 0 : pangoMarkup = g_markup_printf_escaped("<b>%s</b>", GetUTF8FromBundle("printBGOptions").get());
253 0 : gtk_label_set_markup(GTK_LABEL(appearance_label), pangoMarkup);
254 0 : g_free(pangoMarkup);
255 0 : gtk_misc_set_alignment(GTK_MISC(appearance_label), 0, 0);
256 :
257 0 : GtkWidget* appearance_container = gtk_alignment_new(0, 0, 0, 0);
258 0 : gtk_alignment_set_padding(GTK_ALIGNMENT(appearance_container), 8, 0, 12, 0);
259 0 : gtk_container_add(GTK_CONTAINER(appearance_container), appearance_buttons_container);
260 :
261 0 : GtkWidget* appearance_vertical_squasher = gtk_vbox_new(FALSE, 0);
262 0 : gtk_box_pack_start(GTK_BOX(appearance_vertical_squasher), appearance_label, FALSE, FALSE, 0);
263 0 : gtk_box_pack_start(GTK_BOX(appearance_vertical_squasher), appearance_container, FALSE, FALSE, 0);
264 :
265 : // "Header & Footer" options label, bold and center-aligned
266 0 : GtkWidget* header_footer_label = gtk_label_new(nullptr);
267 0 : pangoMarkup = g_markup_printf_escaped("<b>%s</b>", GetUTF8FromBundle("headerFooter").get());
268 0 : gtk_label_set_markup(GTK_LABEL(header_footer_label), pangoMarkup);
269 0 : g_free(pangoMarkup);
270 0 : gtk_misc_set_alignment(GTK_MISC(header_footer_label), 0, 0);
271 :
272 0 : GtkWidget* header_footer_container = gtk_alignment_new(0, 0, 0, 0);
273 0 : gtk_alignment_set_padding(GTK_ALIGNMENT(header_footer_container), 8, 0, 12, 0);
274 :
275 :
276 : // --- Table for making the header and footer options ---
277 0 : GtkWidget* header_footer_table = gtk_table_new(3, 3, FALSE); // 3x3 table
278 0 : nsXPIDLString header_footer_str[3];
279 :
280 0 : aSettings->GetHeaderStrLeft(getter_Copies(header_footer_str[0]));
281 0 : aSettings->GetHeaderStrCenter(getter_Copies(header_footer_str[1]));
282 0 : aSettings->GetHeaderStrRight(getter_Copies(header_footer_str[2]));
283 :
284 0 : for (unsigned int i = 0; i < ArrayLength(header_dropdown); i++) {
285 0 : header_dropdown[i] = ConstructHeaderFooterDropdown(header_footer_str[i].get());
286 : // Those 4 magic numbers in the middle provide the position in the table.
287 : // The last two numbers mean 2 px padding on every side.
288 0 : gtk_table_attach(GTK_TABLE(header_footer_table), header_dropdown[i], i, (i + 1),
289 0 : 0, 1, (GtkAttachOptions) 0, (GtkAttachOptions) 0, 2, 2);
290 : }
291 :
292 0 : const char labelKeys[][7] = {"left", "center", "right"};
293 0 : for (unsigned int i = 0; i < ArrayLength(labelKeys); i++) {
294 0 : gtk_table_attach(GTK_TABLE(header_footer_table),
295 0 : gtk_label_new(GetUTF8FromBundle(labelKeys[i]).get()),
296 0 : i, (i + 1), 1, 2, (GtkAttachOptions) 0, (GtkAttachOptions) 0, 2, 2);
297 : }
298 :
299 0 : aSettings->GetFooterStrLeft(getter_Copies(header_footer_str[0]));
300 0 : aSettings->GetFooterStrCenter(getter_Copies(header_footer_str[1]));
301 0 : aSettings->GetFooterStrRight(getter_Copies(header_footer_str[2]));
302 :
303 0 : for (unsigned int i = 0; i < ArrayLength(footer_dropdown); i++) {
304 0 : footer_dropdown[i] = ConstructHeaderFooterDropdown(header_footer_str[i].get());
305 0 : gtk_table_attach(GTK_TABLE(header_footer_table), footer_dropdown[i], i, (i + 1),
306 0 : 2, 3, (GtkAttachOptions) 0, (GtkAttachOptions) 0, 2, 2);
307 : }
308 : // ---
309 :
310 0 : gtk_container_add(GTK_CONTAINER(header_footer_container), header_footer_table);
311 :
312 0 : GtkWidget* header_footer_vertical_squasher = gtk_vbox_new(FALSE, 0);
313 0 : gtk_box_pack_start(GTK_BOX(header_footer_vertical_squasher), header_footer_label, FALSE, FALSE, 0);
314 0 : gtk_box_pack_start(GTK_BOX(header_footer_vertical_squasher), header_footer_container, FALSE, FALSE, 0);
315 :
316 : // Construction of everything
317 0 : gtk_box_pack_start(GTK_BOX(custom_options_tab), print_frames_label, FALSE, FALSE, 0);
318 0 : gtk_box_pack_start(GTK_BOX(custom_options_tab), frames_radio_container, FALSE, FALSE, 0);
319 0 : gtk_box_pack_start(GTK_BOX(custom_options_tab), check_buttons_container, FALSE, FALSE, 10); // 10px padding
320 0 : gtk_box_pack_start(GTK_BOX(custom_options_tab), appearance_vertical_squasher, FALSE, FALSE, 10);
321 0 : gtk_box_pack_start(GTK_BOX(custom_options_tab), header_footer_vertical_squasher, FALSE, FALSE, 0);
322 :
323 0 : gtk_print_unix_dialog_add_custom_tab(GTK_PRINT_UNIX_DIALOG(dialog), custom_options_tab, tab_label);
324 0 : gtk_widget_show_all(custom_options_tab);
325 0 : }
326 :
327 : NS_ConvertUTF16toUTF8
328 0 : nsPrintDialogWidgetGTK::GetUTF8FromBundle(const char *aKey)
329 : {
330 0 : nsXPIDLString intlString;
331 0 : printBundle->GetStringFromName(NS_ConvertUTF8toUTF16(aKey).get(), getter_Copies(intlString));
332 0 : return NS_ConvertUTF16toUTF8(intlString); // Return the actual object so we don't lose reference
333 : }
334 :
335 : const char*
336 0 : nsPrintDialogWidgetGTK::OptionWidgetToString(GtkWidget *dropdown)
337 : {
338 0 : gint index = gtk_combo_box_get_active(GTK_COMBO_BOX(dropdown));
339 :
340 0 : NS_ASSERTION(index <= CUSTOM_VALUE_INDEX, "Index of dropdown is higher than expected!");
341 :
342 0 : if (index == CUSTOM_VALUE_INDEX)
343 0 : return (const char*) g_object_get_data(G_OBJECT(dropdown), "custom-text");
344 : else
345 0 : return header_footer_tags[index];
346 : }
347 :
348 : gint
349 0 : nsPrintDialogWidgetGTK::Run()
350 : {
351 0 : const gint response = gtk_dialog_run(GTK_DIALOG(dialog));
352 0 : gtk_widget_hide(dialog);
353 0 : return response;
354 : }
355 :
356 : void
357 0 : nsPrintDialogWidgetGTK::ExportFramePrinting(nsIPrintSettings *aNS, GtkPrintSettings *aSettings)
358 : {
359 0 : if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radio_as_laid_out)))
360 0 : aNS->SetPrintFrameType(nsIPrintSettings::kFramesAsIs);
361 0 : else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radio_selected_frame)))
362 0 : aNS->SetPrintFrameType(nsIPrintSettings::kSelectedFrame);
363 0 : else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radio_separate_frames)))
364 0 : aNS->SetPrintFrameType(nsIPrintSettings::kEachFrameSep);
365 : else
366 0 : aNS->SetPrintFrameType(nsIPrintSettings::kNoFrames);
367 0 : }
368 :
369 : void
370 0 : nsPrintDialogWidgetGTK::ExportHeaderFooter(nsIPrintSettings *aNS)
371 : {
372 : const char* header_footer_str;
373 0 : header_footer_str = OptionWidgetToString(header_dropdown[0]);
374 0 : aNS->SetHeaderStrLeft(NS_ConvertUTF8toUTF16(header_footer_str).get());
375 :
376 0 : header_footer_str = OptionWidgetToString(header_dropdown[1]);
377 0 : aNS->SetHeaderStrCenter(NS_ConvertUTF8toUTF16(header_footer_str).get());
378 :
379 0 : header_footer_str = OptionWidgetToString(header_dropdown[2]);
380 0 : aNS->SetHeaderStrRight(NS_ConvertUTF8toUTF16(header_footer_str).get());
381 :
382 0 : header_footer_str = OptionWidgetToString(footer_dropdown[0]);
383 0 : aNS->SetFooterStrLeft(NS_ConvertUTF8toUTF16(header_footer_str).get());
384 :
385 0 : header_footer_str = OptionWidgetToString(footer_dropdown[1]);
386 0 : aNS->SetFooterStrCenter(NS_ConvertUTF8toUTF16(header_footer_str).get());
387 :
388 0 : header_footer_str = OptionWidgetToString(footer_dropdown[2]);
389 0 : aNS->SetFooterStrRight(NS_ConvertUTF8toUTF16(header_footer_str).get());
390 0 : }
391 :
392 : nsresult
393 0 : nsPrintDialogWidgetGTK::ImportSettings(nsIPrintSettings *aNSSettings)
394 : {
395 0 : NS_PRECONDITION(aNSSettings, "aSettings must not be null");
396 0 : NS_ENSURE_TRUE(aNSSettings, NS_ERROR_FAILURE);
397 :
398 0 : nsCOMPtr<nsPrintSettingsGTK> aNSSettingsGTK(do_QueryInterface(aNSSettings));
399 0 : if (!aNSSettingsGTK)
400 0 : return NS_ERROR_FAILURE;
401 :
402 0 : GtkPrintSettings* settings = aNSSettingsGTK->GetGtkPrintSettings();
403 0 : GtkPageSetup* setup = aNSSettingsGTK->GetGtkPageSetup();
404 :
405 : bool geckoBool;
406 0 : aNSSettings->GetShrinkToFit(&geckoBool);
407 0 : gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(shrink_to_fit_toggle), geckoBool);
408 :
409 0 : aNSSettings->GetPrintBGColors(&geckoBool);
410 0 : gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(print_bg_colors_toggle), geckoBool);
411 :
412 0 : aNSSettings->GetPrintBGImages(&geckoBool);
413 0 : gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(print_bg_images_toggle), geckoBool);
414 :
415 0 : gtk_print_unix_dialog_set_settings(GTK_PRINT_UNIX_DIALOG(dialog), settings);
416 0 : gtk_print_unix_dialog_set_page_setup(GTK_PRINT_UNIX_DIALOG(dialog), setup);
417 :
418 0 : return NS_OK;
419 : }
420 :
421 : nsresult
422 0 : nsPrintDialogWidgetGTK::ExportSettings(nsIPrintSettings *aNSSettings)
423 : {
424 0 : NS_PRECONDITION(aNSSettings, "aSettings must not be null");
425 0 : NS_ENSURE_TRUE(aNSSettings, NS_ERROR_FAILURE);
426 :
427 0 : GtkPrintSettings* settings = gtk_print_unix_dialog_get_settings(GTK_PRINT_UNIX_DIALOG(dialog));
428 0 : GtkPageSetup* setup = gtk_print_unix_dialog_get_page_setup(GTK_PRINT_UNIX_DIALOG(dialog));
429 0 : GtkPrinter* printer = gtk_print_unix_dialog_get_selected_printer(GTK_PRINT_UNIX_DIALOG(dialog));
430 0 : if (settings && setup && printer) {
431 0 : ExportFramePrinting(aNSSettings, settings);
432 0 : ExportHeaderFooter(aNSSettings);
433 :
434 0 : aNSSettings->SetOutputFormat(nsIPrintSettings::kOutputFormatNative);
435 :
436 : // Print-to-file is true by default. This must be turned off or else printing won't occur!
437 : // (We manually copy the spool file when this flag is set, because we love our embedders)
438 : // Even if it is print-to-file in GTK's case, GTK does The Right Thing when we send the job.
439 0 : aNSSettings->SetPrintToFile(false);
440 :
441 0 : aNSSettings->SetShrinkToFit(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(shrink_to_fit_toggle)));
442 :
443 0 : aNSSettings->SetPrintBGColors(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(print_bg_colors_toggle)));
444 0 : aNSSettings->SetPrintBGImages(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(print_bg_images_toggle)));
445 :
446 : // Try to save native settings in the session object
447 0 : nsCOMPtr<nsPrintSettingsGTK> aNSSettingsGTK(do_QueryInterface(aNSSettings));
448 0 : if (aNSSettingsGTK) {
449 0 : aNSSettingsGTK->SetGtkPrintSettings(settings);
450 0 : aNSSettingsGTK->SetGtkPageSetup(setup);
451 0 : aNSSettingsGTK->SetGtkPrinter(printer);
452 : bool printSelectionOnly;
453 0 : if (useNativeSelection) {
454 0 : _GtkPrintPages pageSetting = (_GtkPrintPages)gtk_print_settings_get_print_pages(settings);
455 0 : printSelectionOnly = (pageSetting == _GTK_PRINT_PAGES_SELECTION);
456 : } else {
457 0 : printSelectionOnly = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(selection_only_toggle));
458 : }
459 0 : aNSSettingsGTK->SetForcePrintSelectionOnly(printSelectionOnly);
460 : }
461 : }
462 :
463 0 : if (settings)
464 0 : g_object_unref(settings);
465 0 : return NS_OK;
466 : }
467 :
468 : GtkWidget*
469 0 : nsPrintDialogWidgetGTK::ConstructHeaderFooterDropdown(const char16_t *currentString)
470 : {
471 : #if (MOZ_WIDGET_GTK == 2)
472 : GtkWidget* dropdown = gtk_combo_box_new_text();
473 : #else
474 0 : GtkWidget* dropdown = gtk_combo_box_text_new();
475 : #endif
476 : const char hf_options[][22] = {"headerFooterBlank", "headerFooterTitle",
477 : "headerFooterURL", "headerFooterDate",
478 : "headerFooterPage", "headerFooterPageTotal",
479 0 : "headerFooterCustom"};
480 :
481 0 : for (unsigned int i = 0; i < ArrayLength(hf_options); i++) {
482 : #if (MOZ_WIDGET_GTK == 2)
483 : gtk_combo_box_append_text(GTK_COMBO_BOX(dropdown), GetUTF8FromBundle(hf_options[i]).get());
484 : #else
485 0 : gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(dropdown), nullptr,
486 0 : GetUTF8FromBundle(hf_options[i]).get());
487 : #endif
488 : }
489 :
490 0 : bool shouldBeCustom = true;
491 0 : NS_ConvertUTF16toUTF8 currentStringUTF8(currentString);
492 :
493 0 : for (unsigned int i = 0; i < ArrayLength(header_footer_tags); i++) {
494 0 : if (!strcmp(currentStringUTF8.get(), header_footer_tags[i])) {
495 0 : gtk_combo_box_set_active(GTK_COMBO_BOX(dropdown), i);
496 0 : g_object_set_data(G_OBJECT(dropdown), "previous-active", GINT_TO_POINTER(i));
497 0 : shouldBeCustom = false;
498 0 : break;
499 : }
500 : }
501 :
502 0 : if (shouldBeCustom) {
503 0 : gtk_combo_box_set_active(GTK_COMBO_BOX(dropdown), CUSTOM_VALUE_INDEX);
504 0 : g_object_set_data(G_OBJECT(dropdown), "previous-active", GINT_TO_POINTER(CUSTOM_VALUE_INDEX));
505 0 : char* custom_string = strdup(currentStringUTF8.get());
506 0 : g_object_set_data_full(G_OBJECT(dropdown), "custom-text", custom_string, (GDestroyNotify) free);
507 : }
508 :
509 0 : g_signal_connect(dropdown, "changed", (GCallback) ShowCustomDialog, dialog);
510 0 : return dropdown;
511 : }
512 :
513 0 : NS_IMPL_ISUPPORTS(nsPrintDialogServiceGTK, nsIPrintDialogService)
514 :
515 0 : nsPrintDialogServiceGTK::nsPrintDialogServiceGTK()
516 : {
517 0 : }
518 :
519 0 : nsPrintDialogServiceGTK::~nsPrintDialogServiceGTK()
520 : {
521 0 : }
522 :
523 : NS_IMETHODIMP
524 0 : nsPrintDialogServiceGTK::Init()
525 : {
526 0 : return NS_OK;
527 : }
528 :
529 : NS_IMETHODIMP
530 0 : nsPrintDialogServiceGTK::Show(nsPIDOMWindowOuter *aParent,
531 : nsIPrintSettings *aSettings,
532 : nsIWebBrowserPrint *aWebBrowserPrint)
533 : {
534 0 : NS_PRECONDITION(aParent, "aParent must not be null");
535 0 : NS_PRECONDITION(aSettings, "aSettings must not be null");
536 :
537 0 : nsPrintDialogWidgetGTK printDialog(aParent, aSettings);
538 0 : nsresult rv = printDialog.ImportSettings(aSettings);
539 :
540 0 : NS_ENSURE_SUCCESS(rv, rv);
541 :
542 0 : const gint response = printDialog.Run();
543 :
544 : // Handle the result
545 0 : switch (response) {
546 : case GTK_RESPONSE_OK: // Proceed
547 0 : rv = printDialog.ExportSettings(aSettings);
548 0 : break;
549 :
550 : case GTK_RESPONSE_CANCEL:
551 : case GTK_RESPONSE_CLOSE:
552 : case GTK_RESPONSE_DELETE_EVENT:
553 : case GTK_RESPONSE_NONE:
554 0 : rv = NS_ERROR_ABORT;
555 0 : break;
556 :
557 : case GTK_RESPONSE_APPLY: // Print preview
558 : default:
559 0 : NS_WARNING("Unexpected response");
560 0 : rv = NS_ERROR_ABORT;
561 : }
562 0 : return rv;
563 : }
564 :
565 : NS_IMETHODIMP
566 0 : nsPrintDialogServiceGTK::ShowPageSetup(nsPIDOMWindowOuter *aParent,
567 : nsIPrintSettings *aNSSettings)
568 : {
569 0 : NS_PRECONDITION(aParent, "aParent must not be null");
570 0 : NS_PRECONDITION(aNSSettings, "aSettings must not be null");
571 0 : NS_ENSURE_TRUE(aNSSettings, NS_ERROR_FAILURE);
572 :
573 0 : nsCOMPtr<nsIWidget> widget = WidgetUtils::DOMWindowToWidget(aParent);
574 0 : NS_ASSERTION(widget, "Need a widget for dialog to be modal.");
575 0 : GtkWindow* gtkParent = get_gtk_window_for_nsiwidget(widget);
576 0 : NS_ASSERTION(gtkParent, "Need a GTK window for dialog to be modal.");
577 :
578 0 : nsCOMPtr<nsPrintSettingsGTK> aNSSettingsGTK(do_QueryInterface(aNSSettings));
579 0 : if (!aNSSettingsGTK)
580 0 : return NS_ERROR_FAILURE;
581 :
582 : // We need to init the prefs here because aNSSettings in its current form is a dummy in both uses of the word
583 0 : nsCOMPtr<nsIPrintSettingsService> psService = do_GetService("@mozilla.org/gfx/printsettings-service;1");
584 0 : if (psService) {
585 0 : nsXPIDLString printName;
586 0 : aNSSettings->GetPrinterName(getter_Copies(printName));
587 0 : if (!printName) {
588 0 : psService->GetDefaultPrinterName(getter_Copies(printName));
589 0 : aNSSettings->SetPrinterName(printName.get());
590 : }
591 0 : psService->InitPrintSettingsFromPrefs(aNSSettings, true, nsIPrintSettings::kInitSaveAll);
592 : }
593 :
594 0 : GtkPrintSettings* gtkSettings = aNSSettingsGTK->GetGtkPrintSettings();
595 0 : GtkPageSetup* oldPageSetup = aNSSettingsGTK->GetGtkPageSetup();
596 :
597 0 : GtkPageSetup* newPageSetup = gtk_print_run_page_setup_dialog(gtkParent, oldPageSetup, gtkSettings);
598 :
599 0 : aNSSettingsGTK->SetGtkPageSetup(newPageSetup);
600 :
601 : // Now newPageSetup has a refcount of 2 (SetGtkPageSetup will addref), put it to 1 so if
602 : // this gets replaced we don't leak.
603 0 : g_object_unref(newPageSetup);
604 :
605 0 : if (psService)
606 0 : psService->SavePrintSettingsToPrefs(aNSSettings, true, nsIPrintSettings::kInitSaveAll);
607 :
608 0 : return NS_OK;
609 : }
|