/* * openmoko-dates -- OpenMoko Calendar Application * * Authored by Chris Lord * * Copyright (C) 2006-2007 OpenMoko Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser Public License as published by * the Free Software Foundation; version 2 of the license. * * 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 Lesser Public License for more details. * * Current Version: $Rev$ ($Date$) [$Author$] */ #include #include #include #include #include #include #include #include "dates.h" #include "dates-month.h" #include "dates-utils.h" static gboolean hidden = TRUE; static void list_selection_changed_cb (GtkTreeSelection *selection, DatesData *data); static void set_range (DatesData *data, gint month) { gchar *title; jana_time_set_month (data->start, month); jana_time_set_day (data->start, 1); /* Set window title */ title = jana_utils_strftime (data->start, "%b %Y"); gtk_window_set_title (GTK_WINDOW (data->window), title); g_free (title); jana_gtk_month_view_set_month ( JANA_GTK_MONTH_VIEW (data->month_view), data->start); g_object_unref (data->end); data->end = jana_time_duplicate (data->start); jana_utils_time_set_start_of_week (data->start); jana_time_set_day (data->end, jana_utils_time_days_in_month ( jana_time_get_year (data->end), jana_time_get_month (data->end))); jana_utils_time_set_end_of_week (data->end); dates_utils_refresh_query (data); list_selection_changed_cb (gtk_tree_view_get_selection ( GTK_TREE_VIEW (data->month_list_view)), data); } static void refilter (DatesData *data) { jana_gtk_event_list_refilter ( (JanaGtkEventList *)data->month_list_view); jana_gtk_month_view_refilter ( (JanaGtkMonthView *)data->month_view); } static void page_shown (DatesData *data) { /* Remove window title setting callback */ if (data->title_idle) { g_source_remove (data->title_idle); data->title_idle = 0; } set_range (data, jana_time_get_month (data->start)); refilter (data); } static void page_hidden (DatesData *data) { if (jana_time_get_day (data->start) != 1) { /* Set time to the beginning of the month, so switching to * the edit/view tab and then back again doesn't decrement * the viewed month. */ jana_time_set_month (data->start, jana_time_get_month (data->start) + 1); jana_time_set_day (data->start, 1); } if (!data->title_idle) data->title_idle = g_idle_add ((GSourceFunc) dates_utils_title_idle_cb, data); } static void notify_visible_cb (GObject *gobject, GParamSpec *arg1, DatesData *data) { if ((!hidden) && (!GTK_WIDGET_VISIBLE (gobject))) { hidden = TRUE; page_hidden (data); } } static gboolean visibility_notify_event_cb (GtkWidget *widget, GdkEventVisibility *event, DatesData *data) { if (((event->state == GDK_VISIBILITY_PARTIAL) || (event->state == GDK_VISIBILITY_UNOBSCURED)) && (hidden)) { hidden = FALSE; page_shown (data); }/* else if ((event->state == GDK_VISIBILITY_FULLY_OBSCURED) && (!hidden)) { hidden = TRUE; }*/ return FALSE; } static void unmap_cb (GtkWidget *widget, DatesData *data) { if (!hidden) { hidden = TRUE; page_hidden (data); } } static void new_clicked_cb (GtkToolButton *button, DatesData *data) { JanaTime *time; if (!(time = dates_utils_event_list_get_time (JANA_GTK_EVENT_LIST ( data->list_view)))) { g_object_get (data->month_view, "selection", &time, NULL); if (!time) time = jana_time_duplicate (data->start); } if (jana_time_get_isdate (time)) { jana_time_set_isdate (time, FALSE); jana_time_set_hours (time, 9); } dates_utils_create_new_event (data, time); g_object_unref (time); data->editing = TRUE; gtk_notebook_set_current_page (GTK_NOTEBOOK (data->notebook), -1); } static void back_clicked_cb (GtkToolButton *button, DatesData *data) { gint month; if (jana_time_get_day (data->start) == 1) month = jana_time_get_month (data->start) - 1; else month = jana_time_get_month (data->start); set_range (data, month); } static void home_clicked_cb (GtkToolButton *button, DatesData *data) { g_object_unref (data->start); data->start = jana_ecal_utils_time_today (data->location); set_range (data, jana_time_get_month (data->start)); } static void forward_clicked_cb (GtkToolButton *button, DatesData *data) { gint month; if (jana_time_get_day (data->start) == 1) month = jana_time_get_month (data->start) + 1; else month = jana_time_get_month (data->start) + 2; set_range (data, month); } static void year_selection_changed_cb (JanaGtkYearView *year_view, gint month, DatesData *data) { GtkWidget *window = gtk_widget_get_toplevel (GTK_WIDGET (year_view)); gtk_widget_destroy (window); set_range (data, month); } static void year_clicked_cb (GtkButton *button, DatesData *data) { GtkWidget *window, *frame, *year_view; GList *store; JanaTime *now; /* Create window, set parent and set undecorated */ window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (data->window)); gtk_window_set_decorated (GTK_WINDOW (window), FALSE); gtk_window_set_modal (GTK_WINDOW (window), TRUE); gtk_window_set_type_hint (GTK_WINDOW (window), GDK_WINDOW_TYPE_HINT_DIALOG); /* Create border for undecorated window */ frame = gtk_frame_new (NULL); gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN); /* Create year view and set size */ /* Correct the year if we're viewing events from December */ if ((jana_time_get_month (data->start) == 12) && (jana_time_get_day (data->start) != 1)) jana_time_set_year (data->start, jana_time_get_year (data->start) + 1); jana_time_set_day (data->start, 1); jana_time_set_month (data->start, 1); g_object_unref (data->end); data->end = jana_time_duplicate (data->start); jana_time_set_year (data->end, jana_time_get_year (data->end) + 1); dates_utils_refresh_query (data); year_view = jana_gtk_year_view_new ( 3, data->start); /* Highlight the month that the current time is in */ now = jana_ecal_utils_time_now (data->location); jana_gtk_year_view_set_highlighted_time ( JANA_GTK_YEAR_VIEW (year_view), now); g_object_unref (now); g_signal_connect (year_view, "selection_changed", G_CALLBACK (year_selection_changed_cb), data); for (store = data->models; store; store = store->next) jana_gtk_year_view_add_store (JANA_GTK_YEAR_VIEW (year_view), JANA_GTK_EVENT_STORE (store->data)); gtk_window_resize (GTK_WINDOW (window), (data->window->allocation.width * 2)/3, (data->window->allocation.height * 2)/3); gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER_ON_PARENT); /* Pack and show widgets */ gtk_container_add (GTK_CONTAINER (window), frame); gtk_container_add (GTK_CONTAINER (frame), year_view); gtk_widget_show_all (window); /* Display window */ gtk_widget_show (window); } static void search_text_changed_cb (MokoSearchBar *bar, GtkEditable *editable, DatesData *data) { if (hidden || (!moko_search_bar_search_visible (bar))) return; if (data->category) { g_free (data->category); data->category = NULL; } g_free (data->search); data->search = g_utf8_casefold (gtk_entry_get_text ( GTK_ENTRY (editable)), -1); refilter (data); } static void search_combo_changed_cb (MokoSearchBar *bar, GtkComboBox *combo_box, DatesData *data) { if (hidden || moko_search_bar_search_visible (bar)) return; if (data->search) { g_free (data->search); data->search = NULL; } g_free (data->category); if (gtk_combo_box_get_active (combo_box) > 0) data->category = gtk_combo_box_get_active_text (combo_box); else data->category = NULL; refilter (data); } static void search_toggled_cb (MokoSearchBar *bar, gboolean search_visible, DatesData *data) { if (hidden) return; if (search_visible) { search_text_changed_cb (bar, (GtkEditable *) moko_search_bar_get_entry (bar), data); } else { search_combo_changed_cb (bar, moko_search_bar_get_combo_box (bar), data); } } static void view_size_allocate_cb (GtkWidget *view, GtkAllocation *allocation, GtkWidget *scroll) { static gint last_height = 0; if (allocation->height != last_height) { last_height = allocation->height; gtk_widget_set_size_request (scroll, -1, last_height * 0.33); } } static void day_selection_changed_cb (JanaGtkMonthView *self, JanaTime *day, DatesData *data) { GtkTreeModel *model; GtkTreeIter iter; gboolean set = FALSE; if (!day) return; /* Go through the rows in the event list and select/scroll to the * correct row */ model = gtk_tree_view_get_model ( GTK_TREE_VIEW (data->month_list_view)); if (gtk_tree_model_get_iter_first (model, &iter)) do { JanaTime *time; gtk_tree_model_get (model, &iter, JANA_GTK_EVENT_LIST_COL_TIME, &time, -1); if (!time) continue; if (jana_utils_time_compare (time, day, TRUE) == 0) { GtkTreeSelection *selection; GtkTreePath *path; selection = gtk_tree_view_get_selection ( GTK_TREE_VIEW (data->month_list_view)); gtk_tree_selection_select_iter (selection, &iter); path = gtk_tree_model_get_path (model, &iter); gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW ( data->month_list_view), path, NULL, TRUE, 0, 0); gtk_tree_path_free (path); set = TRUE; break; } } while (gtk_tree_model_iter_next (model, &iter)); if (!set) { /* If we didn't find a matching header for the time, clear * the selection. */ gtk_tree_selection_unselect_all (gtk_tree_view_get_selection ( GTK_TREE_VIEW (data->month_list_view))); } } static void list_selection_changed_cb (GtkTreeSelection *selection, DatesData *data) { /* If we're hidden, don't do anything */ if (hidden) return; dates_utils_event_list_selection_changed_cb (selection, data); } GtkWidget * dates_create_month_page (DatesData *data) { GtkWidget *vbox, *toolbar, *combo, *scroll, *ratio_vbox, *frame, *year_button, *year_label, *month_box; GtkToolItem *button; vbox = gtk_vbox_new (FALSE, 0); /* Create toolbar */ toolbar = gtk_toolbar_new (); gtk_box_pack_start (GTK_BOX (vbox), toolbar, FALSE, TRUE, 0); /* New button */ button = dates_utils_toolbutton_new (GTK_STOCK_NEW); gtk_toolbar_insert (GTK_TOOLBAR (toolbar), button, 0); gtk_toolbar_insert (GTK_TOOLBAR (toolbar), gtk_separator_tool_item_new (), 0); g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (new_clicked_cb), data); /* Forward button */ button = dates_utils_toolbutton_new (GTK_STOCK_GO_FORWARD); gtk_toolbar_insert (GTK_TOOLBAR (toolbar), button, 0); gtk_toolbar_insert (GTK_TOOLBAR (toolbar), gtk_separator_tool_item_new (), 0); g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (forward_clicked_cb), data); /* Home button */ button = dates_utils_toolbutton_new (GTK_STOCK_HOME); gtk_toolbar_insert (GTK_TOOLBAR (toolbar), button, 0); gtk_toolbar_insert (GTK_TOOLBAR (toolbar), gtk_separator_tool_item_new (), 0); g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (home_clicked_cb), data); /* Back button */ button = dates_utils_toolbutton_new (GTK_STOCK_GO_BACK); gtk_toolbar_insert (GTK_TOOLBAR (toolbar), button, 0); g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (back_clicked_cb), data); gtk_widget_show_all (toolbar); /* Create search box */ combo = gtk_combo_box_new_text (); data->month_searchbar = moko_search_bar_new_with_combo ( GTK_COMBO_BOX (combo)); gtk_box_pack_start (GTK_BOX (vbox), data->month_searchbar, FALSE, TRUE, 0); gtk_widget_show (data->month_searchbar); /* Create month view and year-view button */ data->month_view = jana_gtk_month_view_new (data->start); jana_gtk_month_view_set_visible_func (JANA_GTK_MONTH_VIEW ( data->month_view), (GtkTreeModelFilterVisibleFunc) dates_utils_event_store_filter_cb, data); g_object_set (G_OBJECT (jana_gtk_month_view_get_cell_renderer ( JANA_GTK_MONTH_VIEW (data->month_view))), "category_color_hash", data->category_color_hash, NULL); g_signal_connect (data->month_view, "selection_changed", G_CALLBACK (day_selection_changed_cb), data); frame = gtk_frame_new (NULL); gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN); year_button = gtk_button_new (); year_label = gtk_label_new ("Year view"); gtk_label_set_angle (GTK_LABEL (year_label), 90); gtk_container_add (GTK_CONTAINER (year_button), year_label); gtk_widget_show (year_label); gtk_widget_set_name (year_button, "moko-dates-hborder-button"); g_signal_connect (year_button, "clicked", G_CALLBACK (year_clicked_cb), data); gtk_container_add (GTK_CONTAINER (frame), data->month_view); gtk_widget_show (data->month_view); month_box = gtk_hbox_new (FALSE, 0); gtk_box_pack_start (GTK_BOX (month_box), frame, TRUE, TRUE, 0); gtk_box_pack_end (GTK_BOX (month_box), year_button, FALSE, TRUE, 0); gtk_widget_show (frame); gtk_widget_show (year_button); /* Create list view */ scroll = moko_finger_scroll_new (); data->month_list_view = jana_gtk_event_list_new (); gtk_tree_model_filter_set_visible_func (jana_gtk_event_list_get_filter ( JANA_GTK_EVENT_LIST (data->month_list_view)), (GtkTreeModelFilterVisibleFunc)dates_utils_event_list_filter_cb, data, NULL); gtk_container_add (GTK_CONTAINER (scroll), data->month_list_view); gtk_widget_show (data->month_list_view); g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW ( data->month_list_view)), "changed", G_CALLBACK (list_selection_changed_cb), data); ratio_vbox = gtk_vbox_new (FALSE, 0); gtk_box_pack_start (GTK_BOX (ratio_vbox), month_box, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (ratio_vbox), scroll, FALSE, TRUE, 0); gtk_widget_show (month_box); gtk_widget_show (scroll); gtk_box_pack_start (GTK_BOX (vbox), ratio_vbox, TRUE, TRUE, 0); gtk_widget_show (ratio_vbox); g_signal_connect (ratio_vbox, "size-allocate", G_CALLBACK (view_size_allocate_cb), scroll); gtk_widget_add_events (data->month_view, GDK_VISIBILITY_NOTIFY_MASK); g_signal_connect (data->month_view, "visibility-notify-event", G_CALLBACK (visibility_notify_event_cb), data); g_signal_connect (data->month_view, "notify::visible", G_CALLBACK (notify_visible_cb), data); g_signal_connect (vbox, "unmap", G_CALLBACK (unmap_cb), data); g_signal_connect (data->month_searchbar, "text_changed", G_CALLBACK (search_text_changed_cb), data); g_signal_connect (data->month_searchbar, "combo_changed", G_CALLBACK (search_combo_changed_cb), data); g_signal_connect (data->month_searchbar, "toggled", G_CALLBACK (search_toggled_cb), data); return vbox; }