/*
* Copyright (C) 2000, 2001, 2002 Marco Pesenti Gritti
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "ephy-shell.h"
#include "ephy-state.h"
#include "ephy-embed-shell.h"
#include "eel-gconf-extensions.h"
#include "ephy-prefs.h"
#include "ephy-favicon-cache.h"
#include "ephy-stock-icons.h"
#include "ephy-window.h"
#include "ephy-file-helpers.h"
#include "ephy-thread-helpers.h"
#include "ephy-bookmarks-import.h"
#include "ephy-bookmarks-editor.h"
#include "ephy-history-window.h"
#include "ephy-debug.h"
#include "toolbar.h"
#include <string.h>
#include <libgnomeui/gnome-client.h>
#include <bonobo/bonobo-main.h>
#include <bonobo/bonobo-i18n.h>
#include <gtk/gtksignal.h>
#include <gtk/gtkmain.h>
#include <gtk/gtkmessagedialog.h>
#ifdef ENABLE_NAUTILUS_VIEW
#include <bonobo/bonobo-generic-factory.h>
#include "ephy-nautilus-view.h"
#define EPHY_NAUTILUS_VIEW_OAFIID "OAFIID:GNOME_Epiphany_NautilusViewFactory"
#endif
struct EphyShellPrivate
{
Session *session;
EphyAutocompletion *autocompletion;
EphyBookmarks *bookmarks;
EphyToolbarsModel *toolbars_model;
GtkWidget *bme;
GtkWidget *history_window;
};
enum
{
STARTPAGE_HOME,
STARTPAGE_LAST,
STARTPAGE_BLANK,
};
static void
ephy_shell_class_init (EphyShellClass *klass);
static void
ephy_shell_init (EphyShell *gs);
static void
ephy_shell_finalize (GObject *object);
static void
ephy_init_services (EphyShell *gs);
#ifdef ENABLE_NAUTILUS_VIEW
static void
ephy_nautilus_view_init_factory (EphyShell *gs);
static BonoboObject *
ephy_nautilus_view_new (BonoboGenericFactory *factory,
const char *id,
EphyShell *gs);
#endif
static GObjectClass *parent_class = NULL;
EphyShell *ephy_shell;
GType
ephy_shell_get_type (void)
{
static GType ephy_shell_type = 0;
if (ephy_shell_type == 0)
{
static const GTypeInfo our_info =
{
sizeof (EphyShellClass),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) ephy_shell_class_init,
NULL,
NULL, /* class_data */
sizeof (EphyShell),
0, /* n_preallocs */
(GInstanceInitFunc) ephy_shell_init
};
ephy_shell_type = g_type_register_static (EPHY_EMBED_SHELL_TYPE,
"EphyShell",
&our_info, 0);
}
return ephy_shell_type;
}
static void
ephy_shell_class_init (EphyShellClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
parent_class = g_type_class_peek_parent (klass);
object_class->finalize = ephy_shell_finalize;
}
static void
ephy_shell_command_cb (EphyEmbedShell *shell,
char *command,
char *param,
gpointer data)
{
EphyBookmarks *bookmarks;
GtkWidget *dialog;
const gchar *message = NULL;
GtkMessageType message_type = GTK_MESSAGE_INFO;
EphyWindow *window;
bookmarks = ephy_shell_get_bookmarks (EPHY_SHELL (shell));
if (strcmp (command, "import-mozilla-bookmarks") == 0)
{
if (ephy_bookmarks_import_mozilla (bookmarks, param))
{
message_type = GTK_MESSAGE_INFO;
message = _("Mozilla bookmarks imported successfully.");
}
else
{
message_type = GTK_MESSAGE_ERROR;
message = _("Importing Mozilla bookmarks failed.");
}
}
else if (strcmp (command, "import-galeon-bookmarks") == 0)
{
if (ephy_bookmarks_import_xbel (bookmarks, param,
_("Galeon")))
{
message_type = GTK_MESSAGE_INFO;
message = _("Galeon bookmarks imported successfully.");
}
else
{
message_type = GTK_MESSAGE_ERROR;
message = _("Importing Galeon bookmarks failed.");
}
}
else if (strcmp (command, "import-konqueror-bookmarks") == 0)
{
if (ephy_bookmarks_import_xbel (bookmarks, param,
_("Konqueror")))
{
message_type = GTK_MESSAGE_INFO;
message = _("Konqueror bookmarks imported successfully.");
}
else
{
message_type = GTK_MESSAGE_ERROR;
message = _("Importing Konqueror bookmarks failed.");
}
}
else if (strcmp (command, "configure-network") == 0)
{
ephy_file_launch_application ("gnome-network-preferences",
NULL,
FALSE);
}
if (message != NULL)
{
window = ephy_shell_get_active_window (EPHY_SHELL (shell));
dialog = gtk_message_dialog_new (GTK_WINDOW (window),
GTK_DIALOG_DESTROY_WITH_PARENT,
message_type,
GTK_BUTTONS_OK,
message);
gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
g_signal_connect_swapped (G_OBJECT (dialog), "response",
G_CALLBACK (gtk_widget_destroy),
G_OBJECT (dialog));
gtk_widget_show (dialog);
}
}
static void
ephy_shell_new_window_cb (EphyEmbedShell *shell,
EphyEmbed **new_embed,
EmbedChromeMask chromemask,
gpointer data)
{
EphyTab *new_tab;
EphyWindow *window;
gboolean open_in_tab;
g_assert (new_embed != NULL);
open_in_tab = (chromemask & EMBED_CHROME_OPENASCHROME) ?
FALSE :
eel_gconf_get_boolean (CONF_TABS_TABBED_POPUPS);
if (open_in_tab)
{
window = ephy_shell_get_active_window (ephy_shell);
}
else
{
window = ephy_window_new ();
ephy_window_set_chrome (window, chromemask);
}
new_tab = ephy_tab_new ();
ephy_window_add_tab (window, new_tab, EPHY_NOTEBOOK_INSERT_GROUPED, FALSE);
*new_embed = ephy_tab_get_embed (new_tab);
}
static void
ephy_shell_init (EphyShell *gs)
{
EphyEmbedSingle *single;
gs->priv = g_new0 (EphyShellPrivate, 1);
gs->priv->session = NULL;
gs->priv->bookmarks = NULL;
gs->priv->bme = NULL;
gs->priv->history_window = NULL;
gs->priv->toolbars_model = NULL;
ephy_shell = gs;
g_object_add_weak_pointer (G_OBJECT(ephy_shell),
(gpointer *)&ephy_shell);
ephy_debug_init ();
ephy_thread_helpers_init ();
ephy_node_system_init (EPHY_NODE_RESERVED_IDS);
ephy_file_helpers_init ();
ephy_stock_icons_init ();
ephy_ensure_dir_exists (ephy_dot_dir ());
/* This ensures mozilla is fired up */
single = ephy_embed_shell_get_embed_single (EPHY_EMBED_SHELL (gs));
g_signal_connect (G_OBJECT (single),
"new_window_orphan",
G_CALLBACK(ephy_shell_new_window_cb),
NULL);
g_signal_connect (G_OBJECT (gs),
"command",
G_CALLBACK(ephy_shell_command_cb),
NULL);
ephy_init_services (gs);
}
static void
save_toolbars (EggToolbarsModel *model)
{
char *xml_file;
xml_file = g_build_filename (ephy_dot_dir (),
"ephy-toolbar.xml",
NULL);
egg_toolbars_model_save (model, xml_file);
g_free (xml_file);
}
static void
ephy_shell_finalize (GObject *object)
{
EphyShell *gs;
g_return_if_fail (object != NULL);
g_return_if_fail (IS_EPHY_SHELL (object));
gs = EPHY_SHELL (object);
g_return_if_fail (gs->priv != NULL);
g_assert (ephy_shell == NULL);
LOG ("Unref toolbars model")
if (gs->priv->toolbars_model)
{
save_toolbars (EGG_TOOLBARS_MODEL (gs->priv->toolbars_model));
g_object_unref (G_OBJECT (gs->priv->toolbars_model));
}
LOG ("Unref session")
if (gs->priv->session)
{
g_return_if_fail (IS_SESSION(gs->priv->session));
g_object_remove_weak_pointer
(G_OBJECT(gs->priv->session),
(gpointer *)&gs->priv->session);
g_object_unref (G_OBJECT (gs->priv->session));
}
LOG ("Unref autocompletion")
if (gs->priv->autocompletion)
{
g_object_unref (gs->priv->autocompletion);
}
LOG ("Unref Bookmarks Editor");
if (gs->priv->bme)
{
gtk_widget_destroy (GTK_WIDGET (gs->priv->bme));
}
LOG ("Unref History Window");
if (gs->priv->history_window)
{
gtk_widget_destroy (GTK_WIDGET (gs->priv->history_window));
}
LOG ("Unref bookmarks")
if (gs->priv->bookmarks)
{
g_object_unref (gs->priv->bookmarks);
}
G_OBJECT_CLASS (parent_class)->finalize (object);
g_free (gs->priv);
ephy_state_save ();
ephy_file_helpers_shutdown ();
ephy_node_system_shutdown ();
LOG ("Ephy shell finalized")
bonobo_main_quit ();
LOG ("Bonobo quit done")
}
EphyShell *
ephy_shell_new (void)
{
return EPHY_SHELL (g_object_new (EPHY_SHELL_TYPE, NULL));
}
static void
ephy_init_services (EphyShell *gs)
{
/* preload the prefs */
/* it also enables notifiers support */
eel_gconf_monitor_add ("/apps/epiphany");
eel_gconf_monitor_add ("/apps/nautilus/preferences");
eel_gconf_monitor_add ("/system/proxy");
#ifdef ENABLE_NAUTILUS_VIEW
ephy_nautilus_view_init_factory (gs);
#endif
}
static char *
build_homepage_url (EphyShell *gs,
EphyEmbed *previous_embed)
{
const gchar *last_page_url;
gchar *home_page_url;
gint page_type;
EphyHistory *gh;
char *result = NULL;
if (previous_embed == NULL)
{
page_type = STARTPAGE_HOME;
}
else
{
page_type = eel_gconf_get_integer (CONF_GENERAL_NEWPAGE_TYPE);
}
/* return the appropriate page */
if (page_type == STARTPAGE_HOME)
{
/* get location of home page */
home_page_url = eel_gconf_get_string(CONF_GENERAL_HOMEPAGE);
result = home_page_url;
}
else if (page_type == STARTPAGE_LAST)
{
if (previous_embed != NULL)
{
ephy_embed_get_location (previous_embed,
TRUE,
&result);
}
if (result == NULL)
{
/* get location of last page */
gh = ephy_embed_shell_get_global_history
(EPHY_EMBED_SHELL (gs));
last_page_url = ephy_history_get_last_page (gh);
result = g_strdup (last_page_url);
}
}
if (result == NULL)
{
/* even in case of error, it's a good default */
result = g_strdup ("about:blank");
}
return result;
}
/**
* ephy_shell_get_active_window:
* @gs: a #EphyShell
*
* Get the current active window. Use it when you
* need to take an action (like opening an url) on
* a window but you dont have a target window.
* Ex. open a new tab from command line.
*
* Return value: the current active window
**/
EphyWindow *
ephy_shell_get_active_window (EphyShell *gs)
{
Session *session;
const GList *windows;
session = ephy_shell_get_session (gs);
windows = session_get_windows (session);
if (windows == NULL) return NULL;
return EPHY_WINDOW(windows->data);
}
/**
* ephy_shell_new_tab:
* @shell: a #EphyShell
* @parent_window: the target #EphyWindow or %NULL
* @previous_tab: the referrer tab or %NULL
* @url: an url to load or %NULL
*
* Create a new tab and the parent window when necessary.
* Ever use this function to open urls in new window/tabs.
*
* ReturnValue: the created #EphyTab
**/
EphyTab *
ephy_shell_new_tab (EphyShell *shell,
EphyWindow *parent_window,
EphyTab *previous_tab,
const char *url,
EphyNewTabFlags flags)
{
EphyWindow *window;
EphyTab *tab;
EphyEmbed *embed;
gboolean in_new_window;
gboolean grouped = FALSE;
gboolean jump_to;
EphyEmbed *previous_embed = NULL;
GtkWidget *nb;
gint position;
in_new_window = !eel_gconf_get_boolean (CONF_TABS_TABBED);
if (flags & EPHY_NEW_TAB_IN_NEW_WINDOW) in_new_window = TRUE;
if (flags & EPHY_NEW_TAB_IN_EXISTING_WINDOW) in_new_window = FALSE;
jump_to = eel_gconf_get_boolean (CONF_TABS_TABBED_AUTOJUMP);
if (flags & EPHY_NEW_TAB_JUMP) jump_to = TRUE;
if (flags & EPHY_NEW_TAB_DONT_JUMP_TO) jump_to = FALSE;
if (!in_new_window && parent_window != NULL)
{
window = parent_window;
}
else
{
window = ephy_window_new ();
}
if (previous_tab)
{
previous_embed = ephy_tab_get_embed (previous_tab);
}
if (url != NULL || flags & EPHY_NEW_TAB_IS_A_COPY ||
flags & EPHY_NEW_TAB_VIEW_SOURCE)
{
grouped = TRUE;
}
if (flags & EPHY_NEW_TAB_APPEND_GROUPED) grouped = TRUE;
if (flags & EPHY_NEW_TAB_APPEND_LAST) grouped = FALSE;
if ((flags & EPHY_NEW_TAB_APPEND_AFTER) && previous_embed != NULL)
{
nb = ephy_window_get_notebook (window);
position = gtk_notebook_page_num (GTK_NOTEBOOK (nb),
GTK_WIDGET (previous_embed)) + 1;
}
else
{
position = grouped ? EPHY_NOTEBOOK_INSERT_GROUPED : EPHY_NOTEBOOK_INSERT_LAST;
}
tab = ephy_tab_new ();
embed = ephy_tab_get_embed (tab);
gtk_widget_show (GTK_WIDGET(embed));
ephy_window_add_tab (window, tab,
position,
jump_to);
if (flags & EPHY_NEW_TAB_RAISE_WINDOW)
{
gtk_window_present (GTK_WINDOW(window));
}
else
{
gtk_widget_show (GTK_WIDGET(window));
}
if (flags & EPHY_NEW_TAB_HOMEPAGE)
{
Toolbar *toolbar;
char *homepage;
homepage = build_homepage_url (shell, previous_embed);
g_assert (homepage != NULL);
toolbar = ephy_window_get_toolbar (window);
toolbar_edit_location (toolbar);
ephy_embed_load_url (embed, homepage);
g_free (homepage);
}
else if ((flags & EPHY_NEW_TAB_IS_A_COPY) ||
(flags & EPHY_NEW_TAB_VIEW_SOURCE))
{
EmbedDisplayType display_type =
(flags & EPHY_NEW_TAB_VIEW_SOURCE) ?
DISPLAY_AS_SOURCE : DISPLAY_NORMAL;
ephy_embed_load_url (embed, "about:blank");
ephy_embed_copy_page (embed, previous_embed, display_type);
}
else if (url)
{
ephy_embed_load_url (embed, url);
}
if (flags & EPHY_NEW_TAB_FULLSCREEN)
{
ephy_window_set_chrome (window, EMBED_CHROME_OPENASFULLSCREEN |
EMBED_CHROME_DEFAULT);
}
return tab;
}
#ifdef ENABLE_NAUTILUS_VIEW
static void
ephy_nautilus_view_init_factory (EphyShell *gs)
{
BonoboGenericFactory *ephy_nautilusview_factory;
ephy_nautilusview_factory = bonobo_generic_factory_new
(EPHY_NAUTILUS_VIEW_OAFIID,
(BonoboFactoryCallback) ephy_nautilus_view_new, gs);
if (!BONOBO_IS_GENERIC_FACTORY (ephy_nautilusview_factory))
g_warning ("Couldn't create the factory!");
}
static BonoboObject *
ephy_nautilus_view_new (BonoboGenericFactory *factory, const char *id,
EphyShell *gs)
{
return ephy_nautilus_view_new_component (gs);
}
#endif
/**
* ephy_shell_get_session:
* @gs: a #EphyShell
*
* Returns current session.
*
* Return value: the current session.
**/
Session *
ephy_shell_get_session (EphyShell *gs)
{
if (!gs->priv->session)
{
gs->priv->session = session_new ();
g_object_add_weak_pointer
(G_OBJECT(gs->priv->session),
(gpointer *)&gs->priv->session);
}
return gs->priv->session;
}
EphyAutocompletion *
ephy_shell_get_autocompletion (EphyShell *gs)
{
EphyShellPrivate *p = gs->priv;
if (!p->autocompletion)
{
static const gchar *prefixes[] = {
EPHY_AUTOCOMPLETION_USUAL_WEB_PREFIXES,
NULL
};
EphyHistory *gh = ephy_embed_shell_get_global_history (EPHY_EMBED_SHELL (gs));
EphyBookmarks *bmk = ephy_shell_get_bookmarks (gs);
p->autocompletion = ephy_autocompletion_new ();
ephy_autocompletion_set_prefixes (p->autocompletion, prefixes);
ephy_autocompletion_add_source (p->autocompletion,
EPHY_AUTOCOMPLETION_SOURCE (gh));
ephy_autocompletion_add_source (p->autocompletion,
EPHY_AUTOCOMPLETION_SOURCE (bmk));
}
return p->autocompletion;
}
EphyBookmarks *
ephy_shell_get_bookmarks (EphyShell *gs)
{
if (gs->priv->bookmarks == NULL)
{
gs->priv->bookmarks = ephy_bookmarks_new ();
}
return gs->priv->bookmarks;
}
EphyToolbarsModel *
ephy_shell_get_toolbars_model (EphyShell *gs)
{
if (gs->priv->toolbars_model == NULL)
{
char *xml_file;
EggToolbarsModel *model;
gs->priv->toolbars_model = ephy_toolbars_model_new ();
model = EGG_TOOLBARS_MODEL (gs->priv->toolbars_model);
xml_file = g_build_filename (ephy_dot_dir (),
"ephy-toolbar.xml",
NULL);
if (g_file_test (xml_file, G_FILE_TEST_EXISTS))
{
egg_toolbars_model_load (model, xml_file);
}
else
{
const char *default_xml;
default_xml = ephy_file ("epiphany-toolbar.xml");
egg_toolbars_model_load (model, default_xml);
}
g_free (xml_file);
}
return gs->priv->toolbars_model;
}
static void
bookmarks_hide_cb (GtkWidget *widget, gpointer data)
{
LOG ("Unref shell for bookmarks editor")
g_object_unref (ephy_shell);
}
void
ephy_shell_show_bookmarks_editor (EphyShell *gs,
GtkWidget *parent)
{
EphyBookmarks *bookmarks;
if (gs->priv->bme == NULL)
{
bookmarks = ephy_shell_get_bookmarks (ephy_shell);
g_assert (bookmarks != NULL);
gs->priv->bme = ephy_bookmarks_editor_new (bookmarks);
g_signal_connect (gs->priv->bme, "hide",
G_CALLBACK (bookmarks_hide_cb), NULL);
}
if (!GTK_WIDGET_VISIBLE (gs->priv->bme))
{
LOG ("Ref shell for bookmarks editor")
g_object_ref (ephy_shell);
}
if (parent)
{
ephy_bookmarks_editor_set_parent
(EPHY_BOOKMARKS_EDITOR (gs->priv->bme), parent);
}
gtk_window_present (GTK_WINDOW (gs->priv->bme));
}
static void
history_window_hide_cb (GtkWidget *widget, gpointer data)
{
LOG ("Unref shell for history window")
g_object_unref (ephy_shell);
}
void
ephy_shell_show_history_window (EphyShell *gs,
GtkWidget *parent)
{
EphyHistory *history;
if (gs->priv->history_window == NULL)
{
history = ephy_embed_shell_get_global_history
(EPHY_EMBED_SHELL (ephy_shell));
g_assert (history != NULL);
gs->priv->history_window = ephy_history_window_new (history);
g_signal_connect (gs->priv->history_window, "hide",
G_CALLBACK (history_window_hide_cb), NULL);
}
if (!GTK_WIDGET_VISIBLE (gs->priv->history_window))
{
LOG ("Ref shell for history window")
g_object_ref (ephy_shell);
}
if (parent)
{
ephy_history_window_set_parent
(EPHY_HISTORY_WINDOW (gs->priv->history_window), parent);
}
gtk_window_present (GTK_WINDOW (gs->priv->history_window));
}