mirror of
https://github.com/VibedByKaKi/yad.git
synced 2026-08-28 23:31:13 +02:00
633 lines
18 KiB
C
633 lines
18 KiB
C
/*
|
|
* This file is part of YAD.
|
|
*
|
|
* YAD is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* YAD is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with YAD. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
* Copyright (C) 2008-2025, Victor Ananjevsky <victor@sanana.kiev.ua>
|
|
*/
|
|
|
|
#include "yad.h"
|
|
|
|
enum {
|
|
SIZE_FIT,
|
|
SIZE_ORIG,
|
|
SIZE_INC,
|
|
SIZE_DEC
|
|
};
|
|
|
|
enum {
|
|
ROTATE_LEFT,
|
|
ROTATE_RIGHT,
|
|
ROTATE_FLIP_VERT,
|
|
ROTATE_FLIP_HOR
|
|
};
|
|
|
|
enum {
|
|
COPY_IMAGE,
|
|
COPY_FILE
|
|
};
|
|
|
|
typedef struct {
|
|
gchar *filename;
|
|
GdkPixbufAnimation *anim_pb;
|
|
GdkPixbuf *orig_pb;
|
|
gboolean loaded;
|
|
gboolean animated;
|
|
} ImageItem;
|
|
|
|
static GList *img_list = NULL;
|
|
static GList *lp = NULL;
|
|
static ImageItem *img = NULL;
|
|
|
|
static GtkWidget *picture;
|
|
static GtkWidget *viewport;
|
|
static GtkWidget *popup_menu;
|
|
|
|
static void create_popup_menu ();
|
|
|
|
static void
|
|
img_free (ImageItem *ii)
|
|
{
|
|
if (ii)
|
|
{
|
|
g_free (ii->filename);
|
|
if (ii->orig_pb)
|
|
g_object_unref (ii->orig_pb);
|
|
if (ii->anim_pb)
|
|
g_object_unref (ii->anim_pb);
|
|
g_free (ii);
|
|
}
|
|
}
|
|
|
|
static void
|
|
load_picture ()
|
|
{
|
|
if (!img)
|
|
return;
|
|
|
|
if (!img->loaded)
|
|
{
|
|
if (img->filename && g_file_test (img->filename, G_FILE_TEST_EXISTS))
|
|
{
|
|
img->anim_pb = gdk_pixbuf_animation_new_from_file (img->filename, NULL);
|
|
img->orig_pb = gdk_pixbuf_animation_get_static_image (img->anim_pb);
|
|
|
|
img->animated = !gdk_pixbuf_animation_is_static_image (img->anim_pb);
|
|
}
|
|
img->loaded = TRUE;
|
|
}
|
|
|
|
if (img->orig_pb)
|
|
{
|
|
if (img->animated)
|
|
gtk_image_set_from_animation (GTK_IMAGE (picture), g_object_ref (img->anim_pb));
|
|
else
|
|
gtk_image_set_from_pixbuf (GTK_IMAGE (picture), g_object_ref (img->orig_pb));
|
|
if (options.picture_data.size == YAD_PICTURE_FIT)
|
|
picture_fit_to_window ();
|
|
}
|
|
else
|
|
gtk_image_set_from_icon_name (GTK_IMAGE (picture), "image-missing", GTK_ICON_SIZE_DIALOG);
|
|
}
|
|
|
|
static void
|
|
img_changed_hook ()
|
|
{
|
|
gchar *qfn, *cmd = NULL;
|
|
|
|
if (options.action_data.changed == NULL)
|
|
return;
|
|
if (!img)
|
|
return;
|
|
|
|
qfn = g_shell_quote (img->filename);
|
|
if (g_strstr_len (options.action_data.changed, -1, "%s") != NULL)
|
|
cmd = g_strdup_printf (options.action_data.changed, qfn);
|
|
else
|
|
cmd = g_strdup_printf ("%s '%s'", options.action_data.changed, qfn);
|
|
g_free (qfn);
|
|
|
|
run_command_async (cmd);
|
|
g_free (cmd);
|
|
}
|
|
|
|
static void
|
|
next_img_cb (GtkWidget *w, gpointer d)
|
|
{
|
|
lp = g_list_next (lp);
|
|
if (!lp)
|
|
lp = g_list_first (img_list);
|
|
if (lp)
|
|
img = (ImageItem *) lp->data;
|
|
|
|
load_picture ();
|
|
img_changed_hook ();
|
|
}
|
|
|
|
static void
|
|
prev_img_cb (GtkWidget *w, gpointer d)
|
|
{
|
|
lp = g_list_previous (lp);
|
|
if (!lp)
|
|
lp = g_list_last (img_list);
|
|
if (lp)
|
|
img = (ImageItem *) lp->data;
|
|
|
|
load_picture ();
|
|
img_changed_hook ();
|
|
}
|
|
|
|
static void
|
|
first_img_cb (GtkWidget *w, gpointer d)
|
|
{
|
|
lp = g_list_first (img_list);
|
|
if (lp)
|
|
img = (ImageItem *) lp->data;
|
|
|
|
load_picture ();
|
|
img_changed_hook ();
|
|
}
|
|
|
|
static void
|
|
last_img_cb (GtkWidget *w, gpointer d)
|
|
{
|
|
lp = g_list_last (img_list);
|
|
if (lp)
|
|
img = (ImageItem *) lp->data;
|
|
|
|
load_picture ();
|
|
img_changed_hook ();
|
|
}
|
|
|
|
void
|
|
picture_fit_to_window ()
|
|
{
|
|
gdouble width, height, ww, wh;
|
|
gdouble factor;
|
|
|
|
if (!gtk_widget_get_realized (viewport) || !img)
|
|
return;
|
|
|
|
width = gdk_pixbuf_get_width (img->orig_pb);
|
|
height = gdk_pixbuf_get_height (img->orig_pb);
|
|
|
|
ww = gdk_window_get_width (gtk_viewport_get_view_window (GTK_VIEWPORT (viewport)));
|
|
wh = gdk_window_get_height (gtk_viewport_get_view_window (GTK_VIEWPORT (viewport)));
|
|
|
|
factor = MIN (ww / width, wh / height);
|
|
if (factor < 1.0)
|
|
{
|
|
GdkPixbuf *pb = gdk_pixbuf_scale_simple (img->orig_pb, width * factor, height * factor, GDK_INTERP_HYPER);
|
|
if (pb)
|
|
gtk_image_set_from_pixbuf (GTK_IMAGE (picture), pb);
|
|
}
|
|
}
|
|
|
|
static void
|
|
change_size_cb (GtkWidget *w, gint type)
|
|
{
|
|
gdouble width, height;
|
|
GdkPixbuf *new_pb, *pb = gtk_image_get_pixbuf (GTK_IMAGE (picture));
|
|
|
|
if (!pb)
|
|
{
|
|
g_printerr ("picture: can't get pixbuf\n");
|
|
return;
|
|
}
|
|
|
|
width = gdk_pixbuf_get_width (pb);
|
|
height = gdk_pixbuf_get_height (pb);
|
|
|
|
switch (type)
|
|
{
|
|
case SIZE_FIT:
|
|
picture_fit_to_window ();
|
|
options.picture_data.size = YAD_PICTURE_FIT;
|
|
break;
|
|
case SIZE_ORIG:
|
|
gtk_image_set_from_pixbuf (GTK_IMAGE (picture), g_object_ref (img->orig_pb));
|
|
options.picture_data.size = YAD_PICTURE_ORIG;
|
|
break;
|
|
case SIZE_INC:
|
|
new_pb = gdk_pixbuf_scale_simple (img->orig_pb, width + options.picture_data.inc,
|
|
height + options.picture_data.inc, GDK_INTERP_HYPER);
|
|
if (new_pb)
|
|
{
|
|
gtk_image_set_from_pixbuf (GTK_IMAGE (picture), new_pb);
|
|
g_object_unref (pb);
|
|
}
|
|
break;
|
|
case SIZE_DEC:
|
|
new_pb = gdk_pixbuf_scale_simple (img->orig_pb, width - options.picture_data.inc,
|
|
height - options.picture_data.inc, GDK_INTERP_HYPER);
|
|
if (new_pb)
|
|
{
|
|
gtk_image_set_from_pixbuf (GTK_IMAGE (picture), new_pb);
|
|
g_object_unref (pb);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
rotate_cb (GtkWidget *w, gint type)
|
|
{
|
|
GdkPixbuf *new_pb = NULL;
|
|
GdkPixbuf *pb = gtk_image_get_pixbuf (GTK_IMAGE (picture));
|
|
|
|
if (!pb)
|
|
{
|
|
g_printerr ("picture: can't get pixbuf\n");
|
|
return;
|
|
}
|
|
|
|
switch (type)
|
|
{
|
|
case ROTATE_LEFT:
|
|
new_pb = gdk_pixbuf_rotate_simple (pb, GDK_PIXBUF_ROTATE_COUNTERCLOCKWISE);
|
|
break;
|
|
case ROTATE_RIGHT:
|
|
new_pb = gdk_pixbuf_rotate_simple (pb, GDK_PIXBUF_ROTATE_CLOCKWISE);
|
|
break;
|
|
case ROTATE_FLIP_VERT:
|
|
new_pb = gdk_pixbuf_flip (pb, FALSE);
|
|
break;
|
|
case ROTATE_FLIP_HOR:
|
|
new_pb = gdk_pixbuf_flip (pb, TRUE);
|
|
break;
|
|
}
|
|
|
|
if (new_pb)
|
|
{
|
|
gtk_image_set_from_pixbuf (GTK_IMAGE (picture), new_pb);
|
|
g_object_unref (pb);
|
|
}
|
|
}
|
|
|
|
static void
|
|
open_file_cb (GtkWidget *w, gpointer d)
|
|
{
|
|
GtkWidget *dlg;
|
|
GtkFileFilter *imgf, *allf;
|
|
static gchar *dir = NULL;
|
|
|
|
imgf = gtk_file_filter_new ();
|
|
gtk_file_filter_set_name (imgf, _("Images"));
|
|
gtk_file_filter_add_pixbuf_formats (imgf);
|
|
|
|
allf = gtk_file_filter_new ();
|
|
gtk_file_filter_set_name (allf, _("All files"));
|
|
gtk_file_filter_add_pattern (allf, "*");
|
|
|
|
dlg = gtk_file_chooser_dialog_new (_("YAD - Select Image(s)"),
|
|
GTK_WINDOW (gtk_widget_get_toplevel (w)),
|
|
GTK_FILE_CHOOSER_ACTION_OPEN,
|
|
_("Cancel"), GTK_RESPONSE_CANCEL,
|
|
_("OK"), GTK_RESPONSE_ACCEPT,
|
|
NULL);
|
|
gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dlg), TRUE);
|
|
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dlg), imgf);
|
|
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dlg), allf);
|
|
if (dir)
|
|
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dlg), dir);
|
|
|
|
if (gtk_dialog_run (GTK_DIALOG (dlg)) == GTK_RESPONSE_ACCEPT)
|
|
{
|
|
GSList *fp, *fn = gtk_file_chooser_get_filenames (GTK_FILE_CHOOSER (dlg));
|
|
|
|
if (img_list)
|
|
{
|
|
g_list_free_full (img_list, (GDestroyNotify) img_free);
|
|
img_list = NULL;
|
|
}
|
|
|
|
for (fp = fn; fp; fp = fp->next)
|
|
{
|
|
ImageItem *ii = g_new0 (ImageItem, 1);
|
|
|
|
ii->filename = g_strdup (fp->data);
|
|
img_list = g_list_append (img_list, ii);
|
|
}
|
|
g_slist_free_full (fn, g_free);
|
|
|
|
lp = g_list_first (img_list);
|
|
img = (ImageItem *) lp->data;
|
|
load_picture ();
|
|
img_changed_hook ();
|
|
|
|
/* recreate menu */
|
|
gtk_widget_destroy (popup_menu);
|
|
create_popup_menu ();
|
|
|
|
/* keep current dir */
|
|
g_free (dir);
|
|
dir = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (dlg));
|
|
}
|
|
|
|
gtk_widget_destroy (dlg);
|
|
}
|
|
|
|
static void
|
|
copy_cb (GtkWidget *w, gint type)
|
|
{
|
|
GtkClipboard *clip;
|
|
|
|
clip = gtk_clipboard_get_default (gdk_display_get_default ());
|
|
|
|
switch (type)
|
|
{
|
|
case COPY_IMAGE:
|
|
gtk_clipboard_set_image (clip, img->orig_pb);
|
|
break;
|
|
case COPY_FILE:
|
|
gtk_clipboard_set_text (clip, img->filename, -1);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
create_popup_menu ()
|
|
{
|
|
GtkWidget *mi, *al;
|
|
|
|
popup_menu = gtk_menu_new ();
|
|
gtk_menu_set_reserve_toggle_size (GTK_MENU (popup_menu), FALSE);
|
|
|
|
if (options.common_data.file_op)
|
|
{
|
|
mi = gtk_menu_item_new_with_label (_("Open file(s)..."));
|
|
al = gtk_bin_get_child (GTK_BIN (mi));
|
|
gtk_accel_label_set_accel (GTK_ACCEL_LABEL (al), GDK_KEY_o, GDK_CONTROL_MASK);
|
|
gtk_widget_show (mi);
|
|
gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), mi);
|
|
g_signal_connect (G_OBJECT (mi), "activate", G_CALLBACK (open_file_cb), NULL);
|
|
|
|
mi = gtk_separator_menu_item_new ();
|
|
gtk_widget_show (mi);
|
|
gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), mi);
|
|
}
|
|
|
|
if (img_list)
|
|
{
|
|
mi = gtk_menu_item_new_with_label (_("Next image"));
|
|
al = gtk_bin_get_child (GTK_BIN (mi));
|
|
gtk_accel_label_set_accel (GTK_ACCEL_LABEL (al), GDK_KEY_Right, 0);
|
|
gtk_widget_show (mi);
|
|
gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), mi);
|
|
g_signal_connect (G_OBJECT (mi), "activate", G_CALLBACK (next_img_cb), NULL);
|
|
|
|
mi = gtk_menu_item_new_with_label (_("Previous image"));
|
|
al = gtk_bin_get_child (GTK_BIN (mi));
|
|
gtk_accel_label_set_accel (GTK_ACCEL_LABEL (al), GDK_KEY_Left, 0);
|
|
gtk_widget_show (mi);
|
|
gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), mi);
|
|
g_signal_connect (G_OBJECT (mi), "activate", G_CALLBACK (prev_img_cb), NULL);
|
|
|
|
mi = gtk_menu_item_new_with_label (_("First image"));
|
|
al = gtk_bin_get_child (GTK_BIN (mi));
|
|
gtk_accel_label_set_accel (GTK_ACCEL_LABEL (al), GDK_KEY_Home, 0);
|
|
gtk_widget_show (mi);
|
|
gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), mi);
|
|
g_signal_connect (G_OBJECT (mi), "activate", G_CALLBACK (first_img_cb), NULL);
|
|
|
|
mi = gtk_menu_item_new_with_label (_("Last image"));
|
|
al = gtk_bin_get_child (GTK_BIN (mi));
|
|
gtk_accel_label_set_accel (GTK_ACCEL_LABEL (al), GDK_KEY_End, 0);
|
|
gtk_widget_show (mi);
|
|
gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), mi);
|
|
g_signal_connect (G_OBJECT (mi), "activate", G_CALLBACK (last_img_cb), NULL);
|
|
|
|
mi = gtk_separator_menu_item_new ();
|
|
gtk_widget_show (mi);
|
|
gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), mi);
|
|
}
|
|
|
|
mi = gtk_menu_item_new_with_label (_("Fit to window"));
|
|
al = gtk_bin_get_child (GTK_BIN (mi));
|
|
gtk_accel_label_set_accel (GTK_ACCEL_LABEL (al), GDK_KEY_w, 0);
|
|
gtk_widget_show (mi);
|
|
gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), mi);
|
|
g_signal_connect (G_OBJECT (mi), "activate", G_CALLBACK (change_size_cb), GINT_TO_POINTER (SIZE_FIT));
|
|
|
|
mi = gtk_menu_item_new_with_label (_("Original size"));
|
|
al = gtk_bin_get_child (GTK_BIN (mi));
|
|
gtk_accel_label_set_accel (GTK_ACCEL_LABEL (al), GDK_KEY_o, 0);
|
|
gtk_widget_show (mi);
|
|
gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), mi);
|
|
g_signal_connect (G_OBJECT (mi), "activate", G_CALLBACK (change_size_cb), GINT_TO_POINTER (SIZE_ORIG));
|
|
|
|
mi = gtk_menu_item_new_with_label (_("Increase size"));
|
|
al = gtk_bin_get_child (GTK_BIN (mi));
|
|
gtk_accel_label_set_accel (GTK_ACCEL_LABEL (al), GDK_KEY_plus, 0);
|
|
gtk_widget_show (mi);
|
|
gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), mi);
|
|
g_signal_connect (G_OBJECT (mi), "activate", G_CALLBACK (change_size_cb), GINT_TO_POINTER (SIZE_INC));
|
|
|
|
mi = gtk_menu_item_new_with_label (_("Decrease size"));
|
|
al = gtk_bin_get_child (GTK_BIN (mi));
|
|
gtk_accel_label_set_accel (GTK_ACCEL_LABEL (al), GDK_KEY_minus, 0);
|
|
gtk_widget_show (mi);
|
|
gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), mi);
|
|
g_signal_connect (G_OBJECT (mi), "activate", G_CALLBACK (change_size_cb), GINT_TO_POINTER (SIZE_DEC));
|
|
|
|
mi = gtk_separator_menu_item_new ();
|
|
gtk_widget_show (mi);
|
|
gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), mi);
|
|
|
|
mi = gtk_menu_item_new_with_label (_("Rotate left"));
|
|
al = gtk_bin_get_child (GTK_BIN (mi));
|
|
gtk_accel_label_set_accel (GTK_ACCEL_LABEL (al), GDK_KEY_l, 0);
|
|
gtk_widget_show (mi);
|
|
gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), mi);
|
|
g_signal_connect (G_OBJECT (mi), "activate", G_CALLBACK (rotate_cb), GINT_TO_POINTER (ROTATE_LEFT));
|
|
|
|
mi = gtk_menu_item_new_with_label (_("Rotate right"));
|
|
al = gtk_bin_get_child (GTK_BIN (mi));
|
|
gtk_accel_label_set_accel (GTK_ACCEL_LABEL (al), GDK_KEY_r, 0);
|
|
gtk_widget_show (mi);
|
|
gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), mi);
|
|
g_signal_connect (G_OBJECT (mi), "activate", G_CALLBACK (rotate_cb), GINT_TO_POINTER (ROTATE_RIGHT));
|
|
|
|
mi = gtk_menu_item_new_with_label (_("Flip vertical"));
|
|
al = gtk_bin_get_child (GTK_BIN (mi));
|
|
gtk_accel_label_set_accel (GTK_ACCEL_LABEL (al), GDK_KEY_v, 0);
|
|
gtk_widget_show (mi);
|
|
gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), mi);
|
|
g_signal_connect (G_OBJECT (mi), "activate", G_CALLBACK (rotate_cb), GINT_TO_POINTER (ROTATE_FLIP_VERT));
|
|
|
|
mi = gtk_menu_item_new_with_label (_("Flip horizontal"));
|
|
al = gtk_bin_get_child (GTK_BIN (mi));
|
|
gtk_accel_label_set_accel (GTK_ACCEL_LABEL (al), GDK_KEY_h, 0);
|
|
gtk_widget_show (mi);
|
|
gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), mi);
|
|
g_signal_connect (G_OBJECT (mi), "activate", G_CALLBACK (rotate_cb), GINT_TO_POINTER (ROTATE_FLIP_HOR));
|
|
|
|
mi = gtk_separator_menu_item_new ();
|
|
gtk_widget_show (mi);
|
|
gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), mi);
|
|
|
|
mi = gtk_menu_item_new_with_label (_("Copy image to clipboard"));
|
|
gtk_widget_show (mi);
|
|
gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), mi);
|
|
g_signal_connect (G_OBJECT (mi), "activate", G_CALLBACK (copy_cb), GINT_TO_POINTER (COPY_IMAGE));
|
|
|
|
mi = gtk_menu_item_new_with_label (_("Copy filename to clipboard"));
|
|
gtk_widget_show (mi);
|
|
gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), mi);
|
|
g_signal_connect (G_OBJECT (mi), "activate", G_CALLBACK (copy_cb), GINT_TO_POINTER (COPY_FILE));
|
|
}
|
|
|
|
static gboolean
|
|
button_handler (GtkWidget *w, GdkEventButton *ev, gpointer data)
|
|
{
|
|
if (ev->button == 3 && (!img || !img->animated))
|
|
{
|
|
gtk_menu_popup_at_pointer (GTK_MENU (popup_menu), NULL);
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static gboolean
|
|
key_handler (GtkWidget *w, GdkEventKey *ev, gpointer data)
|
|
{
|
|
switch (ev->keyval)
|
|
{
|
|
case GDK_KEY_Right:
|
|
case GDK_KEY_KP_Right:
|
|
next_img_cb (w, NULL);
|
|
return TRUE;
|
|
case GDK_KEY_Left:
|
|
case GDK_KEY_KP_Left:
|
|
prev_img_cb (w, NULL);
|
|
return TRUE;
|
|
case GDK_KEY_Home:
|
|
case GDK_KEY_KP_Home:
|
|
first_img_cb (w, NULL);
|
|
return TRUE;
|
|
case GDK_KEY_End:
|
|
case GDK_KEY_KP_End:
|
|
last_img_cb (w, NULL);
|
|
return TRUE;
|
|
case GDK_KEY_W:
|
|
case GDK_KEY_w:
|
|
change_size_cb (w, SIZE_FIT);
|
|
return TRUE;
|
|
case GDK_KEY_O:
|
|
case GDK_KEY_o:
|
|
if (ev->state & GDK_CONTROL_MASK)
|
|
open_file_cb (w, NULL);
|
|
else
|
|
change_size_cb (w, SIZE_ORIG);
|
|
return TRUE;
|
|
case GDK_KEY_plus:
|
|
case GDK_KEY_KP_Add:
|
|
change_size_cb (w, SIZE_INC);
|
|
return TRUE;
|
|
case GDK_KEY_minus:
|
|
case GDK_KEY_KP_Subtract:
|
|
change_size_cb (w, SIZE_DEC);
|
|
return TRUE;
|
|
case GDK_KEY_L:
|
|
case GDK_KEY_l:
|
|
rotate_cb (w, ROTATE_LEFT);
|
|
return TRUE;
|
|
case GDK_KEY_R:
|
|
case GDK_KEY_r:
|
|
rotate_cb (w, ROTATE_RIGHT);
|
|
return TRUE;
|
|
case GDK_KEY_V:
|
|
case GDK_KEY_v:
|
|
rotate_cb (w, ROTATE_FLIP_VERT);
|
|
return TRUE;
|
|
case GDK_KEY_H:
|
|
case GDK_KEY_h:
|
|
rotate_cb (w, ROTATE_FLIP_HOR);
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
size_allocate_cb ()
|
|
{
|
|
if (options.picture_data.size == YAD_PICTURE_FIT)
|
|
picture_fit_to_window ();
|
|
}
|
|
|
|
static void init_img_data ()
|
|
{
|
|
if (options.common_data.uri)
|
|
{
|
|
img = g_new0 (ImageItem, 1);
|
|
img->filename = options.common_data.uri;
|
|
}
|
|
else if (options.extra_data && *options.extra_data)
|
|
{
|
|
gchar **args = options.extra_data;
|
|
gint i = 0;
|
|
|
|
while (args[i] != NULL)
|
|
{
|
|
ImageItem *ii;
|
|
|
|
ii = g_new0 (ImageItem, 1);
|
|
ii->filename = g_strdup (args[i]);
|
|
img_list = g_list_append (img_list, ii);
|
|
i++;
|
|
}
|
|
|
|
lp = g_list_first (img_list);
|
|
img = (ImageItem *) lp->data;
|
|
}
|
|
}
|
|
|
|
GtkWidget *
|
|
picture_create_widget (GtkWidget * dlg)
|
|
{
|
|
GtkWidget *sw, *ev;
|
|
|
|
sw = gtk_scrolled_window_new (NULL, NULL);
|
|
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_NONE);
|
|
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), options.data.hscroll_policy, options.data.vscroll_policy);
|
|
|
|
viewport = gtk_viewport_new (gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (sw)),
|
|
gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (sw)));
|
|
gtk_container_add (GTK_CONTAINER (sw), viewport);
|
|
|
|
ev = gtk_event_box_new ();
|
|
gtk_container_add (GTK_CONTAINER (viewport), ev);
|
|
|
|
picture = gtk_image_new ();
|
|
gtk_widget_set_can_focus (picture, TRUE); /* need to get key press events */
|
|
gtk_container_add (GTK_CONTAINER (ev), picture);
|
|
|
|
g_signal_connect (G_OBJECT (ev), "button-press-event", G_CALLBACK (button_handler), NULL);
|
|
g_signal_connect (G_OBJECT (ev), "key-press-event", G_CALLBACK (key_handler), NULL);
|
|
g_signal_connect (G_OBJECT (ev), "size-allocate", G_CALLBACK (size_allocate_cb), NULL);
|
|
|
|
init_img_data ();
|
|
|
|
/* must be after calling init_img_data() */
|
|
create_popup_menu ();
|
|
|
|
/* load picture */
|
|
if (img)
|
|
load_picture ();
|
|
else
|
|
gtk_image_set_from_icon_name (GTK_IMAGE (picture), "image-missing", GTK_ICON_SIZE_DIALOG);
|
|
|
|
return sw;
|
|
}
|