1 /* gtd-manager.c
2  *
3  * Copyright (C) 2015-2020 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #define G_LOG_DOMAIN "GtdManager"
20 
21 #include "models/gtd-list-store.h"
22 #include "models/gtd-task-model-private.h"
23 #include "gtd-clock.h"
24 #include "gtd-debug.h"
25 #include "gtd-manager.h"
26 #include "gtd-manager-protected.h"
27 #include "gtd-notification.h"
28 #include "gtd-panel.h"
29 #include "gtd-plugin-manager.h"
30 #include "gtd-provider.h"
31 #include "gtd-task.h"
32 #include "gtd-task-list.h"
33 #include "gtd-utils.h"
34 #include "gtd-workspace.h"
35 
36 #include <glib/gi18n.h>
37 
38 /**
39  * SECTION:gtd-manager
40  * @short_description:bridge between plugins and GNOME To Do
41  * @title:GtdManager
42  * @stability:Unstable
43  * @see_also:#GtdNotification,#GtdActivatable
44  *
45  * The #GtdManager object is a singleton object that exposes all the data
46  * inside the plugin to GNOME To Do, and vice-versa. From here, plugins have
47  * access to all the tasklists, tasks and panels of the other plugins.
48  *
49  * Objects can use gtd_manager_emit_error_message() to send errors to GNOME
50  * To Do. This will create a #GtdNotification internally.
51  */
52 
53 struct _GtdManager
54 {
55   GtdObject           parent;
56 
57   GSettings          *settings;
58   GtdPluginManager   *plugin_manager;
59 
60   GListModel         *inbox_model;
61   GListModel         *lists_model;
62   GListModel         *providers_model;
63   GListModel         *tasks_model;
64   GListModel         *unarchived_tasks_model;
65 
66   GList              *providers;
67   GtdProvider        *default_provider;
68   GtdClock           *clock;
69 
70   GCancellable       *cancellable;
71 };
72 
73 G_DEFINE_TYPE (GtdManager, gtd_manager, GTD_TYPE_OBJECT)
74 
75 /* Singleton instance */
76 static GtdManager *gtd_manager_instance = NULL;
77 
78 enum
79 {
80   LIST_ADDED,
81   LIST_CHANGED,
82   LIST_REMOVED,
83   SHOW_ERROR_MESSAGE,
84   SHOW_NOTIFICATION,
85   PROVIDER_ADDED,
86   PROVIDER_REMOVED,
87   NUM_SIGNALS
88 };
89 
90 enum
91 {
92   PROP_0,
93   PROP_DEFAULT_PROVIDER,
94   PROP_CLOCK,
95   PROP_PLUGIN_MANAGER,
96   LAST_PROP
97 };
98 
99 static guint signals[NUM_SIGNALS] = { 0, };
100 
101 
102 /*
103  * Auxiliary methods
104  */
105 
106 static void
check_provider_is_default(GtdManager * self,GtdProvider * provider)107 check_provider_is_default (GtdManager  *self,
108                            GtdProvider *provider)
109 {
110   g_autofree gchar *default_provider = NULL;
111 
112   default_provider = g_settings_get_string (self->settings, "default-provider");
113 
114   if (g_strcmp0 (default_provider, gtd_provider_get_id (provider)) == 0)
115     gtd_manager_set_default_provider (self, provider);
116 }
117 
118 
119 /*
120  * Callbacks
121  */
122 
123 static gboolean
filter_archived_lists_func(gpointer item,gpointer user_data)124 filter_archived_lists_func (gpointer item,
125                             gpointer user_data)
126 {
127   GtdTaskList *list;
128   GtdTask *task;
129 
130   task = (GtdTask*) item;
131   list = gtd_task_get_list (task);
132 
133   return !gtd_task_list_get_archived (list);
134 }
135 
136 static gboolean
filter_inbox_cb(gpointer item,gpointer user_data)137 filter_inbox_cb (gpointer item,
138                  gpointer user_data)
139 {
140   GtdProvider *provider = gtd_task_list_get_provider (item);
141 
142   return gtd_provider_get_inbox (provider) == item;
143 }
144 
145 static gint
compare_lists_cb(GtdTaskList * list_a,GtdTaskList * list_b,gpointer user_data)146 compare_lists_cb (GtdTaskList *list_a,
147                   GtdTaskList *list_b,
148                   gpointer     user_data)
149 {
150   gint result;
151 
152   /* First, compare by their providers */
153   result = gtd_provider_compare (gtd_task_list_get_provider (list_a), gtd_task_list_get_provider (list_b));
154 
155   if (result != 0)
156     return result;
157 
158   return gtd_collate_compare_strings (gtd_task_list_get_name (list_a), gtd_task_list_get_name (list_b));
159 }
160 
161 static void
on_task_list_modified_cb(GtdTaskList * list,GtdTask * task,GtdManager * self)162 on_task_list_modified_cb (GtdTaskList *list,
163                           GtdTask     *task,
164                           GtdManager  *self)
165 {
166   GTD_ENTRY;
167   g_signal_emit (self, signals[LIST_CHANGED], 0, list);
168   GTD_EXIT;
169 }
170 
171 static void
on_list_added_cb(GtdProvider * provider,GtdTaskList * list,GtdManager * self)172 on_list_added_cb (GtdProvider *provider,
173                   GtdTaskList *list,
174                   GtdManager  *self)
175 {
176   GTD_ENTRY;
177 
178   gtd_list_store_insert_sorted (GTD_LIST_STORE (self->lists_model),
179                                 list,
180                                 (GCompareDataFunc) compare_lists_cb,
181                                 self);
182 
183   g_signal_connect (list,
184                     "task-added",
185                     G_CALLBACK (on_task_list_modified_cb),
186                     self);
187 
188   g_signal_connect (list,
189                     "task-updated",
190                     G_CALLBACK (on_task_list_modified_cb),
191                     self);
192 
193   g_signal_connect (list,
194                     "task-removed",
195                     G_CALLBACK (on_task_list_modified_cb),
196                     self);
197 
198   g_signal_emit (self, signals[LIST_ADDED], 0, list);
199 
200   GTD_EXIT;
201 }
202 
203 static void
on_list_changed_cb(GtdProvider * provider,GtdTaskList * list,GtdManager * self)204 on_list_changed_cb (GtdProvider *provider,
205                     GtdTaskList *list,
206                     GtdManager  *self)
207 {
208   GtkFilter *filter;
209 
210   GTD_ENTRY;
211 
212   gtd_list_store_sort (GTD_LIST_STORE (self->lists_model),
213                        (GCompareDataFunc) compare_lists_cb,
214                        self);
215 
216   filter = gtk_filter_list_model_get_filter (GTK_FILTER_LIST_MODEL (self->unarchived_tasks_model));
217   gtk_filter_changed (filter, GTK_FILTER_CHANGE_DIFFERENT);
218 
219   g_signal_emit (self, signals[LIST_CHANGED], 0, list);
220 
221   GTD_EXIT;
222 }
223 
224 static void
on_list_removed_cb(GtdProvider * provider,GtdTaskList * list,GtdManager * self)225 on_list_removed_cb (GtdProvider *provider,
226                     GtdTaskList *list,
227                     GtdManager  *self)
228 {
229   GTD_ENTRY;
230 
231   if (!list)
232       GTD_RETURN ();
233 
234   gtd_list_store_remove (GTD_LIST_STORE (self->lists_model), list);
235 
236   g_signal_handlers_disconnect_by_func (list,
237                                         on_task_list_modified_cb,
238                                         self);
239 
240   g_signal_emit (self, signals[LIST_REMOVED], 0, list);
241 
242   GTD_EXIT;
243 }
244 
245 
246 /*
247  * GObject overrides
248  */
249 
250 static void
gtd_manager_finalize(GObject * object)251 gtd_manager_finalize (GObject *object)
252 {
253   GtdManager *self = (GtdManager *)object;
254 
255   g_cancellable_cancel (self->cancellable);
256   g_clear_object (&self->cancellable);
257   g_clear_object (&self->plugin_manager);
258   g_clear_object (&self->settings);
259   g_clear_object (&self->clock);
260   g_clear_object (&self->unarchived_tasks_model);
261   g_clear_object (&self->lists_model);
262   g_clear_object (&self->inbox_model);
263 
264   G_OBJECT_CLASS (gtd_manager_parent_class)->finalize (object);
265 }
266 
267 static void
gtd_manager_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)268 gtd_manager_get_property (GObject    *object,
269                           guint       prop_id,
270                           GValue     *value,
271                           GParamSpec *pspec)
272 {
273   GtdManager *self = (GtdManager *) object;
274 
275   switch (prop_id)
276     {
277     case PROP_DEFAULT_PROVIDER:
278       g_value_set_object (value, self->default_provider);
279       break;
280 
281     case PROP_CLOCK:
282       g_value_set_object (value, self->clock);
283       break;
284 
285     case PROP_PLUGIN_MANAGER:
286       g_value_set_object (value, self->plugin_manager);
287       break;
288 
289     default:
290       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
291     }
292 }
293 
294 static void
gtd_manager_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)295 gtd_manager_set_property (GObject      *object,
296                           guint         prop_id,
297                           const GValue *value,
298                           GParamSpec   *pspec)
299 {
300   GtdManager *self = (GtdManager *) object;
301 
302   switch (prop_id)
303     {
304     case PROP_DEFAULT_PROVIDER:
305       if (g_set_object (&self->default_provider, g_value_get_object (value)))
306         g_object_notify (object, "default-provider");
307       break;
308 
309     default:
310       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
311     }
312 }
313 
314 static void
gtd_manager_class_init(GtdManagerClass * klass)315 gtd_manager_class_init (GtdManagerClass *klass)
316 {
317   GObjectClass *object_class = G_OBJECT_CLASS (klass);
318 
319   object_class->finalize = gtd_manager_finalize;
320   object_class->get_property = gtd_manager_get_property;
321   object_class->set_property = gtd_manager_set_property;
322 
323   /**
324    * GtdManager::default-provider:
325    *
326    * The default provider.
327    */
328   g_object_class_install_property (
329         object_class,
330         PROP_DEFAULT_PROVIDER,
331         g_param_spec_object ("default-provider",
332                              "The default provider of the application",
333                              "The default provider of the application",
334                              GTD_TYPE_PROVIDER,
335                              G_PARAM_READWRITE));
336 
337   /**
338    * GtdManager::clock:
339    *
340    * The underlying clock of GNOME To Do.
341    */
342   g_object_class_install_property (
343         object_class,
344         PROP_CLOCK,
345         g_param_spec_object ("clock",
346                              "The clock",
347                              "The clock of the application",
348                              GTD_TYPE_CLOCK,
349                              G_PARAM_READABLE));
350 
351   /**
352    * GtdManager::plugin-manager:
353    *
354    * The plugin manager.
355    */
356   g_object_class_install_property (
357         object_class,
358         PROP_PLUGIN_MANAGER,
359         g_param_spec_object ("plugin-manager",
360                              "The plugin manager",
361                              "The plugin manager of the application",
362                              GTD_TYPE_PLUGIN_MANAGER,
363                              G_PARAM_READABLE));
364 
365   /**
366    * GtdManager::list-added:
367    * @manager: a #GtdManager
368    * @list: a #GtdTaskList
369    *
370    * The ::list-added signal is emmited after a #GtdTaskList
371    * is connected.
372    */
373   signals[LIST_ADDED] = g_signal_new ("list-added",
374                                       GTD_TYPE_MANAGER,
375                                       G_SIGNAL_RUN_LAST,
376                                       0,
377                                       NULL,
378                                       NULL,
379                                       NULL,
380                                       G_TYPE_NONE,
381                                       1,
382                                       GTD_TYPE_TASK_LIST);
383 
384   /**
385    * GtdManager::list-changed:
386    * @manager: a #GtdManager
387    * @list: a #GtdTaskList
388    *
389    * The ::list-changed signal is emmited after a #GtdTaskList
390    * has any of it's properties changed.
391    */
392   signals[LIST_CHANGED] = g_signal_new ("list-changed",
393                                         GTD_TYPE_MANAGER,
394                                         G_SIGNAL_RUN_LAST,
395                                         0,
396                                         NULL,
397                                         NULL,
398                                         NULL,
399                                         G_TYPE_NONE,
400                                         1,
401                                         GTD_TYPE_TASK_LIST);
402 
403   /**
404    * GtdManager::list-removed:
405    * @manager: a #GtdManager
406    * @list: a #GtdTaskList
407    *
408    * The ::list-removed signal is emmited after a #GtdTaskList
409    * is disconnected.
410    */
411   signals[LIST_REMOVED] = g_signal_new ("list-removed",
412                                         GTD_TYPE_MANAGER,
413                                         G_SIGNAL_RUN_LAST,
414                                         0,
415                                         NULL,
416                                         NULL,
417                                         NULL,
418                                         G_TYPE_NONE,
419                                         1,
420                                         GTD_TYPE_TASK_LIST);
421 
422   /**
423    * GtdManager::show-error-message:
424    * @manager: a #GtdManager
425    * @primary_text: the primary message
426    * @secondary_text: the detailed explanation of the error or the text to the notification button.
427    * @action : optionally action of type GtdNotificationActionFunc ignored if it's null.
428    * @user_data : user data passed to the action.
429    *
430    * Notifies about errors, and sends the error message for widgets
431    * to display.
432    */
433   signals[SHOW_ERROR_MESSAGE] = g_signal_new ("show-error-message",
434                                               GTD_TYPE_MANAGER,
435                                               G_SIGNAL_RUN_LAST,
436                                               0,
437                                               NULL,
438                                               NULL,
439                                               NULL,
440                                               G_TYPE_NONE,
441                                               4,
442                                               G_TYPE_STRING,
443                                               G_TYPE_STRING,
444                                               G_TYPE_POINTER,
445                                               G_TYPE_POINTER);
446 
447   /**
448    * GtdManager::show-notification:
449    * @manager: a #GtdManager
450    * @notification: the #GtdNotification
451    *
452    * Sends a notification.
453    */
454   signals[SHOW_NOTIFICATION] = g_signal_new ("show-notification",
455                                              GTD_TYPE_MANAGER,
456                                              G_SIGNAL_RUN_LAST,
457                                              0,
458                                              NULL,
459                                              NULL,
460                                              NULL,
461                                              G_TYPE_NONE,
462                                              1,
463                                              GTD_TYPE_NOTIFICATION);
464 
465   /**
466    * GtdManager::provider-added:
467    * @manager: a #GtdManager
468    * @provider: a #GtdProvider
469    *
470    * The ::provider-added signal is emmited after a #GtdProvider
471    * is added.
472    */
473   signals[PROVIDER_ADDED] = g_signal_new ("provider-added",
474                                           GTD_TYPE_MANAGER,
475                                           G_SIGNAL_RUN_LAST,
476                                           0,
477                                           NULL,
478                                           NULL,
479                                           NULL,
480                                           G_TYPE_NONE,
481                                           1,
482                                           GTD_TYPE_PROVIDER);
483 
484   /**
485    * GtdManager::provider-removed:
486    * @manager: a #GtdManager
487    * @provider: a #GtdProvider
488    *
489    * The ::provider-removed signal is emmited after a #GtdProvider
490    * is removed from the list.
491    */
492   signals[PROVIDER_REMOVED] = g_signal_new ("provider-removed",
493                                             GTD_TYPE_MANAGER,
494                                             G_SIGNAL_RUN_LAST,
495                                             0,
496                                             NULL,
497                                             NULL,
498                                             NULL,
499                                             G_TYPE_NONE,
500                                             1,
501                                             GTD_TYPE_PROVIDER);
502 }
503 
504 
505 static void
gtd_manager_init(GtdManager * self)506 gtd_manager_init (GtdManager *self)
507 {
508   GtkCustomFilter *archived_lists_filter;
509   GtkCustomFilter *inbox_filter;
510 
511   inbox_filter = gtk_custom_filter_new (filter_inbox_cb, self, NULL);
512   archived_lists_filter = gtk_custom_filter_new (filter_archived_lists_func, self, NULL);
513 
514   self->settings = g_settings_new ("org.gnome.todo");
515   self->plugin_manager = gtd_plugin_manager_new ();
516   self->clock = gtd_clock_new ();
517   self->cancellable = g_cancellable_new ();
518   self->lists_model = (GListModel*) gtd_list_store_new (GTD_TYPE_TASK_LIST);
519   self->inbox_model = (GListModel*) gtk_filter_list_model_new (self->lists_model,
520                                                                GTK_FILTER (inbox_filter));
521   self->tasks_model = (GListModel*) _gtd_task_model_new (self);
522   self->unarchived_tasks_model = (GListModel*) gtk_filter_list_model_new (self->tasks_model,
523                                                                           GTK_FILTER (archived_lists_filter));
524   self->providers_model = (GListModel*) gtd_list_store_new (GTD_TYPE_PROVIDER);
525 }
526 
527 /**
528  * gtd_manager_get_default:
529  *
530  * Retrieves the singleton #GtdManager instance. You should always
531  * use this function instead of @gtd_manager_new.
532  *
533  * Returns: (transfer none): the singleton #GtdManager instance.
534  */
535 GtdManager*
gtd_manager_get_default(void)536 gtd_manager_get_default (void)
537 {
538   if (!gtd_manager_instance)
539     gtd_manager_instance = gtd_manager_new ();
540 
541   return gtd_manager_instance;
542 }
543 
544 GtdManager*
gtd_manager_new(void)545 gtd_manager_new (void)
546 {
547   return g_object_new (GTD_TYPE_MANAGER, NULL);
548 }
549 
550 /**
551  * gtd_manager_get_providers:
552  * @manager: a #GtdManager
553  *
554  * Retrieves the list of available #GtdProvider.
555  *
556  * Returns: (transfer container) (element-type Gtd.Provider): a newly allocated #GList of
557  * #GtdStorage. Free with @g_list_free after use.
558  */
559 GList*
gtd_manager_get_providers(GtdManager * self)560 gtd_manager_get_providers (GtdManager *self)
561 {
562   g_return_val_if_fail (GTD_IS_MANAGER (self), NULL);
563 
564   return g_list_copy (self->providers);
565 }
566 
567 /**
568  * gtd_manager_add_provider:
569  * @self: a #GtdManager
570  * @provider: a #GtdProvider
571  *
572  * Adds @provider to the list of providers.
573  */
574 void
gtd_manager_add_provider(GtdManager * self,GtdProvider * provider)575 gtd_manager_add_provider (GtdManager  *self,
576                           GtdProvider *provider)
577 {
578   g_autoptr (GList) lists = NULL;
579   GList *l;
580 
581   g_return_if_fail (GTD_IS_MANAGER (self));
582   g_return_if_fail (GTD_IS_PROVIDER (provider));
583 
584   GTD_ENTRY;
585 
586   self->providers = g_list_prepend (self->providers, provider);
587   gtd_list_store_append (GTD_LIST_STORE (self->providers_model), provider);
588 
589   /* Add lists */
590   lists = gtd_provider_get_task_lists (provider);
591 
592   for (l = lists; l != NULL; l = l->next)
593     on_list_added_cb (provider, l->data, self);
594 
595   g_object_connect (provider,
596                     "signal::list-added", G_CALLBACK (on_list_added_cb), self,
597                     "signal::list-changed", G_CALLBACK (on_list_changed_cb), self,
598                     "signal::list-removed", G_CALLBACK (on_list_removed_cb), self,
599                     NULL);
600 
601   /* If we just added the default provider, update the property */
602   check_provider_is_default (self, provider);
603 
604   g_signal_emit (self, signals[PROVIDER_ADDED], 0, provider);
605 
606   GTD_EXIT;
607 }
608 
609 /**
610  * gtd_manager_remove_provider:
611  * @self: a #GtdManager
612  * @provider: a #GtdProvider
613  *
614  * Removes @provider from the list of providers.
615  */
616 void
gtd_manager_remove_provider(GtdManager * self,GtdProvider * provider)617 gtd_manager_remove_provider (GtdManager  *self,
618                              GtdProvider *provider)
619 {
620   g_autoptr (GList) lists = NULL;
621   GList *l;
622 
623   g_return_if_fail (GTD_IS_MANAGER (self));
624   g_return_if_fail (GTD_IS_PROVIDER (provider));
625 
626   GTD_ENTRY;
627 
628   self->providers = g_list_remove (self->providers, provider);
629   gtd_list_store_remove (GTD_LIST_STORE (self->providers_model), provider);
630 
631   /* Remove lists */
632   lists = gtd_provider_get_task_lists (provider);
633 
634   for (l = lists; l != NULL; l = l->next)
635     on_list_removed_cb (provider, l->data, self);
636 
637   g_signal_handlers_disconnect_by_func (provider, on_list_added_cb, self);
638   g_signal_handlers_disconnect_by_func (provider, on_list_changed_cb, self);
639   g_signal_handlers_disconnect_by_func (provider, on_list_removed_cb, self);
640 
641   g_signal_emit (self, signals[PROVIDER_REMOVED], 0, provider);
642 
643   GTD_EXIT;
644 }
645 
646 
647 /**
648  * gtd_manager_get_default_provider:
649  * @manager: a #GtdManager
650  *
651  * Retrieves the default provider location. Default is "local".
652  *
653  * Returns: (transfer none): the default provider.
654  */
655 GtdProvider*
gtd_manager_get_default_provider(GtdManager * self)656 gtd_manager_get_default_provider (GtdManager *self)
657 {
658   g_return_val_if_fail (GTD_IS_MANAGER (self), NULL);
659 
660   return self->default_provider;
661 }
662 
663 /**
664  * gtd_manager_set_default_provider:
665  * @manager: a #GtdManager
666  * @provider: (nullable): the default provider.
667  *
668  * Sets the provider.
669  */
670 void
gtd_manager_set_default_provider(GtdManager * self,GtdProvider * provider)671 gtd_manager_set_default_provider (GtdManager  *self,
672                                   GtdProvider *provider)
673 {
674   g_return_if_fail (GTD_IS_MANAGER (self));
675 
676   if (!g_set_object (&self->default_provider, provider))
677     return;
678 
679   g_settings_set_string (self->settings,
680                          "default-provider",
681                          provider ? gtd_provider_get_id (provider) : "local");
682 
683   g_object_notify (G_OBJECT (self), "default-provider");
684 }
685 
686 /**
687  * gtd_manager_get_inbox:
688  * @self: a #GtdManager
689  *
690  * Retrieves the local inbox.
691  *
692  * Returns: (transfer none)(nullable): a #GtdTaskList
693  */
694 GtdTaskList*
gtd_manager_get_inbox(GtdManager * self)695 gtd_manager_get_inbox (GtdManager *self)
696 {
697   GList *l;
698 
699   g_return_val_if_fail (GTD_IS_MANAGER (self), NULL);
700 
701   for (l = self->providers; l; l = l->next)
702     {
703       if (g_str_equal (gtd_provider_get_id (l->data), "local"))
704         return gtd_provider_get_inbox (l->data);
705     }
706 
707   return NULL;
708 }
709 
710 /**
711  * gtd_manager_get_settings:
712  * @manager: a #GtdManager
713  *
714  * Retrieves the internal #GSettings from @manager.
715  *
716  * Returns: (transfer none): the internal #GSettings of @manager
717  */
718 GSettings*
gtd_manager_get_settings(GtdManager * self)719 gtd_manager_get_settings (GtdManager *self)
720 {
721   g_return_val_if_fail (GTD_IS_MANAGER (self), NULL);
722 
723   return self->settings;
724 }
725 
726 /**
727  * gtd_manager_get_is_first_run:
728  * @manager: a #GtdManager
729  *
730  * Retrieves the 'first-run' setting.
731  *
732  * Returns: %TRUE if GNOME To Do was never run before, %FALSE otherwise.
733  */
734 gboolean
gtd_manager_get_is_first_run(GtdManager * self)735 gtd_manager_get_is_first_run (GtdManager *self)
736 {
737   g_return_val_if_fail (GTD_IS_MANAGER (self), FALSE);
738 
739   return g_settings_get_boolean (self->settings, "first-run");
740 }
741 
742 /**
743  * gtd_manager_set_is_first_run:
744  * @manager: a #GtdManager
745  * @is_first_run: %TRUE to make it first run, %FALSE otherwise.
746  *
747  * Sets the 'first-run' setting.
748  */
749 void
gtd_manager_set_is_first_run(GtdManager * self,gboolean is_first_run)750 gtd_manager_set_is_first_run (GtdManager *self,
751                               gboolean    is_first_run)
752 {
753   g_return_if_fail (GTD_IS_MANAGER (self));
754 
755   g_settings_set_boolean (self->settings, "first-run", is_first_run);
756 }
757 
758 /**
759  * gtd_manager_emit_error_message:
760  * @self: a #GtdManager
761  * @title: (nullable): the title of the error
762  * @description: (nullable): detailed description of the error
763  * @function: (nullable): function to be called when the notification is dismissed
764  * @user_data: user data
765  *
766  * Reports an error.
767  */
768 void
gtd_manager_emit_error_message(GtdManager * self,const gchar * title,const gchar * description,GtdErrorActionFunc function,gpointer user_data)769 gtd_manager_emit_error_message (GtdManager         *self,
770                                 const gchar        *title,
771                                 const gchar        *description,
772                                 GtdErrorActionFunc  function,
773                                 gpointer            user_data)
774 {
775   g_return_if_fail (GTD_IS_MANAGER (self));
776 
777   g_signal_emit (self,
778                  signals[SHOW_ERROR_MESSAGE],
779                  0,
780                  title,
781                  description,
782                  function,
783                  user_data);
784 }
785 
786 /**
787  * gtd_manager_send_notification:
788  * @self: a #GtdManager
789  * @notification: a #GtdNotification
790  *
791  * Sends a notification to the notification system.
792  */
793 void
gtd_manager_send_notification(GtdManager * self,GtdNotification * notification)794 gtd_manager_send_notification (GtdManager      *self,
795                                GtdNotification *notification)
796 {
797   g_return_if_fail (GTD_IS_MANAGER (self));
798 
799   g_signal_emit (self, signals[SHOW_NOTIFICATION], 0, notification);
800 }
801 
802 /**
803  * gtd_manager_get_clock:
804  * @self: a #GtdManager
805  *
806  * Retrieves the #GtdClock from @self. You can use the
807  * clock to know when your code should be updated.
808  *
809  * Returns: (transfer none): a #GtdClock
810  */
811 GtdClock*
gtd_manager_get_clock(GtdManager * self)812 gtd_manager_get_clock (GtdManager *self)
813 {
814   g_return_val_if_fail (GTD_IS_MANAGER (self), NULL);
815 
816   return self->clock;
817 }
818 
819 /**
820  * gtd_manager_get_task_lists_model:
821  * @self: a #GtdManager
822  *
823  * Retrieves the #GListModel containing #GtdTaskLists from
824  * @self. You can use the this model to bind to GtkListBox
825  * or other widgets.
826  *
827  * The model is sorted.
828  *
829  * Returns: (transfer none): a #GListModel
830  */
831 GListModel*
gtd_manager_get_task_lists_model(GtdManager * self)832 gtd_manager_get_task_lists_model (GtdManager *self)
833 {
834   g_return_val_if_fail (GTD_IS_MANAGER (self), NULL);
835 
836   return self->lists_model;
837 }
838 
839 
840 /**
841  * gtd_manager_get_all_tasks_model:
842  * @self: a #GtdManager
843  *
844  * Retrieves the #GListModel containing #GtdTasks from
845  * @self. You can use the this model to bind to GtkListBox
846  * or other widgets.
847  *
848  * The model is sorted.
849  *
850  * Returns: (transfer none): a #GListModel
851  */
852 GListModel*
gtd_manager_get_all_tasks_model(GtdManager * self)853 gtd_manager_get_all_tasks_model (GtdManager *self)
854 {
855   g_return_val_if_fail (GTD_IS_MANAGER (self), NULL);
856 
857   return self->tasks_model;
858 }
859 
860 /**
861  * gtd_manager_get_tasks_model:
862  * @self: a #GtdManager
863  *
864  * Retrieves the #GListModel containing #GtdTasks from
865  * @self. You can use the this model to bind to GtkListBox
866  * or other widgets.
867  *
868  * The model returned by this function is filtered to only
869  * contain tasks from unarchived lists. If you need all tasks,
870  * see gtd_manager_get_all_tasks_model().
871  *
872  * The model is sorted.
873  *
874  * Returns: (transfer none): a #GListModel
875  */
876 GListModel*
gtd_manager_get_tasks_model(GtdManager * self)877 gtd_manager_get_tasks_model (GtdManager *self)
878 {
879   g_return_val_if_fail (GTD_IS_MANAGER (self), NULL);
880 
881   return self->unarchived_tasks_model;
882 }
883 
884 /**
885  * gtd_manager_get_inbox_model:
886  * @self: a #GtdManager
887  *
888  * Retrieves the #GListModel containing #GtdTaskLists that are
889  * inbox.
890  *
891  * Returns: (transfer none): a #GListModel
892  */
893 GListModel*
gtd_manager_get_inbox_model(GtdManager * self)894 gtd_manager_get_inbox_model (GtdManager *self)
895 {
896   g_return_val_if_fail (GTD_IS_MANAGER (self), NULL);
897 
898   return self->inbox_model;
899 }
900 
901 /**
902  * gtd_manager_get_providers_model:
903  * @self: a #GtdManager
904  *
905  * Retrieves the #GListModel containing #GtdProviders.
906  *
907  * Returns: (transfer none): a #GListModel
908  */
909 GListModel*
gtd_manager_get_providers_model(GtdManager * self)910 gtd_manager_get_providers_model (GtdManager *self)
911 {
912   g_return_val_if_fail (GTD_IS_MANAGER (self), NULL);
913 
914   return self->providers_model;
915 }
916 
917 void
gtd_manager_load_plugins(GtdManager * self)918 gtd_manager_load_plugins (GtdManager *self)
919 {
920   GTD_ENTRY;
921 
922   gtd_plugin_manager_load_plugins (self->plugin_manager);
923 
924   GTD_EXIT;
925 }
926 
927 GtdPluginManager*
gtd_manager_get_plugin_manager(GtdManager * self)928 gtd_manager_get_plugin_manager (GtdManager *self)
929 {
930   g_return_val_if_fail (GTD_IS_MANAGER (self), NULL);
931 
932   return self->plugin_manager;
933 }
934