예제 #1
0
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);
}
예제 #2
0
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;
}
예제 #3
0
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;
}