Logo Search packages:      
Sourcecode: f-spot version File versions

eog-file-selection.c

#include <config.h>
#include "eog-file-selection.h"
#include <libgnome/gnome-macros.h>
#include <libgnome/gnome-i18n.h>
#include <glib/gslist.h>
#include <gtk/gtklabel.h>
#include <gtk/gtkmenuitem.h>
#include <gtk/gtkmenu.h>
#include <gtk/gtkoptionmenu.h>
#include <gtk/gtkhbox.h>
#include <gtk/gtkmessagedialog.h>

typedef struct {
      const char *label;
      const char *suffix;
} FileTypeInfo;


struct _EogFileSelectionPrivate {
      GtkWidget            *options;
      FileTypeInfo         *last_info;

      FileTypeInfo         *supported_types;
      gboolean             ensure_suffix;
      gboolean             allow_directories;
};

static FileTypeInfo file_types_load[] =  {
      { N_("By Extension"), "" },
      { N_("BMP"),  "*.bmp" },
      { N_("GIF"),  "*.gif" },
      { N_("ICO"),  "*.ico" },
      { N_("JPEG"), "*.jpg" },
      { N_("PNG"),  "*.png" },
      { N_("PNM"),  "*.pnm" },
      { N_("RAS"),  "*.ras" },
      { N_("SVG"),  "*.svg" },
      { N_("TGA"),  "*.tga" },
      { N_("TIFF"), "*.tif" },
      { N_("XBM"),  "*.xbm" },
      { N_("XPM"),  "*.xpm" },
      { NULL, NULL }
};

static FileTypeInfo file_types_save[] =  {
      { N_("By Extension"), "" },
#ifdef HAVE_JPEG
      { N_("JPEG"), "*.jpg" },
#endif
#ifdef HAVE_PNG
      { N_("PNG"),  "*.png" },
#endif
#ifdef HAVE_XPM 
      { N_("XPM"),  "*.xpm" },
#endif
      { NULL, NULL }
};


#define FILE_TYPE_INFO_KEY  "File Type Info"

GNOME_CLASS_BOILERPLATE (EogFileSelection,
                   eog_file_selection,
                   GtkFileSelection,
                   GTK_TYPE_FILE_SELECTION);

static void
eog_file_selection_dispose (GObject *object)
{
      GNOME_CALL_PARENT (G_OBJECT_CLASS, dispose, (object));
}

static void
eog_file_selection_class_init (EogFileSelectionClass *klass)
{
      GObjectClass *object_class = (GObjectClass*) klass;

      object_class->dispose = eog_file_selection_dispose;
}

static void
eog_file_selection_instance_init (EogFileSelection *filesel)
{
      EogFileSelectionPrivate *priv;

      priv = g_new0 (EogFileSelectionPrivate, 1);

      filesel->priv = priv;
}

static void
eog_append_menu_entry (GtkWidget *menu, FileTypeInfo *info) 
{
      GtkWidget *item;

      item = gtk_menu_item_new_with_label (info->label);
      g_object_set_data (G_OBJECT (item), FILE_TYPE_INFO_KEY, info);
      gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
}

static gboolean
is_filename_valid (GtkDialog *dlg)
{
      EogFileSelection *filesel;
      EogFileSelectionPrivate *priv;
      FileTypeInfo *info;
      GtkWidget *menu;
      GtkWidget *item;
      const gchar *filename;
      gint i;

      g_return_val_if_fail (EOG_IS_FILE_SELECTION (dlg), TRUE);

      filesel = EOG_FILE_SELECTION (dlg);
      priv = filesel->priv;

      menu = gtk_option_menu_get_menu (GTK_OPTION_MENU (filesel->priv->options));
      item = gtk_menu_get_active (GTK_MENU (menu));
      g_assert (item != NULL);
      info = g_object_get_data (G_OBJECT (item), FILE_TYPE_INFO_KEY);
      
      filename = gtk_file_selection_get_filename (GTK_FILE_SELECTION (dlg));

      if (priv->allow_directories && g_file_test (filename, G_FILE_TEST_IS_DIR)) {
            return TRUE;
      }

      if (g_strcasecmp (info->suffix, "") == 0) { /* check by extension */
            
            for (i = 0; priv->supported_types[i].label != NULL; i++) {
                  if (g_pattern_match_simple (priv->supported_types[i].suffix, filename))
                        break;
            }
            
            return (priv->supported_types[i].label != NULL);
      }
      else { /* check specific suffix */
            if (!g_pattern_match_simple (info->suffix, filename)) {
                  gchar *tmp;
                  tmp = g_strconcat (filename, info->suffix + 1, NULL);
                  gtk_file_selection_set_filename (GTK_FILE_SELECTION (dlg), tmp);
            }           
      }

      return TRUE;
}

static void
changed_cb (GtkWidget *widget, gpointer data)
{
      GtkWidget *menu;
      GtkWidget *item;
      FileTypeInfo *info;
      const gchar *filename;
      EogFileSelectionPrivate *priv;
      gboolean do_completion = FALSE;

      priv = EOG_FILE_SELECTION (data)->priv;

      /* obtain selected file type info struct */
      menu = gtk_option_menu_get_menu (GTK_OPTION_MENU (widget));
      item = gtk_menu_get_active (GTK_MENU (menu));

      info = g_object_get_data (G_OBJECT (item), FILE_TYPE_INFO_KEY);

      /* Check if we should perform file completion by suffix.
       * This is mainly to prevent the deletion of filenames entered by
       * the user when browsing through the available file types. 
       * gtk_file_selection_complete is fairly limited wrt this.
       */
      filename = gtk_file_selection_get_filename (GTK_FILE_SELECTION (data));
      if (g_file_test (filename, G_FILE_TEST_IS_DIR))
      {
            do_completion = TRUE;
      }
      else if (priv->last_info != NULL) {
            gchar *basename = g_path_get_basename (filename);

            if (g_strcasecmp (basename, priv->last_info->suffix) == 0) {
                  do_completion = TRUE;
            }
            g_free (basename);
      }

      if (do_completion) {
            gtk_file_selection_complete (GTK_FILE_SELECTION (data), info->suffix);        
      }
      
      if (g_strcasecmp (info->suffix, "") == 0) 
            priv->last_info = NULL;
      else 
            priv->last_info = info;
}

static void
response_cb (GtkDialog *dlg, gint id, gpointer data)
{
      if (id == GTK_RESPONSE_OK && !is_filename_valid (dlg)) {
            GtkWidget *dialog;

            g_signal_stop_emission_by_name (G_OBJECT (dlg), "response");

            dialog = gtk_message_dialog_new (GTK_WINDOW (dlg),
                                     0,
                                     GTK_MESSAGE_WARNING,
                                     GTK_BUTTONS_CLOSE,
                                     _("Unsupported file format."));
            gtk_dialog_run (GTK_DIALOG (dialog));
            gtk_widget_destroy (dialog);
      }
}

static void
eog_file_selection_construct (GtkWidget *widget)
{
      EogFileSelection *filesel;
      GtkWidget *hbox;
      GtkWidget *menu;
      gint i;

      filesel = EOG_FILE_SELECTION (widget);

      hbox = gtk_hbox_new (FALSE, 4);
      gtk_box_pack_start (GTK_BOX (hbox),
                      gtk_label_new (_("Determine File Type:")),
                      FALSE, FALSE, 0);
      filesel->priv->options = gtk_option_menu_new ();
      menu = gtk_menu_new ();
      
      for (i = 0; filesel->priv->supported_types[i].label != NULL; i++) {
            eog_append_menu_entry (menu, &filesel->priv->supported_types[i]);
      }
      
      gtk_option_menu_set_menu (GTK_OPTION_MENU (filesel->priv->options), menu);
      g_signal_connect (G_OBJECT (filesel->priv->options), "changed", 
                          G_CALLBACK (changed_cb), filesel);
      gtk_box_pack_start (GTK_BOX (hbox), filesel->priv->options, FALSE, FALSE, 0);
      gtk_box_pack_start (GTK_BOX (GTK_DIALOG (filesel)->vbox), hbox,
                            FALSE, FALSE, 10);  
      gtk_widget_show_all (hbox);

      g_signal_connect (G_OBJECT (filesel), "response", G_CALLBACK (response_cb), NULL);
}

GtkWidget* 
eog_file_selection_new (EogFileSelectionType type)
{
      GtkWidget *filesel;
      gchar *title;
      EogFileSelectionPrivate *priv;

      filesel = GTK_WIDGET (g_object_new (EOG_TYPE_FILE_SELECTION,
                                  "show_fileops", TRUE,
                                  "select_multiple", FALSE,
                                  NULL));

      priv = EOG_FILE_SELECTION (filesel)->priv;

      switch (type) {
      case EOG_FILE_SELECTION_LOAD:
            priv->supported_types = file_types_load;
            priv->ensure_suffix = FALSE;
#if HAVE_COLLECTION
            priv->allow_directories = TRUE;
#else
            priv->allow_directories = FALSE;
#endif
            title = _("Load Image");
            break;
      case EOG_FILE_SELECTION_SAVE:
            priv->supported_types = file_types_save;
            priv->ensure_suffix = TRUE;
            priv->allow_directories = FALSE;
            title = _("Save Image");
            break;
      default:
            title = NULL;
            g_assert_not_reached ();
      }
      priv->last_info = NULL;
      
      eog_file_selection_construct (filesel);

      gtk_window_set_title (GTK_WINDOW (filesel), title);
      g_signal_connect (G_OBJECT (filesel), "response", G_CALLBACK (response_cb), NULL);

      return filesel;
}


Generated by  Doxygen 1.6.0   Back to index