aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--calendar/calendar.error.xml4
-rw-r--r--calendar/gui/e-day-view.c3
-rw-r--r--data/org.gnome.evolution.calendar.gschema.xml.in5
-rw-r--r--modules/calendar/e-cal-shell-settings.c5
-rw-r--r--modules/calendar/e-cal-shell-view-actions.c42
-rw-r--r--modules/calendar/e-cal-shell-view-actions.h6
-rw-r--r--modules/calendar/e-cal-shell-view-private.c462
-rw-r--r--modules/calendar/e-cal-shell-view-private.h14
-rw-r--r--modules/calendar/e-cal-shell-view.c24
-rw-r--r--ui/evolution-calendars.ui9
-rw-r--r--ui/evolution-shell.ui1
11 files changed, 574 insertions, 1 deletions
diff --git a/calendar/calendar.error.xml b/calendar/calendar.error.xml
index 236f2479fd..9301d8ba65 100644
--- a/calendar/calendar.error.xml
+++ b/calendar/calendar.error.xml
@@ -314,4 +314,8 @@
<_secondary>You must be working online to complete this operation.</_secondary>
</error>
+ <error id="search-error-generic" type="error">
+ <secondary>{0}</secondary>
+ </error>
+
</error-list>
diff --git a/calendar/gui/e-day-view.c b/calendar/gui/e-day-view.c
index 89694506f1..7b4fecfb0a 100644
--- a/calendar/gui/e-day-view.c
+++ b/calendar/gui/e-day-view.c
@@ -2515,6 +2515,9 @@ e_day_view_set_selected_time_range (ECalendarView *cal_view,
work_day_start_hour = e_cal_model_get_work_day_start_hour (model);
work_day_start_minute = e_cal_model_get_work_day_start_minute (model);
+ if (start_time == end_time)
+ end_time += e_calendar_view_get_time_divisions (cal_view) * 60;
+
/* Set the selection. */
start_in_grid = e_day_view_convert_time_to_grid_position (day_view,
start_time,
diff --git a/data/org.gnome.evolution.calendar.gschema.xml.in b/data/org.gnome.evolution.calendar.gschema.xml.in
index cc66fbba86..638a528e31 100644
--- a/data/org.gnome.evolution.calendar.gschema.xml.in
+++ b/data/org.gnome.evolution.calendar.gschema.xml.in
@@ -215,6 +215,11 @@
<_summary>Recurrent Events in Italic</_summary>
<_description>Show days with recurrent events in italic font in bottom left calendar</_description>
</key>
+ <key name="search-range-years" type="i">
+ <default>10</default>
+ <_summary>Search range for time-based searching in years</_summary>
+ <_description>How many years can the time-based search go forward or backward from currently selected day when searching for another occurrence; default is ten years</_description>
+ </key>
<key name="selected-calendars" type="as">
<default>[]</default>
<_summary>List of selected calendars</_summary>
diff --git a/modules/calendar/e-cal-shell-settings.c b/modules/calendar/e-cal-shell-settings.c
index 392bb841cb..045ca28f3b 100644
--- a/modules/calendar/e-cal-shell-settings.c
+++ b/modules/calendar/e-cal-shell-settings.c
@@ -624,6 +624,11 @@ e_cal_shell_backend_init_settings (EShell *shell)
"recur-events-italic");
e_shell_settings_install_property_for_key (
+ "cal-search-range-years",
+ CALENDAR_SCHEMA,
+ "search-range-years");
+
+ e_shell_settings_install_property_for_key (
"cal-show-event-end-times",
CALENDAR_SCHEMA,
"show-event-end");
diff --git a/modules/calendar/e-cal-shell-view-actions.c b/modules/calendar/e-cal-shell-view-actions.c
index 956766571a..d73feef25e 100644
--- a/modules/calendar/e-cal-shell-view-actions.c
+++ b/modules/calendar/e-cal-shell-view-actions.c
@@ -421,6 +421,27 @@ action_calendar_rename_cb (GtkAction *action,
}
static void
+action_calendar_search_next_cb (GtkAction *action,
+ ECalShellView *cal_shell_view)
+{
+ e_cal_shell_view_search_events (cal_shell_view, TRUE);
+}
+
+static void
+action_calendar_search_prev_cb (GtkAction *action,
+ ECalShellView *cal_shell_view)
+{
+ e_cal_shell_view_search_events (cal_shell_view, FALSE);
+}
+
+static void
+action_calendar_search_stop_cb (GtkAction *action,
+ ECalShellView *cal_shell_view)
+{
+ e_cal_shell_view_search_stop (cal_shell_view);
+}
+
+static void
action_calendar_select_one_cb (GtkAction *action,
ECalShellView *cal_shell_view)
{
@@ -1407,6 +1428,27 @@ static GtkActionEntry calendar_entries[] = {
N_("Rename the selected calendar"),
G_CALLBACK (action_calendar_rename_cb) },
+ { "calendar-search-next",
+ GTK_STOCK_GO_FORWARD,
+ N_("Find _next"),
+ "<Control><Shift>n",
+ N_("Find next occurrence of the current search string"),
+ G_CALLBACK (action_calendar_search_next_cb) },
+
+ { "calendar-search-prev",
+ GTK_STOCK_GO_BACK,
+ N_("Find _previous"),
+ "<Control><Shift>p",
+ N_("Find previous occurrence of the current search string"),
+ G_CALLBACK (action_calendar_search_prev_cb) },
+
+ { "calendar-search-stop",
+ GTK_STOCK_STOP,
+ N_("Stop _running search"),
+ NULL,
+ N_("Stop currently running search"),
+ G_CALLBACK (action_calendar_search_stop_cb) },
+
{ "calendar-select-one",
"stock_check-filled",
N_("Show _Only This Calendar"),
diff --git a/modules/calendar/e-cal-shell-view-actions.h b/modules/calendar/e-cal-shell-view-actions.h
index fcc77ea011..ef2c520d74 100644
--- a/modules/calendar/e-cal-shell-view-actions.h
+++ b/modules/calendar/e-cal-shell-view-actions.h
@@ -51,6 +51,12 @@
E_SHELL_WINDOW_ACTION ((window), "calendar-refresh")
#define E_SHELL_WINDOW_ACTION_CALENDAR_RENAME(window) \
E_SHELL_WINDOW_ACTION ((window), "calendar-rename")
+#define E_SHELL_WINDOW_ACTION_CALENDAR_SEARCH_PREV(window) \
+ E_SHELL_WINDOW_ACTION ((window), "calendar-search-prev")
+#define E_SHELL_WINDOW_ACTION_CALENDAR_SEARCH_NEXT(window) \
+ E_SHELL_WINDOW_ACTION ((window), "calendar-search-next")
+#define E_SHELL_WINDOW_ACTION_CALENDAR_SEARCH_STOP(window) \
+ E_SHELL_WINDOW_ACTION ((window), "calendar-search-stop")
#define E_SHELL_WINDOW_ACTION_CALENDAR_SELECT_ONE(window) \
E_SHELL_WINDOW_ACTION ((window), "calendar-select-one")
#define E_SHELL_WINDOW_ACTION_CALENDAR_VIEW_DAY(window) \
diff --git a/modules/calendar/e-cal-shell-view-private.c b/modules/calendar/e-cal-shell-view-private.c
index 818ee3047e..fc94a83a21 100644
--- a/modules/calendar/e-cal-shell-view-private.c
+++ b/modules/calendar/e-cal-shell-view-private.c
@@ -687,6 +687,8 @@ e_cal_shell_view_private_dispose (ECalShellView *cal_shell_view)
ECalShellViewPrivate *priv = cal_shell_view->priv;
gint i;
+ e_cal_shell_view_search_stop (cal_shell_view);
+
/* Calling calendar's save state from here,
* because it is too late in its dispose. */
if (priv->cal_shell_content != NULL)
@@ -1159,3 +1161,463 @@ e_cal_shell_view_update_timezone (ECalShellView *cal_shell_view)
g_list_free (clients);
}
+
+static gint
+cal_searching_get_search_range_years (ECalShellView *cal_shell_view)
+{
+ EShellBackend *backend;
+ EShellSettings *shell_settings;
+ gint value;
+
+ backend = e_shell_view_get_shell_backend (E_SHELL_VIEW (cal_shell_view));
+ shell_settings = e_shell_get_shell_settings (e_shell_backend_get_shell (backend));
+
+ value = e_shell_settings_get_int (shell_settings, "cal-search-range-years");
+ if (value <= 0)
+ value = 10;
+
+ return value;
+}
+
+static gint
+cal_time_t_ptr_compare (gconstpointer a,
+ gconstpointer b)
+{
+ const time_t *ta = a, *tb = b;
+
+ return (ta ? *ta : 0) - (tb ? *tb : 0);
+}
+
+static void cal_iterate_searching (ECalShellView *cal_shell_view);
+
+struct GenerateInstancesData
+{
+ ECalClient *client;
+ ECalShellView *cal_shell_view;
+ GCancellable *cancellable;
+};
+
+static void
+cal_searching_instances_done_cb (gpointer user_data)
+{
+ struct GenerateInstancesData *gid = user_data;
+
+ g_return_if_fail (gid != NULL);
+ g_return_if_fail (gid->cal_shell_view != NULL);
+
+ if (!g_cancellable_is_cancelled (gid->cancellable)) {
+ gid->cal_shell_view->priv->search_pending_count--;
+ if (!gid->cal_shell_view->priv->search_pending_count) {
+ gid->cal_shell_view->priv->search_hit_cache =
+ g_slist_sort (gid->cal_shell_view->priv->search_hit_cache, cal_time_t_ptr_compare);
+ cal_iterate_searching (gid->cal_shell_view);
+ }
+ }
+
+ g_object_unref (gid->cancellable);
+ g_free (gid);
+}
+
+static gboolean
+cal_searching_got_instance_cb (ECalComponent *comp,
+ time_t instance_start,
+ time_t instance_end,
+ gpointer user_data)
+{
+ struct GenerateInstancesData *gid = user_data;
+ ECalShellViewPrivate *priv;
+ ECalComponentDateTime dt;
+ time_t *value;
+
+ g_return_val_if_fail (gid != NULL, FALSE);
+
+ if (g_cancellable_is_cancelled (gid->cancellable))
+ return FALSE;
+
+ g_return_val_if_fail (gid->cal_shell_view != NULL, FALSE);
+ g_return_val_if_fail (gid->cal_shell_view->priv != NULL, FALSE);
+
+ e_cal_component_get_dtstart (comp, &dt);
+
+ if (dt.tzid && dt.value) {
+ icaltimezone *zone = NULL;
+ if (!e_cal_client_get_timezone_sync (gid->client, dt.tzid, &zone, gid->cancellable, NULL)) {
+ zone = NULL;
+ }
+
+ if (g_cancellable_is_cancelled (gid->cancellable))
+ return FALSE;
+
+ if (zone)
+ instance_start = icaltime_as_timet_with_zone (*dt.value, zone);
+ }
+
+ e_cal_component_free_datetime (&dt);
+
+ priv = gid->cal_shell_view->priv;
+ value = g_new (time_t, 1);
+ *value = instance_start;
+ if (!g_slist_find_custom (priv->search_hit_cache, value, cal_time_t_ptr_compare))
+ priv->search_hit_cache = g_slist_append (priv->search_hit_cache, value);
+ else
+ g_free (value);
+
+ return TRUE;
+}
+
+static void
+cal_search_get_object_list_cb (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ ECalClient *client = E_CAL_CLIENT (source);
+ ECalShellView *cal_shell_view = user_data;
+ GSList *icalcomps = NULL;
+ GError *error = NULL;
+
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (result != NULL);
+ g_return_if_fail (cal_shell_view != NULL);
+
+ if (!e_cal_client_get_object_list_finish (client, result, &icalcomps, &error) || !icalcomps) {
+ if (g_error_matches (error, E_CLIENT_ERROR, E_CLIENT_ERROR_CANCELLED) ||
+ g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+ g_clear_error (&error);
+ return;
+ }
+
+ g_clear_error (&error);
+ cal_shell_view->priv->search_pending_count--;
+ if (!cal_shell_view->priv->search_pending_count) {
+ cal_shell_view->priv->search_hit_cache =
+ g_slist_sort (cal_shell_view->priv->search_hit_cache, cal_time_t_ptr_compare);
+ cal_iterate_searching (cal_shell_view);
+ }
+ } else {
+ GSList *iter;
+ GCancellable *cancellable;
+ time_t start, end;
+
+ cancellable = e_activity_get_cancellable (cal_shell_view->priv->searching_activity);
+ start = time_add_day (cal_shell_view->priv->search_time, (-1) * cal_shell_view->priv->search_direction);
+ end = cal_shell_view->priv->search_time;
+ if (start > end) {
+ time_t tmp = start;
+ start = end;
+ end = tmp;
+ }
+
+ for (iter = icalcomps; iter; iter = iter->next) {
+ icalcomponent *icalcomp = iter->data;
+ struct GenerateInstancesData *gid = g_new0 (struct GenerateInstancesData, 1);
+
+ gid->client = client;
+ gid->cal_shell_view = cal_shell_view;
+ gid->cancellable = g_object_ref (cancellable);
+
+ e_cal_client_generate_instances_for_object (client, icalcomp, start, end, cancellable,
+ cal_searching_got_instance_cb, gid, cal_searching_instances_done_cb);
+ }
+
+ e_cal_client_free_icalcomp_slist (icalcomps);
+ }
+}
+
+static gboolean
+cal_searching_check_candidates (ECalShellView *cal_shell_view)
+{
+ ECalShellContent *cal_shell_content;
+ GnomeCalendarViewType view_type;
+ ECalendarView *calendar_view;
+ GnomeCalendar *calendar;
+ GSList *iter;
+ time_t value, candidate = -1;
+
+ g_return_val_if_fail (cal_shell_view != NULL, FALSE);
+ g_return_val_if_fail (cal_shell_view->priv != NULL, FALSE);
+
+ cal_shell_content = cal_shell_view->priv->cal_shell_content;
+ calendar = e_cal_shell_content_get_calendar (cal_shell_content);
+ view_type = gnome_calendar_get_view (calendar);
+ calendar_view = gnome_calendar_get_calendar_view (calendar, view_type);
+
+ if (!e_calendar_view_get_selected_time_range (calendar_view, &value, NULL))
+ return FALSE;
+
+ if (cal_shell_view->priv->search_direction > 0 && (view_type == GNOME_CAL_WEEK_VIEW || view_type == GNOME_CAL_MONTH_VIEW))
+ value = time_add_day (value, 1);
+
+ for (iter = cal_shell_view->priv->search_hit_cache; iter; iter = iter->next) {
+ time_t cache = *((time_t *) iter->data);
+
+ /* list is sorted, once the search iteration is complete */
+ if (cache > value) {
+ if (cal_shell_view->priv->search_direction > 0)
+ candidate = cache;
+ break;
+ } else if (cal_shell_view->priv->search_direction < 0 && cache != value)
+ candidate = cache;
+ }
+
+ if (candidate > 0) {
+ gnome_calendar_goto (calendar, candidate);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+cal_searching_update_alert (ECalShellView *cal_shell_view,
+ const gchar *message)
+{
+ ECalShellViewPrivate *priv;
+ EShellContent *shell_content;
+ EAlert *alert;
+
+ g_return_if_fail (cal_shell_view != NULL);
+ g_return_if_fail (cal_shell_view->priv != NULL);
+
+ priv = cal_shell_view->priv;
+
+ if (priv->search_alert) {
+ e_alert_response (priv->search_alert, e_alert_get_default_response (priv->search_alert));
+ priv->search_alert = NULL;
+ }
+
+ if (!message)
+ return;
+
+ alert = e_alert_new ("calendar:search-error-generic", message, NULL);
+ g_return_if_fail (alert != NULL);
+
+ priv->search_alert = alert;
+ g_object_add_weak_pointer (G_OBJECT (alert), &priv->search_alert);
+ e_alert_start_timer (priv->search_alert, 5);
+
+ shell_content = e_shell_view_get_shell_content (E_SHELL_VIEW (cal_shell_view));
+ e_alert_sink_submit_alert (E_ALERT_SINK (shell_content), priv->search_alert);
+ g_object_unref (priv->search_alert);
+}
+
+static void
+cal_iterate_searching (ECalShellView *cal_shell_view)
+{
+ ECalShellViewPrivate *priv;
+ GList *clients, *iter;
+ ECalModel *model;
+ time_t new_time, range1, range2;
+ icaltimezone *timezone;
+ const gchar *default_tzloc = NULL;
+ GCancellable *cancellable;
+ gchar *sexp, *start, *end;
+
+ g_return_if_fail (cal_shell_view != NULL);
+ g_return_if_fail (cal_shell_view->priv != NULL);
+
+ priv = cal_shell_view->priv;
+ g_return_if_fail (priv->search_direction != 0);
+ g_return_if_fail (priv->search_pending_count == 0);
+
+ cal_searching_update_alert (cal_shell_view, NULL);
+
+ if (cal_searching_check_candidates (cal_shell_view)) {
+ if (priv->searching_activity) {
+ e_activity_set_state (priv->searching_activity, E_ACTIVITY_COMPLETED);
+ g_object_unref (priv->searching_activity);
+ priv->searching_activity = NULL;
+ }
+
+ return;
+ }
+
+ if (!priv->searching_activity) {
+ EShellBackend *shell_backend = e_shell_view_get_shell_backend (E_SHELL_VIEW (cal_shell_view));
+
+ cancellable = g_cancellable_new ();
+ priv->searching_activity = e_activity_new ();
+ e_activity_set_cancellable (priv->searching_activity, cancellable);
+ e_activity_set_state (priv->searching_activity, E_ACTIVITY_RUNNING);
+ e_activity_set_text (priv->searching_activity,
+ priv->search_direction > 0 ?
+ _("Searching next matching event") :
+ _("Searching previous matching event"));
+
+ e_shell_backend_add_activity (shell_backend, priv->searching_activity);
+ }
+
+ new_time = time_add_day (priv->search_time, priv->search_direction);
+ if (new_time > priv->search_max_time || new_time < priv->search_min_time) {
+ gchar *alert_msg;
+ gint range_years;
+
+ /* would get out of bounds, stop searching */
+ e_activity_set_state (priv->searching_activity, E_ACTIVITY_COMPLETED);
+ g_object_unref (priv->searching_activity);
+ priv->searching_activity = NULL;
+
+ range_years = cal_searching_get_search_range_years (cal_shell_view);
+ alert_msg = g_strdup_printf (
+ priv->search_direction > 0 ?
+ ngettext ("Cannot find matching event in the next %d year",
+ "Cannot find matching event in the next %d years",
+ range_years) :
+ ngettext ("Cannot find matching event in the previous %d year",
+ "Cannot find matching event in the previous %d years",
+ range_years),
+ range_years);
+ cal_searching_update_alert (cal_shell_view, alert_msg);
+ g_free (alert_msg);
+
+ e_shell_view_update_actions (E_SHELL_VIEW (cal_shell_view));
+
+ return;
+ }
+
+ model = gnome_calendar_get_model (
+ e_cal_shell_content_get_calendar (cal_shell_view->priv->cal_shell_content));
+ clients = e_cal_model_get_client_list (model);
+
+ if (!clients) {
+ e_activity_set_state (priv->searching_activity, E_ACTIVITY_COMPLETED);
+ g_object_unref (priv->searching_activity);
+ priv->searching_activity = NULL;
+
+ cal_searching_update_alert (cal_shell_view, _("Cannot search with no active calendar"));
+
+ e_shell_view_update_actions (E_SHELL_VIEW (cal_shell_view));
+
+ return;
+ }
+
+ timezone = e_cal_model_get_timezone (model);
+ range1 = priv->search_time;
+ range2 = time_add_day (range1, priv->search_direction);
+ if (range1 < range2) {
+ start = isodate_from_time_t (time_day_begin (range1));
+ end = isodate_from_time_t (time_day_end (range2));
+ } else {
+ start = isodate_from_time_t (time_day_begin (range2));
+ end = isodate_from_time_t (time_day_end (range1));
+ }
+
+ if (timezone && timezone != icaltimezone_get_utc_timezone ())
+ default_tzloc = icaltimezone_get_location (timezone);
+ if (!default_tzloc)
+ default_tzloc = "";
+
+ sexp = g_strdup_printf (
+ "(and %s (occur-in-time-range? "
+ "(make-time \"%s\") "
+ "(make-time \"%s\") \"%s\"))",
+ e_cal_model_get_search_query (model), start, end, default_tzloc);
+
+ g_free (start);
+ g_free (end);
+
+ cancellable = e_activity_get_cancellable (priv->searching_activity);
+ g_list_foreach (clients, (GFunc) g_object_ref, NULL);
+ priv->search_pending_count = g_list_length (clients);
+ priv->search_time = new_time;
+
+ for (iter = clients; iter; iter = iter->next) {
+ ECalClient *client = iter->data;
+
+ e_cal_client_get_object_list (client, sexp, cancellable, cal_search_get_object_list_cb, cal_shell_view);
+ }
+
+ g_list_free_full (clients, g_object_unref);
+ g_free (sexp);
+}
+
+void
+e_cal_shell_view_search_events (ECalShellView *cal_shell_view,
+ gboolean search_forward)
+{
+ ECalShellViewPrivate *priv = cal_shell_view->priv;
+ ECalShellContent *cal_shell_content;
+ GnomeCalendarViewType view_type;
+ ECalendarView *calendar_view;
+ GnomeCalendar *calendar;
+ time_t start_time = 0;
+ gint range_years;
+
+ if (priv->searching_activity || !priv->search_direction)
+ e_cal_shell_view_search_stop (cal_shell_view);
+
+ cal_shell_content = cal_shell_view->priv->cal_shell_content;
+ calendar = e_cal_shell_content_get_calendar (cal_shell_content);
+ view_type = gnome_calendar_get_view (calendar);
+ calendar_view = gnome_calendar_get_calendar_view (calendar, view_type);
+
+ if (!e_calendar_view_get_selected_time_range (calendar_view, &start_time, NULL)) {
+ e_shell_view_update_actions (E_SHELL_VIEW (cal_shell_view));
+ return;
+ }
+
+ start_time = time_day_begin (start_time);
+ if (priv->search_direction) {
+ time_t cached_start, cached_end, tmp;
+
+ cached_start = priv->search_time;
+ cached_end = time_add_day (cached_start, (-1) * priv->search_direction);
+
+ if (priv->search_direction > 0) {
+ tmp = cached_start;
+ cached_start = cached_end;
+ cached_end = tmp;
+ }
+
+ /* clear cached results if searching out of cached bounds */
+ if (start_time < cached_start || start_time > cached_end)
+ e_cal_shell_view_search_stop (cal_shell_view);
+ }
+
+ priv->search_direction = search_forward ? +30 : -30;
+
+ if (cal_searching_check_candidates (cal_shell_view))
+ return;
+
+ range_years = cal_searching_get_search_range_years (cal_shell_view);
+
+ priv->search_pending_count = 0;
+ priv->search_time = start_time;
+ priv->search_min_time = start_time - (range_years * 365 * 24 * 60 * 60);
+ priv->search_max_time = start_time + (range_years * 365 * 24 * 60 * 60);
+
+ if (priv->search_min_time < 0)
+ priv->search_min_time = 0;
+ if (priv->search_hit_cache) {
+ g_slist_free_full (priv->search_hit_cache, g_free);
+ priv->search_hit_cache = NULL;
+ }
+
+ cal_iterate_searching (cal_shell_view);
+}
+
+void
+e_cal_shell_view_search_stop (ECalShellView *cal_shell_view)
+{
+ ECalShellViewPrivate *priv;
+
+ g_return_if_fail (cal_shell_view != NULL);
+ g_return_if_fail (cal_shell_view->priv != NULL);
+
+ priv = cal_shell_view->priv;
+
+ cal_searching_update_alert (cal_shell_view, NULL);
+
+ if (priv->searching_activity) {
+ g_cancellable_cancel (e_activity_get_cancellable (priv->searching_activity));
+ e_activity_set_state (priv->searching_activity, E_ACTIVITY_CANCELLED);
+ g_object_unref (priv->searching_activity);
+ priv->searching_activity = NULL;
+ }
+
+ if (priv->search_hit_cache) {
+ g_slist_free_full (priv->search_hit_cache, g_free);
+ priv->search_hit_cache = NULL;
+ }
+
+ priv->search_direction = 0;
+}
diff --git a/modules/calendar/e-cal-shell-view-private.h b/modules/calendar/e-cal-shell-view-private.h
index ad4984a4ef..4fc5e24724 100644
--- a/modules/calendar/e-cal-shell-view-private.h
+++ b/modules/calendar/e-cal-shell-view-private.h
@@ -122,6 +122,15 @@ struct _ECalShellViewPrivate {
EActivity *memopad_activity;
EActivity *taskpad_activity;
+ /* Time-range searching */
+ EActivity *searching_activity;
+ gpointer search_alert; /* weak pointer to EAlert * */
+ gint search_pending_count; /* how many clients are pending */
+ time_t search_time; /* current search time from */
+ time_t search_min_time, search_max_time; /* time boundary for searching */
+ gint search_direction; /* negative value is backward, positive is forward, zero is error; in days */
+ GSList *search_hit_cache; /* pointers on time_t for matched events */
+
GFileMonitor *monitors[CHECK_NB];
};
@@ -159,6 +168,11 @@ void e_cal_shell_view_update_search_filter
(ECalShellView *cal_shell_view);
void e_cal_shell_view_update_timezone
(ECalShellView *cal_shell_view);
+void e_cal_shell_view_search_events
+ (ECalShellView *cal_shell_view,
+ gboolean search_forward);
+void e_cal_shell_view_search_stop
+ (ECalShellView *cal_shell_view);
/* Memo Pad Utilities */
diff --git a/modules/calendar/e-cal-shell-view.c b/modules/calendar/e-cal-shell-view.c
index ad3477c5ea..9554f7440d 100644
--- a/modules/calendar/e-cal-shell-view.c
+++ b/modules/calendar/e-cal-shell-view.c
@@ -81,6 +81,8 @@ cal_shell_view_execute_search (EShellView *shell_view)
gchar *temp;
gint value;
+ e_cal_shell_view_search_stop (E_CAL_SHELL_VIEW (shell_view));
+
shell_window = e_shell_view_get_shell_window (shell_view);
shell_content = e_shell_view_get_shell_content (shell_view);
shell_sidebar = e_shell_view_get_shell_sidebar (shell_view);
@@ -239,6 +241,9 @@ cal_shell_view_execute_search (EShellView *shell_view)
gnome_calendar_set_search_query (
calendar, query, range_search, start_range, end_range);
g_free (query);
+
+ /* update also actions, thus Find Prev/Next/Stop will be sensitive as expected */
+ e_shell_view_update_actions (shell_view);
}
static icalproperty *
@@ -318,9 +323,12 @@ cal_shell_view_update_actions (EShellView *shell_view)
EShell *shell;
GnomeCalendarViewType view_type;
GnomeCalendar *calendar;
+ ECalModel *model;
ECalendarView *view;
GtkAction *action;
GList *list, *iter;
+ const gchar *model_sexp;
+ gboolean is_searching;
gboolean sensitive;
gboolean visible;
guint32 state;
@@ -364,6 +372,11 @@ cal_shell_view_update_actions (EShellView *shell_view)
calendar = e_cal_shell_content_get_calendar (cal_shell_content);
view_type = gnome_calendar_get_view (calendar);
view = gnome_calendar_get_calendar_view (calendar, view_type);
+ model = gnome_calendar_get_model (calendar);
+ model_sexp = e_cal_model_get_search_query (model);
+ is_searching = model_sexp && *model_sexp &&
+ g_strcmp0 (model_sexp, "#t") != 0 &&
+ g_strcmp0 (model_sexp, "(contains? \"summary\" \"\")") != 0;
list = e_calendar_view_get_selected_events (view);
n_selected = g_list_length (list);
@@ -452,6 +465,15 @@ cal_shell_view_update_actions (EShellView *shell_view)
sensitive = can_delete_primary_source;
gtk_action_set_sensitive (action, sensitive);
+ action = ACTION (CALENDAR_SEARCH_PREV);
+ gtk_action_set_sensitive (action, is_searching);
+
+ action = ACTION (CALENDAR_SEARCH_NEXT);
+ gtk_action_set_sensitive (action, is_searching);
+
+ action = ACTION (CALENDAR_SEARCH_STOP);
+ gtk_action_set_sensitive (action, is_searching && priv->searching_activity != NULL);
+
action = ACTION (EVENT_DELEGATE);
sensitive =
(n_selected == 1) && editable &&
@@ -511,7 +533,7 @@ cal_shell_view_update_actions (EShellView *shell_view)
static void
cal_shell_view_class_init (ECalShellViewClass *class,
- GTypeModule *type_module)
+ GTypeModule *type_module)
{
GObjectClass *object_class;
EShellViewClass *shell_view_class;
diff --git a/ui/evolution-calendars.ui b/ui/evolution-calendars.ui
index 496971bdba..70cb095569 100644
--- a/ui/evolution-calendars.ui
+++ b/ui/evolution-calendars.ui
@@ -31,6 +31,15 @@
<menuitem action='calendar-purge'/>
</menu>
</placeholder>
+ <menu action='search-menu'>
+ <placeholder name='search-extra-actions'>
+ <separator/>
+ <menuitem action='calendar-search-prev'/>
+ <menuitem action='calendar-search-next'/>
+ <menuitem action='calendar-search-stop'/>
+ <separator/>
+ </placeholder>
+ </menu>
</menubar>
<toolbar name='main-toolbar'>
#if !EXPRESS
diff --git a/ui/evolution-shell.ui b/ui/evolution-shell.ui
index fd90ba8f66..ae7ce84eb3 100644
--- a/ui/evolution-shell.ui
+++ b/ui/evolution-shell.ui
@@ -70,6 +70,7 @@
<menu action='search-menu'>
<menuitem action='search-quick'/>
<menuitem action='search-clear'/>
+ <placeholder name='search-extra-actions'/>
<menuitem action='search-advanced'/>
<separator/>
<menuitem action='search-save'/>