aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXan Lopez <xan@igalia.com>2011-12-05 05:28:50 +0800
committerXan Lopez <xan@igalia.com>2011-12-05 05:31:25 +0800
commitebbb1c48197f53b98575b0cb4f6d9fa1e4535abc (patch)
tree014667c6bba38b679e9874ddc356286f449dcd88
parentd5216f2d4cebd894c79d124d583304fd044fa96a (diff)
downloadgsoc2013-epiphany-ebbb1c48197f53b98575b0cb4f6d9fa1e4535abc.tar
gsoc2013-epiphany-ebbb1c48197f53b98575b0cb4f6d9fa1e4535abc.tar.gz
gsoc2013-epiphany-ebbb1c48197f53b98575b0cb4f6d9fa1e4535abc.tar.bz2
gsoc2013-epiphany-ebbb1c48197f53b98575b0cb4f6d9fa1e4535abc.tar.lz
gsoc2013-epiphany-ebbb1c48197f53b98575b0cb4f6d9fa1e4535abc.tar.xz
gsoc2013-epiphany-ebbb1c48197f53b98575b0cb4f6d9fa1e4535abc.tar.zst
gsoc2013-epiphany-ebbb1c48197f53b98575b0cb4f6d9fa1e4535abc.zip
Remove history dropdown menus from action buttons
They are not commonly used and are not present in the new design, so we can get rid of them.
-rw-r--r--src/ephy-navigation-action.c138
-rw-r--r--src/ephy-navigation-action.h7
-rw-r--r--src/ephy-navigation-history-action.c202
-rw-r--r--src/ephy-navigation-up-action.c73
-rw-r--r--src/ephy-toolbar.c12
5 files changed, 2 insertions, 430 deletions
diff --git a/src/ephy-navigation-action.c b/src/ephy-navigation-action.c
index b4055393e..ed544430b 100644
--- a/src/ephy-navigation-action.c
+++ b/src/ephy-navigation-action.c
@@ -3,7 +3,7 @@
* Copyright © 2003, 2004 Marco Pesenti Gritti
* Copyright © 2003, 2004 Christian Persch
* Copyright © 2008 Jan Alonzo
- * Copyright © 2009 Igalia S.L.
+ * Copyright © 2009, 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
@@ -24,31 +24,20 @@
#include "config.h"
#include "ephy-navigation-action.h"
-#include "ephy-debug.h"
-#include "ephy-embed-shell.h"
-#include "ephy-favicon-cache.h"
-#include "ephy-history.h"
-#include "ephy-link.h"
-#include "ephy-shell.h"
-#include "ephy-type-builtins.h"
#include "ephy-window.h"
#include <gtk/gtk.h>
-#include <webkit/webkit.h>
#define EPHY_NAVIGATION_ACTION_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_NAVIGATION_ACTION, EphyNavigationActionPrivate))
struct _EphyNavigationActionPrivate
{
EphyWindow *window;
- char *arrow_tooltip;
- guint statusbar_cid;
};
enum
{
PROP_0,
- PROP_ARROW_TOOLTIP,
PROP_WINDOW
};
@@ -57,54 +46,6 @@ static void ephy_navigation_action_class_init (EphyNavigationActionClass *class)
G_DEFINE_TYPE (EphyNavigationAction, ephy_navigation_action, EPHY_TYPE_LINK_ACTION)
-
-#define MAX_LABEL_LENGTH 48
-
-static GtkWidget *
-build_dropdown_menu (EphyNavigationAction *action)
-{
- EphyNavigationActionClass *class = EPHY_NAVIGATION_ACTION_GET_CLASS (action);
-
- return class->build_dropdown_menu (action);
-}
-
-static void
-menu_activated_cb (GtkMenuToolButton *button,
- EphyNavigationAction *action)
-{
- GtkWidget *menu = NULL;
-
- LOG ("menu_activated_cb");
-
- menu = build_dropdown_menu (action);
- gtk_menu_tool_button_set_menu (button, menu);
-}
-
-static void
-connect_proxy (GtkAction *gaction,
- GtkWidget *proxy)
-{
- LOG ("Connect navigation action proxy");
-
- if (GTK_IS_MENU_TOOL_BUTTON (proxy))
- {
- EphyNavigationAction *action = EPHY_NAVIGATION_ACTION (gaction);
- EphyNavigationActionPrivate *priv = action->priv;
- GtkMenuToolButton *button = GTK_MENU_TOOL_BUTTON (proxy);
- GtkWidget *menu;
-
- /* set dummy menu so the arrow gets sensitive */
- menu = gtk_menu_new ();
- gtk_menu_tool_button_set_menu (button, menu);
- gtk_menu_tool_button_set_arrow_tooltip_text (button, priv->arrow_tooltip);
-
- g_signal_connect (proxy, "show-menu",
- G_CALLBACK (menu_activated_cb), gaction);
- }
-
- GTK_ACTION_CLASS (ephy_navigation_action_parent_class)->connect_proxy (gaction, proxy);
-}
-
static void
ephy_navigation_action_init (EphyNavigationAction *action)
{
@@ -112,16 +53,6 @@ ephy_navigation_action_init (EphyNavigationAction *action)
}
static void
-ephy_navigation_action_finalize (GObject *object)
-{
- EphyNavigationAction *action = EPHY_NAVIGATION_ACTION (object);
-
- g_free (action->priv->arrow_tooltip);
-
- G_OBJECT_CLASS (ephy_navigation_action_parent_class)->finalize (object);
-}
-
-static void
ephy_navigation_action_set_property (GObject *object,
guint prop_id,
const GValue *value,
@@ -131,10 +62,6 @@ ephy_navigation_action_set_property (GObject *object,
switch (prop_id)
{
- case PROP_ARROW_TOOLTIP:
- nav->priv->arrow_tooltip = g_value_dup_string (value);
- g_object_notify (object, "tooltip");
- break;
case PROP_WINDOW:
nav->priv->window = EPHY_WINDOW (g_value_get_object (value));
break;
@@ -151,9 +78,6 @@ ephy_navigation_action_get_property (GObject *object,
switch (prop_id)
{
- case PROP_ARROW_TOOLTIP:
- g_value_set_string (value, nav->priv->arrow_tooltip);
- break;
case PROP_WINDOW:
g_value_set_object (value, nav->priv->window);
break;
@@ -166,20 +90,10 @@ ephy_navigation_action_class_init (EphyNavigationActionClass *class)
GObjectClass *object_class = G_OBJECT_CLASS (class);
GtkActionClass *action_class = GTK_ACTION_CLASS (class);
- object_class->finalize = ephy_navigation_action_finalize;
object_class->set_property = ephy_navigation_action_set_property;
object_class->get_property = ephy_navigation_action_get_property;
- action_class->toolbar_item_type = GTK_TYPE_MENU_TOOL_BUTTON;
- action_class->connect_proxy = connect_proxy;
-
- class->build_dropdown_menu = NULL;
-
- g_object_class_install_property (object_class,
- PROP_ARROW_TOOLTIP,
- g_param_spec_string ("arrow-tooltip", NULL, NULL,
- NULL,
- G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
+ action_class->toolbar_item_type = GTK_TYPE_TOOL_BUTTON;
g_object_class_install_property (object_class,
PROP_WINDOW,
@@ -197,51 +111,3 @@ _ephy_navigation_action_get_window (EphyNavigationAction *action)
return action->priv->window;
}
-
-guint
-_ephy_navigation_action_get_statusbar_context_id (EphyNavigationAction *action)
-{
- g_return_val_if_fail (EPHY_IS_NAVIGATION_ACTION (action), 0);
-
- return action->priv->statusbar_cid;
-}
-
-GtkWidget *
-_ephy_navigation_action_new_history_menu_item (const char *origtext,
- const char *address)
-{
- EphyFaviconCache *cache;
- EphyHistory *history;
- GtkWidget *item, *image;
- GdkPixbuf *icon = NULL;
- GtkLabel *label;
- const char *icon_address;
-
- g_return_val_if_fail (address != NULL && origtext != NULL, NULL);
-
- item = gtk_image_menu_item_new_with_label (origtext);
-
- label = GTK_LABEL (gtk_bin_get_child (GTK_BIN (item)));
- gtk_label_set_ellipsize (label, PANGO_ELLIPSIZE_END);
- gtk_label_set_max_width_chars (label, MAX_LABEL_LENGTH);
-
- history = EPHY_HISTORY
- (ephy_embed_shell_get_global_history (embed_shell));
- icon_address = ephy_history_get_icon (history, address);
-
- cache = EPHY_FAVICON_CACHE
- (ephy_embed_shell_get_favicon_cache (embed_shell));
- icon = ephy_favicon_cache_get (cache, icon_address);
-
- if (icon != NULL)
- {
- image = gtk_image_new_from_pixbuf (icon);
- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
- gtk_widget_show (image);
- g_object_unref (icon);
- }
-
- gtk_widget_show (item);
-
- return item;
-}
diff --git a/src/ephy-navigation-action.h b/src/ephy-navigation-action.h
index d3f3cbfc4..30c4b17b3 100644
--- a/src/ephy-navigation-action.h
+++ b/src/ephy-navigation-action.h
@@ -52,9 +52,6 @@ struct _EphyNavigationAction
struct _EphyNavigationActionClass
{
EphyLinkActionClass parent_class;
-
- /*< virtual >*/
- GtkWidget *(*build_dropdown_menu) (EphyNavigationAction *action);
};
GType ephy_navigation_action_get_type (void);
@@ -63,10 +60,6 @@ GType ephy_navigation_action_get_type (void);
EphyWindow *_ephy_navigation_action_get_window (EphyNavigationAction *action);
-guint _ephy_navigation_action_get_statusbar_context_id (EphyNavigationAction *action);
-
-GtkWidget *_ephy_navigation_action_new_history_menu_item (const char *origtext,
- const char *address);
G_END_DECLS
#endif
diff --git a/src/ephy-navigation-history-action.c b/src/ephy-navigation-history-action.c
index 23aa874d5..daf98ad5e 100644
--- a/src/ephy-navigation-history-action.c
+++ b/src/ephy-navigation-history-action.c
@@ -66,211 +66,12 @@ static void ephy_navigation_history_action_class_init (EphyNavigationHistoryActi
G_DEFINE_TYPE (EphyNavigationHistoryAction, ephy_navigation_history_action, EPHY_TYPE_NAVIGATION_ACTION)
static void
-set_new_back_history (EphyEmbed *source, EphyEmbed *dest, gint offset)
-{
- WebKitWebView *source_view, *dest_view;
- WebKitWebBackForwardList* source_list, *dest_list;
- WebKitWebHistoryItem *item;
- GList *items;
- guint limit;
- guint i;
-
- g_return_if_fail (EPHY_IS_EMBED (source));
- g_return_if_fail (EPHY_IS_EMBED (dest));
-
- source_view = EPHY_GET_WEBKIT_WEB_VIEW_FROM_EMBED (source);
- dest_view = EPHY_GET_WEBKIT_WEB_VIEW_FROM_EMBED (dest);
-
- source_list = webkit_web_view_get_back_forward_list (source_view);
- dest_list = webkit_web_view_get_back_forward_list (dest_view);
-
- if (offset >= 0) {
- /* Copy the whole back history in this case (positive offset) */
- ephy_web_view_copy_back_history (ephy_embed_get_web_view (source),
- ephy_embed_get_web_view (dest));
-
- items = webkit_web_back_forward_list_get_forward_list_with_limit (source_list,
- EPHY_WEBKIT_BACK_FORWARD_LIMIT);
- limit = offset - 1;
- } else {
- items = webkit_web_back_forward_list_get_back_list_with_limit (source_list,
- EPHY_WEBKIT_BACK_FORWARD_LIMIT);
- limit = g_list_length (items) + offset;
- }
-
- /* Add the remaining items to the BackForward list */
- items = g_list_reverse (items);
- for (i = 0; i < limit; i++) {
- item = webkit_web_history_item_copy ((WebKitWebHistoryItem*)items->data);
- webkit_web_back_forward_list_add_item (dest_list, item);
- g_object_unref (item);
-
- items = items->next;
- }
- g_list_free (items);
-}
-
-static void
-middle_click_handle_on_history_menu_item (EphyNavigationHistoryAction *action,
- EphyEmbed *embed,
- WebKitWebHistoryItem *item)
-{
- EphyEmbed *new_embed = NULL;
- WebKitWebView *web_view;
- WebKitWebBackForwardList *history;
- GList *list;
- const gchar *url;
- guint current;
- gint offset;
-
- web_view = EPHY_GET_WEBKIT_WEB_VIEW_FROM_EMBED (embed);
-
- /* Save old history and item's offset from current */
- history = webkit_web_view_get_back_forward_list (web_view);
- if (action->priv->direction == EPHY_NAVIGATION_HISTORY_DIRECTION_BACK) {
- list = webkit_web_back_forward_list_get_back_list_with_limit (history,
- EPHY_WEBKIT_BACK_FORWARD_LIMIT);
- current = -1;
- } else {
- list = webkit_web_back_forward_list_get_forward_list_with_limit (history,
- EPHY_WEBKIT_BACK_FORWARD_LIMIT);
- current = g_list_length (list);
- }
- offset = current - g_list_index (list, item);
-
- new_embed = ephy_shell_new_tab (ephy_shell_get_default (),
- EPHY_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (embed))),
- embed,
- NULL,
- EPHY_NEW_TAB_IN_EXISTING_WINDOW |
- EPHY_NEW_TAB_DONT_COPY_HISTORY);
- g_return_if_fail (new_embed != NULL);
-
- /* We manually set the back history instead of trusting
- ephy_shell_new_tab because the logic is more complex than
- usual, due to handling also the forward history */
- set_new_back_history (embed, new_embed, offset);
-
- /* Load the new URL */
- url = webkit_web_history_item_get_original_uri (item);
- ephy_web_view_load_url (ephy_embed_get_web_view (new_embed), url);
-}
-
-static void
-activate_back_or_forward_menu_item_cb (GtkWidget *menuitem,
- EphyNavigationHistoryAction *action)
-{
- WebKitWebHistoryItem *item;
- EphyWindow *window;
- EphyEmbed *embed;
-
- window = _ephy_navigation_action_get_window (EPHY_NAVIGATION_ACTION (action));
- embed = ephy_embed_container_get_active_child (EPHY_EMBED_CONTAINER (window));
- g_return_if_fail (embed != NULL);
-
- item = (WebKitWebHistoryItem*)g_object_get_data (G_OBJECT (menuitem), HISTORY_ITEM_DATA_KEY);
- g_return_if_fail (item != NULL);
-
- if (ephy_gui_is_middle_click ()) {
- middle_click_handle_on_history_menu_item (action, embed, item);
- } else {
- WebKitWebView *web_view;
-
- web_view = EPHY_GET_WEBKIT_WEB_VIEW_FROM_EMBED (embed);
- webkit_web_view_go_to_back_forward_item (web_view, item);
- }
-}
-
-static void
ephy_history_cleared_cb (EphyHistory *history,
EphyNavigationHistoryAction *action)
{
ephy_action_change_sensitivity_flags (GTK_ACTION (action), SENS_FLAG, TRUE);
}
-static GList*
-webkit_construct_history_list (WebKitWebView *web_view, WebKitHistoryType hist_type)
-{
- WebKitWebBackForwardList *web_back_forward_list;
- GList *webkit_items;
-
- web_back_forward_list = webkit_web_view_get_back_forward_list (web_view);
-
- if (hist_type == WEBKIT_HISTORY_FORWARD) {
- webkit_items =
- g_list_reverse (webkit_web_back_forward_list_get_forward_list_with_limit (web_back_forward_list,
- EPHY_WEBKIT_BACK_FORWARD_LIMIT));
- } else {
- webkit_items =
- webkit_web_back_forward_list_get_back_list_with_limit (web_back_forward_list,
- EPHY_WEBKIT_BACK_FORWARD_LIMIT);
- }
-
- return webkit_items;
-}
-
-static GtkWidget *
-build_dropdown_menu (EphyNavigationAction *nav_action)
-{
- EphyNavigationHistoryAction *action;
- EphyWindow *window;
- GtkMenuShell *menu;
- EphyEmbed *embed;
- GList *list, *l;
- WebKitWebView *web_view;
-
- action = EPHY_NAVIGATION_HISTORY_ACTION (nav_action);
- window = _ephy_navigation_action_get_window (nav_action);
- embed = ephy_embed_container_get_active_child (EPHY_EMBED_CONTAINER (window));
- g_return_val_if_fail (embed != NULL, NULL);
-
- menu = GTK_MENU_SHELL (gtk_menu_new ());
-
- web_view = EPHY_GET_WEBKIT_WEB_VIEW_FROM_EMBED (embed);
- g_return_val_if_fail (web_view != NULL, NULL);
-
- if (action->priv->direction == EPHY_NAVIGATION_HISTORY_DIRECTION_BACK) {
- list = webkit_construct_history_list (web_view,
- WEBKIT_HISTORY_BACKWARD);
- } else {
- list = webkit_construct_history_list (web_view,
- WEBKIT_HISTORY_FORWARD);
- }
-
- for (l = list; l != NULL; l = l->next) {
- GtkWidget *item;
- WebKitWebHistoryItem *hitem;
- const char *url;
- char *title;
-
- hitem = (WebKitWebHistoryItem*)l->data;
- url = webkit_web_history_item_get_uri (hitem);
-
- title = g_strdup (webkit_web_history_item_get_title (hitem));
-
- if ((title == NULL || g_strstrip (title)[0] == '\0'))
- item = _ephy_navigation_action_new_history_menu_item (url, url);
- else
- item = _ephy_navigation_action_new_history_menu_item (title, url);
-
- g_free (title);
-
- g_object_set_data_full (G_OBJECT (item), HISTORY_ITEM_DATA_KEY,
- g_object_ref (hitem), g_object_unref);
-
- g_signal_connect (item, "activate",
- G_CALLBACK (activate_back_or_forward_menu_item_cb),
- action);
-
- gtk_menu_shell_append (menu, item);
- gtk_widget_show_all (item);
- }
-
- g_list_free (list);
-
- return GTK_WIDGET (menu);
-}
-
static void
action_activate (GtkAction *action)
{
@@ -393,7 +194,6 @@ ephy_navigation_history_action_class_init (EphyNavigationHistoryActionClass *kla
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkActionClass *action_class = GTK_ACTION_CLASS (klass);
- EphyNavigationActionClass *nav_action_class = EPHY_NAVIGATION_ACTION_CLASS (klass);
object_class->finalize = ephy_navigation_history_action_finalize;
object_class->set_property = ephy_navigation_history_action_set_property;
@@ -401,8 +201,6 @@ ephy_navigation_history_action_class_init (EphyNavigationHistoryActionClass *kla
action_class->activate = action_activate;
- nav_action_class->build_dropdown_menu = build_dropdown_menu;
-
g_object_class_install_property (object_class,
PROP_DIRECTION,
g_param_spec_int ("direction", NULL, NULL,
diff --git a/src/ephy-navigation-up-action.c b/src/ephy-navigation-up-action.c
index 1c5a7cd0c..9d3f78dd0 100644
--- a/src/ephy-navigation-up-action.c
+++ b/src/ephy-navigation-up-action.c
@@ -45,77 +45,6 @@ static void ephy_navigation_up_action_class_init (EphyNavigationUpActionClass *k
G_DEFINE_TYPE (EphyNavigationUpAction, ephy_navigation_up_action, EPHY_TYPE_NAVIGATION_ACTION)
static void
-activate_up_menu_item_cb (GtkWidget *menuitem,
- EphyNavigationUpAction *action)
-{
- EphyWindow *window;
- EphyEmbed *embed;
- char *url;
-
- window = _ephy_navigation_action_get_window (EPHY_NAVIGATION_ACTION (action));
- embed = ephy_embed_container_get_active_child (EPHY_EMBED_CONTAINER (window));
- g_return_if_fail (embed != NULL);
-
- url = g_object_get_data (G_OBJECT (menuitem), URL_DATA_KEY);
- g_return_if_fail (url != NULL);
-
- ephy_link_open (EPHY_LINK (action), url, NULL,
- ephy_gui_is_middle_click () ? EPHY_LINK_NEW_TAB : 0);
-}
-
-static GtkWidget *
-build_dropdown_menu (EphyNavigationAction *nav_action)
-{
- EphyNavigationUpAction *action;
- EphyWindow *window;
- EphyEmbed *embed;
- EphyHistory *history;
- GtkMenuShell *menu;
- GtkWidget *item;
- GSList *list, *l;
- char *url;
-
- action = EPHY_NAVIGATION_UP_ACTION (nav_action);
- window = _ephy_navigation_action_get_window (nav_action);
- embed = ephy_embed_container_get_active_child (EPHY_EMBED_CONTAINER (window));
- g_return_val_if_fail (embed != NULL, NULL);
-
- menu = GTK_MENU_SHELL (gtk_menu_new ());
- history = EPHY_HISTORY (ephy_embed_shell_get_global_history (embed_shell));
-
- list = ephy_web_view_get_go_up_list (ephy_embed_get_web_view (embed));
- for (l = list; l != NULL; l = l->next) {
- EphyNode *node;
- const char *title = NULL;
-
- url = g_strdup (l->data);
-
- if (url == NULL) continue;
-
- node = ephy_history_get_page (history, url);
- if (node != NULL) {
- title = ephy_node_get_property_string (node, EPHY_NODE_PAGE_PROP_TITLE);
- }
-
- item = _ephy_navigation_action_new_history_menu_item (title ? title : url, url);
-
- g_object_set_data_full (G_OBJECT (item), URL_DATA_KEY, url,
- (GDestroyNotify) g_free);
- g_signal_connect (item, "activate",
- G_CALLBACK (activate_up_menu_item_cb), action);
-
- gtk_menu_shell_append (menu, item);
- gtk_widget_show (item);
- }
-
- /* the list data has been consumed */
- g_slist_foreach (list, (GFunc) g_free, NULL);
- g_slist_free (list);
-
- return GTK_WIDGET (menu);
-}
-
-static void
action_activate (GtkAction *action)
{
EphyWindow *window;
@@ -144,8 +73,6 @@ static void
ephy_navigation_up_action_class_init (EphyNavigationUpActionClass *klass)
{
GtkActionClass *action_class = GTK_ACTION_CLASS (klass);
- EphyNavigationActionClass *nav_action_class = EPHY_NAVIGATION_ACTION_CLASS (klass);
action_class->activate = action_activate;
- nav_action_class->build_dropdown_menu = build_dropdown_menu;
}
diff --git a/src/ephy-toolbar.c b/src/ephy-toolbar.c
index ed67a70f9..7fed22bdd 100644
--- a/src/ephy-toolbar.c
+++ b/src/ephy-toolbar.c
@@ -217,10 +217,6 @@ ephy_toolbar_set_window (EphyToolbar *toolbar,
"label", _("_Back"),
"stock_id", GTK_STOCK_GO_BACK,
"tooltip", _("Go to the previous visited page"),
- /* this is the tooltip on the Back button's drop-down arrow, which will show
- * a menu with all sites you can go 'back' to
- */
- "arrow-tooltip", _("Back history"),
"window", priv->window,
"direction", EPHY_NAVIGATION_HISTORY_DIRECTION_BACK,
"is_important", TRUE,
@@ -237,10 +233,6 @@ ephy_toolbar_set_window (EphyToolbar *toolbar,
"label", _("_Forward"),
"stock_id", GTK_STOCK_GO_FORWARD,
"tooltip", _("Go to the next visited page"),
- /* this is the tooltip on the Forward button's drop-down arrow, which will show
- * a menu with all sites you can go 'forward' to
- */
- "arrow-tooltip", _("Forward history"),
"window", priv->window,
"direction", EPHY_NAVIGATION_HISTORY_DIRECTION_FORWARD,
NULL);
@@ -256,10 +248,6 @@ ephy_toolbar_set_window (EphyToolbar *toolbar,
"label", _("_Up"),
"stock_id", GTK_STOCK_GO_UP,
"tooltip", _("Go up one level"),
- /* this is the tooltip on the Up button's drop-down arrow, which will show
- * a menu with al sites you can go 'up' to
- */
- "arrow-tooltip", _("List of upper levels"),
"window", priv->window,
NULL);
g_signal_connect_swapped (action, "open-link",