midori/src/midori-app.c
Christian Dywan 4a488da7b1 Implement MidoriApp singleton and improve multiple window support
The new singleton holds the shared settings and trash. It is
further more used to keep track of all open windows and quits
when the last window was closed. It also watches the focus in
case you need something like a "current" browser.
2008-05-23 00:17:10 +02:00

386 lines
11 KiB
C

/*
Copyright (C) 2008 Christian Dywan <christian@twotoasts.de>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
See the file COPYING for the full license text.
*/
#include "midori-app.h"
#include <gtk/gtk.h>
#include <glib/gi18n.h>
G_DEFINE_TYPE (MidoriApp, midori_app, G_TYPE_OBJECT)
static MidoriApp* _midori_app_singleton = NULL;
struct _MidoriAppPrivate
{
GList* browsers;
MidoriBrowser* browser;
GtkAccelGroup* accel_group;
MidoriWebSettings* settings;
MidoriTrash* trash;
};
#define MIDORI_APP_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
MIDORI_TYPE_APP, MidoriAppPrivate))
enum
{
PROP_0,
PROP_SETTINGS,
PROP_TRASH,
PROP_BROWSER,
PROP_BROWSER_COUNT
};
enum {
ADD_BROWSER,
QUIT,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL];
static GObject*
midori_app_constructor (GType type,
guint n_construct_properties,
GObjectConstructParam* construct_properties);
static void
midori_app_finalize (GObject* object);
static void
midori_app_set_property (GObject* object,
guint prop_id,
const GValue* value,
GParamSpec* pspec);
static void
midori_app_get_property (GObject* object,
guint prop_id,
GValue* value,
GParamSpec* pspec);
static void
midori_app_add_browser (MidoriApp* app,
MidoriBrowser* browser);
static void
midori_app_quit (MidoriApp* app);
static void
midori_app_class_init (MidoriAppClass* class)
{
signals[ADD_BROWSER] = g_signal_new (
"add-browser",
G_TYPE_FROM_CLASS(class),
(GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
G_STRUCT_OFFSET (MidoriAppClass, add_browser),
0,
NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
MIDORI_TYPE_BROWSER);
signals[QUIT] = g_signal_new (
"quit",
G_TYPE_FROM_CLASS(class),
(GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
G_STRUCT_OFFSET (MidoriAppClass, quit),
0,
NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
GObjectClass* gobject_class = G_OBJECT_CLASS (class);
gobject_class->constructor = midori_app_constructor;
gobject_class->finalize = midori_app_finalize;
gobject_class->set_property = midori_app_set_property;
gobject_class->get_property = midori_app_get_property;
MidoriAppClass* midoriapp_class = MIDORI_APP_CLASS (class);
midoriapp_class->add_browser = midori_app_add_browser;
midoriapp_class->quit = midori_app_quit;
g_object_class_install_property (gobject_class,
PROP_SETTINGS,
g_param_spec_object (
"settings",
_("Settings"),
_("The associated settings"),
MIDORI_TYPE_WEB_SETTINGS,
G_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_TRASH,
g_param_spec_object (
"trash",
_("Trash"),
_("The trash, collecting recently closed tabs and windows"),
MIDORI_TYPE_TRASH,
G_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_BROWSER,
g_param_spec_object (
"browser",
_("Browser"),
_("The current browser"),
MIDORI_TYPE_BROWSER,
G_PARAM_READABLE));
g_object_class_install_property (gobject_class,
PROP_BROWSER_COUNT,
g_param_spec_uint (
"browser-count",
_("Browser Count"),
_("The current number of browsers"),
0, G_MAXUINT, 0,
G_PARAM_READABLE));
g_type_class_add_private (class, sizeof (MidoriAppPrivate));
}
static GObject*
midori_app_constructor (GType type,
guint n_construct_properties,
GObjectConstructParam* construct_properties)
{
if (_midori_app_singleton)
return g_object_ref (_midori_app_singleton);
else
return G_OBJECT_CLASS (midori_app_parent_class)->constructor (
type, n_construct_properties, construct_properties);
}
static void
midori_app_init (MidoriApp* app)
{
g_assert (!_midori_app_singleton);
_midori_app_singleton = app;
app->priv = MIDORI_APP_GET_PRIVATE (app);
MidoriAppPrivate* priv = app->priv;
priv->accel_group = gtk_accel_group_new ();
priv->settings = midori_web_settings_new ();
priv->trash = midori_trash_new (10);
}
static void
midori_app_finalize (GObject* object)
{
MidoriApp* app = MIDORI_APP (object);
MidoriAppPrivate* priv = app->priv;
g_list_free (priv->browsers);
g_object_unref (priv->accel_group);
g_object_unref (priv->settings);
g_object_unref (priv->trash);
G_OBJECT_CLASS (midori_app_parent_class)->finalize (object);
}
static void
midori_app_set_property (GObject* object,
guint prop_id,
const GValue* value,
GParamSpec* pspec)
{
MidoriApp* app = MIDORI_APP (object);
MidoriAppPrivate* priv = app->priv;
switch (prop_id)
{
case PROP_SETTINGS:
katze_object_assign (priv->settings, g_value_get_object (value));
g_object_ref (priv->settings);
// FIXME: Propagate settings to all browsers
break;
case PROP_TRASH:
katze_object_assign (priv->trash, g_value_get_object (value));
g_object_ref (priv->trash);
// FIXME: Propagate trash to all browsers
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
midori_app_get_property (GObject* object,
guint prop_id,
GValue* value,
GParamSpec* pspec)
{
MidoriApp* app = MIDORI_APP (object);
MidoriAppPrivate* priv = app->priv;
switch (prop_id)
{
case PROP_SETTINGS:
g_value_set_object (value, priv->settings);
break;
case PROP_TRASH:
g_value_set_object (value, priv->trash);
break;
case PROP_BROWSER:
g_value_set_object (value, priv->browser);
break;
case PROP_BROWSER_COUNT:
g_value_set_uint (value, g_list_length (priv->browsers));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
midori_browser_focus_in_event_cb (MidoriBrowser* browser,
GdkEventFocus* event,
MidoriApp* app)
{
MidoriAppPrivate* priv = app->priv;
priv->browser = browser;
}
static void
midori_browser_new_window_cb (MidoriBrowser* browser,
const gchar* uri,
MidoriApp* app)
{
MidoriAppPrivate* priv = app->priv;
MidoriBrowser* new_browser = g_object_new (MIDORI_TYPE_BROWSER,
"settings", priv->settings,
"trash", priv->trash,
NULL);
midori_browser_append_uri (new_browser, uri);
gtk_widget_show (GTK_WIDGET (new_browser));
g_signal_emit (app, signals[ADD_BROWSER], 0, new_browser);
}
static gboolean
midori_browser_delete_event_cb (MidoriBrowser* browser,
GdkEvent* event,
MidoriApp* app)
{
return FALSE;
}
static gboolean
midori_browser_destroy_cb (MidoriBrowser* browser,
MidoriApp* app)
{
MidoriAppPrivate* priv = app->priv;
priv->browsers = g_list_remove (priv->browsers, browser);
if (g_list_nth (priv->browsers, 0))
return FALSE;
g_signal_emit (app, signals[QUIT], 0);
return TRUE;
}
static void
midori_browser_quit_cb (MidoriBrowser* browser,
MidoriApp* app)
{
g_signal_emit (app, signals[QUIT], 0);
}
static void
midori_app_add_browser (MidoriApp* app,
MidoriBrowser* browser)
{
MidoriAppPrivate* priv = app->priv;
gtk_window_add_accel_group (GTK_WINDOW (browser), priv->accel_group);
g_object_connect (browser,
"signal::focus-in-event", midori_browser_focus_in_event_cb, app,
"signal::new-window", midori_browser_new_window_cb, app,
"signal::delete-event", midori_browser_delete_event_cb, app,
"signal::destroy", midori_browser_destroy_cb, app,
"signal::quit", midori_browser_quit_cb, app,
NULL);
priv->browsers = g_list_prepend (priv->browsers, browser);
}
static void
midori_app_quit (MidoriApp* app)
{
gtk_main_quit ();
}
/**
* midori_app_new:
*
* Instantiates a new #MidoriApp singleton.
*
* Subsequent calls will ref the initial instance.
*
* Return value: a new #MidoriApp
**/
MidoriApp*
midori_app_new (void)
{
MidoriApp* app = g_object_new (MIDORI_TYPE_APP,
NULL);
return app;
}
/**
* midori_app_get_settings:
* @app: a #MidoriApp
*
* Retrieves the #MidoriWebSettings of the app.
*
* Return value: the assigned #MidoriWebSettings
**/
MidoriWebSettings*
midori_app_get_settings (MidoriApp* app)
{
g_return_val_if_fail (MIDORI_IS_APP (app), NULL);
MidoriAppPrivate* priv = app->priv;
return priv->settings;
}
/**
* midori_app_get_trash:
* @app: a #MidoriApp
*
* Retrieves the #MidoriTrash of the app.
*
* Return value: the assigned #MidoriTrash
**/
MidoriTrash*
midori_app_get_trash (MidoriApp* app)
{
g_return_val_if_fail (MIDORI_IS_APP (app), NULL);
MidoriAppPrivate* priv = app->priv;
return priv->trash;
}