diff options
Diffstat (limited to 'calendar')
-rw-r--r-- | calendar/ChangeLog | 37 | ||||
-rw-r--r-- | calendar/gui/calendar-model.c | 164 | ||||
-rw-r--r-- | calendar/gui/calendar-model.h | 8 | ||||
-rw-r--r-- | calendar/gui/dialogs/task-editor-dialog.glade | 3 | ||||
-rw-r--r-- | calendar/gui/dialogs/task-editor-dialog.glade.h | 26 | ||||
-rw-r--r-- | calendar/gui/dialogs/task-editor.c | 1 | ||||
-rw-r--r-- | calendar/gui/dialogs/task-editor.h | 1 | ||||
-rw-r--r-- | calendar/gui/dialogs/task-page.glade | 3 | ||||
-rw-r--r-- | calendar/gui/e-calendar-table.c | 326 | ||||
-rw-r--r-- | calendar/gui/e-calendar-table.h | 23 | ||||
-rw-r--r-- | calendar/gui/e-day-view.c | 4 | ||||
-rw-r--r-- | calendar/gui/e-tasks.c | 268 | ||||
-rw-r--r-- | calendar/gui/e-tasks.h | 4 | ||||
-rw-r--r-- | calendar/gui/e-week-view.c | 1 | ||||
-rw-r--r-- | calendar/gui/gnome-cal.c | 167 | ||||
-rw-r--r-- | calendar/gui/tasks-control.c | 3 | ||||
-rw-r--r-- | calendar/gui/widget-util.c | 7 |
17 files changed, 836 insertions, 210 deletions
diff --git a/calendar/ChangeLog b/calendar/ChangeLog index 779e6aa30b..95ed315159 100644 --- a/calendar/ChangeLog +++ b/calendar/ChangeLog @@ -1,3 +1,40 @@ +2001-01-14 Damon Chaplin <damon@helixcode.com> + + * gui/dialogs/task-editor.[hc]: moved #include + <cal-client/cal-client.h> to the .h file. + + * gui/e-tasks.c: load & save the Tasks folders' ETable layout. + Added an option menu to filter tasks by category. + + * gui/gnome-cal.c: use the "Tasks" folder for the TaskPad. + (We may make the actual tasks folder shown a per-calendar option.) + + * gui/tasks-control.c (tasks_control_new_task_cmd): added support for + the New Task icon on the toolbar. + + * gui/e-calendar-table.[hc]: we now use an ETableSubsetVariable model + to filter the tasks by a category. And tidied up a little. + + * gui/calendar-model.[hc]: added way to get all the categories used by + the tasks, so we can show an option menu of them. Also a signal which + is emitted when they are changed. + Also allows a default category to be set, which is used to initialize + the 'click-to-add' row. + Also made sure the initialize_value()/get_value() functions don't + return NULL since that can cause a SEGV. + + * gui/e-week-view.c: + * gui/e-day-view.c: set the "fill_color_rgba" arg of the EText items + to black since it doesn't seem to set up a default color properly. + Hopefully this fixes the bug on Solaris where the items appear with + strange colors. + + * gui/widget-util.c (date_edit_new): use the calendar_config function + to set most of the options. It wasn't setting the 12/24 hour option + before. + + * gui/dialogs/task-editor-dialog.glade: added "Undefined" priority. + 2001-01-12 Ettore Perazzoli <ettore@helixcode.com> * gui/component-factory.c (factory_fn): Pass NULL as the diff --git a/calendar/gui/calendar-model.c b/calendar/gui/calendar-model.c index 7168f2714b..2fb4f89bf0 100644 --- a/calendar/gui/calendar-model.c +++ b/calendar/gui/calendar-model.c @@ -23,12 +23,6 @@ #include <config.h> -#include <math.h> -#include <ctype.h> -#include <gnome.h> -#include <cal-util/timeutil.h> -#include "calendar-model.h" -#include "calendar-commands.h" /* We need this for strptime. */ #define _XOPEN_SOURCE 500 @@ -38,6 +32,14 @@ #undef _XOPEN_SOURCE #undef __USE_XOPEN +#include <math.h> +#include <ctype.h> +#include <gnome.h> +#include <cal-util/timeutil.h> +#include "calendar-model.h" +#include "calendar-commands.h" + + /* Private part of the ECalendarModel structure */ @@ -59,8 +61,24 @@ struct _CalendarModelPrivate { /* HACK: so that ETable can do its stupid append_row() thing */ guint appending_row : 1; + + /* The default category to use when creating new tasks, e.g. when the + filter is set to a certain category we use that category when + creating a new task. */ + gchar *default_category; + + /* A balanced tree of the categories used by all the tasks/events. */ + GTree *categories; +}; + +enum { + CATEGORIES_CHANGED, + + LAST_SIGNAL }; +static gint calendar_model_signals [LAST_SIGNAL] = { 0 }; + static void calendar_model_class_init (CalendarModelClass *class); @@ -85,6 +103,9 @@ 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); static ETableModelClass *parent_class; @@ -134,6 +155,17 @@ calendar_model_class_init (CalendarModelClass *class) parent_class = gtk_type_class (E_TABLE_MODEL_TYPE); + calendar_model_signals [CATEGORIES_CHANGED] = + gtk_signal_new ("categories-changed", + GTK_RUN_LAST, object_class->type, + GTK_SIGNAL_OFFSET (CalendarModelClass, + categories_changed), + gtk_signal_default_marshaller, + GTK_TYPE_NONE, 0); + + gtk_object_class_add_signals (object_class, calendar_model_signals, + LAST_SIGNAL); + object_class->destroy = calendar_model_destroy; etm_class->column_count = calendar_model_column_count; @@ -149,6 +181,8 @@ calendar_model_class_init (CalendarModelClass *class) #if 0 etm_class->value_to_string = calendar_model_value_to_string; #endif + + class->categories_changed = NULL; } /* Object initialization function for the calendar table model */ @@ -163,6 +197,8 @@ calendar_model_init (CalendarModel *model) priv->objects = g_array_new (FALSE, TRUE, sizeof (CalComponent *)); priv->uid_index_hash = g_hash_table_new (g_str_hash, g_str_equal); priv->use_24_hour_format = TRUE; + + priv->categories = g_tree_new ((GCompareFunc)strcmp); } /* Called from g_hash_table_foreach_remove(), frees a stored UID->index @@ -232,6 +268,14 @@ calendar_model_destroy (GtkObject *object) g_array_free (priv->objects, TRUE); priv->objects = NULL; + g_free (priv->default_category); + + /* We only need to free the first argument, the key, so g_free will do. + */ + g_tree_traverse (priv->categories, (GTraverseFunc) g_free, + G_PRE_ORDER, NULL); + g_tree_destroy (priv->categories); + /* Free the private structure */ g_free (priv); @@ -307,7 +351,7 @@ get_categories (CalComponent *comp) cal_component_get_categories (comp, &categories); - return g_strdup (categories); + return categories ? (char*) categories : ""; } /* Returns a string based on the CLASSIFICATION property of a calendar component */ @@ -336,7 +380,7 @@ get_classification (CalComponent *comp) default: g_assert_not_reached (); - return NULL; + return ""; } } @@ -1142,6 +1186,10 @@ calendar_model_set_value_at (ETableModel *etm, int col, int row, const void *val switch (col) { case CAL_COMPONENT_FIELD_CATEGORIES: set_categories (comp, value); + if (calendar_model_collect_categories (model, comp)) { + gtk_signal_emit (GTK_OBJECT (model), + calendar_model_signals [CATEGORIES_CHANGED]); + } break; /* FIXME: CLASSIFICATION requires an option menu cell renderer */ @@ -1313,11 +1361,7 @@ calendar_model_duplicate_value (ETableModel *etm, int col, const void *value) switch (col) { case CAL_COMPONENT_FIELD_CATEGORIES: - return dup_string (value); - case CAL_COMPONENT_FIELD_CLASSIFICATION: - return (void *) value; - case CAL_COMPONENT_FIELD_COMPLETED: case CAL_COMPONENT_FIELD_DTEND: case CAL_COMPONENT_FIELD_DTSTART: @@ -1326,11 +1370,7 @@ calendar_model_duplicate_value (ETableModel *etm, int col, const void *value) case CAL_COMPONENT_FIELD_PERCENT: case CAL_COMPONENT_FIELD_PRIORITY: case CAL_COMPONENT_FIELD_SUMMARY: - return dup_string (value); - case CAL_COMPONENT_FIELD_TRANSPARENCY: - return (void *) value; - case CAL_COMPONENT_FIELD_URL: return dup_string (value); @@ -1402,15 +1442,17 @@ init_string (void) static void * calendar_model_initialize_value (ETableModel *etm, int col) { + CalendarModel *model; + g_return_val_if_fail (col >= 0 && col < CAL_COMPONENT_FIELD_NUM_FIELDS, NULL); + model = CALENDAR_MODEL (etm); + switch (col) { case CAL_COMPONENT_FIELD_CATEGORIES: - return init_string (); + return g_strdup (model->priv->default_category ? model->priv->default_category : ""); case CAL_COMPONENT_FIELD_CLASSIFICATION: - return NULL; - case CAL_COMPONENT_FIELD_COMPLETED: case CAL_COMPONENT_FIELD_DTEND: case CAL_COMPONENT_FIELD_DTSTART: @@ -1419,11 +1461,7 @@ calendar_model_initialize_value (ETableModel *etm, int col) case CAL_COMPONENT_FIELD_PERCENT: case CAL_COMPONENT_FIELD_PRIORITY: case CAL_COMPONENT_FIELD_SUMMARY: - return init_string (); - case CAL_COMPONENT_FIELD_TRANSPARENCY: - return NULL; - case CAL_COMPONENT_FIELD_URL: return init_string (); @@ -1506,8 +1544,10 @@ cal_loaded_cb (CalClient *client, e_table_model_pre_change (E_TABLE_MODEL (model)); - if (status == CAL_CLIENT_LOAD_SUCCESS) + if (status == CAL_CLIENT_LOAD_SUCCESS) { load_objects (model); + calendar_model_collect_all_categories (model); + } e_table_model_changed (E_TABLE_MODEL (model)); } @@ -1980,3 +2020,79 @@ calendar_model_set_use_24_hour_format (CalendarModel *model, } } + +void +calendar_model_set_default_category (CalendarModel *model, + gchar *default_category) +{ + g_return_if_fail (IS_CALENDAR_MODEL (model)); + + g_free (model->priv->default_category); + model->priv->default_category = g_strdup (default_category); +} + + +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, + CalComponent *comp) +{ + CalendarModelPrivate *priv; + GSList *categories_list, *elem; + gboolean changed = FALSE; + + priv = model->priv; + + cal_component_get_categories_list (comp, &categories_list); + + for (elem = categories_list; elem; elem = elem->next) { + if (!g_tree_lookup (priv->categories, elem->data)) { + /* We store a '1' as the data, just so we can use + g_tree_lookup() on it. Note that we don't free + the string since it is now part of the tree. */ + g_tree_insert (priv->categories, elem->data, + GINT_TO_POINTER (1)); + changed = TRUE; + } else { + g_free (elem->data); + } + } + + g_slist_free (categories_list); + + return changed; +} + + +GTree* +calendar_model_get_categories (CalendarModel *model) +{ + g_return_val_if_fail (IS_CALENDAR_MODEL (model), NULL); + + return model->priv->categories; +} diff --git a/calendar/gui/calendar-model.h b/calendar/gui/calendar-model.h index b8c08a5dbc..e4946393b6 100644 --- a/calendar/gui/calendar-model.h +++ b/calendar/gui/calendar-model.h @@ -51,6 +51,8 @@ struct _CalendarModel { struct _CalendarModelClass { ETableModelClass parent_class; + + void (* categories_changed) (CalendarModel *model); }; GtkType calendar_model_get_type (void); @@ -73,6 +75,12 @@ gboolean calendar_model_get_use_24_hour_format (CalendarModel *model); void calendar_model_set_use_24_hour_format (CalendarModel *model, gboolean use_24_hour_format); +GTree* calendar_model_get_categories (CalendarModel *model); + +void calendar_model_set_default_category (CalendarModel *model, + gchar *default_category); + + END_GNOME_DECLS diff --git a/calendar/gui/dialogs/task-editor-dialog.glade b/calendar/gui/dialogs/task-editor-dialog.glade index 272fa48e55..ea4adcc5e2 100644 --- a/calendar/gui/dialogs/task-editor-dialog.glade +++ b/calendar/gui/dialogs/task-editor-dialog.glade @@ -401,6 +401,7 @@ Cancelled <items>High Normal Low +Undefined </items> <initial_choice>0</initial_choice> <child> @@ -484,6 +485,7 @@ Confidential <class>GtkButton</class> <name>contacts-button</name> <can_focus>True</can_focus> + <relief>GTK_RELIEF_NORMAL</relief> <child> <padding>0</padding> <expand>False</expand> @@ -522,6 +524,7 @@ Confidential <class>GtkButton</class> <name>categories-button</name> <can_focus>True</can_focus> + <relief>GTK_RELIEF_NORMAL</relief> <child> <padding>0</padding> <expand>False</expand> diff --git a/calendar/gui/dialogs/task-editor-dialog.glade.h b/calendar/gui/dialogs/task-editor-dialog.glade.h index 20f7db3014..052fe951dd 100644 --- a/calendar/gui/dialogs/task-editor-dialog.glade.h +++ b/calendar/gui/dialogs/task-editor-dialog.glade.h @@ -10,22 +10,20 @@ gchar *s = N_("Sta_rt Date:"); gchar *s = N_("_Due Date:"); gchar *s = N_("% Comp_lete:"); gchar *s = N_("_Status:"); -gchar *s = N_("Not Started\n" - "In Progress\n" - "Completed\n" - "Cancelled\n" - ""); +gchar *s = N_("Not Started"); +gchar *s = N_("In Progress"); +gchar *s = N_("Completed"); +gchar *s = N_("Cancelled"); gchar *s = N_("_Priority:"); -gchar *s = N_("High\n" - "Normal\n" - "Low\n" - ""); +gchar *s = N_("High"); +gchar *s = N_("Normal"); +gchar *s = N_("Low"); +gchar *s = N_("Undefined"); gchar *s = N_("C_lassification:"); -gchar *s = N_("None\n" - "Public\n" - "Private\n" - "Confidential\n" - ""); +gchar *s = N_("None"); +gchar *s = N_("Public"); +gchar *s = N_("Private"); +gchar *s = N_("Confidential"); gchar *s = N_("_Contacts..."); gchar *s = N_("Ca_tegories..."); gchar *s = N_("Task"); diff --git a/calendar/gui/dialogs/task-editor.c b/calendar/gui/dialogs/task-editor.c index 288244802e..cca8298713 100644 --- a/calendar/gui/dialogs/task-editor.c +++ b/calendar/gui/dialogs/task-editor.c @@ -36,7 +36,6 @@ #include <e-util/e-dialog-widgets.h> #include <widgets/misc/e-dateedit.h> #include <cal-util/timeutil.h> -#include <cal-client/cal-client.h> #include "task-editor.h" #include "../calendar-config.h" #include "../widget-util.h" diff --git a/calendar/gui/dialogs/task-editor.h b/calendar/gui/dialogs/task-editor.h index a53d29c2a2..c74e979dff 100644 --- a/calendar/gui/dialogs/task-editor.h +++ b/calendar/gui/dialogs/task-editor.h @@ -27,6 +27,7 @@ #include <gtk/gtkobject.h> #include <libgnome/gnome-defs.h> #include <bonobo.h> +#include <cal-client/cal-client.h> BEGIN_GNOME_DECLS diff --git a/calendar/gui/dialogs/task-page.glade b/calendar/gui/dialogs/task-page.glade index 272fa48e55..ea4adcc5e2 100644 --- a/calendar/gui/dialogs/task-page.glade +++ b/calendar/gui/dialogs/task-page.glade @@ -401,6 +401,7 @@ Cancelled <items>High Normal Low +Undefined </items> <initial_choice>0</initial_choice> <child> @@ -484,6 +485,7 @@ Confidential <class>GtkButton</class> <name>contacts-button</name> <can_focus>True</can_focus> + <relief>GTK_RELIEF_NORMAL</relief> <child> <padding>0</padding> <expand>False</expand> @@ -522,6 +524,7 @@ Confidential <class>GtkButton</class> <name>categories-button</name> <can_focus>True</can_focus> + <relief>GTK_RELIEF_NORMAL</relief> <child> <padding>0</padding> <expand>False</expand> diff --git a/calendar/gui/e-calendar-table.c b/calendar/gui/e-calendar-table.c index cd3aacc058..6ee22b9759 100644 --- a/calendar/gui/e-calendar-table.c +++ b/calendar/gui/e-calendar-table.c @@ -49,34 +49,45 @@ #include "check-filled.xpm" -static void e_calendar_table_class_init (ECalendarTableClass *class); -static void e_calendar_table_init (ECalendarTable *cal_table); -static void e_calendar_table_destroy (GtkObject *object); - -static void e_calendar_table_on_double_click (ETable *table, - gint row, - gint col, - GdkEvent *event, - ECalendarTable *cal_table); -static gint e_calendar_table_on_right_click (ETable *table, - gint row, - gint col, - GdkEventButton *event, - ECalendarTable *cal_table); -static void e_calendar_table_on_open_task (GtkWidget *menuitem, - gpointer data); -static void e_calendar_table_on_mark_task_complete (GtkWidget *menuitem, - gpointer data); -static void e_calendar_table_on_delete_task (GtkWidget *menuitem, - gpointer data); -static gint e_calendar_table_on_key_press (ETable *table, - gint row, - gint col, - GdkEventKey *event, - ECalendarTable *cal_table); - -static void e_calendar_table_open_task (ECalendarTable *cal_table, - gint row); +static void e_calendar_table_class_init (ECalendarTableClass *class); +static void e_calendar_table_init (ECalendarTable *cal_table); +static void e_calendar_table_destroy (GtkObject *object); + +static void e_calendar_table_on_double_click (ETable *table, + gint row, + gint col, + GdkEvent *event, + ECalendarTable *cal_table); +static gint e_calendar_table_on_right_click (ETable *table, + gint row, + gint col, + GdkEventButton *event, + ECalendarTable *cal_table); +static void e_calendar_table_on_open_task (GtkWidget *menuitem, + gpointer data); +static void e_calendar_table_on_mark_task_complete (GtkWidget *menuitem, + gpointer data); +static void e_calendar_table_on_delete_task (GtkWidget *menuitem, + gpointer data); +static gint e_calendar_table_on_key_press (ETable *table, + gint row, + gint col, + GdkEventKey *event, + ECalendarTable *cal_table); + +static void e_calendar_table_open_task (ECalendarTable *cal_table, + gint row); + +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_row_inserted (ETableModel *model, + gint row, + ECalendarTable *cal_table); +static void e_calendar_table_on_row_deleted (ETableModel *model, + gint row, + ECalendarTable *cal_table); + /* The icons to represent the task. */ #define E_CALENDAR_MODEL_NUM_ICONS 4 @@ -155,61 +166,61 @@ static char *list [] = { }; #endif -#define E_CALENDAR_TABLE_SPEC \ - "<ETableSpecification click-to-add=\"true\" " \ - " _click-to-add-message=\"Click to add a task\" " \ - " draw-grid=\"true\">" \ - " <ETableColumn model_col= \"0\" _title=\"Categories\" " \ - " expansion=\"1.0\" minimum_width=\"10\" resizable=\"true\" " \ - " cell=\"string\" compare=\"string\"/>" \ - " <ETableColumn model_col= \"1\" _title=\"Classification\" " \ - " expansion=\"1.0\" minimum_width=\"10\" resizable=\"true\" " \ - " cell=\"string\" compare=\"string\"/>" \ - " <ETableColumn model_col= \"2\" _title=\"Completion Date\" " \ - " expansion=\"1.0\" minimum_width=\"10\" resizable=\"true\" " \ - " cell=\"string\" compare=\"string\"/>" \ - " <ETableColumn model_col= \"3\" _title=\"End Date\" " \ - " expansion=\"1.0\" minimum_width=\"10\" resizable=\"true\" " \ - " cell=\"string\" compare=\"string\"/>" \ - " <ETableColumn model_col= \"4\" _title=\"Start Date\" " \ - " expansion=\"1.0\" minimum_width=\"10\" resizable=\"true\" " \ - " cell=\"string\" compare=\"string\"/>" \ - " <ETableColumn model_col= \"5\" _title=\"Due Date\" " \ - " expansion=\"1.0\" minimum_width=\"10\" resizable=\"true\" " \ - " cell=\"string\" compare=\"string\"/>" \ - " <ETableColumn model_col= \"6\" _title=\"Geographical Position\" " \ - " expansion=\"1.0\" minimum_width=\"10\" resizable=\"true\" " \ - " cell=\"string\" compare=\"string\"/>" \ - " <ETableColumn model_col= \"7\" _title=\"Percent complete\" " \ - " expansion=\"1.0\" minimum_width=\"10\" resizable=\"true\" " \ - " cell=\"string\" compare=\"string\"/>" \ - " <ETableColumn model_col= \"8\" _title=\"Priority\" " \ - " expansion=\"1.0\" minimum_width=\"10\" resizable=\"true\" " \ - " cell=\"string\" compare=\"string\"/>" \ - " <ETableColumn model_col= \"9\" _title=\"Summary\" " \ - " expansion=\"1.0\" minimum_width=\"10\" resizable=\"true\" " \ - " cell=\"summary\" compare=\"string\"/>" \ - " <ETableColumn model_col=\"10\" _title=\"Transparency\" " \ - " expansion=\"1.0\" minimum_width=\"10\" resizable=\"true\" " \ - " cell=\"string\" compare=\"string\"/>" \ - " <ETableColumn model_col=\"11\" _title=\"URL\" " \ - " expansion=\"1.0\" minimum_width=\"10\" resizable=\"true\" " \ - " cell=\"string\" compare=\"string\"/>" \ - " <ETableColumn model_col=\"12\" _title=\"Alarms\" " \ - " expansion=\"1.0\" minimum_width=\"10\" resizable=\"true\" " \ - " cell=\"string\" compare=\"string\"/>" \ - " <ETableColumn model_col=\"13\" pixbuf=\"icon\" " \ - " expansion=\"1.0\" minimum_width=\"16\" resizable=\"false\" " \ - " cell=\"icon\" compare=\"integer\"/>" \ - " <ETableColumn model_col=\"14\" pixbuf=\"complete\" " \ - " expansion=\"1.0\" minimum_width=\"16\" resizable=\"false\" " \ - " cell=\"checkbox\" compare=\"integer\"/>" \ - " <ETableState>" \ - " <column source=\"13\"/>" \ - " <column source=\"14\"/>" \ - " <column source= \"9\"/>" \ - " <grouping></grouping>" \ - " </ETableState>" \ +#define E_CALENDAR_TABLE_SPEC \ + "<ETableSpecification click-to-add=\"true\" " \ + " _click-to-add-message=\"Click here to add a task\" " \ + " draw-grid=\"true\">" \ + " <ETableColumn model_col= \"0\" _title=\"Categories\" " \ + " expansion=\"1.0\" minimum_width=\"10\" resizable=\"true\" " \ + " cell=\"calstring\" compare=\"string\"/>" \ + " <ETableColumn model_col= \"1\" _title=\"Classification\" " \ + " expansion=\"1.0\" minimum_width=\"10\" resizable=\"true\" " \ + " cell=\"calstring\" compare=\"string\"/>" \ + " <ETableColumn model_col= \"2\" _title=\"Completion Date\" " \ + " expansion=\"1.0\" minimum_width=\"10\" resizable=\"true\" " \ + " cell=\"calstring\" compare=\"string\"/>" \ + " <ETableColumn model_col= \"3\" _title=\"End Date\" " \ + " expansion=\"1.0\" minimum_width=\"10\" resizable=\"true\" " \ + " cell=\"calstring\" compare=\"string\"/>" \ + " <ETableColumn model_col= \"4\" _title=\"Start Date\" " \ + " expansion=\"1.0\" minimum_width=\"10\" resizable=\"true\" " \ + " cell=\"calstring\" compare=\"string\"/>" \ + " <ETableColumn model_col= \"5\" _title=\"Due Date\" " \ + " expansion=\"1.0\" minimum_width=\"10\" resizable=\"true\" " \ + " cell=\"calstring\" compare=\"string\"/>" \ + " <ETableColumn model_col= \"6\" _title=\"Geographical Position\" " \ + " expansion=\"1.0\" minimum_width=\"10\" resizable=\"true\" " \ + " cell=\"calstring\" compare=\"string\"/>" \ + " <ETableColumn model_col= \"7\" _title=\"% Complete\" " \ + " expansion=\"1.0\" minimum_width=\"10\" resizable=\"true\" " \ + " cell=\"calstring\" compare=\"string\"/>" \ + " <ETableColumn model_col= \"8\" _title=\"Priority\" " \ + " expansion=\"1.0\" minimum_width=\"10\" resizable=\"true\" " \ + " cell=\"calstring\" compare=\"string\"/>" \ + " <ETableColumn model_col= \"9\" _title=\"Summary\" " \ + " expansion=\"1.0\" minimum_width=\"10\" resizable=\"true\" " \ + " cell=\"calstring\" compare=\"string\"/>" \ + " <ETableColumn model_col=\"10\" _title=\"Transparency\" " \ + " expansion=\"1.0\" minimum_width=\"10\" resizable=\"true\" " \ + " cell=\"calstring\" compare=\"string\"/>" \ + " <ETableColumn model_col=\"11\" _title=\"URL\" " \ + " expansion=\"1.0\" minimum_width=\"10\" resizable=\"true\" " \ + " cell=\"calstring\" compare=\"string\"/>" \ + " <ETableColumn model_col=\"12\" _title=\"Alarms\" " \ + " expansion=\"1.0\" minimum_width=\"10\" resizable=\"true\" " \ + " cell=\"calstring\" compare=\"string\"/>" \ + " <ETableColumn model_col=\"13\" pixbuf=\"icon\" " \ + " expansion=\"1.0\" minimum_width=\"16\" resizable=\"false\" "\ + " cell=\"icon\" compare=\"integer\"/>" \ + " <ETableColumn model_col=\"14\" pixbuf=\"complete\" " \ + " expansion=\"1.0\" minimum_width=\"16\" resizable=\"false\" "\ + " cell=\"checkbox\" compare=\"integer\"/>" \ + " <ETableState>" \ + " <column source=\"13\"/>" \ + " <column source=\"14\"/>" \ + " <column source= \"9\"/>" \ + " <grouping></grouping>" \ + " </ETableState>" \ "</ETableSpecification>" static void @@ -217,7 +228,6 @@ e_calendar_table_init (ECalendarTable *cal_table) { GtkWidget *table; ETable *e_table; - ETableModel *model; ECell *cell; ETableExtras *extras; gint i; @@ -243,7 +253,17 @@ e_calendar_table_init (ECalendarTable *cal_table) /* Create the model */ cal_table->model = calendar_model_new (); - model = E_TABLE_MODEL (cal_table->model); + 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_row_inserted", + GTK_SIGNAL_FUNC (e_calendar_table_on_row_inserted), + cal_table); + gtk_signal_connect (GTK_OBJECT (cal_table->model), "model_row_deleted", + GTK_SIGNAL_FUNC (e_calendar_table_on_row_deleted), + cal_table); /* Create the header columns */ @@ -255,7 +275,7 @@ e_calendar_table_init (ECalendarTable *cal_table) "bold_column", CAL_COMPONENT_FIELD_OVERDUE, "color_column", CAL_COMPONENT_FIELD_COLOR, NULL); - e_table_extras_add_cell(extras, "summary", cell); + e_table_extras_add_cell (extras, "calstring", cell); /* Create pixmaps */ @@ -275,8 +295,8 @@ e_calendar_table_init (ECalendarTable *cal_table) /* Create the table */ - table = e_table_scrolled_new (model, extras, E_CALENDAR_TABLE_SPEC, - NULL); + table = e_table_scrolled_new (cal_table->subset_model, extras, + E_CALENDAR_TABLE_SPEC, NULL); gtk_object_unref (GTK_OBJECT (extras)); cal_table->etable = table; @@ -345,6 +365,8 @@ e_calendar_table_on_double_click (ETable *table, GdkEvent *event, ECalendarTable *cal_table) { + g_print ("In e_calendar_table_on_double_click\n"); + e_calendar_table_open_task (cal_table, row); } @@ -500,9 +522,135 @@ void e_calendar_table_save_state (ECalendarTable *cal_table, gchar *filename) { - g_return_if_fail (E_IS_CALENDAR_TABLE (cal_table)); e_table_save_state (e_table_scrolled_get_table(E_TABLE_SCROLLED (cal_table->etable)), filename); } + + +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_row_inserted (ETableModel *model, + gint row, + ECalendarTable *cal_table) +{ + ETableSubsetVariable *etssv; + CalComponent *comp; + gboolean add_row = FALSE; + + etssv = E_TABLE_SUBSET_VARIABLE (cal_table->subset_model); + + if (cal_table->filter_func == NULL) { + add_row = TRUE; + } else { + comp = calendar_model_get_component (cal_table->model, row); + + if ((*cal_table->filter_func) (cal_table, comp, + cal_table->filter_data)) + add_row = TRUE; + } + + if (add_row) { + e_table_subset_variable_increment (etssv, row, 1); + e_table_subset_variable_add (etssv, row); + } +} + + +static void +e_calendar_table_on_row_deleted (ETableModel *model, + gint row, + 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); +} diff --git a/calendar/gui/e-calendar-table.h b/calendar/gui/e-calendar-table.h index 1265a80a72..6ca8a32515 100644 --- a/calendar/gui/e-calendar-table.h +++ b/calendar/gui/e-calendar-table.h @@ -53,16 +53,30 @@ typedef enum 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. */ 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; }; struct _ECalendarTableClass @@ -85,6 +99,15 @@ 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 } #endif /* __cplusplus */ diff --git a/calendar/gui/e-day-view.c b/calendar/gui/e-day-view.c index 1f10194cb0..1cb4b182ec 100644 --- a/calendar/gui/e-day-view.c +++ b/calendar/gui/e-day-view.c @@ -625,6 +625,7 @@ e_day_view_init (EDayView *day_view) "max_lines", 1, "editable", TRUE, "draw_background", FALSE, + "fill_color_rgba", GNOME_CANVAS_COLOR(0, 0, 0), NULL); gnome_canvas_item_hide (day_view->drag_long_event_item); @@ -733,6 +734,7 @@ e_day_view_init (EDayView *day_view) "clip", TRUE, "editable", TRUE, "draw_background", FALSE, + "fill_color_rgba", GNOME_CANVAS_COLOR(0, 0, 0), NULL); gnome_canvas_item_hide (day_view->drag_item); @@ -4194,6 +4196,7 @@ e_day_view_reshape_long_event (EDayView *day_view, "editable", TRUE, "use_ellipsis", TRUE, "draw_background", FALSE, + "fill_color_rgba", GNOME_CANVAS_COLOR(0, 0, 0), NULL); gtk_signal_connect (GTK_OBJECT (event->canvas_item), "event", GTK_SIGNAL_FUNC (e_day_view_on_text_item_event), @@ -4552,6 +4555,7 @@ e_day_view_reshape_day_event (EDayView *day_view, "clip", TRUE, "use_ellipsis", TRUE, "draw_background", FALSE, + "fill_color_rgba", GNOME_CANVAS_COLOR(0, 0, 0), NULL); gtk_signal_connect (GTK_OBJECT (event->canvas_item), "event", diff --git a/calendar/gui/e-tasks.c b/calendar/gui/e-tasks.c index 552b1f54fc..29c067783a 100644 --- a/calendar/gui/e-tasks.c +++ b/calendar/gui/e-tasks.c @@ -26,8 +26,10 @@ #include <gnome.h> #include <gal/util/e-util.h> #include <gal/e-table/e-table-scrolled.h> +#include "dialogs/task-editor.h" #include "e-calendar-table.h" #include "alarm-notify.h" +#include "component-factory.h" #include "e-tasks.h" @@ -49,11 +51,15 @@ struct _ETasksPrivate { /* Loading state; we can be loading or creating a calendar */ LoadState load_state; - /* URI being loaded, NULL if we are not being loaded */ - char *loading_uri; + /* URI of the folder being shown. */ + char *folder_uri; /* The ECalendarTable showing the tasks. */ GtkWidget *tasks_view; + + /* The option menu showing the categories, and the popup menu. */ + GtkWidget *categories_option_menu; + GtkWidget *categories_menu; }; @@ -66,8 +72,21 @@ static void cal_loaded_cb (CalClient *client, CalClientLoadStatus status, gpoint static void obj_updated_cb (CalClient *client, const char *uid, gpointer data); static void obj_removed_cb (CalClient *client, const char *uid, gpointer data); +static char* e_tasks_get_config_filename (ETasks *tasks); + +static void e_tasks_on_filter_selected (GtkMenuShell *menu_shell, + ETasks *tasks); +static void e_tasks_on_categories_changed (CalendarModel *model, + ETasks *tasks); +static void e_tasks_rebuild_categories_menu (ETasks *tasks); +static gint e_tasks_add_menu_item (gpointer key, + gpointer value, + gpointer data); + + static GtkTableClass *parent_class; + E_MAKE_TYPE (e_tasks, "ETasks", ETasks, e_tasks_class_init, e_tasks_init, GTK_TYPE_TABLE) @@ -112,21 +131,47 @@ e_tasks_init (ETasks *tasks) "<grouping/>" \ "</ETableState>" + static void setup_widgets (ETasks *tasks) { ETasksPrivate *priv; ETable *etable; + GtkWidget *hbox, *menuitem, *categories_label; priv = tasks->priv; + hbox = gtk_hbox_new (FALSE, 0); + gtk_widget_show (hbox); + gtk_table_attach (GTK_TABLE (tasks), hbox, 0, 1, 0, 1, + GTK_EXPAND | GTK_FILL, 0, 0, 0); + + 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, + FALSE, FALSE, 0); + + priv->categories_menu = gtk_menu_new (); + + menuitem = gtk_menu_item_new_with_label (_("All")); + gtk_widget_show (menuitem); + gtk_menu_append (GTK_MENU (priv->categories_menu), menuitem); + + gtk_option_menu_set_menu (GTK_OPTION_MENU (priv->categories_option_menu), priv->categories_menu); + + categories_label = gtk_label_new (_("Category:")); + gtk_widget_show (categories_label); + gtk_box_pack_end (GTK_BOX (hbox), categories_label, FALSE, FALSE, 4); + + priv->tasks_view = e_calendar_table_new (); etable = e_table_scrolled_get_table (E_TABLE_SCROLLED (E_CALENDAR_TABLE (priv->tasks_view)->etable)); e_table_set_state (etable, E_TASKS_TABLE_DEFAULT_STATE); - gtk_table_attach (GTK_TABLE (tasks), priv->tasks_view, 0, 1, 0, 1, + gtk_table_attach (GTK_TABLE (tasks), priv->tasks_view, 0, 1, 1, 2, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); gtk_widget_show (priv->tasks_view); + gtk_signal_connect (GTK_OBJECT (E_CALENDAR_TABLE (priv->tasks_view)->model), "categories-changed", GTK_SIGNAL_FUNC (e_tasks_on_categories_changed), tasks); } @@ -182,6 +227,7 @@ e_tasks_destroy (GtkObject *object) { ETasks *tasks; ETasksPrivate *priv; + char *config_filename; g_return_if_fail (object != NULL); g_return_if_fail (E_IS_TASKS (object)); @@ -189,19 +235,17 @@ e_tasks_destroy (GtkObject *object) tasks = E_TASKS (object); priv = tasks->priv; - /* Save the ETable layout. FIXME: Need to save in a per-folder config - file like the mail folders use. */ -#if 0 - filename = g_strdup_printf ("%s/config/TaskPad", evolution_dir); - e_calendar_table_save_state (E_CALENDAR_TABLE (priv->todo), filename); - g_free (filename); -#endif + /* Save the ETable layout. */ + config_filename = e_tasks_get_config_filename (tasks); + e_calendar_table_save_state (E_CALENDAR_TABLE (priv->tasks_view), + config_filename); + g_free (config_filename); priv->load_state = LOAD_STATE_NOT_LOADED; - if (priv->loading_uri) { - g_free (priv->loading_uri); - priv->loading_uri = NULL; + if (priv->folder_uri) { + g_free (priv->folder_uri); + priv->folder_uri = NULL; } if (priv->client) { @@ -224,6 +268,7 @@ e_tasks_open (ETasks *tasks, ETasksOpenMode gcom) { ETasksPrivate *priv; + char *config_filename; g_return_val_if_fail (tasks != NULL, FALSE); g_return_val_if_fail (E_IS_TASKS (tasks), FALSE); @@ -233,9 +278,9 @@ e_tasks_open (ETasks *tasks, g_return_val_if_fail (priv->load_state == LOAD_STATE_NOT_LOADED, FALSE); - g_assert (priv->loading_uri == NULL); + g_assert (priv->folder_uri == NULL); - priv->loading_uri = g_strdup (file); + priv->folder_uri = g_strdup (file); if (gcom == E_TASKS_OPEN) priv->load_state = LOAD_STATE_WAIT_LOAD; @@ -246,10 +291,16 @@ e_tasks_open (ETasks *tasks, return FALSE; } + config_filename = e_tasks_get_config_filename (tasks); + e_calendar_table_load_state (E_CALENDAR_TABLE (priv->tasks_view), + config_filename); + g_free (config_filename); + + if (!cal_client_load_calendar (priv->client, file)) { priv->load_state = LOAD_STATE_NOT_LOADED; - g_free (priv->loading_uri); - priv->loading_uri = NULL; + g_free (priv->folder_uri); + priv->folder_uri = NULL; g_message ("e_tasks_open(): Could not issue the request"); return FALSE; @@ -263,7 +314,7 @@ e_tasks_open (ETasks *tasks, * the cal_loaded signal from the client is invoked. */ static void -initial_load (ETasks *tasks) +initial_load (ETasks *tasks) { ETasksPrivate *priv; @@ -274,7 +325,8 @@ initial_load (ETasks *tasks) /* Displays an error to indicate that loading a calendar failed */ static void -load_error (ETasks *tasks, const char *uri) +load_error (ETasks *tasks, + const char *uri) { char *msg; @@ -285,7 +337,8 @@ load_error (ETasks *tasks, const char *uri) /* Displays an error to indicate that creating a calendar failed */ static void -create_error (ETasks *tasks, const char *uri) +create_error (ETasks *tasks, + const char *uri) { char *msg; @@ -297,7 +350,8 @@ create_error (ETasks *tasks, const char *uri) /* Displays an error to indicate that the specified URI method is not supported */ static void -method_error (ETasks *tasks, const char *uri) +method_error (ETasks *tasks, + const char *uri) { char *msg; @@ -308,7 +362,9 @@ method_error (ETasks *tasks, const char *uri) /* Callback from the calendar client when a calendar is loaded */ static void -cal_loaded_cb (CalClient *client, CalClientLoadStatus status, gpointer data) +cal_loaded_cb (CalClient *client, + CalClientLoadStatus status, + gpointer data) { ETasks *tasks; ETasksPrivate *priv; @@ -319,7 +375,7 @@ cal_loaded_cb (CalClient *client, CalClientLoadStatus status, gpointer data) g_assert (priv->load_state != LOAD_STATE_NOT_LOADED && priv->load_state != LOAD_STATE_LOADED); - g_assert (priv->loading_uri != NULL); + g_assert (priv->folder_uri != NULL); free_uri = TRUE; @@ -330,10 +386,10 @@ cal_loaded_cb (CalClient *client, CalClientLoadStatus status, gpointer data) initial_load (tasks); } else if (status == CAL_CLIENT_LOAD_ERROR) { priv->load_state = LOAD_STATE_NOT_LOADED; - load_error (tasks, priv->loading_uri); + load_error (tasks, priv->folder_uri); } else if (status == CAL_CLIENT_LOAD_METHOD_NOT_SUPPORTED) { priv->load_state = LOAD_STATE_NOT_LOADED; - method_error (tasks, priv->loading_uri); + method_error (tasks, priv->folder_uri); } else g_assert_not_reached (); @@ -348,14 +404,14 @@ cal_loaded_cb (CalClient *client, CalClientLoadStatus status, gpointer data) free_uri = FALSE; if (!cal_client_create_calendar (priv->client, - priv->loading_uri)) { + priv->folder_uri)) { priv->load_state = LOAD_STATE_NOT_LOADED; free_uri = TRUE; g_message ("cal_loaded_cb(): Could not issue the create request"); } } else if (status == CAL_CLIENT_LOAD_METHOD_NOT_SUPPORTED) { priv->load_state = LOAD_STATE_NOT_LOADED; - method_error (tasks, priv->loading_uri); + method_error (tasks, priv->folder_uri); } else g_assert_not_reached (); @@ -367,7 +423,7 @@ cal_loaded_cb (CalClient *client, CalClientLoadStatus status, gpointer data) initial_load (tasks); } else if (status == CAL_CLIENT_LOAD_ERROR) { priv->load_state = LOAD_STATE_NOT_LOADED; - create_error (tasks, priv->loading_uri); + create_error (tasks, priv->folder_uri); } else if (status == CAL_CLIENT_LOAD_IN_USE) { /* Someone created the URI while we were issuing the * create request, so we just try to reload. @@ -376,14 +432,14 @@ cal_loaded_cb (CalClient *client, CalClientLoadStatus status, gpointer data) free_uri = FALSE; if (!cal_client_load_calendar (priv->client, - priv->loading_uri)) { + priv->folder_uri)) { priv->load_state = LOAD_STATE_NOT_LOADED; free_uri = TRUE; g_message ("cal_loaded_cb(): Could not issue the load request"); } } else if (status == CAL_CLIENT_LOAD_METHOD_NOT_SUPPORTED) { priv->load_state = LOAD_STATE_NOT_LOADED; - method_error (tasks, priv->loading_uri); + method_error (tasks, priv->folder_uri); } else g_assert_not_reached (); @@ -392,17 +448,14 @@ cal_loaded_cb (CalClient *client, CalClientLoadStatus status, gpointer data) default: g_assert_not_reached (); } - - if (free_uri) { - g_free (priv->loading_uri); - priv->loading_uri = NULL; - } } /* Callback from the calendar client when an object is updated */ static void -obj_updated_cb (CalClient *client, const char *uid, gpointer data) +obj_updated_cb (CalClient *client, + const char *uid, + gpointer data) { ETasks *tasks; ETasksPrivate *priv; @@ -416,7 +469,9 @@ obj_updated_cb (CalClient *client, const char *uid, gpointer data) /* Callback from the calendar client when an object is removed */ static void -obj_removed_cb (CalClient *client, const char *uid, gpointer data) +obj_removed_cb (CalClient *client, + const char *uid, + gpointer data) { ETasks *tasks; ETasksPrivate *priv; @@ -428,6 +483,27 @@ obj_removed_cb (CalClient *client, const char *uid, gpointer data) } +static char* +e_tasks_get_config_filename (ETasks *tasks) +{ + ETasksPrivate *priv; + char *url, *filename; + + priv = tasks->priv; + + url = g_strdup (priv->folder_uri); + + /* This turns all funny characters into '_', in the string itself. */ + e_filename_make_safe (url); + + filename = g_strdup_printf ("%s/config/et-header-%s", evolution_dir, + url); + g_free (url); + + return filename; +} + + /** * e_tasks_get_cal_client: * @tasks: An #ETasks. @@ -437,14 +513,128 @@ obj_removed_cb (CalClient *client, const char *uid, gpointer data) * Return value: A calendar client interface object. **/ CalClient * -e_tasks_get_cal_client (ETasks *tasks) +e_tasks_get_cal_client (ETasks *tasks) { ETasksPrivate *priv; - g_return_val_if_fail (tasks != NULL, NULL); g_return_val_if_fail (E_IS_TASKS (tasks), NULL); priv = tasks->priv; return priv->client; } + + +void +e_tasks_new_task (ETasks *tasks) +{ + ETasksPrivate *priv; + TaskEditor *tedit; + CalComponent *comp; + + g_return_if_fail (E_IS_TASKS (tasks)); + + priv = tasks->priv; + + tedit = task_editor_new (); + task_editor_set_cal_client (tedit, priv->client); + + comp = cal_component_new (); + cal_component_set_new_vtype (comp, CAL_COMPONENT_TODO); + + task_editor_set_todo_object (tedit, comp); + + gtk_object_unref (GTK_OBJECT (comp)); +} + + +static void +e_tasks_on_filter_selected (GtkMenuShell *menu_shell, + ETasks *tasks) +{ + ETasksPrivate *priv; + ECalendarTable *cal_table; + CalendarModel *model; + GtkWidget *label; + char *category; + + g_return_if_fail (E_IS_TASKS (tasks)); + + priv = tasks->priv; + + label = GTK_BIN (priv->categories_option_menu)->child; + gtk_label_get (GTK_LABEL (label), &category); + + cal_table = E_CALENDAR_TABLE (priv->tasks_view); + model = cal_table->model; + + g_print ("!#!#!#!#!# filter selected: %s\n", category); + + if (!strcmp (category, _("All"))) { + calendar_model_set_default_category (model, NULL); + e_calendar_table_set_filter_func (cal_table, NULL, NULL, + 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); + } +} + + +static void +e_tasks_on_categories_changed (CalendarModel *model, + ETasks *tasks) +{ + g_print ("In e_tasks_on_categories_changed\n"); + + e_tasks_rebuild_categories_menu (tasks); +} + + +static void +e_tasks_rebuild_categories_menu (ETasks *tasks) +{ + ETasksPrivate *priv; + CalendarModel *model; + GTree *categories; + GtkWidget *menuitem; + + priv = tasks->priv; + + priv->categories_menu = gtk_menu_new (); + + menuitem = gtk_menu_item_new_with_label (_("All")); + gtk_widget_show (menuitem); + gtk_menu_append (GTK_MENU (priv->categories_menu), menuitem); + + model = E_CALENDAR_TABLE (priv->tasks_view)->model; + categories = calendar_model_get_categories (model); + g_return_if_fail (categories != NULL); + + g_tree_traverse (categories, e_tasks_add_menu_item, G_IN_ORDER, + priv->categories_menu); + + gtk_option_menu_set_menu (GTK_OPTION_MENU (priv->categories_option_menu), priv->categories_menu); + + gtk_signal_connect (GTK_OBJECT (priv->categories_menu), "deactivate", + GTK_SIGNAL_FUNC (e_tasks_on_filter_selected), + tasks); +} + + +static gint +e_tasks_add_menu_item (gpointer key, + gpointer value, + gpointer data) +{ + GtkWidget *menuitem; + + menuitem = gtk_menu_item_new_with_label ((char*) key); + gtk_widget_show (menuitem); + gtk_menu_append (GTK_MENU (data), menuitem); + + return FALSE; +} + diff --git a/calendar/gui/e-tasks.h b/calendar/gui/e-tasks.h index 86dbb1ff56..a777c32375 100644 --- a/calendar/gui/e-tasks.h +++ b/calendar/gui/e-tasks.h @@ -65,7 +65,9 @@ gboolean e_tasks_open (ETasks *tasks, char *file, ETasksOpenMode gcom); -CalClient *e_tasks_get_cal_client (ETasks *tasks); +CalClient *e_tasks_get_cal_client (ETasks *tasks); + +void e_tasks_new_task (ETasks *tasks); #endif /* _E_TASKS_H_ */ diff --git a/calendar/gui/e-week-view.c b/calendar/gui/e-week-view.c index c9344c88f4..0b7743e970 100644 --- a/calendar/gui/e-week-view.c +++ b/calendar/gui/e-week-view.c @@ -2478,6 +2478,7 @@ e_week_view_reshape_event_span (EWeekView *week_view, "editable", TRUE, "text", text.value ? text.value : "", "use_ellipsis", TRUE, + "fill_color_rgba", GNOME_CANVAS_COLOR(0, 0, 0), NULL); gtk_signal_connect (GTK_OBJECT (span->text_item), "event", GTK_SIGNAL_FUNC (e_week_view_on_text_item_event), diff --git a/calendar/gui/gnome-cal.c b/calendar/gui/gnome-cal.c index 5daf6c9b55..fafd31d583 100644 --- a/calendar/gui/gnome-cal.c +++ b/calendar/gui/gnome-cal.c @@ -51,6 +51,11 @@ typedef enum { /* Private part of the GnomeCalendar structure */ struct _GnomeCalendarPrivate { + + /* + * The Calendar Folder. + */ + /* The calendar client object we monitor */ CalClient *client; @@ -60,6 +65,21 @@ struct _GnomeCalendarPrivate { /* URI being loaded, NULL if we are not being loaded */ char *loading_uri; + /* + * The TaskPad Folder. + */ + + /* The calendar client object we monitor */ + CalClient *task_pad_client; + + /* Loading state; we can be loading or creating a calendar */ + LoadState task_pad_load_state; + + /* URI being loaded, NULL if we are not being loaded */ + char *task_pad_loading_uri; + + + /* Mapping of component UIDs to event editors */ GHashTable *object_editor_hash; @@ -289,6 +309,7 @@ gnome_calendar_init (GnomeCalendar *gcal) gcal->priv = priv; priv->load_state = LOAD_STATE_NOT_LOADED; + priv->task_pad_load_state = LOAD_STATE_NOT_LOADED; priv->object_editor_hash = g_hash_table_new (g_str_hash, g_str_equal); @@ -330,18 +351,30 @@ gnome_calendar_destroy (GtkObject *object) g_free (filename); priv->load_state = LOAD_STATE_NOT_LOADED; + priv->task_pad_load_state = LOAD_STATE_NOT_LOADED; if (priv->loading_uri) { g_free (priv->loading_uri); priv->loading_uri = NULL; } + if (priv->task_pad_loading_uri) { + g_free (priv->task_pad_loading_uri); + priv->task_pad_loading_uri = NULL; + } + if (priv->client) { alarm_notify_remove_client (priv->client); gtk_object_unref (GTK_OBJECT (priv->client)); priv->client = NULL; } + if (priv->task_pad_client) { + alarm_notify_remove_client (priv->task_pad_client); + gtk_object_unref (GTK_OBJECT (priv->task_pad_client)); + priv->task_pad_client = NULL; + } + priv->in_destroy = TRUE; g_hash_table_foreach (priv->object_editor_hash, destroy_editor_cb, NULL); g_hash_table_destroy (priv->object_editor_hash); @@ -673,7 +706,7 @@ load_error (GnomeCalendar *gcal, const char *uri) { char *msg; - msg = g_strdup_printf (_("Could not load the calendar in `%s'"), uri); + msg = g_strdup_printf (_("Could not load the folder in `%s'"), uri); gnome_error_dialog_parented (msg, GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (gcal)))); g_free (msg); } @@ -684,7 +717,7 @@ create_error (GnomeCalendar *gcal, const char *uri) { char *msg; - msg = g_strdup_printf (_("Could not create a calendar in `%s'"), uri); + msg = g_strdup_printf (_("Could not create a folder in `%s'"), uri); gnome_error_dialog_parented (msg, GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (gcal)))); g_free (msg); } @@ -706,27 +739,43 @@ cal_loaded_cb (CalClient *client, CalClientLoadStatus status, gpointer data) { GnomeCalendar *gcal; GnomeCalendarPrivate *priv; - gboolean free_uri; + gboolean free_uri, is_calendar = FALSE; + LoadState *load_state; + char **loading_uri; gcal = GNOME_CALENDAR (data); priv = gcal->priv; - g_assert (priv->load_state != LOAD_STATE_NOT_LOADED && priv->load_state != LOAD_STATE_LOADED); - g_assert (priv->loading_uri != NULL); + if (client == priv->client) { + is_calendar = TRUE; + load_state = &priv->load_state; + loading_uri = &priv->loading_uri; + } else if (client == priv->task_pad_client) { + load_state = &priv->task_pad_load_state; + loading_uri = &priv->task_pad_loading_uri; + } else { + g_assert_not_reached (); + return; + } + + g_assert (*load_state != LOAD_STATE_NOT_LOADED + && *load_state != LOAD_STATE_LOADED); + g_assert (*loading_uri != NULL); free_uri = TRUE; - switch (priv->load_state) { + switch (*load_state) { case LOAD_STATE_WAIT_LOAD: if (status == CAL_CLIENT_LOAD_SUCCESS) { - priv->load_state = LOAD_STATE_LOADED; - initial_load (gcal); + *load_state = LOAD_STATE_LOADED; + if (is_calendar) + initial_load (gcal); } else if (status == CAL_CLIENT_LOAD_ERROR) { - priv->load_state = LOAD_STATE_NOT_LOADED; - load_error (gcal, priv->loading_uri); + *load_state = LOAD_STATE_NOT_LOADED; + load_error (gcal, *loading_uri); } else if (status == CAL_CLIENT_LOAD_METHOD_NOT_SUPPORTED) { - priv->load_state = LOAD_STATE_NOT_LOADED; - method_error (gcal, priv->loading_uri); + *load_state = LOAD_STATE_NOT_LOADED; + method_error (gcal, *loading_uri); } else g_assert_not_reached (); @@ -734,20 +783,22 @@ cal_loaded_cb (CalClient *client, CalClientLoadStatus status, gpointer data) case LOAD_STATE_WAIT_LOAD_BEFORE_CREATE: if (status == CAL_CLIENT_LOAD_SUCCESS) { - priv->load_state = LOAD_STATE_LOADED; - initial_load (gcal); + *load_state = LOAD_STATE_LOADED; + if (is_calendar) + initial_load (gcal); } else if (status == CAL_CLIENT_LOAD_ERROR) { - priv->load_state = LOAD_STATE_WAIT_CREATE; + *load_state = LOAD_STATE_WAIT_CREATE; free_uri = FALSE; - if (!cal_client_create_calendar (priv->client, priv->loading_uri)) { - priv->load_state = LOAD_STATE_NOT_LOADED; + if (!cal_client_create_calendar (client, + *loading_uri)) { + *load_state = LOAD_STATE_NOT_LOADED; free_uri = TRUE; g_message ("cal_loaded_cb(): Could not issue the create request"); } } else if (status == CAL_CLIENT_LOAD_METHOD_NOT_SUPPORTED) { - priv->load_state = LOAD_STATE_NOT_LOADED; - method_error (gcal, priv->loading_uri); + *load_state = LOAD_STATE_NOT_LOADED; + method_error (gcal, *loading_uri); } else g_assert_not_reached (); @@ -755,26 +806,28 @@ cal_loaded_cb (CalClient *client, CalClientLoadStatus status, gpointer data) case LOAD_STATE_WAIT_CREATE: if (status == CAL_CLIENT_LOAD_SUCCESS) { - priv->load_state = LOAD_STATE_LOADED; - initial_load (gcal); + *load_state = LOAD_STATE_LOADED; + if (is_calendar) + initial_load (gcal); } else if (status == CAL_CLIENT_LOAD_ERROR) { - priv->load_state = LOAD_STATE_NOT_LOADED; - create_error (gcal, priv->loading_uri); + *load_state = LOAD_STATE_NOT_LOADED; + create_error (gcal, *loading_uri); } else if (status == CAL_CLIENT_LOAD_IN_USE) { /* Someone created the URI while we were issuing the * create request, so we just try to reload. */ - priv->load_state = LOAD_STATE_WAIT_LOAD; + *load_state = LOAD_STATE_WAIT_LOAD; free_uri = FALSE; - if (!cal_client_load_calendar (priv->client, priv->loading_uri)) { - priv->load_state = LOAD_STATE_NOT_LOADED; + if (!cal_client_load_calendar (client, + *loading_uri)) { + *load_state = LOAD_STATE_NOT_LOADED; free_uri = TRUE; g_message ("cal_loaded_cb(): Could not issue the load request"); } } else if (status == CAL_CLIENT_LOAD_METHOD_NOT_SUPPORTED) { - priv->load_state = LOAD_STATE_NOT_LOADED; - method_error (gcal, priv->loading_uri); + *load_state = LOAD_STATE_NOT_LOADED; + method_error (gcal, *loading_uri); } else g_assert_not_reached (); @@ -785,8 +838,8 @@ cal_loaded_cb (CalClient *client, CalClientLoadStatus status, gpointer data) } if (free_uri) { - g_free (priv->loading_uri); - priv->loading_uri = NULL; + g_free (*loading_uri); + *loading_uri = NULL; } } @@ -816,7 +869,6 @@ obj_removed_cb (CalClient *client, const char *uid, gpointer data) tag_calendar_by_client (priv->date_navigator, priv->client); } - GtkWidget * gnome_calendar_construct (GnomeCalendar *gcal) { @@ -829,6 +881,9 @@ gnome_calendar_construct (GnomeCalendar *gcal) priv = gcal->priv; + /* + * Calendar Folder Client. + */ priv->client = cal_client_new (); if (!priv->client) return NULL; @@ -842,13 +897,32 @@ gnome_calendar_construct (GnomeCalendar *gcal) alarm_notify_add_client (priv->client); - e_calendar_table_set_cal_client (E_CALENDAR_TABLE (priv->todo), priv->client); + e_day_view_set_cal_client (E_DAY_VIEW (priv->day_view), + priv->client); + e_day_view_set_cal_client (E_DAY_VIEW (priv->work_week_view), + priv->client); + e_week_view_set_cal_client (E_WEEK_VIEW (priv->week_view), + priv->client); + e_week_view_set_cal_client (E_WEEK_VIEW (priv->month_view), + priv->client); + + /* + * TaskPad Folder Client. + */ + priv->task_pad_client = cal_client_new (); + if (!priv->task_pad_client) + return NULL; - e_day_view_set_cal_client (E_DAY_VIEW (priv->day_view), priv->client); - e_day_view_set_cal_client (E_DAY_VIEW (priv->work_week_view), priv->client); - e_week_view_set_cal_client (E_WEEK_VIEW (priv->week_view), priv->client); - e_week_view_set_cal_client (E_WEEK_VIEW (priv->month_view), priv->client); + gtk_signal_connect (GTK_OBJECT (priv->task_pad_client), "cal_loaded", + GTK_SIGNAL_FUNC (cal_loaded_cb), gcal); + alarm_notify_add_client (priv->task_pad_client); + + e_calendar_table_set_cal_client (E_CALENDAR_TABLE (priv->todo), + priv->task_pad_client); + + + /* Get the default view to show. */ view = calendar_config_get_default_view (); switch (view) { case 1: @@ -911,6 +985,7 @@ gboolean gnome_calendar_open (GnomeCalendar *gcal, char *file, GnomeCalendarOpenMode gcom) { GnomeCalendarPrivate *priv; + LoadState initial_load_state; g_return_val_if_fail (gcal != NULL, FALSE); g_return_val_if_fail (GNOME_IS_CALENDAR (gcal), FALSE); @@ -918,8 +993,10 @@ gnome_calendar_open (GnomeCalendar *gcal, char *file, GnomeCalendarOpenMode gcom priv = gcal->priv; g_return_val_if_fail (priv->load_state == LOAD_STATE_NOT_LOADED, FALSE); + g_return_val_if_fail (priv->task_pad_load_state == LOAD_STATE_NOT_LOADED, FALSE); g_assert (priv->loading_uri == NULL); + g_assert (priv->task_pad_loading_uri == NULL); priv->loading_uri = g_strdup (file); @@ -932,6 +1009,8 @@ gnome_calendar_open (GnomeCalendar *gcal, char *file, GnomeCalendarOpenMode gcom return FALSE; } + initial_load_state = priv->load_state; + if (!cal_client_load_calendar (priv->client, file)) { priv->load_state = LOAD_STATE_NOT_LOADED; g_free (priv->loading_uri); @@ -941,6 +1020,22 @@ gnome_calendar_open (GnomeCalendar *gcal, char *file, GnomeCalendarOpenMode gcom return FALSE; } + /* Open the appropriate Tasks folder to show in the TaskPad. + Currently we just show the folder named "Tasks", but it will be + a per-calendar option in future. */ + priv->task_pad_loading_uri = g_strdup_printf ("%s/local/Tasks/tasks.ics", evolution_dir); + priv->task_pad_load_state = initial_load_state; + + if (!cal_client_load_calendar (priv->task_pad_client, + priv->task_pad_loading_uri)) { + priv->task_pad_load_state = LOAD_STATE_NOT_LOADED; + g_free (priv->task_pad_loading_uri); + priv->task_pad_loading_uri = NULL; + + g_message ("gnome_calendar_open(): Could not issue the request"); + return FALSE; + } + return TRUE; } diff --git a/calendar/gui/tasks-control.c b/calendar/gui/tasks-control.c index ba2b699dd2..7721b0d08a 100644 --- a/calendar/gui/tasks-control.c +++ b/calendar/gui/tasks-control.c @@ -219,7 +219,8 @@ tasks_control_new_task_cmd (BonoboUIComponent *uic, gpointer data, const char *path) { - g_print ("Create new task\n"); + ETasks *tasks = data; + e_tasks_new_task (tasks); } diff --git a/calendar/gui/widget-util.c b/calendar/gui/widget-util.c index 9d271d29f3..d6034ce8b0 100644 --- a/calendar/gui/widget-util.c +++ b/calendar/gui/widget-util.c @@ -47,11 +47,8 @@ date_edit_new (gboolean show_date, gboolean show_time) e_date_edit_set_show_date (dedit, show_date); e_date_edit_set_show_time (dedit, show_time); - e_date_edit_set_time_popup_range (dedit, - calendar_config_get_day_start_hour (), - calendar_config_get_day_end_hour ()); - e_date_edit_set_week_start_day (dedit, (calendar_config_get_week_start_day () + 6) % 7); - e_date_edit_set_show_week_numbers (dedit, calendar_config_get_dnav_show_week_no ()); + + calendar_config_configure_e_date_edit (dedit); return GTK_WIDGET (dedit); } |