diff options
author | Přemysl Eric Janouch <p@janouch.name> | 2021-12-19 12:35:53 +0100 |
---|---|---|
committer | Přemysl Eric Janouch <p@janouch.name> | 2021-12-21 13:05:11 +0100 |
commit | 9899a266357a30c4371bdc4c66c3dc5af9b66ff0 (patch) | |
tree | 3d59744f0b6e3d765da7fc54d5ef7ef39ea34b3b | |
parent | 24f9d21ca759570ae6e79e7440bcab00091ae14e (diff) | |
download | fiv-9899a266357a30c4371bdc4c66c3dc5af9b66ff0.tar.gz fiv-9899a266357a30c4371bdc4c66c3dc5af9b66ff0.tar.xz fiv-9899a266357a30c4371bdc4c66c3dc5af9b66ff0.zip |
Add a file information dialog based on ExifTool
Right now, it isn't very pleasing to use.
-rw-r--r-- | README.adoc | 5 | ||||
-rw-r--r-- | fastiv.c | 6 | ||||
-rw-r--r-- | fiv-view.c | 78 | ||||
-rw-r--r-- | fiv-view.h | 1 |
4 files changed, 85 insertions, 5 deletions
diff --git a/README.adoc b/README.adoc index 2f4f353..0a80fb0 100644 --- a/README.adoc +++ b/README.adoc @@ -5,8 +5,7 @@ fastiv raw photos, HEIC, AVIF, WebP, SVG, X11 cursors and TIFF, or whatever gdk-pixbuf loads. -It still has some road to go, but it's already become quite usable, -and it has received basic polishing. +Its development status can be summarized as '`beta`'. Non-goals --------- @@ -27,7 +26,7 @@ Build dependencies: Meson, pkg-config + Runtime dependencies: gtk+-3.0, glib>=2.64, pixman-1, shared-mime-info, spng>=0.7.0, libturbojpeg + Optional dependencies: LibRaw, librsvg-2.0, xcursor, libwebp, libheif, libtiff, -gdk-pixbuf-2.0 +gdk-pixbuf-2.0, ExifTool $ git clone --recursive https://git.janouch.name/p/fastiv.git $ meson builddir @@ -147,6 +147,7 @@ static struct key_group help_keys_view[] = { {"<control>p", "Print..."}, {"<control>s", "Save page as..."}, {"<control><shift>s", "Save frame as..."}, + {"<alt>Return", "Show file information"}, {} }}, {} @@ -203,7 +204,6 @@ make_key_window(void) // TODO(p): See if it's possible to give separators room to shrink // by some minor amount of pixels, margin-wise. -// TODO(p): Implement commented-out actions. #define B make_toolbar_button #define T make_toolbar_toggle #define TOOLBAR(XX) \ @@ -234,7 +234,7 @@ make_key_window(void) /* XX(COLOR, B("preferences-color-symbolic", "Color management")) */ \ XX(SAVE, B("document-save-as-symbolic", "Save as...")) \ XX(PRINT, B("document-print-symbolic", "Print...")) \ - /* XX(INFO, B("info-symbolic", "Information")) */ \ + XX(INFO, B("info-symbolic", "Information")) \ XX(S5, gtk_separator_new(GTK_ORIENTATION_HORIZONTAL)) \ XX(LEFT, B("object-rotate-left-symbolic", "Rotate left")) \ XX(MIRROR, B("object-flip-horizontal-symbolic", "Mirror")) \ @@ -948,6 +948,7 @@ on_view_actions_changed(void) gtk_widget_set_sensitive(g.toolbar[TOOLBAR_CHECKERBOARD], has_image); gtk_widget_set_sensitive(g.toolbar[TOOLBAR_SAVE], has_image); gtk_widget_set_sensitive(g.toolbar[TOOLBAR_PRINT], has_image); + gtk_widget_set_sensitive(g.toolbar[TOOLBAR_INFO], has_image); gtk_widget_set_sensitive(g.toolbar[TOOLBAR_LEFT], has_image); gtk_widget_set_sensitive(g.toolbar[TOOLBAR_MIRROR], has_image); @@ -1092,6 +1093,7 @@ make_view_toolbar(void) toolbar_toggler(TOOLBAR_CHECKERBOARD, "checkerboard"); toolbar_command(TOOLBAR_PRINT, FIV_VIEW_COMMAND_PRINT); toolbar_command(TOOLBAR_SAVE, FIV_VIEW_COMMAND_SAVE_PAGE); + toolbar_command(TOOLBAR_INFO, FIV_VIEW_COMMAND_INFO); toolbar_command(TOOLBAR_LEFT, FIV_VIEW_COMMAND_ROTATE_LEFT); toolbar_command(TOOLBAR_MIRROR, FIV_VIEW_COMMAND_MIRROR); toolbar_command(TOOLBAR_RIGHT, FIV_VIEW_COMMAND_ROTATE_RIGHT); @@ -786,6 +786,76 @@ save_as(FivView *self, gboolean frame) } } +static void +info(FivView *self) +{ + // TODO(p): Add a fallback to internal capabilities. + // The simplest is to specify the filename and the resolution. + GtkWindow *window = get_toplevel(GTK_WIDGET(self)); + int flags = G_SUBPROCESS_FLAGS_STDOUT_PIPE | G_SUBPROCESS_FLAGS_STDERR_PIPE; + + GError *error = NULL; + GSubprocess *subprocess = g_subprocess_new(flags, &error, "exiftool", + "-tab", "-groupNames", "-duplicates", "-extractEmbedded", "--binary", + "-quiet", "--", self->path, NULL); + if (error) { + show_error_dialog(window, error); + return; + } + + gchar *out = NULL, *err = NULL; + if (!g_subprocess_communicate_utf8( + subprocess, NULL, NULL, &out, &err, &error)) { + show_error_dialog(window, error); + return; + } + + GtkWidget *dialog = gtk_widget_new(GTK_TYPE_DIALOG, + "use-header-bar", TRUE, + "title", "Information", + "transient-for", window, + "destroy-with-parent", TRUE, NULL); + + GtkWidget *content_area = gtk_dialog_get_content_area(GTK_DIALOG(dialog)); + if (*err) { + GtkWidget *info = gtk_info_bar_new(); + GtkInfoBar *info_bar = GTK_INFO_BAR(info); + gtk_info_bar_set_message_type(info_bar, GTK_MESSAGE_WARNING); + + GtkWidget *info_area = gtk_info_bar_get_content_area(info_bar); + GtkWidget *label = gtk_label_new(g_strstrip(err)); + gtk_container_add(GTK_CONTAINER(info_area), label); + + gtk_container_add(GTK_CONTAINER(content_area), info); + } + + // TODO(p): Parse as GROUP\tTAG\tVALUE, do s/_/ /g in the group name, + // put the data in a GtkTreeModel/GtkTreeView. + GtkWidget *label = gtk_label_new(out); + gtk_label_set_selectable(GTK_LABEL(label), TRUE); + gtk_label_set_xalign(GTK_LABEL(label), 0.); + gtk_label_set_yalign(GTK_LABEL(label), 0.); + gtk_widget_set_hexpand(label, TRUE); + gtk_widget_set_vexpand(label, TRUE); + + GtkWidget *scroller = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_max_content_width( + GTK_SCROLLED_WINDOW(scroller), 800); + gtk_scrolled_window_set_max_content_height( + GTK_SCROLLED_WINDOW(scroller), 800); + gtk_scrolled_window_set_propagate_natural_width( + GTK_SCROLLED_WINDOW(scroller), TRUE); + gtk_scrolled_window_set_propagate_natural_height( + GTK_SCROLLED_WINDOW(scroller), TRUE); + gtk_container_add(GTK_CONTAINER(scroller), label); + gtk_container_add(GTK_CONTAINER(content_area), scroller); + + g_free(out); + g_free(err); + g_object_unref(subprocess); + gtk_widget_show_all(dialog); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - static inline gboolean @@ -823,6 +893,12 @@ fiv_view_key_press_event(GtkWidget *widget, GdkEventKey *event) return save_as(self, TRUE); } } + if (state == GDK_MOD1_MASK) { + switch (event->keyval) { + case GDK_KEY_Return: + return command(self, FIV_VIEW_COMMAND_INFO); + } + } if (state != 0) return FALSE; @@ -1043,6 +1119,8 @@ fiv_view_command(FivView *self, FivViewCommand command) print(self); break; case FIV_VIEW_COMMAND_SAVE_PAGE: save_as(self, FALSE); + break; case FIV_VIEW_COMMAND_INFO: + info(self); break; case FIV_VIEW_COMMAND_ZOOM_IN: set_scale(self, self->scale * SCALE_STEP); @@ -45,6 +45,7 @@ typedef enum _FivViewCommand { FIV_VIEW_COMMAND_TOGGLE_CHECKERBOARD, FIV_VIEW_COMMAND_PRINT, FIV_VIEW_COMMAND_SAVE_PAGE, + FIV_VIEW_COMMAND_INFO, FIV_VIEW_COMMAND_ZOOM_IN, FIV_VIEW_COMMAND_ZOOM_OUT, |