Logo Search packages:      
Sourcecode: danpei version File versions  Download package

thumbnail.c

/*
 * Danpei -- a GTK+ based Image Viewer
 * Copyright (C) 2001-2003 Shinji Moiino
 *
 * 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 2 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, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
/* thumbnail.c */

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <gdk/gdkx.h>
#include <gdk/gdkkeysyms.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <gtk/gtk.h>

#include "config.h"
#include "dialog.h"
#include "dirtree.h"
#include "file_menu.h"
#include "image_cache.h"
#include "intl.h"
#include "main.h"
#include "pcx.h"
#include "thumbnail.h"
#include "version.h"
#include "xbm.h"

/* External variables. */
/* For drag and drop. -- defined in main.c */
extern const GtkTargetEntry dnd_te[];
extern gint  dnd_te_num;

/* Static function declarations. */
static Thumbnail* thumbnail_get_from_widget        (TopLevel*         ,
                                                    GtkWidget*        ,
                                                    gboolean            );

static void       thumbnail_free_rgb_buffer        (guchar*           , 
                                                    gpointer            );

static gint       thumbnail_cb_icon_configure      (GtkWidget*        , 
                                                    GdkEventConfigure*, 
                                                    gpointer            );

static gint       thumbnail_cb_icon_expose         (GtkWidget*        , 
                                                    GdkEventExpose*   , 
                                                    gpointer            );

static gboolean   thumbnail_cb_icon_button_pressed (GtkWidget*        ,
                                                    GdkEventButton*   ,
                                                    gpointer            );

static void       thumbnail_cb_icon_drag_begin     (GtkWidget*        ,
                                                    GdkDragContext*   ,
                                                    gpointer            );

static void       thumbnail_cb_icon_drag_end       (GtkWidget*        ,
                                                    GdkDragContext*   ,
                                                    gpointer            );

static gboolean   thumbnail_cb_entry_key_pressed   (GtkWidget*        ,
                                                    GdkEventKey*      ,
                                                    gpointer            );

static gboolean   thumbnail_cb_entry_focus_in      (GtkWidget*        ,
                                                    GdkEventFocus*    ,
                                                    gpointer            );

static gboolean   thumbnail_cb_entry_focus_out     (GtkWidget*        ,
                                                    GdkEventFocus*    ,
                                                    gpointer            );

/* Function definitions. */
/*
 * @thumbnail_init
 *
 *  Initialize the Thumbnail structure object.
 *
 */
void thumbnail_init(Thumbnail *thumb) {
  thumb->ev_box      = NULL;
  thumb->frame       = NULL;
  thumb->vbox        = NULL;
  thumb->icon_box    = NULL;
  thumb->icon        = NULL;
  thumb->entry       = NULL;
  thumb->pixmap      = NULL;
  thumb->path        = NULL;
  thumb->filename    = NULL;
  thumb->icon_width  = 0;
  thumb->icon_height = 0;
  thumb->selected    = FALSE;
  thumb->disabled    = FALSE;
  thumb->writable    = TRUE;
  thumb->prev        = NULL;
  thumb->next        = NULL;

  return;
}

/*
 * @thumbnail_free_structure_list
 *
 *  Free the Thumbnail structure objects under the specified list.
 *
 */
void thumbnail_free_structure_list(Thumbnail *thumb) {
  Thumbnail *thumb1, *thumb2;

  thumb1 = thumb2 = thumb;
  while(thumb1 != NULL) {
    thumb2 = thumb1->next;
    thumbnail_free_structure(thumb1);
    thumb1 = thumb2;
  }

  return;
}

/*
 * @thumbnail_free_structure
 *
 *  Free a Thumbanil structure object which specified by the argument.
 *
 */
void thumbnail_free_structure(Thumbnail *thumb) {
  /* Free the memory. */
  if (thumb->path != NULL) {
    free(thumb->path); 
    thumb->path = NULL;
  }

  if (thumb->filename != NULL) {
    free(thumb->filename); 
    thumb->filename = NULL;
  }

  if (thumb->pixmap != NULL) {
    gdk_pixmap_unref(thumb->pixmap);
    thumb->pixmap = NULL;
  }
  thumb->icon_width  = 0;
  thumb->icon_height = 0;
  thumb->selected    = FALSE;
  thumb->disabled    = FALSE;
  thumb->writable    = TRUE;

  free(thumb);
 
  return;
}

/*
 * @thumbnail_change_link
 *
 *  Before free a Thumbnail structure object, change it's links
 *  prev and next.
 *
 */
void thumbnail_change_link(ThumbnailTable *thumb_table,
                           Thumbnail      *thumb        ) {
  /* Change the links of the Thumbnail structure list. */
  if (thumb->prev != NULL) {
    (thumb->prev)->next = thumb->next;
  }
  if (thumb->next != NULL) {
    (thumb->next)->prev = thumb->prev;
  }

  if (thumb_table->top_thumbnail == thumb) {
    thumb_table->top_thumbnail = thumb->next;
  }
  if (thumb_table->end_thumbnail == thumb) {
    thumb_table->end_thumbnail = thumb->prev;
  }

  thumb_table->file_num--;

  return;
}


/*
 * @thumbnail_create
 *
 *  Create a new Thumbnail structure object and return the pointer to
 *  the created object.
 *  -- the argument 'thumb' must be initialized by the function
 *     thumbnail_init().
 *
 */
void thumbnail_create(Thumbnail *thumb,
                      TopLevel  *tp     ) {
  /* Initialize local variables. */

  /* Create pixmap image. */
  thumbnail_create_pixmap(thumb, tp);

  /* Create the widgets for display a thumbnail. */
  thumb->ev_box = gtk_event_box_new();
  if (thumb->ev_box == NULL) {
    /* Out of memory. */
    fprintf(stderr, "danpei: Out of memory.\n");
    fprintf(stderr, "        thumbnail.c: error -- 01.\n");
    gtk_exit(-1);
  }
  gtk_signal_connect(GTK_OBJECT(thumb->ev_box), 
                     "button_press_event",
                     GTK_SIGNAL_FUNC(thumbnail_cb_icon_button_pressed), tp);
  gtk_signal_connect(GTK_OBJECT(thumb->ev_box), 
                     "drag-begin",
                     GTK_SIGNAL_FUNC(thumbnail_cb_icon_drag_begin), tp);
  gtk_signal_connect(GTK_OBJECT(thumb->ev_box), 
                     "drag-end",
                     GTK_SIGNAL_FUNC(thumbnail_cb_icon_drag_end), tp);

  if (thumb->disabled == TRUE) {
    gtk_widget_set_sensitive(thumb->ev_box, FALSE);
  }

  /* Set drag and drop. */
  gtk_drag_source_set(thumb->ev_box, GDK_BUTTON1_MASK, 
                      dnd_te, dnd_te_num, 
                      GDK_ACTION_ASK  | GDK_ACTION_COPY | 
                      GDK_ACTION_MOVE | GDK_ACTION_LINK   );
/***********************************************************************
 * Only 'GDK_ACTION_DEFAULT', the dest widget wouldn't set drag and drop.
 *                    GDK_ACTION_DEFAULT); 
***********************************************************************/

  gtk_widget_show(thumb->ev_box);

  thumb->frame = gtk_frame_new(NULL);
  if (thumb->frame == NULL) {
    /* Out of memory. */
    fprintf(stderr, "danpei: Out of memory.\n");
    fprintf(stderr, "        thumbnail.c: error -- 02.\n");
    gtk_exit(-1);
  }
  thumbnail_set_shadow(thumb, FALSE);
  gtk_container_add(GTK_CONTAINER(thumb->ev_box), thumb->frame);
  gtk_widget_show(thumb->frame);

  thumb->vbox = gtk_vbox_new(FALSE, 0);
  gtk_container_add(GTK_CONTAINER(thumb->frame), thumb->vbox);
  gtk_container_border_width(GTK_CONTAINER(thumb->vbox), 4);
  gtk_widget_show(thumb->vbox);

  thumbnail_create_icon_area(thumb, tp);

  thumb->entry = gtk_entry_new_with_max_length(FILENAME_MAX_LENGTH);
  gtk_widget_set_usize(thumb->entry, tp->current_icon_size, 20);
  gtk_entry_set_text(GTK_ENTRY(thumb->entry), thumb->filename);
  gtk_editable_set_position(GTK_EDITABLE(thumb->entry), 0);
  gtk_box_pack_start(GTK_BOX(thumb->vbox), thumb->entry,
                     FALSE, FALSE, 2);
  gtk_signal_connect(GTK_OBJECT(thumb->entry), "key_press_event",
                     GTK_SIGNAL_FUNC(thumbnail_cb_entry_key_pressed), tp);
  gtk_signal_connect(GTK_OBJECT(thumb->entry), "focus-in-event" ,
                     GTK_SIGNAL_FUNC(thumbnail_cb_entry_focus_in)   , tp);
  gtk_signal_connect(GTK_OBJECT(thumb->entry), "focus-out-event",
                     GTK_SIGNAL_FUNC(thumbnail_cb_entry_focus_out)  , tp);
  gtk_widget_set_events(thumb->entry, GDK_FOCUS_CHANGE_MASK);
  if (thumb->writable == FALSE) {
    gtk_widget_set_sensitive(thumb->entry, FALSE);
  }
  if (thumb->disabled == TRUE) {
    gtk_widget_set_sensitive(thumb->entry, FALSE);
  }
  gtk_widget_show(thumb->entry);

  return; 
}


/*
 * @thumbnail_create_pixmap
 *
 *
 *
 */
void thumbnail_create_pixmap(Thumbnail *thumb, TopLevel *tp) {
  GdkPixbuf  *image, *image2;
  gchar      *filename;
  guchar     *rgb_data;
  gint       image_width, image_height;

  /* Initialize local variables. */
  filename = NULL;
  image    = image2 = NULL;

  /* Load the image,that specified 'thumb' structure,by using gdk-pixbuf. */ 
  /* Get image's filename. */
  filename = (gchar*)malloc(sizeof(gchar) * 
                    (strlen(thumb->path) + strlen(thumb->filename) + 2));
  if (filename == NULL) {
    /* Out of memory. */
    fprintf(stderr, "danpei: Out of memory.\n");
    fprintf(stderr, "        thumbnail.c: error -- 03.\n");
    gtk_exit(-1);
  }
  else {
    sprintf(filename, "%s/%s", thumb->path, thumb->filename);
  }

  /* Check the write permission to the directory. */
  if (access(thumb->path, W_OK) == 0) {
    thumb->writable = TRUE;
  }
  else {
    thumb->writable = FALSE;
  }

  /* Serch in the cache files. */
  if (tp->app_option.image_cache.cache_on == TRUE) {
    image_cache_serch(tp, thumb, 
                      tp->current_icon_size, filename);
  }

  /* If not found, create the thumbnail image. */
  if (thumb->pixmap == NULL) {
    /* Load the image and render it. */
    image = gdk_pixbuf_new_from_file(filename);
    if (image == NULL) {
      /* load image as pcx data. */
      rgb_data = pcx_load(filename, &image_width, &image_height);
      if (rgb_data != NULL) {
        image = gdk_pixbuf_new_from_data(rgb_data, GDK_COLORSPACE_RGB, 
                                         FALSE, 8, 
                                         image_width, image_height, 
                                         image_width * 3, 
                                         thumbnail_free_rgb_buffer, NULL);
      }
      /* load image as xbm data. */
      rgb_data = xbm_load(filename, &image_width, &image_height);
      if (rgb_data != NULL) {
        image = gdk_pixbuf_new_from_data(rgb_data, GDK_COLORSPACE_RGB, 
                                         FALSE, 8, 
                                         image_width, image_height, 
                                         image_width * 3, 
                                         thumbnail_free_rgb_buffer, NULL);
      }
    }

    if (image == NULL) {
      thumb->pixmap = NULL;
    }
    else {
      image_width  = gdk_pixbuf_get_width (image);
      image_height = gdk_pixbuf_get_height(image);

      if (image_width > image_height) {
        thumb->icon_width  = tp->current_icon_size;
        thumb->icon_height = (gint)(tp->current_icon_size * 
                                    ((float)(image_height) / 
                                     (float)(image_width )   ));
        if (thumb->icon_height < 1) { thumb->icon_height = 1; }
      }
      else {
        thumb->icon_height = tp->current_icon_size;
        thumb->icon_width  = (gint)(tp->current_icon_size * 
                                     ((float)(image_width ) / 
                                      (float)(image_height)   ));
        if (thumb->icon_width < 1) { thumb->icon_width = 1; }
      }
      thumb->pixmap = gdk_pixmap_new(tp->window->window,
                                     thumb->icon_width , 
                                     thumb->icon_height, -1);
      image2 = gdk_pixbuf_scale_simple(image, 
                                       thumb->icon_width , 
                                       thumb->icon_height,
                                       GDK_INTERP_TILES  ); 
      gdk_pixbuf_render_to_drawable_alpha(image2, thumb->pixmap,
                                          0, 0, 0, 0,
                                          thumb->icon_width, 
                                          thumb->icon_height,
                                          GDK_PIXBUF_ALPHA_BILEVEL,
                                          0, GDK_RGB_DITHER_MAX, 0, 0);

      /* Write the pixmap to the cache file. */
      if (tp->app_option.image_cache.cache_on == TRUE) { 
        image_cache_add(&(tp->cache), image      , 
                        thumb->icon_width, thumb->icon_height, filename);
        image_cache_check_using_disk(tp);
      }
      gdk_pixbuf_unref(image);
      gdk_pixbuf_unref(image2);
    }
  }
  free(filename);

  return;
}

/*
 * @thumbnail_create_icon_area
 *
 *
 *
 */
void thumbnail_create_icon_area(Thumbnail *thumb,
                                TopLevel  *tp     ) {
  /* This function has no local variables. */

  if (thumb->icon_width < thumb->icon_height) {
    thumb->icon_box = gtk_hbox_new(FALSE, 0);
    if (thumb->icon_box == NULL) {
      /* Out of memory. */
      fprintf(stderr, "danpei: Out of memory.\n");
      fprintf(stderr, "        thumbnail.c: error -- 04.\n");
      gtk_exit(-1);
    }
  }
  else {
    thumb->icon_box = gtk_vbox_new(FALSE, 0);
    if (thumb->icon_box == NULL) {
      /* Out of memory. */
      fprintf(stderr, "danpei: Out of memory.\n");
      fprintf(stderr, "        thumbnail.c: error -- 05.\n");
      gtk_exit(-1);
    }
  }
  gtk_widget_set_usize(thumb->icon_box, 
                       tp->current_icon_size, tp->current_icon_size);
  gtk_box_pack_start(GTK_BOX(thumb->vbox), thumb->icon_box, TRUE, TRUE, 2);
  gtk_box_reorder_child(GTK_BOX(thumb->vbox), thumb->icon_box, 0);
  gtk_widget_show(thumb->icon_box);

  thumb->icon = gtk_drawing_area_new();
  if (thumb->icon == NULL) {
    /* Out of memory. */
    fprintf(stderr, "danpei: Out of memory.\n");
    fprintf(stderr, "        thumbnail.c: error -- 06.\n");
    gtk_exit(-1);
  }
  gtk_widget_set_usize(thumb->icon, thumb->icon_width, thumb->icon_height);
  gtk_drawing_area_size(GTK_DRAWING_AREA(thumb->icon),
                        thumb->icon_width, thumb->icon_height);
  gtk_signal_connect(GTK_OBJECT(thumb->icon), "configure_event",
                     GTK_SIGNAL_FUNC(thumbnail_cb_icon_configure), 
                     thumb);
  gtk_signal_connect(GTK_OBJECT(thumb->icon), "expose_event",
                     GTK_SIGNAL_FUNC(thumbnail_cb_icon_expose), 
                     thumb);
  gtk_box_pack_start(GTK_BOX(thumb->icon_box), thumb->icon, TRUE, FALSE, 0);
  gtk_widget_show(thumb->icon);

  return;
}

/*
 * @thumbnail_set_sensitive
 *
 *  Set the thumbnail enable or disable.
 *  When be disabled, set thumbnail unselected.
 *
 */
void thumbnail_set_sensitive(Thumbnail *thumb   , 
                             gboolean  sensitive  ) {
  if (sensitive == TRUE) { 
    thumb->disabled = FALSE; 
  }
  else {
    thumb->disabled = TRUE; 
    thumb->selected = FALSE;
  }
  if (sensitive == TRUE) {
    gtk_frame_set_shadow_type(GTK_FRAME(thumb->frame), GTK_SHADOW_OUT);
  }
  else {
    gtk_frame_set_shadow_type(GTK_FRAME(thumb->frame), GTK_SHADOW_ETCHED_OUT);
  }
  gtk_widget_set_sensitive(thumb->ev_box  , sensitive);
  gtk_widget_set_sensitive(thumb->frame   , sensitive);
  gtk_widget_set_sensitive(thumb->vbox    , sensitive);
  gtk_widget_set_sensitive(thumb->icon_box, sensitive);
  gtk_widget_set_sensitive(thumb->icon    , sensitive);
  if (thumb->writable == FALSE) {
    gtk_widget_set_sensitive(thumb->entry , FALSE);
  }
  else {
    gtk_widget_set_sensitive(thumb->entry , sensitive);
  }

  return;
}

/*
 * @thumbnail_entry_set_sensitive
 *
 *
 *
 */
void thumbnail_entry_set_sensitive(Thumbnail *thumb   ,
                                   gboolean  sensitive  ) {
  thumb->writable = sensitive;
  gtk_widget_set_sensitive(thumb->entry , sensitive);

  return;
}

/*
 * @thumbnail_count_selected_thumbnails
 *
 *  Increse or decrese thumbnail_table->selected_thumbnails, and
 *  set the sensitivity of the toolbar and menu items
 *
 */
void thumbnail_count_selected_thumbnails(TopLevel *tp,
                                         gint     num  ) {
  if (tp->thumbnail_table.selected_thumbnails < 0) { 
    tp->thumbnail_table.selected_thumbnails = 0;
  }

  tp->thumbnail_table.selected_thumbnails += num;

  if (tp->thumbnail_table.selected_thumbnails < 1) {
    /*  Set the toolbar un-sensitive. */
    toplevel_set_menu_sensitive(tp, STATUS_NO_SELECTED);
  }
  else {
    /*  Set the toolbar sensitive. */
    toplevel_set_menu_sensitive(tp, STATUS_SELECTED);
  }

  return;
}

/*
 * @thumbnail_set_shadow
 *
 *
 *
 */
void thumbnail_set_shadow(Thumbnail *thumb, 
                          gboolean  is_selected) {
  if (is_selected == TRUE) {
    gtk_frame_set_shadow_type(GTK_FRAME(thumb->frame), GTK_SHADOW_IN);
    thumb->selected = TRUE;
  }
  else {
    if (thumb->disabled == TRUE) {
      gtk_frame_set_shadow_type(GTK_FRAME(thumb->frame), 
                                GTK_SHADOW_ETCHED_OUT);
    }
    else {
      gtk_frame_set_shadow_type(GTK_FRAME(thumb->frame), GTK_SHADOW_OUT);
    }
    thumb->selected = FALSE;
  }
}

/*
 * @thumbnail_get_from_path
 *
 *  Serch a Thumbnail structure object from 'path'.
 *
 */
Thumbnail* thumbnail_get_from_path(TopLevel *tp,
                                   gchar    *full_path) {
  Thumbnail *thumb;
  gchar     *path, *filename;

  /* Initialize the local variables. */
  thumb = NULL;
  path  = filename = NULL;

  /* Serch by using 'ev_box'. */
  thumb = tp->thumbnail_table.top_thumbnail;
  while(thumb != NULL) {
    path = (gchar*)malloc(sizeof(gchar) * 
                          (strlen(thumb->path)     +
                           strlen("/")             +
                           strlen(thumb->filename) + 1));
    if (path == NULL) {
      /* Out of memory. */
      fprintf(stderr, "danpei: Out of memory.\n");
      fprintf(stderr, "        thumbnail.c: error -- 07.\n");
      gtk_exit(-1);
    }
    else {
      sprintf(path, "%s/%s", thumb->path, thumb->filename);
    }

    if (strcmp(path, full_path) == 0) {
      free(path);
      return thumb;
    }
    free(path);
    thumb = thumb->next;
  }
  
  return NULL;
}

/* Static function definitions. */
/*
 * @thumbnail_get_from widget
 *
 *  Get the Thumbnail structure object which specified by the widget.
 *  -- widget must be the member 'ev_box' or 'entry'.
 *
 */
static Thumbnail* thumbnail_get_from_widget(TopLevel  *tp    , 
                                            GtkWidget *widget,
                                            gboolean  disp_err ) {
  Thumbnail *thumb;
  gint      i;

  /* Initialize the local variables. */
  thumb = NULL;
  i     = 0;

  /* Serch by using 'ev_box'. */
  thumb = tp->thumbnail_table.top_thumbnail;
  while(thumb != NULL) {
    if (i < tp->thumbnail_table.start_pos) ;
    else {
      if (thumb->ev_box == widget) { return thumb; } 
      if (thumb->entry  == widget) { return thumb; } 
    }
    i++;
    thumb = thumb->next;
  }

  /* Widget not found. */
  if (disp_err == TRUE) {
    dialog_error_dialog_create(INTERNAL_ERROR, NULL, GTK_WINDOW(tp->window));
  }

  return NULL;
}

/*
 * @thumbnail_free_rgb_buffer
 *
 *
 *
 */
static void thumbnail_free_rgb_buffer(guchar   *pixels,
                                      gpointer data     ) {
  g_free(pixels);

  return;
}

/* Callback function definitions. */
/*
 * @thumbnail_cb_icon_configure
 *
 *
 *
 */
gint thumbnail_cb_icon_configure(GtkWidget         *widget,
                                 GdkEventConfigure *ev    ,
                                 gpointer          data     ) {
  return TRUE;
}

/*
 * @thumbnail_cb_icon_expose
 *
 *  Called when an icon(ev_box) receives Expose event.
 *
 */
gint thumbnail_cb_icon_expose(GtkWidget      *widget, 
                              GdkEventExpose *ev    , 
                              gpointer       data    ) {
  Thumbnail *thumb;

  thumb = (Thumbnail*)data;

  if (thumb->pixmap != NULL) {
    gdk_draw_pixmap(widget->window,
      widget->style->fg_gc[GTK_WIDGET_STATE(widget)], 
      thumb->pixmap,
      ev->area.x, ev->area.y,
      ev->area.x, ev->area.y,
      ev->area.width, ev->area.height);
  }

  /* Check the member 'selected' changed.
   * If not changed, return with doing nothing. 
   */
  if (thumb->selected == TRUE) {
    if (GTK_FRAME(thumb->frame)->shadow_type == GTK_SHADOW_IN) {
      return FALSE;
    }
  }
  else {
    if (thumb->disabled == FALSE) {
      if (GTK_FRAME(thumb->frame)->shadow_type == GTK_SHADOW_OUT) {
        return FALSE;
      }
    }
    else {
      if (GTK_FRAME(thumb->frame)->shadow_type == GTK_SHADOW_ETCHED_OUT) {
        return FALSE;
      }
    }
  }

  /* If the file changed by other terminal(ex. removed),
   * make that thumbnail not be operated.
   */
  if (thumb->disabled == TRUE) {
    thumbnail_set_sensitive(thumb, FALSE);
  }
  else {
    thumbnail_set_sensitive(thumb, TRUE);
  }

  if (thumb->selected == TRUE) {
    thumbnail_set_shadow(thumb, TRUE);
  }
  else {
    thumbnail_set_shadow(thumb, FALSE);
  }

  return TRUE;
}

/*
 * @thumbnail_cb_icon_button_pressed
 *
 *  A callback function called when a thumbnail is clicked.
 *
 */
static gboolean thumbnail_cb_icon_button_pressed(GtkWidget      *widget,
                                                 GdkEventButton *ev    ,
                                                 gpointer       data     ) {
  TopLevel  *tp;
  Thumbnail *thumb;
  static gboolean  save_selected;

  /* Initialize the local variables. */
  tp    = (TopLevel*)data;
  thumb = NULL;

  thumb = thumbnail_get_from_widget(tp, widget, TRUE);
  if (thumb == NULL) { return FALSE; }

  if ((ev->type    == GDK_BUTTON_PRESS           ) &&
      ((ev->button == 1) || (ev->button == 3)    ) &&
      ((ev->time - tp->last_ev_button.time) > 500)    ) {
    if (ev->button == 1) {
      /* Left button single click */
      /* Save the current status.
       * If double clicked, status wouldn't be changed. */
      save_selected = thumb->selected;

      if (thumb->selected == TRUE) {
        /* Thumbnail is already selected. */ 
        thumbnail_set_shadow(thumb, FALSE);
        thumbnail_count_selected_thumbnails(tp, -1);
      }
      else {
        /* Thumbnail is not selected. */ 
        thumbnail_set_shadow(thumb, TRUE);
        thumbnail_count_selected_thumbnails(tp, 1);
      }
    }
    else {
      /* Right button single clicked. */
      if (thumb->selected != TRUE) {
        /* Thumbnail is not selected. */ 
        thumbnail_set_shadow(thumb, TRUE);
        thumbnail_count_selected_thumbnails(tp, 1);
      }
      /* Raise the pop up menu. */
      tp->op_thumb = thumb;
      gtk_item_factory_popup(tp->popup_thumbnail.item_factory, 
                             ev->x_root, ev->y_root, 2, GDK_CURRENT_TIME);
    }
  }
  else {
    if ((ev->type == GDK_2BUTTON_PRESS) && (ev->button == 1)) {
      /* Left button double clicked. */
      if (thumb->selected != TRUE) {
        /* Thumbnail is not selected. */ 
        thumbnail_set_shadow(thumb, TRUE);
        thumbnail_count_selected_thumbnails(tp, 1);
      }
      /* Start the viewer. */
      tp->from_2button = TRUE;
      tp->op_thumb     = thumb;
      file_menu_cb_view(NULL, tp, 0);
      tp->from_2button = FALSE;
      if (save_selected == FALSE) {
        thumbnail_set_shadow(thumb, FALSE);
        thumbnail_count_selected_thumbnails(tp, -1);
      }
    }
  }

  /* Save the GdkButtonPressEvent structure object, because this 
   * informationwill be used to judge a double click at the next time.
   */
  tp->last_ev_button = *ev;

  return FALSE;
}

/*
 * @thumbnail_cb_icon_drag_begin
 *
 *
 *
 */
static void thumbnail_cb_icon_drag_begin(GtkWidget      *widget ,
                                         GdkDragContext *context,
                                         gpointer       data      ) {
  TopLevel  *tp;
  Thumbnail *thumb;

  /* Initialize the local variables. */
  tp    = (TopLevel*)data;
  thumb = NULL;

  /* Get the Thumbnail structure object. */
  thumb = thumbnail_get_from_widget(tp, widget, TRUE);
  if (thumb == NULL) { return; }

  /* Reset the selected folder for dnd. */
  tp->dnd_selected_row = -1;

  /* Set the clicked thumbnail selected. */
  if (thumb->selected != TRUE) {
    thumbnail_set_shadow(thumb, TRUE);
    thumbnail_count_selected_thumbnails(tp, 1);
  }

  return;
}

/*
 * @thumbnail_cb_icon_drag_end
 *
 *
 *
 */
static void thumbnail_cb_icon_drag_end(GtkWidget      *widget ,
                                       GdkDragContext *context,
                                       gpointer       data      ) {
  TopLevel  *tp;

  /* Initialize the local variables. */
  tp    = (TopLevel*)data;

  dirtree_set_directory_non_hilighted(tp);

  return;
}

/*
 * @thumbnail_cb_entry_key_pressed
 *
 *  When ESC key pressed at the thumbnail's entry, reset changes.
 *
 */
static gboolean thumbnail_cb_entry_key_pressed(GtkWidget     *widget,
                                               GdkEventKey   *ev    ,
                                               gpointer      data     ) {
  TopLevel  *tp;
  Thumbnail *thumb;

  /* Initialize the local variables. */
  tp = (TopLevel*)data;
  thumb = NULL;

  thumb = thumbnail_get_from_widget(tp, widget, TRUE);
  if (thumb != NULL) {
    if ((ev != NULL) && (ev->keyval == GDK_Escape)) {
      gtk_entry_set_text(GTK_ENTRY(thumb->entry), tp->save_filename);
      gtk_editable_set_position(GTK_EDITABLE(thumb->entry), 0);
    }
  }

  return FALSE;
}

/*
 * @thumbnail_cb_entry_focus_in
 *
 *
 *
 */
static gboolean thumbnail_cb_entry_focus_in(GtkWidget     *widget,
                                            GdkEventFocus *ev    ,
                                            gpointer      data     ) {
  TopLevel  *tp;
  Thumbnail *thumb;

  /* Initialize the local variables. */
  tp = (TopLevel*)data;
  thumb = NULL;

  thumb = thumbnail_get_from_widget(tp, widget, TRUE);
  if (thumb != NULL) {
    if (tp->save_filename != NULL) { free(tp->save_filename); }

    if ((tp->save_filename = strdup(thumb->filename)) == NULL) {
      /* Out of memory. */
      fprintf(stderr, "danpei: Out of memory.\n");
      fprintf(stderr, "        thumbnail.c: error -- 08.\n");
      gtk_exit(-1);
    }
    tp->focused_entry = widget;
  }

  return FALSE;
}

/*
 * @thumbnail_cb_entry_focus_out
 *
 *
 *
 */
static gboolean thumbnail_cb_entry_focus_out(GtkWidget     *widget,
                                             GdkEventFocus *ev    ,
                                             gpointer      data     ) {
  static gboolean in_process = FALSE;

  TopLevel  *tp;
  Thumbnail *thumb;
  gchar     *src, *dist;

  /* Initialize the local variables. */
  tp    = (TopLevel*)data;
  thumb = NULL;
  src   = dist = NULL;

  if ((in_process == TRUE) || (tp->focused_entry == NULL)) { 
    return FALSE;
   }
  else {
    in_process = TRUE;
  }

  /* Get thumbnail from widget. */
  if ((tp->app_status == STATUS_TABLE_REFRESH) ||
      (tp->app_status == STATUS_TABLE_PREV   ) ||
      (tp->app_status == STATUS_TABLE_NEXT   )    ){
    thumb = thumbnail_get_from_widget(tp, widget, FALSE);
  } 
  else {
    thumb = thumbnail_get_from_widget(tp, widget, TRUE);
  }
  if (thumb == NULL) {
    in_process = FALSE;
    return FALSE;
  }

  src  = (gchar*)malloc(sizeof(gchar) * 
                        (strlen(thumb->path) + 
                         strlen(tp->save_filename)) + 2);
  dist = (gchar*)malloc(sizeof(gchar) * 
                        (strlen(thumb->path) +
                         strlen(gtk_entry_get_text(GTK_ENTRY(widget)))) + 2);
  if ((src == NULL) || (dist == NULL)) {
    /* Out of memory. */
    if (tp->save_filename != NULL) { free(tp->save_filename); }
    fprintf(stderr, "danpei: Out of memory.\n");
    fprintf(stderr, "        thumbnail.c: error -- 09.\n");
    gtk_exit(-1);
  }
  else {
    sprintf(src , "%s/%s", thumb->path, thumb->filename);
    sprintf(dist, "%s/%s", thumb->path, gtk_entry_get_text(GTK_ENTRY(widget)));
  }

  if ((strcmp(src, dist) ==    0)                 ||
      (tp->app_status    == STATUS_TABLE_REFRESH) ||
      (tp->app_status    == STATUS_TABLE_PREV   ) ||
      (tp->app_status    == STATUS_TABLE_NEXT   )    ) ;
  else {
    if (access(dist, F_OK) == 0) {
      dialog_error_dialog_create(FILE_ALREADY_EXISTS, NULL,
                                 GTK_WINDOW(tp->window));
      gtk_entry_set_text(GTK_ENTRY(thumb->entry), tp->save_filename);
      gtk_editable_set_position(GTK_EDITABLE(thumb->entry), 0);
    }
    else {
      if((rename(src, dist)) != 0) {
        switch (errno) {
          case ENOENT:
            dialog_error_dialog_create(FILE_NOT_EXISTS, NULL,
                                       GTK_WINDOW(tp->window));
            image_cache_delete(&(tp->cache), src);
            thumb->disabled = TRUE;
            thumbnail_set_sensitive(thumb, FALSE);
            thumbnail_count_selected_thumbnails(tp, -1);
            break;
          case EPERM:
          case EACCES:
            dialog_error_dialog_create(PERMISSION_DENIED, NULL, 
                                       GTK_WINDOW(tp->window));
            thumbnail_entry_set_sensitive(thumb, FALSE);
            break;
          case EROFS:
            dialog_error_dialog_create(READ_ONLY_FS, NULL,
                                       GTK_WINDOW(tp->window));
            thumbnail_entry_set_sensitive(thumb, FALSE);
            break;
          case ENAMETOOLONG:
            dialog_error_dialog_create(TOO_LONG_FILE_NAME, NULL,
                                       GTK_WINDOW(tp->window));
            break;
          default:
            dialog_error_dialog_create(RENAME_ERROR, NULL,
                                       GTK_WINDOW(tp->window));
            break;
        }
        gtk_entry_set_text(GTK_ENTRY(thumb->entry), tp->save_filename);
        gtk_editable_set_position(GTK_EDITABLE(thumb->entry), 0);
      }
      else {
        free(thumb->filename);
        thumb->filename = strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
        if (thumb->filename == NULL) {
          /* Out of memory. */
          fprintf(stderr, "danpei: Out of memory.\n");
          fprintf(stderr, "        thumbnail.c: error -- 10.\n");
          gtk_exit(-1);
        }
        else {
          image_cache_rename(&(tp->cache), src, dist);
        }
      }
    }
  }
  
  free(src); free(dist);

  /* Clear the saved filename. */
  if (tp->save_filename != NULL) { 
    free(tp->save_filename); 
    tp->save_filename = NULL;
  }

  tp->focused_entry = NULL;
  in_process = FALSE;

  return FALSE;
}


Generated by  Doxygen 1.6.0   Back to index