Fix #1089: Sync xmp:Rating across all sidecar images
[geeqie.git] / src / print.cc
index 68828b3..d4abcea 100644 (file)
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-#include "main.h"
 #include "print.h"
 
+#include <cstddef>
+
+#include <cairo.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <gdk/gdk.h>
+#include <glib-object.h>
+#include <pango/pango.h>
+#include <pango/pangocairo.h>
+
+#include "compat.h"
+#include "debug.h"
 #include "exif.h"
 #include "filedata.h"
 #include "image-load.h"
+#include "intl.h"
+#include "main-defines.h"
+#include "options.h"
 #include "osd.h"
 #include "pixbuf-util.h"
-#include "ui-misc.h"
 #include "ui-fileops.h"
+#include "ui-misc.h"
 
 #define PRINT_SETTINGS "print_settings" // filename save printer settings
 #define PAGE_SETUP "page_setup" // filename save page setup
 /* method to use when scaling down image data */
 #define PRINT_MAX_INTERP GDK_INTERP_BILINEAR
 
+namespace
+{
+
+constexpr gint PRE_FORMATTED_COLUMNS = 4;
+
+} // namespace
+
 /* reverse order is important */
 enum TextPosition {
        FOOTER_2,
@@ -119,10 +139,37 @@ static gboolean print_job_render_image(PrintWindow *pw)
 
        return TRUE;
 }
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
+static void font_activated_cb(GtkFontChooser *widget, gchar *fontname, gpointer option)
+{
+       option = g_strdup(fontname);
+
+       g_free(fontname);
+
+       gq_gtk_widget_destroy(GTK_WIDGET(widget));
+}
+#pragma GCC diagnostic pop
+
+static void font_response_cb(GtkDialog *dialog, int response_id, gpointer option)
+{
+       gchar *font;
+
+       if (response_id == GTK_RESPONSE_OK)
+               {
+               font = gtk_font_chooser_get_font(GTK_FONT_CHOOSER(dialog));
+               g_free(option);
+               option = g_strdup(font);
+               g_free(font);
+               }
+
+       gq_gtk_widget_destroy(GTK_WIDGET(dialog));
+}
 
 static void print_set_font_cb(GtkWidget *widget, gpointer data)
 {
        gpointer option;
+       GtkWidget *dialog;
 
        if (g_strcmp0(static_cast<const gchar *>(data), "Image text font") == 0)
                {
@@ -133,23 +180,14 @@ static void print_set_font_cb(GtkWidget *widget, gpointer data)
                option = options->printer.page_font;
                }
 
-       GtkWidget *dialog;
-       char *font;
-       PangoFontDescription *font_desc;
-
        dialog = gtk_font_chooser_dialog_new(static_cast<const gchar *>(data), GTK_WINDOW(gtk_widget_get_toplevel(widget)));
+       gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
        gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dialog), static_cast<const gchar *>(option));
 
-       if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
-               {
-               font_desc = gtk_font_chooser_get_font_desc(GTK_FONT_CHOOSER(dialog));
-               font = pango_font_description_to_string(font_desc);
-               g_free(option);
-               option = g_strdup(font);
-               g_free(font);
-               }
+       g_signal_connect(dialog, "font-activated", G_CALLBACK(font_activated_cb), option);
+       g_signal_connect(dialog, "response", G_CALLBACK(font_response_cb), option);
 
-       gtk_widget_destroy(dialog);
+       gtk_widget_show(dialog);
 }
 
 static gint set_toggle(GSList *list, TextPosition pos)
@@ -325,7 +363,6 @@ static void image_text_template_view_changed_cb(GtkWidget *, gpointer data)
                                          gtk_text_buffer_get_text(pTextBuffer, &iStart, &iEnd, TRUE));
 }
 
-#define PRE_FORMATTED_COLUMNS 4
 static void print_text_menu(GtkWidget *box, PrintWindow *pw)
 {
        GtkWidget *group;
@@ -352,19 +389,19 @@ static void print_text_menu(GtkWidget *box, PrintWindow *pw)
        pref_checkbox_link_sensitivity(image_text_button, subgroup);
 
        hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
-       gtk_box_pack_start(GTK_BOX(subgroup), hbox, FALSE, FALSE, 0);
+       gq_gtk_box_pack_start(GTK_BOX(subgroup), hbox, FALSE, FALSE, 0);
 
        /* order is important */
-       button1 = pref_radiobutton_new(hbox, nullptr,  "Header 1",
+       button1 = pref_radiobutton_new(hbox, nullptr,  _("Header 1"),
                                                        options->printer.image_text_position == HEADER_1,
                                                        G_CALLBACK(image_text_position_h1_cb), pw);
-       button1 = pref_radiobutton_new(hbox, button1,  "Header 2",
+       button1 = pref_radiobutton_new(hbox, button1,  _("Header 2"),
                                                        options->printer.image_text_position == HEADER_2,
                                                        G_CALLBACK(image_text_position_h2_cb), pw);
-       button1 = pref_radiobutton_new(hbox, button1, "Footer 1",
+       button1 = pref_radiobutton_new(hbox, button1, _("Footer 1"),
                                                        options->printer.image_text_position == FOOTER_1,
                                                        G_CALLBACK(image_text_position_f1_cb), pw);
-       button1 = pref_radiobutton_new(hbox, button1, "Footer 2",
+       button1 = pref_radiobutton_new(hbox, button1, _("Footer 2"),
                                                        options->printer.image_text_position == FOOTER_2,
                                                        G_CALLBACK(image_text_position_f2_cb), pw);
        gtk_widget_show(hbox);
@@ -373,7 +410,7 @@ static void print_text_menu(GtkWidget *box, PrintWindow *pw)
        image_text_template_view = gtk_text_view_new();
 
        scrolled_pre_formatted = osd_new(PRE_FORMATTED_COLUMNS, image_text_template_view);
-       gtk_box_pack_start(GTK_BOX(subgroup), scrolled_pre_formatted, FALSE, FALSE, 0);
+       gq_gtk_box_pack_start(GTK_BOX(subgroup), scrolled_pre_formatted, FALSE, FALSE, 0);
        gtk_widget_show(scrolled_pre_formatted);
        gtk_widget_show(subgroup);
 
@@ -385,10 +422,10 @@ static void print_text_menu(GtkWidget *box, PrintWindow *pw)
        gq_gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
        gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
                                                                        GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
-       gtk_box_pack_start(GTK_BOX(subgroup), scrolled, TRUE, TRUE, 5);
+       gq_gtk_box_pack_start(GTK_BOX(subgroup), scrolled, TRUE, TRUE, 5);
        gtk_widget_show(scrolled);
 
-       gtk_container_add(GTK_CONTAINER(scrolled), image_text_template_view);
+       gq_gtk_container_add(GTK_WIDGET(scrolled), image_text_template_view);
        gtk_widget_show(image_text_template_view);
 
        buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(image_text_template_view));
@@ -401,7 +438,7 @@ static void print_text_menu(GtkWidget *box, PrintWindow *pw)
        button = pref_button_new(nullptr, GQ_ICON_SELECT_FONT, _("Font"),
                                 G_CALLBACK(print_set_font_cb), const_cast<char *>("Image text font"));
 
-       gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
+       gq_gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
        gtk_widget_show(button);
 
        pref_spacer(group, PREF_PAD_GAP);
@@ -415,19 +452,19 @@ static void print_text_menu(GtkWidget *box, PrintWindow *pw)
        pref_checkbox_link_sensitivity(page_text_button, subgroup);
 
        hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
-       gtk_box_pack_start(GTK_BOX(subgroup), hbox, FALSE, FALSE, 0);
+       gq_gtk_box_pack_start(GTK_BOX(subgroup), hbox, FALSE, FALSE, 0);
 
        /* order is important */
-       button2 = pref_radiobutton_new(hbox, nullptr, "Header 1",
+       button2 = pref_radiobutton_new(hbox, nullptr, _("Header 1"),
                                                        options->printer.page_text_position == HEADER_1,
                                                        G_CALLBACK(page_text_position_h1_cb), pw);
-       button2 = pref_radiobutton_new(hbox, button2,  "Header 2",
+       button2 = pref_radiobutton_new(hbox, button2,  _("Header 2"),
                                                        options->printer.page_text_position == HEADER_2,
                                                        G_CALLBACK(page_text_position_h2_cb), pw);
-       button2 = pref_radiobutton_new(hbox, button2, "Footer 1",
+       button2 = pref_radiobutton_new(hbox, button2, _("Footer 1"),
                                                        options->printer.page_text_position == FOOTER_1,
                                                        G_CALLBACK(page_text_position_f1_cb), pw);
-       button2 = pref_radiobutton_new(hbox, button2, "Footer 2",
+       button2 = pref_radiobutton_new(hbox, button2, _("Footer 2"),
                                                        options->printer.page_text_position == FOOTER_2,
                                                        G_CALLBACK(page_text_position_f2_cb), pw);
        gtk_widget_show(hbox);
@@ -438,7 +475,7 @@ static void print_text_menu(GtkWidget *box, PrintWindow *pw)
        gq_gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
        gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
                                       GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
-       gtk_box_pack_start(GTK_BOX(subgroup), scrolled, TRUE, TRUE, 5);
+       gq_gtk_box_pack_start(GTK_BOX(subgroup), scrolled, TRUE, TRUE, 5);
        gtk_widget_show(scrolled);
 
        page_text_view = gtk_text_view_new();
@@ -447,7 +484,7 @@ static void print_text_menu(GtkWidget *box, PrintWindow *pw)
        g_object_ref(pw->page_text);
 
        gtk_widget_set_tooltip_markup(page_text_view, (_("Text shown on each page of a single or multi-page print job")));
-       gtk_container_add(GTK_CONTAINER(scrolled), page_text_view);
+       gq_gtk_container_add(GTK_WIDGET(scrolled), page_text_view);
        gtk_widget_show(page_text_view);
 
        hbox = pref_box_new(subgroup, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
@@ -455,7 +492,7 @@ static void print_text_menu(GtkWidget *box, PrintWindow *pw)
        button = pref_button_new(nullptr, GQ_ICON_SELECT_FONT, _("Font"),
                                 G_CALLBACK(print_set_font_cb), const_cast<char *>("Page text font"));
 
-       gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
+       gq_gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
        gtk_widget_show(button);
 }
 
@@ -467,10 +504,8 @@ static gboolean paginate_cb(GtkPrintOperation *, GtkPrintContext *, gpointer dat
                {
                return TRUE;
                }
-       else
-               {
-               return FALSE;
-               }
+
+       return FALSE;
 }
 
 gchar *form_image_text(const gchar *template_string, FileData *fd, PrintWindow *pw, gint page_nr, gint total)
@@ -513,7 +548,8 @@ gchar *form_image_text(const gchar *template_string, FileData *fd, PrintWindow *
 
        if (fd->pixbuf)
                {
-               gint w, h;
+               gint w;
+               gint h;
                w = gdk_pixbuf_get_width(fd->pixbuf);
                h = gdk_pixbuf_get_height(fd->pixbuf);
 
@@ -541,8 +577,10 @@ static void draw_page(GtkPrintOperation *, GtkPrintContext *context, gint page_n
        auto pw = static_cast<PrintWindow *>(data);
        FileData *fd;
        cairo_t *cr;
-       gdouble context_width, context_height;
-       gdouble pixbuf_image_width, pixbuf_image_height;
+       gdouble context_width;
+       gdouble context_height;
+       gdouble pixbuf_image_width;
+       gdouble pixbuf_image_height;
        gdouble width_offset;
        gdouble height_offset;
        GdkPixbuf *pixbuf;
@@ -552,15 +590,22 @@ static void draw_page(GtkPrintOperation *, GtkPrintContext *context, gint page_n
        PangoFontDescription *desc;
        GString *image_text = g_string_new(nullptr);
        GString *page_text = g_string_new(nullptr);
-       PangoRectangle ink_rect, logical_rect;
-       gdouble w, h, scale;
-       gdouble image_text_width, image_text_height, page_text_width, page_text_height;
+       PangoRectangle ink_rect;
+       PangoRectangle logical_rect;
+       gdouble w;
+       gdouble h;
+       gdouble scale;
+       gdouble image_text_width;
+       gdouble image_text_height;
+       gdouble page_text_width;
+       gdouble page_text_height;
        gint image_y;
        gint incr_y;
        gdouble pango_height;
        gdouble pango_image_height;
        gdouble pango_page_height;
-       GtkTextIter start, end;
+       GtkTextIter start;
+       GtkTextIter end;
        gchar *tmp;
        gint total;
 
@@ -769,7 +814,8 @@ GObject *option_tab_cb(GtkPrintOperation *, gpointer user_data)
 static void print_pref_store(PrintWindow *pw)
 {
        gchar *tmp;
-       GtkTextIter start, end;
+       GtkTextIter start;
+       GtkTextIter end;
 
        gtk_text_buffer_get_bounds(GTK_TEXT_BUFFER(pw->page_text), &start, &end);
        tmp = gtk_text_buffer_get_text(GTK_TEXT_BUFFER(pw->page_text), &start, &end, FALSE);
@@ -831,6 +877,11 @@ static void end_print_cb(GtkPrintOperation *operation, GtkPrintContext *, gpoint
        g_free(pw);
 }
 
+static void print_response_cb(GtkDialog *dialog, gint, gpointer)
+{
+       gq_gtk_widget_destroy(GTK_WIDGET(dialog));
+}
+
 void print_window_new(FileData *, GList *selection, GList *, GtkWidget *parent)
 {
        GtkWidget *vbox;
@@ -867,7 +918,7 @@ void print_window_new(FileData *, GList *selection, GList *, GtkWidget *parent)
        operation = gtk_print_operation_new();
        settings = gtk_print_settings_new();
 
-       gtk_print_operation_set_custom_tab_label(operation, "Options");
+       gtk_print_operation_set_custom_tab_label(operation, _("Options"));
        gtk_print_operation_set_use_full_page(operation, TRUE);
        gtk_print_operation_set_unit(operation, GTK_UNIT_POINTS);
        gtk_print_operation_set_embed_page_setup(operation, TRUE);
@@ -932,7 +983,7 @@ void print_window_new(FileData *, GList *selection, GList *, GtkWidget *parent)
                                                                "%s", error->message);
                g_error_free (error);
 
-               g_signal_connect(dialog, "response", G_CALLBACK(gtk_widget_destroy), NULL);
+               g_signal_connect(dialog, "response", G_CALLBACK(print_response_cb), NULL);
 
                gtk_widget_show (dialog);
                }