aboutsummaryrefslogtreecommitdiffstats
path: root/src/adblock-ui.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/adblock-ui.c')
-rw-r--r--src/adblock-ui.c390
1 files changed, 390 insertions, 0 deletions
diff --git a/src/adblock-ui.c b/src/adblock-ui.c
new file mode 100644
index 000000000..d41ed53c1
--- /dev/null
+++ b/src/adblock-ui.c
@@ -0,0 +1,390 @@
+/*
+ * Copyright © 2011 Igalia S.L.
+ *
+ * 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, or (at your option)
+ * any later version.
+ *
+ * Some parts of this file based on the Midori's 'adblock' extension,
+ * licensed with the GNU Lesser General Public License 2.1, Copyright
+ * (C) 2009-2010 Christian Dywan <christian@twotoasts.de> and 2009
+ * Alexander Butenko <a.butenka@gmail.com>. Check Midori's web site
+ * at http://www.twotoasts.de
+ *
+ * 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.
+ */
+
+#include "config.h"
+#include "adblock-ui.h"
+
+#include "ephy-adblock.h"
+#include "ephy-adblock-manager.h"
+#include "ephy-debug.h"
+#include "ephy-embed-shell.h"
+
+#include <glib/gi18n-lib.h>
+#include <gtk/gtk.h>
+
+#define ADBLOCK_UI_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE((object), TYPE_ADBLOCK_UI, AdblockUIPrivate))
+
+#define ADBLOCK_FILTER_VALID(__filter) \
+ (__filter && (g_str_has_prefix (__filter, "http") \
+ || g_str_has_prefix (__filter, "file")))
+
+struct _AdblockUIPrivate
+{
+ GtkWidget *dialog;
+
+ /* The dialog buttons. */
+ GtkEntry *new_filter;
+ GtkButton *add, *edit, *remove;
+
+ /* Data. */
+ GtkTreeView *treeview;
+ GtkTreeSelection *selection;
+ GtkListStore *store;
+
+ /* The uri tester. */
+ UriTester *tester;
+
+ /* Whether something has actually changed. */
+ gboolean dirty;
+};
+
+enum
+{
+ PROP_0,
+ PROP_TESTER,
+};
+
+enum
+{
+ COL_FILTER_URI,
+ N_COLUMNS
+};
+
+G_DEFINE_DYNAMIC_TYPE (AdblockUI, adblock_ui, EPHY_TYPE_DIALOG);
+
+/* Private functions. */
+
+static gboolean
+adblock_ui_foreach_save (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ GSList **filters)
+{
+ char *filter = NULL;
+
+ gtk_tree_model_get (model, iter, COL_FILTER_URI, &filter, -1);
+ *filters = g_slist_prepend (*filters, filter);
+
+ return FALSE;
+}
+
+static void
+adblock_ui_save (AdblockUI *dialog)
+{
+ GSList *filters = NULL;
+ gtk_tree_model_foreach (GTK_TREE_MODEL (dialog->priv->store),
+ (GtkTreeModelForeachFunc)adblock_ui_foreach_save,
+ &filters);
+
+ uri_tester_set_filters (dialog->priv->tester, filters);
+}
+
+static void
+adblock_ui_response_cb (GtkWidget *widget,
+ int response,
+ AdblockUI *dialog)
+{
+ if (response == GTK_RESPONSE_CLOSE && dialog->priv->dirty)
+ {
+ EphyAdBlockManager *manager;
+
+ adblock_ui_save (dialog);
+
+ /* Ask uri tester to reload all its patterns. */
+ uri_tester_reload (dialog->priv->tester);
+
+ /* Ask manager to emit a signal that rules have changed. */
+ manager = EPHY_ADBLOCK_MANAGER (ephy_embed_shell_get_adblock_manager (embed_shell));
+
+ g_signal_emit_by_name (manager, "rules_changed", NULL);
+ }
+
+ g_object_unref (dialog);
+}
+
+static void
+adblock_ui_add_filter (AdblockUI *dialog)
+{
+ GtkTreeIter iter;
+
+ const char *new_filter = gtk_entry_get_text (dialog->priv->new_filter);
+
+ if (ADBLOCK_FILTER_VALID (new_filter))
+ {
+ GtkListStore *store = dialog->priv->store;
+
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter, COL_FILTER_URI, new_filter, -1);
+
+ /* Makes the pattern field blank. */
+ gtk_entry_set_text (dialog->priv->new_filter, "");
+
+ dialog->priv->dirty = TRUE;
+ }
+ else
+ {
+ GtkWidget *error_dialog = NULL;
+ error_dialog = gtk_message_dialog_new (GTK_WINDOW (dialog->priv->dialog),
+ GTK_DIALOG_MODAL,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_OK,
+ "%s",
+ _("Invalid filter"));
+ gtk_dialog_run (GTK_DIALOG (error_dialog));
+ gtk_widget_destroy (error_dialog);
+
+ gtk_entry_set_text (dialog->priv->new_filter, "");
+ }
+}
+
+static void
+adblock_ui_add_cb (GtkButton *button,
+ AdblockUI *dialog)
+{
+ adblock_ui_add_filter (dialog);
+}
+
+static void
+adblock_ui_edit_cb (GtkButton *button,
+ AdblockUI *dialog)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GtkTreeSelection *selection;
+
+ selection = dialog->priv->selection;
+
+ if (gtk_tree_selection_get_selected (selection, &model, &iter))
+ {
+ char* path = gtk_tree_model_get_string_from_iter (model, &iter);
+ GtkTreePath* tree_path = gtk_tree_path_new_from_string (path);
+ GtkTreeView *treeview = dialog->priv->treeview;
+ GtkTreeViewColumn *column = gtk_tree_view_get_column (treeview,
+ COL_FILTER_URI);
+
+ gtk_tree_view_set_cursor (treeview, tree_path, column, TRUE);
+ gtk_tree_path_free (tree_path);
+ g_free (path);
+ }
+}
+
+static void
+adblock_ui_remove_cb (GtkButton *button,
+ AdblockUI *dialog)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GtkTreeSelection *selection;
+
+ selection = dialog->priv->selection;
+
+ if (gtk_tree_selection_get_selected (selection, &model, &iter))
+ {
+ gtk_list_store_remove (GTK_LIST_STORE(model), &iter);
+ gtk_entry_set_text (dialog->priv->new_filter, "");
+
+ dialog->priv->dirty = TRUE;
+ }
+}
+
+static void
+adblock_ui_cell_edited_cb (GtkCellRendererText *cell,
+ char *path_string,
+ char *new_filter,
+ AdblockUI *dialog)
+{
+ GtkTreeModel *model = GTK_TREE_MODEL (dialog->priv->store);
+ GtkTreePath *path = gtk_tree_path_new_from_string (path_string);
+ GtkTreeIter iter;
+
+ gtk_tree_model_get_iter (model, &iter, path);
+ gtk_list_store_set (dialog->priv->store, &iter, COL_FILTER_URI, new_filter, -1);
+ gtk_tree_path_free (path);
+
+ dialog->priv->dirty = TRUE;
+}
+
+static void
+adblock_ui_build_treeview (AdblockUI *dialog)
+{
+ GtkCellRenderer *renderer;
+
+ dialog->priv->store = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING);
+
+ renderer = gtk_cell_renderer_text_new ();
+ g_object_set(renderer, "editable", TRUE, NULL);
+ g_signal_connect(renderer,
+ "edited",
+ (GCallback) adblock_ui_cell_edited_cb,
+ (gpointer)dialog);
+
+ gtk_tree_view_insert_column_with_attributes (dialog->priv->treeview,
+ COL_FILTER_URI, _("Filter URI"),
+ renderer,
+ "text", COL_FILTER_URI,
+ NULL);
+
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (dialog->priv->store),
+ COL_FILTER_URI,
+ GTK_SORT_ASCENDING);
+
+ gtk_tree_view_set_model (dialog->priv->treeview, GTK_TREE_MODEL (dialog->priv->store));
+ gtk_tree_view_set_search_column (dialog->priv->treeview, COL_FILTER_URI);
+
+ g_object_unref (dialog->priv->store);
+
+ dialog->priv->selection = gtk_tree_view_get_selection (dialog->priv->treeview);
+ gtk_tree_selection_set_mode (dialog->priv->selection, GTK_SELECTION_SINGLE);
+
+ dialog->priv->dirty = FALSE;
+}
+
+static void
+adblock_ui_populate_store (AdblockUI *dialog)
+{
+ GSList *filters = NULL;
+ GSList *item = NULL;
+ const char *filter_uri = NULL;
+ GtkTreeIter iter;
+
+ filters = uri_tester_get_filters (dialog->priv->tester);
+ for (item = filters; item; item = g_slist_next (item))
+ {
+ filter_uri = (const char *) item->data;
+
+ gtk_list_store_append (dialog->priv->store, &iter);
+ gtk_list_store_set (dialog->priv->store, &iter, COL_FILTER_URI, filter_uri, -1);
+ }
+}
+
+static void
+adblock_ui_init (AdblockUI *dialog)
+{
+ LOG ("AdblockUI initialising");
+ dialog->priv = ADBLOCK_UI_GET_PRIVATE (dialog);
+}
+
+static void
+adblock_ui_constructed (GObject *object)
+{
+ AdblockUI *dialog;
+ AdblockUIPrivate *priv;
+ EphyDialog *edialog;
+
+ dialog = ADBLOCK_UI (object);
+ edialog = EPHY_DIALOG (object);
+
+ priv = dialog->priv;
+
+ ephy_dialog_construct (EPHY_DIALOG (edialog),
+ "/org/gnome/epiphany/adblock.ui",
+ "adblock-ui",
+ GETTEXT_PACKAGE);
+
+ ephy_dialog_get_controls (edialog,
+ "adblock-ui", &priv->dialog,
+ "new_filter_entry", &priv->new_filter,
+ "treeview", &priv->treeview,
+ "add_button", &priv->add,
+ "edit_button", &priv->edit,
+ "remove_button", &priv->remove,
+ NULL);
+
+ g_signal_connect (priv->dialog, "response",
+ G_CALLBACK (adblock_ui_response_cb), dialog);
+
+ g_signal_connect (priv->add, "clicked",
+ G_CALLBACK (adblock_ui_add_cb), dialog);
+ g_signal_connect (priv->edit, "clicked",
+ G_CALLBACK (adblock_ui_edit_cb), dialog);
+ g_signal_connect (priv->remove, "clicked",
+ G_CALLBACK (adblock_ui_remove_cb), dialog);
+ g_signal_connect (priv->new_filter, "activate",
+ G_CALLBACK (adblock_ui_add_cb), dialog);
+
+ /* Build and fill. */
+ adblock_ui_build_treeview (dialog);
+ adblock_ui_populate_store (dialog);
+
+ /* Chain up. */
+ G_OBJECT_CLASS (adblock_ui_parent_class)->constructed (object);
+}
+
+static void
+adblock_ui_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ AdblockUI *dialog = ADBLOCK_UI (object);
+
+ switch (prop_id)
+ {
+ case PROP_TESTER:
+ dialog->priv->tester = g_value_get_object (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+adblock_ui_class_init (AdblockUIClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->constructed = adblock_ui_constructed;
+ object_class->set_property = adblock_ui_set_property;
+
+ g_object_class_install_property
+ (object_class,
+ PROP_TESTER,
+ g_param_spec_object ("tester",
+ "UriTester",
+ "UriTester",
+ TYPE_URI_TESTER,
+ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_type_class_add_private (object_class, sizeof (AdblockUIPrivate));
+}
+
+static void adblock_ui_class_finalize (AdblockUIClass *klass)
+{
+}
+
+/* Public functions. */
+
+void adblock_ui_register (GTypeModule *module)
+{
+ adblock_ui_register_type (module);
+}
+
+AdblockUI *
+adblock_ui_new (UriTester *tester)
+{
+ return g_object_new (TYPE_ADBLOCK_UI,
+ "tester", tester,
+ NULL);
+}