[rhythmbox] playlist: save settings in playlists.xml



commit 682fa7c3c687c911267cc631c08ee0a2e93c266f
Author: Jonathan Matthew <jonathan d14n org>
Date:   Sat Jul 13 22:57:36 2013 +1000

    playlist: save settings in playlists.xml
    
    This includes browser visibility (and size) and the selected search
    type.  Sorting for automatic playlists was already covered, and
    static playlists aren't sortable.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=703626
    https://bugzilla.gnome.org/show_bug.cgi?id=652892

 plugins/daap/rb-daap-source.c       |   16 ++---
 sources/rb-auto-playlist-source.c   |    7 ++-
 sources/rb-auto-playlist-source.h   |    1 +
 sources/rb-playlist-source.c        |  104 +++++++++++++++++++++++++++++++++--
 sources/rb-playlist-xml.h           |    3 +
 sources/rb-static-playlist-source.c |   20 ++-----
 sources/rb-static-playlist-source.h |    3 +-
 7 files changed, 122 insertions(+), 32 deletions(-)
---
diff --git a/plugins/daap/rb-daap-source.c b/plugins/daap/rb-daap-source.c
index 8ded5e8..b605185 100644
--- a/plugins/daap/rb-daap-source.c
+++ b/plugins/daap/rb-daap-source.c
@@ -612,6 +612,8 @@ rb_daap_source_connection_cb (DMAPConnection   *connection,
 {
        RBDAAPSource *daap_source = RB_DAAP_SOURCE (source);
        RBShell *shell = NULL;
+       GSettings *plugin_settings;
+       GSettings *settings;
        GSList *playlists;
        GSList *l;
        RhythmDBEntryType *entry_type;
@@ -635,21 +637,15 @@ rb_daap_source_connection_cb (DMAPConnection   *connection,
        g_object_get (daap_source,
                      "shell", &shell,
                      "entry-type", &entry_type,
+                     "settings", &plugin_settings,
                      NULL);
+       settings = g_settings_get_child (plugin_settings, "source");
        playlists = dmap_connection_get_playlists (DMAP_CONNECTION (daap_source->priv->connection));
        for (l = playlists; l != NULL; l = g_slist_next (l)) {
                DMAPPlaylist *playlist = l->data;
                RBSource *playlist_source;
-               char *settings_name;
-
-               /* Construct a unique settings name for this playlist, as <Share Name>_<Playlist> */
-               /* XXX disabled for now, not sure it's a good idea */
-               /*settings_name = g_strjoin (NULL, daap_source->priv->service_name, "_", playlist->name, 
NULL); */
 
-               settings_name = "/org/gnome/rhythmbox/plugins/daap/source";
-
-               playlist_source = rb_static_playlist_source_new (shell, playlist->name, settings_name, FALSE, 
entry_type);
-               /*g_free (settings_name);*/
+               playlist_source = rb_static_playlist_source_new (shell, playlist->name, settings, FALSE, 
entry_type);
 
                g_list_foreach (playlist->uris, (GFunc)_add_location_to_playlist, playlist_source);
 
@@ -657,6 +653,8 @@ rb_daap_source_connection_cb (DMAPConnection   *connection,
                daap_source->priv->playlist_sources = g_slist_prepend (daap_source->priv->playlist_sources, 
playlist_source);
        }
 
+       g_object_unref (settings);
+       g_object_unref (plugin_settings);
        g_object_unref (shell);
        g_object_unref (entry_type);
 }
diff --git a/sources/rb-auto-playlist-source.c b/sources/rb-auto-playlist-source.c
index 6dbb13a..e075cc4 100644
--- a/sources/rb-auto-playlist-source.c
+++ b/sources/rb-auto-playlist-source.c
@@ -226,6 +226,7 @@ rb_auto_playlist_source_constructed (GObject *object)
                                                entry_type);
        g_object_unref (entry_type);
        gtk_paned_pack1 (GTK_PANED (priv->paned), GTK_WIDGET (priv->browser), TRUE, FALSE);
+       gtk_widget_set_no_show_all (GTK_WIDGET (priv->browser), TRUE);
        g_signal_connect_object (G_OBJECT (priv->browser), "notify::output-model",
                                 G_CALLBACK (rb_auto_playlist_source_browser_changed_cb),
                                 source, 0);
@@ -319,6 +320,7 @@ rb_auto_playlist_source_new (RBShell *shell, const char *name, gboolean local)
                                          "is-local", local,
                                          "entry-type", RHYTHMDB_ENTRY_TYPE_SONG,
                                          "toolbar-menu", toolbar,
+                                         "settings", NULL,
                                          NULL));
        g_object_unref (builder);
        return source;
@@ -369,6 +371,7 @@ rb_auto_playlist_source_get_property (GObject *object,
 /**
  * rb_auto_playlist_source_new_from_xml:
  * @shell: the #RBShell instance
+ * @name: playlist name
  * @node: libxml node containing the playlist
  *
  * Creates a new auto playlist source by parsing an XML-encoded query.
@@ -376,9 +379,9 @@ rb_auto_playlist_source_get_property (GObject *object,
  * Return value: the new source
  */
 RBSource *
-rb_auto_playlist_source_new_from_xml (RBShell *shell, xmlNodePtr node)
+rb_auto_playlist_source_new_from_xml (RBShell *shell, const char *name, xmlNodePtr node)
 {
-       RBAutoPlaylistSource *source = RB_AUTO_PLAYLIST_SOURCE (rb_auto_playlist_source_new (shell, NULL, 
TRUE));
+       RBAutoPlaylistSource *source = RB_AUTO_PLAYLIST_SOURCE (rb_auto_playlist_source_new (shell, name, 
TRUE));
        xmlNodePtr child;
        xmlChar *tmp;
        GPtrArray *query;
diff --git a/sources/rb-auto-playlist-source.h b/sources/rb-auto-playlist-source.h
index aba0de8..65c9c22 100644
--- a/sources/rb-auto-playlist-source.h
+++ b/sources/rb-auto-playlist-source.h
@@ -64,6 +64,7 @@ RBSource *    rb_auto_playlist_source_new             (RBShell *shell,
                                                         gboolean local);
 
 RBSource *     rb_auto_playlist_source_new_from_xml    (RBShell *shell,
+                                                        const char *name,
                                                         xmlNodePtr node);
 
 void           rb_auto_playlist_source_set_query       (RBAutoPlaylistSource *source,
diff --git a/sources/rb-playlist-source.c b/sources/rb-playlist-source.c
index 7e39d21..c2c454a 100644
--- a/sources/rb-playlist-source.c
+++ b/sources/rb-playlist-source.c
@@ -37,6 +37,9 @@
 #include <gtk/gtk.h>
 #include <totem-pl-parser.h>
 
+#define G_SETTINGS_ENABLE_BACKEND
+#include <gio/gsettingsbackend.h>
+
 #include "rb-entry-view.h"
 #include "rb-search-entry.h"
 #include "rb-file-helpers.h"
@@ -151,6 +154,8 @@ enum
 
 static const GtkTargetEntry target_uri [] = { { "text/uri-list", 0, 0 } };
 
+static GSettingsBackend *playlist_settings_backend = NULL;
+
 G_DEFINE_ABSTRACT_TYPE (RBPlaylistSource, rb_playlist_source, RB_TYPE_SOURCE);
 
 static void
@@ -228,6 +233,10 @@ static void
 rb_playlist_source_init (RBPlaylistSource *source)
 {
        source->priv = RB_PLAYLIST_SOURCE_GET_PRIVATE (source);
+       
+       if (playlist_settings_backend == NULL) {
+               playlist_settings_backend = g_memory_settings_backend_new ();
+       }
 }
 
 static void
@@ -254,6 +263,12 @@ rb_playlist_source_set_db (RBPlaylistSource *source,
 }
 
 static void
+playlist_settings_changed_cb (GSettings *settings, char *key, RBPlaylistSource *source)
+{
+       rb_playlist_source_mark_dirty (source);
+}
+
+static void
 rb_playlist_source_constructed (GObject *object)
 {
        GObject *shell_player;
@@ -262,6 +277,7 @@ rb_playlist_source_constructed (GObject *object)
        RhythmDB *db;
        RhythmDBQueryModel *query_model;
        GtkBuilder *builder;
+       GSettings *settings;
 
        RB_CHAIN_GOBJECT_METHOD (rb_playlist_source_parent_class, constructed, object);
        source = RB_PLAYLIST_SOURCE (object);
@@ -276,6 +292,27 @@ rb_playlist_source_constructed (GObject *object)
 
        g_object_unref (shell);
 
+       /* store playlist settings using the memory backend
+        * this means the settings path doesn't have to be consistent,
+        * it just has to be unique, so the address of the source object works.
+        * for local playlists, we write the settings into the playlist file on disk
+        * to make them persistent.
+        */
+       g_object_get (source, "settings", &settings, NULL);
+       if (settings == NULL) {
+               char *path;
+               path = g_strdup_printf ("/org/gnome/rhythmbox/playlist/%p/", source);
+               settings = g_settings_new_with_backend_and_path ("org.gnome.rhythmbox.source",
+                                                                playlist_settings_backend,
+                                                                path);
+               g_free (path);
+
+               g_object_set (source, "settings", settings, NULL);
+       }
+
+       g_signal_connect (settings, "changed", G_CALLBACK (playlist_settings_changed_cb), source);
+       g_object_unref (settings);
+
        builder = rb_builder_load ("playlist-popup.ui", NULL);
        source->priv->popup = G_MENU (gtk_builder_get_object (builder, "playlist-popup"));
        rb_application_link_shared_menus (RB_APPLICATION (g_application_get_default ()), source->priv->popup);
@@ -753,6 +790,45 @@ get_playlist_name_from_xml (xmlNodePtr node)
        return name;
 }
 
+static void
+apply_source_settings (RBPlaylistSource *source, xmlNodePtr node)
+{
+       GSettings *settings;
+       xmlChar *value;
+
+       g_object_get (source, "settings", &settings, NULL);
+       if (settings == NULL)
+               return;
+
+       value = xmlGetProp (node, RB_PLAYLIST_SHOW_BROWSER);
+       if (value != NULL) {
+               g_settings_set_boolean (settings,
+                                       "show-browser",
+                                       (g_strcmp0 ((char *)value, "true") == 0));
+               xmlFree (value);
+       }
+       
+       value = xmlGetProp (node, RB_PLAYLIST_BROWSER_POSITION);
+       if (value != NULL) {
+               long position;
+               char *end;
+
+               position = strtol ((char *)value, &end, 10);
+               if (end != (char *)value) {
+                       g_settings_set_int (settings, "paned-position", position);
+               }
+               xmlFree (value);
+       }
+
+       value = xmlGetProp (node, RB_PLAYLIST_SEARCH_TYPE);
+       if (value != NULL) {
+               g_settings_set_string (settings, "search-type", (char *)value);
+               xmlFree (value);
+       }
+
+       g_object_unref (settings);
+}
+
 /**
  * rb_playlist_source_new_from_xml:
  * @shell: the #RBShell instance
@@ -782,26 +858,26 @@ rb_playlist_source_new_from_xml   (RBShell *shell,
        tmp = xmlGetProp (node, RB_PLAYLIST_TYPE);
 
        if (!xmlStrcmp (tmp, RB_PLAYLIST_AUTOMATIC))
-               source = rb_auto_playlist_source_new_from_xml (shell, node);
+               source = rb_auto_playlist_source_new_from_xml (shell, (const char *)name, node);
        else if (!xmlStrcmp (tmp, RB_PLAYLIST_STATIC))
-               source = rb_static_playlist_source_new_from_xml (shell, node);
+               source = rb_static_playlist_source_new_from_xml (shell, (const char *)name, node);
        else if (!xmlStrcmp (tmp, RB_PLAYLIST_QUEUE)) {
                RBStaticPlaylistSource *queue;
 
                g_object_get (shell, "queue-source", &queue, NULL);
                rb_static_playlist_source_load_from_xml (queue, node);
+               apply_source_settings (RB_PLAYLIST_SOURCE (queue), node);
                g_object_unref (queue);
        } else {
                g_warning ("attempting to load playlist '%s' of unknown type '%s'", name, tmp);
        }
 
-       if (source != NULL) {
-               g_object_set (G_OBJECT (source), "name", name, NULL);
-       }
-
        xmlFree (name);
        xmlFree (tmp);
 
+       if (source != NULL) {
+               apply_source_settings (RB_PLAYLIST_SOURCE (source), node);
+       }
        return source;
 }
 
@@ -819,6 +895,7 @@ rb_playlist_source_save_to_xml (RBPlaylistSource *source,
 {
        xmlNodePtr node;
        xmlChar *name;
+       GSettings *settings;
        RBPlaylistSourceClass *klass = RB_PLAYLIST_SOURCE_GET_CLASS (source);
 
        g_return_if_fail (RB_IS_PLAYLIST_SOURCE (source));
@@ -828,6 +905,21 @@ rb_playlist_source_save_to_xml (RBPlaylistSource *source,
        xmlSetProp (node, RB_PLAYLIST_NAME, name);
        g_free (name);
 
+       g_object_get (source, "settings", &settings, NULL);
+       if (settings) {
+               char buf[99];
+               xmlSetProp (node,
+                           RB_PLAYLIST_SHOW_BROWSER,
+                           (xmlChar *)(g_settings_get_boolean (settings, "show-browser") ? "true" : 
"false"));
+
+               sprintf (buf, "%d", g_settings_get_int (settings, "paned-position"));
+               xmlSetProp (node, RB_PLAYLIST_BROWSER_POSITION, (xmlChar *)buf);
+
+               xmlSetProp (node, RB_PLAYLIST_SEARCH_TYPE, (xmlChar *)g_settings_get_string (settings, 
"search-type"));
+               g_object_unref (settings);
+       }
+
+
        klass->impl_save_contents_to_xml (source, node);
 
        source->priv->dirty = FALSE;
diff --git a/sources/rb-playlist-xml.h b/sources/rb-playlist-xml.h
index f7b2b31..ff647a8 100644
--- a/sources/rb-playlist-xml.h
+++ b/sources/rb-playlist-xml.h
@@ -42,6 +42,9 @@
 /* common attributes for all playlists */
 #define RB_PLAYLIST_TYPE (xmlChar *) "type"
 #define RB_PLAYLIST_NAME (xmlChar *) "name"
+#define RB_PLAYLIST_SHOW_BROWSER (xmlChar *) "show-browser"
+#define RB_PLAYLIST_BROWSER_POSITION (xmlChar *) "browser-position"
+#define RB_PLAYLIST_SEARCH_TYPE (xmlChar *) "search-type"
 
 /* values for the 'type' attribute */
 #define RB_PLAYLIST_AUTOMATIC (xmlChar *) "automatic"
diff --git a/sources/rb-static-playlist-source.c b/sources/rb-static-playlist-source.c
index ac81fe6..eef4a2e 100644
--- a/sources/rb-static-playlist-source.c
+++ b/sources/rb-static-playlist-source.c
@@ -270,6 +270,7 @@ rb_static_playlist_source_constructed (GObject *object)
        }
 
        gtk_paned_pack1 (GTK_PANED (paned), GTK_WIDGET (priv->browser), TRUE, FALSE);
+       gtk_widget_set_no_show_all (GTK_WIDGET (priv->browser), TRUE);
        g_signal_connect_object (priv->browser, "notify::output-model",
                                 G_CALLBACK (rb_static_playlist_source_browser_changed_cb),
                                 source, 0);
@@ -343,7 +344,7 @@ rb_static_playlist_source_constructed (GObject *object)
  * rb_static_playlist_source_new:
  * @shell: the #RBShell
  * @name: the playlist name
- * @settings_name: the settings name for the playlist (GSettings path friendly)
+ * @settings: GSettings instance, or NULL to have one created
  * @local: if %TRUE, the playlist is local to the library
  * @entry_type: type of database entries that can be added to the playlist.
  *
@@ -352,25 +353,15 @@ rb_static_playlist_source_constructed (GObject *object)
  * Return value: new playlist.
  */
 RBSource *
-rb_static_playlist_source_new (RBShell *shell, const char *name, const char *settings_name, gboolean local, 
RhythmDBEntryType *entry_type)
+rb_static_playlist_source_new (RBShell *shell, const char *name, GSettings *settings, gboolean local, 
RhythmDBEntryType *entry_type)
 {
        RBSource *source;
-       GSettings *settings;
        GtkBuilder *builder;
        GMenu *toolbar;
 
        if (name == NULL)
                name = "";
 
-       if (settings_name != NULL) {
-               char *path;
-               path = g_strdup_printf ("/org/gnome/rhythmbox/playlist/%s/", settings_name);
-               settings = g_settings_new_with_path ("org.gnome.rhythmbox.source", path);
-               g_free (path);
-       } else {
-               settings = NULL;
-       }
-
        builder = rb_builder_load ("playlist-toolbar.ui", NULL);
        toolbar = G_MENU (gtk_builder_get_object (builder, "playlist-toolbar"));
        rb_application_link_shared_menus (RB_APPLICATION (g_application_get_default ()), toolbar);
@@ -460,6 +451,7 @@ rb_static_playlist_source_load_from_xml (RBStaticPlaylistSource *source, xmlNode
 /**
  * rb_static_playlist_source_new_from_xml:
  * @shell: the #RBShell
+ * @name: playlist name
  * @node: XML node containing playlist entries
  *
  * Constructs a new playlist from the given XML document node.
@@ -467,10 +459,10 @@ rb_static_playlist_source_load_from_xml (RBStaticPlaylistSource *source, xmlNode
  * Return value: playlist read from XML
  */
 RBSource *
-rb_static_playlist_source_new_from_xml (RBShell *shell, xmlNodePtr node)
+rb_static_playlist_source_new_from_xml (RBShell *shell, const char *name, xmlNodePtr node)
 {
        RBSource *psource = rb_static_playlist_source_new (shell,
-                                                          NULL,
+                                                          name,
                                                           NULL,
                                                           TRUE,
                                                           RHYTHMDB_ENTRY_TYPE_SONG);
diff --git a/sources/rb-static-playlist-source.h b/sources/rb-static-playlist-source.h
index 4a2c80f..f3dc4f1 100644
--- a/sources/rb-static-playlist-source.h
+++ b/sources/rb-static-playlist-source.h
@@ -62,11 +62,12 @@ GType               rb_static_playlist_source_get_type      (void);
 
 RBSource *     rb_static_playlist_source_new           (RBShell *shell,
                                                         const char *name,
-                                                        const char *settings_name,
+                                                        GSettings *settings,
                                                         gboolean local,
                                                         RhythmDBEntryType *entry_type);
 
 RBSource *     rb_static_playlist_source_new_from_xml  (RBShell *shell,
+                                                        const char *name,
                                                         xmlNodePtr node);
 void           rb_static_playlist_source_load_from_xml (RBStaticPlaylistSource *source,
                                                         xmlNodePtr node);


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