diff options
Diffstat (limited to 'calendar/gui')
-rw-r--r-- | calendar/gui/GNOME_Evolution_Calendar.oaf.in | 13 | ||||
-rw-r--r-- | calendar/gui/Makefile.am | 2 | ||||
-rw-r--r-- | calendar/gui/cal-search-bar.c | 260 | ||||
-rw-r--r-- | calendar/gui/cal-search-bar.h | 62 | ||||
-rw-r--r-- | calendar/gui/calendar-commands.c | 120 | ||||
-rw-r--r-- | calendar/gui/calendar-model.c | 379 | ||||
-rw-r--r-- | calendar/gui/calendar-model.h | 3 | ||||
-rw-r--r-- | calendar/gui/comp-editor-factory.c | 228 | ||||
-rw-r--r-- | calendar/gui/comp-editor-factory.h | 59 | ||||
-rw-r--r-- | calendar/gui/e-calendar-table.c | 191 | ||||
-rw-r--r-- | calendar/gui/e-calendar-table.h | 36 | ||||
-rw-r--r-- | calendar/gui/e-tasks.c | 93 | ||||
-rw-r--r-- | calendar/gui/gnome-cal.c | 132 | ||||
-rw-r--r-- | calendar/gui/itip-utils.c | 1 |
14 files changed, 944 insertions, 635 deletions
diff --git a/calendar/gui/GNOME_Evolution_Calendar.oaf.in b/calendar/gui/GNOME_Evolution_Calendar.oaf.in index 70924677f7..0e07c3bfa2 100644 --- a/calendar/gui/GNOME_Evolution_Calendar.oaf.in +++ b/calendar/gui/GNOME_Evolution_Calendar.oaf.in @@ -117,4 +117,17 @@ _value="A sample Bonobo control which displays an calendar."/> </oaf_server> +<oaf_server iid="OAFIID:GNOME_Evolution_Calendar_CompEditorFactory" + type="exe" + location="evolution-calendar"> + + <oaf_attribute name="repo_ids" type="stringv"> + <item value="IDL:GNOME/Evolution/Calendar/CompEditorFactory:1.0"/> + <item value="IDL:Bonobo/Unknown:1.0"/> + </oaf_attribute> + + <oaf_attribute name="description" type="string" + _value="Factory to centralize calendar component editor dialogs"/> +</oaf_server> + </oaf_info> diff --git a/calendar/gui/Makefile.am b/calendar/gui/Makefile.am index 0aa57aeda8..a694e1b21a 100644 --- a/calendar/gui/Makefile.am +++ b/calendar/gui/Makefile.am @@ -59,6 +59,8 @@ etspec_DATA = e-calendar-table.etspec evolution_calendar_SOURCES = \ $(IDL_GENERATED) \ + cal-search-bar.c \ + cal-search-bar.h \ calendar-config.c \ calendar-config.h \ calendar-commands.c \ diff --git a/calendar/gui/cal-search-bar.c b/calendar/gui/cal-search-bar.c new file mode 100644 index 0000000000..351f65c5e6 --- /dev/null +++ b/calendar/gui/cal-search-bar.c @@ -0,0 +1,260 @@ +/* Evolution calendar - Search bar widget for calendar views + * + * Copyright (C) 2001 Ximian, Inc. + * + * Author: Federico Mena-Quintero <federico@ximian.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <glib.h> +#include <gtk/gtksignal.h> +#include <libgnome/gnome-defs.h> +#include <libgnome/gnome-i18n.h> +#include "cal-search-bar.h" + + + +/* Menu items for the ESearchBar */ +static ESearchBarItem search_menu_items[] = { + E_FILTERBAR_RESET, + { NULL, -1 } +}; + +/* IDs and option items for the ESearchBar */ +enum { + SEARCH_ANY_FIELD_CONTAINS, + SEARCH_SUMMARY_CONTAINS, + SEARCH_DESCRIPTION_CONTAINS, + SEARCH_COMMENT_CONTAINS, + SEARCH_HAS_CATEGORY +}; + +static ESearchBarItem search_option_items[] = { + { N_("Any field contains"), SEARCH_ANY_FIELD_CONTAINS }, + { N_("Summary contains"), SEARCH_SUMMARY_CONTAINS }, + { N_("Description contains"), SEARCH_DESCRIPTION_CONTAINS }, + { N_("Comment contains"), SEARCH_COMMENT_CONTAINS }, + { N_("Has category"), SEARCH_HAS_CATEGORY }, + { NULL, -1 } +}; + + + +static void cal_search_bar_class_init (CalSearchBarClass *class); + +static void cal_search_bar_query_changed (ESearchBar *search); +static void cal_search_bar_menu_activated (ESearchBar *search, int item); + +/* Signal IDs */ +enum { + SEXP_CHANGED, + LAST_SIGNAL +}; + +static guint cal_search_bar_signals[LAST_SIGNAL] = { 0 }; + + + +/** + * cal_search_bar_get_type: + * + * Registers the #CalSearchBar class if necessary and returns the type ID + * associated to it. + * + * Return value: The type ID of the #CalSearchBar class. + **/ +GtkType +cal_search_bar_get_type (void) +{ + static GtkType cal_search_bar_type = 0; + + if (!cal_search_bar_type) { + static const GtkTypeInfo cal_search_bar_info = { + "CalSearchBar", + sizeof (CalSearchBar), + sizeof (CalSearchBarClass), + (GtkClassInitFunc) cal_search_bar_class_init, + (GtkObjectInitFunc) NULL, + NULL, /* reserved_1 */ + NULL, /* reserved_2 */ + (GtkClassInitFunc) NULL + }; + + cal_search_bar_type = gtk_type_unique (E_SEARCH_BAR_TYPE, &cal_search_bar_info); + } + + return cal_search_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; + object_class = (GtkObjectClass *) class; + + cal_search_bar_signals[SEXP_CHANGED] = + gtk_signal_new ("sexp_changed", + GTK_RUN_FIRST, + object_class->type, + GTK_SIGNAL_OFFSET (CalSearchBarClass, sexp_changed), + gtk_marshal_NONE__STRING, + GTK_TYPE_NONE, 1, + GTK_TYPE_STRING); + + gtk_object_class_add_signals (object_class, cal_search_bar_signals, LAST_SIGNAL); + + class->sexp_changed = NULL; + + e_search_bar_class->query_changed = cal_search_bar_query_changed; + e_search_bar_class->menu_activated = cal_search_bar_menu_activated; +} + + + +/* Emits the "sexp_changed" signal for the calendar search bar */ +static void +notify_sexp_changed (CalSearchBar *cal_search, const char *sexp) +{ + gtk_signal_emit (GTK_OBJECT (cal_search), cal_search_bar_signals[SEXP_CHANGED], + sexp); +} + +/* Sets the query string to be (contains? "field" "text") */ +static void +notify_query_contains (CalSearchBar *cal_search, const char *field, const char *text) +{ + char *sexp; + + sexp = g_strdup_printf ("(contains? \"%s\" \"%s\")", field, text); + notify_sexp_changed (cal_search, sexp); + g_free (sexp); +} + +/* query_changed handler for the calendar search bar */ +static void +cal_search_bar_query_changed (ESearchBar *search) +{ + CalSearchBar *cal_search; + int item; + char *text; + + cal_search = CAL_SEARCH_BAR (search); + + item = e_search_bar_get_option_choice (search); + text = e_search_bar_get_text (search); + + if (!text) + return; /* This is an error in the UTF8 conversion, not an empty string! */ + + switch (item) { + case SEARCH_ANY_FIELD_CONTAINS: + notify_query_contains (cal_search, "any", text); + break; + + case SEARCH_SUMMARY_CONTAINS: + notify_query_contains (cal_search, "summary", text); + break; + + case SEARCH_DESCRIPTION_CONTAINS: + notify_query_contains (cal_search, "description", text); + break; + + case SEARCH_COMMENT_CONTAINS: + notify_query_contains (cal_search, "comment", text); + break; + + case SEARCH_HAS_CATEGORY: { + char *sexp; + + sexp = g_strdup_printf ("(has-categories? \"%s\")", text); + notify_sexp_changed (cal_search, sexp); + g_free (sexp); + break; + } + + default: + g_assert_not_reached (); + } + + g_free (text); +} + +/* menu_activated handler for the calendar search bar */ +static void +cal_search_bar_menu_activated (ESearchBar *search, int item) +{ + CalSearchBar *cal_search; + + cal_search = CAL_SEARCH_BAR (search); + + switch (item) { + case E_FILTERBAR_RESET_ID: + notify_sexp_changed (cal_search, "#t"); /* match all */ + /* FIXME: should we change the rest of the search bar so that + * the user sees that he selected "show all" instead of some + * type/text search combination? + */ + break; + + default: + g_assert_not_reached (); + } +} + + + +/** + * cal_search_bar_construct: + * @cal_search: A calendar search bar. + * + * Constructs a calendar search bar by binding its menu and option items. + * + * Return value: The same value as @cal_search. + **/ +CalSearchBar * +cal_search_bar_construct (CalSearchBar *cal_search) +{ + g_return_val_if_fail (cal_search != NULL, NULL); + g_return_val_if_fail (IS_CAL_SEARCH_BAR (cal_search), NULL); + + e_search_bar_construct (E_SEARCH_BAR (cal_search), search_menu_items, search_option_items); + return cal_search; +} + +/** + * cal_search_bar_new: + * + * Creates a new calendar search bar. + * + * Return value: A newly-created calendar search bar. You should connect to the + * "sexp_changed" signal to monitor changes in the generated sexps. + **/ +GtkWidget * +cal_search_bar_new (void) +{ + CalSearchBar *cal_search; + + cal_search = gtk_type_new (TYPE_CAL_SEARCH_BAR); + return GTK_WIDGET (cal_search_bar_construct (cal_search)); +} diff --git a/calendar/gui/cal-search-bar.h b/calendar/gui/cal-search-bar.h new file mode 100644 index 0000000000..1317369371 --- /dev/null +++ b/calendar/gui/cal-search-bar.h @@ -0,0 +1,62 @@ +/* Evolution calendar - Search bar widget for calendar views + * + * Copyright (C) 2001 Ximian, Inc. + * + * Author: Federico Mena-Quintero <federico@ximian.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef CAL_SEARCH_BAR_H +#define CAL_SEARCH_BAR_H + +#include <libgnome/gnome-defs.h> +#include "widgets/misc/e-search-bar.h" +#include "widgets/misc/e-filter-bar.h" + +BEGIN_GNOME_DECLS + + + +#define TYPE_CAL_SEARCH_BAR (cal_search_bar_get_type ()) +#define CAL_SEARCH_BAR(obj) (GTK_CHECK_CAST ((obj), TYPE_CAL_SEARCH_BAR, CalSearchBar)) +#define CAL_SEARCH_BAR_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), TYPE_CAL_SEARCH_BAR, \ + CalSearchBarClass)) +#define IS_CAL_SEARCH_BAR(obj) (GTK_CHECK_TYPE ((obj), TYPE_CAL_SEARCH_BAR)) +#define IS_CAL_SEARCH_BAR_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), TYPE_CAL_SEARCH_BAR)) + +typedef struct { + ESearchBar search_bar; +} CalSearchBar; + +typedef struct { + ESearchBarClass parent_class; + + /* Notification signals */ + + void (* sexp_changed) (CalSearchBar *cal_search, const char *sexp); +} CalSearchBarClass; + +GtkType cal_search_bar_get_type (void); + +CalSearchBar *cal_search_bar_construct (CalSearchBar *cal_search); + +GtkWidget *cal_search_bar_new (void); + + + +END_GNOME_DECLS + +#endif diff --git a/calendar/gui/calendar-commands.c b/calendar/gui/calendar-commands.c index 0216c15f48..a0366685c9 100644 --- a/calendar/gui/calendar-commands.c +++ b/calendar/gui/calendar-commands.c @@ -263,104 +263,7 @@ show_month_view_clicked (BonoboUIComponent *uic, gpointer data, const char *path static void -new_calendar_cmd (BonoboUIComponent *uic, gpointer data, const char *path) -{ - new_calendar (); -} - -static void -open_ok (GtkWidget *widget, GtkFileSelection *fs) -{ - GtkWidget *error_dialog; - int ret; - if(!g_file_exists (gtk_file_selection_get_filename (fs))) { - error_dialog = gnome_message_box_new ( - _("File not found"), - GNOME_MESSAGE_BOX_ERROR, - GNOME_STOCK_BUTTON_OK, - NULL); - - gnome_dialog_set_parent (GNOME_DIALOG (error_dialog), GTK_WINDOW (fs)); - ret = gnome_dialog_run (GNOME_DIALOG (error_dialog)); - } else { - /* FIXME: find out who owns this calendar and use that name */ -#ifndef NO_WARNINGS -#warning "FIXME: find out who owns this calendar and use that name" -#endif - /* - new_calendar ("Somebody", gtk_file_selection_get_filename (fs)); - */ - gtk_widget_destroy (GTK_WIDGET (fs)); - } -} - -static void -open_calendar_cmd (BonoboUIComponent *uic, gpointer data, const char *path) -{ - GtkFileSelection *fs; - - fs = GTK_FILE_SELECTION (gtk_file_selection_new (_("Open calendar"))); - - gtk_signal_connect (GTK_OBJECT (fs->ok_button), "clicked", - (GtkSignalFunc) open_ok, - fs); - gtk_signal_connect_object (GTK_OBJECT (fs->cancel_button), "clicked", - (GtkSignalFunc) gtk_widget_destroy, - GTK_OBJECT (fs)); - - gtk_widget_show (GTK_WIDGET (fs)); - gtk_grab_add (GTK_WIDGET (fs)); /* Yes, it is modal, so sue me */ -} - -static void -save_ok (GtkWidget *widget, GtkFileSelection *fs) -{ - GnomeCalendar *gcal; - gchar *fname; - - gcal = GNOME_CALENDAR (gtk_object_get_user_data (GTK_OBJECT (fs))); - gtk_window_set_wmclass (GTK_WINDOW (gcal), "gnomecal", "gnomecal"); - - fname = g_strdup (gtk_file_selection_get_filename (fs)); - g_free(fname); - gtk_main_quit (); -} - -static gint -close_save (GtkWidget *w) -{ - gtk_main_quit (); - return TRUE; -} - -static void -save_as_calendar_cmd (BonoboUIComponent *uic, gpointer data, const char *path) -{ - GnomeCalendar *gcal; - GtkFileSelection *fs; - - gcal = GNOME_CALENDAR (data); - - fs = GTK_FILE_SELECTION (gtk_file_selection_new (_("Save calendar"))); - gtk_object_set_user_data (GTK_OBJECT (fs), gcal); - - gtk_signal_connect (GTK_OBJECT (fs->ok_button), "clicked", - (GtkSignalFunc) save_ok, - fs); - gtk_signal_connect_object (GTK_OBJECT (fs->cancel_button), "clicked", - (GtkSignalFunc) close_save, - GTK_OBJECT (fs)); - gtk_signal_connect_object (GTK_OBJECT (fs), "delete_event", - GTK_SIGNAL_FUNC (close_save), - GTK_OBJECT (fs)); - gtk_widget_show (GTK_WIDGET (fs)); - gtk_grab_add (GTK_WIDGET (fs)); /* Yes, it is modal, so sue me even more */ - gtk_main (); - gtk_widget_destroy (GTK_WIDGET (fs)); -} - -static void -preferences_cmd (BonoboUIComponent *uic, gpointer data, const char *path) +settings_cmd (BonoboUIComponent *uic, gpointer data, const char *path) { if (!preferences_dialog) preferences_dialog = cal_prefs_dialog_new (); @@ -471,21 +374,16 @@ clear_folder_bar_label (BonoboControl *control) } static BonoboUIVerb verbs [] = { - BONOBO_UI_VERB ("CalendarNew", new_calendar_cmd), - BONOBO_UI_VERB ("CalendarOpen", open_calendar_cmd), - BONOBO_UI_VERB ("CalendarSaveAs", save_as_calendar_cmd), BONOBO_UI_VERB ("CalendarPrint", file_print_cb), BONOBO_UI_VERB ("CalendarPrintPreview", file_print_preview_cb), - BONOBO_UI_VERB ("EditNewAppointment", new_appointment_cb), - BONOBO_UI_VERB ("EditNewEvent", new_event_cb), - BONOBO_UI_VERB ("CalendarPreferences", preferences_cmd), + BONOBO_UI_VERB ("CalendarNewAppointment", new_appointment_cb), + BONOBO_UI_VERB ("CalendarNewEvent", new_event_cb), + BONOBO_UI_VERB ("CalendarSettings", settings_cmd), BONOBO_UI_VERB ("CutEvent", cut_event_cmd), BONOBO_UI_VERB ("CopyEvent", copy_event_cmd), BONOBO_UI_VERB ("PasteEvent", paste_event_cmd), - BONOBO_UI_VERB ("PublishFreeBusy", publish_freebusy_cmd), - BONOBO_UI_VERB ("CalendarPrev", previous_clicked), BONOBO_UI_VERB ("CalendarToday", today_clicked), BONOBO_UI_VERB ("CalendarNext", next_clicked), @@ -496,16 +394,18 @@ static BonoboUIVerb verbs [] = { BONOBO_UI_VERB ("ShowWeekView", show_week_view_clicked), BONOBO_UI_VERB ("ShowMonthView", show_month_view_clicked), + BONOBO_UI_VERB ("PublishFreeBusy", publish_freebusy_cmd), + BONOBO_UI_VERB_END }; static EPixmap pixmaps [] = { - E_PIXMAP ("/menu/File/New/NewFirstItem/CalendarNew", "new_appointment.xpm"), + E_PIXMAP ("/menu/File/New/NewFirstItem/NewAppointment", "new_appointment.xpm"), E_PIXMAP ("/menu/File/Print/Print", "print.xpm"), - E_PIXMAP ("/menu/File/Print/Print Preview", "print-preview.xpm"), - E_PIXMAP ("/menu/Actions/Component/CalendarNew", "new_appointment.xpm"), - E_PIXMAP ("/menu/Tools/Component/CalendarPreferences", "configure_16_calendar.xpm"), + E_PIXMAP ("/menu/File/Print/PrintPreview", "print-preview.xpm"), + E_PIXMAP ("/menu/Actions/Component/NewAppointment", "new_appointment.xpm"), + E_PIXMAP ("/menu/Tools/Component/CalendarSettings", "configure_16_calendar.xpm"), E_PIXMAP ("/Toolbar/New", "buttons/new_appointment.png"), E_PIXMAP ("/Toolbar/Print", "buttons/print.png"), diff --git a/calendar/gui/calendar-model.c b/calendar/gui/calendar-model.c index 2e48ecf00c..7fccf3937a 100644 --- a/calendar/gui/calendar-model.c +++ b/calendar/gui/calendar-model.c @@ -48,6 +48,10 @@ struct _CalendarModelPrivate { /* Types of objects we are dealing with */ CalObjType type; + /* S-expression for query and the query object */ + char *sexp; + CalQuery *query; + /* Array of pointers to calendar objects */ GArray *objects; @@ -96,12 +100,10 @@ static void calendar_model_free_value (ETableModel *etm, int col, void *value); static void *calendar_model_initialize_value (ETableModel *etm, int col); static gboolean calendar_model_value_is_empty (ETableModel *etm, int col, const void *value); static char * calendar_model_value_to_string (ETableModel *etm, int col, const void *value); -static void load_objects (CalendarModel *model); static int remove_object (CalendarModel *model, const char *uid); static void ensure_task_complete (CalComponent *comp, time_t completed_date); static void ensure_task_not_complete (CalComponent *comp); -static void calendar_model_collect_all_categories (CalendarModel *model); static gboolean calendar_model_collect_categories (CalendarModel *model, CalComponent *comp); @@ -190,6 +192,9 @@ calendar_model_init (CalendarModel *model) priv = g_new0 (CalendarModelPrivate, 1); model->priv = priv; + priv->sexp = g_strdup ("#t"); /* match all by default */ + priv->query = NULL; + priv->objects = g_array_new (FALSE, TRUE, sizeof (CalComponent *)); priv->uid_index_hash = g_hash_table_new (g_str_hash, g_str_equal); priv->new_comp_vtype = CAL_COMPONENT_EVENT; @@ -257,6 +262,17 @@ calendar_model_destroy (GtkObject *object) priv->client = NULL; } + if (priv->sexp) { + g_free (priv->sexp); + priv->sexp = NULL; + } + + if (priv->query) { + gtk_signal_disconnect_by_data (GTK_OBJECT (priv->query), model); + gtk_object_unref (GTK_OBJECT (priv->query)); + priv->query = NULL; + } + /* Free the uid->index hash data and the array of UIDs */ free_objects (model); @@ -1729,105 +1745,20 @@ calendar_model_new (void) } -/* Callback used when a calendar is opened into the server */ +/* Callback used when a component is updated in the live query */ static void -cal_opened_cb (CalClient *client, CalClientOpenStatus status, gpointer data) -{ - CalendarModel *model; - - model = CALENDAR_MODEL (data); - - e_table_model_pre_change (E_TABLE_MODEL (model)); - - if (status == CAL_CLIENT_OPEN_SUCCESS) { - load_objects (model); - calendar_model_collect_all_categories (model); - } - - e_table_model_changed (E_TABLE_MODEL (model)); -} - - -/* Removes an object from the model and updates all the indices that follow. - * Returns the index of the object that was removed, or -1 if no object with - * such UID was found. - */ -static int -remove_object (CalendarModel *model, const char *uid) -{ - CalendarModelPrivate *priv; - int *idx; - CalComponent *orig_comp; - int i; - int n; - - priv = model->priv; - - /* Find the index of the object to be removed */ - - idx = g_hash_table_lookup (priv->uid_index_hash, uid); - if (!idx) - return -1; - - orig_comp = g_array_index (priv->objects, CalComponent *, *idx); - g_assert (orig_comp != NULL); - - /* Decrease the indices of all the objects that follow in the array */ - - for (i = *idx + 1; i < priv->objects->len; i++) { - CalComponent *comp; - int *comp_idx; - const char *comp_uid; - - comp = g_array_index (priv->objects, CalComponent *, i); - g_assert (comp != NULL); - - cal_component_get_uid (comp, &comp_uid); - - comp_idx = g_hash_table_lookup (priv->uid_index_hash, comp_uid); - g_assert (comp_idx != NULL); - - (*comp_idx)--; - g_assert (*comp_idx >= 0); - } - - /* Remove this object from the array and hash */ - - g_hash_table_remove (priv->uid_index_hash, uid); - g_array_remove_index (priv->objects, *idx); - - gtk_object_unref (GTK_OBJECT (orig_comp)); - - n = *idx; - g_free (idx); - - return n; -} - -/* Returns whether a component's type matches the types we support */ -static gboolean -matches_type (CalObjType type, CalComponentVType vtype) -{ - return ((vtype == CAL_COMPONENT_EVENT && (type & CALOBJ_TYPE_EVENT)) - || (vtype == CAL_COMPONENT_TODO && (type & CALOBJ_TYPE_TODO)) - || (vtype == CAL_COMPONENT_JOURNAL && (type & CALOBJ_TYPE_JOURNAL))); -} - -/* Callback used when an object is updated in the server */ -static void -obj_updated_cb (CalClient *client, const char *uid, gpointer data) +query_obj_updated_cb (CalQuery *query, const char *uid, + gboolean query_in_progress, int n_scanned, int total, + gpointer data) { CalendarModel *model; CalendarModelPrivate *priv; int orig_idx; CalComponent *new_comp; - CalComponentVType new_comp_vtype; const char *new_comp_uid; int *new_idx; CalClientGetStatus status; - g_print ("In calendar model obj_updated_cb\n"); - model = CALENDAR_MODEL (data); priv = model->priv; @@ -1837,14 +1768,6 @@ obj_updated_cb (CalClient *client, const char *uid, gpointer data) switch (status) { case CAL_CLIENT_GET_SUCCESS: - /* Check if we are interested in this type of object */ - - new_comp_vtype = cal_component_get_vtype (new_comp); - if (!matches_type (priv->type, new_comp_vtype)) { - gtk_object_unref (GTK_OBJECT (new_comp)); - break; - } - /* Insert the object into the model */ cal_component_get_uid (new_comp, &new_comp_uid); @@ -1922,13 +1845,11 @@ obj_updated_cb (CalClient *client, const char *uid, gpointer data) default: g_assert_not_reached (); } - - g_print ("Out calendar model obj_updated_cb\n"); } -/* Callback used when an object is removed in the server */ +/* Callback used when a component is removed from the live query */ static void -obj_removed_cb (CalClient *client, const char *uid, gpointer data) +query_obj_removed_cb (CalQuery *query, const char *uid, gpointer data) { CalendarModel *model; int idx; @@ -1941,67 +1862,175 @@ obj_removed_cb (CalClient *client, const char *uid, gpointer data) e_table_model_row_deleted (E_TABLE_MODEL (model), idx); } -/* Loads the required objects from the calendar client */ +/* Callback used when a query ends */ static void -load_objects (CalendarModel *model) +query_query_done_cb (CalQuery *query, CalQueryDoneStatus status, const char *error_str, gpointer data) +{ + CalendarModel *model; + + model = CALENDAR_MODEL (data); + + /* FIXME */ + + if (status != CAL_QUERY_DONE_SUCCESS) + fprintf (stderr, "query done: %s\n", error_str); +} + +/* Callback used when an evaluation error occurs when running a query */ +static void +query_eval_error_cb (CalQuery *query, const char *error_str, gpointer data) +{ + CalendarModel *model; + + model = CALENDAR_MODEL (data); + + /* FIXME */ + + fprintf (stderr, "eval error: %s\n", error_str); +} + +/* Builds a complete query sexp for the calendar model by adding the predicates + * to filter only for the type of objects that the model supports. + */ +static char * +adjust_query_sexp (CalendarModel *model, const char *sexp) { CalendarModelPrivate *priv; - GList *uids; - GList *l; + CalObjType type; + char *type_sexp; + char *new_sexp; priv = model->priv; - g_assert (cal_client_get_load_state (priv->client) == CAL_CLIENT_LOAD_LOADED); + type = priv->type; - uids = cal_client_get_uids (priv->client, priv->type); + if (!(type & CALOBJ_TYPE_ANY)) + type_sexp = g_strdup ("#t"); + else + type_sexp = g_strdup_printf ( + "(or %s %s %s)", + (type & CALOBJ_TYPE_EVENT) ? "(= (get-vtype) \"VEVENT\")" : "", + (type & CALOBJ_TYPE_TODO) ? "(= (get-vtype) \"VTODO\")" : "", + (type & CALOBJ_TYPE_JOURNAL) ? "(= (get-vtype) \"VJOURNAL\")" : ""); - for (l = uids; l; l = l->next) { - char *uid; - CalComponent *comp; - const char *comp_uid; - CalClientGetStatus status; - CalComponentVType comp_vtype; - int *idx; + new_sexp = g_strdup_printf ("(and %s %s)", type_sexp, sexp); + g_free (type_sexp); + + return new_sexp; +} + +/* Restarts a query */ +static void +update_query (CalendarModel *model) +{ + CalendarModelPrivate *priv; + char *real_sexp; - uid = l->data; - status = cal_client_get_object (priv->client, uid, &comp); + priv = model->priv; - switch (status) { - case CAL_CLIENT_GET_SUCCESS: - break; + e_table_model_pre_change (E_TABLE_MODEL (model)); + free_objects (model); + e_table_model_changed (E_TABLE_MODEL (model)); - case CAL_CLIENT_GET_NOT_FOUND: - /* Nothing; the object may have been removed from the server */ - continue; + if (!(priv->client + && cal_client_get_load_state (priv->client) == CAL_CLIENT_LOAD_LOADED)) + return; - case CAL_CLIENT_GET_SYNTAX_ERROR: - g_message ("load_objects(): Syntax error when getting object `%s'", uid); - continue; + if (priv->query) { + gtk_signal_disconnect_by_data (GTK_OBJECT (priv->query), model); + gtk_object_unref (GTK_OBJECT (priv->query)); + } - default: - g_assert_not_reached (); - } + g_assert (priv->sexp != NULL); + real_sexp = adjust_query_sexp (model, priv->sexp); - /* Check if we are interested in this type of object */ + priv->query = cal_client_get_query (priv->client, real_sexp); + g_free (real_sexp); - comp_vtype = cal_component_get_vtype (comp); - if (!matches_type (priv->type, comp_vtype)) { - gtk_object_unref (GTK_OBJECT (comp)); - continue; - } + if (!priv->query) { + g_message ("update_query(): Could not create the query"); + return; + } - /* Insert the object into the model */ + gtk_signal_connect (GTK_OBJECT (priv->query), "obj_updated", + GTK_SIGNAL_FUNC (query_obj_updated_cb), model); + gtk_signal_connect (GTK_OBJECT (priv->query), "obj_removed", + GTK_SIGNAL_FUNC (query_obj_removed_cb), model); + gtk_signal_connect (GTK_OBJECT (priv->query), "query_done", + GTK_SIGNAL_FUNC (query_query_done_cb), model); + gtk_signal_connect (GTK_OBJECT (priv->query), "eval_error", + GTK_SIGNAL_FUNC (query_eval_error_cb), model); +} + +/* Callback used when a calendar is opened into the server */ +static void +cal_opened_cb (CalClient *client, CalClientOpenStatus status, gpointer data) +{ + CalendarModel *model; - idx = g_new (int, 1); + model = CALENDAR_MODEL (data); + + if (status != CAL_CLIENT_OPEN_SUCCESS) + return; - g_array_append_val (priv->objects, comp); - *idx = priv->objects->len - 1; + update_query (model); +} + + +/* Removes an object from the model and updates all the indices that follow. + * Returns the index of the object that was removed, or -1 if no object with + * such UID was found. + */ +static int +remove_object (CalendarModel *model, const char *uid) +{ + CalendarModelPrivate *priv; + int *idx; + CalComponent *orig_comp; + int i; + int n; + + priv = model->priv; + + /* Find the index of the object to be removed */ + + idx = g_hash_table_lookup (priv->uid_index_hash, uid); + if (!idx) + return -1; + + orig_comp = g_array_index (priv->objects, CalComponent *, *idx); + g_assert (orig_comp != NULL); + + /* Decrease the indices of all the objects that follow in the array */ + + for (i = *idx + 1; i < priv->objects->len; i++) { + CalComponent *comp; + int *comp_idx; + const char *comp_uid; + + comp = g_array_index (priv->objects, CalComponent *, i); + g_assert (comp != NULL); cal_component_get_uid (comp, &comp_uid); - g_hash_table_insert (priv->uid_index_hash, (char *) comp_uid, idx); + + comp_idx = g_hash_table_lookup (priv->uid_index_hash, comp_uid); + g_assert (comp_idx != NULL); + + (*comp_idx)--; + g_assert (*comp_idx >= 0); } - cal_obj_uid_list_free (uids); + /* Remove this object from the array and hash */ + + g_hash_table_remove (priv->uid_index_hash, uid); + g_array_remove_index (priv->objects, *idx); + + gtk_object_unref (GTK_OBJECT (orig_comp)); + + n = *idx; + g_free (idx); + + return n; } /** @@ -2051,8 +2080,6 @@ calendar_model_set_cal_client (CalendarModel *model, CalClient *client, CalObjTy if (priv->client == client && priv->type == type) return; - e_table_model_pre_change (E_TABLE_MODEL(model)); - if (client) gtk_object_ref (GTK_OBJECT (client)); @@ -2061,25 +2088,42 @@ calendar_model_set_cal_client (CalendarModel *model, CalClient *client, CalObjTy gtk_object_unref (GTK_OBJECT (priv->client)); } - free_objects (model); - priv->client = client; priv->type = type; if (priv->client) { - gtk_signal_connect (GTK_OBJECT (priv->client), "obj_updated", - GTK_SIGNAL_FUNC (obj_updated_cb), model); - gtk_signal_connect (GTK_OBJECT (priv->client), "obj_removed", - GTK_SIGNAL_FUNC (obj_removed_cb), model); - - if (cal_client_get_load_state (priv->client) != CAL_CLIENT_LOAD_LOADED) + if (cal_client_get_load_state (priv->client) == CAL_CLIENT_LOAD_LOADED) + update_query (model); + else gtk_signal_connect (GTK_OBJECT (priv->client), "cal_opened", GTK_SIGNAL_FUNC (cal_opened_cb), model); - else - load_objects (model); } +} - e_table_model_changed (E_TABLE_MODEL (model)); +/** + * calendar_model_set_query: + * @model: A calendar model. + * @sexp: Sexp that defines the query. + * + * Sets the query sexp that a calendar model will use to filter its contents. + **/ +void +calendar_model_set_query (CalendarModel *model, const char *sexp) +{ + CalendarModelPrivate *priv; + + g_return_if_fail (model != NULL); + g_return_if_fail (IS_CALENDAR_MODEL (model)); + g_return_if_fail (sexp != NULL); + + priv = model->priv; + + if (priv->sexp) + g_free (priv->sexp); + + priv->sexp = g_strdup (sexp); + + update_query (model); } @@ -2294,31 +2338,6 @@ calendar_model_set_default_category (CalendarModel *model, } -static void -calendar_model_collect_all_categories (CalendarModel *model) -{ - CalendarModelPrivate *priv; - CalComponent *comp; - int i; - - priv = model->priv; - - /* Destroy the current tree and start from scratch. */ - g_tree_traverse (priv->categories, (GTraverseFunc) g_free, - G_PRE_ORDER, NULL); - g_tree_destroy (priv->categories); - - priv->categories = g_tree_new ((GCompareFunc)strcmp); - - for (i = 0; i < priv->objects->len; i++) { - comp = g_array_index (priv->objects, CalComponent *, i); - calendar_model_collect_categories (model, comp); - } - - gtk_signal_emit (GTK_OBJECT (model), - calendar_model_signals [CATEGORIES_CHANGED]); -} - static gboolean calendar_model_collect_categories (CalendarModel *model, diff --git a/calendar/gui/calendar-model.h b/calendar/gui/calendar-model.h index 5a47d3752e..c06b1f3f48 100644 --- a/calendar/gui/calendar-model.h +++ b/calendar/gui/calendar-model.h @@ -65,6 +65,9 @@ void calendar_model_set_cal_client (CalendarModel *model, CalClient *client, CalObjType type); +void calendar_model_set_query (CalendarModel *model, + const char *sexp); + void calendar_model_set_new_comp_vtype (CalendarModel *model, CalComponentVType vtype); CalComponentVType calendar_model_get_new_comp_vtype (CalendarModel *model); diff --git a/calendar/gui/comp-editor-factory.c b/calendar/gui/comp-editor-factory.c new file mode 100644 index 0000000000..8c32bb3059 --- /dev/null +++ b/calendar/gui/comp-editor-factory.c @@ -0,0 +1,228 @@ +/* Evolution calendar - Component editor factory object + * + * Copyright (C) 2001 Ximian, Inc. + * + * Authors: Federico Mena-Quintero <federico@ximian.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <cal-client/cal-client.h> +#include "comp-editor-factory.h" + + + +/* An client we have open */ +typedef struct { + /* Uri of the calendar, used as key in the clients hash table */ + GnomeVFSURI *uri; + + /* Client of the calendar */ + CalClient *client; + + /* Hash table of components that belong to this client */ + GHashTable *uid_comp_hash; + + /* Number of times this client has been opened */ + int refcount; +} OpenClient; + +/* A component that is being edited */ +typedef struct { + /* Our parent client */ + OpenClient *parent; + + /* UID of the component we are editing, used as the key in the hash table */ + const char *uid; + + /* Component we are editing */ + CalComponent *comp; +} Component; + +/* Private part of the CompEditorFactory structure */ +struct CompEditorFactoryPrivate { + /* Hash table of URI->OpenClient */ + GHashTable *uri_client_hash; +}; + + + +static void comp_editor_factory_class_init (CompEditorFactoryClass *class); +static void comp_editor_factory_init (CompEditorFactory *factory); +static void comp_editor_factory_destroy (GtkObject *object); + +static void impl_editExisting (PortableServer_Servant servant, + const CORBA_char *uri, + const GNOME_Evolution_Calendar_CalObjUID uid, + CORBA_Environment *ev); +static void impl_editNew (PortableServer_Servant servant, + const CORBA_char *uri, + const GNOME_Evolution_Calendar_CalObjType type, + CORBA_Environment *ev); + +static BonoboXObjectClass *parent_class = NULL; + + + +BONOBO_X_TYPE_FUNC_FULL (CompEditorFactory, + GNOME_Evolution_Calendar_CompEditorFactory, + BONOBO_X_OBJECT_TYPE, + comp_editor_factory); + +/* Class initialization function for the component editor factory */ +static void +comp_editor_factory_class_init (CompEditorFactoryClass *class) +{ + GtkObjectClass *object_class; + + object_class = (GtkObjectClass *) class; + + parent_class = gtk_type_class (BONOBO_X_OBJECT_TYPE); + + class->epv.editExisting = impl_editExisting; + class->epv.editNew = impl_editNew; + + object_class->destroy = comp_editor_factory_destroy; +} + +/* Object initialization function for the component editor factory */ +static void +comp_editor_factory_init (CompEditorFactory *factory) +{ + CompEditorFactoryPrivate *priv; + + priv = g_new (CompEditorFactoryPrivate, 1); + + priv->uri_client_hash = g_hash_table_new (gnome_vfs_uri_hash, gnome_vfs_uri_hequal); +} + +/* Used from g_hash_table_foreach(); frees a client structure */ +static void +free_client_cb (gpointer key, gpointer value, gpointer data) +{ + OpenClient *oc; + + oc = value; + + gnome_vfs_uri_unref (oc->uri); + cal_client_unref (oc->client); + g_hash_table_destroy (oc->uid_comp_hash); + + g_free (oc); +} + +/* Destroy handler for the component editor factory */ +static void +comp_editor_factory_destroy (GtkObject *object) +{ + CompEditorFactory *factory; + CompEditorFactoryPrivate *priv; + + g_return_if_fail (object != NULL); + g_return_if_fail (IS_COMP_EDITOR_FACTORY (object)); + + factory = COMP_EDITOR_FACTORY (object); + priv = factory->priv; + + g_hash_table_foreach (priv->uri_client_hash, free_client_cb, NULL); + g_hash_table_destroy (priv->uri_client_hash); + priv->uri_client_hash = NULL; + + g_free (priv); + factory->priv = NULL; + + if (GTK_OBJECT_CLASS (parent_class)->destroy) + (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); +} + + + +/* Creates a new OpenClient structure by synchronously (!) opening a calendar + * client. Returns NULL if it could not open it. + */ +static OpenClient * +open_client (GnomeVFSURI *uri) +{ + CalClient *client; + + client = cal_client_new (); + if (!client) + return NULL; + + gtk_signal_connect (GTK_OBJECT (client), "cal_opened", + GTK_SIGNAL_FUNC (cal_opened_cb), NULL); + + oc = g_new (OpenClient, 1); + oc->uri = uri; + oc->client = client; + oc->uid_comp_hash = g_hash_table_new (g_str_hash, g_str_equal); + oc->refcount = 1; + +} + +static void +impl_editExisting (PortableServer_Servant servant, + const CORBA_char *str_uri, + const GNOME_Evolution_Calendar_CalObjUID uid, + CORBA_Environment *ev) +{ + CompEditorFactory *factory; + CompEditorFactoryPrivate *priv; + GnomeVFSURI *uri; + OpenClient *oc; + CalClient *client; + Component *c; + + factory = COMP_EDITOR_FACTORY (bonobo_object_from_servant (servant)); + priv = factory->priv; + + /* Look up the client */ + + uri = gnome_vfs_uri_new (str_uri); + if (!uri) { + CORBA_exception_set (ev, CORBA_USER_EXCEPTION, + ex_GNOME_Evolution_Calendar_CompEditorFactory_InvalidURI, + NULL); + return; + } + + oc = g_hash_table_lookup (priv->uri_client_hash, uri); + if (oc) + client = oc->client; + else { + oc = open_client (uri); + if (!oc) { + gnome_vfs_uri_unref (uri); + + CORBA_exception_set ( + ev, CORBA_USER_EXCEPTION, + ex_GNOME_Evolution_Calendar_CompEditorFactory_BackendContactError, + NULL); + return; + } + + client = oc->client; + } + + gnome_vfs_uri_unref (uri); + + /* Look up the component */ + + c = g_hash_table_lookup (oc->uid_comp_hash, +} diff --git a/calendar/gui/comp-editor-factory.h b/calendar/gui/comp-editor-factory.h new file mode 100644 index 0000000000..3e8387d6a7 --- /dev/null +++ b/calendar/gui/comp-editor-factory.h @@ -0,0 +1,59 @@ +/* Evolution calendar - Component editor factory object + * + * Copyright (C) 2001 Ximian, Inc. + * + * Authors: Federico Mena-Quintero <federico@ximian.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef COMP_EDITOR_FACTORY_H +#define COMP_EDITOR_FACTORY_H + +#include <bonobo/bonobo-xobject.h> +#include "evolution-calendar.h" + + + +#define TYPE_COMP_EDITOR_FACTORY (comp_editor_factory_get_type ()) +#define COMP_EDITOR_FACTORY(obj) (GTK_CHECK_CAST ((obj), TYPE_COMP_EDITOR_FACTORY, \ + CompEditorFactory)) +#define COMP_EDITOR_FACTORY_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), \ + TYPE_COMP_EDITOR_FACTORY, CompEditorFactoryClass)) +#define IS_COMP_EDITOR_FACTORY(obj) (GTK_CHECK_TYPE ((obj), TYPE_COMP_EDITOR_FACTORY)) +#define IS_COMP_EDITOR_FACTORY_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), TYPE_COMP_EDITOR_FACTORY)) + +typedef struct CompEditorFactoryPrivate CompEditorFactoryPrivate; + +typedef struct { + BonoboXObject xobject; + + /* Private data */ + CompEditorFactoryPrivate *priv; +} CompEditorFactory; + +typedef struct { + BonoboXObjectClass parent_class; + + POA_GNOME_Evolution_Calendar_CompEditorFactory__epv epv; +} CompEditorFactoryClass; + +GtkType comp_editor_factory_get_type (void); + +CompEditorFactory *comp_editor_factory_new (void); + + + +#endif diff --git a/calendar/gui/e-calendar-table.c b/calendar/gui/e-calendar-table.c index 999b64d99f..fc86f5e4f9 100644 --- a/calendar/gui/e-calendar-table.c +++ b/calendar/gui/e-calendar-table.c @@ -82,18 +82,6 @@ static gint e_calendar_table_on_key_press (ETable *table, GdkEventKey *event, ECalendarTable *cal_table); -static void e_calendar_table_apply_filter (ECalendarTable *cal_table); -static void e_calendar_table_on_model_changed (ETableModel *model, - ECalendarTable *cal_table); -static void e_calendar_table_on_rows_inserted (ETableModel *model, - int row, - int count, - ECalendarTable *cal_table); -static void e_calendar_table_on_rows_deleted (ETableModel *model, - int row, - int count, - ECalendarTable *cal_table); - static void selection_clear_event (GtkWidget *invisible, GdkEventSelection *event, ECalendarTable *cal_table); @@ -252,39 +240,11 @@ e_calendar_table_init (ECalendarTable *cal_table) ETableExtras *extras; gint i; GdkPixbuf *pixbuf; - GdkColormap *colormap; - gboolean success[E_CALENDAR_TABLE_COLOR_LAST]; - gint nfailed; GList *strings; - /* Allocate the colors we need. */ - - colormap = gtk_widget_get_colormap (GTK_WIDGET (cal_table)); - - cal_table->colors[E_CALENDAR_TABLE_COLOR_OVERDUE].red = 65535; - cal_table->colors[E_CALENDAR_TABLE_COLOR_OVERDUE].green = 0; - cal_table->colors[E_CALENDAR_TABLE_COLOR_OVERDUE].blue = 0; - - nfailed = gdk_colormap_alloc_colors (colormap, cal_table->colors, - E_CALENDAR_TABLE_COLOR_LAST, - FALSE, TRUE, success); - if (nfailed) - g_warning ("Failed to allocate all colors"); - /* Create the model */ cal_table->model = calendar_model_new (); - cal_table->subset_model = e_table_subset_variable_new (E_TABLE_MODEL (cal_table->model)); - - gtk_signal_connect (GTK_OBJECT (cal_table->model), "model_changed", - GTK_SIGNAL_FUNC (e_calendar_table_on_model_changed), - cal_table); - gtk_signal_connect (GTK_OBJECT (cal_table->model), "model_rows_inserted", - GTK_SIGNAL_FUNC (e_calendar_table_on_rows_inserted), - cal_table); - gtk_signal_connect (GTK_OBJECT (cal_table->model), "model_rows_deleted", - GTK_SIGNAL_FUNC (e_calendar_table_on_rows_deleted), - cal_table); /* Create the header columns */ @@ -472,7 +432,7 @@ e_calendar_table_init (ECalendarTable *cal_table) /* Create the table */ - table = e_table_scrolled_new_from_spec_file (cal_table->subset_model, + table = e_table_scrolled_new_from_spec_file (E_TABLE_MODEL (cal_table->model), extras, EVOLUTION_ETSPECDIR "/e-calendar-table.etspec", NULL); @@ -566,9 +526,6 @@ e_calendar_table_destroy (GtkObject *object) gtk_object_unref (GTK_OBJECT (cal_table->model)); cal_table->model = NULL; - gtk_object_unref (GTK_OBJECT (cal_table->subset_model)); - cal_table->subset_model = NULL; - if (cal_table->invisible) gtk_widget_destroy (cal_table->invisible); if (cal_table->clipboard_selection) @@ -577,15 +534,6 @@ e_calendar_table_destroy (GtkObject *object) GTK_OBJECT_CLASS (parent_class)->destroy (object); } - -void -e_calendar_table_set_cal_client (ECalendarTable *cal_table, - CalClient *client) -{ - calendar_model_set_cal_client (cal_table->model, client, - CALOBJ_TYPE_TODO); -} - /** * e_calendar_table_get_table: * @cal_table: A calendar table. @@ -724,6 +672,8 @@ e_calendar_table_delete_selected (ECalendarTable *cal_table) else comp = NULL; + /* FIXME: this may be something other than a TODO component */ + if (delete_component_dialog (comp, n_selected, CAL_COMPONENT_TODO, GTK_WIDGET (cal_table))) delete_selected_components (cal_table); } @@ -1011,141 +961,6 @@ e_calendar_table_save_state (ECalendarTable *cal_table, } -void -e_calendar_table_set_filter_func (ECalendarTable *cal_table, - ECalendarTableFilterFunc filter_func, - gpointer filter_data, - GDestroyNotify filter_data_destroy) -{ - g_return_if_fail (E_IS_CALENDAR_TABLE (cal_table)); - - if (cal_table->filter_func == filter_func - && cal_table->filter_data == filter_data - && cal_table->filter_data_destroy == filter_data_destroy) - return; - - if (cal_table->filter_data_destroy) - (*cal_table->filter_data_destroy) (cal_table->filter_data); - - cal_table->filter_func = filter_func; - cal_table->filter_data = filter_data; - cal_table->filter_data_destroy = filter_data_destroy; - - e_calendar_table_apply_filter (cal_table); -} - - -static void -e_calendar_table_apply_filter (ECalendarTable *cal_table) -{ - ETableSubsetVariable *etssv; - CalComponent *comp; - gint rows, row; - - etssv = E_TABLE_SUBSET_VARIABLE (cal_table->subset_model); - - /* Make sure that any edits get saved first. */ - e_table_model_pre_change (cal_table->subset_model); - - /* FIXME: A hack to remove all the existing rows quickly. */ - E_TABLE_SUBSET (cal_table->subset_model)->n_map = 0; - - if (cal_table->filter_func == NULL) { - e_table_subset_variable_add_all (etssv); - } else { - rows = e_table_model_row_count (E_TABLE_MODEL (cal_table->model)); - for (row = 0; row < rows; row++) { - comp = calendar_model_get_component (cal_table->model, - row); - - if ((*cal_table->filter_func) (cal_table, comp, - cal_table->filter_data)) - e_table_subset_variable_add (etssv, row); - } - } - - e_table_model_changed (cal_table->subset_model); -} - - -gboolean -e_calendar_table_filter_by_category (ECalendarTable *cal_table, - CalComponent *comp, - gpointer filter_data) -{ - GSList *categories_list, *elem; - gboolean retval = FALSE; - - cal_component_get_categories_list (comp, &categories_list); - - for (elem = categories_list; elem; elem = elem->next) { - if (retval == FALSE - && !strcmp ((char*) elem->data, (char*) filter_data)) - retval = TRUE; - g_free (elem->data); - } - - g_slist_free (categories_list); - - return retval; -} - - -static void -e_calendar_table_on_model_changed (ETableModel *model, - ECalendarTable *cal_table) -{ - e_calendar_table_apply_filter (cal_table); -} - - -static void -e_calendar_table_on_rows_inserted (ETableModel *model, - int row, - int count, - ECalendarTable *cal_table) -{ - int i; - - for (i = 0; i < count; i++) { - gboolean add_row; - - add_row = FALSE; - - if (cal_table->filter_func) { - CalComponent *comp; - - comp = calendar_model_get_component (cal_table->model, row + i); - g_assert (comp != NULL); - - add_row = (* cal_table->filter_func) (cal_table, comp, - cal_table->filter_data); - } else - add_row = TRUE; - - if (add_row) { - ETableSubsetVariable *etssv; - - etssv = E_TABLE_SUBSET_VARIABLE (cal_table->subset_model); - - e_table_subset_variable_increment (etssv, row, 1); - e_table_subset_variable_add (etssv, row); - } - } -} - - -static void -e_calendar_table_on_rows_deleted (ETableModel *model, - int row, - int count, - ECalendarTable *cal_table) -{ - /* We just reapply the filter since we aren't too bothered about - being efficient. It doesn't happen often. */ - e_calendar_table_apply_filter (cal_table); -} - static void invisible_destroyed (GtkWidget *invisible, ECalendarTable *cal_table) { diff --git a/calendar/gui/e-calendar-table.h b/calendar/gui/e-calendar-table.h index 5ab32f3c18..c7e83e5d80 100644 --- a/calendar/gui/e-calendar-table.h +++ b/calendar/gui/e-calendar-table.h @@ -39,14 +39,6 @@ extern "C" { * Used for calendar events and tasks. */ -/* These index our colors array. */ -typedef enum -{ - E_CALENDAR_TABLE_COLOR_OVERDUE, - - E_CALENDAR_TABLE_COLOR_LAST -} ECalendarTableColors; - #define E_CALENDAR_TABLE(obj) GTK_CHECK_CAST (obj, e_calendar_table_get_type (), ECalendarTable) #define E_CALENDAR_TABLE_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, e_calendar_table_get_type (), ECalendarTableClass) @@ -57,29 +49,14 @@ typedef struct _ECalendarTable ECalendarTable; typedef struct _ECalendarTableClass ECalendarTableClass; -typedef gboolean (*ECalendarTableFilterFunc) (ECalendarTable *cal_table, - CalComponent *comp, - gpointer data); - struct _ECalendarTable { GtkTable table; - /* This is the underlying model which contains all the tasks/events. */ + /* The model that we use */ CalendarModel *model; - /* This is the model that we use when filtering the tasks/events. */ - ETableModel *subset_model; - GtkWidget *etable; - - /* Colors for drawing. */ - GdkColor colors[E_CALENDAR_TABLE_COLOR_LAST]; - - /* Data for filtering the Tasks. */ - ECalendarTableFilterFunc filter_func; - gpointer filter_data; - GDestroyNotify filter_data_destroy; /* The ECell used to view & edit dates. */ ECellDateEdit *dates_cell; @@ -101,9 +78,6 @@ GtkWidget* e_calendar_table_new (void); CalendarModel *e_calendar_table_get_model (ECalendarTable *cal_table); -void e_calendar_table_set_cal_client (ECalendarTable *cal_table, - CalClient *client); - ETable *e_calendar_table_get_table (ECalendarTable *cal_table); void e_calendar_table_delete_selected (ECalendarTable *cal_table); @@ -120,14 +94,6 @@ void e_calendar_table_load_state (ECalendarTable *cal_table, void e_calendar_table_save_state (ECalendarTable *cal_table, gchar *filename); -void e_calendar_table_set_filter_func (ECalendarTable *cal_table, - ECalendarTableFilterFunc filter_func, - gpointer filter_data, - GDestroyNotify filter_data_destroy); -gboolean e_calendar_table_filter_by_category (ECalendarTable *cal_table, - CalComponent *comp, - gpointer filter_data); - #ifdef __cplusplus } diff --git a/calendar/gui/e-tasks.c b/calendar/gui/e-tasks.c index dbf7a7d779..e0a0b8ef8f 100644 --- a/calendar/gui/e-tasks.c +++ b/calendar/gui/e-tasks.c @@ -32,6 +32,7 @@ #include <gal/menus/gal-view-etable.h> #include "widgets/menus/gal-view-menus.h" #include "dialogs/task-editor.h" +#include "cal-search-bar.h" #include "calendar-config.h" #include "component-factory.h" @@ -50,10 +51,17 @@ struct _ETasksPrivate { /* The ECalendarTable showing the tasks. */ GtkWidget *tasks_view; + /* Search bar for tasks and the current sexp */ + GtkWidget *search_bar; + char *sexp; + /* The option menu showing the categories, and the popup menu. */ GtkWidget *categories_option_menu; GtkWidget *categories_menu; + /* The category that is currently selected, used to filter out items */ + char *category; + /* View collection and the view menus handler */ GalViewCollection *view_collection; GalViewMenus *view_menus; @@ -131,6 +139,9 @@ e_tasks_init (ETasks *tasks) priv = g_new0 (ETasksPrivate, 1); tasks->priv = priv; + priv->sexp = g_strdup ("#t"); /* Match all */ + priv->category = NULL; + setup_widgets (tasks); } @@ -148,6 +159,51 @@ table_selection_change_cb (ETable *etable, gpointer data) n_selected); } +/* Updates the query in the table model by composing the currently selected + * category with the current sexp. + */ +static void +update_query (ETasks *tasks) +{ + ETasksPrivate *priv; + char *new_sexp; + gboolean free_new_sexp; + CalendarModel *model; + + priv = tasks->priv; + + g_assert (priv->sexp != NULL); + + if (priv->category) { + new_sexp = g_strdup_printf ("(and %s (has-categories? \"%s\"))", + priv->sexp, priv->category); + free_new_sexp = TRUE; + } else { + new_sexp = priv->sexp; + free_new_sexp = FALSE; + } + + model = e_calendar_table_get_model (E_CALENDAR_TABLE (priv->tasks_view)); + calendar_model_set_query (model, new_sexp); + + if (free_new_sexp) + g_free (new_sexp); +} + +/* Callback used when the sexp in the search bar changes */ +static void +search_bar_sexp_changed_cb (CalSearchBar *cal_search, const char *sexp, gpointer data) +{ + ETasks *tasks; + ETasksPrivate *priv; + + tasks = E_TASKS (data); + priv = tasks->priv; + + priv->sexp = g_strdup (sexp); + update_query (tasks); +} + #define E_TASKS_TABLE_DEFAULT_STATE \ "<?xml version=\"1.0\"?>" \ "<ETableState>" \ @@ -169,11 +225,17 @@ setup_widgets (ETasks *tasks) priv = tasks->priv; - hbox = gtk_hbox_new (FALSE, 0); + hbox = gtk_hbox_new (FALSE, GNOME_PAD_SMALL); gtk_widget_show (hbox); gtk_table_attach (GTK_TABLE (tasks), hbox, 0, 1, 0, 1, GTK_EXPAND | GTK_FILL, 0, 0, 0); + priv->search_bar = cal_search_bar_new (); + gtk_signal_connect (GTK_OBJECT (priv->search_bar), "sexp_changed", + GTK_SIGNAL_FUNC (search_bar_sexp_changed_cb), tasks); + gtk_box_pack_start (GTK_BOX (hbox), priv->search_bar, TRUE, TRUE, 0); + gtk_widget_show (priv->search_bar); + priv->categories_option_menu = gtk_option_menu_new (); gtk_widget_show (priv->categories_option_menu); gtk_box_pack_end (GTK_BOX (hbox), priv->categories_option_menu, @@ -215,6 +277,7 @@ GtkWidget * e_tasks_construct (ETasks *tasks) { ETasksPrivate *priv; + CalendarModel *model; g_return_val_if_fail (tasks != NULL, NULL); g_return_val_if_fail (E_IS_TASKS (tasks), NULL); @@ -232,8 +295,10 @@ e_tasks_construct (ETasks *tasks) gtk_signal_connect (GTK_OBJECT (priv->client), "obj_removed", GTK_SIGNAL_FUNC (obj_removed_cb), tasks); - e_calendar_table_set_cal_client (E_CALENDAR_TABLE (priv->tasks_view), - priv->client); + model = e_calendar_table_get_model (E_CALENDAR_TABLE (priv->tasks_view)); + g_assert (model != NULL); + + calendar_model_set_cal_client (model, priv->client, CALOBJ_TYPE_TODO); return GTK_WIDGET (tasks); } @@ -271,6 +336,15 @@ e_tasks_destroy (GtkObject *object) tasks = E_TASKS (object); priv = tasks->priv; + g_assert (priv->sexp != NULL); + g_free (priv->sexp); + priv->sexp = NULL; + + if (priv->category) { + g_free (priv->category); + priv->category = NULL; + } + /* Save the ETable layout. */ config_filename = e_tasks_get_config_filename (tasks); e_calendar_table_save_state (E_CALENDAR_TABLE (priv->tasks_view), @@ -497,7 +571,6 @@ e_tasks_delete_selected (ETasks *tasks) e_calendar_table_delete_selected (cal_table); } - static void e_tasks_on_filter_selected (GtkMenuShell *menu_shell, ETasks *tasks) @@ -518,16 +591,18 @@ e_tasks_on_filter_selected (GtkMenuShell *menu_shell, cal_table = E_CALENDAR_TABLE (priv->tasks_view); model = cal_table->model; + if (priv->category) + g_free (priv->category); + if (!strcmp (category, _("All"))) { calendar_model_set_default_category (model, NULL); - e_calendar_table_set_filter_func (cal_table, NULL, NULL, - NULL); + priv->category = NULL; } else { calendar_model_set_default_category (model, category); - e_calendar_table_set_filter_func (cal_table, - e_calendar_table_filter_by_category, - g_strdup (category), g_free); + priv->category = g_strdup (category); } + + update_query (tasks); } diff --git a/calendar/gui/gnome-cal.c b/calendar/gui/gnome-cal.c index 7068fbe1fe..9aaaefb396 100644 --- a/calendar/gui/gnome-cal.c +++ b/calendar/gui/gnome-cal.c @@ -40,8 +40,6 @@ #include <gal/e-paned/e-vpaned.h> #include <cal-util/timeutil.h> #include "widgets/menus/gal-view-menus.h" -#include "widgets/misc/e-search-bar.h" -#include "widgets/misc/e-filter-bar.h" #include "dialogs/event-editor.h" #include "e-calendar-table.h" #include "e-day-view.h" @@ -49,6 +47,7 @@ #include "evolution-calendar.h" #include "gnome-cal.h" #include "component-factory.h" +#include "cal-search-bar.h" #include "calendar-commands.h" #include "calendar-config.h" #include "calendar-view.h" @@ -201,28 +200,6 @@ gnome_calendar_class_init (GnomeCalendarClass *class) object_class->destroy = gnome_calendar_destroy; } -static ESearchBarItem search_menu_items[] = { - E_FILTERBAR_RESET, - { NULL, -1 } -}; - -enum { - SEARCH_ANY_FIELD_CONTAINS, - SEARCH_SUMMARY_CONTAINS, - SEARCH_DESCRIPTION_CONTAINS, - SEARCH_COMMENT_CONTAINS, - SEARCH_HAS_CATEGORY -}; - -static ESearchBarItem search_option_items[] = { - { N_("Any field contains"), SEARCH_ANY_FIELD_CONTAINS }, - { N_("Summary contains"), SEARCH_SUMMARY_CONTAINS }, - { N_("Description contains"), SEARCH_DESCRIPTION_CONTAINS }, - { N_("Comment contains"), SEARCH_COMMENT_CONTAINS }, - { N_("Has category"), SEARCH_HAS_CATEGORY }, - { NULL, -1 } -}; - /** * gnome_calendar_set_query: * @gcal: A calendar. @@ -264,88 +241,6 @@ gnome_calendar_set_query (GnomeCalendar *gcal, char *sexp) } } -/* Sets the query string to be (contains? "field" "text") */ -static void -set_query_contains (GnomeCalendar *gcal, const char *field, const char *text) -{ - char *sexp; - - sexp = g_strdup_printf ("(contains? \"%s\" \"%s\")", field, text); - gnome_calendar_set_query (gcal, sexp); - g_free (sexp); -} - -/* Callback used when the query string is changed in the search bar */ -static void -search_bar_query_changed_cb (ESearchBar *search_bar, gpointer data) -{ - GnomeCalendar *gcal; - int item; - char *text; - - gcal = GNOME_CALENDAR (data); - - item = e_search_bar_get_option_choice (search_bar); - text = e_search_bar_get_text (search_bar); - - if (!text) - return; /* This is an error in the UTF8 conversion, not an empty string! */ - - switch (item) { - case SEARCH_ANY_FIELD_CONTAINS: - set_query_contains (gcal, "any", text); - break; - - case SEARCH_SUMMARY_CONTAINS: - set_query_contains (gcal, "summary", text); - break; - - case SEARCH_DESCRIPTION_CONTAINS: - set_query_contains (gcal, "description", text); - break; - - case SEARCH_COMMENT_CONTAINS: - set_query_contains (gcal, "comment", text); - break; - - case SEARCH_HAS_CATEGORY: { - char *sexp; - - sexp = g_strdup_printf ("(has-categories? \"%s\")", text); - gnome_calendar_set_query (gcal, sexp); - g_free (sexp); - break; - } - - default: - g_assert_not_reached (); - } - - g_free (text); -} - -/* Callback used when a menu item is activated in the search bar */ -static void -search_bar_menu_activated_cb (ESearchBar *search_bar, int item, gpointer data) -{ - GnomeCalendar *gcal; - - gcal = GNOME_CALENDAR (data); - - switch (item) { - case E_FILTERBAR_RESET_ID: - gnome_calendar_set_query (gcal, "#t"); /* match all */ - /* FIXME: should we change the rest of the search bar so that - * the user sees that he selected "show all" instead of some - * type/text search combination? - */ - break; - - default: - g_assert_not_reached (); - } -} - /* Returns the current time, for the ECalendarItem. */ static struct tm get_current_time (ECalendarItem *calitem, gpointer data) @@ -372,6 +267,16 @@ get_current_time (ECalendarItem *calitem, gpointer data) return tmp_tm; } +/* Callback used when the sexp changes in the calendar search bar */ +static void +search_bar_sexp_changed_cb (CalSearchBar *cal_search, const char *sexp, gpointer data) +{ + GnomeCalendar *gcal; + + gcal = GNOME_CALENDAR (data); + gnome_calendar_set_query (gcal, sexp); +} + static void setup_widgets (GnomeCalendar *gcal) { @@ -382,11 +287,9 @@ setup_widgets (GnomeCalendar *gcal) priv = gcal->priv; - priv->search_bar = e_search_bar_new (search_menu_items, search_option_items); - gtk_signal_connect (GTK_OBJECT (priv->search_bar), "query_changed", - GTK_SIGNAL_FUNC (search_bar_query_changed_cb), gcal); - gtk_signal_connect (GTK_OBJECT (priv->search_bar), "menu_activated", - GTK_SIGNAL_FUNC (search_bar_menu_activated_cb), gcal); + priv->search_bar = cal_search_bar_new (); + gtk_signal_connect (GTK_OBJECT (priv->search_bar), "sexp_changed", + GTK_SIGNAL_FUNC (search_bar_sexp_changed_cb), gcal); gtk_widget_show (priv->search_bar); gtk_box_pack_start (GTK_BOX (gcal), priv->search_bar, FALSE, FALSE, 0); @@ -1138,6 +1041,7 @@ gnome_calendar_construct (GnomeCalendar *gcal) { GnomeCalendarPrivate *priv; GnomeCalendarViewType view_type; + CalendarModel *model; g_return_val_if_fail (gcal != NULL, NULL); g_return_val_if_fail (GNOME_IS_CALENDAR (gcal), NULL); @@ -1177,8 +1081,10 @@ gnome_calendar_construct (GnomeCalendar *gcal) gtk_signal_connect (GTK_OBJECT (priv->task_pad_client), "cal_opened", GTK_SIGNAL_FUNC (cal_opened_cb), gcal); - e_calendar_table_set_cal_client (E_CALENDAR_TABLE (priv->todo), - priv->task_pad_client); + model = e_calendar_table_get_model (E_CALENDAR_TABLE (priv->todo)); + g_assert (model != NULL); + + calendar_model_set_cal_client (model, priv->task_pad_client, CALOBJ_TYPE_TODO); /* Get the default view to show. */ view_type = calendar_config_get_default_view (); diff --git a/calendar/gui/itip-utils.c b/calendar/gui/itip-utils.c index 57212106c6..7c3add0dd1 100644 --- a/calendar/gui/itip-utils.c +++ b/calendar/gui/itip-utils.c @@ -34,6 +34,7 @@ #include <gal/util/e-util.h> #include <ical.h> #include <Evolution-Composer.h> +#include "cal-util/cal-util.h" #include "itip-utils.h" #define GNOME_EVOLUTION_COMPOSER_OAFIID "OAFIID:GNOME_Evolution_Mail_Composer" |