/* $Id: monthview_gui.c,v 1.35 2006/06/23 13:38:22 rousseau Exp $ */ /******************************************************************************* * monthview_gui.c * A module of J-Pilot http://jpilot.org * * Copyright (C) 1999-2002 by Judd Montgomery * * 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; 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 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 ******************************************************************************/ #include "config.h" #include "i18n.h" #include #include #include #include #include "utils.h" #include "print.h" #include "prefs.h" #include "log.h" #include "datebook.h" #include #include "config.h" extern int datebook_category; extern int glob_app; static GtkWidget *window=NULL; static GtkWidget *glob_month_vbox; static GtkWidget *glob_month_labels[37]; #ifdef ENABLE_GTK2 static GObject *glob_month_text_buffers[37]; static GtkWidget *glob_month_text_views[37]; static GObject *big_text_buffer; #else static GtkWidget *glob_month_texts[37]; static GtkWidget *big_text; #endif static GtkWidget *glob_month_month_label; static GtkWidget *glob_last_hbox_row; static int glob_offset; static struct tm glob_month_date; int display_months_appts(struct tm *glob_month_date, GtkWidget **glob_month_texts); void hide_show_month_boxes(); static gboolean cb_destroy(GtkWidget *widget) { int n; GString *gstr; GtkWidget *text; window = NULL; for (n=0; n<37; n++) { #ifdef ENABLE_GTK2 text = glob_month_text_views[n]; #else text = glob_month_texts[n]; #endif gstr = gtk_object_get_data(GTK_OBJECT(text), "gstr"); if (gstr) { g_string_free(gstr, TRUE); gtk_object_remove_data(GTK_OBJECT(text), "gstr"); } } return FALSE; } static void cb_quit(GtkWidget *widget, gpointer data) { int w, h; gdk_window_get_size(window->window, &w, &h); set_pref(PREF_MONTHVIEW_WIDTH, w, NULL, FALSE); set_pref(PREF_MONTHVIEW_HEIGHT, h, NULL, FALSE); gtk_widget_destroy(data); } static void cb_month_move(GtkWidget *widget, gpointer data) { if (GPOINTER_TO_INT(data)==-1) { glob_month_date.tm_mday=15; sub_days_from_date(&glob_month_date, 30); } if (GPOINTER_TO_INT(data)==1) { glob_month_date.tm_mday=15; add_days_to_date(&glob_month_date, 30); } hide_show_month_boxes(); #ifdef ENABLE_GTK2 display_months_appts(&glob_month_date, glob_month_text_views); #else display_months_appts(&glob_month_date, glob_month_texts); #endif } /*---------------------------------------------------------------------- * cb_month_print This is where month printing is kicked off from *----------------------------------------------------------------------*/ static void cb_month_print(GtkWidget *widget, gpointer data) { long paper_size; jp_logf(JP_LOG_DEBUG, "cb_month_print called\n"); if (print_gui(window, DATEBOOK, 3, 0x04) == DIALOG_SAID_PRINT) { get_pref(PREF_PAPER_SIZE, &paper_size, NULL); if (paper_size==1) { print_months_appts(&glob_month_date, PAPER_A4); } else { print_months_appts(&glob_month_date, PAPER_Letter); } } } /*----------------------------------------------------------------------*/ static void cb_enter_notify(GtkWidget *widget, GdkEvent *event, gpointer data) { static int prev_day=-1; GString *gstr; if (prev_day==GPOINTER_TO_INT(data)+1-glob_offset) { return; } prev_day = GPOINTER_TO_INT(data)+1-glob_offset; gstr = gtk_object_get_data(GTK_OBJECT(widget), "gstr"); #ifdef ENABLE_GTK2 if (gstr) { gtk_text_buffer_set_text(GTK_TEXT_BUFFER(big_text_buffer), gstr->str, -1); } else { gtk_text_buffer_set_text(GTK_TEXT_BUFFER(big_text_buffer), "", -1); } #else gtk_text_set_point(GTK_TEXT(big_text), gtk_text_get_length(GTK_TEXT(big_text))); gtk_text_backward_delete(GTK_TEXT(big_text), gtk_text_get_length(GTK_TEXT(big_text))); if (gstr) { gtk_text_insert(GTK_TEXT(big_text), NULL, NULL, NULL, gstr->str, -1); } #endif } /* Called when a day is clicked on the month view */ static void cb_enter_selected_day(GtkWidget *widget, GdkEvent *event, gpointer data) { int day = GPOINTER_TO_INT(data) + 1 - glob_offset; if (glob_app != DATEBOOK) return; /* Redisplay the day view based on the date the user clicked on */ datebook_gui_setdate(glob_month_date.tm_year, glob_month_date.tm_mon, day); } /* * Hide, or show month boxes (days) according to the month. * Also, set a global offset for indexing day 1. * Also relabel day labels. */ void hide_show_month_boxes() { int n; int dow, ndim; int now_today; long fdow; char str[40]; int d; GtkWidget *text; #ifdef ENABLE_GTK2 char *markup_str; #endif /* Determine today for highlighting */ now_today = get_highlighted_today(&glob_month_date); get_month_info(glob_month_date.tm_mon, 1, glob_month_date.tm_year, &dow, &ndim); get_pref(PREF_FDOW, &fdow, NULL); glob_offset = (7+dow-fdow)%7; d = 1 - glob_offset; if (glob_offset + ndim > 35) { gtk_widget_show(GTK_WIDGET(glob_last_hbox_row)); } else { gtk_widget_hide(GTK_WIDGET(glob_last_hbox_row)); } for (n=0; n<37; n++, d++) { #ifdef ENABLE_GTK2 text = glob_month_text_views[n]; #else text = glob_month_texts[n]; #endif g_snprintf(str, sizeof(str), "%d", d); #ifdef ENABLE_GTK2 if (d == now_today) { markup_str = g_markup_printf_escaped("%s", str); } else { markup_str = g_markup_printf_escaped("%s", str); } gtk_label_set_markup(GTK_LABEL(glob_month_labels[n]), markup_str); g_free(markup_str); #else if (d == now_today) { g_snprintf(str, sizeof(str), "%s%s", str, _(" (TODAY)")); } gtk_label_set_text(GTK_LABEL(glob_month_labels[n]), str); #endif if (n<7) { if (d>0) { gtk_widget_show(GTK_WIDGET(text)); gtk_widget_show(GTK_WIDGET(glob_month_labels[n])); } else { gtk_widget_hide(GTK_WIDGET(text)); gtk_widget_hide(GTK_WIDGET(glob_month_labels[n])); } } if (n>27) { if (d<=ndim) { gtk_widget_show(GTK_WIDGET(text)); gtk_widget_show(GTK_WIDGET(glob_month_labels[n])); } else { gtk_widget_hide(GTK_WIDGET(text)); gtk_widget_hide(GTK_WIDGET(glob_month_labels[n])); } } } } void create_month_boxes_texts(GtkWidget *month_vbox) { int i, j, n; GtkWidget *hbox_row; GtkWidget *vbox; GtkWidget *text; char str[80]; n=0; for (i=0; i<6; i++) { hbox_row = gtk_hbox_new(TRUE, 0); gtk_box_pack_start(GTK_BOX(month_vbox), hbox_row, TRUE, TRUE, 0); for (j=0; j<7; j++) { vbox = gtk_vbox_new(FALSE, 0); #ifdef ENABLE_GTK2 gtk_box_pack_start(GTK_BOX(hbox_row), vbox, TRUE, TRUE, 2); #else gtk_box_pack_start(GTK_BOX(hbox_row), vbox, TRUE, TRUE, 0); #endif n=i*7+j; if (n<37) { sprintf(str, "%d", n + 1); /* Day of month labels */ glob_month_labels[n] = gtk_label_new(str); gtk_misc_set_alignment(GTK_MISC(glob_month_labels[n]), 0.0, 0.5); gtk_box_pack_start(GTK_BOX(vbox), glob_month_labels[n], FALSE, FALSE, 0); #ifdef ENABLE_GTK2 /* text variable only used to save some typing */ text = glob_month_text_views[n] = gtk_text_view_new(); glob_month_text_buffers[n] = G_OBJECT(gtk_text_view_get_buffer(GTK_TEXT_VIEW(text))); gtk_widget_set_usize(GTK_WIDGET(text), 10, 10); gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(text), FALSE); gtk_text_view_set_editable(GTK_TEXT_VIEW(text), FALSE); gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text), GTK_WRAP_WORD); /* motion notify is overkill but the enter_notify event doesn't work */ gtk_signal_connect(GTK_OBJECT(text), "motion_notify_event", GTK_SIGNAL_FUNC(cb_enter_notify), GINT_TO_POINTER(n)); #else text = glob_month_texts[n] = gtk_text_new(NULL, NULL); gtk_widget_set_usize(GTK_WIDGET(glob_month_texts[n]), 10, 10); gtk_text_set_word_wrap(GTK_TEXT(glob_month_texts[n]), FALSE); gtk_signal_connect(GTK_OBJECT(glob_month_texts[n]), "enter_notify_event", GTK_SIGNAL_FUNC(cb_enter_notify), GINT_TO_POINTER(n)); #endif gtk_signal_connect(GTK_OBJECT(text), "button_press_event", GTK_SIGNAL_FUNC(cb_enter_selected_day), GINT_TO_POINTER(n)); gtk_box_pack_start(GTK_BOX(vbox), text, TRUE, TRUE, 0); } } } glob_last_hbox_row = hbox_row; #ifdef ENABLE_GTK2 text = gtk_text_view_new(); big_text_buffer = G_OBJECT(gtk_text_view_get_buffer(GTK_TEXT_VIEW(text))); gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(text), FALSE); gtk_text_view_set_editable(GTK_TEXT_VIEW(text), FALSE); gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text), GTK_WRAP_WORD); gtk_widget_set_usize(GTK_WIDGET(text), 10, 10); gtk_box_pack_start(GTK_BOX(month_vbox), text, TRUE, TRUE, 4); #else big_text = gtk_text_new(NULL, NULL); gtk_widget_set_usize(GTK_WIDGET(big_text), 10, 10); gtk_box_pack_start(GTK_BOX(month_vbox), big_text, TRUE, TRUE, 0); #endif } int display_months_appts(struct tm *date_in, GtkWidget **day_texts) { AppointmentList *a_list; AppointmentList *temp_al; struct tm date; GtkWidget **texts; #ifdef ENABLE_GTK2 GObject **text_buffers; #endif char desc[100]; char datef[20]; char str[80]; int dow; int ndim; int n; int mask; int num_shown; #ifdef ENABLE_DATEBK int ret; int cat_bit; int db3_type; long use_db3_tags; struct db4_struct db4; #endif GString *gstr; GtkWidget *temp_text; texts = &day_texts[glob_offset]; #ifdef ENABLE_GTK2 text_buffers = &glob_month_text_buffers[glob_offset]; #endif a_list = NULL; mask=0; for (n=0; n<37; n++) { #ifdef ENABLE_GTK2 temp_text = glob_month_text_views[n]; #else temp_text = glob_month_texts[n]; #endif gstr = gtk_object_get_data(GTK_OBJECT(temp_text), "gstr"); if (gstr) { g_string_free(gstr, TRUE); gtk_object_remove_data(GTK_OBJECT(temp_text), "gstr"); } } /* Set Month name label */ jp_strftime(str, sizeof(str), "%B %Y", date_in); gtk_label_set_text(GTK_LABEL(glob_month_month_label), str); memcpy(&date, date_in, sizeof(struct tm)); /* Get all of the appointments */ get_days_appointments2(&a_list, NULL, 2, 2, 2, NULL); get_month_info(date.tm_mon, 1, date.tm_year, &dow, &ndim); weed_datebook_list(&a_list, date.tm_mon, date.tm_year, 0, &mask); for (n=0, date.tm_mday=1; date.tm_mday<=ndim; date.tm_mday++, n++) { gstr=NULL; date.tm_sec=0; date.tm_min=0; date.tm_hour=11; date.tm_isdst=-1; date.tm_wday=0; date.tm_yday=1; mktime(&date); #ifdef ENABLE_GTK2 gtk_text_buffer_set_text(GTK_TEXT_BUFFER(text_buffers[n]), "", -1); #else gtk_text_set_point(GTK_TEXT(texts[n]), gtk_text_get_length(GTK_TEXT(texts[n]))); gtk_text_backward_delete(GTK_TEXT(texts[n]), gtk_text_get_length(GTK_TEXT(texts[n]))); #endif num_shown = 0; for (temp_al = a_list; temp_al; temp_al=temp_al->next) { #ifdef ENABLE_DATEBK get_pref(PREF_USE_DB3, &use_db3_tags, NULL); if (use_db3_tags) { ret = db3_parse_tag(temp_al->mappt.appt.note, &db3_type, &db4); jp_logf(JP_LOG_DEBUG, "category = 0x%x\n", db4.category); cat_bit=1<mappt.appt), &date)) { if (num_shown) { #ifdef ENABLE_GTK2 gtk_text_buffer_insert_at_cursor(GTK_TEXT_BUFFER(text_buffers[n]), "\n", -1); #else gtk_text_insert(GTK_TEXT(texts[n]), NULL, NULL, NULL, "\n", -1); #endif g_string_append(gstr, "\n"); } else { gstr=g_string_new(""); } num_shown++; if (temp_al->mappt.appt.event) { strcpy(desc, "*"); } else { get_pref_time_no_secs(datef); jp_strftime(desc, sizeof(desc), datef, &(temp_al->mappt.appt.begin)); strcat(desc, " "); } g_string_append(gstr, desc); g_string_append(gstr, temp_al->mappt.appt.description); if (temp_al->mappt.appt.description) { strncat(desc, temp_al->mappt.appt.description, 36); desc[35]='\0'; } remove_cr_lfs(desc); /* Append number of anniversary years if enabled & appropriate */ append_anni_years(desc, 35, &date, &temp_al->mappt.appt); #ifdef ENABLE_GTK2 gtk_text_buffer_insert_at_cursor(GTK_TEXT_BUFFER(text_buffers[n]), desc, -1); #else gtk_text_insert(GTK_TEXT(texts[n]), NULL, NULL, NULL, desc, -1); #endif } } gtk_object_set_data(GTK_OBJECT(texts[n]), "gstr", gstr); } free_AppointmentList(&a_list); return EXIT_SUCCESS; } void monthview_gui(struct tm *date_in) { struct tm date; GtkWidget *label; GtkWidget *button; #ifndef ENABLE_GTK2 GtkWidget *arrow; #endif GtkWidget *align; GtkWidget *vbox; GtkWidget *hbox; GtkWidget *hbox_temp; int i; char str[256]; char str_dow[256]; long fdow; char title[200]; long w, h; if (window) { /* Delete any existing window to ensure that new window is biased * around currently selected date and so that the new window * contents are updated with any changes on the day view. */ gtk_widget_destroy(window); } memcpy(&glob_month_date, date_in, sizeof(struct tm)); get_pref(PREF_FDOW, &fdow, NULL); get_pref(PREF_MONTHVIEW_WIDTH, &w, NULL); get_pref(PREF_MONTHVIEW_HEIGHT, &h, NULL); g_snprintf(title, sizeof(title), "%s %s", PN, _("Monthly View")); window = gtk_widget_new(GTK_TYPE_WINDOW, "type", GTK_WINDOW_TOPLEVEL, "title", title, NULL); gtk_window_set_default_size(GTK_WINDOW(window), w, h); gtk_container_set_border_width(GTK_CONTAINER(window), 10); gtk_signal_connect(GTK_OBJECT(window), "destroy", GTK_SIGNAL_FUNC(cb_destroy), window); vbox = gtk_vbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(window), vbox); /* This box has the close button and arrows in it */ align = gtk_alignment_new(0.5, 0.5, 0, 0); gtk_box_pack_start(GTK_BOX(vbox), align, FALSE, FALSE, 0); hbox_temp = gtk_hbutton_box_new(); gtk_button_box_set_spacing(GTK_BUTTON_BOX(hbox_temp), 6); gtk_container_set_border_width(GTK_CONTAINER(hbox_temp), 6); gtk_container_add(GTK_CONTAINER(align), hbox_temp); /*Make a left arrow for going back a week */ #ifdef ENABLE_GTK2 button = gtk_button_new_from_stock(GTK_STOCK_GO_BACK); #else button = gtk_button_new(); arrow = gtk_arrow_new(GTK_ARROW_LEFT, GTK_SHADOW_OUT); gtk_container_add(GTK_CONTAINER(button), arrow); #endif gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(cb_month_move), GINT_TO_POINTER(-1)); gtk_box_pack_start(GTK_BOX(hbox_temp), button, FALSE, FALSE, 3); /* Create a "Close" button */ #ifdef ENABLE_GTK2 button = gtk_button_new_from_stock(GTK_STOCK_CLOSE); #else button = gtk_button_new_with_label(_("Close")); #endif gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(cb_quit), window); gtk_box_pack_start(GTK_BOX(hbox_temp), button, FALSE, FALSE, 0); /* Create a "Print" button */ #ifdef ENABLE_GTK2 button = gtk_button_new_from_stock(GTK_STOCK_PRINT); #else button = gtk_button_new_with_label(_("Print")); #endif gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(cb_month_print), window); gtk_box_pack_start(GTK_BOX(hbox_temp), button, FALSE, FALSE, 0); /*Make a right arrow for going forward a week */ #ifdef ENABLE_GTK2 button = gtk_button_new_from_stock(GTK_STOCK_GO_FORWARD); #else button = gtk_button_new(); arrow = gtk_arrow_new(GTK_ARROW_RIGHT, GTK_SHADOW_OUT); gtk_container_add(GTK_CONTAINER(button), arrow); #endif gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(cb_month_move), GINT_TO_POINTER(1)); gtk_box_pack_start(GTK_BOX(hbox_temp), button, FALSE, FALSE, 3); /* Month name label */ jp_strftime(str, sizeof(str), "%B %Y", &glob_month_date); glob_month_month_label = gtk_label_new(str); gtk_box_pack_start(GTK_BOX(vbox), glob_month_month_label, FALSE, FALSE, 0); /* We know this is on a Sunday */ memset(&date, 0, sizeof(date)); date.tm_hour=12; date.tm_mday=3; date.tm_mon=1; date.tm_year=80; mktime(&date); /* Get to the first day of week */ if (fdow) add_days_to_date(&date, fdow); /* Days of the week */ hbox = gtk_hbox_new(TRUE, 0); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); for (i=0; i<7; i++) { jp_strftime(str_dow, sizeof(str_dow), "%A", &date); label = gtk_label_new(str_dow); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); add_days_to_date(&date, 1); } /* glob_month_vbox */ glob_month_vbox = vbox; create_month_boxes_texts(glob_month_vbox); gtk_widget_show_all(window); hide_show_month_boxes(); #ifdef ENABLE_GTK2 display_months_appts(&glob_month_date, glob_month_text_views); #else display_months_appts(&glob_month_date, glob_month_texts); #endif }