1 /* gtd-provider.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 "GtdProvider"
20 
21 #include "gtd-provider.h"
22 #include "gtd-task.h"
23 #include "gtd-task-list.h"
24 #include "gtd-utils.h"
25 
26 /**
27  * SECTION:gtd-provider
28  * @short_description:data sources for GNOME To do
29  * @title: GtdProvider
30  * @stability:Unstable
31  *
32  * The #GtdProvider is the interface that GNOME To Do uses to
33  * connect to data sources. It must provide ways to create, update
34  * and remove tasks and tasklists.
35  *
36  * A provider implementation must also expose which is the default
37  * tasklist among the tasklists it manages.
38  */
39 
40 G_DEFINE_INTERFACE (GtdProvider, gtd_provider, GTD_TYPE_OBJECT)
41 
42 enum
43 {
44   LIST_ADDED,
45   LIST_CHANGED,
46   LIST_REMOVED,
47   NUM_SIGNALS
48 };
49 
50 static guint signals[NUM_SIGNALS] = { 0, };
51 
52 
53 static void
gtd_provider_default_init(GtdProviderInterface * iface)54 gtd_provider_default_init (GtdProviderInterface *iface)
55 {
56   /**
57    * GtdProvider::enabled:
58    *
59    * Whether the #GtdProvider is enabled.
60    */
61   g_object_interface_install_property (iface,
62                                        g_param_spec_boolean ("enabled",
63                                                              "Identifier of the provider",
64                                                              "The identifier of the provider",
65                                                              FALSE,
66                                                              G_PARAM_READABLE));
67 
68   /**
69    * GtdProvider::icon:
70    *
71    * The icon of the #GtdProvider, e.g. the account icon
72    * of a GNOME Online Accounts' account.
73    */
74   g_object_interface_install_property (iface,
75                                        g_param_spec_object ("icon",
76                                                             "Icon of the provider",
77                                                             "The icon of the provider",
78                                                             G_TYPE_ICON,
79                                                             G_PARAM_READABLE));
80 
81   /**
82    * GtdProvider::id:
83    *
84    * The unique identifier of the #GtdProvider.
85    */
86   g_object_interface_install_property (iface,
87                                        g_param_spec_string ("id",
88                                                             "Identifier of the provider",
89                                                             "The identifier of the provider",
90                                                             NULL,
91                                                             G_PARAM_READABLE));
92 
93   /**
94    * GtdProvider::name:
95    *
96    * The user-visible name of the #GtdProvider.
97    */
98   g_object_interface_install_property (iface,
99                                        g_param_spec_string ("name",
100                                                             "Name of the provider",
101                                                             "The user-visible name of the provider",
102                                                             NULL,
103                                                             G_PARAM_READABLE));
104 
105   /**
106    * GtdProvider::provider-type:
107    *
108    * The type of the #GtdProvider.
109    */
110   g_object_interface_install_property (iface,
111                                        g_param_spec_string ("provider-type",
112                                                             "Type of the provider",
113                                                             "The type of the provider",
114                                                             NULL,
115                                                             G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
116 
117   /**
118    * GtdProvider::description:
119    *
120    * The description of the #GtdProvider, e.g. the account user
121    * of a GNOME Online Accounts' account.
122    */
123   g_object_interface_install_property (iface,
124                                        g_param_spec_string ("description",
125                                                             "Description of the provider",
126                                                             "The description of the provider",
127                                                             NULL,
128                                                             G_PARAM_READABLE));
129 
130   /**
131    * GtdProvider::list-added:
132    * @provider: a #GtdProvider
133    * @list: a #GtdTaskList
134    *
135    * The ::list-added signal is emmited after a #GtdTaskList
136    * is connected.
137    */
138   signals[LIST_ADDED] = g_signal_new ("list-added",
139                                       GTD_TYPE_PROVIDER,
140                                       G_SIGNAL_RUN_LAST,
141                                       0,
142                                       NULL,
143                                       NULL,
144                                       NULL,
145                                       G_TYPE_NONE,
146                                       1,
147                                       GTD_TYPE_TASK_LIST);
148 
149   /**
150    * GtdProvider::list-changed:
151    * @provider: a #GtdProvider
152    * @list: a #GtdTaskList
153    *
154    * The ::list-changed signal is emmited after a #GtdTaskList
155    * has any of it's properties changed.
156    */
157   signals[LIST_CHANGED] = g_signal_new ("list-changed",
158                                         GTD_TYPE_PROVIDER,
159                                         G_SIGNAL_RUN_LAST,
160                                         0,
161                                         NULL,
162                                         NULL,
163                                         NULL,
164                                         G_TYPE_NONE,
165                                         1,
166                                         GTD_TYPE_TASK_LIST);
167 
168   /**
169    * GtdProvider::list-removed:
170    * @provider: a #GtdProvider
171    * @list: a #GtdTaskList
172    *
173    * The ::list-removed signal is emmited after a #GtdTaskList
174    * is disconnected.
175    */
176   signals[LIST_REMOVED] = g_signal_new ("list-removed",
177                                         GTD_TYPE_PROVIDER,
178                                         G_SIGNAL_RUN_LAST,
179                                         0,
180                                         NULL,
181                                         NULL,
182                                         NULL,
183                                         G_TYPE_NONE,
184                                         1,
185                                         GTD_TYPE_TASK_LIST);
186 }
187 
188 /**
189  * gtd_provider_get_id:
190  * @provider: a #GtdProvider
191  *
192  * Retrieves the identifier of @provider.
193  *
194  * Returns: (transfer none): the id of @provider
195  */
196 const gchar*
gtd_provider_get_id(GtdProvider * provider)197 gtd_provider_get_id (GtdProvider *provider)
198 {
199   g_return_val_if_fail (GTD_IS_PROVIDER (provider), NULL);
200   g_return_val_if_fail (GTD_PROVIDER_GET_IFACE (provider)->get_id, NULL);
201 
202   return GTD_PROVIDER_GET_IFACE (provider)->get_id (provider);
203 }
204 
205 /**
206  * gtd_provider_get_name:
207  * @provider: a #GtdProvider
208  *
209  * Retrieves the user-visible name of @provider.
210  *
211  * Returns: (transfer none): the name of @provider
212  */
213 const gchar*
gtd_provider_get_name(GtdProvider * provider)214 gtd_provider_get_name (GtdProvider *provider)
215 {
216   g_return_val_if_fail (GTD_IS_PROVIDER (provider), NULL);
217   g_return_val_if_fail (GTD_PROVIDER_GET_IFACE (provider)->get_name, NULL);
218 
219   return GTD_PROVIDER_GET_IFACE (provider)->get_name (provider);
220 }
221 
222 /**
223  * gtd_provider_get_provider_type:
224  * @provider: a #GtdProvider
225  *
226  * Retrieves the type of the @provider. This should return the
227  * same value, regardless of the account name.
228  *
229  * For example: "todoist", "todo-txt" or "google"
230  *
231  * Returns: (transfer none): the type of the @provider
232  */
233 const gchar*
gtd_provider_get_provider_type(GtdProvider * provider)234 gtd_provider_get_provider_type (GtdProvider *provider)
235 {
236   g_return_val_if_fail (GTD_IS_PROVIDER (provider), NULL);
237   g_return_val_if_fail (GTD_PROVIDER_GET_IFACE (provider)->get_name, NULL);
238 
239   return GTD_PROVIDER_GET_IFACE (provider)->get_provider_type (provider);
240 }
241 
242 /**
243  * gtd_provider_get_description:
244  * @provider: a #GtdProvider
245  *
246  * Retrieves the description of @provider.
247  *
248  * Returns: (transfer none): the description of @provider
249  */
250 const gchar*
gtd_provider_get_description(GtdProvider * provider)251 gtd_provider_get_description (GtdProvider *provider)
252 {
253   g_return_val_if_fail (GTD_IS_PROVIDER (provider), NULL);
254   g_return_val_if_fail (GTD_PROVIDER_GET_IFACE (provider)->get_description, NULL);
255 
256   return GTD_PROVIDER_GET_IFACE (provider)->get_description (provider);
257 }
258 
259 /**
260  * gtd_provider_get_enabled:
261  * @provider: a #GtdProvider
262  *
263  * Retrieves whether @provider is enabled or not. A disabled
264  * provider cannot be selected to be default nor be selected
265  * to add tasks to it.
266  *
267  * Returns: %TRUE if provider is enabled, %FALSE otherwise.
268  */
269 gboolean
gtd_provider_get_enabled(GtdProvider * provider)270 gtd_provider_get_enabled (GtdProvider *provider)
271 {
272   g_return_val_if_fail (GTD_IS_PROVIDER (provider), FALSE);
273   g_return_val_if_fail (GTD_PROVIDER_GET_IFACE (provider)->get_enabled, FALSE);
274 
275   return GTD_PROVIDER_GET_IFACE (provider)->get_enabled (provider);
276 }
277 
278 /**
279  * gtd_provider_refresh:
280  * @provider: a #GtdProvider
281  *
282  * Asks the provider to refresh. Online providers may want to
283  * synchronize tasks and tasklists, credentials, etc, when this
284  * is called.
285  *
286  * This is an optional feature. Providers that do not implement
287  * the "refresh" vfunc will be ignored.
288  */
289 void
gtd_provider_refresh(GtdProvider * provider)290 gtd_provider_refresh (GtdProvider *provider)
291 {
292   g_return_if_fail (GTD_IS_PROVIDER (provider));
293 
294   if (GTD_PROVIDER_GET_IFACE (provider)->refresh)
295     GTD_PROVIDER_GET_IFACE (provider)->refresh (provider);
296 }
297 
298 /**
299  * gtd_provider_get_icon:
300  * @provider: a #GtdProvider
301  *
302  * The icon of @provider.
303  *
304  * Returns: (transfer none): a #GIcon
305  */
306 GIcon*
gtd_provider_get_icon(GtdProvider * provider)307 gtd_provider_get_icon (GtdProvider *provider)
308 {
309   g_return_val_if_fail (GTD_IS_PROVIDER (provider), NULL);
310   g_return_val_if_fail (GTD_PROVIDER_GET_IFACE (provider)->get_icon, NULL);
311 
312   return GTD_PROVIDER_GET_IFACE (provider)->get_icon (provider);
313 }
314 
315 /**
316  * gtd_provider_create_task:
317  * @provider: a #GtdProvider
318  * @task: a #GtdTask
319  * @due_date: (nullable): a #GDateTime
320  * @cancellable: (nullable): a #GCancellable
321  * @callback: (scope async): a callback
322  * @user_data: (closure): user data for @callback
323  *
324  * Creates the given task in @provider.
325  */
326 void
gtd_provider_create_task(GtdProvider * provider,GtdTaskList * list,const gchar * title,GDateTime * due_date,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)327 gtd_provider_create_task (GtdProvider         *provider,
328                           GtdTaskList         *list,
329                           const gchar         *title,
330                           GDateTime           *due_date,
331                           GCancellable        *cancellable,
332                           GAsyncReadyCallback  callback,
333                           gpointer             user_data)
334 {
335   g_return_if_fail (GTD_IS_PROVIDER (provider));
336   g_return_if_fail (GTD_PROVIDER_GET_IFACE (provider)->create_task);
337 
338   GTD_PROVIDER_GET_IFACE (provider)->create_task (provider,
339                                                   list,
340                                                   title,
341                                                   due_date,
342                                                   cancellable,
343                                                   callback,
344                                                   user_data);
345 }
346 
347 /**
348  * gtd_provider_create_task_finish:
349  * @self: a #GtdProvider
350  * @result: a #GAsyncResult
351  * @error: (direction out)(nullable): return location for a #GError
352  *
353  * Finishes creating the task.
354  *
355  * Returns: (transfer none)(nullable): a #GtdTask
356  */
357 GtdTask*
gtd_provider_create_task_finish(GtdProvider * self,GAsyncResult * result,GError ** error)358 gtd_provider_create_task_finish (GtdProvider   *self,
359                                  GAsyncResult  *result,
360                                  GError       **error)
361 {
362   g_return_val_if_fail (GTD_IS_PROVIDER (self), FALSE);
363   g_return_val_if_fail (!error || !*error, FALSE);
364   g_return_val_if_fail (GTD_PROVIDER_GET_IFACE (self)->create_task_finish, FALSE);
365 
366   return GTD_PROVIDER_GET_IFACE (self)->create_task_finish (self, result, error);
367 }
368 
369 /**
370  * gtd_provider_update_task:
371  * @provider: a #GtdProvider
372  * @task: a #GtdTask
373  * @cancellable: (nullable): a #GCancellable
374  * @callback: (scope async): a callback
375  * @user_data: (closure): user data for @callback
376  *
377  * Updates the given task in @provider.
378  */
379 void
gtd_provider_update_task(GtdProvider * provider,GtdTask * task,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)380 gtd_provider_update_task (GtdProvider         *provider,
381                           GtdTask             *task,
382                           GCancellable        *cancellable,
383                           GAsyncReadyCallback  callback,
384                           gpointer             user_data)
385 {
386   g_return_if_fail (GTD_IS_PROVIDER (provider));
387   g_return_if_fail (GTD_PROVIDER_GET_IFACE (provider)->update_task);
388 
389   GTD_PROVIDER_GET_IFACE (provider)->update_task (provider,
390                                                   task,
391                                                   cancellable,
392                                                   callback,
393                                                   user_data);
394 }
395 
396 /**
397  * gtd_provider_update_task_finish:
398  * @self: a #GtdProvider
399  * @result: a #GAsyncResult
400  * @error: (direction out)(nullable): return location for a #GError
401  *
402  * Finishes updating the task list.
403  *
404  * Returns: %TRUE if task list was successfully updated, %FALSE otherwise
405  */
406 gboolean
gtd_provider_update_task_finish(GtdProvider * self,GAsyncResult * result,GError ** error)407 gtd_provider_update_task_finish (GtdProvider   *self,
408                                  GAsyncResult  *result,
409                                  GError       **error)
410 {
411   g_return_val_if_fail (GTD_IS_PROVIDER (self), FALSE);
412   g_return_val_if_fail (!error || !*error, FALSE);
413   g_return_val_if_fail (GTD_PROVIDER_GET_IFACE (self)->update_task_finish, FALSE);
414 
415   return GTD_PROVIDER_GET_IFACE (self)->update_task_finish (self, result, error);
416 }
417 
418 /**
419  * gtd_provider_remove_task:
420  * @provider: a #GtdProvider
421  * @task: a #GtdTask
422  * @cancellable: (nullable): a #GCancellable
423  * @callback: (scope async): a callback
424  * @user_data: (closure): user data for @callback
425  *
426  * Removes the given task from @provider.
427  */
428 void
gtd_provider_remove_task(GtdProvider * provider,GtdTask * task,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)429 gtd_provider_remove_task (GtdProvider         *provider,
430                           GtdTask             *task,
431                           GCancellable        *cancellable,
432                           GAsyncReadyCallback  callback,
433                           gpointer             user_data)
434 {
435   g_return_if_fail (GTD_IS_PROVIDER (provider));
436   g_return_if_fail (GTD_PROVIDER_GET_IFACE (provider)->remove_task);
437 
438   GTD_PROVIDER_GET_IFACE (provider)->remove_task (provider,
439                                                   task,
440                                                   cancellable,
441                                                   callback,
442                                                   user_data);
443 }
444 
445 /**
446  * gtd_provider_remove_task_finish:
447  * @self: a #GtdProvider
448  * @result: a #GAsyncResult
449  * @error: (direction out)(nullable): return location for a #GError
450  *
451  * Finishes removing the task.
452  *
453  * Returns: %TRUE if task was successfully removed, %FALSE otherwise
454  */
455 gboolean
gtd_provider_remove_task_finish(GtdProvider * self,GAsyncResult * result,GError ** error)456 gtd_provider_remove_task_finish (GtdProvider   *self,
457                                  GAsyncResult  *result,
458                                  GError       **error)
459 {
460   g_return_val_if_fail (GTD_IS_PROVIDER (self), FALSE);
461   g_return_val_if_fail (!error || !*error, FALSE);
462   g_return_val_if_fail (GTD_PROVIDER_GET_IFACE (self)->remove_task_finish, FALSE);
463 
464   return GTD_PROVIDER_GET_IFACE (self)->remove_task_finish (self, result, error);
465 }
466 
467 /**
468  * gtd_provider_create_task_list:
469  * @provider: a #GtdProvider
470  * @name: (nullable): the name of the new task list
471  * @cancellable: (nullable): a #GCancellable
472  * @callback: (scope async): a callback
473  * @user_data: (closure): user data for @callback
474  *
475  * Creates the given list in @provider.
476  */
477 void
gtd_provider_create_task_list(GtdProvider * provider,const gchar * name,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)478 gtd_provider_create_task_list (GtdProvider         *provider,
479                                const gchar         *name,
480                                GCancellable        *cancellable,
481                                GAsyncReadyCallback  callback,
482                                gpointer             user_data)
483 {
484   g_return_if_fail (GTD_IS_PROVIDER (provider));
485   g_return_if_fail (GTD_PROVIDER_GET_IFACE (provider)->create_task_list);
486 
487   GTD_PROVIDER_GET_IFACE (provider)->create_task_list (provider,
488                                                        name,
489                                                        cancellable,
490                                                        callback,
491                                                        user_data);
492 }
493 
494 /**
495  * gtd_provider_create_task_list_finish:
496  * @self: a #GtdProvider
497  * @result: a #GAsyncResult
498  * @error: (direction out)(nullable): return location for a #GError
499  *
500  * Finishes creating the task list. The provider will emit the
501  * GtdProvider:list-added signal after creating the task list.
502  *
503  * Returns: %TRUE if task list was successfully created, %FALSE otherwise
504  */
505 gboolean
gtd_provider_create_task_list_finish(GtdProvider * self,GAsyncResult * result,GError ** error)506 gtd_provider_create_task_list_finish (GtdProvider   *self,
507                                       GAsyncResult  *result,
508                                       GError       **error)
509 {
510   g_return_val_if_fail (GTD_IS_PROVIDER (self), FALSE);
511   g_return_val_if_fail (!error || !*error, FALSE);
512   g_return_val_if_fail (GTD_PROVIDER_GET_IFACE (self)->create_task_list_finish, FALSE);
513 
514   return GTD_PROVIDER_GET_IFACE (self)->create_task_list_finish (self, result, error);
515 }
516 
517 /**
518  * gtd_provider_update_task_list:
519  * @provider: a #GtdProvider
520  * @list: a #GtdTaskList
521  * @cancellable: (nullable): a #GCancellable
522  * @callback: (scope async): a callback
523  * @user_data: (closure): user data for @callback
524  *
525  * Updates the given list in @provider.
526  */
527 void
gtd_provider_update_task_list(GtdProvider * provider,GtdTaskList * list,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)528 gtd_provider_update_task_list (GtdProvider         *provider,
529                                GtdTaskList         *list,
530                                GCancellable        *cancellable,
531                                GAsyncReadyCallback  callback,
532                                gpointer             user_data)
533 {
534   g_return_if_fail (GTD_IS_PROVIDER (provider));
535   g_return_if_fail (GTD_PROVIDER_GET_IFACE (provider)->update_task_list);
536 
537   GTD_PROVIDER_GET_IFACE (provider)->update_task_list (provider,
538                                                        list,
539                                                        cancellable,
540                                                        callback,
541                                                        user_data);
542 }
543 
544 /**
545  * gtd_provider_create_task_list_finish:
546  * @self: a #GtdProvider
547  * @result: a #GAsyncResult
548  * @error: (direction out)(nullable): return location for a #GError
549  *
550  * Finishes updating the task list. The provider will emit the
551  * GtdProvider:list-updated signal after updating the task list.
552  *
553  * Returns: %TRUE if task list was successfully created, %FALSE otherwise
554  */
555 gboolean
gtd_provider_update_task_list_finish(GtdProvider * self,GAsyncResult * result,GError ** error)556 gtd_provider_update_task_list_finish (GtdProvider   *self,
557                                       GAsyncResult  *result,
558                                       GError       **error)
559 {
560   g_return_val_if_fail (GTD_IS_PROVIDER (self), FALSE);
561   g_return_val_if_fail (!error || !*error, FALSE);
562   g_return_val_if_fail (GTD_PROVIDER_GET_IFACE (self)->update_task_list_finish, FALSE);
563 
564   return GTD_PROVIDER_GET_IFACE (self)->update_task_list_finish (self, result, error);
565 }
566 
567 /**
568  * gtd_provider_remove_task_list:
569  * @provider: a #GtdProvider
570  * @list: a #GtdTaskList
571  * @cancellable: (nullable): a #GCancellable
572  * @callback: (scope async): a callback
573  * @user_data: (closure): user data for @callback
574  *
575  * Removes the given list from @provider.
576  */
577 void
gtd_provider_remove_task_list(GtdProvider * provider,GtdTaskList * list,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)578 gtd_provider_remove_task_list (GtdProvider         *provider,
579                                GtdTaskList         *list,
580                                GCancellable        *cancellable,
581                                GAsyncReadyCallback  callback,
582                                gpointer             user_data)
583 {
584   g_return_if_fail (GTD_IS_PROVIDER (provider));
585   g_return_if_fail (GTD_PROVIDER_GET_IFACE (provider)->remove_task_list);
586 
587   GTD_PROVIDER_GET_IFACE (provider)->remove_task_list (provider,
588                                                        list,
589                                                        cancellable,
590                                                        callback,
591                                                        user_data);
592 }
593 
594 /**
595  * gtd_provider_remove_task_list_finish:
596  * @self: a #GtdProvider
597  * @result: a #GAsyncResult
598  * @error: (direction out)(nullable): return location for a #GError
599  *
600  * Finishes removing the task list. The provider will emit the
601  * GtdProvider:list-removed signal after removing the task list.
602  *
603  * Returns: %TRUE if task list was successfully removed, %FALSE otherwise
604  */
605 gboolean
gtd_provider_remove_task_list_finish(GtdProvider * self,GAsyncResult * result,GError ** error)606 gtd_provider_remove_task_list_finish (GtdProvider   *self,
607                                       GAsyncResult  *result,
608                                       GError       **error)
609 {
610   g_return_val_if_fail (GTD_IS_PROVIDER (self), FALSE);
611   g_return_val_if_fail (!error || !*error, FALSE);
612   g_return_val_if_fail (GTD_PROVIDER_GET_IFACE (self)->remove_task_list_finish, FALSE);
613 
614   return GTD_PROVIDER_GET_IFACE (self)->remove_task_list_finish (self, result, error);
615 }
616 
617 /**
618  * gtd_provider_get_task_lists:
619  * @provider: a #GtdProvider
620  *
621  * Retrieves the tasklists that this provider contains.
622  *
623  * Returns: (transfer container) (element-type Gtd.TaskList): the list of tasks, or %NULL
624  */
625 GList*
gtd_provider_get_task_lists(GtdProvider * provider)626 gtd_provider_get_task_lists (GtdProvider *provider)
627 {
628   g_return_val_if_fail (GTD_IS_PROVIDER (provider), NULL);
629   g_return_val_if_fail (GTD_PROVIDER_GET_IFACE (provider)->get_task_lists, NULL);
630 
631   return GTD_PROVIDER_GET_IFACE (provider)->get_task_lists (provider);
632 }
633 
634 /**
635  * gtd_provider_get_inbox:
636  * @provider: a #GtdProvider
637  *
638  * Retrieves the inbox of @provider.
639  *
640  * Returns: (transfer none)(nullable): a #GtdTaskList
641  */
642 GtdTaskList*
gtd_provider_get_inbox(GtdProvider * provider)643 gtd_provider_get_inbox (GtdProvider *provider)
644 {
645   g_return_val_if_fail (GTD_IS_PROVIDER (provider), NULL);
646   g_return_val_if_fail (GTD_PROVIDER_GET_IFACE (provider)->get_inbox, NULL);
647 
648   return GTD_PROVIDER_GET_IFACE (provider)->get_inbox (provider);
649 }
650 
651 /**
652  * gtd_provider_compare:
653  * @a: a #GtdProvider
654  * @b: a #GtdProvider
655  *
656  * Compares @a and @b. The sorting criteria is internal and
657  * may change.
658  *
659  * Returns: -1 if @a comes before @b, 1 for the oposite, and
660  * 0 if they're equal
661  */
662 gint
gtd_provider_compare(GtdProvider * a,GtdProvider * b)663 gtd_provider_compare (GtdProvider *a,
664                       GtdProvider *b)
665 {
666   gint result;
667 
668   g_return_val_if_fail (GTD_IS_PROVIDER (a), 0);
669   g_return_val_if_fail (GTD_IS_PROVIDER (b), 0);
670 
671   if (a == b)
672     return 0;
673 
674   result = gtd_collate_compare_strings (gtd_provider_get_name (a), gtd_provider_get_name (b));
675 
676   if (result != 0)
677     return result;
678 
679   return gtd_collate_compare_strings (gtd_provider_get_description (a), gtd_provider_get_description (b));
680 }
681