aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--calendar/ChangeLog26
-rw-r--r--calendar/gui/Makefile.am10
-rw-r--r--calendar/gui/cal-search-bar.c521
-rw-r--r--calendar/gui/cal-search-bar.h8
-rw-r--r--calendar/gui/caltypes.xml278
-rw-r--r--calendar/gui/e-cal-model.c31
-rw-r--r--calendar/gui/e-cal-model.h1
-rw-r--r--calendar/gui/gnome-cal.c67
-rw-r--r--calendar/gui/memotypes.xml233
-rw-r--r--calendar/gui/tasktypes.xml311
10 files changed, 1377 insertions, 109 deletions
diff --git a/calendar/ChangeLog b/calendar/ChangeLog
index 174e5ebe16..81e6778494 100644
--- a/calendar/ChangeLog
+++ b/calendar/ChangeLog
@@ -1,3 +1,29 @@
+2007-06-04 Chenthill Palanisamy <pchenthill@novell.com>
+
+ * gui/Makefile.am: Added the filter flags and the new files.
+ * gui/cal-search-bar.c: (cal_search_bar_class_init),
+ (cal_search_bar_init), (cal_search_bar_destroy),
+ (get_current_category), (get_show_option_sexp),
+ (notify_e_cal_view_contains), (notify_category_is), (regen_query),
+ (setup_category_options), (make_suboptions),
+ (search_menu_activated), (cal_search_bar_construct),
+ (cal_search_bar_get_category), (cal_search_bar_get_time_range):
+ * gui/cal-search-bar.h:
+ * gui/e-cal-model.[ch]:
+ (e_cal_model_set_search_query_with_time_range): Set the time range
+ and the search query.
+ * gui/gnome-cal.c: (set_search_query),
+ (search_bar_sexp_changed_cb), (update_memo_view),
+ (gnome_calendar_init), (update_view_times), (display_view),
+ (display_view_cb), (gnome_calendar_update_date_navigator): Hide
+ the date navigator in list view for searches based on date.
+ * gui/caltypes.xml:
+ * gui/memotypes.xml:
+ * gui/tasktypes.xml: Added the Advanced search options.
+
+ Committing on behalf of Keshav Upadhyaya <ukeshav@novell.com> and
+ Abhishek Parwal <pabhishek@novell.com>.
+
2007-06-03 Srinivasa Ragavan <sragavan@novell.com>
** Fix for bug #386503 from Matthew Barnes
diff --git a/calendar/gui/Makefile.am b/calendar/gui/Makefile.am
index efb573ebce..2fa778b85c 100644
--- a/calendar/gui/Makefile.am
+++ b/calendar/gui/Makefile.am
@@ -51,6 +51,11 @@ ecalendarincludedir = $(privincludedir)/calendar/gui
ecalendarinclude_HEADERS = \
e-cal-config.h
+search_files = tasktypes.xml memotypes.xml caltypes.xml
+
+ruledir = $(privdatadir)
+rule_DATA = $(search_files)
+
INCLUDES = \
-DG_LOG_DOMAIN=\"calendar-gui\" \
-I$(top_builddir)/shell \
@@ -60,6 +65,7 @@ INCLUDES = \
-I$(top_srcdir)/widgets \
-I$(top_srcdir)/widgets/misc \
-I$(top_srcdir)/a11y/calendar \
+ -DSEARCH_RULE_DIR=\"$(ruledir)\" \
-DEVOLUTION_GLADEDIR=\""$(gladedir)"\" \
-DEVOLUTION_ETSPECDIR=\""$(etspecdir)"\" \
-DEVOLUTION_GALVIEWSDIR=\""$(viewsdir)"\" \
@@ -235,6 +241,7 @@ libevolution_calendar_la_LIBADD = \
$(top_builddir)/calendar/importers/libevolution-calendar-importers.la \
$(top_builddir)/widgets/e-timezone-dialog/libetimezonedialog.la \
$(top_builddir)/widgets/misc/libemiscwidgets.la \
+ $(top_builddir)/filter/libfilter.la \
$(top_builddir)/e-util/libeutil.la \
$(top_builddir)/a11y/calendar/libevolution-calendar-a11y.la \
$(LIBSOUP_LIBS) \
@@ -261,7 +268,8 @@ EXTRA_DIST = \
$(glade_DATA) \
$(schema_in_files) \
$(etspec_DATA) \
- $(server_in_files)
+ $(server_in_files) \
+ $(search_files)
BUILT_SOURCES = $(IDL_GENERATED) $(server_DATA)
CLEANFILES = $(BUILT_SOURCES)
diff --git a/calendar/gui/cal-search-bar.c b/calendar/gui/cal-search-bar.c
index 7b2efc5de2..75e0d819ad 100644
--- a/calendar/gui/cal-search-bar.c
+++ b/calendar/gui/cal-search-bar.c
@@ -31,23 +31,39 @@
#include <gtk/gtksignal.h>
#include <glib/gi18n.h>
#include <libedataserver/e-categories.h>
+#include <libecal/e-cal-time-util.h>
#include <e-util/e-icon-factory.h>
#include <libedataserver/e-categories.h>
+#include <filter/rule-editor.h>
#include "cal-search-bar.h"
+#include "e-util/e-error.h"
+#include "e-util/e-util-private.h"
+
typedef struct CALSearchBarItem {
ESearchBarItem search;
- char *image;
-}CALSearchBarItem;
+ const char *image;
+} CALSearchBarItem;
+
+static ESearchBarItem calendar_search_items[] = {
+ E_FILTERBAR_ADVANCED,
+ {NULL, 0, 0},
+ E_FILTERBAR_SAVE,
+ E_FILTERBAR_EDIT,
+ {NULL, -1, 0}
+};
+
/* IDs and option items for the ESearchBar */
enum {
SEARCH_SUMMARY_CONTAINS,
SEARCH_DESCRIPTION_CONTAINS,
+ SEARCH_ANY_FIELD_CONTAINS,
SEARCH_CATEGORY_IS,
SEARCH_COMMENT_CONTAINS,
SEARCH_LOCATION_CONTAINS,
- SEARCH_ANY_FIELD_CONTAINS
+ SEARCH_ATTENDEE_CONTAINS
+
};
/* Comments are disabled because they are kind of useless right now, see bug 33247 */
@@ -61,14 +77,44 @@ static ESearchBarItem search_option_items[] = {
};
/* IDs for the categories suboptions */
-#define CATEGORIES_ALL 0
-#define CATEGORIES_UNMATCHED 1
-#define CATEGORIES_OFFSET 3
+
+typedef enum {
+ CATEGORIES_ALL,
+ CATEGORIES_UNMATCHED,
+ LAST_FIELD
+} common_search_options;
+
+typedef enum {
+ N_DAY_TASK = LAST_FIELD,
+ ACTIVE_TASK,
+ OVERDUE_TASK,
+ COMPLETED_TASK,
+ TASK_WITH_ATTACHMENT,
+ TASK_LAST_FIELD
+} task_search_options;
+
+typedef enum {
+ ACTIVE_APPONTMENT = LAST_FIELD,
+ N_DAY_APPOINTMENT,
+ CAL_LAST_FIELD
+} cal_search_options;
+
+/* We add 2 to the offset to include the separators used to differenciate the quick search queries. */
+#define CATEGORIES_TASKS_OFFSET (TASK_LAST_FIELD + 2)
+#define CATEGORIES_MEMOS_OFFSET (LAST_FIELD + 1)
+#define CATEGORIES_CALENDAR_OFFSET (CAL_LAST_FIELD + 2)
/* Private part of the CalSearchBar structure */
struct CalSearchBarPrivate {
/* Array of categories */
GPtrArray *categories;
+
+ RuleContext *search_context;
+ FilterRule *search_rule;
+ guint32 view_flag;
+
+ time_t start;
+ time_t end;
};
static void cal_search_bar_destroy (GtkObject *object);
@@ -84,16 +130,17 @@ enum {
static guint cal_search_bar_signals[LAST_SIGNAL] = { 0 };
-G_DEFINE_TYPE (CalSearchBar, cal_search_bar, E_SEARCH_BAR_TYPE)
+
+G_DEFINE_TYPE (CalSearchBar, cal_search_bar, E_FILTER_BAR_TYPE)
/* Class initialization function for the calendar search bar */
static void
cal_search_bar_class_init (CalSearchBarClass *class)
{
- ESearchBarClass *e_search_bar_class;
- GtkObjectClass *object_class;
- e_search_bar_class = (ESearchBarClass *) class;
+ EFilterBarClass *e_search_bar_class;
+ GtkObjectClass *object_class;
+ e_search_bar_class = (EFilterBarClass *) class;
object_class = (GtkObjectClass *) class;
cal_search_bar_signals[SEXP_CHANGED] =
@@ -116,9 +163,7 @@ cal_search_bar_class_init (CalSearchBarClass *class)
class->sexp_changed = NULL;
class->category_changed = NULL;
-
- e_search_bar_class->search_activated = cal_search_bar_search_activated;
-
+ ((ESearchBarClass *) e_search_bar_class)->search_activated = cal_search_bar_search_activated;
object_class->destroy = cal_search_bar_destroy;
}
@@ -133,6 +178,9 @@ cal_search_bar_init (CalSearchBar *cal_search)
priv->categories = g_ptr_array_new ();
g_ptr_array_set_size (priv->categories, 0);
+
+ priv->start = -1;
+ priv->end = -1;
}
/* Frees an array of categories */
@@ -168,6 +216,17 @@ cal_search_bar_destroy (GtkObject *object)
priv->categories = NULL;
}
+ if (priv->search_rule) {
+ g_object_unref (priv->search_rule);
+ priv->search_rule = NULL;
+ }
+
+ /* FIXME
+ if (priv->search_context) {
+ g_object_unref (priv->search_context);
+ priv->search_context = NULL;
+ }*/
+
g_free (priv);
cal_search->priv = NULL;
}
@@ -186,14 +245,13 @@ notify_sexp_changed (CalSearchBar *cal_search, const char *sexp)
sexp);
}
-/* Returns the string of the currently selected category, NULL for "Unmatched",
- * or (const char *) 1 for "All".
- */
+/* Returns the string of the currently selected category, NULL for "Unmatched" and "All
+*/
static const char *
get_current_category (CalSearchBar *cal_search)
{
CalSearchBarPrivate *priv;
- gint viewid;
+ gint viewid, i;
priv = cal_search->priv;
@@ -201,18 +259,20 @@ get_current_category (CalSearchBar *cal_search)
viewid = e_search_bar_get_viewitem_id (E_SEARCH_BAR (cal_search));
- if (viewid == CATEGORIES_ALL)
- return (const char *) 1;
- else if (viewid == CATEGORIES_UNMATCHED)
+ if (viewid == CATEGORIES_ALL || viewid == CATEGORIES_UNMATCHED)
return NULL;
- else {
- int i;
-
- i = viewid - CATEGORIES_OFFSET;
- g_assert (i >= 0 && i < priv->categories->len);
+ if (priv->view_flag == CAL_SEARCH_TASKS_DEFAULT)
+ i = viewid - CATEGORIES_TASKS_OFFSET;
+ else if (priv->view_flag == CAL_SEARCH_MEMOS_DEFAULT)
+ i = viewid - CATEGORIES_MEMOS_OFFSET;
+ else if (priv->view_flag == CAL_SEARCH_CALENDAR_DEFAULT)
+ i = viewid - CATEGORIES_CALENDAR_OFFSET;
+
+ if (i >= 0 && i < priv->categories->len)
return priv->categories->pdata[i];
- }
+ else
+ return NULL;
}
@@ -221,22 +281,123 @@ get_current_category (CalSearchBar *cal_search)
* as NULL.
*/
static char *
-get_category_sexp (CalSearchBar *cal_search)
+get_show_option_sexp (CalSearchBar *cal_search)
{
- const char *category;
+ CalSearchBarPrivate *priv ;
+ gint viewid ;
+ char *start, *end, *due, *ret = NULL;
+ const char *category = NULL ;
+ time_t start_range, end_range;
- category = get_current_category (cal_search);
+ priv = cal_search->priv;
+ viewid = e_search_bar_get_viewitem_id (E_SEARCH_BAR (cal_search));
- if (category == NULL)
+ if (viewid == CATEGORIES_UNMATCHED)
return g_strdup ("(has-categories? #f)"); /* Unfiled items */
- else if (category == (const char *) 1) {
+ else if (viewid == CATEGORIES_ALL)
return NULL; /* All items */
+
+ switch (priv->view_flag) {
+ case CAL_SEARCH_TASKS_DEFAULT:
+ if (viewid == N_DAY_TASK) {
+ start_range = time(NULL);
+ end_range = time_add_day(start_range, 7);
+ start = isodate_from_time_t (start_range);
+ due = isodate_from_time_t (end_range);
+
+ ret = g_strdup_printf ("(due-in-time-range? (make-time \"%s\")"
+ " (make-time \"%s\"))",
+ start, due);
+
+ g_free (start);
+ g_free (due);
+
+ return ret;
+ } else if (viewid == ACTIVE_TASK) {
+ /* Shows the tasks due for an year from now which are not completed yet*/
+ start_range = time(NULL);
+ end_range = time_add_day(start_range, 365);
+ start = isodate_from_time_t (start_range);
+ due = isodate_from_time_t (end_range);
+
+ ret = g_strdup_printf ("(and (due-in-time-range? (make-time \"%s\")"
+ " (make-time \"%s\")) (not (is-completed?)))",
+ start, due);
+
+ g_free (start);
+ g_free (due);
+
+ return ret;
+ } else if (viewid == OVERDUE_TASK) {
+ /* Shows the tasks which are overdue from lower limit 1970 to the current time */
+ start_range = 0;
+ end_range = time (NULL);
+ start = isodate_from_time_t (start_range);
+ due = isodate_from_time_t (end_range);
+
+ ret = g_strdup_printf ("(and (due-in-time-range? (make-time \"%s\")"
+ " (make-time \"%s\")) (not (is-completed?)))",
+ start, due);
+
+ g_free (start);
+ g_free (due);
+
+ return ret;
+ } else if (viewid == COMPLETED_TASK)
+ return g_strdup ("(is-completed?)");
+ else if (viewid == TASK_WITH_ATTACHMENT)
+ return g_strdup ("(has-attachments?)");
+ break;
+ case CAL_SEARCH_CALENDAR_DEFAULT:
+ if (viewid == ACTIVE_APPONTMENT) {
+ /* Shows next one year's Appointments */
+ start_range = time (NULL);
+ end_range = time_add_day (start_range, 365);
+ start = isodate_from_time_t (start_range);
+ end = isodate_from_time_t (end_range);
+
+ ret = g_strdup_printf ("(occur-in-time-range? (make-time \"%s\")"
+ " (make-time \"%s\"))",
+ start, end);
+
+ cal_search->priv->start = start_range;
+ cal_search->priv->end = end_range;
+
+ g_free (start);
+ g_free (end);
+
+ return ret;
+ } else if (viewid == N_DAY_APPOINTMENT) {
+ start_range = time (NULL);
+ end_range = time_add_day (start_range, 7);
+ start = isodate_from_time_t (start_range);
+ end = isodate_from_time_t (end_range);
+
+ ret = g_strdup_printf ("(occur-in-time-range? (make-time \"%s\")"
+ " (make-time \"%s\"))",
+ start, end);
+
+ cal_search->priv->start = start_range;
+ cal_search->priv->end = end_range;
+
+ g_free (start);
+ g_free (end);
+
+ return ret;
+ }
+ break;
+ default:
+ break;
}
+
+ category = get_current_category (cal_search);
+
+ if (category != NULL)
+ return g_strdup_printf ("(has-categories? \"%s\")", category);
else
- return g_strdup_printf ("(has-categories? \"%s\")", category); /* Specific category */
+ return NULL;
}
-
/* Sets the query string to be (contains? "field" "text") */
static void
notify_e_cal_view_contains (CalSearchBar *cal_search, const char *field, const char *view)
@@ -257,11 +418,12 @@ notify_e_cal_view_contains (CalSearchBar *cal_search, const char *field, const c
/* Apply the selected view on search */
- view = get_category_sexp (cal_search);
- if (view && *view)
+ if (view && *view){
sexp = g_strconcat ("(and ",sexp, view, ")", NULL);
-
+ }
+
notify_sexp_changed (cal_search, sexp);
+
g_free (sexp);
}
@@ -272,7 +434,7 @@ notify_category_is (CalSearchBar *cal_search)
{
char *sexp;
- sexp = get_category_sexp (cal_search);
+ sexp = get_show_option_sexp (cal_search);
if (!sexp)
notify_sexp_changed (cal_search, "#t"); /* Match all */
@@ -289,39 +451,62 @@ static void
regen_query (CalSearchBar *cal_search)
{
int id;
- const char *category_sexp;
+ char *show_option_sexp = NULL;
+ char *sexp = NULL;
+ GString *out = NULL;
+ EFilterBar *efb = (EFilterBar *) cal_search;
/* Fetch the data from the ESearchBar's entry widgets */
id = e_search_bar_get_item_id (E_SEARCH_BAR (cal_search));
+ cal_search->priv->start = -1;
+ cal_search->priv->end = -1;
+
/* Get the selected view */
- category_sexp = get_category_sexp (cal_search);
+ show_option_sexp = get_show_option_sexp (cal_search);
/* Generate the different types of queries */
switch (id) {
case SEARCH_ANY_FIELD_CONTAINS:
- notify_e_cal_view_contains (cal_search, "any", category_sexp);
+ notify_e_cal_view_contains (cal_search, "any", show_option_sexp);
break;
case SEARCH_SUMMARY_CONTAINS:
- notify_e_cal_view_contains (cal_search, "summary", category_sexp);
+ notify_e_cal_view_contains (cal_search, "summary", show_option_sexp);
break;
case SEARCH_DESCRIPTION_CONTAINS:
- notify_e_cal_view_contains (cal_search, "description", category_sexp);
+ notify_e_cal_view_contains (cal_search, "description", show_option_sexp);
break;
case SEARCH_COMMENT_CONTAINS:
- notify_e_cal_view_contains (cal_search, "comment", category_sexp);
+ notify_e_cal_view_contains (cal_search, "comment", show_option_sexp);
break;
case SEARCH_LOCATION_CONTAINS:
- notify_e_cal_view_contains (cal_search, "location", category_sexp);
+ notify_e_cal_view_contains (cal_search, "location", show_option_sexp);
+ break;
+ case SEARCH_ATTENDEE_CONTAINS:
+ notify_e_cal_view_contains (cal_search, "attendee", show_option_sexp);
+ break;
+ case E_FILTERBAR_ADVANCED_ID:
+ out = g_string_new ("");
+ filter_rule_build_code (efb->current_query, out);
+
+ if (show_option_sexp && *show_option_sexp)
+ sexp = g_strconcat ("(and ", out->str, show_option_sexp, ")", NULL);
+
+ notify_sexp_changed (cal_search, sexp ? sexp : out->str);
+
+ g_string_free (out, TRUE);
+ g_free(sexp);
break;
default:
g_assert_not_reached ();
}
+
+ g_free (show_option_sexp);
}
#if 0
@@ -407,13 +592,44 @@ generate_viewoption_menu (CALSearchBarItem *subitems)
return menu;
}
+static void
+setup_category_options (CalSearchBar *cal_search, CALSearchBarItem *subitems, gint index, gint offset)
+{
+ CalSearchBarPrivate *priv;
+ gint i;
+
+ priv = cal_search->priv;
+
+ if (priv->categories->len > 0) {
+ subitems[index].search.text = NULL; /* separator */
+ subitems[index].search.id = 0;
+ subitems[index].image = NULL;
+
+ for (i = 0; i < priv->categories->len; i++) {
+ const char *category;
+
+ category = priv->categories->pdata[i] ? priv->categories->pdata [i] : "";
+
+ /* The search.text field should not be free'd */
+ subitems[i + offset].search.text = (char *) category;
+ subitems[i + offset].search.id = i + offset;
+ subitems[i + offset].image = e_categories_get_icon_file_for (category);
+ }
+ index = i + offset;
+ }
+
+ subitems[index].search.id = -1; /* terminator */
+ subitems[index].search.text = NULL;
+ subitems[index].image = NULL;
+}
+
+
/* Creates the suboptions menu for the ESearchBar with the list of categories */
static void
make_suboptions (CalSearchBar *cal_search)
{
CalSearchBarPrivate *priv;
- CALSearchBarItem *subitems;
- int i;
+ CALSearchBarItem *subitems = NULL;
GtkWidget *menu;
priv = cal_search->priv;
@@ -421,56 +637,110 @@ make_suboptions (CalSearchBar *cal_search)
g_assert (priv->categories != NULL);
/* Categories plus "all", "unmatched", separator, terminator */
- subitems = g_new (CALSearchBarItem, priv->categories->len + 3 + 1);
/* All, unmatched, separator */
- subitems[0].search.text = _("Any Category");
- subitems[0].search.id = CATEGORIES_ALL;
- subitems[0].image = NULL;
+ if (priv->view_flag == CAL_SEARCH_TASKS_DEFAULT) {
+ subitems = g_new (CALSearchBarItem, priv->categories->len + CATEGORIES_TASKS_OFFSET + 1);
- subitems[1].search.text = _("Unmatched");
- subitems[1].search.id = CATEGORIES_UNMATCHED;
- subitems[1].image = NULL;
-
- /* All the other items */
+ subitems[0].search.text = _("Any Category");
+ subitems[0].search.id = CATEGORIES_ALL;
+ subitems[0].image = NULL;
- if (priv->categories->len > 0) {
- subitems[2].search.text = NULL; /* separator */
- subitems[2].search.id = 0;
- subitems[2].image = 0;
-
- for (i = 0; i < priv->categories->len; i++) {
- const char *category;
- char *str;
-
- category = priv->categories->pdata[i];
- str = g_strdup (category ? category : "");
-
- subitems[i + CATEGORIES_OFFSET].search.text = str;
- subitems[i + CATEGORIES_OFFSET].search.id = i + CATEGORIES_OFFSET;
- subitems[i + CATEGORIES_OFFSET].image = g_strdup (e_categories_get_icon_file_for(str));
- }
-
- subitems[i + CATEGORIES_OFFSET].search.id = -1; /* terminator */
- subitems[2].search.text = NULL;
- subitems[2].image = NULL;
- } else {
-
- subitems[2].search.id = -1; /* terminator */
- subitems[2].search.text = NULL;
- subitems[2].image = NULL;
- }
-
- menu = generate_viewoption_menu (subitems);
- e_search_bar_set_viewoption_menu ((ESearchBar *)cal_search, menu);
-
- /* Free the strings */
- for (i = 0; i < priv->categories->len; i++) {
- g_free (subitems[i + CATEGORIES_OFFSET].search.text);
- g_free (subitems[i + CATEGORIES_OFFSET].image);
+ subitems[1].search.text = _("Unmatched");
+ subitems[1].search.id = CATEGORIES_UNMATCHED;
+ subitems[1].image = NULL;
+
+ subitems[2].search.text = NULL;
+ subitems[2].search.id = 0;
+ subitems[2].image = 0;
+
+ subitems[3].search.text = _("Next 7 days Tasks");
+ subitems[3].search.id = N_DAY_TASK;
+ subitems[3].image = NULL;
+
+ subitems[4].search.text = _("Active Tasks");
+ subitems[4].search.id = ACTIVE_TASK;
+ subitems[4].image = NULL;
+
+ subitems[5].search.text = _("Over Due Tasks");
+ subitems[5].search.id = OVERDUE_TASK;
+ subitems[5].image = NULL;
+
+ subitems[6].search.text = _("Completed Tasks");
+ subitems[6].search.id = COMPLETED_TASK;
+ subitems[6].image = NULL;
+
+ subitems[7].search.text = _("Tasks With Attachments");
+ subitems[7].search.id = TASK_WITH_ATTACHMENT;
+ subitems[7].image = NULL;
+
+ /* All the other items */
+ setup_category_options (cal_search, subitems, 8, CATEGORIES_TASKS_OFFSET);
+
+ menu = generate_viewoption_menu (subitems);
+ e_search_bar_set_viewoption_menu ((ESearchBar *)cal_search, menu);
+
+ } else if (priv->view_flag == CAL_SEARCH_MEMOS_DEFAULT) {
+ subitems = g_new (CALSearchBarItem, priv->categories->len + CATEGORIES_MEMOS_OFFSET + 1);
+
+ /* All, unmatched, separator */
+
+ subitems[0].search.text = _("Any Category");
+ subitems[0].search.id = CATEGORIES_ALL;
+ subitems[0].image = NULL;
+
+ subitems[1].search.text = _("Unmatched");
+ subitems[1].search.id = CATEGORIES_UNMATCHED;
+ subitems[1].image = NULL;
+
+ /* All the other items */
+ setup_category_options (cal_search, subitems, 2, CATEGORIES_MEMOS_OFFSET);
+
+ menu = generate_viewoption_menu (subitems);
+ e_search_bar_set_viewoption_menu ((ESearchBar *)cal_search, menu);
+
+ } else if (priv->view_flag == CAL_SEARCH_CALENDAR_DEFAULT) {
+ subitems = g_new (CALSearchBarItem, priv->categories->len + CATEGORIES_CALENDAR_OFFSET + 1);
+
+ /* All, unmatched, separator */
+
+ subitems[0].search.text = _("Any Category");
+ subitems[0].search.id = CATEGORIES_ALL;
+ subitems[0].image = NULL;
+
+ subitems[1].search.text = _("Unmatched");
+ subitems[1].search.id = CATEGORIES_UNMATCHED;
+ subitems[1].image = NULL;
+
+ subitems[2].search.text = NULL;
+ subitems[2].search.id = 0;
+ subitems[2].image = 0;
+
+ subitems[3].search.text = _("Active Appointments");
+ subitems[3].search.id = ACTIVE_APPONTMENT;
+ subitems[3].image = NULL;
+
+ subitems[4].search.text = _("Next 7 Day Appointments");
+ subitems[4].search.id = N_DAY_APPOINTMENT;
+ subitems[4].image = NULL;
+
+ /* All the other items */
+ setup_category_options (cal_search, subitems, 5, CATEGORIES_CALENDAR_OFFSET);
+
+ menu = generate_viewoption_menu (subitems);
+ e_search_bar_set_viewoption_menu ((ESearchBar *)cal_search, menu);
}
- g_free (subitems);
+
+ if(subitems != NULL)
+ g_free (subitems);
+}
+
+static void
+search_menu_activated (ESearchBar *esb, int id)
+{
+ if (id == E_FILTERBAR_ADVANCED_ID)
+ e_search_bar_set_item_id (esb, id);
}
/**
@@ -488,6 +758,11 @@ cal_search_bar_construct (CalSearchBar *cal_search, guint32 flags)
ESearchBarItem *items;
guint32 bit = 0x1;
int i, j;
+ char *xmlfile = NULL;
+ char *userfile = NULL;
+ FilterPart *part;
+ RuleContext *search_context;
+ FilterRule *search_rule;
g_return_val_if_fail (IS_CAL_SEARCH_BAR (cal_search), NULL);
@@ -503,10 +778,51 @@ cal_search_bar_construct (CalSearchBar *cal_search, guint32 flags)
items[j].text = NULL;
items[j].id = -1;
+ search_context = rule_context_new ();
+ cal_search->priv->view_flag = flags;
+
+ rule_context_add_part_set (search_context, "partset", filter_part_get_type (),
+ rule_context_add_part, rule_context_next_part);
+ rule_context_add_rule_set (search_context, "ruleset", filter_rule_get_type (),
+ rule_context_add_rule, rule_context_next_rule);
+
+ if (flags == CAL_SEARCH_MEMOS_DEFAULT) {
+ userfile = g_build_filename (g_get_home_dir (), ".evolution/memos/searches.xml", NULL);
+ xmlfile = g_build_filename (SEARCH_RULE_DIR, "memotypes.xml", NULL);
+ } else if (flags == CAL_SEARCH_TASKS_DEFAULT) {
+ userfile = g_build_filename (g_get_home_dir (), ".evolution/tasks/searches.xml", NULL);
+ xmlfile = g_build_filename (SEARCH_RULE_DIR, "tasktypes.xml", NULL);
+ } else {
+ userfile = g_build_filename (g_get_home_dir (), ".evolution/calendar/searches.xml", NULL);
+ xmlfile = g_build_filename (SEARCH_RULE_DIR, "caltypes.xml", NULL);
+ }
+
+ g_object_set_data_full (G_OBJECT (search_context), "user", userfile, g_free);
+ g_object_set_data_full (G_OBJECT (search_context), "system", xmlfile, g_free);
+
+ rule_context_load (search_context, xmlfile, userfile);
+ search_rule = filter_rule_new ();
+ part = rule_context_next_part (search_context, NULL);
- e_search_bar_construct (E_SEARCH_BAR (cal_search), NULL, items);
+ if (part == NULL)
+ g_warning ("Could not load calendar search; no parts.");
+ else
+ filter_rule_add_part (search_rule, filter_part_clone (part));
+
+ e_filter_bar_new_construct (search_context, xmlfile, userfile, NULL, cal_search,
+ (EFilterBar*) cal_search );
+ e_search_bar_set_menu ((ESearchBar *) cal_search, calendar_search_items);
+
+ g_signal_connect ((ESearchBar *) cal_search, "menu_activated", G_CALLBACK (search_menu_activated), cal_search);
+
make_suboptions (cal_search);
+ cal_search->priv->search_rule = search_rule;
+ cal_search->priv->search_context = search_context;
+
+ g_free (xmlfile);
+ g_free (userfile);
+
return cal_search;
}
@@ -514,9 +830,9 @@ cal_search_bar_construct (CalSearchBar *cal_search, guint32 flags)
* cal_search_bar_new:
* flags: bitfield of items to appear in the search menu
*
- * Creates a new calendar search bar.
+ * creates a new calendar search bar.
*
- * Return value: A newly-created calendar search bar. You should connect to the
+ * return value: a newly-created calendar search bar. you should connect to the
* "sexp_changed" signal to monitor changes in the generated sexps.
**/
GtkWidget *
@@ -605,8 +921,19 @@ cal_search_bar_get_category (CalSearchBar *cal_search)
category = get_current_category (cal_search);
- if (!category || category == (const char *) 1)
- return NULL;
- else
- return category;
+ return category;
+}
+
+void
+cal_search_bar_get_time_range (CalSearchBar *cal_search, time_t *start, time_t *end)
+{
+ CalSearchBarPrivate *priv;
+
+ g_return_if_fail (IS_CAL_SEARCH_BAR (cal_search));
+
+ priv = cal_search->priv;
+
+ *start = priv->start;
+ *end = priv->end;
}
+
diff --git a/calendar/gui/cal-search-bar.h b/calendar/gui/cal-search-bar.h
index dfb235a378..53b8a346ad 100644
--- a/calendar/gui/cal-search-bar.h
+++ b/calendar/gui/cal-search-bar.h
@@ -48,18 +48,18 @@ enum {
#define CAL_SEARCH_ALL (0xff)
#define CAL_SEARCH_CALENDAR_DEFAULT (0x33)
-#define CAL_SEARCH_TASKS_DEFAULT (0x23)
+#define CAL_SEARCH_TASKS_DEFAULT (0xE3)
#define CAL_SEARCH_MEMOS_DEFAULT (0x23)
typedef struct {
- ESearchBar search_bar;
+ EFilterBar search_bar;
/* Private data */
CalSearchBarPrivate *priv;
} CalSearchBar;
typedef struct {
- ESearchBarClass parent_class;
+ EFilterBarClass parent_class;
/* Notification signals */
@@ -77,6 +77,8 @@ void cal_search_bar_set_categories (CalSearchBar *cal_search, GPtrArray *categor
const char *cal_search_bar_get_category (CalSearchBar *cal_search);
+void cal_search_bar_get_time_range (CalSearchBar *cal_search, time_t *start, time_t *end);
+
G_END_DECLS
diff --git a/calendar/gui/caltypes.xml b/calendar/gui/caltypes.xml
new file mode 100644
index 0000000000..73038d2600
--- /dev/null
+++ b/calendar/gui/caltypes.xml
@@ -0,0 +1,278 @@
+<?xml version="1.0"?>
+<filterdescription>
+<partset>
+ <part name="summary">
+ <title>Summary</title>
+ <input type="optionlist" name="summary-type">
+ <option value="contains">
+ <title>contains</title>
+ <code>(contains? "summary" ${summary})</code>
+ </option>
+ <option value="not contains">
+ <title>does not contain</title>
+ <code>(not (contains? "summary" ${summary}))</code>
+ </option>
+ </input>
+ <input type="string" name="summary"/>
+ </part>
+
+ <part name="description">
+ <title>Description</title>
+ <input type="optionlist" name="description-type">
+ <option value="contains">
+ <title>contains</title>
+ <code>(contains? "description" ${description})</code>
+ </option>
+ <option value="not contains">
+ <title>does not contain</title>
+ <code>(not (contains? "description" ${description}))</code>
+ </option>
+ </input>
+ <input type="string" name="description"/>
+ </part>
+ <part name="anyfield">
+ <title>Any Field</title>
+ <input type="optionlist" name="anyfield-type">
+ <option value="contains">
+ <title>contains</title>
+ <code>(contains? "any" ${anyfield})</code>
+ </option>
+ <option value="not contains">
+ <title>does not contain</title>
+ <code>(not (contains? "any" ${anyfield}))</code>
+ </option>
+ </input>
+ <input type="string" name="anyfield"/>
+ </part>
+
+ <part name="name5">
+ <title>Classification</title>
+ <input type="optionlist" name="name-type">
+ <option value="is">
+ <title>is</title>
+ <code>(contains? "classification" ${classification})</code>
+ </option>
+ <option value="is not">
+ <title>is not</title>
+ <code>(not(contains? "classification" ${classification}))</code>
+ </option>
+ </input>
+ <input type="optionlist" name="classification">
+ <option value="Public">
+ <title>Public</title>
+ </option>
+ <option value="Private">
+ <title>Private</title>
+ </option>
+ <option value="Confidential">
+ <title>Confidential</title>
+ </option>
+ </input>
+ </part>
+
+
+ <part name="name2">
+ <title>Organizer</title>
+ <input type="optionlist" name="name-type">
+ <option value="contains">
+ <title>contains</title>
+ <code>(contains? "organizer" ${name})</code>
+ </option>
+ <option value="not contains">
+ <title>does not contain</title>
+ <code>(not (contains? "organizer" ${name}))</code>
+ </option>
+ </input>
+ <input type="string" name="name"/>
+ </part>
+
+ <part name="name3">
+ <title>Attendee</title>
+ <input type="optionlist" name="name-type">
+ <option value="contains">
+ <title>contains</title>
+ <code>(contains? "attendee" ${name})</code>
+ </option>
+ <option value="not contains">
+ <title>does not contain</title>
+ <code>(not (contains? "attendee" ${name}))</code>
+ </option>
+ </input>
+ <input type="string" name="name"/>
+ </part>
+
+ <part name="name4">
+ <title>Loaction</title>
+ <input type="optionlist" name="name-type">
+ <option value="contains">
+ <title>contains</title>
+ <code>(contains? "location" ${name})</code>
+ </option>
+ <option value="not contains">
+ <title>does not contain</title>
+ <code>(not (contains? "location" ${name}))</code>
+ </option>
+ </input>
+ <input type="string" name="name"/>
+ </part>
+
+ <part name="category">
+ <title>Category</title>
+ <input type="optionlist" name="category-type">
+ <option value="is">
+ <title>is</title>
+ <code>(has-categories? ${category})</code>
+ </option>
+ <option value="is not">
+ <title>is not</title>
+ <code>(not(has-categories? ${category}))</code>
+ </option>
+ </input>
+ <input type="optionlist" name="category">
+ <option value="Anniversary">
+ <title>Anniversary</title>
+ </option>
+ <option value="Holiday">
+ <title>Holiday</title>
+ </option>
+ <option value="Ideas">
+ <title>Ideas</title>
+ </option>
+ <option value="Status">
+ <title>Status</title>
+ </option>
+ <option value="Holiday Cards">
+ <title>Holiday Cards</title>
+ </option>
+ <option value="Hot Contacts">
+ <title>Hot Contacts</title>
+ </option>
+ <option value="International">
+ <title>International</title>
+ </option>
+ <option value="Next 7 days">
+ <title>Next 7 days</title>
+ </option>
+ <option value="Birthday">
+ <title>Birthday</title>
+ </option>
+ <option value="VIP">
+ <title>VIP</title>
+ </option>
+ <option value="Gifts">
+ <title>Gifts</title>
+ </option>
+ <option value="Waiting">
+ <title>Waiting</title>
+ </option>
+ <option value="Key Customer">
+ <title>Key Customer</title>
+ </option>
+ <option value="Time &amp; Expenses">
+ <title>Time &amp; Expenses </title>
+ </option>
+ <option value="Miscellaneous">
+ <title>Miscellaneous</title>
+ </option>
+ <option value="Business">
+ <title>Business</title>
+ </option>
+ <option value="Personal">
+ <title>Personal</title>
+ </option>
+ <option value="Suppliers">
+ <title>Suppliers</title>
+ </option>
+ <option value="Goals/Objectives">
+ <title>Goals/Objectives</title>
+ </option>
+ <option value="Strategies">
+ <title>Strategies</title>
+ </option>
+ <option value="Competition">
+ <title>Competition</title>
+ </option>
+ <option value="Favourites">
+ <title>Favourites</title>
+ </option>
+ <option value="Phone Calls">
+ <title>Phone Calls</title>
+ </option>
+ </input>
+ </part>
+
+ <part name="attachments">
+ <title>Attachments</title>
+ <input type="optionlist" name="match-type">
+ <option value="exist">
+ <title>Exist</title>
+ <code>
+ (has-attachments?)
+ </code>
+ </option>
+ <option value="not exist">
+ <title>Do Not Exist</title>
+ <code>
+ (not(has-attachments?))
+ </code>
+ </option>
+ </input>
+ </part>
+
+ <part name="recurrences">
+ <title>Recurrence</title>
+ <input type="optionlist" name="match-type">
+ <option value="exist">
+ <title>Exist</title>
+ <code>
+ (has-recurrences?)
+ </code>
+ </option>
+ <option value="not exist">
+ <title>Do Not Exist</title>
+ <code>
+ (not (has-recurrences?))
+ </code>
+ </option>
+ </input>
+ </part>
+ </partset>
+
+<ruleset>
+ <rule grouping="any" source="demand">
+ <_title>Summary Contain</_title>
+ <partset>
+ <part name="summary">
+ <value name="summary-type" type="option" value="contains"/>
+ <value name="summary" type="string"/>
+ </part>
+ </partset>
+
+ <sources/>
+ </rule>
+
+ <rule grouping="any" source="demand">
+ <_title>Description Contain</_title>
+ <partset>
+ <part name="description">
+ <value name="description-type" type="option" value="contains"/>
+ <value name="description" type="string"/>
+ </part>
+ </partset>
+ <sources/>
+ </rule>
+
+ <rule grouping="any" source="demand">
+ <_title>Any field contains</_title>
+ <partset>
+ <part name="anyfield">
+ <value name="anyfield-type" type="option" value="contains"/>
+ <value name="anyfield" type="string"/>
+ </part>
+ </partset>
+ <sources/>
+ </rule>
+
+ </ruleset>
+
+ </filterdescription>
diff --git a/calendar/gui/e-cal-model.c b/calendar/gui/e-cal-model.c
index 78afb704a3..5cdc412a54 100644
--- a/calendar/gui/e-cal-model.c
+++ b/calendar/gui/e-cal-model.c
@@ -1812,6 +1812,37 @@ e_cal_model_set_search_query (ECalModel *model, const char *sexp)
}
/**
+ * e_cal_model_set_query
+ */
+void
+e_cal_model_set_search_query_with_time_range (ECalModel *model, const char *sexp, time_t start, time_t end)
+{
+ ECalModelPrivate *priv;
+ gboolean do_query = FALSE;
+
+ g_return_if_fail (E_IS_CAL_MODEL (model));
+
+ priv = model->priv;
+
+ if (strcmp (sexp ? sexp : "", priv->search_sexp ? priv->search_sexp : "")) {
+ if (priv->search_sexp)
+ g_free (priv->search_sexp);
+
+ priv->search_sexp = g_strdup (sexp);
+ do_query = TRUE;
+ }
+
+ if (!(priv->start == start && priv->end == end)) {
+ priv->start = start;
+ priv->end = end;
+ do_query = TRUE;
+ }
+
+ if (do_query)
+ redo_queries (model);
+}
+
+/**
* e_cal_model_create_component_with_defaults
*/
icalcomponent *
diff --git a/calendar/gui/e-cal-model.h b/calendar/gui/e-cal-model.h
index 5fcef40a29..46418d9f80 100644
--- a/calendar/gui/e-cal-model.h
+++ b/calendar/gui/e-cal-model.h
@@ -154,6 +154,7 @@ void e_cal_model_generate_instances (ECalModel
gpointer cb_data);
GPtrArray * e_cal_model_get_object_array (ECalModel *model);
void e_cal_model_set_instance_times (ECalModelComponent *comp_data, const icaltimezone *zone);
+void e_cal_model_set_search_query_with_time_range (ECalModel *model, const char *sexp, time_t start, time_t end);
diff --git a/calendar/gui/gnome-cal.c b/calendar/gui/gnome-cal.c
index 3c27eb3fe2..864cc064fa 100644
--- a/calendar/gui/gnome-cal.c
+++ b/calendar/gui/gnome-cal.c
@@ -185,6 +185,10 @@ struct _GnomeCalendarPrivate {
time_t visible_start;
time_t visible_end;
gboolean updating;
+
+ /* If this is true list view uses range of showing the events as the dates selected in date navigator which is one month, else
+ it uses the date range set in search bar */
+ gboolean lview_select_daten_range;
};
/* Signal IDs */
@@ -883,6 +887,7 @@ set_search_query (GnomeCalendar *gcal, const char *sexp)
{
GnomeCalendarPrivate *priv;
int i;
+ time_t start, end;
g_return_if_fail (gcal != NULL);
g_return_if_fail (GNOME_IS_CALENDAR (gcal));
@@ -900,8 +905,23 @@ set_search_query (GnomeCalendar *gcal, const char *sexp)
update_query (gcal);
/* Set the query on the views */
- for (i = 0; i < GNOME_CAL_LAST_VIEW; i++)
- e_cal_model_set_search_query (e_calendar_view_get_model (priv->views[i]), sexp);
+ for (i = 0; i < GNOME_CAL_LAST_VIEW; i++) {
+ if (i == GNOME_CAL_LIST_VIEW) {
+ if (!priv->lview_select_daten_range) {
+ cal_search_bar_get_time_range ((CalSearchBar *)priv->search_bar, &start, &end);
+ e_cal_model_set_search_query_with_time_range (e_calendar_view_get_model (priv->views [i]), sexp, start, end);
+ } else {
+ start = priv->base_view_time;
+ get_times_for_views (gcal, GNOME_CAL_LIST_VIEW, &start, &end);
+
+ e_cal_model_set_search_query_with_time_range (e_calendar_view_get_model (priv->views [i]), sexp, start, end);
+
+ if (priv->current_view_type == GNOME_CAL_LIST_VIEW)
+ gnome_calendar_update_date_navigator (gcal);
+ }
+ } else
+ e_cal_model_set_search_query (e_calendar_view_get_model (priv->views[i]), sexp);
+ }
/* Set the query on the task pad */
update_todo_view (gcal);
@@ -932,8 +952,20 @@ static void
search_bar_sexp_changed_cb (CalSearchBar *cal_search, const char *sexp, gpointer data)
{
GnomeCalendar *gcal;
+ const char *d_sexp = "occur-in-time-range?";
gcal = GNOME_CALENDAR (data);
+
+ /* Choose List view if the search made in the search bar is based on date */
+ if(sexp != NULL && strstr (sexp, d_sexp ) != NULL) {
+ gcal->priv->lview_select_daten_range = FALSE;
+ gtk_widget_hide (GTK_WIDGET (gcal->priv->date_navigator));
+ gnome_calendar_set_view (gcal, GNOME_CAL_LIST_VIEW);
+ } else {
+ gcal->priv->lview_select_daten_range = TRUE;
+ gtk_widget_show (GTK_WIDGET (gcal->priv->date_navigator));
+ }
+
set_search_query (gcal, sexp);
}
@@ -1209,10 +1241,6 @@ update_memo_view (GnomeCalendar *gcal)
priv = gcal->priv;
/* Set the query on the memo pad*/
- if (priv->memo_sexp) {
- g_free (priv->memo_sexp);
- }
-
model = e_memo_table_get_model (E_MEMO_TABLE (priv->memo));
view_model = e_calendar_view_get_model(priv->views[priv->current_view_type]);
e_cal_model_get_time_range (view_model, &start, &end);
@@ -1221,6 +1249,10 @@ update_memo_view (GnomeCalendar *gcal)
iso_start = isodate_from_time_t (start);
iso_end = isodate_from_time_t (end);
+ if (priv->memo_sexp) {
+ g_free (priv->memo_sexp);
+ }
+
priv->memo_sexp = g_strdup_printf ("(and (occur-in-time-range? (make-time \"%s\")"
" (make-time \"%s\"))"
" %s)",
@@ -1692,6 +1724,7 @@ gnome_calendar_init (GnomeCalendar *gcal)
priv->current_view_type = GNOME_CAL_DAY_VIEW;
priv->range_selected = FALSE;
+ priv->lview_select_daten_range = TRUE;
setup_config (gcal);
setup_widgets (gcal);
@@ -1997,7 +2030,10 @@ update_view_times (GnomeCalendar *gcal, time_t start_time)
model = e_calendar_view_get_model (priv->views[i]);
get_times_for_views (gcal, i, &real_start_time, &end_time);
- e_cal_model_set_time_range (model, real_start_time, end_time);
+ if (i == GNOME_CAL_LIST_VIEW && !priv->lview_select_daten_range)
+ continue;
+
+ e_cal_model_set_time_range (model, real_start_time, end_time);
}
}
@@ -2183,15 +2219,18 @@ display_view (GnomeCalendar *gcal, GnomeCalendarViewType view_type, gboolean gra
case GNOME_CAL_DAY_VIEW:
if (!priv->range_selected)
e_day_view_set_days_shown (E_DAY_VIEW (priv->day_view), 1);
-
+
+ gtk_widget_show (GTK_WIDGET (gcal->priv->date_navigator));
break;
case GNOME_CAL_WORK_WEEK_VIEW:
preserve_day = TRUE;
+ gtk_widget_show (GTK_WIDGET (gcal->priv->date_navigator));
break;
case GNOME_CAL_WEEK_VIEW:
preserve_day = TRUE;
+ gtk_widget_show (GTK_WIDGET (gcal->priv->date_navigator));
break;
case GNOME_CAL_MONTH_VIEW:
@@ -2199,9 +2238,14 @@ display_view (GnomeCalendar *gcal, GnomeCalendarViewType view_type, gboolean gra
e_week_view_set_weeks_shown (E_WEEK_VIEW (priv->month_view), 6);
preserve_day = TRUE;
+ gtk_widget_show (GTK_WIDGET (gcal->priv->date_navigator));
break;
case GNOME_CAL_LIST_VIEW:
+ if (!priv->lview_select_daten_range)
+ gtk_widget_hide (GTK_WIDGET (gcal->priv->date_navigator));
+ else
+ gtk_widget_show (GTK_WIDGET (gcal->priv->date_navigator));
break;
default:
@@ -2267,6 +2311,10 @@ display_view_cb (GalViewInstance *view_instance, GalView *view, gpointer data)
display_view (gcal, view_type, TRUE);
gnome_calendar_update_date_navigator (gcal);
gnome_calendar_notify_dates_shown_changed (gcal);
+
+ if (!priv->lview_select_daten_range && priv->current_view_type != GNOME_CAL_LIST_VIEW)
+ update_query (gcal);
+
}
/**
@@ -3255,6 +3303,9 @@ gnome_calendar_update_date_navigator (GnomeCalendar *gcal)
if (!GTK_WIDGET_VISIBLE (priv->date_navigator))
return;
+ if (priv->current_view_type == GNOME_CAL_LIST_VIEW && !priv->lview_select_daten_range)
+ return;
+
model = e_calendar_view_get_model (priv->views[priv->current_view_type]);
e_cal_model_get_time_range (model, &start, &end);
diff --git a/calendar/gui/memotypes.xml b/calendar/gui/memotypes.xml
new file mode 100644
index 0000000000..20a60529f7
--- /dev/null
+++ b/calendar/gui/memotypes.xml
@@ -0,0 +1,233 @@
+<?xml version="1.0"?>
+<filterdescription>
+<partset>
+ <part name="summary">
+ <title>Summary</title>
+ <input type="optionlist" name="summary-type">
+ <option value="contains">
+ <title>contains</title>
+ <code>(contains? "summary" ${summary})</code>
+ </option>
+ <option value="not contains">
+ <title>does not contain</title>
+ <code>(not (contains? "summary" ${summary}))</code>
+ </option>
+ </input>
+ <input type="string" name="summary"/>
+ </part>
+
+ <part name="description">
+ <title>Description</title>
+ <input type="optionlist" name="description-type">
+ <option value="contains">
+ <title>contains</title>
+ <code>(contains? "description" ${description})</code>
+ </option>
+ <option value="not contains">
+ <title>does not contain</title>
+ <code>(not (contains? "description" ${description}))</code>
+ </option>
+ </input>
+ <input type="string" name="description"/>
+ </part>
+
+ <part name="anyfield">
+ <title>Any Field</title>
+ <input type="optionlist" name="anyfield-type">
+ <option value="contains">
+ <title>contains</title>
+ <code>(contains? "any" ${anyfield})</code>
+ </option>
+ <option value="not contains">
+ <title>does not contain</title>
+ <code>(not (contains? "any" ${anyfield}))</code>
+ </option>
+ </input>
+ <input type="string" name="anyfield"/>
+ </part>
+
+ <part name="name2">
+ <title>Organizer</title>
+ <input type="optionlist" name="name-type">
+ <option value="contains">
+ <title>contains</title>
+ <code>(contains? "organizer" ${name})</code>
+ </option>
+ <option value="not contains">
+ <title>does not contain</title>
+ <code>(not (contains? "organizer" ${name}))</code>
+ </option>
+ </input>
+ <input type="string" name="name"/>
+ </part>
+
+<part name="name2">
+ <title>Classification</title>
+ <input type="optionlist" name="name-type">
+ <option value="is">
+ <title>is</title>
+ <code>(contains? "classification" ${classification})</code>
+ </option>
+ <option value="is not">
+ <title>is not</title>
+ <code>(not(contains? "classification" ${classification}))</code>
+ </option>
+ </input>
+ <input type="optionlist" name="classification">
+ <option value="Public">
+ <title>Public</title>
+ </option>
+ <option value="Private">
+ <title>Private</title>
+ </option>
+ <option value="Confidential">
+ <title>Confidential</title>
+ </option>
+ </input>
+ </part>
+
+ <part name="category">
+ <title>Category</title>
+ <input type="optionlist" name="category-type">
+ <option value="is">
+ <title>is</title>
+ <code>(has-categories? ${category})</code>
+ </option>
+ <option value="is not">
+ <title>is not</title>
+ <code>(not(has-categories? ${category}))</code>
+ </option>
+ </input>
+ <input type="optionlist" name="category">
+ <option value="Anniversary">
+ <title>Anniversary</title>
+ </option>
+ <option value="Holiday">
+ <title>Holiday</title>
+ </option>
+ <option value="Ideas">
+ <title>Ideas</title>
+ </option>
+ <option value="Status">
+ <title>Status</title>
+ </option>
+ <option value="Holiday Cards">
+ <title>Holiday Cards</title>
+ </option>
+ <option value="Hot Contacts">
+ <title>Hot Contacts</title>
+ </option>
+ <option value="International">
+ <title>International</title>
+ </option>
+ <option value="Next 7 days">
+ <title>Next 7 days</title>
+ </option>
+ <option value="Birthday">
+ <title>Birthday</title>
+ </option>
+ <option value="VIP">
+ <title>VIP</title>
+ </option>
+ <option value="Gifts">
+ <title>Gifts</title>
+ </option>
+ <option value="Waiting">
+ <title>Waiting</title>
+ </option>
+ <option value="Key Customer">
+ <title>Key Customer</title>
+ </option>
+ <option value="Time &amp; Expenses">
+ <title>Time &amp; Expenses </title>
+ </option>
+ <option value="Miscellaneous">
+ <title>Miscellaneous</title>
+ </option>
+ <option value="Business">
+ <title>Business</title>
+ </option>
+ <option value="Personal">
+ <title>Personal</title>
+ </option>
+ <option value="Suppliers">
+ <title>Suppliers</title>
+ </option>
+ <option value="Goals/Objectives">
+ <title>Goals/Objectives</title>
+ </option>
+ <option value="Strategies">
+ <title>Strategies</title>
+ </option>
+ <option value="Competition">
+ <title>Competition</title>
+ </option>
+ <option value="Favourites">
+ <title>Favourites</title>
+ </option>
+ <option value="Phone Calls">
+ <title>Phone Calls</title>
+ </option>
+ </input>
+ </part>
+
+<part name="attachments">
+ <title>Attachments</title>
+ <input type="optionlist" name="match-type">
+ <option value="exist">
+ <title>Exist</title>
+ <code>
+ (has-attachments?)
+
+ </code>
+ </option>
+ <option value="not exist">
+ <title>Do Not Exist</title>
+ <code>
+ (not(has-attachments?))
+ </code>
+ </option>
+ </input>
+ </part>
+
+
+</partset>
+
+<ruleset>
+
+ <rule grouping="any" source="demand">
+ <_title>Summary Contain</_title>
+ <partset>
+ <part name="summary">
+ <value name="summary-type" type="option" value="contains"/>
+ <value name="summary" type="string"/>
+ </part>
+ </partset>
+ <sources/>
+ </rule>
+
+ <rule grouping="any" source="demand">
+ <_title>Description Contain</_title>
+ <partset>
+ <part name="description">
+ <value name="description-type" type="option" value="contains"/>
+ <value name="description" type="string"/>
+ </part>
+ </partset>
+ <sources/>
+ </rule>
+
+ <rule grouping="any" source="demand">
+ <_title>Any field contains</_title>
+ <partset>
+ <part name="anyfield">
+ <value name="anyfield-type" type="option" value="contains"/>
+ <value name="anyfield" type="string"/>
+ </part>
+ </partset>
+ <sources/>
+ </rule>
+
+ </ruleset>
+
+ </filterdescription>
diff --git a/calendar/gui/tasktypes.xml b/calendar/gui/tasktypes.xml
new file mode 100644
index 0000000000..5871a3abbf
--- /dev/null
+++ b/calendar/gui/tasktypes.xml
@@ -0,0 +1,311 @@
+<?xml version="1.0"?>
+<filterdescription>
+ <partset>
+ <part name="summary">
+ <title>Summary</title>
+ <input type="optionlist" name="summary-type">
+ <option value="contains">
+ <title>contains</title>
+ <code>(contains? "summary" ${summary})</code>
+ </option>
+ <option value="not contains">
+ <title>does not contain</title>
+ <code>(not (contains? "summary" ${summary}))</code>
+ </option>
+ </input>
+ <input type="string" name="summary"/>
+ </part>
+
+ <part name="description">
+ <title>Description</title>
+ <input type="optionlist" name="description-type">
+ <option value="contains">
+ <title>contains</title>
+ <code>(contains? "description" ${description})</code>
+ </option>
+ <option value="not contains">
+ <title>does not contain</title>
+ <code>(not (contains? "description" ${description}))</code>
+ </option>
+ </input>
+ <input type="string" name="description"/>
+ </part>
+
+ <part name="name2">
+ <title>Organizer</title>
+ <input type="optionlist" name="name-type">
+ <option value="contains">
+ <title>contains</title>
+ <code>(contains? "organizer" ${name})</code>
+ </option>
+ <option value="not contains">
+ <title>does not contain</title>
+ <code>(not (contains? "organizer" ${name}))</code>
+ </option>
+ </input>
+ <input type="string" name="name"/>
+ </part>
+
+ <part name="name3">
+ <title>Attendee</title>
+ <input type="optionlist" name="name-type">
+ <option value="contains">
+ <title>contains</title>
+ <code>(contains? "attendee" ${name})</code>
+ </option>
+ <option value="not contains">
+ <title>does not contain</title>
+ <code>(not (contains? "attendee" ${name}))</code>
+ </option>
+ </input>
+ <input type="string" name="name"/>
+ </part>
+
+ <part name="anyfield">
+ <title>Any Field</title>
+ <input type="optionlist" name="anyfield-type">
+ <option value="contains">
+ <title>contains</title>
+ <code>(contains? "any" ${anyfield})</code>
+ </option>
+ <option value="not contains">
+ <title>does not contain</title>
+ <code>(not (contains? "any" ${anyfield}))</code>
+ </option>
+ </input>
+ <input type="string" name="anyfield"/>
+ </part>
+
+ <part name="status">
+ <title>Status</title>
+ <input type="optionlist" name="status-type">
+ <option value="is">
+ <title>is</title>
+ <code>(contains? "status" ${status})</code>
+ </option>
+ <option value="is not">
+ <title>is not</title>
+ <code>(not(contains? "status" ${status}))</code>
+ </option>
+ </input>
+ <input type="optionlist" name="status">
+ <option value="NOT STARTED">
+ <title>Not Started</title>
+ </option>
+ <option value="IN PROGRESS">
+ <title>In progress</title>
+ </option>
+ <option value="COMPLETED">
+ <title>Completed</title>
+ </option>
+ <option value="CANCELLED">
+ <title>Cancelled</title>
+ </option>
+
+ </input>
+ </part>
+
+ <part name="attachments">
+ <title>Attachments</title>
+ <input type="optionlist" name="match-type">
+ <option value="exist">
+ <title>Exist</title>
+ <code>
+ (has-attachments?)
+ </code>
+ </option>
+ <option value="not exist">
+ <title>Do Not Exist</title>
+ <code>
+ (not(has-attachments?))
+ </code>
+ </option>
+ </input>
+ </part>
+
+ <part name="priority">
+ <title>Priority</title>
+ <input type="optionlist" name="priority-type">
+ <option value="is">
+ <title>is</title>
+ <code>(contains? "priority" ${priority})</code>
+ </option>
+ <option value="is not">
+ <title>is not</title>
+ <code>(not(contains? "priority" ${priority}))</code>
+ </option>
+ </input>
+ <input type="optionlist" name="priority">
+ <option value="HIGH">
+ <title>High</title>
+ </option>
+ <option value="NORMAL">
+ <title>Normal</title>
+ </option>
+ <option value="LOW">
+ <title>Low</title>
+ </option>
+ <option value="UNDEFINED">
+ <title>Undefined</title>
+ </option>
+
+ </input>
+ </part>
+
+ <part name="category">
+ <title>Category</title>
+ <input type="optionlist" name="category-type">
+ <option value="is">
+ <title>is</title>
+ <code>(has-categories? ${category})</code>
+ </option>
+ <option value="is not">
+ <title>is not</title>
+ <code>(not(has-categories? ${category}))</code>
+ </option>
+ </input>
+ <input type="optionlist" name="category">
+ <option value="Anniversary">
+ <title>Anniversary</title>
+ </option>
+ <option value="Holiday">
+ <title>Holiday</title>
+ </option>
+ <option value="Ideas">
+ <title>Ideas</title>ke
+ </option>
+ <option value="Status">
+ <title>Status</title>
+ </option>
+ <option value="Holiday Cards">
+ <title>Holiday Cards</title>
+ </option>
+ <option value="Hot Contacts">
+ <title>Hot Contacts</title>
+ </option>
+ <option value="International">
+ <title>International</title>
+ </option>
+ <option value="Next 7 days">
+ <title>Next 7 days</title>
+ </option>
+ <option value="Birthday">
+ <title>Birthday</title>
+ </option>
+ <option value="VIP">
+ <title>VIP</title>
+ </option>
+ <option value="Gifts">
+ <title>Gifts</title>
+ </option>
+ <option value="Waiting">
+ <title>Waiting</title>
+ </option>
+ <option value="Key Customer">
+ <title>Key Customer</title>
+ </option>
+ <option value="Time &amp; Expenses">
+ <title>Time &amp; Expenses </title>
+ </option>
+ <option value="Miscellaneous">
+ <title>Miscellaneous</title>
+ </option>
+ <option value="Business">
+ <title>Business</title>
+ </option>
+ <option value="Personal">
+ ke
+ <title>Personal</title>
+ </option>
+ <option value="Suppliers">
+ <title>Suppliers</title>
+ </option>
+ <option value="Goals/Objectives">
+ <title>Goals/Objectives</title>
+ </option>
+ <option value="Strategies">
+ <title>Strategies</title>
+ </option>
+ <option value="Competition">
+ <title>Competition</title>
+ </option>
+ <option value="Favourites">
+ <title>Favourites</title>
+ </option>
+ <option value="Phone Calls">
+ <title>Phone Calls</title>
+ </option>
+ </input>
+ </part>
+
+ <part name="completed">
+ <title>% Completed</title>
+ <input type="optionlist" name="completed-type">
+ <option value="is">
+ <title>is</title>
+ <code>
+ (= (percent-complete?) ${versus} )
+ </code>
+ </option>
+ <option value="is-not">
+ <title>is not</title>
+ <code>
+ (not(= (percent-complete?) ${versus} ))
+ </code>
+ </option>
+ <option value="greater-than">
+ <title>is greater than</title>
+ <code>
+ (&gt; (percent-complete?) ${versus} )
+ </code>
+ </option>
+ <option value="less-than">
+ <title>is less than</title>
+ <code>
+ (&lt; (percent-complete?) ${versus} )
+ </code>
+ </option>
+ </input>
+ <input type="completedpercent" name="versus"/>
+ </part>
+
+ </partset>
+ <ruleset>
+ <rule grouping="any" source="demand">
+ <_title>Summary Contain</_title>
+ <partset>
+ <part name="summary">
+ <value name="summary-type" type="option" value="contains"/>
+ <value name="summary" type="string"/>
+ </part>
+ </partset>
+
+ <sources/>
+ </rule>
+
+ <rule grouping="any" source="demand">
+ <_title>Description Contain</_title>
+ <partset>
+ <part name="description">
+ <value name="description-type" type="option" value="contains"/>
+ <value name="description" type="string"/>
+ </part>
+ </partset>
+
+ <sources/>
+ </rule>
+
+ <rule grouping="any" source="demand">
+ <_title>Any field contains</_title>
+ <partset>
+ <part name="anyfield">
+ <value name="anyfield-type" type="option" value="contains"/>
+ <value name="anyfield" type="string"/>
+ </part>
+ </partset>
+
+ <sources/>
+ </rule>
+ </ruleset>
+
+</filterdescription>