ed6ed71239
MidoriBrowser gains the show-preferences signal which gives API users a chance to add preferences. katze_preferences_add_category now returns a box to allow freely packing a widget into the page. The extension panel is packed into the preferences now rather than being appended as a proper panel. Motivation is consistency here, such as with Gedit or Emerillon and also the aspect that extensions often really do tweak behaviour like preferences do. Spacing and icons are added for visual consistency.
433 lines
14 KiB
C
433 lines
14 KiB
C
/*
|
|
Copyright (C) 2008-2009 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-extensions.h"
|
|
|
|
#include "midori-app.h"
|
|
#include "midori-extension.h"
|
|
#include "midori-stock.h"
|
|
#include "midori-viewable.h"
|
|
|
|
#include "sokoke.h"
|
|
#include <glib/gi18n.h>
|
|
|
|
struct _MidoriExtensions
|
|
{
|
|
GtkVBox parent_instance;
|
|
|
|
GtkWidget* toolbar;
|
|
GtkWidget* treeview;
|
|
MidoriApp* app;
|
|
};
|
|
|
|
struct _MidoriExtensionsClass
|
|
{
|
|
GtkVBoxClass parent_class;
|
|
};
|
|
|
|
static void
|
|
midori_extensions_viewable_iface_init (MidoriViewableIface* iface);
|
|
|
|
G_DEFINE_TYPE_WITH_CODE (MidoriExtensions, midori_extensions, GTK_TYPE_VBOX,
|
|
G_IMPLEMENT_INTERFACE (MIDORI_TYPE_VIEWABLE,
|
|
midori_extensions_viewable_iface_init));
|
|
|
|
enum
|
|
{
|
|
PROP_0,
|
|
|
|
PROP_APP
|
|
};
|
|
|
|
static void
|
|
midori_extensions_set_property (GObject* object,
|
|
guint prop_id,
|
|
const GValue* value,
|
|
GParamSpec* pspec);
|
|
|
|
static void
|
|
midori_extensions_get_property (GObject* object,
|
|
guint prop_id,
|
|
GValue* value,
|
|
GParamSpec* pspec);
|
|
|
|
static void
|
|
midori_extensions_finalize (GObject* object);
|
|
|
|
static void
|
|
midori_extensions_class_init (MidoriExtensionsClass* class)
|
|
{
|
|
GObjectClass* gobject_class;
|
|
GParamFlags flags;
|
|
|
|
gobject_class = G_OBJECT_CLASS (class);
|
|
gobject_class->set_property = midori_extensions_set_property;
|
|
gobject_class->get_property = midori_extensions_get_property;
|
|
gobject_class->finalize = midori_extensions_finalize;
|
|
|
|
flags = G_PARAM_READWRITE;
|
|
|
|
g_object_class_install_property (gobject_class,
|
|
PROP_APP,
|
|
g_param_spec_object (
|
|
"app",
|
|
"App",
|
|
"The app",
|
|
MIDORI_TYPE_APP,
|
|
flags));
|
|
}
|
|
|
|
static const gchar*
|
|
midori_extensions_get_label (MidoriViewable* viewable)
|
|
{
|
|
return _("Extensions");
|
|
}
|
|
|
|
static const gchar*
|
|
midori_extensions_get_stock_id (MidoriViewable* viewable)
|
|
{
|
|
return STOCK_EXTENSIONS;
|
|
}
|
|
|
|
static GtkWidget*
|
|
midori_extensions_get_toolbar (MidoriViewable* extensions)
|
|
{
|
|
if (!MIDORI_EXTENSIONS (extensions)->toolbar)
|
|
{
|
|
GtkWidget* toolbar;
|
|
|
|
toolbar = gtk_toolbar_new ();
|
|
gtk_toolbar_set_icon_size (GTK_TOOLBAR (toolbar), GTK_ICON_SIZE_BUTTON);
|
|
|
|
MIDORI_EXTENSIONS (extensions)->toolbar = toolbar;
|
|
}
|
|
|
|
return MIDORI_EXTENSIONS (extensions)->toolbar;
|
|
}
|
|
|
|
static void
|
|
midori_extensions_viewable_iface_init (MidoriViewableIface* iface)
|
|
{
|
|
iface->get_stock_id = midori_extensions_get_stock_id;
|
|
iface->get_label = midori_extensions_get_label;
|
|
iface->get_toolbar = midori_extensions_get_toolbar;
|
|
}
|
|
|
|
static void
|
|
midori_extensions_extension_activate_cb (MidoriExtension* extension,
|
|
MidoriApp* app,
|
|
MidoriExtensions* extensions)
|
|
{
|
|
gtk_widget_queue_draw (GTK_WIDGET (extensions->treeview));
|
|
}
|
|
|
|
static void
|
|
midori_extensions_extension_deactivate_cb (MidoriExtension* extension,
|
|
MidoriExtensions* extensions)
|
|
{
|
|
gtk_widget_queue_draw (GTK_WIDGET (extensions->treeview));
|
|
}
|
|
|
|
static void
|
|
midori_extensions_add_item_cb (KatzeArray* array,
|
|
MidoriExtension* extension,
|
|
MidoriExtensions* extensions)
|
|
{
|
|
GtkTreeIter iter;
|
|
GtkTreeModel* model;
|
|
|
|
model = gtk_tree_view_get_model (GTK_TREE_VIEW (extensions->treeview));
|
|
gtk_list_store_append (GTK_LIST_STORE (model), &iter);
|
|
gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, extension, -1);
|
|
g_signal_connect (extension, "activate",
|
|
G_CALLBACK (midori_extensions_extension_activate_cb), extensions);
|
|
g_signal_connect (extension, "deactivate",
|
|
G_CALLBACK (midori_extensions_extension_deactivate_cb), extensions);
|
|
}
|
|
|
|
static void
|
|
midori_extensions_set_property (GObject* object,
|
|
guint prop_id,
|
|
const GValue* value,
|
|
GParamSpec* pspec)
|
|
{
|
|
MidoriExtensions* extensions = MIDORI_EXTENSIONS (object);
|
|
|
|
switch (prop_id)
|
|
{
|
|
case PROP_APP:
|
|
{
|
|
KatzeArray* array;
|
|
MidoriExtension* extension;
|
|
|
|
/* FIXME: Handle NULL and subsequent assignments */
|
|
extensions->app = g_value_get_object (value);
|
|
array = katze_object_get_object (extensions->app, "extensions");
|
|
g_signal_connect (array, "add-item",
|
|
G_CALLBACK (midori_extensions_add_item_cb), extensions);
|
|
|
|
KATZE_ARRAY_FOREACH_ITEM (extension, array)
|
|
midori_extensions_add_item_cb (array, extension, extensions);
|
|
|
|
/* Hide if there are no extensions at all */
|
|
if (!katze_array_get_nth_item (array, 0))
|
|
gtk_widget_hide (GTK_WIDGET (object));
|
|
}
|
|
break;
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
midori_extensions_get_property (GObject* object,
|
|
guint prop_id,
|
|
GValue* value,
|
|
GParamSpec* pspec)
|
|
{
|
|
MidoriExtensions* extensions = MIDORI_EXTENSIONS (object);
|
|
|
|
switch (prop_id)
|
|
{
|
|
case PROP_APP:
|
|
g_value_set_object (value, extensions->app);
|
|
break;
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
midori_extensions_treeview_render_tick_cb (GtkTreeViewColumn* column,
|
|
GtkCellRenderer* renderer,
|
|
GtkTreeModel* model,
|
|
GtkTreeIter* iter,
|
|
GtkWidget* treeview)
|
|
{
|
|
MidoriExtension* extension;
|
|
|
|
gtk_tree_model_get (model, iter, 0, &extension, -1);
|
|
|
|
g_object_set (renderer,
|
|
"activatable", midori_extension_is_prepared (extension),
|
|
"active", midori_extension_is_active (extension) || g_object_get_data (G_OBJECT (extension), "static"),
|
|
"xpad", 4,
|
|
NULL);
|
|
|
|
g_object_unref (extension);
|
|
}
|
|
|
|
static void
|
|
midori_extensions_treeview_render_icon_cb (GtkTreeViewColumn* column,
|
|
GtkCellRenderer* renderer,
|
|
GtkTreeModel* model,
|
|
GtkTreeIter* iter,
|
|
GtkWidget* treeview)
|
|
{
|
|
g_object_set (renderer, "stock-id", STOCK_EXTENSION,
|
|
"stock-size", GTK_ICON_SIZE_BUTTON,
|
|
"xpad", 4, NULL);
|
|
}
|
|
|
|
static void
|
|
midori_extensions_treeview_render_text_cb (GtkTreeViewColumn* column,
|
|
GtkCellRenderer* renderer,
|
|
GtkTreeModel* model,
|
|
GtkTreeIter* iter,
|
|
GtkWidget* treeview)
|
|
{
|
|
MidoriExtension* extension;
|
|
gchar* name;
|
|
gchar* version;
|
|
gchar* desc;
|
|
gchar* text;
|
|
|
|
gtk_tree_model_get (model, iter, 0, &extension, -1);
|
|
|
|
name = katze_object_get_string (extension, "name");
|
|
version = katze_object_get_string (extension, "version");
|
|
desc = katze_object_get_string (extension, "description");
|
|
text = g_markup_printf_escaped ("<b>%s</b> %s\n%s",
|
|
name, version && *version ? version : "", desc);
|
|
g_free (name);
|
|
g_free (version);
|
|
g_free (desc);
|
|
|
|
g_object_set (renderer,
|
|
"markup", text,
|
|
"sensitive", midori_extension_is_prepared (extension),
|
|
NULL);
|
|
|
|
g_free (text);
|
|
g_object_unref (extension);
|
|
}
|
|
|
|
static void
|
|
midori_extensions_treeview_row_activated_cb (GtkTreeView* treeview,
|
|
GtkTreePath* path,
|
|
GtkTreeViewColumn* column,
|
|
MidoriExtensions* extensions)
|
|
{
|
|
GtkTreeModel* model;
|
|
GtkTreeIter iter;
|
|
|
|
model = gtk_tree_view_get_model (treeview);
|
|
if (gtk_tree_model_get_iter (model, &iter, path))
|
|
{
|
|
MidoriExtension* extension;
|
|
|
|
gtk_tree_model_get (model, &iter, 0, &extension, -1);
|
|
if (midori_extension_is_active (extension))
|
|
midori_extension_deactivate (extension);
|
|
else if (midori_extension_is_prepared (extension))
|
|
g_signal_emit_by_name (extension, "activate", extensions->app);
|
|
|
|
g_object_unref (extension);
|
|
}
|
|
}
|
|
|
|
static void
|
|
midori_extensions_cell_renderer_toggled_cb (GtkCellRendererToggle* renderer,
|
|
const gchar* path,
|
|
MidoriExtensions* extensions)
|
|
{
|
|
GtkTreeModel* model;
|
|
GtkTreeIter iter;
|
|
|
|
model = gtk_tree_view_get_model (GTK_TREE_VIEW (extensions->treeview));
|
|
if (gtk_tree_model_get_iter_from_string (model, &iter, path))
|
|
{
|
|
MidoriExtension* extension;
|
|
|
|
gtk_tree_model_get (model, &iter, 0, &extension, -1);
|
|
if (midori_extension_is_active (extension))
|
|
midori_extension_deactivate (extension);
|
|
else if (midori_extension_is_prepared (extension))
|
|
g_signal_emit_by_name (extension, "activate", extensions->app);
|
|
|
|
g_object_unref (extension);
|
|
}
|
|
}
|
|
|
|
static gint
|
|
midori_extensions_tree_sort_func (GtkTreeModel* model,
|
|
GtkTreeIter* a,
|
|
GtkTreeIter* b,
|
|
gpointer data)
|
|
{
|
|
MidoriExtension* e1, *e2;
|
|
gchar* name1, *name2;
|
|
gint result = 0;
|
|
|
|
gtk_tree_model_get (model, a, 0, &e1, -1);
|
|
gtk_tree_model_get (model, b, 0, &e2, -1);
|
|
|
|
name1 = katze_object_get_string (e1, "name");
|
|
name2 = katze_object_get_string (e2, "name");
|
|
|
|
g_object_unref (e1);
|
|
g_object_unref (e2);
|
|
|
|
result = g_strcmp0 (name1, name2);
|
|
|
|
g_free (name1);
|
|
g_free (name2);
|
|
|
|
return result;
|
|
}
|
|
|
|
static void
|
|
midori_extensions_init (MidoriExtensions* extensions)
|
|
{
|
|
/* Create the treeview */
|
|
GtkTreeViewColumn* column;
|
|
GtkCellRenderer* renderer_icon;
|
|
GtkCellRenderer* renderer_text;
|
|
GtkCellRenderer* renderer_toggle;
|
|
GtkListStore* liststore = gtk_list_store_new (1, G_TYPE_OBJECT);
|
|
extensions->treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (liststore));
|
|
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (liststore),
|
|
0, GTK_SORT_ASCENDING);
|
|
gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (liststore),
|
|
0, midori_extensions_tree_sort_func, NULL, NULL);
|
|
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (extensions->treeview), FALSE);
|
|
column = gtk_tree_view_column_new ();
|
|
renderer_toggle = gtk_cell_renderer_toggle_new ();
|
|
gtk_tree_view_column_pack_start (column, renderer_toggle, FALSE);
|
|
gtk_tree_view_column_set_cell_data_func (column, renderer_toggle,
|
|
(GtkTreeCellDataFunc)midori_extensions_treeview_render_tick_cb,
|
|
extensions->treeview, NULL);
|
|
g_signal_connect (renderer_toggle, "toggled",
|
|
G_CALLBACK (midori_extensions_cell_renderer_toggled_cb), extensions);
|
|
gtk_tree_view_append_column (GTK_TREE_VIEW (extensions->treeview), column);
|
|
column = gtk_tree_view_column_new ();
|
|
renderer_icon = gtk_cell_renderer_pixbuf_new ();
|
|
gtk_tree_view_column_pack_start (column, renderer_icon, FALSE);
|
|
gtk_tree_view_column_set_cell_data_func (column, renderer_icon,
|
|
(GtkTreeCellDataFunc)midori_extensions_treeview_render_icon_cb,
|
|
extensions->treeview, NULL);
|
|
gtk_tree_view_append_column (GTK_TREE_VIEW (extensions->treeview), column);
|
|
column = gtk_tree_view_column_new ();
|
|
gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
|
|
renderer_text = gtk_cell_renderer_text_new ();
|
|
gtk_tree_view_column_pack_start (column, renderer_text, FALSE);
|
|
gtk_tree_view_column_set_cell_data_func (column, renderer_text,
|
|
(GtkTreeCellDataFunc)midori_extensions_treeview_render_text_cb,
|
|
extensions->treeview, NULL);
|
|
gtk_tree_view_append_column (GTK_TREE_VIEW (extensions->treeview), column);
|
|
g_object_unref (liststore);
|
|
g_object_connect (extensions->treeview,
|
|
"signal::row-activated",
|
|
midori_extensions_treeview_row_activated_cb, extensions,
|
|
NULL);
|
|
gtk_widget_show (extensions->treeview);
|
|
gtk_box_pack_start (GTK_BOX (extensions), extensions->treeview, TRUE, TRUE, 0);
|
|
}
|
|
|
|
static void
|
|
midori_extensions_finalize (GObject* object)
|
|
{
|
|
MidoriExtensions* extensions = MIDORI_EXTENSIONS (object);
|
|
KatzeArray* array = katze_object_get_object (extensions->app, "extensions");
|
|
MidoriExtension* extension;
|
|
|
|
KATZE_ARRAY_FOREACH_ITEM (extension, array)
|
|
{
|
|
g_signal_handlers_disconnect_by_func (extension,
|
|
midori_extensions_extension_activate_cb, extensions);
|
|
g_signal_handlers_disconnect_by_func (extension,
|
|
midori_extensions_extension_deactivate_cb, extensions);
|
|
}
|
|
g_signal_handlers_disconnect_by_func (array,
|
|
midori_extensions_add_item_cb, extensions);
|
|
|
|
g_object_unref (array);
|
|
}
|
|
|
|
/**
|
|
* midori_extensions_new:
|
|
*
|
|
* Creates a new empty extensions.
|
|
*
|
|
* Return value: a new #MidoriExtensions
|
|
*
|
|
* Since: 0.1.2
|
|
**/
|
|
GtkWidget*
|
|
midori_extensions_new (void)
|
|
{
|
|
MidoriExtensions* extensions = g_object_new (MIDORI_TYPE_EXTENSIONS,
|
|
NULL);
|
|
|
|
return GTK_WIDGET (extensions);
|
|
}
|