[gnome-terminal] Bug 24457 - allow saving terminal content



commit 8b1a8640231945b50c691b34ebb82b9026dde0cd
Author: Behdad Esfahbod <behdad behdad org>
Date:   Wed Jan 13 20:22:11 2010 -0500

    Bug 24457 - allow saving terminal content
    
    Implemented now.

 configure.ac                  |    2 +-
 src/gnome-terminal.schemas.in |   17 +++++++
 src/terminal-accels.c         |    4 ++
 src/terminal-window.c         |   93 ++++++++++++++++++++++++++++++++++++++++-
 src/terminal.xml              |    1 +
 5 files changed, 115 insertions(+), 2 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 9c97f2c..33eb440 100644
--- a/configure.ac
+++ b/configure.ac
@@ -43,7 +43,7 @@ GLIB_REQUIRED=2.16.0
 GTK_REQUIRED=2.14.0
 GCONF_REQUIRED=2.14.0
 DBUS_GLIB_REQUIRED=0.6
-VTE_REQUIRED=0.23.1
+VTE_REQUIRED=0.23.5
 
 PKG_CHECK_MODULES([TERM],
   [vte >= $VTE_REQUIRED
diff --git a/src/gnome-terminal.schemas.in b/src/gnome-terminal.schemas.in
index 4c5230a..be11301 100644
--- a/src/gnome-terminal.schemas.in
+++ b/src/gnome-terminal.schemas.in
@@ -758,6 +758,23 @@
     </schema>
 
     <schema>
+      <key>/schemas/apps/gnome-terminal/keybindings/save_contents</key>
+      <applyto>/apps/gnome-terminal/keybindings/save_contents</applyto>
+      <owner>gnome-terminal</owner>
+      <type>string</type>
+      <default>disabled</default>
+      <locale name="C">
+          <short>Keyboard shortcut to save the current tab contents to file</short>
+          <long>
+          Keyboard shortcut key to save the current tab contents to a file. Expressed as a string
+          in the same format used for GTK+ resource files.
+          If you set the option to the special string "disabled", then there
+          will be no keyboard shortcut for this action.
+          </long>
+      </locale>
+    </schema>
+
+    <schema>
       <key>/schemas/apps/gnome-terminal/keybindings/close_tab</key>
       <applyto>/apps/gnome-terminal/keybindings/close_tab</applyto>
       <owner>gnome-terminal</owner>
diff --git a/src/terminal-accels.c b/src/terminal-accels.c
index e7d8567..5d1d1a7 100644
--- a/src/terminal-accels.c
+++ b/src/terminal-accels.c
@@ -50,6 +50,7 @@
 #define ACCEL_PATH_NEW_TAB              ACCEL_PATH_ROOT "FileNewTab"
 #define ACCEL_PATH_NEW_WINDOW           ACCEL_PATH_ROOT "FileNewWindow"
 #define ACCEL_PATH_NEW_PROFILE          ACCEL_PATH_ROOT "FileNewProfile"
+#define ACCEL_PATH_SAVE_CONTENTS        ACCEL_PATH_ROOT "FileSaveContents"
 #define ACCEL_PATH_CLOSE_TAB            ACCEL_PATH_ROOT "FileCloseTab"
 #define ACCEL_PATH_CLOSE_WINDOW         ACCEL_PATH_ROOT "FileCloseWindow"
 #define ACCEL_PATH_COPY                 ACCEL_PATH_ROOT "EditCopy"
@@ -86,6 +87,7 @@
 #define KEY_PREV_TAB            CONF_KEYS_PREFIX "/prev_tab"
 #define KEY_RESET_AND_CLEAR     CONF_KEYS_PREFIX "/reset_and_clear"
 #define KEY_RESET               CONF_KEYS_PREFIX "/reset"
+#define KEY_SAVE_CONTENTS       CONF_KEYS_PREFIX "/save_contents"
 #define KEY_SET_TERMINAL_TITLE  CONF_KEYS_PREFIX "/set_window_title"
 #define KEY_TOGGLE_MENUBAR      CONF_KEYS_PREFIX "/toggle_menubar"
 #define KEY_ZOOM_IN             CONF_KEYS_PREFIX "/zoom_in"
@@ -122,6 +124,8 @@ static KeyEntry file_entries[] =
     KEY_NEW_WINDOW, ACCEL_PATH_NEW_WINDOW, GDK_SHIFT_MASK | GDK_CONTROL_MASK, GDK_n, NULL, FALSE, TRUE },
   { N_("New Profile"),
     KEY_NEW_PROFILE, ACCEL_PATH_NEW_PROFILE, 0, 0, NULL, FALSE, TRUE },
+  { N_("Save Contents"),
+    KEY_SAVE_CONTENTS, ACCEL_PATH_SAVE_CONTENTS, 0, 0, NULL, FALSE },
   { N_("Close Tab"),
     KEY_CLOSE_TAB, ACCEL_PATH_CLOSE_TAB, GDK_SHIFT_MASK | GDK_CONTROL_MASK, GDK_w, NULL, FALSE, TRUE },
   { N_("Close Window"),
diff --git a/src/terminal-window.c b/src/terminal-window.c
index e2326d3..f872c58 100644
--- a/src/terminal-window.c
+++ b/src/terminal-window.c
@@ -136,6 +136,8 @@ static void file_new_tab_callback             (GtkAction *action,
                                                TerminalWindow *window);
 static void file_close_window_callback        (GtkAction *action,
                                                TerminalWindow *window);
+static void file_save_contents_callback       (GtkAction *action,
+                                               TerminalWindow *window);
 static void file_close_tab_callback           (GtkAction *action,
                                                TerminalWindow *window);
 static void edit_copy_callback                (GtkAction *action,
@@ -1723,6 +1725,9 @@ terminal_window_init (TerminalWindow *window)
       { "FileNewProfile", GTK_STOCK_OPEN, N_("New _Profileâ?¦"), "",
         NULL,
         G_CALLBACK (file_new_profile_callback) },
+      { "FileSaveContents", GTK_STOCK_SAVE, N_("_Save Contents"), "",
+        NULL,
+        G_CALLBACK (file_save_contents_callback) },
       { "FileCloseTab", GTK_STOCK_CLOSE, N_("C_lose Tab"), "<shift><control>W",
         NULL,
         G_CALLBACK (file_close_tab_callback) },
@@ -3063,11 +3068,97 @@ file_close_window_callback (GtkAction *action,
 {
   if (confirm_close_window_or_tab (window, NULL))
     return;
-  
+
   gtk_widget_destroy (GTK_WIDGET (window));
 }
 
 static void
+save_contents_dialog_on_response (GtkDialog *dialog, gint response_id, gpointer terminal)
+{
+  GtkWindow *parent;
+  gchar *filename_uri = NULL;
+  GFile *file;
+  GOutputStream *stream;
+  GError *error = NULL;
+
+  if (response_id != GTK_RESPONSE_ACCEPT)
+    {
+      gtk_widget_destroy (GTK_WIDGET (dialog));
+      return;
+    }
+
+  parent = (GtkWindow*) gtk_widget_get_ancestor (GTK_WIDGET (terminal), GTK_TYPE_WINDOW);
+  filename_uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dialog));
+
+  gtk_widget_destroy (GTK_WIDGET (dialog));
+
+  if (filename_uri == NULL)
+    return;
+
+  file = g_file_new_for_uri (filename_uri);
+  stream = G_OUTPUT_STREAM (g_file_replace (file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, &error));
+
+  if (stream)
+    {
+      /* XXX
+       * FIXME
+       * This is a sync operation.
+       * Should be replaced with the async version when vte implements that.
+       */
+      vte_terminal_write_contents (terminal, stream,
+				   VTE_TERMINAL_WRITE_DEFAULT,
+				   NULL, &error);
+      g_object_unref (stream);
+    }
+
+  if (error)
+    {
+      terminal_util_show_error_dialog (parent, NULL, error,
+				       "%s", _("Could not save contents"));
+      g_error_free (error);
+    }
+
+  g_object_unref(file);
+  g_free(filename_uri);
+}
+
+static void
+file_save_contents_callback (GtkAction *action,
+                             TerminalWindow *window)
+{
+  GtkWidget *dialog = NULL;
+  TerminalWindowPrivate *priv = window->priv;
+  VteTerminal *terminal;
+
+  if (!priv->active_screen)
+    return;
+
+  terminal = VTE_TERMINAL (priv->active_screen);
+  g_return_if_fail (VTE_IS_TERMINAL (terminal));
+
+  dialog = gtk_file_chooser_dialog_new (_("Save as..."),
+                                        GTK_WINDOW(window),
+                                        GTK_FILE_CHOOSER_ACTION_SAVE,
+                                        GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+                                        GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
+                                        NULL);
+
+  gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
+  /* XXX where should we save to? */
+  gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP));
+
+  gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW(window));
+  gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
+  gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE);
+
+  g_signal_connect (dialog, "response", G_CALLBACK (save_contents_dialog_on_response), terminal);
+  g_signal_connect (dialog, "delete_event", G_CALLBACK (terminal_util_dialog_response_on_delete), NULL);
+
+  gtk_window_present (GTK_WINDOW (dialog));
+}
+
+
+static void
 file_close_tab_callback (GtkAction *action,
                          TerminalWindow *window)
 {
diff --git a/src/terminal.xml b/src/terminal.xml
index f2c41f1..179bed6 100644
--- a/src/terminal.xml
+++ b/src/terminal.xml
@@ -7,6 +7,7 @@
       <menu action="FileNewTabProfiles" />
       <separator />
       <menuitem action="FileNewProfile" />
+      <menuitem action="FileSaveContents" />
       <separator />
       <menuitem action="FileCloseTab" />
       <menuitem action="FileCloseWindow" />



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