summaryrefslogtreecommitdiff
path: root/src/plugins/today-panel/gtd-today-omni-area-addin.c
diff options
context:
space:
mode:
authorMatthew Fennell <matthew@fennell.dev>2025-12-27 12:40:20 +0000
committerMatthew Fennell <matthew@fennell.dev>2025-12-27 12:40:20 +0000
commit5d8e439bc597159e3c9f0a8b65c0ae869dead3a8 (patch)
treeed28aefed8add0da1c55c08fdf80b23c4346e0dc /src/plugins/today-panel/gtd-today-omni-area-addin.c
Import Upstream version 43.0upstream/latest
Diffstat (limited to 'src/plugins/today-panel/gtd-today-omni-area-addin.c')
-rw-r--r--src/plugins/today-panel/gtd-today-omni-area-addin.c304
1 files changed, 304 insertions, 0 deletions
diff --git a/src/plugins/today-panel/gtd-today-omni-area-addin.c b/src/plugins/today-panel/gtd-today-omni-area-addin.c
new file mode 100644
index 0000000..d92979d
--- /dev/null
+++ b/src/plugins/today-panel/gtd-today-omni-area-addin.c
@@ -0,0 +1,304 @@
+/* gtd-today-omni-area-addin.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-today-omni-area-addin.h"
+
+#include "endeavour.h"
+#include "config.h"
+
+#include <glib/gi18n.h>
+
+#define MESSAGE_ID "today-counter-message-id"
+
+struct _GtdTodayOmniAreaAddin
+{
+ GObject parent;
+
+ GIcon *icon;
+ GtkFilterListModel *filter_model;
+
+ GtdOmniArea *omni_area;
+ guint number_of_tasks;
+
+ gboolean had_tasks;
+ gboolean finished_tasks;
+
+ guint idle_update_message_timeout_id;
+};
+
+static void gtd_omni_area_addin_iface_init (GtdOmniAreaAddinInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GtdTodayOmniAreaAddin, gtd_today_omni_area_addin, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (GTD_TYPE_OMNI_AREA_ADDIN, gtd_omni_area_addin_iface_init))
+
+const gchar *end_messages[] =
+{
+ N_("No more tasks left"),
+ N_("Nothing else to do here"),
+ N_("You made it!"),
+ N_("Looks like there’s nothing else left here")
+};
+
+static gboolean
+can_show_omni_area_message (GtdTodayOmniAreaAddin *self)
+{
+ GtdWorkspace *current_workspace;
+ GtdWindow *window;
+
+ window = GTD_WINDOW (gtk_widget_get_root (GTK_WIDGET (self->omni_area)));
+ current_workspace = gtd_window_get_current_workspace (window);
+
+ if (current_workspace &&
+ g_str_equal (gtd_workspace_get_id (current_workspace), "task-lists"))
+ {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+update_omni_area_message (GtdTodayOmniAreaAddin *self)
+{
+
+ g_autofree gchar *message = NULL;
+
+ g_assert (self->omni_area != NULL);
+
+ if (!can_show_omni_area_message (self))
+ {
+ gtd_omni_area_withdraw_message (self->omni_area, MESSAGE_ID);
+ return;
+ }
+
+ if (self->number_of_tasks > 0)
+ {
+ message = g_strdup_printf (g_dngettext (GETTEXT_PACKAGE,
+ "%d task for today",
+ "%d tasks for today",
+ self->number_of_tasks),
+ self->number_of_tasks);
+ }
+ else
+ {
+ if (self->finished_tasks)
+ {
+ gint message_index = g_random_int_range (0, G_N_ELEMENTS (end_messages));
+
+ message = g_strdup (gettext (end_messages[message_index]));
+ }
+ else
+ {
+ message = g_strdup (_("No tasks scheduled for today"));
+ }
+ }
+
+ gtd_omni_area_withdraw_message (self->omni_area, MESSAGE_ID);
+ gtd_omni_area_push_message (self->omni_area, MESSAGE_ID, message, self->icon);
+}
+
+static gboolean
+is_today (GDateTime *today,
+ GDateTime *dt)
+{
+ if (!dt)
+ return FALSE;
+
+ if (g_date_time_get_year (dt) == g_date_time_get_year (today) &&
+ g_date_time_get_day_of_year (dt) == g_date_time_get_day_of_year (today))
+ {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/*
+ * Callbacks
+ */
+
+static gboolean
+idle_update_omni_area_message_cb (gpointer user_data)
+{
+ GtdTodayOmniAreaAddin *self = GTD_TODAY_OMNI_AREA_ADDIN (user_data);
+
+ update_omni_area_message (self);
+
+ self->idle_update_message_timeout_id = 0;
+
+ return G_SOURCE_REMOVE;
+}
+
+static gboolean
+filter_func (gpointer item,
+ gpointer user_data)
+{
+ g_autoptr (GDateTime) task_dt = NULL;
+ g_autoptr (GDateTime) now = NULL;
+ GtdTask *task;
+
+ task = (GtdTask*) item;
+
+ if (gtd_task_get_complete (task))
+ return FALSE;
+
+ now = g_date_time_new_now_local ();
+ task_dt = gtd_task_get_due_date (task);
+
+ return is_today (now, task_dt);
+}
+
+static void
+on_clock_day_changed_cb (GtdClock *clock,
+ GtdTodayOmniAreaAddin *self)
+{
+ GtkFilter *filter;
+
+ self->had_tasks = FALSE;
+ self->finished_tasks = FALSE;
+
+ filter = gtk_filter_list_model_get_filter (self->filter_model);
+ gtk_filter_changed (filter, GTK_FILTER_CHANGE_DIFFERENT);
+}
+
+static void
+on_model_items_changed_cb (GListModel *model,
+ guint position,
+ guint n_removed,
+ guint n_added,
+ GtdTodayOmniAreaAddin *self)
+{
+ guint number_of_tasks = g_list_model_get_n_items (model);
+
+ if (self->number_of_tasks == number_of_tasks)
+ return;
+
+ self->number_of_tasks = number_of_tasks;
+
+ if (number_of_tasks != 0)
+ self->had_tasks = number_of_tasks != 0;
+
+ self->finished_tasks = self->had_tasks && number_of_tasks == 0;
+
+ g_clear_handle_id (&self->idle_update_message_timeout_id, g_source_remove);
+ self->idle_update_message_timeout_id = g_timeout_add_seconds (2, idle_update_omni_area_message_cb, self);
+}
+
+static void
+on_window_current_workspace_changed_cb (GtdWindow *window,
+ GParamSpec *pspec,
+ GtdTodayOmniAreaAddin *self)
+{
+ update_omni_area_message (self);
+}
+
+
+/*
+ * GtdOmniAreaAddin iface
+ */
+
+static void
+gtd_today_omni_area_addin_omni_area_addin_load (GtdOmniAreaAddin *addin,
+ GtdOmniArea *omni_area)
+{
+ GtdTodayOmniAreaAddin *self;
+ GtdWindow *window;
+
+ self = GTD_TODAY_OMNI_AREA_ADDIN (addin);
+ window = GTD_WINDOW (gtk_widget_get_root (GTK_WIDGET (omni_area)));
+
+ g_signal_connect_object (window,
+ "notify::current-workspace",
+ G_CALLBACK (on_window_current_workspace_changed_cb),
+ self,
+ 0);
+
+ self->omni_area = omni_area;
+ update_omni_area_message (self);
+}
+
+static void
+gtd_today_omni_area_addin_omni_area_addin_unload (GtdOmniAreaAddin *addin,
+ GtdOmniArea *omni_area)
+{
+ GtdTodayOmniAreaAddin *self = GTD_TODAY_OMNI_AREA_ADDIN (addin);
+
+ gtd_omni_area_withdraw_message (omni_area, MESSAGE_ID);
+ self->omni_area = NULL;
+}
+
+static void
+gtd_omni_area_addin_iface_init (GtdOmniAreaAddinInterface *iface)
+{
+ iface->load = gtd_today_omni_area_addin_omni_area_addin_load;
+ iface->unload = gtd_today_omni_area_addin_omni_area_addin_unload;
+}
+
+/*
+ * GObject overrides
+ */
+
+static void
+gtd_today_omni_area_addin_finalize (GObject *object)
+{
+ GtdTodayOmniAreaAddin *self = (GtdTodayOmniAreaAddin *)object;
+
+ g_clear_handle_id (&self->idle_update_message_timeout_id, g_source_remove);
+ g_clear_object (&self->icon);
+ g_clear_object (&self->filter_model);
+
+ G_OBJECT_CLASS (gtd_today_omni_area_addin_parent_class)->finalize (object);
+}
+
+static void
+gtd_today_omni_area_addin_class_init (GtdTodayOmniAreaAddinClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = gtd_today_omni_area_addin_finalize;
+}
+
+static void
+gtd_today_omni_area_addin_init (GtdTodayOmniAreaAddin *self)
+{
+ GtkCustomFilter *filter;
+ GtdManager *manager;
+
+ manager = gtd_manager_get_default ();
+
+ self->icon = g_themed_icon_new ("view-tasks-today-symbolic");
+
+ filter = gtk_custom_filter_new (filter_func, self, NULL);
+ self->filter_model = gtk_filter_list_model_new (gtd_manager_get_tasks_model (manager),
+ GTK_FILTER (filter));
+
+ g_signal_connect_object (self->filter_model,
+ "items-changed",
+ G_CALLBACK (on_model_items_changed_cb),
+ self,
+ 0);
+
+ g_signal_connect_object (gtd_manager_get_clock (manager),
+ "day-changed",
+ G_CALLBACK (on_clock_day_changed_cb),
+ self,
+ 0);
+}