/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ /* * Copyright (C) 2018 Sébastien Wilmet * * 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, see . */ #include "dh-tab.h" #include #include "tepl-info-bar.h" /* A DhWebView with a possible TeplInfoBar on top. */ struct _DhTabPrivate { TeplInfoBar *info_bar; DhWebView *web_view; }; G_DEFINE_TYPE_WITH_PRIVATE (DhTab, dh_tab, GTK_TYPE_GRID) static void dh_tab_dispose (GObject *object) { DhTab *tab = DH_TAB (object); tab->priv->info_bar = NULL; tab->priv->web_view = NULL; G_OBJECT_CLASS (dh_tab_parent_class)->dispose (object); } static void dh_tab_class_init (DhTabClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->dispose = dh_tab_dispose; } static gboolean web_view_load_failed_cb (WebKitWebView *web_view, WebKitLoadEvent load_event, const gchar *failing_uri, GError *error, DhTab *tab) { /* Ignore cancellation errors, which happen when typing fast in the * search entry. */ if (g_error_matches (error, WEBKIT_NETWORK_ERROR, WEBKIT_NETWORK_ERROR_CANCELLED)) return GDK_EVENT_STOP; if (tab->priv->info_bar != NULL) gtk_widget_destroy (GTK_WIDGET (tab->priv->info_bar)); tab->priv->info_bar = tepl_info_bar_new_simple (GTK_MESSAGE_ERROR, _("Error opening the requested link."), error->message); tepl_info_bar_add_close_button (tab->priv->info_bar); g_signal_connect (tab->priv->info_bar, "destroy", G_CALLBACK (gtk_widget_destroyed), &tab->priv->info_bar); gtk_grid_attach_next_to (GTK_GRID (tab), GTK_WIDGET (tab->priv->info_bar), GTK_WIDGET (tab->priv->web_view), GTK_POS_TOP, 1, 1); gtk_widget_show (GTK_WIDGET (tab->priv->info_bar)); return GDK_EVENT_STOP; } static gboolean web_view_decide_policy_cb (WebKitWebView *web_view, WebKitPolicyDecision *decision, WebKitPolicyDecisionType decision_type, DhTab *tab) { if (decision_type == WEBKIT_POLICY_DECISION_TYPE_NAVIGATION_ACTION && tab->priv->info_bar != NULL) { /* The error is no longer relevant. Do it here, not in * ::load-changed, so that it works when clicking on a link to * an anchor inside the same page too, not only when loading a * different page. */ gtk_widget_destroy (GTK_WIDGET (tab->priv->info_bar)); } return GDK_EVENT_PROPAGATE; } static void dh_tab_init (DhTab *tab) { tab->priv = dh_tab_get_instance_private (tab); gtk_orientable_set_orientation (GTK_ORIENTABLE (tab), GTK_ORIENTATION_VERTICAL); tab->priv->web_view = dh_web_view_new (); gtk_widget_show (GTK_WIDGET (tab->priv->web_view)); gtk_container_add (GTK_CONTAINER (tab), GTK_WIDGET (tab->priv->web_view)); g_signal_connect (tab->priv->web_view, "load-failed", G_CALLBACK (web_view_load_failed_cb), tab); /* Other ::decide-policy signal handlers that return GDK_EVENT_STOP must * be connected *after* this one. This code relies on the fact that * GObject executes the handlers in the same order than the connection * order (for all the handlers belonging to the same emission stage). */ g_signal_connect (tab->priv->web_view, "decide-policy", G_CALLBACK (web_view_decide_policy_cb), tab); } DhTab * dh_tab_new (void) { return g_object_new (DH_TYPE_TAB, NULL); } DhWebView * dh_tab_get_web_view (DhTab *tab) { g_return_val_if_fail (DH_IS_TAB (tab), NULL); return tab->priv->web_view; }