X-Git-Url: http://git.maemo.org/git/?p=gconf-editor;a=blobdiff_plain;f=src%2Fgedit-output-window.c;fp=src%2Fgedit-output-window.c;h=18b6dc9a4acbda323c453de1a2581d8a112c7433;hp=0000000000000000000000000000000000000000;hb=34f89e89320f83ec38ebf7257ddfe4d4a84b7cf0;hpb=3a0d577474f47cb857051247625d9fb7911d0f50 diff --git a/src/gedit-output-window.c b/src/gedit-output-window.c new file mode 100644 index 0000000..18b6dc9 --- /dev/null +++ b/src/gedit-output-window.c @@ -0,0 +1,603 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * gedit-output_window.c + * This file is part of gedit + * + * Copyright (C) 1998, 1999 Alex Roberts, Evan Lawrence + * Copyright (C) 2000, 2002 Chema Celorio, Paolo Maggi + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the gedit Team, 1998-2002. See the AUTHORS file for a + * list of people on the gedit Team. + * See the ChangeLog files for a list of changes. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include "gedit-output-window.h" + +struct _GeditOutputWindowPrivate +{ + GtkWidget *close_button; + GtkWidget *copy_button; + GtkWidget *clear_button; + + GtkWidget *close_menu_item; + GtkWidget *copy_menu_item; + GtkWidget *clear_menu_item; + + GtkWidget *treeview; + GtkTreeModel *model; +}; + +enum { + CLOSE_REQUESTED, + SELECTION_CHANGED, + LAST_SIGNAL +}; + +static guint signals [LAST_SIGNAL]; + +enum +{ + COLUMN_LINES, + NUM_COLUMNS +}; + + +static void gedit_output_window_finalize (GObject *object); +static void gedit_output_window_destroy (GtkObject *object); + +G_DEFINE_TYPE(GeditOutputWindow, gedit_output_window, GTK_TYPE_HBOX) + +static void +gedit_output_window_class_init (GeditOutputWindowClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = gedit_output_window_finalize; + + GTK_OBJECT_CLASS (klass)->destroy = gedit_output_window_destroy; + + signals[CLOSE_REQUESTED] = + g_signal_new ("close_requested", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GeditOutputWindowClass, close_requested), + NULL, + NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + signals[SELECTION_CHANGED] = + g_signal_new ("selection_changed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GeditOutputWindowClass, selection_changed), + NULL, + NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, + 1, G_TYPE_STRING); + +} + +static void +gedit_output_window_copy_selection (GeditOutputWindow *ow) +{ + gboolean ret; + GtkTreeIter iter; + GtkTreeSelection *selection; + + GString *string = NULL; + + g_return_if_fail (GEDIT_IS_OUTPUT_WINDOW (ow)); + + selection = gtk_tree_view_get_selection ( + GTK_TREE_VIEW (ow->priv->treeview)); + + ret = gtk_tree_model_get_iter_first (ow->priv->model, &iter); + + while (ret) + { + if (gtk_tree_selection_iter_is_selected (selection, &iter)) + { + gchar *line; + + gtk_tree_model_get (ow->priv->model, &iter, COLUMN_LINES, &line, -1); + + if (string == NULL) + string = g_string_new (line); + else + string = g_string_append (string, line); + + string = g_string_append_c (string, '\n'); + + g_free (line); + } + + ret = gtk_tree_model_iter_next (ow->priv->model, &iter); + } + + if (string != NULL) + { + gchar *text; + + pango_parse_markup (string->str, string->len, 0, NULL, &text, NULL, NULL); + + gtk_clipboard_set_text (gtk_widget_get_clipboard ( + GTK_WIDGET (ow), GDK_SELECTION_CLIPBOARD), + text, + -1); + + g_free (text); + } + + g_string_free (string, TRUE); +} + +static void +close_clicked_callback (GtkWidget *widget, gpointer user_data) +{ + GeditOutputWindow *ow; + + ow = GEDIT_OUTPUT_WINDOW (user_data); + + g_signal_emit (ow, signals [CLOSE_REQUESTED], 0); +} + +static void +clear_clicked_callback (GtkWidget *widget, gpointer user_data) +{ + GeditOutputWindow *ow; + + ow = GEDIT_OUTPUT_WINDOW (user_data); + + gedit_output_window_clear (ow); +} + +static void +copy_clicked_callback (GtkWidget *widget, gpointer user_data) +{ + GeditOutputWindow *ow; + + ow = GEDIT_OUTPUT_WINDOW (user_data); + + gedit_output_window_copy_selection (ow); +} + +static gboolean +gedit_output_window_key_press_event_cb (GtkTreeView *widget, GdkEventKey *event, + GeditOutputWindow *ow) +{ + if (event->keyval == GDK_Delete) + { + gedit_output_window_clear (ow); + return TRUE; + } + + if (event->keyval == 'c') + { + gedit_output_window_copy_selection (ow); + return TRUE; + } + + return FALSE; +} + +static GtkWidget * +create_popup_menu (GeditOutputWindow *output_window) +{ + GtkWidget *menu; + GtkWidget *menu_item; + + menu = gtk_menu_new (); + + /* Add the clear button */ + output_window->priv->clear_menu_item = gtk_image_menu_item_new_from_stock (GTK_STOCK_CLEAR, NULL); + gtk_widget_show (output_window->priv->clear_menu_item); + g_signal_connect (G_OBJECT (output_window->priv->clear_menu_item), "activate", + G_CALLBACK (clear_clicked_callback), output_window); + gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), output_window->priv->clear_menu_item); + + /* Add the copy button */ + output_window->priv->copy_menu_item = gtk_image_menu_item_new_from_stock (GTK_STOCK_COPY, NULL); + gtk_widget_show (output_window->priv->copy_menu_item); + g_signal_connect (G_OBJECT (output_window->priv->copy_menu_item), "activate", + G_CALLBACK (copy_clicked_callback), output_window); + gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), output_window->priv->copy_menu_item); + + /* Add the separator */ + menu_item = gtk_separator_menu_item_new (); + gtk_widget_show (menu_item); + gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), menu_item); + + /* Add the close button */ + output_window->priv->close_menu_item = gtk_image_menu_item_new_from_stock (GTK_STOCK_CLOSE, NULL); + gtk_widget_show (output_window->priv->close_menu_item); + g_signal_connect (G_OBJECT (output_window->priv->close_menu_item), "activate", + G_CALLBACK (close_clicked_callback), output_window); + gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), output_window->priv->close_menu_item); + + gtk_widget_set_sensitive (output_window->priv->copy_menu_item, FALSE); + gtk_widget_set_sensitive (output_window->priv->clear_menu_item, FALSE); + + return menu; +} + +static gint +my_popup_handler (GtkWidget *widget, GdkEvent *event) +{ + GtkMenu *menu; + GdkEventButton *event_button; + + g_return_val_if_fail (widget != NULL, FALSE); + g_return_val_if_fail (GTK_IS_MENU (widget), FALSE); + g_return_val_if_fail (event != NULL, FALSE); + + /* The "widget" is the menu that was supplied when + * g_signal_connect_swapped() was called. + */ + menu = GTK_MENU (widget); + + if (event->type == GDK_BUTTON_PRESS) + { + event_button = (GdkEventButton *) event; + if (event_button->button == 3) + { + gtk_menu_popup (menu, NULL, NULL, NULL, NULL, + event_button->button, event_button->time); + return TRUE; + } + } + + return FALSE; +} + +static void +gedit_output_window_treeview_selection_changed (GtkTreeSelection *selection, + GeditOutputWindow *output_window) +{ + gboolean selected; + GtkTreeModel *model; + GtkTreeIter iter; + gchar *line; + + g_return_if_fail (output_window != NULL); + g_return_if_fail (selection != NULL); + + selected = (gtk_tree_selection_count_selected_rows (selection) > 0); + + gtk_widget_set_sensitive (output_window->priv->copy_menu_item, selected); + gtk_widget_set_sensitive (output_window->priv->copy_button, selected); + + if (gtk_tree_selection_get_selected (selection, &model, &iter)) { + gtk_tree_model_get (model, &iter, COLUMN_LINES, &line, -1); + g_signal_emit (output_window, signals [SELECTION_CHANGED], 0, line); + } +} + +static void +gedit_output_window_format_button (GtkButton* button, gint w, gint h) +{ + GtkRcStyle* rc = gtk_widget_get_modifier_style (GTK_WIDGET (button)); + rc->xthickness = 0; + rc->ythickness = 0; + gtk_widget_modify_style (GTK_WIDGET (button), rc); + gtk_button_set_relief (button, GTK_RELIEF_NONE); + gtk_button_set_focus_on_click (button, FALSE); +} + +static void +gedit_output_window_init (GeditOutputWindow *output_window) +{ + GtkSettings *settings; + gint w, h; + GtkWidget *vbox1; + GtkWidget *image; + GtkWidget *hbox2; + GtkWidget *vseparator; + GtkWidget *vbox2; + GtkWidget *scrolledwindow; + GtkTreeViewColumn *column; + GtkCellRenderer *cell; + GtkTreeSelection *selection; + GtkWidget *popup_menu; + + GList *focusable_widgets = NULL; + + output_window->priv = g_new0 (GeditOutputWindowPrivate, 1); + + settings = gtk_widget_get_settings (GTK_WIDGET (output_window)); + + gtk_icon_size_lookup_for_settings (settings, + GTK_ICON_SIZE_MENU, + &w, &h); + + vbox1 = gtk_vbox_new (FALSE, 2); + gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2); + + /* Create the close button */ + output_window->priv->close_button = gtk_button_new (); + gtk_box_pack_start (GTK_BOX (vbox1), output_window->priv->close_button, FALSE, FALSE, 0); + + gtk_widget_set_tooltip_text (output_window->priv->close_button, + _("Close the output window")); + + gedit_output_window_format_button (GTK_BUTTON (output_window->priv->close_button), w, h); + + image = gtk_image_new_from_stock (GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU); + gtk_container_add (GTK_CONTAINER (output_window->priv->close_button), image); + + g_signal_connect (output_window->priv->close_button, + "clicked", + G_CALLBACK (close_clicked_callback), + output_window); + + /* Create the 3 vertical separators */ + hbox2 = gtk_hbox_new (TRUE, 0); + gtk_box_pack_start (GTK_BOX (vbox1), hbox2, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox2), 4); + + vseparator = gtk_vseparator_new (); + gtk_box_pack_start (GTK_BOX (hbox2), vseparator, FALSE, FALSE, 0); + + vseparator = gtk_vseparator_new (); + gtk_box_pack_start (GTK_BOX (hbox2), vseparator, FALSE, FALSE, 0); + + vseparator = gtk_vseparator_new (); + gtk_box_pack_start (GTK_BOX (hbox2), vseparator, FALSE, TRUE, 0); + + /* Create the vbox for the copy and clear buttons */ + vbox2 = gtk_vbox_new (TRUE, 0); + gtk_box_pack_start (GTK_BOX (vbox1), vbox2, FALSE, TRUE, 0); + + /* Create the copy button */ + output_window->priv->copy_button = gtk_button_new (); + gtk_box_pack_start (GTK_BOX (vbox2), output_window->priv->copy_button, FALSE, FALSE, 0); + + gtk_widget_set_tooltip_text (output_window->priv->copy_button, + _("Copy selected lines")); + + gedit_output_window_format_button (GTK_BUTTON (output_window->priv->copy_button), w, h); + + image = gtk_image_new_from_stock (GTK_STOCK_COPY, GTK_ICON_SIZE_MENU); + gtk_container_add (GTK_CONTAINER (output_window->priv->copy_button), image); + + g_signal_connect (output_window->priv->copy_button, + "clicked", + G_CALLBACK (copy_clicked_callback), + output_window); + + /* Create the clear button */ + output_window->priv->clear_button = gtk_button_new (); + gtk_box_pack_start (GTK_BOX (vbox2), output_window->priv->clear_button, FALSE, FALSE, 0); + + gtk_widget_set_tooltip_text (output_window->priv->clear_button, + _("Clear the output window")); + + gedit_output_window_format_button (GTK_BUTTON (output_window->priv->clear_button), w, h); + + image = gtk_image_new_from_stock (GTK_STOCK_CLEAR, GTK_ICON_SIZE_MENU); + gtk_container_add (GTK_CONTAINER (output_window->priv->clear_button), image); + + g_signal_connect (output_window->priv->clear_button, + "clicked", + G_CALLBACK (clear_clicked_callback), + output_window); + + gtk_widget_set_sensitive (output_window->priv->copy_button, FALSE); + gtk_widget_set_sensitive (output_window->priv->clear_button, FALSE); + + /* Create the scrolled window */ + scrolledwindow = gtk_scrolled_window_new (NULL, NULL); + + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow), + GTK_SHADOW_ETCHED_IN); + + output_window->priv->treeview = gtk_tree_view_new (); + gtk_container_add (GTK_CONTAINER (scrolledwindow), output_window->priv->treeview); + gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (output_window->priv->treeview), FALSE); + + + /* List */ + output_window->priv->model = GTK_TREE_MODEL ( + gtk_list_store_new (NUM_COLUMNS, G_TYPE_STRING)); + + gtk_tree_view_set_model (GTK_TREE_VIEW (output_window->priv->treeview), + output_window->priv->model); + + /* Add the suggestions column */ + cell = gtk_cell_renderer_text_new (); + column = gtk_tree_view_column_new_with_attributes (_("Output Lines"), cell, + "markup", COLUMN_LINES, NULL); + + gtk_tree_view_append_column (GTK_TREE_VIEW (output_window->priv->treeview), column); + + gtk_tree_view_set_search_column (GTK_TREE_VIEW (output_window->priv->treeview), + COLUMN_LINES); + + selection = gtk_tree_view_get_selection ( + GTK_TREE_VIEW (output_window->priv->treeview)); + + gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE); + + gtk_box_pack_end (GTK_BOX (output_window), scrolledwindow, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (output_window), vbox1, FALSE, FALSE, 0); + + gtk_widget_set_size_request (GTK_WIDGET (output_window), 3 * w, 5 * (h + 2)); + + g_signal_connect (G_OBJECT (output_window->priv->treeview), "key_press_event", + G_CALLBACK (gedit_output_window_key_press_event_cb), output_window); + + g_signal_connect (G_OBJECT (selection), "changed", + G_CALLBACK (gedit_output_window_treeview_selection_changed), + output_window); + + focusable_widgets = g_list_append (focusable_widgets, output_window->priv->treeview); + focusable_widgets = g_list_append (focusable_widgets, output_window->priv->close_button); + focusable_widgets = g_list_append (focusable_widgets, output_window->priv->copy_button); + focusable_widgets = g_list_append (focusable_widgets, output_window->priv->clear_button); + + gtk_container_set_focus_chain (GTK_CONTAINER (output_window), focusable_widgets); + + g_list_free (focusable_widgets); + + popup_menu = create_popup_menu (output_window); + + gtk_menu_attach_to_widget(GTK_MENU(popup_menu), output_window->priv->treeview, NULL); + + g_signal_connect_swapped (output_window->priv->treeview, "button_press_event", G_CALLBACK (my_popup_handler), popup_menu); + + +} + +static void +gedit_output_window_finalize (GObject *object) +{ + GeditOutputWindow *ow; + + ow = GEDIT_OUTPUT_WINDOW (object); + + if (ow->priv != NULL) + { + g_free (ow->priv); + } + + G_OBJECT_CLASS (gedit_output_window_parent_class)->finalize (object); +} + +static void +gedit_output_window_destroy (GtkObject *object) +{ + GTK_OBJECT_CLASS (gedit_output_window_parent_class)->destroy (object); +} + +GtkWidget * +gedit_output_window_new (void) +{ + return gtk_widget_new (GEDIT_TYPE_OUTPUT_WINDOW, NULL); +} + +void +gedit_output_window_clear (GeditOutputWindow *ow) +{ + g_return_if_fail (GEDIT_IS_OUTPUT_WINDOW (ow)); + + gtk_list_store_clear (GTK_LIST_STORE (ow->priv->model)); + + gtk_widget_set_sensitive (ow->priv->clear_button, FALSE); + gtk_widget_set_sensitive (ow->priv->clear_menu_item, FALSE); +} + +void +gedit_output_window_append_line (GeditOutputWindow *ow, const gchar *line, gboolean scroll) +{ + GtkListStore *store; + GtkTreeIter iter; + GtkTreePath *path; + + g_return_if_fail (GEDIT_IS_OUTPUT_WINDOW (ow)); + g_return_if_fail (line != NULL); + + store = GTK_LIST_STORE (ow->priv->model); + g_return_if_fail (store != NULL); + + gtk_list_store_append (store, &iter); + + gtk_list_store_set (store, &iter, COLUMN_LINES, line, -1); + + gtk_widget_set_sensitive (ow->priv->clear_button, TRUE); + gtk_widget_set_sensitive (ow->priv->clear_menu_item, TRUE); + + if (!scroll) + return; + + path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), &iter); + g_return_if_fail (path != NULL); + + gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (ow->priv->treeview), + path, + NULL, + TRUE, + 0.0, + 0.0); + + gtk_tree_path_free (path); +} + +void +gedit_output_window_prepend_line (GeditOutputWindow *ow, const gchar *line, gboolean scroll) +{ + GtkListStore *store; + GtkTreeIter iter; + GtkTreePath *path; + + g_return_if_fail (GEDIT_IS_OUTPUT_WINDOW (ow)); + g_return_if_fail (line != NULL); + + store = GTK_LIST_STORE (ow->priv->model); + g_return_if_fail (store != NULL); + + gtk_list_store_prepend (store, &iter); + + gtk_list_store_set (store, &iter, COLUMN_LINES, line, -1); + + gtk_widget_set_sensitive (ow->priv->clear_button, TRUE); + gtk_widget_set_sensitive (ow->priv->clear_menu_item, TRUE); + + if (!scroll) + return; + + path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), &iter); + g_return_if_fail (path != NULL); + + gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (ow->priv->treeview), + path, + NULL, + TRUE, + 0.0, + 0.0); + + gtk_tree_path_free (path); + +} + + + +void +gedit_output_window_set_select_multiple (GeditOutputWindow *ow, const GtkSelectionMode type) +{ + GtkTreeSelection *selection; + + g_return_if_fail (GEDIT_IS_OUTPUT_WINDOW (ow)); + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (ow->priv->treeview)); + gtk_tree_selection_set_mode (selection, type); +}