[eog] Rework how EogJobs are executed



commit df887eac1709d566bc1ebde48f211a52efe130b7
Author: Felix Riemann <friemann svn gnome org>
Date:   Fri May 22 17:51:14 2009 +0200

    Rework how EogJobs are executed
    
    Instead of having EogJobQueue detect the specific job type in a big
    if-cascade, execution is now implemented in the EogJob base class as an
    abstract function. Special casing the execution is thus not necessary
    anymore.
---
 ChangeLog                      |   19 +++++
 bindings/python/eog.defs       |   33 ++-------
 doc/reference/eog-sections.txt |    7 +--
 src/eog-job-queue.c            |   14 +---
 src/eog-jobs.c                 |  167 +++++++++++++++++++++++++++-------------
 src/eog-jobs.h                 |   12 +--
 6 files changed, 143 insertions(+), 109 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 06db2b3..d427277 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,24 @@
 2009-05-22  Felix Riemann  <friemann svn gnome org>
 
+	* bindings/python/eog.defs:
+	* src/eog-job-queue.c (handle_job):
+	* src/eog-jobs.c (eog_job_run_default), (eog_job_class_init),
+	(eog_job_run), (eog_job_thumbnail_class_init),
+	(eog_job_thumbnail_run), (eog_job_load_class_init),
+	(eog_job_load_run), (eog_job_model_class_init),
+	(eog_job_model_run), (eog_job_transform_class_init),
+	(eog_job_transform_run), (eog_job_save_class_init),
+	(eog_job_save_run), (eog_job_save_as_class_init),
+	(eog_job_save_as_run), (eog_job_copy_class_init),
+	(eog_job_copy_run):
+	* src/eog-jobs.h:
+	Rework how EogJobs are executed. Instead of having EogJobQueue detect
+	the specific job type to choose the correct function this is now
+	implemented in the EogJob base class as an abstract function.
+	Special casing the execution is thus not necessary anymore.
+
+2009-05-22  Felix Riemann  <friemann svn gnome org>
+
 	* src/eog-image.c (eog_image_set_exif_data):
 	Secure Exif data updating with a mutex. Should fix crashes when
 	reading the Exif block during the update. Fixes bug #583448.
diff --git a/bindings/python/eog.defs b/bindings/python/eog.defs
index 3f0beb0..276cd06 100644
--- a/bindings/python/eog.defs
+++ b/bindings/python/eog.defs
@@ -536,6 +536,12 @@
   (return-type "none")
 )
 
+(define-method run
+  (of-object "EogJob")
+  (c-name "eog_job_run")
+  (return-type "none")
+)
+
 (define-method set_progress
   (of-object "EogJob")
   (c-name "eog_job_set_progress")
@@ -559,12 +565,6 @@
   )
 )
 
-(define-method run
-  (of-object "EogJobThumbnail")
-  (c-name "eog_job_thumbnail_run")
-  (return-type "none")
-)
-
 (define-function eog_job_load_get_type
   (c-name "eog_job_load_get_type")
   (return-type "GType")
@@ -580,12 +580,6 @@
   )
 )
 
-(define-method run
-  (of-object "EogJobLoad")
-  (c-name "eog_job_load_run")
-  (return-type "none")
-)
-
 (define-function eog_job_model_get_type
   (c-name "eog_job_model_get_type")
   (return-type "GType")
@@ -600,12 +594,6 @@
   )
 )
 
-(define-method run
-  (of-object "EogJobModel")
-  (c-name "eog_job_model_run")
-  (return-type "none")
-)
-
 (define-function eog_job_transform_get_type
   (c-name "eog_job_transform_get_type")
   (return-type "GType")
@@ -621,15 +609,6 @@
   )
 )
 
-(define-method run
-  (of-object "EogJobTransform")
-  (c-name "eog_job_transform_run")
-  (return-type "none")
-)
-
-
-
-
 ;; From eog-list-store.h
 
 (define-function eog_list_store_get_type
diff --git a/doc/reference/eog-sections.txt b/doc/reference/eog-sections.txt
index 09c8a80..7aeb2b9 100644
--- a/doc/reference/eog-sections.txt
+++ b/doc/reference/eog-sections.txt
@@ -240,27 +240,22 @@ EogJobSaveAs
 <TITLE>EogJobCopy</TITLE>
 EogJobCopy
 eog_job_finished
+eog_job_run
 eog_job_set_progress
 eog_job_thumbnail_get_type
 eog_job_thumbnail_new
-eog_job_thumbnail_run
 eog_job_load_get_type
 eog_job_load_new
-eog_job_load_run
 eog_job_model_get_type
 eog_job_model_new
-eog_job_model_run
 eog_job_transform_get_type
 eog_job_transform_new
-eog_job_transform_run
 eog_job_save_get_type
 eog_job_save_new
-eog_job_save_run
 eog_job_save_as_get_type
 eog_job_save_as_new
 eog_job_copy_get_type
 eog_job_copy_new
-eog_job_copy_run
 <SUBSECTION Standard>
 EOG_JOB
 EOG_IS_JOB
diff --git a/src/eog-job-queue.c b/src/eog-job-queue.c
index 7e3bb4e..f6d8d69 100644
--- a/src/eog-job-queue.c
+++ b/src/eog-job-queue.c
@@ -73,18 +73,8 @@ handle_job (EogJob *job)
 {
 	g_object_ref (G_OBJECT (job));
 
-	if (EOG_IS_JOB_THUMBNAIL (job))
-		eog_job_thumbnail_run (EOG_JOB_THUMBNAIL (job));
-	else if (EOG_IS_JOB_LOAD (job))
-		eog_job_load_run (EOG_JOB_LOAD (job));
-	else if (EOG_IS_JOB_MODEL (job))
-		eog_job_model_run (EOG_JOB_MODEL (job));
-	else if (EOG_IS_JOB_TRANSFORM (job))
-		eog_job_transform_run (EOG_JOB_TRANSFORM (job));
-	else if (EOG_IS_JOB_SAVE (job))
-		eog_job_save_run (EOG_JOB_SAVE (job));
-	else if (EOG_IS_JOB_COPY (job))
-		eog_job_copy_run (EOG_JOB_COPY (job));
+	// Do the EOG_JOB cast for safety
+	eog_job_run (EOG_JOB (job));
 
 	g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
 			 (GSourceFunc) notify_finished,
diff --git a/src/eog-jobs.c b/src/eog-jobs.c
index cf32f28..22e4b33 100644
--- a/src/eog-jobs.c
+++ b/src/eog-jobs.c
@@ -54,8 +54,13 @@ enum
 
 static guint job_signals[SIGNAL_LAST_SIGNAL];
 
-static void eog_job_save_real_run (EogJobSave *job);
-static void eog_job_save_as_real_run (EogJobSave *job);
+static void eog_job_copy_run      (EogJob *ejob);
+static void eog_job_load_run 	  (EogJob *ejob);
+static void eog_job_model_run     (EogJob *ejob);
+static void eog_job_save_run      (EogJob *job);
+static void eog_job_save_as_run   (EogJob *job);
+static void eog_job_thumbnail_run (EogJob *ejob);
+static void eog_job_transform_run (EogJob *ejob);
 
 static void eog_job_init (EogJob *job)
 {
@@ -84,6 +89,13 @@ eog_job_dispose (GObject *object)
 }
 
 static void
+eog_job_run_default (EogJob *job)
+{
+	g_critical ("Class \"%s\" does not implement the required run action",
+		    G_OBJECT_CLASS_NAME (G_OBJECT_GET_CLASS (job)));
+}
+
+static void
 eog_job_class_init (EogJobClass *class)
 {
 	GObjectClass *oclass;
@@ -92,6 +104,8 @@ eog_job_class_init (EogJobClass *class)
 
 	oclass->dispose = eog_job_dispose;
 
+	class->run = eog_job_run_default;
+
 	job_signals [SIGNAL_FINISHED] =
 		g_signal_new ("finished",
 			      EOG_TYPE_JOB,
@@ -120,6 +134,26 @@ eog_job_finished (EogJob *job)
 	g_signal_emit (job, job_signals[SIGNAL_FINISHED], 0);
 }
 
+/**
+ * eog_job_run:
+ * @job: the job to execute.
+ *
+ * Executes the job passed as @job. Usually there is no need to call this
+ * on your own. Jobs should be executed by using the EogJobQueue.
+ **/
+void
+eog_job_run (EogJob *job)
+{
+	EogJobClass *class;
+
+	g_return_if_fail (EOG_IS_JOB (job));
+
+	class = EOG_JOB_GET_CLASS (job);
+	if (class->run)
+		class->run (job);
+	else
+		eog_job_run_default (job);
+}
 static gboolean
 notify_progress (gpointer data)
 {
@@ -173,6 +207,8 @@ eog_job_thumbnail_class_init (EogJobThumbnailClass *class)
 	oclass = G_OBJECT_CLASS (class);
 
 	oclass->dispose = eog_job_thumbnail_dispose;
+
+	EOG_JOB_CLASS (class)->run = eog_job_thumbnail_run;
 }
 
 EogJob *
@@ -189,25 +225,28 @@ eog_job_thumbnail_new (EogImage *image)
 	return EOG_JOB (job);
 }
 
-void
-eog_job_thumbnail_run (EogJobThumbnail *job)
+static void
+eog_job_thumbnail_run (EogJob *ejob)
 {
 	gchar *orig_width, *orig_height;
 	gint width, height;
 	GdkPixbuf *pixbuf;
+	EogJobThumbnail *job;
+
+	g_return_if_fail (EOG_IS_JOB_THUMBNAIL (ejob));
 
-	g_return_if_fail (EOG_IS_JOB_THUMBNAIL (job));
+	job = EOG_JOB_THUMBNAIL (ejob);
 
-	if (EOG_JOB (job)->error) {
-	        g_error_free (EOG_JOB (job)->error);
-		EOG_JOB (job)->error = NULL;
+	if (ejob->error) {
+	        g_error_free (ejob->error);
+		ejob->error = NULL;
 	}
 
 	job->thumbnail = eog_thumbnail_load (job->image,
-					     &EOG_JOB (job)->error);
+					     &ejob->error);
 
 	if (!job->thumbnail) {
-		EOG_JOB (job)->finished = TRUE;
+		ejob->finished = TRUE;
 		return;
 	}
 
@@ -234,11 +273,11 @@ eog_job_thumbnail_run (EogJobThumbnail *job)
 		g_free (orig_height);
 	}
 
-	if (EOG_JOB (job)->error) {
-		g_warning ("%s", EOG_JOB (job)->error->message);
+	if (ejob->error) {
+		g_warning ("%s", ejob->error->message);
 	}
 
-	EOG_JOB (job)->finished = TRUE;
+	ejob->finished = TRUE;
 }
 
 static void eog_job_load_init (EogJobLoad *job) { /* Do Nothing */ }
@@ -266,6 +305,7 @@ eog_job_load_class_init (EogJobLoadClass *class)
 	oclass = G_OBJECT_CLASS (class);
 
 	oclass->dispose = eog_job_load_dispose;
+	EOG_JOB_CLASS (class)->run = eog_job_load_run;
 }
 
 EogJob *
@@ -283,22 +323,22 @@ eog_job_load_new (EogImage *image, EogImageData data)
 	return EOG_JOB (job);
 }
 
-void
-eog_job_load_run (EogJobLoad *job)
+static void
+eog_job_load_run (EogJob *job)
 {
 	g_return_if_fail (EOG_IS_JOB_LOAD (job));
 
-	if (EOG_JOB (job)->error) {
-	        g_error_free (EOG_JOB (job)->error);
-		EOG_JOB (job)->error = NULL;
+	if (job->error) {
+	        g_error_free (job->error);
+		job->error = NULL;
 	}
 
-	eog_image_load (EOG_IMAGE (job->image),
-			job->data,
-			EOG_JOB (job),
-			&EOG_JOB (job)->error);
+	eog_image_load (EOG_IMAGE (EOG_JOB_LOAD (job)->image),
+			EOG_JOB_LOAD (job)->data,
+			job,
+			&job->error);
 
-	EOG_JOB (job)->finished = TRUE;
+	job->finished = TRUE;
 }
 
 static void eog_job_model_init (EogJobModel *job) { /* Do Nothing */ }
@@ -321,6 +361,7 @@ eog_job_model_class_init (EogJobModelClass *class)
 	oclass = G_OBJECT_CLASS (class);
 
 	oclass->dispose = eog_job_model_dispose;
+	EOG_JOB_CLASS (class)->run = eog_job_model_run;
 }
 
 EogJob *
@@ -391,13 +432,16 @@ filter_files (GSList *files, GList **file_list, GList **error_list)
 	*error_list = g_list_reverse (*error_list);
 }
 
-void
-eog_job_model_run (EogJobModel *job)
+static void
+eog_job_model_run (EogJob *ejob)
 {
 	GList *filtered_list = NULL;
 	GList *error_list = NULL;
+	EogJobModel *job;
+
+	g_return_if_fail (EOG_IS_JOB_MODEL (ejob));
 
-	g_return_if_fail (EOG_IS_JOB_MODEL (job));
+	job = EOG_JOB_MODEL (ejob);
 
 	filter_files (job->file_list, &filtered_list, &error_list);
 
@@ -411,7 +455,7 @@ eog_job_model_run (EogJobModel *job)
 	g_list_foreach (error_list, (GFunc) g_free, NULL);
 	g_list_free (error_list);
 
-	EOG_JOB (job)->finished = TRUE;
+	ejob->finished = TRUE;
 }
 
 static void eog_job_transform_init (EogJobTransform *job) { /* Do Nothing */ }
@@ -442,6 +486,8 @@ eog_job_transform_class_init (EogJobTransformClass *class)
 	oclass = G_OBJECT_CLASS (class);
 
 	oclass->dispose = eog_job_transform_dispose;
+
+	EOG_JOB_CLASS (class)->run = eog_job_transform_run;
 }
 
 EogJob *
@@ -474,15 +520,18 @@ eog_job_transform_image_modified (gpointer data)
 }
 
 void
-eog_job_transform_run (EogJobTransform *job)
+eog_job_transform_run (EogJob *ejob)
 {
+	EogJobTransform *job;
 	GList *it;
 
-	g_return_if_fail (EOG_IS_JOB_TRANSFORM (job));
+	g_return_if_fail (EOG_IS_JOB_TRANSFORM (ejob));
+
+	job = EOG_JOB_TRANSFORM (ejob);
 
-	if (EOG_JOB (job)->error) {
-	        g_error_free (EOG_JOB (job)->error);
-		EOG_JOB (job)->error = NULL;
+	if (ejob->error) {
+	        g_error_free (ejob->error);
+		ejob->error = NULL;
 	}
 
 	for (it = job->images; it != NULL; it = it->next) {
@@ -491,7 +540,7 @@ eog_job_transform_run (EogJobTransform *job)
 		if (job->trans == NULL) {
 			eog_image_undo (image);
 		} else {
-			eog_image_transform (image, job->trans, EOG_JOB (job));
+			eog_image_transform (image, job->trans, ejob);
 		}
 
 		if (eog_image_is_modified (image) || job->trans == NULL) {
@@ -500,7 +549,7 @@ eog_job_transform_run (EogJobTransform *job)
 		}
 	}
 
-	EOG_JOB (job)->finished = TRUE;
+	ejob->finished = TRUE;
 }
 
 static void eog_job_save_init (EogJobSave *job) { /* do nothing */ }
@@ -525,7 +574,7 @@ static void
 eog_job_save_class_init (EogJobSaveClass *class)
 {
 	G_OBJECT_CLASS (class)->dispose = eog_job_save_dispose;
-        class->run = eog_job_save_real_run;
+	EOG_JOB_CLASS (class)->run = eog_job_save_run;
 }
 
 EogJob *
@@ -554,10 +603,15 @@ save_progress_handler (EogImage *image, gfloat progress, gpointer data)
 }
 
 static void
-eog_job_save_real_run (EogJobSave *job)
+eog_job_save_run (EogJob *ejob)
 {
+	EogJobSave *job;
 	GList *it;
 
+	g_return_if_fail (EOG_IS_JOB_SAVE (ejob));
+
+	job = EOG_JOB_SAVE (ejob);
+
 	job->current_pos = 0;
 
 	for (it = job->images; it != NULL; it = it->next, job->current_pos++) {
@@ -575,7 +629,7 @@ eog_job_save_real_run (EogJobSave *job)
 			eog_image_load (image,
 					EOG_IMAGE_DATA_ALL,
 					NULL,
-					&EOG_JOB (job)->error);
+					&ejob->error);
 		}
 
 		handler_id = g_signal_connect (G_OBJECT (image),
@@ -587,7 +641,7 @@ eog_job_save_real_run (EogJobSave *job)
 
 		success = eog_image_save_by_info (image,
 						  save_info,
-						  &EOG_JOB (job)->error);
+						  &ejob->error);
 
 		if (save_info)
 			g_object_unref (save_info);
@@ -600,13 +654,7 @@ eog_job_save_real_run (EogJobSave *job)
 		if (!success) break;
 	}
 
-	EOG_JOB (job)->finished = TRUE;
-}
-
-void
-eog_job_save_run (EogJobSave *job)
-{
-	EOG_JOB_SAVE_GET_CLASS (job)->run(job);
+	ejob->finished = TRUE;
 }
 
 static void eog_job_save_as_init (EogJobSaveAs *job) { /* do nothing */ }
@@ -632,7 +680,7 @@ static void
 eog_job_save_as_class_init (EogJobSaveAsClass *class)
 {
 	G_OBJECT_CLASS (class)->dispose = eog_job_save_as_dispose;
-        EOG_JOB_SAVE_CLASS (class)->run = eog_job_save_as_real_run;
+	EOG_JOB_CLASS (class)->run = eog_job_save_as_run;
 }
 
 EogJob *
@@ -653,13 +701,16 @@ eog_job_save_as_new (GList *images, EogURIConverter *converter, GFile *file)
 }
 
 static void
-eog_job_save_as_real_run (EogJobSave *job)
+eog_job_save_as_run (EogJob *ejob)
 {
+	EogJobSave *job;
 	EogJobSaveAs *saveas_job;
 	GList *it;
 	guint n_images;
 
-	g_assert (EOG_IS_JOB_SAVE_AS (job));
+	g_return_if_fail (EOG_IS_JOB_SAVE_AS (ejob));
+
+	job = EOG_JOB_SAVE (ejob);
 
 	n_images = g_list_length (job->images);
 
@@ -682,10 +733,10 @@ eog_job_save_as_real_run (EogJobSave *job)
 			eog_image_load (image,
 					EOG_IMAGE_DATA_ALL,
 					NULL,
-					&EOG_JOB (job)->error);
+					&ejob->error);
 		}
 
-		g_assert (EOG_JOB (job)->error == NULL);
+		g_assert (ejob->error == NULL);
 
 		handler_id = g_signal_connect (G_OBJECT (image),
 					       "save-progress",
@@ -725,7 +776,7 @@ eog_job_save_as_real_run (EogJobSave *job)
 		success = eog_image_save_as_by_info (image,
 						     src_info,
 						     dest_info,
-						     &EOG_JOB (job)->error);
+						     &ejob->error);
 
 		if (src_info)
 			g_object_unref (src_info);
@@ -742,7 +793,7 @@ eog_job_save_as_real_run (EogJobSave *job)
 			break;
 	}
 
-	EOG_JOB (job)->finished = TRUE;
+	ejob->finished = TRUE;
 }
 
 static void eog_job_copy_init (EogJobCopy *job) { /* do nothing */};
@@ -764,6 +815,7 @@ static void
 eog_job_copy_class_init (EogJobCopyClass *class)
 {
 	G_OBJECT_CLASS (class)->dispose = eog_job_copy_dispose;
+	EOG_JOB_CLASS (class)->run = eog_job_copy_run;
 }
 
 EogJob *
@@ -799,13 +851,18 @@ eog_job_copy_progress_callback (goffset current_num_bytes,
 }
 
 void
-eog_job_copy_run (EogJobCopy *job)
+eog_job_copy_run (EogJob *ejob)
 {
+	EogJobCopy *job;
 	GList *it;
 	guint n_images;
 	GFile *src, *dest;
 	gchar *filename, *dest_filename;
 
+	g_return_if_fail (EOG_IS_JOB_COPY (ejob));
+
+	job = EOG_JOB_COPY (ejob);
+
 	n_images = g_list_length (job->images);
 
 	job->current_pos = 0;
@@ -819,10 +876,10 @@ eog_job_copy_run (EogJobCopy *job)
 		g_file_copy (src, dest,
 			     G_FILE_COPY_OVERWRITE, NULL,
 			     eog_job_copy_progress_callback, job,
-			     &EOG_JOB (job)->error);
+			     &ejob->error);
 		g_free (filename);
 		g_free (dest_filename);
 	}
 
-	EOG_JOB (job)->finished = TRUE;
+	ejob->finished = TRUE;
 }
diff --git a/src/eog-jobs.h b/src/eog-jobs.h
index 0ec705c..c26e089 100644
--- a/src/eog-jobs.h
+++ b/src/eog-jobs.h
@@ -77,6 +77,7 @@ typedef struct _EogJobCopyClass EogJobCopyClass;
 #define EOG_JOB(obj)		       (G_TYPE_CHECK_INSTANCE_CAST((obj), EOG_TYPE_JOB, EogJob))
 #define EOG_JOB_CLASS(klass)	       (G_TYPE_CHECK_CLASS_CAST((klass),  EOG_TYPE_JOB, EogJobClass))
 #define EOG_IS_JOB(obj)	               (G_TYPE_CHECK_INSTANCE_TYPE((obj), EOG_TYPE_JOB))
+#define EOG_JOB_GET_CLASS(obj)         (G_TYPE_INSTANCE_GET_CLASS ((obj), EOG_TYPE_JOB, EogJobClass))
 
 #define EOG_TYPE_JOB_THUMBNAIL	       (eog_job_thumbnail_get_type())
 #define EOG_JOB_THUMBNAIL(obj)	       (G_TYPE_CHECK_INSTANCE_CAST((obj), EOG_TYPE_JOB_THUMBNAIL, EogJobThumbnail))
@@ -131,6 +132,7 @@ struct _EogJobClass
 
 	void    (* finished) (EogJob *job);
 	void    (* progress) (EogJob *job, float progress);
+	void    (*run)       (EogJob *job);
 };
 
 struct _EogJobThumbnail
@@ -201,9 +203,6 @@ struct _EogJobSave
 struct _EogJobSaveClass
 {
 	EogJobClass parent_class;
-
-        void (*run) (EogJobSave *job);
-
 };
 
 struct _EogJobSaveAs
@@ -234,35 +233,31 @@ struct _EogJobCopyClass
 /* base job class */
 GType           eog_job_get_type           (void) G_GNUC_CONST;
 void            eog_job_finished           (EogJob          *job);
+void            eog_job_run                (EogJob          *job);
 void            eog_job_set_progress       (EogJob          *job,
 					    float            progress);
 
 /* EogJobThumbnail */
 GType           eog_job_thumbnail_get_type (void) G_GNUC_CONST;
 EogJob         *eog_job_thumbnail_new      (EogImage     *image);
-void            eog_job_thumbnail_run      (EogJobThumbnail *thumbnail);
 
 /* EogJobLoad */
 GType           eog_job_load_get_type      (void) G_GNUC_CONST;
 EogJob 	       *eog_job_load_new 	   (EogImage        *image,
 					    EogImageData     data);
-void		eog_job_load_run 	   (EogJobLoad 	    *load);
 
 /* EogJobModel */
 GType 		eog_job_model_get_type     (void) G_GNUC_CONST;
 EogJob 	       *eog_job_model_new          (GSList          *file_list);
-void            eog_job_model_run          (EogJobModel     *model);
 
 /* EogJobTransform */
 GType 		eog_job_transform_get_type (void) G_GNUC_CONST;
 EogJob 	       *eog_job_transform_new      (GList           *images,
 					    EogTransform    *trans);
-void            eog_job_transform_run      (EogJobTransform *model);
 
 /* EogJobSave */
 GType		eog_job_save_get_type      (void) G_GNUC_CONST;
 EogJob         *eog_job_save_new           (GList           *images);
-void            eog_job_save_run           (EogJobSave      *job);
 
 /* EogJobSaveAs */
 GType		eog_job_save_as_get_type   (void) G_GNUC_CONST;
@@ -274,7 +269,6 @@ EogJob         *eog_job_save_as_new        (GList           *images,
 GType          eog_job_copy_get_type      (void) G_GNUC_CONST;
 EogJob        *eog_job_copy_new           (GList            *images,
 					   const gchar      *dest);
-void           eog_job_copy_run           (EogJobCopy       *job);
 
 G_END_DECLS
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]