743 lines
23 KiB
C
743 lines
23 KiB
C
/* PIKA - Photo and Image Kooker Application
|
|
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
|
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
|
*
|
|
* Original copyright, applying to most contents (license remains unchanged):
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <string.h>
|
|
|
|
#include <gegl.h>
|
|
#include <gtk/gtk.h>
|
|
|
|
#include "libpikabase/pikabase.h"
|
|
#include "libpikathumb/pikathumb.h"
|
|
#include "libpikawidgets/pikawidgets.h"
|
|
|
|
#include "widgets-types.h"
|
|
|
|
#include "config/pikacoreconfig.h"
|
|
|
|
#include "core/pika.h"
|
|
#include "core/pikacontext.h"
|
|
#include "core/pikaimagefile.h"
|
|
#include "core/pikaprogress.h"
|
|
#include "core/pikasubprogress.h"
|
|
|
|
#include "plug-in/pikapluginmanager-file.h"
|
|
|
|
#include "pikafiledialog.h" /* eek */
|
|
#include "pikathumbbox.h"
|
|
#include "pikaview.h"
|
|
#include "pikaviewrenderer-frame.h"
|
|
#include "pikawidgets-utils.h"
|
|
|
|
#include "pika-intl.h"
|
|
|
|
|
|
/* local function prototypes */
|
|
|
|
static void pika_thumb_box_progress_iface_init (PikaProgressInterface *iface);
|
|
|
|
static void pika_thumb_box_dispose (GObject *object);
|
|
static void pika_thumb_box_finalize (GObject *object);
|
|
|
|
static PikaProgress *
|
|
pika_thumb_box_progress_start (PikaProgress *progress,
|
|
gboolean cancellable,
|
|
const gchar *message);
|
|
static void pika_thumb_box_progress_end (PikaProgress *progress);
|
|
static gboolean pika_thumb_box_progress_is_active (PikaProgress *progress);
|
|
static void pika_thumb_box_progress_set_value (PikaProgress *progress,
|
|
gdouble percentage);
|
|
static gdouble pika_thumb_box_progress_get_value (PikaProgress *progress);
|
|
static void pika_thumb_box_progress_pulse (PikaProgress *progress);
|
|
|
|
static gboolean pika_thumb_box_progress_message (PikaProgress *progress,
|
|
Pika *pika,
|
|
PikaMessageSeverity severity,
|
|
const gchar *domain,
|
|
const gchar *message);
|
|
|
|
static gboolean pika_thumb_box_ebox_button_press (GtkWidget *widget,
|
|
GdkEventButton *bevent,
|
|
PikaThumbBox *box);
|
|
static void pika_thumb_box_thumbnail_clicked (GtkWidget *widget,
|
|
GdkModifierType state,
|
|
PikaThumbBox *box);
|
|
static void pika_thumb_box_imagefile_info_changed (PikaImagefile *imagefile,
|
|
PikaThumbBox *box);
|
|
static void pika_thumb_box_thumb_state_notify (PikaThumbnail *thumb,
|
|
GParamSpec *pspec,
|
|
PikaThumbBox *box);
|
|
static void pika_thumb_box_create_thumbnails (PikaThumbBox *box,
|
|
gboolean force);
|
|
static void pika_thumb_box_create_thumbnail (PikaThumbBox *box,
|
|
GFile *file,
|
|
PikaThumbnailSize size,
|
|
gboolean force,
|
|
PikaProgress *progress);
|
|
static gboolean pika_thumb_box_auto_thumbnail (PikaThumbBox *box);
|
|
|
|
|
|
G_DEFINE_TYPE_WITH_CODE (PikaThumbBox, pika_thumb_box, GTK_TYPE_FRAME,
|
|
G_IMPLEMENT_INTERFACE (PIKA_TYPE_PROGRESS,
|
|
pika_thumb_box_progress_iface_init))
|
|
|
|
#define parent_class pika_thumb_box_parent_class
|
|
|
|
|
|
static void
|
|
pika_thumb_box_class_init (PikaThumbBoxClass *klass)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
|
|
|
object_class->dispose = pika_thumb_box_dispose;
|
|
object_class->finalize = pika_thumb_box_finalize;
|
|
|
|
gtk_widget_class_set_css_name (widget_class, "treeview");
|
|
}
|
|
|
|
static void
|
|
pika_thumb_box_init (PikaThumbBox *box)
|
|
{
|
|
gtk_frame_set_shadow_type (GTK_FRAME (box), GTK_SHADOW_IN);
|
|
|
|
box->idle_id = 0;
|
|
}
|
|
|
|
static void
|
|
pika_thumb_box_progress_iface_init (PikaProgressInterface *iface)
|
|
{
|
|
iface->start = pika_thumb_box_progress_start;
|
|
iface->end = pika_thumb_box_progress_end;
|
|
iface->is_active = pika_thumb_box_progress_is_active;
|
|
iface->set_value = pika_thumb_box_progress_set_value;
|
|
iface->get_value = pika_thumb_box_progress_get_value;
|
|
iface->pulse = pika_thumb_box_progress_pulse;
|
|
iface->message = pika_thumb_box_progress_message;
|
|
}
|
|
|
|
static void
|
|
pika_thumb_box_dispose (GObject *object)
|
|
{
|
|
PikaThumbBox *box = PIKA_THUMB_BOX (object);
|
|
|
|
if (box->idle_id)
|
|
{
|
|
g_source_remove (box->idle_id);
|
|
box->idle_id = 0;
|
|
}
|
|
|
|
G_OBJECT_CLASS (parent_class)->dispose (object);
|
|
|
|
box->progress = NULL;
|
|
}
|
|
|
|
static void
|
|
pika_thumb_box_finalize (GObject *object)
|
|
{
|
|
PikaThumbBox *box = PIKA_THUMB_BOX (object);
|
|
|
|
pika_thumb_box_take_files (box, NULL);
|
|
|
|
g_clear_object (&box->imagefile);
|
|
|
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
|
}
|
|
|
|
static PikaProgress *
|
|
pika_thumb_box_progress_start (PikaProgress *progress,
|
|
gboolean cancellable,
|
|
const gchar *message)
|
|
{
|
|
PikaThumbBox *box = PIKA_THUMB_BOX (progress);
|
|
|
|
if (! box->progress)
|
|
return NULL;
|
|
|
|
if (! box->progress_active)
|
|
{
|
|
GtkProgressBar *bar = GTK_PROGRESS_BAR (box->progress);
|
|
GtkWidget *toplevel;
|
|
|
|
gtk_progress_bar_set_fraction (bar, 0.0);
|
|
|
|
box->progress_active = TRUE;
|
|
|
|
toplevel = gtk_widget_get_toplevel (GTK_WIDGET (box));
|
|
|
|
if (PIKA_IS_FILE_DIALOG (toplevel))
|
|
gtk_dialog_set_response_sensitive (GTK_DIALOG (toplevel),
|
|
GTK_RESPONSE_CANCEL, cancellable);
|
|
|
|
return progress;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static void
|
|
pika_thumb_box_progress_end (PikaProgress *progress)
|
|
{
|
|
if (pika_thumb_box_progress_is_active (progress))
|
|
{
|
|
PikaThumbBox *box = PIKA_THUMB_BOX (progress);
|
|
GtkProgressBar *bar = GTK_PROGRESS_BAR (box->progress);
|
|
|
|
gtk_progress_bar_set_fraction (bar, 0.0);
|
|
|
|
box->progress_active = FALSE;
|
|
}
|
|
}
|
|
|
|
static gboolean
|
|
pika_thumb_box_progress_is_active (PikaProgress *progress)
|
|
{
|
|
PikaThumbBox *box = PIKA_THUMB_BOX (progress);
|
|
|
|
return (box->progress && box->progress_active);
|
|
}
|
|
|
|
static void
|
|
pika_thumb_box_progress_set_value (PikaProgress *progress,
|
|
gdouble percentage)
|
|
{
|
|
if (pika_thumb_box_progress_is_active (progress))
|
|
{
|
|
PikaThumbBox *box = PIKA_THUMB_BOX (progress);
|
|
GtkProgressBar *bar = GTK_PROGRESS_BAR (box->progress);
|
|
|
|
gtk_progress_bar_set_fraction (bar, percentage);
|
|
}
|
|
}
|
|
|
|
static gdouble
|
|
pika_thumb_box_progress_get_value (PikaProgress *progress)
|
|
{
|
|
if (pika_thumb_box_progress_is_active (progress))
|
|
{
|
|
PikaThumbBox *box = PIKA_THUMB_BOX (progress);
|
|
GtkProgressBar *bar = GTK_PROGRESS_BAR (box->progress);
|
|
|
|
return gtk_progress_bar_get_fraction (bar);
|
|
}
|
|
|
|
return 0.0;
|
|
}
|
|
|
|
static void
|
|
pika_thumb_box_progress_pulse (PikaProgress *progress)
|
|
{
|
|
if (pika_thumb_box_progress_is_active (progress))
|
|
{
|
|
PikaThumbBox *box = PIKA_THUMB_BOX (progress);
|
|
GtkProgressBar *bar = GTK_PROGRESS_BAR (box->progress);
|
|
|
|
gtk_progress_bar_pulse (bar);
|
|
}
|
|
}
|
|
|
|
static gboolean
|
|
pika_thumb_box_progress_message (PikaProgress *progress,
|
|
Pika *pika,
|
|
PikaMessageSeverity severity,
|
|
const gchar *domain,
|
|
const gchar *message)
|
|
{
|
|
/* PikaThumbBox never shows any messages */
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/* stupid PikaHeader class just so we get a "header" CSS node */
|
|
|
|
#define PIKA_TYPE_HEADER (pika_header_get_type ())
|
|
|
|
typedef struct _GtkBox PikaHeader;
|
|
typedef struct _GtkBoxClass PikaHeaderClass;
|
|
|
|
static GType pika_header_get_type (void) G_GNUC_CONST;
|
|
|
|
G_DEFINE_TYPE (PikaHeader, pika_header, GTK_TYPE_BOX)
|
|
|
|
static void
|
|
pika_header_class_init (PikaHeaderClass *klass)
|
|
{
|
|
gtk_widget_class_set_css_name (GTK_WIDGET_CLASS (klass), "header");
|
|
}
|
|
|
|
static void
|
|
pika_header_init (PikaHeader *header)
|
|
{
|
|
gtk_orientable_set_orientation (GTK_ORIENTABLE (header),
|
|
GTK_ORIENTATION_VERTICAL);
|
|
}
|
|
|
|
|
|
/* public functions */
|
|
|
|
GtkWidget *
|
|
pika_thumb_box_new (PikaContext *context)
|
|
{
|
|
PikaThumbBox *box;
|
|
GtkWidget *vbox;
|
|
GtkWidget *vbox2;
|
|
GtkWidget *ebox;
|
|
GtkWidget *button;
|
|
GtkWidget *label;
|
|
gchar *str;
|
|
gint h, v;
|
|
|
|
g_return_val_if_fail (PIKA_IS_CONTEXT (context), NULL);
|
|
|
|
box = g_object_new (PIKA_TYPE_THUMB_BOX, NULL);
|
|
|
|
gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (box)),
|
|
GTK_STYLE_CLASS_VIEW);
|
|
|
|
box->context = context;
|
|
|
|
ebox = gtk_event_box_new ();
|
|
gtk_container_add (GTK_CONTAINER (box), ebox);
|
|
gtk_widget_show (ebox);
|
|
|
|
g_signal_connect (ebox, "button-press-event",
|
|
G_CALLBACK (pika_thumb_box_ebox_button_press),
|
|
box);
|
|
|
|
str = g_strdup_printf (_("Click to update preview\n"
|
|
"%s-Click to force update even "
|
|
"if preview is up-to-date"),
|
|
pika_get_mod_string (pika_get_toggle_behavior_mask ()));
|
|
|
|
pika_help_set_help_data (ebox, str, NULL);
|
|
|
|
g_free (str);
|
|
|
|
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
|
gtk_container_add (GTK_CONTAINER (ebox), vbox);
|
|
gtk_widget_show (vbox);
|
|
|
|
vbox2 = g_object_new (PIKA_TYPE_HEADER, NULL);
|
|
gtk_box_pack_start (GTK_BOX (vbox), vbox2, FALSE, FALSE, 0);
|
|
gtk_widget_show (vbox2);
|
|
|
|
button = gtk_button_new ();
|
|
gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
|
|
gtk_widget_show (button);
|
|
|
|
label = gtk_label_new_with_mnemonic (_("Pr_eview"));
|
|
gtk_label_set_xalign (GTK_LABEL (label), 0.0);
|
|
gtk_container_add (GTK_CONTAINER (button), label);
|
|
gtk_widget_show (label);
|
|
|
|
g_signal_connect (button, "button-press-event",
|
|
G_CALLBACK (gtk_true),
|
|
NULL);
|
|
g_signal_connect (button, "button-release-event",
|
|
G_CALLBACK (gtk_true),
|
|
NULL);
|
|
g_signal_connect (button, "enter-notify-event",
|
|
G_CALLBACK (gtk_true),
|
|
NULL);
|
|
g_signal_connect (button, "leave-notify-event",
|
|
G_CALLBACK (gtk_true),
|
|
NULL);
|
|
|
|
vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
|
|
gtk_container_set_border_width (GTK_CONTAINER (vbox2), 4);
|
|
gtk_box_pack_start (GTK_BOX (vbox), vbox2, TRUE, TRUE, 0);
|
|
gtk_widget_show (vbox2);
|
|
|
|
box->imagefile = pika_imagefile_new (context->pika, NULL);
|
|
|
|
g_signal_connect (box->imagefile, "info-changed",
|
|
G_CALLBACK (pika_thumb_box_imagefile_info_changed),
|
|
box);
|
|
|
|
g_signal_connect (pika_imagefile_get_thumbnail (box->imagefile),
|
|
"notify::thumb-state",
|
|
G_CALLBACK (pika_thumb_box_thumb_state_notify),
|
|
box);
|
|
|
|
pika_view_renderer_get_frame_size (&h, &v);
|
|
|
|
box->preview = pika_view_new (context,
|
|
PIKA_VIEWABLE (box->imagefile),
|
|
/* add padding for the shadow frame */
|
|
context->pika->config->thumbnail_size +
|
|
MAX (h, v),
|
|
0, FALSE);
|
|
|
|
gtk_style_context_add_class (gtk_widget_get_style_context (box->preview),
|
|
GTK_STYLE_CLASS_VIEW);
|
|
gtk_box_pack_start (GTK_BOX (vbox2), box->preview, FALSE, FALSE, 0);
|
|
gtk_widget_show (box->preview);
|
|
|
|
gtk_label_set_mnemonic_widget (GTK_LABEL (label), box->preview);
|
|
|
|
g_signal_connect (box->preview, "clicked",
|
|
G_CALLBACK (pika_thumb_box_thumbnail_clicked),
|
|
box);
|
|
|
|
box->filename = gtk_label_new (_("No selection"));
|
|
gtk_label_set_max_width_chars (GTK_LABEL (box->filename), 1);
|
|
gtk_label_set_ellipsize (GTK_LABEL (box->filename), PANGO_ELLIPSIZE_MIDDLE);
|
|
gtk_label_set_justify (GTK_LABEL (box->filename), GTK_JUSTIFY_CENTER);
|
|
pika_label_set_attributes (GTK_LABEL (box->filename),
|
|
PANGO_ATTR_STYLE, PANGO_STYLE_OBLIQUE,
|
|
-1);
|
|
gtk_box_pack_start (GTK_BOX (vbox2), box->filename, FALSE, FALSE, 0);
|
|
gtk_widget_show (box->filename);
|
|
|
|
box->info = gtk_label_new (" \n \n \n ");
|
|
gtk_label_set_justify (GTK_LABEL (box->info), GTK_JUSTIFY_CENTER);
|
|
gtk_label_set_line_wrap (GTK_LABEL (box->info), TRUE);
|
|
pika_label_set_attributes (GTK_LABEL (box->info),
|
|
PANGO_ATTR_SCALE, PANGO_SCALE_SMALL,
|
|
-1);
|
|
gtk_box_pack_start (GTK_BOX (vbox2), box->info, FALSE, FALSE, 0);
|
|
gtk_widget_show (box->info);
|
|
|
|
box->progress = gtk_progress_bar_new ();
|
|
gtk_widget_set_halign (box->progress, GTK_ALIGN_FILL);
|
|
gtk_progress_bar_set_show_text (GTK_PROGRESS_BAR (box->progress), TRUE);
|
|
gtk_progress_bar_set_text (GTK_PROGRESS_BAR (box->progress), "Fog");
|
|
gtk_box_pack_end (GTK_BOX (vbox2), box->progress, FALSE, FALSE, 0);
|
|
/* don't gtk_widget_show (box->progress); */
|
|
|
|
gtk_widget_set_size_request (GTK_WIDGET (box),
|
|
MAX ((gint) PIKA_THUMB_SIZE_NORMAL,
|
|
(gint) context->pika->config->thumbnail_size) +
|
|
2 * MAX (h, v),
|
|
-1);
|
|
|
|
return GTK_WIDGET (box);
|
|
}
|
|
|
|
void
|
|
pika_thumb_box_take_file (PikaThumbBox *box,
|
|
GFile *file)
|
|
{
|
|
g_return_if_fail (PIKA_IS_THUMB_BOX (box));
|
|
g_return_if_fail (file == NULL || G_IS_FILE (file));
|
|
|
|
if (box->idle_id)
|
|
{
|
|
g_source_remove (box->idle_id);
|
|
box->idle_id = 0;
|
|
}
|
|
|
|
pika_imagefile_set_file (box->imagefile, file);
|
|
|
|
if (file)
|
|
{
|
|
gchar *basename = g_path_get_basename (pika_file_get_utf8_name (file));
|
|
gtk_label_set_text (GTK_LABEL (box->filename), basename);
|
|
g_free (basename);
|
|
}
|
|
else
|
|
{
|
|
gtk_label_set_text (GTK_LABEL (box->filename), _("No selection"));
|
|
}
|
|
|
|
gtk_widget_set_sensitive (GTK_WIDGET (box), file != NULL);
|
|
pika_imagefile_update (box->imagefile);
|
|
}
|
|
|
|
void
|
|
pika_thumb_box_take_files (PikaThumbBox *box,
|
|
GSList *files)
|
|
{
|
|
g_return_if_fail (PIKA_IS_THUMB_BOX (box));
|
|
|
|
if (box->files)
|
|
{
|
|
g_slist_free_full (box->files, (GDestroyNotify) g_object_unref);
|
|
box->files = NULL;
|
|
}
|
|
|
|
box->files = files;
|
|
}
|
|
|
|
|
|
/* private functions */
|
|
|
|
static gboolean
|
|
pika_thumb_box_ebox_button_press (GtkWidget *widget,
|
|
GdkEventButton *bevent,
|
|
PikaThumbBox *box)
|
|
{
|
|
pika_thumb_box_thumbnail_clicked (widget, bevent->state, box);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
pika_thumb_box_thumbnail_clicked (GtkWidget *widget,
|
|
GdkModifierType state,
|
|
PikaThumbBox *box)
|
|
{
|
|
pika_thumb_box_create_thumbnails (box,
|
|
(state & pika_get_toggle_behavior_mask ()) ?
|
|
TRUE : FALSE);
|
|
}
|
|
|
|
static void
|
|
pika_thumb_box_imagefile_info_changed (PikaImagefile *imagefile,
|
|
PikaThumbBox *box)
|
|
{
|
|
gtk_label_set_text (GTK_LABEL (box->info),
|
|
pika_imagefile_get_desc_string (imagefile));
|
|
}
|
|
|
|
static void
|
|
pika_thumb_box_thumb_state_notify (PikaThumbnail *thumb,
|
|
GParamSpec *pspec,
|
|
PikaThumbBox *box)
|
|
{
|
|
if (box->idle_id)
|
|
return;
|
|
|
|
if (thumb->image_state == PIKA_THUMB_STATE_REMOTE)
|
|
return;
|
|
|
|
switch (thumb->thumb_state)
|
|
{
|
|
case PIKA_THUMB_STATE_NOT_FOUND:
|
|
case PIKA_THUMB_STATE_OLD:
|
|
box->idle_id =
|
|
g_idle_add_full (G_PRIORITY_LOW,
|
|
(GSourceFunc) pika_thumb_box_auto_thumbnail,
|
|
box, NULL);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
pika_thumb_box_create_thumbnails (PikaThumbBox *box,
|
|
gboolean force)
|
|
{
|
|
Pika *pika = box->context->pika;
|
|
PikaProgress *progress = PIKA_PROGRESS (box);
|
|
PikaFileDialog *dialog = NULL;
|
|
GtkWidget *toplevel;
|
|
GSList *list;
|
|
gint n_files;
|
|
gint i;
|
|
|
|
if (pika->config->thumbnail_size == PIKA_THUMBNAIL_SIZE_NONE)
|
|
return;
|
|
|
|
toplevel = gtk_widget_get_toplevel (GTK_WIDGET (box));
|
|
|
|
if (PIKA_IS_FILE_DIALOG (toplevel))
|
|
dialog = PIKA_FILE_DIALOG (toplevel);
|
|
|
|
pika_set_busy (pika);
|
|
|
|
if (dialog)
|
|
pika_file_dialog_set_sensitive (dialog, FALSE);
|
|
else
|
|
gtk_widget_set_sensitive (toplevel, FALSE);
|
|
|
|
if (box->files)
|
|
{
|
|
gtk_widget_hide (box->info);
|
|
gtk_widget_show (box->progress);
|
|
}
|
|
|
|
n_files = g_slist_length (box->files);
|
|
|
|
if (n_files > 1)
|
|
{
|
|
gchar *str;
|
|
|
|
pika_progress_start (PIKA_PROGRESS (box), TRUE, "%s", "");
|
|
|
|
progress = pika_sub_progress_new (PIKA_PROGRESS (box));
|
|
|
|
pika_sub_progress_set_step (PIKA_SUB_PROGRESS (progress), 0, n_files);
|
|
|
|
for (list = box->files->next, i = 1;
|
|
list;
|
|
list = g_slist_next (list), i++)
|
|
{
|
|
str = g_strdup_printf (_("Thumbnail %d of %d"), i, n_files);
|
|
gtk_progress_bar_set_text (GTK_PROGRESS_BAR (box->progress), str);
|
|
g_free (str);
|
|
|
|
pika_progress_set_value (progress, 0.0);
|
|
|
|
while (g_main_context_pending (NULL))
|
|
g_main_context_iteration (NULL, FALSE);
|
|
|
|
pika_thumb_box_create_thumbnail (box,
|
|
list->data,
|
|
pika->config->thumbnail_size,
|
|
force,
|
|
progress);
|
|
|
|
if (dialog && dialog->canceled)
|
|
goto canceled;
|
|
|
|
pika_sub_progress_set_step (PIKA_SUB_PROGRESS (progress), i, n_files);
|
|
}
|
|
|
|
str = g_strdup_printf (_("Thumbnail %d of %d"), n_files, n_files);
|
|
gtk_progress_bar_set_text (GTK_PROGRESS_BAR (box->progress), str);
|
|
g_free (str);
|
|
|
|
pika_progress_set_value (progress, 0.0);
|
|
|
|
while (g_main_context_pending (NULL))
|
|
g_main_context_iteration (NULL, FALSE);
|
|
}
|
|
|
|
if (box->files)
|
|
{
|
|
pika_thumb_box_create_thumbnail (box,
|
|
box->files->data,
|
|
pika->config->thumbnail_size,
|
|
force,
|
|
progress);
|
|
|
|
pika_progress_set_value (progress, 1.0);
|
|
}
|
|
|
|
canceled:
|
|
|
|
if (n_files > 1)
|
|
{
|
|
g_object_unref (progress);
|
|
|
|
pika_progress_end (PIKA_PROGRESS (box));
|
|
gtk_progress_bar_set_text (GTK_PROGRESS_BAR (box->progress), "");
|
|
}
|
|
|
|
if (box->files)
|
|
{
|
|
gtk_widget_hide (box->progress);
|
|
gtk_widget_show (box->info);
|
|
}
|
|
|
|
if (dialog)
|
|
pika_file_dialog_set_sensitive (dialog, TRUE);
|
|
else
|
|
gtk_widget_set_sensitive (toplevel, TRUE);
|
|
|
|
pika_unset_busy (pika);
|
|
}
|
|
|
|
static void
|
|
pika_thumb_box_create_thumbnail (PikaThumbBox *box,
|
|
GFile *file,
|
|
PikaThumbnailSize size,
|
|
gboolean force,
|
|
PikaProgress *progress)
|
|
{
|
|
PikaThumbnail *thumb = pika_imagefile_get_thumbnail (box->imagefile);
|
|
gchar *basename;
|
|
|
|
basename = g_path_get_basename (pika_file_get_utf8_name (file));
|
|
gtk_label_set_text (GTK_LABEL (box->filename), basename);
|
|
g_free (basename);
|
|
|
|
pika_imagefile_set_file (box->imagefile, file);
|
|
|
|
if (force ||
|
|
(pika_thumbnail_peek_thumb (thumb, (PikaThumbSize) size) < PIKA_THUMB_STATE_FAILED &&
|
|
! pika_thumbnail_has_failed (thumb)))
|
|
{
|
|
GError *error = NULL;
|
|
|
|
if (! pika_imagefile_create_thumbnail (box->imagefile, box->context,
|
|
progress,
|
|
size, ! force, &error))
|
|
{
|
|
pika_message_literal (box->context->pika,
|
|
G_OBJECT (progress), PIKA_MESSAGE_ERROR,
|
|
error->message);
|
|
g_clear_error (&error);
|
|
}
|
|
}
|
|
}
|
|
|
|
static gboolean
|
|
pika_thumb_box_auto_thumbnail (PikaThumbBox *box)
|
|
{
|
|
Pika *pika = box->context->pika;
|
|
PikaThumbnail *thumb = pika_imagefile_get_thumbnail (box->imagefile);
|
|
GFile *file = pika_imagefile_get_file (box->imagefile);
|
|
|
|
box->idle_id = 0;
|
|
|
|
if (thumb->image_state == PIKA_THUMB_STATE_NOT_FOUND)
|
|
return FALSE;
|
|
|
|
switch (thumb->thumb_state)
|
|
{
|
|
case PIKA_THUMB_STATE_NOT_FOUND:
|
|
case PIKA_THUMB_STATE_OLD:
|
|
if (thumb->image_filesize < pika->config->thumbnail_filesize_limit &&
|
|
! pika_thumbnail_has_failed (thumb) &&
|
|
pika_plug_in_manager_file_procedure_find_by_extension (pika->plug_in_manager,
|
|
PIKA_FILE_PROCEDURE_GROUP_OPEN,
|
|
file))
|
|
{
|
|
if (thumb->image_filesize > 0)
|
|
{
|
|
gchar *size;
|
|
gchar *text;
|
|
|
|
size = g_format_size (thumb->image_filesize);
|
|
text = g_strdup_printf ("%s\n%s",
|
|
size, _("Creating preview..."));
|
|
|
|
gtk_label_set_text (GTK_LABEL (box->info), text);
|
|
|
|
g_free (text);
|
|
g_free (size);
|
|
}
|
|
else
|
|
{
|
|
gtk_label_set_text (GTK_LABEL (box->info),
|
|
_("Creating preview..."));
|
|
}
|
|
|
|
pika_imagefile_create_thumbnail_weak (box->imagefile, box->context,
|
|
PIKA_PROGRESS (box),
|
|
pika->config->thumbnail_size,
|
|
TRUE);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|