static void gwy_recent_file_update_thumbnail(GwyRecentFile *rf, GwyContainer *data, gint hint, GdkPixbuf *use_this_pixbuf) { GwyDataField *dfield; GdkPixbuf *pixbuf; GStatBuf st; gchar *fnm; GwySIUnit *siunit; GwySIValueFormat *vf; gdouble xreal, yreal; gchar str_mtime[22]; gchar str_size[22]; gchar str_width[22]; gchar str_height[22]; GError *err = NULL; GQuark quark; gint id; g_return_if_fail(GWY_CONTAINER(data)); if (use_this_pixbuf) { /* If we are given a pixbuf, hint must be the ultimate channel id. * We also ignore the thnumbnail state then. */ g_return_if_fail(GDK_IS_PIXBUF(use_this_pixbuf)); id = hint; pixbuf = g_object_ref(use_this_pixbuf); } else { pixbuf = NULL; id = gwy_recent_file_find_some_channel(data, hint); if (rf->file_state == FILE_STATE_UNKNOWN) gwy_app_recent_file_try_load_thumbnail(rf); } /* Find channel with the lowest id not smaller than hint */ if (id == G_MAXINT) { gwy_debug("There is no channel in the file, cannot make thumbnail."); return; } if (g_stat(rf->file_sys, &st) != 0) { g_warning("File <%s> was just loaded or saved, but it doesn't seem to " "exist any more: %s", rf->file_utf8, g_strerror(errno)); return; } if ((gulong)rf->file_mtime == (gulong)st.st_mtime) return; quark = gwy_app_get_data_key_for_id(id); dfield = GWY_DATA_FIELD(gwy_container_get_object(data, quark)); g_return_if_fail(GWY_IS_DATA_FIELD(dfield)); rf->file_mtime = st.st_mtime; rf->file_size = st.st_size; rf->image_width = gwy_data_field_get_xres(dfield); rf->image_height = gwy_data_field_get_yres(dfield); xreal = gwy_data_field_get_xreal(dfield); yreal = gwy_data_field_get_yreal(dfield); siunit = gwy_data_field_get_si_unit_xy(dfield); vf = gwy_si_unit_get_format(siunit, GWY_SI_UNIT_FORMAT_VFMARKUP, sqrt(xreal*yreal), NULL); g_free(rf->image_real_size); rf->image_real_size = g_strdup_printf("%.*f×%.*f%s%s", vf->precision, xreal/vf->magnitude, vf->precision, yreal/vf->magnitude, (vf->units && *vf->units) ? " " : "", vf->units); rf->file_state = FILE_STATE_OK; gwy_si_unit_value_format_free(vf); if (g_str_has_prefix(rf->file_sys, gwy_recent_file_thumbnail_dir())) { gchar c; c = rf->file_sys[strlen(gwy_recent_file_thumbnail_dir())]; if (!c || G_IS_DIR_SEPARATOR(c)) return; } if (!pixbuf) pixbuf = gwy_app_get_channel_thumbnail(data, id, TMS_NORMAL_THUMB_SIZE, TMS_NORMAL_THUMB_SIZE); g_snprintf(str_mtime, sizeof(str_mtime), "%lu", rf->file_mtime); g_snprintf(str_size, sizeof(str_size), "%lu", rf->file_size); g_snprintf(str_width, sizeof(str_width), "%d", rf->image_width); g_snprintf(str_height, sizeof(str_height), "%d", rf->image_height); /* invent an unique temporary name for atomic save * FIXME: rough, but works on Win32 */ fnm = g_strdup_printf("%s.%u", rf->thumb_sys, getpid()); if (!gdk_pixbuf_save(pixbuf, fnm, "png", &err, KEY_SOFTWARE, PACKAGE_NAME, KEY_THUMB_URI, rf->file_uri, KEY_THUMB_MTIME, str_mtime, KEY_THUMB_FILESIZE, str_size, KEY_THUMB_IMAGE_WIDTH, str_width, KEY_THUMB_IMAGE_HEIGHT, str_height, KEY_THUMB_GWY_REAL_SIZE, rf->image_real_size, NULL)) { g_clear_error(&err); rf->thumb_state = FILE_STATE_FAILED; } #ifndef G_OS_WIN32 chmod(fnm, 0600); #endif g_unlink(rf->thumb_sys); if (g_rename(fnm, rf->thumb_sys) != 0) { g_unlink(fnm); rf->thumb_state = FILE_STATE_FAILED; rf->thumb_mtime = 0; } else { rf->thumb_state = FILE_STATE_UNKNOWN; /* force reload */ rf->thumb_mtime = rf->file_mtime; } g_free(fnm); gwy_object_unref(rf->pixbuf); g_object_unref(pixbuf); }
static gboolean gwy_app_file_chooser_do_full_preview(gpointer user_data) { GtkFileChooser *fchooser; GtkTreeModel *model; GtkListStore *store; GwyAppFileChooser *chooser; GSList *channel_ids, *l; GdkPixbuf *pixbuf; GtkTreeIter iter; GString *str; gint id; chooser = GWY_APP_FILE_CHOOSER(user_data); chooser->full_preview_id = 0; /* Always no-op here? */ gwy_app_file_chooser_free_preview(chooser); fchooser = GTK_FILE_CHOOSER(chooser); chooser->preview_name_sys = gtk_file_chooser_get_preview_filename(fchooser); /* We should not be called when gtk_file_chooser_get_preview_filename() * returns NULL preview file name */ if (!chooser->preview_name_sys) { g_warning("Full preview invoked with NULL preview file name"); return FALSE; } model = gtk_icon_view_get_model(GTK_ICON_VIEW(chooser->preview)); store = GTK_LIST_STORE(model); chooser->preview_data = gwy_file_load(chooser->preview_name_sys, GWY_RUN_NONINTERACTIVE, NULL); if (!chooser->preview_data) { gwy_app_file_chooser_free_preview(chooser); gtk_tree_model_get_iter_first(model, &iter); gtk_list_store_set(store, &iter, COLUMN_FILEINFO, _("Cannot preview"), -1); return FALSE; } channel_ids = NULL; gwy_container_foreach(chooser->preview_data, NULL, add_channel_id, &channel_ids); channel_ids = g_slist_sort(channel_ids, compare_ids); if (!channel_ids) { gwy_app_file_chooser_free_preview(chooser); return FALSE; } g_object_set(chooser->renderer_fileinfo, "ellipsize", PANGO_ELLIPSIZE_END, "wrap-width", -1, NULL); gtk_list_store_clear(store); str = g_string_new(NULL); for (l = channel_ids; l; l = g_slist_next(l)) { id = GPOINTER_TO_INT(l->data); pixbuf = gwy_app_get_channel_thumbnail(chooser->preview_data, id, TMS_NORMAL_THUMB_SIZE, TMS_NORMAL_THUMB_SIZE); if (!pixbuf) { g_warning("Cannot make a pixbuf of channel %d", id); continue; } if (chooser->make_thumbnail) { _gwy_app_recent_file_write_thumbnail(chooser->preview_name_sys, chooser->preview_data, id, pixbuf); chooser->make_thumbnail = FALSE; } gwy_app_file_chooser_describe_channel(chooser->preview_data, id, str); gtk_list_store_insert_with_values(store, &iter, -1, COLUMN_PIXBUF, pixbuf, COLUMN_FILEINFO, str->str, -1); g_object_unref(pixbuf); } g_string_free(str, TRUE); return FALSE; }
static gboolean gwy_app_file_chooser_do_full_preview(gpointer user_data) { GtkFileChooser *fchooser; GtkTreeModel *model; GtkListStore *store; GwyAppFileChooser *chooser; FileInfoData filedata; GwyContainer *data, *settings; GdkPixbuf *pixbuf; GtkTreeIter iter; const gchar *name; gboolean row_level = FALSE, plane_level = FALSE; GString *str; GSList *l; gint id; chooser = GWY_APP_FILE_CHOOSER(user_data); chooser->full_preview_id = 0; /* Always no-op here? */ gwy_app_file_chooser_free_preview(chooser); fchooser = GTK_FILE_CHOOSER(chooser); chooser->preview_name_sys = gtk_file_chooser_get_preview_filename(fchooser); /* We should not be called when gtk_file_chooser_get_preview_filename() * returns NULL preview file name */ if (!chooser->preview_name_sys) { g_warning("Full preview invoked with NULL preview file name"); return FALSE; } model = gtk_icon_view_get_model(GTK_ICON_VIEW(chooser->preview)); store = GTK_LIST_STORE(model); data = gwy_file_load(chooser->preview_name_sys, GWY_RUN_NONINTERACTIVE, NULL); if (!data) { gwy_app_file_chooser_free_preview(chooser); gtk_list_store_clear(store); gtk_list_store_append(store, &iter); gtk_list_store_set(store, &iter, COLUMN_FILEINFO, _("Cannot preview"), -1); return FALSE; } gwy_data_validate(data, GWY_DATA_VALIDATE_CORRECT | GWY_DATA_VALIDATE_NO_REPORT); memset(&filedata, 0, sizeof(FileInfoData)); gwy_container_foreach(data, NULL, add_object_id, &filedata); filedata.channels = g_slist_sort(filedata.channels, compare_ids); filedata.graphs = g_slist_sort(filedata.graphs, compare_ids); filedata.spectra = g_slist_sort(filedata.spectra, compare_ids); str = g_string_new(NULL); if (gwy_file_get_data_info(data, &name, NULL)) { /* FIXME: Make this translatable */ g_string_printf(str, "<small>%s", name); if (filedata.nchannels) g_string_append_printf(str, ", %d ch", filedata.nchannels); if (filedata.graphs) g_string_append_printf(str, ", %d gr", filedata.ngraphs); if (filedata.spectra) g_string_append_printf(str, ", %d sps", filedata.nspectra); g_string_append(str, "</small>"); gtk_label_set_markup(GTK_LABEL(chooser->preview_type), str->str); } if (!filedata.channels) { g_string_free(str, TRUE); g_slist_free(filedata.channels); g_slist_free(filedata.graphs); g_slist_free(filedata.spectra); g_object_unref(data); gwy_app_file_chooser_free_preview(chooser); return FALSE; } g_object_set(chooser->renderer_fileinfo, "ellipsize", PANGO_ELLIPSIZE_END, "wrap-width", -1, NULL); settings = gwy_app_settings_get(); gwy_container_gis_boolean_by_name(settings, "/app/file/preview/plane-level", &plane_level); gwy_container_gis_boolean_by_name(settings, "/app/file/preview/row-level", &row_level); gtk_list_store_clear(store); for (l = filedata.channels; l; l = g_slist_next(l)) { id = GPOINTER_TO_INT(l->data); modify_channel_for_preview(data, id, plane_level, row_level); pixbuf = gwy_app_get_channel_thumbnail(data, id, TMS_NORMAL_THUMB_SIZE, TMS_NORMAL_THUMB_SIZE); if (!pixbuf) { g_warning("Cannot make a pixbuf of channel %d", id); continue; } if (chooser->make_thumbnail) { _gwy_app_recent_file_write_thumbnail(chooser->preview_name_sys, data, id, pixbuf); chooser->make_thumbnail = FALSE; } gwy_app_file_chooser_describe_channel(data, id, str); gtk_list_store_insert_with_values(store, &iter, -1, COLUMN_PIXBUF, pixbuf, COLUMN_FILEINFO, str->str, -1); g_object_unref(pixbuf); } g_slist_free(filedata.channels); g_slist_free(filedata.graphs); g_slist_free(filedata.spectra); g_string_free(str, TRUE); g_object_unref(data); return FALSE; }