/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
/*
* Copyright (C) 2018 Sébastien Wilmet <swilmet@gnome.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "dh-tab.h"
#include <glib/gi18n.h>
#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;
}