aboutsummaryrefslogtreecommitdiffstats
path: root/calendar/gui
diff options
context:
space:
mode:
Diffstat (limited to 'calendar/gui')
-rw-r--r--calendar/gui/cal-search-bar.c45
-rw-r--r--calendar/gui/calendar-commands.c16
-rw-r--r--calendar/gui/calendar-model.c10
-rw-r--r--calendar/gui/dialogs/recurrence-page.c2
-rw-r--r--calendar/gui/e-day-view.c48
-rw-r--r--calendar/gui/e-day-view.h6
-rw-r--r--calendar/gui/e-week-view.c49
-rw-r--r--calendar/gui/e-week-view.h6
-rw-r--r--calendar/gui/gnome-cal.c487
-rw-r--r--calendar/gui/gnome-cal.h11
-rw-r--r--calendar/gui/main.c2
-rw-r--r--calendar/gui/tag-calendar.c12
-rw-r--r--calendar/gui/tag-calendar.h2
13 files changed, 531 insertions, 165 deletions
diff --git a/calendar/gui/cal-search-bar.c b/calendar/gui/cal-search-bar.c
index e5cfcf95e9..a112409412 100644
--- a/calendar/gui/cal-search-bar.c
+++ b/calendar/gui/cal-search-bar.c
@@ -23,6 +23,7 @@
#include <config.h>
#endif
+#include <stdlib.h>
#include <glib.h>
#include <gtk/gtkmenu.h>
#include <gtk/gtkmenuitem.h>
@@ -401,6 +402,39 @@ item_destroyed_cb (GtkObject *object, gpointer data)
g_free (category);
}
+/* Used from qsort() */
+static int
+compare_categories_cb (const void *a, const void *b)
+{
+ const char **ca, **cb;
+
+ ca = (const char **) a;
+ cb = (const char **) b;
+
+ /* FIXME: should use some utf8 strcoll() thingy */
+ return strcmp (*ca, *cb);
+}
+
+/* Creates a sorted array of categories based on the original one; does not
+ * duplicate the string values.
+ */
+static GPtrArray *
+sort_categories (GPtrArray *categories)
+{
+ GPtrArray *c;
+ int i;
+
+ c = g_ptr_array_new ();
+ g_ptr_array_set_size (c, categories->len);
+
+ for (i = 0; i < categories->len; i++)
+ c->pdata[i] = categories->pdata[i];
+
+ qsort (c->pdata, c->len, sizeof (gpointer), compare_categories_cb);
+
+ return c;
+}
+
/**
* cal_search_bar_set_categories:
* @cal_search: A calendar search bar.
@@ -417,6 +451,7 @@ cal_search_bar_set_categories (CalSearchBar *cal_search, GPtrArray *categories)
CalSearchBarPrivate *priv;
GtkMenu *menu;
GtkWidget *item;
+ GPtrArray *sorted;
int i;
g_return_if_fail (cal_search != NULL);
@@ -450,19 +485,21 @@ cal_search_bar_set_categories (CalSearchBar *cal_search, GPtrArray *categories)
/* Categories items */
- for (i = 0; i < categories->len; i++) {
+ sorted = sort_categories (categories);
+
+ for (i = 0; i < sorted->len; i++) {
char *str;
/* FIXME: Put the category icons here */
- str = e_utf8_to_gtk_string (GTK_WIDGET (menu), categories->pdata[i]);
+ str = e_utf8_to_gtk_string (GTK_WIDGET (menu), sorted->pdata[i]);
if (!str)
continue;
item = gtk_menu_item_new_with_label (str);
g_free (str);
- gtk_object_set_user_data (GTK_OBJECT (item), g_strdup (categories->pdata[i]));
+ gtk_object_set_user_data (GTK_OBJECT (item), g_strdup (sorted->pdata[i]));
gtk_signal_connect (GTK_OBJECT (item), "destroy",
GTK_SIGNAL_FUNC (item_destroyed_cb),
NULL);
@@ -471,6 +508,8 @@ cal_search_bar_set_categories (CalSearchBar *cal_search, GPtrArray *categories)
gtk_widget_show (item);
}
+ g_ptr_array_free (sorted, TRUE);
+
/* Set the new menu; the old one will be destroyed automatically */
gtk_option_menu_set_menu (priv->categories_omenu, GTK_WIDGET (menu));
diff --git a/calendar/gui/calendar-commands.c b/calendar/gui/calendar-commands.c
index 8f4c9da265..22640d2629 100644
--- a/calendar/gui/calendar-commands.c
+++ b/calendar/gui/calendar-commands.c
@@ -513,22 +513,6 @@ calendar_control_activate (BonoboControl *control,
bonobo_ui_component_set_container (uic, remote_uih);
bonobo_object_release_unref (remote_uih, NULL);
-#if 0
- /* FIXME: Need to update this to use new Bonobo ui stuff somehow.
- Also need radio buttons really. */
-
- /* Note that these indices should correspond with the button indices
- in the gnome_toolbar_view_buttons UIINFO struct. */
- gnome_calendar_set_view_buttons (cal,
- gnome_toolbar_view_buttons[0].widget,
- gnome_toolbar_view_buttons[1].widget,
- gnome_toolbar_view_buttons[2].widget,
- gnome_toolbar_view_buttons[3].widget);
-
- /* This makes the appropriate radio button in the toolbar active. */
- gnome_calendar_update_view_buttons (cal);
-#endif
-
bonobo_ui_component_add_verb_list_with_data (uic, verbs, gcal);
bonobo_ui_component_freeze (uic, NULL);
diff --git a/calendar/gui/calendar-model.c b/calendar/gui/calendar-model.c
index 94221fdd61..43195071f0 100644
--- a/calendar/gui/calendar-model.c
+++ b/calendar/gui/calendar-model.c
@@ -1897,6 +1897,7 @@ static void
update_query (CalendarModel *model)
{
CalendarModelPrivate *priv;
+ CalQuery *old_query;
char *real_sexp;
priv = model->priv;
@@ -1909,9 +1910,12 @@ update_query (CalendarModel *model)
&& cal_client_get_load_state (priv->client) == CAL_CLIENT_LOAD_LOADED))
return;
- if (priv->query) {
- gtk_signal_disconnect_by_data (GTK_OBJECT (priv->query), model);
- gtk_object_unref (GTK_OBJECT (priv->query));
+ old_query = priv->query;
+ priv->query = NULL;
+
+ if (old_query) {
+ gtk_signal_disconnect_by_data (GTK_OBJECT (old_query), model);
+ gtk_object_unref (GTK_OBJECT (old_query));
}
g_assert (priv->sexp != NULL);
diff --git a/calendar/gui/dialogs/recurrence-page.c b/calendar/gui/dialogs/recurrence-page.c
index 5c7e7d65cb..20310f6433 100644
--- a/calendar/gui/dialogs/recurrence-page.c
+++ b/calendar/gui/dialogs/recurrence-page.c
@@ -900,7 +900,7 @@ preview_recur (RecurrencePage *rpage)
fill_component (rpage, comp);
tag_calendar_by_comp (E_CALENDAR (priv->preview_calendar), comp,
- COMP_EDITOR_PAGE (rpage)->client);
+ COMP_EDITOR_PAGE (rpage)->client, TRUE);
gtk_object_unref (GTK_OBJECT (comp));
}
diff --git a/calendar/gui/e-day-view.c b/calendar/gui/e-day-view.c
index daff360ab6..e1b5a7b444 100644
--- a/calendar/gui/e-day-view.c
+++ b/calendar/gui/e-day-view.c
@@ -565,6 +565,8 @@ e_day_view_init (EDayView *day_view)
day_view->auto_scroll_timeout_id = 0;
+ day_view->default_category = NULL;
+
/* Create the large font. */
day_view->large_font = gdk_font_load (E_DAY_VIEW_LARGE_FONT);
if (!day_view->large_font)
@@ -896,8 +898,15 @@ e_day_view_destroy (GtkObject *object)
day_view->query = NULL;
}
- if (day_view->large_font)
+ if (day_view->large_font) {
gdk_font_unref (day_view->large_font);
+ day_view->large_font = NULL;
+ }
+
+ if (day_view->default_category) {
+ g_free (day_view->default_category);
+ day_view->default_category = NULL;
+ }
gdk_cursor_destroy (day_view->normal_cursor);
gdk_cursor_destroy (day_view->move_cursor);
@@ -1562,7 +1571,7 @@ adjust_query_sexp (EDayView *day_view, const char *sexp)
/* If the dates have not been set yet, we just want an empty query. */
if (day_view->lower == 0 || day_view->upper == 0)
- return g_strdup ("#f");
+ return NULL;
start = isodate_from_time_t (day_view->lower);
end = isodate_from_time_t (day_view->upper);
@@ -1585,6 +1594,7 @@ adjust_query_sexp (EDayView *day_view, const char *sexp)
static void
update_query (EDayView *day_view)
{
+ CalQuery *old_query;
char *real_sexp;
e_day_view_free_events (day_view);
@@ -1595,13 +1605,19 @@ update_query (EDayView *day_view)
&& cal_client_get_load_state (day_view->client) == CAL_CLIENT_LOAD_LOADED))
return;
- if (day_view->query) {
- gtk_signal_disconnect_by_data (GTK_OBJECT (day_view->query), day_view);
- gtk_object_unref (GTK_OBJECT (day_view->query));
+ old_query = day_view->query;
+ day_view->query = NULL;
+
+ if (old_query) {
+ gtk_signal_disconnect_by_data (GTK_OBJECT (old_query), day_view);
+ gtk_object_unref (GTK_OBJECT (old_query));
}
g_assert (day_view->sexp != NULL);
+
real_sexp = adjust_query_sexp (day_view, day_view->sexp);
+ if (!real_sexp)
+ return; /* No time range is set, so don't start a query */
day_view->query = cal_client_get_query (day_view->client, real_sexp);
g_free (real_sexp);
@@ -1698,6 +1714,26 @@ e_day_view_set_query (EDayView *day_view, const char *sexp)
}
+/**
+ * e_day_view_set_default_category:
+ * @day_view: A day view.
+ * @category: Default category name or NULL for no category.
+ *
+ * Sets the default category that will be used when creating new calendar
+ * components from the day view.
+ **/
+void
+e_day_view_set_default_category (EDayView *day_view, const char *category)
+{
+ g_return_if_fail (day_view != NULL);
+ g_return_if_fail (E_IS_DAY_VIEW (day_view));
+
+ if (day_view->default_category)
+ g_free (day_view->default_category);
+
+ day_view->default_category = g_strdup (category);
+}
+
static gboolean
e_day_view_update_event_cb (EDayView *day_view,
gint day,
@@ -4933,6 +4969,8 @@ e_day_view_key_press (GtkWidget *widget, GdkEventKey *event)
day_view->zone);
cal_component_set_dtend (comp, &dt);
+ cal_component_set_categories (comp, day_view->default_category);
+
/* We add the event locally and start editing it. When we get the
"update_event" callback from the server, we basically ignore it.
If we were to wait for the "update_event" callback it wouldn't be
diff --git a/calendar/gui/e-day-view.h b/calendar/gui/e-day-view.h
index bddc36b708..bc663d7a6c 100644
--- a/calendar/gui/e-day-view.h
+++ b/calendar/gui/e-day-view.h
@@ -480,6 +480,9 @@ struct _EDayView
/* the invisible widget to manage the clipboard selections */
GtkWidget *invisible;
gchar *clipboard_selection;
+
+ /* The default category for new events */
+ char *default_category;
};
struct _EDayViewClass
@@ -500,6 +503,9 @@ void e_day_view_set_cal_client (EDayView *day_view,
void e_day_view_set_query (EDayView *day_view,
const char *sexp);
+void e_day_view_set_default_category (EDayView *day_view,
+ const char *category);
+
/* This sets the selected time range. The EDayView will show the day or week
corresponding to the start time. If the start_time & end_time are not equal
and are both visible in the view, then the selection is set to those times,
diff --git a/calendar/gui/e-week-view.c b/calendar/gui/e-week-view.c
index c0b9d82a10..5d269cf471 100644
--- a/calendar/gui/e-week-view.c
+++ b/calendar/gui/e-week-view.c
@@ -297,6 +297,8 @@ e_week_view_init (EWeekView *week_view)
week_view->main_gc = NULL;
+ week_view->default_category = NULL;
+
/* Create the small font. */
week_view->use_small_font = TRUE;
week_view->small_font = gdk_font_load (E_WEEK_VIEW_SMALL_FONT);
@@ -463,8 +465,15 @@ e_week_view_destroy (GtkObject *object)
week_view->query = NULL;
}
- if (week_view->small_font)
+ if (week_view->small_font) {
gdk_font_unref (week_view->small_font);
+ week_view->small_font = NULL;
+ }
+
+ if (week_view->default_category) {
+ g_free (week_view->default_category);
+ week_view->default_category = NULL;
+ }
gdk_cursor_destroy (week_view->normal_cursor);
gdk_cursor_destroy (week_view->move_cursor);
@@ -1056,7 +1065,7 @@ adjust_query_sexp (EWeekView *week_view, const char *sexp)
/* If the dates have not been set yet, we just want an empty query. */
if (!g_date_valid (&week_view->first_day_shown))
- return g_strdup ("#f");
+ return NULL;
num_days = week_view->multi_week_view ? week_view->weeks_shown * 7 : 7;
@@ -1080,6 +1089,7 @@ adjust_query_sexp (EWeekView *week_view, const char *sexp)
static void
update_query (EWeekView *week_view)
{
+ CalQuery *old_query;
char *real_sexp;
e_week_view_free_events (week_view);
@@ -1089,13 +1099,19 @@ update_query (EWeekView *week_view)
&& cal_client_get_load_state (week_view->client) == CAL_CLIENT_LOAD_LOADED))
return;
- if (week_view->query) {
- gtk_signal_disconnect_by_data (GTK_OBJECT (week_view->query), week_view);
- gtk_object_unref (GTK_OBJECT (week_view->query));
+ old_query = week_view->query;
+ week_view->query = NULL;
+
+ if (old_query) {
+ gtk_signal_disconnect_by_data (GTK_OBJECT (old_query), week_view);
+ gtk_object_unref (GTK_OBJECT (old_query));
}
g_assert (week_view->sexp != NULL);
+
real_sexp = adjust_query_sexp (week_view, week_view->sexp);
+ if (!real_sexp)
+ return; /* No time range is set, so don't start a query */
week_view->query = cal_client_get_query (week_view->client, real_sexp);
g_free (real_sexp);
@@ -1192,6 +1208,27 @@ e_week_view_set_query (EWeekView *week_view, const char *sexp)
}
+/**
+ * e_week_view_set_default_category:
+ * @week_view: A week view.
+ * @category: Default category name or NULL for no category.
+ *
+ * Sets the default category that will be used when creating new calendar
+ * components from the week view.
+ **/
+void
+e_week_view_set_default_category (EWeekView *week_view, const char *category)
+{
+ g_return_if_fail (week_view != NULL);
+ g_return_if_fail (E_IS_WEEK_VIEW (week_view));
+
+ if (week_view->default_category)
+ g_free (week_view->default_category);
+
+ week_view->default_category = g_strdup (category);
+}
+
+
/* This sets the selected time range. The EWeekView will show the corresponding
month and the days between start_time and end_time will be selected.
To select a single day, use the same value for start_time & end_time. */
@@ -3091,6 +3128,8 @@ e_week_view_key_press (GtkWidget *widget, GdkEventKey *event)
week_view->zone);
cal_component_set_dtend (comp, &date);
+ cal_component_set_categories (comp, week_view->default_category);
+
/* We add the event locally and start editing it. We don't send the
new event to the server until the edit is finished.
FIXME: If we get an obj-updated or obj-removed signal while editing
diff --git a/calendar/gui/e-week-view.h b/calendar/gui/e-week-view.h
index 5b3f257f5e..a75cc5df5e 100644
--- a/calendar/gui/e-week-view.h
+++ b/calendar/gui/e-week-view.h
@@ -353,6 +353,9 @@ struct _EWeekView
/* the invisible widget to manage the clipboard selections */
GtkWidget *invisible;
gchar *clipboard_selection;
+
+ /* The default category for new events */
+ char *default_category;
};
struct _EWeekViewClass
@@ -381,6 +384,9 @@ void e_week_view_set_cal_client (EWeekView *week_view,
void e_week_view_set_query (EWeekView *week_view,
const char *sexp);
+void e_week_view_set_default_category (EWeekView *week_view,
+ const char *category);
+
/* The selected time range. The EWeekView will show the corresponding
month and the days between start_time and end_time will be selected.
To select a single day, use the same value for start_time & end_time. */
diff --git a/calendar/gui/gnome-cal.c b/calendar/gui/gnome-cal.c
index 847a89ea06..2588d4dee2 100644
--- a/calendar/gui/gnome-cal.c
+++ b/calendar/gui/gnome-cal.c
@@ -65,6 +65,9 @@ struct _GnomeCalendarPrivate {
/* The calendar client object we monitor */
CalClient *client;
+ /* Set of categories from the calendar client */
+ GPtrArray *cal_categories;
+
/*
* The TaskPad Folder.
*/
@@ -72,6 +75,9 @@ struct _GnomeCalendarPrivate {
/* The calendar client object we monitor */
CalClient *task_pad_client;
+ /* Set of categories from the tasks client */
+ GPtrArray *tasks_categories;
+
/*
* Fields for the calendar view
*/
@@ -101,11 +107,9 @@ struct _GnomeCalendarPrivate {
GtkWidget *week_view;
GtkWidget *month_view;
- /* These are the toolbar radio buttons for switching views. */
- GtkWidget *day_button;
- GtkWidget *work_week_button;
- GtkWidget *week_button;
- GtkWidget *month_button;
+ /* Calendar query for the date navigator */
+ CalQuery *dn_query;
+ char *sexp;
/* This is the view currently shown. We use it to keep track of the
positions of the panes. range_selected is TRUE if a range of dates
@@ -170,6 +174,8 @@ static void gnome_calendar_on_date_navigator_selection_changed (ECalendarItem
GnomeCalendar *gcal);
static void gnome_calendar_notify_dates_shown_changed (GnomeCalendar *gcal);
+static void update_query (GnomeCalendar *gcal);
+
static GtkVBoxClass *parent_class;
@@ -227,6 +233,197 @@ gnome_calendar_class_init (GnomeCalendarClass *class)
class->dates_shown_changed = NULL;
}
+/* Callback used when the calendar query reports of an updated object */
+static void
+dn_query_obj_updated_cb (CalQuery *query, const char *uid,
+ gboolean query_in_progress, int n_scanned, int total,
+ gpointer data)
+{
+ GnomeCalendar *gcal;
+ GnomeCalendarPrivate *priv;
+ CalComponent *comp;
+ CalClientGetStatus status;
+
+ gcal = GNOME_CALENDAR (data);
+ priv = gcal->priv;
+
+ status = cal_client_get_object (priv->client, uid, &comp);
+
+ switch (status) {
+ case CAL_CLIENT_GET_SUCCESS:
+ /* Everything is fine */
+ break;
+
+ case CAL_CLIENT_GET_SYNTAX_ERROR:
+ g_message ("dn_query_obj_updated_cb(): Syntax error while getting object `%s'", uid);
+ break;
+
+ case CAL_CLIENT_GET_NOT_FOUND:
+ /* The object is no longer in the server, so do nothing */
+ break;
+
+ default:
+ g_assert_not_reached ();
+ return;
+ }
+
+ tag_calendar_by_comp (priv->date_navigator, comp, priv->client, FALSE);
+ gtk_object_unref (GTK_OBJECT (comp));
+}
+
+/* Callback used when the calendar query reports of a removed object */
+static void
+dn_query_obj_removed_cb (CalQuery *query, const char *uid, gpointer data)
+{
+ GnomeCalendar *gcal;
+
+ gcal = GNOME_CALENDAR (data);
+
+ /* Just retag the whole thing */
+ update_query (gcal);
+}
+
+/* Callback used when the calendar query is done */
+static void
+dn_query_query_done_cb (CalQuery *query, CalQueryDoneStatus status, const char *error_str,
+ gpointer data)
+{
+ GnomeCalendar *gcal;
+
+ gcal = GNOME_CALENDAR (data);
+
+ /* FIXME */
+
+ if (status != CAL_QUERY_DONE_SUCCESS)
+ fprintf (stderr, "query done: %s\n", error_str);
+}
+
+/* Callback used when the calendar query reports an evaluation error */
+static void
+dn_query_eval_error_cb (CalQuery *query, const char *error_str, gpointer data)
+{
+ GnomeCalendar *gcal;
+
+ gcal = GNOME_CALENDAR (data);
+
+ /* FIXME */
+
+ fprintf (stderr, "eval error: %s\n", error_str);
+}
+
+/* Computes the range of time that the date navigator is showing */
+static void
+get_date_navigator_range (GnomeCalendar *gcal, time_t *start_time, time_t *end_time)
+{
+ GnomeCalendarPrivate *priv;
+ gint start_year, start_month, start_day;
+ gint end_year, end_month, end_day;
+ struct icaltimetype start_tt;
+ struct icaltimetype end_tt;
+
+ priv = gcal->priv;
+
+ start_tt = icaltime_null_time ();
+ end_tt = icaltime_null_time ();
+
+ if (!e_calendar_item_get_date_range (priv->date_navigator->calitem,
+ &start_year, &start_month, &start_day,
+ &end_year, &end_month, &end_day)) {
+ *start_time = -1;
+ *end_time = -1;
+ return;
+ }
+
+ start_tt.year = start_year;
+ start_tt.month = start_month + 1;
+ start_tt.day = start_day;
+
+ end_tt.year = end_year;
+ end_tt.month = end_month + 1;
+ end_tt.day = end_day;
+
+ icaltime_adjust (&end_tt, 1, 0, 0, 0);
+
+ *start_time = icaltime_as_timet_with_zone (start_tt, priv->zone);
+ *end_time = icaltime_as_timet_with_zone (end_tt, priv->zone);
+}
+
+/* Adjusts a given query sexp with the time range of the date navigator */
+static char *
+adjust_query_sexp (GnomeCalendar *gcal, const char *sexp)
+{
+ time_t start_time, end_time;
+ char *start, *end;
+ char *new_sexp;
+
+ get_date_navigator_range (gcal, &start_time, &end_time);
+ if (start_time == -1 || end_time == -1)
+ return NULL;
+
+ start = isodate_from_time_t (start_time);
+ end = isodate_from_time_t (end_time);
+
+ new_sexp = g_strdup_printf ("(and (= (get-vtype) \"VEVENT\")"
+ " (occur-in-time-range? (make-time \"%s\")"
+ " (make-time \"%s\"))"
+ " %s)",
+ start, end,
+ sexp);
+
+ g_free (start);
+ g_free (end);
+
+ return new_sexp;
+}
+
+/* Restarts a query for the date navigator in the calendar */
+static void
+update_query (GnomeCalendar *gcal)
+{
+ GnomeCalendarPrivate *priv;
+ CalQuery *old_query;
+ char *real_sexp;
+
+ priv = gcal->priv;
+
+ e_calendar_item_clear_marks (priv->date_navigator->calitem);
+
+ if (!(priv->client
+ && cal_client_get_load_state (priv->client) == CAL_CLIENT_LOAD_LOADED))
+ return;
+
+ old_query = priv->dn_query;
+ priv->dn_query = NULL;
+
+ if (old_query) {
+ gtk_signal_disconnect_by_data (GTK_OBJECT (old_query), gcal);
+ gtk_object_unref (GTK_OBJECT (old_query));
+ }
+
+ g_assert (priv->sexp != NULL);
+
+ real_sexp = adjust_query_sexp (gcal, priv->sexp);
+ if (!real_sexp)
+ return; /* No time range is set, so don't start a query */
+
+ priv->dn_query = cal_client_get_query (priv->client, real_sexp);
+ g_free (real_sexp);
+
+ if (!priv->dn_query) {
+ g_message ("update_query(): Could not create the query");
+ return;
+ }
+
+ gtk_signal_connect (GTK_OBJECT (priv->dn_query), "obj_updated",
+ GTK_SIGNAL_FUNC (dn_query_obj_updated_cb), gcal);
+ gtk_signal_connect (GTK_OBJECT (priv->dn_query), "obj_removed",
+ GTK_SIGNAL_FUNC (dn_query_obj_removed_cb), gcal);
+ gtk_signal_connect (GTK_OBJECT (priv->dn_query), "query_done",
+ GTK_SIGNAL_FUNC (dn_query_query_done_cb), gcal);
+ gtk_signal_connect (GTK_OBJECT (priv->dn_query), "eval_error",
+ GTK_SIGNAL_FUNC (dn_query_eval_error_cb), gcal);
+}
+
/**
* gnome_calendar_set_query:
* @gcal: A calendar.
@@ -246,6 +443,15 @@ gnome_calendar_set_query (GnomeCalendar *gcal, const char *sexp)
priv = gcal->priv;
+ /* Set the query on the date navigator */
+
+ if (priv->sexp)
+ g_free (priv->sexp);
+
+ priv->sexp = g_strdup (sexp);
+
+ update_query (gcal);
+
/* Set the query on the main view */
switch (priv->current_view_type) {
@@ -323,9 +529,10 @@ search_bar_category_changed_cb (CalSearchBar *cal_search, const char *category,
gcal = GNOME_CALENDAR (data);
priv = gcal->priv;
- /* FIXME: Set the default category for the calendar views */
-
- /* Set the default category for the task pad */
+ e_day_view_set_default_category (E_DAY_VIEW (priv->day_view), category);
+ e_day_view_set_default_category (E_DAY_VIEW (priv->work_week_view), category);
+ e_week_view_set_default_category (E_WEEK_VIEW (priv->week_view), category);
+ e_week_view_set_default_category (E_WEEK_VIEW (priv->month_view), category);
model = e_calendar_table_get_model (E_CALENDAR_TABLE (priv->todo));
calendar_model_set_default_category (model, category);
@@ -452,12 +659,17 @@ gnome_calendar_init (GnomeCalendar *gcal)
priv = g_new0 (GnomeCalendarPrivate, 1);
gcal->priv = priv;
+ priv->cal_categories = NULL;
+ priv->tasks_categories = NULL;
+
priv->object_editor_hash = g_hash_table_new (g_str_hash, g_str_equal);
priv->current_view_type = GNOME_CAL_DAY_VIEW;
priv->range_selected = FALSE;
setup_widgets (gcal);
+ priv->dn_query = NULL;
+ priv->sexp = g_strdup ("#t"); /* Match all */
priv->selection_start_time = time_day_begin_with_zone (time (NULL),
priv->zone);
@@ -467,6 +679,21 @@ gnome_calendar_init (GnomeCalendar *gcal)
priv->view_menus = NULL;
}
+/* Frees a set of categories */
+static void
+free_categories (GPtrArray *categories)
+{
+ int i;
+
+ if (!categories)
+ return;
+
+ for (i = 0; i < categories->len; i++)
+ g_free (categories->pdata[i]);
+
+ g_ptr_array_free (categories, TRUE);
+}
+
/* Used from g_hash_table_foreach(); frees an UID string */
static void
destroy_editor_cb (gpointer key, gpointer value, gpointer data)
@@ -490,11 +717,28 @@ gnome_calendar_destroy (GtkObject *object)
gcal = GNOME_CALENDAR (object);
priv = gcal->priv;
+ free_categories (priv->cal_categories);
+ priv->cal_categories = NULL;
+
+ free_categories (priv->tasks_categories);
+ priv->tasks_categories = NULL;
+
/* Save the TaskPad layout. */
filename = g_strdup_printf ("%s/config/TaskPad", evolution_dir);
e_calendar_table_save_state (E_CALENDAR_TABLE (priv->todo), filename);
g_free (filename);
+ if (priv->dn_query) {
+ gtk_signal_disconnect_by_data (GTK_OBJECT (priv->dn_query), gcal);
+ gtk_object_unref (GTK_OBJECT (priv->dn_query));
+ priv->dn_query = NULL;
+ }
+
+ if (priv->sexp) {
+ g_free (priv->sexp);
+ priv->sexp = NULL;
+ }
+
if (priv->client) {
gtk_object_unref (GTK_OBJECT (priv->client));
priv->client = NULL;
@@ -672,10 +916,7 @@ gnome_calendar_dayjump (GnomeCalendar *gcal, time_t time)
priv->zone);
priv->selection_end_time = time_add_day_with_zone (priv->selection_start_time, 1, priv->zone);
- if (priv->day_button)
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->day_button), TRUE);
- else
- gnome_calendar_set_view (gcal, GNOME_CAL_DAY_VIEW, FALSE, TRUE);
+ gnome_calendar_set_view (gcal, GNOME_CAL_DAY_VIEW, FALSE, TRUE);
}
static void
@@ -998,19 +1239,6 @@ gnome_calendar_set_pane_positions (GnomeCalendar *gcal)
gtk_widget_set_usize (GTK_WIDGET (priv->date_navigator), -2, top_pane_height + 1);
}
-/* Loads the initial data into the calendar; this should be called right after
- * the cal_opened signal from the client is invoked.
- */
-static void
-initial_load (GnomeCalendar *gcal)
-{
- GnomeCalendarPrivate *priv;
-
- priv = gcal->priv;
-
- tag_calendar_by_client (priv->date_navigator, priv->client);
-}
-
/* Displays an error to indicate that opening a calendar failed */
static void
open_error (GnomeCalendar *gcal, const char *uri)
@@ -1035,7 +1263,7 @@ method_error (GnomeCalendar *gcal, const char *uri)
/* Callback from the calendar client when a calendar is loaded */
static void
-cal_opened_cb (CalClient *client, CalClientOpenStatus status, gpointer data)
+client_cal_opened_cb (CalClient *client, CalClientOpenStatus status, gpointer data)
{
GnomeCalendar *gcal;
GnomeCalendarPrivate *priv;
@@ -1046,7 +1274,7 @@ cal_opened_cb (CalClient *client, CalClientOpenStatus status, gpointer data)
switch (status) {
case CAL_CLIENT_OPEN_SUCCESS:
if (client == priv->client)
- initial_load (gcal);
+ update_query (gcal);
break;
@@ -1069,30 +1297,118 @@ cal_opened_cb (CalClient *client, CalClientOpenStatus status, gpointer data)
}
}
-/* Callback from the calendar client when an object is updated */
+/* Duplicates an array of categories */
+static GPtrArray *
+copy_categories (GPtrArray *categories)
+{
+ GPtrArray *c;
+ int i;
+
+ c = g_ptr_array_new ();
+ g_ptr_array_set_size (c, categories->len);
+
+ for (i = 0; i < categories->len; i++)
+ c->pdata[i] = g_strdup (categories->pdata[i]);
+
+ return c;
+}
+
+/* Adds the categories from an array to a hash table if they don't exist there
+ * already.
+ */
static void
-obj_updated_cb (CalClient *client, const char *uid, gpointer data)
+add_categories (GHashTable *categories, GPtrArray *c)
{
- GnomeCalendar *gcal;
- GnomeCalendarPrivate *priv;
+ int i;
- gcal = GNOME_CALENDAR (data);
- priv = gcal->priv;
+ if (!c)
+ return;
+
+ for (i = 0; i < c->len; i++) {
+ const char *cat;
+ const char *str;
+
+ cat = c->pdata[i];
+ str = g_hash_table_lookup (categories, cat);
+
+ if (!str)
+ g_hash_table_insert (categories, (char *) cat, NULL);
+ }
+}
+
+/* Used to append categories from a hash table to an array */
+struct append_category_closure {
+ GPtrArray *c;
+
+ int i;
+};
+
+/* Appends a category from the hash table to the array */
+static void
+append_category_cb (gpointer key, gpointer value, gpointer data)
+{
+ struct append_category_closure *closure;
+ const char *category;
+
+ category = key;
+ closure = data;
+
+ closure->c->pdata[closure->i] = g_strdup (category);
+ closure->i++;
+}
+
+/* Creates the union of two sets of categories */
+static GPtrArray *
+merge_categories (GPtrArray *a, GPtrArray *b)
+{
+ GHashTable *categories;
+ int n;
+ GPtrArray *c;
+ struct append_category_closure closure;
+
+ categories = g_hash_table_new (g_str_hash, g_str_equal);
+
+ add_categories (categories, a);
+ add_categories (categories, b);
- tag_calendar_by_client (priv->date_navigator, priv->client);
+ n = g_hash_table_size (categories);
+
+ c = g_ptr_array_new ();
+ g_ptr_array_set_size (c, n);
+
+ closure.c = c;
+ closure.i = 0;
+ g_hash_table_foreach (categories, append_category_cb, &closure);
+ g_hash_table_destroy (categories);
+
+ return c;
}
-/* Callback from the calendar client when an object is removed */
+/* Callback from the calendar client when the set of categories changes. We
+ * have to merge the categories of the calendar and tasks clients.
+ */
static void
-obj_removed_cb (CalClient *client, const char *uid, gpointer data)
+client_categories_changed_cb (CalClient *client, GPtrArray *categories, gpointer data)
{
GnomeCalendar *gcal;
GnomeCalendarPrivate *priv;
+ GPtrArray *merged;
gcal = GNOME_CALENDAR (data);
priv = gcal->priv;
- tag_calendar_by_client (priv->date_navigator, priv->client);
+ if (client == priv->client) {
+ free_categories (priv->cal_categories);
+ priv->cal_categories = copy_categories (categories);
+ } else if (client == priv->task_pad_client) {
+ free_categories (priv->tasks_categories);
+ priv->tasks_categories = copy_categories (categories);
+ } else
+ g_assert_not_reached ();
+
+ merged = merge_categories (priv->cal_categories, priv->tasks_categories);
+ cal_search_bar_set_categories (CAL_SEARCH_BAR (priv->search_bar), merged);
+ free_categories (merged);
}
GtkWidget *
@@ -1115,11 +1431,9 @@ gnome_calendar_construct (GnomeCalendar *gcal)
return NULL;
gtk_signal_connect (GTK_OBJECT (priv->client), "cal_opened",
- GTK_SIGNAL_FUNC (cal_opened_cb), gcal);
- gtk_signal_connect (GTK_OBJECT (priv->client), "obj_updated",
- GTK_SIGNAL_FUNC (obj_updated_cb), gcal);
- gtk_signal_connect (GTK_OBJECT (priv->client), "obj_removed",
- GTK_SIGNAL_FUNC (obj_removed_cb), gcal);
+ GTK_SIGNAL_FUNC (client_cal_opened_cb), gcal);
+ gtk_signal_connect (GTK_OBJECT (priv->client), "categories_changed",
+ GTK_SIGNAL_FUNC (client_categories_changed_cb), gcal);
e_day_view_set_cal_client (E_DAY_VIEW (priv->day_view),
priv->client);
@@ -1138,7 +1452,9 @@ gnome_calendar_construct (GnomeCalendar *gcal)
return NULL;
gtk_signal_connect (GTK_OBJECT (priv->task_pad_client), "cal_opened",
- GTK_SIGNAL_FUNC (cal_opened_cb), gcal);
+ GTK_SIGNAL_FUNC (client_cal_opened_cb), gcal);
+ gtk_signal_connect (GTK_OBJECT (priv->task_pad_client), "categories_changed",
+ GTK_SIGNAL_FUNC (client_categories_changed_cb), gcal);
model = e_calendar_table_get_model (E_CALENDAR_TABLE (priv->todo));
g_assert (model != NULL);
@@ -1559,6 +1875,7 @@ gnome_calendar_new_appointment_for (GnomeCalendar *cal,
struct icaltimetype itt;
CalComponentDateTime dt;
CalComponent *comp;
+ const char *category;
g_return_if_fail (cal != NULL);
g_return_if_fail (GNOME_IS_CALENDAR (cal));
@@ -1568,9 +1885,13 @@ gnome_calendar_new_appointment_for (GnomeCalendar *cal,
dt.value = &itt;
dt.tzid = icaltimezone_get_tzid (priv->zone);
+ /* Component type */
+
comp = cal_component_new ();
cal_component_set_new_vtype (comp, CAL_COMPONENT_EVENT);
+ /* DTSTART, DTEND */
+
itt = icaltime_from_timet_with_zone (dtstart, FALSE, priv->zone);
if (all_day)
itt.hour = itt.minute = itt.second = 0;
@@ -1583,6 +1904,13 @@ gnome_calendar_new_appointment_for (GnomeCalendar *cal,
}
cal_component_set_dtend (comp, &dt);
+ /* Category */
+
+ category = cal_search_bar_get_category (CAL_SEARCH_BAR (priv->search_bar));
+ cal_component_set_categories (comp, category);
+
+ /* Edit! */
+
cal_component_commit_sequence (comp);
gnome_calendar_edit_object (cal, comp);
@@ -1801,7 +2129,6 @@ gnome_calendar_on_date_navigator_selection_changed (ECalendarItem *calitem,
gnome_calendar_set_view (gcal, GNOME_CAL_DAY_VIEW, TRUE, FALSE);
}
- gnome_calendar_update_view_buttons (gcal);
focus_current_view (gcal);
}
@@ -1810,11 +2137,7 @@ static void
gnome_calendar_on_date_navigator_date_range_changed (ECalendarItem *calitem,
GnomeCalendar *gcal)
{
- GnomeCalendarPrivate *priv;
-
- priv = gcal->priv;
-
- tag_calendar_by_client (priv->date_navigator, priv->client);
+ update_query (gcal);
}
@@ -1918,72 +2241,6 @@ gnome_calendar_on_date_navigator_size_allocate (GtkWidget *widget,
}
void
-gnome_calendar_set_view_buttons (GnomeCalendar *gcal,
- GtkWidget *day_button,
- GtkWidget *work_week_button,
- GtkWidget *week_button,
- GtkWidget *month_button)
-{
- GnomeCalendarPrivate *priv;
-
- g_return_if_fail (gcal != NULL);
- g_return_if_fail (GNOME_IS_CALENDAR (gcal));
- g_return_if_fail (day_button != NULL);
- g_return_if_fail (GTK_IS_TOGGLE_BUTTON (day_button));
- g_return_if_fail (work_week_button != NULL);
- g_return_if_fail (GTK_IS_TOGGLE_BUTTON (work_week_button));
- g_return_if_fail (week_button != NULL);
- g_return_if_fail (GTK_IS_TOGGLE_BUTTON (week_button));
- g_return_if_fail (month_button != NULL);
- g_return_if_fail (GTK_IS_TOGGLE_BUTTON (month_button));
-
- priv = gcal->priv;
-
- priv->day_button = day_button;
- priv->work_week_button = work_week_button;
- priv->week_button = week_button;
- priv->month_button = month_button;
-}
-
-/* This makes the appropriate radio button in the toolbar active. It blocks the
- * signals so that we can do a clean setup without affecting the views.
- */
-void
-gnome_calendar_update_view_buttons (GnomeCalendar *gcal)
-{
- GnomeCalendarPrivate *priv;
- GtkWidget *button;
-
- priv = gcal->priv;
-
- switch (priv->current_view_type) {
- case GNOME_CAL_DAY_VIEW:
- button = priv->day_button;
- break;
-
- case GNOME_CAL_WORK_WEEK_VIEW:
- button = priv->work_week_button;
- break;
-
- case GNOME_CAL_WEEK_VIEW:
- button = priv->week_button;
- break;
-
- case GNOME_CAL_MONTH_VIEW:
- button = priv->month_button;
- break;
-
- default:
- g_assert_not_reached ();
- return;
- }
-
- gtk_signal_handler_block_by_data (GTK_OBJECT (button), gcal);
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
- gtk_signal_handler_unblock_by_data (GTK_OBJECT (button), gcal);
-}
-
-void
gnome_calendar_cut_clipboard (GnomeCalendar *gcal)
{
GnomeCalendarPrivate *priv;
diff --git a/calendar/gui/gnome-cal.h b/calendar/gui/gnome-cal.h
index 5409c6f55e..85f490aea0 100644
--- a/calendar/gui/gnome-cal.h
+++ b/calendar/gui/gnome-cal.h
@@ -126,17 +126,6 @@ void gnome_calendar_get_current_time_range (GnomeCalendar *gcal,
void gnome_calendar_update_config_settings (GnomeCalendar *gcal,
gboolean initializing);
-void gnome_calendar_set_view_buttons (GnomeCalendar *gcal,
- GtkWidget *day_button,
- GtkWidget *work_week_button,
- GtkWidget *week_button,
- GtkWidget *month_button);
-
-/* This makes the appropriate radio button in the toolbar active.
- It sets the ignore_view_button_clicks flag so the "clicked" signal handlers
- just return without doing anything. */
-void gnome_calendar_update_view_buttons (GnomeCalendar *gcal);
-
/* Get the current timezone. */
icaltimezone *gnome_calendar_get_timezone (GnomeCalendar *gcal);
diff --git a/calendar/gui/main.c b/calendar/gui/main.c
index 8054bbb752..318fbfbfa3 100644
--- a/calendar/gui/main.c
+++ b/calendar/gui/main.c
@@ -61,6 +61,8 @@ init_bonobo (int argc, char **argv)
int
main (int argc, char **argv)
{
+ free (malloc (8));
+
bindtextdomain(PACKAGE, EVOLUTION_LOCALEDIR);
textdomain(PACKAGE);
diff --git a/calendar/gui/tag-calendar.c b/calendar/gui/tag-calendar.c
index a84f4e965e..de59407c20 100644
--- a/calendar/gui/tag-calendar.c
+++ b/calendar/gui/tag-calendar.c
@@ -42,7 +42,7 @@ struct calendar_tag_closure {
* Returns FALSE if the calendar has no dates shown.
*/
static gboolean
-prepare_tag (ECalendar *ecal, struct calendar_tag_closure *c)
+prepare_tag (ECalendar *ecal, struct calendar_tag_closure *c, gboolean clear_first)
{
gint start_year, start_month, start_day;
gint end_year, end_month, end_day;
@@ -50,7 +50,8 @@ prepare_tag (ECalendar *ecal, struct calendar_tag_closure *c)
struct icaltimetype end_tt = icaltime_null_time ();
char *location;
- e_calendar_item_clear_marks (ecal->calitem);
+ if (clear_first)
+ e_calendar_item_clear_marks (ecal->calitem);
if (!e_calendar_item_get_date_range (ecal->calitem,
&start_year, &start_month,
@@ -127,7 +128,7 @@ tag_calendar_by_client (ECalendar *ecal, CalClient *client)
if (cal_client_get_load_state (client) != CAL_CLIENT_LOAD_LOADED)
return;
- if (!prepare_tag (ecal, &c))
+ if (!prepare_tag (ecal, &c, TRUE))
return;
#if 0
@@ -142,12 +143,13 @@ tag_calendar_by_client (ECalendar *ecal, CalClient *client)
* tag_calendar_by_comp:
* @ecal: Calendar widget to tag.
* @comp: A calendar component object.
+ * @clear_first: Whether the #ECalendar should be cleared of any marks first.
*
* Tags an #ECalendar widget with any occurrences of a specific calendar
* component that occur within the calendar's current time range.
**/
void
-tag_calendar_by_comp (ECalendar *ecal, CalComponent *comp, CalClient *client)
+tag_calendar_by_comp (ECalendar *ecal, CalComponent *comp, CalClient *client, gboolean clear_first)
{
struct calendar_tag_closure c;
@@ -160,7 +162,7 @@ tag_calendar_by_comp (ECalendar *ecal, CalComponent *comp, CalClient *client)
if (!GTK_WIDGET_VISIBLE (ecal))
return;
- if (!prepare_tag (ecal, &c))
+ if (!prepare_tag (ecal, &c, clear_first))
return;
#if 0
diff --git a/calendar/gui/tag-calendar.h b/calendar/gui/tag-calendar.h
index f9b11c1a5a..0ec7b5a148 100644
--- a/calendar/gui/tag-calendar.h
+++ b/calendar/gui/tag-calendar.h
@@ -28,6 +28,6 @@
void tag_calendar_by_client (ECalendar *ecal, CalClient *client);
void tag_calendar_by_comp (ECalendar *ecal, CalComponent *comp,
- CalClient *client);
+ CalClient *client, gboolean clear_first);
#endif