summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXan Lopez <xan@igalia.com>2012-07-02 18:41:53 +0200
committerXan Lopez <xan@igalia.com>2012-07-02 18:41:53 +0200
commitc15b64dcd7de8cdc2fcf0ba519fcd8473f76bb02 (patch)
treed96bfb0260392547ba485e9230b35da7600e2389
parent4df50904275b1c1319d67d8c81b4a2570af3df32 (diff)
downloadepiphany-c15b64dcd7de8cdc2fcf0ba519fcd8473f76bb02.tar.gz
WIP for title+domain widget in the toolbar.wip/titledomain
TODO: - Size of the location entry is wrong again due to padding added to back/forward buttons to match design. - Title+domain still shown in some cases where it should not, and viceversa. - Clicking on the widget does nothing.
-rw-r--r--src/Makefile.am2
-rw-r--r--src/ephy-title-domain-box.c243
-rw-r--r--src/ephy-title-domain-box.h64
-rw-r--r--src/ephy-toolbar.c101
-rw-r--r--src/ephy-window.c1
-rw-r--r--src/resources/epiphany.css4
6 files changed, 408 insertions, 7 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 3750c19ec..cfcb87b2e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -31,6 +31,7 @@ NOINST_H_FILES = \
ephy-page-menu-action.h \
ephy-password-info.h \
ephy-private.h \
+ ephy-title-domain-box.h \
ephy-toolbar.h \
ephy-window-action.h \
languages.h \
@@ -72,6 +73,7 @@ libephymain_la_SOURCES = \
ephy-password-info.c \
ephy-session.c \
ephy-shell.c \
+ ephy-title-domain-box.c \
ephy-toolbar.c \
ephy-window.c \
ephy-window-action.c \
diff --git a/src/ephy-title-domain-box.c b/src/ephy-title-domain-box.c
new file mode 100644
index 000000000..59696cf40
--- /dev/null
+++ b/src/ephy-title-domain-box.c
@@ -0,0 +1,243 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Copyright © 2012 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.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "ephy-title-domain-box.h"
+
+#include <libsoup/soup.h>
+
+struct _EphyTitleDomainBoxPrivate {
+ GtkWidget *title;
+ GtkWidget *domain;
+
+ EphyWebView *view;
+
+ GBinding *title_binding;
+ GBinding *domain_binding;
+};
+
+enum {
+ PROP_0,
+
+ PROP_TITLE,
+ PROP_DOMAIN,
+ PROP_VIEW
+};
+
+#define EPHY_TITLE_DOMAIN_BOX_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_TITLE_DOMAIN_BOX, EphyTitleDomainBoxPrivate))
+
+G_DEFINE_TYPE (EphyTitleDomainBox, ephy_title_domain_box, GTK_TYPE_BOX)
+
+static gboolean
+transform_uri_to_domain (GBinding *binding,
+ const GValue *source_value,
+ GValue *target_value,
+ gpointer user_data)
+{
+ const char *uri;
+ SoupURI *soup_uri;
+
+ uri = g_value_get_string (source_value);
+ if (!uri)
+ return FALSE;
+
+ soup_uri = soup_uri_new (uri);
+ g_value_set_string (target_value, soup_uri->host);
+ soup_uri_free (soup_uri);
+
+ return TRUE;
+}
+
+static void
+reset_bindings (EphyTitleDomainBox *box)
+{
+ EphyTitleDomainBoxPrivate *priv = box->priv;
+
+ g_clear_object (&priv->title_binding);
+
+ if (priv->view)
+ priv->title_binding = g_object_bind_property (priv->view, "title",
+ box, "title",
+ G_BINDING_SYNC_CREATE);
+
+ g_clear_object (&priv->domain_binding);
+
+ if (priv->view)
+ priv->domain_binding = g_object_bind_property_full (priv->view, "uri",
+ box, "domain",
+ G_BINDING_SYNC_CREATE,
+ transform_uri_to_domain,
+ NULL, NULL, NULL);
+}
+
+static void
+ephy_title_domain_box_constructed (GObject *object)
+{
+ reset_bindings (EPHY_TITLE_DOMAIN_BOX (object));
+
+ G_OBJECT_CLASS (ephy_title_domain_box_parent_class)->constructed (object);
+}
+
+static void
+ephy_title_domain_box_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ EphyTitleDomainBoxPrivate *priv = EPHY_TITLE_DOMAIN_BOX (object)->priv;
+
+ switch (prop_id) {
+ case PROP_TITLE:
+ break;
+ case PROP_DOMAIN:
+ break;
+ case PROP_VIEW:
+ g_value_set_object (value, priv->view);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+ephy_title_domain_box_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ EphyTitleDomainBoxPrivate *priv = EPHY_TITLE_DOMAIN_BOX (object)->priv;
+
+ switch (prop_id) {
+ case PROP_TITLE: {
+ char *markup = g_markup_printf_escaped ("<span weight='bold'>%s</span>", g_value_get_string (value));
+ gtk_label_set_markup (GTK_LABEL (priv->title), markup);
+ g_free (markup);
+ break;
+ }
+ case PROP_DOMAIN: {
+ const char *base_domain = soup_tld_get_base_domain (g_value_get_string (value), NULL);
+ char *markup = g_markup_printf_escaped ("<span foreground='gray' size='small'>%s</span>", base_domain);
+ gtk_label_set_markup (GTK_LABEL (priv->domain), markup);
+ g_free (markup);
+ break;
+ }
+ case PROP_VIEW:
+ ephy_title_domain_box_set_view (EPHY_TITLE_DOMAIN_BOX (object),
+ g_value_get_object (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+ephy_title_domain_box_class_init (EphyTitleDomainBoxClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->constructed = ephy_title_domain_box_constructed;
+ gobject_class->get_property = ephy_title_domain_box_get_property;
+ gobject_class->set_property = ephy_title_domain_box_set_property;
+
+ g_object_class_install_property (gobject_class,
+ PROP_TITLE,
+ g_param_spec_string ("title",
+ "Domain",
+ "The box's title",
+ "",
+ G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
+ g_object_class_install_property (gobject_class,
+ PROP_DOMAIN,
+ g_param_spec_string ("domain",
+ "Domain",
+ "The box's domain",
+ "",
+ G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
+
+ g_object_class_install_property (gobject_class,
+ PROP_VIEW,
+ g_param_spec_object ("view",
+ "View",
+ "The WebView associated to this widget",
+ EPHY_TYPE_WEB_VIEW,
+ G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
+
+ g_type_class_add_private (klass, sizeof (EphyTitleDomainBoxPrivate));
+}
+
+static void
+ephy_title_domain_box_init (EphyTitleDomainBox *box)
+{
+ EphyTitleDomainBoxPrivate *priv;
+
+ priv = box->priv = EPHY_TITLE_DOMAIN_BOX_GET_PRIVATE (box);
+
+ gtk_orientable_set_orientation (GTK_ORIENTABLE (box), GTK_ORIENTATION_VERTICAL);
+ gtk_box_set_spacing (GTK_BOX (box), 0);
+
+ priv->title = gtk_label_new ("");
+ gtk_widget_set_halign (priv->title, GTK_ALIGN_CENTER);
+ gtk_widget_show (priv->title);
+ gtk_box_pack_start (GTK_BOX (box),
+ priv->title,
+ FALSE, FALSE, 0);
+
+ priv->domain = gtk_label_new ("");
+ gtk_widget_set_halign (priv->domain, GTK_ALIGN_CENTER);
+ gtk_widget_show (priv->domain);
+ gtk_box_pack_start (GTK_BOX (box),
+ priv->domain,
+ FALSE, FALSE, 0);
+}
+
+void
+ephy_title_domain_box_set_view (EphyTitleDomainBox *box,
+ EphyWebView *view)
+{
+ EphyTitleDomainBoxPrivate *priv;
+
+ g_return_if_fail (EPHY_IS_TITLE_DOMAIN_BOX (box));
+
+ priv = box->priv;
+
+ if (priv->view)
+ g_object_unref (priv->view);
+
+ priv->view = view;
+
+ if (priv->view)
+ g_object_ref (priv->view);
+
+ reset_bindings (box);
+
+ g_object_notify (G_OBJECT (box), "view");
+}
+
+GtkWidget *
+ephy_title_domain_box_new (EphyWebView *view)
+{
+ return g_object_new (EPHY_TYPE_TITLE_DOMAIN_BOX,
+ "view", view,
+ NULL);
+}
+
diff --git a/src/ephy-title-domain-box.h b/src/ephy-title-domain-box.h
new file mode 100644
index 000000000..2a7f5958e
--- /dev/null
+++ b/src/ephy-title-domain-box.h
@@ -0,0 +1,64 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=2 sts=2 et: */
+/*
+ * Copyright © 2012 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.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#if !defined (__EPHY_EPIPHANY_H_INSIDE__) && !defined (EPIPHANY_COMPILATION)
+#error "Only <epiphany/epiphany.h> can be included directly."
+#endif
+
+#ifndef EPHY_TITLE_DOMAIN_BOX_H
+#define EPHY_TITLE_DOMAIN_BOX_H
+
+#include <gtk/gtk.h>
+
+#include "ephy-web-view.h"
+
+G_BEGIN_DECLS
+
+#define EPHY_TYPE_TITLE_DOMAIN_BOX (ephy_title_domain_box_get_type ())
+#define EPHY_TITLE_DOMAIN_BOX(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EPHY_TYPE_TITLE_DOMAIN_BOX, EphyTitleDomainBox))
+#define EPHY_TITLE_DOMAIN_BOX_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), EPHY_TYPE_TITLE_DOMAIN_BOX, EphyTitleDomainBoxClass))
+#define EPHY_IS_TITLE_DOMAIN_BOX(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EPHY_TYPE_TITLE_DOMAIN_BOX))
+#define EPHY_IS_TITLE_DOMAIN_BOX_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), EPHY_TYPE_TITLE_DOMAIN_BOX))
+#define EPHY_TITLE_DOMAIN_BOX_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EPHY_TYPE_TITLE_DOMAIN_BOX, EphyTitleDomainBoxClass))
+
+typedef struct _EphyTitleDomainBoxClass EphyTitleDomainBoxClass;
+typedef struct _EphyTitleDomainBox EphyTitleDomainBox;
+typedef struct _EphyTitleDomainBoxPrivate EphyTitleDomainBoxPrivate;
+
+struct _EphyTitleDomainBox {
+ GtkBox parent;
+
+ /*< private >*/
+ EphyTitleDomainBoxPrivate *priv;
+};
+
+struct _EphyTitleDomainBoxClass {
+ GtkBoxClass parent_class;
+};
+
+GType ephy_title_domain_box_get_type (void);
+GtkWidget * ephy_title_domain_box_new (EphyWebView *view);
+void ephy_title_domain_box_set_view (EphyTitleDomainBox *box,
+ EphyWebView *view);
+
+G_END_DECLS
+
+#endif
diff --git a/src/ephy-toolbar.c b/src/ephy-toolbar.c
index 97a72a13d..d25f4cad6 100644
--- a/src/ephy-toolbar.c
+++ b/src/ephy-toolbar.c
@@ -21,9 +21,11 @@
#include "config.h"
#include "ephy-toolbar.h"
+#include "ephy-embed-container.h"
#include "ephy-location-entry.h"
#include "ephy-middle-clickable-button.h"
#include "ephy-private.h"
+#include "ephy-title-domain-box.h"
G_DEFINE_TYPE (EphyToolbar, ephy_toolbar, GTK_TYPE_TOOLBAR)
@@ -40,6 +42,12 @@ static GParamSpec *object_properties[N_PROPERTIES] = { NULL, };
struct _EphyToolbarPrivate {
EphyWindow *window;
GtkWidget *entry;
+ GtkWidget *title_domain;
+ GtkWidget *title_domain_tool_item;
+ GtkWidget *location_stop_reload;
+
+ EphyWebView *view;
+ gulong active_embed_tracker_id;
};
static void
@@ -78,12 +86,45 @@ ephy_toolbar_get_property (GObject *object,
}
static void
+active_embed_load_status_cb (EphyWebView *view, GParamSpec *spec, EphyToolbar *toolbar)
+{
+ WebKitLoadStatus status;
+ EphyToolbarPrivate *priv = toolbar->priv;
+
+ status = webkit_web_view_get_load_status (WEBKIT_WEB_VIEW (view));
+
+ if (status == WEBKIT_LOAD_FINISHED)
+ gtk_widget_show (priv->title_domain_tool_item);
+ else
+ gtk_widget_hide (priv->title_domain_tool_item);
+}
+
+static void
+active_child_cb (EphyWindow *window, GParamSpec *pspec, EphyToolbar *toolbar)
+{
+ EphyEmbed *embed;
+ EphyToolbarPrivate *priv = toolbar->priv;
+
+ embed = ephy_embed_container_get_active_child (EPHY_EMBED_CONTAINER (window));
+ if (embed) {
+ priv->view = ephy_embed_get_web_view (embed);
+ ephy_title_domain_box_set_view (EPHY_TITLE_DOMAIN_BOX (priv->title_domain), priv->view);
+
+ if (priv->active_embed_tracker_id)
+ g_signal_handlers_disconnect_by_func (priv->view, active_embed_load_status_cb, toolbar);
+
+ priv->active_embed_tracker_id = g_signal_connect (priv->view, "notify::load-status",
+ G_CALLBACK (active_embed_load_status_cb), toolbar);
+ }
+}
+
+static void
ephy_toolbar_constructed (GObject *object)
{
EphyToolbarPrivate *priv = EPHY_TOOLBAR (object)->priv;
GtkActionGroup *action_group;
GtkAction *action;
- GtkToolItem *back_forward, *location_stop_reload, *tool_item;
+ GtkToolItem *back_forward, *tool_item;
GtkWidget *tool_button, *box, *location, *toolbar;
GtkSizeGroup *size;
@@ -103,6 +144,7 @@ ephy_toolbar_constructed (GObject *object)
/* Back and Forward */
back_forward = gtk_tool_item_new ();
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+ gtk_widget_set_name (box, "ephy-back-forward-button-container");
/* Back */
tool_button = ephy_middle_clickable_button_new ();
@@ -121,6 +163,7 @@ ephy_toolbar_constructed (GObject *object)
/* FIXME: apparently we need an image inside the button for the action
* icon to appear. */
gtk_button_set_image (GTK_BUTTON (tool_button), gtk_image_new ());
+
action = gtk_action_group_get_action (action_group, "NavigationForward");
gtk_activatable_set_related_action (GTK_ACTIVATABLE (tool_button),
action);
@@ -138,11 +181,19 @@ ephy_toolbar_constructed (GObject *object)
gtk_widget_set_margin_right (GTK_WIDGET (back_forward), 12);
/* Location and Reload/Stop */
- location_stop_reload = gtk_tool_item_new ();
+ priv->location_stop_reload = GTK_WIDGET (gtk_tool_item_new ());
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
/* Location */
priv->entry = location = ephy_location_entry_new ();
+
+ /* Make the whole entry+reload combo visible if the entry is
+ * visible, since some parts of Epiphany set the entry visible in
+ * reaction to some event (like Ctrl+L). */
+ g_object_bind_property (priv->entry, "visible",
+ priv->location_stop_reload, "visible",
+ G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
+
gtk_box_pack_start (GTK_BOX (box), location,
TRUE, TRUE, 0);
gtk_style_context_add_class (gtk_widget_get_style_context (box),
@@ -158,20 +209,42 @@ ephy_toolbar_constructed (GObject *object)
action);
gtk_container_add (GTK_CONTAINER (box), GTK_WIDGET (tool_button));
- gtk_container_add (GTK_CONTAINER (location_stop_reload), box);
+ gtk_container_add (GTK_CONTAINER (priv->location_stop_reload), box);
gtk_container_child_set (GTK_CONTAINER (toolbar),
- GTK_WIDGET (location_stop_reload),
+ GTK_WIDGET (priv->location_stop_reload),
"expand", TRUE,
NULL);
- gtk_container_add (GTK_CONTAINER (toolbar), GTK_WIDGET (location_stop_reload));
+ gtk_container_add (GTK_CONTAINER (toolbar), GTK_WIDGET (priv->location_stop_reload));
gtk_size_group_add_widget (size, tool_button);
gtk_size_group_add_widget (size, location);
g_object_unref (size);
- gtk_widget_set_margin_right (GTK_WIDGET (location_stop_reload), 12);
- gtk_widget_show_all (GTK_WIDGET (location_stop_reload));
+ gtk_widget_set_margin_right (GTK_WIDGET (priv->location_stop_reload), 12);
+ gtk_widget_show_all (GTK_WIDGET (priv->location_stop_reload));
+
+ /* Title+domain widget. */
+ priv->title_domain_tool_item = GTK_WIDGET (gtk_tool_item_new ());
+ priv->title_domain = ephy_title_domain_box_new (NULL);
+
+ gtk_container_child_set (GTK_CONTAINER (toolbar),
+ GTK_WIDGET (priv->title_domain_tool_item),
+ "expand", TRUE,
+ NULL);
+ g_signal_connect (priv->window, "notify::active-child",
+ G_CALLBACK (active_child_cb), toolbar);
+
+ /* Add it, but don't show it, it's hidden by default. */
+ gtk_widget_show (GTK_WIDGET (priv->title_domain));
+ gtk_container_add (GTK_CONTAINER (priv->title_domain_tool_item), priv->title_domain);
+ gtk_container_add (GTK_CONTAINER (toolbar), GTK_WIDGET (priv->title_domain_tool_item));
+
+ /* If the location entry is visible the title+domain widget cannot
+ * be, and viceversa. */
+ g_object_bind_property (priv->title_domain_tool_item, "visible",
+ priv->location_stop_reload, "visible",
+ G_BINDING_SYNC_CREATE | G_BINDING_INVERT_BOOLEAN | G_BINDING_BIDIRECTIONAL);
/* Page Menu */
tool_item = gtk_tool_item_new ();
@@ -189,10 +262,24 @@ ephy_toolbar_constructed (GObject *object)
}
static void
+ephy_toolbar_dispose (GObject *object)
+{
+ EphyToolbarPrivate *priv = EPHY_TOOLBAR (object)->priv;
+
+ if (priv->active_embed_tracker_id) {
+ g_signal_handlers_disconnect_by_func (priv->view, active_embed_load_status_cb, object);
+ priv->active_embed_tracker_id = 0;
+ }
+
+ G_OBJECT_CLASS (ephy_toolbar_parent_class)->dispose (object);
+}
+
+static void
ephy_toolbar_class_init (EphyToolbarClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->dispose = ephy_toolbar_dispose;
gobject_class->set_property = ephy_toolbar_set_property;
gobject_class->get_property = ephy_toolbar_get_property;
gobject_class->constructed = ephy_toolbar_constructed;
diff --git a/src/ephy-window.c b/src/ephy-window.c
index 3e1cf4773..86d01a443 100644
--- a/src/ephy-window.c
+++ b/src/ephy-window.c
@@ -3751,6 +3751,7 @@ _ephy_window_activate_location (EphyWindow *window)
gboolean visible;
entry = ephy_toolbar_get_location_entry (EPHY_TOOLBAR (priv->toolbar));
+ gtk_widget_show (entry);
g_object_get (G_OBJECT (priv->toolbar), "visible", &visible, NULL);
if (visible == FALSE)
diff --git a/src/resources/epiphany.css b/src/resources/epiphany.css
index 113856f42..a623b3ece 100644
--- a/src/resources/epiphany.css
+++ b/src/resources/epiphany.css
@@ -14,6 +14,10 @@
padding: 0;
}
+#ephy-back-forward-button-container GtkButton {
+ padding: 6px;
+}
+
.primary-toolbar.toolbar {
padding-left: 0;
padding-right: 0;