[gnac] Improved file filters



commit aea007a7924a67764e08bdb25d9d66ca8971d190
Author: Benoît Dupasquier <bdupasqu src gnome org>
Date:   Tue Jun 8 21:23:10 2010 +0100

    Improved file filters

 data/ui/gnac.xml |  105 ++++++++++++++
 src/gnac-main.c  |  304 ++--------------------------------------
 src/gnac-main.h  |    5 -
 src/gnac-ui.c    |  411 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 src/gnac-ui.h    |   30 ++++
 5 files changed, 555 insertions(+), 300 deletions(-)
---
diff --git a/data/ui/gnac.xml b/data/ui/gnac.xml
index 1141a46..39a5a35 100644
--- a/data/ui/gnac.xml
+++ b/data/ui/gnac.xml
@@ -387,4 +387,109 @@ Alexandre Roux &lt;alexroux src gnome org&gt;</property>
       </object>
     </child>
   </object>
+  <object class="GtkFileChooserDialog" id="gnac_file_chooser">
+    <property name="border_width">5</property>
+    <property name="title" translatable="yes">Open a File...</property>
+    <property name="modal">True</property>
+    <property name="window_position">center-on-parent</property>
+    <property name="type_hint">dialog</property>
+    <property name="has_separator">False</property>
+    <property name="select_multiple">True</property>
+    <property name="use_preview_label">False</property>
+    <property name="preview_widget_active">False</property>
+    <signal name="delete-event" handler="gtk_widget_hide_on_delete"/>
+    <signal name="key-press-event" handler="gnac_ui_file_chooser_key_press_event_cb"/>
+    <signal name="file-activated" handler="gnac_ui_file_chooser_file_activated_cb"/>
+    <signal name="response" handler="gnac_ui_file_chooser_response_cb"/>
+    <signal name="destroy" handler="gnac_ui_file_chooser_response_cb"/>
+    <child internal-child="vbox">
+      <object class="GtkVBox" id="dialog-vbox2">
+        <property name="visible">True</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">2</property>
+        <child>
+          <object class="GtkAlignment" id="alignment1">
+            <property name="visible">True</property>
+            <property name="bottom_padding">12</property>
+            <property name="left_padding">5</property>
+            <property name="right_padding">5</property>
+            <child>
+              <object class="GtkHBox" id="hbox2">
+                <property name="visible">True</property>
+                <child>
+                  <object class="GtkCheckButton" id="close_on_add_button">
+                    <property name="label" translatable="yes">Close dialog on add</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">False</property>
+                    <property name="active">True</property>
+                    <property name="draw_indicator">True</property>
+                  </object>
+                  <packing>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkComboBox" id="filters_combo">
+                    <property name="visible">True</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="position">2</property>
+          </packing>
+        </child>
+        <child internal-child="action_area">
+          <object class="GtkHButtonBox" id="dialog-action_area2">
+            <property name="visible">True</property>
+            <property name="layout_style">end</property>
+            <child>
+              <object class="GtkButton" id="add_button">
+                <property name="label" translatable="yes">gtk-add</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="close_button">
+                <property name="label" translatable="yes">gtk-close</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <action-widgets>
+      <action-widget response="-1">add_button</action-widget>
+      <action-widget response="-7">close_button</action-widget>
+    </action-widgets>
+  </object>
 </interface>
diff --git a/src/gnac-main.c b/src/gnac-main.c
index ec3b599..3c481ea 100644
--- a/src/gnac-main.c
+++ b/src/gnac-main.c
@@ -27,7 +27,6 @@
 #include "config.h"
 #endif /* HAVE_CONFIG_H */
 
-#include <gdk/gdkkeysyms.h>
 #include <gio/gio.h>
 #include <glib/gi18n.h>
 #include <gst/gst.h>
@@ -54,10 +53,6 @@
 #include "profiles/gnac-profiles-utils.h"
 
 
-static GtkFileFilter    *current_file_filter;
-static GtkFileFilter    *default_file_filter;
-static GSList           *filters;
-static gchar            *current_directory;
 static LibgnacConverter *converter;
 static gboolean          conversion_errors;
 static guint64           prev_time_left;
@@ -72,9 +67,9 @@ static gboolean          remember_overwrite = FALSE;
 gint                     nb_files_total;
 guint                    nb_files_added;
 
-GnacState                state;
-GnacState                prev_state;
-LibgnacMetadata         *metadata;
+GnacState        state;
+GnacState        prev_state;
+LibgnacMetadata *metadata;
 
 static const gchar *states[] = {
   "GNAC_AUDIO_EMPTY_STATE",
@@ -336,179 +331,6 @@ gnac_add_files(GSList *files)
 }
 
 
-static void
-gnac_file_chooser_foreach(gpointer data, 
-                          gpointer user_data)
-{
-  GFile *file;
-  GSList **list;
-  
-  list = (GSList**) user_data;
-  file = g_file_new_for_uri((gchar*)data);
-  *list = g_slist_append(*list, file);
-  g_free(data);
-}
-
-
-static void
-gnac_init_filters(void)
-{
-  filters = (GSList*) NULL;
-  
-  /* To translators: translation of filters' name can be
-   * found in /usr/share/mime */
-  const gchar *lossy_mime[][2] = {
-    { "audio/mpeg"            , _("MP3 audio (*.mp3)")                  },
-    { "audio/mp4"             , _("MPEG-4 audio (*.aac, *.m4a, *.mp4)") },
-    { "audio/x-musepack"      , _("Musepack audio (*.mpc)")             },
-    { "audio/ogg"             , _("Ogg Audio (*.oga)")                  },
-    { "audio/vnd.rn-realaudio", _("RealAudio document (*.ra)")          },
-    { "audio/x-speex"         , _("Speex audio (*.spx)")                },
-    { "audio/x-ms-wma"        , _("Windows Media audio (*.wma)")        },
-    { NULL, NULL }
-  };
-
-  const gchar *lossless_mime[][2] = {
-    /* XXX the Monkey's Audio plug-in has not yet been ported 
-     * to gstreamer-0.10 */
-    /*{ "audio/x-ape" , _("Monkey's audio (*.ape)")   },*/
-    { "audio/x-flac"   , _("Flac audio (*.flac)")  },
-    { "audio/x-wav"    , _("WAV audio (*.wav)")    },
-    { "audio/x-wavpack", _("WavPack audio (*.wv)") },
-    { NULL, NULL }
-  };
-
-  const gchar *supported_mime_playlists[][2] = {
-    { "audio/x-mpegurl"     , _("MP3 audio (streamed) (*.m3u)")   },
-    { "audio/x-scpls"       , _("MP3 ShoutCast playlist (*.pls)") },
-    { "application/xspf+xml", _("XSPF playlist (*.xspf)")         },
-    { NULL, NULL }
-  };
-
-  GtkFileFilter *file_filter_all = gtk_file_filter_new();
-  gtk_file_filter_add_pattern(file_filter_all, "*");
-  gtk_file_filter_set_name(file_filter_all, _("All files (*.*)"));
-
-  GtkFileFilter* file_filter_supported = gtk_file_filter_new();
-  gtk_file_filter_set_name(file_filter_supported, _("Supported files"));
-
-  /* all supported types */
-
-  guint i = 0;
-  while (lossless_mime[i][0] != NULL) {
-    gtk_file_filter_add_mime_type(file_filter_supported, lossless_mime[i][0]);
-    i++;
-  }
-
-  i = 0;
-  while (lossy_mime[i][0] != NULL) {
-    gtk_file_filter_add_mime_type(file_filter_supported, lossy_mime[i][0]);
-    i++;
-  }
-
-  i = 0;
-  GtkFileFilter *file_filter_playlists = gtk_file_filter_new();
-  gtk_file_filter_set_name(file_filter_playlists, _("Playlists files"));
-  while (supported_mime_playlists[i][0] != NULL) {
-    gtk_file_filter_add_mime_type(file_filter_supported, supported_mime_playlists[i][0]);
-    gtk_file_filter_add_mime_type(file_filter_playlists, supported_mime_playlists[i][0]);
-    i++;
-  }
-
-  filters = g_slist_append(filters, (gpointer) file_filter_all);
-  filters = g_slist_append(filters, (gpointer) file_filter_supported);
-  filters = g_slist_append(filters, (gpointer) file_filter_playlists);
-
-  /* Lossless types */
-
-  i = 0;
-  GtkFileFilter *file_filter_lossless = gtk_file_filter_new();
-  gtk_file_filter_set_name(file_filter_lossless, _("Lossless codecs"));
-  while (lossless_mime[i][0] != NULL) {
-    gtk_file_filter_add_mime_type(file_filter_lossless, lossless_mime[i][0]);
-    i++;
-  }
-  filters = g_slist_append(filters, (gpointer) file_filter_lossless);
-
-  /* Lossy types */
-
-  i = 0;
-  GtkFileFilter *file_filter_lossy = gtk_file_filter_new();
-  gtk_file_filter_set_name(file_filter_lossy, _("Lossy codecs"));
-  while (lossy_mime[i][0] != NULL) {
-    gtk_file_filter_add_mime_type(file_filter_lossy, lossy_mime[i][0]);
-    i++;
-  }
-  filters = g_slist_append(filters, (gpointer) file_filter_lossy);
-
-  /* Create filters for each kind of audio files */
-
-  i = 0;
-  GtkFileFilter *file_filter_tmp;
-  while (lossless_mime[i][0] != NULL) {
-    file_filter_tmp = gtk_file_filter_new();
-    gtk_file_filter_add_mime_type(file_filter_tmp, lossless_mime[i][0]);
-    gtk_file_filter_set_name(file_filter_tmp, lossless_mime[i][1]);
-    filters = g_slist_append(filters, (gpointer) file_filter_tmp);
-    i++;
-  }
-
-  i = 0;
-  while (lossy_mime[i][0] != NULL) {
-    file_filter_tmp = gtk_file_filter_new();
-    gtk_file_filter_add_mime_type(file_filter_tmp, lossy_mime[i][0]);
-    gtk_file_filter_set_name(file_filter_tmp, lossy_mime[i][1]);
-    filters = g_slist_append(filters, (gpointer) file_filter_tmp);
-    i++;
-  }
-
-  /* Create filters for playlists */
-
-  i = 0;
-  while (supported_mime_playlists[i][0] != NULL) {
-    file_filter_tmp = gtk_file_filter_new();
-    gtk_file_filter_add_mime_type(file_filter_tmp, supported_mime_playlists[i][0]);
-    gtk_file_filter_set_name(file_filter_tmp, supported_mime_playlists[i][1]);
-    filters = g_slist_append(filters, (gpointer) file_filter_tmp);
-    i++;
-  }
-
-  GSList *next;
-  for (next = filters; next; next = next->next) {
-    g_object_ref(G_OBJECT(next->data)); 
-  }
-  current_file_filter = file_filter_supported;
-  default_file_filter = file_filter_supported;
-}
-
-
-static void
-gnac_add_filters(GtkFileChooser *file_chooser)
-{
-  GSList *next;
-
-  for (next = filters; next; next = next->next) {
-    gtk_file_chooser_add_filter (file_chooser, GTK_FILE_FILTER(next->data));
-  }
-
-  /* we want to keep track of the chosen file filter 
-   * (Supported files at the beginning) */
-  gtk_file_chooser_set_filter(file_chooser, current_file_filter);
-}
-
-
-static void
-gnac_unref_filters(void)
-{
-  GSList *next;
-  for (next = filters; next; next = next->next) {
-     g_object_ref_sink(G_OBJECT(next->data)); 
-     g_object_unref(next->data);
-  }
-  g_slist_free(filters);
-}
-
-
 void
 gnac_add_file(GFile *file)
 {
@@ -530,12 +352,13 @@ gnac_add_file(GFile *file)
   filter_info.mime_type = g_file_info_get_content_type(info);
 
   if (filter_info.mime_type != NULL) {
-
     /* Check whether we have a playlist */
     if (gnac_playlist_is_mime_playlist(filter_info.mime_type)) {
       gnac_playlist_parse(file, filter_info.mime_type);
     /* Check whether the file format is supported */
-    } else if (gtk_file_filter_filter(current_file_filter, &filter_info)) {
+    } else if (gtk_file_filter_filter(gnac_ui_get_current_filter(),
+        &filter_info))
+    {
       libgnac_info("Add file %s", g_file_get_uri(file));
       libgnac_converter_add(converter, file, &error);
     }
@@ -595,13 +418,9 @@ gnac_on_ui_destroy_cb(GtkWidget *widget,
     if (thread != NULL) g_thread_join(thread);
   }
 
-  g_free(current_directory);
-
   g_object_unref(converter);
   g_object_unref(metadata);
 
-  gnac_unref_filters();
-
   gnac_properties_destroy();
   gnac_prefs_destroy();
   gnac_profiles_destroy();
@@ -613,74 +432,6 @@ gnac_on_ui_destroy_cb(GtkWidget *widget,
 }
 
 
-static void
-gnac_file_chooser_file_activated_cb(GtkFileChooser *chooser,
-                                    gpointer        user_data)
-{
-  gnac_file_chooser_response_cb(GTK_DIALOG(chooser), GTK_RESPONSE_NONE, NULL);
-}
-
-
-static gboolean
-gnac_file_chooser_key_press_event_cb(GtkWidget   *widget,
-                                     GdkEventKey *event,
-                                     gpointer     user_data)
-{
-  if (event->type == GDK_KEY_PRESS && event->keyval == GDK_Return)
-  {
-    gnac_file_chooser_response_cb(GTK_DIALOG(widget), GTK_RESPONSE_NONE, NULL);
-    return TRUE;
-  }
-  return FALSE;
-}
-
-
-void
-gnac_file_chooser_response_cb(GtkDialog *dialog,
-                              gint       response,
-                              gpointer   user_data)
-{
-  GSList *list_path;
-  GSList *list_files = NULL;
-
-  GtkWidget *close_on_add_button;
-  
-  switch (response) {
-    /* Add button */
-    case GTK_RESPONSE_NONE:
-      
-      /* Set the current file filter */
-      current_file_filter = gtk_file_chooser_get_filter(GTK_FILE_CHOOSER(dialog));
-      list_path = gtk_file_chooser_get_uris(GTK_FILE_CHOOSER(dialog));
-
-      /* Add the differents files */
-      g_slist_foreach(list_path,(GFunc) gnac_file_chooser_foreach, (gpointer) &list_files);
-
-      /* free the list */
-      g_slist_free(list_path);
-      
-      /* add files */
-      gnac_add_files(list_files);
-
-      /* Do we have to close de file chooser? */
-      close_on_add_button = gtk_file_chooser_get_extra_widget(GTK_FILE_CHOOSER(dialog));
-
-      /* Get the current uri */
-      g_free(current_directory);
-      current_directory = gtk_file_chooser_get_current_folder_uri(GTK_FILE_CHOOSER(dialog));
-
-      if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(close_on_add_button))) return;
-
-      break;
-     
-    case GTK_RESPONSE_CLOSE:
-    default: 
-      break;
-  }
-  gtk_widget_destroy(GTK_WIDGET(dialog));
-}
-
-
 static gboolean
 gnac_on_converter_overwrite_cb(LibgnacConverter *converter, 
                                gpointer          file,
@@ -1051,37 +802,7 @@ void
 gnac_on_ui_add_cb(GtkAction *action, 
                   gpointer   data)
 {
-  GtkWidget *close_on_add_button;
-  GtkWidget *file_chooser;
-  
-  file_chooser = gtk_file_chooser_dialog_new(_("Open a File..."),
-      GTK_WINDOW(data),
-      GTK_FILE_CHOOSER_ACTION_OPEN,
-      GTK_STOCK_ADD, GTK_RESPONSE_NONE,
-      GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
-      NULL);
-
-  gtk_window_set_type_hint(GTK_WINDOW(file_chooser), GDK_WINDOW_TYPE_HINT_DIALOG);
-
-  gtk_file_chooser_set_current_folder_uri(GTK_FILE_CHOOSER(file_chooser), 
-                  current_directory);
-  gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(file_chooser), TRUE);
-
-  close_on_add_button = gtk_check_button_new_with_label(_("Close dialog on add"));
-  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(close_on_add_button),TRUE);
-  gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER(file_chooser),
-                  close_on_add_button);
-
-  gnac_add_filters(GTK_FILE_CHOOSER(file_chooser));
-
-  g_signal_connect(file_chooser, "response", 
-                  G_CALLBACK(gnac_file_chooser_response_cb), data);
-  g_signal_connect(file_chooser, "key-press-event", 
-                  G_CALLBACK(gnac_file_chooser_key_press_event_cb), data);
-  g_signal_connect(file_chooser, "file-activated", 
-                  G_CALLBACK(gnac_file_chooser_file_activated_cb), data);
-
-  gtk_dialog_run(GTK_DIALOG(file_chooser));
+  gtk_widget_show_all(gnac_ui_get_file_chooser());
 }
 
 
@@ -1155,7 +876,7 @@ gnac_on_ui_drag_data_received_cb(GtkWidget        *widget,
   gint index = 0;
 
   /* Disable any filtering for DnD. */
-  current_file_filter = default_file_filter;
+  gnac_ui_reset_file_filter();
 
   uris = gtk_selection_data_get_uris(selection_data);
 
@@ -1217,12 +938,12 @@ main(gint    argc,
     textdomain(GETTEXT_PACKAGE);
   #endif /* ENABLE_NLS */
 
-  /* Parse command line arguments */
-  gnac_options_init(argc, argv);
-
   /* Set a name for the application */
   g_set_application_name(PACKAGE_NAME);
 
+  /* Parse command line arguments */
+  gnac_options_init(argc, argv);
+
   /* Initialisation of libraries */
   gdk_threads_init();
 
@@ -1234,12 +955,9 @@ main(gint    argc,
   /* Init gstreamer plugins helper*/
   gst_pb_utils_init();
 
-  gnac_init_filters();
   gnac_gconf_init();
   gnac_profiles_init();
 
-  current_directory = g_strdup(g_get_home_dir());
-
   /* Initialise converter and connect signals */
   metadata = LIBGNAC_METADATA(libgnac_metadata_new());
   converter = LIBGNAC_CONVERTER(libgnac_converter_new(metadata));
diff --git a/src/gnac-main.h b/src/gnac-main.h
index bea7156..b4e913f 100644
--- a/src/gnac-main.h
+++ b/src/gnac-main.h
@@ -104,11 +104,6 @@ gnac_on_file_monitor_changed_cb(GFileMonitor      *monitor,
                                 GFileMonitorEvent  event_type,
                                 gpointer           user_data);
 
-void
-gnac_file_chooser_response_cb(GtkDialog *dialog,
-                              gint       response,
-                              gpointer   user_data);
-
 G_END_DECLS
 
 #endif /* GNAC_MAIN_H */
diff --git a/src/gnac-ui.c b/src/gnac-ui.c
index 7e17ee2..07204ae 100644
--- a/src/gnac-ui.c
+++ b/src/gnac-ui.c
@@ -27,6 +27,7 @@
 #include "config.h"
 #endif /* HAVE_CONFIG_H */
 
+#include <gdk/gdkkeysyms.h>
 #include <glib/gi18n.h>
 #include <glib/gprintf.h>
 
@@ -39,10 +40,15 @@
 #include "gnac-gconf.h"
 #include "profiles/gnac-profiles.h"
 
+extern GnacState state;
 extern LibgnacMetadata *metadata;
 
+static GSList         *filters;
 static GtkBuilder     *gnac_main_builder = NULL;
+static GtkFileFilter  *default_file_filter;
 static GtkStatusIcon  *trayicon = NULL;
+static GtkWidget      *gnac_file_chooser;
+static gchar          *current_directory;
 static gchar          *status_msg = NULL;
 static gchar          *tooltip_path = NULL;
 static gchar          *progress_msg = NULL;
@@ -60,8 +66,6 @@ static GtkTargetEntry target_list[] =  {
 
 static guint n_targets = G_N_ELEMENTS(target_list);
 
-extern GnacState state;
-
 
 static void
 gnac_about_url_hook(GtkAboutDialog *dialog,
@@ -90,6 +94,401 @@ gnac_about_email_hook(GtkAboutDialog *dialog,
 }
 
 
+static void
+gnac_ui_file_chooser_unref_filters(void)
+{
+  GSList *f;
+  for (f = filters; f; f = f->next) {
+    g_object_unref(f->data);
+  }
+  g_slist_free(f);
+}
+
+
+static void
+gnac_ui_file_chooser_dispose(void)
+{
+  gnac_ui_file_chooser_unref_filters();
+  gtk_widget_destroy(gnac_file_chooser);
+}
+
+
+static void
+gnac_ui_file_chooser_cell_data_func(GtkCellLayout   *layout,
+                                    GtkCellRenderer *cell,
+                                    GtkTreeModel    *model,
+                                    GtkTreeIter     *iter,
+                                    gpointer         data)
+{
+  GtkFileFilter *filter;
+  gtk_tree_model_get(model, iter, 0, &filter, -1);
+  g_object_set(cell, "text", gtk_file_filter_get_name(filter), NULL);
+}
+
+
+static GtkTreeModel *
+gnac_ui_file_chooser_get_filters_model(void)
+{
+  guint          i;
+  GSList        *f;
+  GtkFileFilter *filter;
+  GtkTreeIter    iter1, iter2, iter3;
+  GtkTreeStore  *store;
+
+  /* To translators: translation of filters' name can be
+   * found in /usr/share/mime */
+  const gchar *lossy_mime[][2] = {
+    { "audio/mpeg"            , _("MP3 audio")           },
+    { "audio/mp4"             , _("MPEG-4 audio")        },
+    { "audio/x-musepack"      , _("Musepack audio")      },
+    { "audio/ogg"             , _("Ogg Audio")           },
+    { "audio/vnd.rn-realaudio", _("RealAudio document")  },
+    { "audio/x-speex"         , _("Speex audio")         },
+    { "audio/x-ms-wma"        , _("Windows Media audio") },
+    { NULL, NULL }
+  };
+
+  const gchar *lossless_mime[][2] = {
+    /* XXX the Monkey's Audio plug-in has not yet been ported
+     * to gstreamer-0.10 */
+    /*{ "audio/x-ape" , _("Monkey's audio")   },*/
+    { "audio/x-flac"   , _("Flac audio")    },
+    { "audio/x-wav"    , _("WAV audio")     },
+    { "audio/x-wavpack", _("WavPack audio") },
+    { NULL, NULL }
+  };
+
+  const gchar *playlists_mime[][2] = {
+    { "audio/x-mpegurl"     , _("MP3 audio (streamed)")   },
+    { "audio/x-scpls"       , _("MP3 ShoutCast playlist") },
+    { "application/xspf+xml", _("XSPF playlist")          },
+    { NULL, NULL }
+  };
+
+  filters = NULL;
+  store = gtk_tree_store_new(1, G_TYPE_POINTER);
+
+  /* All files */
+  filter = gtk_file_filter_new();
+  gtk_file_filter_add_pattern(filter, "*");
+  gtk_file_filter_set_name(filter, _("All files"));
+  gtk_tree_store_append(store, &iter1, NULL);
+  gtk_tree_store_set(store, &iter1, 0, filter, -1);
+  filters = g_slist_append(filters, (gpointer)filter);
+
+  /* Supported files */
+  filter = gtk_file_filter_new();
+  gtk_file_filter_set_name(filter, _("Supported files"));
+  i = 0;
+  while (lossless_mime[i][0]) {
+    gtk_file_filter_add_mime_type(filter, lossless_mime[i][0]);
+    i++;
+  }
+  i = 0;
+  while (lossy_mime[i][0]) {
+    gtk_file_filter_add_mime_type(filter, lossy_mime[i][0]);
+    i++;
+  }
+  i = 0;
+  while (playlists_mime[i][0]) {
+    gtk_file_filter_add_mime_type(filter, playlists_mime[i][0]);
+    i++;
+  }
+  gtk_tree_store_append(store, &iter1, NULL);
+  gtk_tree_store_set(store, &iter1, 0, filter, -1);
+  filters = g_slist_append(filters, (gpointer)filter);
+  default_file_filter = filter;
+
+  /* Audio files */
+  filter = gtk_file_filter_new();
+  gtk_file_filter_set_name(filter, _("Audio files"));
+  i = 0;
+  while (lossless_mime[i][0]) {
+    gtk_file_filter_add_mime_type(filter, lossless_mime[i][0]);
+    i++;
+  }
+  i = 0;
+  while (lossy_mime[i][0]) {
+    gtk_file_filter_add_mime_type(filter, lossy_mime[i][0]);
+    i++;
+  }
+  i = 0;
+  while (playlists_mime[i][0]) {
+    gtk_file_filter_add_mime_type(filter, playlists_mime[i][0]);
+    i++;
+  }
+  gtk_tree_store_append(store, &iter1, NULL);
+  gtk_tree_store_set(store, &iter1, 0, filter, -1);
+  filters = g_slist_append(filters, (gpointer)filter);
+
+  /* Lossy files */
+  filter = gtk_file_filter_new();
+  gtk_file_filter_set_name(filter, _("Lossy files"));
+  i = 0;
+  while (lossy_mime[i][0]) {
+    gtk_file_filter_add_mime_type(filter, lossy_mime[i][0]);
+    i++;
+  }
+  gtk_tree_store_append(store, &iter2, &iter1);
+  gtk_tree_store_set(store, &iter2, 0, filter, -1);
+  filters = g_slist_append(filters, (gpointer)filter);
+
+  /* Individual lossy files */
+  i = 0;
+  while (lossy_mime[i][0]) {
+    filter = gtk_file_filter_new();
+    gtk_file_filter_add_mime_type(filter, lossy_mime[i][0]);
+    gtk_file_filter_set_name(filter, lossy_mime[i][1]);
+    gtk_tree_store_append(store, &iter3, &iter2);
+    gtk_tree_store_set(store, &iter3, 0, filter, -1);
+    filters = g_slist_append(filters, (gpointer)filter);
+    i++;
+  }
+
+  /* Lossless files */
+  filter = gtk_file_filter_new();
+  gtk_file_filter_set_name(filter, _("Lossless files"));
+  i = 0;
+  while (lossless_mime[i][0]) {
+    gtk_file_filter_add_mime_type(filter, lossless_mime[i][0]);
+    i++;
+  }
+  gtk_tree_store_append(store, &iter2, &iter1);
+  gtk_tree_store_set(store, &iter2, 0, filter, -1);
+  filters = g_slist_append(filters, (gpointer)filter);
+
+  /* Individual lossless files */
+  i = 0;
+  while (lossless_mime[i][0]) {
+    filter = gtk_file_filter_new();
+    gtk_file_filter_add_mime_type(filter, lossless_mime[i][0]);
+    gtk_file_filter_set_name(filter, lossless_mime[i][1]);
+    gtk_tree_store_append(store, &iter3, &iter2);
+    gtk_tree_store_set(store, &iter3, 0, filter, -1);
+    filters = g_slist_append(filters, (gpointer)filter);
+    i++;
+  }
+
+  /* Playlists */
+  filter = gtk_file_filter_new();
+  gtk_file_filter_set_name(filter, _("Playlists"));
+  i = 0;
+  while (playlists_mime[i][0]) {
+    gtk_file_filter_add_mime_type(filter, playlists_mime[i][0]);
+    i++;
+  }
+  gtk_tree_store_append(store, &iter1, NULL);
+  gtk_tree_store_set(store, &iter1, 0, filter, -1);
+  filters = g_slist_append(filters, (gpointer)filter);
+
+  /* Individual playlists */
+  i = 0;
+  while (playlists_mime[i][0]) {
+    filter = gtk_file_filter_new();
+    gtk_file_filter_add_mime_type(filter, playlists_mime[i][0]);
+    gtk_file_filter_set_name(filter, playlists_mime[i][1]);
+    gtk_tree_store_append(store, &iter2, &iter1);
+    gtk_tree_store_set(store, &iter2, 0, filter, -1);
+    filters = g_slist_append(filters, (gpointer)filter);
+    i++;
+  }
+
+  for (f = filters; f; f = f->next) {
+    g_object_ref(G_OBJECT(f->data));
+  }
+
+  return GTK_TREE_MODEL(store);
+}
+
+
+static void
+gnac_ui_file_chooser_foreach(gpointer data,
+                             gpointer user_data)
+{
+  GFile   *file;
+  GSList **list;
+
+  list = (GSList**) user_data;
+  file = g_file_new_for_uri((gchar*)data);
+  *list = g_slist_append(*list, file);
+  g_free(data);
+}
+
+
+static GtkWidget *
+gnac_ui_file_chooser_new(void)
+{
+  GtkCellRenderer *renderer;
+  GtkTreeModel    *model;
+  GtkWidget       *combo;
+
+  gnac_file_chooser = gnac_ui_get_widget("gnac_file_chooser");
+  model = gnac_ui_file_chooser_get_filters_model();
+  combo = gnac_ui_get_widget("filters_combo");
+  gtk_combo_box_set_model(GTK_COMBO_BOX(combo), model);
+
+  renderer = gtk_cell_renderer_text_new();
+  gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo), renderer, TRUE);
+  gtk_cell_layout_set_cell_data_func(GTK_CELL_LAYOUT(combo), renderer,
+      (GtkCellLayoutDataFunc)gnac_ui_file_chooser_cell_data_func,
+      NULL, NULL);
+
+  g_signal_connect(G_OBJECT(combo), "changed",
+      G_CALLBACK(gnac_ui_on_filter_changed), gnac_file_chooser);
+
+  /* Use the 'Supported files' filter by default */
+  gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 1);
+  gnac_ui_on_filter_changed(GTK_COMBO_BOX(combo), gnac_file_chooser);
+
+  return gnac_file_chooser;
+}
+
+
+void
+gnac_ui_reset_file_filter(void)
+{
+  GtkComboBox *combo;
+  combo = GTK_COMBO_BOX(gnac_ui_get_widget("filters_combo"));
+  gtk_combo_box_set_active(combo, 1);
+  gnac_ui_on_filter_changed(combo, gnac_file_chooser);
+}
+
+
+GtkWidget *
+gnac_ui_get_file_chooser(void)
+{
+  if (G_UNLIKELY(!gnac_file_chooser)) {
+    gnac_file_chooser = gnac_ui_file_chooser_new();
+  }
+  return gnac_file_chooser;
+}
+
+
+GtkFileFilter *
+gnac_ui_get_current_filter(void)
+{
+  gpointer      filter;
+  GtkTreeIter   iter;
+  GtkTreeModel *model;
+  GtkComboBox  *combo;
+
+  /* make sure the filters have been created */
+  gnac_ui_get_file_chooser();
+
+  combo = GTK_COMBO_BOX(gnac_ui_get_widget("filters_combo"));
+
+  if (!gtk_combo_box_get_active_iter(combo, &iter)) {
+    return default_file_filter;
+  }
+
+  model = gtk_combo_box_get_model(combo);
+  g_return_val_if_fail(model, default_file_filter);
+
+  gtk_tree_model_get(model, &iter, 0, &filter, -1);
+  if (GTK_IS_FILE_FILTER(filter)) {
+    return GTK_FILE_FILTER(filter);
+  }
+
+  return default_file_filter;
+}
+
+
+GtkFileFilter *
+gnac_ui_get_default_filter(void)
+{
+  return default_file_filter;
+}
+
+
+void
+gnac_ui_on_filter_changed(GtkComboBox *combo,
+                          gpointer     user_data)
+{
+  gpointer      filter;
+  GtkTreeIter   iter;
+  GtkTreeModel *model;
+
+  if (!gtk_combo_box_get_active_iter(combo, &iter)) return;
+
+  model = gtk_combo_box_get_model(combo);
+  g_return_if_fail(model);
+  gtk_tree_model_get(model, &iter, 0, &filter, -1);
+  if (GTK_IS_FILE_FILTER(filter)) {
+    gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(user_data),
+        GTK_FILE_FILTER(filter));
+  }
+}
+
+
+void
+gnac_ui_file_chooser_response_cb(GtkDialog *dialog,
+                                 gint       response,
+                                 gpointer   user_data)
+{
+  GSList *list_path;
+  GSList *list_files = NULL;
+
+  GtkWidget *close_on_add_button;
+
+  switch (response) {
+    /* Add button */
+    case GTK_RESPONSE_NONE:
+      list_path = gtk_file_chooser_get_uris(GTK_FILE_CHOOSER(dialog));
+
+      /* Add the differents files */
+      g_slist_foreach(list_path,(GFunc) gnac_ui_file_chooser_foreach,
+          (gpointer)&list_files);
+
+      /* free the list */
+      g_slist_free(list_path);
+
+      /* add files */
+      gnac_add_files(list_files);
+
+      /* Do we have to close de file chooser? */
+      close_on_add_button = gnac_ui_get_widget("close_on_add_button");
+
+      /* Get the current uri */
+      g_free(current_directory);
+      current_directory = gtk_file_chooser_get_current_folder_uri(
+          GTK_FILE_CHOOSER(dialog));
+
+      if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(close_on_add_button)))
+          return;
+
+      break;
+
+    case GTK_RESPONSE_CLOSE:
+    default:
+      break;
+  }
+  gtk_widget_hide(GTK_WIDGET(dialog));
+}
+
+
+void
+gnac_ui_file_chooser_file_activated_cb(GtkFileChooser *chooser,
+                                       gpointer        user_data)
+{
+  gnac_ui_file_chooser_response_cb(GTK_DIALOG(chooser),
+      GTK_RESPONSE_NONE, NULL);
+}
+
+
+gboolean
+gnac_ui_file_chooser_key_press_event_cb(GtkWidget   *widget,
+                                        GdkEventKey *event,
+                                        gpointer     user_data)
+{
+  if (event->type == GDK_KEY_PRESS && event->keyval == GDK_Return) {
+    gnac_ui_file_chooser_response_cb(GTK_DIALOG(widget),
+        GTK_RESPONSE_NONE, NULL);
+    return TRUE;
+  }
+  return FALSE;
+}
+
+
 void
 gnac_ui_new(void)
 {
@@ -117,6 +516,8 @@ gnac_ui_new(void)
   gtk_about_dialog_set_url_hook(gnac_about_url_hook, NULL, NULL);
   gtk_about_dialog_set_email_hook(gnac_about_email_hook, NULL, NULL);
 
+  current_directory = g_strdup(g_get_home_dir());
+
   file_list = gnac_file_list_new();
 
   audio_profile_hbox = GTK_WIDGET(gtk_builder_get_object(gnac_main_builder, "audio_profile_hbox"));
@@ -356,6 +757,11 @@ gnac_ui_destroy(void)
     }
   }
 
+  if (current_directory) {
+    g_free(current_directory);
+    current_directory = NULL;
+  }
+
   gnac_file_list_destroy();
   
   if (gnac_main_builder) {
@@ -363,6 +769,7 @@ gnac_ui_destroy(void)
     if (main_window) gtk_widget_destroy(main_window);
     about_dialog = gnac_ui_get_widget("aboutdialog");
     if (about_dialog) gtk_widget_destroy(about_dialog);
+    if (gnac_file_chooser) gnac_ui_file_chooser_dispose();
     g_object_unref(gnac_main_builder); 
     gnac_main_builder = NULL;
   }
diff --git a/src/gnac-ui.h b/src/gnac-ui.h
index fa0831a..4a05701 100644
--- a/src/gnac-ui.h
+++ b/src/gnac-ui.h
@@ -67,6 +67,36 @@ void
 gnac_ui_show_about_dialog(void);
 
 void
+gnac_ui_reset_file_filter(void);
+
+GtkWidget *
+gnac_ui_get_file_chooser(void);
+
+GtkFileFilter *
+gnac_ui_get_current_filter(void);
+
+GtkFileFilter *
+gnac_ui_get_default_filter(void);
+
+void
+gnac_ui_on_filter_changed(GtkComboBox *combo,
+                          gpointer     user_data);
+
+void
+gnac_ui_file_chooser_response_cb(GtkDialog *dialog,
+                                 gint       response,
+                                 gpointer   user_data);
+
+void
+gnac_ui_file_chooser_file_activated_cb(GtkFileChooser *chooser,
+                                       gpointer        user_data);
+
+gboolean
+gnac_ui_file_chooser_key_press_event_cb(GtkWidget   *widget,
+                                        GdkEventKey *event,
+                                        gpointer     user_data);
+
+void
 gnac_ui_new(void);
 
 GtkWidget *



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]