[gnome-news/wip/gbsneto/improvements] project: implement starred items



commit 44d3a32f4bc2ea3663ec2de4c82c49506c900373
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date:   Mon Mar 7 17:12:50 2016 -0300

    project: implement starred items
    
    This commit implements the starred items functionality
    both in Tracker class and throughout the UI. Also, it
    adapts the StarredView to work.

 data/ui/headerbar.ui |   22 ++++++++++++++++++++++
 gnomenews/post.py    |    1 +
 gnomenews/toolbar.py |   27 +++++++++++++++++++++++++++
 gnomenews/tracker.py |   38 ++++++++++++++++++++++++++++++++++++++
 gnomenews/view.py    |    3 ++-
 gnomenews/window.py  |   15 +++++++++++++++
 6 files changed, 105 insertions(+), 1 deletions(-)
---
diff --git a/data/ui/headerbar.ui b/data/ui/headerbar.ui
index 1cc6408..dc66419 100644
--- a/data/ui/headerbar.ui
+++ b/data/ui/headerbar.ui
@@ -122,6 +122,28 @@
     <property name="visible">True</property>
     <property name="vexpand">False</property>
     <child>
+      <object class="GtkButton" id="starred-button">
+        <property name="can_focus">False</property>
+        <property name="valign">center</property>
+        <property name="sensitive">True</property>
+        <property name="tooltip_text" translatable="yes">Mark this article as starred</property>
+        <style>
+          <class name="image-button"/>
+        </style>
+        <child>
+          <object class="GtkImage" id="starred-button-image">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="icon-name">non-starred-symbolic</property>
+            <property name="icon-size">1</property>
+          </object>
+        </child>
+      </object>
+      <packing>
+        <property name="pack_type">end</property>
+      </packing>
+    </child>
+    <child>
       <object class="GtkToggleButton" id="search-button">
         <property name="visible">True</property>
         <property name="can_focus">False</property>
diff --git a/gnomenews/post.py b/gnomenews/post.py
index 88b95bf..aea43a5 100644
--- a/gnomenews/post.py
+++ b/gnomenews/post.py
@@ -47,6 +47,7 @@ class Post(GObject.GObject):
         self.content = cursor['content']
         self.url = cursor['url']
         self.is_read = cursor['is_read']
+        self.is_starred = cursor['is_starred']
 
         self.author = self.sanitize_author(cursor['fullname'])
         self.author_email = cursor['author_email']
diff --git a/gnomenews/toolbar.py b/gnomenews/toolbar.py
index 17af8da..bb2c760 100644
--- a/gnomenews/toolbar.py
+++ b/gnomenews/toolbar.py
@@ -33,6 +33,7 @@ class Toolbar(GObject.GObject):
 
     __gsignals__ = {
         'state-changed': (GObject.SignalFlags.RUN_FIRST, None, ()),
+        'toggle-starred': (GObject.SignalFlags.RUN_FIRST, None, (bool,)),
     }
 
     @log
@@ -68,6 +69,13 @@ class Toolbar(GObject.GObject):
 
         self.window.search_entry.connect('search-changed', self._search_changed)
 
+        # Starred button
+        self._starred_button = self._ui.get_object('starred-button')
+        self._starred_image = self._ui.get_object('starred-button-image')
+
+        self._starred_button.connect('clicked', self._toggle_starred)
+        self.starred = False
+
         self.set_state(ToolbarState.MAIN)
 
         self._stack_switcher.show()
@@ -77,6 +85,11 @@ class Toolbar(GObject.GObject):
         self.header_bar.set_custom_title(self._stack_switcher)
 
     @log
+    def _toggle_starred(self, button):
+        self.set_starred(not self.starred)
+        self.emit('toggle-starred', self.starred)
+
+    @log
     def _search_changed(self, entry, data=None):
         if entry.get_text_length() > 0:
             self.set_state(ToolbarState.SEARCH_VIEW)
@@ -86,6 +99,19 @@ class Toolbar(GObject.GObject):
             self.header_bar.set_title(_("News"))
 
     @log
+    def set_starred(self, starred):
+        # Don't set the same value
+        if starred is self.starred:
+            return
+
+        self.starred = starred
+
+        if starred:
+            self._starred_image.set_from_icon_name('starred-symbolic', Gtk.IconSize.BUTTON)
+        else:
+            self._starred_image.set_from_icon_name('non-starred-symbolic', Gtk.IconSize.BUTTON)
+
+    @log
     def set_stack(self, stack):
         self._stack_switcher.set_stack(stack)
 
@@ -116,6 +142,7 @@ class Toolbar(GObject.GObject):
 
         self._back_button.set_visible(self._state == ToolbarState.CHILD_VIEW)
         self._search_button.set_visible(self._state != ToolbarState.CHILD_VIEW)
+        self._starred_button.set_visible(self._state == ToolbarState.CHILD_VIEW)
         self.add_toggle_button.set_visible(self._state != ToolbarState.CHILD_VIEW)
 
     @log
diff --git a/gnomenews/tracker.py b/gnomenews/tracker.py
index 07ba4da..a7bd4ef 100644
--- a/gnomenews/tracker.py
+++ b/gnomenews/tracker.py
@@ -55,6 +55,7 @@ class Tracker(GObject.GObject):
           nie:contentCreated(?msg) AS date
           nmo:htmlMessageContent(?msg) AS content
           nmo:isRead(?msg) AS is_read
+          ?msg BOUND(?tag) as is_starred
         WHERE
           { ?msg a mfo:FeedMessage """
 
@@ -66,6 +67,8 @@ class Tracker(GObject.GObject):
 
         query += """.
             OPTIONAL { ?msg nco:creator ?creator .
+                       ?msg nao:hasTag ?tag .
+                       FILTER(?tag = nao:predefined-tag-favorite) .
                        OPTIONAL {?creator nco:hasEmailAddress ?email } .
                        OPTIONAL {?creator nco:websiteUrl ?website }
             }
@@ -145,6 +148,35 @@ class Tracker(GObject.GObject):
         self.sparql.update(query, GLib.PRIORITY_DEFAULT, None)
 
     @log
+    def mark_post_as_starred(self, url, starred=True):
+        """Marks given post as starred
+
+        Args:
+            url (str): URL of the post.
+            starred (Optional): whether the post is starred or not.
+        """
+
+        query = ''
+
+        if starred:
+            query = """
+            INSERT
+              { ?msg nao:hasTag nao:predefined-tag-favorite }
+            WHERE
+              { ?msg nie:url "%s" }
+            """ % url
+        else:
+            query = """
+            DELETE
+              { ?msg nao:hasTag nao:predefined-tag-favorite }
+            WHERE
+              { ?msg nie:url "%s";
+                     nao:hasTag nao:predefined-tag-favorite }
+            """ % url
+
+        self.sparql.update(query, GLib.PRIORITY_DEFAULT, None)
+
+    @log
     def remove_channel(self, url):
         """Drop channel from fetching by tracker
 
@@ -177,10 +209,13 @@ class Tracker(GObject.GObject):
           nie:contentCreated(?msg) AS date
           nmo:htmlMessageContent(?msg) AS content
           nmo:isRead(?msg) AS is_read
+          ?msg BOUND(?tag) as is_starred
           { ?msg a mfo:FeedMessage;
                  nmo:communicationChannel ?chan .
             ?chan nie:url "%s" .
             OPTIONAL { ?msg nco:creator ?creator .
+                       ?msg nao:hasTag ?tag .
+                       FILTER(?tag = nao:predefined-tag-favorite) .
                        OPTIONAL { ?creator nco:hasEmailAddress ?email } .
                        OPTIONAL { ?creator nco:websiteUrl ?website }}
           }
@@ -241,6 +276,7 @@ class Tracker(GObject.GObject):
           nie:contentCreated(?msg) AS ?date_created
           nmo:htmlMessageContent(?msg) AS ?content
           nmo:isRead(?msg) AS ?is_read
+          ?msg BOUND(?tag) as ?is_starred
           { ?msg a mfo:FeedMessage; """
 
         if channel:
@@ -251,6 +287,8 @@ class Tracker(GObject.GObject):
         query += """
                  fts:match "%s" .
             OPTIONAL { ?msg nco:creator ?creator .
+                       ?msg nao:hasTag ?tag .
+                       FILTER(?tag = nao:predefined-tag-favorite) .
                        OPTIONAL { ?creator nco:hasEmailAddress ?email } .
                        OPTIONAL { ?creator nco:websiteUrl ?website }}
           }
diff --git a/gnomenews/view.py b/gnomenews/view.py
index 13087d9..18563d0 100644
--- a/gnomenews/view.py
+++ b/gnomenews/view.py
@@ -150,6 +150,7 @@ class FeedView(Gtk.Stack):
         self.add(webview)
         self.show_all()
 
+        self.post = post
         self.url = post.url
 
     @staticmethod
@@ -371,7 +372,7 @@ class StarredView(GenericFeedsView):
     def update(self, _=None):
         [self.flowbox.remove(old_feed) for old_feed in self.flowbox.get_children()]
 
-        posts = self.tracker.get_post_sorted_by_date(10, starred=True)
+        posts = self.tracker.get_post_sorted_by_date(starred=True)
         [self._add_a_new_preview(post) for post in posts]
         self.show_all()
 
diff --git a/gnomenews/window.py b/gnomenews/window.py
index ee942a7..413fba6 100644
--- a/gnomenews/window.py
+++ b/gnomenews/window.py
@@ -112,6 +112,8 @@ class Window(Gtk.ApplicationWindow):
         self.toolbar = Toolbar(self)
         self.set_titlebar(self.toolbar.header_bar)
 
+        self.toolbar.connect('toggle-starred', self.toggle_starred)
+
         self._add_views()
 
         self.toolbar._back_button.set_visible(False)
@@ -123,6 +125,17 @@ class Window(Gtk.ApplicationWindow):
             visible_view.update()
 
     @log
+    def toggle_starred(self, toolbar, starred):
+        # Ignore the signal when we're not in FeedView
+        if not self.feed_view:
+            return
+
+        post = self.feed_view.post
+        post.is_starred = starred
+
+        self.tracker.mark_post_as_starred(post.url, starred)
+
+    @log
     def _add_views(self):
         self.views.append(view.NewView(self.tracker))
         self.views.append(view.FeedsView(self.tracker))
@@ -153,6 +166,8 @@ class Window(Gtk.ApplicationWindow):
         self._stack.add_named(self.feed_view, 'feedview')
         self._stack.set_visible_child(self.feed_view)
 
+        self.toolbar.set_starred(post.is_starred)
+
         # Mark the post as read
         self.tracker.mark_post_as_read(post.url)
 


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