Revision: 2266
          http://gtkpod.svn.sourceforge.net/gtkpod/?rev=2266&view=rev
Author:   jcsjcs
Date:     2009-02-28 13:49:10 +0000 (Sat, 28 Feb 2009)

Log Message:
-----------
        * src/misc.h
          src/display.h
          src/sort_window.c
          src/display_sorttabs.c
          src/misc.c:
          Optimation in the sort code -- thanks to javier Kohen for
          the patches.

Modified Paths:
--------------
    gtkpod/trunk/ChangeLog
    gtkpod/trunk/src/display.h
    gtkpod/trunk/src/display_sorttabs.c
    gtkpod/trunk/src/misc.c
    gtkpod/trunk/src/misc.h
    gtkpod/trunk/src/sort_window.c

Modified: gtkpod/trunk/ChangeLog
===================================================================
--- gtkpod/trunk/ChangeLog      2009-02-28 13:19:48 UTC (rev 2265)
+++ gtkpod/trunk/ChangeLog      2009-02-28 13:49:10 UTC (rev 2266)
@@ -1,5 +1,15 @@
 2009-02-28 Jorg Schuler <jcsjcs at users.sourceforge.net>
 
+       * src/misc.h
+         src/display.h
+         src/sort_window.c
+         src/display_sorttabs.c
+         src/misc.c:
+         Optimation in the sort code -- thanks to javier Kohen for
+         the patches.
+
+2009-02-28 Jorg Schuler <jcsjcs at users.sourceforge.net>
+
        * src/display_coverart.c
          src/display_tracks.c
          src/display_sorttabs.c:

Modified: gtkpod/trunk/src/display.h
===================================================================
--- gtkpod/trunk/src/display.h  2009-02-28 13:19:48 UTC (rev 2265)
+++ gtkpod/trunk/src/display.h  2009-02-28 13:49:10 UTC (rev 2266)
@@ -90,6 +90,19 @@
 /* struct for each entry in sort tab */
 typedef struct {
   gchar *name;
+
+  /* The sort key can be compared with other sort keys using strcmp
+   * and it will give the expected result, according to the user
+   * settings. Must be regenerated if the user settings change.
+   */
+  gchar *name_sortkey;
+
+  /* The fuzzy sortkey can be used to compare discarding some
+   * prefixes, such as "the", "el", "la", etc. If NULL, you should use
+   * name_sortkey instead.
+   */
+  gchar *name_fuzzy_sortkey;
+
   gboolean master; /* set if this is the "All" entry */
   gboolean compilation; /* set if this is the "Compilation" entry */
   GList *members;  /* GList with member tracks (pointer to "Track") */
@@ -128,7 +141,7 @@
   TimeInfo ti_played;                /* TimeInfo "played" (sp)        */
   GtkTooltipsData *sp_tooltips_data; /* ptr to tooltips in special st */
   /* function used for string comparisons, set in on_st_switch_page   */
-  gint (*string_compare_func) (const gchar *str1, const gchar *str2);
+  gint (*entry_compare_func) (const TabEntry *a, const TabEntry *b);
 } SortTab;
 
 /* "Column numbers" in sort tab model */
@@ -333,7 +346,9 @@
 void st_adopt_order_in_playlist (void);
 TabEntry *st_get_selected_entry (gint inst);
 void st_update_paned_position ();
+void st_rebuild_sortkeys ();
 
+
 void cal_open_calendar (gint inst, T_item item);
 void sp_go (guint32 inst);
 void sp_conditions_changed (guint32 inst);

Modified: gtkpod/trunk/src/display_sorttabs.c
===================================================================
--- gtkpod/trunk/src/display_sorttabs.c 2009-02-28 13:19:48 UTC (rev 2265)
+++ gtkpod/trunk/src/display_sorttabs.c 2009-02-28 13:49:10 UTC (rev 2266)
@@ -263,7 +263,50 @@
   return FALSE;
 }
 
+static void
+st_build_sortkeys (TabEntry *entry)
+{
+    C_FREE (entry->name_sortkey);
+    C_FREE (entry->name_fuzzy_sortkey);
+    entry->name_sortkey = make_sortkey (entry->name);
+    if (entry->name != fuzzy_skip_prefix (entry->name))
+    {
+       entry->name_fuzzy_sortkey =
+           make_sortkey (fuzzy_skip_prefix (entry->name));
+    }
+}
 
+void
+st_rebuild_sortkeys ()
+{
+    gint inst;
+    for (inst = 0; inst < prefs_get_int("sort_tab_num"); inst++)
+    {
+        SortTab *st = sorttab[inst];
+       GList *entries;
+
+       for (entries = st->entries; entries; entries = g_list_next (entries))
+        {
+           TabEntry *entry = (TabEntry *)entries->data;
+           st_build_sortkeys (entry);
+       }
+    }
+}
+
+gint compare_entry (const TabEntry *a, const TabEntry *b)
+{
+    return strcmp (a->name_sortkey, b->name_sortkey);
+}
+
+gint compare_entry_fuzzy (const TabEntry *a, const TabEntry *b)
+{
+    const gchar *ka, *kb;
+    ka = a->name_fuzzy_sortkey ? a->name_fuzzy_sortkey : a->name_sortkey;
+    kb = b->name_fuzzy_sortkey ? b->name_fuzzy_sortkey : b->name_sortkey;
+    return strcmp (ka, kb);
+}
+
+
 /* set string compare function according to whether the ignore field
    is set or not */
 static void st_set_string_compare_func (guint inst, guint page_num)
@@ -273,9 +316,9 @@
     {
        buf = g_strdup_printf ("sort_ign_field_%d", ST_to_T (page_num));
        if (prefs_get_int (buf))
-           sorttab[inst]->string_compare_func = compare_string_fuzzy;
+           sorttab[inst]->entry_compare_func = compare_entry_fuzzy;
        else
-           sorttab[inst]->string_compare_func = compare_string;
+           sorttab[inst]->entry_compare_func = compare_entry;
        g_free (buf);
     }
 }
@@ -1087,7 +1130,9 @@
     }
     gtk_list_store_set (GTK_LIST_STORE (model), &iter,
                        ST_COLUMN_ENTRY, entry, -1);
-    st->entries = g_list_append (st->entries, entry);
+    /* Prepend entry to the list, but always add after the master. */
+    st->entries = g_list_insert (st->entries, entry, 1);
+
     if (!entry->master && !entry->compilation)
     {
        if (!st->entry_hash)
@@ -1145,6 +1190,8 @@
                g_hash_table_remove (st->entry_hash, entry->name);
        }
        g_free (entry->name);
+       g_free (entry->name_sortkey);
+       g_free (entry->name_fuzzy_sortkey);
        g_free (entry);
     }
 }
@@ -1573,6 +1620,7 @@
        { /* doesn't exist yet -- let's create it */
            master_entry = g_malloc0 (sizeof (TabEntry));
            master_entry->name = g_strdup (_("All"));
+           st_build_sortkeys (master_entry);
            master_entry->master = TRUE;
            master_entry->compilation = FALSE;
            st_add_entry (master_entry, inst);
@@ -1604,6 +1652,7 @@
            {
                entry->name = g_strdup (entryname);
            }
+           st_build_sortkeys (entry);
            entry->compilation = group_track;
            entry->master = FALSE;
            st_add_entry (entry, inst);
@@ -2230,18 +2279,18 @@
          if (hash_entry == entry)
              g_hash_table_remove (st->entry_hash, entry->name);
          /* replace entry name */
+         g_free (entry->name);
          if (sorttab[inst]->current_category == ST_CAT_YEAR)
          {   /* make sure the entry->name is identical to
                 atoi(new_text) */
-             g_free (entry->name);
              entry->name = g_strdup_printf ("%d", atoi (new_text));
              g_object_set (G_OBJECT (renderer), "text", entry->name, NULL);
          }
          else
          {
-             g_free (entry->name);
              entry->name = g_strdup (new_text);
          }
+         st_build_sortkeys (entry);
 
          /* re-insert into hash table if the same name doesn't
             already exist */
@@ -2408,7 +2457,7 @@
 
   st = sorttab[inst];
 
-  return st->string_compare_func (entry1->name, entry2->name);
+  return st->entry_compare_func (entry1, entry2);
 }
 
 /* Stop editing. If @cancel is TRUE, the edited value will be

Modified: gtkpod/trunk/src/misc.c
===================================================================
--- gtkpod/trunk/src/misc.c     2009-02-28 13:19:48 UTC (rev 2265)
+++ gtkpod/trunk/src/misc.c     2009-02-28 13:49:10 UTC (rev 2266)
@@ -336,10 +336,15 @@
  * depending on prefs settings */
 gint compare_string (const gchar *str1, const gchar *str2)
 {
-    if (prefs_get_int("case_sensitive"))
-       return strcmp (str1, str2);
-    else
-       return compare_string_case_insensitive (str1, str2);
+    gint result;
+    gchar *sortkey1 = make_sortkey (str1);
+    gchar *sortkey2 = make_sortkey (str2);
+
+    result = strcmp (sortkey1, sortkey2);
+
+    g_free (sortkey1);
+    g_free (sortkey2);
+    return result;
 }
 
 struct csfk
@@ -351,6 +356,30 @@
 static GList *csfk_list = NULL;
 
 
+/* Returns the sortkey for an entry name.
+ *
+ * The sort key can be compared with other sort keys using strcmp and
+ * it will give the expected result, according to the user
+ * settings. Must be regenerated if the user settings change.
+ *
+ * The caller is responsible of freeing the returned key with g_free.
+ */
+gchar *
+make_sortkey (const gchar *name)
+{
+    if (prefs_get_int("case_sensitive"))
+    {
+       return g_utf8_collate_key (name, -1);
+    }
+    else
+    {
+       gchar *casefolded = g_utf8_casefold (name, -1);
+       gchar *key = g_utf8_collate_key (casefolded, -1);
+       g_free (casefolded);
+       return key;
+    }
+}
+
 /* needs to be called everytime the sort_ign_strings in the prefs were
    changed */
 void compare_string_fuzzy_generate_keys (void)
@@ -387,87 +416,63 @@
        csfk->key = g_utf8_collate_key (tempStr, -1 );
        g_free (tempStr);
 
-       csfk_list = g_list_append (csfk_list, csfk);
+       csfk_list = g_list_prepend (csfk_list, csfk);
     }
     prefs_free_list(sort_ign_strings);
 }
 
-
-/* compare @str1 and @str2 case-sensitively or case-insensitively
- * depending on prefs settings, and ignoring certain initial articles 
- * ("the", "le"/"la", etc) */
-gint compare_string_fuzzy (const gchar *str1, const gchar *str2)
+/* Returns a pointer inside the name, possibly skiping a prefix from
+ * the list generated by compare_string_fuzzy_generate_keys.
+ */
+const gchar *
+fuzzy_skip_prefix (const gchar *name)
 {
-    gchar *tempStr;
-    gint   result;
-    
-    gchar *cleanStr1 = g_utf8_casefold (str1, -1);
-    gchar *cleanStr2 = g_utf8_casefold (str2, -1);
+    const gchar *result = name;
+    const GList *gl;
+    gchar *cleanStr;
 
-    const gchar *pstr1 = str1;
-    const gchar *pstr2 = str2;
-    gchar *pcleanStr1 = cleanStr1;
-    gchar *pcleanStr2 = cleanStr2;
-    
-    GList *gl;
-
     /* If the article collations keys have not been generated, 
      * do that first
      */
     if (!csfk_list)
        compare_string_fuzzy_generate_keys ();
 
-    if (!csfk_list)
-       return compare_string (str1, str2);
+    cleanStr = g_utf8_casefold (name, -1);
 
-    /* Check the beginnings of both strings for any of the 
-     * articles we should ignore
-     */
-    for (gl=csfk_list; gl; gl=gl->next)
+    for (gl=csfk_list; gl; gl=g_list_next(gl))
     {
        struct csfk *csfk = gl->data;
+       gchar *tempStr;
+
        g_return_val_if_fail (csfk, 0);
-       tempStr = g_utf8_collate_key (cleanStr1, csfk->length);
+
+       tempStr = g_utf8_collate_key (cleanStr, csfk->length);
        if (strcmp (tempStr, csfk->key) == 0)
        {
            /* Found article, bump pointers ahead appropriate distance
             */
-           pstr1 += csfk->length;
-           pcleanStr1 = g_utf8_offset_to_pointer (cleanStr1, csfk->length);
+           result += csfk->length;
            g_free (tempStr);
            break;
        }
        g_free (tempStr);
     }
-    for (gl=csfk_list; gl; gl=gl->next)
-    {
-       struct csfk *csfk = gl->data;
-       g_return_val_if_fail (csfk, 0);
-       tempStr = g_utf8_collate_key (cleanStr2, csfk->length);
-       if (strcmp (tempStr, csfk->key) == 0)
-       {
-           /* Found article, bump pointers ahead apropriate distance
-            */
-           pstr2 += csfk->length;
-           pcleanStr2 = g_utf8_offset_to_pointer (cleanStr2, csfk->length);
-           g_free (tempStr);
-           break;
-       }
-       g_free (tempStr);
-    }
 
-    if (prefs_get_int("case_sensitive"))
-       result = strcmp(pstr1, pstr2);
-    else
-       result = g_utf8_collate(pcleanStr1, pcleanStr2);
+    g_free (cleanStr);
 
-    g_free (cleanStr1);
-    g_free (cleanStr2);
     return result;
 }
 
 /* compare @str1 and @str2 case-sensitively or case-insensitively
- * depending on prefs settings */
+ * depending on prefs settings, and ignoring certain initial articles 
+ * ("the", "le"/"la", etc) */
+gint compare_string_fuzzy (const gchar *str1, const gchar *str2)
+{
+    return compare_string (fuzzy_skip_prefix (str1),
+                          fuzzy_skip_prefix (str2));
+}
+
+/* compare @str1 and @str2 case-insensitively */
 gint compare_string_case_insensitive (const gchar *str1, const gchar *str2)
 {
     gchar *string1 = g_utf8_casefold (str1, -1);

Modified: gtkpod/trunk/src/misc.h
===================================================================
--- gtkpod/trunk/src/misc.h     2009-02-28 13:19:48 UTC (rev 2265)
+++ gtkpod/trunk/src/misc.h     2009-02-28 13:49:10 UTC (rev 2266)
@@ -143,9 +143,11 @@
 
 gchar *get_filesize_as_string (double size);
 
+gchar *make_sortkey (const gchar *name);
 gint compare_string (const gchar *str1, const gchar *str2);
 void compare_string_fuzzy_generate_keys (void);
 gint compare_string_fuzzy (const gchar *str1, const gchar *str2);
+const gchar *fuzzy_skip_prefix (const gchar *sortkey);
 gint compare_string_case_insensitive (const gchar *str1,
                                      const gchar *str2);
 gint compare_string_start_case_insensitive (const gchar *haystack,

Modified: gtkpod/trunk/src/sort_window.c
===================================================================
--- gtkpod/trunk/src/sort_window.c      2009-02-28 13:19:48 UTC (rev 2265)
+++ gtkpod/trunk/src/sort_window.c      2009-02-28 13:49:10 UTC (rev 2266)
@@ -487,6 +487,12 @@
     /* update compare string keys */
     compare_string_fuzzy_generate_keys ();
 
+    /* if case sensitive has changed, rebuild sortkeys */
+    if (temp_prefs_get_int_value(sort_temp_prefs, "case_sensitive", &val))
+    {
+       st_rebuild_sortkeys ();
+       temp_prefs_remove_key (sort_temp_prefs, "case_sensitive");
+    }
     /* if sort type has changed, initialize display */
     if (temp_prefs_get_int_value(sort_temp_prefs, "pm_sort", &val))
     {


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

------------------------------------------------------------------------------
Open Source Business Conference (OSBC), March 24-25, 2009, San Francisco, CA
-OSBC tackles the biggest issue in open source: Open Sourcing the Enterprise
-Strategies to boost innovation and cut costs with open source participation
-Receive a $600 discount off the registration fee with the source code: SFAD
http://p.sf.net/sfu/XcvMzF8H
_______________________________________________
gtkpod-cvs2 mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/gtkpod-cvs2

Reply via email to