From ef0467789bfc8406b57ba553e4d59f4d6c3f9be8 Mon Sep 17 00:00:00 2001 From: Stefano Karapetsas Date: Wed, 14 Dec 2011 10:13:54 +0100 Subject: Moved from Mate-Extra repository --- logview/logview-filter-manager.c | 569 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 569 insertions(+) create mode 100644 logview/logview-filter-manager.c (limited to 'logview/logview-filter-manager.c') diff --git a/logview/logview-filter-manager.c b/logview/logview-filter-manager.c new file mode 100644 index 00000000..d46f1aca --- /dev/null +++ b/logview/logview-filter-manager.c @@ -0,0 +1,569 @@ +/*-*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */ +/* + * mate-utils + * Copyright (C) Johannes Schmid 2009 + * + * mate-utils 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 3 of the License, or + * (at your option) any later version. + * + * mate-utils 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, see . + */ + +#include "logview-filter-manager.h" +#include "logview-prefs.h" +#include +#include +#include + +#define UI_FILE LOGVIEW_DATADIR "/logview-filter.ui" + +struct _LogviewFilterManagerPrivate { + GtkWidget *tree; + + GtkWidget *add_button; + GtkWidget *remove_button; + GtkWidget *edit_button; + + GtkTreeModel *model; + GtkBuilder* builder; + + LogviewPrefs* prefs; +}; + +enum { + COLUMN_NAME = 0, + COLUMN_FILTER, + N_COLUMNS +}; + +#define LOGVIEW_FILTER_MANAGER_GET_PRIVATE(o) \ +(G_TYPE_INSTANCE_GET_PRIVATE ((o), LOGVIEW_TYPE_FILTER_MANAGER, LogviewFilterManagerPrivate)) + +G_DEFINE_TYPE (LogviewFilterManager, logview_filter_manager, GTK_TYPE_DIALOG); + +static void +logview_filter_manager_update_model (LogviewFilterManager *manager) +{ + GList *filters; + GList *filter; + gchar *name; + GtkTreeIter iter; + + gtk_list_store_clear (GTK_LIST_STORE (manager->priv->model)); + + filters = logview_prefs_get_filters (manager->priv->prefs); + + for (filter = filters; filter != NULL; filter = g_list_next (filter)) { + g_object_get (filter->data, "name", &name, NULL); + + gtk_list_store_append (GTK_LIST_STORE(manager->priv->model), &iter); + gtk_list_store_set (GTK_LIST_STORE (manager->priv->model), + &iter, + COLUMN_NAME, name, + COLUMN_FILTER, filter->data, + -1); + + g_free (name); + } + + g_list_free (filters); +} + +static gboolean +check_name (LogviewFilterManager *manager, const gchar *name) +{ + GtkWidget *dialog; + + if (!strlen (name)) { + dialog = gtk_message_dialog_new (GTK_WINDOW (manager), + GTK_DIALOG_MODAL, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_CLOSE, + "%s", _("Filter name is empty!")); + gtk_dialog_run (GTK_DIALOG (dialog)); + + gtk_widget_destroy (dialog); + + return FALSE; + } + + if (strstr (name, ":") != NULL) { + dialog = gtk_message_dialog_new (GTK_WINDOW(manager), + GTK_DIALOG_MODAL, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_CLOSE, + "%s", _("Filter name may not contain the ':' character")); + gtk_dialog_run (GTK_DIALOG (dialog)); + + gtk_widget_destroy (dialog); + + return FALSE; + } + + return TRUE; +} + +static gboolean +check_regex (LogviewFilterManager *manager, const gchar *regex) +{ + GtkWidget *dialog; + GError *error = NULL; + GRegex *reg; + + if (!strlen (regex)) { + dialog = gtk_message_dialog_new (GTK_WINDOW(manager), + GTK_DIALOG_MODAL, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_CLOSE, + "%s", _("Regular expression is empty!")); + + gtk_dialog_run (GTK_DIALOG (dialog)); + + gtk_widget_destroy (dialog); + + return FALSE; + } + + reg = g_regex_new (regex, + 0, 0, &error); + if (error) { + dialog = gtk_message_dialog_new (GTK_WINDOW (manager), + GTK_DIALOG_MODAL, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_CLOSE, + _("Regular expression is invalid: %s"), + error->message); + gtk_dialog_run (GTK_DIALOG (dialog)); + + gtk_widget_destroy (dialog); + g_error_free (error); + + return FALSE; + } + + g_regex_unref (reg); + + return TRUE; +} + +static void +on_check_toggled (GtkToggleButton *button, GtkWidget *widget) +{ + gtk_widget_set_sensitive (widget, + gtk_toggle_button_get_active (button)); +} + +static void +on_dialog_add_edit_reponse (GtkWidget *dialog, int response_id, + LogviewFilterManager *manager) +{ + GtkWidget *entry_name, *entry_regex; + GtkWidget *radio_color, *radio_visible; + GtkWidget *check_foreground, *check_background; + GtkWidget *color_foreground, *color_background; + gchar *old_name; + const gchar *name; + const gchar *regex; + LogviewFilter *filter; + GtkTextTag *tag; + GtkBuilder *builder; + + old_name = g_object_get_data (G_OBJECT (manager), "old_name"); + builder = manager->priv->builder; + + entry_name = GTK_WIDGET (gtk_builder_get_object (builder, + "entry_name")); + entry_regex = GTK_WIDGET (gtk_builder_get_object (builder, + "entry_regex")); + radio_color = GTK_WIDGET (gtk_builder_get_object (builder, + "radio_color")); + radio_visible = GTK_WIDGET (gtk_builder_get_object (builder, + "radio_visible")); + check_foreground = GTK_WIDGET (gtk_builder_get_object (builder, + "check_foreground")); + check_background = GTK_WIDGET (gtk_builder_get_object (builder, + "check_background")); + color_foreground = GTK_WIDGET (gtk_builder_get_object (builder, + "color_foreground")); + color_background = GTK_WIDGET (gtk_builder_get_object (builder, + "color_background")); + + if (response_id == GTK_RESPONSE_APPLY) { + name = gtk_entry_get_text (GTK_ENTRY (entry_name)); + regex = gtk_entry_get_text (GTK_ENTRY (entry_regex)); + + if (!check_name (manager, name) || !check_regex (manager, regex)) { + return; + } + + filter = logview_filter_new (name, regex); + tag = gtk_text_tag_new (name); + + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (radio_color))) { + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check_foreground))) { + GdkColor foreground_color; + gtk_color_button_get_color (GTK_COLOR_BUTTON (color_foreground), + &foreground_color); + g_object_set (G_OBJECT (tag), + "foreground-gdk", &foreground_color, + "foreground-set", TRUE, NULL); + } + + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check_background))) { + GdkColor background_color; + gtk_color_button_get_color (GTK_COLOR_BUTTON (color_background), + &background_color); + g_object_set (tag, + "paragraph-background-gdk", &background_color, + "paragraph-background-set", TRUE, NULL); + } + + if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check_foreground)) + && !gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check_background))) { + GtkWidget *error_dialog; + + error_dialog = gtk_message_dialog_new (GTK_WINDOW (manager), + GTK_DIALOG_MODAL, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_CLOSE, + "%s", + _("Please specify either foreground or background color!")); + gtk_dialog_run (GTK_DIALOG (error_dialog)); + gtk_widget_destroy (error_dialog); + g_object_unref (tag); + g_object_unref (filter); + + return; + } + } else { /* !gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (radio_color)) */ + g_object_set (tag, "invisible", TRUE, NULL); + } + + if (old_name && !g_str_equal (old_name, name)) { + logview_prefs_remove_filter (manager->priv->prefs, old_name); + } + + g_object_set (G_OBJECT (filter), "texttag", tag, NULL); + g_object_unref (tag); + + logview_prefs_add_filter (manager->priv->prefs, filter); + g_object_unref (filter); + + logview_filter_manager_update_model (manager); + } + + gtk_widget_destroy (dialog); +} + +static void +run_add_edit_dialog (LogviewFilterManager *manager, LogviewFilter *filter) +{ + GError *error; + gchar *name, *regex; + const gchar *title; + GtkWidget *dialog, *entry_name, *entry_regex, *radio_color; + GtkWidget *radio_visible, *check_foreground, *check_background; + GtkWidget *color_foreground, *color_background, *vbox_color; + gboolean foreground_set, background_set, invisible; + GtkTextTag *tag; + GtkBuilder* builder; + + builder = manager->priv->builder; + + error = NULL; + name = NULL; + + gtk_builder_add_from_file (builder, UI_FILE, &error); + + if (error) { + g_warning ("Could not load filter ui: %s", error->message); + g_error_free (error); + return; + } + + title = (filter != NULL ? _("Edit filter") : _("Add new filter")); + + dialog = GTK_WIDGET (gtk_builder_get_object (builder, + "dialog_filter")); + + entry_name = GTK_WIDGET (gtk_builder_get_object (builder, + "entry_name")); + entry_regex = GTK_WIDGET (gtk_builder_get_object (builder, + "entry_regex")); + radio_color = GTK_WIDGET (gtk_builder_get_object (builder, + "radio_color")); + radio_visible = GTK_WIDGET (gtk_builder_get_object (builder, + "radio_visible")); + + gtk_radio_button_set_group (GTK_RADIO_BUTTON (radio_color), + gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_visible))); + + check_foreground = GTK_WIDGET (gtk_builder_get_object (builder, + "check_foreground")); + check_background = GTK_WIDGET (gtk_builder_get_object (builder, + "check_background")); + color_foreground = GTK_WIDGET (gtk_builder_get_object (builder, + "color_foreground")); + color_background = GTK_WIDGET (gtk_builder_get_object (builder, + "color_background")); + g_signal_connect (check_foreground, "toggled", G_CALLBACK (on_check_toggled), + color_foreground); + g_signal_connect (check_background, "toggled", G_CALLBACK (on_check_toggled), + color_background); + + on_check_toggled (GTK_TOGGLE_BUTTON (check_foreground), + color_foreground); + on_check_toggled (GTK_TOGGLE_BUTTON (check_background), + color_background); + + vbox_color = GTK_WIDGET (gtk_builder_get_object (builder, "vbox_color")); + g_signal_connect (radio_color, "toggled", G_CALLBACK (on_check_toggled), + vbox_color); + on_check_toggled (GTK_TOGGLE_BUTTON (radio_color), + vbox_color); + + if (filter) { + g_object_get (filter, + "name", &name, + "regex", ®ex, + "texttag", &tag, + NULL); + g_object_get (tag, + "foreground-set", &foreground_set, + "paragraph-background-set", &background_set, + "invisible", &invisible, NULL); + gtk_entry_set_text (GTK_ENTRY(entry_name), name); + gtk_entry_set_text (GTK_ENTRY(entry_regex), regex); + + if (foreground_set) { + GdkColor *foreground; + + g_object_get (tag, "foreground-gdk", &foreground, NULL); + gtk_color_button_set_color (GTK_COLOR_BUTTON (color_foreground), + foreground); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_foreground), + TRUE); + + gdk_color_free (foreground); + } + + if (background_set) { + GdkColor *background; + + g_object_get (tag, "paragraph-background-gdk", &background, NULL); + gtk_color_button_set_color (GTK_COLOR_BUTTON (color_background), + background); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_background), + TRUE); + + gdk_color_free (background); + } + + if (background_set || foreground_set) { + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio_color), TRUE); + } else if (invisible) { + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio_visible), TRUE); + } + + g_free (regex); + g_object_unref (tag); + } + + g_object_set_data_full (G_OBJECT (manager), "old_name", name, g_free); + + g_signal_connect (G_OBJECT (dialog), "response", + G_CALLBACK (on_dialog_add_edit_reponse), manager); + gtk_window_set_transient_for (GTK_WINDOW (dialog), + GTK_WINDOW (manager)); + gtk_window_set_modal (GTK_WINDOW (dialog), + TRUE); + + gtk_widget_show (GTK_WIDGET (dialog)); +} + +static void +on_add_clicked (GtkWidget *button, LogviewFilterManager *manager) +{ + run_add_edit_dialog (manager, NULL); +} + +static void +on_edit_clicked (GtkWidget *button, LogviewFilterManager *manager) +{ + GtkTreeIter iter; + GtkTreeModel *model; + LogviewFilter *filter; + GtkTreeSelection *selection; + + selection = + gtk_tree_view_get_selection (GTK_TREE_VIEW (manager->priv->tree)); + + gtk_tree_selection_get_selected (selection, &model, &iter); + gtk_tree_model_get (model, &iter, COLUMN_FILTER, &filter, -1); + + run_add_edit_dialog (manager, filter); + + g_object_unref (filter); +} + +static void +on_remove_clicked (GtkWidget *button, LogviewFilterManager *manager) +{ + GtkTreeSelection *selection; + GtkTreeIter iter; + GtkTreeModel *model; + gchar *name; + + selection = + gtk_tree_view_get_selection (GTK_TREE_VIEW (manager->priv->tree)); + + gtk_tree_selection_get_selected (selection, &model, &iter); + gtk_tree_model_get (model, &iter, COLUMN_NAME, &name, -1); + + logview_prefs_remove_filter (manager->priv->prefs, name); + logview_filter_manager_update_model (manager); + + g_free(name); +} + +static void +on_tree_selection_changed (GtkTreeSelection *selection, LogviewFilterManager *manager) +{ + gboolean status; + + status = gtk_tree_selection_get_selected (selection, NULL, NULL); + + gtk_widget_set_sensitive (manager->priv->edit_button, status); + gtk_widget_set_sensitive (manager->priv->remove_button, status); +} + +static void +logview_filter_manager_init (LogviewFilterManager *manager) +{ + GtkWidget *table; + GtkWidget *scrolled_window; + GtkTreeViewColumn *column; + GtkCellRenderer *text_renderer; + LogviewFilterManagerPrivate *priv; + + manager->priv = LOGVIEW_FILTER_MANAGER_GET_PRIVATE (manager); + priv = manager->priv; + + priv->builder = gtk_builder_new (); + g_object_ref (priv->builder); + priv->prefs = logview_prefs_get (); + + gtk_dialog_add_button (GTK_DIALOG(manager), + GTK_STOCK_CLOSE, + GTK_RESPONSE_CLOSE); + gtk_window_set_modal (GTK_WINDOW (manager), + TRUE); + + priv->model = GTK_TREE_MODEL (gtk_list_store_new (N_COLUMNS, + G_TYPE_STRING, + G_TYPE_OBJECT)); + logview_filter_manager_update_model (manager); + + table = gtk_table_new (3, 2, FALSE); + scrolled_window = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window), + GTK_SHADOW_ETCHED_IN); + priv->tree = gtk_tree_view_new_with_model (priv->model); + gtk_widget_set_size_request (priv->tree, 150, 200); + gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (priv->tree), FALSE); + gtk_container_add (GTK_CONTAINER (scrolled_window), priv->tree); + + text_renderer = gtk_cell_renderer_text_new (); + + column = gtk_tree_view_column_new(); + gtk_tree_view_column_pack_start (column, text_renderer, TRUE); + gtk_tree_view_column_set_attributes (column, + text_renderer, + "text", COLUMN_NAME, + NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (priv->tree), + column); + + priv->add_button = gtk_button_new_from_stock (GTK_STOCK_ADD); + priv->edit_button = gtk_button_new_from_stock (GTK_STOCK_PROPERTIES); + priv->remove_button = gtk_button_new_from_stock (GTK_STOCK_REMOVE); + + gtk_window_set_title (GTK_WINDOW (manager), + _("Filters")); + + g_signal_connect (priv->add_button, "clicked", + G_CALLBACK (on_add_clicked), manager); + g_signal_connect (priv->edit_button, "clicked", + G_CALLBACK (on_edit_clicked), manager); + g_signal_connect (priv->remove_button, "clicked", + G_CALLBACK (on_remove_clicked), manager); + + gtk_widget_set_sensitive (priv->edit_button, FALSE); + gtk_widget_set_sensitive (priv->remove_button, FALSE); + + g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tree)), + "changed", G_CALLBACK (on_tree_selection_changed), + manager); + + gtk_table_attach_defaults (GTK_TABLE (table), + scrolled_window, + 0, 1, 0, 3); + gtk_table_attach (GTK_TABLE (table), + priv->add_button, + 1, 2, 0, 1, GTK_FILL, 0, 5, 5); + gtk_table_attach (GTK_TABLE (table), + priv->edit_button, + 1, 2, 1, 2, GTK_FILL, 0, 5, 5); + gtk_table_attach (GTK_TABLE (table), + priv->remove_button, + 1, 2, 2, 3, GTK_FILL, 0, 5, 5); + gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (manager))), + table, TRUE, TRUE, 5); + gtk_widget_show_all (GTK_WIDGET (manager)); +} + +static void +logview_filter_manager_dispose (GObject *object) +{ + LogviewFilterManager* manager; + + manager = LOGVIEW_FILTER_MANAGER (object); + + g_object_unref (manager->priv->builder); + + G_OBJECT_CLASS (logview_filter_manager_parent_class)->dispose (object); +} + +static void +logview_filter_manager_response (GtkDialog* dialog, gint response_id) +{ + gtk_widget_destroy (GTK_WIDGET (dialog)); +} + +static void +logview_filter_manager_class_init (LogviewFilterManagerClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GtkDialogClass *parent_class = GTK_DIALOG_CLASS (klass); + + g_type_class_add_private (klass, sizeof (LogviewFilterManagerPrivate)); + + object_class->dispose = logview_filter_manager_dispose; + parent_class->response = logview_filter_manager_response; +} + +GtkWidget * +logview_filter_manager_new (void) +{ + return g_object_new (LOGVIEW_TYPE_FILTER_MANAGER, NULL); +} -- cgit v1.2.1