totem r5841 - in trunk: . src
- From: hadess svn gnome org
- To: svn-commits-list gnome org
- Subject: totem r5841 - in trunk: . src
- Date: Wed, 10 Dec 2008 17:23:36 +0000 (UTC)
Author: hadess
Date: Wed Dec 10 17:23:36 2008
New Revision: 5841
URL: http://svn.gnome.org/viewvc/totem?rev=5841&view=rev
Log:
2008-12-10 Bastien Nocera <hadess hadess net>
* src/Makefile.am:
* src/eggfileformatchooser.[ch]: Add the EggFileFormatChooser
from bug 440431
* src/totem-playlist.c (totem_playlist_save_playlist),
(suffix_match_replace), (format_selection_changed),
(totem_playlist_save_add_format_chooser),
(totem_playlist_save_files): Use a better file format chooser,
- if the extension isn't known, use "PLS"
- when changing the file type, change the prefix of the saved file
(Closes: #379608)
Added:
trunk/src/eggfileformatchooser.c
trunk/src/eggfileformatchooser.h
Modified:
trunk/ChangeLog
trunk/src/Makefile.am
trunk/src/totem-playlist.c
Modified: trunk/src/Makefile.am
==============================================================================
--- trunk/src/Makefile.am (original)
+++ trunk/src/Makefile.am Wed Dec 10 17:23:36 2008
@@ -101,8 +101,9 @@
totem-private.h \
totem-preferences.c totem-preferences.h \
totem-dnd-menu.c totem-dnd-menu.h \
- totem-options.c totem-options.h \
- totem-playlist.c totem-playlist.h \
+ totem-options.c totem-options.h \
+ totem-playlist.c totem-playlist.h \
+ eggfileformatchooser.c eggfileformatchooser.h \
totem-screenshot.c \
totem-screenshot.h \
totem-session.c totem-session.h \
Added: trunk/src/eggfileformatchooser.c
==============================================================================
--- (empty file)
+++ trunk/src/eggfileformatchooser.c Wed Dec 10 17:23:36 2008
@@ -0,0 +1,664 @@
+#include "eggfileformatchooser.h"
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <string.h>
+#include <ctype.h>
+
+typedef struct _EggFileFormatSearch EggFileFormatSearch;
+
+enum
+{
+ MODEL_COLUMN_ID,
+ MODEL_COLUMN_NAME,
+ MODEL_COLUMN_ICON,
+ MODEL_COLUMN_EXTENSIONS,
+ MODEL_COLUMN_DATA,
+ MODEL_COLUMN_DESTROY
+};
+
+enum
+{
+ SIGNAL_SELECTION_CHANGED,
+ SIGNAL_LAST
+};
+
+struct _EggFileFormatChooserPrivate
+{
+ GtkTreeStore *model;
+ GtkTreeSelection *selection;
+ guint idle_hack;
+ guint last_id;
+};
+
+struct _EggFileFormatSearch
+{
+ gboolean success;
+ GtkTreeIter iter;
+
+ guint format;
+ const gchar *extension;
+};
+
+static guint signals[SIGNAL_LAST];
+
+G_DEFINE_TYPE (EggFileFormatChooser,
+ egg_file_format_chooser,
+ GTK_TYPE_EXPANDER);
+
+static void
+selection_changed (GtkTreeSelection *selection,
+ EggFileFormatChooser *self)
+{
+ gchar *label;
+ gchar *name;
+
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+
+ if (gtk_tree_selection_get_selected (selection, &model, &iter))
+ {
+ gtk_tree_model_get (model, &iter, MODEL_COLUMN_NAME, &name, -1);
+
+ label = g_strdup_printf (_("File Format: %s"), name);
+ gtk_expander_set_label (GTK_EXPANDER (self), label);
+
+ g_free (name);
+ g_free (label);
+
+ g_signal_emit (self, signals[SIGNAL_SELECTION_CHANGED], 0);
+ }
+}
+
+/* XXX This hack is needed, as gtk_expander_set_label seems
+ * not to work from egg_file_format_chooser_init */
+static gboolean
+select_default_file_format (gpointer data)
+{
+ EggFileFormatChooser *self = EGG_FILE_FORMAT_CHOOSER (data);
+ egg_file_format_chooser_set_format (self, 0);
+ self->priv->idle_hack = 0;
+ return FALSE;
+}
+
+static gboolean
+find_by_format (GtkTreeModel *model,
+ GtkTreePath *path G_GNUC_UNUSED,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ EggFileFormatSearch *search = data;
+ guint id;
+
+ gtk_tree_model_get (model, iter, MODEL_COLUMN_ID, &id, -1);
+
+ if (id == search->format)
+ {
+ search->success = TRUE;
+ search->iter = *iter;
+ }
+
+ return search->success;
+}
+
+static gboolean
+find_in_list (gchar *list,
+ const gchar *needle)
+{
+ gchar *saveptr;
+ gchar *token;
+
+ for(token = strtok_r (list, ",", &saveptr); NULL != token;
+ token = strtok_r (NULL, ",", &saveptr))
+ {
+ token = g_strstrip (token);
+
+ if (g_str_equal (needle, token))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+find_by_extension (GtkTreeModel *model,
+ GtkTreePath *path G_GNUC_UNUSED,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ EggFileFormatSearch *search = data;
+
+ gchar *extensions = NULL;
+ guint format = 0;
+
+ gtk_tree_model_get (model, iter,
+ MODEL_COLUMN_EXTENSIONS, &extensions,
+ MODEL_COLUMN_ID, &format,
+ -1);
+
+ if (extensions && find_in_list (extensions, search->extension))
+ {
+ search->format = format;
+ search->success = TRUE;
+ search->iter = *iter;
+ }
+
+ g_free (extensions);
+ return search->success;
+}
+
+static void
+egg_file_format_chooser_init (EggFileFormatChooser *self)
+{
+ GtkWidget *scroller;
+ GtkWidget *view;
+
+ GtkTreeViewColumn *column;
+ GtkCellRenderer *cell;
+ GtkTreeIter iter;
+
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, EGG_TYPE_FILE_FORMAT_CHOOSER,
+ EggFileFormatChooserPrivate);
+
+/* tree model */
+
+ self->priv->model = gtk_tree_store_new (6, G_TYPE_UINT, G_TYPE_STRING,
+ G_TYPE_STRING, G_TYPE_STRING,
+ G_TYPE_POINTER, G_TYPE_POINTER);
+
+ gtk_tree_store_append (self->priv->model, &iter, NULL);
+ gtk_tree_store_set (self->priv->model, &iter,
+ MODEL_COLUMN_NAME, _("By Extension"),
+ MODEL_COLUMN_ID, 0,
+ -1);
+
+/* tree view */
+
+ view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (self->priv->model));
+ self->priv->selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (view));
+ gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (view), TRUE);
+
+/* file format column */
+
+ column = gtk_tree_view_column_new ();
+ gtk_tree_view_column_set_expand (column, TRUE);
+ gtk_tree_view_column_set_title (column, _("File Format"));
+ gtk_tree_view_append_column (GTK_TREE_VIEW (view), column);
+
+ cell = gtk_cell_renderer_pixbuf_new ();
+ gtk_tree_view_column_pack_start (column, cell, FALSE);
+ gtk_tree_view_column_set_attributes (column, cell,
+ "icon-name", MODEL_COLUMN_ICON,
+ NULL);
+
+ cell = gtk_cell_renderer_text_new ();
+ gtk_tree_view_column_pack_start (column, cell, TRUE);
+ gtk_tree_view_column_set_attributes (column, cell,
+ "text", MODEL_COLUMN_NAME,
+ NULL);
+
+/* extensions column */
+
+ column = gtk_tree_view_column_new_with_attributes (
+ _("Extension(s)"), gtk_cell_renderer_text_new (),
+ "text", MODEL_COLUMN_EXTENSIONS, NULL);
+ gtk_tree_view_column_set_expand (column, FALSE);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (view), column);
+
+/* selection */
+
+ gtk_tree_selection_set_mode (self->priv->selection, GTK_SELECTION_BROWSE);
+ g_signal_connect (self->priv->selection, "changed", G_CALLBACK (selection_changed), self);
+ self->priv->idle_hack = g_idle_add (select_default_file_format, self);
+
+/* scroller */
+
+ scroller = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroller),
+ GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroller),
+ GTK_SHADOW_IN);
+ gtk_widget_set_size_request (scroller, -1, 150);
+ gtk_container_add (GTK_CONTAINER (scroller), view);
+ gtk_widget_show_all (scroller);
+
+ gtk_container_add (GTK_CONTAINER (self), scroller);
+}
+
+static void
+reset_model (EggFileFormatChooser *self)
+{
+ GtkTreeModel *model = GTK_TREE_MODEL (self->priv->model);
+ GtkTreeIter iter;
+
+ if (gtk_tree_model_get_iter_first (model, &iter))
+ {
+ do
+ {
+ GDestroyNotify destroy = NULL;
+ gpointer data = NULL;
+
+ gtk_tree_model_get (model, &iter,
+ MODEL_COLUMN_DESTROY, &destroy,
+ MODEL_COLUMN_DATA, &data,
+ -1);
+
+ if (destroy)
+ destroy (data);
+ }
+ while (gtk_tree_model_iter_next (model, &iter));
+ }
+
+ gtk_tree_store_clear (self->priv->model);
+}
+
+static void
+egg_file_format_chooser_dispose (GObject *obj)
+{
+ EggFileFormatChooser *self = EGG_FILE_FORMAT_CHOOSER (obj);
+
+ if (NULL != self)
+ {
+ if (self->priv->idle_hack)
+ {
+ g_source_remove (self->priv->idle_hack);
+ self->priv->idle_hack = 0;
+ }
+ }
+
+ G_OBJECT_CLASS (egg_file_format_chooser_parent_class)->dispose (obj);
+}
+
+static void
+egg_file_format_chooser_finalize (GObject *obj)
+{
+ EggFileFormatChooser *self = EGG_FILE_FORMAT_CHOOSER (obj);
+
+ if (NULL != self)
+ {
+ if (self->priv->model)
+ {
+ reset_model (self);
+ g_object_unref (self->priv->model);
+ self->priv->model = NULL;
+ }
+ }
+
+ G_OBJECT_CLASS (egg_file_format_chooser_parent_class)->finalize (obj);
+}
+
+static void
+egg_file_format_chooser_class_init (EggFileFormatChooserClass *cls)
+{
+ g_type_class_add_private (cls, sizeof (EggFileFormatChooserPrivate));
+
+ G_OBJECT_CLASS (cls)->dispose = egg_file_format_chooser_dispose;
+ G_OBJECT_CLASS (cls)->finalize = egg_file_format_chooser_finalize;
+
+ signals[SIGNAL_SELECTION_CHANGED] = g_signal_new (
+ "selection-changed", EGG_TYPE_FILE_FORMAT_CHOOSER, G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (EggFileFormatChooserClass, selection_changed),
+ NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+}
+
+GtkWidget*
+egg_file_format_chooser_new (void)
+{
+ return g_object_new (EGG_TYPE_FILE_FORMAT_CHOOSER, NULL);
+}
+
+static guint
+egg_file_format_chooser_add_format_impl (EggFileFormatChooser *self,
+ guint parent,
+ const gchar *name,
+ const gchar *icon,
+ const gchar *extensions)
+{
+ EggFileFormatSearch search;
+ GtkTreeIter iter;
+
+ search.success = FALSE;
+ search.format = parent;
+
+ if (parent > 0)
+ gtk_tree_model_foreach (GTK_TREE_MODEL (self->priv->model),
+ find_by_format, &search);
+
+ gtk_tree_store_append (self->priv->model, &iter,
+ search.success ? &search.iter : NULL);
+
+ gtk_tree_store_set (self->priv->model, &iter,
+ MODEL_COLUMN_ID, ++self->priv->last_id,
+ MODEL_COLUMN_EXTENSIONS, extensions,
+ MODEL_COLUMN_NAME, name,
+ MODEL_COLUMN_ICON, icon,
+ -1);
+
+ return self->priv->last_id;
+}
+
+guint
+egg_file_format_chooser_add_format (EggFileFormatChooser *self,
+ guint parent,
+ const gchar *name,
+ const gchar *icon,
+ ...)
+{
+ GString *buffer = NULL;
+ const gchar* extptr;
+ va_list extensions;
+ guint id;
+
+ g_return_val_if_fail (EGG_IS_FILE_FORMAT_CHOOSER (self), 0);
+ g_return_val_if_fail (NULL != name, 0);
+
+ va_start (extensions, icon);
+
+ while (NULL != (extptr = va_arg (extensions, const gchar*)))
+ {
+ if (NULL == buffer)
+ buffer = g_string_new (NULL);
+ else
+ g_string_append (buffer, ", ");
+
+ g_string_append (buffer, extptr);
+ }
+
+ va_end (extensions);
+
+ id = egg_file_format_chooser_add_format_impl (self, parent, name, icon,
+ buffer ? buffer->str : NULL);
+
+ if (buffer)
+ g_string_free (buffer, TRUE);
+
+ return id;
+}
+
+static gchar*
+get_icon_name (const gchar *mime_type)
+{
+ gchar *name = NULL;
+ gchar *s;
+
+ if (mime_type)
+ {
+ name = g_strconcat ("gnome-mime-", mime_type, NULL);
+
+ for(s = name; *s; ++s)
+ {
+ if (!isalpha (*s) || !isascii (*s))
+ *s = '-';
+ }
+ }
+
+ if (!name ||
+ !gtk_icon_theme_has_icon (gtk_icon_theme_get_default (), name))
+ {
+ g_free (name);
+ name = g_strdup ("gnome-mime-image");
+ }
+
+ return name;
+}
+
+void
+egg_file_format_chooser_add_pixbuf_formats (EggFileFormatChooser *self,
+ guint parent G_GNUC_UNUSED,
+ guint **formats)
+{
+ GSList *pixbuf_formats = NULL;
+ GSList *iter;
+ gint i;
+
+ g_return_if_fail (EGG_IS_FILE_FORMAT_CHOOSER (self));
+
+ pixbuf_formats = gdk_pixbuf_get_formats ();
+
+ if (formats)
+ *formats = g_new0 (guint, g_slist_length (pixbuf_formats) + 1);
+
+ for(iter = pixbuf_formats, i = 0; iter; iter = iter->next, ++i)
+ {
+ GdkPixbufFormat *format = iter->data;
+
+ gchar *description, *name, *extensions, *icon;
+ gchar **mime_types, **extension_list;
+ guint id;
+
+ if (gdk_pixbuf_format_is_disabled (format) ||
+ !gdk_pixbuf_format_is_writable (format))
+ continue;
+
+ mime_types = gdk_pixbuf_format_get_mime_types (format);
+ icon = get_icon_name (mime_types[0]);
+ g_strfreev (mime_types);
+
+ extension_list = gdk_pixbuf_format_get_extensions (format);
+ extensions = g_strjoinv (", ", extension_list);
+ g_strfreev (extension_list);
+
+ description = gdk_pixbuf_format_get_description (format);
+ name = gdk_pixbuf_format_get_name (format);
+
+ id = egg_file_format_chooser_add_format_impl (self, parent, description,
+ icon, extensions);
+
+ g_free (description);
+ g_free (extensions);
+ g_free (icon);
+
+ egg_file_format_chooser_set_format_data (self, id, name, g_free);
+
+ if (formats)
+ *formats[i] = id;
+ }
+
+ g_slist_free (pixbuf_formats);
+}
+
+void
+egg_file_format_chooser_remove_format (EggFileFormatChooser *self,
+ guint format)
+{
+ GDestroyNotify destroy = NULL;
+ gpointer data = NULL;
+
+ EggFileFormatSearch search;
+ GtkTreeModel *model;
+
+ g_return_if_fail (EGG_IS_FILE_FORMAT_CHOOSER (self));
+
+ search.success = FALSE;
+ search.format = format;
+
+ model = GTK_TREE_MODEL (self->priv->model);
+ gtk_tree_model_foreach (model, find_by_format, &search);
+
+ g_return_if_fail (search.success);
+
+ gtk_tree_model_get (model, &search.iter,
+ MODEL_COLUMN_DESTROY, &destroy,
+ MODEL_COLUMN_DATA, &data,
+ -1);
+
+ if (destroy)
+ destroy (data);
+
+ gtk_tree_store_remove (self->priv->model, &search.iter);
+}
+
+void
+egg_file_format_chooser_set_format (EggFileFormatChooser *self,
+ guint format)
+{
+ EggFileFormatSearch search;
+
+ GtkTreeModel *model;
+ GtkTreePath *path;
+ GtkTreeView *view;
+
+ g_return_if_fail (EGG_IS_FILE_FORMAT_CHOOSER (self));
+
+ search.success = FALSE;
+ search.format = format;
+
+ model = GTK_TREE_MODEL (self->priv->model);
+ gtk_tree_model_foreach (model, find_by_format, &search);
+
+ g_return_if_fail (search.success);
+
+ path = gtk_tree_model_get_path (model, &search.iter);
+ view = gtk_tree_selection_get_tree_view (self->priv->selection);
+
+ gtk_tree_view_expand_to_path (view, path);
+ gtk_tree_selection_unselect_all (self->priv->selection);
+ gtk_tree_selection_select_path (self->priv->selection, path);
+
+ gtk_tree_path_free (path);
+
+ if (self->priv->idle_hack > 0)
+ {
+ g_source_remove (self->priv->idle_hack);
+ self->priv->idle_hack = 0;
+ }
+}
+
+guint
+egg_file_format_chooser_get_format (EggFileFormatChooser *self,
+ const gchar *filename)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ guint format = 0;
+
+ g_return_val_if_fail (EGG_IS_FILE_FORMAT_CHOOSER (self), -1);
+
+ if (gtk_tree_selection_get_selected (self->priv->selection, &model, &iter))
+ gtk_tree_model_get (model, &iter, MODEL_COLUMN_ID, &format, -1);
+
+ if (0 == format && NULL != filename)
+ {
+ EggFileFormatSearch search;
+
+ search.extension = strrchr(filename, '.');
+ search.success = FALSE;
+
+ if (search.extension++)
+ gtk_tree_model_foreach (model, find_by_extension, &search);
+ if (search.success)
+ format = search.format;
+ }
+
+ return format;
+}
+
+void
+egg_file_format_chooser_set_format_data (EggFileFormatChooser *self,
+ guint format,
+ gpointer data,
+ GDestroyNotify destroy)
+{
+ EggFileFormatSearch search;
+
+ g_return_if_fail (EGG_IS_FILE_FORMAT_CHOOSER (self));
+
+ search.success = FALSE;
+ search.format = format;
+
+ gtk_tree_model_foreach (GTK_TREE_MODEL (self->priv->model),
+ find_by_format, &search);
+
+ g_return_if_fail (search.success);
+
+ gtk_tree_store_set (self->priv->model, &search.iter,
+ MODEL_COLUMN_DESTROY, destroy,
+ MODEL_COLUMN_DATA, data,
+ -1);
+}
+
+gpointer
+egg_file_format_chooser_get_format_data (EggFileFormatChooser *self,
+ guint format)
+{
+ EggFileFormatSearch search;
+ gpointer data = NULL;
+ GtkTreeModel *model;
+
+ g_return_val_if_fail (EGG_IS_FILE_FORMAT_CHOOSER (self), NULL);
+
+ search.success = FALSE;
+ search.format = format;
+
+ model = GTK_TREE_MODEL (self->priv->model);
+ gtk_tree_model_foreach (model, find_by_format, &search);
+
+ g_return_val_if_fail (search.success, NULL);
+
+ gtk_tree_model_get (model, &search.iter,
+ MODEL_COLUMN_DATA, &data,
+ -1);
+ return data;
+}
+
+gchar*
+egg_file_format_chooser_append_extension (EggFileFormatChooser *self,
+ const gchar *filename,
+ guint format)
+{
+ EggFileFormatSearch search;
+ GtkTreeModel *model;
+ GtkTreeIter child;
+
+ gchar *extensions;
+ gchar *tmpstr;
+
+ g_return_val_if_fail (EGG_IS_FILE_FORMAT_CHOOSER (self), NULL);
+ g_return_val_if_fail (NULL != filename, NULL);
+
+ if (0 == format)
+ format = egg_file_format_chooser_get_format (self, filename);
+
+ if (0 == format)
+ {
+ g_warning ("%s: No file format selected. Cannot append extension.", __FUNCTION__);
+ return NULL;
+ }
+
+ search.success = FALSE;
+ search.format = format;
+
+ model = GTK_TREE_MODEL (self->priv->model);
+ gtk_tree_model_foreach (model, find_by_format, &search);
+
+ g_return_val_if_fail (search.success, NULL);
+
+ gtk_tree_model_get (model, &search.iter,
+ MODEL_COLUMN_EXTENSIONS, &extensions,
+ -1);
+
+ if (NULL == extensions &&
+ gtk_tree_model_iter_nth_child (model, &child, &search.iter, 0))
+ {
+ gtk_tree_model_get (model, &child,
+ MODEL_COLUMN_EXTENSIONS, &extensions,
+ -1);
+ }
+
+ if (NULL == extensions)
+ {
+ g_warning ("%s: File format %d doesn't provide file extensions. "
+ "Cannot append extension.", __FUNCTION__, format);
+ return NULL;
+ }
+
+ if (NULL != (tmpstr = strchr(extensions, ',')))
+ *tmpstr = '\0';
+
+ tmpstr = g_strconcat (filename, ".", extensions, NULL);
+ g_free (extensions);
+
+ return tmpstr;
+}
+
+/* vim: set sw=2 sta et: */
Added: trunk/src/eggfileformatchooser.h
==============================================================================
--- (empty file)
+++ trunk/src/eggfileformatchooser.h Wed Dec 10 17:23:36 2008
@@ -0,0 +1,66 @@
+#ifndef __EGG_FILE_FORMAT_CHOOSER_H__
+#define __EGG_FILE_FORMAT_CHOOSER_H__
+
+#include <gtk/gtkexpander.h>
+
+G_BEGIN_DECLS
+
+#define EGG_TYPE_FILE_FORMAT_CHOOSER (egg_file_format_chooser_get_type())
+#define EGG_FILE_FORMAT_CHOOSER(obj) (G_TYPE_CHECK_INSTANCE_CAST(obj, EGG_TYPE_FILE_FORMAT_CHOOSER, EggFileFormatChooser))
+#define EGG_FILE_FORMAT_CHOOSER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST(klass, EGG_TYPE_FILE_FORMAT_CHOOSER, EggFileFormatChooserClass))
+#define EGG_IS_FILE_FORMAT_CHOOSER(obj) (G_TYPE_CHECK_INSTANCE_TYPE(obj, EGG_TYPE_FILE_FORMAT_CHOOSER))
+#define EGG_IS_FILE_FORMAT_CHOOSER_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE(obj, EGG_TYPE_FILE_FORMAT_CHOOSER))
+#define EGG_FILE_FORMAT_CHOOSER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), EGG_TYPE_FILE_FORMAT_CHOOSER, EggFileFormatChooserClass))
+
+typedef struct _EggFileFormatChooser EggFileFormatChooser;
+typedef struct _EggFileFormatChooserClass EggFileFormatChooserClass;
+typedef struct _EggFileFormatChooserPrivate EggFileFormatChooserPrivate;
+
+struct _EggFileFormatChooser
+{
+ GtkExpander parent;
+ EggFileFormatChooserPrivate *priv;
+};
+
+struct _EggFileFormatChooserClass
+{
+ GtkExpanderClass parent;
+
+ void (*selection_changed)(EggFileFormatChooser *self);
+};
+
+GType egg_file_format_chooser_get_type (void) G_GNUC_CONST;
+GtkWidget* egg_file_format_chooser_new (void);
+
+guint egg_file_format_chooser_add_format (EggFileFormatChooser *self,
+ guint parent,
+ const gchar *name,
+ const gchar *icon,
+ ...) G_GNUC_NULL_TERMINATED;
+void egg_file_format_chooser_add_pixbuf_formats (EggFileFormatChooser *self,
+ guint parent,
+ guint **formats);
+void egg_file_format_chooser_remove_format (EggFileFormatChooser *self,
+ guint format);
+
+void egg_file_format_chooser_set_format (EggFileFormatChooser *self,
+ guint format);
+guint egg_file_format_chooser_get_format (EggFileFormatChooser *self,
+ const gchar *filename);
+
+void egg_file_format_chooser_set_format_data (EggFileFormatChooser *self,
+ guint format,
+ gpointer data,
+ GDestroyNotify destroy);
+gpointer egg_file_format_chooser_get_format_data (EggFileFormatChooser *self,
+ guint format);
+
+gchar* egg_file_format_chooser_append_extension (EggFileFormatChooser *self,
+ const gchar *filename,
+ guint format);
+
+G_END_DECLS
+
+#endif /* __EGG_FILE_FORMAT_CHOOSER_H__ */
+
+/* vim: set sw=2 sta et: */
Modified: trunk/src/totem-playlist.c
==============================================================================
--- trunk/src/totem-playlist.c (original)
+++ trunk/src/totem-playlist.c Wed Dec 10 17:23:36 2008
@@ -32,6 +32,7 @@
#include <gio/gio.h>
#include <string.h>
+#include "eggfileformatchooser.h"
#include "totem-dnd-menu.h"
#include "totem-uri.h"
#include "totem-interface.h"
@@ -43,8 +44,6 @@
static void ensure_shuffled (TotemPlaylist *playlist, gboolean shuffle);
static gboolean totem_playlist_add_one_mrl (TotemPlaylist *playlist, const char *mrl, const char *display_name);
-typedef gboolean (*PlaylistCallback) (TotemPlaylist *playlist, const char *mrl,
- gpointer data);
typedef gboolean (*ClearComparisonFunc) (TotemPlaylist *playlist, GtkTreeIter *iter, gconstpointer data);
static void totem_playlist_clear_with_compare (TotemPlaylist *playlist,
@@ -68,17 +67,6 @@
gpointer user_data;
} PlaylistForeachContext;
-typedef struct {
- char *mimetype;
- PlaylistCallback func;
-} PlaylistTypes;
-
-typedef struct {
- const char *name;
- const char *suffix;
- TotemPlParserType type;
-} PlaylistSaveType;
-
struct TotemPlaylistPrivate
{
GtkBuilder *xml;
@@ -95,6 +83,8 @@
/* These is the current paths for the file selectors */
char *path;
char *save_path;
+ guint save_format;
+ GtkWidget *file_chooser;
/* Shuffle mode */
int *shuffled;
@@ -149,11 +139,18 @@
NUM_COLS
};
+typedef struct {
+ const char *name;
+ const char *suffix;
+ TotemPlParserType type;
+} PlaylistSaveType;
+
static PlaylistSaveType save_types [] = {
- {".PLS", ".pls", TOTEM_PL_PARSER_PLS},
- {".M3U", ".m3u", TOTEM_PL_PARSER_M3U},
- {".M3U (DOS)", ".m3u", TOTEM_PL_PARSER_M3U_DOS},
- {".XSPF", ".xspf", TOTEM_PL_PARSER_XSPF}
+ { NULL, NULL, -1 }, /* By extension entry */
+ { N_("MP3 ShoutCast playlist"), "pls", TOTEM_PL_PARSER_PLS },
+ { N_("MP3 audio (streamed)"), "m3u", TOTEM_PL_PARSER_M3U },
+ { N_("MP3 audio (streamed, DOS format)"), "m3u", TOTEM_PL_PARSER_M3U_DOS },
+ { N_("XML Shareable Playlist"), "xspf", TOTEM_PL_PARSER_XSPF }
};
static int totem_playlist_table_signals[LAST_SIGNAL];
@@ -972,103 +969,144 @@
static void
totem_playlist_save_playlist (TotemPlaylist *playlist, char *filename, gint active_format)
{
- PlaylistSaveType *cur = NULL;
- guint i;
+ if (active_format == 0)
+ active_format = 1;
- if (active_format > 0)
- totem_playlist_save_current_playlist_ext (playlist, filename,
- save_types[active_format - 1].type);
- else {
- for (i = 0; i < G_N_ELEMENTS(save_types); i++) {
- if (g_str_has_suffix (filename, save_types[i].suffix)) {
- cur = &save_types[i];
- break;
+ totem_playlist_save_current_playlist_ext (playlist, filename,
+ save_types[active_format].type);
+}
+
+static char *
+suffix_match_replace (const char *fname, guint old_format, guint new_format)
+{
+ char *ext;
+
+ ext = g_strdup_printf (".%s", save_types[old_format].suffix);
+ if (g_str_has_suffix (fname, ext) != FALSE) {
+ char *no_suffix, *new_fname;
+
+ no_suffix = g_strndup (fname, strlen (fname) - strlen (ext));
+ new_fname = g_strconcat (no_suffix, ".", save_types[new_format].suffix, NULL);
+ g_free (no_suffix);
+ g_free (ext);
+
+ return new_fname;
+ }
+ g_free (ext);
+
+ return NULL;
+}
+
+static void
+format_selection_changed (EggFileFormatChooser *chooser, TotemPlaylist *playlist)
+{
+ guint format;
+
+ format = egg_file_format_chooser_get_format (chooser, NULL);
+
+ if (format != playlist->priv->save_format) {
+ char *fname, *new_fname;
+
+ new_fname = NULL;
+ fname = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (playlist->priv->file_chooser));
+
+ if (format == 0) {
+ /* The new format is "By extension" don't touch anything */
+ } else if (playlist->priv->save_format == 0) {
+ guint i;
+
+ for (i = 1; i < G_N_ELEMENTS (save_types); i++) {
+ new_fname = suffix_match_replace (fname, i, format);
+ if (new_fname != NULL)
+ break;
}
+ } else {
+ new_fname = suffix_match_replace (fname, playlist->priv->save_format, format);
}
- if (cur == NULL)
- totem_playlist_error (_("Could not save the playlist"), _("Unknown file extension."), playlist);
- else
- totem_playlist_save_current_playlist_ext (playlist, filename, cur->type);
+ if (new_fname != NULL) {
+ char *basename;
+
+ basename = g_path_get_basename (new_fname);
+ g_free (new_fname);
+ gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (playlist->priv->file_chooser), basename);
+ g_free (basename);
+ }
+ playlist->priv->save_format = format;
}
}
static GtkWidget *
-totem_playlist_save_add_format_combo_box (GtkFileChooser *fc)
+totem_playlist_save_add_format_chooser (GtkFileChooser *fc, TotemPlaylist *playlist)
{
- GtkWidget *hbox, *label, *combo_box;
+ GtkWidget *format_chooser;
guint i;
- hbox = gtk_hbox_new (FALSE, 4);
- label = gtk_label_new (_("Select playlist format:"));
- gtk_widget_show (label);
-
- combo_box = gtk_combo_box_new_text ();
- gtk_combo_box_append_text (GTK_COMBO_BOX (combo_box),
- _("By extension"));
- gtk_combo_box_set_active (GTK_COMBO_BOX (combo_box), 0);
- for (i = 0; i < G_N_ELEMENTS(save_types); i++) {
- gtk_combo_box_append_text (GTK_COMBO_BOX (combo_box),
- save_types[i].name);
- }
- gtk_widget_show (combo_box);
-
- gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
- gtk_box_pack_start (GTK_BOX (hbox), combo_box, TRUE, TRUE, 0);
- gtk_widget_show (hbox);
- gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER (fc), hbox);
-
- atk_object_add_relationship (gtk_widget_get_accessible (label),
- ATK_RELATION_LABEL_FOR,
- gtk_widget_get_accessible (combo_box));
- atk_object_add_relationship (gtk_widget_get_accessible (combo_box),
- ATK_RELATION_LABELLED_BY,
- gtk_widget_get_accessible (label));
+ format_chooser = egg_file_format_chooser_new ();
+
+ playlist->priv->save_format = 0;
+
+ for (i = 1; i < G_N_ELEMENTS (save_types) ; i++) {
+ egg_file_format_chooser_add_format (
+ EGG_FILE_FORMAT_CHOOSER (format_chooser), 0, _(save_types[i].name),
+ "gnome-mime-audio", save_types[i].suffix, NULL);
+ }
+
+ g_signal_connect (format_chooser, "selection-changed",
+ G_CALLBACK (format_selection_changed), playlist);
+
+ gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER (fc),
+ format_chooser);
- return combo_box;
+ return format_chooser;
}
void
totem_playlist_save_files (GtkWidget *widget, TotemPlaylist *playlist)
{
- GtkWidget *fs, *combo_box;
+ GtkWidget *fs, *format_chooser;
char *filename;
int response;
+ g_assert (playlist->priv->file_chooser == NULL);
+
fs = gtk_file_chooser_dialog_new (_("Save Playlist"),
- totem_playlist_get_toplevel (playlist),
- GTK_FILE_CHOOSER_ACTION_SAVE,
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
- NULL);
+ totem_playlist_get_toplevel (playlist),
+ GTK_FILE_CHOOSER_ACTION_SAVE,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
+ NULL);
gtk_dialog_set_default_response (GTK_DIALOG (fs), GTK_RESPONSE_ACCEPT);
gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (fs), FALSE);
gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (fs), TRUE);
+
/* translators: Playlist is the default saved playlist filename,
* without the suffix */
- filename = g_strconcat (_("Playlist"), save_types[0].suffix, NULL);
+ filename = g_strconcat (_("Playlist"), ".", save_types[1].suffix, NULL);
gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (fs), filename);
g_free (filename);
- combo_box = totem_playlist_save_add_format_combo_box (GTK_FILE_CHOOSER (fs));
+ format_chooser = totem_playlist_save_add_format_chooser (GTK_FILE_CHOOSER (fs), playlist);
- if (playlist->priv->save_path != NULL)
- {
+ if (playlist->priv->save_path != NULL) {
gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (fs),
playlist->priv->save_path);
}
+ playlist->priv->file_chooser = fs;
+
response = gtk_dialog_run (GTK_DIALOG (fs));
gtk_widget_hide (fs);
while (gtk_events_pending())
gtk_main_iteration();
- if (response == GTK_RESPONSE_ACCEPT)
- {
+ if (response == GTK_RESPONSE_ACCEPT) {
char *fname;
- gint active_format;
+ guint active_format;
fname = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (fs));
- active_format = gtk_combo_box_get_active (GTK_COMBO_BOX (combo_box));
+ active_format = egg_file_format_chooser_get_format (EGG_FILE_FORMAT_CHOOSER (format_chooser),
+ fname);
+ playlist->priv->file_chooser = NULL;
gtk_widget_destroy (fs);
if (fname == NULL)
@@ -1080,6 +1118,7 @@
totem_playlist_save_playlist (playlist, fname, active_format);
g_free (fname);
} else {
+ playlist->priv->file_chooser = NULL;
gtk_widget_destroy (fs);
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]