Read addons into a list for more flexibility

Until now we used to scan directories every time
we wanted to either display the list of addons
or load addons in order to execute them. That
is wasteful and inflexible.

Use a list of elements and only update it when
needed, for example when the directory folder
notifies us of a change.

This is a stop towards disabling particular elements.
This commit is contained in:
Arnaud Renevier 2008-08-23 19:57:22 +02:00 committed by Christian Dywan
parent af2e90a4b1
commit e4457be3ed
2 changed files with 224 additions and 103 deletions

View file

@ -23,6 +23,9 @@
#include <JavaScriptCore/JavaScript.h>
#include <glib/gi18n.h>
#include <string.h>
#if HAVE_GIO
#include <gio/gio.h>
#endif
struct _MidoriAddons
{
@ -32,6 +35,19 @@ struct _MidoriAddons
MidoriAddonKind kind;
GtkWidget* toolbar;
GtkWidget* treeview;
GSList* elements;
};
struct AddonElement
{
gchar *fullpath;
gchar *name;
gchar *description;
gboolean enabled;
GSList* includes;
GSList* excludes;
};
G_DEFINE_TYPE (MidoriAddons, midori_addons, GTK_TYPE_VBOX)
@ -44,6 +60,9 @@ enum
PROP_KIND
};
static void
midori_addons_finalize (GObject* object);
static void
midori_addons_set_property (GObject* object,
guint prop_id,
@ -81,6 +100,7 @@ midori_addons_class_init (MidoriAddonsClass* class)
GParamFlags flags;
gobject_class = G_OBJECT_CLASS (class);
gobject_class->finalize = midori_addons_finalize;
gobject_class->set_property = midori_addons_set_property;
gobject_class->get_property = midori_addons_get_property;
@ -183,50 +203,60 @@ _addons_get_extension (MidoriAddons* addons)
}
static GSList*
_addons_get_files (MidoriAddons* addons)
_addons_get_directories (MidoriAddons* addons)
{
GSList* files;
GDir* addon_dir;
const gchar* addons_name;
const gchar* addons_extension;
const char* const *datadirs;
const gchar* filename;
gchar *dirname;
gchar *fullname;
GSList *directories;
const char* const* datadirs;
const gchar* folder;
gchar* path;
files = NULL;
addons_name = _addons_get_folder (addons);
addons_extension = _addons_get_extension (addons);
folder = _addons_get_folder (addons);
/* user data dir */
path = g_build_path (G_DIR_SEPARATOR_S, g_get_user_data_dir (),
PACKAGE_NAME, folder, NULL);
directories = g_slist_prepend (NULL, path);
/* system data dirs */
datadirs = g_get_system_data_dirs ();
while (*datadirs)
{
dirname = g_build_filename (*datadirs, PACKAGE_NAME, addons_name, NULL);
if ((addon_dir = g_dir_open (dirname, 0, NULL)))
{
while ((filename = g_dir_read_name (addon_dir)))
{
if (g_str_has_suffix (filename, addons_extension))
{
fullname = g_build_filename (dirname, filename, NULL);
files = g_slist_prepend (files, fullname);
}
}
g_dir_close (addon_dir);
}
g_free (dirname);
path = g_build_path (G_DIR_SEPARATOR_S, *datadirs,
PACKAGE_NAME, folder, NULL);
directories = g_slist_prepend (directories, path);
datadirs++;
}
/* user data dir */
dirname = g_build_filename (g_get_user_data_dir () , PACKAGE_NAME,
addons_name, NULL);
return directories;
}
static GSList*
_addons_get_files (MidoriAddons* addons)
{
GSList* files;
GDir* addon_dir;
const gchar* folder;
const gchar* extension;
GSList* list;
GSList* directories;
const gchar* filename;
gchar* dirname;
gchar* fullname;
files = NULL;
folder = _addons_get_folder (addons);
extension = _addons_get_extension (addons);
directories = _addons_get_directories (addons);
list = directories;
while (directories)
{
dirname = directories->data;
if ((addon_dir = g_dir_open (dirname, 0, NULL)))
{
while ((filename = g_dir_read_name (addon_dir)))
{
if (g_str_has_suffix (filename, addons_extension))
if (g_str_has_suffix (filename, extension))
{
fullname = g_build_filename (dirname, filename, NULL);
files = g_slist_prepend (files, fullname);
@ -235,10 +265,25 @@ _addons_get_files (MidoriAddons* addons)
g_dir_close (addon_dir);
}
g_free (dirname);
directories = g_slist_next (directories);
}
g_slist_free (list);
return files;
}
#if HAVE_GIO
static void
midori_addons_directory_monitor_changed (GFileMonitor* monitor,
GFile* child,
GFile* other_file,
GFileMonitorEvent flags,
MidoriAddons* addons)
{
midori_addons_update_elements (addons);
}
#endif
static void
midori_addons_button_add_clicked_cb (GtkToolItem* toolitem,
MidoriAddons* addons)
@ -251,6 +296,11 @@ midori_addons_button_add_clicked_cb (GtkToolItem* toolitem,
_addons_get_folder (addons));
gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (dialog);
#if !HAVE_GIO
/* FIXME: Without GIO clicking this button is the only
way to update the list */
midori_addons_update_elements (addons);
#endif
}
static void
@ -275,13 +325,13 @@ midori_addons_treeview_render_text_cb (GtkTreeViewColumn* column,
GtkTreeIter* iter,
GtkWidget* treeview)
{
gchar* displayname;
gchar* name;
gtk_tree_model_get (model, iter, 0, &displayname, -1);
gtk_tree_model_get (model, iter, 0, &name, -1);
g_object_set (renderer, "text", displayname, NULL);
g_object_set (renderer, "text", name, NULL);
g_free (displayname);
g_free (name);
}
static void
@ -308,6 +358,7 @@ midori_addons_init (MidoriAddons* addons)
GtkCellRenderer* renderer_pixbuf;
addons->web_widget = NULL;
addons->elements = NULL;
addons->treeview = gtk_tree_view_new ();
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (addons->treeview), FALSE);
@ -330,6 +381,13 @@ midori_addons_init (MidoriAddons* addons)
gtk_box_pack_start (GTK_BOX (addons), addons->treeview, TRUE, TRUE, 0);
}
static void
midori_addons_finalize (GObject* object)
{
MidoriAddons* addons = MIDORI_ADDONS (object);
g_slist_free (addons->elements);
}
static gboolean
_metadata_from_file (const gchar* filename,
GSList** includes,
@ -457,7 +515,9 @@ _convert_to_simple_regexp (const gchar* pattern)
}
return dest;
}
#else
static bool
_match_with_wildcard (const gchar* str,
const gchar* pattern)
@ -563,7 +623,7 @@ _may_load_script (const gchar* uri,
break;
}
#endif
list = list->next;
list = g_slist_next (list);
}
return match;
}
@ -602,12 +662,14 @@ _js_style_from_file (JSContextRef js_context,
const gchar* filename,
gchar** exception)
{
gboolean result = FALSE;
gboolean result;
gchar* style;
GError* error = NULL;
GError* error;
guint i, n;
gchar* style_script;
result = FALSE;
error = NULL;
if (g_file_get_contents (filename, &style, NULL, &error))
{
n = strlen (style);
@ -651,40 +713,29 @@ midori_web_widget_window_object_cleared_cb (GtkWidget* web_widget,
JSObjectRef js_window,
MidoriAddons* addons)
{
gchar* fullname;
GSList* includes;
GSList* excludes;
const gchar* uri;
GSList* elements;
struct AddonElement* element;
gchar* fullname;
gchar* exception;
gchar* message;
GSList* addon_files;
GSList* list;
uri = webkit_web_frame_get_uri (web_frame);
if (!uri)
return;
addon_files = _addons_get_files (addons);
list = addon_files;
while (addon_files)
elements = addons->elements;
while (elements)
{
fullname = addon_files->data;
includes = NULL;
excludes = NULL;
if (addons->kind == MIDORI_ADDON_USER_SCRIPTS &&
!_metadata_from_file (fullname, &includes, &excludes, NULL, NULL))
element = elements->data;
fullname = element->fullpath;
if (element->includes || element->excludes)
if (!_may_load_script (uri, &element->includes, &element->excludes))
{
addon_files = g_slist_next (addon_files);
elements = g_slist_next (elements);
continue;
}
if (includes || excludes)
if (!_may_load_script (uri, &includes, &excludes))
{
addon_files = g_slist_next (addon_files);
continue;
}
g_slist_free (includes);
g_slist_free (excludes);
exception = NULL;
if (addons->kind == MIDORI_ADDON_USER_SCRIPTS &&
!_js_script_from_file (js_context, fullname, &exception))
@ -702,9 +753,9 @@ midori_web_widget_window_object_cleared_cb (GtkWidget* web_widget,
g_free (message);
g_free (exception);
}
addon_files = addon_files->next;
elements = g_slist_next (elements);
}
g_slist_free (list);
}
/**
@ -724,6 +775,13 @@ midori_addons_new (GtkWidget* web_widget,
MidoriAddonKind kind)
{
MidoriAddons* addons;
#if HAVE_GIO
GSList* directories;
GSList* list;
GFile* directory;
GError* error;
GFileMonitor* monitor;
#endif
g_return_val_if_fail (GTK_IS_WIDGET (web_widget), NULL);
@ -732,6 +790,30 @@ midori_addons_new (GtkWidget* web_widget,
"kind", kind, */ NULL);
addons->web_widget = web_widget;
midori_addons_set_kind (addons, kind);
midori_addons_update_elements (addons);
#if HAVE_GIO
directories = _addons_get_directories (addons);
list = directories;
while (directories)
{
directory = g_file_new_for_path (directories->data);
directories = directories->next;
error = NULL;
monitor = g_file_monitor_directory (directory,
G_FILE_MONITOR_NONE,
NULL, &error);
if (!monitor)
{
g_warning ("could not monitor %s: %s", g_file_get_parse_name (directory),
error->message);
g_error_free (error);
}
g_signal_connect (monitor, "changed",
G_CALLBACK (midori_addons_directory_monitor_changed), addons);
}
g_slist_free (list);
#endif
return GTK_WIDGET (addons);
}
@ -784,14 +866,6 @@ void
midori_addons_set_kind (MidoriAddons* addons,
MidoriAddonKind kind)
{
GtkListStore* liststore;
gchar* fullname;
gchar* displayname;
gchar* name;
GtkTreeIter iter;
GSList* addon_files;
GSList* list;
g_return_if_fail (MIDORI_IS_ADDONS (addons));
g_return_if_fail (addons->kind == MIDORI_ADDON_NONE);
@ -807,38 +881,6 @@ midori_addons_set_kind (MidoriAddons* addons,
g_signal_connect (addons->web_widget, "window-object-cleared",
G_CALLBACK (midori_web_widget_window_object_cleared_cb), addons);
liststore = gtk_list_store_new (3, G_TYPE_STRING,
G_TYPE_INT,
G_TYPE_STRING);
addon_files = _addons_get_files (addons);
list = addon_files;
while (addon_files)
{
fullname = addon_files->data;
displayname = g_filename_display_basename (fullname);
if (kind == MIDORI_ADDON_USER_SCRIPTS)
{
name = NULL;
if (!_metadata_from_file (fullname, NULL, NULL, &name, NULL))
continue;
if (name)
{
g_free (displayname);
displayname = name;
}
}
gtk_list_store_append (liststore, &iter);
gtk_list_store_set (liststore, &iter, 0, displayname, 1, 0, 2, "", -1);
addon_files = addon_files->next;
}
g_slist_free (list);
gtk_tree_view_set_model (GTK_TREE_VIEW (addons->treeview),
GTK_TREE_MODEL (liststore));
g_object_notify (G_OBJECT (addons), "kind");
}
@ -902,3 +944,79 @@ midori_addons_get_toolbar (MidoriAddons* addons)
return addons->toolbar;
}
/**
* midori_addons_update_elements:
* @addons: a #MidoriAddons
*
* Updates all addons elements (file paths and metadata).
*
**/
void
midori_addons_update_elements (MidoriAddons* addons)
{
gchar* fullname;
gchar* displayname;
gchar* name;
gchar* description;
GSList* includes;
GSList* excludes;
GtkListStore* liststore;
GtkTreeIter iter;
GSList* addon_files;
GSList* list;
struct AddonElement* element;
g_return_if_fail (addons->kind != MIDORI_ADDON_NONE);
g_slist_free (addons->elements);
addons->elements = NULL;
liststore = gtk_list_store_new (3, G_TYPE_STRING,
G_TYPE_INT,
G_TYPE_STRING);
addon_files = _addons_get_files (addons);
list = addon_files;
while (addon_files)
{
fullname = addon_files->data;
displayname = g_filename_display_basename (fullname);
description = NULL;
includes = NULL;
excludes = NULL;
if (addons->kind == MIDORI_ADDON_USER_SCRIPTS)
{
name = NULL;
if (!_metadata_from_file (fullname, &includes, &excludes, &name,
&description))
continue;
if (name)
{
g_free (displayname);
displayname = name;
}
}
gtk_list_store_append (liststore, &iter);
gtk_list_store_set (liststore, &iter,
0, g_strdup (displayname), 1, 0, 2, "", -1);
element = g_new (struct AddonElement, 1);
element->name = displayname;
element->description = description;
element->fullpath = fullname;
element->enabled = TRUE;
element->includes = includes;
element->excludes = excludes;
addons->elements = g_slist_prepend (addons->elements, element);
addon_files = g_slist_next (addon_files);
}
addons->elements = g_slist_reverse (addons->elements);
g_slist_free (list);
gtk_tree_view_set_model (GTK_TREE_VIEW (addons->treeview),
GTK_TREE_MODEL (liststore));
}

View file

@ -77,6 +77,9 @@ midori_addons_get_kind (MidoriAddons* addons);
GtkWidget*
midori_addons_get_toolbar (MidoriAddons* addons);
void
midori_addons_update_elements (MidoriAddons* addons);
G_END_DECLS
#endif /* __MIDORI_ADDONS_H__ */