[evince/wip/app: 8/19] shell: Port to GtkApplication
- From: Christian Persch <chpe src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evince/wip/app: 8/19] shell: Port to GtkApplication
- Date: Fri, 29 Jun 2012 10:08:38 +0000 (UTC)
commit a6f1720f8fff096445a1c3992c5fafd53054ff75
Author: Christian Persch <chpe gnome org>
Date: Tue Jun 12 18:53:35 2012 +0200
shell: Port to GtkApplication
shell/ev-application.c | 277 +++++++++++++++++++++++++-----------------------
shell/ev-application.h | 6 +-
shell/ev-gdbus.c | 13 ++-
shell/ev-window.c | 26 +----
shell/ev-window.h | 6 +-
shell/main.c | 18 +++-
6 files changed, 177 insertions(+), 169 deletions(-)
---
diff --git a/shell/ev-application.c b/shell/ev-application.c
index 8a58b2b..8a6c422 100644
--- a/shell/ev-application.c
+++ b/shell/ev-application.c
@@ -1,7 +1,7 @@
/* this file is part of evince, a gnome document viewer
*
* Copyright (C) 2004 Martin Kretzschmar
- * Copyright  2010 Christian Persch
+ * Copyright  2010, 2012 Christian Persch
*
* Author:
* Martin Kretzschmar <martink gnome org>
@@ -51,14 +51,13 @@
#endif /* ENABLE_DBUS */
struct _EvApplication {
- GObject base_instance;
+ GtkApplication base_instance;
gchar *uri;
gchar *dot_dir;
#ifdef ENABLE_DBUS
- GDBusConnection *connection;
EvEvinceApplicationImpl *impl;
EvMediaPlayerKeys *keys;
gboolean doc_registered;
@@ -72,12 +71,10 @@ struct _EvApplication {
};
struct _EvApplicationClass {
- GObjectClass base_class;
+ GtkApplicationClass base_class;
};
-static EvApplication *instance;
-
-G_DEFINE_TYPE (EvApplication, ev_application, G_TYPE_OBJECT);
+G_DEFINE_TYPE (EvApplication, ev_application, GTK_TYPE_APPLICATION);
#ifdef ENABLE_DBUS
#define APPLICATION_DBUS_OBJECT_PATH "/org/gnome/evince/Evince"
@@ -105,20 +102,21 @@ static void _ev_application_open_uri_at_dest (EvApplication *application,
guint timestamp);
/**
- * ev_application_get_instance:
- *
- * Checks for #EvApplication instance, if it doesn't exist it does create it.
- *
- * Returns: an instance of the #EvApplication data.
+ * ev_application_new:
+ *
+ * Creates a new #EvApplication instance.
+ *
+ * Returns: (transfer full): a newly created #EvApplication
*/
EvApplication *
-ev_application_get_instance (void)
+ev_application_new (void)
{
- if (!instance) {
- instance = EV_APPLICATION (g_object_new (EV_TYPE_APPLICATION, NULL));
- }
+ const GApplicationFlags flags = G_APPLICATION_NON_UNIQUE;
- return instance;
+ return g_object_new (EV_TYPE_APPLICATION,
+ "application-id", NULL,
+ "flags", flags,
+ NULL);
}
/* Session */
@@ -165,10 +163,10 @@ smclient_save_state_cb (EggSMClient *client,
}
static void
-smclient_quit_cb (EggSMClient *client,
- EvApplication *application)
+smclient_quit_cb (EggSMClient *client,
+ GApplication *application)
{
- ev_application_shutdown (application);
+ g_application_quit (application);
}
#endif /* WITH_SMCLIENT */
@@ -315,43 +313,27 @@ ev_spawn (const char *uri,
}
if (error != NULL) {
- g_warning ("Error launching evince %s: %s\n", uri, error->message);
+ g_printerr ("Error launching evince %s: %s\n", uri, error->message);
g_error_free (error);
}
g_free (cmdline);
}
-GList *
-ev_application_get_windows (EvApplication *application)
-{
- GList *l, *toplevels;
- GList *windows = NULL;
-
- toplevels = gtk_window_list_toplevels ();
-
- for (l = toplevels; l != NULL; l = l->next) {
- if (EV_IS_WINDOW (l->data)) {
- windows = g_list_append (windows, l->data);
- }
- }
-
- g_list_free (toplevels);
-
- return windows;
-}
-
static EvWindow *
ev_application_get_empty_window (EvApplication *application,
GdkScreen *screen)
{
EvWindow *empty_window = NULL;
- GList *windows = ev_application_get_windows (application);
- GList *l;
+ GList *windows, *l;
+ windows = gtk_application_get_windows (GTK_APPLICATION (application));
for (l = windows; l != NULL; l = l->next) {
EvWindow *window = EV_WINDOW (l->data);
+ if (!EV_IS_WINDOW (window))
+ continue;
+
if (ev_window_is_empty (window) &&
gtk_window_get_screen (GTK_WINDOW (window)) == screen) {
empty_window = window;
@@ -359,8 +341,6 @@ ev_application_get_empty_window (EvApplication *application,
}
}
- g_list_free (windows);
-
return empty_window;
}
@@ -399,18 +379,19 @@ on_reload_cb (GObject *source_object,
GVariant *value;
GError *error = NULL;
+ g_application_release (g_application_get_default ());
+
value = g_dbus_connection_call_finish (connection, res, &error);
- if (!value) {
- g_warning ("Failed to Reload: %s", error->message);
+ if (value != NULL) {
+ g_variant_unref (value);
+ } else {
+ g_printerr ("Failed to Reload: %s\n", error->message);
g_error_free (error);
}
- g_variant_unref (value);
/* We did not open a window, so manually clear the startup
* notification. */
gdk_notify_startup_complete ();
-
- ev_application_shutdown (EV_APP);
}
static void
@@ -426,9 +407,11 @@ on_register_uri_cb (GObject *source_object,
GVariantBuilder builder;
GError *error = NULL;
+ g_application_release (G_APPLICATION (application));
+
value = g_dbus_connection_call_finish (connection, res, &error);
if (!value) {
- g_warning ("Error registering document: %s\n", error->message);
+ g_printerr ("Error registering document: %s\n", error->message);
g_error_free (error);
_ev_application_open_uri_at_dest (application,
@@ -518,6 +501,7 @@ on_register_uri_cb (GObject *source_object,
NULL,
on_reload_cb,
NULL);
+ g_application_hold (G_APPLICATION (application));
g_variant_unref (value);
ev_register_doc_data_free (data);
}
@@ -546,23 +530,25 @@ ev_application_register_uri (EvApplication *application,
{
EvRegisterDocData *data;
- if (!application->connection)
+ if (!application->impl)
return;
if (application->doc_registered) {
/* Already registered, reload */
GList *windows, *l;
- windows = ev_application_get_windows (application);
+ windows = gtk_application_get_windows (GTK_APPLICATION (application));
for (l = windows; l != NULL; l = g_list_next (l)) {
EvWindow *ev_window = EV_WINDOW (l->data);
+ if (!EV_IS_WINDOW (ev_window))
+ continue;
+
ev_application_open_uri_in_window (application, uri, ev_window,
screen, dest, mode,
search_string,
timestamp);
}
- g_list_free (windows);
return;
}
@@ -575,7 +561,7 @@ ev_application_register_uri (EvApplication *application,
data->search_string = search_string ? g_strdup (search_string) : NULL;
data->timestamp = timestamp;
- g_dbus_connection_call (application->connection,
+ g_dbus_connection_call (g_application_get_dbus_connection (G_APPLICATION (application)),
EVINCE_DAEMON_SERVICE,
EVINCE_DAEMON_OBJECT_PATH,
EVINCE_DAEMON_INTERFACE,
@@ -587,6 +573,8 @@ ev_application_register_uri (EvApplication *application,
NULL,
on_register_uri_cb,
data);
+
+ g_application_hold (G_APPLICATION (application));
}
static void
@@ -603,7 +591,7 @@ ev_application_unregister_uri (EvApplication *application,
* so it's safe to use the sync api
*/
value = g_dbus_connection_call_sync (
- application->connection,
+ g_application_get_dbus_connection (G_APPLICATION (application)),
EVINCE_DAEMON_SERVICE,
EVINCE_DAEMON_OBJECT_PATH,
EVINCE_DAEMON_INTERFACE,
@@ -615,7 +603,7 @@ ev_application_unregister_uri (EvApplication *application,
NULL,
&error);
if (value == NULL) {
- g_warning ("Error unregistering document: %s\n", error->message);
+ g_printerr ("Error unregistering document: %s\n", error->message);
g_error_free (error);
} else {
g_variant_unref (value);
@@ -875,8 +863,8 @@ ev_application_migrate_config_dir (EvApplication *application)
error = NULL;
g_file_move (old_file, new_file, 0, NULL, NULL, NULL, &error);
if (error) {
- g_warning ("Error migrating config file %s: %s\n",
- old_filename, error->message);
+ g_printerr ("Error migrating config file %s: %s\n",
+ old_filename, error->message);
g_error_free (error);
}
@@ -904,8 +892,8 @@ ev_application_migrate_config_dir (EvApplication *application)
error = NULL;
g_file_move (old_accels_file, new_accels_file, 0, NULL, NULL, NULL, &error);
if (error) {
- g_warning ("Error migrating accelerator specifications file %s: %s\n",
- old_accels, error->message);
+ g_printerr ("Error migrating accelerator specifications file %s: %s\n",
+ old_accels, error->message);
g_error_free (error);
}
@@ -917,9 +905,11 @@ ev_application_migrate_config_dir (EvApplication *application)
g_free (old_accels);
}
-void
-ev_application_shutdown (EvApplication *application)
+static void
+ev_application_shutdown (GApplication *gapplication)
{
+ EvApplication *application = EV_APPLICATION (gapplication);
+
if (application->uri) {
#ifdef ENABLE_DBUS
ev_application_unregister_uri (application,
@@ -934,43 +924,101 @@ ev_application_shutdown (EvApplication *application)
g_object_unref (application->scr_saver);
application->scr_saver = NULL;
+ g_free (application->dot_dir);
+ application->dot_dir = NULL;
+
+ G_APPLICATION_CLASS (ev_application_parent_class)->shutdown (gapplication);
+}
+
+static void
+ev_application_activate (GApplication *gapplication)
+{
+ EvApplication *application = EV_APPLICATION (gapplication);
+ GList *windows, *l;
+
+ windows = gtk_application_get_windows (GTK_APPLICATION (application));
+ for (l = windows; l != NULL; l = l->next) {
+ EvWindow *window = l->data;
+
+ if (!EV_IS_WINDOW (window))
+ continue;
+
+ gtk_window_present (GTK_WINDOW (window));
+ }
+}
+
#ifdef ENABLE_DBUS
- if (application->keys) {
- g_object_unref (application->keys);
- application->keys = NULL;
- }
+
+static gboolean
+ev_application_dbus_register (GApplication *gapplication,
+ GDBusConnection *connection,
+ const gchar *object_path,
+ GError **error)
+{
+ EvApplication *application = EV_APPLICATION (gapplication);
+ EvEvinceApplicationImpl *impl;
+
+ if (!G_APPLICATION_CLASS (ev_application_parent_class)->dbus_register (gapplication,
+ connection,
+ object_path,
+ error))
+ return FALSE;
+
+ impl = ev_evince_application_impl_new ();
+ if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (impl),
+ connection,
+ APPLICATION_DBUS_OBJECT_PATH,
+ error)) {
+ g_object_unref (impl);
+ return FALSE;
+ }
+
+ application->impl = impl;
+ application->keys = ev_media_player_keys_new ();
+ return TRUE;
+}
+
+static void
+ev_application_dbus_unregister (GApplication *gapplication,
+ GDBusConnection *connection,
+ const gchar *object_path)
+{
+ EvApplication *application = EV_APPLICATION (gapplication);
+
+ if (application->keys) {
+ g_object_unref (application->keys);
+ application->keys = NULL;
+ }
if (application->impl != NULL) {
g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (application->impl));
g_object_unref (application->impl);
application->impl = NULL;
}
- if (application->connection != NULL) {
- g_object_unref (application->connection);
- application->connection = NULL;
- }
-#endif /* ENABLE_DBUS */
-
- g_free (application->dot_dir);
- application->dot_dir = NULL;
- g_object_unref (application);
- instance = NULL;
-
- gtk_main_quit ();
+ G_APPLICATION_CLASS (ev_application_parent_class)->dbus_unregister (gapplication,
+ connection,
+ object_path);
}
+#endif /* ENABLE_DBUS */
+
static void
ev_application_class_init (EvApplicationClass *ev_application_class)
{
+ GApplicationClass *g_application_class = G_APPLICATION_CLASS (ev_application_class);
+
+ g_application_class->activate = ev_application_activate;
+ g_application_class->shutdown = ev_application_shutdown;
+
+#ifdef ENABLE_DBUS
+ g_application_class->dbus_register = ev_application_dbus_register;
+ g_application_class->dbus_unregister = ev_application_dbus_unregister;
+#endif
}
static void
ev_application_init (EvApplication *ev_application)
{
-#ifdef ENABLE_DBUS
- GError *error = NULL;
-#endif
-
ev_application->dot_dir = g_build_filename (g_get_user_config_dir (),
"evince", NULL);
if (!g_file_test (ev_application->dot_dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))
@@ -980,79 +1028,42 @@ ev_application_init (EvApplication *ev_application)
ev_application_accel_map_load (ev_application);
-#ifdef ENABLE_DBUS
- ev_application->connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
- if (ev_application->connection != NULL) {
- EvEvinceApplicationImpl *impl;
-
- impl = ev_evince_application_impl_new ();
- if (g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (impl),
- ev_application->connection,
- APPLICATION_DBUS_OBJECT_PATH,
- &error)) {
- ev_application->impl = impl;
- } else {
- g_object_unref (impl);
- g_printerr ("Failed to register bus object: %s\n", error->message);
- g_error_free (error);
- }
- } else {
- g_printerr ("Failed to get bus connection: %s\n", error->message);
- g_error_free (error);
- }
-
- ev_application->keys = ev_media_player_keys_new ();
-#endif /* ENABLE_DBUS */
-
ev_application->scr_saver = totem_scrsaver_new ();
g_object_set (ev_application->scr_saver,
"reason", _("Running in presentation mode"),
NULL);
}
-GDBusConnection *
-ev_application_get_dbus_connection (EvApplication *application)
-{
-#ifdef ENABLE_DBUS
- return application->connection;
-#else
- return NULL;
-#endif
-}
-
gboolean
ev_application_has_window (EvApplication *application)
{
- GList *l, *toplevels;
- gboolean retval = FALSE;
+ GList *l, *windows;
- toplevels = gtk_window_list_toplevels ();
+ windows = gtk_application_get_windows (GTK_APPLICATION (application));
+ for (l = windows; l != NULL; l = l->next) {
+ if (!EV_IS_WINDOW (l->data))
+ continue;
- for (l = toplevels; l != NULL && !retval; l = l->next) {
- if (EV_IS_WINDOW (l->data))
- retval = TRUE;
+ return TRUE;
}
- g_list_free (toplevels);
-
- return retval;
+ return FALSE;
}
guint
ev_application_get_n_windows (EvApplication *application)
{
- GList *l, *toplevels;
- guint retval = 0;
+ GList *l, *windows;
+ guint retval = 0;
- toplevels = gtk_window_list_toplevels ();
+ windows = gtk_application_get_windows (GTK_APPLICATION (application));
+ for (l = windows; l != NULL && !retval; l = l->next) {
+ if (!EV_IS_WINDOW (l->data))
+ continue;
- for (l = toplevels; l != NULL; l = l->next) {
- if (EV_IS_WINDOW (l->data))
- retval++;
+ retval++;
}
- g_list_free (toplevels);
-
return retval;
}
diff --git a/shell/ev-application.h b/shell/ev-application.h
index f40c44c..b631127 100644
--- a/shell/ev-application.h
+++ b/shell/ev-application.h
@@ -44,12 +44,11 @@ typedef struct _EvApplicationClass EvApplicationClass;
#define EV_IS_APPLICATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), EV_TYPE_APPLICATION))
#define EV_APPLICATION_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS((object), EV_TYPE_APPLICATION, EvApplicationClass))
-#define EV_APP (ev_application_get_instance ())
+#define EV_APP ((EvApplication *) g_application_get_default ())
GType ev_application_get_type (void) G_GNUC_CONST;
-EvApplication *ev_application_get_instance (void);
+EvApplication *ev_application_new (void);
-void ev_application_shutdown (EvApplication *application);
gboolean ev_application_load_session (EvApplication *application);
void ev_application_open_window (EvApplication *application,
GdkScreen *screen,
@@ -73,7 +72,6 @@ void ev_application_open_uri_list (EvApplication *application,
GSList *uri_list,
GdkScreen *screen,
guint32 timestamp);
-GDBusConnection *ev_application_get_dbus_connection (EvApplication *application);
gboolean ev_application_has_window (EvApplication *application);
guint ev_application_get_n_windows (EvApplication *application);
GList *ev_application_get_windows (EvApplication *application);
diff --git a/shell/ev-gdbus.c b/shell/ev-gdbus.c
index f3e7063..c495c65 100644
--- a/shell/ev-gdbus.c
+++ b/shell/ev-gdbus.c
@@ -39,19 +39,20 @@ static gboolean
ev_evince_application_impl_get_window_list (EvEvinceApplication *object,
GDBusMethodInvocation *invocation)
{
- EvApplication *application = EV_APP;
GList *windows, *l;
GPtrArray *paths;
paths = g_ptr_array_new ();
- windows = ev_application_get_windows (application);
+ windows = gtk_application_get_windows (GTK_APPLICATION (g_application_get_default));
for (l = windows; l; l = g_list_next (l)) {
EvWindow *window = (EvWindow *)l->data;
+ if (!EV_IS_WINDOW (window))
+ continue;
+
g_ptr_array_add (paths, (gpointer) ev_window_get_dbus_object_path (window));
}
- g_list_free (windows);
g_ptr_array_add (paths, NULL);
ev_evince_application_complete_get_window_list (object, invocation,
@@ -106,17 +107,19 @@ ev_evince_application_impl_reload (EvEvinceApplication *object,
else
screen = gdk_screen_get_default ();
- windows = ev_application_get_windows (application);
+ windows = gtk_application_get_windows (GTK_APPLICATION (g_application_get_default ()));
for (l = windows; l != NULL; l = g_list_next (l)) {
EvWindow *ev_window = EV_WINDOW (l->data);
+ if (!EV_IS_WINDOW (ev_window))
+ continue;
+
ev_application_open_uri_in_window (application, NULL,
ev_window,
screen, dest, mode,
search_string,
timestamp);
}
- g_list_free (windows);
if (dest)
g_object_unref (dest);
diff --git a/shell/ev-window.c b/shell/ev-window.c
index 914ac1a..e350884 100644
--- a/shell/ev-window.c
+++ b/shell/ev-window.c
@@ -6,7 +6,7 @@
* Copyright (C) 2004 Martin Kretzschmar
* Copyright (C) 2004 Red Hat, Inc.
* Copyright (C) 2000, 2001, 2002, 2003, 2004 Marco Pesenti Gritti
- * Copyright  2003, 2004, 2005, 2009 Christian Persch
+ * Copyright  2003, 2004, 2005, 2009, 2012 Christian Persch
*
* Author:
* Martin Kretzschmar <martink gnome org>
@@ -368,11 +368,9 @@ static void ev_window_emit_doc_loaded (EvWindow *window);
#endif
static void ev_window_setup_bookmarks (EvWindow *window);
-static guint ev_window_n_copies = 0;
-
static gchar *nautilus_sendto = NULL;
-G_DEFINE_TYPE (EvWindow, ev_window, GTK_TYPE_WINDOW)
+G_DEFINE_TYPE (EvWindow, ev_window, GTK_TYPE_APPLICATION_WINDOW)
static gdouble
get_screen_dpi (EvWindow *window)
@@ -2482,8 +2480,6 @@ ev_window_open_copy_at_dest (EvWindow *window,
{
EvWindow *new_window = EV_WINDOW (ev_window_new ());
- ev_window_n_copies++;
-
if (window->priv->metadata)
new_window->priv->metadata = g_object_ref (window->priv->metadata);
ev_window_open_document (new_window,
@@ -5473,18 +5469,6 @@ ev_window_drag_data_received (GtkWidget *widget,
}
static void
-ev_window_finalize (GObject *object)
-{
- G_OBJECT_CLASS (ev_window_parent_class)->finalize (object);
-
- if (ev_window_n_copies == 0) {
- ev_application_shutdown (EV_APP);
- } else {
- ev_window_n_copies--;
- }
-}
-
-static void
ev_window_dispose (GObject *object)
{
EvWindow *window = EV_WINDOW (object);
@@ -5776,7 +5760,6 @@ ev_window_class_init (EvWindowClass *ev_window_class)
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (ev_window_class);
g_object_class->dispose = ev_window_dispose;
- g_object_class->finalize = ev_window_finalize;
widget_class->delete_event = ev_window_delete_event;
widget_class->key_press_event = ev_window_key_press_event;
@@ -7038,7 +7021,7 @@ ev_window_emit_closed (EvWindow *window)
* to make sure the signal is emitted.
*/
if (ev_application_get_n_windows (EV_APP) == 1)
- g_dbus_connection_flush_sync (ev_application_get_dbus_connection (EV_APP), NULL, NULL);
+ g_dbus_connection_flush_sync (g_application_get_dbus_connection (g_application_get_default ()), NULL, NULL);
}
static void
@@ -7085,7 +7068,7 @@ ev_window_init (EvWindow *ev_window)
ev_window->priv = EV_WINDOW_GET_PRIVATE (ev_window);
#ifdef ENABLE_DBUS
- connection = ev_application_get_dbus_connection (EV_APP);
+ connection = g_application_get_dbus_connection (g_application_get_default ());
if (connection) {
EvEvinceWindowImpl *impl;
@@ -7509,6 +7492,7 @@ ev_window_new (void)
ev_window = GTK_WIDGET (g_object_new (EV_TYPE_WINDOW,
"type", GTK_WINDOW_TOPLEVEL,
+ "application", g_application_get_default (),
NULL));
return ev_window;
diff --git a/shell/ev-window.h b/shell/ev-window.h
index bb8a3b1..4ee4cce 100644
--- a/shell/ev-window.h
+++ b/shell/ev-window.h
@@ -60,12 +60,12 @@ typedef struct _EvWindowPrivate EvWindowPrivate;
struct _EvWindow {
- GtkWindow base_instance;
- EvWindowPrivate *priv;
+ GtkApplicationWindow base_instance;
+ EvWindowPrivate *priv;
};
struct _EvWindowClass {
- GtkWindowClass base_class;
+ GtkApplicationWindowClass base_class;
};
GType ev_window_get_type (void) G_GNUC_CONST;
diff --git a/shell/main.c b/shell/main.c
index 10e074d..c1e756b 100644
--- a/shell/main.c
+++ b/shell/main.c
@@ -236,8 +236,10 @@ load_files (const char **files)
int
main (int argc, char *argv[])
{
+ EvApplication *application;
GOptionContext *context;
GError *error = NULL;
+ int status;
#ifdef G_OS_WIN32
@@ -311,7 +313,15 @@ main (int argc, char *argv[])
gtk_window_set_default_icon_name ("evince");
#endif /* WITH_SMCLIENT && GDK_WINDOWING_X11 */
- ev_application_load_session (EV_APP);
+ application = ev_application_new ();
+ if (!g_application_register (G_APPLICATION (application), NULL, &error)) {
+ g_printerr ("Failed to register: %s\n", error->message);
+ g_error_free (error);
+ status = 1;
+ goto done;
+ }
+
+ ev_application_load_session (application);
load_files (file_arguments);
/* Change directory so we don't prevent unmounting in case the initial cwd
@@ -319,10 +329,12 @@ main (int argc, char *argv[])
*/
g_chdir (g_get_home_dir ());
- gtk_main ();
+ status = g_application_run (G_APPLICATION (application), 0, NULL);
+ done:
ev_shutdown ();
ev_stock_icons_shutdown ();
- return 0;
+ g_object_unref (application);
+ return status;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]