[gnome-todo/gbsneto/planning: 6/6] WIP Introduce an inbox planner



commit 1bff520d1e2f844bca36c2b781c00d5fd11521af
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date:   Sun May 3 14:58:59 2020 -0300

    WIP Introduce an inbox planner

 src/plugins/planning-workspace/gtd-inbox-planner.c | 149 ++++++++++++++++
 src/plugins/planning-workspace/gtd-inbox-planner.h |  30 ++++
 .../planning-workspace/gtd-inbox-planner.ui        | 126 ++++++++++++++
 .../planning-workspace/gtd-provider-section.c      | 191 +++++++++++++++++++++
 .../planning-workspace/gtd-provider-section.h      |  35 ++++
 .../planning-workspace/gtd-provider-section.ui     |  63 +++++++
 src/plugins/planning-workspace/gtd-task-card.c     | 156 +++++++++++++++++
 src/plugins/planning-workspace/gtd-task-card.h     |  34 ++++
 src/plugins/planning-workspace/gtd-task-card.ui    |  43 +++++
 .../planning-workspace/gtd-task-list-card.c        | 176 +++++++++++++++++++
 .../planning-workspace/gtd-task-list-card.h        |  34 ++++
 .../planning-workspace/gtd-task-list-card.ui       |  63 +++++++
 src/plugins/planning-workspace/meson.build         |   4 +
 .../planning-workspace/planning-workspace-plugin.c |   5 +
 .../planning-workspace.gresource.xml               |   5 +
 src/plugins/planning-workspace/themes/shared.css   |  30 ++++
 16 files changed, 1144 insertions(+)
---
diff --git a/src/plugins/planning-workspace/gtd-inbox-planner.c 
b/src/plugins/planning-workspace/gtd-inbox-planner.c
new file mode 100644
index 0000000..8c3b516
--- /dev/null
+++ b/src/plugins/planning-workspace/gtd-inbox-planner.c
@@ -0,0 +1,149 @@
+/* gtd-inbox-planner.c
+ *
+ * Copyright 2020 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "GtdInboxPlanner"
+
+#include "gtd-inbox-planner.h"
+
+#include "gnome-todo.h"
+
+#include "gtd-debug.h"
+#include "gtd-provider-section.h"
+#include "gtd-task-card.h"
+
+#include <glib/gi18n.h>
+
+struct _GtdInboxPlanner
+{
+  GtkBin              parent;
+
+  GtkFlowBox         *providers_flowbox;
+  GtkFlowBox         *tasks_flowbox;
+};
+
+static void          gtd_planner_iface_init                      (GtdPlannerInterface  *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GtdInboxPlanner, gtd_inbox_planner, GTK_TYPE_BIN,
+                         G_IMPLEMENT_INTERFACE (GTD_TYPE_PLANNER, gtd_planner_iface_init))
+
+
+/*
+ * Callbacks
+ */
+
+static GtkWidget*
+create_provider_section_func (gpointer item,
+                              gpointer user_data)
+{
+  return gtd_provider_section_new (item);
+}
+
+static GtkWidget*
+create_task_card_func (gpointer item,
+                       gpointer user_data)
+{
+  return gtd_task_card_new (item);
+}
+
+
+/*
+ * GtdPlanner implementation
+ */
+
+static const gchar*
+gtd_inbox_planner_get_id (GtdPlanner *planner)
+{
+  return "inbox-planner";
+}
+
+static const gchar*
+gtd_inbox_planner_get_title (GtdPlanner *planner)
+{
+  return _("Inbox");
+}
+
+static gint
+gtd_inbox_planner_get_priority (GtdPlanner *planner)
+{
+  return 1000;
+}
+
+static GIcon*
+gtd_inbox_planner_get_icon (GtdPlanner *planner)
+{
+  return g_themed_icon_new ("mail-inbox-symbolic");
+}
+
+static void
+gtd_planner_iface_init (GtdPlannerInterface *iface)
+{
+  iface->get_id = gtd_inbox_planner_get_id;
+  iface->get_title = gtd_inbox_planner_get_title;
+  iface->get_priority = gtd_inbox_planner_get_priority;
+  iface->get_icon = gtd_inbox_planner_get_icon;
+}
+
+static void
+gtd_inbox_planner_finalize (GObject *object)
+{
+  GtdInboxPlanner *self = (GtdInboxPlanner *)object;
+
+  G_OBJECT_CLASS (gtd_inbox_planner_parent_class)->finalize (object);
+}
+
+static void
+gtd_inbox_planner_class_init (GtdInboxPlannerClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  object_class->finalize = gtd_inbox_planner_finalize;
+
+  gtk_widget_class_set_template_from_resource (widget_class, 
"/org/gnome/todo/plugins/planning-workspace/gtd-inbox-planner.ui");
+
+  gtk_widget_class_bind_template_child (widget_class, GtdInboxPlanner, providers_flowbox);
+  gtk_widget_class_bind_template_child (widget_class, GtdInboxPlanner, tasks_flowbox);
+
+  gtk_widget_class_set_css_name (widget_class, "inbox-planner");
+}
+
+static void
+gtd_inbox_planner_init (GtdInboxPlanner *self)
+{
+  g_autoptr (GtkFlattenListModel) flat_model = NULL;
+  GtdManager *manager;
+
+  gtk_widget_init_template (GTK_WIDGET (self));
+
+  manager = gtd_manager_get_default ();
+  flat_model = gtk_flatten_list_model_new (GTD_TYPE_TASK, gtd_manager_get_inbox_model (manager));
+  gtk_flow_box_bind_model (self->tasks_flowbox,
+                           G_LIST_MODEL (flat_model),
+                           create_task_card_func,
+                           self,
+                           NULL);
+
+  gtk_flow_box_bind_model (self->providers_flowbox,
+                           gtd_manager_get_providers_model (manager),
+                           create_provider_section_func,
+                           self,
+                           NULL);
+
+}
diff --git a/src/plugins/planning-workspace/gtd-inbox-planner.h 
b/src/plugins/planning-workspace/gtd-inbox-planner.h
new file mode 100644
index 0000000..034e9c9
--- /dev/null
+++ b/src/plugins/planning-workspace/gtd-inbox-planner.h
@@ -0,0 +1,30 @@
+/* gtd-inbox-planner.h
+ *
+ * Copyright 2020 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GTD_TYPE_INBOX_PLANNER (gtd_inbox_planner_get_type())
+G_DECLARE_FINAL_TYPE (GtdInboxPlanner, gtd_inbox_planner, GTD, INBOX_PLANNER, GtkBin)
+
+G_END_DECLS
diff --git a/src/plugins/planning-workspace/gtd-inbox-planner.ui 
b/src/plugins/planning-workspace/gtd-inbox-planner.ui
new file mode 100644
index 0000000..677fe16
--- /dev/null
+++ b/src/plugins/planning-workspace/gtd-inbox-planner.ui
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <template class="GtdInboxPlanner" parent="GtkBin">
+
+    <child>
+      <object class="GtkBox">
+        <property name="margin-top">18</property>
+        <property name="margin-start">18</property>
+        <property name="hexpand">true</property>
+        <property name="vexpand">true</property>
+        <property name="spacing">18</property>
+        <property name="orientation">vertical</property>
+
+        <child>
+          <object class="GtkBox">
+            <property name="spacing">12</property>
+            <property name="orientation">vertical</property>
+            <child>
+              <object class="GtkBox">
+                <property name="spacing">12</property>
+                <style>
+                  <class name="title" />
+                </style>
+
+                <child>
+                  <object class="GtkImage">
+                    <property name="icon-name">mail-inbox-symbolic</property>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkLabel">
+                    <property name="hexpand">true</property>
+                    <property name="label" translatable="yes">Inbox</property>
+                    <property name="xalign">0.0</property>
+                  </object>
+                </child>
+              </object>
+            </child>
+
+            <child>
+              <object class="GtkScrolledWindow">
+                <property name="hexpand">true</property>
+                <property name="vexpand">false</property>
+                <property name="vscrollbar-policy">never</property>
+                <child>
+                  <object class="GtkFlowBox" id="tasks_flowbox">
+                    <property name="margin-top">12</property>
+                    <property name="margin-bottom">12</property>
+                    <property name="margin-start">18</property>
+                    <property name="margin-end">18</property>
+                    <property name="halign">start</property>
+                    <property name="orientation">vertical</property>
+                    <property name="row-spacing">12</property>
+                    <property name="column-spacing">12</property>
+                    <property name="homogeneous">true</property>
+                    <property name="selection-mode">none</property>
+                    <property name="min-children-per-line">2</property>
+                    <property name="max-children-per-line">2</property>
+                  </object>
+                </child>
+              </object>
+            </child>
+
+          </object>
+        </child>
+
+
+
+        <child>
+          <object class="GtkBox">
+            <property name="spacing">12</property>
+            <property name="orientation">vertical</property>
+
+            <child>
+              <object class="GtkBox">
+                <property name="spacing">12</property>
+                <style>
+                  <class name="title" />
+                </style>
+
+                <child>
+                  <object class="GtkImage">
+                    <property name="icon-name">view-list-symbolic</property>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkLabel">
+                    <property name="hexpand">true</property>
+                    <property name="label" translatable="yes">Task Lists</property>
+                    <property name="xalign">0.0</property>
+                  </object>
+                </child>
+              </object>
+            </child>
+
+            <child>
+              <object class="GtkScrolledWindow">
+                <property name="hexpand">true</property>
+                <property name="vexpand">true</property>
+                <property name="vscrollbar-policy">never</property>
+                <child>
+                  <object class="GtkFlowBox" id="providers_flowbox">
+                    <property name="margin-top">12</property>
+                    <property name="margin-bottom">12</property>
+                    <property name="margin-start">18</property>
+                    <property name="margin-end">18</property>
+                    <property name="halign">start</property>
+                    <property name="selection-mode">none</property>
+                    <property name="orientation">vertical</property>
+                    <property name="row-spacing">18</property>
+                    <property name="min-children-per-line">1</property>
+                    <property name="max-children-per-line">1</property>
+                  </object>
+                </child>
+              </object>
+            </child>
+
+          </object>
+        </child>
+
+      </object>
+    </child>
+
+  </template>
+
+</interface>
diff --git a/src/plugins/planning-workspace/gtd-provider-section.c 
b/src/plugins/planning-workspace/gtd-provider-section.c
new file mode 100644
index 0000000..7bf513d
--- /dev/null
+++ b/src/plugins/planning-workspace/gtd-provider-section.c
@@ -0,0 +1,191 @@
+/* gtd-provider-section.c
+ *
+ * Copyright 2020 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include "gtd-provider-section.h"
+
+#include "gtd-task-list-card.h"
+
+struct _GtdProviderSection
+{
+  GtkFlowBoxChild     parent_instance;
+
+  GtkLabel           *name_label;
+  GtkImage           *provider_icon;
+  GtkFlowBox         *task_lists_flowbox;
+
+  GtdProvider        *provider;
+};
+
+G_DEFINE_TYPE (GtdProviderSection, gtd_provider_section, GTK_TYPE_FLOW_BOX_CHILD)
+
+enum
+{
+  PROP_0,
+  PROP_PROVIDER,
+  N_PROPS
+};
+
+static GParamSpec *properties [N_PROPS];
+
+
+/*
+ * Callbacks
+ */
+
+static gboolean
+filter_by_provider_func (gpointer item,
+                         gpointer user_data)
+{
+  GtdProviderSection *self = (GtdProviderSection *)user_data;
+
+  return gtd_task_list_get_provider (item) == self->provider &&
+         !gtd_task_list_get_archived (item);
+}
+
+static GtkWidget*
+create_task_list_card_func (gpointer item,
+                            gpointer user_data)
+{
+  return gtd_task_list_card_new (item);
+}
+
+
+/*
+ * GObject overrides
+ */
+
+static void
+gtd_provider_section_finalize (GObject *object)
+{
+  GtdProviderSection *self = (GtdProviderSection *)object;
+
+  g_clear_object (&self->provider);
+
+  G_OBJECT_CLASS (gtd_provider_section_parent_class)->finalize (object);
+}
+
+static void
+gtd_provider_section_get_property (GObject    *object,
+                                   guint       prop_id,
+                                   GValue     *value,
+                                   GParamSpec *pspec)
+{
+  GtdProviderSection *self = GTD_PROVIDER_SECTION (object);
+
+  switch (prop_id)
+    {
+    case PROP_PROVIDER:
+      g_value_set_object (value, self->provider);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+gtd_provider_section_set_property (GObject      *object,
+                                   guint         prop_id,
+                                   const GValue *value,
+                                   GParamSpec   *pspec)
+{
+  GtdProviderSection *self = GTD_PROVIDER_SECTION (object);
+
+  switch (prop_id)
+    {
+    case PROP_PROVIDER:
+        {
+          g_autoptr (GtkFilterListModel) filter_model = NULL;
+          GtdManager *manager;
+
+          g_assert (self->provider == NULL);
+          self->provider = g_value_dup_object (value);
+
+          g_object_bind_property (self->provider,
+                                  "icon",
+                                  self->provider_icon,
+                                  "gicon",
+                                  G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE);
+
+          g_object_bind_property (self->provider,
+                                  "name",
+                                  self->name_label,
+                                  "label",
+                                  G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE);
+
+          manager = gtd_manager_get_default ();
+          filter_model = gtk_filter_list_model_new (gtd_manager_get_task_lists_model (manager),
+                                                    filter_by_provider_func,
+                                                    self,
+                                                    NULL);
+          gtk_flow_box_bind_model (self->task_lists_flowbox,
+                                   G_LIST_MODEL (filter_model),
+                                   create_task_list_card_func,
+                                   self,
+                                   NULL);
+
+        }
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+gtd_provider_section_class_init (GtdProviderSectionClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  object_class->finalize = gtd_provider_section_finalize;
+  object_class->get_property = gtd_provider_section_get_property;
+  object_class->set_property = gtd_provider_section_set_property;
+
+  properties[PROP_PROVIDER] = g_param_spec_object ("provider",
+                                                   "Provider",
+                                                   "Provider",
+                                                   GTD_TYPE_PROVIDER,
+                                                   G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | 
G_PARAM_STATIC_STRINGS);
+
+  g_object_class_install_properties (object_class, N_PROPS, properties);
+
+  gtk_widget_class_set_template_from_resource (widget_class, 
"/org/gnome/todo/plugins/planning-workspace/gtd-provider-section.ui");
+
+  gtk_widget_class_bind_template_child (widget_class, GtdProviderSection, name_label);
+  gtk_widget_class_bind_template_child (widget_class, GtdProviderSection, provider_icon);
+  gtk_widget_class_bind_template_child (widget_class, GtdProviderSection, task_lists_flowbox);
+
+  gtk_widget_class_set_css_name (widget_class, "provider-section");
+}
+
+static void
+gtd_provider_section_init (GtdProviderSection *self)
+{
+  gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+GtkWidget*
+gtd_provider_section_new (GtdProvider *provider)
+{
+  return g_object_new (GTD_TYPE_PROVIDER_SECTION,
+                       "provider", provider,
+                       NULL);
+}
diff --git a/src/plugins/planning-workspace/gtd-provider-section.h 
b/src/plugins/planning-workspace/gtd-provider-section.h
new file mode 100644
index 0000000..a6bb1a2
--- /dev/null
+++ b/src/plugins/planning-workspace/gtd-provider-section.h
@@ -0,0 +1,35 @@
+/* gtd-provider-section.h
+ *
+ * Copyright 2020 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include "gnome-todo.h"
+
+G_BEGIN_DECLS
+
+#define GTD_TYPE_PROVIDER_SECTION (gtd_provider_section_get_type())
+
+G_DECLARE_FINAL_TYPE (GtdProviderSection, gtd_provider_section, GTD, PROVIDER_SECTION, GtkFlowBoxChild)
+
+GtkWidget*           gtd_provider_section_new                    (GtdProvider        *provider);
+
+GtdProvider*         gtd_provider_section_get_provider           (GtdProviderSection *self);
+
+G_END_DECLS
diff --git a/src/plugins/planning-workspace/gtd-provider-section.ui 
b/src/plugins/planning-workspace/gtd-provider-section.ui
new file mode 100644
index 0000000..54eaf7c
--- /dev/null
+++ b/src/plugins/planning-workspace/gtd-provider-section.ui
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <template class="GtdProviderSection" parent="GtkFlowBoxChild">
+    <property name="margin-top">6</property>
+    <property name="margin-bottom">6</property>
+    <property name="margin-start">6</property>
+    <property name="margin-end">6</property>
+    <child>
+      <object class="GtkBox">
+        <property name="hexpand">true</property>
+        <property name="vexpand">true</property>
+        <property name="spacing">12</property>
+        <property name="orientation">vertical</property>
+
+        <child>
+          <object class="GtkBox">
+            <property name="hexpand">true</property>
+            <property name="spacing">12</property>
+
+            <!-- Icon -->
+            <child>
+              <object class="GtkImage" id="provider_icon">
+                <property name="pixel-size">16</property>
+                <style>
+                  <class name="dim-label" />
+                </style>
+              </object>
+            </child>
+
+            <!-- Name -->
+            <child>
+              <object class="GtkLabel" id="name_label">
+                <property name="hexpand">true</property>
+                <property name="xalign">0.0</property>
+              </object>
+            </child>
+
+          </object>
+        </child>
+
+        <!-- Flowbox -->
+        <child>
+          <object class="GtkFlowBox" id="task_lists_flowbox">
+            <property name="hexpand">true</property>
+            <property name="vexpand">true</property>
+            <property name="valign">start</property>
+            <property name="halign">start</property>
+            <property name="orientation">vertical</property>
+            <property name="homogeneous">true</property>
+            <property name="row-spacing">12</property>
+            <property name="column-spacing">12</property>
+            <property name="selection-mode">none</property>
+            <property name="min-children-per-line">1</property>
+            <property name="max-children-per-line">8</property>
+          </object>
+        </child>
+
+      </object>
+    </child>
+
+  </template>
+
+</interface>
diff --git a/src/plugins/planning-workspace/gtd-task-card.c b/src/plugins/planning-workspace/gtd-task-card.c
new file mode 100644
index 0000000..8c9953f
--- /dev/null
+++ b/src/plugins/planning-workspace/gtd-task-card.c
@@ -0,0 +1,156 @@
+/* gtd-task-card.c
+ *
+ * Copyright 2020 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "GtdTaskCard"
+
+#include "gtd-task-card.h"
+
+struct _GtdTaskCard
+{
+  GtkFlowBoxChild     parent_instance;
+
+  GtkLabel           *title_label;
+
+  GtdTask            *task;
+};
+
+G_DEFINE_TYPE (GtdTaskCard, gtd_task_card, GTK_TYPE_FLOW_BOX_CHILD)
+
+enum
+{
+  PROP_0,
+  PROP_TASK,
+  N_PROPS
+};
+
+static GParamSpec *properties [N_PROPS];
+
+
+
+/*
+ * GObject overrides
+ */
+
+static void
+gtd_task_card_finalize (GObject *object)
+{
+  GtdTaskCard *self = (GtdTaskCard *)object;
+
+  g_clear_object (&self->task);
+
+  G_OBJECT_CLASS (gtd_task_card_parent_class)->finalize (object);
+}
+
+static void
+gtd_task_card_get_property (GObject    *object,
+                            guint       prop_id,
+                            GValue     *value,
+                            GParamSpec *pspec)
+{
+  GtdTaskCard *self = GTD_TASK_CARD (object);
+
+  switch (prop_id)
+    {
+    case PROP_TASK:
+      g_value_set_object (value, self->task);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+gtd_task_card_set_property (GObject      *object,
+                            guint         prop_id,
+                            const GValue *value,
+                            GParamSpec   *pspec)
+{
+  GtdTaskCard *self = GTD_TASK_CARD (object);
+
+  switch (prop_id)
+    {
+    case PROP_TASK:
+      g_assert (self->task == NULL);
+      self->task = g_value_dup_object (value);
+
+      g_object_bind_property (self->task,
+                              "title",
+                              self->title_label,
+                              "label",
+                              G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+gtd_task_card_class_init (GtdTaskCardClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  object_class->finalize = gtd_task_card_finalize;
+  object_class->get_property = gtd_task_card_get_property;
+  object_class->set_property = gtd_task_card_set_property;
+
+  properties[PROP_TASK] = g_param_spec_object ("task",
+                                               "Task",
+                                               "Task",
+                                               GTD_TYPE_TASK,
+                                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | 
G_PARAM_STATIC_STRINGS);
+
+  g_object_class_install_properties (object_class, N_PROPS, properties);
+
+  g_type_ensure (GTD_TYPE_STAR_WIDGET);
+  g_type_ensure (GTD_TYPE_TEXT_WIDTH_LAYOUT);
+
+  gtk_widget_class_set_template_from_resource (widget_class, 
"/org/gnome/todo/plugins/planning-workspace/gtd-task-card.ui");
+
+  gtk_widget_class_bind_template_child (widget_class, GtdTaskCard, title_label);
+
+  gtk_widget_class_set_css_name (widget_class, "task-card");
+}
+
+static void
+gtd_task_card_init (GtdTaskCard *self)
+{
+  gtk_widget_init_template (GTK_WIDGET (self));
+
+  gtk_widget_set_cursor_from_name (GTK_WIDGET (self), "grab");
+}
+
+GtkWidget*
+gtd_task_card_new (GtdTask *task)
+{
+  return g_object_new (GTD_TYPE_TASK_CARD,
+                       "task", task,
+                       NULL);
+}
+
+GtdTask*
+gtd_task_card_get_task (GtdTaskCard *self)
+{
+  g_return_val_if_fail (GTD_IS_TASK_CARD (self), NULL);
+
+  return self->task;
+}
diff --git a/src/plugins/planning-workspace/gtd-task-card.h b/src/plugins/planning-workspace/gtd-task-card.h
new file mode 100644
index 0000000..841fab8
--- /dev/null
+++ b/src/plugins/planning-workspace/gtd-task-card.h
@@ -0,0 +1,34 @@
+/* gtd-task-card.h
+ *
+ * Copyright 2020 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include "gnome-todo.h"
+
+G_BEGIN_DECLS
+
+#define GTD_TYPE_TASK_CARD (gtd_task_card_get_type())
+G_DECLARE_FINAL_TYPE (GtdTaskCard, gtd_task_card, GTD, TASK_CARD, GtkFlowBoxChild)
+
+GtkWidget*           gtd_task_card_new                           (GtdTask            *task);
+
+GtdTask*             gtd_task_card_get_task                      (GtdTaskCard        *self);
+
+G_END_DECLS
diff --git a/src/plugins/planning-workspace/gtd-task-card.ui b/src/plugins/planning-workspace/gtd-task-card.ui
new file mode 100644
index 0000000..9e1df0d
--- /dev/null
+++ b/src/plugins/planning-workspace/gtd-task-card.ui
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <template class="GtdTaskCard" parent="GtkFlowBoxChild">
+    <property name="layout-manager">
+      <object class="GtdTextWidthLayout">
+        <property name="width-chars">20</property>
+        <property name="max-width-chars">40</property>
+      </object>
+    </property>
+
+    <child>
+      <object class="GtkBox">
+        <property name="hexpand">true</property>
+        <property name="vexpand">true</property>
+        <property name="spacing">6</property>
+
+        <!-- Drag Icon -->
+        <child>
+          <object class="GtkImage">
+            <property name="pixel-size">16</property>
+            <property name="icon-name">list-drag-handle-symbolic</property>
+            <style>
+              <class name="dim-label" />
+            </style>
+          </object>
+        </child>
+
+        <!-- Title -->
+        <child>
+          <object class="GtkLabel" id="title_label">
+            <property name="hexpand">true</property>
+            <property name="xalign">0.0</property>
+            <property name="ellipsize">end</property>
+            <property name="max-width-chars">30</property>
+          </object>
+        </child>
+
+      </object>
+    </child>
+
+  </template>
+
+</interface>
diff --git a/src/plugins/planning-workspace/gtd-task-list-card.c 
b/src/plugins/planning-workspace/gtd-task-list-card.c
new file mode 100644
index 0000000..521bd12
--- /dev/null
+++ b/src/plugins/planning-workspace/gtd-task-list-card.c
@@ -0,0 +1,176 @@
+/* gtd-task-list-card.c
+ *
+ * Copyright 2020 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include "gtd-task-list-card.h"
+
+struct _GtdTaskListCard
+{
+  GtkFlowBoxChild     parent_instance;
+
+  GtkImage           *color_icon;
+  GtkLabel           *title_label;
+
+  GtdTaskList        *task_list;
+};
+
+G_DEFINE_TYPE (GtdTaskListCard, gtd_task_list_card, GTK_TYPE_FLOW_BOX_CHILD)
+
+enum
+{
+  PROP_0,
+  PROP_TASK_LIST,
+  N_PROPS
+};
+
+static GParamSpec *properties [N_PROPS];
+
+
+/*
+ * Auxiliary methods
+ */
+
+static void
+update_color (GtdTaskListCard *self)
+{
+  g_autoptr (GdkPaintable) paintable = NULL;
+  g_autoptr (GdkRGBA) color = NULL;
+
+  color = gtd_task_list_get_color (self->task_list);
+  paintable = gtd_create_circular_paintable (color, 12);
+
+  gtk_image_set_from_paintable (self->color_icon, paintable);
+}
+
+
+/*
+ * Callbacks
+ */
+
+static void
+on_task_list_color_changed_cb (GtdTaskList     *task_list,
+                               GParamSpec      *pspec,
+                               GtdTaskListCard *self)
+{
+  update_color (self);
+}
+
+
+/*
+ * GObject overrides
+ */
+
+static void
+gtd_task_list_card_finalize (GObject *object)
+{
+  GtdTaskListCard *self = (GtdTaskListCard *)object;
+
+  g_clear_object (&self->task_list);
+
+  G_OBJECT_CLASS (gtd_task_list_card_parent_class)->finalize (object);
+}
+
+static void
+gtd_task_list_card_get_property (GObject    *object,
+                                 guint       prop_id,
+                                 GValue     *value,
+                                 GParamSpec *pspec)
+{
+  GtdTaskListCard *self = GTD_TASK_LIST_CARD (object);
+
+  switch (prop_id)
+    {
+    case PROP_TASK_LIST:
+      g_value_set_object (value, self->task_list);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+gtd_task_list_card_set_property (GObject      *object,
+                                 guint         prop_id,
+                                 const GValue *value,
+                                 GParamSpec   *pspec)
+{
+  GtdTaskListCard *self = GTD_TASK_LIST_CARD (object);
+
+  switch (prop_id)
+    {
+    case PROP_TASK_LIST:
+      g_assert (self->task_list == NULL);
+      self->task_list = g_value_dup_object (value);
+
+      g_object_bind_property (self->task_list,
+                              "name",
+                              self->title_label,
+                              "label",
+                              G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE);
+
+      g_signal_connect (self->task_list, "notify::color", G_CALLBACK (on_task_list_color_changed_cb), self);
+      update_color (self);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+gtd_task_list_card_class_init (GtdTaskListCardClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  object_class->finalize = gtd_task_list_card_finalize;
+  object_class->get_property = gtd_task_list_card_get_property;
+  object_class->set_property = gtd_task_list_card_set_property;
+
+  properties[PROP_TASK_LIST] = g_param_spec_object ("task-list",
+                                                    "Task list",
+                                                    "Task list",
+                                                    GTD_TYPE_TASK_LIST,
+                                                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | 
G_PARAM_STATIC_STRINGS);
+
+  g_object_class_install_properties (object_class, N_PROPS, properties);
+
+  gtk_widget_class_set_template_from_resource (widget_class, 
"/org/gnome/todo/plugins/planning-workspace/gtd-task-list-card.ui");
+
+  gtk_widget_class_bind_template_child (widget_class, GtdTaskListCard, color_icon);
+  gtk_widget_class_bind_template_child (widget_class, GtdTaskListCard, title_label);
+
+  gtk_widget_class_set_css_name (widget_class, "task-list-card");
+}
+
+static void
+gtd_task_list_card_init (GtdTaskListCard *self)
+{
+  gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+GtkWidget*
+gtd_task_list_card_new (GtdTaskList *task_list)
+{
+  return g_object_new (GTD_TYPE_TASK_LIST_CARD,
+                       "task-list", task_list,
+                       NULL);
+}
+
diff --git a/src/plugins/planning-workspace/gtd-task-list-card.h 
b/src/plugins/planning-workspace/gtd-task-list-card.h
new file mode 100644
index 0000000..6a89116
--- /dev/null
+++ b/src/plugins/planning-workspace/gtd-task-list-card.h
@@ -0,0 +1,34 @@
+/* gtd-task-list-card.h
+ *
+ * Copyright 2020 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include "gnome-todo.h"
+
+G_BEGIN_DECLS
+
+#define GTD_TYPE_TASK_LIST_CARD (gtd_task_list_card_get_type())
+G_DECLARE_FINAL_TYPE (GtdTaskListCard, gtd_task_list_card, GTD, TASK_LIST_CARD, GtkFlowBoxChild)
+
+GtkWidget*           gtd_task_list_card_new                      (GtdTaskList        *task_list);
+
+GtdTaskList*         gtd_task_list_card_get_list                 (GtdTaskListCard    *self);
+
+G_END_DECLS
diff --git a/src/plugins/planning-workspace/gtd-task-list-card.ui 
b/src/plugins/planning-workspace/gtd-task-list-card.ui
new file mode 100644
index 0000000..1896aee
--- /dev/null
+++ b/src/plugins/planning-workspace/gtd-task-list-card.ui
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <template class="GtdTaskListCard" parent="GtkFlowBoxChild">
+    <property name="layout-manager">
+      <object class="GtdTextWidthLayout">
+        <property name="width-chars">10</property>
+        <property name="max-width-chars">20</property>
+      </object>
+    </property>
+
+    <child>
+      <object class="GtkGrid">
+        <property name="hexpand">true</property>
+        <property name="vexpand">true</property>
+        <property name="row-spacing">3</property>
+        <property name="column-spacing">6</property>
+
+        <!-- Color Dot -->
+        <child>
+          <object class="GtkImage" id="color_icon">
+            <property name="halign">end</property>
+            <property name="pixel-size">12</property>
+            <layout>
+              <property name="left-attach">1</property>
+              <property name="top-attach">0</property>
+            </layout>
+          </object>
+        </child>
+
+        <!-- Title -->
+        <child>
+          <object class="GtkLabel" id="title_label">
+            <property name="hexpand">true</property>
+            <property name="xalign">0.0</property>
+            <property name="ellipsize">end</property>
+            <property name="max-width-chars">20</property>
+            <layout>
+              <property name="left-attach">0</property>
+              <property name="top-attach">0</property>
+            </layout>
+          </object>
+        </child>
+
+        <!-- Title -->
+        <child>
+          <object class="GtkLabel" id="tasks_counter_label">
+            <property name="hexpand">true</property>
+            <property name="xalign">0.0</property>
+            <property name="ellipsize">end</property>
+            <layout>
+              <property name="left-attach">0</property>
+              <property name="top-attach">1</property>
+              <property name="column-span">2</property>
+            </layout>
+          </object>
+        </child>
+
+      </object>
+    </child>
+
+  </template>
+
+</interface>
diff --git a/src/plugins/planning-workspace/meson.build b/src/plugins/planning-workspace/meson.build
index c4dd704..39a626e 100644
--- a/src/plugins/planning-workspace/meson.build
+++ b/src/plugins/planning-workspace/meson.build
@@ -1,7 +1,11 @@
 plugins_ldflags += ['-Wl,--undefined=planning_workspace_plugin_register_types']
 
 plugins_sources += files(
+  'gtd-inbox-planner.c',
   'gtd-planning-workspace.c',
+  'gtd-provider-section.c',
+  'gtd-task-card.c',
+  'gtd-task-list-card.c',
   'planning-workspace-plugin.c',
 )
 
diff --git a/src/plugins/planning-workspace/planning-workspace-plugin.c 
b/src/plugins/planning-workspace/planning-workspace-plugin.c
index 6ea0a50..af4457a 100644
--- a/src/plugins/planning-workspace/planning-workspace-plugin.c
+++ b/src/plugins/planning-workspace/planning-workspace-plugin.c
@@ -20,6 +20,7 @@
 
 #include "gnome-todo.h"
 
+#include "gtd-inbox-planner.h"
 #include "gtd-planning-workspace.h"
 
 G_MODULE_EXPORT void
@@ -28,4 +29,8 @@ planning_workspace_plugin_register_types (PeasObjectModule *module)
   peas_object_module_register_extension_type (module,
                                               GTD_TYPE_WORKSPACE,
                                               GTD_TYPE_PLANNING_WORKSPACE);
+
+  peas_object_module_register_extension_type (module,
+                                              GTD_TYPE_PLANNER,
+                                              GTD_TYPE_INBOX_PLANNER);
 }
diff --git a/src/plugins/planning-workspace/planning-workspace.gresource.xml 
b/src/plugins/planning-workspace/planning-workspace.gresource.xml
index d409f93..06b97a4 100644
--- a/src/plugins/planning-workspace/planning-workspace.gresource.xml
+++ b/src/plugins/planning-workspace/planning-workspace.gresource.xml
@@ -1,7 +1,12 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <gresources>
   <gresource prefix="/org/gnome/todo/plugins/planning-workspace">
+    <file>themes/shared.css</file>
+    <file>gtd-inbox-planner.ui</file>
     <file>gtd-planning-workspace.ui</file>
+    <file>gtd-provider-section.ui</file>
+    <file>gtd-task-card.ui</file>
+    <file>gtd-task-list-card.ui</file>
     <file>planning-workspace.plugin</file>
   </gresource>
 </gresources>
diff --git a/src/plugins/planning-workspace/themes/shared.css 
b/src/plugins/planning-workspace/themes/shared.css
new file mode 100644
index 0000000..5ebcbff
--- /dev/null
+++ b/src/plugins/planning-workspace/themes/shared.css
@@ -0,0 +1,30 @@
+inbox-planner box.title label {
+  font-size: 1.5rem;
+}
+
+inbox-planner box.title image {
+  -gtk-icon-size: 24px;
+}
+
+task-card {
+  background-color: @theme_base_color;
+  border: @borders 1px solid;
+  border-radius: 5px;
+  padding: 12px 12px 12px 6px;
+
+  transition: all 150ms cubic-bezier(0.25, 0.46, 0.45, 0.94);
+}
+
+task-card:focus,
+task-card:hover {
+  background-color: alpha(@theme_fg_color, 0.05);
+}
+
+task-list-card {
+  background-color: @theme_base_color;
+  border: @borders 1px solid;
+  border-radius: 5px;
+  padding: 12px;
+
+  transition: all 150ms cubic-bezier(0.25, 0.46, 0.45, 0.94);
+}



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