[Goodies-commits] r7582 - in parole/trunk: . data/interfaces src

Ali Abdallah aliov at xfce.org
Mon Jun 15 21:55:24 CEST 2009


Author: aliov
Date: 2009-06-15 19:55:24 +0000 (Mon, 15 Jun 2009)
New Revision: 7582

Modified:
   parole/trunk/ChangeLog
   parole/trunk/data/interfaces/playlist.ui
   parole/trunk/src/filters.c
   parole/trunk/src/filters.h
   parole/trunk/src/gst.c
   parole/trunk/src/mediachooser.c
   parole/trunk/src/medialist.c
   parole/trunk/src/player.c
   parole/trunk/src/utils.c
   parole/trunk/src/utils.h
Log:
	* Add support for drag and drop in the media list view, it can now
	handle dropping of a single file or list of files or a folder 
	contains media files/other subfolders with media files.

Modified: parole/trunk/ChangeLog
===================================================================
--- parole/trunk/ChangeLog	2009-06-15 15:53:44 UTC (rev 7581)
+++ parole/trunk/ChangeLog	2009-06-15 19:55:24 UTC (rev 7582)
@@ -1,3 +1,8 @@
+2008-06-15: 20:00 Ali aliov at xfce.org
+	* Add support for drag and drop in the media list view, it can now
+	handle dropping of a single file or list of files or a folder 
+	contains media files/other subfolders with media files.
+
 2009-06-15: Ali aliov at xfce.org
 	* Clear the play pixbuf when finishing playing a list.
 	* Added mime type functions to generate mime types supported

Modified: parole/trunk/data/interfaces/playlist.ui
===================================================================
--- parole/trunk/data/interfaces/playlist.ui	2009-06-15 15:53:44 UTC (rev 7581)
+++ parole/trunk/data/interfaces/playlist.ui	2009-06-15 19:55:24 UTC (rev 7582)
@@ -20,6 +20,7 @@
             <signal name="cursor_changed" handler="parole_media_list_cursor_changed_cb"/>
             <signal name="row_activated" handler="parole_media_list_row_activated_cb"/>
             <signal name="button_release_event" handler="parole_media_list_button_release_event"/>
+            <signal name="drag_data_received" handler="parole_media_list_drag_data_received_cb"/>
           </object>
         </child>
       </object>

Modified: parole/trunk/src/filters.c
===================================================================
--- parole/trunk/src/filters.c	2009-06-15 15:53:44 UTC (rev 7581)
+++ parole/trunk/src/filters.c	2009-06-15 19:55:24 UTC (rev 7582)
@@ -88,3 +88,61 @@
     
     return filter;
 }
+
+gboolean parole_file_filter (GtkFileFilter *filter, ParoleMediaFile *file)
+{
+    GtkFileFilterInfo filter_info;
+
+    gboolean ret;
+    
+    filter_info.display_name = parole_media_file_get_display_name (file);
+    filter_info.mime_type = parole_media_file_get_content_type (file);
+    
+    filter_info.contains = GTK_FILE_FILTER_DISPLAY_NAME | GTK_FILE_FILTER_MIME_TYPE;
+    
+    ret = gtk_file_filter_filter (filter, &filter_info);
+
+    return ret;
+}
+
+void parole_get_media_files (GtkFileFilter *filter, const gchar *path, GSList **list)
+{
+    GDir *dir;
+    const gchar *name;
+    ParoleMediaFile *file;
+    
+    if ( g_file_test (path, G_FILE_TEST_IS_REGULAR ) )
+    {
+	file = parole_media_file_new (path);
+	if ( parole_file_filter (filter, file) )
+	    *list = g_slist_append (*list, file);
+	else
+	    g_object_unref (file);
+    }
+    else if ( g_file_test (path, G_FILE_TEST_IS_DIR ) )
+    {
+	dir = g_dir_open (path, 0, NULL);
+    
+	if ( G_UNLIKELY (dir == NULL) )
+	    return;
+	
+	while ( (name = g_dir_read_name (dir)) )
+	{
+	    gchar *path_internal = g_strdup_printf ("%s/%s", path, name);
+	    if ( g_file_test (path, G_FILE_TEST_IS_DIR) )
+	    {
+		parole_get_media_files (filter, path_internal, list);
+	    }
+	    else if ( g_file_test (path, G_FILE_TEST_IS_REGULAR) )
+	    {
+		file = parole_media_file_new (path_internal);
+		if ( parole_file_filter (filter, file) )
+		    *list = g_slist_append (*list, file);
+		else
+		    g_object_unref (file);
+	    }
+	    g_free (path_internal);
+	}
+	g_dir_close (dir);
+    }
+}

Modified: parole/trunk/src/filters.h
===================================================================
--- parole/trunk/src/filters.h	2009-06-15 15:53:44 UTC (rev 7581)
+++ parole/trunk/src/filters.h	2009-06-15 19:55:24 UTC (rev 7582)
@@ -22,6 +22,7 @@
 #define __PAROLE_FILTERS_H
 
 #include <gtk/gtk.h>
+#include "mediafile.h"
 
 GtkFileFilter 		*parole_get_supported_audio_filter	(void);
 
@@ -29,5 +30,11 @@
 
 GtkFileFilter 		*parole_get_supported_media_filter	(void);
 
+gboolean		 parole_file_filter			(GtkFileFilter *filter,
+								 ParoleMediaFile *file);
 
+void			 parole_get_media_files			(GtkFileFilter *filter,
+								 const gchar *path,
+								 GSList **list);
+
 #endif /* PAROLE_FILTERS_H */

Modified: parole/trunk/src/gst.c
===================================================================
--- parole/trunk/src/gst.c	2009-06-15 15:53:44 UTC (rev 7581)
+++ parole/trunk/src/gst.c	2009-06-15 19:55:24 UTC (rev 7582)
@@ -935,6 +935,8 @@
     gboolean seekable;
     gboolean ret;
 
+    TRACE ("Seeking");
+
     g_object_get (G_OBJECT (gst->priv->stream),
 		  "absolute-duration", &absolute_duration,
 		  "duration", &duration,

Modified: parole/trunk/src/mediachooser.c
===================================================================
--- parole/trunk/src/mediachooser.c	2009-06-15 15:53:44 UTC (rev 7581)
+++ parole/trunk/src/mediachooser.c	2009-06-15 19:55:24 UTC (rev 7582)
@@ -88,176 +88,6 @@
     }
 }
 
-/*
- * compare_by_name_using_number
- * 
- * * Copyright (c) 2005-2007 Benedikt Meurer <benny at xfce.org>
- * 
- */
-static gint
-compare_by_name_using_number (const gchar *ap,
-                              const gchar *bp)
-{
-    guint anum;
-    guint bnum;
-
-    /* determine the numbers in ap and bp */
-    anum = strtoul (ap, NULL, 10);
-    bnum = strtoul (bp, NULL, 10);
-
-    /* compare the numbers */
-    if (anum < bnum)
-	return -1;
-    else if (anum > bnum)
-	return 1;
-
-    /* the numbers are equal, and so the higher first digit should
-    * be sorted first, i.e. 'file10' before 'file010', since we
-    * also sort 'file10' before 'file011'.
-    */
-    return (*bp - *ap);
-}
-
-/*
- * thunar_file_compare_by_name
- * 
- * * Copyright (c) 2005-2007 Benedikt Meurer <benny at xfce.org>
- * 
- */
-static gint
-thunar_file_compare_by_name (ParoleMediaFile *file_a,
-                             ParoleMediaFile *file_b,
-                             gboolean       case_sensitive)
-{
-    const gchar *ap;
-    const gchar *bp;
-    guint        ac;
-    guint        bc;
-
-
-    /* we compare only the display names (UTF-8!) */
-    ap = parole_media_file_get_display_name (file_a);
-    bp = parole_media_file_get_display_name (file_b);
-
-    /* check if we should ignore case */
-    if (G_LIKELY (case_sensitive))
-    {
-	/* try simple (fast) ASCII comparison first */
-	for (;; ++ap, ++bp)
-        {
-	    /* check if the characters differ or we have a non-ASCII char */
-	    ac = *((const guchar *) ap);
-	    bc = *((const guchar *) bp);
-	    if (ac != bc || ac == 0 || ac > 127)
-		break;
-	}
-
-	/* fallback to Unicode comparison */
-	if (G_UNLIKELY (ac > 127 || bc > 127))
-        {
-	    for (;; ap = g_utf8_next_char (ap), bp = g_utf8_next_char (bp))
-            {
-		/* check if characters differ or end of string */
-		ac = g_utf8_get_char (ap);
-		bc = g_utf8_get_char (bp);
-		if (ac != bc || ac == 0)
-		    break;
-	    }
-        }
-    }
-    else
-    {
-	/* try simple (fast) ASCII comparison first (case-insensitive!) */
-	for (;; ++ap, ++bp)
-        {
-	    /* check if the characters differ or we have a non-ASCII char */
-	    ac = *((const guchar *) ap);
-	    bc = *((const guchar *) bp);
-	    if (g_ascii_tolower (ac) != g_ascii_tolower (bc) || ac == 0 || ac > 127)
-		break;
-        }
-
-	/* fallback to Unicode comparison (case-insensitive!) */
-	if (G_UNLIKELY (ac > 127 || bc > 127))
-	{
-	    for (;; ap = g_utf8_next_char (ap), bp = g_utf8_next_char (bp))
-            {
-		/* check if characters differ or end of string */
-		ac = g_utf8_get_char (ap);
-		bc = g_utf8_get_char (bp);
-		if (g_unichar_tolower (ac) != g_unichar_tolower (bc) || ac == 0)
-		    break;
-            }
-        }
-    }
-
-    /* if both strings are equal, we're done */
-    if (G_UNLIKELY (ac == bc || (!case_sensitive && g_unichar_tolower (ac) == g_unichar_tolower (bc))))
-	return 0;
-
-    /* check if one of the characters that differ is a digit */
-    if (G_UNLIKELY (g_ascii_isdigit (ac) || g_ascii_isdigit (bc)))
-    {
-	/* if both strings differ in a digit, we use a smarter comparison
-	 * to get sorting 'file1', 'file5', 'file10' done the right way.
-	 */
-	if (g_ascii_isdigit (ac) && g_ascii_isdigit (bc))
-	    return compare_by_name_using_number (ap, bp);
-
-	/* a second case is '20 file' and '2file', where comparison by number
-	 * makes sense, if the previous char for both strings is a digit.
-	 */
-	if (ap > parole_media_file_get_display_name (file_a) && bp > parole_media_file_get_display_name (file_b)
-	    && g_ascii_isdigit (*(ap - 1)) && g_ascii_isdigit (*(bp - 1)))
-        {
-	    return compare_by_name_using_number (ap - 1, bp - 1);
-        }
-    }
-
-    /* otherwise, if they differ in a unicode char, use the
-     * appropriate collate function for the current locale (only
-     * if charset is UTF-8, else the required transformations
-     * would be too expensive)
-     */
-#ifdef HAVE_STRCOLL
-    if ((ac > 127 || bc > 127) && g_get_charset (NULL))
-    {
-	/* case-sensitive is easy, case-insensitive is expensive,
-         * but we use a simple optimization to make it fast.
-         */
-	if (G_LIKELY (case_sensitive))
-        {
-	    return strcoll (ap, bp);
-        }
-	else
-        {
-	    /* we use a trick here, so we don't need to allocate
-             * and transform the two strings completely first (8
-             * byte for each buffer, so all compilers should align
-             * them properly)
-             */
-	    gchar abuf[8];
-	    gchar bbuf[8];
-
-	    /* transform the unicode chars to strings and
-             * make sure the strings are nul-terminated.
-	     */
-	    abuf[g_unichar_to_utf8 (ac, abuf)] = '\0';
-	    bbuf[g_unichar_to_utf8 (bc, bbuf)] = '\0';
-
-	    /* compare the unicode chars (as strings) */
-	    return strcoll (abuf, bbuf);
-        }
-    }
-#endif
-
-    /* else, they differ in an ASCII character */
-    if (G_UNLIKELY (!case_sensitive))
-	return (g_unichar_tolower (ac) > g_unichar_tolower (bc)) ? 1 : -1;
-    else
-	return (ac > bc) ? 1 : -1;
-}
-
 static void
 parole_media_chooser_sort_and_emit (ParoleMediaChooser *chooser, GSList **list)
 {
@@ -266,75 +96,11 @@
     g_signal_emit (G_OBJECT (chooser), signals [MEDIA_FILES_OPENED], 0, *list);
 }
 
-static gboolean
-parole_media_chooser_filter_media (GtkFileFilter *filter, ParoleMediaFile *file)
-{
-    GtkFileFilterInfo filter_info;
-
-    gboolean ret;
-    
-    filter_info.display_name = parole_media_file_get_display_name (file);
-    filter_info.mime_type = parole_media_file_get_content_type (file);
-    
-    filter_info.contains = GTK_FILE_FILTER_DISPLAY_NAME | GTK_FILE_FILTER_MIME_TYPE;
-    
-    ret = gtk_file_filter_filter (filter, &filter_info);
-
-    return ret;
-}
-
 static void
-parole_media_chooser_get_media_files (ParoleMediaChooser *chooser, GtkFileFilter *filter, const gchar *filename)
-{
-    GDir *dir;
-    GSList *list = NULL;
-    const gchar *name;
-    ParoleMediaFile *file;
-    
-    if ( g_file_test (filename, G_FILE_TEST_IS_REGULAR ) )
-    {
-	file = parole_media_file_new (filename);
-	if ( parole_media_chooser_filter_media (filter, file) )
-	    list = g_slist_append (list, file);
-	else
-	    g_object_unref (file);
-    }
-    else if ( g_file_test (filename, G_FILE_TEST_IS_DIR ) )
-    {
-	dir = g_dir_open (filename, 0, NULL);
-    
-	if ( G_UNLIKELY (dir == NULL) )
-	    return;
-	
-	while ( (name = g_dir_read_name (dir)) )
-	{
-	    gchar *path = g_strdup_printf ("%s/%s", filename, name);
-	    if ( g_file_test (path, G_FILE_TEST_IS_DIR) )
-	    {
-		parole_media_chooser_get_media_files (chooser, filter, path);
-	    }
-	    else if ( g_file_test (path, G_FILE_TEST_IS_REGULAR) )
-	    {
-		file = parole_media_file_new (path);
-		if ( parole_media_chooser_filter_media (filter, file) )
-		    list = g_slist_append (list, file);
-		else
-		    g_object_unref (file);
-	    }
-	    g_free (path);
-	}
-	g_dir_close (dir);
-    }
-    
-    parole_media_chooser_sort_and_emit (chooser, &list);
-    
-    g_slist_free (list);
-}
-
-static void
 parole_media_chooser_add_many (ParoleMediaChooser *chooser, GtkWidget *file_chooser)
 {
     GSList *files;
+    GSList *media_files = NULL;
     GtkFileFilter *filter;
     gchar *file;
     guint    i;
@@ -347,10 +113,13 @@
 	return;
 	
     len = g_slist_length (files);
+    
     for ( i = 0; i < len; i++)
     {
 	file = g_slist_nth_data (files, i);
-	parole_media_chooser_get_media_files (chooser, filter, file);
+	parole_get_media_files (filter, file, &media_files);
+	parole_media_chooser_sort_and_emit (chooser, &media_files);
+	g_slist_free (media_files);
     }
     
     g_slist_foreach (files, (GFunc) g_free, NULL);

Modified: parole/trunk/src/medialist.c
===================================================================
--- parole/trunk/src/medialist.c	2009-06-15 15:53:44 UTC (rev 7581)
+++ parole/trunk/src/medialist.c	2009-06-15 19:55:24 UTC (rev 7582)
@@ -36,6 +36,8 @@
 #include "mediafile.h"
 #include "mediachooser.h"
 #include "builder.h"
+#include "filters.h"
+#include "utils.h"
 
 /*
  * Callbacks for GtkBuilder
@@ -54,7 +56,7 @@
 
 void		parole_media_list_row_activated_cb 	(GtkTreeView *view, 
 							 GtkTreePath *path,
-							 GtkTreeViewColumn *col, 
+							 GtkTreeViewColumn *col,
 							 ParoleMediaList *list);
 
 void		parole_media_list_cursor_changed_cb 	(GtkTreeView *view, 
@@ -63,6 +65,15 @@
 gboolean	parole_media_list_button_release_event  (GtkWidget *widget, 
 							 GdkEventButton *ev, 
 							 ParoleMediaList *list);
+							 
+void		parole_media_list_drag_data_received_cb (GtkWidget *widget,
+							 GdkDragContext *drag_context,
+							 gint x,
+							 gint y,
+							 GtkSelectionData *data,
+							 guint info,
+							 guint drag_time,
+							 ParoleMediaList *list);
 /*
  * End of GtkBuilder callbacks
  */
@@ -87,6 +98,12 @@
     LAST_SIGNAL
 };
 
+static GtkTargetEntry target_entry[] =
+{
+    { "STRING",        0, 0 },
+    { "text/uri-list", 0, 1 },
+};
+
 static guint signals [LAST_SIGNAL] = { 0 };
 
 G_DEFINE_TYPE (ParoleMediaList, parole_media_list, GTK_TYPE_VBOX)
@@ -175,6 +192,49 @@
     gtk_widget_show_all (GTK_WIDGET (chooser));
 }
 
+void	parole_media_list_drag_data_received_cb (GtkWidget *widget,
+						 GdkDragContext *drag_context,
+						 gint x,
+						 gint y,
+						 GtkSelectionData *data,
+						 guint info,
+						 guint drag_time,
+						 ParoleMediaList *list)
+{
+    GtkFileFilter *filter;
+    ParoleMediaFile *file;
+    gchar **uri_list;
+    gchar *path;
+    guint i;
+    guint len;
+    gboolean ret = FALSE;
+    
+    uri_list = g_uri_list_extract_uris ((const gchar *)data->data);
+    filter = parole_get_supported_media_filter ();
+    g_object_ref_sink (filter);
+    
+    for ( i = 0; uri_list[i] != NULL; i++)
+    {
+	GSList *file_list = NULL;
+	path = g_filename_from_uri (uri_list[i], NULL, NULL);
+	parole_get_media_files (filter, path, &file_list);
+	
+	file_list = g_slist_sort (file_list, (GCompareFunc) thunar_file_compare_by_name);
+	
+	for ( len = 0; len < g_slist_length (file_list); len++)
+	{
+	    file = g_slist_nth_data (file_list, len);
+	    parole_media_list_add (list, file, FALSE);
+	    ret = TRUE;
+	}
+	g_slist_free (file_list);
+    }
+    
+    g_object_unref (filter);
+    
+    gtk_drag_finish (drag_context, ret, FALSE, drag_time);
+}
+
 void
 parole_media_list_add_clicked_cb (GtkButton *button, ParoleMediaList *list)
 {
@@ -394,7 +454,7 @@
     GtkListStore *list_store;
     GtkTreeViewColumn *col;
     GtkCellRenderer *renderer;
-    
+
     list_store = gtk_list_store_new (COL_NUMBERS, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_OBJECT);
 
     gtk_tree_view_set_model (GTK_TREE_VIEW (list->priv->view), GTK_TREE_MODEL(list_store));
@@ -414,6 +474,9 @@
     
     gtk_tree_view_append_column (GTK_TREE_VIEW (list->priv->view), col);
     gtk_tree_view_column_set_title (col, _("Media list"));
+
+    gtk_drag_dest_set (list->priv->view, GTK_DEST_DEFAULT_ALL, target_entry, G_N_ELEMENTS (target_entry),
+                       GDK_ACTION_COPY | GDK_ACTION_MOVE);
     
     list->priv->store = list_store;
 }

Modified: parole/trunk/src/player.c
===================================================================
--- parole/trunk/src/player.c	2009-06-15 15:53:44 UTC (rev 7581)
+++ parole/trunk/src/player.c	2009-06-15 19:55:24 UTC (rev 7582)
@@ -231,7 +231,11 @@
 static void
 parole_player_media_progressed_cb (ParoleGst *gst, const ParoleStream *stream, gdouble value, ParolePlayer *player)
 {
-    if ( !player->priv->user_seeking && value > 0)
+#ifdef DEBUG
+    g_return_if_fail (value > 0);
+#endif
+    
+    if ( !player->priv->user_seeking && player->priv->state == PAROLE_MEDIA_STATE_PLAYING )
     {
 	parole_player_change_range_value (player, value);
     }
@@ -319,6 +323,8 @@
     
     player->priv->state = PAROLE_MEDIA_STATE_PAUSED;
     
+    TRACE ("Player paused");
+    
     if ( !player->priv->buffering )
 	parole_statusbar_set_text (player->priv->status, _("Paused"));
 	
@@ -399,6 +405,7 @@
 	}
 	else
 	{
+	    TRACE ("No remaining media in the list");
 	    gtk_tree_row_reference_free (player->priv->row);
 	    player->priv->row = NULL;
 	}

Modified: parole/trunk/src/utils.c
===================================================================
--- parole/trunk/src/utils.c	2009-06-15 15:53:44 UTC (rev 7581)
+++ parole/trunk/src/utils.c	2009-06-15 19:55:24 UTC (rev 7582)
@@ -74,3 +74,173 @@
 
     g_object_unref (empty_bitmap);
 }
+
+/*
+ * compare_by_name_using_number
+ * 
+ * * Copyright (c) 2005-2007 Benedikt Meurer <benny at xfce.org>
+ * 
+ */
+static gint
+compare_by_name_using_number (const gchar *ap,
+                              const gchar *bp)
+{
+    guint anum;
+    guint bnum;
+
+    /* determine the numbers in ap and bp */
+    anum = strtoul (ap, NULL, 10);
+    bnum = strtoul (bp, NULL, 10);
+
+    /* compare the numbers */
+    if (anum < bnum)
+	return -1;
+    else if (anum > bnum)
+	return 1;
+
+    /* the numbers are equal, and so the higher first digit should
+    * be sorted first, i.e. 'file10' before 'file010', since we
+    * also sort 'file10' before 'file011'.
+    */
+    return (*bp - *ap);
+}
+
+/*
+ * thunar_file_compare_by_name
+ * 
+ * * Copyright (c) 2005-2007 Benedikt Meurer <benny at xfce.org>
+ * 
+ */
+gint
+thunar_file_compare_by_name (ParoleMediaFile *file_a,
+                             ParoleMediaFile *file_b,
+                             gboolean         case_sensitive)
+{
+    const gchar *ap;
+    const gchar *bp;
+    guint        ac;
+    guint        bc;
+
+
+    /* we compare only the display names (UTF-8!) */
+    ap = parole_media_file_get_display_name (file_a);
+    bp = parole_media_file_get_display_name (file_b);
+
+    /* check if we should ignore case */
+    if (G_LIKELY (case_sensitive))
+    {
+	/* try simple (fast) ASCII comparison first */
+	for (;; ++ap, ++bp)
+        {
+	    /* check if the characters differ or we have a non-ASCII char */
+	    ac = *((const guchar *) ap);
+	    bc = *((const guchar *) bp);
+	    if (ac != bc || ac == 0 || ac > 127)
+		break;
+	}
+
+	/* fallback to Unicode comparison */
+	if (G_UNLIKELY (ac > 127 || bc > 127))
+        {
+	    for (;; ap = g_utf8_next_char (ap), bp = g_utf8_next_char (bp))
+            {
+		/* check if characters differ or end of string */
+		ac = g_utf8_get_char (ap);
+		bc = g_utf8_get_char (bp);
+		if (ac != bc || ac == 0)
+		    break;
+	    }
+        }
+    }
+    else
+    {
+	/* try simple (fast) ASCII comparison first (case-insensitive!) */
+	for (;; ++ap, ++bp)
+        {
+	    /* check if the characters differ or we have a non-ASCII char */
+	    ac = *((const guchar *) ap);
+	    bc = *((const guchar *) bp);
+	    if (g_ascii_tolower (ac) != g_ascii_tolower (bc) || ac == 0 || ac > 127)
+		break;
+        }
+
+	/* fallback to Unicode comparison (case-insensitive!) */
+	if (G_UNLIKELY (ac > 127 || bc > 127))
+	{
+	    for (;; ap = g_utf8_next_char (ap), bp = g_utf8_next_char (bp))
+            {
+		/* check if characters differ or end of string */
+		ac = g_utf8_get_char (ap);
+		bc = g_utf8_get_char (bp);
+		if (g_unichar_tolower (ac) != g_unichar_tolower (bc) || ac == 0)
+		    break;
+            }
+        }
+    }
+
+    /* if both strings are equal, we're done */
+    if (G_UNLIKELY (ac == bc || (!case_sensitive && g_unichar_tolower (ac) == g_unichar_tolower (bc))))
+	return 0;
+
+    /* check if one of the characters that differ is a digit */
+    if (G_UNLIKELY (g_ascii_isdigit (ac) || g_ascii_isdigit (bc)))
+    {
+	/* if both strings differ in a digit, we use a smarter comparison
+	 * to get sorting 'file1', 'file5', 'file10' done the right way.
+	 */
+	if (g_ascii_isdigit (ac) && g_ascii_isdigit (bc))
+	    return compare_by_name_using_number (ap, bp);
+
+	/* a second case is '20 file' and '2file', where comparison by number
+	 * makes sense, if the previous char for both strings is a digit.
+	 */
+	if (ap > parole_media_file_get_display_name (file_a) && bp > parole_media_file_get_display_name (file_b)
+	    && g_ascii_isdigit (*(ap - 1)) && g_ascii_isdigit (*(bp - 1)))
+        {
+	    return compare_by_name_using_number (ap - 1, bp - 1);
+        }
+    }
+
+    /* otherwise, if they differ in a unicode char, use the
+     * appropriate collate function for the current locale (only
+     * if charset is UTF-8, else the required transformations
+     * would be too expensive)
+     */
+#ifdef HAVE_STRCOLL
+    if ((ac > 127 || bc > 127) && g_get_charset (NULL))
+    {
+	/* case-sensitive is easy, case-insensitive is expensive,
+         * but we use a simple optimization to make it fast.
+         */
+	if (G_LIKELY (case_sensitive))
+        {
+	    return strcoll (ap, bp);
+        }
+	else
+        {
+	    /* we use a trick here, so we don't need to allocate
+             * and transform the two strings completely first (8
+             * byte for each buffer, so all compilers should align
+             * them properly)
+             */
+	    gchar abuf[8];
+	    gchar bbuf[8];
+
+	    /* transform the unicode chars to strings and
+             * make sure the strings are nul-terminated.
+	     */
+	    abuf[g_unichar_to_utf8 (ac, abuf)] = '\0';
+	    bbuf[g_unichar_to_utf8 (bc, bbuf)] = '\0';
+
+	    /* compare the unicode chars (as strings) */
+	    return strcoll (abuf, bbuf);
+        }
+    }
+#endif
+
+    /* else, they differ in an ASCII character */
+    if (G_UNLIKELY (!case_sensitive))
+	return (g_unichar_tolower (ac) > g_unichar_tolower (bc)) ? 1 : -1;
+    else
+	return (ac > bc) ? 1 : -1;
+}

Modified: parole/trunk/src/utils.h
===================================================================
--- parole/trunk/src/utils.h	2009-06-15 15:53:44 UTC (rev 7581)
+++ parole/trunk/src/utils.h	2009-06-15 19:55:24 UTC (rev 7582)
@@ -24,8 +24,13 @@
 #include <gtk/gtk.h>
 #include <gdk/gdk.h>
 
+#include "mediafile.h"
+
 void		parole_window_busy_cursor		(GdkWindow *window);
 
 void		parole_window_invisible_cursor		(GdkWindow *window);
 
+gint            thunar_file_compare_by_name 		(ParoleMediaFile *file_a,
+							 ParoleMediaFile *file_b,
+							 gboolean         case_sensitive);
 #endif /* __PAROLE_UTILS_ */




More information about the Goodies-commits mailing list