#include #include #include #include #include #include #include "dir.h" #define TIMEOUT 20 #define ZOOM_FACTOR 0.1 enum scale_mode { fit = 0, zoomed = 1, }; GtkWidget *window; GtkWidget *image; GdkPixbuf *pixbuf; GdkPixbuf *curr_pixbuf; int pixbuf_width, pixbuf_height; double aspect_ratio; double curr_zoom = 1.0; enum scale_mode curr_scale_mod; GError *error = NULL; char *curr_file_name; GDir *dir; char **file_list; int curr_file_index, file_list_count; void print_supported_formats() { GSList *list, *it; GdkPixbufFormat *format; gchar **extensions; gchar *ex; list = gdk_pixbuf_get_formats(); if (list != NULL) { for (it = list; it->next != NULL; it = it->next) { format = (GdkPixbufFormat *)it->data; g_print("%s:", gdk_pixbuf_format_get_description(format)); extensions = gdk_pixbuf_format_get_extensions(format); for (ex = *extensions; *ex; ex++) { g_print(" %s", ex); } g_print("\n"); } g_slist_free(list); } } void fit_image() { gint win_width, win_height; gint new_pixbuf_width, new_pixbuf_height; gtk_window_get_size(GTK_WINDOW(window), &win_width, &win_height); if (win_width < pixbuf_width && win_height > pixbuf_height) { new_pixbuf_width = win_width; new_pixbuf_height = (double)new_pixbuf_width / aspect_ratio; } else if (win_width > pixbuf_width && win_height < pixbuf_height) { new_pixbuf_height = win_height; new_pixbuf_width = (double)new_pixbuf_height * aspect_ratio; } else if (win_width < pixbuf_width && win_height < pixbuf_height) { if (((double)win_width / (double)win_height) > aspect_ratio) { new_pixbuf_height = win_height; new_pixbuf_width = ((double)new_pixbuf_height * aspect_ratio); } else { new_pixbuf_width = win_width; new_pixbuf_height = (double)new_pixbuf_width / aspect_ratio; } } else { new_pixbuf_width = pixbuf_width; new_pixbuf_height = pixbuf_height; } curr_zoom = (double)new_pixbuf_width / (double)pixbuf_width; if (curr_pixbuf != NULL) g_object_unref(curr_pixbuf); curr_pixbuf = gdk_pixbuf_scale_simple(GDK_PIXBUF(pixbuf), new_pixbuf_width, new_pixbuf_height, GDK_INTERP_BILINEAR); gtk_image_set_from_pixbuf(GTK_IMAGE(image), GDK_PIXBUF(curr_pixbuf)); } void next() { if (curr_file_index >= file_list_count - 1) { return; } curr_file_index++; curr_file_name = file_list[curr_file_index]; g_print("qwe2: %s\n", curr_file_name); g_object_unref(pixbuf); pixbuf = gdk_pixbuf_new_from_file(curr_file_name, &error); if (error) { g_warning("gdk_pixbuf_new_from_file() failed with error: %s\n", error->message); g_clear_error(&error); return; } pixbuf_width = gdk_pixbuf_get_width(GDK_PIXBUF(pixbuf)); pixbuf_height = gdk_pixbuf_get_height(GDK_PIXBUF(pixbuf)); aspect_ratio = (double)pixbuf_width / (double)pixbuf_height; curr_zoom = 1.0; fit_image(); } void prev() { if (curr_file_index <= 0) { return; } curr_file_index--; curr_file_name = file_list[curr_file_index]; g_print("qwe2: %s\n", curr_file_name); g_object_unref(pixbuf); pixbuf = gdk_pixbuf_new_from_file(curr_file_name, &error); if (error) { g_warning("gdk_pixbuf_new_from_file() failed with error: %s\n", error->message); g_clear_error(&error); return; } pixbuf_width = gdk_pixbuf_get_width(GDK_PIXBUF(pixbuf)); pixbuf_height = gdk_pixbuf_get_height(GDK_PIXBUF(pixbuf)); aspect_ratio = (double)pixbuf_width / (double)pixbuf_height; curr_zoom = 1.0; fit_image(); } void zoom(int type) { if (type == 0) { if (curr_zoom == 1.0) return; curr_zoom = (double)1.0; } else if (type < 0) { if (curr_zoom < 0.2) return; curr_zoom -= (double)ZOOM_FACTOR; } else if (type > 0) { if (curr_zoom > 2) return; curr_zoom += (double)ZOOM_FACTOR; } if (curr_pixbuf != NULL) g_object_unref(curr_pixbuf); curr_pixbuf = gdk_pixbuf_scale_simple(GDK_PIXBUF(pixbuf), pixbuf_width * curr_zoom, pixbuf_height * curr_zoom, GDK_INTERP_BILINEAR); gtk_image_set_from_pixbuf(GTK_IMAGE(image), GDK_PIXBUF(curr_pixbuf)); } static gboolean key_press(GtkWindow *window, GdkEvent *event, gpointer data) { switch (event->key.keyval) { case GDK_KEY_q: g_application_quit( G_APPLICATION(gtk_window_get_application(GTK_WINDOW(window)))); return FALSE; case GDK_KEY_w: curr_scale_mod = fit; fit_image(); return FALSE; case GDK_KEY_plus: zoom(1); return FALSE; case GDK_KEY_minus: zoom(-1); return FALSE; case GDK_KEY_equal: zoom(0); return FALSE; case GDK_KEY_n: case GDK_KEY_j: next(); return FALSE; case GDK_KEY_p: case GDK_KEY_k: prev(); return FALSE; default: return TRUE; } } gboolean scroll_callback(GtkWindow *window, GdkEvent *event, gpointer data) { GdkModifierType state; gdk_event_get_state(event, &state); if (state & GDK_CONTROL_MASK && event->scroll.direction == GDK_SCROLL_UP) { zoom(1); curr_scale_mod = zoomed; return FALSE; } else if (state & GDK_CONTROL_MASK && event->scroll.direction == GDK_SCROLL_DOWN) { zoom(-1); curr_scale_mod = zoomed; return FALSE; } return TRUE; } gboolean resize_done(gpointer data) { guint *id = data; *id = 0; fit_image(); return FALSE; } gboolean configure_callback(GtkWindow *window, GdkEvent *event, gpointer data) { if (curr_scale_mod != fit) { return FALSE; } static guint id = 0; if (id) g_source_remove(id); id = g_timeout_add(TIMEOUT, resize_done, &id); return FALSE; } static void activate(GtkApplication *app, gpointer user_data) { window = gtk_application_window_new(app); gtk_window_set_title(GTK_WINDOW(window), "qwe"); gtk_window_set_default_size(GTK_WINDOW(window), 800, 600); g_signal_connect(G_OBJECT(window), "configure-event", G_CALLBACK(configure_callback), NULL); g_signal_connect(G_OBJECT(window), "key-press-event", G_CALLBACK(key_press), NULL); gtk_widget_add_events(GTK_WIDGET(window), GDK_SCROLL_MASK); g_signal_connect(G_OBJECT(window), "scroll-event", G_CALLBACK(scroll_callback), NULL); char *curr_filename = "/home/nirav/Downloads/Saved Pictures/bash help shortcuts.png"; curr_file_index = scan(curr_filename, &file_list, &file_list_count); printf("num %d %d\n", curr_file_index, file_list_count); printf("file %s\n", file_list[curr_file_index]); pixbuf = gdk_pixbuf_new_from_file(curr_filename, &error); if (error) { g_warning("gdk_pixbuf_new_from_file() failed with error: %s\n", error->message); g_clear_error(&error); return; } pixbuf_width = gdk_pixbuf_get_width(GDK_PIXBUF(pixbuf)); pixbuf_height = gdk_pixbuf_get_height(GDK_PIXBUF(pixbuf)); aspect_ratio = (double)pixbuf_width / (double)pixbuf_height; image = gtk_image_new_from_pixbuf(GDK_PIXBUF(pixbuf)); GtkWidget *scrolled_window = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_container_add(GTK_CONTAINER(scrolled_window), GTK_WIDGET(image)); gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(scrolled_window)); gtk_widget_show_all(GTK_WIDGET(window)); } int main(int argc, char *argv[]) { GtkApplication *app; int status; app = gtk_application_new("org.gtk.qwe", G_APPLICATION_FLAGS_NONE); g_signal_connect(app, "activate", G_CALLBACK(activate), NULL); status = g_application_run(G_APPLICATION(app), argc, argv); g_object_unref(app); return status; }