[gedit] Implemented full support for compressed files



commit 0863222bac3fdf9ed8964d25be1396bd63167be1
Author: Jesse van den Kieboom <jessevdk gnome org>
Date:   Thu May 13 14:06:33 2010 +0200

    Implemented full support for compressed files
    
    This adds a CompressionType similar to NewlineType.

 gedit/gedit-commands-file.c               |  126 ++++++++++++++++++--
 gedit/gedit-document-loader.c             |   91 +++++++++++---
 gedit/gedit-document-loader.h             |    2 +
 gedit/gedit-document-saver.c              |   34 +++++-
 gedit/gedit-document-saver.h              |   11 +-
 gedit/gedit-document.c                    |  188 ++++++++++++++++++++++------
 gedit/gedit-document.h                    |   42 +++++--
 gedit/gedit-file-chooser-dialog.c         |   30 +++--
 gedit/gedit-marshal.list                  |    2 +-
 gedit/gedit-tab.c                         |   18 ++-
 gedit/gedit-tab.h                         |    3 +-
 gedit/gedit-utils.c                       |   16 +++
 gedit/gedit-utils.h                       |    4 +
 plugin-loaders/python/bindings/gedit.defs |   17 +++
 tests/document-saver.c                    |    2 +-
 15 files changed, 477 insertions(+), 109 deletions(-)
---
diff --git a/gedit/gedit-commands-file.c b/gedit/gedit-commands-file.c
index 1a8d0c6..f074e0b 100644
--- a/gedit/gedit-commands-file.c
+++ b/gedit/gedit-commands-file.c
@@ -571,17 +571,106 @@ replace_read_only_file (GtkWindow *parent, GFile *file)
 	return (ret == GTK_RESPONSE_YES);
 }
 
+static gboolean
+change_compression (GtkWindow *parent,
+                    GFile     *file,
+                    gboolean   compressed)
+{
+	GtkWidget *dialog;
+	gint ret;
+	gchar *parse_name;
+	gchar *name_for_display;
+	const gchar *primary_message;
+	const gchar *secondary_message;
+	const gchar *button_label;
+
+	gedit_debug (DEBUG_COMMANDS);
+
+	parse_name = g_file_get_parse_name (file);
+
+	/* Truncate the name so it doesn't get insanely wide. Note that even
+	 * though the dialog uses wrapped text, if the name doesn't contain
+	 * white space then the text-wrapping code is too stupid to wrap it.
+	 */
+	name_for_display = gedit_utils_str_middle_truncate (parse_name, 50);
+	g_free (parse_name);
+
+	if (compressed)
+	{
+		primary_message = _("Save the file using compression?");
+		secondary_message = _("The file \"%s\" was previously saved as plain "
+		                      "text and will now be saved using compression.");
+		button_label = _("Save using compression");
+	}
+	else
+	{
+		primary_message = _("Save the file as plain text?");
+		secondary_message = _("The file \"%s\" was previously saved "
+		                      "using compression and will now be saved as plain text.");
+		button_label = _("Save as plain text");
+	}
+
+	dialog = gtk_message_dialog_new (parent,
+					 GTK_DIALOG_DESTROY_WITH_PARENT,
+					 GTK_MESSAGE_QUESTION,
+					 GTK_BUTTONS_NONE,
+					 "%s",
+					 primary_message);
+
+	gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+						  secondary_message,
+						  name_for_display);
+
+	g_free (name_for_display);
+
+	gtk_dialog_add_button (GTK_DIALOG (dialog),
+			       GTK_STOCK_CANCEL,
+			       GTK_RESPONSE_CANCEL);
+
+	gedit_dialog_add_button (GTK_DIALOG (dialog),
+				 button_label,
+			  	 GTK_STOCK_SAVE_AS,
+			  	 GTK_RESPONSE_YES);
+
+	gtk_dialog_set_default_response	(GTK_DIALOG (dialog),
+					 GTK_RESPONSE_CANCEL);
+
+	gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
+
+	ret = gtk_dialog_run (GTK_DIALOG (dialog));
+
+	gtk_widget_destroy (dialog);
+
+	return (ret == GTK_RESPONSE_YES);
+}
+
+static GeditDocumentCompressionType
+get_compression_type_from_file (GFile *file)
+{
+	gchar *name;
+	gchar *content_type;
+	GeditDocumentCompressionType type;
+
+	name = g_file_get_basename (file);
+	content_type = g_content_type_guess (name, NULL, 0, NULL);
+
+	type = gedit_utils_get_compression_type_from_content_type (content_type);
+
+	g_free (name);
+	g_free (content_type);
+
+	return type;
+}
+
 static void
 save_dialog_response_cb (GeditFileChooserDialog *dialog,
                          gint                    response_id,
                          GeditWindow            *window)
 {
 	GFile *file;
-	const GeditEncoding *encoding;
 	GeditTab *tab;
 	gpointer data;
 	GSList *tabs_to_save_as;
-	GeditDocumentNewlineType newline_type;
 
 	gedit_debug (DEBUG_COMMANDS);
 
@@ -598,15 +687,36 @@ save_dialog_response_cb (GeditFileChooserDialog *dialog,
 	file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
 	g_return_if_fail (file != NULL);
 
-	encoding = gedit_file_chooser_dialog_get_encoding (dialog);
-	newline_type = gedit_file_chooser_dialog_get_newline_type (dialog);
-
-	gtk_widget_destroy (GTK_WIDGET (dialog));
-
 	if (tab != NULL)
 	{
 		GeditDocument *doc;
 		gchar *parse_name;
+		GeditDocumentNewlineType newline_type;
+		GeditDocumentCompressionType compression_type;
+		GeditDocumentCompressionType current_compression_type;
+		const GeditEncoding *encoding;
+
+		doc = gedit_tab_get_document (tab);
+		compression_type = get_compression_type_from_file (file);
+		current_compression_type = gedit_document_get_compression_type (doc);
+
+		if ((compression_type == GEDIT_DOCUMENT_COMPRESSION_TYPE_NONE) !=
+		    (current_compression_type == GEDIT_DOCUMENT_COMPRESSION_TYPE_NONE))
+		{
+			if (!change_compression (GTK_WINDOW (dialog),
+			                         file,
+			                         compression_type != GEDIT_DOCUMENT_COMPRESSION_TYPE_NONE))
+			{
+				gtk_widget_destroy (GTK_WIDGET (dialog));
+
+				goto save_next_tab;
+			}
+		}
+
+		encoding = gedit_file_chooser_dialog_get_encoding (dialog);
+		newline_type = gedit_file_chooser_dialog_get_newline_type (dialog);
+
+		gtk_widget_destroy (GTK_WIDGET (dialog));
 
 		doc = gedit_tab_get_document (tab);
 		g_return_if_fail (GEDIT_IS_DOCUMENT (doc));
@@ -624,7 +734,7 @@ save_dialog_response_cb (GeditFileChooserDialog *dialog,
 		 * even if the saving fails... */
 		 _gedit_window_set_default_location (window, file);
 
-		_gedit_tab_save_as (tab, file, encoding, newline_type);
+		_gedit_tab_save_as (tab, file, encoding, newline_type, compression_type);
 	}
 
 	g_object_unref (file);
diff --git a/gedit/gedit-document-loader.c b/gedit/gedit-document-loader.c
index 1969ab9..65a1223 100644
--- a/gedit/gedit-document-loader.c
+++ b/gedit/gedit-document-loader.c
@@ -79,7 +79,8 @@ enum
 	PROP_LOCATION,
 	PROP_ENCODING,
 	PROP_NEWLINE_TYPE,
-	PROP_STREAM
+	PROP_STREAM,
+	PROP_COMPRESSION_TYPE
 };
 
 #define READ_CHUNK_SIZE 8192
@@ -110,6 +111,7 @@ struct _GeditDocumentLoaderPrivate
 	const GeditEncoding	 *encoding;
 	const GeditEncoding	 *auto_detected_encoding;
 	GeditDocumentNewlineType  auto_detected_newline_type;
+	GeditDocumentCompressionType auto_detected_compression_type;
 	
 	goffset                   bytes_read;
 
@@ -154,6 +156,9 @@ gedit_document_loader_set_property (GObject      *object,
 		case PROP_STREAM:
 			loader->priv->stream = g_value_dup_object (value);
 			break;
+		case PROP_COMPRESSION_TYPE:
+			loader->priv->auto_detected_compression_type = g_value_get_enum (value);
+			break;
 		default:
 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 			break;
@@ -185,6 +190,9 @@ gedit_document_loader_get_property (GObject    *object,
 		case PROP_STREAM:
 			g_value_set_object (value, loader->priv->stream);
 			break;
+		case PROP_COMPRESSION_TYPE:
+			g_value_set_enum (value, loader->priv->auto_detected_compression_type);
+			break;
 		default:
 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 			break;
@@ -295,6 +303,18 @@ gedit_document_loader_class_init (GeditDocumentLoaderClass *klass)
 	                                                    GEDIT_TYPE_DOCUMENT_NEWLINE_TYPE,
 	                                                    GEDIT_DOCUMENT_NEWLINE_TYPE_LF,
 	                                                    G_PARAM_READWRITE |
+	                                                    G_PARAM_CONSTRUCT |
+	                                                    G_PARAM_STATIC_NAME |
+	                                                    G_PARAM_STATIC_BLURB));
+
+	g_object_class_install_property (object_class, PROP_COMPRESSION_TYPE,
+	                                 g_param_spec_enum ("compression-type",
+	                                                    "Compression type",
+	                                                    "The compression type",
+	                                                    GEDIT_TYPE_DOCUMENT_COMPRESSION_TYPE,
+	                                                    GEDIT_DOCUMENT_COMPRESSION_TYPE_NONE,
+	                                                    G_PARAM_READWRITE |
+	                                                    G_PARAM_CONSTRUCT |
 	                                                    G_PARAM_STATIC_NAME |
 	                                                    G_PARAM_STATIC_BLURB));
 
@@ -327,10 +347,6 @@ gedit_document_loader_init (GeditDocumentLoader *loader)
 {
 	loader->priv = GEDIT_DOCUMENT_LOADER_GET_PRIVATE (loader);
 
-	loader->priv->used = FALSE;
-	loader->priv->auto_detected_newline_type = GEDIT_DOCUMENT_NEWLINE_TYPE_DEFAULT;
-	loader->priv->converter = NULL;
-	loader->priv->error = NULL;
 	loader->priv->enc_settings = g_settings_new ("org.gnome.gedit.preferences.encodings");
 }
 
@@ -593,6 +609,8 @@ async_read_cb (GInputStream *stream,
 			g_file_info_set_attribute_string (loader->priv->info,
 			                                  G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
 			                                  guessed);
+
+			g_free (guessed);
 		}
 	}
 
@@ -669,12 +687,30 @@ get_candidate_encodings (GeditDocumentLoader *loader)
 	return encodings;
 }
 
+static GInputStream *
+compression_gzip_stream (GeditDocumentLoader *loader)
+{
+	GZlibDecompressor *decompressor;
+	GInputStream *base_stream;
+
+	decompressor = g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP);
+
+	base_stream = g_converter_input_stream_new (loader->priv->stream,
+	                                            G_CONVERTER (decompressor));
+
+	g_object_unref (decompressor);
+
+	loader->priv->auto_detected_compression_type = GEDIT_DOCUMENT_COMPRESSION_TYPE_GZIP;
+
+	return base_stream;
+}
+
 static void
 start_stream_read (AsyncData *async)
 {
 	GSList *candidate_encodings;
 	GeditDocumentLoader *loader;
-	GInputStream *base_stream;
+	GInputStream *base_stream = NULL;
 	GFileInfo *info;
 
 	loader = async->loader;
@@ -693,21 +729,25 @@ start_stream_read (AsyncData *async)
 	loader->priv->converter = gedit_smart_charset_converter_new (candidate_encodings);
 	g_slist_free (candidate_encodings);
 
-	if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE) &&
-	    g_strcmp0 (g_file_info_get_content_type (info), "application/x-gzip") == 0)
+	if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE))
 	{
-		GZlibDecompressor *decompressor;
+		const gchar *content_type = g_file_info_get_content_type (info);
 
-		decompressor = g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP);
-
-		base_stream = g_converter_input_stream_new (loader->priv->stream,
-		                                            G_CONVERTER (decompressor));
-
-		g_object_unref (decompressor);
+		switch (gedit_utils_get_compression_type_from_content_type (content_type))
+		{
+			case GEDIT_DOCUMENT_COMPRESSION_TYPE_GZIP:
+				base_stream = compression_gzip_stream (loader);
+				break;
+			case GEDIT_DOCUMENT_COMPRESSION_TYPE_NONE:
+				/* NOOP */
+				break;
+		}
 	}
-	else
+
+	if (base_stream == NULL)
 	{
 		base_stream = g_object_ref (loader->priv->stream);
+		loader->priv->auto_detected_compression_type = GEDIT_DOCUMENT_COMPRESSION_TYPE_NONE;
 	}
 
 	g_object_unref (loader->priv->stream);
@@ -755,6 +795,7 @@ query_info_cb (GFile        *source,
 {
 	GFileInfo *info;
 	GError *error = NULL;
+	GeditDocumentLoaderPrivate *priv;
 
 	gedit_debug (DEBUG_LOADER);
 
@@ -765,8 +806,10 @@ query_info_cb (GFile        *source,
 		return;
 	}	
 
+	priv = async->loader->priv;
+
 	/* finish the info query */
-	info = g_file_query_info_finish (async->loader->priv->location,
+	info = g_file_query_info_finish (priv->location,
 	                                 res,
 	                                 &error);
 
@@ -777,8 +820,8 @@ query_info_cb (GFile        *source,
 		return;
 	}
 
-	async->loader->priv->info = info;
-	
+	priv->info = info;
+
 	finish_query_info (async);
 }
 
@@ -1039,6 +1082,15 @@ gedit_document_loader_get_newline_type (GeditDocumentLoader *loader)
 	return loader->priv->auto_detected_newline_type;
 }
 
+GeditDocumentCompressionType
+gedit_document_loader_get_compression_type (GeditDocumentLoader *loader)
+{
+	g_return_val_if_fail (GEDIT_IS_DOCUMENT_LOADER (loader),
+			      GEDIT_DOCUMENT_COMPRESSION_TYPE_NONE);
+
+	return loader->priv->auto_detected_compression_type;
+}
+
 GFileInfo *
 gedit_document_loader_get_info (GeditDocumentLoader *loader)
 {
@@ -1046,4 +1098,5 @@ gedit_document_loader_get_info (GeditDocumentLoader *loader)
 
 	return loader->priv->info;
 }
+
 /* ex:ts=8:noet: */
diff --git a/gedit/gedit-document-loader.h b/gedit/gedit-document-loader.h
index 33bcaf0..cd2da0d 100644
--- a/gedit/gedit-document-loader.h
+++ b/gedit/gedit-document-loader.h
@@ -110,6 +110,8 @@ const GeditEncoding	*gedit_document_loader_get_encoding	(GeditDocumentLoader *lo
 
 GeditDocumentNewlineType gedit_document_loader_get_newline_type (GeditDocumentLoader *loader);
 
+GeditDocumentCompressionType gedit_document_loader_get_compression_type (GeditDocumentLoader *loader);
+
 goffset			 gedit_document_loader_get_bytes_read	(GeditDocumentLoader *loader);
 
 /* You can get from the info: content_type, time_modified, standard_size, access_can_write 
diff --git a/gedit/gedit-document-saver.c b/gedit/gedit-document-saver.c
index 9d7da09..fb62d7d 100644
--- a/gedit/gedit-document-saver.c
+++ b/gedit/gedit-document-saver.c
@@ -64,6 +64,7 @@ enum {
 	PROP_LOCATION,
 	PROP_ENCODING,
 	PROP_NEWLINE_TYPE,
+	PROP_COMPRESSION_TYPE,
 	PROP_FLAGS
 };
 
@@ -98,6 +99,7 @@ struct _GeditDocumentSaverPrivate
 	GFile			 *location;
 	const GeditEncoding      *encoding;
 	GeditDocumentNewlineType  newline_type;
+	GeditDocumentCompressionType compression_type;
 
 	GeditDocumentSaveFlags    flags;
 
@@ -142,6 +144,9 @@ gedit_document_saver_set_property (GObject      *object,
 		case PROP_NEWLINE_TYPE:
 			saver->priv->newline_type = g_value_get_enum (value);
 			break;
+		case PROP_COMPRESSION_TYPE:
+			saver->priv->compression_type = g_value_get_enum (value);
+			break;
 		case PROP_FLAGS:
 			saver->priv->flags = g_value_get_flags (value);
 			break;
@@ -173,6 +178,9 @@ gedit_document_saver_get_property (GObject    *object,
 		case PROP_NEWLINE_TYPE:
 			g_value_set_enum (value, saver->priv->newline_type);
 			break;
+		case PROP_COMPRESSION_TYPE:
+			g_value_set_enum (value, saver->priv->compression_type);
+			break;
 		case PROP_FLAGS:
 			g_value_set_flags (value, saver->priv->flags);
 			break;
@@ -316,6 +324,18 @@ gedit_document_saver_class_init (GeditDocumentSaverClass *klass)
 					                    G_PARAM_CONSTRUCT_ONLY));
 
 	g_object_class_install_property (object_class,
+					 PROP_COMPRESSION_TYPE,
+					 g_param_spec_enum ("compression-type",
+					                    "Compression type",
+					                    "The compression type",
+					                    GEDIT_TYPE_DOCUMENT_COMPRESSION_TYPE,
+					                    GEDIT_DOCUMENT_COMPRESSION_TYPE_NONE,
+					                    G_PARAM_READWRITE |
+					                    G_PARAM_STATIC_NAME |
+					                    G_PARAM_STATIC_BLURB |
+					                    G_PARAM_CONSTRUCT_ONLY));
+
+	g_object_class_install_property (object_class,
 					 PROP_FLAGS,
 					 g_param_spec_flags ("flags",
 							     "Flags",
@@ -352,11 +372,12 @@ gedit_document_saver_init (GeditDocumentSaver *saver)
 }
 
 GeditDocumentSaver *
-gedit_document_saver_new (GeditDocument           *doc,
-			  GFile                   *location,
-			  const GeditEncoding     *encoding,
-			  GeditDocumentNewlineType newline_type,
-			  GeditDocumentSaveFlags   flags)
+gedit_document_saver_new (GeditDocument                *doc,
+			  GFile                        *location,
+			  const GeditEncoding          *encoding,
+			  GeditDocumentNewlineType      newline_type,
+			  GeditDocumentCompressionType  compression_type,
+			  GeditDocumentSaveFlags        flags)
 {
 	g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), NULL);
 
@@ -368,6 +389,7 @@ gedit_document_saver_new (GeditDocument           *doc,
 						   "location", location,
 						   "encoding", encoding,
 						   "newline_type", newline_type,
+						   "compression_type", compression_type,
 						   "flags", flags,
 						   NULL));
 }
@@ -720,7 +742,7 @@ async_replace_ready_callback (GFile        *source,
 
 	content_type = gedit_document_get_content_type (saver->priv->document);
 
-	if (g_strcmp0 (content_type, "application/x-gzip") == 0)
+	if (saver->priv->compression_type == GEDIT_DOCUMENT_COMPRESSION_TYPE_GZIP)
 	{
 		GZlibCompressor *compressor;
 
diff --git a/gedit/gedit-document-saver.h b/gedit/gedit-document-saver.h
index 9b10241..ba8f2e6 100644
--- a/gedit/gedit-document-saver.h
+++ b/gedit/gedit-document-saver.h
@@ -82,11 +82,12 @@ struct _GeditDocumentSaverClass
 GType 		 	 gedit_document_saver_get_type		(void) G_GNUC_CONST;
 
 /* If enconding == NULL, the encoding will be autodetected */
-GeditDocumentSaver 	*gedit_document_saver_new 		(GeditDocument           *doc,
-								 GFile                   *location,
-								 const GeditEncoding     *encoding,
-								 GeditDocumentNewlineType newline_type,
-								 GeditDocumentSaveFlags   flags);
+GeditDocumentSaver 	*gedit_document_saver_new 		(GeditDocument                *doc,
+								 GFile                        *location,
+								 const GeditEncoding          *encoding,
+								 GeditDocumentNewlineType      newline_type,
+								 GeditDocumentCompressionType  compression_type,
+								 GeditDocumentSaveFlags        flags);
 
 void			 gedit_document_saver_saving		(GeditDocumentSaver *saver,
 								 gboolean            completed,
diff --git a/gedit/gedit-document.c b/gedit/gedit-document.c
index 7a9dd1d..b8fabac 100644
--- a/gedit/gedit-document.c
+++ b/gedit/gedit-document.c
@@ -78,28 +78,29 @@ PROFILE (static GTimer *timer = NULL)
 
 #define GEDIT_DOCUMENT_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), GEDIT_TYPE_DOCUMENT, GeditDocumentPrivate))
 
-static void	gedit_document_load_real	(GeditDocument          *doc,
-						 GFile                  *location,
-						 const GeditEncoding    *encoding,
-						 gint                    line_pos,
-						 gint                    column_pos,
-						 gboolean                create);
-static void	gedit_document_save_real	(GeditDocument           *doc,
-						 GFile                   *location,
-						 const GeditEncoding     *encoding,
-						 GeditDocumentNewlineType newline_type,
-						 GeditDocumentSaveFlags   flags);
-static void	to_search_region_range 		(GeditDocument *doc,
-						 GtkTextIter   *start, 
-						 GtkTextIter   *end);
-static void 	insert_text_cb		 	(GeditDocument *doc, 
-						 GtkTextIter   *pos,
-						 const gchar   *text, 
-						 gint           length);
+static void	gedit_document_load_real	(GeditDocument                *doc,
+						 GFile                        *location,
+						 const GeditEncoding          *encoding,
+						 gint                          line_pos,
+						 gint                          column_pos,
+						 gboolean                      create);
+static void	gedit_document_save_real	(GeditDocument                *doc,
+						 GFile                        *location,
+						 const GeditEncoding          *encoding,
+						 GeditDocumentNewlineType      newline_type,
+						 GeditDocumentCompressionType  compression_type,
+						 GeditDocumentSaveFlags        flags);
+static void	to_search_region_range 		(GeditDocument                *doc,
+						 GtkTextIter                  *start,
+						 GtkTextIter                  *end);
+static void 	insert_text_cb		 	(GeditDocument                *doc,
+						 GtkTextIter                  *pos,
+						 const gchar                  *text,
+						 gint                          length);
 						 
-static void	delete_range_cb 		(GeditDocument *doc, 
-						 GtkTextIter   *start,
-						 GtkTextIter   *end);
+static void	delete_range_cb 		(GeditDocument                *doc,
+						 GtkTextIter                  *start,
+						 GtkTextIter                  *end);
 			     
 struct _GeditDocumentPrivate
 {
@@ -124,6 +125,7 @@ struct _GeditDocumentPrivate
 	gint	     num_of_lines_search_text;
 
 	GeditDocumentNewlineType newline_type;
+	GeditDocumentCompressionType compression_type;
 
 	/* Temp data while loading */
 	GeditDocumentLoader *loader;
@@ -162,7 +164,8 @@ enum {
 	PROP_ENCODING,
 	PROP_CAN_SEARCH_AGAIN,
 	PROP_ENABLE_SEARCH_HIGHLIGHTING,
-	PROP_NEWLINE_TYPE
+	PROP_NEWLINE_TYPE,
+	PROP_COMPRESSION_TYPE
 };
 
 enum {
@@ -240,6 +243,18 @@ set_newline_type (GeditDocument           *doc,
 }
 
 static void
+set_compression_type (GeditDocument *doc,
+                      GeditDocumentCompressionType compression_type)
+{
+	if (doc->priv->compression_type != compression_type)
+	{
+		doc->priv->compression_type = compression_type;
+
+		g_object_notify (G_OBJECT (doc), "compression-type");
+	}
+}
+
+static void
 gedit_document_dispose (GObject *object)
 {
 	GeditDocument *doc = GEDIT_DOCUMENT (object); 
@@ -376,6 +391,9 @@ gedit_document_get_property (GObject    *object,
 		case PROP_NEWLINE_TYPE:
 			g_value_set_enum (value, doc->priv->newline_type);
 			break;
+		case PROP_COMPRESSION_TYPE:
+			g_value_set_enum (value, doc->priv->compression_type);
+			break;
 		default:
 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 			break;
@@ -400,6 +418,10 @@ gedit_document_set_property (GObject      *object,
 			set_newline_type (doc,
 					  g_value_get_enum (value));
 			break;
+		case PROP_COMPRESSION_TYPE:
+			set_compression_type (doc,
+			                      g_value_get_enum (value));
+			break;
 		case PROP_SHORTNAME:
 			gedit_document_set_short_name_for_display (doc,
 			                                           g_value_get_string (value));
@@ -545,6 +567,24 @@ gedit_document_class_init (GeditDocumentClass *klass)
 	                                                    GEDIT_TYPE_DOCUMENT_NEWLINE_TYPE,
 	                                                    GEDIT_DOCUMENT_NEWLINE_TYPE_LF,
 	                                                    G_PARAM_READWRITE |
+	                                                    G_PARAM_CONSTRUCT |
+	                                                    G_PARAM_STATIC_NAME |
+	                                                    G_PARAM_STATIC_BLURB));
+
+	/**
+	 * GeditDocument:compression-type:
+	 *
+	 * The :compression-type property determines how to compress the
+	 * document when saving
+	 */
+	g_object_class_install_property (object_class, PROP_COMPRESSION_TYPE,
+	                                 g_param_spec_enum ("compression-type",
+	                                                    "Compression type",
+	                                                    "The save compression type",
+	                                                    GEDIT_TYPE_DOCUMENT_COMPRESSION_TYPE,
+	                                                    GEDIT_DOCUMENT_COMPRESSION_TYPE_NONE,
+	                                                    G_PARAM_READWRITE |
+	                                                    G_PARAM_CONSTRUCT |
 	                                                    G_PARAM_STATIC_NAME |
 	                                                    G_PARAM_STATIC_BLURB));
 
@@ -633,14 +673,15 @@ gedit_document_class_init (GeditDocumentClass *klass)
 			      G_SIGNAL_RUN_LAST,
 			      G_STRUCT_OFFSET (GeditDocumentClass, save),
 			      NULL, NULL,
-			      gedit_marshal_VOID__OBJECT_BOXED_ENUM_FLAGS,
+			      gedit_marshal_VOID__OBJECT_BOXED_ENUM_ENUM_FLAGS,
 			      G_TYPE_NONE,
-			      4,
+			      5,
 			      G_TYPE_FILE,
 			      /* we rely on the fact that the GeditEncoding pointer stays
 			       * the same forever */
 			      GEDIT_TYPE_ENCODING | G_SIGNAL_TYPE_STATIC_SCOPE,
 			      GEDIT_TYPE_DOCUMENT_NEWLINE_TYPE,
+			      GEDIT_TYPE_DOCUMENT_COMPRESSION_TYPE,
 			      GEDIT_TYPE_DOCUMENT_SAVE_FLAGS);
 
 	document_signals[SAVING] =
@@ -936,8 +977,6 @@ gedit_document_init (GeditDocument *doc)
 
 	doc->priv->encoding = gedit_encoding_get_utf8 ();
 
-	doc->priv->newline_type = GEDIT_DOCUMENT_NEWLINE_TYPE_DEFAULT;
-
 	g_settings_get (doc->priv->editor_settings, GEDIT_SETTINGS_MAX_UNDO_ACTIONS,
 			"u", &undo_actions);
 	bracket_matching = g_settings_get_boolean (doc->priv->editor_settings,
@@ -988,10 +1027,40 @@ gedit_document_new (void)
 	return GEDIT_DOCUMENT (g_object_new (GEDIT_TYPE_DOCUMENT, NULL));
 }
 
+static gchar *
+get_content_type_from_content (GeditDocument *doc)
+{
+	gchar *content_type;
+	gchar *data;
+	gsize datalen;
+	GtkTextBuffer *buf;
+	GtkTextIter start, end;
+
+	buf = GTK_TEXT_BUFFER (doc);
+
+	gtk_text_buffer_get_start_iter (buf, &start);
+	end = start;
+	gtk_text_iter_forward_chars (&end, 255);
+
+	data = gtk_text_buffer_get_text (buf, &start, &end, TRUE);
+	datalen = strlen (data);
+
+	content_type = g_content_type_guess (NULL,
+	                                     (const guchar *)data,
+	                                     datalen,
+	                                     NULL);
+
+	g_free (data);
+
+	return content_type;
+}
+
 static void
 set_content_type_no_guess (GeditDocument *doc,
 			   const gchar   *content_type)
 {
+	gchar *dupped_content_type;
+
 	gedit_debug (DEBUG_DOCUMENT);
 
 	if (doc->priv->content_type != NULL && content_type != NULL &&
@@ -1000,10 +1069,27 @@ set_content_type_no_guess (GeditDocument *doc,
 
 	g_free (doc->priv->content_type);
 
-	if (content_type == NULL || g_content_type_is_unknown (content_type))
+	/* For compression types, we try to just guess from the content */
+	if (gedit_utils_get_compression_type_from_content_type (content_type) !=
+	    GEDIT_DOCUMENT_COMPRESSION_TYPE_NONE)
+	{
+		dupped_content_type = get_content_type_from_content (doc);
+	}
+	else
+	{
+		dupped_content_type = g_strdup (content_type);
+	}
+
+	if (dupped_content_type == NULL ||
+	    g_content_type_is_unknown (dupped_content_type))
+	{
 		doc->priv->content_type = get_default_content_type ();
+		g_free (dupped_content_type);
+	}
 	else
-		doc->priv->content_type = g_strdup (content_type);
+	{
+		doc->priv->content_type = dupped_content_type;
+	}
 
 	g_object_notify (G_OBJECT (doc), "content-type");
 }
@@ -1320,6 +1406,9 @@ document_loader_loaded (GeditDocumentLoader *loader,
 		set_newline_type (doc,
 		                  gedit_document_loader_get_newline_type (loader));
 
+		set_compression_type (doc,
+		                      gedit_document_loader_get_compression_type (loader));
+
 		restore_cursor = g_settings_get_boolean (doc->priv->editor_settings,
 							 GEDIT_SETTINGS_RESTORE_CURSOR_POSITION);
 
@@ -1612,18 +1701,22 @@ document_saver_saving (GeditDocumentSaver *saver,
 }
 
 static void
-gedit_document_save_real (GeditDocument           *doc,
-			  GFile                   *location,
-			  const GeditEncoding     *encoding,
-			  GeditDocumentNewlineType newline_type,
-			  GeditDocumentSaveFlags   flags)
+gedit_document_save_real (GeditDocument                *doc,
+			  GFile                        *location,
+			  const GeditEncoding          *encoding,
+			  GeditDocumentNewlineType      newline_type,
+			  GeditDocumentCompressionType  compression_type,
+			  GeditDocumentSaveFlags        flags)
 {
 	g_return_if_fail (doc->priv->saver == NULL);
 
 	/* create a saver, it will be destroyed once saving is complete */
-	doc->priv->saver = gedit_document_saver_new (doc, location, encoding,
-						     newline_type,
-						     flags);
+	doc->priv->saver = gedit_document_saver_new (doc,
+	                                             location,
+	                                             encoding,
+	                                             newline_type,
+	                                             compression_type,
+	                                             flags);
 
 	g_signal_connect (doc->priv->saver,
 			  "saving",
@@ -1632,6 +1725,7 @@ gedit_document_save_real (GeditDocument           *doc,
 
 	doc->priv->requested_encoding = encoding;
 	doc->priv->newline_type = newline_type;
+	doc->priv->compression_type = compression_type;
 
 	gedit_document_saver_save (doc->priv->saver,
 				   &doc->priv->mtime);
@@ -1658,6 +1752,7 @@ gedit_document_save (GeditDocument          *doc,
 		       doc->priv->location,
 		       doc->priv->encoding,
 		       doc->priv->newline_type,
+		       doc->priv->compression_type,
 		       flags);
 }
 
@@ -1673,11 +1768,12 @@ gedit_document_save (GeditDocument          *doc,
  * to be emitted.
  */
 void
-gedit_document_save_as (GeditDocument           *doc,
-			GFile                   *location,
-			const GeditEncoding     *encoding,
-			GeditDocumentNewlineType newline_type,
-			GeditDocumentSaveFlags   flags)
+gedit_document_save_as (GeditDocument                *doc,
+			GFile                        *location,
+			const GeditEncoding          *encoding,
+			GeditDocumentNewlineType      newline_type,
+			GeditDocumentCompressionType  compression_type,
+			GeditDocumentSaveFlags        flags)
 {
 	g_return_if_fail (GEDIT_IS_DOCUMENT (doc));
 	g_return_if_fail (G_IS_FILE (location));
@@ -1691,6 +1787,7 @@ gedit_document_save_as (GeditDocument           *doc,
 		       location,
 		       encoding,
 		       newline_type,
+		       compression_type,
 		       flags | GEDIT_DOCUMENT_SAVE_IGNORE_MTIME);
 }
 
@@ -2614,6 +2711,14 @@ gedit_document_get_newline_type (GeditDocument *doc)
 	return doc->priv->newline_type;
 }
 
+GeditDocumentCompressionType
+gedit_document_get_compression_type (GeditDocument *doc)
+{
+	g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), 0);
+
+	return doc->priv->compression_type;
+}
+
 void
 _gedit_document_set_mount_operation_factory (GeditDocument 	       *doc,
 					    GeditMountOperationFactory	callback,
@@ -2798,4 +2903,5 @@ gedit_document_set_metadata (GeditDocument *doc,
 	g_object_unref (info);
 }
 #endif
+
 /* ex:ts=8:noet: */
diff --git a/gedit/gedit-document.h b/gedit/gedit-document.h
index b5a80ed..4d24e2d 100644
--- a/gedit/gedit-document.h
+++ b/gedit/gedit-document.h
@@ -82,6 +82,23 @@ typedef enum
 
 } GeditSearchFlags;
 
+/*
+ * NOTE: when adding a new compression type, make sure to update:
+ *   1) The document loader to support it
+ *   2) gedit_document_compression_type_for_display
+ */
+
+/**
+ * GeditDocumentCompressionType:
+ * @GEDIT_DOCUMENT_COMPRESSION_TYPE_NONE: save file in plain text.
+ * @GEDIT_DOCUMENT_COMPRESSION_TYPE_GZIP: save file using gzip compression.
+ */
+typedef enum
+{
+	GEDIT_DOCUMENT_COMPRESSION_TYPE_NONE,
+	GEDIT_DOCUMENT_COMPRESSION_TYPE_GZIP
+} GeditDocumentCompressionType;
+
 /**
  * GeditDocumentSaveFlags:
  * @GEDIT_DOCUMENT_SAVE_IGNORE_MTIME: save file despite external modifications.
@@ -140,11 +157,12 @@ struct _GeditDocumentClass
 					 const GError     *error);
 
 	/* Document save */
-	void (* save)			(GeditDocument           *document,
-					 GFile                   *location,
-					 const GeditEncoding     *encoding,
-					 GeditDocumentNewlineType newline_type,
-					 GeditDocumentSaveFlags   flags);
+	void (* save)			(GeditDocument                *document,
+					 GFile                        *location,
+					 const GeditEncoding          *encoding,
+					 GeditDocumentNewlineType      newline_type,
+					 GeditDocumentCompressionType  compression_type,
+					 GeditDocumentSaveFlags        flags);
 
 	void (* saving)			(GeditDocument    *document,
 					 goffset	   size,
@@ -220,11 +238,12 @@ gboolean	 gedit_document_load_cancel	(GeditDocument       *doc);
 void		 gedit_document_save 		(GeditDocument       *doc,
 						 GeditDocumentSaveFlags flags);
 
-void		 gedit_document_save_as 	(GeditDocument           *doc,	
-						 GFile                   *location, 
-						 const GeditEncoding     *encoding,
-						 GeditDocumentNewlineType newline_type,
-						 GeditDocumentSaveFlags   flags);
+void		 gedit_document_save_as 	(GeditDocument                *doc,
+						 GFile                        *location,
+						 const GeditEncoding          *encoding,
+						 GeditDocumentNewlineType      newline_type,
+						 GeditDocumentCompressionType  compression_type,
+						 GeditDocumentSaveFlags        flags);
 
 gboolean	 gedit_document_is_untouched 	(GeditDocument       *doc);
 gboolean	 gedit_document_is_untitled 	(GeditDocument       *doc);
@@ -285,6 +304,9 @@ gboolean	 gedit_document_get_enable_search_highlighting
 GeditDocumentNewlineType
 		 gedit_document_get_newline_type (GeditDocument *doc);
 
+GeditDocumentCompressionType
+		 gedit_document_get_compression_type (GeditDocument *doc);
+
 gchar		*gedit_document_get_metadata	(GeditDocument *doc,
 						 const gchar   *key);
 
diff --git a/gedit/gedit-file-chooser-dialog.c b/gedit/gedit-file-chooser-dialog.c
index 84de7fb..9cbacfe 100644
--- a/gedit/gedit-file-chooser-dialog.c
+++ b/gedit/gedit-file-chooser-dialog.c
@@ -524,17 +524,14 @@ gedit_file_chooser_dialog_get_encoding (GeditFileChooserDialog *dialog)
 				GEDIT_ENCODINGS_COMBO_BOX (dialog->priv->option_menu));
 }
 
-void
-gedit_file_chooser_dialog_set_newline_type (GeditFileChooserDialog  *dialog,
-					    GeditDocumentNewlineType newline_type)
+static void
+set_enum_combo (GtkComboBox *combo,
+                gint         value)
 {
 	GtkTreeIter iter;
 	GtkTreeModel *model;
 
-	g_return_if_fail (GEDIT_IS_FILE_CHOOSER_DIALOG (dialog));
-	g_return_if_fail (gtk_file_chooser_get_action (GTK_FILE_CHOOSER (dialog)) == GTK_FILE_CHOOSER_ACTION_SAVE);
-
-	model = GTK_TREE_MODEL (dialog->priv->newline_store);
+	model = gtk_combo_box_get_model (combo);
 
 	if (!gtk_tree_model_get_iter_first (model, &iter))
 	{
@@ -543,19 +540,29 @@ gedit_file_chooser_dialog_set_newline_type (GeditFileChooserDialog  *dialog,
 
 	do
 	{
-		GeditDocumentNewlineType nt;
+		gint nt;
 
 		gtk_tree_model_get (model, &iter, 1, &nt, -1);
 
-		if (newline_type == nt)
+		if (value == nt)
 		{
-			gtk_combo_box_set_active_iter (GTK_COMBO_BOX (dialog->priv->newline_combo),
-			                               &iter);
+			gtk_combo_box_set_active_iter (combo, &iter);
 			break;
 		}
 	} while (gtk_tree_model_iter_next (model, &iter));
 }
 
+void
+gedit_file_chooser_dialog_set_newline_type (GeditFileChooserDialog  *dialog,
+					    GeditDocumentNewlineType newline_type)
+{
+	g_return_if_fail (GEDIT_IS_FILE_CHOOSER_DIALOG (dialog));
+	g_return_if_fail (gtk_file_chooser_get_action (GTK_FILE_CHOOSER (dialog)) == GTK_FILE_CHOOSER_ACTION_SAVE);
+
+	set_enum_combo (GTK_COMBO_BOX (dialog->priv->newline_combo),
+	                newline_type);
+}
+
 GeditDocumentNewlineType
 gedit_file_chooser_dialog_get_newline_type (GeditFileChooserDialog *dialog)
 {
@@ -577,4 +584,5 @@ gedit_file_chooser_dialog_get_newline_type (GeditFileChooserDialog *dialog)
 
 	return newline_type;
 }
+
 /* ex:ts=8:noet: */
diff --git a/gedit/gedit-marshal.list b/gedit/gedit-marshal.list
index 8a46a0b..dec851b 100644
--- a/gedit/gedit-marshal.list
+++ b/gedit/gedit-marshal.list
@@ -5,7 +5,7 @@ VOID:BOOLEAN,POINTER
 VOID:BOXED,BOXED
 VOID:OBJECT
 VOID:POINTER
-VOID:OBJECT,BOXED,ENUM,FLAGS
+VOID:OBJECT,BOXED,ENUM,ENUM,FLAGS
 VOID:OBJECT,BOXED,INT,BOOLEAN
 VOID:UINT,POINTER
 VOID:UINT64,UINT64
diff --git a/gedit/gedit-tab.c b/gedit/gedit-tab.c
index e3ba9a1..7c178ac 100644
--- a/gedit/gedit-tab.c
+++ b/gedit/gedit-tab.c
@@ -1294,6 +1294,7 @@ recoverable_saving_error_message_area_response (GtkWidget *message_area,
 					tab->priv->tmp_save_location,
 					tab->priv->tmp_encoding,
 					gedit_document_get_newline_type (doc),
+					gedit_document_get_compression_type (doc),
 					tab->priv->save_flags);
 	}
 	else
@@ -2274,10 +2275,11 @@ gedit_tab_auto_save (GeditTab *tab)
 }
 
 void
-_gedit_tab_save_as (GeditTab                 *tab,
-                    GFile                    *location,
-                    const GeditEncoding      *encoding,
-                    GeditDocumentNewlineType  newline_type)
+_gedit_tab_save_as (GeditTab                     *tab,
+                    GFile                        *location,
+                    const GeditEncoding          *encoding,
+                    GeditDocumentNewlineType      newline_type,
+                    GeditDocumentCompressionType  compression_type)
 {
 	GeditDocument *doc;
 	GeditDocumentSaveFlags save_flags;
@@ -2323,8 +2325,12 @@ _gedit_tab_save_as (GeditTab                 *tab,
 	if (tab->priv->auto_save_timeout > 0)
 		remove_auto_save_timeout (tab);
 
-	gedit_document_save_as (doc, location, encoding, newline_type,
-				tab->priv->save_flags);
+	gedit_document_save_as (doc,
+	                        location,
+	                        encoding,
+	                        newline_type,
+	                        compression_type,
+	                        tab->priv->save_flags);
 }
 
 #define GEDIT_PAGE_SETUP_KEY "gedit-page-setup-key"
diff --git a/gedit/gedit-tab.h b/gedit/gedit-tab.h
index f607a96..bf64425 100644
--- a/gedit/gedit-tab.h
+++ b/gedit/gedit-tab.h
@@ -162,7 +162,8 @@ void		 _gedit_tab_save		(GeditTab            *tab);
 void		 _gedit_tab_save_as		(GeditTab            *tab,
 						 GFile               *location,
 						 const GeditEncoding *encoding,
-						 GeditDocumentNewlineType newline_type);
+						 GeditDocumentNewlineType newline_type,
+						 GeditDocumentCompressionType compression_type);
 
 void		 _gedit_tab_print		(GeditTab            *tab);
 void		 _gedit_tab_print_preview	(GeditTab            *tab);
diff --git a/gedit/gedit-utils.c b/gedit/gedit-utils.c
index beddc24..9f7c0f3 100644
--- a/gedit/gedit-utils.c
+++ b/gedit/gedit-utils.c
@@ -1539,4 +1539,20 @@ gedit_utils_can_read_from_stdin (void)
 #endif
 }
 
+GeditDocumentCompressionType
+gedit_utils_get_compression_type_from_content_type (const gchar *content_type)
+{
+	if (content_type == NULL)
+	{
+		return GEDIT_DOCUMENT_COMPRESSION_TYPE_NONE;
+	}
+
+	if (g_content_type_is_a (content_type, "application/x-gzip"))
+	{
+		return GEDIT_DOCUMENT_COMPRESSION_TYPE_GZIP;
+	}
+
+	return GEDIT_DOCUMENT_COMPRESSION_TYPE_NONE;
+}
+
 /* ex:ts=8:noet: */
diff --git a/gedit/gedit-utils.h b/gedit/gedit-utils.h
index 7225a3f..4602595 100644
--- a/gedit/gedit-utils.h
+++ b/gedit/gedit-utils.h
@@ -37,6 +37,7 @@
 #include <gtk/gtk.h>
 #include <atk/atk.h>
 #include <gedit/gedit-encodings.h>
+#include <gedit/gedit-document.h>
 #include <gtksourceview/gtksourceview.h>
 
 G_BEGIN_DECLS
@@ -157,6 +158,9 @@ gchar 	       **gedit_utils_drop_get_uris		(GtkSelectionData *selection_data);
 
 gboolean	 gedit_utils_can_read_from_stdin	(void);
 
+GeditDocumentCompressionType
+		 gedit_utils_get_compression_type_from_content_type (const gchar *content_type);
+
 G_END_DECLS
 
 #endif /* __GEDIT_UTILS_H__ */
diff --git a/plugin-loaders/python/bindings/gedit.defs b/plugin-loaders/python/bindings/gedit.defs
index e19eb2c..b634405 100644
--- a/plugin-loaders/python/bindings/gedit.defs
+++ b/plugin-loaders/python/bindings/gedit.defs
@@ -114,6 +114,16 @@
   )
 )
 
+(define-enum CompressionType
+  (in-module "Gedit")
+  (c-name "GeditDocumentCompressionType")
+  (gtype-id "GEDIT_TYPE_DOCUMENT_COMPRESSION_TYPE")
+  (values
+    '("none" "GEDIT_DOCUMENT_COMPRESSION_TYPE_NONE")
+    '("gzip" "GEDIT_DOCUMENT_COMPRESSION_TYPE_GZIP")
+  )
+)
+
 (define-flags DocumentSaveFlags
   (in-module "Gedit")
   (c-name "GeditDocumentSaveFlags")
@@ -290,6 +300,12 @@
   (return-type "GeditDocumentNewlineType")
 )
 
+(define-method get_compression_type
+  (of-object "GeditDocument")
+  (c-name "gedit_document_get_compression_type")
+  (return-type "GeditDocumentCompressionType")
+)
+
 (define-method get_uri_for_display
   (of-object "GeditDocument")
   (c-name "gedit_document_get_uri_for_display")
@@ -356,6 +372,7 @@
     '("GFile*" "location")
     '("const-GeditEncoding*" "encoding" (default "NULL") (null-ok))
     '("GeditDocumentNewlineType" "newline_type" (default "0"))
+    '("GeditDocumentCompressionType" "compression_type" (default "0"))
     '("GeditDocumentSaveFlags" "flags" (default "0"))
   )
 )
diff --git a/tests/document-saver.c b/tests/document-saver.c
index 070fcb0..e5da2b6 100644
--- a/tests/document-saver.c
+++ b/tests/document-saver.c
@@ -218,7 +218,7 @@ test_saver (const gchar              *filename_or_uri,
 	ensure_mounted (file);
 
 	gedit_document_save_as (document, file, gedit_encoding_get_utf8 (),
-			        newline_type, save_flags);
+			        newline_type, 0, save_flags);
 
 	while (!test_completed)
 	{



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