diff options
author | Matthew Barnes <mbarnes@src.gnome.org> | 2008-09-12 09:54:07 +0800 |
---|---|---|
committer | Matthew Barnes <mbarnes@src.gnome.org> | 2008-09-12 09:54:07 +0800 |
commit | df6a8262a141e0bec824149e7f65568d2187c5c2 (patch) | |
tree | 463604008060e542f3dcdbfdd5fce4e056af8c1c | |
parent | cbe90f148abbfd273f301358c7fa73a58ff5dd41 (diff) | |
download | gsoc2013-evolution-df6a8262a141e0bec824149e7f65568d2187c5c2.tar gsoc2013-evolution-df6a8262a141e0bec824149e7f65568d2187c5c2.tar.gz gsoc2013-evolution-df6a8262a141e0bec824149e7f65568d2187c5c2.tar.bz2 gsoc2013-evolution-df6a8262a141e0bec824149e7f65568d2187c5c2.tar.lz gsoc2013-evolution-df6a8262a141e0bec824149e7f65568d2187c5c2.tar.xz gsoc2013-evolution-df6a8262a141e0bec824149e7f65568d2187c5c2.tar.zst gsoc2013-evolution-df6a8262a141e0bec824149e7f65568d2187c5c2.zip |
Arrange for an ESourceList to be shared amongst all instances of a type of
shell view. For example, all EBookShellView instances will now share the
same ESourceList instance for address books.
svn path=/branches/kill-bonobo/; revision=36311
29 files changed, 890 insertions, 498 deletions
diff --git a/addressbook/gui/component/e-book-shell-module.c b/addressbook/gui/component/e-book-shell-module.c index 117206c9b7..7f4b2a8875 100644 --- a/addressbook/gui/component/e-book-shell-module.c +++ b/addressbook/gui/component/e-book-shell-module.c @@ -57,28 +57,42 @@ GalViewCollection *e_book_shell_module_view_collection = NULL; static void book_module_ensure_sources (EShellModule *shell_module) { + /* XXX This is basically the same algorithm across all modules. + * Maybe we could somehow integrate this into EShellModule? */ + ESourceList *source_list; ESourceGroup *on_this_computer; ESourceGroup *on_ldap_servers; - ESource *personal_source; + ESource *personal; GSList *groups, *iter; - const gchar *base_dir; + const gchar *data_dir; gchar *base_uri; - gchar *base_uri_proto; + gchar *filename; on_this_computer = NULL; on_ldap_servers = NULL; - personal_source = NULL; + personal = NULL; if (!e_book_get_addressbooks (&source_list, NULL)) { g_warning ("Could not get addressbook sources from GConf!"); return; } - base_dir = e_shell_module_get_data_dir (shell_module); - base_uri = g_build_filename (base_dir, "local", NULL); - - base_uri_proto = g_filename_to_uri (base_uri, NULL, NULL); + /* Share the source list with all address book views. This + * is accessible via e_book_shell_view_get_source_list(). + * Note: EShellModule takes ownership of the reference. + * + * XXX I haven't yet decided if I want to add a proper + * EShellModule API for this. The mail module would + * not use it. */ + g_object_set_data_full ( + G_OBJECT (shell_module), "source-list", + source_list, (GDestroyNotify) g_object_unref); + + data_dir = e_shell_module_get_data_dir (shell_module); + filename = g_build_filename (data_dir, "local", NULL); + base_uri = g_filename_to_uri (filename, NULL, NULL); + g_free (filename); groups = e_source_list_peek_groups (source_list); for (iter = groups; iter != NULL; iter = iter->next) { @@ -87,14 +101,14 @@ book_module_ensure_sources (EShellModule *shell_module) group_base_uri = e_source_group_peek_base_uri (source_group); - /* Compare only "file://" part. if user home directory - * changes, we do not want to create one more group. */ + /* Compare only "file://" part. If the user's home + * changes, we do not want to create another group. */ if (on_this_computer == NULL && - strncmp (base_uri_proto, group_base_uri, 7) == 0) + strncmp (base_uri, group_base_uri, 7) == 0) on_this_computer = source_group; else if (on_ldap_servers == NULL && - g_str_equal (LDAP_BASE_URI, group_base_uri)) + strcmp (LDAP_BASE_URI, group_base_uri) == 0) on_ldap_servers = source_group; } @@ -105,7 +119,7 @@ book_module_ensure_sources (EShellModule *shell_module) sources = e_source_group_peek_sources (on_this_computer); group_base_uri = e_source_group_peek_base_uri (on_this_computer); - /* Make this group includes a "Personal" source. */ + /* Make sure this group includes a "Personal" source. */ for (iter = sources; iter != NULL; iter = iter->next) { ESource *source = iter->data; const gchar *relative_uri; @@ -114,22 +128,23 @@ book_module_ensure_sources (EShellModule *shell_module) if (relative_uri == NULL) continue; - if (g_str_equal (PERSONAL_RELATIVE_URI, relative_uri)) { - personal_source = source; - break; - } + if (strcmp (PERSONAL_RELATIVE_URI, relative_uri) != 0) + continue; + + personal = source; + break; } /* Make sure we have the correct base URI. This can * change when the user's home directory changes. */ - if (!g_str_equal (base_uri_proto, group_base_uri)) { + if (strcmp (base_uri, group_base_uri) != 0) { e_source_group_set_base_uri ( - on_this_computer, base_uri_proto); + on_this_computer, base_uri); /* XXX We shouldn't need this sync call here as * set_base_uri() results in synching to GConf, * but that happens in an idle loop and too late - * to prevent the user from seeing "Cannot + * to prevent the user from seeing a "Cannot * Open ... because of invalid URI" error. */ e_source_list_sync (source_list, NULL); } @@ -138,13 +153,13 @@ book_module_ensure_sources (EShellModule *shell_module) ESourceGroup *source_group; const gchar *name; - /* Create the local source group. */ name = _("On This Computer"); - source_group = e_source_group_new (name, base_uri_proto); + source_group = e_source_group_new (name, base_uri); e_source_list_add_group (source_list, source_group, -1); + g_object_unref (source_group); } - if (personal_source == NULL) { + if (personal == NULL) { ESource *source; const gchar *name; @@ -160,13 +175,12 @@ book_module_ensure_sources (EShellModule *shell_module) ESourceGroup *source_group; const gchar *name; - /* Create the LDAP source group. */ name = _("On LDAP Servers"); source_group = e_source_group_new (name, LDAP_BASE_URI); e_source_list_add_group (source_list, source_group, -1); + g_object_unref (source_group); } - g_free (base_uri_proto); g_free (base_uri); } @@ -236,10 +250,10 @@ book_module_book_loaded_cb (EBook *book, action = GTK_ACTION (user_data); action_name = gtk_action_get_name (action); - if (g_str_equal (action_name, "contact-new")) + if (strcmp (action_name, "contact-new") == 0) eab_show_contact_editor (book, contact, TRUE, TRUE); - if (g_str_equal (action_name, "contact-list-new")) + if (strcmp (action_name, "contact-list-new") == 0) eab_show_contact_list_editor (book, contact, TRUE, TRUE); g_object_unref (contact); @@ -250,7 +264,7 @@ static void action_contact_new_cb (GtkAction *action, EShellWindow *shell_window) { - EBook *book; + EBook *book = NULL; GConfClient *client; ESourceList *source_list; const gchar *key; @@ -435,7 +449,9 @@ e_shell_module_init (GTypeModule *type_module) shell_module = E_SHELL_MODULE (type_module); shell = e_shell_module_get_shell (shell_module); + /* Register the GType for EBookShellView. */ e_book_shell_view_get_type (type_module); + e_shell_module_set_info (shell_module, &module_info); book_module_ensure_sources (shell_module); diff --git a/addressbook/gui/component/e-book-shell-view-private.c b/addressbook/gui/component/e-book-shell-view-private.c index 4bea688437..1ed66f8289 100644 --- a/addressbook/gui/component/e-book-shell-view-private.c +++ b/addressbook/gui/component/e-book-shell-view-private.c @@ -281,11 +281,18 @@ book_shell_view_primary_selection_changed_cb (EBookShellView *book_shell_view, } void -e_book_shell_view_private_init (EBookShellView *book_shell_view) +e_book_shell_view_private_init (EBookShellView *book_shell_view, + EShellViewClass *shell_view_class) { EBookShellViewPrivate *priv = book_shell_view->priv; + ESourceList *source_list; GHashTable *uid_to_view; GHashTable *uid_to_editor; + GObject *object; + + object = G_OBJECT (shell_view_class->type_module); + source_list = g_object_get_data (object, "source-list"); + g_return_if_fail (E_IS_SOURCE_LIST (source_list)); uid_to_view = g_hash_table_new_full ( g_str_hash, g_str_equal, @@ -297,12 +304,11 @@ e_book_shell_view_private_init (EBookShellView *book_shell_view) (GDestroyNotify) g_free, (GDestroyNotify) g_free); + priv->source_list = g_object_ref (source_list); priv->contact_actions = gtk_action_group_new ("contacts"); priv->activity_handler = e_activity_handler_new (); priv->uid_to_view = uid_to_view; priv->uid_to_editor = uid_to_editor; - - e_book_get_addressbooks (&priv->source_list, NULL); } void @@ -385,6 +391,8 @@ e_book_shell_view_private_dispose (EBookShellView *book_shell_view) { EBookShellViewPrivate *priv = book_shell_view->priv; + DISPOSE (priv->source_list); + DISPOSE (priv->contact_actions); DISPOSE (priv->notebook); @@ -397,7 +405,6 @@ e_book_shell_view_private_dispose (EBookShellView *book_shell_view) g_hash_table_remove_all (priv->uid_to_editor); DISPOSE (priv->book); - DISPOSE (priv->source_list); } void diff --git a/addressbook/gui/component/e-book-shell-view-private.h b/addressbook/gui/component/e-book-shell-view-private.h index ccd344567e..6fbff31c5d 100644 --- a/addressbook/gui/component/e-book-shell-view-private.h +++ b/addressbook/gui/component/e-book-shell-view-private.h @@ -81,6 +81,10 @@ enum { struct _EBookShellViewPrivate { + /*** Module Data ***/ + + ESourceList *source_list; + /*** UI Management ***/ GtkActionGroup *contact_actions; @@ -98,14 +102,14 @@ struct _EBookShellViewPrivate { EBook *book; guint activity_id; - ESourceList *source_list; gchar *password; EABMenu *menu; }; void e_book_shell_view_private_init - (EBookShellView *book_shell_view); + (EBookShellView *book_shell_view, + EShellViewClass *shell_view_class); void e_book_shell_view_private_constructed (EBookShellView *book_shell_view); void e_book_shell_view_private_dispose diff --git a/addressbook/gui/component/e-book-shell-view.c b/addressbook/gui/component/e-book-shell-view.c index 4c06cc5fba..ce0c8f2b55 100644 --- a/addressbook/gui/component/e-book-shell-view.c +++ b/addressbook/gui/component/e-book-shell-view.c @@ -20,6 +20,11 @@ #include "e-book-shell-view-private.h" +enum { + PROP_0, + PROP_SOURCE_LIST +}; + GType e_book_shell_view_type = 0; static gpointer parent_class; @@ -151,6 +156,23 @@ book_shell_view_source_list_changed_cb (EBookShellView *book_shell_view, } static void +book_shell_view_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_SOURCE_LIST: + g_value_set_object ( + value, e_book_shell_view_get_source_list ( + E_BOOK_SHELL_VIEW (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void book_shell_view_dispose (GObject *object) { e_book_shell_view_private_dispose (E_BOOK_SHELL_VIEW (object)); @@ -217,6 +239,7 @@ book_shell_view_class_init (EBookShellViewClass *class, g_type_class_add_private (class, sizeof (EBookShellViewPrivate)); object_class = G_OBJECT_CLASS (class); + object_class->get_property = book_shell_view_get_property; object_class->dispose = book_shell_view_dispose; object_class->finalize = book_shell_view_finalize; object_class->constructed = book_shell_view_constructed; @@ -226,15 +249,26 @@ book_shell_view_class_init (EBookShellViewClass *class, shell_view_class->icon_name = "x-office-address-book"; shell_view_class->type_module = type_module; shell_view_class->changed = book_shell_view_changed; + + g_object_class_install_property ( + object_class, + PROP_SOURCE_LIST, + g_param_spec_object ( + "source-list", + _("Source List"), + _("The registry of address books"), + E_TYPE_SOURCE_LIST, + G_PARAM_READABLE)); } static void -book_shell_view_init (EBookShellView *book_shell_view) +book_shell_view_init (EBookShellView *book_shell_view, + EShellViewClass *shell_view_class) { book_shell_view->priv = E_BOOK_SHELL_VIEW_GET_PRIVATE (book_shell_view); - e_book_shell_view_private_init (book_shell_view); + e_book_shell_view_private_init (book_shell_view, shell_view_class); g_signal_connect_swapped ( book_shell_view->priv->source_list, "changed", @@ -267,3 +301,11 @@ e_book_shell_view_get_type (GTypeModule *type_module) return e_book_shell_view_type; } + +ESourceList * +e_book_shell_view_get_source_list (EBookShellView *book_shell_view) +{ + g_return_val_if_fail (E_IS_BOOK_SHELL_VIEW (book_shell_view), NULL); + + return book_shell_view->priv->source_list; +} diff --git a/addressbook/gui/component/e-book-shell-view.h b/addressbook/gui/component/e-book-shell-view.h index 9071fc7ba4..9dcb48e980 100644 --- a/addressbook/gui/component/e-book-shell-view.h +++ b/addressbook/gui/component/e-book-shell-view.h @@ -22,6 +22,7 @@ #define E_BOOK_SHELL_VIEW_H #include <e-shell-view.h> +#include <libedataserver/e-source-list.h> /* Standard GObject macros */ #define E_TYPE_BOOK_SHELL_VIEW \ @@ -59,7 +60,10 @@ struct _EBookShellViewClass { EShellViewClass parent_class; }; -GType e_book_shell_view_get_type (GTypeModule *type_module); +GType e_book_shell_view_get_type + (GTypeModule *type_module); +ESourceList * e_book_shell_view_get_source_list + (EBookShellView *book_shell_view); G_END_DECLS diff --git a/calendar/gui/Makefile.am b/calendar/gui/Makefile.am index df9485d139..d2f092e422 100644 --- a/calendar/gui/Makefile.am +++ b/calendar/gui/Makefile.am @@ -44,6 +44,9 @@ module_LTLIBRARIES = \ libevolution-tasks.la libevolution_calendar_la_SOURCES = \ + calendar-config.c \ + calendar-config.h \ + calendar-config-keys.h \ e-cal-shell-module.c \ e-cal-shell-view.c \ e-cal-shell-view.h \ @@ -53,6 +56,9 @@ libevolution_calendar_la_SOURCES = \ e-cal-shell-view-private.h libevolution_memos_la_SOURCES = \ + calendar-config.c \ + calendar-config.h \ + calendar-config-keys.h \ e-memo-shell-module.c \ e-memo-shell-view.c \ e-memo-shell-view.h \ @@ -62,6 +68,9 @@ libevolution_memos_la_SOURCES = \ e-memo-shell-view-private.h libevolution_tasks_la_SOURCES = \ + calendar-config.c \ + calendar-config.h \ + calendar-config-keys.h \ e-task-shell-module.c \ e-task-shell-view.c \ e-task-shell-view.h \ diff --git a/calendar/gui/calendar-component.c b/calendar/gui/calendar-component.c index 3b17466682..12a946418c 100644 --- a/calendar/gui/calendar-component.c +++ b/calendar/gui/calendar-component.c @@ -145,191 +145,6 @@ calcomp_vpane_resized (GtkWidget *vpane, GdkEventButton *e, CalendarComponentVie return FALSE; } -static void -ensure_sources (CalendarComponent *component) -{ - GSList *groups; - ESourceList *source_list; - ESourceGroup *group; - ESourceGroup *on_this_computer; - ESourceGroup *on_the_web; - ESourceGroup *contacts; - ESourceGroup *weather; - ESource *personal_source; - ESource *birthdays_source; - char *base_uri, *base_uri_proto; - const gchar *base_dir; - gchar *create_source; - - on_this_computer = NULL; - on_the_web = NULL; - contacts = NULL; - weather = NULL; - personal_source = NULL; - birthdays_source = NULL; - - if (!e_cal_get_sources (&source_list, E_CAL_SOURCE_TYPE_EVENT, NULL)) { - g_warning ("Could not get calendar source list from GConf!"); - return; - } - - base_dir = calendar_component_peek_base_directory (component); - base_uri = g_build_filename (base_dir, "local", NULL); - - base_uri_proto = g_filename_to_uri (base_uri, NULL, NULL); - - groups = e_source_list_peek_groups (source_list); - if (groups) { - /* groups are already there, we need to search for things... */ - GSList *g; - - for (g = groups; g; g = g->next) { - - group = E_SOURCE_GROUP (g->data); - - /* compare only file:// part. If user home dir name changes we do not want to create - one more group */ - - if (!on_this_computer && !strncmp (base_uri_proto, e_source_group_peek_base_uri (group), 7)) - on_this_computer = group; - else if (!on_the_web && !strcmp (WEB_BASE_URI, e_source_group_peek_base_uri (group))) - on_the_web = group; - else if (!contacts && !strcmp (CONTACTS_BASE_URI, e_source_group_peek_base_uri (group))) - contacts = group; - else if (!weather && !strcmp (WEATHER_BASE_URI, e_source_group_peek_base_uri (group))) - weather = group; - } - } - - if (on_this_computer) { - /* make sure "Personal" shows up as a source under - this group */ - GSList *sources = e_source_group_peek_sources (on_this_computer); - GSList *s; - for (s = sources; s; s = s->next) { - ESource *source = E_SOURCE (s->data); - const gchar *relative_uri; - - relative_uri = e_source_peek_relative_uri (source); - if (relative_uri == NULL) - continue; - if (!strcmp (PERSONAL_RELATIVE_URI, relative_uri)) { - personal_source = source; - break; - } - } - /* Make sure we have the correct base uri. This can change when user's - homedir name changes */ - if (strcmp (base_uri_proto, e_source_group_peek_base_uri (on_this_computer))) { - e_source_group_set_base_uri (on_this_computer, base_uri_proto); - - /* *sigh* . We shouldn't need this sync call here as set_base_uri - call results in synching to gconf, but that happens in idle loop - and too late to prevent user seeing "Can not Open ... because of invalid uri" error.*/ - e_source_list_sync (source_list,NULL); - } - } - else { - /* create the local source group */ - group = e_source_group_new (_("On This Computer"), base_uri_proto); - e_source_list_add_group (source_list, group, -1); - - on_this_computer = group; - } - - if (!personal_source) { - char *primary_calendar = calendar_config_get_primary_calendar(); - GSList *calendars_selected; - - /* Create the default Person addressbook */ - personal_source = e_source_new (_("Personal"), PERSONAL_RELATIVE_URI); - e_source_group_add_source (on_this_computer, personal_source, -1); - g_object_unref (personal_source); - - calendars_selected = calendar_config_get_calendars_selected (); - if (!primary_calendar && !calendars_selected) { - GSList selected; - - calendar_config_set_primary_calendar (e_source_peek_uid (personal_source)); - - selected.data = (gpointer)e_source_peek_uid (personal_source); - selected.next = NULL; - calendar_config_set_calendars_selected (&selected); - } - - if (calendars_selected) { - g_slist_foreach (calendars_selected, (GFunc) g_free, NULL); - g_slist_free (calendars_selected); - } - - g_free (primary_calendar); - e_source_set_color_spec (personal_source, "#BECEDD"); - } - - if (!on_the_web) { - /* Create the On the web source group */ - group = e_source_group_new (_("On The Web"), WEB_BASE_URI); - e_source_list_add_group (source_list, group, -1); - - on_the_web = group; - } - if (contacts) { - GSList *sources = e_source_group_peek_sources (contacts); - if (sources) { - birthdays_source = E_SOURCE (sources->data); /* There is only one source under Contacts Group*/ - - if (sources->next) { - /* Ensure we have only one contacts source - we was able to create more than one before */ - GSList *l = NULL, *p; - - for (p = sources->next; p; p = p->next) - l = g_slist_prepend (l, p->data); - - for (p = l; p; p = p->next) - e_source_group_remove_source (contacts, p->data); - - g_slist_free (l); - } - } - } - else { - /* Create the contacts group */ - group = e_source_group_new (_("Contacts"), CONTACTS_BASE_URI); - e_source_list_add_group (source_list, group, -1); - contacts = group; - } - - create_source = e_source_group_get_property (contacts, "create_source"); - if (!create_source) - e_source_group_set_property (contacts, "create_source", "no"); - g_free (create_source); - - if (!birthdays_source) { - birthdays_source = e_source_new (_("Birthdays & Anniversaries"), "/"); - e_source_group_add_source (contacts, birthdays_source, -1); - g_object_unref (birthdays_source); - } - - if (!e_source_get_property (birthdays_source, "delete")) - e_source_set_property(birthdays_source, "delete", "no"); - - if (e_source_peek_color_spec (birthdays_source) == NULL) - e_source_set_color_spec (birthdays_source, "#DDBECE"); - - if (!weather) { - /* Create the weather group */ - group = e_source_group_new (_("Weather"), WEATHER_BASE_URI); - e_source_list_add_group (source_list, group, -1); - weather = group; - } - - component->priv->source_list = source_list; - - g_free (base_uri_proto); - g_free (base_uri); -} - - /* Utility functions. */ static gboolean @@ -1694,7 +1509,6 @@ calendar_component_init (CalendarComponent *component) priv->notifications = g_list_prepend (priv->notifications, GUINT_TO_POINTER (not)); component->priv = priv; - ensure_sources (component); if (!e_cal_get_sources (&priv->task_source_list, E_CAL_SOURCE_TYPE_TODO, NULL)) ; diff --git a/calendar/gui/calendar-component.h b/calendar/gui/calendar-component.h index 131ffd3a3a..8fdb92abbb 100644 --- a/calendar/gui/calendar-component.h +++ b/calendar/gui/calendar-component.h @@ -55,10 +55,6 @@ struct _CalendarComponentClass { GType calendar_component_get_type (void); -CalendarComponent *calendar_component_peek (void); - -const char *calendar_component_peek_base_directory (CalendarComponent *component); -const char *calendar_component_peek_config_directory (CalendarComponent *component); ESourceList *calendar_component_peek_source_list (CalendarComponent *component); diff --git a/calendar/gui/calendar-config.c b/calendar/gui/calendar-config.c index 2b704db903..b6b7a375ca 100644 --- a/calendar/gui/calendar-config.c +++ b/calendar/gui/calendar-config.c @@ -29,13 +29,13 @@ #include <config.h> #endif -#include <string.h> #include <time.h> +#include <string.h> +#include <e-util/e-util.h> #include <libgnomeui/gnome-dialog.h> +#include <libecal/e-cal-time-util.h> #include <libedataserver/e-data-server-util.h> -#include <e-util/e-util.h> #include <widgets/e-timezone-dialog/e-timezone-dialog.h> -#include <libecal/e-cal-time-util.h> #include "calendar-config-keys.h" #include "calendar-config.h" diff --git a/calendar/gui/e-cal-shell-module.c b/calendar/gui/e-cal-shell-module.c index e928631298..7df23a92f3 100644 --- a/calendar/gui/e-cal-shell-module.c +++ b/calendar/gui/e-cal-shell-module.c @@ -18,12 +18,18 @@ * Boston, MA 02110-1301, USA. */ +#include <string.h> #include <glib/gi18n.h> +#include <libecal/e-cal.h> +#include <libedataserver/e-source.h> +#include <libedataserver/e-source-list.h> +#include <libedataserver/e-source-group.h> #include <e-shell.h> #include <e-shell-module.h> #include <e-shell-window.h> +#include <calendar-config.h> #include <e-cal-shell-view.h> #define MODULE_NAME "calendar" @@ -32,10 +38,250 @@ #define MODULE_SEARCHES "caltypes.xml" #define MODULE_SORT_ORDER 400 +#define CONTACTS_BASE_URI "contacts://" +#define WEATHER_BASE_URI "weather://" +#define WEB_BASE_URI "webcal://" +#define PERSONAL_RELATIVE_URI "system" + /* Module Entry Point */ void e_shell_module_init (GTypeModule *type_module); static void +cal_module_ensure_sources (EShellModule *shell_module) +{ + /* XXX This is basically the same algorithm across all modules. + * Maybe we could somehow integrate this into EShellModule? */ + + ESourceList *source_list; + ESourceGroup *on_this_computer; + ESourceGroup *on_the_web; + ESourceGroup *contacts; + ESourceGroup *weather; + ESource *birthdays; + ESource *personal; + GSList *groups, *iter; + const gchar *data_dir; + gchar *base_uri; + gchar *filename; + gchar *property; + + on_this_computer = NULL; + on_the_web = NULL; + contacts = NULL; + weather = NULL; + birthdays = NULL; + personal = NULL; + + if (!e_cal_get_sources (&source_list, E_CAL_SOURCE_TYPE_EVENT, NULL)) { + g_warning ("Could not get calendar sources from GConf!"); + return; + } + + /* Share the source list with all calendar views. This + * is accessible via e_cal_shell_view_get_source_list(). + * Note: EShellModule takes ownership of the reference. + * + * XXX I haven't yet decided if I want to add a proper + * EShellModule API for this. The mail module would + * not use it. */ + g_object_set_data_full ( + G_OBJECT (shell_module), "source-list", + source_list, (GDestroyNotify) g_object_unref); + + data_dir = e_shell_module_get_data_dir (shell_module); + filename = g_build_filename (data_dir, "local", NULL); + base_uri = g_filename_to_uri (filename, NULL, NULL); + g_free (filename); + + groups = e_source_list_peek_groups (source_list); + for (iter = groups; iter != NULL; iter = iter->next) { + ESourceGroup *source_group = iter->data; + const gchar *group_base_uri; + + group_base_uri = e_source_group_peek_base_uri (source_group); + + /* Compare only "file://" part. if the user's home + * changes, we do not want to create another group. */ + if (on_this_computer == NULL && + strncmp (base_uri, group_base_uri, 7) == 0) + on_this_computer = source_group; + + else if (on_the_web == NULL && + strcmp (WEB_BASE_URI, group_base_uri) == 0) + on_the_web = source_group; + + else if (contacts == NULL && + strcmp (CONTACTS_BASE_URI, group_base_uri) == 0) + contacts = source_group; + + else if (weather == NULL && + strcmp (WEATHER_BASE_URI, group_base_uri) == 0) + weather = source_group; + } + + if (on_this_computer != NULL) { + GSList *sources; + const gchar *group_base_uri; + + sources = e_source_group_peek_sources (on_this_computer); + group_base_uri = e_source_group_peek_base_uri (on_this_computer); + + /* Make sure this group includes a "Personal" source. */ + for (iter = sources; iter != NULL; iter = iter->next) { + ESource *source = iter->data; + const gchar *relative_uri; + + relative_uri = e_source_peek_relative_uri (source); + if (relative_uri == NULL) + continue; + + if (strcmp (PERSONAL_RELATIVE_URI, relative_uri) != 0) + continue; + + personal = source; + break; + } + + /* Make sure we have the correct base URI. This can + * change when the user's home directory changes. */ + if (strcmp (base_uri, group_base_uri) != 0) { + e_source_group_set_base_uri ( + on_this_computer, base_uri); + + /* XXX We shouldn't need this sync call here as + * set_base_uri() results in synching to GConf, + * but that happens in an idle loop and too late + * to prevent the user from seeing a "Cannot + * Open ... because of invalid URI" error. */ + e_source_list_sync (source_list, NULL); + } + + } else { + ESourceGroup *source_group; + const gchar *name; + + name = _("On This Computer"); + source_group = e_source_group_new (name, base_uri); + e_source_list_add_group (source_list, source_group, -1); + g_object_unref (source_group); + } + + if (personal == NULL) { + ESource *source; + GSList *selected; + const gchar *name; + gchar *primary; + + name = _("Personal"); + source = e_source_new (name, PERSONAL_RELATIVE_URI); + e_source_group_add_source (on_this_computer, source, -1); + g_object_unref (source); + + primary = calendar_config_get_primary_calendar (); + selected = calendar_config_get_calendars_selected (); + + if (primary == NULL && selected == NULL) { + const gchar *uid; + + uid = e_source_peek_uid (source); + selected = g_slist_prepend (NULL, g_strdup (uid)); + + calendar_config_set_primary_calendar (uid); + calendar_config_set_calendars_selected (selected); + } + + g_slist_foreach (selected, (GFunc) g_free, NULL); + g_slist_free (selected); + g_free (primary); + } + + if (on_the_web == NULL) { + ESourceGroup *source_group; + const gchar *name; + + name = _("On The Web"); + source_group = e_source_group_new (name, WEB_BASE_URI); + e_source_list_add_group (source_list, source_group, -1); + g_object_unref (source_group); + } + + if (contacts != NULL) { + GSList *sources; + + sources = e_source_group_peek_sources (contacts); + + if (sources != NULL) { + GSList *trash; + + /* There is only one source under Contacts. */ + birthdays = E_SOURCE (sources->data); + sources = g_slist_next (sources); + + /* Delete any other sources in this group. + * Earlier versions allowed you to create + * additional sources under Contacts. */ + trash = g_slist_copy (sources); + while (trash != NULL) { + ESource *source = trash->data; + e_source_group_remove_source (contacts, source); + trash = g_slist_delete_link (trash, trash); + } + + } + } else { + ESourceGroup *source_group; + const gchar *name; + + name = _("Contacts"); + source_group = e_source_group_new (name, CONTACTS_BASE_URI); + e_source_list_add_group (source_list, source_group, -1); + g_object_unref (source_group); + + /* This is now a borrowed reference. */ + contacts = source_group; + } + + /* XXX e_source_group_get_property() returns a newly-allocated + * string when it could just as easily return a const string. + * Unfortunately, fixing that would break the API. */ + property = e_source_group_get_property (contacts, "create_source"); + if (property == NULL) + e_source_group_set_property (contacts, "create_source", "no"); + g_free (property); + + if (birthdays == NULL) { + ESource *source; + const gchar *name; + + name = _("Birthdays & Anniversaries"); + source = e_source_new (name, "/"); + e_source_group_add_source (contacts, source, -1); + g_object_unref (source); + + /* This is now a borrowed reference. */ + birthdays = source; + } + + if (e_source_get_property (birthdays, "delete") == NULL) + e_source_set_property (birthdays, "delete", "no"); + + if (e_source_peek_color_spec (birthdays) == NULL) + e_source_set_color_spec (birthdays, "#DDBECE"); + + if (weather == NULL) { + ESourceGroup *source_group; + const gchar *name; + + name = _("Weather"); + source_group = e_source_group_new (name, WEATHER_BASE_URI); + e_source_list_add_group (source_list, source_group, -1); + g_object_unref (source_group); + } + + g_free (base_uri); +} + +static void action_appointment_new_cb (GtkAction *action, EShellWindow *shell_window) { @@ -136,9 +382,13 @@ e_shell_module_init (GTypeModule *type_module) shell_module = E_SHELL_MODULE (type_module); shell = e_shell_module_get_shell (shell_module); + /* Register the GType for ECalShellView. */ e_cal_shell_view_get_type (type_module); + e_shell_module_set_info (shell_module, &module_info); + cal_module_ensure_sources (shell_module); + g_signal_connect_swapped ( shell, "handle-uri", G_CALLBACK (cal_module_handle_uri), shell_module); diff --git a/calendar/gui/e-cal-shell-view-private.c b/calendar/gui/e-cal-shell-view-private.c index 100a12b09f..2e7619cadc 100644 --- a/calendar/gui/e-cal-shell-view-private.c +++ b/calendar/gui/e-cal-shell-view-private.c @@ -21,10 +21,18 @@ #include "e-cal-shell-view-private.h" void -e_cal_shell_view_private_init (ECalShellView *cal_shell_view) +e_cal_shell_view_private_init (ECalShellView *cal_shell_view, + EShellViewClass *shell_view_class) { ECalShellViewPrivate *priv = cal_shell_view->priv; + ESourceList *source_list; + GObject *object; + object = G_OBJECT (shell_view_class->type_module); + source_list = g_object_get_data (object, "source-list"); + g_return_if_fail (E_IS_SOURCE_LIST (source_list)); + + priv->source_list = g_object_ref (source_list); priv->calendar_actions = gtk_action_group_new ("calendars"); } @@ -39,6 +47,8 @@ e_cal_shell_view_private_dispose (ECalShellView *cal_shell_view) { ECalShellViewPrivate *priv = cal_shell_view->priv; + DISPOSE (priv->source_list); + DISPOSE (priv->calendar_actions); } diff --git a/calendar/gui/e-cal-shell-view-private.h b/calendar/gui/e-cal-shell-view-private.h index fa591d11ed..0b2633d2be 100644 --- a/calendar/gui/e-cal-shell-view-private.h +++ b/calendar/gui/e-cal-shell-view-private.h @@ -52,13 +52,18 @@ G_BEGIN_DECLS struct _ECalShellViewPrivate { + /*** Module Data ***/ + + ESourceList *source_list; + /*** UI Management ***/ GtkActionGroup *calendar_actions; }; void e_cal_shell_view_private_init - (ECalShellView *cal_shell_view); + (ECalShellView *cal_shell_view, + EShellViewClass *shell_view_class); void e_cal_shell_view_private_constructed (ECalShellView *cal_shell_view); void e_cal_shell_view_private_dispose diff --git a/calendar/gui/e-cal-shell-view.c b/calendar/gui/e-cal-shell-view.c index 7a77d84991..a1e21ab36f 100644 --- a/calendar/gui/e-cal-shell-view.c +++ b/calendar/gui/e-cal-shell-view.c @@ -20,10 +20,32 @@ #include "e-cal-shell-view-private.h" +enum { + PROP_0, + PROP_SOURCE_LIST +}; + GType e_cal_shell_view_type = 0; static gpointer parent_class; static void +cal_shell_view_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_SOURCE_LIST: + g_value_set_object ( + value, e_cal_shell_view_get_source_list ( + E_CAL_SHELL_VIEW (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void cal_shell_view_dispose (GObject *object) { e_cal_shell_view_private_dispose (E_CAL_SHELL_VIEW (object)); @@ -75,6 +97,7 @@ cal_shell_view_class_init (ECalShellView *class, g_type_class_add_private (class, sizeof (ECalShellViewPrivate)); object_class = G_OBJECT_CLASS (class); + object_class->get_property = cal_shell_view_get_property; object_class->dispose = cal_shell_view_dispose; object_class->finalize = cal_shell_view_finalize; object_class->constructed = cal_shell_view_constructed; @@ -84,15 +107,26 @@ cal_shell_view_class_init (ECalShellView *class, shell_view_class->icon_name = "evolution-cals"; shell_view_class->type_module = type_module; shell_view_class->changed = cal_shell_view_changed; + + g_object_class_install_property ( + object_class, + PROP_SOURCE_LIST, + g_param_spec_object ( + "source-list", + _("Source List"), + _("The registry of calendars"), + E_TYPE_SOURCE_LIST, + G_PARAM_READABLE)); } static void -cal_shell_view_init (ECalShellView *cal_shell_view) +cal_shell_view_init (ECalShellView *cal_shell_view, + EShellViewClass *shell_view_class) { cal_shell_view->priv = E_CAL_SHELL_VIEW_GET_PRIVATE (cal_shell_view); - e_cal_shell_view_private_init (cal_shell_view); + e_cal_shell_view_private_init (cal_shell_view, shell_view_class); } GType @@ -120,3 +154,11 @@ e_cal_shell_view_get_type (GTypeModule *type_module) return e_cal_shell_view_type; } + +ESourceList * +e_cal_shell_view_get_source_list (ECalShellView *cal_shell_view) +{ + g_return_val_if_fail (E_IS_CAL_SHELL_VIEW (cal_shell_view), NULL); + + return cal_shell_view->priv->source_list; +} diff --git a/calendar/gui/e-cal-shell-view.h b/calendar/gui/e-cal-shell-view.h index d0078b041c..14ce530c61 100644 --- a/calendar/gui/e-cal-shell-view.h +++ b/calendar/gui/e-cal-shell-view.h @@ -22,6 +22,7 @@ #define E_CAL_SHELL_VIEW_H #include <e-shell-view.h> +#include <libedataserver/e-source-list.h> /* Standard GObject macros */ #define E_TYPE_CAL_SHELL_VIEW \ @@ -59,7 +60,10 @@ struct _ECalShellViewClass { EShellViewClass parent_class; }; -GType e_cal_shell_view_get_type (GTypeModule *type_module); +GType e_cal_shell_view_get_type + (GTypeModule *type_module); +ESourceList * e_cal_shell_view_get_source_list + (ECalShellView *cal_shell_view); G_END_DECLS diff --git a/calendar/gui/e-memo-shell-module.c b/calendar/gui/e-memo-shell-module.c index d5c0a2d60d..7629c2d0e3 100644 --- a/calendar/gui/e-memo-shell-module.c +++ b/calendar/gui/e-memo-shell-module.c @@ -18,12 +18,18 @@ * Boston, MA 02110-1301, USA. */ +#include <string.h> #include <glib/gi18n.h> +#include <libecal/e-cal.h> +#include <libedataserver/e-source.h> +#include <libedataserver/e-source-list.h> +#include <libedataserver/e-source-group.h> #include <e-shell.h> #include <e-shell-module.h> #include <e-shell-window.h> +#include <calendar-config.h> #include <e-memo-shell-view.h> #define MODULE_NAME "memos" @@ -32,10 +38,160 @@ #define MODULE_SEARCHES "memotypes.xml" #define MODULE_SORT_ORDER 500 +#define WEB_BASE_URI "webcal://" +#define PERSONAL_RELATIVE_URI "system" + /* Module Entry Point */ void e_shell_module_init (GTypeModule *type_module); static void +memo_module_ensure_sources (EShellModule *shell_module) +{ + /* XXX This is basically the same algorithm across all modules. + * Maybe we could somehow integrate this into EShellModule? */ + + ESourceList *source_list; + ESourceGroup *on_this_computer; + ESourceGroup *on_the_web; + ESource *personal; + GSList *groups, *iter; + const gchar *data_dir; + gchar *base_uri; + gchar *filename; + + on_this_computer = NULL; + on_the_web = NULL; + personal = NULL; + + if (!e_cal_get_sources (&source_list, E_CAL_SOURCE_TYPE_JOURNAL, NULL)) { + g_warning ("Could not get memo sources from GConf!"); + return; + } + + /* Share the source list with all memo views. This is + * accessible via e_memo_shell_view_get_source_list(). + * Note: EShellModule takes ownership of the reference. + * + * XXX I haven't yet decided if I want to add a proper + * EShellModule API for this. The mail module would + * not use it. */ + g_object_set_data_full ( + G_OBJECT (shell_module), "source-list", + source_list, (GDestroyNotify) g_object_unref); + + data_dir = e_shell_module_get_data_dir (shell_module); + filename = g_build_filename (data_dir, "local", NULL); + base_uri = g_filename_to_uri (filename, NULL, NULL); + g_free (filename); + + groups = e_source_list_peek_groups (source_list); + for (iter = groups; iter != NULL; iter = iter->next) { + ESourceGroup *source_group = iter->data; + const gchar *group_base_uri; + + group_base_uri = e_source_group_peek_base_uri (source_group); + + /* Compare only "file://" part. If the user's home + * changes, we do not want to create another group. */ + if (on_this_computer == NULL && + strncmp (base_uri, group_base_uri, 7) == 0) + on_this_computer = source_group; + + else if (on_the_web == NULL && + strcmp (WEB_BASE_URI, group_base_uri) == 0) + on_the_web = source_group; + } + + if (on_this_computer != NULL) { + GSList *sources; + const gchar *group_base_uri; + + sources = e_source_group_peek_sources (on_this_computer); + group_base_uri = e_source_group_peek_base_uri (on_this_computer); + + /* Make sure this group includes a "Personal" source. */ + for (iter = sources; iter != NULL; iter = iter->next) { + ESource *source = iter->data; + const gchar *relative_uri; + + relative_uri = e_source_peek_relative_uri (source); + if (relative_uri == NULL) + continue; + + if (strcmp (PERSONAL_RELATIVE_URI, relative_uri) != 0) + continue; + + personal = source; + break; + } + + /* Make sure we have the correct base URI. This can + * change when the user's home directory changes. */ + if (strcmp (base_uri, group_base_uri) != 0) { + e_source_group_set_base_uri ( + on_this_computer, base_uri); + + /* XXX We shouldn't need this sync call here as + * set_base_uri() results in synching to GConf, + * but that happens in an idle loop and too late + * to prevent the user from seeing a "Cannot + * Open ... because of invalid URI" error. */ + e_source_list_sync (source_list, NULL); + } + + } else { + ESourceGroup *source_group; + const gchar *name; + + name = _("On This Computer"); + source_group = e_source_group_new (name, base_uri); + e_source_list_add_group (source_list, source_group, -1); + g_object_unref (source_group); + } + + if (personal == NULL) { + ESource *source; + GSList *selected; + const gchar *name; + gchar *primary; + + name = _("Personal"); + source = e_source_new (name, PERSONAL_RELATIVE_URI); + e_source_group_add_source (on_this_computer, source, -1); + g_object_unref (source); + + primary = calendar_config_get_primary_memos (); + selected = calendar_config_get_memos_selected (); + + if (primary == NULL && selected == NULL) { + const gchar *uid; + + uid = e_source_peek_uid (source); + selected = g_slist_prepend (NULL, g_strdup (uid)); + + calendar_config_set_primary_memos (uid); + calendar_config_set_memos_selected (selected); + } + + g_slist_foreach (selected, (GFunc) g_free, NULL); + g_slist_free (selected); + g_free (primary); + } + + if (on_the_web == NULL) { + ESourceGroup *source_group; + const gchar *name; + + name = _("On The Web"); + source_group = e_source_group_new (name, WEB_BASE_URI); + e_source_list_add_group (source_list, source_group, -1); + g_object_unref (source_group); + } + + g_free (base_uri); +} + +static void action_memo_new_cb (GtkAction *action, EShellWindow *shell_window) { @@ -123,9 +279,13 @@ e_shell_module_init (GTypeModule *type_module) shell_module = E_SHELL_MODULE (type_module); shell = e_shell_module_get_shell (shell_module); + /* Register the GType for EMemoShellView. */ e_memo_shell_view_get_type (type_module); + e_shell_module_set_info (shell_module, &module_info); + memo_module_ensure_sources (shell_module); + g_signal_connect_swapped ( shell, "handle-uri", G_CALLBACK (memo_module_handle_uri), shell_module); diff --git a/calendar/gui/e-memo-shell-view-private.c b/calendar/gui/e-memo-shell-view-private.c index 7af55aedbf..bc38ee4a3e 100644 --- a/calendar/gui/e-memo-shell-view-private.c +++ b/calendar/gui/e-memo-shell-view-private.c @@ -21,10 +21,18 @@ #include "e-memo-shell-view-private.h" void -e_memo_shell_view_private_init (EMemoShellView *memo_shell_view) +e_memo_shell_view_private_init (EMemoShellView *memo_shell_view, + EShellViewClass *shell_view_class) { EMemoShellViewPrivate *priv = memo_shell_view->priv; + ESourceList *source_list; + GObject *object; + object = G_OBJECT (shell_view_class->type_module); + source_list = g_object_get_data (object, "source-list"); + g_return_if_fail (E_IS_SOURCE_LIST (source_list)); + + priv->source_list = g_object_ref (source_list); priv->memo_actions = gtk_action_group_new ("memos"); } @@ -39,6 +47,8 @@ e_memo_shell_view_private_dispose (EMemoShellView *memo_shell_view) { EMemoShellViewPrivate *priv = memo_shell_view->priv; + DISPOSE (priv->source_list); + DISPOSE (priv->memo_actions); } diff --git a/calendar/gui/e-memo-shell-view-private.h b/calendar/gui/e-memo-shell-view-private.h index ad75d4f2b8..1940dc0927 100644 --- a/calendar/gui/e-memo-shell-view-private.h +++ b/calendar/gui/e-memo-shell-view-private.h @@ -51,13 +51,18 @@ G_BEGIN_DECLS struct _EMemoShellViewPrivate { + /*** Module Data ***/ + + ESourceList *source_list; + /*** UI Management ***/ GtkActionGroup *memo_actions; }; void e_memo_shell_view_private_init - (EMemoShellView *memo_shell_view); + (EMemoShellView *memo_shell_view, + EShellViewClass *shell_view_class); void e_memo_shell_view_private_constructed (EMemoShellView *memo_shell_view); void e_memo_shell_view_private_dispose diff --git a/calendar/gui/e-memo-shell-view.c b/calendar/gui/e-memo-shell-view.c index c6ece950f0..6b9032bb17 100644 --- a/calendar/gui/e-memo-shell-view.c +++ b/calendar/gui/e-memo-shell-view.c @@ -20,10 +20,32 @@ #include "e-memo-shell-view-private.h" +enum { + PROP_0, + PROP_SOURCE_LIST +}; + GType e_memo_shell_view_type = 0; static gpointer parent_class; static void +memo_shell_view_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_SOURCE_LIST: + g_value_set_object ( + value, e_memo_shell_view_get_source_list ( + E_MEMO_SHELL_VIEW (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void memo_shell_view_dispose (GObject *object) { e_memo_shell_view_private_dispose (E_MEMO_SHELL_VIEW (object)); @@ -75,6 +97,7 @@ memo_shell_view_class_init (EMemoShellView *class, g_type_class_add_private (class, sizeof (EMemoShellViewPrivate)); object_class = G_OBJECT_CLASS (class); + object_class->get_property = memo_shell_view_get_property; object_class->dispose = memo_shell_view_dispose; object_class->finalize = memo_shell_view_finalize; object_class->constructed = memo_shell_view_constructed; @@ -84,15 +107,26 @@ memo_shell_view_class_init (EMemoShellView *class, shell_view_class->icon_name = "evolution-memos"; shell_view_class->type_module = type_module; shell_view_class->changed = memo_shell_view_changed; + + g_object_class_install_property ( + object_class, + PROP_SOURCE_LIST, + g_param_spec_object ( + "source-list", + _("Source List"), + _("The registry of memo lists"), + E_TYPE_SOURCE_LIST, + G_PARAM_READABLE)); } static void -memo_shell_view_init (EMemoShellView *memo_shell_view) +memo_shell_view_init (EMemoShellView *memo_shell_view, + EShellViewClass *shell_view_class) { memo_shell_view->priv = E_MEMO_SHELL_VIEW_GET_PRIVATE (memo_shell_view); - e_memo_shell_view_private_init (memo_shell_view); + e_memo_shell_view_private_init (memo_shell_view, shell_view_class); } GType @@ -120,3 +154,11 @@ e_memo_shell_view_get_type (GTypeModule *type_module) return e_memo_shell_view_type; } + +ESourceList * +e_memo_shell_view_get_source_list (EMemoShellView *memo_shell_view) +{ + g_return_val_if_fail (E_IS_MEMO_SHELL_VIEW (memo_shell_view), NULL); + + return memo_shell_view->priv->source_list; +} diff --git a/calendar/gui/e-memo-shell-view.h b/calendar/gui/e-memo-shell-view.h index be5c2a325a..c6faa8382c 100644 --- a/calendar/gui/e-memo-shell-view.h +++ b/calendar/gui/e-memo-shell-view.h @@ -22,6 +22,7 @@ #define E_MEMO_SHELL_VIEW_H #include <e-shell-view.h> +#include <libedataserver/e-source-list.h> /* Standard GObject macros */ #define E_TYPE_MEMO_SHELL_VIEW \ @@ -59,7 +60,10 @@ struct _EMemoShellViewClass { EShellViewClass parent_class; }; -GType e_memo_shell_view_get_type (GTypeModule *type_module); +GType e_memo_shell_view_get_type + (GTypeModule *type_module); +ESourceList * e_memo_shell_view_get_source_list + (EMemoShellView *memo_shell_view); G_END_DECLS diff --git a/calendar/gui/e-task-shell-module.c b/calendar/gui/e-task-shell-module.c index a87b63ea60..7dee36a9cc 100644 --- a/calendar/gui/e-task-shell-module.c +++ b/calendar/gui/e-task-shell-module.c @@ -18,12 +18,18 @@ * Boston, MA 02110-1301, USA. */ +#include <string.h> #include <glib/gi18n.h> +#include <libecal/e-cal.h> +#include <libedataserver/e-source.h> +#include <libedataserver/e-source-list.h> +#include <libedataserver/e-source-group.h> #include <e-shell.h> #include <e-shell-module.h> #include <e-shell-window.h> +#include <calendar-config.h> #include <e-task-shell-view.h> #define MODULE_NAME "tasks" @@ -32,10 +38,160 @@ #define MODULE_SEARCHES "tasktypes.xml" #define MODULE_SORT_ORDER 600 +#define WEB_BASE_URI "webcal://" +#define PERSONAL_RELATIVE_URI "system" + /* Module Entry Point */ void e_shell_module_init (GTypeModule *type_module); static void +task_module_ensure_sources (EShellModule *shell_module) +{ + /* XXX This is basically the same algorithm across all modules. + * Maybe we could somehow integrate this into EShellModule? */ + + ESourceList *source_list; + ESourceGroup *on_this_computer; + ESourceGroup *on_the_web; + ESource *personal; + GSList *groups, *iter; + const gchar *data_dir; + gchar *base_uri; + gchar *filename; + + on_this_computer = NULL; + on_the_web = NULL; + personal = NULL; + + if (!e_cal_get_sources (&source_list, E_CAL_SOURCE_TYPE_TODO, NULL)) { + g_warning ("Could not get task sources from GConf!"); + return; + } + + /* Share the source list with all task views. This is + * accessible via e_task_shell_view_get_source_list(). + * Note: EShellModule takes ownership of the reference. + * + * XXX I haven't yet decided if I want to add a proper + * EShellModule API for this. The mail module would + * not use it. */ + g_object_set_data_full ( + G_OBJECT (shell_module), "source-list", + source_list, (GDestroyNotify) g_object_unref); + + data_dir = e_shell_module_get_data_dir (shell_module); + filename = g_build_filename (data_dir, "local", NULL); + base_uri = g_filename_to_uri (filename, NULL, NULL); + g_free (filename); + + groups = e_source_list_peek_groups (source_list); + for (iter = groups; iter != NULL; iter = iter->next) { + ESourceGroup *source_group = iter->data; + const gchar *group_base_uri; + + group_base_uri = e_source_group_peek_base_uri (source_group); + + /* Compare only "file://" part. If the user's home + * changes, we do not want to create another group. */ + if (on_this_computer == NULL && + strncmp (base_uri, group_base_uri, 7) == 0) + on_this_computer = source_group; + + else if (on_the_web == NULL && + strcmp (WEB_BASE_URI, group_base_uri) == 0) + on_the_web = source_group; + } + + if (on_this_computer != NULL) { + GSList *sources; + const gchar *group_base_uri; + + sources = e_source_group_peek_sources (on_this_computer); + group_base_uri = e_source_group_peek_base_uri (on_this_computer); + + /* Make sure this group includes a "Personal" source. */ + for (iter = sources; iter != NULL; iter = iter->next) { + ESource *source = iter->data; + const gchar *relative_uri; + + relative_uri = e_source_peek_relative_uri (source); + if (relative_uri == NULL) + continue; + + if (strcmp (PERSONAL_RELATIVE_URI, relative_uri) != 0) + continue; + + personal = source; + break; + } + + /* Make sure we have the correct base URI. This can + * change when the user's home directory changes. */ + if (strcmp (base_uri, group_base_uri) != 0) { + e_source_group_set_base_uri ( + on_this_computer, base_uri); + + /* XXX We shouldn't need this sync call here as + * set_base_uri() results in synching to GConf, + * but that happens in an idle loop and too late + * to prevent the user from seeing a "Cannot + * Open ... because of invalid URI" error. */ + e_source_list_sync (source_list, NULL); + } + + } else { + ESourceGroup *source_group; + const gchar *name; + + name = _("On This Computer"); + source_group = e_source_group_new (name, base_uri); + e_source_list_add_group (source_list, source_group, -1); + g_object_unref (source_group); + } + + if (personal == NULL) { + ESource *source; + GSList *selected; + const gchar *name; + gchar *primary; + + name = _("Personal"); + source = e_source_new (name, PERSONAL_RELATIVE_URI); + e_source_group_add_source (on_this_computer, source, -1); + g_object_unref (source); + + primary = calendar_config_get_primary_tasks (); + selected = calendar_config_get_tasks_selected (); + + if (primary == NULL && selected == NULL) { + const gchar *uid; + + uid = e_source_peek_uid (source); + selected = g_slist_prepend (NULL, g_strdup (uid)); + + calendar_config_set_primary_tasks (uid); + calendar_config_set_tasks_selected (selected); + } + + g_slist_foreach (selected, (GFunc) g_free, NULL); + g_slist_free (selected); + g_free (primary); + } + + if (on_the_web == NULL) { + ESourceGroup *source_group; + const gchar *name; + + name = _("On The Web"); + source_group = e_source_group_new (name, WEB_BASE_URI); + e_source_list_add_group (source_list, source_group, -1); + g_object_unref (source_group); + } + + g_free (base_uri); +} + +static void action_task_new_cb (GtkAction *action, EShellWindow *shell_window) { @@ -123,9 +279,13 @@ e_shell_module_init (GTypeModule *type_module) shell_module = E_SHELL_MODULE (type_module); shell = e_shell_module_get_shell (shell_module); + /* Register the GType for ETaskShellView. */ e_task_shell_view_get_type (type_module); + e_shell_module_set_info (shell_module, &module_info); + task_module_ensure_sources (shell_module); + g_signal_connect_swapped ( shell, "handle-uri", G_CALLBACK (task_module_handle_uri), shell_module); diff --git a/calendar/gui/e-task-shell-view-private.c b/calendar/gui/e-task-shell-view-private.c index b6cae85179..e41b1fb5bc 100644 --- a/calendar/gui/e-task-shell-view-private.c +++ b/calendar/gui/e-task-shell-view-private.c @@ -21,10 +21,18 @@ #include "e-task-shell-view-private.h" void -e_task_shell_view_private_init (ETaskShellView *task_shell_view) +e_task_shell_view_private_init (ETaskShellView *task_shell_view, + EShellViewClass *shell_view_class) { ETaskShellViewPrivate *priv = task_shell_view->priv; + ESourceList *source_list; + GObject *object; + object = G_OBJECT (shell_view_class->type_module); + source_list = g_object_get_data (object, "source-list"); + g_return_if_fail (E_IS_SOURCE_LIST (source_list)); + + priv->source_list = g_object_ref (source_list); priv->task_actions = gtk_action_group_new ("tasks"); } @@ -39,6 +47,8 @@ e_task_shell_view_private_dispose (ETaskShellView *task_shell_view) { ETaskShellViewPrivate *priv = task_shell_view->priv; + DISPOSE (priv->source_list); + DISPOSE (priv->task_actions); } diff --git a/calendar/gui/e-task-shell-view-private.h b/calendar/gui/e-task-shell-view-private.h index 42a9ea10bc..22db8668c0 100644 --- a/calendar/gui/e-task-shell-view-private.h +++ b/calendar/gui/e-task-shell-view-private.h @@ -51,13 +51,18 @@ G_BEGIN_DECLS struct _ETaskShellViewPrivate { + /*** Module Data ***/ + + ESourceList *source_list; + /*** UI Management ***/ GtkActionGroup *task_actions; }; void e_task_shell_view_private_init - (ETaskShellView *task_shell_view); + (ETaskShellView *task_shell_view, + EShellViewClass *shell_view_class); void e_task_shell_view_private_constructed (ETaskShellView *task_shell_view); void e_task_shell_view_private_dispose diff --git a/calendar/gui/e-task-shell-view.c b/calendar/gui/e-task-shell-view.c index 526769234f..798d868910 100644 --- a/calendar/gui/e-task-shell-view.c +++ b/calendar/gui/e-task-shell-view.c @@ -20,10 +20,32 @@ #include "e-task-shell-view-private.h" +enum { + PROP_0, + PROP_SOURCE_LIST +}; + GType e_task_shell_view_type = 0; static gpointer parent_class; static void +task_shell_view_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_SOURCE_LIST: + g_value_set_object ( + value, e_task_shell_view_get_source_list ( + E_TASK_SHELL_VIEW (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void task_shell_view_dispose (GObject *object) { e_task_shell_view_private_dispose (E_TASK_SHELL_VIEW (object)); @@ -75,6 +97,7 @@ task_shell_view_class_init (ETaskShellView *class, g_type_class_add_private (class, sizeof (ETaskShellViewPrivate)); object_class = G_OBJECT_CLASS (class); + object_class->get_property = task_shell_view_get_property; object_class->dispose = task_shell_view_dispose; object_class->finalize = task_shell_view_finalize; object_class->constructed = task_shell_view_constructed; @@ -84,15 +107,26 @@ task_shell_view_class_init (ETaskShellView *class, shell_view_class->icon_name = "evolution-tasks"; shell_view_class->type_module = type_module; shell_view_class->changed = task_shell_view_changed; + + g_object_class_install_property ( + object_class, + PROP_SOURCE_LIST, + g_param_spec_object ( + "source-list", + _("Source List"), + _("The registry of task lists"), + E_TYPE_SOURCE_LIST, + G_PARAM_READABLE)); } static void -task_shell_view_init (ETaskShellView *task_shell_view) +task_shell_view_init (ETaskShellView *task_shell_view, + EShellViewClass *shell_view_class) { task_shell_view->priv = E_TASK_SHELL_VIEW_GET_PRIVATE (task_shell_view); - e_task_shell_view_private_init (task_shell_view); + e_task_shell_view_private_init (task_shell_view, shell_view_class); } GType @@ -120,3 +154,11 @@ e_task_shell_view_get_type (GTypeModule *type_module) return e_task_shell_view_type; } + +ESourceList * +e_task_shell_view_get_source_list (ETaskShellView *task_shell_view) +{ + g_return_val_if_fail (E_IS_TASK_SHELL_VIEW (task_shell_view), NULL); + + return task_shell_view->priv->source_list; +} diff --git a/calendar/gui/e-task-shell-view.h b/calendar/gui/e-task-shell-view.h index 94dca3e491..785a3585b1 100644 --- a/calendar/gui/e-task-shell-view.h +++ b/calendar/gui/e-task-shell-view.h @@ -22,6 +22,7 @@ #define E_TASK_SHELL_VIEW_H #include <e-shell-view.h> +#include <libedataserver/e-source-list.h> /* Standard GObject macros */ #define E_TYPE_TASK_SHELL_VIEW \ @@ -59,7 +60,10 @@ struct _ETaskShellViewClass { EShellViewClass parent_class; }; -GType e_task_shell_view_get_type (GTypeModule *type_module); +GType e_task_shell_view_get_type + (GTypeModule *type_module); +ESourceList * e_task_shell_view_get_source_list + (ETaskShellView *task_shell_view); G_END_DECLS diff --git a/calendar/gui/memos-component.c b/calendar/gui/memos-component.c index e292e8a7da..93af51f061 100644 --- a/calendar/gui/memos-component.c +++ b/calendar/gui/memos-component.c @@ -119,128 +119,6 @@ struct _MemosComponentPrivate { /* #define d(x) x */ #define d(x) -static void -ensure_sources (MemosComponent *component) -{ - GSList *groups; - ESourceList *source_list; - ESourceGroup *group; - ESourceGroup *on_this_computer; - ESourceGroup *on_the_web; - ESource *personal_source; - char *base_uri, *base_uri_proto; - const gchar *base_dir; - - on_this_computer = NULL; - on_the_web = NULL; - personal_source = NULL; - - if (!e_cal_get_sources (&source_list, E_CAL_SOURCE_TYPE_JOURNAL, NULL)) { - g_warning ("Could not get memo source list from GConf!"); - return; - } - - base_dir = memos_component_peek_base_directory (component); - base_uri = g_build_filename (base_dir, "local", NULL); - - base_uri_proto = g_filename_to_uri (base_uri, NULL, NULL); - - groups = e_source_list_peek_groups (source_list); - if (groups) { - /* groups are already there, we need to search for things... */ - GSList *g; - - for (g = groups; g; g = g->next) { - - group = E_SOURCE_GROUP (g->data); - - /* compare only file:// part. If user home dir name changes we do not want to create - one more group */ - - if (!on_this_computer && !strncmp (base_uri_proto, e_source_group_peek_base_uri (group), 7)) - on_this_computer = group; - else if (!on_the_web && !strcmp (WEB_BASE_URI, e_source_group_peek_base_uri (group))) - on_the_web = group; - } - } - - if (on_this_computer) { - /* make sure "Personal" shows up as a source under - this group */ - GSList *sources = e_source_group_peek_sources (on_this_computer); - GSList *s; - for (s = sources; s; s = s->next) { - ESource *source = E_SOURCE (s->data); - const gchar *relative_uri; - - relative_uri = e_source_peek_relative_uri (source); - if (relative_uri == NULL) - continue; - if (!strcmp (PERSONAL_RELATIVE_URI, relative_uri)) { - personal_source = source; - break; - } - } - /* Make sure we have the correct base uri. This can change when user's - homedir name changes */ - if (strcmp (base_uri_proto, e_source_group_peek_base_uri (on_this_computer))) { - e_source_group_set_base_uri (on_this_computer, base_uri_proto); - - /* *sigh* . We shouldn't need this sync call here as set_base_uri - call results in synching to gconf, but that happens in idle loop - and too late to prevent user seeing "Can not Open ... because of invalid uri" error.*/ - e_source_list_sync (source_list,NULL); - } - } - else { - /* create the local source group */ - group = e_source_group_new (_("On This Computer"), base_uri_proto); - e_source_list_add_group (source_list, group, -1); - - on_this_computer = group; - } - - if (!personal_source) { - GSList *memos_selected; - /* Create the default Person addressbook */ - ESource *source = e_source_new (_("Personal"), PERSONAL_RELATIVE_URI); - e_source_group_add_source (on_this_computer, source, -1); - g_object_unref (source); - - memos_selected = calendar_config_get_memos_selected (); - - if (!calendar_config_get_primary_memos () && !memos_selected) { - GSList selected; - - calendar_config_set_primary_memos (e_source_peek_uid (source)); - - selected.data = (gpointer)e_source_peek_uid (source); - selected.next = NULL; - calendar_config_set_memos_selected (&selected); - } - - if (memos_selected) { - g_slist_foreach (memos_selected, (GFunc) g_free, NULL); - g_slist_free (memos_selected); - } - - e_source_set_color_spec (source, "#BECEDD"); - personal_source = source; - } - - if (!on_the_web) { - /* Create the LDAP source group */ - group = e_source_group_new (_("On The Web"), WEB_BASE_URI); - e_source_list_add_group (source_list, group, -1); - - on_the_web = group; - } - - component->priv->source_list = source_list; - g_free (base_uri_proto); - g_free (base_uri); -} - /* Utility functions. */ /* FIXME Some of these are duplicated from calendar-component.c */ static gboolean @@ -1346,7 +1224,6 @@ memos_component_init (MemosComponent *component, MemosComponentClass *klass) priv = g_new0 (MemosComponentPrivate, 1); component->priv = priv; - ensure_sources (component); } /* Public API */ diff --git a/calendar/gui/memos-component.h b/calendar/gui/memos-component.h index b3995628ab..399f0ce06a 100644 --- a/calendar/gui/memos-component.h +++ b/calendar/gui/memos-component.h @@ -56,9 +56,6 @@ struct _MemosComponentClass { GType memos_component_get_type (void); MemosComponent *memos_component_peek (void); - -const char *memos_component_peek_base_directory (MemosComponent *component); -const char *memos_component_peek_config_directory (MemosComponent *component); ESourceList *memos_component_peek_source_list (MemosComponent *component); #endif /* _MEMOS_COMPONENT_H_ */ diff --git a/calendar/gui/tasks-component.c b/calendar/gui/tasks-component.c index 80e36c0feb..92c45baab2 100644 --- a/calendar/gui/tasks-component.c +++ b/calendar/gui/tasks-component.c @@ -115,128 +115,6 @@ struct _TasksComponentPrivate { GList *notifications; }; -static void -ensure_sources (TasksComponent *component) -{ - GSList *groups; - ESourceList *source_list; - ESourceGroup *group; - ESourceGroup *on_this_computer; - ESourceGroup *on_the_web; - ESource *personal_source; - char *base_uri, *base_uri_proto; - const gchar *base_dir; - - on_this_computer = NULL; - on_the_web = NULL; - personal_source = NULL; - - if (!e_cal_get_sources (&source_list, E_CAL_SOURCE_TYPE_TODO, NULL)) { - g_warning ("Could not get addressbook source list from GConf!"); - return; - } - - base_dir = tasks_component_peek_base_directory (component); - base_uri = g_build_filename (base_dir, "local", NULL); - - base_uri_proto = g_filename_to_uri (base_uri, NULL, NULL); - - groups = e_source_list_peek_groups (source_list); - if (groups) { - /* groups are already there, we need to search for things... */ - GSList *g; - - for (g = groups; g; g = g->next) { - - group = E_SOURCE_GROUP (g->data); - - /* compare only file:// part. If user home dir name changes we do not want to create - one more group */ - - if (!on_this_computer && !strncmp (base_uri_proto, e_source_group_peek_base_uri (group), 7)) - on_this_computer = group; - else if (!on_the_web && !strcmp (WEB_BASE_URI, e_source_group_peek_base_uri (group))) - on_the_web = group; - } - } - - if (on_this_computer) { - /* make sure "Personal" shows up as a source under - this group */ - GSList *sources = e_source_group_peek_sources (on_this_computer); - GSList *s; - for (s = sources; s; s = s->next) { - ESource *source = E_SOURCE (s->data); - const gchar *relative_uri; - - relative_uri = e_source_peek_relative_uri (source); - if (relative_uri == NULL) - continue; - if (!strcmp (PERSONAL_RELATIVE_URI, relative_uri)) { - personal_source = source; - break; - } - } - /* Make sure we have the correct base uri. This can change when user's - homedir name changes */ - if (strcmp (base_uri_proto, e_source_group_peek_base_uri (on_this_computer))) { - e_source_group_set_base_uri (on_this_computer, base_uri_proto); - - /* *sigh* . We shouldn't need this sync call here as set_base_uri - call results in synching to gconf, but that happens in idle loop - and too late to prevent user seeing "Can not Open ... because of invalid uri" error.*/ - e_source_list_sync (source_list,NULL); - } - } - else { - /* create the local source group */ - group = e_source_group_new (_("On This Computer"), base_uri_proto); - e_source_list_add_group (source_list, group, -1); - - on_this_computer = group; - } - - if (!personal_source) { - GSList *tasks_selected; - /* Create the default Person addressbook */ - ESource *source = e_source_new (_("Personal"), PERSONAL_RELATIVE_URI); - e_source_group_add_source (on_this_computer, source, -1); - g_object_unref (source); - - tasks_selected = calendar_config_get_tasks_selected (); - - if (!calendar_config_get_primary_tasks () && !tasks_selected) { - GSList selected; - - calendar_config_set_primary_tasks (e_source_peek_uid (source)); - - selected.data = (gpointer)e_source_peek_uid (source); - selected.next = NULL; - calendar_config_set_tasks_selected (&selected); - } - - if (tasks_selected) { - g_slist_foreach (tasks_selected, (GFunc) g_free, NULL); - g_slist_free (tasks_selected); - } - - e_source_set_color_spec (source, "#BECEDD"); - personal_source = source; - } - - if (!on_the_web) { - /* Create the LDAP source group */ - group = e_source_group_new (_("On The Web"), WEB_BASE_URI); - e_source_list_add_group (source_list, group, -1); - - on_the_web = group; - } - - component->priv->source_list = source_list; - g_free (base_uri_proto); - g_free (base_uri); -} - /* Utility functions. */ /* FIXME Some of these are duplicated from calendar-component.c */ static gboolean @@ -1410,7 +1288,6 @@ tasks_component_init (TasksComponent *component, TasksComponentClass *klass) priv = g_new0 (TasksComponentPrivate, 1); component->priv = priv; - ensure_sources (component); } /* Public API */ diff --git a/calendar/gui/tasks-component.h b/calendar/gui/tasks-component.h index cbb25d793e..8947b3da3e 100644 --- a/calendar/gui/tasks-component.h +++ b/calendar/gui/tasks-component.h @@ -54,10 +54,7 @@ struct _TasksComponentClass { GType tasks_component_get_type (void); -TasksComponent *tasks_component_peek (void); -const char *tasks_component_peek_base_directory (TasksComponent *component); -const char *tasks_component_peek_config_directory (TasksComponent *component); ESourceList *tasks_component_peek_source_list (TasksComponent *component); #endif /* _TASKS_COMPONENT_H_ */ diff --git a/shell/e-shell-window.c b/shell/e-shell-window.c index d2b1f36ff6..78c6a31836 100644 --- a/shell/e-shell-window.c +++ b/shell/e-shell-window.c @@ -30,7 +30,6 @@ enum { PROP_0, PROP_CURRENT_VIEW, - PROP_ICON_NAME, PROP_SAFE_MODE, PROP_SHELL }; |