[gnome-todo] window: add "Clear completed tasks" item for gear menu



commit c4f2174bfde9b20d65b0fe95a2fedad4738bb153
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date:   Tue Sep 1 21:17:24 2015 -0300

    window: add "Clear completed tasks" item for gear menu
    
    Very handy when you have tons of completed tasks and want to
    get rid of them quickly.

 data/gtk/menus.ui        |    8 +++
 data/ui/window.ui        |   20 +++++++-
 src/gtd-task-list-view.c |  110 +++++++++++++++++++++++++++++++++++++++++++---
 src/gtd-window.c         |   11 ++++-
 4 files changed, 139 insertions(+), 10 deletions(-)
---
diff --git a/data/gtk/menus.ui b/data/gtk/menus.ui
index d312903..f22db6c 100644
--- a/data/gtk/menus.ui
+++ b/data/gtk/menus.ui
@@ -27,4 +27,12 @@
       </item>
     </section>
   </menu>
+  <menu id="gear-menu">
+    <section>
+      <item>
+        <attribute name="label" translatable="yes">Clear completed taskā€¦</attribute>
+        <attribute name="action">list.clear-completed-tasks</attribute>
+      </item>
+    </section>
+  </menu>
 </interface>
diff --git a/data/ui/window.ui b/data/ui/window.ui
index 09ddfb1..0e63ad4 100644
--- a/data/ui/window.ui
+++ b/data/ui/window.ui
@@ -252,6 +252,23 @@
           </packing>
         </child>
         <child>
+          <object class="GtkMenuButton" id="gear_menu_button">
+            <property name="can_focus">True</property>
+            <style>
+              <class name="image-button" />
+            </style>
+            <child>
+              <object class="GtkImage">
+                <property name="visible">True</property>
+                <property name="icon_name">open-menu-symbolic</property>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="pack_type">end</property>
+          </packing>
+        </child>
+        <child>
           <object class="GtkToggleButton" id="select_button">
             <property name="visible" bind-source="back_button" bind-property="visible" 
bind-flags="default|invert-boolean|sync-create"/>
             <property name="can_focus">True</property>
@@ -267,7 +284,6 @@
           </object>
           <packing>
             <property name="pack_type">end</property>
-            <property name="position">3</property>
           </packing>
         </child>
         <child>
@@ -285,7 +301,6 @@
           </object>
           <packing>
             <property name="pack_type">end</property>
-            <property name="position">4</property>
           </packing>
         </child>
         <child>
@@ -296,7 +311,6 @@
           </object>
           <packing>
             <property name="pack_type">end</property>
-            <property name="position">4</property>
           </packing>
         </child>
       </object>
diff --git a/src/gtd-task-list-view.c b/src/gtd-task-list-view.c
index da8068a..b0a0827 100644
--- a/src/gtd-task-list-view.c
+++ b/src/gtd-task-list-view.c
@@ -55,6 +55,9 @@ typedef struct
 
   /* color provider */
   GtkCssProvider        *color_provider;
+
+  /* action */
+  GActionGroup          *action_group;
 } GtdTaskListViewPrivate;
 
 struct _GtdTaskListView
@@ -71,12 +74,25 @@ struct _GtdTaskListView
 #define TASK_REMOVED_NOTIFICATION_ID             "task-removed-id"
 
 /* prototypes */
+static void             gtd_task_list_view__clear_completed_tasks    (GSimpleAction     *simple,
+                                                                      GVariant          *parameter,
+                                                                      gpointer           user_data);
+
+static void             gtd_task_list_view__remove_task              (GtdTaskListView   *view,
+                                                                      GtdTask           *task);
+
 static void             gtd_task_list_view__task_completed            (GObject          *object,
                                                                        GParamSpec       *spec,
                                                                        gpointer          user_data);
 
+static void             gtd_task_list_view__update_done_label         (GtdTaskListView   *view);
+
 G_DEFINE_TYPE_WITH_PRIVATE (GtdTaskListView, gtd_task_list_view, GTK_TYPE_OVERLAY)
 
+static const GActionEntry gtd_task_list_view_entries[] = {
+  { "clear-completed-tasks", gtd_task_list_view__clear_completed_tasks },
+};
+
 typedef struct
 {
   GtdTaskListView *view;
@@ -110,6 +126,10 @@ undo_remove_task_action (GtdNotification *notification,
   RemoveTaskData  *data = user_data;
   GtdTaskList *list = gtd_task_get_list (data->task);
 
+  /*
+   * This will emit GtdTaskList::task-added and we'll readd
+   * to the list.
+   */
   gtd_task_list_save_task (list, data->task);
 
   g_free (data);
@@ -142,6 +162,36 @@ update_font_color (GtdTaskListView *view)
 }
 
 static void
+gtd_task_list_view__clear_completed_tasks (GSimpleAction *simple,
+                                           GVariant      *parameter,
+                                           gpointer       user_data)
+{
+  GtdTaskListView *view;
+  GList *tasks;
+  GList *l;
+
+  view = GTD_TASK_LIST_VIEW (user_data);
+  tasks = gtd_task_list_view_get_list (view);
+
+  for (l = tasks; l != NULL; l = l->next)
+    {
+      if (gtd_task_get_complete (l->data))
+        {
+          GtdTaskList *list;
+
+          list = gtd_task_get_list (l->data);
+
+          gtd_task_list_remove_task (list, l->data);
+          gtd_manager_remove_task (view->priv->manager, l->data);
+        }
+    }
+
+  gtd_task_list_view__update_done_label (view);
+
+  g_list_free (tasks);
+}
+
+static void
 gtd_task_list_view__update_empty_state (GtdTaskListView *view)
 {
   GtdTaskListViewPrivate *priv;
@@ -284,6 +334,8 @@ gtd_task_list_view__update_done_label (GtdTaskListView *view)
 
   g_return_if_fail (GTD_IS_TASK_LIST_VIEW (view));
 
+  gtk_revealer_set_reveal_child (GTK_REVEALER (view->priv->revealer), view->priv->complete_tasks > 0);
+
   new_label = g_strdup_printf ("%s (%d)",
                                _("Done"),
                                view->priv->complete_tasks);
@@ -427,8 +479,8 @@ gtd_task_list_view__add_task (GtdTaskListView *view,
 }
 
 static void
-gtd_task_list_view__remove_task (GtdTaskListView *view,
-                                 GtdTask         *task)
+gtd_task_list_view__remove_row_for_task (GtdTaskListView *view,
+                                         GtdTask         *task)
 {
   GtdTaskListViewPrivate *priv = view->priv;
   GList *children;
@@ -448,10 +500,25 @@ gtd_task_list_view__remove_task (GtdTaskListView *view,
         }
     }
 
+  g_list_free (children);
+}
+
+static void
+gtd_task_list_view__remove_task (GtdTaskListView *view,
+                                 GtdTask         *task)
+{
+  /* Remove the correspondent row */
+  gtd_task_list_view__remove_row_for_task (view, task);
+
+  /* Update the "Done" label */
+  if (gtd_task_get_complete (task))
+    {
+      view->priv->complete_tasks--;
+      gtd_task_list_view__update_done_label (view);
+    }
+
   /* Check if it should show the empty state */
   gtd_task_list_view__update_empty_state (view);
-
-  g_list_free (children);
 }
 
 static void
@@ -488,12 +555,11 @@ gtd_task_list_view__task_completed (GObject    *object,
     }
 
   gtd_task_list_view__update_done_label (GTD_TASK_LIST_VIEW (user_data));
-  gtk_revealer_set_reveal_child (priv->revealer, priv->complete_tasks > 0);
 
   if (!priv->show_completed)
     {
       if (task_complete)
-        gtd_task_list_view__remove_task (GTD_TASK_LIST_VIEW (user_data), task);
+        gtd_task_list_view__remove_row_for_task (GTD_TASK_LIST_VIEW (user_data), task);
       else
         gtd_task_list_view__add_task (GTD_TASK_LIST_VIEW (user_data), task);
     }
@@ -619,6 +685,14 @@ gtd_task_list_view_constructed (GObject *object)
 
   G_OBJECT_CLASS (gtd_task_list_view_parent_class)->constructed (object);
 
+  /* action_group */
+  self->priv->action_group = G_ACTION_GROUP (g_simple_action_group_new ());
+
+  g_action_map_add_action_entries (G_ACTION_MAP (self->priv->action_group),
+                                   gtd_task_list_view_entries,
+                                   G_N_ELEMENTS (gtd_task_list_view_entries),
+                                   object);
+
   /* css provider */
   self->priv->color_provider = gtk_css_provider_new ();
 
@@ -634,6 +708,28 @@ gtd_task_list_view_constructed (GObject *object)
 }
 
 static void
+gtd_task_list_view_map (GtkWidget *widget)
+{
+  GtdTaskListViewPrivate *priv;
+  GtkWidget *window;
+
+  GTK_WIDGET_CLASS (gtd_task_list_view_parent_class)->map (widget);
+
+  priv = GTD_TASK_LIST_VIEW (widget)->priv;
+  window = gtk_widget_get_toplevel (widget);
+
+  /* Clear previously added "list" actions */
+  gtk_widget_insert_action_group (window,
+                                  "list",
+                                  NULL);
+
+  /* Add this instance's action group */
+  gtk_widget_insert_action_group (window,
+                                  "list",
+                                  priv->action_group);
+}
+
+static void
 gtd_task_list_view_class_init (GtdTaskListViewClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
@@ -644,6 +740,8 @@ gtd_task_list_view_class_init (GtdTaskListViewClass *klass)
   object_class->get_property = gtd_task_list_view_get_property;
   object_class->set_property = gtd_task_list_view_set_property;
 
+  widget_class->map = gtd_task_list_view_map;
+
   /**
    * GtdTaskListView::manager:
    *
diff --git a/src/gtd-window.c b/src/gtd-window.c
index 594c3ae..17fb16c 100644
--- a/src/gtd-window.c
+++ b/src/gtd-window.c
@@ -36,6 +36,7 @@ typedef struct
   GtkButton                     *back_button;
   GtkWidget                     *cancel_selection_button;
   GtkColorButton                *color_button;
+  GtkWidget                     *gear_menu_button;
   GtkHeaderBar                  *headerbar;
   GtkFlowBox                    *lists_flowbox;
   GtkStack                      *main_stack;
@@ -428,7 +429,7 @@ gtd_window__stack_visible_child_cb (GtdWindow *window)
 
   gtk_widget_set_visible (GTK_WIDGET (priv->search_button), is_list_view);
   gtk_widget_set_visible (GTK_WIDGET (priv->select_button), is_list_view);
-
+  gtk_widget_set_visible (priv->gear_menu_button, !is_list_view);
 }
 
 static void
@@ -872,12 +873,19 @@ static void
 gtd_window_constructed (GObject *object)
 {
   GtdWindowPrivate *priv = GTD_WINDOW (object)->priv;
+  GtkApplication *app;
+  GMenu *menu;
 
   G_OBJECT_CLASS (gtd_window_parent_class)->constructed (object);
 
   /* load stored size */
   gtd_window__load_geometry (GTD_WINDOW (object));
 
+  /* gear menu */
+  app = GTK_APPLICATION (g_application_get_default ());
+  menu = gtk_application_get_menu_by_id (app, "gear-menu");
+  gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (priv->gear_menu_button), G_MENU_MODEL (menu));
+
   gtk_flow_box_set_sort_func (priv->lists_flowbox,
                               (GtkFlowBoxSortFunc) gtd_window__flowbox_sort_func,
                               NULL,
@@ -1076,6 +1084,7 @@ gtd_window_class_init (GtdWindowClass *klass)
   gtk_widget_class_bind_template_child_private (widget_class, GtdWindow, back_button);
   gtk_widget_class_bind_template_child_private (widget_class, GtdWindow, cancel_selection_button);
   gtk_widget_class_bind_template_child_private (widget_class, GtdWindow, color_button);
+  gtk_widget_class_bind_template_child_private (widget_class, GtdWindow, gear_menu_button);
   gtk_widget_class_bind_template_child_private (widget_class, GtdWindow, headerbar);
   gtk_widget_class_bind_template_child_private (widget_class, GtdWindow, lists_flowbox);
   gtk_widget_class_bind_template_child_private (widget_class, GtdWindow, list_view);


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