commit 26bce607a85b8fc7487f3658245ac6484c40848b
Author: Yash Mehrotra <yashmehrotra95@gmail.com>
Date:   Wed Feb 10 23:44:37 2016 +0530

    Option to rename playlists
    
    Now you can rename user created playlists. https://bugzilla.gnome.org/show_bug.cgi?id=744822

diff --git a/gnomemusic/playlists.py b/gnomemusic/playlists.py
index a7aaaf8..c5b6089 100644
--- a/gnomemusic/playlists.py
+++ b/gnomemusic/playlists.py
@@ -94,6 +94,7 @@ class Playlists(GObject.GObject):
         'playlist-created': (GObject.SignalFlags.RUN_FIRST, None, (Grl.Media,)),
         'playlist-deleted': (GObject.SignalFlags.RUN_FIRST, None, (Grl.Media,)),
         'playlist-updated': (GObject.SignalFlags.RUN_FIRST, None, (int,)),
+        'playlist-renamed': (GObject.SignalFlags.RUN_FIRST, None, (Grl.Media,)),
         'song-added-to-playlist': (
             GObject.SignalFlags.RUN_FIRST, None, (Grl.Media, Grl.Media)
         ),
@@ -245,6 +246,17 @@ class Playlists(GObject.GObject):
         )
 
     @log
+    def rename_playlist(self, item, name):
+        def update_callback(conn, res, data):
+            conn.update_finish(res)
+            self.emit('playlist-renamed', item)
+
+        self.tracker.update_async(
+            Query.rename_playlist(item.get_id(), name), GLib.PRIORITY_LOW,
+            None, update_callback, None
+        )
+
+    @log
     def add_to_playlist(self, playlist, items):
         def get_callback(source, param, item, count, data, error):
             if item:
diff --git a/gnomemusic/query.py b/gnomemusic/query.py
index b882fb7..46ebfa9 100644
--- a/gnomemusic/query.py
+++ b/gnomemusic/query.py
@@ -492,6 +492,31 @@ class Query():
         return query
 
     @staticmethod
+    def rename_playlist(playlist_id, name):
+        query = """
+    INSERT OR REPLACE {
+        ?playlist
+            nie:title "%(title)s"
+    }
+    WHERE {
+        ?playlist
+            a nmm:Playlist ;
+            a nfo:MediaList .
+        OPTIONAL {
+            ?playlist
+                nfo:hasMediaFileListEntry ?entry .
+        }
+        FILTER (
+            tracker:id(?playlist) = %(playlist_id)s
+        )
+    }
+    """.replace("\n", " ").strip() % {
+            'title': name,
+            'playlist_id': playlist_id
+        }
+        return query
+
+    @staticmethod
     def delete_playlist(playlist_id):
         query = """
     DELETE {
diff --git a/gnomemusic/view.py b/gnomemusic/view.py
index bb9b0d5..c3b1482 100644
--- a/gnomemusic/view.py
+++ b/gnomemusic/view.py
@@ -831,6 +831,9 @@ class Playlist(ViewContainer):
         playlistPlayAction = Gio.SimpleAction.new('playlist_play', None)
         playlistPlayAction.connect('activate', self._on_play_activate)
         window.add_action(playlistPlayAction)
+        self.playlistRenameAction = Gio.SimpleAction.new('playlist_rename', None)
+        self.playlistRenameAction.connect('activate', self._on_rename_activate)
+        window.add_action(self.playlistRenameAction)
         self.playlistDeleteAction = Gio.SimpleAction.new('playlist_delete', None)
         self.playlistDeleteAction.connect('activate', self._on_delete_activate)
         window.add_action(self.playlistDeleteAction)
@@ -1137,11 +1140,13 @@ class Playlist(ViewContainer):
         self.songs_count = 0
         GLib.idle_add(grilo.populate_playlist_songs, playlist, self._add_item)
 
-        # disable delete button if current playlist is a smart playlist
+        # disable delete button and rename button if current playlist is a smart playlist
         if self.current_playlist_is_protected():
             self.playlistDeleteAction.set_enabled(False)
+            self.playlistRenameAction.set_enabled(False)
         else:
             self.playlistDeleteAction.set_enabled(True)
+            self.playlistRenameAction.set_enabled(True)
 
     @log
     def _add_item(self, source, param, item, remaining=0, data=None):
@@ -1229,6 +1234,17 @@ class Playlist(ViewContainer):
         self.stage_playlist_for_deletion()
 
     @log
+    def _on_rename_activate(self, menuitem, data=None):
+        _iter = self.playlists_sidebar.get_generic_view().get_selection().get_selected()[1]
+        playlist = self.playlists_model.get_value(_iter, 5)
+
+        self.pl_torename = playlist
+        self.window._init_playlist_rename()
+
+        self.playlists_model.clear()
+        self._populate()
+
+    @log
     def _on_playlist_created(self, playlists, item):
         self._add_playlist_item_to_model(item)
         if self.playlists_model.iter_n_children(None) == 1:
diff --git a/gnomemusic/widgets.py b/gnomemusic/widgets.py
index 03673c9..9a4d03e 100644
--- a/gnomemusic/widgets.py
+++ b/gnomemusic/widgets.py
@@ -889,3 +889,23 @@ class CellRendererClickablePixbuf(Gtk.CellRendererPixbuf):
             else:
                 self.set_property('icon_name', '')
             self.show_star = value
+
+class PlaylistRenameDialog(Gtk.Dialog):
+    def __init__(self, parent, prev_name=''):
+        Gtk.Dialog.__init__(self, "Rename Playlist", parent, 0,
+            (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
+             Gtk.STOCK_OK, Gtk.ResponseType.OK))
+
+        self.set_default_size(300, 50)
+
+        box = self.get_content_area()
+
+        self.input_text = Gtk.Entry()
+        self.input_text.set_text(prev_name)
+        box.add(self.input_text)
+
+        self.show_all()
+
+    @property
+    def text(self):
+        return self.input_text.get_text()
\ No newline at end of file
diff --git a/gnomemusic/window.py b/gnomemusic/window.py
index e6bc69d..a5ea18b 100644
--- a/gnomemusic/window.py
+++ b/gnomemusic/window.py
@@ -344,6 +344,14 @@ class Window(Gtk.ApplicationWindow):
         self.notification_handler = GLib.timeout_add(1000, self._show_notification)
 
     @log
+    def _init_playlist_rename(self):
+        widget = Widgets.PlaylistRenameDialog(self, self.views[3].pl_torename.get_title())
+        if widget.run() == Gtk.ResponseType.OK:
+            Views.playlists.rename_playlist(self.views[3].pl_torename, widget.text)
+
+        widget.destroy()
+
+    @log
     def _init_playlist_removal_notification(self):
         self.notification = Gd.Notification()
         self.notification.set_timeout(20)
