[gnome-todo/wip/gbsneto/plugins: 2/2] panels: add List selector panel
- From: Georges Basile Stavracas Neto <gbsneto src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-todo/wip/gbsneto/plugins: 2/2] panels: add List selector panel
- Date: Mon, 28 Dec 2015 20:29:11 +0000 (UTC)
commit 8639b41c9d34d13e5ef9767ccf63fec785d3e18a
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date: Mon Dec 28 18:27:01 2015 -0200
panels: add List selector panel
The list selector panel is the port of the
old "Lists" tab to the new model, which is
a GtdPanel implementation.
This implements the basic grid view using
a GtkFlowBox. Next logical step is to add
a list view using GtkListBox.
data/Makefile.am | 1 +
data/todo.gresource.xml | 1 +
data/ui/list-selector-panel.ui | 261 ++++++++++++++++
data/ui/window.ui | 278 +-----------------
src/Makefile.am | 4 +
src/gtd-window.c | 551 ++---------------------------------
src/views/gtd-list-selector-grid.c | 413 ++++++++++++++++++++++++++
src/views/gtd-list-selector-grid.h | 36 +++
src/views/gtd-list-selector-panel.c | 556 +++++++++++++++++++++++++++++++++++
src/views/gtd-list-selector-panel.h | 36 +++
10 files changed, 1334 insertions(+), 803 deletions(-)
---
diff --git a/data/Makefile.am b/data/Makefile.am
index 3e8b513..f1b2ee7 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -32,6 +32,7 @@ EXTRA_DIST= \
gtk/menus.ui \
ui/edit-pane.ui \
ui/initial-setup.ui \
+ ui/list-selector-panel.ui \
ui/list-view.ui \
ui/notification.ui \
ui/provider-dialog.ui \
diff --git a/data/todo.gresource.xml b/data/todo.gresource.xml
index 46e12c4..c4d7648 100644
--- a/data/todo.gresource.xml
+++ b/data/todo.gresource.xml
@@ -4,6 +4,7 @@
<file alias="gtk/menus.ui">gtk/menus.ui</file>
<file compressed="true" preprocess="xml-stripblanks">ui/edit-pane.ui</file>
<file compressed="true" preprocess="xml-stripblanks">ui/initial-setup.ui</file>
+ <file compressed="true" preprocess="xml-stripblanks">ui/list-selector-panel.ui</file>
<file compressed="true" preprocess="xml-stripblanks">ui/list-view.ui</file>
<file compressed="true" preprocess="xml-stripblanks">ui/notification.ui</file>
<file compressed="true" preprocess="xml-stripblanks">ui/provider-dialog.ui</file>
diff --git a/data/ui/list-selector-panel.ui b/data/ui/list-selector-panel.ui
new file mode 100644
index 0000000..a5059fc
--- /dev/null
+++ b/data/ui/list-selector-panel.ui
@@ -0,0 +1,261 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.19.0 -->
+<interface>
+ <requires lib="gtk+" version="3.16"/>
+ <template class="GtdListSelectorPanel" parent="GtkStack">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="transition_type">crossfade</property>
+ <signal name="key-press-event" handler="gtd_list_selector_panel_on_key_press_event" object="search_bar"
swapped="no" />
+ <child>
+ <object class="GtkBox" id="lists">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkSearchBar" id="search_bar">
+ <property name="visible">True</property>
+ <property name="app_paintable">True</property>
+ <property name="can_focus">False</property>
+ <property name="show_close_button">True</property>
+ <child>
+ <object class="GtkSearchEntry" id="search_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="width_chars">40</property>
+ <property name="primary_icon_name">edit-find-symbolic</property>
+ <property name="primary_icon_activatable">False</property>
+ <property name="primary_icon_sensitive">False</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="hscrollbar_policy">never</property>
+ <child>
+ <object class="GtkViewport" id="viewport">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkStack" id="stack">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hhomogeneous">False</property>
+ <property name="vhomogeneous">False</property>
+ <property name="transition_type">crossfade</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkActionBar" id="actionbar">
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkButton" id="rename_button">
+ <property name="label" translatable="yes">Rename</property>
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="delete_button">
+ <property name="label" translatable="yes">Delete</property>
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <signal name="clicked" handler="gtd_list_selector_panel_delete_button_clicked"
object="GtdListSelectorPanel" swapped="no" />
+ <style>
+ <class name="destructive-action"/>
+ </style>
+ </object>
+ <packing>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="name">lists</property>
+ <property name="title" translatable="yes">Lists</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtdTaskListView" id="tasklist_view">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="readonly">False</property>
+ </object>
+ <packing>
+ <property name="name">tasks</property>
+ <property name="title" translatable="yes">Tasks</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </template>
+ <object class="GtkPopover" id="rename_popover">
+ <property name="can_focus">False</property>
+ <property name="border_width">12</property>
+ <child>
+ <object class="GtkGrid" id="grid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">12</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Name of the task list</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="rename_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <signal name="notify::text" handler="gtd_list_selector_panel_rename_entry_text_changed"
object="GtdListSelectorPanel" swapped="no" />
+ <signal name="activate" handler="gtd_list_selector_panel_rename_task_list"
object="GtdListSelectorPanel" swapped="yes" />
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="save_rename_button">
+ <property name="label" translatable="yes">Rename</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <signal name="clicked" handler="gtd_list_selector_panel_rename_task_list"
object="GtdListSelectorPanel" swapped="yes" />
+ <style>
+ <class name="suggested-action"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <object class="GtkButton" id="back_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="halign">start</property>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">go-previous-symbolic</property>
+ </object>
+ </child>
+ </object>
+ <object class="GtkToggleButton" id="search_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="halign">end</property>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">edit-find-symbolic</property>
+ </object>
+ </child>
+ </object>
+ <object class="GtkToggleButton" id="selection_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="halign">end</property>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">emblem-ok-symbolic</property>
+ </object>
+ </child>
+ </object>
+ <object class="GtkButton" id="view_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="halign">end</property>
+ <child>
+ <object class="GtkImage" id="view_button_image">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">view-grid-symbolic</property>
+ </object>
+ </child>
+ </object>
+ <object class="GtkColorButton" id="color_button">
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="halign">end</property>
+ <signal name="color_set" handler="gtd_list_selector_panel_list_color_set" object="GtdListSelectorPanel"
swapped="no" />
+ </object>
+ <object class="GtkMenuButton" id="new_list_button">
+ <property name="visible" bind-source="back_button" bind-property="visible"
bind-flags="invert-boolean|sync-create"/>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="popover">new_list_popover</property>
+ <property name="halign">start</property>
+ <child>
+ <object class="GtkLabel" id="new_list_button_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">New List</property>
+ </object>
+ </child>
+ </object>
+ <object class="GtdProviderPopover" id="new_list_popover">
+ <property name="can_focus">False</property>
+ <property name="position">bottom</property>
+ </object>
+</interface>
diff --git a/data/ui/window.ui b/data/ui/window.ui
index 1d320d7..1a60fa5 100644
--- a/data/ui/window.ui
+++ b/data/ui/window.ui
@@ -2,10 +2,6 @@
<!-- Generated with glade 3.18.1 -->
<interface>
<requires lib="gtk+" version="3.16"/>
- <object class="GtdProviderPopover" id="new_list_popover">
- <property name="can_focus">False</property>
- <property name="position">bottom</property>
- </object>
<object class="GtdProviderDialog" id="provider_dialog">
<property name="visible">False</property>
<property name="modal">True</property>
@@ -15,7 +11,6 @@
<property name="can_focus">False</property>
<property name="default_width">800</property>
<property name="default_height">600</property>
- <signal name="key-press-event" handler="gtd_window__on_key_press_event" object="search_bar" swapped="no"
/>
<child>
<object class="GtkOverlay" id="overlay">
<property name="visible">True</property>
@@ -29,143 +24,17 @@
</object>
</child>
<child>
- <object class="GtkStack" id="main_stack">
+ <object class="GtkStack" id="stack">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="transition_duration">250</property>
<property name="transition_type">crossfade</property>
<signal name="notify::visible-child" handler="gtd_window__stack_visible_child_cb"
object="GtdWindow" swapped="yes" />
- <child>
- <object class="GtkBox" id="main_box">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="hexpand">True</property>
- <property name="vexpand">True</property>
- <property name="orientation">vertical</property>
- <child>
- <object class="GtkSearchBar" id="search_bar">
- <property name="visible">True</property>
- <property name="show_close_button">True</property>
- <property name="search_mode_enabled" bind-source="search_button" bind-property="active"
bind-flags="default|bidirectional" />
- <child>
- <object class="GtkSearchEntry" id="search_entry">
- <property name="visible">True</property>
- <property name="width_request">400</property>
- <signal name="search-changed" handler="gtk_flow_box_invalidate_filter"
object="lists_flowbox" swapped="yes" />
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkStack" id="stack">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="hexpand">True</property>
- <property name="vexpand">True</property>
- <property name="transition_duration">250</property>
- <property name="transition_type">crossfade</property>
- <signal name="notify::visible-child" handler="gtd_window__stack_visible_child_cb"
object="GtdWindow" swapped="yes" />
- <style>
- <class name="background" />
- </style>
- <child>
- <object class="GtkScrolledWindow" id="lists_scrolled_window">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="hexpand">True</property>
- <property name="vexpand">True</property>
- <property name="hscrollbar_policy">never</property>
- <child>
- <object class="GtkViewport" id="lists_viewport">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="shadow_type">none</property>
- <child>
- <object class="GtkFlowBox" id="lists_flowbox">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="has_focus">True</property>
- <property name="halign">start</property>
- <property name="valign">start</property>
- <property name="hexpand">True</property>
- <property name="vexpand">True</property>
- <property name="border_width">12</property>
- <property name="homogeneous">True</property>
- <property name="column_spacing">12</property>
- <property name="row_spacing">12</property>
- <property name="max_children_per_line">100</property>
- <property name="selection_mode">none</property>
- <signal name="child-activated" handler="gtd_window__list_selected"
object="GtdWindow" swapped="no" />
- </object>
- </child>
- </object>
- </child>
- </object>
- <packing>
- <property name="name">lists</property>
- <property name="title" translatable="yes">Lists</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkActionBar" id="action_bar">
- <property name="can_focus">False</property>
- <child>
- <object class="GtkButton" id="rename_button">
- <property name="label" translatable="yes">Rename</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="sensitive">False</property>
- <signal name="clicked" handler="gtd_window__rename_button_clicked"
object="GtdWindow" swapped="yes" />
- </object>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkButton" id="remove_button">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="sensitive">False</property>
- <property name="label" translatable="yes">Delete</property>
- <signal name="clicked" handler="gtd_window__remove_button_clicked"
object="GtdWindow" swapped="yes" />
- <style>
- <class name="destructive-action"/>
- </style>
- </object>
- <packing>
- <property name="pack_type">end</property>
- <property name="position">0</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">2</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="name">overview</property>
- </packing>
- </child>
- <child>
- <object class="GtdTaskListView" id="list_view">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="readonly">False</property>
- </object>
- <packing>
- <property name="name">tasks</property>
- <property name="position">1</property>
- </packing>
- </child>
+ <style>
+ <class name="background" />
+ </style>
</object>
</child>
</object>
@@ -175,38 +44,6 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="show_close_button">True</property>
- <child>
- <object class="GtkButton" id="back_button">
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <signal name="clicked" handler="gtd_window__back_button_clicked" object="GtdWindow" swapped="no"
/>
- <child>
- <object class="GtkImage" id="back_button_image">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="icon_name">go-previous-symbolic</property>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkMenuButton" id="new_list_button">
- <property name="visible" bind-source="back_button" bind-property="visible"
bind-flags="invert-boolean|sync-create"/>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="popover">new_list_popover</property>
- <child>
- <object class="GtkLabel" id="new_list_button_label">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">New List</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
<child type="title">
<object class="GtkStackSwitcher" id="stack_switcher">
<property name="visible">True</property>
@@ -244,108 +81,7 @@
<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>
- <property name="receives_default">True</property>
- <signal name="toggled" handler="gtd_window__select_button_toggled" object="GtdWindow"
swapped="no" />
- <child>
- <object class="GtkImage" id="select_button_image">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="icon_name">object-select-symbolic</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="pack_type">end</property>
- </packing>
- </child>
- <child>
- <object class="GtkToggleButton" id="search_button">
- <property name="visible" bind-source="back_button" bind-property="visible"
bind-flags="invert-boolean|sync-create"/>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <child>
- <object class="GtkImage" id="search_button_image">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="icon_name">edit-find-symbolic</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="pack_type">end</property>
- </packing>
- </child>
- <child>
- <object class="GtkColorButton" id="color_button">
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <signal name="color_set" handler="gtd_window__list_color_set" object="GtdWindow" swapped="no" />
- </object>
- <packing>
- <property name="pack_type">end</property>
- </packing>
- </child>
</object>
</child>
</template>
- <object class="GtkPopover" id="rename_popover">
- <property name="can_focus">False</property>
- <property name="border_width">12</property>
- <child>
- <object class="GtkGrid" id="grid">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="row_spacing">12</property>
- <property name="column_spacing">12</property>
- <child>
- <object class="GtkLabel" id="label">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">Name of the task list</property>
- <property name="xalign">0</property>
- <attributes>
- <attribute name="weight" value="bold"/>
- </attributes>
- </object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">0</property>
- <property name="width">2</property>
- </packing>
- </child>
- <child>
- <object class="GtkEntry" id="rename_entry">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <signal name="notify::text" handler="gtd_window__rename_entry_text_changed" object="GtdWindow"
swapped="no" />
- <signal name="activate" handler="gtd_window__rename_task_list" object="GtdWindow" swapped="yes"
/>
- </object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkButton" id="save_rename_button">
- <property name="label" translatable="yes">Rename</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <signal name="clicked" handler="gtd_window__rename_task_list" object="GtdWindow" swapped="yes" />
- <style>
- <class name="suggested-action"/>
- </style>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="top_attach">1</property>
- </packing>
- </child>
- </object>
- </child>
- </object>
</interface>
diff --git a/src/Makefile.am b/src/Makefile.am
index 718d0d1..afbc54b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -40,6 +40,10 @@ gnome_todo_SOURCES = \
provider/gtd-provider-selector.h \
views/gtd-list-selector.c \
views/gtd-list-selector.h \
+ views/gtd-list-selector-grid.c \
+ views/gtd-list-selector-grid.h \
+ views/gtd-list-selector-panel.c \
+ views/gtd-list-selector-panel.h \
gtd-application.c \
gtd-application.h \
gtd-arrow-frame.c \
diff --git a/src/gtd-window.c b/src/gtd-window.c
index d0d6a2c..35b04d7 100644
--- a/src/gtd-window.c
+++ b/src/gtd-window.c
@@ -18,6 +18,7 @@
#include "interfaces/gtd-provider.h"
#include "interfaces/gtd-panel.h"
+#include "views/gtd-list-selector-panel.h"
#include "gtd-application.h"
#include "gtd-enum-types.h"
#include "gtd-task-list-view.h"
@@ -34,32 +35,13 @@
typedef struct
{
- GtkWidget *action_bar;
- GtkButton *back_button;
GtkWidget *cancel_selection_button;
- GtkColorButton *color_button;
GtkWidget *gear_menu_button;
GtkHeaderBar *headerbar;
- GtkFlowBox *lists_flowbox;
- GtkStack *main_stack;
- GtkWidget *new_list_button;
- GtkWidget *new_list_popover;
GtdNotificationWidget *notification_widget;
- GtkWidget *remove_button;
- GtkWidget *rename_button;
- GtkSearchBar *search_bar;
- GtkToggleButton *search_button;
- GtkSearchEntry *search_entry;
- GtkWidget *select_button;
GtkStack *stack;
GtkStackSwitcher *stack_switcher;
GtdProviderDialog *provider_dialog;
- GtdTaskListView *list_view;
-
- /* rename popover */
- GtkWidget *rename_entry;
- GtkWidget *rename_popover;
- GtkWidget *save_rename_button;
/* mode */
GtdWindowMode mode;
@@ -81,10 +63,6 @@ struct _GtdWindow
#define SAVE_GEOMETRY_ID_TIMEOUT 100 /* ms */
-static void gtd_window__create_new_list (GSimpleAction *simple,
- GVariant *parameter,
- gpointer user_data);
-
static void gtd_window__change_storage_action (GSimpleAction *simple,
GVariant *parameter,
gpointer user_data);
@@ -93,7 +71,6 @@ G_DEFINE_TYPE_WITH_PRIVATE (GtdWindow, gtd_window, GTK_TYPE_APPLICATION_WINDOW)
static const GActionEntry gtd_window_entries[] = {
{ "change-storage", gtd_window__change_storage_action },
- { "new-list", gtd_window__create_new_list }
};
enum {
@@ -302,224 +279,14 @@ gtd_window__save_geometry (gpointer user_data)
return FALSE;
}
-static GtdTaskListItem*
-get_selected_list (GtdWindow *window)
-{
- GtdWindowPrivate *priv;
- GtdTaskListItem *item;
- GList *children;
- GList *l;
-
- priv = window->priv;
- item = NULL;
-
- /* Retrieve the only selected task list */
- children = gtk_container_get_children (GTK_CONTAINER (priv->lists_flowbox));
-
- for (l = children; l != NULL; l = l->next)
- {
- if (gtd_task_list_item_get_selected (l->data))
- {
- item = l->data;
- break;
- }
- }
-
- g_list_free (children);
-
- return item;
-}
-
-static void
-gtd_window__remove_button_clicked (GtdWindow *window)
-{
- GtdWindowPrivate *priv;
- GtkWidget *dialog;
- GtkWidget *button;
- GList *children;
- GList *l;
- gint response;
-
- priv = window->priv;
- dialog = gtk_message_dialog_new (GTK_WINDOW (window),
- GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT |
GTK_DIALOG_USE_HEADER_BAR,
- GTK_MESSAGE_QUESTION,
- GTK_BUTTONS_NONE,
- _("Remove the selected task lists?"));
-
- gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
- _("Once removed, the task lists cannot be recovered."));
-
- /* Focus the Cancel button by default */
- gtk_dialog_add_button (GTK_DIALOG (dialog),
- _("Cancel"),
- GTK_RESPONSE_CANCEL);
-
- button = gtk_dialog_get_widget_for_response (GTK_DIALOG (dialog), GTK_RESPONSE_CANCEL);
- gtk_widget_grab_focus (button);
-
- /* Make the Remove button visually destructive */
- gtk_dialog_add_button (GTK_DIALOG (dialog),
- _("Remove task lists"),
- GTK_RESPONSE_ACCEPT);
-
- button = gtk_dialog_get_widget_for_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
- gtk_style_context_add_class (gtk_widget_get_style_context (button), "destructive-action");
-
- response = gtk_dialog_run (GTK_DIALOG (dialog));
-
- /* Remove selected lists */
- if (response == GTK_RESPONSE_ACCEPT)
- {
- children = gtk_container_get_children (GTK_CONTAINER (priv->lists_flowbox));
-
- for (l = children; l != NULL; l = l->next)
- {
- if (gtd_task_list_item_get_selected (l->data))
- {
- GtdTaskList *list;
-
- list = gtd_task_list_item_get_list (l->data);
-
- if (gtd_task_list_is_removable (list))
- gtd_manager_remove_task_list (priv->manager, list);
- }
- }
-
- g_list_free (children);
- }
-
- gtk_widget_destroy (dialog);
-
- /* After removing the lists, exit SELECTION mode */
- gtd_window_set_mode (window, GTD_WINDOW_MODE_NORMAL);
-}
-
-static void
-gtd_window__rename_button_clicked (GtdWindow *window)
-{
- GtdWindowPrivate *priv;
- GtdTaskListItem *item;
-
- priv = window->priv;
- item = get_selected_list (window);
-
- if (item)
- {
- GtdTaskList *list;
-
- list = gtd_task_list_item_get_list (item);
-
- gtk_popover_set_relative_to (GTK_POPOVER (priv->rename_popover), GTK_WIDGET (item));
- gtk_entry_set_text (GTK_ENTRY (priv->rename_entry), gtd_task_list_get_name (list));
- gtk_widget_show (priv->rename_popover);
-
- gtk_widget_grab_focus (priv->rename_entry);
- }
-}
-
-static void
-gtd_window__rename_entry_text_changed (GObject *object,
- GParamSpec *pspec,
- GtdWindow *window)
-{
- gtk_widget_set_sensitive (window->priv->save_rename_button,
- gtk_entry_get_text_length (GTK_ENTRY (object)) > 0);
-}
-
-static void
-gtd_window__rename_task_list (GtdWindow *window)
-{
- GtdWindowPrivate *priv;
- GtdTaskListItem *item;
-
- priv = window->priv;
-
- /*
- * If the save_rename_button is insensitive, the list name is
- * empty and cannot be saved.
- */
- if (!gtk_widget_get_sensitive (priv->save_rename_button))
- return;
-
- item = get_selected_list (window);
-
- if (item)
- {
- GtdTaskList *list;
-
- list = gtd_task_list_item_get_list (item);
-
- gtd_task_list_set_name (list, gtk_entry_get_text (GTK_ENTRY (priv->rename_entry)));
- gtk_flow_box_invalidate_sort (GTK_FLOW_BOX (priv->lists_flowbox));
- gtd_window_set_mode (window, GTD_WINDOW_MODE_NORMAL);
-
- gtk_widget_hide (priv->rename_popover);
- }
-}
-
-static void
-gtd_window__stack_visible_child_cb (GtdWindow *window)
-{
- GtdWindowPrivate *priv;
- gboolean is_list_view;
-
- priv = window->priv;
- is_list_view = g_strcmp0 (gtk_stack_get_visible_child_name (priv->main_stack), "overview") == 0 &&
- g_strcmp0 (gtk_stack_get_visible_child_name (priv->stack), "lists") == 0;
-
- 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
-update_action_bar_buttons (GtdWindow *window)
-{
- GtdWindowPrivate *priv;
- GList *children;
- GList *l;
- gboolean all_lists_removable;
- gint selected_lists;
-
- priv = window->priv;
- children = gtk_container_get_children (GTK_CONTAINER (priv->lists_flowbox));
- selected_lists = 0;
- all_lists_removable = TRUE;
-
- for (l = children; l != NULL; l = l->next)
- {
- GtdTaskList *list;
-
- list = gtd_task_list_item_get_list (l->data);
-
- if (gtd_task_list_item_get_selected (l->data))
- {
- selected_lists++;
-
- if (!gtd_task_list_is_removable (list))
- all_lists_removable = FALSE;
- }
- }
-
- gtk_widget_set_sensitive (priv->remove_button, selected_lists > 0 && all_lists_removable);
- gtk_widget_set_sensitive (priv->rename_button, selected_lists == 1);
-}
-
-static void
-gtd_window__select_button_toggled (GtkToggleButton *button,
- GtdWindow *window)
-{
- gtd_window_set_mode (window, gtk_toggle_button_get_active (button) ? GTD_WINDOW_MODE_SELECTION :
GTD_WINDOW_MODE_NORMAL);
-}
-
static void
gtd_window__cancel_selection_button_clicked (GtkWidget *button,
GtdWindow *window)
{
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (window->priv->select_button), FALSE);
+ gtd_window_set_mode (window, GTD_WINDOW_MODE_NORMAL);
}
+/*
static void
gtd_window__create_new_list (GSimpleAction *simple,
GVariant *parameter,
@@ -533,6 +300,7 @@ gtd_window__create_new_list (GSimpleAction *simple,
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->new_list_button), TRUE);
}
+ */
static void
gtd_window__change_storage_action (GSimpleAction *simple,
@@ -549,113 +317,6 @@ gtd_window__change_storage_action (GSimpleAction *simple,
}
static void
-gtd_window__list_color_set (GtkColorChooser *button,
- gpointer user_data)
-{
- GtdWindowPrivate *priv = GTD_WINDOW (user_data)->priv;
- GtdTaskList *list;
- GdkRGBA new_color;
-
- g_return_if_fail (GTD_IS_WINDOW (user_data));
- g_return_if_fail (gtd_task_list_view_get_task_list (priv->list_view));
-
- list = gtd_task_list_view_get_task_list (priv->list_view);
-
- g_debug ("%s: %s: %s",
- G_STRFUNC,
- _("Setting new color for task list"),
- gtd_task_list_get_name (list));
-
- gtk_color_chooser_get_rgba (button, &new_color);
- gtd_task_list_set_color (list, &new_color);
-
- gtd_manager_save_task_list (priv->manager, list);
-}
-
-static gboolean
-gtd_window__on_key_press_event (GtkWidget *widget,
- GdkEvent *event,
- GtkSearchBar *bar)
-{
- GtdWindowPrivate *priv;
-
- g_return_val_if_fail (GTD_IS_WINDOW (widget), TRUE);
-
- priv = GTD_WINDOW (widget)->priv;
-
- if (g_strcmp0 (gtk_stack_get_visible_child_name (GTK_STACK (priv->main_stack)), "overview") == 0 &&
- g_strcmp0 (gtk_stack_get_visible_child_name (GTK_STACK (priv->stack)), "lists") == 0)
- {
- return gtk_search_bar_handle_event (bar, event);
- }
-
- return FALSE;
-}
-
-static gint
-gtd_window__flowbox_sort_func (GtdTaskListItem *a,
- GtdTaskListItem *b,
- gpointer user_data)
-{
- GtdProvider *p1;
- GtdProvider *p2;
- GtdTaskList *l1;
- GtdTaskList *l2;
- gint retval = 0;
-
- l1 = gtd_task_list_item_get_list (a);
- p1 = gtd_task_list_get_provider (l1);
-
- l2 = gtd_task_list_item_get_list (b);
- p2 = gtd_task_list_get_provider (l2);
-
- retval = g_strcmp0 (gtd_provider_get_description (p1), gtd_provider_get_description (p2));
-
- if (retval != 0)
- return retval;
-
- return g_strcmp0 (gtd_task_list_get_name (l1), gtd_task_list_get_name (l2));
-}
-
-static gboolean
-gtd_window__flowbox_filter_func (GtdTaskListItem *item,
- GtdWindow *window)
-{
- GtdWindowPrivate *priv;
- GtdTaskList *list;
- gboolean return_value;
- gchar *search_folded;
- gchar *list_name_folded;
- gchar *haystack;
-
- g_return_val_if_fail (GTD_IS_WINDOW (window), FALSE);
-
- priv = window->priv;
- list = gtd_task_list_item_get_list (item);
- haystack = NULL;
- search_folded = g_utf8_casefold (gtk_entry_get_text (GTK_ENTRY (priv->search_entry)), -1);
- list_name_folded = g_utf8_casefold (gtd_task_list_get_name (list), -1);
-
- if (!search_folded || search_folded[0] == '\0')
- {
- return_value = TRUE;
- goto out;
- }
-
- haystack = g_strstr_len (list_name_folded,
- -1,
- search_folded);
-
- return_value = (haystack != NULL);
-
-out:
- g_free (search_folded);
- g_free (list_name_folded);
-
- return return_value;
-}
-
-static void
gtd_window__manager_ready_changed (GObject *source,
GParamSpec *spec,
gpointer user_data)
@@ -675,117 +336,6 @@ gtd_window__manager_ready_changed (GObject *source,
}
static void
-gtd_window__back_button_clicked (GtkButton *button,
- gpointer user_data)
-{
- GtdWindowPrivate *priv = GTD_WINDOW (user_data)->priv;
-
- g_return_if_fail (GTD_IS_WINDOW (user_data));
-
- gtk_stack_set_visible_child_name (priv->main_stack, "overview");
- gtk_header_bar_set_custom_title (priv->headerbar, GTK_WIDGET (priv->stack_switcher));
- gtk_header_bar_set_title (priv->headerbar, _("To Do"));
- gtk_widget_hide (GTK_WIDGET (priv->back_button));
- gtk_widget_hide (GTK_WIDGET (priv->color_button));
-}
-
-static void
-gtd_window__list_selected (GtkFlowBox *flowbox,
- GtdTaskListItem *item,
- gpointer user_data)
-{
- GtdWindowPrivate *priv = GTD_WINDOW (user_data)->priv;
- GtdProvider *provider;
- GtdTaskList *list;
- GdkRGBA *list_color;
-
- g_return_if_fail (GTD_IS_WINDOW (user_data));
- g_return_if_fail (GTD_IS_TASK_LIST_ITEM (item));
-
- switch (priv->mode)
- {
- case GTD_WINDOW_MODE_SELECTION:
- gtd_task_list_item_set_selected (item, !gtd_task_list_item_get_selected (item));
- update_action_bar_buttons (GTD_WINDOW (user_data));
- break;
-
- case GTD_WINDOW_MODE_NORMAL:
- list = gtd_task_list_item_get_list (item);
- provider = gtd_task_list_get_provider (list);
- list_color = gtd_task_list_get_color (list);
-
- g_signal_handlers_block_by_func (priv->color_button,
- gtd_window__list_color_set,
- user_data);
-
- gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER (priv->color_button), list_color);
-
- gtk_stack_set_visible_child_name (priv->main_stack, "tasks");
- gtk_header_bar_set_title (priv->headerbar, gtd_task_list_get_name (list));
- gtk_header_bar_set_subtitle (priv->headerbar, gtd_provider_get_description (provider));
- gtk_header_bar_set_custom_title (priv->headerbar, NULL);
- gtk_search_bar_set_search_mode (priv->search_bar, FALSE);
- gtd_task_list_view_set_task_list (priv->list_view, list);
- gtd_task_list_view_set_show_completed (priv->list_view, FALSE);
- gtk_widget_show (GTK_WIDGET (priv->back_button));
- gtk_widget_show (GTK_WIDGET (priv->color_button));
-
- g_signal_handlers_unblock_by_func (priv->color_button,
- gtd_window__list_color_set,
- user_data);
-
- gdk_rgba_free (list_color);
- break;
-
- default:
- g_assert_not_reached ();
- }
-}
-
-static void
-gtd_window__list_added (GtdManager *manager,
- GtdTaskList *list,
- gpointer user_data)
-{
- GtdWindowPrivate *priv = GTD_WINDOW (user_data)->priv;
- GtkWidget *item;
-
- item = gtd_task_list_item_new (list);
-
- g_object_bind_property (user_data,
- "mode",
- item,
- "mode",
- G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
-
- gtk_widget_show (item);
-
- gtk_flow_box_insert (priv->lists_flowbox,
- item,
- -1);
-}
-
-static void
-gtd_window__list_removed (GtdManager *manager,
- GtdTaskList *list,
- gpointer user_data)
-{
- GtdWindowPrivate *priv = GTD_WINDOW (user_data)->priv;
- GList *children;
- GList *l;
-
- children = gtk_container_get_children (GTK_CONTAINER (priv->lists_flowbox));
-
- for (l = children; l != NULL; l = l->next)
- {
- if (gtd_task_list_item_get_list (l->data) == list)
- gtk_widget_destroy (l->data);
- }
-
- g_list_free (children);
-}
-
-static void
gtd_window__show_error_message (GtdManager *manager,
const gchar *primary_text,
const gchar *secondary_text,
@@ -880,27 +430,6 @@ gtd_window_constructed (GObject *object)
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,
- NULL);
-
- gtk_flow_box_set_filter_func (priv->lists_flowbox,
- (GtkFlowBoxFilterFunc) gtd_window__flowbox_filter_func,
- object,
- NULL);
-
- g_object_bind_property (object,
- "manager",
- priv->new_list_popover,
- "manager",
- G_BINDING_DEFAULT);
- g_object_bind_property (object,
- "manager",
- priv->provider_dialog,
- "manager",
- G_BINDING_DEFAULT);
}
GtkWidget*
@@ -961,14 +490,6 @@ gtd_window_set_property (GObject *object,
G_CALLBACK (gtd_window__manager_ready_changed),
self);
g_signal_connect (self->priv->manager,
- "list-added",
- G_CALLBACK (gtd_window__list_added),
- self);
- g_signal_connect (self->priv->manager,
- "list-removed",
- G_CALLBACK (gtd_window__list_removed),
- self);
- g_signal_connect (self->priv->manager,
"panel-added",
G_CALLBACK (gtd_window__panel_added),
self);
@@ -993,17 +514,6 @@ gtd_window_set_property (GObject *object,
g_list_free (lists);
- /* Add already loaded lists */
- lists = gtd_manager_get_task_lists (self->priv->manager);
-
- for (l = lists; l != NULL; l = l->next)
- {
- gtd_window__list_added (self->priv->manager,
- l->data,
- object);
- }
-
- g_list_free (lists);
g_object_notify (object, "manager");
break;
@@ -1061,47 +571,22 @@ gtd_window_class_init (GtdWindowClass *klass)
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/todo/ui/window.ui");
- gtk_widget_class_bind_template_child_private (widget_class, GtdWindow, action_bar);
- 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);
- gtk_widget_class_bind_template_child_private (widget_class, GtdWindow, main_stack);
- gtk_widget_class_bind_template_child_private (widget_class, GtdWindow, new_list_button);
- gtk_widget_class_bind_template_child_private (widget_class, GtdWindow, new_list_popover);
gtk_widget_class_bind_template_child_private (widget_class, GtdWindow, notification_widget);
gtk_widget_class_bind_template_child_private (widget_class, GtdWindow, provider_dialog);
- gtk_widget_class_bind_template_child_private (widget_class, GtdWindow, remove_button);
- gtk_widget_class_bind_template_child_private (widget_class, GtdWindow, rename_button);
- gtk_widget_class_bind_template_child_private (widget_class, GtdWindow, rename_entry);
- gtk_widget_class_bind_template_child_private (widget_class, GtdWindow, rename_popover);
- gtk_widget_class_bind_template_child_private (widget_class, GtdWindow, save_rename_button);
gtk_widget_class_bind_template_child_private (widget_class, GtdWindow, stack);
- gtk_widget_class_bind_template_child_private (widget_class, GtdWindow, search_bar);
- gtk_widget_class_bind_template_child_private (widget_class, GtdWindow, search_button);
- gtk_widget_class_bind_template_child_private (widget_class, GtdWindow, search_entry);
- gtk_widget_class_bind_template_child_private (widget_class, GtdWindow, select_button);
gtk_widget_class_bind_template_child_private (widget_class, GtdWindow, stack_switcher);
- gtk_widget_class_bind_template_callback (widget_class, gtd_window__back_button_clicked);
gtk_widget_class_bind_template_callback (widget_class, gtd_window__cancel_selection_button_clicked);
- gtk_widget_class_bind_template_callback (widget_class, gtd_window__list_color_set);
- gtk_widget_class_bind_template_callback (widget_class, gtd_window__list_selected);
- gtk_widget_class_bind_template_callback (widget_class, gtd_window__on_key_press_event);
- gtk_widget_class_bind_template_callback (widget_class, gtd_window__remove_button_clicked);
- gtk_widget_class_bind_template_callback (widget_class, gtd_window__rename_button_clicked);
- gtk_widget_class_bind_template_callback (widget_class, gtd_window__rename_entry_text_changed);
- gtk_widget_class_bind_template_callback (widget_class, gtd_window__rename_task_list);
- gtk_widget_class_bind_template_callback (widget_class, gtd_window__select_button_toggled);
- gtk_widget_class_bind_template_callback (widget_class, gtd_window__stack_visible_child_cb);
}
static void
gtd_window_init (GtdWindow *self)
{
+ GtkWidget *panel;
+
self->priv = gtd_window_get_instance_private (self);
self->priv->loading_notification = gtd_notification_new (_("Loading your task lists…"), 0);
@@ -1114,6 +599,19 @@ gtd_window_init (GtdWindow *self)
self);
gtk_widget_init_template (GTK_WIDGET (self));
+
+ /* Add the default 'Lists' panel before everything else */
+ panel = gtd_list_selector_panel_new ();
+
+ gtd_window__panel_added (gtd_manager_get_default (),
+ GTD_PANEL (panel),
+ self);
+
+ g_object_bind_property (self,
+ "mode",
+ panel,
+ "mode",
+ G_BINDING_BIDIRECTIONAL);
}
/**
@@ -1220,11 +718,7 @@ gtd_window_set_mode (GtdWindow *window,
context = gtk_widget_get_style_context (GTK_WIDGET (priv->headerbar));
is_selection_mode = (mode == GTD_WINDOW_MODE_SELECTION);
- gtk_widget_set_visible (priv->select_button, !is_selection_mode);
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->select_button), is_selection_mode);
gtk_widget_set_visible (priv->cancel_selection_button, is_selection_mode);
- gtk_widget_set_visible (GTK_WIDGET (priv->new_list_button), !is_selection_mode);
- gtk_widget_set_visible (GTK_WIDGET (priv->action_bar), is_selection_mode);
gtk_header_bar_set_show_close_button (priv->headerbar, !is_selection_mode);
gtk_header_bar_set_subtitle (priv->headerbar, NULL);
@@ -1233,16 +727,9 @@ gtd_window_set_mode (GtdWindow *window,
gtk_style_context_add_class (context, "selection-mode");
gtk_header_bar_set_custom_title (priv->headerbar, NULL);
gtk_header_bar_set_title (priv->headerbar, _("Click a task list to select"));
-
- update_action_bar_buttons (window);
}
else
{
- /* Unselect all items when leaving selection mode */
- gtk_container_foreach (GTK_CONTAINER (priv->lists_flowbox),
- (GtkCallback) gtd_task_list_item_set_selected,
- FALSE);
-
gtk_style_context_remove_class (context, "selection-mode");
gtk_header_bar_set_custom_title (priv->headerbar, GTK_WIDGET (priv->stack_switcher));
gtk_header_bar_set_title (priv->headerbar, _("To Do"));
diff --git a/src/views/gtd-list-selector-grid.c b/src/views/gtd-list-selector-grid.c
new file mode 100644
index 0000000..0a0f816
--- /dev/null
+++ b/src/views/gtd-list-selector-grid.c
@@ -0,0 +1,413 @@
+/* gtd-list-selector-grid.c
+ *
+ * Copyright (C) 2015 Georges Basile Stavracas Neto <georges stavracas gmail com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "interfaces/gtd-provider.h"
+#include "gtd-list-selector.h"
+#include "gtd-list-selector-grid.h"
+#include "gtd-manager.h"
+#include "gtd-task-list.h"
+#include "gtd-task-list-item.h"
+
+struct _GtdListSelectorGrid
+{
+ GtkFlowBox parent;
+
+ gchar *search_query;
+
+ GtdWindowMode mode;
+};
+
+static void gtd_list_selector_iface_init (GtdListSelectorInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (GtdListSelectorGrid, gtd_list_selector_grid, GTK_TYPE_FLOW_BOX,
+ 0,
+ G_IMPLEMENT_INTERFACE (GTD_TYPE_LIST_SELECTOR,
+ gtd_list_selector_iface_init))
+
+enum {
+ PROP_0,
+ PROP_MODE,
+ PROP_SEARCH_QUERY,
+ N_PROPS
+};
+
+static void
+gtd_list_selector_grid_list_added (GtdManager *manager,
+ GtdTaskList *list,
+ GtdListSelectorGrid *selector)
+{
+ GtkWidget *item;
+
+ item = gtd_task_list_item_new (list);
+
+ g_object_bind_property (selector,
+ "mode",
+ item,
+ "mode",
+ G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
+
+ gtk_widget_show (item);
+
+ gtk_flow_box_insert (GTK_FLOW_BOX (selector),
+ item,
+ -1);
+}
+
+static void
+gtd_list_selector_grid_list_removed (GtdManager *manager,
+ GtdTaskList *list,
+ GtdListSelectorGrid *selector)
+{
+ GList *children;
+ GList *l;
+
+ children = gtk_container_get_children (GTK_CONTAINER (selector));
+
+ for (l = children; l != NULL; l = l->next)
+ {
+ if (gtd_task_list_item_get_list (l->data) == list)
+ gtk_widget_destroy (l->data);
+ }
+
+ g_list_free (children);
+}
+
+
+static gint
+gtd_list_selector_grid_sort_func (GtdTaskListItem *a,
+ GtdTaskListItem *b,
+ GtdListSelectorGrid *selector)
+{
+ GtdProvider *p1;
+ GtdProvider *p2;
+ GtdTaskList *l1;
+ GtdTaskList *l2;
+ gint retval = 0;
+
+ l1 = gtd_task_list_item_get_list (a);
+ p1 = gtd_task_list_get_provider (l1);
+
+ l2 = gtd_task_list_item_get_list (b);
+ p2 = gtd_task_list_get_provider (l2);
+
+ retval = g_strcmp0 (gtd_provider_get_description (p1), gtd_provider_get_description (p2));
+
+ if (retval != 0)
+ return retval;
+
+ return g_strcmp0 (gtd_task_list_get_name (l1), gtd_task_list_get_name (l2));
+}
+
+static gboolean
+gtd_list_selector_grid_filter_func (GtdTaskListItem *item,
+ GtdListSelectorGrid *selector)
+{
+ GtdTaskList *list;
+ gboolean return_value;
+ gchar *search_folded;
+ gchar *list_name_folded;
+ gchar *haystack;
+
+ /*
+ * When no search query is set, we obviously don't
+ * filter out anything.
+ */
+ if (!selector->search_query)
+ return TRUE;
+
+ list = gtd_task_list_item_get_list (item);
+ haystack = NULL;
+ search_folded = g_utf8_casefold (selector->search_query, -1);
+ list_name_folded = g_utf8_casefold (gtd_task_list_get_name (list), -1);
+
+ if (!search_folded || search_folded[0] == '\0')
+ {
+ return_value = TRUE;
+ goto out;
+ }
+
+ haystack = g_strstr_len (list_name_folded,
+ -1,
+ search_folded);
+
+ return_value = (haystack != NULL);
+
+out:
+ g_free (search_folded);
+ g_free (list_name_folded);
+
+ return return_value;
+}
+
+/******************************
+ * GtdListSelector iface init *
+ ******************************/
+static GtdWindowMode
+gtd_list_selector_grid_get_mode (GtdListSelector *selector)
+{
+ g_return_val_if_fail (GTD_IS_LIST_SELECTOR_GRID (selector), GTD_WINDOW_MODE_NORMAL);
+
+ return GTD_LIST_SELECTOR_GRID (selector)->mode;
+}
+
+static void
+gtd_list_selector_grid_set_mode (GtdListSelector *selector,
+ GtdWindowMode mode)
+{
+ GtdListSelectorGrid *self;
+
+ g_return_if_fail (GTD_IS_LIST_SELECTOR_GRID (selector));
+
+ self = GTD_LIST_SELECTOR_GRID (selector);
+
+ if (self->mode != mode)
+ {
+ self->mode = mode;
+
+ /* Unselect all items when leaving selection mode */
+ if (mode != GTD_WINDOW_MODE_SELECTION)
+ {
+ gtk_container_foreach (GTK_CONTAINER (self),
+ (GtkCallback) gtd_task_list_item_set_selected,
+ FALSE);
+ }
+
+
+ g_object_notify (G_OBJECT (self), "mode");
+ }
+}
+
+static const gchar*
+gtd_list_selector_grid_get_search_query (GtdListSelector *selector)
+{
+ g_return_val_if_fail (GTD_IS_LIST_SELECTOR_GRID (selector), NULL);
+
+ return GTD_LIST_SELECTOR_GRID (selector)->search_query;
+}
+
+static void
+gtd_list_selector_grid_set_search_query (GtdListSelector *selector,
+ const gchar *search_query)
+{
+ GtdListSelectorGrid *self;
+
+ g_return_if_fail (GTD_IS_LIST_SELECTOR_GRID (selector));
+
+ self = GTD_LIST_SELECTOR_GRID (selector);
+
+ if (g_strcmp0 (self->search_query, search_query) != 0)
+ {
+ g_clear_pointer (&self->search_query, g_free);
+ self->search_query = g_strdup (search_query);
+
+ gtk_flow_box_invalidate_filter (GTK_FLOW_BOX (self));
+
+ g_object_notify (G_OBJECT (self), "search-query");
+ }
+}
+
+static GList*
+gtd_list_selector_grid_get_selected_lists (GtdListSelector *selector)
+{
+ GList *selected;
+ GList *children;
+ GList *l;
+
+ /* Retrieve the only selected task list */
+ children = gtk_container_get_children (GTK_CONTAINER (selector));
+ selected = NULL;
+
+ for (l = children; l != NULL; l = l->next)
+ {
+ if (gtd_task_list_item_get_selected (l->data))
+ selected = g_list_append (selected, l->data);
+ }
+
+ g_list_free (children);
+
+ return selected;
+}
+
+static void
+gtd_list_selector_iface_init (GtdListSelectorInterface *iface)
+{
+ iface->get_mode = gtd_list_selector_grid_get_mode;
+ iface->set_mode = gtd_list_selector_grid_set_mode;
+ iface->get_search_query = gtd_list_selector_grid_get_search_query;
+ iface->set_search_query = gtd_list_selector_grid_set_search_query;
+ iface->get_selected_lists = gtd_list_selector_grid_get_selected_lists;
+}
+
+static void
+gtd_list_selector_grid_finalize (GObject *object)
+{
+ GtdListSelectorGrid *self = (GtdListSelectorGrid *)object;
+
+ g_clear_pointer (&self->search_query, g_free);
+
+ G_OBJECT_CLASS (gtd_list_selector_grid_parent_class)->finalize (object);
+}
+
+static void
+gtd_list_selector_grid_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GtdListSelectorGrid *self = GTD_LIST_SELECTOR_GRID (object);
+
+ switch (prop_id)
+ {
+ case PROP_MODE:
+ g_value_set_enum (value, self->mode);
+ break;
+
+ case PROP_SEARCH_QUERY:
+ g_value_set_string (value, self->search_query);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gtd_list_selector_grid_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GtdListSelector *self = GTD_LIST_SELECTOR (object);
+
+ switch (prop_id)
+ {
+ case PROP_MODE:
+ gtd_list_selector_set_mode (self, g_value_get_enum (value));
+ break;
+
+ case PROP_SEARCH_QUERY:
+ gtd_list_selector_set_search_query (self, g_value_get_string (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gtd_list_selector_grid_child_activated (GtkFlowBox *flowbox,
+ GtkFlowBoxChild *child)
+{
+ GtdTaskListItem *item;
+
+ if (!GTD_IS_TASK_LIST_ITEM (child))
+ return;
+
+ item = GTD_TASK_LIST_ITEM (child);
+
+ gtd_task_list_item_set_selected (item, !gtd_task_list_item_get_selected (item));
+
+ g_signal_emit_by_name (flowbox, "list-selected", gtd_task_list_item_get_list (item));
+}
+
+static void
+gtd_list_selector_grid_class_init (GtdListSelectorGridClass *klass)
+{
+ GtkFlowBoxClass *flowbox_class = GTK_FLOW_BOX_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ flowbox_class->child_activated = gtd_list_selector_grid_child_activated;
+
+ object_class->finalize = gtd_list_selector_grid_finalize;
+ object_class->get_property = gtd_list_selector_grid_get_property;
+ object_class->set_property = gtd_list_selector_grid_set_property;
+
+ g_object_class_override_property (object_class,
+ PROP_MODE,
+ "mode");
+
+ g_object_class_override_property (object_class,
+ PROP_SEARCH_QUERY,
+ "search-query");
+}
+
+static void
+gtd_list_selector_grid_init (GtdListSelectorGrid *self)
+{
+ GtdManager *manager;
+ GtkFlowBox *flowbox;
+ GtkWidget *widget;
+ GList *lists;
+ GList *l;
+
+ manager = gtd_manager_get_default ();
+
+ g_signal_connect (manager,
+ "list-added",
+ G_CALLBACK (gtd_list_selector_grid_list_added),
+ self);
+ g_signal_connect (manager,
+ "list-removed",
+ G_CALLBACK (gtd_list_selector_grid_list_removed),
+ self);
+
+ /* Add already loaded lists */
+ lists = gtd_manager_get_task_lists (manager);
+
+ for (l = lists; l != NULL; l = l->next)
+ {
+ gtd_list_selector_grid_list_added (manager,
+ l->data,
+ self);
+ }
+
+ g_list_free (lists);
+
+ /* Setup filter and sorting functions */
+ gtk_flow_box_set_sort_func (GTK_FLOW_BOX (self),
+ (GtkFlowBoxSortFunc) gtd_list_selector_grid_sort_func,
+ NULL,
+ NULL);
+
+ gtk_flow_box_set_filter_func (GTK_FLOW_BOX (self),
+ (GtkFlowBoxFilterFunc) gtd_list_selector_grid_filter_func,
+ self,
+ NULL);
+ /* Setup some properties */
+ widget = GTK_WIDGET (self);
+ flowbox = GTK_FLOW_BOX (self);
+
+ gtk_flow_box_set_max_children_per_line (flowbox, 100);
+ gtk_flow_box_set_selection_mode (flowbox, GTK_SELECTION_NONE);
+ gtk_flow_box_set_column_spacing (flowbox, 12);
+ gtk_flow_box_set_row_spacing (flowbox, 12);
+ gtk_flow_box_set_homogeneous (flowbox, TRUE);
+ gtk_container_set_border_width (GTK_CONTAINER (self), 12);
+ gtk_widget_set_hexpand (widget, TRUE);
+ gtk_widget_set_vexpand (widget, TRUE);
+ gtk_widget_set_halign (widget, GTK_ALIGN_START);
+ gtk_widget_set_valign (widget, GTK_ALIGN_START);
+ gtk_widget_show_all (widget);
+}
+
+GtkWidget*
+gtd_list_selector_grid_new (void)
+{
+ return g_object_new (GTD_TYPE_LIST_SELECTOR_GRID, NULL);
+}
+
diff --git a/src/views/gtd-list-selector-grid.h b/src/views/gtd-list-selector-grid.h
new file mode 100644
index 0000000..4488b55
--- /dev/null
+++ b/src/views/gtd-list-selector-grid.h
@@ -0,0 +1,36 @@
+/* gtd-list-selector-grid.h
+ *
+ * Copyright (C) 2015 Georges Basile Stavracas Neto <georges stavracas gmail com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GTD_LIST_SELECTOR_GRID_H
+#define GTD_LIST_SELECTOR_GRID_H
+
+#include <glib-object.h>
+#include <glib.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GTD_TYPE_LIST_SELECTOR_GRID (gtd_list_selector_grid_get_type())
+
+G_DECLARE_FINAL_TYPE (GtdListSelectorGrid, gtd_list_selector_grid, GTD, LIST_SELECTOR_GRID, GtkFlowBox)
+
+GtkWidget* gtd_list_selector_grid_new (void);
+
+G_END_DECLS
+
+#endif /* GTD_LIST_SELECTOR_GRID_H */
diff --git a/src/views/gtd-list-selector-panel.c b/src/views/gtd-list-selector-panel.c
new file mode 100644
index 0000000..247f9e4
--- /dev/null
+++ b/src/views/gtd-list-selector-panel.c
@@ -0,0 +1,556 @@
+/* gtd-list-selector-panel.c
+ *
+ * Copyright (C) 2015 Georges Basile Stavracas Neto <georges stavracas gmail com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "interfaces/gtd-panel.h"
+#include "gtd-enum-types.h"
+#include "gtd-list-selector.h"
+#include "gtd-list-selector-grid.h"
+#include "gtd-list-selector-panel.h"
+#include "gtd-manager.h"
+#include "gtd-task-list.h"
+#include "gtd-task-list-item.h"
+#include "gtd-task-list-view.h"
+#include "gtd-window.h"
+
+#include <glib/gi18n.h>
+
+struct _GtdListSelectorPanel
+{
+ GtkBox parent;
+
+ GtkWidget *stack;
+ GtkWidget *tasklist_view;
+
+ GtkWidget *grid_selector;
+
+ /* Action bar widgets */
+ GtkWidget *actionbar;
+ GtkWidget *delete_button;
+ GtkWidget *rename_button;
+
+ /* Header widgets */
+ GtkWidget *back_button;
+ GtkWidget *color_button;
+ GtkWidget *new_list_button;
+ GtkWidget *search_button;
+ GtkWidget *selection_button;
+ GtkWidget *view_button;
+
+ /* Rename widgets */
+ GtkWidget *rename_entry;
+ GtkWidget *rename_popover;
+ GtkWidget *save_rename_button;
+
+ /* Search bar widgets */
+ GtkWidget *search_bar;
+
+ GtdWindowMode mode;
+};
+
+static void gtd_panel_iface_init (GtdPanelInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (GtdListSelectorPanel, gtd_list_selector_panel, GTK_TYPE_STACK,
+ 0,
+ G_IMPLEMENT_INTERFACE (GTD_TYPE_PANEL,
+ gtd_panel_iface_init))
+
+enum {
+ PROP_0,
+ PROP_HEADER_WIDGETS,
+ PROP_MODE,
+ PROP_MENU,
+ PROP_NAME,
+ PROP_TITLE,
+ N_PROPS
+};
+
+
+static void
+gtd_list_selector_panel_select_button_toggled (GtkToggleButton *button,
+ GtdListSelectorPanel *panel)
+{
+ GtdWindowMode mode;
+ GtdWindow *window;
+
+ window = GTD_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (panel)));
+ mode = gtk_toggle_button_get_active (button) ? GTD_WINDOW_MODE_SELECTION : GTD_WINDOW_MODE_NORMAL;
+
+ gtd_window_set_mode (window, mode);
+}
+
+
+static gboolean
+gtd_list_selector_panel_on_key_press_event (GtdListSelectorPanel *panel,
+ GdkEvent *event,
+ GtkSearchBar *bar)
+{
+ if (g_strcmp0 (gtk_stack_get_visible_child_name (GTK_STACK (panel)), "lists") == 0)
+ {
+ return gtk_search_bar_handle_event (bar, event);
+ }
+
+ return FALSE;
+}
+
+static void
+gtd_list_selector_panel_list_color_set (GtkColorChooser *button,
+ GtdListSelectorPanel *panel)
+{
+ GtdTaskList *list;
+ GtdManager *manager;
+ GdkRGBA new_color;
+
+ manager = gtd_manager_get_default ();
+ list = gtd_task_list_view_get_task_list (GTD_TASK_LIST_VIEW (panel->tasklist_view));
+
+ g_debug ("%s: %s: %s",
+ G_STRFUNC,
+ _("Setting new color for task list"),
+ gtd_task_list_get_name (list));
+
+ gtk_color_chooser_get_rgba (button, &new_color);
+ gtd_task_list_set_color (list, &new_color);
+
+ gtd_manager_save_task_list (manager, list);
+}
+
+static void
+update_action_bar_buttons (GtdListSelectorPanel *panel)
+{
+ GList *selection;
+ GList *l;
+ gboolean all_lists_removable;
+ gint selected_lists;
+
+ selection = gtd_list_selector_get_selected_lists (GTD_LIST_SELECTOR (panel->grid_selector));
+ selected_lists = g_list_length (selection);
+ all_lists_removable = TRUE;
+
+ for (l = selection; l != NULL; l = l->next)
+ {
+ GtdTaskList *list;
+
+ list = gtd_task_list_item_get_list (l->data);
+
+ if (!gtd_task_list_is_removable (list))
+ {
+ all_lists_removable = FALSE;
+ break;
+ }
+ }
+
+ gtk_widget_set_sensitive (panel->delete_button, selected_lists > 0 && all_lists_removable);
+ gtk_widget_set_sensitive (panel->rename_button, selected_lists == 1);
+}
+
+static void
+gtd_list_selector_panel_list_selected (GtdListSelector *selector,
+ GtdTaskList *list,
+ GtdListSelectorPanel *panel)
+{
+ GtdWindow *window;
+ GdkRGBA *list_color;
+
+ window = GTD_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (panel)));
+
+ switch (gtd_window_get_mode (window))
+ {
+ case GTD_WINDOW_MODE_SELECTION:
+ update_action_bar_buttons (panel);
+ break;
+
+ case GTD_WINDOW_MODE_NORMAL:
+ list_color = gtd_task_list_get_color (list);
+
+ g_signal_handlers_block_by_func (panel->color_button,
+ gtd_list_selector_panel_list_color_set,
+ panel);
+
+ gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER (panel->color_button), list_color);
+
+ gtk_stack_set_visible_child_name (GTK_STACK (panel), "tasks");
+ gtk_search_bar_set_search_mode (GTK_SEARCH_BAR (panel->search_bar), FALSE);
+ gtd_task_list_view_set_task_list (GTD_TASK_LIST_VIEW (panel->tasklist_view), list);
+ gtd_task_list_view_set_show_completed (GTD_TASK_LIST_VIEW (panel->tasklist_view), FALSE);
+ gtk_widget_show (panel->back_button);
+ gtk_widget_show (panel->color_button);
+
+ g_signal_handlers_unblock_by_func (panel->color_button,
+ gtd_list_selector_panel_list_color_set,
+ panel);
+
+ gdk_rgba_free (list_color);
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+static void
+gtd_list_selector_panel_back_button_clicked (GtkButton *button,
+ GtdListSelectorPanel *panel)
+{
+ // TODO: add a way to set custom title on GtdWindow's headerbar
+ gtk_stack_set_visible_child_name (GTK_STACK (panel), "lists");
+ gtk_widget_hide (panel->back_button);
+ gtk_widget_hide (panel->color_button);
+}
+
+static void
+gtd_list_selector_panel_rename_entry_text_changed (GObject *object,
+ GParamSpec *pspec,
+ GtdListSelectorPanel *panel)
+{
+ gtk_widget_set_sensitive (panel->save_rename_button,
+ gtk_entry_get_text_length (GTK_ENTRY (object)) > 0);
+}
+
+static void
+gtd_list_selector_panel_rename_task_list (GtdListSelectorPanel *panel)
+{
+ GList *selection;
+
+ /*
+ * If the save_rename_button is insensitive, the list name is
+ * empty and cannot be saved.
+ */
+ if (!gtk_widget_get_sensitive (panel->save_rename_button))
+ return;
+
+ selection = gtd_list_selector_get_selected_lists (GTD_LIST_SELECTOR (panel->grid_selector));
+
+ if (selection && selection->data)
+ {
+ GtdTaskListItem *item;
+ GtdTaskList *list;
+ GtdWindow *window;
+
+ item = selection->data;
+ list = gtd_task_list_item_get_list (item);
+ window = GTD_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (panel)));
+
+ gtd_task_list_set_name (list, gtk_entry_get_text (GTK_ENTRY (panel->rename_entry)));
+ gtd_window_set_mode (window, GTD_WINDOW_MODE_NORMAL);
+
+ gtk_widget_hide (panel->rename_popover);
+ }
+
+ g_list_free (selection);
+}
+
+static void
+gtd_list_selector_panel_rename_button_clicked (GtdListSelectorPanel *panel)
+{
+ GList *selection;
+
+ selection = gtd_list_selector_get_selected_lists (GTD_LIST_SELECTOR (panel->grid_selector));
+
+ if (selection && selection->data)
+ {
+ GtdTaskListItem *item;
+ GtdTaskList *list;
+
+ item = selection->data;
+ list = gtd_task_list_item_get_list (item);
+
+ gtk_popover_set_relative_to (GTK_POPOVER (panel->rename_popover), GTK_WIDGET (item));
+ gtk_entry_set_text (GTK_ENTRY (panel->rename_entry), gtd_task_list_get_name (list));
+ gtk_widget_show (panel->rename_popover);
+
+ gtk_widget_grab_focus (panel->rename_entry);
+ }
+
+ g_list_free (selection);
+}
+
+static void
+gtd_list_selector_panel_delete_button_clicked (GtdListSelectorPanel *panel)
+{
+ GtkWindow *toplevel;
+ GtkWidget *dialog;
+ GtkWidget *button;
+ GList *children;
+ GList *l;
+ gint response;
+
+ toplevel = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (panel)));
+
+ dialog = gtk_message_dialog_new (toplevel,
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT |
GTK_DIALOG_USE_HEADER_BAR,
+ GTK_MESSAGE_QUESTION,
+ GTK_BUTTONS_NONE,
+ _("Remove the selected task lists?"));
+
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ _("Once removed, the task lists cannot be recovered."));
+
+ /* Focus the Cancel button by default */
+ gtk_dialog_add_button (GTK_DIALOG (dialog),
+ _("Cancel"),
+ GTK_RESPONSE_CANCEL);
+
+ button = gtk_dialog_get_widget_for_response (GTK_DIALOG (dialog), GTK_RESPONSE_CANCEL);
+ gtk_widget_grab_focus (button);
+
+ /* Make the Remove button visually destructive */
+ gtk_dialog_add_button (GTK_DIALOG (dialog),
+ _("Remove task lists"),
+ GTK_RESPONSE_ACCEPT);
+
+ button = gtk_dialog_get_widget_for_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
+ gtk_style_context_add_class (gtk_widget_get_style_context (button), "destructive-action");
+
+ response = gtk_dialog_run (GTK_DIALOG (dialog));
+
+ /* Remove selected lists */
+ if (response == GTK_RESPONSE_ACCEPT)
+ {
+ children = gtd_list_selector_get_selected_lists (GTD_LIST_SELECTOR (panel->grid_selector));
+
+ for (l = children; l != NULL; l = l->next)
+ {
+ GtdTaskList *list;
+
+ list = gtd_task_list_item_get_list (l->data);
+
+ if (gtd_task_list_is_removable (list))
+ gtd_manager_remove_task_list (gtd_manager_get_default (), list);
+ }
+
+ g_list_free (children);
+ }
+
+ gtk_widget_destroy (dialog);
+
+ /* After removing the lists, exit SELECTION mode */
+ gtd_window_set_mode (GTD_WINDOW (toplevel), GTD_WINDOW_MODE_NORMAL);
+}
+
+/***********************
+ * GtdPanel iface init *
+ ***********************/
+static GList*
+gtd_list_selector_panel_get_header_widgets (GtdPanel *panel)
+{
+ GtdListSelectorPanel *self = GTD_LIST_SELECTOR_PANEL (panel);
+ GList *widgets;
+
+ widgets = g_list_append (NULL, self->search_button);
+ widgets = g_list_append (widgets, self->selection_button);
+ widgets = g_list_append (widgets, self->view_button);
+
+ return widgets;
+}
+
+static const GMenu*
+gtd_list_selector_panel_get_menu (GtdPanel *panel)
+{
+ /* TODO: add a menu for GtdListSelectorPanel */
+ return NULL;
+}
+
+static const gchar*
+gtd_list_selector_panel_get_name (GtdPanel *panel)
+{
+ return "panel-lists";
+}
+
+static const gchar*
+gtd_list_selector_panel_get_title (GtdPanel *panel)
+{
+ return _("Lists");
+}
+
+static void
+gtd_panel_iface_init (GtdPanelInterface *iface)
+{
+ iface->get_header_widgets = gtd_list_selector_panel_get_header_widgets;
+ iface->get_menu = gtd_list_selector_panel_get_menu;
+ iface->get_name = gtd_list_selector_panel_get_name;
+ iface->get_title = gtd_list_selector_panel_get_title;
+}
+
+static void
+gtd_list_selector_panel_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GtdPanel *self = GTD_PANEL (object);
+
+ switch (prop_id)
+ {
+ case PROP_HEADER_WIDGETS:
+ g_value_set_pointer (value, gtd_list_selector_panel_get_header_widgets (self));
+ break;
+
+ case PROP_MODE:
+ g_value_set_enum (value, GTD_LIST_SELECTOR_PANEL (object)->mode);
+ break;
+
+ case PROP_MENU:
+ g_value_set_object (value, (GMenu*) gtd_list_selector_panel_get_menu (self));
+ break;
+
+ case PROP_NAME:
+ g_value_set_string (value, gtd_list_selector_panel_get_name (self));
+ break;
+
+ case PROP_TITLE:
+ g_value_set_string (value, gtd_list_selector_panel_get_title (self));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gtd_list_selector_panel_set_mode (GtdListSelectorPanel *panel,
+ GtdWindowMode mode)
+{
+ if (panel->mode != mode)
+ {
+ panel->mode = mode;
+
+ gtk_widget_set_visible (panel->actionbar, mode == GTD_WINDOW_MODE_SELECTION);
+
+ g_object_notify (G_OBJECT (panel), "mode");
+ }
+}
+
+static void
+gtd_list_selector_panel_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GtdListSelectorPanel *self = GTD_LIST_SELECTOR_PANEL (object);
+
+ switch (prop_id)
+ {
+ case PROP_MODE:
+ gtd_list_selector_panel_set_mode (self, g_value_get_enum (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gtd_list_selector_panel_class_init (GtdListSelectorPanelClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = gtd_list_selector_panel_get_property;
+ object_class->set_property = gtd_list_selector_panel_set_property;
+
+ g_object_class_override_property (object_class,
+ PROP_HEADER_WIDGETS,
+ "header-widgets");
+
+ g_object_class_override_property (object_class,
+ PROP_MENU,
+ "menu");
+
+ g_object_class_override_property (object_class,
+ PROP_NAME,
+ "name");
+
+ g_object_class_override_property (object_class,
+ PROP_TITLE,
+ "title");
+
+ /**
+ * GtdListSelectorPanel::mode:
+ *
+ * This is a utility property so we can chain the "mode"
+ * property all the way up/down from window to the list
+ * items.
+ */
+ g_object_class_install_property (object_class,
+ PROP_MODE,
+ g_param_spec_enum ("mode",
+ "Mode of the selector",
+ "The mode of the selector",
+ GTD_TYPE_WINDOW_MODE,
+ GTD_WINDOW_MODE_NORMAL,
+ G_PARAM_READWRITE));
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/todo/ui/list-selector-panel.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, GtdListSelectorPanel, actionbar);
+ gtk_widget_class_bind_template_child (widget_class, GtdListSelectorPanel, back_button);
+ gtk_widget_class_bind_template_child (widget_class, GtdListSelectorPanel, color_button);
+ gtk_widget_class_bind_template_child (widget_class, GtdListSelectorPanel, delete_button);
+ gtk_widget_class_bind_template_child (widget_class, GtdListSelectorPanel, new_list_button);
+ gtk_widget_class_bind_template_child (widget_class, GtdListSelectorPanel, rename_button);
+ gtk_widget_class_bind_template_child (widget_class, GtdListSelectorPanel, rename_entry);
+ gtk_widget_class_bind_template_child (widget_class, GtdListSelectorPanel, rename_popover);
+ gtk_widget_class_bind_template_child (widget_class, GtdListSelectorPanel, save_rename_button);
+ gtk_widget_class_bind_template_child (widget_class, GtdListSelectorPanel, search_bar);
+ gtk_widget_class_bind_template_child (widget_class, GtdListSelectorPanel, search_button);
+ gtk_widget_class_bind_template_child (widget_class, GtdListSelectorPanel, selection_button);
+ gtk_widget_class_bind_template_child (widget_class, GtdListSelectorPanel, stack);
+ gtk_widget_class_bind_template_child (widget_class, GtdListSelectorPanel, tasklist_view);
+ gtk_widget_class_bind_template_child (widget_class, GtdListSelectorPanel, view_button);
+
+ gtk_widget_class_bind_template_callback (widget_class, gtd_list_selector_panel_back_button_clicked);
+ gtk_widget_class_bind_template_callback (widget_class, gtd_list_selector_panel_delete_button_clicked);
+ gtk_widget_class_bind_template_callback (widget_class, gtd_list_selector_panel_list_color_set);
+ gtk_widget_class_bind_template_callback (widget_class, gtd_list_selector_panel_on_key_press_event);
+ gtk_widget_class_bind_template_callback (widget_class, gtd_list_selector_panel_rename_button_clicked);
+ gtk_widget_class_bind_template_callback (widget_class, gtd_list_selector_panel_rename_entry_text_changed);
+ gtk_widget_class_bind_template_callback (widget_class, gtd_list_selector_panel_rename_task_list);
+ gtk_widget_class_bind_template_callback (widget_class, gtd_list_selector_panel_select_button_toggled);
+}
+
+static void
+gtd_list_selector_panel_init (GtdListSelectorPanel *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ /* Grid selector */
+ self->grid_selector = gtd_list_selector_grid_new ();
+
+ g_object_bind_property (self,
+ "mode",
+ self->grid_selector,
+ "mode",
+ G_BINDING_BIDIRECTIONAL);
+
+ g_signal_connect (self->grid_selector,
+ "list-selected",
+ G_CALLBACK (gtd_list_selector_panel_list_selected),
+ self);
+
+ gtk_stack_add_titled (GTK_STACK (self->stack),
+ self->grid_selector,
+ "grid",
+ "Grid");
+}
+
+GtkWidget*
+gtd_list_selector_panel_new (void)
+{
+ return g_object_new (GTD_TYPE_LIST_SELECTOR_PANEL, NULL);
+}
+
diff --git a/src/views/gtd-list-selector-panel.h b/src/views/gtd-list-selector-panel.h
new file mode 100644
index 0000000..7bbe413
--- /dev/null
+++ b/src/views/gtd-list-selector-panel.h
@@ -0,0 +1,36 @@
+/* gtd-list-selector-panel.h
+ *
+ * Copyright (C) 2015 Georges Basile Stavracas Neto <georges stavracas gmail com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GTD_LIST_SELECTOR_PANEL_H
+#define GTD_LIST_SELECTOR_PANEL_H
+
+#include <glib-object.h>
+#include <glib.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GTD_TYPE_LIST_SELECTOR_PANEL (gtd_list_selector_panel_get_type())
+
+G_DECLARE_FINAL_TYPE (GtdListSelectorPanel, gtd_list_selector_panel, GTD, LIST_SELECTOR_PANEL, GtkStack)
+
+GtkWidget* gtd_list_selector_panel_new (void);
+
+G_END_DECLS
+
+#endif /* GTD_LIST_SELECTOR_PANEL_H */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]