aboutsummaryrefslogtreecommitdiffstats
path: root/opening.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--opening.c173
1 files changed, 173 insertions, 0 deletions
diff --git a/opening.c b/opening.c
new file mode 100644
index 0000000..3e98740
--- /dev/null
+++ b/opening.c
@@ -0,0 +1,173 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+int
+load_image(struct file *file, int errors_to_stderr)
+{
+ const char *error_message;
+ GError *error = NULL;
+ GtkWidget *dialog;
+ GdkPixbuf *image;
+ GdkPixbufLoader *loader = NULL;
+ struct stat st;
+ unsigned char buffer[8 << 10];
+ ssize_t r;
+ int fd, ret = 1;
+
+ if (!file)
+ return 0;
+
+ fd = open(file->path, O_RDONLY | O_NOCTTY);
+ if (fd < 0)
+ goto fail_errno;
+
+ if (fstat(fd, &st))
+ goto fail_errno;
+
+ if (!S_ISREG(st.st_mode)) {
+ error_message = "Not a regular file";
+ goto fail;
+ }
+
+ loader = gdk_pixbuf_loader_new();
+ if (!loader)
+ goto fail_errno;
+ for (;;) {
+ r = read(fd, buffer, sizeof(buffer));
+ if (r <= 0) {
+ if (!r)
+ break;
+ if (errno == EINTR)
+ continue;
+ goto fail_errno;
+ }
+ if (!gdk_pixbuf_loader_write(loader, buffer, (size_t)r, &error))
+ goto fail_gerror;
+ }
+ if (!gdk_pixbuf_loader_close(loader, &error)) {
+ fail_gerror:
+ error_message = error->message;
+ goto fail;
+ }
+ image = gdk_pixbuf_loader_get_pixbuf(loader);
+ if (!image) {
+ error_message = "Unsupported image format";
+ goto fail;
+ }
+ g_object_ref(image);
+
+ g_clear_object(&file->image);
+
+ file->size = st.st_size;
+ file->image = image;
+
+out:
+ g_clear_object(&loader);
+ if (fd >= 0)
+ close(fd);
+ return ret;
+
+fail_errno:
+ error_message = strerror(errno);
+
+fail:
+ if (errors_to_stderr) {
+ weprintf("Cannot open %s: %s", file->path, error_message);
+ } else {
+ dialog = gtk_message_dialog_new(GTK_WINDOW(window), GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_CLOSE, "Cannot open %s", file->path);
+ gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), "%s", error_message);
+ gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(dialog);
+ }
+
+ g_clear_error(&error);
+ ret = 0;
+ goto out;
+}
+
+static void
+preview_image(GtkFileChooser *chooser, GtkWidget *preview_widget)
+{
+ char *filename;
+ GdkPixbuf *preview;
+ GtkWidget *image, *label;
+
+ filename = gtk_file_chooser_get_preview_filename(chooser);
+ preview = !filename ? NULL :
+ gdk_pixbuf_new_from_file_at_scale(filename, PREVIEW_WIDTH, PREVIEW_HEIGHT, 1, NULL);
+ image = g_object_get_data(G_OBJECT(preview_widget), "image");
+ label = g_object_get_data(G_OBJECT(preview_widget), "label");
+ gtk_image_set_from_pixbuf(GTK_IMAGE(image), preview);
+ if (preview) {
+ gtk_widget_show(image);
+ gtk_widget_hide(label);
+ } else {
+ gtk_widget_hide(image);
+ gtk_widget_show(label);
+ }
+ gtk_file_chooser_set_preview_widget_active(chooser, 1);
+ if (preview)
+ g_object_unref(preview);
+ g_free(filename);
+}
+
+static const char *
+get_home_directory(void)
+{
+ static const char *home_directory = NULL;
+
+ struct passwd *pwd;
+
+ if (home_directory)
+ return home_directory;
+
+ home_directory = getenv("HOME");
+ if (!home_directory || !*home_directory) {
+ pwd = getpwuid(getuid());
+ if (pwd && pwd->pw_dir && *pwd->pw_dir)
+ home_directory = pwd->pw_dir;
+ else
+ home_directory = ".";
+ }
+
+ return home_directory;
+}
+
+GtkFileChooser *
+construct_chooser(void)
+{
+ GtkWidget *widget, *image, *label, *preview;
+ GtkFileChooser *chooser;
+
+ widget = gtk_file_chooser_dialog_new("Open",
+ GTK_WINDOW(window),
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
+ NULL);
+ chooser = GTK_FILE_CHOOSER(widget);
+
+ g_object_set(gtk_settings_get_default(), "gtk-recent-files-enabled", 0, NULL);
+ gtk_file_chooser_set_select_multiple(chooser, 1);
+ gtk_file_chooser_set_current_folder(chooser, get_home_directory());
+ gtk_file_chooser_set_local_only(chooser, 1);
+ gtk_file_chooser_set_do_overwrite_confirmation(chooser, 0);
+
+ preview = gtk_vbox_new(0, 6);
+ image = gtk_image_new();
+ label = gtk_label_new("Preview");
+ gtk_widget_set_size_request(preview, PREVIEW_WIDTH, PREVIEW_HEIGHT);
+ gtk_widget_set_size_request(image, PREVIEW_WIDTH, PREVIEW_HEIGHT);
+ gtk_box_pack_start(GTK_BOX(preview), image, 0, 0, 0u);
+ gtk_box_pack_start(GTK_BOX(preview), label, 0, 0, 0u);
+ g_object_set_data(G_OBJECT(preview), "image", image);
+ g_object_set_data(G_OBJECT(preview), "label", label);
+ gtk_file_chooser_set_preview_widget(chooser, preview);
+ gtk_file_chooser_set_use_preview_label(chooser, 0);
+ gtk_file_chooser_set_preview_widget_active(chooser, 1);
+ gtk_widget_hide(image);
+ g_signal_connect(chooser, "update-preview", G_CALLBACK(&preview_image), preview);
+
+ return chooser;
+}