[almanah] Highlight important entries in the calendar
- From: Philip Withnall <pwithnall src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [almanah] Highlight important entries in the calendar
- Date: Sun, 18 Apr 2010 13:27:00 +0000 (UTC)
commit ad5ccd5a9ca76d8032e0e4b1d759a18c6daa0157
Author: Philip Withnall <philip tecnocode co uk>
Date: Sun Apr 18 14:25:57 2010 +0100
Highlight important entries in the calendar
This creates a new AlmanahCalendar widget, which takes care of a few things
which require extensions to GtkCalendar. This is now used across the project.
Helps: bgo#572927
data/almanah.ui | 4 +-
src/Makefile.am | 4 +-
src/interface.c | 24 --------
src/main-window.c | 31 +++-------
src/printing.c | 29 ++++-----
src/storage-manager.c | 28 +++++++++
src/storage-manager.h | 1 +
src/widgets/calendar.c | 152 ++++++++++++++++++++++++++++++++++++++++++++++++
src/widgets/calendar.h | 57 ++++++++++++++++++
9 files changed, 265 insertions(+), 65 deletions(-)
---
diff --git a/data/almanah.ui b/data/almanah.ui
index 1731d12..2e75900 100644
--- a/data/almanah.ui
+++ b/data/almanah.ui
@@ -369,11 +369,11 @@
</packing>
</child>
<child>
- <object class="GtkCalendar" id="almanah_mw_calendar">
+ <object class="AlmanahCalendar" id="almanah_mw_calendar">
<property name="width-request">200</property>
<property name="can-focus">True</property>
+ <property name="show-details">False</property>
<signal name="day-selected" handler="mw_calendar_day_selected_cb"/>
- <signal name="month-changed" handler="almanah_calendar_month_changed_cb"/>
<accessibility>
<relation target="almanah_mw_calendar_label" type="labelled-by"/>
</accessibility>
diff --git a/src/Makefile.am b/src/Makefile.am
index bc816ed..627937f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -42,7 +42,9 @@ almanah_SOURCES = \
events/f-spot-photo.c \
events/f-spot-photo.h \
event-factories/f-spot.c \
- event-factories/f-spot.h
+ event-factories/f-spot.h \
+ widgets/calendar.c \
+ widgets/calendar.h
if HAVE_EVO
almanah_SOURCES += \
diff --git a/src/interface.c b/src/interface.c
index fcb3079..07d646c 100644
--- a/src/interface.c
+++ b/src/interface.c
@@ -106,27 +106,3 @@ almanah_interface_create_text_tags (GtkTextBuffer *text_buffer, gboolean connect
if (connect_events == TRUE)
g_signal_connect (tag, "event", G_CALLBACK (definition_tag_event_cb), NULL);
}
-
-/* TODO: This exists so that different calendars can be highlighted according to which days have entries
- * (i.e. the ones on the print dialogue). This should eventually be replaced by a custom calendar widget. */
-void
-almanah_calendar_month_changed_cb (GtkCalendar *calendar, gpointer user_data)
-{
- /* Mark the days on the calendar which have diary entries */
- guint i, year, month, num_days;
- gboolean *days;
-
- gtk_calendar_get_date (calendar, &year, &month, NULL);
- month++;
- days = almanah_storage_manager_get_month_marked_days (almanah->storage_manager, year, month, &num_days);
-
- gtk_calendar_clear_marks (calendar);
- for (i = 0; i < num_days; i++) {
- if (days[i] == TRUE)
- gtk_calendar_mark_day (calendar, i + 1);
- else
- gtk_calendar_unmark_day (calendar, i + 1);
- }
-
- g_free (days);
-}
diff --git a/src/main-window.c b/src/main-window.c
index 1f2888e..5832b5f 100644
--- a/src/main-window.c
+++ b/src/main-window.c
@@ -41,6 +41,7 @@
#include "definition.h"
#include "definition-manager-window.h"
#include "import-dialog.h"
+#include "widgets/calendar.h"
static void almanah_main_window_dispose (GObject *object);
static void save_window_state (AlmanahMainWindow *self);
@@ -87,7 +88,7 @@ void mw_view_button_clicked_cb (GtkButton *button, AlmanahMainWindow *main_windo
struct _AlmanahMainWindowPrivate {
GtkTextView *entry_view;
GtkTextBuffer *entry_buffer;
- GtkCalendar *calendar;
+ AlmanahCalendar *calendar;
GtkLabel *date_label;
GtkButton *view_button;
GtkAction *add_action;
@@ -194,7 +195,7 @@ almanah_main_window_new (void)
/* Grab our child widgets */
priv->entry_view = GTK_TEXT_VIEW (gtk_builder_get_object (builder, "almanah_mw_entry_view"));
priv->entry_buffer = gtk_text_view_get_buffer (priv->entry_view);
- priv->calendar = GTK_CALENDAR (gtk_builder_get_object (builder, "almanah_mw_calendar"));
+ priv->calendar = ALMANAH_CALENDAR (gtk_builder_get_object (builder, "almanah_mw_calendar"));
priv->date_label = GTK_LABEL (gtk_builder_get_object (builder, "almanah_mw_date_label"));
priv->view_button = GTK_BUTTON (gtk_builder_get_object (builder, "almanah_mw_view_button"));
priv->add_action = GTK_ACTION (gtk_builder_get_object (builder, "almanah_ui_add_definition"));
@@ -247,8 +248,7 @@ almanah_main_window_new (void)
g_signal_connect (almanah->storage_manager, "definition-removed", G_CALLBACK (mw_definition_removed_cb), main_window);
/* Select the current day and month */
- almanah_calendar_month_changed_cb (priv->calendar, NULL);
- mw_calendar_day_selected_cb (priv->calendar, main_window);
+ mw_jump_to_today_activate_cb (NULL, main_window);
/* Set up the treeview */
g_signal_connect (priv->events_selection, "changed", G_CALLBACK (mw_events_selection_changed_cb), main_window);
@@ -420,26 +420,16 @@ save_current_entry (AlmanahMainWindow *self)
/* Mark the day on the calendar if the entry was non-empty (and deleted)
* and update the state of the add definition action. */
if (entry_is_empty == TRUE) {
- gtk_calendar_unmark_day (priv->calendar, g_date_get_day (&date));
+ gtk_calendar_unmark_day (GTK_CALENDAR (priv->calendar), g_date_get_day (&date));
/* Since the entry is empty, remove all the events from the treeview */
gtk_list_store_clear (priv->event_store);
} else {
- gtk_calendar_mark_day (priv->calendar, g_date_get_day (&date));
+ gtk_calendar_mark_day (GTK_CALENDAR (priv->calendar), g_date_get_day (&date));
}
}
static void
-get_selected_date (AlmanahMainWindow *self, GDate *date)
-{
- guint year, month, day;
-
- gtk_calendar_get_date (self->priv->calendar, &year, &month, &day);
- month++;
- g_date_set_dmy (date, day, month, year);
-}
-
-static void
add_definition_to_current_entry (AlmanahMainWindow *self)
{
AlmanahMainWindowPrivate *priv = self->priv;
@@ -533,8 +523,7 @@ remove_definition_from_current_entry (AlmanahMainWindow *self)
void
almanah_main_window_select_date (AlmanahMainWindow *self, GDate *date)
{
- gtk_calendar_select_month (self->priv->calendar, g_date_get_month (date) - 1, g_date_get_year (date));
- gtk_calendar_select_day (self->priv->calendar, g_date_get_day (date));
+ almanah_calendar_select_date (self->priv->calendar, date);
}
static void
@@ -980,7 +969,7 @@ mw_events_updated_cb (AlmanahEventManager *event_manager, AlmanahEventFactoryTyp
GSList *_events, *events;
GDate date;
- get_selected_date (main_window, &date);
+ almanah_calendar_get_date (main_window->priv->calendar, &date);
_events = almanah_event_manager_get_events (event_manager, type_id, &date);
/* Clear all the events generated by this factory out of the list store first */
@@ -1023,7 +1012,7 @@ mw_calendar_day_selected_cb (GtkCalendar *calendar, AlmanahMainWindow *main_wind
AlmanahMainWindowPrivate *priv = main_window->priv;
/* Update the date label */
- get_selected_date (main_window, &calendar_date);
+ almanah_calendar_get_date (main_window->priv->calendar, &calendar_date);
/* Translators: This is a strftime()-format string for the date displayed at the top of the main window. */
g_date_strftime (calendar_string, sizeof (calendar_string), _("%A, %e %B %Y"), &calendar_date);
@@ -1158,7 +1147,7 @@ mw_definition_removed_cb (AlmanahStorageManager *storage_manager, const gchar *d
{
/* We need to remove any definition tags in the current entry which match @definition_text. It's
* probably easier to just reload the current entry, though. */
- mw_calendar_day_selected_cb (main_window->priv->calendar, main_window);
+ mw_calendar_day_selected_cb (GTK_CALENDAR (main_window->priv->calendar), main_window);
}
#ifdef ENABLE_SPELL_CHECKING
diff --git a/src/printing.c b/src/printing.c
index 46fd428..69524cd 100644
--- a/src/printing.c
+++ b/src/printing.c
@@ -25,6 +25,7 @@
#include "interface.h"
#include "main.h"
#include "printing.h"
+#include "widgets/calendar.h"
#define TITLE_MARGIN_BOTTOM 15 /* margin under the title, in pixels */
#define ENTRY_MARGIN_BOTTOM 10 /* margin under the entry, in pixels */
@@ -36,8 +37,8 @@ typedef struct {
GDate *start_date;
GDate *end_date;
GDate *current_date;
- GtkCalendar *start_calendar;
- GtkCalendar *end_calendar;
+ AlmanahCalendar *start_calendar;
+ AlmanahCalendar *end_calendar;
GtkSpinButton *line_spacing_spin_button;
gdouble line_spacing;
guint current_line;
@@ -411,10 +412,8 @@ create_custom_widget_cb (GtkPrintOperation *operation, AlmanahPrintOperation *al
GtkBox *vbox, *hbox;
/* Start and end calendars */
- start_calendar = gtk_calendar_new ();
- g_signal_connect (start_calendar, "month-changed", G_CALLBACK (almanah_calendar_month_changed_cb), NULL);
- end_calendar = gtk_calendar_new ();
- g_signal_connect (end_calendar, "month-changed", G_CALLBACK (almanah_calendar_month_changed_cb), NULL);
+ start_calendar = almanah_calendar_new ();
+ end_calendar = almanah_calendar_new ();
start_label = GTK_LABEL (gtk_label_new (_("Start date:")));
gtk_misc_set_alignment (GTK_MISC (start_label), 0.0, 0.5);
@@ -430,8 +429,8 @@ create_custom_widget_cb (GtkPrintOperation *operation, AlmanahPrintOperation *al
gtk_table_attach (table, GTK_WIDGET (start_label), 0, 1, 0, 1, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
gtk_table_attach (table, GTK_WIDGET (end_label), 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
- almanah_operation->start_calendar = GTK_CALENDAR (start_calendar);
- almanah_operation->end_calendar = GTK_CALENDAR (end_calendar);
+ almanah_operation->start_calendar = ALMANAH_CALENDAR (start_calendar);
+ almanah_operation->end_calendar = ALMANAH_CALENDAR (end_calendar);
/* Line spacing */
line_spacing_label = GTK_LABEL (gtk_label_new (_("Line spacing:")));
@@ -450,8 +449,8 @@ create_custom_widget_cb (GtkPrintOperation *operation, AlmanahPrintOperation *al
gtk_widget_show_all (GTK_WIDGET (vbox));
/* Make sure they have the dates with entries marked */
- almanah_calendar_month_changed_cb (GTK_CALENDAR (start_calendar), NULL);
- almanah_calendar_month_changed_cb (GTK_CALENDAR (end_calendar), NULL);
+ almanah_calendar_select_today (almanah_operation->start_calendar);
+ almanah_calendar_select_today (almanah_operation->end_calendar);
return GTK_WIDGET (vbox);
}
@@ -459,16 +458,12 @@ create_custom_widget_cb (GtkPrintOperation *operation, AlmanahPrintOperation *al
static void
custom_widget_apply_cb (GtkPrintOperation *operation, GtkWidget *widget, AlmanahPrintOperation *almanah_operation)
{
- guint year, month, day;
-
/* Start date */
- gtk_calendar_get_date (almanah_operation->start_calendar, &year, &month, &day);
- g_date_set_dmy (almanah_operation->start_date, day, month + 1, year);
- g_date_set_dmy (almanah_operation->current_date, day, month + 1, year);
+ almanah_calendar_get_date (almanah_operation->start_calendar, almanah_operation->start_date);
+ almanah_calendar_get_date (almanah_operation->start_calendar, almanah_operation->current_date);
/* End date */
- gtk_calendar_get_date (almanah_operation->end_calendar, &year, &month, &day);
- g_date_set_dmy (almanah_operation->end_date, day, month + 1, year);
+ almanah_calendar_get_date (almanah_operation->end_calendar, almanah_operation->end_date);
/* Ensure they're in order */
if (g_date_compare (almanah_operation->start_date, almanah_operation->end_date) > 0) {
diff --git a/src/storage-manager.c b/src/storage-manager.c
index c0b4659..8706786 100644
--- a/src/storage-manager.c
+++ b/src/storage-manager.c
@@ -1007,6 +1007,34 @@ almanah_storage_manager_get_month_marked_days (AlmanahStorageManager *self, GDat
return days;
}
+/* NOTE: Free results with g_free. Return value is 0-based. */
+gboolean *
+almanah_storage_manager_get_month_important_days (AlmanahStorageManager *self, GDateYear year, GDateMonth month, guint *num_days)
+{
+ AlmanahQueryResults *results;
+ gint i;
+ gboolean *days;
+
+ i = g_date_get_days_in_month (month, year);
+ if (num_days != NULL)
+ *num_days = i;
+ days = g_malloc0 (sizeof (gboolean) * i);
+
+ results = almanah_storage_manager_query (self, "SELECT day FROM entries WHERE year = %u AND month = %u AND is_important = 1", NULL,
+ year,
+ month);
+
+ if (results == NULL)
+ return days;
+
+ for (i = 1; i <= results->rows; i++)
+ days[atoi (results->data[i]) - 1] = TRUE;
+
+ almanah_storage_manager_free_results (results);
+
+ return days;
+}
+
/**
* almanah_storage_manager_get_definitions:
* @self: an #AlmanahStorageManager
diff --git a/src/storage-manager.h b/src/storage-manager.h
index de14656..e572fa3 100644
--- a/src/storage-manager.h
+++ b/src/storage-manager.h
@@ -86,6 +86,7 @@ gint almanah_storage_manager_search_entries (AlmanahStorageManager *self, const
GSList *almanah_storage_manager_get_entries (AlmanahStorageManager *self) G_GNUC_WARN_UNUSED_RESULT;
gboolean *almanah_storage_manager_get_month_marked_days (AlmanahStorageManager *self, GDateYear year, GDateMonth month, guint *num_days);
+gboolean *almanah_storage_manager_get_month_important_days (AlmanahStorageManager *self, GDateYear year, GDateMonth month, guint *num_days);
GSList *almanah_storage_manager_get_definitions (AlmanahStorageManager *self);
AlmanahDefinition *almanah_storage_manager_get_definition (AlmanahStorageManager *self, const gchar *definition_text);
diff --git a/src/widgets/calendar.c b/src/widgets/calendar.c
new file mode 100644
index 0000000..44a147d
--- /dev/null
+++ b/src/widgets/calendar.c
@@ -0,0 +1,152 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ * Almanah
+ * Copyright (C) Philip Withnall 2010 <philip tecnocode co uk>
+ *
+ * Almanah 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Almanah 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 Almanah. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include "calendar.h"
+#include "storage-manager.h"
+#include "main.h"
+
+static void almanah_calendar_finalize (GObject *object);
+static void almanah_calendar_month_changed (GtkCalendar *calendar);
+static gchar *almanah_calendar_detail_func (GtkCalendar *calendar, guint year, guint month, guint day, gpointer user_data);
+
+struct _AlmanahCalendarPrivate {
+ gboolean *important_days;
+};
+
+G_DEFINE_TYPE (AlmanahCalendar, almanah_calendar, GTK_TYPE_CALENDAR)
+
+static void
+almanah_calendar_class_init (AlmanahCalendarClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GtkCalendarClass *calendar_class = GTK_CALENDAR_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (AlmanahCalendarPrivate));
+
+ gobject_class->finalize = almanah_calendar_finalize;
+
+ calendar_class->month_changed = almanah_calendar_month_changed;
+}
+
+static void
+almanah_calendar_init (AlmanahCalendar *self)
+{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, ALMANAH_TYPE_CALENDAR, AlmanahCalendarPrivate);
+ gtk_calendar_set_detail_func (GTK_CALENDAR (self), almanah_calendar_detail_func, NULL, NULL);
+}
+
+static void
+almanah_calendar_finalize (GObject *object)
+{
+ AlmanahCalendarPrivate *priv = ALMANAH_CALENDAR (object)->priv;
+
+ g_free (priv->important_days);
+
+ /* Chain up to the parent class */
+ G_OBJECT_CLASS (almanah_calendar_parent_class)->finalize (object);
+}
+
+static void
+almanah_calendar_month_changed (GtkCalendar *calendar)
+{
+ AlmanahCalendarPrivate *priv = ALMANAH_CALENDAR (calendar)->priv;
+ guint i, year, month, num_days;
+ gboolean *days;
+
+ /* Mark the days on the calendar which have diary entries */
+ gtk_calendar_get_date (calendar, &year, &month, NULL);
+ month++;
+ days = almanah_storage_manager_get_month_marked_days (almanah->storage_manager, year, month, &num_days);
+
+ gtk_calendar_clear_marks (calendar);
+ for (i = 0; i < num_days; i++) {
+ if (days[i] == TRUE)
+ gtk_calendar_mark_day (calendar, i + 1);
+ else
+ gtk_calendar_unmark_day (calendar, i + 1);
+ }
+
+ g_free (days);
+
+ /* Cache the days which are important, so that the detail function isn't hideously slow */
+ g_free (priv->important_days);
+ priv->important_days = almanah_storage_manager_get_month_important_days (almanah->storage_manager, year, month, &num_days);
+}
+
+static gchar *
+almanah_calendar_detail_func (GtkCalendar *calendar, guint year, guint month, guint day, gpointer user_data)
+{
+ AlmanahCalendarPrivate *priv = ALMANAH_CALENDAR (calendar)->priv;
+ guint calendar_year, calendar_month;
+
+ gtk_calendar_get_date (calendar, &calendar_year, &calendar_month, NULL);
+
+ /* Check we actually have the data available for the requested month */
+ if (priv->important_days == NULL || year != calendar_year || month != calendar_month)
+ return NULL;
+
+ /* Display markup if the day is important; don't otherwise */
+ if (priv->important_days[day - 1] == TRUE) {
+ /* Translators: This is the detail string for important days as displayed in the calendar. */
+ return g_strdup (_("Important!"));
+ }
+ return NULL;
+}
+
+GtkWidget *
+almanah_calendar_new (void)
+{
+ return g_object_new (ALMANAH_TYPE_CALENDAR, NULL);
+}
+
+void
+almanah_calendar_select_date (AlmanahCalendar *self, GDate *date)
+{
+ g_return_if_fail (ALMANAH_IS_CALENDAR (self));
+ g_return_if_fail (date != NULL);
+
+ gtk_calendar_select_month (GTK_CALENDAR (self), g_date_get_month (date) - 1, g_date_get_year (date));
+ gtk_calendar_select_day (GTK_CALENDAR (self), g_date_get_day (date));
+}
+
+void
+almanah_calendar_select_today (AlmanahCalendar *self)
+{
+ GDate current_date;
+
+ g_return_if_fail (ALMANAH_IS_CALENDAR (self));
+
+ g_date_set_time_t (¤t_date, time (NULL));
+ almanah_calendar_select_date (self, ¤t_date);
+}
+
+void
+almanah_calendar_get_date (AlmanahCalendar *self, GDate *date)
+{
+ guint year, month, day;
+
+ g_return_if_fail (ALMANAH_IS_CALENDAR (self));
+ g_return_if_fail (date != NULL);
+
+ gtk_calendar_get_date (GTK_CALENDAR (self), &year, &month, &day);
+ g_date_set_dmy (date, day, month + 1, year);
+}
diff --git a/src/widgets/calendar.h b/src/widgets/calendar.h
new file mode 100644
index 0000000..492f440
--- /dev/null
+++ b/src/widgets/calendar.h
@@ -0,0 +1,57 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ * Almanah
+ * Copyright (C) Philip Withnall 2010 <philip tecnocode co uk>
+ *
+ * Almanah 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Almanah 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 Almanah. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef ALMANAH_CALENDAR_H
+#define ALMANAH_CALENDAR_H
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define ALMANAH_TYPE_CALENDAR (almanah_calendar_get_type ())
+#define ALMANAH_CALENDAR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), ALMANAH_TYPE_CALENDAR, AlmanahCalendar))
+#define ALMANAH_CALENDAR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), ALMANAH_TYPE_CALENDAR, AlmanahCalendarClass))
+#define ALMANAH_IS_CALENDAR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), ALMANAH_TYPE_CALENDAR))
+#define ALMANAH_IS_CALENDAR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), ALMANAH_TYPE_CALENDAR))
+#define ALMANAH_CALENDAR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), ALMANAH_TYPE_CALENDAR, AlmanahCalendarClass))
+
+typedef struct _AlmanahCalendarPrivate AlmanahCalendarPrivate;
+
+typedef struct {
+ GtkCalendar parent;
+ AlmanahCalendarPrivate *priv;
+} AlmanahCalendar;
+
+typedef struct {
+ GtkCalendarClass parent;
+} AlmanahCalendarClass;
+
+GType almanah_calendar_get_type (void) G_GNUC_CONST;
+
+GtkWidget *almanah_calendar_new (void) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
+
+void almanah_calendar_select_date (AlmanahCalendar *self, GDate *date);
+void almanah_calendar_select_today (AlmanahCalendar *self);
+void almanah_calendar_get_date (AlmanahCalendar *self, GDate *date);
+
+G_END_DECLS
+
+#endif /* !ALMANAH_CALENDAR_H */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]